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 "VertexBasedCellPopulation.hpp" 00037 #include "VertexMeshWriter.hpp" 00038 #include "Warnings.hpp" 00039 00040 template<unsigned DIM> 00041 VertexBasedCellPopulation<DIM>::VertexBasedCellPopulation(MutableVertexMesh<DIM, DIM>& rMesh, 00042 std::vector<CellPtr>& rCells, 00043 bool deleteMesh, 00044 bool validate, 00045 const std::vector<unsigned> locationIndices) 00046 : AbstractOffLatticeCellPopulation<DIM>(rMesh, rCells, locationIndices), 00047 mDeleteMesh(deleteMesh) 00048 { 00049 mpMutableVertexMesh = static_cast<MutableVertexMesh<DIM, DIM>* >(&(this->mrMesh)); 00050 00051 // Check the mesh contains boundary nodes 00052 bool contains_boundary_nodes = false; 00053 for (typename MutableVertexMesh<DIM,DIM>::NodeIterator node_iter = mpMutableVertexMesh->GetNodeIteratorBegin(); 00054 node_iter != mpMutableVertexMesh->GetNodeIteratorEnd(); 00055 ++node_iter) 00056 { 00057 if (node_iter->IsBoundaryNode()) 00058 { 00059 contains_boundary_nodes = true; 00060 } 00061 } 00062 //if (mpMutableVertexMesh->GetNumBoundaryNodes() == 0) 00064 if (!contains_boundary_nodes) 00065 { 00066 EXCEPTION("No boundary nodes are defined in the supplied vertex mesh which are needed for vertex based simulations."); 00067 } 00068 00069 // Check each element has only one cell attached 00070 if (validate) 00071 { 00072 Validate(); 00073 } 00074 } 00075 00076 template<unsigned DIM> 00077 VertexBasedCellPopulation<DIM>::VertexBasedCellPopulation(MutableVertexMesh<DIM, DIM>& rMesh) 00078 : AbstractOffLatticeCellPopulation<DIM>(rMesh), 00079 mDeleteMesh(true) 00080 { 00081 mpMutableVertexMesh = static_cast<MutableVertexMesh<DIM, DIM>* >(&(this->mrMesh)); 00082 } 00083 00084 template<unsigned DIM> 00085 VertexBasedCellPopulation<DIM>::~VertexBasedCellPopulation() 00086 { 00087 if (mDeleteMesh) 00088 { 00089 delete &this->mrMesh; 00090 } 00091 } 00092 00093 template<unsigned DIM> 00094 double VertexBasedCellPopulation<DIM>::GetDampingConstant(unsigned nodeIndex) 00095 { 00096 // Take the average of the cells containing this vertex 00097 double average_damping_constant = 0.0; 00098 00099 std::set<unsigned> containing_elements = GetNode(nodeIndex)->rGetContainingElementIndices(); 00100 double temp = 1.0/((double) containing_elements.size()); 00101 00102 for (std::set<unsigned>::iterator iter = containing_elements.begin(); 00103 iter != containing_elements.end(); 00104 ++iter) 00105 { 00106 CellPtr p_cell = this->GetCellUsingLocationIndex(*iter); 00107 bool cell_is_wild_type = p_cell->GetMutationState()->IsType<WildTypeCellMutationState>(); 00108 bool cell_is_labelled = p_cell->HasCellProperty<CellLabel>(); 00109 00110 if (cell_is_wild_type && !cell_is_labelled) 00111 { 00112 average_damping_constant += this->GetDampingConstantNormal()*temp; 00113 } 00114 else 00115 { 00116 average_damping_constant += this->GetDampingConstantMutant()*temp; 00117 } 00118 } 00119 00120 return average_damping_constant; 00121 } 00122 00123 template<unsigned DIM> 00124 MutableVertexMesh<DIM, DIM>& VertexBasedCellPopulation<DIM>::rGetMesh() 00125 { 00126 return *mpMutableVertexMesh; 00127 } 00128 00129 template<unsigned DIM> 00130 const MutableVertexMesh<DIM, DIM>& VertexBasedCellPopulation<DIM>::rGetMesh() const 00131 { 00132 return *mpMutableVertexMesh; 00133 } 00134 00135 template<unsigned DIM> 00136 VertexElement<DIM, DIM>* VertexBasedCellPopulation<DIM>::GetElement(unsigned elementIndex) 00137 { 00138 return mpMutableVertexMesh->GetElement(elementIndex); 00139 } 00140 00141 template<unsigned DIM> 00142 unsigned VertexBasedCellPopulation<DIM>::GetNumNodes() 00143 { 00144 return this->mrMesh.GetNumNodes(); 00145 } 00146 00147 template<unsigned DIM> 00148 c_vector<double, DIM> VertexBasedCellPopulation<DIM>::GetLocationOfCellCentre(CellPtr pCell) 00149 { 00150 return mpMutableVertexMesh->GetCentroidOfElement(this->mCellLocationMap[pCell.get()]); 00151 } 00152 00153 template<unsigned DIM> 00154 Node<DIM>* VertexBasedCellPopulation<DIM>::GetNode(unsigned index) 00155 { 00156 return this->mrMesh.GetNode(index); 00157 } 00158 00159 template<unsigned DIM> 00160 unsigned VertexBasedCellPopulation<DIM>::AddNode(Node<DIM>* pNewNode) 00161 { 00162 return mpMutableVertexMesh->AddNode(pNewNode); 00163 } 00164 00165 template<unsigned DIM> 00166 void VertexBasedCellPopulation<DIM>::SetNode(unsigned nodeIndex, ChastePoint<DIM>& rNewLocation) 00167 { 00168 mpMutableVertexMesh->SetNode(nodeIndex, rNewLocation); 00169 } 00170 00171 template<unsigned DIM> 00172 VertexElement<DIM, DIM>* VertexBasedCellPopulation<DIM>::GetElementCorrespondingToCell(CellPtr pCell) 00173 { 00174 return mpMutableVertexMesh->GetElement(this->GetLocationIndexUsingCell(pCell)); 00175 } 00176 00177 template<unsigned DIM> 00178 unsigned VertexBasedCellPopulation<DIM>::GetNumElements() 00179 { 00180 return mpMutableVertexMesh->GetNumElements(); 00181 } 00182 00183 template<unsigned DIM> 00184 CellPtr VertexBasedCellPopulation<DIM>::AddCell(CellPtr pNewCell, const c_vector<double,DIM>& rCellDivisionVector, CellPtr pParentCell) 00185 { 00186 // Get the element associated with this cell 00187 VertexElement<DIM, DIM>* p_element = GetElementCorrespondingToCell(pParentCell); 00188 00189 // Divide the element 00190 unsigned new_element_index; 00191 if (norm_2(rCellDivisionVector) < DBL_EPSILON) 00192 { 00193 // If the cell division vector is the default zero vector, divide the element along the short axis 00194 new_element_index = mpMutableVertexMesh->DivideElementAlongShortAxis(p_element, true); 00195 } 00196 else 00197 { 00198 // If the cell division vector has any non-zero component, divide the element along this axis 00199 new_element_index = mpMutableVertexMesh->DivideElementAlongGivenAxis(p_element, rCellDivisionVector, true); 00200 } 00201 00202 // Associate the new cell with the element 00203 this->mCells.push_back(pNewCell); 00204 00205 // Update location cell map 00206 CellPtr p_created_cell = this->mCells.back(); 00207 this->SetCellUsingLocationIndex(new_element_index,p_created_cell); 00208 this->mCellLocationMap[p_created_cell.get()] = new_element_index; 00209 return p_created_cell; 00210 } 00211 00212 template<unsigned DIM> 00213 unsigned VertexBasedCellPopulation<DIM>::RemoveDeadCells() 00214 { 00215 unsigned num_removed = 0; 00216 00217 for (std::list<CellPtr>::iterator it = this->mCells.begin(); 00218 it != this->mCells.end(); 00219 ++it) 00220 { 00221 if ((*it)->IsDead()) 00222 { 00223 // Remove the element from the mesh 00224 num_removed++; 00225 mpMutableVertexMesh->DeleteElementPriorToReMesh(this->GetLocationIndexUsingCell((*it))); 00226 it = this->mCells.erase(it); 00227 --it; 00228 } 00229 } 00230 return num_removed; 00231 } 00232 00233 template<unsigned DIM> 00234 void VertexBasedCellPopulation<DIM>::UpdateNodeLocations(const std::vector< c_vector<double, DIM> >& rNodeForces, double dt) 00235 { 00236 // Iterate over all nodes associated with real cells to update their positions 00237 for (unsigned node_index=0; node_index<GetNumNodes(); node_index++) 00238 { 00239 // Get the damping constant for this node 00240 double damping_const = this->GetDampingConstant(node_index); 00241 00242 // Compute the displacement of this node 00243 c_vector<double, DIM> displacement = dt*rNodeForces[node_index]/damping_const; 00244 00245 /* 00246 * If the displacement of this node is greater than half the cell rearrangement threshold, 00247 * this could result in nodes moving into the interior of other elements, which should not 00248 * be possible. Therefore in this case we restrict the displacement of the node to the cell 00249 * rearrangement threshold and warn the user that a smaller timestep should be used. This 00250 * restriction ensures that vertex elements remain well defined (see #1376). 00251 */ 00252 if (norm_2(displacement) > 0.5*mpMutableVertexMesh->GetCellRearrangementThreshold()) 00253 { 00254 WARN_ONCE_ONLY("Vertices are moving more than half the CellRearrangementThreshold. This could cause elements to become inverted so the motion has been restricted. Use a smaller timestep to avoid these warnings."); 00255 displacement *= 0.5*mpMutableVertexMesh->GetCellRearrangementThreshold()/norm_2(displacement); 00256 } 00257 00258 // Get new node location 00259 c_vector<double, DIM> new_node_location = this->GetNode(node_index)->rGetLocation() + displacement; 00260 00261 for (unsigned i=0; i<DIM; i++) 00262 { 00263 assert(!std::isnan(new_node_location(i))); 00264 } 00265 00266 // Create ChastePoint for new node location 00267 ChastePoint<DIM> new_point(new_node_location); 00268 00269 // Move the node 00270 this->SetNode(node_index, new_point); 00271 } 00272 } 00273 00274 template<unsigned DIM> 00275 bool VertexBasedCellPopulation<DIM>::IsCellAssociatedWithADeletedLocation(CellPtr pCell) 00276 { 00277 return GetElementCorrespondingToCell(pCell)->IsDeleted();; 00278 } 00279 00280 template<unsigned DIM> 00281 void VertexBasedCellPopulation<DIM>::Update(bool hasHadBirthsOrDeaths) 00282 { 00283 VertexElementMap element_map(mpMutableVertexMesh->GetNumAllElements()); 00284 00285 mpMutableVertexMesh->ReMesh(element_map); 00286 00287 if (!element_map.IsIdentityMap()) 00288 { 00289 // Fix up the mappings between CellPtrs and VertexElements 00291 std::map<Cell*, unsigned> old_map = this->mCellLocationMap; 00292 00293 this->mCellLocationMap.clear(); 00294 this->mLocationCellMap.clear(); 00295 00296 for (std::list<CellPtr>::iterator cell_iter = this->mCells.begin(); 00297 cell_iter != this->mCells.end(); 00298 ++cell_iter) 00299 { 00300 // This shouldn't ever happen, as the cell vector only contains living cells 00301 unsigned old_elem_index = old_map[(*cell_iter).get()]; 00302 00303 if (element_map.IsDeleted(old_elem_index)) 00304 { 00309 WARNING("Cell removed due to T2Swap this is not counted in the dead cells counter"); 00310 cell_iter = this->mCells.erase(cell_iter); 00311 --cell_iter; 00312 } 00313 else 00314 { 00315 unsigned new_elem_index = element_map.GetNewIndex(old_elem_index); 00316 00317 this->SetCellUsingLocationIndex(new_elem_index,*cell_iter); 00318 } 00319 } 00320 00321 // Check that each VertexElement has only one CellPtr associated with it in the updated cell population 00322 Validate(); 00323 } 00324 00325 element_map.ResetToIdentity(); 00326 } 00327 00328 template<unsigned DIM> 00329 void VertexBasedCellPopulation<DIM>::Validate() 00330 { 00331 // Check each element has only one cell attached 00332 std::vector<unsigned> validated_element = std::vector<unsigned>(this->GetNumElements(), 0); 00333 00334 for (typename AbstractCellPopulation<DIM>::Iterator cell_iter = this->Begin(); 00335 cell_iter != this->End(); 00336 ++cell_iter) 00337 { 00338 unsigned elem_index = this->GetLocationIndexUsingCell(*cell_iter); 00339 validated_element[elem_index]++; 00340 } 00341 00342 for (unsigned i=0; i<validated_element.size(); i++) 00343 { 00344 if (validated_element[i] == 0) 00345 { 00346 EXCEPTION("Element " << i << " does not appear to have a cell associated with it"); 00347 } 00348 00349 if (validated_element[i] > 1) 00350 { 00351 // This should never be reached as you can only set one cell per element index. 00352 EXCEPTION("Element " << i << " appears to have " << validated_element[i] << " cells associated with it"); 00353 } 00354 } 00355 } 00356 00357 template<unsigned DIM> 00358 void VertexBasedCellPopulation<DIM>::WriteResultsToFiles() 00359 { 00360 AbstractOffLatticeCellPopulation<DIM>::WriteResultsToFiles(); 00361 00362 SimulationTime* p_time = SimulationTime::Instance(); 00363 00364 // Write Locations of T1Swaps to file 00365 *mpT1SwapLocationsFile << p_time->GetTime() << "\t"; 00366 std::vector< c_vector<double, DIM> > t1_swap_locations = mpMutableVertexMesh->GetLocationsOfT1Swaps(); 00367 *mpT1SwapLocationsFile << t1_swap_locations.size() << "\t"; 00368 for (unsigned index = 0; index < t1_swap_locations.size(); index++) 00369 { 00370 for (unsigned i=0; i<DIM; i++) 00371 { 00372 *mpT1SwapLocationsFile << t1_swap_locations[index][i] << "\t"; 00373 } 00374 } 00375 *mpT1SwapLocationsFile << "\n"; 00376 mpMutableVertexMesh->ClearLocationsOfT1Swaps(); 00377 00378 // Write Locations of T3Swaps to file 00379 *mpT3SwapLocationsFile << p_time->GetTime() << "\t"; 00380 std::vector< c_vector<double, DIM> > t3_swap_locations = mpMutableVertexMesh->GetLocationsOfT3Swaps(); 00381 *mpT3SwapLocationsFile << t3_swap_locations.size() << "\t"; 00382 for (unsigned index = 0; index < t3_swap_locations.size(); index++) 00383 { 00384 for (unsigned i=0; i<DIM; i++) 00385 { 00386 *mpT3SwapLocationsFile << t3_swap_locations[index][i] << "\t"; 00387 } 00388 } 00389 *mpT3SwapLocationsFile << "\n"; 00390 mpMutableVertexMesh->ClearLocationsOfT3Swaps(); 00391 00392 // Write element data to file 00393 *mpVizElementsFile << p_time->GetTime() << "\t"; 00394 00395 // Loop over cells and find associated elements so in the same order as the cells in output files 00396 for (std::list<CellPtr>::iterator cell_iter = this->mCells.begin(); 00397 cell_iter != this->mCells.end(); 00398 ++cell_iter) 00399 { 00400 unsigned elem_index = this->GetLocationIndexUsingCell(*cell_iter); 00401 00402 // Hack that covers the case where the element is associated with a cell that has just been killed (#1129) 00403 bool elem_corresponds_to_dead_cell = false; 00404 00405 if (this->IsCellAttachedToLocationIndex(elem_index)) 00406 { 00407 elem_corresponds_to_dead_cell = this->GetCellUsingLocationIndex(elem_index)->IsDead(); 00408 } 00409 00410 // Write element data to file 00411 if (!(GetElement(elem_index)->IsDeleted()) && !elem_corresponds_to_dead_cell) 00412 { 00413 VertexElement<DIM, DIM>* p_element = mpMutableVertexMesh->GetElement(elem_index); 00414 00415 unsigned num_nodes_in_element = p_element->GetNumNodes(); 00416 00417 // First write the number of Nodes belonging to this VertexElement 00418 *mpVizElementsFile << num_nodes_in_element << " "; 00419 00420 // Then write the global index of each Node in this element 00421 for (unsigned i=0; i<num_nodes_in_element; i++) 00422 { 00423 *mpVizElementsFile << p_element->GetNodeGlobalIndex(i) << " "; 00424 } 00425 } 00426 } 00427 *mpVizElementsFile << "\n"; 00428 } 00429 00430 template<unsigned DIM> 00431 double VertexBasedCellPopulation<DIM>::GetVolumeOfCell(CellPtr pCell) 00432 { 00433 // Get the vertex element index corresponding to this cell 00434 unsigned elem_index = this->GetLocationIndexUsingCell(pCell); 00435 00436 // Get the cell's volume from the vertex mesh 00437 double cell_volume = mpMutableVertexMesh->GetVolumeOfElement(elem_index); 00438 00439 return cell_volume; 00440 } 00441 00442 template<unsigned DIM> 00443 void VertexBasedCellPopulation<DIM>::WriteCellVolumeResultsToFile() 00444 { 00445 assert(DIM==2); 00446 00447 // Write time to file 00448 *(this->mpCellVolumesFile) << SimulationTime::Instance()->GetTime() << " "; 00449 00450 // Loop over cells and find associated elements so in the same order as the cells in output files 00451 for (typename AbstractCellPopulation<DIM>::Iterator cell_iter = this->Begin(); 00452 cell_iter != this->End(); 00453 ++cell_iter) 00454 { 00455 unsigned elem_index = this->GetLocationIndexUsingCell(*cell_iter); 00456 00457 // Hack that covers the case where the element is associated with a cell that has just been killed (#1129) 00458 bool elem_corresponds_to_dead_cell = false; 00459 00460 if (this->IsCellAttachedToLocationIndex(elem_index)) 00461 { 00462 elem_corresponds_to_dead_cell = this->GetCellUsingLocationIndex(elem_index)->IsDead(); 00463 } 00464 00465 // Write node data to file 00466 if (!(GetElement(elem_index)->IsDeleted()) && !elem_corresponds_to_dead_cell) 00467 { 00468 // Write element index to file 00469 *(this->mpCellVolumesFile) << elem_index << " "; 00470 00471 // Write cell ID to file 00472 unsigned cell_index = (*cell_iter)->GetCellId(); 00473 *(this->mpCellVolumesFile) << cell_index << " "; 00474 00475 // Write location of element centroid to file 00476 c_vector<double, DIM> centre_location = GetLocationOfCellCentre(*cell_iter); 00477 for (unsigned i=0; i<DIM; i++) 00478 { 00479 *(this->mpCellVolumesFile) << centre_location[i] << " "; 00480 } 00481 00482 // Write cell volume (in 3D) or area (in 2D) to file 00483 double cell_volume = this->GetVolumeOfCell(*cell_iter); 00484 *(this->mpCellVolumesFile) << cell_volume << " "; 00485 } 00486 } 00487 *(this->mpCellVolumesFile) << "\n"; 00488 } 00489 00490 template<unsigned DIM> 00491 void VertexBasedCellPopulation<DIM>::WriteVtkResultsToFile() 00492 { 00493 #ifdef CHASTE_VTK 00494 SimulationTime* p_time = SimulationTime::Instance(); 00495 00496 VertexMeshWriter<DIM, DIM> mesh_writer(this->mDirPath, "results", false); 00497 std::stringstream time; 00498 time << p_time->GetTimeStepsElapsed(); 00499 00500 unsigned num_elements = mpMutableVertexMesh->GetNumElements(); 00501 std::vector<double> cell_types(num_elements); 00502 std::vector<double> cell_ancestors(num_elements); 00503 std::vector<double> cell_mutation_states(num_elements); 00504 std::vector<double> cell_ages(num_elements); 00505 std::vector<double> cell_cycle_phases(num_elements); 00506 std::vector<double> cell_volumes(num_elements); 00507 std::vector<std::vector<double> > cellwise_data; 00508 00509 unsigned num_cell_data_items = 0; 00510 std::vector<std::string> cell_data_names; 00511 //We assume that the first cell is representative of all cells 00512 num_cell_data_items = this->Begin()->GetCellData()->GetNumItems(); 00513 cell_data_names = this->Begin()->GetCellData()->GetKeys(); 00514 00515 for (unsigned var=0; var<num_cell_data_items; var++) 00516 { 00517 std::vector<double> cellwise_data_var(num_elements); 00518 cellwise_data.push_back(cellwise_data_var); 00519 } 00520 00521 // Loop over vertex elements 00522 for (typename VertexMesh<DIM,DIM>::VertexElementIterator elem_iter = mpMutableVertexMesh->GetElementIteratorBegin(); 00523 elem_iter != mpMutableVertexMesh->GetElementIteratorEnd(); 00524 ++elem_iter) 00525 { 00526 // Get index of this element in the vertex mesh 00527 unsigned elem_index = elem_iter->GetIndex(); 00528 00529 // Get the cell corresponding to this element 00530 CellPtr p_cell = this->GetCellUsingLocationIndex(elem_index); 00531 assert(p_cell); 00532 00533 if (this->mOutputCellAncestors) 00534 { 00535 double ancestor_index = (p_cell->GetAncestor() == UNSIGNED_UNSET) ? (-1.0) : (double)p_cell->GetAncestor(); 00536 cell_ancestors[elem_index] = ancestor_index; 00537 } 00538 if (this->mOutputCellProliferativeTypes) 00539 { 00540 double cell_type = p_cell->GetCellProliferativeType(); 00541 cell_types[elem_index] = cell_type; 00542 } 00543 if (this->mOutputCellMutationStates) 00544 { 00545 double mutation_state = p_cell->GetMutationState()->GetColour(); 00546 cell_mutation_states[elem_index] = mutation_state; 00547 } 00548 if (this->mOutputCellAges) 00549 { 00550 double age = p_cell->GetAge(); 00551 cell_ages[elem_index] = age; 00552 } 00553 if (this->mOutputCellCyclePhases) 00554 { 00555 double cycle_phase = p_cell->GetCellCycleModel()->GetCurrentCellCyclePhase(); 00556 cell_cycle_phases[elem_index] = cycle_phase; 00557 } 00558 if (this->mOutputCellVolumes) 00559 { 00560 double cell_volume = mpMutableVertexMesh->GetVolumeOfElement(elem_index); 00561 cell_volumes[elem_index] = cell_volume; 00562 } 00563 for (unsigned var=0; var<num_cell_data_items; var++) 00564 { 00565 cellwise_data[var][elem_index] = p_cell->GetCellData()->GetItem(cell_data_names[var]); 00566 } 00567 } 00568 00569 if (this->mOutputCellProliferativeTypes) 00570 { 00571 mesh_writer.AddCellData("Cell types", cell_types); 00572 } 00573 if (this->mOutputCellAncestors) 00574 { 00575 mesh_writer.AddCellData("Ancestors", cell_ancestors); 00576 } 00577 if (this->mOutputCellMutationStates) 00578 { 00579 mesh_writer.AddCellData("Mutation states", cell_mutation_states); 00580 } 00581 if (this->mOutputCellAges) 00582 { 00583 mesh_writer.AddCellData("Ages", cell_ages); 00584 } 00585 if (this->mOutputCellCyclePhases) 00586 { 00587 mesh_writer.AddCellData("Cycle phases", cell_cycle_phases); 00588 } 00589 if (this->mOutputCellVolumes) 00590 { 00591 mesh_writer.AddCellData("Cell volumes", cell_volumes); 00592 } 00593 if (num_cell_data_items > 0) 00594 { 00595 for (unsigned var=0; var<cellwise_data.size(); var++) 00596 { 00597 mesh_writer.AddCellData(cell_data_names[var], cellwise_data[var]); 00598 } 00599 } 00600 00601 mesh_writer.WriteVtkUsingMesh(*mpMutableVertexMesh, time.str()); 00602 *(this->mpVtkMetaFile) << " <DataSet timestep=\""; 00603 *(this->mpVtkMetaFile) << p_time->GetTimeStepsElapsed(); 00604 *(this->mpVtkMetaFile) << "\" group=\"\" part=\"0\" file=\"results_"; 00605 *(this->mpVtkMetaFile) << p_time->GetTimeStepsElapsed(); 00606 *(this->mpVtkMetaFile) << ".vtu\"/>\n"; 00607 #endif //CHASTE_VTK 00608 } 00609 00610 template<unsigned DIM> 00611 void VertexBasedCellPopulation<DIM>::CreateOutputFiles(const std::string& rDirectory, bool cleanOutputDirectory) 00612 { 00613 AbstractOffLatticeCellPopulation<DIM>::CreateOutputFiles(rDirectory, cleanOutputDirectory); 00614 00615 OutputFileHandler output_file_handler(rDirectory, cleanOutputDirectory); 00616 mpVizElementsFile = output_file_handler.OpenOutputFile("results.vizelements"); 00617 mpT1SwapLocationsFile = output_file_handler.OpenOutputFile("T1SwapLocations.dat"); 00618 mpT3SwapLocationsFile = output_file_handler.OpenOutputFile("T3SwapLocations.dat"); 00619 } 00620 00621 template<unsigned DIM> 00622 void VertexBasedCellPopulation<DIM>::CloseOutputFiles() 00623 { 00624 AbstractOffLatticeCellPopulation<DIM>::CloseOutputFiles(); 00625 mpVizElementsFile->close(); 00626 mpT1SwapLocationsFile->close(); 00627 mpT3SwapLocationsFile->close(); 00628 } 00629 00630 template<unsigned DIM> 00631 void VertexBasedCellPopulation<DIM>::GenerateCellResultsAndWriteToFiles() 00632 { 00633 // Set up cell type counter 00634 unsigned num_cell_types = this->mCellProliferativeTypeCount.size(); 00635 std::vector<unsigned> cell_type_counter(num_cell_types); 00636 for (unsigned i=0; i<num_cell_types; i++) 00637 { 00638 cell_type_counter[i] = 0; 00639 } 00640 00641 // Set up cell cycle phase counter 00642 unsigned num_cell_cycle_phases = this->mCellCyclePhaseCount.size(); 00643 std::vector<unsigned> cell_cycle_phase_counter(num_cell_cycle_phases); 00644 for (unsigned i=0; i<num_cell_cycle_phases; i++) 00645 { 00646 cell_cycle_phase_counter[i] = 0; 00647 } 00648 00649 for (typename AbstractCellPopulation<DIM>::Iterator cell_iter = this->Begin(); 00650 cell_iter != this->End(); 00651 ++cell_iter) 00652 { 00653 this->GenerateCellResults(*cell_iter, cell_type_counter, cell_cycle_phase_counter); 00654 } 00655 00656 this->WriteCellResultsToFiles(cell_type_counter, cell_cycle_phase_counter); 00657 } 00658 00659 template<unsigned DIM> 00660 void VertexBasedCellPopulation<DIM>::OutputCellPopulationParameters(out_stream& rParamsFile) 00661 { 00662 *rParamsFile << "\t\t<CellRearrangementThreshold>" << mpMutableVertexMesh->GetCellRearrangementThreshold() << "</CellRearrangementThreshold>\n"; 00663 *rParamsFile << "\t\t<T2Threshold>" << mpMutableVertexMesh->GetT2Threshold() << "</T2Threshold>\n"; 00664 *rParamsFile << "\t\t<CellRearrangementRatio>" << mpMutableVertexMesh->GetCellRearrangementRatio() << "</CellRearrangementRatio>\n"; 00665 00666 // Call method on direct parent class 00667 AbstractOffLatticeCellPopulation<DIM>::OutputCellPopulationParameters(rParamsFile); 00668 } 00669 00670 template<unsigned DIM> 00671 double VertexBasedCellPopulation<DIM>::GetWidth(const unsigned& rDimension) 00672 { 00673 // Call GetWidth() on the mesh 00674 double width = this->mrMesh.GetWidth(rDimension); 00675 00676 return width; 00677 } 00678 00679 template<unsigned DIM> 00680 std::set<unsigned> VertexBasedCellPopulation<DIM>::GetNeighbouringNodeIndices(unsigned index) 00681 { 00682 return mpMutableVertexMesh->GetNeighbouringNodeIndices(index); 00683 } 00684 00686 // Explicit instantiation 00688 00689 template class VertexBasedCellPopulation<1>; 00690 template class VertexBasedCellPopulation<2>; 00691 template class VertexBasedCellPopulation<3>; 00692 00693 // Serialization for Boost >= 1.36 00694 #include "SerializationExportWrapperForCpp.hpp" 00695 EXPORT_TEMPLATE_CLASS_SAME_DIMS(VertexBasedCellPopulation)