xref: /petsc/src/vec/is/sf/tests/ex3.c (revision 9566063d113dddea24716c546802770db7481bc0)
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*9566063dSJacob Faibussowitsch   PetscCall(PetscInitialize(&argc,&argv,(char*)0,help));
21*9566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_size(PETSC_COMM_WORLD,&size));
22*9566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(PETSC_COMM_WORLD,&rank));
23c4762a1bSJed Brown 
24*9566063dSJacob Faibussowitsch   PetscCall(PetscOptionsGetString(NULL,NULL,"-op",opname,sizeof(opname),&flag));
25*9566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp(opname,"replace",&isreplace));
26*9566063dSJacob Faibussowitsch   PetscCall(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 
32*9566063dSJacob Faibussowitsch   PetscCall(VecCreate(PETSC_COMM_WORLD,&x));
33*9566063dSJacob Faibussowitsch   PetscCall(VecSetFromOptions(x));
34*9566063dSJacob Faibussowitsch   PetscCall(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] */
41*9566063dSJacob Faibussowitsch   PetscCall(VecGetOwnershipRange(x,&low,&high));
42*9566063dSJacob Faibussowitsch   for (i=low; i<high; i++) PetscCall(VecSetValue(x,i,(PetscScalar)i+1.0,INSERT_VALUES));
43*9566063dSJacob Faibussowitsch   PetscCall(VecAssemblyBegin(x));
44*9566063dSJacob Faibussowitsch   PetscCall(VecAssemblyEnd(x));
45c4762a1bSJed Brown 
46c4762a1bSJed Brown   /* Create the gather SF */
47*9566063dSJacob Faibussowitsch   PetscCall(PetscPrintf(PETSC_COMM_WORLD,"\nTesting PetscSFFetchAndOp on a PETSCSF_PATTERN_GATHER graph with op = %s\n",mpiopname));
48*9566063dSJacob Faibussowitsch   PetscCall(VecGetLayout(x,&layout));
49*9566063dSJacob Faibussowitsch   PetscCall(PetscSFCreate(PETSC_COMM_WORLD,&gathersf));
50*9566063dSJacob Faibussowitsch   PetscCall(PetscSFSetGraphWithPattern(gathersf,layout,PETSCSF_PATTERN_GATHER));
51c4762a1bSJed Brown 
52c4762a1bSJed Brown   /* Create the leaf vector y (seq vector) and its duplicate y2 working as leafupdate */
53*9566063dSJacob Faibussowitsch   PetscCall(PetscSFGetGraph(gathersf,NULL,&nleaves,NULL,NULL));
54*9566063dSJacob Faibussowitsch   PetscCall(VecCreateSeq(PETSC_COMM_SELF,nleaves,&y));
55*9566063dSJacob Faibussowitsch   PetscCall(VecDuplicate(y,&y2));
56c4762a1bSJed Brown 
57*9566063dSJacob Faibussowitsch   PetscCall(VecGetArray(x,&rootdata));
58*9566063dSJacob Faibussowitsch   PetscCall(VecGetArray(y,&leafdata));
59*9566063dSJacob Faibussowitsch   PetscCall(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] */
62*9566063dSJacob Faibussowitsch   PetscCall(PetscSFBcastBegin(gathersf,MPIU_SCALAR,rootdata,leafdata,MPI_REPLACE));
63*9566063dSJacob Faibussowitsch   PetscCall(PetscSFBcastEnd(gathersf,MPIU_SCALAR,rootdata,leafdata,MPI_REPLACE));
64*9566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(y,&leafdata));
65*9566063dSJacob Faibussowitsch   PetscCall(VecScale(y,2));
66*9566063dSJacob Faibussowitsch   PetscCall(VecGetArray(y,&leafdata));
67c4762a1bSJed Brown 
68c4762a1bSJed Brown   /* FetchAndOp x to y */
69*9566063dSJacob Faibussowitsch   PetscCall(PetscSFFetchAndOpBegin(gathersf,MPIU_SCALAR,rootdata,leafdata,leafupdate,op));
70*9566063dSJacob Faibussowitsch   PetscCall(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] */
73*9566063dSJacob Faibussowitsch   PetscCall(VecCreateMPIWithArray(PETSC_COMM_WORLD,1,nleaves,PETSC_DECIDE,leafupdate,&gy2));
74*9566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetName((PetscObject)x,"rootdata"));
75*9566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetName((PetscObject)gy2,"leafupdate"));
76c4762a1bSJed Brown 
77*9566063dSJacob Faibussowitsch   PetscCall(VecView(x,PETSC_VIEWER_STDOUT_WORLD));
78*9566063dSJacob Faibussowitsch   PetscCall(VecView(gy2,PETSC_VIEWER_STDOUT_WORLD));
79*9566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&gy2));
80c4762a1bSJed Brown 
81*9566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(y2,&leafupdate));
82*9566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&y2));
83c4762a1bSJed Brown 
84*9566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(y,&leafdata));
85*9566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&y));
86c4762a1bSJed Brown 
87*9566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(x,&rootdata));
88*9566063dSJacob Faibussowitsch   /* PetscCall(VecDestroy(&x)); */ /* We will reuse x in ALLGATHER, so do not destroy it */
89c4762a1bSJed Brown 
90*9566063dSJacob Faibussowitsch   PetscCall(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] */
97*9566063dSJacob Faibussowitsch   for (i=low; i<high; i++) PetscCall(VecSetValue(x,i,(PetscScalar)i+1.0,INSERT_VALUES));
98*9566063dSJacob Faibussowitsch   PetscCall(VecAssemblyBegin(x));
99*9566063dSJacob Faibussowitsch   PetscCall(VecAssemblyEnd(x));
100c4762a1bSJed Brown 
101c4762a1bSJed Brown   /* Create the allgather SF */
102*9566063dSJacob Faibussowitsch   PetscCall(PetscPrintf(PETSC_COMM_WORLD,"\nTesting PetscSFFetchAndOp on a PETSCSF_PATTERN_ALLGATHER graph with op = %s\n",mpiopname));
103*9566063dSJacob Faibussowitsch   PetscCall(VecGetLayout(x,&layout));
104*9566063dSJacob Faibussowitsch   PetscCall(PetscSFCreate(PETSC_COMM_WORLD,&allgathersf));
105*9566063dSJacob Faibussowitsch   PetscCall(PetscSFSetGraphWithPattern(allgathersf,layout,PETSCSF_PATTERN_ALLGATHER));
106c4762a1bSJed Brown 
107c4762a1bSJed Brown   /* Create the leaf vector y (seq vector) and its duplicate y2 working as leafupdate */
108*9566063dSJacob Faibussowitsch   PetscCall(PetscSFGetGraph(allgathersf,NULL,&nleaves,NULL,NULL));
109*9566063dSJacob Faibussowitsch   PetscCall(VecCreateSeq(PETSC_COMM_SELF,nleaves,&y));
110*9566063dSJacob Faibussowitsch   PetscCall(VecDuplicate(y,&y2));
111c4762a1bSJed Brown 
112*9566063dSJacob Faibussowitsch   PetscCall(VecGetArray(x,&rootdata));
113*9566063dSJacob Faibussowitsch   PetscCall(VecGetArray(y,&leafdata));
114*9566063dSJacob Faibussowitsch   PetscCall(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] */
117*9566063dSJacob Faibussowitsch   PetscCall(PetscSFBcastBegin(allgathersf,MPIU_SCALAR,rootdata,leafdata,MPI_REPLACE));
118*9566063dSJacob Faibussowitsch   PetscCall(PetscSFBcastEnd(allgathersf,MPIU_SCALAR,rootdata,leafdata,MPI_REPLACE));
119*9566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(y,&leafdata));
120*9566063dSJacob Faibussowitsch   PetscCall(VecScale(y,2));
121*9566063dSJacob Faibussowitsch   PetscCall(VecGetArray(y,&leafdata));
122c4762a1bSJed Brown 
123c4762a1bSJed Brown   /* FetchAndOp x to y */
124*9566063dSJacob Faibussowitsch   PetscCall(PetscSFFetchAndOpBegin(allgathersf,MPIU_SCALAR,rootdata,leafdata,leafupdate,op));
125*9566063dSJacob Faibussowitsch   PetscCall(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    */
133*9566063dSJacob Faibussowitsch   PetscCall(VecCreateMPIWithArray(PETSC_COMM_WORLD,1,nleaves,PETSC_DECIDE,leafupdate,&gy2));
134*9566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetName((PetscObject)x,"rootdata"));
135*9566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetName((PetscObject)gy2,"leafupdate"));
136c4762a1bSJed Brown 
137*9566063dSJacob Faibussowitsch   PetscCall(VecView(x,PETSC_VIEWER_STDOUT_WORLD));
138*9566063dSJacob Faibussowitsch   PetscCall(VecView(gy2,PETSC_VIEWER_STDOUT_WORLD));
139*9566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&gy2));
140c4762a1bSJed Brown 
141*9566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(y2,&leafupdate));
142*9566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&y2));
143c4762a1bSJed Brown 
144*9566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(y,&leafdata));
145*9566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&y));
146c4762a1bSJed Brown 
147*9566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(x,&rootdata));
148*9566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&x)); /* We won't reuse x in ALLGATHER, so destroy it */
149c4762a1bSJed Brown 
150*9566063dSJacob Faibussowitsch   PetscCall(PetscSFDestroy(&allgathersf));
151c4762a1bSJed Brown 
152c4762a1bSJed Brown   /*-------------------------------------*/
153c4762a1bSJed Brown   /*       PETSCSF_PATTERN_ALLTOALL     */
154c4762a1bSJed Brown   /*-------------------------------------*/
155c4762a1bSJed Brown 
156*9566063dSJacob Faibussowitsch   PetscCall(VecCreate(PETSC_COMM_WORLD,&x));
157*9566063dSJacob Faibussowitsch   PetscCall(VecSetFromOptions(x));
158*9566063dSJacob Faibussowitsch   PetscCall(VecSetSizes(x,size,PETSC_DECIDE));
159c4762a1bSJed Brown 
160c4762a1bSJed Brown   /* set MPI vec x to [1, 2, .., size^2] */
161*9566063dSJacob Faibussowitsch   PetscCall(VecGetOwnershipRange(x,&low,&high));
162*9566063dSJacob Faibussowitsch   for (i=low; i<high; i++) PetscCall(VecSetValue(x,i,(PetscScalar)i+1.0,INSERT_VALUES));
163*9566063dSJacob Faibussowitsch   PetscCall(VecAssemblyBegin(x));
164*9566063dSJacob Faibussowitsch   PetscCall(VecAssemblyEnd(x));
165c4762a1bSJed Brown 
166c4762a1bSJed Brown /* Create the alltoall SF */
167*9566063dSJacob Faibussowitsch   PetscCall(PetscPrintf(PETSC_COMM_WORLD,"\nTesting PetscSFFetchAndOp on a PETSCSF_PATTERN_ALLTOALL graph with op = %s\n",mpiopname));
168*9566063dSJacob Faibussowitsch   PetscCall(PetscSFCreate(PETSC_COMM_WORLD,&alltoallsf));
169*9566063dSJacob Faibussowitsch   PetscCall(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 */
172*9566063dSJacob Faibussowitsch   PetscCall(PetscSFGetGraph(alltoallsf,NULL,&nleaves,NULL,NULL));
173*9566063dSJacob Faibussowitsch   PetscCall(VecCreateSeq(PETSC_COMM_SELF,nleaves,&y));
174*9566063dSJacob Faibussowitsch   PetscCall(VecDuplicate(y,&y2));
175c4762a1bSJed Brown 
176*9566063dSJacob Faibussowitsch   PetscCall(VecGetArray(x,&rootdata));
177*9566063dSJacob Faibussowitsch   PetscCall(VecGetArray(y,&leafdata));
178*9566063dSJacob Faibussowitsch   PetscCall(VecGetArray(y2,&leafupdate));
179c4762a1bSJed Brown 
180c4762a1bSJed Brown   /* Bcast x to y, to initialize y = 1+rank+size*i, with i=0..size-1 */
181*9566063dSJacob Faibussowitsch   PetscCall(PetscSFBcastBegin(alltoallsf,MPIU_SCALAR,rootdata,leafdata,MPI_REPLACE));
182*9566063dSJacob Faibussowitsch   PetscCall(PetscSFBcastEnd(alltoallsf,MPIU_SCALAR,rootdata,leafdata,MPI_REPLACE));
183c4762a1bSJed Brown 
184c4762a1bSJed Brown   /* FetchAndOp x to y */
185*9566063dSJacob Faibussowitsch   PetscCall(PetscSFFetchAndOpBegin(alltoallsf,MPIU_SCALAR,rootdata,leafdata,leafupdate,op));
186*9566063dSJacob Faibussowitsch   PetscCall(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    */
191*9566063dSJacob Faibussowitsch   PetscCall(VecCreateMPIWithArray(PETSC_COMM_WORLD,1,nleaves,PETSC_DECIDE,leafupdate,&gy2));
192*9566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetName((PetscObject)x,"rootdata"));
193*9566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetName((PetscObject)gy2,"leafupdate"));
194c4762a1bSJed Brown 
195*9566063dSJacob Faibussowitsch   PetscCall(VecView(x,PETSC_VIEWER_STDOUT_WORLD));
196*9566063dSJacob Faibussowitsch   PetscCall(VecView(gy2,PETSC_VIEWER_STDOUT_WORLD));
197*9566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&gy2));
198c4762a1bSJed Brown 
199*9566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(y2,&leafupdate));
200*9566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&y2));
201c4762a1bSJed Brown 
202*9566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(y,&leafdata));
203*9566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&y));
204c4762a1bSJed Brown 
205*9566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(x,&rootdata));
206*9566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&x));
207c4762a1bSJed Brown 
208*9566063dSJacob Faibussowitsch   PetscCall(PetscSFDestroy(&alltoallsf));
209c4762a1bSJed Brown 
210*9566063dSJacob Faibussowitsch   PetscCall(PetscFinalize());
211b122ec5aSJacob 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