Mesh Oriented datABase  (version 5.6.0)
An array-based unstructured mesh library
moab::IntxAreaUtils Class Reference

#include <IntxUtils.hpp>

Public Types

enum  AreaMethod { lHuiller = 0 , Girard = 1 , GaussQuadrature = 2 }
 

Public Member Functions

 IntxAreaUtils (AreaMethod p_eAreaMethod=lHuiller)
 
 ~IntxAreaUtils ()
 
double spherical_angle (const double *A, const double *B, const double *C, double Radius)
 
double area_spherical_triangle (const double *A, const double *B, const double *C, double Radius)
 
double area_spherical_polygon (const double *A, int N, double Radius, int *sign=NULL)
 
double area_spherical_element (Interface *mb, EntityHandle elem, double R)
 
double area_on_sphere (Interface *mb, EntityHandle set, double R)
 
ErrorCode positive_orientation (Interface *mb, EntityHandle set, double R)
 

Private Member Functions

double area_spherical_triangle_lHuiller (const double *ptA, const double *ptB, const double *ptC, double Radius)
 
double area_spherical_polygon_lHuiller (const double *A, int N, double Radius, int *sign=NULL)
 
double area_spherical_triangle_girard (const double *A, const double *B, const double *C, double Radius)
 
double area_spherical_polygon_girard (const double *A, int N, double Radius)
 

Private Attributes

AreaMethod m_eAreaMethod
 

Detailed Description

Definition at line 232 of file IntxUtils.hpp.

Member Enumeration Documentation

◆ AreaMethod

Enumerator
lHuiller 
Girard 
GaussQuadrature 

Definition at line 235 of file IntxUtils.hpp.

236  {
237  lHuiller = 0,
238  Girard = 1,
239  GaussQuadrature = 2
240  };

Constructor & Destructor Documentation

◆ IntxAreaUtils()

moab::IntxAreaUtils::IntxAreaUtils ( AreaMethod  p_eAreaMethod = lHuiller)
inline

Definition at line 242 of file IntxUtils.hpp.

242 : m_eAreaMethod( p_eAreaMethod ) {}

◆ ~IntxAreaUtils()

moab::IntxAreaUtils::~IntxAreaUtils ( )
inline

Definition at line 244 of file IntxUtils.hpp.

244 {}

Member Function Documentation

◆ area_on_sphere()

double moab::IntxAreaUtils::area_on_sphere ( Interface mb,
EntityHandle  set,
double  R 
)

Definition at line 1484 of file IntxUtils.cpp.

1485 {
1486  // Get all entities of dimension 2
1487  Range inputRange;
1488  ErrorCode rval = mb->get_entities_by_dimension( set, 2, inputRange );MB_CHK_ERR_RET_VAL( rval, -1.0 );
1489 
1490  // Filter by elements that are owned by current process
1491  std::vector< int > ownerinfo( inputRange.size(), -1 );
1492  Tag intxOwnerTag;
1493  rval = mb->tag_get_handle( "ORIG_PROC", intxOwnerTag );
1494  if( MB_SUCCESS == rval )
1495  {
1496  rval = mb->tag_get_data( intxOwnerTag, inputRange, &ownerinfo[0] );MB_CHK_ERR_RET_VAL( rval, -1.0 );
1497  }
1498 
1499  // compare total area with 4*M_PI * R^2
1500  int ie = 0;
1501  double total_area = 0.;
1502  for( Range::iterator eit = inputRange.begin(); eit != inputRange.end(); ++eit )
1503  {
1504 
1505  // All zero/positive owner data represents ghosted elems
1506  if( ownerinfo[ie++] >= 0 ) continue;
1507 
1508  EntityHandle eh = *eit;
1509  const double elem_area = this->area_spherical_element( mb, eh, R );
1510 
1511  // check whether the area of the spherical element is positive.
1512  if( elem_area <= 0 )
1513  {
1514  std::cout << "Area of element " << mb->id_from_handle( eh ) << " is = " << elem_area << "\n";
1515  mb->list_entity( eh );
1516  }
1517  assert( elem_area > 0 );
1518 
1519  // sum up the contribution
1520  total_area += elem_area;
1521  }
1522 
1523  // return total mesh area
1524  return total_area;
1525 }

References area_spherical_element(), moab::Range::begin(), moab::Range::end(), ErrorCode, mb, MB_CHK_ERR_RET_VAL, MB_SUCCESS, moab::R, and moab::Range::size().

Referenced by main().

◆ area_spherical_element()

double moab::IntxAreaUtils::area_spherical_element ( Interface mb,
EntityHandle  elem,
double  R 
)

Definition at line 1527 of file IntxUtils.cpp.

1528 {
1529  // get the nodes, then the coordinates
1530  const EntityHandle* verts;
1531  int nsides;
1532  ErrorCode rval = mb->get_connectivity( elem, verts, nsides );MB_CHK_ERR_RET_VAL( rval, -1.0 );
1533 
1534  // account for possible padded polygons
1535  while( verts[nsides - 2] == verts[nsides - 1] && nsides > 3 )
1536  nsides--;
1537 
1538  // get coordinates
1539  std::vector< double > coords( 3 * nsides );
1540  rval = mb->get_coords( verts, nsides, &coords[0] );MB_CHK_ERR_RET_VAL( rval, -1.0 );
1541 
1542  // compute and return the area of the polygonal element
1543  return area_spherical_polygon( &coords[0], nsides, R );
1544 }

References area_spherical_polygon(), ErrorCode, mb, MB_CHK_ERR_RET_VAL, and moab::R.

Referenced by area_on_sphere(), and moab::Intx2MeshOnSphere::update_tracer_data().

◆ area_spherical_polygon()

double moab::IntxAreaUtils::area_spherical_polygon ( const double *  A,
int  N,
double  Radius,
int *  sign = NULL 
)

Definition at line 1195 of file IntxUtils.cpp.

1196 {
1197  switch( m_eAreaMethod )
1198  {
1199  case Girard:
1200  return area_spherical_polygon_girard( A, N, Radius );
1201 #ifdef MOAB_HAVE_TEMPESTREMAP
1202  case GaussQuadrature:
1203  return area_spherical_polygon_GQ( A, N ) * Radius * Radius; //area_spherical_polygon_GQ normalizes
1204 #endif
1205  case lHuiller:
1206  default:
1207  return area_spherical_polygon_lHuiller( A, N, Radius, sign );
1208  }
1209 }

References area_spherical_polygon_girard(), area_spherical_polygon_lHuiller(), GaussQuadrature, Girard, lHuiller, and m_eAreaMethod.

Referenced by area_spherical_element(), moab::Intx2MeshEdges::EdgeSplits(), and main().

◆ area_spherical_polygon_girard()

double moab::IntxAreaUtils::area_spherical_polygon_girard ( const double *  A,
int  N,
double  Radius 
)
private

Definition at line 1225 of file IntxUtils.cpp.

1226 {
1227  // this should work for non-convex polygons too
1228  // assume that the A, A+3, ..., A+3*(N-1) are the coordinates
1229  //
1230  if( N <= 2 ) return 0.;
1231  double sum_angles = 0.;
1232  for( int i = 0; i < N; i++ )
1233  {
1234  int i1 = ( i + 1 ) % N;
1235  int i2 = ( i + 2 ) % N;
1236  sum_angles += IntxUtils::oriented_spherical_angle( A + 3 * i, A + 3 * i1, A + 3 * i2 );
1237  }
1238  double correction = sum_angles - ( N - 2 ) * M_PI;
1239  return Radius * Radius * correction;
1240 }

References moab::IntxUtils::oriented_spherical_angle().

Referenced by area_spherical_polygon().

◆ area_spherical_polygon_lHuiller()

double moab::IntxAreaUtils::area_spherical_polygon_lHuiller ( const double *  A,
int  N,
double  Radius,
int *  sign = NULL 
)
private

Definition at line 1242 of file IntxUtils.cpp.

1243 {
1244  // This should work for non-convex polygons too
1245  // In the input vector A, assume that the A, A+3, ..., A+3*(N-1) are the coordinates
1246  // We also assume that the orientation is positive;
1247  // If negative orientation, the area will be negative
1248  if( N <= 2 ) return 0.;
1249 
1250  int lsign = 1; // assume positive orientain
1251  double area = 0.;
1252  for( int i = 1; i < N - 1; i++ )
1253  {
1254  int i1 = i + 1;
1255  double areaTriangle = area_spherical_triangle_lHuiller( A, A + 3 * i, A + 3 * i1, Radius );
1256  if( areaTriangle < 0 ) lsign = -1; // signal that we have at least one triangle with negative orientation ;
1257  // possible nonconvex polygon
1258  area += areaTriangle;
1259  }
1260  if( sign ) *sign = lsign;
1261 
1262  return area;
1263 }

References area_spherical_triangle_lHuiller().

Referenced by area_spherical_polygon(), and positive_orientation().

◆ area_spherical_triangle()

double moab::IntxAreaUtils::area_spherical_triangle ( const double *  A,
const double *  B,
const double *  C,
double  Radius 
)

Definition at line 1179 of file IntxUtils.cpp.

1180 {
1181  switch( m_eAreaMethod )
1182  {
1183  case Girard:
1184  return area_spherical_triangle_girard( A, B, C, Radius );
1185 #ifdef MOAB_HAVE_TEMPESTREMAP
1186  case GaussQuadrature:
1187  return area_spherical_triangle_GQ( A, B, C );
1188 #endif
1189  case lHuiller:
1190  default:
1191  return area_spherical_triangle_lHuiller( A, B, C, Radius );
1192  }
1193 }

References area_spherical_triangle_girard(), area_spherical_triangle_lHuiller(), GaussQuadrature, Girard, lHuiller, and m_eAreaMethod.

Referenced by moab::Intx2MeshOnSphere::findNodes().

◆ area_spherical_triangle_girard()

double moab::IntxAreaUtils::area_spherical_triangle_girard ( const double *  A,
const double *  B,
const double *  C,
double  Radius 
)
private

Definition at line 1211 of file IntxUtils.cpp.

1212 {
1213  double correction = spherical_angle( A, B, C, Radius ) + spherical_angle( B, C, A, Radius ) +
1214  spherical_angle( C, A, B, Radius ) - M_PI;
1215  double area = Radius * Radius * correction;
1216  // now, is it negative or positive? is it pointing toward the center or outward?
1217  CartVect a( A ), b( B ), c( C );
1218  CartVect abc = ( b - a ) * ( c - a );
1219  if( abc % a > 0 ) // dot product positive, means ABC points out
1220  return area;
1221  else
1222  return -area;
1223 }

References spherical_angle().

Referenced by area_spherical_triangle().

◆ area_spherical_triangle_lHuiller()

double moab::IntxAreaUtils::area_spherical_triangle_lHuiller ( const double *  ptA,
const double *  ptB,
const double *  ptC,
double  Radius 
)
private

Definition at line 1428 of file IntxUtils.cpp.

1432 {
1433 
1434  // now, a is angle BOC, O is origin
1435  CartVect vA( ptA ), vB( ptB ), vC( ptC );
1436  double a = angle_robust( vB, vC );
1437  double b = angle_robust( vC, vA );
1438  double c = angle_robust( vA, vB );
1439  int sign = 1;
1440  // if( fabs( ( vA * vB ) % vC ) < 1e-17 ) sign = -1;
1441  if( ( vA * vB ) % vC < 0 ) sign = -1;
1442  double s = ( a + b + c ) / 2;
1443  double a1 = ( s - a ) / 2;
1444  double b1 = ( s - b ) / 2;
1445  double c1 = ( s - c ) / 2;
1446 #ifdef MOAB_HAVE_TEMPESTREMAP
1447  if( fabs( a1 ) < 1.e-14 || fabs( b1 ) < 1.e-14 || fabs( c1 ) < 1.e-14 )
1448  {
1449  double area = area_spherical_triangle_GQ( ptA, ptB, ptC ) * sign;
1450 #ifdef VERBOSE
1451  std::cout << " very obtuse angle, use TR to compute area "
1452  << " a1:" << a1 << " b1:" << b1 << " c1:" << c1 << "\n";
1453  std::cout << " area with TR: " << area << "\n";
1454 #endif
1455  return area;
1456  }
1457 #endif
1458  double tmp = tan( s / 2 ) * tan( a1 ) * tan( b1 ) * tan( c1 );
1459  if( tmp < 0. ) tmp = 0.;
1460 
1461  double E = 4 * atan( sqrt( tmp ) );
1462  if( E != E ) std::cout << " NaN at spherical triangle area \n";
1463 
1464  double area = sign * E * Radius * Radius;
1465 
1466 #ifdef CHECKNEGATIVEAREA
1467  if( area < 0 )
1468  {
1469  std::cout << "negative area: " << area << "\n";
1470  std::cout << std::setprecision( 15 );
1471  std::cout << "vA: " << vA << "\n";
1472  std::cout << "vB: " << vB << "\n";
1473  std::cout << "vC: " << vC << "\n";
1474  std::cout << "sign: " << sign << "\n";
1475  std::cout << " a: " << a << "\n";
1476  std::cout << " b: " << b << "\n";
1477  std::cout << " c: " << c << "\n";
1478  }
1479 #endif
1480 
1481  return area;
1482 }

References moab::angle_robust(), and moab::E.

Referenced by area_spherical_polygon_lHuiller(), area_spherical_triangle(), and positive_orientation().

◆ positive_orientation()

ErrorCode moab::IntxAreaUtils::positive_orientation ( Interface mb,
EntityHandle  set,
double  R 
)

Definition at line 1744 of file IntxUtils.cpp.

1745 {
1746  Range cells2d;
1747  MB_CHK_ERR( mb->get_entities_by_dimension( set, 2, cells2d ) );
1748  for( Range::iterator qit = cells2d.begin(); qit != cells2d.end(); ++qit )
1749  {
1750  EntityHandle cell = *qit;
1751  const EntityHandle* conn = nullptr;
1752  int num_nodes = 0;
1753  MB_CHK_ERR( mb->get_connectivity( cell, conn, num_nodes ) );
1754  if( num_nodes < 3 ) return MB_FAILURE;
1755 
1756  double coords[9];
1757  MB_CHK_ERR( mb->get_coords( conn, 3, coords ) );
1758 
1759  double area;
1760  if( R > 0 )
1761  area = area_spherical_triangle_lHuiller( coords, coords + 3, coords + 6, R );
1762  else
1763  area = IntxUtils::area2D( coords, coords + 3, coords + 6 );
1764  if( area < 0 )
1765  {
1766  // compute all area, do not revert if total area is positive
1767  std::vector< double > coords2( 3 * num_nodes );
1768  // get coordinates
1769  MB_CHK_ERR( mb->get_coords( conn, num_nodes, &coords2[0] ) );
1770  double totArea = area_spherical_polygon_lHuiller( &coords2[0], num_nodes, R );
1771  if( totArea < 0 )
1772  {
1773  std::vector< EntityHandle > newconn( num_nodes );
1774  for( int i = 0; i < num_nodes; i++ )
1775  {
1776  newconn[num_nodes - 1 - i] = conn[i];
1777  }
1778  MB_CHK_ERR( mb->set_connectivity( cell, &newconn[0], num_nodes ) );
1779  }
1780  else
1781  {
1782  std::cout << " nonconvex problem first area:" << area << " total area: " << totArea << std::endl;
1783  }
1784  }
1785  }
1786  return MB_SUCCESS;
1787 }

References moab::IntxUtils::area2D(), area_spherical_polygon_lHuiller(), area_spherical_triangle_lHuiller(), moab::Range::begin(), moab::Range::end(), mb, MB_CHK_ERR, MB_SUCCESS, and moab::R.

Referenced by moab::TempestRemapper::ComputeOverlapMesh(), and main().

◆ spherical_angle()

double moab::IntxAreaUtils::spherical_angle ( const double *  A,
const double *  B,
const double *  C,
double  Radius 
)

Definition at line 1141 of file IntxUtils.cpp.

1142 {
1143  // the angle by definition is between the planes OAB and OBC
1144  CartVect a( A );
1145  CartVect b( B );
1146  CartVect c( C );
1147  double err1 = a.length_squared() - Radius * Radius;
1148  if( fabs( err1 ) > 0.0001 )
1149  {
1150  std::cout << " error in input " << a << " radius: " << Radius << " error:" << err1 << "\n";
1151  }
1152  CartVect normalOAB = a * b;
1153  CartVect normalOCB = c * b;
1154  return angle( normalOAB, normalOCB );
1155 }

References moab::angle(), and moab::CartVect::length_squared().

Referenced by area_spherical_triangle_girard().

Member Data Documentation

◆ m_eAreaMethod

AreaMethod moab::IntxAreaUtils::m_eAreaMethod
private

Definition at line 292 of file IntxUtils.hpp.

Referenced by area_spherical_polygon(), and area_spherical_triangle().


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