xref: /petsc/src/vec/is/sf/impls/window/sfwindow.c (revision 4c8fdceaee2187f6ed586d920f30b56dbb227b33)
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 */
85b0d146aSStefano Zampini   PetscSFDataLink         link;   /* List of MPI data types, lazily constructed for each data type */
995fce210SBarry Smith   PetscSFWinLink          wins;   /* List of active windows */
105b0d146aSStefano Zampini   PetscSFWindowFlavorType flavor; /* Current PETSCSF_WINDOW_FLAVOR_ */
115b0d146aSStefano Zampini   PetscSF                 dynsf;
125b0d146aSStefano 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;
265b0d146aSStefano Zampini   void                    *paddr;
2795fce210SBarry Smith   MPI_Win                 win;
28684a874aSStefano Zampini   MPI_Request             *reqs;
295b0d146aSStefano Zampini   PetscSFWindowFlavorType flavor;
305b0d146aSStefano Zampini   MPI_Aint                *dyn_target_addr;
3195fce210SBarry Smith   PetscBool               epoch;
3295fce210SBarry Smith   PetscSFWinLink          next;
3395fce210SBarry Smith };
3495fce210SBarry Smith 
35*4c8fdceaSLisandro Dalcin const char *const PetscSFWindowSyncTypes[] = {"FENCE","LOCK","ACTIVE","PetscSFWindowSyncType","PETSCSF_WINDOW_SYNC_",NULL};
36*4c8fdceaSLisandro Dalcin const char *const PetscSFWindowFlavorTypes[] = {"CREATE","DYNAMIC","ALLOCATE","SHARED","PetscSFWindowFlavorType","PETSCSF_WINDOW_FLAVOR_",NULL};
3795fce210SBarry Smith 
38b2566f29SBarry Smith /* Built-in MPI_Ops act elementwise inside MPI_Accumulate, but cannot be used with composite types inside collectives (MPIU_Allreduce) */
3995fce210SBarry Smith static PetscErrorCode PetscSFWindowOpTranslate(MPI_Op *op)
4095fce210SBarry Smith {
4195fce210SBarry Smith   PetscFunctionBegin;
4295fce210SBarry Smith   if (*op == MPIU_SUM) *op = MPI_SUM;
4395fce210SBarry Smith   else if (*op == MPIU_MAX) *op = MPI_MAX;
4495fce210SBarry Smith   else if (*op == MPIU_MIN) *op = MPI_MIN;
4595fce210SBarry Smith   PetscFunctionReturn(0);
4695fce210SBarry Smith }
4795fce210SBarry Smith 
4895fce210SBarry Smith /*@C
4995fce210SBarry Smith    PetscSFWindowGetDataTypes - gets composite local and remote data types for each rank
5095fce210SBarry Smith 
5195fce210SBarry Smith    Not Collective
5295fce210SBarry Smith 
5395fce210SBarry Smith    Input Arguments:
5495fce210SBarry Smith +  sf - star forest
5595fce210SBarry Smith -  unit - data type for each node
5695fce210SBarry Smith 
5795fce210SBarry Smith    Output Arguments:
5895fce210SBarry Smith +  localtypes - types describing part of local leaf buffer referencing each remote rank
5995fce210SBarry Smith -  remotetypes - types describing part of remote root buffer referenced for each remote rank
6095fce210SBarry Smith 
6195fce210SBarry Smith    Level: developer
6295fce210SBarry Smith 
6395fce210SBarry Smith .seealso: PetscSFSetGraph(), PetscSFView()
6495fce210SBarry Smith @*/
6595fce210SBarry Smith static PetscErrorCode PetscSFWindowGetDataTypes(PetscSF sf,MPI_Datatype unit,const MPI_Datatype **localtypes,const MPI_Datatype **remotetypes)
6695fce210SBarry Smith {
6795fce210SBarry Smith   PetscSF_Window    *w = (PetscSF_Window*)sf->data;
6895fce210SBarry Smith   PetscErrorCode    ierr;
6995fce210SBarry Smith   PetscSFDataLink   link;
7095fce210SBarry Smith   PetscInt          i,nranks;
7195fce210SBarry Smith   const PetscInt    *roffset,*rmine,*rremote;
7295fce210SBarry Smith   const PetscMPIInt *ranks;
7395fce210SBarry Smith 
7495fce210SBarry Smith   PetscFunctionBegin;
7595fce210SBarry Smith   /* Look for types in cache */
7695fce210SBarry Smith   for (link=w->link; link; link=link->next) {
7795fce210SBarry Smith     PetscBool match;
7895fce210SBarry Smith     ierr = MPIPetsc_Type_compare(unit,link->unit,&match);CHKERRQ(ierr);
7995fce210SBarry Smith     if (match) {
8095fce210SBarry Smith       *localtypes  = link->mine;
8195fce210SBarry Smith       *remotetypes = link->remote;
8295fce210SBarry Smith       PetscFunctionReturn(0);
8395fce210SBarry Smith     }
8495fce210SBarry Smith   }
8595fce210SBarry Smith 
8695fce210SBarry Smith   /* Create new composite types for each send rank */
87dec1416fSJunchao Zhang   ierr = PetscSFGetRootRanks(sf,&nranks,&ranks,&roffset,&rmine,&rremote);CHKERRQ(ierr);
8895dccacaSBarry Smith   ierr = PetscNew(&link);CHKERRQ(ierr);
8995fce210SBarry Smith   ierr = MPI_Type_dup(unit,&link->unit);CHKERRQ(ierr);
90dcca6d9dSJed Brown   ierr = PetscMalloc2(nranks,&link->mine,nranks,&link->remote);CHKERRQ(ierr);
9195fce210SBarry Smith   for (i=0; i<nranks; i++) {
925b0d146aSStefano Zampini     PetscInt    rcount = roffset[i+1] - roffset[i];
9395fce210SBarry Smith     PetscMPIInt *rmine,*rremote;
9495fce210SBarry Smith #if !defined(PETSC_USE_64BIT_INDICES)
9595fce210SBarry Smith     rmine   = sf->rmine + sf->roffset[i];
9695fce210SBarry Smith     rremote = sf->rremote + sf->roffset[i];
9795fce210SBarry Smith #else
9895fce210SBarry Smith     PetscInt j;
99dcca6d9dSJed Brown     ierr = PetscMalloc2(rcount,&rmine,rcount,&rremote);CHKERRQ(ierr);
10095fce210SBarry Smith     for (j=0; j<rcount; j++) {
10195fce210SBarry Smith       ierr = PetscMPIIntCast(sf->rmine[sf->roffset[i]+j],rmine+j);CHKERRQ(ierr);
10295fce210SBarry Smith       ierr = PetscMPIIntCast(sf->rremote[sf->roffset[i]+j],rremote+j);CHKERRQ(ierr);
10395fce210SBarry Smith     }
10495fce210SBarry Smith #endif
1055b0d146aSStefano Zampini 
10695fce210SBarry Smith     ierr = MPI_Type_create_indexed_block(rcount,1,rmine,link->unit,&link->mine[i]);CHKERRQ(ierr);
10795fce210SBarry Smith     ierr = MPI_Type_create_indexed_block(rcount,1,rremote,link->unit,&link->remote[i]);CHKERRQ(ierr);
10895fce210SBarry Smith #if defined(PETSC_USE_64BIT_INDICES)
10995fce210SBarry Smith     ierr = PetscFree2(rmine,rremote);CHKERRQ(ierr);
11095fce210SBarry Smith #endif
11195fce210SBarry Smith     ierr = MPI_Type_commit(&link->mine[i]);CHKERRQ(ierr);
11295fce210SBarry Smith     ierr = MPI_Type_commit(&link->remote[i]);CHKERRQ(ierr);
11395fce210SBarry Smith   }
11495fce210SBarry Smith   link->next = w->link;
11595fce210SBarry Smith   w->link    = link;
11695fce210SBarry Smith 
11795fce210SBarry Smith   *localtypes  = link->mine;
11895fce210SBarry Smith   *remotetypes = link->remote;
11995fce210SBarry Smith   PetscFunctionReturn(0);
12095fce210SBarry Smith }
12195fce210SBarry Smith 
12295fce210SBarry Smith /*@C
1235b0d146aSStefano Zampini    PetscSFWindowSetFlavorType - Set flavor type for MPI_Win creation
1245b0d146aSStefano Zampini 
1255b0d146aSStefano Zampini    Logically Collective
1265b0d146aSStefano Zampini 
1275b0d146aSStefano Zampini    Input Arguments:
1285b0d146aSStefano Zampini +  sf - star forest for communication
1295b0d146aSStefano Zampini -  flavor - flavor type
1305b0d146aSStefano Zampini 
1315b0d146aSStefano Zampini    Options Database Key:
1325b0d146aSStefano Zampini .  -sf_window_flavor <flavor> - sets the flavor type CREATE, DYNAMIC, ALLOCATE or SHARED (see PetscSFWindowFlavorType)
1335b0d146aSStefano Zampini 
1345b0d146aSStefano Zampini    Level: advanced
1355b0d146aSStefano Zampini 
1365b0d146aSStefano Zampini    Notes: Windows reusage follow this rules:
1375b0d146aSStefano Zampini 
1385b0d146aSStefano Zampini      PETSCSF_WINDOW_FLAVOR_CREATE: creates a new window every time, uses MPI_Win_create
1395b0d146aSStefano Zampini 
1405b0d146aSStefano 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.
1415b0d146aSStefano Zampini        for i=1 to K
1425b0d146aSStefano Zampini          PetscSFOperationBegin(rootdata1,leafdata_whatever);
1435b0d146aSStefano Zampini          PetscSFOperationEnd(rootdata1,leafdata_whatever);
1445b0d146aSStefano Zampini          ...
1455b0d146aSStefano Zampini          PetscSFOperationBegin(rootdataN,leafdata_whatever);
1465b0d146aSStefano Zampini          PetscSFOperationEnd(rootdataN,leafdata_whatever);
1475b0d146aSStefano Zampini        endfor
1485b0d146aSStefano Zampini        The following pattern will instead raise an error
1495b0d146aSStefano Zampini          PetscSFOperationBegin(rootdata1,leafdata_whatever);
1505b0d146aSStefano Zampini          PetscSFOperationEnd(rootdata1,leafdata_whatever);
1515b0d146aSStefano Zampini          PetscSFOperationBegin(rank ? rootdata1 : rootdata2,leafdata_whatever);
1525b0d146aSStefano Zampini          PetscSFOperationEnd(rank ? rootdata1 : rootdata2,leafdata_whatever);
1535b0d146aSStefano Zampini 
1545b0d146aSStefano Zampini      PETSCSF_WINDOW_FLAVOR_ALLOCATE: uses MPI_Win_allocate, reuses any pre-existing window which fits the data and it is not in use
1555b0d146aSStefano Zampini 
1565b0d146aSStefano Zampini      PETSCSF_WINDOW_FLAVOR_SHARED: uses MPI_Win_allocate_shared, reusage policy as for PETSCSF_WINDOW_FLAVOR_ALLOCATE
1575b0d146aSStefano Zampini 
1585b0d146aSStefano Zampini .seealso: PetscSFSetFromOptions(), PetscSFWindowGetFlavorType()
1595b0d146aSStefano Zampini @*/
1605b0d146aSStefano Zampini PetscErrorCode PetscSFWindowSetFlavorType(PetscSF sf,PetscSFWindowFlavorType flavor)
1615b0d146aSStefano Zampini {
1625b0d146aSStefano Zampini   PetscErrorCode ierr;
1635b0d146aSStefano Zampini 
1645b0d146aSStefano Zampini   PetscFunctionBegin;
1655b0d146aSStefano Zampini   PetscValidHeaderSpecific(sf,PETSCSF_CLASSID,1);
1665b0d146aSStefano Zampini   PetscValidLogicalCollectiveEnum(sf,flavor,2);
1675b0d146aSStefano Zampini   ierr = PetscTryMethod(sf,"PetscSFWindowSetFlavorType_C",(PetscSF,PetscSFWindowFlavorType),(sf,flavor));CHKERRQ(ierr);
1685b0d146aSStefano Zampini   PetscFunctionReturn(0);
1695b0d146aSStefano Zampini }
1705b0d146aSStefano Zampini 
1715b0d146aSStefano Zampini static PetscErrorCode PetscSFWindowSetFlavorType_Window(PetscSF sf,PetscSFWindowFlavorType flavor)
1725b0d146aSStefano Zampini {
1735b0d146aSStefano Zampini   PetscSF_Window *w = (PetscSF_Window*)sf->data;
1745b0d146aSStefano Zampini 
1755b0d146aSStefano Zampini   PetscFunctionBegin;
1765b0d146aSStefano Zampini   w->flavor = flavor;
1775b0d146aSStefano Zampini   PetscFunctionReturn(0);
1785b0d146aSStefano Zampini }
1795b0d146aSStefano Zampini 
1805b0d146aSStefano Zampini /*@C
1815b0d146aSStefano Zampini    PetscSFWindowGetFlavorType - Get flavor type for PetscSF communication
1825b0d146aSStefano Zampini 
1835b0d146aSStefano Zampini    Logically Collective
1845b0d146aSStefano Zampini 
1855b0d146aSStefano Zampini    Input Argument:
1865b0d146aSStefano Zampini .  sf - star forest for communication
1875b0d146aSStefano Zampini 
1885b0d146aSStefano Zampini    Output Argument:
1895b0d146aSStefano Zampini .  flavor - flavor type
1905b0d146aSStefano Zampini 
1915b0d146aSStefano Zampini    Level: advanced
1925b0d146aSStefano Zampini 
1935b0d146aSStefano Zampini .seealso: PetscSFSetFromOptions(), PetscSFWindowSetFlavorType()
1945b0d146aSStefano Zampini @*/
1955b0d146aSStefano Zampini PetscErrorCode PetscSFWindowGetFlavorType(PetscSF sf,PetscSFWindowFlavorType *flavor)
1965b0d146aSStefano Zampini {
1975b0d146aSStefano Zampini   PetscErrorCode ierr;
1985b0d146aSStefano Zampini 
1995b0d146aSStefano Zampini   PetscFunctionBegin;
2005b0d146aSStefano Zampini   PetscValidHeaderSpecific(sf,PETSCSF_CLASSID,1);
2015b0d146aSStefano Zampini   PetscValidPointer(flavor,2);
2025b0d146aSStefano Zampini   ierr = PetscUseMethod(sf,"PetscSFWindowGetFlavorType_C",(PetscSF,PetscSFWindowFlavorType*),(sf,flavor));CHKERRQ(ierr);
2035b0d146aSStefano Zampini   PetscFunctionReturn(0);
2045b0d146aSStefano Zampini }
2055b0d146aSStefano Zampini 
2065b0d146aSStefano Zampini static PetscErrorCode PetscSFWindowGetFlavorType_Window(PetscSF sf,PetscSFWindowFlavorType *flavor)
2075b0d146aSStefano Zampini {
2085b0d146aSStefano Zampini   PetscSF_Window *w = (PetscSF_Window*)sf->data;
2095b0d146aSStefano Zampini 
2105b0d146aSStefano Zampini   PetscFunctionBegin;
2115b0d146aSStefano Zampini   *flavor = w->flavor;
2125b0d146aSStefano Zampini   PetscFunctionReturn(0);
2135b0d146aSStefano Zampini }
2145b0d146aSStefano Zampini 
2155b0d146aSStefano Zampini /*@C
2165b0d146aSStefano Zampini    PetscSFWindowSetSyncType - Set synchronization type for PetscSF communication
21795fce210SBarry Smith 
21895fce210SBarry Smith    Logically Collective
21995fce210SBarry Smith 
22095fce210SBarry Smith    Input Arguments:
22195fce210SBarry Smith +  sf - star forest for communication
22295fce210SBarry Smith -  sync - synchronization type
22395fce210SBarry Smith 
22495fce210SBarry Smith    Options Database Key:
22560263706SJed Brown .  -sf_window_sync <sync> - sets the synchronization type FENCE, LOCK, or ACTIVE (see PetscSFWindowSyncType)
22695fce210SBarry Smith 
22795fce210SBarry Smith    Level: advanced
22895fce210SBarry Smith 
22995fce210SBarry Smith .seealso: PetscSFSetFromOptions(), PetscSFWindowGetSyncType()
23095fce210SBarry Smith @*/
23195fce210SBarry Smith PetscErrorCode PetscSFWindowSetSyncType(PetscSF sf,PetscSFWindowSyncType sync)
23295fce210SBarry Smith {
23395fce210SBarry Smith   PetscErrorCode ierr;
23495fce210SBarry Smith 
23595fce210SBarry Smith   PetscFunctionBegin;
23695fce210SBarry Smith   PetscValidHeaderSpecific(sf,PETSCSF_CLASSID,1);
23795fce210SBarry Smith   PetscValidLogicalCollectiveEnum(sf,sync,2);
2385b0d146aSStefano Zampini   ierr = PetscTryMethod(sf,"PetscSFWindowSetSyncType_C",(PetscSF,PetscSFWindowSyncType),(sf,sync));CHKERRQ(ierr);
23995fce210SBarry Smith   PetscFunctionReturn(0);
24095fce210SBarry Smith }
24195fce210SBarry Smith 
242f7a08781SBarry Smith static PetscErrorCode PetscSFWindowSetSyncType_Window(PetscSF sf,PetscSFWindowSyncType sync)
24395fce210SBarry Smith {
24495fce210SBarry Smith   PetscSF_Window *w = (PetscSF_Window*)sf->data;
24595fce210SBarry Smith 
24695fce210SBarry Smith   PetscFunctionBegin;
24795fce210SBarry Smith   w->sync = sync;
24895fce210SBarry Smith   PetscFunctionReturn(0);
24995fce210SBarry Smith }
25095fce210SBarry Smith 
25195fce210SBarry Smith /*@C
2525b0d146aSStefano Zampini    PetscSFWindowGetSyncType - Get synchronization type for PetscSF communication
25395fce210SBarry Smith 
25495fce210SBarry Smith    Logically Collective
25595fce210SBarry Smith 
25695fce210SBarry Smith    Input Argument:
25795fce210SBarry Smith .  sf - star forest for communication
25895fce210SBarry Smith 
25995fce210SBarry Smith    Output Argument:
26095fce210SBarry Smith .  sync - synchronization type
26195fce210SBarry Smith 
26295fce210SBarry Smith    Level: advanced
26395fce210SBarry Smith 
2645b0d146aSStefano Zampini .seealso: PetscSFSetFromOptions(), PetscSFWindowSetSyncType()
26595fce210SBarry Smith @*/
26695fce210SBarry Smith PetscErrorCode PetscSFWindowGetSyncType(PetscSF sf,PetscSFWindowSyncType *sync)
26795fce210SBarry Smith {
26895fce210SBarry Smith   PetscErrorCode ierr;
26995fce210SBarry Smith 
27095fce210SBarry Smith   PetscFunctionBegin;
27195fce210SBarry Smith   PetscValidHeaderSpecific(sf,PETSCSF_CLASSID,1);
27295fce210SBarry Smith   PetscValidPointer(sync,2);
273163d334eSBarry Smith   ierr = PetscUseMethod(sf,"PetscSFWindowGetSyncType_C",(PetscSF,PetscSFWindowSyncType*),(sf,sync));CHKERRQ(ierr);
27495fce210SBarry Smith   PetscFunctionReturn(0);
27595fce210SBarry Smith }
27695fce210SBarry Smith 
277f7a08781SBarry Smith static PetscErrorCode PetscSFWindowGetSyncType_Window(PetscSF sf,PetscSFWindowSyncType *sync)
27895fce210SBarry Smith {
27995fce210SBarry Smith   PetscSF_Window *w = (PetscSF_Window*)sf->data;
28095fce210SBarry Smith 
28195fce210SBarry Smith   PetscFunctionBegin;
28295fce210SBarry Smith   *sync = w->sync;
28395fce210SBarry Smith   PetscFunctionReturn(0);
28495fce210SBarry Smith }
28595fce210SBarry Smith 
28695fce210SBarry Smith /*@C
2875b0d146aSStefano Zampini    PetscSFWindowSetInfo - Set the MPI_Info handle that will be used for subsequent windows allocation
2885b0d146aSStefano Zampini 
2895b0d146aSStefano Zampini    Logically Collective
2905b0d146aSStefano Zampini 
2915b0d146aSStefano Zampini    Input Argument:
2925b0d146aSStefano Zampini +  sf - star forest for communication
2935b0d146aSStefano Zampini -  info - MPI_Info handle
2945b0d146aSStefano Zampini 
2955b0d146aSStefano Zampini    Level: advanced
2965b0d146aSStefano Zampini 
2975b0d146aSStefano Zampini    Notes: the info handle is duplicated with a call to MPI_Info_dup unless info = MPI_INFO_NULL.
2985b0d146aSStefano Zampini 
2995b0d146aSStefano Zampini .seealso: PetscSFSetFromOptions(), PetscSFWindowGetInfo()
3005b0d146aSStefano Zampini @*/
3015b0d146aSStefano Zampini PetscErrorCode PetscSFWindowSetInfo(PetscSF sf,MPI_Info info)
3025b0d146aSStefano Zampini {
3035b0d146aSStefano Zampini   PetscErrorCode ierr;
3045b0d146aSStefano Zampini 
3055b0d146aSStefano Zampini   PetscFunctionBegin;
3065b0d146aSStefano Zampini   PetscValidHeaderSpecific(sf,PETSCSF_CLASSID,1);
3075b0d146aSStefano Zampini   ierr = PetscTryMethod(sf,"PetscSFWindowSetInfo_C",(PetscSF,MPI_Info),(sf,info));CHKERRQ(ierr);
3085b0d146aSStefano Zampini   PetscFunctionReturn(0);
3095b0d146aSStefano Zampini }
3105b0d146aSStefano Zampini 
3115b0d146aSStefano Zampini static PetscErrorCode PetscSFWindowSetInfo_Window(PetscSF sf,MPI_Info info)
3125b0d146aSStefano Zampini {
3135b0d146aSStefano Zampini   PetscSF_Window *w = (PetscSF_Window*)sf->data;
3145b0d146aSStefano Zampini   PetscErrorCode ierr;
3155b0d146aSStefano Zampini 
3165b0d146aSStefano Zampini   PetscFunctionBegin;
3175b0d146aSStefano Zampini   if (w->info != MPI_INFO_NULL) {
3185b0d146aSStefano Zampini     ierr = MPI_Info_free(&w->info);CHKERRQ(ierr);
3195b0d146aSStefano Zampini   }
3205b0d146aSStefano Zampini   if (info != MPI_INFO_NULL) {
3215b0d146aSStefano Zampini     ierr = MPI_Info_dup(info,&w->info);CHKERRQ(ierr);
3225b0d146aSStefano Zampini   }
3235b0d146aSStefano Zampini   PetscFunctionReturn(0);
3245b0d146aSStefano Zampini }
3255b0d146aSStefano Zampini 
3265b0d146aSStefano Zampini /*@C
3275b0d146aSStefano Zampini    PetscSFWindowGetInfo - Get the MPI_Info handle used for windows allocation
3285b0d146aSStefano Zampini 
3295b0d146aSStefano Zampini    Logically Collective
3305b0d146aSStefano Zampini 
3315b0d146aSStefano Zampini    Input Argument:
3325b0d146aSStefano Zampini .  sf - star forest for communication
3335b0d146aSStefano Zampini 
3345b0d146aSStefano Zampini    Output Argument:
3355b0d146aSStefano Zampini .  info - MPI_Info handle
3365b0d146aSStefano Zampini 
3375b0d146aSStefano Zampini    Level: advanced
3385b0d146aSStefano Zampini 
3395b0d146aSStefano Zampini    Notes: if PetscSFWindowSetInfo() has not be called, this returns MPI_INFO_NULL
3405b0d146aSStefano Zampini 
3415b0d146aSStefano Zampini .seealso: PetscSFSetFromOptions(), PetscSFWindowSetInfo()
3425b0d146aSStefano Zampini @*/
3435b0d146aSStefano Zampini PetscErrorCode PetscSFWindowGetInfo(PetscSF sf,MPI_Info *info)
3445b0d146aSStefano Zampini {
3455b0d146aSStefano Zampini   PetscErrorCode ierr;
3465b0d146aSStefano Zampini 
3475b0d146aSStefano Zampini   PetscFunctionBegin;
3485b0d146aSStefano Zampini   PetscValidHeaderSpecific(sf,PETSCSF_CLASSID,1);
3495b0d146aSStefano Zampini   PetscValidPointer(info,2);
3505b0d146aSStefano Zampini   ierr = PetscUseMethod(sf,"PetscSFWindowGetInfo_C",(PetscSF,MPI_Info*),(sf,info));CHKERRQ(ierr);
3515b0d146aSStefano Zampini   PetscFunctionReturn(0);
3525b0d146aSStefano Zampini }
3535b0d146aSStefano Zampini 
3545b0d146aSStefano Zampini static PetscErrorCode PetscSFWindowGetInfo_Window(PetscSF sf,MPI_Info *info)
3555b0d146aSStefano Zampini {
3565b0d146aSStefano Zampini   PetscSF_Window *w = (PetscSF_Window*)sf->data;
3575b0d146aSStefano Zampini 
3585b0d146aSStefano Zampini   PetscFunctionBegin;
3595b0d146aSStefano Zampini   *info = w->info;
3605b0d146aSStefano Zampini   PetscFunctionReturn(0);
3615b0d146aSStefano Zampini }
3625b0d146aSStefano Zampini 
3635b0d146aSStefano Zampini /*
36495fce210SBarry Smith    PetscSFGetWindow - Get a window for use with a given data type
36595fce210SBarry Smith 
36695fce210SBarry Smith    Collective on PetscSF
36795fce210SBarry Smith 
36895fce210SBarry Smith    Input Arguments:
36995fce210SBarry Smith +  sf - star forest
37095fce210SBarry Smith .  unit - data type
37195fce210SBarry Smith .  array - array to be sent
3725b0d146aSStefano Zampini .  sync - type of synchronization PetscSFWindowSyncType
37395fce210SBarry Smith .  epoch - PETSC_TRUE to acquire the window and start an epoch, PETSC_FALSE to just acquire the window
3745b0d146aSStefano Zampini .  fenceassert - assert parameter for call to MPI_Win_fence(), if sync == PETSCSF_WINDOW_SYNC_FENCE
3755b0d146aSStefano Zampini .  postassert - assert parameter for call to MPI_Win_post(), if sync == PETSCSF_WINDOW_SYNC_ACTIVE
376684a874aSStefano Zampini -  startassert - assert parameter for call to MPI_Win_start(), if sync == PETSCSF_WINDOW_SYNC_ACTIVE
37795fce210SBarry Smith 
37895fce210SBarry Smith    Output Arguments:
379684a874aSStefano Zampini +  target_disp - target_disp argument for RMA calls (significative for PETSCSF_WINDOW_FLAVOR_DYNAMIC only)
380684a874aSStefano Zampini +  reqs - array of requests (significative for sync == PETSCSF_WINDOW_SYNC_LOCK only)
381684a874aSStefano Zampini -  win - window
38295fce210SBarry Smith 
38395fce210SBarry Smith    Level: developer
384dec1416fSJunchao Zhang .seealso: PetscSFGetRootRanks(), PetscSFWindowGetDataTypes()
3855b0d146aSStefano Zampini */
386684a874aSStefano 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_Request **reqs, MPI_Win *win)
38795fce210SBarry Smith {
38895fce210SBarry Smith   PetscSF_Window *w = (PetscSF_Window*)sf->data;
38995fce210SBarry Smith   PetscErrorCode ierr;
39095fce210SBarry Smith   MPI_Aint       lb,lb_true,bytes,bytes_true;
39195fce210SBarry Smith   PetscSFWinLink link;
3925b0d146aSStefano Zampini   MPI_Aint       winaddr;
3935b0d146aSStefano Zampini   PetscInt       nranks;
3945b0d146aSStefano Zampini   PetscBool      reuse = PETSC_FALSE, update = PETSC_FALSE;
3955b0d146aSStefano Zampini   PetscBool      dummy[2];
3965b0d146aSStefano 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");
4035b0d146aSStefano Zampini   if (w->flavor != PETSCSF_WINDOW_FLAVOR_CREATE) reuse = PETSC_TRUE;
4045b0d146aSStefano Zampini   for (link=w->wins; reuse && link; link=link->next) {
4055b0d146aSStefano Zampini     PetscBool winok = PETSC_FALSE;
4065b0d146aSStefano Zampini     if (w->flavor != link->flavor) continue;
4075b0d146aSStefano Zampini     switch (w->flavor) {
4085b0d146aSStefano 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) */
4095b0d146aSStefano Zampini       if (array == link->addr) {
41076bd3646SJed Brown         if (PetscDefined(USE_DEBUG)) {
4115b0d146aSStefano Zampini           dummy[0] = PETSC_TRUE;
4125b0d146aSStefano Zampini           dummy[1] = PETSC_TRUE;
4135b0d146aSStefano Zampini           ierr = MPI_Allreduce(MPI_IN_PLACE,dummy  ,1,MPIU_BOOL,MPI_LAND,PetscObjectComm((PetscObject)sf));CHKERRQ(ierr);
4145b0d146aSStefano Zampini           ierr = MPI_Allreduce(MPI_IN_PLACE,dummy+1,1,MPIU_BOOL,MPI_LOR ,PetscObjectComm((PetscObject)sf));CHKERRQ(ierr);
4155b0d146aSStefano 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");
41676bd3646SJed Brown         }
4175b0d146aSStefano Zampini         if (link->inuse) SETERRQ(PetscObjectComm((PetscObject)sf),PETSC_ERR_PLIB,"Window in use");
4185b0d146aSStefano Zampini         if (epoch && link->epoch) SETERRQ(PetscObjectComm((PetscObject)sf),PETSC_ERR_PLIB,"Window epoch not finished");
4195b0d146aSStefano Zampini         winok = PETSC_TRUE;
4205b0d146aSStefano Zampini         link->paddr = array;
42176bd3646SJed Brown       } else if (PetscDefined(USE_DEBUG)) {
4225b0d146aSStefano Zampini         dummy[0] = PETSC_FALSE;
4235b0d146aSStefano Zampini         dummy[1] = PETSC_FALSE;
4245b0d146aSStefano Zampini         ierr = MPI_Allreduce(MPI_IN_PLACE,dummy  ,1,MPIU_BOOL,MPI_LAND,PetscObjectComm((PetscObject)sf));CHKERRQ(ierr);
4255b0d146aSStefano Zampini         ierr = MPI_Allreduce(MPI_IN_PLACE,dummy+1,1,MPIU_BOOL,MPI_LOR ,PetscObjectComm((PetscObject)sf));CHKERRQ(ierr);
4265b0d146aSStefano 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");
4275b0d146aSStefano Zampini       }
4285b0d146aSStefano Zampini       break;
4295b0d146aSStefano Zampini     case PETSCSF_WINDOW_FLAVOR_ALLOCATE: /* check available by matching size, allocate if in use */
4305b0d146aSStefano Zampini     case PETSCSF_WINDOW_FLAVOR_SHARED:
4315b0d146aSStefano Zampini       if (!link->inuse && bytes == (MPI_Aint)link->bytes) {
4325b0d146aSStefano Zampini         update = PETSC_TRUE;
4335b0d146aSStefano Zampini         link->paddr = array;
4345b0d146aSStefano Zampini         winok = PETSC_TRUE;
4355b0d146aSStefano Zampini       }
4365b0d146aSStefano Zampini       break;
4375b0d146aSStefano Zampini     default: SETERRQ1(PetscObjectComm((PetscObject)sf),PETSC_ERR_SUP,"No support for flavor %s",PetscSFWindowFlavorTypes[w->flavor]);
4385b0d146aSStefano Zampini     }
4395b0d146aSStefano Zampini     if (winok) {
4405b0d146aSStefano Zampini       *win = link->win;
4415b0d146aSStefano Zampini       ierr = PetscInfo3(sf,"Reusing window %d of flavor %d for comm %d\n",link->win,link->flavor,PetscObjectComm((PetscObject)sf));CHKERRQ(ierr);
4425b0d146aSStefano Zampini       goto found;
4435b0d146aSStefano Zampini     }
4445b0d146aSStefano Zampini   }
4455b0d146aSStefano Zampini 
4465b0d146aSStefano Zampini   wsize = (MPI_Aint)bytes*sf->nroots;
44795dccacaSBarry Smith   ierr = PetscNew(&link);CHKERRQ(ierr);
44895fce210SBarry Smith   link->bytes           = bytes;
44995fce210SBarry Smith   link->next            = w->wins;
4505b0d146aSStefano Zampini   link->flavor          = w->flavor;
4515b0d146aSStefano Zampini   link->dyn_target_addr = NULL;
452684a874aSStefano Zampini   link->reqs            = NULL;
45395fce210SBarry Smith   w->wins               = link;
454684a874aSStefano Zampini   if (sync == PETSCSF_WINDOW_SYNC_LOCK) {
455684a874aSStefano Zampini     PetscInt i;
456684a874aSStefano Zampini 
457684a874aSStefano Zampini     ierr = PetscMalloc1(sf->nranks,&link->reqs);CHKERRQ(ierr);
458684a874aSStefano Zampini     for (i = 0; i < sf->nranks; i++) link->reqs[i] = MPI_REQUEST_NULL;
459684a874aSStefano Zampini   }
4605b0d146aSStefano Zampini   switch (w->flavor) {
4615b0d146aSStefano Zampini   case PETSCSF_WINDOW_FLAVOR_CREATE:
4625b0d146aSStefano Zampini     ierr = MPI_Win_create(array,wsize,(PetscMPIInt)bytes,w->info,PetscObjectComm((PetscObject)sf),&link->win);CHKERRQ(ierr);
4635b0d146aSStefano Zampini     link->addr  = array;
4645b0d146aSStefano Zampini     link->paddr = array;
4655b0d146aSStefano Zampini     break;
4665b0d146aSStefano Zampini   case PETSCSF_WINDOW_FLAVOR_DYNAMIC:
4675b0d146aSStefano Zampini     ierr = MPI_Win_create_dynamic(w->info,PetscObjectComm((PetscObject)sf),&link->win);CHKERRQ(ierr);
4685b0d146aSStefano Zampini #if defined(PETSC_HAVE_OMPI_MAJOR_VERSION) /* some OpenMPI versions do not support MPI_Win_attach(win,NULL,0); */
4695b0d146aSStefano Zampini     ierr = MPI_Win_attach(link->win,wsize ? array : &ierr,wsize);CHKERRQ(ierr);
4705b0d146aSStefano Zampini #else
4715b0d146aSStefano Zampini     ierr = MPI_Win_attach(link->win,array,wsize);CHKERRQ(ierr);
4725b0d146aSStefano Zampini #endif
4735b0d146aSStefano Zampini     link->addr  = array;
4745b0d146aSStefano Zampini     link->paddr = array;
4755b0d146aSStefano Zampini     if (!w->dynsf) SETERRQ(PetscObjectComm((PetscObject)sf),PETSC_ERR_ORDER,"Must call PetscSFSetUp()");
4765b0d146aSStefano Zampini     ierr = PetscSFSetUp(w->dynsf);CHKERRQ(ierr);
4775b0d146aSStefano Zampini     ierr = PetscSFGetRootRanks(w->dynsf,&nranks,NULL,NULL,NULL,NULL);CHKERRQ(ierr);
4785b0d146aSStefano Zampini     ierr = PetscMalloc1(nranks,&link->dyn_target_addr);CHKERRQ(ierr);
4795b0d146aSStefano Zampini     ierr = MPI_Get_address(array,&winaddr);CHKERRQ(ierr);
4805b0d146aSStefano Zampini     ierr = PetscSFBcastBegin(w->dynsf,MPI_AINT,&winaddr,link->dyn_target_addr);CHKERRQ(ierr);
4815b0d146aSStefano Zampini     ierr = PetscSFBcastEnd(w->dynsf,MPI_AINT,&winaddr,link->dyn_target_addr);CHKERRQ(ierr);
4825b0d146aSStefano Zampini     break;
4835b0d146aSStefano Zampini   case PETSCSF_WINDOW_FLAVOR_ALLOCATE:
4845b0d146aSStefano Zampini     ierr = MPI_Win_allocate(wsize,(PetscMPIInt)bytes,w->info,PetscObjectComm((PetscObject)sf),&link->addr,&link->win);CHKERRQ(ierr);
4855b0d146aSStefano Zampini     update = PETSC_TRUE;
4865b0d146aSStefano Zampini     link->paddr = array;
4875b0d146aSStefano Zampini     break;
4885b0d146aSStefano Zampini #if defined(PETSC_HAVE_MPI_PROCESS_SHARED_MEMORY)
4895b0d146aSStefano Zampini   case PETSCSF_WINDOW_FLAVOR_SHARED:
4905b0d146aSStefano Zampini     ierr = MPI_Win_allocate_shared(wsize,(PetscMPIInt)bytes,w->info,PetscObjectComm((PetscObject)sf),&link->addr,&link->win);CHKERRQ(ierr);
4915b0d146aSStefano Zampini     update = PETSC_TRUE;
4925b0d146aSStefano Zampini     link->paddr = array;
4935b0d146aSStefano Zampini     break;
4945b0d146aSStefano Zampini #endif
4955b0d146aSStefano Zampini   default: SETERRQ1(PetscObjectComm((PetscObject)sf),PETSC_ERR_SUP,"No support for flavor %s",PetscSFWindowFlavorTypes[w->flavor]);
4965b0d146aSStefano Zampini   }
4975b0d146aSStefano Zampini   ierr = PetscInfo3(sf,"New window %d of flavor %d for comm %d\n",link->win,link->flavor,PetscObjectComm((PetscObject)sf));CHKERRQ(ierr);
49895fce210SBarry Smith   *win = link->win;
49995fce210SBarry Smith 
5005b0d146aSStefano Zampini found:
5015b0d146aSStefano Zampini 
502684a874aSStefano Zampini   if (target_disp) *target_disp = link->dyn_target_addr;
503684a874aSStefano Zampini   if (reqs) *reqs = link->reqs;
504684a874aSStefano Zampini   if (update) { /* locks are needed for the "separate" memory model only, the fence guaranties memory-synchronization */
505684a874aSStefano Zampini     PetscMPIInt rank;
506684a874aSStefano Zampini 
507684a874aSStefano Zampini     ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)sf),&rank);CHKERRQ(ierr);
508684a874aSStefano Zampini     if (sync == PETSCSF_WINDOW_SYNC_LOCK) { ierr = MPI_Win_lock(MPI_LOCK_EXCLUSIVE,rank,MPI_MODE_NOCHECK,*win);CHKERRQ(ierr); }
5095b0d146aSStefano Zampini     ierr = PetscMemcpy(link->addr,array,sf->nroots*bytes);CHKERRQ(ierr);
5105b0d146aSStefano Zampini     if (sync == PETSCSF_WINDOW_SYNC_LOCK) {
511684a874aSStefano Zampini       ierr = MPI_Win_unlock(rank,*win);CHKERRQ(ierr);
5125b0d146aSStefano Zampini       ierr = MPI_Win_fence(0,*win);CHKERRQ(ierr);
5135b0d146aSStefano Zampini     }
5145b0d146aSStefano Zampini   }
5155b0d146aSStefano Zampini   link->inuse = PETSC_TRUE;
5165b0d146aSStefano Zampini   link->epoch = epoch;
51795fce210SBarry Smith   if (epoch) {
5185b0d146aSStefano Zampini     switch (sync) {
51995fce210SBarry Smith     case PETSCSF_WINDOW_SYNC_FENCE:
52095fce210SBarry Smith       ierr = MPI_Win_fence(fenceassert,*win);CHKERRQ(ierr);
52195fce210SBarry Smith       break;
52295fce210SBarry Smith     case PETSCSF_WINDOW_SYNC_LOCK: /* Handled outside */
52395fce210SBarry Smith       break;
52495fce210SBarry Smith     case PETSCSF_WINDOW_SYNC_ACTIVE: {
52595fce210SBarry Smith       MPI_Group   ingroup,outgroup;
5265b0d146aSStefano Zampini       PetscMPIInt isize,osize;
5275b0d146aSStefano Zampini 
5285b0d146aSStefano Zampini       /* OpenMPI 4.0.2 with btl=vader does not like calling
5295b0d146aSStefano Zampini          - MPI_Win_complete when ogroup is empty
5305b0d146aSStefano Zampini          - MPI_Win_wait when igroup is empty
5315b0d146aSStefano Zampini          So, we do not even issue the corresponding start and post calls
5325b0d146aSStefano Zampini          The MPI standard (Sec. 11.5.2 of MPI 3.1) only requires that
5335b0d146aSStefano Zampini          start(outgroup) has a matching post(ingroup)
5345b0d146aSStefano Zampini          and this is guaranteed by PetscSF
5355b0d146aSStefano Zampini       */
53695fce210SBarry Smith       ierr = PetscSFGetGroups(sf,&ingroup,&outgroup);CHKERRQ(ierr);
5375b0d146aSStefano Zampini       ierr = MPI_Group_size(ingroup,&isize);CHKERRQ(ierr);
5385b0d146aSStefano Zampini       ierr = MPI_Group_size(outgroup,&osize);CHKERRQ(ierr);
5395b0d146aSStefano Zampini       if (isize) { ierr = MPI_Win_post(ingroup,postassert,*win);CHKERRQ(ierr); }
5405b0d146aSStefano Zampini       if (osize) { ierr = MPI_Win_start(outgroup,startassert,*win);CHKERRQ(ierr); }
54195fce210SBarry Smith     } break;
54295fce210SBarry Smith     default: SETERRQ(PetscObjectComm((PetscObject)sf),PETSC_ERR_PLIB,"Unknown synchronization type");
54395fce210SBarry Smith     }
54495fce210SBarry Smith   }
54595fce210SBarry Smith   PetscFunctionReturn(0);
54695fce210SBarry Smith }
54795fce210SBarry Smith 
5485b0d146aSStefano Zampini /*
54995fce210SBarry Smith    PetscSFFindWindow - Finds a window that is already in use
55095fce210SBarry Smith 
55195fce210SBarry Smith    Not Collective
55295fce210SBarry Smith 
55395fce210SBarry Smith    Input Arguments:
55495fce210SBarry Smith +  sf - star forest
55595fce210SBarry Smith .  unit - data type
55695fce210SBarry Smith -  array - array with which the window is associated
55795fce210SBarry Smith 
55895fce210SBarry Smith    Output Arguments:
559684a874aSStefano Zampini +  win - window
560684a874aSStefano Zampini -  reqs - outstanding requests associated to the window
56195fce210SBarry Smith 
56295fce210SBarry Smith    Level: developer
56395fce210SBarry Smith 
56495fce210SBarry Smith .seealso: PetscSFGetWindow(), PetscSFRestoreWindow()
5655b0d146aSStefano Zampini */
566684a874aSStefano Zampini static PetscErrorCode PetscSFFindWindow(PetscSF sf,MPI_Datatype unit,const void *array,MPI_Win *win,MPI_Request **reqs)
56795fce210SBarry Smith {
56895fce210SBarry Smith   PetscSF_Window *w = (PetscSF_Window*)sf->data;
56995fce210SBarry Smith   PetscSFWinLink link;
5705b0d146aSStefano Zampini   PetscErrorCode ierr;
57195fce210SBarry Smith 
57295fce210SBarry Smith   PetscFunctionBegin;
573c0cd0301SJed Brown   *win = MPI_WIN_NULL;
57495fce210SBarry Smith   for (link=w->wins; link; link=link->next) {
5755b0d146aSStefano Zampini     if (array == link->paddr) {
5765b0d146aSStefano Zampini       ierr = PetscInfo3(sf,"Window %d of flavor %d for comm %d\n",link->win,link->flavor,PetscObjectComm((PetscObject)sf));CHKERRQ(ierr);
57795fce210SBarry Smith       *win = link->win;
578684a874aSStefano Zampini       *reqs = link->reqs;
57995fce210SBarry Smith       PetscFunctionReturn(0);
58095fce210SBarry Smith     }
58195fce210SBarry Smith   }
58295fce210SBarry Smith   SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Requested window not in use");
58395fce210SBarry Smith   PetscFunctionReturn(0);
58495fce210SBarry Smith }
58595fce210SBarry Smith 
5865b0d146aSStefano Zampini /*
58795fce210SBarry Smith    PetscSFRestoreWindow - Restores a window obtained with PetscSFGetWindow()
58895fce210SBarry Smith 
58995fce210SBarry Smith    Collective
59095fce210SBarry Smith 
59195fce210SBarry Smith    Input Arguments:
59295fce210SBarry Smith +  sf - star forest
59395fce210SBarry Smith .  unit - data type
59495fce210SBarry Smith .  array - array associated with window
5955b0d146aSStefano Zampini .  sync - type of synchronization PetscSFWindowSyncType
59695fce210SBarry Smith .  epoch - close an epoch, must match argument to PetscSFGetWindow()
5975b0d146aSStefano Zampini .  update - if we have to update the local window array
59895fce210SBarry Smith -  win - window
59995fce210SBarry Smith 
60095fce210SBarry Smith    Level: developer
60195fce210SBarry Smith 
60295fce210SBarry Smith .seealso: PetscSFFindWindow()
6035b0d146aSStefano Zampini */
6045b0d146aSStefano Zampini static PetscErrorCode PetscSFRestoreWindow(PetscSF sf,MPI_Datatype unit,void *array,PetscSFWindowSyncType sync,PetscBool epoch,PetscMPIInt fenceassert,PetscBool update,MPI_Win *win)
60595fce210SBarry Smith {
60695fce210SBarry Smith   PetscSF_Window          *w = (PetscSF_Window*)sf->data;
60795fce210SBarry Smith   PetscErrorCode          ierr;
60895fce210SBarry Smith   PetscSFWinLink          *p,link;
6095b0d146aSStefano Zampini   PetscBool               reuse = PETSC_FALSE;
6105b0d146aSStefano Zampini   PetscSFWindowFlavorType flavor;
6115b0d146aSStefano Zampini   void*                   laddr;
6125b0d146aSStefano Zampini   size_t                  bytes;
61395fce210SBarry Smith 
61495fce210SBarry Smith   PetscFunctionBegin;
61595fce210SBarry Smith   for (p=&w->wins; *p; p=&(*p)->next) {
61695fce210SBarry Smith     link = *p;
61795fce210SBarry Smith     if (*win == link->win) {
6185b0d146aSStefano Zampini       if (array != link->paddr) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Matched window, but not array");
61995fce210SBarry Smith       if (epoch != link->epoch) {
62095fce210SBarry Smith         if (epoch) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"No epoch to end");
62195fce210SBarry Smith         else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Restoring window without ending epoch");
62295fce210SBarry Smith       }
6235b0d146aSStefano Zampini       laddr = link->addr;
6245b0d146aSStefano Zampini       flavor = link->flavor;
6255b0d146aSStefano Zampini       bytes = link->bytes;
6265b0d146aSStefano Zampini       if (flavor != PETSCSF_WINDOW_FLAVOR_CREATE) reuse = PETSC_TRUE;
6275b0d146aSStefano Zampini       else { *p = link->next; update = PETSC_FALSE; } /* remove from list */
62895fce210SBarry Smith       goto found;
62995fce210SBarry Smith     }
63095fce210SBarry Smith   }
63195fce210SBarry Smith   SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Requested window not in use");
63295fce210SBarry Smith 
63395fce210SBarry Smith found:
6345b0d146aSStefano Zampini   ierr = PetscInfo3(sf,"Window %d of flavor %d for comm %d\n",link->win,link->flavor,PetscObjectComm((PetscObject)sf));CHKERRQ(ierr);
63595fce210SBarry Smith   if (epoch) {
6365b0d146aSStefano Zampini     switch (sync) {
63795fce210SBarry Smith     case PETSCSF_WINDOW_SYNC_FENCE:
63895fce210SBarry Smith       ierr = MPI_Win_fence(fenceassert,*win);CHKERRQ(ierr);
63995fce210SBarry Smith       break;
6405b0d146aSStefano Zampini     case PETSCSF_WINDOW_SYNC_LOCK: /* Handled outside */
6415b0d146aSStefano Zampini       break;
64295fce210SBarry Smith     case PETSCSF_WINDOW_SYNC_ACTIVE: {
6435b0d146aSStefano Zampini       MPI_Group   ingroup,outgroup;
6445b0d146aSStefano Zampini       PetscMPIInt isize,osize;
6455b0d146aSStefano Zampini 
6465b0d146aSStefano Zampini       /* OpenMPI 4.0.2 with btl=wader does not like calling
6475b0d146aSStefano Zampini          - MPI_Win_complete when ogroup is empty
6485b0d146aSStefano Zampini          - MPI_Win_wait when igroup is empty
6495b0d146aSStefano Zampini          The MPI standard (Sec. 11.5.2 of MPI 3.1) only requires that
6505b0d146aSStefano Zampini          - each process who issues a call to MPI_Win_start issues a call to MPI_Win_Complete
6515b0d146aSStefano Zampini          - each process who issues a call to MPI_Win_post issues a call to MPI_Win_Wait
6525b0d146aSStefano Zampini       */
6535b0d146aSStefano Zampini       ierr = PetscSFGetGroups(sf,&ingroup,&outgroup);CHKERRQ(ierr);
6545b0d146aSStefano Zampini       ierr = MPI_Group_size(ingroup,&isize);CHKERRQ(ierr);
6555b0d146aSStefano Zampini       ierr = MPI_Group_size(outgroup,&osize);CHKERRQ(ierr);
6565b0d146aSStefano Zampini       if (osize) { ierr = MPI_Win_complete(*win);CHKERRQ(ierr); }
6575b0d146aSStefano Zampini       if (isize) { ierr = MPI_Win_wait(*win);CHKERRQ(ierr); }
65895fce210SBarry Smith     } break;
65995fce210SBarry Smith     default: SETERRQ(PetscObjectComm((PetscObject)sf),PETSC_ERR_PLIB,"Unknown synchronization type");
66095fce210SBarry Smith     }
66195fce210SBarry Smith   }
6625b0d146aSStefano Zampini   if (update) {
6635b0d146aSStefano Zampini     if (sync == PETSCSF_WINDOW_SYNC_LOCK) {
6645b0d146aSStefano Zampini       ierr = MPI_Win_fence(MPI_MODE_NOPUT|MPI_MODE_NOSUCCEED,*win);CHKERRQ(ierr);
6655b0d146aSStefano Zampini     }
6665b0d146aSStefano Zampini     ierr = PetscMemcpy(array,laddr,sf->nroots*bytes);CHKERRQ(ierr);
6675b0d146aSStefano Zampini   }
6685b0d146aSStefano Zampini   link->epoch = PETSC_FALSE;
6695b0d146aSStefano Zampini   link->inuse = PETSC_FALSE;
6705b0d146aSStefano Zampini   link->paddr = NULL;
6715b0d146aSStefano Zampini   if (!reuse) {
672684a874aSStefano Zampini     ierr = PetscFree(link->dyn_target_addr);CHKERRQ(ierr);
673684a874aSStefano Zampini     ierr = PetscFree(link->reqs);CHKERRQ(ierr);
67495fce210SBarry Smith     ierr = MPI_Win_free(&link->win);CHKERRQ(ierr);
67595fce210SBarry Smith     ierr = PetscFree(link);CHKERRQ(ierr);
67695fce210SBarry Smith     *win = MPI_WIN_NULL;
6775b0d146aSStefano Zampini   }
67895fce210SBarry Smith   PetscFunctionReturn(0);
67995fce210SBarry Smith }
68095fce210SBarry Smith 
68195fce210SBarry Smith static PetscErrorCode PetscSFSetUp_Window(PetscSF sf)
68295fce210SBarry Smith {
68395fce210SBarry Smith   PetscSF_Window *w = (PetscSF_Window*)sf->data;
68495fce210SBarry Smith   PetscErrorCode ierr;
68595fce210SBarry Smith   MPI_Group      ingroup,outgroup;
68695fce210SBarry Smith 
68795fce210SBarry Smith   PetscFunctionBegin;
688b5a8e515SJed Brown   ierr = PetscSFSetUpRanks(sf,MPI_GROUP_EMPTY);CHKERRQ(ierr);
6895b0d146aSStefano Zampini   if (!w->dynsf) {
6905b0d146aSStefano Zampini     PetscInt    i;
6915b0d146aSStefano Zampini     PetscSFNode *remotes;
6925b0d146aSStefano Zampini 
6935b0d146aSStefano Zampini     ierr = PetscMalloc1(sf->nranks,&remotes);CHKERRQ(ierr);
6945b0d146aSStefano Zampini     for (i=0;i<sf->nranks;i++) {
6955b0d146aSStefano Zampini       remotes[i].rank  = sf->ranks[i];
6965b0d146aSStefano Zampini       remotes[i].index = 0;
6975b0d146aSStefano Zampini     }
6985b0d146aSStefano Zampini     ierr = PetscSFDuplicate(sf,PETSCSF_DUPLICATE_RANKS,&w->dynsf);CHKERRQ(ierr);
6995b0d146aSStefano Zampini     ierr = PetscSFWindowSetFlavorType(w->dynsf,PETSCSF_WINDOW_FLAVOR_CREATE);CHKERRQ(ierr); /* break recursion */
7005b0d146aSStefano Zampini     ierr = PetscSFSetGraph(w->dynsf,1,sf->nranks,NULL,PETSC_OWN_POINTER,remotes,PETSC_OWN_POINTER);CHKERRQ(ierr);
7015b0d146aSStefano Zampini     ierr = PetscLogObjectParent((PetscObject)sf,(PetscObject)w->dynsf);CHKERRQ(ierr);
7025b0d146aSStefano Zampini   }
70395fce210SBarry Smith   switch (w->sync) {
70495fce210SBarry Smith   case PETSCSF_WINDOW_SYNC_ACTIVE:
70595fce210SBarry Smith     ierr = PetscSFGetGroups(sf,&ingroup,&outgroup);CHKERRQ(ierr);
70695fce210SBarry Smith   default:
70795fce210SBarry Smith     break;
70895fce210SBarry Smith   }
70995fce210SBarry Smith   PetscFunctionReturn(0);
71095fce210SBarry Smith }
71195fce210SBarry Smith 
7124416b707SBarry Smith static PetscErrorCode PetscSFSetFromOptions_Window(PetscOptionItems *PetscOptionsObject,PetscSF sf)
71395fce210SBarry Smith {
71495fce210SBarry Smith   PetscSF_Window          *w = (PetscSF_Window*)sf->data;
71595fce210SBarry Smith   PetscErrorCode          ierr;
7165b0d146aSStefano Zampini   PetscSFWindowFlavorType flavor = w->flavor;
71795fce210SBarry Smith 
71895fce210SBarry Smith   PetscFunctionBegin;
719e55864a3SBarry Smith   ierr = PetscOptionsHead(PetscOptionsObject,"PetscSF Window options");CHKERRQ(ierr);
72095fce210SBarry 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);
7215b0d146aSStefano Zampini   ierr = PetscOptionsEnum("-sf_window_flavor","flavor to use for PetscSF Window creation","PetscSFWindowSetFlavorType",PetscSFWindowFlavorTypes,(PetscEnum)flavor,(PetscEnum*)&flavor,NULL);CHKERRQ(ierr);
7225b0d146aSStefano Zampini   ierr = PetscSFWindowSetFlavorType(sf,flavor);CHKERRQ(ierr);
72395fce210SBarry Smith   ierr = PetscOptionsTail();CHKERRQ(ierr);
72495fce210SBarry Smith   PetscFunctionReturn(0);
72595fce210SBarry Smith }
72695fce210SBarry Smith 
72795fce210SBarry Smith static PetscErrorCode PetscSFReset_Window(PetscSF sf)
72895fce210SBarry Smith {
72995fce210SBarry Smith   PetscSF_Window  *w = (PetscSF_Window*)sf->data;
73095fce210SBarry Smith   PetscErrorCode  ierr;
73195fce210SBarry Smith   PetscSFDataLink link,next;
73295fce210SBarry Smith   PetscSFWinLink  wlink,wnext;
73395fce210SBarry Smith   PetscInt        i;
73495fce210SBarry Smith 
73595fce210SBarry Smith   PetscFunctionBegin;
73695fce210SBarry Smith   for (link=w->link; link; link=next) {
73795fce210SBarry Smith     next = link->next;
73895fce210SBarry Smith     ierr = MPI_Type_free(&link->unit);CHKERRQ(ierr);
73995fce210SBarry Smith     for (i=0; i<sf->nranks; i++) {
74095fce210SBarry Smith       ierr = MPI_Type_free(&link->mine[i]);CHKERRQ(ierr);
74195fce210SBarry Smith       ierr = MPI_Type_free(&link->remote[i]);CHKERRQ(ierr);
74295fce210SBarry Smith     }
74395fce210SBarry Smith     ierr = PetscFree2(link->mine,link->remote);CHKERRQ(ierr);
74495fce210SBarry Smith     ierr = PetscFree(link);CHKERRQ(ierr);
74595fce210SBarry Smith   }
74695fce210SBarry Smith   w->link = NULL;
74795fce210SBarry Smith   for (wlink=w->wins; wlink; wlink=wnext) {
74895fce210SBarry Smith     wnext = wlink->next;
74995fce210SBarry Smith     if (wlink->inuse) SETERRQ1(PetscObjectComm((PetscObject)sf),PETSC_ERR_ARG_WRONGSTATE,"Window still in use with address %p",(void*)wlink->addr);
7505b0d146aSStefano Zampini     ierr = PetscFree(wlink->dyn_target_addr);CHKERRQ(ierr);
751684a874aSStefano Zampini     ierr = PetscFree(wlink->reqs);CHKERRQ(ierr);
75295fce210SBarry Smith     ierr = MPI_Win_free(&wlink->win);CHKERRQ(ierr);
75395fce210SBarry Smith     ierr = PetscFree(wlink);CHKERRQ(ierr);
75495fce210SBarry Smith   }
75595fce210SBarry Smith   w->wins = NULL;
7565b0d146aSStefano Zampini   ierr = PetscSFDestroy(&w->dynsf);CHKERRQ(ierr);
7575b0d146aSStefano Zampini   if (w->info != MPI_INFO_NULL) {
7585b0d146aSStefano Zampini     ierr = MPI_Info_free(&w->info);CHKERRQ(ierr);
7595b0d146aSStefano Zampini   }
76095fce210SBarry Smith   PetscFunctionReturn(0);
76195fce210SBarry Smith }
76295fce210SBarry Smith 
76395fce210SBarry Smith static PetscErrorCode PetscSFDestroy_Window(PetscSF sf)
76495fce210SBarry Smith {
76595fce210SBarry Smith   PetscErrorCode ierr;
76695fce210SBarry Smith 
76795fce210SBarry Smith   PetscFunctionBegin;
76829046d53SLisandro Dalcin   ierr = PetscSFReset_Window(sf);CHKERRQ(ierr);
76995fce210SBarry Smith   ierr = PetscFree(sf->data);CHKERRQ(ierr);
770bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)sf,"PetscSFWindowSetSyncType_C",NULL);CHKERRQ(ierr);
771bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)sf,"PetscSFWindowGetSyncType_C",NULL);CHKERRQ(ierr);
7725b0d146aSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)sf,"PetscSFWindowSetFlavorType_C",NULL);CHKERRQ(ierr);
7735b0d146aSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)sf,"PetscSFWindowGetFlavorType_C",NULL);CHKERRQ(ierr);
7745b0d146aSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)sf,"PetscSFWindowSetInfo_C",NULL);CHKERRQ(ierr);
7755b0d146aSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)sf,"PetscSFWindowGetInfo_C",NULL);CHKERRQ(ierr);
77695fce210SBarry Smith   PetscFunctionReturn(0);
77795fce210SBarry Smith }
77895fce210SBarry Smith 
77995fce210SBarry Smith static PetscErrorCode PetscSFView_Window(PetscSF sf,PetscViewer viewer)
78095fce210SBarry Smith {
78195fce210SBarry Smith   PetscSF_Window    *w = (PetscSF_Window*)sf->data;
78295fce210SBarry Smith   PetscErrorCode    ierr;
78395fce210SBarry Smith   PetscBool         iascii;
7845b0d146aSStefano Zampini   PetscViewerFormat format;
78595fce210SBarry Smith 
78695fce210SBarry Smith   PetscFunctionBegin;
7875b0d146aSStefano Zampini   ierr = PetscViewerGetFormat(viewer,&format);CHKERRQ(ierr);
78895fce210SBarry Smith   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr);
78995fce210SBarry Smith   if (iascii) {
7905b0d146aSStefano 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);
7915b0d146aSStefano Zampini     if (format == PETSC_VIEWER_ASCII_INFO_DETAIL) {
7925b0d146aSStefano Zampini       if (w->info != MPI_INFO_NULL) {
7935b0d146aSStefano Zampini         PetscMPIInt k,nkeys;
7945b0d146aSStefano Zampini         char        key[MPI_MAX_INFO_KEY], value[MPI_MAX_INFO_VAL];
7955b0d146aSStefano Zampini 
7965b0d146aSStefano Zampini         ierr = MPI_Info_get_nkeys(w->info,&nkeys);CHKERRQ(ierr);
7975b0d146aSStefano Zampini         ierr = PetscViewerASCIIPrintf(viewer,"    current info with %d keys. Ordered key-value pairs follow:\n",nkeys);CHKERRQ(ierr);
7985b0d146aSStefano Zampini         for (k = 0; k < nkeys; k++) {
7995b0d146aSStefano Zampini           PetscMPIInt flag;
8005b0d146aSStefano Zampini 
8015b0d146aSStefano Zampini           ierr = MPI_Info_get_nthkey(w->info,k,key);CHKERRQ(ierr);
8025b0d146aSStefano Zampini           ierr = MPI_Info_get(w->info,key,MPI_MAX_INFO_VAL,value,&flag);CHKERRQ(ierr);
8035b0d146aSStefano Zampini           if (!flag) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Missing key %s",key);
8045b0d146aSStefano Zampini           ierr = PetscViewerASCIIPrintf(viewer,"      %s = %s\n",key,value);CHKERRQ(ierr);
8055b0d146aSStefano Zampini         }
8065b0d146aSStefano Zampini       } else {
8075b0d146aSStefano Zampini         ierr = PetscViewerASCIIPrintf(viewer,"    current info=MPI_INFO_NULL\n");CHKERRQ(ierr);
8085b0d146aSStefano Zampini       }
8095b0d146aSStefano Zampini     }
81095fce210SBarry Smith   }
81195fce210SBarry Smith   PetscFunctionReturn(0);
81295fce210SBarry Smith }
81395fce210SBarry Smith 
81495fce210SBarry Smith static PetscErrorCode PetscSFDuplicate_Window(PetscSF sf,PetscSFDuplicateOption opt,PetscSF newsf)
81595fce210SBarry Smith {
81695fce210SBarry Smith   PetscSF_Window        *w = (PetscSF_Window*)sf->data;
81795fce210SBarry Smith   PetscErrorCode        ierr;
81895fce210SBarry Smith   PetscSFWindowSyncType synctype;
81995fce210SBarry Smith 
82095fce210SBarry Smith   PetscFunctionBegin;
82195fce210SBarry Smith   synctype = w->sync;
82295fce210SBarry Smith   /* HACK: Must use FENCE or LOCK when called from PetscSFGetGroups() because ACTIVE here would cause recursion. */
8235b0d146aSStefano Zampini   if (!sf->setupcalled) synctype = PETSCSF_WINDOW_SYNC_LOCK;
82495fce210SBarry Smith   ierr = PetscSFWindowSetSyncType(newsf,synctype);CHKERRQ(ierr);
8255b0d146aSStefano Zampini   ierr = PetscSFWindowSetFlavorType(newsf,w->flavor);CHKERRQ(ierr);
8265b0d146aSStefano Zampini   ierr = PetscSFWindowSetInfo(newsf,w->info);CHKERRQ(ierr);
82795fce210SBarry Smith   PetscFunctionReturn(0);
82895fce210SBarry Smith }
82995fce210SBarry Smith 
830eb02082bSJunchao Zhang static PetscErrorCode PetscSFBcastAndOpBegin_Window(PetscSF sf,MPI_Datatype unit,PetscMemType rootmtype,const void *rootdata,PetscMemType leafmtype,void *leafdata,MPI_Op op)
83195fce210SBarry Smith {
83295fce210SBarry Smith   PetscSF_Window     *w = (PetscSF_Window*)sf->data;
83395fce210SBarry Smith   PetscErrorCode     ierr;
83495fce210SBarry Smith   PetscInt           i,nranks;
83595fce210SBarry Smith   const PetscMPIInt  *ranks;
8365b0d146aSStefano Zampini   const MPI_Aint     *target_disp;
83795fce210SBarry Smith   const MPI_Datatype *mine,*remote;
838684a874aSStefano Zampini   MPI_Request        *reqs;
83995fce210SBarry Smith   MPI_Win            win;
84095fce210SBarry Smith 
84195fce210SBarry Smith   PetscFunctionBegin;
8425b0d146aSStefano 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");
843dec1416fSJunchao Zhang   ierr = PetscSFGetRootRanks(sf,&nranks,&ranks,NULL,NULL,NULL);CHKERRQ(ierr);
84495fce210SBarry Smith   ierr = PetscSFWindowGetDataTypes(sf,unit,&mine,&remote);CHKERRQ(ierr);
845684a874aSStefano Zampini   ierr = PetscSFGetWindow(sf,unit,(void*)rootdata,w->sync,PETSC_TRUE,MPI_MODE_NOPUT|MPI_MODE_NOPRECEDE,MPI_MODE_NOPUT,0,&target_disp,&reqs,&win);CHKERRQ(ierr);
84695fce210SBarry Smith   for (i=0; i<nranks; i++) {
8475b0d146aSStefano Zampini     MPI_Aint tdp = target_disp ? target_disp[i] : 0;
8485b0d146aSStefano Zampini 
849684a874aSStefano Zampini     if (w->sync == PETSCSF_WINDOW_SYNC_LOCK) {
850684a874aSStefano Zampini       ierr = MPI_Win_lock(MPI_LOCK_SHARED,ranks[i],MPI_MODE_NOCHECK,win);CHKERRQ(ierr);
851684a874aSStefano Zampini #if defined(PETSC_HAVE_MPI_RGET)
852684a874aSStefano Zampini       ierr = MPI_Rget(leafdata,1,mine[i],ranks[i],tdp,1,remote[i],win,&reqs[i]);CHKERRQ(ierr);
853684a874aSStefano Zampini #else
8545b0d146aSStefano Zampini       ierr = MPI_Get(leafdata,1,mine[i],ranks[i],tdp,1,remote[i],win);CHKERRQ(ierr);
855684a874aSStefano Zampini #endif
856684a874aSStefano Zampini     } else {
857684a874aSStefano Zampini       ierr = MPI_Get(leafdata,1,mine[i],ranks[i],tdp,1,remote[i],win);CHKERRQ(ierr);
858684a874aSStefano Zampini     }
85995fce210SBarry Smith   }
86095fce210SBarry Smith   PetscFunctionReturn(0);
86195fce210SBarry Smith }
86295fce210SBarry Smith 
86300816365SJunchao Zhang PetscErrorCode PetscSFBcastAndOpEnd_Window(PetscSF sf,MPI_Datatype unit,const void *rootdata,void *leafdata,MPI_Op op)
86495fce210SBarry Smith {
8655b0d146aSStefano Zampini   PetscSF_Window *w = (PetscSF_Window*)sf->data;
86695fce210SBarry Smith   PetscErrorCode ierr;
86795fce210SBarry Smith   MPI_Win        win;
8684b9acda6SJunchao Zhang   MPI_Request    *reqs = NULL;
86995fce210SBarry Smith 
87095fce210SBarry Smith   PetscFunctionBegin;
871684a874aSStefano Zampini   ierr = PetscSFFindWindow(sf,unit,rootdata,&win,&reqs);CHKERRQ(ierr);
872684a874aSStefano Zampini   if (reqs) { ierr = MPI_Waitall(sf->nranks,reqs,MPI_STATUSES_IGNORE);CHKERRQ(ierr); }
873684a874aSStefano Zampini   if (w->sync == PETSCSF_WINDOW_SYNC_LOCK) {
874684a874aSStefano Zampini     PetscInt           i,nranks;
875684a874aSStefano Zampini     const PetscMPIInt  *ranks;
876684a874aSStefano Zampini 
877684a874aSStefano Zampini     ierr = PetscSFGetRootRanks(sf,&nranks,&ranks,NULL,NULL,NULL);CHKERRQ(ierr);
878684a874aSStefano Zampini     for (i=0; i<nranks; i++) {
879684a874aSStefano Zampini       ierr = MPI_Win_unlock(ranks[i],win);CHKERRQ(ierr);
880684a874aSStefano Zampini     }
881684a874aSStefano Zampini   }
8825b0d146aSStefano Zampini   ierr = PetscSFRestoreWindow(sf,unit,(void*)rootdata,w->sync,PETSC_TRUE,MPI_MODE_NOSTORE|MPI_MODE_NOSUCCEED,PETSC_FALSE,&win);CHKERRQ(ierr);
88395fce210SBarry Smith   PetscFunctionReturn(0);
88495fce210SBarry Smith }
88595fce210SBarry Smith 
886eb02082bSJunchao Zhang PetscErrorCode PetscSFReduceBegin_Window(PetscSF sf,MPI_Datatype unit,PetscMemType leafmtype,const void *leafdata,PetscMemType rootmtype,void *rootdata,MPI_Op op)
88795fce210SBarry Smith {
88895fce210SBarry Smith   PetscSF_Window     *w = (PetscSF_Window*)sf->data;
88995fce210SBarry Smith   PetscErrorCode     ierr;
89095fce210SBarry Smith   PetscInt           i,nranks;
89195fce210SBarry Smith   const PetscMPIInt  *ranks;
8925b0d146aSStefano Zampini   const MPI_Aint     *target_disp;
89395fce210SBarry Smith   const MPI_Datatype *mine,*remote;
89495fce210SBarry Smith   MPI_Win            win;
89595fce210SBarry Smith 
89695fce210SBarry Smith   PetscFunctionBegin;
897dec1416fSJunchao Zhang   ierr = PetscSFGetRootRanks(sf,&nranks,&ranks,NULL,NULL,NULL);CHKERRQ(ierr);
89895fce210SBarry Smith   ierr = PetscSFWindowGetDataTypes(sf,unit,&mine,&remote);CHKERRQ(ierr);
89995fce210SBarry Smith   ierr = PetscSFWindowOpTranslate(&op);CHKERRQ(ierr);
900684a874aSStefano Zampini   ierr = PetscSFGetWindow(sf,unit,rootdata,w->sync,PETSC_TRUE,MPI_MODE_NOPRECEDE,0,0,&target_disp,NULL,&win);CHKERRQ(ierr);
90195fce210SBarry Smith   for (i=0; i<nranks; i++) {
9025b0d146aSStefano Zampini     MPI_Aint tdp = target_disp ? target_disp[i] : 0;
9035b0d146aSStefano Zampini 
90495fce210SBarry Smith     if (w->sync == PETSCSF_WINDOW_SYNC_LOCK) {ierr = MPI_Win_lock(MPI_LOCK_SHARED,ranks[i],MPI_MODE_NOCHECK,win);CHKERRQ(ierr);}
9055b0d146aSStefano Zampini     ierr = MPI_Accumulate((void*)leafdata,1,mine[i],ranks[i],tdp,1,remote[i],op,win);
9065b0d146aSStefano Zampini     if (ierr) { /* intercept the MPI error since the combination of unit and op is not supported */
9075b0d146aSStefano Zampini       PetscMPIInt len;
9085b0d146aSStefano Zampini       char        errstring[MPI_MAX_ERROR_STRING];
9095b0d146aSStefano Zampini 
9105b0d146aSStefano Zampini       MPI_Error_string(ierr,errstring,&len);
9115b0d146aSStefano Zampini       SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_SUP,"Internal error in MPI: %s",errstring);
9125b0d146aSStefano Zampini     }
91395fce210SBarry Smith     if (w->sync == PETSCSF_WINDOW_SYNC_LOCK) {ierr = MPI_Win_unlock(ranks[i],win);CHKERRQ(ierr);}
91495fce210SBarry Smith   }
91595fce210SBarry Smith   PetscFunctionReturn(0);
91695fce210SBarry Smith }
91795fce210SBarry Smith 
91800816365SJunchao Zhang static PetscErrorCode PetscSFReduceEnd_Window(PetscSF sf,MPI_Datatype unit,const void *leafdata,void *rootdata,MPI_Op op)
91995fce210SBarry Smith {
92095fce210SBarry Smith   PetscSF_Window *w = (PetscSF_Window*)sf->data;
92195fce210SBarry Smith   PetscErrorCode ierr;
92295fce210SBarry Smith   MPI_Win        win;
9234b9acda6SJunchao Zhang   MPI_Request    *reqs = NULL;
92495fce210SBarry Smith 
92595fce210SBarry Smith   PetscFunctionBegin;
926684a874aSStefano Zampini   ierr = PetscSFFindWindow(sf,unit,rootdata,&win,&reqs);CHKERRQ(ierr);
927684a874aSStefano Zampini   if (reqs) { ierr = MPI_Waitall(sf->nranks,reqs,MPI_STATUSES_IGNORE);CHKERRQ(ierr); }
9285b0d146aSStefano Zampini   ierr = PetscSFRestoreWindow(sf,unit,rootdata,w->sync,PETSC_TRUE,MPI_MODE_NOSUCCEED,PETSC_TRUE,&win);CHKERRQ(ierr);
92995fce210SBarry Smith   PetscFunctionReturn(0);
93095fce210SBarry Smith }
9315b0d146aSStefano Zampini 
932eb02082bSJunchao Zhang static PetscErrorCode PetscSFFetchAndOpBegin_Window(PetscSF sf,MPI_Datatype unit,PetscMemType rootmtype,void *rootdata,PetscMemType leafmtype,const void *leafdata,void *leafupdate,MPI_Op op)
93395fce210SBarry Smith {
93495fce210SBarry Smith   PetscErrorCode     ierr;
93595fce210SBarry Smith   PetscInt           i,nranks;
93695fce210SBarry Smith   const PetscMPIInt  *ranks;
93795fce210SBarry Smith   const MPI_Datatype *mine,*remote;
9385b0d146aSStefano Zampini   const MPI_Aint     *target_disp;
93995fce210SBarry Smith   MPI_Win            win;
9405b0d146aSStefano Zampini   PetscSF_Window     *w = (PetscSF_Window*)sf->data;
9415b0d146aSStefano Zampini #if !defined(PETSC_HAVE_MPI_GET_ACCUMULATE)
9425b0d146aSStefano Zampini   PetscSFWindowFlavorType oldf;
9435b0d146aSStefano Zampini #endif
94495fce210SBarry Smith 
94595fce210SBarry Smith   PetscFunctionBegin;
946dec1416fSJunchao Zhang   ierr = PetscSFGetRootRanks(sf,&nranks,&ranks,NULL,NULL,NULL);CHKERRQ(ierr);
94795fce210SBarry Smith   ierr = PetscSFWindowGetDataTypes(sf,unit,&mine,&remote);CHKERRQ(ierr);
94895fce210SBarry Smith   ierr = PetscSFWindowOpTranslate(&op);CHKERRQ(ierr);
9495b0d146aSStefano Zampini #if !defined(PETSC_HAVE_MPI_GET_ACCUMULATE)
9505b0d146aSStefano Zampini   /* FetchAndOp without MPI_Get_Accumulate requires locking.
9515b0d146aSStefano Zampini      we create a new window every time to not interfere with user-defined MPI_Info which may have used "no_locks"="true" */
9525b0d146aSStefano Zampini   oldf = w->flavor;
9535b0d146aSStefano Zampini   w->flavor = PETSCSF_WINDOW_FLAVOR_CREATE;
954684a874aSStefano Zampini   ierr = PetscSFGetWindow(sf,unit,rootdata,PETSCSF_WINDOW_SYNC_LOCK,PETSC_FALSE,0,0,0,&target_disp,NULL,&win);CHKERRQ(ierr);
9555b0d146aSStefano Zampini #else
956684a874aSStefano Zampini   ierr = PetscSFGetWindow(sf,unit,rootdata,w->sync,PETSC_TRUE,MPI_MODE_NOPRECEDE,0,0,&target_disp,NULL,&win);CHKERRQ(ierr);
9575b0d146aSStefano Zampini #endif
9585b0d146aSStefano Zampini   for (i=0; i<nranks; i++) {
9595b0d146aSStefano Zampini     MPI_Aint tdp = target_disp ? target_disp[i] : 0;
9605b0d146aSStefano Zampini 
9615b0d146aSStefano Zampini #if !defined(PETSC_HAVE_MPI_GET_ACCUMULATE)
9625b0d146aSStefano Zampini     ierr = MPI_Win_lock(MPI_LOCK_EXCLUSIVE,ranks[i],0,win);CHKERRQ(ierr);
9635b0d146aSStefano Zampini     ierr = MPI_Get(leafupdate,1,mine[i],ranks[i],tdp,1,remote[i],win);CHKERRQ(ierr);
9645b0d146aSStefano Zampini     ierr = MPI_Accumulate((void*)leafdata,1,mine[i],ranks[i],tdp,1,remote[i],op,win);
9655b0d146aSStefano Zampini     if (ierr) { /* intercept the MPI error since the combination of unit and op is not supported */
9665b0d146aSStefano Zampini       PetscMPIInt len;
9675b0d146aSStefano Zampini       char        errstring[MPI_MAX_ERROR_STRING];
9685b0d146aSStefano Zampini 
9695b0d146aSStefano Zampini       MPI_Error_string(ierr,errstring,&len);
9705b0d146aSStefano Zampini       SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_SUP,"Internal error in MPI: %s",errstring);
97195fce210SBarry Smith     }
9725b0d146aSStefano Zampini     ierr = MPI_Win_unlock(ranks[i],win);CHKERRQ(ierr);
9735b0d146aSStefano Zampini #else
9745b0d146aSStefano Zampini     if (w->sync == PETSCSF_WINDOW_SYNC_LOCK) { ierr = MPI_Win_lock(MPI_LOCK_SHARED,ranks[i],0,win);CHKERRQ(ierr); }
9755b0d146aSStefano Zampini     ierr = MPI_Get_accumulate((void*)leafdata,1,mine[i],leafupdate,1,mine[i],ranks[i],tdp,1,remote[i],op,win);
9765b0d146aSStefano Zampini     if (ierr) { /* intercept the MPI error since the combination of unit and op is not supported */
9775b0d146aSStefano Zampini       PetscMPIInt len;
9785b0d146aSStefano Zampini       char        errstring[MPI_MAX_ERROR_STRING];
9795b0d146aSStefano Zampini 
9805b0d146aSStefano Zampini       MPI_Error_string(ierr,errstring,&len);
9815b0d146aSStefano Zampini       SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_SUP,"Internal error in MPI: %s",errstring);
9825b0d146aSStefano Zampini     }
9835b0d146aSStefano Zampini     if (w->sync == PETSCSF_WINDOW_SYNC_LOCK) { ierr = MPI_Win_unlock(ranks[i],win);CHKERRQ(ierr); }
9845b0d146aSStefano Zampini #endif
9855b0d146aSStefano Zampini   }
9865b0d146aSStefano Zampini #if !defined(PETSC_HAVE_MPI_GET_ACCUMULATE)
9875b0d146aSStefano Zampini   w->flavor = oldf;
9885b0d146aSStefano Zampini #endif
98995fce210SBarry Smith   PetscFunctionReturn(0);
99095fce210SBarry Smith }
99195fce210SBarry Smith 
99200816365SJunchao Zhang static PetscErrorCode PetscSFFetchAndOpEnd_Window(PetscSF sf,MPI_Datatype unit,void *rootdata,const void *leafdata,void *leafupdate,MPI_Op op)
99395fce210SBarry Smith {
99495fce210SBarry Smith   PetscErrorCode ierr;
99595fce210SBarry Smith   MPI_Win        win;
9965b0d146aSStefano Zampini #if defined(PETSC_HAVE_MPI_GET_ACCUMULATE)
9975b0d146aSStefano Zampini   PetscSF_Window *w = (PetscSF_Window*)sf->data;
9985b0d146aSStefano Zampini #endif
9994b9acda6SJunchao Zhang   MPI_Request    *reqs = NULL;
100095fce210SBarry Smith 
100195fce210SBarry Smith   PetscFunctionBegin;
1002684a874aSStefano Zampini   ierr = PetscSFFindWindow(sf,unit,rootdata,&win,&reqs);CHKERRQ(ierr);
1003684a874aSStefano Zampini   if (reqs) { ierr = MPI_Waitall(sf->nranks,reqs,MPI_STATUSES_IGNORE);CHKERRQ(ierr); }
10045b0d146aSStefano Zampini #if defined(PETSC_HAVE_MPI_GET_ACCUMULATE)
10055b0d146aSStefano Zampini   ierr = PetscSFRestoreWindow(sf,unit,rootdata,w->sync,PETSC_TRUE,MPI_MODE_NOSUCCEED,PETSC_TRUE,&win);CHKERRQ(ierr);
10065b0d146aSStefano Zampini #else
10075b0d146aSStefano Zampini   ierr = PetscSFRestoreWindow(sf,unit,rootdata,PETSCSF_WINDOW_SYNC_LOCK,PETSC_FALSE,0,PETSC_TRUE,&win);CHKERRQ(ierr);
10085b0d146aSStefano Zampini #endif
100995fce210SBarry Smith   PetscFunctionReturn(0);
101095fce210SBarry Smith }
101195fce210SBarry Smith 
1012dec1416fSJunchao Zhang PETSC_INTERN PetscErrorCode PetscSFCreate_Window(PetscSF sf)
101395fce210SBarry Smith {
101495fce210SBarry Smith   PetscSF_Window *w = (PetscSF_Window*)sf->data;
101595fce210SBarry Smith   PetscErrorCode ierr;
101695fce210SBarry Smith 
101795fce210SBarry Smith   PetscFunctionBegin;
101895fce210SBarry Smith   sf->ops->SetUp           = PetscSFSetUp_Window;
101995fce210SBarry Smith   sf->ops->SetFromOptions  = PetscSFSetFromOptions_Window;
102095fce210SBarry Smith   sf->ops->Reset           = PetscSFReset_Window;
102195fce210SBarry Smith   sf->ops->Destroy         = PetscSFDestroy_Window;
102295fce210SBarry Smith   sf->ops->View            = PetscSFView_Window;
102395fce210SBarry Smith   sf->ops->Duplicate       = PetscSFDuplicate_Window;
1024de49d1a2SJunchao Zhang   sf->ops->BcastAndOpBegin = PetscSFBcastAndOpBegin_Window;
1025de49d1a2SJunchao Zhang   sf->ops->BcastAndOpEnd   = PetscSFBcastAndOpEnd_Window;
102695fce210SBarry Smith   sf->ops->ReduceBegin     = PetscSFReduceBegin_Window;
102795fce210SBarry Smith   sf->ops->ReduceEnd       = PetscSFReduceEnd_Window;
102895fce210SBarry Smith   sf->ops->FetchAndOpBegin = PetscSFFetchAndOpBegin_Window;
102995fce210SBarry Smith   sf->ops->FetchAndOpEnd   = PetscSFFetchAndOpEnd_Window;
103095fce210SBarry Smith 
1031b00a9115SJed Brown   ierr = PetscNewLog(sf,&w);CHKERRQ(ierr);
103295fce210SBarry Smith   sf->data  = (void*)w;
103395fce210SBarry Smith   w->sync   = PETSCSF_WINDOW_SYNC_FENCE;
10345b0d146aSStefano Zampini   w->flavor = PETSCSF_WINDOW_FLAVOR_CREATE;
10355b0d146aSStefano Zampini   w->info   = MPI_INFO_NULL;
103695fce210SBarry Smith 
1037bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)sf,"PetscSFWindowSetSyncType_C",PetscSFWindowSetSyncType_Window);CHKERRQ(ierr);
1038bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)sf,"PetscSFWindowGetSyncType_C",PetscSFWindowGetSyncType_Window);CHKERRQ(ierr);
10395b0d146aSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)sf,"PetscSFWindowSetFlavorType_C",PetscSFWindowSetFlavorType_Window);CHKERRQ(ierr);
10405b0d146aSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)sf,"PetscSFWindowGetFlavorType_C",PetscSFWindowGetFlavorType_Window);CHKERRQ(ierr);
10415b0d146aSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)sf,"PetscSFWindowSetInfo_C",PetscSFWindowSetInfo_Window);CHKERRQ(ierr);
10425b0d146aSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)sf,"PetscSFWindowGetInfo_C",PetscSFWindowGetInfo_Window);CHKERRQ(ierr);
104395fce210SBarry Smith 
104495fce210SBarry Smith #if defined(OMPI_MAJOR_VERSION) && (OMPI_MAJOR_VERSION < 1 || (OMPI_MAJOR_VERSION == 1 && OMPI_MINOR_VERSION <= 6))
104595fce210SBarry Smith   {
104695fce210SBarry Smith     PetscBool ackbug = PETSC_FALSE;
1047c5929fdfSBarry Smith     ierr = PetscOptionsGetBool(NULL,NULL,"-acknowledge_ompi_onesided_bug",&ackbug,NULL);CHKERRQ(ierr);
104895fce210SBarry Smith     if (ackbug) {
1049955c1f14SBarry Smith       ierr = PetscInfo(sf,"Acknowledged Open MPI bug, proceeding anyway. Expect memory corruption.\n");CHKERRQ(ierr);
105095fce210SBarry 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");
105195fce210SBarry Smith   }
105295fce210SBarry Smith #endif
105395fce210SBarry Smith   PetscFunctionReturn(0);
105495fce210SBarry Smith }
1055