60OctantRec :: giveNodeList()
66OctantRec :: giveIPElementList()
72OctantRec :: giveElementList(
int region)
82OctantRec :: giveChild(
int xi,
int yi,
int zi)
84 if ( ( xi >= 0 ) && ( xi < 2 ) && ( yi >= 0 ) && ( yi < 2 ) && ( zi >= 0 ) && ( zi < 2 ) ) {
85 return this->
child [ xi ] [ yi ] [ zi ].get();
89 OOFEM_ERROR(
"invalid child index (%d,%d,%d)", xi, yi, zi);
96OctantRec :: ChildStatus
105 for (
int i = 0; i < coords.
giveSize(); ++i ) {
106 ind[i] = mask[i] && coords[i] > this->
origin[i];
109 child = this->child [ ind[0] ] [ ind[1] ] [ ind[2] ].get();
115OctantRec :: isTerminalOctant()
119 return ! this->
child [ 0 ] [ 0 ] [ 0 ];
124OctantRec :: divideLocally(
int level,
const IntArray &mask)
128 for (
int i = 0; i <= mask.
at(1); i++ ) {
129 for (
int j = 0; j <= mask.
at(2); j++ ) {
130 for (
int k = 0; k <= mask.
at(3); k++ ) {
132 this->
origin.at(1) + ( i - 0.5 ) * this->halfWidth * mask.
at(1),
133 this->origin.at(2) + ( j - 0.5 ) * this->halfWidth * mask.
at(2),
134 this->origin.at(3) + ( k - 0.5 ) * this->halfWidth * mask.
at(3)
136 this->
child [ i ] [ j ] [ k ] = std::make_unique<OctantRec>(
this, std::move(childOrigin), this->
halfWidth * 0.5);
142 int newLevel = level - 1;
143 if ( newLevel > 0 ) {
145 for (
int i = 0; i <= mask.
at(1); i++ ) {
146 for (
int j = 0; j <= mask.
at(2); j++ ) {
147 for (
int k = 0; k <= mask.
at(3); k++ ) {
148 if ( this->
child [ i ] [ j ] [ k ] ) {
149 this->
child [ i ] [ j ] [ k ]->divideLocally(newLevel, mask);
158OctantRec :: BoundingBoxStatus
161 bool bbInside =
true;
163 for (
int i = 1; i <= coords.
giveSize(); i++ ) {
165 double bb0 = coords.
at(i) - radius;
166 double bb1 = coords.
at(i) + radius;
170 if ( oct1 < bb0 || oct0 > bb1 ) {
174 bbInside = bbInside && oct0 < bb0 && oct1 > bb1;
181void OctantRec :: printYourself()
184 std :: cout <<
" center = {" << this->
origin.at(1) <<
"," << this->
origin.at(2) <<
"," << this->
origin.at(3)
187 if ( this->
depth == 0 ) {
188 printf(
"*ROOTCELL*");
191 for (
int i = 0; i <= 1; i++ ) {
192 for (
int j = 0; j <= 1; j++ ) {
193 for (
int k = 0; k <= 1; k++ ) {
194 if ( this->
child [ i ] [ j ] [ k ] ) {
195 for (
int q = 0; q < this->
depth - 1; q++ ) {
199 this->
child [ i ] [ j ] [ k ]->printYourself();
215 omp_init_lock(&ElementIPDataStructureLock);
216 omp_init_lock(&buildOctreeDataStructureLock);
217 omp_init_lock(&initLock);
229 if ( result == OctantRec :: CS_NoChild ) {
230 OOFEM_ERROR(
"internal error - octree inconsistency");
238OctreeSpatialLocalizer :: buildOctreeDataStructure()
241 int init = 1, nnode = this->
domain->giveNumberOfDofManagers();
242 double rootSize, resolutionLimit;
250 omp_set_lock(&buildOctreeDataStructureLock);
252 omp_unset_lock(&buildOctreeDataStructureLock);
266 for (
int i = 1; i <= nnode; i++ ) {
272 for (
int j = 1; j <= coords.giveSize(); j++ ) {
273 minc.at(j) = maxc.
at(j) = coords.at(j);
276 for (
int j = 1; j <= coords.giveSize(); j++ ) {
277 if ( coords.at(j) < minc.at(j) ) {
278 minc.at(j) = coords.at(j);
281 if ( coords.at(j) > maxc.
at(j) ) {
282 maxc.
at(j) = coords.at(j);
291 for (
int i = 1; i <= 3; i++ ) {
292 rootSize =
max( rootSize, 1.000001 * (maxc.
at(i) - minc.at(i)) );
296 resolutionLimit =
min(1.e-3, rootSize / 1.e6);
297 for (
int i = 1; i <= 3; i++ ) {
298 if ( ( maxc.
at(i) - minc.at(i) ) > resolutionLimit ) {
309 this->
rootCell = std::make_unique<OctantRec>(
nullptr, center, rootSize * 0.5);
317 for (
int i = 1; i <= nnode; i++ ) {
331 omp_unset_lock(&buildOctreeDataStructureLock);
338OctreeSpatialLocalizer :: initElementIPDataStructure()
342 int nelems = this->
domain->giveNumberOfElements();
348 omp_set_lock(&ElementIPDataStructureLock);
350 omp_unset_lock(&ElementIPDataStructureLock);
355 for (
int i = 1; i <= nelems; i++ ) {
391 omp_unset_lock(&ElementIPDataStructureLock);
407OctreeSpatialLocalizer :: initElementDataStructure(
int region)
416 for (
int i = 1; i <= this->
domain->giveNumberOfElements(); i++ ) {
421 interface->SpatialLocalizerI_giveBBox(b0, b1);
440 for (
int i = 1; i <= b0.
giveSize(); i++ ) {
442 bbc [ 0 ].
at(i) = b0.
at(i) <= origin.
at(i);
443 bbc [ 1 ].
at(i) = b1.
at(i) >= origin.
at(i);
445 bbc [ 0 ].
at(i) = bbc [ 1 ].
at(i) =
true;
448 for (
int i = b0.
giveSize() + 1; i <= 3; i++ ) {
449 bbc [ 0 ].
at(i) = bbc [ 1 ].
at(i) =
true;
452 if (
rootCell.isTerminalOctant() ) {
453 rootCell.addElement(region, elemNum);
457 for (
int i = 0; i <=
octreeMask.at(1); i++ ) {
458 if ( bbc [ i ].at(1) ) {
459 for (
int j = 0; j <=
octreeMask.at(2); j++ ) {
460 if ( bbc [ j ].at(2) ) {
461 for (
int k = 0; k <=
octreeMask.at(3); k++ ) {
462 if ( bbc [ k ].at(3) &&
rootCell.giveChild(i, j, k) ) {
475OctreeSpatialLocalizer :: insertElementsUsingNodalConnectivitiesIntoOctree(
OctantRec &currCell)
480 const IntArray *dofmanConnectivity =
domain->giveConnectivityTable()->giveDofManConnectivityArray(inod);
481 if ( dofmanConnectivity ) {
482 for (
int d: *dofmanConnectivity ) {
488 for (
int i = 0; i <=
octreeMask.at(1); i++ ) {
489 for (
int j = 0; j <=
octreeMask.at(2); j++ ) {
490 for (
int k = 0; k <=
octreeMask.at(3); k++ ) {
491 auto child = currCell.
giveChild(i, j, k);
509 int nCellItems = (int) cellNodeList.size();
518 for (
int inod: cellNodeList ) {
538 if ( result != OctantRec :: CS_ChildFound ) {
539 OOFEM_ERROR(
"internal error - octree inconsistency");
549OctreeSpatialLocalizer :: giveElementContainingPoint(
const FloatArray &coords,
const IntArray *regionList)
551 OctantRec *currCell, *childCell =
nullptr;
565 childCell = currCell;
576OctreeSpatialLocalizer :: giveElementContainingPoint(
const FloatArray &coords,
const Set &eset)
578 OctantRec *currCell, *childCell =
nullptr;
593 childCell = currCell;
624 if ( interface->SpatialLocalizerI_BBoxContainsPoint(coords) == 0 ) {
628 if ( interface->SpatialLocalizerI_containsPoint(coords) ) {
637 for (
int i = 0; i <=
octreeMask.at(1); i++ ) {
638 for (
int j = 0; j <=
octreeMask.at(2); j++ ) {
639 for (
int k = 0; k <=
octreeMask.at(3); k++ ) {
642 if ( scannedChild == child ) {
679 if ( interface->SpatialLocalizerI_BBoxContainsPoint(coords) == 0 ) {
683 if ( interface->SpatialLocalizerI_containsPoint(coords) ) {
692 for (
int i = 0; i <=
octreeMask.at(1); i++ ) {
693 for (
int j = 0; j <=
octreeMask.at(2); j++ ) {
694 for (
int k = 0; k <=
octreeMask.at(3); k++ ) {
697 if ( scannedChild == child ) {
720 std :: list< OctantRec * >cellList;
722 double radius, prevRadius;
737 while ( radius < minDist ) {
750OctreeSpatialLocalizer :: giveElementClosestToPointWithinOctant(
OctantRec &currCell,
const FloatArray &gcoords,
757 for (
int iel: elementList ) {
769 if ( currDist < minDist ) {
770 lcoords = currLcoords;
771 closest = currClosest;
774 if ( minDist == 0.0 ) {
783OctreeSpatialLocalizer :: giveClosestIP(
const FloatArray &coords,
int region,
bool iCohesiveZoneGP)
793 double minDist = 1.1 *
rootCell->giveWidth();
799 for (
int iel: elementList ) {
810 if ( !iCohesiveZoneGP ) {
816 double dist =
distance(coords, jGpCoords);
817 if ( dist < minDist ) {
832 for (
size_t czRuleIndex = 0; czRuleIndex < numCZRules; czRuleIndex++ ) {
835 for (
auto &jGp: *iRule ) {
838 double dist =
distance(coords, jGpCoords);
840 if ( dist < minDist ) {
860 if ( BBStatus == OctantRec :: BBS_InsideCell ) {
862 }
else if ( BBStatus == OctantRec :: BBS_ContainsCell ) {
863 std :: list< OctantRec * >cellList;
868 if ( startCell !=
rootCell.get() ) {
869 while ( startCell->
testBoundingBox(coords, minDist, this->octreeMask) != OctantRec :: BBS_InsideCell ) {
871 if ( startCell ==
rootCell.get() ) {
880 if ( currCell == icell ) {
894 while ( startCell->
testBoundingBox(coords, minDist, this->octreeMask) != OctantRec :: BBS_InsideCell ) {
910 set< int >nearElementList;
915 if ( !nearElementList.empty() ) {
916 for (
int elnum: nearElementList ) {
917 ielem =
domain->giveElement(elnum);
919 if ( region == ielem->giveRegionNumber() ) {
920 iRule = ielem->giveDefaultIntegrationRulePtr();
921 for (
auto &jGp: *iRule ) {
922 if ( ielem->computeGlobalCoordinates( jGpCoords, * ( jGp->giveCoordinates() ) ) ) {
924 double dist =
distance(coords, jGpCoords);
925 if ( dist < minDist ) {
947OctreeSpatialLocalizer :: giveClosestIPWithinOctant(
OctantRec ¤tCell,
949 int region,
double &dist,
GaussPoint *&answer,
bool iCohesiveZoneGP)
967 if ( !iCohesiveZoneGP ) {
973 double currDist =
distance(coords, jGpCoords);
975 if ( currDist <= dist ) {
990 for (
size_t czRuleIndex = 0; czRuleIndex < numCZRules; czRuleIndex++ ) {
993 for (
auto &gp: *iRule ) {
995 double currDist =
distance(coords, jGpCoords);
997 if ( currDist <= dist ) {
1011 for (
int i = 0; i <=
octreeMask.at(1); i++ ) {
1012 for (
int j = 0; j <=
octreeMask.at(2); j++ ) {
1013 for (
int k = 0; k <=
octreeMask.at(3); k++ ) {
1017 if ( BBStatus == OctantRec :: BBS_InsideCell || BBStatus == OctantRec :: BBS_ContainsCell ) {
1031OctreeSpatialLocalizer :: giveClosestIP(
const FloatArray &coords,
Set &elementSet,
bool iCohesiveZoneGP)
1041 double minDist = 1.1 *
rootCell->giveWidth();
1057 if ( !iCohesiveZoneGP ) {
1063 double dist =
distance(coords, jGpCoords);
1064 if ( dist < minDist ) {
1079 for (
size_t czRuleIndex = 0; czRuleIndex < numCZRules; czRuleIndex++ ) {
1082 for (
auto &jGp: *iRule ) {
1085 double dist =
distance(coords, jGpCoords);
1087 if ( dist < minDist ) {
1107 if ( BBStatus == OctantRec :: BBS_InsideCell ) {
1109 }
else if ( BBStatus == OctantRec :: BBS_ContainsCell ) {
1110 std :: list< OctantRec * >cellList;
1115 if ( startCell !=
rootCell.get() ) {
1116 while ( startCell->
testBoundingBox(coords, minDist, this->octreeMask) != OctantRec :: BBS_InsideCell ) {
1118 if ( startCell ==
rootCell.get() ) {
1127 if ( currCell == icell ) {
1141 while ( startCell->
testBoundingBox(coords, minDist, this->octreeMask) != OctantRec :: BBS_InsideCell ) {
1157 set< int >nearElementList;
1162 if ( !nearElementList.empty() ) {
1163 for (
int iel: nearElementList ) {
1170 double dist =
distance(coords, jGpCoords);
1171 if ( dist < minDist ) {
1194OctreeSpatialLocalizer :: giveClosestIPWithinOctant(
OctantRec ¤tCell,
1196 Set &elementSet,
double &dist,
GaussPoint *&answer,
bool iCohesiveZoneGP)
1215 if ( !iCohesiveZoneGP ) {
1221 currDist =
distance(coords, jGpCoords);
1223 if ( currDist <= dist ) {
1238 for (
size_t czRuleIndex = 0; czRuleIndex < numCZRules; czRuleIndex++ ) {
1241 for (
auto &gp: *iRule ) {
1243 currDist =
distance(coords, jGpCoords);
1245 if ( currDist <= dist ) {
1259 for (
int i = 0; i <=
octreeMask.at(1); i++ ) {
1260 for (
int j = 0; j <=
octreeMask.at(2); j++ ) {
1261 for (
int k = 0; k <=
octreeMask.at(3); k++ ) {
1265 if ( BBStatus == OctantRec :: BBS_InsideCell || BBStatus == OctantRec :: BBS_ContainsCell ) {
1280 const double radius,
bool iCohesiveZoneGP)
1287 if ( currCell !=
rootCell.get() ) {
1288 while ( currCell->
testBoundingBox(coords, radius, this->octreeMask) != OctantRec :: BBS_InsideCell ) {
1290 if ( currCell ==
rootCell.get() ) {
1303 const double radius,
bool iCohesiveZoneGP)
1314 const FloatArray &coords,
const double radius,
bool iCohesiveZoneGP)
1331 if ( !iCohesiveZoneGP ) {
1335 currDist =
distance(coords, jGpCoords);
1337 if ( currDist <= radius ) {
1352 for (
size_t czRuleIndex = 0; czRuleIndex < numCZRules; czRuleIndex++ ) {
1355 for (
auto &gp: *iRule ) {
1357 currDist =
distance(coords, jGpCoords);
1359 if ( currDist <= radius ) {
1361 czRuleIndex = numCZRules;
1374 for (
int i = 0; i <=
octreeMask.at(1); i++ ) {
1375 for (
int j = 0; j <=
octreeMask.at(2); j++ ) {
1376 for (
int k = 0; k <=
octreeMask.at(3); k++ ) {
1377 auto child = currentCell.
giveChild(i, j, k);
1380 auto BBStatus = child->testBoundingBox(coords, radius, this->
octreeMask);
1381 if ( BBStatus == OctantRec :: BBS_InsideCell || BBStatus == OctantRec :: BBS_ContainsCell ) {
1400 if ( currCell !=
rootCell.get() ) {
1401 while ( currCell->
testBoundingBox(coords, radius, this->octreeMask) != OctantRec :: BBS_InsideCell ) {
1403 if ( currCell ==
rootCell.get() ) {
1415OctreeSpatialLocalizer :: giveNodeClosestToPoint(
const FloatArray &gcoords,
double maxDist)
1417 Node *answer =
nullptr;
1418 std :: list< OctantRec * > cellList;
1421 double minDist = maxDist;
1428 double prevRadius = 0.;
1435 prevRadius = radius;
1437 }
while ( prevRadius < minDist );
1444 double &minDist,
Node * &answer)
1446 double minDist2 = minDist*minDist;
1452 if ( currDist2 < minDist2 ) {
1454 minDist2 = currDist2;
1457 minDist = sqrt(minDist2);
1463 const FloatArray &coords,
const double radius)
1467 if ( !cellNodes.empty() ) {
1468 for (
int inod: cellNodes ) {
1470 const auto &nodeCoords =
domain->giveNode(inod)->giveCoordinates();
1472 if (
distance(nodeCoords, coords) <= radius ) {
1474 nodeList.push_back(inod);
1479 for (
int i = 0; i <=
octreeMask.at(1); i++ ) {
1480 for (
int j = 0; j <=
octreeMask.at(2); j++ ) {
1481 for (
int k = 0; k <=
octreeMask.at(3); k++ ) {
1482 auto child = currentCell.
giveChild(i, j, k);
1485 auto BBStatus = child->testBoundingBox(coords, radius, this->
octreeMask);
1486 if ( BBStatus == OctantRec :: BBS_InsideCell || BBStatus == OctantRec :: BBS_ContainsCell ) {
1499OctreeSpatialLocalizer :: giveMaxTreeDepthFrom(
OctantRec &root)
1502 for (
int i = 0; i <=
octreeMask.at(1); i++ ) {
1503 for (
int j = 0; j <=
octreeMask.at(2); j++ ) {
1504 for (
int k = 0; k <=
octreeMask.at(3); k++ ) {
1512 return maxDepth + 1;
1517OctreeSpatialLocalizer :: giveListOfTerminalCellsInBoundingBox(std :: list< OctantRec * > &cellList,
const FloatArray &coords,
1518 double radius,
double innerRadius,
OctantRec ¤tCell)
1521 if ( BBStatus != OctantRec :: BBS_OutsideCell ) {
1524 cellList.push_back(¤tCell);
1527 for (
int i = 0; i <=
octreeMask.at(1); i++ ) {
1528 for (
int j = 0; j <=
octreeMask.at(2); j++ ) {
1529 for (
int k = 0; k <=
octreeMask.at(3); k++ ) {
1530 auto child = currentCell.
giveChild(i, j, k);
1543OctreeSpatialLocalizer :: init(
bool force)
1549 omp_set_lock(&initLock);
1551 omp_unset_lock(&initLock);
1562 omp_unset_lock(&initLock);
1569 omp_set_lock(&initLock);
1571 omp_unset_lock(&initLock);
1580 omp_unset_lock(&initLock);
const FloatArray & giveCoordinates() const
Node * giveNode(int i) const
virtual int computeGlobalCoordinates(FloatArray &answer, const FloatArray &lcoords)
virtual int giveNumberOfNodes() const
int giveNumberOfIntegrationRules()
elementParallelMode giveParallelMode() const
virtual IntegrationRule * giveDefaultIntegrationRulePtr()
virtual Interface * giveInterface(InterfaceType t)
Index giveSize() const
Returns the size of receiver.
virtual void printYourself() const
void add(const FloatArray &src)
bool insertSortedOnce(int value, int allocChunk=0)
int findSorted(int value) const
int findFirstIndexOf(int value) const
std ::list< int > nodeList
Octant node list.
std ::list< int > & giveNodeList()
OctantRec * giveChild(int xi, int yi, int zi)
void addNode(int nodeNum)
FloatArray origin
Octant origin coordinates (lower corner).
std ::vector< std ::list< int > > elementList
Element list of all elements close to the cell.
std::unique_ptr< OctantRec > child[2][2][2]
Link to octant children.
void divideLocally(int level, const IntArray &octantMask)
std ::list< int > & giveElementList(int region)
double halfWidth
Octant size.
OctantRec * parent
Link to parent cell record.
OctantRec(OctantRec *parent, FloatArray origin, double halfWidth)
Constructor.
BoundingBoxStatus testBoundingBox(const FloatArray &coords, double radius, const IntArray &mask)
void addElementIP(int elementNum)
IntArray elementIPList
Element list, containing all elements having IP in cell.
IntArray & giveIPElementList()
ChildStatus giveChildContainingPoint(OctantRec *&child, const FloatArray &coords, const IntArray &mask)
int init(bool force=false) override
OctantRec * findTerminalContaining(OctantRec &startCell, const FloatArray &coords)
bool elementIPListsInitialized
Flag indicating elementIP tables are initialized.
int giveMaxTreeDepthFrom(OctantRec &root)
void insertIPElementIntoOctree(OctantRec &rootCell, int elemNum, const FloatArray &coords)
void giveElementClosestToPointWithinOctant(OctantRec &currCell, const FloatArray &gcoords, double &minDist, FloatArray &lcoords, FloatArray &closest, Element *&answer, int region)
void giveAllElementsWithIpWithinBox(elementContainerType &elemSet, const FloatArray &coords, const double radius) override
void giveNodesWithinBox(nodeContainerType &nodeList, OctantRec ¤tCell, const FloatArray &coords, const double radius)
void initElementIPDataStructure()
std::unique_ptr< OctantRec > rootCell
Root cell of octree.
Element * giveElementContainingPoint(const FloatArray &coords, const IntArray *regionList=nullptr) override
void insertNodeIntoOctree(OctantRec &rootCell, int nodeNum, const FloatArray &coords)
IntArray octreeMask
Octree degenerate mask.
void giveClosestIPWithinOctant(OctantRec ¤tCell, const FloatArray &coords, int region, double &dist, GaussPoint *&answer, bool iCohesiveZoneGP)
void initElementDataStructure(int region=0)
void insertElementIntoOctree(OctantRec &rootCell, int region, int elemNum, const FloatArray &b0, const FloatArray &b1)
bool buildOctreeDataStructure()
void giveAllElementsWithIpWithinBox_EvenIfEmpty(elementContainerType &elemSet, const FloatArray &coords, const double radius) override
IntArray elementListsInitialized
void giveElementsWithIPWithinBox(elementContainerType &elemSet, OctantRec ¤tCell, const FloatArray &coords, const double radius, bool iCohesiveZoneGP=false)
void giveNodeClosestToPointWithinOctant(OctantRec &cell, const FloatArray &gcoords, double &minDist, Node *&answer)
void insertElementsUsingNodalConnectivitiesIntoOctree(OctantRec &rootCell)
void giveListOfTerminalCellsInBoundingBox(std ::list< OctantRec * > &cellList, const FloatArray &coords, const double radius, double innerRadius, OctantRec ¤tCell)
bool hasElement(int elem) const
Return True if given element is contained.
virtual double SpatialLocalizerI_giveClosestPoint(FloatArray &lcoords, FloatArray &closest, const FloatArray &gcoords)
SpatialLocalizer(Domain *d)
Constructor.
Domain * domain
Link to domain object.
Domain * giveDomain()
Returns the domain that localizer acts on.
std ::list< int > nodeContainerType
Typedefs to introduce the container type for nodal numbers, returned by some services.
IntArray elementContainerType
Typedefs to introduce the container type for element numbers, returned by some services.
double getUtime()
Returns total user time elapsed in seconds.
std ::vector< std ::unique_ptr< IntegrationRule > > mpCZIntegrationRules
#define OOFEM_LOG_INFO(...)
#define OOFEM_LOG_DEBUG(...)
FloatArrayF< N > min(const FloatArrayF< N > &a, const FloatArrayF< N > &b)
@ Element_remote
Element in active domain is only mirror of some remote element.
FloatArrayF< N > max(const FloatArrayF< N > &a, const FloatArrayF< N > &b)
@ SpatialLocalizerInterfaceType
double distance(const FloatArray &x, const FloatArray &y)
double distance_square(const FloatArray &x, const FloatArray &y)
static FloatArray Vec3(const double &a, const double &b, const double &c)
#define OCTREE_MAX_DEPTH
Max octree depth.
#define OCTREE_MAX_NODES_LIMIT
Max desired number of nodes per octant.