OnLatticeSimulation.cpp

00001 /*
00002 
00003 Copyright (C) University of Oxford, 2005-2011
00004 
00005 University of Oxford means the Chancellor, Masters and Scholars of the
00006 University of Oxford, having an administrative office at Wellington
00007 Square, Oxford OX1 2JD, UK.
00008 
00009 This file is part of Chaste.
00010 
00011 Chaste is free software: you can redistribute it and/or modify it
00012 under the terms of the GNU Lesser General Public License as published
00013 by the Free Software Foundation, either version 2.1 of the License, or
00014 (at your option) any later version.
00015 
00016 Chaste is distributed in the hope that it will be useful, but WITHOUT
00017 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
00018 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
00019 License for more details. The offer of Chaste under the terms of the
00020 License is subject to the License being interpreted in accordance with
00021 English Law and subject to any action against the University of Oxford
00022 being under the jurisdiction of the English Courts.
00023 
00024 You should have received a copy of the GNU Lesser General Public License
00025 along with Chaste. If not, see <http://www.gnu.org/licenses/>.
00026 
00027 */
00028 
00029 #include "OnLatticeSimulation.hpp"
00030 #include "CaBasedCellPopulation.hpp"
00031 #include "PottsBasedCellPopulation.hpp"
00032 #include "CellBasedEventHandler.hpp"
00033 #include "LogFile.hpp"
00034 #include "Version.hpp"
00035 #include "ExecutableSupport.hpp"
00036 
00037 template<unsigned DIM>
00038 OnLatticeSimulation<DIM>::OnLatticeSimulation(AbstractCellPopulation<DIM>& rCellPopulation,
00039                                               bool deleteCellPopulationInDestructor,
00040                                               bool initialiseCells)
00041     : AbstractCellBasedSimulation<DIM>(rCellPopulation,
00042                                        deleteCellPopulationInDestructor,
00043                                        initialiseCells),
00044       mOutputCellVelocities(false)
00045 {
00046     if (!dynamic_cast<AbstractOnLatticeCellPopulation<DIM>*>(&rCellPopulation))
00047     {
00048         EXCEPTION("OnLatticeSimulations require a subclass of AbstractOnLatticeCellPopulation.");
00049     }
00050 
00051     this->mDt = 0.1; // 6 minutes
00052 }
00053 
00054 template<unsigned DIM>
00055 void OnLatticeSimulation<DIM>::AddCaUpdateRule(boost::shared_ptr<AbstractCaUpdateRule<DIM> > pUpdateRule)
00056 {
00057     if (dynamic_cast<CaBasedCellPopulation<DIM>*>(&(this->mrCellPopulation)))
00058     {
00059         static_cast<CaBasedCellPopulation<DIM>*>(&(this->mrCellPopulation))->AddUpdateRule(pUpdateRule);
00060     }
00061 }
00062 
00063 template<unsigned DIM>
00064 void OnLatticeSimulation<DIM>::AddPottsUpdateRule(boost::shared_ptr<AbstractPottsUpdateRule<DIM> > pUpdateRule)
00065 {
00066     if (dynamic_cast<PottsBasedCellPopulation<DIM>*>(&(this->mrCellPopulation)))
00067     {
00068         static_cast<PottsBasedCellPopulation<DIM>*>(&(this->mrCellPopulation))->AddUpdateRule(pUpdateRule);
00069     }
00070 }
00071 
00072 template<unsigned DIM>
00073 c_vector<double, DIM> OnLatticeSimulation<DIM>::CalculateCellDivisionVector(CellPtr pParentCell)
00074 {
00076     return zero_vector<double>(DIM);
00077 }
00078 
00079 template<unsigned DIM>
00080 void OnLatticeSimulation<DIM>::WriteVisualizerSetupFile()
00081 {
00082     if (dynamic_cast<PottsBasedCellPopulation<DIM>*>(&this->mrCellPopulation))
00083     {
00084        *this->mpVizSetupFile << "PottsSimulation\n";
00085     }
00086 }
00087 
00088 template<unsigned DIM>
00089 void OnLatticeSimulation<DIM>::UpdateCellLocationsAndTopology()
00090 {
00091     // Store whether we are sampling results at the current timestep
00092     SimulationTime* p_time = SimulationTime::Instance();
00093     bool at_sampling_timestep = (p_time->GetTimeStepsElapsed()%this->mSamplingTimestepMultiple == 0);
00094 
00095     /*
00096      * If required, store the current locations of cell centres. Note that we need to
00097      * use a std::map between cells and locations, rather than (say) a std::vector with
00098      * location indices corresponding to cells, since once we call UpdateCellLocations()
00099      * the location index of each cell may change. This is especially true in the case
00100      * of a CaBasedCellPopulation.
00101      */
00102     std::map<CellPtr, c_vector<double, DIM> > old_cell_locations;
00103     if (mOutputCellVelocities && at_sampling_timestep)
00104     {
00105         for (typename AbstractCellPopulation<DIM>::Iterator cell_iter = this->mrCellPopulation.Begin();
00106              cell_iter != this->mrCellPopulation.End();
00107              ++cell_iter)
00108         {
00109             old_cell_locations[*cell_iter] = this->mrCellPopulation.GetLocationOfCellCentre(*cell_iter);
00110         }
00111     }
00112 
00113     // Update cell locations
00114     CellBasedEventHandler::BeginEvent(CellBasedEventHandler::POSITION);
00115     static_cast<AbstractOnLatticeCellPopulation<DIM>*>(&(this->mrCellPopulation))->UpdateCellLocations(this->mDt);
00116     CellBasedEventHandler::EndEvent(CellBasedEventHandler::POSITION);
00117 
00118     // Now write cell velocities to file if required
00119     if (mOutputCellVelocities && at_sampling_timestep)
00120     {
00121         *mpCellVelocitiesFile << p_time->GetTime() << "\t";
00122 
00123         for (typename AbstractCellPopulation<DIM>::Iterator cell_iter = this->mrCellPopulation.Begin();
00124              cell_iter != this->mrCellPopulation.End();
00125              ++cell_iter)
00126         {
00127             unsigned index = this->mrCellPopulation.GetLocationIndexUsingCell(*cell_iter);
00128             const c_vector<double,DIM>& position = this->mrCellPopulation.GetLocationOfCellCentre(*cell_iter);
00129 
00130             c_vector<double, DIM> velocity = (position - old_cell_locations[*cell_iter])/this->mDt;
00131 
00132             *mpCellVelocitiesFile << index  << " ";
00133             for (unsigned i=0; i<DIM; i++)
00134             {
00135                 *mpCellVelocitiesFile << position[i] << " ";
00136             }
00137 
00138             for (unsigned i=0; i<DIM; i++)
00139             {
00140                 *mpCellVelocitiesFile << velocity[i] << " ";
00141             }
00142         }
00143         *mpCellVelocitiesFile << "\n";
00144     }
00145 }
00146 
00147 template<unsigned DIM>
00148 void OnLatticeSimulation<DIM>::SetupSolve()
00149 {
00150     // First call method on base class
00151     AbstractCellBasedSimulation<DIM>::SetupSolve();
00152 
00153     if (mOutputCellVelocities)
00154     {
00155         OutputFileHandler output_file_handler2(this->mSimulationOutputDirectory+"/", false);
00156         mpCellVelocitiesFile = output_file_handler2.OpenOutputFile("cellvelocities.dat");
00157     }
00158 }
00159 
00160 template<unsigned DIM>
00161 void OnLatticeSimulation<DIM>::AfterSolve()
00162 {
00163     // First call method on base class
00164     AbstractCellBasedSimulation<DIM>::AfterSolve();
00165 
00166     if (mOutputCellVelocities)
00167     {
00168         mpCellVelocitiesFile->close();
00169     }
00170 }
00171 
00172 template<unsigned DIM>
00173 bool OnLatticeSimulation<DIM>::GetOutputCellVelocities()
00174 {
00175     return mOutputCellVelocities;
00176 }
00177 
00178 template<unsigned DIM>
00179 void OnLatticeSimulation<DIM>::SetOutputCellVelocities(bool outputCellVelocities)
00180 {
00181     mOutputCellVelocities = outputCellVelocities;
00182 }
00183 
00184 
00185 template<unsigned DIM>
00186 void OnLatticeSimulation<DIM>::UpdateCellPopulation()
00187 {
00188     bool update_cell_population_this_timestep = true;
00189     if (dynamic_cast<CaBasedCellPopulation<DIM>*>(&(this->mrCellPopulation)))
00190     {
00191         /*
00192          * If mInitialiseCells is false, then the simulation has been loaded from an archive.
00193          * In this case, we should not call UpdateCellPopulation() at the first time step. This is
00194          * because it will have already been called at the final time step prior to saving;
00195          * if we were to call it again now, then we would have introduced an extra call to
00196          * the random number generator compared to if we had not saved and loaded the simulation,
00197          * thus affecting results. This would be bad - we don't want saving and loading to have
00198          * any effect on the course of a simulation! See #1445.
00199          */
00200         if (!this->mInitialiseCells && (SimulationTime::Instance()->GetTimeStepsElapsed() == 0))
00201         {
00202             update_cell_population_this_timestep = false;
00203         }
00204     }
00205 
00206     if (update_cell_population_this_timestep)
00207     {
00208         AbstractCellBasedSimulation<DIM>::UpdateCellPopulation();
00209     }
00210 }
00211 
00212 template<unsigned DIM>
00213 void OnLatticeSimulation<DIM>::OutputAdditionalSimulationSetup(out_stream& rParamsFile)
00214 {
00215     // Loop over the collection of update rules and output info for each
00216     *rParamsFile << "\n\t<UpdateRules>\n";
00217     if (dynamic_cast<PottsBasedCellPopulation<DIM>*>(&(this->mrCellPopulation)))
00218     {
00219         std::vector<boost::shared_ptr<AbstractPottsUpdateRule<DIM> > > collection =
00220             static_cast<PottsBasedCellPopulation<DIM>*>(&(this->mrCellPopulation))->rGetUpdateRuleCollection();
00221 
00222         for (typename std::vector<boost::shared_ptr<AbstractPottsUpdateRule<DIM> > >::iterator iter = collection.begin();
00223              iter != collection.end();
00224              ++iter)
00225         {
00226             (*iter)->OutputUpdateRuleInfo(rParamsFile);
00227         }
00228     }
00229     else
00230     {
00231         std::vector<boost::shared_ptr<AbstractCaUpdateRule<DIM> > > collection =
00232             static_cast<CaBasedCellPopulation<DIM>*>(&(this->mrCellPopulation))->rGetUpdateRuleCollection();
00233 
00234         for (typename std::vector<boost::shared_ptr<AbstractCaUpdateRule<DIM> > >::iterator iter = collection.begin();
00235              iter != collection.end();
00236              ++iter)
00237         {
00238             (*iter)->OutputUpdateRuleInfo(rParamsFile);
00239         }
00240     }
00241     *rParamsFile << "\t</UpdateRules>\n";
00242 }
00243 
00244 template<unsigned DIM>
00245 void OnLatticeSimulation<DIM>::OutputSimulationParameters(out_stream& rParamsFile)
00246 {
00247     *rParamsFile << "\t\t<OutputCellVelocities>" << mOutputCellVelocities << "</OutputCellVelocities>\n";
00248 
00249     // Call method on direct parent class
00250     AbstractCellBasedSimulation<DIM>::OutputSimulationParameters(rParamsFile);
00251 }
00252 
00254 // Explicit instantiation
00256 
00257 template class OnLatticeSimulation<1>;
00258 template class OnLatticeSimulation<2>;
00259 template class OnLatticeSimulation<3>;
00260 
00261 // Serialization for Boost >= 1.36
00262 #include "SerializationExportWrapperForCpp.hpp"
00263 EXPORT_TEMPLATE_CLASS_SAME_DIMS(OnLatticeSimulation)
Generated on Thu Dec 22 13:00:05 2011 for Chaste by  doxygen 1.6.3