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
00030
00031
00032
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);
00084
00085 this->mNodes.push_back(p_node_copy);
00086
00087
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
00122 MutableMesh<SPACE_DIM,SPACE_DIM>::Clear();
00123
00124
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
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
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
00342 mNodesMapping[pNewNode->GetIndex()] = location_in_nodes_vector;
00343
00344
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
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
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
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;
00504 }
00505 }
00506
00507
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
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
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
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
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
00636 for (unsigned i=0; i<this->mNodes.size(); i++)
00637 {
00638 this->mNodes[i]->SetIndex(GetNextAvailableIndex());
00639 }
00640 }
00641
00643
00645
00646 template class NodesOnlyMesh<1>;
00647 template class NodesOnlyMesh<2>;
00648 template class NodesOnlyMesh<3>;
00649
00650
00651 #include "SerializationExportWrapperForCpp.hpp"
00652 EXPORT_TEMPLATE_CLASS_SAME_DIMS(NodesOnlyMesh)