MeshKit
1.0
|
00001 #include "meshkit/ModelEnt.hpp" 00002 #include "meshkit/MKCore.hpp" 00003 #include "moab/Interface.hpp" 00004 #include "FreeSmoothDomain.hpp" 00005 #include "MsqError.hpp" 00006 00007 namespace MeshKit { 00008 00009 using namespace moab; 00010 using namespace Mesquite; 00011 00012 FreeSmoothDomain::FreeSmoothDomain( MKCore* core, const MEntVector& entities ) 00013 : MsqCommonIGeom(core->igeom_instance()->instance()), 00014 haveEntGeomRelTag(false), 00015 moabIface(core->moab_instance()) 00016 { 00017 // Group input entities and all child entities by dimension. 00018 // This way if a vertex is contained in all entities in which it 00019 // is used rather than just the one that owns it, it will still 00020 // get assigned correctly as long as we work from highest to lowest 00021 // dimension. 00022 MEntVector ents_by_dim[4], tmp_vec; 00023 MEntVector::const_iterator i; 00024 for (i = entities.begin(); i != entities.end(); ++i) { 00025 ModelEnt* ent = *i; 00026 int dim = ent->dimension(); 00027 if (dim < 0 || dim > 3) 00028 throw Error(MK_WRONG_DIMENSION, "Entity of invalid dimension %d", dim); 00029 ents_by_dim[dim].push_back(ent); 00030 for (int d = 0; d < dim; ++d) { 00031 tmp_vec.clear(); 00032 ent->get_adjacencies( d, tmp_vec ); 00033 ents_by_dim[d].insert( ents_by_dim[d].end(), tmp_vec.begin(), tmp_vec.end() ); 00034 } 00035 } 00036 00037 // Create a tag to store geometry handles on mesh entities 00038 assert( sizeof(iBase_EntityHandle) == sizeof(moab::EntityHandle) ); 00039 const moab::EntityHandle zero = 0; 00040 moab::ErrorCode rval = moabIface->tag_get_handle( 0, 00041 1, 00042 MB_TYPE_HANDLE, 00043 entGeomRel, 00044 moab::MB_TAG_DENSE|moab::MB_TAG_CREAT, 00045 &zero ); 00046 MBERRCHK( rval, moabIface ); 00047 haveEntGeomRelTag = true; 00048 00049 // NOTE: We only go up to a dimension of 2 here! 00050 // Mesquite only cares about surface elements constrained 00051 // to a surface and vertices constrained to lie on surfaces, 00052 // curves, or points. 00053 for (int d = 0; d < 3; ++d) { 00054 std::sort( ents_by_dim[d].begin(), ents_by_dim[d].end() ); 00055 MEntVector::iterator end = std::unique( ents_by_dim[d].begin(), ents_by_dim[d].end() ); 00056 for (i = ents_by_dim[d].begin(); i != end; ++i) { 00057 EntityHandle set = (*i)->mesh_handle(); 00058 iBase_EntityHandle geom = (*i)->geom_handle(); 00059 if (!geom) 00060 throw Error(MK_BAD_GEOMETRIC_EVALUATION, "Cannot do free smooth if ModelEnt doesn't have geometry" ); 00061 00062 // assign surface elements 00063 if (d == 2) { 00064 Range elems; 00065 rval = moabIface->get_entities_by_dimension( set, 2, elems ); 00066 MBERRCHK( rval, moabIface ); 00067 rval = moabIface->tag_clear_data( entGeomRel, elems, &geom ); 00068 MBERRCHK( rval, moabIface ); 00069 } 00070 00071 // assign vertices 00072 Range verts; 00073 rval = moabIface->get_entities_by_dimension( set, 0, verts ); 00074 MBERRCHK( rval, moabIface ); 00075 rval = moabIface->tag_clear_data( entGeomRel, verts, &geom ); 00076 MBERRCHK( rval, moabIface ); 00077 } 00078 } 00079 } 00080 00081 FreeSmoothDomain::~FreeSmoothDomain() 00082 { 00083 if (haveEntGeomRelTag) 00084 moabIface->tag_delete( entGeomRel ); 00085 } 00086 00087 iBase_EntityHandle FreeSmoothDomain::get_geometry( Mesh::EntityHandle mesh_ent ) const 00088 { 00089 iBase_EntityHandle result; 00090 moab::EntityHandle ent = (moab::EntityHandle)mesh_ent; 00091 moab::ErrorCode rval = moabIface->tag_get_data( entGeomRel, &ent, 1, &result ); 00092 MBERRCHK( rval, moabIface ); 00093 return result; 00094 } 00095 00096 void FreeSmoothDomain::get_geometry( const Mesh::EntityHandle* mesh_ents, 00097 size_t num_handles, 00098 iBase_EntityHandle* geom_ents, 00099 MsqError& err ) const 00100 { 00101 const moab::EntityHandle* ents = (const moab::EntityHandle*)mesh_ents; 00102 moab::ErrorCode rval = moabIface->tag_get_data( entGeomRel, ents, num_handles, geom_ents ); 00103 if (MB_SUCCESS != rval) { 00104 MSQ_SETERR(err)(MsqError::INTERNAL_ERROR, 00105 "Error querying MOAB for geom"); 00106 } 00107 } 00108 00109 00110 void FreeSmoothDomain::snap_to( Mesh::VertexHandle handle, 00111 Vector3D& coordinate ) const 00112 { 00113 iBase_EntityHandle geom = get_geometry( handle ); 00114 if (geom) { 00115 int ierr = move_to( geom, coordinate ); 00116 IBERRCHK(ierr, "iGeom evaluation error"); 00117 } 00118 } 00119 00120 void FreeSmoothDomain::vertex_normal_at( Mesh::VertexHandle handle, 00121 Vector3D& coordinate ) const 00122 { 00123 iBase_EntityHandle geom = get_geometry( handle ); 00124 if (geom) { 00125 int ierr = normal( geom, coordinate ); 00126 IBERRCHK(ierr, "iGeom evaluation error"); 00127 } 00128 } 00129 00130 void FreeSmoothDomain::element_normal_at( Mesh::ElementHandle handle, 00131 Vector3D& coordinate ) const 00132 { 00133 FreeSmoothDomain::vertex_normal_at( handle, coordinate ); 00134 } 00135 00136 void FreeSmoothDomain::vertex_normal_at( const Mesh::VertexHandle* handle, 00137 Vector3D coordinates[], 00138 unsigned count, 00139 MsqError& err ) const 00140 { 00141 tmpHandles.resize( count ); 00142 get_geometry( handle, count, &tmpHandles[0], err ); 00143 MSQ_ERRRTN(err); 00144 00145 int ierr = normal( &tmpHandles[0], coordinates, count ); 00146 if (iBase_SUCCESS != ierr) 00147 MSQ_SETERR(err)(MsqError::INTERNAL_ERROR,"Failure to evaluate geometry. iBase ErrorCode %d\n", ierr); 00148 } 00149 00150 void FreeSmoothDomain::domain_DoF( const Mesh::VertexHandle* handle_array, 00151 unsigned short* dof_array, 00152 size_t count, 00153 MsqError& err ) const 00154 { 00155 tmpHandles.resize( count ); 00156 get_geometry( handle_array, count, &tmpHandles[0], err ); 00157 MSQ_ERRRTN(err); 00158 00159 int ierr, type; 00160 for (size_t i = 0; i < count; ++i) { 00161 if (!tmpHandles[i]) 00162 dof_array[i] = 3; // don't have geom handles for volumes 00163 else if (i > 0 && tmpHandles[i-1] == tmpHandles[i]) 00164 dof_array[i] = dof_array[i-1]; 00165 else { 00166 iGeom_getEntType( geomIFace, tmpHandles[i], &type, &ierr ); 00167 dof_array[i] = type; 00168 00169 if (iBase_SUCCESS != ierr) { 00170 MSQ_SETERR(err)(MsqError::INTERNAL_ERROR,"Failure to evaluate geometry. iBase ErrorCode %d\n", ierr); 00171 return; 00172 } 00173 } 00174 } 00175 } 00176 00177 void FreeSmoothDomain::closest_point( Mesh::VertexHandle handle, 00178 const Vector3D& position, 00179 Vector3D& closest, 00180 Vector3D& normal, 00181 MsqError& err ) const 00182 { 00183 iBase_EntityHandle geom = get_geometry( handle ); 00184 if (geom) { 00185 int ierr = closest_and_normal( geom, position, closest, normal ); 00186 if (iBase_SUCCESS != ierr) { 00187 MSQ_SETERR(err)(MsqError::INTERNAL_ERROR,"Failure to evaluate geometry. iBase ErrorCode %d\n", ierr); 00188 } 00189 } 00190 } 00191 00192 00193 } // namespace MeshKit