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