timeControl.C
Go to the documentation of this file.
1 /*---------------------------------------------------------------------------*\
2  ========= |
3  \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
4  \\ / O peration | Website: https://openfoam.org
5  \\ / A nd | Copyright (C) 2011-2024 OpenFOAM Foundation
6  \\/ M anipulation |
7 -------------------------------------------------------------------------------
8 License
9  This file is part of OpenFOAM.
10 
11  OpenFOAM is free software: you can redistribute it and/or modify it
12  under the terms of the GNU General Public License as published by
13  the Free Software Foundation, either version 3 of the License, or
14  (at your option) any later version.
15 
16  OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
17  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
18  FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
19  for more details.
20 
21  You should have received a copy of the GNU General Public License
22  along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
23 
24 \*---------------------------------------------------------------------------*/
25 
26 #include "timeControl.H"
27 #include "PstreamReduceOps.H"
28 
29 // * * * * * * * * * * * * * Static Member Data * * * * * * * * * * * * * * //
30 
31 namespace Foam
32 {
33  template<>
34  const char* NamedEnum<timeControl::timeControls, 9>::
35  names[] =
36  {
37  "timeStep",
38  "writeTime",
39  "outputTime",
40  "adjustableRunTime",
41  "runTime",
42  "runTimes",
43  "clockTime",
44  "cpuTime",
45  "none"
46  };
47 }
48 
50  Foam::timeControl::timeControlNames_;
51 
52 
53 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
54 
56 (
57  const Time& t,
58  const dictionary& dict,
59  const word& prefix
60 )
61 :
62  time_(t),
63  prefix_(prefix),
64  timeControl_(timeControls::timeStep),
65  intervalSteps_(0),
66  interval_(-1),
67  timeDelta_(0),
68  executionIndex_(0)
69 {
70  read(dict);
71 }
72 
73 
74 // * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
75 
77 {}
78 
79 
80 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
81 
83 {
84  word controlName(prefix_ + "Control");
85  word intervalName(prefix_ + "Interval");
86 
87  // For backward compatibility support the deprecated 'outputControl' option
88  // now superseded by 'writeControl' for compatibility with Time
89  if (prefix_ == "write" && dict.found("outputControl"))
90  {
92  << "Using deprecated 'outputControl'" << nl
93  << " Please use 'writeControl' with 'writeInterval'"
94  << endl;
95 
96  // Change to the old names for this option
97  controlName = "outputControl";
98  intervalName = "outputInterval";
99  }
100 
101  if (dict.found(controlName))
102  {
103  timeControl_ = timeControlNames_.read(dict.lookup(controlName));
104  }
105  else
106  {
107  timeControl_ = timeControls::timeStep;
108  }
109 
110  switch (timeControl_)
111  {
112  case timeControls::timeStep:
113  {
114  intervalSteps_ = dict.lookupOrDefault<label>(intervalName, 0);
115  break;
116  }
117 
118  case timeControls::writeTime:
119  case timeControls::outputTime:
120  {
121  intervalSteps_ = dict.lookupOrDefault<label>(intervalName, 1);
122  break;
123  }
124 
125  case timeControls::clockTime:
126  case timeControls::runTime:
127  case timeControls::cpuTime:
128  case timeControls::adjustableRunTime:
129  {
130  interval_ = dict.lookup<scalar>(intervalName, time_.userUnits());
131 
132  if (timeControl_ == timeControls::adjustableRunTime)
133  {
134  executionIndex_ = label
135  (
136  (
137  (time_.value() - time_.beginTime().value())
138  + 0.5*time_.deltaTValue()
139  )
140  /interval_
141  );
142  }
143 
144  break;
145  }
146 
147  case timeControls::runTimes:
148  {
149  const word timesName(prefix_ + "Times");
150  const word frequenciesName(prefix_ + "Frequencies");
151  const bool repeat = dict.lookupOrDefault("writeRepeat", false);
152 
153  timeDelta_ =
155  (
156  "timeDelta",
157  unitNone,
158  1e-3*time_.userDeltaTValue()
159  );
160 
161  if (dict.found(timesName))
162  {
163  times_ = dict.lookup<scalarList>(timesName, unitNone);
164  }
165  else if (dict.found(frequenciesName))
166  {
167  List<Pair<scalar>> frequencies
168  (
169  dict.lookup(frequenciesName)
170  );
171 
172  if (!repeat)
173  {
174  frequencies.append
175  (
176  {time_.endTime().value(), frequencies.last().second()}
177  );
178  }
179 
180  const scalar frequenciesDuration =
181  frequencies.last().first() - frequencies.first().first();
182 
183  DynamicList<scalar> times(1, frequencies[0].first());
184  label i = 0;
185  label repeati = 0;
186  while (times[i] < time_.endTime().value())
187  {
188  for(label pi=0; pi<frequencies.size()-1; pi++)
189  {
190  while
191  (
192  times[i]
193  < frequencies[pi + 1].first()
194  + repeati*frequenciesDuration - timeDelta_
195  )
196  {
197  times(i + 1) = times[i] + frequencies[pi].second();
198  i++;
199  }
200  }
201  repeati++;
202  }
203 
204  times_ = times;
205  }
206  else
207  {
209  << "Undefined " << timesName
210  << " or " << frequenciesName << " for output control: "
211  << timeControlNames_[timeControl_] << nl
212  << exit(FatalError);
213  }
214 
215  forAll(times_, i)
216  {
217  timeIndices_.insert
218  (
219  int64_t((times_[i] + timeDelta_/2.0)/timeDelta_)
220  );
221  }
222 
223  intervalSteps_ = dict.lookupOrDefault<label>(intervalName, 1);
224  break;
225  }
226 
227  default:
228  {
229  break;
230  }
231  }
232 }
233 
234 
236 {
237  switch (timeControl_)
238  {
239  case timeControls::timeStep:
240  {
241  return
242  (
243  (intervalSteps_ <= 1)
244  || !(time_.timeIndex() % intervalSteps_)
245  );
246  break;
247  }
248 
249  case timeControls::writeTime:
250  case timeControls::outputTime:
251  {
252  if (time_.writeTime())
253  {
254  executionIndex_++;
255  return !(executionIndex_ % intervalSteps_);
256  }
257  break;
258  }
259 
260  case timeControls::runTime:
261  case timeControls::adjustableRunTime:
262  {
263  const label executionIndex = label
264  (
265  (
266  (time_.value() - time_.beginTime().value())
267  + 0.5*time_.deltaTValue()
268  )
269  /interval_
270  );
271 
272  if (executionIndex > executionIndex_)
273  {
274  executionIndex_ = executionIndex;
275  return true;
276  }
277  break;
278  }
279 
280  case timeControls::runTimes:
281  {
282  return timeIndices_.found
283  (
284  (time_.userTimeValue() + timeDelta_/2)/timeDelta_
285  );
286 
287  break;
288  }
289 
290  case timeControls::cpuTime:
291  {
292  const label executionIndex = label
293  (
294  returnReduce(time_.elapsedCpuTime(), maxOp<double>())
295  /interval_
296  );
297  if (executionIndex > executionIndex_)
298  {
299  executionIndex_ = executionIndex;
300  return true;
301  }
302  break;
303  }
304 
305  case timeControls::clockTime:
306  {
307  const label executionIndex = label
308  (
309  returnReduce(label(time_.elapsedClockTime()), maxOp<label>())
310  /interval_
311  );
312  if (executionIndex > executionIndex_)
313  {
314  executionIndex_ = executionIndex;
315  return true;
316  }
317  break;
318  }
319 
320  case timeControls::none:
321  {
322  return false;
323  }
324 
325  default:
326  {
328  << "Undefined output control: "
329  << timeControlNames_[timeControl_] << nl
330  << exit(FatalError);
331  break;
332  }
333  }
334 
335  return false;
336 }
337 
338 
340 {
341  switch (timeControl_)
342  {
343  case timeControls::timeStep:
344  case timeControls::writeTime:
345  case timeControls::outputTime:
346  case timeControls::runTime:
347  case timeControls::cpuTime:
348  case timeControls::clockTime:
349  case timeControls::none:
350  {
351  return vGreat;
352  break;
353  }
354 
355  case timeControls::adjustableRunTime:
356  {
357  return
358  max
359  (
360  0.0,
361  (executionIndex_ + 1)*interval_
362  - (time_.value() - time_.beginTime().value())
363  );
364  break;
365  }
366 
367  case timeControls::runTimes:
368  {
369  if (time_.userTimeValue() + timeDelta_ < times_.last())
370  {
371  forAll(times_, i)
372  {
373  if (times_[i] > time_.userTimeValue() + timeDelta_)
374  {
375  return time_.userTimeToTime
376  (
377  times_[i] - time_.userTimeValue()
378  );
379  }
380  }
381  }
382 
383  return vGreat;
384 
385  break;
386  }
387 
388  default:
389  {
391  << "Undefined output control: "
392  << timeControlNames_[timeControl_] << nl
393  << exit(FatalError);
394  break;
395  }
396  }
397 
398  return vGreat;
399 }
400 
401 
402 // ************************************************************************* //
Inter-processor communication reduction functions.
#define forAll(list, i)
Loop across all elements in list.
Definition: UList.H:434
void append(const T &)
Append an element at the end of the list.
Definition: ListI.H:178
void size(const label)
Override size to be inconsistent with allocated storage.
Definition: ListI.H:164
Initialise the NamedEnum HashTable from the static list of names.
Definition: NamedEnum.H:54
Class to control time during OpenFOAM simulations that is also the top-level objectRegistry.
Definition: Time.H:76
T & first()
Return the first element of the list.
Definition: UListI.H:114
T & last()
Return the last element of the list.
Definition: UListI.H:128
A list of keyword definitions, which are a keyword followed by any number of values (e....
Definition: dictionary.H:162
T lookupOrDefault(const word &, const T &, bool recursive=false, bool patternMatch=true) const
Find and return a T, if not found return the given default.
ITstream & lookup(const word &, bool recursive=false, bool patternMatch=true) const
Find and return an entry data stream.
Definition: dictionary.C:710
bool found(const word &, bool recursive=false, bool patternMatch=true) const
Search dictionary for given keyword.
Definition: dictionary.C:509
timeControls
The time control options.
Definition: timeControl.H:56
void read(const dictionary &)
Read from dictionary.
Definition: timeControl.C:82
~timeControl()
Destructor.
Definition: timeControl.C:76
scalar timeToNextAction()
Return the time to the next write.
Definition: timeControl.C:339
bool execute()
Flag to indicate whether to execute.
Definition: timeControl.C:235
timeControl(const Time &, const dictionary &, const word &prefix)
Construct from Time object and dictionary.
Definition: timeControl.C:56
A class for handling words, derived from string.
Definition: word.H:62
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:334
#define IOWarningInFunction(ios)
Report an IO warning using Foam::Warning.
Namespace for OpenFOAM.
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition: errorManip.H:124
const doubleScalar e
Definition: doubleScalar.H:106
intWM_LABEL_SIZE_t label
A label is an int32_t or int64_t as specified by the pre-processor macro WM_LABEL_SIZE.
Definition: label.H:59
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:257
const unitConversion unitNone
labelList first(const UList< labelPair > &p)
Definition: patchToPatch.C:39
T returnReduce(const T &Value, const BinaryOp &bop, const int tag=Pstream::msgType(), const label comm=UPstream::worldComm)
layerAndWeight max(const layerAndWeight &a, const layerAndWeight &b)
error FatalError
List< Type > repeat(const UList< Type > &a, const UList< Type > &b)
static const char nl
Definition: Ostream.H:266
dictionary dict