moab
|
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