Chaste Release::3.1
AbstractCentreBasedCellPopulation.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 "AbstractCentreBasedCellPopulation.hpp"
00037 
00038 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00039 AbstractCentreBasedCellPopulation<ELEMENT_DIM, SPACE_DIM>::AbstractCentreBasedCellPopulation( AbstractMesh<ELEMENT_DIM, SPACE_DIM>& rMesh,
00040                                                                     std::vector<CellPtr>& rCells,
00041                                                                   const std::vector<unsigned> locationIndices)
00042     : AbstractOffLatticeCellPopulation<ELEMENT_DIM, SPACE_DIM>(rMesh, rCells, locationIndices),
00043       mMeinekeDivisionSeparation(0.3) // educated guess
00044 {
00045 }
00046 
00047 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00048 AbstractCentreBasedCellPopulation<ELEMENT_DIM, SPACE_DIM>::AbstractCentreBasedCellPopulation(AbstractMesh<ELEMENT_DIM, SPACE_DIM>& rMesh)
00049     : AbstractOffLatticeCellPopulation<ELEMENT_DIM, SPACE_DIM>(rMesh),
00050       mMeinekeDivisionSeparation(0.3) // educated guess
00051 
00052 {
00053 }
00054 
00055 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00056 c_vector<double, SPACE_DIM> AbstractCentreBasedCellPopulation<ELEMENT_DIM, SPACE_DIM>::GetLocationOfCellCentre(CellPtr pCell)
00057 {
00058     return GetNodeCorrespondingToCell(pCell)->rGetLocation();
00059 }
00060 
00061 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00062 Node<SPACE_DIM>* AbstractCentreBasedCellPopulation<ELEMENT_DIM, SPACE_DIM>::GetNodeCorrespondingToCell(CellPtr pCell)
00063 {
00064     unsigned index = this->GetLocationIndexUsingCell(pCell);
00065     return this->GetNode(index);
00066 }
00067 
00068 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00069 CellPtr AbstractCentreBasedCellPopulation<ELEMENT_DIM, SPACE_DIM>::AddCell(CellPtr pNewCell, const c_vector<double,SPACE_DIM>& rCellDivisionVector, CellPtr pParentCell)
00070 {
00071     // Create a new node
00072     Node<SPACE_DIM>* p_new_node = new Node<SPACE_DIM>(this->GetNumNodes(), rCellDivisionVector, false);   // never on boundary
00073     unsigned new_node_index = this->AddNode(p_new_node); // use copy constructor so it doesn't matter that new_node goes out of scope
00074 
00075     // Update cells vector
00076     this->mCells.push_back(pNewCell);
00077 
00078     // Update mappings between cells and location indices
00079     this->SetCellUsingLocationIndex(new_node_index,pNewCell);
00080     this->mCellLocationMap[pNewCell.get()] = new_node_index;
00081 
00082     return pNewCell;
00083 }
00084 
00085 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00086 std::pair<CellPtr,CellPtr> AbstractCentreBasedCellPopulation<ELEMENT_DIM, SPACE_DIM>::CreateCellPair(CellPtr pCell1, CellPtr pCell2)
00087 {
00088     assert(pCell1);
00089     assert(pCell2);
00090 
00091     std::pair<CellPtr,CellPtr> cell_pair;
00092 
00093     if (pCell1->GetCellId() < pCell2->GetCellId())
00094     {
00095         cell_pair.first = pCell1;
00096         cell_pair.second = pCell2;
00097     }
00098     else
00099     {
00100         cell_pair.first = pCell2;
00101         cell_pair.second = pCell1;
00102     }
00103     return cell_pair;
00104 }
00105 
00106 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00107 bool AbstractCentreBasedCellPopulation<ELEMENT_DIM, SPACE_DIM>::IsMarkedSpring(const std::pair<CellPtr,CellPtr>& rCellPair)
00108 {
00109     // the pair should be ordered like this (CreateCellPair will ensure this)
00110     assert(rCellPair.first->GetCellId() < rCellPair.second->GetCellId());
00111 
00112     return mMarkedSprings.find(rCellPair) != mMarkedSprings.end();
00113 }
00114 
00115 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00116 void AbstractCentreBasedCellPopulation<ELEMENT_DIM, SPACE_DIM>::MarkSpring(std::pair<CellPtr,CellPtr>& rCellPair)
00117 {
00118     // the pair should be ordered like this (CreateCellPair will ensure this)
00119     assert(rCellPair.first->GetCellId() < rCellPair.second->GetCellId());
00120 
00121     mMarkedSprings.insert(rCellPair);
00122 }
00123 
00124 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00125 void AbstractCentreBasedCellPopulation<ELEMENT_DIM, SPACE_DIM>::UnmarkSpring(std::pair<CellPtr,CellPtr>& rCellPair)
00126 {
00127     // the pair should be ordered like this (CreateCellPair will ensure this)
00128     assert(rCellPair.first->GetCellId() < rCellPair.second->GetCellId());
00129 
00130     mMarkedSprings.erase(rCellPair);
00131 }
00132 
00133 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00134 bool AbstractCentreBasedCellPopulation<ELEMENT_DIM, SPACE_DIM>::IsCellAssociatedWithADeletedLocation(CellPtr pCell)
00135 {
00136     return GetNodeCorrespondingToCell(pCell)->IsDeleted();
00137 }
00138 
00139 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00140 void AbstractCentreBasedCellPopulation<ELEMENT_DIM, SPACE_DIM>::UpdateNodeLocations(const std::vector< c_vector<double, SPACE_DIM> >& rNodeForces, double dt)
00141 {
00142     // Iterate over all nodes associated with real cells to update their positions
00143     for (typename AbstractCellPopulation<ELEMENT_DIM, SPACE_DIM>::Iterator cell_iter = this->Begin();
00144          cell_iter != this->End();
00145          ++cell_iter)
00146     {
00147         // Get index of node associated with cell
00148         unsigned node_index = this->GetLocationIndexUsingCell((*cell_iter));
00149 
00150         // Get damping constant for node
00151         double damping_const = this->GetDampingConstant(node_index);
00152 
00153         // Get displacement
00154         c_vector<double,SPACE_DIM> displacement=dt*rNodeForces[node_index]/damping_const;
00155 
00156         // Throws an exception if the cell movement goes beyond mAbsoluteMovementThreshold
00157         if (norm_2(displacement) > this->mAbsoluteMovementThreshold)
00158         {
00159             EXCEPTION("Cells are moving by: " << norm_2(displacement) <<
00160                     ", which is more than the AbsoluteMovementThreshold: "
00161                     << this->mAbsoluteMovementThreshold <<
00162                     ". Use a smaller timestep to avoid this exception.");
00163         }
00164 
00165         // Get new node location
00166         c_vector<double, SPACE_DIM> new_node_location = this->GetNode(node_index)->rGetLocation() + displacement;
00167 
00168         // Create ChastePoint for new node location
00169         ChastePoint<SPACE_DIM> new_point(new_node_location);
00170 
00171         // Move the node
00172         this->SetNode(node_index, new_point);
00173     }
00174 }
00175 
00176 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00177 double AbstractCentreBasedCellPopulation<ELEMENT_DIM, SPACE_DIM>::GetDampingConstant(unsigned nodeIndex)
00178 {
00179     CellPtr p_cell = this->GetCellUsingLocationIndex(nodeIndex);
00180     if (p_cell->GetMutationState()->IsType<WildTypeCellMutationState>() && !p_cell->HasCellProperty<CellLabel>())
00181     {
00182         return this->GetDampingConstantNormal();
00183     }
00184     else
00185     {
00186         return this->GetDampingConstantMutant();
00187     }
00188 }
00189 
00190 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00191 bool AbstractCentreBasedCellPopulation<ELEMENT_DIM, SPACE_DIM>::IsGhostNode(unsigned index)
00192 {
00193     return false;
00194 }
00195 
00196 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00197 bool AbstractCentreBasedCellPopulation<ELEMENT_DIM, SPACE_DIM>::IsParticle(unsigned index)
00198 {
00199     return false;
00200 }
00201 
00202 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00203 void AbstractCentreBasedCellPopulation<ELEMENT_DIM, SPACE_DIM>::GenerateCellResultsAndWriteToFiles()
00204 {
00205 
00206     // Set up cell type counter
00207     unsigned num_cell_types = this->mCellProliferativeTypeCount.size();
00208     std::vector<unsigned> cell_type_counter(num_cell_types);
00209     for (unsigned i=0; i<num_cell_types; i++)
00210     {
00211         cell_type_counter[i] = 0;
00212     }
00213 
00214     // Set up cell cycle phase counter
00215     unsigned num_cell_cycle_phases = this->mCellCyclePhaseCount.size();
00216     std::vector<unsigned> cell_cycle_phase_counter(num_cell_cycle_phases);
00217     for (unsigned i=0; i<num_cell_cycle_phases; i++)
00218     {
00219         cell_cycle_phase_counter[i] = 0;
00220     }
00221 
00222     // Write cell data to file
00223     for (unsigned node_index=0; node_index<this->GetNumNodes(); node_index++)
00224     {
00225         // Hack that covers the case where the node is associated with a cell that has just been killed (#1129)
00226         bool node_corresponds_to_dead_cell = false;
00227         if (this->IsCellAttachedToLocationIndex(node_index))
00228         {
00229             node_corresponds_to_dead_cell = this->GetCellUsingLocationIndex(node_index)->IsDead();
00230         }
00231 
00232         // Write cell data to file
00233         if (!(this->GetNode(node_index)->IsDeleted())
00234                 && !node_corresponds_to_dead_cell
00235                 && !(this->IsParticle(node_index)))
00236         {
00237 
00238             if (IsGhostNode(node_index) == true)
00239             {
00240                 *(this->mpVizCellProliferativeTypesFile) << INVISIBLE_COLOUR << " ";
00241             }
00242             else
00243             {
00244                 this->GenerateCellResults(this->GetCellUsingLocationIndex(node_index),cell_type_counter,cell_cycle_phase_counter);
00245             }
00246         }
00247     }
00248 
00249     this->WriteCellResultsToFiles(cell_type_counter, cell_cycle_phase_counter);
00250 }
00251 
00252 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00253 void AbstractCentreBasedCellPopulation<ELEMENT_DIM, SPACE_DIM>::WriteTimeAndNodeResultsToFiles()
00254 {
00255     OutputFileHandler output_file_handler(this->mDirPath, false);
00256 
00257     PetscTools::BeginRoundRobin();
00258     {
00259         if (!PetscTools::AmMaster() || SimulationTime::Instance()->GetTimeStepsElapsed()!=0)
00260         {
00261             this->mpVizNodesFile = output_file_handler.OpenOutputFile("results.viznodes", std::ios::app);
00262             this->mpVizBoundaryNodesFile = output_file_handler.OpenOutputFile("results.vizboundarynodes", std::ios::app);
00263         }
00264         if (PetscTools::AmMaster())
00265         {
00266             double time = SimulationTime::Instance()->GetTime();
00267 
00268             *this->mpVizNodesFile << time << "\t";
00269             *this->mpVizBoundaryNodesFile << time << "\t";
00270         }
00271 
00272 
00273         // Write node data to file
00274         for (typename AbstractMesh<ELEMENT_DIM, SPACE_DIM>::NodeIterator node_iter = this->mrMesh.GetNodeIteratorBegin();
00275                 node_iter != this->mrMesh.GetNodeIteratorEnd();
00276                 ++node_iter)
00277         {
00278 
00279             /*
00280              * Hack that covers the case where the node in an AbstractCentreBasedCellPopulation
00281              * is associated with a cell that has just been killed (#1129). This breaks the
00282              * vertex visualizer when apoptotic cells are involved.
00283              */
00284             bool node_corresponds_to_dead_cell = false;
00285             if (this->IsCellAttachedToLocationIndex(node_iter->GetIndex()))
00286             {
00287                 node_corresponds_to_dead_cell = this->GetCellUsingLocationIndex(node_iter->GetIndex())->IsDead();
00288             }
00289 
00290             // Write node data to file
00291             if (!(node_iter->IsDeleted()) && !node_corresponds_to_dead_cell)
00292             {
00293                 const c_vector<double,SPACE_DIM>& position = node_iter->rGetLocation();
00294 
00295                 for (unsigned i=0; i<SPACE_DIM; i++)
00296                 {
00297                     *this->mpVizNodesFile << position[i] << " ";
00298                 }
00299                 *this->mpVizBoundaryNodesFile << node_iter->IsBoundaryNode() << " ";
00300             }
00301         }
00302 
00303         if (PetscTools::AmTopMost())
00304         {
00305             *this->mpVizNodesFile << "\n";
00306             *this->mpVizBoundaryNodesFile << "\n";
00307         }
00308 
00309         this->mpVizNodesFile->close();
00310         this->mpVizBoundaryNodesFile->close();
00311     }
00312     PetscTools::EndRoundRobin();
00313 }
00314 
00315 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00316 double AbstractCentreBasedCellPopulation<ELEMENT_DIM, SPACE_DIM>::GetMeinekeDivisionSeparation()
00317 {
00318     return mMeinekeDivisionSeparation;
00319 }
00320 
00321 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00322 void AbstractCentreBasedCellPopulation<ELEMENT_DIM, SPACE_DIM>::SetMeinekeDivisionSeparation(double divisionSeparation)
00323 {
00324     assert(divisionSeparation <= 1.0);
00325     assert(divisionSeparation >= 0.0);
00326     mMeinekeDivisionSeparation = divisionSeparation;
00327 }
00328 
00329 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00330 void AbstractCentreBasedCellPopulation<ELEMENT_DIM, SPACE_DIM>::OutputCellPopulationParameters(out_stream& rParamsFile)
00331 {
00332     *rParamsFile << "\t\t<MeinekeDivisionSeparation>" << mMeinekeDivisionSeparation << "</MeinekeDivisionSeparation>\n";
00333 
00334     // Call method on direct parent class
00335     AbstractOffLatticeCellPopulation<ELEMENT_DIM, SPACE_DIM>::OutputCellPopulationParameters(rParamsFile);
00336 }
00337 
00339 // Explicit instantiation
00341 
00342 template class AbstractCentreBasedCellPopulation<1,1>;
00343 template class AbstractCentreBasedCellPopulation<1,2>;
00344 template class AbstractCentreBasedCellPopulation<2,2>;
00345 template class AbstractCentreBasedCellPopulation<1,3>;
00346 template class AbstractCentreBasedCellPopulation<2,3>;
00347 template class AbstractCentreBasedCellPopulation<3,3>;