12c0dbf93SJed Brown #define PETSCMAT_DLL 22c0dbf93SJed Brown 32c0dbf93SJed Brown #include "private/matimpl.h" /*I "petscmat.h" I*/ 42c0dbf93SJed Brown 52c0dbf93SJed Brown typedef struct { 62c0dbf93SJed Brown Mat Top; 72c0dbf93SJed Brown PetscErrorCode (*SetValues)(Mat,PetscInt,const PetscInt[],PetscInt,const PetscInt[],const PetscScalar[],InsertMode); 82c0dbf93SJed Brown PetscErrorCode (*SetValuesBlocked)(Mat,PetscInt,const PetscInt[],PetscInt,const PetscInt[],const PetscScalar[],InsertMode); 92c0dbf93SJed Brown } Mat_LocalRef; 102c0dbf93SJed Brown 112c0dbf93SJed Brown /* These need to be macros because they use sizeof */ 122c0dbf93SJed Brown #define IndexSpaceGet(buf,nrow,ncol,irowm,icolm) do { \ 132c0dbf93SJed Brown if (nrow + ncol > sizeof(buf)/sizeof(buf[0])) { \ 142c0dbf93SJed Brown ierr = PetscMalloc2(nrow,PetscInt,&irowm,ncol,PetscInt,&icolm);CHKERRQ(ierr); \ 152c0dbf93SJed Brown } else { \ 162c0dbf93SJed Brown irowm = &buf[0]; \ 172c0dbf93SJed Brown icolm = &buf[nrow]; \ 182c0dbf93SJed Brown } \ 192c0dbf93SJed Brown } while (0) 202c0dbf93SJed Brown 212c0dbf93SJed Brown #define IndexSpaceRestore(buf,nrow,ncol,irowm,icolm) do { \ 222c0dbf93SJed Brown if (nrow + ncol > sizeof(buf)/sizeof(buf[0])) { \ 232c0dbf93SJed Brown ierr = PetscFree2(irowm,icolm);CHKERRQ(ierr); \ 242c0dbf93SJed Brown } \ 252c0dbf93SJed Brown } while (0) 262c0dbf93SJed Brown 272c0dbf93SJed Brown static void BlockIndicesExpand(PetscInt n,const PetscInt idx[],PetscInt bs,PetscInt idxm[]) 282c0dbf93SJed Brown { 292c0dbf93SJed Brown PetscInt i,j; 302c0dbf93SJed Brown for (i=0; i<n; i++) { 312c0dbf93SJed Brown for (j=0; j<bs; j++) { 322c0dbf93SJed Brown idxm[i*bs+j] = idx[i]*bs + j; 332c0dbf93SJed Brown } 342c0dbf93SJed Brown } 352c0dbf93SJed Brown } 362c0dbf93SJed Brown 372c0dbf93SJed Brown #undef __FUNCT__ 382c0dbf93SJed Brown #define __FUNCT__ "MatSetValuesBlockedLocal_LocalRef_Block" 392c0dbf93SJed Brown static PetscErrorCode MatSetValuesBlockedLocal_LocalRef_Block(Mat A,PetscInt nrow,const PetscInt irow[],PetscInt ncol,const PetscInt icol[],const PetscScalar y[],InsertMode addv) 402c0dbf93SJed Brown { 412c0dbf93SJed Brown Mat_LocalRef *lr = (Mat_LocalRef*)A->data; 422c0dbf93SJed Brown PetscErrorCode ierr; 432c0dbf93SJed Brown PetscInt buf[4096],*irowm,*icolm; 442c0dbf93SJed Brown 452c0dbf93SJed Brown PetscFunctionBegin; 462c0dbf93SJed Brown if (!nrow || !ncol) PetscFunctionReturn(0); 472c0dbf93SJed Brown IndexSpaceGet(buf,nrow,ncol,irowm,icolm); 482c0dbf93SJed Brown ierr = ISLocalToGlobalMappingApply(A->rbmapping,nrow,irow,irowm);CHKERRQ(ierr); 492c0dbf93SJed Brown ierr = ISLocalToGlobalMappingApply(A->cbmapping,ncol,icol,icolm);CHKERRQ(ierr); 502c0dbf93SJed Brown ierr = (*lr->SetValuesBlocked)(lr->Top,nrow,irowm,ncol,icolm,y,addv);CHKERRQ(ierr); 512c0dbf93SJed Brown IndexSpaceRestore(buf,nrow,ncol,irowm,icolm); 522c0dbf93SJed Brown PetscFunctionReturn(0); 532c0dbf93SJed Brown } 542c0dbf93SJed Brown 552c0dbf93SJed Brown #undef __FUNCT__ 562c0dbf93SJed Brown #define __FUNCT__ "MatSetValuesBlockedLocal_LocalRef_Scalar" 572c0dbf93SJed Brown static PetscErrorCode MatSetValuesBlockedLocal_LocalRef_Scalar(Mat A,PetscInt nrow,const PetscInt irow[],PetscInt ncol,const PetscInt icol[],const PetscScalar y[],InsertMode addv) 582c0dbf93SJed Brown { 592c0dbf93SJed Brown Mat_LocalRef *lr = (Mat_LocalRef*)A->data; 602c0dbf93SJed Brown PetscErrorCode ierr; 612c0dbf93SJed Brown PetscInt bs = A->rmap->bs,buf[4096],*irowm,*icolm; 622c0dbf93SJed Brown 632c0dbf93SJed Brown PetscFunctionBegin; 642c0dbf93SJed Brown IndexSpaceGet(buf,nrow*bs,ncol*bs,irowm,icolm); 652c0dbf93SJed Brown BlockIndicesExpand(nrow,irow,bs,irowm); 662c0dbf93SJed Brown BlockIndicesExpand(ncol,icol,bs,icolm); 672c0dbf93SJed Brown ierr = ISLocalToGlobalMappingApply(A->rmapping,nrow*bs,irowm,irowm);CHKERRQ(ierr); 682c0dbf93SJed Brown ierr = ISLocalToGlobalMappingApply(A->cmapping,ncol*bs,icolm,icolm);CHKERRQ(ierr); 692c0dbf93SJed Brown ierr = (*lr->SetValues)(lr->Top,nrow*bs,irowm,ncol*bs,icolm,y,addv);CHKERRQ(ierr); 702c0dbf93SJed Brown IndexSpaceRestore(buf,nrow*bs,ncol*bs,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); 842c0dbf93SJed Brown ierr = ISLocalToGlobalMappingApply(A->rmapping,nrow,irow,irowm);CHKERRQ(ierr); 852c0dbf93SJed Brown ierr = ISLocalToGlobalMappingApply(A->cmapping,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" 932c0dbf93SJed Brown static PetscErrorCode ISL2GCompose(IS is,ISLocalToGlobalMapping ltog,ISLocalToGlobalMapping *cltog) 942c0dbf93SJed Brown { 952c0dbf93SJed Brown PetscErrorCode ierr; 962c0dbf93SJed Brown const PetscInt *idx; 972c0dbf93SJed Brown PetscInt m,*idxm; 982c0dbf93SJed Brown 992c0dbf93SJed Brown PetscFunctionBegin; 100*b3e8af9fSJed Brown PetscValidHeaderSpecific(is,IS_CLASSID,1); 101*b3e8af9fSJed Brown PetscValidHeaderSpecific(ltog,IS_LTOGM_CLASSID,2); 102*b3e8af9fSJed Brown PetscValidPointer(cltog,3); 1032c0dbf93SJed Brown ierr = ISGetLocalSize(is,&m);CHKERRQ(ierr); 1042c0dbf93SJed Brown ierr = ISGetIndices(is,&idx);CHKERRQ(ierr); 1052c0dbf93SJed Brown #if defined(PETSC_USE_DEBUG) 1062c0dbf93SJed Brown { 1072c0dbf93SJed Brown PetscInt i; 1082c0dbf93SJed Brown for (i=0; i<m; i++) { 1092c0dbf93SJed Brown if (idx[i] < 0 || ltog->n <= idx[i]) SETERRQ3(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"is[%D] = %D is not in the local range [0:%D]",i,idx[i],ltog->n); 1102c0dbf93SJed Brown } 1112c0dbf93SJed Brown } 1122c0dbf93SJed Brown #endif 1132c0dbf93SJed Brown ierr = PetscMalloc(m*sizeof(PetscInt),&idxm);CHKERRQ(ierr); 1142c0dbf93SJed Brown if (ltog) { 1152c0dbf93SJed Brown ierr = ISLocalToGlobalMappingApply(ltog,m,idx,idxm);CHKERRQ(ierr); 1162c0dbf93SJed Brown } else { 1172c0dbf93SJed Brown ierr = PetscMemcpy(idxm,idx,m*sizeof(PetscInt));CHKERRQ(ierr); 1182c0dbf93SJed Brown } 1192c0dbf93SJed Brown ierr = ISLocalToGlobalMappingCreate(((PetscObject)is)->comm,m,idxm,PETSC_OWN_POINTER,cltog);CHKERRQ(ierr); 1202c0dbf93SJed Brown ierr = ISRestoreIndices(is,&idx);CHKERRQ(ierr); 1212c0dbf93SJed Brown PetscFunctionReturn(0); 1222c0dbf93SJed Brown } 1232c0dbf93SJed Brown 1242c0dbf93SJed Brown #undef __FUNCT__ 1252c0dbf93SJed Brown #define __FUNCT__ "ISL2GComposeBlock" 1262c0dbf93SJed Brown static PetscErrorCode ISL2GComposeBlock(IS is,ISLocalToGlobalMapping ltog,ISLocalToGlobalMapping *cltog) 1272c0dbf93SJed Brown { 1282c0dbf93SJed Brown PetscErrorCode ierr; 1292c0dbf93SJed Brown const PetscInt *idx; 1302c0dbf93SJed Brown PetscInt m,*idxm; 1312c0dbf93SJed Brown 1322c0dbf93SJed Brown PetscFunctionBegin; 133*b3e8af9fSJed Brown PetscValidHeaderSpecific(is,IS_CLASSID,1); 134*b3e8af9fSJed Brown PetscValidHeaderSpecific(ltog,IS_LTOGM_CLASSID,2); 135*b3e8af9fSJed Brown PetscValidPointer(cltog,3); 1362c0dbf93SJed Brown ierr = ISBlockGetLocalSize(is,&m);CHKERRQ(ierr); 1372c0dbf93SJed Brown ierr = ISBlockGetIndices(is,&idx);CHKERRQ(ierr); 1382c0dbf93SJed Brown #if defined(PETSC_USE_DEBUG) 1392c0dbf93SJed Brown { 1402c0dbf93SJed Brown PetscInt i; 1412c0dbf93SJed Brown for (i=0; i<m; i++) { 1422c0dbf93SJed Brown if (idx[i] < 0 || ltog->n <= idx[i]) SETERRQ3(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"is[%D] = %D is not in the local range [0:%D]",i,idx[i],ltog->n); 1432c0dbf93SJed Brown } 1442c0dbf93SJed Brown } 1452c0dbf93SJed Brown #endif 1462c0dbf93SJed Brown ierr = PetscMalloc(m*sizeof(PetscInt),&idxm);CHKERRQ(ierr); 1472c0dbf93SJed Brown if (ltog) { 1482c0dbf93SJed Brown ierr = ISLocalToGlobalMappingApply(ltog,m,idx,idxm);CHKERRQ(ierr); 1492c0dbf93SJed Brown } else { 1502c0dbf93SJed Brown ierr = PetscMemcpy(idxm,idx,m*sizeof(PetscInt));CHKERRQ(ierr); 1512c0dbf93SJed Brown } 1522c0dbf93SJed Brown ierr = ISLocalToGlobalMappingCreate(((PetscObject)is)->comm,m,idxm,PETSC_OWN_POINTER,cltog);CHKERRQ(ierr); 1532c0dbf93SJed Brown ierr = ISBlockRestoreIndices(is,&idx);CHKERRQ(ierr); 1542c0dbf93SJed Brown PetscFunctionReturn(0); 1552c0dbf93SJed Brown } 1562c0dbf93SJed Brown 1572c0dbf93SJed Brown #undef __FUNCT__ 1582c0dbf93SJed Brown #define __FUNCT__ "MatDestroy_LocalRef" 1592c0dbf93SJed Brown static PetscErrorCode MatDestroy_LocalRef(Mat B) 1602c0dbf93SJed Brown { 1612c0dbf93SJed Brown PetscErrorCode ierr; 1622c0dbf93SJed Brown 1632c0dbf93SJed Brown PetscFunctionBegin; 1642c0dbf93SJed Brown ierr = PetscFree(B->data);CHKERRQ(ierr); 1652c0dbf93SJed Brown PetscFunctionReturn(0); 1662c0dbf93SJed Brown } 1672c0dbf93SJed Brown 1682c0dbf93SJed Brown 1692c0dbf93SJed Brown #undef __FUNCT__ 1702c0dbf93SJed Brown #define __FUNCT__ "MatCreateLocalRef" 1712c0dbf93SJed Brown /*@ 1722c0dbf93SJed Brown MatCreateLocalRef - Gets a logical reference to a local submatrix, for use in assembly 1732c0dbf93SJed Brown 1742c0dbf93SJed Brown Not Collective 1752c0dbf93SJed Brown 1762c0dbf93SJed Brown Input Arguments: 1772c0dbf93SJed Brown + A - Full matrix, generally parallel 1782c0dbf93SJed Brown . isrow - Local index set for the rows 1792c0dbf93SJed Brown - iscol - Local index set for the columns 1802c0dbf93SJed Brown 1812c0dbf93SJed Brown Output Arguments: 1822c0dbf93SJed Brown . newmat - New serial Mat 1832c0dbf93SJed Brown 1842c0dbf93SJed Brown Level: developer 1852c0dbf93SJed Brown 1862c0dbf93SJed Brown Notes: 1872c0dbf93SJed Brown Most will use MatGetLocalSubMatrix() which returns a real matrix corresponding to the local 1882c0dbf93SJed Brown block if it available, such as with matrix formats that store these blocks separately. 1892c0dbf93SJed Brown 1902c0dbf93SJed Brown The new matrix forwards MatSetValuesLocal() and MatSetValuesBlockedLocal() to the global system. 1912c0dbf93SJed Brown In general, it does not define MatMult() or any other functions. Local submatrices can be nested. 1922c0dbf93SJed Brown 1932c0dbf93SJed Brown .seealso: MatSetValuesLocal(), MatSetValuesBlockedLocal(), MatGetLocalSubMatrix(), MatCreateSubMatrix() 1942c0dbf93SJed Brown @*/ 1952c0dbf93SJed Brown PetscErrorCode PETSCMAT_DLLEXPORT MatCreateLocalRef(Mat A,IS isrow,IS iscol,Mat *newmat) 1962c0dbf93SJed Brown { 1972c0dbf93SJed Brown PetscErrorCode ierr; 1982c0dbf93SJed Brown Mat_LocalRef *lr; 1992c0dbf93SJed Brown Mat B; 2002c0dbf93SJed Brown PetscInt m,n; 2012c0dbf93SJed Brown PetscBool islr; 2022c0dbf93SJed Brown 2032c0dbf93SJed Brown PetscFunctionBegin; 2042c0dbf93SJed Brown PetscValidHeaderSpecific(A,MAT_CLASSID,1); 2052c0dbf93SJed Brown PetscValidHeaderSpecific(isrow,IS_CLASSID,2); 2062c0dbf93SJed Brown PetscValidHeaderSpecific(iscol,IS_CLASSID,3); 2072c0dbf93SJed Brown PetscValidPointer(newmat,4); 2082c0dbf93SJed Brown *newmat = 0; 2092c0dbf93SJed Brown 2102c0dbf93SJed Brown ierr = MatCreate(PETSC_COMM_SELF,&B);CHKERRQ(ierr); 2112c0dbf93SJed Brown ierr = ISGetLocalSize(isrow,&m);CHKERRQ(ierr); 2122c0dbf93SJed Brown ierr = ISGetLocalSize(iscol,&n);CHKERRQ(ierr); 2132c0dbf93SJed Brown ierr = MatSetSizes(B,m,n,m,n);CHKERRQ(ierr); 2142c0dbf93SJed Brown ierr = PetscObjectChangeTypeName((PetscObject)B,MATLOCALREF);CHKERRQ(ierr); 2152c0dbf93SJed Brown 2162c0dbf93SJed Brown B->ops->destroy = MatDestroy_LocalRef; 2172c0dbf93SJed Brown 2182c0dbf93SJed Brown ierr = PetscNewLog(B,Mat_LocalRef,&lr);CHKERRQ(ierr); 2192c0dbf93SJed Brown B->data = (void*)lr; 2202c0dbf93SJed Brown 2212c0dbf93SJed Brown ierr = PetscTypeCompare((PetscObject)A,MATLOCALREF,&islr);CHKERRQ(ierr); 2222c0dbf93SJed Brown if (islr) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Nesting MatLocalRef not implemented yet"); 2232c0dbf93SJed Brown else { 2242c0dbf93SJed Brown ISLocalToGlobalMapping rltog,cltog; 2252c0dbf93SJed Brown PetscInt abs,rbs,cbs; 2262c0dbf93SJed Brown 2272c0dbf93SJed Brown /* This does not increase the reference count because MatLocalRef is not allowed to live longer than its parent */ 2282c0dbf93SJed Brown lr->Top = A; 2292c0dbf93SJed Brown 2302c0dbf93SJed Brown /* The immediate parent is the top level and we will translate directly to global indices */ 2312c0dbf93SJed Brown lr->SetValues = MatSetValues; 2322c0dbf93SJed Brown lr->SetValuesBlocked = MatSetValuesBlocked; 2332c0dbf93SJed Brown 2342c0dbf93SJed Brown B->ops->setvalueslocal = MatSetValuesLocal_LocalRef_Scalar; 2352c0dbf93SJed Brown ierr = ISL2GCompose(isrow,A->rmapping,&rltog);CHKERRQ(ierr); 2362c0dbf93SJed Brown if (isrow == iscol && A->rmapping == A->cmapping) { 2372c0dbf93SJed Brown ierr = PetscObjectReference((PetscObject)rltog);CHKERRQ(ierr); 2382c0dbf93SJed Brown cltog = rltog; 2392c0dbf93SJed Brown } else { 2402c0dbf93SJed Brown ierr = ISL2GCompose(iscol,A->cmapping,&cltog);CHKERRQ(ierr); 2412c0dbf93SJed Brown } 2422c0dbf93SJed Brown ierr = MatSetLocalToGlobalMapping(B,rltog,cltog);CHKERRQ(ierr); 2432c0dbf93SJed Brown ierr = ISLocalToGlobalMappingDestroy(rltog);CHKERRQ(ierr); 2442c0dbf93SJed Brown ierr = ISLocalToGlobalMappingDestroy(cltog);CHKERRQ(ierr); 2452c0dbf93SJed Brown 2462c0dbf93SJed Brown ierr = MatGetBlockSize(A,&abs);CHKERRQ(ierr); 247520db06cSJed Brown ierr = ISGetBlockSize(isrow,&rbs);CHKERRQ(ierr); 248520db06cSJed Brown ierr = ISGetBlockSize(iscol,&cbs);CHKERRQ(ierr); 2492c0dbf93SJed Brown if (rbs == cbs) { /* submatrix has block structure, so user can insert values with blocked interface */ 2502c0dbf93SJed Brown ierr = PetscLayoutSetBlockSize(A->rmap,abs);CHKERRQ(ierr); 2512c0dbf93SJed Brown ierr = PetscLayoutSetBlockSize(A->rmap,abs);CHKERRQ(ierr); 2522c0dbf93SJed Brown if (abs != rbs) { 2532c0dbf93SJed Brown /* Top-level matrix has different block size, so we have to call its scalar insertion interface */ 2542c0dbf93SJed Brown B->ops->setvaluesblockedlocal = MatSetValuesBlockedLocal_LocalRef_Scalar; 2552c0dbf93SJed Brown } else { 2562c0dbf93SJed Brown /* Block sizes match so we can forward values to the top level using the block interface */ 2572c0dbf93SJed Brown B->ops->setvaluesblockedlocal = MatSetValuesBlockedLocal_LocalRef_Block; 2582c0dbf93SJed Brown ierr = ISL2GComposeBlock(isrow,A->rbmapping,&rltog);CHKERRQ(ierr); 2592c0dbf93SJed Brown if (isrow == iscol && A->rbmapping == A->cbmapping) { 2602c0dbf93SJed Brown ierr = PetscObjectReference((PetscObject)rltog);CHKERRQ(ierr); 2612c0dbf93SJed Brown cltog = rltog; 2622c0dbf93SJed Brown } else { 2632c0dbf93SJed Brown ierr = ISL2GComposeBlock(iscol,A->cbmapping,&cltog);CHKERRQ(ierr); 2642c0dbf93SJed Brown } 2652c0dbf93SJed Brown ierr = MatSetLocalToGlobalMappingBlock(B,rltog,cltog);CHKERRQ(ierr); 2662c0dbf93SJed Brown ierr = ISLocalToGlobalMappingDestroy(rltog);CHKERRQ(ierr); 2672c0dbf93SJed Brown ierr = ISLocalToGlobalMappingDestroy(cltog);CHKERRQ(ierr); 2682c0dbf93SJed Brown } 2692c0dbf93SJed Brown } 2702c0dbf93SJed Brown } 2712c0dbf93SJed Brown *newmat = B; 2722c0dbf93SJed Brown PetscFunctionReturn(0); 2732c0dbf93SJed Brown } 274