36 #include "VertexBasedCellPopulation.hpp"
37 #include <boost/foreach.hpp>
38 #include "VertexMeshWriter.hpp"
39 #include "Warnings.hpp"
42 #include "ShortAxisVertexBasedDivisionRule.hpp"
45 #include "CellAgesWriter.hpp"
46 #include "CellAncestorWriter.hpp"
47 #include "CellProliferativePhasesWriter.hpp"
48 #include "CellProliferativeTypesWriter.hpp"
49 #include "CellVolumesWriter.hpp"
52 #include "CellMutationStatesCountWriter.hpp"
53 #include "CellPopulationElementWriter.hpp"
54 #include "VertexT1SwapLocationsWriter.hpp"
55 #include "VertexT2SwapLocationsWriter.hpp"
56 #include "VertexT3SwapLocationsWriter.hpp"
58 template<
unsigned DIM>
60 std::vector<CellPtr>& rCells,
63 const std::vector<unsigned> locationIndices)
65 mDeleteMesh(deleteMesh),
66 mOutputCellRearrangementLocations(true)
72 std::list<CellPtr>::iterator it = this->
mCells.begin();
73 for (
unsigned i=0; it != this->
mCells.end(); ++it, ++i)
75 unsigned index = locationIndices.empty() ? i : locationIndices[i];
86 template<
unsigned DIM>
90 mOutputCellRearrangementLocations(true)
95 template<
unsigned DIM>
100 delete &this->mrMesh;
104 template<
unsigned DIM>
108 double average_damping_constant = 0.0;
110 std::set<unsigned> containing_elements = GetNode(nodeIndex)->rGetContainingElementIndices();
112 unsigned num_containing_elements = containing_elements.size();
113 if (num_containing_elements == 0)
115 EXCEPTION(
"At time " <<
SimulationTime::Instance()->GetTime() <<
", Node " << nodeIndex <<
" is not contained in any elements, so GetDampingConstant() returns zero");
118 double temp = 1.0/((
double) num_containing_elements);
119 for (std::set<unsigned>::iterator iter = containing_elements.begin();
120 iter != containing_elements.end();
123 CellPtr p_cell = this->GetCellUsingLocationIndex(*iter);
125 bool cell_is_labelled = p_cell->HasCellProperty<
CellLabel>();
127 if (cell_is_wild_type && !cell_is_labelled)
129 average_damping_constant += this->GetDampingConstantNormal()*temp;
133 average_damping_constant += this->GetDampingConstantMutant()*temp;
137 return average_damping_constant;
140 template<
unsigned DIM>
143 return *mpMutableVertexMesh;
146 template<
unsigned DIM>
149 return *mpMutableVertexMesh;
152 template<
unsigned DIM>
155 return mpMutableVertexMesh->GetElement(elementIndex);
158 template<
unsigned DIM>
161 return this->mrMesh.GetNumNodes();
164 template<
unsigned DIM>
167 return mpMutableVertexMesh->GetCentroidOfElement(this->mCellLocationMap[pCell.get()]);
170 template<
unsigned DIM>
173 return this->mrMesh.GetNode(index);
176 template<
unsigned DIM>
179 unsigned elem_index = this->GetLocationIndexUsingCell(pCell);
180 return this->rGetMesh().GetNeighbouringElementIndices(elem_index);
183 template<
unsigned DIM>
186 return mpMutableVertexMesh->AddNode(pNewNode);
189 template<
unsigned DIM>
192 mpMutableVertexMesh->SetNode(nodeIndex, rNewLocation);
195 template<
unsigned DIM>
198 return mpMutableVertexMesh->GetElement(this->GetLocationIndexUsingCell(pCell));
201 template<
unsigned DIM>
204 return mpMutableVertexMesh->GetNumElements();
207 template<
unsigned DIM>
209 const c_vector<double,DIM>& rCellDivisionVector,
216 unsigned new_element_index = mpMutableVertexMesh->DivideElementAlongGivenAxis(p_element,
220 this->mCells.push_back(pNewCell);
223 CellPtr p_created_cell = this->mCells.back();
224 this->SetCellUsingLocationIndex(new_element_index,p_created_cell);
225 this->mCellLocationMap[p_created_cell.get()] = new_element_index;
226 return p_created_cell;
229 template<
unsigned DIM>
232 unsigned num_removed = 0;
234 for (std::list<CellPtr>::iterator it = this->mCells.begin();
235 it != this->mCells.end();
245 if (!(this->GetElement(this->GetLocationIndexUsingCell((*it)))->IsDeleted()))
249 WARN_ONCE_ONLY(
"A Cell is removed without performing a T2 swap. This could leave a void in the mesh.");
250 mpMutableVertexMesh->DeleteElementPriorToReMesh(this->GetLocationIndexUsingCell((*it)));
254 it = this->mCells.erase(it);
264 template<
unsigned DIM>
268 for (
unsigned node_index=0; node_index<GetNumNodes(); node_index++)
271 double damping_const = this->GetDampingConstant(node_index);
274 c_vector<double, DIM> displacement = dt*this->GetNode(node_index)->rGetAppliedForce()/damping_const;
283 if (norm_2(displacement) > 0.5*mpMutableVertexMesh->GetCellRearrangementThreshold())
285 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.");
286 displacement *= 0.5*mpMutableVertexMesh->GetCellRearrangementThreshold()/norm_2(displacement);
290 c_vector<double, DIM> new_node_location = this->GetNode(node_index)->rGetLocation() + displacement;
292 for (
unsigned i=0; i<DIM; i++)
294 assert(!std::isnan(new_node_location(i)));
301 this->SetNode(node_index, new_point);
305 template<
unsigned DIM>
308 return GetElementCorrespondingToCell(pCell)->IsDeleted();;
311 template<
unsigned DIM>
315 mpMutableVertexMesh->ReMesh(element_map);
317 if (!element_map.IsIdentityMap())
321 std::map<Cell*, unsigned> old_map = this->mCellLocationMap;
323 this->mCellLocationMap.clear();
324 this->mLocationCellMap.clear();
326 for (std::list<CellPtr>::iterator cell_iter = this->mCells.begin();
327 cell_iter != this->mCells.end();
331 unsigned old_elem_index = old_map[(*cell_iter).get()];
332 assert(!element_map.IsDeleted(old_elem_index));
334 unsigned new_elem_index = element_map.
GetNewIndex(old_elem_index);
335 this->SetCellUsingLocationIndex(new_elem_index, *cell_iter);
342 element_map.ResetToIdentity();
345 template<
unsigned DIM>
349 std::vector<unsigned> validated_element = std::vector<unsigned>(this->GetNumElements(), 0);
351 cell_iter != this->End();
354 unsigned elem_index = this->GetLocationIndexUsingCell(*cell_iter);
355 validated_element[elem_index]++;
358 for (
unsigned i=0; i<validated_element.size(); i++)
360 if (validated_element[i] == 0)
365 if (validated_element[i] > 1)
368 EXCEPTION(
"At time " <<
SimulationTime::Instance()->GetTime() <<
", Element " << i <<
" appears to have " << validated_element[i] <<
" cells associated with it");
373 template<
unsigned DIM>
376 pPopulationWriter->Visit(
this);
379 template<
unsigned DIM>
382 pPopulationCountWriter->Visit(
this);
385 template<
unsigned DIM>
388 pCellWriter->VisitCell(pCell,
this);
391 template<
unsigned DIM>
395 unsigned elem_index = this->GetLocationIndexUsingCell(pCell);
398 unsigned rosette_rank = mpMutableVertexMesh->GetRosetteRankOfElement(elem_index);
403 template<
unsigned DIM>
407 unsigned elem_index = this->GetLocationIndexUsingCell(pCell);
410 double cell_volume = mpMutableVertexMesh->GetVolumeOfElement(elem_index);
415 template<
unsigned DIM>
424 unsigned num_cells = this->GetNumAllCells();
426 cell_writer_iter != this->mCellWriters.end();
430 std::vector<double> vtk_cell_data(num_cells);
434 elem_iter != mpMutableVertexMesh->GetElementIteratorEnd();
438 unsigned elem_index = elem_iter->GetIndex();
441 CellPtr p_cell = this->GetCellUsingLocationIndex(elem_index);
445 vtk_cell_data[elem_index] = (*cell_writer_iter)->GetCellDataForVtkOutput(p_cell,
this);
448 mesh_writer.
AddCellData((*cell_writer_iter)->GetVtkCellDataName(), vtk_cell_data);
452 unsigned num_cell_data_items = this->Begin()->GetCellData()->GetNumItems();
453 std::vector<std::string> cell_data_names = this->Begin()->GetCellData()->GetKeys();
455 std::vector<std::vector<double> > cell_data;
456 for (
unsigned var=0; var<num_cell_data_items; var++)
458 std::vector<double> cell_data_var(num_cells);
459 cell_data.push_back(cell_data_var);
464 elem_iter != mpMutableVertexMesh->GetElementIteratorEnd();
468 unsigned elem_index = elem_iter->GetIndex();
471 CellPtr p_cell = this->GetCellUsingLocationIndex(elem_index);
474 for (
unsigned var=0; var<num_cell_data_items; var++)
476 cell_data[var][elem_index] = p_cell->GetCellData()->GetItem(cell_data_names[var]);
479 for (
unsigned var=0; var<num_cell_data_items; var++)
481 mesh_writer.
AddCellData(cell_data_names[var], cell_data[var]);
485 std::stringstream time;
486 time << num_timesteps;
490 *(this->mpVtkMetaFile) <<
" <DataSet timestep=\"";
491 *(this->mpVtkMetaFile) << num_timesteps;
492 *(this->mpVtkMetaFile) <<
"\" group=\"\" part=\"0\" file=\"results_";
493 *(this->mpVtkMetaFile) << num_timesteps;
494 *(this->mpVtkMetaFile) <<
".vtu\"/>\n";
498 template<
unsigned DIM>
501 if (this->mOutputResultsForChasteVisualizer)
503 if (!this->
template HasWriter<CellPopulationElementWriter>())
505 this->
template AddPopulationWriter<CellPopulationElementWriter>();
509 if (mOutputCellRearrangementLocations)
511 if (!this->
template HasWriter<VertexT1SwapLocationsWriter>())
513 this->
template AddPopulationWriter<VertexT1SwapLocationsWriter>();
515 if (!this->
template HasWriter<VertexT2SwapLocationsWriter>())
517 this->
template AddPopulationWriter<VertexT2SwapLocationsWriter>();
519 if (!this->
template HasWriter<VertexT3SwapLocationsWriter>())
521 this->
template AddPopulationWriter<VertexT3SwapLocationsWriter>();
528 template<
unsigned DIM>
531 return mOutputCellRearrangementLocations;
534 template<
unsigned DIM>
537 mOutputCellRearrangementLocations = outputCellRearrangementLocations;
540 template<
unsigned DIM>
543 *rParamsFile <<
"\t\t<CellRearrangementThreshold>" << mpMutableVertexMesh->GetCellRearrangementThreshold() <<
"</CellRearrangementThreshold>\n";
544 *rParamsFile <<
"\t\t<T2Threshold>" << mpMutableVertexMesh->GetT2Threshold() <<
"</T2Threshold>\n";
545 *rParamsFile <<
"\t\t<CellRearrangementRatio>" << mpMutableVertexMesh->GetCellRearrangementRatio() <<
"</CellRearrangementRatio>\n";
546 *rParamsFile <<
"\t\t<OutputCellRearrangementLocations>" << mOutputCellRearrangementLocations <<
"</OutputCellRearrangementLocations>\n";
549 *rParamsFile <<
"\t\t<VertexBasedDivisionRule>\n";
550 mpVertexBasedDivisionRule->OutputCellVertexBasedDivisionRuleInfo(rParamsFile);
551 *rParamsFile <<
"\t\t</VertexBasedDivisionRule>\n";
557 template<
unsigned DIM>
561 double width = this->mrMesh.GetWidth(rDimension);
566 template<
unsigned DIM>
569 return mpMutableVertexMesh->GetNeighbouringNodeIndices(index);
572 template<
unsigned DIM>
575 return mpVertexBasedDivisionRule;
578 template<
unsigned DIM>
581 mpVertexBasedDivisionRule = pVertexBasedDivisionRule;
584 template<
unsigned DIM>
587 return mLocationsOfT2Swaps;
590 template<
unsigned DIM>
593 return mCellIdsOfT2Swaps;
596 template<
unsigned DIM>
599 mLocationsOfT2Swaps.push_back(locationOfT2Swap);
602 template<
unsigned DIM>
605 mCellIdsOfT2Swaps.push_back(idOfT2Swap);
608 template<
unsigned DIM>
611 mCellIdsOfT2Swaps.clear();
612 mLocationsOfT2Swaps.clear();
615 template<
unsigned DIM>
622 unsigned num_vertex_nodes = mpMutableVertexMesh->GetNumNodes();
623 unsigned num_vertex_elements = mpMutableVertexMesh->GetNumElements();
625 std::string mesh_file_name =
"mesh";
628 std::stringstream pid;
630 OutputFileHandler output_file_handler(
"2D_temporary_tetrahedral_mesh_" + pid.str());
634 unsigned num_tetrahedral_nodes = num_vertex_nodes + num_vertex_elements;
637 out_stream p_node_file = output_file_handler.OpenOutputFile(mesh_file_name+
".node");
638 (*p_node_file) << std::scientific;
639 (*p_node_file) << std::setprecision(20);
640 (*p_node_file) << num_tetrahedral_nodes <<
"\t2\t0\t1" << std::endl;
643 for (
unsigned node_index=0; node_index<num_vertex_nodes; node_index++)
645 Node<DIM>* p_node = mpMutableVertexMesh->GetNode(node_index);
648 unsigned index = p_node->
GetIndex();
650 c_vector<double, DIM> location = p_node->
rGetLocation();
654 (*p_node_file) << index <<
"\t" << location[0] <<
"\t" << location[1] <<
"\t" << is_boundary_node << std::endl;
658 unsigned num_tetrahedral_elements = 0;
659 for (
unsigned vertex_elem_index=0; vertex_elem_index<num_vertex_elements; vertex_elem_index++)
661 unsigned index = num_vertex_nodes + vertex_elem_index;
663 c_vector<double, DIM> location = mpMutableVertexMesh->GetCentroidOfElement(vertex_elem_index);
666 unsigned is_boundary_node = 0;
667 (*p_node_file) << index <<
"\t" << location[0] <<
"\t" << location[1] <<
"\t" << is_boundary_node << std::endl;
670 num_tetrahedral_elements += mpMutableVertexMesh->GetElement(vertex_elem_index)->GetNumNodes();
672 p_node_file->close();
675 out_stream p_elem_file = output_file_handler.OpenOutputFile(mesh_file_name+
".ele");
676 (*p_elem_file) << std::scientific;
677 (*p_elem_file) << num_tetrahedral_elements <<
"\t3\t0" << std::endl;
679 std::set<std::pair<unsigned, unsigned> > tetrahedral_edges;
681 unsigned tetrahedral_elem_index = 0;
682 for (
unsigned vertex_elem_index=0; vertex_elem_index<num_vertex_elements; vertex_elem_index++)
687 unsigned num_nodes_in_vertex_element = p_vertex_element->
GetNumNodes();
688 for (
unsigned local_index=0; local_index<num_nodes_in_vertex_element; local_index++)
691 unsigned node_1_index = p_vertex_element->
GetNodeGlobalIndex((local_index+1)%num_nodes_in_vertex_element);
692 unsigned node_2_index = num_vertex_nodes + vertex_elem_index;
694 (*p_elem_file) << tetrahedral_elem_index++ <<
"\t" << node_0_index <<
"\t" << node_1_index <<
"\t" << node_2_index << std::endl;
697 std::pair<unsigned, unsigned> edge_0 = this->CreateOrderedPair(node_0_index, node_1_index);
698 std::pair<unsigned, unsigned> edge_1 = this->CreateOrderedPair(node_1_index, node_2_index);
699 std::pair<unsigned, unsigned> edge_2 = this->CreateOrderedPair(node_2_index, node_0_index);
701 tetrahedral_edges.insert(edge_0);
702 tetrahedral_edges.insert(edge_1);
703 tetrahedral_edges.insert(edge_2);
706 p_elem_file->close();
709 out_stream p_edge_file = output_file_handler.OpenOutputFile(mesh_file_name+
".edge");
710 (*p_edge_file) << std::scientific;
711 (*p_edge_file) << tetrahedral_edges.size() <<
"\t1" << std::endl;
713 unsigned edge_index = 0;
714 for (std::set<std::pair<unsigned, unsigned> >::iterator edge_iter = tetrahedral_edges.begin();
715 edge_iter != tetrahedral_edges.end();
718 std::pair<unsigned, unsigned> this_edge = *edge_iter;
721 bool is_boundary_edge =
false;
722 if (this_edge.first < mpMutableVertexMesh->GetNumNodes() &&
723 this_edge.second < mpMutableVertexMesh->GetNumNodes())
725 is_boundary_edge = (mpMutableVertexMesh->GetNode(this_edge.first)->IsBoundaryNode() &&
726 mpMutableVertexMesh->GetNode(this_edge.second)->IsBoundaryNode() );
728 unsigned is_boundary_edge_unsigned = is_boundary_edge ? 1 : 0;
730 (*p_edge_file) << edge_index++ <<
"\t" << this_edge.first <<
"\t" << this_edge.second <<
"\t" << is_boundary_edge_unsigned << std::endl;
732 p_edge_file->close();
743 output_file_handler.FindFile(
"").Remove();
void SetOutputCellRearrangementLocations(bool outputCellRearrangementLocations)
void AddCellData(std::string dataName, std::vector< double > dataPayload)
std::vector< c_vector< double, DIM > > GetLocationsOfT2Swaps()
virtual void AcceptPopulationCountWriter(boost::shared_ptr< AbstractCellPopulationCountWriter< DIM, DIM > > pPopulationCountWriter)
double GetVolumeOfCell(CellPtr pCell)
virtual ~VertexBasedCellPopulation()
unsigned GetNodeGlobalIndex(unsigned localIndex) const
void UpdateNodeLocations(double dt)
unsigned GetNumElements()
bool IsBoundaryNode() const
#define EXCEPTION(message)
static SimulationTime * Instance()
boost::shared_ptr< AbstractVertexBasedDivisionRule< DIM > > mpVertexBasedDivisionRule
void ConstructFromMeshReader(AbstractMeshReader< ELEMENT_DIM, SPACE_DIM > &rMeshReader)
virtual void AcceptCellWriter(boost::shared_ptr< AbstractCellWriter< DIM, DIM > > pCellWriter, CellPtr pCell)
void SetVertexBasedDivisionRule(boost::shared_ptr< AbstractVertexBasedDivisionRule< DIM > > pVertexBasedDivisionRule)
std::vector< unsigned > GetCellIdsOfT2Swaps()
unsigned GetTimeStepsElapsed() const
std::set< unsigned > GetNeighbouringNodeIndices(unsigned index)
std::string GetOutputDirectoryFullPath() const
boost::shared_ptr< AbstractVertexBasedDivisionRule< DIM > > GetVertexBasedDivisionRule()
bool IsCellAssociatedWithADeletedLocation(CellPtr pCell)
double GetDampingConstant(unsigned nodeIndex)
std::set< unsigned > GetNeighbouringLocationIndices(CellPtr pCell)
unsigned GetRosetteRankOfCell(CellPtr pCell)
MutableVertexMesh< DIM, DIM > & rGetMesh()
TetrahedralMesh< DIM, DIM > * GetTetrahedralMeshUsingVertexMesh()
VertexElementIterator GetElementIteratorBegin(bool skipDeletedElements=true)
#define EXPORT_TEMPLATE_CLASS_SAME_DIMS(CLASS)
virtual void AcceptPopulationWriter(boost::shared_ptr< AbstractCellPopulationWriter< DIM, DIM > > pPopulationWriter)
void Update(bool hasHadBirthsOrDeaths=true)
void AddLocationOfT2Swap(c_vector< double, DIM > locationOfT2Swap)
VertexBasedCellPopulation(MutableVertexMesh< DIM, DIM > &rMesh, std::vector< CellPtr > &rCells, bool deleteMesh=false, bool validate=true, const std::vector< unsigned > locationIndices=std::vector< unsigned >())
Node< DIM > * GetNode(unsigned index)
unsigned GetNumNodes() const
void WriteVtkUsingMesh(VertexMesh< ELEMENT_DIM, SPACE_DIM > &rMesh, std::string stamp="")
unsigned GetNewIndex(unsigned oldIndex) const
void OutputCellPopulationParameters(out_stream &rParamsFile)
virtual void OutputCellPopulationParameters(out_stream &rParamsFile)
unsigned RemoveDeadCells()
virtual void OpenWritersFiles(OutputFileHandler &rOutputFileHandler)
std::list< CellPtr > mCells
virtual void OpenWritersFiles(OutputFileHandler &rOutputFileHandler)
void SetMeshHasChangedSinceLoading()
void SetNode(unsigned index, ChastePoint< DIM > &rNewLocation)
const c_vector< double, SPACE_DIM > & rGetLocation() const
void AddCellIdOfT2Swap(unsigned idOfT2Swap)
double GetWidth(const unsigned &rDimension)
c_vector< double, DIM > GetLocationOfCellCentre(CellPtr pCell)
unsigned AddNode(Node< DIM > *pNewNode)
MutableVertexMesh< DIM, DIM > * mpMutableVertexMesh
virtual void WriteVtkResultsToFile(const std::string &rDirectory)
unsigned GetIndex() const
void ClearLocationsAndCellIdsOfT2Swaps()
virtual void AddCellUsingLocationIndex(unsigned index, CellPtr pCell)
CellPtr AddCell(CellPtr pNewCell, const c_vector< double, DIM > &rCellDivisionVector, CellPtr pParentCell=CellPtr())
AbstractMesh< ELEMENT_DIM, SPACE_DIM > & mrMesh
VertexElement< DIM, DIM > * GetElement(unsigned elementIndex)
bool GetOutputCellRearrangementLocations()
VertexElement< DIM, DIM > * GetElementCorrespondingToCell(CellPtr pCell)