Mesh Oriented datABase
(version 5.4.1)
Array-based unstructured mesh datastructure
|
00001 /** 00002 * MOAB, a Mesh-Oriented datABase, is a software component for creating, 00003 * storing and accessing finite element mesh data. 00004 * 00005 * Copyright 2004 Sandia Corporation. Under the terms of Contract 00006 * DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government 00007 * retains certain rights in this software. 00008 * 00009 * This library is free software; you can redistribute it and/or 00010 * modify it under the terms of the GNU Lesser General Public 00011 * License as published by the Free Software Foundation; either 00012 * version 2.1 of the License, or (at your option) any later version. 00013 * 00014 */ 00015 00016 #ifndef SWEPT_ELEMENT_DATA_HPP 00017 #define SWEPT_ELEMENT_DATA_HPP 00018 00019 // 00020 // Class: SweptElementData 00021 // 00022 // Purpose: represent a rectangular element of mesh 00023 // 00024 // A SweptElement represents a rectangular element of mesh, including both vertices and 00025 // elements, and the parametric space used to address that element. Vertex data, 00026 // i.e. coordinates, may not be stored directly in the element, but the element returns 00027 // information about the vertex handles of vertices in the element. Vertex and element 00028 // handles associated with the element are each contiguous. 00029 00030 #include "SequenceData.hpp" 00031 #include "moab/HomXform.hpp" 00032 #include "moab/CN.hpp" 00033 #include "SweptVertexData.hpp" 00034 #include "Internals.hpp" 00035 #include "moab/Range.hpp" 00036 00037 #include <vector> 00038 #include <algorithm> 00039 00040 namespace moab 00041 { 00042 00043 class SweptElementData : public SequenceData 00044 { 00045 00046 //! structure to hold references to bounding vertex blocks 00047 class VertexDataRef 00048 { 00049 private: 00050 HomCoord minmax[2]; 00051 HomXform xform, invXform; 00052 SweptVertexData* srcSeq; 00053 00054 public: 00055 friend class SweptElementData; 00056 00057 VertexDataRef( const HomCoord& min, const HomCoord& max, const HomXform& tmp_xform, SweptVertexData* this_seq ); 00058 00059 bool contains( const HomCoord& coords ) const; 00060 }; 00061 00062 private: 00063 //! parameter min/max/stride, in homogeneous coords ijkh 00064 HomCoord elementParams[3]; 00065 00066 //! difference between max and min params plus one (i.e. # VERTICES in 00067 //! each parametric direction) 00068 int dIJK[3]; 00069 00070 //! difference between max and min params (i.e. # ELEMENTS in 00071 //! each parametric direction) 00072 int dIJKm1[3]; 00073 00074 //! bare constructor, so compiler doesn't create one for me 00075 SweptElementData(); 00076 00077 //! list of bounding vertex blocks 00078 std::vector< VertexDataRef > vertexSeqRefs; 00079 00080 public: 00081 //! constructor 00082 SweptElementData( EntityHandle start_handle, 00083 const int imin, 00084 const int jmin, 00085 const int kmin, 00086 const int imax, 00087 const int jmax, 00088 const int kmax, 00089 const int* Cq ); 00090 00091 virtual ~SweptElementData(); 00092 00093 //! get handle of vertex at homogeneous coords 00094 inline EntityHandle get_vertex( const HomCoord& coords ) const; 00095 inline EntityHandle get_vertex( int i, int j, int k ) const 00096 { 00097 return get_vertex( HomCoord( i, j, k ) ); 00098 } 00099 00100 //! get handle of element at i, j, k 00101 EntityHandle get_element( const int i, const int j, const int k ) const; 00102 00103 //! get min params for this element 00104 const HomCoord& min_params() const; 00105 00106 //! get max params for this element 00107 const HomCoord& max_params() const; 00108 00109 //! get the number of vertices in each direction, inclusive 00110 void param_extents( int& di, int& dj, int& dk ) const; 00111 00112 //! given a handle, get the corresponding parameters 00113 ErrorCode get_params( const EntityHandle ehandle, int& i, int& j, int& k ) const; 00114 00115 //! convenience functions for parameter extents 00116 int i_min() const 00117 { 00118 return ( elementParams[0].hom_coord() )[0]; 00119 } 00120 int j_min() const 00121 { 00122 return ( elementParams[0].hom_coord() )[1]; 00123 } 00124 int k_min() const 00125 { 00126 return ( elementParams[0].hom_coord() )[2]; 00127 } 00128 int i_max() const 00129 { 00130 return ( elementParams[1].hom_coord() )[0]; 00131 } 00132 int j_max() const 00133 { 00134 return ( elementParams[1].hom_coord() )[1]; 00135 } 00136 int k_max() const 00137 { 00138 return ( elementParams[1].hom_coord() )[2]; 00139 } 00140 00141 //! test the bounding vertex sequences and determine whether they fully 00142 //! define the vertices covering this element block's parameter space 00143 bool boundary_complete() const; 00144 00145 //! test whether this sequence contains these parameters 00146 inline bool contains( const HomCoord& coords ) const; 00147 00148 //! get connectivity of an entity given entity's parameters 00149 inline ErrorCode get_params_connectivity( const int i, 00150 const int j, 00151 const int k, 00152 std::vector< EntityHandle >& connectivity ) const; 00153 00154 //! add a vertex seq ref to this element sequence; 00155 //! if bb_input is true, bounding box (in eseq-local coords) of vseq being added 00156 //! is input in bb_min and bb_max (allows partial sharing of vseq rather than the whole 00157 //! vseq); if it's false, the whole vseq is referenced and the eseq-local coordinates 00158 //! is computed from the transformed bounding box of the vseq 00159 ErrorCode add_vsequence( SweptVertexData* vseq, 00160 const HomCoord& p1, 00161 const HomCoord& q1, 00162 const HomCoord& p2, 00163 const HomCoord& q2, 00164 const HomCoord& p3, 00165 const HomCoord& q3, 00166 bool bb_input = false, 00167 const HomCoord& bb_min = HomCoord::unitv[0], 00168 const HomCoord& bb_max = HomCoord::unitv[0] ); 00169 00170 SequenceData* subset( EntityHandle start, 00171 EntityHandle end, 00172 const int* sequence_data_sizes, 00173 const int* tag_data_sizes ) const; 00174 00175 static EntityID calc_num_entities( EntityHandle start_handle, int irange, int jrange, int krange ); 00176 00177 unsigned long get_memory_use() const; 00178 }; 00179 00180 inline EntityHandle SweptElementData::get_element( const int i, const int j, const int k ) const 00181 { 00182 return start_handle() + ( i - i_min() ) + ( j - j_min() ) * dIJKm1[0] + ( k - k_min() ) * dIJKm1[0] * dIJKm1[1]; 00183 } 00184 00185 inline const HomCoord& SweptElementData::min_params() const 00186 { 00187 return elementParams[0]; 00188 } 00189 00190 inline const HomCoord& SweptElementData::max_params() const 00191 { 00192 return elementParams[1]; 00193 } 00194 00195 //! get the number of vertices in each direction, inclusive 00196 inline void SweptElementData::param_extents( int& di, int& dj, int& dk ) const 00197 { 00198 di = dIJK[0]; 00199 dj = dIJK[1]; 00200 dk = dIJK[2]; 00201 } 00202 00203 inline ErrorCode SweptElementData::get_params( const EntityHandle ehandle, int& i, int& j, int& k ) const 00204 { 00205 if( TYPE_FROM_HANDLE( ehandle ) != TYPE_FROM_HANDLE( start_handle() ) ) return MB_FAILURE; 00206 00207 int hdiff = ehandle - start_handle(); 00208 00209 // use double ?: test below because on some platforms, both sides of the : are 00210 // evaluated, and if dIJKm1[1] is zero, that'll generate a divide-by-zero 00211 k = ( dIJKm1[1] > 0 ? hdiff / ( dIJKm1[1] > 0 ? dIJKm1[0] * dIJKm1[1] : 1 ) : 0 ); 00212 j = ( hdiff - ( k * dIJKm1[0] * dIJKm1[1] ) ) / dIJKm1[0]; 00213 i = hdiff % dIJKm1[0]; 00214 00215 k += elementParams[0].k(); 00216 j += elementParams[0].j(); 00217 i += elementParams[0].i(); 00218 00219 return ( ehandle >= start_handle() && ehandle < start_handle() + size() && i >= i_min() && i <= i_max() && 00220 j >= j_min() && j <= j_max() && k >= k_min() && k <= k_max() ) 00221 ? MB_SUCCESS 00222 : MB_FAILURE; 00223 } 00224 00225 inline bool SweptElementData::contains( const HomCoord& temp ) const 00226 { 00227 // upper bound is < instead of <= because element params max is one less 00228 // than vertex params max 00229 return ( temp >= elementParams[0] && temp < elementParams[1] ); 00230 } 00231 00232 inline bool SweptElementData::VertexDataRef::contains( const HomCoord& coords ) const 00233 { 00234 return ( minmax[0] <= coords && minmax[1] >= coords ); 00235 } 00236 00237 inline SweptElementData::VertexDataRef::VertexDataRef( const HomCoord& this_min, 00238 const HomCoord& this_max, 00239 const HomXform& tmp_xform, 00240 SweptVertexData* this_seq ) 00241 : xform( tmp_xform ), invXform( tmp_xform.inverse() ), srcSeq( this_seq ) 00242 { 00243 minmax[0] = HomCoord( this_min ); 00244 minmax[1] = HomCoord( this_max ); 00245 } 00246 00247 inline EntityHandle SweptElementData::get_vertex( const HomCoord& coords ) const 00248 { 00249 assert( boundary_complete() ); 00250 for( std::vector< VertexDataRef >::const_iterator it = vertexSeqRefs.begin(); it != vertexSeqRefs.end(); ++it ) 00251 { 00252 if( ( *it ).minmax[0] <= coords && ( *it ).minmax[1] >= coords ) 00253 { 00254 // first get the vertex block-local parameters 00255 HomCoord local_coords = coords / ( *it ).xform; 00256 00257 // now get the vertex handle for those coords 00258 return ( *it ).srcSeq->get_vertex( local_coords ); 00259 } 00260 } 00261 00262 // got here, it's an error 00263 return 0; 00264 } 00265 00266 inline ErrorCode SweptElementData::add_vsequence( SweptVertexData* vseq, 00267 const HomCoord& p1, 00268 const HomCoord& q1, 00269 const HomCoord& p2, 00270 const HomCoord& q2, 00271 const HomCoord& p3, 00272 const HomCoord& q3, 00273 bool bb_input, 00274 const HomCoord& bb_min, 00275 const HomCoord& bb_max ) 00276 { 00277 // compute the transform given the vseq-local parameters and the mapping to 00278 // this element sequence's parameters passed in minmax 00279 HomXform M; 00280 M.three_pt_xform( p1, q1, p2, q2, p3, q3 ); 00281 00282 // min and max in element seq's parameter system may not be same as those in 00283 // vseq's system, so need to take min/max 00284 00285 HomCoord minmax[2]; 00286 if( bb_input ) 00287 { 00288 minmax[0] = bb_min; 00289 minmax[1] = bb_max; 00290 } 00291 else 00292 { 00293 minmax[0] = vseq->min_params() * M; 00294 minmax[1] = vseq->max_params() * M; 00295 } 00296 00297 // check against other vseq's to make sure they don't overlap 00298 for( std::vector< VertexDataRef >::const_iterator vsit = vertexSeqRefs.begin(); vsit != vertexSeqRefs.end(); 00299 ++vsit ) 00300 if( ( *vsit ).contains( minmax[0] ) || ( *vsit ).contains( minmax[1] ) ) return MB_FAILURE; 00301 00302 HomCoord tmp_min( std::min( minmax[0].i(), minmax[1].i() ), std::min( minmax[0].j(), minmax[1].j() ), 00303 std::min( minmax[0].k(), minmax[1].k() ) ); 00304 HomCoord tmp_max( std::max( minmax[0].i(), minmax[1].i() ), std::max( minmax[0].j(), minmax[1].j() ), 00305 std::max( minmax[0].k(), minmax[1].k() ) ); 00306 00307 // set up a new vertex sequence reference 00308 VertexDataRef tmp_seq_ref( tmp_min, tmp_max, M, vseq ); 00309 00310 // add to the list 00311 vertexSeqRefs.push_back( tmp_seq_ref ); 00312 00313 return MB_SUCCESS; 00314 } 00315 00316 inline ErrorCode SweptElementData::get_params_connectivity( const int i, 00317 const int j, 00318 const int k, 00319 std::vector< EntityHandle >& connectivity ) const 00320 { 00321 if( contains( HomCoord( i, j, k ) ) == false ) return MB_FAILURE; 00322 00323 connectivity.push_back( get_vertex( i, j, k ) ); 00324 connectivity.push_back( get_vertex( i + 1, j, k ) ); 00325 if( CN::Dimension( TYPE_FROM_HANDLE( start_handle() ) ) < 2 ) return MB_SUCCESS; 00326 connectivity.push_back( get_vertex( i + 1, j + 1, k ) ); 00327 connectivity.push_back( get_vertex( i, j + 1, k ) ); 00328 if( CN::Dimension( TYPE_FROM_HANDLE( start_handle() ) ) < 3 ) return MB_SUCCESS; 00329 connectivity.push_back( get_vertex( i, j, k + 1 ) ); 00330 connectivity.push_back( get_vertex( i + 1, j, k + 1 ) ); 00331 connectivity.push_back( get_vertex( i + 1, j + 1, k + 1 ) ); 00332 connectivity.push_back( get_vertex( i, j + 1, k + 1 ) ); 00333 return MB_SUCCESS; 00334 } 00335 00336 } // namespace moab 00337 00338 #endif