xref: /petsc/src/vec/is/sf/impls/window/sfwindow.c (revision 4dfa11a44d5adf2389f1d3acbc8f3c1116dc6c3a)
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 
354c8fdceaSLisandro Dalcin const char *const PetscSFWindowSyncTypes[]   = {"FENCE", "LOCK", "ACTIVE", "PetscSFWindowSyncType", "PETSCSF_WINDOW_SYNC_", NULL};
364c8fdceaSLisandro Dalcin const char *const PetscSFWindowFlavorTypes[] = {"CREATE", "DYNAMIC", "ALLOCATE", "SHARED", "PetscSFWindowFlavorType", "PETSCSF_WINDOW_FLAVOR_", NULL};
3795fce210SBarry Smith 
38820f2d46SBarry Smith /* Built-in MPI_Ops act elementwise inside MPI_Accumulate, but cannot be used with composite types inside collectives (MPI_Allreduce) */
399371c9d4SSatish Balay static PetscErrorCode PetscSFWindowOpTranslate(MPI_Op *op) {
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 
524165533cSJose E. Roman    Input Parameters:
5395fce210SBarry Smith +  sf - star forest
5495fce210SBarry Smith -  unit - data type for each node
5595fce210SBarry Smith 
564165533cSJose E. Roman    Output Parameters:
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 
62db781477SPatrick Sanan .seealso: `PetscSFSetGraph()`, `PetscSFView()`
6395fce210SBarry Smith @*/
649371c9d4SSatish Balay static PetscErrorCode PetscSFWindowGetDataTypes(PetscSF sf, MPI_Datatype unit, const MPI_Datatype **localtypes, const MPI_Datatype **remotetypes) {
6595fce210SBarry Smith   PetscSF_Window    *w = (PetscSF_Window *)sf->data;
6695fce210SBarry Smith   PetscSFDataLink    link;
6795fce210SBarry Smith   PetscInt           i, nranks;
6895fce210SBarry Smith   const PetscInt    *roffset, *rmine, *rremote;
6995fce210SBarry Smith   const PetscMPIInt *ranks;
7095fce210SBarry Smith 
7195fce210SBarry Smith   PetscFunctionBegin;
7295fce210SBarry Smith   /* Look for types in cache */
7395fce210SBarry Smith   for (link = w->link; link; link = link->next) {
7495fce210SBarry Smith     PetscBool match;
759566063dSJacob Faibussowitsch     PetscCall(MPIPetsc_Type_compare(unit, link->unit, &match));
7695fce210SBarry Smith     if (match) {
7795fce210SBarry Smith       *localtypes  = link->mine;
7895fce210SBarry Smith       *remotetypes = link->remote;
7995fce210SBarry Smith       PetscFunctionReturn(0);
8095fce210SBarry Smith     }
8195fce210SBarry Smith   }
8295fce210SBarry Smith 
8395fce210SBarry Smith   /* Create new composite types for each send rank */
849566063dSJacob Faibussowitsch   PetscCall(PetscSFGetRootRanks(sf, &nranks, &ranks, &roffset, &rmine, &rremote));
859566063dSJacob Faibussowitsch   PetscCall(PetscNew(&link));
869566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Type_dup(unit, &link->unit));
879566063dSJacob Faibussowitsch   PetscCall(PetscMalloc2(nranks, &link->mine, nranks, &link->remote));
8895fce210SBarry Smith   for (i = 0; i < nranks; i++) {
895b0d146aSStefano Zampini     PetscInt     rcount = roffset[i + 1] - roffset[i];
9095fce210SBarry Smith     PetscMPIInt *rmine, *rremote;
9195fce210SBarry Smith #if !defined(PETSC_USE_64BIT_INDICES)
9295fce210SBarry Smith     rmine   = sf->rmine + sf->roffset[i];
9395fce210SBarry Smith     rremote = sf->rremote + sf->roffset[i];
9495fce210SBarry Smith #else
9595fce210SBarry Smith     PetscInt j;
969566063dSJacob Faibussowitsch     PetscCall(PetscMalloc2(rcount, &rmine, rcount, &rremote));
9795fce210SBarry Smith     for (j = 0; j < rcount; j++) {
989566063dSJacob Faibussowitsch       PetscCall(PetscMPIIntCast(sf->rmine[sf->roffset[i] + j], rmine + j));
999566063dSJacob Faibussowitsch       PetscCall(PetscMPIIntCast(sf->rremote[sf->roffset[i] + j], rremote + j));
10095fce210SBarry Smith     }
10195fce210SBarry Smith #endif
1025b0d146aSStefano Zampini 
1039566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Type_create_indexed_block(rcount, 1, rmine, link->unit, &link->mine[i]));
1049566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Type_create_indexed_block(rcount, 1, rremote, link->unit, &link->remote[i]));
10595fce210SBarry Smith #if defined(PETSC_USE_64BIT_INDICES)
1069566063dSJacob Faibussowitsch     PetscCall(PetscFree2(rmine, rremote));
10795fce210SBarry Smith #endif
1089566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Type_commit(&link->mine[i]));
1099566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Type_commit(&link->remote[i]));
11095fce210SBarry Smith   }
11195fce210SBarry Smith   link->next = w->link;
11295fce210SBarry Smith   w->link    = link;
11395fce210SBarry Smith 
11495fce210SBarry Smith   *localtypes  = link->mine;
11595fce210SBarry Smith   *remotetypes = link->remote;
11695fce210SBarry Smith   PetscFunctionReturn(0);
11795fce210SBarry Smith }
11895fce210SBarry Smith 
11995fce210SBarry Smith /*@C
1205b0d146aSStefano Zampini    PetscSFWindowSetFlavorType - Set flavor type for MPI_Win creation
1215b0d146aSStefano Zampini 
1225b0d146aSStefano Zampini    Logically Collective
1235b0d146aSStefano Zampini 
1244165533cSJose E. Roman    Input Parameters:
1255b0d146aSStefano Zampini +  sf - star forest for communication
1265b0d146aSStefano Zampini -  flavor - flavor type
1275b0d146aSStefano Zampini 
1285b0d146aSStefano Zampini    Options Database Key:
1295b0d146aSStefano Zampini .  -sf_window_flavor <flavor> - sets the flavor type CREATE, DYNAMIC, ALLOCATE or SHARED (see PetscSFWindowFlavorType)
1305b0d146aSStefano Zampini 
1315b0d146aSStefano Zampini    Level: advanced
1325b0d146aSStefano Zampini 
1335b0d146aSStefano Zampini    Notes: Windows reusage follow this rules:
1345b0d146aSStefano Zampini 
1355b0d146aSStefano Zampini      PETSCSF_WINDOW_FLAVOR_CREATE: creates a new window every time, uses MPI_Win_create
1365b0d146aSStefano Zampini 
1375b0d146aSStefano 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.
1385b0d146aSStefano Zampini        for i=1 to K
1395b0d146aSStefano Zampini          PetscSFOperationBegin(rootdata1,leafdata_whatever);
1405b0d146aSStefano Zampini          PetscSFOperationEnd(rootdata1,leafdata_whatever);
1415b0d146aSStefano Zampini          ...
1425b0d146aSStefano Zampini          PetscSFOperationBegin(rootdataN,leafdata_whatever);
1435b0d146aSStefano Zampini          PetscSFOperationEnd(rootdataN,leafdata_whatever);
1445b0d146aSStefano Zampini        endfor
1455b0d146aSStefano Zampini        The following pattern will instead raise an error
1465b0d146aSStefano Zampini          PetscSFOperationBegin(rootdata1,leafdata_whatever);
1475b0d146aSStefano Zampini          PetscSFOperationEnd(rootdata1,leafdata_whatever);
1485b0d146aSStefano Zampini          PetscSFOperationBegin(rank ? rootdata1 : rootdata2,leafdata_whatever);
1495b0d146aSStefano Zampini          PetscSFOperationEnd(rank ? rootdata1 : rootdata2,leafdata_whatever);
1505b0d146aSStefano Zampini 
1515b0d146aSStefano Zampini      PETSCSF_WINDOW_FLAVOR_ALLOCATE: uses MPI_Win_allocate, reuses any pre-existing window which fits the data and it is not in use
1525b0d146aSStefano Zampini 
1535b0d146aSStefano Zampini      PETSCSF_WINDOW_FLAVOR_SHARED: uses MPI_Win_allocate_shared, reusage policy as for PETSCSF_WINDOW_FLAVOR_ALLOCATE
1545b0d146aSStefano Zampini 
155db781477SPatrick Sanan .seealso: `PetscSFSetFromOptions()`, `PetscSFWindowGetFlavorType()`
1565b0d146aSStefano Zampini @*/
1579371c9d4SSatish Balay PetscErrorCode PetscSFWindowSetFlavorType(PetscSF sf, PetscSFWindowFlavorType flavor) {
1585b0d146aSStefano Zampini   PetscFunctionBegin;
1595b0d146aSStefano Zampini   PetscValidHeaderSpecific(sf, PETSCSF_CLASSID, 1);
1605b0d146aSStefano Zampini   PetscValidLogicalCollectiveEnum(sf, flavor, 2);
161cac4c232SBarry Smith   PetscTryMethod(sf, "PetscSFWindowSetFlavorType_C", (PetscSF, PetscSFWindowFlavorType), (sf, flavor));
1625b0d146aSStefano Zampini   PetscFunctionReturn(0);
1635b0d146aSStefano Zampini }
1645b0d146aSStefano Zampini 
1659371c9d4SSatish Balay static PetscErrorCode PetscSFWindowSetFlavorType_Window(PetscSF sf, PetscSFWindowFlavorType flavor) {
1665b0d146aSStefano Zampini   PetscSF_Window *w = (PetscSF_Window *)sf->data;
1675b0d146aSStefano Zampini 
1685b0d146aSStefano Zampini   PetscFunctionBegin;
1695b0d146aSStefano Zampini   w->flavor = flavor;
1705b0d146aSStefano Zampini   PetscFunctionReturn(0);
1715b0d146aSStefano Zampini }
1725b0d146aSStefano Zampini 
1735b0d146aSStefano Zampini /*@C
1745b0d146aSStefano Zampini    PetscSFWindowGetFlavorType - Get flavor type for PetscSF communication
1755b0d146aSStefano Zampini 
1765b0d146aSStefano Zampini    Logically Collective
1775b0d146aSStefano Zampini 
1784165533cSJose E. Roman    Input Parameter:
1795b0d146aSStefano Zampini .  sf - star forest for communication
1805b0d146aSStefano Zampini 
1814165533cSJose E. Roman    Output Parameter:
1825b0d146aSStefano Zampini .  flavor - flavor type
1835b0d146aSStefano Zampini 
1845b0d146aSStefano Zampini    Level: advanced
1855b0d146aSStefano Zampini 
186db781477SPatrick Sanan .seealso: `PetscSFSetFromOptions()`, `PetscSFWindowSetFlavorType()`
1875b0d146aSStefano Zampini @*/
1889371c9d4SSatish Balay PetscErrorCode PetscSFWindowGetFlavorType(PetscSF sf, PetscSFWindowFlavorType *flavor) {
1895b0d146aSStefano Zampini   PetscFunctionBegin;
1905b0d146aSStefano Zampini   PetscValidHeaderSpecific(sf, PETSCSF_CLASSID, 1);
1915b0d146aSStefano Zampini   PetscValidPointer(flavor, 2);
192cac4c232SBarry Smith   PetscUseMethod(sf, "PetscSFWindowGetFlavorType_C", (PetscSF, PetscSFWindowFlavorType *), (sf, flavor));
1935b0d146aSStefano Zampini   PetscFunctionReturn(0);
1945b0d146aSStefano Zampini }
1955b0d146aSStefano Zampini 
1969371c9d4SSatish Balay static PetscErrorCode PetscSFWindowGetFlavorType_Window(PetscSF sf, PetscSFWindowFlavorType *flavor) {
1975b0d146aSStefano Zampini   PetscSF_Window *w = (PetscSF_Window *)sf->data;
1985b0d146aSStefano Zampini 
1995b0d146aSStefano Zampini   PetscFunctionBegin;
2005b0d146aSStefano Zampini   *flavor = w->flavor;
2015b0d146aSStefano Zampini   PetscFunctionReturn(0);
2025b0d146aSStefano Zampini }
2035b0d146aSStefano Zampini 
2045b0d146aSStefano Zampini /*@C
2055b0d146aSStefano Zampini    PetscSFWindowSetSyncType - Set synchronization type for PetscSF communication
20695fce210SBarry Smith 
20795fce210SBarry Smith    Logically Collective
20895fce210SBarry Smith 
2094165533cSJose E. Roman    Input Parameters:
21095fce210SBarry Smith +  sf - star forest for communication
21195fce210SBarry Smith -  sync - synchronization type
21295fce210SBarry Smith 
21395fce210SBarry Smith    Options Database Key:
21460263706SJed Brown .  -sf_window_sync <sync> - sets the synchronization type FENCE, LOCK, or ACTIVE (see PetscSFWindowSyncType)
21595fce210SBarry Smith 
21695fce210SBarry Smith    Level: advanced
21795fce210SBarry Smith 
218db781477SPatrick Sanan .seealso: `PetscSFSetFromOptions()`, `PetscSFWindowGetSyncType()`
21995fce210SBarry Smith @*/
2209371c9d4SSatish Balay PetscErrorCode PetscSFWindowSetSyncType(PetscSF sf, PetscSFWindowSyncType sync) {
22195fce210SBarry Smith   PetscFunctionBegin;
22295fce210SBarry Smith   PetscValidHeaderSpecific(sf, PETSCSF_CLASSID, 1);
22395fce210SBarry Smith   PetscValidLogicalCollectiveEnum(sf, sync, 2);
224cac4c232SBarry Smith   PetscTryMethod(sf, "PetscSFWindowSetSyncType_C", (PetscSF, PetscSFWindowSyncType), (sf, sync));
22595fce210SBarry Smith   PetscFunctionReturn(0);
22695fce210SBarry Smith }
22795fce210SBarry Smith 
2289371c9d4SSatish Balay static PetscErrorCode PetscSFWindowSetSyncType_Window(PetscSF sf, PetscSFWindowSyncType sync) {
22995fce210SBarry Smith   PetscSF_Window *w = (PetscSF_Window *)sf->data;
23095fce210SBarry Smith 
23195fce210SBarry Smith   PetscFunctionBegin;
23295fce210SBarry Smith   w->sync = sync;
23395fce210SBarry Smith   PetscFunctionReturn(0);
23495fce210SBarry Smith }
23595fce210SBarry Smith 
23695fce210SBarry Smith /*@C
2375b0d146aSStefano Zampini    PetscSFWindowGetSyncType - Get synchronization type for PetscSF communication
23895fce210SBarry Smith 
23995fce210SBarry Smith    Logically Collective
24095fce210SBarry Smith 
2414165533cSJose E. Roman    Input Parameter:
24295fce210SBarry Smith .  sf - star forest for communication
24395fce210SBarry Smith 
2444165533cSJose E. Roman    Output Parameter:
24595fce210SBarry Smith .  sync - synchronization type
24695fce210SBarry Smith 
24795fce210SBarry Smith    Level: advanced
24895fce210SBarry Smith 
249db781477SPatrick Sanan .seealso: `PetscSFSetFromOptions()`, `PetscSFWindowSetSyncType()`
25095fce210SBarry Smith @*/
2519371c9d4SSatish Balay PetscErrorCode PetscSFWindowGetSyncType(PetscSF sf, PetscSFWindowSyncType *sync) {
25295fce210SBarry Smith   PetscFunctionBegin;
25395fce210SBarry Smith   PetscValidHeaderSpecific(sf, PETSCSF_CLASSID, 1);
25495fce210SBarry Smith   PetscValidPointer(sync, 2);
255cac4c232SBarry Smith   PetscUseMethod(sf, "PetscSFWindowGetSyncType_C", (PetscSF, PetscSFWindowSyncType *), (sf, sync));
25695fce210SBarry Smith   PetscFunctionReturn(0);
25795fce210SBarry Smith }
25895fce210SBarry Smith 
2599371c9d4SSatish Balay static PetscErrorCode PetscSFWindowGetSyncType_Window(PetscSF sf, PetscSFWindowSyncType *sync) {
26095fce210SBarry Smith   PetscSF_Window *w = (PetscSF_Window *)sf->data;
26195fce210SBarry Smith 
26295fce210SBarry Smith   PetscFunctionBegin;
26395fce210SBarry Smith   *sync = w->sync;
26495fce210SBarry Smith   PetscFunctionReturn(0);
26595fce210SBarry Smith }
26695fce210SBarry Smith 
26795fce210SBarry Smith /*@C
2685b0d146aSStefano Zampini    PetscSFWindowSetInfo - Set the MPI_Info handle that will be used for subsequent windows allocation
2695b0d146aSStefano Zampini 
2705b0d146aSStefano Zampini    Logically Collective
2715b0d146aSStefano Zampini 
2724165533cSJose E. Roman    Input Parameters:
2735b0d146aSStefano Zampini +  sf - star forest for communication
2745b0d146aSStefano Zampini -  info - MPI_Info handle
2755b0d146aSStefano Zampini 
2765b0d146aSStefano Zampini    Level: advanced
2775b0d146aSStefano Zampini 
2785b0d146aSStefano Zampini    Notes: the info handle is duplicated with a call to MPI_Info_dup unless info = MPI_INFO_NULL.
2795b0d146aSStefano Zampini 
280db781477SPatrick Sanan .seealso: `PetscSFSetFromOptions()`, `PetscSFWindowGetInfo()`
2815b0d146aSStefano Zampini @*/
2829371c9d4SSatish Balay PetscErrorCode PetscSFWindowSetInfo(PetscSF sf, MPI_Info info) {
2835b0d146aSStefano Zampini   PetscFunctionBegin;
2845b0d146aSStefano Zampini   PetscValidHeaderSpecific(sf, PETSCSF_CLASSID, 1);
285cac4c232SBarry Smith   PetscTryMethod(sf, "PetscSFWindowSetInfo_C", (PetscSF, MPI_Info), (sf, info));
2865b0d146aSStefano Zampini   PetscFunctionReturn(0);
2875b0d146aSStefano Zampini }
2885b0d146aSStefano Zampini 
2899371c9d4SSatish Balay static PetscErrorCode PetscSFWindowSetInfo_Window(PetscSF sf, MPI_Info info) {
2905b0d146aSStefano Zampini   PetscSF_Window *w = (PetscSF_Window *)sf->data;
2915b0d146aSStefano Zampini 
2925b0d146aSStefano Zampini   PetscFunctionBegin;
29348a46eb9SPierre Jolivet   if (w->info != MPI_INFO_NULL) PetscCallMPI(MPI_Info_free(&w->info));
29448a46eb9SPierre Jolivet   if (info != MPI_INFO_NULL) PetscCallMPI(MPI_Info_dup(info, &w->info));
2955b0d146aSStefano Zampini   PetscFunctionReturn(0);
2965b0d146aSStefano Zampini }
2975b0d146aSStefano Zampini 
2985b0d146aSStefano Zampini /*@C
2995b0d146aSStefano Zampini    PetscSFWindowGetInfo - Get the MPI_Info handle used for windows allocation
3005b0d146aSStefano Zampini 
3015b0d146aSStefano Zampini    Logically Collective
3025b0d146aSStefano Zampini 
3034165533cSJose E. Roman    Input Parameter:
3045b0d146aSStefano Zampini .  sf - star forest for communication
3055b0d146aSStefano Zampini 
3064165533cSJose E. Roman    Output Parameter:
3075b0d146aSStefano Zampini .  info - MPI_Info handle
3085b0d146aSStefano Zampini 
3095b0d146aSStefano Zampini    Level: advanced
3105b0d146aSStefano Zampini 
3115b0d146aSStefano Zampini    Notes: if PetscSFWindowSetInfo() has not be called, this returns MPI_INFO_NULL
3125b0d146aSStefano Zampini 
313db781477SPatrick Sanan .seealso: `PetscSFSetFromOptions()`, `PetscSFWindowSetInfo()`
3145b0d146aSStefano Zampini @*/
3159371c9d4SSatish Balay PetscErrorCode PetscSFWindowGetInfo(PetscSF sf, MPI_Info *info) {
3165b0d146aSStefano Zampini   PetscFunctionBegin;
3175b0d146aSStefano Zampini   PetscValidHeaderSpecific(sf, PETSCSF_CLASSID, 1);
3185b0d146aSStefano Zampini   PetscValidPointer(info, 2);
319cac4c232SBarry Smith   PetscUseMethod(sf, "PetscSFWindowGetInfo_C", (PetscSF, MPI_Info *), (sf, info));
3205b0d146aSStefano Zampini   PetscFunctionReturn(0);
3215b0d146aSStefano Zampini }
3225b0d146aSStefano Zampini 
3239371c9d4SSatish Balay static PetscErrorCode PetscSFWindowGetInfo_Window(PetscSF sf, MPI_Info *info) {
3245b0d146aSStefano Zampini   PetscSF_Window *w = (PetscSF_Window *)sf->data;
3255b0d146aSStefano Zampini 
3265b0d146aSStefano Zampini   PetscFunctionBegin;
3275b0d146aSStefano Zampini   *info = w->info;
3285b0d146aSStefano Zampini   PetscFunctionReturn(0);
3295b0d146aSStefano Zampini }
3305b0d146aSStefano Zampini 
3315b0d146aSStefano Zampini /*
33295fce210SBarry Smith    PetscSFGetWindow - Get a window for use with a given data type
33395fce210SBarry Smith 
33495fce210SBarry Smith    Collective on PetscSF
33595fce210SBarry Smith 
3364165533cSJose E. Roman    Input Parameters:
33795fce210SBarry Smith +  sf - star forest
33895fce210SBarry Smith .  unit - data type
33995fce210SBarry Smith .  array - array to be sent
3405b0d146aSStefano Zampini .  sync - type of synchronization PetscSFWindowSyncType
34195fce210SBarry Smith .  epoch - PETSC_TRUE to acquire the window and start an epoch, PETSC_FALSE to just acquire the window
3425b0d146aSStefano Zampini .  fenceassert - assert parameter for call to MPI_Win_fence(), if sync == PETSCSF_WINDOW_SYNC_FENCE
3435b0d146aSStefano Zampini .  postassert - assert parameter for call to MPI_Win_post(), if sync == PETSCSF_WINDOW_SYNC_ACTIVE
344684a874aSStefano Zampini -  startassert - assert parameter for call to MPI_Win_start(), if sync == PETSCSF_WINDOW_SYNC_ACTIVE
34595fce210SBarry Smith 
3464165533cSJose E. Roman    Output Parameters:
347684a874aSStefano Zampini +  target_disp - target_disp argument for RMA calls (significative for PETSCSF_WINDOW_FLAVOR_DYNAMIC only)
348684a874aSStefano Zampini +  reqs - array of requests (significative for sync == PETSCSF_WINDOW_SYNC_LOCK only)
349684a874aSStefano Zampini -  win - window
35095fce210SBarry Smith 
35195fce210SBarry Smith    Level: developer
352db781477SPatrick Sanan .seealso: `PetscSFGetRootRanks()`, `PetscSFWindowGetDataTypes()`
3535b0d146aSStefano Zampini */
3549371c9d4SSatish Balay 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) {
35595fce210SBarry Smith   PetscSF_Window *w = (PetscSF_Window *)sf->data;
35695fce210SBarry Smith   MPI_Aint        lb, lb_true, bytes, bytes_true;
35795fce210SBarry Smith   PetscSFWinLink  link;
358d547623eSJunchao Zhang #if defined(PETSC_HAVE_MPI_FEATURE_DYNAMIC_WINDOW)
3595b0d146aSStefano Zampini   MPI_Aint winaddr;
3605b0d146aSStefano Zampini   PetscInt nranks;
361d547623eSJunchao Zhang #endif
3625b0d146aSStefano Zampini   PetscBool reuse = PETSC_FALSE, update = PETSC_FALSE;
3635b0d146aSStefano Zampini   PetscBool dummy[2];
3645b0d146aSStefano Zampini   MPI_Aint  wsize;
36595fce210SBarry Smith 
36695fce210SBarry Smith   PetscFunctionBegin;
3679566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Type_get_extent(unit, &lb, &bytes));
3689566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Type_get_true_extent(unit, &lb_true, &bytes_true));
369c9cc58a2SBarry Smith   PetscCheck(lb == 0 && lb_true == 0, 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");
37008401ef6SPierre Jolivet   PetscCheck(bytes == bytes_true, 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");
3715b0d146aSStefano Zampini   if (w->flavor != PETSCSF_WINDOW_FLAVOR_CREATE) reuse = PETSC_TRUE;
3725b0d146aSStefano Zampini   for (link = w->wins; reuse && link; link = link->next) {
3735b0d146aSStefano Zampini     PetscBool winok = PETSC_FALSE;
3745b0d146aSStefano Zampini     if (w->flavor != link->flavor) continue;
3755b0d146aSStefano Zampini     switch (w->flavor) {
3765b0d146aSStefano 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) */
3775b0d146aSStefano Zampini       if (array == link->addr) {
37876bd3646SJed Brown         if (PetscDefined(USE_DEBUG)) {
3795b0d146aSStefano Zampini           dummy[0] = PETSC_TRUE;
3805b0d146aSStefano Zampini           dummy[1] = PETSC_TRUE;
3819566063dSJacob Faibussowitsch           PetscCallMPI(MPI_Allreduce(MPI_IN_PLACE, dummy, 1, MPIU_BOOL, MPI_LAND, PetscObjectComm((PetscObject)sf)));
3829566063dSJacob Faibussowitsch           PetscCallMPI(MPI_Allreduce(MPI_IN_PLACE, dummy + 1, 1, MPIU_BOOL, MPI_LOR, PetscObjectComm((PetscObject)sf)));
38308401ef6SPierre Jolivet           PetscCheck(dummy[0] == dummy[1], 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");
38476bd3646SJed Brown         }
38528b400f6SJacob Faibussowitsch         PetscCheck(!link->inuse, PetscObjectComm((PetscObject)sf), PETSC_ERR_PLIB, "Window in use");
38608401ef6SPierre Jolivet         PetscCheck(!epoch || !link->epoch, PetscObjectComm((PetscObject)sf), PETSC_ERR_PLIB, "Window epoch not finished");
3875b0d146aSStefano Zampini         winok       = PETSC_TRUE;
3885b0d146aSStefano Zampini         link->paddr = array;
38976bd3646SJed Brown       } else if (PetscDefined(USE_DEBUG)) {
3905b0d146aSStefano Zampini         dummy[0] = PETSC_FALSE;
3915b0d146aSStefano Zampini         dummy[1] = PETSC_FALSE;
3929566063dSJacob Faibussowitsch         PetscCallMPI(MPI_Allreduce(MPI_IN_PLACE, dummy, 1, MPIU_BOOL, MPI_LAND, PetscObjectComm((PetscObject)sf)));
3939566063dSJacob Faibussowitsch         PetscCallMPI(MPI_Allreduce(MPI_IN_PLACE, dummy + 1, 1, MPIU_BOOL, MPI_LOR, PetscObjectComm((PetscObject)sf)));
39408401ef6SPierre Jolivet         PetscCheck(dummy[0] == dummy[1], 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");
3955b0d146aSStefano Zampini       }
3965b0d146aSStefano Zampini       break;
3975b0d146aSStefano Zampini     case PETSCSF_WINDOW_FLAVOR_ALLOCATE: /* check available by matching size, allocate if in use */
3985b0d146aSStefano Zampini     case PETSCSF_WINDOW_FLAVOR_SHARED:
3995b0d146aSStefano Zampini       if (!link->inuse && bytes == (MPI_Aint)link->bytes) {
4005b0d146aSStefano Zampini         update      = PETSC_TRUE;
4015b0d146aSStefano Zampini         link->paddr = array;
4025b0d146aSStefano Zampini         winok       = PETSC_TRUE;
4035b0d146aSStefano Zampini       }
4045b0d146aSStefano Zampini       break;
40598921bdaSJacob Faibussowitsch     default: SETERRQ(PetscObjectComm((PetscObject)sf), PETSC_ERR_SUP, "No support for flavor %s", PetscSFWindowFlavorTypes[w->flavor]);
4065b0d146aSStefano Zampini     }
4075b0d146aSStefano Zampini     if (winok) {
4085b0d146aSStefano Zampini       *win = link->win;
4099566063dSJacob Faibussowitsch       PetscCall(PetscInfo(sf, "Reusing window %" PETSC_MPI_WIN_FMT " of flavor %d for comm %" PETSC_MPI_COMM_FMT "\n", link->win, link->flavor, PetscObjectComm((PetscObject)sf)));
4105b0d146aSStefano Zampini       goto found;
4115b0d146aSStefano Zampini     }
4125b0d146aSStefano Zampini   }
4135b0d146aSStefano Zampini 
4145b0d146aSStefano Zampini   wsize = (MPI_Aint)bytes * sf->nroots;
4159566063dSJacob Faibussowitsch   PetscCall(PetscNew(&link));
41695fce210SBarry Smith   link->bytes           = bytes;
41795fce210SBarry Smith   link->next            = w->wins;
4185b0d146aSStefano Zampini   link->flavor          = w->flavor;
4195b0d146aSStefano Zampini   link->dyn_target_addr = NULL;
420684a874aSStefano Zampini   link->reqs            = NULL;
42195fce210SBarry Smith   w->wins               = link;
422684a874aSStefano Zampini   if (sync == PETSCSF_WINDOW_SYNC_LOCK) {
423684a874aSStefano Zampini     PetscInt i;
424684a874aSStefano Zampini 
4259566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(sf->nranks, &link->reqs));
426684a874aSStefano Zampini     for (i = 0; i < sf->nranks; i++) link->reqs[i] = MPI_REQUEST_NULL;
427684a874aSStefano Zampini   }
4285b0d146aSStefano Zampini   switch (w->flavor) {
4295b0d146aSStefano Zampini   case PETSCSF_WINDOW_FLAVOR_CREATE:
4309566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Win_create(array, wsize, (PetscMPIInt)bytes, w->info, PetscObjectComm((PetscObject)sf), &link->win));
4315b0d146aSStefano Zampini     link->addr  = array;
4325b0d146aSStefano Zampini     link->paddr = array;
4335b0d146aSStefano Zampini     break;
434d547623eSJunchao Zhang #if defined(PETSC_HAVE_MPI_FEATURE_DYNAMIC_WINDOW)
4359371c9d4SSatish Balay   case PETSCSF_WINDOW_FLAVOR_DYNAMIC: PetscCallMPI(MPI_Win_create_dynamic(w->info, PetscObjectComm((PetscObject)sf), &link->win));
4365b0d146aSStefano Zampini #if defined(PETSC_HAVE_OMPI_MAJOR_VERSION) /* some OpenMPI versions do not support MPI_Win_attach(win,NULL,0); */
437244dd087SJunchao Zhang     PetscCallMPI(MPI_Win_attach(link->win, wsize ? array : (void *)dummy, wsize));
4385b0d146aSStefano Zampini #else
4399566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Win_attach(link->win, array, wsize));
4405b0d146aSStefano Zampini #endif
4415b0d146aSStefano Zampini     link->addr  = array;
4425b0d146aSStefano Zampini     link->paddr = array;
44328b400f6SJacob Faibussowitsch     PetscCheck(w->dynsf, PetscObjectComm((PetscObject)sf), PETSC_ERR_ORDER, "Must call PetscSFSetUp()");
4449566063dSJacob Faibussowitsch     PetscCall(PetscSFSetUp(w->dynsf));
4459566063dSJacob Faibussowitsch     PetscCall(PetscSFGetRootRanks(w->dynsf, &nranks, NULL, NULL, NULL, NULL));
4469566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(nranks, &link->dyn_target_addr));
4479566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Get_address(array, &winaddr));
4489566063dSJacob Faibussowitsch     PetscCall(PetscSFBcastBegin(w->dynsf, MPI_AINT, &winaddr, link->dyn_target_addr, MPI_REPLACE));
4499566063dSJacob Faibussowitsch     PetscCall(PetscSFBcastEnd(w->dynsf, MPI_AINT, &winaddr, link->dyn_target_addr, MPI_REPLACE));
4505b0d146aSStefano Zampini     break;
4515b0d146aSStefano Zampini   case PETSCSF_WINDOW_FLAVOR_ALLOCATE:
4529566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Win_allocate(wsize, (PetscMPIInt)bytes, w->info, PetscObjectComm((PetscObject)sf), &link->addr, &link->win));
4535b0d146aSStefano Zampini     update      = PETSC_TRUE;
4545b0d146aSStefano Zampini     link->paddr = array;
4555b0d146aSStefano Zampini     break;
456d547623eSJunchao Zhang #endif
4575b0d146aSStefano Zampini #if defined(PETSC_HAVE_MPI_PROCESS_SHARED_MEMORY)
4585b0d146aSStefano Zampini   case PETSCSF_WINDOW_FLAVOR_SHARED:
4599566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Win_allocate_shared(wsize, (PetscMPIInt)bytes, w->info, PetscObjectComm((PetscObject)sf), &link->addr, &link->win));
4605b0d146aSStefano Zampini     update      = PETSC_TRUE;
4615b0d146aSStefano Zampini     link->paddr = array;
4625b0d146aSStefano Zampini     break;
4635b0d146aSStefano Zampini #endif
46498921bdaSJacob Faibussowitsch   default: SETERRQ(PetscObjectComm((PetscObject)sf), PETSC_ERR_SUP, "No support for flavor %s", PetscSFWindowFlavorTypes[w->flavor]);
4655b0d146aSStefano Zampini   }
4669566063dSJacob Faibussowitsch   PetscCall(PetscInfo(sf, "New window %" PETSC_MPI_WIN_FMT " of flavor %d for comm %" PETSC_MPI_COMM_FMT "\n", link->win, link->flavor, PetscObjectComm((PetscObject)sf)));
46795fce210SBarry Smith   *win = link->win;
46895fce210SBarry Smith 
4695b0d146aSStefano Zampini found:
4705b0d146aSStefano Zampini 
471684a874aSStefano Zampini   if (target_disp) *target_disp = link->dyn_target_addr;
472684a874aSStefano Zampini   if (reqs) *reqs = link->reqs;
473684a874aSStefano Zampini   if (update) { /* locks are needed for the "separate" memory model only, the fence guaranties memory-synchronization */
474684a874aSStefano Zampini     PetscMPIInt rank;
475684a874aSStefano Zampini 
4769566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)sf), &rank));
4779566063dSJacob Faibussowitsch     if (sync == PETSCSF_WINDOW_SYNC_LOCK) PetscCallMPI(MPI_Win_lock(MPI_LOCK_EXCLUSIVE, rank, MPI_MODE_NOCHECK, *win));
4789566063dSJacob Faibussowitsch     PetscCall(PetscMemcpy(link->addr, array, sf->nroots * bytes));
4795b0d146aSStefano Zampini     if (sync == PETSCSF_WINDOW_SYNC_LOCK) {
4809566063dSJacob Faibussowitsch       PetscCallMPI(MPI_Win_unlock(rank, *win));
4819566063dSJacob Faibussowitsch       PetscCallMPI(MPI_Win_fence(0, *win));
4825b0d146aSStefano Zampini     }
4835b0d146aSStefano Zampini   }
4845b0d146aSStefano Zampini   link->inuse = PETSC_TRUE;
4855b0d146aSStefano Zampini   link->epoch = epoch;
48695fce210SBarry Smith   if (epoch) {
4875b0d146aSStefano Zampini     switch (sync) {
4889371c9d4SSatish Balay     case PETSCSF_WINDOW_SYNC_FENCE: PetscCallMPI(MPI_Win_fence(fenceassert, *win)); break;
4899371c9d4SSatish Balay     case PETSCSF_WINDOW_SYNC_LOCK: /* Handled outside */ break;
49095fce210SBarry Smith     case PETSCSF_WINDOW_SYNC_ACTIVE: {
49195fce210SBarry Smith       MPI_Group   ingroup, outgroup;
4925b0d146aSStefano Zampini       PetscMPIInt isize, osize;
4935b0d146aSStefano Zampini 
4945b0d146aSStefano Zampini       /* OpenMPI 4.0.2 with btl=vader does not like calling
4955b0d146aSStefano Zampini          - MPI_Win_complete when ogroup is empty
4965b0d146aSStefano Zampini          - MPI_Win_wait when igroup is empty
4975b0d146aSStefano Zampini          So, we do not even issue the corresponding start and post calls
4985b0d146aSStefano Zampini          The MPI standard (Sec. 11.5.2 of MPI 3.1) only requires that
4995b0d146aSStefano Zampini          start(outgroup) has a matching post(ingroup)
5005b0d146aSStefano Zampini          and this is guaranteed by PetscSF
5015b0d146aSStefano Zampini       */
5029566063dSJacob Faibussowitsch       PetscCall(PetscSFGetGroups(sf, &ingroup, &outgroup));
5039566063dSJacob Faibussowitsch       PetscCallMPI(MPI_Group_size(ingroup, &isize));
5049566063dSJacob Faibussowitsch       PetscCallMPI(MPI_Group_size(outgroup, &osize));
5059566063dSJacob Faibussowitsch       if (isize) PetscCallMPI(MPI_Win_post(ingroup, postassert, *win));
5069566063dSJacob Faibussowitsch       if (osize) PetscCallMPI(MPI_Win_start(outgroup, startassert, *win));
50795fce210SBarry Smith     } break;
50895fce210SBarry Smith     default: SETERRQ(PetscObjectComm((PetscObject)sf), PETSC_ERR_PLIB, "Unknown synchronization type");
50995fce210SBarry Smith     }
51095fce210SBarry Smith   }
51195fce210SBarry Smith   PetscFunctionReturn(0);
51295fce210SBarry Smith }
51395fce210SBarry Smith 
5145b0d146aSStefano Zampini /*
51595fce210SBarry Smith    PetscSFFindWindow - Finds a window that is already in use
51695fce210SBarry Smith 
51795fce210SBarry Smith    Not Collective
51895fce210SBarry Smith 
5194165533cSJose E. Roman    Input Parameters:
52095fce210SBarry Smith +  sf - star forest
52195fce210SBarry Smith .  unit - data type
52295fce210SBarry Smith -  array - array with which the window is associated
52395fce210SBarry Smith 
5244165533cSJose E. Roman    Output Parameters:
525684a874aSStefano Zampini +  win - window
526684a874aSStefano Zampini -  reqs - outstanding requests associated to the window
52795fce210SBarry Smith 
52895fce210SBarry Smith    Level: developer
52995fce210SBarry Smith 
530db781477SPatrick Sanan .seealso: `PetscSFGetWindow()`, `PetscSFRestoreWindow()`
5315b0d146aSStefano Zampini */
5329371c9d4SSatish Balay static PetscErrorCode PetscSFFindWindow(PetscSF sf, MPI_Datatype unit, const void *array, MPI_Win *win, MPI_Request **reqs) {
53395fce210SBarry Smith   PetscSF_Window *w = (PetscSF_Window *)sf->data;
53495fce210SBarry Smith   PetscSFWinLink  link;
53595fce210SBarry Smith 
53695fce210SBarry Smith   PetscFunctionBegin;
537c0cd0301SJed Brown   *win = MPI_WIN_NULL;
53895fce210SBarry Smith   for (link = w->wins; link; link = link->next) {
5395b0d146aSStefano Zampini     if (array == link->paddr) {
5409566063dSJacob Faibussowitsch       PetscCall(PetscInfo(sf, "Window %" PETSC_MPI_WIN_FMT " of flavor %d for comm %" PETSC_MPI_COMM_FMT "\n", link->win, link->flavor, PetscObjectComm((PetscObject)sf)));
54195fce210SBarry Smith       *win  = link->win;
542684a874aSStefano Zampini       *reqs = link->reqs;
54395fce210SBarry Smith       PetscFunctionReturn(0);
54495fce210SBarry Smith     }
54595fce210SBarry Smith   }
54695fce210SBarry Smith   SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, "Requested window not in use");
54795fce210SBarry Smith }
54895fce210SBarry Smith 
5495b0d146aSStefano Zampini /*
55095fce210SBarry Smith    PetscSFRestoreWindow - Restores a window obtained with PetscSFGetWindow()
55195fce210SBarry Smith 
55295fce210SBarry Smith    Collective
55395fce210SBarry Smith 
5544165533cSJose E. Roman    Input Parameters:
55595fce210SBarry Smith +  sf - star forest
55695fce210SBarry Smith .  unit - data type
55795fce210SBarry Smith .  array - array associated with window
5585b0d146aSStefano Zampini .  sync - type of synchronization PetscSFWindowSyncType
55995fce210SBarry Smith .  epoch - close an epoch, must match argument to PetscSFGetWindow()
5605b0d146aSStefano Zampini .  update - if we have to update the local window array
56195fce210SBarry Smith -  win - window
56295fce210SBarry Smith 
56395fce210SBarry Smith    Level: developer
56495fce210SBarry Smith 
565db781477SPatrick Sanan .seealso: `PetscSFFindWindow()`
5665b0d146aSStefano Zampini */
5679371c9d4SSatish Balay static PetscErrorCode PetscSFRestoreWindow(PetscSF sf, MPI_Datatype unit, void *array, PetscSFWindowSyncType sync, PetscBool epoch, PetscMPIInt fenceassert, PetscBool update, MPI_Win *win) {
56895fce210SBarry Smith   PetscSF_Window         *w = (PetscSF_Window *)sf->data;
56995fce210SBarry Smith   PetscSFWinLink         *p, link;
5705b0d146aSStefano Zampini   PetscBool               reuse = PETSC_FALSE;
5715b0d146aSStefano Zampini   PetscSFWindowFlavorType flavor;
5725b0d146aSStefano Zampini   void                   *laddr;
5735b0d146aSStefano Zampini   size_t                  bytes;
57495fce210SBarry Smith 
57595fce210SBarry Smith   PetscFunctionBegin;
57695fce210SBarry Smith   for (p = &w->wins; *p; p = &(*p)->next) {
57795fce210SBarry Smith     link = *p;
57895fce210SBarry Smith     if (*win == link->win) {
57908401ef6SPierre Jolivet       PetscCheck(array == link->paddr, PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, "Matched window, but not array");
58095fce210SBarry Smith       if (epoch != link->epoch) {
58128b400f6SJacob Faibussowitsch         PetscCheck(!epoch, PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, "No epoch to end");
582f7d195e4SLawrence Mitchell         SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, "Restoring window without ending epoch");
58395fce210SBarry Smith       }
5845b0d146aSStefano Zampini       laddr  = link->addr;
5855b0d146aSStefano Zampini       flavor = link->flavor;
5865b0d146aSStefano Zampini       bytes  = link->bytes;
5875b0d146aSStefano Zampini       if (flavor != PETSCSF_WINDOW_FLAVOR_CREATE) reuse = PETSC_TRUE;
5889371c9d4SSatish Balay       else {
5899371c9d4SSatish Balay         *p     = link->next;
5909371c9d4SSatish Balay         update = PETSC_FALSE;
5919371c9d4SSatish Balay       } /* remove from list */
59295fce210SBarry Smith       goto found;
59395fce210SBarry Smith     }
59495fce210SBarry Smith   }
59595fce210SBarry Smith   SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, "Requested window not in use");
59695fce210SBarry Smith 
59795fce210SBarry Smith found:
5989566063dSJacob Faibussowitsch   PetscCall(PetscInfo(sf, "Window %" PETSC_MPI_WIN_FMT " of flavor %d for comm %" PETSC_MPI_COMM_FMT "\n", link->win, link->flavor, PetscObjectComm((PetscObject)sf)));
59995fce210SBarry Smith   if (epoch) {
6005b0d146aSStefano Zampini     switch (sync) {
6019371c9d4SSatish Balay     case PETSCSF_WINDOW_SYNC_FENCE: PetscCallMPI(MPI_Win_fence(fenceassert, *win)); break;
6029371c9d4SSatish Balay     case PETSCSF_WINDOW_SYNC_LOCK: /* Handled outside */ break;
60395fce210SBarry Smith     case PETSCSF_WINDOW_SYNC_ACTIVE: {
6045b0d146aSStefano Zampini       MPI_Group   ingroup, outgroup;
6055b0d146aSStefano Zampini       PetscMPIInt isize, osize;
6065b0d146aSStefano Zampini 
6075b0d146aSStefano Zampini       /* OpenMPI 4.0.2 with btl=wader does not like calling
6085b0d146aSStefano Zampini          - MPI_Win_complete when ogroup is empty
6095b0d146aSStefano Zampini          - MPI_Win_wait when igroup is empty
6105b0d146aSStefano Zampini          The MPI standard (Sec. 11.5.2 of MPI 3.1) only requires that
6115b0d146aSStefano Zampini          - each process who issues a call to MPI_Win_start issues a call to MPI_Win_Complete
6125b0d146aSStefano Zampini          - each process who issues a call to MPI_Win_post issues a call to MPI_Win_Wait
6135b0d146aSStefano Zampini       */
6149566063dSJacob Faibussowitsch       PetscCall(PetscSFGetGroups(sf, &ingroup, &outgroup));
6159566063dSJacob Faibussowitsch       PetscCallMPI(MPI_Group_size(ingroup, &isize));
6169566063dSJacob Faibussowitsch       PetscCallMPI(MPI_Group_size(outgroup, &osize));
6179566063dSJacob Faibussowitsch       if (osize) PetscCallMPI(MPI_Win_complete(*win));
6189566063dSJacob Faibussowitsch       if (isize) PetscCallMPI(MPI_Win_wait(*win));
61995fce210SBarry Smith     } break;
62095fce210SBarry Smith     default: SETERRQ(PetscObjectComm((PetscObject)sf), PETSC_ERR_PLIB, "Unknown synchronization type");
62195fce210SBarry Smith     }
62295fce210SBarry Smith   }
6235b0d146aSStefano Zampini   if (update) {
62448a46eb9SPierre Jolivet     if (sync == PETSCSF_WINDOW_SYNC_LOCK) PetscCallMPI(MPI_Win_fence(MPI_MODE_NOPUT | MPI_MODE_NOSUCCEED, *win));
6259566063dSJacob Faibussowitsch     PetscCall(PetscMemcpy(array, laddr, sf->nroots * bytes));
6265b0d146aSStefano Zampini   }
6275b0d146aSStefano Zampini   link->epoch = PETSC_FALSE;
6285b0d146aSStefano Zampini   link->inuse = PETSC_FALSE;
6295b0d146aSStefano Zampini   link->paddr = NULL;
6305b0d146aSStefano Zampini   if (!reuse) {
6319566063dSJacob Faibussowitsch     PetscCall(PetscFree(link->dyn_target_addr));
6329566063dSJacob Faibussowitsch     PetscCall(PetscFree(link->reqs));
6339566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Win_free(&link->win));
6349566063dSJacob Faibussowitsch     PetscCall(PetscFree(link));
63595fce210SBarry Smith     *win = MPI_WIN_NULL;
6365b0d146aSStefano Zampini   }
63795fce210SBarry Smith   PetscFunctionReturn(0);
63895fce210SBarry Smith }
63995fce210SBarry Smith 
6409371c9d4SSatish Balay static PetscErrorCode PetscSFSetUp_Window(PetscSF sf) {
64195fce210SBarry Smith   PetscSF_Window *w = (PetscSF_Window *)sf->data;
64295fce210SBarry Smith   MPI_Group       ingroup, outgroup;
64395fce210SBarry Smith 
64495fce210SBarry Smith   PetscFunctionBegin;
6459566063dSJacob Faibussowitsch   PetscCall(PetscSFSetUpRanks(sf, MPI_GROUP_EMPTY));
6465b0d146aSStefano Zampini   if (!w->dynsf) {
6475b0d146aSStefano Zampini     PetscInt     i;
6485b0d146aSStefano Zampini     PetscSFNode *remotes;
6495b0d146aSStefano Zampini 
6509566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(sf->nranks, &remotes));
6515b0d146aSStefano Zampini     for (i = 0; i < sf->nranks; i++) {
6525b0d146aSStefano Zampini       remotes[i].rank  = sf->ranks[i];
6535b0d146aSStefano Zampini       remotes[i].index = 0;
6545b0d146aSStefano Zampini     }
6559566063dSJacob Faibussowitsch     PetscCall(PetscSFDuplicate(sf, PETSCSF_DUPLICATE_RANKS, &w->dynsf));
6569566063dSJacob Faibussowitsch     PetscCall(PetscSFWindowSetFlavorType(w->dynsf, PETSCSF_WINDOW_FLAVOR_CREATE)); /* break recursion */
6579566063dSJacob Faibussowitsch     PetscCall(PetscSFSetGraph(w->dynsf, 1, sf->nranks, NULL, PETSC_OWN_POINTER, remotes, PETSC_OWN_POINTER));
6585b0d146aSStefano Zampini   }
65995fce210SBarry Smith   switch (w->sync) {
6609371c9d4SSatish Balay   case PETSCSF_WINDOW_SYNC_ACTIVE: PetscCall(PetscSFGetGroups(sf, &ingroup, &outgroup));
6619371c9d4SSatish Balay   default: break;
66295fce210SBarry Smith   }
66395fce210SBarry Smith   PetscFunctionReturn(0);
66495fce210SBarry Smith }
66595fce210SBarry Smith 
6669371c9d4SSatish Balay static PetscErrorCode PetscSFSetFromOptions_Window(PetscSF sf, PetscOptionItems *PetscOptionsObject) {
66795fce210SBarry Smith   PetscSF_Window         *w      = (PetscSF_Window *)sf->data;
6685b0d146aSStefano Zampini   PetscSFWindowFlavorType flavor = w->flavor;
66995fce210SBarry Smith 
67095fce210SBarry Smith   PetscFunctionBegin;
671d0609cedSBarry Smith   PetscOptionsHeadBegin(PetscOptionsObject, "PetscSF Window options");
6729566063dSJacob Faibussowitsch   PetscCall(PetscOptionsEnum("-sf_window_sync", "synchronization type to use for PetscSF Window communication", "PetscSFWindowSetSyncType", PetscSFWindowSyncTypes, (PetscEnum)w->sync, (PetscEnum *)&w->sync, NULL));
6739566063dSJacob Faibussowitsch   PetscCall(PetscOptionsEnum("-sf_window_flavor", "flavor to use for PetscSF Window creation", "PetscSFWindowSetFlavorType", PetscSFWindowFlavorTypes, (PetscEnum)flavor, (PetscEnum *)&flavor, NULL));
6749566063dSJacob Faibussowitsch   PetscCall(PetscSFWindowSetFlavorType(sf, flavor));
675d0609cedSBarry Smith   PetscOptionsHeadEnd();
67695fce210SBarry Smith   PetscFunctionReturn(0);
67795fce210SBarry Smith }
67895fce210SBarry Smith 
6799371c9d4SSatish Balay static PetscErrorCode PetscSFReset_Window(PetscSF sf) {
68095fce210SBarry Smith   PetscSF_Window *w = (PetscSF_Window *)sf->data;
68195fce210SBarry Smith   PetscSFDataLink link, next;
68295fce210SBarry Smith   PetscSFWinLink  wlink, wnext;
68395fce210SBarry Smith   PetscInt        i;
68495fce210SBarry Smith 
68595fce210SBarry Smith   PetscFunctionBegin;
68695fce210SBarry Smith   for (link = w->link; link; link = next) {
68795fce210SBarry Smith     next = link->next;
6889566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Type_free(&link->unit));
68995fce210SBarry Smith     for (i = 0; i < sf->nranks; i++) {
6909566063dSJacob Faibussowitsch       PetscCallMPI(MPI_Type_free(&link->mine[i]));
6919566063dSJacob Faibussowitsch       PetscCallMPI(MPI_Type_free(&link->remote[i]));
69295fce210SBarry Smith     }
6939566063dSJacob Faibussowitsch     PetscCall(PetscFree2(link->mine, link->remote));
6949566063dSJacob Faibussowitsch     PetscCall(PetscFree(link));
69595fce210SBarry Smith   }
69695fce210SBarry Smith   w->link = NULL;
69795fce210SBarry Smith   for (wlink = w->wins; wlink; wlink = wnext) {
69895fce210SBarry Smith     wnext = wlink->next;
69928b400f6SJacob Faibussowitsch     PetscCheck(!wlink->inuse, PetscObjectComm((PetscObject)sf), PETSC_ERR_ARG_WRONGSTATE, "Window still in use with address %p", (void *)wlink->addr);
7009566063dSJacob Faibussowitsch     PetscCall(PetscFree(wlink->dyn_target_addr));
7019566063dSJacob Faibussowitsch     PetscCall(PetscFree(wlink->reqs));
7029566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Win_free(&wlink->win));
7039566063dSJacob Faibussowitsch     PetscCall(PetscFree(wlink));
70495fce210SBarry Smith   }
70595fce210SBarry Smith   w->wins = NULL;
7069566063dSJacob Faibussowitsch   PetscCall(PetscSFDestroy(&w->dynsf));
70748a46eb9SPierre Jolivet   if (w->info != MPI_INFO_NULL) PetscCallMPI(MPI_Info_free(&w->info));
70895fce210SBarry Smith   PetscFunctionReturn(0);
70995fce210SBarry Smith }
71095fce210SBarry Smith 
7119371c9d4SSatish Balay static PetscErrorCode PetscSFDestroy_Window(PetscSF sf) {
71295fce210SBarry Smith   PetscFunctionBegin;
7139566063dSJacob Faibussowitsch   PetscCall(PetscSFReset_Window(sf));
7149566063dSJacob Faibussowitsch   PetscCall(PetscFree(sf->data));
7159566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)sf, "PetscSFWindowSetSyncType_C", NULL));
7169566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)sf, "PetscSFWindowGetSyncType_C", NULL));
7179566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)sf, "PetscSFWindowSetFlavorType_C", NULL));
7189566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)sf, "PetscSFWindowGetFlavorType_C", NULL));
7199566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)sf, "PetscSFWindowSetInfo_C", NULL));
7209566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)sf, "PetscSFWindowGetInfo_C", NULL));
72195fce210SBarry Smith   PetscFunctionReturn(0);
72295fce210SBarry Smith }
72395fce210SBarry Smith 
7249371c9d4SSatish Balay static PetscErrorCode PetscSFView_Window(PetscSF sf, PetscViewer viewer) {
72595fce210SBarry Smith   PetscSF_Window   *w = (PetscSF_Window *)sf->data;
72695fce210SBarry Smith   PetscBool         iascii;
7275b0d146aSStefano Zampini   PetscViewerFormat format;
72895fce210SBarry Smith 
72995fce210SBarry Smith   PetscFunctionBegin;
7309566063dSJacob Faibussowitsch   PetscCall(PetscViewerGetFormat(viewer, &format));
7319566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
73295fce210SBarry Smith   if (iascii) {
7339566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  current flavor=%s synchronization=%s MultiSF sort=%s\n", PetscSFWindowFlavorTypes[w->flavor], PetscSFWindowSyncTypes[w->sync], sf->rankorder ? "rank-order" : "unordered"));
7345b0d146aSStefano Zampini     if (format == PETSC_VIEWER_ASCII_INFO_DETAIL) {
7355b0d146aSStefano Zampini       if (w->info != MPI_INFO_NULL) {
7365b0d146aSStefano Zampini         PetscMPIInt k, nkeys;
7375b0d146aSStefano Zampini         char        key[MPI_MAX_INFO_KEY], value[MPI_MAX_INFO_VAL];
7385b0d146aSStefano Zampini 
7399566063dSJacob Faibussowitsch         PetscCallMPI(MPI_Info_get_nkeys(w->info, &nkeys));
7409566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, "    current info with %d keys. Ordered key-value pairs follow:\n", nkeys));
7415b0d146aSStefano Zampini         for (k = 0; k < nkeys; k++) {
7425b0d146aSStefano Zampini           PetscMPIInt flag;
7435b0d146aSStefano Zampini 
7449566063dSJacob Faibussowitsch           PetscCallMPI(MPI_Info_get_nthkey(w->info, k, key));
7459566063dSJacob Faibussowitsch           PetscCallMPI(MPI_Info_get(w->info, key, MPI_MAX_INFO_VAL, value, &flag));
74628b400f6SJacob Faibussowitsch           PetscCheck(flag, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Missing key %s", key);
7479566063dSJacob Faibussowitsch           PetscCall(PetscViewerASCIIPrintf(viewer, "      %s = %s\n", key, value));
7485b0d146aSStefano Zampini         }
7495b0d146aSStefano Zampini       } else {
7509566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, "    current info=MPI_INFO_NULL\n"));
7515b0d146aSStefano Zampini       }
7525b0d146aSStefano Zampini     }
75395fce210SBarry Smith   }
75495fce210SBarry Smith   PetscFunctionReturn(0);
75595fce210SBarry Smith }
75695fce210SBarry Smith 
7579371c9d4SSatish Balay static PetscErrorCode PetscSFDuplicate_Window(PetscSF sf, PetscSFDuplicateOption opt, PetscSF newsf) {
75895fce210SBarry Smith   PetscSF_Window       *w = (PetscSF_Window *)sf->data;
75995fce210SBarry Smith   PetscSFWindowSyncType synctype;
76095fce210SBarry Smith 
76195fce210SBarry Smith   PetscFunctionBegin;
76295fce210SBarry Smith   synctype = w->sync;
76395fce210SBarry Smith   /* HACK: Must use FENCE or LOCK when called from PetscSFGetGroups() because ACTIVE here would cause recursion. */
7645b0d146aSStefano Zampini   if (!sf->setupcalled) synctype = PETSCSF_WINDOW_SYNC_LOCK;
7659566063dSJacob Faibussowitsch   PetscCall(PetscSFWindowSetSyncType(newsf, synctype));
7669566063dSJacob Faibussowitsch   PetscCall(PetscSFWindowSetFlavorType(newsf, w->flavor));
7679566063dSJacob Faibussowitsch   PetscCall(PetscSFWindowSetInfo(newsf, w->info));
76895fce210SBarry Smith   PetscFunctionReturn(0);
76995fce210SBarry Smith }
77095fce210SBarry Smith 
7719371c9d4SSatish Balay static PetscErrorCode PetscSFBcastBegin_Window(PetscSF sf, MPI_Datatype unit, PetscMemType rootmtype, const void *rootdata, PetscMemType leafmtype, void *leafdata, MPI_Op op) {
77295fce210SBarry Smith   PetscSF_Window     *w = (PetscSF_Window *)sf->data;
77395fce210SBarry Smith   PetscInt            i, nranks;
77495fce210SBarry Smith   const PetscMPIInt  *ranks;
7755b0d146aSStefano Zampini   const MPI_Aint     *target_disp;
77695fce210SBarry Smith   const MPI_Datatype *mine, *remote;
777684a874aSStefano Zampini   MPI_Request        *reqs;
77895fce210SBarry Smith   MPI_Win             win;
77995fce210SBarry Smith 
78095fce210SBarry Smith   PetscFunctionBegin;
78108401ef6SPierre Jolivet   PetscCheck(op == MPI_REPLACE, PetscObjectComm((PetscObject)sf), PETSC_ERR_SUP, "PetscSFBcastBegin_Window with op!=MPI_REPLACE has not been implemented");
7829566063dSJacob Faibussowitsch   PetscCall(PetscSFGetRootRanks(sf, &nranks, &ranks, NULL, NULL, NULL));
7839566063dSJacob Faibussowitsch   PetscCall(PetscSFWindowGetDataTypes(sf, unit, &mine, &remote));
7849566063dSJacob Faibussowitsch   PetscCall(PetscSFGetWindow(sf, unit, (void *)rootdata, w->sync, PETSC_TRUE, MPI_MODE_NOPUT | MPI_MODE_NOPRECEDE, MPI_MODE_NOPUT, 0, &target_disp, &reqs, &win));
78595fce210SBarry Smith   for (i = 0; i < nranks; i++) {
7865b0d146aSStefano Zampini     MPI_Aint tdp = target_disp ? target_disp[i] : 0;
7875b0d146aSStefano Zampini 
788684a874aSStefano Zampini     if (w->sync == PETSCSF_WINDOW_SYNC_LOCK) {
7899566063dSJacob Faibussowitsch       PetscCallMPI(MPI_Win_lock(MPI_LOCK_SHARED, ranks[i], MPI_MODE_NOCHECK, win));
790684a874aSStefano Zampini #if defined(PETSC_HAVE_MPI_RGET)
7919566063dSJacob Faibussowitsch       PetscCallMPI(MPI_Rget(leafdata, 1, mine[i], ranks[i], tdp, 1, remote[i], win, &reqs[i]));
792684a874aSStefano Zampini #else
7939566063dSJacob Faibussowitsch       PetscCallMPI(MPI_Get(leafdata, 1, mine[i], ranks[i], tdp, 1, remote[i], win));
794684a874aSStefano Zampini #endif
795684a874aSStefano Zampini     } else {
7969566063dSJacob Faibussowitsch       PetscCallMPI(MPI_Get(leafdata, 1, mine[i], ranks[i], tdp, 1, remote[i], win));
797684a874aSStefano Zampini     }
79895fce210SBarry Smith   }
79995fce210SBarry Smith   PetscFunctionReturn(0);
80095fce210SBarry Smith }
80195fce210SBarry Smith 
8029371c9d4SSatish Balay PetscErrorCode PetscSFBcastEnd_Window(PetscSF sf, MPI_Datatype unit, const void *rootdata, void *leafdata, MPI_Op op) {
8035b0d146aSStefano Zampini   PetscSF_Window *w = (PetscSF_Window *)sf->data;
80495fce210SBarry Smith   MPI_Win         win;
8054b9acda6SJunchao Zhang   MPI_Request    *reqs = NULL;
80695fce210SBarry Smith 
80795fce210SBarry Smith   PetscFunctionBegin;
8089566063dSJacob Faibussowitsch   PetscCall(PetscSFFindWindow(sf, unit, rootdata, &win, &reqs));
8099566063dSJacob Faibussowitsch   if (reqs) PetscCallMPI(MPI_Waitall(sf->nranks, reqs, MPI_STATUSES_IGNORE));
810684a874aSStefano Zampini   if (w->sync == PETSCSF_WINDOW_SYNC_LOCK) {
811684a874aSStefano Zampini     PetscInt           i, nranks;
812684a874aSStefano Zampini     const PetscMPIInt *ranks;
813684a874aSStefano Zampini 
8149566063dSJacob Faibussowitsch     PetscCall(PetscSFGetRootRanks(sf, &nranks, &ranks, NULL, NULL, NULL));
81548a46eb9SPierre Jolivet     for (i = 0; i < nranks; i++) PetscCallMPI(MPI_Win_unlock(ranks[i], win));
816684a874aSStefano Zampini   }
8179566063dSJacob Faibussowitsch   PetscCall(PetscSFRestoreWindow(sf, unit, (void *)rootdata, w->sync, PETSC_TRUE, MPI_MODE_NOSTORE | MPI_MODE_NOSUCCEED, PETSC_FALSE, &win));
81895fce210SBarry Smith   PetscFunctionReturn(0);
81995fce210SBarry Smith }
82095fce210SBarry Smith 
8219371c9d4SSatish Balay PetscErrorCode PetscSFReduceBegin_Window(PetscSF sf, MPI_Datatype unit, PetscMemType leafmtype, const void *leafdata, PetscMemType rootmtype, void *rootdata, MPI_Op op) {
82295fce210SBarry Smith   PetscSF_Window     *w = (PetscSF_Window *)sf->data;
82395fce210SBarry Smith   PetscInt            i, nranks;
82495fce210SBarry Smith   const PetscMPIInt  *ranks;
8255b0d146aSStefano Zampini   const MPI_Aint     *target_disp;
82695fce210SBarry Smith   const MPI_Datatype *mine, *remote;
82795fce210SBarry Smith   MPI_Win             win;
82895fce210SBarry Smith 
82995fce210SBarry Smith   PetscFunctionBegin;
8309566063dSJacob Faibussowitsch   PetscCall(PetscSFGetRootRanks(sf, &nranks, &ranks, NULL, NULL, NULL));
8319566063dSJacob Faibussowitsch   PetscCall(PetscSFWindowGetDataTypes(sf, unit, &mine, &remote));
8329566063dSJacob Faibussowitsch   PetscCall(PetscSFWindowOpTranslate(&op));
8339566063dSJacob Faibussowitsch   PetscCall(PetscSFGetWindow(sf, unit, rootdata, w->sync, PETSC_TRUE, MPI_MODE_NOPRECEDE, 0, 0, &target_disp, NULL, &win));
83495fce210SBarry Smith   for (i = 0; i < nranks; i++) {
8355b0d146aSStefano Zampini     MPI_Aint tdp = target_disp ? target_disp[i] : 0;
8365b0d146aSStefano Zampini 
8379566063dSJacob Faibussowitsch     if (w->sync == PETSCSF_WINDOW_SYNC_LOCK) PetscCallMPI(MPI_Win_lock(MPI_LOCK_SHARED, ranks[i], MPI_MODE_NOCHECK, win));
8389566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Accumulate((void *)leafdata, 1, mine[i], ranks[i], tdp, 1, remote[i], op, win));
8399566063dSJacob Faibussowitsch     if (w->sync == PETSCSF_WINDOW_SYNC_LOCK) PetscCallMPI(MPI_Win_unlock(ranks[i], win));
84095fce210SBarry Smith   }
84195fce210SBarry Smith   PetscFunctionReturn(0);
84295fce210SBarry Smith }
84395fce210SBarry Smith 
8449371c9d4SSatish Balay static PetscErrorCode PetscSFReduceEnd_Window(PetscSF sf, MPI_Datatype unit, const void *leafdata, void *rootdata, MPI_Op op) {
84595fce210SBarry Smith   PetscSF_Window *w = (PetscSF_Window *)sf->data;
84695fce210SBarry Smith   MPI_Win         win;
8474b9acda6SJunchao Zhang   MPI_Request    *reqs = NULL;
84895fce210SBarry Smith 
84995fce210SBarry Smith   PetscFunctionBegin;
8509566063dSJacob Faibussowitsch   PetscCall(PetscSFFindWindow(sf, unit, rootdata, &win, &reqs));
8519566063dSJacob Faibussowitsch   if (reqs) PetscCallMPI(MPI_Waitall(sf->nranks, reqs, MPI_STATUSES_IGNORE));
8529566063dSJacob Faibussowitsch   PetscCall(PetscSFRestoreWindow(sf, unit, rootdata, w->sync, PETSC_TRUE, MPI_MODE_NOSUCCEED, PETSC_TRUE, &win));
85395fce210SBarry Smith   PetscFunctionReturn(0);
85495fce210SBarry Smith }
8555b0d146aSStefano Zampini 
8569371c9d4SSatish Balay static PetscErrorCode PetscSFFetchAndOpBegin_Window(PetscSF sf, MPI_Datatype unit, PetscMemType rootmtype, void *rootdata, PetscMemType leafmtype, const void *leafdata, void *leafupdate, MPI_Op op) {
85795fce210SBarry Smith   PetscInt            i, nranks;
85895fce210SBarry Smith   const PetscMPIInt  *ranks;
85995fce210SBarry Smith   const MPI_Datatype *mine, *remote;
8605b0d146aSStefano Zampini   const MPI_Aint     *target_disp;
86195fce210SBarry Smith   MPI_Win             win;
8625b0d146aSStefano Zampini   PetscSF_Window     *w = (PetscSF_Window *)sf->data;
8635b0d146aSStefano Zampini #if !defined(PETSC_HAVE_MPI_GET_ACCUMULATE)
8645b0d146aSStefano Zampini   PetscSFWindowFlavorType oldf;
8655b0d146aSStefano Zampini #endif
86695fce210SBarry Smith 
86795fce210SBarry Smith   PetscFunctionBegin;
8689566063dSJacob Faibussowitsch   PetscCall(PetscSFGetRootRanks(sf, &nranks, &ranks, NULL, NULL, NULL));
8699566063dSJacob Faibussowitsch   PetscCall(PetscSFWindowGetDataTypes(sf, unit, &mine, &remote));
8709566063dSJacob Faibussowitsch   PetscCall(PetscSFWindowOpTranslate(&op));
8715b0d146aSStefano Zampini #if !defined(PETSC_HAVE_MPI_GET_ACCUMULATE)
8725b0d146aSStefano Zampini   /* FetchAndOp without MPI_Get_Accumulate requires locking.
8735b0d146aSStefano Zampini      we create a new window every time to not interfere with user-defined MPI_Info which may have used "no_locks"="true" */
8745b0d146aSStefano Zampini   oldf      = w->flavor;
8755b0d146aSStefano Zampini   w->flavor = PETSCSF_WINDOW_FLAVOR_CREATE;
8769566063dSJacob Faibussowitsch   PetscCall(PetscSFGetWindow(sf, unit, rootdata, PETSCSF_WINDOW_SYNC_LOCK, PETSC_FALSE, 0, 0, 0, &target_disp, NULL, &win));
8775b0d146aSStefano Zampini #else
8789566063dSJacob Faibussowitsch   PetscCall(PetscSFGetWindow(sf, unit, rootdata, w->sync, PETSC_TRUE, MPI_MODE_NOPRECEDE, 0, 0, &target_disp, NULL, &win));
8795b0d146aSStefano Zampini #endif
8805b0d146aSStefano Zampini   for (i = 0; i < nranks; i++) {
8815b0d146aSStefano Zampini     MPI_Aint tdp = target_disp ? target_disp[i] : 0;
8825b0d146aSStefano Zampini 
8835b0d146aSStefano Zampini #if !defined(PETSC_HAVE_MPI_GET_ACCUMULATE)
8849566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Win_lock(MPI_LOCK_EXCLUSIVE, ranks[i], 0, win));
8859566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Get(leafupdate, 1, mine[i], ranks[i], tdp, 1, remote[i], win));
8869566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Accumulate((void *)leafdata, 1, mine[i], ranks[i], tdp, 1, remote[i], op, win));
8879566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Win_unlock(ranks[i], win));
8885b0d146aSStefano Zampini #else
8899566063dSJacob Faibussowitsch     if (w->sync == PETSCSF_WINDOW_SYNC_LOCK) PetscCallMPI(MPI_Win_lock(MPI_LOCK_SHARED, ranks[i], 0, win));
8909566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Get_accumulate((void *)leafdata, 1, mine[i], leafupdate, 1, mine[i], ranks[i], tdp, 1, remote[i], op, win));
8919566063dSJacob Faibussowitsch     if (w->sync == PETSCSF_WINDOW_SYNC_LOCK) PetscCallMPI(MPI_Win_unlock(ranks[i], win));
8925b0d146aSStefano Zampini #endif
8935b0d146aSStefano Zampini   }
8945b0d146aSStefano Zampini #if !defined(PETSC_HAVE_MPI_GET_ACCUMULATE)
8955b0d146aSStefano Zampini   w->flavor = oldf;
8965b0d146aSStefano Zampini #endif
89795fce210SBarry Smith   PetscFunctionReturn(0);
89895fce210SBarry Smith }
89995fce210SBarry Smith 
9009371c9d4SSatish Balay static PetscErrorCode PetscSFFetchAndOpEnd_Window(PetscSF sf, MPI_Datatype unit, void *rootdata, const void *leafdata, void *leafupdate, MPI_Op op) {
90195fce210SBarry Smith   MPI_Win win;
9025b0d146aSStefano Zampini #if defined(PETSC_HAVE_MPI_GET_ACCUMULATE)
9035b0d146aSStefano Zampini   PetscSF_Window *w = (PetscSF_Window *)sf->data;
9045b0d146aSStefano Zampini #endif
9054b9acda6SJunchao Zhang   MPI_Request *reqs = NULL;
90695fce210SBarry Smith 
90795fce210SBarry Smith   PetscFunctionBegin;
9089566063dSJacob Faibussowitsch   PetscCall(PetscSFFindWindow(sf, unit, rootdata, &win, &reqs));
9099566063dSJacob Faibussowitsch   if (reqs) PetscCallMPI(MPI_Waitall(sf->nranks, reqs, MPI_STATUSES_IGNORE));
9105b0d146aSStefano Zampini #if defined(PETSC_HAVE_MPI_GET_ACCUMULATE)
9119566063dSJacob Faibussowitsch   PetscCall(PetscSFRestoreWindow(sf, unit, rootdata, w->sync, PETSC_TRUE, MPI_MODE_NOSUCCEED, PETSC_TRUE, &win));
9125b0d146aSStefano Zampini #else
9139566063dSJacob Faibussowitsch   PetscCall(PetscSFRestoreWindow(sf, unit, rootdata, PETSCSF_WINDOW_SYNC_LOCK, PETSC_FALSE, 0, PETSC_TRUE, &win));
9145b0d146aSStefano Zampini #endif
91595fce210SBarry Smith   PetscFunctionReturn(0);
91695fce210SBarry Smith }
91795fce210SBarry Smith 
9189371c9d4SSatish Balay PETSC_INTERN PetscErrorCode PetscSFCreate_Window(PetscSF sf) {
91995fce210SBarry Smith   PetscSF_Window *w = (PetscSF_Window *)sf->data;
92095fce210SBarry Smith 
92195fce210SBarry Smith   PetscFunctionBegin;
92295fce210SBarry Smith   sf->ops->SetUp           = PetscSFSetUp_Window;
92395fce210SBarry Smith   sf->ops->SetFromOptions  = PetscSFSetFromOptions_Window;
92495fce210SBarry Smith   sf->ops->Reset           = PetscSFReset_Window;
92595fce210SBarry Smith   sf->ops->Destroy         = PetscSFDestroy_Window;
92695fce210SBarry Smith   sf->ops->View            = PetscSFView_Window;
92795fce210SBarry Smith   sf->ops->Duplicate       = PetscSFDuplicate_Window;
928ad227feaSJunchao Zhang   sf->ops->BcastBegin      = PetscSFBcastBegin_Window;
929ad227feaSJunchao Zhang   sf->ops->BcastEnd        = PetscSFBcastEnd_Window;
93095fce210SBarry Smith   sf->ops->ReduceBegin     = PetscSFReduceBegin_Window;
93195fce210SBarry Smith   sf->ops->ReduceEnd       = PetscSFReduceEnd_Window;
93295fce210SBarry Smith   sf->ops->FetchAndOpBegin = PetscSFFetchAndOpBegin_Window;
93395fce210SBarry Smith   sf->ops->FetchAndOpEnd   = PetscSFFetchAndOpEnd_Window;
93495fce210SBarry Smith 
935*4dfa11a4SJacob Faibussowitsch   PetscCall(PetscNew(&w));
93695fce210SBarry Smith   sf->data  = (void *)w;
93795fce210SBarry Smith   w->sync   = PETSCSF_WINDOW_SYNC_FENCE;
9385b0d146aSStefano Zampini   w->flavor = PETSCSF_WINDOW_FLAVOR_CREATE;
9395b0d146aSStefano Zampini   w->info   = MPI_INFO_NULL;
94095fce210SBarry Smith 
9419566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)sf, "PetscSFWindowSetSyncType_C", PetscSFWindowSetSyncType_Window));
9429566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)sf, "PetscSFWindowGetSyncType_C", PetscSFWindowGetSyncType_Window));
9439566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)sf, "PetscSFWindowSetFlavorType_C", PetscSFWindowSetFlavorType_Window));
9449566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)sf, "PetscSFWindowGetFlavorType_C", PetscSFWindowGetFlavorType_Window));
9459566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)sf, "PetscSFWindowSetInfo_C", PetscSFWindowSetInfo_Window));
9469566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)sf, "PetscSFWindowGetInfo_C", PetscSFWindowGetInfo_Window));
94795fce210SBarry Smith 
94895fce210SBarry Smith #if defined(OMPI_MAJOR_VERSION) && (OMPI_MAJOR_VERSION < 1 || (OMPI_MAJOR_VERSION == 1 && OMPI_MINOR_VERSION <= 6))
94995fce210SBarry Smith   {
95095fce210SBarry Smith     PetscBool ackbug = PETSC_FALSE;
9519566063dSJacob Faibussowitsch     PetscCall(PetscOptionsGetBool(NULL, NULL, "-acknowledge_ompi_onesided_bug", &ackbug, NULL));
95295fce210SBarry Smith     if (ackbug) {
9539566063dSJacob Faibussowitsch       PetscCall(PetscInfo(sf, "Acknowledged Open MPI bug, proceeding anyway. Expect memory corruption.\n"));
95495fce210SBarry 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");
95595fce210SBarry Smith   }
95695fce210SBarry Smith #endif
95795fce210SBarry Smith   PetscFunctionReturn(0);
95895fce210SBarry Smith }
959