#include "AdaptInstationary.h" #include "Parameters.h" #include "Estimator.h" #include "TecPlotWriter.h" #include "ProblemIterationInterface.h" #include "ProblemTimeInterface.h" #include "Serializer.h" namespace AMDiS { AdaptInstationary::AdaptInstationary(const char *name, ProblemIterationInterface *problemStat, AdaptInfo *info, ProblemTimeInterface *problemInstat, AdaptInfo *initialInfo, time_t initialTimestamp) : AdaptBase(name, problemStat, info, problemInstat, initialInfo), breakWhenStable(0) { FUNCNAME("AdaptInstationary::AdaptInstationary()"); initialize(name_); fixedTimestep_ = (info->getMinTimestep() == info->getMaxTimestep()); if (initialTimestamp == 0) { initialTimestamp_ = time(NULL); } else { initialTimestamp_ = initialTimestamp; } // Check if the problem should be deserialized because of the -rs parameter. std::string serializationFilename = ""; GET_PARAMETER(0, "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; GET_PARAMETER(0, (*problemStat).getName() + "->input->read serialization", "%d", &readSerialization); GET_PARAMETER(0, (*problemStat).getName() + "->input->serialization with adaptinfo", "%d", &readSerializationWithAdaptInfo); if (readSerialization && readSerializationWithAdaptInfo) { std::string serializationFilename = ""; GET_PARAMETER(0, (*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(); } } } AdaptInstationary::~AdaptInstationary() { } 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_); } 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_->getTimestep() <= adaptInfo_->getMinTimestep()) { adaptInfo_->setTime(adaptInfo_->getTime() - adaptInfo_->getTimestep()); adaptInfo_->setTimestep(adaptInfo_->getTimestep() * time_delta_1); 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() * time_delta_1); 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()); if (!fixedTimestep_ && adaptInfo_->timeErrorLow()) { adaptInfo_->setTimestep(adaptInfo_->getTimestep() *time_delta_2); } } void AdaptInstationary::oneTimestep() { FUNCNAME("AdaptInstationary::oneTimestep"); adaptInfo_->setTimestepIteration(0); switch(strategy) { case 0: explicitTimeStrategy(); break; case 1: implicitTimeStrategy(); break; default: MSG("unknown strategy = %d; use explicit strategy\n", strategy); explicitTimeStrategy(); } 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 (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_->getTime() < adaptInfo_->getEndTime() - DBL_TOL) { 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; } } return errorCode; } void AdaptInstationary::initialize(const std::string& aName) { FUNCNAME("AdaptInstationary::initialize()"); strategy = 0; time_delta_1 = 0.7071; time_delta_2 = 1.4142; queueRuntime_ = -1; queueSerializationFilename_ = "__serialized_problem.ser"; GET_PARAMETER(0, aName + "->strategy", "%d", &strategy); GET_PARAMETER(0, aName + "->time delta 1", "%f", &time_delta_1); GET_PARAMETER(0, aName + "->time delta 2", "%f", &time_delta_2); GET_PARAMETER(0, aName + "->info", "%d", &info_); GET_PARAMETER(0, aName + "->break when stable", "%d", &breakWhenStable); GET_PARAMETER(0, aName + "->queue->runtime", "%d", &queueRuntime_); GET_PARAMETER(0, aName + "->queue->serialization filename", &queueSerializationFilename_); return; } void AdaptInstationary::serialize(std::ostream &out) { FUNCNAME("AdaptInstationary::serialize()"); 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<int> 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; } }