xref: /petsc/src/vec/is/sf/impls/window/sfwindow.c (revision 62152ded5d3f58425759210e6510d2e74b2caa3e)
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 
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);
89ffc4695bSBarry Smith   ierr = MPI_Type_dup(unit,&link->unit);CHKERRMPI(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 
106ffc4695bSBarry Smith     ierr = MPI_Type_create_indexed_block(rcount,1,rmine,link->unit,&link->mine[i]);CHKERRMPI(ierr);
107ffc4695bSBarry Smith     ierr = MPI_Type_create_indexed_block(rcount,1,rremote,link->unit,&link->remote[i]);CHKERRMPI(ierr);
10895fce210SBarry Smith #if defined(PETSC_USE_64BIT_INDICES)
10995fce210SBarry Smith     ierr = PetscFree2(rmine,rremote);CHKERRQ(ierr);
11095fce210SBarry Smith #endif
111ffc4695bSBarry Smith     ierr = MPI_Type_commit(&link->mine[i]);CHKERRMPI(ierr);
112ffc4695bSBarry Smith     ierr = MPI_Type_commit(&link->remote[i]);CHKERRMPI(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) {
318ffc4695bSBarry Smith     ierr = MPI_Info_free(&w->info);CHKERRMPI(ierr);
3195b0d146aSStefano Zampini   }
3205b0d146aSStefano Zampini   if (info != MPI_INFO_NULL) {
321ffc4695bSBarry Smith     ierr = MPI_Info_dup(info,&w->info);CHKERRMPI(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   PetscBool      dummy[2];
3965b0d146aSStefano Zampini   MPI_Aint       wsize;
39795fce210SBarry Smith 
39895fce210SBarry Smith   PetscFunctionBegin;
399ffc4695bSBarry Smith   ierr = MPI_Type_get_extent(unit,&lb,&bytes);CHKERRMPI(ierr);
400ffc4695bSBarry Smith   ierr = MPI_Type_get_true_extent(unit,&lb_true,&bytes_true);CHKERRMPI(ierr);
40195fce210SBarry 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");
40295fce210SBarry 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");
4035b0d146aSStefano Zampini   if (w->flavor != PETSCSF_WINDOW_FLAVOR_CREATE) reuse = PETSC_TRUE;
4045b0d146aSStefano Zampini   for (link=w->wins; reuse && link; link=link->next) {
4055b0d146aSStefano Zampini     PetscBool winok = PETSC_FALSE;
4065b0d146aSStefano Zampini     if (w->flavor != link->flavor) continue;
4075b0d146aSStefano Zampini     switch (w->flavor) {
4085b0d146aSStefano 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) */
4095b0d146aSStefano Zampini       if (array == link->addr) {
41076bd3646SJed Brown         if (PetscDefined(USE_DEBUG)) {
4115b0d146aSStefano Zampini           dummy[0] = PETSC_TRUE;
4125b0d146aSStefano Zampini           dummy[1] = PETSC_TRUE;
413ffc4695bSBarry Smith           ierr = MPI_Allreduce(MPI_IN_PLACE,dummy,1,MPIU_BOOL,MPI_LAND,PetscObjectComm((PetscObject)sf));CHKERRMPI(ierr);
414ffc4695bSBarry Smith           ierr = MPI_Allreduce(MPI_IN_PLACE,dummy+1,1,MPIU_BOOL,MPI_LOR ,PetscObjectComm((PetscObject)sf));CHKERRMPI(ierr);
4155b0d146aSStefano 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");
41676bd3646SJed Brown         }
4175b0d146aSStefano Zampini         if (link->inuse) SETERRQ(PetscObjectComm((PetscObject)sf),PETSC_ERR_PLIB,"Window in use");
4185b0d146aSStefano Zampini         if (epoch && link->epoch) SETERRQ(PetscObjectComm((PetscObject)sf),PETSC_ERR_PLIB,"Window epoch not finished");
4195b0d146aSStefano Zampini         winok = PETSC_TRUE;
4205b0d146aSStefano Zampini         link->paddr = array;
42176bd3646SJed Brown       } else if (PetscDefined(USE_DEBUG)) {
4225b0d146aSStefano Zampini         dummy[0] = PETSC_FALSE;
4235b0d146aSStefano Zampini         dummy[1] = PETSC_FALSE;
424ffc4695bSBarry Smith         ierr = MPI_Allreduce(MPI_IN_PLACE,dummy  ,1,MPIU_BOOL,MPI_LAND,PetscObjectComm((PetscObject)sf));CHKERRMPI(ierr);
425ffc4695bSBarry Smith         ierr = MPI_Allreduce(MPI_IN_PLACE,dummy+1,1,MPIU_BOOL,MPI_LOR ,PetscObjectComm((PetscObject)sf));CHKERRMPI(ierr);
4265b0d146aSStefano 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");
4275b0d146aSStefano Zampini       }
4285b0d146aSStefano Zampini       break;
4295b0d146aSStefano Zampini     case PETSCSF_WINDOW_FLAVOR_ALLOCATE: /* check available by matching size, allocate if in use */
4305b0d146aSStefano Zampini     case PETSCSF_WINDOW_FLAVOR_SHARED:
4315b0d146aSStefano Zampini       if (!link->inuse && bytes == (MPI_Aint)link->bytes) {
4325b0d146aSStefano Zampini         update = PETSC_TRUE;
4335b0d146aSStefano Zampini         link->paddr = array;
4345b0d146aSStefano Zampini         winok = PETSC_TRUE;
4355b0d146aSStefano Zampini       }
4365b0d146aSStefano Zampini       break;
4375b0d146aSStefano Zampini     default: SETERRQ1(PetscObjectComm((PetscObject)sf),PETSC_ERR_SUP,"No support for flavor %s",PetscSFWindowFlavorTypes[w->flavor]);
4385b0d146aSStefano Zampini     }
4395b0d146aSStefano Zampini     if (winok) {
4405b0d146aSStefano Zampini       *win = link->win;
4415b0d146aSStefano Zampini       ierr = PetscInfo3(sf,"Reusing window %d of flavor %d for comm %d\n",link->win,link->flavor,PetscObjectComm((PetscObject)sf));CHKERRQ(ierr);
4425b0d146aSStefano Zampini       goto found;
4435b0d146aSStefano Zampini     }
4445b0d146aSStefano Zampini   }
4455b0d146aSStefano Zampini 
4465b0d146aSStefano Zampini   wsize = (MPI_Aint)bytes*sf->nroots;
44795dccacaSBarry Smith   ierr = PetscNew(&link);CHKERRQ(ierr);
44895fce210SBarry Smith   link->bytes           = bytes;
44995fce210SBarry Smith   link->next            = w->wins;
4505b0d146aSStefano Zampini   link->flavor          = w->flavor;
4515b0d146aSStefano Zampini   link->dyn_target_addr = NULL;
452684a874aSStefano Zampini   link->reqs            = NULL;
45395fce210SBarry Smith   w->wins               = link;
454684a874aSStefano Zampini   if (sync == PETSCSF_WINDOW_SYNC_LOCK) {
455684a874aSStefano Zampini     PetscInt i;
456684a874aSStefano Zampini 
457684a874aSStefano Zampini     ierr = PetscMalloc1(sf->nranks,&link->reqs);CHKERRQ(ierr);
458684a874aSStefano Zampini     for (i = 0; i < sf->nranks; i++) link->reqs[i] = MPI_REQUEST_NULL;
459684a874aSStefano Zampini   }
4605b0d146aSStefano Zampini   switch (w->flavor) {
4615b0d146aSStefano Zampini   case PETSCSF_WINDOW_FLAVOR_CREATE:
462ffc4695bSBarry Smith     ierr = MPI_Win_create(array,wsize,(PetscMPIInt)bytes,w->info,PetscObjectComm((PetscObject)sf),&link->win);CHKERRMPI(ierr);
4635b0d146aSStefano Zampini     link->addr  = array;
4645b0d146aSStefano Zampini     link->paddr = array;
4655b0d146aSStefano Zampini     break;
4665b0d146aSStefano Zampini   case PETSCSF_WINDOW_FLAVOR_DYNAMIC:
467ffc4695bSBarry Smith     ierr = MPI_Win_create_dynamic(w->info,PetscObjectComm((PetscObject)sf),&link->win);CHKERRMPI(ierr);
4685b0d146aSStefano Zampini #if defined(PETSC_HAVE_OMPI_MAJOR_VERSION) /* some OpenMPI versions do not support MPI_Win_attach(win,NULL,0); */
469ffc4695bSBarry Smith     ierr = MPI_Win_attach(link->win,wsize ? array : &ierr,wsize);CHKERRMPI(ierr);
4705b0d146aSStefano Zampini #else
471ffc4695bSBarry Smith     ierr = MPI_Win_attach(link->win,array,wsize);CHKERRMPI(ierr);
4725b0d146aSStefano Zampini #endif
4735b0d146aSStefano Zampini     link->addr  = array;
4745b0d146aSStefano Zampini     link->paddr = array;
4755b0d146aSStefano Zampini     if (!w->dynsf) SETERRQ(PetscObjectComm((PetscObject)sf),PETSC_ERR_ORDER,"Must call PetscSFSetUp()");
4765b0d146aSStefano Zampini     ierr = PetscSFSetUp(w->dynsf);CHKERRQ(ierr);
4775b0d146aSStefano Zampini     ierr = PetscSFGetRootRanks(w->dynsf,&nranks,NULL,NULL,NULL,NULL);CHKERRQ(ierr);
4785b0d146aSStefano Zampini     ierr = PetscMalloc1(nranks,&link->dyn_target_addr);CHKERRQ(ierr);
479ffc4695bSBarry Smith     ierr = MPI_Get_address(array,&winaddr);CHKERRMPI(ierr);
4805b0d146aSStefano Zampini     ierr = PetscSFBcastBegin(w->dynsf,MPI_AINT,&winaddr,link->dyn_target_addr);CHKERRQ(ierr);
4815b0d146aSStefano Zampini     ierr = PetscSFBcastEnd(w->dynsf,MPI_AINT,&winaddr,link->dyn_target_addr);CHKERRQ(ierr);
4825b0d146aSStefano Zampini     break;
4835b0d146aSStefano Zampini   case PETSCSF_WINDOW_FLAVOR_ALLOCATE:
484ffc4695bSBarry Smith     ierr = MPI_Win_allocate(wsize,(PetscMPIInt)bytes,w->info,PetscObjectComm((PetscObject)sf),&link->addr,&link->win);CHKERRMPI(ierr);
4855b0d146aSStefano Zampini     update = PETSC_TRUE;
4865b0d146aSStefano Zampini     link->paddr = array;
4875b0d146aSStefano Zampini     break;
4885b0d146aSStefano Zampini #if defined(PETSC_HAVE_MPI_PROCESS_SHARED_MEMORY)
4895b0d146aSStefano Zampini   case PETSCSF_WINDOW_FLAVOR_SHARED:
490ffc4695bSBarry Smith     ierr = MPI_Win_allocate_shared(wsize,(PetscMPIInt)bytes,w->info,PetscObjectComm((PetscObject)sf),&link->addr,&link->win);CHKERRMPI(ierr);
4915b0d146aSStefano Zampini     update = PETSC_TRUE;
4925b0d146aSStefano Zampini     link->paddr = array;
4935b0d146aSStefano Zampini     break;
4945b0d146aSStefano Zampini #endif
4955b0d146aSStefano Zampini   default: SETERRQ1(PetscObjectComm((PetscObject)sf),PETSC_ERR_SUP,"No support for flavor %s",PetscSFWindowFlavorTypes[w->flavor]);
4965b0d146aSStefano Zampini   }
4975b0d146aSStefano Zampini   ierr = PetscInfo3(sf,"New window %d of flavor %d for comm %d\n",link->win,link->flavor,PetscObjectComm((PetscObject)sf));CHKERRQ(ierr);
49895fce210SBarry Smith   *win = link->win;
49995fce210SBarry Smith 
5005b0d146aSStefano Zampini found:
5015b0d146aSStefano Zampini 
502684a874aSStefano Zampini   if (target_disp) *target_disp = link->dyn_target_addr;
503684a874aSStefano Zampini   if (reqs) *reqs = link->reqs;
504684a874aSStefano Zampini   if (update) { /* locks are needed for the "separate" memory model only, the fence guaranties memory-synchronization */
505684a874aSStefano Zampini     PetscMPIInt rank;
506684a874aSStefano Zampini 
507ffc4695bSBarry Smith     ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)sf),&rank);CHKERRMPI(ierr);
508ffc4695bSBarry Smith     if (sync == PETSCSF_WINDOW_SYNC_LOCK) {ierr = MPI_Win_lock(MPI_LOCK_EXCLUSIVE,rank,MPI_MODE_NOCHECK,*win);CHKERRMPI(ierr);}
5095b0d146aSStefano Zampini     ierr = PetscMemcpy(link->addr,array,sf->nroots*bytes);CHKERRQ(ierr);
5105b0d146aSStefano Zampini     if (sync == PETSCSF_WINDOW_SYNC_LOCK) {
511ffc4695bSBarry Smith       ierr = MPI_Win_unlock(rank,*win);CHKERRMPI(ierr);
512ffc4695bSBarry Smith       ierr = MPI_Win_fence(0,*win);CHKERRMPI(ierr);
5135b0d146aSStefano Zampini     }
5145b0d146aSStefano Zampini   }
5155b0d146aSStefano Zampini   link->inuse = PETSC_TRUE;
5165b0d146aSStefano Zampini   link->epoch = epoch;
51795fce210SBarry Smith   if (epoch) {
5185b0d146aSStefano Zampini     switch (sync) {
51995fce210SBarry Smith     case PETSCSF_WINDOW_SYNC_FENCE:
520ffc4695bSBarry Smith       ierr = MPI_Win_fence(fenceassert,*win);CHKERRMPI(ierr);
52195fce210SBarry Smith       break;
52295fce210SBarry Smith     case PETSCSF_WINDOW_SYNC_LOCK: /* Handled outside */
52395fce210SBarry Smith       break;
52495fce210SBarry Smith     case PETSCSF_WINDOW_SYNC_ACTIVE: {
52595fce210SBarry Smith       MPI_Group   ingroup,outgroup;
5265b0d146aSStefano Zampini       PetscMPIInt isize,osize;
5275b0d146aSStefano Zampini 
5285b0d146aSStefano Zampini       /* OpenMPI 4.0.2 with btl=vader does not like calling
5295b0d146aSStefano Zampini          - MPI_Win_complete when ogroup is empty
5305b0d146aSStefano Zampini          - MPI_Win_wait when igroup is empty
5315b0d146aSStefano Zampini          So, we do not even issue the corresponding start and post calls
5325b0d146aSStefano Zampini          The MPI standard (Sec. 11.5.2 of MPI 3.1) only requires that
5335b0d146aSStefano Zampini          start(outgroup) has a matching post(ingroup)
5345b0d146aSStefano Zampini          and this is guaranteed by PetscSF
5355b0d146aSStefano Zampini       */
53695fce210SBarry Smith       ierr = PetscSFGetGroups(sf,&ingroup,&outgroup);CHKERRQ(ierr);
537ffc4695bSBarry Smith       ierr = MPI_Group_size(ingroup,&isize);CHKERRMPI(ierr);
538ffc4695bSBarry Smith       ierr = MPI_Group_size(outgroup,&osize);CHKERRMPI(ierr);
539ffc4695bSBarry Smith       if (isize) {ierr = MPI_Win_post(ingroup,postassert,*win);CHKERRMPI(ierr);}
540ffc4695bSBarry Smith       if (osize) {ierr = MPI_Win_start(outgroup,startassert,*win);CHKERRMPI(ierr);}
54195fce210SBarry Smith     } break;
54295fce210SBarry Smith     default: SETERRQ(PetscObjectComm((PetscObject)sf),PETSC_ERR_PLIB,"Unknown synchronization type");
54395fce210SBarry Smith     }
54495fce210SBarry Smith   }
54595fce210SBarry Smith   PetscFunctionReturn(0);
54695fce210SBarry Smith }
54795fce210SBarry Smith 
5485b0d146aSStefano Zampini /*
54995fce210SBarry Smith    PetscSFFindWindow - Finds a window that is already in use
55095fce210SBarry Smith 
55195fce210SBarry Smith    Not Collective
55295fce210SBarry Smith 
55395fce210SBarry Smith    Input Arguments:
55495fce210SBarry Smith +  sf - star forest
55595fce210SBarry Smith .  unit - data type
55695fce210SBarry Smith -  array - array with which the window is associated
55795fce210SBarry Smith 
55895fce210SBarry Smith    Output Arguments:
559684a874aSStefano Zampini +  win - window
560684a874aSStefano Zampini -  reqs - outstanding requests associated to the window
56195fce210SBarry Smith 
56295fce210SBarry Smith    Level: developer
56395fce210SBarry Smith 
56495fce210SBarry Smith .seealso: PetscSFGetWindow(), PetscSFRestoreWindow()
5655b0d146aSStefano Zampini */
566684a874aSStefano Zampini static PetscErrorCode PetscSFFindWindow(PetscSF sf,MPI_Datatype unit,const void *array,MPI_Win *win,MPI_Request **reqs)
56795fce210SBarry Smith {
56895fce210SBarry Smith   PetscSF_Window *w = (PetscSF_Window*)sf->data;
56995fce210SBarry Smith   PetscSFWinLink link;
5705b0d146aSStefano Zampini   PetscErrorCode ierr;
57195fce210SBarry Smith 
57295fce210SBarry Smith   PetscFunctionBegin;
573c0cd0301SJed Brown   *win = MPI_WIN_NULL;
57495fce210SBarry Smith   for (link=w->wins; link; link=link->next) {
5755b0d146aSStefano Zampini     if (array == link->paddr) {
5765b0d146aSStefano Zampini       ierr = PetscInfo3(sf,"Window %d of flavor %d for comm %d\n",link->win,link->flavor,PetscObjectComm((PetscObject)sf));CHKERRQ(ierr);
57795fce210SBarry Smith       *win = link->win;
578684a874aSStefano Zampini       *reqs = link->reqs;
57995fce210SBarry Smith       PetscFunctionReturn(0);
58095fce210SBarry Smith     }
58195fce210SBarry Smith   }
58295fce210SBarry Smith   SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Requested window not in use");
58395fce210SBarry Smith }
58495fce210SBarry Smith 
5855b0d146aSStefano Zampini /*
58695fce210SBarry Smith    PetscSFRestoreWindow - Restores a window obtained with PetscSFGetWindow()
58795fce210SBarry Smith 
58895fce210SBarry Smith    Collective
58995fce210SBarry Smith 
59095fce210SBarry Smith    Input Arguments:
59195fce210SBarry Smith +  sf - star forest
59295fce210SBarry Smith .  unit - data type
59395fce210SBarry Smith .  array - array associated with window
5945b0d146aSStefano Zampini .  sync - type of synchronization PetscSFWindowSyncType
59595fce210SBarry Smith .  epoch - close an epoch, must match argument to PetscSFGetWindow()
5965b0d146aSStefano Zampini .  update - if we have to update the local window array
59795fce210SBarry Smith -  win - window
59895fce210SBarry Smith 
59995fce210SBarry Smith    Level: developer
60095fce210SBarry Smith 
60195fce210SBarry Smith .seealso: PetscSFFindWindow()
6025b0d146aSStefano Zampini */
6035b0d146aSStefano Zampini static PetscErrorCode PetscSFRestoreWindow(PetscSF sf,MPI_Datatype unit,void *array,PetscSFWindowSyncType sync,PetscBool epoch,PetscMPIInt fenceassert,PetscBool update,MPI_Win *win)
60495fce210SBarry Smith {
60595fce210SBarry Smith   PetscSF_Window          *w = (PetscSF_Window*)sf->data;
60695fce210SBarry Smith   PetscErrorCode          ierr;
60795fce210SBarry Smith   PetscSFWinLink          *p,link;
6085b0d146aSStefano Zampini   PetscBool               reuse = PETSC_FALSE;
6095b0d146aSStefano Zampini   PetscSFWindowFlavorType flavor;
6105b0d146aSStefano Zampini   void*                   laddr;
6115b0d146aSStefano Zampini   size_t                  bytes;
61295fce210SBarry Smith 
61395fce210SBarry Smith   PetscFunctionBegin;
61495fce210SBarry Smith   for (p=&w->wins; *p; p=&(*p)->next) {
61595fce210SBarry Smith     link = *p;
61695fce210SBarry Smith     if (*win == link->win) {
6175b0d146aSStefano Zampini       if (array != link->paddr) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Matched window, but not array");
61895fce210SBarry Smith       if (epoch != link->epoch) {
61995fce210SBarry Smith         if (epoch) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"No epoch to end");
62095fce210SBarry Smith         else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Restoring window without ending epoch");
62195fce210SBarry Smith       }
6225b0d146aSStefano Zampini       laddr = link->addr;
6235b0d146aSStefano Zampini       flavor = link->flavor;
6245b0d146aSStefano Zampini       bytes = link->bytes;
6255b0d146aSStefano Zampini       if (flavor != PETSCSF_WINDOW_FLAVOR_CREATE) reuse = PETSC_TRUE;
6265b0d146aSStefano Zampini       else { *p = link->next; update = PETSC_FALSE; } /* remove from list */
62795fce210SBarry Smith       goto found;
62895fce210SBarry Smith     }
62995fce210SBarry Smith   }
63095fce210SBarry Smith   SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Requested window not in use");
63195fce210SBarry Smith 
63295fce210SBarry Smith found:
6335b0d146aSStefano Zampini   ierr = PetscInfo3(sf,"Window %d of flavor %d for comm %d\n",link->win,link->flavor,PetscObjectComm((PetscObject)sf));CHKERRQ(ierr);
63495fce210SBarry Smith   if (epoch) {
6355b0d146aSStefano Zampini     switch (sync) {
63695fce210SBarry Smith     case PETSCSF_WINDOW_SYNC_FENCE:
637ffc4695bSBarry Smith       ierr = MPI_Win_fence(fenceassert,*win);CHKERRMPI(ierr);
63895fce210SBarry Smith       break;
6395b0d146aSStefano Zampini     case PETSCSF_WINDOW_SYNC_LOCK: /* Handled outside */
6405b0d146aSStefano Zampini       break;
64195fce210SBarry Smith     case PETSCSF_WINDOW_SYNC_ACTIVE: {
6425b0d146aSStefano Zampini       MPI_Group   ingroup,outgroup;
6435b0d146aSStefano Zampini       PetscMPIInt isize,osize;
6445b0d146aSStefano Zampini 
6455b0d146aSStefano Zampini       /* OpenMPI 4.0.2 with btl=wader does not like calling
6465b0d146aSStefano Zampini          - MPI_Win_complete when ogroup is empty
6475b0d146aSStefano Zampini          - MPI_Win_wait when igroup is empty
6485b0d146aSStefano Zampini          The MPI standard (Sec. 11.5.2 of MPI 3.1) only requires that
6495b0d146aSStefano Zampini          - each process who issues a call to MPI_Win_start issues a call to MPI_Win_Complete
6505b0d146aSStefano Zampini          - each process who issues a call to MPI_Win_post issues a call to MPI_Win_Wait
6515b0d146aSStefano Zampini       */
6525b0d146aSStefano Zampini       ierr = PetscSFGetGroups(sf,&ingroup,&outgroup);CHKERRQ(ierr);
653ffc4695bSBarry Smith       ierr = MPI_Group_size(ingroup,&isize);CHKERRMPI(ierr);
654ffc4695bSBarry Smith       ierr = MPI_Group_size(outgroup,&osize);CHKERRMPI(ierr);
655ffc4695bSBarry Smith       if (osize) {ierr = MPI_Win_complete(*win);CHKERRMPI(ierr);}
656ffc4695bSBarry Smith       if (isize) {ierr = MPI_Win_wait(*win);CHKERRMPI(ierr);}
65795fce210SBarry Smith     } break;
65895fce210SBarry Smith     default: SETERRQ(PetscObjectComm((PetscObject)sf),PETSC_ERR_PLIB,"Unknown synchronization type");
65995fce210SBarry Smith     }
66095fce210SBarry Smith   }
6615b0d146aSStefano Zampini   if (update) {
6625b0d146aSStefano Zampini     if (sync == PETSCSF_WINDOW_SYNC_LOCK) {
663ffc4695bSBarry Smith       ierr = MPI_Win_fence(MPI_MODE_NOPUT|MPI_MODE_NOSUCCEED,*win);CHKERRMPI(ierr);
6645b0d146aSStefano Zampini     }
6655b0d146aSStefano Zampini     ierr = PetscMemcpy(array,laddr,sf->nroots*bytes);CHKERRQ(ierr);
6665b0d146aSStefano Zampini   }
6675b0d146aSStefano Zampini   link->epoch = PETSC_FALSE;
6685b0d146aSStefano Zampini   link->inuse = PETSC_FALSE;
6695b0d146aSStefano Zampini   link->paddr = NULL;
6705b0d146aSStefano Zampini   if (!reuse) {
671684a874aSStefano Zampini     ierr = PetscFree(link->dyn_target_addr);CHKERRQ(ierr);
672684a874aSStefano Zampini     ierr = PetscFree(link->reqs);CHKERRQ(ierr);
673ffc4695bSBarry Smith     ierr = MPI_Win_free(&link->win);CHKERRMPI(ierr);
67495fce210SBarry Smith     ierr = PetscFree(link);CHKERRQ(ierr);
67595fce210SBarry Smith     *win = MPI_WIN_NULL;
6765b0d146aSStefano Zampini   }
67795fce210SBarry Smith   PetscFunctionReturn(0);
67895fce210SBarry Smith }
67995fce210SBarry Smith 
68095fce210SBarry Smith static PetscErrorCode PetscSFSetUp_Window(PetscSF sf)
68195fce210SBarry Smith {
68295fce210SBarry Smith   PetscSF_Window *w = (PetscSF_Window*)sf->data;
68395fce210SBarry Smith   PetscErrorCode ierr;
68495fce210SBarry Smith   MPI_Group      ingroup,outgroup;
68595fce210SBarry Smith 
68695fce210SBarry Smith   PetscFunctionBegin;
687b5a8e515SJed Brown   ierr = PetscSFSetUpRanks(sf,MPI_GROUP_EMPTY);CHKERRQ(ierr);
6885b0d146aSStefano Zampini   if (!w->dynsf) {
6895b0d146aSStefano Zampini     PetscInt    i;
6905b0d146aSStefano Zampini     PetscSFNode *remotes;
6915b0d146aSStefano Zampini 
6925b0d146aSStefano Zampini     ierr = PetscMalloc1(sf->nranks,&remotes);CHKERRQ(ierr);
6935b0d146aSStefano Zampini     for (i=0;i<sf->nranks;i++) {
6945b0d146aSStefano Zampini       remotes[i].rank  = sf->ranks[i];
6955b0d146aSStefano Zampini       remotes[i].index = 0;
6965b0d146aSStefano Zampini     }
6975b0d146aSStefano Zampini     ierr = PetscSFDuplicate(sf,PETSCSF_DUPLICATE_RANKS,&w->dynsf);CHKERRQ(ierr);
6985b0d146aSStefano Zampini     ierr = PetscSFWindowSetFlavorType(w->dynsf,PETSCSF_WINDOW_FLAVOR_CREATE);CHKERRQ(ierr); /* break recursion */
6995b0d146aSStefano Zampini     ierr = PetscSFSetGraph(w->dynsf,1,sf->nranks,NULL,PETSC_OWN_POINTER,remotes,PETSC_OWN_POINTER);CHKERRQ(ierr);
7005b0d146aSStefano Zampini     ierr = PetscLogObjectParent((PetscObject)sf,(PetscObject)w->dynsf);CHKERRQ(ierr);
7015b0d146aSStefano Zampini   }
70295fce210SBarry Smith   switch (w->sync) {
70395fce210SBarry Smith   case PETSCSF_WINDOW_SYNC_ACTIVE:
70495fce210SBarry Smith     ierr = PetscSFGetGroups(sf,&ingroup,&outgroup);CHKERRQ(ierr);
70595fce210SBarry Smith   default:
70695fce210SBarry Smith     break;
70795fce210SBarry Smith   }
70895fce210SBarry Smith   PetscFunctionReturn(0);
70995fce210SBarry Smith }
71095fce210SBarry Smith 
7114416b707SBarry Smith static PetscErrorCode PetscSFSetFromOptions_Window(PetscOptionItems *PetscOptionsObject,PetscSF sf)
71295fce210SBarry Smith {
71395fce210SBarry Smith   PetscSF_Window          *w = (PetscSF_Window*)sf->data;
71495fce210SBarry Smith   PetscErrorCode          ierr;
7155b0d146aSStefano Zampini   PetscSFWindowFlavorType flavor = w->flavor;
71695fce210SBarry Smith 
71795fce210SBarry Smith   PetscFunctionBegin;
718e55864a3SBarry Smith   ierr = PetscOptionsHead(PetscOptionsObject,"PetscSF Window options");CHKERRQ(ierr);
71995fce210SBarry 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);
7205b0d146aSStefano Zampini   ierr = PetscOptionsEnum("-sf_window_flavor","flavor to use for PetscSF Window creation","PetscSFWindowSetFlavorType",PetscSFWindowFlavorTypes,(PetscEnum)flavor,(PetscEnum*)&flavor,NULL);CHKERRQ(ierr);
7215b0d146aSStefano Zampini   ierr = PetscSFWindowSetFlavorType(sf,flavor);CHKERRQ(ierr);
72295fce210SBarry Smith   ierr = PetscOptionsTail();CHKERRQ(ierr);
72395fce210SBarry Smith   PetscFunctionReturn(0);
72495fce210SBarry Smith }
72595fce210SBarry Smith 
72695fce210SBarry Smith static PetscErrorCode PetscSFReset_Window(PetscSF sf)
72795fce210SBarry Smith {
72895fce210SBarry Smith   PetscSF_Window  *w = (PetscSF_Window*)sf->data;
72995fce210SBarry Smith   PetscErrorCode  ierr;
73095fce210SBarry Smith   PetscSFDataLink link,next;
73195fce210SBarry Smith   PetscSFWinLink  wlink,wnext;
73295fce210SBarry Smith   PetscInt        i;
73395fce210SBarry Smith 
73495fce210SBarry Smith   PetscFunctionBegin;
73595fce210SBarry Smith   for (link=w->link; link; link=next) {
73695fce210SBarry Smith     next = link->next;
737ffc4695bSBarry Smith     ierr = MPI_Type_free(&link->unit);CHKERRMPI(ierr);
73895fce210SBarry Smith     for (i=0; i<sf->nranks; i++) {
739ffc4695bSBarry Smith       ierr = MPI_Type_free(&link->mine[i]);CHKERRMPI(ierr);
740ffc4695bSBarry Smith       ierr = MPI_Type_free(&link->remote[i]);CHKERRMPI(ierr);
74195fce210SBarry Smith     }
74295fce210SBarry Smith     ierr = PetscFree2(link->mine,link->remote);CHKERRQ(ierr);
74395fce210SBarry Smith     ierr = PetscFree(link);CHKERRQ(ierr);
74495fce210SBarry Smith   }
74595fce210SBarry Smith   w->link = NULL;
74695fce210SBarry Smith   for (wlink=w->wins; wlink; wlink=wnext) {
74795fce210SBarry Smith     wnext = wlink->next;
74895fce210SBarry Smith     if (wlink->inuse) SETERRQ1(PetscObjectComm((PetscObject)sf),PETSC_ERR_ARG_WRONGSTATE,"Window still in use with address %p",(void*)wlink->addr);
7495b0d146aSStefano Zampini     ierr = PetscFree(wlink->dyn_target_addr);CHKERRQ(ierr);
750684a874aSStefano Zampini     ierr = PetscFree(wlink->reqs);CHKERRQ(ierr);
751ffc4695bSBarry Smith     ierr = MPI_Win_free(&wlink->win);CHKERRMPI(ierr);
75295fce210SBarry Smith     ierr = PetscFree(wlink);CHKERRQ(ierr);
75395fce210SBarry Smith   }
75495fce210SBarry Smith   w->wins = NULL;
7555b0d146aSStefano Zampini   ierr = PetscSFDestroy(&w->dynsf);CHKERRQ(ierr);
7565b0d146aSStefano Zampini   if (w->info != MPI_INFO_NULL) {
757ffc4695bSBarry Smith     ierr = MPI_Info_free(&w->info);CHKERRMPI(ierr);
7585b0d146aSStefano Zampini   }
75995fce210SBarry Smith   PetscFunctionReturn(0);
76095fce210SBarry Smith }
76195fce210SBarry Smith 
76295fce210SBarry Smith static PetscErrorCode PetscSFDestroy_Window(PetscSF sf)
76395fce210SBarry Smith {
76495fce210SBarry Smith   PetscErrorCode ierr;
76595fce210SBarry Smith 
76695fce210SBarry Smith   PetscFunctionBegin;
76729046d53SLisandro Dalcin   ierr = PetscSFReset_Window(sf);CHKERRQ(ierr);
76895fce210SBarry Smith   ierr = PetscFree(sf->data);CHKERRQ(ierr);
769bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)sf,"PetscSFWindowSetSyncType_C",NULL);CHKERRQ(ierr);
770bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)sf,"PetscSFWindowGetSyncType_C",NULL);CHKERRQ(ierr);
7715b0d146aSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)sf,"PetscSFWindowSetFlavorType_C",NULL);CHKERRQ(ierr);
7725b0d146aSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)sf,"PetscSFWindowGetFlavorType_C",NULL);CHKERRQ(ierr);
7735b0d146aSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)sf,"PetscSFWindowSetInfo_C",NULL);CHKERRQ(ierr);
7745b0d146aSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)sf,"PetscSFWindowGetInfo_C",NULL);CHKERRQ(ierr);
77595fce210SBarry Smith   PetscFunctionReturn(0);
77695fce210SBarry Smith }
77795fce210SBarry Smith 
77895fce210SBarry Smith static PetscErrorCode PetscSFView_Window(PetscSF sf,PetscViewer viewer)
77995fce210SBarry Smith {
78095fce210SBarry Smith   PetscSF_Window    *w = (PetscSF_Window*)sf->data;
78195fce210SBarry Smith   PetscErrorCode    ierr;
78295fce210SBarry Smith   PetscBool         iascii;
7835b0d146aSStefano Zampini   PetscViewerFormat format;
78495fce210SBarry Smith 
78595fce210SBarry Smith   PetscFunctionBegin;
7865b0d146aSStefano Zampini   ierr = PetscViewerGetFormat(viewer,&format);CHKERRQ(ierr);
78795fce210SBarry Smith   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr);
78895fce210SBarry Smith   if (iascii) {
789*62152dedSBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"  current flavor=%s synchronization=%s MultiSF sort=%s\n",PetscSFWindowFlavorTypes[w->flavor],PetscSFWindowSyncTypes[w->sync],sf->rankorder ? "rank-order" : "unordered");CHKERRQ(ierr);
7905b0d146aSStefano Zampini     if (format == PETSC_VIEWER_ASCII_INFO_DETAIL) {
7915b0d146aSStefano Zampini       if (w->info != MPI_INFO_NULL) {
7925b0d146aSStefano Zampini         PetscMPIInt k,nkeys;
7935b0d146aSStefano Zampini         char        key[MPI_MAX_INFO_KEY], value[MPI_MAX_INFO_VAL];
7945b0d146aSStefano Zampini 
795ffc4695bSBarry Smith         ierr = MPI_Info_get_nkeys(w->info,&nkeys);CHKERRMPI(ierr);
7965b0d146aSStefano Zampini         ierr = PetscViewerASCIIPrintf(viewer,"    current info with %d keys. Ordered key-value pairs follow:\n",nkeys);CHKERRQ(ierr);
7975b0d146aSStefano Zampini         for (k = 0; k < nkeys; k++) {
7985b0d146aSStefano Zampini           PetscMPIInt flag;
7995b0d146aSStefano Zampini 
800ffc4695bSBarry Smith           ierr = MPI_Info_get_nthkey(w->info,k,key);CHKERRMPI(ierr);
801ffc4695bSBarry Smith           ierr = MPI_Info_get(w->info,key,MPI_MAX_INFO_VAL,value,&flag);CHKERRMPI(ierr);
8025b0d146aSStefano Zampini           if (!flag) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Missing key %s",key);
8035b0d146aSStefano Zampini           ierr = PetscViewerASCIIPrintf(viewer,"      %s = %s\n",key,value);CHKERRQ(ierr);
8045b0d146aSStefano Zampini         }
8055b0d146aSStefano Zampini       } else {
8065b0d146aSStefano Zampini         ierr = PetscViewerASCIIPrintf(viewer,"    current info=MPI_INFO_NULL\n");CHKERRQ(ierr);
8075b0d146aSStefano Zampini       }
8085b0d146aSStefano Zampini     }
80995fce210SBarry Smith   }
81095fce210SBarry Smith   PetscFunctionReturn(0);
81195fce210SBarry Smith }
81295fce210SBarry Smith 
81395fce210SBarry Smith static PetscErrorCode PetscSFDuplicate_Window(PetscSF sf,PetscSFDuplicateOption opt,PetscSF newsf)
81495fce210SBarry Smith {
81595fce210SBarry Smith   PetscSF_Window        *w = (PetscSF_Window*)sf->data;
81695fce210SBarry Smith   PetscErrorCode        ierr;
81795fce210SBarry Smith   PetscSFWindowSyncType synctype;
81895fce210SBarry Smith 
81995fce210SBarry Smith   PetscFunctionBegin;
82095fce210SBarry Smith   synctype = w->sync;
82195fce210SBarry Smith   /* HACK: Must use FENCE or LOCK when called from PetscSFGetGroups() because ACTIVE here would cause recursion. */
8225b0d146aSStefano Zampini   if (!sf->setupcalled) synctype = PETSCSF_WINDOW_SYNC_LOCK;
82395fce210SBarry Smith   ierr = PetscSFWindowSetSyncType(newsf,synctype);CHKERRQ(ierr);
8245b0d146aSStefano Zampini   ierr = PetscSFWindowSetFlavorType(newsf,w->flavor);CHKERRQ(ierr);
8255b0d146aSStefano Zampini   ierr = PetscSFWindowSetInfo(newsf,w->info);CHKERRQ(ierr);
82695fce210SBarry Smith   PetscFunctionReturn(0);
82795fce210SBarry Smith }
82895fce210SBarry Smith 
829eb02082bSJunchao Zhang static PetscErrorCode PetscSFBcastAndOpBegin_Window(PetscSF sf,MPI_Datatype unit,PetscMemType rootmtype,const void *rootdata,PetscMemType leafmtype,void *leafdata,MPI_Op op)
83095fce210SBarry Smith {
83195fce210SBarry Smith   PetscSF_Window     *w = (PetscSF_Window*)sf->data;
83295fce210SBarry Smith   PetscErrorCode     ierr;
83395fce210SBarry Smith   PetscInt           i,nranks;
83495fce210SBarry Smith   const PetscMPIInt  *ranks;
8355b0d146aSStefano Zampini   const MPI_Aint     *target_disp;
83695fce210SBarry Smith   const MPI_Datatype *mine,*remote;
837684a874aSStefano Zampini   MPI_Request        *reqs;
83895fce210SBarry Smith   MPI_Win            win;
83995fce210SBarry Smith 
84095fce210SBarry Smith   PetscFunctionBegin;
8415b0d146aSStefano 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");
842dec1416fSJunchao Zhang   ierr = PetscSFGetRootRanks(sf,&nranks,&ranks,NULL,NULL,NULL);CHKERRQ(ierr);
84395fce210SBarry Smith   ierr = PetscSFWindowGetDataTypes(sf,unit,&mine,&remote);CHKERRQ(ierr);
844684a874aSStefano 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);
84595fce210SBarry Smith   for (i=0; i<nranks; i++) {
8465b0d146aSStefano Zampini     MPI_Aint tdp = target_disp ? target_disp[i] : 0;
8475b0d146aSStefano Zampini 
848684a874aSStefano Zampini     if (w->sync == PETSCSF_WINDOW_SYNC_LOCK) {
849ffc4695bSBarry Smith       ierr = MPI_Win_lock(MPI_LOCK_SHARED,ranks[i],MPI_MODE_NOCHECK,win);CHKERRMPI(ierr);
850684a874aSStefano Zampini #if defined(PETSC_HAVE_MPI_RGET)
851ffc4695bSBarry Smith       ierr = MPI_Rget(leafdata,1,mine[i],ranks[i],tdp,1,remote[i],win,&reqs[i]);CHKERRMPI(ierr);
852684a874aSStefano Zampini #else
853ffc4695bSBarry Smith       ierr = MPI_Get(leafdata,1,mine[i],ranks[i],tdp,1,remote[i],win);CHKERRMPI(ierr);
854684a874aSStefano Zampini #endif
855684a874aSStefano Zampini     } else {
856ffc4695bSBarry Smith       ierr = MPI_Get(leafdata,1,mine[i],ranks[i],tdp,1,remote[i],win);CHKERRMPI(ierr);
857684a874aSStefano Zampini     }
85895fce210SBarry Smith   }
85995fce210SBarry Smith   PetscFunctionReturn(0);
86095fce210SBarry Smith }
86195fce210SBarry Smith 
86200816365SJunchao Zhang PetscErrorCode PetscSFBcastAndOpEnd_Window(PetscSF sf,MPI_Datatype unit,const void *rootdata,void *leafdata,MPI_Op op)
86395fce210SBarry Smith {
8645b0d146aSStefano Zampini   PetscSF_Window *w = (PetscSF_Window*)sf->data;
86595fce210SBarry Smith   PetscErrorCode ierr;
86695fce210SBarry Smith   MPI_Win        win;
8674b9acda6SJunchao Zhang   MPI_Request    *reqs = NULL;
86895fce210SBarry Smith 
86995fce210SBarry Smith   PetscFunctionBegin;
870684a874aSStefano Zampini   ierr = PetscSFFindWindow(sf,unit,rootdata,&win,&reqs);CHKERRQ(ierr);
871ffc4695bSBarry Smith   if (reqs) {ierr = MPI_Waitall(sf->nranks,reqs,MPI_STATUSES_IGNORE);CHKERRMPI(ierr);}
872684a874aSStefano Zampini   if (w->sync == PETSCSF_WINDOW_SYNC_LOCK) {
873684a874aSStefano Zampini     PetscInt           i,nranks;
874684a874aSStefano Zampini     const PetscMPIInt  *ranks;
875684a874aSStefano Zampini 
876684a874aSStefano Zampini     ierr = PetscSFGetRootRanks(sf,&nranks,&ranks,NULL,NULL,NULL);CHKERRQ(ierr);
877684a874aSStefano Zampini     for (i=0; i<nranks; i++) {
878ffc4695bSBarry Smith       ierr = MPI_Win_unlock(ranks[i],win);CHKERRMPI(ierr);
879684a874aSStefano Zampini     }
880684a874aSStefano Zampini   }
8815b0d146aSStefano Zampini   ierr = PetscSFRestoreWindow(sf,unit,(void*)rootdata,w->sync,PETSC_TRUE,MPI_MODE_NOSTORE|MPI_MODE_NOSUCCEED,PETSC_FALSE,&win);CHKERRQ(ierr);
88295fce210SBarry Smith   PetscFunctionReturn(0);
88395fce210SBarry Smith }
88495fce210SBarry Smith 
885eb02082bSJunchao Zhang PetscErrorCode PetscSFReduceBegin_Window(PetscSF sf,MPI_Datatype unit,PetscMemType leafmtype,const void *leafdata,PetscMemType rootmtype,void *rootdata,MPI_Op op)
88695fce210SBarry Smith {
88795fce210SBarry Smith   PetscSF_Window     *w = (PetscSF_Window*)sf->data;
88895fce210SBarry Smith   PetscErrorCode     ierr;
88995fce210SBarry Smith   PetscInt           i,nranks;
89095fce210SBarry Smith   const PetscMPIInt  *ranks;
8915b0d146aSStefano Zampini   const MPI_Aint     *target_disp;
89295fce210SBarry Smith   const MPI_Datatype *mine,*remote;
89395fce210SBarry Smith   MPI_Win            win;
89495fce210SBarry Smith 
89595fce210SBarry Smith   PetscFunctionBegin;
896dec1416fSJunchao Zhang   ierr = PetscSFGetRootRanks(sf,&nranks,&ranks,NULL,NULL,NULL);CHKERRQ(ierr);
89795fce210SBarry Smith   ierr = PetscSFWindowGetDataTypes(sf,unit,&mine,&remote);CHKERRQ(ierr);
89895fce210SBarry Smith   ierr = PetscSFWindowOpTranslate(&op);CHKERRQ(ierr);
899684a874aSStefano Zampini   ierr = PetscSFGetWindow(sf,unit,rootdata,w->sync,PETSC_TRUE,MPI_MODE_NOPRECEDE,0,0,&target_disp,NULL,&win);CHKERRQ(ierr);
90095fce210SBarry Smith   for (i=0; i<nranks; i++) {
9015b0d146aSStefano Zampini     MPI_Aint tdp = target_disp ? target_disp[i] : 0;
9025b0d146aSStefano Zampini 
903ffc4695bSBarry Smith     if (w->sync == PETSCSF_WINDOW_SYNC_LOCK) {ierr = MPI_Win_lock(MPI_LOCK_SHARED,ranks[i],MPI_MODE_NOCHECK,win);CHKERRMPI(ierr);}
904c2c9d402SJose E. Roman     ierr = MPI_Accumulate((void*)leafdata,1,mine[i],ranks[i],tdp,1,remote[i],op,win);CHKERRMPI(ierr);
905ffc4695bSBarry Smith     if (w->sync == PETSCSF_WINDOW_SYNC_LOCK) {ierr = MPI_Win_unlock(ranks[i],win);CHKERRMPI(ierr);}
90695fce210SBarry Smith   }
90795fce210SBarry Smith   PetscFunctionReturn(0);
90895fce210SBarry Smith }
90995fce210SBarry Smith 
91000816365SJunchao Zhang static PetscErrorCode PetscSFReduceEnd_Window(PetscSF sf,MPI_Datatype unit,const void *leafdata,void *rootdata,MPI_Op op)
91195fce210SBarry Smith {
91295fce210SBarry Smith   PetscSF_Window *w = (PetscSF_Window*)sf->data;
91395fce210SBarry Smith   PetscErrorCode ierr;
91495fce210SBarry Smith   MPI_Win        win;
9154b9acda6SJunchao Zhang   MPI_Request    *reqs = NULL;
91695fce210SBarry Smith 
91795fce210SBarry Smith   PetscFunctionBegin;
918684a874aSStefano Zampini   ierr = PetscSFFindWindow(sf,unit,rootdata,&win,&reqs);CHKERRQ(ierr);
919ffc4695bSBarry Smith   if (reqs) {ierr = MPI_Waitall(sf->nranks,reqs,MPI_STATUSES_IGNORE);CHKERRMPI(ierr);}
9205b0d146aSStefano Zampini   ierr = PetscSFRestoreWindow(sf,unit,rootdata,w->sync,PETSC_TRUE,MPI_MODE_NOSUCCEED,PETSC_TRUE,&win);CHKERRQ(ierr);
92195fce210SBarry Smith   PetscFunctionReturn(0);
92295fce210SBarry Smith }
9235b0d146aSStefano Zampini 
924eb02082bSJunchao Zhang static PetscErrorCode PetscSFFetchAndOpBegin_Window(PetscSF sf,MPI_Datatype unit,PetscMemType rootmtype,void *rootdata,PetscMemType leafmtype,const void *leafdata,void *leafupdate,MPI_Op op)
92595fce210SBarry Smith {
92695fce210SBarry Smith   PetscErrorCode     ierr;
92795fce210SBarry Smith   PetscInt           i,nranks;
92895fce210SBarry Smith   const PetscMPIInt  *ranks;
92995fce210SBarry Smith   const MPI_Datatype *mine,*remote;
9305b0d146aSStefano Zampini   const MPI_Aint     *target_disp;
93195fce210SBarry Smith   MPI_Win            win;
9325b0d146aSStefano Zampini   PetscSF_Window     *w = (PetscSF_Window*)sf->data;
9335b0d146aSStefano Zampini #if !defined(PETSC_HAVE_MPI_GET_ACCUMULATE)
9345b0d146aSStefano Zampini   PetscSFWindowFlavorType oldf;
9355b0d146aSStefano Zampini #endif
93695fce210SBarry Smith 
93795fce210SBarry Smith   PetscFunctionBegin;
938dec1416fSJunchao Zhang   ierr = PetscSFGetRootRanks(sf,&nranks,&ranks,NULL,NULL,NULL);CHKERRQ(ierr);
93995fce210SBarry Smith   ierr = PetscSFWindowGetDataTypes(sf,unit,&mine,&remote);CHKERRQ(ierr);
94095fce210SBarry Smith   ierr = PetscSFWindowOpTranslate(&op);CHKERRQ(ierr);
9415b0d146aSStefano Zampini #if !defined(PETSC_HAVE_MPI_GET_ACCUMULATE)
9425b0d146aSStefano Zampini   /* FetchAndOp without MPI_Get_Accumulate requires locking.
9435b0d146aSStefano Zampini      we create a new window every time to not interfere with user-defined MPI_Info which may have used "no_locks"="true" */
9445b0d146aSStefano Zampini   oldf = w->flavor;
9455b0d146aSStefano Zampini   w->flavor = PETSCSF_WINDOW_FLAVOR_CREATE;
946684a874aSStefano Zampini   ierr = PetscSFGetWindow(sf,unit,rootdata,PETSCSF_WINDOW_SYNC_LOCK,PETSC_FALSE,0,0,0,&target_disp,NULL,&win);CHKERRQ(ierr);
9475b0d146aSStefano Zampini #else
948684a874aSStefano Zampini   ierr = PetscSFGetWindow(sf,unit,rootdata,w->sync,PETSC_TRUE,MPI_MODE_NOPRECEDE,0,0,&target_disp,NULL,&win);CHKERRQ(ierr);
9495b0d146aSStefano Zampini #endif
9505b0d146aSStefano Zampini   for (i=0; i<nranks; i++) {
9515b0d146aSStefano Zampini     MPI_Aint tdp = target_disp ? target_disp[i] : 0;
9525b0d146aSStefano Zampini 
9535b0d146aSStefano Zampini #if !defined(PETSC_HAVE_MPI_GET_ACCUMULATE)
954ffc4695bSBarry Smith     ierr = MPI_Win_lock(MPI_LOCK_EXCLUSIVE,ranks[i],0,win);CHKERRMPI(ierr);
955ffc4695bSBarry Smith     ierr = MPI_Get(leafupdate,1,mine[i],ranks[i],tdp,1,remote[i],win);CHKERRMPI(ierr);
956c2c9d402SJose E. Roman     ierr = MPI_Accumulate((void*)leafdata,1,mine[i],ranks[i],tdp,1,remote[i],op,win);CHKERRMPI(ierr);
957ffc4695bSBarry Smith     ierr = MPI_Win_unlock(ranks[i],win);CHKERRMPI(ierr);
9585b0d146aSStefano Zampini #else
959ffc4695bSBarry Smith     if (w->sync == PETSCSF_WINDOW_SYNC_LOCK) {ierr = MPI_Win_lock(MPI_LOCK_SHARED,ranks[i],0,win);CHKERRMPI(ierr);}
960c2c9d402SJose E. Roman     ierr = MPI_Get_accumulate((void*)leafdata,1,mine[i],leafupdate,1,mine[i],ranks[i],tdp,1,remote[i],op,win);CHKERRMPI(ierr);
961ffc4695bSBarry Smith     if (w->sync == PETSCSF_WINDOW_SYNC_LOCK) {ierr = MPI_Win_unlock(ranks[i],win);CHKERRMPI(ierr);}
9625b0d146aSStefano Zampini #endif
9635b0d146aSStefano Zampini   }
9645b0d146aSStefano Zampini #if !defined(PETSC_HAVE_MPI_GET_ACCUMULATE)
9655b0d146aSStefano Zampini   w->flavor = oldf;
9665b0d146aSStefano Zampini #endif
96795fce210SBarry Smith   PetscFunctionReturn(0);
96895fce210SBarry Smith }
96995fce210SBarry Smith 
97000816365SJunchao Zhang static PetscErrorCode PetscSFFetchAndOpEnd_Window(PetscSF sf,MPI_Datatype unit,void *rootdata,const void *leafdata,void *leafupdate,MPI_Op op)
97195fce210SBarry Smith {
97295fce210SBarry Smith   PetscErrorCode ierr;
97395fce210SBarry Smith   MPI_Win        win;
9745b0d146aSStefano Zampini #if defined(PETSC_HAVE_MPI_GET_ACCUMULATE)
9755b0d146aSStefano Zampini   PetscSF_Window *w = (PetscSF_Window*)sf->data;
9765b0d146aSStefano Zampini #endif
9774b9acda6SJunchao Zhang   MPI_Request    *reqs = NULL;
97895fce210SBarry Smith 
97995fce210SBarry Smith   PetscFunctionBegin;
980684a874aSStefano Zampini   ierr = PetscSFFindWindow(sf,unit,rootdata,&win,&reqs);CHKERRQ(ierr);
981ffc4695bSBarry Smith   if (reqs) {ierr = MPI_Waitall(sf->nranks,reqs,MPI_STATUSES_IGNORE);CHKERRMPI(ierr);}
9825b0d146aSStefano Zampini #if defined(PETSC_HAVE_MPI_GET_ACCUMULATE)
9835b0d146aSStefano Zampini   ierr = PetscSFRestoreWindow(sf,unit,rootdata,w->sync,PETSC_TRUE,MPI_MODE_NOSUCCEED,PETSC_TRUE,&win);CHKERRQ(ierr);
9845b0d146aSStefano Zampini #else
9855b0d146aSStefano Zampini   ierr = PetscSFRestoreWindow(sf,unit,rootdata,PETSCSF_WINDOW_SYNC_LOCK,PETSC_FALSE,0,PETSC_TRUE,&win);CHKERRQ(ierr);
9865b0d146aSStefano Zampini #endif
98795fce210SBarry Smith   PetscFunctionReturn(0);
98895fce210SBarry Smith }
98995fce210SBarry Smith 
990dec1416fSJunchao Zhang PETSC_INTERN PetscErrorCode PetscSFCreate_Window(PetscSF sf)
99195fce210SBarry Smith {
99295fce210SBarry Smith   PetscSF_Window *w = (PetscSF_Window*)sf->data;
99395fce210SBarry Smith   PetscErrorCode ierr;
99495fce210SBarry Smith 
99595fce210SBarry Smith   PetscFunctionBegin;
99695fce210SBarry Smith   sf->ops->SetUp           = PetscSFSetUp_Window;
99795fce210SBarry Smith   sf->ops->SetFromOptions  = PetscSFSetFromOptions_Window;
99895fce210SBarry Smith   sf->ops->Reset           = PetscSFReset_Window;
99995fce210SBarry Smith   sf->ops->Destroy         = PetscSFDestroy_Window;
100095fce210SBarry Smith   sf->ops->View            = PetscSFView_Window;
100195fce210SBarry Smith   sf->ops->Duplicate       = PetscSFDuplicate_Window;
1002de49d1a2SJunchao Zhang   sf->ops->BcastAndOpBegin = PetscSFBcastAndOpBegin_Window;
1003de49d1a2SJunchao Zhang   sf->ops->BcastAndOpEnd   = PetscSFBcastAndOpEnd_Window;
100495fce210SBarry Smith   sf->ops->ReduceBegin     = PetscSFReduceBegin_Window;
100595fce210SBarry Smith   sf->ops->ReduceEnd       = PetscSFReduceEnd_Window;
100695fce210SBarry Smith   sf->ops->FetchAndOpBegin = PetscSFFetchAndOpBegin_Window;
100795fce210SBarry Smith   sf->ops->FetchAndOpEnd   = PetscSFFetchAndOpEnd_Window;
100895fce210SBarry Smith 
1009b00a9115SJed Brown   ierr = PetscNewLog(sf,&w);CHKERRQ(ierr);
101095fce210SBarry Smith   sf->data  = (void*)w;
101195fce210SBarry Smith   w->sync   = PETSCSF_WINDOW_SYNC_FENCE;
10125b0d146aSStefano Zampini   w->flavor = PETSCSF_WINDOW_FLAVOR_CREATE;
10135b0d146aSStefano Zampini   w->info   = MPI_INFO_NULL;
101495fce210SBarry Smith 
1015bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)sf,"PetscSFWindowSetSyncType_C",PetscSFWindowSetSyncType_Window);CHKERRQ(ierr);
1016bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)sf,"PetscSFWindowGetSyncType_C",PetscSFWindowGetSyncType_Window);CHKERRQ(ierr);
10175b0d146aSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)sf,"PetscSFWindowSetFlavorType_C",PetscSFWindowSetFlavorType_Window);CHKERRQ(ierr);
10185b0d146aSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)sf,"PetscSFWindowGetFlavorType_C",PetscSFWindowGetFlavorType_Window);CHKERRQ(ierr);
10195b0d146aSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)sf,"PetscSFWindowSetInfo_C",PetscSFWindowSetInfo_Window);CHKERRQ(ierr);
10205b0d146aSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)sf,"PetscSFWindowGetInfo_C",PetscSFWindowGetInfo_Window);CHKERRQ(ierr);
102195fce210SBarry Smith 
102295fce210SBarry Smith #if defined(OMPI_MAJOR_VERSION) && (OMPI_MAJOR_VERSION < 1 || (OMPI_MAJOR_VERSION == 1 && OMPI_MINOR_VERSION <= 6))
102395fce210SBarry Smith   {
102495fce210SBarry Smith     PetscBool ackbug = PETSC_FALSE;
1025c5929fdfSBarry Smith     ierr = PetscOptionsGetBool(NULL,NULL,"-acknowledge_ompi_onesided_bug",&ackbug,NULL);CHKERRQ(ierr);
102695fce210SBarry Smith     if (ackbug) {
1027955c1f14SBarry Smith       ierr = PetscInfo(sf,"Acknowledged Open MPI bug, proceeding anyway. Expect memory corruption.\n");CHKERRQ(ierr);
102895fce210SBarry 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");
102995fce210SBarry Smith   }
103095fce210SBarry Smith #endif
103195fce210SBarry Smith   PetscFunctionReturn(0);
103295fce210SBarry Smith }
1033