// // Software License for AMDiS // // Copyright (c) 2010 Dresden University of Technology // All rights reserved. // Authors: Simon Vey, Thomas Witkowski et al. // // This file is part of AMDiS // // See also license.opensource.txt in the distribution. #include "AdaptInstationary.h" #include "Parameters.h" #include "Estimator.h" #include "ProblemIterationInterface.h" #include "ProblemTimeInterface.h" #include "Serializer.h" #if HAVE_PARALLEL_DOMAIN_AMDIS #include "parallel/MeshDistributor.h" #include #endif namespace AMDiS { AdaptInstationary::AdaptInstationary(std::string name, ProblemIterationInterface *problemStat, AdaptInfo *info, ProblemTimeInterface *problemInstat, AdaptInfo *initialInfo, time_t initialTimestampSet) : AdaptBase(name, problemStat, info, problemInstat, initialInfo), breakWhenStable(0), dbgMode(false) { FUNCNAME("AdaptInstationary::AdaptInstationary()"); MSG("You make use of the obsolete constructor AdaptInstationary::AdaptInstationary(...)!\n"); MSG("Please use the constructor that uses references instead of pointers!\n"); initConstructor(problemStat, info, initialInfo, initialTimestampSet); } AdaptInstationary::AdaptInstationary(std::string name, ProblemIterationInterface &problemStat, AdaptInfo &info, ProblemTimeInterface &problemInstat, AdaptInfo &initialInfo, time_t initialTimestampSet) : AdaptBase(name, &problemStat, &info, &problemInstat, &initialInfo), breakWhenStable(0), dbgMode(false) { FUNCNAME("AdaptInstationary::AdaptInstationary()"); initConstructor(&problemStat, &info, &initialInfo, initialTimestampSet); } void AdaptInstationary::initConstructor(ProblemIterationInterface *problemStat, AdaptInfo *info, AdaptInfo *initialInfo, time_t initialTimestampSet) { initialize(name); fixedTimestep = (info->getMinTimestep() == info->getMaxTimestep()); if (initialTimestampSet == 0) initialTimestamp = time(NULL); else initialTimestamp = initialTimestampSet; // Check if the problem should be deserialized because of the -rs parameter. std::string serializationFilename = ""; Parameters::get("argv->rs", serializationFilename); if (serializationFilename.compare("")) { // The value of the -rs argument is ignored, because we want to use the // serialization file mentioned in the used init file. MSG("Deserialization from file: %s\n", queueSerializationFilename.c_str()); std::ifstream in(queueSerializationFilename.c_str()); deserialize(in); in.close(); info->setIsDeserialized(true); initialInfo->setIsDeserialized(true); } else { int readSerialization = 0; int readSerializationWithAdaptInfo = 0; Parameters::get((*problemStat).getName() + "->input->read serialization", readSerialization); Parameters::get((*problemStat).getName() + "->input->serialization with adaptinfo", readSerializationWithAdaptInfo); if (readSerialization && readSerializationWithAdaptInfo) { std::string serializationFilename = ""; Parameters::get((*problemStat).getName() + "->input->serialization filename", serializationFilename); TEST_EXIT(serializationFilename != "")("no serialization file\n"); MSG("Deserialization with AdaptInfo from file: %s\n", serializationFilename.c_str()); std::ifstream in(serializationFilename.c_str()); deserialize(in); in.close(); } } } void AdaptInstationary::explicitTimeStrategy() { FUNCNAME("AdaptInstationary::explicitTimeStrategy()"); // estimate before first adaption if (adaptInfo->getTime() <= adaptInfo->getStartTime()) problemIteration->oneIteration(adaptInfo, ESTIMATE); // increment time adaptInfo->setTime(adaptInfo->getTime() + adaptInfo->getTimestep()); problemTime->setTime(adaptInfo); INFO(info, 6)("time = %e, timestep = %e\n", adaptInfo->getTime(), adaptInfo->getTimestep()); adaptInfo->setSpaceIteration(0); // do the iteration problemIteration->beginIteration(adaptInfo); problemIteration->oneIteration(adaptInfo, FULL_ITERATION); problemIteration->endIteration(adaptInfo); adaptInfo->setLastProcessedTimestep(adaptInfo->getTimestep()); } void AdaptInstationary::implicitTimeStrategy() { FUNCNAME("AdaptInstationary::implicitTimeStrategy()"); do { adaptInfo->setTime(adaptInfo->getTime() + adaptInfo->getTimestep()); problemTime->setTime(adaptInfo); INFO(info,6)("time = %e, try timestep = %e\n", adaptInfo->getTime(), adaptInfo->getTimestep()); problemIteration->oneIteration(adaptInfo, NO_ADAPTION); adaptInfo->incTimestepIteration(); if (!fixedTimestep && !adaptInfo->timeToleranceReached() && adaptInfo->getTimestepIteration() <= adaptInfo->getMaxTimestepIteration() && !(adaptInfo->getTimestep() <= adaptInfo->getMinTimestep())) { adaptInfo->setTime(adaptInfo->getTime() - adaptInfo->getTimestep()); adaptInfo->setTimestep(adaptInfo->getTimestep() * timeDelta1); continue; } adaptInfo->setSpaceIteration(0); // === Do only space iterations only if the maximum is higher than 0. === if (adaptInfo->getMaxSpaceIteration() > 0) { // === Space iterations. === do { problemIteration->beginIteration(adaptInfo); if (problemIteration->oneIteration(adaptInfo, FULL_ITERATION)) { if (!fixedTimestep && !adaptInfo->timeToleranceReached() && !(adaptInfo->getTimestep() <= adaptInfo->getMinTimestep())) { adaptInfo->setTime(adaptInfo->getTime() - adaptInfo->getTimestep()); adaptInfo->setTimestep(adaptInfo->getTimestep() * timeDelta2); problemIteration->endIteration(adaptInfo); adaptInfo->incSpaceIteration(); break; } } adaptInfo->incSpaceIteration(); problemIteration->endIteration(adaptInfo); } while (!adaptInfo->spaceToleranceReached() && adaptInfo->getSpaceIteration() <= adaptInfo->getMaxSpaceIteration()); } else { problemIteration->endIteration(adaptInfo); } } while(!adaptInfo->timeToleranceReached() && !(adaptInfo->getTimestep() <= adaptInfo->getMinTimestep()) && adaptInfo->getTimestepIteration() <= adaptInfo->getMaxTimestepIteration()); adaptInfo->setLastProcessedTimestep(adaptInfo->getTimestep()); // After successful iteration/timestep the timestep will be changed according // adaption rules for next timestep. // First, check for increase of timestep if (!fixedTimestep && adaptInfo->timeErrorLow()) { adaptInfo->setTimestep(adaptInfo->getTimestep() * timeDelta2); if (dbgMode) { // print information about timestep increase } } else { if (dbgMode) { std::cout << "=== ADAPT INFO DEBUG MODE ===\n"; std::cout << " Do not increase timestep: \n"; if (fixedTimestep) std::cout << " fixedTimestep = true\n"; if (!adaptInfo->timeErrorLow()) adaptInfo->printTimeErrorLowInfo(); } } // Second, check for decrease of timestep if (!fixedTimestep && !adaptInfo->timeToleranceReached() && !(adaptInfo->getTimestep() <= adaptInfo->getMinTimestep())) adaptInfo->setTimestep(adaptInfo->getTimestep() * timeDelta1); } void AdaptInstationary::simpleAdaptiveTimeStrategy() { FUNCNAME("AdaptInstationary::simpleAdaptiveTimeStrategy()"); // estimate before first adaption if (adaptInfo->getTime() <= adaptInfo->getStartTime()) problemIteration->oneIteration(adaptInfo, ESTIMATE); adaptInfo->setTime(adaptInfo->getTime() + adaptInfo->getTimestep()); problemTime->setTime(adaptInfo); INFO(info,6)("time = %e, timestep = %e\n", adaptInfo->getTime(), adaptInfo->getTimestep()); problemIteration->oneIteration(adaptInfo, FULL_ITERATION); adaptInfo->setLastProcessedTimestep(adaptInfo->getTimestep()); if (dbgMode) { std::cout << "=== ADAPT INFO DEBUG MODE ===\n"; std::cout << "=== in simpleAdaptiveTimeStrategy() ===\n"; adaptInfo->printTimeErrorLowInfo(); } // First, check for increase of timestep if (!fixedTimestep && adaptInfo->timeErrorLow()) adaptInfo->setTimestep(adaptInfo->getTimestep() * timeDelta2); // Second, check for decrease of timestep if (!fixedTimestep && !adaptInfo->timeToleranceReached() && !(adaptInfo->getTimestep() <= adaptInfo->getMinTimestep())) adaptInfo->setTimestep(adaptInfo->getTimestep() * timeDelta1); } void AdaptInstationary::oneTimestep() { FUNCNAME("AdaptInstationary::oneTimestep()"); MSG("ONE TIMESTEP!\n"); adaptInfo->setTimestepIteration(0); switch (strategy) { case 0: explicitTimeStrategy(); break; case 1: implicitTimeStrategy(); break; case 2: simpleAdaptiveTimeStrategy(); break; default: ERROR_EXIT("Unknown strategy = %d!\n", strategy); } adaptInfo->incTimestepNumber(); } int AdaptInstationary::adapt() { FUNCNAME("AdaptInstationary::adapt()"); int errorCode = 0; TEST_EXIT(adaptInfo->getTimestep() >= adaptInfo->getMinTimestep()) ("timestep < min timestep\n"); TEST_EXIT(adaptInfo->getTimestep() <= adaptInfo->getMaxTimestep()) ("timestep > max timestep\n"); TEST_EXIT(adaptInfo->getTimestep() > 0)("timestep <= 0!\n"); #if HAVE_PARALLEL_DOMAIN_AMDIS MeshDistributor::globalMeshDistributor->initParallelization(); #endif if (adaptInfo->getTimestepNumber() == 0) { adaptInfo->setTime(adaptInfo->getStartTime()); initialAdaptInfo->setStartTime(adaptInfo->getStartTime()); initialAdaptInfo->setTime(adaptInfo->getStartTime()); problemTime->setTime(adaptInfo); // initial adaption problemTime->solveInitialProblem(initialAdaptInfo); problemTime->transferInitialSolution(adaptInfo); } while (!adaptInfo->reachedEndTime()) { iterationTimestamp = time(NULL); problemTime->initTimestep(adaptInfo); oneTimestep(); problemTime->closeTimestep(adaptInfo); if (breakWhenStable && (adaptInfo->getSolverIterations() == 0)) break; // Check if there is a runtime limitation. If there is a runtime limitation // and there is no more time for a next adaption loop, than return the error // code for rescheduling the problem and break the adaption loop. if (checkQueueRuntime()) { errorCode = RescheduleErrorCode; break; } } #ifdef HAVE_PARALLEL_DOMAIN_AMDIS MeshDistributor::globalMeshDistributor->exitParallelization(); PetscFinalize(); #endif return errorCode; } void AdaptInstationary::initialize(std::string aName) { FUNCNAME("AdaptInstationary::initialize()"); strategy = 0; timeDelta1 = 0.7071; timeDelta2 = 1.4142; queueRuntime = -1; queueSerializationFilename = "__serialized_problem.ser"; Parameters::get(aName + "->strategy", strategy); Parameters::get(aName + "->time delta 1", timeDelta1); Parameters::get(aName + "->time delta 2", timeDelta2); Parameters::get(aName + "->info", info); Parameters::get(aName + "->break when stable", breakWhenStable); Parameters::get(aName + "->time adaptivity debug mode", dbgMode); Parameters::get(aName + "->queue->runtime", queueRuntime); Parameters::get(aName + "->queue->serialization filename", queueSerializationFilename); } void AdaptInstationary::serialize(std::ostream &out) { FUNCNAME("AdaptInstationary::serialize()"); SerUtil::serialize(out, amdisRevisionNumber); problemIteration->serialize(out); adaptInfo->serialize(out); if (problemTime) problemTime->serialize(out); } void AdaptInstationary::deserialize(std::istream &in) { FUNCNAME("AdaptInstationary::deserialize()"); problemIteration->deserialize(in); adaptInfo->deserialize(in); if (problemTime) problemTime->deserialize(in); } bool AdaptInstationary::checkQueueRuntime() { // If there is no time limited runtime queue, there is also nothing to check. if (queueRuntime == -1) { return false; } // Get the current time. time_t currentTimestamp = time(NULL); // Update list with the last iteration runtimes. lastIterationsDuration.push(currentTimestamp - iterationTimestamp); // The list should not contain more than 5 elements. If so, delete the oldest one. if (lastIterationsDuration.size() > 5) lastIterationsDuration.pop(); // Calculate the avarage of the last iterations. std::queue tmpQueue = lastIterationsDuration; int avrgLastIterations = 0; while (!tmpQueue.empty()) { avrgLastIterations += tmpQueue.front(); tmpQueue.pop(); } avrgLastIterations /= lastIterationsDuration.size(); // Check if there is enough time for a further iteration. if (initialTimestamp + queueRuntime - currentTimestamp < avrgLastIterations * 2) { std::ofstream out(queueSerializationFilename.c_str()); serialize(out); out.close(); return true; } return false; } }