1 /* 2 Creates a matrix class for using the Neumann-Neumann type preconditioners. 3 This stores the matrices in globally unassembled form. Each processor 4 assembles only its local Neumann problem and the parallel matrix vector 5 product is handled "implicitly". 6 7 Currently this allows for only one subdomain per processor. 8 */ 9 10 #include <../src/mat/impls/is/matis.h> /*I "petscmat.h" I*/ 11 #include <petsc/private/sfimpl.h> 12 #include <petsc/private/vecimpl.h> 13 14 #define MATIS_MAX_ENTRIES_INSERTION 2048 15 static PetscErrorCode MatSetValuesLocal_IS(Mat,PetscInt,const PetscInt*,PetscInt,const PetscInt*,const PetscScalar*,InsertMode); 16 static PetscErrorCode MatSetValuesBlockedLocal_IS(Mat,PetscInt,const PetscInt*,PetscInt,const PetscInt*,const PetscScalar*,InsertMode); 17 static PetscErrorCode MatISSetUpScatters_Private(Mat); 18 19 static PetscErrorCode MatISContainerDestroyPtAP_Private(void *ptr) 20 { 21 MatISPtAP ptap = (MatISPtAP)ptr; 22 PetscErrorCode ierr; 23 24 PetscFunctionBegin; 25 ierr = MatDestroySubMatrices(ptap->ris1 ? 2 : 1,&ptap->lP);CHKERRQ(ierr); 26 ierr = ISDestroy(&ptap->cis0);CHKERRQ(ierr); 27 ierr = ISDestroy(&ptap->cis1);CHKERRQ(ierr); 28 ierr = ISDestroy(&ptap->ris0);CHKERRQ(ierr); 29 ierr = ISDestroy(&ptap->ris1);CHKERRQ(ierr); 30 ierr = PetscFree(ptap);CHKERRQ(ierr); 31 PetscFunctionReturn(0); 32 } 33 34 static PetscErrorCode MatPtAPNumeric_IS_XAIJ(Mat A, Mat P, Mat C) 35 { 36 MatISPtAP ptap; 37 Mat_IS *matis = (Mat_IS*)A->data; 38 Mat lA,lC; 39 MatReuse reuse; 40 IS ris[2],cis[2]; 41 PetscContainer c; 42 PetscInt n; 43 PetscErrorCode ierr; 44 45 PetscFunctionBegin; 46 ierr = PetscObjectQuery((PetscObject)C,"_MatIS_PtAP",(PetscObject*)&c);CHKERRQ(ierr); 47 if (!c) SETERRQ(PetscObjectComm((PetscObject)C),PETSC_ERR_PLIB,"Missing PtAP information"); 48 ierr = PetscContainerGetPointer(c,(void**)&ptap);CHKERRQ(ierr); 49 ris[0] = ptap->ris0; 50 ris[1] = ptap->ris1; 51 cis[0] = ptap->cis0; 52 cis[1] = ptap->cis1; 53 n = ptap->ris1 ? 2 : 1; 54 reuse = ptap->lP ? MAT_REUSE_MATRIX : MAT_INITIAL_MATRIX; 55 ierr = MatCreateSubMatrices(P,n,ris,cis,reuse,&ptap->lP);CHKERRQ(ierr); 56 57 ierr = MatISGetLocalMat(A,&lA);CHKERRQ(ierr); 58 ierr = MatISGetLocalMat(C,&lC);CHKERRQ(ierr); 59 if (ptap->ris1) { /* unsymmetric A mapping */ 60 Mat lPt; 61 62 ierr = MatTranspose(ptap->lP[1],MAT_INITIAL_MATRIX,&lPt);CHKERRQ(ierr); 63 ierr = MatMatMatMult(lPt,lA,ptap->lP[0],reuse,ptap->fill,&lC);CHKERRQ(ierr); 64 if (matis->storel2l) { 65 ierr = PetscObjectCompose((PetscObject)(A),"_MatIS_PtAP_l2l",(PetscObject)lPt);CHKERRQ(ierr); 66 } 67 ierr = MatDestroy(&lPt);CHKERRQ(ierr); 68 } else { 69 ierr = MatPtAP(lA,ptap->lP[0],reuse,ptap->fill,&lC);CHKERRQ(ierr); 70 if (matis->storel2l) { 71 ierr = PetscObjectCompose((PetscObject)(C),"_MatIS_PtAP_l2l",(PetscObject)ptap->lP[0]);CHKERRQ(ierr); 72 } 73 } 74 if (reuse == MAT_INITIAL_MATRIX) { 75 ierr = MatISSetLocalMat(C,lC);CHKERRQ(ierr); 76 ierr = MatDestroy(&lC);CHKERRQ(ierr); 77 } 78 ierr = MatAssemblyBegin(C,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 79 ierr = MatAssemblyEnd(C,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 80 PetscFunctionReturn(0); 81 } 82 83 static PetscErrorCode MatGetNonzeroColumnsLocal_Private(Mat PT,IS *cis) 84 { 85 Mat Po,Pd; 86 IS zd,zo; 87 const PetscInt *garray; 88 PetscInt *aux,i,bs; 89 PetscInt dc,stc,oc,ctd,cto; 90 PetscBool ismpiaij,ismpibaij,isseqaij,isseqbaij; 91 MPI_Comm comm; 92 PetscErrorCode ierr; 93 94 PetscFunctionBegin; 95 PetscValidHeaderSpecific(PT,MAT_CLASSID,1); 96 PetscValidPointer(cis,2); 97 ierr = PetscObjectGetComm((PetscObject)PT,&comm);CHKERRQ(ierr); 98 bs = 1; 99 ierr = PetscObjectBaseTypeCompare((PetscObject)PT,MATMPIAIJ,&ismpiaij);CHKERRQ(ierr); 100 ierr = PetscObjectBaseTypeCompare((PetscObject)PT,MATMPIBAIJ,&ismpibaij);CHKERRQ(ierr); 101 ierr = PetscObjectBaseTypeCompare((PetscObject)PT,MATSEQAIJ,&isseqaij);CHKERRQ(ierr); 102 ierr = PetscObjectTypeCompare((PetscObject)PT,MATSEQBAIJ,&isseqbaij);CHKERRQ(ierr); 103 if (isseqaij || isseqbaij) { 104 Pd = PT; 105 Po = NULL; 106 garray = NULL; 107 } else if (ismpiaij) { 108 ierr = MatMPIAIJGetSeqAIJ(PT,&Pd,&Po,&garray);CHKERRQ(ierr); 109 } else if (ismpibaij) { 110 ierr = MatMPIBAIJGetSeqBAIJ(PT,&Pd,&Po,&garray);CHKERRQ(ierr); 111 ierr = MatGetBlockSize(PT,&bs);CHKERRQ(ierr); 112 } else SETERRQ1(comm,PETSC_ERR_SUP,"Not for matrix type %s",((PetscObject)(PT))->type_name); 113 114 /* identify any null columns in Pd or Po */ 115 /* We use a tolerance comparison since it may happen that, with geometric multigrid, 116 some of the columns are not really zero, but very close to */ 117 zo = zd = NULL; 118 if (Po) { 119 ierr = MatFindNonzeroRowsOrCols_Basic(Po,PETSC_TRUE,PETSC_SMALL,&zo);CHKERRQ(ierr); 120 } 121 ierr = MatFindNonzeroRowsOrCols_Basic(Pd,PETSC_TRUE,PETSC_SMALL,&zd);CHKERRQ(ierr); 122 123 ierr = MatGetLocalSize(PT,NULL,&dc);CHKERRQ(ierr); 124 ierr = MatGetOwnershipRangeColumn(PT,&stc,NULL);CHKERRQ(ierr); 125 if (Po) { ierr = MatGetLocalSize(Po,NULL,&oc);CHKERRQ(ierr); } 126 else oc = 0; 127 ierr = PetscMalloc1((dc+oc)/bs,&aux);CHKERRQ(ierr); 128 if (zd) { 129 const PetscInt *idxs; 130 PetscInt nz; 131 132 /* this will throw an error if bs is not valid */ 133 ierr = ISSetBlockSize(zd,bs);CHKERRQ(ierr); 134 ierr = ISGetLocalSize(zd,&nz);CHKERRQ(ierr); 135 ierr = ISGetIndices(zd,&idxs);CHKERRQ(ierr); 136 ctd = nz/bs; 137 for (i=0; i<ctd; i++) aux[i] = (idxs[bs*i]+stc)/bs; 138 ierr = ISRestoreIndices(zd,&idxs);CHKERRQ(ierr); 139 } else { 140 ctd = dc/bs; 141 for (i=0; i<ctd; i++) aux[i] = i+stc/bs; 142 } 143 if (zo) { 144 const PetscInt *idxs; 145 PetscInt nz; 146 147 /* this will throw an error if bs is not valid */ 148 ierr = ISSetBlockSize(zo,bs);CHKERRQ(ierr); 149 ierr = ISGetLocalSize(zo,&nz);CHKERRQ(ierr); 150 ierr = ISGetIndices(zo,&idxs);CHKERRQ(ierr); 151 cto = nz/bs; 152 for (i=0; i<cto; i++) aux[i+ctd] = garray[idxs[bs*i]/bs]; 153 ierr = ISRestoreIndices(zo,&idxs);CHKERRQ(ierr); 154 } else { 155 cto = oc/bs; 156 for (i=0; i<cto; i++) aux[i+ctd] = garray[i]; 157 } 158 ierr = ISCreateBlock(comm,bs,ctd+cto,aux,PETSC_OWN_POINTER,cis);CHKERRQ(ierr); 159 ierr = ISDestroy(&zd);CHKERRQ(ierr); 160 ierr = ISDestroy(&zo);CHKERRQ(ierr); 161 PetscFunctionReturn(0); 162 } 163 164 static PetscErrorCode MatPtAPSymbolic_IS_XAIJ(Mat A,Mat P,PetscReal fill,Mat *C) 165 { 166 Mat PT,lA; 167 MatISPtAP ptap; 168 ISLocalToGlobalMapping Crl2g,Ccl2g,rl2g,cl2g; 169 PetscContainer c; 170 MatType lmtype; 171 const PetscInt *garray; 172 PetscInt ibs,N,dc; 173 MPI_Comm comm; 174 PetscErrorCode ierr; 175 176 PetscFunctionBegin; 177 ierr = PetscObjectGetComm((PetscObject)A,&comm);CHKERRQ(ierr); 178 ierr = MatCreate(comm,C);CHKERRQ(ierr); 179 ierr = MatSetType(*C,MATIS);CHKERRQ(ierr); 180 ierr = MatISGetLocalMat(A,&lA);CHKERRQ(ierr); 181 ierr = MatGetType(lA,&lmtype);CHKERRQ(ierr); 182 ierr = MatISSetLocalMatType(*C,lmtype);CHKERRQ(ierr); 183 ierr = MatGetSize(P,NULL,&N);CHKERRQ(ierr); 184 ierr = MatGetLocalSize(P,NULL,&dc);CHKERRQ(ierr); 185 ierr = MatSetSizes(*C,dc,dc,N,N);CHKERRQ(ierr); 186 /* Not sure about this 187 ierr = MatGetBlockSizes(P,NULL,&ibs);CHKERRQ(ierr); 188 ierr = MatSetBlockSize(*C,ibs);CHKERRQ(ierr); 189 */ 190 191 ierr = PetscNew(&ptap);CHKERRQ(ierr); 192 ierr = PetscContainerCreate(PETSC_COMM_SELF,&c);CHKERRQ(ierr); 193 ierr = PetscContainerSetPointer(c,ptap);CHKERRQ(ierr); 194 ierr = PetscContainerSetUserDestroy(c,MatISContainerDestroyPtAP_Private);CHKERRQ(ierr); 195 ierr = PetscObjectCompose((PetscObject)(*C),"_MatIS_PtAP",(PetscObject)c);CHKERRQ(ierr); 196 ierr = PetscContainerDestroy(&c);CHKERRQ(ierr); 197 ptap->fill = fill; 198 199 ierr = MatGetLocalToGlobalMapping(A,&rl2g,&cl2g);CHKERRQ(ierr); 200 201 ierr = ISLocalToGlobalMappingGetBlockSize(cl2g,&ibs);CHKERRQ(ierr); 202 ierr = ISLocalToGlobalMappingGetSize(cl2g,&N);CHKERRQ(ierr); 203 ierr = ISLocalToGlobalMappingGetBlockIndices(cl2g,&garray);CHKERRQ(ierr); 204 ierr = ISCreateBlock(comm,ibs,N/ibs,garray,PETSC_COPY_VALUES,&ptap->ris0);CHKERRQ(ierr); 205 ierr = ISLocalToGlobalMappingRestoreBlockIndices(cl2g,&garray);CHKERRQ(ierr); 206 207 ierr = MatCreateSubMatrix(P,ptap->ris0,NULL,MAT_INITIAL_MATRIX,&PT);CHKERRQ(ierr); 208 ierr = MatGetNonzeroColumnsLocal_Private(PT,&ptap->cis0);CHKERRQ(ierr); 209 ierr = ISLocalToGlobalMappingCreateIS(ptap->cis0,&Ccl2g);CHKERRQ(ierr); 210 ierr = MatDestroy(&PT);CHKERRQ(ierr); 211 212 Crl2g = NULL; 213 if (rl2g != cl2g) { /* unsymmetric A mapping */ 214 PetscBool same,lsame = PETSC_FALSE; 215 PetscInt N1,ibs1; 216 217 ierr = ISLocalToGlobalMappingGetSize(rl2g,&N1);CHKERRQ(ierr); 218 ierr = ISLocalToGlobalMappingGetBlockSize(rl2g,&ibs1);CHKERRQ(ierr); 219 ierr = ISLocalToGlobalMappingGetBlockIndices(rl2g,&garray);CHKERRQ(ierr); 220 ierr = ISCreateBlock(comm,ibs,N/ibs,garray,PETSC_COPY_VALUES,&ptap->ris1);CHKERRQ(ierr); 221 ierr = ISLocalToGlobalMappingRestoreBlockIndices(rl2g,&garray);CHKERRQ(ierr); 222 if (ibs1 == ibs && N1 == N) { /* check if the l2gmaps are the same */ 223 const PetscInt *i1,*i2; 224 225 ierr = ISBlockGetIndices(ptap->ris0,&i1);CHKERRQ(ierr); 226 ierr = ISBlockGetIndices(ptap->ris1,&i2);CHKERRQ(ierr); 227 ierr = PetscArraycmp(i1,i2,N,&lsame);CHKERRQ(ierr); 228 } 229 ierr = MPIU_Allreduce(&lsame,&same,1,MPIU_BOOL,MPI_LAND,comm);CHKERRQ(ierr); 230 if (same) { 231 ierr = ISDestroy(&ptap->ris1);CHKERRQ(ierr); 232 } else { 233 ierr = MatCreateSubMatrix(P,ptap->ris1,NULL,MAT_INITIAL_MATRIX,&PT);CHKERRQ(ierr); 234 ierr = MatGetNonzeroColumnsLocal_Private(PT,&ptap->cis1);CHKERRQ(ierr); 235 ierr = ISLocalToGlobalMappingCreateIS(ptap->cis1,&Crl2g);CHKERRQ(ierr); 236 ierr = MatDestroy(&PT);CHKERRQ(ierr); 237 } 238 } 239 /* Not sure about this 240 if (!Crl2g) { 241 ierr = MatGetBlockSize(*C,&ibs);CHKERRQ(ierr); 242 ierr = ISLocalToGlobalMappingSetBlockSize(Ccl2g,ibs);CHKERRQ(ierr); 243 } 244 */ 245 ierr = MatSetLocalToGlobalMapping(*C,Crl2g ? Crl2g : Ccl2g,Ccl2g);CHKERRQ(ierr); 246 ierr = ISLocalToGlobalMappingDestroy(&Crl2g);CHKERRQ(ierr); 247 ierr = ISLocalToGlobalMappingDestroy(&Ccl2g);CHKERRQ(ierr); 248 249 (*C)->ops->ptapnumeric = MatPtAPNumeric_IS_XAIJ; 250 PetscFunctionReturn(0); 251 } 252 253 PETSC_INTERN PetscErrorCode MatPtAP_IS_XAIJ(Mat A,Mat P,MatReuse scall,PetscReal fill,Mat *C) 254 { 255 PetscErrorCode ierr; 256 257 PetscFunctionBegin; 258 if (scall == MAT_INITIAL_MATRIX) { 259 ierr = PetscLogEventBegin(MAT_PtAPSymbolic,A,P,0,0);CHKERRQ(ierr); 260 ierr = MatPtAPSymbolic_IS_XAIJ(A,P,fill,C);CHKERRQ(ierr); 261 ierr = PetscLogEventEnd(MAT_PtAPSymbolic,A,P,0,0);CHKERRQ(ierr); 262 } 263 ierr = PetscLogEventBegin(MAT_PtAPNumeric,A,P,0,0);CHKERRQ(ierr); 264 ierr = ((*C)->ops->ptapnumeric)(A,P,*C);CHKERRQ(ierr); 265 ierr = PetscLogEventEnd(MAT_PtAPNumeric,A,P,0,0);CHKERRQ(ierr); 266 PetscFunctionReturn(0); 267 } 268 269 static PetscErrorCode MatISContainerDestroyFields_Private(void *ptr) 270 { 271 MatISLocalFields lf = (MatISLocalFields)ptr; 272 PetscInt i; 273 PetscErrorCode ierr; 274 275 PetscFunctionBegin; 276 for (i=0;i<lf->nr;i++) { 277 ierr = ISDestroy(&lf->rf[i]);CHKERRQ(ierr); 278 } 279 for (i=0;i<lf->nc;i++) { 280 ierr = ISDestroy(&lf->cf[i]);CHKERRQ(ierr); 281 } 282 ierr = PetscFree2(lf->rf,lf->cf);CHKERRQ(ierr); 283 ierr = PetscFree(lf);CHKERRQ(ierr); 284 PetscFunctionReturn(0); 285 } 286 287 static PetscErrorCode MatConvert_SeqXAIJ_IS(Mat A,MatType type,MatReuse reuse,Mat *newmat) 288 { 289 Mat B,lB; 290 PetscErrorCode ierr; 291 292 PetscFunctionBegin; 293 if (reuse != MAT_REUSE_MATRIX) { 294 ISLocalToGlobalMapping rl2g,cl2g; 295 PetscInt bs; 296 IS is; 297 298 ierr = MatGetBlockSize(A,&bs);CHKERRQ(ierr); 299 ierr = ISCreateStride(PetscObjectComm((PetscObject)A),A->rmap->n/bs,0,1,&is);CHKERRQ(ierr); 300 if (bs > 1) { 301 IS is2; 302 PetscInt i,*aux; 303 304 ierr = ISGetLocalSize(is,&i);CHKERRQ(ierr); 305 ierr = ISGetIndices(is,(const PetscInt**)&aux);CHKERRQ(ierr); 306 ierr = ISCreateBlock(PetscObjectComm((PetscObject)A),bs,i,aux,PETSC_COPY_VALUES,&is2);CHKERRQ(ierr); 307 ierr = ISRestoreIndices(is,(const PetscInt**)&aux);CHKERRQ(ierr); 308 ierr = ISDestroy(&is);CHKERRQ(ierr); 309 is = is2; 310 } 311 ierr = ISSetIdentity(is);CHKERRQ(ierr); 312 ierr = ISLocalToGlobalMappingCreateIS(is,&rl2g);CHKERRQ(ierr); 313 ierr = ISDestroy(&is);CHKERRQ(ierr); 314 ierr = ISCreateStride(PetscObjectComm((PetscObject)A),A->cmap->n/bs,0,1,&is);CHKERRQ(ierr); 315 if (bs > 1) { 316 IS is2; 317 PetscInt i,*aux; 318 319 ierr = ISGetLocalSize(is,&i);CHKERRQ(ierr); 320 ierr = ISGetIndices(is,(const PetscInt**)&aux);CHKERRQ(ierr); 321 ierr = ISCreateBlock(PetscObjectComm((PetscObject)A),bs,i,aux,PETSC_COPY_VALUES,&is2);CHKERRQ(ierr); 322 ierr = ISRestoreIndices(is,(const PetscInt**)&aux);CHKERRQ(ierr); 323 ierr = ISDestroy(&is);CHKERRQ(ierr); 324 is = is2; 325 } 326 ierr = ISSetIdentity(is);CHKERRQ(ierr); 327 ierr = ISLocalToGlobalMappingCreateIS(is,&cl2g);CHKERRQ(ierr); 328 ierr = ISDestroy(&is);CHKERRQ(ierr); 329 ierr = MatCreateIS(PetscObjectComm((PetscObject)A),bs,A->rmap->n,A->cmap->n,A->rmap->N,A->cmap->N,rl2g,cl2g,&B);CHKERRQ(ierr); 330 ierr = ISLocalToGlobalMappingDestroy(&rl2g);CHKERRQ(ierr); 331 ierr = ISLocalToGlobalMappingDestroy(&cl2g);CHKERRQ(ierr); 332 ierr = MatDuplicate(A,MAT_COPY_VALUES,&lB);CHKERRQ(ierr); 333 if (reuse == MAT_INITIAL_MATRIX) *newmat = B; 334 } else { 335 B = *newmat; 336 ierr = PetscObjectReference((PetscObject)A);CHKERRQ(ierr); 337 lB = A; 338 } 339 ierr = MatISSetLocalMat(B,lB);CHKERRQ(ierr); 340 ierr = MatDestroy(&lB);CHKERRQ(ierr); 341 ierr = MatAssemblyBegin(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 342 ierr = MatAssemblyEnd(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 343 if (reuse == MAT_INPLACE_MATRIX) { 344 ierr = MatHeaderReplace(A,&B);CHKERRQ(ierr); 345 } 346 PetscFunctionReturn(0); 347 } 348 349 static PetscErrorCode MatISScaleDisassembling_Private(Mat A) 350 { 351 Mat_IS *matis = (Mat_IS*)(A->data); 352 PetscScalar *aa; 353 const PetscInt *ii,*jj; 354 PetscInt i,n,m; 355 PetscInt *ecount,**eneighs; 356 PetscBool flg; 357 PetscErrorCode ierr; 358 359 PetscFunctionBegin; 360 ierr = MatGetRowIJ(matis->A,0,PETSC_FALSE,PETSC_FALSE,&m,&ii,&jj,&flg);CHKERRQ(ierr); 361 if (!flg) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Cannot get IJ structure"); 362 ierr = ISLocalToGlobalMappingGetNodeInfo(A->rmap->mapping,&n,&ecount,&eneighs);CHKERRQ(ierr); 363 if (m != n) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Unexpected %D != %D",m,n); 364 ierr = MatSeqAIJGetArray(matis->A,&aa);CHKERRQ(ierr); 365 for (i=0;i<n;i++) { 366 if (ecount[i] > 1) { 367 PetscInt j; 368 369 for (j=ii[i];j<ii[i+1];j++) { 370 PetscInt i2 = jj[j],p,p2; 371 PetscReal scal = 0.0; 372 373 for (p=0;p<ecount[i];p++) { 374 for (p2=0;p2<ecount[i2];p2++) { 375 if (eneighs[i][p] == eneighs[i2][p2]) { scal += 1.0; break; } 376 } 377 } 378 if (scal) aa[j] /= scal; 379 } 380 } 381 } 382 ierr = ISLocalToGlobalMappingRestoreNodeInfo(A->rmap->mapping,&n,&ecount,&eneighs);CHKERRQ(ierr); 383 ierr = MatSeqAIJRestoreArray(matis->A,&aa);CHKERRQ(ierr); 384 ierr = MatRestoreRowIJ(matis->A,0,PETSC_FALSE,PETSC_FALSE,&m,&ii,&jj,&flg);CHKERRQ(ierr); 385 if (!flg) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Cannot restore IJ structure"); 386 PetscFunctionReturn(0); 387 } 388 389 typedef enum {MAT_IS_DISASSEMBLE_L2G_NATURAL,MAT_IS_DISASSEMBLE_L2G_MAT, MAT_IS_DISASSEMBLE_L2G_ND} MatISDisassemblel2gType; 390 391 static PetscErrorCode MatMPIXAIJComputeLocalToGlobalMapping_Private(Mat A, ISLocalToGlobalMapping *l2g) 392 { 393 Mat Ad,Ao; 394 IS is,ndmap,ndsub; 395 MPI_Comm comm; 396 const PetscInt *garray,*ndmapi; 397 PetscInt bs,i,cnt,nl,*ncount,*ndmapc; 398 PetscBool ismpiaij,ismpibaij; 399 const char *const MatISDisassemblel2gTypes[] = {"NATURAL","MAT","ND","MatISDisassemblel2gType","MAT_IS_DISASSEMBLE_L2G_",0}; 400 MatISDisassemblel2gType mode = MAT_IS_DISASSEMBLE_L2G_NATURAL; 401 MatPartitioning part; 402 PetscSF sf; 403 PetscErrorCode ierr; 404 405 PetscFunctionBegin; 406 ierr = PetscOptionsBegin(PetscObjectComm((PetscObject)A),((PetscObject)A)->prefix,"MatIS l2g disassembling options","Mat");CHKERRQ(ierr); 407 ierr = PetscOptionsEnum("-mat_is_disassemble_l2g_type","Type of local-to-global mapping to be used for disassembling","MatISDisassemblel2gType",MatISDisassemblel2gTypes,(PetscEnum)mode,(PetscEnum*)&mode,NULL);CHKERRQ(ierr); 408 ierr = PetscOptionsEnd();CHKERRQ(ierr); 409 if (mode == MAT_IS_DISASSEMBLE_L2G_MAT) { 410 ierr = MatGetLocalToGlobalMapping(A,l2g,NULL);CHKERRQ(ierr); 411 PetscFunctionReturn(0); 412 } 413 ierr = PetscObjectGetComm((PetscObject)A,&comm);CHKERRQ(ierr); 414 ierr = PetscObjectBaseTypeCompare((PetscObject)A,MATMPIAIJ ,&ismpiaij);CHKERRQ(ierr); 415 ierr = PetscObjectBaseTypeCompare((PetscObject)A,MATMPIBAIJ,&ismpibaij);CHKERRQ(ierr); 416 ierr = MatGetBlockSize(A,&bs);CHKERRQ(ierr); 417 switch (mode) { 418 case MAT_IS_DISASSEMBLE_L2G_ND: 419 ierr = MatPartitioningCreate(comm,&part);CHKERRQ(ierr); 420 ierr = MatPartitioningSetAdjacency(part,A);CHKERRQ(ierr); 421 ierr = PetscObjectSetOptionsPrefix((PetscObject)part,((PetscObject)A)->prefix);CHKERRQ(ierr); 422 ierr = MatPartitioningSetFromOptions(part);CHKERRQ(ierr); 423 ierr = MatPartitioningApplyND(part,&ndmap);CHKERRQ(ierr); 424 ierr = MatPartitioningDestroy(&part);CHKERRQ(ierr); 425 ierr = ISBuildTwoSided(ndmap,NULL,&ndsub);CHKERRQ(ierr); 426 ierr = MatMPIAIJSetUseScalableIncreaseOverlap(A,PETSC_TRUE);CHKERRQ(ierr); 427 ierr = MatIncreaseOverlap(A,1,&ndsub,1);CHKERRQ(ierr); 428 ierr = ISLocalToGlobalMappingCreateIS(ndsub,l2g);CHKERRQ(ierr); 429 430 /* it may happen that a separator node is not properly shared */ 431 ierr = ISLocalToGlobalMappingGetNodeInfo(*l2g,&nl,&ncount,NULL);CHKERRQ(ierr); 432 ierr = PetscSFCreate(comm,&sf);CHKERRQ(ierr); 433 ierr = ISLocalToGlobalMappingGetIndices(*l2g,&garray);CHKERRQ(ierr); 434 ierr = PetscSFSetGraphLayout(sf,A->rmap,nl,NULL,PETSC_OWN_POINTER,garray);CHKERRQ(ierr); 435 ierr = ISLocalToGlobalMappingRestoreIndices(*l2g,&garray);CHKERRQ(ierr); 436 ierr = PetscCalloc1(A->rmap->n,&ndmapc);CHKERRQ(ierr); 437 ierr = PetscSFReduceBegin(sf,MPIU_INT,ncount,ndmapc,MPIU_REPLACE);CHKERRQ(ierr); 438 ierr = PetscSFReduceEnd(sf,MPIU_INT,ncount,ndmapc,MPIU_REPLACE);CHKERRQ(ierr); 439 ierr = ISLocalToGlobalMappingRestoreNodeInfo(*l2g,NULL,&ncount,NULL);CHKERRQ(ierr); 440 ierr = ISGetIndices(ndmap,&ndmapi);CHKERRQ(ierr); 441 for (i = 0, cnt = 0; i < A->rmap->n; i++) 442 if (ndmapi[i] < 0 && ndmapc[i] < 2) 443 cnt++; 444 445 ierr = MPIU_Allreduce(&cnt,&i,1,MPIU_INT,MPI_MAX,comm);CHKERRQ(ierr); 446 if (i) { /* we detected isolated separator nodes */ 447 Mat A2,A3; 448 IS *workis,is2; 449 PetscScalar *vals; 450 PetscInt gcnt = i,*dnz,*onz,j,*lndmapi; 451 ISLocalToGlobalMapping ll2g; 452 PetscBool flg; 453 const PetscInt *ii,*jj; 454 455 /* communicate global id of separators */ 456 ierr = MatPreallocateInitialize(comm,A->rmap->n,A->cmap->n,dnz,onz);CHKERRQ(ierr); 457 for (i = 0, cnt = 0; i < A->rmap->n; i++) 458 dnz[i] = ndmapi[i] < 0 ? i + A->rmap->rstart : -1; 459 460 ierr = PetscMalloc1(nl,&lndmapi);CHKERRQ(ierr); 461 ierr = PetscSFBcastBegin(sf,MPIU_INT,dnz,lndmapi);CHKERRQ(ierr); 462 463 /* compute adjacency of isolated separators node */ 464 ierr = PetscMalloc1(gcnt,&workis);CHKERRQ(ierr); 465 for (i = 0, cnt = 0; i < A->rmap->n; i++) { 466 if (ndmapi[i] < 0 && ndmapc[i] < 2) { 467 ierr = ISCreateStride(comm,1,i+A->rmap->rstart,1,&workis[cnt++]);CHKERRQ(ierr); 468 } 469 } 470 for (i = cnt; i < gcnt; i++) { 471 ierr = ISCreateStride(comm,0,0,1,&workis[i]);CHKERRQ(ierr); 472 } 473 for (i = 0; i < gcnt; i++) { 474 ierr = PetscObjectSetName((PetscObject)workis[i],"ISOLATED");CHKERRQ(ierr); 475 ierr = ISViewFromOptions(workis[i],NULL,"-view_isolated_separators");CHKERRQ(ierr); 476 } 477 478 /* no communications since all the ISes correspond to locally owned rows */ 479 ierr = MatIncreaseOverlap(A,gcnt,workis,1);CHKERRQ(ierr); 480 481 /* end communicate global id of separators */ 482 ierr = PetscSFBcastEnd(sf,MPIU_INT,dnz,lndmapi);CHKERRQ(ierr); 483 484 /* communicate new layers : create a matrix and transpose it */ 485 ierr = PetscArrayzero(dnz,A->rmap->n);CHKERRQ(ierr); 486 ierr = PetscArrayzero(onz,A->rmap->n);CHKERRQ(ierr); 487 for (i = 0, j = 0; i < A->rmap->n; i++) { 488 if (ndmapi[i] < 0 && ndmapc[i] < 2) { 489 const PetscInt* idxs; 490 PetscInt s; 491 492 ierr = ISGetLocalSize(workis[j],&s);CHKERRQ(ierr); 493 ierr = ISGetIndices(workis[j],&idxs);CHKERRQ(ierr); 494 ierr = MatPreallocateSet(i+A->rmap->rstart,s,idxs,dnz,onz);CHKERRQ(ierr); 495 j++; 496 } 497 } 498 if (j != cnt) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Unexpected local count %D != %D",j,cnt); 499 500 for (i = 0; i < gcnt; i++) { 501 ierr = PetscObjectSetName((PetscObject)workis[i],"EXTENDED");CHKERRQ(ierr); 502 ierr = ISViewFromOptions(workis[i],NULL,"-view_isolated_separators");CHKERRQ(ierr); 503 } 504 505 for (i = 0, j = 0; i < A->rmap->n; i++) j = PetscMax(j,dnz[i]+onz[i]); 506 ierr = PetscMalloc1(j,&vals);CHKERRQ(ierr); 507 for (i = 0; i < j; i++) vals[i] = 1.0; 508 509 ierr = MatCreate(comm,&A2);CHKERRQ(ierr); 510 ierr = MatSetType(A2,MATMPIAIJ);CHKERRQ(ierr); 511 ierr = MatSetSizes(A2,A->rmap->n,A->cmap->n,A->rmap->N,A->cmap->N);CHKERRQ(ierr); 512 ierr = MatMPIAIJSetPreallocation(A2,0,dnz,0,onz);CHKERRQ(ierr); 513 ierr = MatSetOption(A2,MAT_NO_OFF_PROC_ENTRIES,PETSC_TRUE);CHKERRQ(ierr); 514 for (i = 0, j = 0; i < A2->rmap->n; i++) { 515 PetscInt row = i+A2->rmap->rstart,s = dnz[i] + onz[i]; 516 const PetscInt* idxs; 517 518 if (s) { 519 ierr = ISGetIndices(workis[j],&idxs);CHKERRQ(ierr); 520 ierr = MatSetValues(A2,1,&row,s,idxs,vals,INSERT_VALUES);CHKERRQ(ierr); 521 ierr = ISRestoreIndices(workis[j],&idxs);CHKERRQ(ierr); 522 j++; 523 } 524 } 525 if (j != cnt) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Unexpected local count %D != %D",j,cnt); 526 ierr = PetscFree(vals);CHKERRQ(ierr); 527 ierr = MatAssemblyBegin(A2,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 528 ierr = MatAssemblyEnd(A2,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 529 ierr = MatTranspose(A2,MAT_INPLACE_MATRIX,&A2);CHKERRQ(ierr); 530 531 /* extract submatrix corresponding to the coupling "owned separators" x "isolated separators" */ 532 for (i = 0, j = 0; i < nl; i++) 533 if (lndmapi[i] >= 0) lndmapi[j++] = lndmapi[i]; 534 ierr = ISCreateGeneral(comm,j,lndmapi,PETSC_USE_POINTER,&is);CHKERRQ(ierr); 535 ierr = MatMPIAIJGetLocalMatCondensed(A2,MAT_INITIAL_MATRIX,&is,NULL,&A3);CHKERRQ(ierr); 536 ierr = ISDestroy(&is);CHKERRQ(ierr); 537 ierr = MatDestroy(&A2);CHKERRQ(ierr); 538 539 /* extend local to global map to include connected isolated separators */ 540 ierr = PetscObjectQuery((PetscObject)A3,"_petsc_GetLocalMatCondensed_iscol",(PetscObject*)&is);CHKERRQ(ierr); 541 if (!is) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Missing column map"); 542 ierr = ISLocalToGlobalMappingCreateIS(is,&ll2g);CHKERRQ(ierr); 543 ierr = MatGetRowIJ(A3,0,PETSC_FALSE,PETSC_FALSE,&i,&ii,&jj,&flg);CHKERRQ(ierr); 544 if (!flg) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Cannot get IJ structure"); 545 ierr = ISCreateGeneral(PETSC_COMM_SELF,ii[i],jj,PETSC_COPY_VALUES,&is);CHKERRQ(ierr); 546 ierr = MatRestoreRowIJ(A3,0,PETSC_FALSE,PETSC_FALSE,&i,&ii,&jj,&flg);CHKERRQ(ierr); 547 if (!flg) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Cannot get IJ structure"); 548 ierr = ISLocalToGlobalMappingApplyIS(ll2g,is,&is2);CHKERRQ(ierr); 549 ierr = ISDestroy(&is);CHKERRQ(ierr); 550 ierr = ISLocalToGlobalMappingDestroy(&ll2g);CHKERRQ(ierr); 551 552 /* add new nodes to the local-to-global map */ 553 ierr = ISLocalToGlobalMappingDestroy(l2g);CHKERRQ(ierr); 554 ierr = ISExpand(ndsub,is2,&is);CHKERRQ(ierr); 555 ierr = ISDestroy(&is2);CHKERRQ(ierr); 556 ierr = ISLocalToGlobalMappingCreateIS(is,l2g);CHKERRQ(ierr); 557 ierr = ISDestroy(&is);CHKERRQ(ierr); 558 559 ierr = MatDestroy(&A3);CHKERRQ(ierr); 560 ierr = PetscFree(lndmapi);CHKERRQ(ierr); 561 ierr = MatPreallocateFinalize(dnz,onz);CHKERRQ(ierr); 562 for (i = 0; i < gcnt; i++) { 563 ierr = ISDestroy(&workis[i]);CHKERRQ(ierr); 564 } 565 ierr = PetscFree(workis);CHKERRQ(ierr); 566 } 567 ierr = ISRestoreIndices(ndmap,&ndmapi);CHKERRQ(ierr); 568 ierr = PetscSFDestroy(&sf);CHKERRQ(ierr); 569 ierr = PetscFree(ndmapc);CHKERRQ(ierr); 570 ierr = ISDestroy(&ndmap);CHKERRQ(ierr); 571 ierr = ISDestroy(&ndsub);CHKERRQ(ierr); 572 ierr = ISLocalToGlobalMappingSetBlockSize(*l2g,bs);CHKERRQ(ierr); 573 ierr = ISLocalToGlobalMappingViewFromOptions(*l2g,NULL,"-matis_nd_l2g_view");CHKERRQ(ierr); 574 break; 575 case MAT_IS_DISASSEMBLE_L2G_NATURAL: 576 if (ismpiaij) { 577 ierr = MatMPIAIJGetSeqAIJ(A,&Ad,&Ao,&garray);CHKERRQ(ierr); 578 } else if (ismpibaij) { 579 ierr = MatMPIBAIJGetSeqBAIJ(A,&Ad,&Ao,&garray);CHKERRQ(ierr); 580 } else SETERRQ1(comm,PETSC_ERR_SUP,"Type %s",((PetscObject)A)->type_name); 581 if (!garray) SETERRQ(comm,PETSC_ERR_ARG_WRONGSTATE,"garray not present"); 582 if (A->rmap->n) { 583 PetscInt dc,oc,stc,*aux; 584 585 ierr = MatGetLocalSize(A,NULL,&dc);CHKERRQ(ierr); 586 ierr = MatGetLocalSize(Ao,NULL,&oc);CHKERRQ(ierr); 587 ierr = MatGetOwnershipRangeColumn(A,&stc,NULL);CHKERRQ(ierr); 588 ierr = PetscMalloc1((dc+oc)/bs,&aux);CHKERRQ(ierr); 589 for (i=0; i<dc/bs; i++) aux[i] = i+stc/bs; 590 for (i=0; i<oc/bs; i++) aux[i+dc/bs] = garray[i]; 591 ierr = ISCreateBlock(comm,bs,(dc+oc)/bs,aux,PETSC_OWN_POINTER,&is);CHKERRQ(ierr); 592 } else { 593 ierr = ISCreateBlock(comm,1,0,NULL,PETSC_OWN_POINTER,&is);CHKERRQ(ierr); 594 } 595 ierr = ISLocalToGlobalMappingCreateIS(is,l2g);CHKERRQ(ierr); 596 ierr = ISDestroy(&is);CHKERRQ(ierr); 597 break; 598 default: 599 SETERRQ1(comm,PETSC_ERR_ARG_WRONG,"Unsupported l2g disassembling type %D",mode); 600 } 601 PetscFunctionReturn(0); 602 } 603 604 PETSC_INTERN PetscErrorCode MatConvert_XAIJ_IS(Mat A,MatType type,MatReuse reuse,Mat *newmat) 605 { 606 Mat lA,Ad,Ao,B = NULL; 607 ISLocalToGlobalMapping rl2g,cl2g; 608 IS is; 609 MPI_Comm comm; 610 void *ptrs[2]; 611 const char *names[2] = {"_convert_csr_aux","_convert_csr_data"}; 612 const PetscInt *garray; 613 PetscScalar *dd,*od,*aa,*data; 614 const PetscInt *di,*dj,*oi,*oj; 615 const PetscInt *odi,*odj,*ooi,*ooj; 616 PetscInt *aux,*ii,*jj; 617 PetscInt bs,lc,dr,dc,oc,str,stc,nnz,i,jd,jo,cum; 618 PetscBool flg,ismpiaij,ismpibaij,was_inplace = PETSC_FALSE; 619 PetscMPIInt size; 620 PetscErrorCode ierr; 621 622 PetscFunctionBegin; 623 ierr = PetscObjectGetComm((PetscObject)A,&comm);CHKERRQ(ierr); 624 ierr = MPI_Comm_size(comm,&size);CHKERRQ(ierr); 625 if (size == 1) { 626 ierr = MatConvert_SeqXAIJ_IS(A,type,reuse,newmat);CHKERRQ(ierr); 627 PetscFunctionReturn(0); 628 } 629 if (reuse != MAT_REUSE_MATRIX && A->cmap->N == A->rmap->N) { 630 ierr = MatMPIXAIJComputeLocalToGlobalMapping_Private(A,&rl2g);CHKERRQ(ierr); 631 ierr = MatCreate(comm,&B);CHKERRQ(ierr); 632 ierr = MatSetType(B,MATIS);CHKERRQ(ierr); 633 ierr = MatSetSizes(B,A->rmap->n,A->cmap->n,A->rmap->N,A->cmap->N);CHKERRQ(ierr); 634 ierr = MatSetLocalToGlobalMapping(B,rl2g,rl2g);CHKERRQ(ierr); 635 ierr = MatGetBlockSize(A,&bs);CHKERRQ(ierr); 636 ierr = MatSetBlockSize(B,bs);CHKERRQ(ierr); 637 ierr = ISLocalToGlobalMappingDestroy(&rl2g);CHKERRQ(ierr); 638 if (reuse == MAT_INPLACE_MATRIX) was_inplace = PETSC_TRUE; 639 reuse = MAT_REUSE_MATRIX; 640 } 641 if (reuse == MAT_REUSE_MATRIX) { 642 Mat *newlA, lA; 643 IS rows, cols; 644 const PetscInt *ridx, *cidx; 645 PetscInt rbs, cbs, nr, nc; 646 647 if (!B) B = *newmat; 648 ierr = MatGetLocalToGlobalMapping(B,&rl2g,&cl2g);CHKERRQ(ierr); 649 ierr = ISLocalToGlobalMappingGetBlockIndices(rl2g,&ridx);CHKERRQ(ierr); 650 ierr = ISLocalToGlobalMappingGetBlockIndices(cl2g,&cidx);CHKERRQ(ierr); 651 ierr = ISLocalToGlobalMappingGetSize(rl2g,&nr);CHKERRQ(ierr); 652 ierr = ISLocalToGlobalMappingGetSize(cl2g,&nc);CHKERRQ(ierr); 653 ierr = ISLocalToGlobalMappingGetBlockSize(rl2g,&rbs);CHKERRQ(ierr); 654 ierr = ISLocalToGlobalMappingGetBlockSize(cl2g,&cbs);CHKERRQ(ierr); 655 ierr = ISCreateBlock(comm,rbs,nr/rbs,ridx,PETSC_USE_POINTER,&rows);CHKERRQ(ierr); 656 if (rl2g != cl2g) { 657 ierr = ISCreateBlock(comm,cbs,nc/cbs,cidx,PETSC_USE_POINTER,&cols);CHKERRQ(ierr); 658 } else { 659 ierr = PetscObjectReference((PetscObject)rows);CHKERRQ(ierr); 660 cols = rows; 661 } 662 ierr = MatISGetLocalMat(B,&lA);CHKERRQ(ierr); 663 ierr = MatCreateSubMatrices(A,1,&rows,&cols,MAT_INITIAL_MATRIX,&newlA);CHKERRQ(ierr); 664 ierr = MatConvert(newlA[0],MATSEQAIJ,MAT_INPLACE_MATRIX,&newlA[0]);CHKERRQ(ierr); 665 ierr = ISLocalToGlobalMappingRestoreBlockIndices(rl2g,&ridx);CHKERRQ(ierr); 666 ierr = ISLocalToGlobalMappingRestoreBlockIndices(cl2g,&cidx);CHKERRQ(ierr); 667 ierr = ISDestroy(&rows);CHKERRQ(ierr); 668 ierr = ISDestroy(&cols);CHKERRQ(ierr); 669 if (!lA->preallocated) { /* first time */ 670 ierr = MatDuplicate(newlA[0],MAT_COPY_VALUES,&lA);CHKERRQ(ierr); 671 ierr = MatISSetLocalMat(B,lA);CHKERRQ(ierr); 672 ierr = PetscObjectDereference((PetscObject)lA);CHKERRQ(ierr); 673 } 674 ierr = MatCopy(newlA[0],lA,SAME_NONZERO_PATTERN);CHKERRQ(ierr); 675 ierr = MatDestroySubMatrices(1,&newlA);CHKERRQ(ierr); 676 ierr = MatISScaleDisassembling_Private(B);CHKERRQ(ierr); 677 ierr = MatAssemblyBegin(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 678 ierr = MatAssemblyEnd(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 679 if (was_inplace) { ierr = MatHeaderReplace(A,&B);CHKERRQ(ierr); } 680 else *newmat = B; 681 PetscFunctionReturn(0); 682 } 683 /* rectangular case, just compress out the column space */ 684 ierr = PetscObjectBaseTypeCompare((PetscObject)A,MATMPIAIJ ,&ismpiaij);CHKERRQ(ierr); 685 ierr = PetscObjectBaseTypeCompare((PetscObject)A,MATMPIBAIJ,&ismpibaij);CHKERRQ(ierr); 686 if (ismpiaij) { 687 bs = 1; 688 ierr = MatMPIAIJGetSeqAIJ(A,&Ad,&Ao,&garray);CHKERRQ(ierr); 689 } else if (ismpibaij) { 690 ierr = MatGetBlockSize(A,&bs);CHKERRQ(ierr); 691 ierr = MatMPIBAIJGetSeqBAIJ(A,&Ad,&Ao,&garray);CHKERRQ(ierr); 692 ierr = MatConvert(Ad,MATSEQAIJ,MAT_INITIAL_MATRIX,&Ad);CHKERRQ(ierr); 693 ierr = MatConvert(Ao,MATSEQAIJ,MAT_INITIAL_MATRIX,&Ao);CHKERRQ(ierr); 694 } else SETERRQ1(comm,PETSC_ERR_SUP,"Type %s",((PetscObject)A)->type_name); 695 ierr = MatSeqAIJGetArray(Ad,&dd);CHKERRQ(ierr); 696 ierr = MatSeqAIJGetArray(Ao,&od);CHKERRQ(ierr); 697 if (!garray) SETERRQ(comm,PETSC_ERR_ARG_WRONGSTATE,"garray not present"); 698 699 /* access relevant information from MPIAIJ */ 700 ierr = MatGetOwnershipRange(A,&str,NULL);CHKERRQ(ierr); 701 ierr = MatGetOwnershipRangeColumn(A,&stc,NULL);CHKERRQ(ierr); 702 ierr = MatGetLocalSize(A,&dr,&dc);CHKERRQ(ierr); 703 ierr = MatGetLocalSize(Ao,NULL,&oc);CHKERRQ(ierr); 704 ierr = MatGetRowIJ(Ad,0,PETSC_FALSE,PETSC_FALSE,&i,&di,&dj,&flg);CHKERRQ(ierr); 705 if (!flg) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Cannot get IJ structure"); 706 ierr = MatGetRowIJ(Ao,0,PETSC_FALSE,PETSC_FALSE,&i,&oi,&oj,&flg);CHKERRQ(ierr); 707 if (!flg) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Cannot get IJ structure"); 708 nnz = di[dr] + oi[dr]; 709 /* store original pointers to be restored later */ 710 odi = di; odj = dj; ooi = oi; ooj = oj; 711 712 /* generate l2g maps for rows and cols */ 713 ierr = ISCreateStride(comm,dr/bs,str/bs,1,&is);CHKERRQ(ierr); 714 if (bs > 1) { 715 IS is2; 716 717 ierr = ISGetLocalSize(is,&i);CHKERRQ(ierr); 718 ierr = ISGetIndices(is,(const PetscInt**)&aux);CHKERRQ(ierr); 719 ierr = ISCreateBlock(comm,bs,i,aux,PETSC_COPY_VALUES,&is2);CHKERRQ(ierr); 720 ierr = ISRestoreIndices(is,(const PetscInt**)&aux);CHKERRQ(ierr); 721 ierr = ISDestroy(&is);CHKERRQ(ierr); 722 is = is2; 723 } 724 ierr = ISLocalToGlobalMappingCreateIS(is,&rl2g);CHKERRQ(ierr); 725 ierr = ISDestroy(&is);CHKERRQ(ierr); 726 if (dr) { 727 ierr = PetscMalloc1((dc+oc)/bs,&aux);CHKERRQ(ierr); 728 for (i=0; i<dc/bs; i++) aux[i] = i+stc/bs; 729 for (i=0; i<oc/bs; i++) aux[i+dc/bs] = garray[i]; 730 ierr = ISCreateBlock(comm,bs,(dc+oc)/bs,aux,PETSC_OWN_POINTER,&is);CHKERRQ(ierr); 731 lc = dc+oc; 732 } else { 733 ierr = ISCreateBlock(comm,bs,0,NULL,PETSC_OWN_POINTER,&is);CHKERRQ(ierr); 734 lc = 0; 735 } 736 ierr = ISLocalToGlobalMappingCreateIS(is,&cl2g);CHKERRQ(ierr); 737 ierr = ISDestroy(&is);CHKERRQ(ierr); 738 739 /* create MATIS object */ 740 ierr = MatCreate(comm,&B);CHKERRQ(ierr); 741 ierr = MatSetSizes(B,dr,dc,PETSC_DECIDE,PETSC_DECIDE);CHKERRQ(ierr); 742 ierr = MatSetType(B,MATIS);CHKERRQ(ierr); 743 ierr = MatSetBlockSize(B,bs);CHKERRQ(ierr); 744 ierr = MatSetLocalToGlobalMapping(B,rl2g,cl2g);CHKERRQ(ierr); 745 ierr = ISLocalToGlobalMappingDestroy(&rl2g);CHKERRQ(ierr); 746 ierr = ISLocalToGlobalMappingDestroy(&cl2g);CHKERRQ(ierr); 747 748 /* merge local matrices */ 749 ierr = PetscMalloc1(nnz+dr+1,&aux);CHKERRQ(ierr); 750 ierr = PetscMalloc1(nnz,&data);CHKERRQ(ierr); 751 ii = aux; 752 jj = aux+dr+1; 753 aa = data; 754 *ii = *(di++) + *(oi++); 755 for (jd=0,jo=0,cum=0;*ii<nnz;cum++) 756 { 757 for (;jd<*di;jd++) { *jj++ = *dj++; *aa++ = *dd++; } 758 for (;jo<*oi;jo++) { *jj++ = *oj++ + dc; *aa++ = *od++; } 759 *(++ii) = *(di++) + *(oi++); 760 } 761 for (;cum<dr;cum++) *(++ii) = nnz; 762 763 ierr = MatRestoreRowIJ(Ad,0,PETSC_FALSE,PETSC_FALSE,&i,&odi,&odj,&flg);CHKERRQ(ierr); 764 if (!flg) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Cannot restore IJ structure"); 765 ierr = MatRestoreRowIJ(Ao,0,PETSC_FALSE,PETSC_FALSE,&i,&ooi,&ooj,&flg);CHKERRQ(ierr); 766 if (!flg) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Cannot restore IJ structure"); 767 ierr = MatSeqAIJRestoreArray(Ad,&dd);CHKERRQ(ierr); 768 ierr = MatSeqAIJRestoreArray(Ao,&od);CHKERRQ(ierr); 769 770 ii = aux; 771 jj = aux+dr+1; 772 aa = data; 773 ierr = MatCreateSeqAIJWithArrays(PETSC_COMM_SELF,dr,lc,ii,jj,aa,&lA);CHKERRQ(ierr); 774 775 /* create containers to destroy the data */ 776 ptrs[0] = aux; 777 ptrs[1] = data; 778 for (i=0; i<2; i++) { 779 PetscContainer c; 780 781 ierr = PetscContainerCreate(PETSC_COMM_SELF,&c);CHKERRQ(ierr); 782 ierr = PetscContainerSetPointer(c,ptrs[i]);CHKERRQ(ierr); 783 ierr = PetscContainerSetUserDestroy(c,PetscContainerUserDestroyDefault);CHKERRQ(ierr); 784 ierr = PetscObjectCompose((PetscObject)lA,names[i],(PetscObject)c);CHKERRQ(ierr); 785 ierr = PetscContainerDestroy(&c);CHKERRQ(ierr); 786 } 787 if (ismpibaij) { /* destroy converted local matrices */ 788 ierr = MatDestroy(&Ad);CHKERRQ(ierr); 789 ierr = MatDestroy(&Ao);CHKERRQ(ierr); 790 } 791 792 /* finalize matrix */ 793 ierr = MatISSetLocalMat(B,lA);CHKERRQ(ierr); 794 ierr = MatDestroy(&lA);CHKERRQ(ierr); 795 ierr = MatAssemblyBegin(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 796 ierr = MatAssemblyEnd(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 797 if (reuse == MAT_INPLACE_MATRIX) { 798 ierr = MatHeaderReplace(A,&B);CHKERRQ(ierr); 799 } else *newmat = B; 800 PetscFunctionReturn(0); 801 } 802 803 PETSC_INTERN PetscErrorCode MatConvert_Nest_IS(Mat A,MatType type,MatReuse reuse,Mat *newmat) 804 { 805 Mat **nest,*snest,**rnest,lA,B; 806 IS *iscol,*isrow,*islrow,*islcol; 807 ISLocalToGlobalMapping rl2g,cl2g; 808 MPI_Comm comm; 809 PetscInt *lr,*lc,*l2gidxs; 810 PetscInt i,j,nr,nc,rbs,cbs; 811 PetscBool convert,lreuse,*istrans; 812 PetscErrorCode ierr; 813 814 PetscFunctionBegin; 815 ierr = MatNestGetSubMats(A,&nr,&nc,&nest);CHKERRQ(ierr); 816 lreuse = PETSC_FALSE; 817 rnest = NULL; 818 if (reuse == MAT_REUSE_MATRIX) { 819 PetscBool ismatis,isnest; 820 821 ierr = PetscObjectTypeCompare((PetscObject)*newmat,MATIS,&ismatis);CHKERRQ(ierr); 822 if (!ismatis) SETERRQ1(PetscObjectComm((PetscObject)*newmat),PETSC_ERR_USER,"Cannot reuse matrix of type %s",((PetscObject)(*newmat))->type_name); 823 ierr = MatISGetLocalMat(*newmat,&lA);CHKERRQ(ierr); 824 ierr = PetscObjectTypeCompare((PetscObject)lA,MATNEST,&isnest);CHKERRQ(ierr); 825 if (isnest) { 826 ierr = MatNestGetSubMats(lA,&i,&j,&rnest);CHKERRQ(ierr); 827 lreuse = (PetscBool)(i == nr && j == nc); 828 if (!lreuse) rnest = NULL; 829 } 830 } 831 ierr = PetscObjectGetComm((PetscObject)A,&comm);CHKERRQ(ierr); 832 ierr = PetscCalloc2(nr,&lr,nc,&lc);CHKERRQ(ierr); 833 ierr = PetscCalloc6(nr,&isrow,nc,&iscol,nr,&islrow,nc,&islcol,nr*nc,&snest,nr*nc,&istrans);CHKERRQ(ierr); 834 ierr = MatNestGetISs(A,isrow,iscol);CHKERRQ(ierr); 835 for (i=0;i<nr;i++) { 836 for (j=0;j<nc;j++) { 837 PetscBool ismatis; 838 PetscInt l1,l2,lb1,lb2,ij=i*nc+j; 839 840 /* Null matrix pointers are allowed in MATNEST */ 841 if (!nest[i][j]) continue; 842 843 /* Nested matrices should be of type MATIS */ 844 ierr = PetscObjectTypeCompare((PetscObject)nest[i][j],MATTRANSPOSEMAT,&istrans[ij]);CHKERRQ(ierr); 845 if (istrans[ij]) { 846 Mat T,lT; 847 ierr = MatTransposeGetMat(nest[i][j],&T);CHKERRQ(ierr); 848 ierr = PetscObjectTypeCompare((PetscObject)T,MATIS,&ismatis);CHKERRQ(ierr); 849 if (!ismatis) SETERRQ2(comm,PETSC_ERR_SUP,"Cannot convert from MATNEST to MATIS! Matrix block (%D,%D) (transposed) is not of type MATIS",i,j); 850 ierr = MatISGetLocalMat(T,&lT);CHKERRQ(ierr); 851 ierr = MatCreateTranspose(lT,&snest[ij]);CHKERRQ(ierr); 852 } else { 853 ierr = PetscObjectTypeCompare((PetscObject)nest[i][j],MATIS,&ismatis);CHKERRQ(ierr); 854 if (!ismatis) SETERRQ2(comm,PETSC_ERR_SUP,"Cannot convert from MATNEST to MATIS! Matrix block (%D,%D) is not of type MATIS",i,j); 855 ierr = MatISGetLocalMat(nest[i][j],&snest[ij]);CHKERRQ(ierr); 856 } 857 858 /* Check compatibility of local sizes */ 859 ierr = MatGetSize(snest[ij],&l1,&l2);CHKERRQ(ierr); 860 ierr = MatGetBlockSizes(snest[ij],&lb1,&lb2);CHKERRQ(ierr); 861 if (!l1 || !l2) continue; 862 if (lr[i] && l1 != lr[i]) SETERRQ4(PETSC_COMM_SELF,PETSC_ERR_SUP,"Cannot convert from MATNEST to MATIS! Matrix block (%D,%D) has invalid local size %D != %D",i,j,lr[i],l1); 863 if (lc[j] && l2 != lc[j]) SETERRQ4(PETSC_COMM_SELF,PETSC_ERR_SUP,"Cannot convert from MATNEST to MATIS! Matrix block (%D,%D) has invalid local size %D != %D",i,j,lc[j],l2); 864 lr[i] = l1; 865 lc[j] = l2; 866 867 /* check compatibilty for local matrix reusage */ 868 if (rnest && !rnest[i][j] != !snest[ij]) lreuse = PETSC_FALSE; 869 } 870 } 871 872 #if defined (PETSC_USE_DEBUG) 873 /* Check compatibility of l2g maps for rows */ 874 for (i=0;i<nr;i++) { 875 rl2g = NULL; 876 for (j=0;j<nc;j++) { 877 PetscInt n1,n2; 878 879 if (!nest[i][j]) continue; 880 if (istrans[i*nc+j]) { 881 Mat T; 882 883 ierr = MatTransposeGetMat(nest[i][j],&T);CHKERRQ(ierr); 884 ierr = MatGetLocalToGlobalMapping(T,NULL,&cl2g);CHKERRQ(ierr); 885 } else { 886 ierr = MatGetLocalToGlobalMapping(nest[i][j],&cl2g,NULL);CHKERRQ(ierr); 887 } 888 ierr = ISLocalToGlobalMappingGetSize(cl2g,&n1);CHKERRQ(ierr); 889 if (!n1) continue; 890 if (!rl2g) { 891 rl2g = cl2g; 892 } else { 893 const PetscInt *idxs1,*idxs2; 894 PetscBool same; 895 896 ierr = ISLocalToGlobalMappingGetSize(rl2g,&n2);CHKERRQ(ierr); 897 if (n1 != n2) SETERRQ4(PETSC_COMM_SELF,PETSC_ERR_SUP,"Cannot convert from MATNEST to MATIS! Matrix block (%D,%D) has invalid row l2gmap size %D != %D",i,j,n1,n2); 898 ierr = ISLocalToGlobalMappingGetIndices(cl2g,&idxs1);CHKERRQ(ierr); 899 ierr = ISLocalToGlobalMappingGetIndices(rl2g,&idxs2);CHKERRQ(ierr); 900 ierr = PetscArraycmp(idxs1,idxs2,n1,&same);CHKERRQ(ierr); 901 ierr = ISLocalToGlobalMappingRestoreIndices(cl2g,&idxs1);CHKERRQ(ierr); 902 ierr = ISLocalToGlobalMappingRestoreIndices(rl2g,&idxs2);CHKERRQ(ierr); 903 if (!same) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_SUP,"Cannot convert from MATNEST to MATIS! Matrix block (%D,%D) has invalid row l2gmap",i,j); 904 } 905 } 906 } 907 /* Check compatibility of l2g maps for columns */ 908 for (i=0;i<nc;i++) { 909 rl2g = NULL; 910 for (j=0;j<nr;j++) { 911 PetscInt n1,n2; 912 913 if (!nest[j][i]) continue; 914 if (istrans[j*nc+i]) { 915 Mat T; 916 917 ierr = MatTransposeGetMat(nest[j][i],&T);CHKERRQ(ierr); 918 ierr = MatGetLocalToGlobalMapping(T,&cl2g,NULL);CHKERRQ(ierr); 919 } else { 920 ierr = MatGetLocalToGlobalMapping(nest[j][i],NULL,&cl2g);CHKERRQ(ierr); 921 } 922 ierr = ISLocalToGlobalMappingGetSize(cl2g,&n1);CHKERRQ(ierr); 923 if (!n1) continue; 924 if (!rl2g) { 925 rl2g = cl2g; 926 } else { 927 const PetscInt *idxs1,*idxs2; 928 PetscBool same; 929 930 ierr = ISLocalToGlobalMappingGetSize(rl2g,&n2);CHKERRQ(ierr); 931 if (n1 != n2) SETERRQ4(PETSC_COMM_SELF,PETSC_ERR_SUP,"Cannot convert from MATNEST to MATIS! Matrix block (%D,%D) has invalid column l2gmap size %D != %D",j,i,n1,n2); 932 ierr = ISLocalToGlobalMappingGetIndices(cl2g,&idxs1);CHKERRQ(ierr); 933 ierr = ISLocalToGlobalMappingGetIndices(rl2g,&idxs2);CHKERRQ(ierr); 934 ierr = PetscArraycmp(idxs1,idxs2,n1,&same);CHKERRQ(ierr); 935 ierr = ISLocalToGlobalMappingRestoreIndices(cl2g,&idxs1);CHKERRQ(ierr); 936 ierr = ISLocalToGlobalMappingRestoreIndices(rl2g,&idxs2);CHKERRQ(ierr); 937 if (!same) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_SUP,"Cannot convert from MATNEST to MATIS! Matrix block (%D,%D) has invalid column l2gmap",j,i); 938 } 939 } 940 } 941 #endif 942 943 B = NULL; 944 if (reuse != MAT_REUSE_MATRIX) { 945 PetscInt stl; 946 947 /* Create l2g map for the rows of the new matrix and index sets for the local MATNEST */ 948 for (i=0,stl=0;i<nr;i++) stl += lr[i]; 949 ierr = PetscMalloc1(stl,&l2gidxs);CHKERRQ(ierr); 950 for (i=0,stl=0;i<nr;i++) { 951 Mat usedmat; 952 Mat_IS *matis; 953 const PetscInt *idxs; 954 955 /* local IS for local NEST */ 956 ierr = ISCreateStride(PETSC_COMM_SELF,lr[i],stl,1,&islrow[i]);CHKERRQ(ierr); 957 958 /* l2gmap */ 959 j = 0; 960 usedmat = nest[i][j]; 961 while (!usedmat && j < nc-1) usedmat = nest[i][++j]; 962 if (!usedmat) SETERRQ(comm,PETSC_ERR_SUP,"Cannot find valid row mat"); 963 964 if (istrans[i*nc+j]) { 965 Mat T; 966 ierr = MatTransposeGetMat(usedmat,&T);CHKERRQ(ierr); 967 usedmat = T; 968 } 969 matis = (Mat_IS*)(usedmat->data); 970 ierr = ISGetIndices(isrow[i],&idxs);CHKERRQ(ierr); 971 if (istrans[i*nc+j]) { 972 ierr = PetscSFBcastBegin(matis->csf,MPIU_INT,idxs,l2gidxs+stl);CHKERRQ(ierr); 973 ierr = PetscSFBcastEnd(matis->csf,MPIU_INT,idxs,l2gidxs+stl);CHKERRQ(ierr); 974 } else { 975 ierr = PetscSFBcastBegin(matis->sf,MPIU_INT,idxs,l2gidxs+stl);CHKERRQ(ierr); 976 ierr = PetscSFBcastEnd(matis->sf,MPIU_INT,idxs,l2gidxs+stl);CHKERRQ(ierr); 977 } 978 ierr = ISRestoreIndices(isrow[i],&idxs);CHKERRQ(ierr); 979 stl += lr[i]; 980 } 981 ierr = ISLocalToGlobalMappingCreate(comm,1,stl,l2gidxs,PETSC_OWN_POINTER,&rl2g);CHKERRQ(ierr); 982 983 /* Create l2g map for columns of the new matrix and index sets for the local MATNEST */ 984 for (i=0,stl=0;i<nc;i++) stl += lc[i]; 985 ierr = PetscMalloc1(stl,&l2gidxs);CHKERRQ(ierr); 986 for (i=0,stl=0;i<nc;i++) { 987 Mat usedmat; 988 Mat_IS *matis; 989 const PetscInt *idxs; 990 991 /* local IS for local NEST */ 992 ierr = ISCreateStride(PETSC_COMM_SELF,lc[i],stl,1,&islcol[i]);CHKERRQ(ierr); 993 994 /* l2gmap */ 995 j = 0; 996 usedmat = nest[j][i]; 997 while (!usedmat && j < nr-1) usedmat = nest[++j][i]; 998 if (!usedmat) SETERRQ(comm,PETSC_ERR_SUP,"Cannot find valid column mat"); 999 if (istrans[j*nc+i]) { 1000 Mat T; 1001 ierr = MatTransposeGetMat(usedmat,&T);CHKERRQ(ierr); 1002 usedmat = T; 1003 } 1004 matis = (Mat_IS*)(usedmat->data); 1005 ierr = ISGetIndices(iscol[i],&idxs);CHKERRQ(ierr); 1006 if (istrans[j*nc+i]) { 1007 ierr = PetscSFBcastBegin(matis->sf,MPIU_INT,idxs,l2gidxs+stl);CHKERRQ(ierr); 1008 ierr = PetscSFBcastEnd(matis->sf,MPIU_INT,idxs,l2gidxs+stl);CHKERRQ(ierr); 1009 } else { 1010 ierr = PetscSFBcastBegin(matis->csf,MPIU_INT,idxs,l2gidxs+stl);CHKERRQ(ierr); 1011 ierr = PetscSFBcastEnd(matis->csf,MPIU_INT,idxs,l2gidxs+stl);CHKERRQ(ierr); 1012 } 1013 ierr = ISRestoreIndices(iscol[i],&idxs);CHKERRQ(ierr); 1014 stl += lc[i]; 1015 } 1016 ierr = ISLocalToGlobalMappingCreate(comm,1,stl,l2gidxs,PETSC_OWN_POINTER,&cl2g);CHKERRQ(ierr); 1017 1018 /* Create MATIS */ 1019 ierr = MatCreate(comm,&B);CHKERRQ(ierr); 1020 ierr = MatSetSizes(B,A->rmap->n,A->cmap->n,A->rmap->N,A->cmap->N);CHKERRQ(ierr); 1021 ierr = MatGetBlockSizes(A,&rbs,&cbs);CHKERRQ(ierr); 1022 ierr = MatSetBlockSizes(B,rbs,cbs);CHKERRQ(ierr); 1023 ierr = MatSetType(B,MATIS);CHKERRQ(ierr); 1024 ierr = MatISSetLocalMatType(B,MATNEST);CHKERRQ(ierr); 1025 { /* hack : avoid setup of scatters */ 1026 Mat_IS *matis = (Mat_IS*)(B->data); 1027 matis->islocalref = PETSC_TRUE; 1028 } 1029 ierr = MatSetLocalToGlobalMapping(B,rl2g,cl2g);CHKERRQ(ierr); 1030 ierr = ISLocalToGlobalMappingDestroy(&rl2g);CHKERRQ(ierr); 1031 ierr = ISLocalToGlobalMappingDestroy(&cl2g);CHKERRQ(ierr); 1032 ierr = MatCreateNest(PETSC_COMM_SELF,nr,islrow,nc,islcol,snest,&lA);CHKERRQ(ierr); 1033 ierr = MatNestSetVecType(lA,VECNEST);CHKERRQ(ierr); 1034 for (i=0;i<nr*nc;i++) { 1035 if (istrans[i]) { 1036 ierr = MatDestroy(&snest[i]);CHKERRQ(ierr); 1037 } 1038 } 1039 ierr = MatISSetLocalMat(B,lA);CHKERRQ(ierr); 1040 ierr = MatDestroy(&lA);CHKERRQ(ierr); 1041 { /* hack : setup of scatters done here */ 1042 Mat_IS *matis = (Mat_IS*)(B->data); 1043 1044 matis->islocalref = PETSC_FALSE; 1045 ierr = MatISSetUpScatters_Private(B);CHKERRQ(ierr); 1046 } 1047 ierr = MatAssemblyBegin(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 1048 ierr = MatAssemblyEnd(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 1049 if (reuse == MAT_INPLACE_MATRIX) { 1050 ierr = MatHeaderReplace(A,&B);CHKERRQ(ierr); 1051 } else { 1052 *newmat = B; 1053 } 1054 } else { 1055 if (lreuse) { 1056 ierr = MatISGetLocalMat(*newmat,&lA);CHKERRQ(ierr); 1057 for (i=0;i<nr;i++) { 1058 for (j=0;j<nc;j++) { 1059 if (snest[i*nc+j]) { 1060 ierr = MatNestSetSubMat(lA,i,j,snest[i*nc+j]);CHKERRQ(ierr); 1061 if (istrans[i*nc+j]) { 1062 ierr = MatDestroy(&snest[i*nc+j]);CHKERRQ(ierr); 1063 } 1064 } 1065 } 1066 } 1067 } else { 1068 PetscInt stl; 1069 for (i=0,stl=0;i<nr;i++) { 1070 ierr = ISCreateStride(PETSC_COMM_SELF,lr[i],stl,1,&islrow[i]);CHKERRQ(ierr); 1071 stl += lr[i]; 1072 } 1073 for (i=0,stl=0;i<nc;i++) { 1074 ierr = ISCreateStride(PETSC_COMM_SELF,lc[i],stl,1,&islcol[i]);CHKERRQ(ierr); 1075 stl += lc[i]; 1076 } 1077 ierr = MatCreateNest(PETSC_COMM_SELF,nr,islrow,nc,islcol,snest,&lA);CHKERRQ(ierr); 1078 for (i=0;i<nr*nc;i++) { 1079 if (istrans[i]) { 1080 ierr = MatDestroy(&snest[i]);CHKERRQ(ierr); 1081 } 1082 } 1083 ierr = MatISSetLocalMat(*newmat,lA);CHKERRQ(ierr); 1084 ierr = MatDestroy(&lA);CHKERRQ(ierr); 1085 } 1086 ierr = MatAssemblyBegin(*newmat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 1087 ierr = MatAssemblyEnd(*newmat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 1088 } 1089 1090 /* Create local matrix in MATNEST format */ 1091 convert = PETSC_FALSE; 1092 ierr = PetscOptionsGetBool(NULL,((PetscObject)A)->prefix,"-matis_convert_local_nest",&convert,NULL);CHKERRQ(ierr); 1093 if (convert) { 1094 Mat M; 1095 MatISLocalFields lf; 1096 PetscContainer c; 1097 1098 ierr = MatISGetLocalMat(*newmat,&lA);CHKERRQ(ierr); 1099 ierr = MatConvert(lA,MATAIJ,MAT_INITIAL_MATRIX,&M);CHKERRQ(ierr); 1100 ierr = MatISSetLocalMat(*newmat,M);CHKERRQ(ierr); 1101 ierr = MatDestroy(&M);CHKERRQ(ierr); 1102 1103 /* attach local fields to the matrix */ 1104 ierr = PetscNew(&lf);CHKERRQ(ierr); 1105 ierr = PetscMalloc2(nr,&lf->rf,nc,&lf->cf);CHKERRQ(ierr); 1106 for (i=0;i<nr;i++) { 1107 PetscInt n,st; 1108 1109 ierr = ISGetLocalSize(islrow[i],&n);CHKERRQ(ierr); 1110 ierr = ISStrideGetInfo(islrow[i],&st,NULL);CHKERRQ(ierr); 1111 ierr = ISCreateStride(comm,n,st,1,&lf->rf[i]);CHKERRQ(ierr); 1112 } 1113 for (i=0;i<nc;i++) { 1114 PetscInt n,st; 1115 1116 ierr = ISGetLocalSize(islcol[i],&n);CHKERRQ(ierr); 1117 ierr = ISStrideGetInfo(islcol[i],&st,NULL);CHKERRQ(ierr); 1118 ierr = ISCreateStride(comm,n,st,1,&lf->cf[i]);CHKERRQ(ierr); 1119 } 1120 lf->nr = nr; 1121 lf->nc = nc; 1122 ierr = PetscContainerCreate(PetscObjectComm((PetscObject)(*newmat)),&c);CHKERRQ(ierr); 1123 ierr = PetscContainerSetPointer(c,lf);CHKERRQ(ierr); 1124 ierr = PetscContainerSetUserDestroy(c,MatISContainerDestroyFields_Private);CHKERRQ(ierr); 1125 ierr = PetscObjectCompose((PetscObject)(*newmat),"_convert_nest_lfields",(PetscObject)c);CHKERRQ(ierr); 1126 ierr = PetscContainerDestroy(&c);CHKERRQ(ierr); 1127 } 1128 1129 /* Free workspace */ 1130 for (i=0;i<nr;i++) { 1131 ierr = ISDestroy(&islrow[i]);CHKERRQ(ierr); 1132 } 1133 for (i=0;i<nc;i++) { 1134 ierr = ISDestroy(&islcol[i]);CHKERRQ(ierr); 1135 } 1136 ierr = PetscFree6(isrow,iscol,islrow,islcol,snest,istrans);CHKERRQ(ierr); 1137 ierr = PetscFree2(lr,lc);CHKERRQ(ierr); 1138 PetscFunctionReturn(0); 1139 } 1140 1141 static PetscErrorCode MatDiagonalScale_IS(Mat A, Vec l, Vec r) 1142 { 1143 Mat_IS *matis = (Mat_IS*)A->data; 1144 Vec ll,rr; 1145 const PetscScalar *Y,*X; 1146 PetscScalar *x,*y; 1147 PetscErrorCode ierr; 1148 1149 PetscFunctionBegin; 1150 if (l) { 1151 ll = matis->y; 1152 ierr = VecGetArrayRead(l,&Y);CHKERRQ(ierr); 1153 ierr = VecGetArray(ll,&y);CHKERRQ(ierr); 1154 ierr = PetscSFBcastBegin(matis->sf,MPIU_SCALAR,Y,y);CHKERRQ(ierr); 1155 } else { 1156 ll = NULL; 1157 } 1158 if (r) { 1159 rr = matis->x; 1160 ierr = VecGetArrayRead(r,&X);CHKERRQ(ierr); 1161 ierr = VecGetArray(rr,&x);CHKERRQ(ierr); 1162 ierr = PetscSFBcastBegin(matis->csf,MPIU_SCALAR,X,x);CHKERRQ(ierr); 1163 } else { 1164 rr = NULL; 1165 } 1166 if (ll) { 1167 ierr = PetscSFBcastEnd(matis->sf,MPIU_SCALAR,Y,y);CHKERRQ(ierr); 1168 ierr = VecRestoreArrayRead(l,&Y);CHKERRQ(ierr); 1169 ierr = VecRestoreArray(ll,&y);CHKERRQ(ierr); 1170 } 1171 if (rr) { 1172 ierr = PetscSFBcastEnd(matis->csf,MPIU_SCALAR,X,x);CHKERRQ(ierr); 1173 ierr = VecRestoreArrayRead(r,&X);CHKERRQ(ierr); 1174 ierr = VecRestoreArray(rr,&x);CHKERRQ(ierr); 1175 } 1176 ierr = MatDiagonalScale(matis->A,ll,rr);CHKERRQ(ierr); 1177 PetscFunctionReturn(0); 1178 } 1179 1180 static PetscErrorCode MatGetInfo_IS(Mat A,MatInfoType flag,MatInfo *ginfo) 1181 { 1182 Mat_IS *matis = (Mat_IS*)A->data; 1183 MatInfo info; 1184 PetscLogDouble isend[6],irecv[6]; 1185 PetscInt bs; 1186 PetscErrorCode ierr; 1187 1188 PetscFunctionBegin; 1189 ierr = MatGetBlockSize(A,&bs);CHKERRQ(ierr); 1190 if (matis->A->ops->getinfo) { 1191 ierr = MatGetInfo(matis->A,MAT_LOCAL,&info);CHKERRQ(ierr); 1192 isend[0] = info.nz_used; 1193 isend[1] = info.nz_allocated; 1194 isend[2] = info.nz_unneeded; 1195 isend[3] = info.memory; 1196 isend[4] = info.mallocs; 1197 } else { 1198 isend[0] = 0.; 1199 isend[1] = 0.; 1200 isend[2] = 0.; 1201 isend[3] = 0.; 1202 isend[4] = 0.; 1203 } 1204 isend[5] = matis->A->num_ass; 1205 if (flag == MAT_LOCAL) { 1206 ginfo->nz_used = isend[0]; 1207 ginfo->nz_allocated = isend[1]; 1208 ginfo->nz_unneeded = isend[2]; 1209 ginfo->memory = isend[3]; 1210 ginfo->mallocs = isend[4]; 1211 ginfo->assemblies = isend[5]; 1212 } else if (flag == MAT_GLOBAL_MAX) { 1213 ierr = MPIU_Allreduce(isend,irecv,6,MPIU_PETSCLOGDOUBLE,MPI_MAX,PetscObjectComm((PetscObject)A));CHKERRQ(ierr); 1214 1215 ginfo->nz_used = irecv[0]; 1216 ginfo->nz_allocated = irecv[1]; 1217 ginfo->nz_unneeded = irecv[2]; 1218 ginfo->memory = irecv[3]; 1219 ginfo->mallocs = irecv[4]; 1220 ginfo->assemblies = irecv[5]; 1221 } else if (flag == MAT_GLOBAL_SUM) { 1222 ierr = MPIU_Allreduce(isend,irecv,5,MPIU_PETSCLOGDOUBLE,MPI_SUM,PetscObjectComm((PetscObject)A));CHKERRQ(ierr); 1223 1224 ginfo->nz_used = irecv[0]; 1225 ginfo->nz_allocated = irecv[1]; 1226 ginfo->nz_unneeded = irecv[2]; 1227 ginfo->memory = irecv[3]; 1228 ginfo->mallocs = irecv[4]; 1229 ginfo->assemblies = A->num_ass; 1230 } 1231 ginfo->block_size = bs; 1232 ginfo->fill_ratio_given = 0; 1233 ginfo->fill_ratio_needed = 0; 1234 ginfo->factor_mallocs = 0; 1235 PetscFunctionReturn(0); 1236 } 1237 1238 PetscErrorCode MatTranspose_IS(Mat A,MatReuse reuse,Mat *B) 1239 { 1240 Mat C,lC,lA; 1241 PetscErrorCode ierr; 1242 1243 PetscFunctionBegin; 1244 if (reuse == MAT_INITIAL_MATRIX || reuse == MAT_INPLACE_MATRIX) { 1245 ISLocalToGlobalMapping rl2g,cl2g; 1246 ierr = MatCreate(PetscObjectComm((PetscObject)A),&C);CHKERRQ(ierr); 1247 ierr = MatSetSizes(C,A->cmap->n,A->rmap->n,A->cmap->N,A->rmap->N);CHKERRQ(ierr); 1248 ierr = MatSetBlockSizes(C,PetscAbs(A->cmap->bs),PetscAbs(A->rmap->bs));CHKERRQ(ierr); 1249 ierr = MatSetType(C,MATIS);CHKERRQ(ierr); 1250 ierr = MatGetLocalToGlobalMapping(A,&rl2g,&cl2g);CHKERRQ(ierr); 1251 ierr = MatSetLocalToGlobalMapping(C,cl2g,rl2g);CHKERRQ(ierr); 1252 } else { 1253 C = *B; 1254 } 1255 1256 /* perform local transposition */ 1257 ierr = MatISGetLocalMat(A,&lA);CHKERRQ(ierr); 1258 ierr = MatTranspose(lA,MAT_INITIAL_MATRIX,&lC);CHKERRQ(ierr); 1259 ierr = MatISSetLocalMat(C,lC);CHKERRQ(ierr); 1260 ierr = MatDestroy(&lC);CHKERRQ(ierr); 1261 1262 if (reuse == MAT_INITIAL_MATRIX || reuse == MAT_REUSE_MATRIX) { 1263 *B = C; 1264 } else { 1265 ierr = MatHeaderMerge(A,&C);CHKERRQ(ierr); 1266 } 1267 ierr = MatAssemblyBegin(*B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 1268 ierr = MatAssemblyEnd(*B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 1269 PetscFunctionReturn(0); 1270 } 1271 1272 PetscErrorCode MatDiagonalSet_IS(Mat A,Vec D,InsertMode insmode) 1273 { 1274 Mat_IS *is = (Mat_IS*)A->data; 1275 PetscErrorCode ierr; 1276 1277 PetscFunctionBegin; 1278 if (D) { /* MatShift_IS pass D = NULL */ 1279 ierr = VecScatterBegin(is->rctx,D,is->y,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 1280 ierr = VecScatterEnd(is->rctx,D,is->y,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 1281 } 1282 ierr = VecPointwiseDivide(is->y,is->y,is->counter);CHKERRQ(ierr); 1283 ierr = MatDiagonalSet(is->A,is->y,insmode);CHKERRQ(ierr); 1284 PetscFunctionReturn(0); 1285 } 1286 1287 PetscErrorCode MatShift_IS(Mat A,PetscScalar a) 1288 { 1289 Mat_IS *is = (Mat_IS*)A->data; 1290 PetscErrorCode ierr; 1291 1292 PetscFunctionBegin; 1293 ierr = VecSet(is->y,a);CHKERRQ(ierr); 1294 ierr = MatDiagonalSet_IS(A,NULL,ADD_VALUES);CHKERRQ(ierr); 1295 PetscFunctionReturn(0); 1296 } 1297 1298 static PetscErrorCode MatSetValuesLocal_SubMat_IS(Mat A,PetscInt m,const PetscInt *rows, PetscInt n,const PetscInt *cols,const PetscScalar *values,InsertMode addv) 1299 { 1300 PetscErrorCode ierr; 1301 PetscInt rows_l[MATIS_MAX_ENTRIES_INSERTION],cols_l[MATIS_MAX_ENTRIES_INSERTION]; 1302 1303 PetscFunctionBegin; 1304 #if defined(PETSC_USE_DEBUG) 1305 if (m > MATIS_MAX_ENTRIES_INSERTION || n > MATIS_MAX_ENTRIES_INSERTION) SETERRQ3(PETSC_COMM_SELF,PETSC_ERR_SUP,"Number of row/column indices must be <= %D: they are %D %D",MATIS_MAX_ENTRIES_INSERTION,m,n); 1306 #endif 1307 ierr = ISLocalToGlobalMappingApply(A->rmap->mapping,m,rows,rows_l);CHKERRQ(ierr); 1308 ierr = ISLocalToGlobalMappingApply(A->cmap->mapping,n,cols,cols_l);CHKERRQ(ierr); 1309 ierr = MatSetValuesLocal_IS(A,m,rows_l,n,cols_l,values,addv);CHKERRQ(ierr); 1310 PetscFunctionReturn(0); 1311 } 1312 1313 static PetscErrorCode MatSetValuesBlockedLocal_SubMat_IS(Mat A,PetscInt m,const PetscInt *rows, PetscInt n,const PetscInt *cols,const PetscScalar *values,InsertMode addv) 1314 { 1315 PetscErrorCode ierr; 1316 PetscInt rows_l[MATIS_MAX_ENTRIES_INSERTION],cols_l[MATIS_MAX_ENTRIES_INSERTION]; 1317 1318 PetscFunctionBegin; 1319 #if defined(PETSC_USE_DEBUG) 1320 if (m > MATIS_MAX_ENTRIES_INSERTION || n > MATIS_MAX_ENTRIES_INSERTION) SETERRQ3(PETSC_COMM_SELF,PETSC_ERR_SUP,"Number of row/column block indices must be <= %D: they are %D %D",MATIS_MAX_ENTRIES_INSERTION,m,n); 1321 #endif 1322 ierr = ISLocalToGlobalMappingApplyBlock(A->rmap->mapping,m,rows,rows_l);CHKERRQ(ierr); 1323 ierr = ISLocalToGlobalMappingApplyBlock(A->cmap->mapping,n,cols,cols_l);CHKERRQ(ierr); 1324 ierr = MatSetValuesBlockedLocal_IS(A,m,rows_l,n,cols_l,values,addv);CHKERRQ(ierr); 1325 PetscFunctionReturn(0); 1326 } 1327 1328 static PetscErrorCode MatCreateSubMatrix_IS(Mat mat,IS irow,IS icol,MatReuse scall,Mat *newmat) 1329 { 1330 Mat locmat,newlocmat; 1331 Mat_IS *newmatis; 1332 #if defined(PETSC_USE_DEBUG) 1333 Vec rtest,ltest; 1334 const PetscScalar *array; 1335 #endif 1336 const PetscInt *idxs; 1337 PetscInt i,m,n; 1338 PetscErrorCode ierr; 1339 1340 PetscFunctionBegin; 1341 if (scall == MAT_REUSE_MATRIX) { 1342 PetscBool ismatis; 1343 1344 ierr = PetscObjectTypeCompare((PetscObject)*newmat,MATIS,&ismatis);CHKERRQ(ierr); 1345 if (!ismatis) SETERRQ(PetscObjectComm((PetscObject)*newmat),PETSC_ERR_ARG_WRONG,"Cannot reuse matrix! Not of MATIS type"); 1346 newmatis = (Mat_IS*)(*newmat)->data; 1347 if (!newmatis->getsub_ris) SETERRQ(PetscObjectComm((PetscObject)*newmat),PETSC_ERR_ARG_WRONG,"Cannot reuse matrix! Misses local row IS"); 1348 if (!newmatis->getsub_cis) SETERRQ(PetscObjectComm((PetscObject)*newmat),PETSC_ERR_ARG_WRONG,"Cannot reuse matrix! Misses local col IS"); 1349 } 1350 /* irow and icol may not have duplicate entries */ 1351 #if defined(PETSC_USE_DEBUG) 1352 ierr = MatCreateVecs(mat,<est,&rtest);CHKERRQ(ierr); 1353 ierr = ISGetLocalSize(irow,&n);CHKERRQ(ierr); 1354 ierr = ISGetIndices(irow,&idxs);CHKERRQ(ierr); 1355 for (i=0;i<n;i++) { 1356 ierr = VecSetValue(rtest,idxs[i],1.0,ADD_VALUES);CHKERRQ(ierr); 1357 } 1358 ierr = VecAssemblyBegin(rtest);CHKERRQ(ierr); 1359 ierr = VecAssemblyEnd(rtest);CHKERRQ(ierr); 1360 ierr = VecGetLocalSize(rtest,&n);CHKERRQ(ierr); 1361 ierr = VecGetOwnershipRange(rtest,&m,NULL);CHKERRQ(ierr); 1362 ierr = VecGetArrayRead(rtest,&array);CHKERRQ(ierr); 1363 for (i=0;i<n;i++) if (array[i] != 0. && array[i] != 1.) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_SUP,"Index %D counted %D times! Irow may not have duplicate entries",i+m,(PetscInt)PetscRealPart(array[i])); 1364 ierr = VecRestoreArrayRead(rtest,&array);CHKERRQ(ierr); 1365 ierr = ISRestoreIndices(irow,&idxs);CHKERRQ(ierr); 1366 ierr = ISGetLocalSize(icol,&n);CHKERRQ(ierr); 1367 ierr = ISGetIndices(icol,&idxs);CHKERRQ(ierr); 1368 for (i=0;i<n;i++) { 1369 ierr = VecSetValue(ltest,idxs[i],1.0,ADD_VALUES);CHKERRQ(ierr); 1370 } 1371 ierr = VecAssemblyBegin(ltest);CHKERRQ(ierr); 1372 ierr = VecAssemblyEnd(ltest);CHKERRQ(ierr); 1373 ierr = VecGetLocalSize(ltest,&n);CHKERRQ(ierr); 1374 ierr = VecGetOwnershipRange(ltest,&m,NULL);CHKERRQ(ierr); 1375 ierr = VecGetArrayRead(ltest,&array);CHKERRQ(ierr); 1376 for (i=0;i<n;i++) if (array[i] != 0. && array[i] != 1.) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_SUP,"Index %D counted %D times! Icol may not have duplicate entries",i+m,(PetscInt)PetscRealPart(array[i])); 1377 ierr = VecRestoreArrayRead(ltest,&array);CHKERRQ(ierr); 1378 ierr = ISRestoreIndices(icol,&idxs);CHKERRQ(ierr); 1379 ierr = VecDestroy(&rtest);CHKERRQ(ierr); 1380 ierr = VecDestroy(<est);CHKERRQ(ierr); 1381 #endif 1382 if (scall == MAT_INITIAL_MATRIX) { 1383 Mat_IS *matis = (Mat_IS*)mat->data; 1384 ISLocalToGlobalMapping rl2g; 1385 IS is; 1386 PetscInt *lidxs,*lgidxs,*newgidxs; 1387 PetscInt ll,newloc,irbs,icbs,arbs,acbs,rbs,cbs; 1388 PetscBool cong; 1389 MPI_Comm comm; 1390 1391 ierr = PetscObjectGetComm((PetscObject)mat,&comm);CHKERRQ(ierr); 1392 ierr = MatGetBlockSizes(mat,&arbs,&acbs);CHKERRQ(ierr); 1393 ierr = ISGetBlockSize(irow,&irbs);CHKERRQ(ierr); 1394 ierr = ISGetBlockSize(icol,&icbs);CHKERRQ(ierr); 1395 rbs = arbs == irbs ? irbs : 1; 1396 cbs = acbs == icbs ? icbs : 1; 1397 ierr = ISGetLocalSize(irow,&m);CHKERRQ(ierr); 1398 ierr = ISGetLocalSize(icol,&n);CHKERRQ(ierr); 1399 ierr = MatCreate(comm,newmat);CHKERRQ(ierr); 1400 ierr = MatSetType(*newmat,MATIS);CHKERRQ(ierr); 1401 ierr = MatSetSizes(*newmat,m,n,PETSC_DECIDE,PETSC_DECIDE);CHKERRQ(ierr); 1402 ierr = MatSetBlockSizes(*newmat,rbs,cbs);CHKERRQ(ierr); 1403 /* communicate irow to their owners in the layout */ 1404 ierr = ISGetIndices(irow,&idxs);CHKERRQ(ierr); 1405 ierr = PetscLayoutMapLocal(mat->rmap,m,idxs,&ll,&lidxs,&lgidxs);CHKERRQ(ierr); 1406 ierr = ISRestoreIndices(irow,&idxs);CHKERRQ(ierr); 1407 ierr = PetscArrayzero(matis->sf_rootdata,matis->sf->nroots);CHKERRQ(ierr); 1408 for (i=0;i<ll;i++) matis->sf_rootdata[lidxs[i]] = lgidxs[i]+1; 1409 ierr = PetscFree(lidxs);CHKERRQ(ierr); 1410 ierr = PetscFree(lgidxs);CHKERRQ(ierr); 1411 ierr = PetscSFBcastBegin(matis->sf,MPIU_INT,matis->sf_rootdata,matis->sf_leafdata);CHKERRQ(ierr); 1412 ierr = PetscSFBcastEnd(matis->sf,MPIU_INT,matis->sf_rootdata,matis->sf_leafdata);CHKERRQ(ierr); 1413 for (i=0,newloc=0;i<matis->sf->nleaves;i++) if (matis->sf_leafdata[i]) newloc++; 1414 ierr = PetscMalloc1(newloc,&newgidxs);CHKERRQ(ierr); 1415 ierr = PetscMalloc1(newloc,&lidxs);CHKERRQ(ierr); 1416 for (i=0,newloc=0;i<matis->sf->nleaves;i++) 1417 if (matis->sf_leafdata[i]) { 1418 lidxs[newloc] = i; 1419 newgidxs[newloc++] = matis->sf_leafdata[i]-1; 1420 } 1421 ierr = ISCreateGeneral(comm,newloc,newgidxs,PETSC_OWN_POINTER,&is);CHKERRQ(ierr); 1422 ierr = ISLocalToGlobalMappingCreateIS(is,&rl2g);CHKERRQ(ierr); 1423 ierr = ISLocalToGlobalMappingSetBlockSize(rl2g,rbs);CHKERRQ(ierr); 1424 ierr = ISDestroy(&is);CHKERRQ(ierr); 1425 /* local is to extract local submatrix */ 1426 newmatis = (Mat_IS*)(*newmat)->data; 1427 ierr = ISCreateGeneral(comm,newloc,lidxs,PETSC_OWN_POINTER,&newmatis->getsub_ris);CHKERRQ(ierr); 1428 ierr = MatHasCongruentLayouts(mat,&cong);CHKERRQ(ierr); 1429 if (cong && irow == icol && matis->csf == matis->sf) { 1430 ierr = MatSetLocalToGlobalMapping(*newmat,rl2g,rl2g);CHKERRQ(ierr); 1431 ierr = PetscObjectReference((PetscObject)newmatis->getsub_ris);CHKERRQ(ierr); 1432 newmatis->getsub_cis = newmatis->getsub_ris; 1433 } else { 1434 ISLocalToGlobalMapping cl2g; 1435 1436 /* communicate icol to their owners in the layout */ 1437 ierr = ISGetIndices(icol,&idxs);CHKERRQ(ierr); 1438 ierr = PetscLayoutMapLocal(mat->cmap,n,idxs,&ll,&lidxs,&lgidxs);CHKERRQ(ierr); 1439 ierr = ISRestoreIndices(icol,&idxs);CHKERRQ(ierr); 1440 ierr = PetscArrayzero(matis->csf_rootdata,matis->csf->nroots);CHKERRQ(ierr); 1441 for (i=0;i<ll;i++) matis->csf_rootdata[lidxs[i]] = lgidxs[i]+1; 1442 ierr = PetscFree(lidxs);CHKERRQ(ierr); 1443 ierr = PetscFree(lgidxs);CHKERRQ(ierr); 1444 ierr = PetscSFBcastBegin(matis->csf,MPIU_INT,matis->csf_rootdata,matis->csf_leafdata);CHKERRQ(ierr); 1445 ierr = PetscSFBcastEnd(matis->csf,MPIU_INT,matis->csf_rootdata,matis->csf_leafdata);CHKERRQ(ierr); 1446 for (i=0,newloc=0;i<matis->csf->nleaves;i++) if (matis->csf_leafdata[i]) newloc++; 1447 ierr = PetscMalloc1(newloc,&newgidxs);CHKERRQ(ierr); 1448 ierr = PetscMalloc1(newloc,&lidxs);CHKERRQ(ierr); 1449 for (i=0,newloc=0;i<matis->csf->nleaves;i++) 1450 if (matis->csf_leafdata[i]) { 1451 lidxs[newloc] = i; 1452 newgidxs[newloc++] = matis->csf_leafdata[i]-1; 1453 } 1454 ierr = ISCreateGeneral(comm,newloc,newgidxs,PETSC_OWN_POINTER,&is);CHKERRQ(ierr); 1455 ierr = ISLocalToGlobalMappingCreateIS(is,&cl2g);CHKERRQ(ierr); 1456 ierr = ISLocalToGlobalMappingSetBlockSize(cl2g,cbs);CHKERRQ(ierr); 1457 ierr = ISDestroy(&is);CHKERRQ(ierr); 1458 /* local is to extract local submatrix */ 1459 ierr = ISCreateGeneral(comm,newloc,lidxs,PETSC_OWN_POINTER,&newmatis->getsub_cis);CHKERRQ(ierr); 1460 ierr = MatSetLocalToGlobalMapping(*newmat,rl2g,cl2g);CHKERRQ(ierr); 1461 ierr = ISLocalToGlobalMappingDestroy(&cl2g);CHKERRQ(ierr); 1462 } 1463 ierr = ISLocalToGlobalMappingDestroy(&rl2g);CHKERRQ(ierr); 1464 } else { 1465 ierr = MatISGetLocalMat(*newmat,&newlocmat);CHKERRQ(ierr); 1466 } 1467 ierr = MatISGetLocalMat(mat,&locmat);CHKERRQ(ierr); 1468 newmatis = (Mat_IS*)(*newmat)->data; 1469 ierr = MatCreateSubMatrix(locmat,newmatis->getsub_ris,newmatis->getsub_cis,scall,&newlocmat);CHKERRQ(ierr); 1470 if (scall == MAT_INITIAL_MATRIX) { 1471 ierr = MatISSetLocalMat(*newmat,newlocmat);CHKERRQ(ierr); 1472 ierr = MatDestroy(&newlocmat);CHKERRQ(ierr); 1473 } 1474 ierr = MatAssemblyBegin(*newmat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 1475 ierr = MatAssemblyEnd(*newmat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 1476 PetscFunctionReturn(0); 1477 } 1478 1479 static PetscErrorCode MatCopy_IS(Mat A,Mat B,MatStructure str) 1480 { 1481 Mat_IS *a = (Mat_IS*)A->data,*b; 1482 PetscBool ismatis; 1483 PetscErrorCode ierr; 1484 1485 PetscFunctionBegin; 1486 ierr = PetscObjectTypeCompare((PetscObject)B,MATIS,&ismatis);CHKERRQ(ierr); 1487 if (!ismatis) SETERRQ(PetscObjectComm((PetscObject)B),PETSC_ERR_SUP,"Need to be implemented"); 1488 b = (Mat_IS*)B->data; 1489 ierr = MatCopy(a->A,b->A,str);CHKERRQ(ierr); 1490 ierr = PetscObjectStateIncrease((PetscObject)B);CHKERRQ(ierr); 1491 PetscFunctionReturn(0); 1492 } 1493 1494 static PetscErrorCode MatMissingDiagonal_IS(Mat A,PetscBool *missing,PetscInt *d) 1495 { 1496 Vec v; 1497 const PetscScalar *array; 1498 PetscInt i,n; 1499 PetscErrorCode ierr; 1500 1501 PetscFunctionBegin; 1502 *missing = PETSC_FALSE; 1503 ierr = MatCreateVecs(A,NULL,&v);CHKERRQ(ierr); 1504 ierr = MatGetDiagonal(A,v);CHKERRQ(ierr); 1505 ierr = VecGetLocalSize(v,&n);CHKERRQ(ierr); 1506 ierr = VecGetArrayRead(v,&array);CHKERRQ(ierr); 1507 for (i=0;i<n;i++) if (array[i] == 0.) break; 1508 ierr = VecRestoreArrayRead(v,&array);CHKERRQ(ierr); 1509 ierr = VecDestroy(&v);CHKERRQ(ierr); 1510 if (i != n) *missing = PETSC_TRUE; 1511 if (d) { 1512 *d = -1; 1513 if (*missing) { 1514 PetscInt rstart; 1515 ierr = MatGetOwnershipRange(A,&rstart,NULL);CHKERRQ(ierr); 1516 *d = i+rstart; 1517 } 1518 } 1519 PetscFunctionReturn(0); 1520 } 1521 1522 static PetscErrorCode MatISSetUpSF_IS(Mat B) 1523 { 1524 Mat_IS *matis = (Mat_IS*)(B->data); 1525 const PetscInt *gidxs; 1526 PetscInt nleaves; 1527 PetscErrorCode ierr; 1528 1529 PetscFunctionBegin; 1530 if (matis->sf) PetscFunctionReturn(0); 1531 ierr = PetscSFCreate(PetscObjectComm((PetscObject)B),&matis->sf);CHKERRQ(ierr); 1532 ierr = ISLocalToGlobalMappingGetIndices(B->rmap->mapping,&gidxs);CHKERRQ(ierr); 1533 ierr = ISLocalToGlobalMappingGetSize(B->rmap->mapping,&nleaves);CHKERRQ(ierr); 1534 ierr = PetscSFSetGraphLayout(matis->sf,B->rmap,nleaves,NULL,PETSC_OWN_POINTER,gidxs);CHKERRQ(ierr); 1535 ierr = ISLocalToGlobalMappingRestoreIndices(B->rmap->mapping,&gidxs);CHKERRQ(ierr); 1536 ierr = PetscMalloc2(matis->sf->nroots,&matis->sf_rootdata,matis->sf->nleaves,&matis->sf_leafdata);CHKERRQ(ierr); 1537 if (B->rmap->mapping != B->cmap->mapping) { /* setup SF for columns */ 1538 ierr = ISLocalToGlobalMappingGetSize(B->cmap->mapping,&nleaves);CHKERRQ(ierr); 1539 ierr = PetscSFCreate(PetscObjectComm((PetscObject)B),&matis->csf);CHKERRQ(ierr); 1540 ierr = ISLocalToGlobalMappingGetIndices(B->cmap->mapping,&gidxs);CHKERRQ(ierr); 1541 ierr = PetscSFSetGraphLayout(matis->csf,B->cmap,nleaves,NULL,PETSC_OWN_POINTER,gidxs);CHKERRQ(ierr); 1542 ierr = ISLocalToGlobalMappingRestoreIndices(B->cmap->mapping,&gidxs);CHKERRQ(ierr); 1543 ierr = PetscMalloc2(matis->csf->nroots,&matis->csf_rootdata,matis->csf->nleaves,&matis->csf_leafdata);CHKERRQ(ierr); 1544 } else { 1545 matis->csf = matis->sf; 1546 matis->csf_leafdata = matis->sf_leafdata; 1547 matis->csf_rootdata = matis->sf_rootdata; 1548 } 1549 PetscFunctionReturn(0); 1550 } 1551 1552 /*@ 1553 MatISStoreL2L - Store local-to-local operators during the Galerkin process of MatPtAP. 1554 1555 Collective 1556 1557 Input Parameters: 1558 + A - the matrix 1559 - store - the boolean flag 1560 1561 Level: advanced 1562 1563 Notes: 1564 1565 .seealso: MatCreate(), MatCreateIS(), MatISSetPreallocation(), MatPtAP() 1566 @*/ 1567 PetscErrorCode MatISStoreL2L(Mat A, PetscBool store) 1568 { 1569 PetscErrorCode ierr; 1570 1571 PetscFunctionBegin; 1572 PetscValidHeaderSpecific(A,MAT_CLASSID,1); 1573 PetscValidType(A,1); 1574 PetscValidLogicalCollectiveBool(A,store,2); 1575 ierr = PetscTryMethod(A,"MatISStoreL2L_C",(Mat,PetscBool),(A,store));CHKERRQ(ierr); 1576 PetscFunctionReturn(0); 1577 } 1578 1579 static PetscErrorCode MatISStoreL2L_IS(Mat A, PetscBool store) 1580 { 1581 Mat_IS *matis = (Mat_IS*)(A->data); 1582 PetscErrorCode ierr; 1583 1584 PetscFunctionBegin; 1585 matis->storel2l = store; 1586 if (!store) { 1587 ierr = PetscObjectCompose((PetscObject)(A),"_MatIS_PtAP_l2l",NULL);CHKERRQ(ierr); 1588 } 1589 PetscFunctionReturn(0); 1590 } 1591 1592 /*@ 1593 MatISFixLocalEmpty - Compress out zero local rows from the local matrices 1594 1595 Collective 1596 1597 Input Parameters: 1598 + A - the matrix 1599 - fix - the boolean flag 1600 1601 Level: advanced 1602 1603 Notes: When fix is true, new local matrices and l2g maps are generated during the final assembly process. 1604 1605 .seealso: MatCreate(), MatCreateIS(), MatISSetPreallocation(), MatAssemblyEnd(), MAT_FINAL_ASSEMBLY 1606 @*/ 1607 PetscErrorCode MatISFixLocalEmpty(Mat A, PetscBool fix) 1608 { 1609 PetscErrorCode ierr; 1610 1611 PetscFunctionBegin; 1612 PetscValidHeaderSpecific(A,MAT_CLASSID,1); 1613 PetscValidType(A,1); 1614 PetscValidLogicalCollectiveBool(A,fix,2); 1615 ierr = PetscTryMethod(A,"MatISFixLocalEmpty_C",(Mat,PetscBool),(A,fix));CHKERRQ(ierr); 1616 PetscFunctionReturn(0); 1617 } 1618 1619 static PetscErrorCode MatISFixLocalEmpty_IS(Mat A, PetscBool fix) 1620 { 1621 Mat_IS *matis = (Mat_IS*)(A->data); 1622 1623 PetscFunctionBegin; 1624 matis->locempty = fix; 1625 PetscFunctionReturn(0); 1626 } 1627 1628 /*@ 1629 MatISSetPreallocation - Preallocates memory for a MATIS parallel matrix. 1630 1631 Collective 1632 1633 Input Parameters: 1634 + B - the matrix 1635 . d_nz - number of nonzeros per row in DIAGONAL portion of local submatrix 1636 (same value is used for all local rows) 1637 . d_nnz - array containing the number of nonzeros in the various rows of the 1638 DIAGONAL portion of the local submatrix (possibly different for each row) 1639 or NULL, if d_nz is used to specify the nonzero structure. 1640 The size of this array is equal to the number of local rows, i.e 'm'. 1641 For matrices that will be factored, you must leave room for (and set) 1642 the diagonal entry even if it is zero. 1643 . o_nz - number of nonzeros per row in the OFF-DIAGONAL portion of local 1644 submatrix (same value is used for all local rows). 1645 - o_nnz - array containing the number of nonzeros in the various rows of the 1646 OFF-DIAGONAL portion of the local submatrix (possibly different for 1647 each row) or NULL, if o_nz is used to specify the nonzero 1648 structure. The size of this array is equal to the number 1649 of local rows, i.e 'm'. 1650 1651 If the *_nnz parameter is given then the *_nz parameter is ignored 1652 1653 Level: intermediate 1654 1655 Notes: 1656 This function has the same interface as the MPIAIJ preallocation routine in order to simplify the transition 1657 from the asssembled format to the unassembled one. It overestimates the preallocation of MATIS local 1658 matrices; for exact preallocation, the user should set the preallocation directly on local matrix objects. 1659 1660 .seealso: MatCreate(), MatCreateIS(), MatMPIAIJSetPreallocation(), MatISGetLocalMat(), MATIS 1661 @*/ 1662 PetscErrorCode MatISSetPreallocation(Mat B,PetscInt d_nz,const PetscInt d_nnz[],PetscInt o_nz,const PetscInt o_nnz[]) 1663 { 1664 PetscErrorCode ierr; 1665 1666 PetscFunctionBegin; 1667 PetscValidHeaderSpecific(B,MAT_CLASSID,1); 1668 PetscValidType(B,1); 1669 ierr = PetscTryMethod(B,"MatISSetPreallocation_C",(Mat,PetscInt,const PetscInt[],PetscInt,const PetscInt[]),(B,d_nz,d_nnz,o_nz,o_nnz));CHKERRQ(ierr); 1670 PetscFunctionReturn(0); 1671 } 1672 1673 /* this is used by DMDA */ 1674 PETSC_EXTERN PetscErrorCode MatISSetPreallocation_IS(Mat B,PetscInt d_nz,const PetscInt d_nnz[],PetscInt o_nz,const PetscInt o_nnz[]) 1675 { 1676 Mat_IS *matis = (Mat_IS*)(B->data); 1677 PetscInt bs,i,nlocalcols; 1678 PetscErrorCode ierr; 1679 1680 PetscFunctionBegin; 1681 if (!matis->A) SETERRQ(PetscObjectComm((PetscObject)B),PETSC_ERR_SUP,"You should first call MatSetLocalToGlobalMapping"); 1682 1683 if (!d_nnz) for (i=0;i<matis->sf->nroots;i++) matis->sf_rootdata[i] = d_nz; 1684 else for (i=0;i<matis->sf->nroots;i++) matis->sf_rootdata[i] = d_nnz[i]; 1685 1686 if (!o_nnz) for (i=0;i<matis->sf->nroots;i++) matis->sf_rootdata[i] += o_nz; 1687 else for (i=0;i<matis->sf->nroots;i++) matis->sf_rootdata[i] += o_nnz[i]; 1688 1689 ierr = PetscSFBcastBegin(matis->sf,MPIU_INT,matis->sf_rootdata,matis->sf_leafdata);CHKERRQ(ierr); 1690 ierr = MatGetSize(matis->A,NULL,&nlocalcols);CHKERRQ(ierr); 1691 ierr = MatGetBlockSize(matis->A,&bs);CHKERRQ(ierr); 1692 ierr = PetscSFBcastEnd(matis->sf,MPIU_INT,matis->sf_rootdata,matis->sf_leafdata);CHKERRQ(ierr); 1693 1694 for (i=0;i<matis->sf->nleaves;i++) matis->sf_leafdata[i] = PetscMin(matis->sf_leafdata[i],nlocalcols); 1695 ierr = MatSeqAIJSetPreallocation(matis->A,0,matis->sf_leafdata);CHKERRQ(ierr); 1696 #if defined(PETSC_HAVE_HYPRE) 1697 ierr = MatHYPRESetPreallocation(matis->A,0,matis->sf_leafdata,0,NULL);CHKERRQ(ierr); 1698 #endif 1699 1700 for (i=0;i<matis->sf->nleaves/bs;i++) matis->sf_leafdata[i] = matis->sf_leafdata[i*bs]/bs; 1701 ierr = MatSeqBAIJSetPreallocation(matis->A,bs,0,matis->sf_leafdata);CHKERRQ(ierr); 1702 1703 nlocalcols /= bs; 1704 for (i=0;i<matis->sf->nleaves/bs;i++) matis->sf_leafdata[i] = PetscMin(matis->sf_leafdata[i],nlocalcols - i); 1705 ierr = MatSeqSBAIJSetPreallocation(matis->A,bs,0,matis->sf_leafdata);CHKERRQ(ierr); 1706 1707 /* for other matrix types */ 1708 ierr = MatSetUp(matis->A);CHKERRQ(ierr); 1709 PetscFunctionReturn(0); 1710 } 1711 1712 PETSC_EXTERN PetscErrorCode MatISSetMPIXAIJPreallocation_Private(Mat A, Mat B, PetscBool maxreduce) 1713 { 1714 Mat_IS *matis = (Mat_IS*)(A->data); 1715 PetscInt *my_dnz,*my_onz,*dnz,*onz,*mat_ranges,*row_ownership; 1716 const PetscInt *global_indices_r,*global_indices_c; 1717 PetscInt i,j,bs,rows,cols; 1718 PetscInt lrows,lcols; 1719 PetscInt local_rows,local_cols; 1720 PetscMPIInt size; 1721 PetscBool isdense,issbaij; 1722 PetscErrorCode ierr; 1723 1724 PetscFunctionBegin; 1725 ierr = MPI_Comm_size(PetscObjectComm((PetscObject)A),&size);CHKERRQ(ierr); 1726 ierr = MatGetSize(A,&rows,&cols);CHKERRQ(ierr); 1727 ierr = MatGetBlockSize(A,&bs);CHKERRQ(ierr); 1728 ierr = MatGetSize(matis->A,&local_rows,&local_cols);CHKERRQ(ierr); 1729 ierr = PetscObjectBaseTypeCompare((PetscObject)matis->A,MATSEQDENSE,&isdense);CHKERRQ(ierr); 1730 ierr = PetscObjectBaseTypeCompare((PetscObject)matis->A,MATSEQSBAIJ,&issbaij);CHKERRQ(ierr); 1731 ierr = ISLocalToGlobalMappingGetIndices(A->rmap->mapping,&global_indices_r);CHKERRQ(ierr); 1732 if (A->rmap->mapping != A->cmap->mapping) { 1733 ierr = ISLocalToGlobalMappingGetIndices(A->cmap->mapping,&global_indices_c);CHKERRQ(ierr); 1734 } else { 1735 global_indices_c = global_indices_r; 1736 } 1737 1738 if (issbaij) { 1739 ierr = MatGetRowUpperTriangular(matis->A);CHKERRQ(ierr); 1740 } 1741 /* 1742 An SF reduce is needed to sum up properly on shared rows. 1743 Note that generally preallocation is not exact, since it overestimates nonzeros 1744 */ 1745 ierr = MatGetLocalSize(A,&lrows,&lcols);CHKERRQ(ierr); 1746 ierr = MatPreallocateInitialize(PetscObjectComm((PetscObject)A),lrows,lcols,dnz,onz);CHKERRQ(ierr); 1747 /* All processes need to compute entire row ownership */ 1748 ierr = PetscMalloc1(rows,&row_ownership);CHKERRQ(ierr); 1749 ierr = MatGetOwnershipRanges(A,(const PetscInt**)&mat_ranges);CHKERRQ(ierr); 1750 for (i=0;i<size;i++) { 1751 for (j=mat_ranges[i];j<mat_ranges[i+1];j++) { 1752 row_ownership[j] = i; 1753 } 1754 } 1755 ierr = MatGetOwnershipRangesColumn(A,(const PetscInt**)&mat_ranges);CHKERRQ(ierr); 1756 1757 /* 1758 my_dnz and my_onz contains exact contribution to preallocation from each local mat 1759 then, they will be summed up properly. This way, preallocation is always sufficient 1760 */ 1761 ierr = PetscCalloc2(local_rows,&my_dnz,local_rows,&my_onz);CHKERRQ(ierr); 1762 /* preallocation as a MATAIJ */ 1763 if (isdense) { /* special case for dense local matrices */ 1764 for (i=0;i<local_rows;i++) { 1765 PetscInt owner = row_ownership[global_indices_r[i]]; 1766 for (j=0;j<local_cols;j++) { 1767 PetscInt index_col = global_indices_c[j]; 1768 if (index_col > mat_ranges[owner]-1 && index_col < mat_ranges[owner+1]) { /* diag block */ 1769 my_dnz[i] += 1; 1770 } else { /* offdiag block */ 1771 my_onz[i] += 1; 1772 } 1773 } 1774 } 1775 } else if (matis->A->ops->getrowij) { 1776 const PetscInt *ii,*jj,*jptr; 1777 PetscBool done; 1778 ierr = MatGetRowIJ(matis->A,0,PETSC_FALSE,PETSC_FALSE,&local_rows,&ii,&jj,&done);CHKERRQ(ierr); 1779 if (!done) SETERRQ(PetscObjectComm((PetscObject)(matis->A)),PETSC_ERR_PLIB,"Error in MatGetRowIJ"); 1780 jptr = jj; 1781 for (i=0;i<local_rows;i++) { 1782 PetscInt index_row = global_indices_r[i]; 1783 for (j=0;j<ii[i+1]-ii[i];j++,jptr++) { 1784 PetscInt owner = row_ownership[index_row]; 1785 PetscInt index_col = global_indices_c[*jptr]; 1786 if (index_col > mat_ranges[owner]-1 && index_col < mat_ranges[owner+1] ) { /* diag block */ 1787 my_dnz[i] += 1; 1788 } else { /* offdiag block */ 1789 my_onz[i] += 1; 1790 } 1791 /* same as before, interchanging rows and cols */ 1792 if (issbaij && index_col != index_row) { 1793 owner = row_ownership[index_col]; 1794 if (index_row > mat_ranges[owner]-1 && index_row < mat_ranges[owner+1] ) { 1795 my_dnz[*jptr] += 1; 1796 } else { 1797 my_onz[*jptr] += 1; 1798 } 1799 } 1800 } 1801 } 1802 ierr = MatRestoreRowIJ(matis->A,0,PETSC_FALSE,PETSC_FALSE,&local_rows,&ii,&jj,&done);CHKERRQ(ierr); 1803 if (!done) SETERRQ(PetscObjectComm((PetscObject)(matis->A)),PETSC_ERR_PLIB,"Error in MatRestoreRowIJ"); 1804 } else { /* loop over rows and use MatGetRow */ 1805 for (i=0;i<local_rows;i++) { 1806 const PetscInt *cols; 1807 PetscInt ncols,index_row = global_indices_r[i]; 1808 ierr = MatGetRow(matis->A,i,&ncols,&cols,NULL);CHKERRQ(ierr); 1809 for (j=0;j<ncols;j++) { 1810 PetscInt owner = row_ownership[index_row]; 1811 PetscInt index_col = global_indices_c[cols[j]]; 1812 if (index_col > mat_ranges[owner]-1 && index_col < mat_ranges[owner+1] ) { /* diag block */ 1813 my_dnz[i] += 1; 1814 } else { /* offdiag block */ 1815 my_onz[i] += 1; 1816 } 1817 /* same as before, interchanging rows and cols */ 1818 if (issbaij && index_col != index_row) { 1819 owner = row_ownership[index_col]; 1820 if (index_row > mat_ranges[owner]-1 && index_row < mat_ranges[owner+1] ) { 1821 my_dnz[cols[j]] += 1; 1822 } else { 1823 my_onz[cols[j]] += 1; 1824 } 1825 } 1826 } 1827 ierr = MatRestoreRow(matis->A,i,&ncols,&cols,NULL);CHKERRQ(ierr); 1828 } 1829 } 1830 if (global_indices_c != global_indices_r) { 1831 ierr = ISLocalToGlobalMappingRestoreIndices(A->cmap->mapping,&global_indices_c);CHKERRQ(ierr); 1832 } 1833 ierr = ISLocalToGlobalMappingRestoreIndices(A->rmap->mapping,&global_indices_r);CHKERRQ(ierr); 1834 ierr = PetscFree(row_ownership);CHKERRQ(ierr); 1835 1836 /* Reduce my_dnz and my_onz */ 1837 if (maxreduce) { 1838 ierr = PetscSFReduceBegin(matis->sf,MPIU_INT,my_dnz,dnz,MPI_MAX);CHKERRQ(ierr); 1839 ierr = PetscSFReduceBegin(matis->sf,MPIU_INT,my_onz,onz,MPI_MAX);CHKERRQ(ierr); 1840 ierr = PetscSFReduceEnd(matis->sf,MPIU_INT,my_dnz,dnz,MPI_MAX);CHKERRQ(ierr); 1841 ierr = PetscSFReduceEnd(matis->sf,MPIU_INT,my_onz,onz,MPI_MAX);CHKERRQ(ierr); 1842 } else { 1843 ierr = PetscSFReduceBegin(matis->sf,MPIU_INT,my_dnz,dnz,MPI_SUM);CHKERRQ(ierr); 1844 ierr = PetscSFReduceBegin(matis->sf,MPIU_INT,my_onz,onz,MPI_SUM);CHKERRQ(ierr); 1845 ierr = PetscSFReduceEnd(matis->sf,MPIU_INT,my_dnz,dnz,MPI_SUM);CHKERRQ(ierr); 1846 ierr = PetscSFReduceEnd(matis->sf,MPIU_INT,my_onz,onz,MPI_SUM);CHKERRQ(ierr); 1847 } 1848 ierr = PetscFree2(my_dnz,my_onz);CHKERRQ(ierr); 1849 1850 /* Resize preallocation if overestimated */ 1851 for (i=0;i<lrows;i++) { 1852 dnz[i] = PetscMin(dnz[i],lcols); 1853 onz[i] = PetscMin(onz[i],cols-lcols); 1854 } 1855 1856 /* Set preallocation */ 1857 ierr = MatSeqAIJSetPreallocation(B,0,dnz);CHKERRQ(ierr); 1858 ierr = MatMPIAIJSetPreallocation(B,0,dnz,0,onz);CHKERRQ(ierr); 1859 for (i=0;i<lrows;i+=bs) { 1860 PetscInt b, d = dnz[i],o = onz[i]; 1861 1862 for (b=1;b<bs;b++) { 1863 d = PetscMax(d,dnz[i+b]); 1864 o = PetscMax(o,onz[i+b]); 1865 } 1866 dnz[i/bs] = PetscMin(d/bs + d%bs,lcols/bs); 1867 onz[i/bs] = PetscMin(o/bs + o%bs,(cols-lcols)/bs); 1868 } 1869 ierr = MatSeqBAIJSetPreallocation(B,bs,0,dnz);CHKERRQ(ierr); 1870 ierr = MatMPIBAIJSetPreallocation(B,bs,0,dnz,0,onz);CHKERRQ(ierr); 1871 ierr = MatMPISBAIJSetPreallocation(B,bs,0,dnz,0,onz);CHKERRQ(ierr); 1872 ierr = MatPreallocateFinalize(dnz,onz);CHKERRQ(ierr); 1873 if (issbaij) { 1874 ierr = MatRestoreRowUpperTriangular(matis->A);CHKERRQ(ierr); 1875 } 1876 ierr = MatSetOption(B,MAT_NEW_NONZERO_ALLOCATION_ERR,PETSC_TRUE);CHKERRQ(ierr); 1877 PetscFunctionReturn(0); 1878 } 1879 1880 PETSC_INTERN PetscErrorCode MatConvert_IS_XAIJ(Mat mat, MatType mtype, MatReuse reuse, Mat *M) 1881 { 1882 Mat_IS *matis = (Mat_IS*)(mat->data); 1883 Mat local_mat,MT; 1884 PetscInt rbs,cbs,rows,cols,lrows,lcols; 1885 PetscInt local_rows,local_cols; 1886 PetscBool isseqdense,isseqsbaij,isseqaij,isseqbaij; 1887 #if defined (PETSC_USE_DEBUG) 1888 PetscBool lb[4],bb[4]; 1889 #endif 1890 PetscMPIInt size; 1891 const PetscScalar *array; 1892 PetscErrorCode ierr; 1893 1894 PetscFunctionBegin; 1895 ierr = MPI_Comm_size(PetscObjectComm((PetscObject)mat),&size);CHKERRQ(ierr); 1896 if (size == 1 && mat->rmap->N == matis->A->rmap->N && mat->cmap->N == matis->A->cmap->N) { 1897 Mat B; 1898 IS irows = NULL,icols = NULL; 1899 PetscInt rbs,cbs; 1900 1901 ierr = ISLocalToGlobalMappingGetBlockSize(mat->rmap->mapping,&rbs);CHKERRQ(ierr); 1902 ierr = ISLocalToGlobalMappingGetBlockSize(mat->cmap->mapping,&cbs);CHKERRQ(ierr); 1903 if (reuse != MAT_REUSE_MATRIX) { /* check if l2g maps are one-to-one */ 1904 IS rows,cols; 1905 const PetscInt *ridxs,*cidxs; 1906 PetscInt i,nw,*work; 1907 1908 ierr = ISLocalToGlobalMappingGetBlockIndices(mat->rmap->mapping,&ridxs);CHKERRQ(ierr); 1909 ierr = ISLocalToGlobalMappingGetSize(mat->rmap->mapping,&nw);CHKERRQ(ierr); 1910 nw = nw/rbs; 1911 ierr = PetscCalloc1(nw,&work);CHKERRQ(ierr); 1912 for (i=0;i<nw;i++) work[ridxs[i]] += 1; 1913 for (i=0;i<nw;i++) if (!work[i] || work[i] > 1) break; 1914 if (i == nw) { 1915 ierr = ISCreateBlock(PETSC_COMM_SELF,rbs,nw,ridxs,PETSC_USE_POINTER,&rows);CHKERRQ(ierr); 1916 ierr = ISSetPermutation(rows);CHKERRQ(ierr); 1917 ierr = ISInvertPermutation(rows,PETSC_DECIDE,&irows);CHKERRQ(ierr); 1918 ierr = ISDestroy(&rows);CHKERRQ(ierr); 1919 } 1920 ierr = ISLocalToGlobalMappingRestoreBlockIndices(mat->rmap->mapping,&ridxs);CHKERRQ(ierr); 1921 ierr = PetscFree(work);CHKERRQ(ierr); 1922 if (irows && mat->rmap->mapping != mat->cmap->mapping) { 1923 ierr = ISLocalToGlobalMappingGetBlockIndices(mat->cmap->mapping,&cidxs);CHKERRQ(ierr); 1924 ierr = ISLocalToGlobalMappingGetSize(mat->cmap->mapping,&nw);CHKERRQ(ierr); 1925 nw = nw/cbs; 1926 ierr = PetscCalloc1(nw,&work);CHKERRQ(ierr); 1927 for (i=0;i<nw;i++) work[cidxs[i]] += 1; 1928 for (i=0;i<nw;i++) if (!work[i] || work[i] > 1) break; 1929 if (i == nw) { 1930 ierr = ISCreateBlock(PETSC_COMM_SELF,cbs,nw,cidxs,PETSC_USE_POINTER,&cols);CHKERRQ(ierr); 1931 ierr = ISSetPermutation(cols);CHKERRQ(ierr); 1932 ierr = ISInvertPermutation(cols,PETSC_DECIDE,&icols);CHKERRQ(ierr); 1933 ierr = ISDestroy(&cols);CHKERRQ(ierr); 1934 } 1935 ierr = ISLocalToGlobalMappingRestoreBlockIndices(mat->cmap->mapping,&cidxs);CHKERRQ(ierr); 1936 ierr = PetscFree(work);CHKERRQ(ierr); 1937 } else if (irows) { 1938 ierr = PetscObjectReference((PetscObject)irows);CHKERRQ(ierr); 1939 icols = irows; 1940 } 1941 } else { 1942 ierr = PetscObjectQuery((PetscObject)(*M),"_MatIS_IS_XAIJ_irows",(PetscObject*)&irows);CHKERRQ(ierr); 1943 ierr = PetscObjectQuery((PetscObject)(*M),"_MatIS_IS_XAIJ_icols",(PetscObject*)&icols);CHKERRQ(ierr); 1944 if (irows) { ierr = PetscObjectReference((PetscObject)irows);CHKERRQ(ierr); } 1945 if (icols) { ierr = PetscObjectReference((PetscObject)icols);CHKERRQ(ierr); } 1946 } 1947 if (!irows || !icols) { 1948 ierr = ISDestroy(&icols);CHKERRQ(ierr); 1949 ierr = ISDestroy(&irows);CHKERRQ(ierr); 1950 goto general_assembly; 1951 } 1952 ierr = MatConvert(matis->A,mtype,MAT_INITIAL_MATRIX,&B);CHKERRQ(ierr); 1953 if (reuse != MAT_INPLACE_MATRIX) { 1954 ierr = MatCreateSubMatrix(B,irows,icols,reuse,M);CHKERRQ(ierr); 1955 ierr = PetscObjectCompose((PetscObject)(*M),"_MatIS_IS_XAIJ_irows",(PetscObject)irows);CHKERRQ(ierr); 1956 ierr = PetscObjectCompose((PetscObject)(*M),"_MatIS_IS_XAIJ_icols",(PetscObject)icols);CHKERRQ(ierr); 1957 } else { 1958 Mat C; 1959 1960 ierr = MatCreateSubMatrix(B,irows,icols,MAT_INITIAL_MATRIX,&C);CHKERRQ(ierr); 1961 ierr = MatHeaderReplace(mat,&C);CHKERRQ(ierr); 1962 } 1963 ierr = MatDestroy(&B);CHKERRQ(ierr); 1964 ierr = ISDestroy(&icols);CHKERRQ(ierr); 1965 ierr = ISDestroy(&irows);CHKERRQ(ierr); 1966 PetscFunctionReturn(0); 1967 } 1968 general_assembly: 1969 ierr = MatGetSize(mat,&rows,&cols);CHKERRQ(ierr); 1970 ierr = ISLocalToGlobalMappingGetBlockSize(mat->rmap->mapping,&rbs);CHKERRQ(ierr); 1971 ierr = ISLocalToGlobalMappingGetBlockSize(mat->cmap->mapping,&cbs);CHKERRQ(ierr); 1972 ierr = MatGetLocalSize(mat,&lrows,&lcols);CHKERRQ(ierr); 1973 ierr = MatGetSize(matis->A,&local_rows,&local_cols);CHKERRQ(ierr); 1974 ierr = PetscObjectBaseTypeCompare((PetscObject)matis->A,MATSEQDENSE,&isseqdense);CHKERRQ(ierr); 1975 ierr = PetscObjectBaseTypeCompare((PetscObject)matis->A,MATSEQAIJ,&isseqaij);CHKERRQ(ierr); 1976 ierr = PetscObjectBaseTypeCompare((PetscObject)matis->A,MATSEQBAIJ,&isseqbaij);CHKERRQ(ierr); 1977 ierr = PetscObjectBaseTypeCompare((PetscObject)matis->A,MATSEQSBAIJ,&isseqsbaij);CHKERRQ(ierr); 1978 if (!isseqdense && !isseqaij && !isseqbaij && !isseqsbaij) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_SUP,"Not for matrix type %s",((PetscObject)(matis->A))->type_name); 1979 #if defined (PETSC_USE_DEBUG) 1980 lb[0] = isseqdense; 1981 lb[1] = isseqaij; 1982 lb[2] = isseqbaij; 1983 lb[3] = isseqsbaij; 1984 ierr = MPIU_Allreduce(lb,bb,4,MPIU_BOOL,MPI_LAND,PetscObjectComm((PetscObject)mat));CHKERRQ(ierr); 1985 if (!bb[0] && !bb[1] && !bb[2] && !bb[3]) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Local matrices must have the same type"); 1986 #endif 1987 1988 if (reuse != MAT_REUSE_MATRIX) { 1989 ierr = MatCreate(PetscObjectComm((PetscObject)mat),&MT);CHKERRQ(ierr); 1990 ierr = MatSetSizes(MT,lrows,lcols,rows,cols);CHKERRQ(ierr); 1991 ierr = MatSetType(MT,mtype);CHKERRQ(ierr); 1992 ierr = MatSetBlockSizes(MT,rbs,cbs);CHKERRQ(ierr); 1993 ierr = MatISSetMPIXAIJPreallocation_Private(mat,MT,PETSC_FALSE);CHKERRQ(ierr); 1994 } else { 1995 PetscInt mrbs,mcbs,mrows,mcols,mlrows,mlcols; 1996 1997 /* some checks */ 1998 MT = *M; 1999 ierr = MatGetBlockSizes(MT,&mrbs,&mcbs);CHKERRQ(ierr); 2000 ierr = MatGetSize(MT,&mrows,&mcols);CHKERRQ(ierr); 2001 ierr = MatGetLocalSize(MT,&mlrows,&mlcols);CHKERRQ(ierr); 2002 if (mrows != rows) SETERRQ2(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse matrix. Wrong number of rows (%d != %d)",rows,mrows); 2003 if (mcols != cols) SETERRQ2(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse matrix. Wrong number of cols (%d != %d)",cols,mcols); 2004 if (mlrows != lrows) SETERRQ2(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse matrix. Wrong number of local rows (%d != %d)",lrows,mlrows); 2005 if (mlcols != lcols) SETERRQ2(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse matrix. Wrong number of local cols (%d != %d)",lcols,mlcols); 2006 if (mrbs != rbs) SETERRQ2(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse matrix. Wrong row block size (%d != %d)",rbs,mrbs); 2007 if (mcbs != cbs) SETERRQ2(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse matrix. Wrong col block size (%d != %d)",cbs,mcbs); 2008 ierr = MatZeroEntries(MT);CHKERRQ(ierr); 2009 } 2010 2011 if (isseqsbaij || isseqbaij) { 2012 ierr = MatConvert(matis->A,MATSEQAIJ,MAT_INITIAL_MATRIX,&local_mat);CHKERRQ(ierr); 2013 isseqaij = PETSC_TRUE; 2014 } else { 2015 ierr = PetscObjectReference((PetscObject)matis->A);CHKERRQ(ierr); 2016 local_mat = matis->A; 2017 } 2018 2019 /* Set values */ 2020 ierr = MatSetLocalToGlobalMapping(MT,mat->rmap->mapping,mat->cmap->mapping);CHKERRQ(ierr); 2021 if (isseqdense) { /* special case for dense local matrices */ 2022 PetscInt i,*dummy; 2023 2024 ierr = PetscMalloc1(PetscMax(local_rows,local_cols),&dummy);CHKERRQ(ierr); 2025 for (i=0;i<PetscMax(local_rows,local_cols);i++) dummy[i] = i; 2026 ierr = MatSetOption(MT,MAT_ROW_ORIENTED,PETSC_FALSE);CHKERRQ(ierr); 2027 ierr = MatDenseGetArrayRead(local_mat,&array);CHKERRQ(ierr); 2028 ierr = MatSetValuesLocal(MT,local_rows,dummy,local_cols,dummy,array,ADD_VALUES);CHKERRQ(ierr); 2029 ierr = MatDenseRestoreArrayRead(local_mat,&array);CHKERRQ(ierr); 2030 ierr = PetscFree(dummy);CHKERRQ(ierr); 2031 } else if (isseqaij) { 2032 const PetscInt *blocks; 2033 PetscInt i,nvtxs,*xadj,*adjncy, nb; 2034 PetscBool done; 2035 PetscScalar *sarray; 2036 2037 ierr = MatGetRowIJ(local_mat,0,PETSC_FALSE,PETSC_FALSE,&nvtxs,(const PetscInt**)&xadj,(const PetscInt**)&adjncy,&done);CHKERRQ(ierr); 2038 if (!done) SETERRQ(PetscObjectComm((PetscObject)local_mat),PETSC_ERR_PLIB,"Error in MatGetRowIJ"); 2039 ierr = MatSeqAIJGetArray(local_mat,&sarray);CHKERRQ(ierr); 2040 ierr = MatGetVariableBlockSizes(local_mat,&nb,&blocks);CHKERRQ(ierr); 2041 if (nb) { /* speed up assembly for special blocked matrices (used by BDDC) */ 2042 PetscInt sum; 2043 2044 for (i=0,sum=0;i<nb;i++) sum += blocks[i]; 2045 if (sum == nvtxs) { 2046 PetscInt r; 2047 2048 for (i=0,r=0;i<nb;i++) { 2049 #if defined(PETSC_USE_DEBUG) 2050 if (blocks[i] != xadj[r+1] - xadj[r]) SETERRQ3(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Invalid block sizes prescribed for block %D: expected %D, got %D",i,blocks[i],xadj[r+1] - xadj[r]); 2051 #endif 2052 ierr = MatSetValuesLocal(MT,blocks[i],adjncy+xadj[r],blocks[i],adjncy+xadj[r],sarray+xadj[r],ADD_VALUES);CHKERRQ(ierr); 2053 r += blocks[i]; 2054 } 2055 } else { 2056 for (i=0;i<nvtxs;i++) { 2057 ierr = MatSetValuesLocal(MT,1,&i,xadj[i+1]-xadj[i],adjncy+xadj[i],sarray+xadj[i],ADD_VALUES);CHKERRQ(ierr); 2058 } 2059 } 2060 } else { 2061 for (i=0;i<nvtxs;i++) { 2062 ierr = MatSetValuesLocal(MT,1,&i,xadj[i+1]-xadj[i],adjncy+xadj[i],sarray+xadj[i],ADD_VALUES);CHKERRQ(ierr); 2063 } 2064 } 2065 ierr = MatRestoreRowIJ(local_mat,0,PETSC_FALSE,PETSC_FALSE,&nvtxs,(const PetscInt**)&xadj,(const PetscInt**)&adjncy,&done);CHKERRQ(ierr); 2066 if (!done) SETERRQ(PetscObjectComm((PetscObject)local_mat),PETSC_ERR_PLIB,"Error in MatRestoreRowIJ"); 2067 ierr = MatSeqAIJRestoreArray(local_mat,&sarray);CHKERRQ(ierr); 2068 } else { /* very basic values insertion for all other matrix types */ 2069 PetscInt i; 2070 2071 for (i=0;i<local_rows;i++) { 2072 PetscInt j; 2073 const PetscInt *local_indices_cols; 2074 2075 ierr = MatGetRow(local_mat,i,&j,&local_indices_cols,&array);CHKERRQ(ierr); 2076 ierr = MatSetValuesLocal(MT,1,&i,j,local_indices_cols,array,ADD_VALUES);CHKERRQ(ierr); 2077 ierr = MatRestoreRow(local_mat,i,&j,&local_indices_cols,&array);CHKERRQ(ierr); 2078 } 2079 } 2080 ierr = MatAssemblyBegin(MT,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 2081 ierr = MatDestroy(&local_mat);CHKERRQ(ierr); 2082 ierr = MatAssemblyEnd(MT,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 2083 if (isseqdense) { 2084 ierr = MatSetOption(MT,MAT_ROW_ORIENTED,PETSC_TRUE);CHKERRQ(ierr); 2085 } 2086 if (reuse == MAT_INPLACE_MATRIX) { 2087 ierr = MatHeaderReplace(mat,&MT);CHKERRQ(ierr); 2088 } else if (reuse == MAT_INITIAL_MATRIX) { 2089 *M = MT; 2090 } 2091 PetscFunctionReturn(0); 2092 } 2093 2094 /*@ 2095 MatISGetMPIXAIJ - Converts MATIS matrix into a parallel AIJ format 2096 2097 Input Parameter: 2098 + mat - the matrix (should be of type MATIS) 2099 - reuse - either MAT_INITIAL_MATRIX or MAT_REUSE_MATRIX 2100 2101 Output Parameter: 2102 . newmat - the matrix in AIJ format 2103 2104 Level: developer 2105 2106 Notes: 2107 This function has been deprecated and it will be removed in future releases. Update your code to use the MatConvert() interface. 2108 2109 .seealso: MATIS, MatConvert() 2110 @*/ 2111 PetscErrorCode MatISGetMPIXAIJ(Mat mat, MatReuse reuse, Mat *newmat) 2112 { 2113 PetscErrorCode ierr; 2114 2115 PetscFunctionBegin; 2116 PetscValidHeaderSpecific(mat,MAT_CLASSID,1); 2117 PetscValidLogicalCollectiveEnum(mat,reuse,2); 2118 PetscValidPointer(newmat,3); 2119 if (reuse == MAT_REUSE_MATRIX) { 2120 PetscValidHeaderSpecific(*newmat,MAT_CLASSID,3); 2121 PetscCheckSameComm(mat,1,*newmat,3); 2122 if (mat == *newmat) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse the same matrix"); 2123 } 2124 ierr = PetscUseMethod(mat,"MatISGetMPIXAIJ_C",(Mat,MatType,MatReuse,Mat*),(mat,MATAIJ,reuse,newmat));CHKERRQ(ierr); 2125 PetscFunctionReturn(0); 2126 } 2127 2128 PetscErrorCode MatDuplicate_IS(Mat mat,MatDuplicateOption op,Mat *newmat) 2129 { 2130 PetscErrorCode ierr; 2131 Mat_IS *matis = (Mat_IS*)(mat->data); 2132 PetscInt rbs,cbs,m,n,M,N; 2133 Mat B,localmat; 2134 2135 PetscFunctionBegin; 2136 ierr = ISLocalToGlobalMappingGetBlockSize(mat->rmap->mapping,&rbs);CHKERRQ(ierr); 2137 ierr = ISLocalToGlobalMappingGetBlockSize(mat->cmap->mapping,&cbs);CHKERRQ(ierr); 2138 ierr = MatGetSize(mat,&M,&N);CHKERRQ(ierr); 2139 ierr = MatGetLocalSize(mat,&m,&n);CHKERRQ(ierr); 2140 ierr = MatCreate(PetscObjectComm((PetscObject)mat),&B);CHKERRQ(ierr); 2141 ierr = MatSetSizes(B,m,n,M,N);CHKERRQ(ierr); 2142 ierr = MatSetBlockSize(B,rbs == cbs ? rbs : 1);CHKERRQ(ierr); 2143 ierr = MatSetType(B,MATIS);CHKERRQ(ierr); 2144 ierr = MatISSetLocalMatType(B,matis->lmattype);CHKERRQ(ierr); 2145 ierr = MatSetLocalToGlobalMapping(B,mat->rmap->mapping,mat->cmap->mapping);CHKERRQ(ierr); 2146 ierr = MatDuplicate(matis->A,op,&localmat);CHKERRQ(ierr); 2147 ierr = MatISSetLocalMat(B,localmat);CHKERRQ(ierr); 2148 ierr = MatDestroy(&localmat);CHKERRQ(ierr); 2149 ierr = MatAssemblyBegin(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 2150 ierr = MatAssemblyEnd(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 2151 *newmat = B; 2152 PetscFunctionReturn(0); 2153 } 2154 2155 static PetscErrorCode MatIsHermitian_IS(Mat A,PetscReal tol,PetscBool *flg) 2156 { 2157 PetscErrorCode ierr; 2158 Mat_IS *matis = (Mat_IS*)A->data; 2159 PetscBool local_sym; 2160 2161 PetscFunctionBegin; 2162 ierr = MatIsHermitian(matis->A,tol,&local_sym);CHKERRQ(ierr); 2163 ierr = MPIU_Allreduce(&local_sym,flg,1,MPIU_BOOL,MPI_LAND,PetscObjectComm((PetscObject)A));CHKERRQ(ierr); 2164 PetscFunctionReturn(0); 2165 } 2166 2167 static PetscErrorCode MatIsSymmetric_IS(Mat A,PetscReal tol,PetscBool *flg) 2168 { 2169 PetscErrorCode ierr; 2170 Mat_IS *matis = (Mat_IS*)A->data; 2171 PetscBool local_sym; 2172 2173 PetscFunctionBegin; 2174 ierr = MatIsSymmetric(matis->A,tol,&local_sym);CHKERRQ(ierr); 2175 ierr = MPIU_Allreduce(&local_sym,flg,1,MPIU_BOOL,MPI_LAND,PetscObjectComm((PetscObject)A));CHKERRQ(ierr); 2176 PetscFunctionReturn(0); 2177 } 2178 2179 static PetscErrorCode MatIsStructurallySymmetric_IS(Mat A,PetscBool *flg) 2180 { 2181 PetscErrorCode ierr; 2182 Mat_IS *matis = (Mat_IS*)A->data; 2183 PetscBool local_sym; 2184 2185 PetscFunctionBegin; 2186 if (A->rmap->mapping != A->cmap->mapping) { 2187 *flg = PETSC_FALSE; 2188 PetscFunctionReturn(0); 2189 } 2190 ierr = MatIsStructurallySymmetric(matis->A,&local_sym);CHKERRQ(ierr); 2191 ierr = MPIU_Allreduce(&local_sym,flg,1,MPIU_BOOL,MPI_LAND,PetscObjectComm((PetscObject)A));CHKERRQ(ierr); 2192 PetscFunctionReturn(0); 2193 } 2194 2195 static PetscErrorCode MatDestroy_IS(Mat A) 2196 { 2197 PetscErrorCode ierr; 2198 Mat_IS *b = (Mat_IS*)A->data; 2199 2200 PetscFunctionBegin; 2201 ierr = PetscFree(b->bdiag);CHKERRQ(ierr); 2202 ierr = PetscFree(b->lmattype);CHKERRQ(ierr); 2203 ierr = MatDestroy(&b->A);CHKERRQ(ierr); 2204 ierr = VecScatterDestroy(&b->cctx);CHKERRQ(ierr); 2205 ierr = VecScatterDestroy(&b->rctx);CHKERRQ(ierr); 2206 ierr = VecDestroy(&b->x);CHKERRQ(ierr); 2207 ierr = VecDestroy(&b->y);CHKERRQ(ierr); 2208 ierr = VecDestroy(&b->counter);CHKERRQ(ierr); 2209 ierr = ISDestroy(&b->getsub_ris);CHKERRQ(ierr); 2210 ierr = ISDestroy(&b->getsub_cis);CHKERRQ(ierr); 2211 if (b->sf != b->csf) { 2212 ierr = PetscSFDestroy(&b->csf);CHKERRQ(ierr); 2213 ierr = PetscFree2(b->csf_rootdata,b->csf_leafdata);CHKERRQ(ierr); 2214 } else b->csf = NULL; 2215 ierr = PetscSFDestroy(&b->sf);CHKERRQ(ierr); 2216 ierr = PetscFree2(b->sf_rootdata,b->sf_leafdata);CHKERRQ(ierr); 2217 ierr = PetscFree(A->data);CHKERRQ(ierr); 2218 ierr = PetscObjectChangeTypeName((PetscObject)A,0);CHKERRQ(ierr); 2219 ierr = PetscObjectComposeFunction((PetscObject)A,"MatISSetLocalMatType_C",NULL);CHKERRQ(ierr); 2220 ierr = PetscObjectComposeFunction((PetscObject)A,"MatISGetLocalMat_C",NULL);CHKERRQ(ierr); 2221 ierr = PetscObjectComposeFunction((PetscObject)A,"MatISSetLocalMat_C",NULL);CHKERRQ(ierr); 2222 ierr = PetscObjectComposeFunction((PetscObject)A,"MatISGetMPIXAIJ_C",NULL);CHKERRQ(ierr); 2223 ierr = PetscObjectComposeFunction((PetscObject)A,"MatISSetPreallocation_C",NULL);CHKERRQ(ierr); 2224 ierr = PetscObjectComposeFunction((PetscObject)A,"MatISStoreL2L_C",NULL);CHKERRQ(ierr); 2225 ierr = PetscObjectComposeFunction((PetscObject)A,"MatISFixLocalEmpty_C",NULL);CHKERRQ(ierr); 2226 ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_is_mpiaij_C",NULL);CHKERRQ(ierr); 2227 ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_is_mpibaij_C",NULL);CHKERRQ(ierr); 2228 ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_is_mpisbaij_C",NULL);CHKERRQ(ierr); 2229 ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_is_seqaij_C",NULL);CHKERRQ(ierr); 2230 ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_is_seqbaij_C",NULL);CHKERRQ(ierr); 2231 ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_is_seqsbaij_C",NULL);CHKERRQ(ierr); 2232 ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_is_aij_C",NULL);CHKERRQ(ierr); 2233 PetscFunctionReturn(0); 2234 } 2235 2236 static PetscErrorCode MatMult_IS(Mat A,Vec x,Vec y) 2237 { 2238 PetscErrorCode ierr; 2239 Mat_IS *is = (Mat_IS*)A->data; 2240 PetscScalar zero = 0.0; 2241 2242 PetscFunctionBegin; 2243 /* scatter the global vector x into the local work vector */ 2244 ierr = VecScatterBegin(is->cctx,x,is->x,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 2245 ierr = VecScatterEnd(is->cctx,x,is->x,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 2246 2247 /* multiply the local matrix */ 2248 ierr = MatMult(is->A,is->x,is->y);CHKERRQ(ierr); 2249 2250 /* scatter product back into global memory */ 2251 ierr = VecSet(y,zero);CHKERRQ(ierr); 2252 ierr = VecScatterBegin(is->rctx,is->y,y,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 2253 ierr = VecScatterEnd(is->rctx,is->y,y,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 2254 PetscFunctionReturn(0); 2255 } 2256 2257 static PetscErrorCode MatMultAdd_IS(Mat A,Vec v1,Vec v2,Vec v3) 2258 { 2259 Vec temp_vec; 2260 PetscErrorCode ierr; 2261 2262 PetscFunctionBegin; /* v3 = v2 + A * v1.*/ 2263 if (v3 != v2) { 2264 ierr = MatMult(A,v1,v3);CHKERRQ(ierr); 2265 ierr = VecAXPY(v3,1.0,v2);CHKERRQ(ierr); 2266 } else { 2267 ierr = VecDuplicate(v2,&temp_vec);CHKERRQ(ierr); 2268 ierr = MatMult(A,v1,temp_vec);CHKERRQ(ierr); 2269 ierr = VecAXPY(temp_vec,1.0,v2);CHKERRQ(ierr); 2270 ierr = VecCopy(temp_vec,v3);CHKERRQ(ierr); 2271 ierr = VecDestroy(&temp_vec);CHKERRQ(ierr); 2272 } 2273 PetscFunctionReturn(0); 2274 } 2275 2276 static PetscErrorCode MatMultTranspose_IS(Mat A,Vec y,Vec x) 2277 { 2278 Mat_IS *is = (Mat_IS*)A->data; 2279 PetscErrorCode ierr; 2280 2281 PetscFunctionBegin; 2282 /* scatter the global vector x into the local work vector */ 2283 ierr = VecScatterBegin(is->rctx,y,is->y,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 2284 ierr = VecScatterEnd(is->rctx,y,is->y,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 2285 2286 /* multiply the local matrix */ 2287 ierr = MatMultTranspose(is->A,is->y,is->x);CHKERRQ(ierr); 2288 2289 /* scatter product back into global vector */ 2290 ierr = VecSet(x,0);CHKERRQ(ierr); 2291 ierr = VecScatterBegin(is->cctx,is->x,x,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 2292 ierr = VecScatterEnd(is->cctx,is->x,x,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 2293 PetscFunctionReturn(0); 2294 } 2295 2296 static PetscErrorCode MatMultTransposeAdd_IS(Mat A,Vec v1,Vec v2,Vec v3) 2297 { 2298 Vec temp_vec; 2299 PetscErrorCode ierr; 2300 2301 PetscFunctionBegin; /* v3 = v2 + A' * v1.*/ 2302 if (v3 != v2) { 2303 ierr = MatMultTranspose(A,v1,v3);CHKERRQ(ierr); 2304 ierr = VecAXPY(v3,1.0,v2);CHKERRQ(ierr); 2305 } else { 2306 ierr = VecDuplicate(v2,&temp_vec);CHKERRQ(ierr); 2307 ierr = MatMultTranspose(A,v1,temp_vec);CHKERRQ(ierr); 2308 ierr = VecAXPY(temp_vec,1.0,v2);CHKERRQ(ierr); 2309 ierr = VecCopy(temp_vec,v3);CHKERRQ(ierr); 2310 ierr = VecDestroy(&temp_vec);CHKERRQ(ierr); 2311 } 2312 PetscFunctionReturn(0); 2313 } 2314 2315 static PetscErrorCode MatView_IS(Mat A,PetscViewer viewer) 2316 { 2317 Mat_IS *a = (Mat_IS*)A->data; 2318 PetscErrorCode ierr; 2319 PetscViewer sviewer; 2320 PetscBool isascii,view = PETSC_TRUE; 2321 2322 PetscFunctionBegin; 2323 ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&isascii);CHKERRQ(ierr); 2324 if (isascii) { 2325 PetscViewerFormat format; 2326 2327 ierr = PetscViewerGetFormat(viewer,&format);CHKERRQ(ierr); 2328 if (format == PETSC_VIEWER_ASCII_INFO) view = PETSC_FALSE; 2329 } 2330 if (!view) PetscFunctionReturn(0); 2331 ierr = PetscViewerGetSubViewer(viewer,PETSC_COMM_SELF,&sviewer);CHKERRQ(ierr); 2332 ierr = MatView(a->A,sviewer);CHKERRQ(ierr); 2333 ierr = PetscViewerRestoreSubViewer(viewer,PETSC_COMM_SELF,&sviewer);CHKERRQ(ierr); 2334 ierr = PetscViewerFlush(viewer);CHKERRQ(ierr); 2335 PetscFunctionReturn(0); 2336 } 2337 2338 static PetscErrorCode MatInvertBlockDiagonal_IS(Mat mat,const PetscScalar **values) 2339 { 2340 Mat_IS *is = (Mat_IS*)mat->data; 2341 MPI_Datatype nodeType; 2342 const PetscScalar *lv; 2343 PetscInt bs; 2344 PetscErrorCode ierr; 2345 2346 PetscFunctionBegin; 2347 ierr = MatGetBlockSize(mat,&bs);CHKERRQ(ierr); 2348 ierr = MatSetBlockSize(is->A,bs);CHKERRQ(ierr); 2349 ierr = MatInvertBlockDiagonal(is->A,&lv);CHKERRQ(ierr); 2350 if (!is->bdiag) { 2351 ierr = PetscMalloc1(bs*mat->rmap->n,&is->bdiag);CHKERRQ(ierr); 2352 } 2353 ierr = MPI_Type_contiguous(bs,MPIU_SCALAR,&nodeType);CHKERRQ(ierr); 2354 ierr = MPI_Type_commit(&nodeType);CHKERRQ(ierr); 2355 ierr = PetscSFReduceBegin(is->sf,nodeType,lv,is->bdiag,MPIU_REPLACE);CHKERRQ(ierr); 2356 ierr = PetscSFReduceEnd(is->sf,nodeType,lv,is->bdiag,MPIU_REPLACE);CHKERRQ(ierr); 2357 ierr = MPI_Type_free(&nodeType);CHKERRQ(ierr); 2358 if (values) *values = is->bdiag; 2359 PetscFunctionReturn(0); 2360 } 2361 2362 static PetscErrorCode MatISSetUpScatters_Private(Mat A) 2363 { 2364 Vec cglobal,rglobal; 2365 IS from; 2366 Mat_IS *is = (Mat_IS*)A->data; 2367 PetscScalar sum; 2368 const PetscInt *garray; 2369 PetscInt nr,rbs,nc,cbs; 2370 PetscBool iscuda; 2371 PetscErrorCode ierr; 2372 2373 PetscFunctionBegin; 2374 ierr = ISLocalToGlobalMappingGetSize(A->rmap->mapping,&nr);CHKERRQ(ierr); 2375 ierr = ISLocalToGlobalMappingGetBlockSize(A->rmap->mapping,&rbs);CHKERRQ(ierr); 2376 ierr = ISLocalToGlobalMappingGetSize(A->cmap->mapping,&nc);CHKERRQ(ierr); 2377 ierr = ISLocalToGlobalMappingGetBlockSize(A->cmap->mapping,&cbs);CHKERRQ(ierr); 2378 ierr = VecDestroy(&is->x);CHKERRQ(ierr); 2379 ierr = VecDestroy(&is->y);CHKERRQ(ierr); 2380 ierr = VecDestroy(&is->counter);CHKERRQ(ierr); 2381 ierr = VecScatterDestroy(&is->rctx);CHKERRQ(ierr); 2382 ierr = VecScatterDestroy(&is->cctx);CHKERRQ(ierr); 2383 ierr = MatCreateVecs(is->A,&is->x,&is->y);CHKERRQ(ierr); 2384 ierr = VecBindToCPU(is->y,PETSC_TRUE);CHKERRQ(ierr); 2385 ierr = PetscObjectTypeCompare((PetscObject)is->y,VECSEQCUDA,&iscuda);CHKERRQ(ierr); 2386 if (iscuda) { 2387 ierr = PetscFree(A->defaultvectype);CHKERRQ(ierr); 2388 ierr = PetscStrallocpy(VECCUDA,&A->defaultvectype);CHKERRQ(ierr); 2389 } 2390 ierr = MatCreateVecs(A,&cglobal,&rglobal);CHKERRQ(ierr); 2391 ierr = VecBindToCPU(rglobal,PETSC_TRUE);CHKERRQ(ierr); 2392 ierr = ISLocalToGlobalMappingGetBlockIndices(A->rmap->mapping,&garray);CHKERRQ(ierr); 2393 ierr = ISCreateBlock(PetscObjectComm((PetscObject)A),rbs,nr/rbs,garray,PETSC_USE_POINTER,&from);CHKERRQ(ierr); 2394 ierr = VecScatterCreate(rglobal,from,is->y,NULL,&is->rctx);CHKERRQ(ierr); 2395 ierr = ISLocalToGlobalMappingRestoreBlockIndices(A->rmap->mapping,&garray);CHKERRQ(ierr); 2396 ierr = ISDestroy(&from);CHKERRQ(ierr); 2397 if (A->rmap->mapping != A->cmap->mapping) { 2398 ierr = ISLocalToGlobalMappingGetBlockIndices(A->cmap->mapping,&garray);CHKERRQ(ierr); 2399 ierr = ISCreateBlock(PetscObjectComm((PetscObject)A),cbs,nc/cbs,garray,PETSC_USE_POINTER,&from);CHKERRQ(ierr); 2400 ierr = VecScatterCreate(cglobal,from,is->x,NULL,&is->cctx);CHKERRQ(ierr); 2401 ierr = ISLocalToGlobalMappingRestoreBlockIndices(A->cmap->mapping,&garray);CHKERRQ(ierr); 2402 ierr = ISDestroy(&from);CHKERRQ(ierr); 2403 } else { 2404 ierr = PetscObjectReference((PetscObject)is->rctx);CHKERRQ(ierr); 2405 is->cctx = is->rctx; 2406 } 2407 ierr = VecDestroy(&cglobal);CHKERRQ(ierr); 2408 2409 /* interface counter vector (local) */ 2410 ierr = VecDuplicate(is->y,&is->counter);CHKERRQ(ierr); 2411 ierr = VecBindToCPU(is->counter,PETSC_TRUE);CHKERRQ(ierr); 2412 ierr = VecSet(is->y,1.);CHKERRQ(ierr); 2413 ierr = VecScatterBegin(is->rctx,is->y,rglobal,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 2414 ierr = VecScatterEnd(is->rctx,is->y,rglobal,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 2415 ierr = VecScatterBegin(is->rctx,rglobal,is->counter,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 2416 ierr = VecScatterEnd(is->rctx,rglobal,is->counter,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 2417 ierr = VecBindToCPU(is->y,PETSC_FALSE);CHKERRQ(ierr); 2418 ierr = VecBindToCPU(is->counter,PETSC_FALSE);CHKERRQ(ierr); 2419 2420 /* special functions for block-diagonal matrices */ 2421 ierr = VecSum(rglobal,&sum);CHKERRQ(ierr); 2422 if ((PetscInt)(PetscRealPart(sum)) == A->rmap->N && A->rmap->N == A->cmap->N && A->rmap->mapping == A->cmap->mapping) { 2423 A->ops->invertblockdiagonal = MatInvertBlockDiagonal_IS; 2424 } else { 2425 A->ops->invertblockdiagonal = NULL; 2426 } 2427 ierr = VecDestroy(&rglobal);CHKERRQ(ierr); 2428 2429 /* setup SF for general purpose shared indices based communications */ 2430 ierr = MatISSetUpSF_IS(A);CHKERRQ(ierr); 2431 PetscFunctionReturn(0); 2432 } 2433 2434 static PetscErrorCode MatSetLocalToGlobalMapping_IS(Mat A,ISLocalToGlobalMapping rmapping,ISLocalToGlobalMapping cmapping) 2435 { 2436 PetscErrorCode ierr; 2437 PetscInt nr,rbs,nc,cbs; 2438 Mat_IS *is = (Mat_IS*)A->data; 2439 2440 PetscFunctionBegin; 2441 PetscCheckSameComm(A,1,rmapping,2); 2442 PetscCheckSameComm(A,1,cmapping,3); 2443 ierr = MatDestroy(&is->A);CHKERRQ(ierr); 2444 if (is->csf != is->sf) { 2445 ierr = PetscSFDestroy(&is->csf);CHKERRQ(ierr); 2446 ierr = PetscFree2(is->csf_rootdata,is->csf_leafdata);CHKERRQ(ierr); 2447 } else is->csf = NULL; 2448 ierr = PetscSFDestroy(&is->sf);CHKERRQ(ierr); 2449 ierr = PetscFree2(is->sf_rootdata,is->sf_leafdata);CHKERRQ(ierr); 2450 ierr = PetscFree(is->bdiag);CHKERRQ(ierr); 2451 2452 /* Setup Layout and set local to global maps */ 2453 ierr = PetscLayoutSetUp(A->rmap);CHKERRQ(ierr); 2454 ierr = PetscLayoutSetUp(A->cmap);CHKERRQ(ierr); 2455 ierr = ISLocalToGlobalMappingGetSize(rmapping,&nr);CHKERRQ(ierr); 2456 ierr = ISLocalToGlobalMappingGetBlockSize(rmapping,&rbs);CHKERRQ(ierr); 2457 ierr = ISLocalToGlobalMappingGetSize(cmapping,&nc);CHKERRQ(ierr); 2458 ierr = ISLocalToGlobalMappingGetBlockSize(cmapping,&cbs);CHKERRQ(ierr); 2459 /* check if the two mappings are actually the same for square matrices (DOLFIN passes 2 different objects) */ 2460 if (rmapping != cmapping && A->rmap->N == A->cmap->N) { 2461 PetscBool same,gsame; 2462 2463 same = PETSC_FALSE; 2464 if (nr == nc && cbs == rbs) { 2465 const PetscInt *idxs1,*idxs2; 2466 2467 ierr = ISLocalToGlobalMappingGetBlockIndices(rmapping,&idxs1);CHKERRQ(ierr); 2468 ierr = ISLocalToGlobalMappingGetBlockIndices(cmapping,&idxs2);CHKERRQ(ierr); 2469 ierr = PetscArraycmp(idxs1,idxs2,nr/rbs,&same);CHKERRQ(ierr); 2470 ierr = ISLocalToGlobalMappingRestoreBlockIndices(rmapping,&idxs1);CHKERRQ(ierr); 2471 ierr = ISLocalToGlobalMappingRestoreBlockIndices(cmapping,&idxs2);CHKERRQ(ierr); 2472 } 2473 ierr = MPIU_Allreduce(&same,&gsame,1,MPIU_BOOL,MPI_LAND,PetscObjectComm((PetscObject)A));CHKERRQ(ierr); 2474 if (gsame) cmapping = rmapping; 2475 } 2476 ierr = PetscLayoutSetBlockSize(A->rmap,rbs);CHKERRQ(ierr); 2477 ierr = PetscLayoutSetBlockSize(A->cmap,cbs);CHKERRQ(ierr); 2478 ierr = PetscLayoutSetISLocalToGlobalMapping(A->rmap,rmapping);CHKERRQ(ierr); 2479 ierr = PetscLayoutSetISLocalToGlobalMapping(A->cmap,cmapping);CHKERRQ(ierr); 2480 2481 /* Create the local matrix A */ 2482 ierr = MatCreate(PETSC_COMM_SELF,&is->A);CHKERRQ(ierr); 2483 ierr = MatSetType(is->A,is->lmattype);CHKERRQ(ierr); 2484 ierr = MatSetSizes(is->A,nr,nc,nr,nc);CHKERRQ(ierr); 2485 ierr = MatSetBlockSizes(is->A,rbs,cbs);CHKERRQ(ierr); 2486 ierr = MatSetOptionsPrefix(is->A,"is_");CHKERRQ(ierr); 2487 ierr = MatAppendOptionsPrefix(is->A,((PetscObject)A)->prefix);CHKERRQ(ierr); 2488 ierr = PetscLayoutSetUp(is->A->rmap);CHKERRQ(ierr); 2489 ierr = PetscLayoutSetUp(is->A->cmap);CHKERRQ(ierr); 2490 2491 if (!is->islocalref) { /* setup scatters and local vectors for MatMult */ 2492 ierr = MatISSetUpScatters_Private(A);CHKERRQ(ierr); 2493 } 2494 ierr = MatSetUp(A);CHKERRQ(ierr); 2495 PetscFunctionReturn(0); 2496 } 2497 2498 static PetscErrorCode MatSetValues_IS(Mat mat, PetscInt m,const PetscInt *rows, PetscInt n,const PetscInt *cols, const PetscScalar *values, InsertMode addv) 2499 { 2500 Mat_IS *is = (Mat_IS*)mat->data; 2501 PetscErrorCode ierr; 2502 #if defined(PETSC_USE_DEBUG) 2503 PetscInt i,zm,zn; 2504 #endif 2505 PetscInt rows_l[MATIS_MAX_ENTRIES_INSERTION],cols_l[MATIS_MAX_ENTRIES_INSERTION]; 2506 2507 PetscFunctionBegin; 2508 #if defined(PETSC_USE_DEBUG) 2509 if (m > MATIS_MAX_ENTRIES_INSERTION || n > MATIS_MAX_ENTRIES_INSERTION) SETERRQ3(PETSC_COMM_SELF,PETSC_ERR_SUP,"Number of row/column indices must be <= %D: they are %D %D",MATIS_MAX_ENTRIES_INSERTION,m,n); 2510 /* count negative indices */ 2511 for (i=0,zm=0;i<m;i++) if (rows[i] < 0) zm++; 2512 for (i=0,zn=0;i<n;i++) if (cols[i] < 0) zn++; 2513 #endif 2514 ierr = ISGlobalToLocalMappingApply(mat->rmap->mapping,IS_GTOLM_MASK,m,rows,&m,rows_l);CHKERRQ(ierr); 2515 ierr = ISGlobalToLocalMappingApply(mat->cmap->mapping,IS_GTOLM_MASK,n,cols,&n,cols_l);CHKERRQ(ierr); 2516 #if defined(PETSC_USE_DEBUG) 2517 /* count negative indices (should be the same as before) */ 2518 for (i=0;i<m;i++) if (rows_l[i] < 0) zm--; 2519 for (i=0;i<n;i++) if (cols_l[i] < 0) zn--; 2520 if (!is->A->rmap->mapping && zm) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Some of the row indices can not be mapped! Maybe you should not use MATIS"); 2521 if (!is->A->cmap->mapping && zn) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Some of the column indices can not be mapped! Maybe you should not use MATIS"); 2522 #endif 2523 ierr = MatSetValues(is->A,m,rows_l,n,cols_l,values,addv);CHKERRQ(ierr); 2524 PetscFunctionReturn(0); 2525 } 2526 2527 static PetscErrorCode MatSetValuesBlocked_IS(Mat mat, PetscInt m,const PetscInt *rows, PetscInt n,const PetscInt *cols, const PetscScalar *values, InsertMode addv) 2528 { 2529 Mat_IS *is = (Mat_IS*)mat->data; 2530 PetscErrorCode ierr; 2531 #if defined(PETSC_USE_DEBUG) 2532 PetscInt i,zm,zn; 2533 #endif 2534 PetscInt rows_l[MATIS_MAX_ENTRIES_INSERTION],cols_l[MATIS_MAX_ENTRIES_INSERTION]; 2535 2536 PetscFunctionBegin; 2537 #if defined(PETSC_USE_DEBUG) 2538 if (m > MATIS_MAX_ENTRIES_INSERTION || n > MATIS_MAX_ENTRIES_INSERTION) SETERRQ3(PETSC_COMM_SELF,PETSC_ERR_SUP,"Number of row/column block indices must be <= %D: they are %D %D",MATIS_MAX_ENTRIES_INSERTION,m,n); 2539 /* count negative indices */ 2540 for (i=0,zm=0;i<m;i++) if (rows[i] < 0) zm++; 2541 for (i=0,zn=0;i<n;i++) if (cols[i] < 0) zn++; 2542 #endif 2543 ierr = ISGlobalToLocalMappingApplyBlock(mat->rmap->mapping,IS_GTOLM_MASK,m,rows,&m,rows_l);CHKERRQ(ierr); 2544 ierr = ISGlobalToLocalMappingApplyBlock(mat->cmap->mapping,IS_GTOLM_MASK,n,cols,&n,cols_l);CHKERRQ(ierr); 2545 #if defined(PETSC_USE_DEBUG) 2546 /* count negative indices (should be the same as before) */ 2547 for (i=0;i<m;i++) if (rows_l[i] < 0) zm--; 2548 for (i=0;i<n;i++) if (cols_l[i] < 0) zn--; 2549 if (!is->A->rmap->mapping && zm) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Some of the row indices can not be mapped! Maybe you should not use MATIS"); 2550 if (!is->A->cmap->mapping && zn) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Some of the column indices can not be mapped! Maybe you should not use MATIS"); 2551 #endif 2552 ierr = MatSetValuesBlocked(is->A,m,rows_l,n,cols_l,values,addv);CHKERRQ(ierr); 2553 PetscFunctionReturn(0); 2554 } 2555 2556 static PetscErrorCode MatSetValuesLocal_IS(Mat A,PetscInt m,const PetscInt *rows, PetscInt n,const PetscInt *cols,const PetscScalar *values,InsertMode addv) 2557 { 2558 PetscErrorCode ierr; 2559 Mat_IS *is = (Mat_IS*)A->data; 2560 2561 PetscFunctionBegin; 2562 if (is->A->rmap->mapping) { 2563 ierr = MatSetValuesLocal(is->A,m,rows,n,cols,values,addv);CHKERRQ(ierr); 2564 } else { 2565 ierr = MatSetValues(is->A,m,rows,n,cols,values,addv);CHKERRQ(ierr); 2566 } 2567 PetscFunctionReturn(0); 2568 } 2569 2570 static PetscErrorCode MatSetValuesBlockedLocal_IS(Mat A,PetscInt m,const PetscInt *rows, PetscInt n,const PetscInt *cols,const PetscScalar *values,InsertMode addv) 2571 { 2572 PetscErrorCode ierr; 2573 Mat_IS *is = (Mat_IS*)A->data; 2574 2575 PetscFunctionBegin; 2576 if (is->A->rmap->mapping) { 2577 #if defined(PETSC_USE_DEBUG) 2578 PetscInt ibs,bs; 2579 2580 ierr = ISLocalToGlobalMappingGetBlockSize(is->A->rmap->mapping,&ibs);CHKERRQ(ierr); 2581 ierr = MatGetBlockSize(is->A,&bs);CHKERRQ(ierr); 2582 if (ibs != bs) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_SUP,"Different block sizes! local mat %D, local l2g map %D",bs,ibs); 2583 #endif 2584 ierr = MatSetValuesBlockedLocal(is->A,m,rows,n,cols,values,addv);CHKERRQ(ierr); 2585 } else { 2586 ierr = MatSetValuesBlocked(is->A,m,rows,n,cols,values,addv);CHKERRQ(ierr); 2587 } 2588 PetscFunctionReturn(0); 2589 } 2590 2591 static PetscErrorCode MatISZeroRowsColumnsLocal_Private(Mat A,PetscInt n,const PetscInt rows[],PetscScalar diag,PetscBool columns) 2592 { 2593 Mat_IS *is = (Mat_IS*)A->data; 2594 PetscErrorCode ierr; 2595 2596 PetscFunctionBegin; 2597 if (!n) { 2598 is->pure_neumann = PETSC_TRUE; 2599 } else { 2600 PetscInt i; 2601 is->pure_neumann = PETSC_FALSE; 2602 2603 if (columns) { 2604 ierr = MatZeroRowsColumns(is->A,n,rows,diag,0,0);CHKERRQ(ierr); 2605 } else { 2606 ierr = MatZeroRows(is->A,n,rows,diag,0,0);CHKERRQ(ierr); 2607 } 2608 if (diag != 0.) { 2609 const PetscScalar *array; 2610 ierr = VecGetArrayRead(is->counter,&array);CHKERRQ(ierr); 2611 for (i=0; i<n; i++) { 2612 ierr = MatSetValue(is->A,rows[i],rows[i],diag/(array[rows[i]]),INSERT_VALUES);CHKERRQ(ierr); 2613 } 2614 ierr = VecRestoreArrayRead(is->counter,&array);CHKERRQ(ierr); 2615 } 2616 ierr = MatAssemblyBegin(is->A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 2617 ierr = MatAssemblyEnd(is->A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 2618 } 2619 PetscFunctionReturn(0); 2620 } 2621 2622 static PetscErrorCode MatZeroRowsColumns_Private_IS(Mat A,PetscInt n,const PetscInt rows[],PetscScalar diag,Vec x,Vec b,PetscBool columns) 2623 { 2624 Mat_IS *matis = (Mat_IS*)A->data; 2625 PetscInt nr,nl,len,i; 2626 PetscInt *lrows; 2627 PetscErrorCode ierr; 2628 2629 PetscFunctionBegin; 2630 #if defined(PETSC_USE_DEBUG) 2631 if (columns || diag != 0. || (x && b)) { 2632 PetscBool cong; 2633 2634 ierr = PetscLayoutCompare(A->rmap,A->cmap,&cong);CHKERRQ(ierr); 2635 cong = (PetscBool)(cong && matis->sf == matis->csf); 2636 if (!cong && columns) SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_SUP,"Columns can be zeroed if and only if A->rmap and A->cmap are congruent and the l2g maps are the same for MATIS"); 2637 if (!cong && diag != 0.) SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_SUP,"Nonzero diagonal value supported if and only if A->rmap and A->cmap are congruent and the l2g maps are the same for MATIS"); 2638 if (!cong && x && b) SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_SUP,"A->rmap and A->cmap need to be congruent, and the l2g maps be the same"); 2639 } 2640 #endif 2641 /* get locally owned rows */ 2642 ierr = PetscLayoutMapLocal(A->rmap,n,rows,&len,&lrows,NULL);CHKERRQ(ierr); 2643 /* fix right hand side if needed */ 2644 if (x && b) { 2645 const PetscScalar *xx; 2646 PetscScalar *bb; 2647 2648 ierr = VecGetArrayRead(x, &xx);CHKERRQ(ierr); 2649 ierr = VecGetArray(b, &bb);CHKERRQ(ierr); 2650 for (i=0;i<len;++i) bb[lrows[i]] = diag*xx[lrows[i]]; 2651 ierr = VecRestoreArrayRead(x, &xx);CHKERRQ(ierr); 2652 ierr = VecRestoreArray(b, &bb);CHKERRQ(ierr); 2653 } 2654 /* get rows associated to the local matrices */ 2655 ierr = MatGetSize(matis->A,&nl,NULL);CHKERRQ(ierr); 2656 ierr = PetscArrayzero(matis->sf_leafdata,nl);CHKERRQ(ierr); 2657 ierr = PetscArrayzero(matis->sf_rootdata,A->rmap->n);CHKERRQ(ierr); 2658 for (i=0;i<len;i++) matis->sf_rootdata[lrows[i]] = 1; 2659 ierr = PetscFree(lrows);CHKERRQ(ierr); 2660 ierr = PetscSFBcastBegin(matis->sf,MPIU_INT,matis->sf_rootdata,matis->sf_leafdata);CHKERRQ(ierr); 2661 ierr = PetscSFBcastEnd(matis->sf,MPIU_INT,matis->sf_rootdata,matis->sf_leafdata);CHKERRQ(ierr); 2662 ierr = PetscMalloc1(nl,&lrows);CHKERRQ(ierr); 2663 for (i=0,nr=0;i<nl;i++) if (matis->sf_leafdata[i]) lrows[nr++] = i; 2664 ierr = MatISZeroRowsColumnsLocal_Private(A,nr,lrows,diag,columns);CHKERRQ(ierr); 2665 ierr = PetscFree(lrows);CHKERRQ(ierr); 2666 PetscFunctionReturn(0); 2667 } 2668 2669 static PetscErrorCode MatZeroRows_IS(Mat A,PetscInt n,const PetscInt rows[],PetscScalar diag,Vec x,Vec b) 2670 { 2671 PetscErrorCode ierr; 2672 2673 PetscFunctionBegin; 2674 ierr = MatZeroRowsColumns_Private_IS(A,n,rows,diag,x,b,PETSC_FALSE);CHKERRQ(ierr); 2675 PetscFunctionReturn(0); 2676 } 2677 2678 static PetscErrorCode MatZeroRowsColumns_IS(Mat A,PetscInt n,const PetscInt rows[],PetscScalar diag,Vec x,Vec b) 2679 { 2680 PetscErrorCode ierr; 2681 2682 PetscFunctionBegin; 2683 ierr = MatZeroRowsColumns_Private_IS(A,n,rows,diag,x,b,PETSC_TRUE);CHKERRQ(ierr); 2684 PetscFunctionReturn(0); 2685 } 2686 2687 static PetscErrorCode MatAssemblyBegin_IS(Mat A,MatAssemblyType type) 2688 { 2689 Mat_IS *is = (Mat_IS*)A->data; 2690 PetscErrorCode ierr; 2691 2692 PetscFunctionBegin; 2693 ierr = MatAssemblyBegin(is->A,type);CHKERRQ(ierr); 2694 PetscFunctionReturn(0); 2695 } 2696 2697 static PetscErrorCode MatAssemblyEnd_IS(Mat A,MatAssemblyType type) 2698 { 2699 Mat_IS *is = (Mat_IS*)A->data; 2700 PetscErrorCode ierr; 2701 2702 PetscFunctionBegin; 2703 ierr = MatAssemblyEnd(is->A,type);CHKERRQ(ierr); 2704 /* fix for local empty rows/cols */ 2705 if (is->locempty && type == MAT_FINAL_ASSEMBLY) { 2706 Mat newlA; 2707 ISLocalToGlobalMapping rl2g,cl2g; 2708 IS nzr,nzc; 2709 PetscInt nr,nc,nnzr,nnzc; 2710 PetscBool lnewl2g,newl2g; 2711 2712 ierr = MatGetSize(is->A,&nr,&nc);CHKERRQ(ierr); 2713 ierr = MatFindNonzeroRowsOrCols_Basic(is->A,PETSC_FALSE,PETSC_SMALL,&nzr);CHKERRQ(ierr); 2714 if (!nzr) { 2715 ierr = ISCreateStride(PetscObjectComm((PetscObject)is->A),nr,0,1,&nzr);CHKERRQ(ierr); 2716 } 2717 ierr = MatFindNonzeroRowsOrCols_Basic(is->A,PETSC_TRUE,PETSC_SMALL,&nzc);CHKERRQ(ierr); 2718 if (!nzc) { 2719 ierr = ISCreateStride(PetscObjectComm((PetscObject)is->A),nc,0,1,&nzc);CHKERRQ(ierr); 2720 } 2721 ierr = ISGetSize(nzr,&nnzr);CHKERRQ(ierr); 2722 ierr = ISGetSize(nzc,&nnzc);CHKERRQ(ierr); 2723 if (nnzr != nr || nnzc != nc) { 2724 ISLocalToGlobalMapping l2g; 2725 IS is1,is2; 2726 2727 /* need new global l2g map */ 2728 lnewl2g = PETSC_TRUE; 2729 ierr = MPI_Allreduce(&lnewl2g,&newl2g,1,MPIU_BOOL,MPI_LOR,PetscObjectComm((PetscObject)A));CHKERRQ(ierr); 2730 2731 /* extract valid submatrix */ 2732 ierr = MatCreateSubMatrix(is->A,nzr,nzc,MAT_INITIAL_MATRIX,&newlA);CHKERRQ(ierr); 2733 2734 /* attach local l2g maps for successive calls of MatSetValues on the local matrix */ 2735 ierr = ISLocalToGlobalMappingCreateIS(nzr,&l2g);CHKERRQ(ierr); 2736 ierr = ISCreateStride(PetscObjectComm((PetscObject)is->A),nr,0,1,&is1);CHKERRQ(ierr); 2737 ierr = ISGlobalToLocalMappingApplyIS(l2g,IS_GTOLM_MASK,is1,&is2);CHKERRQ(ierr); 2738 ierr = ISLocalToGlobalMappingDestroy(&l2g);CHKERRQ(ierr); 2739 if (is->A->rmap->mapping) { /* the matrix has a local-to-local map already attached (probably DMDA generated) */ 2740 const PetscInt *idxs1,*idxs2; 2741 PetscInt j,i,nl,*tidxs; 2742 2743 ierr = ISLocalToGlobalMappingGetSize(is->A->rmap->mapping,&nl);CHKERRQ(ierr); 2744 ierr = ISLocalToGlobalMappingGetIndices(is->A->rmap->mapping,&idxs1);CHKERRQ(ierr); 2745 ierr = PetscMalloc1(nl,&tidxs);CHKERRQ(ierr); 2746 ierr = ISGetIndices(is2,&idxs2);CHKERRQ(ierr); 2747 for (i=0,j=0;i<nl;i++) tidxs[i] = idxs1[i] < 0 ? -1 : idxs2[j++]; 2748 if (j != nr) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Unexpected count %D != %D",j,nr); 2749 ierr = ISLocalToGlobalMappingRestoreIndices(is->A->rmap->mapping,&idxs1);CHKERRQ(ierr); 2750 ierr = ISRestoreIndices(is2,&idxs2);CHKERRQ(ierr); 2751 ierr = ISDestroy(&is2);CHKERRQ(ierr); 2752 ierr = ISCreateGeneral(PetscObjectComm((PetscObject)is->A->rmap->mapping),nl,tidxs,PETSC_OWN_POINTER,&is2);CHKERRQ(ierr); 2753 } 2754 ierr = ISLocalToGlobalMappingCreateIS(is2,&rl2g);CHKERRQ(ierr); 2755 ierr = ISDestroy(&is1);CHKERRQ(ierr); 2756 ierr = ISDestroy(&is2);CHKERRQ(ierr); 2757 2758 ierr = ISLocalToGlobalMappingCreateIS(nzc,&l2g);CHKERRQ(ierr); 2759 ierr = ISCreateStride(PetscObjectComm((PetscObject)is->A),nc,0,1,&is1);CHKERRQ(ierr); 2760 ierr = ISGlobalToLocalMappingApplyIS(l2g,IS_GTOLM_MASK,is1,&is2);CHKERRQ(ierr); 2761 ierr = ISLocalToGlobalMappingDestroy(&l2g);CHKERRQ(ierr); 2762 if (is->A->cmap->mapping) { /* the matrix has a local-to-local map already attached (probably DMDA generated) */ 2763 const PetscInt *idxs1,*idxs2; 2764 PetscInt j,i,nl,*tidxs; 2765 2766 ierr = ISLocalToGlobalMappingGetSize(is->A->cmap->mapping,&nl);CHKERRQ(ierr); 2767 ierr = ISLocalToGlobalMappingGetIndices(is->A->cmap->mapping,&idxs1);CHKERRQ(ierr); 2768 ierr = PetscMalloc1(nl,&tidxs);CHKERRQ(ierr); 2769 ierr = ISGetIndices(is2,&idxs2);CHKERRQ(ierr); 2770 for (i=0,j=0;i<nl;i++) tidxs[i] = idxs1[i] < 0 ? -1 : idxs2[j++]; 2771 if (j != nc) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Unexpected count %D != %D",j,nc); 2772 ierr = ISLocalToGlobalMappingRestoreIndices(is->A->cmap->mapping,&idxs1);CHKERRQ(ierr); 2773 ierr = ISRestoreIndices(is2,&idxs2);CHKERRQ(ierr); 2774 ierr = ISDestroy(&is2);CHKERRQ(ierr); 2775 ierr = ISCreateGeneral(PetscObjectComm((PetscObject)is->A->cmap->mapping),nl,tidxs,PETSC_OWN_POINTER,&is2);CHKERRQ(ierr); 2776 } 2777 ierr = ISLocalToGlobalMappingCreateIS(is2,&cl2g);CHKERRQ(ierr); 2778 ierr = ISDestroy(&is1);CHKERRQ(ierr); 2779 ierr = ISDestroy(&is2);CHKERRQ(ierr); 2780 2781 ierr = MatSetLocalToGlobalMapping(newlA,rl2g,cl2g);CHKERRQ(ierr); 2782 2783 ierr = ISLocalToGlobalMappingDestroy(&rl2g);CHKERRQ(ierr); 2784 ierr = ISLocalToGlobalMappingDestroy(&cl2g);CHKERRQ(ierr); 2785 } else { /* local matrix fully populated */ 2786 lnewl2g = PETSC_FALSE; 2787 ierr = MPI_Allreduce(&lnewl2g,&newl2g,1,MPIU_BOOL,MPI_LOR,PetscObjectComm((PetscObject)A));CHKERRQ(ierr); 2788 ierr = PetscObjectReference((PetscObject)is->A);CHKERRQ(ierr); 2789 newlA = is->A; 2790 } 2791 /* attach new global l2g map if needed */ 2792 if (newl2g) { 2793 IS gnzr,gnzc; 2794 const PetscInt *grid,*gcid; 2795 2796 ierr = ISLocalToGlobalMappingApplyIS(A->rmap->mapping,nzr,&gnzr);CHKERRQ(ierr); 2797 ierr = ISLocalToGlobalMappingApplyIS(A->cmap->mapping,nzc,&gnzc);CHKERRQ(ierr); 2798 ierr = ISGetIndices(gnzr,&grid);CHKERRQ(ierr); 2799 ierr = ISGetIndices(gnzc,&gcid);CHKERRQ(ierr); 2800 ierr = ISLocalToGlobalMappingCreate(PetscObjectComm((PetscObject)A),1,nnzr,grid,PETSC_COPY_VALUES,&rl2g);CHKERRQ(ierr); 2801 ierr = ISLocalToGlobalMappingCreate(PetscObjectComm((PetscObject)A),1,nnzc,gcid,PETSC_COPY_VALUES,&cl2g);CHKERRQ(ierr); 2802 ierr = ISRestoreIndices(gnzr,&grid);CHKERRQ(ierr); 2803 ierr = ISRestoreIndices(gnzc,&gcid);CHKERRQ(ierr); 2804 ierr = ISDestroy(&gnzr);CHKERRQ(ierr); 2805 ierr = ISDestroy(&gnzc);CHKERRQ(ierr); 2806 ierr = MatSetLocalToGlobalMapping(A,rl2g,cl2g);CHKERRQ(ierr); 2807 ierr = ISLocalToGlobalMappingDestroy(&rl2g);CHKERRQ(ierr); 2808 ierr = ISLocalToGlobalMappingDestroy(&cl2g);CHKERRQ(ierr); 2809 } 2810 ierr = MatISSetLocalMat(A,newlA);CHKERRQ(ierr); 2811 ierr = MatDestroy(&newlA);CHKERRQ(ierr); 2812 ierr = ISDestroy(&nzr);CHKERRQ(ierr); 2813 ierr = ISDestroy(&nzc);CHKERRQ(ierr); 2814 is->locempty = PETSC_FALSE; 2815 } 2816 PetscFunctionReturn(0); 2817 } 2818 2819 static PetscErrorCode MatISGetLocalMat_IS(Mat mat,Mat *local) 2820 { 2821 Mat_IS *is = (Mat_IS*)mat->data; 2822 2823 PetscFunctionBegin; 2824 *local = is->A; 2825 PetscFunctionReturn(0); 2826 } 2827 2828 static PetscErrorCode MatISRestoreLocalMat_IS(Mat mat,Mat *local) 2829 { 2830 PetscFunctionBegin; 2831 *local = NULL; 2832 PetscFunctionReturn(0); 2833 } 2834 2835 /*@ 2836 MatISGetLocalMat - Gets the local matrix stored inside a MATIS matrix. 2837 2838 Input Parameter: 2839 . mat - the matrix 2840 2841 Output Parameter: 2842 . local - the local matrix 2843 2844 Level: advanced 2845 2846 Notes: 2847 This can be called if you have precomputed the nonzero structure of the 2848 matrix and want to provide it to the inner matrix object to improve the performance 2849 of the MatSetValues() operation. 2850 2851 Call MatISRestoreLocalMat() when finished with the local matrix. 2852 2853 .seealso: MATIS 2854 @*/ 2855 PetscErrorCode MatISGetLocalMat(Mat mat,Mat *local) 2856 { 2857 PetscErrorCode ierr; 2858 2859 PetscFunctionBegin; 2860 PetscValidHeaderSpecific(mat,MAT_CLASSID,1); 2861 PetscValidPointer(local,2); 2862 ierr = PetscUseMethod(mat,"MatISGetLocalMat_C",(Mat,Mat*),(mat,local));CHKERRQ(ierr); 2863 PetscFunctionReturn(0); 2864 } 2865 2866 /*@ 2867 MatISRestoreLocalMat - Restores the local matrix obtained with MatISGetLocalMat() 2868 2869 Input Parameter: 2870 . mat - the matrix 2871 2872 Output Parameter: 2873 . local - the local matrix 2874 2875 Level: advanced 2876 2877 .seealso: MATIS 2878 @*/ 2879 PetscErrorCode MatISRestoreLocalMat(Mat mat,Mat *local) 2880 { 2881 PetscErrorCode ierr; 2882 2883 PetscFunctionBegin; 2884 PetscValidHeaderSpecific(mat,MAT_CLASSID,1); 2885 PetscValidPointer(local,2); 2886 ierr = PetscUseMethod(mat,"MatISRestoreLocalMat_C",(Mat,Mat*),(mat,local));CHKERRQ(ierr); 2887 PetscFunctionReturn(0); 2888 } 2889 2890 static PetscErrorCode MatISSetLocalMatType_IS(Mat mat,MatType mtype) 2891 { 2892 Mat_IS *is = (Mat_IS*)mat->data; 2893 PetscErrorCode ierr; 2894 2895 PetscFunctionBegin; 2896 if (is->A) { 2897 ierr = MatSetType(is->A,mtype);CHKERRQ(ierr); 2898 } 2899 ierr = PetscFree(is->lmattype);CHKERRQ(ierr); 2900 ierr = PetscStrallocpy(mtype,&is->lmattype);CHKERRQ(ierr); 2901 PetscFunctionReturn(0); 2902 } 2903 2904 /*@ 2905 MatISSetLocalMatType - Specifies the type of local matrix 2906 2907 Input Parameter: 2908 + mat - the matrix 2909 - mtype - the local matrix type 2910 2911 Output Parameter: 2912 2913 Level: advanced 2914 2915 .seealso: MATIS, MatSetType(), MatType 2916 @*/ 2917 PetscErrorCode MatISSetLocalMatType(Mat mat,MatType mtype) 2918 { 2919 PetscErrorCode ierr; 2920 2921 PetscFunctionBegin; 2922 PetscValidHeaderSpecific(mat,MAT_CLASSID,1); 2923 ierr = PetscUseMethod(mat,"MatISSetLocalMatType_C",(Mat,MatType),(mat,mtype));CHKERRQ(ierr); 2924 PetscFunctionReturn(0); 2925 } 2926 2927 static PetscErrorCode MatISSetLocalMat_IS(Mat mat,Mat local) 2928 { 2929 Mat_IS *is = (Mat_IS*)mat->data; 2930 PetscInt nrows,ncols,orows,ocols; 2931 PetscErrorCode ierr; 2932 MatType mtype,otype; 2933 PetscBool sametype = PETSC_TRUE; 2934 2935 PetscFunctionBegin; 2936 if (is->A) { 2937 ierr = MatGetSize(is->A,&orows,&ocols);CHKERRQ(ierr); 2938 ierr = MatGetSize(local,&nrows,&ncols);CHKERRQ(ierr); 2939 if (orows != nrows || ocols != ncols) SETERRQ4(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Local MATIS matrix should be of size %Dx%D (you passed a %Dx%D matrix)",orows,ocols,nrows,ncols); 2940 ierr = MatGetType(local,&mtype);CHKERRQ(ierr); 2941 ierr = MatGetType(is->A,&otype);CHKERRQ(ierr); 2942 ierr = PetscStrcmp(mtype,otype,&sametype);CHKERRQ(ierr); 2943 } 2944 ierr = PetscObjectReference((PetscObject)local);CHKERRQ(ierr); 2945 ierr = MatDestroy(&is->A);CHKERRQ(ierr); 2946 is->A = local; 2947 ierr = MatGetType(is->A,&mtype);CHKERRQ(ierr); 2948 ierr = MatISSetLocalMatType(mat,mtype);CHKERRQ(ierr); 2949 if (!sametype && !is->islocalref) { 2950 ierr = MatISSetUpScatters_Private(mat);CHKERRQ(ierr); 2951 } 2952 PetscFunctionReturn(0); 2953 } 2954 2955 /*@ 2956 MatISSetLocalMat - Replace the local matrix stored inside a MATIS object. 2957 2958 Collective on Mat 2959 2960 Input Parameter: 2961 + mat - the matrix 2962 - local - the local matrix 2963 2964 Output Parameter: 2965 2966 Level: advanced 2967 2968 Notes: 2969 This can be called if you have precomputed the local matrix and 2970 want to provide it to the matrix object MATIS. 2971 2972 .seealso: MATIS 2973 @*/ 2974 PetscErrorCode MatISSetLocalMat(Mat mat,Mat local) 2975 { 2976 PetscErrorCode ierr; 2977 2978 PetscFunctionBegin; 2979 PetscValidHeaderSpecific(mat,MAT_CLASSID,1); 2980 PetscValidHeaderSpecific(local,MAT_CLASSID,2); 2981 ierr = PetscUseMethod(mat,"MatISSetLocalMat_C",(Mat,Mat),(mat,local));CHKERRQ(ierr); 2982 PetscFunctionReturn(0); 2983 } 2984 2985 static PetscErrorCode MatZeroEntries_IS(Mat A) 2986 { 2987 Mat_IS *a = (Mat_IS*)A->data; 2988 PetscErrorCode ierr; 2989 2990 PetscFunctionBegin; 2991 ierr = MatZeroEntries(a->A);CHKERRQ(ierr); 2992 PetscFunctionReturn(0); 2993 } 2994 2995 static PetscErrorCode MatScale_IS(Mat A,PetscScalar a) 2996 { 2997 Mat_IS *is = (Mat_IS*)A->data; 2998 PetscErrorCode ierr; 2999 3000 PetscFunctionBegin; 3001 ierr = MatScale(is->A,a);CHKERRQ(ierr); 3002 PetscFunctionReturn(0); 3003 } 3004 3005 static PetscErrorCode MatGetDiagonal_IS(Mat A, Vec v) 3006 { 3007 Mat_IS *is = (Mat_IS*)A->data; 3008 PetscErrorCode ierr; 3009 3010 PetscFunctionBegin; 3011 /* get diagonal of the local matrix */ 3012 ierr = MatGetDiagonal(is->A,is->y);CHKERRQ(ierr); 3013 3014 /* scatter diagonal back into global vector */ 3015 ierr = VecSet(v,0);CHKERRQ(ierr); 3016 ierr = VecScatterBegin(is->rctx,is->y,v,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 3017 ierr = VecScatterEnd(is->rctx,is->y,v,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 3018 PetscFunctionReturn(0); 3019 } 3020 3021 static PetscErrorCode MatSetOption_IS(Mat A,MatOption op,PetscBool flg) 3022 { 3023 Mat_IS *a = (Mat_IS*)A->data; 3024 PetscErrorCode ierr; 3025 3026 PetscFunctionBegin; 3027 ierr = MatSetOption(a->A,op,flg);CHKERRQ(ierr); 3028 PetscFunctionReturn(0); 3029 } 3030 3031 static PetscErrorCode MatAXPY_IS(Mat Y,PetscScalar a,Mat X,MatStructure str) 3032 { 3033 Mat_IS *y = (Mat_IS*)Y->data; 3034 Mat_IS *x; 3035 #if defined(PETSC_USE_DEBUG) 3036 PetscBool ismatis; 3037 #endif 3038 PetscErrorCode ierr; 3039 3040 PetscFunctionBegin; 3041 #if defined(PETSC_USE_DEBUG) 3042 ierr = PetscObjectTypeCompare((PetscObject)X,MATIS,&ismatis);CHKERRQ(ierr); 3043 if (!ismatis) SETERRQ(PetscObjectComm((PetscObject)Y),PETSC_ERR_SUP,"Cannot call MatAXPY(Y,a,X,str) with X not of type MATIS"); 3044 #endif 3045 x = (Mat_IS*)X->data; 3046 ierr = MatAXPY(y->A,a,x->A,str);CHKERRQ(ierr); 3047 PetscFunctionReturn(0); 3048 } 3049 3050 static PetscErrorCode MatGetLocalSubMatrix_IS(Mat A,IS row,IS col,Mat *submat) 3051 { 3052 Mat lA; 3053 Mat_IS *matis; 3054 ISLocalToGlobalMapping rl2g,cl2g; 3055 IS is; 3056 const PetscInt *rg,*rl; 3057 PetscInt nrg; 3058 PetscInt N,M,nrl,i,*idxs; 3059 PetscErrorCode ierr; 3060 3061 PetscFunctionBegin; 3062 ierr = ISLocalToGlobalMappingGetIndices(A->rmap->mapping,&rg);CHKERRQ(ierr); 3063 ierr = ISGetLocalSize(row,&nrl);CHKERRQ(ierr); 3064 ierr = ISGetIndices(row,&rl);CHKERRQ(ierr); 3065 ierr = ISLocalToGlobalMappingGetSize(A->rmap->mapping,&nrg);CHKERRQ(ierr); 3066 #if defined(PETSC_USE_DEBUG) 3067 for (i=0;i<nrl;i++) if (rl[i]>=nrg) SETERRQ3(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Local row index %D -> %D greater then maximum possible %D",i,rl[i],nrg); 3068 #endif 3069 ierr = PetscMalloc1(nrg,&idxs);CHKERRQ(ierr); 3070 /* map from [0,nrl) to row */ 3071 for (i=0;i<nrl;i++) idxs[i] = rl[i]; 3072 for (i=nrl;i<nrg;i++) idxs[i] = -1; 3073 ierr = ISRestoreIndices(row,&rl);CHKERRQ(ierr); 3074 ierr = ISLocalToGlobalMappingRestoreIndices(A->rmap->mapping,&rg);CHKERRQ(ierr); 3075 ierr = ISCreateGeneral(PetscObjectComm((PetscObject)A),nrg,idxs,PETSC_OWN_POINTER,&is);CHKERRQ(ierr); 3076 ierr = ISLocalToGlobalMappingCreateIS(is,&rl2g);CHKERRQ(ierr); 3077 ierr = ISDestroy(&is);CHKERRQ(ierr); 3078 /* compute new l2g map for columns */ 3079 if (col != row || A->rmap->mapping != A->cmap->mapping) { 3080 const PetscInt *cg,*cl; 3081 PetscInt ncg; 3082 PetscInt ncl; 3083 3084 ierr = ISLocalToGlobalMappingGetIndices(A->cmap->mapping,&cg);CHKERRQ(ierr); 3085 ierr = ISGetLocalSize(col,&ncl);CHKERRQ(ierr); 3086 ierr = ISGetIndices(col,&cl);CHKERRQ(ierr); 3087 ierr = ISLocalToGlobalMappingGetSize(A->cmap->mapping,&ncg);CHKERRQ(ierr); 3088 #if defined(PETSC_USE_DEBUG) 3089 for (i=0;i<ncl;i++) if (cl[i]>=ncg) SETERRQ3(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Local column index %D -> %D greater then maximum possible %D",i,cl[i],ncg); 3090 #endif 3091 ierr = PetscMalloc1(ncg,&idxs);CHKERRQ(ierr); 3092 /* map from [0,ncl) to col */ 3093 for (i=0;i<ncl;i++) idxs[i] = cl[i]; 3094 for (i=ncl;i<ncg;i++) idxs[i] = -1; 3095 ierr = ISRestoreIndices(col,&cl);CHKERRQ(ierr); 3096 ierr = ISLocalToGlobalMappingRestoreIndices(A->cmap->mapping,&cg);CHKERRQ(ierr); 3097 ierr = ISCreateGeneral(PetscObjectComm((PetscObject)A),ncg,idxs,PETSC_OWN_POINTER,&is);CHKERRQ(ierr); 3098 ierr = ISLocalToGlobalMappingCreateIS(is,&cl2g);CHKERRQ(ierr); 3099 ierr = ISDestroy(&is);CHKERRQ(ierr); 3100 } else { 3101 ierr = PetscObjectReference((PetscObject)rl2g);CHKERRQ(ierr); 3102 cl2g = rl2g; 3103 } 3104 /* create the MATIS submatrix */ 3105 ierr = MatGetSize(A,&M,&N);CHKERRQ(ierr); 3106 ierr = MatCreate(PetscObjectComm((PetscObject)A),submat);CHKERRQ(ierr); 3107 ierr = MatSetSizes(*submat,PETSC_DECIDE,PETSC_DECIDE,M,N);CHKERRQ(ierr); 3108 ierr = MatSetType(*submat,MATIS);CHKERRQ(ierr); 3109 matis = (Mat_IS*)((*submat)->data); 3110 matis->islocalref = PETSC_TRUE; 3111 ierr = MatSetLocalToGlobalMapping(*submat,rl2g,cl2g);CHKERRQ(ierr); 3112 ierr = MatISGetLocalMat(A,&lA);CHKERRQ(ierr); 3113 ierr = MatISSetLocalMat(*submat,lA);CHKERRQ(ierr); 3114 ierr = MatSetUp(*submat);CHKERRQ(ierr); 3115 ierr = MatAssemblyBegin(*submat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 3116 ierr = MatAssemblyEnd(*submat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 3117 ierr = ISLocalToGlobalMappingDestroy(&rl2g);CHKERRQ(ierr); 3118 ierr = ISLocalToGlobalMappingDestroy(&cl2g);CHKERRQ(ierr); 3119 /* remove unsupported ops */ 3120 ierr = PetscMemzero((*submat)->ops,sizeof(struct _MatOps));CHKERRQ(ierr); 3121 (*submat)->ops->destroy = MatDestroy_IS; 3122 (*submat)->ops->setvalueslocal = MatSetValuesLocal_SubMat_IS; 3123 (*submat)->ops->setvaluesblockedlocal = MatSetValuesBlockedLocal_SubMat_IS; 3124 (*submat)->ops->assemblybegin = MatAssemblyBegin_IS; 3125 (*submat)->ops->assemblyend = MatAssemblyEnd_IS; 3126 PetscFunctionReturn(0); 3127 } 3128 3129 static PetscErrorCode MatSetFromOptions_IS(PetscOptionItems *PetscOptionsObject, Mat A) 3130 { 3131 Mat_IS *a = (Mat_IS*)A->data; 3132 char type[256]; 3133 PetscBool flg; 3134 PetscErrorCode ierr; 3135 3136 PetscFunctionBegin; 3137 ierr = PetscOptionsHead(PetscOptionsObject,"MATIS options");CHKERRQ(ierr); 3138 ierr = PetscOptionsBool("-matis_fixempty","Fix local matrices in case of empty local rows/columns","MatISFixLocalEmpty",a->locempty,&a->locempty,NULL);CHKERRQ(ierr); 3139 ierr = PetscOptionsBool("-matis_storel2l","Store local-to-local matrices generated from PtAP operations","MatISStoreL2L",a->storel2l,&a->storel2l,NULL);CHKERRQ(ierr); 3140 ierr = PetscOptionsFList("-matis_localmat_type","Matrix type","MatISSetLocalMatType",MatList,a->lmattype,type,256,&flg);CHKERRQ(ierr); 3141 if (flg) { 3142 ierr = MatISSetLocalMatType(A,type);CHKERRQ(ierr); 3143 } 3144 if (a->A) { 3145 ierr = MatSetFromOptions(a->A);CHKERRQ(ierr); 3146 } 3147 ierr = PetscOptionsTail();CHKERRQ(ierr); 3148 PetscFunctionReturn(0); 3149 } 3150 3151 /*@ 3152 MatCreateIS - Creates a "process" unassembled matrix, assembled on each 3153 process but not across processes. 3154 3155 Input Parameters: 3156 + comm - MPI communicator that will share the matrix 3157 . bs - block size of the matrix 3158 . m,n,M,N - local and/or global sizes of the left and right vector used in matrix vector products 3159 . rmap - local to global map for rows 3160 - cmap - local to global map for cols 3161 3162 Output Parameter: 3163 . A - the resulting matrix 3164 3165 Level: advanced 3166 3167 Notes: 3168 See MATIS for more details. 3169 m and n are NOT related to the size of the map; they represent the size of the local parts of the vectors 3170 used in MatMult operations. The sizes of rmap and cmap define the size of the local matrices. 3171 If either rmap or cmap are NULL, then the matrix is assumed to be square. 3172 3173 .seealso: MATIS, MatSetLocalToGlobalMapping() 3174 @*/ 3175 PetscErrorCode MatCreateIS(MPI_Comm comm,PetscInt bs,PetscInt m,PetscInt n,PetscInt M,PetscInt N,ISLocalToGlobalMapping rmap,ISLocalToGlobalMapping cmap,Mat *A) 3176 { 3177 PetscErrorCode ierr; 3178 3179 PetscFunctionBegin; 3180 if (!rmap && !cmap) SETERRQ(comm,PETSC_ERR_USER,"You need to provide at least one of the mappings"); 3181 ierr = MatCreate(comm,A);CHKERRQ(ierr); 3182 ierr = MatSetSizes(*A,m,n,M,N);CHKERRQ(ierr); 3183 if (bs > 0) { 3184 ierr = MatSetBlockSize(*A,bs);CHKERRQ(ierr); 3185 } 3186 ierr = MatSetType(*A,MATIS);CHKERRQ(ierr); 3187 if (rmap && cmap) { 3188 ierr = MatSetLocalToGlobalMapping(*A,rmap,cmap);CHKERRQ(ierr); 3189 } else if (!rmap) { 3190 ierr = MatSetLocalToGlobalMapping(*A,cmap,cmap);CHKERRQ(ierr); 3191 } else { 3192 ierr = MatSetLocalToGlobalMapping(*A,rmap,rmap);CHKERRQ(ierr); 3193 } 3194 PetscFunctionReturn(0); 3195 } 3196 3197 /*MC 3198 MATIS - MATIS = "is" - A matrix type to be used for using the non-overlapping domain decomposition methods (e.g. PCBDDC or KSPFETIDP). 3199 This stores the matrices in globally unassembled form. Each processor assembles only its local Neumann problem and the parallel matrix vector 3200 product is handled "implicitly". 3201 3202 Options Database Keys: 3203 + -mat_type is - sets the matrix type to "is" during a call to MatSetFromOptions() 3204 . -matis_fixempty - Fixes local matrices in case of empty local rows/columns. 3205 - -matis_storel2l - stores the local-to-local operators generated by the Galerkin process of MatPtAP(). 3206 3207 Notes: 3208 Options prefix for the inner matrix are given by -is_mat_xxx 3209 3210 You must call MatSetLocalToGlobalMapping() before using this matrix type. 3211 3212 You can do matrix preallocation on the local matrix after you obtain it with 3213 MatISGetLocalMat(); otherwise, you could use MatISSetPreallocation() 3214 3215 Level: advanced 3216 3217 .seealso: Mat, MatISGetLocalMat(), MatSetLocalToGlobalMapping(), MatISSetPreallocation(), MatCreateIS(), PCBDDC, KSPFETIDP 3218 3219 M*/ 3220 3221 PETSC_EXTERN PetscErrorCode MatCreate_IS(Mat A) 3222 { 3223 PetscErrorCode ierr; 3224 Mat_IS *b; 3225 3226 PetscFunctionBegin; 3227 ierr = PetscNewLog(A,&b);CHKERRQ(ierr); 3228 ierr = PetscStrallocpy(MATAIJ,&b->lmattype);CHKERRQ(ierr); 3229 A->data = (void*)b; 3230 3231 /* matrix ops */ 3232 ierr = PetscMemzero(A->ops,sizeof(struct _MatOps));CHKERRQ(ierr); 3233 A->ops->mult = MatMult_IS; 3234 A->ops->multadd = MatMultAdd_IS; 3235 A->ops->multtranspose = MatMultTranspose_IS; 3236 A->ops->multtransposeadd = MatMultTransposeAdd_IS; 3237 A->ops->destroy = MatDestroy_IS; 3238 A->ops->setlocaltoglobalmapping = MatSetLocalToGlobalMapping_IS; 3239 A->ops->setvalues = MatSetValues_IS; 3240 A->ops->setvaluesblocked = MatSetValuesBlocked_IS; 3241 A->ops->setvalueslocal = MatSetValuesLocal_IS; 3242 A->ops->setvaluesblockedlocal = MatSetValuesBlockedLocal_IS; 3243 A->ops->zerorows = MatZeroRows_IS; 3244 A->ops->zerorowscolumns = MatZeroRowsColumns_IS; 3245 A->ops->assemblybegin = MatAssemblyBegin_IS; 3246 A->ops->assemblyend = MatAssemblyEnd_IS; 3247 A->ops->view = MatView_IS; 3248 A->ops->zeroentries = MatZeroEntries_IS; 3249 A->ops->scale = MatScale_IS; 3250 A->ops->getdiagonal = MatGetDiagonal_IS; 3251 A->ops->setoption = MatSetOption_IS; 3252 A->ops->ishermitian = MatIsHermitian_IS; 3253 A->ops->issymmetric = MatIsSymmetric_IS; 3254 A->ops->isstructurallysymmetric = MatIsStructurallySymmetric_IS; 3255 A->ops->duplicate = MatDuplicate_IS; 3256 A->ops->missingdiagonal = MatMissingDiagonal_IS; 3257 A->ops->copy = MatCopy_IS; 3258 A->ops->getlocalsubmatrix = MatGetLocalSubMatrix_IS; 3259 A->ops->createsubmatrix = MatCreateSubMatrix_IS; 3260 A->ops->axpy = MatAXPY_IS; 3261 A->ops->diagonalset = MatDiagonalSet_IS; 3262 A->ops->shift = MatShift_IS; 3263 A->ops->transpose = MatTranspose_IS; 3264 A->ops->getinfo = MatGetInfo_IS; 3265 A->ops->diagonalscale = MatDiagonalScale_IS; 3266 A->ops->setfromoptions = MatSetFromOptions_IS; 3267 3268 /* special MATIS functions */ 3269 ierr = PetscObjectComposeFunction((PetscObject)A,"MatISSetLocalMatType_C",MatISSetLocalMatType_IS);CHKERRQ(ierr); 3270 ierr = PetscObjectComposeFunction((PetscObject)A,"MatISGetLocalMat_C",MatISGetLocalMat_IS);CHKERRQ(ierr); 3271 ierr = PetscObjectComposeFunction((PetscObject)A,"MatISRestoreLocalMat_C",MatISRestoreLocalMat_IS);CHKERRQ(ierr); 3272 ierr = PetscObjectComposeFunction((PetscObject)A,"MatISSetLocalMat_C",MatISSetLocalMat_IS);CHKERRQ(ierr); 3273 ierr = PetscObjectComposeFunction((PetscObject)A,"MatISGetMPIXAIJ_C",MatConvert_IS_XAIJ);CHKERRQ(ierr); 3274 ierr = PetscObjectComposeFunction((PetscObject)A,"MatISSetPreallocation_C",MatISSetPreallocation_IS);CHKERRQ(ierr); 3275 ierr = PetscObjectComposeFunction((PetscObject)A,"MatISStoreL2L_C",MatISStoreL2L_IS);CHKERRQ(ierr); 3276 ierr = PetscObjectComposeFunction((PetscObject)A,"MatISFixLocalEmpty_C",MatISFixLocalEmpty_IS);CHKERRQ(ierr); 3277 ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_is_mpiaij_C",MatConvert_IS_XAIJ);CHKERRQ(ierr); 3278 ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_is_mpibaij_C",MatConvert_IS_XAIJ);CHKERRQ(ierr); 3279 ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_is_mpisbaij_C",MatConvert_IS_XAIJ);CHKERRQ(ierr); 3280 ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_is_seqaij_C",MatConvert_IS_XAIJ);CHKERRQ(ierr); 3281 ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_is_seqbaij_C",MatConvert_IS_XAIJ);CHKERRQ(ierr); 3282 ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_is_seqsbaij_C",MatConvert_IS_XAIJ);CHKERRQ(ierr); 3283 ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_is_aij_C",MatConvert_IS_XAIJ);CHKERRQ(ierr); 3284 ierr = PetscObjectChangeTypeName((PetscObject)A,MATIS);CHKERRQ(ierr); 3285 PetscFunctionReturn(0); 3286 } 3287