Chaste Commit::baa90ac2819b962188b7562f2326be23c47859a7
NodesOnlyMesh.cpp
1/*
2
3Copyright (c) 2005-2024, University of Oxford.
4All rights reserved.
5
6University of Oxford means the Chancellor, Masters and Scholars of the
7University of Oxford, having an administrative office at Wellington
8Square, Oxford OX1 2JD, UK.
9
10This file is part of Chaste.
11
12Redistribution and use in source and binary forms, with or without
13modification, 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
23THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
24AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
27LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
28CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
29GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
32OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33
34*/
35
36#include <map>
37#include "NodesOnlyMesh.hpp"
38#include "ChasteCuboid.hpp"
39
40template<unsigned SPACE_DIM>
42 : MutableMesh<SPACE_DIM, SPACE_DIM>(),
43 mMaximumInteractionDistance(1.0),
44 mIndexCounter(0u),
45 mMinimumNodeDomainBoundarySeparation(1.0),
46 mMaxAddedNodeIndex(0u),
47 mpBoxCollection(nullptr),
48 mCalculateNodeNeighbours(true)
49{
50}
51
52template<unsigned SPACE_DIM>
54{
55 Clear();
56 ClearBoxCollection();
57}
58
59template<unsigned SPACE_DIM>
60void NodesOnlyMesh<SPACE_DIM>::ConstructNodesWithoutMesh(const std::vector<Node<SPACE_DIM>*>& rNodes, double maxInteractionDistance)
61{
62 assert(maxInteractionDistance > 0.0 && maxInteractionDistance < DBL_MAX);
63 mMaximumInteractionDistance = maxInteractionDistance;
64
65 mMinimumNodeDomainBoundarySeparation = mMaximumInteractionDistance;
66
67 Clear();
68
69 SetUpBoxCollection(rNodes);
70
71 mLocalInitialNodes.resize(rNodes.size(), false);
72
73 for (unsigned i=0; i<rNodes.size(); i++)
74 {
75 if (mpBoxCollection->IsOwned(rNodes[i]))
76 {
77 assert(!rNodes[i]->IsDeleted());
78
79 mLocalInitialNodes[i] = true;
80
81 // Create a copy of the node, sharing its location
82 c_vector<double, SPACE_DIM> location = rNodes[i]->rGetLocation();
83 Node<SPACE_DIM>* p_node_copy = new Node<SPACE_DIM>(GetNextAvailableIndex(), location);
84
85 p_node_copy->SetRadius(0.5);
86
87 // If the original node has attributes, then copy these
88 if (rNodes[i]->HasNodeAttributes())
89 {
90 p_node_copy->rGetNodeAttributes() = rNodes[i]->rGetNodeAttributes();
91 }
92
93 this->mNodes.push_back(p_node_copy);
94
95 // Update the node map
96 mNodesMapping[p_node_copy->GetIndex()] = this->mNodes.size()-1;
97 }
98 }
99}
100
101template<unsigned SPACE_DIM>
102void NodesOnlyMesh<SPACE_DIM>::ConstructNodesWithoutMesh(const std::vector<boost::shared_ptr<Node<SPACE_DIM> > >& rNodes, double maxInteractionDistance)
103{
104 // This is not efficient. It should replace the corresponding raw ptr method if SetUpBoxCollection and Chaste Cuboid methods are changed to take shared ptrs.
105 std::vector<Node<SPACE_DIM>*> temp_nodes(rNodes.size());
106 for (unsigned idx = 0; idx < rNodes.size(); idx++)
107 {
108 temp_nodes[idx] = rNodes[idx].get();
109 }
110
111 ConstructNodesWithoutMesh(temp_nodes, maxInteractionDistance);
112}
113
114template<unsigned SPACE_DIM>
115void NodesOnlyMesh<SPACE_DIM>::ConstructNodesWithoutMesh(const AbstractMesh<SPACE_DIM,SPACE_DIM>& rGeneratingMesh, double maxInteractionDistance)
116{
117 ConstructNodesWithoutMesh(rGeneratingMesh.mNodes, maxInteractionDistance);
118}
119
120template<unsigned SPACE_DIM>
122{
123 return mLocalInitialNodes;
124}
125
126template<unsigned SPACE_DIM>
127unsigned NodesOnlyMesh<SPACE_DIM>::SolveNodeMapping(unsigned index) const
128{
129 std::map<unsigned, unsigned>::const_iterator node_position = mNodesMapping.find(index);
130
131 if (node_position == mNodesMapping.end())
132 {
133 EXCEPTION("Requested node " << index << " does not belong to process " << PetscTools::GetMyRank());
134 }
135
136 return node_position->second;
137}
138
139template<unsigned SPACE_DIM>
141{
142 // Call Clear() on the parent class
144
145 // Clear the nodes mapping
146 mNodesMapping.clear();
147
148 mIndexCounter = 0;
149}
150
151template<unsigned SPACE_DIM>
156
157template <unsigned SPACE_DIM>
159{
160 Node<SPACE_DIM>* p_node;
161
162 std::map<unsigned, unsigned>::const_iterator node_position = mHaloNodesMapping.find(index);
163
164 if (node_position != mHaloNodesMapping.end())
165 {
166 p_node = mHaloNodes[node_position->second].get();
167 }
168 else
169 {
170 p_node = this->GetNode(index);
171 }
172
173 assert(p_node != nullptr);
174
175 return p_node;
176}
177
178template<unsigned SPACE_DIM>
179bool NodesOnlyMesh<SPACE_DIM>::IsOwned(c_vector<double, SPACE_DIM>& location)
180{
181 return mpBoxCollection->IsOwned(location);
182}
184template<unsigned SPACE_DIM>
186{
187 return this->mNodes.size() - this->mDeletedNodeIndices.size();
188}
189
190template<unsigned SPACE_DIM>
192{
193 return std::max(mIndexCounter* PetscTools::GetNumProcs() + PetscTools::GetMyRank(), mMaxAddedNodeIndex);
194}
195
196template<unsigned SPACE_DIM>
198{
199 mMaximumInteractionDistance = maxDistance;
201
202template<unsigned SPACE_DIM>
204{
205 return mMaximumInteractionDistance;
206}
208template<unsigned SPACE_DIM>
209double NodesOnlyMesh<SPACE_DIM>::GetWidth(const unsigned& rDimension) const
210{
211 double local_width = AbstractMesh<SPACE_DIM, SPACE_DIM>::GetWidth(rDimension);
212 double global_width;
213
214 MPI_Allreduce(&local_width, &global_width, 1, MPI_DOUBLE, MPI_MAX, PetscTools::GetWorld());
215
216 return global_width;
217}
218
219template<unsigned SPACE_DIM>
221{
222 mCalculateNodeNeighbours = calculateNodeNeighbours;
223}
224
225template<unsigned SPACE_DIM>
227{
228 assert(mpBoxCollection);
229
230 mpBoxCollection->CalculateInteriorNodePairs(this->mNodes, rNodePairs);
231}
232
233template<unsigned SPACE_DIM>
235{
236 assert(mpBoxCollection);
237
238 mpBoxCollection->CalculateBoundaryNodePairs(this->mNodes, rNodePairs);
239}
240
241template<unsigned SPACE_DIM>
243{
244 map.ResetToIdentity();
245
246 RemoveDeletedNodes(map);
247
248 this->mDeletedNodeIndices.clear();
249 this->mAddedNodes = false;
250
251 UpdateNodeIndices();
252
253 this->SetMeshHasChangedSinceLoading();
254}
255
256template<unsigned SPACE_DIM>
258{
259 typename std::vector<Node<SPACE_DIM>* >::iterator node_iter = this->mNodes.begin();
260 while (node_iter != this->mNodes.end())
261 {
262 if ((*node_iter)->IsDeleted())
263 {
264 map.SetDeleted((*node_iter)->GetIndex());
265
266 mNodesMapping.erase((*node_iter)->GetIndex());
267
268 // Free memory before erasing the pointer from the list of nodes.
269 delete (*node_iter);
270 node_iter = this->mNodes.erase(node_iter);
272 else
273 {
274 ++node_iter;
275 }
276 }
277}
278
279template<unsigned SPACE_DIM>
281{
282 mNodesMapping.clear();
283 for (unsigned location_in_vector=0; location_in_vector < this->mNodes.size(); location_in_vector++)
284 {
285 unsigned global_index = this->mNodes[location_in_vector]->GetIndex();
286 mNodesMapping[global_index] = location_in_vector;
287 }
288}
289
290template<unsigned SPACE_DIM>
293 mNodesToSendRight.clear();
294 mNodesToSendLeft.clear();
295
296 for (typename AbstractMesh<SPACE_DIM, SPACE_DIM>::NodeIterator node_iter = this->GetNodeIteratorBegin();
297 node_iter != this->GetNodeIteratorEnd();
298 ++node_iter)
300 unsigned owning_process = mpBoxCollection->GetProcessOwningNode(&(*node_iter));
301 if (owning_process == PetscTools::GetMyRank())
302 {
303 // Do nothing.
304 }
305 else if (owning_process == PetscTools::GetMyRank() + 1)
306 {
307 mNodesToSendRight.push_back(node_iter->GetIndex());
308 }
309 else if (owning_process == PetscTools::GetMyRank() - 1)
310 {
311 mNodesToSendLeft.push_back(node_iter->GetIndex());
313 // Periodic cases
314
315 // LCOV_EXCL_START
316 /* This block cannot be covered by regular testing,
317 * but it is covered by the Nightly -np 3 builder
318 * See TestGetNodesOutsideLocalDomainwithPeriodicMesh
319 */
320 else if ( owning_process == (PetscTools::GetNumProcs()-1) )
321 {
322 // We are on the base and need to send to the top (i.e. left)
323 mNodesToSendLeft.push_back(node_iter->GetIndex());
325 else if ( owning_process == 0 )
326 {
327 // We are on the top and need to send to the bottom process (i.e. right)
328 mNodesToSendRight.push_back(node_iter->GetIndex());
329 }
330 // LCOV_EXCL_STOP
331 }
333
334template<unsigned SPACE_DIM>
336{
337 return mNodesToSendLeft;
338}
340template<unsigned SPACE_DIM>
342{
343 return mNodesToSendRight;
344}
345
346template<unsigned SPACE_DIM>
348{
349 return mpBoxCollection->rGetHaloNodesRight();
350}
351
352template<unsigned SPACE_DIM>
354{
355 return mpBoxCollection->rGetHaloNodesLeft();
356}
357
358template<unsigned SPACE_DIM>
360{
361 unsigned location_in_nodes_vector = 0;
363 if (this->mDeletedNodeIndices.empty())
364 {
365 this->mNodes.push_back(pNewNode);
366 location_in_nodes_vector = this->mNodes.size() - 1;
367 }
368 else
370 location_in_nodes_vector = this->mDeletedNodeIndices.back();
371 this->mDeletedNodeIndices.pop_back();
372 delete this->mNodes[location_in_nodes_vector];
373 this->mNodes[location_in_nodes_vector] = pNewNode;
375
376 this->mAddedNodes = true;
377
378 mMaxAddedNodeIndex = (pNewNode->GetIndex() > mMaxAddedNodeIndex) ? pNewNode->GetIndex() : mMaxAddedNodeIndex;
379
380 // Update mNodesMapping
381 mNodesMapping[pNewNode->GetIndex()] = location_in_nodes_vector;
382
383 // Then update cell radius to default.
384 pNewNode->SetRadius(0.5);
385}
386
387template<unsigned SPACE_DIM>
389{
390 mHaloNodes.push_back(pNewNode);
391 mHaloNodesMapping[pNewNode->GetIndex()] = mHaloNodes.size() - 1;
393
394template<unsigned SPACE_DIM>
396{
397 mHaloNodes.clear();
398
399 mHaloNodesMapping.clear();
400}
401
402template<unsigned SPACE_DIM>
404{
405 unsigned fresh_global_index = GetNextAvailableIndex();
406 pNewNode->SetIndex(fresh_global_index);
408 AddNodeWithFixedIndex(pNewNode);
409
410 return fresh_global_index;
411}
413template<unsigned SPACE_DIM>
414void NodesOnlyMesh<SPACE_DIM>::SetNode(unsigned nodeIndex, ChastePoint<SPACE_DIM> point, bool concreteMove)
415{
416 // concreteMove should always be false for a NodesOnlyMesh as there are no elements to check
417 assert(!concreteMove);
418
419 // Update the node's location
420 this->GetNode(nodeIndex)->SetPoint(point);
421}
423template<unsigned SPACE_DIM>
424void NodesOnlyMesh<SPACE_DIM>::AddMovedNode(boost::shared_ptr<Node<SPACE_DIM> > pMovedNode)
425{
426 // Make a deep copy of this node pointer so that it isn't accidentally deleted.
427 unsigned index = pMovedNode->GetIndex();
428 c_vector<double, SPACE_DIM> location = pMovedNode->rGetLocation();
429
430 Node<SPACE_DIM>* p_node = new Node<SPACE_DIM>(index, location);
431
432 if (pMovedNode->HasNodeAttributes())
434 double radius = pMovedNode->GetRadius();
435 p_node->SetRadius(radius);
436
437 unsigned region = pMovedNode->GetRegion();
438 p_node->SetRegion(region);
439
440 bool is_particle = pMovedNode->IsParticle();
441 p_node->SetIsParticle(is_particle);
443 for (unsigned i=0; i<pMovedNode->GetNumNodeAttributes(); i++)
444 {
445 double attribute = pMovedNode->rGetNodeAttributes()[i];
446 p_node->AddNodeAttribute(attribute);
447 }
448 }
449
450 AddNodeWithFixedIndex(p_node);
451}
452
453template<unsigned SPACE_DIM>
455{
456 if (this->GetNode(index)->IsDeleted())
457 {
458 EXCEPTION("Trying to delete a deleted node");
459 }
460
461 unsigned local_index = SolveNodeMapping(index);
462
463 this->mNodes[local_index]->MarkAsDeleted();
464 this->mDeletedNodeIndices.push_back(local_index);
465 mDeletedGlobalNodeIndices.push_back(index);
466}
467
468template<unsigned SPACE_DIM>
471 DeleteNode(index);
472
473 // Remove index from deleted indices, as moved indices must not be re-used.
474 mDeletedGlobalNodeIndices.pop_back();
475}
476
477template<unsigned SPACE_DIM>
479{
480 assert(!(separation < 0.0));
481
482 mMinimumNodeDomainBoundarySeparation = separation;
484
485template<unsigned SPACE_DIM>
487{
488 unsigned index;
489
490 if (!this->mDeletedGlobalNodeIndices.empty())
491 {
492 index = this->mDeletedGlobalNodeIndices.back();
493 this->mDeletedGlobalNodeIndices.pop_back();
494 }
495 else
497 unsigned counter = mIndexCounter;
498 mIndexCounter++;
499 index = counter * PetscTools::GetNumProcs() + PetscTools::GetMyRank();
500 }
501
502 return index;
503}
504
505template <unsigned SPACE_DIM>
507{
508 assert(mpBoxCollection);
509
510 int num_local_rows = mpBoxCollection->GetNumLocalRows();
511 int new_local_rows = num_local_rows + (int)(PetscTools::AmTopMost()) + (int)(PetscTools::AmMaster());
512
513 c_vector<double, 2 * SPACE_DIM> current_domain_size = mpBoxCollection->rGetDomainSize();
514 c_vector<double, 2 * SPACE_DIM> new_domain_size;
515 new_domain_size = current_domain_size;
516
517 double fudge = 1e-14;
518 c_vector<bool, SPACE_DIM> is_periodic = mpBoxCollection->GetIsPeriodicAllDims();
519 for (unsigned d = 0; d < SPACE_DIM; d++)
520 {
521 // We don't enlarge in periodic directions
522 if (!is_periodic(d))
523 {
524 new_domain_size[2 * d] = current_domain_size[2 * d] - (mMaximumInteractionDistance - fudge);
525 new_domain_size[2 * d + 1] = current_domain_size[2 * d + 1] + (mMaximumInteractionDistance - fudge);
526 }
527 }
528 SetUpBoxCollection(mMaximumInteractionDistance, new_domain_size, new_local_rows);
529}
530
531template<unsigned SPACE_DIM>
533{
534 assert(mpBoxCollection);
535
536 int is_local_node_close = 0;
537 c_vector<double, 2*SPACE_DIM> domain_boundary = mpBoxCollection->rGetDomainSize();
538
539 for (typename AbstractMesh<SPACE_DIM, SPACE_DIM>::NodeIterator node_iter = this->GetNodeIteratorBegin();
540 node_iter != this->GetNodeIteratorEnd();
541 ++node_iter)
542 {
543 c_vector<double, SPACE_DIM> location = node_iter->rGetLocation();
544
545 // We need to ignore periodic dimensions
546 c_vector<bool, SPACE_DIM> is_periodic = mpBoxCollection->GetIsPeriodicAllDims();
547 for (unsigned d=0; d<SPACE_DIM; d++)
548 {
549 if ( !is_periodic(d) &&
550 ( location[d] < (domain_boundary[2*d] + mMinimumNodeDomainBoundarySeparation) || location[d] > (domain_boundary[2*d+1] - mMinimumNodeDomainBoundarySeparation) ) )
551 {
552 is_local_node_close = 1;
553 break;
554 }
555 }
556 if (is_local_node_close)
557 {
558 break; // Saves checking every node if we find one close to the boundary
559 }
560 }
561
562 // Synchronise between processes
563 int is_any_node_close = 0;
564 MPI_Allreduce(&is_local_node_close, &is_any_node_close, 1, MPI_INT, MPI_SUM, PetscTools::GetWorld());
565
566 return (is_any_node_close > 0);
567}
568
569template<unsigned SPACE_DIM>
571{
572 if (mpBoxCollection)
573 {
574 delete mpBoxCollection;
575 }
576 mpBoxCollection = nullptr;
577}
578
579template<unsigned SPACE_DIM>
580void NodesOnlyMesh<SPACE_DIM>::SetInitialBoxCollection(const c_vector<double, 2*SPACE_DIM> domainSize, double maxInteractionDistance)
581{
582 this->SetUpBoxCollection(maxInteractionDistance, domainSize);
583}
584
585template<unsigned SPACE_DIM>
587{
588 ClearBoxCollection();
589
590 ChasteCuboid<SPACE_DIM> bounding_box = this->CalculateBoundingBox(rNodes);
591
592 // Note that in circumstances where parts of the bounding box are a long way from the origin then
593 // a hard-coded "swell factor" of 1e-14 will not be noticed.
594 // For example 200*machine_epsilon = 200*2.2e-16 = 4.4e-14 which implies 200+1e-14 == 200.
595
596 double swell_factor = bounding_box.GetWidth(bounding_box.GetLongestAxis()); // Largest dimension
597 swell_factor = (1 + swell_factor) * 1e-14; // Make sure that it's non-zero
598
599 c_vector<double, 2*SPACE_DIM> domain_size;
600 for (unsigned i=0; i < SPACE_DIM; i++)
601 {
602 domain_size[2*i] = bounding_box.rGetLowerCorner()[i] - swell_factor;
603 domain_size[2*i+1] = bounding_box.rGetUpperCorner()[i] + swell_factor;
604 }
605 SetUpBoxCollection(mMaximumInteractionDistance, domain_size);
606}
607
608template<unsigned SPACE_DIM>
609void NodesOnlyMesh<SPACE_DIM>::SetUpBoxCollection(double cutOffLength, c_vector<double, 2*SPACE_DIM> domainSize, int numLocalRows, c_vector<bool,SPACE_DIM> isDimPeriodic)
610{
611 ClearBoxCollection();
612
613 bool isPeriodicInX = false;
614 bool isPeriodicInY = false;
615 bool isPeriodicInZ = false;
616
617 for ( unsigned i=0; i<SPACE_DIM; i++ )
618 {
619 if ( i==0 )
620 {
621 isPeriodicInX = isDimPeriodic(i);
622 }
623 if ( i==1 )
624 {
625 isPeriodicInY = isDimPeriodic(i);
626 }
627 if ( i==2 )
628 {
629 isPeriodicInZ = isDimPeriodic(i);
630 }
631 }
632 mpBoxCollection = new DistributedBoxCollection<SPACE_DIM>(cutOffLength, domainSize, isPeriodicInX, isPeriodicInY, isPeriodicInZ, numLocalRows);
633 mpBoxCollection->SetupLocalBoxesHalfOnly();
634 mpBoxCollection->SetCalculateNodeNeighbours(mCalculateNodeNeighbours);
635}
636
637template<unsigned SPACE_DIM>
639{
640 // Put the nodes in the boxes.
641 for (typename AbstractMesh<SPACE_DIM, SPACE_DIM>::NodeIterator node_iter = this->GetNodeIteratorBegin();
642 node_iter != this->GetNodeIteratorEnd();
643 ++node_iter)
644 {
645 unsigned box_index = mpBoxCollection->CalculateContainingBox(&(*node_iter));
646 mpBoxCollection->rGetBox(box_index).AddNode(&(*node_iter));
647 }
648}
649
650template<unsigned SPACE_DIM>
652{
653 // Add halo nodes
654 for (typename std::vector<boost::shared_ptr<Node<SPACE_DIM> > >::iterator halo_node_iter = mHaloNodes.begin();
655 halo_node_iter != mHaloNodes.end();
656 ++halo_node_iter)
657 {
658 unsigned box_index = mpBoxCollection->CalculateContainingBox((*halo_node_iter).get());
659 mpBoxCollection->rGetHaloBox(box_index).AddNode((*halo_node_iter).get());
660 }
661}
662
663template<unsigned SPACE_DIM>
665{
666 assert(mpBoxCollection);
667
668 // Remove node pointers from boxes in BoxCollection.
669 mpBoxCollection->EmptyBoxes();
670
671 AddNodesToBoxes();
672
673 mpBoxCollection->UpdateHaloBoxes();
674}
675
676template<unsigned SPACE_DIM>
678{
679 if (!mpBoxCollection)
680 {
681 SetUpBoxCollection(this->mNodes);
682 }
683
684 while (IsANodeCloseToDomainBoundary())
685 {
686 EnlargeBoxCollection();
687 }
688}
689
690template<unsigned SPACE_DIM>
692{
693 return mpBoxCollection->GetIsPeriodicAcrossProcs();
694}
695
696template<unsigned SPACE_DIM>
698{
699 std::vector<int> local_node_distribution = mpBoxCollection->CalculateNumberOfNodesInEachStrip();
700
701 unsigned new_rows = mpBoxCollection->LoadBalance(local_node_distribution);
702
703 c_vector<double, 2*SPACE_DIM> current_domain_size = mpBoxCollection->rGetDomainSize();
704
705 // This ensures the domain will stay the same size.
706 double fudge = 1e-14;
707 for (unsigned d=0; d < SPACE_DIM; d++)
708 {
709 current_domain_size[2*d] = current_domain_size[2*d] + fudge;
710 current_domain_size[2*d+1] = current_domain_size[2*d+1] - fudge;
711 }
712 SetUpBoxCollection(mMaximumInteractionDistance, current_domain_size, new_rows);
713}
714
715template<unsigned SPACE_DIM>
717{
719
720 // Set the correct global node indices
721 for (unsigned i=0; i<this->mNodes.size(); i++)
722 {
723 this->mNodes[i]->SetIndex(GetNextAvailableIndex());
724 }
725}
726
727template<unsigned SPACE_DIM>
729{
730 std::vector<unsigned> indices(GetNumNodes()); // GetNumNodes = mNodes - mDeletedNodes
731 unsigned live_index=0;
732 for (unsigned i=0; i<this->mNodes.size(); i++)
733 {
734 // Only use nodes which are not deleted
735 if (!this->mNodes[i]->IsDeleted())
736 {
737 indices[live_index] = this->mNodes[i]->GetIndex();
738 live_index++;
739 }
740 }
741 return indices;
742}
743
744// Explicit instantiation
745template class NodesOnlyMesh<1>;
746template class NodesOnlyMesh<2>;
747template class NodesOnlyMesh<3>;
748
749// Serialization for Boost >= 1.36
#define EXCEPTION(message)
#define EXPORT_TEMPLATE_CLASS_SAME_DIMS(CLASS)
virtual double GetWidth(const unsigned &rDimension) const
std::vector< Node< SPACE_DIM > * > mNodes
const ChastePoint< SPACE_DIM > & rGetUpperCorner() const
const ChastePoint< SPACE_DIM > & rGetLowerCorner() const
unsigned GetLongestAxis() const
double GetWidth(unsigned rDimension) const
void SetDeleted(unsigned index)
Definition NodeMap.cpp:76
void ResetToIdentity()
Definition NodeMap.cpp:57
Definition Node.hpp:59
void SetRegion(unsigned region)
Definition Node.cpp:430
void AddNodeAttribute(double attribute)
Definition Node.cpp:170
std::vector< double > & rGetNodeAttributes()
Definition Node.cpp:178
void SetIndex(unsigned index)
Definition Node.cpp:121
void SetRadius(double radius)
Definition Node.cpp:256
unsigned GetIndex() const
Definition Node.cpp:158
void SetIsParticle(bool isParticle)
Definition Node.cpp:240
void ClearBoxCollection()
void AddMovedNode(boost::shared_ptr< Node< SPACE_DIM > > pMovedNode)
void ConstructNodesWithoutMesh(const std::vector< Node< SPACE_DIM > * > &rNodes, double maxInteractionDistance)
double GetMaximumInteractionDistance()
void EnlargeBoxCollection()
unsigned GetNumNodes() const
virtual unsigned GetMaximumNodeIndex()
void AddNodeWithFixedIndex(Node< SPACE_DIM > *pNewNode)
void SetMaximumInteractionDistance(double maxDistance)
unsigned AddNode(Node< SPACE_DIM > *pNewNode)
void DeleteNode(unsigned index)
unsigned GetNextAvailableIndex()
void UpdateBoxCollection()
std::vector< unsigned > GetAllNodeIndices() const
void CalculateNodesOutsideLocalDomain()
void SetInitialBoxCollection(const c_vector< double, 2 *SPACE_DIM > domainSize, double maxInteractionDistance)
DistributedBoxCollection< SPACE_DIM > * GetBoxCollection()
std::vector< bool > & rGetInitiallyOwnedNodes()
void SetUpBoxCollection(const std::vector< Node< SPACE_DIM > * > &rNodes)
void SetCalculateNodeNeighbours(bool calculateNodeNeighbours)
void ConstructFromMeshReader(AbstractMeshReader< SPACE_DIM, SPACE_DIM > &rMeshReader)
void SetNode(unsigned nodeIndex, ChastePoint< SPACE_DIM > point, bool concreteMove=false)
Node< SPACE_DIM > * GetNodeOrHaloNode(unsigned index) const
virtual ~NodesOnlyMesh()
bool IsANodeCloseToDomainBoundary()
std::vector< unsigned > & rGetHaloNodesToSendRight()
double GetWidth(const unsigned &rDimension) const
void RemoveDeletedNodes(NodeMap &map)
std::vector< unsigned > & rGetNodesToSendLeft()
unsigned SolveNodeMapping(unsigned index) const
void CalculateBoundaryNodePairs(std::vector< std::pair< Node< SPACE_DIM > *, Node< SPACE_DIM > * > > &rNodePairs)
void ResizeBoxCollection()
void SetMinimumNodeDomainBoundarySeparation(double separation)
void AddHaloNode(boost::shared_ptr< Node< SPACE_DIM > > pNewNode)
std::vector< unsigned > & rGetHaloNodesToSendLeft()
void AddHaloNodesToBoxes()
void DeleteMovedNode(unsigned index)
void CalculateInteriorNodePairs(std::vector< std::pair< Node< SPACE_DIM > *, Node< SPACE_DIM > * > > &rNodePairs)
bool GetIsPeriodicAcrossProcsFromBoxCollection() const
bool IsOwned(c_vector< double, SPACE_DIM > &location)
std::vector< unsigned > & rGetNodesToSendRight()
static MPI_Comm GetWorld()
static bool AmMaster()
static bool AmTopMost()
static unsigned GetMyRank()
static unsigned GetNumProcs()
void ConstructFromMeshReader(AbstractMeshReader< ELEMENT_DIM, SPACE_DIM > &rMeshReader)