00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042 #include "SundanceDoublingStepController.hpp"
00043 #include "SundanceDiscreteFunction.hpp"
00044 #include "SundanceExprFieldWrapper.hpp"
00045 #include "PlayaLinearCombinationImpl.hpp"
00046 #include "PlayaOut.hpp"
00047 #include "PlayaTabs.hpp"
00048
00049 namespace Sundance
00050 {
00051 using std::min;
00052 using std::max;
00053
00054 bool DoublingStepController::run() const
00055 {
00056 Tabs tab0(0);
00057 Tabs tab1;
00058 int verb = stepControl_.verbosity_;
00059 if (MPIComm::world().getRank()!=0) verb = 0;
00060 double t = stepControl_.tStart_;
00061 double p = stepControl_.stepOrder_;
00062 double tau = stepControl_.tau_;
00063 double tStop = stepControl_.tStop_;
00064 int maxSteps = stepControl_.maxSteps_;
00065
00066 double safety = stepControl_.stepsizeReductionSafetyFactor_;
00067
00068
00069 double dt = stepControl_.initialStepsize_;
00070
00071 double minStepsize = dt * stepControl_.minStepsizeFactor_;
00072 double maxStepsize = dt * stepControl_.maxStepsizeFactor_;
00073 bool atMinStepsize = false;
00074 bool atMaxStepsize = false;
00075
00076 double minStepUsed = fabs(dt);
00077 double maxStepUsed = fabs(dt);
00078
00079 PLAYA_ROOT_MSG1(verb, tab0 << "=================================================="
00080 << endl
00081 << tab0 << " starting time integration " << endl
00082 << tab0 << "==================================================");
00083 PLAYA_ROOT_MSG2(verb, tab1 << "Initial time: " << t);
00084 PLAYA_ROOT_MSG2(verb, tab1 << "Final time: " << tStop);
00085 PLAYA_ROOT_MSG2(verb, tab1 << "Initial stepsize: " << dt);
00086 PLAYA_ROOT_MSG2(verb, tab1 << "Min allowed stepsize: " << minStepsize);
00087 PLAYA_ROOT_MSG2(verb, tab1 << "Max allowed stepsize: " << maxStepsize);
00088 PLAYA_ROOT_MSG2(verb, tab1 << "Step tolerance: " << tau);
00089 PLAYA_ROOT_MSG2(verb, tab1 << "Method order: " << p);
00090 PLAYA_ROOT_MSG2(verb, tab1 << "Max steps: " << maxSteps);
00091
00092 Expr uCur = copyDiscreteFunction(prob_.uCur());
00093 Expr uTmp = copyDiscreteFunction(uCur);
00094 Expr uSolnOneFullStep = copyDiscreteFunction(uCur);
00095 Expr uSolnHalfStep = copyDiscreteFunction(uCur);
00096 Expr uSolnTwoHalfSteps = copyDiscreteFunction(uCur);
00097
00098 int writeIndex = 1;
00099 double tNextWrite = outputControl_.writeInterval_;
00100 int writeVerb = outputControl_.verbosity_;
00101 double writeInterval = outputControl_.writeInterval_;
00102
00103
00104 write(0, 0.0, uCur);
00105
00106
00107 int step = 0;
00108 int numShrink = 0;
00109 int numGrow = 0;
00110 int numSolves = 0;
00111
00112 bool gotEvent = false;
00113 bool terminateOnDetection = false;
00114 if (eventHandler_.get()) terminateOnDetection
00115 = eventHandler_->terminateOnDetection();
00116 PLAYA_ROOT_MSG2(verb, tab1 << "Terminate on event detection: "
00117 << terminateOnDetection);
00118
00119 while (t < tStop && step < maxSteps)
00120 {
00121 Tabs tab2;
00122 PLAYA_ROOT_MSG3(verb, tab2 << " step " << step << " time=" << t
00123 << " to " << t + dt << " stepsize=" << dt);
00124 Tabs tab3;
00125
00126 if (t + dt > tStop)
00127 {
00128 dt = tStop - t;
00129 PLAYA_ROOT_MSG3(verb, tab3 << "timestep exceeds interval: reducing to dt=" << dt);
00130 PLAYA_ROOT_MSG3(verb, tab3 << " step " << step << " is now time=" << t
00131 << " to " << t + dt << " stepsize=" << dt);
00132 }
00133
00134 PLAYA_ROOT_MSG5(verb, tab3 << "doing full step");
00135 bool stepOK = prob_.step(t, uCur, t+dt, uSolnOneFullStep, solver_);
00136 PLAYA_ROOT_MSG5(verb, tab3 << "doing first half step");
00137 stepOK = prob_.step(t, uCur, t+0.5*dt, uSolnHalfStep, solver_);
00138 PLAYA_ROOT_MSG5(verb, tab3 << "doing second half step");
00139 stepOK = prob_.step(t+0.5*dt, uSolnHalfStep, t+dt, uSolnTwoHalfSteps, solver_);
00140 numSolves += 3;
00141
00142 double err = compare_->diff(uSolnTwoHalfSteps, uSolnOneFullStep);
00143
00144 PLAYA_ROOT_MSG3(verb, tab3 << "error=" << err << " tau=" << tau);
00145
00146 double dtNew = dt;
00147 if (err < tau) dtNew = dt*pow(tau/err, 1.0/(p+1.0));
00148 else dtNew = dt*pow(tau/err, 1.0/p);
00149
00150 if (dtNew < dt && !atMinStepsize)
00151 {
00152 if (safety*dtNew <= minStepsize)
00153 {
00154 dt = minStepsize;
00155 atMinStepsize = true;
00156 PLAYA_ROOT_MSG1(verb, tab2 << "WARNING: minimum stepsize reached");
00157 }
00158 else
00159 {
00160 dt = safety*dtNew;
00161 }
00162 atMaxStepsize = false;
00163 PLAYA_ROOT_MSG3(verb, tab3 << "reducing step to dt=" << dt);
00164 numShrink++;
00165 continue;
00166 }
00167
00168 if (stepHook_.get()) stepHook_->call(t+dt, uSolnTwoHalfSteps);
00169
00170 if (eventHandler_.get())
00171 {
00172 gotEvent = eventHandler_->checkForEvent(t, uCur, t+0.5*dt, uSolnHalfStep);
00173 if (gotEvent && terminateOnDetection) break;
00174
00175 gotEvent = eventHandler_->checkForEvent(t+0.5*dt, uSolnHalfStep,
00176 t+dt, uSolnTwoHalfSteps);
00177 }
00178
00179 while ( tNextWrite >= t && tNextWrite < t+dt)
00180 {
00181 double tNode0 = t;
00182 double tNode1 = t+dt/2.0;
00183 double tNode2 = t+dt;
00184
00185 double phi0 = (tNextWrite-tNode1)*(tNextWrite-tNode2)/(tNode0-tNode1)/(tNode0-tNode2);
00186 double phi1 = (tNextWrite-tNode0)*(tNextWrite-tNode2)/(tNode1-tNode0)/(tNode1-tNode2);
00187 double phi2 = (tNextWrite-tNode0)*(tNextWrite-tNode1)/(tNode2-tNode0)/(tNode2-tNode1);
00188
00189 Vector<double> y0 = getDiscreteFunctionVector(uCur);
00190 Vector<double> y1 = getDiscreteFunctionVector(uSolnHalfStep);
00191 Vector<double> y2 = getDiscreteFunctionVector(uSolnTwoHalfSteps);
00192
00193 Vector<double> yTmp = phi0*y0 + phi1*y1 + phi2*y2;
00194 setDiscreteFunctionVector(uTmp, yTmp);
00195
00196 write(writeIndex, tNextWrite, uTmp);
00197
00198 tNextWrite += writeInterval;
00199 writeIndex++;
00200 }
00201
00202 minStepUsed = min(minStepUsed, fabs(dt));
00203 maxStepUsed = max(maxStepUsed, fabs(dt));
00204
00205 updateDiscreteFunction(uSolnTwoHalfSteps, uCur);
00206 t += dt;
00207 step++;
00208
00209 if (gotEvent && terminateOnDetection) break;
00210
00211 if (t < tStop && dtNew > dt && !atMaxStepsize)
00212 {
00213 if (dtNew >= maxStepsize)
00214 {
00215 dt = maxStepsize;
00216 atMaxStepsize = true;
00217 PLAYA_ROOT_MSG2(verb, tab2 << "WARNING: maximum stepsize reached");
00218 }
00219 else
00220 {
00221 dt = dtNew;
00222 }
00223 atMinStepsize = false;
00224 PLAYA_ROOT_MSG3(verb, tab3 << "increasing step to dt=" << dt);
00225 numGrow++;
00226 }
00227 }
00228
00229
00230
00231 PLAYA_ROOT_MSG1(verb, tab0 << "=================================================================="
00232 << endl
00233 << tab0 << " done time integration ");
00234 PLAYA_ROOT_MSG2(verb, tab0 << "------------------------------------------------------------------");
00235 PLAYA_ROOT_MSG2(verb, tab1 << "Final time: " << t);
00236 PLAYA_ROOT_MSG2(verb, tab1 << "Num steps: " << step);
00237 PLAYA_ROOT_MSG2(verb, tab1 << "Min stepsize used: " << minStepUsed
00238 << " (would need " << fabs(t-stepControl_.tStart_)/minStepUsed
00239 << " steps of this size)");
00240 PLAYA_ROOT_MSG2(verb, tab1 << "Max stepsize used: " << maxStepUsed);
00241 PLAYA_ROOT_MSG2(verb, tab1 << "Num nonlinear solves: " << numSolves);
00242 PLAYA_ROOT_MSG2(verb, tab1 << "Num step reductions: " << numShrink);
00243 PLAYA_ROOT_MSG2(verb, tab1 << "Num step increases: " << numGrow);
00244 if (terminateOnDetection && gotEvent)
00245 {
00246 PLAYA_ROOT_MSG2(verb, tab1 << "Terminated by event detection at time="
00247 << eventHandler_->eventTime());
00248 }
00249 PLAYA_ROOT_MSG1(verb, tab0 << "==================================================================");
00250 return true;
00251 }
00252
00253
00254 void DoublingStepController::write(int index, double t, const Expr& u) const
00255 {
00256 Tabs tab(0);
00257 string name = outputControl_.filename_ + "-" + Teuchos::toString(index);
00258
00259 FieldWriter w = outputControl_.wf_.createWriter(name);
00260
00261 PLAYA_ROOT_MSG1(outputControl_.verbosity_, tab << "writing to " << name);
00262
00263 Mesh mesh = getDiscreteFunctionMesh(u);
00264 w.addMesh(mesh);
00265 for (int i=0; i<u.size(); i++)
00266 {
00267 w.addField("output[" + Teuchos::toString(i) + "]",
00268 new ExprFieldWrapper(u[i]));
00269 }
00270 w.write();
00271
00272 }
00273
00274
00275 }