12362add9SBarry Smith 2af0996ceSBarry Smith #include <petsc/private/isimpl.h> /*I "petscis.h" I*/ 30c312b8eSJed Brown #include <petscsf.h> 4665c2dedSJed Brown #include <petscviewer.h> 52362add9SBarry Smith 67087cfbeSBarry Smith PetscClassId IS_LTOGM_CLASSID; 7268a049cSStefano Zampini static PetscErrorCode ISLocalToGlobalMappingGetBlockInfo_Private(ISLocalToGlobalMapping,PetscInt*,PetscInt**,PetscInt**,PetscInt***); 88e58c17dSMatthew Knepley 9186d4ecdSBarry Smith #undef __FUNCT__ 10*6658fb44Sstefano_zampini #define __FUNCT__ "ISLocalToGlobalMappingDuplicate" 11*6658fb44Sstefano_zampini /*@ 12*6658fb44Sstefano_zampini ISLocalToGlobalMappingDuplicate - Duplicates the local to global mapping object 13*6658fb44Sstefano_zampini 14*6658fb44Sstefano_zampini Not Collective 15*6658fb44Sstefano_zampini 16*6658fb44Sstefano_zampini Input Parameter: 17*6658fb44Sstefano_zampini . ltog - local to global mapping 18*6658fb44Sstefano_zampini 19*6658fb44Sstefano_zampini Output Parameter: 20*6658fb44Sstefano_zampini . nltog - the duplicated local to global mapping 21*6658fb44Sstefano_zampini 22*6658fb44Sstefano_zampini Level: advanced 23*6658fb44Sstefano_zampini 24*6658fb44Sstefano_zampini Concepts: mapping^local to global 25*6658fb44Sstefano_zampini 26*6658fb44Sstefano_zampini .seealso: ISLocalToGlobalMappingDestroy(), ISLocalToGlobalMappingCreate() 27*6658fb44Sstefano_zampini @*/ 28*6658fb44Sstefano_zampini PetscErrorCode ISLocalToGlobalMappingDuplicate(ISLocalToGlobalMapping ltog,ISLocalToGlobalMapping* nltog) 29*6658fb44Sstefano_zampini { 30*6658fb44Sstefano_zampini PetscErrorCode ierr; 31*6658fb44Sstefano_zampini 32*6658fb44Sstefano_zampini PetscFunctionBegin; 33*6658fb44Sstefano_zampini PetscValidHeaderSpecific(ltog,IS_LTOGM_CLASSID,1); 34*6658fb44Sstefano_zampini ierr = ISLocalToGlobalMappingCreate(PetscObjectComm((PetscObject)ltog),ltog->bs,ltog->n,ltog->indices,PETSC_COPY_VALUES,nltog);CHKERRQ(ierr); 35*6658fb44Sstefano_zampini PetscFunctionReturn(0); 36*6658fb44Sstefano_zampini } 37*6658fb44Sstefano_zampini 38*6658fb44Sstefano_zampini #undef __FUNCT__ 394a2ae208SSatish Balay #define __FUNCT__ "ISLocalToGlobalMappingGetSize" 40565245c5SBarry Smith /*@ 41107e9a97SBarry Smith ISLocalToGlobalMappingGetSize - Gets the local size of a local to global mapping 423b9aefa3SBarry Smith 433b9aefa3SBarry Smith Not Collective 443b9aefa3SBarry Smith 453b9aefa3SBarry Smith Input Parameter: 463b9aefa3SBarry Smith . ltog - local to global mapping 473b9aefa3SBarry Smith 483b9aefa3SBarry Smith Output Parameter: 49107e9a97SBarry Smith . n - the number of entries in the local mapping, ISLocalToGlobalMappingGetIndices() returns an array of this length 503b9aefa3SBarry Smith 513b9aefa3SBarry Smith Level: advanced 523b9aefa3SBarry Smith 53273d9f13SBarry Smith Concepts: mapping^local to global 543b9aefa3SBarry Smith 553b9aefa3SBarry Smith .seealso: ISLocalToGlobalMappingDestroy(), ISLocalToGlobalMappingCreate() 563b9aefa3SBarry Smith @*/ 577087cfbeSBarry Smith PetscErrorCode ISLocalToGlobalMappingGetSize(ISLocalToGlobalMapping mapping,PetscInt *n) 583b9aefa3SBarry Smith { 593b9aefa3SBarry Smith PetscFunctionBegin; 600700a824SBarry Smith PetscValidHeaderSpecific(mapping,IS_LTOGM_CLASSID,1); 614482741eSBarry Smith PetscValidIntPointer(n,2); 62107e9a97SBarry Smith *n = mapping->bs*mapping->n; 633b9aefa3SBarry Smith PetscFunctionReturn(0); 643b9aefa3SBarry Smith } 653b9aefa3SBarry Smith 664a2ae208SSatish Balay #undef __FUNCT__ 674a2ae208SSatish Balay #define __FUNCT__ "ISLocalToGlobalMappingView" 685a5d4f66SBarry Smith /*@C 695a5d4f66SBarry Smith ISLocalToGlobalMappingView - View a local to global mapping 705a5d4f66SBarry Smith 71b9cd556bSLois Curfman McInnes Not Collective 72b9cd556bSLois Curfman McInnes 735a5d4f66SBarry Smith Input Parameters: 743b9aefa3SBarry Smith + ltog - local to global mapping 753b9aefa3SBarry Smith - viewer - viewer 765a5d4f66SBarry Smith 77a997ad1aSLois Curfman McInnes Level: advanced 78a997ad1aSLois Curfman McInnes 79273d9f13SBarry Smith Concepts: mapping^local to global 805a5d4f66SBarry Smith 815a5d4f66SBarry Smith .seealso: ISLocalToGlobalMappingDestroy(), ISLocalToGlobalMappingCreate() 825a5d4f66SBarry Smith @*/ 837087cfbeSBarry Smith PetscErrorCode ISLocalToGlobalMappingView(ISLocalToGlobalMapping mapping,PetscViewer viewer) 845a5d4f66SBarry Smith { 8532dcc486SBarry Smith PetscInt i; 8632dcc486SBarry Smith PetscMPIInt rank; 87ace3abfcSBarry Smith PetscBool iascii; 886849ba73SBarry Smith PetscErrorCode ierr; 895a5d4f66SBarry Smith 905a5d4f66SBarry Smith PetscFunctionBegin; 910700a824SBarry Smith PetscValidHeaderSpecific(mapping,IS_LTOGM_CLASSID,1); 923050cee2SBarry Smith if (!viewer) { 93ce94432eSBarry Smith ierr = PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)mapping),&viewer);CHKERRQ(ierr); 943050cee2SBarry Smith } 950700a824SBarry Smith PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,2); 965a5d4f66SBarry Smith 97ce94432eSBarry Smith ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)mapping),&rank);CHKERRQ(ierr); 98251f4c67SDmitry Karpeev ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr); 9932077d6dSBarry Smith if (iascii) { 10098c3331eSBarry Smith ierr = PetscObjectPrintClassNamePrefixType((PetscObject)mapping,viewer);CHKERRQ(ierr); 1011575c14dSBarry Smith ierr = PetscViewerASCIIPushSynchronized(viewer);CHKERRQ(ierr); 1025a5d4f66SBarry Smith for (i=0; i<mapping->n; i++) { 1037904a332SBarry Smith ierr = PetscViewerASCIISynchronizedPrintf(viewer,"[%d] %D %D\n",rank,i,mapping->indices[i]);CHKERRQ(ierr); 1046831982aSBarry Smith } 105b0a32e0cSBarry Smith ierr = PetscViewerFlush(viewer);CHKERRQ(ierr); 1061575c14dSBarry Smith ierr = PetscViewerASCIIPopSynchronized(viewer);CHKERRQ(ierr); 1071575c14dSBarry Smith } 1085a5d4f66SBarry Smith PetscFunctionReturn(0); 1095a5d4f66SBarry Smith } 1105a5d4f66SBarry Smith 1114a2ae208SSatish Balay #undef __FUNCT__ 1124a2ae208SSatish Balay #define __FUNCT__ "ISLocalToGlobalMappingCreateIS" 1131f428162SBarry Smith /*@ 1142bdab257SBarry Smith ISLocalToGlobalMappingCreateIS - Creates a mapping between a local (0 to n) 1152bdab257SBarry Smith ordering and a global parallel ordering. 1162bdab257SBarry Smith 1170f5bd95cSBarry Smith Not collective 118b9cd556bSLois Curfman McInnes 119a997ad1aSLois Curfman McInnes Input Parameter: 1208c03b21aSDmitry Karpeev . is - index set containing the global numbers for each local number 1212bdab257SBarry Smith 122a997ad1aSLois Curfman McInnes Output Parameter: 1232bdab257SBarry Smith . mapping - new mapping data structure 1242bdab257SBarry Smith 125f0413b6fSBarry Smith Notes: the block size of the IS determines the block size of the mapping 126a997ad1aSLois Curfman McInnes Level: advanced 127a997ad1aSLois Curfman McInnes 128273d9f13SBarry Smith Concepts: mapping^local to global 1292bdab257SBarry Smith 1302bdab257SBarry Smith .seealso: ISLocalToGlobalMappingDestroy(), ISLocalToGlobalMappingCreate() 1312bdab257SBarry Smith @*/ 1327087cfbeSBarry Smith PetscErrorCode ISLocalToGlobalMappingCreateIS(IS is,ISLocalToGlobalMapping *mapping) 1332bdab257SBarry Smith { 1346849ba73SBarry Smith PetscErrorCode ierr; 1353bbf0e92SBarry Smith PetscInt n,bs; 1365d0c19d7SBarry Smith const PetscInt *indices; 1372bdab257SBarry Smith MPI_Comm comm; 1383bbf0e92SBarry Smith PetscBool isblock; 1393a40ed3dSBarry Smith 1403a40ed3dSBarry Smith PetscFunctionBegin; 1410700a824SBarry Smith PetscValidHeaderSpecific(is,IS_CLASSID,1); 1424482741eSBarry Smith PetscValidPointer(mapping,2); 1432bdab257SBarry Smith 1442bdab257SBarry Smith ierr = PetscObjectGetComm((PetscObject)is,&comm);CHKERRQ(ierr); 1453b9aefa3SBarry Smith ierr = ISGetLocalSize(is,&n);CHKERRQ(ierr); 1463bbf0e92SBarry Smith ierr = PetscObjectTypeCompare((PetscObject)is,ISBLOCK,&isblock);CHKERRQ(ierr); 1476006e8d2SBarry Smith if (!isblock) { 148f0413b6fSBarry Smith ierr = ISGetIndices(is,&indices);CHKERRQ(ierr); 149f0413b6fSBarry Smith ierr = ISLocalToGlobalMappingCreate(comm,1,n,indices,PETSC_COPY_VALUES,mapping);CHKERRQ(ierr); 1502bdab257SBarry Smith ierr = ISRestoreIndices(is,&indices);CHKERRQ(ierr); 1516006e8d2SBarry Smith } else { 1526006e8d2SBarry Smith ierr = ISGetBlockSize(is,&bs);CHKERRQ(ierr); 153f0413b6fSBarry Smith ierr = ISBlockGetIndices(is,&indices);CHKERRQ(ierr); 15428bc9809SBarry Smith ierr = ISLocalToGlobalMappingCreate(comm,bs,n/bs,indices,PETSC_COPY_VALUES,mapping);CHKERRQ(ierr); 155f0413b6fSBarry Smith ierr = ISBlockRestoreIndices(is,&indices);CHKERRQ(ierr); 1566006e8d2SBarry Smith } 1573a40ed3dSBarry Smith PetscFunctionReturn(0); 1582bdab257SBarry Smith } 1595a5d4f66SBarry Smith 160a4d96a55SJed Brown #undef __FUNCT__ 161a4d96a55SJed Brown #define __FUNCT__ "ISLocalToGlobalMappingCreateSF" 162a4d96a55SJed Brown /*@C 163a4d96a55SJed Brown ISLocalToGlobalMappingCreateSF - Creates a mapping between a local (0 to n) 164a4d96a55SJed Brown ordering and a global parallel ordering. 165a4d96a55SJed Brown 166a4d96a55SJed Brown Collective 167a4d96a55SJed Brown 168a4d96a55SJed Brown Input Parameter: 169a4d96a55SJed Brown + sf - star forest mapping contiguous local indices to (rank, offset) 170a4d96a55SJed Brown - start - first global index on this process 171a4d96a55SJed Brown 172a4d96a55SJed Brown Output Parameter: 173a4d96a55SJed Brown . mapping - new mapping data structure 174a4d96a55SJed Brown 175a4d96a55SJed Brown Level: advanced 176a4d96a55SJed Brown 177a4d96a55SJed Brown Concepts: mapping^local to global 178a4d96a55SJed Brown 179a4d96a55SJed Brown .seealso: ISLocalToGlobalMappingDestroy(), ISLocalToGlobalMappingCreate(), ISLocalToGlobalMappingCreateIS() 180a4d96a55SJed Brown @*/ 181a4d96a55SJed Brown PetscErrorCode ISLocalToGlobalMappingCreateSF(PetscSF sf,PetscInt start,ISLocalToGlobalMapping *mapping) 182a4d96a55SJed Brown { 183a4d96a55SJed Brown PetscErrorCode ierr; 184a4d96a55SJed Brown PetscInt i,maxlocal,nroots,nleaves,*globals,*ltog; 185a4d96a55SJed Brown const PetscInt *ilocal; 186a4d96a55SJed Brown MPI_Comm comm; 187a4d96a55SJed Brown 188a4d96a55SJed Brown PetscFunctionBegin; 189a4d96a55SJed Brown PetscValidHeaderSpecific(sf,PETSCSF_CLASSID,1); 190a4d96a55SJed Brown PetscValidPointer(mapping,3); 191a4d96a55SJed Brown 192a4d96a55SJed Brown ierr = PetscObjectGetComm((PetscObject)sf,&comm);CHKERRQ(ierr); 1930298fd71SBarry Smith ierr = PetscSFGetGraph(sf,&nroots,&nleaves,&ilocal,NULL);CHKERRQ(ierr); 194f6e5521dSKarl Rupp if (ilocal) { 195f6e5521dSKarl Rupp for (i=0,maxlocal=0; i<nleaves; i++) maxlocal = PetscMax(maxlocal,ilocal[i]+1); 196f6e5521dSKarl Rupp } 197a4d96a55SJed Brown else maxlocal = nleaves; 198785e854fSJed Brown ierr = PetscMalloc1(nroots,&globals);CHKERRQ(ierr); 199785e854fSJed Brown ierr = PetscMalloc1(maxlocal,<og);CHKERRQ(ierr); 200a4d96a55SJed Brown for (i=0; i<nroots; i++) globals[i] = start + i; 201a4d96a55SJed Brown for (i=0; i<maxlocal; i++) ltog[i] = -1; 202a4d96a55SJed Brown ierr = PetscSFBcastBegin(sf,MPIU_INT,globals,ltog);CHKERRQ(ierr); 203a4d96a55SJed Brown ierr = PetscSFBcastEnd(sf,MPIU_INT,globals,ltog);CHKERRQ(ierr); 204f0413b6fSBarry Smith ierr = ISLocalToGlobalMappingCreate(comm,1,maxlocal,ltog,PETSC_OWN_POINTER,mapping);CHKERRQ(ierr); 205a4d96a55SJed Brown ierr = PetscFree(globals);CHKERRQ(ierr); 206a4d96a55SJed Brown PetscFunctionReturn(0); 207a4d96a55SJed Brown } 208b46b645bSBarry Smith 2094a2ae208SSatish Balay #undef __FUNCT__ 21063fa5c83Sstefano_zampini #define __FUNCT__ "ISLocalToGlobalMappingSetBlockSize" 21163fa5c83Sstefano_zampini /*@ 21263fa5c83Sstefano_zampini ISLocalToGlobalMappingSetBlockSize - Sets the blocksize of the mapping 21363fa5c83Sstefano_zampini 21463fa5c83Sstefano_zampini Not collective 21563fa5c83Sstefano_zampini 21663fa5c83Sstefano_zampini Input Parameters: 21763fa5c83Sstefano_zampini . mapping - mapping data structure 21863fa5c83Sstefano_zampini . bs - the blocksize 21963fa5c83Sstefano_zampini 22063fa5c83Sstefano_zampini Level: advanced 22163fa5c83Sstefano_zampini 22263fa5c83Sstefano_zampini Concepts: mapping^local to global 22363fa5c83Sstefano_zampini 22463fa5c83Sstefano_zampini .seealso: ISLocalToGlobalMappingDestroy(), ISLocalToGlobalMappingCreateIS() 22563fa5c83Sstefano_zampini @*/ 22663fa5c83Sstefano_zampini PetscErrorCode ISLocalToGlobalMappingSetBlockSize(ISLocalToGlobalMapping mapping,PetscInt bs) 22763fa5c83Sstefano_zampini { 22863fa5c83Sstefano_zampini PetscInt *nid,*oid; 2298b7cb0e6Sstefano_zampini PetscInt i,cn,on,obs,nn,cum,r,rbs,ri; 23063fa5c83Sstefano_zampini PetscErrorCode ierr; 23163fa5c83Sstefano_zampini 23263fa5c83Sstefano_zampini PetscFunctionBegin; 23363fa5c83Sstefano_zampini PetscValidHeaderSpecific(mapping,IS_LTOGM_CLASSID,1); 23463fa5c83Sstefano_zampini if (bs < 1) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Invalid block size %D",bs); 23563fa5c83Sstefano_zampini if (bs == mapping->bs) PetscFunctionReturn(0); 23663fa5c83Sstefano_zampini on = mapping->n; 23763fa5c83Sstefano_zampini obs = mapping->bs; 23863fa5c83Sstefano_zampini oid = mapping->indices; 23963fa5c83Sstefano_zampini nn = (on*obs)/bs; 24063fa5c83Sstefano_zampini if ((on*obs)%bs) SETERRQ3(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Block size %D is inconsistent with block size %D and number of block indices %D",bs,obs,on); 2418b7cb0e6Sstefano_zampini if (bs < obs && obs%bs) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Block size %D is inconsistent with block size %D",bs,obs); 2428b7cb0e6Sstefano_zampini if (bs < obs) { 2438b7cb0e6Sstefano_zampini r = bs; 2448b7cb0e6Sstefano_zampini rbs = obs/bs; 2458b7cb0e6Sstefano_zampini ri = 1; 2468b7cb0e6Sstefano_zampini } else { 2478b7cb0e6Sstefano_zampini r = obs; 2488b7cb0e6Sstefano_zampini rbs = 1; 2498b7cb0e6Sstefano_zampini ri = bs/obs; 2508b7cb0e6Sstefano_zampini } 25163fa5c83Sstefano_zampini ierr = PetscMalloc1(nn,&nid);CHKERRQ(ierr); 252c9345713Sstefano_zampini for (i=0,cum=0,cn=0;i<on;i++) { 2538b7cb0e6Sstefano_zampini if (oid[i] < 0) cn += r; 2548b7cb0e6Sstefano_zampini if ((cn && !(cn%bs)) || (oid[i] > -1 && !((oid[i]*obs)%bs))) { 25563fa5c83Sstefano_zampini if (cum == nn) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Block sizes %D and %D are incompatible with the block indices",bs,obs); 2568b7cb0e6Sstefano_zampini if (cn && cn%bs) SETERRQ5(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Block sizes %D and %D are incompatible with the block indices (neg = %D, rbs %D, r %D)",bs,obs,cn,rbs,r); 2578b7cb0e6Sstefano_zampini if (cn) { 2588b7cb0e6Sstefano_zampini PetscInt j; 2598b7cb0e6Sstefano_zampini for (j=0;j<rbs;j++) nid[cum++] = -1; 2608b7cb0e6Sstefano_zampini } else { 2618b7cb0e6Sstefano_zampini PetscInt j; 2628b7cb0e6Sstefano_zampini for (j=1;j<ri;j++) { 2638b7cb0e6Sstefano_zampini if (i+j >= on) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Block sizes %D and %D are incompatible with the block indices: non consecutive indices found",bs,obs); 2648b7cb0e6Sstefano_zampini if (oid[i] != oid[i+j]-j) SETERRQ6(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Block sizes %D and %D are incompatible with the block indices: non consecutive indices %D %D (%D,%D)",bs,obs,oid[i],oid[i+j],j,ri); 2658b7cb0e6Sstefano_zampini } 2668b7cb0e6Sstefano_zampini for (j=0;j<rbs;j++) nid[cum++] = (oid[i]*obs)/bs+j; 2678b7cb0e6Sstefano_zampini } 268c9345713Sstefano_zampini cn = 0; 26963fa5c83Sstefano_zampini } 27063fa5c83Sstefano_zampini } 271c9345713Sstefano_zampini if (cum != nn || cn) { 27263fa5c83Sstefano_zampini ierr = PetscFree(nid);CHKERRQ(ierr); 2738b7cb0e6Sstefano_zampini SETERRQ6(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Incompatible block sizes %D and %D (new block indices found %D != %D, neg %D, rbs %D)",bs,obs,cum,nn,cn,rbs); 27463fa5c83Sstefano_zampini } 27563fa5c83Sstefano_zampini mapping->n = nn; 27663fa5c83Sstefano_zampini mapping->bs = bs; 27763fa5c83Sstefano_zampini ierr = PetscFree(mapping->indices);CHKERRQ(ierr); 27863fa5c83Sstefano_zampini mapping->indices = nid; 279c9345713Sstefano_zampini ierr = PetscFree(mapping->globals);CHKERRQ(ierr); 280c9345713Sstefano_zampini mapping->globalstart = 0; 281c9345713Sstefano_zampini mapping->globalend = 0; 28263fa5c83Sstefano_zampini PetscFunctionReturn(0); 28363fa5c83Sstefano_zampini } 28463fa5c83Sstefano_zampini 28563fa5c83Sstefano_zampini #undef __FUNCT__ 28645b6f7e9SBarry Smith #define __FUNCT__ "ISLocalToGlobalMappingGetBlockSize" 28745b6f7e9SBarry Smith /*@ 28845b6f7e9SBarry Smith ISLocalToGlobalMappingGetBlockSize - Gets the blocksize of the mapping 28945b6f7e9SBarry Smith ordering and a global parallel ordering. 29045b6f7e9SBarry Smith 29145b6f7e9SBarry Smith Not Collective 29245b6f7e9SBarry Smith 29345b6f7e9SBarry Smith Input Parameters: 29445b6f7e9SBarry Smith . mapping - mapping data structure 29545b6f7e9SBarry Smith 29645b6f7e9SBarry Smith Output Parameter: 29745b6f7e9SBarry Smith . bs - the blocksize 29845b6f7e9SBarry Smith 29945b6f7e9SBarry Smith Level: advanced 30045b6f7e9SBarry Smith 30145b6f7e9SBarry Smith Concepts: mapping^local to global 30245b6f7e9SBarry Smith 30345b6f7e9SBarry Smith .seealso: ISLocalToGlobalMappingDestroy(), ISLocalToGlobalMappingCreateIS() 30445b6f7e9SBarry Smith @*/ 30545b6f7e9SBarry Smith PetscErrorCode ISLocalToGlobalMappingGetBlockSize(ISLocalToGlobalMapping mapping,PetscInt *bs) 30645b6f7e9SBarry Smith { 30745b6f7e9SBarry Smith PetscFunctionBegin; 308cbc1caf0SMatthew G. Knepley PetscValidHeaderSpecific(mapping,IS_LTOGM_CLASSID,1); 30945b6f7e9SBarry Smith *bs = mapping->bs; 31045b6f7e9SBarry Smith PetscFunctionReturn(0); 31145b6f7e9SBarry Smith } 31245b6f7e9SBarry Smith 31345b6f7e9SBarry Smith #undef __FUNCT__ 3144a2ae208SSatish Balay #define __FUNCT__ "ISLocalToGlobalMappingCreate" 315ba5bb76aSSatish Balay /*@ 31690f02eecSBarry Smith ISLocalToGlobalMappingCreate - Creates a mapping between a local (0 to n) 31790f02eecSBarry Smith ordering and a global parallel ordering. 3182362add9SBarry Smith 31989d82c54SBarry Smith Not Collective, but communicator may have more than one process 320b9cd556bSLois Curfman McInnes 3212362add9SBarry Smith Input Parameters: 32289d82c54SBarry Smith + comm - MPI communicator 323f0413b6fSBarry Smith . bs - the block size 32428bc9809SBarry Smith . n - the number of local elements divided by the block size, or equivalently the number of block indices 32528bc9809SBarry Smith . 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 326d5ad8652SBarry Smith - mode - see PetscCopyMode 3272362add9SBarry Smith 328a997ad1aSLois Curfman McInnes Output Parameter: 32990f02eecSBarry Smith . mapping - new mapping data structure 3302362add9SBarry Smith 331f0413b6fSBarry Smith Notes: There is one integer value in indices per block and it represents the actual indices bs*idx + j, where j=0,..,bs-1 332a997ad1aSLois Curfman McInnes Level: advanced 333a997ad1aSLois Curfman McInnes 334273d9f13SBarry Smith Concepts: mapping^local to global 3352362add9SBarry Smith 336d5ad8652SBarry Smith .seealso: ISLocalToGlobalMappingDestroy(), ISLocalToGlobalMappingCreateIS() 3372362add9SBarry Smith @*/ 33860c7cefcSBarry Smith PetscErrorCode ISLocalToGlobalMappingCreate(MPI_Comm comm,PetscInt bs,PetscInt n,const PetscInt indices[],PetscCopyMode mode,ISLocalToGlobalMapping *mapping) 3392362add9SBarry Smith { 3406849ba73SBarry Smith PetscErrorCode ierr; 34132dcc486SBarry Smith PetscInt *in; 342b46b645bSBarry Smith 343b46b645bSBarry Smith PetscFunctionBegin; 34473911063SBarry Smith if (n) PetscValidIntPointer(indices,3); 3454482741eSBarry Smith PetscValidPointer(mapping,4); 346b46b645bSBarry Smith 3470298fd71SBarry Smith *mapping = NULL; 348607a6623SBarry Smith ierr = ISInitializePackage();CHKERRQ(ierr); 3492362add9SBarry Smith 35073107ff1SLisandro Dalcin ierr = PetscHeaderCreate(*mapping,IS_LTOGM_CLASSID,"ISLocalToGlobalMapping","Local to global mapping","IS", 35160c7cefcSBarry Smith comm,ISLocalToGlobalMappingDestroy,ISLocalToGlobalMappingView);CHKERRQ(ierr); 352d4bb536fSBarry Smith (*mapping)->n = n; 353f0413b6fSBarry Smith (*mapping)->bs = bs; 354268a049cSStefano Zampini (*mapping)->info_cached = PETSC_FALSE; 355268a049cSStefano Zampini (*mapping)->info_free = PETSC_FALSE; 356268a049cSStefano Zampini (*mapping)->info_procs = NULL; 357268a049cSStefano Zampini (*mapping)->info_numprocs = NULL; 358268a049cSStefano Zampini (*mapping)->info_indices = NULL; 359d4bb536fSBarry Smith /* 360d4bb536fSBarry Smith Do not create the global to local mapping. This is only created if 361d4bb536fSBarry Smith ISGlobalToLocalMapping() is called 362d4bb536fSBarry Smith */ 363d4bb536fSBarry Smith (*mapping)->globals = 0; 364d5ad8652SBarry Smith if (mode == PETSC_COPY_VALUES) { 365785e854fSJed Brown ierr = PetscMalloc1(n,&in);CHKERRQ(ierr); 366d5ad8652SBarry Smith ierr = PetscMemcpy(in,indices,n*sizeof(PetscInt));CHKERRQ(ierr); 367d5ad8652SBarry Smith (*mapping)->indices = in; 3686389a1a1SBarry Smith ierr = PetscLogObjectMemory((PetscObject)*mapping,n*sizeof(PetscInt));CHKERRQ(ierr); 3696389a1a1SBarry Smith } else if (mode == PETSC_OWN_POINTER) { 3706389a1a1SBarry Smith (*mapping)->indices = (PetscInt*)indices; 3716389a1a1SBarry Smith ierr = PetscLogObjectMemory((PetscObject)*mapping,n*sizeof(PetscInt));CHKERRQ(ierr); 3726389a1a1SBarry Smith } 37360c7cefcSBarry Smith else SETERRQ(comm,PETSC_ERR_SUP,"Cannot currently use PETSC_USE_POINTER"); 374d96308ebSBarry Smith ierr = PetscStrallocpy("basic",&((PetscObject)*mapping)->type_name);CHKERRQ(ierr); 3753a40ed3dSBarry Smith PetscFunctionReturn(0); 3762362add9SBarry Smith } 3772362add9SBarry Smith 3784a2ae208SSatish Balay #undef __FUNCT__ 3794a2ae208SSatish Balay #define __FUNCT__ "ISLocalToGlobalMappingDestroy" 38090f02eecSBarry Smith /*@ 38190f02eecSBarry Smith ISLocalToGlobalMappingDestroy - Destroys a mapping between a local (0 to n) 38290f02eecSBarry Smith ordering and a global parallel ordering. 38390f02eecSBarry Smith 3840f5bd95cSBarry Smith Note Collective 385b9cd556bSLois Curfman McInnes 38690f02eecSBarry Smith Input Parameters: 38790f02eecSBarry Smith . mapping - mapping data structure 38890f02eecSBarry Smith 389a997ad1aSLois Curfman McInnes Level: advanced 390a997ad1aSLois Curfman McInnes 3913acfe500SLois Curfman McInnes .seealso: ISLocalToGlobalMappingCreate() 39290f02eecSBarry Smith @*/ 3936bf464f9SBarry Smith PetscErrorCode ISLocalToGlobalMappingDestroy(ISLocalToGlobalMapping *mapping) 39490f02eecSBarry Smith { 395dfbe8321SBarry Smith PetscErrorCode ierr; 3965fd66863SKarl Rupp 3973a40ed3dSBarry Smith PetscFunctionBegin; 3986bf464f9SBarry Smith if (!*mapping) PetscFunctionReturn(0); 3996bf464f9SBarry Smith PetscValidHeaderSpecific((*mapping),IS_LTOGM_CLASSID,1); 400997056adSBarry Smith if (--((PetscObject)(*mapping))->refct > 0) {*mapping = 0;PetscFunctionReturn(0);} 4016bf464f9SBarry Smith ierr = PetscFree((*mapping)->indices);CHKERRQ(ierr); 4026bf464f9SBarry Smith ierr = PetscFree((*mapping)->globals);CHKERRQ(ierr); 403268a049cSStefano Zampini ierr = PetscFree((*mapping)->info_procs);CHKERRQ(ierr); 404268a049cSStefano Zampini ierr = PetscFree((*mapping)->info_numprocs);CHKERRQ(ierr); 405268a049cSStefano Zampini if ((*mapping)->info_indices) { 406268a049cSStefano Zampini PetscInt i; 407268a049cSStefano Zampini 408268a049cSStefano Zampini ierr = PetscFree(((*mapping)->info_indices)[0]);CHKERRQ(ierr); 409268a049cSStefano Zampini for (i=1; i<(*mapping)->info_nproc; i++) { 410268a049cSStefano Zampini ierr = PetscFree(((*mapping)->info_indices)[i]);CHKERRQ(ierr); 411268a049cSStefano Zampini } 412268a049cSStefano Zampini ierr = PetscFree((*mapping)->info_indices);CHKERRQ(ierr); 413268a049cSStefano Zampini } 414d38fa0fbSBarry Smith ierr = PetscHeaderDestroy(mapping);CHKERRQ(ierr); 415992144d0SBarry Smith *mapping = 0; 4163a40ed3dSBarry Smith PetscFunctionReturn(0); 41790f02eecSBarry Smith } 41890f02eecSBarry Smith 4194a2ae208SSatish Balay #undef __FUNCT__ 4204a2ae208SSatish Balay #define __FUNCT__ "ISLocalToGlobalMappingApplyIS" 42190f02eecSBarry Smith /*@ 4223acfe500SLois Curfman McInnes ISLocalToGlobalMappingApplyIS - Creates from an IS in the local numbering 4233acfe500SLois Curfman McInnes a new index set using the global numbering defined in an ISLocalToGlobalMapping 4243acfe500SLois Curfman McInnes context. 42590f02eecSBarry Smith 426b9cd556bSLois Curfman McInnes Not collective 427b9cd556bSLois Curfman McInnes 42890f02eecSBarry Smith Input Parameters: 429b9cd556bSLois Curfman McInnes + mapping - mapping between local and global numbering 430b9cd556bSLois Curfman McInnes - is - index set in local numbering 43190f02eecSBarry Smith 43290f02eecSBarry Smith Output Parameters: 43390f02eecSBarry Smith . newis - index set in global numbering 43490f02eecSBarry Smith 435a997ad1aSLois Curfman McInnes Level: advanced 436a997ad1aSLois Curfman McInnes 437273d9f13SBarry Smith Concepts: mapping^local to global 4383acfe500SLois Curfman McInnes 43990f02eecSBarry Smith .seealso: ISLocalToGlobalMappingApply(), ISLocalToGlobalMappingCreate(), 440d4bb536fSBarry Smith ISLocalToGlobalMappingDestroy(), ISGlobalToLocalMappingApply() 44190f02eecSBarry Smith @*/ 4427087cfbeSBarry Smith PetscErrorCode ISLocalToGlobalMappingApplyIS(ISLocalToGlobalMapping mapping,IS is,IS *newis) 44390f02eecSBarry Smith { 4446849ba73SBarry Smith PetscErrorCode ierr; 445e24637baSBarry Smith PetscInt n,*idxout; 4465d0c19d7SBarry Smith const PetscInt *idxin; 4473a40ed3dSBarry Smith 4483a40ed3dSBarry Smith PetscFunctionBegin; 4490700a824SBarry Smith PetscValidHeaderSpecific(mapping,IS_LTOGM_CLASSID,1); 4500700a824SBarry Smith PetscValidHeaderSpecific(is,IS_CLASSID,2); 4514482741eSBarry Smith PetscValidPointer(newis,3); 45290f02eecSBarry Smith 4533b9aefa3SBarry Smith ierr = ISGetLocalSize(is,&n);CHKERRQ(ierr); 45490f02eecSBarry Smith ierr = ISGetIndices(is,&idxin);CHKERRQ(ierr); 455785e854fSJed Brown ierr = PetscMalloc1(n,&idxout);CHKERRQ(ierr); 456e24637baSBarry Smith ierr = ISLocalToGlobalMappingApply(mapping,n,idxin,idxout);CHKERRQ(ierr); 4573b9aefa3SBarry Smith ierr = ISRestoreIndices(is,&idxin);CHKERRQ(ierr); 458543f3098SMatthew G. Knepley ierr = ISCreateGeneral(PetscObjectComm((PetscObject)is),n,idxout,PETSC_OWN_POINTER,newis);CHKERRQ(ierr); 4593a40ed3dSBarry Smith PetscFunctionReturn(0); 46090f02eecSBarry Smith } 46190f02eecSBarry Smith 462afcb2eb5SJed Brown #undef __FUNCT__ 463afcb2eb5SJed Brown #define __FUNCT__ "ISLocalToGlobalMappingApply" 464b89cb25eSSatish Balay /*@ 4653acfe500SLois Curfman McInnes ISLocalToGlobalMappingApply - Takes a list of integers in a local numbering 4663acfe500SLois Curfman McInnes and converts them to the global numbering. 46790f02eecSBarry Smith 468b9cd556bSLois Curfman McInnes Not collective 469b9cd556bSLois Curfman McInnes 470bb25748dSBarry Smith Input Parameters: 471b9cd556bSLois Curfman McInnes + mapping - the local to global mapping context 472bb25748dSBarry Smith . N - number of integers 473b9cd556bSLois Curfman McInnes - in - input indices in local numbering 474bb25748dSBarry Smith 475bb25748dSBarry Smith Output Parameter: 476bb25748dSBarry Smith . out - indices in global numbering 477bb25748dSBarry Smith 478b9cd556bSLois Curfman McInnes Notes: 479b9cd556bSLois Curfman McInnes The in and out array parameters may be identical. 480d4bb536fSBarry Smith 481a997ad1aSLois Curfman McInnes Level: advanced 482a997ad1aSLois Curfman McInnes 48345b6f7e9SBarry Smith .seealso: ISLocalToGlobalMappingApplyBlock(), ISLocalToGlobalMappingCreate(),ISLocalToGlobalMappingDestroy(), 4840752156aSBarry Smith ISLocalToGlobalMappingApplyIS(),AOCreateBasic(),AOApplicationToPetsc(), 485d4bb536fSBarry Smith AOPetscToApplication(), ISGlobalToLocalMappingApply() 486bb25748dSBarry Smith 487273d9f13SBarry Smith Concepts: mapping^local to global 488afcb2eb5SJed Brown @*/ 489afcb2eb5SJed Brown PetscErrorCode ISLocalToGlobalMappingApply(ISLocalToGlobalMapping mapping,PetscInt N,const PetscInt in[],PetscInt out[]) 490afcb2eb5SJed Brown { 491cbc1caf0SMatthew G. Knepley PetscInt i,bs,Nmax; 49245b6f7e9SBarry Smith 49345b6f7e9SBarry Smith PetscFunctionBegin; 494cbc1caf0SMatthew G. Knepley PetscValidHeaderSpecific(mapping,IS_LTOGM_CLASSID,1); 495cbc1caf0SMatthew G. Knepley bs = mapping->bs; 496cbc1caf0SMatthew G. Knepley Nmax = bs*mapping->n; 49745b6f7e9SBarry Smith if (bs == 1) { 498cbc1caf0SMatthew G. Knepley const PetscInt *idx = mapping->indices; 49945b6f7e9SBarry Smith for (i=0; i<N; i++) { 50045b6f7e9SBarry Smith if (in[i] < 0) { 50145b6f7e9SBarry Smith out[i] = in[i]; 50245b6f7e9SBarry Smith continue; 50345b6f7e9SBarry Smith } 504e24637baSBarry Smith if (in[i] >= Nmax) SETERRQ3(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Local index %D too large %D (max) at %D",in[i],Nmax-1,i); 50545b6f7e9SBarry Smith out[i] = idx[in[i]]; 50645b6f7e9SBarry Smith } 50745b6f7e9SBarry Smith } else { 508cbc1caf0SMatthew G. Knepley const PetscInt *idx = mapping->indices; 50945b6f7e9SBarry Smith for (i=0; i<N; i++) { 51045b6f7e9SBarry Smith if (in[i] < 0) { 51145b6f7e9SBarry Smith out[i] = in[i]; 51245b6f7e9SBarry Smith continue; 51345b6f7e9SBarry Smith } 514e24637baSBarry Smith if (in[i] >= Nmax) SETERRQ3(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Local index %D too large %D (max) at %D",in[i],Nmax-1,i); 51545b6f7e9SBarry Smith out[i] = idx[in[i]/bs]*bs + (in[i] % bs); 51645b6f7e9SBarry Smith } 51745b6f7e9SBarry Smith } 51845b6f7e9SBarry Smith PetscFunctionReturn(0); 51945b6f7e9SBarry Smith } 52045b6f7e9SBarry Smith 52145b6f7e9SBarry Smith #undef __FUNCT__ 52245b6f7e9SBarry Smith #define __FUNCT__ "ISLocalToGlobalMappingApplyBlock" 52345b6f7e9SBarry Smith /*@ 5246006e8d2SBarry Smith ISLocalToGlobalMappingApplyBlock - Takes a list of integers in a local block numbering and converts them to the global block numbering 52545b6f7e9SBarry Smith 52645b6f7e9SBarry Smith Not collective 52745b6f7e9SBarry Smith 52845b6f7e9SBarry Smith Input Parameters: 52945b6f7e9SBarry Smith + mapping - the local to global mapping context 53045b6f7e9SBarry Smith . N - number of integers 5316006e8d2SBarry Smith - in - input indices in local block numbering 53245b6f7e9SBarry Smith 53345b6f7e9SBarry Smith Output Parameter: 5346006e8d2SBarry Smith . out - indices in global block numbering 53545b6f7e9SBarry Smith 53645b6f7e9SBarry Smith Notes: 53745b6f7e9SBarry Smith The in and out array parameters may be identical. 53845b6f7e9SBarry Smith 5396006e8d2SBarry Smith Example: 5406006e8d2SBarry Smith 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 5416006e8d2SBarry Smith (the first block) would produce 0 and the mapping applied to 1 (the second block) would produce 3. 5426006e8d2SBarry Smith 54345b6f7e9SBarry Smith Level: advanced 54445b6f7e9SBarry Smith 54545b6f7e9SBarry Smith .seealso: ISLocalToGlobalMappingApply(), ISLocalToGlobalMappingCreate(),ISLocalToGlobalMappingDestroy(), 54645b6f7e9SBarry Smith ISLocalToGlobalMappingApplyIS(),AOCreateBasic(),AOApplicationToPetsc(), 54745b6f7e9SBarry Smith AOPetscToApplication(), ISGlobalToLocalMappingApply() 54845b6f7e9SBarry Smith 54945b6f7e9SBarry Smith Concepts: mapping^local to global 55045b6f7e9SBarry Smith @*/ 55145b6f7e9SBarry Smith PetscErrorCode ISLocalToGlobalMappingApplyBlock(ISLocalToGlobalMapping mapping,PetscInt N,const PetscInt in[],PetscInt out[]) 55245b6f7e9SBarry Smith { 553cbc1caf0SMatthew G. Knepley 554cbc1caf0SMatthew G. Knepley PetscFunctionBegin; 555cbc1caf0SMatthew G. Knepley PetscValidHeaderSpecific(mapping,IS_LTOGM_CLASSID,1); 556cbc1caf0SMatthew G. Knepley { 557afcb2eb5SJed Brown PetscInt i,Nmax = mapping->n; 558afcb2eb5SJed Brown const PetscInt *idx = mapping->indices; 559d4bb536fSBarry Smith 560afcb2eb5SJed Brown for (i=0; i<N; i++) { 561afcb2eb5SJed Brown if (in[i] < 0) { 562afcb2eb5SJed Brown out[i] = in[i]; 563afcb2eb5SJed Brown continue; 564afcb2eb5SJed Brown } 565e24637baSBarry Smith if (in[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); 566afcb2eb5SJed Brown out[i] = idx[in[i]]; 567afcb2eb5SJed Brown } 568cbc1caf0SMatthew G. Knepley } 569afcb2eb5SJed Brown PetscFunctionReturn(0); 570afcb2eb5SJed Brown } 571d4bb536fSBarry Smith 572d4bb536fSBarry Smith /* -----------------------------------------------------------------------------------------*/ 573d4bb536fSBarry Smith 5744a2ae208SSatish Balay #undef __FUNCT__ 5754a2ae208SSatish Balay #define __FUNCT__ "ISGlobalToLocalMappingSetUp_Private" 576d4bb536fSBarry Smith /* 577d4bb536fSBarry Smith Creates the global fields in the ISLocalToGlobalMapping structure 578d4bb536fSBarry Smith */ 5796849ba73SBarry Smith static PetscErrorCode ISGlobalToLocalMappingSetUp_Private(ISLocalToGlobalMapping mapping) 580d4bb536fSBarry Smith { 5816849ba73SBarry Smith PetscErrorCode ierr; 58232dcc486SBarry Smith PetscInt i,*idx = mapping->indices,n = mapping->n,end,start,*globals; 583d4bb536fSBarry Smith 5843a40ed3dSBarry Smith PetscFunctionBegin; 585d4bb536fSBarry Smith end = 0; 586ec268f7cSJed Brown start = PETSC_MAX_INT; 587d4bb536fSBarry Smith 588d4bb536fSBarry Smith for (i=0; i<n; i++) { 589d4bb536fSBarry Smith if (idx[i] < 0) continue; 590d4bb536fSBarry Smith if (idx[i] < start) start = idx[i]; 591d4bb536fSBarry Smith if (idx[i] > end) end = idx[i]; 592d4bb536fSBarry Smith } 593d4bb536fSBarry Smith if (start > end) {start = 0; end = -1;} 594d4bb536fSBarry Smith mapping->globalstart = start; 595d4bb536fSBarry Smith mapping->globalend = end; 596d4bb536fSBarry Smith 597854ce69bSBarry Smith ierr = PetscMalloc1(end-start+2,&globals);CHKERRQ(ierr); 598b0a32e0cSBarry Smith mapping->globals = globals; 599f6e5521dSKarl Rupp for (i=0; i<end-start+1; i++) globals[i] = -1; 600d4bb536fSBarry Smith for (i=0; i<n; i++) { 601d4bb536fSBarry Smith if (idx[i] < 0) continue; 602d4bb536fSBarry Smith globals[idx[i] - start] = i; 603d4bb536fSBarry Smith } 604d4bb536fSBarry Smith 6053bb1ff40SBarry Smith ierr = PetscLogObjectMemory((PetscObject)mapping,(end-start+1)*sizeof(PetscInt));CHKERRQ(ierr); 6063a40ed3dSBarry Smith PetscFunctionReturn(0); 607d4bb536fSBarry Smith } 608d4bb536fSBarry Smith 6094a2ae208SSatish Balay #undef __FUNCT__ 6104a2ae208SSatish Balay #define __FUNCT__ "ISGlobalToLocalMappingApply" 611d4bb536fSBarry Smith /*@ 612a997ad1aSLois Curfman McInnes ISGlobalToLocalMappingApply - Provides the local numbering for a list of integers 613a997ad1aSLois Curfman McInnes specified with a global numbering. 614d4bb536fSBarry Smith 615b9cd556bSLois Curfman McInnes Not collective 616b9cd556bSLois Curfman McInnes 617d4bb536fSBarry Smith Input Parameters: 618b9cd556bSLois Curfman McInnes + mapping - mapping between local and global numbering 619d4bb536fSBarry Smith . type - IS_GTOLM_MASK - replaces global indices with no local value with -1 620d4bb536fSBarry Smith IS_GTOLM_DROP - drops the indices with no local value from the output list 621d4bb536fSBarry Smith . n - number of global indices to map 622b9cd556bSLois Curfman McInnes - idx - global indices to map 623d4bb536fSBarry Smith 624d4bb536fSBarry Smith Output Parameters: 625b9cd556bSLois Curfman McInnes + nout - number of indices in output array (if type == IS_GTOLM_MASK then nout = n) 626b9cd556bSLois Curfman McInnes - idxout - local index of each global index, one must pass in an array long enough 627e182c471SBarry Smith to hold all the indices. You can call ISGlobalToLocalMappingApply() with 6280298fd71SBarry Smith idxout == NULL to determine the required length (returned in nout) 629e182c471SBarry Smith and then allocate the required space and call ISGlobalToLocalMappingApply() 630e182c471SBarry Smith a second time to set the values. 631d4bb536fSBarry Smith 632b9cd556bSLois Curfman McInnes Notes: 6330298fd71SBarry Smith Either nout or idxout may be NULL. idx and idxout may be identical. 634d4bb536fSBarry Smith 6350f5bd95cSBarry Smith This is not scalable in memory usage. Each processor requires O(Nglobal) size 6360f5bd95cSBarry Smith array to compute these. 6370f5bd95cSBarry Smith 638a997ad1aSLois Curfman McInnes Level: advanced 639a997ad1aSLois Curfman McInnes 64032fd6b96SBarry Smith Developer Note: The manual page states that idx and idxout may be identical but the calling 64132fd6b96SBarry Smith sequence declares idx as const so it cannot be the same as idxout. 64232fd6b96SBarry Smith 643273d9f13SBarry Smith Concepts: mapping^global to local 644d4bb536fSBarry Smith 6459d90f715SBarry Smith .seealso: ISLocalToGlobalMappingApply(), ISGlobalToLocalMappingApplyBlock(), ISLocalToGlobalMappingCreate(), 646d4bb536fSBarry Smith ISLocalToGlobalMappingDestroy() 647d4bb536fSBarry Smith @*/ 6487087cfbeSBarry Smith PetscErrorCode ISGlobalToLocalMappingApply(ISLocalToGlobalMapping mapping,ISGlobalToLocalMappingType type, 64932dcc486SBarry Smith PetscInt n,const PetscInt idx[],PetscInt *nout,PetscInt idxout[]) 650d4bb536fSBarry Smith { 6519d90f715SBarry Smith PetscInt i,*globals,nf = 0,tmp,start,end,bs; 6529d90f715SBarry Smith PetscErrorCode ierr; 6539d90f715SBarry Smith 6549d90f715SBarry Smith PetscFunctionBegin; 6559d90f715SBarry Smith PetscValidHeaderSpecific(mapping,IS_LTOGM_CLASSID,1); 6569d90f715SBarry Smith if (!mapping->globals) { 6579d90f715SBarry Smith ierr = ISGlobalToLocalMappingSetUp_Private(mapping);CHKERRQ(ierr); 6589d90f715SBarry Smith } 6599d90f715SBarry Smith globals = mapping->globals; 6609d90f715SBarry Smith start = mapping->globalstart; 6619d90f715SBarry Smith end = mapping->globalend; 6629d90f715SBarry Smith bs = mapping->bs; 6639d90f715SBarry Smith 6649d90f715SBarry Smith if (type == IS_GTOLM_MASK) { 6659d90f715SBarry Smith if (idxout) { 6669d90f715SBarry Smith for (i=0; i<n; i++) { 6679d90f715SBarry Smith if (idx[i] < 0) idxout[i] = idx[i]; 6689d90f715SBarry Smith else if (idx[i] < bs*start) idxout[i] = -1; 669663bb84eSBarry Smith else if (idx[i] > bs*(end+1)-1) idxout[i] = -1; 6709d90f715SBarry Smith else idxout[i] = bs*globals[idx[i]/bs - start] + (idx[i] % bs); 6719d90f715SBarry Smith } 6729d90f715SBarry Smith } 6739d90f715SBarry Smith if (nout) *nout = n; 6749d90f715SBarry Smith } else { 6759d90f715SBarry Smith if (idxout) { 6769d90f715SBarry Smith for (i=0; i<n; i++) { 6779d90f715SBarry Smith if (idx[i] < 0) continue; 6789d90f715SBarry Smith if (idx[i] < bs*start) continue; 679663bb84eSBarry Smith if (idx[i] > bs*(end+1)-1) continue; 6809d90f715SBarry Smith tmp = bs*globals[idx[i]/bs - start] + (idx[i] % bs); 6819d90f715SBarry Smith if (tmp < 0) continue; 6829d90f715SBarry Smith idxout[nf++] = tmp; 6839d90f715SBarry Smith } 6849d90f715SBarry Smith } else { 6859d90f715SBarry Smith for (i=0; i<n; i++) { 6869d90f715SBarry Smith if (idx[i] < 0) continue; 6879d90f715SBarry Smith if (idx[i] < bs*start) continue; 688663bb84eSBarry Smith if (idx[i] > bs*(end+1)-1) continue; 6899d90f715SBarry Smith tmp = bs*globals[idx[i]/bs - start] + (idx[i] % bs); 6909d90f715SBarry Smith if (tmp < 0) continue; 6919d90f715SBarry Smith nf++; 6929d90f715SBarry Smith } 6939d90f715SBarry Smith } 6949d90f715SBarry Smith if (nout) *nout = nf; 6959d90f715SBarry Smith } 6969d90f715SBarry Smith PetscFunctionReturn(0); 6979d90f715SBarry Smith } 6989d90f715SBarry Smith 6999d90f715SBarry Smith #undef __FUNCT__ 700d4fe737eSStefano Zampini #define __FUNCT__ "ISGlobalToLocalMappingApplyIS" 701d4fe737eSStefano Zampini /*@ 702d4fe737eSStefano Zampini ISGlobalToLocalMappingApplyIS - Creates from an IS in the global numbering 703d4fe737eSStefano Zampini a new index set using the local numbering defined in an ISLocalToGlobalMapping 704d4fe737eSStefano Zampini context. 705d4fe737eSStefano Zampini 706d4fe737eSStefano Zampini Not collective 707d4fe737eSStefano Zampini 708d4fe737eSStefano Zampini Input Parameters: 709d4fe737eSStefano Zampini + mapping - mapping between local and global numbering 710d4fe737eSStefano Zampini - is - index set in global numbering 711d4fe737eSStefano Zampini 712d4fe737eSStefano Zampini Output Parameters: 713d4fe737eSStefano Zampini . newis - index set in local numbering 714d4fe737eSStefano Zampini 715d4fe737eSStefano Zampini Level: advanced 716d4fe737eSStefano Zampini 717d4fe737eSStefano Zampini Concepts: mapping^local to global 718d4fe737eSStefano Zampini 719d4fe737eSStefano Zampini .seealso: ISGlobalToLocalMappingApply(), ISLocalToGlobalMappingCreate(), 720d4fe737eSStefano Zampini ISLocalToGlobalMappingDestroy() 721d4fe737eSStefano Zampini @*/ 722d4fe737eSStefano Zampini PetscErrorCode ISGlobalToLocalMappingApplyIS(ISLocalToGlobalMapping mapping,ISGlobalToLocalMappingType type, IS is,IS *newis) 723d4fe737eSStefano Zampini { 724d4fe737eSStefano Zampini PetscErrorCode ierr; 725d4fe737eSStefano Zampini PetscInt n,nout,*idxout; 726d4fe737eSStefano Zampini const PetscInt *idxin; 727d4fe737eSStefano Zampini 728d4fe737eSStefano Zampini PetscFunctionBegin; 729d4fe737eSStefano Zampini PetscValidHeaderSpecific(mapping,IS_LTOGM_CLASSID,1); 730d4fe737eSStefano Zampini PetscValidHeaderSpecific(is,IS_CLASSID,3); 731d4fe737eSStefano Zampini PetscValidPointer(newis,4); 732d4fe737eSStefano Zampini 733d4fe737eSStefano Zampini ierr = ISGetLocalSize(is,&n);CHKERRQ(ierr); 734d4fe737eSStefano Zampini ierr = ISGetIndices(is,&idxin);CHKERRQ(ierr); 735d4fe737eSStefano Zampini if (type == IS_GTOLM_MASK) { 736d4fe737eSStefano Zampini ierr = PetscMalloc1(n,&idxout);CHKERRQ(ierr); 737d4fe737eSStefano Zampini } else { 738d4fe737eSStefano Zampini ierr = ISGlobalToLocalMappingApply(mapping,type,n,idxin,&nout,NULL);CHKERRQ(ierr); 739d4fe737eSStefano Zampini ierr = PetscMalloc1(nout,&idxout);CHKERRQ(ierr); 740d4fe737eSStefano Zampini } 741d4fe737eSStefano Zampini ierr = ISGlobalToLocalMappingApply(mapping,type,n,idxin,&nout,idxout);CHKERRQ(ierr); 742d4fe737eSStefano Zampini ierr = ISRestoreIndices(is,&idxin);CHKERRQ(ierr); 743d4fe737eSStefano Zampini ierr = ISCreateGeneral(PetscObjectComm((PetscObject)is),nout,idxout,PETSC_OWN_POINTER,newis);CHKERRQ(ierr); 744d4fe737eSStefano Zampini PetscFunctionReturn(0); 745d4fe737eSStefano Zampini } 746d4fe737eSStefano Zampini 747d4fe737eSStefano Zampini #undef __FUNCT__ 7489d90f715SBarry Smith #define __FUNCT__ "ISGlobalToLocalMappingApplyBlock" 7499d90f715SBarry Smith /*@ 7509d90f715SBarry Smith ISGlobalToLocalMappingApplyBlock - Provides the local block numbering for a list of integers 7519d90f715SBarry Smith specified with a block global numbering. 7529d90f715SBarry Smith 7539d90f715SBarry Smith Not collective 7549d90f715SBarry Smith 7559d90f715SBarry Smith Input Parameters: 7569d90f715SBarry Smith + mapping - mapping between local and global numbering 7579d90f715SBarry Smith . type - IS_GTOLM_MASK - replaces global indices with no local value with -1 7589d90f715SBarry Smith IS_GTOLM_DROP - drops the indices with no local value from the output list 7599d90f715SBarry Smith . n - number of global indices to map 7609d90f715SBarry Smith - idx - global indices to map 7619d90f715SBarry Smith 7629d90f715SBarry Smith Output Parameters: 7639d90f715SBarry Smith + nout - number of indices in output array (if type == IS_GTOLM_MASK then nout = n) 7649d90f715SBarry Smith - idxout - local index of each global index, one must pass in an array long enough 7659d90f715SBarry Smith to hold all the indices. You can call ISGlobalToLocalMappingApplyBlock() with 7669d90f715SBarry Smith idxout == NULL to determine the required length (returned in nout) 7679d90f715SBarry Smith and then allocate the required space and call ISGlobalToLocalMappingApplyBlock() 7689d90f715SBarry Smith a second time to set the values. 7699d90f715SBarry Smith 7709d90f715SBarry Smith Notes: 7719d90f715SBarry Smith Either nout or idxout may be NULL. idx and idxout may be identical. 7729d90f715SBarry Smith 7739d90f715SBarry Smith This is not scalable in memory usage. Each processor requires O(Nglobal) size 7749d90f715SBarry Smith array to compute these. 7759d90f715SBarry Smith 7769d90f715SBarry Smith Level: advanced 7779d90f715SBarry Smith 7789d90f715SBarry Smith Developer Note: The manual page states that idx and idxout may be identical but the calling 7799d90f715SBarry Smith sequence declares idx as const so it cannot be the same as idxout. 7809d90f715SBarry Smith 7819d90f715SBarry Smith Concepts: mapping^global to local 7829d90f715SBarry Smith 7839d90f715SBarry Smith .seealso: ISLocalToGlobalMappingApply(), ISGlobalToLocalMappingApply(), ISLocalToGlobalMappingCreate(), 7849d90f715SBarry Smith ISLocalToGlobalMappingDestroy() 7859d90f715SBarry Smith @*/ 7869d90f715SBarry Smith PetscErrorCode ISGlobalToLocalMappingApplyBlock(ISLocalToGlobalMapping mapping,ISGlobalToLocalMappingType type, 7879d90f715SBarry Smith PetscInt n,const PetscInt idx[],PetscInt *nout,PetscInt idxout[]) 7889d90f715SBarry Smith { 78932dcc486SBarry Smith PetscInt i,*globals,nf = 0,tmp,start,end; 7906849ba73SBarry Smith PetscErrorCode ierr; 791d4bb536fSBarry Smith 7923a40ed3dSBarry Smith PetscFunctionBegin; 7930700a824SBarry Smith PetscValidHeaderSpecific(mapping,IS_LTOGM_CLASSID,1); 794d4bb536fSBarry Smith if (!mapping->globals) { 795d4bb536fSBarry Smith ierr = ISGlobalToLocalMappingSetUp_Private(mapping);CHKERRQ(ierr); 796d4bb536fSBarry Smith } 797d4bb536fSBarry Smith globals = mapping->globals; 798d4bb536fSBarry Smith start = mapping->globalstart; 799d4bb536fSBarry Smith end = mapping->globalend; 800d4bb536fSBarry Smith 801d4bb536fSBarry Smith if (type == IS_GTOLM_MASK) { 802d4bb536fSBarry Smith if (idxout) { 803d4bb536fSBarry Smith for (i=0; i<n; i++) { 804d4bb536fSBarry Smith if (idx[i] < 0) idxout[i] = idx[i]; 805d4bb536fSBarry Smith else if (idx[i] < start) idxout[i] = -1; 806d4bb536fSBarry Smith else if (idx[i] > end) idxout[i] = -1; 807d4bb536fSBarry Smith else idxout[i] = globals[idx[i] - start]; 808d4bb536fSBarry Smith } 809d4bb536fSBarry Smith } 810d4bb536fSBarry Smith if (nout) *nout = n; 811d4bb536fSBarry Smith } else { 812d4bb536fSBarry Smith if (idxout) { 813d4bb536fSBarry Smith for (i=0; i<n; i++) { 814d4bb536fSBarry Smith if (idx[i] < 0) continue; 815d4bb536fSBarry Smith if (idx[i] < start) continue; 816d4bb536fSBarry Smith if (idx[i] > end) continue; 817d4bb536fSBarry Smith tmp = globals[idx[i] - start]; 818d4bb536fSBarry Smith if (tmp < 0) continue; 819d4bb536fSBarry Smith idxout[nf++] = tmp; 820d4bb536fSBarry Smith } 821d4bb536fSBarry Smith } else { 822d4bb536fSBarry Smith for (i=0; i<n; i++) { 823d4bb536fSBarry Smith if (idx[i] < 0) continue; 824d4bb536fSBarry Smith if (idx[i] < start) continue; 825d4bb536fSBarry Smith if (idx[i] > end) continue; 826d4bb536fSBarry Smith tmp = globals[idx[i] - start]; 827d4bb536fSBarry Smith if (tmp < 0) continue; 828d4bb536fSBarry Smith nf++; 829d4bb536fSBarry Smith } 830d4bb536fSBarry Smith } 831d4bb536fSBarry Smith if (nout) *nout = nf; 832d4bb536fSBarry Smith } 8333a40ed3dSBarry Smith PetscFunctionReturn(0); 834d4bb536fSBarry Smith } 83590f02eecSBarry Smith 8364a2ae208SSatish Balay #undef __FUNCT__ 8376a818285SBarry Smith #define __FUNCT__ "ISLocalToGlobalMappingGetBlockInfo" 83889d82c54SBarry Smith /*@C 8396a818285SBarry Smith ISLocalToGlobalMappingGetBlockInfo - Gets the neighbor information for each processor and 84089d82c54SBarry Smith each index shared by more than one processor 84189d82c54SBarry Smith 84289d82c54SBarry Smith Collective on ISLocalToGlobalMapping 84389d82c54SBarry Smith 84489d82c54SBarry Smith Input Parameters: 84589d82c54SBarry Smith . mapping - the mapping from local to global indexing 84689d82c54SBarry Smith 84789d82c54SBarry Smith Output Parameter: 84889d82c54SBarry Smith + nproc - number of processors that are connected to this one 84989d82c54SBarry Smith . proc - neighboring processors 85007b52d57SBarry Smith . numproc - number of indices for each subdomain (processor) 8513463a7baSJed Brown - indices - indices of nodes (in local numbering) shared with neighbors (sorted by global numbering) 85289d82c54SBarry Smith 85389d82c54SBarry Smith Level: advanced 85489d82c54SBarry Smith 855273d9f13SBarry Smith Concepts: mapping^local to global 85689d82c54SBarry Smith 8572cfcea29SBarry Smith Fortran Usage: 8582cfcea29SBarry Smith $ ISLocalToGlobalMpngGetInfoSize(ISLocalToGlobalMapping,PetscInt nproc,PetscInt numprocmax,ierr) followed by 8592cfcea29SBarry Smith $ ISLocalToGlobalMappingGetInfo(ISLocalToGlobalMapping,PetscInt nproc, PetscInt procs[nproc],PetscInt numprocs[nproc], 8602cfcea29SBarry Smith PetscInt indices[nproc][numprocmax],ierr) 8612cfcea29SBarry Smith There is no ISLocalToGlobalMappingRestoreInfo() in Fortran. You must make sure that procs[], numprocs[] and 8622cfcea29SBarry Smith indices[][] are large enough arrays, either by allocating them dynamically or defining static ones large enough. 8632cfcea29SBarry Smith 8642cfcea29SBarry Smith 86507b52d57SBarry Smith .seealso: ISLocalToGlobalMappingDestroy(), ISLocalToGlobalMappingCreateIS(), ISLocalToGlobalMappingCreate(), 86607b52d57SBarry Smith ISLocalToGlobalMappingRestoreInfo() 86789d82c54SBarry Smith @*/ 8686a818285SBarry Smith PetscErrorCode ISLocalToGlobalMappingGetBlockInfo(ISLocalToGlobalMapping mapping,PetscInt *nproc,PetscInt *procs[],PetscInt *numprocs[],PetscInt **indices[]) 86989d82c54SBarry Smith { 8706849ba73SBarry Smith PetscErrorCode ierr; 871268a049cSStefano Zampini 872268a049cSStefano Zampini PetscFunctionBegin; 873268a049cSStefano Zampini PetscValidHeaderSpecific(mapping,IS_LTOGM_CLASSID,1); 874268a049cSStefano Zampini if (mapping->info_cached) { 875268a049cSStefano Zampini *nproc = mapping->info_nproc; 876268a049cSStefano Zampini *procs = mapping->info_procs; 877268a049cSStefano Zampini *numprocs = mapping->info_numprocs; 878268a049cSStefano Zampini *indices = mapping->info_indices; 879268a049cSStefano Zampini } else { 880268a049cSStefano Zampini ierr = ISLocalToGlobalMappingGetBlockInfo_Private(mapping,nproc,procs,numprocs,indices);CHKERRQ(ierr); 881268a049cSStefano Zampini } 882268a049cSStefano Zampini PetscFunctionReturn(0); 883268a049cSStefano Zampini } 884268a049cSStefano Zampini 885268a049cSStefano Zampini #undef __FUNCT__ 886268a049cSStefano Zampini #define __FUNCT__ "ISLocalToGlobalMappingGetBlockInfo_Private" 887268a049cSStefano Zampini static PetscErrorCode ISLocalToGlobalMappingGetBlockInfo_Private(ISLocalToGlobalMapping mapping,PetscInt *nproc,PetscInt *procs[],PetscInt *numprocs[],PetscInt **indices[]) 888268a049cSStefano Zampini { 889268a049cSStefano Zampini PetscErrorCode ierr; 89097f1f81fSBarry Smith PetscMPIInt size,rank,tag1,tag2,tag3,*len,*source,imdex; 89132dcc486SBarry Smith PetscInt i,n = mapping->n,Ng,ng,max = 0,*lindices = mapping->indices; 89232dcc486SBarry Smith PetscInt *nprocs,*owner,nsends,*sends,j,*starts,nmax,nrecvs,*recvs,proc; 89397f1f81fSBarry Smith PetscInt cnt,scale,*ownedsenders,*nownedsenders,rstart,nowned; 89432dcc486SBarry Smith PetscInt node,nownedm,nt,*sends2,nsends2,*starts2,*lens2,*dest,nrecvs2,*starts3,*recvs2,k,*bprocs,*tmp; 89532dcc486SBarry Smith PetscInt first_procs,first_numprocs,*first_indices; 89689d82c54SBarry Smith MPI_Request *recv_waits,*send_waits; 89730dcb7c9SBarry Smith MPI_Status recv_status,*send_status,*recv_statuses; 898ce94432eSBarry Smith MPI_Comm comm; 899ace3abfcSBarry Smith PetscBool debug = PETSC_FALSE; 90089d82c54SBarry Smith 90189d82c54SBarry Smith PetscFunctionBegin; 902ce94432eSBarry Smith ierr = PetscObjectGetComm((PetscObject)mapping,&comm);CHKERRQ(ierr); 90324cf384cSBarry Smith ierr = MPI_Comm_size(comm,&size);CHKERRQ(ierr); 90424cf384cSBarry Smith ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr); 90524cf384cSBarry Smith if (size == 1) { 90624cf384cSBarry Smith *nproc = 0; 9070298fd71SBarry Smith *procs = NULL; 90895dccacaSBarry Smith ierr = PetscNew(numprocs);CHKERRQ(ierr); 9091e2105dcSBarry Smith (*numprocs)[0] = 0; 91095dccacaSBarry Smith ierr = PetscNew(indices);CHKERRQ(ierr); 9110298fd71SBarry Smith (*indices)[0] = NULL; 912268a049cSStefano Zampini /* save info for reuse */ 913268a049cSStefano Zampini mapping->info_nproc = *nproc; 914268a049cSStefano Zampini mapping->info_procs = *procs; 915268a049cSStefano Zampini mapping->info_numprocs = *numprocs; 916268a049cSStefano Zampini mapping->info_indices = *indices; 917268a049cSStefano Zampini mapping->info_cached = PETSC_TRUE; 91824cf384cSBarry Smith PetscFunctionReturn(0); 91924cf384cSBarry Smith } 92024cf384cSBarry Smith 921c5929fdfSBarry Smith ierr = PetscOptionsGetBool(((PetscObject)mapping)->options,NULL,"-islocaltoglobalmappinggetinfo_debug",&debug,NULL);CHKERRQ(ierr); 92207b52d57SBarry Smith 9233677ff5aSBarry Smith /* 9246a818285SBarry Smith Notes on ISLocalToGlobalMappingGetBlockInfo 9253677ff5aSBarry Smith 9263677ff5aSBarry Smith globally owned node - the nodes that have been assigned to this processor in global 9273677ff5aSBarry Smith numbering, just for this routine. 9283677ff5aSBarry Smith 9293677ff5aSBarry Smith nontrivial globally owned node - node assigned to this processor that is on a subdomain 9303677ff5aSBarry Smith boundary (i.e. is has more than one local owner) 9313677ff5aSBarry Smith 9323677ff5aSBarry Smith locally owned node - node that exists on this processors subdomain 9333677ff5aSBarry Smith 9343677ff5aSBarry Smith nontrivial locally owned node - node that is not in the interior (i.e. has more than one 9353677ff5aSBarry Smith local subdomain 9363677ff5aSBarry Smith */ 93724cf384cSBarry Smith ierr = PetscObjectGetNewTag((PetscObject)mapping,&tag1);CHKERRQ(ierr); 93824cf384cSBarry Smith ierr = PetscObjectGetNewTag((PetscObject)mapping,&tag2);CHKERRQ(ierr); 93924cf384cSBarry Smith ierr = PetscObjectGetNewTag((PetscObject)mapping,&tag3);CHKERRQ(ierr); 94089d82c54SBarry Smith 94189d82c54SBarry Smith for (i=0; i<n; i++) { 94289d82c54SBarry Smith if (lindices[i] > max) max = lindices[i]; 94389d82c54SBarry Smith } 944b2566f29SBarry Smith ierr = MPIU_Allreduce(&max,&Ng,1,MPIU_INT,MPI_MAX,comm);CHKERRQ(ierr); 94578058e43SBarry Smith Ng++; 94689d82c54SBarry Smith ierr = MPI_Comm_size(comm,&size);CHKERRQ(ierr); 94789d82c54SBarry Smith ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr); 948bc8ff85bSBarry Smith scale = Ng/size + 1; 949a2e34c3dSBarry Smith ng = scale; if (rank == size-1) ng = Ng - scale*(size-1); ng = PetscMax(1,ng); 950caba0dd0SBarry Smith rstart = scale*rank; 95189d82c54SBarry Smith 95289d82c54SBarry Smith /* determine ownership ranges of global indices */ 953785e854fSJed Brown ierr = PetscMalloc1(2*size,&nprocs);CHKERRQ(ierr); 95432dcc486SBarry Smith ierr = PetscMemzero(nprocs,2*size*sizeof(PetscInt));CHKERRQ(ierr); 95589d82c54SBarry Smith 95689d82c54SBarry Smith /* determine owners of each local node */ 957785e854fSJed Brown ierr = PetscMalloc1(n,&owner);CHKERRQ(ierr); 95889d82c54SBarry Smith for (i=0; i<n; i++) { 9593677ff5aSBarry Smith proc = lindices[i]/scale; /* processor that globally owns this index */ 96027c402fcSBarry Smith nprocs[2*proc+1] = 1; /* processor globally owns at least one of ours */ 9613677ff5aSBarry Smith owner[i] = proc; 96227c402fcSBarry Smith nprocs[2*proc]++; /* count of how many that processor globally owns of ours */ 96389d82c54SBarry Smith } 96427c402fcSBarry Smith nsends = 0; for (i=0; i<size; i++) nsends += nprocs[2*i+1]; 9657904a332SBarry Smith ierr = PetscInfo1(mapping,"Number of global owners for my local data %D\n",nsends);CHKERRQ(ierr); 96689d82c54SBarry Smith 96789d82c54SBarry Smith /* inform other processors of number of messages and max length*/ 96827c402fcSBarry Smith ierr = PetscMaxSum(comm,nprocs,&nmax,&nrecvs);CHKERRQ(ierr); 9697904a332SBarry Smith ierr = PetscInfo1(mapping,"Number of local owners for my global data %D\n",nrecvs);CHKERRQ(ierr); 97089d82c54SBarry Smith 97189d82c54SBarry Smith /* post receives for owned rows */ 972785e854fSJed Brown ierr = PetscMalloc1((2*nrecvs+1)*(nmax+1),&recvs);CHKERRQ(ierr); 973854ce69bSBarry Smith ierr = PetscMalloc1(nrecvs+1,&recv_waits);CHKERRQ(ierr); 97489d82c54SBarry Smith for (i=0; i<nrecvs; i++) { 97532dcc486SBarry Smith ierr = MPI_Irecv(recvs+2*nmax*i,2*nmax,MPIU_INT,MPI_ANY_SOURCE,tag1,comm,recv_waits+i);CHKERRQ(ierr); 97689d82c54SBarry Smith } 97789d82c54SBarry Smith 97889d82c54SBarry Smith /* pack messages containing lists of local nodes to owners */ 979854ce69bSBarry Smith ierr = PetscMalloc1(2*n+1,&sends);CHKERRQ(ierr); 980854ce69bSBarry Smith ierr = PetscMalloc1(size+1,&starts);CHKERRQ(ierr); 98189d82c54SBarry Smith starts[0] = 0; 982f6e5521dSKarl Rupp for (i=1; i<size; i++) starts[i] = starts[i-1] + 2*nprocs[2*i-2]; 98389d82c54SBarry Smith for (i=0; i<n; i++) { 98489d82c54SBarry Smith sends[starts[owner[i]]++] = lindices[i]; 98530dcb7c9SBarry Smith sends[starts[owner[i]]++] = i; 98689d82c54SBarry Smith } 98789d82c54SBarry Smith ierr = PetscFree(owner);CHKERRQ(ierr); 98889d82c54SBarry Smith starts[0] = 0; 989f6e5521dSKarl Rupp for (i=1; i<size; i++) starts[i] = starts[i-1] + 2*nprocs[2*i-2]; 99089d82c54SBarry Smith 99189d82c54SBarry Smith /* send the messages */ 992854ce69bSBarry Smith ierr = PetscMalloc1(nsends+1,&send_waits);CHKERRQ(ierr); 993854ce69bSBarry Smith ierr = PetscMalloc1(nsends+1,&dest);CHKERRQ(ierr); 99489d82c54SBarry Smith cnt = 0; 99589d82c54SBarry Smith for (i=0; i<size; i++) { 99627c402fcSBarry Smith if (nprocs[2*i]) { 99732dcc486SBarry Smith ierr = MPI_Isend(sends+starts[i],2*nprocs[2*i],MPIU_INT,i,tag1,comm,send_waits+cnt);CHKERRQ(ierr); 99830dcb7c9SBarry Smith dest[cnt] = i; 99989d82c54SBarry Smith cnt++; 100089d82c54SBarry Smith } 100189d82c54SBarry Smith } 100289d82c54SBarry Smith ierr = PetscFree(starts);CHKERRQ(ierr); 100389d82c54SBarry Smith 100489d82c54SBarry Smith /* wait on receives */ 1005854ce69bSBarry Smith ierr = PetscMalloc1(nrecvs+1,&source);CHKERRQ(ierr); 1006854ce69bSBarry Smith ierr = PetscMalloc1(nrecvs+1,&len);CHKERRQ(ierr); 100789d82c54SBarry Smith cnt = nrecvs; 1008854ce69bSBarry Smith ierr = PetscMalloc1(ng+1,&nownedsenders);CHKERRQ(ierr); 100932dcc486SBarry Smith ierr = PetscMemzero(nownedsenders,ng*sizeof(PetscInt));CHKERRQ(ierr); 101089d82c54SBarry Smith while (cnt) { 101189d82c54SBarry Smith ierr = MPI_Waitany(nrecvs,recv_waits,&imdex,&recv_status);CHKERRQ(ierr); 101289d82c54SBarry Smith /* unpack receives into our local space */ 101332dcc486SBarry Smith ierr = MPI_Get_count(&recv_status,MPIU_INT,&len[imdex]);CHKERRQ(ierr); 101489d82c54SBarry Smith source[imdex] = recv_status.MPI_SOURCE; 101530dcb7c9SBarry Smith len[imdex] = len[imdex]/2; 1016caba0dd0SBarry Smith /* count how many local owners for each of my global owned indices */ 101730dcb7c9SBarry Smith for (i=0; i<len[imdex]; i++) nownedsenders[recvs[2*imdex*nmax+2*i]-rstart]++; 101889d82c54SBarry Smith cnt--; 101989d82c54SBarry Smith } 102089d82c54SBarry Smith ierr = PetscFree(recv_waits);CHKERRQ(ierr); 102189d82c54SBarry Smith 102230dcb7c9SBarry Smith /* count how many globally owned indices are on an edge multiplied by how many processors own them. */ 1023bc8ff85bSBarry Smith nowned = 0; 1024bc8ff85bSBarry Smith nownedm = 0; 1025bc8ff85bSBarry Smith for (i=0; i<ng; i++) { 1026bc8ff85bSBarry Smith if (nownedsenders[i] > 1) {nownedm += nownedsenders[i]; nowned++;} 1027bc8ff85bSBarry Smith } 1028bc8ff85bSBarry Smith 1029bc8ff85bSBarry Smith /* create single array to contain rank of all local owners of each globally owned index */ 1030854ce69bSBarry Smith ierr = PetscMalloc1(nownedm+1,&ownedsenders);CHKERRQ(ierr); 1031854ce69bSBarry Smith ierr = PetscMalloc1(ng+1,&starts);CHKERRQ(ierr); 1032bc8ff85bSBarry Smith starts[0] = 0; 1033bc8ff85bSBarry Smith for (i=1; i<ng; i++) { 1034bc8ff85bSBarry Smith if (nownedsenders[i-1] > 1) starts[i] = starts[i-1] + nownedsenders[i-1]; 1035bc8ff85bSBarry Smith else starts[i] = starts[i-1]; 1036bc8ff85bSBarry Smith } 1037bc8ff85bSBarry Smith 103830dcb7c9SBarry Smith /* for each nontrival globally owned node list all arriving processors */ 1039bc8ff85bSBarry Smith for (i=0; i<nrecvs; i++) { 1040bc8ff85bSBarry Smith for (j=0; j<len[i]; j++) { 104130dcb7c9SBarry Smith node = recvs[2*i*nmax+2*j]-rstart; 1042f6e5521dSKarl Rupp if (nownedsenders[node] > 1) ownedsenders[starts[node]++] = source[i]; 1043bc8ff85bSBarry Smith } 1044bc8ff85bSBarry Smith } 1045bc8ff85bSBarry Smith 104607b52d57SBarry Smith if (debug) { /* ----------------------------------- */ 104730dcb7c9SBarry Smith starts[0] = 0; 104830dcb7c9SBarry Smith for (i=1; i<ng; i++) { 104930dcb7c9SBarry Smith if (nownedsenders[i-1] > 1) starts[i] = starts[i-1] + nownedsenders[i-1]; 105030dcb7c9SBarry Smith else starts[i] = starts[i-1]; 105130dcb7c9SBarry Smith } 105230dcb7c9SBarry Smith for (i=0; i<ng; i++) { 105330dcb7c9SBarry Smith if (nownedsenders[i] > 1) { 10547904a332SBarry Smith ierr = PetscSynchronizedPrintf(comm,"[%d] global node %D local owner processors: ",rank,i+rstart);CHKERRQ(ierr); 105530dcb7c9SBarry Smith for (j=0; j<nownedsenders[i]; j++) { 10567904a332SBarry Smith ierr = PetscSynchronizedPrintf(comm,"%D ",ownedsenders[starts[i]+j]);CHKERRQ(ierr); 105730dcb7c9SBarry Smith } 105830dcb7c9SBarry Smith ierr = PetscSynchronizedPrintf(comm,"\n");CHKERRQ(ierr); 105930dcb7c9SBarry Smith } 106030dcb7c9SBarry Smith } 10610ec8b6e3SBarry Smith ierr = PetscSynchronizedFlush(comm,PETSC_STDOUT);CHKERRQ(ierr); 106207b52d57SBarry Smith } /* ----------------------------------- */ 106330dcb7c9SBarry Smith 10643677ff5aSBarry Smith /* wait on original sends */ 10653a96401aSBarry Smith if (nsends) { 1066785e854fSJed Brown ierr = PetscMalloc1(nsends,&send_status);CHKERRQ(ierr); 10673a96401aSBarry Smith ierr = MPI_Waitall(nsends,send_waits,send_status);CHKERRQ(ierr); 10683a96401aSBarry Smith ierr = PetscFree(send_status);CHKERRQ(ierr); 10693a96401aSBarry Smith } 107089d82c54SBarry Smith ierr = PetscFree(send_waits);CHKERRQ(ierr); 10713a96401aSBarry Smith ierr = PetscFree(sends);CHKERRQ(ierr); 10723677ff5aSBarry Smith ierr = PetscFree(nprocs);CHKERRQ(ierr); 10733677ff5aSBarry Smith 10743677ff5aSBarry Smith /* pack messages to send back to local owners */ 107530dcb7c9SBarry Smith starts[0] = 0; 107630dcb7c9SBarry Smith for (i=1; i<ng; i++) { 107730dcb7c9SBarry Smith if (nownedsenders[i-1] > 1) starts[i] = starts[i-1] + nownedsenders[i-1]; 107830dcb7c9SBarry Smith else starts[i] = starts[i-1]; 107930dcb7c9SBarry Smith } 108030dcb7c9SBarry Smith nsends2 = nrecvs; 1081854ce69bSBarry Smith ierr = PetscMalloc1(nsends2+1,&nprocs);CHKERRQ(ierr); /* length of each message */ 108230dcb7c9SBarry Smith for (i=0; i<nrecvs; i++) { 108330dcb7c9SBarry Smith nprocs[i] = 1; 108430dcb7c9SBarry Smith for (j=0; j<len[i]; j++) { 108530dcb7c9SBarry Smith node = recvs[2*i*nmax+2*j]-rstart; 1086f6e5521dSKarl Rupp if (nownedsenders[node] > 1) nprocs[i] += 2 + nownedsenders[node]; 108730dcb7c9SBarry Smith } 108830dcb7c9SBarry Smith } 1089f6e5521dSKarl Rupp nt = 0; 1090f6e5521dSKarl Rupp for (i=0; i<nsends2; i++) nt += nprocs[i]; 1091f6e5521dSKarl Rupp 1092854ce69bSBarry Smith ierr = PetscMalloc1(nt+1,&sends2);CHKERRQ(ierr); 1093854ce69bSBarry Smith ierr = PetscMalloc1(nsends2+1,&starts2);CHKERRQ(ierr); 1094f6e5521dSKarl Rupp 1095f6e5521dSKarl Rupp starts2[0] = 0; 1096f6e5521dSKarl Rupp for (i=1; i<nsends2; i++) starts2[i] = starts2[i-1] + nprocs[i-1]; 109730dcb7c9SBarry Smith /* 109830dcb7c9SBarry Smith Each message is 1 + nprocs[i] long, and consists of 109930dcb7c9SBarry Smith (0) the number of nodes being sent back 110030dcb7c9SBarry Smith (1) the local node number, 110130dcb7c9SBarry Smith (2) the number of processors sharing it, 110230dcb7c9SBarry Smith (3) the processors sharing it 110330dcb7c9SBarry Smith */ 110430dcb7c9SBarry Smith for (i=0; i<nsends2; i++) { 110530dcb7c9SBarry Smith cnt = 1; 110630dcb7c9SBarry Smith sends2[starts2[i]] = 0; 110730dcb7c9SBarry Smith for (j=0; j<len[i]; j++) { 110830dcb7c9SBarry Smith node = recvs[2*i*nmax+2*j]-rstart; 110930dcb7c9SBarry Smith if (nownedsenders[node] > 1) { 111030dcb7c9SBarry Smith sends2[starts2[i]]++; 111130dcb7c9SBarry Smith sends2[starts2[i]+cnt++] = recvs[2*i*nmax+2*j+1]; 111230dcb7c9SBarry Smith sends2[starts2[i]+cnt++] = nownedsenders[node]; 111332dcc486SBarry Smith ierr = PetscMemcpy(&sends2[starts2[i]+cnt],&ownedsenders[starts[node]],nownedsenders[node]*sizeof(PetscInt));CHKERRQ(ierr); 111430dcb7c9SBarry Smith cnt += nownedsenders[node]; 111530dcb7c9SBarry Smith } 111630dcb7c9SBarry Smith } 111730dcb7c9SBarry Smith } 111830dcb7c9SBarry Smith 111930dcb7c9SBarry Smith /* receive the message lengths */ 112030dcb7c9SBarry Smith nrecvs2 = nsends; 1121854ce69bSBarry Smith ierr = PetscMalloc1(nrecvs2+1,&lens2);CHKERRQ(ierr); 1122854ce69bSBarry Smith ierr = PetscMalloc1(nrecvs2+1,&starts3);CHKERRQ(ierr); 1123854ce69bSBarry Smith ierr = PetscMalloc1(nrecvs2+1,&recv_waits);CHKERRQ(ierr); 112430dcb7c9SBarry Smith for (i=0; i<nrecvs2; i++) { 1125d44834fbSBarry Smith ierr = MPI_Irecv(&lens2[i],1,MPIU_INT,dest[i],tag2,comm,recv_waits+i);CHKERRQ(ierr); 112630dcb7c9SBarry Smith } 1127d44834fbSBarry Smith 11288a8e0b3aSBarry Smith /* send the message lengths */ 11298a8e0b3aSBarry Smith for (i=0; i<nsends2; i++) { 11308a8e0b3aSBarry Smith ierr = MPI_Send(&nprocs[i],1,MPIU_INT,source[i],tag2,comm);CHKERRQ(ierr); 11318a8e0b3aSBarry Smith } 11328a8e0b3aSBarry Smith 1133d44834fbSBarry Smith /* wait on receives of lens */ 11340c468ba9SBarry Smith if (nrecvs2) { 1135785e854fSJed Brown ierr = PetscMalloc1(nrecvs2,&recv_statuses);CHKERRQ(ierr); 1136d44834fbSBarry Smith ierr = MPI_Waitall(nrecvs2,recv_waits,recv_statuses);CHKERRQ(ierr); 1137d44834fbSBarry Smith ierr = PetscFree(recv_statuses);CHKERRQ(ierr); 11380c468ba9SBarry Smith } 1139a2ea699eSBarry Smith ierr = PetscFree(recv_waits);CHKERRQ(ierr); 1140d44834fbSBarry Smith 114130dcb7c9SBarry Smith starts3[0] = 0; 1142d44834fbSBarry Smith nt = 0; 114330dcb7c9SBarry Smith for (i=0; i<nrecvs2-1; i++) { 114430dcb7c9SBarry Smith starts3[i+1] = starts3[i] + lens2[i]; 1145d44834fbSBarry Smith nt += lens2[i]; 114630dcb7c9SBarry Smith } 114776466f69SStefano Zampini if (nrecvs2) nt += lens2[nrecvs2-1]; 1148d44834fbSBarry Smith 1149854ce69bSBarry Smith ierr = PetscMalloc1(nt+1,&recvs2);CHKERRQ(ierr); 1150854ce69bSBarry Smith ierr = PetscMalloc1(nrecvs2+1,&recv_waits);CHKERRQ(ierr); 115152b72c4aSBarry Smith for (i=0; i<nrecvs2; i++) { 115232dcc486SBarry Smith ierr = MPI_Irecv(recvs2+starts3[i],lens2[i],MPIU_INT,dest[i],tag3,comm,recv_waits+i);CHKERRQ(ierr); 115330dcb7c9SBarry Smith } 115430dcb7c9SBarry Smith 115530dcb7c9SBarry Smith /* send the messages */ 1156854ce69bSBarry Smith ierr = PetscMalloc1(nsends2+1,&send_waits);CHKERRQ(ierr); 115730dcb7c9SBarry Smith for (i=0; i<nsends2; i++) { 115832dcc486SBarry Smith ierr = MPI_Isend(sends2+starts2[i],nprocs[i],MPIU_INT,source[i],tag3,comm,send_waits+i);CHKERRQ(ierr); 115930dcb7c9SBarry Smith } 116030dcb7c9SBarry Smith 116130dcb7c9SBarry Smith /* wait on receives */ 11620c468ba9SBarry Smith if (nrecvs2) { 1163785e854fSJed Brown ierr = PetscMalloc1(nrecvs2,&recv_statuses);CHKERRQ(ierr); 116430dcb7c9SBarry Smith ierr = MPI_Waitall(nrecvs2,recv_waits,recv_statuses);CHKERRQ(ierr); 116530dcb7c9SBarry Smith ierr = PetscFree(recv_statuses);CHKERRQ(ierr); 11660c468ba9SBarry Smith } 116730dcb7c9SBarry Smith ierr = PetscFree(recv_waits);CHKERRQ(ierr); 116830dcb7c9SBarry Smith ierr = PetscFree(nprocs);CHKERRQ(ierr); 116930dcb7c9SBarry Smith 117007b52d57SBarry Smith if (debug) { /* ----------------------------------- */ 117130dcb7c9SBarry Smith cnt = 0; 117230dcb7c9SBarry Smith for (i=0; i<nrecvs2; i++) { 117330dcb7c9SBarry Smith nt = recvs2[cnt++]; 117430dcb7c9SBarry Smith for (j=0; j<nt; j++) { 11757904a332SBarry Smith ierr = PetscSynchronizedPrintf(comm,"[%d] local node %D number of subdomains %D: ",rank,recvs2[cnt],recvs2[cnt+1]);CHKERRQ(ierr); 117630dcb7c9SBarry Smith for (k=0; k<recvs2[cnt+1]; k++) { 11777904a332SBarry Smith ierr = PetscSynchronizedPrintf(comm,"%D ",recvs2[cnt+2+k]);CHKERRQ(ierr); 117830dcb7c9SBarry Smith } 117930dcb7c9SBarry Smith cnt += 2 + recvs2[cnt+1]; 118030dcb7c9SBarry Smith ierr = PetscSynchronizedPrintf(comm,"\n");CHKERRQ(ierr); 118130dcb7c9SBarry Smith } 118230dcb7c9SBarry Smith } 11830ec8b6e3SBarry Smith ierr = PetscSynchronizedFlush(comm,PETSC_STDOUT);CHKERRQ(ierr); 118407b52d57SBarry Smith } /* ----------------------------------- */ 118530dcb7c9SBarry Smith 118630dcb7c9SBarry Smith /* count number subdomains for each local node */ 1187785e854fSJed Brown ierr = PetscMalloc1(size,&nprocs);CHKERRQ(ierr); 118832dcc486SBarry Smith ierr = PetscMemzero(nprocs,size*sizeof(PetscInt));CHKERRQ(ierr); 118930dcb7c9SBarry Smith cnt = 0; 119030dcb7c9SBarry Smith for (i=0; i<nrecvs2; i++) { 119130dcb7c9SBarry Smith nt = recvs2[cnt++]; 119230dcb7c9SBarry Smith for (j=0; j<nt; j++) { 1193f6e5521dSKarl Rupp for (k=0; k<recvs2[cnt+1]; k++) nprocs[recvs2[cnt+2+k]]++; 119430dcb7c9SBarry Smith cnt += 2 + recvs2[cnt+1]; 119530dcb7c9SBarry Smith } 119630dcb7c9SBarry Smith } 119730dcb7c9SBarry Smith nt = 0; for (i=0; i<size; i++) nt += (nprocs[i] > 0); 119830dcb7c9SBarry Smith *nproc = nt; 1199854ce69bSBarry Smith ierr = PetscMalloc1(nt+1,procs);CHKERRQ(ierr); 1200854ce69bSBarry Smith ierr = PetscMalloc1(nt+1,numprocs);CHKERRQ(ierr); 1201854ce69bSBarry Smith ierr = PetscMalloc1(nt+1,indices);CHKERRQ(ierr); 12020298fd71SBarry Smith for (i=0;i<nt+1;i++) (*indices)[i]=NULL; 1203785e854fSJed Brown ierr = PetscMalloc1(size,&bprocs);CHKERRQ(ierr); 120430dcb7c9SBarry Smith cnt = 0; 120530dcb7c9SBarry Smith for (i=0; i<size; i++) { 120630dcb7c9SBarry Smith if (nprocs[i] > 0) { 120730dcb7c9SBarry Smith bprocs[i] = cnt; 120830dcb7c9SBarry Smith (*procs)[cnt] = i; 120930dcb7c9SBarry Smith (*numprocs)[cnt] = nprocs[i]; 1210785e854fSJed Brown ierr = PetscMalloc1(nprocs[i],&(*indices)[cnt]);CHKERRQ(ierr); 121130dcb7c9SBarry Smith cnt++; 121230dcb7c9SBarry Smith } 121330dcb7c9SBarry Smith } 121430dcb7c9SBarry Smith 121530dcb7c9SBarry Smith /* make the list of subdomains for each nontrivial local node */ 121632dcc486SBarry Smith ierr = PetscMemzero(*numprocs,nt*sizeof(PetscInt));CHKERRQ(ierr); 121730dcb7c9SBarry Smith cnt = 0; 121830dcb7c9SBarry Smith for (i=0; i<nrecvs2; i++) { 121930dcb7c9SBarry Smith nt = recvs2[cnt++]; 122030dcb7c9SBarry Smith for (j=0; j<nt; j++) { 1221f6e5521dSKarl Rupp for (k=0; k<recvs2[cnt+1]; k++) (*indices)[bprocs[recvs2[cnt+2+k]]][(*numprocs)[bprocs[recvs2[cnt+2+k]]]++] = recvs2[cnt]; 122230dcb7c9SBarry Smith cnt += 2 + recvs2[cnt+1]; 122330dcb7c9SBarry Smith } 122430dcb7c9SBarry Smith } 122530dcb7c9SBarry Smith ierr = PetscFree(bprocs);CHKERRQ(ierr); 122607b52d57SBarry Smith ierr = PetscFree(recvs2);CHKERRQ(ierr); 122730dcb7c9SBarry Smith 122807b52d57SBarry Smith /* sort the node indexing by their global numbers */ 122907b52d57SBarry Smith nt = *nproc; 123007b52d57SBarry Smith for (i=0; i<nt; i++) { 1231854ce69bSBarry Smith ierr = PetscMalloc1((*numprocs)[i],&tmp);CHKERRQ(ierr); 1232f6e5521dSKarl Rupp for (j=0; j<(*numprocs)[i]; j++) tmp[j] = lindices[(*indices)[i][j]]; 123307b52d57SBarry Smith ierr = PetscSortIntWithArray((*numprocs)[i],tmp,(*indices)[i]);CHKERRQ(ierr); 123407b52d57SBarry Smith ierr = PetscFree(tmp);CHKERRQ(ierr); 123507b52d57SBarry Smith } 123607b52d57SBarry Smith 123707b52d57SBarry Smith if (debug) { /* ----------------------------------- */ 123830dcb7c9SBarry Smith nt = *nproc; 123930dcb7c9SBarry Smith for (i=0; i<nt; i++) { 12407904a332SBarry Smith ierr = PetscSynchronizedPrintf(comm,"[%d] subdomain %D number of indices %D: ",rank,(*procs)[i],(*numprocs)[i]);CHKERRQ(ierr); 124130dcb7c9SBarry Smith for (j=0; j<(*numprocs)[i]; j++) { 12427904a332SBarry Smith ierr = PetscSynchronizedPrintf(comm,"%D ",(*indices)[i][j]);CHKERRQ(ierr); 124330dcb7c9SBarry Smith } 124430dcb7c9SBarry Smith ierr = PetscSynchronizedPrintf(comm,"\n");CHKERRQ(ierr); 124530dcb7c9SBarry Smith } 12460ec8b6e3SBarry Smith ierr = PetscSynchronizedFlush(comm,PETSC_STDOUT);CHKERRQ(ierr); 124707b52d57SBarry Smith } /* ----------------------------------- */ 124830dcb7c9SBarry Smith 124930dcb7c9SBarry Smith /* wait on sends */ 125030dcb7c9SBarry Smith if (nsends2) { 1251785e854fSJed Brown ierr = PetscMalloc1(nsends2,&send_status);CHKERRQ(ierr); 125230dcb7c9SBarry Smith ierr = MPI_Waitall(nsends2,send_waits,send_status);CHKERRQ(ierr); 125330dcb7c9SBarry Smith ierr = PetscFree(send_status);CHKERRQ(ierr); 125430dcb7c9SBarry Smith } 125530dcb7c9SBarry Smith 125630dcb7c9SBarry Smith ierr = PetscFree(starts3);CHKERRQ(ierr); 125730dcb7c9SBarry Smith ierr = PetscFree(dest);CHKERRQ(ierr); 125830dcb7c9SBarry Smith ierr = PetscFree(send_waits);CHKERRQ(ierr); 12593677ff5aSBarry Smith 1260bc8ff85bSBarry Smith ierr = PetscFree(nownedsenders);CHKERRQ(ierr); 1261bc8ff85bSBarry Smith ierr = PetscFree(ownedsenders);CHKERRQ(ierr); 1262bc8ff85bSBarry Smith ierr = PetscFree(starts);CHKERRQ(ierr); 126330dcb7c9SBarry Smith ierr = PetscFree(starts2);CHKERRQ(ierr); 126430dcb7c9SBarry Smith ierr = PetscFree(lens2);CHKERRQ(ierr); 126589d82c54SBarry Smith 126689d82c54SBarry Smith ierr = PetscFree(source);CHKERRQ(ierr); 126797f1f81fSBarry Smith ierr = PetscFree(len);CHKERRQ(ierr); 126889d82c54SBarry Smith ierr = PetscFree(recvs);CHKERRQ(ierr); 12693a96401aSBarry Smith ierr = PetscFree(nprocs);CHKERRQ(ierr); 127030dcb7c9SBarry Smith ierr = PetscFree(sends2);CHKERRQ(ierr); 127124cf384cSBarry Smith 127224cf384cSBarry Smith /* put the information about myself as the first entry in the list */ 127324cf384cSBarry Smith first_procs = (*procs)[0]; 127424cf384cSBarry Smith first_numprocs = (*numprocs)[0]; 127524cf384cSBarry Smith first_indices = (*indices)[0]; 127624cf384cSBarry Smith for (i=0; i<*nproc; i++) { 127724cf384cSBarry Smith if ((*procs)[i] == rank) { 127824cf384cSBarry Smith (*procs)[0] = (*procs)[i]; 127924cf384cSBarry Smith (*numprocs)[0] = (*numprocs)[i]; 128024cf384cSBarry Smith (*indices)[0] = (*indices)[i]; 128124cf384cSBarry Smith (*procs)[i] = first_procs; 128224cf384cSBarry Smith (*numprocs)[i] = first_numprocs; 128324cf384cSBarry Smith (*indices)[i] = first_indices; 128424cf384cSBarry Smith break; 128524cf384cSBarry Smith } 128624cf384cSBarry Smith } 1287268a049cSStefano Zampini 1288268a049cSStefano Zampini /* save info for reuse */ 1289268a049cSStefano Zampini mapping->info_nproc = *nproc; 1290268a049cSStefano Zampini mapping->info_procs = *procs; 1291268a049cSStefano Zampini mapping->info_numprocs = *numprocs; 1292268a049cSStefano Zampini mapping->info_indices = *indices; 1293268a049cSStefano Zampini mapping->info_cached = PETSC_TRUE; 129489d82c54SBarry Smith PetscFunctionReturn(0); 129589d82c54SBarry Smith } 129689d82c54SBarry Smith 12974a2ae208SSatish Balay #undef __FUNCT__ 12986a818285SBarry Smith #define __FUNCT__ "ISLocalToGlobalMappingRestoreBlockInfo" 12996a818285SBarry Smith /*@C 13006a818285SBarry Smith ISLocalToGlobalMappingRestoreBlockInfo - Frees the memory allocated by ISLocalToGlobalMappingGetBlockInfo() 13016a818285SBarry Smith 13026a818285SBarry Smith Collective on ISLocalToGlobalMapping 13036a818285SBarry Smith 13046a818285SBarry Smith Input Parameters: 13056a818285SBarry Smith . mapping - the mapping from local to global indexing 13066a818285SBarry Smith 13076a818285SBarry Smith Output Parameter: 13086a818285SBarry Smith + nproc - number of processors that are connected to this one 13096a818285SBarry Smith . proc - neighboring processors 13106a818285SBarry Smith . numproc - number of indices for each processor 13116a818285SBarry Smith - indices - indices of local nodes shared with neighbor (sorted by global numbering) 13126a818285SBarry Smith 13136a818285SBarry Smith Level: advanced 13146a818285SBarry Smith 13156a818285SBarry Smith .seealso: ISLocalToGlobalMappingDestroy(), ISLocalToGlobalMappingCreateIS(), ISLocalToGlobalMappingCreate(), 13166a818285SBarry Smith ISLocalToGlobalMappingGetInfo() 13176a818285SBarry Smith @*/ 13186a818285SBarry Smith PetscErrorCode ISLocalToGlobalMappingRestoreBlockInfo(ISLocalToGlobalMapping mapping,PetscInt *nproc,PetscInt *procs[],PetscInt *numprocs[],PetscInt **indices[]) 13196a818285SBarry Smith { 13206a818285SBarry Smith PetscErrorCode ierr; 13216a818285SBarry Smith 13226a818285SBarry Smith PetscFunctionBegin; 1323cbc1caf0SMatthew G. Knepley PetscValidHeaderSpecific(mapping,IS_LTOGM_CLASSID,1); 1324268a049cSStefano Zampini if (mapping->info_free) { 13256a818285SBarry Smith ierr = PetscFree(*numprocs);CHKERRQ(ierr); 13266a818285SBarry Smith if (*indices) { 1327268a049cSStefano Zampini PetscInt i; 1328268a049cSStefano Zampini 13296a818285SBarry Smith ierr = PetscFree((*indices)[0]);CHKERRQ(ierr); 13306a818285SBarry Smith for (i=1; i<*nproc; i++) { 13316a818285SBarry Smith ierr = PetscFree((*indices)[i]);CHKERRQ(ierr); 13326a818285SBarry Smith } 13336a818285SBarry Smith ierr = PetscFree(*indices);CHKERRQ(ierr); 13346a818285SBarry Smith } 1335268a049cSStefano Zampini } 1336268a049cSStefano Zampini *nproc = 0; 1337268a049cSStefano Zampini *procs = NULL; 1338268a049cSStefano Zampini *numprocs = NULL; 1339268a049cSStefano Zampini *indices = NULL; 13406a818285SBarry Smith PetscFunctionReturn(0); 13416a818285SBarry Smith } 13426a818285SBarry Smith 13436a818285SBarry Smith #undef __FUNCT__ 13446a818285SBarry Smith #define __FUNCT__ "ISLocalToGlobalMappingGetInfo" 13456a818285SBarry Smith /*@C 13466a818285SBarry Smith ISLocalToGlobalMappingGetInfo - Gets the neighbor information for each processor and 13476a818285SBarry Smith each index shared by more than one processor 13486a818285SBarry Smith 13496a818285SBarry Smith Collective on ISLocalToGlobalMapping 13506a818285SBarry Smith 13516a818285SBarry Smith Input Parameters: 13526a818285SBarry Smith . mapping - the mapping from local to global indexing 13536a818285SBarry Smith 13546a818285SBarry Smith Output Parameter: 13556a818285SBarry Smith + nproc - number of processors that are connected to this one 13566a818285SBarry Smith . proc - neighboring processors 13576a818285SBarry Smith . numproc - number of indices for each subdomain (processor) 13586a818285SBarry Smith - indices - indices of nodes (in local numbering) shared with neighbors (sorted by global numbering) 13596a818285SBarry Smith 13606a818285SBarry Smith Level: advanced 13616a818285SBarry Smith 13626a818285SBarry Smith Concepts: mapping^local to global 13636a818285SBarry Smith 13646a818285SBarry Smith Fortran Usage: 13656a818285SBarry Smith $ ISLocalToGlobalMpngGetInfoSize(ISLocalToGlobalMapping,PetscInt nproc,PetscInt numprocmax,ierr) followed by 13666a818285SBarry Smith $ ISLocalToGlobalMappingGetInfo(ISLocalToGlobalMapping,PetscInt nproc, PetscInt procs[nproc],PetscInt numprocs[nproc], 13676a818285SBarry Smith PetscInt indices[nproc][numprocmax],ierr) 13686a818285SBarry Smith There is no ISLocalToGlobalMappingRestoreInfo() in Fortran. You must make sure that procs[], numprocs[] and 13696a818285SBarry Smith indices[][] are large enough arrays, either by allocating them dynamically or defining static ones large enough. 13706a818285SBarry Smith 13716a818285SBarry Smith 13726a818285SBarry Smith .seealso: ISLocalToGlobalMappingDestroy(), ISLocalToGlobalMappingCreateIS(), ISLocalToGlobalMappingCreate(), 13736a818285SBarry Smith ISLocalToGlobalMappingRestoreInfo() 13746a818285SBarry Smith @*/ 13756a818285SBarry Smith PetscErrorCode ISLocalToGlobalMappingGetInfo(ISLocalToGlobalMapping mapping,PetscInt *nproc,PetscInt *procs[],PetscInt *numprocs[],PetscInt **indices[]) 13766a818285SBarry Smith { 13776a818285SBarry Smith PetscErrorCode ierr; 1378268a049cSStefano Zampini PetscInt **bindices = NULL,*bnumprocs = NULL,bs = mapping->bs,i,j,k; 13796a818285SBarry Smith 13806a818285SBarry Smith PetscFunctionBegin; 13816a818285SBarry Smith PetscValidHeaderSpecific(mapping,IS_LTOGM_CLASSID,1); 1382268a049cSStefano Zampini ierr = ISLocalToGlobalMappingGetBlockInfo(mapping,nproc,procs,&bnumprocs,&bindices);CHKERRQ(ierr); 1383268a049cSStefano Zampini if (bs > 1) { /* we need to expand the cached info */ 1384732f65e3SBarry Smith ierr = PetscCalloc1(*nproc,&*indices);CHKERRQ(ierr); 1385268a049cSStefano Zampini ierr = PetscCalloc1(*nproc,&*numprocs);CHKERRQ(ierr); 13866a818285SBarry Smith for (i=0; i<*nproc; i++) { 1387268a049cSStefano Zampini ierr = PetscMalloc1(bs*bnumprocs[i],&(*indices)[i]);CHKERRQ(ierr); 1388268a049cSStefano Zampini for (j=0; j<bnumprocs[i]; j++) { 13896a818285SBarry Smith for (k=0; k<bs; k++) { 13906a818285SBarry Smith (*indices)[i][j*bs+k] = bs*bindices[i][j] + k; 13916a818285SBarry Smith } 13926a818285SBarry Smith } 1393268a049cSStefano Zampini (*numprocs)[i] = bnumprocs[i]*bs; 13946a818285SBarry Smith } 1395268a049cSStefano Zampini mapping->info_free = PETSC_TRUE; 1396268a049cSStefano Zampini } else { 1397268a049cSStefano Zampini *numprocs = bnumprocs; 1398268a049cSStefano Zampini *indices = bindices; 13996a818285SBarry Smith } 14006a818285SBarry Smith PetscFunctionReturn(0); 14016a818285SBarry Smith } 14026a818285SBarry Smith 14036a818285SBarry Smith #undef __FUNCT__ 14044a2ae208SSatish Balay #define __FUNCT__ "ISLocalToGlobalMappingRestoreInfo" 140507b52d57SBarry Smith /*@C 140607b52d57SBarry Smith ISLocalToGlobalMappingRestoreInfo - Frees the memory allocated by ISLocalToGlobalMappingGetInfo() 140789d82c54SBarry Smith 140807b52d57SBarry Smith Collective on ISLocalToGlobalMapping 140907b52d57SBarry Smith 141007b52d57SBarry Smith Input Parameters: 141107b52d57SBarry Smith . mapping - the mapping from local to global indexing 141207b52d57SBarry Smith 141307b52d57SBarry Smith Output Parameter: 141407b52d57SBarry Smith + nproc - number of processors that are connected to this one 141507b52d57SBarry Smith . proc - neighboring processors 141607b52d57SBarry Smith . numproc - number of indices for each processor 141707b52d57SBarry Smith - indices - indices of local nodes shared with neighbor (sorted by global numbering) 141807b52d57SBarry Smith 141907b52d57SBarry Smith Level: advanced 142007b52d57SBarry Smith 142107b52d57SBarry Smith .seealso: ISLocalToGlobalMappingDestroy(), ISLocalToGlobalMappingCreateIS(), ISLocalToGlobalMappingCreate(), 142207b52d57SBarry Smith ISLocalToGlobalMappingGetInfo() 142307b52d57SBarry Smith @*/ 14247087cfbeSBarry Smith PetscErrorCode ISLocalToGlobalMappingRestoreInfo(ISLocalToGlobalMapping mapping,PetscInt *nproc,PetscInt *procs[],PetscInt *numprocs[],PetscInt **indices[]) 142507b52d57SBarry Smith { 14266849ba73SBarry Smith PetscErrorCode ierr; 142707b52d57SBarry Smith 142807b52d57SBarry Smith PetscFunctionBegin; 14296a818285SBarry Smith ierr = ISLocalToGlobalMappingRestoreBlockInfo(mapping,nproc,procs,numprocs,indices);CHKERRQ(ierr); 143007b52d57SBarry Smith PetscFunctionReturn(0); 143107b52d57SBarry Smith } 143286994e45SJed Brown 143386994e45SJed Brown #undef __FUNCT__ 143486994e45SJed Brown #define __FUNCT__ "ISLocalToGlobalMappingGetIndices" 143586994e45SJed Brown /*@C 1436107e9a97SBarry Smith ISLocalToGlobalMappingGetIndices - Get global indices for every local point that is mapped 143786994e45SJed Brown 143886994e45SJed Brown Not Collective 143986994e45SJed Brown 144086994e45SJed Brown Input Arguments: 144186994e45SJed Brown . ltog - local to global mapping 144286994e45SJed Brown 144386994e45SJed Brown Output Arguments: 1444565245c5SBarry Smith . array - array of indices, the length of this array may be obtained with ISLocalToGlobalMappingGetSize() 144586994e45SJed Brown 144686994e45SJed Brown Level: advanced 144786994e45SJed Brown 1448107e9a97SBarry Smith Notes: ISLocalToGlobalMappingGetSize() returns the length the this array 1449107e9a97SBarry Smith 1450107e9a97SBarry Smith .seealso: ISLocalToGlobalMappingCreate(), ISLocalToGlobalMappingApply(), ISLocalToGlobalMappingRestoreIndices(), ISLocalToGlobalMappingGetBlockIndices(), ISLocalToGlobalMappingRestoreBlockIndices() 145186994e45SJed Brown @*/ 14527087cfbeSBarry Smith PetscErrorCode ISLocalToGlobalMappingGetIndices(ISLocalToGlobalMapping ltog,const PetscInt **array) 145386994e45SJed Brown { 145486994e45SJed Brown PetscFunctionBegin; 145586994e45SJed Brown PetscValidHeaderSpecific(ltog,IS_LTOGM_CLASSID,1); 145686994e45SJed Brown PetscValidPointer(array,2); 145745b6f7e9SBarry Smith if (ltog->bs == 1) { 145886994e45SJed Brown *array = ltog->indices; 145945b6f7e9SBarry Smith } else { 146045b6f7e9SBarry Smith PetscInt *jj,k,i,j,n = ltog->n, bs = ltog->bs; 146145b6f7e9SBarry Smith const PetscInt *ii; 146245b6f7e9SBarry Smith PetscErrorCode ierr; 146345b6f7e9SBarry Smith 146445b6f7e9SBarry Smith ierr = PetscMalloc1(bs*n,&jj);CHKERRQ(ierr); 146545b6f7e9SBarry Smith *array = jj; 146645b6f7e9SBarry Smith k = 0; 146745b6f7e9SBarry Smith ii = ltog->indices; 146845b6f7e9SBarry Smith for (i=0; i<n; i++) 146945b6f7e9SBarry Smith for (j=0; j<bs; j++) 147045b6f7e9SBarry Smith jj[k++] = bs*ii[i] + j; 147145b6f7e9SBarry Smith } 147286994e45SJed Brown PetscFunctionReturn(0); 147386994e45SJed Brown } 147486994e45SJed Brown 147586994e45SJed Brown #undef __FUNCT__ 147686994e45SJed Brown #define __FUNCT__ "ISLocalToGlobalMappingRestoreIndices" 147786994e45SJed Brown /*@C 1478193a2b41SJulian Andrej ISLocalToGlobalMappingRestoreIndices - Restore indices obtained with ISLocalToGlobalMappingGetIndices() 147986994e45SJed Brown 148086994e45SJed Brown Not Collective 148186994e45SJed Brown 148286994e45SJed Brown Input Arguments: 148386994e45SJed Brown + ltog - local to global mapping 148486994e45SJed Brown - array - array of indices 148586994e45SJed Brown 148686994e45SJed Brown Level: advanced 148786994e45SJed Brown 148886994e45SJed Brown .seealso: ISLocalToGlobalMappingCreate(), ISLocalToGlobalMappingApply(), ISLocalToGlobalMappingGetIndices() 148986994e45SJed Brown @*/ 14907087cfbeSBarry Smith PetscErrorCode ISLocalToGlobalMappingRestoreIndices(ISLocalToGlobalMapping ltog,const PetscInt **array) 149186994e45SJed Brown { 149286994e45SJed Brown PetscFunctionBegin; 149386994e45SJed Brown PetscValidHeaderSpecific(ltog,IS_LTOGM_CLASSID,1); 149486994e45SJed Brown PetscValidPointer(array,2); 149545b6f7e9SBarry Smith if (ltog->bs == 1 && *array != ltog->indices) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_BADPTR,"Trying to return mismatched pointer"); 149645b6f7e9SBarry Smith 149745b6f7e9SBarry Smith if (ltog->bs > 1) { 149845b6f7e9SBarry Smith PetscErrorCode ierr; 149945b6f7e9SBarry Smith ierr = PetscFree(*(void**)array);CHKERRQ(ierr); 150045b6f7e9SBarry Smith } 150145b6f7e9SBarry Smith PetscFunctionReturn(0); 150245b6f7e9SBarry Smith } 150345b6f7e9SBarry Smith 150445b6f7e9SBarry Smith #undef __FUNCT__ 150545b6f7e9SBarry Smith #define __FUNCT__ "ISLocalToGlobalMappingGetBlockIndices" 150645b6f7e9SBarry Smith /*@C 150745b6f7e9SBarry Smith ISLocalToGlobalMappingGetBlockIndices - Get global indices for every local block 150845b6f7e9SBarry Smith 150945b6f7e9SBarry Smith Not Collective 151045b6f7e9SBarry Smith 151145b6f7e9SBarry Smith Input Arguments: 151245b6f7e9SBarry Smith . ltog - local to global mapping 151345b6f7e9SBarry Smith 151445b6f7e9SBarry Smith Output Arguments: 151545b6f7e9SBarry Smith . array - array of indices 151645b6f7e9SBarry Smith 151745b6f7e9SBarry Smith Level: advanced 151845b6f7e9SBarry Smith 151945b6f7e9SBarry Smith .seealso: ISLocalToGlobalMappingCreate(), ISLocalToGlobalMappingApply(), ISLocalToGlobalMappingRestoreBlockIndices() 152045b6f7e9SBarry Smith @*/ 152145b6f7e9SBarry Smith PetscErrorCode ISLocalToGlobalMappingGetBlockIndices(ISLocalToGlobalMapping ltog,const PetscInt **array) 152245b6f7e9SBarry Smith { 152345b6f7e9SBarry Smith PetscFunctionBegin; 152445b6f7e9SBarry Smith PetscValidHeaderSpecific(ltog,IS_LTOGM_CLASSID,1); 152545b6f7e9SBarry Smith PetscValidPointer(array,2); 152645b6f7e9SBarry Smith *array = ltog->indices; 152745b6f7e9SBarry Smith PetscFunctionReturn(0); 152845b6f7e9SBarry Smith } 152945b6f7e9SBarry Smith 153045b6f7e9SBarry Smith #undef __FUNCT__ 153145b6f7e9SBarry Smith #define __FUNCT__ "ISLocalToGlobalMappingRestoreBlockIndices" 153245b6f7e9SBarry Smith /*@C 153345b6f7e9SBarry Smith ISLocalToGlobalMappingRestoreBlockIndices - Restore indices obtained with ISLocalToGlobalMappingGetBlockIndices() 153445b6f7e9SBarry Smith 153545b6f7e9SBarry Smith Not Collective 153645b6f7e9SBarry Smith 153745b6f7e9SBarry Smith Input Arguments: 153845b6f7e9SBarry Smith + ltog - local to global mapping 153945b6f7e9SBarry Smith - array - array of indices 154045b6f7e9SBarry Smith 154145b6f7e9SBarry Smith Level: advanced 154245b6f7e9SBarry Smith 154345b6f7e9SBarry Smith .seealso: ISLocalToGlobalMappingCreate(), ISLocalToGlobalMappingApply(), ISLocalToGlobalMappingGetIndices() 154445b6f7e9SBarry Smith @*/ 154545b6f7e9SBarry Smith PetscErrorCode ISLocalToGlobalMappingRestoreBlockIndices(ISLocalToGlobalMapping ltog,const PetscInt **array) 154645b6f7e9SBarry Smith { 154745b6f7e9SBarry Smith PetscFunctionBegin; 154845b6f7e9SBarry Smith PetscValidHeaderSpecific(ltog,IS_LTOGM_CLASSID,1); 154945b6f7e9SBarry Smith PetscValidPointer(array,2); 155086994e45SJed Brown if (*array != ltog->indices) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_BADPTR,"Trying to return mismatched pointer"); 15510298fd71SBarry Smith *array = NULL; 155286994e45SJed Brown PetscFunctionReturn(0); 155386994e45SJed Brown } 1554f7efa3c7SJed Brown 1555f7efa3c7SJed Brown #undef __FUNCT__ 1556f7efa3c7SJed Brown #define __FUNCT__ "ISLocalToGlobalMappingConcatenate" 1557f7efa3c7SJed Brown /*@C 1558f7efa3c7SJed Brown ISLocalToGlobalMappingConcatenate - Create a new mapping that concatenates a list of mappings 1559f7efa3c7SJed Brown 1560f7efa3c7SJed Brown Not Collective 1561f7efa3c7SJed Brown 1562f7efa3c7SJed Brown Input Arguments: 1563f7efa3c7SJed Brown + comm - communicator for the new mapping, must contain the communicator of every mapping to concatenate 1564f7efa3c7SJed Brown . n - number of mappings to concatenate 1565f7efa3c7SJed Brown - ltogs - local to global mappings 1566f7efa3c7SJed Brown 1567f7efa3c7SJed Brown Output Arguments: 1568f7efa3c7SJed Brown . ltogcat - new mapping 1569f7efa3c7SJed Brown 15709d90f715SBarry Smith Note: this currently always returns a mapping with block size of 1 15719d90f715SBarry Smith 15729d90f715SBarry Smith Developer Note: If all the input mapping have the same block size we could easily handle that as a special case 15739d90f715SBarry Smith 1574f7efa3c7SJed Brown Level: advanced 1575f7efa3c7SJed Brown 1576f7efa3c7SJed Brown .seealso: ISLocalToGlobalMappingCreate() 1577f7efa3c7SJed Brown @*/ 1578f7efa3c7SJed Brown PetscErrorCode ISLocalToGlobalMappingConcatenate(MPI_Comm comm,PetscInt n,const ISLocalToGlobalMapping ltogs[],ISLocalToGlobalMapping *ltogcat) 1579f7efa3c7SJed Brown { 1580f7efa3c7SJed Brown PetscInt i,cnt,m,*idx; 1581f7efa3c7SJed Brown PetscErrorCode ierr; 1582f7efa3c7SJed Brown 1583f7efa3c7SJed Brown PetscFunctionBegin; 1584f7efa3c7SJed Brown if (n < 0) SETERRQ1(comm,PETSC_ERR_ARG_OUTOFRANGE,"Must have a non-negative number of mappings, given %D",n); 1585f7efa3c7SJed Brown if (n > 0) PetscValidPointer(ltogs,3); 1586f7efa3c7SJed Brown for (i=0; i<n; i++) PetscValidHeaderSpecific(ltogs[i],IS_LTOGM_CLASSID,3); 1587f7efa3c7SJed Brown PetscValidPointer(ltogcat,4); 1588f7efa3c7SJed Brown for (cnt=0,i=0; i<n; i++) { 1589f7efa3c7SJed Brown ierr = ISLocalToGlobalMappingGetSize(ltogs[i],&m);CHKERRQ(ierr); 1590f7efa3c7SJed Brown cnt += m; 1591f7efa3c7SJed Brown } 1592785e854fSJed Brown ierr = PetscMalloc1(cnt,&idx);CHKERRQ(ierr); 1593f7efa3c7SJed Brown for (cnt=0,i=0; i<n; i++) { 1594f7efa3c7SJed Brown const PetscInt *subidx; 1595f7efa3c7SJed Brown ierr = ISLocalToGlobalMappingGetSize(ltogs[i],&m);CHKERRQ(ierr); 1596f7efa3c7SJed Brown ierr = ISLocalToGlobalMappingGetIndices(ltogs[i],&subidx);CHKERRQ(ierr); 1597f7efa3c7SJed Brown ierr = PetscMemcpy(&idx[cnt],subidx,m*sizeof(PetscInt));CHKERRQ(ierr); 1598f7efa3c7SJed Brown ierr = ISLocalToGlobalMappingRestoreIndices(ltogs[i],&subidx);CHKERRQ(ierr); 1599f7efa3c7SJed Brown cnt += m; 1600f7efa3c7SJed Brown } 1601f0413b6fSBarry Smith ierr = ISLocalToGlobalMappingCreate(comm,1,cnt,idx,PETSC_OWN_POINTER,ltogcat);CHKERRQ(ierr); 1602f7efa3c7SJed Brown PetscFunctionReturn(0); 1603f7efa3c7SJed Brown } 160404a59952SBarry Smith 160504a59952SBarry Smith 1606