12c0dbf93SJed Brown 2b45d2f2cSJed Brown #include <petsc-private/matimpl.h> /*I "petscmat.h" I*/ 32c0dbf93SJed Brown 42c0dbf93SJed Brown typedef struct { 52c0dbf93SJed Brown Mat Top; 62c0dbf93SJed Brown PetscErrorCode (*SetValues)(Mat,PetscInt,const PetscInt[],PetscInt,const PetscInt[],const PetscScalar[],InsertMode); 72c0dbf93SJed Brown PetscErrorCode (*SetValuesBlocked)(Mat,PetscInt,const PetscInt[],PetscInt,const PetscInt[],const PetscScalar[],InsertMode); 82c0dbf93SJed Brown } Mat_LocalRef; 92c0dbf93SJed Brown 102c0dbf93SJed Brown /* These need to be macros because they use sizeof */ 112c0dbf93SJed Brown #define IndexSpaceGet(buf,nrow,ncol,irowm,icolm) do { \ 12a52dc253SJed Brown if (nrow + ncol > (PetscInt)(sizeof(buf)/sizeof(buf[0]))) { \ 13dcca6d9dSJed Brown ierr = PetscMalloc2(nrow,&irowm,ncol,&icolm);CHKERRQ(ierr); \ 142c0dbf93SJed Brown } else { \ 152c0dbf93SJed Brown irowm = &buf[0]; \ 162c0dbf93SJed Brown icolm = &buf[nrow]; \ 172c0dbf93SJed Brown } \ 182c0dbf93SJed Brown } while (0) 192c0dbf93SJed Brown 202c0dbf93SJed Brown #define IndexSpaceRestore(buf,nrow,ncol,irowm,icolm) do { \ 21a52dc253SJed Brown if (nrow + ncol > (PetscInt)(sizeof(buf)/sizeof(buf[0]))) { \ 222c0dbf93SJed Brown ierr = PetscFree2(irowm,icolm);CHKERRQ(ierr); \ 232c0dbf93SJed Brown } \ 242c0dbf93SJed Brown } while (0) 252c0dbf93SJed Brown 262c0dbf93SJed Brown static void BlockIndicesExpand(PetscInt n,const PetscInt idx[],PetscInt bs,PetscInt idxm[]) 272c0dbf93SJed Brown { 282c0dbf93SJed Brown PetscInt i,j; 292c0dbf93SJed Brown for (i=0; i<n; i++) { 302c0dbf93SJed Brown for (j=0; j<bs; j++) { 312c0dbf93SJed Brown idxm[i*bs+j] = idx[i]*bs + j; 322c0dbf93SJed Brown } 332c0dbf93SJed Brown } 342c0dbf93SJed Brown } 352c0dbf93SJed Brown 362c0dbf93SJed Brown #undef __FUNCT__ 372c0dbf93SJed Brown #define __FUNCT__ "MatSetValuesBlockedLocal_LocalRef_Block" 382c0dbf93SJed Brown static PetscErrorCode MatSetValuesBlockedLocal_LocalRef_Block(Mat A,PetscInt nrow,const PetscInt irow[],PetscInt ncol,const PetscInt icol[],const PetscScalar y[],InsertMode addv) 392c0dbf93SJed Brown { 402c0dbf93SJed Brown Mat_LocalRef *lr = (Mat_LocalRef*)A->data; 412c0dbf93SJed Brown PetscErrorCode ierr; 422c0dbf93SJed Brown PetscInt buf[4096],*irowm,*icolm; 432c0dbf93SJed Brown 442c0dbf93SJed Brown PetscFunctionBegin; 452c0dbf93SJed Brown if (!nrow || !ncol) PetscFunctionReturn(0); 462c0dbf93SJed Brown IndexSpaceGet(buf,nrow,ncol,irowm,icolm); 4745b6f7e9SBarry Smith ierr = ISLocalToGlobalMappingApplyBlock(A->rmap->mapping,nrow,irow,irowm);CHKERRQ(ierr); 4845b6f7e9SBarry Smith ierr = ISLocalToGlobalMappingApplyBlock(A->cmap->mapping,ncol,icol,icolm);CHKERRQ(ierr); 492c0dbf93SJed Brown ierr = (*lr->SetValuesBlocked)(lr->Top,nrow,irowm,ncol,icolm,y,addv);CHKERRQ(ierr); 502c0dbf93SJed Brown IndexSpaceRestore(buf,nrow,ncol,irowm,icolm); 512c0dbf93SJed Brown PetscFunctionReturn(0); 522c0dbf93SJed Brown } 532c0dbf93SJed Brown 542c0dbf93SJed Brown #undef __FUNCT__ 552c0dbf93SJed Brown #define __FUNCT__ "MatSetValuesBlockedLocal_LocalRef_Scalar" 562c0dbf93SJed Brown static PetscErrorCode MatSetValuesBlockedLocal_LocalRef_Scalar(Mat A,PetscInt nrow,const PetscInt irow[],PetscInt ncol,const PetscInt icol[],const PetscScalar y[],InsertMode addv) 572c0dbf93SJed Brown { 582c0dbf93SJed Brown Mat_LocalRef *lr = (Mat_LocalRef*)A->data; 592c0dbf93SJed Brown PetscErrorCode ierr; 60*6e191704SLawrence Mitchell PetscInt rbs,cbs,buf[4096],*irowm,*icolm; 612c0dbf93SJed Brown 622c0dbf93SJed Brown PetscFunctionBegin; 63*6e191704SLawrence Mitchell ierr = MatGetBlockSizes(A,&rbs,&cbs);CHKERRQ(ierr); 64*6e191704SLawrence Mitchell IndexSpaceGet(buf,nrow*rbs,ncol*cbs,irowm,icolm); 65*6e191704SLawrence Mitchell BlockIndicesExpand(nrow,irow,rbs,irowm); 66*6e191704SLawrence Mitchell BlockIndicesExpand(ncol,icol,cbs,icolm); 67*6e191704SLawrence Mitchell ierr = ISLocalToGlobalMappingApplyBlock(A->rmap->mapping,nrow*rbs,irowm,irowm);CHKERRQ(ierr); 68*6e191704SLawrence Mitchell ierr = ISLocalToGlobalMappingApplyBlock(A->cmap->mapping,ncol*cbs,icolm,icolm);CHKERRQ(ierr); 69*6e191704SLawrence Mitchell ierr = (*lr->SetValues)(lr->Top,nrow*rbs,irowm,ncol*cbs,icolm,y,addv);CHKERRQ(ierr); 70*6e191704SLawrence Mitchell IndexSpaceRestore(buf,nrow*rbs,ncol*cbs,irowm,icolm); 712c0dbf93SJed Brown PetscFunctionReturn(0); 722c0dbf93SJed Brown } 732c0dbf93SJed Brown 742c0dbf93SJed Brown #undef __FUNCT__ 752c0dbf93SJed Brown #define __FUNCT__ "MatSetValuesLocal_LocalRef_Scalar" 762c0dbf93SJed Brown static PetscErrorCode MatSetValuesLocal_LocalRef_Scalar(Mat A,PetscInt nrow,const PetscInt irow[],PetscInt ncol,const PetscInt icol[],const PetscScalar y[],InsertMode addv) 772c0dbf93SJed Brown { 782c0dbf93SJed Brown Mat_LocalRef *lr = (Mat_LocalRef*)A->data; 792c0dbf93SJed Brown PetscErrorCode ierr; 802c0dbf93SJed Brown PetscInt buf[4096],*irowm,*icolm; 812c0dbf93SJed Brown 822c0dbf93SJed Brown PetscFunctionBegin; 832c0dbf93SJed Brown IndexSpaceGet(buf,nrow,ncol,irowm,icolm); 8412e05225SLawrence Mitchell ierr = ISLocalToGlobalMappingApplyBlock(A->rmap->mapping,nrow,irow,irowm);CHKERRQ(ierr); 8512e05225SLawrence Mitchell ierr = ISLocalToGlobalMappingApplyBlock(A->cmap->mapping,ncol,icol,icolm);CHKERRQ(ierr); 862c0dbf93SJed Brown ierr = (*lr->SetValues)(lr->Top,nrow,irowm,ncol,icolm,y,addv);CHKERRQ(ierr); 872c0dbf93SJed Brown IndexSpaceRestore(buf,nrow,ncol,irowm,icolm); 882c0dbf93SJed Brown PetscFunctionReturn(0); 892c0dbf93SJed Brown } 902c0dbf93SJed Brown 912c0dbf93SJed Brown #undef __FUNCT__ 922c0dbf93SJed Brown #define __FUNCT__ "ISL2GCompose" 932265a299SJed Brown /* Compose an IS with an ISLocalToGlobalMapping to map from IS source indices to global indices */ 942c0dbf93SJed Brown static PetscErrorCode ISL2GCompose(IS is,ISLocalToGlobalMapping ltog,ISLocalToGlobalMapping *cltog) 952c0dbf93SJed Brown { 962c0dbf93SJed Brown PetscErrorCode ierr; 972c0dbf93SJed Brown const PetscInt *idx; 982c0dbf93SJed Brown PetscInt m,*idxm; 9912e05225SLawrence Mitchell PetscInt bs; 100565245c5SBarry Smith PetscBool isblock; 1012c0dbf93SJed Brown 1022c0dbf93SJed Brown PetscFunctionBegin; 103b3e8af9fSJed Brown PetscValidHeaderSpecific(is,IS_CLASSID,1); 104b3e8af9fSJed Brown PetscValidHeaderSpecific(ltog,IS_LTOGM_CLASSID,2); 105b3e8af9fSJed Brown PetscValidPointer(cltog,3); 106565245c5SBarry Smith ierr = PetscObjectTypeCompare((PetscObject)is,ISBLOCK,&isblock);CHKERRQ(ierr); 107565245c5SBarry Smith if (isblock) { 10812e05225SLawrence Mitchell PetscInt lbs; 109565245c5SBarry Smith 110565245c5SBarry Smith ierr = ISGetBlockSize(is,&bs);CHKERRQ(ierr); 111565245c5SBarry Smith ierr = ISLocalToGlobalMappingGetBlockSize(ltog,&lbs);CHKERRQ(ierr); 112565245c5SBarry Smith if (bs == lbs) { 113565245c5SBarry Smith ierr = ISGetLocalSize(is,&m);CHKERRQ(ierr); 114565245c5SBarry Smith m = m/bs; 115565245c5SBarry Smith ierr = ISBlockGetIndices(is,&idx);CHKERRQ(ierr); 116565245c5SBarry Smith ierr = PetscMalloc1(m,&idxm);CHKERRQ(ierr); 117565245c5SBarry Smith ierr = ISLocalToGlobalMappingApplyBlock(ltog,m,idx,idxm);CHKERRQ(ierr); 118565245c5SBarry Smith ierr = ISLocalToGlobalMappingCreate(PetscObjectComm((PetscObject)is),bs,m,idxm,PETSC_OWN_POINTER,cltog);CHKERRQ(ierr); 119565245c5SBarry Smith ierr = ISBlockRestoreIndices(is,&idx);CHKERRQ(ierr); 120565245c5SBarry Smith PetscFunctionReturn(0); 121565245c5SBarry Smith } 122565245c5SBarry Smith } 1232c0dbf93SJed Brown ierr = ISGetLocalSize(is,&m);CHKERRQ(ierr); 1242c0dbf93SJed Brown ierr = ISGetIndices(is,&idx);CHKERRQ(ierr); 12512e05225SLawrence Mitchell ierr = ISGetBlockSize(is,&bs);CHKERRQ(ierr); 126785e854fSJed Brown ierr = PetscMalloc1(m,&idxm);CHKERRQ(ierr); 1272c0dbf93SJed Brown if (ltog) { 1282c0dbf93SJed Brown ierr = ISLocalToGlobalMappingApply(ltog,m,idx,idxm);CHKERRQ(ierr); 1292c0dbf93SJed Brown } else { 1302c0dbf93SJed Brown ierr = PetscMemcpy(idxm,idx,m*sizeof(PetscInt));CHKERRQ(ierr); 1312c0dbf93SJed Brown } 13212e05225SLawrence Mitchell ierr = ISLocalToGlobalMappingCreate(PetscObjectComm((PetscObject)is),bs,m,idxm,PETSC_OWN_POINTER,cltog);CHKERRQ(ierr); 1332c0dbf93SJed Brown ierr = ISRestoreIndices(is,&idx);CHKERRQ(ierr); 1342c0dbf93SJed Brown PetscFunctionReturn(0); 1352c0dbf93SJed Brown } 1362c0dbf93SJed Brown 1372c0dbf93SJed Brown #undef __FUNCT__ 1382c0dbf93SJed Brown #define __FUNCT__ "ISL2GComposeBlock" 1392c0dbf93SJed Brown static PetscErrorCode ISL2GComposeBlock(IS is,ISLocalToGlobalMapping ltog,ISLocalToGlobalMapping *cltog) 1402c0dbf93SJed Brown { 1412c0dbf93SJed Brown PetscErrorCode ierr; 1422c0dbf93SJed Brown const PetscInt *idx; 14345b6f7e9SBarry Smith PetscInt m,*idxm,bs; 1442c0dbf93SJed Brown 1452c0dbf93SJed Brown PetscFunctionBegin; 146b3e8af9fSJed Brown PetscValidHeaderSpecific(is,IS_CLASSID,1); 147b3e8af9fSJed Brown PetscValidHeaderSpecific(ltog,IS_LTOGM_CLASSID,2); 148b3e8af9fSJed Brown PetscValidPointer(cltog,3); 1492c0dbf93SJed Brown ierr = ISBlockGetLocalSize(is,&m);CHKERRQ(ierr); 1502c0dbf93SJed Brown ierr = ISBlockGetIndices(is,&idx);CHKERRQ(ierr); 15145b6f7e9SBarry Smith ierr = ISLocalToGlobalMappingGetBlockSize(ltog,&bs);CHKERRQ(ierr); 152785e854fSJed Brown ierr = PetscMalloc1(m,&idxm);CHKERRQ(ierr); 1532c0dbf93SJed Brown if (ltog) { 15445b6f7e9SBarry Smith ierr = ISLocalToGlobalMappingApplyBlock(ltog,m,idx,idxm);CHKERRQ(ierr); 1552c0dbf93SJed Brown } else { 1562c0dbf93SJed Brown ierr = PetscMemcpy(idxm,idx,m*sizeof(PetscInt));CHKERRQ(ierr); 1572c0dbf93SJed Brown } 15845b6f7e9SBarry Smith ierr = ISLocalToGlobalMappingCreate(PetscObjectComm((PetscObject)is),bs,m,idxm,PETSC_OWN_POINTER,cltog);CHKERRQ(ierr); 1592c0dbf93SJed Brown ierr = ISBlockRestoreIndices(is,&idx);CHKERRQ(ierr); 1602c0dbf93SJed Brown PetscFunctionReturn(0); 1612c0dbf93SJed Brown } 1622c0dbf93SJed Brown 1632c0dbf93SJed Brown #undef __FUNCT__ 1642c0dbf93SJed Brown #define __FUNCT__ "MatDestroy_LocalRef" 1652c0dbf93SJed Brown static PetscErrorCode MatDestroy_LocalRef(Mat B) 1662c0dbf93SJed Brown { 1672c0dbf93SJed Brown PetscErrorCode ierr; 1682c0dbf93SJed Brown 1692c0dbf93SJed Brown PetscFunctionBegin; 1702c0dbf93SJed Brown ierr = PetscFree(B->data);CHKERRQ(ierr); 1712c0dbf93SJed Brown PetscFunctionReturn(0); 1722c0dbf93SJed Brown } 1732c0dbf93SJed Brown 1742c0dbf93SJed Brown 1752c0dbf93SJed Brown #undef __FUNCT__ 1762c0dbf93SJed Brown #define __FUNCT__ "MatCreateLocalRef" 1772c0dbf93SJed Brown /*@ 1782c0dbf93SJed Brown MatCreateLocalRef - Gets a logical reference to a local submatrix, for use in assembly 1792c0dbf93SJed Brown 1802c0dbf93SJed Brown Not Collective 1812c0dbf93SJed Brown 1822c0dbf93SJed Brown Input Arguments: 1832c0dbf93SJed Brown + A - Full matrix, generally parallel 1842c0dbf93SJed Brown . isrow - Local index set for the rows 1852c0dbf93SJed Brown - iscol - Local index set for the columns 1862c0dbf93SJed Brown 1872c0dbf93SJed Brown Output Arguments: 1882c0dbf93SJed Brown . newmat - New serial Mat 1892c0dbf93SJed Brown 1902c0dbf93SJed Brown Level: developer 1912c0dbf93SJed Brown 1922c0dbf93SJed Brown Notes: 1932c0dbf93SJed Brown Most will use MatGetLocalSubMatrix() which returns a real matrix corresponding to the local 1942c0dbf93SJed Brown block if it available, such as with matrix formats that store these blocks separately. 1952c0dbf93SJed Brown 1962c0dbf93SJed Brown The new matrix forwards MatSetValuesLocal() and MatSetValuesBlockedLocal() to the global system. 1972c0dbf93SJed Brown In general, it does not define MatMult() or any other functions. Local submatrices can be nested. 1982c0dbf93SJed Brown 1992c0dbf93SJed Brown .seealso: MatSetValuesLocal(), MatSetValuesBlockedLocal(), MatGetLocalSubMatrix(), MatCreateSubMatrix() 2002c0dbf93SJed Brown @*/ 2017087cfbeSBarry Smith PetscErrorCode MatCreateLocalRef(Mat A,IS isrow,IS iscol,Mat *newmat) 2022c0dbf93SJed Brown { 2032c0dbf93SJed Brown PetscErrorCode ierr; 2042c0dbf93SJed Brown Mat_LocalRef *lr; 2052c0dbf93SJed Brown Mat B; 2062c0dbf93SJed Brown PetscInt m,n; 2072c0dbf93SJed Brown PetscBool islr; 2082c0dbf93SJed Brown 2092c0dbf93SJed Brown PetscFunctionBegin; 2102c0dbf93SJed Brown PetscValidHeaderSpecific(A,MAT_CLASSID,1); 2112c0dbf93SJed Brown PetscValidHeaderSpecific(isrow,IS_CLASSID,2); 2122c0dbf93SJed Brown PetscValidHeaderSpecific(iscol,IS_CLASSID,3); 2132c0dbf93SJed Brown PetscValidPointer(newmat,4); 2142c0dbf93SJed Brown *newmat = 0; 2152c0dbf93SJed Brown 2162c0dbf93SJed Brown ierr = MatCreate(PETSC_COMM_SELF,&B);CHKERRQ(ierr); 2172c0dbf93SJed Brown ierr = ISGetLocalSize(isrow,&m);CHKERRQ(ierr); 2182c0dbf93SJed Brown ierr = ISGetLocalSize(iscol,&n);CHKERRQ(ierr); 2192c0dbf93SJed Brown ierr = MatSetSizes(B,m,n,m,n);CHKERRQ(ierr); 2202c0dbf93SJed Brown ierr = PetscObjectChangeTypeName((PetscObject)B,MATLOCALREF);CHKERRQ(ierr); 221be7c243fSJed Brown ierr = MatSetUp(B);CHKERRQ(ierr); 2222c0dbf93SJed Brown 2232c0dbf93SJed Brown B->ops->destroy = MatDestroy_LocalRef; 2242c0dbf93SJed Brown 225b00a9115SJed Brown ierr = PetscNewLog(B,&lr);CHKERRQ(ierr); 2262c0dbf93SJed Brown B->data = (void*)lr; 2272c0dbf93SJed Brown 228251f4c67SDmitry Karpeev ierr = PetscObjectTypeCompare((PetscObject)A,MATLOCALREF,&islr);CHKERRQ(ierr); 2292265a299SJed Brown if (islr) { 2302265a299SJed Brown Mat_LocalRef *alr = (Mat_LocalRef*)A->data; 2312265a299SJed Brown lr->Top = alr->Top; 2322265a299SJed Brown } else { 2332265a299SJed Brown /* This does not increase the reference count because MatLocalRef is not allowed to live longer than its parent */ 2342265a299SJed Brown lr->Top = A; 2352265a299SJed Brown } 2362265a299SJed Brown { 2372c0dbf93SJed Brown ISLocalToGlobalMapping rltog,cltog; 238*6e191704SLawrence Mitchell PetscInt arbs,acbs,rbs,cbs; 2392c0dbf93SJed Brown 2402265a299SJed Brown /* We will translate directly to global indices for the top level */ 2412c0dbf93SJed Brown lr->SetValues = MatSetValues; 2422c0dbf93SJed Brown lr->SetValuesBlocked = MatSetValuesBlocked; 2432c0dbf93SJed Brown 2442c0dbf93SJed Brown B->ops->setvalueslocal = MatSetValuesLocal_LocalRef_Scalar; 2452205254eSKarl Rupp 246992144d0SBarry Smith ierr = ISL2GCompose(isrow,A->rmap->mapping,&rltog);CHKERRQ(ierr); 247992144d0SBarry Smith if (isrow == iscol && A->rmap->mapping == A->cmap->mapping) { 2482c0dbf93SJed Brown ierr = PetscObjectReference((PetscObject)rltog);CHKERRQ(ierr); 2492c0dbf93SJed Brown cltog = rltog; 2502c0dbf93SJed Brown } else { 251992144d0SBarry Smith ierr = ISL2GCompose(iscol,A->cmap->mapping,&cltog);CHKERRQ(ierr); 2522c0dbf93SJed Brown } 2532c0dbf93SJed Brown ierr = MatSetLocalToGlobalMapping(B,rltog,cltog);CHKERRQ(ierr); 2546bf464f9SBarry Smith ierr = ISLocalToGlobalMappingDestroy(&rltog);CHKERRQ(ierr); 2556bf464f9SBarry Smith ierr = ISLocalToGlobalMappingDestroy(&cltog);CHKERRQ(ierr); 2562c0dbf93SJed Brown 257*6e191704SLawrence Mitchell ierr = MatGetBlockSizes(A,&arbs,&acbs);CHKERRQ(ierr); 258520db06cSJed Brown ierr = ISGetBlockSize(isrow,&rbs);CHKERRQ(ierr); 259520db06cSJed Brown ierr = ISGetBlockSize(iscol,&cbs);CHKERRQ(ierr); 260*6e191704SLawrence Mitchell /* Always support block interface insertion on submatrix */ 26192ea8381SJed Brown ierr = PetscLayoutSetBlockSize(B->rmap,rbs);CHKERRQ(ierr); 26292ea8381SJed Brown ierr = PetscLayoutSetBlockSize(B->cmap,cbs);CHKERRQ(ierr); 263*6e191704SLawrence Mitchell if (arbs != rbs || acbs != cbs || (arbs == 1 && acbs == 1)) { 2642c0dbf93SJed Brown /* Top-level matrix has different block size, so we have to call its scalar insertion interface */ 2652c0dbf93SJed Brown B->ops->setvaluesblockedlocal = MatSetValuesBlockedLocal_LocalRef_Scalar; 2662c0dbf93SJed Brown } else { 2672c0dbf93SJed Brown /* Block sizes match so we can forward values to the top level using the block interface */ 2682c0dbf93SJed Brown B->ops->setvaluesblockedlocal = MatSetValuesBlockedLocal_LocalRef_Block; 26926fbe8dcSKarl Rupp 27045b6f7e9SBarry Smith ierr = ISL2GComposeBlock(isrow,A->rmap->mapping,&rltog);CHKERRQ(ierr); 27145b6f7e9SBarry Smith if (isrow == iscol && A->rmap->mapping == A->cmap->mapping) { 2722c0dbf93SJed Brown ierr = PetscObjectReference((PetscObject)rltog);CHKERRQ(ierr); 2732c0dbf93SJed Brown cltog = rltog; 2742c0dbf93SJed Brown } else { 27545b6f7e9SBarry Smith ierr = ISL2GComposeBlock(iscol,A->cmap->mapping,&cltog);CHKERRQ(ierr); 2762c0dbf93SJed Brown } 27745b6f7e9SBarry Smith ierr = MatSetLocalToGlobalMapping(B,rltog,cltog);CHKERRQ(ierr); 2786bf464f9SBarry Smith ierr = ISLocalToGlobalMappingDestroy(&rltog);CHKERRQ(ierr); 2796bf464f9SBarry Smith ierr = ISLocalToGlobalMappingDestroy(&cltog);CHKERRQ(ierr); 2802c0dbf93SJed Brown } 2812c0dbf93SJed Brown } 2822c0dbf93SJed Brown *newmat = B; 2832c0dbf93SJed Brown PetscFunctionReturn(0); 2842c0dbf93SJed Brown } 285