![]() |
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
00038 #include
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