#include "ProblemScal.h" #include "AbstractFunction.h" #include "DirichletBC.h" #include "RobinBC.h" #include "FixVec.h" #include "Flag.h" #include "Serializer.h" #include "RecoveryEstimator.h" #include "Operator.h" #include "DOFMatrix.h" #include "FiniteElemSpace.h" #include "Estimator.h" #include "OEMSolver.h" #include "DOFVector.h" #include "Marker.h" #include "AdaptInfo.h" #include "ElInfo.h" #include "FileWriter.h" #include "RefinementManager.h" #include "CoarseningManager.h" #include "Lagrange.h" #include "PeriodicBC.h" #include "ValueReader.h" #include "ElementFileWriter.h" #include "ProblemVec.h" namespace AMDiS { ProblemScal::~ProblemScal() { FUNCNAME("ProblemScal::~ProblemScal()"); for (int i = 0; i < static_cast(fileWriters.size()); i++) delete fileWriters[i]; if (systemMatrix) delete systemMatrix; if (rhs) delete rhs; if (solution) delete solution; if (estimator) delete estimator; if (marker) delete marker; if (solver) delete solver; if (mesh) delete mesh; FiniteElemSpace::clear(); Lagrange::clear(); } void ProblemScal::writeFiles(AdaptInfo *adaptInfo, bool force) { for (int i = 0; i < static_cast(fileWriters.size()); i++) fileWriters[i]->writeFiles(adaptInfo, force); } void ProblemScal::interpolInitialSolution(AbstractFunction > *fct) { solution->interpol(fct); } void ProblemScal::addMatrixOperator(Operator *op, double *factor, double *estFactor) { systemMatrix->addOperator(op, factor, estFactor); } void ProblemScal::addVectorOperator(Operator *op, double *factor, double *estFactor) { rhs->addOperator(op, factor, estFactor); } void ProblemScal::addDirichletBC(BoundaryType type, AbstractFunction >* b) { DirichletBC *dirichlet = new DirichletBC(type, b, feSpace); if (systemMatrix) systemMatrix->getBoundaryManager()->addBoundaryCondition(dirichlet); if (rhs) rhs->getBoundaryManager()->addBoundaryCondition(dirichlet); if (solution) solution->getBoundaryManager()->addBoundaryCondition(dirichlet); } void ProblemScal::addDirichletBC(BoundaryType type, DOFVector *vec) { DirichletBC *dirichlet = new DirichletBC(type, vec); if (systemMatrix) systemMatrix->getBoundaryManager()->addBoundaryCondition(dirichlet); if (rhs) rhs->getBoundaryManager()->addBoundaryCondition(dirichlet); if (solution) solution->getBoundaryManager()->addBoundaryCondition(dirichlet); } void ProblemScal::addRobinBC(BoundaryType type, AbstractFunction > *n, AbstractFunction > *r) { RobinBC *robin = new RobinBC(type, n, r, feSpace); if (rhs) rhs->getBoundaryManager()->addBoundaryCondition(robin); if (systemMatrix) systemMatrix->getBoundaryManager()->addBoundaryCondition(robin); } void ProblemScal::addNeumannBC(BoundaryType type, AbstractFunction > *n) { NeumannBC *neumann = new NeumannBC(type, n, feSpace); if (rhs) rhs->getBoundaryManager()->addBoundaryCondition(neumann); } void ProblemScal::addRobinBC(BoundaryType type, DOFVector *n, DOFVector *r) { RobinBC *robin = new RobinBC(type, n, r, feSpace); if (rhs) rhs->getBoundaryManager()->addBoundaryCondition(robin); if (systemMatrix) systemMatrix->getBoundaryManager()->addBoundaryCondition(robin); } void ProblemScal::addPeriodicBC(BoundaryType type) { PeriodicBC *periodic = new PeriodicBC(type, feSpace); if (systemMatrix) systemMatrix->getBoundaryManager()->addBoundaryCondition(periodic); if (rhs) rhs->getBoundaryManager()->addBoundaryCondition(periodic); } #ifdef HAVE_PARALLEL_DOMAIN_AMDIS void ProblemScal::useApplicationOrdering(AO *ao) { applicationOrdering = ao; systemMatrix->useApplicationOrdering(ao); rhs->useApplicationOrdering(ao); } #endif void ProblemScal::createMesh() { TEST_EXIT(Parameters::initialized())("parameters not initialized\n"); // === create problems mesh === std::string meshName(""); GET_PARAMETER(0, name + "->info", "%d", &info); GET_PARAMETER(0, name + "->mesh", &meshName); TEST_EXIT(meshName != "")("no mesh name specified\n"); // get problem dimension int dim = 0; GET_PARAMETER(0, name + "->dim", "%d", &dim); TEST_EXIT(dim)("no problem dimension specified!\n"); // create the mesh mesh = new Mesh(meshName, dim); switch (dim) { case 1: coarseningManager = new CoarseningManager1d(); refinementManager = new RefinementManager1d(); break; case 2: coarseningManager = new CoarseningManager2d(); refinementManager = new RefinementManager2d(); break; case 3: coarseningManager = new CoarseningManager3d(); refinementManager = new RefinementManager3d(); break; default: ERROR_EXIT("invalid dim!\n"); } } void ProblemScal::setMeshFromProblemVec(ProblemVec* pv, int i) { mesh = pv->getMesh(i); coarseningManager = pv->getCoarseningManager(i); refinementManager = pv->getRefinementManager(i); } Flag ProblemScal::markElements(AdaptInfo *adaptInfo) { if (marker) return marker->markMesh(adaptInfo, mesh); else WARNING("no marker\n"); return 0; } Flag ProblemScal::refineMesh(AdaptInfo *adaptInfo) { return refinementManager->refineMesh(mesh); } Flag ProblemScal::coarsenMesh(AdaptInfo *adaptInfo) { if (adaptInfo->isCoarseningAllowed(0)) { return coarseningManager->coarsenMesh(mesh); } else { WARNING("coarsening not allowed\n"); return 0; } } void ProblemScal::solve(AdaptInfo *adaptInfo, bool fixedMatrix) { FUNCNAME("Problem::solve()"); if (!solver) { WARNING("no solver\n"); return; } #ifdef _OPENMP double wtime = omp_get_wtime(); #endif clock_t first = clock(); SolverMatrix solverMatrix; solverMatrix.setMatrix(*systemMatrix); int iter = solver->solveSystem(solverMatrix, *solution, *rhs); #ifdef _OPENMP INFO(info, 8)("solution of discrete system needed %.5f seconds system time / %.5f seconds wallclock time\n", TIME_USED(first, clock()), omp_get_wtime() - wtime); #else INFO(info, 8)("solution of discrete system needed %.5f seconds\n", TIME_USED(first, clock())); #endif adaptInfo->setSolverIterations(iter); adaptInfo->setMaxSolverIterations(solver->getMaxIterations()); adaptInfo->setSolverTolerance(solver->getTolerance()); adaptInfo->setSolverResidual(solver->getResidual()); } void ProblemScal::initialize(Flag initFlag, ProblemScal *adoptProblem, Flag adoptFlag) { FUNCNAME("Problem::initialize()"); // === create mesh === if (mesh) { WARNING("mesh already created\n"); } else { if(initFlag.isSet(CREATE_MESH) || ((!adoptFlag.isSet(INIT_MESH))&& (initFlag.isSet(INIT_SYSTEM)||initFlag.isSet(INIT_FE_SPACE)))) { createMesh(); } if(adoptProblem && (adoptFlag.isSet(INIT_MESH) || adoptFlag.isSet(INIT_SYSTEM) || adoptFlag.isSet(INIT_FE_SPACE))) { TEST_EXIT(!mesh)("mesh already created\n"); mesh = adoptProblem->getMesh(); refinementManager = adoptProblem->refinementManager; coarseningManager = adoptProblem->coarseningManager; } } if (!mesh) WARNING("no mesh created\n"); // === create fespace === if (feSpace) { WARNING("feSpace already created\n"); } else { if (initFlag.isSet(INIT_FE_SPACE) || (initFlag.isSet(INIT_SYSTEM) && !adoptFlag.isSet(INIT_FE_SPACE))) { createFESpace(); } if (adoptProblem && (adoptFlag.isSet(INIT_FE_SPACE) || adoptFlag.isSet(INIT_SYSTEM))) { TEST_EXIT(!feSpace)("feSpace already created"); feSpace = dynamic_cast(adoptProblem)->getFESpace(); } } if (!feSpace) WARNING("no feSpace created\n"); // === create system === if (initFlag.isSet(INIT_SYSTEM)) { createMatricesAndVectors(); } if (adoptProblem && adoptFlag.isSet(INIT_SYSTEM)) { TEST_EXIT(!solution)("solution already created\n"); TEST_EXIT(!rhs)("rhs already created\n"); TEST_EXIT(!systemMatrix)("systemMatrix already created\n"); solution = adoptProblem->getSolution(); rhs = adoptProblem->getRHS(); systemMatrix = adoptProblem->getSystemMatrix(); } // === create solver === if (solver) { WARNING("solver already created\n"); } else { if (initFlag.isSet(INIT_SOLVER)) { createSolver(); } if (adoptProblem && adoptFlag.isSet(INIT_SOLVER)) { TEST_EXIT(!solver)("solver already created\n"); solver = adoptProblem->getSolver(); } } if (!solver) WARNING("no solver created\n"); // === create estimator === if (estimator) { WARNING("estimator already created\n"); } else { if (initFlag.isSet(INIT_ESTIMATOR)) { createEstimator(); } if (adoptProblem && adoptFlag.isSet(INIT_ESTIMATOR)) { TEST_EXIT(!estimator)("estimator already created\n"); estimator = adoptProblem->getEstimator(); } } if (!estimator) WARNING("no estimator created\n"); // === create marker === if (marker) { WARNING("marker already created\n"); } else { if(initFlag.isSet(INIT_MARKER)) { createMarker(); } if(adoptProblem && adoptFlag.isSet(INIT_MARKER)) { TEST_EXIT(!marker)("marker already created\n"); marker = adoptProblem->getMarker(); } } if (!marker) WARNING("no marker created\n"); // === create file writer === if(initFlag.isSet(INIT_FILEWRITER)) { createFileWriter(); } // === read serialization and init mesh === // There are two possiblities where the user can define a serialization // to be read from disk. Either by providing the parameter -rs when executing // the program or in the init file. The -rs parameter is always checked first, // because it can be added automatically when rescheduling the program // before timeout of the runqueue. int readSerialization = 0; std::string serializationFilename = ""; GET_PARAMETER(0, "argv->rs", &serializationFilename); // If the parameter -rs is set, we do nothing here, because the problem will be // deserialized in the constructor of a following AdaptInstationary initialization. if (!serializationFilename.compare("")) { GET_PARAMETER(0, name + "->input->read serialization", "%d", &readSerialization); if (readSerialization) { GET_PARAMETER(0, name + "->input->serialization filename", &serializationFilename); TEST_EXIT(serializationFilename != "")("no serialization file\n"); MSG("Deserialization from file: %s\n", serializationFilename.c_str()); std::ifstream in(serializationFilename.c_str()); deserialize(in); in.close(); } else { if (initFlag.isSet(INIT_MESH) && mesh && !mesh->isInitialized()) { mesh->initialize(); } // === read value file and use it for the mesh values === std::string valueFilename(""); GET_PARAMETER(0, mesh->getName() + "->value file name", &valueFilename); if (valueFilename.length()) { ValueReader::readValue(valueFilename, mesh, solution, mesh->getMacroFileInfo()); mesh->clearMacroFileInfo(); } // === do global refinements === if (initFlag.isSet(INIT_GLOBAL_REFINES)) { int globalRefinements = 0; GET_PARAMETER(0, mesh->getName() + "->global refinements", "%d", &globalRefinements); refinementManager->globalRefine(mesh, globalRefinements); } } } } void ProblemScal::createFESpace() { // create finite element space int degree = 1; GET_PARAMETER(0, name + "->polynomial degree" ,"%d", °ree); feSpace = FiniteElemSpace::provideFESpace(NULL, Lagrange::getLagrange(mesh->getDim(), degree), mesh, name + "->feSpace"); // create dof admin for vertex dofs if neccessary if (mesh->getNumberOfDOFs(VERTEX) == 0) { DimVec ln_dof(mesh->getDim(), DEFAULT_VALUE, 0); ln_dof[VERTEX]= 1; mesh->createDOFAdmin("vertex dofs", ln_dof); } } void ProblemScal::createMatricesAndVectors() { // === create vectors and system matrix === systemMatrix = new DOFMatrix(feSpace, feSpace, "system matrix"); rhs = new DOFVector(feSpace, "rhs"); solution = new DOFVector(feSpace, "solution"); solution->setCoarsenOperation(COARSE_INTERPOL); solution->set(0.0); /* initialize u_h ! */ } void ProblemScal::createSolver() { // === create solver === std::string solverType("0"); GET_PARAMETER(0, name + "->solver", &solverType); OEMSolverCreator *solverCreator = dynamic_cast(CreatorMap::getCreator(solverType)); TEST_EXIT(solverCreator)("no solver type\n"); solverCreator->setName(name + "->solver"); solver = solverCreator->create(); solver->initParameters(); } void ProblemScal::createEstimator() { // create and set leaf data prototype mesh->setElementDataPrototype(new LeafDataEstimatable(new LeafDataCoarsenable)); // === create estimator === std::string estimatorType("0"); GET_PARAMETER(0, name + "->estimator", &estimatorType); EstimatorCreator *estimatorCreator = dynamic_cast( CreatorMap::getCreator(estimatorType)); if (estimatorCreator) { estimatorCreator->setName(name + "->estimator"); if (estimatorType == "recovery") { dynamic_cast(estimatorCreator)->setSolution(solution); } estimator = estimatorCreator->create(); // init estimator estimator->addSystem(systemMatrix, solution, rhs); } } void ProblemScal::createMarker() { marker = dynamic_cast(Marker::createMarker(name + "->marker", -1)); } void ProblemScal::createFileWriter() { fileWriters.push_back(new FileWriter(name + "->output", mesh, solution)); int writeSerialization = 0; GET_PARAMETER(0, name + "->output->write serialization", "%d", &writeSerialization); if (writeSerialization) fileWriters.push_back(new Serializer(this)); } void ProblemScal::estimate(AdaptInfo *adaptInfo) { FUNCNAME("Problem::estimate()"); if (estimator) { clock_t first = clock(); estimator->estimate(adaptInfo->getTimestep()); INFO(info,8)("estimation of the error needed %.5f seconds\n", TIME_USED(first,clock())); adaptInfo->setEstSum(estimator->getErrorSum(), 0); adaptInfo->setTimeEstSum(estimator->getTimeEst(), 0); adaptInfo->setEstMax(estimator->getErrorMax(), 0); adaptInfo->setTimeEstMax(estimator->getTimeEstMax(), 0); } else { WARNING("no estimator\n"); } } void ProblemScal::buildAfterCoarsen(AdaptInfo *adaptInfo, Flag flag, bool assembleMatrix, bool assembleVector) { FUNCNAME("ProblemScal::buildAfterCoarsen()"); clock_t first = clock(); #ifndef HAVE_PARALLEL_DOMAIN_AMDIS mesh->dofCompress(); #endif MSG("%d DOFs for %s\n", feSpace->getAdmin()->getUsedDOFs(), feSpace->getName().c_str()); rhs->set(0.0); DOFMatrix::base_matrix_type& base_matrix= systemMatrix->getBaseMatrix(); int nnz_per_row= 0; if (num_rows(base_matrix) != 0) nnz_per_row= int(double(base_matrix.nnz()) / num_rows(base_matrix) * 1.2); if (nnz_per_row < 5) nnz_per_row= 5; // Correct dimensionality of matrix base_matrix.change_dim(feSpace->getAdmin()->getUsedSize(), feSpace->getAdmin()->getUsedSize()); set_to_zero(base_matrix); // Reuse old sparsity information (if available) or default systemMatrix->startInsertion(nnz_per_row); // fill boundary conditions if (systemMatrix->getBoundaryManager()) systemMatrix->getBoundaryManager()->initMatrix(systemMatrix); if (rhs->getBoundaryManager()) rhs->getBoundaryManager()->initVector(rhs); if (solution->getBoundaryManager()) solution->getBoundaryManager()->initVector(solution); BoundaryType *bound; TraverseStack stack; ElInfo *elInfo = stack.traverseFirst(mesh, -1, Mesh::CALL_LEAF_EL | Mesh::FILL_BOUND | Mesh::FILL_COORDS | Mesh::FILL_DET | Mesh::FILL_GRD_LAMBDA | Mesh::FILL_NEIGH); while (elInfo) { if (useGetBound) { bound = GET_MEMORY(BoundaryType, feSpace->getBasisFcts()->getNumber()); feSpace->getBasisFcts()->getBound(elInfo, bound); } else { bound = NULL; } systemMatrix->assemble(1.0, elInfo, bound); rhs->assemble(1.0, elInfo, bound); if (useGetBound) FREE_MEMORY(bound, BoundaryType, feSpace->getBasisFcts()->getNumber()); if (systemMatrix->getBoundaryManager()) systemMatrix->getBoundaryManager()->fillBoundaryConditions(elInfo, systemMatrix); if (rhs->getBoundaryManager()) rhs->getBoundaryManager()->fillBoundaryConditions(elInfo, rhs); if (solution->getBoundaryManager()) solution->getBoundaryManager()->fillBoundaryConditions(elInfo, solution); elInfo = stack.traverseNext(elInfo); } systemMatrix->removeRowsWithDBC(systemMatrix->getApplyDBCs()); // TODO: ExitMatrix should be called after finishInsertion! if (systemMatrix->getBoundaryManager()) systemMatrix->getBoundaryManager()->exitMatrix(systemMatrix); if (rhs->getBoundaryManager()) rhs->getBoundaryManager()->exitVector(rhs); if (solution->getBoundaryManager()) solution->getBoundaryManager()->exitVector(solution); systemMatrix->finishInsertion(); INFO(info, 8)("buildAfterCoarsen needed %.5f seconds\n", TIME_USED(first,clock())); #ifdef HAVE_PARALLEL_DOMAIN_AMDIS // PetscErrorCode ierr; // Mat A; // ierr = MatCreate(PETSC_COMM_WORLD, &A); CHKERRQ(ierr); #endif createPrecon(); } void ProblemScal::writeResidualMesh(AdaptInfo *adaptInfo, const std::string name) { FUNCNAME("ProblemScal::writeResidualMesh()"); std::map vec; TraverseStack stack; ElInfo *elInfo = stack.traverseFirst(this->getMesh(), -1, Mesh::CALL_LEAF_EL | Mesh::FILL_COORDS); while (elInfo) { vec[elInfo->getElement()->getIndex()] = elInfo->getElement()->getEstimation(0); elInfo = stack.traverseNext(elInfo); } ElementFileWriter fw(name, this->getFESpace(), vec); fw.writeFiles(adaptInfo, true); } void ProblemScal::createPrecon() { std::string preconType("no"); GET_PARAMETER(0, name + "->solver->left precon", &preconType); CreatorInterface *preconCreator = CreatorMap::getCreator(preconType); solver->setLeftPrecon( preconCreator->create(systemMatrix->getBaseMatrix()) ); preconType= "no"; GET_PARAMETER(0, name + "->solver->right precon", &preconType); preconCreator = CreatorMap::getCreator(preconType); solver->setRightPrecon( preconCreator->create(systemMatrix->getBaseMatrix()) ); } void ProblemScal::serialize(std::ostream &out) { FUNCNAME("ProblemScal::serialize()"); mesh->serialize(out); solution->serialize(out); } void ProblemScal::deserialize(std::istream &in) { FUNCNAME("ProblemScal::deserialize()"); mesh->deserialize(in); solution->deserialize(in); } }