Chaste  Release::2018.1
PottsMesh.cpp
1 /*
2 
3 Copyright (c) 2005-2018, University of Oxford.
4 All rights reserved.
5 
6 University of Oxford means the Chancellor, Masters and Scholars of the
7 University of Oxford, having an administrative office at Wellington
8 Square, Oxford OX1 2JD, UK.
9 
10 This file is part of Chaste.
11 
12 Redistribution and use in source and binary forms, with or without
13 modification, are permitted provided that the following conditions are met:
14  * Redistributions of source code must retain the above copyright notice,
15  this list of conditions and the following disclaimer.
16  * Redistributions in binary form must reproduce the above copyright notice,
17  this list of conditions and the following disclaimer in the documentation
18  and/or other materials provided with the distribution.
19  * Neither the name of the University of Oxford nor the names of its
20  contributors may be used to endorse or promote products derived from this
21  software without specific prior written permission.
22 
23 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
24 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26 ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
27 LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
28 CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
29 GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30 HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31 LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
32 OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33 
34 */
35 
36 #include "PottsMesh.hpp"
37 #include "RandomNumberGenerator.hpp"
38 
39 
40 template<unsigned DIM>
42  std::vector<PottsElement<DIM>*> pottsElements,
43  std::vector<std::set<unsigned> > vonNeumannNeighbouringNodeIndices,
44  std::vector<std::set<unsigned> > mooreNeighbouringNodeIndices)
45 {
46  // Reset member variables and clear mNodes, mElements.
47  Clear();
48 
49  // Verify the same size of nodes and neighbour information.
50  if ((vonNeumannNeighbouringNodeIndices.size() != nodes.size()) || (mooreNeighbouringNodeIndices.size() != nodes.size()))
51  {
52  EXCEPTION("Nodes and neighbour information for a Potts mesh need to be the same length.");
53  }
54  mVonNeumannNeighbouringNodeIndices = vonNeumannNeighbouringNodeIndices;
55  mMooreNeighbouringNodeIndices = mooreNeighbouringNodeIndices;
56 
57  // Populate mNodes and mElements
58  for (unsigned node_index=0; node_index<nodes.size(); node_index++)
59  {
60  Node<DIM>* p_temp_node = nodes[node_index];
61  this->mNodes.push_back(p_temp_node);
62  }
63  for (unsigned elem_index=0; elem_index<pottsElements.size(); elem_index++)
64  {
65  PottsElement<DIM>* p_temp_element = pottsElements[elem_index];
66  mElements.push_back(p_temp_element);
67  }
68 
69  // Register elements with nodes
70  for (unsigned index=0; index<mElements.size(); index++)
71  {
72  PottsElement<DIM>* p_element = mElements[index];
73 
74  unsigned element_index = p_element->GetIndex();
75  unsigned num_nodes_in_element = p_element->GetNumNodes();
76 
77  for (unsigned node_index=0; node_index<num_nodes_in_element; node_index++)
78  {
79  p_element->GetNode(node_index)->AddElement(element_index);
80  }
81  }
82 
83  this->mMeshChangesDuringSimulation = true;
84 }
85 
86 template<unsigned DIM>
88 {
89  this->mMeshChangesDuringSimulation = true;
90  Clear();
91 }
92 
93 template<unsigned DIM>
95 {
96  Clear();
97 }
98 
99 template<unsigned DIM>
100 unsigned PottsMesh<DIM>::SolveNodeMapping(unsigned index) const
101 {
102  assert(index < this->mNodes.size());
103  return index;
104 }
105 
106 template<unsigned DIM>
107 unsigned PottsMesh<DIM>::SolveElementMapping(unsigned index) const
108 {
109  assert(index < this->mElements.size());
110  return index;
111 }
112 
113 template<unsigned DIM>
114 unsigned PottsMesh<DIM>::SolveBoundaryElementMapping(unsigned index) const
115 {
116  return index;
117 }
118 
119 template<unsigned DIM>
121 {
122  // Delete elements
123  for (unsigned i=0; i<mElements.size(); i++)
124  {
125  delete mElements[i];
126  }
127  mElements.clear();
128 
129  // Delete nodes
130  for (unsigned i=0; i<this->mNodes.size(); i++)
131  {
132  delete this->mNodes[i];
133  }
134  this->mNodes.clear();
135 
136  mDeletedElementIndices.clear();
137 
138  // Delete neighbour info
139  //mVonNeumannNeighbouringNodeIndices.clear();
140  //mMooreNeighbouringNodeIndices.clear();
141 }
142 
143 template<unsigned DIM>
145 {
146  return this->mNodes.size();
147 }
148 
149 template<unsigned DIM>
151 {
152  return mElements.size() - mDeletedElementIndices.size();
153 }
154 
155 template<unsigned DIM>
157 {
158  return mElements.size();
159 }
160 
161 template<unsigned DIM>
163 {
164  assert(index < mElements.size());
165  return mElements[index];
166 }
167 
168 template<unsigned DIM>
169 c_vector<double, DIM> PottsMesh<DIM>::GetCentroidOfElement(unsigned index)
170 {
171  PottsElement<DIM>* p_element = GetElement(index);
172  unsigned num_nodes_in_element = p_element->GetNumNodes();
173 
175  c_vector<double, DIM> centroid = zero_vector<double>(DIM);
176 
177  for (unsigned local_index=0; local_index<num_nodes_in_element; local_index++)
178  {
179  // Find location of current node and add it to the centroid
180  centroid += p_element->GetNodeLocation(local_index);
181  }
182 
183  centroid /= num_nodes_in_element;
184 
185  return centroid;
186 }
187 
188 template<unsigned DIM>
190 {
191  PottsElement<DIM>* p_element = GetElement(index);
192  double element_volume = (double) p_element->GetNumNodes();
193 
194  return element_volume;
195 }
196 
197 template<unsigned DIM>
199 {
201  assert(DIM==2 || DIM==3); // LCOV_EXCL_LINE
202 
203  // Helper variables
204  PottsElement<DIM>* p_element = GetElement(index);
205  unsigned num_nodes = p_element->GetNumNodes();
206 
207  double surface_area = 0.0;
208  for (unsigned node_index=0; node_index<num_nodes; node_index++)
209  {
210  std::set<unsigned> neighbouring_node_indices = GetVonNeumannNeighbouringNodeIndices(p_element->GetNode(node_index)->GetIndex());
211  unsigned local_edges = 2*DIM;
212  for (std::set<unsigned>::iterator iter = neighbouring_node_indices.begin();
213  iter != neighbouring_node_indices.end();
214  iter++)
215  {
216  std::set<unsigned> neighbouring_node_element_indices = this->mNodes[*iter]->rGetContainingElementIndices();
217 
218  if (!(neighbouring_node_element_indices.empty()) && (local_edges!=0))
219  {
220  unsigned neighbouring_node_element_index = *(neighbouring_node_element_indices.begin());
221  if (neighbouring_node_element_index == index)
222  {
223  local_edges--;
224  }
225  }
226  }
227  surface_area += local_edges;
228  }
229  return surface_area;
230 }
231 
232 template<unsigned DIM>
233 std::set<unsigned> PottsMesh<DIM>::GetMooreNeighbouringNodeIndices(unsigned nodeIndex)
234 {
235  return mMooreNeighbouringNodeIndices[nodeIndex];
236 }
237 
238 template<unsigned DIM>
239 std::set<unsigned> PottsMesh<DIM>::GetVonNeumannNeighbouringNodeIndices(unsigned nodeIndex)
240 {
241  return mVonNeumannNeighbouringNodeIndices[nodeIndex];
242 }
243 
244 template<unsigned DIM>
245 void PottsMesh<DIM>::DeleteElement(unsigned index)
246 {
247  // Mark this element as deleted; this also updates the nodes containing element indices
248  this->mElements[index]->MarkAsDeleted();
249  mDeletedElementIndices.push_back(index);
250 }
251 
252 template<unsigned DIM>
254 {
255  // Remove any elements that have been removed and re-order the remaining ones
256  unsigned num_deleted_elements = mDeletedElementIndices.size();
257 
258  for (unsigned index = num_deleted_elements; index>0; index--)
259  {
260  unsigned deleted_elem_index = mDeletedElementIndices[index-1];
261  delete mElements[deleted_elem_index];
262  mElements.erase(mElements.begin()+deleted_elem_index);
263  for (unsigned elem_index=deleted_elem_index; elem_index<mElements.size(); elem_index++)
264  {
265  mElements[elem_index]->ResetIndex(elem_index);
266  }
267  }
268  mDeletedElementIndices.clear();
269 }
270 
271 template<unsigned DIM>
272 void PottsMesh<DIM>::DeleteNode(unsigned index)
273 {
274  //Mark node as deleted so we don't consider it when iterating over nodes
275  this->mNodes[index]->MarkAsDeleted();
276 
277  //Remove from Elements
278  std::set<unsigned> containing_element_indices = this->mNodes[index]->rGetContainingElementIndices();
279 
280  for (std::set<unsigned>::iterator iter = containing_element_indices.begin();
281  iter != containing_element_indices.end();
282  iter++)
283  {
284  assert(mElements[*iter]->GetNumNodes() > 0);
285  if (mElements[*iter]->GetNumNodes() == 1)
286  {
287  DeleteElement(*iter);
288  }
289  else
290  {
291  this->mElements[*iter]->DeleteNode(this->mElements[*iter]->GetNodeLocalIndex(index));
292  }
293  }
294 
295  // Remove from connectivity
296  mVonNeumannNeighbouringNodeIndices[index].clear();
297  mMooreNeighbouringNodeIndices[index].clear();
298 
299  assert(mVonNeumannNeighbouringNodeIndices.size()==mMooreNeighbouringNodeIndices.size());
300  for (unsigned node_index = 0;
301  node_index < mVonNeumannNeighbouringNodeIndices.size();
302  node_index++)
303  {
304  // Remove node "index" from the Von Neuman neighbourhood of node "node_index".
305  mVonNeumannNeighbouringNodeIndices[node_index].erase(index);
306  mMooreNeighbouringNodeIndices[node_index].erase(index);
307 
308  // Check there's still connectivity for the other non-deleted nodes
309  if (!this->mNodes[node_index]->IsDeleted())
310  {
311  assert(!mVonNeumannNeighbouringNodeIndices[node_index].empty());
312  assert(!mMooreNeighbouringNodeIndices[node_index].empty());
313  }
314  }
315 
316  // Remove node from mNodes and renumber all the elements and nodes
317  delete this->mNodes[index];
318  this->mNodes.erase(this->mNodes.begin()+index);
319  unsigned num_nodes = GetNumNodes();
320  mVonNeumannNeighbouringNodeIndices.erase(mVonNeumannNeighbouringNodeIndices.begin()+index);
321  mMooreNeighbouringNodeIndices.erase(mMooreNeighbouringNodeIndices.begin()+index);
322 
323  assert(mVonNeumannNeighbouringNodeIndices.size()==num_nodes);
324  assert(mMooreNeighbouringNodeIndices.size()==num_nodes);
325 
326  for (unsigned node_index = 0; node_index < num_nodes; node_index++)
327  {
328  // Reduce the index of all nodes greater than node "index"
329  if (node_index >= index)
330  {
331  assert(this->mNodes[node_index]->GetIndex() == node_index+1);
332  this->mNodes[node_index]->SetIndex(node_index);
333  }
334  assert(this->mNodes[node_index]->GetIndex() == node_index);
335 
336  // Reduce the index of all nodes greater than node "index"
337  // in the Moore and Von Neuman neighbourhoods.
338  std::set<unsigned> von_neuman = mVonNeumannNeighbouringNodeIndices[node_index];
339  mVonNeumannNeighbouringNodeIndices[node_index].clear();
340  for (std::set<unsigned>::iterator iter = von_neuman.begin();
341  iter != von_neuman.end();
342  iter++)
343  {
344  if (*iter >= index)
345  {
346  mVonNeumannNeighbouringNodeIndices[node_index].insert(*iter-1);
347  }
348  else
349  {
350  mVonNeumannNeighbouringNodeIndices[node_index].insert(*iter);
351  }
352  }
353  std::set<unsigned> moore = mMooreNeighbouringNodeIndices[node_index];
354  mMooreNeighbouringNodeIndices[node_index].clear();
355  for (std::set<unsigned>::iterator iter = moore.begin();
356  iter != moore.end();
357  iter++)
358  {
359  if (*iter >= index)
360  {
361  mMooreNeighbouringNodeIndices[node_index].insert(*iter-1);
362  }
363  else
364  {
365  mMooreNeighbouringNodeIndices[node_index].insert(*iter);
366  }
367  }
368  }
369  // Finally remove any elememts that have been removed
370  assert(mDeletedElementIndices.size() <= 1); // Should have at most one element to remove
371  if (mDeletedElementIndices.size() == 1)
372  {
373  unsigned deleted_elem_index = mDeletedElementIndices[0];
374  delete mElements[deleted_elem_index];
375  mElements.erase(mElements.begin()+deleted_elem_index);
376  mDeletedElementIndices.clear();
377 
378  for (unsigned elem_index=deleted_elem_index; elem_index<GetNumElements(); elem_index++)
379  {
380  mElements[elem_index]->ResetIndex(elem_index);
381  }
382  }
383 }
384 
385 template<unsigned DIM>
387  bool placeOriginalElementBelow)
388 {
390  assert(DIM==2 || DIM==3); // LCOV_EXCL_LINE
391 
392  // Store the number of nodes in the element (this changes when nodes are deleted from the element)
393  unsigned num_nodes = pElement->GetNumNodes();
394 
395  if (num_nodes < 2)
396  {
397  EXCEPTION("Tried to divide a Potts element with only one node. Cell dividing too often given dynamic parameters.");
398  }
399 
400  // Copy the nodes in this element
401  std::vector<Node<DIM>*> nodes_elem;
402  for (unsigned i=0; i<num_nodes; i++)
403  {
404  nodes_elem.push_back(pElement->GetNode(i));
405  }
406 
407  // Get the index of the new element
408  unsigned new_element_index;
409  if (mDeletedElementIndices.empty())
410  {
411  new_element_index = this->mElements.size();
412  }
413  else
414  {
415  new_element_index = mDeletedElementIndices.back();
416  mDeletedElementIndices.pop_back();
417  delete this->mElements[new_element_index];
418  }
419 
420  // Add the new element to the mesh
421  AddElement(new PottsElement<DIM>(new_element_index, nodes_elem));
422 
428  unsigned half_num_nodes = num_nodes/2; // This will round down
429  assert(half_num_nodes > 0);
430  assert(half_num_nodes < num_nodes);
431 
432  // Find lowest element
434  double height_midpoint_1 = 0.0;
435  double height_midpoint_2 = 0.0;
436  unsigned counter_1 = 0;
437  unsigned counter_2 = 0;
438 
439  for (unsigned i=0; i<num_nodes; i++)
440  {
441  if (i<half_num_nodes)
442  {
443  height_midpoint_1 += pElement->GetNode(i)->rGetLocation()[DIM - 1];
444  counter_1++;
445  }
446  else
447  {
448  height_midpoint_2 += pElement->GetNode(i)->rGetLocation()[DIM -1];
449  counter_2++;
450  }
451  }
452  height_midpoint_1 /= (double)counter_1;
453  height_midpoint_2 /= (double)counter_2;
454 
455  for (unsigned i=num_nodes; i>0; i--)
456  {
457  if (i-1 >= half_num_nodes)
458  {
459  if (height_midpoint_1 < height_midpoint_2)
460  {
461  if (placeOriginalElementBelow)
462  {
463  pElement->DeleteNode(i-1);
464  }
465  else
466  {
467  this->mElements[new_element_index]->DeleteNode(i-1);
468  }
469  }
470  else
471  {
472  if (placeOriginalElementBelow)
473  {
474  this->mElements[new_element_index]->DeleteNode(i-1);
475  }
476  else
477  {
478  pElement->DeleteNode(i-1);
479  }
480  }
481  }
482  else // i-1 < half_num_nodes
483  {
484  if (height_midpoint_1 < height_midpoint_2)
485  {
486  if (placeOriginalElementBelow)
487  {
488  this->mElements[new_element_index]->DeleteNode(i-1);
489  }
490  else
491  {
492  pElement->DeleteNode(i-1);
493  }
494  }
495  else
496  {
497  if (placeOriginalElementBelow)
498  {
499  pElement->DeleteNode(i-1);
500  }
501  else
502  {
503  this->mElements[new_element_index]->DeleteNode(i-1);
504  }
505  }
506  }
507  }
508 
509  return new_element_index;
510 }
511 
512 template<unsigned DIM>
514 {
515  unsigned new_element_index = pNewElement->GetIndex();
516 
517  if (new_element_index == this->mElements.size())
518  {
519  this->mElements.push_back(pNewElement);
520  }
521  else
522  {
523  this->mElements[new_element_index] = pNewElement;
524  }
525  pNewElement->RegisterWithNodes();
526  return pNewElement->GetIndex();
527 }
528 
529 template<unsigned DIM>
530 std::set<unsigned> PottsMesh<DIM>::GetNeighbouringElementIndices(unsigned elementIndex)
531 {
532  // Helper variables
533  PottsElement<DIM>* p_element = this->GetElement(elementIndex);
534  unsigned num_nodes = p_element->GetNumNodes();
535 
536  // Create a set of neighbouring element indices
537  std::set<unsigned> neighbouring_element_indices;
538 
539  // Loop over nodes owned by this element
540  for (unsigned local_index=0; local_index<num_nodes; local_index++)
541  {
542  // Get a pointer to this node
543  Node<DIM>* p_node = p_element->GetNode(local_index);
544 
545  // Find the indices of the elements owned by neighbours of this node
546 
547  // Loop over neighbouring nodes. Only want Von Neuman neighbours (i.e N,S,E,W) as need to share an edge
548  std::set<unsigned> neighbouring_node_indices = GetVonNeumannNeighbouringNodeIndices(p_node->GetIndex());
549 
550  // Iterate over these neighbouring nodes
551  for (std::set<unsigned>::iterator neighbour_iter = neighbouring_node_indices.begin();
552  neighbour_iter != neighbouring_node_indices.end();
553  ++neighbour_iter)
554  {
555  std::set<unsigned> neighbouring_node_containing_elem_indices = this->GetNode(*neighbour_iter)->rGetContainingElementIndices();
556 
557  assert(neighbouring_node_containing_elem_indices.size()<2); // Either in element or in medium
558 
559  if (neighbouring_node_containing_elem_indices.size()==1) // Node is in an element
560  {
561  // Add this element to the neighbouring elements set
562  neighbouring_element_indices.insert(*(neighbouring_node_containing_elem_indices.begin()));
563  }
564  }
565  }
566 
567  // Lastly remove this element's index from the set of neighbouring element indices
568  neighbouring_element_indices.erase(elementIndex);
569 
570  return neighbouring_element_indices;
571 }
572 
573 template<unsigned DIM>
575 {
576  assert(rMeshReader.HasNodePermutation() == false);
577 
578  // Store numbers of nodes and elements
579  unsigned num_nodes = rMeshReader.GetNumNodes();
580  unsigned num_elements = rMeshReader.GetNumElements();
581 
582  // Reserve memory for nodes
583  this->mNodes.reserve(num_nodes);
584 
585  rMeshReader.Reset();
586 
587  // Add nodes
588  std::vector<double> node_data;
589  for (unsigned i=0; i<num_nodes; i++)
590  {
591  node_data = rMeshReader.GetNextNode();
592  unsigned is_boundary_node = (bool) node_data[DIM];
593  node_data.pop_back();
594  this->mNodes.push_back(new Node<DIM>(i, node_data, is_boundary_node));
595  }
596 
597  rMeshReader.Reset();
598 
599  // Reserve memory for nodes
600  mElements.reserve(rMeshReader.GetNumElements());
601 
602  // Add elements
603  for (unsigned elem_index=0; elem_index<num_elements; elem_index++)
604  {
605  // Get the data for this element
606  ElementData element_data = rMeshReader.GetNextElementData();
607 
608  // Get the nodes owned by this element
609  std::vector<Node<DIM>*> nodes;
610  unsigned num_nodes_in_element = element_data.NodeIndices.size();
611  for (unsigned j=0; j<num_nodes_in_element; j++)
612  {
613  assert(element_data.NodeIndices[j] < this->mNodes.size());
614  nodes.push_back(this->mNodes[element_data.NodeIndices[j]]);
615  }
616 
617  // Use nodes and index to construct this element
618  PottsElement<DIM>* p_element = new PottsElement<DIM>(elem_index, nodes);
619  mElements.push_back(p_element);
620 
621  if (rMeshReader.GetNumElementAttributes() > 0)
622  {
623  assert(rMeshReader.GetNumElementAttributes() == 1);
624  double attribute_value = element_data.AttributeValue;
625  p_element->SetAttribute(attribute_value);
626  }
627  }
628 
629  // If we are just using a mesh reader, then there is no neighbour information (see #1932)
630  if (mVonNeumannNeighbouringNodeIndices.empty())
631  {
632  mVonNeumannNeighbouringNodeIndices.resize(num_nodes);
633  }
634  if (mMooreNeighbouringNodeIndices.empty())
635  {
636  mMooreNeighbouringNodeIndices.resize(num_nodes);
637  }
638 }
639 
640 // Explicit instantiation
641 template class PottsMesh<1>;
642 template class PottsMesh<2>;
643 template class PottsMesh<3>;
644 
645 // Serialization for Boost >= 1.36
648 
unsigned AddElement(PottsElement< DIM > *pNewElement)
Definition: PottsMesh.cpp:513
unsigned SolveBoundaryElementMapping(unsigned index) const
Definition: PottsMesh.cpp:114
void SetAttribute(double attribute)
virtual ElementData GetNextElementData()=0
Definition: Node.hpp:58
void DeleteNode(unsigned index)
Definition: PottsMesh.cpp:272
void DeleteElement(unsigned index)
Definition: PottsMesh.cpp:245
virtual double GetVolumeOfElement(unsigned index)
Definition: PottsMesh.cpp:189
void ConstructFromMeshReader(AbstractMeshReader< DIM, DIM > &rMeshReader)
Definition: PottsMesh.cpp:574
#define EXCEPTION(message)
Definition: Exception.hpp:143
void RemoveDeletedElements()
Definition: PottsMesh.cpp:253
std::set< unsigned > GetVonNeumannNeighbouringNodeIndices(unsigned nodeIndex)
Definition: PottsMesh.cpp:239
unsigned GetNumAllElements() const
Definition: PottsMesh.cpp:156
virtual ~PottsMesh()
Definition: PottsMesh.cpp:94
std::set< unsigned > GetMooreNeighbouringNodeIndices(unsigned nodeIndex)
Definition: PottsMesh.cpp:233
unsigned SolveElementMapping(unsigned index) const
Definition: PottsMesh.cpp:107
unsigned DivideElement(PottsElement< DIM > *pElement, bool placeOriginalElementBelow=false)
Definition: PottsMesh.cpp:386
std::vector< unsigned > NodeIndices
Node< SPACE_DIM > * GetNode(unsigned localIndex) const
virtual bool HasNodePermutation()
virtual c_vector< double, DIM > GetCentroidOfElement(unsigned index)
Definition: PottsMesh.cpp:169
virtual void Clear()
Definition: PottsMesh.cpp:120
virtual unsigned GetNumNodes() const
Definition: PottsMesh.cpp:144
#define EXPORT_TEMPLATE_CLASS_SAME_DIMS(CLASS)
virtual unsigned GetNumElements() const =0
virtual void Reset()=0
unsigned GetNumNodes() const
virtual double GetSurfaceAreaOfElement(unsigned index)
Definition: PottsMesh.cpp:198
std::set< unsigned > GetNeighbouringElementIndices(unsigned elementIndex)
Definition: PottsMesh.cpp:530
virtual unsigned GetNumElementAttributes() const
PottsElement< DIM > * GetElement(unsigned index) const
Definition: PottsMesh.cpp:162
virtual unsigned GetNumElements() const
Definition: PottsMesh.cpp:150
unsigned GetIndex() const
unsigned SolveNodeMapping(unsigned index) const
Definition: PottsMesh.cpp:100
void DeleteNode(const unsigned &rIndex)
double GetNodeLocation(unsigned localIndex, unsigned dimension) const
virtual std::vector< double > GetNextNode()=0
unsigned GetIndex() const
Definition: Node.cpp:158
virtual unsigned GetNumNodes() const =0