xref: /petsc/src/vec/is/sf/impls/window/sfwindow.c (revision 00816365229eff0fcb3567887feb4c4abe2b0e86)
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 
3595fce210SBarry Smith const char *const PetscSFWindowSyncTypes[] = {"FENCE","LOCK","ACTIVE","PetscSFWindowSyncType","PETSCSF_WINDOW_SYNC_",0};
365b0d146aSStefano Zampini const char *const PetscSFWindowFlavorTypes[] = {"CREATE","DYNAMIC","ALLOCATE","SHARED","PetscSFWindowFlavorType","PETSCSF_WINDOW_FLAVOR_",0};
3795fce210SBarry Smith 
38b2566f29SBarry Smith /* Built-in MPI_Ops act elementwise inside MPI_Accumulate, but cannot be used with composite types inside collectives (MPIU_Allreduce) */
3995fce210SBarry Smith static PetscErrorCode PetscSFWindowOpTranslate(MPI_Op *op)
4095fce210SBarry Smith {
4195fce210SBarry Smith   PetscFunctionBegin;
4295fce210SBarry Smith   if (*op == MPIU_SUM) *op = MPI_SUM;
4395fce210SBarry Smith   else if (*op == MPIU_MAX) *op = MPI_MAX;
4495fce210SBarry Smith   else if (*op == MPIU_MIN) *op = MPI_MIN;
4595fce210SBarry Smith   PetscFunctionReturn(0);
4695fce210SBarry Smith }
4795fce210SBarry Smith 
4895fce210SBarry Smith /*@C
4995fce210SBarry Smith    PetscSFWindowGetDataTypes - gets composite local and remote data types for each rank
5095fce210SBarry Smith 
5195fce210SBarry Smith    Not Collective
5295fce210SBarry Smith 
5395fce210SBarry Smith    Input Arguments:
5495fce210SBarry Smith +  sf - star forest
5595fce210SBarry Smith -  unit - data type for each node
5695fce210SBarry Smith 
5795fce210SBarry Smith    Output Arguments:
5895fce210SBarry Smith +  localtypes - types describing part of local leaf buffer referencing each remote rank
5995fce210SBarry Smith -  remotetypes - types describing part of remote root buffer referenced for each remote rank
6095fce210SBarry Smith 
6195fce210SBarry Smith    Level: developer
6295fce210SBarry Smith 
6395fce210SBarry Smith .seealso: PetscSFSetGraph(), PetscSFView()
6495fce210SBarry Smith @*/
6595fce210SBarry Smith static PetscErrorCode PetscSFWindowGetDataTypes(PetscSF sf,MPI_Datatype unit,const MPI_Datatype **localtypes,const MPI_Datatype **remotetypes)
6695fce210SBarry Smith {
6795fce210SBarry Smith   PetscSF_Window    *w = (PetscSF_Window*)sf->data;
6895fce210SBarry Smith   PetscErrorCode    ierr;
6995fce210SBarry Smith   PetscSFDataLink   link;
7095fce210SBarry Smith   PetscInt          i,nranks;
7195fce210SBarry Smith   const PetscInt    *roffset,*rmine,*rremote;
7295fce210SBarry Smith   const PetscMPIInt *ranks;
7395fce210SBarry Smith 
7495fce210SBarry Smith   PetscFunctionBegin;
7595fce210SBarry Smith   /* Look for types in cache */
7695fce210SBarry Smith   for (link=w->link; link; link=link->next) {
7795fce210SBarry Smith     PetscBool match;
7895fce210SBarry Smith     ierr = MPIPetsc_Type_compare(unit,link->unit,&match);CHKERRQ(ierr);
7995fce210SBarry Smith     if (match) {
8095fce210SBarry Smith       *localtypes  = link->mine;
8195fce210SBarry Smith       *remotetypes = link->remote;
8295fce210SBarry Smith       PetscFunctionReturn(0);
8395fce210SBarry Smith     }
8495fce210SBarry Smith   }
8595fce210SBarry Smith 
8695fce210SBarry Smith   /* Create new composite types for each send rank */
87dec1416fSJunchao Zhang   ierr = PetscSFGetRootRanks(sf,&nranks,&ranks,&roffset,&rmine,&rremote);CHKERRQ(ierr);
8895dccacaSBarry Smith   ierr = PetscNew(&link);CHKERRQ(ierr);
8995fce210SBarry Smith   ierr = MPI_Type_dup(unit,&link->unit);CHKERRQ(ierr);
90dcca6d9dSJed Brown   ierr = PetscMalloc2(nranks,&link->mine,nranks,&link->remote);CHKERRQ(ierr);
9195fce210SBarry Smith   for (i=0; i<nranks; i++) {
925b0d146aSStefano Zampini     PetscInt    rcount = roffset[i+1] - roffset[i];
9395fce210SBarry Smith     PetscMPIInt *rmine,*rremote;
9495fce210SBarry Smith #if !defined(PETSC_USE_64BIT_INDICES)
9595fce210SBarry Smith     rmine   = sf->rmine + sf->roffset[i];
9695fce210SBarry Smith     rremote = sf->rremote + sf->roffset[i];
9795fce210SBarry Smith #else
9895fce210SBarry Smith     PetscInt j;
99dcca6d9dSJed Brown     ierr = PetscMalloc2(rcount,&rmine,rcount,&rremote);CHKERRQ(ierr);
10095fce210SBarry Smith     for (j=0; j<rcount; j++) {
10195fce210SBarry Smith       ierr = PetscMPIIntCast(sf->rmine[sf->roffset[i]+j],rmine+j);CHKERRQ(ierr);
10295fce210SBarry Smith       ierr = PetscMPIIntCast(sf->rremote[sf->roffset[i]+j],rremote+j);CHKERRQ(ierr);
10395fce210SBarry Smith     }
10495fce210SBarry Smith #endif
1055b0d146aSStefano Zampini 
10695fce210SBarry Smith     ierr = MPI_Type_create_indexed_block(rcount,1,rmine,link->unit,&link->mine[i]);CHKERRQ(ierr);
10795fce210SBarry Smith     ierr = MPI_Type_create_indexed_block(rcount,1,rremote,link->unit,&link->remote[i]);CHKERRQ(ierr);
10895fce210SBarry Smith #if defined(PETSC_USE_64BIT_INDICES)
10995fce210SBarry Smith     ierr = PetscFree2(rmine,rremote);CHKERRQ(ierr);
11095fce210SBarry Smith #endif
11195fce210SBarry Smith     ierr = MPI_Type_commit(&link->mine[i]);CHKERRQ(ierr);
11295fce210SBarry Smith     ierr = MPI_Type_commit(&link->remote[i]);CHKERRQ(ierr);
11395fce210SBarry Smith   }
11495fce210SBarry Smith   link->next = w->link;
11595fce210SBarry Smith   w->link    = link;
11695fce210SBarry Smith 
11795fce210SBarry Smith   *localtypes  = link->mine;
11895fce210SBarry Smith   *remotetypes = link->remote;
11995fce210SBarry Smith   PetscFunctionReturn(0);
12095fce210SBarry Smith }
12195fce210SBarry Smith 
12295fce210SBarry Smith /*@C
1235b0d146aSStefano Zampini    PetscSFWindowSetFlavorType - Set flavor type for MPI_Win creation
1245b0d146aSStefano Zampini 
1255b0d146aSStefano Zampini    Logically Collective
1265b0d146aSStefano Zampini 
1275b0d146aSStefano Zampini    Input Arguments:
1285b0d146aSStefano Zampini +  sf - star forest for communication
1295b0d146aSStefano Zampini -  flavor - flavor type
1305b0d146aSStefano Zampini 
1315b0d146aSStefano Zampini    Options Database Key:
1325b0d146aSStefano Zampini .  -sf_window_flavor <flavor> - sets the flavor type CREATE, DYNAMIC, ALLOCATE or SHARED (see PetscSFWindowFlavorType)
1335b0d146aSStefano Zampini 
1345b0d146aSStefano Zampini    Level: advanced
1355b0d146aSStefano Zampini 
1365b0d146aSStefano Zampini    Notes: Windows reusage follow this rules:
1375b0d146aSStefano Zampini 
1385b0d146aSStefano Zampini      PETSCSF_WINDOW_FLAVOR_CREATE: creates a new window every time, uses MPI_Win_create
1395b0d146aSStefano Zampini 
1405b0d146aSStefano Zampini      PETSCSF_WINDOW_FLAVOR_DYNAMIC: uses MPI_Win_create_dynamic/MPI_Win_attach and tries to reuse windows by comparing the root array. Intended to be used on repeated applications of the same SF, e.g.
1415b0d146aSStefano Zampini        for i=1 to K
1425b0d146aSStefano Zampini          PetscSFOperationBegin(rootdata1,leafdata_whatever);
1435b0d146aSStefano Zampini          PetscSFOperationEnd(rootdata1,leafdata_whatever);
1445b0d146aSStefano Zampini          ...
1455b0d146aSStefano Zampini          PetscSFOperationBegin(rootdataN,leafdata_whatever);
1465b0d146aSStefano Zampini          PetscSFOperationEnd(rootdataN,leafdata_whatever);
1475b0d146aSStefano Zampini        endfor
1485b0d146aSStefano Zampini        The following pattern will instead raise an error
1495b0d146aSStefano Zampini          PetscSFOperationBegin(rootdata1,leafdata_whatever);
1505b0d146aSStefano Zampini          PetscSFOperationEnd(rootdata1,leafdata_whatever);
1515b0d146aSStefano Zampini          PetscSFOperationBegin(rank ? rootdata1 : rootdata2,leafdata_whatever);
1525b0d146aSStefano Zampini          PetscSFOperationEnd(rank ? rootdata1 : rootdata2,leafdata_whatever);
1535b0d146aSStefano Zampini 
1545b0d146aSStefano Zampini      PETSCSF_WINDOW_FLAVOR_ALLOCATE: uses MPI_Win_allocate, reuses any pre-existing window which fits the data and it is not in use
1555b0d146aSStefano Zampini 
1565b0d146aSStefano Zampini      PETSCSF_WINDOW_FLAVOR_SHARED: uses MPI_Win_allocate_shared, reusage policy as for PETSCSF_WINDOW_FLAVOR_ALLOCATE
1575b0d146aSStefano Zampini 
1585b0d146aSStefano Zampini .seealso: PetscSFSetFromOptions(), PetscSFWindowGetFlavorType()
1595b0d146aSStefano Zampini @*/
1605b0d146aSStefano Zampini PetscErrorCode PetscSFWindowSetFlavorType(PetscSF sf,PetscSFWindowFlavorType flavor)
1615b0d146aSStefano Zampini {
1625b0d146aSStefano Zampini   PetscErrorCode ierr;
1635b0d146aSStefano Zampini 
1645b0d146aSStefano Zampini   PetscFunctionBegin;
1655b0d146aSStefano Zampini   PetscValidHeaderSpecific(sf,PETSCSF_CLASSID,1);
1665b0d146aSStefano Zampini   PetscValidLogicalCollectiveEnum(sf,flavor,2);
1675b0d146aSStefano Zampini   ierr = PetscTryMethod(sf,"PetscSFWindowSetFlavorType_C",(PetscSF,PetscSFWindowFlavorType),(sf,flavor));CHKERRQ(ierr);
1685b0d146aSStefano Zampini   PetscFunctionReturn(0);
1695b0d146aSStefano Zampini }
1705b0d146aSStefano Zampini 
1715b0d146aSStefano Zampini static PetscErrorCode PetscSFWindowSetFlavorType_Window(PetscSF sf,PetscSFWindowFlavorType flavor)
1725b0d146aSStefano Zampini {
1735b0d146aSStefano Zampini   PetscSF_Window *w = (PetscSF_Window*)sf->data;
1745b0d146aSStefano Zampini 
1755b0d146aSStefano Zampini   PetscFunctionBegin;
1765b0d146aSStefano Zampini   w->flavor = flavor;
1775b0d146aSStefano Zampini   PetscFunctionReturn(0);
1785b0d146aSStefano Zampini }
1795b0d146aSStefano Zampini 
1805b0d146aSStefano Zampini /*@C
1815b0d146aSStefano Zampini    PetscSFWindowGetFlavorType - Get flavor type for PetscSF communication
1825b0d146aSStefano Zampini 
1835b0d146aSStefano Zampini    Logically Collective
1845b0d146aSStefano Zampini 
1855b0d146aSStefano Zampini    Input Argument:
1865b0d146aSStefano Zampini .  sf - star forest for communication
1875b0d146aSStefano Zampini 
1885b0d146aSStefano Zampini    Output Argument:
1895b0d146aSStefano Zampini .  flavor - flavor type
1905b0d146aSStefano Zampini 
1915b0d146aSStefano Zampini    Level: advanced
1925b0d146aSStefano Zampini 
1935b0d146aSStefano Zampini .seealso: PetscSFSetFromOptions(), PetscSFWindowSetFlavorType()
1945b0d146aSStefano Zampini @*/
1955b0d146aSStefano Zampini PetscErrorCode PetscSFWindowGetFlavorType(PetscSF sf,PetscSFWindowFlavorType *flavor)
1965b0d146aSStefano Zampini {
1975b0d146aSStefano Zampini   PetscErrorCode ierr;
1985b0d146aSStefano Zampini 
1995b0d146aSStefano Zampini   PetscFunctionBegin;
2005b0d146aSStefano Zampini   PetscValidHeaderSpecific(sf,PETSCSF_CLASSID,1);
2015b0d146aSStefano Zampini   PetscValidPointer(flavor,2);
2025b0d146aSStefano Zampini   ierr = PetscUseMethod(sf,"PetscSFWindowGetFlavorType_C",(PetscSF,PetscSFWindowFlavorType*),(sf,flavor));CHKERRQ(ierr);
2035b0d146aSStefano Zampini   PetscFunctionReturn(0);
2045b0d146aSStefano Zampini }
2055b0d146aSStefano Zampini 
2065b0d146aSStefano Zampini static PetscErrorCode PetscSFWindowGetFlavorType_Window(PetscSF sf,PetscSFWindowFlavorType *flavor)
2075b0d146aSStefano Zampini {
2085b0d146aSStefano Zampini   PetscSF_Window *w = (PetscSF_Window*)sf->data;
2095b0d146aSStefano Zampini 
2105b0d146aSStefano Zampini   PetscFunctionBegin;
2115b0d146aSStefano Zampini   *flavor = w->flavor;
2125b0d146aSStefano Zampini   PetscFunctionReturn(0);
2135b0d146aSStefano Zampini }
2145b0d146aSStefano Zampini 
2155b0d146aSStefano Zampini /*@C
2165b0d146aSStefano Zampini    PetscSFWindowSetSyncType - Set synchronization type for PetscSF communication
21795fce210SBarry Smith 
21895fce210SBarry Smith    Logically Collective
21995fce210SBarry Smith 
22095fce210SBarry Smith    Input Arguments:
22195fce210SBarry Smith +  sf - star forest for communication
22295fce210SBarry Smith -  sync - synchronization type
22395fce210SBarry Smith 
22495fce210SBarry Smith    Options Database Key:
22560263706SJed Brown .  -sf_window_sync <sync> - sets the synchronization type FENCE, LOCK, or ACTIVE (see PetscSFWindowSyncType)
22695fce210SBarry Smith 
22795fce210SBarry Smith    Level: advanced
22895fce210SBarry Smith 
22995fce210SBarry Smith .seealso: PetscSFSetFromOptions(), PetscSFWindowGetSyncType()
23095fce210SBarry Smith @*/
23195fce210SBarry Smith PetscErrorCode PetscSFWindowSetSyncType(PetscSF sf,PetscSFWindowSyncType sync)
23295fce210SBarry Smith {
23395fce210SBarry Smith   PetscErrorCode ierr;
23495fce210SBarry Smith 
23595fce210SBarry Smith   PetscFunctionBegin;
23695fce210SBarry Smith   PetscValidHeaderSpecific(sf,PETSCSF_CLASSID,1);
23795fce210SBarry Smith   PetscValidLogicalCollectiveEnum(sf,sync,2);
2385b0d146aSStefano Zampini   ierr = PetscTryMethod(sf,"PetscSFWindowSetSyncType_C",(PetscSF,PetscSFWindowSyncType),(sf,sync));CHKERRQ(ierr);
23995fce210SBarry Smith   PetscFunctionReturn(0);
24095fce210SBarry Smith }
24195fce210SBarry Smith 
242f7a08781SBarry Smith static PetscErrorCode PetscSFWindowSetSyncType_Window(PetscSF sf,PetscSFWindowSyncType sync)
24395fce210SBarry Smith {
24495fce210SBarry Smith   PetscSF_Window *w = (PetscSF_Window*)sf->data;
24595fce210SBarry Smith 
24695fce210SBarry Smith   PetscFunctionBegin;
24795fce210SBarry Smith   w->sync = sync;
24895fce210SBarry Smith   PetscFunctionReturn(0);
24995fce210SBarry Smith }
25095fce210SBarry Smith 
25195fce210SBarry Smith /*@C
2525b0d146aSStefano Zampini    PetscSFWindowGetSyncType - Get synchronization type for PetscSF communication
25395fce210SBarry Smith 
25495fce210SBarry Smith    Logically Collective
25595fce210SBarry Smith 
25695fce210SBarry Smith    Input Argument:
25795fce210SBarry Smith .  sf - star forest for communication
25895fce210SBarry Smith 
25995fce210SBarry Smith    Output Argument:
26095fce210SBarry Smith .  sync - synchronization type
26195fce210SBarry Smith 
26295fce210SBarry Smith    Level: advanced
26395fce210SBarry Smith 
2645b0d146aSStefano Zampini .seealso: PetscSFSetFromOptions(), PetscSFWindowSetSyncType()
26595fce210SBarry Smith @*/
26695fce210SBarry Smith PetscErrorCode PetscSFWindowGetSyncType(PetscSF sf,PetscSFWindowSyncType *sync)
26795fce210SBarry Smith {
26895fce210SBarry Smith   PetscErrorCode ierr;
26995fce210SBarry Smith 
27095fce210SBarry Smith   PetscFunctionBegin;
27195fce210SBarry Smith   PetscValidHeaderSpecific(sf,PETSCSF_CLASSID,1);
27295fce210SBarry Smith   PetscValidPointer(sync,2);
273163d334eSBarry Smith   ierr = PetscUseMethod(sf,"PetscSFWindowGetSyncType_C",(PetscSF,PetscSFWindowSyncType*),(sf,sync));CHKERRQ(ierr);
27495fce210SBarry Smith   PetscFunctionReturn(0);
27595fce210SBarry Smith }
27695fce210SBarry Smith 
277f7a08781SBarry Smith static PetscErrorCode PetscSFWindowGetSyncType_Window(PetscSF sf,PetscSFWindowSyncType *sync)
27895fce210SBarry Smith {
27995fce210SBarry Smith   PetscSF_Window *w = (PetscSF_Window*)sf->data;
28095fce210SBarry Smith 
28195fce210SBarry Smith   PetscFunctionBegin;
28295fce210SBarry Smith   *sync = w->sync;
28395fce210SBarry Smith   PetscFunctionReturn(0);
28495fce210SBarry Smith }
28595fce210SBarry Smith 
28695fce210SBarry Smith /*@C
2875b0d146aSStefano Zampini    PetscSFWindowSetInfo - Set the MPI_Info handle that will be used for subsequent windows allocation
2885b0d146aSStefano Zampini 
2895b0d146aSStefano Zampini    Logically Collective
2905b0d146aSStefano Zampini 
2915b0d146aSStefano Zampini    Input Argument:
2925b0d146aSStefano Zampini +  sf - star forest for communication
2935b0d146aSStefano Zampini -  info - MPI_Info handle
2945b0d146aSStefano Zampini 
2955b0d146aSStefano Zampini    Level: advanced
2965b0d146aSStefano Zampini 
2975b0d146aSStefano Zampini    Notes: the info handle is duplicated with a call to MPI_Info_dup unless info = MPI_INFO_NULL.
2985b0d146aSStefano Zampini 
2995b0d146aSStefano Zampini .seealso: PetscSFSetFromOptions(), PetscSFWindowGetInfo()
3005b0d146aSStefano Zampini @*/
3015b0d146aSStefano Zampini PetscErrorCode PetscSFWindowSetInfo(PetscSF sf,MPI_Info info)
3025b0d146aSStefano Zampini {
3035b0d146aSStefano Zampini   PetscErrorCode ierr;
3045b0d146aSStefano Zampini 
3055b0d146aSStefano Zampini   PetscFunctionBegin;
3065b0d146aSStefano Zampini   PetscValidHeaderSpecific(sf,PETSCSF_CLASSID,1);
3075b0d146aSStefano Zampini   ierr = PetscTryMethod(sf,"PetscSFWindowSetInfo_C",(PetscSF,MPI_Info),(sf,info));CHKERRQ(ierr);
3085b0d146aSStefano Zampini   PetscFunctionReturn(0);
3095b0d146aSStefano Zampini }
3105b0d146aSStefano Zampini 
3115b0d146aSStefano Zampini static PetscErrorCode PetscSFWindowSetInfo_Window(PetscSF sf,MPI_Info info)
3125b0d146aSStefano Zampini {
3135b0d146aSStefano Zampini   PetscSF_Window *w = (PetscSF_Window*)sf->data;
3145b0d146aSStefano Zampini   PetscErrorCode ierr;
3155b0d146aSStefano Zampini 
3165b0d146aSStefano Zampini   PetscFunctionBegin;
3175b0d146aSStefano Zampini   if (w->info != MPI_INFO_NULL) {
3185b0d146aSStefano Zampini     ierr = MPI_Info_free(&w->info);CHKERRQ(ierr);
3195b0d146aSStefano Zampini   }
3205b0d146aSStefano Zampini   if (info != MPI_INFO_NULL) {
3215b0d146aSStefano Zampini     ierr = MPI_Info_dup(info,&w->info);CHKERRQ(ierr);
3225b0d146aSStefano Zampini   }
3235b0d146aSStefano Zampini   PetscFunctionReturn(0);
3245b0d146aSStefano Zampini }
3255b0d146aSStefano Zampini 
3265b0d146aSStefano Zampini /*@C
3275b0d146aSStefano Zampini    PetscSFWindowGetInfo - Get the MPI_Info handle used for windows allocation
3285b0d146aSStefano Zampini 
3295b0d146aSStefano Zampini    Logically Collective
3305b0d146aSStefano Zampini 
3315b0d146aSStefano Zampini    Input Argument:
3325b0d146aSStefano Zampini .  sf - star forest for communication
3335b0d146aSStefano Zampini 
3345b0d146aSStefano Zampini    Output Argument:
3355b0d146aSStefano Zampini .  info - MPI_Info handle
3365b0d146aSStefano Zampini 
3375b0d146aSStefano Zampini    Level: advanced
3385b0d146aSStefano Zampini 
3395b0d146aSStefano Zampini    Notes: if PetscSFWindowSetInfo() has not be called, this returns MPI_INFO_NULL
3405b0d146aSStefano Zampini 
3415b0d146aSStefano Zampini .seealso: PetscSFSetFromOptions(), PetscSFWindowSetInfo()
3425b0d146aSStefano Zampini @*/
3435b0d146aSStefano Zampini PetscErrorCode PetscSFWindowGetInfo(PetscSF sf,MPI_Info *info)
3445b0d146aSStefano Zampini {
3455b0d146aSStefano Zampini   PetscErrorCode ierr;
3465b0d146aSStefano Zampini 
3475b0d146aSStefano Zampini   PetscFunctionBegin;
3485b0d146aSStefano Zampini   PetscValidHeaderSpecific(sf,PETSCSF_CLASSID,1);
3495b0d146aSStefano Zampini   PetscValidPointer(info,2);
3505b0d146aSStefano Zampini   ierr = PetscUseMethod(sf,"PetscSFWindowGetInfo_C",(PetscSF,MPI_Info*),(sf,info));CHKERRQ(ierr);
3515b0d146aSStefano Zampini   PetscFunctionReturn(0);
3525b0d146aSStefano Zampini }
3535b0d146aSStefano Zampini 
3545b0d146aSStefano Zampini static PetscErrorCode PetscSFWindowGetInfo_Window(PetscSF sf,MPI_Info *info)
3555b0d146aSStefano Zampini {
3565b0d146aSStefano Zampini   PetscSF_Window *w = (PetscSF_Window*)sf->data;
3575b0d146aSStefano Zampini 
3585b0d146aSStefano Zampini   PetscFunctionBegin;
3595b0d146aSStefano Zampini   *info = w->info;
3605b0d146aSStefano Zampini   PetscFunctionReturn(0);
3615b0d146aSStefano Zampini }
3625b0d146aSStefano Zampini 
3635b0d146aSStefano Zampini /*
36495fce210SBarry Smith    PetscSFGetWindow - Get a window for use with a given data type
36595fce210SBarry Smith 
36695fce210SBarry Smith    Collective on PetscSF
36795fce210SBarry Smith 
36895fce210SBarry Smith    Input Arguments:
36995fce210SBarry Smith +  sf - star forest
37095fce210SBarry Smith .  unit - data type
37195fce210SBarry Smith .  array - array to be sent
3725b0d146aSStefano Zampini .  sync - type of synchronization PetscSFWindowSyncType
37395fce210SBarry Smith .  epoch - PETSC_TRUE to acquire the window and start an epoch, PETSC_FALSE to just acquire the window
3745b0d146aSStefano Zampini .  fenceassert - assert parameter for call to MPI_Win_fence(), if sync == PETSCSF_WINDOW_SYNC_FENCE
3755b0d146aSStefano Zampini .  postassert - assert parameter for call to MPI_Win_post(), if sync == PETSCSF_WINDOW_SYNC_ACTIVE
376684a874aSStefano Zampini -  startassert - assert parameter for call to MPI_Win_start(), if sync == PETSCSF_WINDOW_SYNC_ACTIVE
37795fce210SBarry Smith 
37895fce210SBarry Smith    Output Arguments:
379684a874aSStefano Zampini +  target_disp - target_disp argument for RMA calls (significative for PETSCSF_WINDOW_FLAVOR_DYNAMIC only)
380684a874aSStefano Zampini +  reqs - array of requests (significative for sync == PETSCSF_WINDOW_SYNC_LOCK only)
381684a874aSStefano Zampini -  win - window
38295fce210SBarry Smith 
38395fce210SBarry Smith    Level: developer
384dec1416fSJunchao Zhang .seealso: PetscSFGetRootRanks(), PetscSFWindowGetDataTypes()
3855b0d146aSStefano Zampini */
386684a874aSStefano Zampini static PetscErrorCode PetscSFGetWindow(PetscSF sf,MPI_Datatype unit,void *array,PetscSFWindowSyncType sync,PetscBool epoch,PetscMPIInt fenceassert,PetscMPIInt postassert,PetscMPIInt startassert,const MPI_Aint **target_disp, MPI_Request **reqs, MPI_Win *win)
38795fce210SBarry Smith {
38895fce210SBarry Smith   PetscSF_Window *w = (PetscSF_Window*)sf->data;
38995fce210SBarry Smith   PetscErrorCode ierr;
39095fce210SBarry Smith   MPI_Aint       lb,lb_true,bytes,bytes_true;
39195fce210SBarry Smith   PetscSFWinLink link;
3925b0d146aSStefano Zampini   MPI_Aint       winaddr;
3935b0d146aSStefano Zampini   PetscInt       nranks;
3945b0d146aSStefano Zampini   PetscBool      reuse = PETSC_FALSE, update = PETSC_FALSE;
3955b0d146aSStefano Zampini #if defined(PETSC_USE_DEBUG)
3965b0d146aSStefano Zampini   PetscBool      dummy[2];
3975b0d146aSStefano Zampini #endif
3985b0d146aSStefano Zampini   MPI_Aint       wsize;
39995fce210SBarry Smith 
40095fce210SBarry Smith   PetscFunctionBegin;
40195fce210SBarry Smith   ierr = MPI_Type_get_extent(unit,&lb,&bytes);CHKERRQ(ierr);
40295fce210SBarry Smith   ierr = MPI_Type_get_true_extent(unit,&lb_true,&bytes_true);CHKERRQ(ierr);
40395fce210SBarry Smith   if (lb != 0 || lb_true != 0) SETERRQ(PetscObjectComm((PetscObject)sf),PETSC_ERR_SUP,"No support for unit type with nonzero lower bound, write petsc-maint@mcs.anl.gov if you want this feature");
40495fce210SBarry Smith   if (bytes != bytes_true) SETERRQ(PetscObjectComm((PetscObject)sf),PETSC_ERR_SUP,"No support for unit type with modified extent, write petsc-maint@mcs.anl.gov if you want this feature");
4055b0d146aSStefano Zampini   if (w->flavor != PETSCSF_WINDOW_FLAVOR_CREATE) reuse = PETSC_TRUE;
4065b0d146aSStefano Zampini   for (link=w->wins; reuse && link; link=link->next) {
4075b0d146aSStefano Zampini     PetscBool winok = PETSC_FALSE;
4085b0d146aSStefano Zampini     if (w->flavor != link->flavor) continue;
4095b0d146aSStefano Zampini     switch (w->flavor) {
4105b0d146aSStefano 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) */
4115b0d146aSStefano Zampini       if (array == link->addr) {
4125b0d146aSStefano Zampini #if defined(PETSC_USE_DEBUG)
4135b0d146aSStefano Zampini         dummy[0] = PETSC_TRUE;
4145b0d146aSStefano Zampini         dummy[1] = PETSC_TRUE;
4155b0d146aSStefano Zampini         ierr = MPI_Allreduce(MPI_IN_PLACE,dummy  ,1,MPIU_BOOL,MPI_LAND,PetscObjectComm((PetscObject)sf));CHKERRQ(ierr);
4165b0d146aSStefano Zampini         ierr = MPI_Allreduce(MPI_IN_PLACE,dummy+1,1,MPIU_BOOL,MPI_LOR ,PetscObjectComm((PetscObject)sf));CHKERRQ(ierr);
4175b0d146aSStefano Zampini         if (dummy[0] != dummy[1]) SETERRQ(PetscObjectComm((PetscObject)sf),PETSC_ERR_SUP,"PETSCSF_WINDOW_FLAVOR_DYNAMIC requires root pointers to be consistently used across the comm. Use PETSCSF_WINDOW_FLAVOR_CREATE or PETSCSF_WINDOW_FLAVOR_ALLOCATE instead");
4185b0d146aSStefano Zampini #endif
4195b0d146aSStefano Zampini         if (link->inuse) SETERRQ(PetscObjectComm((PetscObject)sf),PETSC_ERR_PLIB,"Window in use");
4205b0d146aSStefano Zampini         if (epoch && link->epoch) SETERRQ(PetscObjectComm((PetscObject)sf),PETSC_ERR_PLIB,"Window epoch not finished");
4215b0d146aSStefano Zampini         winok = PETSC_TRUE;
4225b0d146aSStefano Zampini         link->paddr = array;
4235b0d146aSStefano Zampini #if defined(PETSC_USE_DEBUG)
4245b0d146aSStefano Zampini       } else {
4255b0d146aSStefano Zampini         dummy[0] = PETSC_FALSE;
4265b0d146aSStefano Zampini         dummy[1] = PETSC_FALSE;
4275b0d146aSStefano Zampini         ierr = MPI_Allreduce(MPI_IN_PLACE,dummy  ,1,MPIU_BOOL,MPI_LAND,PetscObjectComm((PetscObject)sf));CHKERRQ(ierr);
4285b0d146aSStefano Zampini         ierr = MPI_Allreduce(MPI_IN_PLACE,dummy+1,1,MPIU_BOOL,MPI_LOR ,PetscObjectComm((PetscObject)sf));CHKERRQ(ierr);
4295b0d146aSStefano Zampini         if (dummy[0] != dummy[1]) SETERRQ(PetscObjectComm((PetscObject)sf),PETSC_ERR_SUP,"PETSCSF_WINDOW_FLAVOR_DYNAMIC requires root pointers to be consistently used across the comm. Use PETSCSF_WINDOW_FLAVOR_CREATE or PETSCSF_WINDOW_FLAVOR_ALLOCATE instead");
4305b0d146aSStefano Zampini #endif
4315b0d146aSStefano Zampini       }
4325b0d146aSStefano Zampini       break;
4335b0d146aSStefano Zampini     case PETSCSF_WINDOW_FLAVOR_ALLOCATE: /* check available by matching size, allocate if in use */
4345b0d146aSStefano Zampini     case PETSCSF_WINDOW_FLAVOR_SHARED:
4355b0d146aSStefano Zampini       if (!link->inuse && bytes == (MPI_Aint)link->bytes) {
4365b0d146aSStefano Zampini         update = PETSC_TRUE;
4375b0d146aSStefano Zampini         link->paddr = array;
4385b0d146aSStefano Zampini         winok = PETSC_TRUE;
4395b0d146aSStefano Zampini       }
4405b0d146aSStefano Zampini       break;
4415b0d146aSStefano Zampini     default: SETERRQ1(PetscObjectComm((PetscObject)sf),PETSC_ERR_SUP,"No support for flavor %s",PetscSFWindowFlavorTypes[w->flavor]);
4425b0d146aSStefano Zampini     }
4435b0d146aSStefano Zampini     if (winok) {
4445b0d146aSStefano Zampini       *win = link->win;
4455b0d146aSStefano Zampini       ierr = PetscInfo3(sf,"Reusing window %d of flavor %d for comm %d\n",link->win,link->flavor,PetscObjectComm((PetscObject)sf));CHKERRQ(ierr);
4465b0d146aSStefano Zampini       goto found;
4475b0d146aSStefano Zampini     }
4485b0d146aSStefano Zampini   }
4495b0d146aSStefano Zampini 
4505b0d146aSStefano Zampini   wsize = (MPI_Aint)bytes*sf->nroots;
45195dccacaSBarry Smith   ierr = PetscNew(&link);CHKERRQ(ierr);
45295fce210SBarry Smith   link->bytes           = bytes;
45395fce210SBarry Smith   link->next            = w->wins;
4545b0d146aSStefano Zampini   link->flavor          = w->flavor;
4555b0d146aSStefano Zampini   link->dyn_target_addr = NULL;
456684a874aSStefano Zampini   link->reqs            = NULL;
45795fce210SBarry Smith   w->wins               = link;
458684a874aSStefano Zampini   if (sync == PETSCSF_WINDOW_SYNC_LOCK) {
459684a874aSStefano Zampini     PetscInt i;
460684a874aSStefano Zampini 
461684a874aSStefano Zampini     ierr = PetscMalloc1(sf->nranks,&link->reqs);CHKERRQ(ierr);
462684a874aSStefano Zampini     for (i = 0; i < sf->nranks; i++) link->reqs[i] = MPI_REQUEST_NULL;
463684a874aSStefano Zampini   }
4645b0d146aSStefano Zampini   switch (w->flavor) {
4655b0d146aSStefano Zampini   case PETSCSF_WINDOW_FLAVOR_CREATE:
4665b0d146aSStefano Zampini     ierr = MPI_Win_create(array,wsize,(PetscMPIInt)bytes,w->info,PetscObjectComm((PetscObject)sf),&link->win);CHKERRQ(ierr);
4675b0d146aSStefano Zampini     link->addr  = array;
4685b0d146aSStefano Zampini     link->paddr = array;
4695b0d146aSStefano Zampini     break;
4705b0d146aSStefano Zampini   case PETSCSF_WINDOW_FLAVOR_DYNAMIC:
4715b0d146aSStefano Zampini     ierr = MPI_Win_create_dynamic(w->info,PetscObjectComm((PetscObject)sf),&link->win);CHKERRQ(ierr);
4725b0d146aSStefano Zampini #if defined(PETSC_HAVE_OMPI_MAJOR_VERSION) /* some OpenMPI versions do not support MPI_Win_attach(win,NULL,0); */
4735b0d146aSStefano Zampini     ierr = MPI_Win_attach(link->win,wsize ? array : &ierr,wsize);CHKERRQ(ierr);
4745b0d146aSStefano Zampini #else
4755b0d146aSStefano Zampini     ierr = MPI_Win_attach(link->win,array,wsize);CHKERRQ(ierr);
4765b0d146aSStefano Zampini #endif
4775b0d146aSStefano Zampini     link->addr  = array;
4785b0d146aSStefano Zampini     link->paddr = array;
4795b0d146aSStefano Zampini     if (!w->dynsf) SETERRQ(PetscObjectComm((PetscObject)sf),PETSC_ERR_ORDER,"Must call PetscSFSetUp()");
4805b0d146aSStefano Zampini     ierr = PetscSFSetUp(w->dynsf);CHKERRQ(ierr);
4815b0d146aSStefano Zampini     ierr = PetscSFGetRootRanks(w->dynsf,&nranks,NULL,NULL,NULL,NULL);CHKERRQ(ierr);
4825b0d146aSStefano Zampini     ierr = PetscMalloc1(nranks,&link->dyn_target_addr);CHKERRQ(ierr);
4835b0d146aSStefano Zampini     ierr = MPI_Get_address(array,&winaddr);CHKERRQ(ierr);
4845b0d146aSStefano Zampini     ierr = PetscSFBcastBegin(w->dynsf,MPI_AINT,&winaddr,link->dyn_target_addr);CHKERRQ(ierr);
4855b0d146aSStefano Zampini     ierr = PetscSFBcastEnd(w->dynsf,MPI_AINT,&winaddr,link->dyn_target_addr);CHKERRQ(ierr);
4865b0d146aSStefano Zampini     break;
4875b0d146aSStefano Zampini   case PETSCSF_WINDOW_FLAVOR_ALLOCATE:
4885b0d146aSStefano Zampini     ierr = MPI_Win_allocate(wsize,(PetscMPIInt)bytes,w->info,PetscObjectComm((PetscObject)sf),&link->addr,&link->win);CHKERRQ(ierr);
4895b0d146aSStefano Zampini     update = PETSC_TRUE;
4905b0d146aSStefano Zampini     link->paddr = array;
4915b0d146aSStefano Zampini     break;
4925b0d146aSStefano Zampini #if defined(PETSC_HAVE_MPI_PROCESS_SHARED_MEMORY)
4935b0d146aSStefano Zampini   case PETSCSF_WINDOW_FLAVOR_SHARED:
4945b0d146aSStefano Zampini     ierr = MPI_Win_allocate_shared(wsize,(PetscMPIInt)bytes,w->info,PetscObjectComm((PetscObject)sf),&link->addr,&link->win);CHKERRQ(ierr);
4955b0d146aSStefano Zampini     update = PETSC_TRUE;
4965b0d146aSStefano Zampini     link->paddr = array;
4975b0d146aSStefano Zampini     break;
4985b0d146aSStefano Zampini #endif
4995b0d146aSStefano Zampini   default: SETERRQ1(PetscObjectComm((PetscObject)sf),PETSC_ERR_SUP,"No support for flavor %s",PetscSFWindowFlavorTypes[w->flavor]);
5005b0d146aSStefano Zampini   }
5015b0d146aSStefano Zampini   ierr = PetscInfo3(sf,"New window %d of flavor %d for comm %d\n",link->win,link->flavor,PetscObjectComm((PetscObject)sf));CHKERRQ(ierr);
50295fce210SBarry Smith   *win = link->win;
50395fce210SBarry Smith 
5045b0d146aSStefano Zampini found:
5055b0d146aSStefano Zampini 
506684a874aSStefano Zampini   if (target_disp) *target_disp = link->dyn_target_addr;
507684a874aSStefano Zampini   if (reqs) *reqs = link->reqs;
508684a874aSStefano Zampini   if (update) { /* locks are needed for the "separate" memory model only, the fence guaranties memory-synchronization */
509684a874aSStefano Zampini     PetscMPIInt rank;
510684a874aSStefano Zampini 
511684a874aSStefano Zampini     ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)sf),&rank);CHKERRQ(ierr);
512684a874aSStefano Zampini     if (sync == PETSCSF_WINDOW_SYNC_LOCK) { ierr = MPI_Win_lock(MPI_LOCK_EXCLUSIVE,rank,MPI_MODE_NOCHECK,*win);CHKERRQ(ierr); }
5135b0d146aSStefano Zampini     ierr = PetscMemcpy(link->addr,array,sf->nroots*bytes);CHKERRQ(ierr);
5145b0d146aSStefano Zampini     if (sync == PETSCSF_WINDOW_SYNC_LOCK) {
515684a874aSStefano Zampini       ierr = MPI_Win_unlock(rank,*win);CHKERRQ(ierr);
5165b0d146aSStefano Zampini       ierr = MPI_Win_fence(0,*win);CHKERRQ(ierr);
5175b0d146aSStefano Zampini     }
5185b0d146aSStefano Zampini   }
5195b0d146aSStefano Zampini   link->inuse = PETSC_TRUE;
5205b0d146aSStefano Zampini   link->epoch = epoch;
52195fce210SBarry Smith   if (epoch) {
5225b0d146aSStefano Zampini     switch (sync) {
52395fce210SBarry Smith     case PETSCSF_WINDOW_SYNC_FENCE:
52495fce210SBarry Smith       ierr = MPI_Win_fence(fenceassert,*win);CHKERRQ(ierr);
52595fce210SBarry Smith       break;
52695fce210SBarry Smith     case PETSCSF_WINDOW_SYNC_LOCK: /* Handled outside */
52795fce210SBarry Smith       break;
52895fce210SBarry Smith     case PETSCSF_WINDOW_SYNC_ACTIVE: {
52995fce210SBarry Smith       MPI_Group   ingroup,outgroup;
5305b0d146aSStefano Zampini       PetscMPIInt isize,osize;
5315b0d146aSStefano Zampini 
5325b0d146aSStefano Zampini       /* OpenMPI 4.0.2 with btl=vader does not like calling
5335b0d146aSStefano Zampini          - MPI_Win_complete when ogroup is empty
5345b0d146aSStefano Zampini          - MPI_Win_wait when igroup is empty
5355b0d146aSStefano Zampini          So, we do not even issue the corresponding start and post calls
5365b0d146aSStefano Zampini          The MPI standard (Sec. 11.5.2 of MPI 3.1) only requires that
5375b0d146aSStefano Zampini          start(outgroup) has a matching post(ingroup)
5385b0d146aSStefano Zampini          and this is guaranteed by PetscSF
5395b0d146aSStefano Zampini       */
54095fce210SBarry Smith       ierr = PetscSFGetGroups(sf,&ingroup,&outgroup);CHKERRQ(ierr);
5415b0d146aSStefano Zampini       ierr = MPI_Group_size(ingroup,&isize);CHKERRQ(ierr);
5425b0d146aSStefano Zampini       ierr = MPI_Group_size(outgroup,&osize);CHKERRQ(ierr);
5435b0d146aSStefano Zampini       if (isize) { ierr = MPI_Win_post(ingroup,postassert,*win);CHKERRQ(ierr); }
5445b0d146aSStefano Zampini       if (osize) { ierr = MPI_Win_start(outgroup,startassert,*win);CHKERRQ(ierr); }
54595fce210SBarry Smith     } break;
54695fce210SBarry Smith     default: SETERRQ(PetscObjectComm((PetscObject)sf),PETSC_ERR_PLIB,"Unknown synchronization type");
54795fce210SBarry Smith     }
54895fce210SBarry Smith   }
54995fce210SBarry Smith   PetscFunctionReturn(0);
55095fce210SBarry Smith }
55195fce210SBarry Smith 
5525b0d146aSStefano Zampini /*
55395fce210SBarry Smith    PetscSFFindWindow - Finds a window that is already in use
55495fce210SBarry Smith 
55595fce210SBarry Smith    Not Collective
55695fce210SBarry Smith 
55795fce210SBarry Smith    Input Arguments:
55895fce210SBarry Smith +  sf - star forest
55995fce210SBarry Smith .  unit - data type
56095fce210SBarry Smith -  array - array with which the window is associated
56195fce210SBarry Smith 
56295fce210SBarry Smith    Output Arguments:
563684a874aSStefano Zampini +  win - window
564684a874aSStefano Zampini -  reqs - outstanding requests associated to the window
56595fce210SBarry Smith 
56695fce210SBarry Smith    Level: developer
56795fce210SBarry Smith 
56895fce210SBarry Smith .seealso: PetscSFGetWindow(), PetscSFRestoreWindow()
5695b0d146aSStefano Zampini */
570684a874aSStefano Zampini static PetscErrorCode PetscSFFindWindow(PetscSF sf,MPI_Datatype unit,const void *array,MPI_Win *win,MPI_Request **reqs)
57195fce210SBarry Smith {
57295fce210SBarry Smith   PetscSF_Window *w = (PetscSF_Window*)sf->data;
57395fce210SBarry Smith   PetscSFWinLink link;
5745b0d146aSStefano Zampini   PetscErrorCode ierr;
57595fce210SBarry Smith 
57695fce210SBarry Smith   PetscFunctionBegin;
577c0cd0301SJed Brown   *win = MPI_WIN_NULL;
57895fce210SBarry Smith   for (link=w->wins; link; link=link->next) {
5795b0d146aSStefano Zampini     if (array == link->paddr) {
5805b0d146aSStefano Zampini       ierr = PetscInfo3(sf,"Window %d of flavor %d for comm %d\n",link->win,link->flavor,PetscObjectComm((PetscObject)sf));CHKERRQ(ierr);
58195fce210SBarry Smith       *win = link->win;
582684a874aSStefano Zampini       *reqs = link->reqs;
58395fce210SBarry Smith       PetscFunctionReturn(0);
58495fce210SBarry Smith     }
58595fce210SBarry Smith   }
58695fce210SBarry Smith   SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Requested window not in use");
58795fce210SBarry Smith   PetscFunctionReturn(0);
58895fce210SBarry Smith }
58995fce210SBarry Smith 
5905b0d146aSStefano Zampini /*
59195fce210SBarry Smith    PetscSFRestoreWindow - Restores a window obtained with PetscSFGetWindow()
59295fce210SBarry Smith 
59395fce210SBarry Smith    Collective
59495fce210SBarry Smith 
59595fce210SBarry Smith    Input Arguments:
59695fce210SBarry Smith +  sf - star forest
59795fce210SBarry Smith .  unit - data type
59895fce210SBarry Smith .  array - array associated with window
5995b0d146aSStefano Zampini .  sync - type of synchronization PetscSFWindowSyncType
60095fce210SBarry Smith .  epoch - close an epoch, must match argument to PetscSFGetWindow()
6015b0d146aSStefano Zampini .  update - if we have to update the local window array
60295fce210SBarry Smith -  win - window
60395fce210SBarry Smith 
60495fce210SBarry Smith    Level: developer
60595fce210SBarry Smith 
60695fce210SBarry Smith .seealso: PetscSFFindWindow()
6075b0d146aSStefano Zampini */
6085b0d146aSStefano Zampini static PetscErrorCode PetscSFRestoreWindow(PetscSF sf,MPI_Datatype unit,void *array,PetscSFWindowSyncType sync,PetscBool epoch,PetscMPIInt fenceassert,PetscBool update,MPI_Win *win)
60995fce210SBarry Smith {
61095fce210SBarry Smith   PetscSF_Window          *w = (PetscSF_Window*)sf->data;
61195fce210SBarry Smith   PetscErrorCode          ierr;
61295fce210SBarry Smith   PetscSFWinLink          *p,link;
6135b0d146aSStefano Zampini   PetscBool               reuse = PETSC_FALSE;
6145b0d146aSStefano Zampini   PetscSFWindowFlavorType flavor;
6155b0d146aSStefano Zampini   void*                   laddr;
6165b0d146aSStefano Zampini   size_t                  bytes;
61795fce210SBarry Smith 
61895fce210SBarry Smith   PetscFunctionBegin;
61995fce210SBarry Smith   for (p=&w->wins; *p; p=&(*p)->next) {
62095fce210SBarry Smith     link = *p;
62195fce210SBarry Smith     if (*win == link->win) {
6225b0d146aSStefano Zampini       if (array != link->paddr) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Matched window, but not array");
62395fce210SBarry Smith       if (epoch != link->epoch) {
62495fce210SBarry Smith         if (epoch) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"No epoch to end");
62595fce210SBarry Smith         else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Restoring window without ending epoch");
62695fce210SBarry Smith       }
6275b0d146aSStefano Zampini       laddr = link->addr;
6285b0d146aSStefano Zampini       flavor = link->flavor;
6295b0d146aSStefano Zampini       bytes = link->bytes;
6305b0d146aSStefano Zampini       if (flavor != PETSCSF_WINDOW_FLAVOR_CREATE) reuse = PETSC_TRUE;
6315b0d146aSStefano Zampini       else { *p = link->next; update = PETSC_FALSE; } /* remove from list */
63295fce210SBarry Smith       goto found;
63395fce210SBarry Smith     }
63495fce210SBarry Smith   }
63595fce210SBarry Smith   SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Requested window not in use");
63695fce210SBarry Smith 
63795fce210SBarry Smith found:
6385b0d146aSStefano Zampini   ierr = PetscInfo3(sf,"Window %d of flavor %d for comm %d\n",link->win,link->flavor,PetscObjectComm((PetscObject)sf));CHKERRQ(ierr);
63995fce210SBarry Smith   if (epoch) {
6405b0d146aSStefano Zampini     switch (sync) {
64195fce210SBarry Smith     case PETSCSF_WINDOW_SYNC_FENCE:
64295fce210SBarry Smith       ierr = MPI_Win_fence(fenceassert,*win);CHKERRQ(ierr);
64395fce210SBarry Smith       break;
6445b0d146aSStefano Zampini     case PETSCSF_WINDOW_SYNC_LOCK: /* Handled outside */
6455b0d146aSStefano Zampini       break;
64695fce210SBarry Smith     case PETSCSF_WINDOW_SYNC_ACTIVE: {
6475b0d146aSStefano Zampini       MPI_Group   ingroup,outgroup;
6485b0d146aSStefano Zampini       PetscMPIInt isize,osize;
6495b0d146aSStefano Zampini 
6505b0d146aSStefano Zampini       /* OpenMPI 4.0.2 with btl=wader does not like calling
6515b0d146aSStefano Zampini          - MPI_Win_complete when ogroup is empty
6525b0d146aSStefano Zampini          - MPI_Win_wait when igroup is empty
6535b0d146aSStefano Zampini          The MPI standard (Sec. 11.5.2 of MPI 3.1) only requires that
6545b0d146aSStefano Zampini          - each process who issues a call to MPI_Win_start issues a call to MPI_Win_Complete
6555b0d146aSStefano Zampini          - each process who issues a call to MPI_Win_post issues a call to MPI_Win_Wait
6565b0d146aSStefano Zampini       */
6575b0d146aSStefano Zampini       ierr = PetscSFGetGroups(sf,&ingroup,&outgroup);CHKERRQ(ierr);
6585b0d146aSStefano Zampini       ierr = MPI_Group_size(ingroup,&isize);CHKERRQ(ierr);
6595b0d146aSStefano Zampini       ierr = MPI_Group_size(outgroup,&osize);CHKERRQ(ierr);
6605b0d146aSStefano Zampini       if (osize) { ierr = MPI_Win_complete(*win);CHKERRQ(ierr); }
6615b0d146aSStefano Zampini       if (isize) { ierr = MPI_Win_wait(*win);CHKERRQ(ierr); }
66295fce210SBarry Smith     } break;
66395fce210SBarry Smith     default: SETERRQ(PetscObjectComm((PetscObject)sf),PETSC_ERR_PLIB,"Unknown synchronization type");
66495fce210SBarry Smith     }
66595fce210SBarry Smith   }
6665b0d146aSStefano Zampini   if (update) {
6675b0d146aSStefano Zampini     if (sync == PETSCSF_WINDOW_SYNC_LOCK) {
6685b0d146aSStefano Zampini       ierr = MPI_Win_fence(MPI_MODE_NOPUT|MPI_MODE_NOSUCCEED,*win);CHKERRQ(ierr);
6695b0d146aSStefano Zampini     }
6705b0d146aSStefano Zampini     ierr = PetscMemcpy(array,laddr,sf->nroots*bytes);CHKERRQ(ierr);
6715b0d146aSStefano Zampini   }
6725b0d146aSStefano Zampini   link->epoch = PETSC_FALSE;
6735b0d146aSStefano Zampini   link->inuse = PETSC_FALSE;
6745b0d146aSStefano Zampini   link->paddr = NULL;
6755b0d146aSStefano Zampini   if (!reuse) {
676684a874aSStefano Zampini     ierr = PetscFree(link->dyn_target_addr);CHKERRQ(ierr);
677684a874aSStefano Zampini     ierr = PetscFree(link->reqs);CHKERRQ(ierr);
67895fce210SBarry Smith     ierr = MPI_Win_free(&link->win);CHKERRQ(ierr);
67995fce210SBarry Smith     ierr = PetscFree(link);CHKERRQ(ierr);
68095fce210SBarry Smith     *win = MPI_WIN_NULL;
6815b0d146aSStefano Zampini   }
68295fce210SBarry Smith   PetscFunctionReturn(0);
68395fce210SBarry Smith }
68495fce210SBarry Smith 
68595fce210SBarry Smith static PetscErrorCode PetscSFSetUp_Window(PetscSF sf)
68695fce210SBarry Smith {
68795fce210SBarry Smith   PetscSF_Window *w = (PetscSF_Window*)sf->data;
68895fce210SBarry Smith   PetscErrorCode ierr;
68995fce210SBarry Smith   MPI_Group      ingroup,outgroup;
69095fce210SBarry Smith 
69195fce210SBarry Smith   PetscFunctionBegin;
692b5a8e515SJed Brown   ierr = PetscSFSetUpRanks(sf,MPI_GROUP_EMPTY);CHKERRQ(ierr);
6935b0d146aSStefano Zampini   if (!w->dynsf) {
6945b0d146aSStefano Zampini     PetscInt    i;
6955b0d146aSStefano Zampini     PetscSFNode *remotes;
6965b0d146aSStefano Zampini 
6975b0d146aSStefano Zampini     ierr = PetscMalloc1(sf->nranks,&remotes);CHKERRQ(ierr);
6985b0d146aSStefano Zampini     for (i=0;i<sf->nranks;i++) {
6995b0d146aSStefano Zampini       remotes[i].rank  = sf->ranks[i];
7005b0d146aSStefano Zampini       remotes[i].index = 0;
7015b0d146aSStefano Zampini     }
7025b0d146aSStefano Zampini     ierr = PetscSFDuplicate(sf,PETSCSF_DUPLICATE_RANKS,&w->dynsf);CHKERRQ(ierr);
7035b0d146aSStefano Zampini     ierr = PetscSFWindowSetFlavorType(w->dynsf,PETSCSF_WINDOW_FLAVOR_CREATE);CHKERRQ(ierr); /* break recursion */
7045b0d146aSStefano Zampini     ierr = PetscSFSetGraph(w->dynsf,1,sf->nranks,NULL,PETSC_OWN_POINTER,remotes,PETSC_OWN_POINTER);CHKERRQ(ierr);
7055b0d146aSStefano Zampini     ierr = PetscLogObjectParent((PetscObject)sf,(PetscObject)w->dynsf);CHKERRQ(ierr);
7065b0d146aSStefano Zampini   }
70795fce210SBarry Smith   switch (w->sync) {
70895fce210SBarry Smith   case PETSCSF_WINDOW_SYNC_ACTIVE:
70995fce210SBarry Smith     ierr = PetscSFGetGroups(sf,&ingroup,&outgroup);CHKERRQ(ierr);
71095fce210SBarry Smith   default:
71195fce210SBarry Smith     break;
71295fce210SBarry Smith   }
71395fce210SBarry Smith   PetscFunctionReturn(0);
71495fce210SBarry Smith }
71595fce210SBarry Smith 
7164416b707SBarry Smith static PetscErrorCode PetscSFSetFromOptions_Window(PetscOptionItems *PetscOptionsObject,PetscSF sf)
71795fce210SBarry Smith {
71895fce210SBarry Smith   PetscSF_Window          *w = (PetscSF_Window*)sf->data;
71995fce210SBarry Smith   PetscErrorCode          ierr;
7205b0d146aSStefano Zampini   PetscSFWindowFlavorType flavor = w->flavor;
72195fce210SBarry Smith 
72295fce210SBarry Smith   PetscFunctionBegin;
723e55864a3SBarry Smith   ierr = PetscOptionsHead(PetscOptionsObject,"PetscSF Window options");CHKERRQ(ierr);
72495fce210SBarry Smith   ierr = PetscOptionsEnum("-sf_window_sync","synchronization type to use for PetscSF Window communication","PetscSFWindowSetSyncType",PetscSFWindowSyncTypes,(PetscEnum)w->sync,(PetscEnum*)&w->sync,NULL);CHKERRQ(ierr);
7255b0d146aSStefano Zampini   ierr = PetscOptionsEnum("-sf_window_flavor","flavor to use for PetscSF Window creation","PetscSFWindowSetFlavorType",PetscSFWindowFlavorTypes,(PetscEnum)flavor,(PetscEnum*)&flavor,NULL);CHKERRQ(ierr);
7265b0d146aSStefano Zampini   ierr = PetscSFWindowSetFlavorType(sf,flavor);CHKERRQ(ierr);
72795fce210SBarry Smith   ierr = PetscOptionsTail();CHKERRQ(ierr);
72895fce210SBarry Smith   PetscFunctionReturn(0);
72995fce210SBarry Smith }
73095fce210SBarry Smith 
73195fce210SBarry Smith static PetscErrorCode PetscSFReset_Window(PetscSF sf)
73295fce210SBarry Smith {
73395fce210SBarry Smith   PetscSF_Window  *w = (PetscSF_Window*)sf->data;
73495fce210SBarry Smith   PetscErrorCode  ierr;
73595fce210SBarry Smith   PetscSFDataLink link,next;
73695fce210SBarry Smith   PetscSFWinLink  wlink,wnext;
73795fce210SBarry Smith   PetscInt        i;
73895fce210SBarry Smith 
73995fce210SBarry Smith   PetscFunctionBegin;
74095fce210SBarry Smith   for (link=w->link; link; link=next) {
74195fce210SBarry Smith     next = link->next;
74295fce210SBarry Smith     ierr = MPI_Type_free(&link->unit);CHKERRQ(ierr);
74395fce210SBarry Smith     for (i=0; i<sf->nranks; i++) {
74495fce210SBarry Smith       ierr = MPI_Type_free(&link->mine[i]);CHKERRQ(ierr);
74595fce210SBarry Smith       ierr = MPI_Type_free(&link->remote[i]);CHKERRQ(ierr);
74695fce210SBarry Smith     }
74795fce210SBarry Smith     ierr = PetscFree2(link->mine,link->remote);CHKERRQ(ierr);
74895fce210SBarry Smith     ierr = PetscFree(link);CHKERRQ(ierr);
74995fce210SBarry Smith   }
75095fce210SBarry Smith   w->link = NULL;
75195fce210SBarry Smith   for (wlink=w->wins; wlink; wlink=wnext) {
75295fce210SBarry Smith     wnext = wlink->next;
75395fce210SBarry Smith     if (wlink->inuse) SETERRQ1(PetscObjectComm((PetscObject)sf),PETSC_ERR_ARG_WRONGSTATE,"Window still in use with address %p",(void*)wlink->addr);
7545b0d146aSStefano Zampini     ierr = PetscFree(wlink->dyn_target_addr);CHKERRQ(ierr);
755684a874aSStefano Zampini     ierr = PetscFree(wlink->reqs);CHKERRQ(ierr);
75695fce210SBarry Smith     ierr = MPI_Win_free(&wlink->win);CHKERRQ(ierr);
75795fce210SBarry Smith     ierr = PetscFree(wlink);CHKERRQ(ierr);
75895fce210SBarry Smith   }
75995fce210SBarry Smith   w->wins = NULL;
7605b0d146aSStefano Zampini   ierr = PetscSFDestroy(&w->dynsf);CHKERRQ(ierr);
7615b0d146aSStefano Zampini   if (w->info != MPI_INFO_NULL) {
7625b0d146aSStefano Zampini     ierr = MPI_Info_free(&w->info);CHKERRQ(ierr);
7635b0d146aSStefano Zampini   }
76495fce210SBarry Smith   PetscFunctionReturn(0);
76595fce210SBarry Smith }
76695fce210SBarry Smith 
76795fce210SBarry Smith static PetscErrorCode PetscSFDestroy_Window(PetscSF sf)
76895fce210SBarry Smith {
76995fce210SBarry Smith   PetscErrorCode ierr;
77095fce210SBarry Smith 
77195fce210SBarry Smith   PetscFunctionBegin;
77229046d53SLisandro Dalcin   ierr = PetscSFReset_Window(sf);CHKERRQ(ierr);
77395fce210SBarry Smith   ierr = PetscFree(sf->data);CHKERRQ(ierr);
774bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)sf,"PetscSFWindowSetSyncType_C",NULL);CHKERRQ(ierr);
775bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)sf,"PetscSFWindowGetSyncType_C",NULL);CHKERRQ(ierr);
7765b0d146aSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)sf,"PetscSFWindowSetFlavorType_C",NULL);CHKERRQ(ierr);
7775b0d146aSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)sf,"PetscSFWindowGetFlavorType_C",NULL);CHKERRQ(ierr);
7785b0d146aSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)sf,"PetscSFWindowSetInfo_C",NULL);CHKERRQ(ierr);
7795b0d146aSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)sf,"PetscSFWindowGetInfo_C",NULL);CHKERRQ(ierr);
78095fce210SBarry Smith   PetscFunctionReturn(0);
78195fce210SBarry Smith }
78295fce210SBarry Smith 
78395fce210SBarry Smith static PetscErrorCode PetscSFView_Window(PetscSF sf,PetscViewer viewer)
78495fce210SBarry Smith {
78595fce210SBarry Smith   PetscSF_Window    *w = (PetscSF_Window*)sf->data;
78695fce210SBarry Smith   PetscErrorCode    ierr;
78795fce210SBarry Smith   PetscBool         iascii;
7885b0d146aSStefano Zampini   PetscViewerFormat format;
78995fce210SBarry Smith 
79095fce210SBarry Smith   PetscFunctionBegin;
7915b0d146aSStefano Zampini   ierr = PetscViewerGetFormat(viewer,&format);CHKERRQ(ierr);
79295fce210SBarry Smith   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr);
79395fce210SBarry Smith   if (iascii) {
7945b0d146aSStefano Zampini     ierr = PetscViewerASCIIPrintf(viewer,"  current flavor=%s synchronization=%s sort=%s\n",PetscSFWindowFlavorTypes[w->flavor],PetscSFWindowSyncTypes[w->sync],sf->rankorder ? "rank-order" : "unordered");CHKERRQ(ierr);
7955b0d146aSStefano Zampini     if (format == PETSC_VIEWER_ASCII_INFO_DETAIL) {
7965b0d146aSStefano Zampini       if (w->info != MPI_INFO_NULL) {
7975b0d146aSStefano Zampini         PetscMPIInt k,nkeys;
7985b0d146aSStefano Zampini         char        key[MPI_MAX_INFO_KEY], value[MPI_MAX_INFO_VAL];
7995b0d146aSStefano Zampini 
8005b0d146aSStefano Zampini         ierr = MPI_Info_get_nkeys(w->info,&nkeys);CHKERRQ(ierr);
8015b0d146aSStefano Zampini         ierr = PetscViewerASCIIPrintf(viewer,"    current info with %d keys. Ordered key-value pairs follow:\n",nkeys);CHKERRQ(ierr);
8025b0d146aSStefano Zampini         for (k = 0; k < nkeys; k++) {
8035b0d146aSStefano Zampini           PetscMPIInt flag;
8045b0d146aSStefano Zampini 
8055b0d146aSStefano Zampini           ierr = MPI_Info_get_nthkey(w->info,k,key);CHKERRQ(ierr);
8065b0d146aSStefano Zampini           ierr = MPI_Info_get(w->info,key,MPI_MAX_INFO_VAL,value,&flag);CHKERRQ(ierr);
8075b0d146aSStefano Zampini           if (!flag) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Missing key %s",key);
8085b0d146aSStefano Zampini           ierr = PetscViewerASCIIPrintf(viewer,"      %s = %s\n",key,value);CHKERRQ(ierr);
8095b0d146aSStefano Zampini         }
8105b0d146aSStefano Zampini       } else {
8115b0d146aSStefano Zampini         ierr = PetscViewerASCIIPrintf(viewer,"    current info=MPI_INFO_NULL\n");CHKERRQ(ierr);
8125b0d146aSStefano Zampini       }
8135b0d146aSStefano Zampini     }
81495fce210SBarry Smith   }
81595fce210SBarry Smith   PetscFunctionReturn(0);
81695fce210SBarry Smith }
81795fce210SBarry Smith 
81895fce210SBarry Smith static PetscErrorCode PetscSFDuplicate_Window(PetscSF sf,PetscSFDuplicateOption opt,PetscSF newsf)
81995fce210SBarry Smith {
82095fce210SBarry Smith   PetscSF_Window        *w = (PetscSF_Window*)sf->data;
82195fce210SBarry Smith   PetscErrorCode        ierr;
82295fce210SBarry Smith   PetscSFWindowSyncType synctype;
82395fce210SBarry Smith 
82495fce210SBarry Smith   PetscFunctionBegin;
82595fce210SBarry Smith   synctype = w->sync;
82695fce210SBarry Smith   /* HACK: Must use FENCE or LOCK when called from PetscSFGetGroups() because ACTIVE here would cause recursion. */
8275b0d146aSStefano Zampini   if (!sf->setupcalled) synctype = PETSCSF_WINDOW_SYNC_LOCK;
82895fce210SBarry Smith   ierr = PetscSFWindowSetSyncType(newsf,synctype);CHKERRQ(ierr);
8295b0d146aSStefano Zampini   ierr = PetscSFWindowSetFlavorType(newsf,w->flavor);CHKERRQ(ierr);
8305b0d146aSStefano Zampini   ierr = PetscSFWindowSetInfo(newsf,w->info);CHKERRQ(ierr);
83195fce210SBarry Smith   PetscFunctionReturn(0);
83295fce210SBarry Smith }
83395fce210SBarry Smith 
834eb02082bSJunchao Zhang static PetscErrorCode PetscSFBcastAndOpBegin_Window(PetscSF sf,MPI_Datatype unit,PetscMemType rootmtype,const void *rootdata,PetscMemType leafmtype,void *leafdata,MPI_Op op)
83595fce210SBarry Smith {
83695fce210SBarry Smith   PetscSF_Window     *w = (PetscSF_Window*)sf->data;
83795fce210SBarry Smith   PetscErrorCode     ierr;
83895fce210SBarry Smith   PetscInt           i,nranks;
83995fce210SBarry Smith   const PetscMPIInt  *ranks;
8405b0d146aSStefano Zampini   const MPI_Aint     *target_disp;
84195fce210SBarry Smith   const MPI_Datatype *mine,*remote;
842684a874aSStefano Zampini   MPI_Request        *reqs;
84395fce210SBarry Smith   MPI_Win            win;
84495fce210SBarry Smith 
84595fce210SBarry Smith   PetscFunctionBegin;
8465b0d146aSStefano Zampini   if (op != MPI_REPLACE || op != MPIU_REPLACE) SETERRQ(PetscObjectComm((PetscObject)sf), PETSC_ERR_SUP, "PetscSFBcastAndOpBegin_Window with op!=MPI_REPLACE has not been implemented");
847dec1416fSJunchao Zhang   ierr = PetscSFGetRootRanks(sf,&nranks,&ranks,NULL,NULL,NULL);CHKERRQ(ierr);
84895fce210SBarry Smith   ierr = PetscSFWindowGetDataTypes(sf,unit,&mine,&remote);CHKERRQ(ierr);
849684a874aSStefano Zampini   ierr = PetscSFGetWindow(sf,unit,(void*)rootdata,w->sync,PETSC_TRUE,MPI_MODE_NOPUT|MPI_MODE_NOPRECEDE,MPI_MODE_NOPUT,0,&target_disp,&reqs,&win);CHKERRQ(ierr);
85095fce210SBarry Smith   for (i=0; i<nranks; i++) {
8515b0d146aSStefano Zampini     MPI_Aint tdp = target_disp ? target_disp[i] : 0;
8525b0d146aSStefano Zampini 
853684a874aSStefano Zampini     if (w->sync == PETSCSF_WINDOW_SYNC_LOCK) {
854684a874aSStefano Zampini       ierr = MPI_Win_lock(MPI_LOCK_SHARED,ranks[i],MPI_MODE_NOCHECK,win);CHKERRQ(ierr);
855684a874aSStefano Zampini #if defined(PETSC_HAVE_MPI_RGET)
856684a874aSStefano Zampini       ierr = MPI_Rget(leafdata,1,mine[i],ranks[i],tdp,1,remote[i],win,&reqs[i]);CHKERRQ(ierr);
857684a874aSStefano Zampini #else
8585b0d146aSStefano Zampini       ierr = MPI_Get(leafdata,1,mine[i],ranks[i],tdp,1,remote[i],win);CHKERRQ(ierr);
859684a874aSStefano Zampini #endif
860684a874aSStefano Zampini     } else {
861684a874aSStefano Zampini       ierr = MPI_Get(leafdata,1,mine[i],ranks[i],tdp,1,remote[i],win);CHKERRQ(ierr);
862684a874aSStefano Zampini     }
86395fce210SBarry Smith   }
86495fce210SBarry Smith   PetscFunctionReturn(0);
86595fce210SBarry Smith }
86695fce210SBarry Smith 
867*00816365SJunchao Zhang PetscErrorCode PetscSFBcastAndOpEnd_Window(PetscSF sf,MPI_Datatype unit,const void *rootdata,void *leafdata,MPI_Op op)
86895fce210SBarry Smith {
8695b0d146aSStefano Zampini   PetscSF_Window *w = (PetscSF_Window*)sf->data;
87095fce210SBarry Smith   PetscErrorCode ierr;
87195fce210SBarry Smith   MPI_Win        win;
872684a874aSStefano Zampini   MPI_Request    *reqs;
87395fce210SBarry Smith 
87495fce210SBarry Smith   PetscFunctionBegin;
875684a874aSStefano Zampini   ierr = PetscSFFindWindow(sf,unit,rootdata,&win,&reqs);CHKERRQ(ierr);
876684a874aSStefano Zampini   if (reqs) { ierr = MPI_Waitall(sf->nranks,reqs,MPI_STATUSES_IGNORE);CHKERRQ(ierr); }
877684a874aSStefano Zampini   if (w->sync == PETSCSF_WINDOW_SYNC_LOCK) {
878684a874aSStefano Zampini     PetscInt           i,nranks;
879684a874aSStefano Zampini     const PetscMPIInt  *ranks;
880684a874aSStefano Zampini 
881684a874aSStefano Zampini     ierr = PetscSFGetRootRanks(sf,&nranks,&ranks,NULL,NULL,NULL);CHKERRQ(ierr);
882684a874aSStefano Zampini     for (i=0; i<nranks; i++) {
883684a874aSStefano Zampini       ierr = MPI_Win_unlock(ranks[i],win);CHKERRQ(ierr);
884684a874aSStefano Zampini     }
885684a874aSStefano Zampini   }
8865b0d146aSStefano Zampini   ierr = PetscSFRestoreWindow(sf,unit,(void*)rootdata,w->sync,PETSC_TRUE,MPI_MODE_NOSTORE|MPI_MODE_NOSUCCEED,PETSC_FALSE,&win);CHKERRQ(ierr);
88795fce210SBarry Smith   PetscFunctionReturn(0);
88895fce210SBarry Smith }
88995fce210SBarry Smith 
890eb02082bSJunchao Zhang PetscErrorCode PetscSFReduceBegin_Window(PetscSF sf,MPI_Datatype unit,PetscMemType leafmtype,const void *leafdata,PetscMemType rootmtype,void *rootdata,MPI_Op op)
89195fce210SBarry Smith {
89295fce210SBarry Smith   PetscSF_Window     *w = (PetscSF_Window*)sf->data;
89395fce210SBarry Smith   PetscErrorCode     ierr;
89495fce210SBarry Smith   PetscInt           i,nranks;
89595fce210SBarry Smith   const PetscMPIInt  *ranks;
8965b0d146aSStefano Zampini   const MPI_Aint     *target_disp;
89795fce210SBarry Smith   const MPI_Datatype *mine,*remote;
89895fce210SBarry Smith   MPI_Win            win;
89995fce210SBarry Smith 
90095fce210SBarry Smith   PetscFunctionBegin;
901dec1416fSJunchao Zhang   ierr = PetscSFGetRootRanks(sf,&nranks,&ranks,NULL,NULL,NULL);CHKERRQ(ierr);
90295fce210SBarry Smith   ierr = PetscSFWindowGetDataTypes(sf,unit,&mine,&remote);CHKERRQ(ierr);
90395fce210SBarry Smith   ierr = PetscSFWindowOpTranslate(&op);CHKERRQ(ierr);
904684a874aSStefano Zampini   ierr = PetscSFGetWindow(sf,unit,rootdata,w->sync,PETSC_TRUE,MPI_MODE_NOPRECEDE,0,0,&target_disp,NULL,&win);CHKERRQ(ierr);
90595fce210SBarry Smith   for (i=0; i<nranks; i++) {
9065b0d146aSStefano Zampini     MPI_Aint tdp = target_disp ? target_disp[i] : 0;
9075b0d146aSStefano Zampini 
90895fce210SBarry Smith     if (w->sync == PETSCSF_WINDOW_SYNC_LOCK) {ierr = MPI_Win_lock(MPI_LOCK_SHARED,ranks[i],MPI_MODE_NOCHECK,win);CHKERRQ(ierr);}
9095b0d146aSStefano Zampini     ierr = MPI_Accumulate((void*)leafdata,1,mine[i],ranks[i],tdp,1,remote[i],op,win);
9105b0d146aSStefano Zampini     if (ierr) { /* intercept the MPI error since the combination of unit and op is not supported */
9115b0d146aSStefano Zampini       PetscMPIInt len;
9125b0d146aSStefano Zampini       char        errstring[MPI_MAX_ERROR_STRING];
9135b0d146aSStefano Zampini 
9145b0d146aSStefano Zampini       MPI_Error_string(ierr,errstring,&len);
9155b0d146aSStefano Zampini       SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_SUP,"Internal error in MPI: %s",errstring);
9165b0d146aSStefano Zampini     }
91795fce210SBarry Smith     if (w->sync == PETSCSF_WINDOW_SYNC_LOCK) {ierr = MPI_Win_unlock(ranks[i],win);CHKERRQ(ierr);}
91895fce210SBarry Smith   }
91995fce210SBarry Smith   PetscFunctionReturn(0);
92095fce210SBarry Smith }
92195fce210SBarry Smith 
922*00816365SJunchao Zhang static PetscErrorCode PetscSFReduceEnd_Window(PetscSF sf,MPI_Datatype unit,const void *leafdata,void *rootdata,MPI_Op op)
92395fce210SBarry Smith {
92495fce210SBarry Smith   PetscSF_Window *w = (PetscSF_Window*)sf->data;
92595fce210SBarry Smith   PetscErrorCode ierr;
92695fce210SBarry Smith   MPI_Win        win;
927684a874aSStefano Zampini   MPI_Request    *reqs;
92895fce210SBarry Smith 
92995fce210SBarry Smith   PetscFunctionBegin;
930684a874aSStefano Zampini   ierr = PetscSFFindWindow(sf,unit,rootdata,&win,&reqs);CHKERRQ(ierr);
931684a874aSStefano Zampini   if (reqs) { ierr = MPI_Waitall(sf->nranks,reqs,MPI_STATUSES_IGNORE);CHKERRQ(ierr); }
9325b0d146aSStefano Zampini   ierr = PetscSFRestoreWindow(sf,unit,rootdata,w->sync,PETSC_TRUE,MPI_MODE_NOSUCCEED,PETSC_TRUE,&win);CHKERRQ(ierr);
93395fce210SBarry Smith   PetscFunctionReturn(0);
93495fce210SBarry Smith }
9355b0d146aSStefano Zampini 
936eb02082bSJunchao Zhang static PetscErrorCode PetscSFFetchAndOpBegin_Window(PetscSF sf,MPI_Datatype unit,PetscMemType rootmtype,void *rootdata,PetscMemType leafmtype,const void *leafdata,void *leafupdate,MPI_Op op)
93795fce210SBarry Smith {
93895fce210SBarry Smith   PetscErrorCode     ierr;
93995fce210SBarry Smith   PetscInt           i,nranks;
94095fce210SBarry Smith   const PetscMPIInt  *ranks;
94195fce210SBarry Smith   const MPI_Datatype *mine,*remote;
9425b0d146aSStefano Zampini   const MPI_Aint     *target_disp;
94395fce210SBarry Smith   MPI_Win            win;
9445b0d146aSStefano Zampini   PetscSF_Window     *w = (PetscSF_Window*)sf->data;
9455b0d146aSStefano Zampini #if !defined(PETSC_HAVE_MPI_GET_ACCUMULATE)
9465b0d146aSStefano Zampini   PetscSFWindowFlavorType oldf;
9475b0d146aSStefano Zampini #endif
94895fce210SBarry Smith 
94995fce210SBarry Smith   PetscFunctionBegin;
950dec1416fSJunchao Zhang   ierr = PetscSFGetRootRanks(sf,&nranks,&ranks,NULL,NULL,NULL);CHKERRQ(ierr);
95195fce210SBarry Smith   ierr = PetscSFWindowGetDataTypes(sf,unit,&mine,&remote);CHKERRQ(ierr);
95295fce210SBarry Smith   ierr = PetscSFWindowOpTranslate(&op);CHKERRQ(ierr);
9535b0d146aSStefano Zampini #if !defined(PETSC_HAVE_MPI_GET_ACCUMULATE)
9545b0d146aSStefano Zampini   /* FetchAndOp without MPI_Get_Accumulate requires locking.
9555b0d146aSStefano Zampini      we create a new window every time to not interfere with user-defined MPI_Info which may have used "no_locks"="true" */
9565b0d146aSStefano Zampini   oldf = w->flavor;
9575b0d146aSStefano Zampini   w->flavor = PETSCSF_WINDOW_FLAVOR_CREATE;
958684a874aSStefano Zampini   ierr = PetscSFGetWindow(sf,unit,rootdata,PETSCSF_WINDOW_SYNC_LOCK,PETSC_FALSE,0,0,0,&target_disp,NULL,&win);CHKERRQ(ierr);
9595b0d146aSStefano Zampini #else
960684a874aSStefano Zampini   ierr = PetscSFGetWindow(sf,unit,rootdata,w->sync,PETSC_TRUE,MPI_MODE_NOPRECEDE,0,0,&target_disp,NULL,&win);CHKERRQ(ierr);
9615b0d146aSStefano Zampini #endif
9625b0d146aSStefano Zampini   for (i=0; i<nranks; i++) {
9635b0d146aSStefano Zampini     MPI_Aint tdp = target_disp ? target_disp[i] : 0;
9645b0d146aSStefano Zampini 
9655b0d146aSStefano Zampini #if !defined(PETSC_HAVE_MPI_GET_ACCUMULATE)
9665b0d146aSStefano Zampini     ierr = MPI_Win_lock(MPI_LOCK_EXCLUSIVE,ranks[i],0,win);CHKERRQ(ierr);
9675b0d146aSStefano Zampini     ierr = MPI_Get(leafupdate,1,mine[i],ranks[i],tdp,1,remote[i],win);CHKERRQ(ierr);
9685b0d146aSStefano Zampini     ierr = MPI_Accumulate((void*)leafdata,1,mine[i],ranks[i],tdp,1,remote[i],op,win);
9695b0d146aSStefano Zampini     if (ierr) { /* intercept the MPI error since the combination of unit and op is not supported */
9705b0d146aSStefano Zampini       PetscMPIInt len;
9715b0d146aSStefano Zampini       char        errstring[MPI_MAX_ERROR_STRING];
9725b0d146aSStefano Zampini 
9735b0d146aSStefano Zampini       MPI_Error_string(ierr,errstring,&len);
9745b0d146aSStefano Zampini       SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_SUP,"Internal error in MPI: %s",errstring);
97595fce210SBarry Smith     }
9765b0d146aSStefano Zampini     ierr = MPI_Win_unlock(ranks[i],win);CHKERRQ(ierr);
9775b0d146aSStefano Zampini #else
9785b0d146aSStefano Zampini     if (w->sync == PETSCSF_WINDOW_SYNC_LOCK) { ierr = MPI_Win_lock(MPI_LOCK_SHARED,ranks[i],0,win);CHKERRQ(ierr); }
9795b0d146aSStefano Zampini     ierr = MPI_Get_accumulate((void*)leafdata,1,mine[i],leafupdate,1,mine[i],ranks[i],tdp,1,remote[i],op,win);
9805b0d146aSStefano Zampini     if (ierr) { /* intercept the MPI error since the combination of unit and op is not supported */
9815b0d146aSStefano Zampini       PetscMPIInt len;
9825b0d146aSStefano Zampini       char        errstring[MPI_MAX_ERROR_STRING];
9835b0d146aSStefano Zampini 
9845b0d146aSStefano Zampini       MPI_Error_string(ierr,errstring,&len);
9855b0d146aSStefano Zampini       SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_SUP,"Internal error in MPI: %s",errstring);
9865b0d146aSStefano Zampini     }
9875b0d146aSStefano Zampini     if (w->sync == PETSCSF_WINDOW_SYNC_LOCK) { ierr = MPI_Win_unlock(ranks[i],win);CHKERRQ(ierr); }
9885b0d146aSStefano Zampini #endif
9895b0d146aSStefano Zampini   }
9905b0d146aSStefano Zampini #if !defined(PETSC_HAVE_MPI_GET_ACCUMULATE)
9915b0d146aSStefano Zampini   w->flavor = oldf;
9925b0d146aSStefano Zampini #endif
99395fce210SBarry Smith   PetscFunctionReturn(0);
99495fce210SBarry Smith }
99595fce210SBarry Smith 
996*00816365SJunchao Zhang static PetscErrorCode PetscSFFetchAndOpEnd_Window(PetscSF sf,MPI_Datatype unit,void *rootdata,const void *leafdata,void *leafupdate,MPI_Op op)
99795fce210SBarry Smith {
99895fce210SBarry Smith   PetscErrorCode ierr;
99995fce210SBarry Smith   MPI_Win        win;
10005b0d146aSStefano Zampini #if defined(PETSC_HAVE_MPI_GET_ACCUMULATE)
10015b0d146aSStefano Zampini   PetscSF_Window *w = (PetscSF_Window*)sf->data;
10025b0d146aSStefano Zampini #endif
1003684a874aSStefano Zampini   MPI_Request    *reqs;
100495fce210SBarry Smith 
100595fce210SBarry Smith   PetscFunctionBegin;
1006684a874aSStefano Zampini   ierr = PetscSFFindWindow(sf,unit,rootdata,&win,&reqs);CHKERRQ(ierr);
1007684a874aSStefano Zampini   if (reqs) { ierr = MPI_Waitall(sf->nranks,reqs,MPI_STATUSES_IGNORE);CHKERRQ(ierr); }
10085b0d146aSStefano Zampini #if defined(PETSC_HAVE_MPI_GET_ACCUMULATE)
10095b0d146aSStefano Zampini   ierr = PetscSFRestoreWindow(sf,unit,rootdata,w->sync,PETSC_TRUE,MPI_MODE_NOSUCCEED,PETSC_TRUE,&win);CHKERRQ(ierr);
10105b0d146aSStefano Zampini #else
10115b0d146aSStefano Zampini   ierr = PetscSFRestoreWindow(sf,unit,rootdata,PETSCSF_WINDOW_SYNC_LOCK,PETSC_FALSE,0,PETSC_TRUE,&win);CHKERRQ(ierr);
10125b0d146aSStefano Zampini #endif
101395fce210SBarry Smith   PetscFunctionReturn(0);
101495fce210SBarry Smith }
101595fce210SBarry Smith 
1016dec1416fSJunchao Zhang PETSC_INTERN PetscErrorCode PetscSFCreate_Window(PetscSF sf)
101795fce210SBarry Smith {
101895fce210SBarry Smith   PetscSF_Window *w = (PetscSF_Window*)sf->data;
101995fce210SBarry Smith   PetscErrorCode ierr;
102095fce210SBarry Smith 
102195fce210SBarry Smith   PetscFunctionBegin;
102295fce210SBarry Smith   sf->ops->SetUp           = PetscSFSetUp_Window;
102395fce210SBarry Smith   sf->ops->SetFromOptions  = PetscSFSetFromOptions_Window;
102495fce210SBarry Smith   sf->ops->Reset           = PetscSFReset_Window;
102595fce210SBarry Smith   sf->ops->Destroy         = PetscSFDestroy_Window;
102695fce210SBarry Smith   sf->ops->View            = PetscSFView_Window;
102795fce210SBarry Smith   sf->ops->Duplicate       = PetscSFDuplicate_Window;
1028de49d1a2SJunchao Zhang   sf->ops->BcastAndOpBegin = PetscSFBcastAndOpBegin_Window;
1029de49d1a2SJunchao Zhang   sf->ops->BcastAndOpEnd   = PetscSFBcastAndOpEnd_Window;
103095fce210SBarry Smith   sf->ops->ReduceBegin     = PetscSFReduceBegin_Window;
103195fce210SBarry Smith   sf->ops->ReduceEnd       = PetscSFReduceEnd_Window;
103295fce210SBarry Smith   sf->ops->FetchAndOpBegin = PetscSFFetchAndOpBegin_Window;
103395fce210SBarry Smith   sf->ops->FetchAndOpEnd   = PetscSFFetchAndOpEnd_Window;
103495fce210SBarry Smith 
1035b00a9115SJed Brown   ierr = PetscNewLog(sf,&w);CHKERRQ(ierr);
103695fce210SBarry Smith   sf->data  = (void*)w;
103795fce210SBarry Smith   w->sync   = PETSCSF_WINDOW_SYNC_FENCE;
10385b0d146aSStefano Zampini   w->flavor = PETSCSF_WINDOW_FLAVOR_CREATE;
10395b0d146aSStefano Zampini   w->info   = MPI_INFO_NULL;
104095fce210SBarry Smith 
1041bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)sf,"PetscSFWindowSetSyncType_C",PetscSFWindowSetSyncType_Window);CHKERRQ(ierr);
1042bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)sf,"PetscSFWindowGetSyncType_C",PetscSFWindowGetSyncType_Window);CHKERRQ(ierr);
10435b0d146aSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)sf,"PetscSFWindowSetFlavorType_C",PetscSFWindowSetFlavorType_Window);CHKERRQ(ierr);
10445b0d146aSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)sf,"PetscSFWindowGetFlavorType_C",PetscSFWindowGetFlavorType_Window);CHKERRQ(ierr);
10455b0d146aSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)sf,"PetscSFWindowSetInfo_C",PetscSFWindowSetInfo_Window);CHKERRQ(ierr);
10465b0d146aSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)sf,"PetscSFWindowGetInfo_C",PetscSFWindowGetInfo_Window);CHKERRQ(ierr);
104795fce210SBarry Smith 
104895fce210SBarry Smith #if defined(OMPI_MAJOR_VERSION) && (OMPI_MAJOR_VERSION < 1 || (OMPI_MAJOR_VERSION == 1 && OMPI_MINOR_VERSION <= 6))
104995fce210SBarry Smith   {
105095fce210SBarry Smith     PetscBool ackbug = PETSC_FALSE;
1051c5929fdfSBarry Smith     ierr = PetscOptionsGetBool(NULL,NULL,"-acknowledge_ompi_onesided_bug",&ackbug,NULL);CHKERRQ(ierr);
105295fce210SBarry Smith     if (ackbug) {
1053955c1f14SBarry Smith       ierr = PetscInfo(sf,"Acknowledged Open MPI bug, proceeding anyway. Expect memory corruption.\n");CHKERRQ(ierr);
105495fce210SBarry 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");
105595fce210SBarry Smith   }
105695fce210SBarry Smith #endif
105795fce210SBarry Smith   PetscFunctionReturn(0);
105895fce210SBarry Smith }
1059