/*@C PetscSFBcastEnd - end a broadcast operation started with PetscSFBcastBegin() Collective Input Arguments: + sf - star forest . unit - data type - rootdata - buffer to broadcast Output Arguments: . leafdata - buffer to update with values from each leaf's respective root Level: intermediate .seealso: PetscSFSetGraph(), PetscSFReduceEnd() @*/ PetscErrorCode PetscSFBcastEnd(PetscSF sf,MPI_Datatype unit,const void *rootdata,void *leafdata) { PetscErrorCode ierr; PetscFunctionBegin; PetscValidHeaderSpecific(sf,PETSCSF_CLASSID,1); PetscSFCheckGraphSet(sf,1); ierr = PetscLogEventBegin(PETSCSF_BcastEnd,sf,0,0,0);CHKERRQ(ierr); ierr = PetscSFSetUp(sf);CHKERRQ(ierr); ierr = (*sf->ops->BcastEnd)(sf,unit,rootdata,leafdata);CHKERRQ(ierr); ierr = PetscLogEventEnd(PETSCSF_BcastEnd,sf,0,0,0);CHKERRQ(ierr); PetscFunctionReturn(0); }
/*@C PetscSFScatterEnd - ends pointwise scatter operation that was started with PetscSFScatterBegin() Collective Input Arguments: + sf - star forest . unit - data type - multirootdata - root buffer to send to each leaf, one unit of data per leaf Output Argument: . leafdata - leaf data to be update with personal data from each respective root Level: intermediate .seealso: PetscSFComputeDegreeEnd(), PetscSFScatterEnd() @*/ PetscErrorCode PetscSFScatterEnd(PetscSF sf,MPI_Datatype unit,const void *multirootdata,void *leafdata) { PetscErrorCode ierr; PetscSF multi; PetscFunctionBegin; PetscValidHeaderSpecific(sf,PETSCSF_CLASSID,1); PetscSFCheckGraphSet(sf,1); ierr = PetscSFSetUp(sf);CHKERRQ(ierr); ierr = PetscSFGetMultiSF(sf,&multi);CHKERRQ(ierr); ierr = PetscSFBcastEnd(multi,unit,multirootdata,leafdata);CHKERRQ(ierr); PetscFunctionReturn(0); }
/*@C PetscSFFetchAndOpBegin - begin operation that fetches values from root and updates atomically by applying operation using my leaf value, to be completed with PetscSFFetchAndOpEnd() Collective Input Arguments: + sf - star forest . unit - data type . leafdata - leaf values to use in reduction - op - operation to use for reduction Output Arguments: + rootdata - root values to be updated, input state is seen by first process to perform an update - leafupdate - state at each leaf's respective root immediately prior to my atomic update Level: advanced Note: The update is only atomic at the granularity provided by the hardware. Different roots referenced by the same process might be updated in a different order. Furthermore, if a composite type is used for the unit datatype, atomicity is not guaranteed across the whole vertex. Therefore, this function is mostly only used with primitive types such as integers. .seealso: PetscSFComputeDegreeBegin(), PetscSFReduceBegin(), PetscSFSetGraph() @*/ PetscErrorCode PetscSFFetchAndOpBegin(PetscSF sf,MPI_Datatype unit,void *rootdata,const void *leafdata,void *leafupdate,MPI_Op op) { PetscErrorCode ierr; PetscFunctionBegin; PetscValidHeaderSpecific(sf,PETSCSF_CLASSID,1); PetscSFCheckGraphSet(sf,1); ierr = PetscLogEventBegin(PETSCSF_FetchAndOpBegin,sf,0,0,0);CHKERRQ(ierr); ierr = PetscSFSetUp(sf);CHKERRQ(ierr); ierr = (*sf->ops->FetchAndOpBegin)(sf,unit,rootdata,leafdata,leafupdate,op);CHKERRQ(ierr); ierr = PetscLogEventEnd(PETSCSF_FetchAndOpBegin,sf,0,0,0);CHKERRQ(ierr); PetscFunctionReturn(0); }
/*@C PetscSFComputeDegreeEnd - complete computation of degree for each root vertex, started with PetscSFComputeDegreeBegin() Collective Input Arguments: . sf - star forest Output Arguments: . degree - degree of each root vertex Level: developer .seealso: @*/ PetscErrorCode PetscSFComputeDegreeEnd(PetscSF sf,const PetscInt **degree) { PetscErrorCode ierr; PetscFunctionBegin; PetscValidHeaderSpecific(sf,PETSCSF_CLASSID,1); PetscSFCheckGraphSet(sf,1); if (!sf->degreeknown) { ierr = PetscSFReduceEnd(sf,MPIU_INT,sf->degreetmp,sf->degree,MPI_SUM);CHKERRQ(ierr); ierr = PetscFree(sf->degreetmp);CHKERRQ(ierr); sf->degreeknown = PETSC_TRUE; } *degree = sf->degree; PetscFunctionReturn(0); }
/*@C PetscSFComputeDegreeBegin - begin computation of degree for each root vertex, to be completed with PetscSFComputeDegreeEnd() Collective Input Arguments: . sf - star forest Output Arguments: . degree - degree of each root vertex Level: advanced .seealso: PetscSFGatherBegin() @*/ PetscErrorCode PetscSFComputeDegreeBegin(PetscSF sf,const PetscInt **degree) { PetscErrorCode ierr; PetscFunctionBegin; PetscValidHeaderSpecific(sf,PETSCSF_CLASSID,1); PetscSFCheckGraphSet(sf,1); PetscValidPointer(degree,2); if (!sf->degree) { PetscInt i; ierr = PetscMalloc1(sf->nroots,&sf->degree);CHKERRQ(ierr); ierr = PetscMalloc1(sf->nleaves,&sf->degreetmp);CHKERRQ(ierr); for (i=0; i<sf->nroots; i++) sf->degree[i] = 0; for (i=0; i<sf->nleaves; i++) sf->degreetmp[i] = 1; ierr = PetscSFReduceBegin(sf,MPIU_INT,sf->degreetmp,sf->degree,MPIU_SUM);CHKERRQ(ierr); } *degree = NULL; PetscFunctionReturn(0); }
/*@C PetscSFComputeDegreeBegin - begin computation of degree for each root vertex, to be completed with PetscSFComputeDegreeEnd() Collective Input Arguments: . sf - star forest Output Arguments: . degree - degree of each root vertex Level: advanced .seealso: PetscSFGatherBegin() @*/ PetscErrorCode PetscSFComputeDegreeBegin(PetscSF sf,const PetscInt **degree) { PetscErrorCode ierr; PetscFunctionBegin; PetscValidHeaderSpecific(sf,PETSCSF_CLASSID,1); PetscSFCheckGraphSet(sf,1); PetscValidPointer(degree,2); if (!sf->degreeknown) { PetscInt i,maxlocal; if (sf->degree) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Calls to PetscSFComputeDegreeBegin() cannot be nested."); for (i=0,maxlocal=0; i<sf->nleaves; i++) maxlocal = PetscMax(maxlocal,(sf->mine ? sf->mine[i] : i)+1); ierr = PetscMalloc1(sf->nroots,&sf->degree);CHKERRQ(ierr); ierr = PetscMalloc1(maxlocal,&sf->degreetmp);CHKERRQ(ierr); for (i=0; i<sf->nroots; i++) sf->degree[i] = 0; for (i=0; i<maxlocal; i++) sf->degreetmp[i] = 1; ierr = PetscSFReduceBegin(sf,MPIU_INT,sf->degreetmp,sf->degree,MPI_SUM);CHKERRQ(ierr); } *degree = NULL; PetscFunctionReturn(0); }