1 #ifndef ELEM_EVALUATOR_HPP
2 #define ELEM_EVALUATOR_HPP
3 
4 #include "moab/Interface.hpp"
5 #include "moab/CartVect.hpp"
6 #include "moab/Matrix3.hpp"
7 #include "moab/CN.hpp"
8 
9 #include <vector>
10 
11 namespace moab {
12 
13     typedef ErrorCode (*EvalFcn)(const double *params, const double *field, const int ndim, const int num_tuples,
14                           double *work, double *result);
15 
16     typedef ErrorCode (*JacobianFcn)(const double *params, const double *verts, const int nverts, const int ndim,
17                                      double *work, double *result);
18 
19     typedef ErrorCode (*IntegrateFcn)(const double *field, const double *verts, const int nverts, const int ndim,
20                                       const int num_tuples, double *work, double *result);
21 
22     typedef ErrorCode (*InitFcn)(const double *verts, const int nverts, double *&work);
23 
24     typedef int (*InsideFcn)(const double *verts, const int ndims, const double tol);
25 
26     typedef ErrorCode (*ReverseEvalFcn)(EvalFcn eval, JacobianFcn jacob, InsideFcn ins,
27                                         const double *posn, const double *verts, const int nverts, const int ndim,
28                                         const double iter_tol, const double inside_tol,
29                                         double *work, double *params, int *is_inside);
30 
31   typedef ErrorCode (*NormalFcn)(const int ientDim, const int facet, const int nverts, const double *verts,  double normal[3]);
32 
33     class EvalSet
34     {
35   public:
36         /** \brief Forward-evaluation of field at parametric coordinates */
37       EvalFcn evalFcn;
38 
39         /** \brief Reverse-evaluation of parametric coordinates at physical space position */
40       ReverseEvalFcn reverseEvalFcn;
41 
42       /** \brief Evaluate the normal at a local facet (edge/face for 2D/3D) */
43       NormalFcn normalFcn;
44 
45         /** \brief Evaluate the jacobian at a specified parametric position */
46       JacobianFcn jacobianFcn;
47 
48         /** \brief Forward-evaluation of field at parametric coordinates */
49       IntegrateFcn integrateFcn;
50 
51         /** \brief Initialization function for an element */
52       InitFcn initFcn;
53 
54         /** \brief Function that returns whether or not the parameters are inside the natural space of the element */
55       InsideFcn insideFcn;
56 
57         /** \brief Bare constructor */
EvalSet()58       EvalSet() : evalFcn(NULL), reverseEvalFcn(NULL), normalFcn(NULL), jacobianFcn(NULL), integrateFcn(NULL), initFcn(NULL), insideFcn(NULL) {}
59 
60         /** \brief Constructor */
EvalSet(EvalFcn eval,ReverseEvalFcn rev,NormalFcn normal,JacobianFcn jacob,IntegrateFcn integ,InitFcn initf,InsideFcn insidef)61       EvalSet(EvalFcn eval, ReverseEvalFcn rev, NormalFcn normal, JacobianFcn jacob, IntegrateFcn integ, InitFcn initf, InsideFcn insidef)
62               : evalFcn(eval), reverseEvalFcn(rev), normalFcn(normal), jacobianFcn(jacob), integrateFcn(integ), initFcn(initf), insideFcn(insidef)
63           {}
64 
65         /** \brief Given an entity handle, get an appropriate eval set, based on type & #vertices */
66       static ErrorCode get_eval_set(Interface *mb, EntityHandle eh, EvalSet &eval_set);
67 
68         /** \brief Given type & #vertices, get an appropriate eval set */
69       static ErrorCode get_eval_set(EntityType tp, unsigned int num_vertices, EvalSet &eval_set);
70 
71         /** \brief Operator= */
operator =(const EvalSet & eval)72       EvalSet &operator=(const EvalSet &eval) {
73         evalFcn = eval.evalFcn;
74         reverseEvalFcn = eval.reverseEvalFcn;
75         normalFcn = eval.normalFcn;
76         jacobianFcn = eval.jacobianFcn;
77         integrateFcn = eval.integrateFcn;
78         initFcn = eval.initFcn;
79         insideFcn = eval.insideFcn;
80         return *this;
81       }
82 
83         /** \brief Common function to do reverse evaluation based on evaluation and jacobian functions */
84       static ErrorCode evaluate_reverse(EvalFcn eval, JacobianFcn jacob, InsideFcn inside_f,
85                                         const double *posn, const double *verts, const int nverts,
86                                         const int ndim, const double iter_tol, const double inside_tol,
87                                         double *work, double *params, int *inside);
88         /** \brief Common function that returns true if params is in [-1,1]^ndims */
89       static int inside_function(const double *params, const int ndims, const double tol);
90     };
91 
92         /** \brief Given an entity handle, get an appropriate eval set, based on type & #vertices */
get_eval_set(Interface * mb,EntityHandle eh,EvalSet & eval_set)93     inline ErrorCode EvalSet::get_eval_set(Interface *mb, EntityHandle eh, EvalSet &eval_set)
94     {
95       int nv;
96       EntityType tp = mb->type_from_handle(eh);
97       const EntityHandle *connect;
98       std::vector<EntityHandle> dum_vec;
99       ErrorCode rval = mb->get_connectivity(eh, connect, nv, false, &dum_vec);
100       if (MB_SUCCESS != rval) return rval;
101 
102       return get_eval_set(tp, nv, eval_set);
103     }
104 
105 /**\brief Class facilitating local discretization-related functions
106  * \class ElemEvaluator
107  * This class implements discretization-related functionality operating
108  * on data in MOAB.  A member of this class caches certain data about the element
109  * it's currently operating on, but is not meant to be instantiated one-per-element,
110  * but rather one-per-search (or other operation on a collection of elements).
111  *
112  * Actual discretization functionality is accessed through function pointers,
113  * allowing applications to specialize the implementation of specific functions
114  * while still using this class.
115  *
116  * This class depends on MOAB functionality for gathering entity-based data; the functions
117  * it calls through function pointers depend only on POD (plain old data, or intrinsic data types).
118  * This allows the use of other packages for serving these functions, without having to modify
119  * them to get data through MOAB.  This should also promote efficiency, since in many cases they
120  * will be able to read data from its native storage locations.
121  */
122 
123     class ElemEvaluator {
124   public:
125         /** \brief Constructor
126          * \param impl MOAB instance
127          * \param ent Entity handle to cache on the evaluator; if non-zero, calls set_ent_handle, which does some other stuff.
128          * \param tag Tag to cache on the evaluator; if non-zero, calls set_tag_handle, which does some other stuff too.
129          * \param tagged_ent_dim Dimension of entities to be tagged to cache on the evaluator
130          */
131       ElemEvaluator(Interface *impl, EntityHandle ent = 0, Tag tag = 0, int tagged_ent_dim = -1);
132       ~ElemEvaluator();
133 
134         /** \brief Evaluate cached tag at a given parametric location within the cached entity
135          * If evaluating coordinates, call set_tag(0, 0), which indicates coords instead of a tag.
136          * \param params Parameters at which to evaluate field
137          * \param result Result of evaluation
138          * \param num_tuples Size of evaluated field, in number of values
139          */
140       ErrorCode eval(const double *params, double *result, int num_tuples = -1) const;
141 
142         /** \brief Reverse-evaluate the cached entity at a given physical position
143          * \param posn Position at which to evaluate parameters
144          * \param iter_tol Tolerance of reverse evaluation non-linear iteration, usually 10^-10 or so
145          * \param inside_tol Tolerance of is_inside evaluation, usually 10^-6 or so
146          * \param params Result of evaluation
147          * \param is_inside If non-NULL, returns true of resulting parameters place the point inside the element
148          *                  (in most cases, within [-1]*(dim)
149          */
150       ErrorCode reverse_eval(const double *posn, double iter_tol, double inside_tol, double *params,
151                              int *is_inside = NULL) const;
152 
153       /**
154        * \brief Evaluate the normal to a facet of an entity
155        * \param ientDim Dimension of the facet. Should be (d-1) for d-dimensional entities
156        * \param facet Local id of the facet w.r.t the entity
157        * \param normal Returns the normal.
158        */
159       ErrorCode get_normal(const int ientDim, const int facet, double normal[3]) const;
160 
161         /** \brief Evaluate the jacobian of the cached entity at a given parametric location
162          * \param params Parameters at which to evaluate jacobian
163          * \param result Result of evaluation, in the form of a 3x3 matrix, stored in column-major order
164          */
165       ErrorCode jacobian(const double *params, double *result) const;
166 
167         /** \brief Integrate the cached tag over the cached entity
168          * \param result Result of the integration
169          */
170       ErrorCode integrate(double *result) const;
171 
172         /** \brief Return whether a physical position is inside the cached entity to within a tolerance
173          * \param params Parameters at which to query the element
174          * \param tol Tolerance, usually 10^-6 or so
175          */
176       int inside(const double *params, const double tol) const;
177 
178         /** \brief Given a list of entities, return the entity the point is in, or none
179          * This function reverse-evaluates the entities, returning the first entity containing the point.
180          * If no entity contains the point, containing_ent is returned as 0 and params are unchanged.
181          * This function returns something other than MB_SUCCESS only when queries go wrong for some reason.
182          * num_evals, if non-NULL, is always incremented for each call to reverse_eval.
183          * This function calls set_ent_handle for each entity before calling reverse_eval, so the ElemEvaluator
184          * object is changed.
185          * \param entities Entities tested
186          * \param point Point tested, must have 3 dimensions, even for edge and face entities
187          * \param iter_tol Tolerance for non-linear reverse evaluation
188          * \param inside_tol Tolerance for is_inside test
189          * \param containing_ent Entity containing the point, returned 0 if no entity
190          * \param params Parameters of point in containing entity, unchanged if no containing entity
191          * \param num_evals If non-NULL, incremented each time reverse_eval is called
192          * \return Returns non-success only if evaulation failed for some reason (point not in element is NOT a
193          * reason for failure)
194          */
195       ErrorCode find_containing_entity(Range &entities, const double *point,
196                                        const double iter_tol, const double inside_tol,
197                                        EntityHandle &containing_ent, double *params,
198                                        unsigned int *num_evals = NULL);
199 
200         /** \brief Given an entity set, return the contained entity the point is in, or none
201          * This function reverse-evaluates the entities, returning the first entity containing the point.
202          * If no entity contains the point, containing_ent is returned as 0 and params are unchanged.
203          * This function returns something other than MB_SUCCESS only when queries go wrong for some reason.
204          * num_evals, if non-NULL, is always incremented for each call to reverse_eval.
205          * This function calls set_ent_handle for each entity before calling reverse_eval, so the ElemEvaluator
206          * object is changed.
207          * \param ent_set Entity set containing the entities to be tested
208          * \param point Point tested, must have 3 dimensions, even for edge and face entities
209          * \param iter_tol Tolerance for non-linear reverse evaluation
210          * \param inside_tol Tolerance for is_inside test
211          * \param containing_ent Entity containing the point, returned 0 if no entity
212          * \param params Parameters of point in containing entity, unchanged if no containing entity
213          * \param num_evals If non-NULL, incremented each time reverse_eval is called
214          * \return Returns non-success only if evaulation failed for some reason (point not in element is NOT a
215          * reason for failure)
216          */
217       ErrorCode find_containing_entity(EntityHandle ent_set, const double *point,
218                                        const double iter_tol, const double inside_tol,
219                                        EntityHandle &containing_ent, double *params,
220                                        unsigned int *num_evals = NULL);
221 
222         /** \brief Set the eval set for a given type entity
223          * \param tp Entity type for which to set the eval set
224          * \param eval_set Eval set object to use
225          */
226       ErrorCode set_eval_set(EntityType tp, const EvalSet &eval_set);
227 
228         /** \brief Set the eval set using a given entity handle
229         * This function queries the entity type and number of vertices on the entity to decide which type
230         * of shape function to use.
231         * NOTE: this function should only be called after setting a valid MOAB instance on the evaluator
232         * \param eh Entity handle whose type and #vertices are queried
233         */
234       ErrorCode set_eval_set(const EntityHandle eh);
235 
236         /** \brief Get the eval set for a given type entity */
get_eval_set(EntityType tp)237       inline EvalSet get_eval_set(EntityType tp) {return evalSets[tp];}
238 
239         /** \brief Set entity handle & cache connectivty & vertex positions */
240       inline ErrorCode set_ent_handle(EntityHandle ent);
241 
242         /** \brief Get entity handle for this ElemEval */
get_ent_handle() const243       inline EntityHandle get_ent_handle() const {return entHandle;}
244 
245         /* \brief Get vertex positions cached on this EE
246          */
get_vert_pos()247       inline double *get_vert_pos() {return vertPos[0].array();}
248 
249         /* \brief Get the vertex handles cached here */
get_vert_handles() const250       inline const EntityHandle *get_vert_handles() const {return vertHandles;}
251 
252         /* \brief Get the number of vertices for the cached entity */
get_num_verts() const253       inline int get_num_verts() const {return numVerts;}
254 
255         /* \brief Get the tag handle cached on this entity */
get_tag_handle() const256       inline Tag get_tag_handle() const {return tagHandle;};
257 
258         /* \brief Set the tag handle to cache on this evaluator
259          * To designate that vertex coordinates are the desired tag, pass in a tag handle of 0
260          * and a tag dimension of 0.
261          * \param tag Tag handle to cache, or 0 to cache vertex positions
262          * \param tagged_ent_dim Dimension of entities tagged with this tag
263          */
264       inline ErrorCode set_tag_handle(Tag tag, int tagged_ent_dim = -1);
265 
266         /* \brief Set the name of the tag to cache on this evaluator
267          * To designate that vertex coordinates are the desired tag, pass in "COORDS" as the name
268          * and a tag dimension of 0.
269          * \param tag_name Tag handle to cache, or 0 to cache vertex positions
270          * \param tagged_ent_dim Dimension of entities tagged with this tag
271          */
272       inline ErrorCode set_tag(const char *tag_name, int tagged_ent_dim = -1);
273 
274         /* \brief Get the dimension of the entities on which tag is set */
get_tagged_ent_dim() const275       inline int get_tagged_ent_dim() const {return taggedEntDim;};
276 
277         /* \brief Set the dimension of entities having the tag */
278       inline ErrorCode set_tagged_ent_dim(int dim);
279 
280         /* \brief Get work space, sometimes this is useful for evaluating data you don't want to set as tags on entities
281          * Can't be const because most of the functions (evaluate, integrate, etc.) take non-const work space *'s
282          */
get_work_space()283       inline double *get_work_space() {return workSpace;}
284 
285         /* \brief MOAB interface cached on this evaluator */
get_moab()286       inline Interface *get_moab() {return mbImpl;}
287 
288   private:
289 
290         /** \brief Interface */
291       Interface *mbImpl;
292 
293         /** \brief Entity handle being evaluated */
294       EntityHandle entHandle;
295 
296         /** \brief Entity type */
297       EntityType entType;
298 
299         /** \brief Entity dimension */
300       int entDim;
301 
302         /** \brief Number of vertices cached here */
303       int numVerts;
304 
305         /** \brief Cached copy of vertex handle ptr */
306       const EntityHandle *vertHandles;
307 
308         /** \brief Cached copy of vertex positions */
309       CartVect vertPos[CN::MAX_NODES_PER_ELEMENT];
310 
311         /** \brief Tag being evaluated */
312       Tag tagHandle;
313 
314         /** \brief Whether tag is coordinates or something else */
315       bool tagCoords;
316 
317         /** \brief Number of values in this tag */
318       int numTuples;
319 
320         /** \brief Dimension of entities from which to grab tag */
321       int taggedEntDim;
322 
323         /** \brief Tag space */
324       std::vector<unsigned char> tagSpace;
325 
326         /** \brief Evaluation methods for elements of various topologies */
327       EvalSet evalSets[MBMAXTYPE];
328 
329         /** \brief Work space for element-specific data */
330       double *workSpace;
331 
332     }; // class ElemEvaluator
333 
ElemEvaluator(Interface * impl,EntityHandle ent,Tag tag,int tagged_ent_dim)334     inline ElemEvaluator::ElemEvaluator(Interface *impl, EntityHandle ent, Tag tag, int tagged_ent_dim)
335             : mbImpl(impl), entHandle(0), entType(MBMAXTYPE), entDim(-1), numVerts(0),
336               vertHandles(NULL), tagHandle(0), tagCoords(false), numTuples(0),
337               taggedEntDim(0), workSpace(NULL)
338     {
339       if (ent) set_ent_handle(ent);
340       if (tag) set_tag_handle(tag, tagged_ent_dim);
341     }
342 
~ElemEvaluator()343     inline ElemEvaluator::~ElemEvaluator()
344     {
345       if (workSpace)
346         delete [] workSpace;
347     }
348 
set_ent_handle(EntityHandle ent)349     inline ErrorCode ElemEvaluator::set_ent_handle(EntityHandle ent)
350     {
351       entHandle = ent;
352       if (workSpace) {
353         delete [] workSpace;
354         workSpace = NULL;
355       }
356 
357       entType = mbImpl->type_from_handle(ent);
358       entDim = mbImpl->dimension_from_handle(ent);
359 
360       std::vector<EntityHandle> dum_vec;
361       ErrorCode rval = mbImpl->get_connectivity(ent, vertHandles, numVerts, false, &dum_vec);
362       if (MB_SUCCESS != rval) return rval;
363 
364       if (!evalSets[entType].evalFcn)
365         EvalSet::get_eval_set(entType, numVerts, evalSets[entType]);
366 
367       rval = mbImpl->get_coords(vertHandles, numVerts, vertPos[0].array());
368       if (MB_SUCCESS != rval) return rval;
369 
370       if (tagHandle) {
371         rval = set_tag_handle(tagHandle);
372         if (MB_SUCCESS != rval) return rval;
373       }
374       if (evalSets[entType].initFcn) return (*evalSets[entType].initFcn)(vertPos[0].array(), numVerts, workSpace);
375       return MB_SUCCESS;
376     }
377 
set_tag_handle(Tag tag,int tagged_ent_dim)378     inline ErrorCode ElemEvaluator::set_tag_handle(Tag tag, int tagged_ent_dim)
379     {
380       ErrorCode rval = MB_SUCCESS;
381       if (!tag && !tagged_ent_dim) {
382         tagCoords = true;
383         numTuples = 3;
384         taggedEntDim = 0;
385         tagHandle = 0;
386         return rval;
387       }
388       else if (tagHandle != tag) {
389         tagHandle = tag;
390         rval = mbImpl->tag_get_length(tagHandle, numTuples);
391         if (MB_SUCCESS != rval) return rval;
392         int sz;
393         rval = mbImpl->tag_get_bytes(tag, sz);
394         if (MB_SUCCESS != rval) return rval;
395         tagSpace.resize(CN::MAX_NODES_PER_ELEMENT*sz);
396         tagCoords = false;
397       }
398 
399       taggedEntDim = (-1 == tagged_ent_dim ? 0 : tagged_ent_dim);
400 
401       if (entHandle) {
402         if (0 == taggedEntDim) {
403           rval = mbImpl->tag_get_data(tagHandle, vertHandles, numVerts, &tagSpace[0]);
404           if (MB_SUCCESS != rval) return rval;
405         }
406         else if (taggedEntDim == entDim) {
407           rval = mbImpl->tag_get_data(tagHandle, &entHandle, 1, &tagSpace[0]);
408           if (MB_SUCCESS != rval) return rval;
409         }
410       }
411 
412       return rval;
413     }
414 
set_tag(const char * tag_name,int tagged_ent_dim)415     inline ErrorCode ElemEvaluator::set_tag(const char *tag_name, int tagged_ent_dim)
416     {
417       ErrorCode rval = MB_SUCCESS;
418       if (!tag_name || strlen(tag_name) == 0) return MB_FAILURE;
419       Tag tag;
420       if (!strcmp(tag_name, "COORDS")) {
421         tagCoords = true;
422         taggedEntDim = 0;
423         numTuples = 3;
424         tagHandle = 0;
425           // can return here, because vertex coords already cached when entity handle set
426         return rval;
427       }
428       else {
429         rval = mbImpl->tag_get_handle(tag_name, tag);
430         if (MB_SUCCESS != rval) return rval;
431 
432         if (tagHandle != tag) {
433           tagHandle = tag;
434           rval = mbImpl->tag_get_length(tagHandle, numTuples);
435           if (MB_SUCCESS != rval) return rval;
436           int sz;
437           rval = mbImpl->tag_get_bytes(tag, sz);
438           if (MB_SUCCESS != rval) return rval;
439           tagSpace.reserve(CN::MAX_NODES_PER_ELEMENT*sz);
440           tagCoords = false;
441         }
442 
443         taggedEntDim = (-1 == tagged_ent_dim ? entDim : tagged_ent_dim);
444       }
445 
446       if (entHandle) {
447         if (0 == taggedEntDim) {
448           rval = mbImpl->tag_get_data(tagHandle, vertHandles, numVerts, &tagSpace[0]);
449           if (MB_SUCCESS != rval) return rval;
450         }
451         else if (taggedEntDim == entDim) {
452           rval = mbImpl->tag_get_data(tagHandle, &entHandle, 1, &tagSpace[0]);
453           if (MB_SUCCESS != rval) return rval;
454         }
455       }
456 
457       return rval;
458     }
459 
set_eval_set(EntityType tp,const EvalSet & eval_set)460     inline ErrorCode ElemEvaluator::set_eval_set(EntityType tp, const EvalSet &eval_set)
461     {
462       evalSets[tp] = eval_set;
463       if (entHandle && evalSets[entType].initFcn) {
464         ErrorCode rval = (*evalSets[entType].initFcn)(vertPos[0].array(), numVerts, workSpace);
465         if (MB_SUCCESS != rval) return rval;
466       }
467       return MB_SUCCESS;
468     }
469 
eval(const double * params,double * result,int num_tuples) const470     inline ErrorCode ElemEvaluator::eval(const double *params, double *result, int num_tuples) const
471     {
472       assert(entHandle && MBMAXTYPE != entType);
473       return (*evalSets[entType].evalFcn)(params,
474                                           (tagCoords ? (const double*) vertPos[0].array(): (const double*)&tagSpace[0]),
475                                           entDim,
476                                           (-1 == num_tuples ? numTuples : num_tuples), workSpace, result);
477     }
478 
reverse_eval(const double * posn,const double iter_tol,const double inside_tol,double * params,int * ins) const479     inline ErrorCode ElemEvaluator::reverse_eval(const double *posn, const double iter_tol, const double inside_tol,
480                                                  double *params, int *ins) const
481     {
482       assert(entHandle && MBMAXTYPE != entType);
483       return (*evalSets[entType].reverseEvalFcn)(evalSets[entType].evalFcn, evalSets[entType].jacobianFcn, evalSets[entType].insideFcn,
484                                                  posn, vertPos[0].array(), numVerts,
485                                                  entDim, iter_tol, inside_tol, workSpace, params, ins);
486     }
487 
488       /** \brief Evaluate the normal of the cached entity at a given facet */
get_normal(const int ientDim,const int facet,double normal[]) const489     inline ErrorCode ElemEvaluator::get_normal(const int ientDim, const int facet, double normal[]) const
490     {
491       assert(entHandle && MBMAXTYPE != entType);
492       return (*evalSets[entType].normalFcn)( ientDim, facet, numVerts, vertPos[0].array(), normal);
493     }
494 
495       /** \brief Evaluate the jacobian of the cached entity at a given parametric location */
jacobian(const double * params,double * result) const496     inline ErrorCode ElemEvaluator::jacobian(const double *params, double *result) const
497     {
498       assert(entHandle && MBMAXTYPE != entType);
499       return (*evalSets[entType].jacobianFcn)(params, vertPos[0].array(), numVerts, entDim, workSpace, result);
500     }
501 
502       /** \brief Integrate the cached tag over the cached entity */
integrate(double * result) const503     inline ErrorCode ElemEvaluator::integrate(double *result) const
504     {
505       assert(entHandle && MBMAXTYPE != entType && (tagCoords || tagHandle));
506       ErrorCode rval = MB_SUCCESS;
507       if (!tagCoords) {
508         if (0 == taggedEntDim) rval = mbImpl->tag_get_data(tagHandle, vertHandles, numVerts, (void*)&tagSpace[0]);
509         else rval = mbImpl->tag_get_data(tagHandle, &entHandle, 1, (void*)&tagSpace[0]);
510         if (MB_SUCCESS != rval) return rval;
511       }
512       return (*evalSets[entType].integrateFcn)((tagCoords ? vertPos[0].array() : (const double *)&tagSpace[0]),
513                                                vertPos[0].array(), numVerts, entDim, numTuples,
514                                                workSpace, result);
515     }
516 
find_containing_entity(EntityHandle ent_set,const double * point,const double iter_tol,const double inside_tol,EntityHandle & containing_ent,double * params,unsigned int * num_evals)517     inline ErrorCode ElemEvaluator::find_containing_entity(EntityHandle ent_set, const double *point,
518                                                            const double iter_tol, const double inside_tol,
519                                                            EntityHandle &containing_ent, double *params,
520                                                            unsigned int *num_evals)
521     {
522       assert(mbImpl->type_from_handle(ent_set) == MBENTITYSET);
523       Range entities;
524       ErrorCode rval = mbImpl->get_entities_by_handle(ent_set, entities);
525       if (MB_SUCCESS != rval) return rval;
526       else return find_containing_entity(entities, point, iter_tol, inside_tol, containing_ent, params, num_evals);
527     }
528 
inside(const double * params,const double tol) const529     inline int ElemEvaluator::inside(const double *params, const double tol) const
530     {
531       return (*evalSets[entType].insideFcn)(params, entDim, tol);
532     }
533 
set_eval_set(const EntityHandle eh)534     inline ErrorCode ElemEvaluator::set_eval_set(const EntityHandle eh)
535     {
536       EvalSet eset;
537       ErrorCode rval = EvalSet::get_eval_set(mbImpl, eh, evalSets[mbImpl->type_from_handle(eh)]);
538       return rval;
539     }
540 
541 } // namespace moab
542 
543 #endif /*MOAB_ELEM_EVALUATOR_HPP*/
544