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 "OnLatticeSimulation.hpp" 00037 #include "PottsBasedCellPopulation.hpp" 00038 #include "CellBasedEventHandler.hpp" 00039 #include "LogFile.hpp" 00040 #include "Version.hpp" 00041 #include "ExecutableSupport.hpp" 00042 #include "MultipleCaBasedCellPopulation.hpp" 00043 00044 template<unsigned DIM> 00045 OnLatticeSimulation<DIM>::OnLatticeSimulation(AbstractCellPopulation<DIM>& rCellPopulation, 00046 bool deleteCellPopulationInDestructor, 00047 bool initialiseCells) 00048 : AbstractCellBasedSimulation<DIM>(rCellPopulation, 00049 deleteCellPopulationInDestructor, 00050 initialiseCells), 00051 mOutputCellVelocities(false) 00052 { 00053 if (!dynamic_cast<AbstractOnLatticeCellPopulation<DIM>*>(&rCellPopulation)) 00054 { 00055 EXCEPTION("OnLatticeSimulations require a subclass of AbstractOnLatticeCellPopulation."); 00056 } 00057 00058 this->mDt = 0.1; // 6 minutes 00059 } 00060 00061 template<unsigned DIM> 00062 void OnLatticeSimulation<DIM>::AddMultipleCaUpdateRule(boost::shared_ptr<AbstractMultipleCaUpdateRule<DIM> > pUpdateRule) 00063 { 00064 if (dynamic_cast<MultipleCaBasedCellPopulation<DIM>*>(&(this->mrCellPopulation))) 00065 { 00066 static_cast<MultipleCaBasedCellPopulation<DIM>*>(&(this->mrCellPopulation))->AddUpdateRule(pUpdateRule); 00067 } 00068 } 00069 00070 template<unsigned DIM> 00071 void OnLatticeSimulation<DIM>::RemoveAllMultipleCaUpdateRules() 00072 { 00073 if (dynamic_cast<MultipleCaBasedCellPopulation<DIM>*>(&(this->mrCellPopulation))) 00074 { 00075 static_cast<MultipleCaBasedCellPopulation<DIM>*>(&(this->mrCellPopulation))->RemoveAllUpdateRules(); 00076 } 00077 } 00078 00079 template<unsigned DIM> 00080 void OnLatticeSimulation<DIM>::AddPottsUpdateRule(boost::shared_ptr<AbstractPottsUpdateRule<DIM> > pUpdateRule) 00081 { 00082 if (dynamic_cast<PottsBasedCellPopulation<DIM>*>(&(this->mrCellPopulation))) 00083 { 00084 static_cast<PottsBasedCellPopulation<DIM>*>(&(this->mrCellPopulation))->AddUpdateRule(pUpdateRule); 00085 } 00086 } 00087 00088 template<unsigned DIM> 00089 void OnLatticeSimulation<DIM>::RemoveAllPottsUpdateRules() 00090 { 00091 if (dynamic_cast<PottsBasedCellPopulation<DIM>*>(&(this->mrCellPopulation))) 00092 { 00093 static_cast<PottsBasedCellPopulation<DIM>*>(&(this->mrCellPopulation))->RemoveAllUpdateRules(); 00094 } 00095 } 00096 00097 template<unsigned DIM> 00098 c_vector<double, DIM> OnLatticeSimulation<DIM>::CalculateCellDivisionVector(CellPtr pParentCell) 00099 { 00101 return zero_vector<double>(DIM); 00102 } 00103 00104 template<unsigned DIM> 00105 void OnLatticeSimulation<DIM>::WriteVisualizerSetupFile() 00106 { 00107 if (dynamic_cast<PottsBasedCellPopulation<DIM>*>(&this->mrCellPopulation)) 00108 { 00109 *this->mpVizSetupFile << "PottsSimulation\n"; 00110 } 00111 } 00112 00113 template<unsigned DIM> 00114 void OnLatticeSimulation<DIM>::UpdateCellLocationsAndTopology() 00115 { 00116 // Store whether we are sampling results at the current timestep 00117 SimulationTime* p_time = SimulationTime::Instance(); 00118 bool at_sampling_timestep = (p_time->GetTimeStepsElapsed()%this->mSamplingTimestepMultiple == 0); 00119 00120 /* 00121 * If required, store the current locations of cell centres. Note that we need to 00122 * use a std::map between cells and locations, rather than (say) a std::vector with 00123 * location indices corresponding to cells, since once we call UpdateCellLocations() 00124 * the location index of each cell may change. This is especially true in the case 00125 * of a CaBasedCellPopulation. 00126 */ 00127 std::map<CellPtr, c_vector<double, DIM> > old_cell_locations; 00128 if (mOutputCellVelocities && at_sampling_timestep) 00129 { 00130 for (typename AbstractCellPopulation<DIM>::Iterator cell_iter = this->mrCellPopulation.Begin(); 00131 cell_iter != this->mrCellPopulation.End(); 00132 ++cell_iter) 00133 { 00134 old_cell_locations[*cell_iter] = this->mrCellPopulation.GetLocationOfCellCentre(*cell_iter); 00135 } 00136 } 00137 00138 // Update cell locations 00139 CellBasedEventHandler::BeginEvent(CellBasedEventHandler::POSITION); 00140 static_cast<AbstractOnLatticeCellPopulation<DIM>*>(&(this->mrCellPopulation))->UpdateCellLocations(this->mDt); 00141 CellBasedEventHandler::EndEvent(CellBasedEventHandler::POSITION); 00142 00143 // Now write cell velocities to file if required 00144 if (mOutputCellVelocities && at_sampling_timestep) 00145 { 00146 *mpCellVelocitiesFile << p_time->GetTime() << "\t"; 00147 00148 for (typename AbstractCellPopulation<DIM>::Iterator cell_iter = this->mrCellPopulation.Begin(); 00149 cell_iter != this->mrCellPopulation.End(); 00150 ++cell_iter) 00151 { 00152 unsigned index = this->mrCellPopulation.GetLocationIndexUsingCell(*cell_iter); 00153 const c_vector<double,DIM>& position = this->mrCellPopulation.GetLocationOfCellCentre(*cell_iter); 00154 00155 c_vector<double, DIM> velocity = (position - old_cell_locations[*cell_iter])/this->mDt; 00156 00157 *mpCellVelocitiesFile << index << " "; 00158 for (unsigned i=0; i<DIM; i++) 00159 { 00160 *mpCellVelocitiesFile << position[i] << " "; 00161 } 00162 00163 for (unsigned i=0; i<DIM; i++) 00164 { 00165 *mpCellVelocitiesFile << velocity[i] << " "; 00166 } 00167 } 00168 *mpCellVelocitiesFile << "\n"; 00169 } 00170 } 00171 00172 template<unsigned DIM> 00173 void OnLatticeSimulation<DIM>::SetupSolve() 00174 { 00175 if (mOutputCellVelocities) 00176 { 00177 OutputFileHandler output_file_handler2(this->mSimulationOutputDirectory+"/", false); 00178 mpCellVelocitiesFile = output_file_handler2.OpenOutputFile("cellvelocities.dat"); 00179 } 00180 } 00181 00182 template<unsigned DIM> 00183 void OnLatticeSimulation<DIM>::UpdateAtEndOfSolve() 00184 { 00185 if (mOutputCellVelocities) 00186 { 00187 mpCellVelocitiesFile->close(); 00188 } 00189 } 00190 00191 template<unsigned DIM> 00192 bool OnLatticeSimulation<DIM>::GetOutputCellVelocities() 00193 { 00194 return mOutputCellVelocities; 00195 } 00196 00197 template<unsigned DIM> 00198 void OnLatticeSimulation<DIM>::SetOutputCellVelocities(bool outputCellVelocities) 00199 { 00200 mOutputCellVelocities = outputCellVelocities; 00201 } 00202 00203 template<unsigned DIM> 00204 void OnLatticeSimulation<DIM>::UpdateCellPopulation() 00205 { 00206 bool update_cell_population_this_timestep = true; 00207 if (dynamic_cast<MultipleCaBasedCellPopulation<DIM>*>(&(this->mrCellPopulation))) 00208 { 00209 /* 00210 * If mInitialiseCells is false, then the simulation has been loaded from an archive. 00211 * In this case, we should not call UpdateCellPopulation() at the first time step. This is 00212 * because it will have already been called at the final time step prior to saving; 00213 * if we were to call it again now, then we would have introduced an extra call to 00214 * the random number generator compared to if we had not saved and loaded the simulation, 00215 * thus affecting results. This would be bad - we don't want saving and loading to have 00216 * any effect on the course of a simulation! See #1445. 00217 */ 00218 if (!this->mInitialiseCells && (SimulationTime::Instance()->GetTimeStepsElapsed() == 0)) 00219 { 00220 NEVER_REACHED; 00222 // update_cell_population_this_timestep = false; 00223 } 00224 } 00225 00226 if (update_cell_population_this_timestep) 00227 { 00228 AbstractCellBasedSimulation<DIM>::UpdateCellPopulation(); 00229 } 00230 } 00231 00232 template<unsigned DIM> 00233 void OnLatticeSimulation<DIM>::OutputAdditionalSimulationSetup(out_stream& rParamsFile) 00234 { 00235 // Loop over the collection of update rules and output info for each 00236 *rParamsFile << "\n\t<UpdateRules>\n"; 00237 if (dynamic_cast<PottsBasedCellPopulation<DIM>*>(&(this->mrCellPopulation))) 00238 { 00239 std::vector<boost::shared_ptr<AbstractPottsUpdateRule<DIM> > > collection = 00240 static_cast<PottsBasedCellPopulation<DIM>*>(&(this->mrCellPopulation))->rGetUpdateRuleCollection(); 00241 00242 for (typename std::vector<boost::shared_ptr<AbstractPottsUpdateRule<DIM> > >::iterator iter = collection.begin(); 00243 iter != collection.end(); 00244 ++iter) 00245 { 00246 (*iter)->OutputUpdateRuleInfo(rParamsFile); 00247 } 00248 } 00249 else if (dynamic_cast<MultipleCaBasedCellPopulation<DIM>*>(&(this->mrCellPopulation))) 00250 { 00251 std::vector<boost::shared_ptr<AbstractMultipleCaUpdateRule<DIM> > > collection = 00252 static_cast<MultipleCaBasedCellPopulation<DIM>*>(&(this->mrCellPopulation))->rGetUpdateRuleCollection(); 00253 00254 for (typename std::vector<boost::shared_ptr<AbstractMultipleCaUpdateRule<DIM> > >::iterator iter = collection.begin(); 00255 iter != collection.end(); 00256 ++iter) 00257 { 00258 (*iter)->OutputUpdateRuleInfo(rParamsFile); 00259 } 00260 } 00261 else 00262 { 00263 //\todo define the method for `MultipleCaBasedCellPopulation` 00264 } 00265 *rParamsFile << "\t</UpdateRules>\n"; 00266 } 00267 00268 template<unsigned DIM> 00269 void OnLatticeSimulation<DIM>::OutputSimulationParameters(out_stream& rParamsFile) 00270 { 00271 *rParamsFile << "\t\t<OutputCellVelocities>" << mOutputCellVelocities << "</OutputCellVelocities>\n"; 00272 00273 // Call method on direct parent class 00274 AbstractCellBasedSimulation<DIM>::OutputSimulationParameters(rParamsFile); 00275 } 00276 00278 // Explicit instantiation 00280 00281 template class OnLatticeSimulation<1>; 00282 template class OnLatticeSimulation<2>; 00283 template class OnLatticeSimulation<3>; 00284 00285 // Serialization for Boost >= 1.36 00286 #include "SerializationExportWrapperForCpp.hpp" 00287 EXPORT_TEMPLATE_CLASS_SAME_DIMS(OnLatticeSimulation)