#pragma once #include #include #include #include #include #include #include #include #include #include #include namespace AMDiS { template void ProblemStat::initialize( Flag initFlag, Self* adoptProblem, Flag adoptFlag) { // create grides if (grid) { warning("grid already created"); } else { if (initFlag.isSet(CREATE_MESH) || (!adoptFlag.isSet(INIT_MESH) && (initFlag.isSet(INIT_SYSTEM) || initFlag.isSet(INIT_FE_SPACE)))) { createGrid(); } if (adoptProblem && (adoptFlag.isSet(INIT_MESH) || adoptFlag.isSet(INIT_SYSTEM) || adoptFlag.isSet(INIT_FE_SPACE))) { grid = adoptProblem->getGrid(); } componentGrids.resize(nComponents, grid.get()); } if (!grid) warning("no grid created"); int globalRefinements = 0; Parameters::get(gridName + "->global refinements", globalRefinements); if (globalRefinements > 0) { grid->globalRefine(globalRefinements); } // create fespace if (globalBasis) { warning("globalBasis already created"); } else { if (initFlag.isSet(INIT_FE_SPACE) || (initFlag.isSet(INIT_SYSTEM) && !adoptFlag.isSet(INIT_FE_SPACE))) { createGlobalBasis(); } if (adoptProblem && (adoptFlag.isSet(INIT_FE_SPACE) || adoptFlag.isSet(INIT_SYSTEM))) { globalBasis = adoptProblem->getGlobalBasis(); } } if (!globalBasis) warning("no globalBasis created\n"); // create system if (initFlag.isSet(INIT_SYSTEM)) createMatricesAndVectors(); if (adoptProblem && adoptFlag.isSet(INIT_SYSTEM)) { solution = adoptProblem->getSolution(); rhs = adoptProblem->getRhs(); systemMatrix = adoptProblem->getSystemMatrix(); } // create solver if (linearSolver) { warning("solver already created\n"); } else { if (initFlag.isSet(INIT_SOLVER)) createSolver(); if (adoptProblem && adoptFlag.isSet(INIT_SOLVER)) { test_exit(!linearSolver, "solver already created\n"); linearSolver = adoptProblem->getSolver(); } } if (!linearSolver) { warning("no solver created\n"); } // create file writer if (initFlag.isSet(INIT_FILEWRITER)) createFileWriter(); solution->compress(); } template void ProblemStat::createFileWriter() { auto localView = globalBasis->localView(); forEachNode(localView.tree(), [&,this](auto const& node, auto treePath) { std::string componentName = name + "->output[" + to_string(treePath) + "]"; if (!Parameters::get(componentName + "->filename")) return; auto writer = makeFileWriterPtr(componentName, this->getSolution(treePath)); filewriter.push_back(std::move(writer)); }); } // add matrix/vector operator terms template template void ProblemStat::addMatrixOperator( Operator const& preOp, RowTreePath row, ColTreePath col, double* factor, double* estFactor) { static_assert( Concepts::PreTreePath, "row must be a valid treepath, or an integer/index-constant"); static_assert( Concepts::PreTreePath, "col must be a valid treepath, or an integer/index-constant"); auto i = child(globalBasis->localView().tree(), makeTreePath(row)); auto j = child(globalBasis->localView().tree(), makeTreePath(col)); auto op = makeGridOperator(preOp, globalBasis->gridView()); auto localAssembler = makeLocalAssemblerPtr(std::move(op), i, j); matrixOperators[i][j].element.push_back({localAssembler, factor, estFactor}); matrixOperators[i][j].changing = true; } template template void ProblemStat::addMatrixOperator( BoundaryType b, Operator const& preOp, RowTreePath row, ColTreePath col, double* factor, double* estFactor) { static_assert( Concepts::PreTreePath, "row must be a valid treepath, or an integer/index-constant"); static_assert( Concepts::PreTreePath, "col must be a valid treepath, or an integer/index-constant"); auto i = child(globalBasis->localView().tree(), makeTreePath(row)); auto j = child(globalBasis->localView().tree(), makeTreePath(col)); using Intersection = typename GridView::Intersection; auto op = makeGridOperator(preOp, globalBasis->gridView()); auto localAssembler = makeLocalAssemblerPtr(std::move(op), i, j); matrixOperators[i][j].boundary.push_back({localAssembler, factor, estFactor, b}); matrixOperators[i][j].changing = true; } template template void ProblemStat::addVectorOperator( Operator const& preOp, TreePath path, double* factor, double* estFactor) { static_assert( Concepts::PreTreePath, "path must be a valid treepath, or an integer/index-constant"); auto i = child(globalBasis->localView().tree(), makeTreePath(path)); auto op = makeGridOperator(preOp, globalBasis->gridView()); auto localAssembler = makeLocalAssemblerPtr(std::move(op), i); rhsOperators[i].element.push_back({localAssembler, factor, estFactor}); rhsOperators[i].changing = true; } template template void ProblemStat::addVectorOperator( BoundaryType b, Operator const& preOp, TreePath path, double* factor, double* estFactor) { static_assert( Concepts::PreTreePath, "path must be a valid treepath, or an integer/index-constant"); auto i = child(globalBasis->localView().tree(), makeTreePath(path)); using Intersection = typename GridView::Intersection; auto op = makeGridOperator(preOp, globalBasis->gridView()); auto localAssembler = makeLocalAssemblerPtr(std::move(op), i); rhsOperators[i].boundary.push_back({localAssembler, factor, estFactor, b}); rhsOperators[i].changing = true; } // Adds a Dirichlet boundary condition template template void ProblemStat:: addDirichletBC(Predicate const& predicate, RowTreePath row, ColTreePath col, Values const& values) { static_assert( Concepts::Functor, "Function passed to addDirichletBC for `predicate` does not model the Functor concept"); auto i = child(globalBasis->localView().tree(), makeTreePath(row)); auto j = child(globalBasis->localView().tree(), makeTreePath(col)); auto valueGridFct = makeGridFunction(values, globalBasis->gridView()); using Range = RangeType_t; using BcType = DirichletBC; auto bc = std::make_shared(predicate, valueGridFct); constraints[i][j].push_back(bc); // TODO: make DirichletBC an abstract class and add specialization with gridfunction type } template void ProblemStat:: solve(AdaptInfo& adaptInfo, bool createMatrixData, bool storeMatrixData) { Dune::Timer t; SolverInfo solverInfo(name + "->solver"); solverInfo.setCreateMatrixData(createMatrixData); solverInfo.setStoreMatrixData(storeMatrixData); solution->compress(); linearSolver->solve(systemMatrix->getMatrix(), solution->getVector(), rhs->getVector(), solverInfo); if (solverInfo.getInfo() > 0) { msg("solution of discrete system needed ", t.elapsed(), " seconds"); if (solverInfo.getAbsResidual() >= 0.0) { if (solverInfo.getRelResidual() >= 0.0) msg("Residual norm: ||b-Ax|| = ", solverInfo.getAbsResidual(), ", ||b-Ax||/||b|| = ", solverInfo.getRelResidual()); else msg("Residual norm: ||b-Ax|| = ", solverInfo.getAbsResidual()); } } if (solverInfo.doBreak()) { std::stringstream tol_str; if (solverInfo.getAbsTolerance() > 0 && solverInfo.getAbsResidual() > solverInfo.getAbsTolerance()) tol_str << "absTol = " << solverInfo.getAbsTolerance() << " "; if (solverInfo.getRelTolerance() > 0 && solverInfo.getRelResidual() > solverInfo.getRelTolerance()) tol_str << "relTol = " << solverInfo.getRelTolerance() << " "; error_exit("Tolerance ", tol_str.str(), " could not be reached!"); } } template void ProblemStat:: buildAfterCoarsen(AdaptInfo& /*adaptInfo*/, Flag /*flag*/, bool asmMatrix, bool asmVector) { Dune::Timer t; Assembler assembler(*globalBasis, matrixOperators, rhsOperators, constraints); auto gv = leafGridView(); assembler.update(gv); assembler.assemble(*systemMatrix, *solution, *rhs, asmMatrix, asmVector); msg("buildAfterCoarsen needed ", t.elapsed(), " seconds"); } template void ProblemStat:: writeFiles(AdaptInfo& adaptInfo, bool force) { Dune::Timer t; for (auto writer : filewriter) writer->writeFiles(adaptInfo, force); msg("writeFiles needed ", t.elapsed(), " seconds"); } } // end namespace AMDiS