void VoronoiDataWriter<ELEMENT_DIM, SPACE_DIM>::Visit(MeshBasedCellPopulation<ELEMENT_DIM, SPACE_DIM>* pCellPopulation) { assert(SPACE_DIM==2 || SPACE_DIM==3); VertexMesh<ELEMENT_DIM,SPACE_DIM>* voronoi_tesselation = pCellPopulation->GetVoronoiTessellation(); // Loop over elements of voronoi_tesselation for (typename VertexMesh<ELEMENT_DIM,SPACE_DIM>::VertexElementIterator elem_iter = voronoi_tesselation->GetElementIteratorBegin(); elem_iter != voronoi_tesselation->GetElementIteratorEnd(); ++elem_iter) { // Get index of this element in voronoi_tesselation unsigned elem_index = elem_iter->GetIndex(); // Get the index of the corresponding node in mrMesh unsigned node_index = voronoi_tesselation->GetDelaunayNodeIndexCorrespondingToVoronoiElementIndex(elem_index); // Write node index and location to file *this->mpOutStream << node_index << " "; c_vector<double, SPACE_DIM> node_location = pCellPopulation->GetNode(node_index)->rGetLocation(); for (unsigned i=0; i<SPACE_DIM; i++) { *this->mpOutStream << node_location[i] << " "; } double cell_volume = voronoi_tesselation->GetVolumeOfElement(elem_index); double cell_surface_area = voronoi_tesselation->GetSurfaceAreaOfElement(elem_index); *this->mpOutStream << cell_volume << " " << cell_surface_area << " "; } }
void VertexMeshWriter<ELEMENT_DIM, SPACE_DIM>::MakeVtkMesh(VertexMesh<ELEMENT_DIM, SPACE_DIM>& rMesh) { #ifdef CHASTE_VTK // Make the Vtk mesh vtkPoints* p_pts = vtkPoints::New(VTK_DOUBLE); p_pts->GetData()->SetName("Vertex positions"); for (unsigned node_num=0; node_num<rMesh.GetNumNodes(); node_num++) { c_vector<double, SPACE_DIM> position = rMesh.GetNode(node_num)->rGetLocation(); if (SPACE_DIM==2) { p_pts->InsertPoint(node_num, position[0], position[1], 0.0); } else { p_pts->InsertPoint(node_num, position[0], position[1], position[2]); } } mpVtkUnstructedMesh->SetPoints(p_pts); p_pts->Delete(); // Reference counted for (typename VertexMesh<ELEMENT_DIM,SPACE_DIM>::VertexElementIterator iter = rMesh.GetElementIteratorBegin(); iter != rMesh.GetElementIteratorEnd(); ++iter) { vtkCell* p_cell; if (SPACE_DIM == 2) { p_cell = vtkPolygon::New(); } else { p_cell = vtkConvexPointSet::New(); } vtkIdList* p_cell_id_list = p_cell->GetPointIds(); p_cell_id_list->SetNumberOfIds(iter->GetNumNodes()); for (unsigned j=0; j<iter->GetNumNodes(); ++j) { p_cell_id_list->SetId(j, iter->GetNodeGlobalIndex(j)); } mpVtkUnstructedMesh->InsertNextCell(p_cell->GetCellType(), p_cell_id_list); p_cell->Delete(); // Reference counted } #endif //CHASTE_VTK }
void CellPopulationAreaWriter<ELEMENT_DIM, SPACE_DIM>::Visit(MeshBasedCellPopulation<ELEMENT_DIM, SPACE_DIM>* pCellPopulation) { assert(SPACE_DIM==2 || SPACE_DIM==3); VertexMesh<ELEMENT_DIM, SPACE_DIM>* voronoi_tessellation = pCellPopulation->GetVoronoiTessellation(); assert (voronoi_tessellation != NULL); // Don't use the Voronoi tessellation to calculate the total area of the mesh because it gives huge areas for boundary cells double total_area = static_cast<MutableMesh<ELEMENT_DIM,SPACE_DIM>&>((pCellPopulation->rGetMesh())).GetVolume(); double apoptotic_area = 0.0; // Loop over elements of mpVoronoiTessellation for (typename VertexMesh<ELEMENT_DIM,SPACE_DIM>::VertexElementIterator elem_iter = voronoi_tessellation->GetElementIteratorBegin(); elem_iter != voronoi_tessellation->GetElementIteratorEnd(); ++elem_iter) { // Get index of this element in mpVoronoiTessellation unsigned elem_index = elem_iter->GetIndex(); // Get the index of the corresponding node in mrMesh unsigned node_index = voronoi_tessellation->GetDelaunayNodeIndexCorrespondingToVoronoiElementIndex(elem_index); // Discount ghost nodes if (!pCellPopulation->IsGhostNode(node_index)) { // Get the cell corresponding to this node CellPtr p_cell = pCellPopulation->GetCellUsingLocationIndex(node_index); // Only bother calculating the area/volume of apoptotic cells bool cell_is_apoptotic = p_cell->HasCellProperty<ApoptoticCellProperty>(); if (cell_is_apoptotic) { double cell_volume = voronoi_tessellation->GetVolumeOfElement(elem_index); apoptotic_area += cell_volume; } } } *this->mpOutStream << total_area << " " << apoptotic_area; }
void MeshBasedCellPopulationWithGhostNodes<DIM>::WriteVtkResultsToFile(const std::string& rDirectory) { #ifdef CHASTE_VTK if (this->mpVoronoiTessellation != NULL) { unsigned num_timesteps = SimulationTime::Instance()->GetTimeStepsElapsed(); std::stringstream time; time << num_timesteps; // Create mesh writer for VTK output VertexMeshWriter<DIM, DIM> mesh_writer(rDirectory, "results", false); // Iterate over any cell writers that are present unsigned num_vtk_cells = this->mpVoronoiTessellation->GetNumElements(); for (typename std::vector<boost::shared_ptr<AbstractCellWriter<DIM, DIM> > >::iterator cell_writer_iter = this->mCellWriters.begin(); cell_writer_iter != this->mCellWriters.end(); ++cell_writer_iter) { // Create vector to store VTK cell data std::vector<double> vtk_cell_data(num_vtk_cells); // Loop over elements of mpVoronoiTessellation for (typename VertexMesh<DIM, DIM>::VertexElementIterator elem_iter = this->mpVoronoiTessellation->GetElementIteratorBegin(); elem_iter != this->mpVoronoiTessellation->GetElementIteratorEnd(); ++elem_iter) { // Get the indices of this element and the corresponding node in mrMesh unsigned elem_index = elem_iter->GetIndex(); unsigned node_index = this->mpVoronoiTessellation->GetDelaunayNodeIndexCorrespondingToVoronoiElementIndex(elem_index); // If this node corresponds to a ghost node, set any "cell" data to be -1.0 if (this->IsGhostNode(node_index)) { // Populate the vector of VTK cell data vtk_cell_data[elem_index] = -1.0; } else { // Get the cell corresponding to this node CellPtr p_cell = this->GetCellUsingLocationIndex(node_index); // Populate the vector of VTK cell data vtk_cell_data[elem_index] = (*cell_writer_iter)->GetCellDataForVtkOutput(p_cell, this); } } mesh_writer.AddCellData((*cell_writer_iter)->GetVtkCellDataName(), vtk_cell_data); } // Next, record which nodes are ghost nodes // Note that the cell writer hierarchy can not be used to do this as ghost nodes don't have corresponding cells. std::vector<double> ghosts(num_vtk_cells); for (typename VertexMesh<DIM, DIM>::VertexElementIterator elem_iter = this->mpVoronoiTessellation->GetElementIteratorBegin(); elem_iter != this->mpVoronoiTessellation->GetElementIteratorEnd(); ++elem_iter) { unsigned elem_index = elem_iter->GetIndex(); unsigned node_index = this->mpVoronoiTessellation->GetDelaunayNodeIndexCorrespondingToVoronoiElementIndex(elem_index); ghosts[elem_index] = (double) (this->IsGhostNode(node_index)); } mesh_writer.AddCellData("Non-ghosts", ghosts); ///\todo #1975 - deal with possibility of information stored in CellData mesh_writer.WriteVtkUsingMesh(*(this->mpVoronoiTessellation), time.str()); *(this->mpVtkMetaFile) << " <DataSet timestep=\""; *(this->mpVtkMetaFile) << num_timesteps; *(this->mpVtkMetaFile) << "\" group=\"\" part=\"0\" file=\"results_"; *(this->mpVtkMetaFile) << num_timesteps; *(this->mpVtkMetaFile) << ".vtu\"/>\n"; } #endif //CHASTE_VTK }
void FarhadifarForce<DIM>::AddForceContribution(AbstractCellPopulation<DIM>& rCellPopulation) { // Throw an exception message if not using a VertexBasedCellPopulation ///\todo: check whether this line influences profiling tests - if so, we should remove it. if (dynamic_cast<VertexBasedCellPopulation<DIM>*>(&rCellPopulation) == nullptr) { EXCEPTION("FarhadifarForce is to be used with a VertexBasedCellPopulation only"); } // Define some helper variables VertexBasedCellPopulation<DIM>* p_cell_population = static_cast<VertexBasedCellPopulation<DIM>*>(&rCellPopulation); unsigned num_nodes = p_cell_population->GetNumNodes(); unsigned num_elements = p_cell_population->GetNumElements(); // Begin by computing the area and perimeter of each element in the mesh, to avoid having to do this multiple times std::vector<double> element_areas(num_elements); std::vector<double> element_perimeters(num_elements); std::vector<double> target_areas(num_elements); for (typename VertexMesh<DIM,DIM>::VertexElementIterator elem_iter = p_cell_population->rGetMesh().GetElementIteratorBegin(); elem_iter != p_cell_population->rGetMesh().GetElementIteratorEnd(); ++elem_iter) { unsigned elem_index = elem_iter->GetIndex(); element_areas[elem_index] = p_cell_population->rGetMesh().GetVolumeOfElement(elem_index); element_perimeters[elem_index] = p_cell_population->rGetMesh().GetSurfaceAreaOfElement(elem_index); try { // If we haven't specified a growth modifier, there won't be any target areas in the CellData array and CellData // will throw an exception that it doesn't have "target area" entries. We add this piece of code to give a more // understandable message. There is a slight chance that the exception is thrown although the error is not about the // target areas. target_areas[elem_index] = p_cell_population->GetCellUsingLocationIndex(elem_index)->GetCellData()->GetItem("target area"); } catch (Exception&) { EXCEPTION("You need to add an AbstractTargetAreaModifier to the simulation in order to use a FarhadifarForce"); } } // Iterate over vertices in the cell population for (unsigned node_index=0; node_index<num_nodes; node_index++) { Node<DIM>* p_this_node = p_cell_population->GetNode(node_index); /* * The force on this Node is given by the gradient of the total free * energy of the CellPopulation, evaluated at the position of the vertex. This * free energy is the sum of the free energies of all CellPtrs in * the cell population. The free energy of each CellPtr is comprised of three * terms - an area deformation energy, a perimeter deformation energy * and line tension energy. * * Note that since the movement of this Node only affects the free energy * of the CellPtrs containing it, we can just consider the contributions * to the free energy gradient from each of these CellPtrs. */ c_vector<double, DIM> area_elasticity_contribution = zero_vector<double>(DIM); c_vector<double, DIM> perimeter_contractility_contribution = zero_vector<double>(DIM); c_vector<double, DIM> line_tension_contribution = zero_vector<double>(DIM); // Find the indices of the elements owned by this node std::set<unsigned> containing_elem_indices = p_cell_population->GetNode(node_index)->rGetContainingElementIndices(); // Iterate over these elements for (std::set<unsigned>::iterator iter = containing_elem_indices.begin(); iter != containing_elem_indices.end(); ++iter) { // Get this element, its index and its number of nodes VertexElement<DIM, DIM>* p_element = p_cell_population->GetElement(*iter); unsigned elem_index = p_element->GetIndex(); unsigned num_nodes_elem = p_element->GetNumNodes(); // Find the local index of this node in this element unsigned local_index = p_element->GetNodeLocalIndex(node_index); // Add the force contribution from this cell's area elasticity (note the minus sign) c_vector<double, DIM> element_area_gradient = p_cell_population->rGetMesh().GetAreaGradientOfElementAtNode(p_element, local_index); area_elasticity_contribution -= GetAreaElasticityParameter()*(element_areas[elem_index] - target_areas[elem_index])*element_area_gradient; // Get the previous and next nodes in this element unsigned previous_node_local_index = (num_nodes_elem+local_index-1)%num_nodes_elem; Node<DIM>* p_previous_node = p_element->GetNode(previous_node_local_index); unsigned next_node_local_index = (local_index+1)%num_nodes_elem; Node<DIM>* p_next_node = p_element->GetNode(next_node_local_index); // Compute the line tension parameter for each of these edges - be aware that this is half of the actual // value for internal edges since we are looping over each of the internal edges twice double previous_edge_line_tension_parameter = GetLineTensionParameter(p_previous_node, p_this_node, *p_cell_population); double next_edge_line_tension_parameter = GetLineTensionParameter(p_this_node, p_next_node, *p_cell_population); // Compute the gradient of each these edges, computed at the present node c_vector<double, DIM> previous_edge_gradient = -p_cell_population->rGetMesh().GetNextEdgeGradientOfElementAtNode(p_element, previous_node_local_index); c_vector<double, DIM> next_edge_gradient = p_cell_population->rGetMesh().GetNextEdgeGradientOfElementAtNode(p_element, local_index); // Add the force contribution from cell-cell and cell-boundary line tension (note the minus sign) line_tension_contribution -= previous_edge_line_tension_parameter*previous_edge_gradient + next_edge_line_tension_parameter*next_edge_gradient; // Add the force contribution from this cell's perimeter contractility (note the minus sign) c_vector<double, DIM> element_perimeter_gradient = previous_edge_gradient + next_edge_gradient; perimeter_contractility_contribution -= GetPerimeterContractilityParameter()* element_perimeters[elem_index]* element_perimeter_gradient; } c_vector<double, DIM> force_on_node = area_elasticity_contribution + perimeter_contractility_contribution + line_tension_contribution; p_cell_population->GetNode(node_index)->AddAppliedForceContribution(force_on_node); } }
void MeshBasedCellPopulation<ELEMENT_DIM,SPACE_DIM>::WriteVtkResultsToFile(const std::string& rDirectory) { #ifdef CHASTE_VTK // Store the present time as a string unsigned num_timesteps = SimulationTime::Instance()->GetTimeStepsElapsed(); std::stringstream time; time << num_timesteps; // Store the number of cells for which to output data to VTK unsigned num_cells_from_mesh = GetNumNodes(); if (!mWriteVtkAsPoints && (mpVoronoiTessellation != NULL)) { num_cells_from_mesh = mpVoronoiTessellation->GetNumElements(); } // When outputting any CellData, we assume that the first cell is representative of all cells unsigned num_cell_data_items = this->Begin()->GetCellData()->GetNumItems(); std::vector<std::string> cell_data_names = this->Begin()->GetCellData()->GetKeys(); std::vector<std::vector<double> > cell_data; for (unsigned var=0; var<num_cell_data_items; var++) { std::vector<double> cell_data_var(num_cells_from_mesh); cell_data.push_back(cell_data_var); } if (mOutputMeshInVtk) { // Create mesh writer for VTK output VtkMeshWriter<ELEMENT_DIM, SPACE_DIM> mesh_writer(rDirectory, "mesh_"+time.str(), false); mesh_writer.WriteFilesUsingMesh(rGetMesh()); } if (mWriteVtkAsPoints) { // Create mesh writer for VTK output VtkMeshWriter<SPACE_DIM, SPACE_DIM> cells_writer(rDirectory, "results_"+time.str(), false); // Iterate over any cell writers that are present unsigned num_cells = this->GetNumAllCells(); for (typename std::vector<boost::shared_ptr<AbstractCellWriter<ELEMENT_DIM, SPACE_DIM> > >::iterator cell_writer_iter = this->mCellWriters.begin(); cell_writer_iter != this->mCellWriters.end(); ++cell_writer_iter) { // Create vector to store VTK cell data std::vector<double> vtk_cell_data(num_cells); // Loop over cells for (typename AbstractCellPopulation<ELEMENT_DIM,SPACE_DIM>::Iterator cell_iter = this->Begin(); cell_iter != this->End(); ++cell_iter) { // Get the node index corresponding to this cell unsigned node_index = this->GetLocationIndexUsingCell(*cell_iter); // Populate the vector of VTK cell data vtk_cell_data[node_index] = (*cell_writer_iter)->GetCellDataForVtkOutput(*cell_iter, this); } cells_writer.AddPointData((*cell_writer_iter)->GetVtkCellDataName(), vtk_cell_data); } // Loop over cells for (typename AbstractCellPopulation<ELEMENT_DIM,SPACE_DIM>::Iterator cell_iter = this->Begin(); cell_iter != this->End(); ++cell_iter) { // Get the node index corresponding to this cell unsigned node_index = this->GetLocationIndexUsingCell(*cell_iter); for (unsigned var=0; var<num_cell_data_items; var++) { cell_data[var][node_index] = cell_iter->GetCellData()->GetItem(cell_data_names[var]); } } for (unsigned var=0; var<num_cell_data_items; var++) { cells_writer.AddPointData(cell_data_names[var], cell_data[var]); } // Make a copy of the nodes in a disposable mesh for writing { std::vector<Node<SPACE_DIM>* > nodes; for (unsigned index=0; index<this->mrMesh.GetNumNodes(); index++) { Node<SPACE_DIM>* p_node = this->mrMesh.GetNode(index); nodes.push_back(p_node); } NodesOnlyMesh<SPACE_DIM> mesh; mesh.ConstructNodesWithoutMesh(nodes, 1.5); // Arbitrary cut off as connectivity not used. cells_writer.WriteFilesUsingMesh(mesh); } *(this->mpVtkMetaFile) << " <DataSet timestep=\""; *(this->mpVtkMetaFile) << num_timesteps; *(this->mpVtkMetaFile) << "\" group=\"\" part=\"0\" file=\"results_"; *(this->mpVtkMetaFile) << num_timesteps; *(this->mpVtkMetaFile) << ".vtu\"/>\n"; } else if (mpVoronoiTessellation != NULL) { // Create mesh writer for VTK output VertexMeshWriter<ELEMENT_DIM, SPACE_DIM> mesh_writer(rDirectory, "results", false); std::vector<double> cell_volumes(num_cells_from_mesh); // Iterate over any cell writers that are present unsigned num_cells = this->GetNumAllCells(); for (typename std::vector<boost::shared_ptr<AbstractCellWriter<ELEMENT_DIM, SPACE_DIM> > >::iterator cell_writer_iter = this->mCellWriters.begin(); cell_writer_iter != this->mCellWriters.end(); ++cell_writer_iter) { // Create vector to store VTK cell data std::vector<double> vtk_cell_data(num_cells); // Loop over elements of mpVoronoiTessellation for (typename VertexMesh<ELEMENT_DIM, SPACE_DIM>::VertexElementIterator elem_iter = mpVoronoiTessellation->GetElementIteratorBegin(); elem_iter != mpVoronoiTessellation->GetElementIteratorEnd(); ++elem_iter) { // Get index of this element in mpVoronoiTessellation unsigned elem_index = elem_iter->GetIndex(); // Get the cell corresponding to this element, via the index of the corresponding node in mrMesh unsigned node_index = mpVoronoiTessellation->GetDelaunayNodeIndexCorrespondingToVoronoiElementIndex(elem_index); CellPtr p_cell = this->GetCellUsingLocationIndex(node_index); // Populate the vector of VTK cell data vtk_cell_data[elem_index] = (*cell_writer_iter)->GetCellDataForVtkOutput(p_cell, this); } mesh_writer.AddCellData((*cell_writer_iter)->GetVtkCellDataName(), vtk_cell_data); } // Loop over elements of mpVoronoiTessellation for (typename VertexMesh<ELEMENT_DIM, SPACE_DIM>::VertexElementIterator elem_iter = mpVoronoiTessellation->GetElementIteratorBegin(); elem_iter != mpVoronoiTessellation->GetElementIteratorEnd(); ++elem_iter) { // Get index of this element in mpVoronoiTessellation unsigned elem_index = elem_iter->GetIndex(); // Get the cell corresponding to this element, via the index of the corresponding node in mrMesh unsigned node_index = mpVoronoiTessellation->GetDelaunayNodeIndexCorrespondingToVoronoiElementIndex(elem_index); CellPtr p_cell = this->GetCellUsingLocationIndex(node_index); for (unsigned var=0; var<num_cell_data_items; var++) { cell_data[var][elem_index] = p_cell->GetCellData()->GetItem(cell_data_names[var]); } } for (unsigned var=0; var<cell_data.size(); var++) { mesh_writer.AddCellData(cell_data_names[var], cell_data[var]); } mesh_writer.WriteVtkUsingMesh(*mpVoronoiTessellation, time.str()); *(this->mpVtkMetaFile) << " <DataSet timestep=\""; *(this->mpVtkMetaFile) << num_timesteps; *(this->mpVtkMetaFile) << "\" group=\"\" part=\"0\" file=\"results_"; *(this->mpVtkMetaFile) << num_timesteps; *(this->mpVtkMetaFile) << ".vtu\"/>\n"; } #endif //CHASTE_VTK }
void VertexBasedCellPopulation<DIM>::WriteVtkResultsToFile(const std::string& rDirectory) { #ifdef CHASTE_VTK // Create mesh writer for VTK output VertexMeshWriter<DIM, DIM> mesh_writer(rDirectory, "results", false); // Iterate over any cell writers that are present unsigned num_cells = this->GetNumAllCells(); for (typename std::vector<boost::shared_ptr<AbstractCellWriter<DIM, DIM> > >::iterator cell_writer_iter = this->mCellWriters.begin(); cell_writer_iter != this->mCellWriters.end(); ++cell_writer_iter) { // Create vector to store VTK cell data std::vector<double> vtk_cell_data(num_cells); // Iterate over vertex elements ///\todo #2512 - replace with loop over cells for (typename VertexMesh<DIM,DIM>::VertexElementIterator elem_iter = mpMutableVertexMesh->GetElementIteratorBegin(); elem_iter != mpMutableVertexMesh->GetElementIteratorEnd(); ++elem_iter) { // Get index of this element in the vertex mesh unsigned elem_index = elem_iter->GetIndex(); // Get the cell corresponding to this element CellPtr p_cell = this->GetCellUsingLocationIndex(elem_index); assert(p_cell); // Populate the vector of VTK cell data vtk_cell_data[elem_index] = (*cell_writer_iter)->GetCellDataForVtkOutput(p_cell, this); } mesh_writer.AddCellData((*cell_writer_iter)->GetVtkCellDataName(), vtk_cell_data); } // When outputting any CellData, we assume that the first cell is representative of all cells unsigned num_cell_data_items = this->Begin()->GetCellData()->GetNumItems(); std::vector<std::string> cell_data_names = this->Begin()->GetCellData()->GetKeys(); std::vector<std::vector<double> > cell_data; for (unsigned var=0; var<num_cell_data_items; var++) { std::vector<double> cell_data_var(num_cells); cell_data.push_back(cell_data_var); } // Loop over vertex elements ///\todo #2512 - replace with loop over cells for (typename VertexMesh<DIM,DIM>::VertexElementIterator elem_iter = mpMutableVertexMesh->GetElementIteratorBegin(); elem_iter != mpMutableVertexMesh->GetElementIteratorEnd(); ++elem_iter) { // Get index of this element in the vertex mesh unsigned elem_index = elem_iter->GetIndex(); // Get the cell corresponding to this element CellPtr p_cell = this->GetCellUsingLocationIndex(elem_index); assert(p_cell); for (unsigned var=0; var<num_cell_data_items; var++) { cell_data[var][elem_index] = p_cell->GetCellData()->GetItem(cell_data_names[var]); } } for (unsigned var=0; var<num_cell_data_items; var++) { mesh_writer.AddCellData(cell_data_names[var], cell_data[var]); } unsigned num_timesteps = SimulationTime::Instance()->GetTimeStepsElapsed(); std::stringstream time; time << num_timesteps; mesh_writer.WriteVtkUsingMesh(*mpMutableVertexMesh, time.str()); *(this->mpVtkMetaFile) << " <DataSet timestep=\""; *(this->mpVtkMetaFile) << num_timesteps; *(this->mpVtkMetaFile) << "\" group=\"\" part=\"0\" file=\"results_"; *(this->mpVtkMetaFile) << num_timesteps; *(this->mpVtkMetaFile) << ".vtu\"/>\n"; #endif //CHASTE_VTK }