#pragma once #include #include #include #include #include #include #include #include #include #include #include #include #include #include //#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include namespace AMDiS { // forward declaration template class ProblemInstat; template class ProblemStat : public ProblemStatBase , public StandardProblemIteration { using Self = ProblemStat; friend class ProblemInstat; public: // typedefs and static constants using GlobalBasis = typename Traits::GlobalBasis; using GridView = typename GlobalBasis::GridView; using Grid = typename GridView::Grid; using Element = typename GridView::template Codim<0>::Entity; using WorldVector = typename Element::Geometry::GlobalCoordinate; /// Dimension of the grid static constexpr int dim = Grid::dimension; /// Dimension of the world static constexpr int dow = Grid::dimensionworld; using SystemMatrix = DOFMatrix; using SystemVector = DOFVector; using LinearSolverType = LinearSolverInterface; public: /** * \brief Constructor. Takes the name of the problem that is used to * access values corresponding to this problem in the parameter file. **/ explicit ProblemStat(std::string const& name) : StandardProblemIteration(dynamic_cast(*this)) , name_(name) {} /// Constructor taking additionally a reference to a grid that is used /// instead of the default created grid, \ref ProblemStat ProblemStat(std::string const& name, Grid& grid) : ProblemStat(name) { adoptGrid(Dune::stackobject_to_shared_ptr(grid)); } /// \brief Constructor taking a grid reference and a basis reference. /// Stores pointers to both. ProblemStat(std::string const& name, Grid& grid, GlobalBasis& globalBasis) : ProblemStat(name, grid) { adoptGlobalBasis(Dune::stackobject_to_shared_ptr(globalBasis)); } /** * \brief Initialisation of the problem. * * Parameters read in initialize() for problem with name 'PROB' * MESH[0]->global refinements: nr of initial global refinements **/ void initialize(Flag initFlag, Self* adoptProblem = nullptr, Flag adoptFlag = INIT_NOTHING); /// Add an operator to \ref A. /** @{ */ /// Operator evaluated on the whole element /** * Adds an operator to the list of element operators to be assembled in * quadrature points inside the element. * * \param op A (pre-) local operator, \see LocalOperator, \see GridFunctionOperator * \param row TreePath identifying the sub-basis in the global basis tree * corresponding to the row basis. \see treepath() * \param col TreePath identifying the sub-basis in the global basis tree * corresponding to the column basis. \see treepath() * * Example: * ``` * auto op = makeOperator(tag::test_trial{}, 1.0/tau); * prob.addMatrixOperator(op, _0, _0); * ``` **/ template void addMatrixOperator(Operator const& op, RowTreePath row = {}, ColTreePath col = {}) { systemMatrix_->addOperator(tag::element_operator{}, op, row, col); } /// Operator evaluated on the boundary of the domain with boundary index `b` /** * Adds an operator to the list of boundary operators to be assembled in * quadrature points on the boundary intersections. * * \param b Boundary indentifier where to assemble this operator. Can be * constructed from an integer. \see BoundaryType * \param op A (pre-) local operator, \see LocalOperator, \see GridFunctionOperator * \param row TreePath identifying the sub-basis in the global basis tree * corresponding to the row basis. \see treepath() * \param col TreePath identifying the sub-basis in the global basis tree * corresponding to the column basis. \see treepath() * * Example: * ``` * auto op = makeOperator(tag::test_trial{}, alpha); * prob.addMatrixOperator(BoundaryType{1}, op, _0, _0); * ``` **/ template void addMatrixOperator(BoundaryType b, Operator const& op, RowTreePath row = {}, ColTreePath col = {}) { using I = typename GridView::Intersection; systemMatrix_->addOperator(tag::boundary_operator{b}, op, row, col); } /** @} */ /// Add an operator to \ref rhs. /** @{ */ /// Operator evaluated on the whole element /** * Adds an operator to the list of element operators to be assembled in * quadrature points inside the element. * * \param op A (pre-) local operator, \see LocalOperator, \see GridFunctionOperator * \param path TreePath identifying the sub-basis in the global basis tree * corresponding to the row basis. \see treepath() * * Example: * ``` * auto op = makeOperator(tag::test{}, probInstat.getOldSolution(0) / tau); * prob.addVectorOperator(op, _0); * ``` **/ template void addVectorOperator(Operator const& op, TreePath path = {}) { rhs_->addOperator(tag::element_operator{}, op, path); } /// Operator evaluated on the boundary of the domain with boundary index `b` /** * Adds an operator to the list of boundary operators to be assembled in * quadrature points on the boundary intersections. * * \param b Boundary indentifier where to assemble this operator. Can be * constructed from an integer. \see BoundaryType * \param op A (pre-) local operator, \see LocalOperator, \see GridFunctionOperator * \param path TreePath identifying the sub-basis in the global basis tree * corresponding to the row basis. \see treepath() * * Example: * ``` * auto op = makeOperator(tag::test{}, [g](auto const& x) { return g(x); }); * prob.addVectorOperator(BoundaryType{1}, op, _0); * ``` **/ template void addVectorOperator(BoundaryType b, Operator const& op, TreePath path = {}) { using I = typename GridView::Intersection; rhs_->addOperator(tag::boundary_operator{b}, op, path); } /** @} */ /// Add boundary conditions to the system /** @{ */ /// Dirichlet boundary condition /** * Enforce Dirichlet boundary values for the solution vector on boundary * regions identified by the predicate. * * \param predicate Functor `bool(WorldVector)` returning true for all * DOFs on the boundary that should be assigned a value. * \param row TreePath identifying the sub-basis in the global basis tree * corresponding to the row basis. \see treepath() * \param col TreePath identifying the sub-basis in the global basis tree * corresponding to the column basis. \see treepath() * \param values Functor `Range(WorldVector)` or any \ref GridFunction * that is evaluated in the DOFs identified by the predicate. * * Example: * ``` * prob.addDirichletBC([](auto const& x) { return x[0] < 1.e-8; }, 0, 0, * [](auto const& x) { return 0.0; }); * ``` **/ template void addDirichletBC(Predicate const& predicate, RowTreePath row, ColTreePath col, Values const& values); /** @} */ public: /// Implementation of \ref ProblemStatBase::solve virtual void solve(AdaptInfo& adaptInfo, bool createMatrixData = true, bool storeMatrixData = false) override; /// Implementation of \ref ProblemStatBase::buildAfterCoarse virtual void buildAfterAdapt(AdaptInfo& adaptInfo, Flag flag, bool asmMatrix = true, bool asmVector = true) override; /// \brief Assemble the linear system by calling \ref buildAfterAdapt with /// `asmMatrix` and `asmVector` set to true. void assemble(AdaptInfo& adaptInfo) { buildAfterAdapt(adaptInfo, Flag{0}, true, true); } /// Writes output files. void writeFiles(AdaptInfo& adaptInfo, bool force = false); public: // get-methods /// Implementation of \ref ProblemStatBase::name virtual std::string const& name() const override { return name_; } /// Return a reference to the grid, \ref grid Grid& grid() { return *grid_; } Grid const& grid() const { return *grid_; } /// Return the gridView of the leaf-level GridView const& gridView() const { return globalBasis_->gridView(); } /// Return the \ref globalBasis_ GlobalBasis& globalBasis() { return *globalBasis_; } GlobalBasis const& globalBasis() const { return *globalBasis_; } /// Return a reference to the linear solver, \ref linearSolver LinearSolverType& solver() { return *linearSolver_; } LinearSolverType const& solver() const { return *linearSolver_; } /// Returns a reference to system-matrix, \ref systemMatrix_ SystemMatrix& systemMatrix() { return *systemMatrix_; } SystemMatrix const& systemMatrix() const { return *systemMatrix_; } /// Returns a reference to the solution vector, \ref solution_ SystemVector& solutionVector() { return *solution_; } SystemVector const& solutionVector() const { return *solution_; } /// Return a reference to the rhs system-vector, \ref rhs SystemVector& rhsVector() { return *rhs_; } SystemVector const& rhsVector() const { return *rhs_; } /// Return a mutable view to a solution component template auto solution(TreePath path = {}) { auto&& tp = makeTreePath(path); return makeDOFVectorView(*solution_, tp); } /// Return a const view to a solution component template auto solution(TreePath path = {}) const { auto&& tp = makeTreePath(path); return makeDiscreteFunction(*solution_, tp); } public: // set-methods /// Set a new linear solver for the problem void setSolver(std::shared_ptr const& solver) { linearSolver_ = solver; } void setSolver(LinearSolverType& solver) { setSolver(Dune::stackobject_to_shared_ptr(solver)); } /// Set the grid. Stores pointer and initializes feSpaces /// matrices and vectors, as well as markers and file-writers. void setGrid(std::shared_ptr const& grid) { adoptGrid(grid); createGlobalBasis(); createMatricesAndVectors(); createMarker(); createFileWriter(); } void setGrid(Grid& grid) { setGrid(Dune::stackobject_to_shared_ptr(grid)); } void addMarker(std::shared_ptr> const& marker) { marker_.push_back(marker); if (marker_.size() > 1) marker_.back()->setMaximumMarking(true); } void addMarker(Marker& marker) { addMarker(Dune::stackobject_to_shared_ptr(marker)); } protected: // initialization methods void createGlobalBasis(); void createGrid(); void createMatricesAndVectors(); void createSolver(); void createMarker(); void createFileWriter(); void adoptGlobalBasis(std::shared_ptr const& globalBasis) { globalBasis_ = globalBasis; initGlobalBasis(*globalBasis_); } void adoptGrid(std::shared_ptr const& grid) { grid_ = grid; Parameters::get(name_ + "->mesh", gridName_); } private: void createGlobalBasisImpl(std::true_type); void createGlobalBasisImpl(std::false_type); void initGlobalBasis(GlobalBasis const& globalBasis); public: // implementation of iteration interface methods /// Implementation of \ref StandardProblemIteration::oneIteration. virtual Flag oneIteration(AdaptInfo& adaptInfo, Flag toDo = FULL_ITERATION) override { return StandardProblemIteration::oneIteration(adaptInfo, toDo); } /// Implementation of \ref ProblemStatBase::estimate. virtual void estimate(AdaptInfo& adaptInfo) override { /* do nothing. */ } /// Implementation of \ref ProblemStatBase::refineMesh. virtual Flag adaptGrid(AdaptInfo& adaptInfo) override; /// Implementation of \ref ProblemStatBase::markElements. virtual Flag markElements(AdaptInfo& adaptInfo) override; private: /// Name of this problem. std::string name_; /// Grid of this problem. std::shared_ptr grid_; /// Name of the grid std::string gridName_ = "mesh"; /// FE spaces of this problem. std::shared_ptr globalBasis_; /// A FileWriter object std::list> filewriter_; /// Pointer to the adaptation markers std::list>> marker_; /// Pointer to the estimators for this problem // std::vector estimator; /// An object of the linearSolver Interface std::shared_ptr linearSolver_; /// Matrix that is filled during assembling std::shared_ptr systemMatrix_; /// Vector with the solution components std::shared_ptr solution_; /// Vector (load-vector) corresponding to the right-hand side /// of the equation, filled during assembling std::shared_ptr rhs_; /// A vector with the local element error estimates /// for each node in the basis tree, indexed by [to_string(treePath)][element index] std::map> estimates_; private: // some internal data-structures Constraints constraints_; }; #if DUNE_HAVE_CXX_CLASS_TEMPLATE_ARGUMENT_DEDUCTION // Deduction rule template ProblemStat(std::string const& name, Grid& grid, GlobalBasis& globalBasis) -> ProblemStat>; #endif // Generator for ProblemStat with given Grid and GlobalBasis template ProblemStat> makeProblemStat(std::string const& name, Grid& grid, GlobalBasis& globalBasis) { return {name, grid, globalBasis}; } } // end namespace AMDiS #include "ProblemStat.inc.hpp"