Chaste  Release::3.4
MutableVertexMesh.cpp
1 /*
2 
3 Copyright (c) 2005-2016, 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 "MutableVertexMesh.hpp"
37 #include "UblasCustomFunctions.hpp"
38 #include "Warnings.hpp"
39 #include "LogFile.hpp"
40 
41 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
43  std::vector<VertexElement<ELEMENT_DIM,SPACE_DIM>*> vertexElements,
44  double cellRearrangementThreshold,
45  double t2Threshold,
46  double cellRearrangementRatio,
47  double protorosetteFormationProbability,
48  double protorosetteResolutionProbabilityPerTimestep,
49  double rosetteResolutionProbabilityPerTimestep)
50  : mCellRearrangementThreshold(cellRearrangementThreshold),
51  mCellRearrangementRatio(cellRearrangementRatio),
52  mT2Threshold(t2Threshold),
53  mProtorosetteFormationProbability(protorosetteFormationProbability),
54  mProtorosetteResolutionProbabilityPerTimestep(protorosetteResolutionProbabilityPerTimestep),
55  mRosetteResolutionProbabilityPerTimestep(rosetteResolutionProbabilityPerTimestep),
56  mCheckForInternalIntersections(false)
57 {
58  // Threshold parameters must be strictly positive
59  assert(cellRearrangementThreshold > 0.0);
60  assert(t2Threshold > 0.0);
61  assert(protorosetteFormationProbability >= 0.0);
62  assert(protorosetteFormationProbability <= 1.0);
63  assert(protorosetteResolutionProbabilityPerTimestep >= 0.0);
64  assert(protorosetteResolutionProbabilityPerTimestep <= 1.0);
65  assert(rosetteResolutionProbabilityPerTimestep >= 0.0);
66  assert(rosetteResolutionProbabilityPerTimestep <= 1.0);
67 
68  // Reset member variables and clear mNodes and mElements
69  Clear();
70 
71  // Populate mNodes and mElements
72  for (unsigned node_index=0; node_index<nodes.size(); node_index++)
73  {
74  Node<SPACE_DIM>* p_temp_node = nodes[node_index];
75  this->mNodes.push_back(p_temp_node);
76  }
77  for (unsigned elem_index=0; elem_index<vertexElements.size(); elem_index++)
78  {
79  VertexElement<ELEMENT_DIM,SPACE_DIM>* p_temp_vertex_element = vertexElements[elem_index];
80  this->mElements.push_back(p_temp_vertex_element);
81  }
82 
83  // If in 3D, then also populate mFaces
84  if (SPACE_DIM == 3)
85  {
86  // Use a std::set to keep track of which faces have been added to mFaces
87  std::set<unsigned> faces_counted;
88 
89  // Loop over mElements
90  for (unsigned elem_index=0; elem_index<this->mElements.size(); elem_index++)
91  {
92  // Loop over faces of this element
93  for (unsigned face_index=0; face_index<this->mElements[elem_index]->GetNumFaces(); face_index++)
94  {
95  VertexElement<ELEMENT_DIM-1, SPACE_DIM>* p_face = this->mElements[elem_index]->GetFace(face_index);
96 
97  // If this face is not already contained in mFaces, then add it and update faces_counted
98  if (faces_counted.find(p_face->GetIndex()) == faces_counted.end())
99  {
100  this->mFaces.push_back(p_face);
101  faces_counted.insert(p_face->GetIndex());
102  }
103  }
104  }
105  }
106 
107  // Register elements with nodes
108  for (unsigned index=0; index<this->mElements.size(); index++)
109  {
110  VertexElement<ELEMENT_DIM,SPACE_DIM>* p_temp_vertex_element = this->mElements[index];
111  for (unsigned node_index=0; node_index<p_temp_vertex_element->GetNumNodes(); node_index++)
112  {
113  Node<SPACE_DIM>* p_temp_node = p_temp_vertex_element->GetNode(node_index);
114  p_temp_node->AddElement(p_temp_vertex_element->GetIndex());
115  }
116  }
117 
118  this->mMeshChangesDuringSimulation = true;
119 }
120 
121 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
123  : mCellRearrangementThreshold(0.01),
124  mCellRearrangementRatio(1.5),
125  mT2Threshold(0.001),
126  mProtorosetteFormationProbability(0.0),
127  mProtorosetteResolutionProbabilityPerTimestep(0.0),
128  mRosetteResolutionProbabilityPerTimestep(0.0),
129  mCheckForInternalIntersections(false)
130 {
131  // Note that the member variables initialised above will be overwritten as soon as archiving is complete
132  this->mMeshChangesDuringSimulation = true;
133  Clear();
134 }
135 
136 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
138 {
139  Clear();
140 }
141 
142 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
144 {
145  return mCellRearrangementThreshold;
146 }
147 
148 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
150 {
151  return mT2Threshold;
152 }
153 
154 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
156 {
157  return mCellRearrangementRatio;
158 }
159 
160 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
162 {
163  return this->mProtorosetteFormationProbability;
164 }
165 
166 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
168 {
169  return this->mProtorosetteResolutionProbabilityPerTimestep;
170 }
171 
172 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
174 {
175  return this->mRosetteResolutionProbabilityPerTimestep;
176 }
177 
178 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
180 {
181  return mCheckForInternalIntersections;
182 }
183 
184 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
186 {
187  mCellRearrangementThreshold = cellRearrangementThreshold;
188 }
189 
190 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
192 {
193  mT2Threshold = t2Threshold;
194 }
195 
196 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
198 {
199  mCellRearrangementRatio = cellRearrangementRatio;
200 }
201 
202 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
204 {
205  // Check that the new value is in [0,1]
206  if (protorosetteFormationProbability < 0.0)
207  {
208  EXCEPTION("Attempting to assign a negative probability.");
209  }
210  if (protorosetteFormationProbability > 1.0)
211  {
212  EXCEPTION("Attempting to assign a probability greater than one.");
213  }
214 
215  // Assign the new value
216  mProtorosetteFormationProbability = protorosetteFormationProbability;
217 }
218 
219 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
221 {
222  // Check that the new value is in [0,1]
223  if (protorosetteResolutionProbabilityPerTimestep < 0.0)
224  {
225  EXCEPTION("Attempting to assign a negative probability.");
226  }
227  if (protorosetteResolutionProbabilityPerTimestep > 1.0)
228  {
229  EXCEPTION("Attempting to assign a probability greater than one.");
230  }
231 
232  // Assign the new value
233  mProtorosetteResolutionProbabilityPerTimestep = protorosetteResolutionProbabilityPerTimestep;
234 }
235 
236 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
238 {
239  // Check that the new value is in [0,1]
240  if (rosetteResolutionProbabilityPerTimestep < 0.0)
241  {
242  EXCEPTION("Attempting to assign a negative probability.");
243  }
244  if (rosetteResolutionProbabilityPerTimestep > 1.0)
245  {
246  EXCEPTION("Attempting to assign a probability greater than one.");
247  }
248 
249  // Assign the new value
250  mRosetteResolutionProbabilityPerTimestep = rosetteResolutionProbabilityPerTimestep;
251 }
252 
253 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
255 {
256  mCheckForInternalIntersections = checkForInternalIntersections;
257 }
258 
259 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
261 {
262  mDeletedNodeIndices.clear();
263  mDeletedElementIndices.clear();
264 
266 }
267 
268 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
270 {
271  return this->mNodes.size() - mDeletedNodeIndices.size();
272 }
273 
274 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
276 {
277  return this->mElements.size() - mDeletedElementIndices.size();
278 }
279 
280 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
281 std::vector< c_vector<double, SPACE_DIM> > MutableVertexMesh<ELEMENT_DIM, SPACE_DIM>::GetLocationsOfT1Swaps()
282 {
283  return mLocationsOfT1Swaps;
284 }
285 
286 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
288 {
289  return mLastT2SwapLocation;
290 }
291 
292 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
293 std::vector< c_vector<double, SPACE_DIM> > MutableVertexMesh<ELEMENT_DIM, SPACE_DIM>::GetLocationsOfT3Swaps()
294 {
295  return mLocationsOfT3Swaps;
296 }
297 
298 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
300 {
301  mLocationsOfT1Swaps.clear();
302 }
303 
304 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
306 {
307  mLocationsOfT3Swaps.clear();
308 }
309 
310 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
312 {
313  if (mDeletedNodeIndices.empty())
314  {
315  pNewNode->SetIndex(this->mNodes.size());
316  this->mNodes.push_back(pNewNode);
317  }
318  else
319  {
320  unsigned index = mDeletedNodeIndices.back();
321  pNewNode->SetIndex(index);
322  mDeletedNodeIndices.pop_back();
323  delete this->mNodes[index];
324  this->mNodes[index] = pNewNode;
325  }
326  return pNewNode->GetIndex();
327 }
328 
329 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
331 {
332  unsigned new_element_index = pNewElement->GetIndex();
333 
334  if (new_element_index == this->mElements.size())
335  {
336  this->mElements.push_back(pNewElement);
337  }
338  else
339  {
340  this->mElements[new_element_index] = pNewElement;
341  }
342  pNewElement->RegisterWithNodes();
343  return pNewElement->GetIndex();
344 }
345 
346 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
348 {
349  this->mNodes[nodeIndex]->SetPoint(point);
350 }
351 
352 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
354  c_vector<double, SPACE_DIM> axisOfDivision,
355  bool placeOriginalElementBelow)
356 {
357  assert(SPACE_DIM == 2);
358  assert(ELEMENT_DIM == SPACE_DIM);
359 
360  // Get the centroid of the element
361  c_vector<double, SPACE_DIM> centroid = this->GetCentroidOfElement(pElement->GetIndex());
362 
363  // Create a vector perpendicular to the axis of division
364  c_vector<double, SPACE_DIM> perp_axis;
365  perp_axis(0) = -axisOfDivision(1);
366  perp_axis(1) = axisOfDivision(0);
367 
368  /*
369  * Find which edges the axis of division crosses by finding any node
370  * that lies on the opposite side of the axis of division to its next
371  * neighbour.
372  */
373  unsigned num_nodes = pElement->GetNumNodes();
374  std::vector<unsigned> intersecting_nodes;
375  bool is_current_node_on_left = (inner_prod(this->GetVectorFromAtoB(pElement->GetNodeLocation(0), centroid), perp_axis) >= 0);
376  for (unsigned i=0; i<num_nodes; i++)
377  {
378  bool is_next_node_on_left = (inner_prod(this->GetVectorFromAtoB(pElement->GetNodeLocation((i+1)%num_nodes), centroid), perp_axis) >= 0);
379  if (is_current_node_on_left != is_next_node_on_left)
380  {
381  intersecting_nodes.push_back(i);
382  }
383  is_current_node_on_left = is_next_node_on_left;
384  }
385 
386  // If the axis of division does not cross two edges then we cannot proceed
387  if (intersecting_nodes.size() != 2)
388  {
389  EXCEPTION("Cannot proceed with element division: the given axis of division does not cross two edges of the element");
390  }
391 
392  std::vector<unsigned> division_node_global_indices;
393  unsigned nodes_added = 0;
394 
395  // Find the intersections between the axis of division and the element edges
396  for (unsigned i=0; i<intersecting_nodes.size(); i++)
397  {
398  /*
399  * Get pointers to the nodes forming the edge into which one new node will be inserted.
400  *
401  * Note that when we use the first entry of intersecting_nodes to add a node,
402  * we change the local index of the second entry of intersecting_nodes in
403  * pElement, so must account for this by moving one entry further on.
404  */
405  Node<SPACE_DIM>* p_node_A = pElement->GetNode((intersecting_nodes[i]+nodes_added)%pElement->GetNumNodes());
406  Node<SPACE_DIM>* p_node_B = pElement->GetNode((intersecting_nodes[i]+nodes_added+1)%pElement->GetNumNodes());
407 
408  // Find the indices of the elements owned by each node on the edge into which one new node will be inserted
409  std::set<unsigned> elems_containing_node_A = p_node_A->rGetContainingElementIndices();
410  std::set<unsigned> elems_containing_node_B = p_node_B->rGetContainingElementIndices();
411 
412  c_vector<double, SPACE_DIM> position_a = p_node_A->rGetLocation();
413  c_vector<double, SPACE_DIM> position_b = p_node_B->rGetLocation();
414  c_vector<double, SPACE_DIM> a_to_b = this->GetVectorFromAtoB(position_a, position_b);
415 
416  c_vector<double, SPACE_DIM> intersection;
417 
418  if (norm_2(a_to_b) < 2.0*mCellRearrangementRatio*mCellRearrangementThreshold)
419  {
420  WARNING("Edge is too small for normal division; putting node in the middle of a and b. There may be T1 swaps straight away.");
422  intersection = position_a + 0.5*a_to_b;
423  }
424  else
425  {
426  // Find the location of the intersection
427  double determinant = a_to_b[0]*axisOfDivision[1] - a_to_b[1]*axisOfDivision[0];
428 
429  // Note that we define this vector before setting it as otherwise the profiling build will break (see #2367)
430  c_vector<double, SPACE_DIM> moved_centroid;
431  moved_centroid = position_a + this->GetVectorFromAtoB(position_a, centroid);
432 
433  double alpha = (moved_centroid[0]*a_to_b[1] - position_a[0]*a_to_b[1]
434  -moved_centroid[1]*a_to_b[0] + position_a[1]*a_to_b[0])/determinant;
435 
436  intersection = moved_centroid + alpha*axisOfDivision;
437 
438  /*
439  * If then new node is too close to one of the edge nodes, then reposition it
440  * a distance mCellRearrangementRatio*mCellRearrangementThreshold further along the edge.
441  */
442  c_vector<double, SPACE_DIM> a_to_intersection = this->GetVectorFromAtoB(position_a, intersection);
443  if (norm_2(a_to_intersection) < mCellRearrangementThreshold)
444  {
445  intersection = position_a + mCellRearrangementRatio*mCellRearrangementThreshold*a_to_b/norm_2(a_to_b);
446  }
447 
448  c_vector<double, SPACE_DIM> b_to_intersection = this->GetVectorFromAtoB(position_b, intersection);
449  if (norm_2(b_to_intersection) < mCellRearrangementThreshold)
450  {
451  assert(norm_2(a_to_intersection) > mCellRearrangementThreshold); // to prevent moving intersection back to original position
452 
453  intersection = position_b - mCellRearrangementRatio*mCellRearrangementThreshold*a_to_b/norm_2(a_to_b);
454  }
455  }
456 
457  /*
458  * The new node is boundary node if the 2 nodes are boundary nodes and the elements don't look like
459  * ___A___
460  * | | |
461  * |___|___|
462  * B
463  */
464  bool is_boundary = false;
465  if (p_node_A->IsBoundaryNode() && p_node_B->IsBoundaryNode())
466  {
467  if (elems_containing_node_A.size() != 2 ||
468  elems_containing_node_B.size() != 2 ||
469  elems_containing_node_A != elems_containing_node_B)
470  {
471  is_boundary = true;
472  }
473  }
474 
475  // Add a new node to the mesh at the location of the intersection
476  unsigned new_node_global_index = this->AddNode(new Node<SPACE_DIM>(0, is_boundary, intersection[0], intersection[1]));
477  nodes_added++;
478 
479  // Now make sure the new node is added to all neighbouring elements
480 
481  // Find common elements
482  std::set<unsigned> shared_elements;
483  std::set_intersection(elems_containing_node_A.begin(),
484  elems_containing_node_A.end(),
485  elems_containing_node_B.begin(),
486  elems_containing_node_B.end(),
487  std::inserter(shared_elements, shared_elements.begin()));
488 
489  // Iterate over common elements
490  unsigned node_A_index = p_node_A->GetIndex();
491  unsigned node_B_index = p_node_B->GetIndex();
492  for (std::set<unsigned>::iterator iter = shared_elements.begin();
493  iter != shared_elements.end();
494  ++iter)
495  {
496  VertexElement<ELEMENT_DIM, SPACE_DIM>* p_element = this->GetElement(*iter);
497 
498  // Find which node has the lower local index in this element
499  unsigned local_indexA = p_element->GetNodeLocalIndex(node_A_index);
500  unsigned local_indexB = p_element->GetNodeLocalIndex(node_B_index);
501 
502  unsigned index = local_indexB;
503 
504  // If node B has a higher index then use node A's index...
505  if (local_indexB > local_indexA)
506  {
507  index = local_indexA;
508 
509  // ...unless nodes A and B share the element's last edge
510  if ((local_indexA == 0) && (local_indexB == p_element->GetNumNodes()-1))
511  {
512  index = local_indexB;
513  }
514  }
515  else if ((local_indexB == 0) && (local_indexA == p_element->GetNumNodes()-1))
516  {
517  // ...otherwise use node B's index, unless nodes A and B share the element's last edge
518  index = local_indexA;
519  }
520 
521  // Add new node to this element
522  this->GetElement(*iter)->AddNode(this->GetNode(new_node_global_index), index);
523  }
524 
525  // Store index of new node
526  division_node_global_indices.push_back(new_node_global_index);
527  }
528 
529  // Now call DivideElement() to divide the element using the new nodes
530  unsigned new_element_index = DivideElement(pElement,
531  pElement->GetNodeLocalIndex(division_node_global_indices[0]),
532  pElement->GetNodeLocalIndex(division_node_global_indices[1]),
533  placeOriginalElementBelow);
534 
535  return new_element_index;
536 }
537 
538 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
540  bool placeOriginalElementBelow)
541 {
542  assert(SPACE_DIM == 2);
543  assert(ELEMENT_DIM == SPACE_DIM);
544 
545  c_vector<double, SPACE_DIM> short_axis = this->GetShortAxisOfElement(pElement->GetIndex());
546 
547  unsigned new_element_index = DivideElementAlongGivenAxis(pElement, short_axis, placeOriginalElementBelow);
548  return new_element_index;
549 }
550 
551 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
553  unsigned nodeAIndex,
554  unsigned nodeBIndex,
555  bool placeOriginalElementBelow)
556 {
557  assert(SPACE_DIM == 2);
558  assert(ELEMENT_DIM == SPACE_DIM);
559 
560  // Sort nodeA and nodeB such that nodeBIndex > nodeAindex
561  assert(nodeBIndex != nodeAIndex);
562  unsigned node1_index = (nodeAIndex < nodeBIndex) ? nodeAIndex : nodeBIndex; // low index
563  unsigned node2_index = (nodeAIndex < nodeBIndex) ? nodeBIndex : nodeAIndex; // high index
564 
565  // Store the number of nodes in the element (this changes when nodes are deleted from the element)
566  unsigned num_nodes = pElement->GetNumNodes();
567 
568  // Copy the nodes in this element
569  std::vector<Node<SPACE_DIM>*> nodes_elem;
570  for (unsigned i=0; i<num_nodes; i++)
571  {
572  nodes_elem.push_back(pElement->GetNode(i));
573  }
574 
575  // Get the index of the new element
576  unsigned new_element_index;
577  if (mDeletedElementIndices.empty())
578  {
579  new_element_index = this->mElements.size();
580  }
581  else
582  {
583  new_element_index = mDeletedElementIndices.back();
584  mDeletedElementIndices.pop_back();
585  delete this->mElements[new_element_index];
586  }
587 
588  // Add the new element to the mesh
589  AddElement(new VertexElement<ELEMENT_DIM,SPACE_DIM>(new_element_index, nodes_elem));
590 
597  // Find lowest element
599  double height_midpoint_1 = 0.0;
600  double height_midpoint_2 = 0.0;
601  unsigned counter_1 = 0;
602  unsigned counter_2 = 0;
603 
604  for (unsigned i=0; i<num_nodes; i++)
605  {
606  if (i>=node1_index && i<=node2_index)
607  {
608  height_midpoint_1 += pElement->GetNode(i)->rGetLocation()[1];
609  counter_1++;
610  }
611  if (i<=node1_index || i>=node2_index)
612  {
613  height_midpoint_2 += pElement->GetNode(i)->rGetLocation()[1];
614  counter_2++;
615  }
616  }
617  height_midpoint_1 /= (double)counter_1;
618  height_midpoint_2 /= (double)counter_2;
619 
620  for (unsigned i=num_nodes; i>0; i--)
621  {
622  if (i-1 < node1_index || i-1 > node2_index)
623  {
624  if (height_midpoint_1 < height_midpoint_2)
625  {
626  if (placeOriginalElementBelow)
627  {
628  pElement->DeleteNode(i-1);
629  }
630  else
631  {
632  this->mElements[new_element_index]->DeleteNode(i-1);
633  }
634  }
635  else
636  {
637  if (placeOriginalElementBelow)
638  {
639  this->mElements[new_element_index]->DeleteNode(i-1);
640  }
641  else
642  {
643  pElement->DeleteNode(i-1);
644  }
645  }
646  }
647  else if (i-1 > node1_index && i-1 < node2_index)
648  {
649  if (height_midpoint_1 < height_midpoint_2)
650  {
651  if (placeOriginalElementBelow)
652  {
653  this->mElements[new_element_index]->DeleteNode(i-1);
654  }
655  else
656  {
657  pElement->DeleteNode(i-1);
658  }
659  }
660  else
661  {
662  if (placeOriginalElementBelow)
663  {
664  pElement->DeleteNode(i-1);
665  }
666  else
667  {
668  this->mElements[new_element_index]->DeleteNode(i-1);
669  }
670  }
671  }
672  }
673 
674  return new_element_index;
675 }
676 
677 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
679 {
680  assert(SPACE_DIM == 2);
681 
682  // Mark any nodes that are contained only in this element as deleted
683  for (unsigned i=0; i<this->mElements[index]->GetNumNodes(); i++)
684  {
685  Node<SPACE_DIM>* p_node = this->mElements[index]->GetNode(i);
686 
687  if (p_node->rGetContainingElementIndices().size() == 1)
688  {
689  DeleteNodePriorToReMesh(p_node->GetIndex());
690  }
691 
692  // Mark all the nodes contained in the removed element as boundary nodes
693  p_node->SetAsBoundaryNode(true);
694  }
695 
696  // Mark this element as deleted
697  this->mElements[index]->MarkAsDeleted();
698  mDeletedElementIndices.push_back(index);
699 }
700 
701 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
703 {
704  this->mNodes[index]->MarkAsDeleted();
705  mDeletedNodeIndices.push_back(index);
706 }
707 
708 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
710 {
711  // Find the indices of the elements owned by each node
712  std::set<unsigned> elements_containing_nodeA = pNodeA->rGetContainingElementIndices();
713  std::set<unsigned> elements_containing_nodeB = pNodeB->rGetContainingElementIndices();
714 
715  // Find common elements
716  std::set<unsigned> shared_elements;
717  std::set_intersection(elements_containing_nodeA.begin(),
718  elements_containing_nodeA.end(),
719  elements_containing_nodeB.begin(),
720  elements_containing_nodeB.end(),
721  std::inserter(shared_elements, shared_elements.begin()));
722 
723  // Check that the nodes have a common edge and not more than 2
724  assert(!shared_elements.empty());
725  assert(shared_elements.size()<=2u);
726 
727  // Specify if it's a boundary node
728  bool is_boundary_node = false;
729  if (shared_elements.size()==1u)
730  {
731  // If only one shared element then must be on the boundary.
732  assert((pNodeA->IsBoundaryNode()) && (pNodeB->IsBoundaryNode()));
733  is_boundary_node = true;
734  }
735 
736  // Create a new node (position is not important as it will be changed)
737  Node<SPACE_DIM>* p_new_node = new Node<SPACE_DIM>(GetNumNodes(), is_boundary_node, 0.0, 0.0);
738 
739  // Update the node location
740  c_vector<double, SPACE_DIM> new_node_position = pNodeA->rGetLocation() + 0.5*this->GetVectorFromAtoB(pNodeA->rGetLocation(), pNodeB->rGetLocation());
741  ChastePoint<SPACE_DIM> point(new_node_position);
742  p_new_node->SetPoint(new_node_position);
743 
744  // Add node to mesh
745  this->mNodes.push_back(p_new_node);
746 
747  // Iterate over common elements
748  unsigned node_A_index = pNodeA->GetIndex();
749  unsigned node_B_index = pNodeB->GetIndex();
750  for (std::set<unsigned>::iterator iter = shared_elements.begin();
751  iter != shared_elements.end();
752  ++iter)
753  {
754  VertexElement<ELEMENT_DIM, SPACE_DIM>* p_element = this->GetElement(*iter);
755 
756  // Find which node has the lower local index in this element
757  unsigned local_indexA = p_element->GetNodeLocalIndex(node_A_index);
758  unsigned local_indexB = p_element->GetNodeLocalIndex(node_B_index);
759 
760  unsigned index = local_indexB;
761 
762  // If node B has a higher index then use node A's index...
763  if (local_indexB > local_indexA)
764  {
765  index = local_indexA;
766 
767  // ...unless nodes A and B share the element's last edge
768  if ((local_indexA == 0) && (local_indexB == p_element->GetNumNodes()-1))
769  {
770  index = local_indexB;
771  }
772  }
773  else if ((local_indexB == 0) && (local_indexA == p_element->GetNumNodes()-1))
774  {
775  // ...otherwise use node B's index, unless nodes A and B share the element's last edge
776  index = local_indexA;
777  }
778 
779  // Add new node to this element
780  this->GetElement(*iter)->AddNode(p_new_node, index);
781  }
782 }
783 
784 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
786 {
787  // Make sure the map is big enough. Each entry will be set in the loop below.
788  rElementMap.Resize(this->GetNumAllElements());
789 
790  // Remove any elements that have been marked for deletion and store all other elements in a temporary structure
791  std::vector<VertexElement<ELEMENT_DIM, SPACE_DIM>*> live_elements;
792  for (unsigned i=0; i<this->mElements.size(); i++)
793  {
794  if (this->mElements[i]->IsDeleted())
795  {
796  delete this->mElements[i];
797  rElementMap.SetDeleted(i);
798  }
799  else
800  {
801  live_elements.push_back(this->mElements[i]);
802  rElementMap.SetNewIndex(i, (unsigned)(live_elements.size()-1));
803  }
804  }
805 
806  // Sanity check
807  assert(mDeletedElementIndices.size() == this->mElements.size() - live_elements.size());
808 
809  // Repopulate the elements vector and reset the list of deleted element indices
810  mDeletedElementIndices.clear();
811  this->mElements = live_elements;
812 
813  // Finally, reset the element indices to run from zero
814  for (unsigned i=0; i<this->mElements.size(); i++)
815  {
816  this->mElements[i]->ResetIndex(i);
817  }
818 
819  // Remove deleted nodes
820  RemoveDeletedNodes();
821 }
822 
823 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
825 {
826  // Remove any nodes that have been marked for deletion and store all other nodes in a temporary structure
827  std::vector<Node<SPACE_DIM>*> live_nodes;
828  for (unsigned i=0; i<this->mNodes.size(); i++)
829  {
830  if (this->mNodes[i]->IsDeleted())
831  {
832  delete this->mNodes[i];
833  }
834  else
835  {
836  live_nodes.push_back(this->mNodes[i]);
837  }
838  }
839 
840  // Sanity check
841  assert(mDeletedNodeIndices.size() == this->mNodes.size() - live_nodes.size());
842 
843  // Repopulate the nodes vector and reset the list of deleted node indices
844  this->mNodes = live_nodes;
845  mDeletedNodeIndices.clear();
846 
847  // Finally, reset the node indices to run from zero
848  for (unsigned i=0; i<this->mNodes.size(); i++)
849  {
850  this->mNodes[i]->SetIndex(i);
851  }
852 }
853 
854 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
856 {
857  // Make sure that we are in the correct dimension - this code will be eliminated at compile time
858  assert(SPACE_DIM==2 || SPACE_DIM==3);
859  assert(ELEMENT_DIM == SPACE_DIM);
860 
861  if (SPACE_DIM == 2)
862  {
863  // Make sure the map is big enough
864  rElementMap.Resize(this->GetNumAllElements());
865 
866  /*
867  * To begin the remeshing process, we do not need to call Clear() and remove all current data,
868  * since cell birth, rearrangement and death result only in local remeshing of a vertex-based
869  * mesh. Instead, we just remove any deleted elements and nodes.
870  */
871  RemoveDeletedNodesAndElements(rElementMap);
872  bool recheck_mesh = true;
873  while (recheck_mesh == true)
874  {
875  // We check for any short edges and perform swaps if necessary and possible.
876  recheck_mesh = CheckForSwapsFromShortEdges();
877  }
878 
879  // Check for element intersections
880  recheck_mesh = true;
881  while (recheck_mesh == true)
882  {
883  // Check mesh for intersections, and perform T3 swaps where required
884  recheck_mesh = CheckForIntersections();
885  }
886 
887  RemoveDeletedNodes();
888 
889  /*
890  * This is handled in a separate method to allow child classes to implement additional ReMeshing functionality
891  * (see #2664).
892  */
893  this->CheckForRosettes();
894  }
895  else // 3D
896  {
897 #define COVERAGE_IGNORE
898  EXCEPTION("Remeshing has not been implemented in 3D (see #827 and #860)\n");
899 #undef COVERAGE_IGNORE
900  }
902 }
903 
904 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
906 {
907  VertexElementMap map(GetNumElements());
908  ReMesh(map);
909 }
910 
911 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
913 {
914  // Loop over elements to check for T1 swaps
915  for (typename VertexMesh<ELEMENT_DIM, SPACE_DIM>::VertexElementIterator elem_iter = this->GetElementIteratorBegin();
916  elem_iter != this->GetElementIteratorEnd();
917  ++elem_iter)
918  {
920 
921  unsigned num_nodes = elem_iter->GetNumNodes();
922  assert(num_nodes > 0);
923 
924  // Loop over the nodes contained in this element
925  for (unsigned local_index=0; local_index<num_nodes; local_index++)
926  {
927  // Find locations of the current node and anticlockwise node
928  Node<SPACE_DIM>* p_current_node = elem_iter->GetNode(local_index);
929  unsigned local_index_plus_one = (local_index+1)%num_nodes;
930  Node<SPACE_DIM>* p_anticlockwise_node = elem_iter->GetNode(local_index_plus_one);
931 
932  // Find distance between nodes
933  double distance_between_nodes = this->GetDistanceBetweenNodes(p_current_node->GetIndex(), p_anticlockwise_node->GetIndex());
934 
935  // If the nodes are too close together...
936  if (distance_between_nodes < mCellRearrangementThreshold)
937  {
938  // ...then check if any triangular elements are shared by these nodes...
939  std::set<unsigned> elements_of_node_a = p_current_node->rGetContainingElementIndices();
940  std::set<unsigned> elements_of_node_b = p_anticlockwise_node->rGetContainingElementIndices();
941 
942  std::set<unsigned> shared_elements;
943  std::set_intersection(elements_of_node_a.begin(), elements_of_node_a.end(),
944  elements_of_node_b.begin(), elements_of_node_b.end(),
945  std::inserter(shared_elements, shared_elements.begin()));
946 
947  bool both_nodes_share_triangular_element = false;
948  for (std::set<unsigned>::const_iterator it = shared_elements.begin();
949  it != shared_elements.end();
950  ++it)
951  {
952  if (this->GetElement(*it)->GetNumNodes() <= 3)
953  {
954  both_nodes_share_triangular_element = true;
955  break;
956  }
957  }
958 
959  // ...and if none are, then perform the required type of swap and halt the search, returning true
960  if (!both_nodes_share_triangular_element)
961  {
962  IdentifySwapType(p_current_node, p_anticlockwise_node);
963  return true;
964  }
965  }
966  }
967  }
968 
969  return false;
970 }
971 
972 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
974 {
975  // Loop over elements to check for T2 swaps
976  for (typename VertexMesh<ELEMENT_DIM, SPACE_DIM>::VertexElementIterator elem_iter = this->GetElementIteratorBegin();
977  elem_iter != this->GetElementIteratorEnd();
978  ++elem_iter)
979  {
980  // If this element is triangular...
981  if (elem_iter->GetNumNodes() == 3)
982  {
983  // ...and smaller than the threshold area...
984  if (this->GetVolumeOfElement(elem_iter->GetIndex()) < GetT2Threshold())
985  {
986  // ...then perform a T2 swap and break out of the loop
987  PerformT2Swap(*elem_iter);
989  rElementMap.SetDeleted(elem_iter->GetIndex());
990  return true;
991  }
992  }
993  }
994  return false;
995 }
996 
997 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
999 {
1000  // If checking for internal intersections as well as on the boundary, then check that no nodes have overlapped any elements...
1001  if (mCheckForInternalIntersections)
1002  {
1004  for (typename AbstractMesh<ELEMENT_DIM,SPACE_DIM>::NodeIterator node_iter = this->GetNodeIteratorBegin();
1005  node_iter != this->GetNodeIteratorEnd();
1006  ++node_iter)
1007  {
1008  assert(!(node_iter->IsDeleted()));
1009 
1010  for (typename VertexMesh<ELEMENT_DIM, SPACE_DIM>::VertexElementIterator elem_iter = this->GetElementIteratorBegin();
1011  elem_iter != this->GetElementIteratorEnd();
1012  ++elem_iter)
1013  {
1014  unsigned elem_index = elem_iter->GetIndex();
1015 
1016  // Check that the node is not part of this element
1017  if (node_iter->rGetContainingElementIndices().count(elem_index) == 0)
1018  {
1019  if (this->ElementIncludesPoint(node_iter->rGetLocation(), elem_index))
1020  {
1021  PerformIntersectionSwap(&(*node_iter), elem_index);
1022  return true;
1023  }
1024  }
1025  }
1026  }
1027  }
1028  else
1029  {
1030  // ...otherwise, just check that no boundary nodes have overlapped any boundary elements
1031  std::set<unsigned> boundary_element_indices;
1032  for (typename VertexMesh<ELEMENT_DIM, SPACE_DIM>::VertexElementIterator elem_iter = this->GetElementIteratorBegin();
1033  elem_iter != this->GetElementIteratorEnd();
1034  ++elem_iter)
1035  {
1036  if (elem_iter->IsElementOnBoundary())
1037  {
1038  boundary_element_indices.insert(elem_iter->GetIndex());
1039  }
1040  }
1041 
1042  for (typename AbstractMesh<ELEMENT_DIM,SPACE_DIM>::NodeIterator node_iter = this->GetNodeIteratorBegin();
1043  node_iter != this->GetNodeIteratorEnd();
1044  ++node_iter)
1045  {
1046  if (node_iter->IsBoundaryNode())
1047  {
1048  assert(!(node_iter->IsDeleted()));
1049 
1050  for (std::set<unsigned>::iterator elem_iter = boundary_element_indices.begin();
1051  elem_iter != boundary_element_indices.end();
1052  ++elem_iter)
1053  {
1054  // Check that the node is not part of this element
1055  if (node_iter->rGetContainingElementIndices().count(*elem_iter) == 0)
1056  {
1057  if (this->ElementIncludesPoint(node_iter->rGetLocation(), *elem_iter))
1058  {
1059  PerformT3Swap(&(*node_iter), *elem_iter);
1060  return true;
1061  }
1062  }
1063  }
1064  }
1065  }
1066  }
1067 
1068  return false;
1069 }
1070 
1071 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
1073 {
1074  // Find the sets of elements containing nodes A and B
1075  std::set<unsigned> nodeA_elem_indices = pNodeA->rGetContainingElementIndices();
1076  std::set<unsigned> nodeB_elem_indices = pNodeB->rGetContainingElementIndices();
1077 
1078  // Form the set union
1079  std::set<unsigned> all_indices, temp_union_set;
1080  std::set_union(nodeA_elem_indices.begin(), nodeA_elem_indices.end(),
1081  nodeB_elem_indices.begin(), nodeB_elem_indices.end(),
1082  std::inserter(temp_union_set, temp_union_set.begin()));
1083  all_indices.swap(temp_union_set); // temp_set will be deleted, all_indices now contains all the indices of elements
1084  // that touch the potentially swapping nodes
1085 
1086  if ((nodeA_elem_indices.size()>3) || (nodeB_elem_indices.size()>3))
1087  {
1088  /*
1089  * Looks like
1090  *
1091  * \
1092  * \ A B
1093  * ---o---o---
1094  * /
1095  * /
1096  *
1097  */
1098 
1099  /*
1100  * This case is handled in a separate method to allow child classes to implement different
1101  * functionality for high-order-junction remodelling events (see #2664).
1102  */
1103  this->HandleHighOrderJunctions(pNodeA, pNodeB);
1104  }
1105  else // each node is contained in at most three elements
1106  {
1107  switch (all_indices.size())
1108  {
1109  case 1:
1110  {
1111  /*
1112  * Each node is contained in a single element, so the nodes must lie on the boundary
1113  * of the mesh, as shown below. In this case, we merge the nodes and tidy up node
1114  * indices through calls to PerformNodeMerge() and RemoveDeletedNodes().
1115  *
1116  * A B
1117  * ---o---o---
1118  */
1119  assert(pNodeA->IsBoundaryNode());
1120  assert(pNodeB->IsBoundaryNode());
1121 
1122  PerformNodeMerge(pNodeA, pNodeB);
1123  RemoveDeletedNodes();
1124  break;
1125  }
1126  case 2:
1127  {
1128  if (nodeA_elem_indices.size()==2 && nodeB_elem_indices.size()==2)
1129  {
1130  if (pNodeA->IsBoundaryNode() && pNodeB->IsBoundaryNode())
1131  {
1132  /*
1133  * The node configuration is as shown below, with voids on either side. In this case
1134  * we perform a T1 swap, which separates the elements.
1135  *
1136  * \ /
1137  * \ / Node A
1138  * (1) | (2) (element number in brackets)
1139  * / \ Node B
1140  * / \
1141  */
1142  PerformT1Swap(pNodeA, pNodeB,all_indices);
1143  }
1144  else if (pNodeA->IsBoundaryNode() || pNodeB->IsBoundaryNode())
1145  {
1146  /*
1147  * The node configuration is as shown below, with a void on one side. We should not
1148  * be able to reach this case at present, since we allow only for three-way junctions
1149  * or boundaries, so we throw an exception.
1150  *
1151  * \ /
1152  * \ / Node A
1153  * (1) | (2) (element number in brackets)
1154  * x Node B
1155  * |
1156  */
1157  EXCEPTION("There is a non-boundary node contained only in two elements; something has gone wrong.");
1158  }
1159  else
1160  {
1161  /*
1162  * Each node is contained in two elements, so the nodes lie on an internal edge, as shown below.
1163  * We should not be able to reach this case at present, since we allow only for three-way junctions
1164  * or boundaries, so we throw an exception.
1165  *
1166  * A B
1167  * ---o---o---
1168  */
1169  EXCEPTION("There are non-boundary nodes contained only in two elements; something has gone wrong.");
1170  }
1171  }// from [if (nodeA_elem_indices.size()==2 && nodeB_elem_indices.size()==2)]
1172  else
1173  {
1174  /*
1175  * The node configuration looks like that shown below. In this case, we merge the nodes
1176  * and tidy up node indices through calls to PerformNodeMerge() and RemoveDeletedNodes().
1177  *
1178  * Outside
1179  * /
1180  * --o--o (2)
1181  * (1) \
1182  *
1183  * ///\todo this should be a T1 swap (see #1263 and #2401)
1184  * Referring to the todo: this should probably stay a node-merge. If this is a T1 swap then
1185  * the single boundary node will travel from element 1 to element 2, but still remain a single node.
1186  * I.e. we would not reduce the total number of nodes in this situation.
1187  */
1188  PerformNodeMerge(pNodeA, pNodeB);
1189  RemoveDeletedNodes();
1190  }
1191  break;
1192  }
1193  case 3:
1194  {
1195  if (nodeA_elem_indices.size()==1 || nodeB_elem_indices.size()==1)
1196  {
1197  /*
1198  * One node is contained in one element and the other node is contained in three elements.
1199  * We should not be able to reach this case at present, since we allow each boundary node
1200  * to be contained in at most two elements, so we throw an exception.
1201  *
1202  * A B
1203  *
1204  * empty /
1205  * / (3)
1206  * ---o---o----- (element number in brackets)
1207  * (1) \ (2)
1208  * \
1209  */
1210  assert(pNodeA->IsBoundaryNode());
1211  assert(pNodeB->IsBoundaryNode());
1212 
1213  EXCEPTION("There is a boundary node contained in three elements something has gone wrong.");
1214  }
1215  else if (nodeA_elem_indices.size()==2 && nodeB_elem_indices.size()==2)
1216  {
1217  // The short edge must be at the boundary. We need to check whether this edge is
1218  // adjacent to a triangular void before we swap. If it is a triangular void, we perform a T2-type swap.
1219  // If not, then we perform a normal T1 swap. I.e. in detail we need to check whether the
1220  // element in nodeA_elem_indices which is not in nodeB_elem_indices contains a shared node
1221  // with the element in nodeB_elem_indices which is not in nodeA_elem_indices.
1222 
1223  std::set<unsigned> element_A_not_B, temp_set;
1224  std::set_difference(all_indices.begin(), all_indices.end(), nodeB_elem_indices.begin(),
1225  nodeB_elem_indices.end(), std::inserter(temp_set, temp_set.begin()));
1226  element_A_not_B.swap(temp_set);
1227 
1228  // There must be only one such element
1229  assert(element_A_not_B.size() == 1);
1230 
1231  std::set<unsigned> element_B_not_A;
1232  std::set_difference(all_indices.begin(), all_indices.end(), nodeA_elem_indices.begin(),
1233  nodeA_elem_indices.end(), std::inserter(temp_set, temp_set.begin()));
1234  element_B_not_A.swap(temp_set);
1235 
1236  // There must be only one such element
1237  assert(element_B_not_A.size() == 1);
1238 
1239  VertexElement<ELEMENT_DIM, SPACE_DIM>* p_element_A_not_B = this->mElements[*element_A_not_B.begin()];
1240  VertexElement<ELEMENT_DIM, SPACE_DIM>* p_element_B_not_A = this->mElements[*element_B_not_A.begin()];
1241 
1242  unsigned local_index_1 = p_element_A_not_B->GetNodeLocalIndex(pNodeA->GetIndex());
1243  unsigned next_node_1 = p_element_A_not_B->GetNodeGlobalIndex((local_index_1 + 1)%(p_element_A_not_B->GetNumNodes()));
1244  unsigned previous_node_1 = p_element_A_not_B->GetNodeGlobalIndex(
1245  (local_index_1 + p_element_A_not_B->GetNumNodes() - 1)%(p_element_A_not_B->GetNumNodes()));
1246  unsigned local_index_2 = p_element_B_not_A->GetNodeLocalIndex(pNodeB->GetIndex());
1247  unsigned next_node_2 = p_element_B_not_A->GetNodeGlobalIndex(
1248  (local_index_2 + 1)%(p_element_B_not_A->GetNumNodes()));
1249  unsigned previous_node_2 = p_element_B_not_A->GetNodeGlobalIndex(
1250  (local_index_2 + p_element_B_not_A->GetNumNodes() - 1)%(p_element_B_not_A->GetNumNodes()));
1251 
1252  if (next_node_1 == previous_node_2 || next_node_2 == previous_node_1)
1253  {
1254  /*
1255  * The node configuration looks like that shown below, and both nodes must be on the boundary.
1256  * In this case we remove the void through a call to PerformVoidRemoval().
1257  *
1258  * A C B A B
1259  * /\ \ /
1260  * /v \ \ (1) /
1261  * (3)o----o (1) or (2) o----o (3) (element number in brackets, v is a void)
1262  * / (2) \ \v /
1263  * / \ \/
1264  * C
1265  */
1266  assert(pNodeA->IsBoundaryNode());
1267  assert(pNodeB->IsBoundaryNode());
1268 
1269  // Get the third node in the triangular void
1270 
1271  unsigned nodeC_index;
1272  if (next_node_1 == previous_node_2 && next_node_2 != previous_node_1)
1273  {
1274  nodeC_index = next_node_1;
1275  }
1276  else if (next_node_2 == previous_node_1 && next_node_1 != previous_node_2)
1277  {
1278  nodeC_index = next_node_2;
1279  }
1280  else
1281  {
1282  assert(next_node_1 == previous_node_2 && next_node_2 == previous_node_1);
1290  EXCEPTION("Triangular element next to triangular void, not implemented yet.");
1291  }
1292 
1293  if(p_element_A_not_B->GetNumNodes() == 3u || p_element_B_not_A->GetNumNodes() == 3u)
1294  {
1302  EXCEPTION("Triangular element next to triangular void, not implemented yet.");
1303  }
1304 
1305  PerformVoidRemoval(pNodeA, pNodeB, this->mNodes[nodeC_index]);
1306  }
1307  else
1308  {
1309  /*
1310  * The node configuration looks like that below, and both nodes must lie on the boundary.
1311  * In this case we perform a T1 swap.
1312  *
1313  * A B A B
1314  * \ empty/ \ /
1315  * \ / \(1) /
1316  * (3) o--o (1) or (2) o--o (3) (element number in brackets)
1317  * / (2)\ / \
1318  * / \ /empty \
1319  */
1320  assert(pNodeA->IsBoundaryNode());
1321  assert(pNodeB->IsBoundaryNode());
1322 
1323  PerformT1Swap(pNodeA, pNodeB, all_indices);
1324  }
1325  } // from else if (nodeA_elem_indices.size()==2 && nodeB_elem_indices.size()==2)
1326  else
1327  {
1328  // In this case, one node must be contained in two elements and the other in three elements.
1329  assert ( (nodeA_elem_indices.size()==2 && nodeB_elem_indices.size()==3)
1330  || (nodeA_elem_indices.size()==3 && nodeB_elem_indices.size()==2) );
1331 
1332  // They can't both be boundary nodes
1333  assert(!(pNodeA->IsBoundaryNode() && pNodeB->IsBoundaryNode()));
1334 
1335  if (pNodeA->IsBoundaryNode() || pNodeB->IsBoundaryNode())
1336  {
1337  /*
1338  * The node configuration looks like that shown below. We perform a T1 swap in this case.
1339  *
1340  * A B A B
1341  * \ / \ /
1342  * \ (1)/ \(1) /
1343  * (3) o--o (empty) or (empty) o--o (3) (element number in brackets)
1344  * / (2)\ /(2) \
1345  * / \ / \
1346  */
1347  PerformT1Swap(pNodeA, pNodeB, all_indices);
1348  }
1349  else
1350  {
1351  /*
1352  * The node configuration looks like that shown below. We should not be able to reach this case
1353  * at present, since we allow only for three-way junctions or boundaries, so we throw an exception.
1354  *
1355  * A B A B
1356  * \ /
1357  * \ (1) (1) /
1358  * (3) o--o--- or ---o--o (3) (element number in brackets)
1359  * / (2) (2) \
1360  * / \
1361  */
1362  EXCEPTION("There are non-boundary nodes contained only in two elements; something has gone wrong.");
1363  }
1364  }
1365  break;
1366  }
1367  case 4:
1368  {
1369  /*
1370  * The node configuration looks like that shown below. We perform a T1 swap in this case.
1371  *
1372  * \(1)/
1373  * \ / Node A
1374  * (2) | (4) (element number in brackets)
1375  * / \ Node B
1376  * /(3)\
1377  */
1378 
1379  /*
1380  * This case is handled in a separate method to allow child classes to implement different
1381  * functionality for junction remodelling events (see #2664).
1382  */
1383  if (mProtorosetteFormationProbability > RandomNumberGenerator::Instance()->ranf())
1384  {
1385  this->PerformNodeMerge(pNodeA, pNodeB);
1386  this->RemoveDeletedNodes();
1387  }
1388  else
1389  {
1390  this->PerformT1Swap(pNodeA, pNodeB, all_indices);
1391  }
1392  break;
1393  }
1394  default:
1395  // This can't happen
1396  NEVER_REACHED;
1397  }
1398  }
1399 }
1400 
1401 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
1403 {
1404  // Find the sets of elements containing each of the nodes, sorted by index
1405  std::set<unsigned> nodeA_elem_indices = pNodeA->rGetContainingElementIndices();
1406  std::set<unsigned> nodeB_elem_indices = pNodeB->rGetContainingElementIndices();
1407 
1408  // Move node A to the mid-point
1409  pNodeA->rGetModifiableLocation() += 0.5 * this->GetVectorFromAtoB(pNodeA->rGetLocation(), pNodeB->rGetLocation());
1410 
1411  // Update the elements previously containing node B to contain node A
1412  unsigned node_B_index = pNodeB->GetIndex();
1413  for (std::set<unsigned>::const_iterator it = nodeB_elem_indices.begin(); it != nodeB_elem_indices.end(); ++it)
1414  {
1415  // Find the local index of node B in this element
1416  unsigned node_B_local_index = this->mElements[*it]->GetNodeLocalIndex(node_B_index);
1417  assert(node_B_local_index < UINT_MAX); // this element contains node B
1418 
1419  /*
1420  * If this element already contains node A, then just remove node B.
1421  * Otherwise replace it with node A in the element and remove it from mNodes.
1422  */
1423  if (nodeA_elem_indices.count(*it) != 0)
1424  {
1425  this->mElements[*it]->DeleteNode(node_B_local_index);
1426  }
1427  else
1428  {
1429  // Replace node B with node A in this element
1430  this->mElements[*it]->UpdateNode(node_B_local_index, pNodeA);
1431  }
1432  }
1433 
1434  assert(!(this->mNodes[node_B_index]->IsDeleted()));
1435  this->mNodes[node_B_index]->MarkAsDeleted();
1436  mDeletedNodeIndices.push_back(node_B_index);
1437 }
1438 
1439 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
1441  Node<SPACE_DIM>* pNodeB,
1442  std::set<unsigned>& rElementsContainingNodes)
1443 {
1444  // First compute and store the location of the T1 swap, which is at the midpoint of nodes A and B
1445  double distance_between_nodes_CD = mCellRearrangementRatio*mCellRearrangementThreshold;
1446 
1447  c_vector<double, SPACE_DIM> nodeA_location = pNodeA->rGetLocation();
1448  c_vector<double, SPACE_DIM> nodeB_location = pNodeB->rGetLocation();
1449  c_vector<double, SPACE_DIM> vector_AB = this->GetVectorFromAtoB(nodeA_location, nodeB_location);
1450  mLocationsOfT1Swaps.push_back(nodeA_location + 0.5*vector_AB);
1451 
1452  double distance_AB = norm_2(vector_AB);
1453  if (distance_AB < 1e-10)
1454  {
1455  EXCEPTION("Nodes are too close together, this shouldn't happen");
1456  }
1457 
1458  /*
1459  * Compute the locations of two new nodes C, D, placed on either side of the
1460  * edge E_old formed by nodes A and B, such that the edge E_new formed by the
1461  * new nodes is the perpendicular bisector of E_old, with |E_new| 'just larger'
1462  * (mCellRearrangementRatio) than mThresholdDistance.
1463  *
1464  * We implement the following changes to the mesh:
1465  *
1466  * The element whose index was in nodeA_elem_indices but not nodeB_elem_indices,
1467  * and the element whose index was in nodeB_elem_indices but not nodeA_elem_indices,
1468  * should now both contain nodes A and B.
1469  *
1470  * The element whose index was in nodeA_elem_indices and nodeB_elem_indices, and which
1471  * node C lies inside, should now only contain node A.
1472  *
1473  * The element whose index was in nodeA_elem_indices and nodeB_elem_indices, and which
1474  * node D lies inside, should now only contain node B.
1475  *
1476  * Iterate over all elements involved and identify which element they are
1477  * in the diagram then update the nodes as necessary.
1478  *
1479  * \(1)/
1480  * \ / Node A
1481  * (2) | (4) elements in brackets
1482  * / \ Node B
1483  * /(3)\
1484  */
1485 
1486  // Move nodes A and B to C and D respectively
1487  c_vector<double, SPACE_DIM> vector_CD;
1488  vector_CD(0) = -vector_AB(1) * distance_between_nodes_CD / distance_AB;
1489  vector_CD(1) = vector_AB(0) * distance_between_nodes_CD / distance_AB;
1490 
1491  c_vector<double, SPACE_DIM> nodeC_location = nodeA_location + 0.5*vector_AB - 0.5*vector_CD;
1492  c_vector<double, SPACE_DIM> nodeD_location = nodeC_location + vector_CD;
1493 
1494  pNodeA->rGetModifiableLocation() = nodeC_location;
1495  pNodeB->rGetModifiableLocation() = nodeD_location;
1496 
1497  // Find the sets of elements containing nodes A and B
1498  std::set<unsigned> nodeA_elem_indices = pNodeA->rGetContainingElementIndices();
1499  std::set<unsigned> nodeB_elem_indices = pNodeB->rGetContainingElementIndices();
1500 
1501  for (std::set<unsigned>::const_iterator it = rElementsContainingNodes.begin();
1502  it != rElementsContainingNodes.end();
1503  ++it)
1504  {
1505  // If, as in element 3 above, this element does not contain node A (now C)...
1506  if (nodeA_elem_indices.find(*it) == nodeA_elem_indices.end())
1507  {
1508  // ...then add it to the element just after node B (now D), going anticlockwise
1509  unsigned nodeB_local_index = this->mElements[*it]->GetNodeLocalIndex(pNodeB->GetIndex());
1510  assert(nodeB_local_index < UINT_MAX);
1511 
1512  this->mElements[*it]->AddNode(pNodeA, nodeB_local_index);
1513  }
1514  else if (nodeB_elem_indices.find(*it) == nodeB_elem_indices.end())
1515  {
1516  // Do similarly if the element does not contain node B (now D), as in element 4 above
1517  unsigned nodeA_local_index = this->mElements[*it]->GetNodeLocalIndex(pNodeA->GetIndex());
1518  assert(nodeA_local_index < UINT_MAX);
1519 
1520  this->mElements[*it]->AddNode(pNodeB, nodeA_local_index);
1521  }
1522  else
1523  {
1524  // If the element contains both nodes A and B (now C and D respectively)...
1525  unsigned nodeA_local_index = this->mElements[*it]->GetNodeLocalIndex(pNodeA->GetIndex());
1526  unsigned nodeB_local_index = this->mElements[*it]->GetNodeLocalIndex(pNodeB->GetIndex());
1527 
1528  assert(nodeA_local_index < UINT_MAX);
1529  assert(nodeB_local_index < UINT_MAX);
1530 
1531  /*
1532  * Locate local index of nodeA and nodeB and use the ordering to
1533  * identify the element, if nodeB_index > nodeA_index then element 4
1534  * and if nodeA_index > nodeB_index then element 2
1535  */
1536  unsigned nodeB_local_index_plus_one = (nodeB_local_index + 1)%(this->mElements[*it]->GetNumNodes());
1537 
1538  if (nodeA_local_index == nodeB_local_index_plus_one)
1539  {
1540  /*
1541  * In this case the local index of nodeA is the local index of
1542  * nodeB plus one so we are in element 2 so we remove nodeB
1543  */
1544  this->mElements[*it]->DeleteNode(nodeB_local_index);
1545  }
1546  else
1547  {
1548  assert(nodeB_local_index == (nodeA_local_index + 1)%(this->mElements[*it]->GetNumNodes())); // as A and B are next to each other
1549  /*
1550  * In this case the local index of nodeA is the local index of
1551  * nodeB minus one so we are in element 4 so we remove nodeA
1552  */
1553  this->mElements[*it]->DeleteNode(nodeA_local_index);
1554  }
1555  }
1556  }
1557 
1558  // Sort out boundary nodes
1559  if (pNodeA->IsBoundaryNode() || pNodeB->IsBoundaryNode())
1560  {
1561  if (pNodeA->GetNumContainingElements() == 3)
1562  {
1563  pNodeA->SetAsBoundaryNode(false);
1564  }
1565  else
1566  {
1567  pNodeA->SetAsBoundaryNode(true);
1568  }
1569  if (pNodeB->GetNumContainingElements() == 3)
1570  {
1571  pNodeB->SetAsBoundaryNode(false);
1572  }
1573  else
1574  {
1575  pNodeB->SetAsBoundaryNode(true);
1576  }
1577  }
1578 }
1579 
1580 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
1582 {
1583  assert(SPACE_DIM == 2);
1584  assert(ELEMENT_DIM == SPACE_DIM);
1585 
1586  VertexElement<ELEMENT_DIM, SPACE_DIM>* p_element = this->GetElement(elementIndex);
1587  unsigned num_nodes = p_element->GetNumNodes();
1588 
1589  std::set<unsigned> elements_containing_intersecting_node;
1590 
1591  for (unsigned node_local_index=0; node_local_index<num_nodes; node_local_index++)
1592  {
1593  unsigned node_global_index = p_element->GetNodeGlobalIndex(node_local_index);
1594 
1595  std::set<unsigned> node_elem_indices = this->GetNode(node_global_index)->rGetContainingElementIndices();
1596 
1597  for (std::set<unsigned>::const_iterator elem_iter = node_elem_indices.begin();
1598  elem_iter != node_elem_indices.end();
1599  ++elem_iter)
1600  {
1601  VertexElement<ELEMENT_DIM, SPACE_DIM>* p_neighbouring_element = this->GetElement(*elem_iter);
1602  unsigned num_nodes_in_neighbouring_element = p_neighbouring_element->GetNumNodes();
1603 
1604  // Check if element contains the intersecting node
1605  for (unsigned node_index_2 = 0; node_index_2 < num_nodes_in_neighbouring_element; node_index_2++)
1606  {
1607  if (p_neighbouring_element->GetNodeGlobalIndex(node_index_2) == pNode->GetIndex())
1608  {
1609  elements_containing_intersecting_node.insert(p_neighbouring_element->GetIndex());
1610  }
1611  }
1612  }
1613  }
1614  /*
1615  * If there are not two elements containing the intersecting node then the node is coming from the other side of the element
1616  * and there is no way to fix it unless you want to make two new elements.
1617  */
1618  assert(elements_containing_intersecting_node.size() == 2);
1619 
1620  std::set<unsigned> all_elements_containing_intersecting_node = pNode->rGetContainingElementIndices();
1621 
1622  std::set<unsigned> intersecting_element;
1623 
1624  std::set_difference(all_elements_containing_intersecting_node.begin(), all_elements_containing_intersecting_node.end(),
1625  elements_containing_intersecting_node.begin(), elements_containing_intersecting_node.end(),
1626  std::inserter(intersecting_element, intersecting_element.begin()));
1627 
1628  /*
1629  * Identify nodes and elements to perform switch on
1630  * Intersecting node is node A
1631  * Other node is node B
1632  *
1633  * Element 1 only contains node A
1634  * Element 2 has nodes B and A (in that order)
1635  * Element 3 only contains node B
1636  * Element 4 has nodes A and B (in that order)
1637  */
1638  unsigned node_A_index = pNode->GetIndex();
1639  unsigned node_B_index;
1640  unsigned element_1_index = *(intersecting_element.begin());
1641  unsigned element_2_index;
1642  unsigned element_3_index = elementIndex;
1643  unsigned element_4_index;
1644 
1645  std::set<unsigned>::iterator iter = elements_containing_intersecting_node.begin();
1646  unsigned element_a_index = *(iter);
1647  iter++;
1648  unsigned element_b_index = *(iter);
1649 
1650  VertexElement<ELEMENT_DIM, SPACE_DIM>* p_element_a = this->GetElement(element_a_index);
1651  VertexElement<ELEMENT_DIM, SPACE_DIM>* p_element_b = this->GetElement(element_b_index);
1652 
1653  std::set<unsigned> element_a_nodes;
1654  for (unsigned node_index = 0; node_index < p_element_a->GetNumNodes(); node_index++)
1655  {
1656  element_a_nodes.insert(p_element_a->GetNodeGlobalIndex(node_index));
1657  }
1658 
1659  std::set<unsigned> element_b_nodes;
1660  for (unsigned node_index = 0; node_index < p_element_b->GetNumNodes(); node_index++)
1661  {
1662  element_b_nodes.insert(p_element_b->GetNodeGlobalIndex(node_index));
1663  }
1664 
1665  std::set<unsigned> switching_nodes;
1666  std::set_intersection(element_a_nodes.begin(), element_a_nodes.end(),
1667  element_b_nodes.begin(), element_b_nodes.end(),
1668  std::inserter(switching_nodes, switching_nodes.begin()));
1669 
1670  assert(switching_nodes.size() == 2);
1671 
1672  // Check intersecting node is this set
1673  assert(switching_nodes.find(node_A_index) != switching_nodes.end());
1674  switching_nodes.erase(node_A_index);
1675 
1676  assert(switching_nodes.size() == 1);
1677 
1678  node_B_index = *(switching_nodes.begin());
1679 
1680  // Now identify elements 2 and 4
1681  unsigned node_A_local_index_in_a = p_element_a->GetNodeLocalIndex(node_A_index);
1682  unsigned node_B_local_index_in_a = p_element_a->GetNodeLocalIndex(node_B_index);
1683 
1684  if ((node_B_local_index_in_a+1)%p_element_a->GetNumNodes() == node_A_local_index_in_a)
1685  {
1686  assert((p_element_b->GetNodeLocalIndex(node_A_index)+1)%p_element_b->GetNumNodes()
1687  == p_element_b->GetNodeLocalIndex(node_B_index));
1688 
1689  // Element 2 is element a, element 4 is element b
1690  element_2_index = element_a_index;
1691  element_4_index = element_b_index;
1692  }
1693  else
1694  {
1695  assert((p_element_b->GetNodeLocalIndex(node_B_index)+1)%p_element_b->GetNumNodes()
1696  == p_element_b->GetNodeLocalIndex(node_A_index));
1697 
1698  // Element 2 is element b, element 4 is element a
1699  element_2_index = element_b_index;
1700  element_4_index = element_a_index;
1701  }
1702 
1703  unsigned intersected_edge = this->GetLocalIndexForElementEdgeClosestToPoint(pNode->rGetLocation(), elementIndex);
1704 
1705  unsigned node_A_local_index_in_1 = this->GetElement(element_1_index)->GetNodeLocalIndex(node_A_index);
1706 
1707  unsigned node_A_local_index_in_2 = this->GetElement(element_2_index)->GetNodeLocalIndex(node_A_index);
1708  unsigned node_B_local_index_in_2 = this->GetElement(element_2_index)->GetNodeLocalIndex(node_B_index);
1709 
1710  unsigned node_B_local_index_in_3 = this->GetElement(elementIndex)->GetNodeLocalIndex(node_B_index);
1711 
1712  unsigned node_A_local_index_in_4 = this->GetElement(element_4_index)->GetNodeLocalIndex(node_A_index);
1713  unsigned node_B_local_index_in_4 = this->GetElement(element_4_index)->GetNodeLocalIndex(node_B_index);
1714 
1715  if (intersected_edge==node_B_local_index_in_3)
1716  {
1717  /*
1718  * Add node B to element 1 after node A
1719  * Add node A to element 3 after node B
1720  *
1721  * Remove node B from element 2
1722  * Remove node A from element 4
1723  */
1724  this->mElements[element_1_index]->AddNode(this->mNodes[node_B_index], node_A_local_index_in_1);
1725  this->mElements[element_3_index]->AddNode(this->mNodes[node_A_index], node_B_local_index_in_3);
1726 
1727  this->mElements[element_2_index]->DeleteNode(node_B_local_index_in_2);
1728  this->mElements[element_4_index]->DeleteNode(node_A_local_index_in_4);
1729  }
1730  else
1731  {
1732  assert((intersected_edge+1)%num_nodes==node_B_local_index_in_3);
1733 
1734  // Add node B to element 1 before node A and add node A to element 3 before node B
1735  unsigned node_before_A_in_1 = (node_A_local_index_in_1 - 1)%this->GetElement(element_1_index)->GetNumNodes();
1736  unsigned node_before_B_in_3 = (node_B_local_index_in_3 - 1)%this->GetElement(element_3_index)->GetNumNodes();
1737  this->mElements[element_1_index]->AddNode(this->mNodes[node_B_index], node_before_A_in_1);
1738  this->mElements[element_3_index]->AddNode(this->mNodes[node_A_index], node_before_B_in_3);
1739 
1740  // Remove node A from element 2 and remove node B from element 4
1741  this->mElements[element_2_index]->DeleteNode(node_A_local_index_in_2);
1742  this->mElements[element_4_index]->DeleteNode(node_B_local_index_in_4);
1743  }
1744 }
1745 
1746 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
1748 {
1749  // The given element must be triangular for us to be able to perform a T2 swap on it
1750  assert(rElement.GetNumNodes() == 3);
1751 
1752  // Note that we define this vector before setting it, as otherwise the profiling build will break (see #2367)
1753  c_vector<double, SPACE_DIM> new_node_location;
1754  new_node_location = this->GetCentroidOfElement(rElement.GetIndex());
1755  mLastT2SwapLocation = new_node_location;
1756 
1757  // Create a new node at the element's centroid; this will be a boundary node if any existing nodes were on the boundary
1758  bool is_node_on_boundary = false;
1759  for (unsigned i=0; i<3; i++)
1760  {
1761  if (rElement.GetNode(i)->IsBoundaryNode())
1762  {
1763  is_node_on_boundary = true;
1764  break;
1765  }
1766  }
1767  unsigned new_node_global_index = this->AddNode(new Node<SPACE_DIM>(GetNumNodes(), new_node_location, is_node_on_boundary));
1768  Node<SPACE_DIM>* p_new_node = this->GetNode(new_node_global_index);
1769 
1770  // Loop over each of the three nodes contained in rElement
1771  for (unsigned i=0; i<3; i++)
1772  {
1773  // For each node, find the set of other elements containing it
1774  Node<SPACE_DIM>* p_node = rElement.GetNode(i);
1775  std::set<unsigned> containing_elements = p_node->rGetContainingElementIndices();
1776  containing_elements.erase(rElement.GetIndex());
1777 
1778  // For each of these elements...
1779  for (std::set<unsigned>::iterator elem_iter = containing_elements.begin(); elem_iter != containing_elements.end(); ++elem_iter)
1780  {
1781  VertexElement<ELEMENT_DIM,SPACE_DIM>* p_this_elem = this->GetElement(*elem_iter);
1782 
1783  // ...throw an exception if the element is triangular...
1784  if (p_this_elem->GetNumNodes() < 4)
1785  {
1786  EXCEPTION("One of the neighbours of a small triangular element is also a triangle - dealing with this has not been implemented yet");
1787  }
1788 
1789  // ...otherwise, replace p_node with p_new_node unless this has already happened (in which case, delete p_node from the element)
1790  if (p_this_elem->GetNodeLocalIndex(new_node_global_index) == UINT_MAX)
1791  {
1792  p_this_elem->ReplaceNode(p_node, p_new_node);
1793  }
1794  else
1795  {
1796  p_this_elem->DeleteNode(p_this_elem->GetNodeLocalIndex(p_node->GetIndex()));
1797  }
1798  }
1799  }
1800 
1801  // We also have to mark pElement, pElement->GetNode(0), pElement->GetNode(1), and pElement->GetNode(2) as deleted
1802  mDeletedNodeIndices.push_back(rElement.GetNodeGlobalIndex(0));
1803  mDeletedNodeIndices.push_back(rElement.GetNodeGlobalIndex(1));
1804  mDeletedNodeIndices.push_back(rElement.GetNodeGlobalIndex(2));
1805 
1806  rElement.GetNode(0)->MarkAsDeleted();
1807  rElement.GetNode(1)->MarkAsDeleted();
1808  rElement.GetNode(2)->MarkAsDeleted();
1809 
1810  mDeletedElementIndices.push_back(rElement.GetIndex());
1811  rElement.MarkAsDeleted();
1812 }
1813 
1814 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
1816 {
1817  assert(SPACE_DIM == 2);
1818  assert(ELEMENT_DIM == SPACE_DIM);
1819  assert(pNode->IsBoundaryNode());
1820 
1821  // Store the index of the elements containing the intersecting node
1822  std::set<unsigned> elements_containing_intersecting_node = pNode->rGetContainingElementIndices();
1823 
1824  // Get the local index of the node in the intersected element after which the new node is to be added
1825  unsigned node_A_local_index = this->GetLocalIndexForElementEdgeClosestToPoint(pNode->rGetLocation(), elementIndex);
1826 
1827  // Note that we define this vector before setting it as otherwise the profiling build will break (see #2367)
1828  c_vector<double, SPACE_DIM> node_location;
1829  node_location = pNode->rGetModifiableLocation();
1830 
1831  // Get element
1832  VertexElement<ELEMENT_DIM, SPACE_DIM>* p_element = this->GetElement(elementIndex);
1833  unsigned num_nodes = p_element->GetNumNodes();
1834 
1835  // Get the nodes at either end of the edge to be divided
1836  unsigned vertexA_index = p_element->GetNodeGlobalIndex(node_A_local_index);
1837  unsigned vertexB_index = p_element->GetNodeGlobalIndex((node_A_local_index+1)%num_nodes);
1838 
1839  // Check these nodes are also boundary nodes if this fails then the elements have become concave and you need a smaller timestep
1840  if (!this->mNodes[vertexA_index]->IsBoundaryNode() || !this->mNodes[vertexB_index]->IsBoundaryNode())
1841  {
1842  EXCEPTION("A boundary node has intersected a non-boundary edge; this is because the boundary element has become concave. You need to rerun the simulation with a smaller time step to prevent this.");
1843  }
1844 
1845  // Get the nodes at either end of the edge to be divided and calculate intersection
1846  c_vector<double, SPACE_DIM> vertexA = p_element->GetNodeLocation(node_A_local_index);
1847  c_vector<double, SPACE_DIM> vertexB = p_element->GetNodeLocation((node_A_local_index+1)%num_nodes);
1848  c_vector<double, SPACE_DIM> vector_a_to_point = this->GetVectorFromAtoB(vertexA, node_location);
1849 
1850  c_vector<double, SPACE_DIM> vector_a_to_b = this->GetVectorFromAtoB(vertexA, vertexB);
1851 
1852  c_vector<double, SPACE_DIM> edge_ab_unit_vector = vector_a_to_b/norm_2(vector_a_to_b);
1853  c_vector<double, SPACE_DIM> intersection = vertexA + edge_ab_unit_vector*inner_prod(vector_a_to_point, edge_ab_unit_vector);
1854 
1855  // Store the location of the T3 swap, the location of the intersection with the edge
1857  // is called (see #2401) - we should correct this in these cases!
1858 
1859  mLocationsOfT3Swaps.push_back(intersection);
1860 
1861  if (pNode->GetNumContainingElements() == 1)
1862  {
1863  // Get the index of the element containing the intersecting node
1864  unsigned intersecting_element_index = *elements_containing_intersecting_node.begin();
1865 
1866  // Get element
1867  VertexElement<ELEMENT_DIM, SPACE_DIM>* p_intersecting_element = this->GetElement(intersecting_element_index);
1868 
1869  unsigned local_index = p_intersecting_element->GetNodeLocalIndex(pNode->GetIndex());
1870  unsigned next_node = p_intersecting_element->GetNodeGlobalIndex((local_index + 1)%(p_intersecting_element->GetNumNodes()));
1871  unsigned previous_node = p_intersecting_element->GetNodeGlobalIndex((local_index + p_intersecting_element->GetNumNodes() - 1)%(p_intersecting_element->GetNumNodes()));
1872 
1873  // Check to see if the nodes adjacent to the intersecting node are contained in the intersected element between vertices A and B
1874  if (next_node == vertexA_index || previous_node == vertexA_index || next_node == vertexB_index || previous_node == vertexB_index)
1875  {
1876  unsigned common_vertex_index;
1877 
1878  if (next_node == vertexA_index || previous_node == vertexA_index)
1879  {
1880  common_vertex_index = vertexA_index;
1881  }
1882  else
1883  {
1884  common_vertex_index = vertexB_index;
1885  }
1886 
1887  assert(this->mNodes[common_vertex_index]->GetNumContainingElements()>1);
1888 
1889  std::set<unsigned> elements_containing_common_vertex = this->mNodes[common_vertex_index]->rGetContainingElementIndices();
1890  std::set<unsigned>::const_iterator it = elements_containing_common_vertex.begin();
1891  VertexElement<ELEMENT_DIM, SPACE_DIM>* p_element_common_1 = this->GetElement(*it);
1892  it++;
1893  VertexElement<ELEMENT_DIM, SPACE_DIM>* p_element_common_2 = this->GetElement(*it);
1894 
1895  // Find the number and indices of common vertices between element_1 and element_2
1896  unsigned num_common_vertices = 0;
1897  std::vector<unsigned> common_vertex_indices;
1898  for (unsigned i=0; i<p_element_common_1->GetNumNodes(); i++)
1899  {
1900  for (unsigned j=0; j<p_element_common_2->GetNumNodes(); j++)
1901  {
1902  if (p_element_common_1->GetNodeGlobalIndex(i)==p_element_common_2->GetNodeGlobalIndex(j))
1903  {
1904  num_common_vertices++;
1905  common_vertex_indices.push_back(p_element_common_1->GetNodeGlobalIndex(i));
1906  }
1907  }
1908  }
1909 
1910  if (num_common_vertices == 1 || this->mNodes[common_vertex_index]->GetNumContainingElements() > 2)
1911  {
1912  /*
1913  * This is the situation here.
1914  *
1915  * From To
1916  * _ _
1917  * | <--- |
1918  * | /\ |\
1919  * | / \ | \
1920  * _|/____\ _|__\
1921  *
1922  * The edge goes from vertexA--vertexB to vertexA--pNode--vertexB
1923  */
1924 
1925  // Check whether the intersection location fits into the edge and update distances and vertex positions afterwards.
1926  intersection = this->WidenEdgeOrCorrectIntersectionLocationIfNecessary(vertexA_index, vertexB_index, intersection);
1927 
1928  // Move original node
1929  pNode->rGetModifiableLocation() = intersection;
1930 
1931  // Add the moved nodes to the element (this also updates the node)
1932  this->GetElement(elementIndex)->AddNode(pNode, node_A_local_index);
1933 
1934  // Check the nodes are updated correctly
1935  assert(pNode->GetNumContainingElements() == 2);
1936  }
1937  else if (num_common_vertices == 2)
1938  {
1939  // The two elements must have an edge in common. Find whether the common edge is the same as the
1940  // edge that is merged onto.
1941 
1942  if ( ( common_vertex_indices[0]==vertexA_index && common_vertex_indices[1]==vertexB_index ) ||
1943  ( common_vertex_indices[1]==vertexA_index && common_vertex_indices[0]==vertexB_index ) )
1944  {
1945  /*
1946  * Due to a previous T3 swap the situation looks like this.
1947  *
1948  * pNode
1949  * \ |\ /
1950  * \ | \ /
1951  * \_______|__\/
1952  * /A | B
1953  * / \
1954  *
1955  * A T3 Swap would merge pNode onto an edge of its own element.
1956  * We prevent this by just removing pNode. By doing this we also avoid the
1957  * intersecting element to be concave.
1958  */
1959 
1960  // Delete pNode in the intersecting element
1961  unsigned p_node_local_index = this->
1962  GetElement(intersecting_element_index)->GetNodeLocalIndex(pNode->GetIndex());
1963  this->GetElement(intersecting_element_index)->DeleteNode(p_node_local_index);
1964 
1965  // Mark all three nodes as deleted
1966  pNode->MarkAsDeleted();
1967  mDeletedNodeIndices.push_back(pNode->GetIndex());
1968  }
1969  else
1970  {
1971  /*
1972  * This is the situation here.
1973  *
1974  * C is common_vertex D is the other one.
1975  *
1976  * From To
1977  * _ D _
1978  * | <--- |
1979  * | /\ |\
1980  * C|/ \ | \
1981  * _|____\ _|__\
1982  *
1983  * The edge goes from vertexC--vertexB to vertexC--pNode--vertexD
1984  * then vertex B is removed as it is no longer needed.
1985  */
1986 
1987  // Check whether the intersection location fits into the edge and update distances and vertex positions afterwards.
1988  intersection = this->WidenEdgeOrCorrectIntersectionLocationIfNecessary(vertexA_index, vertexB_index, intersection);
1989 
1990  // Move original node
1991  pNode->rGetModifiableLocation() = intersection;
1992 
1993  // Replace common_vertex with the the moved node (this also updates the nodes)
1994  this->GetElement(elementIndex)->ReplaceNode(this->mNodes[common_vertex_index], pNode);
1995 
1996  // Remove common_vertex
1997  unsigned common_vertex_local_index = this->GetElement(intersecting_element_index)->GetNodeLocalIndex(common_vertex_index);
1998  this->GetElement(intersecting_element_index)->DeleteNode(common_vertex_local_index);
1999  assert(this->mNodes[common_vertex_index]->GetNumContainingElements() == 0);
2000 
2001  this->mNodes[common_vertex_index]->MarkAsDeleted();
2002  mDeletedNodeIndices.push_back(common_vertex_index);
2003 
2004  // Check the nodes are updated correctly
2005  assert(pNode->GetNumContainingElements() == 2);
2006  }
2007  }
2008  else if (num_common_vertices == 4)
2009  {
2010  /*
2011  * The two elements share edges CA and BD due to previous swaps but not the edge AB
2012  *
2013  * From To
2014  * D___ D___
2015  * | |
2016  * B|\ |
2017  * | \ |
2018  * | / |
2019  * A|/ |
2020  * C_|__ C_|__
2021  *
2022  * We just remove the intersecting node as well as vertices A and B.
2023  */
2024 
2025  // Delete node A and B in the intersected element
2026  this->GetElement(elementIndex)->DeleteNode(node_A_local_index);
2027  unsigned node_B_local_index = this->
2028  GetElement(elementIndex)->GetNodeLocalIndex(vertexB_index);
2029  this->GetElement(elementIndex)->DeleteNode(node_B_local_index);
2030 
2031  // Delete nodes A and B in the intersecting element
2032  unsigned node_A_local_index_intersecting_element = this->
2033  GetElement(intersecting_element_index)->GetNodeLocalIndex(vertexA_index);
2034  this->GetElement(intersecting_element_index)->DeleteNode(node_A_local_index_intersecting_element);
2035  unsigned node_B_local_index_intersecting_element = this->
2036  GetElement(intersecting_element_index)->GetNodeLocalIndex(vertexB_index);
2037  this->GetElement(intersecting_element_index)->DeleteNode(node_B_local_index_intersecting_element);
2038 
2039  // Delete pNode in the intersecting element
2040  unsigned p_node_local_index = this->
2041  GetElement(intersecting_element_index)->GetNodeLocalIndex(pNode->GetIndex());
2042  this->GetElement(intersecting_element_index)->DeleteNode(p_node_local_index);
2043 
2044  // Mark all three nodes as deleted
2045  pNode->MarkAsDeleted();
2046  mDeletedNodeIndices.push_back(pNode->GetIndex());
2047  this->mNodes[vertexA_index]->MarkAsDeleted();
2048  mDeletedNodeIndices.push_back(vertexA_index);
2049  this->mNodes[vertexB_index]->MarkAsDeleted();
2050  mDeletedNodeIndices.push_back(vertexB_index);
2051  }
2052  else
2053  {
2054  // This can't happen as nodes can't be on the internal edge of 2 elements.
2055  NEVER_REACHED;
2056  }
2057  }
2058  else
2059  {
2060  /*
2061  * From To
2062  * ____ _______
2063  * / \
2064  * /\ ^ / \
2065  * / \ |
2066  *
2067  * The edge goes from vertexA--vertexB to vertexA--new_node--pNode--vertexB
2068  */
2069 
2070  // Check whether the intersection location fits into the edge and update distances and vertex positions afterwards.
2071  intersection = this->WidenEdgeOrCorrectIntersectionLocationIfNecessary(vertexA_index, vertexB_index, intersection);
2072  edge_ab_unit_vector = this->GetPreviousEdgeGradientOfElementAtNode(p_element, (node_A_local_index+1)%num_nodes);
2073 
2074  // Move original node
2075  pNode->rGetModifiableLocation() = intersection + 0.5*mCellRearrangementRatio*mCellRearrangementThreshold*edge_ab_unit_vector;
2076 
2077  // Note that we define this vector before setting it as otherwise the profiling build will break (see #2367)
2078  c_vector<double, SPACE_DIM> new_node_location;
2079  new_node_location = intersection - 0.5*mCellRearrangementRatio*mCellRearrangementThreshold*edge_ab_unit_vector;
2080 
2081  // Add new node which will always be a boundary node
2082  unsigned new_node_global_index = this->AddNode(new Node<SPACE_DIM>(0, true, new_node_location[0], new_node_location[1]));
2083 
2084  // Add the moved and new nodes to the element (this also updates the node)
2085  this->GetElement(elementIndex)->AddNode(pNode, node_A_local_index);
2086  this->GetElement(elementIndex)->AddNode(this->mNodes[new_node_global_index], node_A_local_index);
2087 
2088  // Add the new node to the original element containing pNode (this also updates the node)
2089  this->GetElement(intersecting_element_index)->AddNode(this->mNodes[new_node_global_index], this->GetElement(intersecting_element_index)->GetNodeLocalIndex(pNode->GetIndex()));
2090 
2091  // The nodes must have been updated correctly
2092  assert(pNode->GetNumContainingElements() == 2);
2093  assert(this->mNodes[new_node_global_index]->GetNumContainingElements() == 2);
2094  }
2095  }
2096  else if (pNode->GetNumContainingElements() == 2)
2097  {
2098  // Find the nodes contained in elements containing the intersecting node
2099  std::set<unsigned>::const_iterator it = elements_containing_intersecting_node.begin();
2100 
2101  VertexElement<ELEMENT_DIM, SPACE_DIM>* p_element_1 = this->GetElement(*it);
2102  unsigned num_nodes_elem_1 = p_element_1->GetNumNodes();
2103  it++;
2104 
2105  VertexElement<ELEMENT_DIM, SPACE_DIM>* p_element_2 = this->GetElement(*it);
2106  unsigned num_nodes_elem_2 = p_element_2->GetNumNodes();
2107 
2108  unsigned node_global_index = pNode->GetIndex();
2109 
2110  unsigned local_index_1 = p_element_1->GetNodeLocalIndex(node_global_index);
2111  unsigned next_node_1 = p_element_1->GetNodeGlobalIndex((local_index_1 + 1)%num_nodes_elem_1);
2112  unsigned previous_node_1 = p_element_1->GetNodeGlobalIndex((local_index_1 + num_nodes_elem_1 - 1)%num_nodes_elem_1);
2113 
2114  unsigned local_index_2 = p_element_2->GetNodeLocalIndex(node_global_index);
2115  unsigned next_node_2 = p_element_2->GetNodeGlobalIndex((local_index_2 + 1)%num_nodes_elem_2);
2116  unsigned previous_node_2 = p_element_2->GetNodeGlobalIndex((local_index_2 + num_nodes_elem_2 - 1)%num_nodes_elem_2);
2117 
2118  // Check to see if the nodes adjacent to the intersecting node are contained in the intersected element between vertices A and B
2119  if ((next_node_1 == vertexA_index || previous_node_1 == vertexA_index || next_node_2 == vertexA_index || previous_node_2 == vertexA_index) &&
2120  (next_node_1 == vertexB_index || previous_node_1 == vertexB_index || next_node_2 == vertexB_index || previous_node_2 == vertexB_index))
2121  {
2122  /*
2123  * Here we have
2124  * __
2125  * /| /
2126  * __ / | --> ___/
2127  * \ | \
2128  * \|__ \
2129  *
2130  * Where the node on the left has overlapped the edge A B
2131  *
2132  * Move p_node to the intersection on A B and merge AB and p_node
2133  */
2134 
2135  // Check whether the intersection location fits into the edge and update distances and vertex positions afterwards.
2136  intersection = this->WidenEdgeOrCorrectIntersectionLocationIfNecessary(vertexA_index, vertexB_index, intersection);
2137  edge_ab_unit_vector = this->GetPreviousEdgeGradientOfElementAtNode(p_element, (node_A_local_index+1)%num_nodes);
2138 
2139  // Check they are all boundary nodes
2140  assert(pNode->IsBoundaryNode());
2141  assert(this->mNodes[vertexA_index]->IsBoundaryNode());
2142  assert(this->mNodes[vertexB_index]->IsBoundaryNode());
2143 
2144  // Move p_node to the intersection with the edge AB
2145  pNode->rGetModifiableLocation() = intersection;
2146  pNode->SetAsBoundaryNode(false);
2147 
2148  // Add pNode to the intersected element
2149  this->GetElement(elementIndex)->AddNode(pNode, node_A_local_index);
2150 
2151  // Remove vertex A from elements
2152  std::set<unsigned> elements_containing_vertex_A = this->mNodes[vertexA_index]->rGetContainingElementIndices();
2153  for (std::set<unsigned>::const_iterator iter = elements_containing_vertex_A.begin();
2154  iter != elements_containing_vertex_A.end();
2155  iter++)
2156  {
2157  this->GetElement(*iter)->DeleteNode(this->GetElement(*iter)->GetNodeLocalIndex(vertexA_index));
2158  }
2159 
2160  // Remove vertex A from the mesh
2161  assert(this->mNodes[vertexA_index]->GetNumContainingElements() == 0);
2162  this->mNodes[vertexA_index]->MarkAsDeleted();
2163  mDeletedNodeIndices.push_back(vertexA_index);
2164 
2165  // Remove vertex B from elements
2166  std::set<unsigned> elements_containing_vertex_B = this->mNodes[vertexB_index]->rGetContainingElementIndices();
2167  for (std::set<unsigned>::const_iterator iter = elements_containing_vertex_B.begin();
2168  iter != elements_containing_vertex_B.end();
2169  iter++)
2170  {
2171  this->GetElement(*iter)->DeleteNode(this->GetElement(*iter)->GetNodeLocalIndex(vertexB_index));
2172  }
2173 
2174  // Remove vertex B from the mesh
2175  assert(this->mNodes[vertexB_index]->GetNumContainingElements()==0);
2176  this->mNodes[vertexB_index]->MarkAsDeleted();
2177  mDeletedNodeIndices.push_back(vertexB_index);
2178  }
2179  else
2180  {
2181  if (next_node_1 == vertexA_index || previous_node_1 == vertexA_index || next_node_2 == vertexA_index || previous_node_2 == vertexA_index)
2182  {
2183  // Get elements containing vertexA_index (the common vertex)
2184 
2185  assert(this->mNodes[vertexA_index]->GetNumContainingElements() > 1);
2186 
2187  std::set<unsigned> elements_containing_vertex_A = this->mNodes[vertexA_index]->rGetContainingElementIndices();
2188  std::set<unsigned>::const_iterator iter = elements_containing_vertex_A.begin();
2189  VertexElement<ELEMENT_DIM, SPACE_DIM>* p_element_common_1 = this->GetElement(*iter);
2190  iter++;
2191  VertexElement<ELEMENT_DIM, SPACE_DIM>* p_element_common_2 = this->GetElement(*iter);
2192 
2193  // Calculate the number of common vertices between element_1 and element_2
2194  unsigned num_common_vertices = 0;
2195  for (unsigned i=0; i<p_element_common_1->GetNumNodes(); i++)
2196  {
2197  for (unsigned j=0; j<p_element_common_2->GetNumNodes(); j++)
2198  {
2199  if (p_element_common_1->GetNodeGlobalIndex(i) == p_element_common_2->GetNodeGlobalIndex(j))
2200  {
2201  num_common_vertices++;
2202  }
2203  }
2204  }
2205 
2206  if (num_common_vertices == 1 || this->mNodes[vertexA_index]->GetNumContainingElements() > 2)
2207  {
2208  /*
2209  * From To
2210  * _ B _ B
2211  * | <--- |
2212  * | /|\ |\
2213  * | / | \ | \
2214  * | / | \ |\ \
2215  * _|/___|___\ _|_\_\
2216  * A A
2217  *
2218  * The edge goes from vertexA--vertexB to vertexA--pNode--new_node--vertexB
2219  */
2220 
2221  // Check whether the intersection location fits into the edge and update distances and vertex positions afterwards.
2222  intersection = this->WidenEdgeOrCorrectIntersectionLocationIfNecessary(vertexA_index, vertexB_index, intersection);
2223  edge_ab_unit_vector = this->GetPreviousEdgeGradientOfElementAtNode(p_element, (node_A_local_index+1)%num_nodes);
2224 
2225  // Move original node and change to non-boundary node
2226  pNode->rGetModifiableLocation() = intersection - 0.5*mCellRearrangementRatio*mCellRearrangementThreshold*edge_ab_unit_vector;
2227  pNode->SetAsBoundaryNode(false);
2228 
2229  // Note that we define this vector before setting it as otherwise the profiling build will break (see #2367)
2230  c_vector<double, SPACE_DIM> new_node_location;
2231  new_node_location = intersection + 0.5*mCellRearrangementRatio*mCellRearrangementThreshold*edge_ab_unit_vector;
2232 
2233  // Add new node, which will always be a boundary node
2234  unsigned new_node_global_index = this->AddNode(new Node<SPACE_DIM>(0, true, new_node_location[0], new_node_location[1]));
2235 
2236  // Add the moved nodes to the element (this also updates the node)
2237  this->GetElement(elementIndex)->AddNode(this->mNodes[new_node_global_index], node_A_local_index);
2238  this->GetElement(elementIndex)->AddNode(pNode, node_A_local_index);
2239 
2240  // Add the new nodes to the original elements containing pNode (this also updates the node)
2241  if (next_node_1 == previous_node_2)
2242  {
2243  p_element_1->AddNode(this->mNodes[new_node_global_index], (local_index_1 + p_element_1->GetNumNodes() - 1)%(p_element_1->GetNumNodes()));
2244  }
2245  else
2246  {
2247  assert(next_node_2 == previous_node_1);
2248 
2249  p_element_2->AddNode(this->mNodes[new_node_global_index], (local_index_2 + p_element_2->GetNumNodes() - 1)%(p_element_2->GetNumNodes()));
2250  }
2251 
2252  // Check the nodes are updated correctly
2253  assert(pNode->GetNumContainingElements() == 3);
2254  assert(this->mNodes[new_node_global_index]->GetNumContainingElements() == 2);
2255  }
2256  else if (num_common_vertices == 2)
2257  {
2258  /*
2259  * From To
2260  * _ B _ B
2261  * |<--- |
2262  * | /|\ |\
2263  * |/ | \ | \
2264  * | | \ |\ \
2265  * _|__|___\ _|_\_\
2266  * A A
2267  *
2268  * The edge goes from vertexA--vertexB to vertexA--pNode--new_node--vertexB
2269  * then vertexA is removed
2270  */
2271 
2272  // Check whether the intersection location fits into the edge and update distances and vertex positions afterwards.
2273  intersection = this->WidenEdgeOrCorrectIntersectionLocationIfNecessary(vertexA_index, vertexB_index, intersection);
2274  edge_ab_unit_vector = this->GetPreviousEdgeGradientOfElementAtNode(p_element, (node_A_local_index+1)%num_nodes);
2275 
2276  // Move original node and change to non-boundary node
2277  pNode->rGetModifiableLocation() = intersection - 0.5*mCellRearrangementRatio*mCellRearrangementThreshold*edge_ab_unit_vector;
2278  pNode->SetAsBoundaryNode(false);
2279 
2280  // Note that we define this vector before setting it as otherwise the profiling build will break (see #2367)
2281  c_vector<double, SPACE_DIM> new_node_location;
2282  new_node_location = intersection + 0.5*mCellRearrangementRatio*mCellRearrangementThreshold*edge_ab_unit_vector;
2283 
2284  // Add new node, which will always be a boundary node
2285  unsigned new_node_global_index = this->AddNode(new Node<SPACE_DIM>(0, true, new_node_location[0], new_node_location[1]));
2286 
2287  // Add the moved nodes to the element (this also updates the node)
2288  this->GetElement(elementIndex)->AddNode(this->mNodes[new_node_global_index], node_A_local_index);
2289  this->GetElement(elementIndex)->AddNode(pNode, node_A_local_index);
2290 
2291  // Add the new nodes to the original elements containing pNode (this also updates the node)
2292  if (next_node_1 == previous_node_2)
2293  {
2294  p_element_1->AddNode(this->mNodes[new_node_global_index], (local_index_1 + p_element_1->GetNumNodes() - 1)%(p_element_1->GetNumNodes()));
2295  }
2296  else
2297  {
2298  assert(next_node_2 == previous_node_1);
2299  p_element_2->AddNode(this->mNodes[new_node_global_index], (local_index_2 + p_element_2->GetNumNodes() - 1)%(p_element_2->GetNumNodes()));
2300  }
2301 
2302  // Remove vertex A from the mesh
2303  p_element_common_1->DeleteNode(p_element_common_1->GetNodeLocalIndex(vertexA_index));
2304  p_element_common_2->DeleteNode(p_element_common_2->GetNodeLocalIndex(vertexA_index));
2305 
2306  assert(this->mNodes[vertexA_index]->GetNumContainingElements()==0);
2307 
2308  this->mNodes[vertexA_index]->MarkAsDeleted();
2309  mDeletedNodeIndices.push_back(vertexA_index);
2310 
2311  // Check the nodes are updated correctly
2312  assert(pNode->GetNumContainingElements() == 3);
2313  assert(this->mNodes[new_node_global_index]->GetNumContainingElements() == 2);
2314  }
2315  else
2316  {
2317  // This can't happen as nodes can't be on the internal edge of two elements
2318  NEVER_REACHED;
2319  }
2320  }
2321  else if (next_node_1 == vertexB_index || previous_node_1 == vertexB_index || next_node_2 == vertexB_index || previous_node_2 == vertexB_index)
2322  {
2323  // Get elements containing vertexB_index (the common vertex)
2324 
2325  assert(this->mNodes[vertexB_index]->GetNumContainingElements()>1);
2326 
2327  std::set<unsigned> elements_containing_vertex_B = this->mNodes[vertexB_index]->rGetContainingElementIndices();
2328  std::set<unsigned>::const_iterator iter = elements_containing_vertex_B.begin();
2329  VertexElement<ELEMENT_DIM, SPACE_DIM>* p_element_common_1 = this->GetElement(*iter);
2330  iter++;
2331  VertexElement<ELEMENT_DIM, SPACE_DIM>* p_element_common_2 = this->GetElement(*iter);
2332 
2333  // Calculate the number of common vertices between element_1 and element_2
2334  unsigned num_common_vertices = 0;
2335  for (unsigned i=0; i<p_element_common_1->GetNumNodes(); i++)
2336  {
2337  for (unsigned j=0; j<p_element_common_2->GetNumNodes(); j++)
2338  {
2339  if (p_element_common_1->GetNodeGlobalIndex(i) == p_element_common_2->GetNodeGlobalIndex(j))
2340  {
2341  num_common_vertices++;
2342  }
2343  }
2344  }
2345 
2346  if (num_common_vertices == 1 || this->mNodes[vertexB_index]->GetNumContainingElements() > 2)
2347  {
2348  /*
2349  * From To
2350  * _B_________ _B____
2351  * |\ | / | / /
2352  * | \ | / |/ /
2353  * | \ | / | /
2354  * | \|/ |/
2355  * _| <--- _|
2356  * A
2357  *
2358  * The edge goes from vertexA--vertexB to vertexA--new_node--pNode--vertexB
2359  */
2360 
2361  // Check whether the intersection location fits into the edge and update distances and vertex positions afterwards.
2362  intersection = this->WidenEdgeOrCorrectIntersectionLocationIfNecessary(vertexA_index, vertexB_index, intersection);
2363  edge_ab_unit_vector = this->GetPreviousEdgeGradientOfElementAtNode(p_element, (node_A_local_index+1)%num_nodes);
2364 
2365  // Move original node and change to non-boundary node
2366  pNode->rGetModifiableLocation() = intersection + 0.5*mCellRearrangementRatio*mCellRearrangementThreshold*edge_ab_unit_vector;
2367  pNode->SetAsBoundaryNode(false);
2368 
2369  // Note that we define this vector before setting it as otherwise the profiling build will break (see #2367)
2370  c_vector<double, SPACE_DIM> new_node_location;
2371  new_node_location = intersection - 0.5*mCellRearrangementRatio*mCellRearrangementThreshold*edge_ab_unit_vector;
2372 
2373  // Add new node which will always be a boundary node
2374  unsigned new_node_global_index = this->AddNode(new Node<SPACE_DIM>(0, true, new_node_location[0], new_node_location[1]));
2375 
2376  // Add the moved nodes to the element (this also updates the node)
2377  this->GetElement(elementIndex)->AddNode(pNode, node_A_local_index);
2378  this->GetElement(elementIndex)->AddNode(this->mNodes[new_node_global_index], node_A_local_index);
2379 
2380  // Add the new nodes to the original elements containing pNode (this also updates the node)
2381  if (next_node_1 == previous_node_2)
2382  {
2383  p_element_2->AddNode(this->mNodes[new_node_global_index], local_index_2);
2384  }
2385  else
2386  {
2387  assert(next_node_2 == previous_node_1);
2388  p_element_1->AddNode(this->mNodes[new_node_global_index], local_index_1);
2389  }
2390 
2391  // Check the nodes are updated correctly
2392  assert(pNode->GetNumContainingElements() == 3);
2393  assert(this->mNodes[new_node_global_index]->GetNumContainingElements() == 2);
2394  }
2395  else if (num_common_vertices == 2)
2396  {
2397  /*
2398  * From To
2399  * _B_______ _B____
2400  * | | / | / /
2401  * | | / |/ /
2402  * |\ | / | /
2403  * | \|/ |/
2404  * _| <--- _|
2405  * A
2406  *
2407  * The edge goes from vertexA--vertexB to vertexA--new_node--pNode--vertexB
2408  * then vertexB is removed
2409  */
2410 
2411  // Check whether the intersection location fits into the edge and update distances and vertex positions afterwards.
2412  intersection = this->WidenEdgeOrCorrectIntersectionLocationIfNecessary(vertexA_index, vertexB_index, intersection);
2413  edge_ab_unit_vector = this->GetPreviousEdgeGradientOfElementAtNode(p_element, (node_A_local_index+1)%num_nodes);
2414 
2415  // Move original node and change to non-boundary node
2416  pNode->rGetModifiableLocation() = intersection + 0.5*mCellRearrangementRatio*mCellRearrangementThreshold*edge_ab_unit_vector;
2417  pNode->SetAsBoundaryNode(false);
2418 
2419  // Note that we define this vector before setting it as otherwise the profiling build will break (see #2367)
2420  c_vector<double, SPACE_DIM> new_node_location;
2421  new_node_location = intersection - 0.5*mCellRearrangementRatio*mCellRearrangementThreshold*edge_ab_unit_vector;
2422 
2423  // Add new node which will always be a boundary node
2424  unsigned new_node_global_index = this->AddNode(new Node<SPACE_DIM>(0, true, new_node_location[0], new_node_location[1]));
2425 
2426  // Add the moved nodes to the element (this also updates the node)
2427  this->GetElement(elementIndex)->AddNode(pNode, node_A_local_index);
2428  this->GetElement(elementIndex)->AddNode(this->mNodes[new_node_global_index], node_A_local_index);
2429 
2430  // Add the new nodes to the original elements containing pNode (this also updates the node)
2431  if (next_node_1 == previous_node_2)
2432  {
2433  p_element_2->AddNode(this->mNodes[new_node_global_index], local_index_2);
2434  }
2435  else
2436  {
2437  assert(next_node_2 == previous_node_1);
2438  p_element_1->AddNode(this->mNodes[new_node_global_index], local_index_1);
2439  }
2440 
2441  // Remove vertex B from the mesh
2442  p_element_common_1->DeleteNode(p_element_common_1->GetNodeLocalIndex(vertexB_index));
2443  p_element_common_2->DeleteNode(p_element_common_2->GetNodeLocalIndex(vertexB_index));
2444 
2445  assert(this->mNodes[vertexB_index]->GetNumContainingElements()==0);
2446 
2447  this->mNodes[vertexB_index]->MarkAsDeleted();
2448  mDeletedNodeIndices.push_back(vertexB_index);
2449 
2450  // Check the nodes are updated correctly
2451  assert(pNode->GetNumContainingElements() == 3);
2452  assert(this->mNodes[new_node_global_index]->GetNumContainingElements() == 2);
2453  }
2454  else
2455  {
2456  // This can't happen as nodes can't be on the internal edge of two elements
2457  NEVER_REACHED;
2458  }
2459  }
2460  else
2461  {
2462  /*
2463  * From To
2464  * _____ _______
2465  * / | \
2466  * /|\ ^ / | \
2467  * / | \ |
2468  *
2469  * The edge goes from vertexA--vertexB to vertexA--new_node_1--pNode--new_node_2--vertexB
2470  */
2471 
2472  // Check whether the intersection location fits into the edge and update distances and vertex positions afterwards.
2473  intersection = this->WidenEdgeOrCorrectIntersectionLocationIfNecessary(vertexA_index, vertexB_index, intersection);
2474  edge_ab_unit_vector = this->GetPreviousEdgeGradientOfElementAtNode(p_element, (node_A_local_index+1)%num_nodes);
2475 
2476  // Move original node and change to non-boundary node
2477  pNode->rGetModifiableLocation() = intersection;
2478  pNode->SetAsBoundaryNode(false);
2479 
2480  c_vector<double, SPACE_DIM> new_node_1_location;
2481  new_node_1_location = intersection - mCellRearrangementRatio*mCellRearrangementThreshold*edge_ab_unit_vector;
2482  c_vector<double, SPACE_DIM> new_node_2_location;
2483  new_node_2_location = intersection + mCellRearrangementRatio*mCellRearrangementThreshold*edge_ab_unit_vector;
2484 
2485  // Add new nodes which will always be boundary nodes
2486  unsigned new_node_1_global_index = this->AddNode(new Node<SPACE_DIM>(0, true, new_node_1_location[0], new_node_1_location[1]));
2487  unsigned new_node_2_global_index = this->AddNode(new Node<SPACE_DIM>(0, true, new_node_2_location[0], new_node_2_location[1]));
2488 
2489  // Add the moved and new nodes to the element (this also updates the node)
2490  this->GetElement(elementIndex)->AddNode(this->mNodes[new_node_2_global_index], node_A_local_index);
2491  this->GetElement(elementIndex)->AddNode(pNode, node_A_local_index);
2492  this->GetElement(elementIndex)->AddNode(this->mNodes[new_node_1_global_index], node_A_local_index);
2493 
2494  // Add the new nodes to the original elements containing pNode (this also updates the node)
2495  if (next_node_1 == previous_node_2)
2496  {
2497  p_element_1->AddNode(this->mNodes[new_node_2_global_index], (local_index_1 + p_element_1->GetNumNodes() - 1)%(p_element_1->GetNumNodes()));
2498  p_element_2->AddNode(this->mNodes[new_node_1_global_index], local_index_2);
2499  }
2500  else
2501  {
2502  assert(next_node_2 == previous_node_1);
2503 
2504  p_element_1->AddNode(this->mNodes[new_node_1_global_index], local_index_1);
2505  p_element_2->AddNode(this->mNodes[new_node_2_global_index], (local_index_2 + p_element_2->GetNumNodes() - 1)%(p_element_2->GetNumNodes()));
2506  }
2507 
2508  // Check the nodes are updated correctly
2509  assert(pNode->GetNumContainingElements() == 3);
2510  assert(this->mNodes[new_node_1_global_index]->GetNumContainingElements() == 2);
2511  assert(this->mNodes[new_node_2_global_index]->GetNumContainingElements() == 2);
2512  }
2513  }
2514  }
2515  else
2516  {
2517  EXCEPTION("Trying to merge a node, contained in more than 2 elements, into another element, this is not possible with the vertex mesh.");
2518  }
2519 }
2520 
2521 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
2523 {
2524  // Calculate void centroid
2525  c_vector<double, SPACE_DIM> nodes_midpoint = pNodeA->rGetLocation()
2526  + this->GetVectorFromAtoB(pNodeA->rGetLocation(), pNodeB->rGetLocation()) / 3.0
2527  + this->GetVectorFromAtoB(pNodeA->rGetLocation(), pNodeC->rGetLocation()) / 3.0;
2528 
2529  /*
2530  * In two steps, merge nodes A, B and C into a single node. This is implemented in such a way that
2531  * the ordering of their indices does not matter.
2532  */
2533 
2534  PerformNodeMerge(pNodeA, pNodeB);
2535 
2536  Node<SPACE_DIM>* p_merged_node = pNodeB;
2537 
2538  if (pNodeB->IsDeleted())
2539  {
2540  p_merged_node = pNodeA;
2541  }
2542 
2543  PerformNodeMerge(pNodeC, p_merged_node);
2544 
2545  if (p_merged_node->IsDeleted())
2546  {
2547  p_merged_node = pNodeC;
2548  }
2549 
2550  p_merged_node->rGetModifiableLocation() = nodes_midpoint;
2551 
2552  // Tag remaining node as non-boundary
2553  p_merged_node->SetAsBoundaryNode(false);
2554 
2555  // Remove the deleted nodes and re-index
2556  RemoveDeletedNodes();
2557 }
2558 
2559 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
2561 {
2562  unsigned node_a_rank = pNodeA->rGetContainingElementIndices().size();
2563  unsigned node_b_rank = pNodeB->rGetContainingElementIndices().size();
2564 
2565  if ((node_a_rank > 3) && (node_b_rank > 3))
2566  {
2567  // The code can't handle this case
2568  EXCEPTION("Both nodes involved in a swap event are contained in more than three elements");
2569  }
2570  else // the rosette degree should increase in this case
2571  {
2572  assert(node_a_rank > 3 || node_b_rank > 3);
2573  this->PerformRosetteRankIncrease(pNodeA, pNodeB);
2574  this->RemoveDeletedNodes();
2575  }
2576 }
2577 
2578 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
2580 {
2581  /*
2582  * One of the nodes will have 3 containing element indices, the other
2583  * will have at least four. We first identify which node is which.
2584  */
2585 
2586  unsigned node_a_index = pNodeA->GetIndex();
2587  unsigned node_b_index = pNodeB->GetIndex();
2588 
2589  unsigned node_a_rank = pNodeA->rGetContainingElementIndices().size();
2590  unsigned node_b_rank = pNodeB->rGetContainingElementIndices().size();
2591 
2592  unsigned lo_rank_index = (node_a_rank < node_b_rank) ? node_a_index : node_b_index;
2593  unsigned hi_rank_index = (node_a_rank < node_b_rank) ? node_b_index : node_a_index;
2594 
2595  // Get pointers to the nodes, sorted by index
2596  Node<SPACE_DIM>* p_lo_rank_node = this->GetNode(lo_rank_index);
2597  Node<SPACE_DIM>* p_hi_rank_node = this->GetNode(hi_rank_index);
2598 
2599  // Find the sets of elements containing each of the nodes, sorted by index
2600  std::set<unsigned> lo_rank_elem_indices = p_lo_rank_node->rGetContainingElementIndices();
2601  std::set<unsigned> hi_rank_elem_indices = p_hi_rank_node->rGetContainingElementIndices();
2602 
2629  for (std::set<unsigned>::const_iterator it = lo_rank_elem_indices.begin();
2630  it != lo_rank_elem_indices.end();
2631  ++it)
2632  {
2633  // Find the local index of lo_rank_node in this element
2634  unsigned lo_rank_local_index = this->mElements[*it]->GetNodeLocalIndex(lo_rank_index);
2635  assert(lo_rank_local_index < UINT_MAX); // double check this element contains lo_rank_node
2636 
2637  /*
2638  * If this element already contains the hi_rank_node, we are in the situation of elements
2639  * C and D above, so we just remove lo_rank_node.
2640  *
2641  * Otherwise, we are in element E, so we must replace lo_rank_node with high-rank node,
2642  * and remove it from mNodes.
2643  *
2644  * We can check whether hi_rank_node is in this element using the set::count() method.
2645  */
2646 
2647  if (hi_rank_elem_indices.count(*it) > 0)
2648  {
2649  // Delete lo_rank_node from current element
2650  this->mElements[*it]->DeleteNode(lo_rank_local_index);
2651  }
2652  else
2653  {
2654  // Update lo_rank_node with all information (including index and location) of hi_rank_node
2655  this->mElements[*it]->UpdateNode(lo_rank_local_index, p_hi_rank_node);
2656  }
2657  }
2658 
2659  // Tidy up the mesh by ensuring the global instance of lo_rank_node is deleted
2660  assert(!(this->mNodes[lo_rank_index]->IsDeleted()));
2661  this->mNodes[lo_rank_index]->MarkAsDeleted();
2662  this->mDeletedNodeIndices.push_back(lo_rank_index);
2663 }
2664 
2665 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
2667 {
2668  // Double check we are dealing with a protorosette
2669  assert(pProtorosetteNode->rGetContainingElementIndices().size() == 4);
2670 
2671  // Get random number (0, 1, 2 or 3), as the resolution axis is assumed to be random
2672  unsigned random_elem_increment = RandomNumberGenerator::Instance()->randMod(4);
2673 
2674  // Find global indices of elements around the protorosette node
2675  std::set<unsigned> protorosette_node_containing_elem_indices = pProtorosetteNode->rGetContainingElementIndices();
2676 
2677  // Select random element by advancing iterator a random number times
2678  std::set<unsigned>::const_iterator elem_index_iter(protorosette_node_containing_elem_indices.begin());
2679  advance(elem_index_iter, random_elem_increment);
2680 
2708  /*
2709  * We need to find the global indices of elements B, C and D. We do this with set intersections.
2710  */
2711 
2712  unsigned elem_a_idx = *elem_index_iter;
2713  unsigned elem_b_idx = UINT_MAX;
2714  unsigned elem_c_idx = UINT_MAX;
2715  unsigned elem_d_idx = UINT_MAX;
2716 
2717  // Get pointer to element we've chosen at random (element A)
2718  VertexElement<ELEMENT_DIM,SPACE_DIM>* p_elem_a = this->GetElement(elem_a_idx);
2719 
2720  // Get all necessary info about element A and the protorosette node
2721  unsigned num_nodes_elem_a = p_elem_a->GetNumNodes();
2722  unsigned protorosette_node_global_idx = pProtorosetteNode->GetIndex();
2723  unsigned protorosette_node_local_idx = p_elem_a->GetNodeLocalIndex(protorosette_node_global_idx);
2724 
2725  // Find global indices of previous (cw) and next (ccw) nodes, locally, from the protorosette node, in element A
2726  unsigned prev_node_global_idx = p_elem_a->GetNodeGlobalIndex((protorosette_node_local_idx + num_nodes_elem_a - 1) % num_nodes_elem_a);
2727  unsigned next_node_global_idx = p_elem_a->GetNodeGlobalIndex((protorosette_node_local_idx + 1) % num_nodes_elem_a);
2728 
2729  // Get the set of elements the previous and next nodes are contained in
2730  Node<SPACE_DIM>* p_prev_node = this->GetNode(prev_node_global_idx);
2731  Node<SPACE_DIM>* p_next_node = this->GetNode(next_node_global_idx);
2732  std::set<unsigned> prev_node_elem_indices = p_prev_node->rGetContainingElementIndices();
2733  std::set<unsigned> next_node_elem_indices = p_next_node->rGetContainingElementIndices();
2734 
2735  // Perform set intersections with the set of element indices which the protorosette node is contained in
2736  std::set<unsigned> intersection_with_prev;
2737  std::set<unsigned> intersection_with_next;
2738 
2739  // This intersection should contain just global indices for elements A and B
2740  std::set_intersection(protorosette_node_containing_elem_indices.begin(),
2741  protorosette_node_containing_elem_indices.end(),
2742  prev_node_elem_indices.begin(),
2743  prev_node_elem_indices.end(),
2744  std::inserter(intersection_with_prev, intersection_with_prev.begin()));
2745 
2746  // This intersection should contain just global indices for elements A and D
2747  std::set_intersection(protorosette_node_containing_elem_indices.begin(),
2748  protorosette_node_containing_elem_indices.end(),
2749  next_node_elem_indices.begin(),
2750  next_node_elem_indices.end(),
2751  std::inserter(intersection_with_next, intersection_with_next.begin()));
2752 
2753  assert(intersection_with_prev.size() == 2);
2754  assert(intersection_with_next.size() == 2);
2755 
2756  // Get global index of element B
2757  if (*intersection_with_prev.begin() != elem_a_idx)
2758  {
2759  elem_b_idx = *(intersection_with_prev.begin());
2760  }
2761  else
2762  {
2763  elem_b_idx = *(++(intersection_with_prev.begin()));
2764  }
2765  assert(elem_b_idx < UINT_MAX);
2766 
2767  // Get global index of element D
2768  if (*intersection_with_next.begin() != elem_a_idx)
2769  {
2770  elem_d_idx = *(intersection_with_next.begin());
2771  }
2772  else
2773  {
2774  elem_d_idx = *(++(intersection_with_next.begin()));
2775  }
2776  assert(elem_d_idx < UINT_MAX);
2777 
2778  // By elimination, the remaining unassigned index in the original set must be global index of element C
2779  for (elem_index_iter = protorosette_node_containing_elem_indices.begin();
2780  elem_index_iter != protorosette_node_containing_elem_indices.end();
2781  ++elem_index_iter)
2782  {
2783  if ( (*elem_index_iter != elem_a_idx) && (*elem_index_iter != elem_b_idx) && (*elem_index_iter != elem_d_idx) )
2784  {
2785  elem_c_idx = *elem_index_iter;
2786  }
2787  }
2788  assert(elem_c_idx < UINT_MAX);
2789 
2804  VertexElement<ELEMENT_DIM,SPACE_DIM>* p_elem_b = this->GetElement(elem_b_idx);
2805  VertexElement<ELEMENT_DIM,SPACE_DIM>* p_elem_c = this->GetElement(elem_c_idx);
2806  VertexElement<ELEMENT_DIM,SPACE_DIM>* p_elem_d = this->GetElement(elem_d_idx);
2807 
2808  double swap_distance = (this->mCellRearrangementRatio) * (this->mCellRearrangementThreshold);
2809 
2810  // Get normalized vectors to centre of elements A and B from protorosette node
2811  c_vector<double, SPACE_DIM> node_to_elem_a_centre = this->GetCentroidOfElement(elem_a_idx) - pProtorosetteNode->rGetLocation();
2812  node_to_elem_a_centre /= norm_2(node_to_elem_a_centre);
2813 
2814  c_vector<double, SPACE_DIM> node_to_elem_c_centre = this->GetCentroidOfElement(elem_c_idx) - pProtorosetteNode->rGetLocation();
2815  node_to_elem_c_centre /= norm_2(node_to_elem_c_centre);
2816 
2817  // Calculate new node locations
2818  c_vector<double, SPACE_DIM> new_location_of_protorosette_node = pProtorosetteNode->rGetLocation() + (0.5 * swap_distance) * node_to_elem_a_centre;
2819  c_vector<double, SPACE_DIM> location_of_new_node = pProtorosetteNode->rGetLocation() + (0.5 * swap_distance) * node_to_elem_c_centre;
2820 
2821  // Move protorosette node to new location
2822  pProtorosetteNode->rGetModifiableLocation() = new_location_of_protorosette_node;
2823 
2824  // Create new node in correct location
2825  unsigned new_node_global_index = this->AddNode(new Node<SPACE_DIM>(this->GetNumNodes(), location_of_new_node, false));
2826  Node<SPACE_DIM>* p_new_node = this->GetNode(new_node_global_index);
2827 
2838  unsigned local_idx_elem_b = p_elem_b->GetNodeLocalIndex(protorosette_node_global_idx);
2839  local_idx_elem_b = (local_idx_elem_b + p_elem_b->GetNumNodes() - 1) % p_elem_b->GetNumNodes();
2840  unsigned local_idx_elem_c = p_elem_c->GetNodeLocalIndex(protorosette_node_global_idx);
2841  unsigned local_idx_elem_d = p_elem_d->GetNodeLocalIndex(protorosette_node_global_idx);
2842 
2843  p_elem_b->AddNode(p_new_node, local_idx_elem_b);
2844  p_elem_c->AddNode(p_new_node, local_idx_elem_c);
2845  p_elem_d->AddNode(p_new_node, local_idx_elem_d);
2846 
2847  // All that is left is to remove the original protorosette node from element C
2848  p_elem_c->DeleteNode(p_elem_c->GetNodeLocalIndex(protorosette_node_global_idx));
2849 }
2850 
2851 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
2853 {
2854  unsigned rosette_rank = pRosetteNode->rGetContainingElementIndices().size();
2855 
2856  // Double check we're dealing with a rosette
2857  assert(rosette_rank > 4);
2858 
2859  // Get random number in [0, 1, ..., n) where n is rank of rosette, as the resolution axis is assumed to be random
2860  unsigned random_elem_increment = RandomNumberGenerator::Instance()->randMod(rosette_rank);
2861 
2862  // Find global indices of elements around the protorosette node
2863  std::set<unsigned> rosette_node_containing_elem_indices = pRosetteNode->rGetContainingElementIndices();
2864 
2865  // Select random element by advancing iterator a random number times
2866  std::set<unsigned>::const_iterator elem_index_iter(rosette_node_containing_elem_indices.begin());
2867  advance(elem_index_iter, random_elem_increment);
2868 
2907  /*
2908  * We need to find the global indices of elements N and P. We do this with set intersections.
2909  */
2910 
2911  // Get the vertex element S (which we randomly selected)
2912  unsigned elem_s_idx = *elem_index_iter;
2913  VertexElement<ELEMENT_DIM,SPACE_DIM>* p_elem_s = this->GetElement(elem_s_idx);
2914 
2915  unsigned elem_n_idx = UINT_MAX;
2916  unsigned elem_p_idx = UINT_MAX;
2917 
2918  // Get all necessary info about element S and the rosette node
2919  unsigned num_nodes_elem_s = p_elem_s->GetNumNodes();
2920  unsigned rosette_node_global_idx = pRosetteNode->GetIndex();
2921  unsigned rosette_node_local_idx = p_elem_s->GetNodeLocalIndex(rosette_node_global_idx);
2922 
2923  // Find global indices of previous (cw) and next (ccw) nodes, locally, from the rosette node, in element S
2924  unsigned prev_node_global_idx = p_elem_s->GetNodeGlobalIndex((rosette_node_local_idx + num_nodes_elem_s - 1) % num_nodes_elem_s);
2925  unsigned next_node_global_idx = p_elem_s->GetNodeGlobalIndex((rosette_node_local_idx + 1) % num_nodes_elem_s);
2926 
2927  // Get the set of elements that the previous and next nodes are contained in
2928  Node<SPACE_DIM>* p_prev_node = this->GetNode(prev_node_global_idx);
2929  Node<SPACE_DIM>* p_next_node = this->GetNode(next_node_global_idx);
2930  std::set<unsigned> prev_node_elem_indices = p_prev_node->rGetContainingElementIndices();
2931  std::set<unsigned> next_node_elem_indices = p_next_node->rGetContainingElementIndices();
2932 
2933  // Perform set intersections with the set of element indices that the rosette node is contained in
2934  std::set<unsigned> intersection_with_prev;
2935  std::set<unsigned> intersection_with_next;
2936 
2937  // This intersection should contain just global indices for elements S and N
2938  std::set_intersection(rosette_node_containing_elem_indices.begin(),
2939  rosette_node_containing_elem_indices.end(),
2940  prev_node_elem_indices.begin(),
2941  prev_node_elem_indices.end(),
2942  std::inserter(intersection_with_prev, intersection_with_prev.begin()));
2943 
2944  // This intersection should contain just global indices for elements S and P
2945  std::set_intersection(rosette_node_containing_elem_indices.begin(),
2946  rosette_node_containing_elem_indices.end(),
2947  next_node_elem_indices.begin(),
2948  next_node_elem_indices.end(),
2949  std::inserter(intersection_with_next, intersection_with_next.begin()));
2950 
2951  assert(intersection_with_prev.size() == 2);
2952  assert(intersection_with_next.size() == 2);
2953 
2954  // Get global index of element N
2955  if (*intersection_with_prev.begin() != elem_s_idx)
2956  {
2957  elem_n_idx = *intersection_with_prev.begin();
2958  }
2959  else
2960  {
2961  elem_n_idx = *(++(intersection_with_prev.begin()));
2962  }
2963  assert(elem_n_idx < UINT_MAX);
2964 
2965  // Get global index of element P
2966  if (*intersection_with_next.begin() != elem_s_idx)
2967  {
2968  elem_p_idx = *intersection_with_next.begin();
2969  }
2970  else
2971  {
2972  elem_p_idx = *(++(intersection_with_next.begin()));
2973  }
2974  assert(elem_p_idx < UINT_MAX);
2975 
2986  VertexElement<ELEMENT_DIM,SPACE_DIM>* p_elem_n = this->GetElement(elem_p_idx);
2987  VertexElement<ELEMENT_DIM,SPACE_DIM>* p_elem_p = this->GetElement(elem_n_idx);
2988 
2989  double swap_distance = (this->mCellRearrangementRatio) * (this->mCellRearrangementThreshold);
2990 
2991  // Calculate location of new node
2992  c_vector<double, 2> node_to_selected_elem = this->GetCentroidOfElement(elem_s_idx) - pRosetteNode->rGetLocation();
2993  node_to_selected_elem /= norm_2(node_to_selected_elem);
2994  c_vector<double, 2> new_node_location = pRosetteNode->rGetLocation() + (swap_distance * node_to_selected_elem);
2995 
2996  // Create new node in correct location
2997  unsigned new_node_global_index = this->AddNode(new Node<SPACE_DIM>(this->GetNumNodes(), new_node_location, false));
2998  Node<SPACE_DIM>* p_new_node = this->GetNode(new_node_global_index);
2999 
3011  // Add new node, and remove rosette node, from element S
3012  unsigned node_local_idx_in_elem_s = p_elem_s->GetNodeLocalIndex(rosette_node_global_idx);
3013  p_elem_s->AddNode(p_new_node, node_local_idx_in_elem_s);
3014  p_elem_s->DeleteNode(node_local_idx_in_elem_s);
3015 
3016  // Add new node to element N
3017  unsigned node_local_idx_in_elem_n = p_elem_n->GetNodeLocalIndex(rosette_node_global_idx);
3018  node_local_idx_in_elem_n = (node_local_idx_in_elem_n + p_elem_n->GetNumNodes() - 1) % p_elem_n->GetNumNodes();
3019  p_elem_n->AddNode(p_new_node, node_local_idx_in_elem_n);
3020 
3021  // Add new node to element P
3022  unsigned node_local_idx_in_elem_p = p_elem_p->GetNodeLocalIndex(rosette_node_global_idx);
3023  p_elem_p->AddNode(p_new_node, node_local_idx_in_elem_p);
3024 }
3025 
3026 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
3028 {
3037  // Vectors to store the nodes that need resolution events
3038  std::vector<Node<SPACE_DIM>* > protorosette_nodes;
3039  std::vector<Node<SPACE_DIM>* > rosette_nodes;
3040 
3041  // First loop in which we populate these vectors
3042  unsigned num_nodes = this->GetNumAllNodes();
3043  for (unsigned node_idx = 0 ; node_idx < num_nodes ; node_idx++)
3044  {
3045  Node<SPACE_DIM>* current_node = this->GetNode(node_idx);
3046  unsigned node_rank = current_node->rGetContainingElementIndices().size();
3047 
3048  if (node_rank < 4)
3049  {
3050  // Nothing to do if the node is not high-rank
3051  continue;
3052  }
3053  else if (node_rank == 4)
3054  {
3055  // For protorosette nodes, we check against a random number to decide if resolution is necessary
3056  if (mProtorosetteResolutionProbabilityPerTimestep >= RandomNumberGenerator::Instance()->ranf())
3057  {
3058  protorosette_nodes.push_back(current_node);
3059  }
3060  }
3061  else // if (node_rank > 4)
3062  {
3063  // For rosette nodes, we check against a random number to decide if resolution is necessary
3064  if (mRosetteResolutionProbabilityPerTimestep >= RandomNumberGenerator::Instance()->ranf())
3065  {
3066  rosette_nodes.push_back(current_node);
3067  }
3068  }
3069  }
3070 
3078  // First, resolve any protorosettes
3079  for (unsigned node_idx = 0 ; node_idx < protorosette_nodes.size() ; node_idx++)
3080  {
3081  Node<SPACE_DIM>* current_node = protorosette_nodes[node_idx];
3082 
3083  // Verify that node has not been marked for deletion, and that it is still contained in four elements
3084  assert( !(current_node->IsDeleted()) );
3085  assert( current_node->rGetContainingElementIndices().size() == 4 );
3086 
3087  // Perform protorosette resolution
3088  this->PerformProtorosetteResolution(current_node);
3089  }
3090 
3091  // Finally, resolve any rosettes
3092  for (unsigned node_idx = 0 ; node_idx < rosette_nodes.size() ; node_idx++)
3093  {
3094  Node<SPACE_DIM>* current_node = rosette_nodes[node_idx];
3095 
3096  // Verify that node has not been marked for deletion, and that it is still contained in at least four elements
3097  assert( !(current_node->IsDeleted()) );
3098  assert( current_node->rGetContainingElementIndices().size() > 4 );
3099 
3100  // Perform protorosette resolution
3101  this->PerformRosetteRankDecrease(current_node);
3102  }
3103 }
3104 
3105 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
3107  unsigned indexA, unsigned indexB, c_vector<double,2> intersection)
3108 {
3118  c_vector<double, SPACE_DIM> vertexA = this->GetNode(indexA)->rGetLocation();
3119  c_vector<double, SPACE_DIM> vertexB = this->GetNode(indexB)->rGetLocation();
3120  c_vector<double, SPACE_DIM> vector_a_to_b = this->GetVectorFromAtoB(vertexA, vertexB);
3121 
3122  if (norm_2(vector_a_to_b) < 4.0*mCellRearrangementRatio*mCellRearrangementThreshold)
3123  {
3124  WARNING("Trying to merge a node onto an edge which is too small.");
3125 
3126  c_vector<double, SPACE_DIM> centre_a_and_b = vertexA + 0.5*vector_a_to_b;
3127 
3128  vertexA = centre_a_and_b - 2.0*mCellRearrangementRatio*mCellRearrangementThreshold*vector_a_to_b/norm_2(vector_a_to_b);
3129  ChastePoint<SPACE_DIM> vertex_A_point(vertexA);
3130  SetNode(indexA, vertex_A_point);
3131 
3132  vertexB = centre_a_and_b + 2.0*mCellRearrangementRatio*mCellRearrangementThreshold*vector_a_to_b/norm_2(vector_a_to_b);
3133  ChastePoint<SPACE_DIM> vertex_B_point(vertexB);
3134  SetNode(indexB, vertex_B_point);
3135 
3136  intersection = centre_a_and_b;
3137  }
3138 
3139  // Reset distances
3140  vector_a_to_b = this->GetVectorFromAtoB(vertexA, vertexB);
3141  c_vector<double,2> edge_ab_unit_vector = vector_a_to_b/norm_2(vector_a_to_b);
3142 
3143  // Reset the intersection away from vertices A and B to allow enough room for new nodes
3152  if (norm_2(intersection - vertexA) < 2.0*mCellRearrangementRatio*mCellRearrangementThreshold)
3153  {
3154  intersection = vertexA + 2.0*mCellRearrangementRatio*mCellRearrangementThreshold*edge_ab_unit_vector;
3155  }
3156  if (norm_2(intersection - vertexB) < 2.0*mCellRearrangementRatio*mCellRearrangementThreshold)
3157  {
3158  intersection = vertexB - 2.0*mCellRearrangementRatio*mCellRearrangementThreshold*edge_ab_unit_vector;
3159  }
3160  return intersection;
3161 }
3162 
3163 // Explicit instantiation
3164 template class MutableVertexMesh<1,1>;
3165 template class MutableVertexMesh<1,2>;
3166 template class MutableVertexMesh<1,3>;
3167 template class MutableVertexMesh<2,2>;
3168 template class MutableVertexMesh<2,3>;
3169 template class MutableVertexMesh<3,3>;
3170 
3171 // Serialization for Boost >= 1.36
unsigned DivideElement(VertexElement< ELEMENT_DIM, SPACE_DIM > *pElement, unsigned nodeAIndex, unsigned nodeBIndex, bool placeOriginalElementBelow=false)
void SetRosetteResolutionProbabilityPerTimestep(double rosetteResolutionProbabilityPerTimestep)
double GetRosetteResolutionProbabilityPerTimestep() const
void PerformIntersectionSwap(Node< SPACE_DIM > *pNode, unsigned elementIndex)
double GetCellRearrangementRatio() const
virtual void Clear()
Definition: VertexMesh.cpp:585
c_vector< double, 2 > WidenEdgeOrCorrectIntersectionLocationIfNecessary(unsigned indexA, unsigned indexB, c_vector< double, 2 > intersection)
std::vector< c_vector< double, SPACE_DIM > > GetLocationsOfT3Swaps()
void RemoveDeletedNodesAndElements(VertexElementMap &rElementMap)
void SetPoint(ChastePoint< SPACE_DIM > point)
Definition: Node.cpp:115
void PerformRosetteRankDecrease(Node< SPACE_DIM > *pRosetteNode)
unsigned DivideElementAlongGivenAxis(VertexElement< ELEMENT_DIM, SPACE_DIM > *pElement, c_vector< double, SPACE_DIM > axisOfDivision, bool placeOriginalElementBelow=false)
unsigned randMod(unsigned base)
Definition: Node.hpp:58
void SetAsBoundaryNode(bool value=true)
Definition: Node.cpp:127
bool CheckForT2Swaps(VertexElementMap &rElementMap)
unsigned GetNodeGlobalIndex(unsigned localIndex) const
std::vector< c_vector< double, SPACE_DIM > > GetLocationsOfT1Swaps()
unsigned DivideElementAlongShortAxis(VertexElement< ELEMENT_DIM, SPACE_DIM > *pElement, bool placeOriginalElementBelow=false)
void PerformNodeMerge(Node< SPACE_DIM > *pNodeA, Node< SPACE_DIM > *pNodeB)
void SetProtorosetteResolutionProbabilityPerTimestep(double protorosetteResolutionProbabilityPerTimestep)
bool IsBoundaryNode() const
Definition: Node.cpp:165
#define EXCEPTION(message)
Definition: Exception.hpp:143
double GetT2Threshold() const
unsigned AddNode(Node< SPACE_DIM > *pNewNode)
void ReplaceNode(Node< SPACE_DIM > *pOldNode, Node< SPACE_DIM > *pNewNode)
double GetCellRearrangementThreshold() const
void PerformVoidRemoval(Node< SPACE_DIM > *pNodeA, Node< SPACE_DIM > *pNodeB, Node< SPACE_DIM > *pNodeC)
std::set< unsigned > & rGetContainingElementIndices()
Definition: Node.cpp:301
void SetIndex(unsigned index)
Definition: Node.cpp:121
#define NEVER_REACHED
Definition: Exception.hpp:206
bool GetCheckForInternalIntersections() const
Node< SPACE_DIM > * GetNode(unsigned localIndex) const
void SetCellRearrangementThreshold(double cellRearrangementThreshold)
bool mMeshChangesDuringSimulation
double GetProtorosetteResolutionProbabilityPerTimestep() const
void PerformT3Swap(Node< SPACE_DIM > *pNode, unsigned elementIndex)
void AddNode(Node< SPACE_DIM > *pNode, const unsigned &rIndex)
std::vector< Node< SPACE_DIM > * > mNodes
virtual void SetNode(unsigned nodeIndex, ChastePoint< SPACE_DIM > point)
unsigned AddElement(VertexElement< ELEMENT_DIM, SPACE_DIM > *pNewElement)
void PerformProtorosetteResolution(Node< SPACE_DIM > *pProtorosetteNode)
void SetDeleted(unsigned index)
unsigned GetNumNodes() const
void PerformRosetteRankIncrease(Node< SPACE_DIM > *pNodeA, Node< SPACE_DIM > *pNodeB)
unsigned GetNumNodes() const
void DeleteNodePriorToReMesh(unsigned index)
double GetProtorosetteFormationProbability() const
void SetNewIndex(unsigned oldIndex, unsigned newIndex)
static RandomNumberGenerator * Instance()
void RegisterWithNodes()
#define EXPORT_TEMPLATE_CLASS_ALL_DIMS(CLASS)
void SetProtorosetteFormationProbability(double protorosetteFormationProbability)
std::vector< VertexElement< ELEMENT_DIM, SPACE_DIM > * > mElements
Definition: VertexMesh.hpp:81
virtual void HandleHighOrderJunctions(Node< SPACE_DIM > *pNodeA, Node< SPACE_DIM > *pNodeB)
void DivideEdge(Node< SPACE_DIM > *pNodeA, Node< SPACE_DIM > *pNodeB)
void SetCheckForInternalIntersections(bool checkForInternalIntersections)
const c_vector< double, SPACE_DIM > & rGetLocation() const
Definition: Node.cpp:140
void AddElement(unsigned index)
Definition: Node.cpp:269
void DeleteElementPriorToReMesh(unsigned index)
unsigned GetIndex() const
unsigned GetNumElements() const
void SetCellRearrangementRatio(double cellRearrangementRatio)
void DeleteNode(const unsigned &rIndex)
unsigned GetNumContainingElements() const
Definition: Node.cpp:313
double GetNodeLocation(unsigned localIndex, unsigned dimension) const
void PerformT1Swap(Node< SPACE_DIM > *pNodeA, Node< SPACE_DIM > *pNodeB, std::set< unsigned > &rElementsContainingNodes)
unsigned GetIndex() const
Definition: Node.cpp:159
unsigned GetNodeLocalIndex(unsigned globalIndex) const
void SetT2Threshold(double t2Threshold)
virtual void IdentifySwapType(Node< SPACE_DIM > *pNodeA, Node< SPACE_DIM > *pNodeB)
std::vector< VertexElement< ELEMENT_DIM-1, SPACE_DIM > * > mFaces
Definition: VertexMesh.hpp:84
c_vector< double, SPACE_DIM > & rGetModifiableLocation()
Definition: Node.cpp:152
void MarkAsDeleted()
Definition: Node.cpp:347
bool IsDeleted() const
Definition: Node.cpp:353
c_vector< double, SPACE_DIM > GetLastT2SwapLocation()
void PerformT2Swap(VertexElement< ELEMENT_DIM, SPACE_DIM > &rElement)
void Resize(unsigned size)