AdaptInstationary.cc 9.69 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#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(const char                *name,
				       ProblemIterationInterface *problemStat,  
				       AdaptInfo                 *info,
				       ProblemTimeInterface      *problemInstat,
				       AdaptInfo                 *initialInfo,
				       time_t                    initialTimestamp)
    : 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
Thomas Witkowski's avatar
Thomas Witkowski committed
80
81
    if (adaptInfo->getTime() <= adaptInfo->getStartTime()) {
      problemIteration_->oneIteration(adaptInfo, ESTIMATE);
82
83
84
    }

    // increment time
Thomas Witkowski's avatar
Thomas Witkowski committed
85
    adaptInfo->setTime(adaptInfo->getTime() + adaptInfo->getTimestep());
86

Thomas Witkowski's avatar
Thomas Witkowski committed
87
    problemTime_->setTime(adaptInfo);
88
89

    INFO(info_,6)("time = %e, timestep = %e\n",
Thomas Witkowski's avatar
Thomas Witkowski committed
90
		  adaptInfo->getTime(), adaptInfo->getTimestep());
91

Thomas Witkowski's avatar
Thomas Witkowski committed
92
    adaptInfo->setSpaceIteration(0);
93
94
  
    // do the iteration
Thomas Witkowski's avatar
Thomas Witkowski committed
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 {
Thomas Witkowski's avatar
Thomas Witkowski committed
105
106
      adaptInfo->setTime(adaptInfo->getTime() + adaptInfo->getTimestep());
      problemTime_->setTime(adaptInfo);
107
108

      INFO(info_,6)("time = %e, try timestep = %e\n",
Thomas Witkowski's avatar
Thomas Witkowski committed
109
		    adaptInfo->getTime(), adaptInfo->getTimestep());
110
    
Thomas Witkowski's avatar
Thomas Witkowski committed
111
      problemIteration_->oneIteration(adaptInfo, NO_ADAPTION);
112

Thomas Witkowski's avatar
Thomas Witkowski committed
113
      adaptInfo->incTimestepIteration();
114

115
      if (!fixedTimestep_ && 
Thomas Witkowski's avatar
Thomas Witkowski committed
116
117
	 !adaptInfo->timeToleranceReached() &&
	 !adaptInfo->getTimestep() <= adaptInfo->getMinTimestep()) 
118
	{
Thomas Witkowski's avatar
Thomas Witkowski committed
119
120
	  adaptInfo->setTime(adaptInfo->getTime() - adaptInfo->getTimestep());
	  adaptInfo->setTimestep(adaptInfo->getTimestep() * time_delta_1);
121
122
123
	  continue;
	}

Thomas Witkowski's avatar
Thomas Witkowski committed
124
      adaptInfo->setSpaceIteration(0);
125
126
    
      do {
Thomas Witkowski's avatar
Thomas Witkowski committed
127
	problemIteration_->beginIteration(adaptInfo);
128

Thomas Witkowski's avatar
Thomas Witkowski committed
129
	if (problemIteration_->oneIteration(adaptInfo, FULL_ITERATION)) {
130
	  if (!fixedTimestep_ && 
Thomas Witkowski's avatar
Thomas Witkowski committed
131
132
	     !adaptInfo->timeToleranceReached() &&
	     !adaptInfo->getTimestep() <= adaptInfo->getMinTimestep()) 
133
	    {
Thomas Witkowski's avatar
Thomas Witkowski committed
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;
	    }	
	}

Thomas Witkowski's avatar
Thomas Witkowski committed
142
143
	adaptInfo->incSpaceIteration();
	problemIteration_->endIteration(adaptInfo);
144

Thomas Witkowski's avatar
Thomas Witkowski committed
145
146
147
148
149
      } while(!adaptInfo->spaceToleranceReached() && 
	      adaptInfo->getSpaceIteration() <= adaptInfo->getMaxSpaceIteration());
    } while(!adaptInfo->timeToleranceReached() &&
	    !adaptInfo->getTimestep() <= adaptInfo->getMinTimestep() && 
	    adaptInfo->getTimestepIteration() <= adaptInfo->getMaxTimestepIteration());  
150

Thomas Witkowski's avatar
Thomas Witkowski committed
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");

Thomas Witkowski's avatar
Thomas Witkowski committed
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();
      }

Thomas Witkowski's avatar
Thomas Witkowski committed
175
    adaptInfo->incTimestepNumber();
176
177
178
179
180
181
182
183
  }

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

    int errorCode = 0;

Thomas Witkowski's avatar
Thomas Witkowski committed
184
    TEST_EXIT(adaptInfo->getTimestep() >= adaptInfo->getMinTimestep())
185
      ("timestep < min timestep\n");
Thomas Witkowski's avatar
Thomas Witkowski committed
186
    TEST_EXIT(adaptInfo->getTimestep() <= adaptInfo->getMaxTimestep())
187
188
      ("timestep > max timestep\n");

Thomas Witkowski's avatar
Thomas Witkowski committed
189
    TEST_EXIT(adaptInfo->getTimestep() > 0)("timestep <= 0!\n");
190

Thomas Witkowski's avatar
Thomas Witkowski committed
191
192
193
194
    if (adaptInfo->getTimestepNumber() == 0) {
      adaptInfo->setTime(adaptInfo->getStartTime());
      initialAdaptInfo_->setStartTime(adaptInfo->getStartTime());
      initialAdaptInfo_->setTime(adaptInfo->getStartTime());
195

Thomas Witkowski's avatar
Thomas Witkowski committed
196
      problemTime_->setTime(adaptInfo);
197
198
199

      // initial adaption
      problemTime_->solveInitialProblem(initialAdaptInfo_);
Thomas Witkowski's avatar
Thomas Witkowski committed
200
      problemTime_->transferInitialSolution(adaptInfo);
201
202
    }

Thomas Witkowski's avatar
Thomas Witkowski committed
203
204
    //    while (adaptInfo->getTime() < adaptInfo->getEndTime() - DBL_TOL) {
    while (adaptInfo->getEndTime() - adaptInfo->getTime() > DBL_TOL) {
205
206
      iterationTimestamp_ = time(NULL);

Thomas Witkowski's avatar
Thomas Witkowski committed
207
      problemTime_->initTimestep(adaptInfo);
Thomas Witkowski's avatar
Thomas Witkowski committed
208

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

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

Thomas Witkowski's avatar
Thomas Witkowski committed
227
      problemTime_->closeTimestep(adaptInfo);
228

Thomas Witkowski's avatar
Thomas Witkowski committed
229
      if (breakWhenStable && (adaptInfo->getSolverIterations() == 0)) {
230
231
232
233
234
235
236
237
238
239
240
241
	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
242
243
    problemTime_->startDelayedTimestepCalculation();

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
272
    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);
Thomas Witkowski's avatar
Thomas Witkowski committed
273
    adaptInfo->serialize(out);
274
275
276
277
278
279
280
281
282
283
    if (problemTime_) {
      problemTime_->serialize(out);
    }
  }

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

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

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

}