moab
ScdElementData.hpp
Go to the documentation of this file.
00001 
00016 #ifndef SCD_ELEMENT_DATA_HPP
00017 #define SCD_ELEMENT_DATA_HPP
00018 
00019 //
00020 // Class: ScdElementData
00021 //
00022 // Purpose: represent a rectangular element of mesh
00023 //
00024 // A ScdElement 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 "ScdVertexData.hpp"
00034 #include "Internals.hpp"
00035 #include "moab/Range.hpp"
00036 
00037 #include <vector>
00038 #include <algorithm>
00039 
00040 namespace moab {
00041 
00042 class ScdElementData : public SequenceData
00043 {
00044 
00046 class VertexDataRef
00047 {
00048 private:
00049   HomCoord minmax[2];
00050   HomXform xform, invXform;
00051   ScdVertexData *srcSeq;
00052 public:
00053   friend class ScdElementData;
00054   
00055   VertexDataRef(const HomCoord &min, const HomCoord &max,
00056                 const HomXform &tmp_xform, ScdVertexData *this_seq);
00057     
00058   bool contains(const HomCoord &coords) const;
00059 };
00060 
00061 private:
00062 
00065   HomCoord boxParams[3];
00066 
00069   int dIJK[3];
00070   
00073   int dIJKm1[3];
00074 
00076   int isPeriodic[2];
00077   
00079   ScdElementData();
00080 
00082   std::vector<VertexDataRef> vertexSeqRefs;
00083 
00084 public:
00085 
00087   ScdElementData( EntityHandle start_handle,
00088                   const int imin, const int jmin, const int kmin,
00089                   const int imax, const int jmax, const int kmax,
00090                   int *is_periodic);
00091   
00092   virtual ~ScdElementData();
00093   
00095   inline EntityHandle get_vertex(const HomCoord &coords) const;
00096   inline EntityHandle get_vertex(int i, int j, int k) const
00097     { return get_vertex(HomCoord(i,j,k)); }
00098   
00100   EntityHandle get_element(const int i, const int j, const int k) const;
00101   
00103   const HomCoord &min_params() const;
00104 
00106   const HomCoord &max_params() const;
00107   
00109   void param_extents(int &di, int &dj, int &dk) const;
00110 
00112   ErrorCode get_params(const EntityHandle ehandle,
00113                           int &i, int &j, int &k) const;
00114 
00116   inline int is_periodic_i() const {return isPeriodic[0];};
00117   
00119   inline int is_periodic_j() const {return isPeriodic[1];};
00120 
00121   inline void is_periodic(int is_p[2]) const 
00122       {is_p[0] = isPeriodic[0]; is_p[1] = isPeriodic[1];}
00123   
00125   int i_min() const {return (boxParams[0].hom_coord())[0];}
00126   int j_min() const {return (boxParams[0].hom_coord())[1];}
00127   int k_min() const {return (boxParams[0].hom_coord())[2];}
00128   int i_max() const {return (boxParams[1].hom_coord())[0];}
00129   int j_max() const {return (boxParams[1].hom_coord())[1];}
00130   int k_max() const {return (boxParams[1].hom_coord())[2];}
00131 
00134   bool boundary_complete() const;
00135 
00137   inline bool contains(const HomCoord &coords) const;
00138 
00140   inline bool contains_vertex(const HomCoord &coords) const;
00141 
00143   inline ErrorCode get_params_connectivity(const int i, const int j, const int k,
00144                                        std::vector<EntityHandle>& connectivity) const;
00145   
00151   ErrorCode add_vsequence(ScdVertexData *vseq, 
00152                              const HomCoord &p1, const HomCoord &q1,
00153                              const HomCoord &p2, const HomCoord &q2,
00154                              const HomCoord &p3, const HomCoord &q3,
00155                              bool bb_input = false,
00156                              const HomCoord &bb_min = HomCoord::unitv[0],
00157                              const HomCoord &bb_max = HomCoord::unitv[0]);
00158 
00159 
00160   SequenceData* subset( EntityHandle start, 
00161                         EntityHandle end,
00162                         const int* sequence_data_sizes,
00163                         const int* tag_data_sizes ) const;
00164   
00165   static EntityID calc_num_entities( EntityHandle start_handle,
00166                                        int irange,
00167                                        int jrange,
00168                                      int krange,
00169                                      int *is_periodic = NULL);
00170 
00171   unsigned long get_memory_use() const;
00172 };
00173 
00174 inline EntityHandle ScdElementData::get_element(const int i, const int j, const int k) const
00175 {
00176   return start_handle() + (i-i_min()) + (j-j_min())*dIJKm1[0] + (k-k_min())*dIJKm1[0]*dIJKm1[1];
00177 }
00178 
00179 inline const HomCoord &ScdElementData::min_params() const
00180 {
00181   return boxParams[0];
00182 }
00183 
00184 inline const HomCoord &ScdElementData::max_params() const
00185 {
00186   return boxParams[1];
00187 }
00188 
00190 inline void ScdElementData::param_extents(int &di, int &dj, int &dk) const
00191 {
00192   di = dIJK[0];
00193   dj = dIJK[1];
00194   dk = dIJK[2];
00195 }
00196 
00197 inline ErrorCode ScdElementData::get_params(const EntityHandle ehandle,
00198                                               int &i, int &j, int &k) const
00199 {
00200   if (TYPE_FROM_HANDLE(ehandle) != TYPE_FROM_HANDLE(start_handle())) return MB_FAILURE;
00201 
00202   int hdiff = ehandle - start_handle();
00203 
00204     // use double ?: test below because on some platforms, both sides of the : are
00205     // evaluated, and if dIJKm1[1] is zero, that'll generate a divide-by-zero
00206   k = (dIJKm1[1] > 0 ? hdiff / (dIJKm1[1] > 0 ? dIJKm1[0]*dIJKm1[1] : 1) : 0);
00207   j = (hdiff - (k*dIJKm1[0]*dIJKm1[1])) / dIJKm1[0];
00208   i = hdiff % dIJKm1[0];
00209 
00210   k += boxParams[0].k();
00211   j += boxParams[0].j();
00212   i += boxParams[0].i();
00213 
00214   return (ehandle >= start_handle() &&
00215           ehandle < start_handle()+size() &&
00216           i >= i_min() && i <= i_max() &&
00217           j >= j_min() && j <= j_max() &&
00218           k >= k_min() && k <= k_max()) ? MB_SUCCESS : MB_FAILURE;
00219 }
00220 
00221 inline bool ScdElementData::contains(const HomCoord &temp) const 
00222 {
00223     // upper bound is < instead of <= because element params max is one less
00224     // than vertex params max, except in case of 2d or 1d sequence
00225   return ((dIJKm1[0] && temp.i() >= boxParams[0].i() && temp.i() < boxParams[0].i()+dIJKm1[0]) &&
00226           ((!dIJKm1[1] && temp.j() == boxParams[1].j()) || 
00227            (dIJKm1[1] && temp.j() >= boxParams[0].j() && temp.j() < boxParams[0].j()+dIJKm1[1])) &&
00228           ((!dIJKm1[2] && temp.k() == boxParams[1].k()) || 
00229            (dIJKm1[2] && temp.k() >= boxParams[0].k() && temp.k() < boxParams[0].k()+dIJKm1[2])));
00230 }
00231   
00232 inline bool ScdElementData::contains_vertex(const HomCoord &temp) const 
00233 {
00234     // upper bound is < instead of <= because element params max is one less
00235     // than vertex params max, except in case of 2d or 1d sequence
00236   return ((dIJK[0] && temp.i() >= boxParams[0].i() && temp.i() < boxParams[0].i()+dIJK[0]) &&
00237           ((!dIJK[1] && temp.j() == boxParams[1].j()) || 
00238            (dIJK[1] && temp.j() >= boxParams[0].j() && temp.j() < boxParams[0].j()+dIJK[1])) &&
00239           ((!dIJK[2] && temp.k() == boxParams[1].k()) || 
00240            (dIJK[2] && temp.k() >= boxParams[0].k() && temp.k() < boxParams[0].k()+dIJK[2])));
00241 }
00242   
00243 inline bool ScdElementData::VertexDataRef::contains(const HomCoord &coords) const 
00244 {
00245   return (minmax[0] <= coords && minmax[1] >= coords);
00246 }
00247 
00248 inline ScdElementData::VertexDataRef::VertexDataRef(const HomCoord &this_min, const HomCoord &this_max,
00249                                     const HomXform &tmp_xform, ScdVertexData *this_seq)
00250     : xform(tmp_xform), invXform(tmp_xform.inverse()), srcSeq(this_seq)
00251 {
00252   minmax[0] = HomCoord(this_min);
00253   minmax[1] = HomCoord(this_max); 
00254 }
00255 
00256 inline EntityHandle ScdElementData::get_vertex(const HomCoord &coords) const
00257 {
00258   assert(boundary_complete());
00259    for (std::vector<VertexDataRef>::const_iterator it = vertexSeqRefs.begin();
00260         it != vertexSeqRefs.end(); it++) {
00261      if ((*it).minmax[0] <= coords && (*it).minmax[1] >= coords) {
00262          // first get the vertex block-local parameters
00263        HomCoord local_coords = coords / (*it).xform;
00264 
00265        assert((*it).srcSeq->contains(local_coords));
00266 
00267       // now get the vertex handle for those coords
00268        return (*it).srcSeq->get_vertex(local_coords);
00269      }
00270    }
00271    
00272      // got here, it's an error
00273    return 0;
00274 }
00275 
00276 inline ErrorCode ScdElementData::add_vsequence(ScdVertexData *vseq, 
00277                                                  const HomCoord &p1, const HomCoord &q1,
00278                                                  const HomCoord &p2, const HomCoord &q2, 
00279                                                  const HomCoord &p3, const HomCoord &q3,
00280                                                  bool bb_input,
00281                                                  const HomCoord &bb_min,
00282                                                  const HomCoord &bb_max)
00283 {
00284     // compute the transform given the vseq-local parameters and the mapping to
00285     // this element sequence's parameters passed in minmax
00286   HomXform M;
00287   M.three_pt_xform(p1, q1, p2, q2, p3, q3);
00288   
00289     // min and max in element seq's parameter system may not be same as those in 
00290     // vseq's system, so need to take min/max
00291 
00292   HomCoord minmax[2];
00293   if (bb_input) {
00294     minmax[0] = bb_min;
00295     minmax[1] = bb_max;
00296   }
00297   else {
00298     minmax[0] = vseq->min_params() * M;
00299     minmax[1] = vseq->max_params() * M;
00300   }
00301   
00302     // check against other vseq's to make sure they don't overlap
00303   for (std::vector<VertexDataRef>::const_iterator vsit = vertexSeqRefs.begin();
00304        vsit != vertexSeqRefs.end(); vsit++) 
00305     if ((*vsit).contains(minmax[0]) || (*vsit).contains(minmax[1])) 
00306       return MB_FAILURE;
00307     
00308   HomCoord tmp_min(std::min(minmax[0].i(), minmax[1].i()), 
00309                    std::min(minmax[0].j(), minmax[1].j()), 
00310                    std::min(minmax[0].k(), minmax[1].k()));
00311   HomCoord tmp_max(std::max(minmax[0].i(), minmax[1].i()), 
00312                    std::max(minmax[0].j(), minmax[1].j()), 
00313                    std::max(minmax[0].k(), minmax[1].k()));
00314 
00315   
00316     // set up a new vertex sequence reference
00317   VertexDataRef tmp_seq_ref(tmp_min, tmp_max, M, vseq);
00318 
00319     // add to the list
00320   vertexSeqRefs.push_back(tmp_seq_ref);
00321   
00322   return MB_SUCCESS;
00323 }
00324 
00325 inline ErrorCode ScdElementData::get_params_connectivity(const int i, const int j, const int k,
00326                                                            std::vector<EntityHandle>& connectivity) const
00327 {
00328   if (contains(HomCoord(i, j, k)) == false) return MB_FAILURE;
00329   
00330   int ip1 = (isPeriodic[0] ? (i+1)%dIJKm1[0] : i+1),
00331       jp1 = (isPeriodic[1] ? (j+1)%dIJKm1[1] : j+1);
00332   
00333   connectivity.push_back(get_vertex(i, j, k));
00334   connectivity.push_back(get_vertex(ip1, j, k));
00335   if (CN::Dimension(TYPE_FROM_HANDLE(start_handle())) < 2) return MB_SUCCESS;
00336   connectivity.push_back(get_vertex(ip1, jp1, k));
00337   connectivity.push_back(get_vertex(i, jp1, k));
00338   if (CN::Dimension(TYPE_FROM_HANDLE(start_handle())) < 3) return MB_SUCCESS;
00339   connectivity.push_back(get_vertex(i, j, k+1));
00340   connectivity.push_back(get_vertex(ip1, j, k+1));
00341   connectivity.push_back(get_vertex(ip1, jp1, k+1));
00342   connectivity.push_back(get_vertex(i, jp1, k+1));
00343   return MB_SUCCESS;
00344 }
00345   
00346 } // namespace moab
00347 
00348 #endif
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines