Chaste Release::3.1
OdeSolution.cpp
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 "OdeSolution.hpp"
00037 
00038 #include <sstream>
00039 
00040 #include "ColumnDataWriter.hpp"
00041 #include "Exception.hpp"
00042 #include "PetscTools.hpp"
00043 #include "VectorHelperFunctions.hpp"
00044 
00045 OdeSolution::OdeSolution()
00046     : mNumberOfTimeSteps(0u),
00047       mpOdeSystemInformation()
00048 {
00049 }
00050 
00051 
00052 unsigned OdeSolution::GetNumberOfTimeSteps() const
00053 {
00054     return mNumberOfTimeSteps;
00055 }
00056 
00057 
00058 void OdeSolution::SetNumberOfTimeSteps(unsigned numTimeSteps)
00059 {
00060     mNumberOfTimeSteps = numTimeSteps;
00061     mTimes.reserve(numTimeSteps+1);
00062     mSolutions.reserve(numTimeSteps);
00063 }
00064 
00065 
00066 void OdeSolution::SetOdeSystemInformation(boost::shared_ptr<const AbstractOdeSystemInformation> pOdeSystemInfo)
00067 {
00068     mpOdeSystemInformation = pOdeSystemInfo;
00069 }
00070 
00071 std::vector<double> OdeSolution::GetVariableAtIndex(unsigned index) const
00072 {
00073     std::vector<double> answer;
00074     answer.reserve(mTimes.size());
00075     double temp_number;
00076     for (unsigned i=0; i< mTimes.size(); ++i)
00077     {
00078         if (index < mSolutions[0].size())
00079         {
00080             temp_number = mSolutions[i][index];
00081         }
00082         else
00083         {
00084             unsigned offset = mSolutions[0].size();
00085             if (index - offset < mParameters.size())
00086             {
00087                 temp_number = mParameters[index - offset];
00088             }
00089             else
00090             {
00091                 offset += mParameters.size();
00092                 if (index - offset < mDerivedQuantities[0].size())
00093                 {
00094                     temp_number = mDerivedQuantities[i][index - offset];
00095                 }
00096                 else
00097                 {
00098                     EXCEPTION("Invalid index passed to ""GetVariableAtIndex()"".");
00099                 }
00100             }
00101         }
00102         answer.push_back(temp_number);
00103     }
00104     return answer;
00105 }
00106 
00107 std::vector<double> OdeSolution::GetAnyVariable(const std::string& rName) const
00108 {
00109     return GetVariableAtIndex(mpOdeSystemInformation->GetAnyVariableIndex(rName));
00110 }
00111 
00112 std::vector<double>& OdeSolution::rGetTimes()
00113 {
00114     return mTimes;
00115 }
00116 
00117 const std::vector<double>& OdeSolution::rGetTimes() const
00118 {
00119     return mTimes;
00120 }
00121 
00122 std::vector<std::vector<double> >& OdeSolution::rGetSolutions()
00123 {
00124     return mSolutions;
00125 }
00126 
00127 const std::vector<std::vector<double> >& OdeSolution::rGetSolutions() const
00128 {
00129     return mSolutions;
00130 }
00131 
00132 
00133 template<typename VECTOR>
00134 void OdeSolution::CalculateDerivedQuantitiesAndParameters(AbstractParameterisedSystem<VECTOR>* pOdeSystem)
00135 {
00136     assert(pOdeSystem->GetSystemInformation() == mpOdeSystemInformation); // Just in case...
00137     rGetParameters(pOdeSystem);
00138     rGetDerivedQuantities(pOdeSystem);
00139 }
00140 
00141 
00142 template<typename VECTOR>
00143 std::vector<double>& OdeSolution::rGetParameters(AbstractParameterisedSystem<VECTOR>* pOdeSystem)
00144 {
00145     mParameters.clear();
00146     const unsigned num_params = pOdeSystem->GetNumberOfParameters();
00147     if (num_params > 0)
00148     {
00149         mParameters.reserve(num_params);
00150         for (unsigned i=0; i<num_params; ++i)
00151         {
00152             mParameters.push_back(pOdeSystem->GetParameter(i));
00153         }
00154     }
00155     return mParameters;
00156 }
00157 
00158 
00159 std::vector<std::vector<double> >& OdeSolution::rGetDerivedQuantities(AbstractParameterisedSystem<std::vector<double> >* pOdeSystem)
00160 {
00161     assert(pOdeSystem != NULL);
00162     if (mDerivedQuantities.empty() && pOdeSystem->GetNumberOfDerivedQuantities() > 0)
00163     {
00164         assert(mTimes.size() == mSolutions.size()); // Paranoia
00165         mDerivedQuantities.reserve(mTimes.size());
00166         for (unsigned i=0; i<mTimes.size(); i++)
00167         {
00168             mDerivedQuantities.push_back(pOdeSystem->ComputeDerivedQuantities(mTimes[i], mSolutions[i]));
00169         }
00170     }
00171     return mDerivedQuantities;
00172 }
00173 
00174 #ifdef CHASTE_CVODE
00175 std::vector<std::vector<double> >& OdeSolution::rGetDerivedQuantities(AbstractParameterisedSystem<N_Vector>* pOdeSystem)
00176 {
00177     assert(pOdeSystem != NULL);
00178     if (mDerivedQuantities.empty() && pOdeSystem->GetNumberOfDerivedQuantities() > 0)
00179     {
00180         const unsigned num_solutions = mSolutions.size();
00181         assert(mTimes.size() == num_solutions); // Paranoia
00182         mDerivedQuantities.resize(mTimes.size());
00183         N_Vector state_vars = num_solutions > 0 ? N_VNew_Serial(mSolutions[0].size()) : NULL;
00184         for (unsigned i=0; i<num_solutions; i++)
00185         {
00186             CopyFromStdVector(mSolutions[i], state_vars);
00187             N_Vector dqs = pOdeSystem->ComputeDerivedQuantities(mTimes[i], state_vars);
00188             CopyToStdVector(dqs, mDerivedQuantities[i]);
00189             DeleteVector(dqs);
00190         }
00191         DeleteVector(state_vars);
00192     }
00193     assert(mDerivedQuantities.size()==mTimes.size());
00194     return mDerivedQuantities;
00195 }
00196 #endif // CHASTE_CVODE
00197 
00198 
00199 void OdeSolution::WriteToFile(std::string directoryName,
00200                               std::string baseResultsFilename,
00201                               std::string timeUnits,
00202                               unsigned stepsPerRow,
00203                               bool cleanDirectory,
00204                               unsigned precision,
00205                               bool includeDerivedQuantities)
00206 {
00207     assert(stepsPerRow > 0);
00208     assert(mTimes.size() > 0);
00209     assert(mTimes.size() == mSolutions.size());
00210     assert(mpOdeSystemInformation.get() != NULL);
00211     if (mpOdeSystemInformation->GetNumberOfParameters()==0 && mpOdeSystemInformation->GetNumberOfDerivedQuantities() == 0)
00212     {
00213         includeDerivedQuantities = false;
00214     }
00215 
00216     if (includeDerivedQuantities)
00217     {
00218         if ((mDerivedQuantities.empty() || mDerivedQuantities.size()!=mTimes.size()) && mParameters.empty())
00219         {
00220             EXCEPTION("You must first call ""CalculateDerivedQuantitiesAndParameters()"" in order to write derived quantities.");
00221         }
00222     }
00223 
00224     // Write data to a file using ColumnDataWriter
00225     ColumnDataWriter writer(directoryName, baseResultsFilename, cleanDirectory, precision);
00226 
00227     if (!PetscTools::AmMaster())
00228     {
00229         //Only the master actually writes to file
00230         return;
00231     }
00232 
00233     int time_var_id = writer.DefineUnlimitedDimension("Time", timeUnits);
00234 
00235     // Either: the ODE system should have no names&units defined, or it should
00236     // the same number as the number of solutions per timestep.
00237     assert(  mpOdeSystemInformation->rGetStateVariableNames().size()==0 ||
00238             (mpOdeSystemInformation->rGetStateVariableNames().size()==mSolutions[0].size()) );
00239 
00240     unsigned num_vars = mSolutions[0].size();
00241     unsigned num_params = mpOdeSystemInformation->GetNumberOfParameters();
00242     unsigned num_derived_quantities = mpOdeSystemInformation->GetNumberOfDerivedQuantities();
00243 
00244     std::vector<int> var_ids;
00245     var_ids.reserve(num_vars);
00246     if (mpOdeSystemInformation->rGetStateVariableNames().size() > 0)
00247     {
00248         for (unsigned i=0; i<num_vars; i++)
00249         {
00250             var_ids.push_back(writer.DefineVariable(mpOdeSystemInformation->rGetStateVariableNames()[i],
00251                                                     mpOdeSystemInformation->rGetStateVariableUnits()[i]));
00252         }
00253     }
00254     else
00255     {
00256         for (unsigned i=0; i<num_vars; i++)
00257         {
00258             std::stringstream string_stream;
00259             string_stream << "var_" << i;
00260             var_ids.push_back(writer.DefineVariable(string_stream.str(), ""));
00261         }
00262     }
00263 
00264     if (includeDerivedQuantities)
00265     {
00266         var_ids.reserve(num_vars + num_params + num_derived_quantities);
00267         for (unsigned i=0; i<num_params; ++i)
00268         {
00269             var_ids.push_back(writer.DefineVariable(mpOdeSystemInformation->rGetParameterNames()[i],
00270                                                     mpOdeSystemInformation->rGetParameterUnits()[i]));
00271         }
00272         for (unsigned i=0; i<num_derived_quantities; i++)
00273         {
00274             var_ids.push_back(writer.DefineVariable(mpOdeSystemInformation->rGetDerivedQuantityNames()[i],
00275                                                     mpOdeSystemInformation->rGetDerivedQuantityUnits()[i]));
00276         }
00277     }
00278 
00279     if (mSolverName != "")
00280     {
00281         writer.SetCommentForInfoFile("ODE SOLVER: " + mSolverName);
00282     }
00283 
00284     writer.EndDefineMode();
00285 
00286     for (unsigned i=0; i<mSolutions.size(); i+=stepsPerRow)
00287     {
00288         writer.PutVariable(time_var_id, mTimes[i]);
00289         for (unsigned j=0; j<num_vars; j++)
00290         {
00291             writer.PutVariable(var_ids[j], mSolutions[i][j]);
00292         }
00293         if (includeDerivedQuantities)
00294         {
00295             for (unsigned j=0; j<num_params; ++j)
00296             {
00297                 writer.PutVariable(var_ids[j+num_vars], mParameters[j]);
00298             }
00299             for (unsigned j=0; j<num_derived_quantities; j++)
00300             {
00301                 writer.PutVariable(var_ids[j+num_params+num_vars], mDerivedQuantities[i][j]);
00302             }
00303         }
00304         writer.AdvanceAlongUnlimitedDimension();
00305     }
00306     writer.Close();
00307 }
00308 
00309 //
00310 // Explicit instantiation
00311 //
00312 
00317 template std::vector<double>& OdeSolution::rGetParameters(AbstractParameterisedSystem<std::vector<double> >* pOdeSystem);
00318 template void OdeSolution::CalculateDerivedQuantitiesAndParameters(AbstractParameterisedSystem<std::vector<double> >* pOdeSystem);
00319 
00320 #ifdef CHASTE_CVODE
00321 template std::vector<double>& OdeSolution::rGetParameters(AbstractParameterisedSystem<N_Vector>* pOdeSystem);
00322 template void OdeSolution::CalculateDerivedQuantitiesAndParameters(AbstractParameterisedSystem<N_Vector>* pOdeSystem);
00323 #endif // CHASTE_CVODE
00324