SundanceDoublingStepController.cpp
Go to the documentation of this file.
00001 /* @HEADER@ */
00002 // ************************************************************************
00003 // 
00004 //                              Sundance
00005 //                 Copyright (2005) Sandia Corporation
00006 // 
00007 // Copyright (year first published) Sandia Corporation.  Under the terms 
00008 // of Contract DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government 
00009 // retains certain rights in this software.
00010 // 
00011 // This library is free software; you can redistribute it and/or modify
00012 // it under the terms of the GNU Lesser General Public License as
00013 // published by the Free Software Foundation; either version 2.1 of the
00014 // License, or (at your option) any later version.
00015 //  
00016 // This library is distributed in the hope that it will be useful, but
00017 // WITHOUT ANY WARRANTY; without even the implied warranty of
00018 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00019 // Lesser General Public License for more details.
00020 //                                                                                 
00021 // You should have received a copy of the GNU Lesser General Public
00022 // License along with this library; if not, write to the Free Software
00023 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
00024 // USA                                                                                
00025 // Questions? Contact Kevin Long (krlong@sandia.gov), 
00026 // Sandia National Laboratories, Livermore, California, USA
00027 // 
00028 // ************************************************************************
00029 /* @HEADER@ */
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   /* Write the initial state */
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) /* increase timestep */
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 }

Site Contact