-
Thomas Witkowski authoredThomas Witkowski authored
AdaptInstationary.cc 9.73 KiB
#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(std::string name,
ProblemIterationInterface *problemStat,
AdaptInfo *info,
ProblemTimeInterface *problemInstat,
AdaptInfo *initialInfo,
time_t initialTimestamp)
: AdaptBase(name, problemStat, info, problemInstat, initialInfo),
breakWhenStable(0),
dbgMode(false)
{
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);
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();
}
}
}
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->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;
}
}
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;
}
}