1 2 #include <petsc-private/matimpl.h> /*I "petscmat.h" I*/ 3 4 typedef struct { 5 Mat Top; 6 PetscErrorCode (*SetValues)(Mat,PetscInt,const PetscInt[],PetscInt,const PetscInt[],const PetscScalar[],InsertMode); 7 PetscErrorCode (*SetValuesBlocked)(Mat,PetscInt,const PetscInt[],PetscInt,const PetscInt[],const PetscScalar[],InsertMode); 8 } Mat_LocalRef; 9 10 /* These need to be macros because they use sizeof */ 11 #define IndexSpaceGet(buf,nrow,ncol,irowm,icolm) do { \ 12 if (nrow + ncol > (PetscInt)(sizeof(buf)/sizeof(buf[0]))) { \ 13 ierr = PetscMalloc2(nrow,&irowm,ncol,&icolm);CHKERRQ(ierr); \ 14 } else { \ 15 irowm = &buf[0]; \ 16 icolm = &buf[nrow]; \ 17 } \ 18 } while (0) 19 20 #define IndexSpaceRestore(buf,nrow,ncol,irowm,icolm) do { \ 21 if (nrow + ncol > (PetscInt)(sizeof(buf)/sizeof(buf[0]))) { \ 22 ierr = PetscFree2(irowm,icolm);CHKERRQ(ierr); \ 23 } \ 24 } while (0) 25 26 static void BlockIndicesExpand(PetscInt n,const PetscInt idx[],PetscInt bs,PetscInt idxm[]) 27 { 28 PetscInt i,j; 29 for (i=0; i<n; i++) { 30 for (j=0; j<bs; j++) { 31 idxm[i*bs+j] = idx[i]*bs + j; 32 } 33 } 34 } 35 36 #undef __FUNCT__ 37 #define __FUNCT__ "MatSetValuesBlockedLocal_LocalRef_Block" 38 static PetscErrorCode MatSetValuesBlockedLocal_LocalRef_Block(Mat A,PetscInt nrow,const PetscInt irow[],PetscInt ncol,const PetscInt icol[],const PetscScalar y[],InsertMode addv) 39 { 40 Mat_LocalRef *lr = (Mat_LocalRef*)A->data; 41 PetscErrorCode ierr; 42 PetscInt buf[4096],*irowm,*icolm; 43 44 PetscFunctionBegin; 45 if (!nrow || !ncol) PetscFunctionReturn(0); 46 IndexSpaceGet(buf,nrow,ncol,irowm,icolm); 47 ierr = ISLocalToGlobalMappingApplyBlock(A->rmap->mapping,nrow,irow,irowm);CHKERRQ(ierr); 48 ierr = ISLocalToGlobalMappingApplyBlock(A->cmap->mapping,ncol,icol,icolm);CHKERRQ(ierr); 49 ierr = (*lr->SetValuesBlocked)(lr->Top,nrow,irowm,ncol,icolm,y,addv);CHKERRQ(ierr); 50 IndexSpaceRestore(buf,nrow,ncol,irowm,icolm); 51 PetscFunctionReturn(0); 52 } 53 54 #undef __FUNCT__ 55 #define __FUNCT__ "MatSetValuesBlockedLocal_LocalRef_Scalar" 56 static PetscErrorCode MatSetValuesBlockedLocal_LocalRef_Scalar(Mat A,PetscInt nrow,const PetscInt irow[],PetscInt ncol,const PetscInt icol[],const PetscScalar y[],InsertMode addv) 57 { 58 Mat_LocalRef *lr = (Mat_LocalRef*)A->data; 59 PetscErrorCode ierr; 60 PetscInt bs,buf[4096],*irowm,*icolm; 61 62 PetscFunctionBegin; 63 ierr = MatGetBlockSize(A,&bs);CHKERRQ(ierr); 64 IndexSpaceGet(buf,nrow*bs,ncol*bs,irowm,icolm); 65 BlockIndicesExpand(nrow,irow,bs,irowm); 66 BlockIndicesExpand(ncol,icol,bs,icolm); 67 ierr = ISLocalToGlobalMappingApply(A->rmap->mapping,nrow*bs,irowm,irowm);CHKERRQ(ierr); 68 ierr = ISLocalToGlobalMappingApply(A->cmap->mapping,ncol*bs,icolm,icolm);CHKERRQ(ierr); 69 ierr = (*lr->SetValues)(lr->Top,nrow*bs,irowm,ncol*bs,icolm,y,addv);CHKERRQ(ierr); 70 IndexSpaceRestore(buf,nrow*bs,ncol*bs,irowm,icolm); 71 PetscFunctionReturn(0); 72 } 73 74 #undef __FUNCT__ 75 #define __FUNCT__ "MatSetValuesLocal_LocalRef_Scalar" 76 static PetscErrorCode MatSetValuesLocal_LocalRef_Scalar(Mat A,PetscInt nrow,const PetscInt irow[],PetscInt ncol,const PetscInt icol[],const PetscScalar y[],InsertMode addv) 77 { 78 Mat_LocalRef *lr = (Mat_LocalRef*)A->data; 79 PetscErrorCode ierr; 80 PetscInt buf[4096],*irowm,*icolm; 81 82 PetscFunctionBegin; 83 IndexSpaceGet(buf,nrow,ncol,irowm,icolm); 84 ierr = ISLocalToGlobalMappingApply(A->rmap->mapping,nrow,irow,irowm);CHKERRQ(ierr); 85 ierr = ISLocalToGlobalMappingApply(A->cmap->mapping,ncol,icol,icolm);CHKERRQ(ierr); 86 ierr = (*lr->SetValues)(lr->Top,nrow,irowm,ncol,icolm,y,addv);CHKERRQ(ierr); 87 IndexSpaceRestore(buf,nrow,ncol,irowm,icolm); 88 PetscFunctionReturn(0); 89 } 90 91 #undef __FUNCT__ 92 #define __FUNCT__ "ISL2GCompose" 93 /* Compose an IS with an ISLocalToGlobalMapping to map from IS source indices to global indices */ 94 static PetscErrorCode ISL2GCompose(IS is,ISLocalToGlobalMapping ltog,ISLocalToGlobalMapping *cltog) 95 { 96 PetscErrorCode ierr; 97 const PetscInt *idx; 98 PetscInt m,*idxm; 99 PetscBool isblock; 100 101 PetscFunctionBegin; 102 PetscValidHeaderSpecific(is,IS_CLASSID,1); 103 PetscValidHeaderSpecific(ltog,IS_LTOGM_CLASSID,2); 104 PetscValidPointer(cltog,3); 105 ierr = PetscObjectTypeCompare((PetscObject)is,ISBLOCK,&isblock);CHKERRQ(ierr); 106 if (isblock) { 107 PetscInt bs,lbs; 108 109 ierr = ISGetBlockSize(is,&bs);CHKERRQ(ierr); 110 ierr = ISLocalToGlobalMappingGetBlockSize(ltog,&lbs);CHKERRQ(ierr); 111 if (bs == lbs) { 112 ierr = ISGetLocalSize(is,&m);CHKERRQ(ierr); 113 m = m/bs; 114 ierr = ISBlockGetIndices(is,&idx);CHKERRQ(ierr); 115 ierr = PetscMalloc1(m,&idxm);CHKERRQ(ierr); 116 ierr = ISLocalToGlobalMappingApplyBlock(ltog,m,idx,idxm);CHKERRQ(ierr); 117 ierr = ISLocalToGlobalMappingCreate(PetscObjectComm((PetscObject)is),bs,m,idxm,PETSC_OWN_POINTER,cltog);CHKERRQ(ierr); 118 ierr = ISBlockRestoreIndices(is,&idx);CHKERRQ(ierr); 119 PetscFunctionReturn(0); 120 } 121 } 122 ierr = ISGetLocalSize(is,&m);CHKERRQ(ierr); 123 ierr = ISGetIndices(is,&idx);CHKERRQ(ierr); 124 ierr = PetscMalloc1(m,&idxm);CHKERRQ(ierr); 125 if (ltog) { 126 ierr = ISLocalToGlobalMappingApply(ltog,m,idx,idxm);CHKERRQ(ierr); 127 } else { 128 ierr = PetscMemcpy(idxm,idx,m*sizeof(PetscInt));CHKERRQ(ierr); 129 } 130 ierr = ISLocalToGlobalMappingCreate(PetscObjectComm((PetscObject)is),1,m,idxm,PETSC_OWN_POINTER,cltog);CHKERRQ(ierr); 131 ierr = ISRestoreIndices(is,&idx);CHKERRQ(ierr); 132 PetscFunctionReturn(0); 133 } 134 135 #undef __FUNCT__ 136 #define __FUNCT__ "ISL2GComposeBlock" 137 static PetscErrorCode ISL2GComposeBlock(IS is,ISLocalToGlobalMapping ltog,ISLocalToGlobalMapping *cltog) 138 { 139 PetscErrorCode ierr; 140 const PetscInt *idx; 141 PetscInt m,*idxm,bs; 142 143 PetscFunctionBegin; 144 PetscValidHeaderSpecific(is,IS_CLASSID,1); 145 PetscValidHeaderSpecific(ltog,IS_LTOGM_CLASSID,2); 146 PetscValidPointer(cltog,3); 147 ierr = ISBlockGetLocalSize(is,&m);CHKERRQ(ierr); 148 ierr = ISBlockGetIndices(is,&idx);CHKERRQ(ierr); 149 ierr = ISLocalToGlobalMappingGetBlockSize(ltog,&bs);CHKERRQ(ierr); 150 ierr = PetscMalloc1(m,&idxm);CHKERRQ(ierr); 151 if (ltog) { 152 ierr = ISLocalToGlobalMappingApplyBlock(ltog,m,idx,idxm);CHKERRQ(ierr); 153 } else { 154 ierr = PetscMemcpy(idxm,idx,m*sizeof(PetscInt));CHKERRQ(ierr); 155 } 156 ierr = ISLocalToGlobalMappingCreate(PetscObjectComm((PetscObject)is),bs,m,idxm,PETSC_OWN_POINTER,cltog);CHKERRQ(ierr); 157 ierr = ISBlockRestoreIndices(is,&idx);CHKERRQ(ierr); 158 PetscFunctionReturn(0); 159 } 160 161 #undef __FUNCT__ 162 #define __FUNCT__ "MatDestroy_LocalRef" 163 static PetscErrorCode MatDestroy_LocalRef(Mat B) 164 { 165 PetscErrorCode ierr; 166 167 PetscFunctionBegin; 168 ierr = PetscFree(B->data);CHKERRQ(ierr); 169 PetscFunctionReturn(0); 170 } 171 172 173 #undef __FUNCT__ 174 #define __FUNCT__ "MatCreateLocalRef" 175 /*@ 176 MatCreateLocalRef - Gets a logical reference to a local submatrix, for use in assembly 177 178 Not Collective 179 180 Input Arguments: 181 + A - Full matrix, generally parallel 182 . isrow - Local index set for the rows 183 - iscol - Local index set for the columns 184 185 Output Arguments: 186 . newmat - New serial Mat 187 188 Level: developer 189 190 Notes: 191 Most will use MatGetLocalSubMatrix() which returns a real matrix corresponding to the local 192 block if it available, such as with matrix formats that store these blocks separately. 193 194 The new matrix forwards MatSetValuesLocal() and MatSetValuesBlockedLocal() to the global system. 195 In general, it does not define MatMult() or any other functions. Local submatrices can be nested. 196 197 .seealso: MatSetValuesLocal(), MatSetValuesBlockedLocal(), MatGetLocalSubMatrix(), MatCreateSubMatrix() 198 @*/ 199 PetscErrorCode MatCreateLocalRef(Mat A,IS isrow,IS iscol,Mat *newmat) 200 { 201 PetscErrorCode ierr; 202 Mat_LocalRef *lr; 203 Mat B; 204 PetscInt m,n; 205 PetscBool islr; 206 207 PetscFunctionBegin; 208 PetscValidHeaderSpecific(A,MAT_CLASSID,1); 209 PetscValidHeaderSpecific(isrow,IS_CLASSID,2); 210 PetscValidHeaderSpecific(iscol,IS_CLASSID,3); 211 PetscValidPointer(newmat,4); 212 *newmat = 0; 213 214 ierr = MatCreate(PETSC_COMM_SELF,&B);CHKERRQ(ierr); 215 ierr = ISGetLocalSize(isrow,&m);CHKERRQ(ierr); 216 ierr = ISGetLocalSize(iscol,&n);CHKERRQ(ierr); 217 ierr = MatSetSizes(B,m,n,m,n);CHKERRQ(ierr); 218 ierr = PetscObjectChangeTypeName((PetscObject)B,MATLOCALREF);CHKERRQ(ierr); 219 ierr = MatSetUp(B);CHKERRQ(ierr); 220 221 B->ops->destroy = MatDestroy_LocalRef; 222 223 ierr = PetscNewLog(B,&lr);CHKERRQ(ierr); 224 B->data = (void*)lr; 225 226 ierr = PetscObjectTypeCompare((PetscObject)A,MATLOCALREF,&islr);CHKERRQ(ierr); 227 if (islr) { 228 Mat_LocalRef *alr = (Mat_LocalRef*)A->data; 229 lr->Top = alr->Top; 230 } else { 231 /* This does not increase the reference count because MatLocalRef is not allowed to live longer than its parent */ 232 lr->Top = A; 233 } 234 { 235 ISLocalToGlobalMapping rltog,cltog; 236 PetscInt abs,rbs,cbs; 237 238 /* We will translate directly to global indices for the top level */ 239 lr->SetValues = MatSetValues; 240 lr->SetValuesBlocked = MatSetValuesBlocked; 241 242 B->ops->setvalueslocal = MatSetValuesLocal_LocalRef_Scalar; 243 244 ierr = ISL2GCompose(isrow,A->rmap->mapping,&rltog);CHKERRQ(ierr); 245 if (isrow == iscol && A->rmap->mapping == A->cmap->mapping) { 246 ierr = PetscObjectReference((PetscObject)rltog);CHKERRQ(ierr); 247 cltog = rltog; 248 } else { 249 ierr = ISL2GCompose(iscol,A->cmap->mapping,&cltog);CHKERRQ(ierr); 250 } 251 ierr = MatSetLocalToGlobalMapping(B,rltog,cltog);CHKERRQ(ierr); 252 ierr = ISLocalToGlobalMappingDestroy(&rltog);CHKERRQ(ierr); 253 ierr = ISLocalToGlobalMappingDestroy(&cltog);CHKERRQ(ierr); 254 255 ierr = MatGetBlockSize(A,&abs);CHKERRQ(ierr); 256 ierr = ISGetBlockSize(isrow,&rbs);CHKERRQ(ierr); 257 ierr = ISGetBlockSize(iscol,&cbs);CHKERRQ(ierr); 258 if (rbs == cbs) { /* submatrix has block structure, so user can insert values with blocked interface */ 259 ierr = PetscLayoutSetBlockSize(B->rmap,rbs);CHKERRQ(ierr); 260 ierr = PetscLayoutSetBlockSize(B->cmap,cbs);CHKERRQ(ierr); 261 if (abs != rbs || abs == 1) { 262 /* Top-level matrix has different block size, so we have to call its scalar insertion interface */ 263 B->ops->setvaluesblockedlocal = MatSetValuesBlockedLocal_LocalRef_Scalar; 264 } else { 265 /* Block sizes match so we can forward values to the top level using the block interface */ 266 B->ops->setvaluesblockedlocal = MatSetValuesBlockedLocal_LocalRef_Block; 267 268 ierr = ISL2GComposeBlock(isrow,A->rmap->mapping,&rltog);CHKERRQ(ierr); 269 if (isrow == iscol && A->rmap->mapping == A->cmap->mapping) { 270 ierr = PetscObjectReference((PetscObject)rltog);CHKERRQ(ierr); 271 cltog = rltog; 272 } else { 273 ierr = ISL2GComposeBlock(iscol,A->cmap->mapping,&cltog);CHKERRQ(ierr); 274 } 275 ierr = MatSetLocalToGlobalMapping(B,rltog,cltog);CHKERRQ(ierr); 276 ierr = ISLocalToGlobalMappingDestroy(&rltog);CHKERRQ(ierr); 277 ierr = ISLocalToGlobalMappingDestroy(&cltog);CHKERRQ(ierr); 278 } 279 } 280 } 281 *newmat = B; 282 PetscFunctionReturn(0); 283 } 284