diff --git a/dune/tectonic/globalfriction.hh b/dune/tectonic/globalfriction.hh index 41ddd18f892ea5b1130a63d9620ab5502d4f7421..e87fc139e3354111c8a6bfbb8e56284ff5da99f0 100644 --- a/dune/tectonic/globalfriction.hh +++ b/dune/tectonic/globalfriction.hh @@ -9,9 +9,12 @@ #include <dune/solvers/common/interval.hh> +#include <dune/tnnmg/functionals/nonsmoothconvexfunctional.hh> + #include <dune/tectonic/localfriction.hh> -template <class Matrix, class Vector> class GlobalFriction { +template <class Matrix, class Vector> +class GlobalFriction { //: public Dune::TNNMG::NonsmoothConvexFunctional<> { protected: using ScalarVector = Dune::BlockVector<Dune::FieldVector<double, 1>>; @@ -82,5 +85,6 @@ template <class Matrix, class Vector> class GlobalFriction { } void virtual updateAlpha(ScalarVector const &alpha) = 0; + }; #endif diff --git a/dune/tectonic/mydirectionalconvexfunction.hh b/dune/tectonic/mydirectionalconvexfunction.hh deleted file mode 100644 index 11f20c52df933d36842b7d3bf6f2a6db4534db29..0000000000000000000000000000000000000000 --- a/dune/tectonic/mydirectionalconvexfunction.hh +++ /dev/null @@ -1,68 +0,0 @@ -#ifndef DUNE_TECTONIC_MYDIRECTIONALCONVEXFUNCTION_HH -#define DUNE_TECTONIC_MYDIRECTIONALCONVEXFUNCTION_HH - -// Copied from dune/tnnmg/problem-classes/directionalconvexfunction.hh -// Allows phi to be const - -#include <dune/fufem/arithmetic.hh> -#include <dune/solvers/common/interval.hh> - -template <class Nonlinearity> class MyDirectionalConvexFunction { -public: - using Vector = typename Nonlinearity::VectorType; - using Matrix = typename Nonlinearity::MatrixType; - - MyDirectionalConvexFunction(double A, double b, Nonlinearity const &phi, - Vector const &u, Vector const &v) - : A(A), b(b), phi(phi), u(u), v(v) { - phi.directionalDomain(u, v, dom); - } - - double quadraticPart() const { return A; } - - double linearPart() const { return b; } - - void subDiff(double x, Dune::Solvers::Interval<double> &D) const { - Vector uxv = u; - Arithmetic::addProduct(uxv, x, v); - phi.directionalSubDiff(uxv, v, D); - auto const Axmb = A * x - b; - D[0] += Axmb; - D[1] += Axmb; - } - - void domain(Dune::Solvers::Interval<double> &domain) const { - domain[0] = this->dom[0]; - domain[1] = this->dom[1]; - } - - double A; - double b; - -private: - Nonlinearity const φ - Vector const &u; - Vector const &v; - - Dune::Solvers::Interval<double> dom; -}; - -/* - 1/2 <A(u + hv),u + hv> - <b, u + hv> - = 1/2 <Av,v> h^2 - <b - Au, v> h + const. - - localA = <Av,v> - localb = <b - Au, v> -*/ - -template <class Matrix, class Vector, class Nonlinearity> -MyDirectionalConvexFunction<Nonlinearity> restrict(Matrix const &A, - Vector const &b, - Vector const &u, - Vector const &v, - Nonlinearity const &phi) { - return MyDirectionalConvexFunction<Nonlinearity>( - Arithmetic::Axy(A, v, v), Arithmetic::bmAxy(A, b, u, v), phi, u, v); -} - -#endif diff --git a/dune/tectonic/tectonic.hh b/dune/tectonic/tectonic.hh deleted file mode 100644 index bd921f8f7bdcf36d5cdc187e95f5660edeb4dcd0..0000000000000000000000000000000000000000 --- a/dune/tectonic/tectonic.hh +++ /dev/null @@ -1,5 +0,0 @@ -#ifndef DUNE_TECTONIC_TECTONIC_HH -#define DUNE_TECTONIC_TECTONIC_HH - -// add your classes here -#endif diff --git a/program_structure.txt b/program_structure.txt new file mode 100644 index 0000000000000000000000000000000000000000..a2db29cdfb2d6791876342fd694022dc111f93fb --- /dev/null +++ b/program_structure.txt @@ -0,0 +1,29 @@ +-------------------------- +-- Program structure: -- +-------------------------- + + +1. build n-body system + - contains grids, couplings, gridViews, assembler + + Data structure: LevelContactNetwork + Factories: StackedBlocksFactory + +2. initialize/set up program state + - holds bodyStates, u, v, a, alpha for each body + - defines time, timeStep + - computes initial conditions + + Data structure: ProgramState + +-- tested until here + +3. assemble RSD friction + +4. set up TNNMG solver + - rate updater + - state updater + +5. adaptive time stepper + + diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index d86dde2a5b076bb28e0578c31c69df606c69ca8f..8a2187759e4f0a749c1225193916e479fbf7ff29 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -11,9 +11,9 @@ set(SW_SOURCE_FILES io/hdf5/restart-io.cc io/hdf5/surface-writer.cc io/hdf5/time-writer.cc - one-body-problem-data/mygeometry.cc - one-body-problem-data/mygrid.cc - one-body-problem.cc +# one-body-problem-data/mygeometry.cc +# one-body-problem-data/mygrid.cc +# one-body-problem.cc spatial-solving/fixedpointiterator.cc spatial-solving/solverfactory.cc time-stepping/adaptivetimestepper.cc @@ -46,6 +46,7 @@ set(MSW_SOURCE_FILES multi-body-problem.cc spatial-solving/fixedpointiterator.cc spatial-solving/solverfactory.cc + spatial-solving/solverfactory_old.cc time-stepping/adaptivetimestepper.cc time-stepping/coupledtimestepper.cc time-stepping/rate.cc diff --git a/src/data-structures/.cc b/src/data-structures/.cc new file mode 100644 index 0000000000000000000000000000000000000000..32c9a280f0a4babfa053e3bf37aebf154527b705 --- /dev/null +++ b/src/data-structures/.cc @@ -0,0 +1,7 @@ +#ifndef MY_DIM +#error MY_DIM unset +#endif + +#include "../explicitgrid.hh" + +template class ContactNetwork<Grid, MY_DIM>; diff --git a/src/data-structures/levelcontactnetwork.hh b/src/data-structures/levelcontactnetwork.hh index f6c1bf194f3889ff2effa0a446f317df4e09621f..e7672cd53828ed7c2045a6ee0d1cc1c176a10981 100644 --- a/src/data-structures/levelcontactnetwork.hh +++ b/src/data-structures/levelcontactnetwork.hh @@ -56,6 +56,8 @@ template <class GridType, int dimension> class LevelContactNetwork { using StateEnergyNorms = std::vector<const typename Body::StateEnergyNorm *>; using ExternalForces = std::vector<const typename Body::ExternalForce *>; + using NBodyAssembler = Dune::Contact::NBodyAssembler<DeformedGridType, Vector>; + public: LevelContactNetwork(int nBodies, int nCouplings, int level = 0); @@ -133,7 +135,7 @@ template <class GridType, int dimension> class LevelContactNetwork { std::vector<std::vector<std::unique_ptr<const DeformedLevelGridView>>> levelViews_; std::vector<size_t> leafVertexCounts_; - Dune::Contact::NBodyAssembler<DeformedGridType, Vector> nBodyAssembler_; + NBodyAssembler nBodyAssembler_; Matrices<Matrix,2> matrices_; }; diff --git a/src/data-structures/program_state.hh b/src/data-structures/program_state.hh index 275697da77effe110850f77c239a4d1981b9a41c..181e5c86c568f83f8d81239fd809fabea2250a2c 100644 --- a/src/data-structures/program_state.hh +++ b/src/data-structures/program_state.hh @@ -6,7 +6,6 @@ #include <dune/matrix-vector/axpy.hh> #include <dune/fufem/boundarypatch.hh> -#include <dune/tnnmg/nonlinearities/zerononlinearity.hh> #include <dune/tnnmg/problem-classes/blocknonlineartnnmgproblem.hh> #include <dune/contact/assemblers/nbodyassembler.hh> @@ -17,7 +16,9 @@ #include "levelcontactnetwork.hh" #include "matrices.hh" #include "../spatial-solving/solverfactory.hh" - +#include "../spatial-solving/solverfactory_old.hh" +#include "../spatial-solving/tnnmg/functional.hh" +#include "../spatial-solving/tnnmg/zerononlinearity.hh" #include "../utils/debugutils.hh" template <class VectorTEMPLATE, class ScalarVectorTEMPLATE> class BodyState { @@ -118,15 +119,43 @@ template <class VectorTEMPLATE, class ScalarVectorTEMPLATE> class ProgramState { nBodyAssembler.assembleJacobian(matrices_ptr, bilinearForm); - Vector totalRhs; + Vector totalRhs, oldTotalRhs; nBodyAssembler.assembleRightHandSide(_rhs, totalRhs); + oldTotalRhs = totalRhs; - Vector totalX; + Vector totalX, oldTotalX; nBodyAssembler.nodalToTransformed(_x, totalX); + oldTotalX = totalX; + + // get lower and upper obstacles + const auto& totalObstacles = nBodyAssembler.totalObstacles_; + Vector lower(totalObstacles.size()); + Vector upper(totalObstacles.size()); + + for (size_t j=0; j<totalObstacles.size(); ++j) { + const auto& totalObstaclesj = totalObstacles[j]; + auto& lowerj = lower[j]; + auto& upperj = upper[j]; + for (size_t d=0; d<dims; ++d) { + lowerj[d] = totalObstaclesj[d][0]; + upperj[d] = totalObstaclesj[d][1]; + } + } + + // print problem + print(bilinearForm, "bilinearForm"); + print(totalRhs, "totalRhs"); + print(_dirichletNodes, "ignore"); + print(totalObstacles, "totalObstacles"); + print(lower, "lower"); + print(upper, "upper"); - using DeformedGridType = typename LevelContactNetwork<GridType, dims>::DeformedGridType; - using LinearFactory = SolverFactory<DeformedGridType, GlobalFriction<Matrix, Vector>, Matrix, Vector>; - LinearFactory factory(parset.sub("solver.tnnmg"), nBodyAssembler, _dirichletNodes); + // set up functional and TNMMG solver + using Functional = Functional<Matrix&, Vector&, ZeroNonlinearity, Vector&, Vector&, typename Matrix::field_type>; + Functional J(bilinearForm, totalRhs, ZeroNonlinearity(), lower, upper); + + using Factory = SolverFactory<Functional, Dune::BitSetVector<dims>>; + Factory factory(parset.sub("solver.tnnmg"), J); /* std::vector<Dune::BitSetVector<dims>> bodyDirichletNodes; nBodyAssembler.postprocess(_dirichletNodes, bodyDirichletNodes); @@ -138,13 +167,14 @@ template <class VectorTEMPLATE, class ScalarVectorTEMPLATE> class ProgramState { print(totalX, "totalX: "); print(totalRhs, "totalRhs: ");*/ - auto multigridStep = factory.getStep(); - multigridStep->setProblem(bilinearForm, totalX, totalRhs); + auto tnnmgStep = factory.step(); + tnnmgStep->setIgnore(_dirichletNodes); + factory.setProblem(totalX); const EnergyNorm<Matrix, Vector> norm(bilinearForm); LoopSolver<Vector> solver( - multigridStep.get(), _localParset.get<size_t>("maximumIterations"), + tnnmgStep.get(), _localParset.get<size_t>("maximumIterations"), _localParset.get<double>("tolerance"), &norm, _localParset.get<Solver::VerbosityMode>("verbosity"), false); // absolute error @@ -152,7 +182,38 @@ template <class VectorTEMPLATE, class ScalarVectorTEMPLATE> class ProgramState { solver.preprocess(); solver.solve(); - nBodyAssembler.postprocess(multigridStep->getSol(), _x); + nBodyAssembler.postprocess(tnnmgStep->getSol(), _x); + + Vector res = totalRhs; + bilinearForm.mmv(tnnmgStep->getSol(), res); + std::cout << "TNNMG Res - energy norm: " << norm.operator ()(res) << std::endl; + + // TODO: remove after debugging + /* using DeformedGridType = typename LevelContactNetwork<GridType, dims>::DeformedGridType; + using OldLinearFactory = SolverFactoryOld<DeformedGridType, GlobalFriction<Matrix, Vector>, Matrix, Vector>; + OldLinearFactory oldFactory(parset.sub("solver.tnnmg"), nBodyAssembler, _dirichletNodes); + + auto oldStep = oldFactory.getStep(); + oldStep->setProblem(bilinearForm, oldTotalX, oldTotalRhs); + + LoopSolver<Vector> oldSolver( + oldStep.get(), _localParset.get<size_t>("maximumIterations"), + _localParset.get<double>("tolerance"), &norm, + _localParset.get<Solver::VerbosityMode>("verbosity"), + false); // absolute error + + oldSolver.preprocess(); + oldSolver.solve(); + + Vector oldRes = totalRhs; + bilinearForm.mmv(oldStep->getSol(), oldRes); + std::cout << "Old Res - energy norm: " << norm.operator ()(oldRes) << std::endl;*/ + + print(tnnmgStep->getSol(), "TNNMG Solution: "); + /* print(oldStep->getSol(), "Old Solution: "); + auto diff = tnnmgStep->getSol(); + diff -= oldStep->getSol(); + std::cout << "Energy norm: " << norm.operator ()(diff) << std::endl;*/ }; timeStep = 0; @@ -162,6 +223,7 @@ template <class VectorTEMPLATE, class ScalarVectorTEMPLATE> class ProgramState { std::vector<Vector> ell0(bodyCount_); for (size_t i=0; i<bodyCount_; i++) { // Initial velocity + u[i] = 0.0; v[i] = 0.0; ell0[i].resize(u[i].size()); @@ -175,7 +237,7 @@ template <class VectorTEMPLATE, class ScalarVectorTEMPLATE> class ProgramState { // Assuming dPhi(v = 0) = 0, we thus only have to solve Au = ell0 Dune::BitSetVector<dims> dirichletNodes; levelContactNetwork.totalNodes("dirichlet", dirichletNodes); - for (size_t i=0; i<dirichletNodes.size(); i++) { + /*for (size_t i=0; i<dirichletNodes.size(); i++) { bool val = false; for (size_t d=0; d<dims; d++) { val = val || dirichletNodes[i][d]; @@ -185,7 +247,7 @@ template <class VectorTEMPLATE, class ScalarVectorTEMPLATE> class ProgramState { for (size_t d=0; d<dims; d++) { dirichletNodes[i][d] = val; } - } + }*/ solveLinearProblem(dirichletNodes, levelContactNetwork.matrices().elasticity, ell0, u, parset.sub("u0.solver")); diff --git a/src/explicitgrid.hh b/src/explicitgrid.hh index beefb64cc800f06604d3ac12484eb0be305e7902..fb010a25306c621807104a97869c02312c610b34 100644 --- a/src/explicitgrid.hh +++ b/src/explicitgrid.hh @@ -12,4 +12,7 @@ using LevelGridView = Grid::LevelGridView; using DeformedGridComplex = typename Dune::Contact::DeformedContinuaComplex<Grid, Vector>; using DeformedGrid = DeformedGridComplex::DeformedGridType; +using DefLeafGridView = DeformedGrid::LeafGridView; +using DefLevelGridView = DeformedGrid::LevelGridView; + #endif diff --git a/src/explicitvectors.hh b/src/explicitvectors.hh index 5f2d887fe6fd41720409d537b9960d122d9fb468..548c681faa9e6e867641e591170ee219101fcf0b 100644 --- a/src/explicitvectors.hh +++ b/src/explicitvectors.hh @@ -3,6 +3,7 @@ #include <dune/common/fmatrix.hh> #include <dune/common/fvector.hh> +#include <dune/common/bitsetvector.hh> #include <dune/istl/bcrsmatrix.hh> #include <dune/istl/bvector.hh> @@ -12,4 +13,6 @@ using Vector = Dune::BlockVector<LocalVector>; using Matrix = Dune::BCRSMatrix<LocalMatrix>; using ScalarVector = Dune::BlockVector<Dune::FieldVector<double, 1>>; using ScalarMatrix = Dune::BCRSMatrix<Dune::FieldMatrix<double, 1, 1>>; +using BitVector = Dune::BitSetVector<MY_DIM>; + #endif diff --git a/src/factories/stackedblocksfactory.cc b/src/factories/stackedblocksfactory.cc index 0891faeed91b05c974393734c48b20442ca01a2c..11a3f98c65428e55638aa5eca9f3f0da26c38f4b 100644 --- a/src/factories/stackedblocksfactory.cc +++ b/src/factories/stackedblocksfactory.cc @@ -163,27 +163,40 @@ void StackedBlocksFactory<GridType, dims>::setBoundaryConditions() { std::shared_ptr<LeafBoundaryCondition> neumannBoundary = std::make_shared<LeafBoundaryCondition>(std::make_shared<LeafBoundaryPatch>(body->leafView()), neumannFunction, "neumann"); body->addBoundaryCondition(neumannBoundary); - // Dirichlet Boundary + // right Dirichlet Boundary // identify Dirichlet nodes on leaf level - std::shared_ptr<Dune::BitSetVector<dims>> dirichletNodes = std::make_shared<Dune::BitSetVector<dims>>(leafVertexCount); + std::shared_ptr<Dune::BitSetVector<dims>> velocityDirichletNodes = std::make_shared<Dune::BitSetVector<dims>>(leafVertexCount); for (int j=0; j<leafVertexCount; j++) { if (leafFaces_[i]->right.containsVertex(j)) - (*dirichletNodes)[j][0] = true; + (*velocityDirichletNodes)[j][0] = true; - if (leafFaces_[i]->lower.containsVertex(j)) - (*dirichletNodes)[j][0] = true; - - #if MY_DIM == 3 + #if MY_DIM == 3 //TODO: wrong, needs revision if (leafFaces_[i]->front.containsVertex(j) || leafFaces_[i]->back.containsVertex(j)) - dirichletNodes->at(j)[2] = true; + zeroDirichletNodes->at(j)[2] = true; #endif } - std::shared_ptr<LeafBoundaryCondition> dirichletBoundary = std::make_shared<LeafBoundaryCondition>("dirichlet"); - dirichletBoundary->setBoundaryPatch(body->leafView(), dirichletNodes); - dirichletBoundary->setBoundaryFunction(velocityDirichletFunction); - body->addBoundaryCondition(dirichletBoundary); + std::shared_ptr<LeafBoundaryCondition> velocityDirichletBoundary = std::make_shared<LeafBoundaryCondition>("dirichlet"); + velocityDirichletBoundary->setBoundaryPatch(body->leafView(), velocityDirichletNodes); + velocityDirichletBoundary->setBoundaryFunction(velocityDirichletFunction); + body->addBoundaryCondition(velocityDirichletBoundary); + } + + // lower Dirichlet Boundary + const auto& firstBody = this->levelContactNetwork_.body(0); + const auto& firstLeafVertexCount = firstBody->leafVertexCount(); + std::shared_ptr<Dune::BitSetVector<dims>> zeroDirichletNodes = std::make_shared<Dune::BitSetVector<dims>>(firstLeafVertexCount); + for (int j=0; j<firstLeafVertexCount; j++) { + if (leafFaces_[0]->lower.containsVertex(j)) + (*zeroDirichletNodes)[j][1] = true; } + + std::shared_ptr<LeafBoundaryCondition> zeroDirichletBoundary = std::make_shared<LeafBoundaryCondition>("dirichlet"); + zeroDirichletBoundary->setBoundaryPatch(firstBody->leafView(), zeroDirichletNodes); + + std::shared_ptr<Function> zeroFunction = std::make_shared<NeumannCondition>(); + zeroDirichletBoundary->setBoundaryFunction(zeroFunction); + firstBody->addBoundaryCondition(zeroDirichletBoundary); } #include "stackedblocksfactory_tmpl.cc" diff --git a/src/io/hdf5-bodywriter.hh b/src/io/hdf5-bodywriter.hh new file mode 100644 index 0000000000000000000000000000000000000000..549062c706b1c617b779f0f6c884ace4aafb6bf7 --- /dev/null +++ b/src/io/hdf5-bodywriter.hh @@ -0,0 +1,79 @@ +#ifndef SRC_HDF5_BODYWRITER_HH +#define SRC_HDF5_BODYWRITER_HH + +#include <dune/fufem/functions/basisgridfunction.hh> +#include <dune/fufem/geometry/convexpolyhedron.hh> +#include <dune/fufem/hdf5/file.hh> + +#include "hdf5/frictionalboundary-writer.hh" +#include "hdf5/patchinfo-writer.hh" + +template <class ProgramState, class VertexBasis, class GridView> +class HDF5BodyWriter { +private: + using VertexCoordinates = typename ProgramState::Vector; + using FrictionPatches = std::vector<const BoundaryPatch<GridView>* >; + using WeakPatches = std::vector<const ConvexPolyhedron<LocalVector>* >; + + using LocalVector = typename VertexCoordinates::block_type; + + friend class HDF5LevelWriter<ProgramState, VertexBasis, GridView>; + +public: + HDF5BodyWriter( + HDF5::Grouplike &file, + const VertexCoordinates& vertexCoordinates, + const VertexBasis& vertexBasis, + const FrictionPatches& frictionPatches, + const WeakPatches& weakPatches) : + patchCount_(frictionPatches.size()), + file_(file), +#if MY_DIM == 3 + patchInfoWriters_(patchCount_), +#endif + frictionBoundaryWriters_(patchCount_) { + + assert(patchCount_ == weakPatches.size()); + + for (size_t i=0; i<patchCount_; i++) { +#if MY_DIM == 3 + patchInfoWriters_[i] = new PatchInfoWriter<ProgramState, VertexBasis, GridView>(file_, vertexBasis, *frictionPatches[i], *weakPatches[i], i); +#endif + frictionBoundaryWriters_[i] = new FrictionalBoundaryWriter<ProgramState, GridView>(file_, vertexCoordinates, *frictionPatches[i], i); + } + } + + ~HDF5BodyWriter() { + for (size_t i=0; i<patchCount_; i++) { +#if MY_DIM == 3 + delete patchInfoWriters_[i]; +#endif + delete frictionBoundaryWriters_[i]; + } + } + + template <class Friction> + void reportSolution(ProgramState const &programState, + // for the friction coefficient + std::vector<std::shared_ptr<Friction>>& friction) { + + for (size_t i=0; i<patchCount_; i++) { +#if MY_DIM == 3 + patchInfoWriters_[i]->write(programState); +#endif + frictionBoundaryWriters_[i]->write(programState, *friction[i]); + } + } + +private: + const size_t patchCount_; + + HDF5::Grouplike &file_; + +#if MY_DIM == 3 + std::vector<PatchInfoWriter<ProgramState, VertexBasis, GridView>* > patchInfoWriters_; +#endif + + std::vector<FrictionalBoundaryWriter<ProgramState, GridView>* > frictionBoundaryWriters_; +}; +#endif diff --git a/src/io/hdf5-levelwriter.hh b/src/io/hdf5-levelwriter.hh new file mode 100644 index 0000000000000000000000000000000000000000..66e3c048b7787a742fd3cd4797346b8cbbf3ea16 --- /dev/null +++ b/src/io/hdf5-levelwriter.hh @@ -0,0 +1,73 @@ +#ifndef SRC_HDF5_LEVELWRITER_HH +#define SRC_HDF5_LEVELWRITER_HH + +#include <dune/fufem/hdf5/file.hh> + +#include "hdf5/iteration-writer.hh" +#include "hdf5/time-writer.hh" +#include "hdf5-bodywriter.hh" + +template <class ProgramState, class VertexBasis, class GridView> +class HDF5LevelWriter { +private: + using HDF5BodyWriter = HDF5BodyWriter<ProgramState, VertexBasis, GridView>; + using VertexCoordinates = std::vector<typename HDF5BodyWriter::VertexCoordinates>; + using VertexBases = std::vector<VertexBasis>; + using FrictionPatches = std::vector<typename HDF5BodyWriter::FrictionPatches>; + using WeakPatches = std::vector<typename HDF5BodyWriter::WeakPatches>; + + friend class HDF5NetworkWriter<ProgramState, VertexBasis, GridView>; + +public: + + HDF5LevelWriter(HDF5::Grouplike &file, + const VertexCoordinates& vertexCoordinates, + const VertexBases& vertexBases, + const FrictionPatches& frictionBoundaries, + const WeakPatches& weakPatches) + : bodyCount_(vertexCoordinates.size()), + file_(file), + iterationWriter_(file_), + timeWriter_(file_), + bodyWriters_(bodyCount_) { + + for (size_t i=0; i<bodyCount_; i++) { + bodyWriters_[i] = new HDF5BodyWriter<ProgramState, VertexBasis, GridView>(file_, vertexCoordinates[i], vertexBases[i], frictionBoundaries[i], weakPatches[i]); + } + } + + ~HDF5LevelWriter() { + for (size_t i=0; i<bodyCount_; i++) { + delete bodyWriters_[i]; + } + } + + template <class Friction> + void reportSolution( + ProgramState const &programState, + // for the friction coefficient + std::vector<std::shared_ptr<Friction>>& friction) { + timeWriter_.write(programState); + + for (size_t i=0; i<bodyCount_; i++) { + bodyWriters_[i]->reportSolution(programState, *friction[i]); //TODO + } + } + + void reportIterations( + ProgramState const &programState, + IterationRegister const &iterationCount) { + iterationWriter_.write(programState.timeStep, iterationCount); + } + +private: + const size_t bodyCount_; + + HDF5::Grouplike &file_; + + IterationWriter iterationWriter_; + TimeWriter<ProgramState> timeWriter_; + + std::vector<HDF5BodyWriter* > bodyWriters_; +}; +#endif diff --git a/src/io/hdf5-writer.hh b/src/io/hdf5-writer.hh deleted file mode 100644 index d0351be71cdc9e4e61c82fa32520ef81b5ba1707..0000000000000000000000000000000000000000 --- a/src/io/hdf5-writer.hh +++ /dev/null @@ -1,85 +0,0 @@ -#ifndef SRC_HDF5_WRITER_HH -#define SRC_HDF5_WRITER_HH - -#include <dune/fufem/functions/basisgridfunction.hh> -#include <dune/fufem/geometry/convexpolyhedron.hh> -#include <dune/fufem/hdf5/file.hh> - -#include "hdf5/frictionalboundary-writer.hh" -#include "hdf5/iteration-writer.hh" -#include "hdf5/patchinfo-writer.hh" -#include "hdf5/surface-writer.hh" -#include "hdf5/time-writer.hh" - -template <class ProgramState, class VertexBasis, class GridView> -class HDF5Writer { -private: - using Vector = typename ProgramState::Vector; - using Patch = BoundaryPatch<GridView>; - - using LocalVector = typename Vector::block_type; - -public: - HDF5Writer(HDF5::Grouplike &file, - const std::vector<Vector>& vertexCoordinates, - const std::vector<const VertexBasis* >& vertexBases, - const std::vector<Patch>& frictionalBoundaries, - const std::vector<ConvexPolyhedron<LocalVector>>& weakPatches) - : bodyCount_(vertexCoordinates.size()), - file_(file), - iterationWriter_(file_), - timeWriter_(file_), -#if MY_DIM == 3 - patchInfoWriters_(bodyCount_), -#endif - frictionalBoundaryWriters_(bodyCount_) { - - for (size_t i=0; i<bodyCount_; i++) { -#if MY_DIM == 3 - patchInfoWriters_[i] = new PatchInfoWriter<ProgramState, VertexBasis, GridView>(file_, *vertexBases[i], frictionalBoundaries[i], weakPatches[i], i); -#endif - frictionalBoundaryWriters_[i] = new FrictionalBoundaryWriter<ProgramState, GridView>(file_, vertexCoordinates[i], frictionalBoundaries[i], i); - } - } - - ~HDF5Writer() { - for (size_t i=0; i<bodyCount_; i++) { -#if MY_DIM == 3 - delete patchInfoWriters_[i]; -#endif - delete frictionalBoundaryWriters_[i]; - } - } - - template <class Friction> - void reportSolution(ProgramState const &programState, - // for the friction coefficient - std::vector<std::shared_ptr<Friction>>& friction) { - timeWriter_.write(programState); - - for (size_t i=0; i<bodyCount_; i++) { -#if MY_DIM == 3 - patchInfoWriters_[i]->write(programState); -#endif - frictionalBoundaryWriters_[i]->write(programState, *friction[i]); - } - } - - void reportIterations(ProgramState const &programState, - IterationRegister const &iterationCount) { - iterationWriter_.write(programState.timeStep, iterationCount); - } - -private: - const size_t bodyCount_; - - HDF5::Grouplike &file_; - - IterationWriter iterationWriter_; - TimeWriter<ProgramState> timeWriter_; -#if MY_DIM == 3 - std::vector<PatchInfoWriter<ProgramState, VertexBasis, GridView>* > patchInfoWriters_; -#endif - std::vector<FrictionalBoundaryWriter<ProgramState, GridView>* > frictionalBoundaryWriters_; -}; -#endif diff --git a/src/io/hdf5/frictionalboundary-writer.hh b/src/io/hdf5/frictionalboundary-writer.hh index 4372cdad928bb60643b8996d7571dbc7d14f6cc7..0977401382ef827d78499316607077f3b722bf32 100644 --- a/src/io/hdf5/frictionalboundary-writer.hh +++ b/src/io/hdf5/frictionalboundary-writer.hh @@ -11,7 +11,7 @@ template <class ProgramState, class GridView> class FrictionalBoundaryWriter { using Patch = BoundaryPatch<GridView>; public: - FrictionalBoundaryWriter(HDF5::Grouplike &file, Vector const &vertexCoordinates, + FrictionalBoundaryWriter(HDF5::Grouplike& file, Vector const &vertexCoordinates, Patch const &frictionalBoundary, size_t const id); template <class Friction> diff --git a/src/multi-body-problem.cc b/src/multi-body-problem.cc index de02c49787df22f05ef2cc28ec4b38749533d36d..4d6e7173513a627a72fe179388b6df072e3b9d7b 100644 --- a/src/multi-body-problem.cc +++ b/src/multi-body-problem.cc @@ -30,6 +30,7 @@ #include <dune/fufem/boundarypatch.hh> #include <dune/fufem/formatstring.hh> +#include <dune/fufem/hdf5/file.hh> #include <dune/solvers/norms/energynorm.hh> @@ -46,12 +47,13 @@ #include <dune/contact/projections/normalprojection.hh> #include <dune/tectonic/geocoordinate.hh> -#include <dune/tectonic/myblockproblem.hh> #include <dune/tectonic/globalfriction.hh> -#include <dune/fufem/hdf5/file.hh> + #include "assemblers.hh" #include "gridselector.hh" +#include "explicitgrid.hh" +#include "explicitvectors.hh" #include "data-structures/enumparser.hh" #include "data-structures/enums.hh" @@ -61,7 +63,7 @@ #include "factories/stackedblocksfactory.hh" -#include "io/hdf5-writer.hh" +//#include "io/hdf5-levelwriter.hh" #include "io/hdf5/restart-io.hh" #include "io/vtk.hh" @@ -69,9 +71,11 @@ #include "multi-body-problem-data/mybody.hh" #include "multi-body-problem-data/grid/mygrids.hh" -//#include "spatial-solving/solverfactory.hh" +#include "spatial-solving/tnnmg/functional.hh" +#include "spatial-solving/tnnmg/localbisectionsolver.hh" +#include "spatial-solving/solverfactory.hh" -//#include "time-stepping/adaptivetimestepper.hh" +#include "time-stepping/adaptivetimestepper.hh" #include "time-stepping/rate.hh" #include "time-stepping/state.hh" #include "time-stepping/updaters.hh" @@ -82,7 +86,8 @@ // for getcwd #include <unistd.h> -#define USE_OLD_TNNMG +//#include <tbb/tbb.h> //TODO multi threading preconditioner? +//#include <pthread.h> size_t const dims = MY_DIM; @@ -115,18 +120,7 @@ int main(int argc, char *argv[]) { auto const parset = getParameters(argc, argv); - using Vector = Dune::BlockVector<Dune::FieldVector<double, dims>>; - using DeformedGridComplex = typename Dune::Contact::DeformedContinuaComplex<Grid, Vector>; - using DeformedGrid = DeformedGridComplex::DeformedGridType; - - using DefLeafGridView = DeformedGrid::LeafGridView; - using DefLevelGridView = DeformedGrid::LevelGridView; - using Assembler = MyAssembler<DefLeafGridView, dims>; - using Matrix = Assembler::Matrix; - using LocalVector = Vector::block_type; - using ScalarMatrix = Assembler::ScalarMatrix; - using ScalarVector = Assembler::ScalarVector; using field_type = Matrix::field_type; @@ -225,18 +219,20 @@ int main(int argc, char *argv[]) { typename LevelContactNetwork::BoundaryPatches frictionBoundaries; levelContactNetwork.boundaryPatches("friction", frictionBoundaries); + /* auto dataWriter = writeData ? std::make_unique< HDF5Writer<MyProgramState, MyVertexBasis, DefLeafGridView>>( *dataFile, vertexCoordinates, vertexBases, - frictionBoundaries, weakPatches) - : nullptr; -/* + frictionBoundaries) //, weakPatches) + : nullptr;*/ + const MyVTKWriter<MyVertexBasis, MyCellBasis> vtkWriter(cellBases, vertexBases, "body"); IterationRegister iterationCount; auto const report = [&](bool initial = false) { + /* if (writeData) { dataWriter->reportSolution(programState, levelContactNetwork.globalFriction()); if (!initial) @@ -255,7 +251,7 @@ int main(int argc, char *argv[]) { << ", time = " << std::setw(12) << programState.relativeTime << ", tau = " << std::setw(12) << programState.relativeTau << std::endl; - + */ if (parset.get<bool>("io.vtk.write")) { std::vector<ScalarVector> stress(bodyCount); @@ -264,6 +260,7 @@ int main(int argc, char *argv[]) { body->assembler()->assembleVonMisesStress(body->data()->getYoungModulus(), body->data()->getPoissonRatio(), programState.u[i], stress[i]); + } vtkWriter.write(programState.timeStep, programState.u, programState.v, @@ -271,7 +268,7 @@ int main(int argc, char *argv[]) { } }; report(true); -*/ + // ------------------- // Set up TNNMG solver // ------------------- @@ -279,8 +276,9 @@ int main(int argc, char *argv[]) { Dune::BitSetVector<dims> totalDirichletNodes; levelContactNetwork.totalNodes("dirichlet", totalDirichletNodes); - using NonlinearFactory = SolverFactory<DeformedGrid, GlobalFriction<Matrix, Vector>, Matrix, Vector>; - NonlinearFactory factory(parset.sub("solver.tnnmg"), nBodyAssembler, totalDirichletNodes); + + using Functional = Functional<Matrix&, Vector&, GlobalFriction<Matrix, Vector>&, Vector&, Vector&, field_type>; + using NonlinearFactory = SolverFactory<Functional, BitVector>; using BoundaryFunctions = typename LevelContactNetwork::BoundaryFunctions; using BoundaryNodes = typename LevelContactNetwork::BoundaryNodes; @@ -344,11 +342,11 @@ int main(int argc, char *argv[]) { typename LevelContactNetwork::ExternalForces externalForces; levelContactNetwork.externalForces(externalForces); - AdaptiveTimeStepper<NonlinearFactory, Updaters, EnergyNorm<ScalarMatrix, ScalarVector>> - adaptiveTimeStepper(factory, parset, globalFriction, current, + AdaptiveTimeStepper<NonlinearFactory, decltype(nBodyAssembler), Updaters, EnergyNorm<ScalarMatrix, ScalarVector>> + adaptiveTimeStepper(parset, nBodyAssembler, globalFriction, current, programState.relativeTime, programState.relativeTau, externalForces, stateEnergyNorms, mustRefine); -/* + while (!adaptiveTimeStepper.reachedEnd()) { programState.timeStep++; @@ -374,7 +372,7 @@ int main(int argc, char *argv[]) { break; } } -*/ + std::cout.rdbuf(coutbuf); //reset to standard output again } catch (Dune::Exception &e) { diff --git a/src/multi-body-problem.cfg b/src/multi-body-problem.cfg index b850b5cc829734e50342d1e812254778f74ad97b..80028801f239be2aeb666ece146963b4d9807b61 100644 --- a/src/multi-body-problem.cfg +++ b/src/multi-body-problem.cfg @@ -44,12 +44,12 @@ b = 0.005 # [ ] scheme = newmark [u0.solver] -maximumIterations = 100000 -verbosity = quiet +maximumIterations = 10000 +verbosity = full [a0.solver] -maximumIterations = 100000 -verbosity = quiet +maximumIterations = 10000 +verbosity = full [v.solver] maximumIterations = 100000 @@ -60,7 +60,7 @@ maximumIterations = 10000 lambda = 0.5 [solver.tnnmg.linear] -maxiumumIterations = 100000 +maximumIterations = 100 pre = 3 cycle = 1 # 1 = V, 2 = W, etc. post = 3 diff --git a/src/one-body-problem-data/mygrid.cc b/src/one-body-problem-data/mygrid.cc index bc7c77daf011d97b2b96bfa17ec9e6279fdaa86b..7188f73a0c0ab5b295a5aca2174c3087144ee1cc 100644 --- a/src/one-body-problem-data/mygrid.cc +++ b/src/one-body-problem-data/mygrid.cc @@ -6,7 +6,7 @@ #include "mygrid.hh" #include "midpoint.hh" -#include "../diameter.hh" +#include "../utils/diameter.hh" #if MY_DIM == 3 SimplexManager::SimplexManager(unsigned int shift) : shift_(shift) {} diff --git a/src/one-body-problem.cfg b/src/one-body-problem.cfg index d970f5e93a5f6dc77c3be6e3f053cf4a85e73529..7336759ce77ba8ff4d3183a3f34f6bdbf5af4eb5 100644 --- a/src/one-body-problem.cfg +++ b/src/one-body-problem.cfg @@ -59,7 +59,7 @@ maximumIterations = 10000 lambda = 0.5 [solver.tnnmg.linear] -maxiumumIterations = 100000 +maximumIterations = 100000 pre = 3 cycle = 1 # 1 = V, 2 = W, etc. post = 3 diff --git a/src/spatial-solving/fixedpointiterator.cc b/src/spatial-solving/fixedpointiterator.cc index 6b776feb982debaca743bd3bb6598d4a8ebdd8ca..1dbaec370013f5b97931d5b894164f41a1b92e66 100644 --- a/src/spatial-solving/fixedpointiterator.cc +++ b/src/spatial-solving/fixedpointiterator.cc @@ -27,19 +27,21 @@ #include "fixedpointiterator.hh" +#include "../utils/debugutils.hh" + void FixedPointIterationCounter::operator+=( FixedPointIterationCounter const &other) { iterations += other.iterations; multigridIterations += other.multigridIterations; } -template <class Factory, class Updaters, class ErrorNorm> -FixedPointIterator<Factory, Updaters, ErrorNorm>::FixedPointIterator( - Factory &factory, Dune::ParameterTree const &parset, +template <class Factory, class NBodyAssembler, class Updaters, class ErrorNorm> +FixedPointIterator<Factory, NBodyAssembler, Updaters, ErrorNorm>::FixedPointIterator( + Dune::ParameterTree const &parset, + NBodyAssembler& nBodyAssembler, GlobalFrictionContainer& globalFriction, const std::vector<const ErrorNorm* >& errorNorms) - : factory_(factory), - step_(factory_.getStep()), - parset_(parset), + : parset_(parset), + nBodyAssembler_(nBodyAssembler), globalFriction_(globalFriction), fixedPointMaxIterations_(parset.get<size_t>("v.fpi.maximumIterations")), fixedPointTolerance_(parset.get<double>("v.fpi.tolerance")), @@ -49,23 +51,49 @@ FixedPointIterator<Factory, Updaters, ErrorNorm>::FixedPointIterator( verbosity_(parset.get<Solver::VerbosityMode>("v.solver.verbosity")), errorNorms_(errorNorms) {} -template <class Factory, class Updaters, class ErrorNorm> +template <class Factory, class NBodyAssembler, class Updaters, class ErrorNorm> FixedPointIterationCounter -FixedPointIterator<Factory, Updaters, ErrorNorm>::run( +FixedPointIterator<Factory, NBodyAssembler, Updaters, ErrorNorm>::run( Updaters updaters, const std::vector<Matrix>& velocityMatrices, const std::vector<Vector>& velocityRHSs, std::vector<Vector>& velocityIterates) { - auto contactAssembler = factory_.getNBodyAssembler(); - - Matrix mat; std::vector<const Matrix*> matrices_ptr(velocityMatrices.size()); for (size_t i=0; i<matrices_ptr.size(); i++) { matrices_ptr[i] = &velocityMatrices[i]; } - contactAssembler.assembleJacobian(matrices_ptr, mat); - EnergyNorm<Matrix, Vector> energyNorm(mat); - LoopSolver<Vector> velocityProblemSolver(step_.get(), velocityMaxIterations_, + // assemble full global contact problem + Matrix bilinearForm; + nBodyAssembler_.assembleJacobian(matrices_ptr, bilinearForm); + + Vector totalRhs; + nBodyAssembler_.assembleRightHandSide(velocityRHSs, totalRhs); + + Vector totalX; + nBodyAssembler_.nodalToTransformed(velocityIterates, totalX); + + // get lower and upper obstacles + const auto& totalObstacles = nBodyAssembler_.totalObstacles_; + Vector lower(totalObstacles.size()); + Vector upper(totalObstacles.size()); + + for (size_t j=0; j<totalObstacles.size(); ++j) { + const auto& totalObstaclesj = totalObstacles[j]; + auto& lowerj = lower[j]; + auto& upperj = upper[j]; + for (size_t d=0; d<dims; ++d) { + lowerj[d] = totalObstaclesj[d][0]; + upperj[d] = totalObstaclesj[d][1]; + } + } + + // set up functional and TNMMG solver + Functional J(bilinearForm, totalRhs, ..., lower, upper); + Factory solverFactory(parset.sub("solver.tnnmg"), J); + auto step = solverFactory.step(); + + EnergyNorm<Matrix, Vector> energyNorm(bilinearForm); + LoopSolver<Vector> velocityProblemSolver(step.get(), velocityMaxIterations_, velocityTolerance_, &energyNorm, verbosity_, false); // absolute error @@ -101,20 +129,24 @@ FixedPointIterator<Factory, Updaters, ErrorNorm>::run( // assemble full global contact problem Matrix bilinearForm; - contactAssembler.assembleJacobian(matrices_ptr, bilinearForm); + nBodyAssembler_.assembleJacobian(matrices_ptr, bilinearForm); Vector totalRhs; - contactAssembler.assembleRightHandSide(rhs, totalRhs); + nBodyAssembler_.assembleRightHandSide(rhs, totalRhs); Vector totalVelocityIterate; - contactAssembler.nodalToTransformed(velocityIterates, totalVelocityIterate); + nBodyAssembler_.nodalToTransformed(velocityIterates, totalVelocityIterate); + + print(bilinearForm, "matrix: "); + print(totalRhs, "totalRhs: "); + print(totalVelocityIterate, "iterate: "); // solve a velocity problem - step_->setProblem(bilinearForm, totalVelocityIterate, totalRhs); + step->setProblem(bilinearForm, totalVelocityIterate, totalRhs); velocityProblemSolver.preprocess(); velocityProblemSolver.solve(); - contactAssembler.postprocess(totalVelocityIterate, velocityIterates); + nBodyAssembler_.postprocess(totalVelocityIterate, velocityIterates); multigridIterations += velocityProblemSolver.getResult().iterations; @@ -167,8 +199,8 @@ std::ostream &operator<<(std::ostream &stream, << ")"; } -template <class Factory, class Updaters, class ErrorNorm> -void FixedPointIterator<Factory, Updaters, ErrorNorm>::relativeVelocities(const std::vector<Vector>& v, std::vector<Vector>& v_rel) const { +template <class Factory, class NBodyAssembler, class Updaters, class ErrorNorm> +void FixedPointIterator<Factory, NBodyAssembler, Updaters, ErrorNorm>::relativeVelocities(const std::vector<Vector>& v, std::vector<Vector>& v_rel) const { // init result v_rel.resize(v.size()); for (size_t i=0; i<v_rel.size(); i++) { diff --git a/src/spatial-solving/fixedpointiterator.hh b/src/spatial-solving/fixedpointiterator.hh index 688a80b516c3a8dfe4e34764a9a48688477118a7..02ad3089bfb3597267d46042dfa81985d1f0c57b 100644 --- a/src/spatial-solving/fixedpointiterator.hh +++ b/src/spatial-solving/fixedpointiterator.hh @@ -22,15 +22,18 @@ struct FixedPointIterationCounter { std::ostream &operator<<(std::ostream &stream, FixedPointIterationCounter const &fpic); -template <class Factory, class Updaters, class ErrorNorm> +template <class Factory, class NBodyAssembler, class Updaters, class ErrorNorm> class FixedPointIterator { + using Functional = typename Factory::Functional; using ScalarVector = typename Updaters::StateUpdater::ScalarVector; using Vector = typename Factory::Vector; using Matrix = typename Factory::Matrix; - using Nonlinearity = typename Factory::Nonlinearity; + using Nonlinearity = typename Factory::Functional::Nonlinearity; + + const static int dims = Vector::block_type::dimension; // using Nonlinearity = typename ConvexProblem::NonlinearityType; - using DeformedGrid = typename Factory::DeformedGrid; + // using DeformedGrid = typename Factory::DeformedGrid; public: using GlobalFrictionContainer = GlobalFrictionContainer<Nonlinearity, 2>; @@ -39,7 +42,8 @@ class FixedPointIterator { void relativeVelocities(const std::vector<Vector>& v, std::vector<Vector>& v_rel) const; public: - FixedPointIterator(Factory& factory, const Dune::ParameterTree& parset, + FixedPointIterator(const Dune::ParameterTree& parset, + NBodyAssembler& nBodyAssembler, GlobalFrictionContainer& globalFriction, const std::vector<const ErrorNorm* >& errorNorms); @@ -49,9 +53,8 @@ class FixedPointIterator { std::vector<Vector>& velocityIterates); private: - Factory& factory_; - std::shared_ptr<typename Factory::Step> step_; Dune::ParameterTree const &parset_; + NBodyAssembler& nBodyAssembler_; GlobalFrictionContainer& globalFriction_; size_t fixedPointMaxIterations_; diff --git a/src/spatial-solving/fixedpointiterator_tmpl.cc b/src/spatial-solving/fixedpointiterator_tmpl.cc index eec3461083148f6a5b8b372dcd7abe3cd655e61a..20322c8cc84035fe8792b21fb2998fdd4d52435f 100644 --- a/src/spatial-solving/fixedpointiterator_tmpl.cc +++ b/src/spatial-solving/fixedpointiterator_tmpl.cc @@ -8,25 +8,37 @@ #include <dune/common/function.hh> #include <dune/solvers/norms/energynorm.hh> -#include <dune/tnnmg/problem-classes/convexproblem.hh> + #include <dune/contact/common/deformedcontinuacomplex.hh> #include <dune/tectonic/globalfriction.hh> -#include <dune/tectonic/myblockproblem.hh> #include "../data-structures/levelcontactnetwork.hh" #include "../time-stepping/rate/rateupdater.hh" #include "../time-stepping/state/stateupdater.hh" #include "../time-stepping/updaters.hh" + #include "solverfactory.hh" +#include <dune/tnnmg/iterationsteps/nonlineargsstep.hh> + +#include "../explicitgrid.hh" +#include "../explicitvectors.hh" +//#include "../../dune/tectonic/globalfriction.hh" +//#include "functional.hh" +//#include "localbisectionsolver.hh" -using BoundaryNodes = typename LevelContactNetwork<Grid, MY_DIM>::LevelBoundaryNodes; -using BoundaryFunctions = typename LevelContactNetwork<Grid, MY_DIM>::LevelBoundaryFunctions; +using MyLevelContactNetwork = LevelContactNetwork<Grid, MY_DIM>; +using BoundaryNodes = typename MyLevelContactNetwork::BoundaryNodes; +using BoundaryFunctions = typename MyLevelContactNetwork::BoundaryFunctions; -using Factory = SolverFactory<DeformedGrid, GlobalFriction<Matrix, Vector>, Matrix, Vector>; +using MyGlobalFriction = GlobalFriction<Matrix, Vector>; +using MyFunctional = Functional<Matrix&, Vector&, MyGlobalFriction&, Vector&, Vector&, double>; +using NonlinearLocalSolver = LocalBisectionSolver; +using NonlinearSmoother = Dune::TNNMG::NonlinearGSStep<MyFunctional, NonlinearLocalSolver>; +using Factory = SolverFactory<MyFunctional, BitVector>; using MyStateUpdater = StateUpdater<ScalarVector, Vector>; using MyRateUpdater = RateUpdater<Vector, Matrix, BoundaryFunctions, BoundaryNodes>; @@ -34,4 +46,4 @@ using MyUpdaters = Updaters<MyRateUpdater, MyStateUpdater>; using ErrorNorm = EnergyNorm<ScalarMatrix, ScalarVector>; -template class FixedPointIterator<Factory, MyUpdaters, ErrorNorm>; +template class FixedPointIterator<Factory, typename MyLevelContactNetwork::NBodyAssembler, MyUpdaters, ErrorNorm>; diff --git a/src/spatial-solving/solverfactory.cc b/src/spatial-solving/solverfactory.cc index 0bba4b88001d23557b8608aaef3f7f40f02fd42f..25bc75755807abb46b4201ed8f25aa319732cc21 100644 --- a/src/spatial-solving/solverfactory.cc +++ b/src/spatial-solving/solverfactory.cc @@ -2,77 +2,41 @@ #include "config.h" #endif -#ifdef HAVE_IPOPT -#undef HAVE_IPOPT -#endif - -#include <dune/common/bitsetvector.hh> - -#include <dune/fufem/assemblers/transferoperatorassembler.hh> -#include <dune/solvers/solvers/solver.hh> +#include <dune/solvers/common/wrapownshare.hh> #include "solverfactory.hh" -template <class DeformedGrid, class Nonlinearity, class MatrixType, class VectorType> -SolverFactory<DeformedGrid, Nonlinearity, MatrixType, VectorType>::SolverFactory( - const Dune::ParameterTree& parset, const Dune::Contact::NBodyAssembler<DeformedGrid, VectorType>& nBodyAssembler, - const Dune::BitSetVector<DeformedGrid::dimension>& ignoreNodes) - : nBodyAssembler_(nBodyAssembler), - baseEnergyNorm_(baseSolverStep_), - baseSolver_(&baseSolverStep_, - parset.get<size_t>("linear.maxiumumIterations"), - parset.get<double>("linear.tolerance"), &baseEnergyNorm_, - Solver::QUIET), - transferOperators_(nBodyAssembler.getGrids().at(0)->maxLevel()) { - - /* baseSolverStep_.obstacles_ = using HasObstacle = Dune::BitSetVector<BlockSize>; - using Obstacle = BoxConstraint<Field, BlockSize>; - const HasObstacle* hasObstacle_; - const std::vector<Obstacle>* obstacles_;*/ - - multigridStep_ = std::make_shared<Step>(); - // tnnmg iteration step - multigridStep_->setMGType(parset.get<int>("main.multi"), parset.get<int>("main.pre"), parset.get<int>("main.post")); - multigridStep_->setIgnore(ignoreNodes); - multigridStep_->setBaseSolver(baseSolver_); - multigridStep_->setSmoother(&presmoother_, &postsmoother_); - multigridStep_->setHasObstacle(nBodyAssembler_.totalHasObstacle_); - multigridStep_->setObstacles(nBodyAssembler_.totalObstacles_); - multigridStep_->setVerbosity(NumProc::QUIET); +template <class Functional, class BitVector> +SolverFactory<Functional, BitVector>::SolverFactory( + const Dune::ParameterTree& parset, + Functional& J) : + J_(Dune::Solvers::wrap_own_share<const Functional>(std::forward<Functional>(J))), + //linear solver + //preconditioner_(), + linearSolverStep_(), + energyNorm_(linearSolverStep_) + { + nonlinearSmoother_ = std::make_shared<NonlinearSmoother>(*J_, dummyIterate_, LocalSolver()); - // create the transfer operators - const int nCouplings = nBodyAssembler_.nCouplings(); - const auto grids = nBodyAssembler_.getGrids(); + // linearSolverStep_.setPreconditioner(preconditioner_); + linearSolver_ = std::make_shared<LinearSolver>(linearSolverStep_, parset.get<size_t>("linear.maximumIterations"), parset.get<double>("linear.tolerance"), energyNorm_, Solver::QUIET); - for (size_t i=0; i<transferOperators_.size(); i++) { - transferOperators_[i] = std::make_shared<TransferOperator>(); - } - - std::vector<const Dune::BitSetVector<1>*> fineHasObstacle(nCouplings); - std::vector<const MatrixType*> mortarTransfer(nCouplings); - std::vector<std::array<int,2> > gridIdx(nCouplings); - - for (int j=0; j<nCouplings; j++) { - fineHasObstacle[j] = nBodyAssembler_.contactCoupling_[j]->nonmortarBoundary().getVertices(); - mortarTransfer[j] = &nBodyAssembler_.contactCoupling_[j]->mortarLagrangeMatrix(); - gridIdx[j] = nBodyAssembler_.coupling_[j].gridIdx_; - } - - TransferOperator::setupHierarchy(transferOperators_, - grids, - mortarTransfer, - nBodyAssembler_.localCoordSystems_, - fineHasObstacle, - gridIdx); + tnnmgStep_ = std::make_shared<Step>(*J_, dummyIterate_, nonlinearSmoother_, linearSolver_, DefectProjection(), LineSearchSolver()); + tnnmgStep_->setPreSmoothingSteps(parset.get<int>("main.pre")); +} - multigridStep_->setTransferOperators(transferOperators_); +template <class Functional, class BitVector> +void SolverFactory<Functional, BitVector>::setProblem(Vector& x) { + nonlinearSmoother_->setProblem(x); + tnnmgStep_->setProblem(x); } -template <class DeformedGrid, class Nonlinearity, class MatrixType, class VectorType> -auto SolverFactory<DeformedGrid, Nonlinearity, MatrixType, VectorType>::getStep() - -> std::shared_ptr<Step> { - return multigridStep_; + +template <class Functional, class BitVector> +auto SolverFactory<Functional, BitVector>::step() +-> std::shared_ptr<Step> { + return tnnmgStep_; } #include "solverfactory_tmpl.cc" diff --git a/src/spatial-solving/solverfactory.hh b/src/spatial-solving/solverfactory.hh index 5e87ea27d7920dbab7b044a485c5a7d4f8f159e7..906649b6337a9e8cc10ba68bb25144c8028641ea 100644 --- a/src/spatial-solving/solverfactory.hh +++ b/src/spatial-solving/solverfactory.hh @@ -1,66 +1,66 @@ #ifndef SRC_SPATIAL_SOLVING_SOLVERFACTORY_HH #define SRC_SPATIAL_SOLVING_SOLVERFACTORY_HH +#define NEW_TNNMG_COMPUTE_ITERATES_DIRECTLY + #include <dune/common/bitsetvector.hh> #include <dune/common/parametertree.hh> -#include <dune/solvers/iterationsteps/multigridstep.hh> -#include <dune/solvers/iterationsteps/projectedblockgsstep.hh> -#include <dune/solvers/iterationsteps/blockgsstep.hh> #include <dune/solvers/norms/energynorm.hh> #include <dune/solvers/solvers/loopsolver.hh> +#include <dune/solvers/iterationsteps/cgstep.hh> -//#include <dune/solvers/transferoperators/compressedmultigridtransfer.hh> -//#include <dune/tnnmg/iterationsteps/genericnonlineargs.hh> -//#include <dune/tnnmg/iterationsteps/tnnmgstep.hh> +#include <dune/tnnmg/iterationsteps/tnnmgstep.hh> +#include <dune/tnnmg/iterationsteps/nonlineargsstep.hh> +#include <dune/tnnmg/projections/obstacledefectprojection.hh> -#include <dune/contact/assemblers/nbodyassembler.hh> +#include "tnnmg/functional.hh" +#include "tnnmg/linearization.hh" +#include "tnnmg/linesearchsolver.hh" +#include "tnnmg/localbisectionsolver.hh" -//#include <dune/contact/estimators/hierarchiccontactestimator.hh> -#include <dune/contact/solvers/nsnewtonmgstep.hh> -#include <dune/contact/solvers/nsnewtoncontacttransfer.hh> -#include <dune/contact/solvers/contactobsrestrict.hh> -#include <dune/contact/solvers/contacttransferoperatorassembler.hh> -#include <dune/contact/solvers/nsnewtoncontacttransfer.hh> +template <class FunctionalTEMPLATE, class BitVectorType> +class SolverFactory { +public: + using Functional = FunctionalTEMPLATE; + using Matrix = typename Functional::Matrix; + using Vector = typename Functional::Vector; + using BitVector = BitVectorType; -#define USE_OLD_TNNMG //needed for old bisection.hh in tnnmg + using LocalSolver = LocalBisectionSolver; + using NonlinearSmoother = Dune::TNNMG::NonlinearGSStep<Functional, LocalSolver>; -template <class DeformedGridTEMPLATE, class NonlinearityTEMPLATE, class MatrixType, class VectorType> -class SolverFactory { -//protected: -// const size_t dim = DeformedGrid::dimension; + using Linearization = typename Dune::TNNMG::BoxConstrainedQuadraticFunctionalConstrainedLinearization<Functional, BitVector>; + //using Preconditioner = Dune::Solvers::Preconditioner; //TODO Platzhalter für PatchPreconditioner + using LinearSolverStep = typename Dune::Solvers::CGStep<Matrix, Vector, BitVector>; + using LinearSolver = typename Dune::Solvers::LoopSolver<Vector, BitVector>; -public: - using Matrix = MatrixType; - using Vector = VectorType; - using DeformedGrid = DeformedGridTEMPLATE; - using Nonlinearity = NonlinearityTEMPLATE; + using DefectProjection = typename Dune::TNNMG::ObstacleDefectProjection; + + using Step = typename Dune::TNNMG::TNNMGStep<Functional, BitVector, Linearization, DefectProjection, LineSearchSolver>; -public: - using Step = Dune::Contact::NonSmoothNewtonMGStep<MatrixType, VectorType>; - using TransferOperator = Dune::Contact::NonSmoothNewtonContactTransfer<VectorType>; - SolverFactory(Dune::ParameterTree const &parset, const Dune::Contact::NBodyAssembler<DeformedGrid, VectorType>& nBodyAssembler, - const Dune::BitSetVector<DeformedGrid::dimension>& ignoreNodes); + SolverFactory(Dune::ParameterTree const &, + Functional&); - std::shared_ptr<Step> getStep(); + void setProblem(Vector& x); - const Dune::Contact::NBodyAssembler<DeformedGrid, VectorType>& getNBodyAssembler() const { - return nBodyAssembler_; - } + auto step() -> std::shared_ptr<Step>; private: - const Dune::Contact::NBodyAssembler<DeformedGrid, VectorType>& nBodyAssembler_; + Vector dummyIterate_; + std::shared_ptr<const Functional> J_; - //ProjectedBlockGSStep<MatrixType, VectorType> baseSolverStep_; - BlockGSStep<MatrixType, VectorType> baseSolverStep_; - EnergyNorm<MatrixType, VectorType> baseEnergyNorm_; - LoopSolver<VectorType> baseSolver_; + // nonlinear smoother + std::shared_ptr<NonlinearSmoother> nonlinearSmoother_; - ProjectedBlockGSStep<MatrixType, VectorType> presmoother_; - ProjectedBlockGSStep<MatrixType, VectorType> postsmoother_; - std::shared_ptr<Step> multigridStep_; + // linear solver + //Preconditioner preconditioner_; + LinearSolverStep linearSolverStep_; + EnergyNorm<Matrix, Vector> energyNorm_; + std::shared_ptr<LinearSolver> linearSolver_; - std::vector<std::shared_ptr<TransferOperator>> transferOperators_; + // TNNMGStep + std::shared_ptr<Step> tnnmgStep_; }; #endif diff --git a/src/spatial-solving/solverfactory_old.cc b/src/spatial-solving/solverfactory_old.cc new file mode 100644 index 0000000000000000000000000000000000000000..cbbe5ef1d7cbabc1c2ecd56677dad245192ed600 --- /dev/null +++ b/src/spatial-solving/solverfactory_old.cc @@ -0,0 +1,78 @@ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#ifdef HAVE_IPOPT +#undef HAVE_IPOPT +#endif + +#include <dune/common/bitsetvector.hh> + +#include <dune/fufem/assemblers/transferoperatorassembler.hh> +#include <dune/solvers/solvers/solver.hh> + +#include "solverfactory_old.hh" + + +template <class DeformedGrid, class Nonlinearity, class MatrixType, class VectorType> +SolverFactoryOld<DeformedGrid, Nonlinearity, MatrixType, VectorType>::SolverFactoryOld( + const Dune::ParameterTree& parset, const Dune::Contact::NBodyAssembler<DeformedGrid, VectorType>& nBodyAssembler, + const Dune::BitSetVector<DeformedGrid::dimension>& ignoreNodes) + : nBodyAssembler_(nBodyAssembler), + baseEnergyNorm_(baseSolverStep_), + baseSolver_(&baseSolverStep_, + parset.get<size_t>("linear.maximumIterations"), + parset.get<double>("linear.tolerance"), &baseEnergyNorm_, + Solver::QUIET), + transferOperators_(nBodyAssembler.getGrids().at(0)->maxLevel()) { + + /* baseSolverStep_.obstacles_ = using HasObstacle = Dune::BitSetVector<BlockSize>; + using Obstacle = BoxConstraint<Field, BlockSize>; + const HasObstacle* hasObstacle_; + const std::vector<Obstacle>* obstacles_;*/ + + multigridStep_ = std::make_shared<Step>(); + // tnnmg iteration step + multigridStep_->setMGType(parset.get<int>("main.multi"), parset.get<int>("main.pre"), parset.get<int>("main.post")); + multigridStep_->setIgnore(ignoreNodes); + multigridStep_->setBaseSolver(baseSolver_); + multigridStep_->setSmoother(&presmoother_, &postsmoother_); + multigridStep_->setHasObstacle(nBodyAssembler_.totalHasObstacle_); + multigridStep_->setObstacles(nBodyAssembler_.totalObstacles_); + multigridStep_->setVerbosity(NumProc::QUIET); + + // create the transfer operators + const int nCouplings = nBodyAssembler_.nCouplings(); + const auto grids = nBodyAssembler_.getGrids(); + + for (size_t i=0; i<transferOperators_.size(); i++) { + transferOperators_[i] = std::make_shared<TransferOperator>(); + } + + std::vector<const Dune::BitSetVector<1>*> fineHasObstacle(nCouplings); + std::vector<const MatrixType*> mortarTransfer(nCouplings); + std::vector<std::array<int,2> > gridIdx(nCouplings); + + for (int j=0; j<nCouplings; j++) { + fineHasObstacle[j] = nBodyAssembler_.contactCoupling_[j]->nonmortarBoundary().getVertices(); + mortarTransfer[j] = &nBodyAssembler_.contactCoupling_[j]->mortarLagrangeMatrix(); + gridIdx[j] = nBodyAssembler_.coupling_[j].gridIdx_; + } + + TransferOperator::setupHierarchy(transferOperators_, + grids, + mortarTransfer, + nBodyAssembler_.localCoordSystems_, + fineHasObstacle, + gridIdx); + + multigridStep_->setTransferOperators(transferOperators_); +} + +template <class DeformedGrid, class Nonlinearity, class MatrixType, class VectorType> +auto SolverFactoryOld<DeformedGrid, Nonlinearity, MatrixType, VectorType>::getStep() + -> std::shared_ptr<Step> { + return multigridStep_; +} + +#include "solverfactory_tmpl_old.cc" diff --git a/src/spatial-solving/solverfactory_old.hh b/src/spatial-solving/solverfactory_old.hh new file mode 100644 index 0000000000000000000000000000000000000000..1c383419e1ac32eced29512d04260881f7157a82 --- /dev/null +++ b/src/spatial-solving/solverfactory_old.hh @@ -0,0 +1,66 @@ +#ifndef SRC_SPATIAL_SOLVING_SOLVERFACTORYOLD_HH +#define SRC_SPATIAL_SOLVING_SOLVERFACTORYOLD_HH + +#include <dune/common/bitsetvector.hh> +#include <dune/common/parametertree.hh> + +#include <dune/solvers/iterationsteps/multigridstep.hh> +#include <dune/solvers/iterationsteps/projectedblockgsstep.hh> +#include <dune/solvers/iterationsteps/blockgsstep.hh> +#include <dune/solvers/norms/energynorm.hh> +#include <dune/solvers/solvers/loopsolver.hh> + +//#include <dune/solvers/transferoperators/compressedmultigridtransfer.hh> +//#include <dune/tnnmg/iterationsteps/genericnonlineargs.hh> +//#include <dune/tnnmg/iterationsteps/tnnmgstep.hh> + +#include <dune/contact/assemblers/nbodyassembler.hh> + +//#include <dune/contact/estimators/hierarchiccontactestimator.hh> +#include <dune/contact/solvers/nsnewtonmgstep.hh> +#include <dune/contact/solvers/nsnewtoncontacttransfer.hh> +#include <dune/contact/solvers/contactobsrestrict.hh> +#include <dune/contact/solvers/contacttransferoperatorassembler.hh> +#include <dune/contact/solvers/nsnewtoncontacttransfer.hh> + +#define USE_OLD_TNNMG //needed for old bisection.hh in tnnmg + +template <class DeformedGridTEMPLATE, class NonlinearityTEMPLATE, class MatrixType, class VectorType> +class SolverFactoryOld { +//protected: +// const size_t dim = DeformedGrid::dimension; + +public: + using Matrix = MatrixType; + using Vector = VectorType; + using DeformedGrid = DeformedGridTEMPLATE; + using Nonlinearity = NonlinearityTEMPLATE; + +public: + using Step = Dune::Contact::NonSmoothNewtonMGStep<MatrixType, VectorType>; + using TransferOperator = Dune::Contact::NonSmoothNewtonContactTransfer<VectorType>; + + SolverFactoryOld(Dune::ParameterTree const &parset, const Dune::Contact::NBodyAssembler<DeformedGrid, VectorType>& nBodyAssembler, + const Dune::BitSetVector<DeformedGrid::dimension>& ignoreNodes); + + std::shared_ptr<Step> getStep(); + + const Dune::Contact::NBodyAssembler<DeformedGrid, VectorType>& getNBodyAssembler() const { + return nBodyAssembler_; + } + +private: + const Dune::Contact::NBodyAssembler<DeformedGrid, VectorType>& nBodyAssembler_; + + //ProjectedBlockGSStep<MatrixType, VectorType> baseSolverStep_; + BlockGSStep<MatrixType, VectorType> baseSolverStep_; + EnergyNorm<MatrixType, VectorType> baseEnergyNorm_; + LoopSolver<VectorType> baseSolver_; + + ProjectedBlockGSStep<MatrixType, VectorType> presmoother_; + ProjectedBlockGSStep<MatrixType, VectorType> postsmoother_; + std::shared_ptr<Step> multigridStep_; + + std::vector<std::shared_ptr<TransferOperator>> transferOperators_; +}; +#endif diff --git a/src/spatial-solving/solverfactory_tmpl.cc b/src/spatial-solving/solverfactory_tmpl.cc index 7e06390bb45510eb2a9b4b209a23db01d29a4b1c..60fc8802b7242b1c27eae50ee0bde47a5e715708 100644 --- a/src/spatial-solving/solverfactory_tmpl.cc +++ b/src/spatial-solving/solverfactory_tmpl.cc @@ -5,16 +5,10 @@ #include "../explicitgrid.hh" #include "../explicitvectors.hh" -#include <dune/tnnmg/nonlinearities/zerononlinearity.hh> -#include <dune/tnnmg/problem-classes/blocknonlineartnnmgproblem.hh> -#include <dune/tnnmg/problem-classes/convexproblem.hh> +//#include "../../dune/tectonic/globalratestatefriction.hh" +#include "tnnmg/functional.hh" +#include "tnnmg/zerononlinearity.hh" -#include <dune/tectonic/globalfriction.hh> -#include <dune/tectonic/myblockproblem.hh> +using FrictionlessFunctional = Functional<Matrix&, Vector&, ZeroNonlinearity, Vector&, Vector&, double>; +template class SolverFactory<FrictionlessFunctional, BitVector>; -template class SolverFactory<DeformedGrid, GlobalFriction<Matrix, Vector>, Matrix, Vector>; - -/*template class SolverFactory< - MY_DIM, BlockNonlinearTNNMGProblem<ConvexProblem< - ZeroNonlinearity<LocalVector, LocalMatrix>, Matrix>>, - Grid>;*/ diff --git a/src/spatial-solving/solverfactory_tmpl_old.cc b/src/spatial-solving/solverfactory_tmpl_old.cc new file mode 100644 index 0000000000000000000000000000000000000000..600132d31b71a6fda13c7d955374bf98d01f9412 --- /dev/null +++ b/src/spatial-solving/solverfactory_tmpl_old.cc @@ -0,0 +1,16 @@ +#ifndef MY_DIM +#error MY_DIM unset +#endif + +#include "../explicitgrid.hh" +#include "../explicitvectors.hh" + + +#include <dune/tectonic/globalfriction.hh> + +template class SolverFactoryOld<DeformedGrid, GlobalFriction<Matrix, Vector>, Matrix, Vector>; + +/*template class SolverFactory< + MY_DIM, BlockNonlinearTNNMGProblem<ConvexProblem< + ZeroNonlinearity<LocalVector, LocalMatrix>, Matrix>>, + Grid>;*/ diff --git a/src/spatial-solving/tnnmg/functional.hh b/src/spatial-solving/tnnmg/functional.hh new file mode 100644 index 0000000000000000000000000000000000000000..8b41cd3e7002eaf287dfbdc0c3c26fcb91ad5825 --- /dev/null +++ b/src/spatial-solving/tnnmg/functional.hh @@ -0,0 +1,420 @@ +// -*- tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- +// vi: set ts=8 sw=2 et sts=2: +#ifndef DUNE_TECTONIC_SPATIAL_SOLVING_FUNCTIONAL_HH +#define DUNE_TECTONIC_SPATIAL_SOLVING_FUNCTIONAL_HH + +#include <cstddef> +#include <type_traits> + +#include <dune/solvers/common/wrapownshare.hh> +#include <dune/solvers/common/copyorreference.hh> +#include <dune/solvers/common/interval.hh> +#include <dune/solvers/common/resize.hh> + +#include <dune/matrix-vector/algorithm.hh> +#include <dune/matrix-vector/axpy.hh> + +#include <dune/tnnmg/functionals/boxconstrainedquadraticfunctional.hh> + +/** \brief Coordinate restriction of box constrained quadratic functional with nonlinearity; + * mainly used for presmoothing in TNNMG algorithm + * + * \tparam M global matrix type + * \tparam V global vector type + * \tparam V nonlinearity type + * \tparam R Range type + */ +template<class M, class V, class N, class R> +class ShiftedFunctional : public Dune::TNNMG::ShiftedBoxConstrainedQuadraticFunctional<M,V,R> { + using Base = Dune::TNNMG::ShiftedBoxConstrainedQuadraticFunctional<M,V,R>; + +public: + using Matrix = M; + using Vector = V; + using Nonlinearity = N; + using LowerObstacle = Vector; + using UpperObstacle = Vector; + using Range = R; + + ShiftedFunctional(const Matrix& quadraticPart, const Vector& linearPart, const Nonlinearity& phi, const LowerObstacle& lowerObstacle, const UpperObstacle& upperObstacle, const Vector& origin) : + Base(quadraticPart, linearPart, lowerObstacle, upperObstacle, origin), + phi_(phi) + {} + + Range operator()(const Vector& v) const + { + auto temp = Base::Base::origin(); + temp += v; + if (checkInsideBox(temp, this->originalLowerObstacle(), this->originalUpperObstacle())) + return Base::Base::operator()(v) + phi_.operator()(temp); + return std::numeric_limits<Range>::max(); + } + + const auto& phi() const { + return phi_; + } + +protected: + const Nonlinearity& phi_; +}; + + + + + +/** \brief Coordinate restriction of box constrained quadratic functional with nonlinearity; + * mainly used for line search step in TNNMG algorithm + * + * \tparam M Global matrix type + * \tparam V Global vector type + * \tparam N nonlinearity type + * \tparam L Global lower obstacle type + * \tparam U Global upper obstacle type + * \tparam R Range type + */ +template<class M, class V, class N, class L, class U, class R=double> +class DirectionalRestriction : + public Dune::TNNMG::BoxConstrainedQuadraticDirectionalRestriction<M,V,L,U,R> +{ + using Base = Dune::TNNMG::BoxConstrainedQuadraticDirectionalRestriction<M,V,L,U,R>; + using Nonlinearity = N; + using Interval = typename Dune::Solvers::Interval<R>; + +public: + using GlobalMatrix = typename Base::GlobalMatrix; + using GlobalVector = typename Base::GlobalVector; + using GlobalLowerObstacle = typename Base::GlobalLowerObstacle; + using GlobalUpperObstacle = typename Base::GlobalUpperObstacle; + + using Matrix = typename Base::Matrix; + using Vector = typename Base::Vector; + + DirectionalRestriction(const GlobalMatrix& matrix, const GlobalVector& linearTerm, const Nonlinearity& phi, const GlobalLowerObstacle& lower, const GlobalLowerObstacle& upper, const GlobalVector& origin, const GlobalVector& direction) : + Base(matrix, linearTerm, lower, upper, origin, direction), + origin_(origin), + direction_(direction), + phi_(phi) + { + phi_.directionalDomain(origin_, direction_, domain_); + + if (domain_[0] < this->defectLower_) { + domain_[0] = this->defectLower_; + } + + if (domain_[1] > this->defectUpper_) { + domain_[1] = this->defectUpper_; + } + } + + auto subDifferential(double x) const { + Interval D; + GlobalVector uxv = origin_; + + Dune::MatrixVector::addProduct(uxv, x, direction_); + phi_.directionalSubDiff(uxv, direction_, D); + auto const Axmb = this->quadraticPart_ * x - this->linearPart_; + D[0] += Axmb; + D[1] += Axmb; + + return D; + } + + auto domain() const { + return domain_; + } + + const GlobalVector& origin() const { + return origin_; + } + + const GlobalVector& direction() const { + return direction_; + } + +protected: + const GlobalVector& origin_; + const GlobalVector& direction_; + + const Nonlinearity& phi_; + Interval domain_; +}; + +/** \brief Box constrained quadratic functional with nonlinearity + * Note: call setIgnore() to set up functional in affine subspace with ignore information + * + * \tparam V Vector type + * \tparam N Nonlinearity type + * \tparam L Lower obstacle type + * \tparam U Upper obstacle type + * \tparam R Range type + */ +template<class V, class N, class L, class U, class O, class D, class R> +class FirstOrderModelFunctional { + using Interval = typename Dune::Solvers::Interval<R>; + +public: + using Vector = std::decay_t<V>; + using Nonlinearity = std::decay_t<N>; + using LowerObstacle = std::decay_t<L>; + using UpperObstacle = std::decay_t<U>; + using Range = R; + + using field_type = typename Vector::field_type; + +private: + void init() { + auto origin = origin_.get(); + auto direction = direction_.get(); + + // set defect obstacles + defectLower_ = -std::numeric_limits<field_type>::max(); + defectUpper_ = std::numeric_limits<field_type>::max(); + Dune::TNNMG::directionalObstacles(origin, direction, lower_.get(), upper_.get(), defectLower_, defectUpper_); + + // set domain + phi_.get().directionalDomain(origin, direction, domain_); + + if (domain_[0] < defectLower_) { + domain_[0] = defectLower_; + } + + if (domain_[1] > defectUpper_) { + domain_[1] = defectUpper_; + } + + // set quadratic and linear parts of functional + quadraticPart_ = direction*direction; + quadraticPart_ *= maxEigenvalue_; + + linearPart_ = linearTerm_.get()*direction - maxEigenvalue_*(direction*origin); + } + +public: + template <class MM, class VV1, class NN, class LL, class UU, class VV2, class VV3> + FirstOrderModelFunctional( + const MM& matrix, + VV1&& linearTerm, + NN&& phi, + LL&& lower, + UU&& upper, + VV2&& origin, + VV3&& direction) : + linearTerm_(std::forward<VV1>(linearTerm)), + lower_(std::forward<LL>(lower)), + upper_(std::forward<UU>(upper)), + origin_(std::forward<VV2>(origin)), + direction_(std::forward<VV3>(direction)), + phi_(std::forward<NN>(phi)) { + + // set maxEigenvalue_ from matrix + Vector eigenvalues; + Dune::FMatrixHelp::eigenValues(matrix, eigenvalues); + maxEigenvalue_ = *std::max_element(std::begin(eigenvalues), std::end(eigenvalues)); + + init(); + } + + template <class VV1, class NN, class LL, class UU, class VV2, class VV3> + FirstOrderModelFunctional( + const Range& maxEigenvalue, + VV1&& linearTerm, + NN&& phi, + LL&& lower, + UU&& upper, + VV2&& origin, + VV3&& direction) : + linearTerm_(std::forward<VV1>(linearTerm)), + lower_(std::forward<LL>(lower)), + upper_(std::forward<UU>(upper)), + origin_(std::forward<VV2>(origin)), + direction_(std::forward<VV3>(direction)), + phi_(std::forward<NN>(phi)), + maxEigenvalue_(maxEigenvalue) { + + init(); + } + + template <class BitVector> + auto getIgnoreFunctional(const BitVector& ignore) const { + Vector direction = direction_.get(); + Vector origin = origin_.get(); + // Dune::Solvers::resizeInitializeZero(direction, linearPart()); + for (size_t j = 0; j < ignore.size(); ++j) + if (ignore[j]) + direction[j] = 0; // makes sure result remains in subspace after correction + else + origin[j] = 0; // shift affine offset + + return FirstOrderModelFunctional<Vector, Nonlinearity&, LowerObstacle, UpperObstacle, Vector, Vector, Range>(maxEigenvalue_, linearTerm_, phi_, lower_, upper_, std::move(origin), std::move(direction)); + } + + Range operator()(const Vector& v) const + { + DUNE_THROW(Dune::NotImplemented, "Evaluation of FirstOrderModelFunctional not implemented"); + } + + auto subDifferential(double x) const { + Interval Di; + Vector uxv = origin_.get(); + + Dune::MatrixVector::addProduct(uxv, x, direction_.get()); + phi_.get().directionalSubDiff(uxv, direction_.get(), Di); + + const auto Axmb = quadraticPart_ * x - linearPart_; + Di[0] += Axmb; + Di[1] += Axmb; + + return Di; + } + + const Interval& domain() const { + return domain_; + } + + const Vector& origin() const { + return origin_.get(); + } + + const Vector& direction() const { + return direction_.get(); + } + + const field_type& defectLower() const { + return defectLower_; + } + + const field_type& defectUpper() const { + return defectUpper_; + } + +private: + Dune::Solvers::ConstCopyOrReference<V> linearTerm_; + Dune::Solvers::ConstCopyOrReference<L> lower_; + Dune::Solvers::ConstCopyOrReference<U> upper_; + + Dune::Solvers::ConstCopyOrReference<O> origin_; + Dune::Solvers::ConstCopyOrReference<D> direction_; + + Dune::Solvers::ConstCopyOrReference<N> phi_; + + Interval domain_; + + Range maxEigenvalue_; + + field_type quadraticPart_; + field_type linearPart_; + + field_type defectLower_; + field_type defectUpper_; +}; + +// \ToDo This should be an inline friend of ShiftedBoxConstrainedQuadraticFunctional +// but gcc-4.9.2 shipped with debian jessie does not accept +// inline friends with auto return type due to bug-59766. +// Notice, that this is fixed in gcc-4.9.3. +template<class Index, class M, class V, class Nonlinearity, class R> +auto coordinateRestriction(const ShiftedFunctional<M, V, Nonlinearity, R>& f, const Index& i) +{ + using Range = R; + using LocalMatrix = std::decay_t<decltype(f.quadraticPart()[i][i])>; + using LocalVector = std::decay_t<decltype(f.originalLinearPart()[i])>; + using LocalLowerObstacle = std::decay_t<decltype(f.originalLowerObstacle()[i])>; + using LocalUpperObstacle = std::decay_t<decltype(f.originalUpperObstacle()[i])>; + + using namespace Dune::MatrixVector; + namespace H = Dune::Hybrid; + + const LocalMatrix* Aii_p = nullptr; + + LocalVector ri = f.originalLinearPart()[i]; + const auto& Ai = f.quadraticPart()[i]; + sparseRangeFor(Ai, [&](auto&& Aij, auto&& j) { + // TODO Here we must implement a wrapper to guarantee that this will work with proxy matrices! + H::ifElse(H::equals(j, i), [&](auto&& id){ + Aii_p = id(&Aij); + }); + Dune::TNNMG::Imp::mmv(Aij, f.origin()[j], ri, Dune::PriorityTag<1>()); + }); + + LocalLowerObstacle dli = f.originalLowerObstacle()[i]; + LocalUpperObstacle dui = f.originalUpperObstacle()[i]; + dli -= f.origin()[i]; + dui -= f.origin()[i]; + + auto&& phii = f.phi().restriction(i); + + auto v = ri; + double const vnorm = v.two_norm(); + if (vnorm > 1.0) + v /= vnorm; + + return FirstOrderModelFunctional<LocalVector, decltype(phii), LocalLowerObstacle, LocalUpperObstacle, LocalVector, LocalVector, Range>(*Aii_p, std::move(ri), std::move(phii), std::move(dli), std::move(dui), std::move(f.origin()[i]), std::move(v)); +} + + +/** \brief Box constrained quadratic functional with nonlinearity + * + * \tparam M Matrix type + * \tparam V Vector type + * \tparam L Lower obstacle type + * \tparam U Upper obstacle type + * \tparam R Range type + */ +template<class M, class V, class N, class L, class U, class R> +class Functional : public Dune::TNNMG::BoxConstrainedQuadraticFunctional<M, V, L, U, R> +{ +private: + using Base = Dune::TNNMG::BoxConstrainedQuadraticFunctional<M, V, L, U, R>; + + +public: + using Nonlinearity = std::decay_t<N>; + + using Matrix = typename Base::Matrix; + using Vector = typename Base::Vector; + using Range = typename Base::Range; + using LowerObstacle = typename Base::LowerObstacle; + using UpperObstacle = typename Base::UpperObstacle; + +private: + Dune::Solvers::ConstCopyOrReference<N> phi_; + +public: + + template <class MM, class VV, class NN, class LL, class UU> + Functional( + MM&& matrix, + VV&& linearPart, + NN&& phi, + LL& lower, + UU& upper) : + Base(std::forward<MM>(matrix), std::forward<VV>(linearPart), std::forward<LL>(lower), std::forward<UU>(upper)), + phi_(std::forward<NN>(phi)) + {} + + const Nonlinearity& phi() const { + return phi_.get(); + } + + Range operator()(const Vector& v) const + { + if (Dune::TNNMG::checkInsideBox(v, this->lower_.get(), this->upper_.get())) + return Base::Base::operator()(v) + phi_.get().operator()(v); + return std::numeric_limits<Range>::max(); + } + + friend auto directionalRestriction(const Functional& f, const Vector& origin, const Vector& direction) + -> DirectionalRestriction<Matrix, Vector, Nonlinearity, LowerObstacle, UpperObstacle, Range> + { + return DirectionalRestriction<Matrix, Vector, Nonlinearity, LowerObstacle, UpperObstacle, Range>(f.quadraticPart(), f.linearPart(), f.phi(), f.lowerObstacle(), f.upperObstacle(), origin, direction); + } + + friend auto shift(const Functional& f, const Vector& origin) + -> ShiftedFunctional<Matrix, Vector, Nonlinearity, Range> + { + return ShiftedFunctional<Matrix, Vector, Nonlinearity, Range>(f.quadraticPart(), f.linearPart(), f.phi(), f.lowerObstacle(), f.upperObstacle(), origin); + } +}; + + +#endif diff --git a/src/spatial-solving/tnnmg/levelglobalpreconditioner.hh b/src/spatial-solving/tnnmg/levelglobalpreconditioner.hh new file mode 100644 index 0000000000000000000000000000000000000000..2b7b4e2bb80f6ad5ec302097654dbb5bc320deb4 --- /dev/null +++ b/src/spatial-solving/tnnmg/levelglobalpreconditioner.hh @@ -0,0 +1,158 @@ +#ifndef LEVEL_GLOBAL_PRECONDITIONER_HH +#define LEVEL_GLOBAL_PRECONDITIONER_HH + +#include <string> + +#include <dune/common/fvector.hh> + +#include <dune/solvers/iterationsteps/lineariterationstep.hh> + +#include <dune/istl/umfpack.hh> + +#include <dune/fufem/boundarypatch.hh> +#include <dune/fufem/functiontools/boundarydofs.hh> + +#include <dune/faultnetworks/assemblers/globalfaultassembler.hh> +#include <dune/faultnetworks/levelinterfacenetwork.hh> +#include <dune/faultnetworks/utils/debugutils.hh> + + +template <class BasisType, class LocalAssembler, class LocalInterfaceAssembler, class MatrixType, class VectorType> +class LevelGlobalPreconditioner : public LinearIterationStep<MatrixType, VectorType> { + +public: + enum BoundaryMode {homogeneous, fromIterate}; + +private: + typedef typename BasisType::GridView GridView; + typedef typename GridView::Grid GridType; + + const LevelInterfaceNetwork<GridView>& levelInterfaceNetwork_; + const LocalAssembler& localAssembler_; + const std::vector<std::shared_ptr<LocalInterfaceAssembler>>& localInterfaceAssemblers_; + + const GridType& grid_; + const int level_; + const BasisType basis_; + + Dune::BitSetVector<1> boundaryDofs_; + MatrixType matrix_; + VectorType rhs_; + + bool requireBuild_; + +public: + + // for each active fault in levelInterfaceNetwork: set up local problem, compute local correction + LevelGlobalPreconditioner(const LevelInterfaceNetwork<GridView>& levelInterfaceNetwork, + const LocalAssembler& localAssembler, + const std::vector<std::shared_ptr<LocalInterfaceAssembler>>& localInterfaceAssemblers) : + levelInterfaceNetwork_(levelInterfaceNetwork), + localAssembler_(localAssembler), + localInterfaceAssemblers_(localInterfaceAssemblers), + grid_(levelInterfaceNetwork_.grid()), + level_(levelInterfaceNetwork_.level()), + basis_(levelInterfaceNetwork_) + { + assert(localInterfaceAssemblers_.size() == levelInterfaceNetwork_.size()); + } + + void build() { + //printBasisDofLocation(basis_); + + GlobalFaultAssembler<BasisType, BasisType> globalFaultAssembler(basis_, basis_, levelInterfaceNetwork_); + globalFaultAssembler.assembleOperator(localAssembler_, localInterfaceAssemblers_, matrix_); + + typedef typename MatrixType::row_type RowType; + typedef typename RowType::ConstIterator ColumnIterator; + + const GridView& gridView = levelInterfaceNetwork_.levelGridView(); + + // set boundary conditions + BoundaryPatch<GridView> boundaryPatch(gridView, true); + constructBoundaryDofs(boundaryPatch, basis_, boundaryDofs_); + + for(size_t i=0; i<boundaryDofs_.size(); i++) { + if(!boundaryDofs_[i][0]) + continue; + + RowType& row = matrix_[i]; + + ColumnIterator cIt = row.begin(); + ColumnIterator cEndIt = row.end(); + + for(; cIt!=cEndIt; ++cIt) { + row[cIt.index()] = 0; + } + + row[i] = 1; + } + + requireBuild_ = false; + } + + + + virtual void setProblem(const MatrixType& mat, VectorType& x, const VectorType& rhs) { + this->x_ = &x; + updateRhs(rhs); + this->mat_ = Dune::stackobject_to_shared_ptr(mat); // mat will be set but not used + } + + virtual void iterate() { + //print(matrix_, "coarse matrix: "); + //print(rhs_, "coarse rhs: "); + + // compute solution directly + + if (requireBuild_) + DUNE_THROW(Dune::Exception, "LevelGlobalPreconditioner::iterate() Call build() before solving the global problem!"); + + Dune::Timer timer; + timer.reset(); + timer.start(); + + this->x_->resize(matrix_.M()); + *(this->x_) = 0; + + #if HAVE_UMFPACK + Dune::InverseOperatorResult res; + VectorType rhsCopy(rhs_); + + Dune::UMFPack<MatrixType> solver(matrix_); + solver.apply(*(this->x_), rhsCopy, res); + + #else + #error No UMFPack! + #endif + + //std::cout << "LevelGlobalPreconditioner::iterate() Solving global problem took: " << timer.elapsed() << " seconds" << std::endl; + + } + + const BasisType& basis() const { + return basis_; + } + + const GridView& gridView() const { + return basis_.getGridView(); + } + + const LevelInterfaceNetwork<GridView>& levelInterfaceNetwork() const { + return levelInterfaceNetwork_; + } + +private: + void updateRhs(const VectorType& rhs){ + rhs_.resize(matrix_.M()); + rhs_ = 0; + + for (size_t i=0; i<rhs.size(); i++) { + if (!boundaryDofs_[i][0]) + rhs_[i] = rhs[i]; + } + } +}; + +#endif + diff --git a/src/spatial-solving/tnnmg/levelpatchpreconditioner.hh b/src/spatial-solving/tnnmg/levelpatchpreconditioner.hh new file mode 100644 index 0000000000000000000000000000000000000000..bbe464fdec9c3d9db5c218cecdbe4c448cd06fad --- /dev/null +++ b/src/spatial-solving/tnnmg/levelpatchpreconditioner.hh @@ -0,0 +1,261 @@ +#ifndef LEVEL_PATCH_PRECONDITIONER_HH +#define LEVEL_PATCH_PRECONDITIONER_HH + +#include <string> + +#include <dune/common/timer.hh> +#include <dune/common/fvector.hh> +#include <dune/common/bitsetvector.hh> + +#include <dune/solvers/iterationsteps/lineariterationstep.hh> + +#include <dune/faultnetworks/assemblers/globalfaultassembler.hh> +#include <dune/faultnetworks/patchfactories/supportpatchfactory.hh> +#include <dune/faultnetworks/localproblem.hh> +#include <dune/faultnetworks/levelinterfacenetwork.hh> +#include <dune/faultnetworks/utils/debugutils.hh> + +#include <dune/fufem/boundarypatch.hh> +#include <dune/fufem/functiontools/boundarydofs.hh> + + +template <class BasisType, class LocalAssembler, class LocalInterfaceAssembler, class MatrixType, class VectorType> +class LevelPatchPreconditioner : public LinearIterationStep<MatrixType, VectorType> { + +public: + enum Mode {additive, multiplicative}; + enum BoundaryMode {homogeneous, fromIterate}; + +private: + typedef typename BasisType::GridView GridView; + typedef typename GridView::Grid GridType; + + const LevelInterfaceNetwork<GridView>& levelInterfaceNetwork_; + const BasisType& patchLevelBasis_; + const LocalAssembler& localAssembler_; + const std::vector<std::shared_ptr<LocalInterfaceAssembler>>& localInterfaceAssemblers_; + const Mode mode_; + + const GridType& grid_; + const int level_; + const BasisType basis_; + + size_t patchDepth_; + BoundaryMode boundaryMode_; + + MatrixType matrix_; + std::vector<std::shared_ptr<OscLocalProblem<MatrixType, VectorType>> > localProblems_; + +public: + + // for each coarse patch given by patchLevelBasis: set up local problem, compute local correction + LevelPatchPreconditioner(const LevelInterfaceNetwork<GridView>& levelInterfaceNetwork, + const BasisType& patchLevelBasis, + const LocalAssembler& localAssembler, + const std::vector<std::shared_ptr<LocalInterfaceAssembler>>& localInterfaceAssemblers, + const Mode mode = LevelPatchPreconditioner::Mode::additive) : + levelInterfaceNetwork_(levelInterfaceNetwork), + patchLevelBasis_(patchLevelBasis), + localAssembler_(localAssembler), + localInterfaceAssemblers_(localInterfaceAssemblers), + mode_(mode), + grid_(levelInterfaceNetwork_.grid()), + level_(levelInterfaceNetwork_.level()), + basis_(levelInterfaceNetwork_) + { + setPatchDepth(); + setBoundaryMode(); + + assert(localInterfaceAssemblers_.size() == levelInterfaceNetwork_.size()); + } + + void build() { + // assemble stiffness matrix for entire level including all faults + GlobalFaultAssembler<BasisType, BasisType> globalFaultAssembler(basis_, basis_, levelInterfaceNetwork_); + globalFaultAssembler.assembleOperator(localAssembler_, localInterfaceAssemblers_, matrix_); + + // set boundary conditions + Dune::BitSetVector<1> globalBoundaryDofs; + BoundaryPatch<GridView> boundaryPatch(levelInterfaceNetwork_.levelGridView(), true); + constructBoundaryDofs(boundaryPatch, basis_, globalBoundaryDofs); + + typedef typename MatrixType::row_type RowType; + typedef typename RowType::ConstIterator ColumnIterator; + + for(size_t i=0; i<globalBoundaryDofs.size(); i++) { + if(!globalBoundaryDofs[i][0]) + continue; + + RowType& row = matrix_[i]; + + ColumnIterator cIt = row.begin(); + ColumnIterator cEndIt = row.end(); + + for(; cIt!=cEndIt; ++cIt) { + row[cIt.index()] = 0; + } + row[i] = 1; + } + + // init vertexInElements + const int dim = GridType::dimension; + typedef typename GridType::template Codim<0>::Entity EntityType; + std::vector<std::vector<EntityType>> vertexInElements; + + const GridView& patchLevelGridView = patchLevelBasis_.getGridView(); + vertexInElements.resize(patchLevelGridView.size(dim)); + for (size_t i=0; i<vertexInElements.size(); i++) { + vertexInElements[i].resize(0); + } + + typedef typename BasisType::LocalFiniteElement FE; + typedef typename GridView::template Codim <0>::Iterator ElementLevelIterator; + ElementLevelIterator endElemIt = patchLevelGridView.template end <0>(); + for (ElementLevelIterator it = patchLevelGridView. template begin <0>(); it!=endElemIt; ++it) { + + // compute coarseGrid vertexInElements + const FE& coarseFE = patchLevelBasis_.getLocalFiniteElement(*it); + + for (size_t i=0; i<coarseFE.localBasis().size(); ++i) { + int dofIndex = patchLevelBasis_.indexInGridView(*it, i); + vertexInElements[dofIndex].push_back(*it); + } + } + + localProblems_.resize(vertexInElements.size()); + + std::cout << std::endl; + std::cout << "---------------------------------------------" << std::endl; + std::cout << "Initializing local fine grid corrections! Level: " << level_ << std::endl; + + // init local fine level corrections + Dune::Timer timer; + timer.reset(); + timer.start(); + + const int patchLevel = patchLevelBasis_.faultNetwork().level(); + for (size_t i=0; i<vertexInElements.size(); i++) { + //std::cout << i << std::endl; + //std::cout << "---------------" << std::endl; + + SupportPatchFactory<BasisType> patchFactory(patchLevelBasis_, basis_, patchLevel, level_, vertexInElements, i, patchDepth_); + std::vector<int>& localToGlobal = patchFactory.getLocalToGlobal(); + Dune::BitSetVector<1>& boundaryDofs = patchFactory.getBoundaryDofs(); + VectorType rhs; + rhs.resize(matrix_.N()); + rhs = 0; + + //print(localToGlobal, "localToGlobal: "); + //print(boundaryDofs, "boundaryDofs: "); + + localProblems_[i] = std::make_shared<OscLocalProblem<MatrixType, VectorType>>(matrix_, rhs, localToGlobal, boundaryDofs); + + /* + if ((i+1) % 10 == 0) { + std::cout << '\r' << std::floor((i+1.0)/patchLevelBasis_.size()*100) << " % done. Elapsed time: " << timer.elapsed() << " seconds. Predicted total setup time: " << timer.elapsed()/(i+1.0)*patchLevelBasis_.size() << " seconds." << std::flush; + }*/ + } + + std::cout << std::endl; + std::cout << "Total setup time: " << timer.elapsed() << " seconds." << std::endl; + std::cout << "---------------------------------------------" << std::endl; + timer.stop(); + } + + void setPatchDepth(const size_t patchDepth = 0) { + patchDepth_ = patchDepth; + } + + void setBoundaryMode(const BoundaryMode boundaryMode = LevelPatchPreconditioner::BoundaryMode::homogeneous) { + boundaryMode_ = boundaryMode; + } + + virtual void setProblem(const MatrixType& mat, VectorType& x, const VectorType& rhs) { + this->x_ = &x; + this->rhs_ = &rhs; + this->mat_ = Dune::stackobject_to_shared_ptr(mat); + + for (size_t i=0; i<localProblems_.size(); i++) { + if (boundaryMode_ == BoundaryMode::homogeneous) + localProblems_[i]->updateRhs(rhs); + else + localProblems_[i]->updateRhsAndBoundary(rhs, x); + } + } + + virtual void iterate() { + if (mode_ == additive) + iterateAdd(); + else + iterateMult(); + } + + void iterateAdd() { + *(this->x_) = 0; + + VectorType it, x; + for (size_t i=0; i<localProblems_.size(); i++) { + localProblems_[i]->solve(it); + localProblems_[i]->prolong(it, x); + + /*if (i==5) { + writeToVTK(basis_, x, "/storage/mi/podlesny/data/faultnetworks/iterates/", "exactvertexdata_patchDepth_"+std::to_string(patchDepth_)); + }*/ + + *(this->x_) += x; + } + } + + void iterateMult() { + *(this->x_) = 0; + + VectorType it, x; + for (size_t i=0; i<localProblems_.size(); i++) { + VectorType updatedRhs(*(this->rhs_)); + matrix_.mmv(*(this->x_), updatedRhs); + + //step(i); + //print(updatedRhs, "localRhs: "); + //writeToVTK(basis_, updatedRhs, "/storage/mi/podlesny/data/faultnetworks/rhs/local", "exactvertexdata_step_"+std::to_string(i)); + + if (boundaryMode_ == BoundaryMode::homogeneous) + localProblems_[i]->updateRhs(updatedRhs); + else + localProblems_[i]->updateRhsAndBoundary(updatedRhs, *(this->x_)); + + localProblems_[i]->solve(it); + localProblems_[i]->prolong(it, x); + + + //print(it, "it: "); + //print(x, "x: "); + + //writeToVTK(basis_, x, "/storage/mi/podlesny/data/faultnetworks/sol/local", "exactvertexdata_step_"+std::to_string(i)); + + /*if (i==5) { + writeToVTK(basis_, x, "/storage/mi/podlesny/data/faultnetworks/iterates/", "exactvertexdata_patchDepth_"+std::to_string(patchDepth_)); + }*/ + + *(this->x_) += x; + } + } + + const BasisType& basis() const { + return basis_; + } + + const GridView& gridView() const { + return basis_.getGridView(); + } + + const LevelInterfaceNetwork<GridView>& levelInterfaceNetwork() const { + return levelInterfaceNetwork_; + } + + size_t size() const { + return localProblems_.size(); + } +}; + +#endif + diff --git a/src/spatial-solving/tnnmg/linearization.hh b/src/spatial-solving/tnnmg/linearization.hh new file mode 100644 index 0000000000000000000000000000000000000000..4e7ce13238b727fec2ebdf91da04cdfd51aa9a0a --- /dev/null +++ b/src/spatial-solving/tnnmg/linearization.hh @@ -0,0 +1,99 @@ +#ifndef DUNE_TECTONIC_LINEARIZATION_HH +#define DUNE_TECTONIC_LINEARIZATION_HH + +#include <dune/tnnmg/functionals/bcqfconstrainedlinearization.hh> +#include <dune/istl/matrixindexset.hh> + +//#include <> + +/*#include <dune/common/bitsetvector.hh> +#include <dune/common/parametertree.hh> +#include <dune/common/fmatrixev.hh> + +#include <dune/fufem/arithmetic.hh> +#include <dune/solvers/common/interval.hh> +#include <dune/solvers/computeenergy.hh> +#include <dune/tnnmg/problem-classes/bisection.hh> +#include <dune/tnnmg/problem-classes/blocknonlineargsproblem.hh> + +#include <dune/tectonic/globalfriction.hh> +#include <dune/tectonic/minimisation.hh> +#include <dune/tectonic/mydirectionalconvexfunction.hh> +#include <dune/tectonic/quadraticenergy.hh>*/ + + +template<class F, class BV> +class Linearization : public Dune::TNNMG::BoxConstrainedQuadraticFunctionalConstrainedLinearization<F,BV> { +private: + using Base = Dune::TNNMG::BoxConstrainedQuadraticFunctionalConstrainedLinearization<F,BV>; + using Vector = typename Base::Vector; + using BitVector = typename Base::BitVector; + + template <class T> + void determineRegularityTruncation(const Vector& x, BitVector&& truncationFlags, const T& truncationTolerance) + { + for (size_t i = 0; i < x.size(); ++i) { + if (this->f_.phi().regularity(i, x[i]) > truncationTolerance) { + truncationFlags[i] = true; + } + } + } + +public: + Linearization(const F& f, const BitVector& ignore) : + Base(f, ignore) + {} + + void bind(const Vector& x) { + auto&& A = this->f_.quadraticPart(); + auto&& phi = this->f_.phi(); + + // compute hessian + // --------------- + + // construct sparsity pattern for linearization + Dune::MatrixIndexSet indices(A.N(), A.M()); + indices.import(A); + phi.addHessianIndices(indices); + + // construct matrix from pattern and initialize it + indices.exportIdx(this->hessian_); + this->hessian_ = 0.0; + + // quadratic part + for (size_t i = 0; i < A.N(); ++i) { + auto const end = std::end(A[i]); + for (auto it = std::begin(A[i]); it != end; ++it) + this->hessian_[i][it.index()] += *it; + } + + // nonlinearity part + phi.addHessian(x, this->hessian_); + + // compute gradient + // ---------------- + + // quadratic part + this->negativeGradient_ = derivative(this->f_)(x); // A*x - b + + // nonlinearity part + phi.addGradient(x, this->negativeGradient_); + + // -grad is needed for Newton step + this->negativeGradient_ *= -1; + + + // determine which components to truncate + // ---------------- + this->truncationFlags_ = this->ignore_; + + determineTruncation(x, this->f_.lowerObstacle(), this->f_.upperObstacle(), this->truncationFlags_, this->truncationTolerance_); // obstacle truncation + determineRegularityTruncation(x, this->truncationFlags_, this->truncationTolerance_); // truncation due to regularity deficit of nonlinearity + + // truncate gradient and hessian + truncateVector(this->negativeGradient_, this->truncationFlags_); + truncateMatrix(this->hessian_, this->truncationFlags_, this->truncationFlags_); + } +}; + +#endif diff --git a/src/spatial-solving/tnnmg/linesearchsolver.hh b/src/spatial-solving/tnnmg/linesearchsolver.hh new file mode 100644 index 0000000000000000000000000000000000000000..834740a22386c08f671547c4894fb619e126f475 --- /dev/null +++ b/src/spatial-solving/tnnmg/linesearchsolver.hh @@ -0,0 +1,35 @@ +// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- +// vi: set et ts=4 sw=2 sts=2: +#ifndef DUNE_TECTONIC_LINESEARCHSOLVER_HH +#define DUNE_TECTONIC_LINESEARCHSOLVER_HH + +#include <dune/tnnmg/problem-classes/bisection.hh> + + +/** + * \brief A local solver for scalar quadratic obstacle problems with nonlinearity + * using bisection + */ +class LineSearchSolver +{ +public: + template<class Vector, class Functional, class BitVector> + void operator()(Vector& x, const Functional& f, const BitVector& ignore) const { + x = 0; + + Dune::Solvers::Interval<double> D; + D = f.subDifferential(0); + if (D[1] > 0) // NOTE: Numerical instability can actually get us here + return; + + if (not ignore) { + int bisectionsteps = 0; + const Bisection globalBisection; + x = globalBisection.minimize(f, 1.0, 0.0, bisectionsteps); + // x = globalBisection.minimize(f, vNorm, 0.0, bisectionsteps) / vNorm; // used rescaled v in f? + } + } +}; + +#endif + diff --git a/src/spatial-solving/tnnmg/localbisectionsolver.hh b/src/spatial-solving/tnnmg/localbisectionsolver.hh new file mode 100644 index 0000000000000000000000000000000000000000..50618dd6c69a1a603ae49f68d5f43e476371353b --- /dev/null +++ b/src/spatial-solving/tnnmg/localbisectionsolver.hh @@ -0,0 +1,66 @@ +// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- +// vi: set et ts=4 sw=2 sts=2: +#ifndef DUNE_TECTONIC_LOCALBISECTIONSOLVER_HH +#define DUNE_TECTONIC_LOCALBISECTIONSOLVER_HH + +#include <dune/tnnmg/problem-classes/bisection.hh> + +/** + * \brief A local solver for quadratic obstacle problems with nonlinearity + * using bisection + */ +class LocalBisectionSolver +{ +public: + template<class Vector, class Functional, class BitVector> + void operator()(Vector& x, const Functional& f, const BitVector& ignore) const { + if (ignore.all()) { + return; + } + + double safety = 1e-14; + if (f.defectUpper() - f.defectLower() < safety) { + x = f.origin(); + return; + } + + int bisectionsteps = 0; + const Bisection globalBisection; + + if (ignore.any()) { + auto&& restrictedf = f.getIgnoreFunctional(ignore); + const auto alpha = globalBisection.minimize(restrictedf, 0.0, 0.0, bisectionsteps); + +#ifdef NEW_TNNMG_COMPUTE_ITERATES_DIRECTLY + x = restrictedf.origin(); + auto correction = restrictedf.direction(); + correction *= alpha; + x += correction; +#else + auto x = restrictedf.direction(); + x *= alpha; +#endif + + + } else { // ignore.none() + const auto alpha = globalBisection.minimize(f, 0.0, 0.0, bisectionsteps); + +#ifdef NEW_TNNMG_COMPUTE_ITERATES_DIRECTLY + x = f.origin(); + auto correction = f.direction(); + correction *= alpha; + x += correction; +#else + auto x = f.direction(); + x *= alpha; +#endif + + } + } +}; + +#endif + + + + diff --git a/src/spatial-solving/tnnmg/multilevelpatchpreconditioner.hh b/src/spatial-solving/tnnmg/multilevelpatchpreconditioner.hh new file mode 100644 index 0000000000000000000000000000000000000000..584cca16aa9c02877efcc778c2b7675ea3d6f297 --- /dev/null +++ b/src/spatial-solving/tnnmg/multilevelpatchpreconditioner.hh @@ -0,0 +1,277 @@ +#ifndef MULTILEVEL_PATCH_PRECONDITIONER_HH +#define MULTILEVEL_PATCH_PRECONDITIONER_HH + +#include <string> + +#include <dune/common/timer.hh> +#include <dune/common/fvector.hh> +#include <dune/common/bitsetvector.hh> + +#include <dune/solvers/iterationsteps/lineariterationstep.hh> + +#include <dune/faultnetworks/preconditioners/levelglobalpreconditioner.hh> +#include <dune/faultnetworks/preconditioners/levelpatchpreconditioner.hh> +#include <dune/faultnetworks/levelinterfacenetwork.hh> +#include <dune/faultnetworks/interfacenetwork.hh> +#include <dune/faultnetworks/dgmgtransfer.hh> + +#include <dune/faultnetworks/utils/debugutils.hh> + +template <class BasisType, class LocalOperatorAssembler, class LocalInterfaceAssembler, class MatrixType, class VectorType> +class MultilevelPatchPreconditioner : public LinearIterationStep<MatrixType, VectorType> { + +public: + enum Mode {additive, multiplicative}; + typedef LevelPatchPreconditioner<BasisType, LocalOperatorAssembler, LocalInterfaceAssembler, MatrixType, VectorType> LevelPatchPreconditionerType; + typedef LevelGlobalPreconditioner<BasisType, LocalOperatorAssembler, LocalInterfaceAssembler, MatrixType, VectorType> LevelGlobalPreconditionerType; + +private: + typedef typename BasisType::GridView GridView; + typedef typename GridView::Grid GridType; + + + typedef typename Dune::BitSetVector<1> BitVector; + + const InterfaceNetwork<GridType>& interfaceNetwork_; + const BitVector& activeLevels_; + const std::vector<std::shared_ptr<LocalOperatorAssembler>>& localAssemblers_; + const std::vector<std::vector<std::shared_ptr<LocalInterfaceAssembler>>>& localInterfaceAssemblers_; + const Mode mode_; + + int itCounter_; + + std::shared_ptr<LevelGlobalPreconditionerType> coarseGlobalPreconditioner_; + std::vector<std::shared_ptr<LevelPatchPreconditionerType>> levelPatchPreconditioners_; + std::vector<VectorType> levelX_; + std::vector<VectorType> levelRhs_; + + std::shared_ptr<LevelInterfaceNetwork<GridView>> allFaultLevelInterfaceNetwork_; + std::shared_ptr<BasisType> allFaultBasis_; + + std::vector<std::shared_ptr<DGMGTransfer<BasisType>>> mgTransfer_; + +public: + MultilevelPatchPreconditioner(const InterfaceNetwork<GridType>& interfaceNetwork, + const BitVector& activeLevels, + const std::vector<std::shared_ptr<LocalOperatorAssembler>>& localAssemblers, + const std::vector<std::vector<std::shared_ptr<LocalInterfaceAssembler>>>& localInterfaceAssemblers, + const Mode mode = MultilevelPatchPreconditioner::Mode::additive) : + interfaceNetwork_(interfaceNetwork), + activeLevels_(activeLevels), + localAssemblers_(localAssemblers), + localInterfaceAssemblers_(localInterfaceAssemblers), + mode_(mode) + { + + if (activeLevels_.size() > (size_t) interfaceNetwork.maxLevel() +1) + DUNE_THROW(Dune::Exception, "MultilevelFaultPreconditioner: too many active levels; preconditioner supports at most (grid.maxLevel + 1) levels!"); + + assert(activeLevels.size() == localAssemblers_.size() && activeLevels.size() == localInterfaceAssemblers_.size()); + + // init level fault preconditioners and multigrid transfer + levelPatchPreconditioners_.resize(0); + mgTransfer_.resize(0); + + int maxLevel = -1; + for (size_t i=0; i<activeLevels_.size(); i++) { + if (activeLevels_[i][0]) { + // init global problem on coarsest level + const LevelInterfaceNetwork<GridView>& levelNetwork = interfaceNetwork.levelInterfaceNetwork(i); + coarseGlobalPreconditioner_ = std::make_shared<LevelGlobalPreconditionerType>(levelNetwork, *localAssemblers_[i], localInterfaceAssemblers_[i]); + + maxLevel = i; + break; + } + } + + typename LevelPatchPreconditionerType::Mode levelMode = LevelPatchPreconditionerType::Mode::additive; + if (mode_ != additive){ + levelMode = LevelPatchPreconditionerType::Mode::multiplicative; + } + + for (size_t i=maxLevel+1; i<activeLevels_.size(); i++) { + if (activeLevels_[i][0]) { + // init local patch preconditioners on each level + const LevelInterfaceNetwork<GridView>& levelNetwork = interfaceNetwork.levelInterfaceNetwork(i); + + //levelPatchPreconditioners_.push_back(std::make_shared<LevelGlobalPreconditionerType>(levelNetwork, *localAssemblers_[i], localInterfaceAssemblers_[i])); + + if (levelPatchPreconditioners_.size() == 0) { + levelPatchPreconditioners_.push_back(std::make_shared<LevelPatchPreconditionerType>(levelNetwork, coarseGlobalPreconditioner_->basis(), *localAssemblers_[i], localInterfaceAssemblers_[i], levelMode)); + } else { + //levelPatchPreconditioners_.push_back(std::make_shared<LevelPatchPreconditionerType>(levelNetwork, coarseGlobalPreconditioner_->basis(), *localAssemblers_[i], localInterfaceAssemblers_[i], levelMode)); + + levelPatchPreconditioners_.push_back(std::make_shared<LevelPatchPreconditionerType>(levelNetwork, levelPatchPreconditioners_.back()->basis(), *localAssemblers_[i], localInterfaceAssemblers_[i], levelMode)); + } + + maxLevel = i; + } + } + + levelX_.resize(levelPatchPreconditioners_.size()+1); + levelRhs_.resize(levelPatchPreconditioners_.size()+1); + + allFaultBasis_ = std::make_shared<BasisType>(interfaceNetwork_.levelInterfaceNetwork(maxLevel)); + + // init multigrid transfer + for (size_t i=0; i<levelPatchPreconditioners_.size(); i++) { + mgTransfer_.push_back(std::make_shared<DGMGTransfer<BasisType>>(levelPatchPreconditioners_[i]->basis(), *allFaultBasis_)); + } + mgTransfer_.push_back(std::make_shared<DGMGTransfer<BasisType>>(coarseGlobalPreconditioner_->basis(), *allFaultBasis_)); + + itCounter_ = 0; + } + + + virtual void setProblem(const MatrixType& mat, VectorType& x, const VectorType& rhs) { + this->x_ = &x; + this->rhs_ = &rhs; + this->mat_ = Dune::stackobject_to_shared_ptr(mat); + + for (size_t i=0; i<levelPatchPreconditioners_.size(); i++) { + mgTransfer_[i]->restrict(x, levelX_[i]); + mgTransfer_[i]->restrict(rhs, levelRhs_[i]); + + levelPatchPreconditioners_[i]->setProblem(mat, levelX_[i], levelRhs_[i]); + } + + size_t j = levelPatchPreconditioners_.size(); + mgTransfer_[j]->restrict(x, levelX_[j]); + mgTransfer_[j]->restrict(rhs, levelRhs_[j]); + + coarseGlobalPreconditioner_->setProblem(mat, levelX_[j], levelRhs_[j]); + } + + + virtual void iterate() { + if (mode_ == additive) + iterateAdd(); + else + iterateMult(); + } + + void iterateAdd() { + *(this->x_) = 0; + + VectorType x; + + for (size_t i=0; i<levelPatchPreconditioners_.size(); i++) { + levelPatchPreconditioners_[i]->iterate(); + const VectorType& it = levelPatchPreconditioners_[i]->getSol(); + + mgTransfer_[i]->prolong(it, x); + + //writeToVTK(*allFaultBasis_, x, "/home/mi/podlesny/data/faultnetworks/sol/", "preconditioner_step_"+std::to_string(i)); + + *(this->x_) += x; + } + + coarseGlobalPreconditioner_->iterate(); + const VectorType& it = coarseGlobalPreconditioner_->getSol(); + + mgTransfer_[levelPatchPreconditioners_.size()]->prolong(it, x); + *(this->x_) += x; + + + /* + levelPatchPreconditioners_[itCounter_]->iterate(); + const VectorType& it = levelPatchPreconditioners_[itCounter_]->getSol(); + + mgTransfer_[itCounter_]->prolong(it, x); + + //writeToVTK(*allFaultBasis_, x, "/home/mi/podlesny/data/faultnetworks/sol/", "preconditioner_step_"+std::to_string(i)); + + *(this->x_) += x; + + coarseGlobalPreconditioner_->iterate(); + const VectorType& it2 = coarseGlobalPreconditioner_->getSol(); + + mgTransfer_[levelPatchPreconditioners_.size()]->prolong(it2, x); + *(this->x_) += x; + + itCounter_++; + itCounter_ = itCounter_ % (levelPatchPreconditioners_.size()); + + if (itCounter_==0) + std::cout << "Multilevel pass complete!" << std::endl; + + */ + } + + + void iterateMult() { + *(this->x_) = 0; + + VectorType x; + + for (int i=(levelPatchPreconditioners_.size()-1); i>=0; i--) { + VectorType updatedRhs(*(this->rhs_)); + this->mat_->mmv(*(this->x_), updatedRhs); + + //print(updatedRhs, "globalRhs: "); + + mgTransfer_[i]->restrict(*(this->x_), levelX_[i]); + mgTransfer_[i]->restrict(updatedRhs, levelRhs_[i]); + + //print(levelRhs_[i], "levelLocalCoarseRhs: "); + //writeToVTK(levelPatchPreconditioners_[i]->basis(), levelRhs_[i], "/storage/mi/podlesny/data/faultnetworks/rhs/fine", "exactvertexdata_step_"+std::to_string(itCounter_)); + + levelPatchPreconditioners_[i]->setProblem(*(this->mat_), levelX_[i], levelRhs_[i]); + + levelPatchPreconditioners_[i]->iterate(); + const VectorType& it = levelPatchPreconditioners_[i]->getSol(); + + mgTransfer_[i]->prolong(it, x); + + //writeToVTK(*allFaultBasis_, x, "/storage/mi/podlesny/data/faultnetworks/fineIterates/multilevel", "exactvertexdata_step_"+std::to_string(itCounter_)); + + + *(this->x_) += x; + } + + VectorType updatedCoarseRhs(*(this->rhs_)); + this->mat_->mmv(*(this->x_), updatedCoarseRhs); + + size_t j = levelPatchPreconditioners_.size(); + mgTransfer_[j]->restrict(*(this->x_), levelX_[j]); + mgTransfer_[j]->restrict(updatedCoarseRhs, levelRhs_[j]); + + //print(levelRhs_[j], "localCoarseRhs: "); + //writeToVTK(coarseGlobalPreconditioner_->basis(), levelRhs_[j], "/storage/mi/podlesny/data/faultnetworks/rhs/coarse", "exactvertexdata_step_"+std::to_string(itCounter_)); + + coarseGlobalPreconditioner_->setProblem(*(this->mat_), levelX_[j], levelRhs_[j]); + coarseGlobalPreconditioner_->iterate(); + const VectorType& it = coarseGlobalPreconditioner_->getSol(); + + mgTransfer_[j]->prolong(it, x); + + //writeToVTK(*allFaultBasis_, x, "/storage/mi/podlesny/data/faultnetworks/coarseIterates/multilevel", "exactvertexdata_step_"+std::to_string(itCounter_)); + + *(this->x_) += x; + + itCounter_++; + } + + void build() { + coarseGlobalPreconditioner_->build(); + + for (size_t i=0; i<levelPatchPreconditioners_.size(); i++) { + levelPatchPreconditioners_[i]->build(); + } + } + + std::shared_ptr<LevelPatchPreconditionerType> levelPatchPreconditioner(const int level) { + return levelPatchPreconditioners_[level]; + } + + const BasisType& basis() const { + return *allFaultBasis_; + } + + size_t size() const { + return levelPatchPreconditioners_.size()+1; + } +}; + +#endif + diff --git a/src/spatial-solving/tnnmg/supportpatchfactory.hh b/src/spatial-solving/tnnmg/supportpatchfactory.hh new file mode 100644 index 0000000000000000000000000000000000000000..20754c0d5c371b5d9a715778a2b9d7e87cace00d --- /dev/null +++ b/src/spatial-solving/tnnmg/supportpatchfactory.hh @@ -0,0 +1,253 @@ +#ifndef SUPPORT_PATCH_FACTORY_HH +#define SUPPORT_PATCH_FACTORY_HH + +#include<queue> + +#include <dune/common/bitsetvector.hh> +#include <dune/common/fvector.hh> + +#include <dune/fufem/referenceelementhelper.hh> +#include <dune/grid/common/mcmgmapper.hh> + +#include <dune/faultnetworks/hierarchicleveliterator.hh> + +template <class BasisType> +class SupportPatchFactory +{ + protected: + typedef typename BasisType::GridView GV; + typedef typename BasisType::LocalFiniteElement LFE; + + typedef typename GV::Grid GridType; + typedef typename GridType::ctype ctype; + static const int dim = GridType::dimension; + typedef typename GridType::template Codim<0>::Entity Element; + typedef typename GridType::template Codim<dim>::Entity Vertex; + + typedef HierarchicLevelIterator<GridType> HierarchicLevelIteratorType; + typedef typename Dune::LevelMultipleCodimMultipleGeomTypeMapper<GridType, Dune::MCMGElementLayout > ElementMapper; + + private: + const BasisType& coarseBasis_; + const BasisType& fineBasis_; + + const int coarseLevel_; + const int fineLevel_; + + const std::vector< std::vector <Element>>& vertexInElements_; + const int centerVertexIdx_; + const int patchDepth_; + + + const GridType& grid; + const GV& coarseGridView; + const GV& fineGridView; + + std::vector<int> localToGlobal; + Dune::BitSetVector<1> boundaryDofs; + std::vector<Element> fineRegionElements; + + ElementMapper coarseMapper; + + public: + //setup + SupportPatchFactory(const BasisType& coarseBasis, const BasisType& fineBasis, const int coarseLevel, const int fineLevel, const std::vector< std::vector <Element>>& vertexInElements, const int centerVertexIdx, const int patchDepth) : + coarseBasis_(coarseBasis), + fineBasis_(fineBasis), + coarseLevel_(coarseLevel), + fineLevel_(fineLevel), + vertexInElements_(vertexInElements), + centerVertexIdx_(centerVertexIdx), + patchDepth_(patchDepth), + grid(coarseBasis_.getGridView().grid()), + coarseGridView(coarseBasis_.getGridView()), + fineGridView(fineBasis_.getGridView()), + coarseMapper(grid, coarseLevel_) + { + fineRegionElements.resize(0); + + std::vector<Element> coarseElements; + Dune::BitSetVector<1> visited(coarseMapper.size()); + Dune::BitSetVector<1> vertexVisited(vertexInElements_.size()); + visited.unsetAll(); + vertexVisited.unsetAll(); + + std::set<int> localDofs; + std::set<int> localBoundaryDofs; + + addVertexSupport(centerVertexIdx_, coarseElements, visited, vertexVisited); + + // construct coarse patch + for (int depth=1; depth<patchDepth_; depth++) { + std::vector<Element> coarseElementNeighbors; + + for (size_t i=0; i<coarseElements.size(); ++i) { + const Element& elem = coarseElements[i]; + const LFE& coarseLFE = coarseBasis_.getLocalFiniteElement(elem); + + for (size_t j=0; j<coarseLFE.localBasis().size(); ++j) { + int dofIndex = coarseBasis_.indexInGridView(elem, j); + + if (!vertexVisited[dofIndex][0]) { + addVertexSupport(dofIndex, coarseElementNeighbors, visited, vertexVisited); + } + } + } + + coarseElements.insert(coarseElements.begin(), coarseElementNeighbors.begin(), coarseElementNeighbors.end()); + } + + + // construct fine patch + for (size_t i=0; i<coarseElements.size(); ++i) { + const Element& elem = coarseElements[i]; + addFinePatchElements(elem, visited, localDofs, localBoundaryDofs); + } + + + + localToGlobal.resize(localDofs.size()); + boundaryDofs.resize(localDofs.size()); + boundaryDofs.unsetAll(); + + std::set<int>::iterator dofIt = localDofs.begin(); + std::set<int>::iterator dofEndIt = localDofs.end(); + size_t i=0; + for (; dofIt != dofEndIt; ++dofIt) { + int localDof = *dofIt; + localToGlobal[i] = localDof; + + if (localBoundaryDofs.count(localDof)) { + boundaryDofs[i][0] = true; + } + i++; + } + } + + std::vector<int>& getLocalToGlobal() { + return localToGlobal; + } + + std::vector<Element>& getRegionElements() { + return fineRegionElements; + } + + Dune::BitSetVector<1>& getBoundaryDofs() { + return boundaryDofs; + } + + +private: + + + void print(const Dune::BitSetVector<1>& x, std::string message){ + std::cout << message << std::endl; + for (size_t i=0; i<x.size(); i++) { + std::cout << x[i][0] << " "; + } + std::cout << std::endl << std::endl; + } + + void addVertexSupport(const int vertexIdx, std::vector<Element>& coarseElements, Dune::BitSetVector<1>& visited, Dune::BitSetVector<1>& vertexVisited) { + const std::vector<Element>& vertexInElement = vertexInElements_[vertexIdx]; + + for (size_t i=0; i<vertexInElement.size(); i++) { + const Element& elem = vertexInElement[i]; + const int elemIdx = coarseMapper.index(elem); + + if (!visited[elemIdx][0]) { + coarseElements.push_back(elem); + visited[elemIdx][0] = true; + } + } + vertexVisited[vertexIdx][0] = true; + } + + bool containsInsideSubentity(const Element& elem, const typename GridType::LevelIntersection& intersection, int subEntity, int codim) { + return ReferenceElementHelper<double, dim>::subEntityContainsSubEntity(elem.type(), intersection.indexInInside(), 1, subEntity, codim); + } + + + void addFinePatchElements(const Element& coarseElem, const Dune::BitSetVector<1>& inCoarsePatch, std::set<int>& localDofs, std::set<int>& localBoundaryDofs) { + HierarchicLevelIteratorType endHierIt(grid, coarseElem, HierarchicLevelIteratorType::PositionFlag::end, fineLevel_); + for (HierarchicLevelIteratorType hierIt(grid, coarseElem, HierarchicLevelIteratorType::PositionFlag::begin, fineLevel_); hierIt!=endHierIt; ++hierIt) { + + const Element& fineElem = *hierIt; + fineRegionElements.push_back(fineElem); + + addLocalDofs(coarseElem, fineElem, inCoarsePatch, localDofs, localBoundaryDofs); + } + } + + void addLocalDofs(const Element& coarseElem, const Element& fineElem, const Dune::BitSetVector<1>& inCoarsePatch, std::set<int>& localDofs, std::set<int>& localBoundaryDofs) { + const LFE& fineLFE = fineBasis_.getLocalFiniteElement(fineElem); + + /* + const auto& fineGeometry = fineElem.geometry(); + const auto& coarseGeometry = coarseElem.geometry(); + + const auto& ref = Dune::ReferenceElements<ctype, dim>::general(fineElem.type()); */ + + // insert local dofs + for (size_t i=0; i<fineLFE.localBasis().size(); ++i) { + int dofIndex = fineBasis_.index(fineElem, i); + localDofs.insert(dofIndex); + } + + + // search for parts of the global and inner boundary + typename GridType::LevelIntersectionIterator neighborIt = fineGridView.ibegin(fineElem); + typename GridType::LevelIntersectionIterator neighborItEnd = fineGridView.iend(fineElem); + for (; neighborIt!=neighborItEnd; ++neighborIt) { + const typename GridType::LevelIntersection& intersection = *neighborIt; + + bool isInnerBoundary = false; + if (intersection.neighbor()) { + Element outsideFather = intersection.outside(); + + while (outsideFather.level()>coarseLevel_) { + outsideFather = outsideFather.father(); + } + + if (!inCoarsePatch[coarseMapper.index(outsideFather)][0]) { + isInnerBoundary = true; + } + } + + if (intersection.boundary() or isInnerBoundary) { + typedef typename LFE::Traits::LocalCoefficientsType LocalCoefficients; + const LocalCoefficients* localCoefficients = &fineBasis_.getLocalFiniteElement(intersection.inside()).localCoefficients(); + + for (size_t i=0; i<localCoefficients->size(); i++) { + unsigned int entity = localCoefficients->localKey(i).subEntity(); + unsigned int codim = localCoefficients->localKey(i).codim(); + + if (containsInsideSubentity(fineElem, intersection, entity, codim)) + localBoundaryDofs.insert(fineBasis_.index(intersection.inside(), i)); + } + } + } + + /* add interior coarse level vertices to boundary dofs + for(int i=0; i<coarseGeometry.corners(); ++i) { + const auto& local = fineGeometry.local(coarseGeometry.corner(i)); + + if (!ref.checkInside(local)) + continue; + + const int localBasisSize = fineLFE.localBasis().size(); + std::vector<Dune::FieldVector<double, 1>, std::allocator<Dune::FieldVector<double, 1> > > localBasisRep(localBasisSize); + fineLFE.localBasis().evaluateFunction(local, localBasisRep); + + for(int k=0; k<localBasisSize; ++k) { + if (localBasisRep[k]==1) { + int dofIndex = fineBasis_.index(fineElem, k); + localBoundaryDofs.insert(dofIndex); + break; + } + } + } */ + + } +}; +#endif diff --git a/src/spatial-solving/tnnmg/zerononlinearity.hh b/src/spatial-solving/tnnmg/zerononlinearity.hh new file mode 100644 index 0000000000000000000000000000000000000000..4885d72a9c70ebe7923ae6434934d1e3092a72c7 --- /dev/null +++ b/src/spatial-solving/tnnmg/zerononlinearity.hh @@ -0,0 +1,76 @@ +#ifndef DUNE_TECTONIC_ZERO_NONLINEARITY_HH +#define DUNE_TECTONIC_ZERO_NONLINEARITY_HH + +#include <dune/solvers/common/interval.hh> + +/** \file + * \brief A dummy nonlinearity class representing the zero function + */ + +class ZeroNonlinearity +{ +public: + ZeroNonlinearity() + {} + + const auto& restriction(size_t i) const { + return *this; + } + + /** \brief Returns zero */ + template <class VectorType> + double operator()(const VectorType& v) const + { + return 0.0; + } + + template <class VectorType> + void addGradient(const VectorType& v, VectorType& gradient) const {} + + template <class VectorType, class MatrixType> + void addHessian(const VectorType& v, MatrixType& hessian) const {} + + template <class IndexSet> + void addHessianIndices(IndexSet& indices) const {} + + /** \brief Returns the interval \f$ [0,0]\f$ */ + void subDiff(int i, double x, Dune::Solvers::Interval<double>& D, int j) const + { + D[0] = 0.0; + D[1] = 0.0; + } + + template <class VectorType> + void directionalSubDiff(const VectorType& u, const VectorType& v, Dune::Solvers::Interval<double>& subdifferential) const + { + subdifferential[0] = 0.0; + subdifferential[1] = 0.0; + } + + /** \brief Returns 0 */ + double regularity(int i, double x, int j) const + { + return 0.0; + } + + void domain(int i, Dune::Solvers::Interval<double>& dom, int j) const + { + dom[0] = -std::numeric_limits<double>::max(); + dom[1] = std::numeric_limits<double>::max(); + return; + } + + template <class VectorType> + void directionalDomain(const VectorType& u, const VectorType& v, Dune::Solvers::Interval<double>& dom) const + { + dom[0] = -std::numeric_limits<double>::max(); + dom[1] = std::numeric_limits<double>::max(); + return; + } + + template <class BitVector> + void setIgnore(const BitVector& ignore) {} +}; + +#endif + diff --git a/src/time-stepping/adaptivetimestepper.cc b/src/time-stepping/adaptivetimestepper.cc index cde9e81d81cb6d445e4acdc8aec166be90c56d45..d9618460fc4dd793e82fd4c08663eeb5b2ca480d 100644 --- a/src/time-stepping/adaptivetimestepper.cc +++ b/src/time-stepping/adaptivetimestepper.cc @@ -17,9 +17,10 @@ void IterationRegister::reset() { finalCount = FixedPointIterationCounter(); } -template <class Factory, class Updaters, class ErrorNorm> -AdaptiveTimeStepper<Factory, Updaters, ErrorNorm>::AdaptiveTimeStepper( - Factory &factory, Dune::ParameterTree const &parset, +template <class Factory, class NBodyAssembler, class Updaters, class ErrorNorm> +AdaptiveTimeStepper<Factory, NBodyAssembler, Updaters, ErrorNorm>::AdaptiveTimeStepper( + Dune::ParameterTree const &parset, + NBodyAssembler nBodyAssembler, GlobalFrictionContainer& globalFriction, Updaters ¤t, double relativeTime, double relativeTau, ExternalForces& externalForces, @@ -28,8 +29,8 @@ AdaptiveTimeStepper<Factory, Updaters, ErrorNorm>::AdaptiveTimeStepper( : relativeTime_(relativeTime), relativeTau_(relativeTau), finalTime_(parset.get<double>("problem.finalTime")), - factory_(factory), parset_(parset), + nBodyAssembler_(nBodyAssembler), globalFriction_(globalFriction), current_(current), R1_(), @@ -37,13 +38,13 @@ AdaptiveTimeStepper<Factory, Updaters, ErrorNorm>::AdaptiveTimeStepper( mustRefine_(mustRefine), errorNorms_(errorNorms) {} -template <class Factory, class Updaters, class ErrorNorm> -bool AdaptiveTimeStepper<Factory, Updaters, ErrorNorm>::reachedEnd() { +template <class Factory, class NBodyAssembler, class Updaters, class ErrorNorm> +bool AdaptiveTimeStepper<Factory, NBodyAssembler, Updaters, ErrorNorm>::reachedEnd() { return relativeTime_ >= 1.0; } -template <class Factory, class Updaters, class ErrorNorm> -IterationRegister AdaptiveTimeStepper<Factory, Updaters, ErrorNorm>::advance() { +template <class Factory, class NBodyAssembler, class Updaters, class ErrorNorm> +IterationRegister AdaptiveTimeStepper<Factory, NBodyAssembler, Updaters, ErrorNorm>::advance() { /* | C | We check here if making the step R1 of size tau is a | R1 | R2 | good idea. To check if we can coarsen, we compare @@ -93,13 +94,13 @@ IterationRegister AdaptiveTimeStepper<Factory, Updaters, ErrorNorm>::advance() { return iterationRegister_; } -template <class Factory, class Updaters, class ErrorNorm> -typename AdaptiveTimeStepper<Factory, Updaters, ErrorNorm>::UpdatersWithCount -AdaptiveTimeStepper<Factory, Updaters, ErrorNorm>::step( +template <class Factory, class NBodyAssembler, class Updaters, class ErrorNorm> +typename AdaptiveTimeStepper<Factory, NBodyAssembler, Updaters, ErrorNorm>::UpdatersWithCount +AdaptiveTimeStepper<Factory, NBodyAssembler, Updaters, ErrorNorm>::step( Updaters const &oldUpdaters, double rTime, double rTau) { UpdatersWithCount newUpdatersAndCount = {oldUpdaters.clone(), {}}; newUpdatersAndCount.count = - MyCoupledTimeStepper(finalTime_, factory_, parset_, globalFriction_, + MyCoupledTimeStepper(finalTime_, parset_, nBodyAssembler_, globalFriction_, newUpdatersAndCount.updaters, errorNorms_, externalForces_) .step(rTime, rTau); diff --git a/src/time-stepping/adaptivetimestepper.hh b/src/time-stepping/adaptivetimestepper.hh index 7b251fade0bb1709a209bacae861c696593a6050..6e70c1692a6380905a78f102d55f2f7dfd0efacc 100644 --- a/src/time-stepping/adaptivetimestepper.hh +++ b/src/time-stepping/adaptivetimestepper.hh @@ -15,7 +15,7 @@ struct IterationRegister { FixedPointIterationCounter finalCount; }; -template <class Factory, class Updaters, class ErrorNorm> +template <class Factory, class NBodyAssembler, class Updaters, class ErrorNorm> class AdaptiveTimeStepper { struct UpdatersWithCount { Updaters updaters; @@ -26,13 +26,15 @@ class AdaptiveTimeStepper { //using ConvexProblem = typename Factory::ConvexProblem; //using Nonlinearity = typename Factory::Nonlinearity; - using MyCoupledTimeStepper = CoupledTimeStepper<Factory, Updaters, ErrorNorm>; + using MyCoupledTimeStepper = CoupledTimeStepper<Factory, NBodyAssembler, Updaters, ErrorNorm>; using GlobalFrictionContainer = typename MyCoupledTimeStepper::GlobalFrictionContainer; using ExternalForces = typename MyCoupledTimeStepper::ExternalForces; public: - AdaptiveTimeStepper(Factory &factory, Dune::ParameterTree const &parset, + AdaptiveTimeStepper( + Dune::ParameterTree const &parset, + NBodyAssembler& nBodyAssembler, GlobalFrictionContainer& globalFriction, Updaters ¤t, double relativeTime, double relativeTau, @@ -51,8 +53,8 @@ class AdaptiveTimeStepper { double rTau); double finalTime_; - Factory &factory_; Dune::ParameterTree const &parset_; + NBodyAssembler& nBodyAssembler_; GlobalFrictionContainer& globalFriction_; Updaters ¤t_; UpdatersWithCount R1_; diff --git a/src/time-stepping/adaptivetimestepper_tmpl.cc b/src/time-stepping/adaptivetimestepper_tmpl.cc index 4f11f38799fb9caa92e811342a2ac15da900a5e5..a390e8244d4a45ac8f887bd0ecdfd0598e531324 100644 --- a/src/time-stepping/adaptivetimestepper_tmpl.cc +++ b/src/time-stepping/adaptivetimestepper_tmpl.cc @@ -11,7 +11,6 @@ #include <dune/tnnmg/problem-classes/convexproblem.hh> #include <dune/tectonic/globalfriction.hh> -#include <dune/tectonic/myblockproblem.hh> #include "../data-structures/levelcontactnetwork.hh" #include "../spatial-solving/solverfactory.hh" @@ -19,8 +18,9 @@ #include "state/stateupdater.hh" #include "updaters.hh" -using BoundaryNodes = typename LevelContactNetwork<Grid, MY_DIM>::LevelBoundaryNodes; -using BoundaryFunctions = typename LevelContactNetwork<Grid, MY_DIM>::LevelBoundaryFunctions; +/* +using BoundaryNodes = typename LevelContactNetwork<Grid, MY_DIM>::BoundaryNodes; +using BoundaryFunctions = typename LevelContactNetwork<Grid, MY_DIM>::BoundaryFunctions; using Factory = SolverFactory<DeformedGrid, GlobalFriction<Matrix, Vector>, Matrix, Vector>; using MyStateUpdater = StateUpdater<ScalarVector, Vector>; @@ -30,3 +30,4 @@ using MyUpdaters = Updaters<MyRateUpdater, MyStateUpdater>; using ErrorNorm = EnergyNorm<ScalarMatrix, ScalarVector>; template class AdaptiveTimeStepper<Factory, MyUpdaters, ErrorNorm>; +*/ diff --git a/src/time-stepping/coupledtimestepper.cc b/src/time-stepping/coupledtimestepper.cc index e06ce73233e419f737b8455c354b3fe3ad5e0c61..b948957208f231eb8f0bc8e9eabb4d9ee68b8b95 100644 --- a/src/time-stepping/coupledtimestepper.cc +++ b/src/time-stepping/coupledtimestepper.cc @@ -4,23 +4,24 @@ #include "coupledtimestepper.hh" -template <class Factory, class Updaters, class ErrorNorm> -CoupledTimeStepper<Factory, Updaters, ErrorNorm>::CoupledTimeStepper( - double finalTime, Factory &factory, Dune::ParameterTree const &parset, +template <class Factory, class NBodyAssembler, class Updaters, class ErrorNorm> +CoupledTimeStepper<Factory, NBodyAssembler, Updaters, ErrorNorm>::CoupledTimeStepper( + double finalTime, Dune::ParameterTree const &parset, + NBodyAssembler& nBodyAssembler, GlobalFrictionContainer& globalFriction, Updaters updaters, const std::vector<const ErrorNorm* >& errorNorms, ExternalForces& externalForces) : finalTime_(finalTime), - factory_(factory), parset_(parset), + nBodyAssembler_(nBodyAssembler), globalFriction_(globalFriction), updaters_(updaters), externalForces_(externalForces), errorNorms_(errorNorms) {} -template <class Factory, class Updaters, class ErrorNorm> +template <class Factory, class NBodyAssembler, class Updaters, class ErrorNorm> FixedPointIterationCounter -CoupledTimeStepper<Factory, Updaters, ErrorNorm>::step(double relativeTime, +CoupledTimeStepper<Factory, NBodyAssembler, Updaters, ErrorNorm>::step(double relativeTime, double relativeTau) { updaters_.state_->nextTimeStep(); updaters_.rate_->nextTimeStep(); @@ -39,8 +40,8 @@ CoupledTimeStepper<Factory, Updaters, ErrorNorm>::step(double relativeTime, updaters_.state_->setup(tau); updaters_.rate_->setup(ell, tau, newRelativeTime, velocityRHS, velocityIterate, velocityMatrix); - FixedPointIterator<Factory, Updaters, ErrorNorm> fixedPointIterator( - factory_, parset_, globalFriction_, errorNorms_); + FixedPointIterator<Factory, NBodyAssembler, Updaters, ErrorNorm> fixedPointIterator( + parset_, nBodyAssembler_, globalFriction_, errorNorms_); auto const iterations = fixedPointIterator.run(updaters_, velocityMatrix, velocityRHS, velocityIterate); return iterations; diff --git a/src/time-stepping/coupledtimestepper.hh b/src/time-stepping/coupledtimestepper.hh index 81a53c6fd5bd286dee6951a4eb6a64fbae9fb923..9d129d2d38aad716c8d47be6c0f7a12a94eada76 100644 --- a/src/time-stepping/coupledtimestepper.hh +++ b/src/time-stepping/coupledtimestepper.hh @@ -8,18 +8,19 @@ #include "../spatial-solving/fixedpointiterator.hh" -template <class Factory, class Updaters, class ErrorNorm> +template <class Factory, class NBodyAssembler, class Updaters, class ErrorNorm> class CoupledTimeStepper { using Vector = typename Factory::Vector; using Matrix = typename Factory::Matrix; //using Nonlinearity = typename Factory::Nonlinearity; public: - using GlobalFrictionContainer = typename FixedPointIterator<Factory, Updaters, ErrorNorm>::GlobalFrictionContainer; + using GlobalFrictionContainer = typename FixedPointIterator<Factory, NBodyAssembler, Updaters, ErrorNorm>::GlobalFrictionContainer; using ExternalForces = std::vector<const std::function<void(double, Vector &)>*>; public: - CoupledTimeStepper(double finalTime, Factory &factory, + CoupledTimeStepper(double finalTime, Dune::ParameterTree const &parset, + NBodyAssembler& nBodyAssembler, GlobalFrictionContainer& globalFriction, Updaters updaters, const std::vector<const ErrorNorm* >& errorNorms, ExternalForces& externalForces); @@ -28,8 +29,8 @@ class CoupledTimeStepper { private: double finalTime_; - Factory &factory_; Dune::ParameterTree const &parset_; + NBodyAssembler& nBodyAssembler_; GlobalFrictionContainer& globalFriction_; Updaters updaters_; ExternalForces& externalForces_; diff --git a/src/time-stepping/coupledtimestepper_tmpl.cc b/src/time-stepping/coupledtimestepper_tmpl.cc index e16e9df9c948a02153eb818a75334410cd1fd88b..d5f6d1d14d9d597ad84f283b96d503371ebecf1a 100644 --- a/src/time-stepping/coupledtimestepper_tmpl.cc +++ b/src/time-stepping/coupledtimestepper_tmpl.cc @@ -11,7 +11,6 @@ #include <dune/tnnmg/problem-classes/convexproblem.hh> #include <dune/tectonic/globalfriction.hh> -#include <dune/tectonic/myblockproblem.hh> #include "../data-structures/levelcontactnetwork.hh" #include "../spatial-solving/solverfactory.hh" @@ -19,8 +18,9 @@ #include "state/stateupdater.hh" #include "updaters.hh" -using BoundaryNodes = typename LevelContactNetwork<Grid, MY_DIM>::LevelBoundaryNodes; -using BoundaryFunctions = typename LevelContactNetwork<Grid, MY_DIM>::LevelBoundaryFunctions; +/* +using BoundaryNodes = typename LevelContactNetwork<Grid, MY_DIM>::BoundaryNodes; +using BoundaryFunctions = typename LevelContactNetwork<Grid, MY_DIM>::BoundaryFunctions; using Factory = SolverFactory<DeformedGrid, GlobalFriction<Matrix, Vector>, Matrix, Vector>; @@ -31,3 +31,4 @@ using MyUpdaters = Updaters<MyRateUpdater, MyStateUpdater>; using ErrorNorm = EnergyNorm<ScalarMatrix, ScalarVector>; template class CoupledTimeStepper<Factory, MyUpdaters, ErrorNorm>; +*/ diff --git a/src/time-stepping/rate/newmark.cc b/src/time-stepping/rate/newmark.cc index 2961e7e8885a92681c35fe0b8f48aa7d76d2cee4..4e61938bc64482db31a5f5abc54f94a6773be134 100644 --- a/src/time-stepping/rate/newmark.cc +++ b/src/time-stepping/rate/newmark.cc @@ -21,7 +21,13 @@ void Newmark<Vector, Matrix, BoundaryFunctions, BoundaryNodes>::setup( std::vector<Vector>& rhs, std::vector<Vector>& iterate, std::vector<Matrix>& AM) { - for (size_t i=0; i<this->u.size(); i++) { + const size_t bodyCount = this->u.size(); + + rhs.resize(bodyCount); + iterate.resize(bodyCount); + AM.resize(bodyCount); + + for (size_t i=0; i<bodyCount; i++) { this->tau = _tau; /* We start out with the formulation @@ -77,7 +83,7 @@ void Newmark<Vector, Matrix, BoundaryFunctions, BoundaryNodes>::setup( iterate = this->v_o; - for (size_t i=0; i<iterate.size(); i++) { + for (size_t i=0; i<bodyCount; i++) { auto& bodyIterate = iterate[i]; const auto& bodyDirichletNodes = this->dirichletNodes[i]; @@ -92,7 +98,7 @@ void Newmark<Vector, Matrix, BoundaryFunctions, BoundaryNodes>::setup( for (size_t k=0; k<bcDirichletNodes.size() ; ++k) { for (size_t j=0; j<dim; ++j) { if (bcDirichletNodes[k][j]) { - iterate[k][j] = dirichletValue; + bodyIterate[k][j] = dirichletValue; } } } diff --git a/src/time-stepping/rate/rateupdater_tmpl.cc b/src/time-stepping/rate/rateupdater_tmpl.cc index 273c261198849795ad1fd0d9f39b316b80f256b2..aa8a7168591684a2aecd6d3fc81b974514e645e0 100644 --- a/src/time-stepping/rate/rateupdater_tmpl.cc +++ b/src/time-stepping/rate/rateupdater_tmpl.cc @@ -7,8 +7,8 @@ #include "../../data-structures/levelcontactnetwork.hh" -using BoundaryNodes = typename LevelContactNetwork<Grid, MY_DIM>::LevelBoundaryNodes; -using BoundaryFunctions = typename LevelContactNetwork<Grid, MY_DIM>::LevelBoundaryFunctions; +using BoundaryNodes = typename LevelContactNetwork<Grid, MY_DIM>::BoundaryNodes; +using BoundaryFunctions = typename LevelContactNetwork<Grid, MY_DIM>::BoundaryFunctions; template class RateUpdater<Vector, Matrix, BoundaryFunctions, BoundaryNodes>; template class Newmark<Vector, Matrix, BoundaryFunctions, BoundaryNodes>; diff --git a/src/time-stepping/rate_tmpl.cc b/src/time-stepping/rate_tmpl.cc index 0d1271ed0e11cf146900a568c435c6716ce521da..9627a8ce754aa52a9530ee61641b14a950b624e1 100644 --- a/src/time-stepping/rate_tmpl.cc +++ b/src/time-stepping/rate_tmpl.cc @@ -1,8 +1,8 @@ #include "../data-structures/levelcontactnetwork_tmpl.cc" #include "../explicitvectors.hh" -using BoundaryFunctions = typename LevelContactNetwork<Grid, MY_DIM>::LevelBoundaryFunctions; -using BoundaryNodes = typename LevelContactNetwork<Grid, MY_DIM>::LevelBoundaryNodes; +using BoundaryFunctions = typename LevelContactNetwork<Grid, MY_DIM>::BoundaryFunctions; +using BoundaryNodes = typename LevelContactNetwork<Grid, MY_DIM>::BoundaryNodes; template auto initRateUpdater<Vector, Matrix, BoundaryFunctions, BoundaryNodes>( diff --git a/src/time-stepping/state_tmpl.cc b/src/time-stepping/state_tmpl.cc index 5046cf258356874450b8fb4ad5de5d58ed162795..42fa0b333c77d85d96396c4f86ad81d0f1eb4a9d 100644 --- a/src/time-stepping/state_tmpl.cc +++ b/src/time-stepping/state_tmpl.cc @@ -7,7 +7,7 @@ #include "../data-structures/levelcontactnetwork.hh" -using BoundaryPatchNodes = typename LevelContactNetwork<Grid, MY_DIM>::LevelBoundaryPatchNodes; +using BoundaryPatchNodes = typename LevelContactNetwork<Grid, MY_DIM>::BoundaryPatchNodes; template auto initStateUpdater<ScalarVector, Vector, BoundaryPatchNodes>( diff --git a/src/utils/debugutils.hh b/src/utils/debugutils.hh index 4671ff68de50d8c51cf674d89f968e9097548f56..150aad1cf2cf0b99175678de146e437dc7abd4f7 100644 --- a/src/utils/debugutils.hh +++ b/src/utils/debugutils.hh @@ -29,25 +29,29 @@ using namespace std; template <int dim, typename ctype=double> void print(const Dune::FieldVector<ctype, dim>& x, std::string message){ - std::cout << message << std::endl; + if (message != "") + std::cout << message << std::endl; + for (size_t i=0; i<x.size(); i++) { - std::cout << x[i] << " "; + std::cout << x[i] << ";" << std::endl;; } - std::cout << std::endl; + } template <int dim, typename ctype=double> void print(const Dune::BlockVector<Dune::FieldVector<ctype, dim>>& x, std::string message){ std::cout << message << " " << "size " << x.size() << std::endl; for (size_t i=0; i<x.size(); i++) { - print(x[i], "block " + std::to_string(i) + ":"); + print(x[i], ""); } std::cout << std::endl << std::endl; } template <int dim, typename ctype=double> - void print(const Dune::FieldMatrix<ctype, dim, dim>& mat, std::string message){ - std::cout << message << std::endl; + void print(const Dune::FieldMatrix<ctype, dim, dim>& mat, std::string message, bool endOfLine = true){ + if (message != "") + std::cout << message << std::endl; + for (size_t i=0; i<mat.N(); i++) { for (size_t j=0; j<mat.M(); j++) { if (mat.exists(i,j)) @@ -55,20 +59,44 @@ using namespace std; else std::cout << "0 "; } - std::cout << std::endl; + + if (endOfLine) + std::cout << ";"<< std::endl; } - std::cout << std::endl; } - template <int dim, typename ctype=double> - void print(const Dune::BCRSMatrix<Dune::FieldMatrix<ctype, dim, dim>>& mat, std::string message){ - std::cout << message << " " << "size (" << mat.N() << ", " << mat.M() << ")" <<std::endl; - for (size_t i=0; i<mat.N(); i++) { - for (size_t j=0; j<mat.M(); j++) { - if (mat.exists(i,j)) - print(mat[i][j], "block (" + std::to_string(i) + ", " + std::to_string(j) + "):"); - } - std::cout << std::endl; + template <int dim, typename ctype=double> + void print(const Dune::FieldMatrix<ctype, dim, dim>& mat, std::string message, const size_t line, bool endOfLine = true){ + if (message != "") + std::cout << message << std::endl; + + assert(line<mat.N()); + for (size_t j=0; j<mat.M(); j++) { + if (mat.exists(line,j)) + std::cout << mat[line][j] << " "; + else + std::cout << "0 "; + } + + if (endOfLine) + std::cout << ";"<< std::endl; + } + + template <int dim, typename ctype=double> + void print(const Dune::BCRSMatrix<Dune::FieldMatrix<ctype, dim, dim>>& mat, std::string message){ + std::cout << message << " " << "size (" << mat.N() << ", " << mat.M() << ")" <<std::endl; + + Dune::FieldMatrix<ctype, dim, dim> zeroEntry = 0; + + for (size_t i=0; i<mat.N(); i++) { + for (size_t d=0; d<dim; d++) { + for (size_t j=0; j<mat.M(); j++) { + if (mat.exists(i,j)) + print(mat[i][j], "", d, j==mat.M()-1); + else + print(zeroEntry, "", d, j==mat.M()-1); + } + } } std::cout << std::endl; }