AbstractOneStepIvpOdeSolver.cpp

00001 /*
00002 
00003 Copyright (C) University of Oxford, 2005-2009
00004 
00005 University of Oxford means the Chancellor, Masters and Scholars of the
00006 University of Oxford, having an administrative office at Wellington
00007 Square, Oxford OX1 2JD, UK.
00008 
00009 This file is part of Chaste.
00010 
00011 Chaste is free software: you can redistribute it and/or modify it
00012 under the terms of the GNU Lesser General Public License as published
00013 by the Free Software Foundation, either version 2.1 of the License, or
00014 (at your option) any later version.
00015 
00016 Chaste is distributed in the hope that it will be useful, but WITHOUT
00017 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
00018 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
00019 License for more details. The offer of Chaste under the terms of the
00020 License is subject to the License being interpreted in accordance with
00021 English Law and subject to any action against the University of Oxford
00022 being under the jurisdiction of the English Courts.
00023 
00024 You should have received a copy of the GNU Lesser General Public License
00025 along with Chaste. If not, see <http://www.gnu.org/licenses/>.
00026 
00027 */
00028 
00029 
00030 #include "AbstractOneStepIvpOdeSolver.hpp"
00031 #include "TimeStepper.hpp"
00032 #include <cassert>
00033 #include <cmath>
00034 
00035 
00036 const double smidge=1e-10;
00037 
00038 OdeSolution AbstractOneStepIvpOdeSolver::Solve(AbstractOdeSystem* pOdeSystem,
00039                                                std::vector<double>& rYValues,
00040                                                double startTime,
00041                                                double endTime,
00042                                                double timeStep,
00043                                                double timeSampling)
00044 {
00045     assert(rYValues.size()==pOdeSystem->GetNumberOfStateVariables());
00046     assert(endTime > startTime);
00047     assert(timeStep > 0.0);
00048     assert(timeSampling >= timeStep);
00049 
00050     mStoppingEventOccurred = false;
00051     if ( pOdeSystem->CalculateStoppingEvent(startTime, rYValues) == true )
00052     {
00053         EXCEPTION("(Solve with sampling) Stopping event is true for initial condition");
00054     }
00055     TimeStepper stepper(startTime, endTime, timeSampling);
00056 
00057     // setup solutions if output is required
00058     OdeSolution solutions;
00059     solutions.SetNumberOfTimeSteps(stepper.EstimateTimeSteps());
00060     solutions.rGetSolutions().push_back(rYValues);
00061     solutions.rGetTimes().push_back(startTime);
00062 
00063     mWorkingMemory.resize(rYValues.size());
00064 
00065     // Solve the ODE system
00066     while ( !stepper.IsTimeAtEnd() && !mStoppingEventOccurred )
00067     {
00068         InternalSolve(pOdeSystem, rYValues, mWorkingMemory, stepper.GetTime(), stepper.GetNextTime(), timeStep);
00069         stepper.AdvanceOneTimeStep();
00070         // write current solution into solutions
00071         solutions.rGetSolutions().push_back(rYValues);
00072         // Push back new time into the time solution vector
00073         if ( mStoppingEventOccurred )
00074         {
00075             solutions.rGetTimes().push_back(mStoppingTime);
00076         }
00077         else
00078         {
00079             solutions.rGetTimes().push_back(stepper.GetTime());
00080         }
00081     }
00082 
00083     // stepper.EstimateTimeSteps may have been an overestimate...
00084     solutions.SetNumberOfTimeSteps(stepper.GetTimeStepsElapsed());
00085     return solutions;
00086 }
00087 
00088 void AbstractOneStepIvpOdeSolver::Solve(AbstractOdeSystem* pOdeSystem,
00089                                         std::vector<double>& rYValues,
00090                                         double startTime,
00091                                         double endTime,
00092                                         double timeStep)
00093 {
00094     assert(rYValues.size()==pOdeSystem->GetNumberOfStateVariables());
00095     assert(endTime > startTime);
00096     assert(timeStep > 0.0);
00097 
00098     mStoppingEventOccurred = false;
00099     if ( pOdeSystem->CalculateStoppingEvent(startTime, rYValues) == true )
00100     {
00101         EXCEPTION("(Solve without sampling) Stopping event is true for initial condition");
00102     }
00103 
00104     // Perhaps resize working memory
00105     mWorkingMemory.resize(rYValues.size());
00106     // And solve...
00107     InternalSolve(pOdeSystem, rYValues, mWorkingMemory, startTime, endTime, timeStep);
00108 }
00109 
00110 
00111 void AbstractOneStepIvpOdeSolver::InternalSolve(AbstractOdeSystem* pOdeSystem,
00112                                                 std::vector<double>& rYValues,
00113                                                 std::vector<double>& rWorkingMemory,
00114                                                 double startTime,
00115                                                 double endTime,
00116                                                 double timeStep)
00117 {
00118     TimeStepper stepper(startTime, endTime, timeStep);
00119     // Solve the ODE system
00120 
00121     // Which of our vectors holds the current solution?
00122     // If this is true, it's in rYValues, otherwise it's in rWorkingMemory.
00123     bool curr_is_curr = false;
00124 
00125     // should never get here if this bool has been set to true;
00126     assert(!mStoppingEventOccurred);
00127     while ( !stepper.IsTimeAtEnd() && !mStoppingEventOccurred )
00128     {
00129         curr_is_curr = not curr_is_curr;
00130         // Function that calls the appropriate one-step solver
00131         CalculateNextYValue(pOdeSystem,
00132                             stepper.GetNextTimeStep(),
00133                             stepper.GetTime(),
00134                             curr_is_curr ? rYValues : rWorkingMemory,
00135                             curr_is_curr ? rWorkingMemory : rYValues);
00136         stepper.AdvanceOneTimeStep();
00137         if ( pOdeSystem->CalculateStoppingEvent(stepper.GetTime(),
00138                                                 curr_is_curr ? rWorkingMemory : rYValues) == true )
00139         {
00140             mStoppingTime = stepper.GetTime();
00141             mStoppingEventOccurred = true;
00142         }
00143     }
00144     // Final answer must be in rYValues
00145     if (curr_is_curr)
00146     {
00147         rYValues.assign(rWorkingMemory.begin(), rWorkingMemory.end());
00148     }
00149 }

Generated on Wed Mar 18 12:51:56 2009 for Chaste by  doxygen 1.5.5