![]() |
Mesh Oriented datABase
(version 5.4.1)
Array-based unstructured mesh datastructure
|
00001 #ifndef MOAB_ELEM_UTIL_HPP
00002 #define MOAB_ELEM_UTIL_HPP
00003
00004 #include "moab/CartVect.hpp"
00005 #include
00006 #include "moab/Matrix3.hpp"
00007
00008 // to access data structures for spectral elements
00009
00010 extern "C" {
00011 #include "moab/FindPtFuncs.h"
00012 }
00013
00014 namespace moab
00015 {
00016 namespace ElemUtil
00017 {
00018
00019 bool nat_coords_trilinear_hex( const CartVect* hex_corners, const CartVect& x, CartVect& xi, double tol );
00020 bool point_in_trilinear_hex( const CartVect* hex_corners, const CartVect& xyz, double etol );
00021
00022 bool point_in_trilinear_hex( const CartVect* hex_corners,
00023 const CartVect& xyz,
00024 const CartVect& box_min,
00025 const CartVect& box_max,
00026 double etol );
00027
00028 // wrapper to hex_findpt
00029 void nat_coords_trilinear_hex2( const CartVect* hex_corners, const CartVect& x, CartVect& xi, double til );
00030
00031 void hex_findpt( double* xm[3], int n, CartVect xyz, CartVect& rst, double& dist );
00032
00033 void hex_eval( double* field, int n, CartVect rst, double& value );
00034
00035 bool integrate_trilinear_hex( const CartVect* hex_corners, double* corner_fields, double& field_val, int num_pts );
00036
00037 } // namespace ElemUtil
00038
00039 namespace Element
00040 {
00041 /**\brief Class representing a map (diffeomorphism) F parameterizing a 3D element by its
00042 * canonical preimage.*/
00043 /*
00044 Shape functions on the element can obtained by a pushforward (pullback by the inverse map)
00045 of the shape functions on the canonical element. This is done by extending this class.
00046
00047 We further assume that the parameterizing map is defined by the location of n vertices,
00048 which can be set and retrieved on a Map instance. The number of vertices is fixed at
00049 compile time.
00050 */
00051 class Map
00052 {
00053 public:
00054 /**\brief Construct a Map defined by the given std::vector of vertices. */
00055 Map( const std::vector< CartVect >& v )
00056 {
00057 this->vertex.resize( v.size() );
00058 this->set_vertices( v );
00059 };
00060 /**\brief Construct a Map defined by n vertices. */
00061 Map( const unsigned int n )
00062 {
00063 this->vertex = std::vector< CartVect >( n );
00064 };
00065 virtual ~Map();
00066 /**\brief Evaluate the map on \f$x_i\f$ (calculate \f$\vec x = F($\vec \xi)\f$ )*/
00067 virtual CartVect evaluate( const CartVect& xi ) const = 0;
00068 /**\brief Evaluate the inverse map (calculate \f$\vec \xi = F^-1($\vec x)\f$ to given
00069 * tolerance)*/
00070 virtual CartVect ievaluate( const CartVect& x, double tol = 1e-6, const CartVect& x0 = CartVect( 0.0 ) ) const;
00071 /**\brief decide if within the natural param space, with a tolerance*/
00072 virtual bool inside_nat_space( const CartVect& xi, double& tol ) const = 0;
00073 /* FIX: should evaluate and ievaluate return both the value and the Jacobian (first jet)? */
00074 /**\brief Evaluate the map's Jacobi matrix. */
00075 virtual Matrix3 jacobian( const CartVect& xi ) const = 0;
00076 /* FIX: should this be evaluated in real coordinates and be obtained as part of a Newton
00077 * solve? */
00078 /**\brief Evaluate the inverse of the Jacobi matrix. */
00079 virtual Matrix3 ijacobian( const CartVect& xi ) const
00080 {
00081 return this->jacobian( xi ).inverse();
00082 };
00083 /* det_jacobian and det_ijacobian should be overridden for efficiency. */
00084 /**\brief Evaluate the determinate of the Jacobi matrix. */
00085 virtual double det_jacobian( const CartVect& xi ) const
00086 {
00087 return this->jacobian( xi ).determinant();
00088 };
00089 /* FIX: should this be evaluated in real coordinates and be obtained as part of a Newton
00090 * solve? */
00091 /**\brief Evaluate the determinate of the inverse Jacobi matrix. */
00092 virtual double det_ijacobian( const CartVect& xi ) const
00093 {
00094 return this->jacobian( xi ).inverse().determinant();
00095 };
00096
00097 /**\brief Evaluate a scalar field at a point given field values at the vertices. */
00098 virtual double evaluate_scalar_field( const CartVect& xi, const double* field_vertex_values ) const = 0;
00099 /**\brief Integrate a scalar field over the element given field values at the vertices. */
00100 virtual double integrate_scalar_field( const double* field_vertex_values ) const = 0;
00101
00102 /**\brief Size of the vertices vector. */
00103 unsigned int size()
00104 {
00105 return this->vertex.size();
00106 }
00107 /**\brief Retrieve vertices. */
00108 const std::vector< CartVect >& get_vertices();
00109 /**\brief Set vertices. */
00110 virtual void set_vertices( const std::vector< CartVect >& v );
00111
00112 // will look at the box formed by vertex coordinates, and before doing any NR, bail out if
00113 // necessary
00114 virtual bool inside_box( const CartVect& xi, double& tol ) const;
00115
00116 /* Exception thrown when an evaluation fails (e.g., ievaluate fails to converge). */
00117 class EvaluationError
00118 {
00119 public:
00120 EvaluationError( const CartVect& x, const std::vector< CartVect >& verts ) : p( x ), vertices( verts )
00121 {
00122 #ifndef NDEBUG
00123 std::cout << "p:" << p << "\n vertices.size() " << vertices.size() << "\n";
00124 for( size_t i = 0; i < vertices.size(); i++ )
00125 std::cout << vertices[i] << "\n";
00126 #endif
00127 };
00128
00129 private:
00130 CartVect p;
00131 std::vector< CartVect > vertices;
00132 }; // class EvaluationError
00133
00134 /* Exception thrown when a bad argument is encountered. */
00135 class ArgError
00136 {
00137 public:
00138 ArgError(){};
00139 }; // class ArgError
00140 protected:
00141 std::vector< CartVect > vertex;
00142 }; // class Map
00143
00144 /**\brief Shape function space for trilinear hexahedron, obtained by a pushforward of the
00145 * canonical linear (affine) functions. */
00146 class LinearHex : public Map
00147 {
00148 public:
00149 LinearHex( const std::vector< CartVect >& vertices ) : Map( vertices ){};
00150 LinearHex();
00151 virtual ~LinearHex();
00152
00153 virtual CartVect evaluate( const CartVect& xi ) const;
00154 // virtual CartVect ievaluate(const CartVect& x, double tol) const ;
00155 virtual bool inside_nat_space( const CartVect& xi, double& tol ) const;
00156
00157 virtual Matrix3 jacobian( const CartVect& xi ) const;
00158 virtual double evaluate_scalar_field( const CartVect& xi, const double* field_vertex_values ) const;
00159 virtual double integrate_scalar_field( const double* field_vertex_values ) const;
00160
00161 protected:
00162 /* Preimages of the vertices -- "canonical vertices" -- are known as "corners". */
00163 static const double corner[8][3];
00164 static const double gauss[2][2];
00165 static const unsigned int corner_count = 8;
00166 static const unsigned int gauss_count = 2;
00167
00168 }; // class LinearHex
00169
00170 /**\brief Shape function space for trilinear hexahedron, obtained by a pushforward of the
00171 * canonical linear (affine) functions. */
00172 class QuadraticHex : public Map
00173 {
00174 public:
00175 QuadraticHex( const std::vector< CartVect >& vertices ) : Map( vertices ){};
00176 QuadraticHex();
00177 virtual ~QuadraticHex();
00178 virtual CartVect evaluate( const CartVect& xi ) const;
00179 // virtual CartVect ievaluate(const CartVect& x, double tol) const ;
00180 virtual bool inside_nat_space( const CartVect& xi, double& tol ) const;
00181
00182 virtual Matrix3 jacobian( const CartVect& xi ) const;
00183 virtual double evaluate_scalar_field( const CartVect& xi, const double* field_vertex_values ) const;
00184 virtual double integrate_scalar_field( const double* field_vertex_values ) const;
00185
00186 protected:
00187 /* Preimages of the vertices -- "canonical vertices" -- are known as "corners".
00188 * there are 27 vertices for a tri-quadratic xes*/
00189 static const int corner[27][3];
00190 static const double gauss[8][2]; // TODO fix me
00191 static const unsigned int corner_count = 27;
00192 static const unsigned int gauss_count = 2; // TODO fix me
00193
00194 }; // class QuadraticHex
00195 /**\brief Shape function space for a linear tetrahedron, obtained by a pushforward of the
00196 * canonical affine shape functions. */
00197 class LinearTet : public Map
00198 {
00199 public:
00200 LinearTet( const std::vector< CartVect >& vertices ) : Map( vertices )
00201 {
00202 set_vertices( vertex );
00203 };
00204 LinearTet();
00205 virtual ~LinearTet();
00206 /* Override the evaluation routines to take advantage of the properties of P1. */
00207 virtual CartVect evaluate( const CartVect& xi ) const
00208 {
00209 return this->vertex[0] + this->T * xi;
00210 };
00211 virtual CartVect ievaluate( const CartVect& x, double tol = 1e-6, const CartVect& x0 = CartVect( 0.0 ) ) const;
00212 virtual Matrix3 jacobian( const CartVect& ) const
00213 {
00214 return this->T;
00215 };
00216 virtual Matrix3 ijacobian( const CartVect& ) const
00217 {
00218 return this->T_inverse;
00219 };
00220 virtual double det_jacobian( const CartVect& ) const
00221 {
00222 return this->det_T;
00223 };
00224 virtual double det_ijacobian( const CartVect& ) const
00225 {
00226 return this->det_T_inverse;
00227 };
00228 //
00229 virtual double evaluate_scalar_field( const CartVect& xi, const double* field_vertex_values ) const;
00230 virtual double integrate_scalar_field( const double* field_vertex_values ) const;
00231 //
00232 /* Override set_vertices so we can precompute the matrices effecting the mapping to and from
00233 * the canonical simplex. */
00234 virtual void set_vertices( const std::vector< CartVect >& v );
00235 virtual bool inside_nat_space( const CartVect& xi, double& tol ) const;
00236
00237 protected:
00238 static const double corner[4][3];
00239 Matrix3 T, T_inverse;
00240 double det_T, det_T_inverse;
00241 }; // class LinearTet
00242
00243 class SpectralHex : public Map
00244 {
00245 public:
00246 SpectralHex( const std::vector< CartVect >& vertices ) : Map( vertices )
00247 {
00248 _xyz[0] = _xyz[1] = _xyz[2] = NULL;
00249 };
00250 SpectralHex( int order, double* x, double* y, double* z );
00251 SpectralHex( int order );
00252 SpectralHex();
00253 virtual ~SpectralHex();
00254 void set_gl_points( double* x, double* y, double* z );
00255 virtual CartVect evaluate( const CartVect& xi ) const;
00256 virtual CartVect ievaluate( const CartVect& x, double tol = 1e-6, const CartVect& x0 = CartVect( 0.0 ) ) const;
00257 virtual Matrix3 jacobian( const CartVect& xi ) const;
00258 double evaluate_scalar_field( const CartVect& xi, const double* field_vertex_values ) const;
00259 double integrate_scalar_field( const double* field_vertex_values ) const;
00260 bool inside_nat_space( const CartVect& xi, double& tol ) const;
00261
00262 // to compute the values that need to be cached for each element of order n
00263 void Init( int order );
00264 void freedata();
00265
00266 protected:
00267 /* values that depend only on the order of the element , cached */
00268 /* the order in 3 directions */
00269 static int _n;
00270 static realType* _z[3];
00271 static lagrange_data _ld[3];
00272 static opt_data_3 _data;
00273 static realType* _odwork; // work area
00274
00275 // flag for initialization of data
00276 static bool _init;
00277
00278 realType* _xyz[3];
00279
00280 }; // class SpectralHex
00281
00282 /**\brief Shape function space for bilinear quadrilateral, obtained from the canonical linear
00283 * (affine) functions. */
00284 class LinearQuad : public Map
00285 {
00286 public:
00287 LinearQuad( const std::vector< CartVect >& vertices ) : Map( vertices ){};
00288 LinearQuad();
00289 virtual ~LinearQuad();
00290 virtual CartVect evaluate( const CartVect& xi ) const;
00291 // virtual CartVect ievaluate(const CartVect& x, double tol) const ;
00292 virtual bool inside_nat_space( const CartVect& xi, double& tol ) const;
00293
00294 virtual Matrix3 jacobian( const CartVect& xi ) const;
00295 virtual double evaluate_scalar_field( const CartVect& xi, const double* field_vertex_values ) const;
00296 virtual double integrate_scalar_field( const double* field_vertex_values ) const;
00297
00298 protected:
00299 /* Preimages of the vertices -- "canonical vertices" -- are known as "corners". */
00300 static const double corner[4][3];
00301 static const double gauss[1][2];
00302 static const unsigned int corner_count = 4;
00303 static const unsigned int gauss_count = 1;
00304
00305 }; // class LinearQuad
00306
00307 /**\brief Shape function space for bilinear quadrilateral on sphere, obtained from the
00308 * canonical linear (affine) functions.
00309 * It is mapped using gnomonic projection to a plane tangent at the first vertex
00310 * It works well for edges that are great circle arcs; RLL meshes do not have this property,
00311 * but HOMME or MPAS meshes do have it */
00312 class SphericalQuad : public LinearQuad
00313 {
00314 public:
00315 SphericalQuad( const std::vector< CartVect >& vertices );
00316 virtual ~SphericalQuad(){};
00317 virtual bool inside_box( const CartVect& pos, double& tol ) const;
00318 CartVect ievaluate( const CartVect& x, double tol = 1e-6, const CartVect& x0 = CartVect( 0.0 ) ) const;
00319
00320 protected:
00321 CartVect v1;
00322 Matrix3 transf; // so will have a lot of stuff, including the transf to a coordinate system
00323 // double tangent_plane; // at first vertex; normal to the plane is first vertex
00324
00325 }; // class SphericalQuad
00326
00327 /**\brief Shape function space for linear triangle, similar to linear tet. */
00328 class LinearTri : public Map
00329 {
00330 public:
00331 LinearTri( const std::vector< CartVect >& vertices ) : Map( vertices )
00332 {
00333 set_vertices( vertex );
00334 };
00335 LinearTri();
00336 virtual ~LinearTri();
00337 /* Override the evaluation routines to take advantage of the properties of P1. */
00338 /* similar to tets */
00339 virtual CartVect evaluate( const CartVect& xi ) const
00340 {
00341 return this->vertex[0] + this->T * xi;
00342 };
00343 virtual CartVect ievaluate( const CartVect& x, double tol = 1e-6, const CartVect& x0 = CartVect( 0.0 ) ) const;
00344 virtual Matrix3 jacobian( const CartVect& ) const
00345 {
00346 return this->T;
00347 };
00348 virtual Matrix3 ijacobian( const CartVect& ) const
00349 {
00350 return this->T_inverse;
00351 };
00352 virtual double det_jacobian( const CartVect& ) const
00353 {
00354 return this->det_T;
00355 };
00356 virtual double det_ijacobian( const CartVect& ) const
00357 {
00358 return this->det_T_inverse;
00359 };
00360
00361 /* Override set_vertices so we can precompute the matrices effecting the mapping to and from
00362 * the canonical simplex. */
00363 virtual void set_vertices( const std::vector< CartVect >& v );
00364 virtual bool inside_nat_space( const CartVect& xi, double& tol ) const;
00365
00366 virtual double evaluate_scalar_field( const CartVect& xi, const double* field_vertex_values ) const;
00367 virtual double integrate_scalar_field( const double* field_vertex_values ) const;
00368
00369 protected:
00370 /* Preimages of the vertices -- "canonical vertices" -- are known as "corners". */
00371 static const double corner[3][3];
00372 Matrix3 T, T_inverse;
00373 double det_T, det_T_inverse;
00374
00375 }; // class LinearTri
00376
00377 /**\brief Shape function space for linear triangle on sphere, obtained from the
00378 * canonical linear (affine) functions.
00379 * It is mapped using gnomonic projection to a plane tangent at the first vertex
00380 * It works well for edges that are great circle arcs; RLL meshes do not have this property,
00381 * but HOMME or MPAS meshes do have it */
00382 class SphericalTri : public LinearTri
00383 {
00384 public:
00385 SphericalTri( const std::vector< CartVect >& vertices );
00386 virtual ~SphericalTri(){};
00387 virtual bool inside_box( const CartVect& pos, double& tol ) const;
00388 CartVect ievaluate( const CartVect& x, double tol = 1e-6, const CartVect& x0 = CartVect( 0.0 ) ) const;
00389
00390 protected:
00391 CartVect v1;
00392 Matrix3 transf; // so will have a lot of stuff, including the transf to a coordinate system
00393 // double tangent_plane; // at first vertex; normal to the plane is first vertex
00394
00395 }; // class SphericalTri
00396
00397 /**\brief Shape function space for bilinear quadrilateral, obtained from the canonical linear
00398 * (affine) functions. */
00399 class LinearEdge : public Map
00400 {
00401 public:
00402 LinearEdge( const std::vector< CartVect >& vertices ) : Map( vertices ){};
00403 LinearEdge();
00404 virtual CartVect evaluate( const CartVect& xi ) const;
00405 // virtual CartVect ievaluate(const CartVect& x, double tol) const ;
00406 virtual bool inside_nat_space( const CartVect& xi, double& tol ) const;
00407
00408 virtual Matrix3 jacobian( const CartVect& xi ) const;
00409 virtual double evaluate_scalar_field( const CartVect& xi, const double* field_vertex_values ) const;
00410 virtual double integrate_scalar_field( const double* field_vertex_values ) const;
00411
00412 protected:
00413 /* Preimages of the vertices -- "canonical vertices" -- are known as "corners". */
00414 static const double corner[2][3];
00415 static const double gauss[1][2];
00416 static const unsigned int corner_count = 2;
00417 static const unsigned int gauss_count = 1;
00418
00419 }; // class LinearEdge
00420
00421 class SpectralQuad : public Map
00422 {
00423 public:
00424 SpectralQuad( const std::vector< CartVect >& vertices ) : Map( vertices )
00425 {
00426 _xyz[0] = _xyz[1] = _xyz[2] = NULL;
00427 };
00428 SpectralQuad( int order, double* x, double* y, double* z );
00429 SpectralQuad( int order );
00430 SpectralQuad();
00431 virtual ~SpectralQuad();
00432 void set_gl_points( double* x, double* y, double* z );
00433 virtual CartVect evaluate( const CartVect& xi ) const; // a 2d, so 3rd component is 0, always
00434 virtual CartVect ievaluate(
00435 const CartVect& x,
00436 double tol = 1e-6,
00437 const CartVect& x0 = CartVect( 0.0 ) ) const; // a 2d, so 3rd component is 0, always
00438 virtual Matrix3 jacobian( const CartVect& xi ) const;
00439 double evaluate_scalar_field( const CartVect& xi, const double* field_vertex_values ) const;
00440 double integrate_scalar_field( const double* field_vertex_values ) const;
00441 bool inside_nat_space( const CartVect& xi, double& tol ) const;
00442
00443 // to compute the values that need to be cached for each element of order n
00444 void Init( int order );
00445 void freedata();
00446 // this will take node, vertex positions and compute the gl points
00447 void compute_gl_positions();
00448 void get_gl_points( double*& x, double*& y, double*& z, int& size );
00449
00450 protected:
00451 /* values that depend only on the order of the element , cached */
00452 /* the order in all 3 directions ; it is also np in HOMME lingo*/
00453 static int _n;
00454 static realType* _z[2];
00455 static lagrange_data _ld[2];
00456 static opt_data_2 _data; // we should use only 2nd component
00457 static realType* _odwork; // work area
00458
00459 // flag for initialization of data
00460 static bool _init;
00461 static realType* _glpoints; // it is a space we can use to store gl positions for elements
00462 // on the fly; we do not have a tag yet for them, as in Nek5000 application
00463 // also, these positions might need to be moved on the sphere, for HOMME grids
00464 // do we project them or how do we move them on the sphere?
00465
00466 realType* _xyz[3]; // these are gl points; position?
00467
00468 }; // class SpectralQuad
00469
00470 } // namespace Element
00471
00472 } // namespace moab
00473
00474 #endif /*MOAB_ELEM_UTIL_HPP*/