1827bd09bSSatish Balay 2827bd09bSSatish Balay /***********************************comm.c************************************* 3827bd09bSSatish Balay 4827bd09bSSatish Balay Author: Henry M. Tufo III 5827bd09bSSatish Balay 6827bd09bSSatish Balay e-mail: hmt@cs.brown.edu 7827bd09bSSatish Balay 8827bd09bSSatish Balay snail-mail: 9827bd09bSSatish Balay Division of Applied Mathematics 10827bd09bSSatish Balay Brown University 11827bd09bSSatish Balay Providence, RI 02912 12827bd09bSSatish Balay 13827bd09bSSatish Balay Last Modification: 14827bd09bSSatish Balay 11.21.97 15827bd09bSSatish Balay ***********************************comm.c*************************************/ 16c6db04a5SJed Brown #include <../src/ksp/pc/impls/tfs/tfs.h> 17827bd09bSSatish Balay 18827bd09bSSatish Balay /* global program control variables - explicitly exported */ 19b1c944f5SJed Brown PetscMPIInt PCTFS_my_id = 0; 20b1c944f5SJed Brown PetscMPIInt PCTFS_num_nodes = 1; 21b1c944f5SJed Brown PetscMPIInt PCTFS_floor_num_nodes = 0; 22b1c944f5SJed Brown PetscMPIInt PCTFS_i_log2_num_nodes = 0; 23827bd09bSSatish Balay 24827bd09bSSatish Balay /* global program control variables */ 2552f87cdaSBarry Smith static PetscInt p_init = 0; 2652f87cdaSBarry Smith static PetscInt modfl_num_nodes; 2752f87cdaSBarry Smith static PetscInt edge_not_pow_2; 28827bd09bSSatish Balay 2952f87cdaSBarry Smith static PetscInt edge_node[sizeof(PetscInt) * 32]; 30827bd09bSSatish Balay 317b1ae94cSBarry Smith /***********************************comm.c*************************************/ 32d71ae5a4SJacob Faibussowitsch PetscErrorCode PCTFS_comm_init(void) 33d71ae5a4SJacob Faibussowitsch { 34362febeeSStefano Zampini PetscFunctionBegin; 353fdc5746SBarry Smith if (p_init++) PetscFunctionReturn(0); 36827bd09bSSatish Balay 37b1c944f5SJed Brown MPI_Comm_size(MPI_COMM_WORLD, &PCTFS_num_nodes); 38b1c944f5SJed Brown MPI_Comm_rank(MPI_COMM_WORLD, &PCTFS_my_id); 39827bd09bSSatish Balay 4008401ef6SPierre Jolivet PetscCheck(PCTFS_num_nodes <= (INT_MAX >> 1), PETSC_COMM_SELF, PETSC_ERR_PLIB, "Can't have more then MAX_INT/2 nodes!!!"); 41827bd09bSSatish Balay 42ca8e9878SJed Brown PCTFS_ivec_zero((PetscInt *)edge_node, sizeof(PetscInt) * 32); 43827bd09bSSatish Balay 44b1c944f5SJed Brown PCTFS_floor_num_nodes = 1; 45b1c944f5SJed Brown PCTFS_i_log2_num_nodes = modfl_num_nodes = 0; 46db4deed7SKarl Rupp while (PCTFS_floor_num_nodes <= PCTFS_num_nodes) { 47b1c944f5SJed Brown edge_node[PCTFS_i_log2_num_nodes] = PCTFS_my_id ^ PCTFS_floor_num_nodes; 48b1c944f5SJed Brown PCTFS_floor_num_nodes <<= 1; 49b1c944f5SJed Brown PCTFS_i_log2_num_nodes++; 50827bd09bSSatish Balay } 51827bd09bSSatish Balay 52b1c944f5SJed Brown PCTFS_i_log2_num_nodes--; 53b1c944f5SJed Brown PCTFS_floor_num_nodes >>= 1; 54b1c944f5SJed Brown modfl_num_nodes = (PCTFS_num_nodes - PCTFS_floor_num_nodes); 55827bd09bSSatish Balay 562fa5cd67SKarl Rupp if ((PCTFS_my_id > 0) && (PCTFS_my_id <= modfl_num_nodes)) edge_not_pow_2 = ((PCTFS_my_id | PCTFS_floor_num_nodes) - 1); 572fa5cd67SKarl Rupp else if (PCTFS_my_id >= PCTFS_floor_num_nodes) edge_not_pow_2 = ((PCTFS_my_id ^ PCTFS_floor_num_nodes) + 1); 582fa5cd67SKarl Rupp else edge_not_pow_2 = 0; 593fdc5746SBarry Smith PetscFunctionReturn(0); 60827bd09bSSatish Balay } 61827bd09bSSatish Balay 627b1ae94cSBarry Smith /***********************************comm.c*************************************/ 63d71ae5a4SJacob Faibussowitsch PetscErrorCode PCTFS_giop(PetscInt *vals, PetscInt *work, PetscInt n, PetscInt *oprs) 64d71ae5a4SJacob Faibussowitsch { 653fdc5746SBarry Smith PetscInt mask, edge; 663fdc5746SBarry Smith PetscInt type, dest; 67827bd09bSSatish Balay vfp fp; 68827bd09bSSatish Balay MPI_Status status; 69827bd09bSSatish Balay 703fdc5746SBarry Smith PetscFunctionBegin; 71827bd09bSSatish Balay /* ok ... should have some data, work, and operator(s) */ 72*c75bfeddSPierre Jolivet PetscCheck(vals && work && oprs, PETSC_COMM_SELF, PETSC_ERR_PLIB, "PCTFS_giop() :: vals=%p, work=%p, oprs=%p", (void *)vals, (void *)work, (void *)oprs); 73827bd09bSSatish Balay 74827bd09bSSatish Balay /* non-uniform should have at least two entries */ 7508401ef6SPierre Jolivet PetscCheck(!(oprs[0] == NON_UNIFORM) || !(n < 2), PETSC_COMM_SELF, PETSC_ERR_PLIB, "PCTFS_giop() :: non_uniform and n=0,1?"); 76827bd09bSSatish Balay 77827bd09bSSatish Balay /* check to make sure comm package has been initialized */ 782fa5cd67SKarl Rupp if (!p_init) PCTFS_comm_init(); 79827bd09bSSatish Balay 80827bd09bSSatish Balay /* if there's nothing to do return */ 812fa5cd67SKarl Rupp if ((PCTFS_num_nodes < 2) || (!n)) PetscFunctionReturn(0); 8271a0148aSBarry Smith 83827bd09bSSatish Balay /* a negative number if items to send ==> fatal */ 8463a3b9bcSJacob Faibussowitsch PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_PLIB, "PCTFS_giop() :: n=%" PetscInt_FMT "<0?", n); 85827bd09bSSatish Balay 86827bd09bSSatish Balay /* advance to list of n operations for custom */ 872fa5cd67SKarl Rupp if ((type = oprs[0]) == NON_UNIFORM) oprs++; 88827bd09bSSatish Balay 89827bd09bSSatish Balay /* major league hack */ 907827d75bSBarry Smith PetscCheck(fp = (vfp)PCTFS_ivec_fct_addr(type), PETSC_COMM_SELF, PETSC_ERR_PLIB, "PCTFS_giop() :: Could not retrieve function pointer!"); 91827bd09bSSatish Balay 92827bd09bSSatish Balay /* all msgs will be of the same length */ 93827bd09bSSatish Balay /* if not a hypercube must colapse partial dim */ 94db4deed7SKarl Rupp if (edge_not_pow_2) { 952fa5cd67SKarl Rupp if (PCTFS_my_id >= PCTFS_floor_num_nodes) { 969566063dSJacob Faibussowitsch PetscCallMPI(MPI_Send(vals, n, MPIU_INT, edge_not_pow_2, MSGTAG0 + PCTFS_my_id, MPI_COMM_WORLD)); 972fa5cd67SKarl Rupp } else { 989566063dSJacob Faibussowitsch PetscCallMPI(MPI_Recv(work, n, MPIU_INT, MPI_ANY_SOURCE, MSGTAG0 + edge_not_pow_2, MPI_COMM_WORLD, &status)); 99827bd09bSSatish Balay (*fp)(vals, work, n, oprs); 100827bd09bSSatish Balay } 101827bd09bSSatish Balay } 102827bd09bSSatish Balay 103827bd09bSSatish Balay /* implement the mesh fan in/out exchange algorithm */ 104db4deed7SKarl Rupp if (PCTFS_my_id < PCTFS_floor_num_nodes) { 105db4deed7SKarl Rupp for (mask = 1, edge = 0; edge < PCTFS_i_log2_num_nodes; edge++, mask <<= 1) { 106b1c944f5SJed Brown dest = PCTFS_my_id ^ mask; 1072fa5cd67SKarl Rupp if (PCTFS_my_id > dest) { 1089566063dSJacob Faibussowitsch PetscCallMPI(MPI_Send(vals, n, MPIU_INT, dest, MSGTAG2 + PCTFS_my_id, MPI_COMM_WORLD)); 1092fa5cd67SKarl Rupp } else { 1109566063dSJacob Faibussowitsch PetscCallMPI(MPI_Recv(work, n, MPIU_INT, MPI_ANY_SOURCE, MSGTAG2 + dest, MPI_COMM_WORLD, &status)); 111827bd09bSSatish Balay (*fp)(vals, work, n, oprs); 112827bd09bSSatish Balay } 113827bd09bSSatish Balay } 114827bd09bSSatish Balay 115b1c944f5SJed Brown mask = PCTFS_floor_num_nodes >> 1; 116db4deed7SKarl Rupp for (edge = 0; edge < PCTFS_i_log2_num_nodes; edge++, mask >>= 1) { 1172fa5cd67SKarl Rupp if (PCTFS_my_id % mask) continue; 118827bd09bSSatish Balay 119b1c944f5SJed Brown dest = PCTFS_my_id ^ mask; 1202fa5cd67SKarl Rupp if (PCTFS_my_id < dest) { 1219566063dSJacob Faibussowitsch PetscCallMPI(MPI_Send(vals, n, MPIU_INT, dest, MSGTAG4 + PCTFS_my_id, MPI_COMM_WORLD)); 1222fa5cd67SKarl Rupp } else { 1239566063dSJacob Faibussowitsch PetscCallMPI(MPI_Recv(vals, n, MPIU_INT, MPI_ANY_SOURCE, MSGTAG4 + dest, MPI_COMM_WORLD, &status)); 124827bd09bSSatish Balay } 125827bd09bSSatish Balay } 126827bd09bSSatish Balay } 127827bd09bSSatish Balay 128827bd09bSSatish Balay /* if not a hypercube must expand to partial dim */ 129db4deed7SKarl Rupp if (edge_not_pow_2) { 1302fa5cd67SKarl Rupp if (PCTFS_my_id >= PCTFS_floor_num_nodes) { 1319566063dSJacob Faibussowitsch PetscCallMPI(MPI_Recv(vals, n, MPIU_INT, MPI_ANY_SOURCE, MSGTAG5 + edge_not_pow_2, MPI_COMM_WORLD, &status)); 1322fa5cd67SKarl Rupp } else { 1339566063dSJacob Faibussowitsch PetscCallMPI(MPI_Send(vals, n, MPIU_INT, edge_not_pow_2, MSGTAG5 + PCTFS_my_id, MPI_COMM_WORLD)); 134827bd09bSSatish Balay } 135827bd09bSSatish Balay } 1363fdc5746SBarry Smith PetscFunctionReturn(0); 137827bd09bSSatish Balay } 138827bd09bSSatish Balay 1397b1ae94cSBarry Smith /***********************************comm.c*************************************/ 140d71ae5a4SJacob Faibussowitsch PetscErrorCode PCTFS_grop(PetscScalar *vals, PetscScalar *work, PetscInt n, PetscInt *oprs) 141d71ae5a4SJacob Faibussowitsch { 1423fdc5746SBarry Smith PetscInt mask, edge; 1433fdc5746SBarry Smith PetscInt type, dest; 144827bd09bSSatish Balay vfp fp; 145827bd09bSSatish Balay MPI_Status status; 146827bd09bSSatish Balay 1473fdc5746SBarry Smith PetscFunctionBegin; 148827bd09bSSatish Balay /* ok ... should have some data, work, and operator(s) */ 149*c75bfeddSPierre Jolivet PetscCheck(vals && work && oprs, PETSC_COMM_SELF, PETSC_ERR_PLIB, "PCTFS_grop() :: vals=%p, work=%p, oprs=%p", (void *)vals, (void *)work, (void *)oprs); 150827bd09bSSatish Balay 151827bd09bSSatish Balay /* non-uniform should have at least two entries */ 15208401ef6SPierre Jolivet PetscCheck(!(oprs[0] == NON_UNIFORM) || !(n < 2), PETSC_COMM_SELF, PETSC_ERR_PLIB, "PCTFS_grop() :: non_uniform and n=0,1?"); 153827bd09bSSatish Balay 154827bd09bSSatish Balay /* check to make sure comm package has been initialized */ 1552fa5cd67SKarl Rupp if (!p_init) PCTFS_comm_init(); 156827bd09bSSatish Balay 157827bd09bSSatish Balay /* if there's nothing to do return */ 1582fa5cd67SKarl Rupp if ((PCTFS_num_nodes < 2) || (!n)) PetscFunctionReturn(0); 159827bd09bSSatish Balay 160827bd09bSSatish Balay /* a negative number of items to send ==> fatal */ 16163a3b9bcSJacob Faibussowitsch PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_PLIB, "gdop() :: n=%" PetscInt_FMT "<0?", n); 162827bd09bSSatish Balay 163827bd09bSSatish Balay /* advance to list of n operations for custom */ 1642fa5cd67SKarl Rupp if ((type = oprs[0]) == NON_UNIFORM) oprs++; 165827bd09bSSatish Balay 1667827d75bSBarry Smith PetscCheck(fp = (vfp)PCTFS_rvec_fct_addr(type), PETSC_COMM_SELF, PETSC_ERR_PLIB, "PCTFS_grop() :: Could not retrieve function pointer!"); 167827bd09bSSatish Balay 168827bd09bSSatish Balay /* all msgs will be of the same length */ 169827bd09bSSatish Balay /* if not a hypercube must colapse partial dim */ 1702fa5cd67SKarl Rupp if (edge_not_pow_2) { 1712fa5cd67SKarl Rupp if (PCTFS_my_id >= PCTFS_floor_num_nodes) { 1729566063dSJacob Faibussowitsch PetscCallMPI(MPI_Send(vals, n, MPIU_SCALAR, edge_not_pow_2, MSGTAG0 + PCTFS_my_id, MPI_COMM_WORLD)); 1732fa5cd67SKarl Rupp } else { 1749566063dSJacob Faibussowitsch PetscCallMPI(MPI_Recv(work, n, MPIU_SCALAR, MPI_ANY_SOURCE, MSGTAG0 + edge_not_pow_2, MPI_COMM_WORLD, &status)); 175827bd09bSSatish Balay (*fp)(vals, work, n, oprs); 176827bd09bSSatish Balay } 177827bd09bSSatish Balay } 178827bd09bSSatish Balay 179827bd09bSSatish Balay /* implement the mesh fan in/out exchange algorithm */ 180db4deed7SKarl Rupp if (PCTFS_my_id < PCTFS_floor_num_nodes) { 181db4deed7SKarl Rupp for (mask = 1, edge = 0; edge < PCTFS_i_log2_num_nodes; edge++, mask <<= 1) { 182b1c944f5SJed Brown dest = PCTFS_my_id ^ mask; 1832fa5cd67SKarl Rupp if (PCTFS_my_id > dest) { 1849566063dSJacob Faibussowitsch PetscCallMPI(MPI_Send(vals, n, MPIU_SCALAR, dest, MSGTAG2 + PCTFS_my_id, MPI_COMM_WORLD)); 1852fa5cd67SKarl Rupp } else { 1869566063dSJacob Faibussowitsch PetscCallMPI(MPI_Recv(work, n, MPIU_SCALAR, MPI_ANY_SOURCE, MSGTAG2 + dest, MPI_COMM_WORLD, &status)); 187827bd09bSSatish Balay (*fp)(vals, work, n, oprs); 188827bd09bSSatish Balay } 189827bd09bSSatish Balay } 190827bd09bSSatish Balay 191b1c944f5SJed Brown mask = PCTFS_floor_num_nodes >> 1; 192db4deed7SKarl Rupp for (edge = 0; edge < PCTFS_i_log2_num_nodes; edge++, mask >>= 1) { 1932fa5cd67SKarl Rupp if (PCTFS_my_id % mask) continue; 194827bd09bSSatish Balay 195b1c944f5SJed Brown dest = PCTFS_my_id ^ mask; 1962fa5cd67SKarl Rupp if (PCTFS_my_id < dest) { 1979566063dSJacob Faibussowitsch PetscCallMPI(MPI_Send(vals, n, MPIU_SCALAR, dest, MSGTAG4 + PCTFS_my_id, MPI_COMM_WORLD)); 1982fa5cd67SKarl Rupp } else { 1999566063dSJacob Faibussowitsch PetscCallMPI(MPI_Recv(vals, n, MPIU_SCALAR, MPI_ANY_SOURCE, MSGTAG4 + dest, MPI_COMM_WORLD, &status)); 200827bd09bSSatish Balay } 201827bd09bSSatish Balay } 202827bd09bSSatish Balay } 203827bd09bSSatish Balay 204827bd09bSSatish Balay /* if not a hypercube must expand to partial dim */ 205db4deed7SKarl Rupp if (edge_not_pow_2) { 206db4deed7SKarl Rupp if (PCTFS_my_id >= PCTFS_floor_num_nodes) { 2079566063dSJacob Faibussowitsch PetscCallMPI(MPI_Recv(vals, n, MPIU_SCALAR, MPI_ANY_SOURCE, MSGTAG5 + edge_not_pow_2, MPI_COMM_WORLD, &status)); 208db4deed7SKarl Rupp } else { 2099566063dSJacob Faibussowitsch PetscCallMPI(MPI_Send(vals, n, MPIU_SCALAR, edge_not_pow_2, MSGTAG5 + PCTFS_my_id, MPI_COMM_WORLD)); 210827bd09bSSatish Balay } 211827bd09bSSatish Balay } 2123fdc5746SBarry Smith PetscFunctionReturn(0); 213827bd09bSSatish Balay } 214827bd09bSSatish Balay 2157b1ae94cSBarry Smith /***********************************comm.c*************************************/ 216d71ae5a4SJacob Faibussowitsch PetscErrorCode PCTFS_grop_hc(PetscScalar *vals, PetscScalar *work, PetscInt n, PetscInt *oprs, PetscInt dim) 217d71ae5a4SJacob Faibussowitsch { 2183fdc5746SBarry Smith PetscInt mask, edge; 2193fdc5746SBarry Smith PetscInt type, dest; 220827bd09bSSatish Balay vfp fp; 221827bd09bSSatish Balay MPI_Status status; 222827bd09bSSatish Balay 2233fdc5746SBarry Smith PetscFunctionBegin; 224827bd09bSSatish Balay /* ok ... should have some data, work, and operator(s) */ 225*c75bfeddSPierre Jolivet PetscCheck(vals && work && oprs, PETSC_COMM_SELF, PETSC_ERR_PLIB, "PCTFS_grop_hc() :: vals=%p, work=%p, oprs=%p", (void *)vals, (void *)work, (void *)oprs); 226827bd09bSSatish Balay 227827bd09bSSatish Balay /* non-uniform should have at least two entries */ 22808401ef6SPierre Jolivet PetscCheck(!(oprs[0] == NON_UNIFORM) || !(n < 2), PETSC_COMM_SELF, PETSC_ERR_PLIB, "PCTFS_grop_hc() :: non_uniform and n=0,1?"); 229827bd09bSSatish Balay 230827bd09bSSatish Balay /* check to make sure comm package has been initialized */ 2312fa5cd67SKarl Rupp if (!p_init) PCTFS_comm_init(); 232827bd09bSSatish Balay 233827bd09bSSatish Balay /* if there's nothing to do return */ 2342fa5cd67SKarl Rupp if ((PCTFS_num_nodes < 2) || (!n) || (dim <= 0)) PetscFunctionReturn(0); 235827bd09bSSatish Balay 236827bd09bSSatish Balay /* the error msg says it all!!! */ 23728b400f6SJacob Faibussowitsch PetscCheck(!modfl_num_nodes, PETSC_COMM_SELF, PETSC_ERR_PLIB, "PCTFS_grop_hc() :: PCTFS_num_nodes not a power of 2!?!"); 238827bd09bSSatish Balay 239827bd09bSSatish Balay /* a negative number of items to send ==> fatal */ 24063a3b9bcSJacob Faibussowitsch PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_PLIB, "PCTFS_grop_hc() :: n=%" PetscInt_FMT "<0?", n); 241827bd09bSSatish Balay 242827bd09bSSatish Balay /* can't do more dimensions then exist */ 243b1c944f5SJed Brown dim = PetscMin(dim, PCTFS_i_log2_num_nodes); 244827bd09bSSatish Balay 245827bd09bSSatish Balay /* advance to list of n operations for custom */ 2462fa5cd67SKarl Rupp if ((type = oprs[0]) == NON_UNIFORM) oprs++; 247827bd09bSSatish Balay 2487827d75bSBarry Smith PetscCheck(fp = (vfp)PCTFS_rvec_fct_addr(type), PETSC_COMM_SELF, PETSC_ERR_PLIB, "PCTFS_grop_hc() :: Could not retrieve function pointer!"); 249827bd09bSSatish Balay 250db4deed7SKarl Rupp for (mask = 1, edge = 0; edge < dim; edge++, mask <<= 1) { 251b1c944f5SJed Brown dest = PCTFS_my_id ^ mask; 2522fa5cd67SKarl Rupp if (PCTFS_my_id > dest) { 2539566063dSJacob Faibussowitsch PetscCallMPI(MPI_Send(vals, n, MPIU_SCALAR, dest, MSGTAG2 + PCTFS_my_id, MPI_COMM_WORLD)); 2542fa5cd67SKarl Rupp } else { 2559566063dSJacob Faibussowitsch PetscCallMPI(MPI_Recv(work, n, MPIU_SCALAR, MPI_ANY_SOURCE, MSGTAG2 + dest, MPI_COMM_WORLD, &status)); 256827bd09bSSatish Balay (*fp)(vals, work, n, oprs); 257827bd09bSSatish Balay } 258827bd09bSSatish Balay } 259827bd09bSSatish Balay 2602fa5cd67SKarl Rupp if (edge == dim) mask >>= 1; 261db4deed7SKarl Rupp else { 2622fa5cd67SKarl Rupp while (++edge < dim) mask <<= 1; 263db4deed7SKarl Rupp } 264827bd09bSSatish Balay 265db4deed7SKarl Rupp for (edge = 0; edge < dim; edge++, mask >>= 1) { 2662fa5cd67SKarl Rupp if (PCTFS_my_id % mask) continue; 267827bd09bSSatish Balay 268b1c944f5SJed Brown dest = PCTFS_my_id ^ mask; 2692fa5cd67SKarl Rupp if (PCTFS_my_id < dest) { 2709566063dSJacob Faibussowitsch PetscCallMPI(MPI_Send(vals, n, MPIU_SCALAR, dest, MSGTAG4 + PCTFS_my_id, MPI_COMM_WORLD)); 2712fa5cd67SKarl Rupp } else { 2729566063dSJacob Faibussowitsch PetscCallMPI(MPI_Recv(vals, n, MPIU_SCALAR, MPI_ANY_SOURCE, MSGTAG4 + dest, MPI_COMM_WORLD, &status)); 273827bd09bSSatish Balay } 274827bd09bSSatish Balay } 2753fdc5746SBarry Smith PetscFunctionReturn(0); 276827bd09bSSatish Balay } 277827bd09bSSatish Balay 2787b1ae94cSBarry Smith /******************************************************************************/ 279d71ae5a4SJacob Faibussowitsch PetscErrorCode PCTFS_ssgl_radd(PetscScalar *vals, PetscScalar *work, PetscInt level, PetscInt *segs) 280d71ae5a4SJacob Faibussowitsch { 2813fdc5746SBarry Smith PetscInt edge, type, dest, mask; 2823fdc5746SBarry Smith PetscInt stage_n; 283827bd09bSSatish Balay MPI_Status status; 2840912c85aSBarry Smith PetscMPIInt *maxval, flg; 285827bd09bSSatish Balay 2863fdc5746SBarry Smith PetscFunctionBegin; 287827bd09bSSatish Balay /* check to make sure comm package has been initialized */ 2882fa5cd67SKarl Rupp if (!p_init) PCTFS_comm_init(); 289827bd09bSSatish Balay 290827bd09bSSatish Balay /* all msgs are *NOT* the same length */ 291827bd09bSSatish Balay /* implement the mesh fan in/out exchange algorithm */ 292db4deed7SKarl Rupp for (mask = 0, edge = 0; edge < level; edge++, mask++) { 293827bd09bSSatish Balay stage_n = (segs[level] - segs[edge]); 294db4deed7SKarl Rupp if (stage_n && !(PCTFS_my_id & mask)) { 295827bd09bSSatish Balay dest = edge_node[edge]; 296b1c944f5SJed Brown type = MSGTAG3 + PCTFS_my_id + (PCTFS_num_nodes * edge); 2972fa5cd67SKarl Rupp if (PCTFS_my_id > dest) { 2989566063dSJacob Faibussowitsch PetscCallMPI(MPI_Send(vals + segs[edge], stage_n, MPIU_SCALAR, dest, type, MPI_COMM_WORLD)); 2992fa5cd67SKarl Rupp } else { 300b1c944f5SJed Brown type = type - PCTFS_my_id + dest; 3019566063dSJacob Faibussowitsch PetscCallMPI(MPI_Recv(work, stage_n, MPIU_SCALAR, MPI_ANY_SOURCE, type, MPI_COMM_WORLD, &status)); 302ca8e9878SJed Brown PCTFS_rvec_add(vals + segs[edge], work, stage_n); 303827bd09bSSatish Balay } 304827bd09bSSatish Balay } 305827bd09bSSatish Balay mask <<= 1; 306827bd09bSSatish Balay } 307827bd09bSSatish Balay mask >>= 1; 308db4deed7SKarl Rupp for (edge = 0; edge < level; edge++) { 309827bd09bSSatish Balay stage_n = (segs[level] - segs[level - 1 - edge]); 310db4deed7SKarl Rupp if (stage_n && !(PCTFS_my_id & mask)) { 311827bd09bSSatish Balay dest = edge_node[level - edge - 1]; 312b1c944f5SJed Brown type = MSGTAG6 + PCTFS_my_id + (PCTFS_num_nodes * edge); 3139566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_get_attr(MPI_COMM_WORLD, MPI_TAG_UB, &maxval, &flg)); 31428b400f6SJacob Faibussowitsch PetscCheck(flg, PETSC_COMM_SELF, PETSC_ERR_LIB, "MPI error: MPI_Comm_get_attr() is not returning a MPI_TAG_UB"); 31508401ef6SPierre Jolivet PetscCheck(*maxval > type, PETSC_COMM_SELF, PETSC_ERR_PLIB, "MPI_TAG_UB for your current MPI implementation is not large enough to use PCTFS"); 3162fa5cd67SKarl Rupp if (PCTFS_my_id < dest) { 3179566063dSJacob Faibussowitsch PetscCallMPI(MPI_Send(vals + segs[level - 1 - edge], stage_n, MPIU_SCALAR, dest, type, MPI_COMM_WORLD)); 3182fa5cd67SKarl Rupp } else { 319b1c944f5SJed Brown type = type - PCTFS_my_id + dest; 3209566063dSJacob Faibussowitsch PetscCallMPI(MPI_Recv(vals + segs[level - 1 - edge], stage_n, MPIU_SCALAR, MPI_ANY_SOURCE, type, MPI_COMM_WORLD, &status)); 321827bd09bSSatish Balay } 322827bd09bSSatish Balay } 323827bd09bSSatish Balay mask >>= 1; 324827bd09bSSatish Balay } 3253fdc5746SBarry Smith PetscFunctionReturn(0); 326827bd09bSSatish Balay } 327827bd09bSSatish Balay 3287b1ae94cSBarry Smith /***********************************comm.c*************************************/ 329d71ae5a4SJacob Faibussowitsch PetscErrorCode PCTFS_giop_hc(PetscInt *vals, PetscInt *work, PetscInt n, PetscInt *oprs, PetscInt dim) 330d71ae5a4SJacob Faibussowitsch { 33152f87cdaSBarry Smith PetscInt mask, edge; 33252f87cdaSBarry Smith PetscInt type, dest; 333827bd09bSSatish Balay vfp fp; 334827bd09bSSatish Balay MPI_Status status; 335827bd09bSSatish Balay 3363fdc5746SBarry Smith PetscFunctionBegin; 337827bd09bSSatish Balay /* ok ... should have some data, work, and operator(s) */ 338*c75bfeddSPierre Jolivet PetscCheck(vals && work && oprs, PETSC_COMM_SELF, PETSC_ERR_PLIB, "PCTFS_giop_hc() :: vals=%p, work=%p, oprs=%p", (void *)vals, (void *)work, (void *)oprs); 339827bd09bSSatish Balay 340827bd09bSSatish Balay /* non-uniform should have at least two entries */ 34108401ef6SPierre Jolivet PetscCheck(!(oprs[0] == NON_UNIFORM) || !(n < 2), PETSC_COMM_SELF, PETSC_ERR_PLIB, "PCTFS_giop_hc() :: non_uniform and n=0,1?"); 342827bd09bSSatish Balay 343827bd09bSSatish Balay /* check to make sure comm package has been initialized */ 3442fa5cd67SKarl Rupp if (!p_init) PCTFS_comm_init(); 345827bd09bSSatish Balay 346827bd09bSSatish Balay /* if there's nothing to do return */ 3472fa5cd67SKarl Rupp if ((PCTFS_num_nodes < 2) || (!n) || (dim <= 0)) PetscFunctionReturn(0); 348827bd09bSSatish Balay 349827bd09bSSatish Balay /* the error msg says it all!!! */ 35028b400f6SJacob Faibussowitsch PetscCheck(!modfl_num_nodes, PETSC_COMM_SELF, PETSC_ERR_PLIB, "PCTFS_giop_hc() :: PCTFS_num_nodes not a power of 2!?!"); 351827bd09bSSatish Balay 352827bd09bSSatish Balay /* a negative number of items to send ==> fatal */ 35363a3b9bcSJacob Faibussowitsch PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_PLIB, "PCTFS_giop_hc() :: n=%" PetscInt_FMT "<0?", n); 354827bd09bSSatish Balay 355827bd09bSSatish Balay /* can't do more dimensions then exist */ 356b1c944f5SJed Brown dim = PetscMin(dim, PCTFS_i_log2_num_nodes); 357827bd09bSSatish Balay 358827bd09bSSatish Balay /* advance to list of n operations for custom */ 3592fa5cd67SKarl Rupp if ((type = oprs[0]) == NON_UNIFORM) oprs++; 360827bd09bSSatish Balay 3617827d75bSBarry Smith PetscCheck(fp = (vfp)PCTFS_ivec_fct_addr(type), PETSC_COMM_SELF, PETSC_ERR_PLIB, "PCTFS_giop_hc() :: Could not retrieve function pointer!"); 362827bd09bSSatish Balay 363db4deed7SKarl Rupp for (mask = 1, edge = 0; edge < dim; edge++, mask <<= 1) { 364b1c944f5SJed Brown dest = PCTFS_my_id ^ mask; 3652fa5cd67SKarl Rupp if (PCTFS_my_id > dest) { 3669566063dSJacob Faibussowitsch PetscCallMPI(MPI_Send(vals, n, MPIU_INT, dest, MSGTAG2 + PCTFS_my_id, MPI_COMM_WORLD)); 3672fa5cd67SKarl Rupp } else { 3689566063dSJacob Faibussowitsch PetscCallMPI(MPI_Recv(work, n, MPIU_INT, MPI_ANY_SOURCE, MSGTAG2 + dest, MPI_COMM_WORLD, &status)); 369827bd09bSSatish Balay (*fp)(vals, work, n, oprs); 370827bd09bSSatish Balay } 371827bd09bSSatish Balay } 372827bd09bSSatish Balay 3732fa5cd67SKarl Rupp if (edge == dim) mask >>= 1; 3742fa5cd67SKarl Rupp else { 3752fa5cd67SKarl Rupp while (++edge < dim) mask <<= 1; 3762fa5cd67SKarl Rupp } 377827bd09bSSatish Balay 378db4deed7SKarl Rupp for (edge = 0; edge < dim; edge++, mask >>= 1) { 3792fa5cd67SKarl Rupp if (PCTFS_my_id % mask) continue; 380827bd09bSSatish Balay 381b1c944f5SJed Brown dest = PCTFS_my_id ^ mask; 3822fa5cd67SKarl Rupp if (PCTFS_my_id < dest) { 3839566063dSJacob Faibussowitsch PetscCallMPI(MPI_Send(vals, n, MPIU_INT, dest, MSGTAG4 + PCTFS_my_id, MPI_COMM_WORLD)); 3842fa5cd67SKarl Rupp } else { 3859566063dSJacob Faibussowitsch PetscCallMPI(MPI_Recv(vals, n, MPIU_INT, MPI_ANY_SOURCE, MSGTAG4 + dest, MPI_COMM_WORLD, &status)); 386827bd09bSSatish Balay } 387827bd09bSSatish Balay } 3883fdc5746SBarry Smith PetscFunctionReturn(0); 389827bd09bSSatish Balay } 390