xref: /petsc/src/vec/is/sf/tests/ex3.c (revision 732aec7a18f2199fb53bb9a2f3aef439a834ce31)
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>
main(int argc,char ** argv)7d71ae5a4SJacob Faibussowitsch int main(int argc, char **argv)
8d71ae5a4SJacob Faibussowitsch {
9c4762a1bSJed Brown   PetscInt     i, N = 10, low, high, nleaves;
10c4762a1bSJed Brown   PetscMPIInt  size, rank;
11c4762a1bSJed Brown   Vec          x, y, y2, gy2;
12c4762a1bSJed Brown   PetscScalar *rootdata, *leafdata, *leafupdate;
13c4762a1bSJed Brown   PetscLayout  layout;
14c4762a1bSJed Brown   PetscSF      gathersf, allgathersf, alltoallsf;
15c4762a1bSJed Brown   MPI_Op       op = MPI_SUM;
16c4762a1bSJed Brown   char         opname[64];
17c4762a1bSJed Brown   const char  *mpiopname;
18c4762a1bSJed Brown   PetscBool    flag, isreplace, issum;
19c4762a1bSJed Brown 
20327415f7SBarry Smith   PetscFunctionBeginUser;
21*c8025a54SPierre Jolivet   PetscCall(PetscInitialize(&argc, &argv, NULL, help));
229566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_size(PETSC_COMM_WORLD, &size));
239566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(PETSC_COMM_WORLD, &rank));
24c4762a1bSJed Brown 
259566063dSJacob Faibussowitsch   PetscCall(PetscOptionsGetString(NULL, NULL, "-op", opname, sizeof(opname), &flag));
269566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp(opname, "replace", &isreplace));
279566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp(opname, "sum", &issum));
28c4762a1bSJed Brown 
299371c9d4SSatish Balay   if (isreplace) {
309371c9d4SSatish Balay     op        = MPI_REPLACE;
319371c9d4SSatish Balay     mpiopname = "MPI_REPLACE";
329371c9d4SSatish Balay   } else if (issum) {
339371c9d4SSatish Balay     op        = MPIU_SUM;
349371c9d4SSatish Balay     mpiopname = "MPI_SUM";
359371c9d4SSatish Balay   } else SETERRQ(PETSC_COMM_WORLD, PETSC_ERR_ARG_WRONG, "Unsupported argument (%s) to -op, which must be 'replace' or 'sum'", opname);
36c4762a1bSJed Brown 
379566063dSJacob Faibussowitsch   PetscCall(VecCreate(PETSC_COMM_WORLD, &x));
389566063dSJacob Faibussowitsch   PetscCall(VecSetFromOptions(x));
399566063dSJacob Faibussowitsch   PetscCall(VecSetSizes(x, PETSC_DECIDE, N));
40c4762a1bSJed Brown 
41c4762a1bSJed Brown   /*-------------------------------------*/
42c4762a1bSJed Brown   /*       PETSCSF_PATTERN_GATHER        */
43c4762a1bSJed Brown   /*-------------------------------------*/
44c4762a1bSJed Brown 
45c4762a1bSJed Brown   /* set MPI vec x to [1, 2, .., N] */
469566063dSJacob Faibussowitsch   PetscCall(VecGetOwnershipRange(x, &low, &high));
479566063dSJacob Faibussowitsch   for (i = low; i < high; i++) PetscCall(VecSetValue(x, i, (PetscScalar)i + 1.0, INSERT_VALUES));
489566063dSJacob Faibussowitsch   PetscCall(VecAssemblyBegin(x));
499566063dSJacob Faibussowitsch   PetscCall(VecAssemblyEnd(x));
50c4762a1bSJed Brown 
51c4762a1bSJed Brown   /* Create the gather SF */
529566063dSJacob Faibussowitsch   PetscCall(PetscPrintf(PETSC_COMM_WORLD, "\nTesting PetscSFFetchAndOp on a PETSCSF_PATTERN_GATHER graph with op = %s\n", mpiopname));
539566063dSJacob Faibussowitsch   PetscCall(VecGetLayout(x, &layout));
549566063dSJacob Faibussowitsch   PetscCall(PetscSFCreate(PETSC_COMM_WORLD, &gathersf));
559566063dSJacob Faibussowitsch   PetscCall(PetscSFSetGraphWithPattern(gathersf, layout, PETSCSF_PATTERN_GATHER));
56c4762a1bSJed Brown 
57c4762a1bSJed Brown   /* Create the leaf vector y (seq vector) and its duplicate y2 working as leafupdate */
589566063dSJacob Faibussowitsch   PetscCall(PetscSFGetGraph(gathersf, NULL, &nleaves, NULL, NULL));
599566063dSJacob Faibussowitsch   PetscCall(VecCreateSeq(PETSC_COMM_SELF, nleaves, &y));
609566063dSJacob Faibussowitsch   PetscCall(VecDuplicate(y, &y2));
61c4762a1bSJed Brown 
629566063dSJacob Faibussowitsch   PetscCall(VecGetArray(x, &rootdata));
639566063dSJacob Faibussowitsch   PetscCall(VecGetArray(y, &leafdata));
649566063dSJacob Faibussowitsch   PetscCall(VecGetArray(y2, &leafupdate));
65c4762a1bSJed Brown 
66c4762a1bSJed Brown   /* Bcast x to y,to initialize y = [1,N], then scale y to make leafupdate = y = [2,2*N] */
679566063dSJacob Faibussowitsch   PetscCall(PetscSFBcastBegin(gathersf, MPIU_SCALAR, rootdata, leafdata, MPI_REPLACE));
689566063dSJacob Faibussowitsch   PetscCall(PetscSFBcastEnd(gathersf, MPIU_SCALAR, rootdata, leafdata, MPI_REPLACE));
699566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(y, &leafdata));
709566063dSJacob Faibussowitsch   PetscCall(VecScale(y, 2));
719566063dSJacob Faibussowitsch   PetscCall(VecGetArray(y, &leafdata));
72c4762a1bSJed Brown 
73c4762a1bSJed Brown   /* FetchAndOp x to y */
749566063dSJacob Faibussowitsch   PetscCall(PetscSFFetchAndOpBegin(gathersf, MPIU_SCALAR, rootdata, leafdata, leafupdate, op));
759566063dSJacob Faibussowitsch   PetscCall(PetscSFFetchAndOpEnd(gathersf, MPIU_SCALAR, rootdata, leafdata, leafupdate, op));
76c4762a1bSJed Brown 
77c4762a1bSJed 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] */
789566063dSJacob Faibussowitsch   PetscCall(VecCreateMPIWithArray(PETSC_COMM_WORLD, 1, nleaves, PETSC_DECIDE, leafupdate, &gy2));
799566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetName((PetscObject)x, "rootdata"));
809566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetName((PetscObject)gy2, "leafupdate"));
81c4762a1bSJed Brown 
829566063dSJacob Faibussowitsch   PetscCall(VecView(x, PETSC_VIEWER_STDOUT_WORLD));
839566063dSJacob Faibussowitsch   PetscCall(VecView(gy2, PETSC_VIEWER_STDOUT_WORLD));
849566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&gy2));
85c4762a1bSJed Brown 
869566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(y2, &leafupdate));
879566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&y2));
88c4762a1bSJed Brown 
899566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(y, &leafdata));
909566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&y));
91c4762a1bSJed Brown 
929566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(x, &rootdata));
939566063dSJacob Faibussowitsch   /* PetscCall(VecDestroy(&x)); */ /* We will reuse x in ALLGATHER, so do not destroy it */
94c4762a1bSJed Brown 
959566063dSJacob Faibussowitsch   PetscCall(PetscSFDestroy(&gathersf));
96c4762a1bSJed Brown 
97c4762a1bSJed Brown   /*-------------------------------------*/
98c4762a1bSJed Brown   /*       PETSCSF_PATTERN_ALLGATHER     */
99c4762a1bSJed Brown   /*-------------------------------------*/
100c4762a1bSJed Brown 
101c4762a1bSJed Brown   /* set MPI vec x to [1, 2, .., N] */
1029566063dSJacob Faibussowitsch   for (i = low; i < high; i++) PetscCall(VecSetValue(x, i, (PetscScalar)i + 1.0, INSERT_VALUES));
1039566063dSJacob Faibussowitsch   PetscCall(VecAssemblyBegin(x));
1049566063dSJacob Faibussowitsch   PetscCall(VecAssemblyEnd(x));
105c4762a1bSJed Brown 
106c4762a1bSJed Brown   /* Create the allgather SF */
1079566063dSJacob Faibussowitsch   PetscCall(PetscPrintf(PETSC_COMM_WORLD, "\nTesting PetscSFFetchAndOp on a PETSCSF_PATTERN_ALLGATHER graph with op = %s\n", mpiopname));
1089566063dSJacob Faibussowitsch   PetscCall(VecGetLayout(x, &layout));
1099566063dSJacob Faibussowitsch   PetscCall(PetscSFCreate(PETSC_COMM_WORLD, &allgathersf));
1109566063dSJacob Faibussowitsch   PetscCall(PetscSFSetGraphWithPattern(allgathersf, layout, PETSCSF_PATTERN_ALLGATHER));
111c4762a1bSJed Brown 
112c4762a1bSJed Brown   /* Create the leaf vector y (seq vector) and its duplicate y2 working as leafupdate */
1139566063dSJacob Faibussowitsch   PetscCall(PetscSFGetGraph(allgathersf, NULL, &nleaves, NULL, NULL));
1149566063dSJacob Faibussowitsch   PetscCall(VecCreateSeq(PETSC_COMM_SELF, nleaves, &y));
1159566063dSJacob Faibussowitsch   PetscCall(VecDuplicate(y, &y2));
116c4762a1bSJed Brown 
1179566063dSJacob Faibussowitsch   PetscCall(VecGetArray(x, &rootdata));
1189566063dSJacob Faibussowitsch   PetscCall(VecGetArray(y, &leafdata));
1199566063dSJacob Faibussowitsch   PetscCall(VecGetArray(y2, &leafupdate));
120c4762a1bSJed Brown 
121c4762a1bSJed Brown   /* Bcast x to y, to initialize y = [1,N], then scale y to make leafupdate = y = [2,2*N] */
1229566063dSJacob Faibussowitsch   PetscCall(PetscSFBcastBegin(allgathersf, MPIU_SCALAR, rootdata, leafdata, MPI_REPLACE));
1239566063dSJacob Faibussowitsch   PetscCall(PetscSFBcastEnd(allgathersf, MPIU_SCALAR, rootdata, leafdata, MPI_REPLACE));
1249566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(y, &leafdata));
1259566063dSJacob Faibussowitsch   PetscCall(VecScale(y, 2));
1269566063dSJacob Faibussowitsch   PetscCall(VecGetArray(y, &leafdata));
127c4762a1bSJed Brown 
128c4762a1bSJed Brown   /* FetchAndOp x to y */
1299566063dSJacob Faibussowitsch   PetscCall(PetscSFFetchAndOpBegin(allgathersf, MPIU_SCALAR, rootdata, leafdata, leafupdate, op));
1309566063dSJacob Faibussowitsch   PetscCall(PetscSFFetchAndOpEnd(allgathersf, MPIU_SCALAR, rootdata, leafdata, leafupdate, op));
131c4762a1bSJed Brown 
132c4762a1bSJed Brown   /* View roots (x) and leafupdate (y2). Since this is an allgather graph, we have (suppose ranks get updates in ascending order)
133c4762a1bSJed Brown      rank 0: leafupdate = rootdata = [1,N],   rootdata += leafdata = [3,3*N]
134c4762a1bSJed Brown      rank 1: leafupdate = rootdata = [3,3*N], rootdata += leafdata = [5,5*N]
135c4762a1bSJed Brown      rank 2: leafupdate = rootdata = [5,5*N], rootdata += leafdata = [7,7*N]
136c4762a1bSJed Brown      ...
137c4762a1bSJed Brown    */
1389566063dSJacob Faibussowitsch   PetscCall(VecCreateMPIWithArray(PETSC_COMM_WORLD, 1, nleaves, PETSC_DECIDE, leafupdate, &gy2));
1399566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetName((PetscObject)x, "rootdata"));
1409566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetName((PetscObject)gy2, "leafupdate"));
141c4762a1bSJed Brown 
1429566063dSJacob Faibussowitsch   PetscCall(VecView(x, PETSC_VIEWER_STDOUT_WORLD));
1439566063dSJacob Faibussowitsch   PetscCall(VecView(gy2, PETSC_VIEWER_STDOUT_WORLD));
1449566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&gy2));
145c4762a1bSJed Brown 
1469566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(y2, &leafupdate));
1479566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&y2));
148c4762a1bSJed Brown 
1499566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(y, &leafdata));
1509566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&y));
151c4762a1bSJed Brown 
1529566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(x, &rootdata));
1539566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&x)); /* We won't reuse x in ALLGATHER, so destroy it */
154c4762a1bSJed Brown 
1559566063dSJacob Faibussowitsch   PetscCall(PetscSFDestroy(&allgathersf));
156c4762a1bSJed Brown 
157c4762a1bSJed Brown   /*-------------------------------------*/
158c4762a1bSJed Brown   /*       PETSCSF_PATTERN_ALLTOALL     */
159c4762a1bSJed Brown   /*-------------------------------------*/
160c4762a1bSJed Brown 
1619566063dSJacob Faibussowitsch   PetscCall(VecCreate(PETSC_COMM_WORLD, &x));
1629566063dSJacob Faibussowitsch   PetscCall(VecSetFromOptions(x));
1639566063dSJacob Faibussowitsch   PetscCall(VecSetSizes(x, size, PETSC_DECIDE));
164c4762a1bSJed Brown 
165c4762a1bSJed Brown   /* set MPI vec x to [1, 2, .., size^2] */
1669566063dSJacob Faibussowitsch   PetscCall(VecGetOwnershipRange(x, &low, &high));
1679566063dSJacob Faibussowitsch   for (i = low; i < high; i++) PetscCall(VecSetValue(x, i, (PetscScalar)i + 1.0, INSERT_VALUES));
1689566063dSJacob Faibussowitsch   PetscCall(VecAssemblyBegin(x));
1699566063dSJacob Faibussowitsch   PetscCall(VecAssemblyEnd(x));
170c4762a1bSJed Brown 
171c4762a1bSJed Brown   /* Create the alltoall SF */
1729566063dSJacob Faibussowitsch   PetscCall(PetscPrintf(PETSC_COMM_WORLD, "\nTesting PetscSFFetchAndOp on a PETSCSF_PATTERN_ALLTOALL graph with op = %s\n", mpiopname));
1739566063dSJacob Faibussowitsch   PetscCall(PetscSFCreate(PETSC_COMM_WORLD, &alltoallsf));
1749566063dSJacob Faibussowitsch   PetscCall(PetscSFSetGraphWithPattern(alltoallsf, NULL /*insignificant*/, PETSCSF_PATTERN_ALLTOALL));
175c4762a1bSJed Brown 
176c4762a1bSJed Brown   /* Create the leaf vector y (seq vector) and its duplicate y2 working as leafupdate */
1779566063dSJacob Faibussowitsch   PetscCall(PetscSFGetGraph(alltoallsf, NULL, &nleaves, NULL, NULL));
1789566063dSJacob Faibussowitsch   PetscCall(VecCreateSeq(PETSC_COMM_SELF, nleaves, &y));
1799566063dSJacob Faibussowitsch   PetscCall(VecDuplicate(y, &y2));
180c4762a1bSJed Brown 
1819566063dSJacob Faibussowitsch   PetscCall(VecGetArray(x, &rootdata));
1829566063dSJacob Faibussowitsch   PetscCall(VecGetArray(y, &leafdata));
1839566063dSJacob Faibussowitsch   PetscCall(VecGetArray(y2, &leafupdate));
184c4762a1bSJed Brown 
185c4762a1bSJed Brown   /* Bcast x to y, to initialize y = 1+rank+size*i, with i=0..size-1 */
1869566063dSJacob Faibussowitsch   PetscCall(PetscSFBcastBegin(alltoallsf, MPIU_SCALAR, rootdata, leafdata, MPI_REPLACE));
1879566063dSJacob Faibussowitsch   PetscCall(PetscSFBcastEnd(alltoallsf, MPIU_SCALAR, rootdata, leafdata, MPI_REPLACE));
188c4762a1bSJed Brown 
189c4762a1bSJed Brown   /* FetchAndOp x to y */
1909566063dSJacob Faibussowitsch   PetscCall(PetscSFFetchAndOpBegin(alltoallsf, MPIU_SCALAR, rootdata, leafdata, leafupdate, op));
1919566063dSJacob Faibussowitsch   PetscCall(PetscSFFetchAndOpEnd(alltoallsf, MPIU_SCALAR, rootdata, leafdata, leafupdate, op));
192c4762a1bSJed Brown 
193c4762a1bSJed Brown   /* View roots (x) and leafupdate (y2). Since this is an alltoall graph, each root has only one leaf.
194c4762a1bSJed Brown      So, leafupdate = rootdata = 1+rank+size*i, i=0..size-1; and rootdata += leafdata, i.e., rootdata = [2,2*N]
195c4762a1bSJed Brown    */
1969566063dSJacob Faibussowitsch   PetscCall(VecCreateMPIWithArray(PETSC_COMM_WORLD, 1, nleaves, PETSC_DECIDE, leafupdate, &gy2));
1979566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetName((PetscObject)x, "rootdata"));
1989566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetName((PetscObject)gy2, "leafupdate"));
199c4762a1bSJed Brown 
2009566063dSJacob Faibussowitsch   PetscCall(VecView(x, PETSC_VIEWER_STDOUT_WORLD));
2019566063dSJacob Faibussowitsch   PetscCall(VecView(gy2, PETSC_VIEWER_STDOUT_WORLD));
2029566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&gy2));
203c4762a1bSJed Brown 
2049566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(y2, &leafupdate));
2059566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&y2));
206c4762a1bSJed Brown 
2079566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(y, &leafdata));
2089566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&y));
209c4762a1bSJed Brown 
2109566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(x, &rootdata));
2119566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&x));
212c4762a1bSJed Brown 
2139566063dSJacob Faibussowitsch   PetscCall(PetscSFDestroy(&alltoallsf));
214c4762a1bSJed Brown 
2159566063dSJacob Faibussowitsch   PetscCall(PetscFinalize());
216b122ec5aSJacob Faibussowitsch   return 0;
217c4762a1bSJed Brown }
218c4762a1bSJed Brown 
219c4762a1bSJed Brown /*TEST
220c4762a1bSJed Brown 
221c4762a1bSJed Brown    test:
222c4762a1bSJed Brown       # N=10 is divisible by nsize, to trigger Allgather/Gather in SF
223f424265bSStefano Zampini       #MPI_Sendrecv_replace is broken with 20210400300
2240f85934cSJunchao Zhang       requires: !defined(PETSC_HAVE_I_MPI)
225c4762a1bSJed Brown       nsize: 2
226c4762a1bSJed Brown       args: -op replace
227c4762a1bSJed Brown 
228c4762a1bSJed Brown    test:
229c4762a1bSJed Brown       suffix: 2
230c4762a1bSJed Brown       nsize: 2
231c4762a1bSJed Brown       args: -op sum
232c4762a1bSJed Brown 
233c4762a1bSJed Brown    # N=10 is not divisible by nsize, to trigger Allgatherv/Gatherv in SF
234c4762a1bSJed Brown    test:
235f424265bSStefano Zampini       #MPI_Sendrecv_replace is broken with 20210400300
2360f85934cSJunchao Zhang       requires: !defined(PETSC_HAVE_I_MPI)
237c4762a1bSJed Brown       suffix: 3
238c4762a1bSJed Brown       nsize: 3
239c4762a1bSJed Brown       args: -op replace
240c4762a1bSJed Brown 
241c4762a1bSJed Brown    test:
242c4762a1bSJed Brown       suffix: 4
243c4762a1bSJed Brown       nsize: 3
244c4762a1bSJed Brown       args: -op sum
245c4762a1bSJed Brown 
246c4762a1bSJed Brown TEST*/
247