moab
quadratic_hex_map.hpp
Go to the documentation of this file.
00001 #ifndef MOAB_QUADRATIC_HEX_HPP
00002 #define MOAB_QUADRATIC_HEX_HPP
00003 
00004 #include "moab/Matrix3.hpp"
00005 #include "moab/CartVect.hpp"
00006 #include <sstream>
00007 #include <iomanip>
00008 #include <iostream>
00009 
00010 namespace moab { 
00011 
00012 namespace element_utility {
00013 
00014 namespace {
00015 
00016 double SH(const int i, const double xi)
00017 {
00018   switch (i)
00019   {
00020   case -1: return (xi*xi-xi)/2;
00021   case 0: return 1-xi*xi;
00022   case 1: return (xi*xi+xi)/2;
00023   default: return 0.;
00024   }
00025 }
00026 double DSH(const int i, const double xi)
00027 {
00028   switch (i)
00029   {
00030   case -1: return xi-0.5;
00031   case 0: return -2*xi;
00032   case 1: return xi+0.5;
00033   default: return 0.;
00034   }
00035 }
00036 
00037 
00038 } //non-exported functionality
00039 
00040 template< typename _Matrix>
00041 class Quadratic_hex_map {
00042   public:
00043     typedef _Matrix Matrix;
00044   private:
00045     typedef Quadratic_hex_map< Matrix> Self;
00046   public: 
00047     //Constructor
00048     Quadratic_hex_map() {}
00049     //Copy constructor
00050     Quadratic_hex_map( const Self & f ) {}
00051 
00052  public:
00053     //Natural coordinates
00054     template< typename Moab, typename Entity_handle, 
00055           typename Points, typename Point>
00056     std::pair< bool, Point> operator()( const Moab & /* moab */,
00057                     const Entity_handle & /* h */,
00058                     const Points & v, 
00059                     const Point & p, 
00060                     const double tol = 1.e-6) const {
00061       Point result(3, 0.0);
00062       bool point_found = solve_inverse( p, result, v, tol) &&
00063                 is_contained( result, tol);
00064       return std::make_pair( point_found, result);
00065     }
00066 
00067   private:
00068     //This is a hack to avoid a .cpp file and C++11
00069     //reference_points(i,j) will be a 1 or -1;
00070     //This should unroll..
00071     inline double reference_points( const std::size_t& i,
00072                           const std::size_t& j) const{
00073     const double rpts[27][3] = {
00074         { -1, -1, -1 },
00075         {  1, -1, -1 },
00076         {  1,  1, -1 },  // reference_points nodes: 0-7
00077         { -1,  1, -1 },  // mid-edge nodes: 8-19
00078         { -1, -1,  1 },  // center-face nodes 20-25  center node  26
00079         {  1, -1,  1 },  //
00080         {  1,  1,  1 },
00081         { -1,  1,  1 }, //                    4   ----- 19   -----  7
00082         {  0, -1, -1 }, //                .   |                 .   |
00083         {  1,  0, -1 }, //            16         25         18      |
00084         {  0,  1, -1 }, //         .          |          .          |
00085         { -1,  0, -1 }, //      5   ----- 17   -----  6             |
00086         { -1, -1,  0 }, //      |            12       | 23         15
00087         {  1, -1,  0 }, //      |                     |             |
00088         {  1,  1,  0 }, //      |     20      |  26   |     22      |
00089         { -1,  1,  0 }, //      |                     |             |
00090         {  0, -1,  1 }, //     13         21  |      14             |
00091         {  1,  0,  1 }, //      |             0   ----- 11   -----  3
00092         {  0,  1,  1 }, //      |         .           |         .
00093         { -1,  0,  1 }, //      |      8         24   |     10
00094         {  0, -1,  0 }, //      |  .                  |  .
00095         {  1,  0,  0 }, //      1   -----  9   -----  2
00096         {  0,  1,  0 }, //
00097         { -1,  0,  0 },
00098         {  0,  0, -1 },
00099         {  0,  0,  1 },
00100         {  0,  0,  0 }
00101     };
00102       return rpts[ i][ j];
00103     }
00104 
00105     template< typename Point>
00106     bool is_contained( const Point & p, const double tol) const{
00107      //just look at the box+tol here
00108      return ( p[0]>=-1.-tol) && (p[0]<=1.+tol) &&
00109             ( p[1]>=-1.-tol) && (p[1]<=1.+tol) &&
00110             ( p[2]>=-1.-tol) && (p[2]<=1.+tol);
00111     }
00112 
00113     template< typename Point, typename Points>
00114     bool solve_inverse( const Point & x, 
00115             Point & xi,
00116             const Points & points, 
00117             const double tol=1.e-6) const {
00118       const double error_tol_sqr = tol*tol;
00119       Point delta(3,0.0);
00120       xi = delta;
00121       evaluate( xi, points, delta);
00122       vec_subtract( delta, x);
00123       std::size_t num_iterations=0;
00124       #ifdef QUADRATIC_HEX_DEBUG
00125     std::stringstream ss;
00126     ss << "Point: "; 
00127        ss << x[ 0 ] << ", " << x[ 1] 
00128           << ", " << x [ 2] << std::endl;
00129     ss << "Hex: ";
00130     for(int i = 0; i < 8; ++i){
00131             ss << points[ i][ 0] << ", " << points[ i][ 1] << ", "
00132            << points[ i][ 2] << std::endl;
00133     }
00134     ss << std::endl;
00135       #endif
00136       while ( normsq( delta) > error_tol_sqr) {
00137     #ifdef QUADRATIC_HEX_DEBUG
00138     ss << "Iter #: "  << num_iterations 
00139        << " Err: " << sqrt( normsq( delta)) << " Iterate: ";
00140     ss << xi[ 0 ] << ", " << xi[ 1] 
00141         << ", " << xi[ 2] << std::endl;
00142     #endif
00143     if( ++num_iterations >= 5){ return false; }
00144         Matrix J;
00145     jacobian( xi, points, J);
00146         double det = moab::Matrix::determinant3( J);
00147         if (fabs(det) < 1.e-10){
00148         #ifdef QUADRATIC_HEX_DEBUG
00149             std::cerr << ss.str();
00150         #endif
00151         #ifndef QUADRATIC_HEX_DEBUG
00152         std::cerr << x[ 0 ] << ", " << x[ 1] 
00153               << ", " << x [ 2] << std::endl;
00154         #endif
00155         std::cerr << "inverse solve failure: det: " << det << std::endl;
00156         exit( -1);
00157     }
00158         vec_subtract( xi, moab::Matrix::inverse(J, 1.0/det) * delta);
00159         evaluate( xi, points, delta);
00160     vec_subtract( delta, x);
00161       }
00162        return true;
00163     }
00164 
00165     template< typename Point, typename Points>
00166     Point& evaluate( const Point & p, const Points & points, Point & f) const{ 
00167     typedef typename Points::value_type Vector;
00168     Vector result;
00169     for(int i = 0; i < 3; ++i){ result[ i] = 0; }
00170     for (unsigned i = 0; i < 27; ++i) {
00171         const double sh= SH(reference_points(i,0), p[0])*
00172                          SH(reference_points(i,1), p[1])*
00173                          SH(reference_points(i,2), p[2]);
00174         result += sh * points[ i];
00175     }
00176     for (int i = 0; i < 3; ++i){ f[ i] = result[ i]; }
00177     return f;
00178     }
00179     template< typename Point, typename Field>
00180     double   evaluate_scalar_field( const Point & p, 
00181                     const Field & field) const {
00182       double x=0.0;
00183       for (int i=0; i<27; i++){
00184         const double sh= SH(reference_points(i,0), p[0])*
00185                      SH(reference_points(i,1), p[1])*
00186                      SH(reference_points(i,2), p[2]);
00187         x+=sh* field[i];
00188       }
00189       return x;
00190     }
00191     template< typename Field, typename Points>
00192     double   integrate_scalar_field( const Points & p, 
00193                      const Field & field_values) const { 
00194         // TODO: gaussian integration , probably 2x2x2
00195     return 0.; 
00196     }
00197 
00198     template< typename Point, typename Points>
00199     Matrix& jacobian( const Point & p, const Points & /* points */, Matrix & J) const {
00200     J = Matrix(0.0);
00201     for (int i = 0; i < 27; i++) {
00202       const double sh[3] = { SH(reference_points(i,0), p[0]),
00203                                        SH(reference_points(i,1), p[1]),
00204                                        SH(reference_points(i,2), p[2]) };
00205         const double dsh[3] = { DSH(reference_points(i,0), p[0]),
00206                                   DSH(reference_points(i,1), p[1]),
00207                                   DSH(reference_points(i,2), p[2]) };
00208       for (int j = 0; j < 3; j++) {
00209         // dxj/dr first column
00210         J(j, 0) += dsh[0]*sh[1]*sh[2]*reference_points(i, j);
00211         J(j, 1) += sh[0]*dsh[1]*sh[2]*reference_points(i, j); // dxj/ds
00212         J(j, 2) += sh[0]*sh[1]*dsh[2]*reference_points(i, j); // dxj/dt
00213       }
00214     }
00215     return J;
00216   }
00217   private:
00218 }; //Class Quadratic_hex_map
00219 
00220 }// namespace element_utility
00221 
00222 }// namespace moab
00223 #endif //MOAB_QUADRATIC_HEX_nPP
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines