00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029 #include "VertexBasedCellPopulation.hpp"
00030 #include "CellwiseData.hpp"
00031 #include "VertexMeshWriter.hpp"
00032 #include "Warnings.hpp"
00033
00034 template<unsigned DIM>
00035 VertexBasedCellPopulation<DIM>::VertexBasedCellPopulation(MutableVertexMesh<DIM, DIM>& rMesh,
00036 std::vector<CellPtr>& rCells,
00037 bool deleteMesh,
00038 bool validate,
00039 const std::vector<unsigned> locationIndices)
00040 : AbstractCellPopulation<DIM>(rCells, locationIndices),
00041 mrMesh(rMesh),
00042 mDeleteMesh(deleteMesh)
00043 {
00044
00045 bool contains_boundary_nodes = false;
00046 for (typename MutableVertexMesh<DIM,DIM>::NodeIterator node_iter = mrMesh.GetNodeIteratorBegin();
00047 node_iter != mrMesh.GetNodeIteratorEnd();
00048 ++node_iter)
00049 {
00050 if (node_iter->IsBoundaryNode())
00051 {
00052 contains_boundary_nodes = true;
00053 }
00054 }
00055
00057 if (!contains_boundary_nodes)
00058 {
00059 EXCEPTION("No boundary nodes are defined in the supplied vertex mesh which are needed for vertex based simulations.");
00060 }
00061
00062
00063 if (validate)
00064 {
00065 Validate();
00066 }
00067 }
00068
00069
00070 template<unsigned DIM>
00071 VertexBasedCellPopulation<DIM>::VertexBasedCellPopulation(MutableVertexMesh<DIM, DIM>& rMesh)
00072 : mrMesh(rMesh)
00073 {
00074 mDeleteMesh = true;
00075 }
00076
00077
00078 template<unsigned DIM>
00079 VertexBasedCellPopulation<DIM>::~VertexBasedCellPopulation()
00080 {
00081 if (mDeleteMesh)
00082 {
00083 delete &mrMesh;
00084 }
00085 }
00086
00087
00088 template<unsigned DIM>
00089 double VertexBasedCellPopulation<DIM>::GetDampingConstant(unsigned nodeIndex)
00090 {
00091
00092 double average_damping_constant = 0.0;
00093
00094 std::set<unsigned> containing_elements = GetNode(nodeIndex)->rGetContainingElementIndices();
00095 double temp = 1.0/((double) containing_elements.size());
00096
00097 for (std::set<unsigned>::iterator iter = containing_elements.begin();
00098 iter != containing_elements.end();
00099 ++iter)
00100 {
00101 CellPtr p_cell = this->GetCellUsingLocationIndex(*iter);
00102 bool cell_is_wild_type = p_cell->GetMutationState()->IsType<WildTypeCellMutationState>();
00103 bool cell_is_labelled = p_cell->HasCellProperty<CellLabel>();
00104
00105 if (cell_is_wild_type && !cell_is_labelled)
00106 {
00107 average_damping_constant += this->GetDampingConstantNormal()*temp;
00108 }
00109 else
00110 {
00111 average_damping_constant += this->GetDampingConstantMutant()*temp;
00112 }
00113 }
00114
00115 return average_damping_constant;
00116 }
00117
00118
00119 template<unsigned DIM>
00120 MutableVertexMesh<DIM, DIM>& VertexBasedCellPopulation<DIM>::rGetMesh()
00121 {
00122 return mrMesh;
00123 }
00124
00125
00126 template<unsigned DIM>
00127 const MutableVertexMesh<DIM, DIM>& VertexBasedCellPopulation<DIM>::rGetMesh() const
00128 {
00129 return mrMesh;
00130 }
00131
00132
00133 template<unsigned DIM>
00134 VertexElement<DIM, DIM>* VertexBasedCellPopulation<DIM>::GetElement(unsigned elementIndex)
00135 {
00136 return mrMesh.GetElement(elementIndex);
00137 }
00138
00139
00140 template<unsigned DIM>
00141 unsigned VertexBasedCellPopulation<DIM>::GetNumNodes()
00142 {
00143 return mrMesh.GetNumNodes();
00144 }
00145
00146
00147 template<unsigned DIM>
00148 c_vector<double, DIM> VertexBasedCellPopulation<DIM>::GetLocationOfCellCentre(CellPtr pCell)
00149 {
00150 return mrMesh.GetCentroidOfElement(this->mCellLocationMap[pCell.get()]);
00151 }
00152
00153
00154 template<unsigned DIM>
00155 Node<DIM>* VertexBasedCellPopulation<DIM>::GetNode(unsigned index)
00156 {
00157 return mrMesh.GetNode(index);
00158 }
00159
00160
00161 template<unsigned DIM>
00162 unsigned VertexBasedCellPopulation<DIM>::AddNode(Node<DIM>* pNewNode)
00163 {
00164 return mrMesh.AddNode(pNewNode);
00165 }
00166
00167
00168 template<unsigned DIM>
00169 void VertexBasedCellPopulation<DIM>::SetNode(unsigned nodeIndex, ChastePoint<DIM>& rNewLocation)
00170 {
00171 mrMesh.SetNode(nodeIndex, rNewLocation);
00172 }
00173
00174
00175 template<unsigned DIM>
00176 VertexElement<DIM, DIM>* VertexBasedCellPopulation<DIM>::GetElementCorrespondingToCell(CellPtr pCell)
00177 {
00178 return mrMesh.GetElement(this->mCellLocationMap[pCell.get()]);
00179 }
00180
00181
00182 template<unsigned DIM>
00183 unsigned VertexBasedCellPopulation<DIM>::GetNumElements()
00184 {
00185 return mrMesh.GetNumElements();
00186 }
00187
00188
00189 template<unsigned DIM>
00190 CellPtr VertexBasedCellPopulation<DIM>::AddCell(CellPtr pNewCell, const c_vector<double,DIM>& rCellDivisionVector, CellPtr pParentCell)
00191 {
00192
00193 VertexElement<DIM, DIM>* p_element = GetElementCorrespondingToCell(pParentCell);
00194
00195
00196 unsigned new_element_index;
00197 if (norm_2(rCellDivisionVector) < DBL_EPSILON)
00198 {
00199
00200 new_element_index = mrMesh.DivideElementAlongShortAxis(p_element, true);
00201 }
00202 else
00203 {
00204
00205 new_element_index = mrMesh.DivideElementAlongGivenAxis(p_element, rCellDivisionVector, true);
00206 }
00207
00208
00209 this->mCells.push_back(pNewCell);
00210
00211
00212 CellPtr p_created_cell = this->mCells.back();
00213 this->mLocationCellMap[new_element_index] = p_created_cell;
00214 this->mCellLocationMap[p_created_cell.get()] = new_element_index;
00215 return p_created_cell;
00216 }
00217
00218
00219 template<unsigned DIM>
00220 unsigned VertexBasedCellPopulation<DIM>::RemoveDeadCells()
00221 {
00222 unsigned num_removed = 0;
00223
00224 for (std::list<CellPtr>::iterator it = this->mCells.begin();
00225 it != this->mCells.end();
00226 ++it)
00227 {
00228 if ((*it)->IsDead())
00229 {
00230
00231 num_removed++;
00232 mrMesh.DeleteElementPriorToReMesh(this->mCellLocationMap[(*it).get()]);
00233 it = this->mCells.erase(it);
00234 --it;
00235 }
00236 }
00237 return num_removed;
00238 }
00239
00240
00241 template<unsigned DIM>
00242 void VertexBasedCellPopulation<DIM>::UpdateNodeLocations(const std::vector< c_vector<double, DIM> >& rNodeForces, double dt)
00243 {
00244
00245 for (unsigned node_index=0; node_index<GetNumNodes(); node_index++)
00246 {
00247
00248 double damping_const = this->GetDampingConstant(node_index);
00249
00250
00251 c_vector<double, DIM> displacement = dt*rNodeForces[node_index]/damping_const;
00252
00253
00254
00255
00256
00257
00258
00259
00260 if (norm_2(displacement)>0.5*mrMesh.GetCellRearrangementThreshold())
00261 {
00262 WARN_ONCE_ONLY("Vertices are moving more than half the CellRearrangementThreshold this could cause elements to become inverted the motion has been restricted: - To avoid these warnings use a smaller timestep");
00263 displacement *= 0.5*mrMesh.GetCellRearrangementThreshold()/norm_2(displacement);
00264 }
00265
00266
00267 c_vector<double, DIM> new_node_location = this->GetNode(node_index)->rGetLocation() + displacement;
00268
00269
00270 ChastePoint<DIM> new_point(new_node_location);
00271
00272
00273 this->SetNode(node_index, new_point);
00274 }
00275 }
00276
00277
00278 template<unsigned DIM>
00279 bool VertexBasedCellPopulation<DIM>::IsCellAssociatedWithADeletedLocation(CellPtr pCell)
00280 {
00281 return GetElementCorrespondingToCell(pCell)->IsDeleted();;
00282 }
00283
00284
00285 template<unsigned DIM>
00286 void VertexBasedCellPopulation<DIM>::Update(bool hasHadBirthsOrDeaths)
00287 {
00288 VertexElementMap element_map(mrMesh.GetNumAllElements());
00289
00290 mrMesh.ReMesh(element_map);
00291
00292 if (!element_map.IsIdentityMap())
00293 {
00294
00295 std::map<Cell*, unsigned> old_map = this->mCellLocationMap;
00296
00297 this->mCellLocationMap.clear();
00298 this->mLocationCellMap.clear();
00299
00300 for (std::list<CellPtr>::iterator cell_iter = this->mCells.begin();
00301 cell_iter != this->mCells.end();
00302 ++cell_iter)
00303 {
00304
00305 unsigned old_elem_index = old_map[(*cell_iter).get()];
00306
00307 if (element_map.IsDeleted(old_elem_index))
00308 {
00309
00310
00311
00312 WARNING("Cell removed due to T2Swap this is not counted in the dead cells counter");
00313 cell_iter = this->mCells.erase(cell_iter);
00314 --cell_iter;
00315 }
00316 else
00317 {
00318 unsigned new_elem_index = element_map.GetNewIndex(old_elem_index);
00319
00320 this->mLocationCellMap[new_elem_index] = *cell_iter;
00321 this->mCellLocationMap[(*cell_iter).get()] = new_elem_index;
00322 }
00323 }
00324
00325
00326 Validate();
00327 }
00328
00329 element_map.ResetToIdentity();
00330 }
00331
00332
00333 template<unsigned DIM>
00334 void VertexBasedCellPopulation<DIM>::Validate()
00335 {
00336
00337 std::vector<unsigned> validated_element = std::vector<unsigned>(this->GetNumElements(), 0);
00338
00339 for (typename AbstractCellPopulation<DIM>::Iterator cell_iter = this->Begin();
00340 cell_iter != this->End();
00341 ++cell_iter)
00342 {
00343 unsigned elem_index = GetLocationIndexUsingCell(*cell_iter);
00344 validated_element[elem_index]++;
00345 }
00346
00347 for (unsigned i=0; i<validated_element.size(); i++)
00348 {
00349 if (validated_element[i] == 0)
00350 {
00351 std::stringstream ss;
00352 ss << "Element " << i << " does not appear to have a cell associated with it";
00353 EXCEPTION(ss.str());
00354 }
00355
00356 if (validated_element[i] > 1)
00357 {
00358 std::stringstream ss;
00359 ss << "Element " << i << " appears to have " << validated_element[i] << " cells associated with it";
00360 EXCEPTION(ss.str());
00361 }
00362 }
00363 }
00364
00365
00366 template<unsigned DIM>
00367 void VertexBasedCellPopulation<DIM>::WriteResultsToFiles()
00368 {
00369 AbstractCellPopulation<DIM>::WriteResultsToFiles();
00370
00371 SimulationTime* p_time = SimulationTime::Instance();
00372
00373
00374 *mpT1SwapLocationsFile << p_time->GetTime() << "\t";
00375 std::vector< c_vector<double, DIM> > t1_swap_locations = mrMesh.GetLocationsOfT1Swaps();
00376 *mpT1SwapLocationsFile << t1_swap_locations.size() << "\t";
00377 for (unsigned index = 0; index < t1_swap_locations.size(); index++)
00378 {
00379 for (unsigned i=0; i<DIM; i++)
00380 {
00381 *mpT1SwapLocationsFile << t1_swap_locations[index][i] << "\t";
00382 }
00383 }
00384 *mpT1SwapLocationsFile << "\n";
00385 mrMesh.ClearLocationsOfT1Swaps();
00386
00387
00388 *mpT3SwapLocationsFile << p_time->GetTime() << "\t";
00389 std::vector< c_vector<double, DIM> > t3_swap_locations = mrMesh.GetLocationsOfT3Swaps();
00390 *mpT3SwapLocationsFile << t3_swap_locations.size() << "\t";
00391 for (unsigned index = 0; index < t3_swap_locations.size(); index++)
00392 {
00393 for (unsigned i=0; i<DIM; i++)
00394 {
00395 *mpT3SwapLocationsFile << t3_swap_locations[index][i] << "\t";
00396 }
00397 }
00398 *mpT3SwapLocationsFile << "\n";
00399 mrMesh.ClearLocationsOfT3Swaps();
00400
00401
00402 *mpVizElementsFile << p_time->GetTime() << "\t";
00403
00404
00405 for (std::list<CellPtr>::iterator cell_iter = this->mCells.begin();
00406 cell_iter != this->mCells.end();
00407 ++cell_iter)
00408 {
00409 unsigned elem_index = this->GetLocationIndexUsingCell(*cell_iter);
00410
00411
00412 bool elem_corresponds_to_dead_cell = false;
00413
00414 if (this->mLocationCellMap[elem_index])
00415 {
00416 elem_corresponds_to_dead_cell = this->mLocationCellMap[elem_index]->IsDead();
00417 }
00418
00419
00420 if ( !(GetElement(elem_index)->IsDeleted()) && !elem_corresponds_to_dead_cell)
00421 {
00422 VertexElement<DIM, DIM>* p_element = mrMesh.GetElement(elem_index);
00423
00424 unsigned num_nodes_in_element = p_element->GetNumNodes();
00425
00426
00427 *mpVizElementsFile << num_nodes_in_element << " ";
00428
00429
00430 for (unsigned i=0; i<num_nodes_in_element; i++)
00431 {
00432 *mpVizElementsFile << p_element->GetNodeGlobalIndex(i) << " ";
00433 }
00434 }
00435 }
00436 *mpVizElementsFile << "\n";
00437 }
00438
00439 template<unsigned DIM>
00440 void VertexBasedCellPopulation<DIM>::WriteVtkResultsToFile()
00441 {
00442 #ifdef CHASTE_VTK
00443 SimulationTime* p_time = SimulationTime::Instance();
00444
00445 VertexMeshWriter<DIM, DIM> mesh_writer(this->mDirPath, "results", false);
00446 std::stringstream time;
00447 time << p_time->GetTimeStepsElapsed();
00448
00449 unsigned num_elements = mrMesh.GetNumElements();
00450 std::vector<double> cell_types(num_elements);
00451 std::vector<double> cell_ancestors(num_elements);
00452 std::vector<double> cell_mutation_states(num_elements);
00453 std::vector<double> cell_ages(num_elements);
00454 std::vector<double> cell_cycle_phases(num_elements);
00455 std::vector<double> cell_volumes(num_elements);
00456 std::vector<std::vector<double> > cellwise_data;
00457
00458 if (CellwiseData<DIM>::Instance()->IsSetUp())
00459 {
00460 CellwiseData<DIM>* p_data = CellwiseData<DIM>::Instance();
00461 unsigned num_variables = p_data->GetNumVariables();
00462 for (unsigned var=0; var<num_variables; var++)
00463 {
00464 std::vector<double> cellwise_data_var(num_elements);
00465 cellwise_data.push_back(cellwise_data_var);
00466 }
00467 }
00468
00469
00470 for (typename VertexMesh<DIM,DIM>::VertexElementIterator elem_iter = mrMesh.GetElementIteratorBegin();
00471 elem_iter != mrMesh.GetElementIteratorEnd();
00472 ++elem_iter)
00473 {
00474
00475 unsigned elem_index = elem_iter->GetIndex();
00476
00477
00478 CellPtr p_cell = this->mLocationCellMap[elem_index];
00479 assert(p_cell);
00480
00481 if (this->mOutputCellAncestors)
00482 {
00483 double ancestor_index = (p_cell->GetAncestor() == UNSIGNED_UNSET) ? (-1.0) : (double)p_cell->GetAncestor();
00484 cell_ancestors[elem_index] = ancestor_index;
00485 }
00486 if (this->mOutputCellProliferativeTypes)
00487 {
00488 double cell_type = p_cell->GetCellCycleModel()->GetCellProliferativeType();
00489 cell_types[elem_index] = cell_type;
00490 }
00491 if (this->mOutputCellMutationStates)
00492 {
00493 double mutation_state = p_cell->GetMutationState()->GetColour();
00494 cell_mutation_states[elem_index] = mutation_state;
00495 }
00496 if (this->mOutputCellAges)
00497 {
00498 double age = p_cell->GetAge();
00499 cell_ages[elem_index] = age;
00500 }
00501 if (this->mOutputCellCyclePhases)
00502 {
00503 double cycle_phase = p_cell->GetCellCycleModel()->GetCurrentCellCyclePhase();
00504 cell_cycle_phases[elem_index] = cycle_phase;
00505 }
00506 if (this->mOutputCellVolumes)
00507 {
00508 double cell_volume = mrMesh.GetVolumeOfElement(elem_index);
00509 cell_volumes[elem_index] = cell_volume;
00510 }
00511 if (CellwiseData<DIM>::Instance()->IsSetUp())
00512 {
00513 CellwiseData<DIM>* p_data = CellwiseData<DIM>::Instance();
00514 unsigned num_variables = p_data->GetNumVariables();
00515
00516 for (unsigned var=0; var<num_variables; var++)
00517 {
00518 cellwise_data[var][elem_index] = p_data->GetValue(p_cell, var);
00519 }
00520 }
00521 }
00522
00523 if (this->mOutputCellProliferativeTypes)
00524 {
00525 mesh_writer.AddCellData("Cell types", cell_types);
00526 }
00527 if (this->mOutputCellAncestors)
00528 {
00529 mesh_writer.AddCellData("Ancestors", cell_ancestors);
00530 }
00531 if (this->mOutputCellMutationStates)
00532 {
00533 mesh_writer.AddCellData("Mutation states", cell_mutation_states);
00534 }
00535 if (this->mOutputCellAges)
00536 {
00537 mesh_writer.AddCellData("Ages", cell_ages);
00538 }
00539 if (this->mOutputCellCyclePhases)
00540 {
00541 mesh_writer.AddCellData("Cycle phases", cell_cycle_phases);
00542 }
00543 if (this->mOutputCellVolumes)
00544 {
00545 mesh_writer.AddCellData("Cell volumes", cell_volumes);
00546 }
00547 if (CellwiseData<DIM>::Instance()->IsSetUp())
00548 {
00549 for (unsigned var=0; var<cellwise_data.size(); var++)
00550 {
00551 std::stringstream data_name;
00552 data_name << "Cellwise data " << var;
00553 std::vector<double> cellwise_data_var = cellwise_data[var];
00554 mesh_writer.AddCellData(data_name.str(), cellwise_data_var);
00555 }
00556 }
00557
00558 mesh_writer.WriteVtkUsingMesh(mrMesh, time.str());
00559 *(this->mpVtkMetaFile) << " <DataSet timestep=\"";
00560 *(this->mpVtkMetaFile) << p_time->GetTimeStepsElapsed();
00561 *(this->mpVtkMetaFile) << "\" group=\"\" part=\"0\" file=\"results_";
00562 *(this->mpVtkMetaFile) << p_time->GetTimeStepsElapsed();
00563 *(this->mpVtkMetaFile) << ".vtu\"/>\n";
00564 #endif //CHASTE_VTK
00565 }
00566
00567 template<unsigned DIM>
00568 void VertexBasedCellPopulation<DIM>::CreateOutputFiles(const std::string& rDirectory, bool cleanOutputDirectory)
00569 {
00570 AbstractCellPopulation<DIM>::CreateOutputFiles(rDirectory, cleanOutputDirectory);
00571
00572 OutputFileHandler output_file_handler(rDirectory, cleanOutputDirectory);
00573 mpVizElementsFile = output_file_handler.OpenOutputFile("results.vizelements");
00574 mpT1SwapLocationsFile = output_file_handler.OpenOutputFile("T1SwapLocations.dat");
00575 mpT3SwapLocationsFile = output_file_handler.OpenOutputFile("T3SwapLocations.dat");
00576 }
00577
00578 template<unsigned DIM>
00579 void VertexBasedCellPopulation<DIM>::CloseOutputFiles()
00580 {
00581 AbstractCellPopulation<DIM>::CloseOutputFiles();
00582 mpVizElementsFile->close();
00583 mpT1SwapLocationsFile->close();
00584 mpT3SwapLocationsFile->close();
00585 }
00586
00587
00588 template<unsigned DIM>
00589 void VertexBasedCellPopulation<DIM>::GenerateCellResultsAndWriteToFiles()
00590 {
00591
00592 unsigned num_cell_types = this->mCellProliferativeTypeCount.size();
00593 std::vector<unsigned> cell_type_counter(num_cell_types);
00594 for (unsigned i=0; i<num_cell_types; i++)
00595 {
00596 cell_type_counter[i] = 0;
00597 }
00598
00599
00600 unsigned num_cell_cycle_phases = this->mCellCyclePhaseCount.size();
00601 std::vector<unsigned> cell_cycle_phase_counter(num_cell_cycle_phases);
00602 for (unsigned i=0; i<num_cell_cycle_phases; i++)
00603 {
00604 cell_cycle_phase_counter[i] = 0;
00605 }
00606
00607 for (typename AbstractCellPopulation<DIM>::Iterator cell_iter = this->Begin();
00608 cell_iter != this->End();
00609 ++cell_iter)
00610 {
00611 this->GenerateCellResults(this->GetLocationIndexUsingCell(*cell_iter), cell_type_counter, cell_cycle_phase_counter);
00612 }
00613
00614 this->WriteCellResultsToFiles(cell_type_counter, cell_cycle_phase_counter);
00615 }
00616
00617 template<unsigned DIM>
00618 void VertexBasedCellPopulation<DIM>::OutputCellPopulationParameters(out_stream& rParamsFile)
00619 {
00620 *rParamsFile << "\t\t<CellRearrangementThreshold>" << mrMesh.GetCellRearrangementThreshold() << "</CellRearrangementThreshold> \n";
00621 *rParamsFile << "\t\t<T2Threshold>" << mrMesh.GetT2Threshold() << "</T2Threshold> \n";
00622 *rParamsFile << "\t\t<CellRearrangementRatio>" << mrMesh.GetCellRearrangementRatio() << "</CellRearrangementRatio> \n";
00623
00624
00625 AbstractCellPopulation<DIM>::OutputCellPopulationParameters(rParamsFile);
00626 }
00627
00628 template<unsigned DIM>
00629 double VertexBasedCellPopulation<DIM>::GetWidth(const unsigned& rDimension)
00630 {
00631
00632 double width = mrMesh.GetWidth(rDimension);
00633
00634 return width;
00635 }
00636
00638
00640
00641 template class VertexBasedCellPopulation<1>;
00642 template class VertexBasedCellPopulation<2>;
00643 template class VertexBasedCellPopulation<3>;
00644
00645
00646 #include "SerializationExportWrapperForCpp.hpp"
00647 EXPORT_TEMPLATE_CLASS_SAME_DIMS(VertexBasedCellPopulation)