Chaste Release::3.1
OnLatticeSimulation.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 "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)