#include /*I "petscis.h" I*/ #include #include PetscClassId IS_LTOGM_CLASSID; static PetscErrorCode ISLocalToGlobalMappingGetBlockInfo_Private(ISLocalToGlobalMapping,PetscInt*,PetscInt**,PetscInt**,PetscInt***); #undef __FUNCT__ #define __FUNCT__ "ISG2LMapApply" PetscErrorCode ISG2LMapApply(ISLocalToGlobalMapping mapping,PetscInt n,const PetscInt in[],PetscInt out[]) { PetscErrorCode ierr; PetscInt i,start,end; PetscFunctionBegin; if (!mapping->globals) { ierr = ISGlobalToLocalMappingApply(mapping,IS_GTOLM_MASK,0,0,0,0);CHKERRQ(ierr); } start = mapping->globalstart; end = mapping->globalend; for (i=0; i end) out[i] = -1; else out[i] = mapping->globals[in[i] - start]; } PetscFunctionReturn(0); } #undef __FUNCT__ #define __FUNCT__ "ISLocalToGlobalMappingGetSize" /*@ ISLocalToGlobalMappingGetSize - Gets the local size of a local to global mapping Not Collective Input Parameter: . ltog - local to global mapping Output Parameter: . n - the number of entries in the local mapping, ISLocalToGlobalMappingGetIndices() returns an array of this length Level: advanced Concepts: mapping^local to global .seealso: ISLocalToGlobalMappingDestroy(), ISLocalToGlobalMappingCreate() @*/ PetscErrorCode ISLocalToGlobalMappingGetSize(ISLocalToGlobalMapping mapping,PetscInt *n) { PetscFunctionBegin; PetscValidHeaderSpecific(mapping,IS_LTOGM_CLASSID,1); PetscValidIntPointer(n,2); *n = mapping->bs*mapping->n; PetscFunctionReturn(0); } #undef __FUNCT__ #define __FUNCT__ "ISLocalToGlobalMappingView" /*@C ISLocalToGlobalMappingView - View a local to global mapping Not Collective Input Parameters: + ltog - local to global mapping - viewer - viewer Level: advanced Concepts: mapping^local to global .seealso: ISLocalToGlobalMappingDestroy(), ISLocalToGlobalMappingCreate() @*/ PetscErrorCode ISLocalToGlobalMappingView(ISLocalToGlobalMapping mapping,PetscViewer viewer) { PetscInt i; PetscMPIInt rank; PetscBool iascii; PetscErrorCode ierr; PetscFunctionBegin; PetscValidHeaderSpecific(mapping,IS_LTOGM_CLASSID,1); if (!viewer) { ierr = PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)mapping),&viewer);CHKERRQ(ierr); } PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,2); ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)mapping),&rank);CHKERRQ(ierr); ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr); if (iascii) { ierr = PetscObjectPrintClassNamePrefixType((PetscObject)mapping,viewer);CHKERRQ(ierr); ierr = PetscViewerASCIIPushSynchronized(viewer);CHKERRQ(ierr); for (i=0; in; i++) { ierr = PetscViewerASCIISynchronizedPrintf(viewer,"[%d] %D %D\n",rank,i,mapping->indices[i]);CHKERRQ(ierr); } ierr = PetscViewerFlush(viewer);CHKERRQ(ierr); ierr = PetscViewerASCIIPopSynchronized(viewer);CHKERRQ(ierr); } PetscFunctionReturn(0); } #undef __FUNCT__ #define __FUNCT__ "ISLocalToGlobalMappingCreateIS" /*@ ISLocalToGlobalMappingCreateIS - Creates a mapping between a local (0 to n) ordering and a global parallel ordering. Not collective Input Parameter: . is - index set containing the global numbers for each local number Output Parameter: . mapping - new mapping data structure Notes: the block size of the IS determines the block size of the mapping Level: advanced Concepts: mapping^local to global .seealso: ISLocalToGlobalMappingDestroy(), ISLocalToGlobalMappingCreate() @*/ PetscErrorCode ISLocalToGlobalMappingCreateIS(IS is,ISLocalToGlobalMapping *mapping) { PetscErrorCode ierr; PetscInt n,bs; const PetscInt *indices; MPI_Comm comm; PetscBool isblock; PetscFunctionBegin; PetscValidHeaderSpecific(is,IS_CLASSID,1); PetscValidPointer(mapping,2); ierr = PetscObjectGetComm((PetscObject)is,&comm);CHKERRQ(ierr); ierr = ISGetLocalSize(is,&n);CHKERRQ(ierr); ierr = PetscObjectTypeCompare((PetscObject)is,ISBLOCK,&isblock);CHKERRQ(ierr); if (!isblock) { ierr = ISGetIndices(is,&indices);CHKERRQ(ierr); ierr = ISLocalToGlobalMappingCreate(comm,1,n,indices,PETSC_COPY_VALUES,mapping);CHKERRQ(ierr); ierr = ISRestoreIndices(is,&indices);CHKERRQ(ierr); } else { ierr = ISGetBlockSize(is,&bs);CHKERRQ(ierr); ierr = ISBlockGetIndices(is,&indices);CHKERRQ(ierr); ierr = ISLocalToGlobalMappingCreate(comm,bs,n/bs,indices,PETSC_COPY_VALUES,mapping);CHKERRQ(ierr); ierr = ISBlockRestoreIndices(is,&indices);CHKERRQ(ierr); } PetscFunctionReturn(0); } #undef __FUNCT__ #define __FUNCT__ "ISLocalToGlobalMappingCreateSF" /*@C ISLocalToGlobalMappingCreateSF - Creates a mapping between a local (0 to n) ordering and a global parallel ordering. Collective Input Parameter: + sf - star forest mapping contiguous local indices to (rank, offset) - start - first global index on this process Output Parameter: . mapping - new mapping data structure Level: advanced Concepts: mapping^local to global .seealso: ISLocalToGlobalMappingDestroy(), ISLocalToGlobalMappingCreate(), ISLocalToGlobalMappingCreateIS() @*/ PetscErrorCode ISLocalToGlobalMappingCreateSF(PetscSF sf,PetscInt start,ISLocalToGlobalMapping *mapping) { PetscErrorCode ierr; PetscInt i,maxlocal,nroots,nleaves,*globals,*ltog; const PetscInt *ilocal; MPI_Comm comm; PetscFunctionBegin; PetscValidHeaderSpecific(sf,PETSCSF_CLASSID,1); PetscValidPointer(mapping,3); ierr = PetscObjectGetComm((PetscObject)sf,&comm);CHKERRQ(ierr); ierr = PetscSFGetGraph(sf,&nroots,&nleaves,&ilocal,NULL);CHKERRQ(ierr); if (ilocal) { for (i=0,maxlocal=0; ibs; PetscFunctionReturn(0); } #undef __FUNCT__ #define __FUNCT__ "ISLocalToGlobalMappingCreate" /*@ ISLocalToGlobalMappingCreate - Creates a mapping between a local (0 to n) ordering and a global parallel ordering. Not Collective, but communicator may have more than one process Input Parameters: + comm - MPI communicator . bs - the block size . n - the number of local elements divided by the block size, or equivalently the number of block indices . indices - the global index for each local element, these do not need to be in increasing order (sorted), these values should not be scaled (i.e. multiplied) by the blocksize bs - mode - see PetscCopyMode Output Parameter: . mapping - new mapping data structure Notes: There is one integer value in indices per block and it represents the actual indices bs*idx + j, where j=0,..,bs-1 Level: advanced Concepts: mapping^local to global .seealso: ISLocalToGlobalMappingDestroy(), ISLocalToGlobalMappingCreateIS() @*/ PetscErrorCode ISLocalToGlobalMappingCreate(MPI_Comm comm,PetscInt bs,PetscInt n,const PetscInt indices[],PetscCopyMode mode,ISLocalToGlobalMapping *mapping) { PetscErrorCode ierr; PetscInt *in; PetscFunctionBegin; if (n) PetscValidIntPointer(indices,3); PetscValidPointer(mapping,4); *mapping = NULL; ierr = ISInitializePackage();CHKERRQ(ierr); ierr = PetscHeaderCreate(*mapping,IS_LTOGM_CLASSID,"ISLocalToGlobalMapping","Local to global mapping","IS", comm,ISLocalToGlobalMappingDestroy,ISLocalToGlobalMappingView);CHKERRQ(ierr); (*mapping)->n = n; (*mapping)->bs = bs; (*mapping)->info_cached = PETSC_FALSE; (*mapping)->info_free = PETSC_FALSE; (*mapping)->info_procs = NULL; (*mapping)->info_numprocs = NULL; (*mapping)->info_indices = NULL; /* Do not create the global to local mapping. This is only created if ISGlobalToLocalMapping() is called */ (*mapping)->globals = 0; if (mode == PETSC_COPY_VALUES) { ierr = PetscMalloc1(n,&in);CHKERRQ(ierr); ierr = PetscMemcpy(in,indices,n*sizeof(PetscInt));CHKERRQ(ierr); (*mapping)->indices = in; ierr = PetscLogObjectMemory((PetscObject)*mapping,n*sizeof(PetscInt));CHKERRQ(ierr); } else if (mode == PETSC_OWN_POINTER) { (*mapping)->indices = (PetscInt*)indices; ierr = PetscLogObjectMemory((PetscObject)*mapping,n*sizeof(PetscInt));CHKERRQ(ierr); } else SETERRQ(comm,PETSC_ERR_SUP,"Cannot currently use PETSC_USE_POINTER"); ierr = PetscStrallocpy("basic",&((PetscObject)*mapping)->type_name);CHKERRQ(ierr); PetscFunctionReturn(0); } #undef __FUNCT__ #define __FUNCT__ "ISLocalToGlobalMappingDestroy" /*@ ISLocalToGlobalMappingDestroy - Destroys a mapping between a local (0 to n) ordering and a global parallel ordering. Note Collective Input Parameters: . mapping - mapping data structure Level: advanced .seealso: ISLocalToGlobalMappingCreate() @*/ PetscErrorCode ISLocalToGlobalMappingDestroy(ISLocalToGlobalMapping *mapping) { PetscErrorCode ierr; PetscFunctionBegin; if (!*mapping) PetscFunctionReturn(0); PetscValidHeaderSpecific((*mapping),IS_LTOGM_CLASSID,1); if (--((PetscObject)(*mapping))->refct > 0) {*mapping = 0;PetscFunctionReturn(0);} ierr = PetscFree((*mapping)->indices);CHKERRQ(ierr); ierr = PetscFree((*mapping)->globals);CHKERRQ(ierr); ierr = PetscFree((*mapping)->info_procs);CHKERRQ(ierr); ierr = PetscFree((*mapping)->info_numprocs);CHKERRQ(ierr); if ((*mapping)->info_indices) { PetscInt i; ierr = PetscFree(((*mapping)->info_indices)[0]);CHKERRQ(ierr); for (i=1; i<(*mapping)->info_nproc; i++) { ierr = PetscFree(((*mapping)->info_indices)[i]);CHKERRQ(ierr); } ierr = PetscFree((*mapping)->info_indices);CHKERRQ(ierr); } ierr = PetscHeaderDestroy(mapping);CHKERRQ(ierr); *mapping = 0; PetscFunctionReturn(0); } #undef __FUNCT__ #define __FUNCT__ "ISLocalToGlobalMappingApplyIS" /*@ ISLocalToGlobalMappingApplyIS - Creates from an IS in the local numbering a new index set using the global numbering defined in an ISLocalToGlobalMapping context. Not collective Input Parameters: + mapping - mapping between local and global numbering - is - index set in local numbering Output Parameters: . newis - index set in global numbering Level: advanced Concepts: mapping^local to global .seealso: ISLocalToGlobalMappingApply(), ISLocalToGlobalMappingCreate(), ISLocalToGlobalMappingDestroy(), ISGlobalToLocalMappingApply() @*/ PetscErrorCode ISLocalToGlobalMappingApplyIS(ISLocalToGlobalMapping mapping,IS is,IS *newis) { PetscErrorCode ierr; PetscInt n,*idxout; const PetscInt *idxin; PetscFunctionBegin; PetscValidHeaderSpecific(mapping,IS_LTOGM_CLASSID,1); PetscValidHeaderSpecific(is,IS_CLASSID,2); PetscValidPointer(newis,3); ierr = ISGetLocalSize(is,&n);CHKERRQ(ierr); ierr = ISGetIndices(is,&idxin);CHKERRQ(ierr); ierr = PetscMalloc1(n,&idxout);CHKERRQ(ierr); ierr = ISLocalToGlobalMappingApply(mapping,n,idxin,idxout);CHKERRQ(ierr); ierr = ISRestoreIndices(is,&idxin);CHKERRQ(ierr); ierr = ISCreateGeneral(PetscObjectComm((PetscObject)is),n,idxout,PETSC_OWN_POINTER,newis);CHKERRQ(ierr); PetscFunctionReturn(0); } #undef __FUNCT__ #define __FUNCT__ "ISLocalToGlobalMappingApply" /*@ ISLocalToGlobalMappingApply - Takes a list of integers in a local numbering and converts them to the global numbering. Not collective Input Parameters: + mapping - the local to global mapping context . N - number of integers - in - input indices in local numbering Output Parameter: . out - indices in global numbering Notes: The in and out array parameters may be identical. Level: advanced .seealso: ISLocalToGlobalMappingApplyBlock(), ISLocalToGlobalMappingCreate(),ISLocalToGlobalMappingDestroy(), ISLocalToGlobalMappingApplyIS(),AOCreateBasic(),AOApplicationToPetsc(), AOPetscToApplication(), ISGlobalToLocalMappingApply() Concepts: mapping^local to global @*/ PetscErrorCode ISLocalToGlobalMappingApply(ISLocalToGlobalMapping mapping,PetscInt N,const PetscInt in[],PetscInt out[]) { PetscInt i,bs,Nmax; PetscFunctionBegin; PetscValidHeaderSpecific(mapping,IS_LTOGM_CLASSID,1); bs = mapping->bs; Nmax = bs*mapping->n; if (bs == 1) { const PetscInt *idx = mapping->indices; for (i=0; i= Nmax) SETERRQ3(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Local index %D too large %D (max) at %D",in[i],Nmax-1,i); out[i] = idx[in[i]]; } } else { const PetscInt *idx = mapping->indices; for (i=0; i= Nmax) SETERRQ3(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Local index %D too large %D (max) at %D",in[i],Nmax-1,i); out[i] = idx[in[i]/bs]*bs + (in[i] % bs); } } PetscFunctionReturn(0); } #undef __FUNCT__ #define __FUNCT__ "ISLocalToGlobalMappingApplyBlock" /*@ ISLocalToGlobalMappingApplyBlock - Takes a list of integers in a local block numbering and converts them to the global block numbering Not collective Input Parameters: + mapping - the local to global mapping context . N - number of integers - in - input indices in local block numbering Output Parameter: . out - indices in global block numbering Notes: The in and out array parameters may be identical. Example: If the index values are {0,1,6,7} set with a call to ISLocalToGlobalMappingCreate(PETSC_COMM_SELF,2,2,{0,3}) then the mapping applied to 0 (the first block) would produce 0 and the mapping applied to 1 (the second block) would produce 3. Level: advanced .seealso: ISLocalToGlobalMappingApply(), ISLocalToGlobalMappingCreate(),ISLocalToGlobalMappingDestroy(), ISLocalToGlobalMappingApplyIS(),AOCreateBasic(),AOApplicationToPetsc(), AOPetscToApplication(), ISGlobalToLocalMappingApply() Concepts: mapping^local to global @*/ PetscErrorCode ISLocalToGlobalMappingApplyBlock(ISLocalToGlobalMapping mapping,PetscInt N,const PetscInt in[],PetscInt out[]) { PetscFunctionBegin; PetscValidHeaderSpecific(mapping,IS_LTOGM_CLASSID,1); { PetscInt i,Nmax = mapping->n; const PetscInt *idx = mapping->indices; for (i=0; i= Nmax) SETERRQ3(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Local block index %D too large %D (max) at %D",in[i],Nmax-1,i); out[i] = idx[in[i]]; } } PetscFunctionReturn(0); } /* -----------------------------------------------------------------------------------------*/ #undef __FUNCT__ #define __FUNCT__ "ISGlobalToLocalMappingSetUp_Private" /* Creates the global fields in the ISLocalToGlobalMapping structure */ static PetscErrorCode ISGlobalToLocalMappingSetUp_Private(ISLocalToGlobalMapping mapping) { PetscErrorCode ierr; PetscInt i,*idx = mapping->indices,n = mapping->n,end,start,*globals; PetscFunctionBegin; end = 0; start = PETSC_MAX_INT; for (i=0; i end) end = idx[i]; } if (start > end) {start = 0; end = -1;} mapping->globalstart = start; mapping->globalend = end; ierr = PetscMalloc1(end-start+2,&globals);CHKERRQ(ierr); mapping->globals = globals; for (i=0; iglobals) { ierr = ISGlobalToLocalMappingSetUp_Private(mapping);CHKERRQ(ierr); } globals = mapping->globals; start = mapping->globalstart; end = mapping->globalend; bs = mapping->bs; if (type == IS_GTOLM_MASK) { if (idxout) { for (i=0; i bs*(end+1)-1) idxout[i] = -1; else idxout[i] = bs*globals[idx[i]/bs - start] + (idx[i] % bs); } } if (nout) *nout = n; } else { if (idxout) { for (i=0; i bs*(end+1)-1) continue; tmp = bs*globals[idx[i]/bs - start] + (idx[i] % bs); if (tmp < 0) continue; idxout[nf++] = tmp; } } else { for (i=0; i bs*(end+1)-1) continue; tmp = bs*globals[idx[i]/bs - start] + (idx[i] % bs); if (tmp < 0) continue; nf++; } } if (nout) *nout = nf; } PetscFunctionReturn(0); } #undef __FUNCT__ #define __FUNCT__ "ISGlobalToLocalMappingApplyIS" /*@ ISGlobalToLocalMappingApplyIS - Creates from an IS in the global numbering a new index set using the local numbering defined in an ISLocalToGlobalMapping context. Not collective Input Parameters: + mapping - mapping between local and global numbering - is - index set in global numbering Output Parameters: . newis - index set in local numbering Level: advanced Concepts: mapping^local to global .seealso: ISGlobalToLocalMappingApply(), ISLocalToGlobalMappingCreate(), ISLocalToGlobalMappingDestroy() @*/ PetscErrorCode ISGlobalToLocalMappingApplyIS(ISLocalToGlobalMapping mapping,ISGlobalToLocalMappingType type, IS is,IS *newis) { PetscErrorCode ierr; PetscInt n,nout,*idxout; const PetscInt *idxin; PetscFunctionBegin; PetscValidHeaderSpecific(mapping,IS_LTOGM_CLASSID,1); PetscValidHeaderSpecific(is,IS_CLASSID,3); PetscValidPointer(newis,4); ierr = ISGetLocalSize(is,&n);CHKERRQ(ierr); ierr = ISGetIndices(is,&idxin);CHKERRQ(ierr); if (type == IS_GTOLM_MASK) { ierr = PetscMalloc1(n,&idxout);CHKERRQ(ierr); } else { ierr = ISGlobalToLocalMappingApply(mapping,type,n,idxin,&nout,NULL);CHKERRQ(ierr); ierr = PetscMalloc1(nout,&idxout);CHKERRQ(ierr); } ierr = ISGlobalToLocalMappingApply(mapping,type,n,idxin,&nout,idxout);CHKERRQ(ierr); ierr = ISRestoreIndices(is,&idxin);CHKERRQ(ierr); ierr = ISCreateGeneral(PetscObjectComm((PetscObject)is),nout,idxout,PETSC_OWN_POINTER,newis);CHKERRQ(ierr); PetscFunctionReturn(0); } #undef __FUNCT__ #define __FUNCT__ "ISGlobalToLocalMappingApplyBlock" /*@ ISGlobalToLocalMappingApplyBlock - Provides the local block numbering for a list of integers specified with a block global numbering. Not collective Input Parameters: + mapping - mapping between local and global numbering . type - IS_GTOLM_MASK - replaces global indices with no local value with -1 IS_GTOLM_DROP - drops the indices with no local value from the output list . n - number of global indices to map - idx - global indices to map Output Parameters: + nout - number of indices in output array (if type == IS_GTOLM_MASK then nout = n) - idxout - local index of each global index, one must pass in an array long enough to hold all the indices. You can call ISGlobalToLocalMappingApplyBlock() with idxout == NULL to determine the required length (returned in nout) and then allocate the required space and call ISGlobalToLocalMappingApplyBlock() a second time to set the values. Notes: Either nout or idxout may be NULL. idx and idxout may be identical. This is not scalable in memory usage. Each processor requires O(Nglobal) size array to compute these. Level: advanced Developer Note: The manual page states that idx and idxout may be identical but the calling sequence declares idx as const so it cannot be the same as idxout. Concepts: mapping^global to local .seealso: ISLocalToGlobalMappingApply(), ISGlobalToLocalMappingApply(), ISLocalToGlobalMappingCreate(), ISLocalToGlobalMappingDestroy() @*/ PetscErrorCode ISGlobalToLocalMappingApplyBlock(ISLocalToGlobalMapping mapping,ISGlobalToLocalMappingType type, PetscInt n,const PetscInt idx[],PetscInt *nout,PetscInt idxout[]) { PetscInt i,*globals,nf = 0,tmp,start,end; PetscErrorCode ierr; PetscFunctionBegin; PetscValidHeaderSpecific(mapping,IS_LTOGM_CLASSID,1); if (!mapping->globals) { ierr = ISGlobalToLocalMappingSetUp_Private(mapping);CHKERRQ(ierr); } globals = mapping->globals; start = mapping->globalstart; end = mapping->globalend; if (type == IS_GTOLM_MASK) { if (idxout) { for (i=0; i end) idxout[i] = -1; else idxout[i] = globals[idx[i] - start]; } } if (nout) *nout = n; } else { if (idxout) { for (i=0; i end) continue; tmp = globals[idx[i] - start]; if (tmp < 0) continue; idxout[nf++] = tmp; } } else { for (i=0; i end) continue; tmp = globals[idx[i] - start]; if (tmp < 0) continue; nf++; } } if (nout) *nout = nf; } PetscFunctionReturn(0); } #undef __FUNCT__ #define __FUNCT__ "ISLocalToGlobalMappingGetBlockInfo" /*@C ISLocalToGlobalMappingGetBlockInfo - Gets the neighbor information for each processor and each index shared by more than one processor Collective on ISLocalToGlobalMapping Input Parameters: . mapping - the mapping from local to global indexing Output Parameter: + nproc - number of processors that are connected to this one . proc - neighboring processors . numproc - number of indices for each subdomain (processor) - indices - indices of nodes (in local numbering) shared with neighbors (sorted by global numbering) Level: advanced Concepts: mapping^local to global Fortran Usage: $ ISLocalToGlobalMpngGetInfoSize(ISLocalToGlobalMapping,PetscInt nproc,PetscInt numprocmax,ierr) followed by $ ISLocalToGlobalMappingGetInfo(ISLocalToGlobalMapping,PetscInt nproc, PetscInt procs[nproc],PetscInt numprocs[nproc], PetscInt indices[nproc][numprocmax],ierr) There is no ISLocalToGlobalMappingRestoreInfo() in Fortran. You must make sure that procs[], numprocs[] and indices[][] are large enough arrays, either by allocating them dynamically or defining static ones large enough. .seealso: ISLocalToGlobalMappingDestroy(), ISLocalToGlobalMappingCreateIS(), ISLocalToGlobalMappingCreate(), ISLocalToGlobalMappingRestoreInfo() @*/ PetscErrorCode ISLocalToGlobalMappingGetBlockInfo(ISLocalToGlobalMapping mapping,PetscInt *nproc,PetscInt *procs[],PetscInt *numprocs[],PetscInt **indices[]) { PetscErrorCode ierr; PetscFunctionBegin; PetscValidHeaderSpecific(mapping,IS_LTOGM_CLASSID,1); if (mapping->info_cached) { *nproc = mapping->info_nproc; *procs = mapping->info_procs; *numprocs = mapping->info_numprocs; *indices = mapping->info_indices; } else { ierr = ISLocalToGlobalMappingGetBlockInfo_Private(mapping,nproc,procs,numprocs,indices);CHKERRQ(ierr); } PetscFunctionReturn(0); } #undef __FUNCT__ #define __FUNCT__ "ISLocalToGlobalMappingGetBlockInfo_Private" static PetscErrorCode ISLocalToGlobalMappingGetBlockInfo_Private(ISLocalToGlobalMapping mapping,PetscInt *nproc,PetscInt *procs[],PetscInt *numprocs[],PetscInt **indices[]) { PetscErrorCode ierr; PetscMPIInt size,rank,tag1,tag2,tag3,*len,*source,imdex; PetscInt i,n = mapping->n,Ng,ng,max = 0,*lindices = mapping->indices; PetscInt *nprocs,*owner,nsends,*sends,j,*starts,nmax,nrecvs,*recvs,proc; PetscInt cnt,scale,*ownedsenders,*nownedsenders,rstart,nowned; PetscInt node,nownedm,nt,*sends2,nsends2,*starts2,*lens2,*dest,nrecvs2,*starts3,*recvs2,k,*bprocs,*tmp; PetscInt first_procs,first_numprocs,*first_indices; MPI_Request *recv_waits,*send_waits; MPI_Status recv_status,*send_status,*recv_statuses; MPI_Comm comm; PetscBool debug = PETSC_FALSE; PetscFunctionBegin; ierr = PetscObjectGetComm((PetscObject)mapping,&comm);CHKERRQ(ierr); ierr = MPI_Comm_size(comm,&size);CHKERRQ(ierr); ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr); if (size == 1) { *nproc = 0; *procs = NULL; ierr = PetscMalloc(sizeof(PetscInt),numprocs);CHKERRQ(ierr); (*numprocs)[0] = 0; ierr = PetscMalloc(sizeof(PetscInt*),indices);CHKERRQ(ierr); (*indices)[0] = NULL; /* save info for reuse */ mapping->info_nproc = *nproc; mapping->info_procs = *procs; mapping->info_numprocs = *numprocs; mapping->info_indices = *indices; mapping->info_cached = PETSC_TRUE; PetscFunctionReturn(0); } ierr = PetscOptionsGetBool(((PetscObject)mapping)->options,NULL,"-islocaltoglobalmappinggetinfo_debug",&debug,NULL);CHKERRQ(ierr); /* Notes on ISLocalToGlobalMappingGetBlockInfo globally owned node - the nodes that have been assigned to this processor in global numbering, just for this routine. nontrivial globally owned node - node assigned to this processor that is on a subdomain boundary (i.e. is has more than one local owner) locally owned node - node that exists on this processors subdomain nontrivial locally owned node - node that is not in the interior (i.e. has more than one local subdomain */ ierr = PetscObjectGetNewTag((PetscObject)mapping,&tag1);CHKERRQ(ierr); ierr = PetscObjectGetNewTag((PetscObject)mapping,&tag2);CHKERRQ(ierr); ierr = PetscObjectGetNewTag((PetscObject)mapping,&tag3);CHKERRQ(ierr); for (i=0; i max) max = lindices[i]; } ierr = MPIU_Allreduce(&max,&Ng,1,MPIU_INT,MPI_MAX,comm);CHKERRQ(ierr); Ng++; ierr = MPI_Comm_size(comm,&size);CHKERRQ(ierr); ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr); scale = Ng/size + 1; ng = scale; if (rank == size-1) ng = Ng - scale*(size-1); ng = PetscMax(1,ng); rstart = scale*rank; /* determine ownership ranges of global indices */ ierr = PetscMalloc1(2*size,&nprocs);CHKERRQ(ierr); ierr = PetscMemzero(nprocs,2*size*sizeof(PetscInt));CHKERRQ(ierr); /* determine owners of each local node */ ierr = PetscMalloc1(n,&owner);CHKERRQ(ierr); for (i=0; i 1) {nownedm += nownedsenders[i]; nowned++;} } /* create single array to contain rank of all local owners of each globally owned index */ ierr = PetscMalloc1(nownedm+1,&ownedsenders);CHKERRQ(ierr); ierr = PetscMalloc1(ng+1,&starts);CHKERRQ(ierr); starts[0] = 0; for (i=1; i 1) starts[i] = starts[i-1] + nownedsenders[i-1]; else starts[i] = starts[i-1]; } /* for each nontrival globally owned node list all arriving processors */ for (i=0; i 1) ownedsenders[starts[node]++] = source[i]; } } if (debug) { /* ----------------------------------- */ starts[0] = 0; for (i=1; i 1) starts[i] = starts[i-1] + nownedsenders[i-1]; else starts[i] = starts[i-1]; } for (i=0; i 1) { ierr = PetscSynchronizedPrintf(comm,"[%d] global node %D local owner processors: ",rank,i+rstart);CHKERRQ(ierr); for (j=0; j 1) starts[i] = starts[i-1] + nownedsenders[i-1]; else starts[i] = starts[i-1]; } nsends2 = nrecvs; ierr = PetscMalloc1(nsends2+1,&nprocs);CHKERRQ(ierr); /* length of each message */ for (i=0; i 1) nprocs[i] += 2 + nownedsenders[node]; } } nt = 0; for (i=0; i 1) { sends2[starts2[i]]++; sends2[starts2[i]+cnt++] = recvs[2*i*nmax+2*j+1]; sends2[starts2[i]+cnt++] = nownedsenders[node]; ierr = PetscMemcpy(&sends2[starts2[i]+cnt],&ownedsenders[starts[node]],nownedsenders[node]*sizeof(PetscInt));CHKERRQ(ierr); cnt += nownedsenders[node]; } } } /* receive the message lengths */ nrecvs2 = nsends; ierr = PetscMalloc1(nrecvs2+1,&lens2);CHKERRQ(ierr); ierr = PetscMalloc1(nrecvs2+1,&starts3);CHKERRQ(ierr); ierr = PetscMalloc1(nrecvs2+1,&recv_waits);CHKERRQ(ierr); for (i=0; i 0); *nproc = nt; ierr = PetscMalloc1(nt+1,procs);CHKERRQ(ierr); ierr = PetscMalloc1(nt+1,numprocs);CHKERRQ(ierr); ierr = PetscMalloc1(nt+1,indices);CHKERRQ(ierr); for (i=0;i 0) { bprocs[i] = cnt; (*procs)[cnt] = i; (*numprocs)[cnt] = nprocs[i]; ierr = PetscMalloc1(nprocs[i],&(*indices)[cnt]);CHKERRQ(ierr); cnt++; } } /* make the list of subdomains for each nontrivial local node */ ierr = PetscMemzero(*numprocs,nt*sizeof(PetscInt));CHKERRQ(ierr); cnt = 0; for (i=0; iinfo_nproc = *nproc; mapping->info_procs = *procs; mapping->info_numprocs = *numprocs; mapping->info_indices = *indices; mapping->info_cached = PETSC_TRUE; PetscFunctionReturn(0); } #undef __FUNCT__ #define __FUNCT__ "ISLocalToGlobalMappingRestoreBlockInfo" /*@C ISLocalToGlobalMappingRestoreBlockInfo - Frees the memory allocated by ISLocalToGlobalMappingGetBlockInfo() Collective on ISLocalToGlobalMapping Input Parameters: . mapping - the mapping from local to global indexing Output Parameter: + nproc - number of processors that are connected to this one . proc - neighboring processors . numproc - number of indices for each processor - indices - indices of local nodes shared with neighbor (sorted by global numbering) Level: advanced .seealso: ISLocalToGlobalMappingDestroy(), ISLocalToGlobalMappingCreateIS(), ISLocalToGlobalMappingCreate(), ISLocalToGlobalMappingGetInfo() @*/ PetscErrorCode ISLocalToGlobalMappingRestoreBlockInfo(ISLocalToGlobalMapping mapping,PetscInt *nproc,PetscInt *procs[],PetscInt *numprocs[],PetscInt **indices[]) { PetscErrorCode ierr; PetscFunctionBegin; PetscValidHeaderSpecific(mapping,IS_LTOGM_CLASSID,1); if (mapping->info_free) { ierr = PetscFree(*numprocs);CHKERRQ(ierr); if (*indices) { PetscInt i; ierr = PetscFree((*indices)[0]);CHKERRQ(ierr); for (i=1; i<*nproc; i++) { ierr = PetscFree((*indices)[i]);CHKERRQ(ierr); } ierr = PetscFree(*indices);CHKERRQ(ierr); } } *nproc = 0; *procs = NULL; *numprocs = NULL; *indices = NULL; PetscFunctionReturn(0); } #undef __FUNCT__ #define __FUNCT__ "ISLocalToGlobalMappingGetInfo" /*@C ISLocalToGlobalMappingGetInfo - Gets the neighbor information for each processor and each index shared by more than one processor Collective on ISLocalToGlobalMapping Input Parameters: . mapping - the mapping from local to global indexing Output Parameter: + nproc - number of processors that are connected to this one . proc - neighboring processors . numproc - number of indices for each subdomain (processor) - indices - indices of nodes (in local numbering) shared with neighbors (sorted by global numbering) Level: advanced Concepts: mapping^local to global Fortran Usage: $ ISLocalToGlobalMpngGetInfoSize(ISLocalToGlobalMapping,PetscInt nproc,PetscInt numprocmax,ierr) followed by $ ISLocalToGlobalMappingGetInfo(ISLocalToGlobalMapping,PetscInt nproc, PetscInt procs[nproc],PetscInt numprocs[nproc], PetscInt indices[nproc][numprocmax],ierr) There is no ISLocalToGlobalMappingRestoreInfo() in Fortran. You must make sure that procs[], numprocs[] and indices[][] are large enough arrays, either by allocating them dynamically or defining static ones large enough. .seealso: ISLocalToGlobalMappingDestroy(), ISLocalToGlobalMappingCreateIS(), ISLocalToGlobalMappingCreate(), ISLocalToGlobalMappingRestoreInfo() @*/ PetscErrorCode ISLocalToGlobalMappingGetInfo(ISLocalToGlobalMapping mapping,PetscInt *nproc,PetscInt *procs[],PetscInt *numprocs[],PetscInt **indices[]) { PetscErrorCode ierr; PetscInt **bindices = NULL,*bnumprocs = NULL,bs = mapping->bs,i,j,k; PetscFunctionBegin; PetscValidHeaderSpecific(mapping,IS_LTOGM_CLASSID,1); ierr = ISLocalToGlobalMappingGetBlockInfo(mapping,nproc,procs,&bnumprocs,&bindices);CHKERRQ(ierr); if (bs > 1) { /* we need to expand the cached info */ ierr = PetscCalloc1(*nproc,&*indices);CHKERRQ(ierr); ierr = PetscCalloc1(*nproc,&*numprocs);CHKERRQ(ierr); for (i=0; i<*nproc; i++) { ierr = PetscMalloc1(bs*bnumprocs[i],&(*indices)[i]);CHKERRQ(ierr); for (j=0; jinfo_free = PETSC_TRUE; } else { *numprocs = bnumprocs; *indices = bindices; } PetscFunctionReturn(0); } #undef __FUNCT__ #define __FUNCT__ "ISLocalToGlobalMappingRestoreInfo" /*@C ISLocalToGlobalMappingRestoreInfo - Frees the memory allocated by ISLocalToGlobalMappingGetInfo() Collective on ISLocalToGlobalMapping Input Parameters: . mapping - the mapping from local to global indexing Output Parameter: + nproc - number of processors that are connected to this one . proc - neighboring processors . numproc - number of indices for each processor - indices - indices of local nodes shared with neighbor (sorted by global numbering) Level: advanced .seealso: ISLocalToGlobalMappingDestroy(), ISLocalToGlobalMappingCreateIS(), ISLocalToGlobalMappingCreate(), ISLocalToGlobalMappingGetInfo() @*/ PetscErrorCode ISLocalToGlobalMappingRestoreInfo(ISLocalToGlobalMapping mapping,PetscInt *nproc,PetscInt *procs[],PetscInt *numprocs[],PetscInt **indices[]) { PetscErrorCode ierr; PetscFunctionBegin; ierr = ISLocalToGlobalMappingRestoreBlockInfo(mapping,nproc,procs,numprocs,indices);CHKERRQ(ierr); PetscFunctionReturn(0); } #undef __FUNCT__ #define __FUNCT__ "ISLocalToGlobalMappingGetIndices" /*@C ISLocalToGlobalMappingGetIndices - Get global indices for every local point that is mapped Not Collective Input Arguments: . ltog - local to global mapping Output Arguments: . array - array of indices, the length of this array may be obtained with ISLocalToGlobalMappingGetSize() Level: advanced Notes: ISLocalToGlobalMappingGetSize() returns the length the this array .seealso: ISLocalToGlobalMappingCreate(), ISLocalToGlobalMappingApply(), ISLocalToGlobalMappingRestoreIndices(), ISLocalToGlobalMappingGetBlockIndices(), ISLocalToGlobalMappingRestoreBlockIndices() @*/ PetscErrorCode ISLocalToGlobalMappingGetIndices(ISLocalToGlobalMapping ltog,const PetscInt **array) { PetscFunctionBegin; PetscValidHeaderSpecific(ltog,IS_LTOGM_CLASSID,1); PetscValidPointer(array,2); if (ltog->bs == 1) { *array = ltog->indices; } else { PetscInt *jj,k,i,j,n = ltog->n, bs = ltog->bs; const PetscInt *ii; PetscErrorCode ierr; ierr = PetscMalloc1(bs*n,&jj);CHKERRQ(ierr); *array = jj; k = 0; ii = ltog->indices; for (i=0; ibs == 1 && *array != ltog->indices) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_BADPTR,"Trying to return mismatched pointer"); if (ltog->bs > 1) { PetscErrorCode ierr; ierr = PetscFree(*(void**)array);CHKERRQ(ierr); } PetscFunctionReturn(0); } #undef __FUNCT__ #define __FUNCT__ "ISLocalToGlobalMappingGetBlockIndices" /*@C ISLocalToGlobalMappingGetBlockIndices - Get global indices for every local block Not Collective Input Arguments: . ltog - local to global mapping Output Arguments: . array - array of indices Level: advanced .seealso: ISLocalToGlobalMappingCreate(), ISLocalToGlobalMappingApply(), ISLocalToGlobalMappingRestoreBlockIndices() @*/ PetscErrorCode ISLocalToGlobalMappingGetBlockIndices(ISLocalToGlobalMapping ltog,const PetscInt **array) { PetscFunctionBegin; PetscValidHeaderSpecific(ltog,IS_LTOGM_CLASSID,1); PetscValidPointer(array,2); *array = ltog->indices; PetscFunctionReturn(0); } #undef __FUNCT__ #define __FUNCT__ "ISLocalToGlobalMappingRestoreBlockIndices" /*@C ISLocalToGlobalMappingRestoreBlockIndices - Restore indices obtained with ISLocalToGlobalMappingGetBlockIndices() Not Collective Input Arguments: + ltog - local to global mapping - array - array of indices Level: advanced .seealso: ISLocalToGlobalMappingCreate(), ISLocalToGlobalMappingApply(), ISLocalToGlobalMappingGetIndices() @*/ PetscErrorCode ISLocalToGlobalMappingRestoreBlockIndices(ISLocalToGlobalMapping ltog,const PetscInt **array) { PetscFunctionBegin; PetscValidHeaderSpecific(ltog,IS_LTOGM_CLASSID,1); PetscValidPointer(array,2); if (*array != ltog->indices) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_BADPTR,"Trying to return mismatched pointer"); *array = NULL; PetscFunctionReturn(0); } #undef __FUNCT__ #define __FUNCT__ "ISLocalToGlobalMappingConcatenate" /*@C ISLocalToGlobalMappingConcatenate - Create a new mapping that concatenates a list of mappings Not Collective Input Arguments: + comm - communicator for the new mapping, must contain the communicator of every mapping to concatenate . n - number of mappings to concatenate - ltogs - local to global mappings Output Arguments: . ltogcat - new mapping Note: this currently always returns a mapping with block size of 1 Developer Note: If all the input mapping have the same block size we could easily handle that as a special case Level: advanced .seealso: ISLocalToGlobalMappingCreate() @*/ PetscErrorCode ISLocalToGlobalMappingConcatenate(MPI_Comm comm,PetscInt n,const ISLocalToGlobalMapping ltogs[],ISLocalToGlobalMapping *ltogcat) { PetscInt i,cnt,m,*idx; PetscErrorCode ierr; PetscFunctionBegin; if (n < 0) SETERRQ1(comm,PETSC_ERR_ARG_OUTOFRANGE,"Must have a non-negative number of mappings, given %D",n); if (n > 0) PetscValidPointer(ltogs,3); for (i=0; i