AdaptInstationary.cc 9.61 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
  {
    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.
Thomas Witkowski's avatar
Thomas Witkowski committed
33
    std::string serializationFilename = "";
34
35
36
37
38
39
40
    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());

Thomas Witkowski's avatar
Thomas Witkowski committed
41
      std::ifstream in(queueSerializationFilename_.c_str());
42
43
44
      deserialize(in);
      in.close();

45
46
      info->setIsDeserialized(true);
      initialInfo->setIsDeserialized(true);
47
48
49
50
51
52
53
54
55
56
    } 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
57
	std::string serializationFilename = "";
58
59
60
61
62
63

	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
64
	std::ifstream in(serializationFilename.c_str());
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
	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
    return errorCode;
  }

Thomas Witkowski's avatar
Thomas Witkowski committed
246
  void AdaptInstationary::initialize(const std::string& aName)
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
  {
    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;
  }

Thomas Witkowski's avatar
Thomas Witkowski committed
267
  void AdaptInstationary::serialize(std::ostream &out)
268
269
270
271
  {
    FUNCNAME("AdaptInstationary::serialize()");

    problemIteration_->serialize(out);
272
    adaptInfo_->serialize(out);
273
274
275
276
277
    if (problemTime_) {
      problemTime_->serialize(out);
    }
  }

Thomas Witkowski's avatar
Thomas Witkowski committed
278
  void AdaptInstationary::deserialize(std::istream &in)
279
280
281
282
  {
    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.
Thomas Witkowski's avatar
Thomas Witkowski committed
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
    
    // Check if there is enough time for a further iteration.
    if (initialTimestamp_ + queueRuntime_ - currentTimestamp < avrgLastIterations * 2) {
Thomas Witkowski's avatar
Thomas Witkowski committed
318
      std::ofstream out(queueSerializationFilename_.c_str());
319
320
321
322
323
324
325
326
327
328
      serialize(out);
      out.close();

      return true;
    }

    return false;
  }

}