xref: /petsc/src/vec/is/sf/impls/window/sfwindow.c (revision 4165533ce9fbcd1440639b2ad505faa054a49d0c)
1af0996ceSBarry Smith #include <petsc/private/sfimpl.h> /*I "petscsf.h" I*/
295fce210SBarry Smith 
395fce210SBarry Smith typedef struct _n_PetscSFDataLink *PetscSFDataLink;
495fce210SBarry Smith typedef struct _n_PetscSFWinLink  *PetscSFWinLink;
595fce210SBarry Smith 
695fce210SBarry Smith typedef struct {
795fce210SBarry Smith   PetscSFWindowSyncType   sync;   /* FENCE, LOCK, or ACTIVE synchronization */
85b0d146aSStefano Zampini   PetscSFDataLink         link;   /* List of MPI data types, lazily constructed for each data type */
995fce210SBarry Smith   PetscSFWinLink          wins;   /* List of active windows */
105b0d146aSStefano Zampini   PetscSFWindowFlavorType flavor; /* Current PETSCSF_WINDOW_FLAVOR_ */
115b0d146aSStefano Zampini   PetscSF                 dynsf;
125b0d146aSStefano Zampini   MPI_Info                info;
1395fce210SBarry Smith } PetscSF_Window;
1495fce210SBarry Smith 
1595fce210SBarry Smith struct _n_PetscSFDataLink {
1695fce210SBarry Smith   MPI_Datatype    unit;
1795fce210SBarry Smith   MPI_Datatype    *mine;
1895fce210SBarry Smith   MPI_Datatype    *remote;
1995fce210SBarry Smith   PetscSFDataLink next;
2095fce210SBarry Smith };
2195fce210SBarry Smith 
2295fce210SBarry Smith struct _n_PetscSFWinLink {
2395fce210SBarry Smith   PetscBool               inuse;
2495fce210SBarry Smith   size_t                  bytes;
2595fce210SBarry Smith   void                    *addr;
265b0d146aSStefano Zampini   void                    *paddr;
2795fce210SBarry Smith   MPI_Win                 win;
28684a874aSStefano Zampini   MPI_Request             *reqs;
295b0d146aSStefano Zampini   PetscSFWindowFlavorType flavor;
305b0d146aSStefano Zampini   MPI_Aint                *dyn_target_addr;
3195fce210SBarry Smith   PetscBool               epoch;
3295fce210SBarry Smith   PetscSFWinLink          next;
3395fce210SBarry Smith };
3495fce210SBarry Smith 
354c8fdceaSLisandro Dalcin const char *const PetscSFWindowSyncTypes[] = {"FENCE","LOCK","ACTIVE","PetscSFWindowSyncType","PETSCSF_WINDOW_SYNC_",NULL};
364c8fdceaSLisandro Dalcin const char *const PetscSFWindowFlavorTypes[] = {"CREATE","DYNAMIC","ALLOCATE","SHARED","PetscSFWindowFlavorType","PETSCSF_WINDOW_FLAVOR_",NULL};
3795fce210SBarry Smith 
38820f2d46SBarry Smith /* Built-in MPI_Ops act elementwise inside MPI_Accumulate, but cannot be used with composite types inside collectives (MPI_Allreduce) */
3995fce210SBarry Smith static PetscErrorCode PetscSFWindowOpTranslate(MPI_Op *op)
4095fce210SBarry Smith {
4195fce210SBarry Smith   PetscFunctionBegin;
4295fce210SBarry Smith   if (*op == MPIU_SUM) *op = MPI_SUM;
4395fce210SBarry Smith   else if (*op == MPIU_MAX) *op = MPI_MAX;
4495fce210SBarry Smith   else if (*op == MPIU_MIN) *op = MPI_MIN;
4595fce210SBarry Smith   PetscFunctionReturn(0);
4695fce210SBarry Smith }
4795fce210SBarry Smith 
4895fce210SBarry Smith /*@C
4995fce210SBarry Smith    PetscSFWindowGetDataTypes - gets composite local and remote data types for each rank
5095fce210SBarry Smith 
5195fce210SBarry Smith    Not Collective
5295fce210SBarry Smith 
53*4165533cSJose E. Roman    Input Parameters:
5495fce210SBarry Smith +  sf - star forest
5595fce210SBarry Smith -  unit - data type for each node
5695fce210SBarry Smith 
57*4165533cSJose E. Roman    Output Parameters:
5895fce210SBarry Smith +  localtypes - types describing part of local leaf buffer referencing each remote rank
5995fce210SBarry Smith -  remotetypes - types describing part of remote root buffer referenced for each remote rank
6095fce210SBarry Smith 
6195fce210SBarry Smith    Level: developer
6295fce210SBarry Smith 
6395fce210SBarry Smith .seealso: PetscSFSetGraph(), PetscSFView()
6495fce210SBarry Smith @*/
6595fce210SBarry Smith static PetscErrorCode PetscSFWindowGetDataTypes(PetscSF sf,MPI_Datatype unit,const MPI_Datatype **localtypes,const MPI_Datatype **remotetypes)
6695fce210SBarry Smith {
6795fce210SBarry Smith   PetscSF_Window    *w = (PetscSF_Window*)sf->data;
6895fce210SBarry Smith   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 
127*4165533cSJose E. Roman    Input Parameters:
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 
185*4165533cSJose E. Roman    Input Parameter:
1865b0d146aSStefano Zampini .  sf - star forest for communication
1875b0d146aSStefano Zampini 
188*4165533cSJose E. Roman    Output Parameter:
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 
220*4165533cSJose E. Roman    Input Parameters:
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 
256*4165533cSJose E. Roman    Input Parameter:
25795fce210SBarry Smith .  sf - star forest for communication
25895fce210SBarry Smith 
259*4165533cSJose E. Roman    Output Parameter:
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 
291*4165533cSJose E. Roman    Input Parameters:
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 
331*4165533cSJose E. Roman    Input Parameter:
3325b0d146aSStefano Zampini .  sf - star forest for communication
3335b0d146aSStefano Zampini 
334*4165533cSJose E. Roman    Output Parameter:
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 
368*4165533cSJose E. Roman    Input Parameters:
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 
378*4165533cSJose E. Roman    Output Parameters:
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;
392d547623eSJunchao Zhang #if defined(PETSC_HAVE_MPI_FEATURE_DYNAMIC_WINDOW)
3935b0d146aSStefano Zampini   MPI_Aint       winaddr;
3945b0d146aSStefano Zampini   PetscInt       nranks;
395d547623eSJunchao Zhang #endif
3965b0d146aSStefano Zampini   PetscBool      reuse = PETSC_FALSE, update = PETSC_FALSE;
3975b0d146aSStefano Zampini   PetscBool      dummy[2];
3985b0d146aSStefano Zampini   MPI_Aint       wsize;
39995fce210SBarry Smith 
40095fce210SBarry Smith   PetscFunctionBegin;
401ffc4695bSBarry Smith   ierr = MPI_Type_get_extent(unit,&lb,&bytes);CHKERRMPI(ierr);
402ffc4695bSBarry Smith   ierr = MPI_Type_get_true_extent(unit,&lb_true,&bytes_true);CHKERRMPI(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) {
41276bd3646SJed Brown         if (PetscDefined(USE_DEBUG)) {
4135b0d146aSStefano Zampini           dummy[0] = PETSC_TRUE;
4145b0d146aSStefano Zampini           dummy[1] = PETSC_TRUE;
415ffc4695bSBarry Smith           ierr = MPI_Allreduce(MPI_IN_PLACE,dummy,1,MPIU_BOOL,MPI_LAND,PetscObjectComm((PetscObject)sf));CHKERRMPI(ierr);
416ffc4695bSBarry Smith           ierr = MPI_Allreduce(MPI_IN_PLACE,dummy+1,1,MPIU_BOOL,MPI_LOR ,PetscObjectComm((PetscObject)sf));CHKERRMPI(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");
41876bd3646SJed Brown         }
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;
42376bd3646SJed Brown       } else if (PetscDefined(USE_DEBUG)) {
4245b0d146aSStefano Zampini         dummy[0] = PETSC_FALSE;
4255b0d146aSStefano Zampini         dummy[1] = PETSC_FALSE;
426ffc4695bSBarry Smith         ierr = MPI_Allreduce(MPI_IN_PLACE,dummy  ,1,MPIU_BOOL,MPI_LAND,PetscObjectComm((PetscObject)sf));CHKERRMPI(ierr);
427ffc4695bSBarry Smith         ierr = MPI_Allreduce(MPI_IN_PLACE,dummy+1,1,MPIU_BOOL,MPI_LOR ,PetscObjectComm((PetscObject)sf));CHKERRMPI(ierr);
4285b0d146aSStefano 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");
4295b0d146aSStefano Zampini       }
4305b0d146aSStefano Zampini       break;
4315b0d146aSStefano Zampini     case PETSCSF_WINDOW_FLAVOR_ALLOCATE: /* check available by matching size, allocate if in use */
4325b0d146aSStefano Zampini     case PETSCSF_WINDOW_FLAVOR_SHARED:
4335b0d146aSStefano Zampini       if (!link->inuse && bytes == (MPI_Aint)link->bytes) {
4345b0d146aSStefano Zampini         update = PETSC_TRUE;
4355b0d146aSStefano Zampini         link->paddr = array;
4365b0d146aSStefano Zampini         winok = PETSC_TRUE;
4375b0d146aSStefano Zampini       }
4385b0d146aSStefano Zampini       break;
4395b0d146aSStefano Zampini     default: SETERRQ1(PetscObjectComm((PetscObject)sf),PETSC_ERR_SUP,"No support for flavor %s",PetscSFWindowFlavorTypes[w->flavor]);
4405b0d146aSStefano Zampini     }
4415b0d146aSStefano Zampini     if (winok) {
4425b0d146aSStefano Zampini       *win = link->win;
4435b0d146aSStefano Zampini       ierr = PetscInfo3(sf,"Reusing window %d of flavor %d for comm %d\n",link->win,link->flavor,PetscObjectComm((PetscObject)sf));CHKERRQ(ierr);
4445b0d146aSStefano Zampini       goto found;
4455b0d146aSStefano Zampini     }
4465b0d146aSStefano Zampini   }
4475b0d146aSStefano Zampini 
4485b0d146aSStefano Zampini   wsize = (MPI_Aint)bytes*sf->nroots;
44995dccacaSBarry Smith   ierr = PetscNew(&link);CHKERRQ(ierr);
45095fce210SBarry Smith   link->bytes           = bytes;
45195fce210SBarry Smith   link->next            = w->wins;
4525b0d146aSStefano Zampini   link->flavor          = w->flavor;
4535b0d146aSStefano Zampini   link->dyn_target_addr = NULL;
454684a874aSStefano Zampini   link->reqs            = NULL;
45595fce210SBarry Smith   w->wins               = link;
456684a874aSStefano Zampini   if (sync == PETSCSF_WINDOW_SYNC_LOCK) {
457684a874aSStefano Zampini     PetscInt i;
458684a874aSStefano Zampini 
459684a874aSStefano Zampini     ierr = PetscMalloc1(sf->nranks,&link->reqs);CHKERRQ(ierr);
460684a874aSStefano Zampini     for (i = 0; i < sf->nranks; i++) link->reqs[i] = MPI_REQUEST_NULL;
461684a874aSStefano Zampini   }
4625b0d146aSStefano Zampini   switch (w->flavor) {
4635b0d146aSStefano Zampini   case PETSCSF_WINDOW_FLAVOR_CREATE:
464ffc4695bSBarry Smith     ierr = MPI_Win_create(array,wsize,(PetscMPIInt)bytes,w->info,PetscObjectComm((PetscObject)sf),&link->win);CHKERRMPI(ierr);
4655b0d146aSStefano Zampini     link->addr  = array;
4665b0d146aSStefano Zampini     link->paddr = array;
4675b0d146aSStefano Zampini     break;
468d547623eSJunchao Zhang #if defined(PETSC_HAVE_MPI_FEATURE_DYNAMIC_WINDOW)
4695b0d146aSStefano Zampini   case PETSCSF_WINDOW_FLAVOR_DYNAMIC:
470ffc4695bSBarry Smith     ierr = MPI_Win_create_dynamic(w->info,PetscObjectComm((PetscObject)sf),&link->win);CHKERRMPI(ierr);
4715b0d146aSStefano Zampini #if defined(PETSC_HAVE_OMPI_MAJOR_VERSION) /* some OpenMPI versions do not support MPI_Win_attach(win,NULL,0); */
472ffc4695bSBarry Smith     ierr = MPI_Win_attach(link->win,wsize ? array : &ierr,wsize);CHKERRMPI(ierr);
4735b0d146aSStefano Zampini #else
474ffc4695bSBarry Smith     ierr = MPI_Win_attach(link->win,array,wsize);CHKERRMPI(ierr);
4755b0d146aSStefano Zampini #endif
4765b0d146aSStefano Zampini     link->addr  = array;
4775b0d146aSStefano Zampini     link->paddr = array;
4785b0d146aSStefano Zampini     if (!w->dynsf) SETERRQ(PetscObjectComm((PetscObject)sf),PETSC_ERR_ORDER,"Must call PetscSFSetUp()");
4795b0d146aSStefano Zampini     ierr = PetscSFSetUp(w->dynsf);CHKERRQ(ierr);
4805b0d146aSStefano Zampini     ierr = PetscSFGetRootRanks(w->dynsf,&nranks,NULL,NULL,NULL,NULL);CHKERRQ(ierr);
4815b0d146aSStefano Zampini     ierr = PetscMalloc1(nranks,&link->dyn_target_addr);CHKERRQ(ierr);
482ffc4695bSBarry Smith     ierr = MPI_Get_address(array,&winaddr);CHKERRMPI(ierr);
483ad227feaSJunchao Zhang     ierr = PetscSFBcastBegin(w->dynsf,MPI_AINT,&winaddr,link->dyn_target_addr,MPI_REPLACE);CHKERRQ(ierr);
484ad227feaSJunchao Zhang     ierr = PetscSFBcastEnd(w->dynsf,MPI_AINT,&winaddr,link->dyn_target_addr,MPI_REPLACE);CHKERRQ(ierr);
4855b0d146aSStefano Zampini     break;
4865b0d146aSStefano Zampini   case PETSCSF_WINDOW_FLAVOR_ALLOCATE:
487ffc4695bSBarry Smith     ierr = MPI_Win_allocate(wsize,(PetscMPIInt)bytes,w->info,PetscObjectComm((PetscObject)sf),&link->addr,&link->win);CHKERRMPI(ierr);
4885b0d146aSStefano Zampini     update = PETSC_TRUE;
4895b0d146aSStefano Zampini     link->paddr = array;
4905b0d146aSStefano Zampini     break;
491d547623eSJunchao Zhang #endif
4925b0d146aSStefano Zampini #if defined(PETSC_HAVE_MPI_PROCESS_SHARED_MEMORY)
4935b0d146aSStefano Zampini   case PETSCSF_WINDOW_FLAVOR_SHARED:
494ffc4695bSBarry Smith     ierr = MPI_Win_allocate_shared(wsize,(PetscMPIInt)bytes,w->info,PetscObjectComm((PetscObject)sf),&link->addr,&link->win);CHKERRMPI(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 
511ffc4695bSBarry Smith     ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)sf),&rank);CHKERRMPI(ierr);
512ffc4695bSBarry Smith     if (sync == PETSCSF_WINDOW_SYNC_LOCK) {ierr = MPI_Win_lock(MPI_LOCK_EXCLUSIVE,rank,MPI_MODE_NOCHECK,*win);CHKERRMPI(ierr);}
5135b0d146aSStefano Zampini     ierr = PetscMemcpy(link->addr,array,sf->nroots*bytes);CHKERRQ(ierr);
5145b0d146aSStefano Zampini     if (sync == PETSCSF_WINDOW_SYNC_LOCK) {
515ffc4695bSBarry Smith       ierr = MPI_Win_unlock(rank,*win);CHKERRMPI(ierr);
516ffc4695bSBarry Smith       ierr = MPI_Win_fence(0,*win);CHKERRMPI(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:
524ffc4695bSBarry Smith       ierr = MPI_Win_fence(fenceassert,*win);CHKERRMPI(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);
541ffc4695bSBarry Smith       ierr = MPI_Group_size(ingroup,&isize);CHKERRMPI(ierr);
542ffc4695bSBarry Smith       ierr = MPI_Group_size(outgroup,&osize);CHKERRMPI(ierr);
543ffc4695bSBarry Smith       if (isize) {ierr = MPI_Win_post(ingroup,postassert,*win);CHKERRMPI(ierr);}
544ffc4695bSBarry Smith       if (osize) {ierr = MPI_Win_start(outgroup,startassert,*win);CHKERRMPI(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 
557*4165533cSJose E. Roman    Input Parameters:
55895fce210SBarry Smith +  sf - star forest
55995fce210SBarry Smith .  unit - data type
56095fce210SBarry Smith -  array - array with which the window is associated
56195fce210SBarry Smith 
562*4165533cSJose E. Roman    Output Parameters:
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 }
58895fce210SBarry Smith 
5895b0d146aSStefano Zampini /*
59095fce210SBarry Smith    PetscSFRestoreWindow - Restores a window obtained with PetscSFGetWindow()
59195fce210SBarry Smith 
59295fce210SBarry Smith    Collective
59395fce210SBarry Smith 
594*4165533cSJose E. Roman    Input Parameters:
59595fce210SBarry Smith +  sf - star forest
59695fce210SBarry Smith .  unit - data type
59795fce210SBarry Smith .  array - array associated with window
5985b0d146aSStefano Zampini .  sync - type of synchronization PetscSFWindowSyncType
59995fce210SBarry Smith .  epoch - close an epoch, must match argument to PetscSFGetWindow()
6005b0d146aSStefano Zampini .  update - if we have to update the local window array
60195fce210SBarry Smith -  win - window
60295fce210SBarry Smith 
60395fce210SBarry Smith    Level: developer
60495fce210SBarry Smith 
60595fce210SBarry Smith .seealso: PetscSFFindWindow()
6065b0d146aSStefano Zampini */
6075b0d146aSStefano Zampini static PetscErrorCode PetscSFRestoreWindow(PetscSF sf,MPI_Datatype unit,void *array,PetscSFWindowSyncType sync,PetscBool epoch,PetscMPIInt fenceassert,PetscBool update,MPI_Win *win)
60895fce210SBarry Smith {
60995fce210SBarry Smith   PetscSF_Window          *w = (PetscSF_Window*)sf->data;
61095fce210SBarry Smith   PetscErrorCode          ierr;
61195fce210SBarry Smith   PetscSFWinLink          *p,link;
6125b0d146aSStefano Zampini   PetscBool               reuse = PETSC_FALSE;
6135b0d146aSStefano Zampini   PetscSFWindowFlavorType flavor;
6145b0d146aSStefano Zampini   void*                   laddr;
6155b0d146aSStefano Zampini   size_t                  bytes;
61695fce210SBarry Smith 
61795fce210SBarry Smith   PetscFunctionBegin;
61895fce210SBarry Smith   for (p=&w->wins; *p; p=&(*p)->next) {
61995fce210SBarry Smith     link = *p;
62095fce210SBarry Smith     if (*win == link->win) {
6215b0d146aSStefano Zampini       if (array != link->paddr) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Matched window, but not array");
62295fce210SBarry Smith       if (epoch != link->epoch) {
62395fce210SBarry Smith         if (epoch) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"No epoch to end");
62495fce210SBarry Smith         else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Restoring window without ending epoch");
62595fce210SBarry Smith       }
6265b0d146aSStefano Zampini       laddr = link->addr;
6275b0d146aSStefano Zampini       flavor = link->flavor;
6285b0d146aSStefano Zampini       bytes = link->bytes;
6295b0d146aSStefano Zampini       if (flavor != PETSCSF_WINDOW_FLAVOR_CREATE) reuse = PETSC_TRUE;
6305b0d146aSStefano Zampini       else { *p = link->next; update = PETSC_FALSE; } /* remove from list */
63195fce210SBarry Smith       goto found;
63295fce210SBarry Smith     }
63395fce210SBarry Smith   }
63495fce210SBarry Smith   SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Requested window not in use");
63595fce210SBarry Smith 
63695fce210SBarry Smith found:
6375b0d146aSStefano Zampini   ierr = PetscInfo3(sf,"Window %d of flavor %d for comm %d\n",link->win,link->flavor,PetscObjectComm((PetscObject)sf));CHKERRQ(ierr);
63895fce210SBarry Smith   if (epoch) {
6395b0d146aSStefano Zampini     switch (sync) {
64095fce210SBarry Smith     case PETSCSF_WINDOW_SYNC_FENCE:
641ffc4695bSBarry Smith       ierr = MPI_Win_fence(fenceassert,*win);CHKERRMPI(ierr);
64295fce210SBarry Smith       break;
6435b0d146aSStefano Zampini     case PETSCSF_WINDOW_SYNC_LOCK: /* Handled outside */
6445b0d146aSStefano Zampini       break;
64595fce210SBarry Smith     case PETSCSF_WINDOW_SYNC_ACTIVE: {
6465b0d146aSStefano Zampini       MPI_Group   ingroup,outgroup;
6475b0d146aSStefano Zampini       PetscMPIInt isize,osize;
6485b0d146aSStefano Zampini 
6495b0d146aSStefano Zampini       /* OpenMPI 4.0.2 with btl=wader does not like calling
6505b0d146aSStefano Zampini          - MPI_Win_complete when ogroup is empty
6515b0d146aSStefano Zampini          - MPI_Win_wait when igroup is empty
6525b0d146aSStefano Zampini          The MPI standard (Sec. 11.5.2 of MPI 3.1) only requires that
6535b0d146aSStefano Zampini          - each process who issues a call to MPI_Win_start issues a call to MPI_Win_Complete
6545b0d146aSStefano Zampini          - each process who issues a call to MPI_Win_post issues a call to MPI_Win_Wait
6555b0d146aSStefano Zampini       */
6565b0d146aSStefano Zampini       ierr = PetscSFGetGroups(sf,&ingroup,&outgroup);CHKERRQ(ierr);
657ffc4695bSBarry Smith       ierr = MPI_Group_size(ingroup,&isize);CHKERRMPI(ierr);
658ffc4695bSBarry Smith       ierr = MPI_Group_size(outgroup,&osize);CHKERRMPI(ierr);
659ffc4695bSBarry Smith       if (osize) {ierr = MPI_Win_complete(*win);CHKERRMPI(ierr);}
660ffc4695bSBarry Smith       if (isize) {ierr = MPI_Win_wait(*win);CHKERRMPI(ierr);}
66195fce210SBarry Smith     } break;
66295fce210SBarry Smith     default: SETERRQ(PetscObjectComm((PetscObject)sf),PETSC_ERR_PLIB,"Unknown synchronization type");
66395fce210SBarry Smith     }
66495fce210SBarry Smith   }
6655b0d146aSStefano Zampini   if (update) {
6665b0d146aSStefano Zampini     if (sync == PETSCSF_WINDOW_SYNC_LOCK) {
667ffc4695bSBarry Smith       ierr = MPI_Win_fence(MPI_MODE_NOPUT|MPI_MODE_NOSUCCEED,*win);CHKERRMPI(ierr);
6685b0d146aSStefano Zampini     }
6695b0d146aSStefano Zampini     ierr = PetscMemcpy(array,laddr,sf->nroots*bytes);CHKERRQ(ierr);
6705b0d146aSStefano Zampini   }
6715b0d146aSStefano Zampini   link->epoch = PETSC_FALSE;
6725b0d146aSStefano Zampini   link->inuse = PETSC_FALSE;
6735b0d146aSStefano Zampini   link->paddr = NULL;
6745b0d146aSStefano Zampini   if (!reuse) {
675684a874aSStefano Zampini     ierr = PetscFree(link->dyn_target_addr);CHKERRQ(ierr);
676684a874aSStefano Zampini     ierr = PetscFree(link->reqs);CHKERRQ(ierr);
677ffc4695bSBarry Smith     ierr = MPI_Win_free(&link->win);CHKERRMPI(ierr);
67895fce210SBarry Smith     ierr = PetscFree(link);CHKERRQ(ierr);
67995fce210SBarry Smith     *win = MPI_WIN_NULL;
6805b0d146aSStefano Zampini   }
68195fce210SBarry Smith   PetscFunctionReturn(0);
68295fce210SBarry Smith }
68395fce210SBarry Smith 
68495fce210SBarry Smith static PetscErrorCode PetscSFSetUp_Window(PetscSF sf)
68595fce210SBarry Smith {
68695fce210SBarry Smith   PetscSF_Window *w = (PetscSF_Window*)sf->data;
68795fce210SBarry Smith   PetscErrorCode ierr;
68895fce210SBarry Smith   MPI_Group      ingroup,outgroup;
68995fce210SBarry Smith 
69095fce210SBarry Smith   PetscFunctionBegin;
691b5a8e515SJed Brown   ierr = PetscSFSetUpRanks(sf,MPI_GROUP_EMPTY);CHKERRQ(ierr);
6925b0d146aSStefano Zampini   if (!w->dynsf) {
6935b0d146aSStefano Zampini     PetscInt    i;
6945b0d146aSStefano Zampini     PetscSFNode *remotes;
6955b0d146aSStefano Zampini 
6965b0d146aSStefano Zampini     ierr = PetscMalloc1(sf->nranks,&remotes);CHKERRQ(ierr);
6975b0d146aSStefano Zampini     for (i=0;i<sf->nranks;i++) {
6985b0d146aSStefano Zampini       remotes[i].rank  = sf->ranks[i];
6995b0d146aSStefano Zampini       remotes[i].index = 0;
7005b0d146aSStefano Zampini     }
7015b0d146aSStefano Zampini     ierr = PetscSFDuplicate(sf,PETSCSF_DUPLICATE_RANKS,&w->dynsf);CHKERRQ(ierr);
7025b0d146aSStefano Zampini     ierr = PetscSFWindowSetFlavorType(w->dynsf,PETSCSF_WINDOW_FLAVOR_CREATE);CHKERRQ(ierr); /* break recursion */
7035b0d146aSStefano Zampini     ierr = PetscSFSetGraph(w->dynsf,1,sf->nranks,NULL,PETSC_OWN_POINTER,remotes,PETSC_OWN_POINTER);CHKERRQ(ierr);
7045b0d146aSStefano Zampini     ierr = PetscLogObjectParent((PetscObject)sf,(PetscObject)w->dynsf);CHKERRQ(ierr);
7055b0d146aSStefano Zampini   }
70695fce210SBarry Smith   switch (w->sync) {
70795fce210SBarry Smith   case PETSCSF_WINDOW_SYNC_ACTIVE:
70895fce210SBarry Smith     ierr = PetscSFGetGroups(sf,&ingroup,&outgroup);CHKERRQ(ierr);
70995fce210SBarry Smith   default:
71095fce210SBarry Smith     break;
71195fce210SBarry Smith   }
71295fce210SBarry Smith   PetscFunctionReturn(0);
71395fce210SBarry Smith }
71495fce210SBarry Smith 
7154416b707SBarry Smith static PetscErrorCode PetscSFSetFromOptions_Window(PetscOptionItems *PetscOptionsObject,PetscSF sf)
71695fce210SBarry Smith {
71795fce210SBarry Smith   PetscSF_Window          *w = (PetscSF_Window*)sf->data;
71895fce210SBarry Smith   PetscErrorCode          ierr;
7195b0d146aSStefano Zampini   PetscSFWindowFlavorType flavor = w->flavor;
72095fce210SBarry Smith 
72195fce210SBarry Smith   PetscFunctionBegin;
722e55864a3SBarry Smith   ierr = PetscOptionsHead(PetscOptionsObject,"PetscSF Window options");CHKERRQ(ierr);
72395fce210SBarry 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);
7245b0d146aSStefano Zampini   ierr = PetscOptionsEnum("-sf_window_flavor","flavor to use for PetscSF Window creation","PetscSFWindowSetFlavorType",PetscSFWindowFlavorTypes,(PetscEnum)flavor,(PetscEnum*)&flavor,NULL);CHKERRQ(ierr);
7255b0d146aSStefano Zampini   ierr = PetscSFWindowSetFlavorType(sf,flavor);CHKERRQ(ierr);
72695fce210SBarry Smith   ierr = PetscOptionsTail();CHKERRQ(ierr);
72795fce210SBarry Smith   PetscFunctionReturn(0);
72895fce210SBarry Smith }
72995fce210SBarry Smith 
73095fce210SBarry Smith static PetscErrorCode PetscSFReset_Window(PetscSF sf)
73195fce210SBarry Smith {
73295fce210SBarry Smith   PetscSF_Window  *w = (PetscSF_Window*)sf->data;
73395fce210SBarry Smith   PetscErrorCode  ierr;
73495fce210SBarry Smith   PetscSFDataLink link,next;
73595fce210SBarry Smith   PetscSFWinLink  wlink,wnext;
73695fce210SBarry Smith   PetscInt        i;
73795fce210SBarry Smith 
73895fce210SBarry Smith   PetscFunctionBegin;
73995fce210SBarry Smith   for (link=w->link; link; link=next) {
74095fce210SBarry Smith     next = link->next;
741ffc4695bSBarry Smith     ierr = MPI_Type_free(&link->unit);CHKERRMPI(ierr);
74295fce210SBarry Smith     for (i=0; i<sf->nranks; i++) {
743ffc4695bSBarry Smith       ierr = MPI_Type_free(&link->mine[i]);CHKERRMPI(ierr);
744ffc4695bSBarry Smith       ierr = MPI_Type_free(&link->remote[i]);CHKERRMPI(ierr);
74595fce210SBarry Smith     }
74695fce210SBarry Smith     ierr = PetscFree2(link->mine,link->remote);CHKERRQ(ierr);
74795fce210SBarry Smith     ierr = PetscFree(link);CHKERRQ(ierr);
74895fce210SBarry Smith   }
74995fce210SBarry Smith   w->link = NULL;
75095fce210SBarry Smith   for (wlink=w->wins; wlink; wlink=wnext) {
75195fce210SBarry Smith     wnext = wlink->next;
75295fce210SBarry Smith     if (wlink->inuse) SETERRQ1(PetscObjectComm((PetscObject)sf),PETSC_ERR_ARG_WRONGSTATE,"Window still in use with address %p",(void*)wlink->addr);
7535b0d146aSStefano Zampini     ierr = PetscFree(wlink->dyn_target_addr);CHKERRQ(ierr);
754684a874aSStefano Zampini     ierr = PetscFree(wlink->reqs);CHKERRQ(ierr);
755ffc4695bSBarry Smith     ierr = MPI_Win_free(&wlink->win);CHKERRMPI(ierr);
75695fce210SBarry Smith     ierr = PetscFree(wlink);CHKERRQ(ierr);
75795fce210SBarry Smith   }
75895fce210SBarry Smith   w->wins = NULL;
7595b0d146aSStefano Zampini   ierr = PetscSFDestroy(&w->dynsf);CHKERRQ(ierr);
7605b0d146aSStefano Zampini   if (w->info != MPI_INFO_NULL) {
761ffc4695bSBarry Smith     ierr = MPI_Info_free(&w->info);CHKERRMPI(ierr);
7625b0d146aSStefano Zampini   }
76395fce210SBarry Smith   PetscFunctionReturn(0);
76495fce210SBarry Smith }
76595fce210SBarry Smith 
76695fce210SBarry Smith static PetscErrorCode PetscSFDestroy_Window(PetscSF sf)
76795fce210SBarry Smith {
76895fce210SBarry Smith   PetscErrorCode ierr;
76995fce210SBarry Smith 
77095fce210SBarry Smith   PetscFunctionBegin;
77129046d53SLisandro Dalcin   ierr = PetscSFReset_Window(sf);CHKERRQ(ierr);
77295fce210SBarry Smith   ierr = PetscFree(sf->data);CHKERRQ(ierr);
773bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)sf,"PetscSFWindowSetSyncType_C",NULL);CHKERRQ(ierr);
774bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)sf,"PetscSFWindowGetSyncType_C",NULL);CHKERRQ(ierr);
7755b0d146aSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)sf,"PetscSFWindowSetFlavorType_C",NULL);CHKERRQ(ierr);
7765b0d146aSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)sf,"PetscSFWindowGetFlavorType_C",NULL);CHKERRQ(ierr);
7775b0d146aSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)sf,"PetscSFWindowSetInfo_C",NULL);CHKERRQ(ierr);
7785b0d146aSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)sf,"PetscSFWindowGetInfo_C",NULL);CHKERRQ(ierr);
77995fce210SBarry Smith   PetscFunctionReturn(0);
78095fce210SBarry Smith }
78195fce210SBarry Smith 
78295fce210SBarry Smith static PetscErrorCode PetscSFView_Window(PetscSF sf,PetscViewer viewer)
78395fce210SBarry Smith {
78495fce210SBarry Smith   PetscSF_Window    *w = (PetscSF_Window*)sf->data;
78595fce210SBarry Smith   PetscErrorCode    ierr;
78695fce210SBarry Smith   PetscBool         iascii;
7875b0d146aSStefano Zampini   PetscViewerFormat format;
78895fce210SBarry Smith 
78995fce210SBarry Smith   PetscFunctionBegin;
7905b0d146aSStefano Zampini   ierr = PetscViewerGetFormat(viewer,&format);CHKERRQ(ierr);
79195fce210SBarry Smith   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr);
79295fce210SBarry Smith   if (iascii) {
79362152dedSBarry 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);
7945b0d146aSStefano Zampini     if (format == PETSC_VIEWER_ASCII_INFO_DETAIL) {
7955b0d146aSStefano Zampini       if (w->info != MPI_INFO_NULL) {
7965b0d146aSStefano Zampini         PetscMPIInt k,nkeys;
7975b0d146aSStefano Zampini         char        key[MPI_MAX_INFO_KEY], value[MPI_MAX_INFO_VAL];
7985b0d146aSStefano Zampini 
799ffc4695bSBarry Smith         ierr = MPI_Info_get_nkeys(w->info,&nkeys);CHKERRMPI(ierr);
8005b0d146aSStefano Zampini         ierr = PetscViewerASCIIPrintf(viewer,"    current info with %d keys. Ordered key-value pairs follow:\n",nkeys);CHKERRQ(ierr);
8015b0d146aSStefano Zampini         for (k = 0; k < nkeys; k++) {
8025b0d146aSStefano Zampini           PetscMPIInt flag;
8035b0d146aSStefano Zampini 
804ffc4695bSBarry Smith           ierr = MPI_Info_get_nthkey(w->info,k,key);CHKERRMPI(ierr);
805ffc4695bSBarry Smith           ierr = MPI_Info_get(w->info,key,MPI_MAX_INFO_VAL,value,&flag);CHKERRMPI(ierr);
8065b0d146aSStefano Zampini           if (!flag) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Missing key %s",key);
8075b0d146aSStefano Zampini           ierr = PetscViewerASCIIPrintf(viewer,"      %s = %s\n",key,value);CHKERRQ(ierr);
8085b0d146aSStefano Zampini         }
8095b0d146aSStefano Zampini       } else {
8105b0d146aSStefano Zampini         ierr = PetscViewerASCIIPrintf(viewer,"    current info=MPI_INFO_NULL\n");CHKERRQ(ierr);
8115b0d146aSStefano Zampini       }
8125b0d146aSStefano Zampini     }
81395fce210SBarry Smith   }
81495fce210SBarry Smith   PetscFunctionReturn(0);
81595fce210SBarry Smith }
81695fce210SBarry Smith 
81795fce210SBarry Smith static PetscErrorCode PetscSFDuplicate_Window(PetscSF sf,PetscSFDuplicateOption opt,PetscSF newsf)
81895fce210SBarry Smith {
81995fce210SBarry Smith   PetscSF_Window        *w = (PetscSF_Window*)sf->data;
82095fce210SBarry Smith   PetscErrorCode        ierr;
82195fce210SBarry Smith   PetscSFWindowSyncType synctype;
82295fce210SBarry Smith 
82395fce210SBarry Smith   PetscFunctionBegin;
82495fce210SBarry Smith   synctype = w->sync;
82595fce210SBarry Smith   /* HACK: Must use FENCE or LOCK when called from PetscSFGetGroups() because ACTIVE here would cause recursion. */
8265b0d146aSStefano Zampini   if (!sf->setupcalled) synctype = PETSCSF_WINDOW_SYNC_LOCK;
82795fce210SBarry Smith   ierr = PetscSFWindowSetSyncType(newsf,synctype);CHKERRQ(ierr);
8285b0d146aSStefano Zampini   ierr = PetscSFWindowSetFlavorType(newsf,w->flavor);CHKERRQ(ierr);
8295b0d146aSStefano Zampini   ierr = PetscSFWindowSetInfo(newsf,w->info);CHKERRQ(ierr);
83095fce210SBarry Smith   PetscFunctionReturn(0);
83195fce210SBarry Smith }
83295fce210SBarry Smith 
833ad227feaSJunchao Zhang static PetscErrorCode PetscSFBcastBegin_Window(PetscSF sf,MPI_Datatype unit,PetscMemType rootmtype,const void *rootdata,PetscMemType leafmtype,void *leafdata,MPI_Op op)
83495fce210SBarry Smith {
83595fce210SBarry Smith   PetscSF_Window     *w = (PetscSF_Window*)sf->data;
83695fce210SBarry Smith   PetscErrorCode     ierr;
83795fce210SBarry Smith   PetscInt           i,nranks;
83895fce210SBarry Smith   const PetscMPIInt  *ranks;
8395b0d146aSStefano Zampini   const MPI_Aint     *target_disp;
84095fce210SBarry Smith   const MPI_Datatype *mine,*remote;
841684a874aSStefano Zampini   MPI_Request        *reqs;
84295fce210SBarry Smith   MPI_Win            win;
84395fce210SBarry Smith 
84495fce210SBarry Smith   PetscFunctionBegin;
845ad227feaSJunchao Zhang   if (op != MPI_REPLACE) SETERRQ(PetscObjectComm((PetscObject)sf), PETSC_ERR_SUP, "PetscSFBcastBegin_Window with op!=MPI_REPLACE has not been implemented");
846dec1416fSJunchao Zhang   ierr = PetscSFGetRootRanks(sf,&nranks,&ranks,NULL,NULL,NULL);CHKERRQ(ierr);
84795fce210SBarry Smith   ierr = PetscSFWindowGetDataTypes(sf,unit,&mine,&remote);CHKERRQ(ierr);
848684a874aSStefano 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);
84995fce210SBarry Smith   for (i=0; i<nranks; i++) {
8505b0d146aSStefano Zampini     MPI_Aint tdp = target_disp ? target_disp[i] : 0;
8515b0d146aSStefano Zampini 
852684a874aSStefano Zampini     if (w->sync == PETSCSF_WINDOW_SYNC_LOCK) {
853ffc4695bSBarry Smith       ierr = MPI_Win_lock(MPI_LOCK_SHARED,ranks[i],MPI_MODE_NOCHECK,win);CHKERRMPI(ierr);
854684a874aSStefano Zampini #if defined(PETSC_HAVE_MPI_RGET)
855ffc4695bSBarry Smith       ierr = MPI_Rget(leafdata,1,mine[i],ranks[i],tdp,1,remote[i],win,&reqs[i]);CHKERRMPI(ierr);
856684a874aSStefano Zampini #else
857ffc4695bSBarry Smith       ierr = MPI_Get(leafdata,1,mine[i],ranks[i],tdp,1,remote[i],win);CHKERRMPI(ierr);
858684a874aSStefano Zampini #endif
859684a874aSStefano Zampini     } else {
860ffc4695bSBarry Smith       ierr = MPI_Get(leafdata,1,mine[i],ranks[i],tdp,1,remote[i],win);CHKERRMPI(ierr);
861684a874aSStefano Zampini     }
86295fce210SBarry Smith   }
86395fce210SBarry Smith   PetscFunctionReturn(0);
86495fce210SBarry Smith }
86595fce210SBarry Smith 
866ad227feaSJunchao Zhang PetscErrorCode PetscSFBcastEnd_Window(PetscSF sf,MPI_Datatype unit,const void *rootdata,void *leafdata,MPI_Op op)
86795fce210SBarry Smith {
8685b0d146aSStefano Zampini   PetscSF_Window *w = (PetscSF_Window*)sf->data;
86995fce210SBarry Smith   PetscErrorCode ierr;
87095fce210SBarry Smith   MPI_Win        win;
8714b9acda6SJunchao Zhang   MPI_Request    *reqs = NULL;
87295fce210SBarry Smith 
87395fce210SBarry Smith   PetscFunctionBegin;
874684a874aSStefano Zampini   ierr = PetscSFFindWindow(sf,unit,rootdata,&win,&reqs);CHKERRQ(ierr);
875ffc4695bSBarry Smith   if (reqs) {ierr = MPI_Waitall(sf->nranks,reqs,MPI_STATUSES_IGNORE);CHKERRMPI(ierr);}
876684a874aSStefano Zampini   if (w->sync == PETSCSF_WINDOW_SYNC_LOCK) {
877684a874aSStefano Zampini     PetscInt           i,nranks;
878684a874aSStefano Zampini     const PetscMPIInt  *ranks;
879684a874aSStefano Zampini 
880684a874aSStefano Zampini     ierr = PetscSFGetRootRanks(sf,&nranks,&ranks,NULL,NULL,NULL);CHKERRQ(ierr);
881684a874aSStefano Zampini     for (i=0; i<nranks; i++) {
882ffc4695bSBarry Smith       ierr = MPI_Win_unlock(ranks[i],win);CHKERRMPI(ierr);
883684a874aSStefano Zampini     }
884684a874aSStefano Zampini   }
8855b0d146aSStefano Zampini   ierr = PetscSFRestoreWindow(sf,unit,(void*)rootdata,w->sync,PETSC_TRUE,MPI_MODE_NOSTORE|MPI_MODE_NOSUCCEED,PETSC_FALSE,&win);CHKERRQ(ierr);
88695fce210SBarry Smith   PetscFunctionReturn(0);
88795fce210SBarry Smith }
88895fce210SBarry Smith 
889eb02082bSJunchao Zhang PetscErrorCode PetscSFReduceBegin_Window(PetscSF sf,MPI_Datatype unit,PetscMemType leafmtype,const void *leafdata,PetscMemType rootmtype,void *rootdata,MPI_Op op)
89095fce210SBarry Smith {
89195fce210SBarry Smith   PetscSF_Window     *w = (PetscSF_Window*)sf->data;
89295fce210SBarry Smith   PetscErrorCode     ierr;
89395fce210SBarry Smith   PetscInt           i,nranks;
89495fce210SBarry Smith   const PetscMPIInt  *ranks;
8955b0d146aSStefano Zampini   const MPI_Aint     *target_disp;
89695fce210SBarry Smith   const MPI_Datatype *mine,*remote;
89795fce210SBarry Smith   MPI_Win            win;
89895fce210SBarry Smith 
89995fce210SBarry Smith   PetscFunctionBegin;
900dec1416fSJunchao Zhang   ierr = PetscSFGetRootRanks(sf,&nranks,&ranks,NULL,NULL,NULL);CHKERRQ(ierr);
90195fce210SBarry Smith   ierr = PetscSFWindowGetDataTypes(sf,unit,&mine,&remote);CHKERRQ(ierr);
90295fce210SBarry Smith   ierr = PetscSFWindowOpTranslate(&op);CHKERRQ(ierr);
903684a874aSStefano Zampini   ierr = PetscSFGetWindow(sf,unit,rootdata,w->sync,PETSC_TRUE,MPI_MODE_NOPRECEDE,0,0,&target_disp,NULL,&win);CHKERRQ(ierr);
90495fce210SBarry Smith   for (i=0; i<nranks; i++) {
9055b0d146aSStefano Zampini     MPI_Aint tdp = target_disp ? target_disp[i] : 0;
9065b0d146aSStefano Zampini 
907ffc4695bSBarry Smith     if (w->sync == PETSCSF_WINDOW_SYNC_LOCK) {ierr = MPI_Win_lock(MPI_LOCK_SHARED,ranks[i],MPI_MODE_NOCHECK,win);CHKERRMPI(ierr);}
908c2c9d402SJose E. Roman     ierr = MPI_Accumulate((void*)leafdata,1,mine[i],ranks[i],tdp,1,remote[i],op,win);CHKERRMPI(ierr);
909ffc4695bSBarry Smith     if (w->sync == PETSCSF_WINDOW_SYNC_LOCK) {ierr = MPI_Win_unlock(ranks[i],win);CHKERRMPI(ierr);}
91095fce210SBarry Smith   }
91195fce210SBarry Smith   PetscFunctionReturn(0);
91295fce210SBarry Smith }
91395fce210SBarry Smith 
91400816365SJunchao Zhang static PetscErrorCode PetscSFReduceEnd_Window(PetscSF sf,MPI_Datatype unit,const void *leafdata,void *rootdata,MPI_Op op)
91595fce210SBarry Smith {
91695fce210SBarry Smith   PetscSF_Window *w = (PetscSF_Window*)sf->data;
91795fce210SBarry Smith   PetscErrorCode ierr;
91895fce210SBarry Smith   MPI_Win        win;
9194b9acda6SJunchao Zhang   MPI_Request    *reqs = NULL;
92095fce210SBarry Smith 
92195fce210SBarry Smith   PetscFunctionBegin;
922684a874aSStefano Zampini   ierr = PetscSFFindWindow(sf,unit,rootdata,&win,&reqs);CHKERRQ(ierr);
923ffc4695bSBarry Smith   if (reqs) {ierr = MPI_Waitall(sf->nranks,reqs,MPI_STATUSES_IGNORE);CHKERRMPI(ierr);}
9245b0d146aSStefano Zampini   ierr = PetscSFRestoreWindow(sf,unit,rootdata,w->sync,PETSC_TRUE,MPI_MODE_NOSUCCEED,PETSC_TRUE,&win);CHKERRQ(ierr);
92595fce210SBarry Smith   PetscFunctionReturn(0);
92695fce210SBarry Smith }
9275b0d146aSStefano Zampini 
928eb02082bSJunchao Zhang static PetscErrorCode PetscSFFetchAndOpBegin_Window(PetscSF sf,MPI_Datatype unit,PetscMemType rootmtype,void *rootdata,PetscMemType leafmtype,const void *leafdata,void *leafupdate,MPI_Op op)
92995fce210SBarry Smith {
93095fce210SBarry Smith   PetscErrorCode     ierr;
93195fce210SBarry Smith   PetscInt           i,nranks;
93295fce210SBarry Smith   const PetscMPIInt  *ranks;
93395fce210SBarry Smith   const MPI_Datatype *mine,*remote;
9345b0d146aSStefano Zampini   const MPI_Aint     *target_disp;
93595fce210SBarry Smith   MPI_Win            win;
9365b0d146aSStefano Zampini   PetscSF_Window     *w = (PetscSF_Window*)sf->data;
9375b0d146aSStefano Zampini #if !defined(PETSC_HAVE_MPI_GET_ACCUMULATE)
9385b0d146aSStefano Zampini   PetscSFWindowFlavorType oldf;
9395b0d146aSStefano Zampini #endif
94095fce210SBarry Smith 
94195fce210SBarry Smith   PetscFunctionBegin;
942dec1416fSJunchao Zhang   ierr = PetscSFGetRootRanks(sf,&nranks,&ranks,NULL,NULL,NULL);CHKERRQ(ierr);
94395fce210SBarry Smith   ierr = PetscSFWindowGetDataTypes(sf,unit,&mine,&remote);CHKERRQ(ierr);
94495fce210SBarry Smith   ierr = PetscSFWindowOpTranslate(&op);CHKERRQ(ierr);
9455b0d146aSStefano Zampini #if !defined(PETSC_HAVE_MPI_GET_ACCUMULATE)
9465b0d146aSStefano Zampini   /* FetchAndOp without MPI_Get_Accumulate requires locking.
9475b0d146aSStefano Zampini      we create a new window every time to not interfere with user-defined MPI_Info which may have used "no_locks"="true" */
9485b0d146aSStefano Zampini   oldf = w->flavor;
9495b0d146aSStefano Zampini   w->flavor = PETSCSF_WINDOW_FLAVOR_CREATE;
950684a874aSStefano Zampini   ierr = PetscSFGetWindow(sf,unit,rootdata,PETSCSF_WINDOW_SYNC_LOCK,PETSC_FALSE,0,0,0,&target_disp,NULL,&win);CHKERRQ(ierr);
9515b0d146aSStefano Zampini #else
952684a874aSStefano Zampini   ierr = PetscSFGetWindow(sf,unit,rootdata,w->sync,PETSC_TRUE,MPI_MODE_NOPRECEDE,0,0,&target_disp,NULL,&win);CHKERRQ(ierr);
9535b0d146aSStefano Zampini #endif
9545b0d146aSStefano Zampini   for (i=0; i<nranks; i++) {
9555b0d146aSStefano Zampini     MPI_Aint tdp = target_disp ? target_disp[i] : 0;
9565b0d146aSStefano Zampini 
9575b0d146aSStefano Zampini #if !defined(PETSC_HAVE_MPI_GET_ACCUMULATE)
958ffc4695bSBarry Smith     ierr = MPI_Win_lock(MPI_LOCK_EXCLUSIVE,ranks[i],0,win);CHKERRMPI(ierr);
959ffc4695bSBarry Smith     ierr = MPI_Get(leafupdate,1,mine[i],ranks[i],tdp,1,remote[i],win);CHKERRMPI(ierr);
960c2c9d402SJose E. Roman     ierr = MPI_Accumulate((void*)leafdata,1,mine[i],ranks[i],tdp,1,remote[i],op,win);CHKERRMPI(ierr);
961ffc4695bSBarry Smith     ierr = MPI_Win_unlock(ranks[i],win);CHKERRMPI(ierr);
9625b0d146aSStefano Zampini #else
963ffc4695bSBarry Smith     if (w->sync == PETSCSF_WINDOW_SYNC_LOCK) {ierr = MPI_Win_lock(MPI_LOCK_SHARED,ranks[i],0,win);CHKERRMPI(ierr);}
964c2c9d402SJose 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);
965ffc4695bSBarry Smith     if (w->sync == PETSCSF_WINDOW_SYNC_LOCK) {ierr = MPI_Win_unlock(ranks[i],win);CHKERRMPI(ierr);}
9665b0d146aSStefano Zampini #endif
9675b0d146aSStefano Zampini   }
9685b0d146aSStefano Zampini #if !defined(PETSC_HAVE_MPI_GET_ACCUMULATE)
9695b0d146aSStefano Zampini   w->flavor = oldf;
9705b0d146aSStefano Zampini #endif
97195fce210SBarry Smith   PetscFunctionReturn(0);
97295fce210SBarry Smith }
97395fce210SBarry Smith 
97400816365SJunchao Zhang static PetscErrorCode PetscSFFetchAndOpEnd_Window(PetscSF sf,MPI_Datatype unit,void *rootdata,const void *leafdata,void *leafupdate,MPI_Op op)
97595fce210SBarry Smith {
97695fce210SBarry Smith   PetscErrorCode ierr;
97795fce210SBarry Smith   MPI_Win        win;
9785b0d146aSStefano Zampini #if defined(PETSC_HAVE_MPI_GET_ACCUMULATE)
9795b0d146aSStefano Zampini   PetscSF_Window *w = (PetscSF_Window*)sf->data;
9805b0d146aSStefano Zampini #endif
9814b9acda6SJunchao Zhang   MPI_Request    *reqs = NULL;
98295fce210SBarry Smith 
98395fce210SBarry Smith   PetscFunctionBegin;
984684a874aSStefano Zampini   ierr = PetscSFFindWindow(sf,unit,rootdata,&win,&reqs);CHKERRQ(ierr);
985ffc4695bSBarry Smith   if (reqs) {ierr = MPI_Waitall(sf->nranks,reqs,MPI_STATUSES_IGNORE);CHKERRMPI(ierr);}
9865b0d146aSStefano Zampini #if defined(PETSC_HAVE_MPI_GET_ACCUMULATE)
9875b0d146aSStefano Zampini   ierr = PetscSFRestoreWindow(sf,unit,rootdata,w->sync,PETSC_TRUE,MPI_MODE_NOSUCCEED,PETSC_TRUE,&win);CHKERRQ(ierr);
9885b0d146aSStefano Zampini #else
9895b0d146aSStefano Zampini   ierr = PetscSFRestoreWindow(sf,unit,rootdata,PETSCSF_WINDOW_SYNC_LOCK,PETSC_FALSE,0,PETSC_TRUE,&win);CHKERRQ(ierr);
9905b0d146aSStefano Zampini #endif
99195fce210SBarry Smith   PetscFunctionReturn(0);
99295fce210SBarry Smith }
99395fce210SBarry Smith 
994dec1416fSJunchao Zhang PETSC_INTERN PetscErrorCode PetscSFCreate_Window(PetscSF sf)
99595fce210SBarry Smith {
99695fce210SBarry Smith   PetscSF_Window *w = (PetscSF_Window*)sf->data;
99795fce210SBarry Smith   PetscErrorCode ierr;
99895fce210SBarry Smith 
99995fce210SBarry Smith   PetscFunctionBegin;
100095fce210SBarry Smith   sf->ops->SetUp           = PetscSFSetUp_Window;
100195fce210SBarry Smith   sf->ops->SetFromOptions  = PetscSFSetFromOptions_Window;
100295fce210SBarry Smith   sf->ops->Reset           = PetscSFReset_Window;
100395fce210SBarry Smith   sf->ops->Destroy         = PetscSFDestroy_Window;
100495fce210SBarry Smith   sf->ops->View            = PetscSFView_Window;
100595fce210SBarry Smith   sf->ops->Duplicate       = PetscSFDuplicate_Window;
1006ad227feaSJunchao Zhang   sf->ops->BcastBegin      = PetscSFBcastBegin_Window;
1007ad227feaSJunchao Zhang   sf->ops->BcastEnd        = PetscSFBcastEnd_Window;
100895fce210SBarry Smith   sf->ops->ReduceBegin     = PetscSFReduceBegin_Window;
100995fce210SBarry Smith   sf->ops->ReduceEnd       = PetscSFReduceEnd_Window;
101095fce210SBarry Smith   sf->ops->FetchAndOpBegin = PetscSFFetchAndOpBegin_Window;
101195fce210SBarry Smith   sf->ops->FetchAndOpEnd   = PetscSFFetchAndOpEnd_Window;
101295fce210SBarry Smith 
1013b00a9115SJed Brown   ierr = PetscNewLog(sf,&w);CHKERRQ(ierr);
101495fce210SBarry Smith   sf->data  = (void*)w;
101595fce210SBarry Smith   w->sync   = PETSCSF_WINDOW_SYNC_FENCE;
10165b0d146aSStefano Zampini   w->flavor = PETSCSF_WINDOW_FLAVOR_CREATE;
10175b0d146aSStefano Zampini   w->info   = MPI_INFO_NULL;
101895fce210SBarry Smith 
1019bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)sf,"PetscSFWindowSetSyncType_C",PetscSFWindowSetSyncType_Window);CHKERRQ(ierr);
1020bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)sf,"PetscSFWindowGetSyncType_C",PetscSFWindowGetSyncType_Window);CHKERRQ(ierr);
10215b0d146aSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)sf,"PetscSFWindowSetFlavorType_C",PetscSFWindowSetFlavorType_Window);CHKERRQ(ierr);
10225b0d146aSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)sf,"PetscSFWindowGetFlavorType_C",PetscSFWindowGetFlavorType_Window);CHKERRQ(ierr);
10235b0d146aSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)sf,"PetscSFWindowSetInfo_C",PetscSFWindowSetInfo_Window);CHKERRQ(ierr);
10245b0d146aSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)sf,"PetscSFWindowGetInfo_C",PetscSFWindowGetInfo_Window);CHKERRQ(ierr);
102595fce210SBarry Smith 
102695fce210SBarry Smith #if defined(OMPI_MAJOR_VERSION) && (OMPI_MAJOR_VERSION < 1 || (OMPI_MAJOR_VERSION == 1 && OMPI_MINOR_VERSION <= 6))
102795fce210SBarry Smith   {
102895fce210SBarry Smith     PetscBool ackbug = PETSC_FALSE;
1029c5929fdfSBarry Smith     ierr = PetscOptionsGetBool(NULL,NULL,"-acknowledge_ompi_onesided_bug",&ackbug,NULL);CHKERRQ(ierr);
103095fce210SBarry Smith     if (ackbug) {
1031955c1f14SBarry Smith       ierr = PetscInfo(sf,"Acknowledged Open MPI bug, proceeding anyway. Expect memory corruption.\n");CHKERRQ(ierr);
103295fce210SBarry 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");
103395fce210SBarry Smith   }
103495fce210SBarry Smith #endif
103595fce210SBarry Smith   PetscFunctionReturn(0);
103695fce210SBarry Smith }
1037