38 namespace functionObjects
47 { controlMode::TIME,
"time" },
48 { controlMode::TRIGGER,
"trigger" },
49 { controlMode::TIME_OR_TRIGGER,
"timeOrTrigger" },
50 { controlMode::TIME_AND_TRIGGER,
"timeAndTrigger" }
56 void Foam::functionObjects::timeControl::readControls()
80 nStepsToStartTimeChange_ = 3;
83 "nStepsToStartTimeChange",
84 nStepsToStartTimeChange_
90 bool Foam::functionObjects::timeControl::active()
const
92 label triggeri = time_.functionObjects().triggerIndex();
95 time_.value() >= (timeStart_ - 0.5*time_.deltaTValue())
96 && time_.value() <= (timeEnd_ + 0.5*time_.deltaTValue());
98 bool inTrigger = triggeri >= triggerStart_ && triggeri <= triggerEnd_;
100 switch (controlMode_)
102 case controlMode::TIME:
106 case controlMode::TRIGGER:
110 case controlMode::TIME_OR_TRIGGER:
112 return inTime || inTrigger;
114 case controlMode::TIME_AND_TRIGGER:
116 return inTime && inTrigger;
121 <<
"Unhandled enumeration: " << controlModeNames_[controlMode_]
130 Foam::scalar Foam::functionObjects::timeControl::calcExpansion
132 const scalar startRatio,
137 scalar ratio = startRatio;
156 for (label iter = 0; iter < 100; iter++)
159 scalar
f = (
y-1)*
pow(ratio,
n)+1-
y*
pow(ratio,
n-1);
160 scalar dfdratio = (
y-1)*
n*
pow(ratio,
n-1)-
y*(
n-1)*
pow(ratio,
n-2);
161 scalar dratio =
f/(dfdratio + SMALL);
173 <<
"Did not converge to find new timestep growth factor given "
174 <<
"overall factor " <<
y <<
" and " <<
n <<
" steps to do it in."
175 <<
endl <<
" Returning current best guess " << ratio <<
endl;
181 void Foam::functionObjects::timeControl::calcDeltaTCoeff
183 scalar& requiredDeltaTCoeff,
184 const scalar wantedDT,
186 const scalar presentTime,
187 const scalar timeToNextWrite,
188 const bool rampDirectionUp
191 const scalar writeInterval = writeControl_.interval();
196 scalar newDeltaT = deltaT0_;
198 if (seriesDTCoeff_ != GREAT)
200 newDeltaT *= seriesDTCoeff_;
208 scalar requiredTimeInterval = newDeltaT;
213 if (requiredDeltaTCoeff != 1.0)
215 requiredTimeInterval *=
216 (
pow(requiredDeltaTCoeff, nSteps) - 1)
217 /(requiredDeltaTCoeff - 1);
222 scalar timeToNextMultiple = -presentTime;
226 timeToNextMultiple +=
229 (presentTime + requiredTimeInterval)
236 timeToNextMultiple +=
239 (presentTime - requiredTimeInterval)
246 if (timeToNextWrite <= timeToNextMultiple)
251 newDeltaT = deltaT0_;
252 if (timeToNextWrite < newDeltaT)
254 newDeltaT = timeToNextWrite;
258 if (requiredTimeInterval > writeInterval)
261 <<
"With given ratio needed time span "
262 << requiredTimeInterval
263 <<
" exceeds available writeInterval "
264 << writeInterval <<
nl
265 <<
"Disabling all future time step ramping"
267 deltaTCoeff_ = GREAT;
268 newDeltaT = wantedDT;
273 seriesDTCoeff_ = GREAT;
276 Info<<
"Disabling ramping until time "
277 << presentTime+timeToNextWrite <<
endl;
280 requiredDeltaTCoeff = newDeltaT/deltaT0_;
289 scalar
y = timeToNextMultiple/wantedDT;
290 label requiredSteps = nSteps;
292 scalar ratioEstimate = deltaTCoeff_;
293 scalar ratioMax = deltaTCoeff_;
295 if (seriesDTCoeff_ != GREAT)
297 ratioEstimate = seriesDTCoeff_;
300 if (!rampDirectionUp)
302 ratioEstimate = 1/ratioEstimate;
303 ratioMax = 1/ratioMax;
307 bool searchConverged =
false;
308 for (label iter = 0; iter < 100; iter++)
311 const scalar newRatio = calcExpansion
317 const scalar deltaTLoop =
319 /
pow(newRatio,
mag(requiredSteps)-1);
320 scalar firstDeltaRatio = deltaTLoop/deltaT0_;
324 *(
pow(newRatio,
mag(requiredSteps))-1)
329 Info<<
" nSteps " << requiredSteps
330 <<
" ratioEstimate " << ratioEstimate
331 <<
" a0 " << deltaTLoop
332 <<
" firstDeltaRatio " << firstDeltaRatio
333 <<
" Sn " <<
Sn <<
" Sn+Time " <<
Sn+presentTime
334 <<
" seriesRatio "<< newRatio <<
endl;
341 (firstDeltaRatio < 1.0 && rampDirectionUp)
342 || (firstDeltaRatio > 1.0 && !rampDirectionUp)
347 requiredSteps =
mag(nSteps);
350 Info<<
"firstDeltaRatio " << firstDeltaRatio <<
" rampDir"
351 << rampDirectionUp <<
" newRatio " << newRatio
352 <<
" y " <<
y <<
" steps " << requiredSteps <<
endl;
357 if (firstDeltaRatio > ratioMax && rampDirectionUp)
362 Info<<
"First ratio " << firstDeltaRatio
363 <<
" exceeds threshold " << ratioMax <<
nl
364 <<
"Increasing required steps " << requiredSteps
368 else if (firstDeltaRatio < ratioMax && !rampDirectionUp)
373 Info<<
"First ratio " << firstDeltaRatio
374 <<
" exceeds threshold " << ratioMax <<
nl
375 <<
"Decreasing required steps " << requiredSteps
381 (newRatio > ratioMax && rampDirectionUp)
382 || (newRatio < ratioMax && !rampDirectionUp)
386 requiredSteps = nSteps;
389 Info<<
"Series ratio " << newRatio <<
"exceeds threshold "
390 << ratioMax <<
nl <<
"Consider next deltaT multiple "
391 <<
y*wantedDT + presentTime <<
endl;
396 seriesDTCoeff_ = newRatio;
398 if (requiredSteps == 1)
400 Sn = deltaT0_*firstDeltaRatio;
401 seriesDTCoeff_ = GREAT;
406 remainder(
Sn + presentTime, wantedDT) / wantedDT;
408 if (
mag(jumpError) > ROOTSMALL)
410 requiredSteps = label(timeToNextWrite/wantedDT);
411 firstDeltaRatio = timeToNextWrite/requiredSteps/deltaT0_;
415 Info<<
"All conditions satisfied deltaT0_:" << deltaT0_
416 <<
" calculated deltaTCoeff:" << firstDeltaRatio
417 <<
" series ratio set to:" << seriesDTCoeff_ <<
endl;
419 searchConverged =
true;
420 requiredDeltaTCoeff = firstDeltaRatio;
425 if (!searchConverged)
431 <<
"Did not converge to find new timestep growth factor"
432 <<
" given overall factor " <<
y
433 <<
" and " << requiredSteps <<
" steps to do it in."
434 <<
nl <<
" Falling back to non-adjusted deltatT "
437 requiredDeltaTCoeff = 1.0;
445 Foam::functionObjects::timeControl::timeControl
454 controlMode_(controlMode::TIME),
463 executeTimeIndex_(-1),
465 seriesDTCoeff_(GREAT)
480 ||
dict.found(
"timeStart")
481 ||
dict.found(
"timeEnd")
482 ||
dict.found(
"triggerStart")
483 ||
dict.found(
"triggerEnd")
496 deltaT0_ = time_.deltaTValue();
498 if (active() && (postProcess || executeControl_.execute()))
500 executeTimeIndex_ = time_.timeIndex();
513 foPtr_->execute(subIndex);
522 if (active() && (postProcess || writeControl_.execute()))
525 if (executeTimeIndex_ != time_.timeIndex())
527 executeTimeIndex_ = time_.timeIndex();
540 if (active() && (executeControl_.execute() || writeControl_.execute()))
555 writeControl_.control()
559 const scalar presentTime = time_.value();
564 foPtr_->adjustTimeStep();
565 const scalar wantedDT = time_.deltaTValue();
570 const label writeTimeIndex = writeControl_.executionIndex();
571 const scalar writeInterval = writeControl_.interval();
574 scalar timeToNextWrite =
575 (writeTimeIndex+1)*writeInterval
576 - (presentTime - time_.startTime().value());
577 if (timeToNextWrite <= 0.0)
579 timeToNextWrite = writeInterval;
587 scalar intervalError =
588 remainder(writeInterval, wantedDT)/writeInterval;
591 mag(intervalError) > ROOTSMALL
592 || deltaTCoeff_ == GREAT
595 scalar deltaT = time_.deltaTValue();
596 scalar nSteps = timeToNextWrite/deltaT;
603 deltaTCoeff_ != GREAT
604 || nSteps < nStepsToStartTimeChange_
610 label nStepsToNextWrite =
max(1, round(nSteps));
611 scalar newDeltaT = timeToNextWrite/nStepsToNextWrite;
614 scalar clipThreshold = 2;
615 if (deltaTCoeff_ != GREAT)
617 clipThreshold = deltaTCoeff_;
620 if (newDeltaT >= deltaT)
622 deltaT =
min(newDeltaT, clipThreshold*deltaT);
626 clipThreshold = 1/clipThreshold;
627 deltaT =
max(newDeltaT, clipThreshold*deltaT);
630 const_cast<Time&
>(time_).setDeltaT(deltaT,
false);
636 scalar requiredDeltaTCoeff = deltaTCoeff_;
642 if (seriesDTCoeff_ != GREAT)
644 requiredDeltaTCoeff = seriesDTCoeff_;
649 requiredDeltaTCoeff = deltaTCoeff_;
660 if (wantedDT < deltaT0_)
688 if (wantedDT < deltaT0_)
690 requiredDeltaTCoeff = 1/requiredDeltaTCoeff;
703 if (timeToNextWrite > wantedDT)
705 requiredDeltaTCoeff = wantedDT/deltaT0_;
709 requiredDeltaTCoeff = timeToNextWrite/deltaT0_;
713 if (requiredDeltaTCoeff > deltaTCoeff_ &&
debug)
716 <<
"Required deltaTCoeff "<< requiredDeltaTCoeff
717 <<
" is larger than allowed value "<< deltaTCoeff_
735 scalar newDeltaT = deltaT0_*requiredDeltaTCoeff;
739 const_cast<Time&
>(time_).setDeltaT(newDeltaT,
false);
741 if (seriesDTCoeff_ < 1.0)
743 requiredDeltaTCoeff = 1/requiredDeltaTCoeff;
744 seriesDTCoeff_ = 1/seriesDTCoeff_;
750 foPtr_->adjustTimeStep();
753 if (deltaTCoeff_ != GREAT)
757 scalar requiredDeltaTCoeff =
762 min(deltaTCoeff_, wantedDT/deltaT0_)
766 scalar newDeltaT = deltaT0_*requiredDeltaTCoeff;
770 const_cast<Time&
>( time_).setDeltaT(newDeltaT,
false);
775 const_cast<Time&
>( time_).setDeltaT(wantedDT,
false);
790 writeControl_.read(
dict);
791 executeControl_.read(
dict);
795 return foPtr_->read(
dict);
804 return active() ? foPtr_->filesModified() :
false;
812 foPtr_->updateMesh(mpm);
821 foPtr_->movePoints(
mesh);