00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029 #include "MutableMesh.hpp"
00030
00031
00032 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00033 MutableMesh<ELEMENT_DIM, SPACE_DIM>::MutableMesh()
00034 {
00035 mAddedNodes = false;
00036 }
00037
00038 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00039 MutableMesh<ELEMENT_DIM, SPACE_DIM>::MutableMesh(std::vector<Node<SPACE_DIM> *> nodes)
00040 {
00041 Clear();
00042 for (unsigned index=0; index<nodes.size(); index++)
00043 {
00044 Node<SPACE_DIM>* temp_node = nodes[index];
00045 this->mNodes.push_back(temp_node);
00046 }
00047 mAddedNodes = true;
00048 NodeMap node_map(nodes.size());
00049 ReMesh(node_map);
00050 }
00051
00052 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00053 MutableMesh<ELEMENT_DIM, SPACE_DIM>::~MutableMesh()
00054 {
00055 Clear();
00056 }
00057
00058
00059 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00060 unsigned MutableMesh<ELEMENT_DIM, SPACE_DIM>::AddNode(Node<SPACE_DIM> *pNewNode)
00061 {
00062
00063 if (mDeletedNodeIndices.empty())
00064 {
00065 pNewNode->SetIndex(this->mNodes.size());
00066 this->mNodes.push_back(pNewNode);
00067 }
00068 else
00069 {
00070 unsigned index=mDeletedNodeIndices.back();
00071 pNewNode->SetIndex(index);
00072 mDeletedNodeIndices.pop_back();
00073 delete this->mNodes[index];
00074 this->mNodes[index] = pNewNode;
00075 }
00076 mAddedNodes = true;
00077 return pNewNode->GetIndex();
00078 }
00079
00080 template <unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00081 void MutableMesh<ELEMENT_DIM, SPACE_DIM>::Clear()
00082 {
00083 mDeletedElementIndices.clear();
00084 mDeletedBoundaryElementIndices.clear();
00085 mDeletedNodeIndices.clear();
00086 mAddedNodes = false;
00087
00088 TetrahedralMesh<ELEMENT_DIM, SPACE_DIM>::Clear();
00089 }
00090
00091 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00092 unsigned MutableMesh<ELEMENT_DIM, SPACE_DIM>::GetNumBoundaryElements() const
00093 {
00094 return this->mBoundaryElements.size() - mDeletedBoundaryElementIndices.size();
00095 }
00096
00097
00098 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00099 unsigned MutableMesh<ELEMENT_DIM, SPACE_DIM>::GetNumElements() const
00100 {
00101 return this->mElements.size() - mDeletedElementIndices.size();
00102 }
00103
00104
00106 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00107 unsigned MutableMesh<ELEMENT_DIM, SPACE_DIM>::GetNumNodes() const
00108 {
00109 return this->mNodes.size() - mDeletedNodeIndices.size();
00110 }
00111
00112 template<>
00113 void MutableMesh<1, 1>::RescaleMeshFromBoundaryNode(ChastePoint<1> updatedPoint, unsigned boundaryNodeIndex)
00114 {
00115 assert(this->GetNode(boundaryNodeIndex)->IsBoundaryNode());
00116 double scaleFactor = updatedPoint[0] / this->GetNode(boundaryNodeIndex)->GetPoint()[0];
00117 double temp;
00118 for (unsigned i=0; i < boundaryNodeIndex+1; i++)
00119 {
00120 temp = scaleFactor * this->mNodes[i]->GetPoint()[0];
00121 ChastePoint<1> newPoint(temp);
00122 this->mNodes[i]->SetPoint(newPoint);
00123 }
00124 this->RefreshMesh();
00125 }
00126
00134 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00135 void MutableMesh<ELEMENT_DIM, SPACE_DIM>::SetNode(unsigned index,
00136 ChastePoint<SPACE_DIM> point,
00137 bool concreteMove)
00138 {
00139 this->mNodes[index]->SetPoint(point);
00140
00141 if (concreteMove)
00142 {
00143 for (typename Node<SPACE_DIM>::ContainingElementIterator it = this->mNodes[index]->ContainingElementsBegin();
00144 it != this->mNodes[index]->ContainingElementsEnd();
00145 ++it)
00146 {
00147 if (ELEMENT_DIM == SPACE_DIM)
00148 {
00149 try
00150 {
00151 GetElement(*it)->CalculateInverseJacobian(this->mElementJacobians[ (*it) ],
00152 this->mElementJacobianDeterminants[ (*it) ],
00153 this->mElementInverseJacobians[ (*it) ]);
00154 }
00155 catch (Exception e)
00156 {
00157 EXCEPTION("Moving node caused an element to have a non-positive Jacobian determinant");
00158 }
00159 }
00160 else
00161 {
00162 c_vector<double,SPACE_DIM> previous_direction = this->mElementWeightedDirections[ (*it) ];
00163
00164 GetElement(*it)->CalculateWeightedDirection(this->mElementWeightedDirections[ (*it) ],
00165 this->mElementJacobianDeterminants[ (*it) ]);
00166
00167 if ( inner_prod(previous_direction, this->mElementWeightedDirections[ (*it) ]) < 0)
00168 {
00169 EXCEPTION("Moving node caused an subspace element to change direction");
00170 }
00171
00172 }
00173 }
00174 for (typename Node<SPACE_DIM>::ContainingBoundaryElementIterator it = this->mNodes[index]->ContainingBoundaryElementsBegin();
00175 it != this->mNodes[index]->ContainingBoundaryElementsEnd();
00176 ++it)
00177 {
00178 try
00179 {
00180 GetBoundaryElement(*it)->CalculateWeightedDirection(this->mBoundaryElementWeightedDirections[ (*it) ],
00181 this->mBoundaryElementJacobianDeterminants[ (*it) ]);
00182 }
00183 catch (Exception e)
00184 {
00185 EXCEPTION("Moving node caused a boundary element to have a non-positive Jacobian determinant");
00186 }
00187 }
00188 }
00189 }
00190
00198 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00199 void MutableMesh<ELEMENT_DIM, SPACE_DIM>::DeleteNode(unsigned index)
00200 {
00201 if (this->mNodes[index]->IsDeleted())
00202 {
00203 EXCEPTION("Trying to delete a deleted node");
00204 }
00205 unsigned target_index = (unsigned)(-1);
00206 bool found_target=false;
00207 for (typename Node<SPACE_DIM>::ContainingElementIterator it = this->mNodes[index]->ContainingElementsBegin();
00208 !found_target && it != this->mNodes[index]->ContainingElementsEnd();
00209 ++it)
00210 {
00211 Element <ELEMENT_DIM,SPACE_DIM> *p_element = GetElement(*it);
00212 for (unsigned i=0; i<=ELEMENT_DIM && !found_target; i++)
00213 {
00214 target_index = p_element->GetNodeGlobalIndex(i);
00215 try
00216 {
00217 MoveMergeNode(index, target_index, false);
00218 found_target = true;
00219 }
00220 catch (Exception e)
00221 {
00222
00223 }
00224 }
00225 }
00226 if (!found_target)
00227 {
00228 EXCEPTION("Failure to delete node");
00229 }
00230
00231 MoveMergeNode(index, target_index);
00232 }
00233
00242 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00243 void MutableMesh<ELEMENT_DIM, SPACE_DIM>::DeleteNodePriorToReMesh(unsigned index)
00244 {
00245 #define COVERAGE_IGNORE
00246
00247 assert(SPACE_DIM==2 || SPACE_DIM==3);
00248 #undef COVERAGE_IGNORE
00249 this->mNodes[index]->MarkAsDeleted();
00250 mDeletedNodeIndices.push_back(index);
00251 }
00252
00262 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00263 void MutableMesh<ELEMENT_DIM, SPACE_DIM>::MoveMergeNode(unsigned index,
00264 unsigned targetIndex,
00265 bool concreteMove)
00266 {
00267 if (this->mNodes[index]->IsDeleted())
00268 {
00269 EXCEPTION("Trying to move a deleted node");
00270 }
00271
00272 if (index == targetIndex)
00273 {
00274 EXCEPTION("Trying to merge a node with itself");
00275 }
00276 if (this->mNodes[index]->IsBoundaryNode())
00277 {
00278 if (!this->mNodes[targetIndex]->IsBoundaryNode())
00279 {
00280 EXCEPTION("A boundary node can only be moved on to another boundary node");
00281 }
00282 }
00283 std::set<unsigned> unshared_element_indices;
00284 std::set_difference(this->mNodes[index]->rGetContainingElementIndices().begin(),
00285 this->mNodes[index]->rGetContainingElementIndices().end(),
00286 this->mNodes[targetIndex]->rGetContainingElementIndices().begin(),
00287 this->mNodes[targetIndex]->rGetContainingElementIndices().end(),
00288 std::inserter(unshared_element_indices, unshared_element_indices.begin()));
00289
00290
00291 if (unshared_element_indices.size() == this->mNodes[index]->rGetContainingElementIndices().size())
00292 {
00293 EXCEPTION("These nodes cannot be merged since they are not neighbours");
00294 }
00295
00296 std::set<unsigned> unshared_boundary_element_indices;
00297 std::set_difference(this->mNodes[index]->rGetContainingBoundaryElementIndices().begin(),
00298 this->mNodes[index]->rGetContainingBoundaryElementIndices().end(),
00299 this->mNodes[targetIndex]->rGetContainingBoundaryElementIndices().begin(),
00300 this->mNodes[targetIndex]->rGetContainingBoundaryElementIndices().end(),
00301 std::inserter(unshared_boundary_element_indices, unshared_boundary_element_indices.begin()));
00302
00303
00304 if (this->mNodes[index]->IsBoundaryNode())
00305 {
00306 if (unshared_boundary_element_indices.size()
00307 == this->mNodes[index]->rGetContainingBoundaryElementIndices().size())
00308 {
00309
00310 EXCEPTION("These nodes cannot be merged since they are not neighbours on the boundary");
00311 }
00312 }
00313
00314 this->mNodes[index]->rGetModifiableLocation() = this->mNodes[targetIndex]->rGetLocation();
00315
00316 for (std::set<unsigned>::const_iterator element_iter=unshared_element_indices.begin();
00317 element_iter != unshared_element_indices.end();
00318 element_iter++)
00319 {
00320 try
00321 {
00322 if (SPACE_DIM == ELEMENT_DIM)
00323 {
00324 this->GetElement(*element_iter)->CalculateInverseJacobian(this->mElementJacobians[(*element_iter)],
00325 this->mElementJacobianDeterminants[(*element_iter)],
00326 this->mElementInverseJacobians[ (*element_iter) ]);
00327 }
00328 else
00329 {
00330 this->GetElement(*element_iter)->CalculateWeightedDirection(this->mElementWeightedDirections[(*element_iter)],
00331 this->mElementJacobianDeterminants[(*element_iter)]);
00332 }
00333
00334 if (concreteMove)
00335 {
00336 this->GetElement(*element_iter)->ReplaceNode(this->mNodes[index], this->mNodes[targetIndex]);
00337 }
00338
00339 }
00340 catch (Exception e)
00341 {
00342 EXCEPTION("Moving node caused an element to have a non-positive Jacobian determinant");
00343 }
00344 }
00345
00346 for (std::set<unsigned>::const_iterator boundary_element_iter=
00347 unshared_boundary_element_indices.begin();
00348 boundary_element_iter != unshared_boundary_element_indices.end();
00349 boundary_element_iter++)
00350 {
00351
00352
00353
00354
00355
00356 this->GetBoundaryElement(*boundary_element_iter)->CalculateWeightedDirection(this->mBoundaryElementWeightedDirections[(*boundary_element_iter)],
00357 this->mBoundaryElementJacobianDeterminants[(*boundary_element_iter)]);
00358
00359 if (concreteMove)
00360 {
00361 this->GetBoundaryElement(*boundary_element_iter)->ReplaceNode(this->mNodes[index], this->mNodes[targetIndex]);
00362 }
00363 }
00364
00365 std::set<unsigned> shared_element_indices;
00366 std::set_intersection(this->mNodes[index]->rGetContainingElementIndices().begin(),
00367 this->mNodes[index]->rGetContainingElementIndices().end(),
00368 this->mNodes[targetIndex]->rGetContainingElementIndices().begin(),
00369 this->mNodes[targetIndex]->rGetContainingElementIndices().end(),
00370 std::inserter(shared_element_indices, shared_element_indices.begin()));
00371
00372 for (std::set<unsigned>::const_iterator element_iter=shared_element_indices.begin();
00373 element_iter != shared_element_indices.end();
00374 element_iter++)
00375 {
00376 if (concreteMove)
00377 {
00378 this->GetElement(*element_iter)->MarkAsDeleted();
00379 this->mElementJacobianDeterminants[ (*element_iter) ] = 0.0;
00380 mDeletedElementIndices.push_back(*element_iter);
00381 }
00382 else
00383 {
00384
00385
00386 this->mElementJacobianDeterminants[ (*element_iter) ] = 0.0;
00387 }
00388 }
00389
00390
00391 std::set<unsigned> shared_boundary_element_indices;
00392 std::set_intersection(this->mNodes[index]->rGetContainingBoundaryElementIndices().begin(),
00393 this->mNodes[index]->rGetContainingBoundaryElementIndices().end(),
00394 this->mNodes[targetIndex]->rGetContainingBoundaryElementIndices().begin(),
00395 this->mNodes[targetIndex]->rGetContainingBoundaryElementIndices().end(),
00396 std::inserter(shared_boundary_element_indices, shared_boundary_element_indices.begin()));
00397
00398 for (std::set<unsigned>::const_iterator boundary_element_iter=shared_boundary_element_indices.begin();
00399 boundary_element_iter != shared_boundary_element_indices.end();
00400 boundary_element_iter++)
00401 {
00402 if (concreteMove)
00403 {
00404 this->GetBoundaryElement(*boundary_element_iter)->MarkAsDeleted();
00405 this->mBoundaryElementJacobianDeterminants[ (*boundary_element_iter) ] = 0.0;
00406 mDeletedBoundaryElementIndices.push_back(*boundary_element_iter);
00407 }
00408 else
00409 {
00410
00411
00412 this->mBoundaryElementJacobianDeterminants[ (*boundary_element_iter) ] = 0.0;
00413
00414
00415 this->mBoundaryElementWeightedDirections[ (*boundary_element_iter) ] = zero_vector<double>(SPACE_DIM);
00416 }
00417 }
00418
00419 if (concreteMove)
00420 {
00421 this->mNodes[index]->MarkAsDeleted();
00422 mDeletedNodeIndices.push_back(index);
00423 }
00424 }
00425
00426
00427 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00428 unsigned MutableMesh<ELEMENT_DIM, SPACE_DIM>::RefineElement(
00429 Element<ELEMENT_DIM,SPACE_DIM>* pElement,
00430 ChastePoint<SPACE_DIM> point)
00431 {
00432
00433
00434 if (pElement->IncludesPoint(point, true) == false)
00435 {
00436 EXCEPTION("RefineElement could not be started (point is not in element)");
00437 }
00438
00439
00440 unsigned new_node_index = AddNode(new Node<SPACE_DIM>(0, point.rGetLocation()));
00441
00442
00443
00444
00445 for (unsigned i = 0; i < ELEMENT_DIM; i++)
00446 {
00447
00448
00449 unsigned new_elt_index;
00450 if (mDeletedElementIndices.empty())
00451 {
00452 new_elt_index = this->mElements.size();
00453 }
00454 else
00455 {
00456 new_elt_index = mDeletedElementIndices.back();
00457 mDeletedElementIndices.pop_back();
00458 }
00459
00460 Element<ELEMENT_DIM,SPACE_DIM>* p_new_element=
00461 new Element<ELEMENT_DIM,SPACE_DIM>(*pElement, new_elt_index);
00462
00463
00464 p_new_element->UpdateNode(ELEMENT_DIM-1-i, this->mNodes[new_node_index]);
00465
00466
00467
00468
00469
00470 if ((unsigned) new_elt_index == this->mElements.size())
00471 {
00472 this->mElements.push_back(p_new_element);
00473 }
00474 else
00475 {
00476 delete this->mElements[new_elt_index];
00477 this->mElements[new_elt_index] = p_new_element;
00478 }
00479
00480 }
00481
00482
00483 pElement->UpdateNode(ELEMENT_DIM, this->mNodes[new_node_index]);
00484
00485
00486
00487 return new_node_index;
00488 }
00489
00490 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00491 void MutableMesh<ELEMENT_DIM, SPACE_DIM>::DeleteBoundaryNodeAt(unsigned index)
00492 {
00493 if (!this->mNodes[index]->IsBoundaryNode() )
00494 {
00495 EXCEPTION(" You may only delete a boundary node ");
00496 }
00497
00498 this->mNodes[index]->MarkAsDeleted();
00499 mDeletedNodeIndices.push_back(index);
00500
00501 typename std::vector<Node<SPACE_DIM>*>::iterator b_node_iter
00502 = std::find(this->mBoundaryNodes.begin(), this->mBoundaryNodes.end(), this->mNodes[index]);
00503 this->mBoundaryNodes.erase(b_node_iter);
00504
00505
00506 std::set<unsigned> boundary_element_indices = this->mNodes[index]->rGetContainingBoundaryElementIndices();
00507 std::set<unsigned>::const_iterator boundary_element_indices_iterator = boundary_element_indices.begin();
00508 while (boundary_element_indices_iterator != boundary_element_indices.end())
00509 {
00510 BoundaryElement<ELEMENT_DIM-1, SPACE_DIM>* p_boundary_element = this->GetBoundaryElement(*boundary_element_indices_iterator);
00511 p_boundary_element->MarkAsDeleted();
00512 mDeletedBoundaryElementIndices.push_back(*boundary_element_indices_iterator);
00513 boundary_element_indices_iterator++;
00514 }
00515
00516
00517 std::set<unsigned> element_indices = this->mNodes[index]->rGetContainingElementIndices();
00518 std::set<unsigned>::const_iterator element_indices_iterator = element_indices.begin();
00519 while (element_indices_iterator != element_indices.end())
00520 {
00521 Element<ELEMENT_DIM, SPACE_DIM>* p_element = this->GetElement(*element_indices_iterator);
00522 for (unsigned i=0; i< p_element->GetNumNodes();i++)
00523 {
00524 Node<SPACE_DIM>* p_node = p_element->GetNode(i);
00525 if (!p_node->IsDeleted())
00526 {
00527 p_node->SetAsBoundaryNode();
00528
00529 this->mBoundaryNodes.push_back(p_node);
00530 }
00531 }
00532 p_element->MarkAsDeleted();
00533 mDeletedElementIndices.push_back(p_element->GetIndex());
00534 element_indices_iterator++;
00535 }
00536 }
00537
00538 template <unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00539 void MutableMesh<ELEMENT_DIM, SPACE_DIM>::ReIndex(NodeMap& map)
00540 {
00541 assert(!mAddedNodes);
00542 map.Resize(this->GetNumAllNodes());
00543
00544 std::vector<Element<ELEMENT_DIM, SPACE_DIM> *> live_elements;
00545
00546 for (unsigned i=0; i<this->mElements.size(); i++)
00547 {
00548 assert(i==this->mElements[i]->GetIndex());
00549 if (this->mElements[i]->IsDeleted())
00550 {
00551 delete this->mElements[i];
00552 }
00553 else
00554 {
00555 live_elements.push_back(this->mElements[i]);
00556
00557 if (SPACE_DIM == ELEMENT_DIM)
00558 {
00559 this->mElementJacobians[live_elements.size()-1] = this->mElementJacobians[this->mElements[i]->GetIndex()];
00560 this->mElementInverseJacobians[live_elements.size()-1] = this->mElementInverseJacobians[this->mElements[i]->GetIndex()];
00561 }
00562 else
00563 {
00564 this->mElementWeightedDirections[live_elements.size()-1] = this->mElementWeightedDirections[this->mElements[i]->GetIndex()];
00565 }
00566 this->mElementJacobianDeterminants[live_elements.size()-1] = this->mElementJacobianDeterminants[this->mElements[i]->GetIndex()];
00567 }
00568 }
00569
00570 assert (mDeletedElementIndices.size() == this->mElements.size()-live_elements.size());
00571 mDeletedElementIndices.clear();
00572 this->mElements = live_elements;
00573 unsigned num_elements = this->mElements.size();
00574
00575 if (SPACE_DIM == ELEMENT_DIM)
00576 {
00577 this->mElementJacobians.resize(num_elements);
00578 this->mElementInverseJacobians.resize(num_elements);
00579 }
00580 else
00581 {
00582 this->mElementWeightedDirections.resize(num_elements);
00583 }
00584 this->mElementJacobianDeterminants.resize(num_elements);
00585
00586 std::vector<Node<SPACE_DIM> *> live_nodes;
00587 for (unsigned i=0; i<this->mNodes.size(); i++)
00588 {
00589 if (this->mNodes[i]->IsDeleted())
00590 {
00591 delete this->mNodes[i];
00592 map.SetDeleted(i);
00593 }
00594 else
00595 {
00596 live_nodes.push_back(this->mNodes[i]);
00597
00598
00599 map.SetNewIndex(i, (unsigned)(live_nodes.size()-1));
00600 }
00601 }
00602
00603 assert (mDeletedNodeIndices.size() == this->mNodes.size()-live_nodes.size());
00604 this->mNodes = live_nodes;
00605 mDeletedNodeIndices.clear();
00606
00607 std::vector<BoundaryElement<ELEMENT_DIM-1, SPACE_DIM> *> live_boundary_elements;
00608 for (unsigned i=0; i<this->mBoundaryElements.size(); i++)
00609 {
00610 if (this->mBoundaryElements[i]->IsDeleted())
00611 {
00612 delete this->mBoundaryElements[i];
00613 }
00614 else
00615 {
00616 live_boundary_elements.push_back(this->mBoundaryElements[i]);
00617
00618 this->mBoundaryElementWeightedDirections[live_boundary_elements.size()-1] = this->mBoundaryElementWeightedDirections[this->mBoundaryElements[i]->GetIndex()];
00619 this->mBoundaryElementJacobianDeterminants[live_boundary_elements.size()-1] = this->mBoundaryElementJacobianDeterminants[this->mBoundaryElements[i]->GetIndex()];
00620 }
00621 }
00622
00623 assert (mDeletedBoundaryElementIndices.size() == this->mBoundaryElements.size()-live_boundary_elements.size());
00624 this->mBoundaryElements = live_boundary_elements;
00625 mDeletedBoundaryElementIndices.clear();
00626
00627 unsigned num_boundary_elements = this->mBoundaryElements.size();
00628
00629 this->mBoundaryElementWeightedDirections.resize(num_boundary_elements);
00630 this->mBoundaryElementJacobianDeterminants.resize(num_boundary_elements);
00631
00632
00633 for (unsigned i=0; i<this->mNodes.size();i++)
00634 {
00635 this->mNodes[i]->SetIndex(i);
00636 }
00637 for (unsigned i=0; i<this->mElements.size();i++)
00638 {
00639
00640 this->mElements[i]->ResetIndex(i);
00641 }
00642 for (unsigned i=0; i<this->mBoundaryElements.size();i++)
00643 {
00644 this->mBoundaryElements[i]->ResetIndex(i);
00645 }
00646 }
00647
00648 template <unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00649 void MutableMesh<ELEMENT_DIM, SPACE_DIM>::ReMesh(NodeMap& map)
00650 {
00651
00652 #define COVERAGE_IGNORE
00653 assert( SPACE_DIM==2 || SPACE_DIM==3 );
00654 assert( ELEMENT_DIM == SPACE_DIM );
00655 #undef COVERAGE_IGNORE
00656
00657
00658
00659 if (GetNumNodes() <= SPACE_DIM)
00660 {
00661 EXCEPTION("The number of nodes must exceed the spatial dimension.");
00662 }
00663
00664
00665
00666
00667
00668
00669
00670
00671
00672
00673
00674
00675
00676
00677
00678
00679
00680 map.Resize(this->GetNumAllNodes());
00681
00682 if (SPACE_DIM==2)
00683 {
00684 struct triangulateio triangle_input;
00685 triangle_input.pointlist = (double *) malloc(GetNumNodes() * 2 * sizeof(double));
00686 triangle_input.numberofpoints = GetNumNodes();
00687 triangle_input.numberofpointattributes = 0;
00688 triangle_input.pointmarkerlist = NULL;
00689 triangle_input.numberofsegments = 0;
00690 triangle_input.numberofholes = 0;
00691 triangle_input.numberofregions = 0;
00692
00693 unsigned new_index = 0;
00694 for (unsigned i=0; i<this->GetNumAllNodes(); i++)
00695 {
00696 if (this->mNodes[i]->IsDeleted())
00697 {
00698 map.SetDeleted(i);
00699 }
00700 else
00701 {
00702 map.SetNewIndex(i, new_index);
00703 triangle_input.pointlist[2*new_index] = this->mNodes[i]->rGetLocation()[0];
00704 triangle_input.pointlist[2*new_index + 1] = this->mNodes[i]->rGetLocation()[1];
00705 new_index++;
00706 }
00707 }
00708
00709
00710 struct triangulateio triangle_output;
00711 triangle_output.pointlist = NULL;
00712 triangle_output.pointattributelist = (double *) NULL;
00713 triangle_output.pointmarkerlist = (int *) NULL;
00714 triangle_output.trianglelist = (int *) NULL;
00715 triangle_output.triangleattributelist = (double *) NULL;
00716 triangle_output.edgelist = (int *) NULL;
00717 triangle_output.edgemarkerlist = (int *) NULL;
00718
00719
00720 triangulate((char*)"Qze", &triangle_input, &triangle_output, NULL);
00721
00722 assert(triangle_output.numberofcorners == 3);
00723
00724
00725 Clear();
00726
00727
00728 for (unsigned node_index=0; node_index<(unsigned)triangle_output.numberofpoints; node_index++)
00729 {
00730 if (triangle_output.pointmarkerlist[node_index] == 1)
00731 {
00732
00733 Node<SPACE_DIM> *p_node = new Node<SPACE_DIM>(node_index, true,
00734 triangle_output.pointlist[node_index * 2],
00735 triangle_output.pointlist[node_index * 2+1]);
00736 this->mNodes.push_back(p_node);
00737 this->mBoundaryNodes.push_back(p_node);
00738 }
00739 else
00740 {
00741 this->mNodes.push_back(new Node<SPACE_DIM>(node_index, false,
00742 triangle_output.pointlist[node_index * 2],
00743 triangle_output.pointlist[node_index * 2+1]));
00744 }
00745 }
00746
00747
00748 this->mElements.reserve(triangle_output.numberoftriangles);
00749 for (unsigned element_index=0; element_index<(unsigned)triangle_output.numberoftriangles; element_index++)
00750 {
00751 std::vector<Node<SPACE_DIM>*> nodes;
00752 for (unsigned j=0; j<3; j++)
00753 {
00754 unsigned global_node_index = triangle_output.trianglelist[element_index*3 + j];
00755 assert(global_node_index < this->mNodes.size());
00756 nodes.push_back(this->mNodes[global_node_index]);
00757 }
00758 this->mElements.push_back(new Element<ELEMENT_DIM, SPACE_DIM>(element_index, nodes));
00759 }
00760
00761
00762
00763 unsigned next_boundary_element_index = 0;
00764 for (unsigned boundary_element_index=0; boundary_element_index<(unsigned)triangle_output.numberofedges; boundary_element_index++)
00765 {
00766 if (triangle_output.edgemarkerlist[boundary_element_index] == 1)
00767 {
00768 std::vector<Node<SPACE_DIM>*> nodes;
00769 for (unsigned j=0; j<2; j++)
00770 {
00771 unsigned global_node_index=triangle_output.edgelist[boundary_element_index*2 + j];
00772 assert(global_node_index < this->mNodes.size());
00773 nodes.push_back(this->mNodes[global_node_index]);
00774 }
00775 this->mBoundaryElements.push_back(new BoundaryElement<ELEMENT_DIM-1, SPACE_DIM>(next_boundary_element_index++, nodes));
00776 }
00777 }
00778
00779 free(triangle_input.pointlist);
00780
00781 free(triangle_output.pointlist);
00782 free(triangle_output.pointattributelist);
00783 free(triangle_output.pointmarkerlist);
00784 free(triangle_output.trianglelist);
00785 free(triangle_output.triangleattributelist);
00786 free(triangle_output.edgelist);
00787 free(triangle_output.edgemarkerlist);
00788
00789 this->RefreshJacobianCachedData();
00790 }
00791 else
00792 {
00793 std::stringstream pid;
00794 pid << getpid();
00795
00796 OutputFileHandler handler("");
00797 std::string full_name = handler.GetOutputDirectoryFullPath("") + "temp_" + pid.str() + ".";
00798
00799
00800 if (handler.IsMaster())
00801 {
00802 std::string node_file_name = "temp_" + pid.str() + ".node";
00803 {
00804 out_stream node_file = handler.OpenOutputFile(node_file_name);
00805
00806 (*node_file) << GetNumNodes() << "\t" << SPACE_DIM << "\t0\t0\n";
00807
00808 unsigned new_index = 0;
00809
00810 for (unsigned i=0; i<this->GetNumAllNodes(); i++)
00811 {
00812 if (this->mNodes[i]->IsDeleted())
00813 {
00814 map.SetDeleted(i);
00815 }
00816 else
00817 {
00818 map.SetNewIndex(i, new_index);
00819 new_index++;
00820 const c_vector<double, SPACE_DIM> node_loc = this->mNodes[i]->rGetLocation();
00821 (*node_file) << i << "\t" << node_loc[0] << "\t" << node_loc[1] << "\t" << node_loc[2] << "\n";
00822 }
00823 }
00824 node_file->close();
00825 }
00826
00827 std::string binary_name;
00828
00829
00830
00831
00832
00833
00834
00835
00836
00837
00838
00839 binary_name="tetgen";
00840 std::string command = binary_name + " -Q " + full_name + "node";
00841
00842
00843 command += " > /dev/null";
00844
00845 int return_value = system(command.c_str());
00846 if (return_value != 0)
00847 {
00848 #define COVERAGE_IGNORE
00849 EXCEPTION("The tetgen mesher did not succeed in remeshing. This functionality relies on tetgen. Do you have tetgen from http://tetgen.berlios.de/ in your path?");
00850 #undef COVERAGE_IGNORE
00851 }
00852 }
00853
00854 #ifndef SPECIAL_SERIAL
00855 if (!PetscTools::IsSequential())
00856 {
00857 char full_name_comm[200];
00858 strcpy(full_name_comm, full_name.c_str());
00859 MPI_Bcast(full_name_comm, 200, MPI_CHAR, 0, MPI_COMM_WORLD);
00860 full_name = full_name_comm;
00861 }
00862 #endif //SPECIAL_SERIAL
00863
00864
00865 Clear();
00866
00867
00868 TrianglesMeshReader<ELEMENT_DIM, SPACE_DIM> mesh_reader(full_name+"1");
00869 ConstructFromMeshReader(mesh_reader);
00870
00871
00872 PetscTools::Barrier();
00873
00874 if (handler.IsMaster())
00875 {
00876 std::string remove_command = "rm " + full_name + "*";
00877
00878 }
00879 }
00880 }
00881
00882 template <unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00883 void MutableMesh<ELEMENT_DIM, SPACE_DIM>::ReMesh()
00884 {
00885 NodeMap map(GetNumNodes());
00886 ReMesh(map);
00887 }
00888
00889 template <unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00890 bool MutableMesh<ELEMENT_DIM, SPACE_DIM>::CheckVoronoi(Element<ELEMENT_DIM, SPACE_DIM> *pElement, double maxPenetration)
00891 {
00892 assert(ELEMENT_DIM == SPACE_DIM);
00893 unsigned num_nodes = pElement->GetNumNodes();
00894 std::set<unsigned> neighbouring_elements_indices;
00895 std::set< Element<ELEMENT_DIM,SPACE_DIM> *> neighbouring_elements;
00896 std::set<unsigned> neighbouring_nodes_indices;
00897
00898
00899 for (unsigned i = 0; i < num_nodes; i++)
00900 {
00901 Node<SPACE_DIM>* node = pElement->GetNode(i);
00902 neighbouring_elements_indices = node->rGetContainingElementIndices();
00904 for (std::set<unsigned>::const_iterator it = neighbouring_elements_indices.begin();
00905 it != neighbouring_elements_indices.end(); ++it)
00906 {
00907 neighbouring_elements.insert(this->GetElement(*it));
00908 }
00909 }
00910 neighbouring_elements.erase(pElement);
00911
00912
00913 typedef typename std::set<Element<ELEMENT_DIM,SPACE_DIM> *>::const_iterator ElementIterator;
00914
00915 for (ElementIterator it = neighbouring_elements.begin();
00916 it != neighbouring_elements.end(); ++it)
00917 {
00918 for (unsigned i = 0; i < num_nodes; i++)
00919 {
00920 neighbouring_nodes_indices.insert((*it)->GetNodeGlobalIndex(i));
00921 }
00922 }
00923
00924 for (unsigned i = 0; i < num_nodes; i++)
00925 {
00926 neighbouring_nodes_indices.erase(pElement->GetNodeGlobalIndex(i));
00927 }
00928
00929
00930 c_vector <double, ELEMENT_DIM+1> this_circum_centre;
00931
00932 this_circum_centre = pElement->CalculateCircumsphere(this->mElementJacobians[pElement->GetIndex()], this->mElementInverseJacobians[pElement->GetIndex()]);
00933
00934
00935 c_vector <double, ELEMENT_DIM> circum_centre;
00936 for (unsigned i=0;i<ELEMENT_DIM;i++)
00937 {
00938 circum_centre[i]=this_circum_centre[i];
00939 }
00940
00941 for (std::set<unsigned>::const_iterator it = neighbouring_nodes_indices.begin();
00942 it != neighbouring_nodes_indices.end(); ++it)
00943 {
00944 c_vector <double, ELEMENT_DIM> node_location = this->GetNode(*it)->rGetLocation();
00945
00946
00947 node_location -= circum_centre;
00948
00949 double squared_distance = inner_prod(node_location, node_location);
00950
00951
00952
00953
00954 if (squared_distance < this_circum_centre[ELEMENT_DIM])
00955 {
00956
00957 double radius = sqrt(this_circum_centre[ELEMENT_DIM]);
00958 double distance = radius - sqrt(squared_distance);
00959
00960
00961 if (distance/radius > maxPenetration)
00962 {
00963 return false;
00964 }
00965 }
00966 }
00967 return true;
00968 }
00969
00970 template <unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00971 bool MutableMesh<ELEMENT_DIM, SPACE_DIM>::CheckVoronoi(double maxPenetration)
00972 {
00973
00974 for (unsigned i=0; i < this->mElements.size();i++)
00975 {
00976
00977 if (!this->mElements[i]->IsDeleted())
00978 {
00979
00980 if (CheckVoronoi(this->mElements[i], maxPenetration) == false)
00981 {
00982 return false;
00983 }
00984 }
00985 }
00986 return true;
00987 }
00988
00989
00991
00993
00994 template class MutableMesh<1,1>;
00995 template class MutableMesh<1,2>;
00996 template class MutableMesh<2,2>;
00997 template class MutableMesh<2,3>;
00998 template class MutableMesh<3,3>;