36 #include "VertexBasedCellPopulation.hpp" 37 #include "Warnings.hpp" 38 #include "ShortAxisVertexBasedDivisionRule.hpp" 39 #include "StepSizeException.hpp" 40 #include "WildTypeCellMutationState.hpp" 41 #include "Cylindrical2dVertexMesh.hpp" 43 #include "T2SwapCellKiller.hpp" 44 #include "ApoptoticCellProperty.hpp" 45 #include "CellPopulationElementWriter.hpp" 46 #include "VertexT1SwapLocationsWriter.hpp" 47 #include "VertexT2SwapLocationsWriter.hpp" 48 #include "VertexT3SwapLocationsWriter.hpp" 49 #include "VertexIntersectionSwapLocationsWriter.hpp" 50 #include "AbstractCellBasedSimulation.hpp" 52 template<
unsigned DIM>
54 std::vector<CellPtr>& rCells,
57 const std::vector<unsigned> locationIndices)
59 mDeleteMesh(deleteMesh),
60 mOutputCellRearrangementLocations(true),
61 mRestrictVertexMovement(true)
67 std::list<CellPtr>::iterator it = this->
mCells.begin();
68 for (
unsigned i=0; it != this->
mCells.end(); ++it, ++i)
70 unsigned index = locationIndices.empty() ? i : locationIndices[i];
81 template<
unsigned DIM>
91 template<
unsigned DIM>
100 template<
unsigned DIM>
104 double average_damping_constant = 0.0;
106 std::set<unsigned> containing_elements =
GetNode(nodeIndex)->rGetContainingElementIndices();
108 unsigned num_containing_elements = containing_elements.size();
109 if (num_containing_elements == 0)
111 EXCEPTION(
"At time " <<
SimulationTime::Instance()->GetTime() <<
", Node " << nodeIndex <<
" is not contained in any elements, so GetDampingConstant() returns zero");
114 double temp = 1.0/((
double) num_containing_elements);
115 for (std::set<unsigned>::iterator iter = containing_elements.begin();
116 iter != containing_elements.end();
122 if (cell_is_wild_type)
132 return average_damping_constant;
135 template<
unsigned DIM>
141 template<
unsigned DIM>
147 template<
unsigned DIM>
153 template<
unsigned DIM>
156 return this->
mrMesh.GetNumNodes();
159 template<
unsigned DIM>
165 template<
unsigned DIM>
168 return this->
mrMesh.GetNode(index);
171 template<
unsigned DIM>
178 template<
unsigned DIM>
184 template<
unsigned DIM>
190 template<
unsigned DIM>
196 template<
unsigned DIM>
202 template<
unsigned DIM>
215 this->
mCells.push_back(pNewCell);
218 CellPtr p_created_cell = this->
mCells.back();
222 return p_created_cell;
225 template<
unsigned DIM>
228 unsigned num_removed = 0;
230 for (std::list<CellPtr>::iterator it = this->
mCells.begin();
245 WARN_ONCE_ONLY(
"A Cell is removed without performing a T2 swap. This could leave a void in the mesh.");
250 it = this->
mCells.erase(it);
260 template<
unsigned DIM>
263 double length = norm_2(rDisplacement);
271 std::ostringstream message;
272 message <<
"Vertices are moving more than half the CellRearrangementThreshold. This could cause elements to become inverted ";
273 message <<
"so the motion has been restricted. Use a smaller timestep to avoid these warnings.";
287 template<
unsigned DIM>
293 template<
unsigned DIM>
299 if (!element_map.IsIdentityMap())
308 for (std::list<CellPtr>::iterator cell_iter = this->
mCells.begin();
309 cell_iter != this->
mCells.end();
313 unsigned old_elem_index = old_map[(*cell_iter).get()];
314 assert(!element_map.IsDeleted(old_elem_index));
316 unsigned new_elem_index = element_map.GetNewIndex(old_elem_index);
324 element_map.ResetToIdentity();
327 template<
unsigned DIM>
331 std::vector<unsigned> validated_element = std::vector<unsigned>(this->
GetNumElements(), 0);
333 cell_iter != this->
End();
337 validated_element[elem_index]++;
340 for (
unsigned i=0; i<validated_element.size(); i++)
342 if (validated_element[i] == 0)
347 if (validated_element[i] > 1)
350 EXCEPTION(
"At time " <<
SimulationTime::Instance()->GetTime() <<
", Element " << i <<
" appears to have " << validated_element[i] <<
" cells associated with it");
355 template<
unsigned DIM>
358 pPopulationWriter->Visit(
this);
361 template<
unsigned DIM>
364 pPopulationCountWriter->Visit(
this);
367 template<
unsigned DIM>
370 pCellWriter->VisitCell(pCell,
this);
373 template<
unsigned DIM>
385 template<
unsigned DIM>
397 template<
unsigned DIM>
410 for (
auto cell_writer_iter = this->
mCellWriters.begin();
415 std::vector<double> vtk_cell_data(num_cells);
423 unsigned elem_index = elem_iter->GetIndex();
430 vtk_cell_data[elem_index] = (*cell_writer_iter)->GetCellDataForVtkOutput(p_cell,
this);
433 mesh_writer.
AddCellData((*cell_writer_iter)->GetVtkCellDataName(), vtk_cell_data);
437 unsigned num_cell_data_items = this->
Begin()->GetCellData()->GetNumItems();
438 std::vector<std::string> cell_data_names = this->
Begin()->GetCellData()->GetKeys();
440 std::vector<std::vector<double> > cell_data;
441 for (
unsigned var=0; var<num_cell_data_items; var++)
443 std::vector<double> cell_data_var(num_cells);
444 cell_data.push_back(cell_data_var);
453 unsigned elem_index = elem_iter->GetIndex();
459 for (
unsigned var=0; var<num_cell_data_items; var++)
461 cell_data[var][elem_index] = p_cell->GetCellData()->GetItem(cell_data_names[var]);
464 for (
unsigned var=0; var<num_cell_data_items; var++)
466 mesh_writer.
AddCellData(cell_data_names[var], cell_data[var]);
471 std::stringstream time;
472 time << num_timesteps;
478 *(this->
mpVtkMetaFile) <<
"\" group=\"\" part=\"0\" file=\"results_";
484 template<
unsigned DIM>
489 if (!this->
template HasWriter<CellPopulationElementWriter>())
491 this->
template AddPopulationWriter<CellPopulationElementWriter>();
497 if (!this->
template HasWriter<VertexT1SwapLocationsWriter>())
499 this->
template AddPopulationWriter<VertexT1SwapLocationsWriter>();
501 if (!this->
template HasWriter<VertexT2SwapLocationsWriter>())
503 this->
template AddPopulationWriter<VertexT2SwapLocationsWriter>();
505 if (!this->
template HasWriter<VertexT3SwapLocationsWriter>())
507 this->
template AddPopulationWriter<VertexT3SwapLocationsWriter>();
509 if (!this->
template HasWriter<VertexIntersectionSwapLocationsWriter>())
511 this->
template AddPopulationWriter<VertexIntersectionSwapLocationsWriter>();
518 template<
unsigned DIM>
524 template<
unsigned DIM>
530 template<
unsigned DIM>
539 *rParamsFile <<
"\t\t<VertexBasedDivisionRule>\n";
541 *rParamsFile <<
"\t\t</VertexBasedDivisionRule>\n";
547 template<
unsigned DIM>
551 double width = this->
mrMesh.GetWidth(rDimension);
556 template<
unsigned DIM>
562 template<
unsigned DIM>
568 template<
unsigned DIM>
574 template<
unsigned DIM>
580 template<
unsigned DIM>
586 template<
unsigned DIM>
592 template<
unsigned DIM>
598 template<
unsigned DIM>
605 template<
unsigned DIM>
615 std::string mesh_file_name =
"mesh";
618 std::stringstream pid;
620 OutputFileHandler output_file_handler(
"2D_temporary_tetrahedral_mesh_" + pid.str());
624 unsigned num_tetrahedral_nodes = num_vertex_nodes + num_vertex_elements;
627 out_stream p_node_file = output_file_handler.OpenOutputFile(mesh_file_name+
".node");
628 (*p_node_file) << std::scientific;
629 (*p_node_file) << std::setprecision(20);
630 (*p_node_file) << num_tetrahedral_nodes <<
"\t2\t0\t1" << std::endl;
633 for (
unsigned node_index=0; node_index<num_vertex_nodes; node_index++)
638 unsigned index = p_node->
GetIndex();
639 const c_vector<double, DIM>& r_location = p_node->
rGetLocation();
642 (*p_node_file) << index <<
"\t" << r_location[0] <<
"\t" << r_location[1] <<
"\t" << is_boundary_node << std::endl;
646 unsigned num_tetrahedral_elements = 0;
647 for (
unsigned vertex_elem_index=0; vertex_elem_index<num_vertex_elements; vertex_elem_index++)
649 unsigned index = num_vertex_nodes + vertex_elem_index;
654 unsigned is_boundary_node = 0;
655 (*p_node_file) << index <<
"\t" << location[0] <<
"\t" << location[1] <<
"\t" << is_boundary_node << std::endl;
660 p_node_file->close();
663 out_stream p_elem_file = output_file_handler.OpenOutputFile(mesh_file_name+
".ele");
664 (*p_elem_file) << std::scientific;
665 (*p_elem_file) << num_tetrahedral_elements <<
"\t3\t0" << std::endl;
667 std::set<std::pair<unsigned, unsigned> > tetrahedral_edges;
669 unsigned tetrahedral_elem_index = 0;
670 for (
unsigned vertex_elem_index=0; vertex_elem_index<num_vertex_elements; vertex_elem_index++)
675 unsigned num_nodes_in_vertex_element = p_vertex_element->
GetNumNodes();
676 for (
unsigned local_index=0; local_index<num_nodes_in_vertex_element; local_index++)
679 unsigned node_1_index = p_vertex_element->
GetNodeGlobalIndex((local_index+1)%num_nodes_in_vertex_element);
680 unsigned node_2_index = num_vertex_nodes + vertex_elem_index;
682 (*p_elem_file) << tetrahedral_elem_index++ <<
"\t" << node_0_index <<
"\t" << node_1_index <<
"\t" << node_2_index << std::endl;
685 std::pair<unsigned, unsigned> edge_0 = this->
CreateOrderedPair(node_0_index, node_1_index);
686 std::pair<unsigned, unsigned> edge_1 = this->
CreateOrderedPair(node_1_index, node_2_index);
687 std::pair<unsigned, unsigned> edge_2 = this->
CreateOrderedPair(node_2_index, node_0_index);
689 tetrahedral_edges.insert(edge_0);
690 tetrahedral_edges.insert(edge_1);
691 tetrahedral_edges.insert(edge_2);
694 p_elem_file->close();
697 out_stream p_edge_file = output_file_handler.OpenOutputFile(mesh_file_name+
".edge");
698 (*p_edge_file) << std::scientific;
699 (*p_edge_file) << tetrahedral_edges.size() <<
"\t1" << std::endl;
701 unsigned edge_index = 0;
702 for (std::set<std::pair<unsigned, unsigned> >::iterator edge_iter = tetrahedral_edges.begin();
703 edge_iter != tetrahedral_edges.end();
706 std::pair<unsigned, unsigned> this_edge = *edge_iter;
709 bool is_boundary_edge =
false;
716 unsigned is_boundary_edge_unsigned = is_boundary_edge ? 1 : 0;
718 (*p_edge_file) << edge_index++ <<
"\t" << this_edge.first <<
"\t" << this_edge.second <<
"\t" << is_boundary_edge_unsigned << std::endl;
720 p_edge_file->close();
732 output_file_handler.FindFile(
"").Remove();
740 template<
unsigned DIM>
743 bool non_apoptotic_cell_present =
true;
747 std::set<unsigned> containing_element_indices = this->
GetNode(pdeNodeIndex)->rGetContainingElementIndices();
749 for (std::set<unsigned>::iterator iter = containing_element_indices.begin();
750 iter != containing_element_indices.end();
755 non_apoptotic_cell_present =
false;
769 return non_apoptotic_cell_present;
772 template<
unsigned DIM>
774 unsigned pdeNodeIndex,
775 std::string& rVariableName,
776 bool dirichletBoundaryConditionApplies,
777 double dirichletBoundaryValue)
784 if (pdeNodeIndex >= num_nodes)
787 assert(pdeNodeIndex-num_nodes < num_nodes);
790 value = p_cell->GetCellData()->GetItem(rVariableName);
795 if (dirichletBoundaryConditionApplies)
798 value = dirichletBoundaryValue;
802 assert(pdeNodeIndex < num_nodes);
807 for (std::set<unsigned>::iterator index_iter = containing_elements.begin();
808 index_iter != containing_elements.end();
811 assert(*index_iter < num_nodes);
813 value += p_cell->GetCellData()->GetItem(rVariableName);
815 value /= containing_elements.size();
822 template<
unsigned DIM>
828 template<
unsigned DIM>
831 if (
bool(dynamic_cast<Cylindrical2dVertexMesh*>(&(this->
mrMesh))))
833 *pVizSetupFile <<
"MeshWidth\t" << this->
GetWidth(0) <<
"\n";
837 template<
unsigned DIM>
845 template<
unsigned DIM>
851 template<
unsigned DIM>
void SetOutputCellRearrangementLocations(bool outputCellRearrangementLocations)
void AddCellData(std::string dataName, std::vector< double > dataPayload)
std::vector< c_vector< double, DIM > > GetLocationsOfT2Swaps()
virtual double GetDefaultTimeStep()
unsigned GetNumAllElements() const
std::vector< unsigned > mCellIdsOfT2Swaps
std::string GetOutputDirectoryFullPath() const
double GetCellRearrangementRatio() const
void AddCellKiller(boost::shared_ptr< AbstractCellKiller< SPACE_DIM > > pCellKiller)
virtual void AcceptPopulationCountWriter(boost::shared_ptr< AbstractCellPopulationCountWriter< DIM, DIM > > pPopulationCountWriter)
unsigned DivideElementAlongGivenAxis(VertexElement< ELEMENT_DIM, SPACE_DIM > *pElement, c_vector< double, SPACE_DIM > axisOfDivision, bool placeOriginalElementBelow=false)
double GetVolumeOfCell(CellPtr pCell)
std::set< unsigned > GetNeighbouringNodeIndices(unsigned nodeIndex)
virtual ~VertexBasedCellPopulation()
virtual CellPtr GetCellUsingLocationIndex(unsigned index)
unsigned GetLocationIndexUsingCell(CellPtr pCell)
std::vector< boost::shared_ptr< AbstractCellWriter< ELEMENT_DIM, SPACE_DIM > > > mCellWriters
double GetDampingConstantNormal()
std::vector< c_vector< double, DIM > > mLocationsOfT2Swaps
virtual void SimulationSetupHook(AbstractCellBasedSimulation< DIM, DIM > *pSimulation)
unsigned GetNumElements()
double GetDampingConstantMutant()
#define EXCEPTION(message)
boost::shared_ptr< AbstractVertexBasedDivisionRule< DIM > > mpVertexBasedDivisionRule
MutableVertexMesh< DIM, DIM > * mpMutableVertexMesh
static SimulationTime * Instance()
bool mRestrictVertexMovement
VertexElement< ELEMENT_DIM, SPACE_DIM > * GetElement(unsigned index) const
unsigned AddNode(Node< SPACE_DIM > *pNewNode)
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()
virtual bool IsPdeNodeAssociatedWithNonApoptoticCell(unsigned pdeNodeIndex)
std::set< unsigned > & rGetContainingElementIndices()
unsigned GetIndex() const
virtual void WriteDataToVisualizerSetupFile(out_stream &pVizSetupFile)
unsigned GetNumNodes() const
std::set< unsigned > GetNeighbouringNodeIndices(unsigned index)
bool mOutputCellRearrangementLocations
unsigned GetNumElements() const
unsigned GetNumAllCells()
Node< SPACE_DIM > * GetNode(unsigned index) const
boost::shared_ptr< AbstractVertexBasedDivisionRule< DIM > > GetVertexBasedDivisionRule()
bool mOutputResultsForChasteVisualizer
bool IsCellAssociatedWithADeletedLocation(CellPtr pCell)
double GetDampingConstant(unsigned nodeIndex)
void SetRestrictVertexMovementBoolean(bool restrictVertexMovement)
std::set< unsigned > GetNeighbouringLocationIndices(CellPtr pCell)
unsigned GetRosetteRankOfCell(CellPtr pCell)
MutableVertexMesh< DIM, DIM > & rGetMesh()
unsigned GetNodeGlobalIndex(unsigned localIndex) const
const c_vector< double, SPACE_DIM > & rGetLocation() const
bool GetRestrictVertexMovementBoolean()
std::pair< unsigned, unsigned > CreateOrderedPair(unsigned index1, unsigned index2)
bool mThrowStepSizeException
VertexElementIterator GetElementIteratorBegin(bool skipDeletedElements=true)
#define EXPORT_TEMPLATE_CLASS_SAME_DIMS(CLASS)
virtual void SetNode(unsigned nodeIndex, ChastePoint< SPACE_DIM > point)
std::map< unsigned, std::set< CellPtr > > mLocationCellMap
void SetCellUsingLocationIndex(unsigned index, CellPtr pCell)
virtual void AcceptPopulationWriter(boost::shared_ptr< AbstractCellPopulationWriter< DIM, DIM > > pPopulationWriter)
void Update(bool hasHadBirthsOrDeaths=true)
std::map< Cell *, unsigned > mCellLocationMap
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)
double GetT2Threshold() const
virtual TetrahedralMesh< DIM, DIM > * GetTetrahedralMeshForPdeModifier()
void WriteVtkUsingMesh(VertexMesh< ELEMENT_DIM, SPACE_DIM > &rMesh, std::string stamp="")
double GetCellRearrangementThreshold() const
virtual double GetVolumeOfElement(unsigned index)
virtual void CheckForStepSizeException(unsigned nodeIndex, c_vector< double, DIM > &rDisplacement, double dt)
void OutputCellPopulationParameters(out_stream &rParamsFile)
virtual void OutputCellPopulationParameters(out_stream &rParamsFile)
unsigned RemoveDeadCells()
virtual void OpenWritersFiles(OutputFileHandler &rOutputFileHandler)
std::list< CellPtr > mCells
virtual void ReMesh(VertexElementMap &rElementMap)
virtual void OpenWritersFiles(OutputFileHandler &rOutputFileHandler)
void SetMeshHasChangedSinceLoading()
void SetNode(unsigned index, ChastePoint< DIM > &rNewLocation)
void DeleteElementPriorToReMesh(unsigned index)
void AddCellIdOfT2Swap(unsigned idOfT2Swap)
double GetWidth(const unsigned &rDimension)
c_vector< double, DIM > GetLocationOfCellCentre(CellPtr pCell)
virtual c_vector< double, SPACE_DIM > GetCentroidOfElement(unsigned index)
unsigned AddNode(Node< DIM > *pNewNode)
std::set< unsigned > GetNeighbouringElementIndices(unsigned elementIndex)
CellPtr AddCell(CellPtr pNewCell, CellPtr pParentCell=CellPtr())
unsigned GetNumNodes() const
virtual void WriteVtkResultsToFile(const std::string &rDirectory)
virtual double GetCellDataItemAtPdeNode(unsigned pdeNodeIndex, std::string &rVariableName, bool dirichletBoundaryConditionApplies=false, double dirichletBoundaryValue=0.0)
VertexElementIterator GetElementIteratorEnd()
void ClearLocationsAndCellIdsOfT2Swaps()
virtual void AddCellUsingLocationIndex(unsigned index, CellPtr pCell)
AbstractMesh< ELEMENT_DIM, SPACE_DIM > & mrMesh
bool IsBoundaryNode() const
VertexElement< DIM, DIM > * GetElement(unsigned elementIndex)
unsigned GetTimeStepsElapsed() const
#define MAKE_PTR_ARGS(TYPE, NAME, ARGS)
bool GetOutputCellRearrangementLocations()
VertexElement< DIM, DIM > * GetElementCorrespondingToCell(CellPtr pCell)
unsigned GetRosetteRankOfElement(unsigned index)