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 "NodeBasedCellPopulation.hpp" 00037 #include "VtkMeshWriter.hpp" 00038 00039 template<unsigned DIM> 00040 NodeBasedCellPopulation<DIM>::NodeBasedCellPopulation(NodesOnlyMesh<DIM>& rMesh, 00041 std::vector<CellPtr>& rCells, 00042 const std::vector<unsigned> locationIndices, 00043 bool deleteMesh, 00044 bool validate) 00045 : AbstractCentreBasedCellPopulation<DIM>(rMesh, rCells, locationIndices), 00046 mDeleteMesh(deleteMesh), 00047 mMechanicsCutOffLength(DBL_MAX), 00048 mUseVariableRadii(false) 00049 { 00050 mpNodesOnlyMesh = static_cast<NodesOnlyMesh<DIM>* >(&(this->mrMesh)); 00051 if (validate) 00052 { 00053 Validate(); 00054 } 00055 } 00056 00057 template<unsigned DIM> 00058 NodeBasedCellPopulation<DIM>::NodeBasedCellPopulation(NodesOnlyMesh<DIM>& rMesh) 00059 : AbstractCentreBasedCellPopulation<DIM>(rMesh), 00060 mDeleteMesh(true), 00061 mMechanicsCutOffLength(DBL_MAX), // will be set by serialize() method 00062 mUseVariableRadii(false) // will be set by serialize() method 00063 { 00064 mpNodesOnlyMesh = static_cast<NodesOnlyMesh<DIM>* >(&(this->mrMesh)); 00065 // No Validate() because the cells are not associated with the cell population yet in archiving 00066 } 00067 00068 template<unsigned DIM> 00069 NodeBasedCellPopulation<DIM>::~NodeBasedCellPopulation() 00070 { 00071 Clear(); 00072 if (mDeleteMesh) 00073 { 00074 delete &this->mrMesh; 00075 } 00076 } 00077 00078 template<unsigned DIM> 00079 NodesOnlyMesh<DIM>& NodeBasedCellPopulation<DIM>::rGetMesh() 00080 { 00081 return *mpNodesOnlyMesh; 00082 } 00083 00084 template<unsigned DIM> 00085 const NodesOnlyMesh<DIM>& NodeBasedCellPopulation<DIM>::rGetMesh() const 00086 { 00087 return *mpNodesOnlyMesh; 00088 } 00089 00090 template<unsigned DIM> 00091 void NodeBasedCellPopulation<DIM>::Clear() 00092 { 00093 mNodePairs.clear(); 00094 } 00095 00096 template<unsigned DIM> 00097 void NodeBasedCellPopulation<DIM>::Validate() 00098 { 00099 std::vector<bool> validated_node(GetNumNodes()); 00100 for (unsigned i=0; i<validated_node.size(); i++) 00101 { 00102 validated_node[i] = false; 00103 } 00104 00105 for (typename AbstractCellPopulation<DIM>::Iterator cell_iter=this->Begin(); cell_iter!=this->End(); ++cell_iter) 00106 { 00107 unsigned node_index = this->GetLocationIndexUsingCell((*cell_iter)); 00108 validated_node[node_index] = true; 00109 } 00110 00111 for (unsigned i=0; i<validated_node.size(); i++) 00112 { 00113 if (!validated_node[i]) 00114 { 00115 EXCEPTION("Node " << i << " does not appear to have a cell associated with it"); 00116 } 00117 } 00118 } 00119 00120 template<unsigned DIM> 00121 void NodeBasedCellPopulation<DIM>::SplitUpIntoBoxes(double cutOffLength, c_vector<double, 2*DIM> domainSize) 00122 { 00123 mpNodesOnlyMesh->SetUpBoxCollection(cutOffLength, domainSize); 00124 } 00125 00126 template<unsigned DIM> 00127 void NodeBasedCellPopulation<DIM>::FindMaxAndMin() 00128 { 00129 c_vector<double, DIM> min_posn; 00130 c_vector<double, DIM> max_posn; 00131 for (unsigned i=0; i<DIM; i++) 00132 { 00133 min_posn(i) = DBL_MAX; 00134 max_posn(i) = -DBL_MAX; 00135 } 00136 00137 for (unsigned i=0; i<this->mrMesh.GetNumNodes(); i++) 00138 { 00139 c_vector<double, DIM> posn = this->GetNode(i)->rGetLocation(); 00140 00141 for (unsigned j=0; j<DIM; j++) 00142 { 00143 if (posn(j) > max_posn(j)) 00144 { 00145 max_posn(j) = posn(j); 00146 } 00147 if (posn(j) < min_posn(j)) 00148 { 00149 min_posn(j) = posn(j); 00150 } 00151 } 00152 } 00153 00154 for (unsigned i=0; i<DIM; i++) 00155 { 00156 assert(min_posn(i) != DBL_MAX); 00157 mMinSpatialPositions(i) = min_posn(i); 00158 00159 assert(max_posn(i) != -DBL_MAX); 00160 mMaxSpatialPositions(i) = max_posn(i); 00161 } 00162 } 00163 00164 template<unsigned DIM> 00165 Node<DIM>* NodeBasedCellPopulation<DIM>::GetNode(unsigned index) 00166 { 00167 return this->mrMesh.GetNode(index); 00168 } 00169 00170 template<unsigned DIM> 00171 void NodeBasedCellPopulation<DIM>::SetNode(unsigned nodeIndex, ChastePoint<DIM>& rNewLocation) 00172 { 00173 mpNodesOnlyMesh->GetNode(nodeIndex)->SetPoint(rNewLocation); 00174 } 00175 00176 template<unsigned DIM> 00177 void NodeBasedCellPopulation<DIM>::Update(bool hasHadBirthsOrDeaths) 00178 { 00179 NodeMap map(this->mrMesh.GetNumAllNodes()); 00180 mpNodesOnlyMesh->ReMesh(map); 00181 00182 if (!map.IsIdentityMap()) 00183 { 00184 UpdateParticlesAfterReMesh(map); 00185 00186 // Update the mappings between cells and location indices 00188 std::map<Cell*, unsigned> old_map = this->mCellLocationMap; 00189 00190 // Remove any dead pointers from the maps (needed to avoid archiving errors) 00191 this->mLocationCellMap.clear(); 00192 this->mCellLocationMap.clear(); 00193 00194 for (std::list<CellPtr>::iterator it = this->mCells.begin(); 00195 it != this->mCells.end(); 00196 ++it) 00197 { 00198 unsigned old_node_index = old_map[(*it).get()]; 00199 00200 // This shouldn't ever happen, as the cell vector only contains living cells 00201 assert(!map.IsDeleted(old_node_index)); 00202 00203 unsigned new_node_index = map.GetNewIndex(old_node_index); 00204 this->SetCellUsingLocationIndex(new_node_index,*it); 00205 } 00206 00207 this->Validate(); 00208 } 00209 00210 mpNodesOnlyMesh->SetMeshHasChangedSinceLoading(); 00211 00212 mpNodesOnlyMesh->ClearBoxCollection(); 00213 00214 FindMaxAndMin(); 00215 00216 // Something here to set up the domain size (max and min of each node position dimension) 00217 c_vector<double, 2*DIM> domain_size; 00218 for (unsigned i=0; i<DIM; i++) 00219 { 00220 domain_size(2*i) = mMinSpatialPositions(i); 00221 domain_size(2*i+1) = mMaxSpatialPositions(i); 00222 } 00223 00224 if (mMechanicsCutOffLength == DBL_MAX) 00225 { 00226 std::string error = std::string("NodeBasedCellPopulation cannot create boxes if the cut-off length has not been set - ") 00227 + std::string("Call SetMechanicsCutOffLength on the CellPopulation ensuring it is larger than GetCutOffLength() on the force law"); 00228 EXCEPTION(error); 00229 } 00230 00231 /* 00232 * Add this parameter and suggest that mechanics systems set it. 00233 * Allocates memory for mpBoxCollection and does the splitting 00234 * and putting nodes into boxes. 00235 */ 00236 00237 mpNodesOnlyMesh->SetUpBoxCollection(mMechanicsCutOffLength, domain_size); 00238 00239 mpNodesOnlyMesh->CalculateNodePairs(mNodePairs, mNodeNeighbours); 00240 00241 /* 00242 * Update cell radii based on CellData 00243 */ 00244 if (mUseVariableRadii) 00245 { 00246 for (typename AbstractCellPopulation<DIM>::Iterator cell_iter = this->Begin(); 00247 cell_iter != this->End(); 00248 ++cell_iter) 00249 { 00250 double cell_radius = cell_iter->GetCellData()->GetItem("Radius"); 00251 unsigned node_index = this->GetLocationIndexUsingCell(*cell_iter); 00252 mpNodesOnlyMesh->SetCellRadius(node_index, cell_radius); 00253 } 00254 } 00255 } 00256 00257 template<unsigned DIM> 00258 unsigned NodeBasedCellPopulation<DIM>::RemoveDeadCells() 00259 { 00260 unsigned num_removed = 0; 00261 for (std::list<CellPtr>::iterator cell_iter = this->mCells.begin(); 00262 cell_iter != this->mCells.end(); 00263 ++cell_iter) 00264 { 00265 if ((*cell_iter)->IsDead()) 00266 { 00267 // Remove the node from the mesh 00268 num_removed++; 00269 mpNodesOnlyMesh->DeleteNodePriorToReMesh(this->GetLocationIndexUsingCell((*cell_iter))); 00270 00271 // Update mappings between cells and location indices 00272 unsigned location_index_of_removed_node = this->GetLocationIndexUsingCell((*cell_iter)); 00273 this->RemoveCellUsingLocationIndex(location_index_of_removed_node, (*cell_iter)); 00274 00275 // Update vector of cells 00276 cell_iter = this->mCells.erase(cell_iter); 00277 --cell_iter; 00278 } 00279 } 00280 00281 return num_removed; 00282 } 00283 00284 template<unsigned DIM> 00285 unsigned NodeBasedCellPopulation<DIM>::AddNode(Node<DIM>* pNewNode) 00286 { 00287 return mpNodesOnlyMesh->AddNode(pNewNode); 00288 } 00289 00290 template<unsigned DIM> 00291 unsigned NodeBasedCellPopulation<DIM>::GetNumNodes() 00292 { 00293 return mpNodesOnlyMesh->GetNumAllNodes(); 00294 } 00295 00296 template<unsigned DIM> 00297 void NodeBasedCellPopulation<DIM>::UpdateParticlesAfterReMesh(NodeMap& rMap) 00298 { 00299 } 00300 00301 template<unsigned DIM> 00302 BoxCollection<DIM>* NodeBasedCellPopulation<DIM>::GetBoxCollection() 00303 { 00304 return mpNodesOnlyMesh->GetBoxCollection(); 00305 } 00306 00307 template<unsigned DIM> 00308 std::set< std::pair<Node<DIM>*, Node<DIM>* > >& NodeBasedCellPopulation<DIM>::rGetNodePairs() 00309 { 00310 // if (mNodePairs.empty()) 00311 // { 00312 // EXCEPTION("No node pairs set up, rGetNodePairs probably called before Update"); 00313 // } 00314 return mNodePairs; 00315 } 00316 00317 template<unsigned DIM> 00318 void NodeBasedCellPopulation<DIM>::OutputCellPopulationParameters(out_stream& rParamsFile) 00319 { 00320 *rParamsFile << "\t\t<MechanicsCutOffLength>" << mMechanicsCutOffLength << "</MechanicsCutOffLength>\n"; 00321 *rParamsFile << "\t\t<UseVariableRadii>" << mUseVariableRadii << 00322 "</UseVariableRadii>\n"; 00323 00324 // Call method on direct parent class 00325 AbstractCentreBasedCellPopulation<DIM>::OutputCellPopulationParameters(rParamsFile); 00326 } 00327 00328 template<unsigned DIM> 00329 void NodeBasedCellPopulation<DIM>::SetMechanicsCutOffLength(double mechanicsCutOffLength) 00330 { 00331 assert(mechanicsCutOffLength > 0.0); 00332 mMechanicsCutOffLength = mechanicsCutOffLength; 00333 } 00334 00335 template<unsigned DIM> 00336 double NodeBasedCellPopulation<DIM>::GetMechanicsCutOffLength() 00337 { 00338 return mMechanicsCutOffLength; 00339 } 00340 00341 template<unsigned DIM> 00342 bool NodeBasedCellPopulation<DIM>::GetUseVariableRadii() 00343 { 00344 return mUseVariableRadii; 00345 } 00346 00347 template<unsigned DIM> 00348 void NodeBasedCellPopulation<DIM>::SetUseVariableRadii(bool useVariableRadii) 00349 { 00350 mUseVariableRadii = useVariableRadii; 00351 } 00352 00353 template<unsigned DIM> 00354 double NodeBasedCellPopulation<DIM>::GetWidth(const unsigned& rDimension) 00355 { 00356 // Update the member variables mMinSpatialPositions and mMaxSpatialPositions 00357 FindMaxAndMin(); 00358 00359 // Compute the maximum distance between any nodes in this dimension 00360 double width = mMaxSpatialPositions(rDimension) - mMinSpatialPositions(rDimension); 00361 00362 return width; 00363 } 00364 00365 template<unsigned DIM> 00366 std::set<unsigned> NodeBasedCellPopulation<DIM>::GetNeighbouringNodeIndices(unsigned index) 00367 { 00368 // Check the mNodeNeighbours has been set up correctly 00369 if (mNodeNeighbours.empty()) 00370 { 00371 EXCEPTION("mNodeNeighbours not set up. Call Update() before GetNeighbouringNodeIndices()"); 00372 } 00373 00374 std::set<unsigned> neighbouring_node_indices; 00375 00376 // Get location and radius of node 00377 c_vector<double, DIM> node_i_location = this->GetNode(index)->rGetLocation(); 00378 double radius_of_cell_i = mpNodesOnlyMesh->GetCellRadius(index); 00379 00380 // Make sure that the max_interaction distance is smaller than the box collection size 00381 if (!(radius_of_cell_i * 2.0 < mMechanicsCutOffLength)) 00382 { 00383 EXCEPTION("mMechanicsCutOffLength is smaller than twice the radius of cell " << index << " (" << radius_of_cell_i << ") so interactions may be missed. Make the cut-off larger to avoid errors."); 00384 } 00385 00386 00387 // Get set of 'candidate' neighbours. 00388 std::set<unsigned> near_nodes = mNodeNeighbours.find(index)->second; 00389 00390 // Find which ones are actually close 00391 for (std::set<unsigned>::iterator iter = near_nodes.begin(); 00392 iter != near_nodes.end(); 00393 ++iter) 00394 { 00395 // Be sure not to return the index itself. 00396 if ((*iter) != index) 00397 { 00398 // Get the location of this node 00399 c_vector<double, DIM> node_j_location = this->GetNode((*iter))->rGetLocation(); 00400 00401 // Get the vector the two nodes (assuming no periodicities etc.) 00402 c_vector<double, DIM> node_to_node_vector = node_i_location - node_j_location; 00403 00404 // Calculate the distance between the two nodes 00405 double distance_between_nodes = norm_2(node_to_node_vector); 00406 00407 // Get the radius of the cell corresponding to this node 00408 double radius_of_cell_j = mpNodesOnlyMesh->GetCellRadius((*iter)); 00409 00410 // If the cells are close enough to exert a force on each other... 00411 double max_interaction_distance = radius_of_cell_i + radius_of_cell_j; 00412 00413 // Make sure that the max_interaction distance is smaller than the box collection size 00414 if (!(max_interaction_distance < mMechanicsCutOffLength)) 00415 { 00416 EXCEPTION("mMechanicsCutOffLength is smaller than the sum of radius of cell " << index << " (" << radius_of_cell_i << ") and cell " << (*iter) << " (" << radius_of_cell_j <<"). Make the cut-off larger to avoid errors."); 00417 } 00418 if (distance_between_nodes <= max_interaction_distance)// + DBL_EPSILSON) //Assumes that max_interaction_distance is of over 1 00419 { 00420 // ...then add this node index to the set of neighbouring node indices 00421 neighbouring_node_indices.insert((*iter)); 00422 } 00423 } 00424 } 00425 00426 return neighbouring_node_indices; 00427 } 00428 00429 template<unsigned DIM> 00430 double NodeBasedCellPopulation<DIM>::GetVolumeOfCell(CellPtr pCell) 00431 { 00432 // Get node index corresponding to this cell 00433 unsigned node_index = this->GetLocationIndexUsingCell(pCell); 00434 00435 // Get cell radius 00436 double cell_radius = mpNodesOnlyMesh->GetCellRadius(node_index); 00437 00438 // Begin code to approximate cell volume 00439 double averaged_cell_radius = 0.0; 00440 unsigned num_cells = 0; 00441 00442 // Get the location of this node 00443 c_vector<double, DIM> node_i_location = GetNode(node_index)->rGetLocation(); 00444 00445 // Get the set of node indices corresponding to this cell's neighbours 00446 std::set<unsigned> neighbouring_node_indices = GetNeighbouringNodeIndices(node_index); 00447 00448 // Loop over this set 00449 for (std::set<unsigned>::iterator iter = neighbouring_node_indices.begin(); 00450 iter != neighbouring_node_indices.end(); 00451 ++iter) 00452 { 00453 // Get the location of the neighbouring node 00454 c_vector<double, DIM> node_j_location = GetNode(*iter)->rGetLocation(); 00455 00456 double neighbouring_cell_radius = mpNodesOnlyMesh->GetCellRadius( *iter); 00457 00458 // If this throws then you may not be considering all cell interactions use a larger cut off length 00459 assert(cell_radius+neighbouring_cell_radius<mMechanicsCutOffLength); 00460 00461 // Calculate the distance between the two nodes and add to cell radius 00462 double separation = norm_2(node_j_location - node_i_location); 00463 00464 if (separation < cell_radius+neighbouring_cell_radius) 00465 { 00466 // The effective radius is the mid point of the overlap 00467 averaged_cell_radius = averaged_cell_radius + cell_radius - (cell_radius+neighbouring_cell_radius-separation)/2.0; 00468 num_cells++; 00469 } 00470 } 00471 if (num_cells == 0) 00472 { 00473 averaged_cell_radius = cell_radius; 00474 } 00475 else 00476 { 00477 averaged_cell_radius /= num_cells; 00478 } 00479 assert(averaged_cell_radius<mMechanicsCutOffLength/2.0); 00480 00481 cell_radius = averaged_cell_radius; 00482 00483 // End code to approximate cell volume 00484 00485 // Calculate cell volume from radius of cell 00486 double cell_volume = 0.0; 00487 if (DIM == 2) 00488 { 00489 cell_volume = M_PI*cell_radius*cell_radius; 00490 } 00491 else if (DIM == 3) 00492 { 00493 cell_volume = (4.0/3.0)*M_PI*cell_radius*cell_radius*cell_radius; 00494 } 00495 00496 return cell_volume; 00497 } 00498 00499 template<unsigned DIM> 00500 void NodeBasedCellPopulation<DIM>::WriteCellVolumeResultsToFile() 00501 { 00502 assert(DIM==2 || DIM==3); 00503 00504 // Write time to file 00505 *(this->mpCellVolumesFile) << SimulationTime::Instance()->GetTime() << " "; 00506 00507 // Loop over cells 00508 for (typename AbstractCellPopulation<DIM>::Iterator cell_iter = this->Begin(); 00509 cell_iter != this->End(); 00510 ++cell_iter) 00511 { 00512 // Get the index of the corresponding node in mrMesh 00513 unsigned node_index = this->GetLocationIndexUsingCell(*cell_iter); 00514 00515 // Write node index to file 00516 *(this->mpCellVolumesFile) << node_index << " "; 00517 00518 // Write cell ID to file 00519 *(this->mpCellVolumesFile) << cell_iter->GetCellId() << " "; 00520 00521 // Write node location to file 00522 c_vector<double, DIM> node_location = this->GetNode(node_index)->rGetLocation(); 00523 for (unsigned i=0; i<DIM; i++) 00524 { 00525 *(this->mpCellVolumesFile) << node_location[i] << " "; 00526 } 00527 00528 // Write cell volume (in 3D) or area (in 2D) to file 00529 double cell_volume = this->GetVolumeOfCell(*cell_iter); 00530 *(this->mpCellVolumesFile) << cell_volume << " "; 00531 } 00532 00533 *(this->mpCellVolumesFile) << "\n"; 00534 } 00535 00536 template<unsigned DIM> 00537 void NodeBasedCellPopulation<DIM>::WriteVtkResultsToFile() 00538 { 00539 #ifdef CHASTE_VTK 00540 std::stringstream time; 00541 time << SimulationTime::Instance()->GetTimeStepsElapsed(); 00542 VtkMeshWriter<DIM, DIM> mesh_writer(this->mDirPath, "results_"+time.str(), false); 00543 00544 unsigned num_nodes = GetNumNodes(); 00545 std::vector<double> cell_types(num_nodes); 00546 std::vector<double> cell_ancestors(num_nodes); 00547 std::vector<double> cell_mutation_states(num_nodes); 00548 std::vector<double> cell_ages(num_nodes); 00549 std::vector<double> cell_cycle_phases(num_nodes); 00550 std::vector<double> cell_radii(num_nodes); 00551 std::vector<std::vector<double> > cellwise_data; 00552 00553 unsigned num_cell_data_items = 0; 00554 std::vector<std::string> cell_data_names; 00555 //We assume that the first cell is representative of all cells 00556 num_cell_data_items = this->Begin()->GetCellData()->GetNumItems(); 00557 cell_data_names = this->Begin()->GetCellData()->GetKeys(); 00558 00559 for (unsigned var=0; var<num_cell_data_items; var++) 00560 { 00561 std::vector<double> cellwise_data_var(num_nodes); 00562 cellwise_data.push_back(cellwise_data_var); 00563 } 00564 00565 00566 // Loop over cells 00567 for (typename AbstractCellPopulation<DIM>::Iterator cell_iter = this->Begin(); 00568 cell_iter != this->End(); 00569 ++cell_iter) 00570 { 00571 // Get the node index corresponding to this cell 00572 unsigned node_index = this->GetLocationIndexUsingCell(*cell_iter); 00573 00574 if (this->mOutputCellAncestors) 00575 { 00576 double ancestor_index = (cell_iter->GetAncestor() == UNSIGNED_UNSET) ? (-1.0) : (double)cell_iter->GetAncestor(); 00577 cell_ancestors[node_index] = ancestor_index; 00578 } 00579 if (this->mOutputCellProliferativeTypes) 00580 { 00581 double cell_type = cell_iter->GetCellProliferativeType(); 00582 cell_types[node_index] = cell_type; 00583 } 00584 if (this->mOutputCellMutationStates) 00585 { 00586 double mutation_state = cell_iter->GetMutationState()->GetColour(); 00587 00588 CellPropertyCollection collection = cell_iter->rGetCellPropertyCollection(); 00589 CellPropertyCollection label_collection = collection.GetProperties<CellLabel>(); 00590 00591 if (label_collection.GetSize()==1 ) 00592 { 00593 boost::shared_ptr<CellLabel> p_label = boost::static_pointer_cast<CellLabel>(label_collection.GetProperty()); 00594 mutation_state = p_label->GetColour(); 00595 } 00596 00597 cell_mutation_states[node_index] = mutation_state; 00598 } 00599 if (this->mOutputCellAges) 00600 { 00601 double age = cell_iter->GetAge(); 00602 cell_ages[node_index] = age; 00603 } 00604 if (this->mOutputCellCyclePhases) 00605 { 00606 double cycle_phase = cell_iter->GetCellCycleModel()->GetCurrentCellCyclePhase(); 00607 cell_cycle_phases[node_index] = cycle_phase; 00608 } 00609 if (this->mOutputCellVolumes) 00610 { 00611 double cell_radius = mpNodesOnlyMesh->GetCellRadius(node_index); 00612 cell_radii[node_index] = cell_radius; 00613 } 00614 00615 for (unsigned var=0; var<num_cell_data_items; var++) 00616 { 00617 cellwise_data[var][node_index] = cell_iter->GetCellData()->GetItem(cell_data_names[var]); 00618 } 00619 } 00620 00621 if (this->mOutputCellProliferativeTypes) 00622 { 00623 mesh_writer.AddPointData("Cell types", cell_types); 00624 } 00625 if (this->mOutputCellAncestors) 00626 { 00627 mesh_writer.AddPointData("Ancestors", cell_ancestors); 00628 } 00629 if (this->mOutputCellMutationStates) 00630 { 00631 mesh_writer.AddPointData("Mutation states", cell_mutation_states); 00632 } 00633 if (this->mOutputCellAges) 00634 { 00635 mesh_writer.AddPointData("Ages", cell_ages); 00636 } 00637 if (this->mOutputCellCyclePhases) 00638 { 00639 mesh_writer.AddPointData("Cycle phases", cell_cycle_phases); 00640 } 00641 if (this->mOutputCellVolumes) 00642 { 00643 mesh_writer.AddPointData("Cell radii", cell_radii); 00644 } 00645 if (num_cell_data_items > 0) 00646 { 00647 for (unsigned var=0; var<cellwise_data.size(); var++) 00648 { 00649 mesh_writer.AddPointData(cell_data_names[var], cellwise_data[var]); 00650 } 00651 } 00652 00653 mesh_writer.WriteFilesUsingMesh(*mpNodesOnlyMesh); 00654 00655 *(this->mpVtkMetaFile) << " <DataSet timestep=\""; 00656 *(this->mpVtkMetaFile) << SimulationTime::Instance()->GetTimeStepsElapsed(); 00657 *(this->mpVtkMetaFile) << "\" group=\"\" part=\"0\" file=\"results_"; 00658 *(this->mpVtkMetaFile) << SimulationTime::Instance()->GetTimeStepsElapsed(); 00659 *(this->mpVtkMetaFile) << ".vtu\"/>\n"; 00660 #endif //CHASTE_VTK 00661 } 00662 00663 template<unsigned DIM> 00664 CellPtr NodeBasedCellPopulation<DIM>::AddCell(CellPtr pNewCell, const c_vector<double,DIM>& rCellDivisionVector, CellPtr pParentCell) 00665 { 00666 assert(pNewCell); 00667 00668 // Add new cell to cell population 00669 CellPtr p_created_cell = AbstractCentreBasedCellPopulation<DIM>::AddCell(pNewCell, rCellDivisionVector, pParentCell); 00670 assert(p_created_cell == pNewCell); 00671 00672 // Then set the new cell radius in the NodesOnlyMesh 00673 unsigned parent_node_index = this->GetLocationIndexUsingCell(pParentCell); 00674 unsigned new_node_index = this->GetLocationIndexUsingCell(p_created_cell); 00675 mpNodesOnlyMesh->SetCellRadius(new_node_index, mpNodesOnlyMesh->GetCellRadius(parent_node_index)); 00676 00677 // Return pointer to new cell 00678 return p_created_cell; 00679 } 00680 00682 // Explicit instantiation 00684 00685 template class NodeBasedCellPopulation<1>; 00686 template class NodeBasedCellPopulation<2>; 00687 template class NodeBasedCellPopulation<3>; 00688 00689 // Serialization for Boost >= 1.36 00690 #include "SerializationExportWrapperForCpp.hpp" 00691 EXPORT_TEMPLATE_CLASS_SAME_DIMS(NodeBasedCellPopulation)