#define PETSCDM_DLL #include "petscda.h" /*I "petscda.h" I*/ #include "private/dmimpl.h" #include "petscmat.h" /* rstart is where an array/subvector starts in the global parallel vector, so arrays rstarts are meaningless (and set to the previous one) except on the processor where the array lives */ typedef enum {DMCOMPOSITE_ARRAY, DMCOMPOSITE_DM} DMCompositeLinkType; struct DMCompositeLink { DMCompositeLinkType type; struct DMCompositeLink *next; PetscInt n,rstart; /* rstart is relative to this process */ PetscInt grstart; /* grstart is relative to all processes */ /* only used for DMCOMPOSITE_DM */ PetscInt *grstarts; /* global row for first unknown of this DM on each process */ DM dm; /* only used for DMCOMPOSITE_ARRAY */ PetscMPIInt rank; /* process where array unknowns live */ }; typedef struct { PetscInt n,N,rstart; /* rstart is relative to all processors, n unknowns owned by this process, N is total unknowns */ PetscInt nghost; /* number of all local entries include DA ghost points and any shared redundant arrays */ PetscInt nDM,nredundant,nmine; /* how many DM's and seperate redundant arrays used to build DM(nmine is ones on this process) */ PetscBool setup; /* after this is set, cannot add new links to the DM*/ struct DMCompositeLink *next; PetscErrorCode (*FormCoupleLocations)(DM,Mat,PetscInt*,PetscInt*,PetscInt,PetscInt,PetscInt,PetscInt); } DM_Composite; #undef __FUNCT__ #define __FUNCT__ "DMCompositeSetCoupling" /*@C DMCompositeSetCoupling - Sets user provided routines that compute the coupling between the seperate components (DA's and arrays) in a DMto build the correct matrix nonzero structure. Logically Collective on MPI_Comm Input Parameter: + dm - the composite object - formcouplelocations - routine to set the nonzero locations in the matrix Level: advanced Notes: See DMCompositeSetContext() and DMCompositeGetContext() for how to get user information into this routine .seealso DMCompositeDestroy(), DMCompositeAddArray(), DMCompositeAddDM(), DMCompositeScatter(), DMCompositeGather(), DMCompositeCreateGlobalVector(), DMCompositeGetGlobalIndices(), DMCompositeGetAccess() DMCompositeGetLocalVectors(), DMCompositeRestoreLocalVectors(), DMCompositeGetEntries(), DMCompositeSetContext(), DMCompositeGetContext() @*/ PetscErrorCode PETSCDM_DLLEXPORT DMCompositeSetCoupling(DM dm,PetscErrorCode (*FormCoupleLocations)(DM,Mat,PetscInt*,PetscInt*,PetscInt,PetscInt,PetscInt,PetscInt)) { DM_Composite *com = (DM_Composite*)dm->data; PetscFunctionBegin; com->FormCoupleLocations = FormCoupleLocations; PetscFunctionReturn(0); } #undef __FUNCT__ #define __FUNCT__ "DMCompositeSetContext" /*@ DMCompositeSetContext - Allows user to stash data they may need within the form coupling routine they set with DMCompositeSetCoupling() Not Collective Input Parameter: + dm - the composite object - ctx - the user supplied context Level: advanced Notes: Use DMCompositeGetContext() to retrieve the context when needed. .seealso DMCompositeDestroy(), DMCompositeAddArray(), DMCompositeAddDM(), DMCompositeScatter(), DMCompositeGather(), DMCompositeCreateGlobalVector(), DMCompositeGetGlobalIndices(), DMCompositeGetAccess() DMCompositeGetLocalVectors(), DMCompositeRestoreLocalVectors(), DMCompositeGetEntries(), DMCompositeSetCoupling(), DMCompositeGetContext() @*/ PetscErrorCode PETSCDM_DLLEXPORT DMCompositeSetContext(DM dm,void *ctx) { PetscFunctionBegin; dm->ctx = ctx; PetscFunctionReturn(0); } #undef __FUNCT__ #define __FUNCT__ "DMCompositeGetContext" /*@ DMCompositeGetContext - Access the context set with DMCompositeSetContext() Not Collective Input Parameter: . dm - the composite object Output Parameter: . ctx - the user supplied context Level: advanced Notes: Use DMCompositeGetContext() to retrieve the context when needed. .seealso DMCompositeDestroy(), DMCompositeAddArray(), DMCompositeAddDM(), DMCompositeScatter(), DMCompositeGather(), DMCompositeCreateGlobalVector(), DMCompositeGetGlobalIndices(), DMCompositeGetAccess() DMCompositeGetLocalVectors(), DMCompositeRestoreLocalVectors(), DMCompositeGetEntries(), DMCompositeSetCoupling(), DMCompositeSetContext() @*/ PetscErrorCode PETSCDM_DLLEXPORT DMCompositeGetContext(DM dm,void **ctx) { PetscFunctionBegin; *ctx = dm->ctx; PetscFunctionReturn(0); } #undef __FUNCT__ #define __FUNCT__ "DMCompositeCreate" /*@C DMCompositeCreate - Creates a vector packer, used to generate "composite" vectors made up of several subvectors. Collective on MPI_Comm Input Parameter: . comm - the processors that will share the global vector Output Parameters: . packer - the packer object Level: advanced .seealso DMCompositeDestroy(), DMCompositeAddArray(), DMCompositeAddDM(), DMCompositeScatter(), DMCompositeGather(), DMCompositeCreateGlobalVector(), DMCompositeGetGlobalIndices(), DMCompositeGetAccess() DMCompositeGetLocalVectors(), DMCompositeRestoreLocalVectors(), DMCompositeGetEntries() @*/ PetscErrorCode PETSCDM_DLLEXPORT DMCompositeCreate(MPI_Comm comm,DM *packer) { PetscErrorCode ierr; DM p; DM_Composite *com; PetscFunctionBegin; PetscValidPointer(packer,2); *packer = PETSC_NULL; #ifndef PETSC_USE_DYNAMIC_LIBRARIES ierr = DMInitializePackage(PETSC_NULL);CHKERRQ(ierr); #endif ierr = PetscHeaderCreate(p,_p_DM,struct _DMOps,DM_CLASSID,0,"DM",comm,DMCompositeDestroy,DMCompositeView);CHKERRQ(ierr); ierr = PetscNewLog(p,DM_Composite,&com);CHKERRQ(ierr); p->data = com; ierr = PetscObjectChangeTypeName((PetscObject)p,"DMComposite");CHKERRQ(ierr); com->n = 0; com->next = PETSC_NULL; com->nredundant = 0; com->nDM = 0; p->ops->createglobalvector = DMCompositeCreateGlobalVector; p->ops->createlocalvector = DMCompositeCreateLocalVector; p->ops->refine = DMCompositeRefine; p->ops->getinterpolation = DMCompositeGetInterpolation; p->ops->getmatrix = DMCompositeGetMatrix; p->ops->getcoloring = DMCompositeGetColoring; p->ops->globaltolocalbegin = DMCompositeGlobalToLocalBegin; p->ops->globaltolocalend = DMCompositeGlobalToLocalEnd; p->ops->destroy = DMCompositeDestroy; *packer = p; PetscFunctionReturn(0); } extern PetscErrorCode DMDestroy_Private(DM,PetscBool *); #undef __FUNCT__ #define __FUNCT__ "DMCompositeDestroy" /*@C DMCompositeDestroy - Destroys a vector packer. Collective on DMComposite Input Parameter: . packer - the packer object Level: advanced .seealso DMCompositeCreate(), DMCompositeAddArray(), DMCompositeAddDM(), DMCompositeScatter(),DMCompositeGetEntries() DMCompositeGather(), DMCompositeCreateGlobalVector(), DMCompositeGetGlobalIndices(), DMCompositeGetAccess() @*/ PetscErrorCode PETSCDM_DLLEXPORT DMCompositeDestroy(DM dm) { PetscErrorCode ierr; struct DMCompositeLink *next, *prev; PetscBool done; DM_Composite *com = (DM_Composite *)dm->data; PetscFunctionBegin; PetscValidHeaderSpecific(dm,DM_CLASSID,1); ierr = DMDestroy_Private((DM)dm,&done);CHKERRQ(ierr); if (!done) PetscFunctionReturn(0); next = com->next; while (next) { prev = next; next = next->next; if (prev->type == DMCOMPOSITE_DM) { ierr = DMDestroy(prev->dm);CHKERRQ(ierr); } if (prev->grstarts) { ierr = PetscFree(prev->grstarts);CHKERRQ(ierr); } ierr = PetscFree(prev);CHKERRQ(ierr); } ierr = PetscFree(com);CHKERRQ(ierr); ierr = PetscHeaderDestroy(dm);CHKERRQ(ierr); PetscFunctionReturn(0); } #undef __FUNCT__ #define __FUNCT__ "DMCompositeView" /*@ DMCompositeView - Views a composite DM Collective on DMComposite Input Parameter: + packer - the DMobject to view - v - the viewer Level: intermediate .seealso DMCompositeCreate() @*/ PetscErrorCode PETSCDM_DLLEXPORT DMCompositeView(DM dm,PetscViewer v) { PetscErrorCode ierr; PetscBool iascii; DM_Composite *com = (DM_Composite *)dm->data; PetscFunctionBegin; ierr = PetscTypeCompare((PetscObject)v,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr); if (iascii) { struct DMCompositeLink *lnk = com->next; PetscInt i; ierr = PetscViewerASCIIPrintf(v,"DM (%s)\n",((PetscObject)dm)->prefix?((PetscObject)dm)->prefix:"no prefix");CHKERRQ(ierr); ierr = PetscViewerASCIIPrintf(v," contains %d DMs and %d redundant arrays\n",com->nDM,com->nredundant);CHKERRQ(ierr); ierr = PetscViewerASCIIPushTab(v);CHKERRQ(ierr); for (i=0; lnk; lnk=lnk->next,i++) { if (lnk->dm) { ierr = PetscViewerASCIIPrintf(v,"Link %d: DM of type %s\n",i,((PetscObject)lnk->dm)->type_name);CHKERRQ(ierr); ierr = PetscViewerASCIIPushTab(v);CHKERRQ(ierr); ierr = DMView(lnk->dm,v);CHKERRQ(ierr); ierr = PetscViewerASCIIPopTab(v);CHKERRQ(ierr); } else { ierr = PetscViewerASCIIPrintf(v,"Link %d: Redundant array of size %d owned by rank %d\n",i,lnk->n,lnk->rank);CHKERRQ(ierr); } } ierr = PetscViewerASCIIPopTab(v);CHKERRQ(ierr); } PetscFunctionReturn(0); } /* --------------------------------------------------------------------------------------*/ #undef __FUNCT__ #define __FUNCT__ "DMCompositeSetUp" PetscErrorCode PETSCDM_DLLEXPORT DMCompositeSetUp(DM dm) { PetscErrorCode ierr; PetscInt nprev = 0; PetscMPIInt rank,size; DM_Composite *com = (DM_Composite*)dm->data; struct DMCompositeLink *next = com->next; PetscLayout map; PetscFunctionBegin; if (com->setup) SETERRQ(((PetscObject)dm)->comm,PETSC_ERR_ARG_WRONGSTATE,"Packer has already been setup"); ierr = PetscLayoutCreate(((PetscObject)dm)->comm,&map);CHKERRQ(ierr); ierr = PetscLayoutSetLocalSize(map,com->n);CHKERRQ(ierr); ierr = PetscLayoutSetSize(map,PETSC_DETERMINE);CHKERRQ(ierr); ierr = PetscLayoutSetBlockSize(map,1);CHKERRQ(ierr); ierr = PetscLayoutSetUp(map);CHKERRQ(ierr); ierr = PetscLayoutGetSize(map,&com->N);CHKERRQ(ierr); ierr = PetscLayoutGetRange(map,&com->rstart,PETSC_NULL);CHKERRQ(ierr); ierr = PetscLayoutDestroy(map);CHKERRQ(ierr); /* now set the rstart for each linked array/vector */ ierr = MPI_Comm_rank(((PetscObject)dm)->comm,&rank);CHKERRQ(ierr); ierr = MPI_Comm_size(((PetscObject)dm)->comm,&size);CHKERRQ(ierr); while (next) { next->rstart = nprev; if ((rank == next->rank) || next->type != DMCOMPOSITE_ARRAY) nprev += next->n; next->grstart = com->rstart + next->rstart; if (next->type == DMCOMPOSITE_ARRAY) { ierr = MPI_Bcast(&next->grstart,1,MPIU_INT,next->rank,((PetscObject)dm)->comm);CHKERRQ(ierr); } else { ierr = PetscMalloc(size*sizeof(PetscInt),&next->grstarts);CHKERRQ(ierr); ierr = MPI_Allgather(&next->grstart,1,MPIU_INT,next->grstarts,1,MPIU_INT,((PetscObject)dm)->comm);CHKERRQ(ierr); } next = next->next; } com->setup = PETSC_TRUE; PetscFunctionReturn(0); } #undef __FUNCT__ #define __FUNCT__ "DMCompositeGetAccess_Array" PetscErrorCode DMCompositeGetAccess_Array(DM dm,struct DMCompositeLink *mine,Vec vec,PetscScalar **array) { PetscErrorCode ierr; PetscScalar *varray; PetscMPIInt rank; PetscFunctionBegin; ierr = MPI_Comm_rank(((PetscObject)dm)->comm,&rank);CHKERRQ(ierr); if (array) { if (rank == mine->rank) { ierr = VecGetArray(vec,&varray);CHKERRQ(ierr); *array = varray + mine->rstart; ierr = VecRestoreArray(vec,&varray);CHKERRQ(ierr); } else { *array = 0; } } PetscFunctionReturn(0); } #undef __FUNCT__ #define __FUNCT__ "DMCompositeGetAccess_DM" PetscErrorCode DMCompositeGetAccess_DM(DM dm,struct DMCompositeLink *mine,Vec vec,Vec *global) { PetscErrorCode ierr; PetscScalar *array; PetscFunctionBegin; if (global) { ierr = DMGetGlobalVector(mine->dm,global);CHKERRQ(ierr); ierr = VecGetArray(vec,&array);CHKERRQ(ierr); ierr = VecPlaceArray(*global,array+mine->rstart);CHKERRQ(ierr); ierr = VecRestoreArray(vec,&array);CHKERRQ(ierr); } PetscFunctionReturn(0); } #undef __FUNCT__ #define __FUNCT__ "DMCompositeRestoreAccess_Array" PetscErrorCode DMCompositeRestoreAccess_Array(DM dm,struct DMCompositeLink *mine,Vec vec,PetscScalar **array) { PetscFunctionBegin; PetscFunctionReturn(0); } #undef __FUNCT__ #define __FUNCT__ "DMCompositeRestoreAccess_DM" PetscErrorCode DMCompositeRestoreAccess_DM(DM dm,struct DMCompositeLink *mine,Vec vec,Vec *global) { PetscErrorCode ierr; PetscFunctionBegin; if (global) { ierr = VecResetArray(*global);CHKERRQ(ierr); ierr = DMRestoreGlobalVector(mine->dm,global);CHKERRQ(ierr); } PetscFunctionReturn(0); } #undef __FUNCT__ #define __FUNCT__ "DMCompositeScatter_Array" PetscErrorCode DMCompositeScatter_Array(DM dm,struct DMCompositeLink *mine,Vec vec,PetscScalar *array) { PetscErrorCode ierr; PetscScalar *varray; PetscMPIInt rank; PetscFunctionBegin; ierr = MPI_Comm_rank(((PetscObject)dm)->comm,&rank);CHKERRQ(ierr); if (rank == mine->rank) { ierr = VecGetArray(vec,&varray);CHKERRQ(ierr); ierr = PetscMemcpy(array,varray+mine->rstart,mine->n*sizeof(PetscScalar));CHKERRQ(ierr); ierr = VecRestoreArray(vec,&varray);CHKERRQ(ierr); } ierr = MPI_Bcast(array,mine->n,MPIU_SCALAR,mine->rank,((PetscObject)dm)->comm);CHKERRQ(ierr); PetscFunctionReturn(0); } #undef __FUNCT__ #define __FUNCT__ "DMCompositeScatter_DM" PetscErrorCode DMCompositeScatter_DM(DM dm,struct DMCompositeLink *mine,Vec vec,Vec local) { PetscErrorCode ierr; PetscScalar *array; Vec global; PetscFunctionBegin; ierr = DMGetGlobalVector(mine->dm,&global);CHKERRQ(ierr); ierr = VecGetArray(vec,&array);CHKERRQ(ierr); ierr = VecPlaceArray(global,array+mine->rstart);CHKERRQ(ierr); ierr = DMGlobalToLocalBegin(mine->dm,global,INSERT_VALUES,local);CHKERRQ(ierr); ierr = DMGlobalToLocalEnd(mine->dm,global,INSERT_VALUES,local);CHKERRQ(ierr); ierr = VecRestoreArray(vec,&array);CHKERRQ(ierr); ierr = VecResetArray(global);CHKERRQ(ierr); ierr = DMRestoreGlobalVector(mine->dm,&global);CHKERRQ(ierr); PetscFunctionReturn(0); } #undef __FUNCT__ #define __FUNCT__ "DMCompositeGather_Array" PetscErrorCode DMCompositeGather_Array(DM dm,struct DMCompositeLink *mine,Vec vec,PetscScalar *array) { PetscErrorCode ierr; PetscScalar *varray; PetscMPIInt rank; PetscFunctionBegin; ierr = MPI_Comm_rank(((PetscObject)dm)->comm,&rank);CHKERRQ(ierr); if (rank == mine->rank) { ierr = VecGetArray(vec,&varray);CHKERRQ(ierr); if (varray+mine->rstart == array) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"You need not DMCompositeGather() into objects obtained via DMCompositeGetAccess()"); ierr = PetscMemcpy(varray+mine->rstart,array,mine->n*sizeof(PetscScalar));CHKERRQ(ierr); ierr = VecRestoreArray(vec,&varray);CHKERRQ(ierr); } PetscFunctionReturn(0); } #undef __FUNCT__ #define __FUNCT__ "DMCompositeGather_DM" PetscErrorCode DMCompositeGather_DM(DM dm,struct DMCompositeLink *mine,Vec vec,Vec local) { PetscErrorCode ierr; PetscScalar *array; Vec global; PetscFunctionBegin; ierr = DMGetGlobalVector(mine->dm,&global);CHKERRQ(ierr); ierr = VecGetArray(vec,&array);CHKERRQ(ierr); ierr = VecPlaceArray(global,array+mine->rstart);CHKERRQ(ierr); ierr = DMLocalToGlobal(mine->dm,local,INSERT_VALUES,global);CHKERRQ(ierr); ierr = VecRestoreArray(vec,&array);CHKERRQ(ierr); ierr = VecResetArray(global);CHKERRQ(ierr); ierr = DMRestoreGlobalVector(mine->dm,&global);CHKERRQ(ierr); PetscFunctionReturn(0); } /* ----------------------------------------------------------------------------------*/ #include #undef __FUNCT__ #define __FUNCT__ "DMCompositeGetNumberDM" /*@C DMCompositeGetNumberDM - Get's the number of DM objects in the DMComposite representation. Not Collective Input Parameter: . dm - the packer object Output Parameter: . nDM - the number of DMs Level: beginner .seealso DMCompositeDestroy(), DMCompositeAddArray(), DMCompositeAddDM(), DMCompositeCreateGlobalVector(), DMCompositeGather(), DMCompositeCreate(), DMCompositeGetGlobalIndices(), DMCompositeScatter(), DMCompositeRestoreAccess(), DMCompositeGetLocalVectors(), DMCompositeRestoreLocalVectors(), DMCompositeGetEntries() @*/ PetscErrorCode PETSCDM_DLLEXPORT DMCompositeGetNumberDM(DM dm,PetscInt *nDM) { DM_Composite *com = (DM_Composite*)dm->data; PetscFunctionBegin; PetscValidHeaderSpecific(dm,DM_CLASSID,1); *nDM = com->nDM; PetscFunctionReturn(0); } #undef __FUNCT__ #define __FUNCT__ "DMCompositeGetAccess" /*@C DMCompositeGetAccess - Allows one to access the individual packed vectors in their global representation. Collective on DMComposite Input Parameter: + dm - the packer object . gvec - the global vector - ... - the individual sequential or parallel objects (arrays or vectors) Notes: Use DMCompositeRestoreAccess() to return the vectors when you no longer need them Level: advanced .seealso DMCompositeDestroy(), DMCompositeAddArray(), DMCompositeAddDM(), DMCompositeCreateGlobalVector(), DMCompositeGather(), DMCompositeCreate(), DMCompositeGetGlobalIndices(), DMCompositeScatter(), DMCompositeRestoreAccess(), DMCompositeGetLocalVectors(), DMCompositeRestoreLocalVectors(), DMCompositeGetEntries() @*/ PetscErrorCode PETSCDM_DLLEXPORT DMCompositeGetAccess(DM dm,Vec gvec,...) { va_list Argp; PetscErrorCode ierr; struct DMCompositeLink *next; DM_Composite *com = (DM_Composite*)dm->data; PetscFunctionBegin; PetscValidHeaderSpecific(dm,DM_CLASSID,1); PetscValidHeaderSpecific(gvec,VEC_CLASSID,2); next = com->next; if (!com->setup) { ierr = DMCompositeSetUp(dm);CHKERRQ(ierr); } /* loop over packed objects, handling one at at time */ va_start(Argp,gvec); while (next) { if (next->type == DMCOMPOSITE_ARRAY) { PetscScalar **array; array = va_arg(Argp, PetscScalar**); ierr = DMCompositeGetAccess_Array(dm,next,gvec,array);CHKERRQ(ierr); } else if (next->type == DMCOMPOSITE_DM) { Vec *vec; vec = va_arg(Argp, Vec*); ierr = DMCompositeGetAccess_DM(dm,next,gvec,vec);CHKERRQ(ierr); } else { SETERRQ(((PetscObject)dm)->comm,PETSC_ERR_SUP,"Cannot handle that object type yet"); } next = next->next; } va_end(Argp); PetscFunctionReturn(0); } #undef __FUNCT__ #define __FUNCT__ "DMCompositeRestoreAccess" /*@C DMCompositeRestoreAccess - Returns the vectors obtained with DACompositeGetAccess() representation. Collective on DMComposite Input Parameter: + dm - the packer object . gvec - the global vector - ... - the individual sequential or parallel objects (arrays or vectors) Level: advanced .seealso DMCompositeDestroy(), DMCompositeAddArray(), DMCompositeAddDM(), DMCompositeCreateGlobalVector(), DMCompositeGather(), DMCompositeCreate(), DMCompositeGetGlobalIndices(), DMCompositeScatter(), DMCompositeRestoreAccess(), DACompositeGetAccess() @*/ PetscErrorCode PETSCDM_DLLEXPORT DMCompositeRestoreAccess(DM dm,Vec gvec,...) { va_list Argp; PetscErrorCode ierr; struct DMCompositeLink *next; DM_Composite *com = (DM_Composite*)dm->data; PetscFunctionBegin; PetscValidHeaderSpecific(dm,DM_CLASSID,1); PetscValidHeaderSpecific(gvec,VEC_CLASSID,2); next = com->next; if (!com->setup) { ierr = DMCompositeSetUp(dm);CHKERRQ(ierr); } /* loop over packed objects, handling one at at time */ va_start(Argp,gvec); while (next) { if (next->type == DMCOMPOSITE_ARRAY) { PetscScalar **array; array = va_arg(Argp, PetscScalar**); ierr = DMCompositeRestoreAccess_Array(dm,next,gvec,array);CHKERRQ(ierr); } else if (next->type == DMCOMPOSITE_DM) { Vec *vec; vec = va_arg(Argp, Vec*); ierr = DMCompositeRestoreAccess_DM(dm,next,gvec,vec);CHKERRQ(ierr); } else { SETERRQ(((PetscObject)dm)->comm,PETSC_ERR_SUP,"Cannot handle that object type yet"); } next = next->next; } va_end(Argp); PetscFunctionReturn(0); } #undef __FUNCT__ #define __FUNCT__ "DMCompositeScatter" /*@C DMCompositeScatter - Scatters from a global packed vector into its individual local vectors Collective on DMComposite Input Parameter: + dm - the packer object . gvec - the global vector - ... - the individual sequential objects (arrays or vectors) Level: advanced .seealso DMCompositeDestroy(), DMCompositeAddArray(), DMCompositeAddDM(), DMCompositeCreateGlobalVector(), DMCompositeGather(), DMCompositeCreate(), DMCompositeGetGlobalIndices(), DMCompositeGetAccess(), DMCompositeGetLocalVectors(), DMCompositeRestoreLocalVectors(), DMCompositeGetEntries() @*/ PetscErrorCode PETSCDM_DLLEXPORT DMCompositeScatter(DM dm,Vec gvec,...) { va_list Argp; PetscErrorCode ierr; struct DMCompositeLink *next; PetscInt cnt = 3; DM_Composite *com = (DM_Composite*)dm->data; PetscFunctionBegin; PetscValidHeaderSpecific(dm,DM_CLASSID,1); PetscValidHeaderSpecific(gvec,VEC_CLASSID,2); next = com->next; if (!com->setup) { ierr = DMCompositeSetUp(dm);CHKERRQ(ierr); } /* loop over packed objects, handling one at at time */ va_start(Argp,gvec); while (next) { if (next->type == DMCOMPOSITE_ARRAY) { PetscScalar *array; array = va_arg(Argp, PetscScalar*); ierr = DMCompositeScatter_Array(dm,next,gvec,array);CHKERRQ(ierr); } else if (next->type == DMCOMPOSITE_DM) { Vec vec; vec = va_arg(Argp, Vec); PetscValidHeaderSpecific(vec,VEC_CLASSID,cnt); ierr = DMCompositeScatter_DM(dm,next,gvec,vec);CHKERRQ(ierr); } else { SETERRQ(((PetscObject)dm)->comm,PETSC_ERR_SUP,"Cannot handle that object type yet"); } cnt++; next = next->next; } va_end(Argp); PetscFunctionReturn(0); } #undef __FUNCT__ #define __FUNCT__ "DMCompositeGather" /*@C DMCompositeGather - Gathers into a global packed vector from its individual local vectors Collective on DMComposite Input Parameter: + dm - the packer object . gvec - the global vector - ... - the individual sequential objects (arrays or vectors) Level: advanced .seealso DMCompositeDestroy(), DMCompositeAddArray(), DMCompositeAddDM(), DMCompositeCreateGlobalVector(), DMCompositeScatter(), DMCompositeCreate(), DMCompositeGetGlobalIndices(), DMCompositeGetAccess(), DMCompositeGetLocalVectors(), DMCompositeRestoreLocalVectors(), DMCompositeGetEntries() @*/ PetscErrorCode PETSCDM_DLLEXPORT DMCompositeGather(DM dm,Vec gvec,...) { va_list Argp; PetscErrorCode ierr; struct DMCompositeLink *next; DM_Composite *com = (DM_Composite*)dm->data; PetscFunctionBegin; PetscValidHeaderSpecific(dm,DM_CLASSID,1); PetscValidHeaderSpecific(gvec,VEC_CLASSID,2); next = com->next; if (!com->setup) { ierr = DMCompositeSetUp(dm);CHKERRQ(ierr); } /* loop over packed objects, handling one at at time */ va_start(Argp,gvec); while (next) { if (next->type == DMCOMPOSITE_ARRAY) { PetscScalar *array; array = va_arg(Argp, PetscScalar*); ierr = DMCompositeGather_Array(dm,next,gvec,array);CHKERRQ(ierr); } else if (next->type == DMCOMPOSITE_DM) { Vec vec; vec = va_arg(Argp, Vec); PetscValidHeaderSpecific(vec,VEC_CLASSID,3); ierr = DMCompositeGather_DM(dm,next,gvec,vec);CHKERRQ(ierr); } else { SETERRQ(((PetscObject)dm)->comm,PETSC_ERR_SUP,"Cannot handle that object type yet"); } next = next->next; } va_end(Argp); PetscFunctionReturn(0); } #undef __FUNCT__ #define __FUNCT__ "DMCompositeAddArray" /*@C DMCompositeAddArray - adds an "redundant" array to a DMComposite. The array values will be stored in part of the array on process orank. Collective on DMComposite Input Parameter: + dm - the packer object . orank - the process on which the array entries officially live, this number must be the same on all processes. - n - the length of the array Level: advanced .seealso DMCompositeDestroy(), DMCompositeGather(), DMCompositeAddDM(), DMCompositeCreateGlobalVector(), DMCompositeScatter(), DMCompositeCreate(), DMCompositeGetGlobalIndices(), DMCompositeGetAccess(), DMCompositeGetLocalVectors(), DMCompositeRestoreLocalVectors(), DMCompositeGetEntries() @*/ PetscErrorCode PETSCDM_DLLEXPORT DMCompositeAddArray(DM dm,PetscMPIInt orank,PetscInt n) { struct DMCompositeLink *mine,*next; PetscErrorCode ierr; PetscMPIInt rank; DM_Composite *com = (DM_Composite*)dm->data; PetscFunctionBegin; PetscValidHeaderSpecific(dm,DM_CLASSID,1); next = com->next; if (com->setup) { SETERRQ(((PetscObject)dm)->comm,PETSC_ERR_ARG_WRONGSTATE,"Cannot add an array once you have used the DMComposite"); } #if defined(PETSC_USE_DEBUG) { PetscMPIInt orankmax; ierr = MPI_Allreduce(&orank,&orankmax,1,MPI_INT,MPI_MAX,((PetscObject)dm)->comm);CHKERRQ(ierr); if (orank != orankmax) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"orank %d must be equal on all processes, another process has value %d",orank,orankmax); } #endif ierr = MPI_Comm_rank(((PetscObject)dm)->comm,&rank);CHKERRQ(ierr); /* create new link */ ierr = PetscNew(struct DMCompositeLink,&mine);CHKERRQ(ierr); mine->n = n; mine->rank = orank; mine->dm = PETSC_NULL; mine->type = DMCOMPOSITE_ARRAY; mine->next = PETSC_NULL; if (rank == mine->rank) {com->n += n;com->nmine++;} /* add to end of list */ if (!next) { com->next = mine; } else { while (next->next) next = next->next; next->next = mine; } com->nredundant++; PetscFunctionReturn(0); } #undef __FUNCT__ #define __FUNCT__ "DMCompositeAddDM" /*@C DMCompositeAddDM - adds a DM (includes DA) vector to a DMComposite Collective on DMComposite Input Parameter: + dm - the packer object - dm - the DM object, if the DM is a da you will need to caste it with a (DM) Level: advanced .seealso DMCompositeDestroy(), DMCompositeGather(), DMCompositeAddDM(), DMCompositeCreateGlobalVector(), DMCompositeScatter(), DMCompositeCreate(), DMCompositeGetGlobalIndices(), DMCompositeGetAccess(), DMCompositeGetLocalVectors(), DMCompositeRestoreLocalVectors(), DMCompositeGetEntries() @*/ PetscErrorCode PETSCDM_DLLEXPORT DMCompositeAddDM(DM dmc,DM dm) { PetscErrorCode ierr; PetscInt n; struct DMCompositeLink *mine,*next; Vec global; DM_Composite *com = (DM_Composite*)dmc->data; PetscFunctionBegin; PetscValidHeaderSpecific(dmc,DM_CLASSID,1); PetscValidHeaderSpecific(dm,DM_CLASSID,2); next = com->next; if (com->setup) SETERRQ(((PetscObject)dmc)->comm,PETSC_ERR_ARG_WRONGSTATE,"Cannot add a DA once you have used the DMComposite"); /* create new link */ ierr = PetscNew(struct DMCompositeLink,&mine);CHKERRQ(ierr); ierr = PetscObjectReference((PetscObject)dm);CHKERRQ(ierr); ierr = DMGetGlobalVector(dm,&global);CHKERRQ(ierr); ierr = VecGetLocalSize(global,&n);CHKERRQ(ierr); ierr = DMRestoreGlobalVector(dm,&global);CHKERRQ(ierr); mine->n = n; mine->dm = dm; mine->type = DMCOMPOSITE_DM; mine->next = PETSC_NULL; com->n += n; /* add to end of list */ if (!next) { com->next = mine; } else { while (next->next) next = next->next; next->next = mine; } com->nDM++; com->nmine++; PetscFunctionReturn(0); } extern PetscErrorCode PETSCDM_DLLEXPORT VecView_MPI(Vec,PetscViewer); EXTERN_C_BEGIN #undef __FUNCT__ #define __FUNCT__ "VecView_DMComposite" PetscErrorCode PETSCDM_DLLEXPORT VecView_DMComposite(Vec gvec,PetscViewer viewer) { DM dm; PetscErrorCode ierr; struct DMCompositeLink *next; PetscBool isdraw; DM_Composite *com = (DM_Composite*)dm->data; PetscFunctionBegin; ierr = PetscObjectQuery((PetscObject)gvec,"DMComposite",(PetscObject*)&dm);CHKERRQ(ierr); if (!dm) SETERRQ(((PetscObject)gvec)->comm,PETSC_ERR_ARG_WRONG,"Vector not generated from a DMComposite"); com = (DM_Composite*)dm->data; next = com->next; ierr = PetscTypeCompare((PetscObject)viewer,PETSCVIEWERDRAW,&isdraw);CHKERRQ(ierr); if (!isdraw) { /* do I really want to call this? */ ierr = VecView_MPI(gvec,viewer);CHKERRQ(ierr); } else { PetscInt cnt = 0; /* loop over packed objects, handling one at at time */ while (next) { if (next->type == DMCOMPOSITE_ARRAY) { PetscScalar *array; ierr = DMCompositeGetAccess_Array(dm,next,gvec,&array);CHKERRQ(ierr); /*skip it for now */ } else if (next->type == DMCOMPOSITE_DM) { Vec vec; PetscInt bs; ierr = DMCompositeGetAccess_DM(dm,next,gvec,&vec);CHKERRQ(ierr); ierr = VecView(vec,viewer);CHKERRQ(ierr); ierr = VecGetBlockSize(vec,&bs);CHKERRQ(ierr); ierr = DMCompositeRestoreAccess_DM(dm,next,gvec,&vec);CHKERRQ(ierr); ierr = PetscViewerDrawBaseAdd(viewer,bs);CHKERRQ(ierr); cnt += bs; } else { SETERRQ(((PetscObject)dm)->comm,PETSC_ERR_SUP,"Cannot handle that object type yet"); } next = next->next; } ierr = PetscViewerDrawBaseAdd(viewer,-cnt);CHKERRQ(ierr); } PetscFunctionReturn(0); } EXTERN_C_END #undef __FUNCT__ #define __FUNCT__ "DMCompositeCreateGlobalVector" /*@C DMCompositeCreateGlobalVector - Creates a vector of the correct size to be gathered into by the packer. Collective on DMComposite Input Parameter: . dm - the packer object Output Parameters: . gvec - the global vector Level: advanced Notes: Once this has been created you cannot add additional arrays or vectors to be packed. .seealso DMCompositeDestroy(), DMCompositeAddArray(), DMCompositeAddDM(), DMCompositeScatter(), DMCompositeGather(), DMCompositeCreate(), DMCompositeGetGlobalIndices(), DMCompositeGetAccess(), DMCompositeGetLocalVectors(), DMCompositeRestoreLocalVectors(), DMCompositeGetEntries(), DMCompositeCreateLocalVector() @*/ PetscErrorCode PETSCDM_DLLEXPORT DMCompositeCreateGlobalVector(DM dm,Vec *gvec) { PetscErrorCode ierr; DM_Composite *com = (DM_Composite*)dm->data; PetscFunctionBegin; PetscValidHeaderSpecific(dm,DM_CLASSID,1); if (!com->setup) { ierr = DMCompositeSetUp(dm);CHKERRQ(ierr); } ierr = VecCreateMPI(((PetscObject)dm)->comm,com->n,com->N,gvec);CHKERRQ(ierr); ierr = PetscObjectCompose((PetscObject)*gvec,"DMComposite",(PetscObject)dm);CHKERRQ(ierr); ierr = VecSetOperation(*gvec,VECOP_VIEW,(void(*)(void))VecView_DMComposite);CHKERRQ(ierr); PetscFunctionReturn(0); } #undef __FUNCT__ #define __FUNCT__ "DMCompositeCreateLocalVector" /*@C DMCompositeCreateLocalVector - Creates a vector of the correct size to contain all ghost points and redundant arrays. Not Collective Input Parameter: . dm - the packer object Output Parameters: . lvec - the local vector Level: advanced Notes: Once this has been created you cannot add additional arrays or vectors to be packed. .seealso DMCompositeDestroy(), DMCompositeAddArray(), DMCompositeAddDM(), DMCompositeScatter(), DMCompositeGather(), DMCompositeCreate(), DMCompositeGetGlobalIndices(), DMCompositeGetAccess(), DMCompositeGetLocalVectors(), DMCompositeRestoreLocalVectors(), DMCompositeGetEntries(), DMCompositeCreateGlobalVector() @*/ PetscErrorCode PETSCDM_DLLEXPORT DMCompositeCreateLocalVector(DM dm,Vec *lvec) { PetscErrorCode ierr; DM_Composite *com = (DM_Composite*)dm->data; PetscFunctionBegin; PetscValidHeaderSpecific(dm,DM_CLASSID,1); if (!com->setup) { ierr = DMCompositeSetUp(dm);CHKERRQ(ierr); } ierr = VecCreateSeq(((PetscObject)dm)->comm,com->nghost,lvec);CHKERRQ(ierr); ierr = PetscObjectCompose((PetscObject)*lvec,"DMComposite",(PetscObject)dm);CHKERRQ(ierr); PetscFunctionReturn(0); } #undef __FUNCT__ #define __FUNCT__ "DMCompositeGetLocalISs" /*@C DMCompositeGetLocalISs - gets an IS for each DM/array in the DMComposite, include ghost points Collective on DMComposite Input Parameter: . dm - the packer object Output Parameters: . is - the individual indices for each packed vector/array. Note that this includes all the ghost points that individual ghosted DA's may have. Also each process has an is for EACH redundant array (not just the local redundant arrays). Level: advanced Notes: The is entries should be destroyed with ISDestroy(), the is array should be freed with PetscFree() Use DMCompositeGetGlobalISs() for non-ghosted ISs. .seealso DMCompositeDestroy(), DMCompositeAddArray(), DMCompositeAddDM(), DMCompositeCreateGlobalVector(), DMCompositeGather(), DMCompositeCreate(), DMCompositeGetAccess(), DMCompositeScatter(), DMCompositeGetLocalVectors(), DMCompositeRestoreLocalVectors(),DMCompositeGetEntries() @*/ PetscErrorCode PETSCDM_DLLEXPORT DMCompositeGetGlobalIndices(DM dm,IS *is[]) { PetscErrorCode ierr; PetscInt i,*idx,n,cnt; struct DMCompositeLink *next; Vec global,dglobal; PF pf; PetscScalar *array; PetscMPIInt rank; DM_Composite *com = (DM_Composite*)dm->data; PetscFunctionBegin; PetscValidHeaderSpecific(dm,DM_CLASSID,1); ierr = PetscMalloc(com->nmine*sizeof(IS),is);CHKERRQ(ierr); next = com->next; ierr = DMCompositeCreateGlobalVector(dm,&global);CHKERRQ(ierr); ierr = MPI_Comm_rank(((PetscObject)dm)->comm,&rank);CHKERRQ(ierr); /* put 0 to N-1 into the global vector */ ierr = PFCreate(PETSC_COMM_WORLD,1,1,&pf);CHKERRQ(ierr); ierr = PFSetType(pf,PFIDENTITY,PETSC_NULL);CHKERRQ(ierr); ierr = PFApplyVec(pf,PETSC_NULL,global);CHKERRQ(ierr); ierr = PFDestroy(pf);CHKERRQ(ierr); /* loop over packed objects, handling one at at time */ cnt = 0; while (next) { if (next->type == DMCOMPOSITE_ARRAY) { ierr = PetscMalloc(next->n*sizeof(PetscInt),&idx);CHKERRQ(ierr); if (rank == next->rank) { ierr = VecGetArray(global,&array);CHKERRQ(ierr); array += next->rstart; for (i=0; in; i++) idx[i] = (PetscInt)PetscRealPart(array[i]); array -= next->rstart; ierr = VecRestoreArray(global,&array);CHKERRQ(ierr); } ierr = MPI_Bcast(idx,next->n,MPIU_INT,next->rank,((PetscObject)dm)->comm);CHKERRQ(ierr); ierr = ISCreateGeneral(((PetscObject)dm)->comm,next->n,idx,PETSC_OWN_POINTER,&(*is)[cnt]);CHKERRQ(ierr); } else if (next->type == DMCOMPOSITE_DM) { Vec local; ierr = DMCreateLocalVector(next->dm,&local);CHKERRQ(ierr); ierr = VecGetArray(global,&array);CHKERRQ(ierr); array += next->rstart; ierr = DMGetGlobalVector(next->dm,&dglobal);CHKERRQ(ierr); ierr = VecPlaceArray(dglobal,array);CHKERRQ(ierr); ierr = DMGlobalToLocalBegin(next->dm,dglobal,INSERT_VALUES,local);CHKERRQ(ierr); ierr = DMGlobalToLocalEnd(next->dm,dglobal,INSERT_VALUES,local);CHKERRQ(ierr); array -= next->rstart; ierr = VecRestoreArray(global,&array);CHKERRQ(ierr); ierr = VecResetArray(dglobal);CHKERRQ(ierr); ierr = DMRestoreGlobalVector(next->dm,&dglobal);CHKERRQ(ierr); ierr = VecGetArray(local,&array);CHKERRQ(ierr); ierr = VecGetSize(local,&n);CHKERRQ(ierr); ierr = PetscMalloc(n*sizeof(PetscInt),&idx);CHKERRQ(ierr); for (i=0; icomm,next->n,idx,PETSC_OWN_POINTER,&(*is)[cnt]);CHKERRQ(ierr); } else SETERRQ(((PetscObject)global)->comm,PETSC_ERR_SUP,"Cannot handle that object type yet"); next = next->next; cnt++; } ierr = VecDestroy(global);CHKERRQ(ierr); PetscFunctionReturn(0); } #undef __FUNCT__ #define __FUNCT__ "DMCompositeGetGlobalISs" /*@C DMCompositeGetGlobalISs - Gets the index sets for each composed object Collective on DMComposite Input Parameter: . dm - the packer object Output Parameters: . is - the array of index sets Level: advanced Notes: The is entries should be destroyed with ISDestroy(), the is array should be freed with PetscFree() The number of IS on each process will/may be different when redundant arrays are used These could be used to extract a subset of vector entries for a "multi-physics" preconditioner Use DMCompositeGetLocalISs() for index sets that include ghost points .seealso DMCompositeDestroy(), DMCompositeAddArray(), DMCompositeAddDM(), DMCompositeCreateGlobalVector(), DMCompositeGather(), DMCompositeCreate(), DMCompositeGetAccess(), DMCompositeScatter(), DMCompositeGetLocalVectors(), DMCompositeRestoreLocalVectors(),DMCompositeGetEntries() @*/ PetscErrorCode PETSCDM_DLLEXPORT DMCompositeGetGlobalISs(DM dm,IS *is[]) { PetscErrorCode ierr; PetscInt cnt = 0,*idx,i; struct DMCompositeLink *next; PetscMPIInt rank; DM_Composite *com = (DM_Composite*)dm->data; PetscFunctionBegin; PetscValidHeaderSpecific(dm,DM_CLASSID,1); ierr = PetscMalloc(com->nmine*sizeof(IS),is);CHKERRQ(ierr); next = com->next; ierr = MPI_Comm_rank(((PetscObject)dm)->comm,&rank);CHKERRQ(ierr); /* loop over packed objects, handling one at at time */ while (next) { if (next->type == DMCOMPOSITE_ARRAY) { if (rank == next->rank) { ierr = PetscMalloc(next->n*sizeof(PetscInt),&idx);CHKERRQ(ierr); for (i=0; in; i++) idx[i] = next->grstart + i; ierr = ISCreateGeneral(((PetscObject)dm)->comm,next->n,idx,PETSC_OWN_POINTER,&(*is)[cnt]);CHKERRQ(ierr); cnt++; } } else if (next->type == DMCOMPOSITE_DM) { ierr = PetscMalloc(next->n*sizeof(PetscInt),&idx);CHKERRQ(ierr); for (i=0; in; i++) idx[i] = next->grstart + i; ierr = ISCreateGeneral(((PetscObject)dm)->comm,next->n,idx,PETSC_OWN_POINTER,&(*is)[cnt]);CHKERRQ(ierr); cnt++; } else { SETERRQ(((PetscObject)dm)->comm,PETSC_ERR_SUP,"Cannot handle that object type yet"); } next = next->next; } PetscFunctionReturn(0); } /* -------------------------------------------------------------------------------------*/ #undef __FUNCT__ #define __FUNCT__ "DMCompositeGetLocalVectors_Array" PetscErrorCode DMCompositeGetLocalVectors_Array(DM dm,struct DMCompositeLink *mine,PetscScalar **array) { PetscErrorCode ierr; PetscFunctionBegin; if (array) { ierr = PetscMalloc(mine->n*sizeof(PetscScalar),array);CHKERRQ(ierr); } PetscFunctionReturn(0); } #undef __FUNCT__ #define __FUNCT__ "DMCompositeGetLocalVectors_DM" PetscErrorCode DMCompositeGetLocalVectors_DM(DM dm,struct DMCompositeLink *mine,Vec *local) { PetscErrorCode ierr; PetscFunctionBegin; if (local) { ierr = DMGetLocalVector(mine->dm,local);CHKERRQ(ierr); } PetscFunctionReturn(0); } #undef __FUNCT__ #define __FUNCT__ "DMCompositeRestoreLocalVectors_Array" PetscErrorCode DMCompositeRestoreLocalVectors_Array(DM dm,struct DMCompositeLink *mine,PetscScalar **array) { PetscErrorCode ierr; PetscFunctionBegin; if (array) { ierr = PetscFree(*array);CHKERRQ(ierr); } PetscFunctionReturn(0); } #undef __FUNCT__ #define __FUNCT__ "DMCompositeRestoreLocalVectors_DM" PetscErrorCode DMCompositeRestoreLocalVectors_DM(DM dm,struct DMCompositeLink *mine,Vec *local) { PetscErrorCode ierr; PetscFunctionBegin; if (local) { ierr = DMRestoreLocalVector(mine->dm,local);CHKERRQ(ierr); } PetscFunctionReturn(0); } #undef __FUNCT__ #define __FUNCT__ "DMCompositeGetLocalVectors" /*@C DMCompositeGetLocalVectors - Gets local vectors and arrays for each part of a DMComposite. Use DMCompositeRestoreLocalVectors() to return them. Not Collective Input Parameter: . dm - the packer object Output Parameter: . ... - the individual sequential objects (arrays or vectors) Level: advanced .seealso DMCompositeDestroy(), DMCompositeAddArray(), DMCompositeAddDM(), DMCompositeCreateGlobalVector(), DMCompositeGather(), DMCompositeCreate(), DMCompositeGetGlobalIndices(), DMCompositeGetAccess(), DMCompositeRestoreLocalVectors(), DMCompositeScatter(), DMCompositeGetEntries() @*/ PetscErrorCode PETSCDM_DLLEXPORT DMCompositeGetLocalVectors(DM dm,...) { va_list Argp; PetscErrorCode ierr; struct DMCompositeLink *next; DM_Composite *com = (DM_Composite*)dm->data; PetscFunctionBegin; PetscValidHeaderSpecific(dm,DM_CLASSID,1); next = com->next; /* loop over packed objects, handling one at at time */ va_start(Argp,dm); while (next) { if (next->type == DMCOMPOSITE_ARRAY) { PetscScalar **array; array = va_arg(Argp, PetscScalar**); ierr = DMCompositeGetLocalVectors_Array(dm,next,array);CHKERRQ(ierr); } else if (next->type == DMCOMPOSITE_DM) { Vec *vec; vec = va_arg(Argp, Vec*); ierr = DMCompositeGetLocalVectors_DM(dm,next,vec);CHKERRQ(ierr); } else { SETERRQ(((PetscObject)dm)->comm,PETSC_ERR_SUP,"Cannot handle that object type yet"); } next = next->next; } va_end(Argp); PetscFunctionReturn(0); } #undef __FUNCT__ #define __FUNCT__ "DMCompositeRestoreLocalVectors" /*@C DMCompositeRestoreLocalVectors - Restores local vectors and arrays for each part of a DMComposite. Not Collective Input Parameter: . dm - the packer object Output Parameter: . ... - the individual sequential objects (arrays or vectors) Level: advanced .seealso DMCompositeDestroy(), DMCompositeAddArray(), DMCompositeAddDM(), DMCompositeCreateGlobalVector(), DMCompositeGather(), DMCompositeCreate(), DMCompositeGetGlobalIndices(), DMCompositeGetAccess(), DMCompositeGetLocalVectors(), DMCompositeScatter(), DMCompositeGetEntries() @*/ PetscErrorCode PETSCDM_DLLEXPORT DMCompositeRestoreLocalVectors(DM dm,...) { va_list Argp; PetscErrorCode ierr; struct DMCompositeLink *next; DM_Composite *com = (DM_Composite*)dm->data; PetscFunctionBegin; PetscValidHeaderSpecific(dm,DM_CLASSID,1); next = com->next; /* loop over packed objects, handling one at at time */ va_start(Argp,dm); while (next) { if (next->type == DMCOMPOSITE_ARRAY) { PetscScalar **array; array = va_arg(Argp, PetscScalar**); ierr = DMCompositeRestoreLocalVectors_Array(dm,next,array);CHKERRQ(ierr); } else if (next->type == DMCOMPOSITE_DM) { Vec *vec; vec = va_arg(Argp, Vec*); ierr = DMCompositeRestoreLocalVectors_DM(dm,next,vec);CHKERRQ(ierr); } else { SETERRQ(((PetscObject)dm)->comm,PETSC_ERR_SUP,"Cannot handle that object type yet"); } next = next->next; } va_end(Argp); PetscFunctionReturn(0); } /* -------------------------------------------------------------------------------------*/ #undef __FUNCT__ #define __FUNCT__ "DMCompositeGetEntries_Array" PetscErrorCode DMCompositeGetEntries_Array(DM dm,struct DMCompositeLink *mine,PetscInt *n) { PetscFunctionBegin; if (n) *n = mine->n; PetscFunctionReturn(0); } #undef __FUNCT__ #define __FUNCT__ "DMCompositeGetEntries_DM" PetscErrorCode DMCompositeGetEntries_DM(DM dmi,struct DMCompositeLink *mine,DM *dm) { PetscFunctionBegin; if (dm) *dm = mine->dm; PetscFunctionReturn(0); } #undef __FUNCT__ #define __FUNCT__ "DMCompositeGetEntries" /*@C DMCompositeGetEntries - Gets the DA, redundant size, etc for each entry in a DMComposite. Not Collective Input Parameter: . dm - the packer object Output Parameter: . ... - the individual entries, DAs or integer sizes) Level: advanced .seealso DMCompositeDestroy(), DMCompositeAddArray(), DMCompositeAddDM(), DMCompositeCreateGlobalVector(), DMCompositeGather(), DMCompositeCreate(), DMCompositeGetGlobalIndices(), DMCompositeGetAccess(), DMCompositeRestoreLocalVectors(), DMCompositeGetLocalVectors(), DMCompositeScatter(), DMCompositeGetLocalVectors(), DMCompositeRestoreLocalVectors() @*/ PetscErrorCode PETSCDM_DLLEXPORT DMCompositeGetEntries(DM dm,...) { va_list Argp; PetscErrorCode ierr; struct DMCompositeLink *next; DM_Composite *com = (DM_Composite*)dm->data; PetscFunctionBegin; PetscValidHeaderSpecific(dm,DM_CLASSID,1); next = com->next; /* loop over packed objects, handling one at at time */ va_start(Argp,dm); while (next) { if (next->type == DMCOMPOSITE_ARRAY) { PetscInt *n; n = va_arg(Argp, PetscInt*); ierr = DMCompositeGetEntries_Array(dm,next,n);CHKERRQ(ierr); } else if (next->type == DMCOMPOSITE_DM) { DM *dmn; dmn = va_arg(Argp, DM*); ierr = DMCompositeGetEntries_DM(dm,next,dmn);CHKERRQ(ierr); } else { SETERRQ(((PetscObject)dm)->comm,PETSC_ERR_SUP,"Cannot handle that object type yet"); } next = next->next; } va_end(Argp); PetscFunctionReturn(0); } #undef __FUNCT__ #define __FUNCT__ "DMCompositeRefine" /*@C DMCompositeRefine - Refines a DM by refining all of its DAs Collective on DMComposite Input Parameters: + dm - the packer object - comm - communicator to contain the new DM object, usually PETSC_NULL Output Parameter: . fine - new packer Level: advanced .seealso DMCompositeDestroy(), DMCompositeAddArray(), DMCompositeAddDM(), DMCompositeCreateGlobalVector(), DMCompositeGather(), DMCompositeCreate(), DMCompositeGetGlobalIndices(), DMCompositeGetAccess(), DMCompositeGetLocalVectors(), DMCompositeRestoreLocalVectors(), DMCompositeScatter(), DMCompositeGetEntries() @*/ PetscErrorCode PETSCDM_DLLEXPORT DMCompositeRefine(DM dmi,MPI_Comm comm,DM *fine) { PetscErrorCode ierr; struct DMCompositeLink *next; DM_Composite *com = (DM_Composite*)dmi->data; DM dm; PetscFunctionBegin; PetscValidHeaderSpecific(dmi,DM_CLASSID,1); next = com->next; ierr = DMCompositeCreate(comm,fine);CHKERRQ(ierr); /* loop over packed objects, handling one at at time */ while (next) { if (next->type == DMCOMPOSITE_ARRAY) { ierr = DMCompositeAddArray(*fine,next->rank,next->n);CHKERRQ(ierr); } else if (next->type == DMCOMPOSITE_DM) { ierr = DMRefine(next->dm,comm,&dm);CHKERRQ(ierr); ierr = DMCompositeAddDM(*fine,dm);CHKERRQ(ierr); ierr = PetscObjectDereference((PetscObject)dm);CHKERRQ(ierr); } else { SETERRQ(((PetscObject)dm)->comm,PETSC_ERR_SUP,"Cannot handle that object type yet"); } next = next->next; } PetscFunctionReturn(0); } #include "petscmat.h" struct MatPackLink { Mat A; struct MatPackLink *next; }; struct MatPack { DM right,left; struct MatPackLink *next; }; #undef __FUNCT__ #define __FUNCT__ "MatMultBoth_Shell_Pack" PetscErrorCode MatMultBoth_Shell_Pack(Mat A,Vec x,Vec y,PetscBool add) { struct MatPack *mpack; struct DMCompositeLink *xnext,*ynext; struct MatPackLink *anext; PetscScalar *xarray,*yarray; PetscErrorCode ierr; PetscInt i; Vec xglobal,yglobal; PetscMPIInt rank; DM_Composite *comright; DM_Composite *comleft; PetscFunctionBegin; ierr = MatShellGetContext(A,(void**)&mpack);CHKERRQ(ierr); ierr = MPI_Comm_rank(((PetscObject)mpack->right)->comm,&rank);CHKERRQ(ierr); comright = (DM_Composite*)mpack->right->data; comleft = (DM_Composite*)mpack->left->data; xnext = comright->next; ynext = comleft->next; anext = mpack->next; while (xnext) { if (xnext->type == DMCOMPOSITE_ARRAY) { if (rank == xnext->rank) { ierr = VecGetArray(x,&xarray);CHKERRQ(ierr); ierr = VecGetArray(y,&yarray);CHKERRQ(ierr); if (add) { for (i=0; in; i++) { yarray[ynext->rstart+i] += xarray[xnext->rstart+i]; } } else { ierr = PetscMemcpy(yarray+ynext->rstart,xarray+xnext->rstart,xnext->n*sizeof(PetscScalar));CHKERRQ(ierr); } ierr = VecRestoreArray(x,&xarray);CHKERRQ(ierr); ierr = VecRestoreArray(y,&yarray);CHKERRQ(ierr); } } else if (xnext->type == DMCOMPOSITE_DM) { ierr = VecGetArray(x,&xarray);CHKERRQ(ierr); ierr = VecGetArray(y,&yarray);CHKERRQ(ierr); ierr = DMGetGlobalVector(xnext->dm,&xglobal);CHKERRQ(ierr); ierr = DMGetGlobalVector(ynext->dm,&yglobal);CHKERRQ(ierr); ierr = VecPlaceArray(xglobal,xarray+xnext->rstart);CHKERRQ(ierr); ierr = VecPlaceArray(yglobal,yarray+ynext->rstart);CHKERRQ(ierr); if (add) { ierr = MatMultAdd(anext->A,xglobal,yglobal,yglobal);CHKERRQ(ierr); } else { ierr = MatMult(anext->A,xglobal,yglobal);CHKERRQ(ierr); } ierr = VecRestoreArray(x,&xarray);CHKERRQ(ierr); ierr = VecRestoreArray(y,&yarray);CHKERRQ(ierr); ierr = VecResetArray(xglobal);CHKERRQ(ierr); ierr = VecResetArray(yglobal);CHKERRQ(ierr); ierr = DMRestoreGlobalVector(xnext->dm,&xglobal);CHKERRQ(ierr); ierr = DMRestoreGlobalVector(ynext->dm,&yglobal);CHKERRQ(ierr); anext = anext->next; } else { SETERRQ(((PetscObject)A)->comm,PETSC_ERR_SUP,"Cannot handle that object type yet"); } xnext = xnext->next; ynext = ynext->next; } PetscFunctionReturn(0); } #undef __FUNCT__ #define __FUNCT__ "MatMultAdd_Shell_Pack" PetscErrorCode MatMultAdd_Shell_Pack(Mat A,Vec x,Vec y,Vec z) { PetscErrorCode ierr; PetscFunctionBegin; if (z != y) SETERRQ(((PetscObject)A)->comm,PETSC_ERR_SUP,"Handles y == z only"); ierr = MatMultBoth_Shell_Pack(A,x,y,PETSC_TRUE);CHKERRQ(ierr); PetscFunctionReturn(0); } #undef __FUNCT__ #define __FUNCT__ "MatMult_Shell_Pack" PetscErrorCode MatMult_Shell_Pack(Mat A,Vec x,Vec y) { PetscErrorCode ierr; PetscFunctionBegin; ierr = MatMultBoth_Shell_Pack(A,x,y,PETSC_FALSE);CHKERRQ(ierr); PetscFunctionReturn(0); } #undef __FUNCT__ #define __FUNCT__ "MatMultTranspose_Shell_Pack" PetscErrorCode MatMultTranspose_Shell_Pack(Mat A,Vec x,Vec y) { struct MatPack *mpack; struct DMCompositeLink *xnext,*ynext; struct MatPackLink *anext; PetscScalar *xarray,*yarray; PetscErrorCode ierr; Vec xglobal,yglobal; PetscMPIInt rank; DM_Composite *comright; DM_Composite *comleft; PetscFunctionBegin; ierr = MatShellGetContext(A,(void**)&mpack);CHKERRQ(ierr); ierr = MPI_Comm_rank(((PetscObject)mpack->right)->comm,&rank);CHKERRQ(ierr); comright = (DM_Composite*)mpack->right->data; comleft = (DM_Composite*)mpack->left->data; ynext = comright->next; xnext = comleft->next; anext = mpack->next; while (xnext) { if (xnext->type == DMCOMPOSITE_ARRAY) { if (rank == ynext->rank) { ierr = VecGetArray(x,&xarray);CHKERRQ(ierr); ierr = VecGetArray(y,&yarray);CHKERRQ(ierr); ierr = PetscMemcpy(yarray+ynext->rstart,xarray+xnext->rstart,xnext->n*sizeof(PetscScalar));CHKERRQ(ierr); ierr = VecRestoreArray(x,&xarray);CHKERRQ(ierr); ierr = VecRestoreArray(y,&yarray);CHKERRQ(ierr); } } else if (xnext->type == DMCOMPOSITE_DM) { ierr = VecGetArray(x,&xarray);CHKERRQ(ierr); ierr = VecGetArray(y,&yarray);CHKERRQ(ierr); ierr = DMGetGlobalVector(xnext->dm,&xglobal);CHKERRQ(ierr); ierr = DMGetGlobalVector(ynext->dm,&yglobal);CHKERRQ(ierr); ierr = VecPlaceArray(xglobal,xarray+xnext->rstart);CHKERRQ(ierr); ierr = VecPlaceArray(yglobal,yarray+ynext->rstart);CHKERRQ(ierr); ierr = MatMultTranspose(anext->A,xglobal,yglobal);CHKERRQ(ierr); ierr = VecRestoreArray(x,&xarray);CHKERRQ(ierr); ierr = VecRestoreArray(y,&yarray);CHKERRQ(ierr); ierr = VecResetArray(xglobal);CHKERRQ(ierr); ierr = VecResetArray(yglobal);CHKERRQ(ierr); ierr = DMRestoreGlobalVector(xnext->dm,&xglobal);CHKERRQ(ierr); ierr = DMRestoreGlobalVector(ynext->dm,&yglobal);CHKERRQ(ierr); anext = anext->next; } else { SETERRQ(((PetscObject)A)->comm,PETSC_ERR_SUP,"Cannot handle that object type yet"); } xnext = xnext->next; ynext = ynext->next; } PetscFunctionReturn(0); } #undef __FUNCT__ #define __FUNCT__ "MatDestroy_Shell_Pack" PetscErrorCode MatDestroy_Shell_Pack(Mat A) { struct MatPack *mpack; struct MatPackLink *anext,*oldanext; PetscErrorCode ierr; PetscFunctionBegin; ierr = MatShellGetContext(A,(void**)&mpack);CHKERRQ(ierr); anext = mpack->next; while (anext) { ierr = MatDestroy(anext->A);CHKERRQ(ierr); oldanext = anext; anext = anext->next; ierr = PetscFree(oldanext);CHKERRQ(ierr); } ierr = PetscFree(mpack);CHKERRQ(ierr); ierr = PetscObjectChangeTypeName((PetscObject)A,0);CHKERRQ(ierr); PetscFunctionReturn(0); } #undef __FUNCT__ #define __FUNCT__ "DMCompositeGetInterpolation" /*@C DMCompositeGetInterpolation - GetInterpolations a DM by refining all of its DAs Collective on DMComposite Input Parameters: + coarse - coarse grid packer - fine - fine grid packer Output Parameter: + A - interpolation matrix - v - scaling vector Level: advanced .seealso DMCompositeDestroy(), DMCompositeAddArray(), DMCompositeAddDM(), DMCompositeCreateGlobalVector(), DMCompositeGather(), DMCompositeCreate(), DMCompositeGetGlobalIndices(), DMCompositeGetAccess(), DMCompositeGetLocalVectors(), DMCompositeRestoreLocalVectors(), DMCompositeScatter(),DMCompositeGetEntries() @*/ PetscErrorCode PETSCDM_DLLEXPORT DMCompositeGetInterpolation(DM coarse,DM fine,Mat *A,Vec *v) { PetscErrorCode ierr; PetscInt m,n,M,N; struct DMCompositeLink *nextc; struct DMCompositeLink *nextf; struct MatPackLink *nextmat,*pnextmat = 0; struct MatPack *mpack; Vec gcoarse,gfine; DM_Composite *comcoarse = (DM_Composite*)coarse->data; DM_Composite *comfine = (DM_Composite*)fine->data; PetscFunctionBegin; PetscValidHeaderSpecific(coarse,DM_CLASSID,1); PetscValidHeaderSpecific(fine,DM_CLASSID,2); nextc = comcoarse->next; nextf = comfine->next; /* use global vectors only for determining matrix layout */ ierr = DMCompositeCreateGlobalVector(coarse,&gcoarse);CHKERRQ(ierr); ierr = DMCompositeCreateGlobalVector(fine,&gfine);CHKERRQ(ierr); ierr = VecGetLocalSize(gcoarse,&n);CHKERRQ(ierr); ierr = VecGetLocalSize(gfine,&m);CHKERRQ(ierr); ierr = VecGetSize(gcoarse,&N);CHKERRQ(ierr); ierr = VecGetSize(gfine,&M);CHKERRQ(ierr); ierr = VecDestroy(gcoarse);CHKERRQ(ierr); ierr = VecDestroy(gfine);CHKERRQ(ierr); ierr = PetscNew(struct MatPack,&mpack);CHKERRQ(ierr); mpack->right = coarse; mpack->left = fine; ierr = MatCreate(((PetscObject)fine)->comm,A);CHKERRQ(ierr); ierr = MatSetSizes(*A,m,n,M,N);CHKERRQ(ierr); ierr = MatSetType(*A,MATSHELL);CHKERRQ(ierr); ierr = MatShellSetContext(*A,mpack);CHKERRQ(ierr); ierr = MatShellSetOperation(*A,MATOP_MULT,(void(*)(void))MatMult_Shell_Pack);CHKERRQ(ierr); ierr = MatShellSetOperation(*A,MATOP_MULT_TRANSPOSE,(void(*)(void))MatMultTranspose_Shell_Pack);CHKERRQ(ierr); ierr = MatShellSetOperation(*A,MATOP_MULT_ADD,(void(*)(void))MatMultAdd_Shell_Pack);CHKERRQ(ierr); ierr = MatShellSetOperation(*A,MATOP_DESTROY,(void(*)(void))MatDestroy_Shell_Pack);CHKERRQ(ierr); /* loop over packed objects, handling one at at time */ while (nextc) { if (nextc->type != nextf->type) SETERRQ(((PetscObject)fine)->comm,PETSC_ERR_ARG_INCOMP,"Two DM have different layout"); if (nextc->type == DMCOMPOSITE_ARRAY) { ; } else if (nextc->type == DMCOMPOSITE_DM) { ierr = PetscNew(struct MatPackLink,&nextmat);CHKERRQ(ierr); nextmat->next = 0; if (pnextmat) { pnextmat->next = nextmat; pnextmat = nextmat; } else { pnextmat = nextmat; mpack->next = nextmat; } ierr = DMGetInterpolation(nextc->dm,nextf->dm,&nextmat->A,PETSC_NULL);CHKERRQ(ierr); } else { SETERRQ(((PetscObject)fine)->comm,PETSC_ERR_SUP,"Cannot handle that object type yet"); } nextc = nextc->next; nextf = nextf->next; } PetscFunctionReturn(0); } #undef __FUNCT__ #define __FUNCT__ "DMCompositeGetMatrix" /*@C DMCompositeGetMatrix - Creates a matrix with the correct parallel layout and nonzero structure required for computing the Jacobian on a function defined using the stencils set in the DA's and coupling in the array variables Collective on DA Input Parameter: + dm - the distributed array - mtype - Supported types are MATSEQAIJ, MATMPIAIJ Output Parameters: . J - matrix with the correct nonzero structure (obviously without the correct Jacobian values) Level: advanced Notes: This properly preallocates the number of nonzeros in the sparse matrix so you do not need to do it yourself. .seealso DAGetMatrix(), DMCompositeCreate() @*/ PetscErrorCode PETSCDM_DLLEXPORT DMCompositeGetMatrix(DM dm, const MatType mtype,Mat *J) { PetscErrorCode ierr; DM_Composite *com = (DM_Composite*)dm->data; struct DMCompositeLink *next = com->next; PetscInt m,*dnz,*onz,i,j,mA; Mat Atmp; PetscMPIInt rank; PetscScalar zero = 0.0; PetscBool dense = PETSC_FALSE; PetscFunctionBegin; PetscValidHeaderSpecific(dm,DM_CLASSID,1); /* use global vector to determine layout needed for matrix */ m = com->n; ierr = MPI_Comm_rank(((PetscObject)dm)->comm,&rank);CHKERRQ(ierr); ierr = MatCreate(((PetscObject)dm)->comm,J);CHKERRQ(ierr); ierr = MatSetSizes(*J,m,m,PETSC_DETERMINE,PETSC_DETERMINE);CHKERRQ(ierr); ierr = MatSetType(*J,MATAIJ);CHKERRQ(ierr); /* Extremely inefficient but will compute entire Jacobian for testing */ ierr = PetscOptionsGetTruth(PETSC_NULL,"-dmcomposite_dense_jacobian",&dense,PETSC_NULL);CHKERRQ(ierr); if (dense) { PetscInt rstart,rend,*indices; PetscScalar *values; mA = com->N; ierr = MatMPIAIJSetPreallocation(*J,mA,PETSC_NULL,mA-m,PETSC_NULL);CHKERRQ(ierr); ierr = MatSeqAIJSetPreallocation(*J,mA,PETSC_NULL);CHKERRQ(ierr); ierr = MatGetOwnershipRange(*J,&rstart,&rend);CHKERRQ(ierr); ierr = PetscMalloc2(mA,PetscScalar,&values,mA,PetscInt,&indices);CHKERRQ(ierr); ierr = PetscMemzero(values,mA*sizeof(PetscScalar));CHKERRQ(ierr); for (i=0; icomm,m,m,dnz,onz);CHKERRQ(ierr); /* loop over packed objects, handling one at at time */ next = com->next; while (next) { if (next->type == DMCOMPOSITE_ARRAY) { if (rank == next->rank) { /* zero the "little" block */ for (j=com->rstart+next->rstart; jrstart+next->rstart+next->n; j++) { for (i=com->rstart+next->rstart; irstart+next->rstart+next->n; i++) { ierr = MatPreallocateSet(j,1,&i,dnz,onz);CHKERRQ(ierr); } } } } else if (next->type == DMCOMPOSITE_DM) { PetscInt nc,rstart,*ccols,maxnc; const PetscInt *cols,*rstarts; PetscMPIInt proc; ierr = DMGetMatrix(next->dm,mtype,&Atmp);CHKERRQ(ierr); ierr = MatGetOwnershipRange(Atmp,&rstart,PETSC_NULL);CHKERRQ(ierr); ierr = MatGetOwnershipRanges(Atmp,&rstarts);CHKERRQ(ierr); ierr = MatGetLocalSize(Atmp,&mA,PETSC_NULL);CHKERRQ(ierr); maxnc = 0; for (i=0; i= rstarts[proc+1]) proc++; ccols[j] = cols[j] + next->grstarts[proc] - rstarts[proc]; } ierr = MatPreallocateSet(com->rstart+next->rstart+i,nc,ccols,dnz,onz);CHKERRQ(ierr); ierr = MatRestoreRow(Atmp,rstart+i,&nc,&cols,PETSC_NULL);CHKERRQ(ierr); } ierr = PetscFree(ccols);CHKERRQ(ierr); ierr = MatDestroy(Atmp);CHKERRQ(ierr); } else { SETERRQ(((PetscObject)dm)->comm,PETSC_ERR_SUP,"Cannot handle that object type yet"); } next = next->next; } if (com->FormCoupleLocations) { ierr = (*com->FormCoupleLocations)(dm,PETSC_NULL,dnz,onz,__rstart,__nrows,__start,__end);CHKERRQ(ierr); } ierr = MatMPIAIJSetPreallocation(*J,0,dnz,0,onz);CHKERRQ(ierr); ierr = MatSeqAIJSetPreallocation(*J,0,dnz);CHKERRQ(ierr); ierr = MatPreallocateFinalize(dnz,onz);CHKERRQ(ierr); next = com->next; while (next) { if (next->type == DMCOMPOSITE_ARRAY) { if (rank == next->rank) { for (j=com->rstart+next->rstart; jrstart+next->rstart+next->n; j++) { for (i=com->rstart+next->rstart; irstart+next->rstart+next->n; i++) { ierr = MatSetValues(*J,1,&j,1,&i,&zero,INSERT_VALUES);CHKERRQ(ierr); } } } } else if (next->type == DMCOMPOSITE_DM) { PetscInt nc,rstart,row,maxnc,*ccols; const PetscInt *cols,*rstarts; const PetscScalar *values; PetscMPIInt proc; ierr = DMGetMatrix(next->dm,mtype,&Atmp);CHKERRQ(ierr); ierr = MatGetOwnershipRange(Atmp,&rstart,PETSC_NULL);CHKERRQ(ierr); ierr = MatGetOwnershipRanges(Atmp,&rstarts);CHKERRQ(ierr); ierr = MatGetLocalSize(Atmp,&mA,PETSC_NULL);CHKERRQ(ierr); maxnc = 0; for (i=0; i= rstarts[proc+1]) proc++; ccols[j] = cols[j] + next->grstarts[proc] - rstarts[proc]; } row = com->rstart+next->rstart+i; ierr = MatSetValues(*J,1,&row,nc,ccols,values,INSERT_VALUES);CHKERRQ(ierr); ierr = MatRestoreRow(Atmp,rstart+i,&nc,(const PetscInt **)&cols,&values);CHKERRQ(ierr); } ierr = PetscFree(ccols);CHKERRQ(ierr); ierr = MatDestroy(Atmp);CHKERRQ(ierr); } else { SETERRQ(((PetscObject)dm)->comm,PETSC_ERR_SUP,"Cannot handle that object type yet"); } next = next->next; } if (com->FormCoupleLocations) { PetscInt __rstart; ierr = MatGetOwnershipRange(*J,&__rstart,PETSC_NULL);CHKERRQ(ierr); ierr = (*com->FormCoupleLocations)(dm,*J,PETSC_NULL,PETSC_NULL,__rstart,0,0,0);CHKERRQ(ierr); } ierr = MatAssemblyBegin(*J,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); ierr = MatAssemblyEnd(*J,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); PetscFunctionReturn(0); } #undef __FUNCT__ #define __FUNCT__ "DMCompositeGetColoring" /*@ DMCompositeGetColoring - Gets the coloring required for computing the Jacobian via finite differences on a function defined using a DM "grid" Collective on DA Input Parameter: + dm - the DM object . ctype - IS_COLORING_GLOBAL or IS_COLORING_GHOSTED - mtype - MATAIJ or MATBAIJ Output Parameters: . coloring - matrix coloring for use in computing Jacobians (or PETSC_NULL if not needed) Level: advanced Notes: This colors each diagonal block (associated with a single DM) with a different set of colors; this it will compute the diagonal blocks of the Jacobian correctly. The off diagonal blocks are not computed, hence the Jacobian computed is not the entire Jacobian. If -dmcomposite_dense_jacobian is used then each column of the Jacobian is given a different color so the full Jacobian is computed correctly. Notes: These compute the graph coloring of the graph of A^{T}A. The coloring used for efficient (parallel or thread based) triangular solves etc is NOT yet available. .seealso ISColoringView(), ISColoringGetIS(), MatFDColoringCreate(), ISColoringType, ISColoring, DAGetColoring() @*/ PetscErrorCode PETSCDM_DLLEXPORT DMCompositeGetColoring(DM dm,ISColoringType ctype,const MatType mtype,ISColoring *coloring) { PetscErrorCode ierr; PetscInt n,i,cnt; ISColoringValue *colors; PetscBool dense = PETSC_FALSE; ISColoringValue maxcol = 0; DM_Composite *com = (DM_Composite*)dm->data; PetscFunctionBegin; PetscValidHeaderSpecific(dm,DM_CLASSID,1); if (ctype == IS_COLORING_GHOSTED) { SETERRQ(((PetscObject)dm)->comm,PETSC_ERR_SUP,"Currently you must use -dmmg_iscoloring_type global" ); } else if (ctype == IS_COLORING_GLOBAL) { n = com->n; } else SETERRQ(((PetscObject)dm)->comm,PETSC_ERR_ARG_OUTOFRANGE,"Unknown ISColoringType"); ierr = PetscMalloc(n*sizeof(ISColoringValue),&colors);CHKERRQ(ierr); /* freed in ISColoringDestroy() */ ierr = PetscOptionsGetTruth(PETSC_NULL,"-dmcomposite_dense_jacobian",&dense,PETSC_NULL);CHKERRQ(ierr); if (dense) { for (i=0; irstart + i); } maxcol = com->N; } else { struct DMCompositeLink *next = com->next; PetscMPIInt rank; ierr = MPI_Comm_rank(((PetscObject)dm)->comm,&rank);CHKERRQ(ierr); cnt = 0; while (next) { if (next->type == DMCOMPOSITE_ARRAY) { if (rank == next->rank) { /* each column gets is own color */ for (i=com->rstart+next->rstart; irstart+next->rstart+next->n; i++) { colors[cnt++] = maxcol++; } } ierr = MPI_Bcast(&maxcol,1,MPIU_COLORING_VALUE,next->rank,((PetscObject)dm)->comm);CHKERRQ(ierr); } else if (next->type == DMCOMPOSITE_DM) { ISColoring lcoloring; ierr = DMGetColoring(next->dm,IS_COLORING_GLOBAL,mtype,&lcoloring);CHKERRQ(ierr); for (i=0; iN; i++) { colors[cnt++] = maxcol + lcoloring->colors[i]; } maxcol += lcoloring->n; ierr = ISColoringDestroy(lcoloring);CHKERRQ(ierr); } else { SETERRQ(((PetscObject)dm)->comm,PETSC_ERR_SUP,"Cannot handle that object type yet"); } next = next->next; } } ierr = ISColoringCreate(((PetscObject)dm)->comm,maxcol,n,colors,coloring);CHKERRQ(ierr); PetscFunctionReturn(0); } #undef __FUNCT__ #define __FUNCT__ "DMCompositeGlobalToLocalBegin" /*@C DMCompositeGlobalToLocalBegin - begin update of single local vector from global vector Neighbor-wise Collective on DMComposite Input Parameter: + dm - the packer object . gvec - the global vector - lvec - single local vector Level: advanced .seealso DMCompositeDestroy(), DMCompositeAddArray(), DMCompositeAddDM(), DMCompositeCreateGlobalVector(), DMCompositeGather(), DMCompositeCreate(), DMCompositeGetGlobalIndices(), DMCompositeGetAccess(), DMCompositeGetLocalVectors(), DMCompositeRestoreLocalVectors(), DMCompositeGetEntries() @*/ PetscErrorCode PETSCDM_DLLEXPORT DMCompositeGlobalToLocalBegin(DM dm,Vec gvec,InsertMode mode,Vec lvec) { PetscErrorCode ierr; struct DMCompositeLink *next; PetscInt cnt = 3; PetscMPIInt rank; PetscScalar *garray,*larray; DM_Composite *com = (DM_Composite*)dm->data; PetscFunctionBegin; PetscValidHeaderSpecific(dm,DM_CLASSID,1); PetscValidHeaderSpecific(gvec,VEC_CLASSID,2); next = com->next; if (!com->setup) { ierr = DMCompositeSetUp(dm);CHKERRQ(ierr); } ierr = MPI_Comm_rank(((PetscObject)dm)->comm,&rank);CHKERRQ(ierr); ierr = VecGetArray(gvec,&garray);CHKERRQ(ierr); ierr = VecGetArray(lvec,&larray);CHKERRQ(ierr); /* loop over packed objects, handling one at at time */ while (next) { if (next->type == DMCOMPOSITE_ARRAY) { if (rank == next->rank) { ierr = PetscMemcpy(larray,garray,next->n*sizeof(PetscScalar));CHKERRQ(ierr); garray += next->n; } /* does not handle ADD_VALUES */ ierr = MPI_Bcast(larray,next->n,MPIU_SCALAR,next->rank,((PetscObject)dm)->comm);CHKERRQ(ierr); larray += next->n; } else if (next->type == DMCOMPOSITE_DM) { Vec local,global; PetscInt N; ierr = DMGetGlobalVector(next->dm,&global);CHKERRQ(ierr); ierr = VecGetLocalSize(global,&N);CHKERRQ(ierr); ierr = VecPlaceArray(global,garray);CHKERRQ(ierr); ierr = DMGetLocalVector(next->dm,&local);CHKERRQ(ierr); ierr = VecPlaceArray(local,larray);CHKERRQ(ierr); ierr = DMGlobalToLocalBegin(next->dm,global,mode,local);CHKERRQ(ierr); ierr = DMGlobalToLocalEnd(next->dm,global,mode,local);CHKERRQ(ierr); ierr = VecResetArray(global);CHKERRQ(ierr); ierr = VecResetArray(local);CHKERRQ(ierr); ierr = DMRestoreGlobalVector(next->dm,&global);CHKERRQ(ierr); ierr = DMRestoreGlobalVector(next->dm,&local);CHKERRQ(ierr); larray += next->n; } else { SETERRQ(((PetscObject)dm)->comm,PETSC_ERR_SUP,"Cannot handle that object type yet"); } cnt++; next = next->next; } ierr = VecRestoreArray(gvec,PETSC_NULL);CHKERRQ(ierr); ierr = VecRestoreArray(lvec,PETSC_NULL);CHKERRQ(ierr); PetscFunctionReturn(0); } #undef __FUNCT__ #define __FUNCT__ "DMCompositeGlobalToLocalEnd" /*@C DMCompositeGlobalToLocalEnd - All communication is handled in the Begin phase Neighbor-wise Collective on DMComposite Input Parameter: + dm - the packer object . gvec - the global vector - lvec - single local vector Level: advanced .seealso DMCompositeDestroy(), DMCompositeAddArray(), DMCompositeAddDM(), DMCompositeCreateGlobalVector(), DMCompositeGather(), DMCompositeCreate(), DMCompositeGetGlobalIndices(), DMCompositeGetAccess(), DMCompositeGetLocalVectors(), DMCompositeRestoreLocalVectors(), DMCompositeGetEntries() @*/ PetscErrorCode PETSCDM_DLLEXPORT DMCompositeGlobalToLocalEnd(DM dm,Vec gvec,InsertMode mode,Vec lvec) { PetscFunctionBegin; PetscFunctionReturn(0); }