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