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 "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