AdaptInstationary.cc 12.5 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
//
// 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.


13
14
15
16
17
18
19
20
21
#include "AdaptInstationary.h"
#include "Parameters.h"
#include "Estimator.h"
#include "ProblemIterationInterface.h"
#include "ProblemTimeInterface.h"
#include "Serializer.h"

namespace AMDiS {

Thomas Witkowski's avatar
Thomas Witkowski committed
22
  AdaptInstationary::AdaptInstationary(std::string name,
23
				       ProblemIterationInterface *problemStat,  
24
25
26
				       AdaptInfo *info,
				       ProblemTimeInterface *problemInstat,
				       AdaptInfo *initialInfo,
27
				       time_t initialTimestampSet)
28
    : AdaptBase(name, problemStat, info, problemInstat, initialInfo),
29
30
      breakWhenStable(0),
      dbgMode(false)
31
32
33
  {
    FUNCNAME("AdaptInstationary::AdaptInstationary()");

34
35
36
//     MSG("You make use of the obsolete constructor AdaptInstationary::AdaptInstationary(...)!\n");
//     MSG("Please use the constructor that uses references instead of pointers!\n");

37
38
    initConstructor(problemStat, info, initialInfo, initialTimestampSet);
 }
39

Thomas Witkowski's avatar
Thomas Witkowski committed
40

41
42
43
44
45
  AdaptInstationary::AdaptInstationary(std::string name,
				       ProblemIterationInterface &problemStat,  
				       AdaptInfo &info,
				       ProblemTimeInterface &problemInstat,
				       AdaptInfo &initialInfo,
46
				       time_t initialTimestampSet)
47
48
49
50
51
52
    : AdaptBase(name, &problemStat, &info, &problemInstat, &initialInfo),
      breakWhenStable(0),
      dbgMode(false)
  {
    FUNCNAME("AdaptInstationary::AdaptInstationary()");

53
    initConstructor(&problemStat, &info, &initialInfo, initialTimestampSet);
54
55
  }

Thomas Witkowski's avatar
Thomas Witkowski committed
56

57
58
59
  void AdaptInstationary::initConstructor(ProblemIterationInterface *problemStat,  
					  AdaptInfo *info,
					  AdaptInfo *initialInfo,
60
					  time_t initialTimestampSet)
61
  {
Thomas Witkowski's avatar
Thomas Witkowski committed
62
    initialize(name);
63

Thomas Witkowski's avatar
Thomas Witkowski committed
64
    fixedTimestep = (info->getMinTimestep() == info->getMaxTimestep());
65
66
 
    if (initialTimestampSet == 0)
Thomas Witkowski's avatar
Thomas Witkowski committed
67
      initialTimestamp = time(NULL);
68
    else
69
70
      initialTimestamp = initialTimestampSet;

71
    // Check if the problem should be deserialized because of the -rs parameter.
Thomas Witkowski's avatar
Thomas Witkowski committed
72
    std::string serializationFilename = "";
73
74
75
76
77
    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.
Thomas Witkowski's avatar
Thomas Witkowski committed
78
      MSG("Deserialization from file: %s\n", queueSerializationFilename.c_str());
79

Thomas Witkowski's avatar
Thomas Witkowski committed
80
      std::ifstream in(queueSerializationFilename.c_str());
81
82
83
      deserialize(in);
      in.close();

84
85
      info->setIsDeserialized(true);
      initialInfo->setIsDeserialized(true);
86
87
88
89
90
91
92
93
94
95
    } 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) {
Thomas Witkowski's avatar
Thomas Witkowski committed
96
	std::string serializationFilename = "";
97
98
99
100
101
102

	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());
Thomas Witkowski's avatar
Thomas Witkowski committed
103
	std::ifstream in(serializationFilename.c_str());
104
105
106
107
108
109
	deserialize(in);
	in.close();
      }
    }
  }

Thomas Witkowski's avatar
Thomas Witkowski committed
110

111
112
113
114
  AdaptInstationary::~AdaptInstationary()
  {
  }

Thomas Witkowski's avatar
Thomas Witkowski committed
115

116
117
118
119
120
  void AdaptInstationary::explicitTimeStrategy()
  {
    FUNCNAME("AdaptInstationary::explicitTimeStrategy()");

    // estimate before first adaption
Thomas Witkowski's avatar
Thomas Witkowski committed
121
    if (adaptInfo->getTime() <= adaptInfo->getStartTime())
Thomas Witkowski's avatar
Thomas Witkowski committed
122
      problemIteration->oneIteration(adaptInfo, ESTIMATE);
Thomas Witkowski's avatar
Thomas Witkowski committed
123
124


125
    // increment time
Thomas Witkowski's avatar
* Bla    
Thomas Witkowski committed
126
    adaptInfo->setTime(adaptInfo->getTime() + adaptInfo->getTimestep());
127

Thomas Witkowski's avatar
Thomas Witkowski committed
128
    problemTime->setTime(adaptInfo);
129

Thomas Witkowski's avatar
Thomas Witkowski committed
130
    INFO(info,6)("time = %e, timestep = %e\n",
Thomas Witkowski's avatar
* Bla    
Thomas Witkowski committed
131
		  adaptInfo->getTime(), adaptInfo->getTimestep());
132

Thomas Witkowski's avatar
* Bla    
Thomas Witkowski committed
133
    adaptInfo->setSpaceIteration(0);
134
135
  
    // do the iteration
Thomas Witkowski's avatar
Thomas Witkowski committed
136
137
138
    problemIteration->beginIteration(adaptInfo);
    problemIteration->oneIteration(adaptInfo, FULL_ITERATION);
    problemIteration->endIteration(adaptInfo);
139
    adaptInfo->setLastProcessedTimestep(adaptInfo->getTimestep()); 
140
141
  }

Thomas Witkowski's avatar
Thomas Witkowski committed
142

143
144
145
146
147
  void AdaptInstationary::implicitTimeStrategy()
  {
    FUNCNAME("AdaptInstationary::implicitTimeStrategy()");

    do {
Thomas Witkowski's avatar
* Bla    
Thomas Witkowski committed
148
      adaptInfo->setTime(adaptInfo->getTime() + adaptInfo->getTimestep());
Thomas Witkowski's avatar
Thomas Witkowski committed
149
      problemTime->setTime(adaptInfo);
150

Thomas Witkowski's avatar
Thomas Witkowski committed
151
152
      INFO(info,6)("time = %e, try timestep = %e\n",
		   adaptInfo->getTime(), adaptInfo->getTimestep());
153

Thomas Witkowski's avatar
Thomas Witkowski committed
154
      problemIteration->oneIteration(adaptInfo, NO_ADAPTION);
155

Thomas Witkowski's avatar
* Bla    
Thomas Witkowski committed
156
      adaptInfo->incTimestepIteration();
157
   
Thomas Witkowski's avatar
Thomas Witkowski committed
158
      if (!fixedTimestep && 
Thomas Witkowski's avatar
* Bla    
Thomas Witkowski committed
159
	  !adaptInfo->timeToleranceReached() &&
160
	  adaptInfo->getTimestepIteration() <= adaptInfo->getMaxTimestepIteration() &&
Thomas Witkowski's avatar
Thomas Witkowski committed
161
	  !(adaptInfo->getTimestep() <= adaptInfo->getMinTimestep())) {
162
163
	  
	  adaptInfo->setTime(adaptInfo->getTime() - adaptInfo->getTimestep());
Thomas Witkowski's avatar
Thomas Witkowski committed
164
	  adaptInfo->setTimestep(adaptInfo->getTimestep() * timeDelta1);
165
	  continue;
166
      }
167

168

Thomas Witkowski's avatar
* Bla    
Thomas Witkowski committed
169
      adaptInfo->setSpaceIteration(0);
170
171
172
173


      /* === Do only space iterations only if the maximum is higher than 0. === */

Thomas Witkowski's avatar
* Bla    
Thomas Witkowski committed
174
      if (adaptInfo->getMaxSpaceIteration() > 0) {
175
    
176
177
	/* === Space iterations === */
	do {
Thomas Witkowski's avatar
Thomas Witkowski committed
178
	  problemIteration->beginIteration(adaptInfo);
179
	  
Thomas Witkowski's avatar
Thomas Witkowski committed
180
181
	  if (problemIteration->oneIteration(adaptInfo, FULL_ITERATION)) {
	    if (!fixedTimestep && 
Thomas Witkowski's avatar
* Bla    
Thomas Witkowski committed
182
		!adaptInfo->timeToleranceReached() &&
Thomas Witkowski's avatar
Thomas Witkowski committed
183
184
		!(adaptInfo->getTimestep() <= adaptInfo->getMinTimestep())) {
	      adaptInfo->setTime(adaptInfo->getTime() - adaptInfo->getTimestep());
Thomas Witkowski's avatar
Thomas Witkowski committed
185
186
	      adaptInfo->setTimestep(adaptInfo->getTimestep() * timeDelta2);
	      problemIteration->endIteration(adaptInfo);
Thomas Witkowski's avatar
Thomas Witkowski committed
187
188
189
	      adaptInfo->incSpaceIteration();
	      break;
	    }	
190
191
	  }

Thomas Witkowski's avatar
* Bla    
Thomas Witkowski committed
192
	  adaptInfo->incSpaceIteration();
Thomas Witkowski's avatar
Thomas Witkowski committed
193
	  problemIteration->endIteration(adaptInfo);
194
	  
Thomas Witkowski's avatar
Thomas Witkowski committed
195
196
	} while (!adaptInfo->spaceToleranceReached() && 
		 adaptInfo->getSpaceIteration() <= adaptInfo->getMaxSpaceIteration());
197
198

      } else {
Thomas Witkowski's avatar
Thomas Witkowski committed
199
	problemIteration->endIteration(adaptInfo);
200
201
      }

202

Thomas Witkowski's avatar
* Bla    
Thomas Witkowski committed
203
    } while(!adaptInfo->timeToleranceReached() &&
Thomas Witkowski's avatar
Thomas Witkowski committed
204
	    !(adaptInfo->getTimestep() <= adaptInfo->getMinTimestep()) && 
Thomas Witkowski's avatar
* Bla    
Thomas Witkowski committed
205
	    adaptInfo->getTimestepIteration() <= adaptInfo->getMaxTimestepIteration());  
206

207
    adaptInfo->setLastProcessedTimestep(adaptInfo->getTimestep()); 
208
209
210
211

    // After successful iteration/timestep the timestep will be changed according 
    // adaption rules for next timestep. 
    // First, check for increase of timestep
Thomas Witkowski's avatar
Thomas Witkowski committed
212
213
    if (!fixedTimestep && adaptInfo->timeErrorLow()) {
      adaptInfo->setTimestep(adaptInfo->getTimestep() * timeDelta2);
214
215
216
217
218
219
220
      if (dbgMode) {
	// print information about timestep increase
      }
    } else {
      if (dbgMode) {
	std::cout << "=== ADAPT INFO DEBUG MODE ===\n";
	std::cout << " Do not increase timestep: \n";
Thomas Witkowski's avatar
Thomas Witkowski committed
221
	if (fixedTimestep)
222
	  std::cout << "   fixedTimestep = true\n";	
Thomas Witkowski's avatar
Thomas Witkowski committed
223
	if (!adaptInfo->timeErrorLow())
Thomas Witkowski's avatar
* Bla    
Thomas Witkowski committed
224
	  adaptInfo->printTimeErrorLowInfo();
225
      }
226
    }
Thomas Witkowski's avatar
Thomas Witkowski committed
227

228
    // Second, check for decrease of timestep
Thomas Witkowski's avatar
Thomas Witkowski committed
229
    if (!fixedTimestep &&
230
	!adaptInfo->timeToleranceReached() &&
Thomas Witkowski's avatar
Thomas Witkowski committed
231
232
	!(adaptInfo->getTimestep() <= adaptInfo->getMinTimestep()))
	adaptInfo->setTimestep(adaptInfo->getTimestep() * timeDelta1);    
233
234
  }

Thomas Witkowski's avatar
Thomas Witkowski committed
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265

  void AdaptInstationary::simpleAdaptiveTimeStrategy()
  {
    FUNCNAME("AdaptInstationary::explicitTimeStrategy()");

    // 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());        
    
    // 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);    
  }


266
267
  void AdaptInstationary::oneTimestep()
  {
268
    FUNCNAME("AdaptInstationary::oneTimestep()");
269

Thomas Witkowski's avatar
* Bla    
Thomas Witkowski committed
270
    adaptInfo->setTimestepIteration(0);
271

272
273
274
275
276
277
278
    switch (strategy) {
    case 0:
      explicitTimeStrategy();
      break;
    case 1:
      implicitTimeStrategy();
      break;
Thomas Witkowski's avatar
Thomas Witkowski committed
279
280
281
    case 2:
      simpleAdaptiveTimeStrategy();
      break;
282
    default:
Thomas Witkowski's avatar
Thomas Witkowski committed
283
      ERROR_EXIT("Unknown strategy = %d!\n", strategy);
284
    }
285

Thomas Witkowski's avatar
* Bla    
Thomas Witkowski committed
286
    adaptInfo->incTimestepNumber();
287
288
  }

Thomas Witkowski's avatar
Thomas Witkowski committed
289

290
291
292
293
294
  int AdaptInstationary::adapt()
  {
    FUNCNAME("AdaptInstationary::adapt()");
    int errorCode = 0;

Thomas Witkowski's avatar
* Bla    
Thomas Witkowski committed
295
    TEST_EXIT(adaptInfo->getTimestep() >= adaptInfo->getMinTimestep())
296
      ("timestep < min timestep\n");
Thomas Witkowski's avatar
* Bla    
Thomas Witkowski committed
297
    TEST_EXIT(adaptInfo->getTimestep() <= adaptInfo->getMaxTimestep())
298
299
      ("timestep > max timestep\n");

Thomas Witkowski's avatar
* Bla    
Thomas Witkowski committed
300
    TEST_EXIT(adaptInfo->getTimestep() > 0)("timestep <= 0!\n");
301

Thomas Witkowski's avatar
* Bla    
Thomas Witkowski committed
302
303
    if (adaptInfo->getTimestepNumber() == 0) {
      adaptInfo->setTime(adaptInfo->getStartTime());
Thomas Witkowski's avatar
Thomas Witkowski committed
304
305
      initialAdaptInfo->setStartTime(adaptInfo->getStartTime());
      initialAdaptInfo->setTime(adaptInfo->getStartTime());
306

Thomas Witkowski's avatar
Thomas Witkowski committed
307
      problemTime->setTime(adaptInfo);
308
309

      // initial adaption
Thomas Witkowski's avatar
Thomas Witkowski committed
310
311
      problemTime->solveInitialProblem(initialAdaptInfo);
      problemTime->transferInitialSolution(adaptInfo);
312
313
    }

Thomas Witkowski's avatar
* Bla    
Thomas Witkowski committed
314
    while (!adaptInfo->reachedEndTime()) {
Thomas Witkowski's avatar
Thomas Witkowski committed
315
      iterationTimestamp = time(NULL);
316

Thomas Witkowski's avatar
Thomas Witkowski committed
317
      problemTime->initTimestep(adaptInfo);
318
      oneTimestep();
Thomas Witkowski's avatar
Thomas Witkowski committed
319
      problemTime->closeTimestep(adaptInfo);
Thomas Witkowski's avatar
Thomas Witkowski committed
320

321
      if (breakWhenStable && (adaptInfo->getSolverIterations() == 0)) 
322
	break;
323
324
325
326
      /*     
      if (adaptInfo->forceBreak) 
	  break;
      */
327
328
329
330
331
332
333
334
335
336
337
338
      // 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;
  }

Thomas Witkowski's avatar
Thomas Witkowski committed
339

Thomas Witkowski's avatar
Thomas Witkowski committed
340
  void AdaptInstationary::initialize(std::string aName)
341
342
343
344
  {
    FUNCNAME("AdaptInstationary::initialize()");

    strategy = 0;
Thomas Witkowski's avatar
Thomas Witkowski committed
345
346
347
348
    timeDelta1 = 0.7071;
    timeDelta2 = 1.4142;
    queueRuntime = -1;
    queueSerializationFilename = "__serialized_problem.ser";
349
350

    GET_PARAMETER(0, aName + "->strategy", "%d", &strategy);
Thomas Witkowski's avatar
Thomas Witkowski committed
351
352
353
    GET_PARAMETER(0, aName + "->time delta 1", "%f", &timeDelta1);
    GET_PARAMETER(0, aName + "->time delta 2", "%f", &timeDelta2);
    GET_PARAMETER(0, aName + "->info", "%d", &info);
354
    GET_PARAMETER(0, aName + "->break when stable", "%d", &breakWhenStable);
Thomas Witkowski's avatar
Thomas Witkowski committed
355
    GET_PARAMETER(0, aName + "->queue->runtime", "%d", &queueRuntime);
Thomas Witkowski's avatar
Thomas Witkowski committed
356
    GET_PARAMETER(0, aName + "->queue->serialization filename", 
Thomas Witkowski's avatar
Thomas Witkowski committed
357
		  &queueSerializationFilename);
358
359
  }

Thomas Witkowski's avatar
Thomas Witkowski committed
360

Thomas Witkowski's avatar
Thomas Witkowski committed
361
  void AdaptInstationary::serialize(std::ostream &out)
362
363
364
  {
    FUNCNAME("AdaptInstationary::serialize()");

Thomas Witkowski's avatar
Thomas Witkowski committed
365
    problemIteration->serialize(out);
Thomas Witkowski's avatar
* Bla    
Thomas Witkowski committed
366
    adaptInfo->serialize(out);
Thomas Witkowski's avatar
Thomas Witkowski committed
367
368
    if (problemTime)
      problemTime->serialize(out);    
369
370
  }

Thomas Witkowski's avatar
Thomas Witkowski committed
371

Thomas Witkowski's avatar
Thomas Witkowski committed
372
  void AdaptInstationary::deserialize(std::istream &in)
373
374
375
  {
    FUNCNAME("AdaptInstationary::deserialize()");

Thomas Witkowski's avatar
Thomas Witkowski committed
376
    problemIteration->deserialize(in);
Thomas Witkowski's avatar
* Bla    
Thomas Witkowski committed
377
    adaptInfo->deserialize(in);
Thomas Witkowski's avatar
Thomas Witkowski committed
378
379
    if (problemTime)
      problemTime->deserialize(in);    
380
381
382
383
384
385
  }


  bool AdaptInstationary::checkQueueRuntime()
  {
    // If there is no time limited runtime queue, there is also nothing to check.
Thomas Witkowski's avatar
Thomas Witkowski committed
386
    if (queueRuntime == -1) {
387
388
389
390
391
392
      return false;
    }
    // Get the current time.
    time_t currentTimestamp = time(NULL);

    // Update list with the last iteration runtimes.
Thomas Witkowski's avatar
Thomas Witkowski committed
393
    lastIterationsDuration.push(currentTimestamp - iterationTimestamp);
394
    // The list should not contain more than 5 elements. If so, delete the oldest one.
Thomas Witkowski's avatar
Thomas Witkowski committed
395
396
    if (lastIterationsDuration.size() > 5)
      lastIterationsDuration.pop();    
397
398

    // Calculate the avarage of the last iterations.
Thomas Witkowski's avatar
Thomas Witkowski committed
399
    std::queue<int> tmpQueue = lastIterationsDuration;
400
401
    int avrgLastIterations = 0;
    while (!tmpQueue.empty()) {
402
403
	avrgLastIterations += tmpQueue.front();
	tmpQueue.pop();
404
    } 
Thomas Witkowski's avatar
Thomas Witkowski committed
405
    avrgLastIterations /= lastIterationsDuration.size();
406

407
    // Check if there is enough time for a further iteration.
Thomas Witkowski's avatar
Thomas Witkowski committed
408
409
    if (initialTimestamp + queueRuntime - currentTimestamp < avrgLastIterations * 2) {
      std::ofstream out(queueSerializationFilename.c_str());
410
411
412
413
414
415
416
417
418
419
      serialize(out);
      out.close();

      return true;
    }

    return false;
  }

}