xref: /petsc/src/vec/is/sf/impls/window/sfwindow.c (revision 48a46eb9bd028bec07ec0f396b1a3abb43f14558)
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;
293*48a46eb9SPierre Jolivet   if (w->info != MPI_INFO_NULL) PetscCallMPI(MPI_Info_free(&w->info));
294*48a46eb9SPierre 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) {
624*48a46eb9SPierre 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));
6589566063dSJacob Faibussowitsch     PetscCall(PetscLogObjectParent((PetscObject)sf, (PetscObject)w->dynsf));
6595b0d146aSStefano Zampini   }
66095fce210SBarry Smith   switch (w->sync) {
6619371c9d4SSatish Balay   case PETSCSF_WINDOW_SYNC_ACTIVE: PetscCall(PetscSFGetGroups(sf, &ingroup, &outgroup));
6629371c9d4SSatish Balay   default: break;
66395fce210SBarry Smith   }
66495fce210SBarry Smith   PetscFunctionReturn(0);
66595fce210SBarry Smith }
66695fce210SBarry Smith 
6679371c9d4SSatish Balay static PetscErrorCode PetscSFSetFromOptions_Window(PetscSF sf, PetscOptionItems *PetscOptionsObject) {
66895fce210SBarry Smith   PetscSF_Window         *w      = (PetscSF_Window *)sf->data;
6695b0d146aSStefano Zampini   PetscSFWindowFlavorType flavor = w->flavor;
67095fce210SBarry Smith 
67195fce210SBarry Smith   PetscFunctionBegin;
672d0609cedSBarry Smith   PetscOptionsHeadBegin(PetscOptionsObject, "PetscSF Window options");
6739566063dSJacob Faibussowitsch   PetscCall(PetscOptionsEnum("-sf_window_sync", "synchronization type to use for PetscSF Window communication", "PetscSFWindowSetSyncType", PetscSFWindowSyncTypes, (PetscEnum)w->sync, (PetscEnum *)&w->sync, NULL));
6749566063dSJacob Faibussowitsch   PetscCall(PetscOptionsEnum("-sf_window_flavor", "flavor to use for PetscSF Window creation", "PetscSFWindowSetFlavorType", PetscSFWindowFlavorTypes, (PetscEnum)flavor, (PetscEnum *)&flavor, NULL));
6759566063dSJacob Faibussowitsch   PetscCall(PetscSFWindowSetFlavorType(sf, flavor));
676d0609cedSBarry Smith   PetscOptionsHeadEnd();
67795fce210SBarry Smith   PetscFunctionReturn(0);
67895fce210SBarry Smith }
67995fce210SBarry Smith 
6809371c9d4SSatish Balay static PetscErrorCode PetscSFReset_Window(PetscSF sf) {
68195fce210SBarry Smith   PetscSF_Window *w = (PetscSF_Window *)sf->data;
68295fce210SBarry Smith   PetscSFDataLink link, next;
68395fce210SBarry Smith   PetscSFWinLink  wlink, wnext;
68495fce210SBarry Smith   PetscInt        i;
68595fce210SBarry Smith 
68695fce210SBarry Smith   PetscFunctionBegin;
68795fce210SBarry Smith   for (link = w->link; link; link = next) {
68895fce210SBarry Smith     next = link->next;
6899566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Type_free(&link->unit));
69095fce210SBarry Smith     for (i = 0; i < sf->nranks; i++) {
6919566063dSJacob Faibussowitsch       PetscCallMPI(MPI_Type_free(&link->mine[i]));
6929566063dSJacob Faibussowitsch       PetscCallMPI(MPI_Type_free(&link->remote[i]));
69395fce210SBarry Smith     }
6949566063dSJacob Faibussowitsch     PetscCall(PetscFree2(link->mine, link->remote));
6959566063dSJacob Faibussowitsch     PetscCall(PetscFree(link));
69695fce210SBarry Smith   }
69795fce210SBarry Smith   w->link = NULL;
69895fce210SBarry Smith   for (wlink = w->wins; wlink; wlink = wnext) {
69995fce210SBarry Smith     wnext = wlink->next;
70028b400f6SJacob Faibussowitsch     PetscCheck(!wlink->inuse, PetscObjectComm((PetscObject)sf), PETSC_ERR_ARG_WRONGSTATE, "Window still in use with address %p", (void *)wlink->addr);
7019566063dSJacob Faibussowitsch     PetscCall(PetscFree(wlink->dyn_target_addr));
7029566063dSJacob Faibussowitsch     PetscCall(PetscFree(wlink->reqs));
7039566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Win_free(&wlink->win));
7049566063dSJacob Faibussowitsch     PetscCall(PetscFree(wlink));
70595fce210SBarry Smith   }
70695fce210SBarry Smith   w->wins = NULL;
7079566063dSJacob Faibussowitsch   PetscCall(PetscSFDestroy(&w->dynsf));
708*48a46eb9SPierre Jolivet   if (w->info != MPI_INFO_NULL) PetscCallMPI(MPI_Info_free(&w->info));
70995fce210SBarry Smith   PetscFunctionReturn(0);
71095fce210SBarry Smith }
71195fce210SBarry Smith 
7129371c9d4SSatish Balay static PetscErrorCode PetscSFDestroy_Window(PetscSF sf) {
71395fce210SBarry Smith   PetscFunctionBegin;
7149566063dSJacob Faibussowitsch   PetscCall(PetscSFReset_Window(sf));
7159566063dSJacob Faibussowitsch   PetscCall(PetscFree(sf->data));
7169566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)sf, "PetscSFWindowSetSyncType_C", NULL));
7179566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)sf, "PetscSFWindowGetSyncType_C", NULL));
7189566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)sf, "PetscSFWindowSetFlavorType_C", NULL));
7199566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)sf, "PetscSFWindowGetFlavorType_C", NULL));
7209566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)sf, "PetscSFWindowSetInfo_C", NULL));
7219566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)sf, "PetscSFWindowGetInfo_C", NULL));
72295fce210SBarry Smith   PetscFunctionReturn(0);
72395fce210SBarry Smith }
72495fce210SBarry Smith 
7259371c9d4SSatish Balay static PetscErrorCode PetscSFView_Window(PetscSF sf, PetscViewer viewer) {
72695fce210SBarry Smith   PetscSF_Window   *w = (PetscSF_Window *)sf->data;
72795fce210SBarry Smith   PetscBool         iascii;
7285b0d146aSStefano Zampini   PetscViewerFormat format;
72995fce210SBarry Smith 
73095fce210SBarry Smith   PetscFunctionBegin;
7319566063dSJacob Faibussowitsch   PetscCall(PetscViewerGetFormat(viewer, &format));
7329566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
73395fce210SBarry Smith   if (iascii) {
7349566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  current flavor=%s synchronization=%s MultiSF sort=%s\n", PetscSFWindowFlavorTypes[w->flavor], PetscSFWindowSyncTypes[w->sync], sf->rankorder ? "rank-order" : "unordered"));
7355b0d146aSStefano Zampini     if (format == PETSC_VIEWER_ASCII_INFO_DETAIL) {
7365b0d146aSStefano Zampini       if (w->info != MPI_INFO_NULL) {
7375b0d146aSStefano Zampini         PetscMPIInt k, nkeys;
7385b0d146aSStefano Zampini         char        key[MPI_MAX_INFO_KEY], value[MPI_MAX_INFO_VAL];
7395b0d146aSStefano Zampini 
7409566063dSJacob Faibussowitsch         PetscCallMPI(MPI_Info_get_nkeys(w->info, &nkeys));
7419566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, "    current info with %d keys. Ordered key-value pairs follow:\n", nkeys));
7425b0d146aSStefano Zampini         for (k = 0; k < nkeys; k++) {
7435b0d146aSStefano Zampini           PetscMPIInt flag;
7445b0d146aSStefano Zampini 
7459566063dSJacob Faibussowitsch           PetscCallMPI(MPI_Info_get_nthkey(w->info, k, key));
7469566063dSJacob Faibussowitsch           PetscCallMPI(MPI_Info_get(w->info, key, MPI_MAX_INFO_VAL, value, &flag));
74728b400f6SJacob Faibussowitsch           PetscCheck(flag, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Missing key %s", key);
7489566063dSJacob Faibussowitsch           PetscCall(PetscViewerASCIIPrintf(viewer, "      %s = %s\n", key, value));
7495b0d146aSStefano Zampini         }
7505b0d146aSStefano Zampini       } else {
7519566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, "    current info=MPI_INFO_NULL\n"));
7525b0d146aSStefano Zampini       }
7535b0d146aSStefano Zampini     }
75495fce210SBarry Smith   }
75595fce210SBarry Smith   PetscFunctionReturn(0);
75695fce210SBarry Smith }
75795fce210SBarry Smith 
7589371c9d4SSatish Balay static PetscErrorCode PetscSFDuplicate_Window(PetscSF sf, PetscSFDuplicateOption opt, PetscSF newsf) {
75995fce210SBarry Smith   PetscSF_Window       *w = (PetscSF_Window *)sf->data;
76095fce210SBarry Smith   PetscSFWindowSyncType synctype;
76195fce210SBarry Smith 
76295fce210SBarry Smith   PetscFunctionBegin;
76395fce210SBarry Smith   synctype = w->sync;
76495fce210SBarry Smith   /* HACK: Must use FENCE or LOCK when called from PetscSFGetGroups() because ACTIVE here would cause recursion. */
7655b0d146aSStefano Zampini   if (!sf->setupcalled) synctype = PETSCSF_WINDOW_SYNC_LOCK;
7669566063dSJacob Faibussowitsch   PetscCall(PetscSFWindowSetSyncType(newsf, synctype));
7679566063dSJacob Faibussowitsch   PetscCall(PetscSFWindowSetFlavorType(newsf, w->flavor));
7689566063dSJacob Faibussowitsch   PetscCall(PetscSFWindowSetInfo(newsf, w->info));
76995fce210SBarry Smith   PetscFunctionReturn(0);
77095fce210SBarry Smith }
77195fce210SBarry Smith 
7729371c9d4SSatish Balay static PetscErrorCode PetscSFBcastBegin_Window(PetscSF sf, MPI_Datatype unit, PetscMemType rootmtype, const void *rootdata, PetscMemType leafmtype, void *leafdata, MPI_Op op) {
77395fce210SBarry Smith   PetscSF_Window     *w = (PetscSF_Window *)sf->data;
77495fce210SBarry Smith   PetscInt            i, nranks;
77595fce210SBarry Smith   const PetscMPIInt  *ranks;
7765b0d146aSStefano Zampini   const MPI_Aint     *target_disp;
77795fce210SBarry Smith   const MPI_Datatype *mine, *remote;
778684a874aSStefano Zampini   MPI_Request        *reqs;
77995fce210SBarry Smith   MPI_Win             win;
78095fce210SBarry Smith 
78195fce210SBarry Smith   PetscFunctionBegin;
78208401ef6SPierre Jolivet   PetscCheck(op == MPI_REPLACE, PetscObjectComm((PetscObject)sf), PETSC_ERR_SUP, "PetscSFBcastBegin_Window with op!=MPI_REPLACE has not been implemented");
7839566063dSJacob Faibussowitsch   PetscCall(PetscSFGetRootRanks(sf, &nranks, &ranks, NULL, NULL, NULL));
7849566063dSJacob Faibussowitsch   PetscCall(PetscSFWindowGetDataTypes(sf, unit, &mine, &remote));
7859566063dSJacob 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));
78695fce210SBarry Smith   for (i = 0; i < nranks; i++) {
7875b0d146aSStefano Zampini     MPI_Aint tdp = target_disp ? target_disp[i] : 0;
7885b0d146aSStefano Zampini 
789684a874aSStefano Zampini     if (w->sync == PETSCSF_WINDOW_SYNC_LOCK) {
7909566063dSJacob Faibussowitsch       PetscCallMPI(MPI_Win_lock(MPI_LOCK_SHARED, ranks[i], MPI_MODE_NOCHECK, win));
791684a874aSStefano Zampini #if defined(PETSC_HAVE_MPI_RGET)
7929566063dSJacob Faibussowitsch       PetscCallMPI(MPI_Rget(leafdata, 1, mine[i], ranks[i], tdp, 1, remote[i], win, &reqs[i]));
793684a874aSStefano Zampini #else
7949566063dSJacob Faibussowitsch       PetscCallMPI(MPI_Get(leafdata, 1, mine[i], ranks[i], tdp, 1, remote[i], win));
795684a874aSStefano Zampini #endif
796684a874aSStefano Zampini     } else {
7979566063dSJacob Faibussowitsch       PetscCallMPI(MPI_Get(leafdata, 1, mine[i], ranks[i], tdp, 1, remote[i], win));
798684a874aSStefano Zampini     }
79995fce210SBarry Smith   }
80095fce210SBarry Smith   PetscFunctionReturn(0);
80195fce210SBarry Smith }
80295fce210SBarry Smith 
8039371c9d4SSatish Balay PetscErrorCode PetscSFBcastEnd_Window(PetscSF sf, MPI_Datatype unit, const void *rootdata, void *leafdata, MPI_Op op) {
8045b0d146aSStefano Zampini   PetscSF_Window *w = (PetscSF_Window *)sf->data;
80595fce210SBarry Smith   MPI_Win         win;
8064b9acda6SJunchao Zhang   MPI_Request    *reqs = NULL;
80795fce210SBarry Smith 
80895fce210SBarry Smith   PetscFunctionBegin;
8099566063dSJacob Faibussowitsch   PetscCall(PetscSFFindWindow(sf, unit, rootdata, &win, &reqs));
8109566063dSJacob Faibussowitsch   if (reqs) PetscCallMPI(MPI_Waitall(sf->nranks, reqs, MPI_STATUSES_IGNORE));
811684a874aSStefano Zampini   if (w->sync == PETSCSF_WINDOW_SYNC_LOCK) {
812684a874aSStefano Zampini     PetscInt           i, nranks;
813684a874aSStefano Zampini     const PetscMPIInt *ranks;
814684a874aSStefano Zampini 
8159566063dSJacob Faibussowitsch     PetscCall(PetscSFGetRootRanks(sf, &nranks, &ranks, NULL, NULL, NULL));
816*48a46eb9SPierre Jolivet     for (i = 0; i < nranks; i++) PetscCallMPI(MPI_Win_unlock(ranks[i], win));
817684a874aSStefano Zampini   }
8189566063dSJacob Faibussowitsch   PetscCall(PetscSFRestoreWindow(sf, unit, (void *)rootdata, w->sync, PETSC_TRUE, MPI_MODE_NOSTORE | MPI_MODE_NOSUCCEED, PETSC_FALSE, &win));
81995fce210SBarry Smith   PetscFunctionReturn(0);
82095fce210SBarry Smith }
82195fce210SBarry Smith 
8229371c9d4SSatish Balay PetscErrorCode PetscSFReduceBegin_Window(PetscSF sf, MPI_Datatype unit, PetscMemType leafmtype, const void *leafdata, PetscMemType rootmtype, void *rootdata, MPI_Op op) {
82395fce210SBarry Smith   PetscSF_Window     *w = (PetscSF_Window *)sf->data;
82495fce210SBarry Smith   PetscInt            i, nranks;
82595fce210SBarry Smith   const PetscMPIInt  *ranks;
8265b0d146aSStefano Zampini   const MPI_Aint     *target_disp;
82795fce210SBarry Smith   const MPI_Datatype *mine, *remote;
82895fce210SBarry Smith   MPI_Win             win;
82995fce210SBarry Smith 
83095fce210SBarry Smith   PetscFunctionBegin;
8319566063dSJacob Faibussowitsch   PetscCall(PetscSFGetRootRanks(sf, &nranks, &ranks, NULL, NULL, NULL));
8329566063dSJacob Faibussowitsch   PetscCall(PetscSFWindowGetDataTypes(sf, unit, &mine, &remote));
8339566063dSJacob Faibussowitsch   PetscCall(PetscSFWindowOpTranslate(&op));
8349566063dSJacob Faibussowitsch   PetscCall(PetscSFGetWindow(sf, unit, rootdata, w->sync, PETSC_TRUE, MPI_MODE_NOPRECEDE, 0, 0, &target_disp, NULL, &win));
83595fce210SBarry Smith   for (i = 0; i < nranks; i++) {
8365b0d146aSStefano Zampini     MPI_Aint tdp = target_disp ? target_disp[i] : 0;
8375b0d146aSStefano Zampini 
8389566063dSJacob Faibussowitsch     if (w->sync == PETSCSF_WINDOW_SYNC_LOCK) PetscCallMPI(MPI_Win_lock(MPI_LOCK_SHARED, ranks[i], MPI_MODE_NOCHECK, win));
8399566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Accumulate((void *)leafdata, 1, mine[i], ranks[i], tdp, 1, remote[i], op, win));
8409566063dSJacob Faibussowitsch     if (w->sync == PETSCSF_WINDOW_SYNC_LOCK) PetscCallMPI(MPI_Win_unlock(ranks[i], win));
84195fce210SBarry Smith   }
84295fce210SBarry Smith   PetscFunctionReturn(0);
84395fce210SBarry Smith }
84495fce210SBarry Smith 
8459371c9d4SSatish Balay static PetscErrorCode PetscSFReduceEnd_Window(PetscSF sf, MPI_Datatype unit, const void *leafdata, void *rootdata, MPI_Op op) {
84695fce210SBarry Smith   PetscSF_Window *w = (PetscSF_Window *)sf->data;
84795fce210SBarry Smith   MPI_Win         win;
8484b9acda6SJunchao Zhang   MPI_Request    *reqs = NULL;
84995fce210SBarry Smith 
85095fce210SBarry Smith   PetscFunctionBegin;
8519566063dSJacob Faibussowitsch   PetscCall(PetscSFFindWindow(sf, unit, rootdata, &win, &reqs));
8529566063dSJacob Faibussowitsch   if (reqs) PetscCallMPI(MPI_Waitall(sf->nranks, reqs, MPI_STATUSES_IGNORE));
8539566063dSJacob Faibussowitsch   PetscCall(PetscSFRestoreWindow(sf, unit, rootdata, w->sync, PETSC_TRUE, MPI_MODE_NOSUCCEED, PETSC_TRUE, &win));
85495fce210SBarry Smith   PetscFunctionReturn(0);
85595fce210SBarry Smith }
8565b0d146aSStefano Zampini 
8579371c9d4SSatish Balay static PetscErrorCode PetscSFFetchAndOpBegin_Window(PetscSF sf, MPI_Datatype unit, PetscMemType rootmtype, void *rootdata, PetscMemType leafmtype, const void *leafdata, void *leafupdate, MPI_Op op) {
85895fce210SBarry Smith   PetscInt            i, nranks;
85995fce210SBarry Smith   const PetscMPIInt  *ranks;
86095fce210SBarry Smith   const MPI_Datatype *mine, *remote;
8615b0d146aSStefano Zampini   const MPI_Aint     *target_disp;
86295fce210SBarry Smith   MPI_Win             win;
8635b0d146aSStefano Zampini   PetscSF_Window     *w = (PetscSF_Window *)sf->data;
8645b0d146aSStefano Zampini #if !defined(PETSC_HAVE_MPI_GET_ACCUMULATE)
8655b0d146aSStefano Zampini   PetscSFWindowFlavorType oldf;
8665b0d146aSStefano Zampini #endif
86795fce210SBarry Smith 
86895fce210SBarry Smith   PetscFunctionBegin;
8699566063dSJacob Faibussowitsch   PetscCall(PetscSFGetRootRanks(sf, &nranks, &ranks, NULL, NULL, NULL));
8709566063dSJacob Faibussowitsch   PetscCall(PetscSFWindowGetDataTypes(sf, unit, &mine, &remote));
8719566063dSJacob Faibussowitsch   PetscCall(PetscSFWindowOpTranslate(&op));
8725b0d146aSStefano Zampini #if !defined(PETSC_HAVE_MPI_GET_ACCUMULATE)
8735b0d146aSStefano Zampini   /* FetchAndOp without MPI_Get_Accumulate requires locking.
8745b0d146aSStefano Zampini      we create a new window every time to not interfere with user-defined MPI_Info which may have used "no_locks"="true" */
8755b0d146aSStefano Zampini   oldf      = w->flavor;
8765b0d146aSStefano Zampini   w->flavor = PETSCSF_WINDOW_FLAVOR_CREATE;
8779566063dSJacob Faibussowitsch   PetscCall(PetscSFGetWindow(sf, unit, rootdata, PETSCSF_WINDOW_SYNC_LOCK, PETSC_FALSE, 0, 0, 0, &target_disp, NULL, &win));
8785b0d146aSStefano Zampini #else
8799566063dSJacob Faibussowitsch   PetscCall(PetscSFGetWindow(sf, unit, rootdata, w->sync, PETSC_TRUE, MPI_MODE_NOPRECEDE, 0, 0, &target_disp, NULL, &win));
8805b0d146aSStefano Zampini #endif
8815b0d146aSStefano Zampini   for (i = 0; i < nranks; i++) {
8825b0d146aSStefano Zampini     MPI_Aint tdp = target_disp ? target_disp[i] : 0;
8835b0d146aSStefano Zampini 
8845b0d146aSStefano Zampini #if !defined(PETSC_HAVE_MPI_GET_ACCUMULATE)
8859566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Win_lock(MPI_LOCK_EXCLUSIVE, ranks[i], 0, win));
8869566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Get(leafupdate, 1, mine[i], ranks[i], tdp, 1, remote[i], win));
8879566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Accumulate((void *)leafdata, 1, mine[i], ranks[i], tdp, 1, remote[i], op, win));
8889566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Win_unlock(ranks[i], win));
8895b0d146aSStefano Zampini #else
8909566063dSJacob Faibussowitsch     if (w->sync == PETSCSF_WINDOW_SYNC_LOCK) PetscCallMPI(MPI_Win_lock(MPI_LOCK_SHARED, ranks[i], 0, win));
8919566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Get_accumulate((void *)leafdata, 1, mine[i], leafupdate, 1, mine[i], ranks[i], tdp, 1, remote[i], op, win));
8929566063dSJacob Faibussowitsch     if (w->sync == PETSCSF_WINDOW_SYNC_LOCK) PetscCallMPI(MPI_Win_unlock(ranks[i], win));
8935b0d146aSStefano Zampini #endif
8945b0d146aSStefano Zampini   }
8955b0d146aSStefano Zampini #if !defined(PETSC_HAVE_MPI_GET_ACCUMULATE)
8965b0d146aSStefano Zampini   w->flavor = oldf;
8975b0d146aSStefano Zampini #endif
89895fce210SBarry Smith   PetscFunctionReturn(0);
89995fce210SBarry Smith }
90095fce210SBarry Smith 
9019371c9d4SSatish Balay static PetscErrorCode PetscSFFetchAndOpEnd_Window(PetscSF sf, MPI_Datatype unit, void *rootdata, const void *leafdata, void *leafupdate, MPI_Op op) {
90295fce210SBarry Smith   MPI_Win win;
9035b0d146aSStefano Zampini #if defined(PETSC_HAVE_MPI_GET_ACCUMULATE)
9045b0d146aSStefano Zampini   PetscSF_Window *w = (PetscSF_Window *)sf->data;
9055b0d146aSStefano Zampini #endif
9064b9acda6SJunchao Zhang   MPI_Request *reqs = NULL;
90795fce210SBarry Smith 
90895fce210SBarry Smith   PetscFunctionBegin;
9099566063dSJacob Faibussowitsch   PetscCall(PetscSFFindWindow(sf, unit, rootdata, &win, &reqs));
9109566063dSJacob Faibussowitsch   if (reqs) PetscCallMPI(MPI_Waitall(sf->nranks, reqs, MPI_STATUSES_IGNORE));
9115b0d146aSStefano Zampini #if defined(PETSC_HAVE_MPI_GET_ACCUMULATE)
9129566063dSJacob Faibussowitsch   PetscCall(PetscSFRestoreWindow(sf, unit, rootdata, w->sync, PETSC_TRUE, MPI_MODE_NOSUCCEED, PETSC_TRUE, &win));
9135b0d146aSStefano Zampini #else
9149566063dSJacob Faibussowitsch   PetscCall(PetscSFRestoreWindow(sf, unit, rootdata, PETSCSF_WINDOW_SYNC_LOCK, PETSC_FALSE, 0, PETSC_TRUE, &win));
9155b0d146aSStefano Zampini #endif
91695fce210SBarry Smith   PetscFunctionReturn(0);
91795fce210SBarry Smith }
91895fce210SBarry Smith 
9199371c9d4SSatish Balay PETSC_INTERN PetscErrorCode PetscSFCreate_Window(PetscSF sf) {
92095fce210SBarry Smith   PetscSF_Window *w = (PetscSF_Window *)sf->data;
92195fce210SBarry Smith 
92295fce210SBarry Smith   PetscFunctionBegin;
92395fce210SBarry Smith   sf->ops->SetUp           = PetscSFSetUp_Window;
92495fce210SBarry Smith   sf->ops->SetFromOptions  = PetscSFSetFromOptions_Window;
92595fce210SBarry Smith   sf->ops->Reset           = PetscSFReset_Window;
92695fce210SBarry Smith   sf->ops->Destroy         = PetscSFDestroy_Window;
92795fce210SBarry Smith   sf->ops->View            = PetscSFView_Window;
92895fce210SBarry Smith   sf->ops->Duplicate       = PetscSFDuplicate_Window;
929ad227feaSJunchao Zhang   sf->ops->BcastBegin      = PetscSFBcastBegin_Window;
930ad227feaSJunchao Zhang   sf->ops->BcastEnd        = PetscSFBcastEnd_Window;
93195fce210SBarry Smith   sf->ops->ReduceBegin     = PetscSFReduceBegin_Window;
93295fce210SBarry Smith   sf->ops->ReduceEnd       = PetscSFReduceEnd_Window;
93395fce210SBarry Smith   sf->ops->FetchAndOpBegin = PetscSFFetchAndOpBegin_Window;
93495fce210SBarry Smith   sf->ops->FetchAndOpEnd   = PetscSFFetchAndOpEnd_Window;
93595fce210SBarry Smith 
9369566063dSJacob Faibussowitsch   PetscCall(PetscNewLog(sf, &w));
93795fce210SBarry Smith   sf->data  = (void *)w;
93895fce210SBarry Smith   w->sync   = PETSCSF_WINDOW_SYNC_FENCE;
9395b0d146aSStefano Zampini   w->flavor = PETSCSF_WINDOW_FLAVOR_CREATE;
9405b0d146aSStefano Zampini   w->info   = MPI_INFO_NULL;
94195fce210SBarry Smith 
9429566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)sf, "PetscSFWindowSetSyncType_C", PetscSFWindowSetSyncType_Window));
9439566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)sf, "PetscSFWindowGetSyncType_C", PetscSFWindowGetSyncType_Window));
9449566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)sf, "PetscSFWindowSetFlavorType_C", PetscSFWindowSetFlavorType_Window));
9459566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)sf, "PetscSFWindowGetFlavorType_C", PetscSFWindowGetFlavorType_Window));
9469566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)sf, "PetscSFWindowSetInfo_C", PetscSFWindowSetInfo_Window));
9479566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)sf, "PetscSFWindowGetInfo_C", PetscSFWindowGetInfo_Window));
94895fce210SBarry Smith 
94995fce210SBarry Smith #if defined(OMPI_MAJOR_VERSION) && (OMPI_MAJOR_VERSION < 1 || (OMPI_MAJOR_VERSION == 1 && OMPI_MINOR_VERSION <= 6))
95095fce210SBarry Smith   {
95195fce210SBarry Smith     PetscBool ackbug = PETSC_FALSE;
9529566063dSJacob Faibussowitsch     PetscCall(PetscOptionsGetBool(NULL, NULL, "-acknowledge_ompi_onesided_bug", &ackbug, NULL));
95395fce210SBarry Smith     if (ackbug) {
9549566063dSJacob Faibussowitsch       PetscCall(PetscInfo(sf, "Acknowledged Open MPI bug, proceeding anyway. Expect memory corruption.\n"));
95595fce210SBarry 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");
95695fce210SBarry Smith   }
95795fce210SBarry Smith #endif
95895fce210SBarry Smith   PetscFunctionReturn(0);
95995fce210SBarry Smith }
960