moab
ScdInterface.hpp
Go to the documentation of this file.
00001 
00003 #ifndef SCD_INTERFACE
00004 #define SCD_INTERFACE
00005 
00006 #include "moab/Interface.hpp"
00007 #include "moab/HomXform.hpp"
00008 
00009 #include <iostream>
00010 #include <vector>    
00011 #include "assert.h"
00012 
00013 namespace moab {
00014 
00015 class StructuredElementSeq;
00016 class EntitySequence;
00017 class ScdVertexData;
00018 class EntitySequence;
00019 class ScdBox;
00020 class ParallelComm;
00021 
00103 
00104 class ScdParData {
00105 public:
00106   ScdParData() : partMethod(NOPART), pComm(NULL) {
00107     gDims[0] = gDims[1] = gDims[2] = gDims[3] = gDims[4] = gDims[5] = 0;
00108     gPeriodic[0] = gPeriodic[1] = gPeriodic[2] = 0;
00109     pDims[0] = pDims[1] = pDims[2] = 0;
00110   }
00111 
00115   enum PartitionMethod {ALLJORKORI = 0, ALLJKBAL, SQIJ, SQJK, SQIJK, TRIVIAL, RCBZOLTAN, NOPART};
00116 
00118   static const char *PartitionMethodNames[NOPART + 1];
00119 
00121   int partMethod;
00122   
00124   int gDims[6];
00125 
00127   int gPeriodic[3];
00128 
00130   int pDims[3];
00131 
00133   ParallelComm *pComm;
00134 };
00135   
00136 class ScdInterface 
00137 {
00138 public:
00139   friend class ScdBox;
00140 
00142 
00149   ScdInterface(Interface *impl, bool find_boxes = false);
00150   
00151     // Destructor
00152   ~ScdInterface();
00153 
00155   Interface *impl() const;
00156   
00158 
00175   ErrorCode construct_box(HomCoord low, HomCoord high, const double * const coords, unsigned int num_coords,
00176                           ScdBox *& new_box, int * const lperiodic = NULL, 
00177                           ScdParData * const par_data = NULL,
00178                           bool assign_global_ids = false, int resolve_shared_ents = -1);
00179 
00181 
00191   ErrorCode create_scd_sequence(HomCoord low, HomCoord high, EntityType type,
00192                                 int starting_id, ScdBox *&new_box, 
00193                                 int *is_periodic = NULL);
00194 
00196 
00200   ErrorCode find_boxes(std::vector<ScdBox*> &boxes);
00201 
00203 
00207   ErrorCode find_boxes(Range &boxes);
00208 
00210 
00214   ErrorCode get_boxes(std::vector<ScdBox*> &boxes);
00215 
00217 
00220   Tag box_dims_tag(bool create_if_missing = true);
00221 
00223 
00226   Tag global_box_dims_tag(bool create_if_missing = true);
00227 
00229 
00232   Tag part_method_tag(bool create_if_missing = true);
00233 
00235 
00238   Tag box_periodic_tag(bool create_if_missing = true);
00239 
00241 
00244   Tag box_set_tag(bool create_if_missing = true);
00245 
00247 
00250   ScdBox *get_scd_box(EntityHandle eh);
00251 
00253 
00264   static ErrorCode compute_partition(int np, int nr, const ScdParData &par_data,
00265                                      int *ldims, int *lperiodic = NULL, int *pdims = NULL);
00266   
00268 
00280   static ErrorCode get_neighbor(int np, int nr, const ScdParData &spd, const int * const dijk,
00281                                 int &pto, int *rdims, int *facedims, int *across_bdy);
00282   
00284 
00286   ErrorCode tag_shared_vertices(ParallelComm *pcomm, EntityHandle seth);
00287   
00289 
00291   ErrorCode tag_shared_vertices(ParallelComm *pcomm, ScdBox *box);
00292   
00293 protected:
00295   ErrorCode remove_box(ScdBox *box);
00296   
00298   ErrorCode add_box(ScdBox *box);
00299   
00300 private:
00302 
00307   ErrorCode create_box_set(const HomCoord low, const HomCoord high,
00308                            EntityHandle &scd_set,
00309                            int *is_periodic = NULL);
00310   
00312 
00316   inline static ErrorCode compute_partition_alljorkori(int np, int nr,
00317                                                        const int * const gijk, const int * const gperiodic, 
00318                                                        int *lijk, int *lperiodic, int *pijk);
00319   
00321 
00325   inline static ErrorCode compute_partition_alljkbal(int np, int nr, const int * const gijk, const int * const gperiodic, 
00326                                                      int *lijk, int *lperiodic, int *pijk);
00327 
00329 
00332   inline static ErrorCode compute_partition_sqij(int np, int nr, const int * const gijk, const int * const gperiodic, 
00333                                                  int *lijk, int *lperiodic, int *pijk);
00334   
00336 
00339   inline static ErrorCode compute_partition_sqjk(int np, int nr, const int * const gijk, const int * const gperiodic, 
00340                                                  int *lijk, int *lperiodic, int *pijk);
00341 
00343 
00346   inline static ErrorCode compute_partition_sqijk(int np, int nr, const int * const gijk, const int * const gperiodic, 
00347                                                   int *lijk, int *lperiodic, int *pijk);
00348 
00350 
00356   static ErrorCode get_shared_vertices(ParallelComm *pcomm, ScdBox *box, std::vector<int> &procs,
00357                                        std::vector<int> &offsets, std::vector<int> &shared_indices);
00358 
00359   static ErrorCode get_indices(const int * const ldims, const int * const rdims, const int * const across_bdy, 
00360                                int *face_dims, std::vector<int> &shared_indices);
00361   
00362   static ErrorCode get_neighbor_alljorkori(int np, int pfrom,
00363                                            const int * const gdims, const int * const gperiodic, const int * const dijk, 
00364                                            int &pto, int *rdims, int *facedims, int *across_bdy);
00365   
00366   static ErrorCode get_neighbor_alljkbal(int np, int pfrom,
00367                                          const int * const gdims, const int * const gperiodic, const int * const dijk, 
00368                                          int &pto, int *rdims, int *facedims, int *across_bdy);
00369   
00370   static ErrorCode get_neighbor_sqij(int np, int pfrom,
00371                                      const int * const gdims, const int * const gperiodic, const int * const dijk, 
00372                                      int &pto, int *rdims, int *facedims, int *across_bdy);
00373   
00374   static ErrorCode get_neighbor_sqjk(int np, int pfrom,
00375                                      const int * const gdims, const int * const gperiodic, const int * const dijk, 
00376                                      int &pto, int *rdims, int *facedims, int *across_bdy);
00377   
00378   static ErrorCode get_neighbor_sqijk(int np, int pfrom,
00379                                       const int * const gdims, const int * const gperiodic, const int * const dijk, 
00380                                       int &pto, int *rdims, int *facedims, int *across_bdy);
00381   
00382   static int gtol(const int *gijk, int i, int j, int k);
00383 
00385   ErrorCode assign_global_ids(ScdBox *box);
00386   
00388   Interface *mbImpl;
00389 
00391   bool searchedBoxes;
00392   
00394   std::vector<ScdBox*> scdBoxes;
00395 
00397   Tag boxPeriodicTag;
00398 
00400   Tag boxDimsTag;
00401 
00403   Tag globalBoxDimsTag;
00404 
00406   Tag partMethodTag;
00407 
00409   Tag boxSetTag;
00410   
00411 };
00412 
00413 class ScdBox 
00414 {
00415   friend class ScdInterface;
00416   
00417 public:
00418 
00420   ~ScdBox();
00421 
00423   inline ScdInterface *sc_impl() const;
00424 
00426     /* Add a vertex box to the element sequence referenced by this box.  The passed in vbox must
00427      * be a vertex box, with parametric extents no larger than that of this box.  This vbox is
00428      * oriented to this box by matching parameters from1-from3 in vbox to to1-to3 in this box.
00429      * If bb_input is true, only the part of the vertex sequence between bb_min and bb_max is referenced
00430      * \param vbox The vertex box being added to this box
00431      * \param from1 1st reference point on vbox
00432      * \param to1 1st reference point on this box
00433      * \param from2 2nd reference point on vbox
00434      * \param to2 2nd reference point on this box
00435      * \param from3 3rd reference point on vbox
00436      * \param to3 3rd reference point on this box
00437      * \param bb_input If true, subsequent parameters list extents of vbox referenced
00438      * \param bb_min Lower corner of rectangle referenced
00439      * \param bb_max Upper corner of rectangle referenced
00440      */
00441   ErrorCode add_vbox(ScdBox *vbox,
00442                      HomCoord from1, HomCoord to1, 
00443                      HomCoord from2, HomCoord to2,
00444                      HomCoord from3, HomCoord to3,
00445                      bool bb_input = false,
00446                      const HomCoord &bb_min = HomCoord::unitv[0],
00447                      const HomCoord &bb_max = HomCoord::unitv[0]);
00448 
00450 
00454   bool boundary_complete() const;
00455 
00457   inline int box_dimension() const;
00458   
00460   inline EntityHandle start_vertex() const;
00461   
00463 
00465   inline EntityHandle start_element() const;
00466 
00468     /* Number of elements is (boxSize[0]-1)(boxSize[1]-1)(boxSize[2]-1)
00469      */
00470   inline int num_elements() const;
00471   
00473     /* Number of vertices is boxSize[0] * boxSize[1] * boxSize[2]
00474      */
00475   inline int num_vertices() const;
00476   
00478 
00481   inline const int *box_dims() const;
00482   
00484   inline HomCoord box_min() const;
00485   
00487   inline HomCoord box_max() const;
00488   
00490   inline HomCoord box_size() const;
00491   
00493 
00496   inline void box_size(int *ijk) const;
00497   
00499 
00504   void box_size(int &i, int &j, int &k) const;
00505   
00507 
00510   EntityHandle get_element(HomCoord ijk) const;
00511   
00513 
00518   EntityHandle get_element(int i, int j = 0, int k = 0) const;
00519   
00521 
00524   EntityHandle get_vertex(HomCoord ijk) const;
00525   
00527 
00532   EntityHandle get_vertex(int i, int j = 0, int k = 0) const;
00533   
00535 
00544   ErrorCode get_params(EntityHandle ent, int &i, int &j, int &k, int &dir) const;
00545   
00547 
00554   ErrorCode get_params(EntityHandle ent, int &i, int &j, int &k) const;
00555   
00557 
00563   ErrorCode get_params(EntityHandle ent, HomCoord &ijkd) const;
00564   
00577   ErrorCode get_adj_edge_or_face(int dim, int i, int j, int k, int dir, EntityHandle &ent,
00578                                  bool create_if_missing = true) const;
00579 
00581 
00586   bool contains(int i, int j, int k) const;
00587 
00589 
00594   bool contains(const HomCoord ijk) const;
00595 
00597   void box_set(EntityHandle this_set);
00598   EntityHandle box_set();
00599 
00601 
00606   ErrorCode get_coordinate_arrays(double *&xc, double *&yc, double *&zc);
00607   
00609 
00614   ErrorCode get_coordinate_arrays(const double *&xc, const double *&yc, const double *&zc) const;
00615 
00617 
00620   bool locally_periodic_i() const;
00621   
00623 
00626   bool locally_periodic_j() const;
00627   
00629 
00632   bool locally_periodic_k() const;
00633   
00635 
00638   void locally_periodic(bool lperiodic[3]);
00639 
00641 
00644   const int *locally_periodic() const;
00645  
00647 
00650   ScdParData &par_data() {return parData;}
00651   
00653 
00656   const ScdParData &par_data() const {return parData;}
00657   
00659 
00662   void par_data(const ScdParData &par_datap) {parData = par_datap;}
00663   
00664 private:
00666 
00677   ScdBox(ScdInterface *sc_impl, EntityHandle box_set,
00678          EntitySequence *seq1, EntitySequence *seq2 = NULL);
00679 
00681 
00685   EntityHandle get_vertex_from_seq(int i, int j, int k) const;
00686 
00688   ErrorCode vert_dat(ScdVertexData *vert_dat);
00689   
00691   ScdVertexData *vert_dat() const;
00692   
00694   ErrorCode elem_seq(EntitySequence *elem_seq);
00695   
00697   StructuredElementSeq *elem_seq() const;
00698   
00700   void start_vertex(EntityHandle startv);
00701   
00703   void start_element(EntityHandle starte);
00704 
00706   ScdInterface *scImpl;
00707 
00709   EntityHandle boxSet;
00710 
00713   ScdVertexData *vertDat;
00714 
00716   StructuredElementSeq *elemSeq;
00717   
00719   EntityHandle startVertex;
00720   
00722   EntityHandle startElem;
00723 
00725   int boxDims[6];
00726 
00728   int locallyPeriodic[3];
00729 
00731   ScdParData parData;
00732   
00734   HomCoord boxSize;
00735 
00737   int boxSizeIJ;
00738   int boxSizeIJM1;
00739   int boxSizeIM1;
00740   
00741 };
00742 
00743 inline ErrorCode ScdInterface::compute_partition(int np, int nr, const ScdParData &par_data,
00744                                      int *ldims, int *lperiodic, int *pdims)
00745 {
00746   ErrorCode rval = MB_SUCCESS;
00747   switch (par_data.partMethod) {
00748     case ScdParData::ALLJORKORI:
00749     case -1:
00750         rval = compute_partition_alljorkori(np, nr, par_data.gDims, par_data.gPeriodic, 
00751                                             ldims, lperiodic, pdims);
00752         break;
00753     case ScdParData::ALLJKBAL:
00754         rval = compute_partition_alljkbal(np, nr, par_data.gDims, par_data.gPeriodic, 
00755                                           ldims, lperiodic, pdims);
00756         break;
00757     case ScdParData::SQIJ:
00758         rval = compute_partition_sqij(np, nr, par_data.gDims, par_data.gPeriodic, 
00759                                       ldims, lperiodic, pdims);
00760         break;
00761     case ScdParData::SQJK:
00762         rval = compute_partition_sqjk(np, nr, par_data.gDims, par_data.gPeriodic, 
00763                                       ldims, lperiodic, pdims);
00764         break;
00765     case ScdParData::SQIJK:
00766         rval = compute_partition_sqijk(np, nr, par_data.gDims, par_data.gPeriodic, 
00767                                       ldims, lperiodic, pdims);
00768         break;
00769     default:
00770         rval = MB_FAILURE;
00771         break;
00772   }
00773 
00774   return rval;
00775 }
00776 
00777 inline ErrorCode ScdInterface::compute_partition_alljorkori(int np, int nr,
00778                                                             const int * const gijk, const int * const gperiodic, 
00779                                                             int *ldims, int *lperiodic, int *pijk)
00780 {
00781     // partition *the elements* over the parametric space; 1d partition for now, in the j, k, or i
00782     // parameters
00783   int tmp_lp[3], tmp_pijk[3];
00784   if (!lperiodic) lperiodic = tmp_lp;
00785   if (!pijk) pijk = tmp_pijk;
00786   
00787   for (int i = 0; i < 3; i++) lperiodic[i] = gperiodic[i];
00788   
00789   if (np == 1) {
00790     if (ldims) {
00791       ldims[0] = gijk[0];
00792       ldims[3] = gijk[3];
00793       ldims[1] = gijk[1];
00794       ldims[4] = gijk[4];
00795       ldims[2] = gijk[2];
00796       ldims[5] = gijk[5];
00797     }
00798     pijk[0] = pijk[1] = pijk[2] = 1;
00799   }
00800   else {
00801     if (gijk[4] - gijk[1] > np) {
00802         // partition j over procs
00803       int dj = (gijk[4] - gijk[1]) / np;
00804       int extra = (gijk[4] - gijk[1]) % np;
00805       ldims[1] = gijk[1] + nr*dj + 
00806           std::min(nr, extra);
00807       ldims[4] = ldims[1] + dj + (nr < extra ? 1 : 0);
00808 
00809       if (gperiodic[1] && np > 1) {
00810         lperiodic[1] = 0;
00811         ldims[4]++;
00812       }
00813       
00814       ldims[2] = gijk[2]; ldims[5] = gijk[5];
00815       ldims[0] = gijk[0]; ldims[3] = gijk[3];
00816       pijk[0] = pijk[2] = 1;
00817       pijk[1] = np;
00818     }
00819     else if (gijk[5] - gijk[2] > np) {
00820         // partition k over procs
00821       int dk = (gijk[5] - gijk[2]) / np;
00822       int extra = (gijk[5] - gijk[2]) % np;
00823       ldims[2] = gijk[2] + nr*dk + 
00824           std::min(nr, extra);
00825       ldims[5] = ldims[2] + dk + (nr < extra ? 1 : 0);
00826 
00827       ldims[1] = gijk[1]; ldims[4] = gijk[4];
00828       ldims[0] = gijk[0]; ldims[3] = gijk[3];
00829       pijk[0] = pijk[1] = 1;
00830       pijk[2] = np;
00831     }
00832     else if (gijk[3] - gijk[0] > np) {
00833         // partition i over procs
00834       int di = (gijk[3] - gijk[0]) / np;
00835       int extra = (gijk[3] - gijk[0]) % np;
00836       ldims[0] = gijk[0] + nr*di + 
00837           std::min(nr, extra);
00838       ldims[3] = ldims[0] + di + (nr < extra ? 1 : 0);
00839 
00840       if (gperiodic[0] && np > 1) {
00841         lperiodic[0] = 0;
00842         ldims[3]++;
00843       }
00844 
00845       ldims[2] = gijk[2]; ldims[5] = gijk[5];
00846       ldims[1] = gijk[1]; ldims[4] = gijk[4];
00847 
00848       pijk[1] = pijk[2] = 1;
00849       pijk[0] = np;
00850     }
00851     else {
00852         // Couldn't find a suitable partition...
00853       return MB_FAILURE;
00854     }
00855   }
00856   
00857   return MB_SUCCESS;
00858 }
00859 
00860 inline ErrorCode ScdInterface::compute_partition_alljkbal(int np, int nr,
00861                                                           const int * const gijk, const int * const gperiodic, 
00862                                                           int *ldims, int *lperiodic, int *pijk)
00863 {
00864   int tmp_lp[3], tmp_pijk[3];
00865   if (!lperiodic) lperiodic = tmp_lp;
00866   if (!pijk) pijk = tmp_pijk;
00867 
00868   for (int i = 0; i < 3; i++) lperiodic[i] = gperiodic[i];
00869 
00870   if (np == 1) {
00871     if (ldims) {
00872       ldims[0] = gijk[0];
00873       ldims[3] = gijk[3];
00874       ldims[1] = gijk[1];
00875       ldims[4] = gijk[4];
00876       ldims[2] = gijk[2];
00877       ldims[5] = gijk[5];
00878     }
00879     pijk[0] = pijk[1] = pijk[2] = 1;
00880   }
00881   else {
00882       // improved, possibly 2-d partition
00883     std::vector<double> kfactors;
00884     kfactors.push_back(1);
00885     int K = gijk[5] - gijk[2];
00886     for (int i = 2; i < K; i++) 
00887       if (!(K%i) && !(np%i)) kfactors.push_back(i);
00888     kfactors.push_back(K);
00889   
00890       // compute the ideal nj and nk
00891     int J = gijk[4] - gijk[1];
00892     double njideal = sqrt(((double)(np*J))/((double)K));
00893     double nkideal = (njideal*K)/J;
00894   
00895     int nk, nj;
00896     if (nkideal < 1.0) {
00897       nk = 1;
00898       nj = np;
00899     }
00900     else {
00901       std::vector<double>::iterator vit = std::lower_bound(kfactors.begin(), kfactors.end(), nkideal);
00902       if (vit == kfactors.begin()) nk = 1;
00903       else nk = (int)*(--vit);
00904       nj = np / nk;
00905     }
00906 
00907     int dk = K / nk;
00908     int dj = J / nj;
00909   
00910     ldims[2] = gijk[2] + (nr % nk) * dk;
00911     ldims[5] = ldims[2] + dk;
00912   
00913     int extra = J % nj;
00914   
00915     ldims[1] = gijk[1] + (nr / nk) * dj + std::min(nr / nk, extra);
00916     ldims[4] = ldims[1] + dj + (nr / nk < extra ? 1 : 0);
00917 
00918     ldims[0] = gijk[0];
00919     ldims[3] = gijk[3];
00920 
00921     if (gperiodic[1] && np > 1) {
00922       lperiodic[1] = 0;
00923       if (nr/nk == nj-1) {
00924         ldims[1]++;
00925       }
00926     }
00927 
00928     pijk[0] = 1; pijk[1] = nj; pijk[2] = nk;
00929   }
00930   
00931   return MB_SUCCESS;
00932 }
00933 
00934 inline ErrorCode ScdInterface::compute_partition_sqij(int np, int nr,
00935                                                       const int * const gijk, const int * const gperiodic, 
00936                                                       int *ldims, int *lperiodic, int *pijk)
00937 {
00938   int tmp_lp[3], tmp_pijk[3];
00939   if (!lperiodic) lperiodic = tmp_lp;
00940   if (!pijk) pijk = tmp_pijk;
00941 
00942     // square IxJ partition
00943 
00944   for (int i = 0; i < 3; i++) lperiodic[i] = gperiodic[i];
00945   
00946   if (np == 1) {
00947     if (ldims) {
00948       ldims[0] = gijk[0];
00949       ldims[3] = gijk[3];
00950       ldims[1] = gijk[1];
00951       ldims[4] = gijk[4];
00952       ldims[2] = gijk[2];
00953       ldims[5] = gijk[5];
00954     }
00955     pijk[0] = pijk[1] = pijk[2] = 1;
00956   }
00957   else {
00958     std::vector<double> pfactors, ppfactors;
00959     for (int i = 2; i <= np/2; i++) 
00960       if (!(np%i)) {
00961         pfactors.push_back(i);
00962         ppfactors.push_back(((double)(i*i))/np);
00963       }
00964     pfactors.push_back(np);
00965     ppfactors.push_back( (double)np);
00966     
00967       // ideally, Px/Py = I/J
00968     double ijratio = ((double)(gijk[3]-gijk[0]))/((double)(gijk[4]-gijk[1]));
00969     
00970     unsigned int ind = std::lower_bound(ppfactors.begin(), ppfactors.end(), ijratio) - ppfactors.begin();
00971     if (ind && fabs(ppfactors[ind-1]-ijratio) < fabs(ppfactors[ind]-ijratio)) ind--;
00972     
00973 
00974       // VARIABLES DESCRIBING THE MESH:
00975       // pi, pj = # procs in i and j directions
00976       // nri, nrj = my proc's position in i, j directions
00977       // I, J = # edges/elements in i, j directions
00978       // iextra, jextra = # procs having extra edge in i/j direction
00979       // top_i, top_j = if true, I'm the last proc in the i/j direction
00980       // i, j = # edges locally in i/j direction, *not* including one for iextra/jextra
00981     int pi = pfactors[ind];
00982     int pj = np / pi;
00983     
00984     int I = (gijk[3] - gijk[0]), J = (gijk[4] - gijk[1]);
00985     int iextra = I%pi, jextra = J%pj, i = I/pi, j = J/pj;
00986     int nri = nr % pi, nrj = nr / pi;
00987 
00988     if (ldims) {
00989       ldims[0] = gijk[0] + i*nri + std::min(iextra, nri);
00990       ldims[3] = ldims[0] + i + (nri < iextra ? 1 : 0);
00991       ldims[1] = gijk[1] + j*nrj + std::min(jextra, nrj);
00992       ldims[4] = ldims[1] + j + (nrj < jextra ? 1 : 0);
00993       
00994       ldims[2] = gijk[2];
00995       ldims[5] = gijk[5];
00996 
00997       if (gperiodic[0] && pi > 1) {
00998         lperiodic[0] = 0;
00999         if (nri == pi-1) ldims[3]++;
01000       }
01001       if (gperiodic[1] && pj > 1) {
01002         lperiodic[1] = 0;
01003         if (nrj == pj-1) ldims[4]++;
01004       }
01005       
01006     }
01007 
01008     pijk[0] = pi; pijk[1] = pj; pijk[2] = 1;
01009   }  
01010 
01011   return MB_SUCCESS;
01012 }
01013 
01014 inline ErrorCode ScdInterface::compute_partition_sqjk(int np, int nr,
01015                                                       const int * const gijk, const int * const gperiodic, 
01016                                                       int *ldims, int *lperiodic, int *pijk)
01017 {
01018   int tmp_lp[3], tmp_pijk[3];
01019   if (!lperiodic) lperiodic = tmp_lp;
01020   if (!pijk) pijk = tmp_pijk;
01021 
01022     // square JxK partition
01023   for (int i = 0; i < 3; i++) lperiodic[i] = gperiodic[i];
01024 
01025   if (np == 1) {
01026     if (ldims) {
01027       ldims[0] = gijk[0];
01028       ldims[3] = gijk[3];
01029       ldims[1] = gijk[1];
01030       ldims[4] = gijk[4];
01031       ldims[2] = gijk[2];
01032       ldims[5] = gijk[5];
01033     }
01034     pijk[0] = pijk[1] = pijk[2] = 1;
01035   }
01036   else {
01037     std::vector<double> pfactors, ppfactors;
01038     for (int p = 2; p <= np; p++) 
01039       if (!(np%p)) {
01040         pfactors.push_back(p);
01041         ppfactors.push_back(((double)(p*p))/np);
01042       }
01043   
01044       // ideally, Pj/Pk = J/K
01045     int pj, pk;
01046     if (gijk[5] == gijk[2]) {
01047       pk = 1;
01048       pj = np;
01049     }
01050     else {
01051       double jkratio = ((double)(gijk[4]-gijk[1]))/((double)(gijk[5]-gijk[2]));
01052 
01053       std::vector<double>::iterator vit  = std::lower_bound(ppfactors.begin(), ppfactors.end(), jkratio);
01054       if (vit == ppfactors.end()) vit--;
01055       else if (vit != ppfactors.begin() && fabs(*(vit-1)-jkratio) < fabs((*vit)-jkratio)) vit--;
01056       int ind = vit - ppfactors.begin();
01057   
01058       pj = 1;
01059       if (ind >= 0 && !pfactors.empty()) pfactors[ind];
01060       pk = np / pj;
01061     }
01062 
01063     int K = (gijk[5] - gijk[2]), J = (gijk[4] - gijk[1]);
01064     int jextra = J%pj, kextra = K%pk, j = J/pj, k = K/pk;
01065     int nrj = nr % pj, nrk = nr / pj;
01066     ldims[1] = gijk[1] + j*nrj + std::min(jextra, nrj);
01067     ldims[4] = ldims[1] + j + (nrj < jextra ? 1 : 0);
01068     ldims[2] = gijk[2] + k*nrk + std::min(kextra, nrk);
01069     ldims[5] = ldims[2] + k + (nrk < kextra ? 1 : 0);
01070 
01071     ldims[0] = gijk[0];
01072     ldims[3] = gijk[3];
01073 
01074     if (gperiodic[1] && pj > 1) {
01075       lperiodic[1] = 0;
01076       if (nrj == pj-1) ldims[4]++;
01077     }
01078 
01079     pijk[0] = 1; pijk[1] = pj; pijk[2] = pk;
01080   }
01081   
01082   return MB_SUCCESS;
01083 }
01084 
01085 inline ErrorCode ScdInterface::compute_partition_sqijk(int np, int nr,
01086                                                        const int * const gijk, const int * const gperiodic, 
01087                                                        int *ldims, int *lperiodic, int *pijk)
01088 {
01089   if (gperiodic[0] || gperiodic[1] || gperiodic[2]) return MB_FAILURE;
01090   
01091   int tmp_lp[3], tmp_pijk[3];
01092   if (!lperiodic) lperiodic = tmp_lp;
01093   if (!pijk) pijk = tmp_pijk;
01094 
01095     // square IxJxK partition
01096 
01097   for (int i = 0; i < 3; i++) lperiodic[i] = gperiodic[i];
01098   
01099   if (np == 1) {
01100     if (ldims) 
01101       for (int i = 0; i < 6; i++) ldims[i] = gijk[i];
01102     pijk[0] = pijk[1] = pijk[2] = 1;
01103     return MB_SUCCESS;
01104   }
01105 
01106   std::vector<int> pfactors;
01107   pfactors.push_back(1);
01108   for (int i = 2; i <= np/2; i++) 
01109     if (!(np%i)) pfactors.push_back(i);
01110   pfactors.push_back(np);
01111 
01112     // test for IJ, JK, IK
01113   int IJK[3], dIJK[3];
01114   for (int i = 0; i < 3; i++)
01115     IJK[i] = std::max(gijk[3+i] - gijk[i], 1);
01116     // order IJK from lo to hi
01117   int lo = 0, hi = 0;
01118   for (int i = 1; i < 3; i++) {
01119     if (IJK[i] < IJK[lo]) lo = i;
01120     if (IJK[i] > IJK[hi]) hi = i;
01121   }
01122   if (lo == hi) hi = (lo+1)%3;
01123   int mid = 3 - lo - hi;
01124     // search for perfect subdivision of np that balances #cells
01125   int perfa_best = -1, perfb_best = -1;
01126   double ratio = 0.0;
01127   for (int po = 0; po < (int)pfactors.size(); po++) {
01128     for (int pi = po; pi < (int)pfactors.size() && np/(pfactors[po]*pfactors[pi]) >= pfactors[pi]; pi++) {
01129       int p3 = std::find(pfactors.begin(), pfactors.end(), np/(pfactors[po]*pfactors[pi])) - pfactors.begin();
01130       if (p3 == (int)pfactors.size() || pfactors[po]*pfactors[pi]*pfactors[p3] != np) continue; // po*pi should exactly factor np
01131       assert(po <= pi && pi <= p3);
01132         // by definition, po <= pi <= p3
01133       double minl = std::min(std::min(IJK[lo]/pfactors[po], IJK[mid]/pfactors[pi]), IJK[hi]/pfactors[p3]),
01134           maxl = std::max(std::max(IJK[lo]/pfactors[po], IJK[mid]/pfactors[pi]), IJK[hi]/pfactors[p3]);
01135       if (minl/maxl > ratio) {
01136         ratio = minl/maxl;
01137         perfa_best = po; perfb_best = pi;
01138       }
01139     }
01140   }
01141   if (perfa_best == -1 || perfb_best == -1) 
01142     return MB_FAILURE;
01143 
01144     // VARIABLES DESCRIBING THE MESH:
01145     // pijk[i] = # procs in direction i
01146     // numr[i] = my proc's position in direction i
01147     // dIJK[i] = # edges/elements in direction i
01148     // extra[i]= # procs having extra edge in direction i
01149     // top[i] = if true, I'm the last proc in direction i
01150     
01151   pijk[lo] = pfactors[perfa_best]; pijk[mid] = pfactors[perfb_best]; 
01152   pijk[hi] = (np/(pfactors[perfa_best]*pfactors[perfb_best]));
01153   int extra[3] = {0, 0, 0}, numr[3];
01154   for (int i = 0; i < 3; i++) {
01155     dIJK[i] = IJK[i] / pijk[i];
01156     extra[i] = IJK[i]%pijk[i];
01157   }
01158   numr[2] = nr / (pijk[0]*pijk[1]);
01159   int rem = nr % (pijk[0] * pijk[1]);
01160   numr[1] = rem / pijk[0];
01161   numr[0] = rem % pijk[0];
01162   for (int i = 0; i < 3; i++) {
01163     extra[i] = IJK[i] % dIJK[i];
01164     ldims[i] = gijk[i] + numr[i]*dIJK[i] + std::min(extra[i], numr[i]);
01165     ldims[3+i] = ldims[i] + dIJK[i] + (numr[i] < extra[i] ? 1 : 0);
01166   }
01167 
01168   return MB_SUCCESS;
01169 }
01170 
01171 inline int ScdInterface::gtol(const int *gijk, int i, int j, int k) 
01172 {
01173   return ((k-gijk[2])*(gijk[3]-gijk[0]+1)*(gijk[4]-gijk[1]+1) + (j-gijk[1])*(gijk[3]-gijk[0]+1) + i-gijk[0]);
01174 }
01175 
01176 inline ErrorCode ScdInterface::get_indices(const int * const ldims, const int * const rdims, const int * const across_bdy, 
01177                                            int *face_dims, std::vector<int> &shared_indices) 
01178 {
01179     // check for going across periodic bdy and face_dims not in my ldims (I'll always be on top in that case)...
01180   if (across_bdy[0] > 0 && face_dims[0] != ldims[3]) face_dims[0] = face_dims[3] = ldims[3];
01181   else if (across_bdy[0] < 0 && face_dims[0] != ldims[0]) face_dims[0] = face_dims[3] = ldims[0];
01182   if (across_bdy[1] > 0 && face_dims[1] != ldims[4]) face_dims[1] = face_dims[4] = ldims[4];
01183   else if (across_bdy[1] < 0 && face_dims[1] != ldims[1]) face_dims[0] = face_dims[3] = ldims[1];
01184   
01185   for (int k = face_dims[2]; k <= face_dims[5]; k++)
01186     for (int j = face_dims[1]; j <= face_dims[4]; j++)
01187       for (int i = face_dims[0]; i <= face_dims[3]; i++)
01188         shared_indices.push_back(gtol(ldims, i, j, k));
01189 
01190   if (across_bdy[0] > 0 && face_dims[0] != rdims[0]) face_dims[0] = face_dims[3] = rdims[0];
01191   else if (across_bdy[0] < 0 && face_dims[0] != rdims[3]) face_dims[0] = face_dims[3] = rdims[3];
01192   if (across_bdy[1] > 0 && face_dims[1] != rdims[1]) face_dims[1] = face_dims[4] = rdims[1];
01193   else if (across_bdy[1] < 0 && face_dims[1] != rdims[4]) face_dims[0] = face_dims[3] = rdims[4];
01194   
01195   for (int k = face_dims[2]; k <= face_dims[5]; k++)
01196     for (int j = face_dims[1]; j <= face_dims[4]; j++)
01197       for (int i = face_dims[0]; i <= face_dims[3]; i++)
01198         shared_indices.push_back(gtol(rdims, i, j, k));
01199 
01200   return MB_SUCCESS;
01201 }
01202   
01203 inline ErrorCode ScdInterface::get_neighbor(int np, int pfrom, const ScdParData &spd, const int * const dijk, 
01204                                             int &pto, int *rdims, int *facedims, int *across_bdy)
01205 {
01206   if (!dijk[0] && !dijk[1] && !dijk[2]) {
01207     // not going anywhere, return
01208     pto = -1;
01209     return MB_SUCCESS;
01210   }
01211   
01212   switch (spd.partMethod) {
01213     case ScdParData::ALLJORKORI:
01214     case -1:
01215         return get_neighbor_alljorkori(np, pfrom, spd.gDims, spd.gPeriodic, dijk,
01216                                        pto, rdims, facedims, across_bdy);
01217     case ScdParData::ALLJKBAL:
01218         return get_neighbor_alljkbal(np, pfrom, spd.gDims, spd.gPeriodic, dijk,
01219                                      pto, rdims, facedims, across_bdy);
01220     case ScdParData::SQIJ:
01221         return get_neighbor_sqij(np, pfrom, spd.gDims, spd.gPeriodic, dijk,
01222                                  pto, rdims, facedims, across_bdy);
01223     case ScdParData::SQJK:
01224         return get_neighbor_sqjk(np, pfrom, spd.gDims, spd.gPeriodic, dijk,
01225                                  pto, rdims, facedims, across_bdy);
01226     case ScdParData::SQIJK:
01227         return get_neighbor_sqijk(np, pfrom, spd.gDims, spd.gPeriodic, dijk,
01228                                   pto, rdims, facedims, across_bdy);
01229     default:
01230         break;
01231   }
01232 
01233   return MB_FAILURE;
01234 }
01235 
01236 inline ErrorCode ScdInterface::tag_shared_vertices(ParallelComm *pcomm, EntityHandle seth) 
01237 {
01238   ScdBox *box = get_scd_box(seth);
01239   if (!box) {
01240       // look for contained boxes
01241     Range tmp_range;
01242     ErrorCode rval = mbImpl->get_entities_by_type(seth, MBENTITYSET, tmp_range);
01243     if (MB_SUCCESS != rval) return rval;
01244     for (Range::iterator rit = tmp_range.begin(); rit != tmp_range.end(); rit++) {
01245       box = get_scd_box(*rit);
01246       if (box) break;
01247     }
01248   }
01249   
01250   if (!box) return MB_FAILURE;
01251 
01252   return tag_shared_vertices(pcomm, box);
01253 }
01254 
01255 inline ScdInterface *ScdBox::sc_impl() const 
01256 {
01257   return scImpl;
01258 }
01259 
01260 inline EntityHandle ScdBox::start_vertex() const
01261 {
01262   return startVertex;
01263 }
01264     
01265 inline void ScdBox::start_vertex(EntityHandle startv) 
01266 {
01267   startVertex = startv;
01268 }
01269     
01270 inline EntityHandle ScdBox::start_element() const
01271 {
01272   return startElem;
01273 }
01274     
01275 inline void ScdBox::start_element(EntityHandle starte) 
01276 {
01277   startElem = starte;
01278 }
01279     
01280 inline int ScdBox::num_elements() const
01281 {
01282   return (!startElem ? 0 : 
01283           (boxSize[0]- (locallyPeriodic[0] ? 0 : 1)) * 
01284           (-1 == boxSize[1] ? 1 : (boxSize[1]-(locallyPeriodic[1] ? 0 : 1))) * 
01285           (boxSize[2] == -1 || boxSize[2] == 1 ? 1 : (boxSize[2]-(locallyPeriodic[2] ? 0 : 1))));
01286 }
01287     
01288 inline int ScdBox::num_vertices() const
01289 {
01290   return boxSize[0] * (!boxSize[1] ? 1 : boxSize[1]) * 
01291       (!boxSize[2] ? 1 : boxSize[2]);
01292 }
01293     
01294 inline const int *ScdBox::box_dims() const 
01295 {
01296   return boxDims;
01297 }
01298 
01299 inline HomCoord ScdBox::box_min() const 
01300 {
01301   return HomCoord(boxDims, 3);
01302 }
01303 
01304 inline HomCoord ScdBox::box_max() const 
01305 {
01306   return HomCoord(boxDims+3, 3);
01307 }
01308 
01309 inline HomCoord ScdBox::box_size() const 
01310 {
01311   return boxSize;
01312 }
01313 
01314 inline void ScdBox::box_size(int *ijk) const 
01315 {
01316   ijk[0] = boxSize[0];
01317   ijk[1] = boxSize[1];
01318   ijk[2] = boxSize[2];
01319 }
01320 
01321 inline void ScdBox::box_size(int &i, int &j, int &k) const 
01322 {
01323   i = boxSize[0];
01324   j = boxSize[1];
01325   k = boxSize[2];
01326 }
01327   
01328 inline EntityHandle ScdBox::get_element(int i, int j, int k) const 
01329 {
01330   return (!startElem ? 0 : 
01331           startElem + (k-boxDims[2])*boxSizeIJM1 + (j-boxDims[1])*boxSizeIM1 + i-boxDims[0]);
01332 }
01333 
01334 inline EntityHandle ScdBox::get_element(HomCoord ijk) const 
01335 {
01336   return get_element(ijk[0], ijk[1], ijk[2]);
01337 }
01338   
01339 inline EntityHandle ScdBox::get_vertex(int i, int j, int k) const 
01340 {
01341   return (vertDat ? startVertex + (boxDims[2] == -1 && boxDims[5] == -1 ? 0 : (k-boxDims[2]))*boxSizeIJ +
01342       (boxDims[1] == -1 && boxDims[4] == -1 ? 0 : (j-boxDims[1]))*boxSize[0] + i-boxDims[0] : get_vertex_from_seq(i, j, k));
01343 }
01344 
01345 inline EntityHandle ScdBox::get_vertex(HomCoord ijk) const 
01346 {
01347   return get_vertex(ijk[0], ijk[1], ijk[2]);
01348 }
01349   
01350 inline bool ScdBox::contains(const HomCoord ijk) const
01351 {
01352   return (ijk >= HomCoord(boxDims, 3) && 
01353           ijk <= HomCoord(boxDims+3, 3));
01354 }
01355 
01356 inline bool ScdBox::contains(int i, int j, int k) const
01357 {
01358   return contains(HomCoord(i, j, k));
01359 }
01360 
01361 inline void ScdBox::box_set(EntityHandle this_set) 
01362 {
01363   boxSet = this_set;
01364 }
01365 
01366 inline EntityHandle ScdBox::box_set() 
01367 {
01368   return boxSet;
01369 }
01370     
01371 inline ScdVertexData *ScdBox::vert_dat() const
01372 {
01373   return vertDat;
01374 }
01375   
01376 inline StructuredElementSeq *ScdBox::elem_seq() const
01377 {
01378   return elemSeq;
01379 }
01380   
01381 inline ErrorCode ScdBox::get_params(EntityHandle ent, int &i, int &j, int &k, int &dir) const
01382 {
01383   HomCoord hc;
01384   ErrorCode rval = get_params(ent, hc);
01385   if (MB_SUCCESS == rval) {
01386     i = hc[0];
01387     j = hc[1];
01388     k = hc[2];
01389     dir = hc[3];
01390   }
01391   
01392   return rval;
01393 }
01394 
01395 inline ErrorCode ScdBox::get_params(EntityHandle ent, int &i, int &j, int &k) const 
01396 {
01397   HomCoord hc;
01398   ErrorCode rval = get_params(ent, hc);
01399   if (MB_SUCCESS == rval) {
01400     i = hc[0];
01401     j = hc[1];
01402     k = hc[2];
01403   }
01404   
01405   return rval;
01406 }
01407 
01408 inline bool ScdBox::locally_periodic_i() const 
01409 {
01410   return locallyPeriodic[0];
01411 }
01412 
01413 inline bool ScdBox::locally_periodic_j() const 
01414 {
01415   return locallyPeriodic[1];
01416 }
01417 
01418 inline bool ScdBox::locally_periodic_k() const 
01419 {
01420   return locallyPeriodic[2];
01421 }
01422 
01423 inline void ScdBox::locally_periodic(bool lperiodic[3])
01424 {
01425    for (int i = 0; i < 3; i++) 
01426     locallyPeriodic[i] = lperiodic[i];
01427 }
01428 
01429 inline const int *ScdBox::locally_periodic() const
01430 {
01431   return locallyPeriodic;
01432 }
01433  
01434 inline std::ostream &operator<<(std::ostream &str, const ScdParData &pd) 
01435 {
01436   str << "Partition method = " << ScdParData::PartitionMethodNames[pd.partMethod] << ", gDims = (" 
01437       << pd.gDims[0] << "," << pd.gDims[1] << "," << pd.gDims[2] << ")-(" 
01438       << pd.gDims[3] << "," << pd.gDims[4] << "," << pd.gDims[5] << "), gPeriodic = (" 
01439       << pd.gPeriodic[0] << "," << pd.gPeriodic[1] << "," << pd.gPeriodic[2] << "), pDims = ("
01440       << pd.pDims[0] << "," << pd.pDims[1] << "," << pd.pDims[2] << ")" << std::endl;
01441   return str;
01442 }
01443 
01444 } // namespace moab
01445 #endif
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines