xref: /petsc/src/ksp/pc/impls/tfs/comm.c (revision 3ba1676111f5c958fe6c2729b46ca4d523958bb3)
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;
35*3ba16761SJacob Faibussowitsch   if (p_init++) PetscFunctionReturn(PETSC_SUCCESS);
36827bd09bSSatish Balay 
37*3ba16761SJacob Faibussowitsch   PetscCallMPI(MPI_Comm_size(MPI_COMM_WORLD, &PCTFS_num_nodes));
38*3ba16761SJacob Faibussowitsch   PetscCallMPI(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 
42*3ba16761SJacob Faibussowitsch   PetscCall(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;
59*3ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
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) */
72c75bfeddSPierre 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 */
78*3ba16761SJacob Faibussowitsch   if (!p_init) PetscCall(PCTFS_comm_init());
79827bd09bSSatish Balay 
80827bd09bSSatish Balay   /* if there's nothing to do return */
81*3ba16761SJacob Faibussowitsch   if ((PCTFS_num_nodes < 2) || (!n)) PetscFunctionReturn(PETSC_SUCCESS);
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));
99*3ba16761SJacob Faibussowitsch       PetscCall((*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));
111*3ba16761SJacob Faibussowitsch         PetscCall((*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   }
136*3ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
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) */
149c75bfeddSPierre 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 */
155*3ba16761SJacob Faibussowitsch   if (!p_init) PetscCall(PCTFS_comm_init());
156827bd09bSSatish Balay 
157827bd09bSSatish Balay   /* if there's nothing to do return */
158*3ba16761SJacob Faibussowitsch   if ((PCTFS_num_nodes < 2) || (!n)) PetscFunctionReturn(PETSC_SUCCESS);
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 
166*3ba16761SJacob Faibussowitsch   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));
175*3ba16761SJacob Faibussowitsch       PetscCall((*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));
187*3ba16761SJacob Faibussowitsch         PetscCall((*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   }
212*3ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
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) */
225c75bfeddSPierre 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 */
231*3ba16761SJacob Faibussowitsch   if (!p_init) PetscCall(PCTFS_comm_init());
232827bd09bSSatish Balay 
233827bd09bSSatish Balay   /* if there's nothing to do return */
234*3ba16761SJacob Faibussowitsch   if ((PCTFS_num_nodes < 2) || (!n) || (dim <= 0)) PetscFunctionReturn(PETSC_SUCCESS);
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));
256*3ba16761SJacob Faibussowitsch       PetscCall((*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   }
275*3ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
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 */
288*3ba16761SJacob Faibussowitsch   if (!p_init) PetscCall(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));
302*3ba16761SJacob Faibussowitsch         PetscCall(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   }
325*3ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
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) */
338c75bfeddSPierre 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 */
344*3ba16761SJacob Faibussowitsch   if (!p_init) PetscCall(PCTFS_comm_init());
345827bd09bSSatish Balay 
346827bd09bSSatish Balay   /* if there's nothing to do return */
347*3ba16761SJacob Faibussowitsch   if ((PCTFS_num_nodes < 2) || (!n) || (dim <= 0)) PetscFunctionReturn(PETSC_SUCCESS);
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));
369*3ba16761SJacob Faibussowitsch       PetscCall((*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   }
388*3ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
389827bd09bSSatish Balay }
390