xref: /petsc/src/vec/is/sf/tutorials/ex1.c (revision c4762a1b19cd2af06abeed90e8f9d34fb975dd94)
1*c4762a1bSJed Brown static const char help[] = "Test star forest communication (PetscSF)\n\n";
2*c4762a1bSJed Brown 
3*c4762a1bSJed Brown /*T
4*c4762a1bSJed Brown     Description: A star is a simple tree with one root and zero or more leaves.
5*c4762a1bSJed Brown     A star forest is a union of disjoint stars.
6*c4762a1bSJed Brown     Many common communication patterns can be expressed as updates of rootdata using leafdata and vice-versa.
7*c4762a1bSJed Brown     This example creates a star forest, communicates values using the graph (see options for types of communication), views the graph, then destroys it.
8*c4762a1bSJed Brown T*/
9*c4762a1bSJed Brown 
10*c4762a1bSJed Brown /*
11*c4762a1bSJed Brown   Include petscsf.h so we can use PetscSF objects. Note that this automatically
12*c4762a1bSJed Brown   includes petscsys.h.
13*c4762a1bSJed Brown */
14*c4762a1bSJed Brown #include <petscsf.h>
15*c4762a1bSJed Brown #include <petscviewer.h>
16*c4762a1bSJed Brown 
17*c4762a1bSJed Brown /* like PetscSFView() but with alternative array of local indices */
18*c4762a1bSJed Brown static PetscErrorCode PetscSFViewCustomLocals_Private(PetscSF sf,const PetscInt locals[],PetscViewer viewer)
19*c4762a1bSJed Brown {
20*c4762a1bSJed Brown   const PetscSFNode *iremote;
21*c4762a1bSJed Brown   PetscInt          i,nroots,nleaves,nranks;
22*c4762a1bSJed Brown   PetscMPIInt       rank;
23*c4762a1bSJed Brown   PetscErrorCode    ierr;
24*c4762a1bSJed Brown 
25*c4762a1bSJed Brown   PetscFunctionBeginUser;
26*c4762a1bSJed Brown   ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)sf),&rank);CHKERRQ(ierr);
27*c4762a1bSJed Brown   ierr = PetscSFGetGraph(sf,&nroots,&nleaves,NULL,&iremote);CHKERRQ(ierr);
28*c4762a1bSJed Brown   ierr = PetscSFGetRootRanks(sf,&nranks,NULL,NULL,NULL,NULL);CHKERRQ(ierr);
29*c4762a1bSJed Brown   ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr);
30*c4762a1bSJed Brown   ierr = PetscViewerASCIIPushSynchronized(viewer);CHKERRQ(ierr);
31*c4762a1bSJed Brown   ierr = PetscViewerASCIISynchronizedPrintf(viewer,"[%d] Number of roots=%D, leaves=%D, remote ranks=%D\n",rank,nroots,nleaves,nranks);CHKERRQ(ierr);
32*c4762a1bSJed Brown   for (i=0; i<nleaves; i++) {
33*c4762a1bSJed Brown     ierr = PetscViewerASCIISynchronizedPrintf(viewer,"[%d] %D <- (%D,%D)\n",rank,locals[i],iremote[i].rank,iremote[i].index);CHKERRQ(ierr);
34*c4762a1bSJed Brown   }
35*c4762a1bSJed Brown   ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
36*c4762a1bSJed Brown   ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr);
37*c4762a1bSJed Brown   ierr = PetscViewerASCIIPopSynchronized(viewer);CHKERRQ(ierr);
38*c4762a1bSJed Brown   PetscFunctionReturn(0);
39*c4762a1bSJed Brown }
40*c4762a1bSJed Brown 
41*c4762a1bSJed Brown int main(int argc,char **argv)
42*c4762a1bSJed Brown {
43*c4762a1bSJed Brown   PetscErrorCode ierr;
44*c4762a1bSJed Brown   PetscInt       i,nroots,nrootsalloc,nleaves,nleavesalloc,*mine,stride;
45*c4762a1bSJed Brown   PetscSFNode    *remote;
46*c4762a1bSJed Brown   PetscMPIInt    rank,size;
47*c4762a1bSJed Brown   PetscSF        sf;
48*c4762a1bSJed Brown   PetscBool      test_all,test_bcast,test_bcastop,test_reduce,test_degree,test_fetchandop,test_gather,test_scatter,test_embed,test_invert,test_sf_distribute,test_char;
49*c4762a1bSJed Brown   MPI_Op         mop=MPI_OP_NULL; /* initialize to prevent compiler warnings with cxx_quad build */
50*c4762a1bSJed Brown   char           opstring[256];
51*c4762a1bSJed Brown   PetscBool      strflg;
52*c4762a1bSJed Brown 
53*c4762a1bSJed Brown   ierr = PetscInitialize(&argc,&argv,(char*)0,help);if (ierr) return ierr;
54*c4762a1bSJed Brown   ierr = MPI_Comm_rank(PETSC_COMM_WORLD,&rank);CHKERRQ(ierr);
55*c4762a1bSJed Brown   ierr = MPI_Comm_size(PETSC_COMM_WORLD,&size);CHKERRQ(ierr);
56*c4762a1bSJed Brown 
57*c4762a1bSJed Brown   ierr            = PetscOptionsBegin(PETSC_COMM_WORLD,"","PetscSF Test Options","none");CHKERRQ(ierr);
58*c4762a1bSJed Brown   test_all        = PETSC_FALSE;
59*c4762a1bSJed Brown   ierr            = PetscOptionsBool("-test_all","Test all SF communications","",test_all,&test_all,NULL);CHKERRQ(ierr);
60*c4762a1bSJed Brown   test_bcast      = test_all;
61*c4762a1bSJed Brown   ierr            = PetscOptionsBool("-test_bcast","Test broadcast","",test_bcast,&test_bcast,NULL);CHKERRQ(ierr);
62*c4762a1bSJed Brown   test_bcastop    = test_all;
63*c4762a1bSJed Brown   ierr            = PetscOptionsBool("-test_bcastop","Test broadcast and reduce","",test_bcastop,&test_bcastop,NULL);CHKERRQ(ierr);
64*c4762a1bSJed Brown   test_reduce     = test_all;
65*c4762a1bSJed Brown   ierr            = PetscOptionsBool("-test_reduce","Test reduction","",test_reduce,&test_reduce,NULL);CHKERRQ(ierr);
66*c4762a1bSJed Brown   test_char       = test_all;
67*c4762a1bSJed Brown   ierr            = PetscOptionsBool("-test_char","Test signed char, unsigned char, and char","",test_char,&test_char,NULL);CHKERRQ(ierr);
68*c4762a1bSJed Brown   mop             = MPI_SUM;
69*c4762a1bSJed Brown   ierr            = PetscStrcpy(opstring,"sum");CHKERRQ(ierr);
70*c4762a1bSJed Brown   ierr            = PetscOptionsString("-test_op","Designate which MPI_Op to use","",opstring,opstring,256,NULL);CHKERRQ(ierr);
71*c4762a1bSJed Brown   ierr = PetscStrcmp("sum",opstring,&strflg);CHKERRQ(ierr);
72*c4762a1bSJed Brown   if (strflg) {
73*c4762a1bSJed Brown     mop = MPIU_SUM;
74*c4762a1bSJed Brown   }
75*c4762a1bSJed Brown   ierr = PetscStrcmp("prod",opstring,&strflg);CHKERRQ(ierr);
76*c4762a1bSJed Brown   if (strflg) {
77*c4762a1bSJed Brown     mop = MPI_PROD;
78*c4762a1bSJed Brown   }
79*c4762a1bSJed Brown   ierr = PetscStrcmp("max",opstring,&strflg);CHKERRQ(ierr);
80*c4762a1bSJed Brown   if (strflg) {
81*c4762a1bSJed Brown     mop = MPI_MAX;
82*c4762a1bSJed Brown   }
83*c4762a1bSJed Brown   ierr = PetscStrcmp("min",opstring,&strflg);CHKERRQ(ierr);
84*c4762a1bSJed Brown   if (strflg) {
85*c4762a1bSJed Brown     mop = MPI_MIN;
86*c4762a1bSJed Brown   }
87*c4762a1bSJed Brown   ierr = PetscStrcmp("land",opstring,&strflg);CHKERRQ(ierr);
88*c4762a1bSJed Brown   if (strflg) {
89*c4762a1bSJed Brown     mop = MPI_LAND;
90*c4762a1bSJed Brown   }
91*c4762a1bSJed Brown   ierr = PetscStrcmp("band",opstring,&strflg);CHKERRQ(ierr);
92*c4762a1bSJed Brown   if (strflg) {
93*c4762a1bSJed Brown     mop = MPI_BAND;
94*c4762a1bSJed Brown   }
95*c4762a1bSJed Brown   ierr = PetscStrcmp("lor",opstring,&strflg);CHKERRQ(ierr);
96*c4762a1bSJed Brown   if (strflg) {
97*c4762a1bSJed Brown     mop = MPI_LOR;
98*c4762a1bSJed Brown   }
99*c4762a1bSJed Brown   ierr = PetscStrcmp("bor",opstring,&strflg);CHKERRQ(ierr);
100*c4762a1bSJed Brown   if (strflg) {
101*c4762a1bSJed Brown     mop = MPI_BOR;
102*c4762a1bSJed Brown   }
103*c4762a1bSJed Brown   ierr = PetscStrcmp("lxor",opstring,&strflg);CHKERRQ(ierr);
104*c4762a1bSJed Brown   if (strflg) {
105*c4762a1bSJed Brown     mop = MPI_LXOR;
106*c4762a1bSJed Brown   }
107*c4762a1bSJed Brown   ierr = PetscStrcmp("bxor",opstring,&strflg);CHKERRQ(ierr);
108*c4762a1bSJed Brown   if (strflg) {
109*c4762a1bSJed Brown     mop = MPI_BXOR;
110*c4762a1bSJed Brown   }
111*c4762a1bSJed Brown   test_degree     = test_all;
112*c4762a1bSJed Brown   ierr            = PetscOptionsBool("-test_degree","Test computation of vertex degree","",test_degree,&test_degree,NULL);CHKERRQ(ierr);
113*c4762a1bSJed Brown   test_fetchandop = test_all;
114*c4762a1bSJed Brown   ierr            = PetscOptionsBool("-test_fetchandop","Test atomic Fetch-And-Op","",test_fetchandop,&test_fetchandop,NULL);CHKERRQ(ierr);
115*c4762a1bSJed Brown   test_gather     = test_all;
116*c4762a1bSJed Brown   ierr            = PetscOptionsBool("-test_gather","Test point gather","",test_gather,&test_gather,NULL);CHKERRQ(ierr);
117*c4762a1bSJed Brown   test_scatter    = test_all;
118*c4762a1bSJed Brown   ierr            = PetscOptionsBool("-test_scatter","Test point scatter","",test_scatter,&test_scatter,NULL);CHKERRQ(ierr);
119*c4762a1bSJed Brown   test_embed      = test_all;
120*c4762a1bSJed Brown   ierr            = PetscOptionsBool("-test_embed","Test point embed","",test_embed,&test_embed,NULL);CHKERRQ(ierr);
121*c4762a1bSJed Brown   test_invert     = test_all;
122*c4762a1bSJed Brown   ierr            = PetscOptionsBool("-test_invert","Test point invert","",test_invert,&test_invert,NULL);CHKERRQ(ierr);
123*c4762a1bSJed Brown   stride          = 1;
124*c4762a1bSJed Brown   ierr            = PetscOptionsInt("-stride","Stride for leaf and root data","",stride,&stride,NULL);CHKERRQ(ierr);
125*c4762a1bSJed Brown   test_sf_distribute = PETSC_FALSE;
126*c4762a1bSJed Brown   ierr            = PetscOptionsBool("-test_sf_distribute","Create an SF that 'distributes' to each process, like an alltoall","",test_sf_distribute,&test_sf_distribute,NULL);CHKERRQ(ierr);
127*c4762a1bSJed Brown   ierr            = PetscOptionsString("-test_op","Designate which MPI_Op to use","",opstring,opstring,256,NULL);CHKERRQ(ierr);
128*c4762a1bSJed Brown   ierr            = PetscOptionsEnd();CHKERRQ(ierr);
129*c4762a1bSJed Brown 
130*c4762a1bSJed Brown   if (test_sf_distribute) {
131*c4762a1bSJed Brown     nroots = size;
132*c4762a1bSJed Brown     nrootsalloc = size;
133*c4762a1bSJed Brown     nleaves = size;
134*c4762a1bSJed Brown     nleavesalloc = size;
135*c4762a1bSJed Brown     mine = NULL;
136*c4762a1bSJed Brown     ierr = PetscMalloc1(nleaves,&remote);CHKERRQ(ierr);
137*c4762a1bSJed Brown     for (i=0; i<size; i++) {
138*c4762a1bSJed Brown       remote[i].rank = i;
139*c4762a1bSJed Brown       remote[i].index = rank;
140*c4762a1bSJed Brown     }
141*c4762a1bSJed Brown   } else {
142*c4762a1bSJed Brown     nroots       = 2 + (PetscInt)(rank == 0);
143*c4762a1bSJed Brown     nrootsalloc  = nroots * stride;
144*c4762a1bSJed Brown     nleaves      = 2 + (PetscInt)(rank > 0);
145*c4762a1bSJed Brown     nleavesalloc = nleaves * stride;
146*c4762a1bSJed Brown     mine         = NULL;
147*c4762a1bSJed Brown     if (stride > 1) {
148*c4762a1bSJed Brown       PetscInt i;
149*c4762a1bSJed Brown 
150*c4762a1bSJed Brown       ierr = PetscMalloc1(nleaves,&mine);CHKERRQ(ierr);
151*c4762a1bSJed Brown       for (i = 0; i < nleaves; i++) {
152*c4762a1bSJed Brown         mine[i] = stride * i;
153*c4762a1bSJed Brown       }
154*c4762a1bSJed Brown     }
155*c4762a1bSJed Brown     ierr = PetscMalloc1(nleaves,&remote);CHKERRQ(ierr);
156*c4762a1bSJed Brown     /* Left periodic neighbor */
157*c4762a1bSJed Brown     remote[0].rank  = (rank+size-1)%size;
158*c4762a1bSJed Brown     remote[0].index = 1 * stride;
159*c4762a1bSJed Brown     /* Right periodic neighbor */
160*c4762a1bSJed Brown     remote[1].rank  = (rank+1)%size;
161*c4762a1bSJed Brown     remote[1].index = 0 * stride;
162*c4762a1bSJed Brown     if (rank > 0) {               /* All processes reference rank 0, index 1 */
163*c4762a1bSJed Brown       remote[2].rank  = 0;
164*c4762a1bSJed Brown       remote[2].index = 2 * stride;
165*c4762a1bSJed Brown     }
166*c4762a1bSJed Brown   }
167*c4762a1bSJed Brown 
168*c4762a1bSJed Brown   /* Create a star forest for communication. In this example, the leaf space is dense, so we pass NULL. */
169*c4762a1bSJed Brown   ierr = PetscSFCreate(PETSC_COMM_WORLD,&sf);CHKERRQ(ierr);
170*c4762a1bSJed Brown   ierr = PetscSFSetFromOptions(sf);CHKERRQ(ierr);
171*c4762a1bSJed Brown   ierr = PetscSFSetGraph(sf,nrootsalloc,nleaves,mine,PETSC_OWN_POINTER,remote,PETSC_OWN_POINTER);CHKERRQ(ierr);
172*c4762a1bSJed Brown   ierr = PetscSFSetUp(sf);CHKERRQ(ierr);
173*c4762a1bSJed Brown 
174*c4762a1bSJed Brown   /* View graph, mostly useful for debugging purposes. */
175*c4762a1bSJed Brown   ierr = PetscViewerPushFormat(PETSC_VIEWER_STDOUT_WORLD,PETSC_VIEWER_ASCII_INFO_DETAIL);CHKERRQ(ierr);
176*c4762a1bSJed Brown   ierr = PetscSFView(sf,PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr);
177*c4762a1bSJed Brown   ierr = PetscViewerPopFormat(PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr);
178*c4762a1bSJed Brown 
179*c4762a1bSJed Brown   if (test_bcast) {             /* broadcast rootdata into leafdata */
180*c4762a1bSJed Brown     PetscInt *rootdata,*leafdata;
181*c4762a1bSJed Brown     /* Allocate space for send and recieve buffers. This example communicates PetscInt, but other types, including
182*c4762a1bSJed Brown      * user-defined structures, could also be used. */
183*c4762a1bSJed Brown     ierr = PetscMalloc2(nrootsalloc,&rootdata,nleavesalloc,&leafdata);CHKERRQ(ierr);
184*c4762a1bSJed Brown     /* Set rootdata buffer to be broadcast */
185*c4762a1bSJed Brown     for (i=0; i<nrootsalloc; i++) rootdata[i] = -1;
186*c4762a1bSJed Brown     for (i=0; i<nroots; i++) rootdata[i*stride] = 100*(rank+1) + i;
187*c4762a1bSJed Brown     /* Initialize local buffer, these values are never used. */
188*c4762a1bSJed Brown     for (i=0; i<nleavesalloc; i++) leafdata[i] = -1;
189*c4762a1bSJed Brown     /* Broadcast entries from rootdata to leafdata. Computation or other communication can be performed between the begin and end calls. */
190*c4762a1bSJed Brown     ierr = PetscSFBcastBegin(sf,MPIU_INT,rootdata,leafdata);CHKERRQ(ierr);
191*c4762a1bSJed Brown     ierr = PetscSFBcastEnd(sf,MPIU_INT,rootdata,leafdata);CHKERRQ(ierr);
192*c4762a1bSJed Brown     ierr = PetscViewerASCIIPrintf(PETSC_VIEWER_STDOUT_WORLD,"## Bcast Rootdata\n");CHKERRQ(ierr);
193*c4762a1bSJed Brown     ierr = PetscIntView(nrootsalloc,rootdata,PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr);
194*c4762a1bSJed Brown     ierr = PetscViewerASCIIPrintf(PETSC_VIEWER_STDOUT_WORLD,"## Bcast Leafdata\n");CHKERRQ(ierr);
195*c4762a1bSJed Brown     ierr = PetscIntView(nleavesalloc,leafdata,PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr);
196*c4762a1bSJed Brown     ierr = PetscFree2(rootdata,leafdata);CHKERRQ(ierr);
197*c4762a1bSJed Brown   }
198*c4762a1bSJed Brown 
199*c4762a1bSJed Brown   if (test_bcast && test_char) { /* Bcast with char */
200*c4762a1bSJed Brown     PetscInt len;
201*c4762a1bSJed Brown     char buf[256];
202*c4762a1bSJed Brown     char *rootdata,*leafdata;
203*c4762a1bSJed Brown     ierr = PetscMalloc2(nrootsalloc,&rootdata,nleavesalloc,&leafdata);CHKERRQ(ierr);
204*c4762a1bSJed Brown     /* Set rootdata buffer to be broadcast */
205*c4762a1bSJed Brown     for (i=0; i<nrootsalloc; i++) rootdata[i] = '*';
206*c4762a1bSJed Brown     for (i=0; i<nroots; i++) rootdata[i*stride] = 'A' + rank*3 + i; /* rank is very small, so it is fine to compute a char */
207*c4762a1bSJed Brown     /* Initialize local buffer, these values are never used. */
208*c4762a1bSJed Brown     for (i=0; i<nleavesalloc; i++) leafdata[i] = '?';
209*c4762a1bSJed Brown 
210*c4762a1bSJed Brown     ierr = PetscSFBcastBegin(sf,MPI_CHAR,rootdata,leafdata);CHKERRQ(ierr);
211*c4762a1bSJed Brown     ierr = PetscSFBcastEnd(sf,MPI_CHAR,rootdata,leafdata);CHKERRQ(ierr);
212*c4762a1bSJed Brown 
213*c4762a1bSJed Brown     ierr = PetscViewerASCIIPrintf(PETSC_VIEWER_STDOUT_WORLD,"## Bcast Rootdata in type of char\n");CHKERRQ(ierr);
214*c4762a1bSJed Brown     len  = 0; ierr = PetscSNPrintf(buf,256,"%4d:",rank);CHKERRQ(ierr); len += 5;
215*c4762a1bSJed Brown     for (i=0; i<nrootsalloc; i++) {ierr = PetscSNPrintf(buf+len,256-len,"%5c",rootdata[i]);CHKERRQ(ierr); len += 5;}
216*c4762a1bSJed Brown     ierr = PetscSynchronizedPrintf(PETSC_COMM_WORLD,"%s\n",buf);CHKERRQ(ierr);
217*c4762a1bSJed Brown     ierr = PetscSynchronizedFlush(PETSC_COMM_WORLD,PETSC_STDOUT);CHKERRQ(ierr);
218*c4762a1bSJed Brown 
219*c4762a1bSJed Brown     ierr = PetscViewerASCIIPrintf(PETSC_VIEWER_STDOUT_WORLD,"## Bcast Leafdata in type of char\n");CHKERRQ(ierr);
220*c4762a1bSJed Brown     len = 0; ierr = PetscSNPrintf(buf,256,"%4d:",rank);CHKERRQ(ierr); len += 5;
221*c4762a1bSJed Brown     for (i=0; i<nleavesalloc; i++) {ierr = PetscSNPrintf(buf+len,256-len,"%5c",leafdata[i]);CHKERRQ(ierr); len += 5;}
222*c4762a1bSJed Brown     ierr = PetscSynchronizedPrintf(PETSC_COMM_WORLD,"%s\n",buf);CHKERRQ(ierr);
223*c4762a1bSJed Brown     ierr = PetscSynchronizedFlush(PETSC_COMM_WORLD,PETSC_STDOUT);CHKERRQ(ierr);
224*c4762a1bSJed Brown 
225*c4762a1bSJed Brown     ierr = PetscFree2(rootdata,leafdata);CHKERRQ(ierr);
226*c4762a1bSJed Brown   }
227*c4762a1bSJed Brown 
228*c4762a1bSJed Brown   if (test_bcastop) {         /* Reduce rootdata into leafdata */
229*c4762a1bSJed Brown     PetscInt *rootdata,*leafdata;
230*c4762a1bSJed Brown     /* Allocate space for send and receive buffers. This example communicates PetscInt, but other types, including
231*c4762a1bSJed Brown      * user-defined structures, could also be used. */
232*c4762a1bSJed Brown     ierr = PetscMalloc2(nrootsalloc,&rootdata,nleavesalloc,&leafdata);CHKERRQ(ierr);
233*c4762a1bSJed Brown     /* Set rootdata buffer to be broadcast */
234*c4762a1bSJed Brown     for (i=0; i<nrootsalloc; i++) rootdata[i] = -1;
235*c4762a1bSJed Brown     for (i=0; i<nroots; i++) rootdata[i*stride] = 100*(rank+1) + i;
236*c4762a1bSJed Brown     /* Set leaf values to reduce with */
237*c4762a1bSJed Brown     for (i=0; i<nleavesalloc; i++) leafdata[i] = -10*(rank+1) - i;
238*c4762a1bSJed Brown     ierr = PetscViewerASCIIPrintf(PETSC_VIEWER_STDOUT_WORLD,"## Pre-BcastAndOp Leafdata\n");CHKERRQ(ierr);
239*c4762a1bSJed Brown     ierr = PetscIntView(nleavesalloc,leafdata,PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr);
240*c4762a1bSJed Brown     /* Broadcast entries from rootdata to leafdata. Computation or other communication can be performed between the begin and end calls. */
241*c4762a1bSJed Brown     ierr = PetscSFBcastAndOpBegin(sf,MPIU_INT,rootdata,leafdata,mop);CHKERRQ(ierr);
242*c4762a1bSJed Brown     ierr = PetscSFBcastAndOpEnd(sf,MPIU_INT,rootdata,leafdata,mop);CHKERRQ(ierr);
243*c4762a1bSJed Brown     ierr = PetscViewerASCIIPrintf(PETSC_VIEWER_STDOUT_WORLD,"## BcastAndOp Rootdata\n");CHKERRQ(ierr);
244*c4762a1bSJed Brown     ierr = PetscIntView(nrootsalloc,rootdata,PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr);
245*c4762a1bSJed Brown     ierr = PetscViewerASCIIPrintf(PETSC_VIEWER_STDOUT_WORLD,"## BcastAndOp Leafdata\n");CHKERRQ(ierr);
246*c4762a1bSJed Brown     ierr = PetscIntView(nleavesalloc,leafdata,PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr);
247*c4762a1bSJed Brown     ierr = PetscFree2(rootdata,leafdata);CHKERRQ(ierr);
248*c4762a1bSJed Brown   }
249*c4762a1bSJed Brown 
250*c4762a1bSJed Brown   if (test_reduce) {            /* Reduce leafdata into rootdata */
251*c4762a1bSJed Brown     PetscInt *rootdata,*leafdata;
252*c4762a1bSJed Brown     ierr = PetscMalloc2(nrootsalloc,&rootdata,nleavesalloc,&leafdata);CHKERRQ(ierr);
253*c4762a1bSJed Brown     /* Initialize rootdata buffer in which the result of the reduction will appear. */
254*c4762a1bSJed Brown     for (i=0; i<nrootsalloc; i++) rootdata[i] = -1;
255*c4762a1bSJed Brown     for (i=0; i<nroots; i++) rootdata[i*stride] = 100*(rank+1) + i;
256*c4762a1bSJed Brown     /* Set leaf values to reduce. */
257*c4762a1bSJed Brown     for (i=0; i<nleavesalloc; i++) leafdata[i] = -1;
258*c4762a1bSJed Brown     for (i=0; i<nleaves; i++) leafdata[i*stride] = 1000*(rank+1) + 10*i;
259*c4762a1bSJed Brown     ierr = PetscViewerASCIIPrintf(PETSC_VIEWER_STDOUT_WORLD,"## Pre-Reduce Rootdata\n");CHKERRQ(ierr);
260*c4762a1bSJed Brown     ierr = PetscIntView(nrootsalloc,rootdata,PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr);
261*c4762a1bSJed Brown     /* Perform reduction. Computation or other communication can be performed between the begin and end calls.
262*c4762a1bSJed Brown      * This example sums the values, but other MPI_Ops can be used (e.g MPI_MAX, MPI_PROD). */
263*c4762a1bSJed Brown     ierr = PetscSFReduceBegin(sf,MPIU_INT,leafdata,rootdata,mop);CHKERRQ(ierr);
264*c4762a1bSJed Brown     ierr = PetscSFReduceEnd(sf,MPIU_INT,leafdata,rootdata,mop);CHKERRQ(ierr);
265*c4762a1bSJed Brown     ierr = PetscViewerASCIIPrintf(PETSC_VIEWER_STDOUT_WORLD,"## Reduce Leafdata\n");CHKERRQ(ierr);
266*c4762a1bSJed Brown     ierr = PetscIntView(nleavesalloc,leafdata,PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr);
267*c4762a1bSJed Brown     ierr = PetscViewerASCIIPrintf(PETSC_VIEWER_STDOUT_WORLD,"## Reduce Rootdata\n");CHKERRQ(ierr);
268*c4762a1bSJed Brown     ierr = PetscIntView(nrootsalloc,rootdata,PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr);
269*c4762a1bSJed Brown     ierr = PetscFree2(rootdata,leafdata);CHKERRQ(ierr);
270*c4762a1bSJed Brown   }
271*c4762a1bSJed Brown 
272*c4762a1bSJed Brown   if (test_reduce && test_char) { /* Reduce with signed char */
273*c4762a1bSJed Brown     PetscInt len;
274*c4762a1bSJed Brown     char buf[256];
275*c4762a1bSJed Brown     signed char *rootdata,*leafdata;
276*c4762a1bSJed Brown     ierr = PetscMalloc2(nrootsalloc,&rootdata,nleavesalloc,&leafdata);CHKERRQ(ierr);
277*c4762a1bSJed Brown     /* Initialize rootdata buffer in which the result of the reduction will appear. */
278*c4762a1bSJed Brown     for (i=0; i<nrootsalloc; i++) rootdata[i] = -1;
279*c4762a1bSJed Brown     for (i=0; i<nroots; i++) rootdata[i*stride] = 10*(rank+1) + i;
280*c4762a1bSJed Brown     /* Set leaf values to reduce. */
281*c4762a1bSJed Brown     for (i=0; i<nleavesalloc; i++) leafdata[i] = -1;
282*c4762a1bSJed Brown     for (i=0; i<nleaves; i++) leafdata[i*stride] = 50*(rank+1) + 10*i;
283*c4762a1bSJed Brown     ierr = PetscViewerASCIIPrintf(PETSC_VIEWER_STDOUT_WORLD,"## Pre-Reduce Rootdata in type of signed char\n");CHKERRQ(ierr);
284*c4762a1bSJed Brown 
285*c4762a1bSJed Brown     len = 0; ierr = PetscSNPrintf(buf,256,"%4d:",rank);CHKERRQ(ierr); len += 5;
286*c4762a1bSJed Brown     for (i=0; i<nrootsalloc; i++) {ierr = PetscSNPrintf(buf+len,256-len,"%5d",rootdata[i]);CHKERRQ(ierr); len += 5;}
287*c4762a1bSJed Brown     ierr = PetscSynchronizedPrintf(PETSC_COMM_WORLD,"%s\n",buf);CHKERRQ(ierr);
288*c4762a1bSJed Brown     ierr = PetscSynchronizedFlush(PETSC_COMM_WORLD,PETSC_STDOUT);CHKERRQ(ierr);
289*c4762a1bSJed Brown 
290*c4762a1bSJed Brown     /* Using MPI_CHAR should trigger an error since MPI standard does not support reduction on MPI_CHAR.
291*c4762a1bSJed Brown        Testing with -test_op max, one can see the sign does take effect in MPI_MAX.
292*c4762a1bSJed Brown      */
293*c4762a1bSJed Brown     ierr = PetscSFReduceBegin(sf,MPI_SIGNED_CHAR,leafdata,rootdata,mop);CHKERRQ(ierr);
294*c4762a1bSJed Brown     ierr = PetscSFReduceEnd(sf,MPI_SIGNED_CHAR,leafdata,rootdata,mop);CHKERRQ(ierr);
295*c4762a1bSJed Brown 
296*c4762a1bSJed Brown     ierr = PetscViewerASCIIPrintf(PETSC_VIEWER_STDOUT_WORLD,"## Reduce Leafdata in type of signed char\n");CHKERRQ(ierr);
297*c4762a1bSJed Brown     len  = 0; ierr = PetscSNPrintf(buf,256,"%4d:",rank);CHKERRQ(ierr); len += 5;
298*c4762a1bSJed Brown     for (i=0; i<nleavesalloc; i++) {ierr = PetscSNPrintf(buf+len,256-len,"%5d",leafdata[i]);CHKERRQ(ierr); len += 5;}
299*c4762a1bSJed Brown     ierr = PetscSynchronizedPrintf(PETSC_COMM_WORLD,"%s\n",buf);CHKERRQ(ierr);
300*c4762a1bSJed Brown     ierr = PetscSynchronizedFlush(PETSC_COMM_WORLD,PETSC_STDOUT);CHKERRQ(ierr);
301*c4762a1bSJed Brown 
302*c4762a1bSJed Brown     ierr = PetscViewerASCIIPrintf(PETSC_VIEWER_STDOUT_WORLD,"## Reduce Rootdata in type of signed char\n");CHKERRQ(ierr);
303*c4762a1bSJed Brown     len = 0; ierr = PetscSNPrintf(buf,256,"%4d:",rank);CHKERRQ(ierr); len += 5;
304*c4762a1bSJed Brown     for (i=0; i<nrootsalloc; i++) {ierr = PetscSNPrintf(buf+len,256-len,"%5d",rootdata[i]);CHKERRQ(ierr); len += 5;}
305*c4762a1bSJed Brown     ierr = PetscSynchronizedPrintf(PETSC_COMM_WORLD,"%s\n",buf);CHKERRQ(ierr);
306*c4762a1bSJed Brown     ierr = PetscSynchronizedFlush(PETSC_COMM_WORLD,PETSC_STDOUT);CHKERRQ(ierr);
307*c4762a1bSJed Brown 
308*c4762a1bSJed Brown     ierr = PetscFree2(rootdata,leafdata);CHKERRQ(ierr);
309*c4762a1bSJed Brown   }
310*c4762a1bSJed Brown 
311*c4762a1bSJed Brown   if (test_reduce && test_char) { /* Reduce with unsigned char */
312*c4762a1bSJed Brown     PetscInt len;
313*c4762a1bSJed Brown     char buf[256];
314*c4762a1bSJed Brown     unsigned char *rootdata,*leafdata;
315*c4762a1bSJed Brown     ierr = PetscMalloc2(nrootsalloc,&rootdata,nleavesalloc,&leafdata);CHKERRQ(ierr);
316*c4762a1bSJed Brown     /* Initialize rootdata buffer in which the result of the reduction will appear. */
317*c4762a1bSJed Brown     for (i=0; i<nrootsalloc; i++) rootdata[i] = -1;
318*c4762a1bSJed Brown     for (i=0; i<nroots; i++) rootdata[i*stride] = 10*(rank+1) + i;
319*c4762a1bSJed Brown     /* Set leaf values to reduce. */
320*c4762a1bSJed Brown     for (i=0; i<nleavesalloc; i++) leafdata[i] = -1;
321*c4762a1bSJed Brown     for (i=0; i<nleaves; i++) leafdata[i*stride] = 50*(rank+1) + 10*i;
322*c4762a1bSJed Brown     ierr = PetscViewerASCIIPrintf(PETSC_VIEWER_STDOUT_WORLD,"## Pre-Reduce Rootdata in type of unsigned char\n");CHKERRQ(ierr);
323*c4762a1bSJed Brown 
324*c4762a1bSJed Brown     len = 0; ierr = PetscSNPrintf(buf,256,"%4d:",rank);CHKERRQ(ierr); len += 5;
325*c4762a1bSJed Brown     for (i=0; i<nrootsalloc; i++) {ierr = PetscSNPrintf(buf+len,256-len,"%5u",rootdata[i]);CHKERRQ(ierr); len += 5;}
326*c4762a1bSJed Brown     ierr = PetscSynchronizedPrintf(PETSC_COMM_WORLD,"%s\n",buf);CHKERRQ(ierr);
327*c4762a1bSJed Brown     ierr = PetscSynchronizedFlush(PETSC_COMM_WORLD,PETSC_STDOUT);CHKERRQ(ierr);
328*c4762a1bSJed Brown 
329*c4762a1bSJed Brown     /* Using MPI_CHAR should trigger an error since MPI standard does not support reduction on MPI_CHAR.
330*c4762a1bSJed Brown        Testing with -test_op max, one can see the sign does take effect in MPI_MAX.
331*c4762a1bSJed Brown      */
332*c4762a1bSJed Brown     ierr = PetscSFReduceBegin(sf,MPI_UNSIGNED_CHAR,leafdata,rootdata,mop);CHKERRQ(ierr);
333*c4762a1bSJed Brown     ierr = PetscSFReduceEnd(sf,MPI_UNSIGNED_CHAR,leafdata,rootdata,mop);CHKERRQ(ierr);
334*c4762a1bSJed Brown 
335*c4762a1bSJed Brown     ierr = PetscViewerASCIIPrintf(PETSC_VIEWER_STDOUT_WORLD,"## Reduce Leafdata in type of unsigned char\n");CHKERRQ(ierr);
336*c4762a1bSJed Brown     len  = 0; ierr = PetscSNPrintf(buf,256,"%4d:",rank);CHKERRQ(ierr); len += 5;
337*c4762a1bSJed Brown     for (i=0; i<nleavesalloc; i++) {ierr = PetscSNPrintf(buf+len,256-len,"%5u",leafdata[i]);CHKERRQ(ierr); len += 5;}
338*c4762a1bSJed Brown     ierr = PetscSynchronizedPrintf(PETSC_COMM_WORLD,"%s\n",buf);CHKERRQ(ierr);
339*c4762a1bSJed Brown     ierr = PetscSynchronizedFlush(PETSC_COMM_WORLD,PETSC_STDOUT);CHKERRQ(ierr);
340*c4762a1bSJed Brown 
341*c4762a1bSJed Brown     ierr = PetscViewerASCIIPrintf(PETSC_VIEWER_STDOUT_WORLD,"## Reduce Rootdata in type of unsigned char\n");CHKERRQ(ierr);
342*c4762a1bSJed Brown     len = 0; ierr = PetscSNPrintf(buf,256,"%4d:",rank);CHKERRQ(ierr); len += 5;
343*c4762a1bSJed Brown     for (i=0; i<nrootsalloc; i++) {ierr = PetscSNPrintf(buf+len,256-len,"%5u",rootdata[i]);CHKERRQ(ierr); len += 5;}
344*c4762a1bSJed Brown     ierr = PetscSynchronizedPrintf(PETSC_COMM_WORLD,"%s\n",buf);CHKERRQ(ierr);
345*c4762a1bSJed Brown     ierr = PetscSynchronizedFlush(PETSC_COMM_WORLD,PETSC_STDOUT);CHKERRQ(ierr);
346*c4762a1bSJed Brown 
347*c4762a1bSJed Brown     ierr = PetscFree2(rootdata,leafdata);CHKERRQ(ierr);
348*c4762a1bSJed Brown   }
349*c4762a1bSJed Brown 
350*c4762a1bSJed Brown   if (test_degree) {
351*c4762a1bSJed Brown     const PetscInt *degree;
352*c4762a1bSJed Brown     ierr = PetscSFComputeDegreeBegin(sf,&degree);CHKERRQ(ierr);
353*c4762a1bSJed Brown     ierr = PetscSFComputeDegreeEnd(sf,&degree);CHKERRQ(ierr);
354*c4762a1bSJed Brown     ierr = PetscViewerASCIIPrintf(PETSC_VIEWER_STDOUT_WORLD,"## Root degrees\n");CHKERRQ(ierr);
355*c4762a1bSJed Brown     ierr = PetscIntView(nrootsalloc,degree,PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr);
356*c4762a1bSJed Brown   }
357*c4762a1bSJed Brown 
358*c4762a1bSJed Brown   if (test_fetchandop) {
359*c4762a1bSJed Brown     /* Cannot use text compare here because token ordering is not deterministic */
360*c4762a1bSJed Brown     PetscInt *leafdata,*leafupdate,*rootdata;
361*c4762a1bSJed Brown     ierr = PetscMalloc3(nleavesalloc,&leafdata,nleavesalloc,&leafupdate,nrootsalloc,&rootdata);CHKERRQ(ierr);
362*c4762a1bSJed Brown     for (i=0; i<nleavesalloc; i++) leafdata[i] = -1;
363*c4762a1bSJed Brown     for (i=0; i<nleaves; i++) leafdata[i*stride] = 1;
364*c4762a1bSJed Brown     for (i=0; i<nrootsalloc; i++) rootdata[i] = -1;
365*c4762a1bSJed Brown     for (i=0; i<nroots; i++) rootdata[i*stride] = 0;
366*c4762a1bSJed Brown     ierr = PetscSFFetchAndOpBegin(sf,MPIU_INT,rootdata,leafdata,leafupdate,mop);CHKERRQ(ierr);
367*c4762a1bSJed Brown     ierr = PetscSFFetchAndOpEnd(sf,MPIU_INT,rootdata,leafdata,leafupdate,mop);CHKERRQ(ierr);
368*c4762a1bSJed Brown     ierr = PetscViewerASCIIPrintf(PETSC_VIEWER_STDOUT_WORLD,"## Rootdata (sum of 1 from each leaf)\n");CHKERRQ(ierr);
369*c4762a1bSJed Brown     ierr = PetscIntView(nrootsalloc,rootdata,PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr);
370*c4762a1bSJed Brown     ierr = PetscViewerASCIIPrintf(PETSC_VIEWER_STDOUT_WORLD,"## Leafupdate (value at roots prior to my atomic update)\n");CHKERRQ(ierr);
371*c4762a1bSJed Brown     ierr = PetscIntView(nleavesalloc,leafupdate,PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr);
372*c4762a1bSJed Brown     ierr = PetscFree3(leafdata,leafupdate,rootdata);CHKERRQ(ierr);
373*c4762a1bSJed Brown   }
374*c4762a1bSJed Brown 
375*c4762a1bSJed Brown   if (test_gather) {
376*c4762a1bSJed Brown     const PetscInt *degree;
377*c4762a1bSJed Brown     PetscInt       inedges,*indata,*outdata;
378*c4762a1bSJed Brown     ierr = PetscSFComputeDegreeBegin(sf,&degree);CHKERRQ(ierr);
379*c4762a1bSJed Brown     ierr = PetscSFComputeDegreeEnd(sf,&degree);CHKERRQ(ierr);
380*c4762a1bSJed Brown     for (i=0,inedges=0; i<nrootsalloc; i++) inedges += degree[i];
381*c4762a1bSJed Brown     ierr = PetscMalloc2(inedges,&indata,nleavesalloc,&outdata);CHKERRQ(ierr);
382*c4762a1bSJed Brown     for (i=0; i<nleavesalloc; i++) outdata[i] = -1;
383*c4762a1bSJed Brown     for (i=0; i<nleaves; i++) outdata[i*stride] = 1000*(rank+1) + i;
384*c4762a1bSJed Brown     ierr = PetscSFGatherBegin(sf,MPIU_INT,outdata,indata);CHKERRQ(ierr);
385*c4762a1bSJed Brown     ierr = PetscSFGatherEnd(sf,MPIU_INT,outdata,indata);CHKERRQ(ierr);
386*c4762a1bSJed Brown     ierr = PetscViewerASCIIPrintf(PETSC_VIEWER_STDOUT_WORLD,"## Gathered data at multi-roots from leaves\n");CHKERRQ(ierr);
387*c4762a1bSJed Brown     ierr = PetscIntView(inedges,indata,PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr);
388*c4762a1bSJed Brown     ierr = PetscFree2(indata,outdata);CHKERRQ(ierr);
389*c4762a1bSJed Brown   }
390*c4762a1bSJed Brown 
391*c4762a1bSJed Brown   if (test_scatter) {
392*c4762a1bSJed Brown     const PetscInt *degree;
393*c4762a1bSJed Brown     PetscInt       j,count,inedges,*indata,*outdata;
394*c4762a1bSJed Brown     ierr = PetscSFComputeDegreeBegin(sf,&degree);CHKERRQ(ierr);
395*c4762a1bSJed Brown     ierr = PetscSFComputeDegreeEnd(sf,&degree);CHKERRQ(ierr);
396*c4762a1bSJed Brown     for (i=0,inedges=0; i<nrootsalloc; i++) inedges += degree[i];
397*c4762a1bSJed Brown     ierr = PetscMalloc2(inedges,&indata,nleavesalloc,&outdata);CHKERRQ(ierr);
398*c4762a1bSJed Brown     for (i=0; i<nleavesalloc; i++) outdata[i] = -1;
399*c4762a1bSJed Brown     for (i=0,count=0; i<nrootsalloc; i++) {
400*c4762a1bSJed Brown       for (j=0; j<degree[i]; j++) indata[count++] = 1000*(rank+1) + 100*i + j;
401*c4762a1bSJed Brown     }
402*c4762a1bSJed Brown     ierr = PetscViewerASCIIPrintf(PETSC_VIEWER_STDOUT_WORLD,"## Data at multi-roots, to scatter to leaves\n");CHKERRQ(ierr);
403*c4762a1bSJed Brown     ierr = PetscIntView(inedges,indata,PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr);
404*c4762a1bSJed Brown 
405*c4762a1bSJed Brown     ierr = PetscSFScatterBegin(sf,MPIU_INT,indata,outdata);CHKERRQ(ierr);
406*c4762a1bSJed Brown     ierr = PetscSFScatterEnd(sf,MPIU_INT,indata,outdata);CHKERRQ(ierr);
407*c4762a1bSJed Brown     ierr = PetscViewerASCIIPrintf(PETSC_VIEWER_STDOUT_WORLD,"## Scattered data at leaves\n");CHKERRQ(ierr);
408*c4762a1bSJed Brown     ierr = PetscIntView(nleavesalloc,outdata,PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr);
409*c4762a1bSJed Brown     ierr = PetscFree2(indata,outdata);CHKERRQ(ierr);
410*c4762a1bSJed Brown   }
411*c4762a1bSJed Brown 
412*c4762a1bSJed Brown   if (test_embed) {
413*c4762a1bSJed Brown     const PetscInt nroots = 1 + (PetscInt) !rank;
414*c4762a1bSJed Brown     PetscInt       selected[2];
415*c4762a1bSJed Brown     PetscSF        esf;
416*c4762a1bSJed Brown 
417*c4762a1bSJed Brown     selected[0] = stride;
418*c4762a1bSJed Brown     selected[1] = 2*stride;
419*c4762a1bSJed Brown     ierr = PetscSFCreateEmbeddedSF(sf,nroots,selected,&esf);CHKERRQ(ierr);
420*c4762a1bSJed Brown     ierr = PetscSFSetUp(esf);CHKERRQ(ierr);
421*c4762a1bSJed Brown     ierr = PetscViewerASCIIPrintf(PETSC_VIEWER_STDOUT_WORLD,"## Embedded PetscSF\n");CHKERRQ(ierr);
422*c4762a1bSJed Brown     ierr = PetscViewerPushFormat(PETSC_VIEWER_STDOUT_WORLD,PETSC_VIEWER_ASCII_INFO_DETAIL);CHKERRQ(ierr);
423*c4762a1bSJed Brown     ierr = PetscSFView(esf,PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr);
424*c4762a1bSJed Brown     ierr = PetscViewerPopFormat(PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr);
425*c4762a1bSJed Brown     ierr = PetscSFDestroy(&esf);CHKERRQ(ierr);
426*c4762a1bSJed Brown   }
427*c4762a1bSJed Brown 
428*c4762a1bSJed Brown   if (test_invert) {
429*c4762a1bSJed Brown     const PetscInt *degree;
430*c4762a1bSJed Brown     PetscInt *mRootsOrigNumbering;
431*c4762a1bSJed Brown     PetscInt inedges;
432*c4762a1bSJed Brown     PetscSF msf,imsf;
433*c4762a1bSJed Brown 
434*c4762a1bSJed Brown     ierr = PetscSFGetMultiSF(sf,&msf);CHKERRQ(ierr);
435*c4762a1bSJed Brown     ierr = PetscSFCreateInverseSF(msf,&imsf);CHKERRQ(ierr);
436*c4762a1bSJed Brown     ierr = PetscSFSetUp(msf);CHKERRQ(ierr);
437*c4762a1bSJed Brown     ierr = PetscSFSetUp(imsf);CHKERRQ(ierr);
438*c4762a1bSJed Brown     ierr = PetscViewerASCIIPrintf(PETSC_VIEWER_STDOUT_WORLD,"## Multi-SF\n");CHKERRQ(ierr);
439*c4762a1bSJed Brown     ierr = PetscSFView(msf,PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr);
440*c4762a1bSJed Brown     ierr = PetscViewerASCIIPrintf(PETSC_VIEWER_STDOUT_WORLD,"## Multi-SF roots indices in original SF roots numbering\n");CHKERRQ(ierr);
441*c4762a1bSJed Brown     ierr = PetscSFComputeDegreeBegin(sf,&degree);CHKERRQ(ierr);
442*c4762a1bSJed Brown     ierr = PetscSFComputeDegreeEnd(sf,&degree);CHKERRQ(ierr);
443*c4762a1bSJed Brown     ierr = PetscSFComputeMultiRootOriginalNumbering(sf,degree,&inedges,&mRootsOrigNumbering);CHKERRQ(ierr);
444*c4762a1bSJed Brown     ierr = PetscIntView(inedges,mRootsOrigNumbering,PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr);
445*c4762a1bSJed Brown     ierr = PetscViewerASCIIPrintf(PETSC_VIEWER_STDOUT_WORLD,"## Inverse of Multi-SF\n");CHKERRQ(ierr);
446*c4762a1bSJed Brown     ierr = PetscSFView(imsf,PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr);
447*c4762a1bSJed Brown     ierr = PetscViewerASCIIPrintf(PETSC_VIEWER_STDOUT_WORLD,"## Inverse of Multi-SF, original numbering\n");CHKERRQ(ierr);
448*c4762a1bSJed Brown     ierr = PetscSFViewCustomLocals_Private(imsf,mRootsOrigNumbering,PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr);
449*c4762a1bSJed Brown     ierr = PetscSFDestroy(&imsf);CHKERRQ(ierr);
450*c4762a1bSJed Brown     ierr = PetscFree(mRootsOrigNumbering);CHKERRQ(ierr);
451*c4762a1bSJed Brown   }
452*c4762a1bSJed Brown 
453*c4762a1bSJed Brown   /* Clean storage for star forest. */
454*c4762a1bSJed Brown   ierr = PetscSFDestroy(&sf);CHKERRQ(ierr);
455*c4762a1bSJed Brown   ierr = PetscFinalize();
456*c4762a1bSJed Brown   return ierr;
457*c4762a1bSJed Brown }
458*c4762a1bSJed Brown 
459*c4762a1bSJed Brown /*TEST
460*c4762a1bSJed Brown 
461*c4762a1bSJed Brown    test:
462*c4762a1bSJed Brown       nsize: 4
463*c4762a1bSJed Brown       filter: grep -v "type" | grep -v "sort"
464*c4762a1bSJed Brown       args: -test_bcast -sf_type window -sf_window_sync {{fence active lock}} -sf_window_flavor {{create dynamic allocate}}
465*c4762a1bSJed Brown       requires: define(PETSC_HAVE_MPI_ONE_SIDED)
466*c4762a1bSJed Brown 
467*c4762a1bSJed Brown 
468*c4762a1bSJed Brown    test:
469*c4762a1bSJed Brown       suffix: 2
470*c4762a1bSJed Brown       nsize: 4
471*c4762a1bSJed Brown       filter: grep -v "type" | grep -v "sort"
472*c4762a1bSJed Brown       args: -test_reduce -sf_type window -sf_window_sync {{fence active lock}} -sf_window_flavor {{create dynamic allocate}}
473*c4762a1bSJed Brown       requires: define(PETSC_HAVE_MPI_ONE_SIDED)
474*c4762a1bSJed Brown 
475*c4762a1bSJed Brown    test:
476*c4762a1bSJed Brown       suffix: 2_basic
477*c4762a1bSJed Brown       nsize: 4
478*c4762a1bSJed Brown       args: -test_reduce -sf_type basic
479*c4762a1bSJed Brown 
480*c4762a1bSJed Brown    test:
481*c4762a1bSJed Brown       suffix: 3
482*c4762a1bSJed Brown       nsize: 4
483*c4762a1bSJed Brown       filter: grep -v "type" | grep -v "sort"
484*c4762a1bSJed Brown       args: -test_degree -sf_type window -sf_window_sync {{fence active lock}} -sf_window_flavor {{create dynamic allocate}}
485*c4762a1bSJed Brown       requires: define(PETSC_HAVE_MPI_ONE_SIDED)
486*c4762a1bSJed Brown 
487*c4762a1bSJed Brown    test:
488*c4762a1bSJed Brown       suffix: 3_basic
489*c4762a1bSJed Brown       nsize: 4
490*c4762a1bSJed Brown       args: -test_degree -sf_type basic
491*c4762a1bSJed Brown 
492*c4762a1bSJed Brown    test:
493*c4762a1bSJed Brown       suffix: 4
494*c4762a1bSJed Brown       nsize: 4
495*c4762a1bSJed Brown       filter: grep -v "type" | grep -v "sort"
496*c4762a1bSJed Brown       args: -test_gather -sf_type window -sf_window_sync {{fence active lock}} -sf_window_flavor {{create dynamic allocate}}
497*c4762a1bSJed Brown       requires: define(PETSC_HAVE_MPI_ONE_SIDED)
498*c4762a1bSJed Brown 
499*c4762a1bSJed Brown    test:
500*c4762a1bSJed Brown       suffix: 4_basic
501*c4762a1bSJed Brown       nsize: 4
502*c4762a1bSJed Brown       args: -test_gather -sf_type basic
503*c4762a1bSJed Brown 
504*c4762a1bSJed Brown    test:
505*c4762a1bSJed Brown       suffix: 4_stride
506*c4762a1bSJed Brown       nsize: 4
507*c4762a1bSJed Brown       args: -test_gather -sf_type basic -stride 2
508*c4762a1bSJed Brown 
509*c4762a1bSJed Brown    test:
510*c4762a1bSJed Brown       suffix: 5
511*c4762a1bSJed Brown       nsize: 4
512*c4762a1bSJed Brown       filter: grep -v "type" | grep -v "sort"
513*c4762a1bSJed Brown       args: -test_scatter -sf_type window -sf_window_sync {{fence active lock}} -sf_window_flavor {{create dynamic allocate}}
514*c4762a1bSJed Brown       requires: define(PETSC_HAVE_MPI_ONE_SIDED)
515*c4762a1bSJed Brown 
516*c4762a1bSJed Brown    test:
517*c4762a1bSJed Brown       suffix: 5_basic
518*c4762a1bSJed Brown       nsize: 4
519*c4762a1bSJed Brown       args: -test_scatter -sf_type basic
520*c4762a1bSJed Brown 
521*c4762a1bSJed Brown    test:
522*c4762a1bSJed Brown       suffix: 5_stride
523*c4762a1bSJed Brown       nsize: 4
524*c4762a1bSJed Brown       args: -test_scatter -sf_type basic -stride 2
525*c4762a1bSJed Brown 
526*c4762a1bSJed Brown    test:
527*c4762a1bSJed Brown       suffix: 6
528*c4762a1bSJed Brown       nsize: 4
529*c4762a1bSJed Brown       filter: grep -v "type" | grep -v "sort"
530*c4762a1bSJed Brown       args: -test_embed -sf_type window -sf_window_sync {{fence active lock}} -sf_window_flavor {{create dynamic allocate}}
531*c4762a1bSJed Brown       requires: define(PETSC_HAVE_MPI_ONE_SIDED)
532*c4762a1bSJed Brown 
533*c4762a1bSJed Brown    test:
534*c4762a1bSJed Brown       suffix: 6_basic
535*c4762a1bSJed Brown       nsize: 4
536*c4762a1bSJed Brown       args: -test_embed -sf_type basic
537*c4762a1bSJed Brown 
538*c4762a1bSJed Brown    test:
539*c4762a1bSJed Brown       suffix: 7
540*c4762a1bSJed Brown       nsize: 4
541*c4762a1bSJed Brown       filter: grep -v "type" | grep -v "sort"
542*c4762a1bSJed Brown       args: -test_invert -sf_type window -sf_window_sync {{fence active lock}} -sf_window_flavor {{create dynamic allocate}}
543*c4762a1bSJed Brown       requires: define(PETSC_HAVE_MPI_ONE_SIDED)
544*c4762a1bSJed Brown 
545*c4762a1bSJed Brown    test:
546*c4762a1bSJed Brown       suffix: 7_basic
547*c4762a1bSJed Brown       nsize: 4
548*c4762a1bSJed Brown       args: -test_invert -sf_type basic
549*c4762a1bSJed Brown 
550*c4762a1bSJed Brown    test:
551*c4762a1bSJed Brown       suffix: basic
552*c4762a1bSJed Brown       nsize: 4
553*c4762a1bSJed Brown       args: -test_bcast -sf_type basic
554*c4762a1bSJed Brown       output_file: output/ex1_1_basic.out
555*c4762a1bSJed Brown 
556*c4762a1bSJed Brown    test:
557*c4762a1bSJed Brown       suffix: bcastop_basic
558*c4762a1bSJed Brown       nsize: 4
559*c4762a1bSJed Brown       args: -test_bcastop -sf_type basic
560*c4762a1bSJed Brown       output_file: output/ex1_bcastop_basic.out
561*c4762a1bSJed Brown 
562*c4762a1bSJed Brown    test:
563*c4762a1bSJed Brown       suffix: 8
564*c4762a1bSJed Brown       nsize: 3
565*c4762a1bSJed Brown       filter: grep -v "type" | grep -v "sort"
566*c4762a1bSJed Brown       args: -test_bcast -test_sf_distribute -sf_type window -sf_window_sync {{fence active lock}} -sf_window_flavor {{create dynamic allocate}}
567*c4762a1bSJed Brown       requires: define(PETSC_HAVE_MPI_ONE_SIDED)
568*c4762a1bSJed Brown 
569*c4762a1bSJed Brown    test:
570*c4762a1bSJed Brown       suffix: 8_basic
571*c4762a1bSJed Brown       nsize: 3
572*c4762a1bSJed Brown       args: -test_bcast -test_sf_distribute -sf_type basic
573*c4762a1bSJed Brown 
574*c4762a1bSJed Brown    test:
575*c4762a1bSJed Brown       suffix: 9_char
576*c4762a1bSJed Brown       nsize: 4
577*c4762a1bSJed Brown       args: -sf_type basic -test_bcast -test_reduce -test_op max -test_char
578*c4762a1bSJed Brown 
579*c4762a1bSJed Brown    # Here we do not test -sf_window_flavor dynamic since it is designed for repeated SFs with few different rootdata pointers
580*c4762a1bSJed Brown    test:
581*c4762a1bSJed Brown       suffix: 10
582*c4762a1bSJed Brown       filter: grep -v "type" | grep -v "sort"
583*c4762a1bSJed Brown       nsize: 4
584*c4762a1bSJed Brown       args: -sf_type window -sf_window_sync {{fence active lock}} -sf_window_flavor {{create allocate}} -test_all -test_bcastop 0 -test_fetchandop 0
585*c4762a1bSJed Brown       requires: define(PETSC_HAVE_MPI_ONE_SIDED)
586*c4762a1bSJed Brown 
587*c4762a1bSJed Brown    # The nightly test suite with MPICH uses ch3:sock, which is broken when winsize == 0 in some of the processes
588*c4762a1bSJed Brown    test:
589*c4762a1bSJed Brown       suffix: 10_shared
590*c4762a1bSJed Brown       output_file: output/ex1_10.out
591*c4762a1bSJed Brown       filter: grep -v "type" | grep -v "sort"
592*c4762a1bSJed Brown       nsize: 4
593*c4762a1bSJed Brown       args: -sf_type window -sf_window_sync {{fence active lock}} -sf_window_flavor shared -test_all -test_bcastop 0 -test_fetchandop 0
594*c4762a1bSJed Brown       requires: define(PETSC_HAVE_MPI_PROCESS_SHARED_MEMORY) !define(PETSC_HAVE_MPICH_NUMVERSION) define(PETSC_HAVE_MPI_ONE_SIDED)
595*c4762a1bSJed Brown 
596*c4762a1bSJed Brown    test:
597*c4762a1bSJed Brown       suffix: 10_basic
598*c4762a1bSJed Brown       nsize: 4
599*c4762a1bSJed Brown       args: -sf_type basic -test_all -test_bcastop 0 -test_fetchandop 0
600*c4762a1bSJed Brown 
601*c4762a1bSJed Brown TEST*/
602