Branch data Line data Source code
1 : : /**
2 : : * MOAB, a Mesh-Oriented datABase, is a software component for creating,
3 : : * storing and accessing finite element mesh data.
4 : : *
5 : : * Copyright 2004 Sandia Corporation. Under the terms of Contract
6 : : * DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government
7 : : * retains certain rights in this software.
8 : : *
9 : : * This library is free software; you can redistribute it and/or
10 : : * modify it under the terms of the GNU Lesser General Public
11 : : * License as published by the Free Software Foundation; either
12 : : * version 2.1 of the License, or (at your option) any later version.
13 : : *
14 : : */
15 : :
16 : : #ifndef SWEPT_ELEMENT_DATA_HPP
17 : : #define SWEPT_ELEMENT_DATA_HPP
18 : :
19 : : //
20 : : // Class: SweptElementData
21 : : //
22 : : // Purpose: represent a rectangular element of mesh
23 : : //
24 : : // A SweptElement represents a rectangular element of mesh, including both vertices and
25 : : // elements, and the parametric space used to address that element. Vertex data,
26 : : // i.e. coordinates, may not be stored directly in the element, but the element returns
27 : : // information about the vertex handles of vertices in the element. Vertex and element
28 : : // handles associated with the element are each contiguous.
29 : :
30 : : #include "SequenceData.hpp"
31 : : #include "moab/HomXform.hpp"
32 : : #include "moab/CN.hpp"
33 : : #include "SweptVertexData.hpp"
34 : : #include "Internals.hpp"
35 : : #include "moab/Range.hpp"
36 : :
37 : : #include <vector>
38 : : #include <algorithm>
39 : :
40 : : namespace moab
41 : : {
42 : :
43 : : class SweptElementData : public SequenceData
44 : : {
45 : :
46 : : //! structure to hold references to bounding vertex blocks
47 [ # # ]: 0 : class VertexDataRef
48 : : {
49 : : private:
50 : : HomCoord minmax[2];
51 : : HomXform xform, invXform;
52 : : SweptVertexData* srcSeq;
53 : :
54 : : public:
55 : : friend class SweptElementData;
56 : :
57 : : VertexDataRef( const HomCoord& min, const HomCoord& max, const HomXform& tmp_xform, SweptVertexData* this_seq );
58 : :
59 : : bool contains( const HomCoord& coords ) const;
60 : : };
61 : :
62 : : private:
63 : : //! parameter min/max/stride, in homogeneous coords ijkh
64 : : HomCoord elementParams[3];
65 : :
66 : : //! difference between max and min params plus one (i.e. # VERTICES in
67 : : //! each parametric direction)
68 : : int dIJK[3];
69 : :
70 : : //! difference between max and min params (i.e. # ELEMENTS in
71 : : //! each parametric direction)
72 : : int dIJKm1[3];
73 : :
74 : : //! bare constructor, so compiler doesn't create one for me
75 : : SweptElementData();
76 : :
77 : : //! list of bounding vertex blocks
78 : : std::vector< VertexDataRef > vertexSeqRefs;
79 : :
80 : : public:
81 : : //! constructor
82 : : SweptElementData( EntityHandle start_handle, const int imin, const int jmin, const int kmin, const int imax,
83 : : const int jmax, const int kmax, const int* Cq );
84 : :
85 : : virtual ~SweptElementData();
86 : :
87 : : //! get handle of vertex at homogeneous coords
88 : : inline EntityHandle get_vertex( const HomCoord& coords ) const;
89 : : inline EntityHandle get_vertex( int i, int j, int k ) const
90 : : {
91 : : return get_vertex( HomCoord( i, j, k ) );
92 : : }
93 : :
94 : : //! get handle of element at i, j, k
95 : : EntityHandle get_element( const int i, const int j, const int k ) const;
96 : :
97 : : //! get min params for this element
98 : : const HomCoord& min_params() const;
99 : :
100 : : //! get max params for this element
101 : : const HomCoord& max_params() const;
102 : :
103 : : //! get the number of vertices in each direction, inclusive
104 : : void param_extents( int& di, int& dj, int& dk ) const;
105 : :
106 : : //! given a handle, get the corresponding parameters
107 : : ErrorCode get_params( const EntityHandle ehandle, int& i, int& j, int& k ) const;
108 : :
109 : : //! convenience functions for parameter extents
110 : : int i_min() const
111 : : {
112 : : return ( elementParams[0].hom_coord() )[0];
113 : : }
114 : : int j_min() const
115 : : {
116 : : return ( elementParams[0].hom_coord() )[1];
117 : : }
118 : : int k_min() const
119 : : {
120 : : return ( elementParams[0].hom_coord() )[2];
121 : : }
122 : : int i_max() const
123 : : {
124 : : return ( elementParams[1].hom_coord() )[0];
125 : : }
126 : : int j_max() const
127 : : {
128 : : return ( elementParams[1].hom_coord() )[1];
129 : : }
130 : : int k_max() const
131 : : {
132 : : return ( elementParams[1].hom_coord() )[2];
133 : : }
134 : :
135 : : //! test the bounding vertex sequences and determine whether they fully
136 : : //! define the vertices covering this element block's parameter space
137 : : bool boundary_complete() const;
138 : :
139 : : //! test whether this sequence contains these parameters
140 : : inline bool contains( const HomCoord& coords ) const;
141 : :
142 : : //! get connectivity of an entity given entity's parameters
143 : : inline ErrorCode get_params_connectivity( const int i, const int j, const int k,
144 : : std::vector< EntityHandle >& connectivity ) const;
145 : :
146 : : //! add a vertex seq ref to this element sequence;
147 : : //! if bb_input is true, bounding box (in eseq-local coords) of vseq being added
148 : : //! is input in bb_min and bb_max (allows partial sharing of vseq rather than the whole
149 : : //! vseq); if it's false, the whole vseq is referenced and the eseq-local coordinates
150 : : //! is computed from the transformed bounding box of the vseq
151 : : ErrorCode add_vsequence( SweptVertexData* vseq, const HomCoord& p1, const HomCoord& q1, const HomCoord& p2,
152 : : const HomCoord& q2, const HomCoord& p3, const HomCoord& q3, bool bb_input = false,
153 : : const HomCoord& bb_min = HomCoord::unitv[0], const HomCoord& bb_max = HomCoord::unitv[0] );
154 : :
155 : : SequenceData* subset( EntityHandle start, EntityHandle end, const int* sequence_data_sizes,
156 : : const int* tag_data_sizes ) const;
157 : :
158 : : static EntityID calc_num_entities( EntityHandle start_handle, int irange, int jrange, int krange );
159 : :
160 : : unsigned long get_memory_use() const;
161 : : };
162 : :
163 : : inline EntityHandle SweptElementData::get_element( const int i, const int j, const int k ) const
164 : : {
165 : : return start_handle() + ( i - i_min() ) + ( j - j_min() ) * dIJKm1[0] + ( k - k_min() ) * dIJKm1[0] * dIJKm1[1];
166 : : }
167 : :
168 : : inline const HomCoord& SweptElementData::min_params() const
169 : : {
170 : : return elementParams[0];
171 : : }
172 : :
173 : : inline const HomCoord& SweptElementData::max_params() const
174 : : {
175 : : return elementParams[1];
176 : : }
177 : :
178 : : //! get the number of vertices in each direction, inclusive
179 : : inline void SweptElementData::param_extents( int& di, int& dj, int& dk ) const
180 : : {
181 : : di = dIJK[0];
182 : : dj = dIJK[1];
183 : : dk = dIJK[2];
184 : : }
185 : :
186 : : inline ErrorCode SweptElementData::get_params( const EntityHandle ehandle, int& i, int& j, int& k ) const
187 : : {
188 : : if( TYPE_FROM_HANDLE( ehandle ) != TYPE_FROM_HANDLE( start_handle() ) ) return MB_FAILURE;
189 : :
190 : : int hdiff = ehandle - start_handle();
191 : :
192 : : // use double ?: test below because on some platforms, both sides of the : are
193 : : // evaluated, and if dIJKm1[1] is zero, that'll generate a divide-by-zero
194 : : k = ( dIJKm1[1] > 0 ? hdiff / ( dIJKm1[1] > 0 ? dIJKm1[0] * dIJKm1[1] : 1 ) : 0 );
195 : : j = ( hdiff - ( k * dIJKm1[0] * dIJKm1[1] ) ) / dIJKm1[0];
196 : : i = hdiff % dIJKm1[0];
197 : :
198 : : k += elementParams[0].k();
199 : : j += elementParams[0].j();
200 : : i += elementParams[0].i();
201 : :
202 : : return ( ehandle >= start_handle() && ehandle < start_handle() + size() && i >= i_min() && i <= i_max() &&
203 : : j >= j_min() && j <= j_max() && k >= k_min() && k <= k_max() )
204 : : ? MB_SUCCESS
205 : : : MB_FAILURE;
206 : : }
207 : :
208 : : inline bool SweptElementData::contains( const HomCoord& temp ) const
209 : : {
210 : : // upper bound is < instead of <= because element params max is one less
211 : : // than vertex params max
212 : : return ( temp >= elementParams[0] && temp < elementParams[1] );
213 : : }
214 : :
215 : 0 : inline bool SweptElementData::VertexDataRef::contains( const HomCoord& coords ) const
216 : : {
217 [ # # ][ # # ]: 0 : return ( minmax[0] <= coords && minmax[1] >= coords );
218 : : }
219 : :
220 : : inline SweptElementData::VertexDataRef::VertexDataRef( const HomCoord& this_min, const HomCoord& this_max,
221 : : const HomXform& tmp_xform, SweptVertexData* this_seq )
222 : : : xform( tmp_xform ), invXform( tmp_xform.inverse() ), srcSeq( this_seq )
223 : : {
224 : : minmax[0] = HomCoord( this_min );
225 : : minmax[1] = HomCoord( this_max );
226 : : }
227 : :
228 : : inline EntityHandle SweptElementData::get_vertex( const HomCoord& coords ) const
229 : : {
230 : : assert( boundary_complete() );
231 : : for( std::vector< VertexDataRef >::const_iterator it = vertexSeqRefs.begin(); it != vertexSeqRefs.end(); ++it )
232 : : {
233 : : if( ( *it ).minmax[0] <= coords && ( *it ).minmax[1] >= coords )
234 : : {
235 : : // first get the vertex block-local parameters
236 : : HomCoord local_coords = coords / ( *it ).xform;
237 : :
238 : : // now get the vertex handle for those coords
239 : : return ( *it ).srcSeq->get_vertex( local_coords );
240 : : }
241 : : }
242 : :
243 : : // got here, it's an error
244 : : return 0;
245 : : }
246 : :
247 : : inline ErrorCode SweptElementData::add_vsequence( SweptVertexData* vseq, const HomCoord& p1, const HomCoord& q1,
248 : : const HomCoord& p2, const HomCoord& q2, const HomCoord& p3,
249 : : const HomCoord& q3, bool bb_input, const HomCoord& bb_min,
250 : : const HomCoord& bb_max )
251 : : {
252 : : // compute the transform given the vseq-local parameters and the mapping to
253 : : // this element sequence's parameters passed in minmax
254 : : HomXform M;
255 : : M.three_pt_xform( p1, q1, p2, q2, p3, q3 );
256 : :
257 : : // min and max in element seq's parameter system may not be same as those in
258 : : // vseq's system, so need to take min/max
259 : :
260 : : HomCoord minmax[2];
261 : : if( bb_input )
262 : : {
263 : : minmax[0] = bb_min;
264 : : minmax[1] = bb_max;
265 : : }
266 : : else
267 : : {
268 : : minmax[0] = vseq->min_params() * M;
269 : : minmax[1] = vseq->max_params() * M;
270 : : }
271 : :
272 : : // check against other vseq's to make sure they don't overlap
273 : : for( std::vector< VertexDataRef >::const_iterator vsit = vertexSeqRefs.begin(); vsit != vertexSeqRefs.end();
274 : : ++vsit )
275 : : if( ( *vsit ).contains( minmax[0] ) || ( *vsit ).contains( minmax[1] ) ) return MB_FAILURE;
276 : :
277 : : HomCoord tmp_min( std::min( minmax[0].i(), minmax[1].i() ), std::min( minmax[0].j(), minmax[1].j() ),
278 : : std::min( minmax[0].k(), minmax[1].k() ) );
279 : : HomCoord tmp_max( std::max( minmax[0].i(), minmax[1].i() ), std::max( minmax[0].j(), minmax[1].j() ),
280 : : std::max( minmax[0].k(), minmax[1].k() ) );
281 : :
282 : : // set up a new vertex sequence reference
283 : : VertexDataRef tmp_seq_ref( tmp_min, tmp_max, M, vseq );
284 : :
285 : : // add to the list
286 : : vertexSeqRefs.push_back( tmp_seq_ref );
287 : :
288 : : return MB_SUCCESS;
289 : : }
290 : :
291 : : inline ErrorCode SweptElementData::get_params_connectivity( const int i, const int j, const int k,
292 : : std::vector< EntityHandle >& connectivity ) const
293 : : {
294 : : if( contains( HomCoord( i, j, k ) ) == false ) return MB_FAILURE;
295 : :
296 : : connectivity.push_back( get_vertex( i, j, k ) );
297 : : connectivity.push_back( get_vertex( i + 1, j, k ) );
298 : : if( CN::Dimension( TYPE_FROM_HANDLE( start_handle() ) ) < 2 ) return MB_SUCCESS;
299 : : connectivity.push_back( get_vertex( i + 1, j + 1, k ) );
300 : : connectivity.push_back( get_vertex( i, j + 1, k ) );
301 : : if( CN::Dimension( TYPE_FROM_HANDLE( start_handle() ) ) < 3 ) return MB_SUCCESS;
302 : : connectivity.push_back( get_vertex( i, j, k + 1 ) );
303 : : connectivity.push_back( get_vertex( i + 1, j, k + 1 ) );
304 : : connectivity.push_back( get_vertex( i + 1, j + 1, k + 1 ) );
305 : : connectivity.push_back( get_vertex( i, j + 1, k + 1 ) );
306 : : return MB_SUCCESS;
307 : : }
308 : :
309 : : } // namespace moab
310 : :
311 : : #endif
|