Chaste Release::3.1
|
00001 /* 00002 00003 Copyright (c) 2005-2012, University of Oxford. 00004 All rights reserved. 00005 00006 University of Oxford means the Chancellor, Masters and Scholars of the 00007 University of Oxford, having an administrative office at Wellington 00008 Square, Oxford OX1 2JD, UK. 00009 00010 This file is part of Chaste. 00011 00012 Redistribution and use in source and binary forms, with or without 00013 modification, are permitted provided that the following conditions are met: 00014 * Redistributions of source code must retain the above copyright notice, 00015 this list of conditions and the following disclaimer. 00016 * Redistributions in binary form must reproduce the above copyright notice, 00017 this list of conditions and the following disclaimer in the documentation 00018 and/or other materials provided with the distribution. 00019 * Neither the name of the University of Oxford nor the names of its 00020 contributors may be used to endorse or promote products derived from this 00021 software without specific prior written permission. 00022 00023 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 00024 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 00025 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 00026 ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 00027 LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 00028 CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE 00029 GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 00030 HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 00031 LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 00032 OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 00033 00034 */ 00035 00036 #include "AbstractOneStepIvpOdeSolver.hpp" 00037 #include "TimeStepper.hpp" 00038 #include "Exception.hpp" 00039 #include <cmath> 00040 00041 OdeSolution AbstractOneStepIvpOdeSolver::Solve(AbstractOdeSystem* pOdeSystem, 00042 std::vector<double>& rYValues, 00043 double startTime, 00044 double endTime, 00045 double timeStep, 00046 double timeSampling) 00047 { 00048 assert(rYValues.size()==pOdeSystem->GetNumberOfStateVariables()); 00049 assert(endTime > startTime); 00050 assert(timeStep > 0.0); 00051 assert(timeSampling >= timeStep); 00052 00053 mStoppingEventOccurred = false; 00054 if ( pOdeSystem->CalculateStoppingEvent(startTime, rYValues) == true ) 00055 { 00056 EXCEPTION("(Solve with sampling) Stopping event is true for initial condition"); 00057 } 00058 TimeStepper stepper(startTime, endTime, timeSampling); 00059 00060 // setup solutions if output is required 00061 OdeSolution solutions; 00062 solutions.SetNumberOfTimeSteps(stepper.EstimateTimeSteps()); 00063 solutions.rGetSolutions().push_back(rYValues); 00064 solutions.rGetTimes().push_back(startTime); 00065 solutions.SetOdeSystemInformation(pOdeSystem->GetSystemInformation()); 00066 solutions.SetSolverName( GetIdentifier() ); 00067 00068 mWorkingMemory.resize(rYValues.size()); 00069 00070 // Solve the ODE system 00071 while ( !stepper.IsTimeAtEnd() && !mStoppingEventOccurred ) 00072 { 00073 InternalSolve(pOdeSystem, rYValues, mWorkingMemory, stepper.GetTime(), stepper.GetNextTime(), timeStep); 00074 stepper.AdvanceOneTimeStep(); 00075 // write current solution into solutions 00076 solutions.rGetSolutions().push_back(rYValues); 00077 // Push back new time into the time solution vector 00078 if ( mStoppingEventOccurred ) 00079 { 00080 solutions.rGetTimes().push_back(mStoppingTime); 00081 } 00082 else 00083 { 00084 solutions.rGetTimes().push_back(stepper.GetTime()); 00085 } 00086 } 00087 00088 // stepper.EstimateTimeSteps may have been an overestimate... 00089 solutions.SetNumberOfTimeSteps(stepper.GetTotalTimeStepsTaken()); 00090 return solutions; 00091 } 00092 00093 void AbstractOneStepIvpOdeSolver::Solve(AbstractOdeSystem* pOdeSystem, 00094 std::vector<double>& rYValues, 00095 double startTime, 00096 double endTime, 00097 double timeStep) 00098 { 00099 assert(rYValues.size()==pOdeSystem->GetNumberOfStateVariables()); 00100 assert(endTime > startTime); 00101 assert(timeStep > 0.0); 00102 00103 mStoppingEventOccurred = false; 00104 if ( pOdeSystem->CalculateStoppingEvent(startTime, rYValues) == true ) 00105 { 00106 EXCEPTION("(Solve without sampling) Stopping event is true for initial condition"); 00107 } 00108 00109 // Perhaps resize working memory 00110 mWorkingMemory.resize(rYValues.size()); 00111 // And solve... 00112 InternalSolve(pOdeSystem, rYValues, mWorkingMemory, startTime, endTime, timeStep); 00113 } 00114 00115 void AbstractOneStepIvpOdeSolver::InternalSolve(AbstractOdeSystem* pOdeSystem, 00116 std::vector<double>& rYValues, 00117 std::vector<double>& rWorkingMemory, 00118 double startTime, 00119 double endTime, 00120 double timeStep) 00121 { 00122 TimeStepper stepper(startTime, endTime, timeStep); 00123 // Solve the ODE system 00124 00125 // Which of our vectors holds the current solution? 00126 // If this is true, it's in rYValues, otherwise it's in rWorkingMemory. 00127 bool curr_is_curr = false; 00128 00129 // should never get here if this bool has been set to true; 00130 assert(!mStoppingEventOccurred); 00131 while ( !stepper.IsTimeAtEnd() && !mStoppingEventOccurred ) 00132 { 00133 curr_is_curr = not curr_is_curr; 00134 // Function that calls the appropriate one-step solver 00135 CalculateNextYValue(pOdeSystem, 00136 stepper.GetNextTimeStep(), 00137 stepper.GetTime(), 00138 curr_is_curr ? rYValues : rWorkingMemory, 00139 curr_is_curr ? rWorkingMemory : rYValues); 00140 stepper.AdvanceOneTimeStep(); 00141 if ( pOdeSystem->CalculateStoppingEvent(stepper.GetTime(), 00142 curr_is_curr ? rWorkingMemory : rYValues) == true ) 00143 { 00144 mStoppingTime = stepper.GetTime(); 00145 mStoppingEventOccurred = true; 00146 } 00147 } 00148 // Final answer must be in rYValues 00149 if (curr_is_curr) 00150 { 00151 rYValues.assign(rWorkingMemory.begin(), rWorkingMemory.end()); 00152 } 00153 }