xref: /petsc/src/vec/is/sf/tests/ex3.c (revision b122ec5aa1bd4469eb4e0673542fb7de3f411254)
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>
7c4762a1bSJed Brown int main(int argc,char **argv)
8c4762a1bSJed Brown {
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 
20*b122ec5aSJacob Faibussowitsch   CHKERRQ(PetscInitialize(&argc,&argv,(char*)0,help));
215f80ce2aSJacob Faibussowitsch   CHKERRMPI(MPI_Comm_size(PETSC_COMM_WORLD,&size));
225f80ce2aSJacob Faibussowitsch   CHKERRMPI(MPI_Comm_rank(PETSC_COMM_WORLD,&rank));
23c4762a1bSJed Brown 
245f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscOptionsGetString(NULL,NULL,"-op",opname,sizeof(opname),&flag));
255f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscStrcmp(opname,"replace",&isreplace));
265f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscStrcmp(opname,"sum",&issum));
27c4762a1bSJed Brown 
2883df288dSJunchao Zhang   if (isreplace)  {op = MPI_REPLACE; mpiopname = "MPI_REPLACE";}
29c4762a1bSJed Brown   else if (issum) {op = MPIU_SUM;     mpiopname = "MPI_SUM";}
3098921bdaSJacob Faibussowitsch   else SETERRQ(PETSC_COMM_WORLD,PETSC_ERR_ARG_WRONG,"Unsupported argument (%s) to -op, which must be 'replace' or 'sum'",opname);
31c4762a1bSJed Brown 
325f80ce2aSJacob Faibussowitsch   CHKERRQ(VecCreate(PETSC_COMM_WORLD,&x));
335f80ce2aSJacob Faibussowitsch   CHKERRQ(VecSetFromOptions(x));
345f80ce2aSJacob Faibussowitsch   CHKERRQ(VecSetSizes(x,PETSC_DECIDE,N));
35c4762a1bSJed Brown 
36c4762a1bSJed Brown   /*-------------------------------------*/
37c4762a1bSJed Brown   /*       PETSCSF_PATTERN_GATHER        */
38c4762a1bSJed Brown   /*-------------------------------------*/
39c4762a1bSJed Brown 
40c4762a1bSJed Brown   /* set MPI vec x to [1, 2, .., N] */
415f80ce2aSJacob Faibussowitsch   CHKERRQ(VecGetOwnershipRange(x,&low,&high));
425f80ce2aSJacob Faibussowitsch   for (i=low; i<high; i++) CHKERRQ(VecSetValue(x,i,(PetscScalar)i+1.0,INSERT_VALUES));
435f80ce2aSJacob Faibussowitsch   CHKERRQ(VecAssemblyBegin(x));
445f80ce2aSJacob Faibussowitsch   CHKERRQ(VecAssemblyEnd(x));
45c4762a1bSJed Brown 
46c4762a1bSJed Brown   /* Create the gather SF */
475f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscPrintf(PETSC_COMM_WORLD,"\nTesting PetscSFFetchAndOp on a PETSCSF_PATTERN_GATHER graph with op = %s\n",mpiopname));
485f80ce2aSJacob Faibussowitsch   CHKERRQ(VecGetLayout(x,&layout));
495f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSFCreate(PETSC_COMM_WORLD,&gathersf));
505f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSFSetGraphWithPattern(gathersf,layout,PETSCSF_PATTERN_GATHER));
51c4762a1bSJed Brown 
52c4762a1bSJed Brown   /* Create the leaf vector y (seq vector) and its duplicate y2 working as leafupdate */
535f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSFGetGraph(gathersf,NULL,&nleaves,NULL,NULL));
545f80ce2aSJacob Faibussowitsch   CHKERRQ(VecCreateSeq(PETSC_COMM_SELF,nleaves,&y));
555f80ce2aSJacob Faibussowitsch   CHKERRQ(VecDuplicate(y,&y2));
56c4762a1bSJed Brown 
575f80ce2aSJacob Faibussowitsch   CHKERRQ(VecGetArray(x,&rootdata));
585f80ce2aSJacob Faibussowitsch   CHKERRQ(VecGetArray(y,&leafdata));
595f80ce2aSJacob Faibussowitsch   CHKERRQ(VecGetArray(y2,&leafupdate));
60c4762a1bSJed Brown 
61c4762a1bSJed Brown   /* Bcast x to y,to initialize y = [1,N], then scale y to make leafupdate = y = [2,2*N] */
625f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSFBcastBegin(gathersf,MPIU_SCALAR,rootdata,leafdata,MPI_REPLACE));
635f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSFBcastEnd(gathersf,MPIU_SCALAR,rootdata,leafdata,MPI_REPLACE));
645f80ce2aSJacob Faibussowitsch   CHKERRQ(VecRestoreArray(y,&leafdata));
655f80ce2aSJacob Faibussowitsch   CHKERRQ(VecScale(y,2));
665f80ce2aSJacob Faibussowitsch   CHKERRQ(VecGetArray(y,&leafdata));
67c4762a1bSJed Brown 
68c4762a1bSJed Brown   /* FetchAndOp x to y */
695f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSFFetchAndOpBegin(gathersf,MPIU_SCALAR,rootdata,leafdata,leafupdate,op));
705f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSFFetchAndOpEnd(gathersf,MPIU_SCALAR,rootdata,leafdata,leafupdate,op));
71c4762a1bSJed Brown 
72c4762a1bSJed 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] */
735f80ce2aSJacob Faibussowitsch   CHKERRQ(VecCreateMPIWithArray(PETSC_COMM_WORLD,1,nleaves,PETSC_DECIDE,leafupdate,&gy2));
745f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectSetName((PetscObject)x,"rootdata"));
755f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectSetName((PetscObject)gy2,"leafupdate"));
76c4762a1bSJed Brown 
775f80ce2aSJacob Faibussowitsch   CHKERRQ(VecView(x,PETSC_VIEWER_STDOUT_WORLD));
785f80ce2aSJacob Faibussowitsch   CHKERRQ(VecView(gy2,PETSC_VIEWER_STDOUT_WORLD));
795f80ce2aSJacob Faibussowitsch   CHKERRQ(VecDestroy(&gy2));
80c4762a1bSJed Brown 
815f80ce2aSJacob Faibussowitsch   CHKERRQ(VecRestoreArray(y2,&leafupdate));
825f80ce2aSJacob Faibussowitsch   CHKERRQ(VecDestroy(&y2));
83c4762a1bSJed Brown 
845f80ce2aSJacob Faibussowitsch   CHKERRQ(VecRestoreArray(y,&leafdata));
855f80ce2aSJacob Faibussowitsch   CHKERRQ(VecDestroy(&y));
86c4762a1bSJed Brown 
875f80ce2aSJacob Faibussowitsch   CHKERRQ(VecRestoreArray(x,&rootdata));
885f80ce2aSJacob Faibussowitsch   /* CHKERRQ(VecDestroy(&x)); */ /* We will reuse x in ALLGATHER, so do not destroy it */
89c4762a1bSJed Brown 
905f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSFDestroy(&gathersf));
91c4762a1bSJed Brown 
92c4762a1bSJed Brown   /*-------------------------------------*/
93c4762a1bSJed Brown   /*       PETSCSF_PATTERN_ALLGATHER     */
94c4762a1bSJed Brown   /*-------------------------------------*/
95c4762a1bSJed Brown 
96c4762a1bSJed Brown   /* set MPI vec x to [1, 2, .., N] */
975f80ce2aSJacob Faibussowitsch   for (i=low; i<high; i++) CHKERRQ(VecSetValue(x,i,(PetscScalar)i+1.0,INSERT_VALUES));
985f80ce2aSJacob Faibussowitsch   CHKERRQ(VecAssemblyBegin(x));
995f80ce2aSJacob Faibussowitsch   CHKERRQ(VecAssemblyEnd(x));
100c4762a1bSJed Brown 
101c4762a1bSJed Brown   /* Create the allgather SF */
1025f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscPrintf(PETSC_COMM_WORLD,"\nTesting PetscSFFetchAndOp on a PETSCSF_PATTERN_ALLGATHER graph with op = %s\n",mpiopname));
1035f80ce2aSJacob Faibussowitsch   CHKERRQ(VecGetLayout(x,&layout));
1045f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSFCreate(PETSC_COMM_WORLD,&allgathersf));
1055f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSFSetGraphWithPattern(allgathersf,layout,PETSCSF_PATTERN_ALLGATHER));
106c4762a1bSJed Brown 
107c4762a1bSJed Brown   /* Create the leaf vector y (seq vector) and its duplicate y2 working as leafupdate */
1085f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSFGetGraph(allgathersf,NULL,&nleaves,NULL,NULL));
1095f80ce2aSJacob Faibussowitsch   CHKERRQ(VecCreateSeq(PETSC_COMM_SELF,nleaves,&y));
1105f80ce2aSJacob Faibussowitsch   CHKERRQ(VecDuplicate(y,&y2));
111c4762a1bSJed Brown 
1125f80ce2aSJacob Faibussowitsch   CHKERRQ(VecGetArray(x,&rootdata));
1135f80ce2aSJacob Faibussowitsch   CHKERRQ(VecGetArray(y,&leafdata));
1145f80ce2aSJacob Faibussowitsch   CHKERRQ(VecGetArray(y2,&leafupdate));
115c4762a1bSJed Brown 
116c4762a1bSJed Brown   /* Bcast x to y, to initialize y = [1,N], then scale y to make leafupdate = y = [2,2*N] */
1175f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSFBcastBegin(allgathersf,MPIU_SCALAR,rootdata,leafdata,MPI_REPLACE));
1185f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSFBcastEnd(allgathersf,MPIU_SCALAR,rootdata,leafdata,MPI_REPLACE));
1195f80ce2aSJacob Faibussowitsch   CHKERRQ(VecRestoreArray(y,&leafdata));
1205f80ce2aSJacob Faibussowitsch   CHKERRQ(VecScale(y,2));
1215f80ce2aSJacob Faibussowitsch   CHKERRQ(VecGetArray(y,&leafdata));
122c4762a1bSJed Brown 
123c4762a1bSJed Brown   /* FetchAndOp x to y */
1245f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSFFetchAndOpBegin(allgathersf,MPIU_SCALAR,rootdata,leafdata,leafupdate,op));
1255f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSFFetchAndOpEnd(allgathersf,MPIU_SCALAR,rootdata,leafdata,leafupdate,op));
126c4762a1bSJed Brown 
127c4762a1bSJed Brown   /* View roots (x) and leafupdate (y2). Since this is an allgather graph, we have (suppose ranks get updates in ascending order)
128c4762a1bSJed Brown      rank 0: leafupdate = rootdata = [1,N],   rootdata += leafdata = [3,3*N]
129c4762a1bSJed Brown      rank 1: leafupdate = rootdata = [3,3*N], rootdata += leafdata = [5,5*N]
130c4762a1bSJed Brown      rank 2: leafupdate = rootdata = [5,5*N], rootdata += leafdata = [7,7*N]
131c4762a1bSJed Brown      ...
132c4762a1bSJed Brown    */
1335f80ce2aSJacob Faibussowitsch   CHKERRQ(VecCreateMPIWithArray(PETSC_COMM_WORLD,1,nleaves,PETSC_DECIDE,leafupdate,&gy2));
1345f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectSetName((PetscObject)x,"rootdata"));
1355f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectSetName((PetscObject)gy2,"leafupdate"));
136c4762a1bSJed Brown 
1375f80ce2aSJacob Faibussowitsch   CHKERRQ(VecView(x,PETSC_VIEWER_STDOUT_WORLD));
1385f80ce2aSJacob Faibussowitsch   CHKERRQ(VecView(gy2,PETSC_VIEWER_STDOUT_WORLD));
1395f80ce2aSJacob Faibussowitsch   CHKERRQ(VecDestroy(&gy2));
140c4762a1bSJed Brown 
1415f80ce2aSJacob Faibussowitsch   CHKERRQ(VecRestoreArray(y2,&leafupdate));
1425f80ce2aSJacob Faibussowitsch   CHKERRQ(VecDestroy(&y2));
143c4762a1bSJed Brown 
1445f80ce2aSJacob Faibussowitsch   CHKERRQ(VecRestoreArray(y,&leafdata));
1455f80ce2aSJacob Faibussowitsch   CHKERRQ(VecDestroy(&y));
146c4762a1bSJed Brown 
1475f80ce2aSJacob Faibussowitsch   CHKERRQ(VecRestoreArray(x,&rootdata));
1485f80ce2aSJacob Faibussowitsch   CHKERRQ(VecDestroy(&x)); /* We won't reuse x in ALLGATHER, so destroy it */
149c4762a1bSJed Brown 
1505f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSFDestroy(&allgathersf));
151c4762a1bSJed Brown 
152c4762a1bSJed Brown   /*-------------------------------------*/
153c4762a1bSJed Brown   /*       PETSCSF_PATTERN_ALLTOALL     */
154c4762a1bSJed Brown   /*-------------------------------------*/
155c4762a1bSJed Brown 
1565f80ce2aSJacob Faibussowitsch   CHKERRQ(VecCreate(PETSC_COMM_WORLD,&x));
1575f80ce2aSJacob Faibussowitsch   CHKERRQ(VecSetFromOptions(x));
1585f80ce2aSJacob Faibussowitsch   CHKERRQ(VecSetSizes(x,size,PETSC_DECIDE));
159c4762a1bSJed Brown 
160c4762a1bSJed Brown   /* set MPI vec x to [1, 2, .., size^2] */
1615f80ce2aSJacob Faibussowitsch   CHKERRQ(VecGetOwnershipRange(x,&low,&high));
1625f80ce2aSJacob Faibussowitsch   for (i=low; i<high; i++) CHKERRQ(VecSetValue(x,i,(PetscScalar)i+1.0,INSERT_VALUES));
1635f80ce2aSJacob Faibussowitsch   CHKERRQ(VecAssemblyBegin(x));
1645f80ce2aSJacob Faibussowitsch   CHKERRQ(VecAssemblyEnd(x));
165c4762a1bSJed Brown 
166c4762a1bSJed Brown /* Create the alltoall SF */
1675f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscPrintf(PETSC_COMM_WORLD,"\nTesting PetscSFFetchAndOp on a PETSCSF_PATTERN_ALLTOALL graph with op = %s\n",mpiopname));
1685f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSFCreate(PETSC_COMM_WORLD,&alltoallsf));
1695f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSFSetGraphWithPattern(alltoallsf,NULL/*insignificant*/,PETSCSF_PATTERN_ALLTOALL));
170c4762a1bSJed Brown 
171c4762a1bSJed Brown   /* Create the leaf vector y (seq vector) and its duplicate y2 working as leafupdate */
1725f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSFGetGraph(alltoallsf,NULL,&nleaves,NULL,NULL));
1735f80ce2aSJacob Faibussowitsch   CHKERRQ(VecCreateSeq(PETSC_COMM_SELF,nleaves,&y));
1745f80ce2aSJacob Faibussowitsch   CHKERRQ(VecDuplicate(y,&y2));
175c4762a1bSJed Brown 
1765f80ce2aSJacob Faibussowitsch   CHKERRQ(VecGetArray(x,&rootdata));
1775f80ce2aSJacob Faibussowitsch   CHKERRQ(VecGetArray(y,&leafdata));
1785f80ce2aSJacob Faibussowitsch   CHKERRQ(VecGetArray(y2,&leafupdate));
179c4762a1bSJed Brown 
180c4762a1bSJed Brown   /* Bcast x to y, to initialize y = 1+rank+size*i, with i=0..size-1 */
1815f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSFBcastBegin(alltoallsf,MPIU_SCALAR,rootdata,leafdata,MPI_REPLACE));
1825f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSFBcastEnd(alltoallsf,MPIU_SCALAR,rootdata,leafdata,MPI_REPLACE));
183c4762a1bSJed Brown 
184c4762a1bSJed Brown   /* FetchAndOp x to y */
1855f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSFFetchAndOpBegin(alltoallsf,MPIU_SCALAR,rootdata,leafdata,leafupdate,op));
1865f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSFFetchAndOpEnd(alltoallsf,MPIU_SCALAR,rootdata,leafdata,leafupdate,op));
187c4762a1bSJed Brown 
188c4762a1bSJed Brown   /* View roots (x) and leafupdate (y2). Since this is an alltoall graph, each root has only one leaf.
189c4762a1bSJed Brown      So, leafupdate = rootdata = 1+rank+size*i, i=0..size-1; and rootdata += leafdata, i.e., rootdata = [2,2*N]
190c4762a1bSJed Brown    */
1915f80ce2aSJacob Faibussowitsch   CHKERRQ(VecCreateMPIWithArray(PETSC_COMM_WORLD,1,nleaves,PETSC_DECIDE,leafupdate,&gy2));
1925f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectSetName((PetscObject)x,"rootdata"));
1935f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectSetName((PetscObject)gy2,"leafupdate"));
194c4762a1bSJed Brown 
1955f80ce2aSJacob Faibussowitsch   CHKERRQ(VecView(x,PETSC_VIEWER_STDOUT_WORLD));
1965f80ce2aSJacob Faibussowitsch   CHKERRQ(VecView(gy2,PETSC_VIEWER_STDOUT_WORLD));
1975f80ce2aSJacob Faibussowitsch   CHKERRQ(VecDestroy(&gy2));
198c4762a1bSJed Brown 
1995f80ce2aSJacob Faibussowitsch   CHKERRQ(VecRestoreArray(y2,&leafupdate));
2005f80ce2aSJacob Faibussowitsch   CHKERRQ(VecDestroy(&y2));
201c4762a1bSJed Brown 
2025f80ce2aSJacob Faibussowitsch   CHKERRQ(VecRestoreArray(y,&leafdata));
2035f80ce2aSJacob Faibussowitsch   CHKERRQ(VecDestroy(&y));
204c4762a1bSJed Brown 
2055f80ce2aSJacob Faibussowitsch   CHKERRQ(VecRestoreArray(x,&rootdata));
2065f80ce2aSJacob Faibussowitsch   CHKERRQ(VecDestroy(&x));
207c4762a1bSJed Brown 
2085f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSFDestroy(&alltoallsf));
209c4762a1bSJed Brown 
210*b122ec5aSJacob Faibussowitsch   CHKERRQ(PetscFinalize());
211*b122ec5aSJacob Faibussowitsch   return 0;
212c4762a1bSJed Brown }
213c4762a1bSJed Brown 
214c4762a1bSJed Brown /*TEST
215c4762a1bSJed Brown 
216c4762a1bSJed Brown    test:
217c4762a1bSJed Brown       # N=10 is divisible by nsize, to trigger Allgather/Gather in SF
218f424265bSStefano Zampini       #MPI_Sendrecv_replace is broken with 20210400300
219f424265bSStefano Zampini       requires: !defined(PETSC_HAVE_I_MPI_NUMVERSION)
220c4762a1bSJed Brown       nsize: 2
221c4762a1bSJed Brown       args: -op replace
222c4762a1bSJed Brown 
223c4762a1bSJed Brown    test:
224c4762a1bSJed Brown       suffix: 2
225c4762a1bSJed Brown       nsize: 2
226c4762a1bSJed Brown       args: -op sum
227c4762a1bSJed Brown 
228c4762a1bSJed Brown    # N=10 is not divisible by nsize, to trigger Allgatherv/Gatherv in SF
229c4762a1bSJed Brown    test:
230f424265bSStefano Zampini       #MPI_Sendrecv_replace is broken with 20210400300
231f424265bSStefano Zampini       requires: !defined(PETSC_HAVE_I_MPI_NUMVERSION)
232c4762a1bSJed Brown       suffix: 3
233c4762a1bSJed Brown       nsize: 3
234c4762a1bSJed Brown       args: -op replace
235c4762a1bSJed Brown 
236c4762a1bSJed Brown    test:
237c4762a1bSJed Brown       suffix: 4
238c4762a1bSJed Brown       nsize: 3
239c4762a1bSJed Brown       args: -op sum
240c4762a1bSJed Brown 
241c4762a1bSJed Brown TEST*/
242