NodesOnlyMesh.cpp

00001 /*
00002 
00003 Copyright (c) 2005-2015, University of Oxford.
00004 All rights reserved.
00005 
00006 University of Oxford means the Chancellor, Masters and Scholars of the
00007 University of Oxford, having an administrative office at Wellington
00008 Square, Oxford OX1 2JD, UK.
00009 
00010 This file is part of Chaste.
00011 
00012 Redistribution and use in source and binary forms, with or without
00013 modification, are permitted provided that the following conditions are met:
00014  * Redistributions of source code must retain the above copyright notice,
00015    this list of conditions and the following disclaimer.
00016  * Redistributions in binary form must reproduce the above copyright notice,
00017    this list of conditions and the following disclaimer in the documentation
00018    and/or other materials provided with the distribution.
00019  * Neither the name of the University of Oxford nor the names of its
00020    contributors may be used to endorse or promote products derived from this
00021    software without specific prior written permission.
00022 
00023 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
00024 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00025 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00026 ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
00027 LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
00028 CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
00029 GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
00030 HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
00031 LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
00032 OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00033 
00034 */
00035 
00036 #include <map>
00037 #include "NodesOnlyMesh.hpp"
00038 #include "ChasteCuboid.hpp"
00039 
00040 template<unsigned SPACE_DIM>
00041 NodesOnlyMesh<SPACE_DIM>::NodesOnlyMesh()
00042         : MutableMesh<SPACE_DIM, SPACE_DIM>(),
00043           mMaximumInteractionDistance(1.0),
00044           mIndexCounter(0u),
00045           mMinimumNodeDomainBoundarySeparation(1.0),
00046           mMaxAddedNodeIndex(0u),
00047           mpBoxCollection(NULL),
00048           mCalculateNodeNeighbours(true)
00049 {
00050 }
00051 
00052 template<unsigned SPACE_DIM>
00053 NodesOnlyMesh<SPACE_DIM>::~NodesOnlyMesh()
00054 {
00055     Clear();
00056     ClearBoxCollection();
00057 }
00058 
00059 template<unsigned SPACE_DIM>
00060 void NodesOnlyMesh<SPACE_DIM>::ConstructNodesWithoutMesh(const std::vector<Node<SPACE_DIM>*>& rNodes, double maxInteractionDistance)
00061 {
00062     assert(maxInteractionDistance > 0.0 && maxInteractionDistance < DBL_MAX);
00063     mMaximumInteractionDistance = maxInteractionDistance;
00064 
00065     mMinimumNodeDomainBoundarySeparation = mMaximumInteractionDistance;
00066 
00067     Clear();
00068 
00069     SetUpBoxCollection(rNodes);
00070 
00071     mLocalInitialNodes.resize(rNodes.size(), false);
00072 
00073     for (unsigned i=0; i<rNodes.size(); i++)
00074     {
00075         if (mpBoxCollection->IsOwned(rNodes[i]))
00076         {
00077             mLocalInitialNodes[i] = true;
00078 
00079             assert(!rNodes[i]->IsDeleted());
00080             c_vector<double, SPACE_DIM> location = rNodes[i]->rGetLocation();
00081 
00082             Node<SPACE_DIM>* p_node_copy = new Node<SPACE_DIM>(GetNextAvailableIndex(), location);
00083             p_node_copy->SetRadius(0.5);    // Default value.
00084 
00085             this->mNodes.push_back(p_node_copy);
00086 
00087             // Update the node map
00088             mNodesMapping[p_node_copy->GetIndex()] = this->mNodes.size()-1;
00089         }
00090     }
00091 }
00092 
00093 template<unsigned SPACE_DIM>
00094 void NodesOnlyMesh<SPACE_DIM>::ConstructNodesWithoutMesh(const AbstractMesh<SPACE_DIM,SPACE_DIM>& rGeneratingMesh, double maxInteractionDistance)
00095 {
00096     ConstructNodesWithoutMesh(rGeneratingMesh.mNodes, maxInteractionDistance);
00097 }
00098 
00099 template<unsigned SPACE_DIM>
00100 std::vector<bool>& NodesOnlyMesh<SPACE_DIM>::rGetInitiallyOwnedNodes()
00101 {
00102     return mLocalInitialNodes;
00103 }
00104 
00105 template<unsigned SPACE_DIM>
00106 unsigned NodesOnlyMesh<SPACE_DIM>::SolveNodeMapping(unsigned index) const
00107 {
00108     std::map<unsigned, unsigned>::const_iterator node_position = mNodesMapping.find(index);
00109 
00110     if (node_position == mNodesMapping.end())
00111     {
00112         EXCEPTION("Requested node " << index << " does not belong to process " << PetscTools::GetMyRank());
00113     }
00114 
00115     return node_position->second;
00116 }
00117 
00118 template<unsigned SPACE_DIM>
00119 void NodesOnlyMesh<SPACE_DIM>::Clear()
00120 {
00121     // Call Clear() on the parent class
00122     MutableMesh<SPACE_DIM,SPACE_DIM>::Clear();
00123 
00124     // Clear the nodes mapping
00125     mNodesMapping.clear();
00126 
00127     mIndexCounter = 0;
00128 }
00129 
00130 template<unsigned SPACE_DIM>
00131 DistributedBoxCollection<SPACE_DIM>* NodesOnlyMesh<SPACE_DIM>::GetBoxCollection()
00132 {
00133     return mpBoxCollection;
00134 }
00135 
00136 template <unsigned SPACE_DIM>
00137 Node<SPACE_DIM>* NodesOnlyMesh<SPACE_DIM>::GetNodeOrHaloNode(unsigned index) const
00138 {
00139     Node<SPACE_DIM>* p_node;
00140 
00141     std::map<unsigned, unsigned>::const_iterator node_position = mHaloNodesMapping.find(index);
00142 
00143     if (node_position != mHaloNodesMapping.end())
00144     {
00145         p_node = mHaloNodes[node_position->second].get();
00146     }
00147     else
00148     {
00149         p_node = this->GetNode(index);
00150     }
00151 
00152     assert(p_node != NULL);
00153 
00154     return p_node;
00155 }
00156 
00157 template<unsigned SPACE_DIM>
00158 bool NodesOnlyMesh<SPACE_DIM>::IsOwned(c_vector<double, SPACE_DIM>& location)
00159 {
00160     return mpBoxCollection->IsOwned(location);
00161 }
00162 
00163 template<unsigned SPACE_DIM>
00164 unsigned NodesOnlyMesh<SPACE_DIM>::GetNumNodes() const
00165 {
00166     return this->mNodes.size() - this->mDeletedNodeIndices.size();
00167 }
00168 
00169 template<unsigned SPACE_DIM>
00170 unsigned NodesOnlyMesh<SPACE_DIM>::GetMaximumNodeIndex()
00171 {
00172     return std::max(mIndexCounter* PetscTools::GetNumProcs() + PetscTools::GetMyRank(), mMaxAddedNodeIndex);
00173 }
00174 
00175 template<unsigned SPACE_DIM>
00176 void NodesOnlyMesh<SPACE_DIM>::SetMaximumInteractionDistance(double maxDistance)
00177 {
00178     mMaximumInteractionDistance = maxDistance;
00179 }
00180 
00181 template<unsigned SPACE_DIM>
00182 double NodesOnlyMesh<SPACE_DIM>::GetMaximumInteractionDistance()
00183 {
00184     return mMaximumInteractionDistance;
00185 }
00186 
00187 template<unsigned SPACE_DIM>
00188 double NodesOnlyMesh<SPACE_DIM>::GetWidth(const unsigned& rDimension) const
00189 {
00190     double local_width = AbstractMesh<SPACE_DIM, SPACE_DIM>::GetWidth(rDimension);
00191     double global_width;
00192 
00193     MPI_Allreduce(&local_width, &global_width, 1, MPI_DOUBLE, MPI_MAX, PetscTools::GetWorld());
00194 
00195     return global_width;
00196 }
00197 
00198 template<unsigned SPACE_DIM>
00199 void NodesOnlyMesh<SPACE_DIM>::SetCalculateNodeNeighbours(bool calculateNodeNeighbours)
00200 {
00201     mCalculateNodeNeighbours = calculateNodeNeighbours;
00202 }
00203 
00204 template<unsigned SPACE_DIM>
00205 void NodesOnlyMesh<SPACE_DIM>::CalculateInteriorNodePairs(std::vector<std::pair<Node<SPACE_DIM>*, Node<SPACE_DIM>*> >& rNodePairs, std::map<unsigned, std::set<unsigned> >& rNodeNeighbours)
00206 {
00207     assert(mpBoxCollection);
00208 
00209     mpBoxCollection->CalculateInteriorNodePairs(this->mNodes, rNodePairs, rNodeNeighbours);
00210 }
00211 
00212 template<unsigned SPACE_DIM>
00213 void NodesOnlyMesh<SPACE_DIM>::CalculateBoundaryNodePairs(std::vector<std::pair<Node<SPACE_DIM>*, Node<SPACE_DIM>*> >& rNodePairs, std::map<unsigned, std::set<unsigned> >& rNodeNeighbours)
00214 {
00215     assert(mpBoxCollection);
00216 
00217     mpBoxCollection->CalculateBoundaryNodePairs(this->mNodes, rNodePairs, rNodeNeighbours);
00218 }
00219 
00220 template<unsigned SPACE_DIM>
00221 void NodesOnlyMesh<SPACE_DIM>::ReMesh(NodeMap& map)
00222 {
00223     map.ResetToIdentity();
00224 
00225     RemoveDeletedNodes(map);
00226 
00227     this->mDeletedNodeIndices.clear();
00228     this->mAddedNodes = false;
00229 
00230     UpdateNodeIndices();
00231 
00232     this->SetMeshHasChangedSinceLoading();
00233 }
00234 
00235 template<unsigned SPACE_DIM>
00236 void NodesOnlyMesh<SPACE_DIM>::RemoveDeletedNodes(NodeMap& map)
00237 {
00238     typename std::vector<Node<SPACE_DIM>* >::iterator node_iter = this->mNodes.begin();
00239     while (node_iter != this->mNodes.end())
00240     {
00241         if ((*node_iter)->IsDeleted())
00242         {
00243             map.SetDeleted((*node_iter)->GetIndex());
00244 
00245             mNodesMapping.erase((*node_iter)->GetIndex());
00246 
00247             // Free memory before erasing the pointer from the list of nodes.
00248             delete (*node_iter);
00249             node_iter = this->mNodes.erase(node_iter);
00250         }
00251         else
00252         {
00253             ++node_iter;
00254         }
00255     }
00256 }
00257 
00258 template<unsigned SPACE_DIM>
00259 void NodesOnlyMesh<SPACE_DIM>::UpdateNodeIndices()
00260 {
00261     mNodesMapping.clear();
00262     for (unsigned location_in_vector=0; location_in_vector < this->mNodes.size(); location_in_vector++)
00263     {
00264         unsigned global_index = this->mNodes[location_in_vector]->GetIndex();
00265         mNodesMapping[global_index] = location_in_vector;
00266     }
00267 }
00268 
00269 template<unsigned SPACE_DIM>
00270 void NodesOnlyMesh<SPACE_DIM>::CalculateNodesOutsideLocalDomain()
00271 {
00272     mNodesToSendRight.clear();
00273     mNodesToSendLeft.clear();
00274 
00275     for (typename AbstractMesh<SPACE_DIM, SPACE_DIM>::NodeIterator node_iter = this->GetNodeIteratorBegin();
00276             node_iter != this->GetNodeIteratorEnd();
00277             ++node_iter)
00278     {
00279         unsigned owning_process = mpBoxCollection->GetProcessOwningNode(&(*node_iter));
00280         if (owning_process == PetscTools::GetMyRank())
00281         {
00282             // Do nothing.
00283         }
00284         else if (owning_process == PetscTools::GetMyRank() + 1)
00285         {
00286             mNodesToSendRight.push_back(node_iter->GetIndex());
00287         }
00288         else if (owning_process == PetscTools::GetMyRank() - 1)
00289         {
00290             mNodesToSendLeft.push_back(node_iter->GetIndex());
00291         }
00292     }
00293 }
00294 
00295 template<unsigned SPACE_DIM>
00296 std::vector<unsigned>& NodesOnlyMesh<SPACE_DIM>::rGetNodesToSendLeft()
00297 {
00298     return mNodesToSendLeft;
00299 }
00300 
00301 template<unsigned SPACE_DIM>
00302 std::vector<unsigned>& NodesOnlyMesh<SPACE_DIM>::rGetNodesToSendRight()
00303 {
00304     return mNodesToSendRight;
00305 }
00306 
00307 template<unsigned SPACE_DIM>
00308 std::vector<unsigned>& NodesOnlyMesh<SPACE_DIM>::rGetHaloNodesToSendRight()
00309 {
00310     return mpBoxCollection->rGetHaloNodesRight();
00311 }
00312 
00313 template<unsigned SPACE_DIM>
00314 std::vector<unsigned>& NodesOnlyMesh<SPACE_DIM>::rGetHaloNodesToSendLeft()
00315 {
00316     return mpBoxCollection->rGetHaloNodesLeft();
00317 }
00318 
00319 template<unsigned SPACE_DIM>
00320 void NodesOnlyMesh<SPACE_DIM>::AddNodeWithFixedIndex(Node<SPACE_DIM>* pNewNode)
00321 {
00322     unsigned location_in_nodes_vector = 0;
00323 
00324     if (this->mDeletedNodeIndices.empty())
00325     {
00326         this->mNodes.push_back(pNewNode);
00327         location_in_nodes_vector = this->mNodes.size() - 1;
00328     }
00329     else
00330     {
00331         location_in_nodes_vector = this->mDeletedNodeIndices.back();
00332         this->mDeletedNodeIndices.pop_back();
00333         delete this->mNodes[location_in_nodes_vector];
00334         this->mNodes[location_in_nodes_vector] = pNewNode;
00335     }
00336 
00337     this->mAddedNodes = true;
00338 
00339     mMaxAddedNodeIndex = (pNewNode->GetIndex() > mMaxAddedNodeIndex) ? pNewNode->GetIndex() : mMaxAddedNodeIndex;
00340 
00341     // Update mNodesMapping
00342     mNodesMapping[pNewNode->GetIndex()] = location_in_nodes_vector;
00343 
00344     // Then update cell radius to default.
00345     pNewNode->SetRadius(0.5);
00346 }
00347 
00348 template<unsigned SPACE_DIM>
00349 void NodesOnlyMesh<SPACE_DIM>::AddHaloNode(boost::shared_ptr<Node<SPACE_DIM> > pNewNode)
00350 {
00351     mHaloNodes.push_back(pNewNode);
00352     mHaloNodesMapping[pNewNode->GetIndex()] = mHaloNodes.size() - 1;
00353 }
00354 
00355 template<unsigned SPACE_DIM>
00356 void NodesOnlyMesh<SPACE_DIM>::ClearHaloNodes()
00357 {
00358     mHaloNodes.clear();
00359 
00360     mHaloNodesMapping.clear();
00361 }
00362 
00363 template<unsigned SPACE_DIM>
00364 unsigned NodesOnlyMesh<SPACE_DIM>::AddNode(Node<SPACE_DIM>* pNewNode)
00365 {
00366     unsigned fresh_global_index = GetNextAvailableIndex();
00367     pNewNode->SetIndex(fresh_global_index);
00368 
00369     AddNodeWithFixedIndex(pNewNode);
00370 
00371     return fresh_global_index;
00372 }
00373 
00374 template<unsigned SPACE_DIM>
00375 void NodesOnlyMesh<SPACE_DIM>::AddMovedNode(boost::shared_ptr<Node<SPACE_DIM> > pMovedNode)
00376 {
00377     // Make a deep copy of this node pointer so that it isn't accidentally deleted.
00378     unsigned index = pMovedNode->GetIndex();
00379     c_vector<double, SPACE_DIM> location = pMovedNode->rGetLocation();
00380 
00381     Node<SPACE_DIM>* p_node = new Node<SPACE_DIM>(index, location);
00382 
00383     if (pMovedNode->HasNodeAttributes())
00384     {
00385         double radius = pMovedNode->GetRadius();
00386         p_node->SetRadius(radius);
00387 
00388         unsigned region = pMovedNode->GetRegion();
00389         p_node->SetRegion(region);
00390 
00391         bool is_particle = pMovedNode->IsParticle();
00392         p_node->SetIsParticle(is_particle);
00393 
00394         for (unsigned i=0; i<pMovedNode->GetNumNodeAttributes(); i++)
00395         {
00396             double attribute = pMovedNode->rGetNodeAttributes()[i];
00397             p_node->AddNodeAttribute(attribute);
00398         }
00399     }
00400 
00401     AddNodeWithFixedIndex(p_node);
00402 }
00403 
00404 template<unsigned SPACE_DIM>
00405 void NodesOnlyMesh<SPACE_DIM>::DeleteNode(unsigned index)
00406 {
00407     if (this->GetNode(index)->IsDeleted())
00408     {
00409         EXCEPTION("Trying to delete a deleted node");
00410     }
00411 
00412     unsigned local_index = SolveNodeMapping(index);
00413 
00414     this->mNodes[local_index]->MarkAsDeleted();
00415     this->mDeletedNodeIndices.push_back(local_index);
00416     mDeletedGlobalNodeIndices.push_back(index);
00417 }
00418 
00419 template<unsigned SPACE_DIM>
00420 void NodesOnlyMesh<SPACE_DIM>::DeleteMovedNode(unsigned index)
00421 {
00422     DeleteNode(index);
00423 
00424     // Remove index from deleted indices, as moved indices must not be re-used.
00425     mDeletedGlobalNodeIndices.pop_back();
00426 }
00427 
00428 template<unsigned SPACE_DIM>
00429 void NodesOnlyMesh<SPACE_DIM>::SetMinimumNodeDomainBoundarySeparation(double separation)
00430 {
00431     assert(!(separation < 0.0));
00432 
00433     mMinimumNodeDomainBoundarySeparation = separation;
00434 }
00435 
00436 template<unsigned SPACE_DIM>
00437 unsigned NodesOnlyMesh<SPACE_DIM>::GetNextAvailableIndex()
00438 {
00439     unsigned index;
00440 
00441     if (!this->mDeletedGlobalNodeIndices.empty())
00442     {
00443         index = this->mDeletedGlobalNodeIndices.back();
00444         this->mDeletedGlobalNodeIndices.pop_back();
00445     }
00446     else
00447     {
00448         unsigned counter = mIndexCounter;
00449         mIndexCounter++;
00450         index = counter * PetscTools::GetNumProcs() + PetscTools::GetMyRank();
00451     }
00452 
00453     return index;
00454 }
00455 
00456 template<unsigned SPACE_DIM>
00457 void NodesOnlyMesh<SPACE_DIM>::EnlargeBoxCollection()
00458 {
00459     assert(mpBoxCollection);
00460 
00461     int num_local_rows = mpBoxCollection->GetNumLocalRows();
00462     int new_local_rows = num_local_rows + (int)(PetscTools::AmTopMost()) + (int)(PetscTools::AmMaster());
00463 
00464     c_vector<double, 2*SPACE_DIM> current_domain_size = mpBoxCollection->rGetDomainSize();
00465     c_vector<double, 2*SPACE_DIM> new_domain_size;
00466 
00467     double fudge = 1e-14;
00468     for (unsigned d=0; d < SPACE_DIM; d++)
00469     {
00470         new_domain_size[2*d] = current_domain_size[2*d] - (mMaximumInteractionDistance - fudge);
00471         new_domain_size[2*d+1] = current_domain_size[2*d+1] + (mMaximumInteractionDistance - fudge);
00472     }
00473 
00474     SetUpBoxCollection(mMaximumInteractionDistance, new_domain_size, new_local_rows);
00475 }
00476 
00477 template<unsigned SPACE_DIM>
00478 bool NodesOnlyMesh<SPACE_DIM>::IsANodeCloseToDomainBoundary()
00479 {
00480     assert(mpBoxCollection);
00481 
00482     int is_local_node_close = 0;
00483     c_vector<double, 2*SPACE_DIM> domain_boundary = mpBoxCollection->rGetDomainSize();
00484 
00485     for (typename AbstractMesh<SPACE_DIM, SPACE_DIM>::NodeIterator node_iter = this->GetNodeIteratorBegin();
00486          node_iter != this->GetNodeIteratorEnd();
00487          ++node_iter)
00488     {
00489         // Note that we define this vector before setting it as otherwise the profiling build will break (see #2367)
00490         c_vector<double, SPACE_DIM> location;
00491         location = node_iter->rGetLocation();
00492 
00493         for (unsigned d=0; d<SPACE_DIM; d++)
00494         {
00495             if (location[d] < (domain_boundary[2*d] + mMinimumNodeDomainBoundarySeparation) ||  location[d] > (domain_boundary[2*d+1] - mMinimumNodeDomainBoundarySeparation))
00496             {
00497                 is_local_node_close = 1;
00498                 break;
00499             }
00500         }
00501         if (is_local_node_close)
00502         {
00503             break;  // Saves checking every node if we find one close to the boundary
00504         }
00505     }
00506 
00507     // Synchronise between processes
00508     int is_any_node_close = 0;
00509     MPI_Allreduce(&is_local_node_close, &is_any_node_close, 1, MPI_INT, MPI_SUM, PetscTools::GetWorld());
00510 
00511     return (is_any_node_close > 0);
00512 }
00513 
00514 template<unsigned SPACE_DIM>
00515 void NodesOnlyMesh<SPACE_DIM>::ClearBoxCollection()
00516 {
00517     if (mpBoxCollection)
00518     {
00519         delete mpBoxCollection;
00520     }
00521     mpBoxCollection = NULL;
00522 }
00523 
00524 template<unsigned SPACE_DIM>
00525 void NodesOnlyMesh<SPACE_DIM>::SetInitialBoxCollection(const c_vector<double, 2*SPACE_DIM> domainSize, double maxInteractionDistance)
00526 {
00527     this->SetUpBoxCollection(maxInteractionDistance, domainSize);
00528 }
00529 
00530 template<unsigned SPACE_DIM>
00531 void NodesOnlyMesh<SPACE_DIM>::SetUpBoxCollection(const std::vector<Node<SPACE_DIM>* >& rNodes)
00532 {
00533     ClearBoxCollection();
00534 
00535     ChasteCuboid<SPACE_DIM> bounding_box = this->CalculateBoundingBox(rNodes);
00536 
00537     c_vector<double, 2*SPACE_DIM> domain_size;
00538     for (unsigned i=0; i < SPACE_DIM; i++)
00539     {
00540         domain_size[2*i] = bounding_box.rGetLowerCorner()[i] - 1e-14;
00541         domain_size[2*i+1] = bounding_box.rGetUpperCorner()[i] + 1e-14;
00542     }
00543 
00544     SetUpBoxCollection(mMaximumInteractionDistance, domain_size);
00545 }
00546 
00547 template<unsigned SPACE_DIM>
00548 void NodesOnlyMesh<SPACE_DIM>::SetUpBoxCollection(double cutOffLength, c_vector<double, 2*SPACE_DIM> domainSize, int numLocalRows, bool isPeriodic)
00549 {
00550      ClearBoxCollection();
00551 
00552      mpBoxCollection = new DistributedBoxCollection<SPACE_DIM>(cutOffLength, domainSize, isPeriodic, numLocalRows);
00553      mpBoxCollection->SetupLocalBoxesHalfOnly();
00554      mpBoxCollection->SetupHaloBoxes();
00555      mpBoxCollection->SetCalculateNodeNeighbours(mCalculateNodeNeighbours);
00556 }
00557 
00558 template<unsigned SPACE_DIM>
00559 void NodesOnlyMesh<SPACE_DIM>::AddNodesToBoxes()
00560 {
00561      // Put the nodes in the boxes.
00562      for (typename AbstractMesh<SPACE_DIM, SPACE_DIM>::NodeIterator node_iter = this->GetNodeIteratorBegin();
00563                node_iter != this->GetNodeIteratorEnd();
00564                ++node_iter)
00565      {
00566           unsigned box_index = mpBoxCollection->CalculateContainingBox(&(*node_iter));
00567           mpBoxCollection->rGetBox(box_index).AddNode(&(*node_iter));
00568      }
00569 }
00570 
00571 template<unsigned SPACE_DIM>
00572 void NodesOnlyMesh<SPACE_DIM>::AddHaloNodesToBoxes()
00573 {
00574     // Add halo nodes
00575     for (typename std::vector<boost::shared_ptr<Node<SPACE_DIM> > >::iterator halo_node_iter = mHaloNodes.begin();
00576             halo_node_iter != mHaloNodes.end();
00577             ++halo_node_iter)
00578     {
00579         unsigned box_index = mpBoxCollection->CalculateContainingBox((*halo_node_iter).get());
00580         mpBoxCollection->rGetHaloBox(box_index).AddNode((*halo_node_iter).get());
00581     }
00582 }
00583 
00584 template<unsigned SPACE_DIM>
00585 void NodesOnlyMesh<SPACE_DIM>::UpdateBoxCollection()
00586 {
00587     assert(mpBoxCollection);
00588 
00589     // Remove node pointers from boxes in BoxCollection.
00590     mpBoxCollection->EmptyBoxes();
00591 
00592     AddNodesToBoxes();
00593 
00594     mpBoxCollection->UpdateHaloBoxes();
00595 }
00596 
00597 template<unsigned SPACE_DIM>
00598 void NodesOnlyMesh<SPACE_DIM>::ResizeBoxCollection()
00599 {
00600     if (!mpBoxCollection)
00601     {
00602         SetUpBoxCollection(this->mNodes);
00603     }
00604 
00605     while (IsANodeCloseToDomainBoundary())
00606     {
00607         EnlargeBoxCollection();
00608     }
00609 }
00610 
00611 template<unsigned SPACE_DIM>
00612 void NodesOnlyMesh<SPACE_DIM>::LoadBalanceMesh()
00613 {
00614     std::vector<int> local_node_distribution = mpBoxCollection->CalculateNumberOfNodesInEachStrip();
00615 
00616     unsigned new_rows = mpBoxCollection->LoadBalance(local_node_distribution);
00617 
00618     c_vector<double, 2*SPACE_DIM> current_domain_size = mpBoxCollection->rGetDomainSize();
00619 
00620     // This ensures the domain will stay the same size.
00621     double fudge = 1e-14;
00622     for (unsigned d=0; d < SPACE_DIM; d++)
00623     {
00624         current_domain_size[2*d] = current_domain_size[2*d] + fudge;
00625         current_domain_size[2*d+1] = current_domain_size[2*d+1] - fudge;
00626     }
00627     SetUpBoxCollection(mMaximumInteractionDistance, current_domain_size, new_rows);
00628 }
00629 
00630 template<unsigned SPACE_DIM>
00631 void NodesOnlyMesh<SPACE_DIM>::ConstructFromMeshReader(AbstractMeshReader<SPACE_DIM, SPACE_DIM>& rMeshReader)
00632 {
00633     TetrahedralMesh<SPACE_DIM, SPACE_DIM>::ConstructFromMeshReader(rMeshReader);
00634 
00635     // Set the correct global node indices
00636     for (unsigned i=0; i<this->mNodes.size(); i++)
00637     {
00638         this->mNodes[i]->SetIndex(GetNextAvailableIndex());
00639     }
00640 }
00641 
00643 // Explicit instantiation
00645 
00646 template class NodesOnlyMesh<1>;
00647 template class NodesOnlyMesh<2>;
00648 template class NodesOnlyMesh<3>;
00649 
00650 // Serialization for Boost >= 1.36
00651 #include "SerializationExportWrapperForCpp.hpp"
00652 EXPORT_TEMPLATE_CLASS_SAME_DIMS(NodesOnlyMesh)

Generated by  doxygen 1.6.2