xref: /petsc/src/vec/is/sf/impls/window/sfwindow.c (revision 8112c1cbf372cb53bf7c5aca994a84a6a303db4d)
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;
1397a85fb4SToby Isaac   MPI_Comm                window_comm;
1497a85fb4SToby Isaac   PetscBool               is_empty;
1597a85fb4SToby Isaac   PetscMPIInt            *wcommranks;
1695fce210SBarry Smith } PetscSF_Window;
1795fce210SBarry Smith 
1895fce210SBarry Smith struct _n_PetscSFDataLink {
1995fce210SBarry Smith   MPI_Datatype    unit;
2095fce210SBarry Smith   MPI_Datatype   *mine;
2195fce210SBarry Smith   MPI_Datatype   *remote;
2295fce210SBarry Smith   PetscSFDataLink next;
2395fce210SBarry Smith };
2495fce210SBarry Smith 
2595fce210SBarry Smith struct _n_PetscSFWinLink {
2695fce210SBarry Smith   PetscBool               inuse;
2797a85fb4SToby Isaac   MPI_Aint                bytes;
2895fce210SBarry Smith   void                   *addr;
2997a85fb4SToby Isaac   void                   *rootdata;
3097a85fb4SToby Isaac   void                   *leafdata;
3195fce210SBarry Smith   MPI_Win                 win;
32684a874aSStefano Zampini   MPI_Request            *reqs;
335b0d146aSStefano Zampini   PetscSFWindowFlavorType flavor;
345b0d146aSStefano Zampini   MPI_Aint               *dyn_target_addr;
3595fce210SBarry Smith   PetscBool               epoch;
3697a85fb4SToby Isaac   PetscBool               persistent;
3795fce210SBarry Smith   PetscSFWinLink          next;
3895fce210SBarry Smith };
3995fce210SBarry Smith 
404c8fdceaSLisandro Dalcin const char *const PetscSFWindowSyncTypes[]   = {"FENCE", "LOCK", "ACTIVE", "PetscSFWindowSyncType", "PETSCSF_WINDOW_SYNC_", NULL};
414c8fdceaSLisandro Dalcin const char *const PetscSFWindowFlavorTypes[] = {"CREATE", "DYNAMIC", "ALLOCATE", "SHARED", "PetscSFWindowFlavorType", "PETSCSF_WINDOW_FLAVOR_", NULL};
4295fce210SBarry Smith 
43820f2d46SBarry Smith /* Built-in MPI_Ops act elementwise inside MPI_Accumulate, but cannot be used with composite types inside collectives (MPI_Allreduce) */
PetscSFWindowOpTranslate(MPI_Op * op)44d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscSFWindowOpTranslate(MPI_Op *op)
45d71ae5a4SJacob Faibussowitsch {
4695fce210SBarry Smith   PetscFunctionBegin;
4795fce210SBarry Smith   if (*op == MPIU_SUM) *op = MPI_SUM;
4895fce210SBarry Smith   else if (*op == MPIU_MAX) *op = MPI_MAX;
4995fce210SBarry Smith   else if (*op == MPIU_MIN) *op = MPI_MIN;
503ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5195fce210SBarry Smith }
5295fce210SBarry Smith 
53e33f79d8SJacob Faibussowitsch /*
5495fce210SBarry Smith    PetscSFWindowGetDataTypes - gets composite local and remote data types for each rank
5595fce210SBarry Smith 
5695fce210SBarry Smith    Not Collective
5795fce210SBarry Smith 
584165533cSJose E. Roman    Input Parameters:
59cab54364SBarry Smith +  sf - star forest of type `PETSCSFWINDOW`
6095fce210SBarry Smith -  unit - data type for each node
6195fce210SBarry Smith 
624165533cSJose E. Roman    Output Parameters:
6395fce210SBarry Smith +  localtypes - types describing part of local leaf buffer referencing each remote rank
6495fce210SBarry Smith -  remotetypes - types describing part of remote root buffer referenced for each remote rank
6595fce210SBarry Smith 
6695fce210SBarry Smith    Level: developer
6795fce210SBarry Smith 
68cab54364SBarry Smith .seealso: `PetscSF`, `PETSCSFWINDOW`, `PetscSFSetGraph()`, `PetscSFView()`
6995fce210SBarry Smith @*/
PetscSFWindowGetDataTypes(PetscSF sf,MPI_Datatype unit,const MPI_Datatype ** localtypes,const MPI_Datatype ** remotetypes)70d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscSFWindowGetDataTypes(PetscSF sf, MPI_Datatype unit, const MPI_Datatype **localtypes, const MPI_Datatype **remotetypes)
71d71ae5a4SJacob Faibussowitsch {
7295fce210SBarry Smith   PetscSF_Window *w = (PetscSF_Window *)sf->data;
7395fce210SBarry Smith   PetscSFDataLink link;
746497c311SBarry Smith   PetscMPIInt     nranks;
756497c311SBarry Smith   const PetscInt *roffset;
7695fce210SBarry Smith 
7795fce210SBarry Smith   PetscFunctionBegin;
7895fce210SBarry Smith   /* Look for types in cache */
7995fce210SBarry Smith   for (link = w->link; link; link = link->next) {
8095fce210SBarry Smith     PetscBool match;
816497c311SBarry Smith 
829566063dSJacob Faibussowitsch     PetscCall(MPIPetsc_Type_compare(unit, link->unit, &match));
8395fce210SBarry Smith     if (match) {
8495fce210SBarry Smith       *localtypes  = link->mine;
8595fce210SBarry Smith       *remotetypes = link->remote;
863ba16761SJacob Faibussowitsch       PetscFunctionReturn(PETSC_SUCCESS);
8795fce210SBarry Smith     }
8895fce210SBarry Smith   }
8995fce210SBarry Smith 
9095fce210SBarry Smith   /* Create new composite types for each send rank */
916497c311SBarry Smith   PetscCall(PetscSFGetRootRanks(sf, &nranks, NULL, &roffset, NULL, NULL));
929566063dSJacob Faibussowitsch   PetscCall(PetscNew(&link));
939566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Type_dup(unit, &link->unit));
949566063dSJacob Faibussowitsch   PetscCall(PetscMalloc2(nranks, &link->mine, nranks, &link->remote));
956497c311SBarry Smith   for (PetscMPIInt i = 0; i < nranks; i++) {
966497c311SBarry Smith     PetscMPIInt  rcount;
9795fce210SBarry Smith     PetscMPIInt *rmine, *rremote;
986497c311SBarry Smith 
996497c311SBarry Smith     PetscCall(PetscMPIIntCast(roffset[i + 1] - roffset[i], &rcount));
10095fce210SBarry Smith #if !defined(PETSC_USE_64BIT_INDICES)
10195fce210SBarry Smith     rmine   = sf->rmine + sf->roffset[i];
10295fce210SBarry Smith     rremote = sf->rremote + sf->roffset[i];
10395fce210SBarry Smith #else
1049566063dSJacob Faibussowitsch     PetscCall(PetscMalloc2(rcount, &rmine, rcount, &rremote));
1056497c311SBarry Smith     for (PetscInt j = 0; j < rcount; j++) {
1066497c311SBarry Smith       PetscCall(PetscMPIIntCast(sf->rmine[sf->roffset[i] + j], &rmine[j]));
1076497c311SBarry Smith       PetscCall(PetscMPIIntCast(sf->rremote[sf->roffset[i] + j], &rremote[j]));
10895fce210SBarry Smith     }
10995fce210SBarry Smith #endif
1105b0d146aSStefano Zampini 
1119566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Type_create_indexed_block(rcount, 1, rmine, link->unit, &link->mine[i]));
1129566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Type_create_indexed_block(rcount, 1, rremote, link->unit, &link->remote[i]));
11395fce210SBarry Smith #if defined(PETSC_USE_64BIT_INDICES)
1149566063dSJacob Faibussowitsch     PetscCall(PetscFree2(rmine, rremote));
11595fce210SBarry Smith #endif
1169566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Type_commit(&link->mine[i]));
1179566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Type_commit(&link->remote[i]));
11895fce210SBarry Smith   }
11995fce210SBarry Smith   link->next = w->link;
12095fce210SBarry Smith   w->link    = link;
12195fce210SBarry Smith 
12295fce210SBarry Smith   *localtypes  = link->mine;
12395fce210SBarry Smith   *remotetypes = link->remote;
1243ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
12595fce210SBarry Smith }
12695fce210SBarry Smith 
127cc4c1da9SBarry Smith /*@
128cab54364SBarry Smith   PetscSFWindowSetFlavorType - Set flavor type for `MPI_Win` creation
1295b0d146aSStefano Zampini 
1305b0d146aSStefano Zampini   Logically Collective
1315b0d146aSStefano Zampini 
1324165533cSJose E. Roman   Input Parameters:
133cab54364SBarry Smith + sf     - star forest for communication of type `PETSCSFWINDOW`
1345b0d146aSStefano Zampini - flavor - flavor type
1355b0d146aSStefano Zampini 
1365b0d146aSStefano Zampini   Options Database Key:
137cab54364SBarry Smith . -sf_window_flavor <flavor> - sets the flavor type CREATE, DYNAMIC, ALLOCATE or SHARED (see `PetscSFWindowFlavorType`)
1385b0d146aSStefano Zampini 
1395b0d146aSStefano Zampini   Level: advanced
1405b0d146aSStefano Zampini 
141cab54364SBarry Smith   Notes:
142e33f79d8SJacob Faibussowitsch   Windows reuse follows these rules\:
143cab54364SBarry Smith .vb
1445b0d146aSStefano Zampini      PETSCSF_WINDOW_FLAVOR_CREATE: creates a new window every time, uses MPI_Win_create
1455b0d146aSStefano Zampini 
1465b0d146aSStefano 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.
14797a85fb4SToby Isaac        PetscSFRegisterPersistent(sf,rootdata1,leafdata);
1485b0d146aSStefano Zampini        for i=1 to K
14997a85fb4SToby Isaac          PetscSFOperationBegin(sf,rootdata1,leafdata);
15097a85fb4SToby Isaac          PetscSFOperationEnd(sf,rootdata1,leafdata);
1515b0d146aSStefano Zampini          ...
15297a85fb4SToby Isaac          PetscSFOperationBegin(sf,rootdata1,leafdata);
15397a85fb4SToby Isaac          PetscSFOperationEnd(sf,rootdata1,leafdata);
1545b0d146aSStefano Zampini        endfor
15597a85fb4SToby Isaac        PetscSFDeregisterPersistent(sf,rootdata1,leafdata);
15697a85fb4SToby Isaac 
1575b0d146aSStefano Zampini        The following pattern will instead raise an error
15897a85fb4SToby Isaac          PetscSFOperationBegin(sf,rootdata1,leafdata);
15997a85fb4SToby Isaac          PetscSFOperationEnd(sf,rootdata1,leafdata);
16097a85fb4SToby Isaac          PetscSFOperationBegin(sf,rank ? rootdata1 : rootdata2,leafdata);
16197a85fb4SToby Isaac          PetscSFOperationEnd(sf,rank ? rootdata1 : rootdata2,leafdata);
1625b0d146aSStefano Zampini 
1635b0d146aSStefano Zampini      PETSCSF_WINDOW_FLAVOR_ALLOCATE: uses MPI_Win_allocate, reuses any pre-existing window which fits the data and it is not in use
1645b0d146aSStefano Zampini 
1655b0d146aSStefano Zampini      PETSCSF_WINDOW_FLAVOR_SHARED: uses MPI_Win_allocate_shared, reusage policy as for PETSCSF_WINDOW_FLAVOR_ALLOCATE
166cab54364SBarry Smith .ve
1675b0d146aSStefano Zampini 
168cab54364SBarry Smith .seealso: `PetscSF`, `PETSCSFWINDOW`, `PetscSFSetFromOptions()`, `PetscSFWindowGetFlavorType()`
1695b0d146aSStefano Zampini @*/
PetscSFWindowSetFlavorType(PetscSF sf,PetscSFWindowFlavorType flavor)170d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscSFWindowSetFlavorType(PetscSF sf, PetscSFWindowFlavorType flavor)
171d71ae5a4SJacob Faibussowitsch {
1725b0d146aSStefano Zampini   PetscFunctionBegin;
1735b0d146aSStefano Zampini   PetscValidHeaderSpecific(sf, PETSCSF_CLASSID, 1);
1745b0d146aSStefano Zampini   PetscValidLogicalCollectiveEnum(sf, flavor, 2);
175cac4c232SBarry Smith   PetscTryMethod(sf, "PetscSFWindowSetFlavorType_C", (PetscSF, PetscSFWindowFlavorType), (sf, flavor));
1763ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1775b0d146aSStefano Zampini }
1785b0d146aSStefano Zampini 
PetscSFWindowSetFlavorType_Window(PetscSF sf,PetscSFWindowFlavorType flavor)179d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscSFWindowSetFlavorType_Window(PetscSF sf, PetscSFWindowFlavorType flavor)
180d71ae5a4SJacob Faibussowitsch {
1815b0d146aSStefano Zampini   PetscSF_Window *w = (PetscSF_Window *)sf->data;
1825b0d146aSStefano Zampini 
1835b0d146aSStefano Zampini   PetscFunctionBegin;
1845b0d146aSStefano Zampini   w->flavor = flavor;
1853ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1865b0d146aSStefano Zampini }
1875b0d146aSStefano Zampini 
188cc4c1da9SBarry Smith /*@
189cab54364SBarry Smith   PetscSFWindowGetFlavorType - Get  `PETSCSFWINDOW` flavor type for `PetscSF` communication
1905b0d146aSStefano Zampini 
1915b0d146aSStefano Zampini   Logically Collective
1925b0d146aSStefano Zampini 
1934165533cSJose E. Roman   Input Parameter:
194cab54364SBarry Smith . sf - star forest for communication of type `PETSCSFWINDOW`
1955b0d146aSStefano Zampini 
1964165533cSJose E. Roman   Output Parameter:
1975b0d146aSStefano Zampini . flavor - flavor type
1985b0d146aSStefano Zampini 
1995b0d146aSStefano Zampini   Level: advanced
2005b0d146aSStefano Zampini 
201cab54364SBarry Smith .seealso: `PetscSF`, `PETSCSFWINDOW`, `PetscSFSetFromOptions()`, `PetscSFWindowSetFlavorType()`
2025b0d146aSStefano Zampini @*/
PetscSFWindowGetFlavorType(PetscSF sf,PetscSFWindowFlavorType * flavor)203d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscSFWindowGetFlavorType(PetscSF sf, PetscSFWindowFlavorType *flavor)
204d71ae5a4SJacob Faibussowitsch {
2055b0d146aSStefano Zampini   PetscFunctionBegin;
2065b0d146aSStefano Zampini   PetscValidHeaderSpecific(sf, PETSCSF_CLASSID, 1);
2074f572ea9SToby Isaac   PetscAssertPointer(flavor, 2);
208cac4c232SBarry Smith   PetscUseMethod(sf, "PetscSFWindowGetFlavorType_C", (PetscSF, PetscSFWindowFlavorType *), (sf, flavor));
2093ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2105b0d146aSStefano Zampini }
2115b0d146aSStefano Zampini 
PetscSFWindowGetFlavorType_Window(PetscSF sf,PetscSFWindowFlavorType * flavor)212d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscSFWindowGetFlavorType_Window(PetscSF sf, PetscSFWindowFlavorType *flavor)
213d71ae5a4SJacob Faibussowitsch {
2145b0d146aSStefano Zampini   PetscSF_Window *w = (PetscSF_Window *)sf->data;
2155b0d146aSStefano Zampini 
2165b0d146aSStefano Zampini   PetscFunctionBegin;
2175b0d146aSStefano Zampini   *flavor = w->flavor;
2183ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2195b0d146aSStefano Zampini }
2205b0d146aSStefano Zampini 
221cc4c1da9SBarry Smith /*@
222cab54364SBarry Smith   PetscSFWindowSetSyncType - Set synchronization type for `PetscSF` communication of type  `PETSCSFWINDOW`
22395fce210SBarry Smith 
22495fce210SBarry Smith   Logically Collective
22595fce210SBarry Smith 
2264165533cSJose E. Roman   Input Parameters:
22795fce210SBarry Smith + sf   - star forest for communication
22895fce210SBarry Smith - sync - synchronization type
22995fce210SBarry Smith 
23095fce210SBarry Smith   Options Database Key:
231cab54364SBarry Smith . -sf_window_sync <sync> - sets the synchronization type FENCE, LOCK, or ACTIVE (see `PetscSFWindowSyncType`)
23295fce210SBarry Smith 
23395fce210SBarry Smith   Level: advanced
23495fce210SBarry Smith 
235cab54364SBarry Smith .seealso: `PetscSF`, `PETSCSFWINDOW`, `PetscSFSetFromOptions()`, `PetscSFWindowGetSyncType()`, `PetscSFWindowSyncType`
23695fce210SBarry Smith @*/
PetscSFWindowSetSyncType(PetscSF sf,PetscSFWindowSyncType sync)237d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscSFWindowSetSyncType(PetscSF sf, PetscSFWindowSyncType sync)
238d71ae5a4SJacob Faibussowitsch {
23995fce210SBarry Smith   PetscFunctionBegin;
24095fce210SBarry Smith   PetscValidHeaderSpecific(sf, PETSCSF_CLASSID, 1);
24195fce210SBarry Smith   PetscValidLogicalCollectiveEnum(sf, sync, 2);
242cac4c232SBarry Smith   PetscTryMethod(sf, "PetscSFWindowSetSyncType_C", (PetscSF, PetscSFWindowSyncType), (sf, sync));
2433ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
24495fce210SBarry Smith }
24595fce210SBarry Smith 
PetscSFWindowSetSyncType_Window(PetscSF sf,PetscSFWindowSyncType sync)246d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscSFWindowSetSyncType_Window(PetscSF sf, PetscSFWindowSyncType sync)
247d71ae5a4SJacob Faibussowitsch {
24895fce210SBarry Smith   PetscSF_Window *w = (PetscSF_Window *)sf->data;
24995fce210SBarry Smith 
25095fce210SBarry Smith   PetscFunctionBegin;
25195fce210SBarry Smith   w->sync = sync;
2523ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
25395fce210SBarry Smith }
25495fce210SBarry Smith 
255cc4c1da9SBarry Smith /*@
256cab54364SBarry Smith   PetscSFWindowGetSyncType - Get synchronization type for `PetscSF` communication of type `PETSCSFWINDOW`
25795fce210SBarry Smith 
25895fce210SBarry Smith   Logically Collective
25995fce210SBarry Smith 
2604165533cSJose E. Roman   Input Parameter:
26195fce210SBarry Smith . sf - star forest for communication
26295fce210SBarry Smith 
2634165533cSJose E. Roman   Output Parameter:
26495fce210SBarry Smith . sync - synchronization type
26595fce210SBarry Smith 
26695fce210SBarry Smith   Level: advanced
26795fce210SBarry Smith 
268cab54364SBarry Smith .seealso: `PetscSF`, `PETSCSFWINDOW`, `PetscSFSetFromOptions()`, `PetscSFWindowSetSyncType()`, `PetscSFWindowSyncType`
26995fce210SBarry Smith @*/
PetscSFWindowGetSyncType(PetscSF sf,PetscSFWindowSyncType * sync)270d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscSFWindowGetSyncType(PetscSF sf, PetscSFWindowSyncType *sync)
271d71ae5a4SJacob Faibussowitsch {
27295fce210SBarry Smith   PetscFunctionBegin;
27395fce210SBarry Smith   PetscValidHeaderSpecific(sf, PETSCSF_CLASSID, 1);
2744f572ea9SToby Isaac   PetscAssertPointer(sync, 2);
275cac4c232SBarry Smith   PetscUseMethod(sf, "PetscSFWindowGetSyncType_C", (PetscSF, PetscSFWindowSyncType *), (sf, sync));
2763ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
27795fce210SBarry Smith }
27895fce210SBarry Smith 
PetscSFWindowGetSyncType_Window(PetscSF sf,PetscSFWindowSyncType * sync)279d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscSFWindowGetSyncType_Window(PetscSF sf, PetscSFWindowSyncType *sync)
280d71ae5a4SJacob Faibussowitsch {
28195fce210SBarry Smith   PetscSF_Window *w = (PetscSF_Window *)sf->data;
28295fce210SBarry Smith 
28395fce210SBarry Smith   PetscFunctionBegin;
28495fce210SBarry Smith   *sync = w->sync;
2853ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
28695fce210SBarry Smith }
28795fce210SBarry Smith 
28895fce210SBarry Smith /*@C
289cab54364SBarry Smith   PetscSFWindowSetInfo - Set the `MPI_Info` handle that will be used for subsequent windows allocation
2905b0d146aSStefano Zampini 
2915b0d146aSStefano Zampini   Logically Collective
2925b0d146aSStefano Zampini 
2934165533cSJose E. Roman   Input Parameters:
2945b0d146aSStefano Zampini + sf   - star forest for communication
295cab54364SBarry Smith - info - `MPI_Info` handle
2965b0d146aSStefano Zampini 
2975b0d146aSStefano Zampini   Level: advanced
2985b0d146aSStefano Zampini 
299cab54364SBarry Smith   Note:
300cab54364SBarry Smith   The info handle is duplicated with a call to `MPI_Info_dup()` unless info = `MPI_INFO_NULL`.
3015b0d146aSStefano Zampini 
302cab54364SBarry Smith .seealso: `PetscSF`, `PETSCSFWINDOW`, `PetscSFSetFromOptions()`, `PetscSFWindowGetInfo()`
3035b0d146aSStefano Zampini @*/
PetscSFWindowSetInfo(PetscSF sf,MPI_Info info)304d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscSFWindowSetInfo(PetscSF sf, MPI_Info info)
305d71ae5a4SJacob Faibussowitsch {
3065b0d146aSStefano Zampini   PetscFunctionBegin;
3075b0d146aSStefano Zampini   PetscValidHeaderSpecific(sf, PETSCSF_CLASSID, 1);
308cac4c232SBarry Smith   PetscTryMethod(sf, "PetscSFWindowSetInfo_C", (PetscSF, MPI_Info), (sf, info));
3093ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3105b0d146aSStefano Zampini }
3115b0d146aSStefano Zampini 
PetscSFWindowSetInfo_Window(PetscSF sf,MPI_Info info)312d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscSFWindowSetInfo_Window(PetscSF sf, MPI_Info info)
313d71ae5a4SJacob Faibussowitsch {
3145b0d146aSStefano Zampini   PetscSF_Window *w = (PetscSF_Window *)sf->data;
3155b0d146aSStefano Zampini 
3165b0d146aSStefano Zampini   PetscFunctionBegin;
31748a46eb9SPierre Jolivet   if (w->info != MPI_INFO_NULL) PetscCallMPI(MPI_Info_free(&w->info));
31848a46eb9SPierre Jolivet   if (info != MPI_INFO_NULL) PetscCallMPI(MPI_Info_dup(info, &w->info));
3193ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3205b0d146aSStefano Zampini }
3215b0d146aSStefano Zampini 
3225b0d146aSStefano Zampini /*@C
323cab54364SBarry Smith   PetscSFWindowGetInfo - Get the `MPI_Info` handle used for windows allocation
3245b0d146aSStefano Zampini 
3255b0d146aSStefano Zampini   Logically Collective
3265b0d146aSStefano Zampini 
3274165533cSJose E. Roman   Input Parameter:
3285b0d146aSStefano Zampini . sf - star forest for communication
3295b0d146aSStefano Zampini 
3304165533cSJose E. Roman   Output Parameter:
331cab54364SBarry Smith . info - `MPI_Info` handle
3325b0d146aSStefano Zampini 
3335b0d146aSStefano Zampini   Level: advanced
3345b0d146aSStefano Zampini 
335cab54364SBarry Smith   Note:
336cab54364SBarry Smith   If `PetscSFWindowSetInfo()` has not be called, this returns `MPI_INFO_NULL`
3375b0d146aSStefano Zampini 
338cab54364SBarry Smith .seealso: `PetscSF`, `PETSCSFWINDOW`, `PetscSFSetFromOptions()`, `PetscSFWindowSetInfo()`
3395b0d146aSStefano Zampini @*/
PetscSFWindowGetInfo(PetscSF sf,MPI_Info * info)340d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscSFWindowGetInfo(PetscSF sf, MPI_Info *info)
341d71ae5a4SJacob Faibussowitsch {
3425b0d146aSStefano Zampini   PetscFunctionBegin;
3435b0d146aSStefano Zampini   PetscValidHeaderSpecific(sf, PETSCSF_CLASSID, 1);
3444f572ea9SToby Isaac   PetscAssertPointer(info, 2);
345cac4c232SBarry Smith   PetscUseMethod(sf, "PetscSFWindowGetInfo_C", (PetscSF, MPI_Info *), (sf, info));
3463ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3475b0d146aSStefano Zampini }
3485b0d146aSStefano Zampini 
PetscSFWindowGetInfo_Window(PetscSF sf,MPI_Info * info)349d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscSFWindowGetInfo_Window(PetscSF sf, MPI_Info *info)
350d71ae5a4SJacob Faibussowitsch {
3515b0d146aSStefano Zampini   PetscSF_Window *w = (PetscSF_Window *)sf->data;
3525b0d146aSStefano Zampini 
3535b0d146aSStefano Zampini   PetscFunctionBegin;
3545b0d146aSStefano Zampini   *info = w->info;
3553ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3565b0d146aSStefano Zampini }
3575b0d146aSStefano Zampini 
PetscSFWindowCreateDynamicSF(PetscSF sf,PetscSF * dynsf)35897a85fb4SToby Isaac static PetscErrorCode PetscSFWindowCreateDynamicSF(PetscSF sf, PetscSF *dynsf)
35997a85fb4SToby Isaac {
36097a85fb4SToby Isaac   PetscSFNode *remotes;
36197a85fb4SToby Isaac 
36297a85fb4SToby Isaac   PetscFunctionBegin;
36397a85fb4SToby Isaac   PetscCall(PetscMalloc1(sf->nranks, &remotes));
36497a85fb4SToby Isaac   for (PetscInt i = 0; i < sf->nranks; i++) {
36597a85fb4SToby Isaac     remotes[i].rank  = sf->ranks[i];
36697a85fb4SToby Isaac     remotes[i].index = 0;
36797a85fb4SToby Isaac   }
36897a85fb4SToby Isaac   PetscCall(PetscSFDuplicate(sf, PETSCSF_DUPLICATE_RANKS, dynsf));
36997a85fb4SToby Isaac   PetscCall(PetscSFSetType(*dynsf, PETSCSFBASIC)); /* break recursion */
37097a85fb4SToby Isaac   PetscCall(PetscSFSetGraph(*dynsf, 1, sf->nranks, NULL, PETSC_OWN_POINTER, remotes, PETSC_OWN_POINTER));
37197a85fb4SToby Isaac   PetscFunctionReturn(PETSC_SUCCESS);
37297a85fb4SToby Isaac }
37397a85fb4SToby Isaac 
PetscSFWindowAttach(PetscSF sf,PetscSFWinLink link,void * rootdata,size_t wsize)37497a85fb4SToby Isaac static PetscErrorCode PetscSFWindowAttach(PetscSF sf, PetscSFWinLink link, void *rootdata, size_t wsize)
37597a85fb4SToby Isaac {
37697a85fb4SToby Isaac   PetscFunctionBegin;
37797a85fb4SToby Isaac #if defined(PETSC_HAVE_MPI_FEATURE_DYNAMIC_WINDOW)
37897a85fb4SToby Isaac   {
37997a85fb4SToby Isaac     PetscSF_Window *w = (PetscSF_Window *)sf->data;
38097a85fb4SToby Isaac     MPI_Comm        wcomm;
38197a85fb4SToby Isaac     MPI_Aint        winaddr;
38297a85fb4SToby Isaac     void           *addr = rootdata;
3836497c311SBarry Smith     PetscMPIInt     nranks;
38497a85fb4SToby Isaac     // some Open MPI versions do not support MPI_Win_attach(win,NULL,0);
38597a85fb4SToby Isaac     wcomm = w->window_comm;
38697a85fb4SToby Isaac     if (addr != NULL) PetscCallMPI(MPI_Win_attach(link->win, addr, wsize));
38797a85fb4SToby Isaac     link->addr = addr;
38897a85fb4SToby Isaac     PetscCheck(w->dynsf, wcomm, PETSC_ERR_ORDER, "Must call PetscSFSetUp()");
38997a85fb4SToby Isaac     PetscCall(PetscSFGetRootRanks(w->dynsf, &nranks, NULL, NULL, NULL, NULL));
39097a85fb4SToby Isaac     PetscCallMPI(MPI_Get_address(addr, &winaddr));
39197a85fb4SToby Isaac     if (!link->dyn_target_addr) PetscCall(PetscMalloc1(nranks, &link->dyn_target_addr));
39297a85fb4SToby Isaac     PetscCall(PetscSFBcastBegin(w->dynsf, MPI_AINT, &winaddr, link->dyn_target_addr, MPI_REPLACE));
39397a85fb4SToby Isaac     PetscCall(PetscSFBcastEnd(w->dynsf, MPI_AINT, &winaddr, link->dyn_target_addr, MPI_REPLACE));
39497a85fb4SToby Isaac   }
39597a85fb4SToby Isaac #else
39697a85fb4SToby Isaac   SETERRQ(PETSC_COMM_SELF, PETSC_ERR_PLIB, "dynamic windows not supported");
39797a85fb4SToby Isaac #endif
39897a85fb4SToby Isaac   PetscFunctionReturn(PETSC_SUCCESS);
39997a85fb4SToby Isaac }
40097a85fb4SToby Isaac 
4015b0d146aSStefano Zampini /*
40295fce210SBarry Smith    PetscSFGetWindow - Get a window for use with a given data type
40395fce210SBarry Smith 
404c3339decSBarry Smith    Collective
40595fce210SBarry Smith 
4064165533cSJose E. Roman    Input Parameters:
40795fce210SBarry Smith +  sf - star forest
40895fce210SBarry Smith .  unit - data type
40997a85fb4SToby Isaac .  rootdata - array to be sent
41097a85fb4SToby Isaac .  leafdata - only used to help uniquely identify windows
411cab54364SBarry Smith .  sync - type of synchronization `PetscSFWindowSyncType`
412cab54364SBarry Smith .  epoch - `PETSC_TRUE` to acquire the window and start an epoch, `PETSC_FALSE` to just acquire the window
413cab54364SBarry Smith .  fenceassert - assert parameter for call to `MPI_Win_fence()`, if sync == `PETSCSF_WINDOW_SYNC_FENCE`
414cab54364SBarry Smith .  postassert - assert parameter for call to `MPI_Win_post()`, if sync == `PETSCSF_WINDOW_SYNC_ACTIVE`
415cab54364SBarry Smith -  startassert - assert parameter for call to `MPI_Win_start()`, if sync == `PETSCSF_WINDOW_SYNC_ACTIVE`
41695fce210SBarry Smith 
4174165533cSJose E. Roman    Output Parameters:
418cab54364SBarry Smith +  target_disp - target_disp argument for RMA calls (significative for `PETSCSF_WINDOW_FLAVOR_DYNAMIC` only)
419cab54364SBarry Smith +  reqs - array of requests (significative for sync == `PETSCSF_WINDOW_SYNC_LOCK` only)
420684a874aSStefano Zampini -  win - window
42195fce210SBarry Smith 
42295fce210SBarry Smith    Level: developer
423cab54364SBarry Smith 
424cab54364SBarry Smith .seealso: `PetscSF`, `PETSCSFWINDOW`, `PetscSFGetRootRanks()`, `PetscSFWindowGetDataTypes()`
4255b0d146aSStefano Zampini */
42697a85fb4SToby Isaac 
PetscSFGetWindow(PetscSF sf,MPI_Datatype unit,void * rootdata,void * leafdata,PetscSFWindowSyncType sync,PetscBool epoch,PetscMPIInt fenceassert,PetscMPIInt postassert,PetscMPIInt startassert,const MPI_Aint ** target_disp,MPI_Request ** reqs,MPI_Win * win)42797a85fb4SToby Isaac static PetscErrorCode PetscSFGetWindow(PetscSF sf, MPI_Datatype unit, void *rootdata, void *leafdata, PetscSFWindowSyncType sync, PetscBool epoch, PetscMPIInt fenceassert, PetscMPIInt postassert, PetscMPIInt startassert, const MPI_Aint **target_disp, MPI_Request **reqs, MPI_Win *win)
428d71ae5a4SJacob Faibussowitsch {
42995fce210SBarry Smith   PetscSF_Window *w = (PetscSF_Window *)sf->data;
43097a85fb4SToby Isaac   MPI_Aint        bytes;
43195fce210SBarry Smith   PetscSFWinLink  link;
4325b0d146aSStefano Zampini   PetscBool       reuse = PETSC_FALSE, update = PETSC_FALSE;
4335b0d146aSStefano Zampini   MPI_Aint        wsize;
43497a85fb4SToby Isaac   MPI_Comm        wcomm;
43597a85fb4SToby Isaac   PetscBool       is_empty;
43695fce210SBarry Smith 
43795fce210SBarry Smith   PetscFunctionBegin;
43897a85fb4SToby Isaac   PetscCall(PetscSFGetDatatypeSize_Internal(PetscObjectComm((PetscObject)sf), unit, &bytes));
43997a85fb4SToby Isaac   wsize    = (MPI_Aint)(bytes * sf->nroots);
44097a85fb4SToby Isaac   wcomm    = w->window_comm;
44197a85fb4SToby Isaac   is_empty = w->is_empty;
44297a85fb4SToby Isaac   if (is_empty) {
44397a85fb4SToby Isaac     if (target_disp) *target_disp = NULL;
44497a85fb4SToby Isaac     if (reqs) *reqs = NULL;
44597a85fb4SToby Isaac     *win = MPI_WIN_NULL;
44697a85fb4SToby Isaac     PetscFunctionReturn(PETSC_SUCCESS);
44797a85fb4SToby Isaac   }
4485b0d146aSStefano Zampini   if (w->flavor != PETSCSF_WINDOW_FLAVOR_CREATE) reuse = PETSC_TRUE;
44997a85fb4SToby Isaac   if (PetscDefined(HAVE_MPI_FEATURE_DYNAMIC_WINDOW) && w->flavor == PETSCSF_WINDOW_FLAVOR_DYNAMIC) {
45097a85fb4SToby Isaac     // first search for a persistent window
4515b0d146aSStefano Zampini     for (link = w->wins; reuse && link; link = link->next) {
45297a85fb4SToby Isaac       PetscBool match;
45397a85fb4SToby Isaac 
45497a85fb4SToby Isaac       if (!link->persistent) continue;
45597a85fb4SToby Isaac       match = (link->flavor == w->flavor && link->rootdata == rootdata && link->leafdata == leafdata) ? PETSC_TRUE : PETSC_FALSE;
45676bd3646SJed Brown       if (PetscDefined(USE_DEBUG)) {
45797a85fb4SToby Isaac         PetscInt matches[2];
45897a85fb4SToby Isaac         PetscInt all_matches[2];
45997a85fb4SToby Isaac 
46097a85fb4SToby Isaac         matches[0] = match ? 1 : 0;
46197a85fb4SToby Isaac         matches[1] = match ? -1 : 0;
46297a85fb4SToby Isaac         PetscCallMPI(MPIU_Allreduce(matches, all_matches, 2, MPIU_INT, MPI_MAX, wcomm));
46397a85fb4SToby Isaac         all_matches[1] = -all_matches[1];
46497a85fb4SToby Isaac         PetscCheck(all_matches[0] == all_matches[1], wcomm, PETSC_ERR_ARG_INCOMP,
46597a85fb4SToby Isaac                    "Inconsistent use across MPI processes of persistent leaf and root data registered with PetscSFRegisterPersistent().\n"
46697a85fb4SToby Isaac                    "Either the persistent data was changed on a subset of processes (which is not allowed),\n"
46797a85fb4SToby Isaac                    "or persistent data was not deregistered with PetscSFDeregisterPersistent() before being deallocated");
46876bd3646SJed Brown       }
46997a85fb4SToby Isaac       if (match) {
47097a85fb4SToby Isaac         PetscCheck(!link->inuse, wcomm, PETSC_ERR_ARG_WRONGSTATE, "Communication already in progress on persistent root and leaf data");
47197a85fb4SToby Isaac         PetscCheck(!epoch || !link->epoch, wcomm, PETSC_ERR_ARG_WRONGSTATE, "Communication epoch already open for window");
47297a85fb4SToby Isaac         PetscCheck(bytes == link->bytes, wcomm, PETSC_ERR_ARG_WRONGSTATE, "Wrong data type for persistent root and leaf data");
4735b0d146aSStefano Zampini         *win = link->win;
47497a85fb4SToby Isaac         goto found;
47597a85fb4SToby Isaac       }
47697a85fb4SToby Isaac     }
47797a85fb4SToby Isaac   }
47897a85fb4SToby Isaac   for (link = w->wins; reuse && link; link = link->next) {
47997a85fb4SToby Isaac     if (w->flavor != link->flavor) continue;
48097a85fb4SToby Isaac     /* an existing window can be used (1) if it is not in use, (2) if we are
48197a85fb4SToby Isaac        not asking to start an epoch or it does not have an already started
48297a85fb4SToby Isaac        epoch, and (3) if it is the right size */
48397a85fb4SToby Isaac     if (!link->inuse && (!epoch || !link->epoch) && bytes == (MPI_Aint)link->bytes) {
48497a85fb4SToby Isaac       if (w->flavor == PETSCSF_WINDOW_FLAVOR_DYNAMIC) {
48597a85fb4SToby Isaac         PetscCall(PetscSFWindowAttach(sf, link, rootdata, wsize));
48697a85fb4SToby Isaac       } else {
48797a85fb4SToby Isaac         update = PETSC_TRUE;
48897a85fb4SToby Isaac       }
48997a85fb4SToby Isaac       link->rootdata = rootdata;
49097a85fb4SToby Isaac       link->leafdata = leafdata;
49197a85fb4SToby Isaac       PetscCall(PetscInfo(sf, "Reusing window %" PETSC_INTPTR_T_FMT " of flavor %d for comm %" PETSC_INTPTR_T_FMT "\n", (PETSC_INTPTR_T)link->win, link->flavor, (PETSC_INTPTR_T)wcomm));
49297a85fb4SToby Isaac       *win = link->win;
4935b0d146aSStefano Zampini       goto found;
4945b0d146aSStefano Zampini     }
4955b0d146aSStefano Zampini   }
4965b0d146aSStefano Zampini 
4979566063dSJacob Faibussowitsch   PetscCall(PetscNew(&link));
49895fce210SBarry Smith   link->bytes           = bytes;
49995fce210SBarry Smith   link->next            = w->wins;
5005b0d146aSStefano Zampini   link->flavor          = w->flavor;
5015b0d146aSStefano Zampini   link->dyn_target_addr = NULL;
502684a874aSStefano Zampini   link->reqs            = NULL;
50395fce210SBarry Smith   w->wins               = link;
50497a85fb4SToby Isaac   link->rootdata        = rootdata;
50597a85fb4SToby Isaac   link->leafdata        = leafdata;
506684a874aSStefano Zampini   if (sync == PETSCSF_WINDOW_SYNC_LOCK) {
5079566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(sf->nranks, &link->reqs));
5086497c311SBarry Smith     for (PetscMPIInt i = 0; i < sf->nranks; i++) link->reqs[i] = MPI_REQUEST_NULL;
509684a874aSStefano Zampini   }
5105b0d146aSStefano Zampini   switch (w->flavor) {
5115b0d146aSStefano Zampini   case PETSCSF_WINDOW_FLAVOR_CREATE:
51297a85fb4SToby Isaac     PetscCallMPI(MPI_Win_create(rootdata, wsize, (PetscMPIInt)bytes, w->info, wcomm, &link->win));
51397a85fb4SToby Isaac     link->addr = rootdata;
5145b0d146aSStefano Zampini     break;
515d547623eSJunchao Zhang #if defined(PETSC_HAVE_MPI_FEATURE_DYNAMIC_WINDOW)
516d71ae5a4SJacob Faibussowitsch   case PETSCSF_WINDOW_FLAVOR_DYNAMIC:
51797a85fb4SToby Isaac     PetscCallMPI(MPI_Win_create_dynamic(w->info, wcomm, &link->win));
51897a85fb4SToby Isaac     PetscCall(PetscSFWindowAttach(sf, link, rootdata, wsize));
5195b0d146aSStefano Zampini     break;
5205b0d146aSStefano Zampini   case PETSCSF_WINDOW_FLAVOR_ALLOCATE:
52197a85fb4SToby Isaac     PetscCallMPI(MPI_Win_allocate(wsize, (PetscMPIInt)bytes, w->info, wcomm, &link->addr, &link->win));
5225b0d146aSStefano Zampini     update = PETSC_TRUE;
5235b0d146aSStefano Zampini     break;
524d547623eSJunchao Zhang #endif
5255b0d146aSStefano Zampini #if defined(PETSC_HAVE_MPI_PROCESS_SHARED_MEMORY)
5265b0d146aSStefano Zampini   case PETSCSF_WINDOW_FLAVOR_SHARED:
52797a85fb4SToby Isaac     PetscCallMPI(MPI_Win_allocate_shared(wsize, (PetscMPIInt)bytes, w->info, wcomm, &link->addr, &link->win));
5285b0d146aSStefano Zampini     update = PETSC_TRUE;
5295b0d146aSStefano Zampini     break;
5305b0d146aSStefano Zampini #endif
531d71ae5a4SJacob Faibussowitsch   default:
53297a85fb4SToby Isaac     SETERRQ(wcomm, PETSC_ERR_SUP, "No support for flavor %s", PetscSFWindowFlavorTypes[w->flavor]);
5335b0d146aSStefano Zampini   }
53497a85fb4SToby Isaac   PetscCall(PetscInfo(sf, "New window %" PETSC_INTPTR_T_FMT " of flavor %d for comm %" PETSC_INTPTR_T_FMT "\n", (PETSC_INTPTR_T)link->win, link->flavor, (PETSC_INTPTR_T)wcomm));
53595fce210SBarry Smith   *win = link->win;
53695fce210SBarry Smith 
5375b0d146aSStefano Zampini found:
5385b0d146aSStefano Zampini 
539684a874aSStefano Zampini   if (target_disp) *target_disp = link->dyn_target_addr;
540684a874aSStefano Zampini   if (reqs) *reqs = link->reqs;
54197a85fb4SToby Isaac   if (update) { /* locks are needed for the "separate" memory model only, the fence guarantees memory-synchronization */
542684a874aSStefano Zampini     PetscMPIInt rank;
543684a874aSStefano Zampini 
54497a85fb4SToby Isaac     PetscCallMPI(MPI_Comm_rank(wcomm, &rank));
5459566063dSJacob Faibussowitsch     if (sync == PETSCSF_WINDOW_SYNC_LOCK) PetscCallMPI(MPI_Win_lock(MPI_LOCK_EXCLUSIVE, rank, MPI_MODE_NOCHECK, *win));
54697a85fb4SToby Isaac     PetscCall(PetscMemcpy(link->addr, rootdata, sf->nroots * bytes));
5475b0d146aSStefano Zampini     if (sync == PETSCSF_WINDOW_SYNC_LOCK) {
5489566063dSJacob Faibussowitsch       PetscCallMPI(MPI_Win_unlock(rank, *win));
5499566063dSJacob Faibussowitsch       PetscCallMPI(MPI_Win_fence(0, *win));
5505b0d146aSStefano Zampini     }
5515b0d146aSStefano Zampini   }
5525b0d146aSStefano Zampini   link->inuse = PETSC_TRUE;
5535b0d146aSStefano Zampini   link->epoch = epoch;
55495fce210SBarry Smith   if (epoch) {
5555b0d146aSStefano Zampini     switch (sync) {
556d71ae5a4SJacob Faibussowitsch     case PETSCSF_WINDOW_SYNC_FENCE:
557d71ae5a4SJacob Faibussowitsch       PetscCallMPI(MPI_Win_fence(fenceassert, *win));
558d71ae5a4SJacob Faibussowitsch       break;
559d71ae5a4SJacob Faibussowitsch     case PETSCSF_WINDOW_SYNC_LOCK: /* Handled outside */
560d71ae5a4SJacob Faibussowitsch       break;
56195fce210SBarry Smith     case PETSCSF_WINDOW_SYNC_ACTIVE: {
56295fce210SBarry Smith       MPI_Group   ingroup, outgroup;
5635b0d146aSStefano Zampini       PetscMPIInt isize, osize;
5645b0d146aSStefano Zampini 
5655b0d146aSStefano Zampini       /* Open MPI 4.0.2 with btl=vader does not like calling
5665b0d146aSStefano Zampini          - MPI_Win_complete when ogroup is empty
5675b0d146aSStefano Zampini          - MPI_Win_wait when igroup is empty
5685b0d146aSStefano Zampini          So, we do not even issue the corresponding start and post calls
5695b0d146aSStefano Zampini          The MPI standard (Sec. 11.5.2 of MPI 3.1) only requires that
5705b0d146aSStefano Zampini          start(outgroup) has a matching post(ingroup)
5715b0d146aSStefano Zampini          and this is guaranteed by PetscSF
5725b0d146aSStefano Zampini       */
5739566063dSJacob Faibussowitsch       PetscCall(PetscSFGetGroups(sf, &ingroup, &outgroup));
5749566063dSJacob Faibussowitsch       PetscCallMPI(MPI_Group_size(ingroup, &isize));
5759566063dSJacob Faibussowitsch       PetscCallMPI(MPI_Group_size(outgroup, &osize));
5769566063dSJacob Faibussowitsch       if (isize) PetscCallMPI(MPI_Win_post(ingroup, postassert, *win));
5779566063dSJacob Faibussowitsch       if (osize) PetscCallMPI(MPI_Win_start(outgroup, startassert, *win));
57895fce210SBarry Smith     } break;
579d71ae5a4SJacob Faibussowitsch     default:
58097a85fb4SToby Isaac       SETERRQ(wcomm, PETSC_ERR_PLIB, "Unknown synchronization type");
58195fce210SBarry Smith     }
58295fce210SBarry Smith   }
5833ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
58495fce210SBarry Smith }
58595fce210SBarry Smith 
5865b0d146aSStefano Zampini /*
58795fce210SBarry Smith    PetscSFFindWindow - Finds a window that is already in use
58895fce210SBarry Smith 
58995fce210SBarry Smith    Not Collective
59095fce210SBarry Smith 
5914165533cSJose E. Roman    Input Parameters:
59295fce210SBarry Smith +  sf - star forest
59395fce210SBarry Smith .  unit - data type
59497a85fb4SToby Isaac .  rootdata - array with which the window is associated
59597a85fb4SToby Isaac -  leafdata - only used to help uniquely identify windows
59695fce210SBarry Smith 
5974165533cSJose E. Roman    Output Parameters:
598684a874aSStefano Zampini +  win - window
599684a874aSStefano Zampini -  reqs - outstanding requests associated to the window
60095fce210SBarry Smith 
60195fce210SBarry Smith    Level: developer
60295fce210SBarry Smith 
603cab54364SBarry Smith .seealso: `PetscSF`, `PETSCSFWINDOW`, `PetscSFGetWindow()`, `PetscSFRestoreWindow()`
6045b0d146aSStefano Zampini */
PetscSFFindWindow(PetscSF sf,MPI_Datatype unit,const void * rootdata,const void * leafdata,MPI_Win * win,MPI_Request ** reqs)60597a85fb4SToby Isaac static PetscErrorCode PetscSFFindWindow(PetscSF sf, MPI_Datatype unit, const void *rootdata, const void *leafdata, MPI_Win *win, MPI_Request **reqs)
606d71ae5a4SJacob Faibussowitsch {
60795fce210SBarry Smith   PetscSF_Window *w = (PetscSF_Window *)sf->data;
60895fce210SBarry Smith   PetscSFWinLink  link;
60997a85fb4SToby Isaac   PetscBool       is_empty;
61097a85fb4SToby Isaac   MPI_Aint        bytes;
61195fce210SBarry Smith 
61295fce210SBarry Smith   PetscFunctionBegin;
61397a85fb4SToby Isaac   PetscCall(PetscSFGetDatatypeSize_Internal(PetscObjectComm((PetscObject)sf), unit, &bytes));
614c0cd0301SJed Brown   *win     = MPI_WIN_NULL;
61597a85fb4SToby Isaac   is_empty = w->is_empty;
61697a85fb4SToby Isaac   if (is_empty) {
61797a85fb4SToby Isaac     *reqs = NULL;
61897a85fb4SToby Isaac     *win  = MPI_WIN_NULL;
61997a85fb4SToby Isaac     PetscFunctionReturn(PETSC_SUCCESS);
62097a85fb4SToby Isaac   }
62195fce210SBarry Smith   for (link = w->wins; link; link = link->next) {
62297a85fb4SToby Isaac     if (rootdata == link->rootdata && leafdata == link->leafdata && bytes == link->bytes) {
62397a85fb4SToby Isaac       PetscCall(PetscInfo(sf, "Window %" PETSC_INTPTR_T_FMT " of flavor %d for comm %" PETSC_INTPTR_T_FMT "\n", (PETSC_INTPTR_T)link->win, link->flavor, (PETSC_INTPTR_T)w->window_comm));
62495fce210SBarry Smith       *win  = link->win;
625684a874aSStefano Zampini       *reqs = link->reqs;
6263ba16761SJacob Faibussowitsch       PetscFunctionReturn(PETSC_SUCCESS);
62795fce210SBarry Smith     }
62895fce210SBarry Smith   }
62995fce210SBarry Smith   SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, "Requested window not in use");
63095fce210SBarry Smith }
63195fce210SBarry Smith 
6325b0d146aSStefano Zampini /*
633cab54364SBarry Smith    PetscSFRestoreWindow - Restores a window obtained with `PetscSFGetWindow()`
63495fce210SBarry Smith 
63595fce210SBarry Smith    Collective
63695fce210SBarry Smith 
6374165533cSJose E. Roman    Input Parameters:
63895fce210SBarry Smith +  sf - star forest
63995fce210SBarry Smith .  unit - data type
64095fce210SBarry Smith .  array - array associated with window
641cab54364SBarry Smith .  sync - type of synchronization `PetscSFWindowSyncType`
642cab54364SBarry Smith .  epoch - close an epoch, must match argument to `PetscSFGetWindow()`
6435b0d146aSStefano Zampini .  update - if we have to update the local window array
64495fce210SBarry Smith -  win - window
64595fce210SBarry Smith 
64695fce210SBarry Smith    Level: developer
64795fce210SBarry Smith 
648cab54364SBarry Smith .seealso: `PetscSF`, `PETSCSFWINDOW`, `PetscSFFindWindow()`
6495b0d146aSStefano Zampini */
PetscSFRestoreWindow(PetscSF sf,MPI_Datatype unit,void * array,PetscSFWindowSyncType sync,PetscBool epoch,PetscMPIInt fenceassert,PetscBool update,MPI_Win * win)650d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscSFRestoreWindow(PetscSF sf, MPI_Datatype unit, void *array, PetscSFWindowSyncType sync, PetscBool epoch, PetscMPIInt fenceassert, PetscBool update, MPI_Win *win)
651d71ae5a4SJacob Faibussowitsch {
65295fce210SBarry Smith   PetscSF_Window         *w = (PetscSF_Window *)sf->data;
65395fce210SBarry Smith   PetscSFWinLink         *p, link;
6545b0d146aSStefano Zampini   PetscBool               reuse = PETSC_FALSE;
6555b0d146aSStefano Zampini   PetscSFWindowFlavorType flavor;
6565b0d146aSStefano Zampini   void                   *laddr;
65797a85fb4SToby Isaac   MPI_Aint                bytes;
65897a85fb4SToby Isaac   MPI_Comm                wcomm;
65995fce210SBarry Smith 
66095fce210SBarry Smith   PetscFunctionBegin;
66197a85fb4SToby Isaac   if (*win == MPI_WIN_NULL) PetscFunctionReturn(PETSC_SUCCESS);
66297a85fb4SToby Isaac   wcomm = w->window_comm;
66395fce210SBarry Smith   for (p = &w->wins; *p; p = &(*p)->next) {
66495fce210SBarry Smith     link = *p;
66595fce210SBarry Smith     if (*win == link->win) {
66697a85fb4SToby Isaac       PetscCheck(array == link->rootdata, PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, "Matched window, but not array");
66795fce210SBarry Smith       if (epoch != link->epoch) {
66828b400f6SJacob Faibussowitsch         PetscCheck(!epoch, PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, "No epoch to end");
669f7d195e4SLawrence Mitchell         SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, "Restoring window without ending epoch");
67095fce210SBarry Smith       }
6715b0d146aSStefano Zampini       laddr  = link->addr;
6725b0d146aSStefano Zampini       flavor = link->flavor;
6735b0d146aSStefano Zampini       bytes  = link->bytes;
6745b0d146aSStefano Zampini       if (flavor != PETSCSF_WINDOW_FLAVOR_CREATE) reuse = PETSC_TRUE;
6759371c9d4SSatish Balay       else {
6769371c9d4SSatish Balay         *p     = link->next;
6779371c9d4SSatish Balay         update = PETSC_FALSE;
6789371c9d4SSatish Balay       } /* remove from list */
67995fce210SBarry Smith       goto found;
68095fce210SBarry Smith     }
68195fce210SBarry Smith   }
68295fce210SBarry Smith   SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, "Requested window not in use");
68395fce210SBarry Smith 
68495fce210SBarry Smith found:
68597a85fb4SToby Isaac   PetscCall(PetscInfo(sf, "Window %" PETSC_INTPTR_T_FMT " of flavor %d for comm %" PETSC_INTPTR_T_FMT "\n", (PETSC_INTPTR_T)link->win, link->flavor, (PETSC_INTPTR_T)wcomm));
68695fce210SBarry Smith   if (epoch) {
6875b0d146aSStefano Zampini     switch (sync) {
688d71ae5a4SJacob Faibussowitsch     case PETSCSF_WINDOW_SYNC_FENCE:
689d71ae5a4SJacob Faibussowitsch       PetscCallMPI(MPI_Win_fence(fenceassert, *win));
690d71ae5a4SJacob Faibussowitsch       break;
691d71ae5a4SJacob Faibussowitsch     case PETSCSF_WINDOW_SYNC_LOCK: /* Handled outside */
692d71ae5a4SJacob Faibussowitsch       break;
69395fce210SBarry Smith     case PETSCSF_WINDOW_SYNC_ACTIVE: {
6945b0d146aSStefano Zampini       MPI_Group   ingroup, outgroup;
6955b0d146aSStefano Zampini       PetscMPIInt isize, osize;
6965b0d146aSStefano Zampini 
6975b0d146aSStefano Zampini       /* Open MPI 4.0.2 with btl=wader does not like calling
6985b0d146aSStefano Zampini          - MPI_Win_complete when ogroup is empty
6995b0d146aSStefano Zampini          - MPI_Win_wait when igroup is empty
7005b0d146aSStefano Zampini          The MPI standard (Sec. 11.5.2 of MPI 3.1) only requires that
7015b0d146aSStefano Zampini          - each process who issues a call to MPI_Win_start issues a call to MPI_Win_Complete
7025b0d146aSStefano Zampini          - each process who issues a call to MPI_Win_post issues a call to MPI_Win_Wait
7035b0d146aSStefano Zampini       */
7049566063dSJacob Faibussowitsch       PetscCall(PetscSFGetGroups(sf, &ingroup, &outgroup));
7059566063dSJacob Faibussowitsch       PetscCallMPI(MPI_Group_size(ingroup, &isize));
7069566063dSJacob Faibussowitsch       PetscCallMPI(MPI_Group_size(outgroup, &osize));
7079566063dSJacob Faibussowitsch       if (osize) PetscCallMPI(MPI_Win_complete(*win));
7089566063dSJacob Faibussowitsch       if (isize) PetscCallMPI(MPI_Win_wait(*win));
70995fce210SBarry Smith     } break;
710d71ae5a4SJacob Faibussowitsch     default:
71197a85fb4SToby Isaac       SETERRQ(wcomm, PETSC_ERR_PLIB, "Unknown synchronization type");
71295fce210SBarry Smith     }
71395fce210SBarry Smith   }
71497a85fb4SToby Isaac #if defined(PETSC_HAVE_MPI_FEATURE_DYNAMIC_WINDOW)
71597a85fb4SToby Isaac   if (link->flavor == PETSCSF_WINDOW_FLAVOR_DYNAMIC && !link->persistent) {
71697a85fb4SToby Isaac     if (link->addr != NULL) PetscCallMPI(MPI_Win_detach(link->win, link->addr));
71797a85fb4SToby Isaac     link->addr = NULL;
71897a85fb4SToby Isaac   }
71997a85fb4SToby Isaac #endif
7205b0d146aSStefano Zampini   if (update) {
72148a46eb9SPierre Jolivet     if (sync == PETSCSF_WINDOW_SYNC_LOCK) PetscCallMPI(MPI_Win_fence(MPI_MODE_NOPUT | MPI_MODE_NOSUCCEED, *win));
7229566063dSJacob Faibussowitsch     PetscCall(PetscMemcpy(array, laddr, sf->nroots * bytes));
7235b0d146aSStefano Zampini   }
7245b0d146aSStefano Zampini   link->epoch = PETSC_FALSE;
7255b0d146aSStefano Zampini   link->inuse = PETSC_FALSE;
72697a85fb4SToby Isaac   if (!link->persistent) {
72797a85fb4SToby Isaac     link->rootdata = NULL;
72897a85fb4SToby Isaac     link->leafdata = NULL;
72997a85fb4SToby Isaac   }
7305b0d146aSStefano Zampini   if (!reuse) {
7319566063dSJacob Faibussowitsch     PetscCall(PetscFree(link->dyn_target_addr));
7329566063dSJacob Faibussowitsch     PetscCall(PetscFree(link->reqs));
7339566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Win_free(&link->win));
7349566063dSJacob Faibussowitsch     PetscCall(PetscFree(link));
73595fce210SBarry Smith     *win = MPI_WIN_NULL;
7365b0d146aSStefano Zampini   }
7373ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
73895fce210SBarry Smith }
73995fce210SBarry Smith 
PetscSFSetUp_Window(PetscSF sf)740d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscSFSetUp_Window(PetscSF sf)
741d71ae5a4SJacob Faibussowitsch {
74295fce210SBarry Smith   PetscSF_Window *w = (PetscSF_Window *)sf->data;
74395fce210SBarry Smith   MPI_Group       ingroup, outgroup;
74497a85fb4SToby Isaac   MPI_Comm        comm;
74595fce210SBarry Smith 
74695fce210SBarry Smith   PetscFunctionBegin;
7479566063dSJacob Faibussowitsch   PetscCall(PetscSFSetUpRanks(sf, MPI_GROUP_EMPTY));
74897a85fb4SToby Isaac   PetscCall(PetscObjectGetComm((PetscObject)sf, &comm));
74997a85fb4SToby Isaac   if (w->window_comm == MPI_COMM_NULL) {
75097a85fb4SToby Isaac     PetscInt    nroots, nleaves, nranks;
75197a85fb4SToby Isaac     PetscBool   has_empty;
75297a85fb4SToby Isaac     PetscMPIInt wcommrank;
75397a85fb4SToby Isaac     PetscSF     dynsf_full = NULL;
75497a85fb4SToby Isaac 
75597a85fb4SToby Isaac     if (w->flavor == PETSCSF_WINDOW_FLAVOR_DYNAMIC) PetscCall(PetscSFWindowCreateDynamicSF(sf, &dynsf_full));
75697a85fb4SToby Isaac 
75797a85fb4SToby Isaac     PetscCall(PetscSFGetGraph(sf, &nroots, &nleaves, NULL, NULL));
75897a85fb4SToby Isaac     has_empty = (nroots == 0 && nleaves == 0) ? PETSC_TRUE : PETSC_FALSE;
75997a85fb4SToby Isaac     nranks    = sf->nranks;
76097a85fb4SToby Isaac     PetscCall(PetscMalloc1(nranks, &w->wcommranks));
76197a85fb4SToby Isaac     w->is_empty = has_empty;
762*5440e5dcSBarry Smith     PetscCallMPI(MPIU_Allreduce(MPI_IN_PLACE, &has_empty, 1, MPI_C_BOOL, MPI_LOR, comm));
76397a85fb4SToby Isaac     if (has_empty) {
76497a85fb4SToby Isaac       PetscMPIInt  rank;
76597a85fb4SToby Isaac       MPI_Comm     raw_comm;
7665b0d146aSStefano Zampini       PetscSFNode *remotes;
7675b0d146aSStefano Zampini 
76897a85fb4SToby Isaac       PetscCallMPI(MPI_Comm_rank(comm, &rank));
76997a85fb4SToby Isaac       PetscCallMPI(MPI_Comm_split(comm, w->is_empty ? 1 : 0, rank, &raw_comm));
77097a85fb4SToby Isaac       PetscCall(PetscCommDuplicate(raw_comm, &w->window_comm, NULL));
77197a85fb4SToby Isaac       PetscCallMPI(MPI_Comm_free(&raw_comm));
77297a85fb4SToby Isaac 
77397a85fb4SToby Isaac       PetscCallMPI(MPI_Comm_rank(w->window_comm, &wcommrank));
77497a85fb4SToby Isaac       if (!dynsf_full) PetscCall(PetscSFWindowCreateDynamicSF(sf, &dynsf_full));
77597a85fb4SToby Isaac       PetscCall(PetscSFBcastBegin(dynsf_full, MPI_INT, &wcommrank, w->wcommranks, MPI_REPLACE));
77697a85fb4SToby Isaac       PetscCall(PetscSFBcastEnd(dynsf_full, MPI_INT, &wcommrank, w->wcommranks, MPI_REPLACE));
77797a85fb4SToby Isaac 
77897a85fb4SToby Isaac       if (w->flavor == PETSCSF_WINDOW_FLAVOR_DYNAMIC) {
77997a85fb4SToby Isaac         PetscCall(PetscSFCreate(w->window_comm, &w->dynsf));
78097a85fb4SToby Isaac         PetscCall(PetscSFSetType(w->dynsf, PETSCSFBASIC)); /* break recursion */
7819566063dSJacob Faibussowitsch         PetscCall(PetscMalloc1(sf->nranks, &remotes));
78297a85fb4SToby Isaac         for (PetscInt i = 0; i < sf->nranks; i++) {
78397a85fb4SToby Isaac           remotes[i].rank  = w->wcommranks[i];
7845b0d146aSStefano Zampini           remotes[i].index = 0;
7855b0d146aSStefano Zampini         }
7869566063dSJacob Faibussowitsch         PetscCall(PetscSFSetGraph(w->dynsf, 1, sf->nranks, NULL, PETSC_OWN_POINTER, remotes, PETSC_OWN_POINTER));
7875b0d146aSStefano Zampini       }
78897a85fb4SToby Isaac     } else {
78997a85fb4SToby Isaac       PetscCall(PetscCommDuplicate(PetscObjectComm((PetscObject)sf), &w->window_comm, NULL));
79097a85fb4SToby Isaac       PetscCall(PetscArraycpy(w->wcommranks, sf->ranks, nranks));
79197a85fb4SToby Isaac       PetscCall(PetscObjectReference((PetscObject)dynsf_full));
79297a85fb4SToby Isaac       w->dynsf = dynsf_full;
79397a85fb4SToby Isaac     }
79497a85fb4SToby Isaac     if (w->dynsf) PetscCall(PetscSFSetUp(w->dynsf));
79597a85fb4SToby Isaac     PetscCall(PetscSFDestroy(&dynsf_full));
79697a85fb4SToby Isaac   }
79795fce210SBarry Smith   switch (w->sync) {
798d71ae5a4SJacob Faibussowitsch   case PETSCSF_WINDOW_SYNC_ACTIVE:
799d71ae5a4SJacob Faibussowitsch     PetscCall(PetscSFGetGroups(sf, &ingroup, &outgroup));
800d71ae5a4SJacob Faibussowitsch   default:
801d71ae5a4SJacob Faibussowitsch     break;
80295fce210SBarry Smith   }
8033ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
80495fce210SBarry Smith }
80595fce210SBarry Smith 
PetscSFSetFromOptions_Window(PetscSF sf,PetscOptionItems PetscOptionsObject)806ce78bad3SBarry Smith static PetscErrorCode PetscSFSetFromOptions_Window(PetscSF sf, PetscOptionItems PetscOptionsObject)
807d71ae5a4SJacob Faibussowitsch {
80895fce210SBarry Smith   PetscSF_Window         *w      = (PetscSF_Window *)sf->data;
8095b0d146aSStefano Zampini   PetscSFWindowFlavorType flavor = w->flavor;
81095fce210SBarry Smith 
81195fce210SBarry Smith   PetscFunctionBegin;
812d0609cedSBarry Smith   PetscOptionsHeadBegin(PetscOptionsObject, "PetscSF Window options");
8139566063dSJacob Faibussowitsch   PetscCall(PetscOptionsEnum("-sf_window_sync", "synchronization type to use for PetscSF Window communication", "PetscSFWindowSetSyncType", PetscSFWindowSyncTypes, (PetscEnum)w->sync, (PetscEnum *)&w->sync, NULL));
8149566063dSJacob Faibussowitsch   PetscCall(PetscOptionsEnum("-sf_window_flavor", "flavor to use for PetscSF Window creation", "PetscSFWindowSetFlavorType", PetscSFWindowFlavorTypes, (PetscEnum)flavor, (PetscEnum *)&flavor, NULL));
8159566063dSJacob Faibussowitsch   PetscCall(PetscSFWindowSetFlavorType(sf, flavor));
816d0609cedSBarry Smith   PetscOptionsHeadEnd();
8173ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
81895fce210SBarry Smith }
81995fce210SBarry Smith 
PetscSFReset_Window(PetscSF sf)820d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscSFReset_Window(PetscSF sf)
821d71ae5a4SJacob Faibussowitsch {
82295fce210SBarry Smith   PetscSF_Window *w = (PetscSF_Window *)sf->data;
82395fce210SBarry Smith   PetscSFDataLink link, next;
82495fce210SBarry Smith   PetscSFWinLink  wlink, wnext;
82595fce210SBarry Smith   PetscInt        i;
82697a85fb4SToby Isaac   MPI_Comm        wcomm;
82797a85fb4SToby Isaac   PetscBool       is_empty;
82895fce210SBarry Smith 
82995fce210SBarry Smith   PetscFunctionBegin;
83095fce210SBarry Smith   for (link = w->link; link; link = next) {
83195fce210SBarry Smith     next = link->next;
8329566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Type_free(&link->unit));
83395fce210SBarry Smith     for (i = 0; i < sf->nranks; i++) {
8349566063dSJacob Faibussowitsch       PetscCallMPI(MPI_Type_free(&link->mine[i]));
8359566063dSJacob Faibussowitsch       PetscCallMPI(MPI_Type_free(&link->remote[i]));
83695fce210SBarry Smith     }
8379566063dSJacob Faibussowitsch     PetscCall(PetscFree2(link->mine, link->remote));
8389566063dSJacob Faibussowitsch     PetscCall(PetscFree(link));
83995fce210SBarry Smith   }
84095fce210SBarry Smith   w->link  = NULL;
84197a85fb4SToby Isaac   wcomm    = w->window_comm;
84297a85fb4SToby Isaac   is_empty = w->is_empty;
84397a85fb4SToby Isaac   if (!is_empty) {
84495fce210SBarry Smith     for (wlink = w->wins; wlink; wlink = wnext) {
84595fce210SBarry Smith       wnext = wlink->next;
84697a85fb4SToby Isaac       PetscCheck(!wlink->inuse, wcomm, PETSC_ERR_ARG_WRONGSTATE, "Window still in use with address %p", (void *)wlink->addr);
8479566063dSJacob Faibussowitsch       PetscCall(PetscFree(wlink->dyn_target_addr));
8489566063dSJacob Faibussowitsch       PetscCall(PetscFree(wlink->reqs));
8499566063dSJacob Faibussowitsch       PetscCallMPI(MPI_Win_free(&wlink->win));
8509566063dSJacob Faibussowitsch       PetscCall(PetscFree(wlink));
85195fce210SBarry Smith     }
85297a85fb4SToby Isaac   }
85395fce210SBarry Smith   w->wins = NULL;
8549566063dSJacob Faibussowitsch   PetscCall(PetscSFDestroy(&w->dynsf));
85548a46eb9SPierre Jolivet   if (w->info != MPI_INFO_NULL) PetscCallMPI(MPI_Info_free(&w->info));
85697a85fb4SToby Isaac   PetscCall(PetscCommDestroy(&w->window_comm));
85797a85fb4SToby Isaac   PetscCall(PetscFree(w->wcommranks));
85897a85fb4SToby Isaac   PetscFunctionReturn(PETSC_SUCCESS);
85997a85fb4SToby Isaac }
86097a85fb4SToby Isaac 
PetscSFRegisterPersistent_Window(PetscSF sf,MPI_Datatype unit,const void * rootdata,const void * leafdata)86197a85fb4SToby Isaac static PetscErrorCode PetscSFRegisterPersistent_Window(PetscSF sf, MPI_Datatype unit, const void *rootdata, const void *leafdata)
86297a85fb4SToby Isaac {
86397a85fb4SToby Isaac   PetscSF_Window *w = (PetscSF_Window *)sf->data;
86497a85fb4SToby Isaac   MPI_Aint        bytes, wsize;
86597a85fb4SToby Isaac   PetscBool       is_empty;
86697a85fb4SToby Isaac   PetscSFWinLink  link;
86797a85fb4SToby Isaac 
86897a85fb4SToby Isaac   PetscFunctionBegin;
86997a85fb4SToby Isaac   PetscCall(PetscSFSetUp(sf));
87097a85fb4SToby Isaac   if (w->flavor != PETSCSF_WINDOW_FLAVOR_DYNAMIC) PetscFunctionReturn(PETSC_SUCCESS);
87197a85fb4SToby Isaac   PetscCall(PetscSFGetDatatypeSize_Internal(PetscObjectComm((PetscObject)sf), unit, &bytes));
87297a85fb4SToby Isaac   wsize    = (MPI_Aint)(bytes * sf->nroots);
87397a85fb4SToby Isaac   is_empty = w->is_empty;
87497a85fb4SToby Isaac   if (is_empty) PetscFunctionReturn(PETSC_SUCCESS);
87597a85fb4SToby Isaac   PetscCall(PetscNew(&link));
87697a85fb4SToby Isaac   link->flavor = w->flavor;
87797a85fb4SToby Isaac   link->next   = w->wins;
87897a85fb4SToby Isaac #if defined(PETSC_HAVE_MPI_FEATURE_DYNAMIC_WINDOW)
87997a85fb4SToby Isaac   {
88097a85fb4SToby Isaac     MPI_Comm wcomm = w->window_comm;
88197a85fb4SToby Isaac     PetscCallMPI(MPI_Win_create_dynamic(w->info, wcomm, &link->win));
88297a85fb4SToby Isaac   }
88397a85fb4SToby Isaac #endif
88497a85fb4SToby Isaac   PetscCall(PetscSFWindowAttach(sf, link, (void *)rootdata, wsize));
88597a85fb4SToby Isaac   link->rootdata   = (void *)rootdata;
88697a85fb4SToby Isaac   link->leafdata   = (void *)leafdata;
88797a85fb4SToby Isaac   link->bytes      = bytes;
88897a85fb4SToby Isaac   link->epoch      = PETSC_FALSE;
88997a85fb4SToby Isaac   link->inuse      = PETSC_FALSE;
89097a85fb4SToby Isaac   link->persistent = PETSC_TRUE;
89197a85fb4SToby Isaac   w->wins          = link;
89297a85fb4SToby Isaac   if (w->sync == PETSCSF_WINDOW_SYNC_LOCK) {
89397a85fb4SToby Isaac     PetscInt i;
89497a85fb4SToby Isaac 
89597a85fb4SToby Isaac     PetscCall(PetscMalloc1(sf->nranks, &link->reqs));
89697a85fb4SToby Isaac     for (i = 0; i < sf->nranks; i++) link->reqs[i] = MPI_REQUEST_NULL;
89797a85fb4SToby Isaac   }
89897a85fb4SToby Isaac   PetscFunctionReturn(PETSC_SUCCESS);
89997a85fb4SToby Isaac }
90097a85fb4SToby Isaac 
PetscSFDeregisterPersistent_Window(PetscSF sf,MPI_Datatype unit,const void * rootdata,const void * leafdata)90197a85fb4SToby Isaac static PetscErrorCode PetscSFDeregisterPersistent_Window(PetscSF sf, MPI_Datatype unit, const void *rootdata, const void *leafdata)
90297a85fb4SToby Isaac {
90397a85fb4SToby Isaac   PetscSF_Window *w = (PetscSF_Window *)sf->data;
90497a85fb4SToby Isaac   MPI_Aint        bytes;
90597a85fb4SToby Isaac   MPI_Comm        wcomm;
90697a85fb4SToby Isaac   PetscBool       is_empty;
90797a85fb4SToby Isaac   PetscSFWinLink *p;
90897a85fb4SToby Isaac 
90997a85fb4SToby Isaac   PetscFunctionBegin;
91097a85fb4SToby Isaac   PetscCall(PetscSFSetUp(sf));
91197a85fb4SToby Isaac   if (w->flavor != PETSCSF_WINDOW_FLAVOR_DYNAMIC) PetscFunctionReturn(PETSC_SUCCESS);
91297a85fb4SToby Isaac   PetscCall(PetscSFGetDatatypeSize_Internal(PetscObjectComm((PetscObject)sf), unit, &bytes));
91397a85fb4SToby Isaac   wcomm    = w->window_comm;
91497a85fb4SToby Isaac   is_empty = w->is_empty;
91597a85fb4SToby Isaac   if (is_empty) PetscFunctionReturn(PETSC_SUCCESS);
91697a85fb4SToby Isaac   for (p = &w->wins; *p; p = &(*p)->next) {
91797a85fb4SToby Isaac     PetscSFWinLink link = *p;
91897a85fb4SToby Isaac     if (link->flavor == w->flavor && link->persistent && link->rootdata == rootdata && link->leafdata == leafdata && link->bytes == bytes) {
91997a85fb4SToby Isaac       PetscCheck(!link->inuse, wcomm, PETSC_ERR_ARG_WRONGSTATE, "Deregistering a window when communication is still in progress");
92097a85fb4SToby Isaac       PetscCheck(!link->epoch, wcomm, PETSC_ERR_ARG_WRONGSTATE, "Deregistering a window with an unconcluded epoch");
92197a85fb4SToby Isaac #if defined(PETSC_HAVE_MPI_FEATURE_DYNAMIC_WINDOW)
92297a85fb4SToby Isaac       PetscCallMPI(MPI_Win_detach(link->win, link->addr));
92397a85fb4SToby Isaac       link->addr = NULL;
92497a85fb4SToby Isaac #endif
92597a85fb4SToby Isaac       PetscCall(PetscFree(link->dyn_target_addr));
92697a85fb4SToby Isaac       PetscCall(PetscFree(link->reqs));
92797a85fb4SToby Isaac       PetscCallMPI(MPI_Win_free(&link->win));
92897a85fb4SToby Isaac       *p = link->next;
92997a85fb4SToby Isaac       PetscCall(PetscFree(link));
93097a85fb4SToby Isaac       break;
93197a85fb4SToby Isaac     }
93297a85fb4SToby Isaac   }
9333ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
93495fce210SBarry Smith }
93595fce210SBarry Smith 
PetscSFDestroy_Window(PetscSF sf)936d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscSFDestroy_Window(PetscSF sf)
937d71ae5a4SJacob Faibussowitsch {
93895fce210SBarry Smith   PetscFunctionBegin;
9399566063dSJacob Faibussowitsch   PetscCall(PetscSFReset_Window(sf));
9409566063dSJacob Faibussowitsch   PetscCall(PetscFree(sf->data));
9419566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)sf, "PetscSFWindowSetSyncType_C", NULL));
9429566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)sf, "PetscSFWindowGetSyncType_C", NULL));
9439566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)sf, "PetscSFWindowSetFlavorType_C", NULL));
9449566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)sf, "PetscSFWindowGetFlavorType_C", NULL));
9459566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)sf, "PetscSFWindowSetInfo_C", NULL));
9469566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)sf, "PetscSFWindowGetInfo_C", NULL));
94797a85fb4SToby Isaac   PetscCall(PetscObjectComposeFunction((PetscObject)sf, "PetscSFRegisterPersistent_C", NULL));
94897a85fb4SToby Isaac   PetscCall(PetscObjectComposeFunction((PetscObject)sf, "PetscSFDeregisterPersistent_C", NULL));
9493ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
95095fce210SBarry Smith }
95195fce210SBarry Smith 
PetscSFView_Window(PetscSF sf,PetscViewer viewer)952d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscSFView_Window(PetscSF sf, PetscViewer viewer)
953d71ae5a4SJacob Faibussowitsch {
95495fce210SBarry Smith   PetscSF_Window   *w = (PetscSF_Window *)sf->data;
9559f196a02SMartin Diehl   PetscBool         isascii;
9565b0d146aSStefano Zampini   PetscViewerFormat format;
95795fce210SBarry Smith 
95895fce210SBarry Smith   PetscFunctionBegin;
9599566063dSJacob Faibussowitsch   PetscCall(PetscViewerGetFormat(viewer, &format));
9609f196a02SMartin Diehl   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii));
9619f196a02SMartin Diehl   if (isascii) {
9629566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  current flavor=%s synchronization=%s MultiSF sort=%s\n", PetscSFWindowFlavorTypes[w->flavor], PetscSFWindowSyncTypes[w->sync], sf->rankorder ? "rank-order" : "unordered"));
9635b0d146aSStefano Zampini     if (format == PETSC_VIEWER_ASCII_INFO_DETAIL) {
9645b0d146aSStefano Zampini       if (w->info != MPI_INFO_NULL) {
9655b0d146aSStefano Zampini         PetscMPIInt k, nkeys;
9665b0d146aSStefano Zampini         char        key[MPI_MAX_INFO_KEY], value[MPI_MAX_INFO_VAL];
9675b0d146aSStefano Zampini 
9689566063dSJacob Faibussowitsch         PetscCallMPI(MPI_Info_get_nkeys(w->info, &nkeys));
9699566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, "    current info with %d keys. Ordered key-value pairs follow:\n", nkeys));
9705b0d146aSStefano Zampini         for (k = 0; k < nkeys; k++) {
9715b0d146aSStefano Zampini           PetscMPIInt flag;
9725b0d146aSStefano Zampini 
9739566063dSJacob Faibussowitsch           PetscCallMPI(MPI_Info_get_nthkey(w->info, k, key));
9749566063dSJacob Faibussowitsch           PetscCallMPI(MPI_Info_get(w->info, key, MPI_MAX_INFO_VAL, value, &flag));
97528b400f6SJacob Faibussowitsch           PetscCheck(flag, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Missing key %s", key);
9769566063dSJacob Faibussowitsch           PetscCall(PetscViewerASCIIPrintf(viewer, "      %s = %s\n", key, value));
9775b0d146aSStefano Zampini         }
9785b0d146aSStefano Zampini       } else {
9799566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, "    current info=MPI_INFO_NULL\n"));
9805b0d146aSStefano Zampini       }
9815b0d146aSStefano Zampini     }
98295fce210SBarry Smith   }
9833ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
98495fce210SBarry Smith }
98595fce210SBarry Smith 
PetscSFDuplicate_Window(PetscSF sf,PetscSFDuplicateOption opt,PetscSF newsf)986d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscSFDuplicate_Window(PetscSF sf, PetscSFDuplicateOption opt, PetscSF newsf)
987d71ae5a4SJacob Faibussowitsch {
98895fce210SBarry Smith   PetscSF_Window       *w = (PetscSF_Window *)sf->data;
98995fce210SBarry Smith   PetscSFWindowSyncType synctype;
99095fce210SBarry Smith 
99195fce210SBarry Smith   PetscFunctionBegin;
99295fce210SBarry Smith   synctype = w->sync;
99395fce210SBarry Smith   /* HACK: Must use FENCE or LOCK when called from PetscSFGetGroups() because ACTIVE here would cause recursion. */
9945b0d146aSStefano Zampini   if (!sf->setupcalled) synctype = PETSCSF_WINDOW_SYNC_LOCK;
9959566063dSJacob Faibussowitsch   PetscCall(PetscSFWindowSetSyncType(newsf, synctype));
9969566063dSJacob Faibussowitsch   PetscCall(PetscSFWindowSetFlavorType(newsf, w->flavor));
9979566063dSJacob Faibussowitsch   PetscCall(PetscSFWindowSetInfo(newsf, w->info));
9983ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
99995fce210SBarry Smith }
100095fce210SBarry Smith 
PetscSFBcastBegin_Window(PetscSF sf,MPI_Datatype unit,PetscMemType rootmtype,const void * rootdata,PetscMemType leafmtype,void * leafdata,MPI_Op op)1001d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscSFBcastBegin_Window(PetscSF sf, MPI_Datatype unit, PetscMemType rootmtype, const void *rootdata, PetscMemType leafmtype, void *leafdata, MPI_Op op)
1002d71ae5a4SJacob Faibussowitsch {
100395fce210SBarry Smith   PetscSF_Window     *w = (PetscSF_Window *)sf->data;
10046497c311SBarry Smith   PetscMPIInt         nranks;
100595fce210SBarry Smith   const PetscMPIInt  *ranks;
10065b0d146aSStefano Zampini   const MPI_Aint     *target_disp;
100795fce210SBarry Smith   const MPI_Datatype *mine, *remote;
1008684a874aSStefano Zampini   MPI_Request        *reqs;
100995fce210SBarry Smith   MPI_Win             win;
101095fce210SBarry Smith 
101195fce210SBarry Smith   PetscFunctionBegin;
101208401ef6SPierre Jolivet   PetscCheck(op == MPI_REPLACE, PetscObjectComm((PetscObject)sf), PETSC_ERR_SUP, "PetscSFBcastBegin_Window with op!=MPI_REPLACE has not been implemented");
101397a85fb4SToby Isaac   PetscCall(PetscSFGetRootRanks(sf, &nranks, NULL, NULL, NULL, NULL));
10149566063dSJacob Faibussowitsch   PetscCall(PetscSFWindowGetDataTypes(sf, unit, &mine, &remote));
101597a85fb4SToby Isaac   PetscCall(PetscSFGetWindow(sf, unit, (void *)rootdata, leafdata, w->sync, PETSC_TRUE, MPI_MODE_NOPUT | MPI_MODE_NOPRECEDE, MPI_MODE_NOPUT, 0, &target_disp, &reqs, &win));
101697a85fb4SToby Isaac   ranks = w->wcommranks;
10176497c311SBarry Smith   for (PetscMPIInt i = 0; i < nranks; i++) {
10185b0d146aSStefano Zampini     MPI_Aint tdp = target_disp ? target_disp[i] : 0;
1019684a874aSStefano Zampini     if (w->sync == PETSCSF_WINDOW_SYNC_LOCK) {
10209566063dSJacob Faibussowitsch       PetscCallMPI(MPI_Win_lock(MPI_LOCK_SHARED, ranks[i], MPI_MODE_NOCHECK, win));
1021684a874aSStefano Zampini #if defined(PETSC_HAVE_MPI_RGET)
10229566063dSJacob Faibussowitsch       PetscCallMPI(MPI_Rget(leafdata, 1, mine[i], ranks[i], tdp, 1, remote[i], win, &reqs[i]));
1023684a874aSStefano Zampini #else
10249566063dSJacob Faibussowitsch       PetscCallMPI(MPI_Get(leafdata, 1, mine[i], ranks[i], tdp, 1, remote[i], win));
1025684a874aSStefano Zampini #endif
1026684a874aSStefano Zampini     } else {
10276497c311SBarry Smith       CHKMEMQ;
10289566063dSJacob Faibussowitsch       PetscCallMPI(MPI_Get(leafdata, 1, mine[i], ranks[i], tdp, 1, remote[i], win));
10296497c311SBarry Smith       CHKMEMQ;
1030684a874aSStefano Zampini     }
103195fce210SBarry Smith   }
10323ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
103395fce210SBarry Smith }
103495fce210SBarry Smith 
PetscSFBcastEnd_Window(PetscSF sf,MPI_Datatype unit,const void * rootdata,void * leafdata,MPI_Op op)103566976f2fSJacob Faibussowitsch static PetscErrorCode PetscSFBcastEnd_Window(PetscSF sf, MPI_Datatype unit, const void *rootdata, void *leafdata, MPI_Op op)
1036d71ae5a4SJacob Faibussowitsch {
10375b0d146aSStefano Zampini   PetscSF_Window *w = (PetscSF_Window *)sf->data;
103895fce210SBarry Smith   MPI_Win         win;
10394b9acda6SJunchao Zhang   MPI_Request    *reqs = NULL;
104095fce210SBarry Smith 
104195fce210SBarry Smith   PetscFunctionBegin;
104297a85fb4SToby Isaac   PetscCall(PetscSFFindWindow(sf, unit, rootdata, leafdata, &win, &reqs));
10439566063dSJacob Faibussowitsch   if (reqs) PetscCallMPI(MPI_Waitall(sf->nranks, reqs, MPI_STATUSES_IGNORE));
1044684a874aSStefano Zampini   if (w->sync == PETSCSF_WINDOW_SYNC_LOCK) {
10456497c311SBarry Smith     PetscMPIInt        nranks;
1046684a874aSStefano Zampini     const PetscMPIInt *ranks;
1047684a874aSStefano Zampini 
104897a85fb4SToby Isaac     PetscCall(PetscSFGetRootRanks(sf, &nranks, NULL, NULL, NULL, NULL));
104997a85fb4SToby Isaac     ranks = w->wcommranks;
10506497c311SBarry Smith     for (PetscMPIInt i = 0; i < nranks; i++) PetscCallMPI(MPI_Win_unlock(ranks[i], win));
1051684a874aSStefano Zampini   }
10529566063dSJacob Faibussowitsch   PetscCall(PetscSFRestoreWindow(sf, unit, (void *)rootdata, w->sync, PETSC_TRUE, MPI_MODE_NOSTORE | MPI_MODE_NOSUCCEED, PETSC_FALSE, &win));
10533ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
105495fce210SBarry Smith }
105595fce210SBarry Smith 
PetscSFReduceBegin_Window(PetscSF sf,MPI_Datatype unit,PetscMemType leafmtype,const void * leafdata,PetscMemType rootmtype,void * rootdata,MPI_Op op)105666976f2fSJacob Faibussowitsch static PetscErrorCode PetscSFReduceBegin_Window(PetscSF sf, MPI_Datatype unit, PetscMemType leafmtype, const void *leafdata, PetscMemType rootmtype, void *rootdata, MPI_Op op)
1057d71ae5a4SJacob Faibussowitsch {
105895fce210SBarry Smith   PetscSF_Window     *w = (PetscSF_Window *)sf->data;
10596497c311SBarry Smith   PetscMPIInt         nranks;
106095fce210SBarry Smith   const PetscMPIInt  *ranks;
10615b0d146aSStefano Zampini   const MPI_Aint     *target_disp;
106295fce210SBarry Smith   const MPI_Datatype *mine, *remote;
106395fce210SBarry Smith   MPI_Win             win;
106495fce210SBarry Smith 
106595fce210SBarry Smith   PetscFunctionBegin;
106697a85fb4SToby Isaac   PetscCall(PetscSFGetRootRanks(sf, &nranks, NULL, NULL, NULL, NULL));
10679566063dSJacob Faibussowitsch   PetscCall(PetscSFWindowGetDataTypes(sf, unit, &mine, &remote));
10689566063dSJacob Faibussowitsch   PetscCall(PetscSFWindowOpTranslate(&op));
106997a85fb4SToby Isaac   PetscCall(PetscSFGetWindow(sf, unit, rootdata, (void *)leafdata, w->sync, PETSC_TRUE, MPI_MODE_NOPRECEDE, 0, 0, &target_disp, NULL, &win));
107097a85fb4SToby Isaac   ranks = w->wcommranks;
10716497c311SBarry Smith   for (PetscMPIInt i = 0; i < nranks; i++) {
10725b0d146aSStefano Zampini     MPI_Aint tdp = target_disp ? target_disp[i] : 0;
10735b0d146aSStefano Zampini 
10749566063dSJacob Faibussowitsch     if (w->sync == PETSCSF_WINDOW_SYNC_LOCK) PetscCallMPI(MPI_Win_lock(MPI_LOCK_SHARED, ranks[i], MPI_MODE_NOCHECK, win));
10759566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Accumulate((void *)leafdata, 1, mine[i], ranks[i], tdp, 1, remote[i], op, win));
10769566063dSJacob Faibussowitsch     if (w->sync == PETSCSF_WINDOW_SYNC_LOCK) PetscCallMPI(MPI_Win_unlock(ranks[i], win));
107795fce210SBarry Smith   }
10783ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
107995fce210SBarry Smith }
108095fce210SBarry Smith 
PetscSFReduceEnd_Window(PetscSF sf,MPI_Datatype unit,const void * leafdata,void * rootdata,MPI_Op op)1081d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscSFReduceEnd_Window(PetscSF sf, MPI_Datatype unit, const void *leafdata, void *rootdata, MPI_Op op)
1082d71ae5a4SJacob Faibussowitsch {
108395fce210SBarry Smith   PetscSF_Window *w = (PetscSF_Window *)sf->data;
108495fce210SBarry Smith   MPI_Win         win;
10854b9acda6SJunchao Zhang   MPI_Request    *reqs = NULL;
108695fce210SBarry Smith 
108795fce210SBarry Smith   PetscFunctionBegin;
108897a85fb4SToby Isaac   PetscCall(PetscSFFindWindow(sf, unit, rootdata, leafdata, &win, &reqs));
10899566063dSJacob Faibussowitsch   if (reqs) PetscCallMPI(MPI_Waitall(sf->nranks, reqs, MPI_STATUSES_IGNORE));
10909566063dSJacob Faibussowitsch   PetscCall(PetscSFRestoreWindow(sf, unit, rootdata, w->sync, PETSC_TRUE, MPI_MODE_NOSUCCEED, PETSC_TRUE, &win));
10913ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
109295fce210SBarry Smith }
10935b0d146aSStefano Zampini 
PetscSFFetchAndOpBegin_Window(PetscSF sf,MPI_Datatype unit,PetscMemType rootmtype,void * rootdata,PetscMemType leafmtype,const void * leafdata,void * leafupdate,MPI_Op op)1094d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscSFFetchAndOpBegin_Window(PetscSF sf, MPI_Datatype unit, PetscMemType rootmtype, void *rootdata, PetscMemType leafmtype, const void *leafdata, void *leafupdate, MPI_Op op)
1095d71ae5a4SJacob Faibussowitsch {
10966497c311SBarry Smith   PetscMPIInt         nranks;
109795fce210SBarry Smith   const PetscMPIInt  *ranks;
109895fce210SBarry Smith   const MPI_Datatype *mine, *remote;
10995b0d146aSStefano Zampini   const MPI_Aint     *target_disp;
110095fce210SBarry Smith   MPI_Win             win;
11015b0d146aSStefano Zampini   PetscSF_Window     *w = (PetscSF_Window *)sf->data;
11025b0d146aSStefano Zampini #if !defined(PETSC_HAVE_MPI_GET_ACCUMULATE)
11035b0d146aSStefano Zampini   PetscSFWindowFlavorType oldf;
11045b0d146aSStefano Zampini #endif
110595fce210SBarry Smith 
110695fce210SBarry Smith   PetscFunctionBegin;
110797a85fb4SToby Isaac   PetscCall(PetscSFGetRootRanks(sf, &nranks, NULL, NULL, NULL, NULL));
11089566063dSJacob Faibussowitsch   PetscCall(PetscSFWindowGetDataTypes(sf, unit, &mine, &remote));
11099566063dSJacob Faibussowitsch   PetscCall(PetscSFWindowOpTranslate(&op));
11105b0d146aSStefano Zampini #if !defined(PETSC_HAVE_MPI_GET_ACCUMULATE)
11115b0d146aSStefano Zampini   /* FetchAndOp without MPI_Get_Accumulate requires locking.
11125b0d146aSStefano Zampini      we create a new window every time to not interfere with user-defined MPI_Info which may have used "no_locks"="true" */
11135b0d146aSStefano Zampini   oldf      = w->flavor;
11145b0d146aSStefano Zampini   w->flavor = PETSCSF_WINDOW_FLAVOR_CREATE;
111597a85fb4SToby Isaac   PetscCall(PetscSFGetWindow(sf, unit, rootdata, (void *)leafdata, PETSCSF_WINDOW_SYNC_LOCK, PETSC_FALSE, 0, 0, 0, &target_disp, NULL, &win));
11165b0d146aSStefano Zampini #else
111797a85fb4SToby Isaac   PetscCall(PetscSFGetWindow(sf, unit, rootdata, (void *)leafdata, w->sync, PETSC_TRUE, MPI_MODE_NOPRECEDE, 0, 0, &target_disp, NULL, &win));
11185b0d146aSStefano Zampini #endif
111997a85fb4SToby Isaac   ranks = w->wcommranks;
11206497c311SBarry Smith   for (PetscMPIInt i = 0; i < nranks; i++) {
11215b0d146aSStefano Zampini     MPI_Aint tdp = target_disp ? target_disp[i] : 0;
11225b0d146aSStefano Zampini 
11235b0d146aSStefano Zampini #if !defined(PETSC_HAVE_MPI_GET_ACCUMULATE)
11249566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Win_lock(MPI_LOCK_EXCLUSIVE, ranks[i], 0, win));
11259566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Get(leafupdate, 1, mine[i], ranks[i], tdp, 1, remote[i], win));
11269566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Accumulate((void *)leafdata, 1, mine[i], ranks[i], tdp, 1, remote[i], op, win));
11279566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Win_unlock(ranks[i], win));
11285b0d146aSStefano Zampini #else
11299566063dSJacob Faibussowitsch     if (w->sync == PETSCSF_WINDOW_SYNC_LOCK) PetscCallMPI(MPI_Win_lock(MPI_LOCK_SHARED, ranks[i], 0, win));
11309566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Get_accumulate((void *)leafdata, 1, mine[i], leafupdate, 1, mine[i], ranks[i], tdp, 1, remote[i], op, win));
11319566063dSJacob Faibussowitsch     if (w->sync == PETSCSF_WINDOW_SYNC_LOCK) PetscCallMPI(MPI_Win_unlock(ranks[i], win));
11325b0d146aSStefano Zampini #endif
11335b0d146aSStefano Zampini   }
11345b0d146aSStefano Zampini #if !defined(PETSC_HAVE_MPI_GET_ACCUMULATE)
11355b0d146aSStefano Zampini   w->flavor = oldf;
11365b0d146aSStefano Zampini #endif
11373ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
113895fce210SBarry Smith }
113995fce210SBarry Smith 
PetscSFFetchAndOpEnd_Window(PetscSF sf,MPI_Datatype unit,void * rootdata,const void * leafdata,void * leafupdate,MPI_Op op)1140d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscSFFetchAndOpEnd_Window(PetscSF sf, MPI_Datatype unit, void *rootdata, const void *leafdata, void *leafupdate, MPI_Op op)
1141d71ae5a4SJacob Faibussowitsch {
114295fce210SBarry Smith   MPI_Win win;
11435b0d146aSStefano Zampini #if defined(PETSC_HAVE_MPI_GET_ACCUMULATE)
11445b0d146aSStefano Zampini   PetscSF_Window *w = (PetscSF_Window *)sf->data;
11455b0d146aSStefano Zampini #endif
11464b9acda6SJunchao Zhang   MPI_Request *reqs = NULL;
114795fce210SBarry Smith 
114895fce210SBarry Smith   PetscFunctionBegin;
114997a85fb4SToby Isaac   PetscCall(PetscSFFindWindow(sf, unit, rootdata, leafdata, &win, &reqs));
11509566063dSJacob Faibussowitsch   if (reqs) PetscCallMPI(MPI_Waitall(sf->nranks, reqs, MPI_STATUSES_IGNORE));
11515b0d146aSStefano Zampini #if defined(PETSC_HAVE_MPI_GET_ACCUMULATE)
11529566063dSJacob Faibussowitsch   PetscCall(PetscSFRestoreWindow(sf, unit, rootdata, w->sync, PETSC_TRUE, MPI_MODE_NOSUCCEED, PETSC_TRUE, &win));
11535b0d146aSStefano Zampini #else
11549566063dSJacob Faibussowitsch   PetscCall(PetscSFRestoreWindow(sf, unit, rootdata, PETSCSF_WINDOW_SYNC_LOCK, PETSC_FALSE, 0, PETSC_TRUE, &win));
11555b0d146aSStefano Zampini #endif
11563ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
115795fce210SBarry Smith }
115895fce210SBarry Smith 
PetscSFCreate_Window(PetscSF sf)1159d71ae5a4SJacob Faibussowitsch PETSC_INTERN PetscErrorCode PetscSFCreate_Window(PetscSF sf)
1160d71ae5a4SJacob Faibussowitsch {
116195fce210SBarry Smith   PetscSF_Window *w = (PetscSF_Window *)sf->data;
116295fce210SBarry Smith 
116395fce210SBarry Smith   PetscFunctionBegin;
116495fce210SBarry Smith   sf->ops->SetUp           = PetscSFSetUp_Window;
116595fce210SBarry Smith   sf->ops->SetFromOptions  = PetscSFSetFromOptions_Window;
116695fce210SBarry Smith   sf->ops->Reset           = PetscSFReset_Window;
116795fce210SBarry Smith   sf->ops->Destroy         = PetscSFDestroy_Window;
116895fce210SBarry Smith   sf->ops->View            = PetscSFView_Window;
116995fce210SBarry Smith   sf->ops->Duplicate       = PetscSFDuplicate_Window;
1170ad227feaSJunchao Zhang   sf->ops->BcastBegin      = PetscSFBcastBegin_Window;
1171ad227feaSJunchao Zhang   sf->ops->BcastEnd        = PetscSFBcastEnd_Window;
117295fce210SBarry Smith   sf->ops->ReduceBegin     = PetscSFReduceBegin_Window;
117395fce210SBarry Smith   sf->ops->ReduceEnd       = PetscSFReduceEnd_Window;
117495fce210SBarry Smith   sf->ops->FetchAndOpBegin = PetscSFFetchAndOpBegin_Window;
117595fce210SBarry Smith   sf->ops->FetchAndOpEnd   = PetscSFFetchAndOpEnd_Window;
117695fce210SBarry Smith 
11774dfa11a4SJacob Faibussowitsch   PetscCall(PetscNew(&w));
117895fce210SBarry Smith   sf->data       = (void *)w;
117995fce210SBarry Smith   w->sync        = PETSCSF_WINDOW_SYNC_FENCE;
11805b0d146aSStefano Zampini   w->flavor      = PETSCSF_WINDOW_FLAVOR_CREATE;
11815b0d146aSStefano Zampini   w->info        = MPI_INFO_NULL;
118297a85fb4SToby Isaac   w->window_comm = MPI_COMM_NULL;
118395fce210SBarry Smith 
11849566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)sf, "PetscSFWindowSetSyncType_C", PetscSFWindowSetSyncType_Window));
11859566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)sf, "PetscSFWindowGetSyncType_C", PetscSFWindowGetSyncType_Window));
11869566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)sf, "PetscSFWindowSetFlavorType_C", PetscSFWindowSetFlavorType_Window));
11879566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)sf, "PetscSFWindowGetFlavorType_C", PetscSFWindowGetFlavorType_Window));
11889566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)sf, "PetscSFWindowSetInfo_C", PetscSFWindowSetInfo_Window));
11899566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)sf, "PetscSFWindowGetInfo_C", PetscSFWindowGetInfo_Window));
119097a85fb4SToby Isaac   PetscCall(PetscObjectComposeFunction((PetscObject)sf, "PetscSFRegisterPersistent_C", PetscSFRegisterPersistent_Window));
119197a85fb4SToby Isaac   PetscCall(PetscObjectComposeFunction((PetscObject)sf, "PetscSFDeregisterPersistent_C", PetscSFDeregisterPersistent_Window));
119295fce210SBarry Smith 
1193100ffedbSJunchao Zhang #if defined(PETSC_HAVE_OPENMPI)
1194100ffedbSJunchao Zhang   #if PETSC_PKG_OPENMPI_VERSION_LE(1, 6, 0)
119595fce210SBarry Smith   {
119695fce210SBarry Smith     PetscBool ackbug = PETSC_FALSE;
1197966bd95aSPierre Jolivet 
11989566063dSJacob Faibussowitsch     PetscCall(PetscOptionsGetBool(NULL, NULL, "-acknowledge_ompi_onesided_bug", &ackbug, NULL));
1199966bd95aSPierre Jolivet     PetscCheck(ackbug, 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");
12009566063dSJacob Faibussowitsch     PetscCall(PetscInfo(sf, "Acknowledged Open MPI bug, proceeding anyway. Expect memory corruption.\n"));
120195fce210SBarry Smith   }
120295fce210SBarry Smith   #endif
1203100ffedbSJunchao Zhang #endif
12043ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
120595fce210SBarry Smith }
1206