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 "MeshBasedCellPopulation.hpp" 00037 #include "TrianglesMeshWriter.hpp" 00038 #include "VtkMeshWriter.hpp" 00039 #include "CellBasedEventHandler.hpp" 00040 #include "ApoptoticCellProperty.hpp" 00041 #include "Cylindrical2dMesh.hpp" 00042 #include "NodesOnlyMesh.hpp" 00043 #include "Exception.hpp" 00044 00045 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM> 00046 MeshBasedCellPopulation<ELEMENT_DIM,SPACE_DIM>::MeshBasedCellPopulation(MutableMesh<ELEMENT_DIM,SPACE_DIM>& rMesh, 00047 std::vector<CellPtr>& rCells, 00048 const std::vector<unsigned> locationIndices, 00049 bool deleteMesh, 00050 bool validate) 00051 : AbstractCentreBasedCellPopulation<ELEMENT_DIM,SPACE_DIM>(rMesh, rCells, locationIndices), 00052 mpVoronoiTessellation(NULL), 00053 mDeleteMesh(deleteMesh), 00054 mUseAreaBasedDampingConstant(false), 00055 mAreaBasedDampingConstantParameter(0.1), 00056 mOutputVoronoiData(false), 00057 mOutputCellPopulationVolumes(false), 00058 mWriteVtkAsPoints(false), 00059 mHasVariableRestLength(false) 00060 { 00061 mpMutableMesh = static_cast<MutableMesh<ELEMENT_DIM,SPACE_DIM>* >(&(this->mrMesh)); 00062 // This must always be true 00063 assert(this->mCells.size() <= this->mrMesh.GetNumNodes()); 00064 00065 if (validate) 00066 { 00067 Validate(); 00068 } 00069 } 00070 00071 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM> 00072 MeshBasedCellPopulation<ELEMENT_DIM,SPACE_DIM>::MeshBasedCellPopulation(MutableMesh<ELEMENT_DIM,SPACE_DIM>& rMesh) 00073 : AbstractCentreBasedCellPopulation<ELEMENT_DIM,SPACE_DIM>(rMesh) 00074 { 00075 mpMutableMesh = static_cast<MutableMesh<ELEMENT_DIM,SPACE_DIM>* >(&(this->mrMesh)); 00076 mpVoronoiTessellation = NULL; 00077 mDeleteMesh = true; 00078 } 00079 00080 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM> 00081 MeshBasedCellPopulation<ELEMENT_DIM,SPACE_DIM>::~MeshBasedCellPopulation() 00082 { 00083 delete mpVoronoiTessellation; 00084 00085 if (mDeleteMesh) 00086 { 00087 delete &this->mrMesh; 00088 } 00089 } 00090 00091 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM> 00092 bool MeshBasedCellPopulation<ELEMENT_DIM,SPACE_DIM>::UseAreaBasedDampingConstant() 00093 { 00094 return mUseAreaBasedDampingConstant; 00095 } 00096 00097 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM> 00098 void MeshBasedCellPopulation<ELEMENT_DIM,SPACE_DIM>::SetAreaBasedDampingConstant(bool useAreaBasedDampingConstant) 00099 { 00100 assert(SPACE_DIM==2); 00101 mUseAreaBasedDampingConstant = useAreaBasedDampingConstant; 00102 } 00103 00104 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM> 00105 unsigned MeshBasedCellPopulation<ELEMENT_DIM,SPACE_DIM>::AddNode(Node<SPACE_DIM>* pNewNode) 00106 { 00107 return mpMutableMesh->AddNode(pNewNode); 00108 } 00109 00110 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM> 00111 void MeshBasedCellPopulation<ELEMENT_DIM,SPACE_DIM>::SetNode(unsigned nodeIndex, ChastePoint<SPACE_DIM>& rNewLocation) 00112 { 00113 static_cast<MutableMesh<ELEMENT_DIM,SPACE_DIM>&>((this->mrMesh)).SetNode(nodeIndex, rNewLocation, false); 00114 } 00115 00116 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM> 00117 double MeshBasedCellPopulation<ELEMENT_DIM,SPACE_DIM>::GetDampingConstant(unsigned nodeIndex) 00118 { 00119 double damping_multiplier = AbstractCentreBasedCellPopulation<ELEMENT_DIM,SPACE_DIM>::GetDampingConstant(nodeIndex); 00120 00121 if (mUseAreaBasedDampingConstant) 00122 { 00132 assert(SPACE_DIM==2); 00133 00134 double rest_length = 1.0; 00135 double d0 = mAreaBasedDampingConstantParameter; 00136 00142 double d1 = 2.0*(1.0 - d0)/(sqrt(3)*rest_length*rest_length); 00143 00144 double area_cell = GetVolumeOfVoronoiElement(nodeIndex); 00145 00151 assert(area_cell < 1000); 00152 00153 damping_multiplier = d0 + area_cell*d1; 00154 } 00155 00156 return damping_multiplier; 00157 } 00158 00159 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM> 00160 void MeshBasedCellPopulation<ELEMENT_DIM,SPACE_DIM>::Validate() 00161 { 00162 std::vector<bool> validated_node = std::vector<bool>(this->GetNumNodes(), false); 00163 00164 for (typename AbstractCellPopulation<ELEMENT_DIM,SPACE_DIM>::Iterator cell_iter=this->Begin(); cell_iter!=this->End(); ++cell_iter) 00165 { 00166 unsigned node_index = this->GetLocationIndexUsingCell(*cell_iter); 00167 validated_node[node_index] = true; 00168 } 00169 00170 for (unsigned i=0; i<validated_node.size(); i++) 00171 { 00172 if (!validated_node[i]) 00173 { 00174 EXCEPTION("Node " << i << " does not appear to have a cell associated with it"); 00175 } 00176 } 00177 } 00178 00179 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM> 00180 MutableMesh<ELEMENT_DIM,SPACE_DIM>& MeshBasedCellPopulation<ELEMENT_DIM,SPACE_DIM>::rGetMesh() 00181 { 00182 return *mpMutableMesh; 00183 } 00184 00185 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM> 00186 const MutableMesh<ELEMENT_DIM,SPACE_DIM>& MeshBasedCellPopulation<ELEMENT_DIM,SPACE_DIM>::rGetMesh() const 00187 { 00188 return *mpMutableMesh; 00189 } 00190 00191 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM> 00192 unsigned MeshBasedCellPopulation<ELEMENT_DIM,SPACE_DIM>::RemoveDeadCells() 00193 { 00194 unsigned num_removed = 0; 00195 for (std::list<CellPtr>::iterator it = this->mCells.begin(); 00196 it != this->mCells.end(); 00197 ++it) 00198 { 00199 if ((*it)->IsDead()) 00200 { 00201 // Check if this cell is in a marked spring 00202 std::vector<const std::pair<CellPtr,CellPtr>*> pairs_to_remove; // Pairs that must be purged 00203 for (std::set<std::pair<CellPtr,CellPtr> >::iterator it1 = this->mMarkedSprings.begin(); 00204 it1 != this->mMarkedSprings.end(); 00205 ++it1) 00206 { 00207 const std::pair<CellPtr,CellPtr>& r_pair = *it1; 00208 00209 for (unsigned i=0; i<2; i++) 00210 { 00211 CellPtr p_cell = (i==0 ? r_pair.first : r_pair.second); 00212 00213 if (p_cell == *it) 00214 { 00215 // Remember to purge this spring 00216 pairs_to_remove.push_back(&r_pair); 00217 break; 00218 } 00219 } 00220 } 00221 00222 // Purge any marked springs that contained this cell 00223 for (std::vector<const std::pair<CellPtr,CellPtr>* >::iterator pair_it = pairs_to_remove.begin(); 00224 pair_it != pairs_to_remove.end(); 00225 ++pair_it) 00226 { 00227 this->mMarkedSprings.erase(**pair_it); 00228 } 00229 00230 // Remove the node from the mesh 00231 num_removed++; 00232 static_cast<MutableMesh<ELEMENT_DIM,SPACE_DIM>&>((this->mrMesh)).DeleteNodePriorToReMesh(this->GetLocationIndexUsingCell((*it))); 00233 00234 // Update mappings between cells and location indices 00235 unsigned location_index_of_removed_node = this->GetLocationIndexUsingCell((*it)); 00236 this->RemoveCellUsingLocationIndex(location_index_of_removed_node, (*it)); 00237 00238 // Update vector of cells 00239 it = this->mCells.erase(it); 00240 --it; 00241 } 00242 } 00243 00244 return num_removed; 00245 } 00246 00247 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM> 00248 void MeshBasedCellPopulation<ELEMENT_DIM,SPACE_DIM>::Update(bool hasHadBirthsOrDeaths) 00249 { 00250 NodeMap map(static_cast<MutableMesh<ELEMENT_DIM,SPACE_DIM>&>((this->mrMesh)).GetNumAllNodes()); 00251 static_cast<MutableMesh<ELEMENT_DIM,SPACE_DIM>&>((this->mrMesh)).ReMesh(map); 00252 00253 if (!map.IsIdentityMap()) 00254 { 00255 UpdateGhostNodesAfterReMesh(map); 00256 00257 // Update the mappings between cells and location indices 00258 std::map<Cell*, unsigned> old_map = this->mCellLocationMap; 00259 00260 // Remove any dead pointers from the maps (needed to avoid archiving errors) 00261 this->mLocationCellMap.clear(); 00262 this->mCellLocationMap.clear(); 00263 00264 for (std::list<CellPtr>::iterator it = this->mCells.begin(); 00265 it != this->mCells.end(); 00266 ++it) 00267 { 00268 unsigned old_node_index = old_map[(*it).get()]; 00269 00270 // This shouldn't ever happen, as the cell vector only contains living cells 00271 assert(!map.IsDeleted(old_node_index)); 00272 00273 unsigned new_node_index = map.GetNewIndex(old_node_index); 00274 this->SetCellUsingLocationIndex(new_node_index,*it); 00275 } 00276 00277 this->Validate(); 00278 } 00279 00280 // Purge any marked springs that are no longer springs 00281 std::vector<const std::pair<CellPtr,CellPtr>*> springs_to_remove; 00282 for (std::set<std::pair<CellPtr,CellPtr> >::iterator spring_it = this->mMarkedSprings.begin(); 00283 spring_it != this->mMarkedSprings.end(); 00284 ++spring_it) 00285 { 00286 CellPtr p_cell_1 = spring_it->first; 00287 CellPtr p_cell_2 = spring_it->second; 00288 Node<SPACE_DIM>* p_node_1 = this->GetNodeCorrespondingToCell(p_cell_1); 00289 Node<SPACE_DIM>* p_node_2 = this->GetNodeCorrespondingToCell(p_cell_2); 00290 00291 bool joined = false; 00292 00293 // For each element containing node1, if it also contains node2 then the cells are joined 00294 std::set<unsigned> node2_elements = p_node_2->rGetContainingElementIndices(); 00295 for (typename Node<SPACE_DIM>::ContainingElementIterator elem_iter = p_node_1->ContainingElementsBegin(); 00296 elem_iter != p_node_1->ContainingElementsEnd(); 00297 ++elem_iter) 00298 { 00299 if (node2_elements.find(*elem_iter) != node2_elements.end()) 00300 { 00301 joined = true; 00302 break; 00303 } 00304 } 00305 00306 // If no longer joined, remove this spring from the set 00307 if (!joined) 00308 { 00309 springs_to_remove.push_back(&(*spring_it)); 00310 } 00311 } 00312 00313 // Remove any springs necessary 00314 for (std::vector<const std::pair<CellPtr,CellPtr>* >::iterator spring_it = springs_to_remove.begin(); 00315 spring_it != springs_to_remove.end(); 00316 ++spring_it) 00317 { 00318 this->mMarkedSprings.erase(**spring_it); 00319 } 00320 00321 // Tessellate if needed 00322 TessellateIfNeeded(); 00323 00324 static_cast<MutableMesh<ELEMENT_DIM,SPACE_DIM>&>((this->mrMesh)).SetMeshHasChangedSinceLoading(); 00325 } 00326 00327 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM> 00328 void MeshBasedCellPopulation<ELEMENT_DIM,SPACE_DIM>::TessellateIfNeeded() 00329 { 00330 if ((SPACE_DIM==2 || SPACE_DIM==3)&&(ELEMENT_DIM==SPACE_DIM)) 00331 { 00332 CellBasedEventHandler::BeginEvent(CellBasedEventHandler::TESSELLATION); 00333 if (mUseAreaBasedDampingConstant || mOutputVoronoiData || mOutputCellPopulationVolumes || this->mOutputCellVolumes) 00334 { 00335 CreateVoronoiTessellation(); 00336 } 00337 CellBasedEventHandler::EndEvent(CellBasedEventHandler::TESSELLATION); 00338 } 00339 } 00340 00341 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM> 00342 Node<SPACE_DIM>* MeshBasedCellPopulation<ELEMENT_DIM,SPACE_DIM>::GetNode(unsigned index) 00343 { 00344 return this->mrMesh.GetNode(index); 00345 } 00346 00347 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM> 00348 unsigned MeshBasedCellPopulation<ELEMENT_DIM,SPACE_DIM>::GetNumNodes() 00349 { 00350 return this->mrMesh.GetNumAllNodes(); 00351 } 00352 00353 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM> 00354 void MeshBasedCellPopulation<ELEMENT_DIM,SPACE_DIM>::UpdateGhostNodesAfterReMesh(NodeMap& rMap) 00355 { 00356 } 00357 00358 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM> 00359 CellPtr MeshBasedCellPopulation<ELEMENT_DIM,SPACE_DIM>::AddCell(CellPtr pNewCell, const c_vector<double,SPACE_DIM>& rCellDivisionVector, CellPtr pParentCell) 00360 { 00361 assert(pNewCell); 00362 assert(pParentCell); 00363 00364 // Add new cell to cell population 00365 CellPtr p_created_cell = AbstractCentreBasedCellPopulation<ELEMENT_DIM,SPACE_DIM>::AddCell(pNewCell, rCellDivisionVector, pParentCell); 00366 assert(p_created_cell == pNewCell); 00367 00368 // Mark spring between parent cell and new cell 00369 std::pair<CellPtr,CellPtr> cell_pair = this->CreateCellPair(pParentCell, p_created_cell); 00370 this->MarkSpring(cell_pair); 00371 00372 // Return pointer to new cell 00373 return p_created_cell; 00374 } 00375 00377 // Output methods // 00379 00380 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM> 00381 void MeshBasedCellPopulation<ELEMENT_DIM,SPACE_DIM>::CreateOutputFiles(const std::string& rDirectory, bool cleanOutputDirectory) 00382 { 00383 AbstractCentreBasedCellPopulation<ELEMENT_DIM,SPACE_DIM>::CreateOutputFiles(rDirectory, cleanOutputDirectory); 00384 00385 OutputFileHandler output_file_handler(rDirectory, cleanOutputDirectory); 00386 mpVizElementsFile = output_file_handler.OpenOutputFile("results.vizelements"); 00387 00388 if (mOutputVoronoiData) 00389 { 00390 mpVoronoiFile = output_file_handler.OpenOutputFile("voronoi.dat"); 00391 } 00392 if (mOutputCellPopulationVolumes) 00393 { 00394 mpCellPopulationVolumesFile = output_file_handler.OpenOutputFile("cellpopulationareas.dat"); 00395 } 00396 } 00397 00398 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM> 00399 void MeshBasedCellPopulation<ELEMENT_DIM,SPACE_DIM>::CloseOutputFiles() 00400 { 00401 AbstractCentreBasedCellPopulation<ELEMENT_DIM,SPACE_DIM>::CloseOutputFiles(); 00402 00403 mpVizElementsFile->close(); 00404 00405 if (mOutputVoronoiData) 00406 { 00407 mpVoronoiFile->close(); 00408 } 00409 if (mOutputCellPopulationVolumes) 00410 { 00411 mpCellPopulationVolumesFile->close(); 00412 } 00413 } 00414 00415 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM> 00416 void MeshBasedCellPopulation<ELEMENT_DIM,SPACE_DIM>::WriteResultsToFiles() 00417 { 00418 if (SimulationTime::Instance()->GetTimeStepsElapsed() == 0 && this->mpVoronoiTessellation == NULL) 00419 { 00420 TessellateIfNeeded();//Update isn't run on time-step zero 00421 } 00422 00423 AbstractCentreBasedCellPopulation<ELEMENT_DIM,SPACE_DIM>::WriteResultsToFiles(); 00424 00425 // Write element data to file 00426 *mpVizElementsFile << SimulationTime::Instance()->GetTime() << "\t"; 00427 00428 for (typename MutableMesh<ELEMENT_DIM,SPACE_DIM>::ElementIterator elem_iter = static_cast<MutableMesh<ELEMENT_DIM,SPACE_DIM>&>((this->mrMesh)).GetElementIteratorBegin(); 00429 elem_iter != static_cast<MutableMesh<ELEMENT_DIM,SPACE_DIM>&>((this->mrMesh)).GetElementIteratorEnd(); 00430 ++elem_iter) 00431 { 00432 bool element_contains_dead_cells_or_deleted_nodes = false; 00433 00434 // Hack that covers the case where the element contains a node that is associated with a cell that has just been killed (#1129) 00435 for (unsigned i=0; i<ELEMENT_DIM+1; i++) 00436 { 00437 unsigned node_index = elem_iter->GetNodeGlobalIndex(i); 00438 00439 if (this->GetNode(node_index)->IsDeleted()) 00440 { 00441 element_contains_dead_cells_or_deleted_nodes = true; 00442 break; 00443 } 00444 else if (this->IsCellAttachedToLocationIndex(node_index)) 00445 { 00446 if (this->GetCellUsingLocationIndex(node_index)->IsDead()) 00447 { 00448 element_contains_dead_cells_or_deleted_nodes = true; 00449 break; 00450 } 00451 } 00452 } 00453 if (!element_contains_dead_cells_or_deleted_nodes) 00454 { 00455 for (unsigned i=0; i<ELEMENT_DIM+1; i++) 00456 { 00457 *mpVizElementsFile << elem_iter->GetNodeGlobalIndex(i) << " "; 00458 } 00459 } 00460 } 00461 *mpVizElementsFile << "\n"; 00462 00463 // Write data to file. 00464 if (mOutputVoronoiData) 00465 { 00466 WriteVoronoiResultsToFile(); 00467 } 00468 if (mOutputCellPopulationVolumes) 00469 { 00470 WriteCellPopulationVolumeResultsToFile(); 00471 } 00472 00473 } 00474 00475 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM> 00476 void MeshBasedCellPopulation<ELEMENT_DIM,SPACE_DIM>::WriteVtkResultsToFile() 00477 { 00478 #ifdef CHASTE_VTK 00479 // Write time to file 00480 std::stringstream time; 00481 time << SimulationTime::Instance()->GetTimeStepsElapsed(); 00482 00483 unsigned num_points = GetNumNodes(); 00484 if (!mWriteVtkAsPoints && (mpVoronoiTessellation != NULL)) 00485 { 00486 num_points = mpVoronoiTessellation->GetNumElements(); 00487 } 00488 00489 std::vector<double> cell_types(num_points); 00490 std::vector<double> cell_ancestors(num_points); 00491 std::vector<double> cell_mutation_states(num_points); 00492 std::vector<double> cell_ages(num_points); 00493 std::vector<double> cell_cycle_phases(num_points); 00494 std::vector<std::vector<double> > cellwise_data; 00495 00496 unsigned num_cell_data_items = 0; 00497 std::vector<std::string> cell_data_names; 00498 //We assume that the first cell is representative of all cells 00499 num_cell_data_items = this->Begin()->GetCellData()->GetNumItems(); 00500 cell_data_names = this->Begin()->GetCellData()->GetKeys(); 00501 00502 for (unsigned var=0; var<num_cell_data_items; var++) 00503 { 00504 std::vector<double> cellwise_data_var(num_points); 00505 cellwise_data.push_back(cellwise_data_var); 00506 } 00507 00508 if (mWriteVtkAsPoints) 00509 { 00510 VtkMeshWriter<SPACE_DIM,SPACE_DIM> mesh_writer(this->mDirPath, "results_"+time.str(), false); 00511 00512 // Loop over cells 00513 for (typename AbstractCellPopulation<ELEMENT_DIM,SPACE_DIM>::Iterator cell_iter = this->Begin(); 00514 cell_iter != this->End(); 00515 ++cell_iter) 00516 { 00517 // Get the node index corresponding to this cell 00518 unsigned node_index = this->GetLocationIndexUsingCell(*cell_iter); 00519 00520 // Get this cell-cycle model 00521 AbstractCellCycleModel* p_model = cell_iter->GetCellCycleModel(); 00522 00523 if (this->mOutputCellAncestors) 00524 { 00525 double ancestor_index = (cell_iter->GetAncestor() == UNSIGNED_UNSET) ? (-1.0) : (double)cell_iter->GetAncestor(); 00526 cell_ancestors[node_index] = ancestor_index; 00527 } 00528 if (this->mOutputCellProliferativeTypes) 00529 { 00530 cell_types[node_index] = cell_iter->GetCellProliferativeType(); 00531 } 00532 if (this->mOutputCellMutationStates) 00533 { 00534 cell_mutation_states[node_index] = cell_iter->GetMutationState()->GetColour(); 00535 } 00536 if (this->mOutputCellAges) 00537 { 00538 cell_ages[node_index] = cell_iter->GetAge(); 00539 } 00540 if (this->mOutputCellCyclePhases) 00541 { 00542 cell_cycle_phases[node_index] = p_model->GetCurrentCellCyclePhase(); 00543 } 00544 for (unsigned var=0; var<num_cell_data_items; var++) 00545 { 00546 cellwise_data[var][node_index] = cell_iter->GetCellData()->GetItem(cell_data_names[var]); 00547 } 00548 } 00549 00550 if (this->mOutputCellProliferativeTypes) 00551 { 00552 mesh_writer.AddPointData("Cell types", cell_types); 00553 } 00554 if (this->mOutputCellAncestors) 00555 { 00556 mesh_writer.AddPointData("Ancestors", cell_ancestors); 00557 } 00558 if (this->mOutputCellMutationStates) 00559 { 00560 mesh_writer.AddPointData("Mutation states", cell_mutation_states); 00561 } 00562 if (this->mOutputCellAges) 00563 { 00564 mesh_writer.AddPointData("Ages", cell_ages); 00565 } 00566 if (this->mOutputCellCyclePhases) 00567 { 00568 mesh_writer.AddPointData("Cycle phases", cell_cycle_phases); 00569 } 00570 if (num_cell_data_items > 0) 00571 { 00572 for (unsigned var=0; var<cellwise_data.size(); var++) 00573 { 00574 mesh_writer.AddPointData(cell_data_names[var], cellwise_data[var]); 00575 } 00576 } 00577 00578 { 00579 // Make a copy of the nodes in a disposable mesh for writing 00580 std::vector<Node<SPACE_DIM>* > nodes; 00581 for (unsigned index=0; index<this->mrMesh.GetNumNodes(); index++) 00582 { 00583 Node<SPACE_DIM>* p_node = this->mrMesh.GetNode(index); 00584 nodes.push_back(p_node); 00585 } 00586 00587 NodesOnlyMesh<SPACE_DIM> mesh; 00588 mesh.ConstructNodesWithoutMesh(nodes); 00589 mesh_writer.WriteFilesUsingMesh(mesh); 00590 } 00591 00592 *(this->mpVtkMetaFile) << " <DataSet timestep=\""; 00593 *(this->mpVtkMetaFile) << SimulationTime::Instance()->GetTimeStepsElapsed(); 00594 *(this->mpVtkMetaFile) << "\" group=\"\" part=\"0\" file=\"results_"; 00595 *(this->mpVtkMetaFile) << SimulationTime::Instance()->GetTimeStepsElapsed(); 00596 *(this->mpVtkMetaFile) << ".vtu\"/>\n"; 00597 } 00598 else if (mpVoronoiTessellation != NULL) 00599 { 00600 VertexMeshWriter<ELEMENT_DIM,SPACE_DIM> mesh_writer(this->mDirPath, "results", false); 00601 std::vector<double> cell_volumes(num_points); 00602 00603 // Loop over elements of mpVoronoiTessellation 00604 for (typename VertexMesh<ELEMENT_DIM,SPACE_DIM>::VertexElementIterator elem_iter = mpVoronoiTessellation->GetElementIteratorBegin(); 00605 elem_iter != mpVoronoiTessellation->GetElementIteratorEnd(); 00606 ++elem_iter) 00607 { 00608 // Get index of this element in mpVoronoiTessellation 00609 unsigned elem_index = elem_iter->GetIndex(); 00610 00611 // Get the index of the corresponding node in mrMesh 00612 unsigned node_index = mpVoronoiTessellation->GetDelaunayNodeIndexCorrespondingToVoronoiElementIndex(elem_index); 00613 00614 // There should be no ghost nodes 00615 assert(!this->IsGhostNode(node_index)); 00616 00617 // Get the cell corresponding to this element 00618 CellPtr p_cell = this->GetCellUsingLocationIndex(node_index); 00619 00620 // Get this cell-cycle model 00621 AbstractCellCycleModel* p_model = p_cell->GetCellCycleModel(); 00622 00623 if (this->mOutputCellAncestors) 00624 { 00625 double ancestor_index = (p_cell->GetAncestor() == UNSIGNED_UNSET) ? (-1.0) : (double)p_cell->GetAncestor(); 00626 cell_ancestors[elem_index] = ancestor_index; 00627 } 00628 if (this->mOutputCellProliferativeTypes) 00629 { 00630 cell_types[elem_index] = p_cell->GetCellProliferativeType(); 00631 } 00632 if (this->mOutputCellMutationStates) 00633 { 00634 cell_mutation_states[elem_index] = p_cell->GetMutationState()->GetColour(); 00635 } 00636 if (this->mOutputCellAges) 00637 { 00638 cell_ages[elem_index] = p_cell->GetAge(); 00639 } 00640 if (this->mOutputCellCyclePhases) 00641 { 00642 cell_cycle_phases[elem_index] = p_model->GetCurrentCellCyclePhase(); 00643 } 00644 if (this->mOutputCellVolumes) 00645 { 00646 cell_volumes[elem_index] = mpVoronoiTessellation->GetVolumeOfElement(elem_index); 00647 } 00648 for (unsigned var=0; var<num_cell_data_items; var++) 00649 { 00650 cellwise_data[var][elem_index] = p_cell->GetCellData()->GetItem(cell_data_names[var]); 00651 } 00652 } 00653 00654 if (this->mOutputCellProliferativeTypes) 00655 { 00656 mesh_writer.AddCellData("Cell types", cell_types); 00657 } 00658 if (this->mOutputCellAncestors) 00659 { 00660 mesh_writer.AddCellData("Ancestors", cell_ancestors); 00661 } 00662 if (this->mOutputCellMutationStates) 00663 { 00664 mesh_writer.AddCellData("Mutation states", cell_mutation_states); 00665 } 00666 if (this->mOutputCellAges) 00667 { 00668 mesh_writer.AddCellData("Ages", cell_ages); 00669 } 00670 if (this->mOutputCellCyclePhases) 00671 { 00672 mesh_writer.AddCellData("Cycle phases", cell_cycle_phases); 00673 } 00674 if (this->mOutputCellVolumes) 00675 { 00676 mesh_writer.AddCellData("Cell volumes", cell_volumes); 00677 } 00678 if (num_cell_data_items > 0) 00679 { 00680 for (unsigned var=0; var<cellwise_data.size(); var++) 00681 { 00682 mesh_writer.AddCellData(cell_data_names[var], cellwise_data[var]); 00683 } 00684 } 00685 00686 mesh_writer.WriteVtkUsingMesh(*mpVoronoiTessellation, time.str()); 00687 *(this->mpVtkMetaFile) << " <DataSet timestep=\""; 00688 *(this->mpVtkMetaFile) << SimulationTime::Instance()->GetTimeStepsElapsed(); 00689 *(this->mpVtkMetaFile) << "\" group=\"\" part=\"0\" file=\"results_"; 00690 *(this->mpVtkMetaFile) << SimulationTime::Instance()->GetTimeStepsElapsed(); 00691 *(this->mpVtkMetaFile) << ".vtu\"/>\n"; 00692 } 00693 #endif //CHASTE_VTK 00694 } 00695 00696 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM> 00697 void MeshBasedCellPopulation<ELEMENT_DIM,SPACE_DIM>::WriteVoronoiResultsToFile() 00698 { 00699 assert(SPACE_DIM==2 || SPACE_DIM==3); 00700 assert(mpVoronoiTessellation != NULL); 00701 // Write time to file 00702 *mpVoronoiFile << SimulationTime::Instance()->GetTime() << " "; 00703 00704 // Loop over elements of mpVoronoiTessellation 00705 for (typename VertexMesh<ELEMENT_DIM,SPACE_DIM>::VertexElementIterator elem_iter = mpVoronoiTessellation->GetElementIteratorBegin(); 00706 elem_iter != mpVoronoiTessellation->GetElementIteratorEnd(); 00707 ++elem_iter) 00708 { 00709 // Get index of this element in mpVoronoiTessellation 00710 unsigned elem_index = elem_iter->GetIndex(); 00711 00712 // Get the index of the corresponding node in mrMesh 00713 unsigned node_index = mpVoronoiTessellation->GetDelaunayNodeIndexCorrespondingToVoronoiElementIndex(elem_index); 00714 00715 // Write node index and location to file 00716 *mpVoronoiFile << node_index << " "; 00717 c_vector<double, SPACE_DIM> node_location = this->GetNode(node_index)->rGetLocation(); 00718 for (unsigned i=0; i<SPACE_DIM; i++) 00719 { 00720 *mpVoronoiFile << node_location[i] << " "; 00721 } 00722 00723 double cell_volume = mpVoronoiTessellation->GetVolumeOfElement(elem_index); 00724 double cell_surface_area = mpVoronoiTessellation->GetSurfaceAreaOfElement(elem_index); 00725 *mpVoronoiFile << cell_volume << " " << cell_surface_area << " "; 00726 } 00727 *mpVoronoiFile << "\n"; 00728 } 00729 00730 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM> 00731 void MeshBasedCellPopulation<ELEMENT_DIM,SPACE_DIM>::WriteCellPopulationVolumeResultsToFile() 00732 { 00733 assert(SPACE_DIM==2 || SPACE_DIM==3); 00734 00735 // Write time to file 00736 *mpCellPopulationVolumesFile << SimulationTime::Instance()->GetTime() << " "; 00737 assert (this->mpVoronoiTessellation != NULL); 00738 00739 // Don't use the Voronoi tessellation to calculate the total area of the mesh because it gives huge areas for boundary cells 00740 double total_area = static_cast<MutableMesh<ELEMENT_DIM,SPACE_DIM>&>((this->mrMesh)).GetVolume(); 00741 double apoptotic_area = 0.0; 00742 00743 // Loop over elements of mpVoronoiTessellation 00744 for (typename VertexMesh<ELEMENT_DIM,SPACE_DIM>::VertexElementIterator elem_iter = mpVoronoiTessellation->GetElementIteratorBegin(); 00745 elem_iter != mpVoronoiTessellation->GetElementIteratorEnd(); 00746 ++elem_iter) 00747 { 00748 // Get index of this element in mpVoronoiTessellation 00749 unsigned elem_index = elem_iter->GetIndex(); 00750 00751 // Get the index of the corresponding node in mrMesh 00752 unsigned node_index = mpVoronoiTessellation->GetDelaunayNodeIndexCorrespondingToVoronoiElementIndex(elem_index); 00753 00754 // Discount ghost nodes 00755 if (!this->IsGhostNode(node_index)) 00756 { 00757 // Get the cell corresponding to this node 00758 CellPtr p_cell = this->GetCellUsingLocationIndex(node_index); 00759 00760 // Only bother calculating the area/volume of apoptotic cells 00761 bool cell_is_apoptotic = p_cell->HasCellProperty<ApoptoticCellProperty>(); 00762 if (cell_is_apoptotic) 00763 { 00764 double cell_volume = mpVoronoiTessellation->GetVolumeOfElement(elem_index); 00765 apoptotic_area += cell_volume; 00766 } 00767 } 00768 } 00769 *mpCellPopulationVolumesFile << total_area << " " << apoptotic_area << "\n"; 00770 } 00771 00772 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM> 00773 double MeshBasedCellPopulation<ELEMENT_DIM,SPACE_DIM>::GetVolumeOfCell(CellPtr pCell) 00774 { 00775 // Ensure that the Voronoi tessellation exists 00776 if (mpVoronoiTessellation == NULL) 00777 { 00778 CreateVoronoiTessellation(); 00779 } 00780 00781 // Get the node index corresponding to this cell 00782 unsigned node_index = this->GetLocationIndexUsingCell(pCell); 00783 00784 // Get the element index of the Voronoi tessellation corresponding to this node index 00785 unsigned element_index = mpVoronoiTessellation->GetVoronoiElementIndexCorrespondingToDelaunayNodeIndex(node_index); 00786 00787 // Get the cell's volume from the Voronoi tessellation 00788 double cell_volume = mpVoronoiTessellation->GetVolumeOfElement(element_index); 00789 00790 return cell_volume; 00791 } 00792 00793 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM> 00794 void MeshBasedCellPopulation<ELEMENT_DIM,SPACE_DIM>::WriteCellVolumeResultsToFile() 00795 { 00796 assert (mpVoronoiTessellation != NULL); 00797 assert(SPACE_DIM==2 || SPACE_DIM==3); 00798 00799 // Write time to file 00800 *(this->mpCellVolumesFile) << SimulationTime::Instance()->GetTime() << " "; 00801 00803 00804 // Loop over elements of mpVoronoiTessellation 00805 for (typename VertexMesh<ELEMENT_DIM,SPACE_DIM>::VertexElementIterator elem_iter = mpVoronoiTessellation->GetElementIteratorBegin(); 00806 elem_iter != mpVoronoiTessellation->GetElementIteratorEnd(); 00807 ++elem_iter) 00808 { 00809 // Get index of this element in mpVoronoiTessellation 00810 unsigned elem_index = elem_iter->GetIndex(); 00811 00812 // Get the index of the corresponding node in mrMesh 00813 unsigned node_index = mpVoronoiTessellation->GetDelaunayNodeIndexCorrespondingToVoronoiElementIndex(elem_index); 00814 00815 // Discount ghost nodes 00816 if (!this->IsGhostNode(node_index)) 00817 { 00818 // Write node index to file 00819 *(this->mpCellVolumesFile) << node_index << " "; 00820 00821 // Get the cell corresponding to this node 00822 CellPtr p_cell = this->GetCellUsingLocationIndex(node_index); 00823 00824 // Write cell ID to file 00825 unsigned cell_index = p_cell->GetCellId(); 00826 *(this->mpCellVolumesFile) << cell_index << " "; 00827 00828 // Write node location to file 00829 c_vector<double, SPACE_DIM> node_location = this->GetNode(node_index)->rGetLocation(); 00830 for (unsigned i=0; i<SPACE_DIM; i++) 00831 { 00832 *(this->mpCellVolumesFile) << node_location[i] << " "; 00833 } 00834 00835 // Write cell volume (in 3D) or area (in 2D) to file 00836 double cell_volume = this->GetVolumeOfCell(p_cell); 00837 *(this->mpCellVolumesFile) << cell_volume << " "; 00838 } 00839 } 00840 *(this->mpCellVolumesFile) << "\n"; 00841 00842 } 00843 00844 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM> 00845 void MeshBasedCellPopulation<ELEMENT_DIM,SPACE_DIM>::SetWriteVtkAsPoints(bool writeVtkAsPoints) 00846 { 00847 mWriteVtkAsPoints = writeVtkAsPoints; 00848 } 00849 00850 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM> 00851 bool MeshBasedCellPopulation<ELEMENT_DIM,SPACE_DIM>::GetWriteVtkAsPoints() 00852 { 00853 return mWriteVtkAsPoints; 00854 } 00855 00857 // Spring iterator class // 00859 00860 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM> 00861 Node<SPACE_DIM>* MeshBasedCellPopulation<ELEMENT_DIM,SPACE_DIM>::SpringIterator::GetNodeA() 00862 { 00863 return mEdgeIter.GetNodeA(); 00864 } 00865 00866 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM> 00867 Node<SPACE_DIM>* MeshBasedCellPopulation<ELEMENT_DIM,SPACE_DIM>::SpringIterator::GetNodeB() 00868 { 00869 return mEdgeIter.GetNodeB(); 00870 } 00871 00872 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM> 00873 CellPtr MeshBasedCellPopulation<ELEMENT_DIM,SPACE_DIM>::SpringIterator::GetCellA() 00874 { 00875 assert((*this) != mrCellPopulation.SpringsEnd()); 00876 return mrCellPopulation.GetCellUsingLocationIndex(mEdgeIter.GetNodeA()->GetIndex()); 00877 } 00878 00879 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM> 00880 CellPtr MeshBasedCellPopulation<ELEMENT_DIM,SPACE_DIM>::SpringIterator::GetCellB() 00881 { 00882 assert((*this) != mrCellPopulation.SpringsEnd()); 00883 return mrCellPopulation.GetCellUsingLocationIndex(mEdgeIter.GetNodeB()->GetIndex()); 00884 } 00885 00886 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM> 00887 bool MeshBasedCellPopulation<ELEMENT_DIM,SPACE_DIM>::SpringIterator::operator!=(const MeshBasedCellPopulation<ELEMENT_DIM,SPACE_DIM>::SpringIterator& rOther) 00888 { 00889 return (mEdgeIter != rOther.mEdgeIter); 00890 } 00891 00892 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM> 00893 typename MeshBasedCellPopulation<ELEMENT_DIM,SPACE_DIM>::SpringIterator& MeshBasedCellPopulation<ELEMENT_DIM,SPACE_DIM>::SpringIterator::operator++() 00894 { 00895 bool edge_is_ghost = false; 00896 00897 do 00898 { 00899 ++mEdgeIter; 00900 if (*this != mrCellPopulation.SpringsEnd()) 00901 { 00902 bool a_is_ghost = mrCellPopulation.IsGhostNode(mEdgeIter.GetNodeA()->GetIndex()); 00903 bool b_is_ghost = mrCellPopulation.IsGhostNode(mEdgeIter.GetNodeB()->GetIndex()); 00904 00905 edge_is_ghost = (a_is_ghost || b_is_ghost); 00906 } 00907 } 00908 while (*this!=mrCellPopulation.SpringsEnd() && edge_is_ghost); 00909 00910 return (*this); 00911 } 00912 00913 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM> 00914 MeshBasedCellPopulation<ELEMENT_DIM,SPACE_DIM>::SpringIterator::SpringIterator( 00915 MeshBasedCellPopulation<ELEMENT_DIM,SPACE_DIM>& rCellPopulation, 00916 typename MutableMesh<ELEMENT_DIM,SPACE_DIM>::EdgeIterator edgeIter) 00917 : mrCellPopulation(rCellPopulation), 00918 mEdgeIter(edgeIter) 00919 { 00920 if (mEdgeIter!=static_cast<MutableMesh<ELEMENT_DIM,SPACE_DIM>*>(&(this->mrCellPopulation.mrMesh))->EdgesEnd()) 00921 { 00922 bool a_is_ghost = mrCellPopulation.IsGhostNode(mEdgeIter.GetNodeA()->GetIndex()); 00923 bool b_is_ghost = mrCellPopulation.IsGhostNode(mEdgeIter.GetNodeB()->GetIndex()); 00924 00925 if (a_is_ghost || b_is_ghost) 00926 { 00927 ++(*this); 00928 } 00929 } 00930 } 00931 00932 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM> 00933 typename MeshBasedCellPopulation<ELEMENT_DIM,SPACE_DIM>::SpringIterator MeshBasedCellPopulation<ELEMENT_DIM,SPACE_DIM>::SpringsBegin() 00934 { 00935 return SpringIterator(*this, static_cast<MutableMesh<ELEMENT_DIM,SPACE_DIM>&>((this->mrMesh)).EdgesBegin()); 00936 } 00937 00938 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM> 00939 typename MeshBasedCellPopulation<ELEMENT_DIM,SPACE_DIM>::SpringIterator MeshBasedCellPopulation<ELEMENT_DIM,SPACE_DIM>::SpringsEnd() 00940 { 00941 return SpringIterator(*this, static_cast<MutableMesh<ELEMENT_DIM,SPACE_DIM>&>((this->mrMesh)).EdgesEnd()); 00942 } 00943 00947 template<> 00948 void MeshBasedCellPopulation<2>::CreateVoronoiTessellation() 00949 { 00950 delete mpVoronoiTessellation; 00951 00952 // Check if the mesh associated with this cell population is periodic 00953 bool is_mesh_periodic = false; 00954 if (dynamic_cast<Cylindrical2dMesh*>(&mrMesh)) 00955 { 00956 is_mesh_periodic = true; 00957 } 00958 00959 mpVoronoiTessellation = new VertexMesh<2, 2>(static_cast<MutableMesh<2, 2> &>((this->mrMesh)), is_mesh_periodic); 00960 } 00961 00965 template<> 00966 void MeshBasedCellPopulation<2,3>::CreateVoronoiTessellation() 00967 { 00968 // We don't allow tessellation yet. 00969 NEVER_REACHED; 00970 } 00971 00977 template<> 00978 void MeshBasedCellPopulation<3>::CreateVoronoiTessellation() 00979 { 00980 delete mpVoronoiTessellation; 00981 mpVoronoiTessellation = new VertexMesh<3, 3>(static_cast<MutableMesh<3, 3> &>((this->mrMesh))); 00982 } 00983 00988 template<> 00989 void MeshBasedCellPopulation<1, 1>::CreateVoronoiTessellation() 00990 { 00991 // No 1D Voronoi tessellation 00992 NEVER_REACHED; 00993 } 00994 00999 template<> 01000 void MeshBasedCellPopulation<1, 2>::CreateVoronoiTessellation() 01001 { 01002 // No 1D Voronoi tessellation 01003 NEVER_REACHED; 01004 } 01005 01010 template<> 01011 void MeshBasedCellPopulation<1, 3>::CreateVoronoiTessellation() 01012 { 01013 // No 1D Voronoi tessellation 01014 NEVER_REACHED; 01015 } 01016 01017 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM> 01018 VertexMesh<ELEMENT_DIM,SPACE_DIM>* MeshBasedCellPopulation<ELEMENT_DIM,SPACE_DIM>::GetVoronoiTessellation() 01019 { 01020 assert(mpVoronoiTessellation!=NULL); 01021 return mpVoronoiTessellation; 01022 } 01023 01024 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM> 01025 double MeshBasedCellPopulation<ELEMENT_DIM,SPACE_DIM>::GetVolumeOfVoronoiElement(unsigned index) 01026 { 01027 unsigned element_index = mpVoronoiTessellation->GetVoronoiElementIndexCorrespondingToDelaunayNodeIndex(index); 01028 double volume = mpVoronoiTessellation->GetVolumeOfElement(element_index); 01029 return volume; 01030 } 01031 01032 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM> 01033 double MeshBasedCellPopulation<ELEMENT_DIM,SPACE_DIM>::GetSurfaceAreaOfVoronoiElement(unsigned index) 01034 { 01035 unsigned element_index = mpVoronoiTessellation->GetVoronoiElementIndexCorrespondingToDelaunayNodeIndex(index); 01036 double surface_area = mpVoronoiTessellation->GetSurfaceAreaOfElement(element_index); 01037 return surface_area; 01038 } 01039 01040 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM> 01041 double MeshBasedCellPopulation<ELEMENT_DIM,SPACE_DIM>::GetVoronoiEdgeLength(unsigned index1, unsigned index2) 01042 { 01043 unsigned element_index1 = mpVoronoiTessellation->GetVoronoiElementIndexCorrespondingToDelaunayNodeIndex(index1); 01044 unsigned element_index2 = mpVoronoiTessellation->GetVoronoiElementIndexCorrespondingToDelaunayNodeIndex(index2); 01045 try 01046 { 01047 double edge_length = mpVoronoiTessellation->GetEdgeLength(element_index1, element_index2); 01048 return edge_length; 01049 } 01050 catch (Exception& e) 01051 { 01052 // The edge was between two (potentially infinite) cells on the boundary of the mesh 01053 EXCEPTION("Spring iterator tried to calculate interaction between degenerate cells on the boundary of the mesh. Have you set ghost layers correctly?"); 01054 } 01055 } 01056 01057 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM> 01058 void MeshBasedCellPopulation<ELEMENT_DIM,SPACE_DIM>::CheckCellPointers() 01059 { 01060 bool res = true; 01061 for (std::list<CellPtr>::iterator it=this->mCells.begin(); 01062 it!=this->mCells.end(); 01063 ++it) 01064 { 01065 CellPtr p_cell = *it; 01066 assert(p_cell); 01067 AbstractCellCycleModel* p_model = p_cell->GetCellCycleModel(); 01068 assert(p_model); 01069 01070 // Check cell exists in cell population 01071 unsigned node_index = this->GetLocationIndexUsingCell(p_cell); 01072 std::cout << "Cell at node " << node_index << " addr " << p_cell << std::endl << std::flush; 01073 CellPtr p_cell_in_cell_population = this->GetCellUsingLocationIndex(node_index); 01074 #define COVERAGE_IGNORE //Debugging code. Shouldn't fail under normal conditions 01075 if (p_cell_in_cell_population != p_cell) 01076 { 01077 std::cout << " Mismatch with cell population" << std::endl << std::flush; 01078 res = false; 01079 } 01080 01081 // Check model links back to cell 01082 if (p_model->GetCell() != p_cell) 01083 { 01084 std::cout << " Mismatch with cycle model" << std::endl << std::flush; 01085 res = false; 01086 } 01087 } 01088 assert(res); 01089 #undef COVERAGE_IGNORE 01090 01091 res = true; 01092 for (std::set<std::pair<CellPtr,CellPtr> >::iterator it1 = this->mMarkedSprings.begin(); 01093 it1 != this->mMarkedSprings.end(); 01094 ++it1) 01095 { 01096 const std::pair<CellPtr,CellPtr>& r_pair = *it1; 01097 01098 for (unsigned i=0; i<2; i++) 01099 { 01100 CellPtr p_cell = (i==0 ? r_pair.first : r_pair.second); 01101 01102 assert(p_cell); 01103 AbstractCellCycleModel* p_model = p_cell->GetCellCycleModel(); 01104 assert(p_model); 01105 unsigned node_index = this->GetLocationIndexUsingCell(p_cell); 01106 std::cout << "Cell at node " << node_index << " addr " << p_cell << std::endl << std::flush; 01107 01108 #define COVERAGE_IGNORE //Debugging code. Shouldn't fail under normal conditions 01109 // Check cell is alive 01110 if (p_cell->IsDead()) 01111 { 01112 std::cout << " Cell is dead" << std::endl << std::flush; 01113 res = false; 01114 } 01115 01116 // Check cell exists in cell population 01117 CellPtr p_cell_in_cell_population = this->GetCellUsingLocationIndex(node_index); 01118 if (p_cell_in_cell_population != p_cell) 01119 { 01120 std::cout << " Mismatch with cell population" << std::endl << std::flush; 01121 res = false; 01122 } 01123 01124 // Check model links back to cell 01125 if (p_model->GetCell() != p_cell) 01126 { 01127 std::cout << " Mismatch with cycle model" << std::endl << std::flush; 01128 res = false; 01129 } 01130 } 01131 #undef COVERAGE_IGNORE 01132 } 01133 assert(res); 01134 } 01135 01136 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM> 01137 double MeshBasedCellPopulation<ELEMENT_DIM,SPACE_DIM>::GetAreaBasedDampingConstantParameter() 01138 { 01139 return mAreaBasedDampingConstantParameter; 01140 } 01141 01142 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM> 01143 void MeshBasedCellPopulation<ELEMENT_DIM,SPACE_DIM>::SetAreaBasedDampingConstantParameter(double areaBasedDampingConstantParameter) 01144 { 01145 assert(areaBasedDampingConstantParameter >= 0.0); 01146 mAreaBasedDampingConstantParameter = areaBasedDampingConstantParameter; 01147 } 01148 01149 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM> 01150 bool MeshBasedCellPopulation<ELEMENT_DIM,SPACE_DIM>::GetOutputVoronoiData() 01151 { 01152 return mOutputVoronoiData; 01153 } 01154 01155 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM> 01156 void MeshBasedCellPopulation<ELEMENT_DIM,SPACE_DIM>::SetOutputVoronoiData(bool outputVoronoiData) 01157 { 01158 mOutputVoronoiData = outputVoronoiData; 01159 } 01160 01161 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM> 01162 bool MeshBasedCellPopulation<ELEMENT_DIM,SPACE_DIM>::GetOutputCellPopulationVolumes() 01163 { 01164 return mOutputCellPopulationVolumes; 01165 } 01166 01167 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM> 01168 void MeshBasedCellPopulation<ELEMENT_DIM,SPACE_DIM>::SetOutputCellPopulationVolumes(bool outputCellPopulationVolumes) 01169 { 01170 mOutputCellPopulationVolumes = outputCellPopulationVolumes; 01171 } 01172 01173 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM> 01174 std::set< std::pair<Node<SPACE_DIM>*, Node<SPACE_DIM>* > >& MeshBasedCellPopulation<ELEMENT_DIM,SPACE_DIM>::rGetNodePairs() 01175 { 01176 //mNodePairs.Clear(); 01177 NEVER_REACHED; 01178 return mNodePairs; 01179 } 01180 01181 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM> 01182 void MeshBasedCellPopulation<ELEMENT_DIM,SPACE_DIM>::OutputCellPopulationParameters(out_stream& rParamsFile) 01183 { 01184 *rParamsFile << "\t\t<UseAreaBasedDampingConstant>" << mUseAreaBasedDampingConstant << "</UseAreaBasedDampingConstant>\n"; 01185 *rParamsFile << "\t\t<AreaBasedDampingConstantParameter>" << mAreaBasedDampingConstantParameter << "</AreaBasedDampingConstantParameter>\n"; 01186 *rParamsFile << "\t\t<OutputVoronoiData>" << mOutputVoronoiData << "</OutputVoronoiData>\n"; 01187 *rParamsFile << "\t\t<OutputCellPopulationVolumes>" << mOutputCellPopulationVolumes << "</OutputCellPopulationVolumes>\n"; 01188 01189 // Call method on direct parent class 01190 AbstractCentreBasedCellPopulation<ELEMENT_DIM,SPACE_DIM>::OutputCellPopulationParameters(rParamsFile); 01191 } 01192 01193 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM> 01194 double MeshBasedCellPopulation<ELEMENT_DIM,SPACE_DIM>::GetWidth(const unsigned& rDimension) 01195 { 01196 // Call GetWidth() on the mesh 01197 double width = this->mrMesh.GetWidth(rDimension); 01198 return width; 01199 } 01200 01201 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM> 01202 std::set<unsigned> MeshBasedCellPopulation<ELEMENT_DIM,SPACE_DIM>::GetNeighbouringNodeIndices(unsigned index) 01203 { 01204 // Get pointer to this node 01205 Node<SPACE_DIM>* p_node = this->mrMesh.GetNode(index); 01206 01207 // Loop over containing elements 01208 std::set<unsigned> neighbouring_node_indices; 01209 for (typename Node<SPACE_DIM>::ContainingElementIterator elem_iter = p_node->ContainingElementsBegin(); 01210 elem_iter != p_node->ContainingElementsEnd(); 01211 ++elem_iter) 01212 { 01213 // Get pointer to this containing element 01214 Element<ELEMENT_DIM,SPACE_DIM>* p_element = static_cast<MutableMesh<ELEMENT_DIM,SPACE_DIM>&>((this->mrMesh)).GetElement(*elem_iter); 01215 01216 // Loop over nodes contained in this element 01217 for (unsigned i=0; i<p_element->GetNumNodes(); i++) 01218 { 01219 // Get index of this node and add its index to the set if not the original node 01220 unsigned node_index = p_element->GetNodeGlobalIndex(i); 01221 if (node_index != index) 01222 { 01223 neighbouring_node_indices.insert(node_index); 01224 } 01225 } 01226 } 01227 return neighbouring_node_indices; 01228 } 01229 01230 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM> 01231 void MeshBasedCellPopulation<ELEMENT_DIM,SPACE_DIM>::CalculateRestLengths() 01232 { 01233 mSpringRestLengths.clear(); 01234 01235 // Iterate over all springs and add calculate separation of adjacent node pairs 01236 for (SpringIterator spring_iterator = SpringsBegin(); 01237 spring_iterator != SpringsEnd(); 01238 ++spring_iterator) 01239 { 01240 // Note that nodeA_global_index is always less than nodeB_global_index 01241 Node<SPACE_DIM>* p_nodeA = spring_iterator.GetNodeA(); 01242 Node<SPACE_DIM>* p_nodeB = spring_iterator.GetNodeB(); 01243 01244 unsigned nodeA_global_index = p_nodeA->GetIndex(); 01245 unsigned nodeB_global_index = p_nodeB->GetIndex(); 01246 01247 // Calculate the distance between nodes 01248 c_vector<double, SPACE_DIM> node_a_location = p_nodeA->rGetLocation(); 01249 c_vector<double, SPACE_DIM> node_b_location = p_nodeB->rGetLocation(); 01250 01251 double separation = norm_2(rGetMesh().GetVectorFromAtoB(node_a_location, node_b_location)); 01252 01253 std::pair<unsigned,unsigned> node_pair (nodeA_global_index, nodeB_global_index) ; 01254 01255 mSpringRestLengths[node_pair]= separation; 01256 } 01257 mHasVariableRestLength = true; 01258 } 01259 01260 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM> 01261 double MeshBasedCellPopulation<ELEMENT_DIM,SPACE_DIM>::GetRestLength(unsigned indexA, unsigned indexB) 01262 { 01263 if (mHasVariableRestLength) 01264 { 01265 std::pair<unsigned,unsigned> node_pair (indexA, indexB) ; 01266 01267 std::map<std::pair<unsigned,unsigned>, double>::const_iterator iter = mSpringRestLengths.find(node_pair); 01268 01269 if (iter != mSpringRestLengths.end() ) 01270 { 01271 // Return the stored rest length. 01272 return iter->second; 01273 } 01274 else 01275 { 01276 NEVER_REACHED; 01278 //EXCEPTION("Tried to get a rest length of an edge that doesn't exist. You can only use variable rest lengths if SetUpdateCellPopulationRule is set on the simulation."); 01279 } 01280 } 01281 else 01282 { 01283 return 1.0; 01284 } 01285 } 01286 01287 01289 // Explicit instantiation 01291 01292 template class MeshBasedCellPopulation<1,1>; 01293 template class MeshBasedCellPopulation<1,2>; 01294 template class MeshBasedCellPopulation<2,2>; 01295 template class MeshBasedCellPopulation<1,3>; 01296 template class MeshBasedCellPopulation<2,3>; 01297 template class MeshBasedCellPopulation<3,3>; 01298 01299 // Serialization for Boost >= 1.36 01300 #include "SerializationExportWrapperForCpp.hpp" 01301 EXPORT_TEMPLATE_CLASS_ALL_DIMS(MeshBasedCellPopulation)