AdaptInstationary.cc 12.7 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
#include "AdaptInstationary.h"
#include "Parameters.h"
#include "Estimator.h"
#include "ProblemIterationInterface.h"
#include "ProblemTimeInterface.h"
#include "Serializer.h"

20
21
22
23
24
#if HAVE_PARALLEL_DOMAIN_AMDIS
#include "parallel/MeshDistributor.h"
#include <petsc.h>
#endif

25
26
namespace AMDiS {

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

39
40
    MSG("You make use of the obsolete constructor AdaptInstationary::AdaptInstationary(...)!\n");
    MSG("Please use the constructor that uses references instead of pointers!\n");
41

42
43
    initConstructor(problemStat, info, initialInfo, initialTimestampSet);
 }
44

Thomas Witkowski's avatar
Thomas Witkowski committed
45

46
47
48
49
50
  AdaptInstationary::AdaptInstationary(std::string name,
				       ProblemIterationInterface &problemStat,  
				       AdaptInfo &info,
				       ProblemTimeInterface &problemInstat,
				       AdaptInfo &initialInfo,
51
				       time_t initialTimestampSet)
52
53
54
55
56
57
    : AdaptBase(name, &problemStat, &info, &problemInstat, &initialInfo),
      breakWhenStable(0),
      dbgMode(false)
  {
    FUNCNAME("AdaptInstationary::AdaptInstationary()");

58
    initConstructor(&problemStat, &info, &initialInfo, initialTimestampSet);
59
60
  }

Thomas Witkowski's avatar
Thomas Witkowski committed
61

62
63
64
  void AdaptInstationary::initConstructor(ProblemIterationInterface *problemStat,  
					  AdaptInfo *info,
					  AdaptInfo *initialInfo,
65
					  time_t initialTimestampSet)
66
  {
Thomas Witkowski's avatar
Thomas Witkowski committed
67
    initialize(name);
68

Thomas Witkowski's avatar
Thomas Witkowski committed
69
    fixedTimestep = (info->getMinTimestep() == info->getMaxTimestep());
70
71
 
    if (initialTimestampSet == 0)
Thomas Witkowski's avatar
Thomas Witkowski committed
72
      initialTimestamp = time(NULL);
73
    else
74
75
      initialTimestamp = initialTimestampSet;

76
    // Check if the problem should be deserialized because of the -rs parameter.
Thomas Witkowski's avatar
Thomas Witkowski committed
77
    std::string serializationFilename = "";
78
    Parameters::get("argv->rs", serializationFilename);
79
80
81
82

    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
83
      MSG("Deserialization from file: %s\n", queueSerializationFilename.c_str());
84

Thomas Witkowski's avatar
Thomas Witkowski committed
85
      std::ifstream in(queueSerializationFilename.c_str());
86
87
88
      deserialize(in);
      in.close();

89
90
      info->setIsDeserialized(true);
      initialInfo->setIsDeserialized(true);
91
92
93
94
    } else {
      int readSerialization = 0;
      int readSerializationWithAdaptInfo = 0;

95
96
97
98
      Parameters::get((*problemStat).getName() + "->input->read serialization",
		      readSerialization);
      Parameters::get((*problemStat).getName() + "->input->serialization with adaptinfo",
		      readSerializationWithAdaptInfo);
99
100

      if (readSerialization && readSerializationWithAdaptInfo) {
Thomas Witkowski's avatar
Thomas Witkowski committed
101
	std::string serializationFilename = "";
102

103
104
	Parameters::get((*problemStat).getName() + "->input->serialization filename", 
			serializationFilename);
105
106
107
	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
108
	std::ifstream in(serializationFilename.c_str());
109
110
111
112
113
114
	deserialize(in);
	in.close();
      }
    }
  }

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

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
164
165
  
	adaptInfo->setTime(adaptInfo->getTime() - adaptInfo->getTimestep());
	adaptInfo->setTimestep(adaptInfo->getTimestep() * timeDelta1);
	continue;
166
      }
167

168

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


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

Thomas Witkowski's avatar
* Bla    
Thomas Witkowski committed
174
      if (adaptInfo->getMaxSpaceIteration() > 0) {
175
    
176
	// === Space iterations. ===
177
	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

270
271
    MSG("ONE TIMESTEP!\n");

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

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

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

Thomas Witkowski's avatar
Thomas Witkowski committed
291

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

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

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

304
305
306
307
#if HAVE_PARALLEL_DOMAIN_AMDIS
    MeshDistributor::globalMeshDistributor->initParallelization(); 
#endif

Thomas Witkowski's avatar
* Bla    
Thomas Witkowski committed
308
309
    if (adaptInfo->getTimestepNumber() == 0) {
      adaptInfo->setTime(adaptInfo->getStartTime());
Thomas Witkowski's avatar
Thomas Witkowski committed
310
311
      initialAdaptInfo->setStartTime(adaptInfo->getStartTime());
      initialAdaptInfo->setTime(adaptInfo->getStartTime());
312

Thomas Witkowski's avatar
Thomas Witkowski committed
313
      problemTime->setTime(adaptInfo);
314
315

      // initial adaption
Thomas Witkowski's avatar
Thomas Witkowski committed
316
317
      problemTime->solveInitialProblem(initialAdaptInfo);
      problemTime->transferInitialSolution(adaptInfo);
318
319
    }

Thomas Witkowski's avatar
* Bla    
Thomas Witkowski committed
320
    while (!adaptInfo->reachedEndTime()) {
Thomas Witkowski's avatar
Thomas Witkowski committed
321
      iterationTimestamp = time(NULL);
322

Thomas Witkowski's avatar
Thomas Witkowski committed
323
      problemTime->initTimestep(adaptInfo);
324
      oneTimestep();
Thomas Witkowski's avatar
Thomas Witkowski committed
325
      problemTime->closeTimestep(adaptInfo);
Thomas Witkowski's avatar
Thomas Witkowski committed
326

327
      if (breakWhenStable && (adaptInfo->getSolverIterations() == 0)) 
328
	break;
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;
      }
    }

339
340
341
342
343
#ifdef HAVE_PARALLEL_DOMAIN_AMDIS
    MeshDistributor::globalMeshDistributor->exitParallelization();
    PetscFinalize();
#endif

344
345
346
    return errorCode;
  }

Thomas Witkowski's avatar
Thomas Witkowski committed
347

Thomas Witkowski's avatar
Thomas Witkowski committed
348
  void AdaptInstationary::initialize(std::string aName)
349
350
351
352
  {
    FUNCNAME("AdaptInstationary::initialize()");

    strategy = 0;
Thomas Witkowski's avatar
Thomas Witkowski committed
353
354
355
356
    timeDelta1 = 0.7071;
    timeDelta2 = 1.4142;
    queueRuntime = -1;
    queueSerializationFilename = "__serialized_problem.ser";
357

358
359
360
361
362
363
364
365
    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 + "->queue->runtime", queueRuntime);
    Parameters::get(aName + "->queue->serialization filename", 
		    queueSerializationFilename);
366
367
  }

Thomas Witkowski's avatar
Thomas Witkowski committed
368

Thomas Witkowski's avatar
Thomas Witkowski committed
369
  void AdaptInstationary::serialize(std::ostream &out)
370
371
372
  {
    FUNCNAME("AdaptInstationary::serialize()");

373
    SerUtil::serialize(out, amdisRevisionNumber);
Thomas Witkowski's avatar
Thomas Witkowski committed
374
    problemIteration->serialize(out);
Thomas Witkowski's avatar
* Bla    
Thomas Witkowski committed
375
    adaptInfo->serialize(out);
Thomas Witkowski's avatar
Thomas Witkowski committed
376
377
    if (problemTime)
      problemTime->serialize(out);    
378
379
  }

Thomas Witkowski's avatar
Thomas Witkowski committed
380

Thomas Witkowski's avatar
Thomas Witkowski committed
381
  void AdaptInstationary::deserialize(std::istream &in)
382
383
384
  {
    FUNCNAME("AdaptInstationary::deserialize()");

Thomas Witkowski's avatar
Thomas Witkowski committed
385
    problemIteration->deserialize(in);
Thomas Witkowski's avatar
* Bla    
Thomas Witkowski committed
386
    adaptInfo->deserialize(in);
Thomas Witkowski's avatar
Thomas Witkowski committed
387
388
    if (problemTime)
      problemTime->deserialize(in);    
389
390
391
392
393
394
  }


  bool AdaptInstationary::checkQueueRuntime()
  {
    // If there is no time limited runtime queue, there is also nothing to check.
Thomas Witkowski's avatar
Thomas Witkowski committed
395
    if (queueRuntime == -1) {
396
397
398
399
400
401
      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
402
    lastIterationsDuration.push(currentTimestamp - iterationTimestamp);
403
    // The list should not contain more than 5 elements. If so, delete the oldest one.
Thomas Witkowski's avatar
Thomas Witkowski committed
404
405
    if (lastIterationsDuration.size() > 5)
      lastIterationsDuration.pop();    
406
407

    // Calculate the avarage of the last iterations.
Thomas Witkowski's avatar
Thomas Witkowski committed
408
    std::queue<int> tmpQueue = lastIterationsDuration;
409
410
    int avrgLastIterations = 0;
    while (!tmpQueue.empty()) {
411
412
	avrgLastIterations += tmpQueue.front();
	tmpQueue.pop();
413
    } 
Thomas Witkowski's avatar
Thomas Witkowski committed
414
    avrgLastIterations /= lastIterationsDuration.size();
415

416
    // Check if there is enough time for a further iteration.
Thomas Witkowski's avatar
Thomas Witkowski committed
417
418
    if (initialTimestamp + queueRuntime - currentTimestamp < avrgLastIterations * 2) {
      std::ofstream out(queueSerializationFilename.c_str());
419
420
421
422
423
424
425
426
427
428
      serialize(out);
      out.close();

      return true;
    }

    return false;
  }

}