AdaptInstationary.cc 9.63 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
#include "AdaptInstationary.h"
#include "Parameters.h"
#include "Estimator.h"
#include "TecPlotWriter.h"
#include "ProblemIterationInterface.h"
#include "ProblemTimeInterface.h"
#include "Serializer.h"

namespace AMDiS {

11
  AdaptInstationary::AdaptInstationary(const char *name,
12
				       ProblemIterationInterface *problemStat,  
13
14
15
16
				       AdaptInfo *info,
				       ProblemTimeInterface *problemInstat,
				       AdaptInfo *initialInfo,
				       time_t initialTimestamp)
17
    : AdaptBase(name, problemStat, info, problemInstat, initialInfo),
18
      breakWhenStable(0)
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
  {
    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();

45
46
      info->setIsDeserialized(true);
      initialInfo->setIsDeserialized(true);
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
    } 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
80
81
    if (adaptInfo_->getTime() <= adaptInfo_->getStartTime()) {
      problemIteration_->oneIteration(adaptInfo_, ESTIMATE);
82
83
84
    }

    // increment time
85
    adaptInfo_->setTime(adaptInfo_->getTime() + adaptInfo_->getTimestep());
86

87
    problemTime_->setTime(adaptInfo_);
88
89

    INFO(info_,6)("time = %e, timestep = %e\n",
90
		  adaptInfo_->getTime(), adaptInfo_->getTimestep());
91

92
    adaptInfo_->setSpaceIteration(0);
93
94
  
    // do the iteration
95
96
97
    problemIteration_->beginIteration(adaptInfo_);
    problemIteration_->oneIteration(adaptInfo_, FULL_ITERATION);
    problemIteration_->endIteration(adaptInfo_);
98
99
100
101
102
103
104
  }

  void AdaptInstationary::implicitTimeStrategy()
  {
    FUNCNAME("AdaptInstationary::implicitTimeStrategy()");

    do {
105
106
      adaptInfo_->setTime(adaptInfo_->getTime() + adaptInfo_->getTimestep());
      problemTime_->setTime(adaptInfo_);
107
108

      INFO(info_,6)("time = %e, try timestep = %e\n",
109
		    adaptInfo_->getTime(), adaptInfo_->getTimestep());
110
    
111
      problemIteration_->oneIteration(adaptInfo_, NO_ADAPTION);
112

113
      adaptInfo_->incTimestepIteration();
114

115
      if (!fixedTimestep_ && 
116
117
	 !adaptInfo_->timeToleranceReached() &&
	 !adaptInfo_->getTimestep() <= adaptInfo_->getMinTimestep()) 
118
	{
119
120
	  adaptInfo_->setTime(adaptInfo_->getTime() - adaptInfo_->getTimestep());
	  adaptInfo_->setTimestep(adaptInfo_->getTimestep() * time_delta_1);
121
122
123
	  continue;
	}

124
      adaptInfo_->setSpaceIteration(0);
125
126
    
      do {
127
	problemIteration_->beginIteration(adaptInfo_);
128

129
	if (problemIteration_->oneIteration(adaptInfo_, FULL_ITERATION)) {
130
	  if (!fixedTimestep_ && 
131
132
	     !adaptInfo_->timeToleranceReached() &&
	     !adaptInfo_->getTimestep() <= adaptInfo_->getMinTimestep()) 
133
	    {
134
135
136
137
	      adaptInfo_->setTime(adaptInfo_->getTime() - adaptInfo_->getTimestep());
	      adaptInfo_->setTimestep(adaptInfo_->getTimestep() * time_delta_1);
	      problemIteration_->endIteration(adaptInfo_);
	      adaptInfo_->incSpaceIteration();
138
139
140
141
	      break;
	    }	
	}

142
143
	adaptInfo_->incSpaceIteration();
	problemIteration_->endIteration(adaptInfo_);
144

145
146
147
148
149
      } while(!adaptInfo_->spaceToleranceReached() && 
	      adaptInfo_->getSpaceIteration() <= adaptInfo_->getMaxSpaceIteration());
    } while(!adaptInfo_->timeToleranceReached() &&
	    !adaptInfo_->getTimestep() <= adaptInfo_->getMinTimestep() && 
	    adaptInfo_->getTimestepIteration() <= adaptInfo_->getMaxTimestepIteration());  
150

151
152
    if (!fixedTimestep_ && adaptInfo_->timeErrorLow()) {
      adaptInfo_->setTimestep(adaptInfo_->getTimestep() *time_delta_2);
153
154
155
156
157
158
159
    }
  }

  void AdaptInstationary::oneTimestep()
  {
    FUNCNAME("AdaptInstationary::oneTimestep");

160
    adaptInfo_->setTimestepIteration(0);
161
162
163
164
165
166
167
168
169
170
171
172
173
174

    switch(strategy)
      {
      case 0:
	explicitTimeStrategy();
	break;
      case 1:
	implicitTimeStrategy();
	break;
      default:
	MSG("unknown strategy = %d; use explicit strategy\n", strategy);
	explicitTimeStrategy();
      }

175
    adaptInfo_->incTimestepNumber();
176
177
178
179
180
181
182
183
  }

  int AdaptInstationary::adapt()
  {
    FUNCNAME("AdaptInstationary::adapt()");

    int errorCode = 0;

184
    TEST_EXIT(adaptInfo_->getTimestep() >= adaptInfo_->getMinTimestep())
185
      ("timestep < min timestep\n");
186
    TEST_EXIT(adaptInfo_->getTimestep() <= adaptInfo_->getMaxTimestep())
187
188
      ("timestep > max timestep\n");

189
    TEST_EXIT(adaptInfo_->getTimestep() > 0)("timestep <= 0!\n");
190

191
192
193
194
    if (adaptInfo_->getTimestepNumber() == 0) {
      adaptInfo_->setTime(adaptInfo_->getStartTime());
      initialAdaptInfo_->setStartTime(adaptInfo_->getStartTime());
      initialAdaptInfo_->setTime(adaptInfo_->getStartTime());
195

196
      problemTime_->setTime(adaptInfo_);
197
198
199

      // initial adaption
      problemTime_->solveInitialProblem(initialAdaptInfo_);
200
      problemTime_->transferInitialSolution(adaptInfo_);
201
202
    }

203
    while (adaptInfo_->getTime() < adaptInfo_->getEndTime() - DBL_TOL) {
204
205
      iterationTimestamp_ = time(NULL);

206
      problemTime_->initTimestep(adaptInfo_);
Thomas Witkowski's avatar
Thomas Witkowski committed
207

Thomas Witkowski's avatar
Thomas Witkowski committed
208
209
210
211
#ifdef _OPENMP
      if (problemTime_->existsDelayedCalculation()) {
#pragma omp parallel sections num_threads(2)
	{
Thomas Witkowski's avatar
Thomas Witkowski committed
212
#pragma omp section
Thomas Witkowski's avatar
Thomas Witkowski committed
213
	  problemTime_->startDelayedTimestepCalculation();
Thomas Witkowski's avatar
Thomas Witkowski committed
214
215

#pragma omp section
Thomas Witkowski's avatar
Thomas Witkowski committed
216
217
218
	  oneTimestep();
	}
      } else {
Thomas Witkowski's avatar
Thomas Witkowski committed
219
220
	oneTimestep();
      }
Thomas Witkowski's avatar
Thomas Witkowski committed
221
222
#else     
      problemTime_->startDelayedTimestepCalculation();
223
      oneTimestep();
Thomas Witkowski's avatar
Thomas Witkowski committed
224
#endif
Thomas Witkowski's avatar
Thomas Witkowski committed
225

226
      problemTime_->closeTimestep(adaptInfo_);
227

228
      if (breakWhenStable && (adaptInfo_->getSolverIterations() == 0)) {
229
230
231
232
233
234
235
236
237
238
239
240
	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;
      }
    }

Thomas Witkowski's avatar
Thomas Witkowski committed
241
242
    problemTime_->startDelayedTimestepCalculation();

243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
    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);
272
    adaptInfo_->serialize(out);
273
274
275
276
277
278
279
280
281
282
    if (problemTime_) {
      problemTime_->serialize(out);
    }
  }

  void AdaptInstationary::deserialize(::std::istream &in)
  {
    FUNCNAME("AdaptInstationary::deserialize()");

    problemIteration_->deserialize(in);
283
    adaptInfo_->deserialize(in);
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
    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.
301
    lastIterationsDuration_.push(currentTimestamp - iterationTimestamp_);
302
    // The list should not contain more than 5 elements. If so, delete the oldest one.
303
304
    if (lastIterationsDuration_.size() > 5) {
      lastIterationsDuration_.pop();
305
306
307
    }

    // Calculate the avarage of the last iterations.
308
    ::std::queue<int> tmpQueue = lastIterationsDuration_;
309
310
311
312
313
    int avrgLastIterations = 0;
    while (!tmpQueue.empty()) {
      avrgLastIterations += tmpQueue.front();
      tmpQueue.pop();
    } 
314
    avrgLastIterations /= lastIterationsDuration_.size();
315
316
317
318
319
320
321
322
323
324
325
326
327
328
    
    // 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;
  }

}