19 #ifndef GEOSX_MESHUTILITIES_COMPUTATIONALGEOMETRY_HPP_ 20 #define GEOSX_MESHUTILITIES_COMPUTATIONALGEOMETRY_HPP_ 29 namespace computationalGeometry
48 template<
typename LINEDIR_TYPE,
52 typename INTPOINT_TYPE >
54 POINT_TYPE
const & linePoint,
55 NORMAL_TYPE
const & planeNormal,
56 ORIGIN_TYPE
const & planeOrigin,
57 INTPOINT_TYPE & intersectionPoint )
66 LvArray::tensorOps::subtract< 3 >( dummy, linePoint );
67 real64 const d = LvArray::tensorOps::AiBi< 3 >( dummy, planeNormal ) /
68 LvArray::tensorOps::AiBi< 3 >( lineDir, planeNormal );
70 LvArray::tensorOps::copy< 3 >( intersectionPoint, linePoint );
71 LvArray::tensorOps::scaledAdd< 3 >( intersectionPoint, lineDir, d );
81 template<
typename NORMAL_TYPE >
83 NORMAL_TYPE
const & normal )
89 std::vector< int > indices( numPoints );
90 std::vector< real64 > angle( numPoints );
94 LvArray::tensorOps::fill< 3 >( centroid, 0 );
97 LvArray::tensorOps::add< 3 >( centroid, points[ a ] );
101 LvArray::tensorOps::scale< 3 >( centroid, 1.0 / numPoints );
104 LvArray::tensorOps::subtract< 3 >( v0, points[ 0 ] );
105 LvArray::tensorOps::normalize< 3 >( v0 );
112 LvArray::tensorOps::subtract< 3 >( v, points[ a ] );
113 real64 const dot = LvArray::tensorOps::AiBi< 3 >( v, v0 );
123 std::sort( indices.begin(), indices.end(), [&](
int i,
int j ) {
return angle[ i ] < angle[ j ]; } );
129 LvArray::tensorOps::copy< 3 >( orderedPoints[ a ], points[ indices[ a ] ] );
134 LvArray::tensorOps::copy< 3 >( points[a], orderedPoints[a] );
145 template<
typename NORMAL_TYPE >
147 NORMAL_TYPE
const && normal )
155 LvArray::tensorOps::copy< 3 >( orderedPoints[a], points[a] );
165 LvArray::tensorOps::subtract< 3 >( v1, orderedPoints[ 0 ] );
166 LvArray::tensorOps::subtract< 3 >( v2, orderedPoints[ 0 ] );
168 real64 triangleNormal[ 3 ];
170 surfaceArea += LvArray::tensorOps::l2Norm< 3 >( triangleNormal );
173 return surfaceArea * 0.5;
190 template<
typename CENTER_TYPE,
typename NORMAL_TYPE >
195 CENTER_TYPE && center,
196 NORMAL_TYPE && normal,
197 real64 const areaTolerance = 0.0 )
200 LvArray::tensorOps::fill< 3 >( center, 0 );
201 LvArray::tensorOps::fill< 3 >( normal, 0 );
206 real64 v1[ 3 ], v2[ 3 ], vc[ 3 ];
208 LvArray::tensorOps::copy< 3 >( v1, points[ pointsIndices[ a + 1 ] ] );
209 LvArray::tensorOps::copy< 3 >( v2, points[ pointsIndices[ a + 2 ] ] );
211 LvArray::tensorOps::copy< 3 >( vc, points[ pointsIndices[ 0 ] ] );
212 LvArray::tensorOps::add< 3 >( vc, v1 );
213 LvArray::tensorOps::add< 3 >( vc, v2 );
215 LvArray::tensorOps::subtract< 3 >( v1, points[ pointsIndices[ 0 ] ] );
216 LvArray::tensorOps::subtract< 3 >( v2, points[ pointsIndices[ 0 ] ] );
218 real64 triangleNormal[ 3 ];
220 real64 const triangleArea = LvArray::tensorOps::l2Norm< 3 >( triangleNormal );
222 LvArray::tensorOps::add< 3 >( normal, triangleNormal );
224 area += triangleArea;
225 LvArray::tensorOps::scaledAdd< 3 >( center, vc, triangleArea );
227 if( area > areaTolerance )
229 LvArray::tensorOps::scale< 3 >( center, 1.0 / ( area * 3.0 ) );
230 LvArray::tensorOps::normalize< 3 >( normal );
233 else if( area < -areaTolerance )
237 GEOSX_LOG_RANK(
"Points: " << points[ pointsIndices[ a ] ] <<
" " << pointsIndices[ a ] );
254 template<
typename NORMAL_TYPE >
258 real64 const orientationTolerance = 10 * machinePrecision;
262 if( normal[ 2 ] <= -orientationTolerance )
264 LvArray::tensorOps::scale< 3 >( normal, -1.0 );
266 else if( std::fabs( normal[ 2 ] ) < orientationTolerance )
269 if( normal[ 1 ] <= -orientationTolerance )
271 LvArray::tensorOps::scale< 3 >( normal, -1.0 );
273 else if( fabs( normal[ 1 ] ) < orientationTolerance )
276 if( normal[ 0 ] <= -orientationTolerance )
278 LvArray::tensorOps::scale< 3 >( normal, -1.0 );
291 template<
typename NORMAL_TYPE,
typename MATRIX_TYPE >
294 MATRIX_TYPE && rotationMatrix )
296 real64 m1[ 3 ] = { normal[ 2 ], 0.0, -normal[ 0 ] };
297 real64 m2[ 3 ] = { 0.0, normal[ 2 ], -normal[ 1 ] };
298 real64 const norm_m1 = LvArray::tensorOps::l2Norm< 3 >( m1 );
299 real64 const norm_m2 = LvArray::tensorOps::l2Norm< 3 >( m2 );
303 if( norm_m1+1.e+2*machinePrecision > norm_m2 )
306 LvArray::tensorOps::normalize< 3 >( m2 );
307 LvArray::tensorOps::normalize< 3 >( m1 );
312 LvArray::tensorOps::scale< 3 >( m1, -1 );
313 LvArray::tensorOps::normalize< 3 >( m1 );
314 LvArray::tensorOps::normalize< 3 >( m2 );
318 rotationMatrix( 0, 0 ) = normal[ 0 ];
319 rotationMatrix( 1, 0 ) = normal[ 1 ];
320 rotationMatrix( 2, 0 ) = normal[ 2 ];
321 rotationMatrix( 0, 1 ) = m1[ 0 ];
322 rotationMatrix( 1, 1 ) = m1[ 1 ];
323 rotationMatrix( 2, 1 ) = m1[ 2 ];
324 rotationMatrix( 0, 2 ) = m2[ 0 ];
325 rotationMatrix( 1, 2 ) = m2[ 1 ];
326 rotationMatrix( 2, 2 ) = m2[ 2 ];
328 GEOSX_ERROR_IF( fabs( LvArray::tensorOps::determinant< 3 >( rotationMatrix ) - 1.0 ) > 1.e+1 * machinePrecision,
329 "Rotation matrix with determinant different from +1.0" );
338 template<
typename T >
343 return (T( 0 ) < val) - (val < T( 0 ));
360 template<
typename POINT_TYPE >
364 POINT_TYPE
const & point,
365 real64 const areaTolerance = 0.0 )
367 localIndex const numFaces = faceNodeIndicies.size( 0 );
373 Centroid_3DPolygon( faceNodeIndicies[kf], nodeCoordinates, faceCenter, faceNormal, areaTolerance );
375 LvArray::tensorOps::subtract< 3 >( faceCenter, point );
376 int const s =
sign( LvArray::tensorOps::AiBi< 3 >( faceNormal, faceCenter ) );
379 if( prev_sign * s < 0 )
398 template<
typename VEC_TYPE >
403 VEC_TYPE && boxDims )
408 LvArray::NumericLimits< real64 >::max };
416 localIndex const id = pointIndices( elemIndex, a );
419 minCoords[ d ] = fmin( minCoords[ d ], pointCoordinates(
id, d ) );
420 boxDims[ d ] = fmax( boxDims[ d ], pointCoordinates(
id, d ) );
424 LvArray::tensorOps::subtract< 3 >( boxDims, minCoords );
437 LvArray::tensorOps::subtract< 3 >( X7_X1, X[1] );
440 LvArray::tensorOps::subtract< 3 >( X6_X0, X[0] );
443 LvArray::tensorOps::subtract< 3 >( X7_X2, X[2] );
446 LvArray::tensorOps::subtract< 3 >( X3_X0, X[0] );
449 LvArray::tensorOps::subtract< 3 >( X5_X0, X[0] );
452 LvArray::tensorOps::subtract< 3 >( X7_X4, X[4] );
455 LvArray::tensorOps::add< 3 >( X7_X1plusX6_X0, X6_X0 );
458 LvArray::tensorOps::add< 3 >( X7_X2plusX5_X0, X5_X0 );
461 LvArray::tensorOps::add< 3 >( X7_X4plusX3_X0, X3_X0 );
463 real64 X7_X2crossX3_X0[3];
466 real64 X7_X2plusX5_X0crossX7_X4[3];
469 real64 X5_X0crossX7_X4plusX3_X0[3];
472 return 1.0/12.0 * ( LvArray::tensorOps::AiBi< 3 >( X7_X1plusX6_X0, X7_X2crossX3_X0 ) +
473 LvArray::tensorOps::AiBi< 3 >( X6_X0, X7_X2plusX5_X0crossX7_X4 ) +
474 LvArray::tensorOps::AiBi< 3 >( X7_X1, X5_X0crossX7_X4plusX3_X0 ) );
487 LvArray::tensorOps::subtract< 3 >( X1_X0, X[0] );
490 LvArray::tensorOps::subtract< 3 >( X2_X0, X[0] );
493 LvArray::tensorOps::subtract< 3 >( X3_X0, X[0] );
495 real64 X2_X0crossX3_X0[ 3 ];
498 return std::fabs( LvArray::tensorOps::AiBi< 3 >( X1_X0, X2_X0crossX3_X0 ) / 6.0 );
#define GEOSX_HOST_DEVICE
Marks a host-device function.
Contains functions for outputting array objects.
#define LVARRAY_TENSOROPS_INIT_LOCAL_3(EXP)
Create an initializer list of length 3 from EXP.
This class serves to provide a sliced multidimensional interface to the family of LvArray classes...
void orderPointsCCW(arrayView2d< real64 > const &points, NORMAL_TYPE const &normal)
Reorder a set of points counter-clockwise.
INDEX_TYPE size() const noexcept
GEOSX_HOST_DEVICE void FixNormalOrientation_3D(NORMAL_TYPE &&normal)
Change the orientation of the input vector to be consistent in a global sense.
This class serves to provide a "view" of a multidimensional array.
GEOSX_HOST_DEVICE real64 WedgeVolume(real64 const X[][3])
Compute the volume of a wedge.
double real64
64-bit floating point type.
GEOSX_HOST_DEVICE void RotationMatrix_3D(NORMAL_TYPE const &normal, MATRIX_TYPE &&rotationMatrix)
Calculate the rotation matrix for a face in the 3D space.
GEOSX_HOST_DEVICE GEOSX_FORCE_INLINE int sign(T const val)
Return the sign of a given value as an integer.
constexpr INDEX_TYPE size() const noexcept
#define GEOSX_ERROR(msg)
Raise a hard error and terminate the program.
A wrapper for the std::numeric_limits< T > member functions, this allows their values to be used on d...
#define GEOSX_FORCE_INLINE
Marks a function or lambda for inlining.
std::ptrdiff_t localIndex
Local index type (for indexing objects within an MPI partition).
#define GEOSX_LOG_RANK(msg)
Log a message to the rank output stream.
constexpr void crossProduct(DST_VECTOR &&LVARRAY_RESTRICT_REF dstVector, VECTOR_A const &LVARRAY_RESTRICT_REF vectorA, VECTOR_B const &LVARRAY_RESTRICT_REF vectorB)
Compute the cross product of vectorA and vectorB and put it in dstVector.
GEOSX_HOST_DEVICE GEOSX_FORCE_INLINE real64 Centroid_3DPolygon(arraySlice1d< localIndex const > const pointsIndices, arrayView2d< real64 const, nodes::REFERENCE_POSITION_USD > const &points, CENTER_TYPE &¢er, NORMAL_TYPE &&normal, real64 const areaTolerance=0.0)
Calculate the centroid of a convex 3D polygon as well as the normal and the rotation matrix...
real64 ComputeSurfaceArea(arrayView2d< real64 const > const &points, NORMAL_TYPE const &&normal)
Calculate the area of a polygon given the set of points in ccw order defining it. ...
GEOSX_HOST_DEVICE bool IsPointInsidePolyhedron(arrayView2d< real64 const, nodes::REFERENCE_POSITION_USD > const &nodeCoordinates, array1d< array1d< localIndex > > const &faceNodeIndicies, POINT_TYPE const &point, real64 const areaTolerance=0.0)
Check if a point is inside a convex polyhedron (3D polygon)
#define GEOSX_ERROR_IF(EXP, msg)
Conditionally raise a hard error and terminate the program.
GEOSX_HOST_DEVICE real64 TetVolume(real64 const X[][3])
Compute the volume of an tetrahedron.
GEOSX_HOST_DEVICE real64 PyramidVolume(real64 const X[][3])
Compute the volume of a pyramid.
void LinePlaneIntersection(LINEDIR_TYPE const &lineDir, POINT_TYPE const &linePoint, NORMAL_TYPE const &planeNormal, ORIGIN_TYPE const &planeOrigin, INTPOINT_TYPE &intersectionPoint)
Calculate the intersection between a line and a plane.
This class provides a fixed dimensional resizeable array interface in addition to an interface simila...
GEOSX_HOST_DEVICE real64 HexVolume(real64 const X[][3])
Compute the volume of an hexahedron.
#define GEOSX_ERROR_IF_LT(lhs, rhs)
Raise a hard error if one value compares less than the other.
GEOSX_HOST_DEVICE void GetBoundingBox(localIndex const elemIndex, arrayView2d< localIndex const, cells::NODE_MAP_USD > const &pointIndices, arrayView2d< real64 const, nodes::REFERENCE_POSITION_USD > const &pointCoordinates, VEC_TYPE &&boxDims)
Compute the dimensions of the bounding box containing the element defined here by the coordinates of ...
constexpr real64 machinePrecision
Machine epsilon for double-precision calculations.
float atan2(float const y, float const x)