36 #include "MeshBasedCellPopulationWithGhostNodes.hpp"
37 #include "CellLocationIndexWriter.hpp"
39 template<
unsigned DIM>
42 std::vector<CellPtr>& rCells,
43 const std::vector<unsigned> locationIndices,
45 double ghostSpringStiffness)
47 mGhostSpringStiffness(ghostSpringStiffness)
49 if (!locationIndices.empty())
52 std::set<unsigned> node_indices;
53 std::set<unsigned> location_indices;
54 std::set<unsigned> ghost_node_indices;
58 node_indices.insert(this->
GetNode(i)->GetIndex());
60 for (
unsigned i=0; i<locationIndices.size(); i++)
62 location_indices.insert(locationIndices[i]);
65 std::set_difference(node_indices.begin(), node_indices.end(),
66 location_indices.begin(), location_indices.end(),
67 std::inserter(ghost_node_indices, ghost_node_indices.begin()));
79 template<
unsigned DIM>
81 double ghostSpringStiffness)
83 mGhostSpringStiffness(ghostSpringStiffness)
87 template<
unsigned DIM>
92 template<
unsigned DIM>
95 EXCEPTION(
"Currently can't solve PDEs on meshes with ghost nodes");
99 template<
unsigned DIM>
102 return this->mIsGhostNode;
105 template<
unsigned DIM>
108 return this->mIsGhostNode[index];
111 template<
unsigned DIM>
114 std::set<unsigned> ghost_node_indices;
115 for (
unsigned i=0; i<this->mIsGhostNode.size(); i++)
117 if (this->mIsGhostNode[i])
119 ghost_node_indices.insert(i);
122 return ghost_node_indices;
125 template<
unsigned DIM>
129 this->mIsGhostNode = std::vector<bool>(this->mrMesh.GetNumNodes(),
false);
132 for (std::set<unsigned>::iterator iter=rGhostNodeIndices.begin(); iter!=rGhostNodeIndices.end(); ++iter)
134 this->mIsGhostNode[*iter] =
true;
140 template<
unsigned DIM>
143 assert(rNodeAGlobalIndex != rNodeBGlobalIndex);
144 c_vector<double, DIM> unit_difference;
145 const c_vector<double, DIM>& r_node_a_location = this->GetNode(rNodeAGlobalIndex)->rGetLocation();
146 const c_vector<double, DIM>& r_node_b_location = this->GetNode(rNodeBGlobalIndex)->rGetLocation();
149 unit_difference = this->mrMesh.GetVectorFromAtoB(r_node_a_location, r_node_b_location);
151 double distance_between_nodes = norm_2(unit_difference);
152 unit_difference /= distance_between_nodes;
154 double rest_length = 1.0;
156 return mGhostSpringStiffness * unit_difference * (distance_between_nodes - rest_length);
159 template<
unsigned DIM>
164 assert(p_created_cell == pNewCell);
167 unsigned new_node_index = this->GetLocationIndexUsingCell(p_created_cell);
169 if (this->GetNumNodes() > this->mIsGhostNode.size())
171 this->mIsGhostNode.resize(this->GetNumNodes());
172 this->mIsGhostNode[new_node_index] =
false;
176 return p_created_cell;
179 template<
unsigned DIM>
183 std::vector<bool> validated_node = mIsGhostNode;
184 assert(mIsGhostNode.size()==this->GetNumNodes());
189 unsigned node_index = this->GetLocationIndexUsingCell((*cell_iter));
192 if (mIsGhostNode[node_index])
194 EXCEPTION(
"Node " << node_index <<
" is labelled as a ghost node and has a cell attached");
196 validated_node[node_index] =
true;
199 for (
unsigned i=0; i<validated_node.size(); i++)
201 if (!validated_node[i])
203 EXCEPTION(
"Node " << i <<
" does not appear to be a ghost node or have a cell associated with it");
208 template<
unsigned DIM>
212 std::vector<bool> ghost_nodes_before_remesh = mIsGhostNode;
215 mIsGhostNode.clear();
216 mIsGhostNode.resize(this->GetNumNodes());
219 for (
unsigned old_index=0; old_index<rMap.
GetSize(); old_index++)
224 mIsGhostNode[new_index] = ghost_nodes_before_remesh[old_index];
229 template<
unsigned DIM>
232 unsigned node_index = this->GetLocationIndexUsingCell(pCell);
233 std::set<unsigned> neighbour_indices = this->GetNeighbouringNodeIndices(node_index);
236 for (std::set<unsigned>::iterator iter = neighbour_indices.begin();
237 iter != neighbour_indices.end();)
239 if (this->IsGhostNode(*iter))
241 neighbour_indices.erase(iter++);
249 return neighbour_indices;
252 template<
unsigned DIM>
260 if (! this->IsGhostNode(node_iter->GetIndex()))
263 cell_writer_iter != this->mCellWriters.end();
266 CellPtr cell_from_node = this->GetCellUsingLocationIndex(node_iter->GetIndex());
267 this->AcceptCellWriter(*cell_writer_iter, cell_from_node);
273 template<
unsigned DIM>
277 std::vector<c_vector<double, DIM> > drdt(this->GetNumNodes());
278 for (
unsigned i=0; i<drdt.size(); i++)
280 drdt[i] = zero_vector<double>(DIM);
288 unsigned nodeA_global_index = edge_iterator.GetNodeA()->GetIndex();
289 unsigned nodeB_global_index = edge_iterator.GetNodeB()->GetIndex();
291 c_vector<double, DIM> force = CalculateForceBetweenGhostNodes(nodeA_global_index, nodeB_global_index);
293 if (!this->mIsGhostNode[nodeA_global_index])
295 drdt[nodeB_global_index] -= force;
299 drdt[nodeA_global_index] += force;
301 if (this->mIsGhostNode[nodeB_global_index])
303 drdt[nodeB_global_index] -= force;
309 node_iter != this->mrMesh.GetNodeIteratorEnd();
312 unsigned node_index = node_iter->GetIndex();
313 if (this->mIsGhostNode[node_index])
315 node_iter->ClearAppliedForce();
316 node_iter->AddAppliedForceContribution(drdt[node_index]);
321 template<
unsigned DIM>
324 if (this->mOutputResultsForChasteVisualizer)
326 if (!this->
template HasWriter<CellLocationIndexWriter>())
328 this->
template AddCellWriter<CellLocationIndexWriter>();
335 template<
unsigned DIM>
339 if (this->mpVoronoiTessellation !=
nullptr)
342 std::stringstream time;
343 time << num_timesteps;
349 unsigned num_vtk_cells = this->mpVoronoiTessellation->GetNumElements();
351 cell_writer_iter != this->mCellWriters.end();
355 std::vector<double> vtk_cell_data(num_vtk_cells);
359 elem_iter != this->mpVoronoiTessellation->GetElementIteratorEnd();
363 unsigned elem_index = elem_iter->GetIndex();
364 unsigned node_index = this->mpVoronoiTessellation->GetDelaunayNodeIndexCorrespondingToVoronoiElementIndex(elem_index);
367 if (this->IsGhostNode(node_index))
370 vtk_cell_data[elem_index] = -1.0;
375 CellPtr p_cell = this->GetCellUsingLocationIndex(node_index);
378 vtk_cell_data[elem_index] = (*cell_writer_iter)->GetCellDataForVtkOutput(p_cell,
this);
382 mesh_writer.
AddCellData((*cell_writer_iter)->GetVtkCellDataName(), vtk_cell_data);
387 std::vector<double> ghosts(num_vtk_cells);
389 elem_iter != this->mpVoronoiTessellation->GetElementIteratorEnd();
392 unsigned elem_index = elem_iter->GetIndex();
393 unsigned node_index = this->mpVoronoiTessellation->GetDelaunayNodeIndexCorrespondingToVoronoiElementIndex(elem_index);
394 ghosts[elem_index] = (
double) (this->IsGhostNode(node_index));
401 *(this->mpVtkMetaFile) <<
" <DataSet timestep=\"";
402 *(this->mpVtkMetaFile) << num_timesteps;
403 *(this->mpVtkMetaFile) <<
"\" group=\"\" part=\"0\" file=\"results_";
404 *(this->mpVtkMetaFile) << num_timesteps;
405 *(this->mpVtkMetaFile) <<
".vtu\"/>\n";
410 template<
unsigned DIM>
413 *rParamsFile <<
"\t\t<GhostSpringStiffness>" << mGhostSpringStiffness <<
"</GhostSpringStiffness>\n";
virtual TetrahedralMesh< DIM, DIM > * GetTetrahedralMeshForPdeModifier()
void UpdateGhostNodesAfterReMesh(NodeMap &rMap)
void AddCellData(std::string dataName, std::vector< double > dataPayload)
virtual CellPtr AddCell(CellPtr pNewCell, CellPtr pParentCell)
std::set< unsigned > GetNeighbouringLocationIndices(CellPtr pCell)
virtual void WriteVtkResultsToFile(const std::string &rDirectory)
std::set< unsigned > GetGhostNodeIndices()
virtual void OpenWritersFiles(OutputFileHandler &rOutputFileHandler)
#define EXCEPTION(message)
static SimulationTime * Instance()
bool IsGhostNode(unsigned index)
NodeIterator GetNodeIteratorEnd()
unsigned GetTimeStepsElapsed() const
virtual void AcceptCellWritersAcrossPopulation()
c_vector< double, DIM > CalculateForceBetweenGhostNodes(const unsigned &rNodeAGlobalIndex, const unsigned &rNodeBGlobalIndex)
MeshBasedCellPopulationWithGhostNodes(MutableMesh< DIM, DIM > &rMesh, std::vector< CellPtr > &rCells, const std::vector< unsigned > locationIndices=std::vector< unsigned >(), bool deleteMesh=false, double ghostSpringStiffness=15.0)
CellPtr AddCell(CellPtr pNewCell, CellPtr pParentCell)
VertexElementIterator GetElementIteratorBegin(bool skipDeletedElements=true)
#define EXPORT_TEMPLATE_CLASS_SAME_DIMS(CLASS)
void SetGhostNodes(const std::set< unsigned > &rGhostNodeIndices)
void WriteVtkUsingMesh(VertexMesh< ELEMENT_DIM, SPACE_DIM > &rMesh, std::string stamp="")
NodeIterator GetNodeIteratorBegin(bool skipDeletedNodes=true)
Node< ELEMENT_DIM > * GetNode(unsigned index)
bool IsDeleted(unsigned index)
unsigned GetNewIndex(unsigned oldIndex) const
std::vector< bool > & rGetGhostNodes()
void OutputCellPopulationParameters(out_stream &rParamsFile)
std::vector< bool > mIsGhostNode
void OutputCellPopulationParameters(out_stream &rParamsFile)
virtual ~MeshBasedCellPopulationWithGhostNodes()
virtual void OpenWritersFiles(OutputFileHandler &rOutputFileHandler)