diff --git a/AMDiS/src/AdaptInstationary.cc b/AMDiS/src/AdaptInstationary.cc index ff6fcae77d491652fa04034a3fd0f54e6d2f6c96..0781d4e33d3a1b350a33cbe5949cd36039b9f851 100644 --- a/AMDiS/src/AdaptInstationary.cc +++ b/AMDiS/src/AdaptInstationary.cc @@ -204,7 +204,21 @@ namespace AMDiS { iterationTimestamp_ = time(NULL); problemTime_->initTimestep(adaptInfo_); + +#ifdef _OPENMP +#pragma omp parallel sections + { +#pragma omp section + problemTime_->startDelayedTimestepCalculation(); + +#pragma omp section + oneTimestep(); + } +#else + problemTime_->startDelayedTimestepCalculation(); oneTimestep(); +#endif + problemTime_->closeTimestep(adaptInfo_); if (breakWhenStable && (adaptInfo_->getSolverIterations() == 0)) { @@ -220,6 +234,8 @@ namespace AMDiS { } } + problemTime_->startDelayedTimestepCalculation(); + return errorCode; } diff --git a/AMDiS/src/DataCollector.cc b/AMDiS/src/DataCollector.cc index 88ebc9cfb6798d0a623b2c5dc1e3d2f890bb2e0c..1d0372488347c55531270c64eb226cc3d3b5e972 100644 --- a/AMDiS/src/DataCollector.cc +++ b/AMDiS/src/DataCollector.cc @@ -56,6 +56,19 @@ namespace AMDiS { DELETE dofCoords_; } + void DataCollector::fillAllData() + { + if (!elementDataCollected_) { + startCollectingElementData(); + } + if (!periodicDataCollected_) { + startCollectingPeriodicData(); + } + if (!valueDataCollected_) { + startCollectingValueData(); + } + } + int DataCollector::startCollectingElementData() { FUNCNAME("DataCollector::startCollectingElementData()"); @@ -427,7 +440,7 @@ namespace AMDiS { ::std::list<PeriodicInfo>* DataCollector::getPeriodicInfos() { - if(!periodicDataCollected_) { + if (!periodicDataCollected_) { startCollectingPeriodicData(); } @@ -463,7 +476,7 @@ namespace AMDiS { int DataCollector::getNumberConnections() { - if(!periodicDataCollected_) { + if (!periodicDataCollected_) { startCollectingPeriodicData(); } diff --git a/AMDiS/src/DataCollector.h b/AMDiS/src/DataCollector.h index a0b58709acd4f006d86e61a9229cd16deed57a45..2e5d168c8c4daf2e1b69f45a18d814922f9b2f81 100644 --- a/AMDiS/src/DataCollector.h +++ b/AMDiS/src/DataCollector.h @@ -61,6 +61,11 @@ namespace AMDiS { ~DataCollector(); + /** \brief + * Fills the DataCollector with all possible datas. + */ + void fillAllData(); + /** \brief * Returns list with element information. */ diff --git a/AMDiS/src/DuneSolver.cc b/AMDiS/src/DuneSolver.cc index f0f9d34aab0701248ac000be2a1e35cd03a29adc..654a8ec66c865468d4b9396c6cb0c1b9c6fe1a3d 100644 --- a/AMDiS/src/DuneSolver.cc +++ b/AMDiS/src/DuneSolver.cc @@ -71,6 +71,13 @@ namespace AMDiS { { FUNCNAME("DuneSolver::solveSystem()"); + // Calculate residual reduction which should be achieved by the dune solver. + *p = *x; + *p *= -1.0; + mv->matVec(NoTranspose, *p, *r); + *r += *b; + double reduction = this->tolerance / norm(r); + typedef Dune::Matrix<DuneMatrix> SystemDuneMatrix; typedef Dune::BlockVector<DuneVector> SystemDuneVector; @@ -117,7 +124,7 @@ namespace AMDiS { Dune::InverseOperator<SystemDuneVector, SystemDuneVector> *duneSolver = getSolver<SystemDuneMatrix, SystemDuneVector>(&op, dunePreconditioner); - duneSolver->apply(duneVecX, duneVecB, opRes); + duneSolver->apply(duneVecX, duneVecB, reduction, opRes); for (int i = 0; i < nComponents; i++) { DuneVector::Iterator duneVecIt; @@ -129,6 +136,16 @@ namespace AMDiS { } } + // Calculate and print the residual. + *p = *x; + *p *= -1.0; + mv->matVec(NoTranspose, *p, *r); + *r += *b; + + this->residual = norm(r); + + MSG("Residual: %e\n", this->residual); + delete dunePreconditioner; delete duneSolver; diff --git a/AMDiS/src/DuneSolver.h b/AMDiS/src/DuneSolver.h index a4c24cb24168d30144cc3e0c30437f8090e5c24e..7f9f84726c545b60d93e2c7e954c8024d903baef 100644 --- a/AMDiS/src/DuneSolver.h +++ b/AMDiS/src/DuneSolver.h @@ -123,12 +123,20 @@ namespace AMDiS { /** \brief * Implements OEMSolver<VectorType>::init(). */ - void init() {}; + void init() + { + p = this->vectorCreator->create(); + r = this->vectorCreator->create(); + }; /** \brief * Implements OEMSolver<VectorType>::exit(). */ - void exit() {}; + void exit() + { + this->vectorCreator->free(p); + this->vectorCreator->free(r); + }; /** \brief * Creates a dune preconditioner using the informations in the used init file. @@ -168,6 +176,12 @@ namespace AMDiS { * to be allocated before. */ void mapDOFVector(DOFVector<double> *dofVector, DuneVector *duneVector); + + private: + /** \brief + * These vectors are justed to calculate the final residual of the solution. + */ + VectorType *r, *p; }; } diff --git a/AMDiS/src/DuneSolver.hh b/AMDiS/src/DuneSolver.hh index 6b016ff85b94c30f3438c0c58b1c69398f389b1b..de9f676f53945314eb135514f9406f127a032745 100644 --- a/AMDiS/src/DuneSolver.hh +++ b/AMDiS/src/DuneSolver.hh @@ -90,7 +90,7 @@ namespace AMDiS { Dune::Preconditioner<V, V>* precon) { if (solverType_ == "bicgstab") { - return new Dune::BiCGSTABSolver<V>(*ma, *precon, this->tolerance, this->max_iter, verbose_); + return new Dune::BiCGSTABSolver<V>(*ma, *precon, this->tolerance, this->max_iter, verbose_); } else if (solverType_ == "cg") { return new Dune::CGSolver<V>(*ma, *precon, this->tolerance, this->max_iter, verbose_); } else if (solverType_ == "gradient") { diff --git a/AMDiS/src/ElementFileWriter.h b/AMDiS/src/ElementFileWriter.h index 3ba744748ccd94e932423e8e0b796f80dc11a4bd..722247017d29fcff742dac376ebb34220276c738 100644 --- a/AMDiS/src/ElementFileWriter.h +++ b/AMDiS/src/ElementFileWriter.h @@ -30,6 +30,8 @@ namespace AMDiS { Flag traverseFlag = Mesh::CALL_LEAF_EL, bool (*writeElem)(ElInfo*) = NULL); + void writeDelayedFiles() {}; + protected: /** * Writes element data in tecplot format. diff --git a/AMDiS/src/FileWriter.cc b/AMDiS/src/FileWriter.cc index d125d6a603302732170e0a021a09fa7f9bd91159..2831fa89770fa4e56784bc0febcd2e1dcec01482 100644 --- a/AMDiS/src/FileWriter.cc +++ b/AMDiS/src/FileWriter.cc @@ -5,7 +5,6 @@ #include "ValueWriter.h" #include "MacroWriter.h" #include "VtkWriter.h" -#include "DataCollector.h" #include "FiniteElemSpace.h" #include "AdaptInfo.h" #include "Flag.h" @@ -28,6 +27,8 @@ namespace AMDiS { solutionVecs_.resize(1); solutionVecs_[0] = vec; + + dataCollectors_.resize(1); } @@ -48,6 +49,8 @@ namespace AMDiS { feSpace = vecs[0]->getFESpace(); solutionVecs_ = vecs; + + dataCollectors_.resize(vecs.size()); } @@ -79,6 +82,8 @@ namespace AMDiS { } feSpace = vec->getFESpace(); + + dataCollectors_.resize(nTmpSolutions_); } @@ -91,6 +96,12 @@ namespace AMDiS { DELETE solutionVecs_[i]; } } + + for (int i = 0; i < static_cast<int>(dataCollectors_.size()); i++) { + if (dataCollectors_[i]) { + DELETE dataCollectors_[i]; + } + } } @@ -111,6 +122,9 @@ namespace AMDiS { indexDecimals = 3; tsModulo = 1; nTmpSolutions_ = 0; + delayWriting_ = 0; + writingIsDelayed_ = false; + delayedFilename_ = ""; paraViewAnimationFrames_.resize(0); readParameters(); @@ -135,6 +149,7 @@ namespace AMDiS { GET_PARAMETER(0, name + "->index length", "%d", &indexLength); GET_PARAMETER(0, name + "->index decimals", "%d", &indexDecimals); GET_PARAMETER(0, name + "->write every i-th timestep", "%d", &tsModulo); + GET_PARAMETER(0, name + "->delay", "%d", &delayWriting_); } void FileWriter::writeFiles(AdaptInfo *adaptInfo, @@ -144,10 +159,26 @@ namespace AMDiS { bool (*writeElem)(ElInfo*)) { FUNCNAME("FileWriter::writeFiles()"); - + if ((adaptInfo->getTimestepNumber() % tsModulo != 0) && !force) return; + if (writingIsDelayed_) { + ERROR_EXIT("This should not happen!\n"); + } + + if (writeElem) { + for (int i = 0; i < static_cast<int>(dataCollectors_.size()); i++) { + dataCollectors_[i] = NEW DataCollector(feSpace, solutionVecs_[i], + level, flag, writeElem); + } + } else { + for (int i = 0; i < static_cast<int>(dataCollectors_.size()); i++) { + dataCollectors_[i] = NEW DataCollector(feSpace, solutionVecs_[i], + traverseLevel, flag | traverseFlag, writeElement); + } + } + ::std::string fn = filename; if (appendIndex) { @@ -156,31 +187,29 @@ namespace AMDiS { TEST_EXIT(indexDecimals < indexLength)("index length <= index decimals\n"); char formatStr[9]; - - sprintf(formatStr, "%%0%d.%df", indexLength, indexDecimals); - char timeStr[20]; + sprintf(formatStr, "%%0%d.%df", indexLength, indexDecimals); sprintf(timeStr, formatStr, adaptInfo ? adaptInfo->getTime() : 0.0); fn += timeStr; } - ::std::vector< DataCollector* > dc(solutionVecs_.size()); - if (writeElem) { - for (int i = 0; i < static_cast<int>(dc.size()); i++) { - dc[i] = NEW DataCollector(feSpace, solutionVecs_[i], - level, flag, writeElem); + if (delayWriting_) { + if (writeTecPlotFormat || writeAMDiSFormat || writePeriodicFormat) { + ERROR_EXIT("Delay writing only supported for ParaView file format!\n"); } - } else { - for (int i = 0; i < static_cast<int>(dc.size()); i++) { - dc[i] = NEW DataCollector(feSpace, solutionVecs_[i], - traverseLevel, flag | traverseFlag, writeElement); + + for (int i = 0; i < static_cast<int>(dataCollectors_.size()); i++) { + dataCollectors_[i]->fillAllData(); } - } - + writingIsDelayed_ = true; + delayedFilename_ = fn; + return; + } + if (writeTecPlotFormat) { TecPlotWriter<DOFVector<double> >::writeValues(solutionVecs_[0], const_cast<char*>((fn + tecplotExt).c_str()), @@ -191,42 +220,67 @@ namespace AMDiS { if (writeAMDiSFormat) { TEST_EXIT(mesh)("no mesh\n"); - MacroWriter::writeMacro(dc[0], - const_cast<char*>( (fn + amdisMeshExt).c_str()), + MacroWriter::writeMacro(dataCollectors_[0], + const_cast<char*>((fn + amdisMeshExt).c_str()), adaptInfo ? adaptInfo->getTime() : 0.0); MSG("macro file written to %s\n", (fn + amdisMeshExt).c_str()); - ValueWriter::writeValues(dc[0], + ValueWriter::writeValues(dataCollectors_[0], (fn + amdisDataExt).c_str(), adaptInfo ? adaptInfo->getTime() : 0.0); MSG("value file written to %s\n", (fn + amdisDataExt).c_str()); } if (writePeriodicFormat) { - MacroWriter::writePeriodicFile(dc[0], + MacroWriter::writePeriodicFile(dataCollectors_[0], (fn + periodicFileExt).c_str()); MSG("periodic file written to %s\n", (fn + periodicFileExt).c_str()); } if (writeParaViewFormat) { - VtkWriter vtkWriter(&dc); - - vtkWriter.writeFile(const_cast<char*>( (fn + paraViewFileExt).c_str())); + VtkWriter vtkWriter(&dataCollectors_); + vtkWriter.writeFile(const_cast<char*>((fn + paraViewFileExt).c_str())); + MSG("ParaView file written to %s\n", (fn + paraViewFileExt).c_str()); } if (writeParaViewAnimation) { - VtkWriter vtkWriter(&dc); - + VtkWriter vtkWriter(&dataCollectors_); vtkWriter.updateAnimationFile(fn + paraViewFileExt, ¶ViewAnimationFrames_, - const_cast<char*>( (filename + ".pvd").c_str())); + const_cast<char*>((filename + ".pvd").c_str())); } - for (int i = 0; i < static_cast<int>(dc.size()); i++) { - DELETE dc[i]; + for (int i = 0; i < static_cast<int>(dataCollectors_.size()); i++) { + DELETE dataCollectors_[i]; + } + } + + void FileWriter::writeDelayedFiles() + { + if (!writingIsDelayed_) { + return; + } + + if (writeParaViewFormat) { + VtkWriter vtkWriter(&dataCollectors_); + vtkWriter.writeFile(const_cast<char*>((delayedFilename_ + paraViewFileExt).c_str())); + } + + if (writeParaViewAnimation) { + VtkWriter vtkWriter(&dataCollectors_); + vtkWriter.updateAnimationFile(delayedFilename_ + paraViewFileExt, + ¶ViewAnimationFrames_, + const_cast<char*>((filename + ".pvd").c_str())); } + + for (int i = 0; i < static_cast<int>(dataCollectors_.size()); i++) { + DELETE dataCollectors_[i]; + } + + writingIsDelayed_ = false; + delayedFilename_ = ""; } } diff --git a/AMDiS/src/FileWriter.h b/AMDiS/src/FileWriter.h index 1b9902e231b460969d4a671420cae51555a21d54..2b67ec2ddad39d3f12a107fa83ed46538fd88efc 100644 --- a/AMDiS/src/FileWriter.h +++ b/AMDiS/src/FileWriter.h @@ -31,6 +31,7 @@ #include "MemoryManager.h" #include "MatrixVector.h" #include "Mesh.h" +#include "DataCollector.h" namespace AMDiS { @@ -69,6 +70,8 @@ namespace AMDiS { Flag traverseFlag = Mesh::CALL_LEAF_EL, bool (*writeElem)(ElInfo*) = NULL) = 0; + virtual void writeDelayedFiles() = 0; + void setTraverseProperties(int level, Flag flag, bool (*writeElem)(ElInfo*)) @@ -150,6 +153,8 @@ namespace AMDiS { Flag traverseFlag = Mesh::CALL_LEAF_EL, bool (*writeElem)(ElInfo*) = NULL); + virtual void writeDelayedFiles(); + protected: /** \brief * Initialization of the filewriter. @@ -272,6 +277,28 @@ namespace AMDiS { * stored in solutionVecs_ must be deleted in the destructor. */ int nTmpSolutions_; + + /** \brief + * Containers, which store the data to be written; + */ + ::std::vector< DataCollector* > dataCollectors_; + + /** \brief + * If set to 1, the FileWriter will delay the file writing to the future, where + * it can be executed in parallel with some other independent calculations. + */ + int delayWriting_; + + /** \brief + * If set to true, the FileWriter was filled with data, but the Files are currently + * not written to disk. + */ + bool writingIsDelayed_; + + /** \brief + * Here the filename for the file, which should be written to the next, is stored. + */ + ::std::string delayedFilename_; }; } diff --git a/AMDiS/src/ProblemInstat.cc b/AMDiS/src/ProblemInstat.cc index eb3d387d2d4bcc51c6f9a14d50517d53c074bc52..4778cdf03f9604fd474f6a4b8729fba92a3d2122 100644 --- a/AMDiS/src/ProblemInstat.cc +++ b/AMDiS/src/ProblemInstat.cc @@ -95,7 +95,7 @@ namespace AMDiS { oldSolution = NEW DOFVector<double>(problemStat->getFESpace(), name + "->uOld"); oldSolution->refineInterpol(true); oldSolution->setCoarsenOperation(COARSE_INTERPOL); - if(problemStat->getEstimator()) { + if (problemStat->getEstimator()) { dynamic_cast<Estimator*>(problemStat->getEstimator()) ->addUhOldToSystem(0, oldSolution); } @@ -184,4 +184,14 @@ namespace AMDiS { oldSolution->copy(*(problemStat->getSolution())); } + void ProblemInstatScal::startDelayedTimestepCalculation() + { + problemStat->writeDelayedFiles(); + } + + void ProblemInstatVec::startDelayedTimestepCalculation() + { + problemStat->writeDelayedFiles(); + } + } diff --git a/AMDiS/src/ProblemInstat.h b/AMDiS/src/ProblemInstat.h index 5b3824a6c1ca5969897dce2d003c1e7c50577efc..db398bc6d95b69e771dcaad551741088e5950a48 100644 --- a/AMDiS/src/ProblemInstat.h +++ b/AMDiS/src/ProblemInstat.h @@ -121,6 +121,11 @@ namespace AMDiS { */ virtual void solveInitialProblem(AdaptInfo *adaptInfo); + /** \brief + * Implements the parallel file writing for instationary problems. + */ + virtual void startDelayedTimestepCalculation() {}; + protected: /** \brief * Name of the problem. @@ -199,6 +204,7 @@ namespace AMDiS { */ virtual void transferInitialSolution(AdaptInfo *adaptInfo); + virtual void startDelayedTimestepCalculation(); virtual void serialize(::std::ostream &out) {}; @@ -287,6 +293,8 @@ namespace AMDiS { */ virtual void transferInitialSolution(AdaptInfo *adaptInfo); + virtual void startDelayedTimestepCalculation(); + virtual void serialize(::std::ostream &out) {}; virtual void deserialize(::std::istream &in) {}; diff --git a/AMDiS/src/ProblemScal.cc b/AMDiS/src/ProblemScal.cc index cddd6c8dffd725d45395aec29c7bddc1ae844d9e..26b15aab6307607bac36286f558ff1a1cb9f582d 100644 --- a/AMDiS/src/ProblemScal.cc +++ b/AMDiS/src/ProblemScal.cc @@ -30,9 +30,15 @@ namespace AMDiS { ProblemScal *ProblemScal::traversePtr_ = NULL; void ProblemScal::writeFiles(AdaptInfo *adaptInfo, bool force) { - ::std::list<FileWriterInterface*>::iterator it; - for(it = fileWriters_.begin(); it != fileWriters_.end(); ++it) { - (*it)->writeFiles(adaptInfo, force); + for (int i = 0; i < static_cast<int>(fileWriters_.size()); i++) { + fileWriters_[i]->writeFiles(adaptInfo, force); + } + } + + void ProblemScal::writeDelayedFiles() + { + for (int i = 0; i < static_cast<int>(fileWriters_.size()); i++) { + fileWriters_[i]->writeDelayedFiles(); } } @@ -59,11 +65,11 @@ namespace AMDiS { AbstractFunction<double, WorldVector<double> >* b) { DirichletBC *dirichlet = new DirichletBC(type, b, feSpace_); - if(systemMatrix_) + if (systemMatrix_) systemMatrix_->getBoundaryManager()->addBoundaryCondition(dirichlet); - if(rhs_) + if (rhs_) rhs_->getBoundaryManager()->addBoundaryCondition(dirichlet); - if(solution_) + if (solution_) solution_->getBoundaryManager()->addBoundaryCondition(dirichlet); } @@ -71,11 +77,11 @@ namespace AMDiS { DOFVector<double> *vec) { DirichletBC *dirichlet = new DirichletBC(type, vec); - if(systemMatrix_) + if (systemMatrix_) systemMatrix_->getBoundaryManager()->addBoundaryCondition(dirichlet); - if(rhs_) + if (rhs_) rhs_->getBoundaryManager()->addBoundaryCondition(dirichlet); - if(solution_) + if (solution_) solution_->getBoundaryManager()->addBoundaryCondition(dirichlet); } @@ -84,9 +90,9 @@ namespace AMDiS { AbstractFunction<double, WorldVector<double> > *r) { RobinBC *robin = new RobinBC(type, n, r, feSpace_); - if(rhs_) + if (rhs_) rhs_->getBoundaryManager()->addBoundaryCondition(robin); - if(systemMatrix_) + if (systemMatrix_) systemMatrix_->getBoundaryManager()->addBoundaryCondition(robin); } @@ -103,9 +109,9 @@ namespace AMDiS { DOFVector<double> *r) { RobinBC *robin = new RobinBC(type, n, r, feSpace_); - if(rhs_) + if (rhs_) rhs_->getBoundaryManager()->addBoundaryCondition(robin); - if(systemMatrix_) + if (systemMatrix_) systemMatrix_->getBoundaryManager()->addBoundaryCondition(robin); } @@ -113,13 +119,9 @@ namespace AMDiS { { PeriodicBC *periodic = new PeriodicBC(type, feSpace_); - // TEST_EXIT(mesh_->getPeriodicBCMap()[type] == NULL) - // ("periodic condition already set in mesh\n"); - // mesh_->getPeriodicBCMap()[type] = periodic; - - if(systemMatrix_) + if (systemMatrix_) systemMatrix_->getBoundaryManager()->addBoundaryCondition(periodic); - if(rhs_) + if (rhs_) rhs_->getBoundaryManager()->addBoundaryCondition(periodic); } @@ -131,7 +133,6 @@ namespace AMDiS { ::std::string meshName(""); GET_PARAMETER(0, name_ + "->info", "%d", &info_); - GET_PARAMETER(0, name_ + "->mesh", &meshName); TEST_EXIT(meshName != "") @@ -145,7 +146,7 @@ namespace AMDiS { // create the mesh mesh_ = NEW Mesh(meshName, dim); - switch(dim) { + switch (dim) { case 1: coarseningManager_ = NEW CoarseningManager1d(); refinementManager_ = NEW RefinementManager1d(); @@ -174,10 +175,11 @@ namespace AMDiS { Flag ProblemScal::markElements(AdaptInfo *adaptInfo) { - if(marker_) + if (marker_) return marker_->markMesh(adaptInfo, mesh_); else WARNING("no marker\n"); + return 0; } @@ -190,9 +192,9 @@ namespace AMDiS { Flag ProblemScal::coarsenMesh(AdaptInfo *adaptInfo) { - if(adaptInfo->isCoarseningAllowed(0)) + if (adaptInfo->isCoarseningAllowed(0)) { return coarseningManager_->coarsenMesh(mesh_); - else { + } else { WARNING("coarsening not allowed\n"); return 0; } @@ -201,7 +203,7 @@ namespace AMDiS { void ProblemScal::solve(AdaptInfo *adaptInfo) { FUNCNAME("Problem::solve()"); - if(!solver_) { + if (!solver_) { WARNING("no solver\n"); return; } @@ -240,20 +242,19 @@ namespace AMDiS { } else { if (initFlag.isSet(CREATE_MESH) || ((!adoptFlag.isSet(INIT_MESH))&& - (initFlag.isSet(INIT_SYSTEM)||initFlag.isSet(INIT_FE_SPACE)))) - { - createMesh(); - } + (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_; - } + adoptFlag.isSet(INIT_FE_SPACE))) { + TEST_EXIT(!mesh_)("mesh already created\n"); + mesh_ = adoptProblem->getMesh(); + refinementManager_ = adoptProblem->refinementManager_; + coarseningManager_ = adoptProblem->coarseningManager_; + } } if (!mesh_) @@ -266,11 +267,10 @@ namespace AMDiS { 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<ProblemScal*>(adoptProblem)->getFESpace(); - } + if (adoptProblem && (adoptFlag.isSet(INIT_FE_SPACE) || adoptFlag.isSet(INIT_SYSTEM))) { + TEST_EXIT(!feSpace_)("feSpace already created"); + feSpace_ = dynamic_cast<ProblemScal*>(adoptProblem)->getFESpace(); + } } if (!feSpace_) @@ -306,13 +306,13 @@ namespace AMDiS { WARNING("no solver created\n"); // === create estimator === - if(estimator_) { + if (estimator_) { WARNING("estimator already created\n"); } else { - if(initFlag.isSet(INIT_ESTIMATOR)) { + if (initFlag.isSet(INIT_ESTIMATOR)) { createEstimator(); } - if(adoptProblem && adoptFlag.isSet(INIT_ESTIMATOR)) { + if (adoptProblem && adoptFlag.isSet(INIT_ESTIMATOR)) { TEST_EXIT(!estimator_)("estimator already created\n"); estimator_ = adoptProblem->getEstimator(); } diff --git a/AMDiS/src/ProblemScal.h b/AMDiS/src/ProblemScal.h index 029921a0c0e9825edd37cd6d14027eef3537b0ff..ad4d8002c74e91874544c88363f8b59cfbd862b4 100644 --- a/AMDiS/src/ProblemScal.h +++ b/AMDiS/src/ProblemScal.h @@ -195,6 +195,11 @@ namespace AMDiS { */ void writeFiles(AdaptInfo *adaptInfo, bool force); + /** \brief + * Startes parallel output writing; + */ + void writeDelayedFiles(); + /** \brief * Interpolates fct to \ref solution. */ @@ -418,7 +423,7 @@ namespace AMDiS { */ virtual void deserialize(::std::istream &in); - ::std::list<FileWriterInterface*> getFileWriterList() { + ::std::vector<FileWriterInterface*> getFileWriterList() { return fileWriters_; }; @@ -497,7 +502,7 @@ namespace AMDiS { /** \brief * Writes the meshes and solution after the adaption loop. */ - ::std::list<FileWriterInterface*> fileWriters_; + ::std::vector<FileWriterInterface*> fileWriters_; /** \brief * All actions of mesh refinement are performed by refinementManager. diff --git a/AMDiS/src/ProblemTimeInterface.h b/AMDiS/src/ProblemTimeInterface.h index f248cac44dec551fa06903a9b8c7210312011d69..2f4ce23da26561b688237ac1fb2dcf6d7427b926 100644 --- a/AMDiS/src/ProblemTimeInterface.h +++ b/AMDiS/src/ProblemTimeInterface.h @@ -69,6 +69,12 @@ namespace AMDiS { */ virtual void transferInitialSolution(AdaptInfo *adaptInfo) = 0; + /** \brief + * Starts calculations from the last timestep, which can be done in parallel + * with the calculations of the current timestep; + */ + virtual void startDelayedTimestepCalculation() = 0; + /** \brief * Function that serializes the problem plus information about the iteration. */ diff --git a/AMDiS/src/ProblemVec.cc b/AMDiS/src/ProblemVec.cc index f0f20bf6ee267774f7a125c4b61af453723e920b..055b6aa670c1b317c7a11582ad3e215e42258e31 100644 --- a/AMDiS/src/ProblemVec.cc +++ b/AMDiS/src/ProblemVec.cc @@ -838,6 +838,13 @@ namespace AMDiS { #endif } + void ProblemVec::writeDelayedFiles() + { + for (int i = 0; i < static_cast<int>(fileWriters_.size()); i++) { + fileWriters_[i]->writeDelayedFiles(); + } + } + void ProblemVec::interpolInitialSolution(::std::vector<AbstractFunction<double, WorldVector<double> >*> *fct) { FUNCNAME("ProblemVec::interpolInitialSolution()"); diff --git a/AMDiS/src/ProblemVec.h b/AMDiS/src/ProblemVec.h index d42bfb6123bee854a2589365124b4f526a7a9942..4f4e77d743a2bfebd33c2327165ad70ff1892ba1 100644 --- a/AMDiS/src/ProblemVec.h +++ b/AMDiS/src/ProblemVec.h @@ -217,18 +217,24 @@ namespace AMDiS { * Returns the problem with the given number. If only one problem * is managed by this master problem, the number hasn't to be given. */ - virtual ProblemStatBase *getProblem(int number = 0) { return this; }; + virtual ProblemStatBase *getProblem(int number = 0) { + return this; + }; /** \brief * Writes output files. */ void writeFiles(AdaptInfo *adaptInfo, bool force); + /** \brief + * Startes parallel output writing; + */ + void writeDelayedFiles(); + /** \brief * Interpolates fct to \ref solution. */ - void - interpolInitialSolution(::std::vector<AbstractFunction<double, WorldVector<double> >*> *fct); + void interpolInitialSolution(::std::vector<AbstractFunction<double, WorldVector<double> >*> *fct); /** \brief * Adds an Operator to \ref A. diff --git a/AMDiS/src/Serializer.h b/AMDiS/src/Serializer.h index d623e72ad37c79b63bfcef236ff676e24886e036..23ab41a72416197aa35fb002cd3865021097432e 100644 --- a/AMDiS/src/Serializer.h +++ b/AMDiS/src/Serializer.h @@ -75,6 +75,7 @@ namespace AMDiS { MSG("problem serialized to %s \n", name_.c_str()); }; + virtual void writeDelayedFiles() {}; protected: /** \brief diff --git a/AMDiS/src/SystemVector.h b/AMDiS/src/SystemVector.h index 226f27a4da793e3ab347f0d52edfc6053e1f2d2b..b6d4b95b65cf545d170b2053a29807f6cadde5ac 100644 --- a/AMDiS/src/SystemVector.h +++ b/AMDiS/src/SystemVector.h @@ -475,7 +475,9 @@ namespace AMDiS { TEST_EXIT_DBG(size == matrix.getNumRows())("incompatible sizes\n"); TEST_EXIT_DBG(size == matrix.getNumCols())("incompatible sizes\n"); +#ifdef _OPENMP #pragma omp parallel for schedule(static, 1) +#endif for (i = 0; i < size; i++) { if (!add) result.getDOFVector(i)->set(0.0); @@ -503,7 +505,9 @@ namespace AMDiS { int size = x.getNumVectors(); int i; +#ifdef _OPENMP #pragma omp parallel for schedule(static, 1) +#endif for (i = 0; i < size; i++) { axpy(a, *(x.getDOFVector(i)), *(y.getDOFVector(i))); } diff --git a/AMDiS/src/VtkWriter.cc b/AMDiS/src/VtkWriter.cc index d934577a9466b3453d241d44751b1b8459728679..3bb833e28fb6fbef3b0d386871c89f2c2c7409f3 100644 --- a/AMDiS/src/VtkWriter.cc +++ b/AMDiS/src/VtkWriter.cc @@ -136,7 +136,9 @@ namespace AMDiS { DOFVector<double> *values; DOFVector< ::std::list<WorldVector<double> > > *dofCoords; +#ifdef _OPENMP #pragma omp critical +#endif { interpPointInd = (*dc_)[componentNo]->getInterpPointInd(); values = (*dc_)[componentNo]->getValues();