MOAB: Mesh Oriented datABase
(version 5.4.1)
|
#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 (double *A, double *B, double *C, double Radius) |
double | area_spherical_triangle (double *A, double *B, double *C, double Radius) |
double | area_spherical_polygon (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 (double *ptA, double *ptB, double *ptC, double Radius) |
double | area_spherical_polygon_lHuiller (double *A, int N, double Radius, int *sign=NULL) |
double | area_spherical_triangle_girard (double *A, double *B, double *C, double Radius) |
double | area_spherical_polygon_girard (double *A, int N, double Radius) |
Private Attributes | |
AreaMethod | m_eAreaMethod |
Definition at line 208 of file IntxUtils.hpp.
Definition at line 211 of file IntxUtils.hpp.
{ lHuiller = 0, Girard = 1, GaussQuadrature = 2 };
moab::IntxAreaUtils::IntxAreaUtils | ( | AreaMethod | p_eAreaMethod = lHuiller | ) | [inline] |
Definition at line 218 of file IntxUtils.hpp.
: m_eAreaMethod( p_eAreaMethod ) {}
moab::IntxAreaUtils::~IntxAreaUtils | ( | ) | [inline] |
Definition at line 220 of file IntxUtils.hpp.
{}
double moab::IntxAreaUtils::area_on_sphere | ( | Interface * | mb, |
EntityHandle | set, | ||
double | R | ||
) |
Definition at line 1018 of file IntxUtils.cpp.
References area_spherical_element(), moab::Range::begin(), moab::Range::end(), ErrorCode, moab::Interface::get_entities_by_dimension(), ie, MB_CHK_ERR_RET_VAL, MB_SUCCESS, moab::Range::size(), moab::Interface::tag_get_data(), and moab::Interface::tag_get_handle().
Referenced by main(), test_intx_in_parallel_elem_based(), and test_intx_mpas().
{ // Get all entities of dimension 2 Range inputRange; ErrorCode rval = mb->get_entities_by_dimension( set, 2, inputRange );MB_CHK_ERR_RET_VAL( rval, -1.0 ); // Filter by elements that are owned by current process std::vector< int > ownerinfo( inputRange.size(), -1 ); Tag intxOwnerTag; rval = mb->tag_get_handle( "ORIG_PROC", intxOwnerTag ); if( MB_SUCCESS == rval ) { rval = mb->tag_get_data( intxOwnerTag, inputRange, &ownerinfo[0] );MB_CHK_ERR_RET_VAL( rval, -1.0 ); } // compare total area with 4*M_PI * R^2 int ie = 0; double total_area = 0.; for( Range::iterator eit = inputRange.begin(); eit != inputRange.end(); ++eit ) { // All zero/positive owner data represents ghosted elems if( ownerinfo[ie++] >= 0 ) continue; EntityHandle eh = *eit; const double elem_area = this->area_spherical_element( mb, eh, R ); // check whether the area of the spherical element is positive. assert( elem_area > 0 ); // sum up the contribution total_area += elem_area; } // return total mesh area return total_area; }
double moab::IntxAreaUtils::area_spherical_element | ( | Interface * | mb, |
EntityHandle | elem, | ||
double | R | ||
) |
Definition at line 1056 of file IntxUtils.cpp.
References area_spherical_polygon(), ErrorCode, moab::Interface::get_connectivity(), moab::Interface::get_coords(), and MB_CHK_ERR_RET_VAL.
Referenced by area_on_sphere(), and moab::Intx2MeshOnSphere::update_tracer_data().
{ // get the nodes, then the coordinates const EntityHandle* verts; int nsides; ErrorCode rval = mb->get_connectivity( elem, verts, nsides );MB_CHK_ERR_RET_VAL( rval, -1.0 ); // account for possible padded polygons while( verts[nsides - 2] == verts[nsides - 1] && nsides > 3 ) nsides--; // get coordinates std::vector< double > coords( 3 * nsides ); rval = mb->get_coords( verts, nsides, &coords[0] );MB_CHK_ERR_RET_VAL( rval, -1.0 ); // compute and return the area of the polygonal element return area_spherical_polygon( &coords[0], nsides, R ); }
double moab::IntxAreaUtils::area_spherical_polygon | ( | double * | A, |
int | N, | ||
double | Radius, | ||
int * | sign = NULL |
||
) |
Definition at line 849 of file IntxUtils.cpp.
References area_spherical_polygon_girard(), area_spherical_polygon_lHuiller(), GaussQuadrature, Girard, lHuiller, and m_eAreaMethod.
Referenced by add_field_value(), area_spherical_element(), and main().
{ switch( m_eAreaMethod ) { case Girard: return area_spherical_polygon_girard( A, N, Radius ); #ifdef MOAB_HAVE_TEMPESTREMAP case GaussQuadrature: return area_spherical_polygon_GQ( A, N, Radius ); #endif case lHuiller: default: return area_spherical_polygon_lHuiller( A, N, Radius, sign ); } }
double moab::IntxAreaUtils::area_spherical_polygon_girard | ( | double * | A, |
int | N, | ||
double | Radius | ||
) | [private] |
Definition at line 879 of file IntxUtils.cpp.
References moab::IntxUtils::oriented_spherical_angle().
Referenced by area_spherical_polygon().
{ // this should work for non-convex polygons too // assume that the A, A+3, ..., A+3*(N-1) are the coordinates // if( N <= 2 ) return 0.; double sum_angles = 0.; for( int i = 0; i < N; i++ ) { int i1 = ( i + 1 ) % N; int i2 = ( i + 2 ) % N; sum_angles += IntxUtils::oriented_spherical_angle( A + 3 * i, A + 3 * i1, A + 3 * i2 ); } double correction = sum_angles - ( N - 2 ) * M_PI; return Radius * Radius * correction; }
double moab::IntxAreaUtils::area_spherical_polygon_lHuiller | ( | double * | A, |
int | N, | ||
double | Radius, | ||
int * | sign = NULL |
||
) | [private] |
Definition at line 896 of file IntxUtils.cpp.
References area_spherical_triangle_lHuiller().
Referenced by area_spherical_polygon().
{ // This should work for non-convex polygons too // In the input vector A, assume that the A, A+3, ..., A+3*(N-1) are the coordinates // We also assume that the orientation is positive; // If negative orientation, the area will be negative if( N <= 2 ) return 0.; int lsign = 1; // assume positive orientain double area = 0.; for( int i = 1; i < N - 1; i++ ) { int i1 = i + 1; double areaTriangle = area_spherical_triangle_lHuiller( A, A + 3 * i, A + 3 * i1, Radius ); if( areaTriangle < 0 ) lsign = -1; // signal that we have at least one triangle with negative orientation ; // possible nonconvex polygon area += areaTriangle; } if( sign ) *sign = lsign; return area; }
double moab::IntxAreaUtils::area_spherical_triangle | ( | double * | A, |
double * | B, | ||
double * | C, | ||
double | Radius | ||
) |
Definition at line 833 of file IntxUtils.cpp.
References area_spherical_triangle_girard(), area_spherical_triangle_lHuiller(), GaussQuadrature, Girard, lHuiller, and m_eAreaMethod.
{ switch( m_eAreaMethod ) { case Girard: return area_spherical_triangle_girard( A, B, C, Radius ); #ifdef MOAB_HAVE_TEMPESTREMAP case GaussQuadrature: return area_spherical_triangle_GQ( A, B, C, Radius ); #endif case lHuiller: default: return area_spherical_triangle_lHuiller( A, B, C, Radius ); } }
double moab::IntxAreaUtils::area_spherical_triangle_girard | ( | double * | A, |
double * | B, | ||
double * | C, | ||
double | Radius | ||
) | [private] |
Definition at line 865 of file IntxUtils.cpp.
References spherical_angle().
Referenced by area_spherical_triangle().
{ double correction = spherical_angle( A, B, C, Radius ) + spherical_angle( B, C, A, Radius ) + spherical_angle( C, A, B, Radius ) - M_PI; double area = Radius * Radius * correction; // now, is it negative or positive? is it pointing toward the center or outward? CartVect a( A ), b( B ), c( C ); CartVect abc = ( b - a ) * ( c - a ); if( abc % a > 0 ) // dot product positive, means ABC points out return area; else return -area; }
double moab::IntxAreaUtils::area_spherical_triangle_lHuiller | ( | double * | ptA, |
double * | ptB, | ||
double * | ptC, | ||
double | Radius | ||
) | [private] |
Definition at line 980 of file IntxUtils.cpp.
References moab::angle(), moab::E, and Radius.
Referenced by area_spherical_polygon_lHuiller(), and area_spherical_triangle().
{ // now, a is angle BOC, O is origin CartVect vA( ptA ), vB( ptB ), vC( ptC ); double a = angle( vB, vC ); double b = angle( vC, vA ); double c = angle( vA, vB ); int sign = 1; if( ( vA * vB ) % vC < 0 ) sign = -1; double s = ( a + b + c ) / 2; double tmp = tan( s / 2 ) * tan( ( s - a ) / 2 ) * tan( ( s - b ) / 2 ) * tan( ( s - c ) / 2 ); if( tmp < 0. ) tmp = 0.; double E = 4 * atan( sqrt( tmp ) ); if( E != E ) std::cout << " NaN at spherical triangle area \n"; double area = sign * E * Radius * Radius; #ifdef CHECKNEGATIVEAREA if( area < 0 ) { std::cout << "negative area: " << area << "\n"; std::cout << std::setprecision( 15 ); std::cout << "vA: " << vA << "\n"; std::cout << "vB: " << vB << "\n"; std::cout << "vC: " << vC << "\n"; std::cout << "sign: " << sign << "\n"; std::cout << " a: " << a << "\n"; std::cout << " b: " << b << "\n"; std::cout << " c: " << c << "\n"; } #endif return area; }
ErrorCode moab::IntxAreaUtils::positive_orientation | ( | Interface * | mb, |
EntityHandle | set, | ||
double | R | ||
) |
Definition at line 1272 of file IntxUtils.cpp.
References moab::IntxUtils::area2D(), moab::Range::begin(), moab::Range::end(), ErrorCode, moab::Interface::get_connectivity(), moab::Interface::get_coords(), moab::Interface::get_entities_by_dimension(), MB_SUCCESS, and moab::Interface::set_connectivity().
Referenced by moab::TempestRemapper::ComputeOverlapMesh(), and main().
{ Range cells2d; ErrorCode rval = mb->get_entities_by_dimension( set, 2, cells2d ); if( MB_SUCCESS != rval ) return rval; for( Range::iterator qit = cells2d.begin(); qit != cells2d.end(); ++qit ) { EntityHandle cell = *qit; const EntityHandle* conn = NULL; int num_nodes = 0; rval = mb->get_connectivity( cell, conn, num_nodes ); if( MB_SUCCESS != rval ) return rval; if( num_nodes < 3 ) return MB_FAILURE; double coords[9]; rval = mb->get_coords( conn, 3, coords ); if( MB_SUCCESS != rval ) return rval; double area; if( R > 0 ) area = area_spherical_triangle_lHuiller( coords, coords + 3, coords + 6, R ); else area = IntxUtils::area2D( coords, coords + 3, coords + 6 ); if( area < 0 ) { // compute all area, do not revert if total area is positive std::vector< double > coords2( 3 * num_nodes ); // get coordinates rval = mb->get_coords( conn, num_nodes, &coords2[0] ); if( MB_SUCCESS != rval ) return MB_FAILURE; double totArea = area_spherical_polygon_lHuiller( &coords2[0], num_nodes, R ); if( totArea < 0 ) { std::vector< EntityHandle > newconn( num_nodes ); for( int i = 0; i < num_nodes; i++ ) { newconn[num_nodes - 1 - i] = conn[i]; } rval = mb->set_connectivity( cell, &newconn[0], num_nodes ); if( MB_SUCCESS != rval ) return rval; } else { std::cout << " nonconvex problem first area:" << area << " total area: " << totArea << std::endl; } } } return MB_SUCCESS; }
double moab::IntxAreaUtils::spherical_angle | ( | double * | A, |
double * | B, | ||
double * | C, | ||
double | Radius | ||
) |
Definition at line 795 of file IntxUtils.cpp.
References moab::angle(), moab::CartVect::length_squared(), and Radius.
Referenced by area_spherical_triangle_girard().
{ // the angle by definition is between the planes OAB and OBC CartVect a( A ); CartVect b( B ); CartVect c( C ); double err1 = a.length_squared() - Radius * Radius; if( fabs( err1 ) > 0.0001 ) { std::cout << " error in input " << a << " radius: " << Radius << " error:" << err1 << "\n"; } CartVect normalOAB = a * b; CartVect normalOCB = c * b; return angle( normalOAB, normalOCB ); }
AreaMethod moab::IntxAreaUtils::m_eAreaMethod [private] |
Definition at line 268 of file IntxUtils.hpp.
Referenced by area_spherical_polygon(), and area_spherical_triangle().