xref: /petsc/src/vec/is/sf/impls/window/sfwindow.c (revision 28b400f66ebc7ae0049166a2294dfcd3df27e64b)
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) */
3995fce210SBarry Smith static PetscErrorCode PetscSFWindowOpTranslate(MPI_Op *op)
4095fce210SBarry Smith {
4195fce210SBarry Smith   PetscFunctionBegin;
4295fce210SBarry Smith   if (*op == MPIU_SUM) *op = MPI_SUM;
4395fce210SBarry Smith   else if (*op == MPIU_MAX) *op = MPI_MAX;
4495fce210SBarry Smith   else if (*op == MPIU_MIN) *op = MPI_MIN;
4595fce210SBarry Smith   PetscFunctionReturn(0);
4695fce210SBarry Smith }
4795fce210SBarry Smith 
4895fce210SBarry Smith /*@C
4995fce210SBarry Smith    PetscSFWindowGetDataTypes - gets composite local and remote data types for each rank
5095fce210SBarry Smith 
5195fce210SBarry Smith    Not Collective
5295fce210SBarry Smith 
534165533cSJose E. Roman    Input Parameters:
5495fce210SBarry Smith +  sf - star forest
5595fce210SBarry Smith -  unit - data type for each node
5695fce210SBarry Smith 
574165533cSJose E. Roman    Output Parameters:
5895fce210SBarry Smith +  localtypes - types describing part of local leaf buffer referencing each remote rank
5995fce210SBarry Smith -  remotetypes - types describing part of remote root buffer referenced for each remote rank
6095fce210SBarry Smith 
6195fce210SBarry Smith    Level: developer
6295fce210SBarry Smith 
6395fce210SBarry Smith .seealso: PetscSFSetGraph(), PetscSFView()
6495fce210SBarry Smith @*/
6595fce210SBarry Smith static PetscErrorCode PetscSFWindowGetDataTypes(PetscSF sf,MPI_Datatype unit,const MPI_Datatype **localtypes,const MPI_Datatype **remotetypes)
6695fce210SBarry Smith {
6795fce210SBarry Smith   PetscSF_Window    *w = (PetscSF_Window*)sf->data;
6895fce210SBarry Smith   PetscSFDataLink   link;
6995fce210SBarry Smith   PetscInt          i,nranks;
7095fce210SBarry Smith   const PetscInt    *roffset,*rmine,*rremote;
7195fce210SBarry Smith   const PetscMPIInt *ranks;
7295fce210SBarry Smith 
7395fce210SBarry Smith   PetscFunctionBegin;
7495fce210SBarry Smith   /* Look for types in cache */
7595fce210SBarry Smith   for (link=w->link; link; link=link->next) {
7695fce210SBarry Smith     PetscBool match;
775f80ce2aSJacob Faibussowitsch     CHKERRQ(MPIPetsc_Type_compare(unit,link->unit,&match));
7895fce210SBarry Smith     if (match) {
7995fce210SBarry Smith       *localtypes  = link->mine;
8095fce210SBarry Smith       *remotetypes = link->remote;
8195fce210SBarry Smith       PetscFunctionReturn(0);
8295fce210SBarry Smith     }
8395fce210SBarry Smith   }
8495fce210SBarry Smith 
8595fce210SBarry Smith   /* Create new composite types for each send rank */
865f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSFGetRootRanks(sf,&nranks,&ranks,&roffset,&rmine,&rremote));
875f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscNew(&link));
885f80ce2aSJacob Faibussowitsch   CHKERRMPI(MPI_Type_dup(unit,&link->unit));
895f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscMalloc2(nranks,&link->mine,nranks,&link->remote));
9095fce210SBarry Smith   for (i=0; i<nranks; i++) {
915b0d146aSStefano Zampini     PetscInt    rcount = roffset[i+1] - roffset[i];
9295fce210SBarry Smith     PetscMPIInt *rmine,*rremote;
9395fce210SBarry Smith #if !defined(PETSC_USE_64BIT_INDICES)
9495fce210SBarry Smith     rmine   = sf->rmine + sf->roffset[i];
9595fce210SBarry Smith     rremote = sf->rremote + sf->roffset[i];
9695fce210SBarry Smith #else
9795fce210SBarry Smith     PetscInt j;
985f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscMalloc2(rcount,&rmine,rcount,&rremote));
9995fce210SBarry Smith     for (j=0; j<rcount; j++) {
1005f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscMPIIntCast(sf->rmine[sf->roffset[i]+j],rmine+j));
1015f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscMPIIntCast(sf->rremote[sf->roffset[i]+j],rremote+j));
10295fce210SBarry Smith     }
10395fce210SBarry Smith #endif
1045b0d146aSStefano Zampini 
1055f80ce2aSJacob Faibussowitsch     CHKERRMPI(MPI_Type_create_indexed_block(rcount,1,rmine,link->unit,&link->mine[i]));
1065f80ce2aSJacob Faibussowitsch     CHKERRMPI(MPI_Type_create_indexed_block(rcount,1,rremote,link->unit,&link->remote[i]));
10795fce210SBarry Smith #if defined(PETSC_USE_64BIT_INDICES)
1085f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscFree2(rmine,rremote));
10995fce210SBarry Smith #endif
1105f80ce2aSJacob Faibussowitsch     CHKERRMPI(MPI_Type_commit(&link->mine[i]));
1115f80ce2aSJacob Faibussowitsch     CHKERRMPI(MPI_Type_commit(&link->remote[i]));
11295fce210SBarry Smith   }
11395fce210SBarry Smith   link->next = w->link;
11495fce210SBarry Smith   w->link    = link;
11595fce210SBarry Smith 
11695fce210SBarry Smith   *localtypes  = link->mine;
11795fce210SBarry Smith   *remotetypes = link->remote;
11895fce210SBarry Smith   PetscFunctionReturn(0);
11995fce210SBarry Smith }
12095fce210SBarry Smith 
12195fce210SBarry Smith /*@C
1225b0d146aSStefano Zampini    PetscSFWindowSetFlavorType - Set flavor type for MPI_Win creation
1235b0d146aSStefano Zampini 
1245b0d146aSStefano Zampini    Logically Collective
1255b0d146aSStefano Zampini 
1264165533cSJose E. Roman    Input Parameters:
1275b0d146aSStefano Zampini +  sf - star forest for communication
1285b0d146aSStefano Zampini -  flavor - flavor type
1295b0d146aSStefano Zampini 
1305b0d146aSStefano Zampini    Options Database Key:
1315b0d146aSStefano Zampini .  -sf_window_flavor <flavor> - sets the flavor type CREATE, DYNAMIC, ALLOCATE or SHARED (see PetscSFWindowFlavorType)
1325b0d146aSStefano Zampini 
1335b0d146aSStefano Zampini    Level: advanced
1345b0d146aSStefano Zampini 
1355b0d146aSStefano Zampini    Notes: Windows reusage follow this rules:
1365b0d146aSStefano Zampini 
1375b0d146aSStefano Zampini      PETSCSF_WINDOW_FLAVOR_CREATE: creates a new window every time, uses MPI_Win_create
1385b0d146aSStefano Zampini 
1395b0d146aSStefano 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.
1405b0d146aSStefano Zampini        for i=1 to K
1415b0d146aSStefano Zampini          PetscSFOperationBegin(rootdata1,leafdata_whatever);
1425b0d146aSStefano Zampini          PetscSFOperationEnd(rootdata1,leafdata_whatever);
1435b0d146aSStefano Zampini          ...
1445b0d146aSStefano Zampini          PetscSFOperationBegin(rootdataN,leafdata_whatever);
1455b0d146aSStefano Zampini          PetscSFOperationEnd(rootdataN,leafdata_whatever);
1465b0d146aSStefano Zampini        endfor
1475b0d146aSStefano Zampini        The following pattern will instead raise an error
1485b0d146aSStefano Zampini          PetscSFOperationBegin(rootdata1,leafdata_whatever);
1495b0d146aSStefano Zampini          PetscSFOperationEnd(rootdata1,leafdata_whatever);
1505b0d146aSStefano Zampini          PetscSFOperationBegin(rank ? rootdata1 : rootdata2,leafdata_whatever);
1515b0d146aSStefano Zampini          PetscSFOperationEnd(rank ? rootdata1 : rootdata2,leafdata_whatever);
1525b0d146aSStefano Zampini 
1535b0d146aSStefano Zampini      PETSCSF_WINDOW_FLAVOR_ALLOCATE: uses MPI_Win_allocate, reuses any pre-existing window which fits the data and it is not in use
1545b0d146aSStefano Zampini 
1555b0d146aSStefano Zampini      PETSCSF_WINDOW_FLAVOR_SHARED: uses MPI_Win_allocate_shared, reusage policy as for PETSCSF_WINDOW_FLAVOR_ALLOCATE
1565b0d146aSStefano Zampini 
1575b0d146aSStefano Zampini .seealso: PetscSFSetFromOptions(), PetscSFWindowGetFlavorType()
1585b0d146aSStefano Zampini @*/
1595b0d146aSStefano Zampini PetscErrorCode PetscSFWindowSetFlavorType(PetscSF sf,PetscSFWindowFlavorType flavor)
1605b0d146aSStefano Zampini {
1615b0d146aSStefano Zampini   PetscFunctionBegin;
1625b0d146aSStefano Zampini   PetscValidHeaderSpecific(sf,PETSCSF_CLASSID,1);
1635b0d146aSStefano Zampini   PetscValidLogicalCollectiveEnum(sf,flavor,2);
1645f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscTryMethod(sf,"PetscSFWindowSetFlavorType_C",(PetscSF,PetscSFWindowFlavorType),(sf,flavor)));
1655b0d146aSStefano Zampini   PetscFunctionReturn(0);
1665b0d146aSStefano Zampini }
1675b0d146aSStefano Zampini 
1685b0d146aSStefano Zampini static PetscErrorCode PetscSFWindowSetFlavorType_Window(PetscSF sf,PetscSFWindowFlavorType flavor)
1695b0d146aSStefano Zampini {
1705b0d146aSStefano Zampini   PetscSF_Window *w = (PetscSF_Window*)sf->data;
1715b0d146aSStefano Zampini 
1725b0d146aSStefano Zampini   PetscFunctionBegin;
1735b0d146aSStefano Zampini   w->flavor = flavor;
1745b0d146aSStefano Zampini   PetscFunctionReturn(0);
1755b0d146aSStefano Zampini }
1765b0d146aSStefano Zampini 
1775b0d146aSStefano Zampini /*@C
1785b0d146aSStefano Zampini    PetscSFWindowGetFlavorType - Get flavor type for PetscSF communication
1795b0d146aSStefano Zampini 
1805b0d146aSStefano Zampini    Logically Collective
1815b0d146aSStefano Zampini 
1824165533cSJose E. Roman    Input Parameter:
1835b0d146aSStefano Zampini .  sf - star forest for communication
1845b0d146aSStefano Zampini 
1854165533cSJose E. Roman    Output Parameter:
1865b0d146aSStefano Zampini .  flavor - flavor type
1875b0d146aSStefano Zampini 
1885b0d146aSStefano Zampini    Level: advanced
1895b0d146aSStefano Zampini 
1905b0d146aSStefano Zampini .seealso: PetscSFSetFromOptions(), PetscSFWindowSetFlavorType()
1915b0d146aSStefano Zampini @*/
1925b0d146aSStefano Zampini PetscErrorCode PetscSFWindowGetFlavorType(PetscSF sf,PetscSFWindowFlavorType *flavor)
1935b0d146aSStefano Zampini {
1945b0d146aSStefano Zampini   PetscFunctionBegin;
1955b0d146aSStefano Zampini   PetscValidHeaderSpecific(sf,PETSCSF_CLASSID,1);
1965b0d146aSStefano Zampini   PetscValidPointer(flavor,2);
1975f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscUseMethod(sf,"PetscSFWindowGetFlavorType_C",(PetscSF,PetscSFWindowFlavorType*),(sf,flavor)));
1985b0d146aSStefano Zampini   PetscFunctionReturn(0);
1995b0d146aSStefano Zampini }
2005b0d146aSStefano Zampini 
2015b0d146aSStefano Zampini static PetscErrorCode PetscSFWindowGetFlavorType_Window(PetscSF sf,PetscSFWindowFlavorType *flavor)
2025b0d146aSStefano Zampini {
2035b0d146aSStefano Zampini   PetscSF_Window *w = (PetscSF_Window*)sf->data;
2045b0d146aSStefano Zampini 
2055b0d146aSStefano Zampini   PetscFunctionBegin;
2065b0d146aSStefano Zampini   *flavor = w->flavor;
2075b0d146aSStefano Zampini   PetscFunctionReturn(0);
2085b0d146aSStefano Zampini }
2095b0d146aSStefano Zampini 
2105b0d146aSStefano Zampini /*@C
2115b0d146aSStefano Zampini    PetscSFWindowSetSyncType - Set synchronization type for PetscSF communication
21295fce210SBarry Smith 
21395fce210SBarry Smith    Logically Collective
21495fce210SBarry Smith 
2154165533cSJose E. Roman    Input Parameters:
21695fce210SBarry Smith +  sf - star forest for communication
21795fce210SBarry Smith -  sync - synchronization type
21895fce210SBarry Smith 
21995fce210SBarry Smith    Options Database Key:
22060263706SJed Brown .  -sf_window_sync <sync> - sets the synchronization type FENCE, LOCK, or ACTIVE (see PetscSFWindowSyncType)
22195fce210SBarry Smith 
22295fce210SBarry Smith    Level: advanced
22395fce210SBarry Smith 
22495fce210SBarry Smith .seealso: PetscSFSetFromOptions(), PetscSFWindowGetSyncType()
22595fce210SBarry Smith @*/
22695fce210SBarry Smith PetscErrorCode PetscSFWindowSetSyncType(PetscSF sf,PetscSFWindowSyncType sync)
22795fce210SBarry Smith {
22895fce210SBarry Smith   PetscFunctionBegin;
22995fce210SBarry Smith   PetscValidHeaderSpecific(sf,PETSCSF_CLASSID,1);
23095fce210SBarry Smith   PetscValidLogicalCollectiveEnum(sf,sync,2);
2315f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscTryMethod(sf,"PetscSFWindowSetSyncType_C",(PetscSF,PetscSFWindowSyncType),(sf,sync)));
23295fce210SBarry Smith   PetscFunctionReturn(0);
23395fce210SBarry Smith }
23495fce210SBarry Smith 
235f7a08781SBarry Smith static PetscErrorCode PetscSFWindowSetSyncType_Window(PetscSF sf,PetscSFWindowSyncType sync)
23695fce210SBarry Smith {
23795fce210SBarry Smith   PetscSF_Window *w = (PetscSF_Window*)sf->data;
23895fce210SBarry Smith 
23995fce210SBarry Smith   PetscFunctionBegin;
24095fce210SBarry Smith   w->sync = sync;
24195fce210SBarry Smith   PetscFunctionReturn(0);
24295fce210SBarry Smith }
24395fce210SBarry Smith 
24495fce210SBarry Smith /*@C
2455b0d146aSStefano Zampini    PetscSFWindowGetSyncType - Get synchronization type for PetscSF communication
24695fce210SBarry Smith 
24795fce210SBarry Smith    Logically Collective
24895fce210SBarry Smith 
2494165533cSJose E. Roman    Input Parameter:
25095fce210SBarry Smith .  sf - star forest for communication
25195fce210SBarry Smith 
2524165533cSJose E. Roman    Output Parameter:
25395fce210SBarry Smith .  sync - synchronization type
25495fce210SBarry Smith 
25595fce210SBarry Smith    Level: advanced
25695fce210SBarry Smith 
2575b0d146aSStefano Zampini .seealso: PetscSFSetFromOptions(), PetscSFWindowSetSyncType()
25895fce210SBarry Smith @*/
25995fce210SBarry Smith PetscErrorCode PetscSFWindowGetSyncType(PetscSF sf,PetscSFWindowSyncType *sync)
26095fce210SBarry Smith {
26195fce210SBarry Smith   PetscFunctionBegin;
26295fce210SBarry Smith   PetscValidHeaderSpecific(sf,PETSCSF_CLASSID,1);
26395fce210SBarry Smith   PetscValidPointer(sync,2);
2645f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscUseMethod(sf,"PetscSFWindowGetSyncType_C",(PetscSF,PetscSFWindowSyncType*),(sf,sync)));
26595fce210SBarry Smith   PetscFunctionReturn(0);
26695fce210SBarry Smith }
26795fce210SBarry Smith 
268f7a08781SBarry Smith static PetscErrorCode PetscSFWindowGetSyncType_Window(PetscSF sf,PetscSFWindowSyncType *sync)
26995fce210SBarry Smith {
27095fce210SBarry Smith   PetscSF_Window *w = (PetscSF_Window*)sf->data;
27195fce210SBarry Smith 
27295fce210SBarry Smith   PetscFunctionBegin;
27395fce210SBarry Smith   *sync = w->sync;
27495fce210SBarry Smith   PetscFunctionReturn(0);
27595fce210SBarry Smith }
27695fce210SBarry Smith 
27795fce210SBarry Smith /*@C
2785b0d146aSStefano Zampini    PetscSFWindowSetInfo - Set the MPI_Info handle that will be used for subsequent windows allocation
2795b0d146aSStefano Zampini 
2805b0d146aSStefano Zampini    Logically Collective
2815b0d146aSStefano Zampini 
2824165533cSJose E. Roman    Input Parameters:
2835b0d146aSStefano Zampini +  sf - star forest for communication
2845b0d146aSStefano Zampini -  info - MPI_Info handle
2855b0d146aSStefano Zampini 
2865b0d146aSStefano Zampini    Level: advanced
2875b0d146aSStefano Zampini 
2885b0d146aSStefano Zampini    Notes: the info handle is duplicated with a call to MPI_Info_dup unless info = MPI_INFO_NULL.
2895b0d146aSStefano Zampini 
2905b0d146aSStefano Zampini .seealso: PetscSFSetFromOptions(), PetscSFWindowGetInfo()
2915b0d146aSStefano Zampini @*/
2925b0d146aSStefano Zampini PetscErrorCode PetscSFWindowSetInfo(PetscSF sf,MPI_Info info)
2935b0d146aSStefano Zampini {
2945b0d146aSStefano Zampini   PetscFunctionBegin;
2955b0d146aSStefano Zampini   PetscValidHeaderSpecific(sf,PETSCSF_CLASSID,1);
2965f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscTryMethod(sf,"PetscSFWindowSetInfo_C",(PetscSF,MPI_Info),(sf,info)));
2975b0d146aSStefano Zampini   PetscFunctionReturn(0);
2985b0d146aSStefano Zampini }
2995b0d146aSStefano Zampini 
3005b0d146aSStefano Zampini static PetscErrorCode PetscSFWindowSetInfo_Window(PetscSF sf,MPI_Info info)
3015b0d146aSStefano Zampini {
3025b0d146aSStefano Zampini   PetscSF_Window *w = (PetscSF_Window*)sf->data;
3035b0d146aSStefano Zampini 
3045b0d146aSStefano Zampini   PetscFunctionBegin;
3055b0d146aSStefano Zampini   if (w->info != MPI_INFO_NULL) {
3065f80ce2aSJacob Faibussowitsch     CHKERRMPI(MPI_Info_free(&w->info));
3075b0d146aSStefano Zampini   }
3085b0d146aSStefano Zampini   if (info != MPI_INFO_NULL) {
3095f80ce2aSJacob Faibussowitsch     CHKERRMPI(MPI_Info_dup(info,&w->info));
3105b0d146aSStefano Zampini   }
3115b0d146aSStefano Zampini   PetscFunctionReturn(0);
3125b0d146aSStefano Zampini }
3135b0d146aSStefano Zampini 
3145b0d146aSStefano Zampini /*@C
3155b0d146aSStefano Zampini    PetscSFWindowGetInfo - Get the MPI_Info handle used for windows allocation
3165b0d146aSStefano Zampini 
3175b0d146aSStefano Zampini    Logically Collective
3185b0d146aSStefano Zampini 
3194165533cSJose E. Roman    Input Parameter:
3205b0d146aSStefano Zampini .  sf - star forest for communication
3215b0d146aSStefano Zampini 
3224165533cSJose E. Roman    Output Parameter:
3235b0d146aSStefano Zampini .  info - MPI_Info handle
3245b0d146aSStefano Zampini 
3255b0d146aSStefano Zampini    Level: advanced
3265b0d146aSStefano Zampini 
3275b0d146aSStefano Zampini    Notes: if PetscSFWindowSetInfo() has not be called, this returns MPI_INFO_NULL
3285b0d146aSStefano Zampini 
3295b0d146aSStefano Zampini .seealso: PetscSFSetFromOptions(), PetscSFWindowSetInfo()
3305b0d146aSStefano Zampini @*/
3315b0d146aSStefano Zampini PetscErrorCode PetscSFWindowGetInfo(PetscSF sf,MPI_Info *info)
3325b0d146aSStefano Zampini {
3335b0d146aSStefano Zampini   PetscFunctionBegin;
3345b0d146aSStefano Zampini   PetscValidHeaderSpecific(sf,PETSCSF_CLASSID,1);
3355b0d146aSStefano Zampini   PetscValidPointer(info,2);
3365f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscUseMethod(sf,"PetscSFWindowGetInfo_C",(PetscSF,MPI_Info*),(sf,info)));
3375b0d146aSStefano Zampini   PetscFunctionReturn(0);
3385b0d146aSStefano Zampini }
3395b0d146aSStefano Zampini 
3405b0d146aSStefano Zampini static PetscErrorCode PetscSFWindowGetInfo_Window(PetscSF sf,MPI_Info *info)
3415b0d146aSStefano Zampini {
3425b0d146aSStefano Zampini   PetscSF_Window *w = (PetscSF_Window*)sf->data;
3435b0d146aSStefano Zampini 
3445b0d146aSStefano Zampini   PetscFunctionBegin;
3455b0d146aSStefano Zampini   *info = w->info;
3465b0d146aSStefano Zampini   PetscFunctionReturn(0);
3475b0d146aSStefano Zampini }
3485b0d146aSStefano Zampini 
3495b0d146aSStefano Zampini /*
35095fce210SBarry Smith    PetscSFGetWindow - Get a window for use with a given data type
35195fce210SBarry Smith 
35295fce210SBarry Smith    Collective on PetscSF
35395fce210SBarry Smith 
3544165533cSJose E. Roman    Input Parameters:
35595fce210SBarry Smith +  sf - star forest
35695fce210SBarry Smith .  unit - data type
35795fce210SBarry Smith .  array - array to be sent
3585b0d146aSStefano Zampini .  sync - type of synchronization PetscSFWindowSyncType
35995fce210SBarry Smith .  epoch - PETSC_TRUE to acquire the window and start an epoch, PETSC_FALSE to just acquire the window
3605b0d146aSStefano Zampini .  fenceassert - assert parameter for call to MPI_Win_fence(), if sync == PETSCSF_WINDOW_SYNC_FENCE
3615b0d146aSStefano Zampini .  postassert - assert parameter for call to MPI_Win_post(), if sync == PETSCSF_WINDOW_SYNC_ACTIVE
362684a874aSStefano Zampini -  startassert - assert parameter for call to MPI_Win_start(), if sync == PETSCSF_WINDOW_SYNC_ACTIVE
36395fce210SBarry Smith 
3644165533cSJose E. Roman    Output Parameters:
365684a874aSStefano Zampini +  target_disp - target_disp argument for RMA calls (significative for PETSCSF_WINDOW_FLAVOR_DYNAMIC only)
366684a874aSStefano Zampini +  reqs - array of requests (significative for sync == PETSCSF_WINDOW_SYNC_LOCK only)
367684a874aSStefano Zampini -  win - window
36895fce210SBarry Smith 
36995fce210SBarry Smith    Level: developer
370dec1416fSJunchao Zhang .seealso: PetscSFGetRootRanks(), PetscSFWindowGetDataTypes()
3715b0d146aSStefano Zampini */
372684a874aSStefano Zampini static PetscErrorCode PetscSFGetWindow(PetscSF sf,MPI_Datatype unit,void *array,PetscSFWindowSyncType sync,PetscBool epoch,PetscMPIInt fenceassert,PetscMPIInt postassert,PetscMPIInt startassert,const MPI_Aint **target_disp, MPI_Request **reqs, MPI_Win *win)
37395fce210SBarry Smith {
37495fce210SBarry Smith   PetscSF_Window *w = (PetscSF_Window*)sf->data;
37595fce210SBarry Smith   MPI_Aint       lb,lb_true,bytes,bytes_true;
37695fce210SBarry Smith   PetscSFWinLink link;
377d547623eSJunchao Zhang #if defined(PETSC_HAVE_MPI_FEATURE_DYNAMIC_WINDOW)
3785b0d146aSStefano Zampini   MPI_Aint       winaddr;
3795b0d146aSStefano Zampini   PetscInt       nranks;
380d547623eSJunchao Zhang #endif
3815b0d146aSStefano Zampini   PetscBool      reuse = PETSC_FALSE, update = PETSC_FALSE;
3825b0d146aSStefano Zampini   PetscBool      dummy[2];
3835b0d146aSStefano Zampini   MPI_Aint       wsize;
38495fce210SBarry Smith 
38595fce210SBarry Smith   PetscFunctionBegin;
3865f80ce2aSJacob Faibussowitsch   CHKERRMPI(MPI_Type_get_extent(unit,&lb,&bytes));
3875f80ce2aSJacob Faibussowitsch   CHKERRMPI(MPI_Type_get_true_extent(unit,&lb_true,&bytes_true));
3882c71b3e2SJacob Faibussowitsch   PetscCheckFalse(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");
3892c71b3e2SJacob Faibussowitsch   PetscCheckFalse(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");
3905b0d146aSStefano Zampini   if (w->flavor != PETSCSF_WINDOW_FLAVOR_CREATE) reuse = PETSC_TRUE;
3915b0d146aSStefano Zampini   for (link=w->wins; reuse && link; link=link->next) {
3925b0d146aSStefano Zampini     PetscBool winok = PETSC_FALSE;
3935b0d146aSStefano Zampini     if (w->flavor != link->flavor) continue;
3945b0d146aSStefano Zampini     switch (w->flavor) {
3955b0d146aSStefano 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) */
3965b0d146aSStefano Zampini       if (array == link->addr) {
39776bd3646SJed Brown         if (PetscDefined(USE_DEBUG)) {
3985b0d146aSStefano Zampini           dummy[0] = PETSC_TRUE;
3995b0d146aSStefano Zampini           dummy[1] = PETSC_TRUE;
4005f80ce2aSJacob Faibussowitsch           CHKERRMPI(MPI_Allreduce(MPI_IN_PLACE,dummy,1,MPIU_BOOL,MPI_LAND,PetscObjectComm((PetscObject)sf)));
4015f80ce2aSJacob Faibussowitsch           CHKERRMPI(MPI_Allreduce(MPI_IN_PLACE,dummy+1,1,MPIU_BOOL,MPI_LOR ,PetscObjectComm((PetscObject)sf)));
4022c71b3e2SJacob Faibussowitsch           PetscCheckFalse(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");
40376bd3646SJed Brown         }
404*28b400f6SJacob Faibussowitsch         PetscCheck(!link->inuse,PetscObjectComm((PetscObject)sf),PETSC_ERR_PLIB,"Window in use");
4052c71b3e2SJacob Faibussowitsch         PetscCheckFalse(epoch && link->epoch,PetscObjectComm((PetscObject)sf),PETSC_ERR_PLIB,"Window epoch not finished");
4065b0d146aSStefano Zampini         winok = PETSC_TRUE;
4075b0d146aSStefano Zampini         link->paddr = array;
40876bd3646SJed Brown       } else if (PetscDefined(USE_DEBUG)) {
4095b0d146aSStefano Zampini         dummy[0] = PETSC_FALSE;
4105b0d146aSStefano Zampini         dummy[1] = PETSC_FALSE;
4115f80ce2aSJacob Faibussowitsch         CHKERRMPI(MPI_Allreduce(MPI_IN_PLACE,dummy  ,1,MPIU_BOOL,MPI_LAND,PetscObjectComm((PetscObject)sf)));
4125f80ce2aSJacob Faibussowitsch         CHKERRMPI(MPI_Allreduce(MPI_IN_PLACE,dummy+1,1,MPIU_BOOL,MPI_LOR ,PetscObjectComm((PetscObject)sf)));
4132c71b3e2SJacob Faibussowitsch         PetscCheckFalse(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");
4145b0d146aSStefano Zampini       }
4155b0d146aSStefano Zampini       break;
4165b0d146aSStefano Zampini     case PETSCSF_WINDOW_FLAVOR_ALLOCATE: /* check available by matching size, allocate if in use */
4175b0d146aSStefano Zampini     case PETSCSF_WINDOW_FLAVOR_SHARED:
4185b0d146aSStefano Zampini       if (!link->inuse && bytes == (MPI_Aint)link->bytes) {
4195b0d146aSStefano Zampini         update = PETSC_TRUE;
4205b0d146aSStefano Zampini         link->paddr = array;
4215b0d146aSStefano Zampini         winok = PETSC_TRUE;
4225b0d146aSStefano Zampini       }
4235b0d146aSStefano Zampini       break;
42498921bdaSJacob Faibussowitsch     default: SETERRQ(PetscObjectComm((PetscObject)sf),PETSC_ERR_SUP,"No support for flavor %s",PetscSFWindowFlavorTypes[w->flavor]);
4255b0d146aSStefano Zampini     }
4265b0d146aSStefano Zampini     if (winok) {
4275b0d146aSStefano Zampini       *win = link->win;
4285f80ce2aSJacob Faibussowitsch       CHKERRQ(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)));
4295b0d146aSStefano Zampini       goto found;
4305b0d146aSStefano Zampini     }
4315b0d146aSStefano Zampini   }
4325b0d146aSStefano Zampini 
4335b0d146aSStefano Zampini   wsize = (MPI_Aint)bytes*sf->nroots;
4345f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscNew(&link));
43595fce210SBarry Smith   link->bytes           = bytes;
43695fce210SBarry Smith   link->next            = w->wins;
4375b0d146aSStefano Zampini   link->flavor          = w->flavor;
4385b0d146aSStefano Zampini   link->dyn_target_addr = NULL;
439684a874aSStefano Zampini   link->reqs            = NULL;
44095fce210SBarry Smith   w->wins               = link;
441684a874aSStefano Zampini   if (sync == PETSCSF_WINDOW_SYNC_LOCK) {
442684a874aSStefano Zampini     PetscInt i;
443684a874aSStefano Zampini 
4445f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscMalloc1(sf->nranks,&link->reqs));
445684a874aSStefano Zampini     for (i = 0; i < sf->nranks; i++) link->reqs[i] = MPI_REQUEST_NULL;
446684a874aSStefano Zampini   }
4475b0d146aSStefano Zampini   switch (w->flavor) {
4485b0d146aSStefano Zampini   case PETSCSF_WINDOW_FLAVOR_CREATE:
4495f80ce2aSJacob Faibussowitsch     CHKERRMPI(MPI_Win_create(array,wsize,(PetscMPIInt)bytes,w->info,PetscObjectComm((PetscObject)sf),&link->win));
4505b0d146aSStefano Zampini     link->addr  = array;
4515b0d146aSStefano Zampini     link->paddr = array;
4525b0d146aSStefano Zampini     break;
453d547623eSJunchao Zhang #if defined(PETSC_HAVE_MPI_FEATURE_DYNAMIC_WINDOW)
4545b0d146aSStefano Zampini   case PETSCSF_WINDOW_FLAVOR_DYNAMIC:
4555f80ce2aSJacob Faibussowitsch     CHKERRMPI(MPI_Win_create_dynamic(w->info,PetscObjectComm((PetscObject)sf),&link->win));
4565b0d146aSStefano Zampini #if defined(PETSC_HAVE_OMPI_MAJOR_VERSION) /* some OpenMPI versions do not support MPI_Win_attach(win,NULL,0); */
4575f80ce2aSJacob Faibussowitsch     int dummy = 0;
4585f80ce2aSJacob Faibussowitsch     CHKERRMPI(MPI_Win_attach(link->win,wsize ? array : (void*)&dummy,wsize));
4595b0d146aSStefano Zampini #else
4605f80ce2aSJacob Faibussowitsch     CHKERRMPI(MPI_Win_attach(link->win,array,wsize));
4615b0d146aSStefano Zampini #endif
4625b0d146aSStefano Zampini     link->addr  = array;
4635b0d146aSStefano Zampini     link->paddr = array;
464*28b400f6SJacob Faibussowitsch     PetscCheck(w->dynsf,PetscObjectComm((PetscObject)sf),PETSC_ERR_ORDER,"Must call PetscSFSetUp()");
4655f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSFSetUp(w->dynsf));
4665f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSFGetRootRanks(w->dynsf,&nranks,NULL,NULL,NULL,NULL));
4675f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscMalloc1(nranks,&link->dyn_target_addr));
4685f80ce2aSJacob Faibussowitsch     CHKERRMPI(MPI_Get_address(array,&winaddr));
4695f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSFBcastBegin(w->dynsf,MPI_AINT,&winaddr,link->dyn_target_addr,MPI_REPLACE));
4705f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSFBcastEnd(w->dynsf,MPI_AINT,&winaddr,link->dyn_target_addr,MPI_REPLACE));
4715b0d146aSStefano Zampini     break;
4725b0d146aSStefano Zampini   case PETSCSF_WINDOW_FLAVOR_ALLOCATE:
4735f80ce2aSJacob Faibussowitsch     CHKERRMPI(MPI_Win_allocate(wsize,(PetscMPIInt)bytes,w->info,PetscObjectComm((PetscObject)sf),&link->addr,&link->win));
4745b0d146aSStefano Zampini     update = PETSC_TRUE;
4755b0d146aSStefano Zampini     link->paddr = array;
4765b0d146aSStefano Zampini     break;
477d547623eSJunchao Zhang #endif
4785b0d146aSStefano Zampini #if defined(PETSC_HAVE_MPI_PROCESS_SHARED_MEMORY)
4795b0d146aSStefano Zampini   case PETSCSF_WINDOW_FLAVOR_SHARED:
4805f80ce2aSJacob Faibussowitsch     CHKERRMPI(MPI_Win_allocate_shared(wsize,(PetscMPIInt)bytes,w->info,PetscObjectComm((PetscObject)sf),&link->addr,&link->win));
4815b0d146aSStefano Zampini     update = PETSC_TRUE;
4825b0d146aSStefano Zampini     link->paddr = array;
4835b0d146aSStefano Zampini     break;
4845b0d146aSStefano Zampini #endif
48598921bdaSJacob Faibussowitsch   default: SETERRQ(PetscObjectComm((PetscObject)sf),PETSC_ERR_SUP,"No support for flavor %s",PetscSFWindowFlavorTypes[w->flavor]);
4865b0d146aSStefano Zampini   }
4875f80ce2aSJacob Faibussowitsch   CHKERRQ(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)));
48895fce210SBarry Smith   *win = link->win;
48995fce210SBarry Smith 
4905b0d146aSStefano Zampini found:
4915b0d146aSStefano Zampini 
492684a874aSStefano Zampini   if (target_disp) *target_disp = link->dyn_target_addr;
493684a874aSStefano Zampini   if (reqs) *reqs = link->reqs;
494684a874aSStefano Zampini   if (update) { /* locks are needed for the "separate" memory model only, the fence guaranties memory-synchronization */
495684a874aSStefano Zampini     PetscMPIInt rank;
496684a874aSStefano Zampini 
4975f80ce2aSJacob Faibussowitsch     CHKERRMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)sf),&rank));
4985f80ce2aSJacob Faibussowitsch     if (sync == PETSCSF_WINDOW_SYNC_LOCK) CHKERRMPI(MPI_Win_lock(MPI_LOCK_EXCLUSIVE,rank,MPI_MODE_NOCHECK,*win));
4995f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscMemcpy(link->addr,array,sf->nroots*bytes));
5005b0d146aSStefano Zampini     if (sync == PETSCSF_WINDOW_SYNC_LOCK) {
5015f80ce2aSJacob Faibussowitsch       CHKERRMPI(MPI_Win_unlock(rank,*win));
5025f80ce2aSJacob Faibussowitsch       CHKERRMPI(MPI_Win_fence(0,*win));
5035b0d146aSStefano Zampini     }
5045b0d146aSStefano Zampini   }
5055b0d146aSStefano Zampini   link->inuse = PETSC_TRUE;
5065b0d146aSStefano Zampini   link->epoch = epoch;
50795fce210SBarry Smith   if (epoch) {
5085b0d146aSStefano Zampini     switch (sync) {
50995fce210SBarry Smith     case PETSCSF_WINDOW_SYNC_FENCE:
5105f80ce2aSJacob Faibussowitsch       CHKERRMPI(MPI_Win_fence(fenceassert,*win));
51195fce210SBarry Smith       break;
51295fce210SBarry Smith     case PETSCSF_WINDOW_SYNC_LOCK: /* Handled outside */
51395fce210SBarry Smith       break;
51495fce210SBarry Smith     case PETSCSF_WINDOW_SYNC_ACTIVE: {
51595fce210SBarry Smith       MPI_Group   ingroup,outgroup;
5165b0d146aSStefano Zampini       PetscMPIInt isize,osize;
5175b0d146aSStefano Zampini 
5185b0d146aSStefano Zampini       /* OpenMPI 4.0.2 with btl=vader does not like calling
5195b0d146aSStefano Zampini          - MPI_Win_complete when ogroup is empty
5205b0d146aSStefano Zampini          - MPI_Win_wait when igroup is empty
5215b0d146aSStefano Zampini          So, we do not even issue the corresponding start and post calls
5225b0d146aSStefano Zampini          The MPI standard (Sec. 11.5.2 of MPI 3.1) only requires that
5235b0d146aSStefano Zampini          start(outgroup) has a matching post(ingroup)
5245b0d146aSStefano Zampini          and this is guaranteed by PetscSF
5255b0d146aSStefano Zampini       */
5265f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscSFGetGroups(sf,&ingroup,&outgroup));
5275f80ce2aSJacob Faibussowitsch       CHKERRMPI(MPI_Group_size(ingroup,&isize));
5285f80ce2aSJacob Faibussowitsch       CHKERRMPI(MPI_Group_size(outgroup,&osize));
5295f80ce2aSJacob Faibussowitsch       if (isize) CHKERRMPI(MPI_Win_post(ingroup,postassert,*win));
5305f80ce2aSJacob Faibussowitsch       if (osize) CHKERRMPI(MPI_Win_start(outgroup,startassert,*win));
53195fce210SBarry Smith     } break;
53295fce210SBarry Smith     default: SETERRQ(PetscObjectComm((PetscObject)sf),PETSC_ERR_PLIB,"Unknown synchronization type");
53395fce210SBarry Smith     }
53495fce210SBarry Smith   }
53595fce210SBarry Smith   PetscFunctionReturn(0);
53695fce210SBarry Smith }
53795fce210SBarry Smith 
5385b0d146aSStefano Zampini /*
53995fce210SBarry Smith    PetscSFFindWindow - Finds a window that is already in use
54095fce210SBarry Smith 
54195fce210SBarry Smith    Not Collective
54295fce210SBarry Smith 
5434165533cSJose E. Roman    Input Parameters:
54495fce210SBarry Smith +  sf - star forest
54595fce210SBarry Smith .  unit - data type
54695fce210SBarry Smith -  array - array with which the window is associated
54795fce210SBarry Smith 
5484165533cSJose E. Roman    Output Parameters:
549684a874aSStefano Zampini +  win - window
550684a874aSStefano Zampini -  reqs - outstanding requests associated to the window
55195fce210SBarry Smith 
55295fce210SBarry Smith    Level: developer
55395fce210SBarry Smith 
55495fce210SBarry Smith .seealso: PetscSFGetWindow(), PetscSFRestoreWindow()
5555b0d146aSStefano Zampini */
556684a874aSStefano Zampini static PetscErrorCode PetscSFFindWindow(PetscSF sf,MPI_Datatype unit,const void *array,MPI_Win *win,MPI_Request **reqs)
55795fce210SBarry Smith {
55895fce210SBarry Smith   PetscSF_Window *w = (PetscSF_Window*)sf->data;
55995fce210SBarry Smith   PetscSFWinLink link;
56095fce210SBarry Smith 
56195fce210SBarry Smith   PetscFunctionBegin;
562c0cd0301SJed Brown   *win = MPI_WIN_NULL;
56395fce210SBarry Smith   for (link=w->wins; link; link=link->next) {
5645b0d146aSStefano Zampini     if (array == link->paddr) {
5652abc8c78SJacob Faibussowitsch 
5665f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscInfo(sf,"Window %" PETSC_MPI_WIN_FMT " of flavor %d for comm %" PETSC_MPI_COMM_FMT "\n",link->win,link->flavor,PetscObjectComm((PetscObject)sf)));
56795fce210SBarry Smith       *win = link->win;
568684a874aSStefano Zampini       *reqs = link->reqs;
56995fce210SBarry Smith       PetscFunctionReturn(0);
57095fce210SBarry Smith     }
57195fce210SBarry Smith   }
57295fce210SBarry Smith   SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Requested window not in use");
57395fce210SBarry Smith }
57495fce210SBarry Smith 
5755b0d146aSStefano Zampini /*
57695fce210SBarry Smith    PetscSFRestoreWindow - Restores a window obtained with PetscSFGetWindow()
57795fce210SBarry Smith 
57895fce210SBarry Smith    Collective
57995fce210SBarry Smith 
5804165533cSJose E. Roman    Input Parameters:
58195fce210SBarry Smith +  sf - star forest
58295fce210SBarry Smith .  unit - data type
58395fce210SBarry Smith .  array - array associated with window
5845b0d146aSStefano Zampini .  sync - type of synchronization PetscSFWindowSyncType
58595fce210SBarry Smith .  epoch - close an epoch, must match argument to PetscSFGetWindow()
5865b0d146aSStefano Zampini .  update - if we have to update the local window array
58795fce210SBarry Smith -  win - window
58895fce210SBarry Smith 
58995fce210SBarry Smith    Level: developer
59095fce210SBarry Smith 
59195fce210SBarry Smith .seealso: PetscSFFindWindow()
5925b0d146aSStefano Zampini */
5935b0d146aSStefano Zampini static PetscErrorCode PetscSFRestoreWindow(PetscSF sf,MPI_Datatype unit,void *array,PetscSFWindowSyncType sync,PetscBool epoch,PetscMPIInt fenceassert,PetscBool update,MPI_Win *win)
59495fce210SBarry Smith {
59595fce210SBarry Smith   PetscSF_Window          *w = (PetscSF_Window*)sf->data;
59695fce210SBarry Smith   PetscSFWinLink          *p,link;
5975b0d146aSStefano Zampini   PetscBool               reuse = PETSC_FALSE;
5985b0d146aSStefano Zampini   PetscSFWindowFlavorType flavor;
5995b0d146aSStefano Zampini   void*                   laddr;
6005b0d146aSStefano Zampini   size_t                  bytes;
60195fce210SBarry Smith 
60295fce210SBarry Smith   PetscFunctionBegin;
60395fce210SBarry Smith   for (p=&w->wins; *p; p=&(*p)->next) {
60495fce210SBarry Smith     link = *p;
60595fce210SBarry Smith     if (*win == link->win) {
6062c71b3e2SJacob Faibussowitsch       PetscCheckFalse(array != link->paddr,PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Matched window, but not array");
60795fce210SBarry Smith       if (epoch != link->epoch) {
608*28b400f6SJacob Faibussowitsch         PetscCheck(!epoch,PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"No epoch to end");
60995fce210SBarry Smith         else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Restoring window without ending epoch");
61095fce210SBarry Smith       }
6115b0d146aSStefano Zampini       laddr = link->addr;
6125b0d146aSStefano Zampini       flavor = link->flavor;
6135b0d146aSStefano Zampini       bytes = link->bytes;
6145b0d146aSStefano Zampini       if (flavor != PETSCSF_WINDOW_FLAVOR_CREATE) reuse = PETSC_TRUE;
6155b0d146aSStefano Zampini       else { *p = link->next; update = PETSC_FALSE; } /* remove from list */
61695fce210SBarry Smith       goto found;
61795fce210SBarry Smith     }
61895fce210SBarry Smith   }
61995fce210SBarry Smith   SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Requested window not in use");
62095fce210SBarry Smith 
62195fce210SBarry Smith found:
6225f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscInfo(sf,"Window %" PETSC_MPI_WIN_FMT " of flavor %d for comm %" PETSC_MPI_COMM_FMT "\n",link->win,link->flavor,PetscObjectComm((PetscObject)sf)));
62395fce210SBarry Smith   if (epoch) {
6245b0d146aSStefano Zampini     switch (sync) {
62595fce210SBarry Smith     case PETSCSF_WINDOW_SYNC_FENCE:
6265f80ce2aSJacob Faibussowitsch       CHKERRMPI(MPI_Win_fence(fenceassert,*win));
62795fce210SBarry Smith       break;
6285b0d146aSStefano Zampini     case PETSCSF_WINDOW_SYNC_LOCK: /* Handled outside */
6295b0d146aSStefano Zampini       break;
63095fce210SBarry Smith     case PETSCSF_WINDOW_SYNC_ACTIVE: {
6315b0d146aSStefano Zampini       MPI_Group   ingroup,outgroup;
6325b0d146aSStefano Zampini       PetscMPIInt isize,osize;
6335b0d146aSStefano Zampini 
6345b0d146aSStefano Zampini       /* OpenMPI 4.0.2 with btl=wader does not like calling
6355b0d146aSStefano Zampini          - MPI_Win_complete when ogroup is empty
6365b0d146aSStefano Zampini          - MPI_Win_wait when igroup is empty
6375b0d146aSStefano Zampini          The MPI standard (Sec. 11.5.2 of MPI 3.1) only requires that
6385b0d146aSStefano Zampini          - each process who issues a call to MPI_Win_start issues a call to MPI_Win_Complete
6395b0d146aSStefano Zampini          - each process who issues a call to MPI_Win_post issues a call to MPI_Win_Wait
6405b0d146aSStefano Zampini       */
6415f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscSFGetGroups(sf,&ingroup,&outgroup));
6425f80ce2aSJacob Faibussowitsch       CHKERRMPI(MPI_Group_size(ingroup,&isize));
6435f80ce2aSJacob Faibussowitsch       CHKERRMPI(MPI_Group_size(outgroup,&osize));
6445f80ce2aSJacob Faibussowitsch       if (osize) CHKERRMPI(MPI_Win_complete(*win));
6455f80ce2aSJacob Faibussowitsch       if (isize) CHKERRMPI(MPI_Win_wait(*win));
64695fce210SBarry Smith     } break;
64795fce210SBarry Smith     default: SETERRQ(PetscObjectComm((PetscObject)sf),PETSC_ERR_PLIB,"Unknown synchronization type");
64895fce210SBarry Smith     }
64995fce210SBarry Smith   }
6505b0d146aSStefano Zampini   if (update) {
6515b0d146aSStefano Zampini     if (sync == PETSCSF_WINDOW_SYNC_LOCK) {
6525f80ce2aSJacob Faibussowitsch       CHKERRMPI(MPI_Win_fence(MPI_MODE_NOPUT|MPI_MODE_NOSUCCEED,*win));
6535b0d146aSStefano Zampini     }
6545f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscMemcpy(array,laddr,sf->nroots*bytes));
6555b0d146aSStefano Zampini   }
6565b0d146aSStefano Zampini   link->epoch = PETSC_FALSE;
6575b0d146aSStefano Zampini   link->inuse = PETSC_FALSE;
6585b0d146aSStefano Zampini   link->paddr = NULL;
6595b0d146aSStefano Zampini   if (!reuse) {
6605f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscFree(link->dyn_target_addr));
6615f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscFree(link->reqs));
6625f80ce2aSJacob Faibussowitsch     CHKERRMPI(MPI_Win_free(&link->win));
6635f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscFree(link));
66495fce210SBarry Smith     *win = MPI_WIN_NULL;
6655b0d146aSStefano Zampini   }
66695fce210SBarry Smith   PetscFunctionReturn(0);
66795fce210SBarry Smith }
66895fce210SBarry Smith 
66995fce210SBarry Smith static PetscErrorCode PetscSFSetUp_Window(PetscSF sf)
67095fce210SBarry Smith {
67195fce210SBarry Smith   PetscSF_Window *w = (PetscSF_Window*)sf->data;
67295fce210SBarry Smith   MPI_Group      ingroup,outgroup;
67395fce210SBarry Smith 
67495fce210SBarry Smith   PetscFunctionBegin;
6755f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSFSetUpRanks(sf,MPI_GROUP_EMPTY));
6765b0d146aSStefano Zampini   if (!w->dynsf) {
6775b0d146aSStefano Zampini     PetscInt    i;
6785b0d146aSStefano Zampini     PetscSFNode *remotes;
6795b0d146aSStefano Zampini 
6805f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscMalloc1(sf->nranks,&remotes));
6815b0d146aSStefano Zampini     for (i=0;i<sf->nranks;i++) {
6825b0d146aSStefano Zampini       remotes[i].rank  = sf->ranks[i];
6835b0d146aSStefano Zampini       remotes[i].index = 0;
6845b0d146aSStefano Zampini     }
6855f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSFDuplicate(sf,PETSCSF_DUPLICATE_RANKS,&w->dynsf));
6865f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSFWindowSetFlavorType(w->dynsf,PETSCSF_WINDOW_FLAVOR_CREATE)); /* break recursion */
6875f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSFSetGraph(w->dynsf,1,sf->nranks,NULL,PETSC_OWN_POINTER,remotes,PETSC_OWN_POINTER));
6885f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscLogObjectParent((PetscObject)sf,(PetscObject)w->dynsf));
6895b0d146aSStefano Zampini   }
69095fce210SBarry Smith   switch (w->sync) {
69195fce210SBarry Smith   case PETSCSF_WINDOW_SYNC_ACTIVE:
6925f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSFGetGroups(sf,&ingroup,&outgroup));
69395fce210SBarry Smith   default:
69495fce210SBarry Smith     break;
69595fce210SBarry Smith   }
69695fce210SBarry Smith   PetscFunctionReturn(0);
69795fce210SBarry Smith }
69895fce210SBarry Smith 
6994416b707SBarry Smith static PetscErrorCode PetscSFSetFromOptions_Window(PetscOptionItems *PetscOptionsObject,PetscSF sf)
70095fce210SBarry Smith {
70195fce210SBarry Smith   PetscSF_Window          *w = (PetscSF_Window*)sf->data;
7025b0d146aSStefano Zampini   PetscSFWindowFlavorType flavor = w->flavor;
70395fce210SBarry Smith 
70495fce210SBarry Smith   PetscFunctionBegin;
7055f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscOptionsHead(PetscOptionsObject,"PetscSF Window options"));
7065f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscOptionsEnum("-sf_window_sync","synchronization type to use for PetscSF Window communication","PetscSFWindowSetSyncType",PetscSFWindowSyncTypes,(PetscEnum)w->sync,(PetscEnum*)&w->sync,NULL));
7075f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscOptionsEnum("-sf_window_flavor","flavor to use for PetscSF Window creation","PetscSFWindowSetFlavorType",PetscSFWindowFlavorTypes,(PetscEnum)flavor,(PetscEnum*)&flavor,NULL));
7085f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSFWindowSetFlavorType(sf,flavor));
7095f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscOptionsTail());
71095fce210SBarry Smith   PetscFunctionReturn(0);
71195fce210SBarry Smith }
71295fce210SBarry Smith 
71395fce210SBarry Smith static PetscErrorCode PetscSFReset_Window(PetscSF sf)
71495fce210SBarry Smith {
71595fce210SBarry Smith   PetscSF_Window  *w = (PetscSF_Window*)sf->data;
71695fce210SBarry Smith   PetscSFDataLink link,next;
71795fce210SBarry Smith   PetscSFWinLink  wlink,wnext;
71895fce210SBarry Smith   PetscInt        i;
71995fce210SBarry Smith 
72095fce210SBarry Smith   PetscFunctionBegin;
72195fce210SBarry Smith   for (link=w->link; link; link=next) {
72295fce210SBarry Smith     next = link->next;
7235f80ce2aSJacob Faibussowitsch     CHKERRMPI(MPI_Type_free(&link->unit));
72495fce210SBarry Smith     for (i=0; i<sf->nranks; i++) {
7255f80ce2aSJacob Faibussowitsch       CHKERRMPI(MPI_Type_free(&link->mine[i]));
7265f80ce2aSJacob Faibussowitsch       CHKERRMPI(MPI_Type_free(&link->remote[i]));
72795fce210SBarry Smith     }
7285f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscFree2(link->mine,link->remote));
7295f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscFree(link));
73095fce210SBarry Smith   }
73195fce210SBarry Smith   w->link = NULL;
73295fce210SBarry Smith   for (wlink=w->wins; wlink; wlink=wnext) {
73395fce210SBarry Smith     wnext = wlink->next;
734*28b400f6SJacob Faibussowitsch     PetscCheck(!wlink->inuse,PetscObjectComm((PetscObject)sf),PETSC_ERR_ARG_WRONGSTATE,"Window still in use with address %p",(void*)wlink->addr);
7355f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscFree(wlink->dyn_target_addr));
7365f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscFree(wlink->reqs));
7375f80ce2aSJacob Faibussowitsch     CHKERRMPI(MPI_Win_free(&wlink->win));
7385f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscFree(wlink));
73995fce210SBarry Smith   }
74095fce210SBarry Smith   w->wins = NULL;
7415f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSFDestroy(&w->dynsf));
7425b0d146aSStefano Zampini   if (w->info != MPI_INFO_NULL) {
7435f80ce2aSJacob Faibussowitsch     CHKERRMPI(MPI_Info_free(&w->info));
7445b0d146aSStefano Zampini   }
74595fce210SBarry Smith   PetscFunctionReturn(0);
74695fce210SBarry Smith }
74795fce210SBarry Smith 
74895fce210SBarry Smith static PetscErrorCode PetscSFDestroy_Window(PetscSF sf)
74995fce210SBarry Smith {
75095fce210SBarry Smith   PetscFunctionBegin;
7515f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSFReset_Window(sf));
7525f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscFree(sf->data));
7535f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectComposeFunction((PetscObject)sf,"PetscSFWindowSetSyncType_C",NULL));
7545f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectComposeFunction((PetscObject)sf,"PetscSFWindowGetSyncType_C",NULL));
7555f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectComposeFunction((PetscObject)sf,"PetscSFWindowSetFlavorType_C",NULL));
7565f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectComposeFunction((PetscObject)sf,"PetscSFWindowGetFlavorType_C",NULL));
7575f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectComposeFunction((PetscObject)sf,"PetscSFWindowSetInfo_C",NULL));
7585f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectComposeFunction((PetscObject)sf,"PetscSFWindowGetInfo_C",NULL));
75995fce210SBarry Smith   PetscFunctionReturn(0);
76095fce210SBarry Smith }
76195fce210SBarry Smith 
76295fce210SBarry Smith static PetscErrorCode PetscSFView_Window(PetscSF sf,PetscViewer viewer)
76395fce210SBarry Smith {
76495fce210SBarry Smith   PetscSF_Window    *w = (PetscSF_Window*)sf->data;
76595fce210SBarry Smith   PetscBool         iascii;
7665b0d146aSStefano Zampini   PetscViewerFormat format;
76795fce210SBarry Smith 
76895fce210SBarry Smith   PetscFunctionBegin;
7695f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscViewerGetFormat(viewer,&format));
7705f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii));
77195fce210SBarry Smith   if (iascii) {
7725f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscViewerASCIIPrintf(viewer,"  current flavor=%s synchronization=%s MultiSF sort=%s\n",PetscSFWindowFlavorTypes[w->flavor],PetscSFWindowSyncTypes[w->sync],sf->rankorder ? "rank-order" : "unordered"));
7735b0d146aSStefano Zampini     if (format == PETSC_VIEWER_ASCII_INFO_DETAIL) {
7745b0d146aSStefano Zampini       if (w->info != MPI_INFO_NULL) {
7755b0d146aSStefano Zampini         PetscMPIInt k,nkeys;
7765b0d146aSStefano Zampini         char        key[MPI_MAX_INFO_KEY], value[MPI_MAX_INFO_VAL];
7775b0d146aSStefano Zampini 
7785f80ce2aSJacob Faibussowitsch         CHKERRMPI(MPI_Info_get_nkeys(w->info,&nkeys));
7795f80ce2aSJacob Faibussowitsch         CHKERRQ(PetscViewerASCIIPrintf(viewer,"    current info with %d keys. Ordered key-value pairs follow:\n",nkeys));
7805b0d146aSStefano Zampini         for (k = 0; k < nkeys; k++) {
7815b0d146aSStefano Zampini           PetscMPIInt flag;
7825b0d146aSStefano Zampini 
7835f80ce2aSJacob Faibussowitsch           CHKERRMPI(MPI_Info_get_nthkey(w->info,k,key));
7845f80ce2aSJacob Faibussowitsch           CHKERRMPI(MPI_Info_get(w->info,key,MPI_MAX_INFO_VAL,value,&flag));
785*28b400f6SJacob Faibussowitsch           PetscCheck(flag,PETSC_COMM_SELF,PETSC_ERR_PLIB,"Missing key %s",key);
7865f80ce2aSJacob Faibussowitsch           CHKERRQ(PetscViewerASCIIPrintf(viewer,"      %s = %s\n",key,value));
7875b0d146aSStefano Zampini         }
7885b0d146aSStefano Zampini       } else {
7895f80ce2aSJacob Faibussowitsch         CHKERRQ(PetscViewerASCIIPrintf(viewer,"    current info=MPI_INFO_NULL\n"));
7905b0d146aSStefano Zampini       }
7915b0d146aSStefano Zampini     }
79295fce210SBarry Smith   }
79395fce210SBarry Smith   PetscFunctionReturn(0);
79495fce210SBarry Smith }
79595fce210SBarry Smith 
79695fce210SBarry Smith static PetscErrorCode PetscSFDuplicate_Window(PetscSF sf,PetscSFDuplicateOption opt,PetscSF newsf)
79795fce210SBarry Smith {
79895fce210SBarry Smith   PetscSF_Window        *w = (PetscSF_Window*)sf->data;
79995fce210SBarry Smith   PetscSFWindowSyncType synctype;
80095fce210SBarry Smith 
80195fce210SBarry Smith   PetscFunctionBegin;
80295fce210SBarry Smith   synctype = w->sync;
80395fce210SBarry Smith   /* HACK: Must use FENCE or LOCK when called from PetscSFGetGroups() because ACTIVE here would cause recursion. */
8045b0d146aSStefano Zampini   if (!sf->setupcalled) synctype = PETSCSF_WINDOW_SYNC_LOCK;
8055f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSFWindowSetSyncType(newsf,synctype));
8065f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSFWindowSetFlavorType(newsf,w->flavor));
8075f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSFWindowSetInfo(newsf,w->info));
80895fce210SBarry Smith   PetscFunctionReturn(0);
80995fce210SBarry Smith }
81095fce210SBarry Smith 
811ad227feaSJunchao Zhang static PetscErrorCode PetscSFBcastBegin_Window(PetscSF sf,MPI_Datatype unit,PetscMemType rootmtype,const void *rootdata,PetscMemType leafmtype,void *leafdata,MPI_Op op)
81295fce210SBarry Smith {
81395fce210SBarry Smith   PetscSF_Window     *w = (PetscSF_Window*)sf->data;
81495fce210SBarry Smith   PetscInt           i,nranks;
81595fce210SBarry Smith   const PetscMPIInt  *ranks;
8165b0d146aSStefano Zampini   const MPI_Aint     *target_disp;
81795fce210SBarry Smith   const MPI_Datatype *mine,*remote;
818684a874aSStefano Zampini   MPI_Request        *reqs;
81995fce210SBarry Smith   MPI_Win            win;
82095fce210SBarry Smith 
82195fce210SBarry Smith   PetscFunctionBegin;
8222c71b3e2SJacob Faibussowitsch   PetscCheckFalse(op != MPI_REPLACE,PetscObjectComm((PetscObject)sf), PETSC_ERR_SUP, "PetscSFBcastBegin_Window with op!=MPI_REPLACE has not been implemented");
8235f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSFGetRootRanks(sf,&nranks,&ranks,NULL,NULL,NULL));
8245f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSFWindowGetDataTypes(sf,unit,&mine,&remote));
8255f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSFGetWindow(sf,unit,(void*)rootdata,w->sync,PETSC_TRUE,MPI_MODE_NOPUT|MPI_MODE_NOPRECEDE,MPI_MODE_NOPUT,0,&target_disp,&reqs,&win));
82695fce210SBarry Smith   for (i=0; i<nranks; i++) {
8275b0d146aSStefano Zampini     MPI_Aint tdp = target_disp ? target_disp[i] : 0;
8285b0d146aSStefano Zampini 
829684a874aSStefano Zampini     if (w->sync == PETSCSF_WINDOW_SYNC_LOCK) {
8305f80ce2aSJacob Faibussowitsch       CHKERRMPI(MPI_Win_lock(MPI_LOCK_SHARED,ranks[i],MPI_MODE_NOCHECK,win));
831684a874aSStefano Zampini #if defined(PETSC_HAVE_MPI_RGET)
8325f80ce2aSJacob Faibussowitsch       CHKERRMPI(MPI_Rget(leafdata,1,mine[i],ranks[i],tdp,1,remote[i],win,&reqs[i]));
833684a874aSStefano Zampini #else
8345f80ce2aSJacob Faibussowitsch       CHKERRMPI(MPI_Get(leafdata,1,mine[i],ranks[i],tdp,1,remote[i],win));
835684a874aSStefano Zampini #endif
836684a874aSStefano Zampini     } else {
8375f80ce2aSJacob Faibussowitsch       CHKERRMPI(MPI_Get(leafdata,1,mine[i],ranks[i],tdp,1,remote[i],win));
838684a874aSStefano Zampini     }
83995fce210SBarry Smith   }
84095fce210SBarry Smith   PetscFunctionReturn(0);
84195fce210SBarry Smith }
84295fce210SBarry Smith 
843ad227feaSJunchao Zhang PetscErrorCode PetscSFBcastEnd_Window(PetscSF sf,MPI_Datatype unit,const void *rootdata,void *leafdata,MPI_Op op)
84495fce210SBarry Smith {
8455b0d146aSStefano Zampini   PetscSF_Window *w = (PetscSF_Window*)sf->data;
84695fce210SBarry Smith   MPI_Win        win;
8474b9acda6SJunchao Zhang   MPI_Request    *reqs = NULL;
84895fce210SBarry Smith 
84995fce210SBarry Smith   PetscFunctionBegin;
8505f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSFFindWindow(sf,unit,rootdata,&win,&reqs));
8515f80ce2aSJacob Faibussowitsch   if (reqs) CHKERRMPI(MPI_Waitall(sf->nranks,reqs,MPI_STATUSES_IGNORE));
852684a874aSStefano Zampini   if (w->sync == PETSCSF_WINDOW_SYNC_LOCK) {
853684a874aSStefano Zampini     PetscInt           i,nranks;
854684a874aSStefano Zampini     const PetscMPIInt  *ranks;
855684a874aSStefano Zampini 
8565f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSFGetRootRanks(sf,&nranks,&ranks,NULL,NULL,NULL));
857684a874aSStefano Zampini     for (i=0; i<nranks; i++) {
8585f80ce2aSJacob Faibussowitsch       CHKERRMPI(MPI_Win_unlock(ranks[i],win));
859684a874aSStefano Zampini     }
860684a874aSStefano Zampini   }
8615f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSFRestoreWindow(sf,unit,(void*)rootdata,w->sync,PETSC_TRUE,MPI_MODE_NOSTORE|MPI_MODE_NOSUCCEED,PETSC_FALSE,&win));
86295fce210SBarry Smith   PetscFunctionReturn(0);
86395fce210SBarry Smith }
86495fce210SBarry Smith 
865eb02082bSJunchao Zhang PetscErrorCode PetscSFReduceBegin_Window(PetscSF sf,MPI_Datatype unit,PetscMemType leafmtype,const void *leafdata,PetscMemType rootmtype,void *rootdata,MPI_Op op)
86695fce210SBarry Smith {
86795fce210SBarry Smith   PetscSF_Window     *w = (PetscSF_Window*)sf->data;
86895fce210SBarry Smith   PetscInt           i,nranks;
86995fce210SBarry Smith   const PetscMPIInt  *ranks;
8705b0d146aSStefano Zampini   const MPI_Aint     *target_disp;
87195fce210SBarry Smith   const MPI_Datatype *mine,*remote;
87295fce210SBarry Smith   MPI_Win            win;
87395fce210SBarry Smith 
87495fce210SBarry Smith   PetscFunctionBegin;
8755f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSFGetRootRanks(sf,&nranks,&ranks,NULL,NULL,NULL));
8765f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSFWindowGetDataTypes(sf,unit,&mine,&remote));
8775f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSFWindowOpTranslate(&op));
8785f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSFGetWindow(sf,unit,rootdata,w->sync,PETSC_TRUE,MPI_MODE_NOPRECEDE,0,0,&target_disp,NULL,&win));
87995fce210SBarry Smith   for (i=0; i<nranks; i++) {
8805b0d146aSStefano Zampini     MPI_Aint tdp = target_disp ? target_disp[i] : 0;
8815b0d146aSStefano Zampini 
8825f80ce2aSJacob Faibussowitsch     if (w->sync == PETSCSF_WINDOW_SYNC_LOCK) CHKERRMPI(MPI_Win_lock(MPI_LOCK_SHARED,ranks[i],MPI_MODE_NOCHECK,win));
8835f80ce2aSJacob Faibussowitsch     CHKERRMPI(MPI_Accumulate((void*)leafdata,1,mine[i],ranks[i],tdp,1,remote[i],op,win));
8845f80ce2aSJacob Faibussowitsch     if (w->sync == PETSCSF_WINDOW_SYNC_LOCK) CHKERRMPI(MPI_Win_unlock(ranks[i],win));
88595fce210SBarry Smith   }
88695fce210SBarry Smith   PetscFunctionReturn(0);
88795fce210SBarry Smith }
88895fce210SBarry Smith 
88900816365SJunchao Zhang static PetscErrorCode PetscSFReduceEnd_Window(PetscSF sf,MPI_Datatype unit,const void *leafdata,void *rootdata,MPI_Op op)
89095fce210SBarry Smith {
89195fce210SBarry Smith   PetscSF_Window *w = (PetscSF_Window*)sf->data;
89295fce210SBarry Smith   MPI_Win        win;
8934b9acda6SJunchao Zhang   MPI_Request    *reqs = NULL;
89495fce210SBarry Smith 
89595fce210SBarry Smith   PetscFunctionBegin;
8965f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSFFindWindow(sf,unit,rootdata,&win,&reqs));
8975f80ce2aSJacob Faibussowitsch   if (reqs) CHKERRMPI(MPI_Waitall(sf->nranks,reqs,MPI_STATUSES_IGNORE));
8985f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSFRestoreWindow(sf,unit,rootdata,w->sync,PETSC_TRUE,MPI_MODE_NOSUCCEED,PETSC_TRUE,&win));
89995fce210SBarry Smith   PetscFunctionReturn(0);
90095fce210SBarry Smith }
9015b0d146aSStefano Zampini 
902eb02082bSJunchao Zhang static PetscErrorCode PetscSFFetchAndOpBegin_Window(PetscSF sf,MPI_Datatype unit,PetscMemType rootmtype,void *rootdata,PetscMemType leafmtype,const void *leafdata,void *leafupdate,MPI_Op op)
90395fce210SBarry Smith {
90495fce210SBarry Smith   PetscInt           i,nranks;
90595fce210SBarry Smith   const PetscMPIInt  *ranks;
90695fce210SBarry Smith   const MPI_Datatype *mine,*remote;
9075b0d146aSStefano Zampini   const MPI_Aint     *target_disp;
90895fce210SBarry Smith   MPI_Win            win;
9095b0d146aSStefano Zampini   PetscSF_Window     *w = (PetscSF_Window*)sf->data;
9105b0d146aSStefano Zampini #if !defined(PETSC_HAVE_MPI_GET_ACCUMULATE)
9115b0d146aSStefano Zampini   PetscSFWindowFlavorType oldf;
9125b0d146aSStefano Zampini #endif
91395fce210SBarry Smith 
91495fce210SBarry Smith   PetscFunctionBegin;
9155f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSFGetRootRanks(sf,&nranks,&ranks,NULL,NULL,NULL));
9165f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSFWindowGetDataTypes(sf,unit,&mine,&remote));
9175f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSFWindowOpTranslate(&op));
9185b0d146aSStefano Zampini #if !defined(PETSC_HAVE_MPI_GET_ACCUMULATE)
9195b0d146aSStefano Zampini   /* FetchAndOp without MPI_Get_Accumulate requires locking.
9205b0d146aSStefano Zampini      we create a new window every time to not interfere with user-defined MPI_Info which may have used "no_locks"="true" */
9215b0d146aSStefano Zampini   oldf = w->flavor;
9225b0d146aSStefano Zampini   w->flavor = PETSCSF_WINDOW_FLAVOR_CREATE;
9235f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSFGetWindow(sf,unit,rootdata,PETSCSF_WINDOW_SYNC_LOCK,PETSC_FALSE,0,0,0,&target_disp,NULL,&win));
9245b0d146aSStefano Zampini #else
9255f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSFGetWindow(sf,unit,rootdata,w->sync,PETSC_TRUE,MPI_MODE_NOPRECEDE,0,0,&target_disp,NULL,&win));
9265b0d146aSStefano Zampini #endif
9275b0d146aSStefano Zampini   for (i=0; i<nranks; i++) {
9285b0d146aSStefano Zampini     MPI_Aint tdp = target_disp ? target_disp[i] : 0;
9295b0d146aSStefano Zampini 
9305b0d146aSStefano Zampini #if !defined(PETSC_HAVE_MPI_GET_ACCUMULATE)
9315f80ce2aSJacob Faibussowitsch     CHKERRMPI(MPI_Win_lock(MPI_LOCK_EXCLUSIVE,ranks[i],0,win));
9325f80ce2aSJacob Faibussowitsch     CHKERRMPI(MPI_Get(leafupdate,1,mine[i],ranks[i],tdp,1,remote[i],win));
9335f80ce2aSJacob Faibussowitsch     CHKERRMPI(MPI_Accumulate((void*)leafdata,1,mine[i],ranks[i],tdp,1,remote[i],op,win));
9345f80ce2aSJacob Faibussowitsch     CHKERRMPI(MPI_Win_unlock(ranks[i],win));
9355b0d146aSStefano Zampini #else
9365f80ce2aSJacob Faibussowitsch     if (w->sync == PETSCSF_WINDOW_SYNC_LOCK) CHKERRMPI(MPI_Win_lock(MPI_LOCK_SHARED,ranks[i],0,win));
9375f80ce2aSJacob Faibussowitsch     CHKERRMPI(MPI_Get_accumulate((void*)leafdata,1,mine[i],leafupdate,1,mine[i],ranks[i],tdp,1,remote[i],op,win));
9385f80ce2aSJacob Faibussowitsch     if (w->sync == PETSCSF_WINDOW_SYNC_LOCK) CHKERRMPI(MPI_Win_unlock(ranks[i],win));
9395b0d146aSStefano Zampini #endif
9405b0d146aSStefano Zampini   }
9415b0d146aSStefano Zampini #if !defined(PETSC_HAVE_MPI_GET_ACCUMULATE)
9425b0d146aSStefano Zampini   w->flavor = oldf;
9435b0d146aSStefano Zampini #endif
94495fce210SBarry Smith   PetscFunctionReturn(0);
94595fce210SBarry Smith }
94695fce210SBarry Smith 
94700816365SJunchao Zhang static PetscErrorCode PetscSFFetchAndOpEnd_Window(PetscSF sf,MPI_Datatype unit,void *rootdata,const void *leafdata,void *leafupdate,MPI_Op op)
94895fce210SBarry Smith {
94995fce210SBarry Smith   MPI_Win        win;
9505b0d146aSStefano Zampini #if defined(PETSC_HAVE_MPI_GET_ACCUMULATE)
9515b0d146aSStefano Zampini   PetscSF_Window *w = (PetscSF_Window*)sf->data;
9525b0d146aSStefano Zampini #endif
9534b9acda6SJunchao Zhang   MPI_Request    *reqs = NULL;
95495fce210SBarry Smith 
95595fce210SBarry Smith   PetscFunctionBegin;
9565f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSFFindWindow(sf,unit,rootdata,&win,&reqs));
9575f80ce2aSJacob Faibussowitsch   if (reqs) CHKERRMPI(MPI_Waitall(sf->nranks,reqs,MPI_STATUSES_IGNORE));
9585b0d146aSStefano Zampini #if defined(PETSC_HAVE_MPI_GET_ACCUMULATE)
9595f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSFRestoreWindow(sf,unit,rootdata,w->sync,PETSC_TRUE,MPI_MODE_NOSUCCEED,PETSC_TRUE,&win));
9605b0d146aSStefano Zampini #else
9615f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSFRestoreWindow(sf,unit,rootdata,PETSCSF_WINDOW_SYNC_LOCK,PETSC_FALSE,0,PETSC_TRUE,&win));
9625b0d146aSStefano Zampini #endif
96395fce210SBarry Smith   PetscFunctionReturn(0);
96495fce210SBarry Smith }
96595fce210SBarry Smith 
966dec1416fSJunchao Zhang PETSC_INTERN PetscErrorCode PetscSFCreate_Window(PetscSF sf)
96795fce210SBarry Smith {
96895fce210SBarry Smith   PetscSF_Window *w = (PetscSF_Window*)sf->data;
96995fce210SBarry Smith 
97095fce210SBarry Smith   PetscFunctionBegin;
97195fce210SBarry Smith   sf->ops->SetUp           = PetscSFSetUp_Window;
97295fce210SBarry Smith   sf->ops->SetFromOptions  = PetscSFSetFromOptions_Window;
97395fce210SBarry Smith   sf->ops->Reset           = PetscSFReset_Window;
97495fce210SBarry Smith   sf->ops->Destroy         = PetscSFDestroy_Window;
97595fce210SBarry Smith   sf->ops->View            = PetscSFView_Window;
97695fce210SBarry Smith   sf->ops->Duplicate       = PetscSFDuplicate_Window;
977ad227feaSJunchao Zhang   sf->ops->BcastBegin      = PetscSFBcastBegin_Window;
978ad227feaSJunchao Zhang   sf->ops->BcastEnd        = PetscSFBcastEnd_Window;
97995fce210SBarry Smith   sf->ops->ReduceBegin     = PetscSFReduceBegin_Window;
98095fce210SBarry Smith   sf->ops->ReduceEnd       = PetscSFReduceEnd_Window;
98195fce210SBarry Smith   sf->ops->FetchAndOpBegin = PetscSFFetchAndOpBegin_Window;
98295fce210SBarry Smith   sf->ops->FetchAndOpEnd   = PetscSFFetchAndOpEnd_Window;
98395fce210SBarry Smith 
9845f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscNewLog(sf,&w));
98595fce210SBarry Smith   sf->data  = (void*)w;
98695fce210SBarry Smith   w->sync   = PETSCSF_WINDOW_SYNC_FENCE;
9875b0d146aSStefano Zampini   w->flavor = PETSCSF_WINDOW_FLAVOR_CREATE;
9885b0d146aSStefano Zampini   w->info   = MPI_INFO_NULL;
98995fce210SBarry Smith 
9905f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectComposeFunction((PetscObject)sf,"PetscSFWindowSetSyncType_C",PetscSFWindowSetSyncType_Window));
9915f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectComposeFunction((PetscObject)sf,"PetscSFWindowGetSyncType_C",PetscSFWindowGetSyncType_Window));
9925f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectComposeFunction((PetscObject)sf,"PetscSFWindowSetFlavorType_C",PetscSFWindowSetFlavorType_Window));
9935f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectComposeFunction((PetscObject)sf,"PetscSFWindowGetFlavorType_C",PetscSFWindowGetFlavorType_Window));
9945f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectComposeFunction((PetscObject)sf,"PetscSFWindowSetInfo_C",PetscSFWindowSetInfo_Window));
9955f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectComposeFunction((PetscObject)sf,"PetscSFWindowGetInfo_C",PetscSFWindowGetInfo_Window));
99695fce210SBarry Smith 
99795fce210SBarry Smith #if defined(OMPI_MAJOR_VERSION) && (OMPI_MAJOR_VERSION < 1 || (OMPI_MAJOR_VERSION == 1 && OMPI_MINOR_VERSION <= 6))
99895fce210SBarry Smith   {
99995fce210SBarry Smith     PetscBool ackbug = PETSC_FALSE;
10005f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscOptionsGetBool(NULL,NULL,"-acknowledge_ompi_onesided_bug",&ackbug,NULL));
100195fce210SBarry Smith     if (ackbug) {
10025f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscInfo(sf,"Acknowledged Open MPI bug, proceeding anyway. Expect memory corruption.\n"));
100395fce210SBarry 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");
100495fce210SBarry Smith   }
100595fce210SBarry Smith #endif
100695fce210SBarry Smith   PetscFunctionReturn(0);
100795fce210SBarry Smith }
1008