Chaste  Release::3.4
MutableMesh.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 <map>
37 #include <cstring>
38 
39 #include "MutableMesh.hpp"
40 #include "OutputFileHandler.hpp"
41 
42 //Jonathan Shewchuk's triangle and Hang Si's tetgen
43 #define REAL double
44 #define VOID void
45 #include "triangle.h"
46 #include "tetgen.h"
47 #undef REAL
48 #undef VOID
49 
50 
51 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
53  : mAddedNodes(false)
54 {
55  this->mMeshChangesDuringSimulation = true;
56 }
57 
58 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
60 {
61  this->mMeshChangesDuringSimulation = true;
62  Clear();
63  for (unsigned index=0; index<nodes.size(); index++)
64  {
65  Node<SPACE_DIM>* p_temp_node = nodes[index];
66  this->mNodes.push_back(p_temp_node);
67  }
68  mAddedNodes = true;
69  NodeMap node_map(nodes.size());
70  ReMesh(node_map);
71 }
72 
73 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
75 {
76  Clear();
77 }
78 
79 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
81 {
82  if (mDeletedNodeIndices.empty())
83  {
84  pNewNode->SetIndex(this->mNodes.size());
85  this->mNodes.push_back(pNewNode);
86  }
87  else
88  {
89  unsigned index = mDeletedNodeIndices.back();
90  pNewNode->SetIndex(index);
91  mDeletedNodeIndices.pop_back();
92  delete this->mNodes[index];
93  this->mNodes[index] = pNewNode;
94  }
95  mAddedNodes = true;
96  return pNewNode->GetIndex();
97 }
98 
99 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
101 {
102  unsigned new_elt_index;
103 
104  if (mDeletedElementIndices.empty())
105  {
106  new_elt_index = this->mElements.size();
107  this->mElements.push_back(pNewElement);
108  pNewElement->ResetIndex(new_elt_index);
109  }
110  else
111  {
112  unsigned index = mDeletedElementIndices.back();
113  pNewElement->ResetIndex(index);
114  mDeletedElementIndices.pop_back();
115  delete this->mElements[index];
116  this->mElements[index] = pNewElement;
117  }
118 
119  return pNewElement->GetIndex();
120 }
121 
122 
123 template <unsigned ELEMENT_DIM, unsigned SPACE_DIM>
125 {
126  mDeletedElementIndices.clear();
127  mDeletedBoundaryElementIndices.clear();
128  mDeletedNodeIndices.clear();
129  mAddedNodes = false;
130 
132 }
133 
134 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
136 {
137  return this->mBoundaryElements.size() - mDeletedBoundaryElementIndices.size();
138 }
139 
140 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
142 {
143  return this->mElements.size() - mDeletedElementIndices.size();
144 }
145 
146 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
148 {
149  return this->mNodes.size() - mDeletedNodeIndices.size();
150 }
151 
158 template<>
159 void MutableMesh<1, 1>::RescaleMeshFromBoundaryNode(ChastePoint<1> updatedPoint, unsigned boundaryNodeIndex)
160 {
161  assert(this->GetNode(boundaryNodeIndex)->IsBoundaryNode());
162  double scaleFactor = updatedPoint[0] / this->GetNode(boundaryNodeIndex)->GetPoint()[0];
163  double temp;
164  for (unsigned i=0; i < boundaryNodeIndex+1; i++)
165  {
166  temp = scaleFactor * this->mNodes[i]->GetPoint()[0];
167  ChastePoint<1> newPoint(temp);
168  this->mNodes[i]->SetPoint(newPoint);
169  }
170  this->RefreshMesh();
171 }
172 
173 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
176  bool concreteMove)
177 {
178  this->mNodes[index]->SetPoint(point);
179 
180  if (concreteMove)
181  {
182  for (typename Node<SPACE_DIM>::ContainingBoundaryElementIterator it = this->mNodes[index]->ContainingBoundaryElementsBegin();
183  it != this->mNodes[index]->ContainingBoundaryElementsEnd();
184  ++it)
185  {
186  try
187  {
188  this->GetBoundaryElement(*it)->CalculateWeightedDirection(this->mBoundaryElementWeightedDirections[ (*it) ],
189  this->mBoundaryElementJacobianDeterminants[ (*it) ]);
190  }
191  catch (Exception&)
192  {
193  EXCEPTION("Moving node caused a boundary element to have a non-positive Jacobian determinant");
194  }
195  }
196  for (typename Node<SPACE_DIM>::ContainingElementIterator it = this->mNodes[index]->ContainingElementsBegin();
197  it != this->mNodes[index]->ContainingElementsEnd();
198  ++it)
199  {
200  if (ELEMENT_DIM == SPACE_DIM)
201  {
202  try
203  {
204  this->GetElement(*it)->CalculateInverseJacobian(this->mElementJacobians[ (*it) ],
205  this->mElementJacobianDeterminants[ (*it) ],
206  this->mElementInverseJacobians[ (*it) ]);
207  }
208  catch (Exception&)
209  {
210  EXCEPTION("Moving node caused an element to have a non-positive Jacobian determinant");
211  }
212  }
213  else
214  {
215  c_vector<double,SPACE_DIM> previous_direction = this->mElementWeightedDirections[ (*it) ];
216 
217  this->GetElement(*it)->CalculateWeightedDirection(this->mElementWeightedDirections[ (*it) ],
218  this->mElementJacobianDeterminants[ (*it) ]);
219 
220  if ( inner_prod(previous_direction, this->mElementWeightedDirections[ (*it) ]) < 0)
221  {
222  EXCEPTION("Moving node caused an subspace element to change direction");
223  }
224 
225  }
226  }
227  }
228 }
229 
230 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
232 {
233  if (this->mNodes[index]->IsDeleted())
234  {
235  EXCEPTION("Trying to delete a deleted node");
236  }
237  unsigned target_index = (unsigned)(-1);
238  bool found_target=false;
239  for (typename Node<SPACE_DIM>::ContainingElementIterator it = this->mNodes[index]->ContainingElementsBegin();
240  !found_target && it != this->mNodes[index]->ContainingElementsEnd();
241  ++it)
242  {
243  Element <ELEMENT_DIM,SPACE_DIM>* p_element = this->GetElement(*it);
244  for (unsigned i=0; i<=ELEMENT_DIM && !found_target; i++)
245  {
246  target_index = p_element->GetNodeGlobalIndex(i);
247  try
248  {
249  MoveMergeNode(index, target_index, false);
250  found_target = true;
251  }
252  catch (Exception&)
253  {
254  // Just try the next node
255  }
256  }
257  }
258  if (!found_target)
259  {
260  EXCEPTION("Failure to delete node");
261  }
262 
263  MoveMergeNode(index, target_index);
264 }
265 
266 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
268 {
269  assert(!this->mElements[index]->IsDeleted());
270  this->mElements[index]->MarkAsDeleted();
271  mDeletedElementIndices.push_back(index);
272 
273  //Delete any nodes that are no longer attached to mesh.
274  for (unsigned node_index = 0; node_index < this->mElements[index]->GetNumNodes(); ++node_index)
275  {
276  if (this->mElements[index]->GetNode(node_index)->GetNumContainingElements() == 0u)
277  {
278  if (this->mElements[index]->GetNode(node_index)->GetNumBoundaryElements() == 0u)
279  {
280  this->mElements[index]->GetNode(node_index)->MarkAsDeleted();
281  mDeletedNodeIndices.push_back(this->mElements[index]->GetNode(node_index)->GetIndex());
282  }
283  else if (this->mElements[index]->GetNode(node_index)->GetNumBoundaryElements() == 1u && ELEMENT_DIM == 1)
284  {
285  std::set<unsigned> indices = this->mElements[index]->GetNode(node_index)->rGetContainingBoundaryElementIndices();
286  assert(indices.size() == 1u);
287  this->mBoundaryElements[*indices.begin()]->MarkAsDeleted();
288  mDeletedBoundaryElementIndices.push_back(*indices.begin());
289 
290  this->mElements[index]->GetNode(node_index)->MarkAsDeleted();
291  mDeletedNodeIndices.push_back(this->mElements[index]->GetNode(node_index)->GetIndex());
292  }
293  }
294  }
295 }
296 
297 
298 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
300 {
301  this->mNodes[index]->MarkAsDeleted();
302  mDeletedNodeIndices.push_back(index);
303 }
304 
305 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
307  unsigned targetIndex,
308  bool concreteMove)
309 {
310  if (this->mNodes[index]->IsDeleted())
311  {
312  EXCEPTION("Trying to move a deleted node");
313  }
314 
315  if (index == targetIndex)
316  {
317  EXCEPTION("Trying to merge a node with itself");
318  }
319  if (this->mNodes[index]->IsBoundaryNode())
320  {
321  if (!this->mNodes[targetIndex]->IsBoundaryNode())
322  {
323  EXCEPTION("A boundary node can only be moved on to another boundary node");
324  }
325  }
326  std::set<unsigned> unshared_element_indices;
327  std::set_difference(this->mNodes[index]->rGetContainingElementIndices().begin(),
328  this->mNodes[index]->rGetContainingElementIndices().end(),
329  this->mNodes[targetIndex]->rGetContainingElementIndices().begin(),
330  this->mNodes[targetIndex]->rGetContainingElementIndices().end(),
331  std::inserter(unshared_element_indices, unshared_element_indices.begin()));
332 
333 
334  if (unshared_element_indices.size() == this->mNodes[index]->rGetContainingElementIndices().size())
335  {
336  EXCEPTION("These nodes cannot be merged since they are not neighbours");
337  }
338 
339  std::set<unsigned> unshared_boundary_element_indices;
340  std::set_difference(this->mNodes[index]->rGetContainingBoundaryElementIndices().begin(),
341  this->mNodes[index]->rGetContainingBoundaryElementIndices().end(),
342  this->mNodes[targetIndex]->rGetContainingBoundaryElementIndices().begin(),
343  this->mNodes[targetIndex]->rGetContainingBoundaryElementIndices().end(),
344  std::inserter(unshared_boundary_element_indices, unshared_boundary_element_indices.begin()));
345 
346 
347  if (this->mNodes[index]->IsBoundaryNode())
348  {
349  if (unshared_boundary_element_indices.size()
350  == this->mNodes[index]->rGetContainingBoundaryElementIndices().size())
351  {
352  //May be redundant (only thrown in 1D tests)
353  EXCEPTION("These nodes cannot be merged since they are not neighbours on the boundary");
354  }
355  }
356 
357  this->mNodes[index]->rGetModifiableLocation() = this->mNodes[targetIndex]->rGetLocation();
358 
359  for (std::set<unsigned>::const_iterator element_iter=unshared_element_indices.begin();
360  element_iter != unshared_element_indices.end();
361  element_iter++)
362  {
363  try
364  {
365  if (SPACE_DIM == ELEMENT_DIM)
366  {
367  this->GetElement(*element_iter)->CalculateInverseJacobian(this->mElementJacobians[(*element_iter)],
368  this->mElementJacobianDeterminants[(*element_iter)],
369  this->mElementInverseJacobians[ (*element_iter) ]);
370  }
371  else
372  {
373  this->GetElement(*element_iter)->CalculateWeightedDirection(this->mElementWeightedDirections[(*element_iter)],
374  this->mElementJacobianDeterminants[(*element_iter)]);
375  }
376 
377  if (concreteMove)
378  {
379  this->GetElement(*element_iter)->ReplaceNode(this->mNodes[index], this->mNodes[targetIndex]);
380  }
381 
382  }
383  catch (Exception&)
384  {
385  EXCEPTION("Moving node caused an element to have a non-positive Jacobian determinant");
386  }
387  }
388 
389  for (std::set<unsigned>::const_iterator boundary_element_iter=
390  unshared_boundary_element_indices.begin();
391  boundary_element_iter != unshared_boundary_element_indices.end();
392  boundary_element_iter++)
393  {
394 
395  this->GetBoundaryElement(*boundary_element_iter)->CalculateWeightedDirection(this->mBoundaryElementWeightedDirections[(*boundary_element_iter)],
396  this->mBoundaryElementJacobianDeterminants[(*boundary_element_iter)]);
397 
398  if (concreteMove)
399  {
400  this->GetBoundaryElement(*boundary_element_iter)->ReplaceNode(this->mNodes[index], this->mNodes[targetIndex]);
401  }
402  }
403 
404  std::set<unsigned> shared_element_indices;
405  std::set_intersection(this->mNodes[index]->rGetContainingElementIndices().begin(),
406  this->mNodes[index]->rGetContainingElementIndices().end(),
407  this->mNodes[targetIndex]->rGetContainingElementIndices().begin(),
408  this->mNodes[targetIndex]->rGetContainingElementIndices().end(),
409  std::inserter(shared_element_indices, shared_element_indices.begin()));
410 
411  for (std::set<unsigned>::const_iterator element_iter=shared_element_indices.begin();
412  element_iter != shared_element_indices.end();
413  element_iter++)
414  {
415  if (concreteMove)
416  {
417  this->GetElement(*element_iter)->MarkAsDeleted();
418  this->mElementJacobianDeterminants[ (*element_iter) ] = 0.0; //This used to be done in MarkAsDeleted
419  mDeletedElementIndices.push_back(*element_iter);
420  }
421  else
422  {
423  this->mElementJacobianDeterminants[ (*element_iter) ] = 0.0;
424  }
425  }
426 
427 
428  std::set<unsigned> shared_boundary_element_indices;
429  std::set_intersection(this->mNodes[index]->rGetContainingBoundaryElementIndices().begin(),
430  this->mNodes[index]->rGetContainingBoundaryElementIndices().end(),
431  this->mNodes[targetIndex]->rGetContainingBoundaryElementIndices().begin(),
432  this->mNodes[targetIndex]->rGetContainingBoundaryElementIndices().end(),
433  std::inserter(shared_boundary_element_indices, shared_boundary_element_indices.begin()));
434 
435  for (std::set<unsigned>::const_iterator boundary_element_iter=shared_boundary_element_indices.begin();
436  boundary_element_iter != shared_boundary_element_indices.end();
437  boundary_element_iter++)
438  {
439  if (concreteMove)
440  {
441  this->GetBoundaryElement(*boundary_element_iter)->MarkAsDeleted();
442  this->mBoundaryElementJacobianDeterminants[ (*boundary_element_iter) ] = 0.0; //This used to be done in MarkAsDeleted
443  mDeletedBoundaryElementIndices.push_back(*boundary_element_iter);
444  }
445  else
446  {
447  this->mBoundaryElementJacobianDeterminants[ (*boundary_element_iter) ] = 0.0;
448  this->mBoundaryElementWeightedDirections[ (*boundary_element_iter) ] = zero_vector<double>(SPACE_DIM);
449  }
450  }
451 
452  if (concreteMove)
453  {
454  this->mNodes[index]->MarkAsDeleted();
455  mDeletedNodeIndices.push_back(index);
456  }
457 }
458 
459 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
463 {
464  //Check that the point is in the element
465  if (pElement->IncludesPoint(point, true) == false)
466  {
467  EXCEPTION("RefineElement could not be started (point is not in element)");
468  }
469 
470  // Add a new node from the point that is passed to RefineElement
471  unsigned new_node_index = AddNode(new Node<SPACE_DIM>(0, point.rGetLocation()));
472  // Note: the first argument is the index of the node, which is going to be
473  // overridden by AddNode, so it can safely be ignored
474 
475  // This loop constructs the extra elements which are going to fill the space
476  for (unsigned i = 0; i < ELEMENT_DIM; i++)
477  {
478 
479  // First, make a copy of the current element making sure we update its index
480  unsigned new_elt_index;
481  if (mDeletedElementIndices.empty())
482  {
483  new_elt_index = this->mElements.size();
484  }
485  else
486  {
487  new_elt_index = mDeletedElementIndices.back();
488  mDeletedElementIndices.pop_back();
489  }
490 
491  Element<ELEMENT_DIM,SPACE_DIM>* p_new_element=
492  new Element<ELEMENT_DIM,SPACE_DIM>(*pElement, new_elt_index);
493 
494  // Second, update the node in the element with the new one
495  p_new_element->UpdateNode(ELEMENT_DIM-1-i, this->mNodes[new_node_index]);
496 
497  // Third, add the new element to the set
498  if ((unsigned) new_elt_index == this->mElements.size())
499  {
500  this->mElements.push_back(p_new_element);
501  }
502  else
503  {
504  delete this->mElements[new_elt_index];
505  this->mElements[new_elt_index] = p_new_element;
506  }
507  }
508 
509  // Lastly, update the last node in the element to be refined
510  pElement->UpdateNode(ELEMENT_DIM, this->mNodes[new_node_index]);
511 
512  return new_node_index;
513 }
514 
515 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
517 {
518  if (!this->mNodes[index]->IsBoundaryNode() )
519  {
520  EXCEPTION(" You may only delete a boundary node ");
521  }
522 
523  this->mNodes[index]->MarkAsDeleted();
524  mDeletedNodeIndices.push_back(index);
525 
526  // Update the boundary node vector
527  typename std::vector<Node<SPACE_DIM>*>::iterator b_node_iter
528  = std::find(this->mBoundaryNodes.begin(), this->mBoundaryNodes.end(), this->mNodes[index]);
529  this->mBoundaryNodes.erase(b_node_iter);
530 
531  // Remove boundary elements containing this node
532  std::set<unsigned> boundary_element_indices = this->mNodes[index]->rGetContainingBoundaryElementIndices();
533  std::set<unsigned>::const_iterator boundary_element_indices_iterator = boundary_element_indices.begin();
534  while (boundary_element_indices_iterator != boundary_element_indices.end())
535  {
536  BoundaryElement<ELEMENT_DIM-1, SPACE_DIM>* p_boundary_element = this->GetBoundaryElement(*boundary_element_indices_iterator);
537  p_boundary_element->MarkAsDeleted();
538  mDeletedBoundaryElementIndices.push_back(*boundary_element_indices_iterator);
539  boundary_element_indices_iterator++;
540  }
541 
542  // Remove elements containing this node
543  std::set<unsigned> element_indices = this->mNodes[index]->rGetContainingElementIndices();
544  std::set<unsigned>::const_iterator element_indices_iterator = element_indices.begin();
545  while (element_indices_iterator != element_indices.end())
546  {
547  Element<ELEMENT_DIM, SPACE_DIM>* p_element = this->GetElement(*element_indices_iterator);
548  for (unsigned i=0; i<p_element->GetNumNodes(); i++)
549  {
550  Node<SPACE_DIM>* p_node = p_element->GetNode(i);
551  if (!p_node->IsDeleted())
552  {
553  p_node->SetAsBoundaryNode();
554  // Update the boundary node vector
555  this->mBoundaryNodes.push_back(p_node);
556  }
557  }
558  p_element->MarkAsDeleted();
559  mDeletedElementIndices.push_back(p_element->GetIndex());
560  element_indices_iterator++;
561  }
562 }
563 
564 template <unsigned ELEMENT_DIM, unsigned SPACE_DIM>
566 {
567  assert(!mAddedNodes);
568  map.Resize(this->GetNumAllNodes());
569 
570  std::vector<Element<ELEMENT_DIM, SPACE_DIM> *> live_elements;
571 
572  for (unsigned i=0; i<this->mElements.size(); i++)
573  {
574  assert(i==this->mElements[i]->GetIndex()); // We need this to be true to be able to reindex the Jacobian cache
575  if (this->mElements[i]->IsDeleted())
576  {
577  delete this->mElements[i];
578  }
579  else
580  {
581  live_elements.push_back(this->mElements[i]);
582 
583  unsigned this_element_index = this->mElements[i]->GetIndex();
584  if (SPACE_DIM == ELEMENT_DIM)
585  {
586  this->mElementJacobians[live_elements.size()-1] = this->mElementJacobians[this_element_index];
587  this->mElementInverseJacobians[live_elements.size()-1] = this->mElementInverseJacobians[this_element_index];
588  }
589  else
590  {
591  this->mElementWeightedDirections[live_elements.size()-1] = this->mElementWeightedDirections[this_element_index];
592  }
593  this->mElementJacobianDeterminants[live_elements.size()-1] = this->mElementJacobianDeterminants[this_element_index];
594  }
595  }
596 
597  assert(mDeletedElementIndices.size() == this->mElements.size()-live_elements.size());
598  mDeletedElementIndices.clear();
599  this->mElements = live_elements;
600  unsigned num_elements = this->mElements.size();
601 
602  if (SPACE_DIM == ELEMENT_DIM)
603  {
604  this->mElementJacobians.resize(num_elements);
605  this->mElementInverseJacobians.resize(num_elements);
606  }
607  else
608  {
609  this->mElementWeightedDirections.resize(num_elements);
610  }
611  this->mElementJacobianDeterminants.resize(num_elements);
612 
613  std::vector<Node<SPACE_DIM> *> live_nodes;
614  for (unsigned i=0; i<this->mNodes.size(); i++)
615  {
616  if (this->mNodes[i]->IsDeleted())
617  {
618  delete this->mNodes[i];
619  map.SetDeleted(i);
620  }
621  else
622  {
623  live_nodes.push_back(this->mNodes[i]);
624  // the nodes will have their index set to be the index into the live_nodes
625  // vector further down
626  map.SetNewIndex(i, (unsigned)(live_nodes.size()-1));
627  }
628  }
629 
630  assert(mDeletedNodeIndices.size() == this->mNodes.size()-live_nodes.size());
631  this->mNodes = live_nodes;
632  mDeletedNodeIndices.clear();
633 
634  std::vector<BoundaryElement<ELEMENT_DIM-1, SPACE_DIM> *> live_boundary_elements;
635  for (unsigned i=0; i<this->mBoundaryElements.size(); i++)
636  {
637  if (this->mBoundaryElements[i]->IsDeleted())
638  {
639  delete this->mBoundaryElements[i];
640  }
641  else
642  {
643  live_boundary_elements.push_back(this->mBoundaryElements[i]);
644 
645  this->mBoundaryElementWeightedDirections[live_boundary_elements.size()-1] = this->mBoundaryElementWeightedDirections[this->mBoundaryElements[i]->GetIndex()];
646  this->mBoundaryElementJacobianDeterminants[live_boundary_elements.size()-1] = this->mBoundaryElementJacobianDeterminants[this->mBoundaryElements[i]->GetIndex()];
647  }
648  }
649 
650  assert(mDeletedBoundaryElementIndices.size() == this->mBoundaryElements.size()-live_boundary_elements.size());
651  this->mBoundaryElements = live_boundary_elements;
652  mDeletedBoundaryElementIndices.clear();
653 
654  unsigned num_boundary_elements = this->mBoundaryElements.size();
655 
656  this->mBoundaryElementWeightedDirections.resize(num_boundary_elements);
657  this->mBoundaryElementJacobianDeterminants.resize(num_boundary_elements);
658 
659  for (unsigned i=0; i<this->mNodes.size(); i++)
660  {
661  this->mNodes[i]->SetIndex(i);
662  }
663 
664  for (unsigned i=0; i<this->mElements.size(); i++)
665  {
666 
667  this->mElements[i]->ResetIndex(i);
668  }
669 
670  for (unsigned i=0; i<this->mBoundaryElements.size(); i++)
671  {
672  this->mBoundaryElements[i]->ResetIndex(i);
673  }
674 }
675 
676 template <unsigned ELEMENT_DIM, unsigned SPACE_DIM>
678 {
679  // Make sure that we are in the correct dimension - this code will be eliminated at compile time
680  #define COVERAGE_IGNORE
681  assert( ELEMENT_DIM == SPACE_DIM );
682  #undef COVERAGE_IGNORE
683 
684  // Avoid some triangle/tetgen errors: need at least four
685  // nodes for tetgen, and at least three for triangle
686  if (GetNumNodes() <= SPACE_DIM)
687  {
688  EXCEPTION("The number of nodes must exceed the spatial dimension.");
689  }
690 
691  // Make sure the map is big enough
692  map.Resize(this->GetNumAllNodes());
693  if (mAddedNodes || !mDeletedNodeIndices.empty())
694  {
695  // Size of mesh is about to change
696  if (this->mpDistributedVectorFactory)
697  {
698  delete this->mpDistributedVectorFactory;
699  this->mpDistributedVectorFactory = new DistributedVectorFactory(this->GetNumNodes());
700  }
701  }
702  if (SPACE_DIM==1)
703  {
704  // Store the node locations
705  std::vector<c_vector<double, SPACE_DIM> > old_node_locations;
706  unsigned new_index = 0;
707  for (unsigned i=0; i<this->GetNumAllNodes(); i++)
708  {
709  if (this->mNodes[i]->IsDeleted())
710  {
711  map.SetDeleted(i);
712  }
713  else
714  {
715  map.SetNewIndex(i, new_index);
716  old_node_locations.push_back(this->mNodes[i]->rGetLocation());
717  new_index++;
718  }
719  }
720 
721  // Remove current data
722  Clear();
723 
724  // Construct the nodes and boundary nodes
725  for (unsigned node_index=0; node_index<old_node_locations.size(); node_index++)
726  {
727  Node<SPACE_DIM>* p_node = new Node<SPACE_DIM>(node_index, old_node_locations[node_index], false);
728  this->mNodes.push_back(p_node);
729 
730  // As we're in 1D, the boundary nodes are simply at either end of the mesh
731  if ( node_index==0 || node_index==old_node_locations.size()-1 )
732  {
733  this->mBoundaryNodes.push_back(p_node);
734  }
735  }
736 
737  // Create a map between node indices and node locations
738  std::map<double, unsigned> location_index_map;
739  for (unsigned i=0; i<this->mNodes.size(); i++)
740  {
741  location_index_map[this->mNodes[i]->rGetLocation()[0]] = this->mNodes[i]->GetIndex();
742  }
743 
744  // Use this map to generate a vector of node indices that are ordered spatially
745  std::vector<unsigned> node_indices_ordered_spatially;
746  for (std::map<double, unsigned>::iterator iter = location_index_map.begin();
747  iter != location_index_map.end();
748  ++iter)
749  {
750  node_indices_ordered_spatially.push_back(iter->second);
751  }
752 
753  // Construct the elements
754  this->mElements.reserve(old_node_locations.size()-1);
755  for (unsigned element_index=0; element_index<old_node_locations.size()-1; element_index++)
756  {
757  std::vector<Node<SPACE_DIM>*> nodes;
758  for (unsigned j=0; j<2; j++)
759  {
760  unsigned global_node_index = node_indices_ordered_spatially[element_index + j];
761  assert(global_node_index < this->mNodes.size());
762  nodes.push_back(this->mNodes[global_node_index]);
763  }
764  this->mElements.push_back(new Element<ELEMENT_DIM, SPACE_DIM>(element_index, nodes));
765  }
766 
767  // Construct the two boundary elements - as we're in 1D, these are simply at either end of the mesh
768  std::vector<Node<SPACE_DIM>*> nodes;
769  nodes.push_back(this->mNodes[0]);
770  this->mBoundaryElements.push_back(new BoundaryElement<ELEMENT_DIM-1, SPACE_DIM>(0, nodes));
771 
772  nodes.clear();
773  nodes.push_back(this->mNodes[old_node_locations.size()-1]);
774  this->mBoundaryElements.push_back(new BoundaryElement<ELEMENT_DIM-1, SPACE_DIM>(1, nodes));
775 
776  this->RefreshJacobianCachedData();
777  }
778  else if (SPACE_DIM==2) // In 2D, remesh using triangle via library calls
779  {
780  struct triangulateio mesher_input, mesher_output;
781  this->InitialiseTriangulateIo(mesher_input);
782  this->InitialiseTriangulateIo(mesher_output);
783 
784  this->ExportToMesher(map, mesher_input);
785 
786  // Library call
787  triangulate((char*)"Qze", &mesher_input, &mesher_output, NULL);
788 
789  this->ImportFromMesher(mesher_output, mesher_output.numberoftriangles, mesher_output.trianglelist, mesher_output.numberofedges, mesher_output.edgelist, mesher_output.edgemarkerlist);
790 
791  //Tidy up triangle
792  this->FreeTriangulateIo(mesher_input);
793  this->FreeTriangulateIo(mesher_output);
794  }
795  else // in 3D, remesh using tetgen
796  {
797 
798  class tetgen::tetgenio mesher_input, mesher_output;
799 
800  this->ExportToMesher(map, mesher_input);
801 
802  // Library call
803  tetgen::tetrahedralize((char*)"Qz", &mesher_input, &mesher_output);
804 
805  this->ImportFromMesher(mesher_output, mesher_output.numberoftetrahedra, mesher_output.tetrahedronlist, mesher_output.numberoftrifaces, mesher_output.trifacelist, NULL);
806  }
807 }
808 
809 template <unsigned ELEMENT_DIM, unsigned SPACE_DIM>
811 {
812  NodeMap map(GetNumNodes());
813  ReMesh(map);
814 }
815 
816 template <unsigned ELEMENT_DIM, unsigned SPACE_DIM>
817 std::vector<c_vector<unsigned, 5> > MutableMesh<ELEMENT_DIM, SPACE_DIM>::SplitLongEdges(double cutoffLength)
818 {
819  assert(ELEMENT_DIM == 2);
820  assert(SPACE_DIM == 3);
821 
822  std::vector<c_vector<unsigned, 5> > history;
823 
824 
825  bool long_edge_exists = true;
826 
827  while(long_edge_exists)
828  {
829  std::set<std::pair<unsigned, unsigned> > long_edges;
830 
831  // Loop over elements to check for Long edges
832  for (typename AbstractTetrahedralMesh<ELEMENT_DIM, SPACE_DIM>::ElementIterator elem_iter = this->GetElementIteratorBegin();
833  elem_iter != this->GetElementIteratorEnd();
834  ++elem_iter)
835  {
836  unsigned num_nodes = ELEMENT_DIM+1;
837 
838  // Loop over element vertices
839  for (unsigned local_index=0; local_index<num_nodes; local_index++)
840  {
841  // Find locations of current node (node a) and anticlockwise node (node b)
842  Node<SPACE_DIM>* p_node_a = elem_iter->GetNode(local_index);
843  unsigned local_index_plus_one = (local_index+1)%num_nodes;
844  Node<SPACE_DIM>* p_node_b = elem_iter->GetNode(local_index_plus_one);
845 
846  // Find distance between nodes
847  double distance_between_nodes = this->GetDistanceBetweenNodes(p_node_a->GetIndex(), p_node_b->GetIndex());
848 
849  if (distance_between_nodes > cutoffLength)
850  {
851  if (p_node_a->GetIndex() < p_node_b->GetIndex())
852  {
853  std::pair<unsigned, unsigned> long_edge(p_node_a->GetIndex(),p_node_b->GetIndex());
854  long_edges.insert(long_edge);
855  }
856  else
857  {
858  std::pair<unsigned, unsigned> long_edge(p_node_b->GetIndex(),p_node_a->GetIndex());
859  long_edges.insert(long_edge);
860  }
861  }
862  }
863  }
864 
865  if (long_edges.size() > 0) //Split the edges in decreasing order.
866  {
867  while (long_edges.size() > 0)
868  {
869  double longest_edge = 0.0;
870  std::set<std::pair<unsigned, unsigned> >::iterator longest_edge_iter;
871 
872  //Find the longest edge in the set and split it
873  for (std::set<std::pair<unsigned, unsigned> >::iterator edge_iter = long_edges.begin();
874  edge_iter != long_edges.end();
875  ++edge_iter)
876  {
877  unsigned node_a_global_index = edge_iter->first;
878  unsigned node_b_global_index = edge_iter->second;
879 
880  double distance_between_nodes = this->GetDistanceBetweenNodes(node_a_global_index, node_b_global_index);
881 
882  if (distance_between_nodes > longest_edge)
883  {
884  longest_edge = distance_between_nodes;
885  longest_edge_iter = edge_iter;
886  }
887  }
888  assert(longest_edge >0);
889 
890  c_vector<unsigned, 3> new_node_index = SplitEdge(this->GetNode(longest_edge_iter->first), this->GetNode(longest_edge_iter->second));
891 
892  c_vector<unsigned, 5> node_set;
893  node_set(0) = new_node_index[0];
894  node_set(1) = longest_edge_iter->first;
895  node_set(2) = longest_edge_iter->second;
896  node_set(3) = new_node_index[1];
897  node_set(4) = new_node_index[2];
898  history.push_back(node_set);
899 
900  // Delete pair from set
901  long_edges.erase(*longest_edge_iter);
902  }
903  }
904  else
905  {
906  long_edge_exists = false;
907  }
908  }
909 
910  return history;
911 }
912 
913 template <unsigned ELEMENT_DIM, unsigned SPACE_DIM>
915 {
916  c_vector<unsigned, 3> new_node_index_vector;
917 
918  std::set<unsigned> elements_of_node_a = pNodeA->rGetContainingElementIndices();
919  std::set<unsigned> elements_of_node_b = pNodeB->rGetContainingElementIndices();
920 
921  std::set<unsigned> intersection_elements;
922  std::set_intersection(elements_of_node_a.begin(), elements_of_node_a.end(),
923  elements_of_node_b.begin(), elements_of_node_b.end(),
924  std::inserter(intersection_elements, intersection_elements.begin()));
925 
926  // Create the new node
927  c_vector<double, SPACE_DIM> new_node_location = pNodeA->rGetLocation() + 0.5*this->GetVectorFromAtoB(pNodeA->rGetLocation(), pNodeB->rGetLocation());
928 
929  bool is_boundary_node = intersection_elements.size() == 1; // If only in one element then its on the boundary
930 
931  Node<SPACE_DIM>* p_new_node = new Node<SPACE_DIM>(0u,new_node_location,is_boundary_node); // Index is rewritten once added to mesh
932 
933  unsigned new_node_index = this->AddNode(p_new_node);
934 
935  new_node_index_vector[0] = new_node_index;
936 
937  unsigned counter = 1;
938 
939  for (std::set<unsigned>::const_iterator it = intersection_elements.begin(); it != intersection_elements.end(); ++it)
940  {
941  unsigned elementIndex = *it;
942 
943  Element<ELEMENT_DIM,SPACE_DIM>* p_original_element = this->GetElement(elementIndex);
944 
945  // First, make a copy of the current element and assign an unused index
946  Element<ELEMENT_DIM,SPACE_DIM>* p_new_element = new Element<ELEMENT_DIM,SPACE_DIM>(*p_original_element, UINT_MAX);
947 
948  // Second, add the new element to the set of existing elements. This method will assign a proper index to the element.
949  AddElement(p_new_element);
950 
951  // Third, update node a in the element with the new one
952  p_new_element->ReplaceNode(pNodeA, this->mNodes[new_node_index]);
953 
954  // Last, update node b in the original element with the new one
955  p_original_element->ReplaceNode(pNodeB, this->mNodes[new_node_index]);
956 
957  //Add node in both of these elements to new_node_index_vector (this enables us to add a new spring in the MeshBasedCellPopulation
958  unsigned other_node_index = UNSIGNED_UNSET;
959 
960  if ( (p_original_element->GetNodeGlobalIndex(0) != new_node_index) &&
961  (p_original_element->GetNodeGlobalIndex(0) != pNodeA->GetIndex() ) )
962  {
963  other_node_index = p_original_element->GetNodeGlobalIndex(0);
964  }
965  else if ( (p_original_element->GetNodeGlobalIndex(1) != new_node_index) &&
966  (p_original_element->GetNodeGlobalIndex(1) != pNodeA->GetIndex() ) )
967  {
968  other_node_index = p_original_element->GetNodeGlobalIndex(1);
969  }
970  else if ( (p_original_element->GetNodeGlobalIndex(2) != new_node_index) &&
971  (p_original_element->GetNodeGlobalIndex(2) != pNodeA->GetIndex() ) )
972  {
973  other_node_index = p_original_element->GetNodeGlobalIndex(2);
974  }
975  else
976  {
978  }
979  new_node_index_vector[counter] = other_node_index;
980  counter++;
981  }
982 
983  assert(counter<4);
984  assert(counter>1);// need to be in at least one element
985 
986  if (counter == 2) // only one new element
987  {
988  new_node_index_vector[2] = UNSIGNED_UNSET;
989  }
990 
991  return new_node_index_vector;
992 }
993 
994 template <unsigned ELEMENT_DIM, unsigned SPACE_DIM>
996 {
997  assert(ELEMENT_DIM == SPACE_DIM);
998  unsigned num_nodes = pElement->GetNumNodes();
999  std::set<unsigned> neighbouring_elements_indices;
1000  std::set< Element<ELEMENT_DIM,SPACE_DIM> *> neighbouring_elements;
1001  std::set<unsigned> neighbouring_nodes_indices;
1002 
1003  // Form a set of neighbouring elements via the nodes
1004  for (unsigned i=0; i<num_nodes; i++)
1005  {
1006  Node<SPACE_DIM>* p_node = pElement->GetNode(i);
1007  neighbouring_elements_indices = p_node->rGetContainingElementIndices();
1008  for (std::set<unsigned>::const_iterator it = neighbouring_elements_indices.begin();
1009  it != neighbouring_elements_indices.end();
1010  ++it)
1011  {
1012  neighbouring_elements.insert(this->GetElement(*it));
1013  }
1014  }
1015  neighbouring_elements.erase(pElement);
1016 
1017  // For each neighbouring element find the supporting nodes
1018  typedef typename std::set<Element<ELEMENT_DIM,SPACE_DIM> *>::const_iterator ElementIterator;
1019 
1020  for (ElementIterator it = neighbouring_elements.begin();
1021  it != neighbouring_elements.end();
1022  ++it)
1023  {
1024  for (unsigned i=0; i<num_nodes; i++)
1025  {
1026  neighbouring_nodes_indices.insert((*it)->GetNodeGlobalIndex(i));
1027  }
1028  }
1029 
1030  // Remove the nodes that support this element
1031  for (unsigned i = 0; i < num_nodes; i++)
1032  {
1033  neighbouring_nodes_indices.erase(pElement->GetNodeGlobalIndex(i));
1034  }
1035 
1036  // Get the circumsphere information
1037  c_vector<double, SPACE_DIM+1> this_circum_centre;
1038 
1039  this_circum_centre = pElement->CalculateCircumsphere(this->mElementJacobians[pElement->GetIndex()], this->mElementInverseJacobians[pElement->GetIndex()]);
1040 
1041  // Copy the actualy circumcentre into a smaller vector
1042  c_vector<double, ELEMENT_DIM> circum_centre;
1043  for (unsigned i=0; i<ELEMENT_DIM; i++)
1044  {
1045  circum_centre[i] = this_circum_centre[i];
1046  }
1047 
1048  for (std::set<unsigned>::const_iterator it = neighbouring_nodes_indices.begin();
1049  it != neighbouring_nodes_indices.end();
1050  ++it)
1051  {
1052  c_vector<double, ELEMENT_DIM> node_location = this->GetNode(*it)->rGetLocation();
1053 
1054  // Calculate vector from circumcenter to node
1055  node_location -= circum_centre;
1056 
1057  // This is to calculate the squared distance betweeen them
1058  double squared_distance = inner_prod(node_location, node_location);
1059 
1060  // If the squared idstance is less than the elements circum-radius(squared),
1061  // then the Voronoi property is violated.
1062  if (squared_distance < this_circum_centre[ELEMENT_DIM])
1063  {
1064  // We know the node is inside the circumsphere, but we don't know how far
1065  double radius = sqrt(this_circum_centre[ELEMENT_DIM]);
1066  double distance = radius - sqrt(squared_distance);
1067 
1068  // If the node penetration is greater than supplied maximum penetration factor
1069  if (distance/radius > maxPenetration)
1070  {
1071  return false;
1072  }
1073  }
1074  }
1075  return true;
1076 }
1077 
1078 template <unsigned ELEMENT_DIM, unsigned SPACE_DIM>
1080 {
1081  // Looping through all the elements in the mesh
1083  for (unsigned i=0; i<this->mElements.size(); i++)
1084  {
1085  // Check if the element is not deleted
1086  if (!this->mElements[i]->IsDeleted())
1087  {
1088  // Checking the Voronoi of the Element
1089  if (CheckIsVoronoi(this->mElements[i], maxPenetration) == false)
1090  {
1091  return false;
1092  }
1093  }
1094  }
1095  return true;
1096 }
1097 
1098 
1100 // Explicit instantiation
1102 
1103 template class MutableMesh<1,1>;
1104 template class MutableMesh<1,2>;
1105 template class MutableMesh<1,3>;
1106 template class MutableMesh<2,2>;
1107 template class MutableMesh<2,3>;
1108 template class MutableMesh<3,3>;
1109 
1110 
1111 // Serialization for Boost >= 1.36
std::vector< c_vector< unsigned, 5 > > SplitLongEdges(double cutoffLength)
c_vector< double, SPACE_DIM+1 > CalculateCircumsphere(c_matrix< double, SPACE_DIM, ELEMENT_DIM > &rJacobian, c_matrix< double, ELEMENT_DIM, SPACE_DIM > &rInverseJacobian)
Definition: Element.cpp:118
Definition: Node.hpp:58
c_vector< double, DIM > & rGetLocation()
Definition: ChastePoint.cpp:76
void SetAsBoundaryNode(bool value=true)
Definition: Node.cpp:127
unsigned GetNodeGlobalIndex(unsigned localIndex) const
void DeleteNodePriorToReMesh(unsigned index)
void SetIndex(unsigned index)
void UpdateNode(const unsigned &rIndex, Node< SPACE_DIM > *pNode)
Definition: Element.cpp:89
void ResetIndex(unsigned index)
Definition: Element.cpp:104
#define EXCEPTION(message)
Definition: Exception.hpp:143
unsigned RefineElement(Element< ELEMENT_DIM, SPACE_DIM > *pElement, ChastePoint< SPACE_DIM > point)
void RescaleMeshFromBoundaryNode(ChastePoint< 1 > updatedPoint, unsigned boundaryNodeIndex)
void ReplaceNode(Node< SPACE_DIM > *pOldNode, Node< SPACE_DIM > *pNewNode)
void ReIndex(NodeMap &map)
bool CheckIsVoronoi(Element< ELEMENT_DIM, SPACE_DIM > *pElement, double maxPenetration)
std::set< unsigned > & rGetContainingElementIndices()
Definition: Node.cpp:301
void SetIndex(unsigned index)
Definition: Node.cpp:121
#define NEVER_REACHED
Definition: Exception.hpp:206
virtual void SetNode(unsigned index, ChastePoint< SPACE_DIM > point, bool concreteMove=true)
unsigned GetNumElements() const
virtual unsigned AddNode(Node< SPACE_DIM > *pNewNode)
Definition: MutableMesh.cpp:80
void SetNewIndex(unsigned oldIndex, unsigned newIndex)
Definition: NodeMap.cpp:66
Node< SPACE_DIM > * GetNode(unsigned localIndex) const
void MarkAsDeleted()
Definition: Element.cpp:74
unsigned GetNumNodes() const
virtual void DeleteNode(unsigned index)
bool mMeshChangesDuringSimulation
unsigned GetNumNodes() const
void SetDeleted(unsigned index)
Definition: NodeMap.cpp:75
const unsigned UNSIGNED_UNSET
Definition: Exception.hpp:52
virtual void DeleteElement(unsigned index)
#define EXPORT_TEMPLATE_CLASS_ALL_DIMS(CLASS)
unsigned AddElement(Element< ELEMENT_DIM, SPACE_DIM > *pNewElement)
const c_vector< double, SPACE_DIM > & rGetLocation() const
Definition: Node.cpp:140
void MoveMergeNode(unsigned index, unsigned targetIndex, bool concreteMove=true)
virtual void Clear()
unsigned GetIndex() const
bool IncludesPoint(const ChastePoint< SPACE_DIM > &rTestPoint, bool strict=false)
Definition: Element.cpp:313
unsigned GetNumBoundaryElements() const
unsigned GetIndex() const
Definition: Node.cpp:159
c_vector< unsigned, 3 > SplitEdge(Node< SPACE_DIM > *pNodeA, Node< SPACE_DIM > *pNodeB)
bool IsDeleted() const
Definition: Node.cpp:353
void DeleteBoundaryNodeAt(unsigned index)
virtual ~MutableMesh()
Definition: MutableMesh.cpp:74
void Resize(unsigned size)
Definition: NodeMap.cpp:52