xref: /petsc/src/vec/is/sf/impls/window/sfwindow.c (revision 5b0d146a4c27a34a26fabb00e248697b7b651ba6)
1af0996ceSBarry Smith #include <petsc/private/sfimpl.h> /*I "petscsf.h" I*/
295fce210SBarry Smith 
395fce210SBarry Smith typedef struct _n_PetscSFDataLink *PetscSFDataLink;
495fce210SBarry Smith typedef struct _n_PetscSFWinLink  *PetscSFWinLink;
595fce210SBarry Smith 
695fce210SBarry Smith typedef struct {
795fce210SBarry Smith   PetscSFWindowSyncType   sync;   /* FENCE, LOCK, or ACTIVE synchronization */
8*5b0d146aSStefano Zampini   PetscSFDataLink         link;   /* List of MPI data types, lazily constructed for each data type */
995fce210SBarry Smith   PetscSFWinLink          wins;   /* List of active windows */
10*5b0d146aSStefano Zampini   PetscSFWindowFlavorType flavor; /* Current PETSCSF_WINDOW_FLAVOR_ */
11*5b0d146aSStefano Zampini   PetscSF                 dynsf;
12*5b0d146aSStefano Zampini   MPI_Info                info;
1395fce210SBarry Smith } PetscSF_Window;
1495fce210SBarry Smith 
1595fce210SBarry Smith struct _n_PetscSFDataLink {
1695fce210SBarry Smith   MPI_Datatype    unit;
1795fce210SBarry Smith   MPI_Datatype    *mine;
1895fce210SBarry Smith   MPI_Datatype    *remote;
1995fce210SBarry Smith   PetscSFDataLink next;
2095fce210SBarry Smith };
2195fce210SBarry Smith 
2295fce210SBarry Smith struct _n_PetscSFWinLink {
2395fce210SBarry Smith   PetscBool               inuse;
2495fce210SBarry Smith   size_t                  bytes;
2595fce210SBarry Smith   void                    *addr;
26*5b0d146aSStefano Zampini   void                    *paddr;
2795fce210SBarry Smith   MPI_Win                 win;
28*5b0d146aSStefano Zampini   PetscSFWindowFlavorType flavor;
29*5b0d146aSStefano Zampini   MPI_Aint                *dyn_target_addr;
3095fce210SBarry Smith   PetscBool               epoch;
3195fce210SBarry Smith   PetscSFWinLink          next;
3295fce210SBarry Smith };
3395fce210SBarry Smith 
3495fce210SBarry Smith const char *const PetscSFWindowSyncTypes[] = {"FENCE","LOCK","ACTIVE","PetscSFWindowSyncType","PETSCSF_WINDOW_SYNC_",0};
35*5b0d146aSStefano Zampini const char *const PetscSFWindowFlavorTypes[] = {"CREATE","DYNAMIC","ALLOCATE","SHARED","PetscSFWindowFlavorType","PETSCSF_WINDOW_FLAVOR_",0};
3695fce210SBarry Smith 
37b2566f29SBarry Smith /* Built-in MPI_Ops act elementwise inside MPI_Accumulate, but cannot be used with composite types inside collectives (MPIU_Allreduce) */
3895fce210SBarry Smith static PetscErrorCode PetscSFWindowOpTranslate(MPI_Op *op)
3995fce210SBarry Smith {
4095fce210SBarry Smith   PetscFunctionBegin;
4195fce210SBarry Smith   if (*op == MPIU_SUM) *op = MPI_SUM;
4295fce210SBarry Smith   else if (*op == MPIU_MAX) *op = MPI_MAX;
4395fce210SBarry Smith   else if (*op == MPIU_MIN) *op = MPI_MIN;
4495fce210SBarry Smith   PetscFunctionReturn(0);
4595fce210SBarry Smith }
4695fce210SBarry Smith 
4795fce210SBarry Smith /*@C
4895fce210SBarry Smith    PetscSFWindowGetDataTypes - gets composite local and remote data types for each rank
4995fce210SBarry Smith 
5095fce210SBarry Smith    Not Collective
5195fce210SBarry Smith 
5295fce210SBarry Smith    Input Arguments:
5395fce210SBarry Smith +  sf - star forest
5495fce210SBarry Smith -  unit - data type for each node
5595fce210SBarry Smith 
5695fce210SBarry Smith    Output Arguments:
5795fce210SBarry Smith +  localtypes - types describing part of local leaf buffer referencing each remote rank
5895fce210SBarry Smith -  remotetypes - types describing part of remote root buffer referenced for each remote rank
5995fce210SBarry Smith 
6095fce210SBarry Smith    Level: developer
6195fce210SBarry Smith 
6295fce210SBarry Smith .seealso: PetscSFSetGraph(), PetscSFView()
6395fce210SBarry Smith @*/
6495fce210SBarry Smith static PetscErrorCode PetscSFWindowGetDataTypes(PetscSF sf,MPI_Datatype unit,const MPI_Datatype **localtypes,const MPI_Datatype **remotetypes)
6595fce210SBarry Smith {
6695fce210SBarry Smith   PetscSF_Window    *w = (PetscSF_Window*)sf->data;
6795fce210SBarry Smith   PetscErrorCode    ierr;
6895fce210SBarry Smith   PetscSFDataLink   link;
6995fce210SBarry Smith   PetscInt          i,nranks;
7095fce210SBarry Smith   const PetscInt    *roffset,*rmine,*rremote;
7195fce210SBarry Smith   const PetscMPIInt *ranks;
7295fce210SBarry Smith 
7395fce210SBarry Smith   PetscFunctionBegin;
7495fce210SBarry Smith   /* Look for types in cache */
7595fce210SBarry Smith   for (link=w->link; link; link=link->next) {
7695fce210SBarry Smith     PetscBool match;
7795fce210SBarry Smith     ierr = MPIPetsc_Type_compare(unit,link->unit,&match);CHKERRQ(ierr);
7895fce210SBarry Smith     if (match) {
7995fce210SBarry Smith       *localtypes  = link->mine;
8095fce210SBarry Smith       *remotetypes = link->remote;
8195fce210SBarry Smith       PetscFunctionReturn(0);
8295fce210SBarry Smith     }
8395fce210SBarry Smith   }
8495fce210SBarry Smith 
8595fce210SBarry Smith   /* Create new composite types for each send rank */
86dec1416fSJunchao Zhang   ierr = PetscSFGetRootRanks(sf,&nranks,&ranks,&roffset,&rmine,&rremote);CHKERRQ(ierr);
8795dccacaSBarry Smith   ierr = PetscNew(&link);CHKERRQ(ierr);
8895fce210SBarry Smith   ierr = MPI_Type_dup(unit,&link->unit);CHKERRQ(ierr);
89dcca6d9dSJed Brown   ierr = PetscMalloc2(nranks,&link->mine,nranks,&link->remote);CHKERRQ(ierr);
9095fce210SBarry Smith   for (i=0; i<nranks; i++) {
91*5b0d146aSStefano Zampini     PetscInt    rcount = roffset[i+1] - roffset[i];
9295fce210SBarry Smith     PetscMPIInt *rmine,*rremote;
9395fce210SBarry Smith #if !defined(PETSC_USE_64BIT_INDICES)
9495fce210SBarry Smith     rmine   = sf->rmine + sf->roffset[i];
9595fce210SBarry Smith     rremote = sf->rremote + sf->roffset[i];
9695fce210SBarry Smith #else
9795fce210SBarry Smith     PetscInt j;
98dcca6d9dSJed Brown     ierr = PetscMalloc2(rcount,&rmine,rcount,&rremote);CHKERRQ(ierr);
9995fce210SBarry Smith     for (j=0; j<rcount; j++) {
10095fce210SBarry Smith       ierr = PetscMPIIntCast(sf->rmine[sf->roffset[i]+j],rmine+j);CHKERRQ(ierr);
10195fce210SBarry Smith       ierr = PetscMPIIntCast(sf->rremote[sf->roffset[i]+j],rremote+j);CHKERRQ(ierr);
10295fce210SBarry Smith     }
10395fce210SBarry Smith #endif
104*5b0d146aSStefano Zampini 
10595fce210SBarry Smith     ierr = MPI_Type_create_indexed_block(rcount,1,rmine,link->unit,&link->mine[i]);CHKERRQ(ierr);
10695fce210SBarry Smith     ierr = MPI_Type_create_indexed_block(rcount,1,rremote,link->unit,&link->remote[i]);CHKERRQ(ierr);
10795fce210SBarry Smith #if defined(PETSC_USE_64BIT_INDICES)
10895fce210SBarry Smith     ierr = PetscFree2(rmine,rremote);CHKERRQ(ierr);
10995fce210SBarry Smith #endif
11095fce210SBarry Smith     ierr = MPI_Type_commit(&link->mine[i]);CHKERRQ(ierr);
11195fce210SBarry Smith     ierr = MPI_Type_commit(&link->remote[i]);CHKERRQ(ierr);
11295fce210SBarry Smith   }
11395fce210SBarry Smith   link->next = w->link;
11495fce210SBarry Smith   w->link    = link;
11595fce210SBarry Smith 
11695fce210SBarry Smith   *localtypes  = link->mine;
11795fce210SBarry Smith   *remotetypes = link->remote;
11895fce210SBarry Smith   PetscFunctionReturn(0);
11995fce210SBarry Smith }
12095fce210SBarry Smith 
12195fce210SBarry Smith /*@C
122*5b0d146aSStefano Zampini    PetscSFWindowSetFlavorType - Set flavor type for MPI_Win creation
123*5b0d146aSStefano Zampini 
124*5b0d146aSStefano Zampini    Logically Collective
125*5b0d146aSStefano Zampini 
126*5b0d146aSStefano Zampini    Input Arguments:
127*5b0d146aSStefano Zampini +  sf - star forest for communication
128*5b0d146aSStefano Zampini -  flavor - flavor type
129*5b0d146aSStefano Zampini 
130*5b0d146aSStefano Zampini    Options Database Key:
131*5b0d146aSStefano Zampini .  -sf_window_flavor <flavor> - sets the flavor type CREATE, DYNAMIC, ALLOCATE or SHARED (see PetscSFWindowFlavorType)
132*5b0d146aSStefano Zampini 
133*5b0d146aSStefano Zampini    Level: advanced
134*5b0d146aSStefano Zampini 
135*5b0d146aSStefano Zampini    Notes: Windows reusage follow this rules:
136*5b0d146aSStefano Zampini 
137*5b0d146aSStefano Zampini      PETSCSF_WINDOW_FLAVOR_CREATE: creates a new window every time, uses MPI_Win_create
138*5b0d146aSStefano Zampini 
139*5b0d146aSStefano Zampini      PETSCSF_WINDOW_FLAVOR_DYNAMIC: uses MPI_Win_create_dynamic/MPI_Win_attach and tries to reuse windows by comparing the root array. Intended to be used on repeated applications of the same SF, e.g.
140*5b0d146aSStefano Zampini        for i=1 to K
141*5b0d146aSStefano Zampini          PetscSFOperationBegin(rootdata1,leafdata_whatever);
142*5b0d146aSStefano Zampini          PetscSFOperationEnd(rootdata1,leafdata_whatever);
143*5b0d146aSStefano Zampini          ...
144*5b0d146aSStefano Zampini          PetscSFOperationBegin(rootdataN,leafdata_whatever);
145*5b0d146aSStefano Zampini          PetscSFOperationEnd(rootdataN,leafdata_whatever);
146*5b0d146aSStefano Zampini        endfor
147*5b0d146aSStefano Zampini        The following pattern will instead raise an error
148*5b0d146aSStefano Zampini          PetscSFOperationBegin(rootdata1,leafdata_whatever);
149*5b0d146aSStefano Zampini          PetscSFOperationEnd(rootdata1,leafdata_whatever);
150*5b0d146aSStefano Zampini          PetscSFOperationBegin(rank ? rootdata1 : rootdata2,leafdata_whatever);
151*5b0d146aSStefano Zampini          PetscSFOperationEnd(rank ? rootdata1 : rootdata2,leafdata_whatever);
152*5b0d146aSStefano Zampini 
153*5b0d146aSStefano Zampini      PETSCSF_WINDOW_FLAVOR_ALLOCATE: uses MPI_Win_allocate, reuses any pre-existing window which fits the data and it is not in use
154*5b0d146aSStefano Zampini 
155*5b0d146aSStefano Zampini      PETSCSF_WINDOW_FLAVOR_SHARED: uses MPI_Win_allocate_shared, reusage policy as for PETSCSF_WINDOW_FLAVOR_ALLOCATE
156*5b0d146aSStefano Zampini 
157*5b0d146aSStefano Zampini .seealso: PetscSFSetFromOptions(), PetscSFWindowGetFlavorType()
158*5b0d146aSStefano Zampini @*/
159*5b0d146aSStefano Zampini PetscErrorCode PetscSFWindowSetFlavorType(PetscSF sf,PetscSFWindowFlavorType flavor)
160*5b0d146aSStefano Zampini {
161*5b0d146aSStefano Zampini   PetscErrorCode ierr;
162*5b0d146aSStefano Zampini 
163*5b0d146aSStefano Zampini   PetscFunctionBegin;
164*5b0d146aSStefano Zampini   PetscValidHeaderSpecific(sf,PETSCSF_CLASSID,1);
165*5b0d146aSStefano Zampini   PetscValidLogicalCollectiveEnum(sf,flavor,2);
166*5b0d146aSStefano Zampini   ierr = PetscTryMethod(sf,"PetscSFWindowSetFlavorType_C",(PetscSF,PetscSFWindowFlavorType),(sf,flavor));CHKERRQ(ierr);
167*5b0d146aSStefano Zampini   PetscFunctionReturn(0);
168*5b0d146aSStefano Zampini }
169*5b0d146aSStefano Zampini 
170*5b0d146aSStefano Zampini static PetscErrorCode PetscSFWindowSetFlavorType_Window(PetscSF sf,PetscSFWindowFlavorType flavor)
171*5b0d146aSStefano Zampini {
172*5b0d146aSStefano Zampini   PetscSF_Window *w = (PetscSF_Window*)sf->data;
173*5b0d146aSStefano Zampini 
174*5b0d146aSStefano Zampini   PetscFunctionBegin;
175*5b0d146aSStefano Zampini   w->flavor = flavor;
176*5b0d146aSStefano Zampini   PetscFunctionReturn(0);
177*5b0d146aSStefano Zampini }
178*5b0d146aSStefano Zampini 
179*5b0d146aSStefano Zampini /*@C
180*5b0d146aSStefano Zampini    PetscSFWindowGetFlavorType - Get flavor type for PetscSF communication
181*5b0d146aSStefano Zampini 
182*5b0d146aSStefano Zampini    Logically Collective
183*5b0d146aSStefano Zampini 
184*5b0d146aSStefano Zampini    Input Argument:
185*5b0d146aSStefano Zampini .  sf - star forest for communication
186*5b0d146aSStefano Zampini 
187*5b0d146aSStefano Zampini    Output Argument:
188*5b0d146aSStefano Zampini .  flavor - flavor type
189*5b0d146aSStefano Zampini 
190*5b0d146aSStefano Zampini    Level: advanced
191*5b0d146aSStefano Zampini 
192*5b0d146aSStefano Zampini .seealso: PetscSFSetFromOptions(), PetscSFWindowSetFlavorType()
193*5b0d146aSStefano Zampini @*/
194*5b0d146aSStefano Zampini PetscErrorCode PetscSFWindowGetFlavorType(PetscSF sf,PetscSFWindowFlavorType *flavor)
195*5b0d146aSStefano Zampini {
196*5b0d146aSStefano Zampini   PetscErrorCode ierr;
197*5b0d146aSStefano Zampini 
198*5b0d146aSStefano Zampini   PetscFunctionBegin;
199*5b0d146aSStefano Zampini   PetscValidHeaderSpecific(sf,PETSCSF_CLASSID,1);
200*5b0d146aSStefano Zampini   PetscValidPointer(flavor,2);
201*5b0d146aSStefano Zampini   ierr = PetscUseMethod(sf,"PetscSFWindowGetFlavorType_C",(PetscSF,PetscSFWindowFlavorType*),(sf,flavor));CHKERRQ(ierr);
202*5b0d146aSStefano Zampini   PetscFunctionReturn(0);
203*5b0d146aSStefano Zampini }
204*5b0d146aSStefano Zampini 
205*5b0d146aSStefano Zampini static PetscErrorCode PetscSFWindowGetFlavorType_Window(PetscSF sf,PetscSFWindowFlavorType *flavor)
206*5b0d146aSStefano Zampini {
207*5b0d146aSStefano Zampini   PetscSF_Window *w = (PetscSF_Window*)sf->data;
208*5b0d146aSStefano Zampini 
209*5b0d146aSStefano Zampini   PetscFunctionBegin;
210*5b0d146aSStefano Zampini   *flavor = w->flavor;
211*5b0d146aSStefano Zampini   PetscFunctionReturn(0);
212*5b0d146aSStefano Zampini }
213*5b0d146aSStefano Zampini 
214*5b0d146aSStefano Zampini /*@C
215*5b0d146aSStefano Zampini    PetscSFWindowSetSyncType - Set synchronization type for PetscSF communication
21695fce210SBarry Smith 
21795fce210SBarry Smith    Logically Collective
21895fce210SBarry Smith 
21995fce210SBarry Smith    Input Arguments:
22095fce210SBarry Smith +  sf - star forest for communication
22195fce210SBarry Smith -  sync - synchronization type
22295fce210SBarry Smith 
22395fce210SBarry Smith    Options Database Key:
22460263706SJed Brown .  -sf_window_sync <sync> - sets the synchronization type FENCE, LOCK, or ACTIVE (see PetscSFWindowSyncType)
22595fce210SBarry Smith 
22695fce210SBarry Smith    Level: advanced
22795fce210SBarry Smith 
22895fce210SBarry Smith .seealso: PetscSFSetFromOptions(), PetscSFWindowGetSyncType()
22995fce210SBarry Smith @*/
23095fce210SBarry Smith PetscErrorCode PetscSFWindowSetSyncType(PetscSF sf,PetscSFWindowSyncType sync)
23195fce210SBarry Smith {
23295fce210SBarry Smith   PetscErrorCode ierr;
23395fce210SBarry Smith 
23495fce210SBarry Smith   PetscFunctionBegin;
23595fce210SBarry Smith   PetscValidHeaderSpecific(sf,PETSCSF_CLASSID,1);
23695fce210SBarry Smith   PetscValidLogicalCollectiveEnum(sf,sync,2);
237*5b0d146aSStefano Zampini   ierr = PetscTryMethod(sf,"PetscSFWindowSetSyncType_C",(PetscSF,PetscSFWindowSyncType),(sf,sync));CHKERRQ(ierr);
23895fce210SBarry Smith   PetscFunctionReturn(0);
23995fce210SBarry Smith }
24095fce210SBarry Smith 
241f7a08781SBarry Smith static PetscErrorCode PetscSFWindowSetSyncType_Window(PetscSF sf,PetscSFWindowSyncType sync)
24295fce210SBarry Smith {
24395fce210SBarry Smith   PetscSF_Window *w = (PetscSF_Window*)sf->data;
24495fce210SBarry Smith 
24595fce210SBarry Smith   PetscFunctionBegin;
24695fce210SBarry Smith   w->sync = sync;
24795fce210SBarry Smith   PetscFunctionReturn(0);
24895fce210SBarry Smith }
24995fce210SBarry Smith 
25095fce210SBarry Smith /*@C
251*5b0d146aSStefano Zampini    PetscSFWindowGetSyncType - Get synchronization type for PetscSF communication
25295fce210SBarry Smith 
25395fce210SBarry Smith    Logically Collective
25495fce210SBarry Smith 
25595fce210SBarry Smith    Input Argument:
25695fce210SBarry Smith .  sf - star forest for communication
25795fce210SBarry Smith 
25895fce210SBarry Smith    Output Argument:
25995fce210SBarry Smith .  sync - synchronization type
26095fce210SBarry Smith 
26195fce210SBarry Smith    Level: advanced
26295fce210SBarry Smith 
263*5b0d146aSStefano Zampini .seealso: PetscSFSetFromOptions(), PetscSFWindowSetSyncType()
26495fce210SBarry Smith @*/
26595fce210SBarry Smith PetscErrorCode PetscSFWindowGetSyncType(PetscSF sf,PetscSFWindowSyncType *sync)
26695fce210SBarry Smith {
26795fce210SBarry Smith   PetscErrorCode ierr;
26895fce210SBarry Smith 
26995fce210SBarry Smith   PetscFunctionBegin;
27095fce210SBarry Smith   PetscValidHeaderSpecific(sf,PETSCSF_CLASSID,1);
27195fce210SBarry Smith   PetscValidPointer(sync,2);
272163d334eSBarry Smith   ierr = PetscUseMethod(sf,"PetscSFWindowGetSyncType_C",(PetscSF,PetscSFWindowSyncType*),(sf,sync));CHKERRQ(ierr);
27395fce210SBarry Smith   PetscFunctionReturn(0);
27495fce210SBarry Smith }
27595fce210SBarry Smith 
276f7a08781SBarry Smith static PetscErrorCode PetscSFWindowGetSyncType_Window(PetscSF sf,PetscSFWindowSyncType *sync)
27795fce210SBarry Smith {
27895fce210SBarry Smith   PetscSF_Window *w = (PetscSF_Window*)sf->data;
27995fce210SBarry Smith 
28095fce210SBarry Smith   PetscFunctionBegin;
28195fce210SBarry Smith   *sync = w->sync;
28295fce210SBarry Smith   PetscFunctionReturn(0);
28395fce210SBarry Smith }
28495fce210SBarry Smith 
28595fce210SBarry Smith /*@C
286*5b0d146aSStefano Zampini    PetscSFWindowSetInfo - Set the MPI_Info handle that will be used for subsequent windows allocation
287*5b0d146aSStefano Zampini 
288*5b0d146aSStefano Zampini    Logically Collective
289*5b0d146aSStefano Zampini 
290*5b0d146aSStefano Zampini    Input Argument:
291*5b0d146aSStefano Zampini +  sf - star forest for communication
292*5b0d146aSStefano Zampini -  info - MPI_Info handle
293*5b0d146aSStefano Zampini 
294*5b0d146aSStefano Zampini    Level: advanced
295*5b0d146aSStefano Zampini 
296*5b0d146aSStefano Zampini    Notes: the info handle is duplicated with a call to MPI_Info_dup unless info = MPI_INFO_NULL.
297*5b0d146aSStefano Zampini 
298*5b0d146aSStefano Zampini .seealso: PetscSFSetFromOptions(), PetscSFWindowGetInfo()
299*5b0d146aSStefano Zampini @*/
300*5b0d146aSStefano Zampini PetscErrorCode PetscSFWindowSetInfo(PetscSF sf,MPI_Info info)
301*5b0d146aSStefano Zampini {
302*5b0d146aSStefano Zampini   PetscErrorCode ierr;
303*5b0d146aSStefano Zampini 
304*5b0d146aSStefano Zampini   PetscFunctionBegin;
305*5b0d146aSStefano Zampini   PetscValidHeaderSpecific(sf,PETSCSF_CLASSID,1);
306*5b0d146aSStefano Zampini   ierr = PetscTryMethod(sf,"PetscSFWindowSetInfo_C",(PetscSF,MPI_Info),(sf,info));CHKERRQ(ierr);
307*5b0d146aSStefano Zampini   PetscFunctionReturn(0);
308*5b0d146aSStefano Zampini }
309*5b0d146aSStefano Zampini 
310*5b0d146aSStefano Zampini static PetscErrorCode PetscSFWindowSetInfo_Window(PetscSF sf,MPI_Info info)
311*5b0d146aSStefano Zampini {
312*5b0d146aSStefano Zampini   PetscSF_Window *w = (PetscSF_Window*)sf->data;
313*5b0d146aSStefano Zampini   PetscErrorCode ierr;
314*5b0d146aSStefano Zampini 
315*5b0d146aSStefano Zampini   PetscFunctionBegin;
316*5b0d146aSStefano Zampini   if (w->info != MPI_INFO_NULL) {
317*5b0d146aSStefano Zampini     ierr = MPI_Info_free(&w->info);CHKERRQ(ierr);
318*5b0d146aSStefano Zampini   }
319*5b0d146aSStefano Zampini   if (info != MPI_INFO_NULL) {
320*5b0d146aSStefano Zampini     ierr = MPI_Info_dup(info,&w->info);CHKERRQ(ierr);
321*5b0d146aSStefano Zampini   }
322*5b0d146aSStefano Zampini   PetscFunctionReturn(0);
323*5b0d146aSStefano Zampini }
324*5b0d146aSStefano Zampini 
325*5b0d146aSStefano Zampini /*@C
326*5b0d146aSStefano Zampini    PetscSFWindowGetInfo - Get the MPI_Info handle used for windows allocation
327*5b0d146aSStefano Zampini 
328*5b0d146aSStefano Zampini    Logically Collective
329*5b0d146aSStefano Zampini 
330*5b0d146aSStefano Zampini    Input Argument:
331*5b0d146aSStefano Zampini .  sf - star forest for communication
332*5b0d146aSStefano Zampini 
333*5b0d146aSStefano Zampini    Output Argument:
334*5b0d146aSStefano Zampini .  info - MPI_Info handle
335*5b0d146aSStefano Zampini 
336*5b0d146aSStefano Zampini    Level: advanced
337*5b0d146aSStefano Zampini 
338*5b0d146aSStefano Zampini    Notes: if PetscSFWindowSetInfo() has not be called, this returns MPI_INFO_NULL
339*5b0d146aSStefano Zampini 
340*5b0d146aSStefano Zampini .seealso: PetscSFSetFromOptions(), PetscSFWindowSetInfo()
341*5b0d146aSStefano Zampini @*/
342*5b0d146aSStefano Zampini PetscErrorCode PetscSFWindowGetInfo(PetscSF sf,MPI_Info *info)
343*5b0d146aSStefano Zampini {
344*5b0d146aSStefano Zampini   PetscErrorCode ierr;
345*5b0d146aSStefano Zampini 
346*5b0d146aSStefano Zampini   PetscFunctionBegin;
347*5b0d146aSStefano Zampini   PetscValidHeaderSpecific(sf,PETSCSF_CLASSID,1);
348*5b0d146aSStefano Zampini   PetscValidPointer(info,2);
349*5b0d146aSStefano Zampini   ierr = PetscUseMethod(sf,"PetscSFWindowGetInfo_C",(PetscSF,MPI_Info*),(sf,info));CHKERRQ(ierr);
350*5b0d146aSStefano Zampini   PetscFunctionReturn(0);
351*5b0d146aSStefano Zampini }
352*5b0d146aSStefano Zampini 
353*5b0d146aSStefano Zampini static PetscErrorCode PetscSFWindowGetInfo_Window(PetscSF sf,MPI_Info *info)
354*5b0d146aSStefano Zampini {
355*5b0d146aSStefano Zampini   PetscSF_Window *w = (PetscSF_Window*)sf->data;
356*5b0d146aSStefano Zampini 
357*5b0d146aSStefano Zampini   PetscFunctionBegin;
358*5b0d146aSStefano Zampini   *info = w->info;
359*5b0d146aSStefano Zampini   PetscFunctionReturn(0);
360*5b0d146aSStefano Zampini }
361*5b0d146aSStefano Zampini 
362*5b0d146aSStefano Zampini /*
36395fce210SBarry Smith    PetscSFGetWindow - Get a window for use with a given data type
36495fce210SBarry Smith 
36595fce210SBarry Smith    Collective on PetscSF
36695fce210SBarry Smith 
36795fce210SBarry Smith    Input Arguments:
36895fce210SBarry Smith +  sf - star forest
36995fce210SBarry Smith .  unit - data type
37095fce210SBarry Smith .  array - array to be sent
371*5b0d146aSStefano Zampini .  sync - type of synchronization PetscSFWindowSyncType
37295fce210SBarry Smith .  epoch - PETSC_TRUE to acquire the window and start an epoch, PETSC_FALSE to just acquire the window
373*5b0d146aSStefano Zampini .  fenceassert - assert parameter for call to MPI_Win_fence(), if sync == PETSCSF_WINDOW_SYNC_FENCE
374*5b0d146aSStefano Zampini .  postassert - assert parameter for call to MPI_Win_post(), if sync == PETSCSF_WINDOW_SYNC_ACTIVE
375*5b0d146aSStefano Zampini .  startassert - assert parameter for call to MPI_Win_start(), if sync == PETSCSF_WINDOW_SYNC_ACTIVE
376*5b0d146aSStefano Zampini -  target_disp - target_disp argument to RMA calls (significative for PETSCSF_WINDOW_FLAVOR_DYNAMIC flavor only)
37795fce210SBarry Smith 
37895fce210SBarry Smith    Output Arguments:
37995fce210SBarry Smith .  win - window
38095fce210SBarry Smith 
38195fce210SBarry Smith    Level: developer
382dec1416fSJunchao Zhang .seealso: PetscSFGetRootRanks(), PetscSFWindowGetDataTypes()
383*5b0d146aSStefano Zampini */
384*5b0d146aSStefano Zampini static PetscErrorCode PetscSFGetWindow(PetscSF sf,MPI_Datatype unit,void *array,PetscSFWindowSyncType sync,PetscBool epoch,PetscMPIInt fenceassert,PetscMPIInt postassert,PetscMPIInt startassert,const MPI_Aint **target_disp, MPI_Win *win)
38595fce210SBarry Smith {
38695fce210SBarry Smith   PetscSF_Window *w = (PetscSF_Window*)sf->data;
38795fce210SBarry Smith   PetscErrorCode ierr;
38895fce210SBarry Smith   MPI_Aint       lb,lb_true,bytes,bytes_true;
38995fce210SBarry Smith   PetscSFWinLink link;
390*5b0d146aSStefano Zampini   MPI_Aint       winaddr;
391*5b0d146aSStefano Zampini   PetscInt       nranks;
392*5b0d146aSStefano Zampini   PetscBool      reuse = PETSC_FALSE, update = PETSC_FALSE;
393*5b0d146aSStefano Zampini #if defined(PETSC_USE_DEBUG)
394*5b0d146aSStefano Zampini   PetscBool      dummy[2];
395*5b0d146aSStefano Zampini #endif
396*5b0d146aSStefano Zampini   MPI_Aint       wsize;
39795fce210SBarry Smith 
39895fce210SBarry Smith   PetscFunctionBegin;
39995fce210SBarry Smith   ierr = MPI_Type_get_extent(unit,&lb,&bytes);CHKERRQ(ierr);
40095fce210SBarry Smith   ierr = MPI_Type_get_true_extent(unit,&lb_true,&bytes_true);CHKERRQ(ierr);
40195fce210SBarry Smith   if (lb != 0 || lb_true != 0) SETERRQ(PetscObjectComm((PetscObject)sf),PETSC_ERR_SUP,"No support for unit type with nonzero lower bound, write petsc-maint@mcs.anl.gov if you want this feature");
40295fce210SBarry Smith   if (bytes != bytes_true) SETERRQ(PetscObjectComm((PetscObject)sf),PETSC_ERR_SUP,"No support for unit type with modified extent, write petsc-maint@mcs.anl.gov if you want this feature");
403*5b0d146aSStefano Zampini   if (w->flavor != PETSCSF_WINDOW_FLAVOR_CREATE) reuse = PETSC_TRUE;
404*5b0d146aSStefano Zampini   for (link=w->wins; reuse && link; link=link->next) {
405*5b0d146aSStefano Zampini     PetscBool winok = PETSC_FALSE;
406*5b0d146aSStefano Zampini     if (w->flavor != link->flavor) continue;
407*5b0d146aSStefano Zampini     switch (w->flavor) {
408*5b0d146aSStefano Zampini     case PETSCSF_WINDOW_FLAVOR_DYNAMIC: /* check available matching array, error if in use (we additionally check that the matching condition is the same across processes) */
409*5b0d146aSStefano Zampini       if (array == link->addr) {
410*5b0d146aSStefano Zampini #if defined(PETSC_USE_DEBUG)
411*5b0d146aSStefano Zampini         dummy[0] = PETSC_TRUE;
412*5b0d146aSStefano Zampini         dummy[1] = PETSC_TRUE;
413*5b0d146aSStefano Zampini         ierr = MPI_Allreduce(MPI_IN_PLACE,dummy  ,1,MPIU_BOOL,MPI_LAND,PetscObjectComm((PetscObject)sf));CHKERRQ(ierr);
414*5b0d146aSStefano Zampini         ierr = MPI_Allreduce(MPI_IN_PLACE,dummy+1,1,MPIU_BOOL,MPI_LOR ,PetscObjectComm((PetscObject)sf));CHKERRQ(ierr);
415*5b0d146aSStefano Zampini         if (dummy[0] != dummy[1]) SETERRQ(PetscObjectComm((PetscObject)sf),PETSC_ERR_SUP,"PETSCSF_WINDOW_FLAVOR_DYNAMIC requires root pointers to be consistently used across the comm. Use PETSCSF_WINDOW_FLAVOR_CREATE or PETSCSF_WINDOW_FLAVOR_ALLOCATE instead");
416*5b0d146aSStefano Zampini #endif
417*5b0d146aSStefano Zampini         if (link->inuse) SETERRQ(PetscObjectComm((PetscObject)sf),PETSC_ERR_PLIB,"Window in use");
418*5b0d146aSStefano Zampini         if (epoch && link->epoch) SETERRQ(PetscObjectComm((PetscObject)sf),PETSC_ERR_PLIB,"Window epoch not finished");
419*5b0d146aSStefano Zampini         winok = PETSC_TRUE;
420*5b0d146aSStefano Zampini         link->paddr = array;
421*5b0d146aSStefano Zampini #if defined(PETSC_USE_DEBUG)
422*5b0d146aSStefano Zampini       } else {
423*5b0d146aSStefano Zampini         dummy[0] = PETSC_FALSE;
424*5b0d146aSStefano Zampini         dummy[1] = PETSC_FALSE;
425*5b0d146aSStefano Zampini         ierr = MPI_Allreduce(MPI_IN_PLACE,dummy  ,1,MPIU_BOOL,MPI_LAND,PetscObjectComm((PetscObject)sf));CHKERRQ(ierr);
426*5b0d146aSStefano Zampini         ierr = MPI_Allreduce(MPI_IN_PLACE,dummy+1,1,MPIU_BOOL,MPI_LOR ,PetscObjectComm((PetscObject)sf));CHKERRQ(ierr);
427*5b0d146aSStefano Zampini         if (dummy[0] != dummy[1]) SETERRQ(PetscObjectComm((PetscObject)sf),PETSC_ERR_SUP,"PETSCSF_WINDOW_FLAVOR_DYNAMIC requires root pointers to be consistently used across the comm. Use PETSCSF_WINDOW_FLAVOR_CREATE or PETSCSF_WINDOW_FLAVOR_ALLOCATE instead");
428*5b0d146aSStefano Zampini #endif
429*5b0d146aSStefano Zampini       }
430*5b0d146aSStefano Zampini       break;
431*5b0d146aSStefano Zampini     case PETSCSF_WINDOW_FLAVOR_ALLOCATE: /* check available by matching size, allocate if in use */
432*5b0d146aSStefano Zampini     case PETSCSF_WINDOW_FLAVOR_SHARED:
433*5b0d146aSStefano Zampini       if (!link->inuse && bytes == (MPI_Aint)link->bytes) {
434*5b0d146aSStefano Zampini         update = PETSC_TRUE;
435*5b0d146aSStefano Zampini         link->paddr = array;
436*5b0d146aSStefano Zampini         winok = PETSC_TRUE;
437*5b0d146aSStefano Zampini       }
438*5b0d146aSStefano Zampini       break;
439*5b0d146aSStefano Zampini     default: SETERRQ1(PetscObjectComm((PetscObject)sf),PETSC_ERR_SUP,"No support for flavor %s",PetscSFWindowFlavorTypes[w->flavor]);
440*5b0d146aSStefano Zampini     }
441*5b0d146aSStefano Zampini     if (winok) {
442*5b0d146aSStefano Zampini       *win = link->win;
443*5b0d146aSStefano Zampini       ierr = PetscInfo3(sf,"Reusing window %d of flavor %d for comm %d\n",link->win,link->flavor,PetscObjectComm((PetscObject)sf));CHKERRQ(ierr);
444*5b0d146aSStefano Zampini       goto found;
445*5b0d146aSStefano Zampini     }
446*5b0d146aSStefano Zampini   }
447*5b0d146aSStefano Zampini 
448*5b0d146aSStefano Zampini   wsize = (MPI_Aint)bytes*sf->nroots;
44995dccacaSBarry Smith   ierr = PetscNew(&link);CHKERRQ(ierr);
45095fce210SBarry Smith   link->bytes           = bytes;
45195fce210SBarry Smith   link->next            = w->wins;
452*5b0d146aSStefano Zampini   link->flavor          = w->flavor;
453*5b0d146aSStefano Zampini   link->dyn_target_addr = NULL;
45495fce210SBarry Smith   w->wins               = link;
455*5b0d146aSStefano Zampini   switch (w->flavor) {
456*5b0d146aSStefano Zampini   case PETSCSF_WINDOW_FLAVOR_CREATE:
457*5b0d146aSStefano Zampini     ierr = MPI_Win_create(array,wsize,(PetscMPIInt)bytes,w->info,PetscObjectComm((PetscObject)sf),&link->win);CHKERRQ(ierr);
458*5b0d146aSStefano Zampini     link->addr  = array;
459*5b0d146aSStefano Zampini     link->paddr = array;
460*5b0d146aSStefano Zampini     break;
461*5b0d146aSStefano Zampini   case PETSCSF_WINDOW_FLAVOR_DYNAMIC:
462*5b0d146aSStefano Zampini     ierr = MPI_Win_create_dynamic(w->info,PetscObjectComm((PetscObject)sf),&link->win);CHKERRQ(ierr);
463*5b0d146aSStefano Zampini #if defined(PETSC_HAVE_OMPI_MAJOR_VERSION) /* some OpenMPI versions do not support MPI_Win_attach(win,NULL,0); */
464*5b0d146aSStefano Zampini     ierr = MPI_Win_attach(link->win,wsize ? array : &ierr,wsize);CHKERRQ(ierr);
465*5b0d146aSStefano Zampini #else
466*5b0d146aSStefano Zampini     ierr = MPI_Win_attach(link->win,array,wsize);CHKERRQ(ierr);
467*5b0d146aSStefano Zampini #endif
468*5b0d146aSStefano Zampini     link->addr  = array;
469*5b0d146aSStefano Zampini     link->paddr = array;
470*5b0d146aSStefano Zampini     if (!w->dynsf) SETERRQ(PetscObjectComm((PetscObject)sf),PETSC_ERR_ORDER,"Must call PetscSFSetUp()");
471*5b0d146aSStefano Zampini     ierr = PetscSFSetUp(w->dynsf);CHKERRQ(ierr);
472*5b0d146aSStefano Zampini     ierr = PetscSFGetRootRanks(w->dynsf,&nranks,NULL,NULL,NULL,NULL);CHKERRQ(ierr);
473*5b0d146aSStefano Zampini     ierr = PetscMalloc1(nranks,&link->dyn_target_addr);CHKERRQ(ierr);
474*5b0d146aSStefano Zampini     ierr = MPI_Get_address(array,&winaddr);CHKERRQ(ierr);
475*5b0d146aSStefano Zampini     ierr = PetscSFBcastBegin(w->dynsf,MPI_AINT,&winaddr,link->dyn_target_addr);CHKERRQ(ierr);
476*5b0d146aSStefano Zampini     ierr = PetscSFBcastEnd(w->dynsf,MPI_AINT,&winaddr,link->dyn_target_addr);CHKERRQ(ierr);
477*5b0d146aSStefano Zampini     break;
478*5b0d146aSStefano Zampini   case PETSCSF_WINDOW_FLAVOR_ALLOCATE:
479*5b0d146aSStefano Zampini     ierr = MPI_Win_allocate(wsize,(PetscMPIInt)bytes,w->info,PetscObjectComm((PetscObject)sf),&link->addr,&link->win);CHKERRQ(ierr);
480*5b0d146aSStefano Zampini     update = PETSC_TRUE;
481*5b0d146aSStefano Zampini     link->paddr = array;
482*5b0d146aSStefano Zampini     break;
483*5b0d146aSStefano Zampini #if defined(PETSC_HAVE_MPI_PROCESS_SHARED_MEMORY)
484*5b0d146aSStefano Zampini   case PETSCSF_WINDOW_FLAVOR_SHARED:
485*5b0d146aSStefano Zampini     ierr = MPI_Win_allocate_shared(wsize,(PetscMPIInt)bytes,w->info,PetscObjectComm((PetscObject)sf),&link->addr,&link->win);CHKERRQ(ierr);
486*5b0d146aSStefano Zampini     update = PETSC_TRUE;
487*5b0d146aSStefano Zampini     link->paddr = array;
488*5b0d146aSStefano Zampini     break;
489*5b0d146aSStefano Zampini #endif
490*5b0d146aSStefano Zampini   default: SETERRQ1(PetscObjectComm((PetscObject)sf),PETSC_ERR_SUP,"No support for flavor %s",PetscSFWindowFlavorTypes[w->flavor]);
491*5b0d146aSStefano Zampini   }
492*5b0d146aSStefano Zampini   ierr = PetscInfo3(sf,"New window %d of flavor %d for comm %d\n",link->win,link->flavor,PetscObjectComm((PetscObject)sf));CHKERRQ(ierr);
49395fce210SBarry Smith   *win = link->win;
49495fce210SBarry Smith 
495*5b0d146aSStefano Zampini found:
496*5b0d146aSStefano Zampini 
497*5b0d146aSStefano Zampini   if (update) {
498*5b0d146aSStefano Zampini     ierr = PetscMemcpy(link->addr,array,sf->nroots*bytes);CHKERRQ(ierr);
499*5b0d146aSStefano Zampini     if (sync == PETSCSF_WINDOW_SYNC_LOCK) {
500*5b0d146aSStefano Zampini       ierr = MPI_Win_fence(0,*win);CHKERRQ(ierr);
501*5b0d146aSStefano Zampini     }
502*5b0d146aSStefano Zampini   }
503*5b0d146aSStefano Zampini   link->inuse = PETSC_TRUE;
504*5b0d146aSStefano Zampini   link->epoch = epoch;
505*5b0d146aSStefano Zampini   *target_disp = link->dyn_target_addr;
50695fce210SBarry Smith   if (epoch) {
507*5b0d146aSStefano Zampini     switch (sync) {
50895fce210SBarry Smith     case PETSCSF_WINDOW_SYNC_FENCE:
50995fce210SBarry Smith       ierr = MPI_Win_fence(fenceassert,*win);CHKERRQ(ierr);
51095fce210SBarry Smith       break;
51195fce210SBarry Smith     case PETSCSF_WINDOW_SYNC_LOCK: /* Handled outside */
51295fce210SBarry Smith       break;
51395fce210SBarry Smith     case PETSCSF_WINDOW_SYNC_ACTIVE: {
51495fce210SBarry Smith       MPI_Group   ingroup,outgroup;
515*5b0d146aSStefano Zampini       PetscMPIInt isize,osize;
516*5b0d146aSStefano Zampini 
517*5b0d146aSStefano Zampini       /* OpenMPI 4.0.2 with btl=vader does not like calling
518*5b0d146aSStefano Zampini          - MPI_Win_complete when ogroup is empty
519*5b0d146aSStefano Zampini          - MPI_Win_wait when igroup is empty
520*5b0d146aSStefano Zampini          So, we do not even issue the corresponding start and post calls
521*5b0d146aSStefano Zampini          The MPI standard (Sec. 11.5.2 of MPI 3.1) only requires that
522*5b0d146aSStefano Zampini          start(outgroup) has a matching post(ingroup)
523*5b0d146aSStefano Zampini          and this is guaranteed by PetscSF
524*5b0d146aSStefano Zampini       */
52595fce210SBarry Smith       ierr = PetscSFGetGroups(sf,&ingroup,&outgroup);CHKERRQ(ierr);
526*5b0d146aSStefano Zampini       ierr = MPI_Group_size(ingroup,&isize);CHKERRQ(ierr);
527*5b0d146aSStefano Zampini       ierr = MPI_Group_size(outgroup,&osize);CHKERRQ(ierr);
528*5b0d146aSStefano Zampini       if (isize) { ierr = MPI_Win_post(ingroup,postassert,*win);CHKERRQ(ierr); }
529*5b0d146aSStefano Zampini       if (osize) { ierr = MPI_Win_start(outgroup,startassert,*win);CHKERRQ(ierr); }
53095fce210SBarry Smith     } break;
53195fce210SBarry Smith     default: SETERRQ(PetscObjectComm((PetscObject)sf),PETSC_ERR_PLIB,"Unknown synchronization type");
53295fce210SBarry Smith     }
53395fce210SBarry Smith   }
53495fce210SBarry Smith   PetscFunctionReturn(0);
53595fce210SBarry Smith }
53695fce210SBarry Smith 
537*5b0d146aSStefano Zampini /*
53895fce210SBarry Smith    PetscSFFindWindow - Finds a window that is already in use
53995fce210SBarry Smith 
54095fce210SBarry Smith    Not Collective
54195fce210SBarry Smith 
54295fce210SBarry Smith    Input Arguments:
54395fce210SBarry Smith +  sf - star forest
54495fce210SBarry Smith .  unit - data type
54595fce210SBarry Smith -  array - array with which the window is associated
54695fce210SBarry Smith 
54795fce210SBarry Smith    Output Arguments:
54895fce210SBarry Smith .  win - window
54995fce210SBarry Smith 
55095fce210SBarry Smith    Level: developer
55195fce210SBarry Smith 
55295fce210SBarry Smith .seealso: PetscSFGetWindow(), PetscSFRestoreWindow()
553*5b0d146aSStefano Zampini */
55495fce210SBarry Smith static PetscErrorCode PetscSFFindWindow(PetscSF sf,MPI_Datatype unit,const void *array,MPI_Win *win)
55595fce210SBarry Smith {
55695fce210SBarry Smith   PetscSF_Window *w = (PetscSF_Window*)sf->data;
55795fce210SBarry Smith   PetscSFWinLink link;
558*5b0d146aSStefano Zampini   PetscErrorCode ierr;
55995fce210SBarry Smith 
56095fce210SBarry Smith   PetscFunctionBegin;
561c0cd0301SJed Brown   *win = MPI_WIN_NULL;
56295fce210SBarry Smith   for (link=w->wins; link; link=link->next) {
563*5b0d146aSStefano Zampini     if (array == link->paddr) {
564*5b0d146aSStefano Zampini       ierr = PetscInfo3(sf,"Window %d of flavor %d for comm %d\n",link->win,link->flavor,PetscObjectComm((PetscObject)sf));CHKERRQ(ierr);
56595fce210SBarry Smith       *win = link->win;
56695fce210SBarry Smith       PetscFunctionReturn(0);
56795fce210SBarry Smith     }
56895fce210SBarry Smith   }
56995fce210SBarry Smith   SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Requested window not in use");
57095fce210SBarry Smith   PetscFunctionReturn(0);
57195fce210SBarry Smith }
57295fce210SBarry Smith 
573*5b0d146aSStefano Zampini /*
57495fce210SBarry Smith    PetscSFRestoreWindow - Restores a window obtained with PetscSFGetWindow()
57595fce210SBarry Smith 
57695fce210SBarry Smith    Collective
57795fce210SBarry Smith 
57895fce210SBarry Smith    Input Arguments:
57995fce210SBarry Smith +  sf - star forest
58095fce210SBarry Smith .  unit - data type
58195fce210SBarry Smith .  array - array associated with window
582*5b0d146aSStefano Zampini .  sync - type of synchronization PetscSFWindowSyncType
58395fce210SBarry Smith .  epoch - close an epoch, must match argument to PetscSFGetWindow()
584*5b0d146aSStefano Zampini .  update - if we have to update the local window array
58595fce210SBarry Smith -  win - window
58695fce210SBarry Smith 
58795fce210SBarry Smith    Level: developer
58895fce210SBarry Smith 
58995fce210SBarry Smith .seealso: PetscSFFindWindow()
590*5b0d146aSStefano Zampini */
591*5b0d146aSStefano Zampini static PetscErrorCode PetscSFRestoreWindow(PetscSF sf,MPI_Datatype unit,void *array,PetscSFWindowSyncType sync,PetscBool epoch,PetscMPIInt fenceassert,PetscBool update,MPI_Win *win)
59295fce210SBarry Smith {
59395fce210SBarry Smith   PetscSF_Window          *w = (PetscSF_Window*)sf->data;
59495fce210SBarry Smith   PetscErrorCode          ierr;
59595fce210SBarry Smith   PetscSFWinLink          *p,link;
596*5b0d146aSStefano Zampini   PetscBool               reuse = PETSC_FALSE;
597*5b0d146aSStefano Zampini   PetscSFWindowFlavorType flavor;
598*5b0d146aSStefano Zampini   void*                   laddr;
599*5b0d146aSStefano Zampini   size_t                  bytes;
60095fce210SBarry Smith 
60195fce210SBarry Smith   PetscFunctionBegin;
60295fce210SBarry Smith   for (p=&w->wins; *p; p=&(*p)->next) {
60395fce210SBarry Smith     link = *p;
60495fce210SBarry Smith     if (*win == link->win) {
605*5b0d146aSStefano Zampini       if (array != link->paddr) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Matched window, but not array");
60695fce210SBarry Smith       if (epoch != link->epoch) {
60795fce210SBarry Smith         if (epoch) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"No epoch to end");
60895fce210SBarry Smith         else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Restoring window without ending epoch");
60995fce210SBarry Smith       }
610*5b0d146aSStefano Zampini       laddr = link->addr;
611*5b0d146aSStefano Zampini       flavor = link->flavor;
612*5b0d146aSStefano Zampini       bytes = link->bytes;
613*5b0d146aSStefano Zampini       if (flavor != PETSCSF_WINDOW_FLAVOR_CREATE) reuse = PETSC_TRUE;
614*5b0d146aSStefano Zampini       else { *p = link->next; update = PETSC_FALSE; } /* remove from list */
61595fce210SBarry Smith       goto found;
61695fce210SBarry Smith     }
61795fce210SBarry Smith   }
61895fce210SBarry Smith   SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Requested window not in use");
61995fce210SBarry Smith 
62095fce210SBarry Smith found:
621*5b0d146aSStefano Zampini   ierr = PetscInfo3(sf,"Window %d of flavor %d for comm %d\n",link->win,link->flavor,PetscObjectComm((PetscObject)sf));CHKERRQ(ierr);
62295fce210SBarry Smith   if (epoch) {
623*5b0d146aSStefano Zampini     switch (sync) {
62495fce210SBarry Smith     case PETSCSF_WINDOW_SYNC_FENCE:
62595fce210SBarry Smith       ierr = MPI_Win_fence(fenceassert,*win);CHKERRQ(ierr);
62695fce210SBarry Smith       break;
627*5b0d146aSStefano Zampini     case PETSCSF_WINDOW_SYNC_LOCK: /* Handled outside */
628*5b0d146aSStefano Zampini       break;
62995fce210SBarry Smith     case PETSCSF_WINDOW_SYNC_ACTIVE: {
630*5b0d146aSStefano Zampini       MPI_Group   ingroup,outgroup;
631*5b0d146aSStefano Zampini       PetscMPIInt isize,osize;
632*5b0d146aSStefano Zampini 
633*5b0d146aSStefano Zampini       /* OpenMPI 4.0.2 with btl=wader does not like calling
634*5b0d146aSStefano Zampini          - MPI_Win_complete when ogroup is empty
635*5b0d146aSStefano Zampini          - MPI_Win_wait when igroup is empty
636*5b0d146aSStefano Zampini          The MPI standard (Sec. 11.5.2 of MPI 3.1) only requires that
637*5b0d146aSStefano Zampini          - each process who issues a call to MPI_Win_start issues a call to MPI_Win_Complete
638*5b0d146aSStefano Zampini          - each process who issues a call to MPI_Win_post issues a call to MPI_Win_Wait
639*5b0d146aSStefano Zampini       */
640*5b0d146aSStefano Zampini       ierr = PetscSFGetGroups(sf,&ingroup,&outgroup);CHKERRQ(ierr);
641*5b0d146aSStefano Zampini       ierr = MPI_Group_size(ingroup,&isize);CHKERRQ(ierr);
642*5b0d146aSStefano Zampini       ierr = MPI_Group_size(outgroup,&osize);CHKERRQ(ierr);
643*5b0d146aSStefano Zampini       if (osize) { ierr = MPI_Win_complete(*win);CHKERRQ(ierr); }
644*5b0d146aSStefano Zampini       if (isize) { ierr = MPI_Win_wait(*win);CHKERRQ(ierr); }
64595fce210SBarry Smith     } break;
64695fce210SBarry Smith     default: SETERRQ(PetscObjectComm((PetscObject)sf),PETSC_ERR_PLIB,"Unknown synchronization type");
64795fce210SBarry Smith     }
64895fce210SBarry Smith   }
649*5b0d146aSStefano Zampini   if (update) {
650*5b0d146aSStefano Zampini     if (sync == PETSCSF_WINDOW_SYNC_LOCK) {
651*5b0d146aSStefano Zampini       ierr = MPI_Win_fence(MPI_MODE_NOPUT|MPI_MODE_NOSUCCEED,*win);CHKERRQ(ierr);
652*5b0d146aSStefano Zampini     }
653*5b0d146aSStefano Zampini     ierr = PetscMemcpy(array,laddr,sf->nroots*bytes);CHKERRQ(ierr);
654*5b0d146aSStefano Zampini   }
655*5b0d146aSStefano Zampini   link->epoch = PETSC_FALSE;
656*5b0d146aSStefano Zampini   link->inuse = PETSC_FALSE;
657*5b0d146aSStefano Zampini   link->paddr = NULL;
658*5b0d146aSStefano Zampini   if (!reuse) {
65995fce210SBarry Smith     ierr = MPI_Win_free(&link->win);CHKERRQ(ierr);
66095fce210SBarry Smith     ierr = PetscFree(link);CHKERRQ(ierr);
66195fce210SBarry Smith     *win = MPI_WIN_NULL;
662*5b0d146aSStefano Zampini   }
66395fce210SBarry Smith   PetscFunctionReturn(0);
66495fce210SBarry Smith }
66595fce210SBarry Smith 
66695fce210SBarry Smith static PetscErrorCode PetscSFSetUp_Window(PetscSF sf)
66795fce210SBarry Smith {
66895fce210SBarry Smith   PetscSF_Window *w = (PetscSF_Window*)sf->data;
66995fce210SBarry Smith   PetscErrorCode ierr;
67095fce210SBarry Smith   MPI_Group      ingroup,outgroup;
67195fce210SBarry Smith 
67295fce210SBarry Smith   PetscFunctionBegin;
673b5a8e515SJed Brown   ierr = PetscSFSetUpRanks(sf,MPI_GROUP_EMPTY);CHKERRQ(ierr);
674*5b0d146aSStefano Zampini   if (!w->dynsf) {
675*5b0d146aSStefano Zampini     PetscInt    i;
676*5b0d146aSStefano Zampini     PetscSFNode *remotes;
677*5b0d146aSStefano Zampini 
678*5b0d146aSStefano Zampini     ierr = PetscMalloc1(sf->nranks,&remotes);CHKERRQ(ierr);
679*5b0d146aSStefano Zampini     for (i=0;i<sf->nranks;i++) {
680*5b0d146aSStefano Zampini       remotes[i].rank  = sf->ranks[i];
681*5b0d146aSStefano Zampini       remotes[i].index = 0;
682*5b0d146aSStefano Zampini     }
683*5b0d146aSStefano Zampini     ierr = PetscSFDuplicate(sf,PETSCSF_DUPLICATE_RANKS,&w->dynsf);CHKERRQ(ierr);
684*5b0d146aSStefano Zampini     ierr = PetscSFWindowSetFlavorType(w->dynsf,PETSCSF_WINDOW_FLAVOR_CREATE);CHKERRQ(ierr); /* break recursion */
685*5b0d146aSStefano Zampini     ierr = PetscSFSetGraph(w->dynsf,1,sf->nranks,NULL,PETSC_OWN_POINTER,remotes,PETSC_OWN_POINTER);CHKERRQ(ierr);
686*5b0d146aSStefano Zampini     ierr = PetscLogObjectParent((PetscObject)sf,(PetscObject)w->dynsf);CHKERRQ(ierr);
687*5b0d146aSStefano Zampini   }
68895fce210SBarry Smith   switch (w->sync) {
68995fce210SBarry Smith   case PETSCSF_WINDOW_SYNC_ACTIVE:
69095fce210SBarry Smith     ierr = PetscSFGetGroups(sf,&ingroup,&outgroup);CHKERRQ(ierr);
69195fce210SBarry Smith   default:
69295fce210SBarry Smith     break;
69395fce210SBarry Smith   }
69495fce210SBarry Smith   PetscFunctionReturn(0);
69595fce210SBarry Smith }
69695fce210SBarry Smith 
6974416b707SBarry Smith static PetscErrorCode PetscSFSetFromOptions_Window(PetscOptionItems *PetscOptionsObject,PetscSF sf)
69895fce210SBarry Smith {
69995fce210SBarry Smith   PetscSF_Window          *w = (PetscSF_Window*)sf->data;
70095fce210SBarry Smith   PetscErrorCode          ierr;
701*5b0d146aSStefano Zampini   PetscSFWindowFlavorType flavor = w->flavor;
70295fce210SBarry Smith 
70395fce210SBarry Smith   PetscFunctionBegin;
704e55864a3SBarry Smith   ierr = PetscOptionsHead(PetscOptionsObject,"PetscSF Window options");CHKERRQ(ierr);
70595fce210SBarry Smith   ierr = PetscOptionsEnum("-sf_window_sync","synchronization type to use for PetscSF Window communication","PetscSFWindowSetSyncType",PetscSFWindowSyncTypes,(PetscEnum)w->sync,(PetscEnum*)&w->sync,NULL);CHKERRQ(ierr);
706*5b0d146aSStefano Zampini   ierr = PetscOptionsEnum("-sf_window_flavor","flavor to use for PetscSF Window creation","PetscSFWindowSetFlavorType",PetscSFWindowFlavorTypes,(PetscEnum)flavor,(PetscEnum*)&flavor,NULL);CHKERRQ(ierr);
707*5b0d146aSStefano Zampini   ierr = PetscSFWindowSetFlavorType(sf,flavor);CHKERRQ(ierr);
70895fce210SBarry Smith   ierr = PetscOptionsTail();CHKERRQ(ierr);
70995fce210SBarry Smith   PetscFunctionReturn(0);
71095fce210SBarry Smith }
71195fce210SBarry Smith 
71295fce210SBarry Smith static PetscErrorCode PetscSFReset_Window(PetscSF sf)
71395fce210SBarry Smith {
71495fce210SBarry Smith   PetscSF_Window  *w = (PetscSF_Window*)sf->data;
71595fce210SBarry Smith   PetscErrorCode  ierr;
71695fce210SBarry Smith   PetscSFDataLink link,next;
71795fce210SBarry Smith   PetscSFWinLink  wlink,wnext;
71895fce210SBarry Smith   PetscInt        i;
71995fce210SBarry Smith 
72095fce210SBarry Smith   PetscFunctionBegin;
72195fce210SBarry Smith   for (link=w->link; link; link=next) {
72295fce210SBarry Smith     next = link->next;
72395fce210SBarry Smith     ierr = MPI_Type_free(&link->unit);CHKERRQ(ierr);
72495fce210SBarry Smith     for (i=0; i<sf->nranks; i++) {
72595fce210SBarry Smith       ierr = MPI_Type_free(&link->mine[i]);CHKERRQ(ierr);
72695fce210SBarry Smith       ierr = MPI_Type_free(&link->remote[i]);CHKERRQ(ierr);
72795fce210SBarry Smith     }
72895fce210SBarry Smith     ierr = PetscFree2(link->mine,link->remote);CHKERRQ(ierr);
72995fce210SBarry Smith     ierr = PetscFree(link);CHKERRQ(ierr);
73095fce210SBarry Smith   }
73195fce210SBarry Smith   w->link = NULL;
73295fce210SBarry Smith   for (wlink=w->wins; wlink; wlink=wnext) {
73395fce210SBarry Smith     wnext = wlink->next;
73495fce210SBarry Smith     if (wlink->inuse) SETERRQ1(PetscObjectComm((PetscObject)sf),PETSC_ERR_ARG_WRONGSTATE,"Window still in use with address %p",(void*)wlink->addr);
735*5b0d146aSStefano Zampini     ierr = PetscFree(wlink->dyn_target_addr);CHKERRQ(ierr);
73695fce210SBarry Smith     ierr = MPI_Win_free(&wlink->win);CHKERRQ(ierr);
73795fce210SBarry Smith     ierr = PetscFree(wlink);CHKERRQ(ierr);
73895fce210SBarry Smith   }
73995fce210SBarry Smith   w->wins = NULL;
740*5b0d146aSStefano Zampini   ierr = PetscSFDestroy(&w->dynsf);CHKERRQ(ierr);
741*5b0d146aSStefano Zampini   if (w->info != MPI_INFO_NULL) {
742*5b0d146aSStefano Zampini     ierr = MPI_Info_free(&w->info);CHKERRQ(ierr);
743*5b0d146aSStefano Zampini   }
74495fce210SBarry Smith   PetscFunctionReturn(0);
74595fce210SBarry Smith }
74695fce210SBarry Smith 
74795fce210SBarry Smith static PetscErrorCode PetscSFDestroy_Window(PetscSF sf)
74895fce210SBarry Smith {
74995fce210SBarry Smith   PetscErrorCode ierr;
75095fce210SBarry Smith 
75195fce210SBarry Smith   PetscFunctionBegin;
75229046d53SLisandro Dalcin   ierr = PetscSFReset_Window(sf);CHKERRQ(ierr);
75395fce210SBarry Smith   ierr = PetscFree(sf->data);CHKERRQ(ierr);
754bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)sf,"PetscSFWindowSetSyncType_C",NULL);CHKERRQ(ierr);
755bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)sf,"PetscSFWindowGetSyncType_C",NULL);CHKERRQ(ierr);
756*5b0d146aSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)sf,"PetscSFWindowSetFlavorType_C",NULL);CHKERRQ(ierr);
757*5b0d146aSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)sf,"PetscSFWindowGetFlavorType_C",NULL);CHKERRQ(ierr);
758*5b0d146aSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)sf,"PetscSFWindowSetInfo_C",NULL);CHKERRQ(ierr);
759*5b0d146aSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)sf,"PetscSFWindowGetInfo_C",NULL);CHKERRQ(ierr);
76095fce210SBarry Smith   PetscFunctionReturn(0);
76195fce210SBarry Smith }
76295fce210SBarry Smith 
76395fce210SBarry Smith static PetscErrorCode PetscSFView_Window(PetscSF sf,PetscViewer viewer)
76495fce210SBarry Smith {
76595fce210SBarry Smith   PetscSF_Window    *w = (PetscSF_Window*)sf->data;
76695fce210SBarry Smith   PetscErrorCode    ierr;
76795fce210SBarry Smith   PetscBool         iascii;
768*5b0d146aSStefano Zampini   PetscViewerFormat format;
76995fce210SBarry Smith 
77095fce210SBarry Smith   PetscFunctionBegin;
771*5b0d146aSStefano Zampini   ierr = PetscViewerGetFormat(viewer,&format);CHKERRQ(ierr);
77295fce210SBarry Smith   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr);
77395fce210SBarry Smith   if (iascii) {
774*5b0d146aSStefano Zampini     ierr = PetscViewerASCIIPrintf(viewer,"  current flavor=%s synchronization=%s sort=%s\n",PetscSFWindowFlavorTypes[w->flavor],PetscSFWindowSyncTypes[w->sync],sf->rankorder ? "rank-order" : "unordered");CHKERRQ(ierr);
775*5b0d146aSStefano Zampini     if (format == PETSC_VIEWER_ASCII_INFO_DETAIL) {
776*5b0d146aSStefano Zampini       if (w->info != MPI_INFO_NULL) {
777*5b0d146aSStefano Zampini         PetscMPIInt k,nkeys;
778*5b0d146aSStefano Zampini         char        key[MPI_MAX_INFO_KEY], value[MPI_MAX_INFO_VAL];
779*5b0d146aSStefano Zampini 
780*5b0d146aSStefano Zampini         ierr = MPI_Info_get_nkeys(w->info,&nkeys);CHKERRQ(ierr);
781*5b0d146aSStefano Zampini         ierr = PetscViewerASCIIPrintf(viewer,"    current info with %d keys. Ordered key-value pairs follow:\n",nkeys);CHKERRQ(ierr);
782*5b0d146aSStefano Zampini         for (k = 0; k < nkeys; k++) {
783*5b0d146aSStefano Zampini           PetscMPIInt flag;
784*5b0d146aSStefano Zampini 
785*5b0d146aSStefano Zampini           ierr = MPI_Info_get_nthkey(w->info,k,key);CHKERRQ(ierr);
786*5b0d146aSStefano Zampini           ierr = MPI_Info_get(w->info,key,MPI_MAX_INFO_VAL,value,&flag);CHKERRQ(ierr);
787*5b0d146aSStefano Zampini           if (!flag) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Missing key %s",key);
788*5b0d146aSStefano Zampini           ierr = PetscViewerASCIIPrintf(viewer,"      %s = %s\n",key,value);CHKERRQ(ierr);
789*5b0d146aSStefano Zampini         }
790*5b0d146aSStefano Zampini       } else {
791*5b0d146aSStefano Zampini         ierr = PetscViewerASCIIPrintf(viewer,"    current info=MPI_INFO_NULL\n");CHKERRQ(ierr);
792*5b0d146aSStefano Zampini       }
793*5b0d146aSStefano Zampini     }
79495fce210SBarry Smith   }
79595fce210SBarry Smith   PetscFunctionReturn(0);
79695fce210SBarry Smith }
79795fce210SBarry Smith 
79895fce210SBarry Smith static PetscErrorCode PetscSFDuplicate_Window(PetscSF sf,PetscSFDuplicateOption opt,PetscSF newsf)
79995fce210SBarry Smith {
80095fce210SBarry Smith   PetscSF_Window        *w = (PetscSF_Window*)sf->data;
80195fce210SBarry Smith   PetscErrorCode        ierr;
80295fce210SBarry Smith   PetscSFWindowSyncType synctype;
80395fce210SBarry Smith 
80495fce210SBarry Smith   PetscFunctionBegin;
80595fce210SBarry Smith   synctype = w->sync;
80695fce210SBarry Smith   /* HACK: Must use FENCE or LOCK when called from PetscSFGetGroups() because ACTIVE here would cause recursion. */
807*5b0d146aSStefano Zampini   if (!sf->setupcalled) synctype = PETSCSF_WINDOW_SYNC_LOCK;
80895fce210SBarry Smith   ierr = PetscSFWindowSetSyncType(newsf,synctype);CHKERRQ(ierr);
809*5b0d146aSStefano Zampini   ierr = PetscSFWindowSetFlavorType(newsf,w->flavor);CHKERRQ(ierr);
810*5b0d146aSStefano Zampini   ierr = PetscSFWindowSetInfo(newsf,w->info);CHKERRQ(ierr);
81195fce210SBarry Smith   PetscFunctionReturn(0);
81295fce210SBarry Smith }
81395fce210SBarry Smith 
814eb02082bSJunchao Zhang static PetscErrorCode PetscSFBcastAndOpBegin_Window(PetscSF sf,MPI_Datatype unit,PetscMemType rootmtype,const void *rootdata,PetscMemType leafmtype,void *leafdata,MPI_Op op)
81595fce210SBarry Smith {
81695fce210SBarry Smith   PetscSF_Window     *w = (PetscSF_Window*)sf->data;
81795fce210SBarry Smith   PetscErrorCode     ierr;
81895fce210SBarry Smith   PetscInt           i,nranks;
81995fce210SBarry Smith   const PetscMPIInt  *ranks;
820*5b0d146aSStefano Zampini   const MPI_Aint     *target_disp;
82195fce210SBarry Smith   const MPI_Datatype *mine,*remote;
82295fce210SBarry Smith   MPI_Win            win;
82395fce210SBarry Smith 
82495fce210SBarry Smith   PetscFunctionBegin;
825*5b0d146aSStefano Zampini   if (op != MPI_REPLACE || op != MPIU_REPLACE) SETERRQ(PetscObjectComm((PetscObject)sf), PETSC_ERR_SUP, "PetscSFBcastAndOpBegin_Window with op!=MPI_REPLACE has not been implemented");
826dec1416fSJunchao Zhang   ierr = PetscSFGetRootRanks(sf,&nranks,&ranks,NULL,NULL,NULL);CHKERRQ(ierr);
82795fce210SBarry Smith   ierr = PetscSFWindowGetDataTypes(sf,unit,&mine,&remote);CHKERRQ(ierr);
828*5b0d146aSStefano Zampini   ierr = PetscSFGetWindow(sf,unit,(void*)rootdata,w->sync,PETSC_TRUE,MPI_MODE_NOPUT|MPI_MODE_NOPRECEDE,MPI_MODE_NOPUT,0,&target_disp,&win);CHKERRQ(ierr);
82995fce210SBarry Smith   for (i=0; i<nranks; i++) {
830*5b0d146aSStefano Zampini     MPI_Aint tdp = target_disp ? target_disp[i] : 0;
831*5b0d146aSStefano Zampini 
83295fce210SBarry Smith     if (w->sync == PETSCSF_WINDOW_SYNC_LOCK) {ierr = MPI_Win_lock(MPI_LOCK_SHARED,ranks[i],MPI_MODE_NOCHECK,win);CHKERRQ(ierr);}
833*5b0d146aSStefano Zampini     ierr = MPI_Get(leafdata,1,mine[i],ranks[i],tdp,1,remote[i],win);CHKERRQ(ierr);
83495fce210SBarry Smith     if (w->sync == PETSCSF_WINDOW_SYNC_LOCK) {ierr = MPI_Win_unlock(ranks[i],win);CHKERRQ(ierr);}
83595fce210SBarry Smith   }
83695fce210SBarry Smith   PetscFunctionReturn(0);
83795fce210SBarry Smith }
83895fce210SBarry Smith 
839eb02082bSJunchao Zhang PetscErrorCode PetscSFBcastAndOpEnd_Window(PetscSF sf,MPI_Datatype unit,PetscMemType rootmtype,const void *rootdata,PetscMemType leafmtype,void *leafdata,MPI_Op op)
84095fce210SBarry Smith {
841*5b0d146aSStefano Zampini   PetscSF_Window *w = (PetscSF_Window*)sf->data;
84295fce210SBarry Smith   PetscErrorCode ierr;
84395fce210SBarry Smith   MPI_Win        win;
84495fce210SBarry Smith 
84595fce210SBarry Smith   PetscFunctionBegin;
84695fce210SBarry Smith   ierr = PetscSFFindWindow(sf,unit,rootdata,&win);CHKERRQ(ierr);
847*5b0d146aSStefano Zampini   ierr = PetscSFRestoreWindow(sf,unit,(void*)rootdata,w->sync,PETSC_TRUE,MPI_MODE_NOSTORE|MPI_MODE_NOSUCCEED,PETSC_FALSE,&win);CHKERRQ(ierr);
84895fce210SBarry Smith   PetscFunctionReturn(0);
84995fce210SBarry Smith }
85095fce210SBarry Smith 
851eb02082bSJunchao Zhang PetscErrorCode PetscSFReduceBegin_Window(PetscSF sf,MPI_Datatype unit,PetscMemType leafmtype,const void *leafdata,PetscMemType rootmtype,void *rootdata,MPI_Op op)
85295fce210SBarry Smith {
85395fce210SBarry Smith   PetscSF_Window     *w = (PetscSF_Window*)sf->data;
85495fce210SBarry Smith   PetscErrorCode     ierr;
85595fce210SBarry Smith   PetscInt           i,nranks;
85695fce210SBarry Smith   const PetscMPIInt  *ranks;
857*5b0d146aSStefano Zampini   const MPI_Aint     *target_disp;
85895fce210SBarry Smith   const MPI_Datatype *mine,*remote;
85995fce210SBarry Smith   MPI_Win            win;
86095fce210SBarry Smith 
86195fce210SBarry Smith   PetscFunctionBegin;
862dec1416fSJunchao Zhang   ierr = PetscSFGetRootRanks(sf,&nranks,&ranks,NULL,NULL,NULL);CHKERRQ(ierr);
86395fce210SBarry Smith   ierr = PetscSFWindowGetDataTypes(sf,unit,&mine,&remote);CHKERRQ(ierr);
86495fce210SBarry Smith   ierr = PetscSFWindowOpTranslate(&op);CHKERRQ(ierr);
865*5b0d146aSStefano Zampini   ierr = PetscSFGetWindow(sf,unit,rootdata,w->sync,PETSC_TRUE,MPI_MODE_NOPRECEDE,0,0,&target_disp,&win);CHKERRQ(ierr);
86695fce210SBarry Smith   for (i=0; i<nranks; i++) {
867*5b0d146aSStefano Zampini     MPI_Aint tdp = target_disp ? target_disp[i] : 0;
868*5b0d146aSStefano Zampini 
86995fce210SBarry Smith     if (w->sync == PETSCSF_WINDOW_SYNC_LOCK) {ierr = MPI_Win_lock(MPI_LOCK_SHARED,ranks[i],MPI_MODE_NOCHECK,win);CHKERRQ(ierr);}
870*5b0d146aSStefano Zampini     ierr = MPI_Accumulate((void*)leafdata,1,mine[i],ranks[i],tdp,1,remote[i],op,win);
871*5b0d146aSStefano Zampini     if (ierr) { /* intercept the MPI error since the combination of unit and op is not supported */
872*5b0d146aSStefano Zampini       PetscMPIInt len;
873*5b0d146aSStefano Zampini       char        errstring[MPI_MAX_ERROR_STRING];
874*5b0d146aSStefano Zampini 
875*5b0d146aSStefano Zampini       MPI_Error_string(ierr,errstring,&len);
876*5b0d146aSStefano Zampini       SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_SUP,"Internal error in MPI: %s",errstring);
877*5b0d146aSStefano Zampini     }
87895fce210SBarry Smith     if (w->sync == PETSCSF_WINDOW_SYNC_LOCK) {ierr = MPI_Win_unlock(ranks[i],win);CHKERRQ(ierr);}
87995fce210SBarry Smith   }
88095fce210SBarry Smith   PetscFunctionReturn(0);
88195fce210SBarry Smith }
88295fce210SBarry Smith 
883eb02082bSJunchao Zhang static PetscErrorCode PetscSFReduceEnd_Window(PetscSF sf,MPI_Datatype unit,PetscMemType leafmtype,const void *leafdata,PetscMemType rootmtype,void *rootdata,MPI_Op op)
88495fce210SBarry Smith {
88595fce210SBarry Smith   PetscSF_Window *w = (PetscSF_Window*)sf->data;
88695fce210SBarry Smith   PetscErrorCode ierr;
88795fce210SBarry Smith   MPI_Win        win;
88895fce210SBarry Smith 
88995fce210SBarry Smith   PetscFunctionBegin;
89095fce210SBarry Smith   if (!w->wins) PetscFunctionReturn(0);
89195fce210SBarry Smith   ierr = PetscSFFindWindow(sf,unit,rootdata,&win);CHKERRQ(ierr);
892*5b0d146aSStefano Zampini   ierr = PetscSFRestoreWindow(sf,unit,rootdata,w->sync,PETSC_TRUE,MPI_MODE_NOSUCCEED,PETSC_TRUE,&win);CHKERRQ(ierr);
89395fce210SBarry Smith   PetscFunctionReturn(0);
89495fce210SBarry Smith }
895*5b0d146aSStefano Zampini 
896eb02082bSJunchao Zhang static PetscErrorCode PetscSFFetchAndOpBegin_Window(PetscSF sf,MPI_Datatype unit,PetscMemType rootmtype,void *rootdata,PetscMemType leafmtype,const void *leafdata,void *leafupdate,MPI_Op op)
89795fce210SBarry Smith {
89895fce210SBarry Smith   PetscErrorCode     ierr;
89995fce210SBarry Smith   PetscInt           i,nranks;
90095fce210SBarry Smith   const PetscMPIInt  *ranks;
90195fce210SBarry Smith   const MPI_Datatype *mine,*remote;
902*5b0d146aSStefano Zampini   const MPI_Aint     *target_disp;
90395fce210SBarry Smith   MPI_Win            win;
904*5b0d146aSStefano Zampini   PetscSF_Window     *w = (PetscSF_Window*)sf->data;
905*5b0d146aSStefano Zampini #if !defined(PETSC_HAVE_MPI_GET_ACCUMULATE)
906*5b0d146aSStefano Zampini   PetscSFWindowFlavorType oldf;
907*5b0d146aSStefano Zampini #endif
90895fce210SBarry Smith 
90995fce210SBarry Smith   PetscFunctionBegin;
910dec1416fSJunchao Zhang   ierr = PetscSFGetRootRanks(sf,&nranks,&ranks,NULL,NULL,NULL);CHKERRQ(ierr);
91195fce210SBarry Smith   ierr = PetscSFWindowGetDataTypes(sf,unit,&mine,&remote);CHKERRQ(ierr);
91295fce210SBarry Smith   ierr = PetscSFWindowOpTranslate(&op);CHKERRQ(ierr);
913*5b0d146aSStefano Zampini #if !defined(PETSC_HAVE_MPI_GET_ACCUMULATE)
914*5b0d146aSStefano Zampini   /* FetchAndOp without MPI_Get_Accumulate requires locking.
915*5b0d146aSStefano Zampini      we create a new window every time to not interfere with user-defined MPI_Info which may have used "no_locks"="true" */
916*5b0d146aSStefano Zampini   oldf = w->flavor;
917*5b0d146aSStefano Zampini   w->flavor = PETSCSF_WINDOW_FLAVOR_CREATE;
918*5b0d146aSStefano Zampini   ierr = PetscSFGetWindow(sf,unit,rootdata,PETSCSF_WINDOW_SYNC_LOCK,PETSC_FALSE,0,0,0,&target_disp,&win);CHKERRQ(ierr);
919*5b0d146aSStefano Zampini #else
920*5b0d146aSStefano Zampini   ierr = PetscSFGetWindow(sf,unit,rootdata,w->sync,PETSC_TRUE,MPI_MODE_NOPRECEDE,0,0,&target_disp,&win);CHKERRQ(ierr);
921*5b0d146aSStefano Zampini #endif
922*5b0d146aSStefano Zampini   for (i=0; i<nranks; i++) {
923*5b0d146aSStefano Zampini     MPI_Aint tdp = target_disp ? target_disp[i] : 0;
924*5b0d146aSStefano Zampini 
925*5b0d146aSStefano Zampini #if !defined(PETSC_HAVE_MPI_GET_ACCUMULATE)
926*5b0d146aSStefano Zampini     ierr = MPI_Win_lock(MPI_LOCK_EXCLUSIVE,ranks[i],0,win);CHKERRQ(ierr);
927*5b0d146aSStefano Zampini     ierr = MPI_Get(leafupdate,1,mine[i],ranks[i],tdp,1,remote[i],win);CHKERRQ(ierr);
928*5b0d146aSStefano Zampini     ierr = MPI_Accumulate((void*)leafdata,1,mine[i],ranks[i],tdp,1,remote[i],op,win);
929*5b0d146aSStefano Zampini     if (ierr) { /* intercept the MPI error since the combination of unit and op is not supported */
930*5b0d146aSStefano Zampini       PetscMPIInt len;
931*5b0d146aSStefano Zampini       char        errstring[MPI_MAX_ERROR_STRING];
932*5b0d146aSStefano Zampini 
933*5b0d146aSStefano Zampini       MPI_Error_string(ierr,errstring,&len);
934*5b0d146aSStefano Zampini       SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_SUP,"Internal error in MPI: %s",errstring);
93595fce210SBarry Smith     }
936*5b0d146aSStefano Zampini     ierr = MPI_Win_unlock(ranks[i],win);CHKERRQ(ierr);
937*5b0d146aSStefano Zampini #else
938*5b0d146aSStefano Zampini     if (w->sync == PETSCSF_WINDOW_SYNC_LOCK) { ierr = MPI_Win_lock(MPI_LOCK_SHARED,ranks[i],0,win);CHKERRQ(ierr); }
939*5b0d146aSStefano Zampini     ierr = MPI_Get_accumulate((void*)leafdata,1,mine[i],leafupdate,1,mine[i],ranks[i],tdp,1,remote[i],op,win);
940*5b0d146aSStefano Zampini     if (ierr) { /* intercept the MPI error since the combination of unit and op is not supported */
941*5b0d146aSStefano Zampini       PetscMPIInt len;
942*5b0d146aSStefano Zampini       char        errstring[MPI_MAX_ERROR_STRING];
943*5b0d146aSStefano Zampini 
944*5b0d146aSStefano Zampini       MPI_Error_string(ierr,errstring,&len);
945*5b0d146aSStefano Zampini       SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_SUP,"Internal error in MPI: %s",errstring);
946*5b0d146aSStefano Zampini     }
947*5b0d146aSStefano Zampini     if (w->sync == PETSCSF_WINDOW_SYNC_LOCK) { ierr = MPI_Win_unlock(ranks[i],win);CHKERRQ(ierr); }
948*5b0d146aSStefano Zampini #endif
949*5b0d146aSStefano Zampini   }
950*5b0d146aSStefano Zampini #if !defined(PETSC_HAVE_MPI_GET_ACCUMULATE)
951*5b0d146aSStefano Zampini   w->flavor = oldf;
952*5b0d146aSStefano Zampini #endif
95395fce210SBarry Smith   PetscFunctionReturn(0);
95495fce210SBarry Smith }
95595fce210SBarry Smith 
956eb02082bSJunchao Zhang static PetscErrorCode PetscSFFetchAndOpEnd_Window(PetscSF sf,MPI_Datatype unit,PetscMemType rootmtype,void *rootdata,PetscMemType leafmtype,const void *leafdata,void *leafupdate,MPI_Op op)
95795fce210SBarry Smith {
95895fce210SBarry Smith   PetscErrorCode ierr;
95995fce210SBarry Smith   MPI_Win        win;
960*5b0d146aSStefano Zampini #if defined(PETSC_HAVE_MPI_GET_ACCUMULATE)
961*5b0d146aSStefano Zampini   PetscSF_Window *w = (PetscSF_Window*)sf->data;
962*5b0d146aSStefano Zampini #endif
96395fce210SBarry Smith 
96495fce210SBarry Smith   PetscFunctionBegin;
96595fce210SBarry Smith   ierr = PetscSFFindWindow(sf,unit,rootdata,&win);CHKERRQ(ierr);
966*5b0d146aSStefano Zampini #if defined(PETSC_HAVE_MPI_GET_ACCUMULATE)
967*5b0d146aSStefano Zampini   ierr = PetscSFRestoreWindow(sf,unit,rootdata,w->sync,PETSC_TRUE,MPI_MODE_NOSUCCEED,PETSC_TRUE,&win);CHKERRQ(ierr);
968*5b0d146aSStefano Zampini #else
969*5b0d146aSStefano Zampini   ierr = PetscSFRestoreWindow(sf,unit,rootdata,PETSCSF_WINDOW_SYNC_LOCK,PETSC_FALSE,0,PETSC_TRUE,&win);CHKERRQ(ierr);
970*5b0d146aSStefano Zampini #endif
97195fce210SBarry Smith   PetscFunctionReturn(0);
97295fce210SBarry Smith }
97395fce210SBarry Smith 
974dec1416fSJunchao Zhang PETSC_INTERN PetscErrorCode PetscSFCreate_Window(PetscSF sf)
97595fce210SBarry Smith {
97695fce210SBarry Smith   PetscSF_Window *w = (PetscSF_Window*)sf->data;
97795fce210SBarry Smith   PetscErrorCode ierr;
97895fce210SBarry Smith 
97995fce210SBarry Smith   PetscFunctionBegin;
98095fce210SBarry Smith   sf->ops->SetUp           = PetscSFSetUp_Window;
98195fce210SBarry Smith   sf->ops->SetFromOptions  = PetscSFSetFromOptions_Window;
98295fce210SBarry Smith   sf->ops->Reset           = PetscSFReset_Window;
98395fce210SBarry Smith   sf->ops->Destroy         = PetscSFDestroy_Window;
98495fce210SBarry Smith   sf->ops->View            = PetscSFView_Window;
98595fce210SBarry Smith   sf->ops->Duplicate       = PetscSFDuplicate_Window;
986de49d1a2SJunchao Zhang   sf->ops->BcastAndOpBegin = PetscSFBcastAndOpBegin_Window;
987de49d1a2SJunchao Zhang   sf->ops->BcastAndOpEnd   = PetscSFBcastAndOpEnd_Window;
98895fce210SBarry Smith   sf->ops->ReduceBegin     = PetscSFReduceBegin_Window;
98995fce210SBarry Smith   sf->ops->ReduceEnd       = PetscSFReduceEnd_Window;
99095fce210SBarry Smith   sf->ops->FetchAndOpBegin = PetscSFFetchAndOpBegin_Window;
99195fce210SBarry Smith   sf->ops->FetchAndOpEnd   = PetscSFFetchAndOpEnd_Window;
99295fce210SBarry Smith 
993b00a9115SJed Brown   ierr = PetscNewLog(sf,&w);CHKERRQ(ierr);
99495fce210SBarry Smith   sf->data  = (void*)w;
99595fce210SBarry Smith   w->sync   = PETSCSF_WINDOW_SYNC_FENCE;
996*5b0d146aSStefano Zampini   w->flavor = PETSCSF_WINDOW_FLAVOR_CREATE;
997*5b0d146aSStefano Zampini   w->info   = MPI_INFO_NULL;
99895fce210SBarry Smith 
999bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)sf,"PetscSFWindowSetSyncType_C",PetscSFWindowSetSyncType_Window);CHKERRQ(ierr);
1000bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)sf,"PetscSFWindowGetSyncType_C",PetscSFWindowGetSyncType_Window);CHKERRQ(ierr);
1001*5b0d146aSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)sf,"PetscSFWindowSetFlavorType_C",PetscSFWindowSetFlavorType_Window);CHKERRQ(ierr);
1002*5b0d146aSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)sf,"PetscSFWindowGetFlavorType_C",PetscSFWindowGetFlavorType_Window);CHKERRQ(ierr);
1003*5b0d146aSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)sf,"PetscSFWindowSetInfo_C",PetscSFWindowSetInfo_Window);CHKERRQ(ierr);
1004*5b0d146aSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)sf,"PetscSFWindowGetInfo_C",PetscSFWindowGetInfo_Window);CHKERRQ(ierr);
100595fce210SBarry Smith 
100695fce210SBarry Smith #if defined(OMPI_MAJOR_VERSION) && (OMPI_MAJOR_VERSION < 1 || (OMPI_MAJOR_VERSION == 1 && OMPI_MINOR_VERSION <= 6))
100795fce210SBarry Smith   {
100895fce210SBarry Smith     PetscBool ackbug = PETSC_FALSE;
1009c5929fdfSBarry Smith     ierr = PetscOptionsGetBool(NULL,NULL,"-acknowledge_ompi_onesided_bug",&ackbug,NULL);CHKERRQ(ierr);
101095fce210SBarry Smith     if (ackbug) {
1011955c1f14SBarry Smith       ierr = PetscInfo(sf,"Acknowledged Open MPI bug, proceeding anyway. Expect memory corruption.\n");CHKERRQ(ierr);
101295fce210SBarry Smith     } else SETERRQ(PetscObjectComm((PetscObject)sf),PETSC_ERR_LIB,"Open MPI is known to be buggy (https://svn.open-mpi.org/trac/ompi/ticket/1905 and 2656), use -acknowledge_ompi_onesided_bug to proceed");
101395fce210SBarry Smith   }
101495fce210SBarry Smith #endif
101595fce210SBarry Smith   PetscFunctionReturn(0);
101695fce210SBarry Smith }
1017