moab
ElemEvaluator.cpp
Go to the documentation of this file.
00001 #include <limits>
00002 
00003 #include "moab/ElemEvaluator.hpp"
00004 #include "moab/CartVect.hpp"
00005 #include "moab/Matrix3.hpp"
00006 
00007 // need to include eval set types here to support get_eval_set; alternative would be to have some
00008 // type of registration, but we'd still need static registration for the built-in types
00009 #include "moab/LinearTri.hpp"
00010 #include "moab/LinearQuad.hpp"
00011 #include "moab/LinearTet.hpp"
00012 #include "moab/LinearHex.hpp"
00013 #include "moab/QuadraticHex.hpp"
00014 //#include "moab/SpectralQuad.hpp"
00015 //#include "moab/SpectralHex.hpp"
00016 
00017 namespace moab { 
00018     ErrorCode EvalSet::evaluate_reverse(EvalFcn eval, JacobianFcn jacob, InsideFcn inside_f,
00019                                         const double *posn, const double *verts, const int nverts, 
00020                                         const int ndim, const double iter_tol, const double inside_tol, 
00021                                         double *work, double *params, int *inside) {
00022         // TODO: should differentiate between epsilons used for
00023         // Newton Raphson iteration, and epsilons used for curved boundary geometry errors
00024         // right now, fix the tolerance used for NR
00025       const double error_tol_sqr = iter_tol*iter_tol;
00026       CartVect *cvparams = reinterpret_cast<CartVect*>(params);
00027       const CartVect *cvposn = reinterpret_cast<const CartVect*>(posn);
00028 
00029         // initialize to center of element
00030       *cvparams = CartVect(-.4);
00031   
00032       CartVect new_pos;
00033         // evaluate that first guess to get a new position
00034       ErrorCode rval = (*eval)(cvparams->array(), verts, ndim, 
00035                                3, // hardwire to num_tuples to 3 since the field is coords
00036                                work, new_pos.array());
00037       if (MB_SUCCESS != rval) return rval;
00038       
00039         // residual is diff between old and new pos; need to minimize that
00040       CartVect res = new_pos - *cvposn;
00041       Matrix3 J;
00042       int dum, *tmp_inside = (inside ? inside : &dum);
00043 
00044       int iters=0;
00045         // while |res| larger than tol
00046       while (res % res > error_tol_sqr) {
00047         if(++iters>10) {
00048             // if we haven't converged but we're outside, that's defined as success
00049           *tmp_inside = (*inside_f)(params, ndim, inside_tol);
00050           if (!(*tmp_inside)) return MB_SUCCESS;
00051           else return MB_FAILURE;
00052         }
00053 
00054           // get jacobian at current params
00055         rval = (*jacob)(cvparams->array(), verts, nverts, ndim, work, J[0]);
00056         double det = J.determinant();
00057         if (det < std::numeric_limits<double>::epsilon()) {
00058           *tmp_inside = (*inside_f)(params, ndim, inside_tol);
00059           if (!(*tmp_inside)) return MB_SUCCESS;
00060           else return MB_INDEX_OUT_OF_RANGE;
00061         }
00062 
00063           // new params tries to eliminate residual
00064         *cvparams -= J.inverse(1.0/det) * res;
00065 
00066           // get the new forward-evaluated position, and its difference from the target pt
00067         rval = (*eval)(params, verts, ndim, 
00068                        3, // hardwire to num_tuples to 3 since the field is coords
00069                        work, new_pos.array());
00070         if (MB_SUCCESS != rval) return rval;
00071         res = new_pos - *cvposn;
00072       }
00073 
00074       if (inside)
00075         *inside = (*inside_f)(params, ndim, inside_tol);
00076 
00077       return MB_SUCCESS;
00078     }// Map::evaluate_reverse()
00079 
00080     int EvalSet::inside_function(const double *params, const int ndims, const double tol) 
00081     {
00082       if (params[0] >= -1-tol && params[0] <= 1+tol &&
00083           (ndims < 2 || (params[1] >= -1-tol && params[1] <= 1+tol)) &&
00084           (ndims < 3 || (params[2] >= -1-tol && params[2] <= 1+tol))) 
00085         return true;
00086       else return false;
00087     }
00088 
00090     ErrorCode EvalSet::get_eval_set(EntityType tp, unsigned int num_vertices, EvalSet &eval_set) 
00091     {
00092       switch (tp) {
00093         case MBEDGE:
00094             break;
00095         case MBTRI:
00096             if (LinearTri::compatible(tp, num_vertices, eval_set)) return MB_SUCCESS;
00097             break;
00098         case MBQUAD:
00099             if (LinearQuad::compatible(tp, num_vertices, eval_set)) return MB_SUCCESS;
00100 //            if (SpectralQuad::compatible(tp, num_vertices, eval_set)) return MB_SUCCESS;
00101             break;
00102         case MBTET:
00103             if (LinearTet::compatible(tp, num_vertices, eval_set)) return MB_SUCCESS;
00104             break;
00105         case MBHEX:
00106             if (LinearHex::compatible(tp, num_vertices, eval_set)) return MB_SUCCESS;
00107             if (QuadraticHex::compatible(tp, num_vertices, eval_set)) return MB_SUCCESS;
00108 //            if (SpectralHex::compatible(tp, num_vertices, eval_set)) return MB_SUCCESS;
00109             break;
00110         default:
00111             break;
00112       }
00113 
00114       return MB_NOT_IMPLEMENTED;
00115     }
00116       
00117     ErrorCode ElemEvaluator::find_containing_entity(Range &entities, const double *point, const double iter_tol, 
00118                                                     const double inside_tol, EntityHandle &containing_ent, 
00119                                                     double *params, unsigned int *num_evals) 
00120     {
00121       int is_inside;
00122       ErrorCode rval = MB_SUCCESS;
00123       unsigned int nevals = 0;
00124       Range::iterator i;
00125       for(i = entities.begin(); i != entities.end(); i++) {
00126         nevals++;
00127         set_ent_handle(*i);
00128         rval = reverse_eval(point, iter_tol, inside_tol, params, &is_inside);
00129         if (MB_SUCCESS != rval) return rval;
00130         if (is_inside) break;
00131       }
00132       containing_ent = (i == entities.end() ? 0 : *i);
00133       if (num_evals) *num_evals += nevals;
00134       return MB_SUCCESS;
00135     }
00136 } // namespace moab
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines