MAIA bb96820c
Multiphysics at AIA
Loading...
Searching...
No Matches
Geometry3D Class Reference

#include <geometry3d.h>

Inheritance diagram for Geometry3D:
[legend]
Collaboration diagram for Geometry3D:
[legend]

Public Member Functions

 Geometry3D (const MInt solverId_, const MPI_Comm comm)
 
 Geometry3D (const MInt solverId_, const MString &filename, const MPI_Comm comm)
 
 ~Geometry3D ()
 
MInt getIntersectionElements (MFloat *targetRegion, std::vector< MInt > &nodeList, MFloat cellHalfLength, const MFloat *const cell_coords) override
 Determines all elements that are inside or intersect the target region with the separating axis theorem (SAT). More...
 
MInt getIntersectionElements (MFloat *targetRegion, std::vector< MInt > &nodeList) override
 Determines all elements that are inside or intersect the target region. More...
 
virtual MInt getIntersectionElementsTetraeder (MFloat *targetRegion, std::vector< MInt > &nodeList)
 Determines all elements that are inside or intersect the target region. More...
 
MInt getLineIntersectionElementsOld2 (MFloat *targetRegion, MInt *spaceDirection, std::vector< MInt > &nodeList) override
 Returns the ids of all elements, cut by a orthogonal line (or rectangular region) More...
 
MInt getLineIntersectionElements (MFloat *targetRegion, std::vector< MInt > &nodeList) override
 Returns the ids of all elements, cut by a ray by using the perp-dot operator. More...
 
MInt getLineIntersectionElements (MFloat *targetRegion) override
 
MBool getClosestLineIntersectionLength (MInt bndCndId, const std::vector< MInt > &nodeList, MFloat *targetRegion, MFloat *dist) override
 
MBool edgeTriangleIntersection (MFloat *trianglePoint1, MFloat *trianglePoint2, MFloat *trianglePoint3, MFloat *edgePoint1, MFloat *edgePoint2) override
 Determine intersection between an edge and a triangle. More...
 
MBool edgeTriangleIntersectionLB (MFloat *trianglePoint1, MFloat *trianglePoint2, MFloat *trianglePoint3, MFloat *edgePoint1, MFloat *edgePoint2) override
 Determine intersection between an edge and a triangle. More...
 
MBool getLineTriangleIntersectionSimple (MFloat *p1, MFloat *p2, MFloat *v1, MFloat *v2, MFloat *v3) override
 This function determines if a line crosses a triangle. More...
 
MBool getLineTriangleIntersectionSimpleDistance (MFloat *p1, MFloat *p2, MFloat *v1, MFloat *v2, MFloat *v3, MFloat *dist) override
 This function determines if a line crosses a triangle. More...
 
MBool getLineTriangleIntersection (const MFloat *const p1, const MFloat *const p2, const MFloat radius, const MFloat *const v1, const MFloat *const v2, const MFloat *const v3, MFloat *intersection, MFloat *normal, MFloat *lambda2, MFloat *dist) override
 This function determines if a line crosses a triangle. More...
 
MInt getIntersectionMBElements (MFloat *targetRegion, std::vector< MInt > &nodeList) override
 
MInt getLineIntersectionMBElements (MFloat *targetRegion, std::vector< MInt > &nodeList) override
 
MInt getLineIntersectionMBElements2 (MFloat *targetRegion, MInt *spaceDirection, std::vector< MInt > &nodeList, MInt bcIc) override
 
MInt getSphereIntersectionMBElements (MFloat *P, MFloat radius, std::vector< MInt > &nodeList) override
 
void MoveAllMBElementVertex (MFloat *dx) override
 
void MoveMBElementVertex (MInt e, MInt v, MFloat *dx) override
 
void ReplaceMBElementVertex (MInt e, MInt v, MFloat *np) override
 
void UpdateMBNormalVector (MInt e) override
 
void UpdateMBBoundingBox () override
 
void UpdateADT () override
 
void writeSTL (const char *fileName) override
 
void writeSTLMB (const char *fileName, MInt &noNodes, MInt *&nodeList) override
 
void writeADTAndSTLToNetCDF (const char *fileName) override
 
void readSTLNetCDF (const char *fileName) override
 
void logStatistics () override
 
MFloat ** GetBoundaryVertices (MInt segmentId, MFloat *tri_vx, MInt *keepOffsets, MInt size, MInt *num) override
 This function gets all boundary vertices of an element<3> in a circular order. More...
 
virtual std::vector< std::pair< MFloat *, MFloat * > > GetUniqueSegmentEdgesParGeom (MFloat *tri_vx, MInt *keepOffsets, MInt size)
 Returns unique edges of a given set segment id for parallel geometry. More...
 
virtual std::vector< std::pair< MFloat *, MFloat * > > GetUniqueSegmentEdges (MInt segmentId)
 Returns unique edges of a given set segment id. More...
 
MBool isEdgeAlreadyInCollection (std::vector< std::pair< MFloat *, MFloat * > > tmp_edges, MFloat *p1, MFloat *p2, MInt *pos) override
 Checks if an edge given by two points is in a vector. More...
 
MFloat GetBoundarySize (MInt segmentId) override
 Returns the area of a segment. More...
 
MFloat GetBoundarySize (MFloat *vertices, MInt *keepOffset, MInt size) override
 Returns the area of a segment. More...
 
void determineSegmentOwnership (MInt segmentId, MInt *own, MInt *sumowners, MInt *firstOwner, MInt *owners) override
 Determines the ownership of a segment. More...
 
MFloat getBndMaxRadius (MFloat **vertices, MInt num) override
 This function gets the maximal radius for a boundary segment. More...
 
- Public Member Functions inherited from Geometry< 3 >
 Geometry (const MInt solverId_, const MPI_Comm comm)
 
virtual ~Geometry ()=default
 
MInt solverId () const
 
MPI_Comm mpiComm () const
 
MInt domainId () const
 
MInt noDomains () const
 
GeometryContextgeometryContext ()
 
void getBoundingBox (MFloat *const bBox) const
 Returns the bounding box for the geometry. More...
 
const MFloatboundingBox () const
 
void setHaloElementOffset (MInt off)
 
MInt getHaloElementOffset () const
 
MBool isOnGeometry (const MFloat, const MFloat *, MString)
 
MBool vectorsEqual (MFloat *a, MFloat *b)
 Compares two vectors entry by entry. More...
 
MFloat calcCircumference (MFloat **bndVs, MInt num)
 Returns the circumference of a segment. More...
 
virtual MInt boundaryCheck (MFloat *, MFloat, MFloat *, MInt *)
 
virtual MInt getIntersectionElements (MFloat *, std::vector< MInt > &)
 
virtual MInt getIntersectionElements (MFloat *, std::vector< MInt > &, MFloat, const MFloat *const)
 
virtual MInt getLineIntersectionElementsOld1 (MFloat *, std::vector< MInt > &)
 
virtual MInt getLineIntersectionElementsOld2 (MFloat *, MInt *, std::vector< MInt > &)
 
virtual MInt getLineIntersectionElements (MFloat *, std::vector< MInt > &)
 
virtual MInt getLineIntersectionElements (MFloat *)
 
virtual MBool getClosestLineIntersectionLength (MInt, const std::vector< MInt > &, MFloat *, MFloat *)
 
void getLineIntersectingElementsBcIds (const MFloat *const line, std::set< MInt > &bcIds)
 Return the set of boundary condition ids of the elements cut by the given line. More...
 
virtual MBool edgeTriangleIntersection (MFloat *, MFloat *, MFloat *, MFloat *, MFloat *)
 
virtual MBool edgeTriangleIntersectionLB (MFloat *, MFloat *, MFloat *, MFloat *, MFloat *)
 
virtual MBool getLineTriangleIntersectionSimple (MFloat *, MFloat *, MFloat *, MFloat *, MFloat *)
 
virtual MBool getLineTriangleIntersectionSimpleDistance (MFloat *, MFloat *, MFloat *, MFloat *, MFloat *, MFloat *)
 
virtual MBool getLineTriangleIntersection (const MFloat *const, const MFloat *const, const MFloat, const MFloat *const, const MFloat *const, const MFloat *const, MFloat *, MFloat *, MFloat *, MFloat *)
 
void getBoundingBoxMB (MFloat *const bBox) const
 
virtual MInt getIntersectionMBElements (MFloat *, std::vector< MInt > &)
 
virtual MInt getLineIntersectionMBElements (MFloat *, std::vector< MInt > &)
 
virtual MInt getLineIntersectionMBElements2 (MFloat *, MInt *, std::vector< MInt > &, MInt)
 
virtual MInt getSphereIntersectionMBElements (MFloat *, MFloat, std::vector< MInt > &)
 
virtual void MoveAllMBElementVertex (MFloat *)
 
virtual void MoveMBElementVertex (MInt, MInt, MFloat *)
 
virtual void ReplaceMBElementVertex (MInt, MInt, MFloat *)
 
virtual void UpdateMBNormalVector (MInt)
 
virtual void UpdateMBBoundingBox ()
 
virtual void UpdateADT ()
 
virtual void collectGlobalMemoryUsage ()
 
virtual void writeSTL (const MChar *)
 
virtual void writeADTAndSTLToNetCDF (const MChar *)
 
virtual void writeSTLMB (const MChar *, MInt &, MInt *&)
 
virtual void readSTLNetCDF (const MChar *)
 
virtual void logStatistics ()
 
virtual MInt GetNoElements ()
 
virtual MInt GetNoSegments ()
 
virtual MIntGetBoundaryIds (MInt *noAllBcs)
 
virtual MFloat ** GetBoundaryVertices (MInt, MFloat *, MInt *, MInt, MInt *)
 
virtual MBool isEdgeAlreadyInCollection (std::vector< std::pair< MFloat *, MFloat * > >, MFloat *, MFloat *, MInt *)
 
virtual MFloat GetBoundarySize (MInt)
 
virtual MFloat GetBoundarySize (MFloat *, MInt *, MInt)
 
virtual void determineSegmentOwnership (MInt, MInt *, MInt *, MInt *, MInt *)
 
virtual MFloat getBndMaxRadius (MFloat **, MInt)
 
virtual void rebuildAdtTree ()
 
virtual void calculateBoundingBox ()
 
virtual void writeParallelGeometryVTK (MString)
 
virtual void addElement (MFloat *)
 
virtual void copyElement (MInt, MInt)
 
virtual void resizeCollector (MInt)
 
MBool pointIsInside (const MFloat *const coordinates)
 Determines if a point is inside of the geometry. More...
 
MBool pointIsInside (const MFloat *const coordinates, MInt *numcutsperdir)
 Determines if a point is inside of the geometry. More...
 
MBool pointIsInside2 (const MFloat *const coordinates, MInt *numcutsperdir=nullptr)
 Determines if a point is in or outside the geometry. More...
 
MBool pointIsInsideMBElements (const MFloat *const coordinates, MInt *, MInt *, MInt)
 
MBool pointIsInsideMBElements2 (const MFloat *const coordinates, MInt *, MInt *, MInt)
 
void determineRayIntersectedElements (const MFloat *const coordinates, std::vector< std::vector< MInt > > *resultnodes)
 returns the geometry elements that have a cut with rays originating in the provided coordinates More...
 
MInt noBoundaryIds ()
 

Protected Member Functions

void readSegments () override
 reads the STL segments from file More...
 
virtual void correctVertexCoordinates ()
 
virtual void swap4BytesToBE (char *buf)
 swaps 4 bytes from little to big endian More...
 
virtual MInt is_big_endian ()
 determines the CPU type big or little endian More...
 
virtual Collector< element< 3 > > * readSegmentsSerial ()
 reads the segments in serial More...
 
virtual Collector< element< 3 > > * readSegmentsParallel ()
 
virtual void countSegmentTrianglesASCII (MString fileName, MInt *noElements)
 counts the number of triangles in an ASCII STL file More...
 
virtual void countSegmentTrianglesBINARY (MString fileName, MInt *noElements)
 counts the number of triangles in a BINARY STL file More...
 
virtual void countSegmentTrianglesNETCDF (MString fileName, MInt *noElements, const MPI_Comm comm)
 counts the number of triangles in a NETCDF STL file More...
 
virtual void readSegmentTrianglesASCII (MString fileName, Collector< element< 3 > > *elemCollector, MInt bndCndId, MInt segmentId, MInt *offset)
 reads triangles from an ASCII file More...
 
virtual void readSegmentTrianglesBINARY_BE (MString fileName, Collector< element< 3 > > *elemCollector, MInt bndCndId, MInt segmentId, MInt *offset)
 reads triangles from a BINARY file and swaps to big endian More...
 
virtual void readSegmentTrianglesBINARY_LE (MString fileName, Collector< element< 3 > > *elemCollector, MInt bndCndId, MInt segmentId, MInt *offset)
 reads triangles from a BINARY file and swaps to little endian More...
 
virtual void readSegmentTrianglesNETCDF (MString fileName, Collector< element< 3 > > *elemCollector, MInt bndCndId, MInt segmentId, MInt *offset, const MPI_Comm comm)
 reads triangles from a BINARY file More...
 
void rebuildAdtTree () override
 Rebuilds the ADT tree. More...
 
void calculateBoundingBox () override
 Calculates the global bounding box of the geometry. More...
 
void writeParallelGeometryVTK (MString filename) override
 Write the current geometry to a VTK file for parallel computation. More...
 
void printMemoryUsage ()
 prints the current memory usage of this object More...
 
void collectGlobalMemoryUsage () override
 
void addElement (MFloat *tri) override
 Adds an element<3> to the collector. More...
 
void copyElement (MInt from, MInt to) override
 Copies an element<3> from one poistion to another. More...
 
void copyElement (MInt from, MInt to, element< 3 > *fromPtr, element< 3 > *toPtr)
 Copies an element<3> from one poistion to another. More...
 
void resizeCollector (MInt new_size) override
 deletes the current element<3> collector and reinitializes More...
 
- Protected Member Functions inherited from Geometry< 3 >
virtual void readSegments ()
 
virtual void writeSegmentsToDX ()
 

Protected Attributes

MInt otherCalls = 0
 
MBool m_GFieldInitFromSTL = false
 
MInt m_levelSetIntfBndId = 0
 
MIntm_levelSetIntfBndIds {}
 
MInt m_noLevelSetIntfBndIds = 0
 
MBool m_forceBoundingBox = false
 
MString m_gridCutTest
 
MString m_geomFileType
 
MString m_gridFileName
 
MInt m_noAllTriangles {}
 
MInt m_getLIE2CallCounter = 0
 
MInt getLIE2CommCounter = 0
 
MInt getIECallCounter = 0
 
MInt getIECommCounter = 0
 
MInt getIETCallCounter = 0
 
MInt edgeTICallCounter = 0
 
MBool m_communicateSegmentsSerial = true
 
- Protected Attributes inherited from Geometry< 3 >
MInt m_noSegments
 
std::array< MFloat, 2 *nDim > m_minMax
 
MInt m_noElements
 
MString m_segmentBaseName
 
bodyMap m_bodyMap
 
bodyIterator m_bodyIt
 
MInt m_noMBElements
 
MInt m_noBoundaryIds
 
MIntm_boundaryIds
 
MIntm_allBCs
 
MInt m_noAllBCs
 
MBool m_flowSolver
 

Static Protected Attributes

static constexpr const MInt nDim = 3
 

Private Attributes

MInt m_tg_geometry {}
 
MInt m_t_geometryAll {}
 
MInt m_t_readGeometry {}
 

Additional Inherited Members

- Public Attributes inherited from Geometry< 3 >
std::vector< MIntm_segmentOffsets
 
std::vector< MIntm_segmentOffsetsWithoutMB
 
Collector< element< nDim > > * m_elements
 
element< nDim > * elements
 
GeometryAdt< nDim > * m_adt
 
Collector< element< nDim > > * m_mbelements
 
element< nDim > * mbelements
 
std::array< MFloat, 2 *nDim > m_mbminMax
 
MFloat m_mbMidPnt [3]
 
MBoolm_ownSegmentId
 
std::set< MIntm_uniqueOriginalTriId
 
MFloat m_parGeomMemFactor
 
MString m_inOutTest
 
MBool m_parallelGeometry
 
MBool m_debugParGeom
 
MString m_parallelGeomFileName
 

Detailed Description

Specialized 3D implementation

Definition at line 15 of file geometry3d.h.

Constructor & Destructor Documentation

◆ Geometry3D() [1/2]

Geometry3D::Geometry3D ( const MInt  solverId_,
const MPI_Comm  comm 
)

◆ Geometry3D() [2/2]

Geometry3D::Geometry3D ( const MInt  solverId_,
const MString filename,
const MPI_Comm  comm 
)

Definition at line 270 of file geometry3d.cpp.

270 : Geometry(solverId_, comm) {
271 TRACE();
272
273 m_log << "reading the auxiliary stl " << filename << endl;
274
276
277 m_noElements = 0;
278 m_noMBElements = 0;
279
281
282 m_log << " number of Elements: " << m_noElements << endl;
283
285
286 MInt bla = 0;
288
289 elements = &(m_elements->a[0]);
290
292
293 m_adt = new GeometryAdt<3>(this);
294 m_adt->buildTree();
295}
MBool m_GFieldInitFromSTL
Definition: geometry3d.h:113
static constexpr const MInt nDim
Definition: geometry3d.h:131
virtual void countSegmentTrianglesASCII(MString fileName, MInt *noElements)
counts the number of triangles in an ASCII STL file
Definition: geometry3d.cpp:418
virtual void readSegmentTrianglesASCII(MString fileName, Collector< element< 3 > > *elemCollector, MInt bndCndId, MInt segmentId, MInt *offset)
reads triangles from an ASCII file
Definition: geometry3d.cpp:509
void calculateBoundingBox() override
Calculates the global bounding box of the geometry.
Collector< element< nDim > > * m_elements
Definition: geometry.h:214
element< nDim > * elements
Definition: geometry.h:215
MInt m_noMBElements
Definition: geometry.h:195
MInt m_noElements
Definition: geometry.h:189
GeometryAdt< nDim > * m_adt
Definition: geometry.h:216
InfoOutFile m_log
int32_t MInt
Definition: maiatypes.h:62

◆ ~Geometry3D()

Geometry3D::~Geometry3D ( )

Definition at line 297 of file geometry3d.cpp.

297 {
298 TRACE();
299
300 delete m_adt;
301 delete m_elements;
302
303 // moving boundary
304 if(m_mbelements != nullptr) delete m_mbelements;
305}
Collector< element< nDim > > * m_mbelements
Definition: geometry.h:217

Member Function Documentation

◆ addElement()

void Geometry3D::addElement ( MFloat tri)
overrideprotectedvirtual
Author
Andreas Lintermann
Date
25.09.2015
Parameters
[in]triconatins the following information in MFloat: originalId, segmentId, bndCndId, normal, vertices

Reimplemented from Geometry< 3 >.

Definition at line 5064 of file geometry3d.cpp.

5064 {
5065 // TRACE();
5066
5067 m_elements->append();
5068 m_noElements++;
5069
5070 element<3>* tris = m_elements->a;
5071
5072 MInt segmentId = tri[1];
5073
5074 if(segmentId + 1 != m_noSegments)
5075 for(MInt c = m_noSegments; c > segmentId; c--) {
5077 }
5078
5079 for(MInt c = m_noSegments; c > segmentId; c--) {
5080 m_segmentOffsets[c] += 1;
5081 }
5082
5083 // insert
5084 MInt pos = m_segmentOffsets[segmentId + 1] - 1;
5085 tris[pos].m_originalId = (MInt)tri[0];
5086 tris[pos].m_segmentId = segmentId;
5087 tris[pos].m_bndCndId = (MInt)tri[2];
5088
5089 MInt j = 3;
5090 for(MInt d = 0; d < nDim; d++)
5091 tris[pos].m_normal[d] = tri[j++];
5092 for(MInt d1 = 0; d1 < nDim; d1++)
5093 for(MInt d2 = 0; d2 < nDim; d2++)
5094 tris[pos].m_vertices[d1][d2] = tri[j++];
5095
5096 tris[pos].boundingBox();
5097}
void copyElement(MInt from, MInt to) override
Copies an element<3> from one poistion to another.
std::vector< MInt > m_segmentOffsets
Definition: geometry.h:212
MInt m_noSegments
Definition: geometry.h:185

◆ calculateBoundingBox()

void Geometry3D::calculateBoundingBox ( )
overrideprotectedvirtual
Author
Andreas Lintermann
Date
25.09.2015

Works for both, parallel and serial geometry.

Reimplemented from Geometry< 3 >.

Definition at line 1598 of file geometry3d.cpp.

1598 {
1599 TRACE();
1600
1601 m_log << " + Calculating bounding box ..." << endl;
1602 m_log << " - number of elements to consider: " << m_noElements << endl;
1603
1604 // Communicate a reference triangle for those that have no triangles available
1605 MIntScratchSpace noGlobalElem(noDomains(), AT_, "noGlobalElem");
1606 noGlobalElem[domainId()] = m_noElements;
1607
1608 MPI_Allgather(&m_noElements, 1, MPI_INT, noGlobalElem.getPointer(), 1, MPI_INT, mpiComm(), AT_, "m_noElements",
1609 "noGlobalElem.getPointer()");
1610 MInt refDomain = 0;
1611 for(MInt d = 0; d < noDomains(); d++) {
1612 if(noGlobalElem[d] > 0) {
1613 refDomain = d;
1614 break;
1615 }
1616 }
1617
1618 std::array<MFloat, 2 * nDim> triMinMax;
1619 triMinMax.fill(std::nanf(""));
1620
1621 if(domainId() == refDomain) {
1622 for(MInt j = 0; j < 2 * nDim; j++) {
1623 triMinMax[j] = elements[0].m_minMax[j];
1624 }
1625 }
1626
1627 MPI_Bcast(triMinMax.data(), 2 * nDim, MPI_DOUBLE, refDomain, mpiComm(), AT_, "triMinMax.getPointer()");
1628
1629 // Calculate bounding box of segment
1630 for(MInt j = 0; j < nDim; j++) {
1631 m_minMax[j] = triMinMax[j];
1632 m_minMax[j + nDim] = triMinMax[j + nDim];
1633 }
1634
1635 for(MInt i = 0; i < m_noElements; i++) {
1636 for(MInt j = 0; j < nDim; j++) {
1637 m_minMax[j + nDim] =
1638 (m_minMax[j + nDim] < elements[i].m_minMax[j + nDim]) ? elements[i].m_minMax[j + nDim] : m_minMax[j + nDim];
1639 m_minMax[j] = (m_minMax[j] > elements[i].m_minMax[j]) ? elements[i].m_minMax[j] : m_minMax[j];
1640 }
1641 }
1642 if(m_noElements == 0) ASSERT(m_GFieldInitFromSTL, "");
1643
1644 if(m_noElements > 0) {
1645 m_log << " - local max: ";
1646 for(MInt i = 0; i < nDim; i++) {
1647 m_log << m_minMax[i + nDim] << " ";
1648 }
1649 m_log << endl;
1650
1651 m_log << " - local min: ";
1652 for(MInt i = 0; i < nDim; i++) {
1653 m_log << m_minMax[i] << " ";
1654 }
1655 m_log << endl;
1656 }
1657
1658 if(m_parallelGeometry) {
1659 MPI_Allreduce(MPI_IN_PLACE, &m_minMax[0], nDim, MPI_DOUBLE, MPI_MIN, mpiComm(), AT_, "MPI_IN_PLACE", "m_minMax[0]");
1660 MPI_Allreduce(MPI_IN_PLACE, &m_minMax[0] + nDim, nDim, MPI_DOUBLE, MPI_MAX, mpiComm(), AT_, "MPI_IN_PLACE",
1661 "m_minMax[0]+nDim");
1662 }
1663
1664 if(m_noElements > 0) {
1665 m_log << " - max: ";
1666 for(MInt i = 0; i < nDim; i++) {
1667 m_log << m_minMax[i + nDim] << " ";
1668 }
1669 m_log << endl;
1670
1671 m_log << " - min: ";
1672 for(MInt i = 0; i < nDim; i++) {
1673 m_log << m_minMax[i] << " ";
1674 }
1675 m_log << endl << endl;
1676 }
1677
1678 // Calculate bounding box of Moving Boundary segment
1681 m_log << " Bounding box for Moving Boundary segment:" << endl;
1682 m_log << " max = ";
1683 for(MInt i = 0; i < nDim; i++)
1684 m_log << m_mbminMax[i + nDim] << " ";
1685
1686 m_log << endl;
1687 m_log << " min = ";
1688 for(MInt i = 0; i < nDim; i++)
1689 m_log << m_mbminMax[i] << " ";
1690
1691 m_log << endl;
1692
1693 if(m_forceBoundingBox) {
1694 // use the STL2levelset geometry as bounding box to define the length0 and center of gravity
1695 // this can be useful, to force a length onto a setup!
1696 for(MInt i = 0; i < nDim; i++) {
1697 if(m_mbminMax[i] < m_minMax[i]) {
1698 m_minMax[i] = m_mbminMax[i];
1699 }
1700 if(m_mbminMax[i + nDim] > m_minMax[i + nDim]) {
1701 m_minMax[i + nDim] = m_mbminMax[i + nDim];
1702 }
1703 }
1704 }
1705 }
1706}
MBool m_forceBoundingBox
Definition: geometry3d.h:117
void UpdateMBBoundingBox() override
MInt noDomains() const
Definition: geometry.h:47
std::array< MFloat, 2 *nDim > m_minMax
Definition: geometry.h:187
MPI_Comm mpiComm() const
Definition: geometry.h:45
MInt domainId() const
Definition: geometry.h:46
std::array< MFloat, 2 *nDim > m_mbminMax
Definition: geometry.h:219
MBool m_parallelGeometry
Definition: geometry.h:228
This class is a ScratchSpace.
Definition: scratch.h:758
int MPI_Allreduce(const void *sendbuf, void *recvbuf, int count, MPI_Datatype datatype, MPI_Op op, MPI_Comm comm, const MString &name, const MString &sndvarname, const MString &rcvvarname)
same as MPI_Allreduce
int MPI_Bcast(void *buffer, int count, MPI_Datatype datatype, int root, MPI_Comm comm, const MString &name, const MString &varname)
same as MPI_Bcast
int MPI_Allgather(const void *sendbuf, int sendcount, MPI_Datatype sendtype, void *recvbuf, int recvcount, MPI_Datatype recvtype, MPI_Comm comm, const MString &name, const MString &sndvarname, const MString &rcvvarname)
same as MPI_Allgather

◆ collectGlobalMemoryUsage()

void Geometry3D::collectGlobalMemoryUsage ( )
overrideprotectedvirtual

Reimplemented from Geometry< 3 >.

Definition at line 341 of file geometry3d.cpp.

341 {
342 TRACE();
343
344 MInt count = 3;
345 if(m_GFieldInitFromSTL) count = 4;
346
347 MFloatScratchSpace mem(noDomains() * count, AT_, "mem");
348
349 MFloatScratchSpace snd(count, AT_, "snd");
350 snd[0] = m_noElements;
351 snd[1] = (MFloat)m_elements->memoryUseage() / 1024.0 / 1024.0;
352 snd[2] = (MFloat)m_adt->memoryUsage() / 1024.0 / 1024.0;
353 if(m_GFieldInitFromSTL) snd[3] = (MFloat)m_mbelements->memoryUseage() / 1024.0 / 1024.0;
354
355 MPI_Gather(snd.getPointer(), count, MPI_DOUBLE, mem.getPointer(), count, MPI_DOUBLE, 0, mpiComm(), AT_,
356 "snd.getPointer()", "mem.getPointer()");
357
358 if(domainId() == 0) {
359 ofstream ofl;
360 ofl.open("memrep_geom.txt", std::ios_base::out | std::ios_base::trunc);
361 ofl.precision(10);
362 ofl << "###########################################################################################################"
363 "#"
364 << endl
365 << "#" << endl;
366 ofl << "# domain no_triangles triangles[MB] tree[MB] tmb_triagles[MP]" << endl << "#" << endl;
367
368 MFloatScratchSpace sums(count, AT_, "sums");
369 for(MInt i = 0; i < count; i++)
370 sums[i] = 0.0;
371
372 MFloatScratchSpace min(count, AT_, "min");
373 MFloatScratchSpace max(count, AT_, "max");
374 for(MInt i = 0; i < count; i++) {
375 min[i] = 9999999999999999.9;
376 max[i] = -1.0;
377 }
378
379 for(MInt d = 0; d < noDomains(); d++)
380 for(MInt i = 0; i < count; i++) {
381 sums[i] += mem[d * count + i];
382 if(mem[d * count + i] > max[i]) max[i] = mem[d * count + i];
383 if(mem[d * count + i] < min[i]) min[i] = mem[d * count + i];
384 }
385
386 MString names[4] = {"no_triangles", "triangles", "tree", "mb_triangles"};
387 for(MInt i = 0; i < count; i++) {
388 ofl << "# SUM " << names[i] << " = " << sums[i] << endl;
389 ofl << "# AVG " << names[i] << " = " << sums[i] / noDomains() << endl;
390 ofl << "# MIN " << names[i] << " = " << min[i] << endl;
391 ofl << "# MAX " << names[i] << " = " << max[i] << endl << endl;
392 }
393 ofl << "#" << endl
394 << "###########################################################################################################"
395 "#"
396 << endl;
397
398 for(MInt d = 0; d < noDomains(); d++) {
399 ofl << d << "\t\t";
400 for(MInt i = 0; i < count; i++)
401 ofl << mem[d * count + i] << "\t\t";
402 ofl << endl;
403 }
404 ofl.close();
405 }
406}
std::basic_string< char > MString
Definition: maiatypes.h:55
double MFloat
Definition: maiatypes.h:52
int MPI_Gather(const void *sendbuf, int sendcount, MPI_Datatype sendtype, void *recvbuf, int recvcount, MPI_Datatype recvtype, int root, MPI_Comm comm, const MString &name, const MString &sndvarname, const MString &rcvvarname)
same as MPI_Gather

◆ copyElement() [1/2]

void Geometry3D::copyElement ( MInt  from,
MInt  to 
)
overrideprotectedvirtual
Author
Andreas Lintermann
Date
25.09.2015
Parameters
[in]fromthe location to copy the element<3> from
[in]tothe location to copy the element<3> to

Reimplemented from Geometry< 3 >.

Definition at line 5108 of file geometry3d.cpp.

5108 {
5109 // TRACE();
5110 element<3>* tris = m_elements->a;
5111
5112 for(MInt d = 0; d < nDim; d++)
5113 tris[to].m_normal[d] = tris[from].m_normal[d];
5114
5115 for(MInt d1 = 0; d1 < nDim; d1++)
5116 for(MInt d2 = 0; d2 < nDim; d2++)
5117 tris[to].m_vertices[d1][d2] = tris[from].m_vertices[d1][d2];
5118
5119 for(MInt d = 0; d < 2 * nDim; d++)
5120 tris[to].m_minMax[d] = tris[from].m_minMax[d];
5121
5122 tris[to].m_segmentId = tris[from].m_segmentId;
5123 tris[to].m_bndCndId = tris[from].m_bndCndId;
5124 tris[to].m_originalId = tris[from].m_originalId;
5125}

◆ copyElement() [2/2]

void Geometry3D::copyElement ( MInt  from,
MInt  to,
element< 3 > *  fromPtr,
element< 3 > *  toPtr 
)
protected
Author
Andreas Lintermann
Date
25.09.2015
Parameters
[in]fromthe location to copy the element<3> from
[in]tothe location to copy the element<3> to
[in]fromPtrthe pointer to the from array
[in]toPtrthe pointer to the to array

Definition at line 5138 of file geometry3d.cpp.

5138 {
5139 // TRACE();
5140 for(MInt d = 0; d < nDim; d++)
5141 toPtr[to].m_normal[d] = fromPtr[from].m_normal[d];
5142
5143 for(MInt d1 = 0; d1 < nDim; d1++)
5144 for(MInt d2 = 0; d2 < nDim; d2++)
5145 toPtr[to].m_vertices[d1][d2] = fromPtr[from].m_vertices[d1][d2];
5146
5147 for(MInt d = 0; d < 2 * nDim; d++)
5148 toPtr[to].m_minMax[d] = fromPtr[from].m_minMax[d];
5149
5150 toPtr[to].m_segmentId = fromPtr[from].m_segmentId;
5151 toPtr[to].m_bndCndId = fromPtr[from].m_bndCndId;
5152 toPtr[to].m_originalId = fromPtr[from].m_originalId;
5153}

◆ correctVertexCoordinates()

void Geometry3D::correctVertexCoordinates ( )
protectedvirtual

Definition at line 1709 of file geometry3d.cpp.

1709 {
1710 TRACE();
1711
1712 otherCalls++;
1713
1714
1715 MInt noEl = m_elements->size();
1716 MFloat epsilon = 0.0000001;
1717 MFloat maxCoordinate = F0;
1718 //---
1719
1720 // find the maximum coordinate
1721 for(MInt el = 0; el < noEl; el++)
1722 for(MInt i = 0; i < 3; i++)
1723 for(MInt j = 0; j < 3; j++)
1724 maxCoordinate = mMax(ABS(elements[el].m_vertices[i][j]), maxCoordinate);
1725
1726 // compute epsilon
1727 epsilon *= maxCoordinate;
1728
1729 // remove small values around zero
1730 for(MInt el = 0; el < noEl; el++) {
1731 for(MInt i = 0; i < 3; i++) {
1732 for(MInt j = 0; j < 3; j++) {
1733 if(ABS(elements[el].m_vertices[j][i]) < epsilon) elements[el].m_vertices[j][i] = F0;
1734 }
1735 }
1736 }
1737}
MInt otherCalls
Definition: geometry3d.h:111
Real ABS(const Real x)
Definition: functions.h:85
constexpr T mMax(const T &x, const T &y)
Definition: functions.h:94

◆ countSegmentTrianglesASCII()

void Geometry3D::countSegmentTrianglesASCII ( MString  fileName,
MInt noElements 
)
inlineprotectedvirtual
Author
Andreas Lintermann
Date
20.07.2015
Parameters
[in]fileNamethe name of the file to open
[in]thenumber of entries to be returned (gets nulled in function again)

Definition at line 418 of file geometry3d.cpp.

418 {
419 TRACE();
420
421 *noElements = 0;
422
423 // open file in ascii format
424 ifstream ifl(fileName);
425
426 if(!ifl) {
427 stringstream errorMessage;
428 errorMessage << " ERROR in segment::readSegment, couldn't find file : " << fileName << "!";
429 mTerm(1, AT_, errorMessage.str());
430 }
431
432 char tmp[256];
433 string text;
434 // If number of elements unknown, count them...
435 while(text.find("endsolid") == std::string::npos) {
436 ifl.getline(tmp, 256);
437 text = tmp;
438 if(text.find("facet") != std::string::npos && text.find("endface") == std::string::npos)
439 *noElements = *noElements + 1;
440 }
441 ifl.close();
442}
void mTerm(const MInt errorCode, const MString &location, const MString &message)
Definition: functions.cpp:29

◆ countSegmentTrianglesBINARY()

void Geometry3D::countSegmentTrianglesBINARY ( MString  fileName,
MInt noElements 
)
inlineprotectedvirtual
Author
Andreas Lintermann
Date
20.07.2015

This function detects the file size in byte and substracts the header information (80 bytes) and the the information on the number of triangles (4 bytes). Each triangle carries a total of 50 bytes.

Parameters
[in]fileNamethe name of the file to open
[in]thenumber of entries to be returned (gets nulled in function again)

Definition at line 457 of file geometry3d.cpp.

457 {
458 TRACE();
459
460 *noElements = 0;
461
462 struct stat stat_buf {};
463 MInt rc = stat(fileName.c_str(), &stat_buf);
464 if(rc < 0) {
465 stringstream errorMessage;
466 errorMessage << " ERROR in segment::readSegment, couldn't determine file size of: " << fileName << "!";
467 mTerm(1, AT_, errorMessage.str());
468 }
469
470 *noElements = (stat_buf.st_size - (80 + 4)) / 50;
471}

◆ countSegmentTrianglesNETCDF()

void Geometry3D::countSegmentTrianglesNETCDF ( MString  fileName,
MInt noElements,
const MPI_Comm  comm 
)
inlineprotectedvirtual
Author
Andreas Lintermann
Date
21.07.2015

This is stored in the file in the variable noTriangles.

Parameters
[in]fileNamethe name of the file to open
[in]thenumber of entries to be returned (gets nulled in function again)

Definition at line 485 of file geometry3d.cpp.

485 {
486 TRACE();
487
488 using namespace maia::parallel_io;
489
490 *noElements = 0;
491
492 ParallelIo surface(fileName, PIO_READ, comm);
493 surface.readScalar(noElements, "noTriangles");
494}
PARALLELIO_DEFAULT_BACKEND ParallelIo
Definition: parallelio.h:292

◆ determineSegmentOwnership()

void Geometry3D::determineSegmentOwnership ( MInt  segmentId,
MInt own,
MInt sumowners,
MInt firstOwner,
MInt owners 
)
overridevirtual
Author
Andreas Lintermann
Date
18.09.2015
Parameters
[in]segmentIdthe segment id
[in]ownpointer to the result of this domain owns the segment
[in]sumownerspointer to the result of the sum of the owners
[in]firstOwnerpointer to the result of which is the first owner in the communicator
[in]ownersarray holding information which domain holds the segment

Reimplemented from Geometry< 3 >.

Definition at line 4903 of file geometry3d.cpp.

4903 {
4904 TRACE();
4905
4906 *firstOwner = -1;
4907 *sumowners = 0;
4908
4909 if(m_ownSegmentId[segmentId])
4910 *own = 1;
4911 else
4912 *own = 0;
4913
4914
4915 MPI_Allgather(own, 1, MPI_INT, owners, 1, MPI_INT, mpiComm(), AT_, "own", "owners");
4916 for(MInt d = 0; d < noDomains(); d++) {
4917 if(owners[d] > 0) {
4918 if(*firstOwner < 0) *firstOwner = d;
4919 *sumowners += owners[d];
4920 }
4921 }
4922}
MBool * m_ownSegmentId
Definition: geometry.h:222

◆ edgeTriangleIntersection()

MBool Geometry3D::edgeTriangleIntersection ( MFloat trianglePoint1,
MFloat trianglePoint2,
MFloat trianglePoint3,
MFloat edgePoint1,
MFloat edgePoint2 
)
inlineoverridevirtual

Reimplemented from Geometry< 3 >.

Definition at line 2434 of file geometry3d.cpp.

2435 {
2436 TRACE();
2437
2439
2440 MFloat volume1 = 0;
2441 MFloat volume2 = 0;
2442 MFloat volume3 = 0;
2443 MInt maxRfnLvl = (sizeof(MInt) * 8) - 6;
2444 MFloat eps = 1.0 / FPOW2(maxRfnLvl);
2445 MFloat a[3] = {trianglePoint1[0], trianglePoint1[1], trianglePoint1[2]};
2446 MFloat b[3] = {trianglePoint2[0], trianglePoint2[1], trianglePoint2[2]};
2447 MFloat c[3] = {trianglePoint3[0], trianglePoint3[1], trianglePoint3[2]};
2448 MFloat d[3];
2449 // To determine an intersection between edge and triangle we have to:
2450 // 1. Check if the edge pierces the plane of the triangle
2451 // - compute the signs of the signed tetrahedra build with the triangle points
2452 // - and first and second edge point. Equal signs means edge doesn't pierce.
2453 // 2. Check if the pierce point lies inside the triangles
2454 // - compute the signs of the 3 tetrahedra consisting of always the edge points
2455 // and one edge of the triangle
2456 // - if all signs are equal the edge pierces inside the triangle
2457
2458
2459 // 1.
2460 // Calculate signed tetraeder Volume of triangle and 1st point
2461 for(MInt i = 0; i < nDim; i++) {
2462 d[i] = edgePoint1[i];
2463 }
2464 volume1 = (b[1] * a[2] * d[0] - d[1] * a[0] * c[2] + d[1] * a[0] * b[2] + c[1] * a[0] * d[2] - b[1] * a[0] * d[2]
2465 - a[1] * c[0] * d[2] + a[1] * d[0] * c[2] - a[1] * d[0] * b[2] + d[1] * a[2] * c[0] + d[1] * c[2] * b[0]
2466 - d[1] * a[2] * b[0] - d[1] * b[2] * c[0] - c[1] * d[2] * b[0] - c[1] * a[2] * d[0] + c[1] * b[2] * d[0]
2467 - b[1] * c[2] * d[0] + b[1] * c[0] * d[2] + a[1] * b[0] * d[2] - a[1] * b[0] * c[2] - b[1] * a[2] * c[0]
2468 + a[1] * c[0] * b[2] + c[1] * a[2] * b[0] - c[1] * a[0] * b[2] + b[1] * a[0] * c[2]);
2469
2470 for(MInt i = 0; i < nDim; i++) {
2471 d[i] = edgePoint2[i];
2472 }
2473
2474 // Calculate signed tetraeder Volume of triangle and 2nd point
2475 volume2 = (b[1] * a[2] * d[0] - d[1] * a[0] * c[2] + d[1] * a[0] * b[2] + c[1] * a[0] * d[2] - b[1] * a[0] * d[2]
2476 - a[1] * c[0] * d[2] + a[1] * d[0] * c[2] - a[1] * d[0] * b[2] + d[1] * a[2] * c[0] + d[1] * c[2] * b[0]
2477 - d[1] * a[2] * b[0] - d[1] * b[2] * c[0] - c[1] * d[2] * b[0] - c[1] * a[2] * d[0] + c[1] * b[2] * d[0]
2478 - b[1] * c[2] * d[0] + b[1] * c[0] * d[2] + a[1] * b[0] * d[2] - a[1] * b[0] * c[2] - b[1] * a[2] * c[0]
2479 + a[1] * c[0] * b[2] + c[1] * a[2] * b[0] - c[1] * a[0] * b[2] + b[1] * a[0] * c[2]);
2480
2481 if(volume1 * volume2 >= eps) {
2482 // Equal signs! no pierce point with triangle plane
2483 return false;
2484 }
2485 // 2.
2486 for(MInt i = 0; i < nDim; i++) {
2487 a[i] = edgePoint1[i];
2488 b[i] = trianglePoint1[i];
2489 c[i] = trianglePoint2[i];
2490 d[i] = edgePoint2[i];
2491 }
2492 volume1 = (b[1] * a[2] * d[0] - d[1] * a[0] * c[2] + d[1] * a[0] * b[2] + c[1] * a[0] * d[2] - b[1] * a[0] * d[2]
2493 - a[1] * c[0] * d[2] + a[1] * d[0] * c[2] - a[1] * d[0] * b[2] + d[1] * a[2] * c[0] + d[1] * c[2] * b[0]
2494 - d[1] * a[2] * b[0] - d[1] * b[2] * c[0] - c[1] * d[2] * b[0] - c[1] * a[2] * d[0] + c[1] * b[2] * d[0]
2495 - b[1] * c[2] * d[0] + b[1] * c[0] * d[2] + a[1] * b[0] * d[2] - a[1] * b[0] * c[2] - b[1] * a[2] * c[0]
2496 + a[1] * c[0] * b[2] + c[1] * a[2] * b[0] - c[1] * a[0] * b[2] + b[1] * a[0] * c[2]);
2497
2498 for(MInt i = 0; i < nDim; i++) {
2499 a[i] = edgePoint1[i];
2500 b[i] = trianglePoint3[i];
2501 c[i] = trianglePoint1[i];
2502 d[i] = edgePoint2[i];
2503 }
2504 volume2 = (b[1] * a[2] * d[0] - d[1] * a[0] * c[2] + d[1] * a[0] * b[2] + c[1] * a[0] * d[2] - b[1] * a[0] * d[2]
2505 - a[1] * c[0] * d[2] + a[1] * d[0] * c[2] - a[1] * d[0] * b[2] + d[1] * a[2] * c[0] + d[1] * c[2] * b[0]
2506 - d[1] * a[2] * b[0] - d[1] * b[2] * c[0] - c[1] * d[2] * b[0] - c[1] * a[2] * d[0] + c[1] * b[2] * d[0]
2507 - b[1] * c[2] * d[0] + b[1] * c[0] * d[2] + a[1] * b[0] * d[2] - a[1] * b[0] * c[2] - b[1] * a[2] * c[0]
2508 + a[1] * c[0] * b[2] + c[1] * a[2] * b[0] - c[1] * a[0] * b[2] + b[1] * a[0] * c[2]);
2509
2510 for(MInt i = 0; i < nDim; i++) {
2511 a[i] = edgePoint1[i];
2512 b[i] = trianglePoint2[i];
2513 c[i] = trianglePoint3[i];
2514 d[i] = edgePoint2[i];
2515 }
2516 volume3 = (b[1] * a[2] * d[0] - d[1] * a[0] * c[2] + d[1] * a[0] * b[2] + c[1] * a[0] * d[2] - b[1] * a[0] * d[2]
2517 - a[1] * c[0] * d[2] + a[1] * d[0] * c[2] - a[1] * d[0] * b[2] + d[1] * a[2] * c[0] + d[1] * c[2] * b[0]
2518 - d[1] * a[2] * b[0] - d[1] * b[2] * c[0] - c[1] * d[2] * b[0] - c[1] * a[2] * d[0] + c[1] * b[2] * d[0]
2519 - b[1] * c[2] * d[0] + b[1] * c[0] * d[2] + a[1] * b[0] * d[2] - a[1] * b[0] * c[2] - b[1] * a[2] * c[0]
2520 + a[1] * c[0] * b[2] + c[1] * a[2] * b[0] - c[1] * a[0] * b[2] + b[1] * a[0] * c[2]);
2521 // if(volume1 >= eps && volume2 >= eps && volume3 >= eps)
2522 // return true;
2523 // if(volume1 <= eps && volume2 <= eps && volume3 <= eps)
2524 // return true;
2525
2526 // if(volume1*volume1 < eps*eps || volume2*volume2 < eps*eps || volume3*volume3 < eps*eps ){
2527 if(((volume1 < eps) && (volume1 > -eps)) || ((volume2 < eps) && (volume2 > -eps))
2528 || ((volume3 < eps) && (volume3 > -eps))) {
2529 m_log << " ! SINGULARITY IN TRIANGLE INTERSECTION ! At: " << a[0] << ", " << a[1] << ", " << a[2] << "; " << d[0]
2530 << ", " << d[1] << ", " << d[2] << endl;
2531 // cerr << " ! SINGULARITY IN TRIANGLE INTERSECTION ! At: " << a[0] << ", " << a[1] << ", " << a[2] << "; " <<
2532 // d[0] << ", " << d[1] << ", " << d[2] << endl;
2533 // return true;
2534 return false;
2535 }
2536
2537 if(volume1 >= 0.0 && volume2 >= 0.0 && volume3 >= 0.0) {
2538 return true;
2539 }
2540 if(volume1 <= 0.0 && volume2 <= 0.0 && volume3 <= 0.0) {
2541 return true;
2542 }
2543
2544 return false;
2545}
MInt edgeTICallCounter
Definition: geometry3d.h:130
constexpr MFloat FPOW2(MInt x)
Definition: contexttypes.h:19

◆ edgeTriangleIntersectionLB()

MBool Geometry3D::edgeTriangleIntersectionLB ( MFloat trianglePoint1,
MFloat trianglePoint2,
MFloat trianglePoint3,
MFloat edgePoint1,
MFloat edgePoint2 
)
inlineoverridevirtual

Reimplemented from Geometry< 3 >.

Definition at line 2552 of file geometry3d.cpp.

2553 {
2554 TRACE();
2555
2556 otherCalls++;
2557
2558 MFloat volume1 = 0;
2559 MFloat volume2 = 0;
2560 MFloat volume3 = 0;
2561 MInt maxRfnLvl = (sizeof(MInt) * 8) - 6;
2562 MFloat eps = 1.0 / FPOW2(maxRfnLvl);
2563 MFloat a[3] = {trianglePoint1[0], trianglePoint1[1], trianglePoint1[2]};
2564 MFloat b[3] = {trianglePoint2[0], trianglePoint2[1], trianglePoint2[2]};
2565 MFloat c[3] = {trianglePoint3[0], trianglePoint3[1], trianglePoint3[2]};
2566 MFloat d[3];
2567 // To determine an intersection between edge and triangle we have to:
2568 // 1. Check if the edge pierces the plane of the triangle
2569 // - compute the signs of the signed tetrahedra build with the triangle points
2570 // - and first and second edge point. Equal signs means edge doesn't pierce.
2571 // 2. Check if the pierce point lies inside the triangles
2572 // - compute the signs of the 3 tetrahedra consisting of always the edge points
2573 // and one edge of the triangle
2574 // - if all signs are equal the edge pierces inside the triangle
2575
2576
2577 // 1.
2578 // Calculate signed tetraeder Volume of triangle and 1st point
2579 for(MInt i = 0; i < nDim; i++) {
2580 d[i] = edgePoint1[i];
2581 }
2582 volume1 = (b[1] * a[2] * d[0] - d[1] * a[0] * c[2] + d[1] * a[0] * b[2] + c[1] * a[0] * d[2] - b[1] * a[0] * d[2]
2583 - a[1] * c[0] * d[2] + a[1] * d[0] * c[2] - a[1] * d[0] * b[2] + d[1] * a[2] * c[0] + d[1] * c[2] * b[0]
2584 - d[1] * a[2] * b[0] - d[1] * b[2] * c[0] - c[1] * d[2] * b[0] - c[1] * a[2] * d[0] + c[1] * b[2] * d[0]
2585 - b[1] * c[2] * d[0] + b[1] * c[0] * d[2] + a[1] * b[0] * d[2] - a[1] * b[0] * c[2] - b[1] * a[2] * c[0]
2586 + a[1] * c[0] * b[2] + c[1] * a[2] * b[0] - c[1] * a[0] * b[2] + b[1] * a[0] * c[2]);
2587
2588 for(MInt i = 0; i < nDim; i++) {
2589 d[i] = edgePoint2[i];
2590 }
2591
2592 // Calculate signed tetraeder Volume of triangle and 2nd point
2593 volume2 = (b[1] * a[2] * d[0] - d[1] * a[0] * c[2] + d[1] * a[0] * b[2] + c[1] * a[0] * d[2] - b[1] * a[0] * d[2]
2594 - a[1] * c[0] * d[2] + a[1] * d[0] * c[2] - a[1] * d[0] * b[2] + d[1] * a[2] * c[0] + d[1] * c[2] * b[0]
2595 - d[1] * a[2] * b[0] - d[1] * b[2] * c[0] - c[1] * d[2] * b[0] - c[1] * a[2] * d[0] + c[1] * b[2] * d[0]
2596 - b[1] * c[2] * d[0] + b[1] * c[0] * d[2] + a[1] * b[0] * d[2] - a[1] * b[0] * c[2] - b[1] * a[2] * c[0]
2597 + a[1] * c[0] * b[2] + c[1] * a[2] * b[0] - c[1] * a[0] * b[2] + b[1] * a[0] * c[2]);
2598
2599 if(volume1 * volume2 >= eps) {
2600 // Equal signs! no pierce point with triangle plane
2601 return false;
2602 }
2603 // 2.
2604 for(MInt i = 0; i < nDim; i++) {
2605 a[i] = edgePoint1[i];
2606 b[i] = trianglePoint1[i];
2607 c[i] = trianglePoint2[i];
2608 d[i] = edgePoint2[i];
2609 }
2610 volume1 = (b[1] * a[2] * d[0] - d[1] * a[0] * c[2] + d[1] * a[0] * b[2] + c[1] * a[0] * d[2] - b[1] * a[0] * d[2]
2611 - a[1] * c[0] * d[2] + a[1] * d[0] * c[2] - a[1] * d[0] * b[2] + d[1] * a[2] * c[0] + d[1] * c[2] * b[0]
2612 - d[1] * a[2] * b[0] - d[1] * b[2] * c[0] - c[1] * d[2] * b[0] - c[1] * a[2] * d[0] + c[1] * b[2] * d[0]
2613 - b[1] * c[2] * d[0] + b[1] * c[0] * d[2] + a[1] * b[0] * d[2] - a[1] * b[0] * c[2] - b[1] * a[2] * c[0]
2614 + a[1] * c[0] * b[2] + c[1] * a[2] * b[0] - c[1] * a[0] * b[2] + b[1] * a[0] * c[2]);
2615
2616 for(MInt i = 0; i < nDim; i++) {
2617 a[i] = edgePoint1[i];
2618 b[i] = trianglePoint3[i];
2619 c[i] = trianglePoint1[i];
2620 d[i] = edgePoint2[i];
2621 }
2622 volume2 = (b[1] * a[2] * d[0] - d[1] * a[0] * c[2] + d[1] * a[0] * b[2] + c[1] * a[0] * d[2] - b[1] * a[0] * d[2]
2623 - a[1] * c[0] * d[2] + a[1] * d[0] * c[2] - a[1] * d[0] * b[2] + d[1] * a[2] * c[0] + d[1] * c[2] * b[0]
2624 - d[1] * a[2] * b[0] - d[1] * b[2] * c[0] - c[1] * d[2] * b[0] - c[1] * a[2] * d[0] + c[1] * b[2] * d[0]
2625 - b[1] * c[2] * d[0] + b[1] * c[0] * d[2] + a[1] * b[0] * d[2] - a[1] * b[0] * c[2] - b[1] * a[2] * c[0]
2626 + a[1] * c[0] * b[2] + c[1] * a[2] * b[0] - c[1] * a[0] * b[2] + b[1] * a[0] * c[2]);
2627
2628 for(MInt i = 0; i < nDim; i++) {
2629 a[i] = edgePoint1[i];
2630 b[i] = trianglePoint2[i];
2631 c[i] = trianglePoint3[i];
2632 d[i] = edgePoint2[i];
2633 }
2634 volume3 = (b[1] * a[2] * d[0] - d[1] * a[0] * c[2] + d[1] * a[0] * b[2] + c[1] * a[0] * d[2] - b[1] * a[0] * d[2]
2635 - a[1] * c[0] * d[2] + a[1] * d[0] * c[2] - a[1] * d[0] * b[2] + d[1] * a[2] * c[0] + d[1] * c[2] * b[0]
2636 - d[1] * a[2] * b[0] - d[1] * b[2] * c[0] - c[1] * d[2] * b[0] - c[1] * a[2] * d[0] + c[1] * b[2] * d[0]
2637 - b[1] * c[2] * d[0] + b[1] * c[0] * d[2] + a[1] * b[0] * d[2] - a[1] * b[0] * c[2] - b[1] * a[2] * c[0]
2638 + a[1] * c[0] * b[2] + c[1] * a[2] * b[0] - c[1] * a[0] * b[2] + b[1] * a[0] * c[2]);
2639 // if(volume1 >= eps && volume2 >= eps && volume3 >= eps)
2640 // return true;
2641 // if(volume1 <= eps && volume2 <= eps && volume3 <= eps)
2642 // return true;
2643
2644 // if(volume1*volume1 < eps*eps || volume2*volume2 < eps*eps || volume3*volume3 < eps*eps ){
2645 if(((volume1 < eps) && (volume1 > -eps)) || ((volume2 < eps) && (volume2 > -eps))
2646 || ((volume3 < eps) && (volume3 > -eps))) {
2647 m_log << " ! SINGULARITY IN TRIANGLE INTERSECTION ! At: " << a[0] << ", " << a[1] << ", " << a[2] << "; " << d[0]
2648 << ", " << d[1] << ", " << d[2] << endl;
2649 // cerr << " ! SINGULARITY IN TRIANGLE INTERSECTION ! At: " << a[0] << ", " << a[1] << ", " << a[2] << "; " <<
2650 // d[0] << ", " << d[1] << ", " << d[2] << endl;
2651 return true;
2652 // return false;
2653 }
2654
2655 if(volume1 >= 0.0 && volume2 >= 0.0 && volume3 >= 0.0) return true;
2656 if(volume1 <= 0.0 && volume2 <= 0.0 && volume3 <= 0.0) return true;
2657
2658 return false;
2659}

◆ getBndMaxRadius()

MFloat Geometry3D::getBndMaxRadius ( MFloat **  vertices,
MInt  num 
)
overridevirtual
Author
Andreas Lintermann
Date
21.01.2013

This function first determines the area for all projections XY, XZ, YZ according to

\[A_{xy} = \frac{1}{2}\sum_{i=0}^{n-1}\left(x_i y_{i+1} - x_{i+1} y_i\right)\]

\[A_{xz} = \frac{1}{2}\sum_{i=0}^{n-1}\left(x_i z_{i+1} - x_{i+1} z_i\right)\]

\[A_{xy} = \frac{1}{2}\sum_{i=0}^{n-1}\left(y_i z_{i+1} - y_{i+1} z_i\right)\]

Based on the obtained size of the areas with the consideration of the special cases that some areas can be zero the center of gravity is calculated using:;;;

\[ c_{\alpha}=\frac{1}{6A_{\alpha\beta}}\sum_{i=0}^{n-1}\left(\alpha_i + \alpha_{i+1}\right)\left(\alpha_i *\beta_{i+1}-\alpha_{i+1} \beta_i\right)\]

,

where \(A_{ab}\neq 0\) and \(\alpha,\beta\in\{x,y,z\}\).

Parameters
[in]verticesthe vertices as pointer to a pointer
[in]numthe number of vertices

Reimplemented from Geometry< 3 >.

Definition at line 4947 of file geometry3d.cpp.

4947 {
4948 TRACE();
4949
4950 MFloat areaXY = 0.0;
4951 MFloat areaXZ = 0.0;
4952 MFloat areaYZ = 0.0;
4953 MFloat cog_tmp[3][2] = {{0.0, 0.0}, {0.0, 0.0}, {0.0, 0.0}};
4954 MFloat cog[3] = {0.0, 0.0, 0.0};
4955
4956 for(MInt i = 0; i < num; i++) {
4957 MInt next = (i + 1) % num;
4958 MFloat xy = vertices[i][0] * vertices[next][1] - vertices[next][0] * vertices[i][1];
4959 MFloat xz = vertices[i][0] * vertices[next][2] - vertices[next][0] * vertices[i][2];
4960 MFloat yz = vertices[i][1] * vertices[next][2] - vertices[next][1] * vertices[i][2];
4961
4962 areaXY += xy;
4963 areaXZ += xz;
4964 areaYZ += yz;
4965
4966 cog_tmp[0][0] += (vertices[i][0] + vertices[next][0]) * xy;
4967 cog_tmp[0][1] += (vertices[i][0] + vertices[next][0]) * xz;
4968 cog_tmp[1][0] += (vertices[i][1] + vertices[next][1]) * xy;
4969 cog_tmp[1][1] += (vertices[i][1] + vertices[next][1]) * yz;
4970 cog_tmp[2][0] += (vertices[i][2] + vertices[next][2]) * xz;
4971 cog_tmp[2][1] += (vertices[i][2] + vertices[next][2]) * yz;
4972 }
4973
4974 areaXY = fabs(areaXY) * 0.5;
4975 areaXZ = fabs(areaXZ) * 0.5;
4976 areaYZ = fabs(areaYZ) * 0.5;
4977
4978 MFloat eps = 0.00000001;
4979 if(areaXY < eps) {
4980 if(areaYZ < eps) {
4981 cog[0] = 1.0 / (6.0 * areaXZ) * cog_tmp[0][1];
4982 cog[1] = vertices[0][1];
4983 cog[2] = 1.0 / (6.0 * areaXZ) * cog_tmp[2][0];
4984 } else if(areaXZ < eps) {
4985 cog[0] = vertices[0][0];
4986 cog[1] = 1.0 / (6.0 * areaYZ) * cog_tmp[1][1];
4987 cog[2] = 1.0 / (6.0 * areaYZ) * cog_tmp[2][1];
4988 } else {
4989 cog[0] = 1.0 / (6.0 * areaXZ) * cog_tmp[0][1];
4990 cog[1] = 1.0 / (6.0 * areaYZ) * cog_tmp[1][1];
4991 cog[2] = 1.0 / (6.0 * areaYZ) * cog_tmp[2][1];
4992 }
4993 } else if(areaXZ < eps) {
4994 if(areaYZ < eps) {
4995 cog[0] = 1.0 / (6.0 * areaXY) * cog_tmp[0][0];
4996 cog[1] = 1.0 / (6.0 * areaXY) * cog_tmp[1][0];
4997 cog[2] = vertices[0][2];
4998 } else {
4999 cog[0] = 1.0 / (6.0 * areaXY) * cog_tmp[0][0];
5000 cog[1] = 1.0 / (6.0 * areaYZ) * cog_tmp[1][1];
5001 cog[2] = 1.0 / (6.0 * areaYZ) * cog_tmp[2][1];
5002 }
5003 } else if(areaYZ < eps) {
5004 cog[0] = 1.0 / (6.0 * areaXZ) * cog_tmp[0][1];
5005 cog[1] = 1.0 / (6.0 * areaXY) * cog_tmp[1][0];
5006 cog[2] = 1.0 / (6.0 * areaXZ) * cog_tmp[2][0];
5007 } else {
5008 cog[0] = 1.0 / (6.0 * areaXZ) * cog_tmp[0][1];
5009 cog[1] = 1.0 / (6.0 * areaYZ) * cog_tmp[1][1];
5010 cog[2] = 1.0 / (6.0 * areaYZ) * cog_tmp[2][1];
5011 }
5012
5013 m_log << " * cog: " << cog[0] << " " << cog[1] << " " << cog[2] << endl;
5014
5015 MFloat maxRadius = 0.0;
5016
5017 for(MInt i = 0; i < num; i++) {
5018 MFloat tmp = (vertices[i][0] - cog[0]) * (vertices[i][0] - cog[0])
5019 + (vertices[i][1] - cog[1]) * (vertices[i][1] - cog[1])
5020 + (vertices[i][2] - cog[2]) * (vertices[i][2] - cog[2]);
5021
5022 if(tmp > maxRadius) maxRadius = tmp;
5023 }
5024
5025 return sqrt(maxRadius);
5026}

◆ GetBoundarySize() [1/2]

MFloat Geometry3D::GetBoundarySize ( MFloat vertices,
MInt keepOffset,
MInt  size 
)
overridevirtual
Author
Andreas Lintermann
Date
17.09.2015
Parameters
[in]verticesthe vertices as an array (v00,v01,v02,v10,v11,v12,v20,v21,v22,...)
[in]sizethe size of the array return the area of the segment

Reimplemented from Geometry< 3 >.

Definition at line 4847 of file geometry3d.cpp.

4847 {
4848 TRACE();
4849
4850 MFloat area = 0;
4851 std::array<MFloat, nDim> cross;
4852 std::array<MFloat, nDim> edge1;
4853 std::array<MFloat, nDim> edge2;
4854
4855 for(MInt i = 0; i < size; i++) {
4856 MInt off = i;
4857
4858 if(keepOffset != nullptr) off = keepOffset[i];
4859
4860 for(MInt j = 0; j < nDim; j++) {
4861 edge1[j] = vertices[off + nDim + j] - vertices[off + j];
4862 edge2[j] = vertices[off + 2 * nDim + j] - vertices[off + j];
4863 }
4864
4865 cross[0] = edge1[1] * edge2[2] - edge2[1] * edge1[2];
4866 cross[1] = edge1[2] * edge2[0] - edge2[2] * edge1[0];
4867 cross[2] = edge1[0] * edge2[1] - edge2[0] * edge1[1];
4868
4869 area += sqrt(cross[0] * cross[0] + cross[1] * cross[1] + cross[2] * cross[2]) / 2;
4870 }
4871
4872
4873 return area;
4874}
void cross(const T *const u, const T *const v, T *const c)
Definition: maiamath.h:101

◆ GetBoundarySize() [2/2]

MFloat Geometry3D::GetBoundarySize ( MInt  segmentId)
overridevirtual
Author
Andreas Lintermann
Date
17.09.2015
Parameters
[in]segmentIdthe id of the segment return the area of the segment

Reimplemented from Geometry< 3 >.

Definition at line 4798 of file geometry3d.cpp.

4798 {
4799 TRACE();
4800
4801 MInt offsetStart = 0;
4802 MInt offsetEnd = 0;
4803 if(m_parallelGeometry) {
4804 offsetStart = m_segmentOffsets[segmentId];
4805 offsetEnd = m_segmentOffsets[segmentId + 1];
4806 } else {
4807 offsetStart = m_segmentOffsetsWithoutMB[segmentId];
4808 offsetEnd = m_segmentOffsetsWithoutMB[segmentId + 1];
4809 }
4810
4811 if(offsetStart == offsetEnd && !m_parallelGeometry)
4812 mTerm(1, AT_, "ERROR: You cannot choose a MB segment to calculate the characteristic Length");
4813
4814
4815 MFloat area = 0;
4816 std::array<MFloat, nDim> cross;
4817 std::array<MFloat, nDim> edge1;
4818 std::array<MFloat, nDim> edge2;
4819
4820 for(MInt i = m_segmentOffsets[segmentId]; i < m_segmentOffsets[segmentId + 1]; i++) {
4821 for(MInt j = 0; j < nDim; j++) {
4822 edge1[j] = elements[i].m_vertices[1][j] - elements[i].m_vertices[0][j];
4823 edge2[j] = elements[i].m_vertices[2][j] - elements[i].m_vertices[0][j];
4824 }
4825
4826 cross[0] = edge1[1] * edge2[2] - edge2[1] * edge1[2];
4827 cross[1] = edge1[2] * edge2[0] - edge2[2] * edge1[0];
4828 cross[2] = edge1[0] * edge2[1] - edge2[0] * edge1[1];
4829
4830 area += sqrt(cross[0] * cross[0] + cross[1] * cross[1] + cross[2] * cross[2]) / 2;
4831 }
4832
4833
4834 return area;
4835}
std::vector< MInt > m_segmentOffsetsWithoutMB
Definition: geometry.h:213

◆ GetBoundaryVertices()

MFloat ** Geometry3D::GetBoundaryVertices ( MInt  segmentId,
MFloat tri_vx,
MInt keepOffsets,
MInt  size,
MInt num 
)
overridevirtual
Author
Andreas Lintermann
Date
02.02.2010

The algorithm is devided into two parts. First, all border edges are extracted by running over all triangles of the segment and checking which edge appears only in one triangle. Then, the vertices are extracted in a cirular order by running over all extracted edges and doing a walkthrough element<3> by element<3>.

param[in] segmentId the id of the segment (only for serial geometry) param[in] tri_vx the triangles in one array (v00,v01,v02,v10,v11,v12,v20,v21,v22,...) (only for parallel geometry) param[in] keepOffsets only consider the triangles at the given offsets (only for parallel geometry) param[in] num the size of the first dimension of the returned 2D array return the circular ordered edges of the segment

Reimplemented from Geometry< 3 >.

Definition at line 4717 of file geometry3d.cpp.

4717 {
4718 TRACE();
4719
4720 vector<pair<MFloat*, MFloat*>> tmp_edges;
4721 // this runs over all triangles that have a certain segment id
4722
4724 tmp_edges = GetUniqueSegmentEdgesParGeom(tri_vx, keepOffsets, size);
4725 else
4726 tmp_edges = GetUniqueSegmentEdges(segmentId);
4727
4728 if(tmp_edges.size() < 2) {
4729 stringstream errorMsg;
4730 errorMsg << "ERROR: No boundary edges found for segment " << segmentId << endl;
4731 m_log << errorMsg.str();
4732 mTerm(1, AT_, errorMsg.str());
4733 }
4734
4735 // Get distinct elements in a circular ordering
4736 vector<MFloat*> tmp_points;
4737 MBoolScratchSpace visited(tmp_edges.size(), AT_, "visited");
4738 for(MInt i = 0; i < (signed)tmp_edges.size(); i++)
4739 visited[i] = false;
4740
4741 // insert first edge
4742 tmp_points.push_back(tmp_edges[0].first);
4743 tmp_points.push_back(tmp_edges[0].second);
4744 visited[0] = true;
4745
4746 MFloat* first = tmp_points[0];
4747 MInt cmpPos = 1;
4748
4749 for(MInt i = 1; i < (signed)tmp_edges.size(); i++) {
4750 for(MInt j = 1; j < (signed)tmp_edges.size(); j++) {
4751 // skip if alrady inserted
4752 if(visited[j]) continue;
4753
4754 pair<MFloat*, MFloat*> edge = tmp_edges[j];
4755
4756 // insert in this order
4757 if(vectorsEqual(edge.first, tmp_points[cmpPos])) {
4758 tmp_points.push_back(edge.second);
4759 visited[j] = true;
4760 cmpPos++;
4761 } else if(vectorsEqual(edge.second, tmp_points[cmpPos])) {
4762 tmp_points.push_back(edge.first);
4763 visited[j] = true;
4764 cmpPos++;
4765 }
4766 }
4767 }
4768
4769 if(!vectorsEqual(tmp_points[tmp_points.size() - 1], first)) {
4770 stringstream errorMsg;
4771 errorMsg << "ERROR: Inconsistency in segment " << segmentId << endl;
4772 m_log << errorMsg.str();
4773 mTerm(1, AT_, errorMsg.str());
4774 }
4775
4776 // Fill the array
4777 MFloat** vertices = new MFloat*[tmp_points.size() - 1];
4778 for(MInt i = 0; i < (MInt)tmp_points.size() - 1; i++) {
4779 vertices[i] = new MFloat[nDim];
4780 for(MInt j = 0; j < nDim; j++)
4781 vertices[i][j] = tmp_points[i][j];
4782 }
4783
4784 *num = tmp_points.size() - 1;
4785
4786 return vertices;
4787}
virtual std::vector< std::pair< MFloat *, MFloat * > > GetUniqueSegmentEdges(MInt segmentId)
Returns unique edges of a given set segment id.
virtual std::vector< std::pair< MFloat *, MFloat * > > GetUniqueSegmentEdgesParGeom(MFloat *tri_vx, MInt *keepOffsets, MInt size)
Returns unique edges of a given set segment id for parallel geometry.
MBool vectorsEqual(MFloat *a, MFloat *b)
Compares two vectors entry by entry.
Definition: geometry.cpp:114

◆ getClosestLineIntersectionLength()

MBool Geometry3D::getClosestLineIntersectionLength ( MInt  bndCndId,
const std::vector< MInt > &  nodeList,
MFloat targetRegion,
MFloat dist 
)
overridevirtual

Reimplemented from Geometry< 3 >.

Definition at line 3457 of file geometry3d.cpp.

3458 {
3459 TRACE();
3460
3461 MBool cut = false;
3462 *dist = 100000000000.0;
3463
3464 MFloat tmp_length;
3465
3466 MFloat eps = 0.00000000001;
3467
3468 MFloat u[nDim];
3469 MFloat v[nDim];
3470 MFloat normal[nDim];
3471 MFloat w[nDim];
3472 MFloat ray[nDim];
3473 MFloat ip[nDim];
3474
3475 for(MInt i = 0; i < nDim; i++) {
3476 ip[i] = w[i] = u[i] = v[i] = numeric_limits<MFloat>::max();
3477 }
3478
3479 MFloat a, b, r;
3480 MFloat D, uu, uv, vv, wu, wv;
3481 MFloat s, t;
3482
3483 MInt noReallyIntersectingNodes = 0;
3484
3485
3486 MInt maxNoNodes = 30;
3487 MFloat** tmp = new MFloat*[maxNoNodes];
3488 for(MInt k = 0; k < maxNoNodes; k++) {
3489 tmp[k] = new MFloat[nDim];
3490 }
3491 MBool singleIntersectionPoint;
3492
3493 MFloat e1[3], e2[3];
3494 for(MInt i = 0; i < nDim; i++) {
3495 e1[i] = targetRegion[i];
3496 e2[i] = targetRegion[i + nDim];
3497 ray[i] = e2[i] - e1[i];
3498 }
3499
3500 for(MInt n = 0; n < (signed)nodeList.size(); n++) {
3501 if(elements[nodeList[n]].m_bndCndId != bndCndId) continue;
3502
3503 tmp_length = 0.0;
3504
3505 // Init dot products
3506 a = b = uu = uv = vv = wu = wv = 0.0;
3507
3508 // Fill triangle edges
3509 for(MInt i = 0; i < nDim; i++) {
3510 u[i] = elements[nodeList[n]].m_vertices[1][i] - elements[nodeList[n]].m_vertices[0][i];
3511 v[i] = elements[nodeList[n]].m_vertices[2][i] - elements[nodeList[n]].m_vertices[0][i];
3512 w[i] = e1[i] - elements[nodeList[n]].m_vertices[0][i];
3513 }
3514
3515 // Get normal
3516 normal[0] = u[1] * v[2] - u[2] * v[1];
3517 normal[1] = u[2] * v[0] - u[0] * v[2];
3518 normal[2] = u[0] * v[1] - u[1] * v[0];
3519
3520 // dot products
3521 for(MInt i = 0; i < nDim; i++) {
3522 a += normal[i] * w[i];
3523 b += normal[i] * ray[i];
3524 }
3525 a *= -1;
3526
3527 if(fabs(b) < eps) {
3528 if(fabs(a) < eps) {
3529 // TODO labels:GEOM
3530 // ray lies in triangle plane
3531 noReallyIntersectingNodes++;
3532 cut = true;
3533 continue;
3534 } else
3535 // ray disjoint from plane
3536 continue;
3537 }
3538 r = a / b;
3539
3540 // is the ray going the right direction and is the scaling factor smaller than 1.0+eps
3541 if(r < -eps || r > F1 + eps) continue;
3542
3543 // dot products
3544 for(MInt i = 0; i < nDim; i++) {
3545 ip[i] = e1[i] + r * ray[i];
3546 uu += u[i] * u[i];
3547 uv += u[i] * v[i];
3548 vv += v[i] * v[i];
3549 w[i] = ip[i] - elements[nodeList[n]].m_vertices[0][i];
3550 wu += w[i] * u[i];
3551 wv += w[i] * v[i];
3552 }
3553
3554 D = uv * uv - uu * vv;
3555
3556 s = (uv * wv - vv * wu) / D;
3557 if(s < -eps || s > F1 + eps)
3558 // Intersection point is outside triangle
3559 continue;
3560 t = (uv * wu - uu * wv) / D;
3561 if(t < -eps || (s + t) > F1 + eps)
3562 // Intersection point is outside triangle
3563 continue;
3564
3565 // Here we are checking if such an intersection point has already been found.
3566 // This can be the case if the line intersects a triange edge or a vertex.
3567 singleIntersectionPoint = true;
3568
3569 if(noReallyIntersectingNodes == 0) {
3570 for(MInt i = 0; i < nDim; i++)
3571 tmp[noReallyIntersectingNodes][i] = ip[i];
3572 noReallyIntersectingNodes++;
3573 /*
3574 for(MInt dim=0; dim<nDim; dim++)
3575 tmp_length+=(ip[dim]-e1[dim])*(ip[dim]-e1[dim]);
3576 */
3577 for(MInt dim = 0; dim < nDim; dim++)
3578 tmp_length += (r * ray[dim]) * (r * ray[dim]);
3579
3580 tmp_length = sqrt(tmp_length);
3581
3582 if(tmp_length < *dist) *dist = tmp_length;
3583
3584 cut = true;
3585 } else {
3586 for(MInt f = 0; f < noReallyIntersectingNodes; f++) {
3587 if((fabs(tmp[f][0] - ip[0]) < eps) && (fabs(tmp[f][1] - ip[1]) < eps) && (fabs(tmp[f][2] - ip[2]) < eps)) {
3588 singleIntersectionPoint = false;
3589 break;
3590 }
3591 }
3592 if(singleIntersectionPoint) {
3593 for(MInt i = 0; i < nDim; i++)
3594 tmp[noReallyIntersectingNodes][i] = ip[i];
3595 noReallyIntersectingNodes++;
3596
3597 /*
3598 for(MInt dim=0; dim<nDim; dim++)
3599 tmp_length+=(ip[dim]-e1[dim])*(ip[dim]-e1[dim]);
3600 */
3601 for(MInt dim = 0; dim < nDim; dim++)
3602 tmp_length += (r * ray[dim]) * (r * ray[dim]);
3603
3604 tmp_length = sqrt(tmp_length);
3605
3606
3607 if(tmp_length < *dist) *dist = tmp_length;
3608
3609 cut = true;
3610 }
3611 }
3612 }
3613
3614 // free the temporary space
3615 for(MInt k = 0; k < maxNoNodes; k++) {
3616 delete[] tmp[k];
3617 tmp[k] = nullptr;
3618 }
3619 delete[] tmp;
3620 tmp = nullptr;
3621
3622 return cut;
3623}
bool MBool
Definition: maiatypes.h:58
MFloat dist(const Point< DIM > &p, const Point< DIM > &q)
Definition: pointbox.h:54

◆ getIntersectionElements() [1/2]

MInt Geometry3D::getIntersectionElements ( MFloat targetRegion,
std::vector< MInt > &  nodeList 
)
overridevirtual
Author
Rainhill Freitas
Date
unknown

Target region in this case means the gridcell.

Bug:
labels:GEOM This code does not run on IBM_BLUE_GENE. For plane/line intersection Cramers rule is used. The determinant in the denominator of Cramer's rule can become 0 and this is not acceptable for IBM_BLUE_GENE. Use the other Geometry3D::getIntersectionElements instead.

Reimplemented from Geometry< 3 >.

Definition at line 1910 of file geometry3d.cpp.

1910 {
1911 // TRACE();
1912
1914
1915 MInt noReallyIntersectingNodes = 0;
1916 // get all candidates for an intersection
1917 // Check for intersection...
1918 bitset<6> points[3];
1919 bitset<6> faceCodes[6];
1920 bitset<6> pCode;
1921 MInt spaceId;
1922 MInt spaceId1;
1923 MInt spaceId2;
1924 MInt edges[3][2] = {{0, 1}, {1, 2}, {0, 2}};
1925 // Corner points of the target regione i.e. p0=(targetRegion[targetPoints[0][0],
1926 // targetRegion[targetPoints[0][1],
1927 // targetRegion[targetPoints[0][2])
1928 MInt targetPoints[8][3] = {{0, 1, 2}, {3, 1, 2}, {0, 4, 2}, {3, 4, 2}, {0, 1, 5}, {3, 1, 5}, {0, 4, 5}, {3, 4, 5}};
1929
1930 // Edges of the targetRegion (using targetPoints)
1931 MInt targetEdges[12][2] = {{0, 1}, {2, 3}, {4, 5}, {6, 7}, // x-edges (i.e. parallel to x-axis)
1932 {0, 2}, {1, 3}, {4, 6}, {5, 7}, // y-edes
1933 {0, 4}, {1, 5}, {2, 6}, {3, 7}}; // z-edges
1934 MFloat e1[3];
1935 MFloat e2[3];
1936 MInt rejection = 0;
1937 MBool piercePointInside = 0;
1938 MBool triviallyAccepted = 0;
1939
1940 // Each of the following arrays holds one different point for
1941 // all of the 6 planes. Points are built with the targetRegion
1942 // i.e. a = targetRegiont[pointAInPlane[0]],
1943 // targetRegiont[pointAInPlane[1]],
1944 // targetRegiont[pointAInPlane[2]])
1945 // etc.
1946 MInt pointAInPlane[6][3] = {{0, 1, 2}, {3, 4, 5}, {0, 1, 2}, {3, 4, 5}, {0, 1, 2}, {3, 4, 5}};
1947
1948 MInt pointBInPlane[6][3] = {{0, 4, 2}, {3, 1, 5}, {3, 1, 2}, {0, 4, 5}, {3, 1, 2}, {3, 1, 5}};
1949
1950 MInt pointCInPlane[6][3] = {{0, 1, 5}, {3, 4, 2}, {3, 1, 5}, {0, 4, 2}, {3, 4, 2}, {0, 1, 5}};
1951 MFloat a[3] = {numeric_limits<MFloat>::max(), numeric_limits<MFloat>::max(),
1952 numeric_limits<MFloat>::max()}; // gcc 4.8.2 maybe uninitialized // point in plane
1953 MFloat b[3] = {numeric_limits<MFloat>::max(), numeric_limits<MFloat>::max(),
1954 numeric_limits<MFloat>::max()}; // gcc 4.8.2 maybe uninitialized // point in plane
1955 MFloat c[3] = {numeric_limits<MFloat>::max(), numeric_limits<MFloat>::max(),
1956 numeric_limits<MFloat>::max()}; // gcc 4.8.2 maybe uninitialized // point in plane
1957 MFloat d[3] = {numeric_limits<MFloat>::max(), numeric_limits<MFloat>::max(),
1958 numeric_limits<MFloat>::max()}; // gcc 4.8.2 maybe uninitialized // start of piercing edge
1959 MFloat e[3] = {numeric_limits<MFloat>::max(), numeric_limits<MFloat>::max(),
1960 numeric_limits<MFloat>::max()}; // gcc 4.8.2 maybe uninitialized // end of piercing edge
1961 MFloat s;
1962 MFloat gamma; // For pierce point calculation
1963 MFloat p2;
1964 MFloat q;
1965 MFloat epsilon = 0.00000000001;
1966 MFloat pP[3]; // piercePoint
1967 faceCodes[0] = IPOW2(0);
1968 faceCodes[1] = IPOW2(1);
1969 faceCodes[2] = IPOW2(2);
1970 faceCodes[3] = IPOW2(3);
1971 faceCodes[4] = IPOW2(4);
1972 faceCodes[5] = IPOW2(5);
1973 // edges[0][0] = 0;
1974 // edges[0][1] = 1;
1975 // edges[1][0] = 1;
1976 // edges[1][1] = 2;
1977 // edges[2][0] = 0;
1978 // edges[2][1] = 2;
1979 bitset<6> result;
1980
1981 m_adt->retrieveNodes(targetRegion, nodeList);
1982 const MInt noNodes = nodeList.size();
1983 // return noNodes;
1984 noReallyIntersectingNodes = 0;
1985
1986 for(MInt n = 0; n < noNodes; n++) {
1987 // create edges (in 3D) AB, AC, BC and point A B C
1988 // Determine outcode (see Aftosmis, Solution Adaptive Cartesian Grid Methods for Aerodynamic flows ...)
1989
1990 // Loop over all points of an element<3>
1991 for(MInt p = 0; p < nDim; p++) {
1992 points[p] = 0;
1993 // Calculate outcode for point
1994 for(MInt j = 0; j < nDim; j++) {
1995 if(elements[nodeList[n]].m_vertices[p][j] < targetRegion[j]) {
1996 points[p] |= faceCodes[2 * j];
1997 }
1998 if(elements[nodeList[n]].m_vertices[p][j] > targetRegion[j + nDim]) {
1999 points[p] |= faceCodes[2 * j + 1];
2000 }
2001 }
2002 // m_log << points[p] << endl;
2003 }
2004 rejection = 0;
2005 // check outcode combinations for edges for trivial rejection
2006 for(MInt i = 0; i < nDim; i++) {
2007 if((points[edges[i][0]] & points[edges[i][1]]) != 0) {
2008 rejection++;
2009 } else {
2010 // If one point is inside region the element<3> is trivially accepted
2011 triviallyAccepted = false;
2012 for(MInt k = 0; k < nDim; k++) {
2013 if(points[k] == 0) {
2014 triviallyAccepted = true;
2015 break;
2016 }
2017 }
2018 if(triviallyAccepted) {
2019 break;
2020 }
2021 // No trivial rejection, check for rejection of subsegment:
2022 // For all pierce points!
2023 // 1. Calculate pierce point:
2024 // a - determine plane for pierce point calculation
2025 // b - calculate pierce point
2026 // 2. Check for rejection of new segment
2027 // a - calculate new outcode
2028 // b - check for containment in pierce planes face
2029 // 3. If all(!) pierce points are rejected -> reject edge
2030 // TODO labels:GEOM This algorith might get a problem if a triangle lies completely on
2031 // a face.
2032
2033 // 1.a
2034 result = (points[edges[i][0]] | points[edges[i][1]]);
2035 piercePointInside = false;
2036 for(MInt j = 0; j < 2 * nDim; j++) {
2037 if(result[j] == 1) {
2038 // pierce plane found
2039 // Algorithm taken von AFTOSMIS. There seems to be an
2040 // error in the calculation of s in AFTOSMIS formula, the one below
2041 // should be correct!
2042 for(MInt k = 0; k < nDim; k++) {
2043 a[k] = targetRegion[pointAInPlane[j][k]];
2044 b[k] = targetRegion[pointBInPlane[j][k]];
2045 c[k] = targetRegion[pointCInPlane[j][k]];
2046 d[k] = elements[nodeList[n]].m_vertices[edges[i][0]][k];
2047 e[k] = elements[nodeList[n]].m_vertices[edges[i][1]][k];
2048 }
2049 gamma = ((e[0] - d[0]) * ((a[2] - c[2]) * (c[1] - b[1]) - (a[1] - c[1]) * (c[2] - b[2]))
2050 - (e[1] - d[1]) * ((a[2] - c[2]) * (c[0] - b[0]) - (a[0] - c[0]) * (c[2] - b[2]))
2051 + (e[2] - d[2]) * ((a[1] - c[1]) * (c[0] - b[0]) - (a[0] - c[0]) * (c[1] - b[1])));
2052
2053 s = ((c[0] - d[0]) * ((a[2] - c[2]) * (c[1] - b[1]) - (a[1] - c[1]) * (c[2] - b[2]))
2054 - (c[1] - d[1]) * ((a[2] - c[2]) * (c[0] - b[0]) - (a[0] - c[0]) * (c[2] - b[2]))
2055 + (c[2] - d[2]) * ((a[1] - c[1]) * (c[0] - b[0]) - (a[0] - c[0]) * (c[1] - b[1])))
2056 / gamma;
2057
2058 // 1. b Pierce point pP in plane j:
2059 for(MInt k = 0; k < nDim; k++) {
2060 pP[k] = d[k] + s * (e[k] - d[k]);
2061 }
2062 pCode = 0;
2063 // 2. a Calculate outcode for pierce point
2064 for(MInt k = 0; k < nDim; k++) {
2065 if(pP[k] < targetRegion[k]) {
2066 pCode |= faceCodes[2 * k];
2067 }
2068 if(pP[k] > targetRegion[k + nDim]) {
2069 pCode |= faceCodes[2 * k + 1];
2070 }
2071 }
2072 // m_log << " outcode of pierce point :" << pCode << endl;
2073
2074 } else {
2075 continue;
2076 }
2077 // 2. b
2078 result = faceCodes[j];
2079 result.flip();
2080 result = (result & pCode);
2081 if(result == 0) { // -> is contained
2082 piercePointInside = true;
2083 }
2084 }
2085 // reject if all pierce points are off coresponding face
2086 if(!piercePointInside) {
2087 rejection++;
2088 }
2089 }
2090 }
2091 // Check for internal element<3>, i.e. completely inside target
2092 result = (points[0] | points[1] | points[2]);
2093 if(result == 0) {
2094 nodeList[noReallyIntersectingNodes] = nodeList[n];
2095 noReallyIntersectingNodes++;
2096 continue;
2097 }
2098 // If not all edges are rejected a cutting element<3> has been found
2099 // m_log << rejection << endl;
2100 if(rejection < 3) {
2101 nodeList[noReallyIntersectingNodes] = nodeList[n];
2102 noReallyIntersectingNodes++;
2103 continue;
2104 }
2105
2106 // Even if trivially rejected, check if targetRegion is completely inside triangle
2107 // For that check all edges of the cell against the plane of the triangle,
2108 // calculate all pierce points and their outcodes and finally check for containment
2109 // in the targetRegion. Before the pierce point calculation check if the current
2110 // edge is parallel to the triangle (evaluate the distance of the edgepoints to the plane)
2111 if(rejection >= 3) {
2112 for(MInt t = 0; t < 12; t++) { // Loop over all 12 edges of the targetRegion (cell-cube)
2113 for(MInt p = 0; p < nDim; p++) {
2114 e1[p] = targetRegion[targetPoints[targetEdges[t][0]][p]];
2115 e2[p] = targetRegion[targetPoints[targetEdges[t][1]][p]];
2116 }
2117
2118 if(t < 4) {
2119 spaceId = 1;
2120 spaceId1 = 2;
2121 spaceId2 = 0;
2122 } else {
2123 if(t > 3 && t < 8) {
2124 spaceId = 2;
2125 spaceId1 = 0;
2126 spaceId2 = 1;
2127 } else {
2128 spaceId = 0;
2129 spaceId1 = 1;
2130 spaceId2 = 2;
2131 }
2132 }
2133
2134 for(MInt k = 0; k < nDim; k++) {
2135 a[k] = elements[nodeList[n]].m_vertices[0][k];
2136 b[k] = elements[nodeList[n]].m_vertices[1][k];
2137 c[k] = elements[nodeList[n]].m_vertices[2][k];
2138 }
2139 if(approx(a[spaceId1], b[spaceId1], MFloatEps) && !approx(a[spaceId1], c[spaceId1], MFloatEps)) {
2140 // aspaceId != bspaceId, otherwise a and b would be the same point
2141 q = (e1[spaceId1] - a[spaceId1]) / (c[spaceId1] - a[spaceId1]);
2142 p2 = (e1[spaceId] - a[spaceId] - q * (c[spaceId] - a[spaceId])) / (b[spaceId] - a[spaceId]);
2143 } else {
2144 if(!approx(a[spaceId1], b[spaceId1], MFloatEps) && approx(a[spaceId1], c[spaceId1], MFloatEps)) {
2145 // aspaceId != cspaceId, otherwise a and c would be the same point
2146 p2 = (e1[spaceId1] - a[spaceId1]) / (b[spaceId1] - a[spaceId1]);
2147 q = (e1[spaceId] - a[spaceId] - p2 * (b[spaceId] - a[spaceId])) / (c[spaceId] - a[spaceId]);
2148 } else {
2149 if(approx(a[spaceId], b[spaceId], MFloatEps) && !approx(a[spaceId], c[spaceId], MFloatEps)) {
2150 // aspaceId1 != bspaceId1, otherwise a and b would be the same point
2151 q = (e1[spaceId] - a[spaceId]) / (c[spaceId] - a[spaceId]);
2152 p2 = (e1[spaceId1] - a[spaceId1] - q * (c[spaceId1] - a[spaceId1])) / (b[spaceId1] - a[spaceId1]);
2153 } else {
2154 if(!approx(a[spaceId], b[spaceId], MFloatEps) && approx(a[spaceId], c[spaceId], MFloatEps)) {
2155 // aspaceId1 != cspaceId1, otherwise a and c would be the same point
2156 p2 = (e1[spaceId] - a[spaceId]) / (b[spaceId] - a[spaceId]);
2157 q = (e1[spaceId1] - a[spaceId1] - p2 * (b[spaceId1] - a[spaceId1])) / (c[spaceId1] - a[spaceId1]);
2158 } else {
2159 // aspaceId1 != bspaceId1 && aspaceId1 != cspaceId1 && aspaceId != bspaceId && aspaceId != cspaceId
2160 q = ((e1[spaceId1] - a[spaceId1]) * (b[spaceId] - a[spaceId])
2161 - (b[spaceId1] - a[spaceId1]) * (e1[spaceId] - a[spaceId]))
2162 / ((c[spaceId1] - a[spaceId1]) * (b[spaceId] - a[spaceId])
2163 - (b[spaceId1] - a[spaceId1]) * (c[spaceId] - a[spaceId]));
2164 p2 = (e1[spaceId] - a[spaceId] - q * (c[spaceId] - a[spaceId])) / (b[spaceId] - a[spaceId]);
2165 }
2166 }
2167 }
2168 }
2169
2170 if(p2 * q >= 0 || p2 * q < 0) {
2171 // compute s
2172 gamma = a[spaceId2] + p2 * (b[spaceId2] - a[spaceId2]) + q * (c[spaceId2] - a[spaceId2]);
2173 s = (gamma - e1[spaceId2]) / (e2[spaceId2] - e1[spaceId2]);
2174
2175 if(s < -epsilon || s > F1 + epsilon || p2 < -epsilon || q < -epsilon || (p2 + q) > F1 + epsilon) {
2176 } else {
2178 /* if( edgeTriangleIntersection(elements[nodeList[n]].m_vertices[0],
2179 elements[nodeList[n]].m_vertices[1],
2180 elements[nodeList[n]].m_vertices[2], e1, e2) ){*/
2181 nodeList[noReallyIntersectingNodes] = nodeList[n];
2182 noReallyIntersectingNodes++;
2183 break;
2184 }
2185 }
2186 }
2187 }
2188
2189 // write nodes in reallyIntersectingNodes
2190 }
2191 // if(noNodes)
2192 if((noNodes != 0) && (noReallyIntersectingNodes == 0)) {
2193 // m_log << "Rejected ! "<< ++rejectionCounter << endl;
2194 }
2195
2196 nodeList.resize(noReallyIntersectingNodes);
2197
2198 getIECommCounter += noReallyIntersectingNodes;
2199
2200 return noReallyIntersectingNodes;
2201}
MInt getIECallCounter
Definition: geometry3d.h:127
MInt getIECommCounter
Definition: geometry3d.h:128
MBool approx(const T &, const U &, const T)
Definition: functions.h:272
constexpr MLong IPOW2(MInt x)
constexpr std::underlying_type< FcCell >::type p(const FcCell property)
Converts property name to underlying integer value.

◆ getIntersectionElements() [2/2]

MInt Geometry3D::getIntersectionElements ( MFloat targetRegion,
std::vector< MInt > &  nodeList,
MFloat  cellHalfLength,
const MFloat *const  cell_coords 
)
overridevirtual
Author
Andreas Lintermann
Date
24.11.2009

The separating axis theorem (SAT) states, that two convex polyhedra, that are to be tested against intersection are disjoint, if they can be separated along either an axis parallel to a normal of a face of the first or the second polyhedra, or along an axis formed from the cross product of an edge from them.

To make things simpler, an axis aligned gridcell is considered centered in the origin. Therefore, the triangle is translated accordingly.

Algorithm:

  • 1) Create for all grid directions the normal with the triangle edges Then project the triangle vertices \(v0,v1,v2\) onto these edges and the box as well. For latter purpose create a radius defined by:

    \[r = h_x|a_x| + h_y|a_y| + h_z|a_z|,\]

    where \(h_i\) is the halflength of the box and \(a_i\) is the grid direction. One of the directions for \(a_i\) is 0, which reduces the above to:

    \begin{eqnarray*} r_x = h_y|a_y| + h_z|a_z|\\ r_y = h_x|a_x| + h_z|a_z|\ \ r_z = h_x|a_x| + h_y|a_y| \end{eqnarray*}

    Then check the projected triangle points against the radius

  • 2) Test overlap in the \({x,y,z}\)-directions find min, max of the triangle each direction, and test for overlap in that direction – this is equivalent to testing a minimal AABB around the triangle against the AABB
  • 3) Test if the box intersects the plane of the triangle -> compute plane equation of triangle: \(n*x+d=0\)

If all tests pass, the the box and the triangle are intersecting!

This function replaces Geometry3D::getIntersectionElements.

Reimplemented from Geometry< 3 >.

Definition at line 1784 of file geometry3d.cpp.

1785 {
1786 // TRACE();
1787
1789
1790 m_adt->retrieveNodes(targetRegion, nodeList);
1791 const MInt noNodes = nodeList.size();
1792 MFloat vert_mov[MAX_SPACE_DIMENSIONS][MAX_SPACE_DIMENSIONS];
1793 MFloat edge_mov[MAX_SPACE_DIMENSIONS][MAX_SPACE_DIMENSIONS];
1794 MFloat edge_fabs[MAX_SPACE_DIMENSIONS][MAX_SPACE_DIMENSIONS];
1795 MFloat min;
1796 MFloat max;
1797 MFloat d;
1798 MFloat p0;
1799 MFloat p1;
1800 MFloat rad;
1801 MFloat normal[MAX_SPACE_DIMENSIONS];
1802 MFloat vmin[MAX_SPACE_DIMENSIONS] = {numeric_limits<MFloat>::max(), numeric_limits<MFloat>::max(),
1803 numeric_limits<MFloat>::max()}; // gcc 4.8.2 maybe uninitialized
1804 MFloat vmax[MAX_SPACE_DIMENSIONS] = {numeric_limits<MFloat>::max(), numeric_limits<MFloat>::max(),
1805 numeric_limits<MFloat>::max()}; // gcc 4.8.2 maybe uninitialized
1806
1807 MInt combo[3][6] = {{0, 2, 0, 2, 1, 2}, {0, 2, 0, 2, 0, 1}, {0, 1, 0, 1, 1, 2}};
1808
1809 MInt noReallyIntersectingNodes = 0;
1810 MBool cut;
1811
1812 for(MInt n = 0; n < noNodes; n++) {
1813 cut = true;
1814
1815 // Fill arrays (translate triangle)
1816 for(MInt i = 0; i < nDim; i++) {
1817 for(MInt j = 0; j < nDim; j++) {
1818 vert_mov[j][i] = elements[nodeList[n]].m_vertices[j][i] - cell_coords[i];
1819 }
1820 for(MInt j = 0; j < nDim; j++) {
1821 edge_mov[j][i] = vert_mov[(j + 1) % nDim][i] - vert_mov[j][i];
1822 edge_fabs[j][i] = fabs(edge_mov[j][i]);
1823 }
1824 }
1825
1826 MInt mul;
1827
1828 // Step 1) of the algorithm
1829 for(MInt i = 0; i < nDim; i++) {
1830 mul = 1;
1831 for(MInt l = 0, j = 2, k = 1; l < nDim; l++) {
1832 p0 = mul * edge_mov[i][j] * vert_mov[combo[i][2 * l]][k] - mul * edge_mov[i][k] * vert_mov[combo[i][2 * l]][j];
1833 p1 = mul * edge_mov[i][j] * vert_mov[combo[i][2 * l + 1]][k]
1834 - mul * edge_mov[i][k] * vert_mov[combo[i][2 * l + 1]][j];
1835
1836 (p0 < p1) ? (min = p0, max = p1) : (min = p1, max = p0);
1837 rad = cellHalfLength * (edge_fabs[i][j] + edge_fabs[i][k]);
1838
1839 if(min > rad || max < -rad) {
1840 cut = false;
1841 break;
1842 }
1843
1844 mul *= -1;
1845 j -= l;
1846 k = 0;
1847 }
1848 if(!cut) break;
1849 }
1850 if(!cut) continue;
1851
1852 // Step 2) of the algorithm
1853 for(MInt i = 0; i < nDim; i++) {
1854 min = max = vert_mov[0][i];
1855 for(MInt j = 1; j < nDim; j++) {
1856 if(vert_mov[j][i] < min) min = vert_mov[j][i];
1857 if(vert_mov[j][i] > max) max = vert_mov[j][i];
1858 }
1859
1860 if(min > cellHalfLength || max < -cellHalfLength) {
1861 cut = false;
1862 break;
1863 }
1864 }
1865 if(!cut) continue;
1866
1867 // Step 3) of the algorithm
1868 normal[0] = edge_mov[0][1] * edge_mov[1][2] - edge_mov[0][2] * edge_mov[1][1];
1869 normal[1] = edge_mov[0][2] * edge_mov[1][0] - edge_mov[0][0] * edge_mov[1][2];
1870 normal[2] = edge_mov[0][0] * edge_mov[1][1] - edge_mov[0][1] * edge_mov[1][0];
1871
1872 d = 0.0;
1873 for(MInt i = 0; i < nDim; i++)
1874 d += normal[i] * vert_mov[0][i];
1875 d *= -1;
1876
1877 for(MInt i = 0; i < nDim; i++) {
1878 if(normal[i] > 0.0f) {
1879 vmin[i] = -cellHalfLength;
1880 vmax[i] = cellHalfLength;
1881 } else {
1882 vmin[i] = cellHalfLength;
1883 vmax[i] = -cellHalfLength;
1884 }
1885 }
1886
1887 if((normal[0] * vmin[0] + normal[1] * vmin[1] + normal[2] * vmin[2]) + d > 0.0f) continue;
1888 if((normal[0] * vmax[0] + normal[1] * vmax[1] + normal[2] * vmax[2]) + d >= 0.0f) {
1889 nodeList[noReallyIntersectingNodes] = nodeList[n];
1890 noReallyIntersectingNodes++;
1891 }
1892 }
1893
1894 nodeList.resize(noReallyIntersectingNodes);
1895
1896 getIECommCounter += noReallyIntersectingNodes;
1897
1898 return noReallyIntersectingNodes;
1899}

◆ getIntersectionElementsTetraeder()

MInt Geometry3D::getIntersectionElementsTetraeder ( MFloat targetRegion,
std::vector< MInt > &  nodeList 
)
virtual

Definition at line 2208 of file geometry3d.cpp.

2208 {
2209 TRACE();
2210
2212
2213 MInt noReallyIntersectingNodes = 0;
2214 // get all candidates for an intersection
2215 // Check for intersection...
2216 bitset<6> points[3];
2217 bitset<6> faceCodes[6];
2218 bitset<6> pCode;
2219 MInt edges[3][2] = {{0, 1}, {1, 2}, {0, 2}};
2220 // Corner points of the target regione i.e. p0=(targetRegion[targetPoints[0][0],
2221 // targetRegion[targetPoints[0][1],
2222 // targetRegion[targetPoints[0][2])
2223 MInt targetPoints[8][3] = {{0, 1, 2}, {3, 1, 2}, {0, 4, 2}, {3, 4, 2}, {0, 1, 5}, {3, 1, 5}, {0, 4, 5}, {3, 4, 5}};
2224
2225 // Edges of the targetRegion (using targetPoints)
2226 MInt targetEdges[12][2] = {{0, 1}, {2, 3}, {4, 5}, {6, 7}, // x-edges (i.e. parallel to x-axis)
2227 {0, 2}, {1, 3}, {4, 6}, {5, 7}, // y-edes
2228 {0, 4}, {1, 5}, {2, 6}, {3, 7}}; // z-edges
2229 MFloat e1[3];
2230 MFloat e2[3];
2231 MInt rejection = 0;
2232 MBool piercePointInside = 0;
2233 MBool triviallyAccepted = 0;
2234
2235 // Each of the following arrays holds one different point for
2236 // all of the 6 planes. Points are built with the targetRegion
2237 // i.e. a = targetRegiont[pointAInPlane[0]],
2238 // targetRegiont[pointAInPlane[1]],
2239 // targetRegiont[pointAInPlane[2]])
2240 // etc.
2241 MInt pointAInPlane[6][3] = {{0, 1, 2}, {3, 4, 5}, {0, 1, 2}, {3, 4, 5}, {0, 1, 2}, {3, 4, 5}};
2242
2243 MInt pointBInPlane[6][3] = {{0, 4, 2}, {3, 1, 5}, {3, 1, 2}, {0, 4, 5}, {3, 1, 2}, {3, 1, 5}};
2244
2245 MInt pointCInPlane[6][3] = {{0, 1, 5}, {3, 4, 2}, {3, 1, 5}, {0, 4, 2}, {3, 4, 2}, {0, 1, 5}};
2246 MFloat a[3] = {numeric_limits<MFloat>::max(), numeric_limits<MFloat>::max(),
2247 numeric_limits<MFloat>::max()}; // gcc 4.8.2 maybe uninitialized // point in plane
2248 MFloat b[3] = {numeric_limits<MFloat>::max(), numeric_limits<MFloat>::max(),
2249 numeric_limits<MFloat>::max()}; // gcc 4.8.2 maybe uninitialized // point in plane
2250 MFloat c[3] = {numeric_limits<MFloat>::max(), numeric_limits<MFloat>::max(),
2251 numeric_limits<MFloat>::max()}; // gcc 4.8.2 maybe uninitialized // point in plane
2252 MFloat d[3] = {numeric_limits<MFloat>::max(), numeric_limits<MFloat>::max(),
2253 numeric_limits<MFloat>::max()}; // gcc 4.8.2 maybe uninitialized // start of piercing edge
2254 MFloat e[3] = {numeric_limits<MFloat>::max(), numeric_limits<MFloat>::max(),
2255 numeric_limits<MFloat>::max()}; // gcc 4.8.2 maybe uninitialized // end of piercing edge
2256 MFloat s, gamma; // For pierce point calculation
2257 MFloat pP[3]; // piercePoint
2258 faceCodes[0] = IPOW2(0);
2259 faceCodes[1] = IPOW2(1);
2260 faceCodes[2] = IPOW2(2);
2261 faceCodes[3] = IPOW2(3);
2262 faceCodes[4] = IPOW2(4);
2263 faceCodes[5] = IPOW2(5);
2264 // edges[0][0] = 0;
2265 // edges[0][1] = 1;
2266 // edges[1][0] = 1;
2267 // edges[1][1] = 2;
2268 // edges[2][0] = 0;
2269 // edges[2][1] = 2;
2270 bitset<6> result;
2271
2272 m_adt->retrieveNodes(targetRegion, nodeList);
2273 const MInt noNodes = nodeList.size();
2274 // return noNodes;
2275 noReallyIntersectingNodes = 0;
2276
2277 for(MInt n = 0; n < noNodes; n++) {
2278 // create edges (in 3D) AB, AC, BC and point A B C
2279 // Determine outcode (see Aftosmis, Solution Adaptive Cartesian Grid Methods for Aerodynamic flows ...)
2280
2281 // Loop over all points of an element<3>
2282 for(MInt p = 0; p < nDim; p++) {
2283 points[p] = 0;
2284 // Calculate outcode for point
2285 for(MInt j = 0; j < nDim; j++) {
2286 if(elements[nodeList[n]].m_vertices[p][j] < targetRegion[j]) {
2287 points[p] |= faceCodes[2 * j];
2288 }
2289 if(elements[nodeList[n]].m_vertices[p][j] > targetRegion[j + nDim]) {
2290 points[p] |= faceCodes[2 * j + 1];
2291 }
2292 }
2293 // m_log << points[p] << endl;
2294 }
2295 rejection = 0;
2296 // check outcode combinations for edges for trivial rejection
2297 for(auto& edge : edges) {
2298 if((points[edge[0]] & points[edge[1]]) != 0) {
2299 rejection++;
2300 } else {
2301 // If one point is inside region the element<3> is trivially accepted
2302 triviallyAccepted = false;
2303 for(auto& point : points) {
2304 if(point == 0) {
2305 triviallyAccepted = true;
2306 break;
2307 }
2308 }
2309 if(triviallyAccepted) {
2310 break;
2311 }
2312 // No trivial rejection, check for rejection of subsegment:
2313 // For all pierce points!
2314 // 1. Calculate pierce point:
2315 // a - determine plane for pierce point calculation
2316 // b - calculate pierce point
2317 // 2. Check for rejection of new segment
2318 // a - calculate new outcode
2319 // b - check for containment in pierce planes face
2320 // 3. If all(!) pierce points are rejected -> reject edge
2321 // TODO labels:GEOM This algorith might get a problem if a triangle lies completely on
2322 // a face.
2323
2324 // 1.a
2325 result = (points[edge[0]] | points[edge[1]]);
2326 piercePointInside = false;
2327 for(MInt j = 0; j < 2 * nDim; j++) {
2328 if(result[j] == 1) {
2329 // pierce plane found
2330 // Algorithm taken von AFTOSMIS. There seems to be an
2331 // error in the calculation of s in AFTOSMIS formula, the one below
2332 // should be correct!
2333 for(MInt k = 0; k < nDim; k++) {
2334 a[k] = targetRegion[pointAInPlane[j][k]];
2335 b[k] = targetRegion[pointBInPlane[j][k]];
2336 c[k] = targetRegion[pointCInPlane[j][k]];
2337 d[k] = elements[nodeList[n]].m_vertices[edge[0]][k];
2338 e[k] = elements[nodeList[n]].m_vertices[edge[1]][k];
2339 }
2340 gamma = ((e[0] - d[0]) * ((a[2] - c[2]) * (c[1] - b[1]) - (a[1] - c[1]) * (c[2] - b[2]))
2341 - (e[1] - d[1]) * ((a[2] - c[2]) * (c[0] - b[0]) - (a[0] - c[0]) * (c[2] - b[2]))
2342 + (e[2] - d[2]) * ((a[1] - c[1]) * (c[0] - b[0]) - (a[0] - c[0]) * (c[1] - b[1])));
2343
2344 s = ((c[0] - d[0]) * ((a[2] - c[2]) * (c[1] - b[1]) - (a[1] - c[1]) * (c[2] - b[2]))
2345 - (c[1] - d[1]) * ((a[2] - c[2]) * (c[0] - b[0]) - (a[0] - c[0]) * (c[2] - b[2]))
2346 + (c[2] - d[2]) * ((a[1] - c[1]) * (c[0] - b[0]) - (a[0] - c[0]) * (c[1] - b[1])))
2347 / gamma;
2348
2349 // 1. b Pierce point pP in plane j:
2350 for(MInt k = 0; k < nDim; k++) {
2351 pP[k] = d[k] + s * (e[k] - d[k]);
2352 }
2353 pCode = 0;
2354 // 2. a Calculate outcode for pierce point
2355 for(MInt k = 0; k < nDim; k++) {
2356 if(pP[k] < targetRegion[k]) {
2357 pCode |= faceCodes[2 * k];
2358 }
2359 if(pP[k] > targetRegion[k + nDim]) {
2360 pCode |= faceCodes[2 * k + 1];
2361 }
2362 }
2363 // m_log << " outcode of pierce point :" << pCode << endl;
2364
2365 } else {
2366 continue;
2367 }
2368 // 2. b
2369 result = faceCodes[j];
2370 result.flip();
2371 result = (result & pCode);
2372 if(result == 0) { // -> is contained
2373 piercePointInside = true;
2374 }
2375 }
2376 // reject if all pierce points are off coresponding face
2377 if(!piercePointInside) {
2378 rejection++;
2379 }
2380 }
2381 }
2382 // Check for internal element<3>, i.e. completely inside target
2383 result = (points[0] | points[1] | points[2]);
2384 if(result == 0) {
2385 nodeList[noReallyIntersectingNodes] = nodeList[n];
2386 noReallyIntersectingNodes++;
2387 continue;
2388 }
2389 // If not all edges are rejected a cutting element<3> has been found
2390 // m_log << rejection << endl;
2391 if(rejection < 3) {
2392 nodeList[noReallyIntersectingNodes] = nodeList[n];
2393 noReallyIntersectingNodes++;
2394 continue;
2395 }
2396
2397 // Even if trivially rejected, check if targetRegion is completely inside triangle
2398 // For that check all edges of the cell against the plane of the triangle,
2399 // calculate all pierce points and their outcodes and finally check for containment
2400 // in the targetRegion. Before the pierce point calculation check if the current
2401 // edge is parallel to the triangle (evaluate the distance of the edgepoints to the plane)
2402 if(rejection >= 3) {
2403 for(auto& targetEdge : targetEdges) { // Loop over all 12 edges of the targetRegion (cell-cube)
2404 for(MInt p = 0; p < nDim; p++) {
2405 e1[p] = targetRegion[targetPoints[targetEdge[0]][p]];
2406 e2[p] = targetRegion[targetPoints[targetEdge[1]][p]];
2407 }
2409 if(edgeTriangleIntersection(elements[nodeList[n]].m_vertices[0], elements[nodeList[n]].m_vertices[1],
2410 elements[nodeList[n]].m_vertices[2], e1, e2)) {
2411 nodeList[noReallyIntersectingNodes] = nodeList[n];
2412 noReallyIntersectingNodes++;
2413 break;
2414 }
2415 }
2416 }
2417
2418 // write nodes in reallyIntersectingNodes
2419 }
2420 // if(noNodes)
2421 if(noNodes && !noReallyIntersectingNodes) {
2422 // m_log << "Rejected ! "<< ++rejectionCounter << endl;
2423 }
2424
2425 nodeList.resize(noReallyIntersectingNodes);
2426
2427 return noReallyIntersectingNodes;
2428}
MInt getIETCallCounter
Definition: geometry3d.h:129
MBool edgeTriangleIntersection(MFloat *trianglePoint1, MFloat *trianglePoint2, MFloat *trianglePoint3, MFloat *edgePoint1, MFloat *edgePoint2) override
Determine intersection between an edge and a triangle.

◆ getIntersectionMBElements()

MInt Geometry3D::getIntersectionMBElements ( MFloat targetRegion,
std::vector< MInt > &  nodeList 
)
overridevirtual

Reimplemented from Geometry< 3 >.

Definition at line 3626 of file geometry3d.cpp.

3626 {
3627 TRACE();
3628
3629 otherCalls++;
3630
3631
3632 MInt noReallyIntersectingNodes = 0;
3633 // get all candidates for an intersection
3634 // Check for intersection...
3635 bitset<6> points[3];
3636 bitset<6> faceCodes[6];
3637 bitset<6> pCode;
3638 MInt spaceId;
3639 MInt spaceId1;
3640 MInt spaceId2;
3641 MInt edges[3][2] = {{0, 1}, {1, 2}, {0, 2}};
3642 // Corner points of the target regione i.e. p0=(targetRegion[targetPoints[0][0],
3643 // targetRegion[targetPoints[0][1],
3644 // targetRegion[targetPoints[0][2])
3645 MInt targetPoints[8][3] = {{0, 1, 2}, {3, 1, 2}, {0, 4, 2}, {3, 4, 2}, {0, 1, 5}, {3, 1, 5}, {0, 4, 5}, {3, 4, 5}};
3646
3647 // Edges of the targetRegion (using targetPoints)
3648 MInt targetEdges[12][2] = {{0, 1}, {2, 3}, {4, 5}, {6, 7}, // x-edges (i.e. parallel to x-axis)
3649 {0, 2}, {1, 3}, {4, 6}, {5, 7}, // y-edes
3650 {0, 4}, {1, 5}, {2, 6}, {3, 7}}; // z-edges
3651 MFloat e1[3];
3652 MFloat e2[3];
3653 MInt rejection;
3654 MBool piercePointInside;
3655 MBool triviallyAccepted;
3656
3657 // Each of the following arrays holds one different point for
3658 // all of the 6 planes. Points are built with the targetRegion
3659 // i.e. a = targetRegiont[pointAInPlane[0]],
3660 // targetRegiont[pointAInPlane[1]],
3661 // targetRegiont[pointAInPlane[2]])
3662 // etc.
3663 MInt pointAInPlane[6][3] = {{0, 1, 2}, {3, 4, 5}, {0, 1, 2}, {3, 4, 5}, {0, 1, 2}, {3, 4, 5}};
3664
3665 MInt pointBInPlane[6][3] = {{0, 4, 2}, {3, 1, 5}, {3, 1, 2}, {0, 4, 5}, {3, 1, 2}, {3, 1, 5}};
3666
3667 MInt pointCInPlane[6][3] = {{0, 1, 5}, {3, 4, 2}, {3, 1, 5}, {0, 4, 2}, {3, 4, 2}, {0, 1, 5}};
3668 MFloat a[3]; // point in plane
3669 MFloat b[3]; // point in plane
3670 MFloat c[3]; // point in plane
3671 MFloat d[3] = {numeric_limits<MFloat>::max(), numeric_limits<MFloat>::max(),
3672 numeric_limits<MFloat>::max()}; // gcc 4.8.2 maybe uninitialized // start of piercing edge
3673 MFloat e[3] = {numeric_limits<MFloat>::max(), numeric_limits<MFloat>::max(),
3674 numeric_limits<MFloat>::max()}; // gcc 4.8.2 maybe uninitialized // end of piercing edge
3675 MFloat s;
3676 MFloat gamma; // For pierce point calculation
3677 MFloat p2;
3678 MFloat q;
3679 MFloat epsilon = 0.00000000001;
3680 MFloat pP[3]; // piercePoint
3681 faceCodes[0] = IPOW2(0);
3682 faceCodes[1] = IPOW2(1);
3683 faceCodes[2] = IPOW2(2);
3684 faceCodes[3] = IPOW2(3);
3685 faceCodes[4] = IPOW2(4);
3686 faceCodes[5] = IPOW2(5);
3687 // edges[0][0] = 0;
3688 // edges[0][1] = 1;
3689 // edges[1][0] = 1;
3690 // edges[1][1] = 2;
3691 // edges[2][0] = 0;
3692 // edges[2][1] = 2;
3693 bitset<6> result;
3694 m_adt->retrieveNodesMBElements(targetRegion, nodeList);
3695 const MInt noNodes = nodeList.size();
3696 // return noNodes;
3697 noReallyIntersectingNodes = 0;
3698
3699 for(MInt n = 0; n < noNodes; n++) {
3700 // create edges (in 3D) AB, AC, BC and point A B C
3701 // Determine outcode (see Aftosmis, Solution Adaptive Cartesian Grid Methods for Aerodynamic flows ...)
3702
3703 // Loop over all points of an element<3>
3704 for(MInt p = 0; p < nDim; p++) {
3705 points[p] = 0;
3706 // Calculate outcode for point
3707 for(MInt j = 0; j < nDim; j++) {
3708 if(mbelements[nodeList[n]].m_vertices[p][j] < targetRegion[j]) {
3709 points[p] |= faceCodes[2 * j];
3710 }
3711 if(mbelements[nodeList[n]].m_vertices[p][j] > targetRegion[j + nDim]) {
3712 points[p] |= faceCodes[2 * j + 1];
3713 }
3714 }
3715 // m_log << points[p] << endl;
3716 }
3717 rejection = 0;
3718 // check outcode combinations for edges for trivial rejection
3719 for(auto& edge : edges) {
3720 if((points[edge[0]] & points[edge[1]]) != 0) {
3721 rejection++;
3722 } else {
3723 // If one point is inside region the element<3> is trivially accepted
3724 triviallyAccepted = false;
3725 for(MInt k = 0; k < nDim; k++) {
3726 if(points[k] == 0) {
3727 triviallyAccepted = true;
3728 break;
3729 }
3730 }
3731 if(triviallyAccepted) {
3732 break;
3733 }
3734 // No trivial rejection, check for rejection of subsegment:
3735 // For all pierce points!
3736 // 1. Calculate pierce point:
3737 // a - determine plane for pierce point calculation
3738 // b - calculate pierce point
3739 // 2. Check for rejection of new segment
3740 // a - calculate new outcode
3741 // b - check for containment in pierce planes face
3742 // 3. If all(!) pierce points are rejected -> reject edge
3743 // TODO labels:GEOM This algorith might get a problem if a triangle lies completely on
3744 // a face.
3745
3746 // 1.a
3747 result = (points[edge[0]] | points[edge[1]]);
3748 piercePointInside = false;
3749 for(MInt j = 0; j < 2 * nDim; j++) {
3750 if(result[j] == 1) {
3751 // pierce plane found
3752 // Algorithm taken von AFTOSMIS. There seems to be an
3753 // error in the calculation of s in AFTOSMIS formula, the one below
3754 // should be correct!
3755 for(MInt k = 0; k < nDim; k++) {
3756 a[k] = targetRegion[pointAInPlane[j][k]];
3757 b[k] = targetRegion[pointBInPlane[j][k]];
3758 c[k] = targetRegion[pointCInPlane[j][k]];
3759 d[k] = mbelements[nodeList[n]].m_vertices[edge[0]][k];
3760 e[k] = mbelements[nodeList[n]].m_vertices[edge[1]][k];
3761 }
3762 gamma = ((e[0] - d[0]) * ((a[2] - c[2]) * (c[1] - b[1]) - (a[1] - c[1]) * (c[2] - b[2]))
3763 - (e[1] - d[1]) * ((a[2] - c[2]) * (c[0] - b[0]) - (a[0] - c[0]) * (c[2] - b[2]))
3764 + (e[2] - d[2]) * ((a[1] - c[1]) * (c[0] - b[0]) - (a[0] - c[0]) * (c[1] - b[1])));
3765
3766 s = ((c[0] - d[0]) * ((a[2] - c[2]) * (c[1] - b[1]) - (a[1] - c[1]) * (c[2] - b[2]))
3767 - (c[1] - d[1]) * ((a[2] - c[2]) * (c[0] - b[0]) - (a[0] - c[0]) * (c[2] - b[2]))
3768 + (c[2] - d[2]) * ((a[1] - c[1]) * (c[0] - b[0]) - (a[0] - c[0]) * (c[1] - b[1])))
3769 / gamma;
3770
3771 // 1. b Pierce point pP in plane j:
3772 for(MInt k = 0; k < nDim; k++) {
3773 pP[k] = d[k] + s * (e[k] - d[k]);
3774 }
3775 pCode = 0;
3776 // 2. a Calculate outcode for pierce point
3777 for(MInt k = 0; k < nDim; k++) {
3778 if(pP[k] < targetRegion[k]) {
3779 pCode |= faceCodes[2 * k];
3780 }
3781 if(pP[k] > targetRegion[k + nDim]) {
3782 pCode |= faceCodes[2 * k + 1];
3783 }
3784 }
3785 // m_log << " outcode of pierce point :" << pCode << endl;
3786
3787 } else {
3788 continue;
3789 }
3790 // 2. b
3791 result = faceCodes[j];
3792 result.flip();
3793 result = (result & pCode);
3794 if(result == 0) { // -> is contained
3795 piercePointInside = true;
3796 }
3797 }
3798 // reject if all pierce points are off coresponding face
3799 if(!piercePointInside) {
3800 rejection++;
3801 }
3802 }
3803 }
3804 // Check for internal element<3>, i.e. completely inside target
3805 result = (points[0] | points[1] | points[2]);
3806 if(result == 0) {
3807 nodeList[noReallyIntersectingNodes] = nodeList[n];
3808 noReallyIntersectingNodes++;
3809 continue;
3810 }
3811 // If not all edges are rejected a cutting element<3> has been found
3812 // m_log << rejection << endl;
3813 if(rejection < 3) {
3814 nodeList[noReallyIntersectingNodes] = nodeList[n];
3815 noReallyIntersectingNodes++;
3816 continue;
3817 }
3818
3819 // Even if trivially rejected, check if targetRegion is completely inside triangle
3820 // For that check all edges of the cell against the plane of the triangle,
3821 // calculate all pierce points and their outcodes and finally check for containment
3822 // in the targetRegion. Before the pierce point calculation check if the current
3823 // edge is parallel to the triangle (evaluate the distance of the edgepoints to the plane)
3824 if(rejection >= 3) {
3825 for(MInt t = 0; t < 12; t++) { // Loop over all 12 edges of the targetRegion (cell-cube)
3826 for(MInt p = 0; p < nDim; p++) {
3827 e1[p] = targetRegion[targetPoints[targetEdges[t][0]][p]];
3828 e2[p] = targetRegion[targetPoints[targetEdges[t][1]][p]];
3829 }
3830
3831 if(t < 4) {
3832 spaceId = 1;
3833 spaceId1 = 2;
3834 spaceId2 = 0;
3835 } else {
3836 if(t > 3 && t < 8) {
3837 spaceId = 2;
3838 spaceId1 = 0;
3839 spaceId2 = 1;
3840 } else {
3841 spaceId = 0;
3842 spaceId1 = 1;
3843 spaceId2 = 2;
3844 }
3845 }
3846
3847 for(MInt k = 0; k < nDim; k++) {
3848 a[k] = mbelements[nodeList[n]].m_vertices[0][k];
3849 b[k] = mbelements[nodeList[n]].m_vertices[1][k];
3850 c[k] = mbelements[nodeList[n]].m_vertices[2][k];
3851 }
3852 if(approx(a[spaceId1], b[spaceId1], MFloatEps) && !approx(a[spaceId1], c[spaceId1], MFloatEps)) {
3853 // aspaceId != bspaceId, otherwise a and b would be the same point
3854 q = (e1[spaceId1] - a[spaceId1]) / (c[spaceId1] - a[spaceId1]);
3855 p2 = (e1[spaceId] - a[spaceId] - q * (c[spaceId] - a[spaceId])) / (b[spaceId] - a[spaceId]);
3856 } else {
3857 if(!approx(a[spaceId1], b[spaceId1], MFloatEps) && approx(a[spaceId1], c[spaceId1], MFloatEps)) {
3858 // aspaceId != cspaceId, otherwise a and c would be the same point
3859 p2 = (e1[spaceId1] - a[spaceId1]) / (b[spaceId1] - a[spaceId1]);
3860 q = (e1[spaceId] - a[spaceId] - p2 * (b[spaceId] - a[spaceId])) / (c[spaceId] - a[spaceId]);
3861 } else {
3862 if(approx(a[spaceId], b[spaceId], MFloatEps) && !approx(a[spaceId], c[spaceId], MFloatEps)) {
3863 // aspaceId1 != bspaceId1, otherwise a and b would be the same point
3864 q = (e1[spaceId] - a[spaceId]) / (c[spaceId] - a[spaceId]);
3865 p2 = (e1[spaceId1] - a[spaceId1] - q * (c[spaceId1] - a[spaceId1])) / (b[spaceId1] - a[spaceId1]);
3866 } else {
3867 if(!approx(a[spaceId], b[spaceId], MFloatEps) && approx(a[spaceId], c[spaceId], MFloatEps)) {
3868 // aspaceId1 != cspaceId1, otherwise a and c would be the same point
3869 p2 = (e1[spaceId] - a[spaceId]) / (b[spaceId] - a[spaceId]);
3870 q = (e1[spaceId1] - a[spaceId1] - p2 * (b[spaceId1] - a[spaceId1])) / (c[spaceId1] - a[spaceId1]);
3871 } else {
3872 // aspaceId1 != bspaceId1 && aspaceId1 != cspaceId1 && aspaceId != bspaceId && aspaceId != cspaceId
3873 q = ((e1[spaceId1] - a[spaceId1]) * (b[spaceId] - a[spaceId])
3874 - (b[spaceId1] - a[spaceId1]) * (e1[spaceId] - a[spaceId]))
3875 / ((c[spaceId1] - a[spaceId1]) * (b[spaceId] - a[spaceId])
3876 - (b[spaceId1] - a[spaceId1]) * (c[spaceId] - a[spaceId]));
3877 p2 = (e1[spaceId] - a[spaceId] - q * (c[spaceId] - a[spaceId])) / (b[spaceId] - a[spaceId]);
3878 }
3879 }
3880 }
3881 }
3882
3883 if(p2 * q >= 0 || p2 * q < 0) {
3884 // compute s
3885 gamma = a[spaceId2] + p2 * (b[spaceId2] - a[spaceId2]) + q * (c[spaceId2] - a[spaceId2]);
3886 s = (gamma - e1[spaceId2]) / (e2[spaceId2] - e1[spaceId2]);
3887
3888 if(s < -epsilon || s > F1 + epsilon || p2 < -epsilon || q < -epsilon || (p2 + q) > F1 + epsilon) {
3889 } else {
3891 /* if( edgeTriangleIntersection(elements[nodeList[n]].m_vertices[0],
3892 elements[nodeList[n]].m_vertices[1],
3893 elements[nodeList[n]].m_vertices[2], e1, e2) ){*/
3894 nodeList[noReallyIntersectingNodes] = nodeList[n];
3895 noReallyIntersectingNodes++;
3896 break;
3897 }
3898 }
3899 }
3900 }
3901
3902 // write nodes in reallyIntersectingNodes
3903 }
3904 // if(noNodes)
3905 if(noNodes && !noReallyIntersectingNodes) {
3906 // m_log << "Rejected ! "<< ++rejectionCounter << endl;
3907 }
3908 nodeList.resize(noReallyIntersectingNodes);
3909
3910 return noReallyIntersectingNodes;
3911}
element< nDim > * mbelements
Definition: geometry.h:218

◆ getLineIntersectionElements() [1/2]

MInt Geometry3D::getLineIntersectionElements ( MFloat targetRegion)
overridevirtual

Reimplemented from Geometry< 3 >.

Definition at line 3284 of file geometry3d.cpp.

3284 {
3285 // TRACE();
3286 TERMM(1, "should not be used anymore");
3287
3289
3290 const MFloat eps = 0.00000000001;
3291
3292 MFloat u[nDim];
3293 MFloat v[nDim];
3294 MFloat normal[nDim];
3295 MFloat w[nDim];
3296 MFloat ray[nDim];
3297 MFloat* ip = nullptr;
3298
3299 for(MInt i = 0; i < nDim; i++) {
3300 u[i] = v[i] = w[i] = numeric_limits<MFloat>::max();
3301 }
3302
3303 stack<MFloat*> allIPs;
3304
3305 MFloat a;
3306 MFloat b;
3307 MFloat r;
3308 MFloat D;
3309 MFloat uu;
3310 MFloat uv;
3311 MFloat vv;
3312 MFloat wu;
3313 MFloat wv;
3314 MFloat s;
3315 MFloat t;
3316
3317 MInt noReallyIntersectingNodes = 0;
3318
3319 std::vector<MInt> nodeList;
3320
3321 MInt maxNoNodes = 30;
3322 auto** tmp = new MFloat*[maxNoNodes];
3323 for(MInt k = 0; k < maxNoNodes; k++) {
3324 tmp[k] = new MFloat[nDim];
3325 }
3326 MBool singleIntersectionPoint;
3327
3328 m_adt->retrieveNodes(targetRegion, nodeList);
3329 const MInt noNodes = nodeList.size();
3330
3331 MFloat e1[3];
3332 MFloat e2[3];
3333 for(MInt i = 0; i < nDim; i++) {
3334 e1[i] = targetRegion[i];
3335 e2[i] = targetRegion[i + nDim];
3336 ray[i] = e2[i] - e1[i];
3337 }
3338
3339 for(MInt n = 0; n < noNodes; n++) {
3340 // Init dot products
3341 a = b = uu = uv = vv = wu = wv = 0.0;
3342
3343 // Fill triangle edges
3344 for(MInt i = 0; i < nDim; i++) {
3345 u[i] = elements[nodeList[n]].m_vertices[1][i] - elements[nodeList[n]].m_vertices[0][i];
3346 v[i] = elements[nodeList[n]].m_vertices[2][i] - elements[nodeList[n]].m_vertices[0][i];
3347 w[i] = e1[i] - elements[nodeList[n]].m_vertices[0][i];
3348 }
3349
3350 // Get normal
3351 normal[0] = u[1] * v[2] - u[2] * v[1];
3352 normal[1] = u[2] * v[0] - u[0] * v[2];
3353 normal[2] = u[0] * v[1] - u[1] * v[0];
3354
3355 // dot products
3356 for(MInt i = 0; i < nDim; i++) {
3357 a += normal[i] * w[i];
3358 b += normal[i] * ray[i];
3359 }
3360 a *= -1;
3361
3362 if(fabs(b) < eps) {
3363 if(fabs(a) < eps) {
3364 // ray lies in triangle plane
3365 nodeList[noReallyIntersectingNodes] = nodeList[n];
3366 // noReallyIntersectingNodes++;
3367 m_log << "Found ray in triangle plane" << endl;
3368 continue;
3369 } else
3370 // ray disjoint from plane
3371 continue;
3372 }
3373 r = a / b;
3374
3375 // is the ray going the right direction and is the scaling factor smaller than 1.0+eps
3376 if(r < -eps || r > F1 + eps) continue;
3377
3378 // dot products
3379 ip = new MFloat[3];
3380
3381 for(MInt i = 0; i < nDim; i++) {
3382 ip[i] = e1[i] + r * ray[i];
3383 uu += u[i] * u[i];
3384 uv += u[i] * v[i];
3385 vv += v[i] * v[i];
3386 w[i] = ip[i] - elements[nodeList[n]].m_vertices[0][i];
3387 wu += w[i] * u[i];
3388 wv += w[i] * v[i];
3389 }
3390
3391 D = uv * uv - uu * vv;
3392
3393 s = (uv * wv - vv * wu) / D;
3394 if(s < -eps || s > F1 + eps)
3395 // Intersection point is outside triangle
3396 continue;
3397 t = (uv * wu - uu * wv) / D;
3398 if(t < -eps || (s + t) > F1 + eps)
3399 // Intersection point is outside triangle
3400 continue;
3401
3402 // Here we are checking if there are multiple intersection points.
3403 // This can be the case if the line intersects a triangle edge or a vertex.
3404
3405 singleIntersectionPoint = true;
3406
3407 if(noReallyIntersectingNodes == 0) {
3408 for(MInt i = 0; i < nDim; i++)
3409 tmp[noReallyIntersectingNodes][i] = ip[i];
3410
3411 nodeList[noReallyIntersectingNodes] = nodeList[n];
3412 allIPs.push(tmp[noReallyIntersectingNodes]);
3413
3414 noReallyIntersectingNodes++;
3415 } else {
3416 for(MInt f = 0; f < noReallyIntersectingNodes; f++) {
3417 if((fabs(tmp[f][0] - ip[0]) < eps) && (fabs(tmp[f][1] - ip[1]) < eps) && (fabs(tmp[f][2] - ip[2]) < eps)) {
3418 singleIntersectionPoint = false;
3419 // m_log << "Found multiple points" << endl;
3420 break;
3421 }
3422 }
3423
3424 if(singleIntersectionPoint) {
3425 for(MInt i = 0; i < nDim; i++)
3426 tmp[noReallyIntersectingNodes][i] = ip[i];
3427
3428 nodeList[noReallyIntersectingNodes] = nodeList[n];
3429 noReallyIntersectingNodes++;
3430
3431 } else {
3432 delete[] ip;
3433 }
3434 }
3435 }
3436
3437 nodeList.resize(noReallyIntersectingNodes);
3438
3439 // free the temporary space
3440 for(MInt k = 0; k < maxNoNodes; k++) {
3441 delete[] tmp[k];
3442 tmp[k] = 0;
3443 }
3444 delete[] tmp;
3445 tmp = 0;
3446
3447 getLIE2CommCounter += noReallyIntersectingNodes;
3448
3449 return noReallyIntersectingNodes;
3450}
MInt getLIE2CommCounter
Definition: geometry3d.h:126
MInt m_getLIE2CallCounter
Definition: geometry3d.h:125

◆ getLineIntersectionElements() [2/2]

MInt Geometry3D::getLineIntersectionElements ( MFloat targetRegion,
std::vector< MInt > &  nodeList 
)
overridevirtual
Author
Andreas Lintermann
Date
24.11.2009

Let the following be definded:

  • triangle = \(v0,v1,v2\)
  • edge = \(e1,e2\)
  • normal on triangle plane = \(n\)
  • \(v1-v0 = u\)
  • \(v2-v0 = v\)
  • intersection point = \(w = su + tv\)

The perp-dot operator is defined by

\begin{eqnarray*} v^\perp = n \times v = (u*v)v - (v*v)u\\ u^\perp = n \times u = (u*u)v - (u*v)u \end{eqnarray*}

Then we get:

\begin{eqnarray*} & w & = su + tv\\ \Leftrightarrow & n * v^\perp & = su * v^\perp + tv * v^\perp = su * v^\perp\\ \Leftrightarrow & s & = \frac{w\times v^\perp}{u\times v^\perp}\\ & & =\frac{(u*v)(w*v) - (v*v)(w*u)}{(u*v)(u*v) - (u*u)(v*v)} \end{eqnarray*}

\begin{eqnarray*} & w & = su + tv\\ \Leftrightarrow & n * u^\perp & = su * u^\perp + tv * u^\perp = su * u^\perp\\ \Leftrightarrow & t & = \frac{w\times u^\perp}{u\times u^\perp}\\ & & =\frac{(u*v)(w*u) - (u*u)(w*v)}{(u*v)(u*v) - (u*u)(v*v)} \end{eqnarray*}

Reimplemented from Geometry< 3 >.

Definition at line 3147 of file geometry3d.cpp.

3147 {
3148 // TRACE();
3149
3151
3152 const MFloat eps = 0.00000000001;
3153
3154 MFloat u[nDim];
3155 MFloat v[nDim];
3156 MFloat w[nDim];
3157
3158 constexpr MInt maxNoNodes = 20; // Should prevent vector reallocation in most cases
3159 std::vector<MFloat> ips{};
3160 ips.reserve(nDim * maxNoNodes);
3161
3162 m_adt->retrieveNodes(targetRegion, nodeList);
3163 const MInt noNodes = nodeList.size();
3164 MFloat e1[3];
3165 MFloat ray[nDim];
3166 for(MInt i = 0; i < nDim; i++) {
3167 e1[i] = targetRegion[i];
3168 ray[i] = targetRegion[i + nDim] - e1[i];
3169 }
3170
3171 MInt noReallyIntersectingNodes = 0;
3172 for(MInt n = 0; n < noNodes; n++) {
3173 const MInt nodeId = nodeList[n];
3174 MFloat** const verts = elements[nodeId].m_vertices;
3175 const MFloat* const vert0 = verts[0];
3176 const MFloat* const vert1 = verts[1];
3177 const MFloat* const vert2 = verts[2];
3178
3179 // Fill triangle edges
3180 for(MInt i = 0; i < nDim; i++) {
3181 const MFloat v0 = vert0[i];
3182 u[i] = vert1[i] - v0;
3183 v[i] = vert2[i] - v0;
3184 w[i] = e1[i] - v0;
3185 }
3186
3187 // Get normal
3188 const MFloat normal0 = u[1] * v[2] - u[2] * v[1];
3189 const MFloat normal1 = u[2] * v[0] - u[0] * v[2];
3190 const MFloat normal2 = u[0] * v[1] - u[1] * v[0];
3191
3192 // dot products
3193 const MFloat a = -(normal0 * w[0] + normal1 * w[1] + normal2 * w[2]);
3194 const MFloat b = normal0 * ray[0] + normal1 * ray[1] + normal2 * ray[2];
3195
3196 if(fabs(b) < eps) {
3197 if(fabs(a) < eps) {
3198 // ray lies in triangle plane
3199 // TODO labels:GEOM commented the following two lines; check what should be done in such case as ips is not
3200 // filled for the check later; occurs in case FV/3D_MP_postprocessing_coarse - no difference in results
3201 /* nodeList[noReallyIntersectingNodes] = nodeList[n]; */
3202 /* noReallyIntersectingNodes++; */
3203 m_log << "Found ray in triangle plane" << endl;
3204 continue;
3205 } else {
3206 // ray disjoint from plane
3207 continue;
3208 }
3209 }
3210 const MFloat r = a / b;
3211
3212 const MFloat F1eps = F1 + eps;
3213 // is the ray going the right direction and is the scaling factor smaller than 1.0+eps
3214 if(r < -eps || r > F1eps) continue;
3215
3216
3217 const MFloat uu = u[0] * u[0] + u[1] * u[1] + u[2] * u[2];
3218 const MFloat uv = u[0] * v[0] + u[1] * v[1] + u[2] * v[2];
3219 const MFloat vv = v[0] * v[0] + v[1] * v[1] + v[2] * v[2];
3220
3221 MFloat wu = 0.0;
3222 MFloat wv = 0.0;
3223 MFloat ip[nDim];
3224 // dot products
3225 for(MInt i = 0; i < nDim; i++) {
3226 ip[i] = e1[i] + r * ray[i];
3227 const MFloat tmp = ip[i] - vert0[i];
3228 wu += tmp * u[i];
3229 wv += tmp * v[i];
3230 }
3231
3232 const MFloat D = uv * uv - uu * vv;
3233
3234 const MFloat s = (uv * wv - vv * wu) / D;
3235 if(s < -eps || s > F1eps)
3236 // Intersection point is outside triangle
3237 continue;
3238
3239 const MFloat t = (uv * wu - uu * wv) / D;
3240 if(t < -eps || (s + t) > F1eps)
3241 // Intersection point is outside triangle
3242 continue;
3243
3244 // Here we are checking if such an intersection point has already been found.
3245 // This can be the case if the line intersects a triange edge or a vertex.
3246 if(noReallyIntersectingNodes == 0) {
3247 ASSERT(ips.empty(), "ips not empty");
3248 for(MInt i = 0; i < nDim; i++) {
3249 ips.push_back(ip[i]);
3250 }
3251 nodeList[noReallyIntersectingNodes] = nodeList[n];
3252 noReallyIntersectingNodes++;
3253 } else {
3254 MBool singleIntersectionPoint = true;
3255 for(MInt f = 0; f < noReallyIntersectingNodes; f++) {
3256 if((fabs(ips[f * nDim] - ip[0]) < eps) && (fabs(ips[f * nDim + 1] - ip[1]) < eps)
3257 && (fabs(ips[f * nDim + 2] - ip[2]) < eps)) {
3258 singleIntersectionPoint = false;
3259 // m_log << "Found multiple points" << endl;
3260 break;
3261 }
3262 }
3263 if(singleIntersectionPoint) {
3264 for(MInt i = 0; i < nDim; i++) {
3265 ips.push_back(ip[i]);
3266 }
3267 nodeList[noReallyIntersectingNodes] = nodeList[n];
3268 noReallyIntersectingNodes++;
3269 ASSERT(ips.size() == (MUlong)(noReallyIntersectingNodes * nDim),
3270 "Error: wrong vector size of ips. " + std::to_string(ips.size())
3271 + " != " + std::to_string(noReallyIntersectingNodes * nDim));
3272 }
3273 }
3274 }
3275
3276 nodeList.resize(noReallyIntersectingNodes);
3277
3278 getLIE2CommCounter += noReallyIntersectingNodes;
3279
3280 return noReallyIntersectingNodes;
3281}
uint64_t MUlong
Definition: maiatypes.h:65

◆ getLineIntersectionElementsOld2()

MInt Geometry3D::getLineIntersectionElementsOld2 ( MFloat targetRegion,
MInt spaceDirection,
std::vector< MInt > &  nodeList 
)
overridevirtual
Author
Daniel Hartmann
Date
unknown

Test is evaluated by the barycentric coordinates of the intersection point. Therefore a 3 by 3 linear equation system is solved with Cramers rule. This function replaces Geometry3D::getLineIntersectionElementsOld1.

Bug:
labels:GEOM This method does not run on IBM_BLUE_GENE and is hence not used anymore. This is because the determinant in the denominator of Cramers rule can become 0, which can not be handled by IBM_BLUE_GENE. Please use Geometry3D::getLineIntersectionElements instead.

Reimplemented from Geometry< 3 >.

Definition at line 2989 of file geometry3d.cpp.

2990 {
2991 // TRACE();
2992
2994
2995 MBool singleIntersectionPoint = 0;
2996 MInt noReallyIntersectingNodes = 0;
2997 m_adt->retrieveNodes(targetRegion, nodeList);
2998 const MInt noNodes = nodeList.size();
2999 MInt maxNoNodes = 120;
3000 MInt spaceId;
3001 MInt spaceId1;
3002 MInt spaceId2;
3003 array<MFloat, nDim> e1{};
3004 array<MFloat, nDim> e2{};
3005 MFloat epsilon = 0.00000000001;
3006 array<MFloat, nDim> a{};
3007 array<MFloat, nDim> b{};
3008 array<MFloat, nDim> c{};
3009 MFloat gamma;
3010 MFloat s;
3011 MFloat p;
3012 MFloat q;
3013 array<MFloat, nDim> pP{};
3014 auto** temp = new MFloat*[maxNoNodes];
3015 for(MInt k = 0; k < maxNoNodes; k++) {
3016 temp[k] = new MFloat[nDim];
3017 }
3018
3019 for(MInt i = 0; i < nDim; i++) {
3020 e1[i] = targetRegion[i];
3021 e2[i] = targetRegion[i + nDim];
3022 }
3023 spaceId = spaceDirection[0];
3024 spaceId1 = spaceDirection[1];
3025 spaceId2 = spaceDirection[2];
3026
3027 for(MInt n = 0; n < noNodes; n++) {
3028 for(MInt k = 0; k < nDim; k++) {
3029 a[k] = elements[nodeList[n]].m_vertices[0][k];
3030 b[k] = elements[nodeList[n]].m_vertices[1][k];
3031 c[k] = elements[nodeList[n]].m_vertices[2][k];
3032 }
3033 if(approx(a[spaceId1], b[spaceId1], MFloatEps) && !approx(a[spaceId1], c[spaceId1], MFloatEps)) {
3034 // aspaceId != bspaceId, otherwise a and b would be the same point
3035 q = (e1[spaceId1] - a[spaceId1]) / (c[spaceId1] - a[spaceId1]);
3036 p = (e1[spaceId] - a[spaceId] - q * (c[spaceId] - a[spaceId])) / (b[spaceId] - a[spaceId]);
3037 } else {
3038 if(!approx(a[spaceId1], b[spaceId1], MFloatEps) && approx(a[spaceId1], c[spaceId1], MFloatEps)) {
3039 // aspaceId != cspaceId, otherwise a and c would be the same point
3040 p = (e1[spaceId1] - a[spaceId1]) / (b[spaceId1] - a[spaceId1]);
3041 q = (e1[spaceId] - a[spaceId] - p * (b[spaceId] - a[spaceId])) / (c[spaceId] - a[spaceId]);
3042 } else {
3043 if(approx(a[spaceId], b[spaceId], MFloatEps) && !approx(a[spaceId], c[spaceId], MFloatEps)) {
3044 // aspaceId1 != bspaceId1, otherwise a and b would be the same point
3045 q = (e1[spaceId] - a[spaceId]) / (c[spaceId] - a[spaceId]);
3046 p = (e1[spaceId1] - a[spaceId1] - q * (c[spaceId1] - a[spaceId1])) / (b[spaceId1] - a[spaceId1]);
3047 } else {
3048 if(!approx(a[spaceId], b[spaceId], MFloatEps) && approx(a[spaceId], c[spaceId], MFloatEps)) {
3049 // aspaceId1 != cspaceId1, otherwise a and c would be the same point
3050 p = (e1[spaceId] - a[spaceId]) / (b[spaceId] - a[spaceId]);
3051 q = (e1[spaceId1] - a[spaceId1] - p * (b[spaceId1] - a[spaceId1])) / (c[spaceId1] - a[spaceId1]);
3052 } else {
3053 // aspaceId1 != bspaceId1 && aspaceId1 != cspaceId1 && aspaceId != bspaceId && aspaceId != cspaceId
3054 q = ((e1[spaceId1] - a[spaceId1]) * (b[spaceId] - a[spaceId])
3055 - (b[spaceId1] - a[spaceId1]) * (e1[spaceId] - a[spaceId]))
3056 / ((c[spaceId1] - a[spaceId1]) * (b[spaceId] - a[spaceId])
3057 - (b[spaceId1] - a[spaceId1]) * (c[spaceId] - a[spaceId]));
3058 p = (e1[spaceId] - a[spaceId] - q * (c[spaceId] - a[spaceId])) / (b[spaceId] - a[spaceId]);
3059 }
3060 }
3061 }
3062 }
3063
3064 if(p * q >= 0 || p * q < 0) {
3065 // compute s
3066 gamma = a[spaceId2] + p * (b[spaceId2] - a[spaceId2]) + q * (c[spaceId2] - a[spaceId2]);
3067 s = (gamma - e1[spaceId2]) / (e2[spaceId2] - e1[spaceId2]);
3068
3069 if(s < -epsilon || s > F1 + epsilon || p < -epsilon || q < -epsilon || (p + q) > F1 + epsilon) {
3070 } else {
3071 singleIntersectionPoint = true;
3072
3073 // cut point pP
3074 for(MInt g = 0; g < nDim; g++) {
3075 pP[g] = e1[g] + s * (e2[g] - e1[g]);
3076 temp[noReallyIntersectingNodes][g] = pP[g];
3077 }
3078
3079 if(noReallyIntersectingNodes == 0) {
3080 nodeList[noReallyIntersectingNodes] = nodeList[n];
3081 noReallyIntersectingNodes++;
3082 } else {
3083 for(MInt f = 0; f < noReallyIntersectingNodes; f++) {
3084 if((fabs(temp[f][0] - pP[0]) < epsilon) && (fabs(temp[f][1] - pP[1]) < epsilon)
3085 && (fabs(temp[f][2] - pP[2]) < epsilon)) {
3086 singleIntersectionPoint = false;
3087 break;
3088 }
3089 }
3090 if(singleIntersectionPoint) {
3091 nodeList[noReallyIntersectingNodes] = nodeList[n];
3092 noReallyIntersectingNodes++;
3093 }
3094 }
3095 }
3096 }
3097 }
3098 nodeList.resize(noReallyIntersectingNodes);
3099
3100 // free memory
3101 for(MInt k = 0; k < maxNoNodes; k++) {
3102 delete[] temp[k];
3103 }
3104 delete[] temp;
3105
3106 getLIE2CommCounter += noReallyIntersectingNodes;
3107
3108 return noReallyIntersectingNodes;
3109}

◆ getLineIntersectionMBElements()

MInt Geometry3D::getLineIntersectionMBElements ( MFloat targetRegion,
std::vector< MInt > &  nodeList 
)
overridevirtual

Reimplemented from Geometry< 3 >.

Definition at line 4039 of file geometry3d.cpp.

4039 {
4040 TRACE();
4041
4042 otherCalls++;
4043
4044
4045 MInt noReallyIntersectingNodes = 0;
4046 m_adt->retrieveNodes(targetRegion, nodeList);
4047 const MInt noNodes = nodeList.size();
4048 MFloat e1[3], e2[3];
4049 for(MInt i = 0; i < nDim; i++) {
4050 e1[i] = targetRegion[i];
4051 e2[i] = targetRegion[i + nDim];
4052 }
4053
4054 for(MInt n = 0; n < noNodes; n++) {
4056 if(edgeTriangleIntersection(mbelements[nodeList[n]].m_vertices[0], mbelements[nodeList[n]].m_vertices[1],
4057 mbelements[nodeList[n]].m_vertices[2], e1, e2)) {
4058 nodeList[noReallyIntersectingNodes] = nodeList[n];
4059 noReallyIntersectingNodes++;
4060 }
4061 }
4062 nodeList.resize(noReallyIntersectingNodes);
4063
4064 return noReallyIntersectingNodes;
4065}

◆ getLineIntersectionMBElements2()

MInt Geometry3D::getLineIntersectionMBElements2 ( MFloat targetRegion,
MInt spaceDirection,
std::vector< MInt > &  nodeList,
MInt  bcIc 
)
overridevirtual

Reimplemented from Geometry< 3 >.

Definition at line 4068 of file geometry3d.cpp.

4069 {
4070 TRACE();
4071
4072 otherCalls++;
4073
4074
4075 MBool singleIntersectionPoint;
4076 MInt noReallyIntersectingNodes = 0;
4077 m_adt->retrieveNodesMBElements(targetRegion, nodeList);
4078 const MInt noNodes = nodeList.size();
4079 // TAN maxNoNodes is low
4080 MInt maxNoNodes = noNodes; // 50;
4081 MInt spaceId, spaceId1, spaceId2;
4082 MFloat* e1 = new MFloat[nDim];
4083 MFloat* e2 = new MFloat[nDim];
4084 MFloat epsilon = 0.00000000001;
4085 MFloat* a = new MFloat[nDim];
4086 MFloat* b = new MFloat[nDim];
4087 MFloat* c = new MFloat[nDim];
4088 MFloat gamma, s, p, q;
4089 MFloat* pP = new MFloat[nDim];
4090 MFloat** temp = new MFloat*[maxNoNodes];
4091 for(MInt k = 0; k < maxNoNodes; k++) {
4092 temp[k] = new MFloat[nDim];
4093 }
4094
4095 for(MInt i = 0; i < nDim; i++) {
4096 e1[i] = targetRegion[i];
4097 e2[i] = targetRegion[i + nDim];
4098 }
4099 spaceId = spaceDirection[0];
4100 spaceId1 = spaceDirection[1];
4101 spaceId2 = spaceDirection[2];
4102
4103 for(MInt n = 0; n < noNodes; n++) {
4104 if(mbelements[nodeList[n]].m_bndCndId != bcId) continue;
4105 for(MInt k = 0; k < nDim; k++) {
4106 a[k] = mbelements[nodeList[n]].m_vertices[0][k];
4107 b[k] = mbelements[nodeList[n]].m_vertices[1][k];
4108 c[k] = mbelements[nodeList[n]].m_vertices[2][k];
4109 }
4110 if(approx(a[spaceId1], b[spaceId1], MFloatEps) && !approx(a[spaceId1], c[spaceId1], MFloatEps)) {
4111 // aspaceId != bspaceId, otherwise a and b would be the same point
4112 q = (e1[spaceId1] - a[spaceId1]) / (c[spaceId1] - a[spaceId1]);
4113 p = (e1[spaceId] - a[spaceId] - q * (c[spaceId] - a[spaceId])) / (b[spaceId] - a[spaceId]);
4114 } else {
4115 if(!approx(a[spaceId1], b[spaceId1], MFloatEps) && approx(a[spaceId1], c[spaceId1], MFloatEps)) {
4116 // aspaceId != cspaceId, otherwise a and c would be the same point
4117 p = (e1[spaceId1] - a[spaceId1]) / (b[spaceId1] - a[spaceId1]);
4118 q = (e1[spaceId] - a[spaceId] - p * (b[spaceId] - a[spaceId])) / (c[spaceId] - a[spaceId]);
4119 } else {
4120 if(approx(a[spaceId], b[spaceId], MFloatEps) && !approx(a[spaceId], c[spaceId], MFloatEps)) {
4121 // aspaceId1 != bspaceId1, otherwise a and b would be the same point
4122 q = (e1[spaceId] - a[spaceId]) / (c[spaceId] - a[spaceId]);
4123 p = (e1[spaceId1] - a[spaceId1] - q * (c[spaceId1] - a[spaceId1])) / (b[spaceId1] - a[spaceId1]);
4124 } else {
4125 if(!approx(a[spaceId], b[spaceId], MFloatEps) && approx(a[spaceId], c[spaceId], MFloatEps)) {
4126 // aspaceId1 != cspaceId1, otherwise a and c would be the same point
4127 p = (e1[spaceId] - a[spaceId]) / (b[spaceId] - a[spaceId]);
4128 q = (e1[spaceId1] - a[spaceId1] - p * (b[spaceId1] - a[spaceId1])) / (c[spaceId1] - a[spaceId1]);
4129 } else {
4130 // aspaceId1 != bspaceId1 && aspaceId1 != cspaceId1 && aspaceId != bspaceId && aspaceId != cspaceId
4131 q = ((e1[spaceId1] - a[spaceId1]) * (b[spaceId] - a[spaceId])
4132 - (b[spaceId1] - a[spaceId1]) * (e1[spaceId] - a[spaceId]))
4133 / ((c[spaceId1] - a[spaceId1]) * (b[spaceId] - a[spaceId])
4134 - (b[spaceId1] - a[spaceId1]) * (c[spaceId] - a[spaceId]));
4135 p = (e1[spaceId] - a[spaceId] - q * (c[spaceId] - a[spaceId])) / (b[spaceId] - a[spaceId]);
4136 }
4137 }
4138 }
4139 }
4140
4141 if(p * q >= 0 || p * q < 0) {
4142 // compute s
4143 gamma = a[spaceId2] + p * (b[spaceId2] - a[spaceId2]) + q * (c[spaceId2] - a[spaceId2]);
4144 s = (gamma - e1[spaceId2]) / (e2[spaceId2] - e1[spaceId2]);
4145
4146 if(s < -epsilon || s > F1 + epsilon || p < -epsilon || q < -epsilon || (p + q) > F1 + epsilon) {
4147 } else {
4148 singleIntersectionPoint = true;
4149
4150 // cut point pP
4151 for(MInt g = 0; g < nDim; g++) {
4152 pP[g] = e1[g] + s * (e2[g] - e1[g]);
4153 temp[noReallyIntersectingNodes][g] = pP[g];
4154 }
4155
4156 if(noReallyIntersectingNodes == 0) {
4157 nodeList[noReallyIntersectingNodes] = nodeList[n];
4158 noReallyIntersectingNodes++;
4159 } else {
4160 for(MInt f = 0; f < noReallyIntersectingNodes; f++) {
4161 if((fabs(temp[f][0] - pP[0]) < epsilon) && (fabs(temp[f][1] - pP[1]) < epsilon)
4162 && (fabs(temp[f][2] - pP[2]) < epsilon)) {
4163 singleIntersectionPoint = false;
4164 break;
4165 }
4166 }
4167 if(singleIntersectionPoint) {
4168 nodeList[noReallyIntersectingNodes] = nodeList[n];
4169 noReallyIntersectingNodes++;
4170 }
4171 }
4172 }
4173 }
4174 }
4175 nodeList.resize(noReallyIntersectingNodes);
4176
4177 // free memory
4178 for(MInt k = 0; k < maxNoNodes; k++) {
4179 delete[] temp[k];
4180 temp[k] = nullptr;
4181 }
4182 delete[] temp;
4183 temp = nullptr;
4184
4185 delete[] e1;
4186 e1 = nullptr;
4187 delete[] e2;
4188 e2 = nullptr;
4189 delete[] a;
4190 a = nullptr;
4191 delete[] b;
4192 b = nullptr;
4193 delete[] c;
4194 c = nullptr;
4195 delete[] pP;
4196 pP = nullptr;
4197
4198
4199 return noReallyIntersectingNodes;
4200}

◆ getLineTriangleIntersection()

MBool Geometry3D::getLineTriangleIntersection ( const MFloat *const  p1,
const MFloat *const  p2,
const MFloat  radius,
const MFloat *const  v1,
const MFloat *const  v2,
const MFloat *const  v3,
MFloat intersection,
MFloat normal,
MFloat lambda2,
MFloat dist 
)
overridevirtual
Author
Andreas Lintermann
Date
08.01.2013

The algorithm consists of the following steps:

  1. Get the normal of the triangle:
    • this is done by taking the cross-product of the spanning edges
    • additionally normalize for the steps 2., 2.a, 2.b
      • non-normalizing caused a problem, for very small triangles
      • the denominator in the following case was very small
  2. Get the cutting-point by solving the plane-equation
    • solve \(\vec{n}\cdot\vec{p} = 0\) with \(\vec{p} = \vec{p}_t + r * \vec{l}\) for \(r\)
    • \(\vec{n}\) is the normal
    • \(\vec{p}\) is a point in the plane
    • \(\vec{p}_t\) is a point on the line (the transposed first point of the line)
    • \(\vec{l}\) is the line 2.a Check if line and triangle plane is parallel
    • ckeck if \(\vec{n}\cdot\vec{l}=0\)
    • if yes, proceed with 2.b, else with 3. 2.b Check in 2D if we have an intersection
    • ckeck if both points of the line are in the plane (the line can still be just parallel)
    • if not in plane then we are finished
    • else perform 2D-test:
      • for each triangle edge perform cut with line
      • return the distance, then we are finished
  3. Check if the intesection point is inside the triangle
    • do this by evaluating the barycentric coordinates
Parameters
[in]p1point 1 of the line
[in]p2point 2 of the line
[in]radiusthe radius of a particle
[in]v1vertex 1 of the triangle
[in]v2vertex 2 of the triangle
[in]v3vertex 3 of the triangle
[in]intersectionthe intersection point to be returned
[in]normalthe normal of the cutting triagle to be returned
[in]relativedistance to cutpoint
Returns
true if intersection is valid, false, otherwise

Reimplemented from Geometry< 3 >.

Definition at line 2765 of file geometry3d.cpp.

2767 {
2768 // TRACE();
2769
2770 std::array<MFloat, nDim> edge1{};
2771 std::array<MFloat, nDim> edge2{};
2772 std::array<MFloat, nDim> edge3{};
2773 std::array<MFloat, nDim> line{};
2774 std::array<MFloat, nDim> line_norm{};
2775 std::array<MFloat, nDim> normal_norm{};
2776 std::array<MFloat, nDim> trans_p1{};
2777 std::array<MFloat, nDim> trans_p2{};
2778 constexpr MFloat eps = 0.0000000000000001;
2779 constexpr MFloat eps2 = 0.00000001;
2780
2781 // 1. Get the normal on the triangle
2782 for(MInt d = 0; d < nDim; d++) {
2783 edge1[d] = v2[d] - v1[d];
2784 edge2[d] = v3[d] - v1[d];
2785 edge3[d] = v3[d] - v2[d];
2786 line[d] = p2[d] - p1[d];
2787
2788 trans_p1[d] = p1[d] - v1[d];
2789 trans_p2[d] = p2[d] - v1[d];
2790 }
2791
2792
2793 MFloat line_n_length = 0.0;
2794 for(MInt d = 0; d < nDim; d++) {
2795 line_n_length += line[d] * line[d];
2796 }
2797
2798 line_n_length = sqrt(line_n_length);
2799 const MFloat F1BLine_n_length = 1.0 / line_n_length;
2800
2801 if(radius > 0.0)
2802 for(MInt d = 0; d < nDim; d++) {
2803 line[d] = (line_n_length + radius) * line[d] * F1BLine_n_length;
2804 }
2805
2806 normal[0] = edge1[1] * edge2[2] - edge2[1] * edge1[2];
2807 normal[1] = edge1[2] * edge2[0] - edge2[2] * edge1[0];
2808 normal[2] = edge1[0] * edge2[1] - edge2[0] * edge1[1];
2809
2810 MFloat n_length_sq = 0.0;
2811 for(MInt d = 0; d < nDim; d++) {
2812 n_length_sq += normal[d] * normal[d];
2813 }
2814
2815 // Normalize the normal
2816 const MFloat n_length = sqrt(n_length_sq);
2817 const MFloat F1BN_length = 1.0 / n_length;
2818 for(MInt d = 0; d < nDim; d++) {
2819 normal_norm[d] = normal[d] * F1BN_length;
2820 line_norm[d] = line[d] * F1BLine_n_length;
2821 }
2822
2823 // 2. Get the cutting-point by solving the plane-equation
2824
2825 // 2.a be careful, the dot-product of the normal and the line can 0 (they are perpendicular)
2826 const MFloat denom = (normal_norm[0] * line_norm[0] + normal_norm[1] * line_norm[1] + normal_norm[2] * line_norm[2]);
2827
2828 // 2.b Check in 2D if we have an intersection
2829 if(fabs(denom) < eps) {
2830 // Check if the points are in the plane
2831 MFloat dot1 = trans_p1[0] * normal_norm[0] + trans_p1[1] * normal_norm[1] + trans_p1[2] * normal_norm[2];
2832 MFloat dot2 = trans_p2[0] * normal_norm[0] + trans_p2[1] * normal_norm[1] + trans_p2[2] * normal_norm[2];
2833 if(fabs(dot1) < eps && fabs(dot2) < eps) {
2834 // further testing
2835 MInt l_dim = 0;
2836 MFloat max = 0.0;
2837 for(MInt d = 0; d < nDim; d++) {
2838 if(normal_norm[d] > max) l_dim = d;
2839 }
2840
2841 const std::array<const MFloat*, 3> verts = {v1, v2, v3};
2842
2843 MFloat line2d[2] = {0.0, 0.0};
2844 MFloat pl_1[2] = {0.0, 0.0};
2845 for(MInt i = 0, j = 0; i < nDim; i++) {
2846 if(i != l_dim) {
2847 line2d[j] = p2[i] - p1[i];
2848 pl_1[j] = p1[i];
2849 j++;
2850 }
2851 }
2852
2853 MBool cut = false;
2854 MFloat shortest = 10000000000.0;
2855
2856 // for each triangle edge perform cut with line
2857 for(MInt d = 0; d < nDim; d++) {
2858 MInt next = (d + 1) % nDim;
2859 MFloat tri_edge[2] = {0.0, 0.0};
2860 MFloat tri_v1[2] = {0.0, 0.0};
2861
2862 for(MInt i = 0, j = 0; i < nDim; i++) {
2863 if(i != l_dim) {
2864 tri_edge[j] = verts[next][i] - verts[d][i];
2865 tri_v1[j] = verts[d][i];
2866 j++;
2867 }
2868 }
2869
2870 MFloat denom2 = tri_edge[1] * line2d[0];
2871 if(fabs(denom2) < eps) continue;
2872
2873 MFloat denom3 = 1.0 - (line2d[1] * tri_edge[0] / denom2);
2874 if(fabs(denom3) < eps) continue;
2875
2876 MFloat alpha =
2877 denom3 * (1.0 / line2d[0]) * (tri_v1[0] - pl_1[0] + (tri_edge[0] / tri_edge[1]) * (pl_1[1] - tri_v1[1]));
2878
2879 // we have a cut
2880 if(alpha <= 1.0 && alpha >= 0.0) {
2881 MFloat beta = pl_1[1] / tri_edge[1] + alpha * line2d[1] / tri_edge[1] - tri_v1[1] / tri_edge[1];
2882 if(beta <= 1.0 && beta >= 0.0) {
2883 MFloat l = sqrt(alpha * alpha * line2d[0] * line2d[0] + alpha * alpha * line2d[1] * line2d[1]);
2884 if(l < shortest) shortest = l;
2885 cut = true;
2886 continue;
2887 }
2888 }
2889
2890 // no cut
2891 else
2892 continue;
2893 }
2894
2895 if(cut) {
2896 *dist = shortest;
2897 return true;
2898 } else {
2899 *dist = 0.0;
2900 return false;
2901 }
2902
2903 } else {
2904 *dist = 0.0;
2905 return false;
2906 }
2907 }
2908
2909 const MFloat r =
2910 (-normal_norm[0] * trans_p1[0] - normal_norm[1] * trans_p1[1] - normal_norm[2] * trans_p1[2]) / denom;
2911
2912 // 3. Check if cut-point is inside the triangle
2913 std::array<MFloat, nDim> i_v1{};
2914 std::array<MFloat, nDim> i_v2{};
2915 std::array<MFloat, nDim> i_v3{};
2916
2917 for(MInt d = 0; d < nDim; d++) {
2918 intersection[d] = p1[d] + r * line_norm[d];
2919 i_v1[d] = intersection[d] - v2[d];
2920 i_v2[d] = intersection[d] - v3[d];
2921 i_v3[d] = intersection[d] - v1[d];
2922 }
2923
2924 *dist = r;
2925
2926 if(r >= 0.0)
2927 *lambda2 = r * F1BLine_n_length;
2928 else
2929 *lambda2 = 1.1;
2930
2931 // we are already finished if the cut-point has a larger distance than the second point
2932 if(fabs(*lambda2) > 1.0) return false;
2933
2934 std::array<MFloat, nDim> normal1;
2935 std::array<MFloat, nDim> normal2;
2936 std::array<MFloat, nDim> normal3;
2937
2938 normal1[0] = edge3[1] * i_v1[2] - i_v1[1] * edge3[2];
2939 normal1[1] = edge3[2] * i_v1[0] - i_v1[2] * edge3[0];
2940 normal1[2] = edge3[0] * i_v1[1] - i_v1[0] * edge3[1];
2941
2942 normal2[0] = -edge2[1] * i_v2[2] + i_v2[1] * edge2[2];
2943 normal2[1] = -edge2[2] * i_v2[0] + i_v2[2] * edge2[0];
2944 normal2[2] = -edge2[0] * i_v2[1] + i_v2[0] * edge2[1];
2945
2946 normal3[0] = edge1[1] * i_v3[2] - i_v3[1] * edge1[2];
2947 normal3[1] = edge1[2] * i_v3[0] - i_v3[2] * edge1[0];
2948 normal3[2] = edge1[0] * i_v3[1] - i_v3[0] * edge1[1];
2949
2950 MFloat alpha;
2951 MFloat beta;
2952 MFloat gamma;
2953 alpha = beta = gamma = 0.0;
2954
2955 for(MInt d = 0; d < nDim; d++) {
2956 alpha += normal[d] * normal1[d];
2957 beta += normal[d] * normal2[d];
2958 gamma += normal[d] * normal3[d];
2959 }
2960
2961 alpha /= n_length_sq;
2962 beta /= n_length_sq;
2963 gamma /= n_length_sq;
2964
2965 // check for inside
2966 if((alpha + beta + gamma <= 1.0 + eps2) && (alpha + beta + gamma >= 1.0 - eps2))
2967 if(alpha >= 0 && beta >= 0 && gamma >= 0)
2968 return true;
2969 else
2970 return false;
2971 else
2972 return false;
2973}

◆ getLineTriangleIntersectionSimple()

MBool Geometry3D::getLineTriangleIntersectionSimple ( MFloat p1,
MFloat p2,
MFloat v1,
MFloat v2,
MFloat v3 
)
overridevirtual
Author
Andreas Lintermann
Date
25.01.2013

This is the simple case of getLineTriangleIntersection(...).

Parameters
[in]p1point 1 of the line
[in]p2point 2 of the line
[in]v1vertex 1 of the triangle
[in]v2vertex 2 of the triangle
[in]v3vertex 3 of the triangle
Returns
true if intersection is valid, false, otherwise

Reimplemented from Geometry< 3 >.

Definition at line 2678 of file geometry3d.cpp.

2678 {
2679 // TRACE();
2680
2681 MFloat radius = 0.0;
2682 MFloat intersection[3] = {0.0, 0.0, 0.0};
2683 MFloat normal[3] = {0.0, 0.0, 0.0};
2684 MFloat lambda2 = NAN;
2685 MFloat dist = 0.0;
2686
2687 return (getLineTriangleIntersection(p1, p2, radius, v1, v2, v3, intersection, normal, &lambda2, &dist));
2688}
MBool getLineTriangleIntersection(const MFloat *const p1, const MFloat *const p2, const MFloat radius, const MFloat *const v1, const MFloat *const v2, const MFloat *const v3, MFloat *intersection, MFloat *normal, MFloat *lambda2, MFloat *dist) override
This function determines if a line crosses a triangle.

◆ getLineTriangleIntersectionSimpleDistance()

MBool Geometry3D::getLineTriangleIntersectionSimpleDistance ( MFloat p1,
MFloat p2,
MFloat v1,
MFloat v2,
MFloat v3,
MFloat dist 
)
overridevirtual
Author
Andreas Lintermann
Date
25.01.2013

This is the simple case of getLineTriangleIntersection(...), additionally returns the distance.

Parameters
[in]p1point 1 of the line
[in]p2point 2 of the line
[in]v1vertex 1 of the triangle
[in]v2vertex 2 of the triangle
[in]v3vertex 3 of the triangle
[in]distthe distance to the triangle
Returns
true if intersection is valid, false, otherwise

Reimplemented from Geometry< 3 >.

Definition at line 2708 of file geometry3d.cpp.

2709 {
2710 // TRACE();
2711
2712 MFloat radius = 0.0;
2713 MFloat intersection[3] = {0.0, 0.0, 0.0};
2714 MFloat normal[3] = {0.0, 0.0, 0.0};
2715 MFloat lambda2 = NAN;
2716
2717 return (getLineTriangleIntersection(p1, p2, radius, v1, v2, v3, intersection, normal, &lambda2, dist));
2718}

◆ getSphereIntersectionMBElements()

MInt Geometry3D::getSphereIntersectionMBElements ( MFloat P,
MFloat  radius,
std::vector< MInt > &  nodeList 
)
overridevirtual

Reimplemented from Geometry< 3 >.

Definition at line 3914 of file geometry3d.cpp.

3914 {
3915 // TRACE();
3916
3917 otherCalls++;
3918
3919 MInt noReallyIntersectingNodes = 0;
3920
3921 // compute minimum target region that contains the sphere:
3922 MFloat target[6] = {numeric_limits<MFloat>::max(), numeric_limits<MFloat>::max(),
3923 numeric_limits<MFloat>::max(), numeric_limits<MFloat>::max(),
3924 numeric_limits<MFloat>::max(), numeric_limits<MFloat>::max()}; // gcc 4.8.2 maybe uninitialized
3925 MFloat enlargeFactor = 1.05;
3926 for(MInt i = 0; i < nDim; i++) {
3927 target[i] = P[i] - radius * enlargeFactor;
3928 target[i + nDim] = P[i] + radius * enlargeFactor;
3929 }
3930
3931 // fetch all possibly intersecting triangles in this region:
3932 m_adt->retrieveNodesMBElements(target, nodeList);
3933 const MInt noNodes = nodeList.size();
3934
3935 MFloat A[3] = {numeric_limits<MFloat>::max(), numeric_limits<MFloat>::max(),
3936 numeric_limits<MFloat>::max()}; // gcc 4.8.2 maybe uninitialized
3937 MFloat B[3] = {numeric_limits<MFloat>::max(), numeric_limits<MFloat>::max(),
3938 numeric_limits<MFloat>::max()}; // gcc 4.8.2 maybe uninitialized
3939 MFloat C[3] = {numeric_limits<MFloat>::max(), numeric_limits<MFloat>::max(),
3940 numeric_limits<MFloat>::max()}; // gcc 4.8.2 maybe uninitialized
3941 MFloat AB[3] = {numeric_limits<MFloat>::max(), numeric_limits<MFloat>::max(),
3942 numeric_limits<MFloat>::max()}; // gcc 4.8.2 maybe uninitialized
3943 MFloat BC[3] = {numeric_limits<MFloat>::max(), numeric_limits<MFloat>::max(),
3944 numeric_limits<MFloat>::max()}; // gcc 4.8.2 maybe uninitialized
3945 MFloat CA[3] = {numeric_limits<MFloat>::max(), numeric_limits<MFloat>::max(),
3946 numeric_limits<MFloat>::max()}; // gcc 4.8.2 maybe uninitialized
3947 MFloat V[3], Q1[3], Q2[3], Q3[3], QC[3], QA[3], QB[3];
3948
3949 // loop over all elements
3950 for(MInt n = 0; n < noNodes; n++) {
3951 // store the vertices of the current element<3> in A, B, C:
3952 for(MInt i = 0; i < nDim; i++) {
3953 A[i] = mbelements[nodeList[n]].m_vertices[0][i];
3954 B[i] = mbelements[nodeList[n]].m_vertices[1][i];
3955 C[i] = mbelements[nodeList[n]].m_vertices[2][i];
3956 }
3957
3958 // compute separation algorithm from http://realtimecollisiondetection.net/blog/?p=103:
3959 for(MInt i = 0; i < nDim; i++) {
3960 A[i] = A[i] - P[i];
3961 B[i] = B[i] - P[i];
3962 C[i] = C[i] - P[i];
3963 AB[i] = B[i] - A[i];
3964 BC[i] = C[i] - B[i];
3965 CA[i] = A[i] - C[i];
3966 }
3967 V[0] = -AB[1] * CA[2] + AB[2] * CA[1];
3968 V[1] = -AB[2] * CA[0] + AB[0] * CA[2];
3969 V[2] = -AB[0] * CA[1] + AB[1] * CA[0];
3970 MFloat rr = radius * radius;
3971 MFloat d = F0;
3972 MFloat e = F0;
3973 MFloat aa = F0;
3974 MFloat ab = F0;
3975 MFloat ac = F0;
3976 MFloat bb = F0;
3977 MFloat bc = F0;
3978 MFloat cc = F0;
3979 MFloat e1 = F0;
3980 MFloat e2 = F0;
3981 MFloat e3 = F0;
3982 for(MInt i = 0; i < nDim; i++) {
3983 d += A[i] * V[i];
3984 e += V[i] * V[i];
3985 aa += A[i] * A[i];
3986 ab += A[i] * B[i];
3987 ac += A[i] * C[i];
3988 bb += B[i] * B[i];
3989 bc += B[i] * C[i];
3990 cc += C[i] * C[i];
3991 e1 += AB[i] * AB[i];
3992 e2 += BC[i] * BC[i];
3993 e3 += CA[i] * CA[i];
3994 }
3995 MBool sep1 = d * d > rr * e;
3996 MBool sep2 = (aa > rr) && (ab > aa) && (ac > aa);
3997 MBool sep3 = (bb > rr) && (ab > bb) && (bc > bb);
3998 MBool sep4 = (cc > rr) && (ac > cc) && (bc > cc);
3999 MFloat d1 = ab - aa;
4000 MFloat d2 = bc - bb;
4001 MFloat d3 = ac - cc;
4002 MFloat qq1 = F0;
4003 MFloat qq2 = F0;
4004 MFloat qq3 = F0;
4005 MFloat qq1c = F0;
4006 MFloat qq2a = F0;
4007 MFloat qq3b = F0;
4008 for(MInt i = 0; i < nDim; i++) {
4009 Q1[i] = A[i] * e1 - d1 * AB[i];
4010 Q2[i] = B[i] * e2 - d2 * BC[i];
4011 Q3[i] = C[i] * e3 - d3 * CA[i];
4012 QC[i] = C[i] * e1 - Q1[i];
4013 QA[i] = A[i] * e2 - Q2[i];
4014 QB[i] = B[i] * e3 - Q3[i];
4015 qq1 += Q1[i] * Q1[i];
4016 qq2 += Q2[i] * Q2[i];
4017 qq3 += Q3[i] * Q3[i];
4018 qq1c += Q1[i] * QC[i];
4019 qq2a += Q2[i] * QA[i];
4020 qq3b += Q3[i] * QB[i];
4021 }
4022 MBool sep5 = (qq1 > rr * e1 * e1) && (qq1c > 0);
4023 MBool sep6 = (qq2 > rr * e2 * e2) && (qq2a > 0);
4024 MBool sep7 = (qq3 > rr * e3 * e3) && (qq3b > 0);
4025
4026 MBool separated = sep1 || sep2 || sep3 || sep4 || sep5 || sep6 || sep7;
4027
4028 if(!separated) {
4029 nodeList[noReallyIntersectingNodes] = nodeList[n];
4030 noReallyIntersectingNodes++;
4031 }
4032 }
4033 nodeList.resize(noReallyIntersectingNodes);
4034
4035 return noReallyIntersectingNodes;
4036}

◆ GetUniqueSegmentEdges()

vector< pair< MFloat *, MFloat * > > Geometry3D::GetUniqueSegmentEdges ( MInt  segmentId)
inlinevirtual
Author
Andreas Lintermann
Date
17.09.2015

param[in] segmentId the id of the segment (only for serial geometry) return the edges of the segment

Definition at line 4580 of file geometry3d.cpp.

4580 {
4581 TRACE();
4582
4583 vector<pair<MFloat*, MFloat*>> edges;
4584
4585 for(MInt i = m_segmentOffsetsWithoutMB[segmentId]; i < m_segmentOffsetsWithoutMB[segmentId + 1]; i++) {
4586 // this runs over all edges of the triangle
4587 for(MInt e = 0; e < nDim; e++) {
4588 MFloat* p1 = elements[i].m_vertices[e];
4589 MFloat* p2 = elements[i].m_vertices[(e + 1) % nDim];
4590
4591 // if not in yet, then add
4592 MInt del;
4593 MBool in = isEdgeAlreadyInCollection(edges, p1, p2, &del);
4594 if(!in)
4595 edges.emplace_back(p1, p2);
4596 else {
4597 auto it = edges.begin() + del;
4598 edges.erase(it);
4599 }
4600 }
4601 }
4602
4603 return edges;
4604}
MBool isEdgeAlreadyInCollection(std::vector< std::pair< MFloat *, MFloat * > > tmp_edges, MFloat *p1, MFloat *p2, MInt *pos) override
Checks if an edge given by two points is in a vector.

◆ GetUniqueSegmentEdgesParGeom()

vector< pair< MFloat *, MFloat * > > Geometry3D::GetUniqueSegmentEdgesParGeom ( MFloat tri_vx,
MInt keepOffsets,
MInt  size 
)
inlinevirtual
Author
Andreas Lintermann
Date
17.09.2015

The vertices are proviced by an array (see parameters)

param[in] tri_vx the triangles in one array (v00,v01,v02,v10,v11,v12,v20,v21,v22,...) param[in] keepOffsets only consider the triangles at the given offsets param[in] size the number of triangles in the input array return the edges of the segment

Definition at line 4620 of file geometry3d.cpp.

4621 {
4622 TRACE();
4623
4624 vector<pair<MFloat*, MFloat*>> edges;
4625
4626 for(MInt i = 0; i < size; i++) {
4627 MInt off = keepOffsets[i];
4628
4629 // this runs over all edges of the triangle
4630 for(MInt k = 0; k < nDim; k++) {
4631 MFloat* p1 = &tri_vx[off + k * nDim];
4632 MFloat* p2 = &tri_vx[off + (((k + 1) * nDim) % (nDim * nDim))];
4633
4634
4635 MInt del;
4636 MBool in = isEdgeAlreadyInCollection(edges, p1, p2, &del);
4637 if(!in)
4638 edges.emplace_back(p1, p2);
4639 else {
4640 auto it = edges.begin() + del;
4641 edges.erase(it);
4642 }
4643 }
4644 }
4645
4646 return edges;
4647}

◆ is_big_endian()

MInt Geometry3D::is_big_endian ( void  )
protectedvirtual
Author
Andreas Lintermann
Date
22.07.2015
Returns
if the system is big endian or not

Definition at line 608 of file geometry3d.cpp.

608 {
609 union {
610 uint32_t i;
611 char c[4];
612 } bint = {0x01020304};
613
614 return static_cast<MInt>(bint.c[0] == 1);
615}

◆ isEdgeAlreadyInCollection()

MBool Geometry3D::isEdgeAlreadyInCollection ( std::vector< std::pair< MFloat *, MFloat * > >  tmp_edges,
MFloat p1,
MFloat p2,
MInt pos 
)
inlineoverridevirtual
Author
Andreas Lintermann
Date
17.09.2015
Parameters
[in]edgesthe vector containing the collection of edges
[in]p1point 1 of the edge
[in]p2point 2 of the edge return if the edge is already contained

Reimplemented from Geometry< 3 >.

Definition at line 4660 of file geometry3d.cpp.

4661 {
4662 TRACE();
4663
4664 MInt pos = 0;
4665 for(auto& edge : edges) {
4666 MBool pt1_in = true;
4667 MBool pt2_in = true;
4668
4669 MFloat* pcol1 = edge.first;
4670 MFloat* pcol2 = edge.second;
4671
4672 for(MInt d = 0; d < nDim; d++)
4673 pt1_in = pt1_in && approx(p1[d], pcol1[d], MFloatEps);
4674
4675 if(!pt1_in) {
4676 pt1_in = true;
4677 for(MInt d = 0; d < nDim; d++)
4678 pt1_in = pt1_in && approx(p1[d], pcol2[d], MFloatEps);
4679 }
4680
4681 for(MInt d = 0; d < nDim; d++)
4682 pt2_in = pt2_in && approx(p2[d], pcol1[d], MFloatEps);
4683
4684 if(!pt2_in) {
4685 pt2_in = true;
4686 for(MInt d = 0; d < nDim; d++)
4687 pt2_in = pt2_in && approx(p2[d], pcol2[d], MFloatEps);
4688 }
4689
4690 if(pt1_in && pt2_in) {
4691 *to_delete = pos;
4692 return true;
4693 }
4694 pos++;
4695 }
4696 return false;
4697}

◆ logStatistics()

void Geometry3D::logStatistics ( )
overridevirtual

Reimplemented from Geometry< 3 >.

Definition at line 4877 of file geometry3d.cpp.

4877 {
4878 TRACE();
4879
4880 m_log << "******************** Geometry3D statistics ********************" << endl;
4881 m_log << " Calls to getIntersectionElements: " << getIECallCounter << endl;
4882 m_log << " Comm from getIntersectionElements: " << getIECommCounter << endl;
4883 m_log << " Calls to getIntersectionElementsTetraeder: " << getIETCallCounter << endl;
4884 m_log << " Calls to getLineIntersectionElements2: " << m_getLIE2CallCounter << endl;
4885 m_log << " Comm from getLineIntersectionElements2: " << getLIE2CommCounter << endl;
4886 m_log << " Calls to edgeTriangleIntersection: " << edgeTICallCounter << endl;
4887 m_log << " Other calls in geometry3d: " << otherCalls << endl;
4888 m_log << "***************************************************************" << endl;
4889}

◆ MoveAllMBElementVertex()

void Geometry3D::MoveAllMBElementVertex ( MFloat dx)
overridevirtual

Reimplemented from Geometry< 3 >.

Definition at line 4202 of file geometry3d.cpp.

4202 {
4203 TRACE();
4204
4205 otherCalls++;
4206
4207
4208 for(MInt e = 0; e < m_noMBElements; e++) {
4209 for(MInt j = 0; j < nDim; j++) {
4210 for(MInt i = 0; i < nDim; i++) {
4211 mbelements[e].m_vertices[j][i] += dx[i];
4212 }
4213 }
4214 }
4215}

◆ MoveMBElementVertex()

void Geometry3D::MoveMBElementVertex ( MInt  e,
MInt  v,
MFloat dx 
)
overridevirtual

Reimplemented from Geometry< 3 >.

Definition at line 4217 of file geometry3d.cpp.

4217 {
4218 TRACE();
4219
4220 otherCalls++;
4221
4222
4223 for(MInt i = 0; i < nDim; i++) {
4224 mbelements[e].m_vertices[v][i] += dx[i];
4225 }
4226}

◆ printMemoryUsage()

void Geometry3D::printMemoryUsage ( )
protected
Author
Andreas Lintermann
Date
05.10.2015

Definition at line 328 of file geometry3d.cpp.

328 {
329 TRACE();
330
331 m_log << " + Used memmory for collectors: "
332 << ((MFloat)m_elements->memoryUseage() + (MFloat)m_adt->memoryUsage()) / 1024.0 / 1024.0
333 + (m_GFieldInitFromSTL ? ((MFloat)m_elements->memoryUseage() / 1024.0 / 1024.0) : 0.0)
334 << " MB" << endl;
335 m_log << " * triangles: " << (MFloat)m_elements->memoryUseage() / 1024.0 / 1024.0 << " MB" << endl;
337 m_log << " * mb triangles: " << (MFloat)m_mbelements->memoryUseage() / 1024.0 / 1024.0 << " MB" << endl;
338 m_log << " * adt tree: " << (MFloat)m_adt->memoryUsage() / 1024.0 / 1024.0 << " MB" << endl;
339}

◆ readSegments()

void Geometry3D::readSegments ( )
overrideprotectedvirtual
Author
Rainhill Freitas, Andreas Lintermann
Date
20.07.2015

Calls the according function to read the geometry.

Reimplemented from Geometry< 3 >.

Definition at line 1338 of file geometry3d.cpp.

1338 {
1339 TRACE();
1340
1341 NEW_SUB_TIMER(t_readGeometry, "read geometry", m_t_geometryAll);
1342 m_t_readGeometry = t_readGeometry;
1343 g_tc_geometry.emplace_back("read geometry", m_t_readGeometry);
1344 RECORD_TIMER_START(t_readGeometry);
1345
1346 otherCalls++;
1347
1348 // check binary or ascii
1349 m_geomFileType = "ASCII";
1350 if(geometryContext().propertyExists("geomFileType", 0))
1351 m_geomFileType = *(geometryContext().getProperty("geomFileType", 0)->asString(0));
1352
1353 // check if we need to count the triangles
1354 m_noAllTriangles = 0;
1355 if(geometryContext().propertyExists("noAllTriangles", 0))
1356 m_noAllTriangles = *(geometryContext().getProperty("noAllTriangles", 0)->asInt(0));
1357
1358 string tmp;
1359
1360 // This loop only counts all elements of all segments
1361 for(MInt i = 0; i <= m_noSegments; i++) {
1362 m_segmentOffsets[i] = 0;
1364 }
1365
1366 mAlloc(m_ownSegmentId, m_noSegments, "m_ownSegmentId", true, AT_);
1367
1368 m_log << " + Geometry configuration:" << endl;
1369 m_log << " - File type is set to: " << (m_parallelGeometry ? "NETCDF" : m_geomFileType) << endl;
1370 m_log << " - endianess: " << (is_big_endian() ? "big endian" : "little endian") << endl;
1371 m_log << " - reading method: " << (m_parallelGeometry ? "parallel" : "serial") << endl << endl;
1372
1373 // trust me, this is just the definition, init will be performed in the following funtions
1374 Collector<element<3>>* m_allelements = nullptr;
1375
1377 m_allelements = readSegmentsParallel();
1378 } else {
1379 m_allelements = readSegmentsSerial();
1380 }
1381
1385 }
1386
1387 MInt initSize = m_noElements;
1388
1389 // add 15% overhead
1390 /*
1391 if(m_parallelGeometry)
1392 initSize *= m_parGeomMemFactor;
1393 */
1394
1395 m_elements = new Collector<element<nDim>>(initSize, nDim, 0);
1396 elements = m_elements->a;
1398
1399 MInt mbelem_counter = 0, elem_counter = 0;
1400 MBool mbElem = false;
1401 element<3>* allelements = m_allelements->a;
1402
1403 for(MInt allelem_counter = 0; allelem_counter < m_allelements->size(); allelem_counter++) {
1405 for(MInt id = 0; id < m_noLevelSetIntfBndIds; id++) {
1406 if(allelements[allelem_counter].m_bndCndId == m_levelSetIntfBndIds[id]) {
1407 mbElem = true;
1408 break;
1409 }
1410 }
1411
1412 // LevelSet Moving boundary elements
1413 if(mbElem) {
1414 m_mbelements->append();
1415
1416 for(MInt j = 0; j < 3; j++) {
1417 mbelements[mbelem_counter].m_normal[j] = allelements[allelem_counter].m_normal[j];
1418 for(MInt i = 0; i < 3; i++) {
1419 mbelements[mbelem_counter].m_vertices[j][i] = allelements[allelem_counter].m_vertices[j][i];
1420 }
1421 }
1422
1423 mbelements[mbelem_counter].boundingBox();
1424 mbelements[mbelem_counter].m_bndCndId = allelements[allelem_counter].m_bndCndId;
1425 mbelements[mbelem_counter].m_segmentId = allelements[allelem_counter].m_segmentId;
1426 mbelements[mbelem_counter].m_originalId = allelements[allelem_counter].m_originalId;
1427 mbelem_counter++;
1428 mbElem = false;
1429 }
1430
1431 // Non movable elements
1432 else {
1433 m_elements->append();
1434
1435 for(MInt j = 0; j < 3; j++) {
1436 elements[elem_counter].m_normal[j] = allelements[allelem_counter].m_normal[j];
1437 for(MInt i = 0; i < 3; i++) {
1438 elements[elem_counter].m_vertices[j][i] = allelements[allelem_counter].m_vertices[j][i];
1439 }
1440 }
1441 elements[elem_counter].boundingBox();
1442 elements[elem_counter].m_bndCndId = allelements[allelem_counter].m_bndCndId;
1443 elements[elem_counter].m_segmentId = allelements[allelem_counter].m_segmentId;
1444 elements[elem_counter].m_originalId = allelements[allelem_counter].m_originalId;
1445 elem_counter++;
1446 }
1447 } else {
1448 // LevelSet Moving boundary elements
1449 if(m_GFieldInitFromSTL && (m_levelSetIntfBndId == allelements[allelem_counter].m_bndCndId)) {
1450 m_mbelements->append();
1451
1452 for(MInt j = 0; j < 3; j++) {
1453 mbelements[mbelem_counter].m_normal[j] = allelements[allelem_counter].m_normal[j];
1454 for(MInt i = 0; i < 3; i++) {
1455 mbelements[mbelem_counter].m_vertices[j][i] = allelements[allelem_counter].m_vertices[j][i];
1456 }
1457 }
1458 mbelements[mbelem_counter].boundingBox();
1459 mbelements[mbelem_counter].m_bndCndId = allelements[allelem_counter].m_bndCndId;
1460 mbelements[mbelem_counter].m_segmentId = allelements[allelem_counter].m_segmentId;
1461 mbelements[mbelem_counter].m_originalId = allelements[allelem_counter].m_originalId;
1462 mbelem_counter++;
1463 } else { // Non movable elements
1464
1465 m_elements->append();
1466
1467 for(MInt j = 0; j < 3; j++) {
1468 elements[elem_counter].m_normal[j] = allelements[allelem_counter].m_normal[j];
1469 for(MInt i = 0; i < 3; i++)
1470 elements[elem_counter].m_vertices[j][i] = allelements[allelem_counter].m_vertices[j][i];
1471 }
1472 elements[elem_counter].boundingBox();
1473 elements[elem_counter].m_bndCndId = allelements[allelem_counter].m_bndCndId;
1474 elements[elem_counter].m_segmentId = allelements[allelem_counter].m_segmentId;
1475 elements[elem_counter].m_originalId = allelements[allelem_counter].m_originalId;
1476
1477 elem_counter++;
1478 }
1479 }
1480 }
1481
1482 delete m_allelements;
1483
1484 RECORD_TIMER_STOP(t_readGeometry);
1485
1486 NEW_SUB_TIMER(t_calcBndBox, "calculating bounding box", m_t_geometryAll);
1487 g_tc_geometry.emplace_back("calculating bounding box", t_calcBndBox);
1488 RECORD_TIMER_START(t_calcBndBox);
1489
1491 RECORD_TIMER_STOP(t_calcBndBox);
1492
1493 // update m_haloElementOffset
1495
1497 writeParallelGeometryVTK("readSeg");
1498 }
1499}
void mAlloc(T *&a, const MLong N, const MString &objectName, MString function)
allocates memory for one-dimensional array 'a' of size N
Definition: alloc.h:173
virtual Collector< element< 3 > > * readSegmentsParallel()
virtual Collector< element< 3 > > * readSegmentsSerial()
reads the segments in serial
Definition: geometry3d.cpp:855
MInt m_noAllTriangles
Definition: geometry3d.h:123
virtual MInt is_big_endian()
determines the CPU type big or little endian
Definition: geometry3d.cpp:608
MInt m_t_geometryAll
Definition: geometry3d.h:138
MInt m_levelSetIntfBndId
Definition: geometry3d.h:114
void writeParallelGeometryVTK(MString filename) override
Write the current geometry to a VTK file for parallel computation.
MInt m_noLevelSetIntfBndIds
Definition: geometry3d.h:116
MString m_geomFileType
Definition: geometry3d.h:121
MInt * m_levelSetIntfBndIds
Definition: geometry3d.h:115
MInt m_t_readGeometry
Definition: geometry3d.h:139
MBool propertyExists(MString name, MInt solver)
GeometryProperty * getProperty(const MString &name, MInt segment)
MFloat ** m_vertices
MBool m_flowSolver
Definition: geometry.h:201
void setHaloElementOffset(MInt off)
Definition: geometry.h:51
GeometryContext & geometryContext()
Definition: geometry.h:48
MBool m_debugParGeom
Definition: geometry.h:229
std::vector< std::pair< MString, MInt > > g_tc_geometry

◆ readSegmentsParallel()

virtual Collector< element< 3 > > * Geometry3D::readSegmentsParallel ( )
inlineprotectedvirtual

◆ readSegmentsSerial()

Collector< element< 3 > > * Geometry3D::readSegmentsSerial ( )
inlineprotectedvirtual
Author
Andreas Lintermann
Date
17.09.2015

Iterates over all segments in the geometry file and first counts the number of elements to be read. Then allocates the according memory and fills the geometry from the infomation in file. Depending on the file type of the geomtry a different method is used for counting an reading.

Definition at line 855 of file geometry3d.cpp.

855 {
856 TRACE();
857
858 NEW_SUB_TIMER(t_countTriangles, "count triangles", m_t_readGeometry);
859 g_tc_geometry.emplace_back("count triangles", t_countTriangles);
860 RECORD_TIMER_START(t_countTriangles);
861
862 if(domainId() == 0) { // Count segments only on rank 0 and broadcast total count
863 if(m_noAllTriangles == 0) {
864 MInt segmentId = 0;
865 for(m_bodyIt = m_bodyMap.begin(); m_bodyIt != m_bodyMap.end(); m_bodyIt++) {
866 // Do not create default body!
867 if(m_bodyIt->second->name != "default") {
868 for(MInt i = 0; i < m_bodyIt->second->noSegments; i++) {
869 stringstream fileName;
870 fileName << *geometryContext().getProperty("filename", segmentId)->asString();
871
872 if(geometryContext().noPropertySegments("filename") == 1 && geometryContext().getNoSegments() > 1
873 && (m_bodyIt->second->noSegments > 1 || m_bodyMap.size() > 1)) {
874 fileName << "." << segmentId;
875 }
876
877 m_log << " - file: " << fileName.str() << endl;
878
879 MInt noElements = 0;
880 switch(string2enum(m_geomFileType)) {
881 case ASCII:
882 countSegmentTrianglesASCII(fileName.str(), &noElements);
883 break;
884 case BINARY:
885 countSegmentTrianglesBINARY(fileName.str(), &noElements);
886 break;
887 case NETCDF:
888 countSegmentTrianglesNETCDF(fileName.str(), &noElements, MPI_COMM_SELF);
889 break;
890 default:
891 break;
892 }
893
894 m_log << " * no. triangles: " << noElements << endl;
895
896 m_noElements += noElements;
897 segmentId++;
898 }
899 }
900 }
901
902 } else {
904 }
905 }
906 MPI_Bcast(&m_noElements, 1, MPI_INT, 0, mpiComm(), AT_, "m_noElements");
907 RECORD_TIMER_STOP(t_countTriangles);
908
909 m_log << " - total no. triangles: " << m_noElements << endl << endl;
910 m_log << " + Reading segments ..." << endl;
911
912 NEW_SUB_TIMER(t_readTriangles, "read triangles", m_t_readGeometry);
913 g_tc_geometry.emplace_back("read triangles", t_readTriangles);
914 RECORD_TIMER_START(t_readTriangles);
915
916 auto* m_allelements = new Collector<element<nDim>>(m_noElements, nDim, 0);
917 // Read segments only on rank 0 and communicate (if mode is not disabled)
919 vector<MInt> allBCs;
920 MInt segmentId = 0;
921 MInt counter = 0;
922
923 // This loop reads all elements from all segments
924 for(m_bodyIt = m_bodyMap.begin(); m_bodyIt != m_bodyMap.end(); m_bodyIt++) {
925 // Do not create default body!
926 if(m_bodyIt->second->name != "default") {
927 for(MInt index = 0; index < m_bodyIt->second->noSegments; index++) {
928 stringstream fileName;
929 fileName << *geometryContext().getProperty("filename", segmentId)->asString();
930
931 if(geometryContext().noPropertySegments("filename") == 1 && geometryContext().getNoSegments() > 1
932 && (m_bodyIt->second->noSegments > 1 || m_bodyMap.size() > 1)) {
933 fileName << "." << segmentId;
934 }
935 MInt bndCndId = *geometryContext().getProperty("BC", segmentId)->asInt();
936 allBCs.push_back(bndCndId);
937
938 m_log << " - file: " << fileName.str() << endl;
939
940 switch(string2enum(m_geomFileType)) {
941 case ASCII:
942 readSegmentTrianglesASCII(fileName.str(), m_allelements, bndCndId, segmentId, &counter);
943 break;
944 case BINARY:
945 if(is_big_endian() != 0)
946 readSegmentTrianglesBINARY_BE(fileName.str(), m_allelements, bndCndId, segmentId, &counter);
947 else
948 readSegmentTrianglesBINARY_LE(fileName.str(), m_allelements, bndCndId, segmentId, &counter);
949 break;
950 case NETCDF: {
951 const MPI_Comm commSelf = MPI_COMM_SELF;
952 const MPI_Comm comm = (m_communicateSegmentsSerial) ? commSelf : mpiComm();
953 readSegmentTrianglesNETCDF(fileName.str(), m_allelements, bndCndId, segmentId, &counter, comm);
954 break;
955 }
956 default:
957 break;
958 }
959
960 segmentId++;
961 m_segmentOffsets[segmentId] = counter;
962 m_segmentOffsetsWithoutMB[segmentId] = m_segmentOffsetsWithoutMB[segmentId - 1]
963 + (m_segmentOffsets[segmentId] - m_segmentOffsets[segmentId - 1]);
964 if(m_noLevelSetIntfBndIds > 0) {
965 for(MInt i = 0; i < m_noLevelSetIntfBndIds; i++) {
966 if(bndCndId == m_levelSetIntfBndIds[i])
967 m_segmentOffsetsWithoutMB[segmentId] = m_segmentOffsetsWithoutMB[segmentId - 1];
968 }
969 }
970 }
971 }
972 }
973 m_log << endl;
974
975 m_noAllBCs = allBCs.size();
976 mAlloc(m_allBCs, m_noAllBCs, "m_allBCs", 0, AT_);
977 for(MInt i = 0; i < m_noAllBCs; i++) {
978 m_allBCs[i] = allBCs[i];
979 }
980 }
981
982 // Broadcast geometry information
984 MFloatScratchSpace normalsBuffer(3 * m_noElements, AT_, "normalsBuffer");
985 MFloatScratchSpace verticesBuffer(9 * m_noElements, AT_, "verticesBuffer");
986 MIntScratchSpace idsBuffer(3 * m_noElements, AT_, "idsBuffer");
987 // Fill buffers on rank 0 and broadcast
988 if(domainId() == 0) {
989 for(MInt i = 0; i < m_noElements; i++) {
990 idsBuffer[i] = m_allelements->a[i].m_bndCndId;
991 idsBuffer[m_noElements + i] = m_allelements->a[i].m_segmentId;
992 idsBuffer[(2 * m_noElements) + i] = m_allelements->a[i].m_originalId;
993 for(MInt j = 0; j < nDim; j++) {
994 normalsBuffer[(i * nDim) + j] = m_allelements->a[i].m_normal[j];
995 for(MInt k = 0; k < nDim; k++) {
996 verticesBuffer[(i * 9) + (j * nDim) + k] = m_allelements->a[i].m_vertices[j][k];
997 }
998 }
999 }
1000 }
1001 MPI_Bcast(normalsBuffer.getPointer(), 3 * m_noElements, maia::type_traits<MFloat>::mpiType(), 0, mpiComm(), AT_,
1002 "elemNormals");
1003 MPI_Bcast(verticesBuffer.getPointer(), 9 * m_noElements, maia::type_traits<MFloat>::mpiType(), 0, mpiComm(), AT_,
1004 "elemVertices");
1005 MPI_Bcast(idsBuffer.getPointer(), 3 * m_noElements, maia::type_traits<MInt>::mpiType(), 0, mpiComm(), AT_,
1006 "elemIds");
1007
1008 // Assemble geometry information from buffers
1009 if(domainId() != 0) {
1010 for(MInt i = 0; i < m_noElements; i++) {
1011 m_allelements->append();
1012 for(MInt j = 0; j < nDim; j++) {
1013 m_allelements->a[i].m_normal[j] = normalsBuffer[(i * nDim) + j];
1014 for(MInt k = 0; k < nDim; k++) {
1015 m_allelements->a[i].m_vertices[j][k] = verticesBuffer[(i * 9) + (j * nDim) + k];
1016 }
1017 }
1018 m_allelements->a[i].boundingBox();
1019 m_allelements->a[i].m_bndCndId = idsBuffer[i];
1020 m_allelements->a[i].m_segmentId = idsBuffer[m_noElements + i];
1021 m_allelements->a[i].m_originalId = idsBuffer[(2 * m_noElements) + i];
1022 }
1023 }
1024
1025 // Communicate remaining info from rank 0
1026 MPI_Bcast(&m_noMBElements, 1, maia::type_traits<MInt>::mpiType(), 0, mpiComm(), AT_, "m_noMBElements");
1028 "m_segmentOffsets");
1030 mpiComm(), AT_, "m_segmentOffsetsWithoutMB");
1031 MPI_Bcast(&m_noAllBCs, 1, maia::type_traits<MInt>::mpiType(), 0, mpiComm(), AT_, "m_noAllBCs");
1032 if(domainId() != 0) {
1033 mAlloc(m_allBCs, m_noAllBCs, "m_allBCs", 0, AT_);
1034 }
1036 }
1037
1038 RECORD_TIMER_STOP(t_readTriangles);
1039 return m_allelements;
1040}
virtual void readSegmentTrianglesBINARY_BE(MString fileName, Collector< element< 3 > > *elemCollector, MInt bndCndId, MInt segmentId, MInt *offset)
reads triangles from a BINARY file and swaps to big endian
Definition: geometry3d.cpp:631
virtual void readSegmentTrianglesBINARY_LE(MString fileName, Collector< element< 3 > > *elemCollector, MInt bndCndId, MInt segmentId, MInt *offset)
reads triangles from a BINARY file and swaps to little endian
Definition: geometry3d.cpp:717
MBool m_communicateSegmentsSerial
Definition: geometry3d.h:133
virtual void countSegmentTrianglesBINARY(MString fileName, MInt *noElements)
counts the number of triangles in a BINARY STL file
Definition: geometry3d.cpp:457
virtual void countSegmentTrianglesNETCDF(MString fileName, MInt *noElements, const MPI_Comm comm)
counts the number of triangles in a NETCDF STL file
Definition: geometry3d.cpp:485
virtual void readSegmentTrianglesNETCDF(MString fileName, Collector< element< 3 > > *elemCollector, MInt bndCndId, MInt segmentId, MInt *offset, const MPI_Comm comm)
reads triangles from a BINARY file
Definition: geometry3d.cpp:783
MInt m_noAllBCs
Definition: geometry.h:199
bodyMap m_bodyMap
Definition: geometry.h:192
MInt * m_allBCs
Definition: geometry.h:198
bodyIterator m_bodyIt
Definition: geometry.h:193
MInt string2enum(MString theString)
This global function translates strings in their corresponding enum values (integer values)....
Definition: enums.cpp:20
@ NETCDF
Definition: enums.h:18
@ BINARY
Definition: enums.h:18
@ ASCII
Definition: enums.h:18
IdType index(const FloatType *const x, const IdType level)
Return Hilbert index for given location and level in 2D or 3D.
Definition: hilbert.h:165

◆ readSegmentTrianglesASCII()

void Geometry3D::readSegmentTrianglesASCII ( MString  fileName,
Collector< element< 3 > > *  elemCollector,
MInt  bndCndId,
MInt  segmentId,
MInt offset 
)
inlineprotectedvirtual
Author
Andreas Lintermann
Date
20.07.2015
Parameters
[in]fileNamethe name of the file to open
[in]elemCollectorpointer to the collector holding the triangles
[in]bndCndIdthe boundary condition id associated with this segment
[in]segmenIdthe id of the segment
[in]thepointer to the segment offset for later computation

Definition at line 509 of file geometry3d.cpp.

510 {
511 TRACE();
512
513 // open file in ascii format
514 ifstream ifl(fileName);
515
516 if(!ifl) {
517 stringstream errorMessage;
518 errorMessage << " ERROR in segment::readSegment, couldn't find file : " << fileName << "!";
519 mTerm(1, AT_, errorMessage.str());
520 }
521
522 element<3>* allelements = elemCollector->a;
523 string text;
524 char tmp[1024]{};
525 while(text.find("endsolid") == std::string::npos) {
526 ifl.getline(tmp, 1024);
527 text = tmp;
528 if(text.find("normal") != std::string::npos) {
529 elemCollector->append();
530 trim(text);
531 std::vector<std::string> tokens;
532 tokenize(text, tokens, " ", true);
533
534 // Read normal vector components
535 for(MInt i = 0; i < 3; i++) {
536 tokens[i + 2] = trim(tokens[i + 2]);
537 if(tokens[i + 2].find_first_not_of("0123456789.eE-+") != std::string::npos) {
538 cerr << "ERROR: normal component " << tokens[i + 2] << " is not a number " << endl;
539 TERM(-1);
540 }
541
542 allelements[*offset].m_normal[i] = stod(tokens[i + 2]);
543 }
544 // Jump expression : outer loop
545 ifl.getline(tmp, 256);
546
547 // Read vertices
548
549 for(MInt j = 0; j < 3; j++) {
550 ifl.getline(tmp, 1024);
551
552 text = tmp;
553 trim(text);
554 std::vector<std::string> vertex;
555 tokenize(text, vertex, " ", true);
556
557 for(MInt i = 0; i < 3; i++) {
558 vertex[i + 1] = trim(vertex[i + 1]);
559 if(vertex[i + 1].find_first_not_of("0123456789.eE-+") != std::string::npos) {
560 cerr << "ERROR: vertex component " << vertex[i + 1] << " is not a number " << endl;
561 TERM(-1);
562 }
563
564
565 allelements[*offset].m_vertices[j][i] = stod(vertex[i + 1]);
566 }
567 }
568
569 allelements[*offset].boundingBox();
570 allelements[*offset].m_bndCndId = bndCndId;
571 allelements[*offset].m_segmentId = segmentId;
572 allelements[*offset].m_originalId = -1;
573
575 for(MInt id = 0; id < m_noLevelSetIntfBndIds; id++)
576 if(bndCndId == m_levelSetIntfBndIds[id]) m_noMBElements++;
577
578 *offset = *offset + 1;
579 }
580 }
581
582 ifl.close();
583}
void append()
Definition: collector.h:153
void tokenize(const std::string &str, ContainerT &tokens, const std::string &delimiters=" ", MBool trimEmpty=false)
Definition: functions.h:439

◆ readSegmentTrianglesBINARY_BE()

void Geometry3D::readSegmentTrianglesBINARY_BE ( MString  fileName,
Collector< element< 3 > > *  elemCollector,
MInt  bndCndId,
MInt  segmentId,
MInt offset 
)
inlineprotectedvirtual
Author
Andreas Lintermann
Date
22.07.2015

This function is called on big endian machines like the Juqueen.

Parameters
[in]fileNamethe name of the file to open
[in]elemCollectorpointer to the collector holding the triangles
[in]bndCndIdthe boundary condition id associated with this segment
[in]segmenIdthe id of the segment
[in]thepointer to the segment offset for later computation

Definition at line 631 of file geometry3d.cpp.

632 {
633 TRACE();
634
635 using facet_t = struct { float n[3], v1[3], v2[3], v3[3]; };
636 facet_t facet;
637
638 // open file in binary format
639 FILE* fp = nullptr;
640
641 if((fp = fopen(fileName.c_str(), "rb")) == nullptr) {
642 stringstream errorMessage;
643 errorMessage << " ERROR in segment::readSegment, couldn't find file : " << fileName << "!";
644 mTerm(1, AT_, errorMessage.str());
645 }
646
647 element<3>* allelements = elemCollector->a;
648 char header[85];
649 MUshort ibuff2 = 0;
650 if(!fread(header, 1, 84, fp)) {
651 TERMM(-1, "ERROR: Memory error!");
652 }
653
654 for(MInt i = 0; fread(&facet, 48, 1, fp) > 0; i++) {
655 if(!fread(&ibuff2, 2, 1, fp)) {
656 TERMM(-1, "ERROR: Memory error!");
657 }
658
659 elemCollector->append();
660
661 // reorder
662 for(float& k : facet.n) {
663 char* buf = (char*)(&k);
664 swap4BytesToBE(buf);
665 }
666 for(float& k : facet.v1) {
667 char* buf = (char*)(&k);
668 swap4BytesToBE(buf);
669 }
670 for(float& k : facet.v2) {
671 char* buf = (char*)(&k);
672 swap4BytesToBE(buf);
673 }
674 for(float& k : facet.v3) {
675 char* buf = (char*)(&k);
676 swap4BytesToBE(buf);
677 }
678
679
680 for(MInt j = 0; j < nDim; j++) {
681 allelements[*offset].m_normal[j] = facet.n[j];
682 allelements[*offset].m_vertices[0][j] = facet.v1[j];
683 allelements[*offset].m_vertices[1][j] = facet.v2[j];
684 allelements[*offset].m_vertices[2][j] = facet.v3[j];
685 }
686
687 allelements[*offset].boundingBox();
688 allelements[*offset].m_bndCndId = bndCndId;
689 allelements[*offset].m_segmentId = segmentId;
690 allelements[*offset].m_originalId = -1;
691
693 for(MInt id = 0; id < m_noLevelSetIntfBndIds; id++)
694 if(bndCndId == m_levelSetIntfBndIds[id]) m_noMBElements++;
695
696 *offset = *offset + 1;
697 }
698
699 fclose(fp);
700}
virtual void swap4BytesToBE(char *buf)
swaps 4 bytes from little to big endian
Definition: geometry3d.cpp:592
uint_least16_t MUshort
Definition: maiatypes.h:61

◆ readSegmentTrianglesBINARY_LE()

void Geometry3D::readSegmentTrianglesBINARY_LE ( MString  fileName,
Collector< element< 3 > > *  elemCollector,
MInt  bndCndId,
MInt  segmentId,
MInt offset 
)
inlineprotectedvirtual
Author
Andreas Lintermann
Date
22.07.2015

This function is called on little endian machines.

Parameters
[in]fileNamethe name of the file to open
[in]elemCollectorpointer to the collector holding the triangles
[in]bndCndIdthe boundary condition id associated with this segment
[in]segmenIdthe id of the segment
[in]thepointer to the segment offset for later computation

Definition at line 717 of file geometry3d.cpp.

718 {
719 TRACE();
720
721 using facet_t = struct { float n[3], v1[3], v2[3], v3[3]; };
722 facet_t facet;
723
724 // open file in binary format
725 FILE* fp = nullptr;
726
727 if((fp = fopen(fileName.c_str(), "rb")) == nullptr) {
728 stringstream errorMessage;
729 errorMessage << " ERROR in segment::readSegment, couldn't find file : " << fileName << "!";
730 mTerm(1, AT_, errorMessage.str());
731 }
732
733 element<3>* allelements = elemCollector->a;
734 char header[85];
735 MUshort ibuff2 = 0;
736
737 if(fread(header, 1, 84, fp) == 0u) {
738 TERMM(-1, "ERROR: Memory error!");
739 }
740
741 for(MInt i = 0; fread(&facet, 48, 1, fp) > 0; i++) {
742 if(fread(&ibuff2, 2, 1, fp) == 0u) {
743 TERMM(-1, "ERROR: Memory error!");
744 }
745
746 elemCollector->append();
747
748 for(MInt j = 0; j < nDim; j++) {
749 allelements[*offset].m_normal[j] = facet.n[j];
750 allelements[*offset].m_vertices[0][j] = facet.v1[j];
751 allelements[*offset].m_vertices[1][j] = facet.v2[j];
752 allelements[*offset].m_vertices[2][j] = facet.v3[j];
753 }
754
755 allelements[*offset].boundingBox();
756 allelements[*offset].m_bndCndId = bndCndId;
757 allelements[*offset].m_segmentId = segmentId;
758 allelements[*offset].m_originalId = -1;
759
761 for(MInt id = 0; id < m_noLevelSetIntfBndIds; id++)
762 if(bndCndId == m_levelSetIntfBndIds[id]) m_noMBElements++;
763
764 *offset = *offset + 1;
765 }
766
767 fclose(fp);
768}

◆ readSegmentTrianglesNETCDF()

void Geometry3D::readSegmentTrianglesNETCDF ( MString  fileName,
Collector< element< 3 > > *  elemCollector,
MInt  bndCndId,
MInt  segmentId,
MInt offset,
const MPI_Comm  comm 
)
inlineprotectedvirtual
Author
Andreas Lintermann
Date
20.07.2015
Parameters
[in]fileNamethe name of the file to open
[in]elemCollectorpointer to the collector holding the triangles
[in]bndCndIdthe boundary condition id associated with this segment
[in]segmenIdthe id of the segment
[in]thepointer to the segment offset for later computation

Definition at line 783 of file geometry3d.cpp.

784 {
785 TRACE();
786
787 using namespace maia::parallel_io;
788
789 MInt offsetstart = *offset;
790 MInt noTriangles = -1;
791 ParallelIo surface(fileName, PIO_READ, comm);
792 surface.readScalar(&noTriangles, "noTriangles");
793
794 MInt noEntries = noTriangles;
795
796 MFloatScratchSpace tmp_array(noEntries, AT_, "tmp_array");
797
798 element<3>* allelements = elemCollector->a;
799 for(MInt i = 0; i < noTriangles; i++) {
800 elemCollector->append();
801
802 allelements[*offset].m_bndCndId = bndCndId;
803 allelements[*offset].m_segmentId = segmentId;
804 allelements[*offset].m_originalId = -1;
805
807 for(MInt id = 0; id < m_noLevelSetIntfBndIds; id++)
808 if(bndCndId == m_levelSetIntfBndIds[id]) m_noMBElements++;
809
810 *offset = *offset + 1;
811 }
812
813 MString normalnames[3] = {"normals0", "normals1", "normals2"};
814 MString vertexnames[3][3] = {{"vertices00", "vertices01", "vertices02"},
815 {"vertices10", "vertices11", "vertices12"},
816 {"vertices20", "vertices21", "vertices22"}};
817
818 // normals
819 for(MInt d = 0; d < nDim; d++) {
820 surface.setOffset(noEntries, 0);
821 surface.readArray(tmp_array.begin(), normalnames[d]);
822
823 for(MInt i = offsetstart, j = 0; i < offsetstart + noTriangles; i++, j++)
824 allelements[i].m_normal[d] = tmp_array[j];
825 }
826
827 // vertices
828 for(MInt vtx = 0; vtx < nDim; vtx++) {
829 for(MInt coord = 0; coord < nDim; coord++) {
830 surface.setOffset(noEntries, 0);
831 surface.readArray(tmp_array.begin(), vertexnames[vtx][coord]);
832 for(MInt i = offsetstart, j = 0; i < offsetstart + noTriangles; i++, j++) {
833 allelements[i].m_vertices[vtx][coord] = tmp_array[j];
834 }
835 }
836 }
837
838 for(MInt i = offsetstart; i < offsetstart + noTriangles; i++) {
839 allelements[i].boundingBox();
840 }
841}

◆ readSTLNetCDF()

void Geometry3D::readSTLNetCDF ( const char *  fileName)
overridevirtual

Reimplemented from Geometry< 3 >.

Definition at line 4464 of file geometry3d.cpp.

4464 {
4465 TRACE();
4466
4467 otherCalls++;
4468
4469 m_log << "domainId() = " << domainId() << endl;
4470 m_log << "noDomains = " << noDomains() << endl;
4471
4472 ParallelIo::size_type count = 0;
4473
4474 // WARNING: untested switch from NetCDF/Parallel netCDF to ParallelIo
4475 // The method previously used direct I/O calls, which were replaced by
4476 // ParallelIo methods in summer 2015. However, since the method was not
4477 // used by any of the testcases, this code is still *untested*. Thus,
4478 // if your code uses this part of the code, please make sure that the
4479 // I/O still works as expected and then remove this warning as well as
4480 // the subsequent TERMM().
4481 TERMM(1, "untested I/O method, please see comment for how to proceed");
4482 ParallelIo parallelIo(fileName, maia::parallel_io::PIO_READ, MPI_COMM_SELF);
4483
4484 ParallelIo::size_type noVerticesVarSize = 0;
4485 noVerticesVarSize = parallelIo.getArraySize("noVertices");
4486
4487 MInt domainStartRead;
4488 MInt domainEndRead;
4489 MInt elementsPerDomain = noVerticesVarSize / noDomains() + 1;
4490 domainStartRead = domainId() * elementsPerDomain;
4491
4492 if(domainId() == noDomains() - 1) {
4493 m_noElements = noVerticesVarSize - ((noDomains() - 1) * (elementsPerDomain));
4494 domainEndRead = domainStartRead + m_noElements - 1;
4495 } else {
4496 m_noElements = elementsPerDomain;
4497 domainEndRead = domainStartRead + m_noElements - 1;
4498 }
4499
4500 m_log << "no elements in file: " << noVerticesVarSize << endl;
4501 m_log << "m_noElements = " << m_noElements << endl;
4502 m_log << "domainStartRead = " << domainStartRead << endl;
4503 m_log << "domainEndRead = " << domainEndRead << endl;
4504
4505 if(m_elements != nullptr) delete m_elements;
4507 elements = m_elements->a;
4508
4509 MFloat* tmp = new MFloat[9 * m_noElements];
4510 MInt* tmpI = new MInt[m_noElements];
4511
4512 count = m_noElements;
4513 parallelIo.setOffset(count, 0, 2);
4514 parallelIo.readArray(tmp, "vertexNormal");
4515
4516 for(MInt i = 0; i < m_noElements; i++) {
4517 m_elements->append();
4518 for(MInt j = 0; j < 3; j++) {
4519 elements[i].m_normal[j] = tmp[i * 3 + j];
4520 }
4521 }
4522
4523 count = m_noElements;
4524 parallelIo.setOffset(count, 0, 3);
4525 parallelIo.readArray(tmp, "vertexCoordinates");
4526
4527 for(MInt i = 0; i < m_noElements; i++) {
4528 for(MInt j = 0; j < 3; j++) {
4529 for(MInt k = 0; k < 3; k++) {
4530 elements[i].m_vertices[j][k] = tmp[3 * (i * 3 + j) + k];
4531 }
4532 }
4533 elements[i].boundingBox();
4534 }
4535
4536 count = m_noElements;
4537 parallelIo.setOffset(count, 0);
4538 parallelIo.readArray(tmpI, "boundaryConditionId");
4539
4540 for(MInt i = 0; i < m_noElements; i++) {
4541 for(MInt j = 0; j < 3; j++) {
4542 elements[i].m_bndCndId = tmpI[i];
4543 }
4544 }
4545
4546 count = 2 * nDim;
4547 parallelIo.setOffset(count, 0);
4548 parallelIo.readArray(tmp, "minMax");
4549 for(MInt i = 0; i < 2 * nDim; i++) {
4550 m_minMax[i] = tmp[i];
4551 }
4552
4553 /*
4554 for(MInt j=0; j < nDim; j++){
4555 m_minMax[j] = elements[0].m_minMax[j];
4556 m_minMax[j + nDim] = elements[0].m_minMax[j + nDim];
4557 }
4558 for(MInt i=0; i < m_noElements; i++){
4559 for(MInt j=0; j < nDim; j++){
4560 m_minMax[j + nDim] = (m_minMax[j + nDim] <
4561 elements[i].m_minMax[j + nDim]) ? elements[i].m_minMax[j + nDim] : m_minMax[j + nDim];
4562 m_minMax[j] = (m_minMax[j] > elements[i].m_minMax[j]) ? elements[i].m_minMax[j] : m_minMax[j];
4563 }
4564 }
4565 */
4566
4567 delete[] tmp;
4568 delete[] tmpI;
4569}
const MInt PIO_READ
Definition: parallelio.h:40

◆ rebuildAdtTree()

void Geometry3D::rebuildAdtTree ( )
overrideprotectedvirtual
Author
Andreas Lintermann
Date
25.09.2015

Reimplemented from Geometry< 3 >.

Definition at line 313 of file geometry3d.cpp.

313 {
314 delete m_adt;
315
316 m_adt = new GeometryAdt<3>(this);
317 m_adt->buildTree();
318
320}
void printMemoryUsage()
prints the current memory usage of this object
Definition: geometry3d.cpp:328

◆ ReplaceMBElementVertex()

void Geometry3D::ReplaceMBElementVertex ( MInt  e,
MInt  v,
MFloat np 
)
overridevirtual

Reimplemented from Geometry< 3 >.

Definition at line 4228 of file geometry3d.cpp.

4228 {
4229 TRACE();
4230
4231 otherCalls++;
4232
4233
4234 for(MInt i = 0; i < nDim; i++) {
4235 mbelements[e].m_vertices[v][i] = np[i];
4236 }
4237}

◆ resizeCollector()

void Geometry3D::resizeCollector ( MInt  new_size)
overrideprotectedvirtual
Author
Andreas Lintermann
Date
11.01.2016
Parameters
[in]new_sizethe new size of the collector

Reimplemented from Geometry< 3 >.

Definition at line 5036 of file geometry3d.cpp.

5036 {
5037 TRACE();
5038
5039 m_log << " * resizing collector: " << m_noElements << " - " << m_noElements + new_size << endl;
5040
5041 auto* tmp = new Collector<element<nDim>>(m_noElements + new_size, nDim, 0);
5042
5043 element<nDim>* fromPtr = m_elements->a;
5044 element<nDim>* toPtr = tmp->a;
5045
5046 for(MInt e = 0; e < m_noElements; e++) {
5047 tmp->append();
5048 copyElement(e, e, fromPtr, toPtr);
5049 }
5050
5051 delete m_elements;
5052 m_elements = tmp;
5053 elements = m_elements->a;
5054}

◆ swap4BytesToBE()

void Geometry3D::swap4BytesToBE ( char *  buf)
inlineprotectedvirtual
Author
Andreas Lintermann
Date
22.07.2015
Parameters
[in]bufa pointer to a char array of 4 bytes

Definition at line 592 of file geometry3d.cpp.

592 {
593 char tmp_byte = buf[0];
594 buf[0] = buf[3];
595 buf[3] = tmp_byte;
596 tmp_byte = buf[1];
597 buf[1] = buf[2];
598 buf[2] = tmp_byte;
599}

◆ UpdateADT()

void Geometry3D::UpdateADT ( )
overridevirtual

Reimplemented from Geometry< 3 >.

Definition at line 4282 of file geometry3d.cpp.

4282 {
4283 TRACE();
4284
4285 otherCalls++;
4286
4287 m_adt->buildTreeMB();
4288}

◆ UpdateMBBoundingBox()

void Geometry3D::UpdateMBBoundingBox ( )
overridevirtual

Reimplemented from Geometry< 3 >.

Definition at line 4259 of file geometry3d.cpp.

4259 {
4260 TRACE();
4261
4262 otherCalls++;
4263
4264
4265 for(MInt e = 0; e < m_mbelements->size(); e++) {
4266 mbelements[e].boundingBox();
4267 }
4268 for(MInt j = 0; j < nDim; j++) {
4269 m_mbminMax[j] = mbelements[0].m_minMax[j];
4270 m_mbminMax[j + nDim] = mbelements[0].m_minMax[j + nDim];
4271 }
4272 for(MInt i = 0; i < m_mbelements->size(); i++) {
4273 for(MInt j = 0; j < nDim; j++) {
4274 m_mbminMax[j + nDim] = (m_mbminMax[j + nDim] < mbelements[i].m_minMax[j + nDim])
4275 ? mbelements[i].m_minMax[j + nDim]
4276 : m_mbminMax[j + nDim];
4277 m_mbminMax[j] = (m_mbminMax[j] > mbelements[i].m_minMax[j]) ? mbelements[i].m_minMax[j] : m_mbminMax[j];
4278 }
4279 }
4280}

◆ UpdateMBNormalVector()

void Geometry3D::UpdateMBNormalVector ( MInt  e)
overridevirtual

Reimplemented from Geometry< 3 >.

Definition at line 4239 of file geometry3d.cpp.

4239 {
4240 TRACE();
4241
4242 otherCalls++;
4243
4244
4245 MFloat v1[3], v2[3], n[3], norm_n = NAN;
4246 for(MInt i = 0; i < nDim; i++) {
4247 v1[i] = mbelements[e].m_vertices[1][i] - mbelements[e].m_vertices[0][i];
4248 v2[i] = mbelements[e].m_vertices[2][i] - mbelements[e].m_vertices[0][i];
4249 }
4250 n[0] = v1[1] * v2[2] - v2[1] * v1[2];
4251 n[1] = v1[2] * v2[0] - v2[2] * v1[0];
4252 n[2] = v1[0] * v2[1] - v2[0] * v1[1];
4253
4254 norm_n = sqrt(POW2(n[0]) + POW2(n[1]) + POW2(n[2]));
4255 for(MInt i = 0; i < nDim; i++)
4256 mbelements[e].m_normal[i] = n[i] / norm_n;
4257}
constexpr Real POW2(const Real x)
Definition: functions.h:119

◆ writeADTAndSTLToNetCDF()

void Geometry3D::writeADTAndSTLToNetCDF ( const char *  fileName)
overridevirtual

Reimplemented from Geometry< 3 >.

Definition at line 4354 of file geometry3d.cpp.

4354 {
4355 TRACE();
4356 using namespace maia::parallel_io;
4357
4358 ParallelIo::size_type count = 0;
4359
4360 // WARNING: untested switch from NetCDF/Parallel netCDF to ParallelIo
4361 // The method previously used direct I/O calls, which were replaced by
4362 // ParallelIo methods in summer 2015. However, since the method was not
4363 // used by any of the testcases, this code is still *untested*. Thus,
4364 // if your code uses this part of the code, please make sure that the
4365 // I/O still works as expected and then remove this warning as well as
4366 // the subsequent TERMM().
4367 TERMM(1, "untested I/O method, please see comment for how to proceed");
4368 ParallelIo parallelIo(fileName, maia::parallel_io::PIO_REPLACE, MPI_COMM_SELF);
4369
4370 /*
4371 *
4372 * ParallelIo define solver --->
4373 *
4374 */
4375 ParallelIo::size_type tempDim[2];
4376 ParallelIo::size_type tempDim3D[3];
4377
4378 tempDim[0] = m_noElements;
4379 tempDim[1] = nDim;
4380
4381 tempDim3D[0] = m_noElements;
4382 tempDim3D[1] = 3;
4383 tempDim3D[2] = nDim;
4384
4385 parallelIo.defineArray(PIO_FLOAT, "minMax", 2 * nDim);
4386
4387 parallelIo.defineArray(PIO_FLOAT, "vertexNormal", 2, tempDim);
4388
4389 parallelIo.defineArray(PIO_FLOAT, "vertexCoordinates", 3, tempDim3D);
4390
4391 parallelIo.defineArray(PIO_INT, "boundaryConditionId", m_noElements);
4392
4393 /*
4394 *
4395 * <--- ParallelIo define solver
4396 *
4397 */
4398
4399 MFloatScratchSpace floatScratch(9 * m_noElements, AT_, "tmp_float_array");
4400 MFloat* tmp = floatScratch.getPointer();
4401 MIntScratchSpace intScratch(m_noElements, AT_, "tmp_int_array");
4402 MInt* tmpI = intScratch.getPointer();
4403
4404 for(MInt i = 0; i < 2 * nDim; i++) {
4405 tmp[i] = m_minMax[i];
4406 }
4407 count = 2 * nDim;
4408 parallelIo.setOffset(count, 0);
4409 parallelIo.writeArray(&tmp[0], "minMax");
4410
4411 for(MInt i = 0; i < m_noElements; i++) {
4412 for(MInt j = 0; j < 3; j++) {
4413 tmp[i * 3 + j] = elements[i].m_normal[j];
4414 }
4415 }
4416 count = m_noElements;
4417 parallelIo.setOffset(count, 0, 2);
4418 parallelIo.writeArray(&tmp[0], "vertexNormal");
4419
4420 for(MInt i = 0; i < m_noElements; i++) {
4421 for(MInt j = 0; j < 3; j++) {
4422 for(MInt k = 0; k < 3; k++) {
4423 tmp[3 * (i * 3 + j) + k] = elements[i].m_vertices[j][k];
4424 }
4425 }
4426 }
4427 count = m_noElements;
4428 parallelIo.setOffset(count, 0, 3);
4429 parallelIo.writeArray(&tmp[0], "vertexCoordinates");
4430
4431 for(MInt i = 0; i < m_noElements; i++) {
4432 tmpI[i] = elements[i].m_bndCndId;
4433 }
4434 count = m_noElements;
4435 parallelIo.setOffset(count, 0);
4436 parallelIo.writeArray(&tmpI[0], "boundaryConditionId");
4437
4438 /* If the tree needs to be saved
4439 // parIdVar = file.add_var("parentNodeId", ncInt, noNodeDim);
4440 // for(MInt i = 0; i < m_noElements; i++){
4441 // tmp[i] = m_adt->m_nodes[i].m_parent;
4442 // }
4443 // parIdVar->put(&tmp[0], m_noElements);
4444
4445 // childIdVar = file.add_var("childNodeIds", ncInt, noNodeDim, noChildDim);
4446 // tmp[2*i] = m_adt->m_nodes[i].m_leftSubtree;
4447 // tmp[2*i+1] = m_adt->m_nodes[i].m_rightSubtree;
4448 // }
4449 // childIdVar->put(&tmp[0], m_noElements, 2);
4450
4451 // levelVar = file.add_var("level", ncInt, noNodeDim);
4452 // level[i] = m_adt->m_nodes[i].m_depth;
4453 // }
4454 // levelVar->put(&tmp[0], m_noElements);
4455
4456 // vertsVar = file.add_var("vertex", ncInt, noNodeDim);
4457 // tmp[i] = m_adt->m_nodes[i].m_element;
4458 // }
4459 // vertsVar->put(&tmp[0], m_noElements);
4460 */
4461 // m_log << Scratch::printSelf();
4462}
const MInt PIO_REPLACE
Definition: parallelio.h:36

◆ writeParallelGeometryVTK()

void Geometry3D::writeParallelGeometryVTK ( MString  filename)
overrideprotectedvirtual
Author
Andreas Lintermann
Date
25.09.2015
Parameters
[in]filenamethe name of the file without extension

Reimplemented from Geometry< 3 >.

Definition at line 1508 of file geometry3d.cpp.

1508 {
1509 TRACE();
1510
1511 const MBool allTimerRunning = timers().isRunning(m_t_geometryAll);
1512 if(!allTimerRunning) {
1513 RECORD_TIMER_START(m_t_geometryAll);
1514 }
1515 NEW_SUB_TIMER(t_wrtParGeom, "writing parallel geometry", m_t_geometryAll);
1516 g_tc_geometry.emplace_back("writing parallel geometry", t_wrtParGeom);
1517 RECORD_TIMER_START(t_wrtParGeom);
1518
1519 stringstream name;
1520 name << "out/" << domainId() << "_" << filename << ".vtk";
1521 ofstream st;
1522 st.open(name.str());
1523 st << "# vtk DataFile Version 3.0" << endl;
1524 st << "vtk output" << endl;
1525 st << "ASCII" << endl;
1526 st << "DATASET POLYDATA" << endl;
1527 st << "POINTS " << m_noElements * nDim << " float" << endl;
1528
1529 for(MInt i = 0; i < m_noElements; i++)
1530 for(MInt v = 0; v < 3; v++) {
1531 for(MInt d = 0; d < 3; d++)
1532 st << elements[i].m_vertices[v][d] << " ";
1533 st << endl;
1534 }
1535
1536 st << endl;
1537 st << "POLYGONS " << m_noElements << " " << m_noElements * (nDim + 1) << endl;
1538 for(MInt i = 0, j = 0; i < m_noElements; i++) {
1539 st << nDim << " ";
1540 for(MInt v = 0; v < 3; v++, j++)
1541 st << j << " ";
1542 st << endl;
1543 }
1544
1545 st << endl;
1546 st << "CELL_DATA " << m_noElements << endl;
1547 st << "SCALARS domainId int 1" << endl;
1548 st << "LOOKUP_TABLE default" << endl;
1549 for(MInt i = 0; i < m_noElements; i++)
1550 st << domainId() << endl;
1551 st << endl;
1552 st << "SCALARS segmentId int 1" << endl;
1553 st << "LOOKUP_TABLE default" << endl;
1554 for(MInt i = 0; i < m_noElements; i++)
1555 st << elements[i].m_segmentId << endl;
1556 st << endl;
1557 st << "SCALARS originalCellId int 1" << endl;
1558 st << "LOOKUP_TABLE default" << endl;
1559 for(MInt i = 0; i < m_noElements; i++)
1560 st << elements[i].m_originalId << endl;
1561 st << endl;
1562 st << "SCALARS BC int 1" << endl;
1563 st << "LOOKUP_TABLE default" << endl;
1564 for(MInt i = 0; i < m_noElements; i++)
1565 st << elements[i].m_bndCndId << endl;
1566 st << "SCALARS area double 1" << endl;
1567 st << "LOOKUP_TABLE default" << endl;
1568 for(MInt i = 0; i < m_noElements; i++) {
1569 MFloat edge1[3];
1570 MFloat edge2[3];
1571 MFloat cross[3];
1572 for(MInt j = 0; j < nDim; j++) {
1573 edge1[j] = elements[i].m_vertices[1][j] - elements[i].m_vertices[0][j];
1574 edge2[j] = elements[i].m_vertices[2][j] - elements[i].m_vertices[0][j];
1575 }
1576 cross[0] = edge1[1] * edge2[2] - edge2[1] * edge1[2];
1577 cross[1] = edge1[2] * edge2[0] - edge2[2] * edge1[0];
1578 cross[2] = edge1[0] * edge2[1] - edge2[0] * edge1[1];
1579
1580 MFloat area = sqrt(cross[0] * cross[0] + cross[1] * cross[1] + cross[2] * cross[2]);
1581 st << area << endl;
1582 }
1583 st.close();
1584 RECORD_TIMER_STOP(t_wrtParGeom);
1585 if(!allTimerRunning) {
1586 RECORD_TIMER_STOP(m_t_geometryAll);
1587 }
1588}
MInt isRunning(const MInt timerId) const
Definition: timer.h:192
MTimers & timers()
Definition: timer.cpp:19

◆ writeSTL()

void Geometry3D::writeSTL ( const char *  fileName)
overridevirtual

Reimplemented from Geometry< 3 >.

Definition at line 4290 of file geometry3d.cpp.

4290 {
4291 TRACE();
4292
4293 ofstream ofl;
4294
4295 ofl.open(fileName);
4296 ofl.precision(12);
4297
4298 if(ofl) {
4299 ofl << "solid PRO2STL version 1.0 part " << domainId() << endl;
4300
4301 for(MInt i = 0; i < m_noElements; i++) {
4302 ofl << " facet normal";
4303 for(MInt j = 0; j < 3; j++) {
4304 ofl << " " << elements[i].m_normal[j];
4305 }
4306 ofl << endl << " outer loop" << endl;
4307
4308 for(MInt k = 0; k < 3; k++) {
4309 ofl << " vertex";
4310 for(MInt l = 0; l < 3; l++) {
4311 ofl << " " << elements[i].m_vertices[k][l];
4312 }
4313 ofl << endl;
4314 }
4315
4316 ofl << " endloop" << endl << " endfacet" << endl;
4317 }
4318 ofl << "endsolid PRO2STL version 1.0 part " << domainId() << endl;
4319 }
4320}

◆ writeSTLMB()

void Geometry3D::writeSTLMB ( const char *  fileName,
MInt noNodes,
MInt *&  nodeList 
)
overridevirtual

Reimplemented from Geometry< 3 >.

Definition at line 4322 of file geometry3d.cpp.

4322 {
4323 TRACE();
4324
4325 ofstream ofl;
4326
4327 ofl.open(fileName);
4328 ofl.precision(12);
4329
4330 if(ofl) {
4331 ofl << "solid PRO2STL version 1.0 part " << domainId() << endl;
4332
4333 for(MInt i = 0; i < noNodes; i++) {
4334 ofl << " facet normal";
4335 for(MInt j = 0; j < 3; j++) {
4336 ofl << " " << mbelements[nodeList[i]].m_normal[j];
4337 }
4338 ofl << endl << " outer loop" << endl;
4339
4340 for(MInt k = 0; k < 3; k++) {
4341 ofl << " vertex";
4342 for(MInt l = 0; l < 3; l++) {
4343 ofl << " " << mbelements[nodeList[i]].m_vertices[k][l];
4344 }
4345 ofl << endl;
4346 }
4347
4348 ofl << " endloop" << endl << " endfacet" << endl;
4349 }
4350 ofl << "endsolid PRO2STL version 1.0 part " << domainId() << endl;
4351 }
4352}

Member Data Documentation

◆ edgeTICallCounter

MInt Geometry3D::edgeTICallCounter = 0
protected

Definition at line 130 of file geometry3d.h.

◆ getIECallCounter

MInt Geometry3D::getIECallCounter = 0
protected

Definition at line 127 of file geometry3d.h.

◆ getIECommCounter

MInt Geometry3D::getIECommCounter = 0
protected

Definition at line 128 of file geometry3d.h.

◆ getIETCallCounter

MInt Geometry3D::getIETCallCounter = 0
protected

Definition at line 129 of file geometry3d.h.

◆ getLIE2CommCounter

MInt Geometry3D::getLIE2CommCounter = 0
protected

Definition at line 126 of file geometry3d.h.

◆ m_communicateSegmentsSerial

MBool Geometry3D::m_communicateSegmentsSerial = true
protected

Definition at line 133 of file geometry3d.h.

◆ m_forceBoundingBox

MBool Geometry3D::m_forceBoundingBox = false
protected

Definition at line 117 of file geometry3d.h.

◆ m_geomFileType

MString Geometry3D::m_geomFileType
protected

Definition at line 121 of file geometry3d.h.

◆ m_getLIE2CallCounter

MInt Geometry3D::m_getLIE2CallCounter = 0
protected

Definition at line 125 of file geometry3d.h.

◆ m_GFieldInitFromSTL

MBool Geometry3D::m_GFieldInitFromSTL = false
protected

Definition at line 113 of file geometry3d.h.

◆ m_gridCutTest

MString Geometry3D::m_gridCutTest
protected

Definition at line 119 of file geometry3d.h.

◆ m_gridFileName

MString Geometry3D::m_gridFileName
protected

Definition at line 122 of file geometry3d.h.

◆ m_levelSetIntfBndId

MInt Geometry3D::m_levelSetIntfBndId = 0
protected

Definition at line 114 of file geometry3d.h.

◆ m_levelSetIntfBndIds

MInt* Geometry3D::m_levelSetIntfBndIds {}
protected

Definition at line 115 of file geometry3d.h.

◆ m_noAllTriangles

MInt Geometry3D::m_noAllTriangles {}
protected

Definition at line 123 of file geometry3d.h.

◆ m_noLevelSetIntfBndIds

MInt Geometry3D::m_noLevelSetIntfBndIds = 0
protected

Definition at line 116 of file geometry3d.h.

◆ m_t_geometryAll

MInt Geometry3D::m_t_geometryAll {}
private

Definition at line 138 of file geometry3d.h.

◆ m_t_readGeometry

MInt Geometry3D::m_t_readGeometry {}
private

Definition at line 139 of file geometry3d.h.

◆ m_tg_geometry

MInt Geometry3D::m_tg_geometry {}
private

Definition at line 137 of file geometry3d.h.

◆ nDim

constexpr const MInt Geometry3D::nDim = 3
staticconstexprprotected

Definition at line 131 of file geometry3d.h.

◆ otherCalls

MInt Geometry3D::otherCalls = 0
protected

Definition at line 111 of file geometry3d.h.


The documentation for this class was generated from the following files: