xref: /petsc/src/vec/is/sf/tests/ex3.c (revision c4762a1b19cd2af06abeed90e8f9d34fb975dd94)
1*c4762a1bSJed Brown static char help[]= "Test PetscSFFetchAndOp on patterned SF graphs. PetscSFFetchAndOp internally uses PetscSFBcastAndOp \n\
2*c4762a1bSJed Brown  and PetscSFReduce. So it is a good test to see if they all work for patterned graphs.\n\
3*c4762a1bSJed Brown  Run with ./prog -op [replace | sum]\n\n";
4*c4762a1bSJed Brown 
5*c4762a1bSJed Brown #include <petscvec.h>
6*c4762a1bSJed Brown #include <petscsf.h>
7*c4762a1bSJed Brown int main(int argc,char **argv)
8*c4762a1bSJed Brown {
9*c4762a1bSJed Brown   PetscErrorCode ierr;
10*c4762a1bSJed Brown   PetscInt       i,N=10,low,high,nleaves;
11*c4762a1bSJed Brown   PetscMPIInt    size,rank;
12*c4762a1bSJed Brown   Vec            x,y,y2,gy2;
13*c4762a1bSJed Brown   PetscScalar    *rootdata,*leafdata,*leafupdate;
14*c4762a1bSJed Brown   PetscLayout    layout;
15*c4762a1bSJed Brown   PetscSF        gathersf,allgathersf,alltoallsf;
16*c4762a1bSJed Brown   MPI_Op         op=MPI_SUM;
17*c4762a1bSJed Brown   char           opname[64];
18*c4762a1bSJed Brown   const char     *mpiopname;
19*c4762a1bSJed Brown   PetscBool      flag,isreplace,issum;
20*c4762a1bSJed Brown 
21*c4762a1bSJed Brown   ierr = PetscInitialize(&argc,&argv,(char*)0,help);if (ierr) return ierr;
22*c4762a1bSJed Brown   ierr = MPI_Comm_size(PETSC_COMM_WORLD,&size);CHKERRQ(ierr);
23*c4762a1bSJed Brown   ierr = MPI_Comm_rank(PETSC_COMM_WORLD,&rank);CHKERRQ(ierr);
24*c4762a1bSJed Brown 
25*c4762a1bSJed Brown   ierr = PetscOptionsGetString(NULL,NULL,"-op",opname,64,&flag);CHKERRQ(ierr);
26*c4762a1bSJed Brown   ierr = PetscStrcmp(opname,"replace",&isreplace);CHKERRQ(ierr);
27*c4762a1bSJed Brown   ierr = PetscStrcmp(opname,"sum",&issum);CHKERRQ(ierr);
28*c4762a1bSJed Brown 
29*c4762a1bSJed Brown   if (isreplace)  {op = MPIU_REPLACE; mpiopname = "MPI_REPLACE";}
30*c4762a1bSJed Brown   else if (issum) {op = MPIU_SUM;     mpiopname = "MPI_SUM";}
31*c4762a1bSJed Brown   else SETERRQ1(PETSC_COMM_WORLD,PETSC_ERR_ARG_WRONG,"Unsupported argument (%s) to -op, which must be 'replace' or 'sum'",opname);
32*c4762a1bSJed Brown 
33*c4762a1bSJed Brown   ierr = VecCreate(PETSC_COMM_WORLD,&x);CHKERRQ(ierr);
34*c4762a1bSJed Brown   ierr = VecSetFromOptions(x);CHKERRQ(ierr);
35*c4762a1bSJed Brown   ierr = VecSetSizes(x,PETSC_DECIDE,N);CHKERRQ(ierr);
36*c4762a1bSJed Brown 
37*c4762a1bSJed Brown   /*-------------------------------------*/
38*c4762a1bSJed Brown   /*       PETSCSF_PATTERN_GATHER        */
39*c4762a1bSJed Brown   /*-------------------------------------*/
40*c4762a1bSJed Brown 
41*c4762a1bSJed Brown   /* set MPI vec x to [1, 2, .., N] */
42*c4762a1bSJed Brown   ierr = VecGetOwnershipRange(x,&low,&high);CHKERRQ(ierr);
43*c4762a1bSJed Brown   for (i=low; i<high; i++) {ierr = VecSetValue(x,i,(PetscScalar)i+1.0,INSERT_VALUES);CHKERRQ(ierr);}
44*c4762a1bSJed Brown   ierr = VecAssemblyBegin(x);CHKERRQ(ierr);
45*c4762a1bSJed Brown   ierr = VecAssemblyEnd(x);CHKERRQ(ierr);
46*c4762a1bSJed Brown 
47*c4762a1bSJed Brown   /* Create the gather SF */
48*c4762a1bSJed Brown   ierr = PetscPrintf(PETSC_COMM_WORLD,"\nTesting PetscSFFetchAndOp on a PETSCSF_PATTERN_GATHER graph with op = %s\n",mpiopname);CHKERRQ(ierr);
49*c4762a1bSJed Brown   ierr = VecGetLayout(x,&layout);CHKERRQ(ierr);
50*c4762a1bSJed Brown   ierr = PetscSFCreate(PETSC_COMM_WORLD,&gathersf);CHKERRQ(ierr);
51*c4762a1bSJed Brown   ierr = PetscSFSetGraphWithPattern(gathersf,layout,PETSCSF_PATTERN_GATHER);CHKERRQ(ierr);
52*c4762a1bSJed Brown 
53*c4762a1bSJed Brown   /* Create the leaf vector y (seq vector) and its duplicate y2 working as leafupdate */
54*c4762a1bSJed Brown   ierr = PetscSFGetGraph(gathersf,NULL,&nleaves,NULL,NULL);CHKERRQ(ierr);
55*c4762a1bSJed Brown   ierr = VecCreateSeq(PETSC_COMM_SELF,nleaves,&y);CHKERRQ(ierr);
56*c4762a1bSJed Brown   ierr = VecDuplicate(y,&y2);CHKERRQ(ierr);
57*c4762a1bSJed Brown 
58*c4762a1bSJed Brown   ierr = VecGetArray(x,&rootdata);CHKERRQ(ierr);
59*c4762a1bSJed Brown   ierr = VecGetArray(y,&leafdata);CHKERRQ(ierr);
60*c4762a1bSJed Brown   ierr = VecGetArray(y2,&leafupdate);CHKERRQ(ierr);
61*c4762a1bSJed Brown 
62*c4762a1bSJed Brown   /* Bcast x to y,to initialize y = [1,N], then scale y to make leafupdate = y = [2,2*N] */
63*c4762a1bSJed Brown   ierr = PetscSFBcastAndOpBegin(gathersf,MPIU_SCALAR,rootdata,leafdata,MPIU_REPLACE);CHKERRQ(ierr);
64*c4762a1bSJed Brown   ierr = PetscSFBcastAndOpEnd(gathersf,MPIU_SCALAR,rootdata,leafdata,MPIU_REPLACE);CHKERRQ(ierr);
65*c4762a1bSJed Brown   ierr = VecRestoreArray(y,&leafdata);CHKERRQ(ierr);
66*c4762a1bSJed Brown   ierr = VecScale(y,2);CHKERRQ(ierr);
67*c4762a1bSJed Brown   ierr = VecGetArray(y,&leafdata);CHKERRQ(ierr);
68*c4762a1bSJed Brown 
69*c4762a1bSJed Brown   /* FetchAndOp x to y */
70*c4762a1bSJed Brown   ierr = PetscSFFetchAndOpBegin(gathersf,MPIU_SCALAR,rootdata,leafdata,leafupdate,op);CHKERRQ(ierr);
71*c4762a1bSJed Brown   ierr = PetscSFFetchAndOpEnd(gathersf,MPIU_SCALAR,rootdata,leafdata,leafupdate,op);CHKERRQ(ierr);
72*c4762a1bSJed Brown 
73*c4762a1bSJed 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] */
74*c4762a1bSJed Brown   ierr = VecCreateMPIWithArray(PETSC_COMM_WORLD,1,nleaves,PETSC_DECIDE,leafupdate,&gy2);CHKERRQ(ierr);
75*c4762a1bSJed Brown   ierr = PetscObjectSetName((PetscObject)x,"rootdata");CHKERRQ(ierr);
76*c4762a1bSJed Brown   ierr = PetscObjectSetName((PetscObject)gy2,"leafupdate");CHKERRQ(ierr);
77*c4762a1bSJed Brown 
78*c4762a1bSJed Brown   ierr = VecView(x,PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr);
79*c4762a1bSJed Brown   ierr = VecView(gy2,PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr);
80*c4762a1bSJed Brown   ierr = VecDestroy(&gy2);CHKERRQ(ierr);
81*c4762a1bSJed Brown 
82*c4762a1bSJed Brown   ierr = VecRestoreArray(y2,&leafupdate);CHKERRQ(ierr);
83*c4762a1bSJed Brown   ierr = VecDestroy(&y2);CHKERRQ(ierr);
84*c4762a1bSJed Brown 
85*c4762a1bSJed Brown   ierr = VecRestoreArray(y,&leafdata);CHKERRQ(ierr);
86*c4762a1bSJed Brown   ierr = VecDestroy(&y);CHKERRQ(ierr);
87*c4762a1bSJed Brown 
88*c4762a1bSJed Brown   ierr = VecRestoreArray(x,&rootdata);CHKERRQ(ierr);
89*c4762a1bSJed Brown   /* ierr = VecDestroy(&x);CHKERRQ(ierr); */ /* We will reuse x in ALLGATHER, so do not destroy it */
90*c4762a1bSJed Brown 
91*c4762a1bSJed Brown   ierr = PetscSFDestroy(&gathersf);CHKERRQ(ierr);
92*c4762a1bSJed Brown 
93*c4762a1bSJed Brown   /*-------------------------------------*/
94*c4762a1bSJed Brown   /*       PETSCSF_PATTERN_ALLGATHER     */
95*c4762a1bSJed Brown   /*-------------------------------------*/
96*c4762a1bSJed Brown 
97*c4762a1bSJed Brown   /* set MPI vec x to [1, 2, .., N] */
98*c4762a1bSJed Brown   for (i=low; i<high; i++) {ierr = VecSetValue(x,i,(PetscScalar)i+1.0,INSERT_VALUES);CHKERRQ(ierr);}
99*c4762a1bSJed Brown   ierr = VecAssemblyBegin(x);CHKERRQ(ierr);
100*c4762a1bSJed Brown   ierr = VecAssemblyEnd(x);CHKERRQ(ierr);
101*c4762a1bSJed Brown 
102*c4762a1bSJed Brown   /* Create the allgather SF */
103*c4762a1bSJed Brown   ierr = PetscPrintf(PETSC_COMM_WORLD,"\nTesting PetscSFFetchAndOp on a PETSCSF_PATTERN_ALLGATHER graph with op = %s\n",mpiopname);CHKERRQ(ierr);
104*c4762a1bSJed Brown   ierr = VecGetLayout(x,&layout);CHKERRQ(ierr);
105*c4762a1bSJed Brown   ierr = PetscSFCreate(PETSC_COMM_WORLD,&allgathersf);CHKERRQ(ierr);
106*c4762a1bSJed Brown   ierr = PetscSFSetGraphWithPattern(allgathersf,layout,PETSCSF_PATTERN_ALLGATHER);CHKERRQ(ierr);
107*c4762a1bSJed Brown 
108*c4762a1bSJed Brown   /* Create the leaf vector y (seq vector) and its duplicate y2 working as leafupdate */
109*c4762a1bSJed Brown   ierr = PetscSFGetGraph(allgathersf,NULL,&nleaves,NULL,NULL);CHKERRQ(ierr);
110*c4762a1bSJed Brown   ierr = VecCreateSeq(PETSC_COMM_SELF,nleaves,&y);CHKERRQ(ierr);
111*c4762a1bSJed Brown   ierr = VecDuplicate(y,&y2);CHKERRQ(ierr);
112*c4762a1bSJed Brown 
113*c4762a1bSJed Brown   ierr = VecGetArray(x,&rootdata);CHKERRQ(ierr);
114*c4762a1bSJed Brown   ierr = VecGetArray(y,&leafdata);CHKERRQ(ierr);
115*c4762a1bSJed Brown   ierr = VecGetArray(y2,&leafupdate);CHKERRQ(ierr);
116*c4762a1bSJed Brown 
117*c4762a1bSJed Brown   /* Bcast x to y, to initialize y = [1,N], then scale y to make leafupdate = y = [2,2*N] */
118*c4762a1bSJed Brown   ierr = PetscSFBcastAndOpBegin(allgathersf,MPIU_SCALAR,rootdata,leafdata,MPIU_REPLACE);CHKERRQ(ierr);
119*c4762a1bSJed Brown   ierr = PetscSFBcastAndOpEnd(allgathersf,MPIU_SCALAR,rootdata,leafdata,MPIU_REPLACE);CHKERRQ(ierr);
120*c4762a1bSJed Brown   ierr = VecRestoreArray(y,&leafdata);CHKERRQ(ierr);
121*c4762a1bSJed Brown   ierr = VecScale(y,2);CHKERRQ(ierr);
122*c4762a1bSJed Brown   ierr = VecGetArray(y,&leafdata);CHKERRQ(ierr);
123*c4762a1bSJed Brown 
124*c4762a1bSJed Brown   /* FetchAndOp x to y */
125*c4762a1bSJed Brown   ierr = PetscSFFetchAndOpBegin(allgathersf,MPIU_SCALAR,rootdata,leafdata,leafupdate,op);CHKERRQ(ierr);
126*c4762a1bSJed Brown   ierr = PetscSFFetchAndOpEnd(allgathersf,MPIU_SCALAR,rootdata,leafdata,leafupdate,op);CHKERRQ(ierr);
127*c4762a1bSJed Brown 
128*c4762a1bSJed Brown   /* View roots (x) and leafupdate (y2). Since this is an allgather graph, we have (suppose ranks get updates in ascending order)
129*c4762a1bSJed Brown      rank 0: leafupdate = rootdata = [1,N],   rootdata += leafdata = [3,3*N]
130*c4762a1bSJed Brown      rank 1: leafupdate = rootdata = [3,3*N], rootdata += leafdata = [5,5*N]
131*c4762a1bSJed Brown      rank 2: leafupdate = rootdata = [5,5*N], rootdata += leafdata = [7,7*N]
132*c4762a1bSJed Brown      ...
133*c4762a1bSJed Brown    */
134*c4762a1bSJed Brown   ierr = VecCreateMPIWithArray(PETSC_COMM_WORLD,1,nleaves,PETSC_DECIDE,leafupdate,&gy2);CHKERRQ(ierr);
135*c4762a1bSJed Brown   ierr = PetscObjectSetName((PetscObject)x,"rootdata");CHKERRQ(ierr);
136*c4762a1bSJed Brown   ierr = PetscObjectSetName((PetscObject)gy2,"leafupdate");CHKERRQ(ierr);
137*c4762a1bSJed Brown 
138*c4762a1bSJed Brown   ierr = VecView(x,PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr);
139*c4762a1bSJed Brown   ierr = VecView(gy2,PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr);
140*c4762a1bSJed Brown   ierr = VecDestroy(&gy2);CHKERRQ(ierr);
141*c4762a1bSJed Brown 
142*c4762a1bSJed Brown   ierr = VecRestoreArray(y2,&leafupdate);CHKERRQ(ierr);
143*c4762a1bSJed Brown   ierr = VecDestroy(&y2);CHKERRQ(ierr);
144*c4762a1bSJed Brown 
145*c4762a1bSJed Brown   ierr = VecRestoreArray(y,&leafdata);CHKERRQ(ierr);
146*c4762a1bSJed Brown   ierr = VecDestroy(&y);CHKERRQ(ierr);
147*c4762a1bSJed Brown 
148*c4762a1bSJed Brown   ierr = VecRestoreArray(x,&rootdata);CHKERRQ(ierr);
149*c4762a1bSJed Brown   ierr = VecDestroy(&x);CHKERRQ(ierr); /* We won't reuse x in ALLGATHER, so destroy it */
150*c4762a1bSJed Brown 
151*c4762a1bSJed Brown   ierr = PetscSFDestroy(&allgathersf);CHKERRQ(ierr);
152*c4762a1bSJed Brown 
153*c4762a1bSJed Brown   /*-------------------------------------*/
154*c4762a1bSJed Brown   /*       PETSCSF_PATTERN_ALLTOALL     */
155*c4762a1bSJed Brown   /*-------------------------------------*/
156*c4762a1bSJed Brown 
157*c4762a1bSJed Brown   ierr = VecCreate(PETSC_COMM_WORLD,&x);CHKERRQ(ierr);
158*c4762a1bSJed Brown   ierr = VecSetFromOptions(x);CHKERRQ(ierr);
159*c4762a1bSJed Brown   ierr = VecSetSizes(x,size,PETSC_DECIDE);CHKERRQ(ierr);
160*c4762a1bSJed Brown 
161*c4762a1bSJed Brown   /* set MPI vec x to [1, 2, .., size^2] */
162*c4762a1bSJed Brown   ierr = VecGetOwnershipRange(x,&low,&high);CHKERRQ(ierr);
163*c4762a1bSJed Brown   for (i=low; i<high; i++) {ierr = VecSetValue(x,i,(PetscScalar)i+1.0,INSERT_VALUES);CHKERRQ(ierr);}
164*c4762a1bSJed Brown   ierr = VecAssemblyBegin(x);CHKERRQ(ierr);
165*c4762a1bSJed Brown   ierr = VecAssemblyEnd(x);CHKERRQ(ierr);
166*c4762a1bSJed Brown 
167*c4762a1bSJed Brown /* Create the alltoall SF */
168*c4762a1bSJed Brown   ierr = PetscPrintf(PETSC_COMM_WORLD,"\nTesting PetscSFFetchAndOp on a PETSCSF_PATTERN_ALLTOALL graph with op = %s\n",mpiopname);CHKERRQ(ierr);
169*c4762a1bSJed Brown   ierr = PetscSFCreate(PETSC_COMM_WORLD,&alltoallsf);CHKERRQ(ierr);
170*c4762a1bSJed Brown   ierr = PetscSFSetGraphWithPattern(alltoallsf,NULL/*insignificant*/,PETSCSF_PATTERN_ALLTOALL);CHKERRQ(ierr);
171*c4762a1bSJed Brown 
172*c4762a1bSJed Brown   /* Create the leaf vector y (seq vector) and its duplicate y2 working as leafupdate */
173*c4762a1bSJed Brown   ierr = PetscSFGetGraph(alltoallsf,NULL,&nleaves,NULL,NULL);CHKERRQ(ierr);
174*c4762a1bSJed Brown   ierr = VecCreateSeq(PETSC_COMM_SELF,nleaves,&y);CHKERRQ(ierr);
175*c4762a1bSJed Brown   ierr = VecDuplicate(y,&y2);CHKERRQ(ierr);
176*c4762a1bSJed Brown 
177*c4762a1bSJed Brown   ierr = VecGetArray(x,&rootdata);CHKERRQ(ierr);
178*c4762a1bSJed Brown   ierr = VecGetArray(y,&leafdata);CHKERRQ(ierr);
179*c4762a1bSJed Brown   ierr = VecGetArray(y2,&leafupdate);CHKERRQ(ierr);
180*c4762a1bSJed Brown 
181*c4762a1bSJed Brown   /* Bcast x to y, to initialize y = 1+rank+size*i, with i=0..size-1 */
182*c4762a1bSJed Brown   ierr = PetscSFBcastAndOpBegin(alltoallsf,MPIU_SCALAR,rootdata,leafdata,MPIU_REPLACE);CHKERRQ(ierr);
183*c4762a1bSJed Brown   ierr = PetscSFBcastAndOpEnd(alltoallsf,MPIU_SCALAR,rootdata,leafdata,MPIU_REPLACE);CHKERRQ(ierr);
184*c4762a1bSJed Brown 
185*c4762a1bSJed Brown   /* FetchAndOp x to y */
186*c4762a1bSJed Brown   ierr = PetscSFFetchAndOpBegin(alltoallsf,MPIU_SCALAR,rootdata,leafdata,leafupdate,op);CHKERRQ(ierr);
187*c4762a1bSJed Brown   ierr = PetscSFFetchAndOpEnd(alltoallsf,MPIU_SCALAR,rootdata,leafdata,leafupdate,op);CHKERRQ(ierr);
188*c4762a1bSJed Brown 
189*c4762a1bSJed Brown   /* View roots (x) and leafupdate (y2). Since this is an alltoall graph, each root has only one leaf.
190*c4762a1bSJed Brown      So, leafupdate = rootdata = 1+rank+size*i, i=0..size-1; and rootdata += leafdata, i.e., rootdata = [2,2*N]
191*c4762a1bSJed Brown    */
192*c4762a1bSJed Brown   ierr = VecCreateMPIWithArray(PETSC_COMM_WORLD,1,nleaves,PETSC_DECIDE,leafupdate,&gy2);CHKERRQ(ierr);
193*c4762a1bSJed Brown   ierr = PetscObjectSetName((PetscObject)x,"rootdata");CHKERRQ(ierr);
194*c4762a1bSJed Brown   ierr = PetscObjectSetName((PetscObject)gy2,"leafupdate");CHKERRQ(ierr);
195*c4762a1bSJed Brown 
196*c4762a1bSJed Brown   ierr = VecView(x,PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr);
197*c4762a1bSJed Brown   ierr = VecView(gy2,PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr);
198*c4762a1bSJed Brown   ierr = VecDestroy(&gy2);CHKERRQ(ierr);
199*c4762a1bSJed Brown 
200*c4762a1bSJed Brown   ierr = VecRestoreArray(y2,&leafupdate);CHKERRQ(ierr);
201*c4762a1bSJed Brown   ierr = VecDestroy(&y2);CHKERRQ(ierr);
202*c4762a1bSJed Brown 
203*c4762a1bSJed Brown   ierr = VecRestoreArray(y,&leafdata);CHKERRQ(ierr);
204*c4762a1bSJed Brown   ierr = VecDestroy(&y);CHKERRQ(ierr);
205*c4762a1bSJed Brown 
206*c4762a1bSJed Brown   ierr = VecRestoreArray(x,&rootdata);CHKERRQ(ierr);
207*c4762a1bSJed Brown   ierr = VecDestroy(&x);CHKERRQ(ierr);
208*c4762a1bSJed Brown 
209*c4762a1bSJed Brown   ierr = PetscSFDestroy(&alltoallsf);CHKERRQ(ierr);
210*c4762a1bSJed Brown 
211*c4762a1bSJed Brown   ierr = PetscFinalize();
212*c4762a1bSJed Brown   return ierr;
213*c4762a1bSJed Brown }
214*c4762a1bSJed Brown 
215*c4762a1bSJed Brown /*TEST
216*c4762a1bSJed Brown 
217*c4762a1bSJed Brown    test:
218*c4762a1bSJed Brown       # N=10 is divisible by nsize, to trigger Allgather/Gather in SF
219*c4762a1bSJed Brown       nsize: 2
220*c4762a1bSJed Brown       args: -op replace
221*c4762a1bSJed Brown 
222*c4762a1bSJed Brown    test:
223*c4762a1bSJed Brown       suffix: 2
224*c4762a1bSJed Brown       nsize: 2
225*c4762a1bSJed Brown       args: -op sum
226*c4762a1bSJed Brown 
227*c4762a1bSJed Brown    # N=10 is not divisible by nsize, to trigger Allgatherv/Gatherv in SF
228*c4762a1bSJed Brown    test:
229*c4762a1bSJed Brown       suffix: 3
230*c4762a1bSJed Brown       nsize: 3
231*c4762a1bSJed Brown       args: -op replace
232*c4762a1bSJed Brown 
233*c4762a1bSJed Brown    test:
234*c4762a1bSJed Brown       suffix: 4
235*c4762a1bSJed Brown       nsize: 3
236*c4762a1bSJed Brown       args: -op sum
237*c4762a1bSJed Brown 
238*c4762a1bSJed Brown TEST*/
239*c4762a1bSJed Brown 
240