moab
|
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*/