moab
ElemEvaluator.hpp
Go to the documentation of this file.
00001 #ifndef ELEM_EVALUATOR_HPP
00002 #define ELEM_EVALUATOR_HPP
00003 
00004 #include "moab/Interface.hpp"
00005 #include "moab/CartVect.hpp"
00006 #include "moab/Matrix3.hpp"
00007 #include "moab/CN.hpp"
00008 
00009 #include <vector>
00010 
00011 namespace moab {
00012 
00013     typedef ErrorCode (*EvalFcn)(const double *params, const double *field, const int ndim, const int num_tuples, 
00014                           double *work, double *result);
00015 
00016     typedef ErrorCode (*JacobianFcn)(const double *params, const double *verts, const int nverts, const int ndim, 
00017                                      double *work, double *result);
00018         
00019     typedef ErrorCode (*IntegrateFcn)(const double *field, const double *verts, const int nverts, const int ndim,
00020                                       const int num_tuples, double *work, double *result);
00021 
00022     typedef ErrorCode (*InitFcn)(const double *verts, const int nverts, double *&work);
00023 
00024     typedef int (*InsideFcn)(const double *verts, const int ndims, const double tol);
00025 
00026     typedef ErrorCode (*ReverseEvalFcn)(EvalFcn eval, JacobianFcn jacob, InsideFcn ins, 
00027                                         const double *posn, const double *verts, const int nverts, const int ndim,
00028                                         const double iter_tol, const double inside_tol, 
00029                                         double *work, double *params, int *is_inside);
00030         
00031     class EvalSet
00032     {
00033   public:
00035       EvalFcn evalFcn;
00036         
00038       ReverseEvalFcn reverseEvalFcn;
00039         
00041       JacobianFcn jacobianFcn;
00042         
00044       IntegrateFcn integrateFcn;
00045 
00047       InitFcn initFcn;
00048 
00050       InsideFcn insideFcn;
00051 
00053       EvalSet() : evalFcn(NULL), reverseEvalFcn(NULL), jacobianFcn(NULL), integrateFcn(NULL), initFcn(NULL), insideFcn(NULL) {}
00054 
00056       EvalSet(EvalFcn eval, ReverseEvalFcn rev, JacobianFcn jacob, IntegrateFcn integ, InitFcn initf, InsideFcn insidef)
00057               : evalFcn(eval), reverseEvalFcn(rev), jacobianFcn(jacob), integrateFcn(integ), initFcn(initf), insideFcn(insidef)
00058           {}
00059 
00061       static ErrorCode get_eval_set(Interface *mb, EntityHandle eh, EvalSet &eval_set);
00062       
00064       static ErrorCode get_eval_set(EntityType tp, unsigned int num_vertices, EvalSet &eval_set);
00065       
00067       EvalSet &operator=(const EvalSet &eval) {
00068         evalFcn = eval.evalFcn;
00069         reverseEvalFcn = eval.reverseEvalFcn;
00070         jacobianFcn = eval.jacobianFcn;
00071         integrateFcn = eval.integrateFcn;
00072         initFcn = eval.initFcn;
00073         insideFcn = eval.insideFcn;
00074         return *this;
00075       }
00076 
00078       static ErrorCode evaluate_reverse(EvalFcn eval, JacobianFcn jacob, InsideFcn inside_f,
00079                                         const double *posn, const double *verts, const int nverts, 
00080                                         const int ndim, const double iter_tol, const double inside_tol, 
00081                                         double *work, double *params, int *inside);
00083       static int inside_function(const double *params, const int ndims, const double tol);
00084     };
00085 
00087     inline ErrorCode EvalSet::get_eval_set(Interface *mb, EntityHandle eh, EvalSet &eval_set) 
00088     {
00089       int nv;
00090       EntityType tp = mb->type_from_handle(eh);
00091       const EntityHandle *connect;
00092       std::vector<EntityHandle> dum_vec;
00093       ErrorCode rval = mb->get_connectivity(eh, connect, nv, false, &dum_vec);
00094       if (MB_SUCCESS != rval) return rval;
00095       
00096       return get_eval_set(tp, nv, eval_set);
00097     }
00098       
00117     class ElemEvaluator {
00118   public:
00125       ElemEvaluator(Interface *impl, EntityHandle ent = 0, Tag tag = 0, int tagged_ent_dim = -1);
00126 
00133       ErrorCode eval(const double *params, double *result, int num_tuples = -1) const;
00134         
00143       ErrorCode reverse_eval(const double *posn, double iter_tol, double inside_tol, double *params, 
00144                              int *is_inside = NULL) const;
00145         
00150       ErrorCode jacobian(const double *params, double *result) const;
00151         
00155       ErrorCode integrate(double *result) const;
00156       
00161       int inside(const double *params, const double tol) const;
00162 
00180       ErrorCode find_containing_entity(Range &entities, const double *point, 
00181                                        const double iter_tol, const double inside_tol, 
00182                                        EntityHandle &containing_ent, double *params, 
00183                                        unsigned int *num_evals = NULL);
00184       
00202       ErrorCode find_containing_entity(EntityHandle ent_set, const double *point, 
00203                                        const double iter_tol, const double inside_tol,
00204                                        EntityHandle &containing_ent, double *params, 
00205                                        unsigned int *num_evals = NULL);
00206       
00211       ErrorCode set_eval_set(EntityType tp, const EvalSet &eval_set);
00212       
00219       ErrorCode set_eval_set(const EntityHandle eh);
00220       
00222       inline EvalSet get_eval_set(EntityType tp) {return evalSets[tp];}
00223 
00225       inline ErrorCode set_ent_handle(EntityHandle ent);
00226 
00228       inline EntityHandle get_ent_handle() const {return entHandle;}
00229 
00230         /* \brief Get vertex positions cached on this EE
00231          */
00232       inline double *get_vert_pos() {return vertPos[0].array();}
00233       
00234         /* \brief Get the vertex handles cached here */
00235       inline const EntityHandle *get_vert_handles() const {return vertHandles;}
00236 
00237         /* \brief Get the number of vertices for the cached entity */
00238       inline int get_num_verts() const {return numVerts;}
00239 
00240         /* \brief Get the tag handle cached on this entity */
00241       inline Tag get_tag_handle() const {return tagHandle;};
00242 
00243         /* \brief Set the tag handle to cache on this evaluator
00244          * To designate that vertex coordinates are the desired tag, pass in a tag handle of 0
00245          * and a tag dimension of 0.
00246          * \param tag Tag handle to cache, or 0 to cache vertex positions
00247          * \param tagged_ent_dim Dimension of entities tagged with this tag
00248          */
00249       inline ErrorCode set_tag_handle(Tag tag, int tagged_ent_dim = -1);
00250 
00251         /* \brief Set the name of the tag to cache on this evaluator
00252          * To designate that vertex coordinates are the desired tag, pass in "COORDS" as the name
00253          * and a tag dimension of 0.
00254          * \param tag_name Tag handle to cache, or 0 to cache vertex positions
00255          * \param tagged_ent_dim Dimension of entities tagged with this tag
00256          */
00257       inline ErrorCode set_tag(const char *tag_name, int tagged_ent_dim = -1);
00258       
00259         /* \brief Get the dimension of the entities on which tag is set */
00260       inline int get_tagged_ent_dim() const {return taggedEntDim;};
00261 
00262         /* \brief Set the dimension of entities having the tag */
00263       inline ErrorCode set_tagged_ent_dim(int dim);
00264 
00265         /* \brief Get work space, sometimes this is useful for evaluating data you don't want to set as tags on entities
00266          * Can't be const because most of the functions (evaluate, integrate, etc.) take non-const work space *'s
00267          */
00268       inline double *get_work_space() {return workSpace;}
00269             
00270         /* \brief MOAB interface cached on this evaluator */
00271       inline Interface *get_moab() {return mbImpl;}
00272       
00273   private:
00274 
00276       Interface *mbImpl;
00277       
00279       EntityHandle entHandle;
00280 
00282       EntityType entType;
00283 
00285       int entDim;
00286             
00288       int numVerts;
00289 
00291       const EntityHandle *vertHandles;
00292       
00294       CartVect vertPos[CN::MAX_NODES_PER_ELEMENT];
00295       
00297       Tag tagHandle;
00298 
00300       bool tagCoords;
00301       
00303       int numTuples;
00304 
00306       int taggedEntDim;
00307 
00309       std::vector<unsigned char> tagSpace;
00310       
00312       EvalSet evalSets[MBMAXTYPE];
00313 
00315       double *workSpace;
00316 
00317     }; // class ElemEvaluator
00318 
00319     inline ElemEvaluator::ElemEvaluator(Interface *impl, EntityHandle ent, Tag tag, int tagged_ent_dim) 
00320             : mbImpl(impl), entHandle(0), entType(MBMAXTYPE), entDim(-1), numVerts(0), 
00321               vertHandles(NULL), tagHandle(0), tagCoords(false), numTuples(0), 
00322               taggedEntDim(0), workSpace(NULL)
00323     {
00324       if (ent) set_ent_handle(ent);
00325       if (tag) set_tag_handle(tag, tagged_ent_dim);
00326     }
00327     
00328     inline ErrorCode ElemEvaluator::set_ent_handle(EntityHandle ent) 
00329     {
00330       entHandle = ent;
00331       if (workSpace) {
00332         delete [] workSpace;
00333         workSpace = NULL;
00334       }
00335 
00336       entType = mbImpl->type_from_handle(ent);
00337       entDim = mbImpl->dimension_from_handle(ent);
00338 
00339       std::vector<EntityHandle> dum_vec;
00340       ErrorCode rval = mbImpl->get_connectivity(ent, vertHandles, numVerts, false, &dum_vec);
00341       if (MB_SUCCESS != rval) return rval;
00342 
00343       if (!evalSets[entType].evalFcn)
00344         EvalSet::get_eval_set(entType, numVerts, evalSets[entType]);
00345 
00346       rval = mbImpl->get_coords(vertHandles, numVerts, vertPos[0].array());
00347       if (MB_SUCCESS != rval) return rval;
00348 
00349       if (tagHandle) {
00350         rval = set_tag_handle(tagHandle);
00351         if (MB_SUCCESS != rval) return rval;
00352       }
00353       if (evalSets[entType].initFcn) return (*evalSets[entType].initFcn)(vertPos[0].array(), numVerts, workSpace);
00354       return MB_SUCCESS;
00355     }
00356     
00357     inline ErrorCode ElemEvaluator::set_tag_handle(Tag tag, int tagged_ent_dim) 
00358     {
00359       ErrorCode rval = MB_SUCCESS;
00360       if (!tag && !tagged_ent_dim) {
00361         tagCoords = true;
00362         numTuples = 3;
00363         taggedEntDim = 0;
00364         tagHandle = 0;
00365         return rval;
00366       }
00367       else if (tagHandle != tag) {
00368         tagHandle = tag;
00369         rval = mbImpl->tag_get_length(tagHandle, numTuples);
00370         if (MB_SUCCESS != rval) return rval;
00371         int sz;
00372         rval = mbImpl->tag_get_bytes(tag, sz);
00373         if (MB_SUCCESS != rval) return rval;
00374         tagSpace.reserve(CN::MAX_NODES_PER_ELEMENT*sz);
00375         tagCoords = false;
00376       }
00377 
00378       taggedEntDim = (-1 == tagged_ent_dim ? 0 : tagged_ent_dim);
00379       
00380       if (entHandle) {
00381         if (0 == taggedEntDim) {
00382           rval = mbImpl->tag_get_data(tagHandle, vertHandles, numVerts, &tagSpace[0]);
00383           if (MB_SUCCESS != rval) return rval;
00384         }
00385         else if (taggedEntDim == entDim) {
00386           rval = mbImpl->tag_get_data(tagHandle, &entHandle, 1, &tagSpace[0]);
00387           if (MB_SUCCESS != rval) return rval;
00388         }
00389       }
00390 
00391       return rval;
00392     }
00393 
00394     inline ErrorCode ElemEvaluator::set_tag(const char *tag_name, int tagged_ent_dim) 
00395     {
00396       ErrorCode rval = MB_SUCCESS;
00397       if (!tag_name || strlen(tag_name) == 0) return MB_FAILURE;
00398       Tag tag;
00399       if (!strcmp(tag_name, "COORDS")) {
00400         tagCoords = true;
00401         taggedEntDim = 0;
00402         numTuples = 3;
00403         tagHandle = 0;
00404           // can return here, because vertex coords already cached when entity handle set
00405         return rval;
00406       }
00407       else {
00408         rval = mbImpl->tag_get_handle(tag_name, tag);
00409         if (MB_SUCCESS != rval) return rval;
00410       
00411         if (tagHandle != tag) {
00412           tagHandle = tag;
00413           rval = mbImpl->tag_get_length(tagHandle, numTuples);
00414           if (MB_SUCCESS != rval) return rval;
00415           int sz;
00416           rval = mbImpl->tag_get_bytes(tag, sz);
00417           if (MB_SUCCESS != rval) return rval;
00418           tagSpace.reserve(CN::MAX_NODES_PER_ELEMENT*sz);
00419           tagCoords = false;
00420         }
00421 
00422         taggedEntDim = (-1 == tagged_ent_dim ? entDim : tagged_ent_dim);
00423       }
00424       
00425       if (entHandle) {
00426         if (0 == taggedEntDim) {
00427           rval = mbImpl->tag_get_data(tagHandle, vertHandles, numVerts, &tagSpace[0]);
00428           if (MB_SUCCESS != rval) return rval;
00429         }
00430         else if (taggedEntDim == entDim) {
00431           rval = mbImpl->tag_get_data(tagHandle, &entHandle, 1, &tagSpace[0]);
00432           if (MB_SUCCESS != rval) return rval;
00433         }
00434       }
00435 
00436       return rval;
00437     }
00438 
00439     inline ErrorCode ElemEvaluator::set_eval_set(EntityType tp, const EvalSet &eval_set) 
00440     {
00441       evalSets[tp] = eval_set;
00442       if (entHandle && evalSets[entType].initFcn) {
00443         ErrorCode rval = (*evalSets[entType].initFcn)(vertPos[0].array(), numVerts, workSpace);
00444         if (MB_SUCCESS != rval) return rval;
00445       }
00446       return MB_SUCCESS;
00447     }
00448     
00449     inline ErrorCode ElemEvaluator::eval(const double *params, double *result, int num_tuples) const 
00450     {
00451       assert(entHandle && MBMAXTYPE != entType);
00452       return (*evalSets[entType].evalFcn)(params, 
00453                                           (tagCoords ? (const double*) vertPos[0].array(): (const double*)&tagSpace[0]), 
00454                                           entDim, 
00455                                           (-1 == num_tuples ? numTuples : num_tuples), workSpace, result);
00456     }
00457         
00458     inline ErrorCode ElemEvaluator::reverse_eval(const double *posn, const double iter_tol, const double inside_tol,
00459                                                  double *params, int *ins) const
00460     {
00461       assert(entHandle && MBMAXTYPE != entType);
00462       return (*evalSets[entType].reverseEvalFcn)(evalSets[entType].evalFcn, evalSets[entType].jacobianFcn, evalSets[entType].insideFcn,
00463                                                  posn, vertPos[0].array(), numVerts, 
00464                                                  entDim, iter_tol, inside_tol, workSpace, params, ins);
00465     }
00466         
00468     inline ErrorCode ElemEvaluator::jacobian(const double *params, double *result) const
00469     {
00470       assert(entHandle && MBMAXTYPE != entType);
00471       return (*evalSets[entType].jacobianFcn)(params, vertPos[0].array(), numVerts, entDim, workSpace, result);
00472     }
00473         
00475     inline ErrorCode ElemEvaluator::integrate(double *result) const
00476     {
00477       assert(entHandle && MBMAXTYPE != entType && (tagCoords || tagHandle));
00478       ErrorCode rval = MB_SUCCESS;
00479       if (!tagCoords) {
00480         if (0 == taggedEntDim) rval = mbImpl->tag_get_data(tagHandle, vertHandles, numVerts, (void*)&tagSpace[0]);
00481         else rval = mbImpl->tag_get_data(tagHandle, &entHandle, 1, (void*)&tagSpace[0]);
00482         if (MB_SUCCESS != rval) return rval;
00483       }
00484       return (*evalSets[entType].integrateFcn)((tagCoords ? vertPos[0].array() : (const double *)&tagSpace[0]), 
00485                                                vertPos[0].array(), numVerts, entDim, numTuples, 
00486                                                workSpace, result);
00487     }
00488 
00489     inline ErrorCode ElemEvaluator::find_containing_entity(EntityHandle ent_set, const double *point, 
00490                                                            const double iter_tol, const double inside_tol,
00491                                                            EntityHandle &containing_ent, double *params, 
00492                                                            unsigned int *num_evals) 
00493     {
00494       assert(mbImpl->type_from_handle(ent_set) == MBENTITYSET);
00495       Range entities;
00496       ErrorCode rval = mbImpl->get_entities_by_handle(ent_set, entities);
00497       if (MB_SUCCESS != rval) return rval;
00498       else return find_containing_entity(entities, point, iter_tol, inside_tol, containing_ent, params, num_evals);
00499     }
00500         
00501     inline int ElemEvaluator::inside(const double *params, const double tol) const 
00502     {
00503       return (*evalSets[entType].insideFcn)(params, entDim, tol);
00504     }
00505 
00506     inline ErrorCode ElemEvaluator::set_eval_set(const EntityHandle eh) 
00507     {
00508       EvalSet eset;
00509       ErrorCode rval = EvalSet::get_eval_set(mbImpl, eh, evalSets[mbImpl->type_from_handle(eh)]); 
00510       return rval;
00511     }
00512 
00513 } // namespace moab
00514 
00515 #endif /*MOAB_ELEM_EVALUATOR_HPP*/
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines