SundanceDoublingStepController.cpp
Go to the documentation of this file.
00001 /* @HEADER@ */
00002 // ************************************************************************
00003 // 
00004 //                             Sundance
00005 //                 Copyright 2011 Sandia Corporation
00006 // 
00007 // Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
00008 // the U.S. Government retains certain rights in this software.
00009 //
00010 // Redistribution and use in source and binary forms, with or without
00011 // modification, are permitted provided that the following conditions are
00012 // met:
00013 //
00014 // 1. Redistributions of source code must retain the above copyright
00015 // notice, this list of conditions and the following disclaimer.
00016 //
00017 // 2. Redistributions in binary form must reproduce the above copyright
00018 // notice, this list of conditions and the following disclaimer in the
00019 // documentation and/or other materials provided with the distribution.
00020 //
00021 // 3. Neither the name of the Corporation nor the names of the
00022 // contributors may be used to endorse or promote products derived from
00023 // this software without specific prior written permission.
00024 //
00025 // THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
00026 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00027 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
00028 // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
00029 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
00030 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
00031 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
00032 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
00033 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
00034 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
00035 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00036 //
00037 // Questions? Contact Kevin Long (kevin.long@ttu.edu)
00038 // 
00039 
00040 /* @HEADER@ */
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   /* Write the initial state */
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) /* increase timestep */
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 }

Site Contact