#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 "Preconditioner.h" #include "MatVecMultiplier.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" namespace AMDiS { ProblemScal *ProblemScal::traversePtr_ = NULL; 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 (leftPrecon) DELETE leftPrecon; if (rightPrecon) DELETE rightPrecon; 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); } 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(); int iter = solver->solve(matVec_, solution, rhs, leftPrecon, rightPrecon); #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.c_str(), 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); std::cout << degree << std::endl; WAIT_REALLY; 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 ! */ // === create matVec === matVec_ = NEW StandardMatVec >(systemMatrix); } void ProblemScal::createSolver() { // === create solver === std::string solverType("no"); 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(); // === create preconditioners === std::string preconType("no"); Preconditioner > *precon; GET_PARAMETER(0, name_ + "->solver->left precon", &preconType); CreatorInterface *preconCreator = CreatorMap::getCreator(preconType); if (!preconCreator->isNullCreator()) { dynamic_cast(preconCreator)->setSizeAndRow(1, 0); dynamic_cast(preconCreator)->setName(name_ + "->solver->left precon"); } precon = preconCreator->create(); if (precon) { dynamic_cast(precon)->setMatrix(&systemMatrix); leftPrecon = precon; } preconType.assign("no"); GET_PARAMETER(0, name_ + "->solver->right precon", &preconType); preconCreator = CreatorMap::getCreator(preconType); if (!preconCreator->isNullCreator()) { dynamic_cast(preconCreator)->setSizeAndRow(1, 0); dynamic_cast(preconCreator)->setName(name_ + "->solver->left precon"); } precon = preconCreator->create(); if (precon) { dynamic_cast(precon)->setMatrix(&systemMatrix); rightPrecon = precon; } // === create vector creator === solver->setVectorCreator(new DOFVector::Creator(feSpace_)); } void ProblemScal::createEstimator() { // create and set leaf data prototype mesh->setElementDataPrototype(NEW LeafDataEstimatable(NEW LeafDataCoarsenable)); // === create estimator === std::string estimatorType("no"); 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(); mesh->dofCompress(); MSG("%d DOFs for %s\n", feSpace_->getAdmin()->getUsedSize(), feSpace_->getName().c_str()); Flag assembleFlag = flag | systemMatrix->getAssembleFlag() | rhs->getAssembleFlag(); if (useGetBound_) assembleFlag |= Mesh::FILL_BOUND; systemMatrix->clear(); rhs->set(0.0); traversePtr_ = this; mesh->traverse(-1, assembleFlag, &buildAfterCoarsenFct); // fill boundary conditions if (systemMatrix->getBoundaryManager()) systemMatrix->getBoundaryManager()->initMatrix(systemMatrix); if (rhs->getBoundaryManager()) rhs->getBoundaryManager()->initVector(rhs); if (solution->getBoundaryManager()) solution->getBoundaryManager()->initVector(solution); 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); // for all elements ... while (elInfo) { 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()); if (systemMatrix->getBoundaryManager()) systemMatrix->getBoundaryManager()->exitMatrix(systemMatrix); if (rhs->getBoundaryManager()) rhs->getBoundaryManager()->exitVector(rhs); if (solution->getBoundaryManager()) solution->getBoundaryManager()->exitVector(solution); INFO(info_, 8)("buildAfterCoarsen needed %.5f seconds\n", TIME_USED(first,clock())); return; } int ProblemScal::buildAfterCoarsenFct(ElInfo *elInfo) { BoundaryType *bound; if (traversePtr_->getBoundUsed()) { bound = GET_MEMORY(BoundaryType, traversePtr_->getFESpace()->getBasisFcts()->getNumber()); traversePtr_->getFESpace()->getBasisFcts()->getBound(elInfo, bound); } else { bound = NULL; } traversePtr_->getSystemMatrix()->assemble(1.0, elInfo, bound); traversePtr_->getRHS()->assemble(1.0, elInfo, bound); if (traversePtr_->getBoundUsed()) { FREE_MEMORY(bound, BoundaryType, traversePtr_->getFESpace()->getBasisFcts()->getNumber()); } return 0; } void ProblemScal::writeResidualMesh(AdaptInfo *adaptInfo, const std::string name) { FUNCNAME("ProblemVec::writeResidualMesh()"); Mesh *mesh = this->getMesh(); FiniteElemSpace *fe = this->getFESpace(); std::map vec; TraverseStack stack; ElInfo *elInfo = stack.traverseFirst(mesh, -1, Mesh::CALL_LEAF_EL | Mesh::FILL_COORDS); while (elInfo) { Element *el = elInfo->getElement(); double lError = el->getEstimation(0); vec[elInfo->getElement()->getIndex()] = lError; elInfo = stack.traverseNext(elInfo); } ElementFileWriter fw(name, mesh, fe, vec); fw.writeFiles(adaptInfo, true); } 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); } }