xref: /petsc/src/vec/is/sf/tests/ex3.c (revision 9371c9d470a9602b6d10a8bf50c9b2280a79e45a)
1c4762a1bSJed Brown static char help[] = "Test PetscSFFetchAndOp on patterned SF graphs. PetscSFFetchAndOp internally uses PetscSFBcastAndOp \n\
2c4762a1bSJed Brown  and PetscSFReduce. So it is a good test to see if they all work for patterned graphs.\n\
3c4762a1bSJed Brown  Run with ./prog -op [replace | sum]\n\n";
4c4762a1bSJed Brown 
5c4762a1bSJed Brown #include <petscvec.h>
6c4762a1bSJed Brown #include <petscsf.h>
7*9371c9d4SSatish Balay int main(int argc, char **argv) {
8c4762a1bSJed Brown   PetscInt     i, N = 10, low, high, nleaves;
9c4762a1bSJed Brown   PetscMPIInt  size, rank;
10c4762a1bSJed Brown   Vec          x, y, y2, gy2;
11c4762a1bSJed Brown   PetscScalar *rootdata, *leafdata, *leafupdate;
12c4762a1bSJed Brown   PetscLayout  layout;
13c4762a1bSJed Brown   PetscSF      gathersf, allgathersf, alltoallsf;
14c4762a1bSJed Brown   MPI_Op       op = MPI_SUM;
15c4762a1bSJed Brown   char         opname[64];
16c4762a1bSJed Brown   const char  *mpiopname;
17c4762a1bSJed Brown   PetscBool    flag, isreplace, issum;
18c4762a1bSJed Brown 
19327415f7SBarry Smith   PetscFunctionBeginUser;
209566063dSJacob Faibussowitsch   PetscCall(PetscInitialize(&argc, &argv, (char *)0, help));
219566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_size(PETSC_COMM_WORLD, &size));
229566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(PETSC_COMM_WORLD, &rank));
23c4762a1bSJed Brown 
249566063dSJacob Faibussowitsch   PetscCall(PetscOptionsGetString(NULL, NULL, "-op", opname, sizeof(opname), &flag));
259566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp(opname, "replace", &isreplace));
269566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp(opname, "sum", &issum));
27c4762a1bSJed Brown 
28*9371c9d4SSatish Balay   if (isreplace) {
29*9371c9d4SSatish Balay     op        = MPI_REPLACE;
30*9371c9d4SSatish Balay     mpiopname = "MPI_REPLACE";
31*9371c9d4SSatish Balay   } else if (issum) {
32*9371c9d4SSatish Balay     op        = MPIU_SUM;
33*9371c9d4SSatish Balay     mpiopname = "MPI_SUM";
34*9371c9d4SSatish Balay   } else SETERRQ(PETSC_COMM_WORLD, PETSC_ERR_ARG_WRONG, "Unsupported argument (%s) to -op, which must be 'replace' or 'sum'", opname);
35c4762a1bSJed Brown 
369566063dSJacob Faibussowitsch   PetscCall(VecCreate(PETSC_COMM_WORLD, &x));
379566063dSJacob Faibussowitsch   PetscCall(VecSetFromOptions(x));
389566063dSJacob Faibussowitsch   PetscCall(VecSetSizes(x, PETSC_DECIDE, N));
39c4762a1bSJed Brown 
40c4762a1bSJed Brown   /*-------------------------------------*/
41c4762a1bSJed Brown   /*       PETSCSF_PATTERN_GATHER        */
42c4762a1bSJed Brown   /*-------------------------------------*/
43c4762a1bSJed Brown 
44c4762a1bSJed Brown   /* set MPI vec x to [1, 2, .., N] */
459566063dSJacob Faibussowitsch   PetscCall(VecGetOwnershipRange(x, &low, &high));
469566063dSJacob Faibussowitsch   for (i = low; i < high; i++) PetscCall(VecSetValue(x, i, (PetscScalar)i + 1.0, INSERT_VALUES));
479566063dSJacob Faibussowitsch   PetscCall(VecAssemblyBegin(x));
489566063dSJacob Faibussowitsch   PetscCall(VecAssemblyEnd(x));
49c4762a1bSJed Brown 
50c4762a1bSJed Brown   /* Create the gather SF */
519566063dSJacob Faibussowitsch   PetscCall(PetscPrintf(PETSC_COMM_WORLD, "\nTesting PetscSFFetchAndOp on a PETSCSF_PATTERN_GATHER graph with op = %s\n", mpiopname));
529566063dSJacob Faibussowitsch   PetscCall(VecGetLayout(x, &layout));
539566063dSJacob Faibussowitsch   PetscCall(PetscSFCreate(PETSC_COMM_WORLD, &gathersf));
549566063dSJacob Faibussowitsch   PetscCall(PetscSFSetGraphWithPattern(gathersf, layout, PETSCSF_PATTERN_GATHER));
55c4762a1bSJed Brown 
56c4762a1bSJed Brown   /* Create the leaf vector y (seq vector) and its duplicate y2 working as leafupdate */
579566063dSJacob Faibussowitsch   PetscCall(PetscSFGetGraph(gathersf, NULL, &nleaves, NULL, NULL));
589566063dSJacob Faibussowitsch   PetscCall(VecCreateSeq(PETSC_COMM_SELF, nleaves, &y));
599566063dSJacob Faibussowitsch   PetscCall(VecDuplicate(y, &y2));
60c4762a1bSJed Brown 
619566063dSJacob Faibussowitsch   PetscCall(VecGetArray(x, &rootdata));
629566063dSJacob Faibussowitsch   PetscCall(VecGetArray(y, &leafdata));
639566063dSJacob Faibussowitsch   PetscCall(VecGetArray(y2, &leafupdate));
64c4762a1bSJed Brown 
65c4762a1bSJed Brown   /* Bcast x to y,to initialize y = [1,N], then scale y to make leafupdate = y = [2,2*N] */
669566063dSJacob Faibussowitsch   PetscCall(PetscSFBcastBegin(gathersf, MPIU_SCALAR, rootdata, leafdata, MPI_REPLACE));
679566063dSJacob Faibussowitsch   PetscCall(PetscSFBcastEnd(gathersf, MPIU_SCALAR, rootdata, leafdata, MPI_REPLACE));
689566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(y, &leafdata));
699566063dSJacob Faibussowitsch   PetscCall(VecScale(y, 2));
709566063dSJacob Faibussowitsch   PetscCall(VecGetArray(y, &leafdata));
71c4762a1bSJed Brown 
72c4762a1bSJed Brown   /* FetchAndOp x to y */
739566063dSJacob Faibussowitsch   PetscCall(PetscSFFetchAndOpBegin(gathersf, MPIU_SCALAR, rootdata, leafdata, leafupdate, op));
749566063dSJacob Faibussowitsch   PetscCall(PetscSFFetchAndOpEnd(gathersf, MPIU_SCALAR, rootdata, leafdata, leafupdate, op));
75c4762a1bSJed Brown 
76c4762a1bSJed Brown   /* View roots (x) and leafupdate (y2). Since this is a gather graph, leafudpate = rootdata = [1,N], then rootdata += leafdata, i.e., [3,3*N] */
779566063dSJacob Faibussowitsch   PetscCall(VecCreateMPIWithArray(PETSC_COMM_WORLD, 1, nleaves, PETSC_DECIDE, leafupdate, &gy2));
789566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetName((PetscObject)x, "rootdata"));
799566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetName((PetscObject)gy2, "leafupdate"));
80c4762a1bSJed Brown 
819566063dSJacob Faibussowitsch   PetscCall(VecView(x, PETSC_VIEWER_STDOUT_WORLD));
829566063dSJacob Faibussowitsch   PetscCall(VecView(gy2, PETSC_VIEWER_STDOUT_WORLD));
839566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&gy2));
84c4762a1bSJed Brown 
859566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(y2, &leafupdate));
869566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&y2));
87c4762a1bSJed Brown 
889566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(y, &leafdata));
899566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&y));
90c4762a1bSJed Brown 
919566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(x, &rootdata));
929566063dSJacob Faibussowitsch   /* PetscCall(VecDestroy(&x)); */ /* We will reuse x in ALLGATHER, so do not destroy it */
93c4762a1bSJed Brown 
949566063dSJacob Faibussowitsch   PetscCall(PetscSFDestroy(&gathersf));
95c4762a1bSJed Brown 
96c4762a1bSJed Brown   /*-------------------------------------*/
97c4762a1bSJed Brown   /*       PETSCSF_PATTERN_ALLGATHER     */
98c4762a1bSJed Brown   /*-------------------------------------*/
99c4762a1bSJed Brown 
100c4762a1bSJed Brown   /* set MPI vec x to [1, 2, .., N] */
1019566063dSJacob Faibussowitsch   for (i = low; i < high; i++) PetscCall(VecSetValue(x, i, (PetscScalar)i + 1.0, INSERT_VALUES));
1029566063dSJacob Faibussowitsch   PetscCall(VecAssemblyBegin(x));
1039566063dSJacob Faibussowitsch   PetscCall(VecAssemblyEnd(x));
104c4762a1bSJed Brown 
105c4762a1bSJed Brown   /* Create the allgather SF */
1069566063dSJacob Faibussowitsch   PetscCall(PetscPrintf(PETSC_COMM_WORLD, "\nTesting PetscSFFetchAndOp on a PETSCSF_PATTERN_ALLGATHER graph with op = %s\n", mpiopname));
1079566063dSJacob Faibussowitsch   PetscCall(VecGetLayout(x, &layout));
1089566063dSJacob Faibussowitsch   PetscCall(PetscSFCreate(PETSC_COMM_WORLD, &allgathersf));
1099566063dSJacob Faibussowitsch   PetscCall(PetscSFSetGraphWithPattern(allgathersf, layout, PETSCSF_PATTERN_ALLGATHER));
110c4762a1bSJed Brown 
111c4762a1bSJed Brown   /* Create the leaf vector y (seq vector) and its duplicate y2 working as leafupdate */
1129566063dSJacob Faibussowitsch   PetscCall(PetscSFGetGraph(allgathersf, NULL, &nleaves, NULL, NULL));
1139566063dSJacob Faibussowitsch   PetscCall(VecCreateSeq(PETSC_COMM_SELF, nleaves, &y));
1149566063dSJacob Faibussowitsch   PetscCall(VecDuplicate(y, &y2));
115c4762a1bSJed Brown 
1169566063dSJacob Faibussowitsch   PetscCall(VecGetArray(x, &rootdata));
1179566063dSJacob Faibussowitsch   PetscCall(VecGetArray(y, &leafdata));
1189566063dSJacob Faibussowitsch   PetscCall(VecGetArray(y2, &leafupdate));
119c4762a1bSJed Brown 
120c4762a1bSJed Brown   /* Bcast x to y, to initialize y = [1,N], then scale y to make leafupdate = y = [2,2*N] */
1219566063dSJacob Faibussowitsch   PetscCall(PetscSFBcastBegin(allgathersf, MPIU_SCALAR, rootdata, leafdata, MPI_REPLACE));
1229566063dSJacob Faibussowitsch   PetscCall(PetscSFBcastEnd(allgathersf, MPIU_SCALAR, rootdata, leafdata, MPI_REPLACE));
1239566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(y, &leafdata));
1249566063dSJacob Faibussowitsch   PetscCall(VecScale(y, 2));
1259566063dSJacob Faibussowitsch   PetscCall(VecGetArray(y, &leafdata));
126c4762a1bSJed Brown 
127c4762a1bSJed Brown   /* FetchAndOp x to y */
1289566063dSJacob Faibussowitsch   PetscCall(PetscSFFetchAndOpBegin(allgathersf, MPIU_SCALAR, rootdata, leafdata, leafupdate, op));
1299566063dSJacob Faibussowitsch   PetscCall(PetscSFFetchAndOpEnd(allgathersf, MPIU_SCALAR, rootdata, leafdata, leafupdate, op));
130c4762a1bSJed Brown 
131c4762a1bSJed Brown   /* View roots (x) and leafupdate (y2). Since this is an allgather graph, we have (suppose ranks get updates in ascending order)
132c4762a1bSJed Brown      rank 0: leafupdate = rootdata = [1,N],   rootdata += leafdata = [3,3*N]
133c4762a1bSJed Brown      rank 1: leafupdate = rootdata = [3,3*N], rootdata += leafdata = [5,5*N]
134c4762a1bSJed Brown      rank 2: leafupdate = rootdata = [5,5*N], rootdata += leafdata = [7,7*N]
135c4762a1bSJed Brown      ...
136c4762a1bSJed Brown    */
1379566063dSJacob Faibussowitsch   PetscCall(VecCreateMPIWithArray(PETSC_COMM_WORLD, 1, nleaves, PETSC_DECIDE, leafupdate, &gy2));
1389566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetName((PetscObject)x, "rootdata"));
1399566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetName((PetscObject)gy2, "leafupdate"));
140c4762a1bSJed Brown 
1419566063dSJacob Faibussowitsch   PetscCall(VecView(x, PETSC_VIEWER_STDOUT_WORLD));
1429566063dSJacob Faibussowitsch   PetscCall(VecView(gy2, PETSC_VIEWER_STDOUT_WORLD));
1439566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&gy2));
144c4762a1bSJed Brown 
1459566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(y2, &leafupdate));
1469566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&y2));
147c4762a1bSJed Brown 
1489566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(y, &leafdata));
1499566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&y));
150c4762a1bSJed Brown 
1519566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(x, &rootdata));
1529566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&x)); /* We won't reuse x in ALLGATHER, so destroy it */
153c4762a1bSJed Brown 
1549566063dSJacob Faibussowitsch   PetscCall(PetscSFDestroy(&allgathersf));
155c4762a1bSJed Brown 
156c4762a1bSJed Brown   /*-------------------------------------*/
157c4762a1bSJed Brown   /*       PETSCSF_PATTERN_ALLTOALL     */
158c4762a1bSJed Brown   /*-------------------------------------*/
159c4762a1bSJed Brown 
1609566063dSJacob Faibussowitsch   PetscCall(VecCreate(PETSC_COMM_WORLD, &x));
1619566063dSJacob Faibussowitsch   PetscCall(VecSetFromOptions(x));
1629566063dSJacob Faibussowitsch   PetscCall(VecSetSizes(x, size, PETSC_DECIDE));
163c4762a1bSJed Brown 
164c4762a1bSJed Brown   /* set MPI vec x to [1, 2, .., size^2] */
1659566063dSJacob Faibussowitsch   PetscCall(VecGetOwnershipRange(x, &low, &high));
1669566063dSJacob Faibussowitsch   for (i = low; i < high; i++) PetscCall(VecSetValue(x, i, (PetscScalar)i + 1.0, INSERT_VALUES));
1679566063dSJacob Faibussowitsch   PetscCall(VecAssemblyBegin(x));
1689566063dSJacob Faibussowitsch   PetscCall(VecAssemblyEnd(x));
169c4762a1bSJed Brown 
170c4762a1bSJed Brown   /* Create the alltoall SF */
1719566063dSJacob Faibussowitsch   PetscCall(PetscPrintf(PETSC_COMM_WORLD, "\nTesting PetscSFFetchAndOp on a PETSCSF_PATTERN_ALLTOALL graph with op = %s\n", mpiopname));
1729566063dSJacob Faibussowitsch   PetscCall(PetscSFCreate(PETSC_COMM_WORLD, &alltoallsf));
1739566063dSJacob Faibussowitsch   PetscCall(PetscSFSetGraphWithPattern(alltoallsf, NULL /*insignificant*/, PETSCSF_PATTERN_ALLTOALL));
174c4762a1bSJed Brown 
175c4762a1bSJed Brown   /* Create the leaf vector y (seq vector) and its duplicate y2 working as leafupdate */
1769566063dSJacob Faibussowitsch   PetscCall(PetscSFGetGraph(alltoallsf, NULL, &nleaves, NULL, NULL));
1779566063dSJacob Faibussowitsch   PetscCall(VecCreateSeq(PETSC_COMM_SELF, nleaves, &y));
1789566063dSJacob Faibussowitsch   PetscCall(VecDuplicate(y, &y2));
179c4762a1bSJed Brown 
1809566063dSJacob Faibussowitsch   PetscCall(VecGetArray(x, &rootdata));
1819566063dSJacob Faibussowitsch   PetscCall(VecGetArray(y, &leafdata));
1829566063dSJacob Faibussowitsch   PetscCall(VecGetArray(y2, &leafupdate));
183c4762a1bSJed Brown 
184c4762a1bSJed Brown   /* Bcast x to y, to initialize y = 1+rank+size*i, with i=0..size-1 */
1859566063dSJacob Faibussowitsch   PetscCall(PetscSFBcastBegin(alltoallsf, MPIU_SCALAR, rootdata, leafdata, MPI_REPLACE));
1869566063dSJacob Faibussowitsch   PetscCall(PetscSFBcastEnd(alltoallsf, MPIU_SCALAR, rootdata, leafdata, MPI_REPLACE));
187c4762a1bSJed Brown 
188c4762a1bSJed Brown   /* FetchAndOp x to y */
1899566063dSJacob Faibussowitsch   PetscCall(PetscSFFetchAndOpBegin(alltoallsf, MPIU_SCALAR, rootdata, leafdata, leafupdate, op));
1909566063dSJacob Faibussowitsch   PetscCall(PetscSFFetchAndOpEnd(alltoallsf, MPIU_SCALAR, rootdata, leafdata, leafupdate, op));
191c4762a1bSJed Brown 
192c4762a1bSJed Brown   /* View roots (x) and leafupdate (y2). Since this is an alltoall graph, each root has only one leaf.
193c4762a1bSJed Brown      So, leafupdate = rootdata = 1+rank+size*i, i=0..size-1; and rootdata += leafdata, i.e., rootdata = [2,2*N]
194c4762a1bSJed Brown    */
1959566063dSJacob Faibussowitsch   PetscCall(VecCreateMPIWithArray(PETSC_COMM_WORLD, 1, nleaves, PETSC_DECIDE, leafupdate, &gy2));
1969566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetName((PetscObject)x, "rootdata"));
1979566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetName((PetscObject)gy2, "leafupdate"));
198c4762a1bSJed Brown 
1999566063dSJacob Faibussowitsch   PetscCall(VecView(x, PETSC_VIEWER_STDOUT_WORLD));
2009566063dSJacob Faibussowitsch   PetscCall(VecView(gy2, PETSC_VIEWER_STDOUT_WORLD));
2019566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&gy2));
202c4762a1bSJed Brown 
2039566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(y2, &leafupdate));
2049566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&y2));
205c4762a1bSJed Brown 
2069566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(y, &leafdata));
2079566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&y));
208c4762a1bSJed Brown 
2099566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(x, &rootdata));
2109566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&x));
211c4762a1bSJed Brown 
2129566063dSJacob Faibussowitsch   PetscCall(PetscSFDestroy(&alltoallsf));
213c4762a1bSJed Brown 
2149566063dSJacob Faibussowitsch   PetscCall(PetscFinalize());
215b122ec5aSJacob Faibussowitsch   return 0;
216c4762a1bSJed Brown }
217c4762a1bSJed Brown 
218c4762a1bSJed Brown /*TEST
219c4762a1bSJed Brown 
220c4762a1bSJed Brown    test:
221c4762a1bSJed Brown       # N=10 is divisible by nsize, to trigger Allgather/Gather in SF
222f424265bSStefano Zampini       #MPI_Sendrecv_replace is broken with 20210400300
223f424265bSStefano Zampini       requires: !defined(PETSC_HAVE_I_MPI_NUMVERSION)
224c4762a1bSJed Brown       nsize: 2
225c4762a1bSJed Brown       args: -op replace
226c4762a1bSJed Brown 
227c4762a1bSJed Brown    test:
228c4762a1bSJed Brown       suffix: 2
229c4762a1bSJed Brown       nsize: 2
230c4762a1bSJed Brown       args: -op sum
231c4762a1bSJed Brown 
232c4762a1bSJed Brown    # N=10 is not divisible by nsize, to trigger Allgatherv/Gatherv in SF
233c4762a1bSJed Brown    test:
234f424265bSStefano Zampini       #MPI_Sendrecv_replace is broken with 20210400300
235f424265bSStefano Zampini       requires: !defined(PETSC_HAVE_I_MPI_NUMVERSION)
236c4762a1bSJed Brown       suffix: 3
237c4762a1bSJed Brown       nsize: 3
238c4762a1bSJed Brown       args: -op replace
239c4762a1bSJed Brown 
240c4762a1bSJed Brown    test:
241c4762a1bSJed Brown       suffix: 4
242c4762a1bSJed Brown       nsize: 3
243c4762a1bSJed Brown       args: -op sum
244c4762a1bSJed Brown 
245c4762a1bSJed Brown TEST*/
246