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 = PetscObjectTypeCompare((PetscObject)PT,MATMPIAIJ,&ismpiaij);CHKERRQ(ierr); 100 ierr = PetscObjectTypeCompare((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 = PetscMemcmp(i1,i2,N*sizeof(*i1),&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 = PetscObjectTypeCompare((PetscObject)A,MATMPIAIJ ,&ismpiaij);CHKERRQ(ierr); 415 ierr = PetscObjectTypeCompare((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 = PetscMemzero(dnz,A->rmap->n*sizeof(*dnz));CHKERRQ(ierr); 486 ierr = PetscMemzero(onz,A->rmap->n*sizeof(*onz));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 = PetscObjectTypeCompare((PetscObject)A,MATMPIAIJ ,&ismpiaij);CHKERRQ(ierr); 685 ierr = PetscObjectTypeCompare((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); 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, 834 nr,&islrow,nc,&islcol, 835 nr*nc,&snest,nr*nc,&istrans);CHKERRQ(ierr); 836 ierr = MatNestGetISs(A,isrow,iscol);CHKERRQ(ierr); 837 for (i=0;i<nr;i++) { 838 for (j=0;j<nc;j++) { 839 PetscBool ismatis; 840 PetscInt l1,l2,lb1,lb2,ij=i*nc+j; 841 842 /* Null matrix pointers are allowed in MATNEST */ 843 if (!nest[i][j]) continue; 844 845 /* Nested matrices should be of type MATIS */ 846 ierr = PetscObjectTypeCompare((PetscObject)nest[i][j],MATTRANSPOSEMAT,&istrans[ij]);CHKERRQ(ierr); 847 if (istrans[ij]) { 848 Mat T,lT; 849 ierr = MatTransposeGetMat(nest[i][j],&T);CHKERRQ(ierr); 850 ierr = PetscObjectTypeCompare((PetscObject)T,MATIS,&ismatis);CHKERRQ(ierr); 851 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); 852 ierr = MatISGetLocalMat(T,&lT);CHKERRQ(ierr); 853 ierr = MatCreateTranspose(lT,&snest[ij]);CHKERRQ(ierr); 854 } else { 855 ierr = PetscObjectTypeCompare((PetscObject)nest[i][j],MATIS,&ismatis);CHKERRQ(ierr); 856 if (!ismatis) SETERRQ2(comm,PETSC_ERR_SUP,"Cannot convert from MATNEST to MATIS! Matrix block (%D,%D) is not of type MATIS",i,j); 857 ierr = MatISGetLocalMat(nest[i][j],&snest[ij]);CHKERRQ(ierr); 858 } 859 860 /* Check compatibility of local sizes */ 861 ierr = MatGetSize(snest[ij],&l1,&l2);CHKERRQ(ierr); 862 ierr = MatGetBlockSizes(snest[ij],&lb1,&lb2);CHKERRQ(ierr); 863 if (!l1 || !l2) continue; 864 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); 865 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); 866 lr[i] = l1; 867 lc[j] = l2; 868 869 /* check compatibilty for local matrix reusage */ 870 if (rnest && !rnest[i][j] != !snest[ij]) lreuse = PETSC_FALSE; 871 } 872 } 873 874 #if defined (PETSC_USE_DEBUG) 875 /* Check compatibility of l2g maps for rows */ 876 for (i=0;i<nr;i++) { 877 rl2g = NULL; 878 for (j=0;j<nc;j++) { 879 PetscInt n1,n2; 880 881 if (!nest[i][j]) continue; 882 if (istrans[i*nc+j]) { 883 Mat T; 884 885 ierr = MatTransposeGetMat(nest[i][j],&T);CHKERRQ(ierr); 886 ierr = MatGetLocalToGlobalMapping(T,NULL,&cl2g);CHKERRQ(ierr); 887 } else { 888 ierr = MatGetLocalToGlobalMapping(nest[i][j],&cl2g,NULL);CHKERRQ(ierr); 889 } 890 ierr = ISLocalToGlobalMappingGetSize(cl2g,&n1);CHKERRQ(ierr); 891 if (!n1) continue; 892 if (!rl2g) { 893 rl2g = cl2g; 894 } else { 895 const PetscInt *idxs1,*idxs2; 896 PetscBool same; 897 898 ierr = ISLocalToGlobalMappingGetSize(rl2g,&n2);CHKERRQ(ierr); 899 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); 900 ierr = ISLocalToGlobalMappingGetIndices(cl2g,&idxs1);CHKERRQ(ierr); 901 ierr = ISLocalToGlobalMappingGetIndices(rl2g,&idxs2);CHKERRQ(ierr); 902 ierr = PetscMemcmp(idxs1,idxs2,n1*sizeof(PetscInt),&same);CHKERRQ(ierr); 903 ierr = ISLocalToGlobalMappingRestoreIndices(cl2g,&idxs1);CHKERRQ(ierr); 904 ierr = ISLocalToGlobalMappingRestoreIndices(rl2g,&idxs2);CHKERRQ(ierr); 905 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); 906 } 907 } 908 } 909 /* Check compatibility of l2g maps for columns */ 910 for (i=0;i<nc;i++) { 911 rl2g = NULL; 912 for (j=0;j<nr;j++) { 913 PetscInt n1,n2; 914 915 if (!nest[j][i]) continue; 916 if (istrans[j*nc+i]) { 917 Mat T; 918 919 ierr = MatTransposeGetMat(nest[j][i],&T);CHKERRQ(ierr); 920 ierr = MatGetLocalToGlobalMapping(T,&cl2g,NULL);CHKERRQ(ierr); 921 } else { 922 ierr = MatGetLocalToGlobalMapping(nest[j][i],NULL,&cl2g);CHKERRQ(ierr); 923 } 924 ierr = ISLocalToGlobalMappingGetSize(cl2g,&n1);CHKERRQ(ierr); 925 if (!n1) continue; 926 if (!rl2g) { 927 rl2g = cl2g; 928 } else { 929 const PetscInt *idxs1,*idxs2; 930 PetscBool same; 931 932 ierr = ISLocalToGlobalMappingGetSize(rl2g,&n2);CHKERRQ(ierr); 933 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); 934 ierr = ISLocalToGlobalMappingGetIndices(cl2g,&idxs1);CHKERRQ(ierr); 935 ierr = ISLocalToGlobalMappingGetIndices(rl2g,&idxs2);CHKERRQ(ierr); 936 ierr = PetscMemcmp(idxs1,idxs2,n1*sizeof(PetscInt),&same);CHKERRQ(ierr); 937 ierr = ISLocalToGlobalMappingRestoreIndices(cl2g,&idxs1);CHKERRQ(ierr); 938 ierr = ISLocalToGlobalMappingRestoreIndices(rl2g,&idxs2);CHKERRQ(ierr); 939 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); 940 } 941 } 942 } 943 #endif 944 945 B = NULL; 946 if (reuse != MAT_REUSE_MATRIX) { 947 PetscInt stl; 948 949 /* Create l2g map for the rows of the new matrix and index sets for the local MATNEST */ 950 for (i=0,stl=0;i<nr;i++) stl += lr[i]; 951 ierr = PetscMalloc1(stl,&l2gidxs);CHKERRQ(ierr); 952 for (i=0,stl=0;i<nr;i++) { 953 Mat usedmat; 954 Mat_IS *matis; 955 const PetscInt *idxs; 956 957 /* local IS for local NEST */ 958 ierr = ISCreateStride(PETSC_COMM_SELF,lr[i],stl,1,&islrow[i]);CHKERRQ(ierr); 959 960 /* l2gmap */ 961 j = 0; 962 usedmat = nest[i][j]; 963 while (!usedmat && j < nc-1) usedmat = nest[i][++j]; 964 if (!usedmat) SETERRQ(comm,PETSC_ERR_SUP,"Cannot find valid row mat"); 965 966 if (istrans[i*nc+j]) { 967 Mat T; 968 ierr = MatTransposeGetMat(usedmat,&T);CHKERRQ(ierr); 969 usedmat = T; 970 } 971 matis = (Mat_IS*)(usedmat->data); 972 ierr = ISGetIndices(isrow[i],&idxs);CHKERRQ(ierr); 973 if (istrans[i*nc+j]) { 974 ierr = PetscSFBcastBegin(matis->csf,MPIU_INT,idxs,l2gidxs+stl);CHKERRQ(ierr); 975 ierr = PetscSFBcastEnd(matis->csf,MPIU_INT,idxs,l2gidxs+stl);CHKERRQ(ierr); 976 } else { 977 ierr = PetscSFBcastBegin(matis->sf,MPIU_INT,idxs,l2gidxs+stl);CHKERRQ(ierr); 978 ierr = PetscSFBcastEnd(matis->sf,MPIU_INT,idxs,l2gidxs+stl);CHKERRQ(ierr); 979 } 980 ierr = ISRestoreIndices(isrow[i],&idxs);CHKERRQ(ierr); 981 stl += lr[i]; 982 } 983 ierr = ISLocalToGlobalMappingCreate(comm,1,stl,l2gidxs,PETSC_OWN_POINTER,&rl2g);CHKERRQ(ierr); 984 985 /* Create l2g map for columns of the new matrix and index sets for the local MATNEST */ 986 for (i=0,stl=0;i<nc;i++) stl += lc[i]; 987 ierr = PetscMalloc1(stl,&l2gidxs);CHKERRQ(ierr); 988 for (i=0,stl=0;i<nc;i++) { 989 Mat usedmat; 990 Mat_IS *matis; 991 const PetscInt *idxs; 992 993 /* local IS for local NEST */ 994 ierr = ISCreateStride(PETSC_COMM_SELF,lc[i],stl,1,&islcol[i]);CHKERRQ(ierr); 995 996 /* l2gmap */ 997 j = 0; 998 usedmat = nest[j][i]; 999 while (!usedmat && j < nr-1) usedmat = nest[++j][i]; 1000 if (!usedmat) SETERRQ(comm,PETSC_ERR_SUP,"Cannot find valid column mat"); 1001 if (istrans[j*nc+i]) { 1002 Mat T; 1003 ierr = MatTransposeGetMat(usedmat,&T);CHKERRQ(ierr); 1004 usedmat = T; 1005 } 1006 matis = (Mat_IS*)(usedmat->data); 1007 ierr = ISGetIndices(iscol[i],&idxs);CHKERRQ(ierr); 1008 if (istrans[j*nc+i]) { 1009 ierr = PetscSFBcastBegin(matis->sf,MPIU_INT,idxs,l2gidxs+stl);CHKERRQ(ierr); 1010 ierr = PetscSFBcastEnd(matis->sf,MPIU_INT,idxs,l2gidxs+stl);CHKERRQ(ierr); 1011 } else { 1012 ierr = PetscSFBcastBegin(matis->csf,MPIU_INT,idxs,l2gidxs+stl);CHKERRQ(ierr); 1013 ierr = PetscSFBcastEnd(matis->csf,MPIU_INT,idxs,l2gidxs+stl);CHKERRQ(ierr); 1014 } 1015 ierr = ISRestoreIndices(iscol[i],&idxs);CHKERRQ(ierr); 1016 stl += lc[i]; 1017 } 1018 ierr = ISLocalToGlobalMappingCreate(comm,1,stl,l2gidxs,PETSC_OWN_POINTER,&cl2g);CHKERRQ(ierr); 1019 1020 /* Create MATIS */ 1021 ierr = MatCreate(comm,&B);CHKERRQ(ierr); 1022 ierr = MatSetSizes(B,A->rmap->n,A->cmap->n,A->rmap->N,A->cmap->N);CHKERRQ(ierr); 1023 ierr = MatGetBlockSizes(A,&rbs,&cbs);CHKERRQ(ierr); 1024 ierr = MatSetBlockSizes(B,rbs,cbs);CHKERRQ(ierr); 1025 ierr = MatSetType(B,MATIS);CHKERRQ(ierr); 1026 ierr = MatISSetLocalMatType(B,MATNEST);CHKERRQ(ierr); 1027 { /* hack : avoid setup of scatters */ 1028 Mat_IS *matis = (Mat_IS*)(B->data); 1029 matis->islocalref = PETSC_TRUE; 1030 } 1031 ierr = MatSetLocalToGlobalMapping(B,rl2g,cl2g);CHKERRQ(ierr); 1032 ierr = ISLocalToGlobalMappingDestroy(&rl2g);CHKERRQ(ierr); 1033 ierr = ISLocalToGlobalMappingDestroy(&cl2g);CHKERRQ(ierr); 1034 ierr = MatCreateNest(PETSC_COMM_SELF,nr,islrow,nc,islcol,snest,&lA);CHKERRQ(ierr); 1035 ierr = MatNestSetVecType(lA,VECNEST);CHKERRQ(ierr); 1036 for (i=0;i<nr*nc;i++) { 1037 if (istrans[i]) { 1038 ierr = MatDestroy(&snest[i]);CHKERRQ(ierr); 1039 } 1040 } 1041 ierr = MatISSetLocalMat(B,lA);CHKERRQ(ierr); 1042 ierr = MatDestroy(&lA);CHKERRQ(ierr); 1043 { /* hack : setup of scatters done here */ 1044 Mat_IS *matis = (Mat_IS*)(B->data); 1045 1046 matis->islocalref = PETSC_FALSE; 1047 ierr = MatISSetUpScatters_Private(B);CHKERRQ(ierr); 1048 } 1049 ierr = MatAssemblyBegin(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 1050 ierr = MatAssemblyEnd(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 1051 if (reuse == MAT_INPLACE_MATRIX) { 1052 ierr = MatHeaderReplace(A,&B);CHKERRQ(ierr); 1053 } else { 1054 *newmat = B; 1055 } 1056 } else { 1057 if (lreuse) { 1058 ierr = MatISGetLocalMat(*newmat,&lA);CHKERRQ(ierr); 1059 for (i=0;i<nr;i++) { 1060 for (j=0;j<nc;j++) { 1061 if (snest[i*nc+j]) { 1062 ierr = MatNestSetSubMat(lA,i,j,snest[i*nc+j]);CHKERRQ(ierr); 1063 if (istrans[i*nc+j]) { 1064 ierr = MatDestroy(&snest[i*nc+j]);CHKERRQ(ierr); 1065 } 1066 } 1067 } 1068 } 1069 } else { 1070 PetscInt stl; 1071 for (i=0,stl=0;i<nr;i++) { 1072 ierr = ISCreateStride(PETSC_COMM_SELF,lr[i],stl,1,&islrow[i]);CHKERRQ(ierr); 1073 stl += lr[i]; 1074 } 1075 for (i=0,stl=0;i<nc;i++) { 1076 ierr = ISCreateStride(PETSC_COMM_SELF,lc[i],stl,1,&islcol[i]);CHKERRQ(ierr); 1077 stl += lc[i]; 1078 } 1079 ierr = MatCreateNest(PETSC_COMM_SELF,nr,islrow,nc,islcol,snest,&lA);CHKERRQ(ierr); 1080 for (i=0;i<nr*nc;i++) { 1081 if (istrans[i]) { 1082 ierr = MatDestroy(&snest[i]);CHKERRQ(ierr); 1083 } 1084 } 1085 ierr = MatISSetLocalMat(*newmat,lA);CHKERRQ(ierr); 1086 ierr = MatDestroy(&lA);CHKERRQ(ierr); 1087 } 1088 ierr = MatAssemblyBegin(*newmat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 1089 ierr = MatAssemblyEnd(*newmat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 1090 } 1091 1092 /* Create local matrix in MATNEST format */ 1093 convert = PETSC_FALSE; 1094 ierr = PetscOptionsGetBool(NULL,((PetscObject)A)->prefix,"-matis_convert_local_nest",&convert,NULL);CHKERRQ(ierr); 1095 if (convert) { 1096 Mat M; 1097 MatISLocalFields lf; 1098 PetscContainer c; 1099 1100 ierr = MatISGetLocalMat(*newmat,&lA);CHKERRQ(ierr); 1101 ierr = MatConvert(lA,MATAIJ,MAT_INITIAL_MATRIX,&M);CHKERRQ(ierr); 1102 ierr = MatISSetLocalMat(*newmat,M);CHKERRQ(ierr); 1103 ierr = MatDestroy(&M);CHKERRQ(ierr); 1104 1105 /* attach local fields to the matrix */ 1106 ierr = PetscNew(&lf);CHKERRQ(ierr); 1107 ierr = PetscCalloc2(nr,&lf->rf,nc,&lf->cf);CHKERRQ(ierr); 1108 for (i=0;i<nr;i++) { 1109 PetscInt n,st; 1110 1111 ierr = ISGetLocalSize(islrow[i],&n);CHKERRQ(ierr); 1112 ierr = ISStrideGetInfo(islrow[i],&st,NULL);CHKERRQ(ierr); 1113 ierr = ISCreateStride(comm,n,st,1,&lf->rf[i]);CHKERRQ(ierr); 1114 } 1115 for (i=0;i<nc;i++) { 1116 PetscInt n,st; 1117 1118 ierr = ISGetLocalSize(islcol[i],&n);CHKERRQ(ierr); 1119 ierr = ISStrideGetInfo(islcol[i],&st,NULL);CHKERRQ(ierr); 1120 ierr = ISCreateStride(comm,n,st,1,&lf->cf[i]);CHKERRQ(ierr); 1121 } 1122 lf->nr = nr; 1123 lf->nc = nc; 1124 ierr = PetscContainerCreate(PetscObjectComm((PetscObject)(*newmat)),&c);CHKERRQ(ierr); 1125 ierr = PetscContainerSetPointer(c,lf);CHKERRQ(ierr); 1126 ierr = PetscContainerSetUserDestroy(c,MatISContainerDestroyFields_Private);CHKERRQ(ierr); 1127 ierr = PetscObjectCompose((PetscObject)(*newmat),"_convert_nest_lfields",(PetscObject)c);CHKERRQ(ierr); 1128 ierr = PetscContainerDestroy(&c);CHKERRQ(ierr); 1129 } 1130 1131 /* Free workspace */ 1132 for (i=0;i<nr;i++) { 1133 ierr = ISDestroy(&islrow[i]);CHKERRQ(ierr); 1134 } 1135 for (i=0;i<nc;i++) { 1136 ierr = ISDestroy(&islcol[i]);CHKERRQ(ierr); 1137 } 1138 ierr = PetscFree6(isrow,iscol,islrow,islcol,snest,istrans);CHKERRQ(ierr); 1139 ierr = PetscFree2(lr,lc);CHKERRQ(ierr); 1140 PetscFunctionReturn(0); 1141 } 1142 1143 static PetscErrorCode MatDiagonalScale_IS(Mat A, Vec l, Vec r) 1144 { 1145 Mat_IS *matis = (Mat_IS*)A->data; 1146 Vec ll,rr; 1147 const PetscScalar *Y,*X; 1148 PetscScalar *x,*y; 1149 PetscErrorCode ierr; 1150 1151 PetscFunctionBegin; 1152 if (l) { 1153 ll = matis->y; 1154 ierr = VecGetArrayRead(l,&Y);CHKERRQ(ierr); 1155 ierr = VecGetArray(ll,&y);CHKERRQ(ierr); 1156 ierr = PetscSFBcastBegin(matis->sf,MPIU_SCALAR,Y,y);CHKERRQ(ierr); 1157 } else { 1158 ll = NULL; 1159 } 1160 if (r) { 1161 rr = matis->x; 1162 ierr = VecGetArrayRead(r,&X);CHKERRQ(ierr); 1163 ierr = VecGetArray(rr,&x);CHKERRQ(ierr); 1164 ierr = PetscSFBcastBegin(matis->csf,MPIU_SCALAR,X,x);CHKERRQ(ierr); 1165 } else { 1166 rr = NULL; 1167 } 1168 if (ll) { 1169 ierr = PetscSFBcastEnd(matis->sf,MPIU_SCALAR,Y,y);CHKERRQ(ierr); 1170 ierr = VecRestoreArrayRead(l,&Y);CHKERRQ(ierr); 1171 ierr = VecRestoreArray(ll,&y);CHKERRQ(ierr); 1172 } 1173 if (rr) { 1174 ierr = PetscSFBcastEnd(matis->csf,MPIU_SCALAR,X,x);CHKERRQ(ierr); 1175 ierr = VecRestoreArrayRead(r,&X);CHKERRQ(ierr); 1176 ierr = VecRestoreArray(rr,&x);CHKERRQ(ierr); 1177 } 1178 ierr = MatDiagonalScale(matis->A,ll,rr);CHKERRQ(ierr); 1179 PetscFunctionReturn(0); 1180 } 1181 1182 static PetscErrorCode MatGetInfo_IS(Mat A,MatInfoType flag,MatInfo *ginfo) 1183 { 1184 Mat_IS *matis = (Mat_IS*)A->data; 1185 MatInfo info; 1186 PetscReal isend[6],irecv[6]; 1187 PetscInt bs; 1188 PetscErrorCode ierr; 1189 1190 PetscFunctionBegin; 1191 ierr = MatGetBlockSize(A,&bs);CHKERRQ(ierr); 1192 if (matis->A->ops->getinfo) { 1193 ierr = MatGetInfo(matis->A,MAT_LOCAL,&info);CHKERRQ(ierr); 1194 isend[0] = info.nz_used; 1195 isend[1] = info.nz_allocated; 1196 isend[2] = info.nz_unneeded; 1197 isend[3] = info.memory; 1198 isend[4] = info.mallocs; 1199 } else { 1200 isend[0] = 0.; 1201 isend[1] = 0.; 1202 isend[2] = 0.; 1203 isend[3] = 0.; 1204 isend[4] = 0.; 1205 } 1206 isend[5] = matis->A->num_ass; 1207 if (flag == MAT_LOCAL) { 1208 ginfo->nz_used = isend[0]; 1209 ginfo->nz_allocated = isend[1]; 1210 ginfo->nz_unneeded = isend[2]; 1211 ginfo->memory = isend[3]; 1212 ginfo->mallocs = isend[4]; 1213 ginfo->assemblies = isend[5]; 1214 } else if (flag == MAT_GLOBAL_MAX) { 1215 ierr = MPIU_Allreduce(isend,irecv,6,MPIU_REAL,MPIU_MAX,PetscObjectComm((PetscObject)A));CHKERRQ(ierr); 1216 1217 ginfo->nz_used = irecv[0]; 1218 ginfo->nz_allocated = irecv[1]; 1219 ginfo->nz_unneeded = irecv[2]; 1220 ginfo->memory = irecv[3]; 1221 ginfo->mallocs = irecv[4]; 1222 ginfo->assemblies = irecv[5]; 1223 } else if (flag == MAT_GLOBAL_SUM) { 1224 ierr = MPIU_Allreduce(isend,irecv,5,MPIU_REAL,MPIU_SUM,PetscObjectComm((PetscObject)A));CHKERRQ(ierr); 1225 1226 ginfo->nz_used = irecv[0]; 1227 ginfo->nz_allocated = irecv[1]; 1228 ginfo->nz_unneeded = irecv[2]; 1229 ginfo->memory = irecv[3]; 1230 ginfo->mallocs = irecv[4]; 1231 ginfo->assemblies = A->num_ass; 1232 } 1233 ginfo->block_size = bs; 1234 ginfo->fill_ratio_given = 0; 1235 ginfo->fill_ratio_needed = 0; 1236 ginfo->factor_mallocs = 0; 1237 PetscFunctionReturn(0); 1238 } 1239 1240 PetscErrorCode MatTranspose_IS(Mat A,MatReuse reuse,Mat *B) 1241 { 1242 Mat C,lC,lA; 1243 PetscErrorCode ierr; 1244 1245 PetscFunctionBegin; 1246 if (reuse == MAT_INITIAL_MATRIX || reuse == MAT_INPLACE_MATRIX) { 1247 ISLocalToGlobalMapping rl2g,cl2g; 1248 ierr = MatCreate(PetscObjectComm((PetscObject)A),&C);CHKERRQ(ierr); 1249 ierr = MatSetSizes(C,A->cmap->n,A->rmap->n,A->cmap->N,A->rmap->N);CHKERRQ(ierr); 1250 ierr = MatSetBlockSizes(C,PetscAbs(A->cmap->bs),PetscAbs(A->rmap->bs));CHKERRQ(ierr); 1251 ierr = MatSetType(C,MATIS);CHKERRQ(ierr); 1252 ierr = MatGetLocalToGlobalMapping(A,&rl2g,&cl2g);CHKERRQ(ierr); 1253 ierr = MatSetLocalToGlobalMapping(C,cl2g,rl2g);CHKERRQ(ierr); 1254 } else { 1255 C = *B; 1256 } 1257 1258 /* perform local transposition */ 1259 ierr = MatISGetLocalMat(A,&lA);CHKERRQ(ierr); 1260 ierr = MatTranspose(lA,MAT_INITIAL_MATRIX,&lC);CHKERRQ(ierr); 1261 ierr = MatISSetLocalMat(C,lC);CHKERRQ(ierr); 1262 ierr = MatDestroy(&lC);CHKERRQ(ierr); 1263 1264 if (reuse == MAT_INITIAL_MATRIX || reuse == MAT_REUSE_MATRIX) { 1265 *B = C; 1266 } else { 1267 ierr = MatHeaderMerge(A,&C);CHKERRQ(ierr); 1268 } 1269 ierr = MatAssemblyBegin(*B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 1270 ierr = MatAssemblyEnd(*B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 1271 PetscFunctionReturn(0); 1272 } 1273 1274 PetscErrorCode MatDiagonalSet_IS(Mat A,Vec D,InsertMode insmode) 1275 { 1276 Mat_IS *is = (Mat_IS*)A->data; 1277 PetscErrorCode ierr; 1278 1279 PetscFunctionBegin; 1280 if (D) { /* MatShift_IS pass D = NULL */ 1281 ierr = VecScatterBegin(is->rctx,D,is->y,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 1282 ierr = VecScatterEnd(is->rctx,D,is->y,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 1283 } 1284 ierr = VecPointwiseDivide(is->y,is->y,is->counter);CHKERRQ(ierr); 1285 ierr = MatDiagonalSet(is->A,is->y,insmode);CHKERRQ(ierr); 1286 PetscFunctionReturn(0); 1287 } 1288 1289 PetscErrorCode MatShift_IS(Mat A,PetscScalar a) 1290 { 1291 Mat_IS *is = (Mat_IS*)A->data; 1292 PetscErrorCode ierr; 1293 1294 PetscFunctionBegin; 1295 ierr = VecSet(is->y,a);CHKERRQ(ierr); 1296 ierr = MatDiagonalSet_IS(A,NULL,ADD_VALUES);CHKERRQ(ierr); 1297 PetscFunctionReturn(0); 1298 } 1299 1300 static PetscErrorCode MatSetValuesLocal_SubMat_IS(Mat A,PetscInt m,const PetscInt *rows, PetscInt n,const PetscInt *cols,const PetscScalar *values,InsertMode addv) 1301 { 1302 PetscErrorCode ierr; 1303 PetscInt rows_l[MATIS_MAX_ENTRIES_INSERTION],cols_l[MATIS_MAX_ENTRIES_INSERTION]; 1304 1305 PetscFunctionBegin; 1306 #if defined(PETSC_USE_DEBUG) 1307 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); 1308 #endif 1309 ierr = ISLocalToGlobalMappingApply(A->rmap->mapping,m,rows,rows_l);CHKERRQ(ierr); 1310 ierr = ISLocalToGlobalMappingApply(A->cmap->mapping,n,cols,cols_l);CHKERRQ(ierr); 1311 ierr = MatSetValuesLocal_IS(A,m,rows_l,n,cols_l,values,addv);CHKERRQ(ierr); 1312 PetscFunctionReturn(0); 1313 } 1314 1315 static PetscErrorCode MatSetValuesBlockedLocal_SubMat_IS(Mat A,PetscInt m,const PetscInt *rows, PetscInt n,const PetscInt *cols,const PetscScalar *values,InsertMode addv) 1316 { 1317 PetscErrorCode ierr; 1318 PetscInt rows_l[MATIS_MAX_ENTRIES_INSERTION],cols_l[MATIS_MAX_ENTRIES_INSERTION]; 1319 1320 PetscFunctionBegin; 1321 #if defined(PETSC_USE_DEBUG) 1322 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); 1323 #endif 1324 ierr = ISLocalToGlobalMappingApplyBlock(A->rmap->mapping,m,rows,rows_l);CHKERRQ(ierr); 1325 ierr = ISLocalToGlobalMappingApplyBlock(A->cmap->mapping,n,cols,cols_l);CHKERRQ(ierr); 1326 ierr = MatSetValuesBlockedLocal_IS(A,m,rows_l,n,cols_l,values,addv);CHKERRQ(ierr); 1327 PetscFunctionReturn(0); 1328 } 1329 1330 static PetscErrorCode MatCreateSubMatrix_IS(Mat mat,IS irow,IS icol,MatReuse scall,Mat *newmat) 1331 { 1332 Mat locmat,newlocmat; 1333 Mat_IS *newmatis; 1334 #if defined(PETSC_USE_DEBUG) 1335 Vec rtest,ltest; 1336 const PetscScalar *array; 1337 #endif 1338 const PetscInt *idxs; 1339 PetscInt i,m,n; 1340 PetscErrorCode ierr; 1341 1342 PetscFunctionBegin; 1343 if (scall == MAT_REUSE_MATRIX) { 1344 PetscBool ismatis; 1345 1346 ierr = PetscObjectTypeCompare((PetscObject)*newmat,MATIS,&ismatis);CHKERRQ(ierr); 1347 if (!ismatis) SETERRQ(PetscObjectComm((PetscObject)*newmat),PETSC_ERR_ARG_WRONG,"Cannot reuse matrix! Not of MATIS type"); 1348 newmatis = (Mat_IS*)(*newmat)->data; 1349 if (!newmatis->getsub_ris) SETERRQ(PetscObjectComm((PetscObject)*newmat),PETSC_ERR_ARG_WRONG,"Cannot reuse matrix! Misses local row IS"); 1350 if (!newmatis->getsub_cis) SETERRQ(PetscObjectComm((PetscObject)*newmat),PETSC_ERR_ARG_WRONG,"Cannot reuse matrix! Misses local col IS"); 1351 } 1352 /* irow and icol may not have duplicate entries */ 1353 #if defined(PETSC_USE_DEBUG) 1354 ierr = MatCreateVecs(mat,<est,&rtest);CHKERRQ(ierr); 1355 ierr = ISGetLocalSize(irow,&n);CHKERRQ(ierr); 1356 ierr = ISGetIndices(irow,&idxs);CHKERRQ(ierr); 1357 for (i=0;i<n;i++) { 1358 ierr = VecSetValue(rtest,idxs[i],1.0,ADD_VALUES);CHKERRQ(ierr); 1359 } 1360 ierr = VecAssemblyBegin(rtest);CHKERRQ(ierr); 1361 ierr = VecAssemblyEnd(rtest);CHKERRQ(ierr); 1362 ierr = VecGetLocalSize(rtest,&n);CHKERRQ(ierr); 1363 ierr = VecGetOwnershipRange(rtest,&m,NULL);CHKERRQ(ierr); 1364 ierr = VecGetArrayRead(rtest,&array);CHKERRQ(ierr); 1365 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])); 1366 ierr = VecRestoreArrayRead(rtest,&array);CHKERRQ(ierr); 1367 ierr = ISRestoreIndices(irow,&idxs);CHKERRQ(ierr); 1368 ierr = ISGetLocalSize(icol,&n);CHKERRQ(ierr); 1369 ierr = ISGetIndices(icol,&idxs);CHKERRQ(ierr); 1370 for (i=0;i<n;i++) { 1371 ierr = VecSetValue(ltest,idxs[i],1.0,ADD_VALUES);CHKERRQ(ierr); 1372 } 1373 ierr = VecAssemblyBegin(ltest);CHKERRQ(ierr); 1374 ierr = VecAssemblyEnd(ltest);CHKERRQ(ierr); 1375 ierr = VecGetLocalSize(ltest,&n);CHKERRQ(ierr); 1376 ierr = VecGetOwnershipRange(ltest,&m,NULL);CHKERRQ(ierr); 1377 ierr = VecGetArrayRead(ltest,&array);CHKERRQ(ierr); 1378 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])); 1379 ierr = VecRestoreArrayRead(ltest,&array);CHKERRQ(ierr); 1380 ierr = ISRestoreIndices(icol,&idxs);CHKERRQ(ierr); 1381 ierr = VecDestroy(&rtest);CHKERRQ(ierr); 1382 ierr = VecDestroy(<est);CHKERRQ(ierr); 1383 #endif 1384 if (scall == MAT_INITIAL_MATRIX) { 1385 Mat_IS *matis = (Mat_IS*)mat->data; 1386 ISLocalToGlobalMapping rl2g; 1387 IS is; 1388 PetscInt *lidxs,*lgidxs,*newgidxs; 1389 PetscInt ll,newloc,irbs,icbs,arbs,acbs,rbs,cbs; 1390 PetscBool cong; 1391 MPI_Comm comm; 1392 1393 ierr = PetscObjectGetComm((PetscObject)mat,&comm);CHKERRQ(ierr); 1394 ierr = MatGetBlockSizes(mat,&arbs,&acbs);CHKERRQ(ierr); 1395 ierr = ISGetBlockSize(irow,&irbs);CHKERRQ(ierr); 1396 ierr = ISGetBlockSize(icol,&icbs);CHKERRQ(ierr); 1397 rbs = arbs == irbs ? irbs : 1; 1398 cbs = acbs == icbs ? icbs : 1; 1399 ierr = ISGetLocalSize(irow,&m);CHKERRQ(ierr); 1400 ierr = ISGetLocalSize(icol,&n);CHKERRQ(ierr); 1401 ierr = MatCreate(comm,newmat);CHKERRQ(ierr); 1402 ierr = MatSetType(*newmat,MATIS);CHKERRQ(ierr); 1403 ierr = MatSetSizes(*newmat,m,n,PETSC_DECIDE,PETSC_DECIDE);CHKERRQ(ierr); 1404 ierr = MatSetBlockSizes(*newmat,rbs,cbs);CHKERRQ(ierr); 1405 /* communicate irow to their owners in the layout */ 1406 ierr = ISGetIndices(irow,&idxs);CHKERRQ(ierr); 1407 ierr = PetscLayoutMapLocal(mat->rmap,m,idxs,&ll,&lidxs,&lgidxs);CHKERRQ(ierr); 1408 ierr = ISRestoreIndices(irow,&idxs);CHKERRQ(ierr); 1409 ierr = PetscMemzero(matis->sf_rootdata,matis->sf->nroots*sizeof(PetscInt));CHKERRQ(ierr); 1410 for (i=0;i<ll;i++) matis->sf_rootdata[lidxs[i]] = lgidxs[i]+1; 1411 ierr = PetscFree(lidxs);CHKERRQ(ierr); 1412 ierr = PetscFree(lgidxs);CHKERRQ(ierr); 1413 ierr = PetscSFBcastBegin(matis->sf,MPIU_INT,matis->sf_rootdata,matis->sf_leafdata);CHKERRQ(ierr); 1414 ierr = PetscSFBcastEnd(matis->sf,MPIU_INT,matis->sf_rootdata,matis->sf_leafdata);CHKERRQ(ierr); 1415 for (i=0,newloc=0;i<matis->sf->nleaves;i++) if (matis->sf_leafdata[i]) newloc++; 1416 ierr = PetscMalloc1(newloc,&newgidxs);CHKERRQ(ierr); 1417 ierr = PetscMalloc1(newloc,&lidxs);CHKERRQ(ierr); 1418 for (i=0,newloc=0;i<matis->sf->nleaves;i++) 1419 if (matis->sf_leafdata[i]) { 1420 lidxs[newloc] = i; 1421 newgidxs[newloc++] = matis->sf_leafdata[i]-1; 1422 } 1423 ierr = ISCreateGeneral(comm,newloc,newgidxs,PETSC_OWN_POINTER,&is);CHKERRQ(ierr); 1424 ierr = ISLocalToGlobalMappingCreateIS(is,&rl2g);CHKERRQ(ierr); 1425 ierr = ISLocalToGlobalMappingSetBlockSize(rl2g,rbs);CHKERRQ(ierr); 1426 ierr = ISDestroy(&is);CHKERRQ(ierr); 1427 /* local is to extract local submatrix */ 1428 newmatis = (Mat_IS*)(*newmat)->data; 1429 ierr = ISCreateGeneral(comm,newloc,lidxs,PETSC_OWN_POINTER,&newmatis->getsub_ris);CHKERRQ(ierr); 1430 ierr = MatHasCongruentLayouts(mat,&cong);CHKERRQ(ierr); 1431 if (cong && irow == icol && matis->csf == matis->sf) { 1432 ierr = MatSetLocalToGlobalMapping(*newmat,rl2g,rl2g);CHKERRQ(ierr); 1433 ierr = PetscObjectReference((PetscObject)newmatis->getsub_ris);CHKERRQ(ierr); 1434 newmatis->getsub_cis = newmatis->getsub_ris; 1435 } else { 1436 ISLocalToGlobalMapping cl2g; 1437 1438 /* communicate icol to their owners in the layout */ 1439 ierr = ISGetIndices(icol,&idxs);CHKERRQ(ierr); 1440 ierr = PetscLayoutMapLocal(mat->cmap,n,idxs,&ll,&lidxs,&lgidxs);CHKERRQ(ierr); 1441 ierr = ISRestoreIndices(icol,&idxs);CHKERRQ(ierr); 1442 ierr = PetscMemzero(matis->csf_rootdata,matis->csf->nroots*sizeof(PetscInt));CHKERRQ(ierr); 1443 for (i=0;i<ll;i++) matis->csf_rootdata[lidxs[i]] = lgidxs[i]+1; 1444 ierr = PetscFree(lidxs);CHKERRQ(ierr); 1445 ierr = PetscFree(lgidxs);CHKERRQ(ierr); 1446 ierr = PetscSFBcastBegin(matis->csf,MPIU_INT,matis->csf_rootdata,matis->csf_leafdata);CHKERRQ(ierr); 1447 ierr = PetscSFBcastEnd(matis->csf,MPIU_INT,matis->csf_rootdata,matis->csf_leafdata);CHKERRQ(ierr); 1448 for (i=0,newloc=0;i<matis->csf->nleaves;i++) if (matis->csf_leafdata[i]) newloc++; 1449 ierr = PetscMalloc1(newloc,&newgidxs);CHKERRQ(ierr); 1450 ierr = PetscMalloc1(newloc,&lidxs);CHKERRQ(ierr); 1451 for (i=0,newloc=0;i<matis->csf->nleaves;i++) 1452 if (matis->csf_leafdata[i]) { 1453 lidxs[newloc] = i; 1454 newgidxs[newloc++] = matis->csf_leafdata[i]-1; 1455 } 1456 ierr = ISCreateGeneral(comm,newloc,newgidxs,PETSC_OWN_POINTER,&is);CHKERRQ(ierr); 1457 ierr = ISLocalToGlobalMappingCreateIS(is,&cl2g);CHKERRQ(ierr); 1458 ierr = ISLocalToGlobalMappingSetBlockSize(cl2g,cbs);CHKERRQ(ierr); 1459 ierr = ISDestroy(&is);CHKERRQ(ierr); 1460 /* local is to extract local submatrix */ 1461 ierr = ISCreateGeneral(comm,newloc,lidxs,PETSC_OWN_POINTER,&newmatis->getsub_cis);CHKERRQ(ierr); 1462 ierr = MatSetLocalToGlobalMapping(*newmat,rl2g,cl2g);CHKERRQ(ierr); 1463 ierr = ISLocalToGlobalMappingDestroy(&cl2g);CHKERRQ(ierr); 1464 } 1465 ierr = ISLocalToGlobalMappingDestroy(&rl2g);CHKERRQ(ierr); 1466 } else { 1467 ierr = MatISGetLocalMat(*newmat,&newlocmat);CHKERRQ(ierr); 1468 } 1469 ierr = MatISGetLocalMat(mat,&locmat);CHKERRQ(ierr); 1470 newmatis = (Mat_IS*)(*newmat)->data; 1471 ierr = MatCreateSubMatrix(locmat,newmatis->getsub_ris,newmatis->getsub_cis,scall,&newlocmat);CHKERRQ(ierr); 1472 if (scall == MAT_INITIAL_MATRIX) { 1473 ierr = MatISSetLocalMat(*newmat,newlocmat);CHKERRQ(ierr); 1474 ierr = MatDestroy(&newlocmat);CHKERRQ(ierr); 1475 } 1476 ierr = MatAssemblyBegin(*newmat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 1477 ierr = MatAssemblyEnd(*newmat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 1478 PetscFunctionReturn(0); 1479 } 1480 1481 static PetscErrorCode MatCopy_IS(Mat A,Mat B,MatStructure str) 1482 { 1483 Mat_IS *a = (Mat_IS*)A->data,*b; 1484 PetscBool ismatis; 1485 PetscErrorCode ierr; 1486 1487 PetscFunctionBegin; 1488 ierr = PetscObjectTypeCompare((PetscObject)B,MATIS,&ismatis);CHKERRQ(ierr); 1489 if (!ismatis) SETERRQ(PetscObjectComm((PetscObject)B),PETSC_ERR_SUP,"Need to be implemented"); 1490 b = (Mat_IS*)B->data; 1491 ierr = MatCopy(a->A,b->A,str);CHKERRQ(ierr); 1492 ierr = PetscObjectStateIncrease((PetscObject)B);CHKERRQ(ierr); 1493 PetscFunctionReturn(0); 1494 } 1495 1496 static PetscErrorCode MatMissingDiagonal_IS(Mat A,PetscBool *missing,PetscInt *d) 1497 { 1498 Vec v; 1499 const PetscScalar *array; 1500 PetscInt i,n; 1501 PetscErrorCode ierr; 1502 1503 PetscFunctionBegin; 1504 *missing = PETSC_FALSE; 1505 ierr = MatCreateVecs(A,NULL,&v);CHKERRQ(ierr); 1506 ierr = MatGetDiagonal(A,v);CHKERRQ(ierr); 1507 ierr = VecGetLocalSize(v,&n);CHKERRQ(ierr); 1508 ierr = VecGetArrayRead(v,&array);CHKERRQ(ierr); 1509 for (i=0;i<n;i++) if (array[i] == 0.) break; 1510 ierr = VecRestoreArrayRead(v,&array);CHKERRQ(ierr); 1511 ierr = VecDestroy(&v);CHKERRQ(ierr); 1512 if (i != n) *missing = PETSC_TRUE; 1513 if (d) { 1514 *d = -1; 1515 if (*missing) { 1516 PetscInt rstart; 1517 ierr = MatGetOwnershipRange(A,&rstart,NULL);CHKERRQ(ierr); 1518 *d = i+rstart; 1519 } 1520 } 1521 PetscFunctionReturn(0); 1522 } 1523 1524 static PetscErrorCode MatISSetUpSF_IS(Mat B) 1525 { 1526 Mat_IS *matis = (Mat_IS*)(B->data); 1527 const PetscInt *gidxs; 1528 PetscInt nleaves; 1529 PetscErrorCode ierr; 1530 1531 PetscFunctionBegin; 1532 if (matis->sf) PetscFunctionReturn(0); 1533 ierr = PetscSFCreate(PetscObjectComm((PetscObject)B),&matis->sf);CHKERRQ(ierr); 1534 ierr = ISLocalToGlobalMappingGetIndices(B->rmap->mapping,&gidxs);CHKERRQ(ierr); 1535 ierr = ISLocalToGlobalMappingGetSize(B->rmap->mapping,&nleaves);CHKERRQ(ierr); 1536 ierr = PetscSFSetGraphLayout(matis->sf,B->rmap,nleaves,NULL,PETSC_OWN_POINTER,gidxs);CHKERRQ(ierr); 1537 ierr = ISLocalToGlobalMappingRestoreIndices(B->rmap->mapping,&gidxs);CHKERRQ(ierr); 1538 ierr = PetscMalloc2(matis->sf->nroots,&matis->sf_rootdata,matis->sf->nleaves,&matis->sf_leafdata);CHKERRQ(ierr); 1539 if (B->rmap->mapping != B->cmap->mapping) { /* setup SF for columns */ 1540 ierr = ISLocalToGlobalMappingGetSize(B->cmap->mapping,&nleaves);CHKERRQ(ierr); 1541 ierr = PetscSFCreate(PetscObjectComm((PetscObject)B),&matis->csf);CHKERRQ(ierr); 1542 ierr = ISLocalToGlobalMappingGetIndices(B->cmap->mapping,&gidxs);CHKERRQ(ierr); 1543 ierr = PetscSFSetGraphLayout(matis->csf,B->cmap,nleaves,NULL,PETSC_OWN_POINTER,gidxs);CHKERRQ(ierr); 1544 ierr = ISLocalToGlobalMappingRestoreIndices(B->cmap->mapping,&gidxs);CHKERRQ(ierr); 1545 ierr = PetscMalloc2(matis->csf->nroots,&matis->csf_rootdata,matis->csf->nleaves,&matis->csf_leafdata);CHKERRQ(ierr); 1546 } else { 1547 matis->csf = matis->sf; 1548 matis->csf_leafdata = matis->sf_leafdata; 1549 matis->csf_rootdata = matis->sf_rootdata; 1550 } 1551 PetscFunctionReturn(0); 1552 } 1553 1554 /*@ 1555 MatISStoreL2L - Store local-to-local operators during the Galerkin process of MatPtAP. 1556 1557 Collective on MPI_Comm 1558 1559 Input Parameters: 1560 + A - the matrix 1561 - store - the boolean flag 1562 1563 Level: advanced 1564 1565 Notes: 1566 1567 .keywords: matrix 1568 1569 .seealso: MatCreate(), MatCreateIS(), MatISSetPreallocation(), MatPtAP() 1570 @*/ 1571 PetscErrorCode MatISStoreL2L(Mat A, PetscBool store) 1572 { 1573 PetscErrorCode ierr; 1574 1575 PetscFunctionBegin; 1576 PetscValidHeaderSpecific(A,MAT_CLASSID,1); 1577 PetscValidType(A,1); 1578 PetscValidLogicalCollectiveBool(A,store,2); 1579 ierr = PetscTryMethod(A,"MatISStoreL2L_C",(Mat,PetscBool),(A,store));CHKERRQ(ierr); 1580 PetscFunctionReturn(0); 1581 } 1582 1583 static PetscErrorCode MatISStoreL2L_IS(Mat A, PetscBool store) 1584 { 1585 Mat_IS *matis = (Mat_IS*)(A->data); 1586 PetscErrorCode ierr; 1587 1588 PetscFunctionBegin; 1589 matis->storel2l = store; 1590 if (!store) { 1591 ierr = PetscObjectCompose((PetscObject)(A),"_MatIS_PtAP_l2l",NULL);CHKERRQ(ierr); 1592 } 1593 PetscFunctionReturn(0); 1594 } 1595 1596 /*@ 1597 MatISFixLocalEmpty - Compress out zero local rows from the local matrices 1598 1599 Collective on MPI_Comm 1600 1601 Input Parameters: 1602 + A - the matrix 1603 - fix - the boolean flag 1604 1605 Level: advanced 1606 1607 Notes: When fix is true, new local matrices and l2g maps are generated during the final assembly process. 1608 1609 .keywords: matrix 1610 1611 .seealso: MatCreate(), MatCreateIS(), MatISSetPreallocation(), MatAssemblyEnd(), MAT_FINAL_ASSEMBLY 1612 @*/ 1613 PetscErrorCode MatISFixLocalEmpty(Mat A, PetscBool fix) 1614 { 1615 PetscErrorCode ierr; 1616 1617 PetscFunctionBegin; 1618 PetscValidHeaderSpecific(A,MAT_CLASSID,1); 1619 PetscValidType(A,1); 1620 PetscValidLogicalCollectiveBool(A,fix,2); 1621 ierr = PetscTryMethod(A,"MatISFixLocalEmpty_C",(Mat,PetscBool),(A,fix));CHKERRQ(ierr); 1622 PetscFunctionReturn(0); 1623 } 1624 1625 static PetscErrorCode MatISFixLocalEmpty_IS(Mat A, PetscBool fix) 1626 { 1627 Mat_IS *matis = (Mat_IS*)(A->data); 1628 1629 PetscFunctionBegin; 1630 matis->locempty = fix; 1631 PetscFunctionReturn(0); 1632 } 1633 1634 /*@ 1635 MatISSetPreallocation - Preallocates memory for a MATIS parallel matrix. 1636 1637 Collective on MPI_Comm 1638 1639 Input Parameters: 1640 + B - the matrix 1641 . d_nz - number of nonzeros per row in DIAGONAL portion of local submatrix 1642 (same value is used for all local rows) 1643 . d_nnz - array containing the number of nonzeros in the various rows of the 1644 DIAGONAL portion of the local submatrix (possibly different for each row) 1645 or NULL, if d_nz is used to specify the nonzero structure. 1646 The size of this array is equal to the number of local rows, i.e 'm'. 1647 For matrices that will be factored, you must leave room for (and set) 1648 the diagonal entry even if it is zero. 1649 . o_nz - number of nonzeros per row in the OFF-DIAGONAL portion of local 1650 submatrix (same value is used for all local rows). 1651 - o_nnz - array containing the number of nonzeros in the various rows of the 1652 OFF-DIAGONAL portion of the local submatrix (possibly different for 1653 each row) or NULL, if o_nz is used to specify the nonzero 1654 structure. The size of this array is equal to the number 1655 of local rows, i.e 'm'. 1656 1657 If the *_nnz parameter is given then the *_nz parameter is ignored 1658 1659 Level: intermediate 1660 1661 Notes: 1662 This function has the same interface as the MPIAIJ preallocation routine in order to simplify the transition 1663 from the asssembled format to the unassembled one. It overestimates the preallocation of MATIS local 1664 matrices; for exact preallocation, the user should set the preallocation directly on local matrix objects. 1665 1666 .keywords: matrix 1667 1668 .seealso: MatCreate(), MatCreateIS(), MatMPIAIJSetPreallocation(), MatISGetLocalMat(), MATIS 1669 @*/ 1670 PetscErrorCode MatISSetPreallocation(Mat B,PetscInt d_nz,const PetscInt d_nnz[],PetscInt o_nz,const PetscInt o_nnz[]) 1671 { 1672 PetscErrorCode ierr; 1673 1674 PetscFunctionBegin; 1675 PetscValidHeaderSpecific(B,MAT_CLASSID,1); 1676 PetscValidType(B,1); 1677 ierr = PetscTryMethod(B,"MatISSetPreallocation_C",(Mat,PetscInt,const PetscInt[],PetscInt,const PetscInt[]),(B,d_nz,d_nnz,o_nz,o_nnz));CHKERRQ(ierr); 1678 PetscFunctionReturn(0); 1679 } 1680 1681 /* this is used by DMDA */ 1682 PETSC_EXTERN PetscErrorCode MatISSetPreallocation_IS(Mat B,PetscInt d_nz,const PetscInt d_nnz[],PetscInt o_nz,const PetscInt o_nnz[]) 1683 { 1684 Mat_IS *matis = (Mat_IS*)(B->data); 1685 PetscInt bs,i,nlocalcols; 1686 PetscErrorCode ierr; 1687 1688 PetscFunctionBegin; 1689 if (!matis->A) SETERRQ(PetscObjectComm((PetscObject)B),PETSC_ERR_SUP,"You should first call MatSetLocalToGlobalMapping"); 1690 1691 if (!d_nnz) for (i=0;i<matis->sf->nroots;i++) matis->sf_rootdata[i] = d_nz; 1692 else for (i=0;i<matis->sf->nroots;i++) matis->sf_rootdata[i] = d_nnz[i]; 1693 1694 if (!o_nnz) for (i=0;i<matis->sf->nroots;i++) matis->sf_rootdata[i] += o_nz; 1695 else for (i=0;i<matis->sf->nroots;i++) matis->sf_rootdata[i] += o_nnz[i]; 1696 1697 ierr = PetscSFBcastBegin(matis->sf,MPIU_INT,matis->sf_rootdata,matis->sf_leafdata);CHKERRQ(ierr); 1698 ierr = MatGetSize(matis->A,NULL,&nlocalcols);CHKERRQ(ierr); 1699 ierr = MatGetBlockSize(matis->A,&bs);CHKERRQ(ierr); 1700 ierr = PetscSFBcastEnd(matis->sf,MPIU_INT,matis->sf_rootdata,matis->sf_leafdata);CHKERRQ(ierr); 1701 1702 for (i=0;i<matis->sf->nleaves;i++) matis->sf_leafdata[i] = PetscMin(matis->sf_leafdata[i],nlocalcols); 1703 ierr = MatSeqAIJSetPreallocation(matis->A,0,matis->sf_leafdata);CHKERRQ(ierr); 1704 #if defined(PETSC_HAVE_HYPRE) 1705 ierr = MatHYPRESetPreallocation(matis->A,0,matis->sf_leafdata,0,NULL);CHKERRQ(ierr); 1706 #endif 1707 1708 for (i=0;i<matis->sf->nleaves/bs;i++) matis->sf_leafdata[i] = matis->sf_leafdata[i*bs]/bs; 1709 ierr = MatSeqBAIJSetPreallocation(matis->A,bs,0,matis->sf_leafdata);CHKERRQ(ierr); 1710 1711 nlocalcols /= bs; 1712 for (i=0;i<matis->sf->nleaves/bs;i++) matis->sf_leafdata[i] = PetscMin(matis->sf_leafdata[i],nlocalcols - i); 1713 ierr = MatSeqSBAIJSetPreallocation(matis->A,bs,0,matis->sf_leafdata);CHKERRQ(ierr); 1714 1715 /* for other matrix types */ 1716 ierr = MatSetUp(matis->A);CHKERRQ(ierr); 1717 PetscFunctionReturn(0); 1718 } 1719 1720 PETSC_EXTERN PetscErrorCode MatISSetMPIXAIJPreallocation_Private(Mat A, Mat B, PetscBool maxreduce) 1721 { 1722 Mat_IS *matis = (Mat_IS*)(A->data); 1723 PetscInt *my_dnz,*my_onz,*dnz,*onz,*mat_ranges,*row_ownership; 1724 const PetscInt *global_indices_r,*global_indices_c; 1725 PetscInt i,j,bs,rows,cols; 1726 PetscInt lrows,lcols; 1727 PetscInt local_rows,local_cols; 1728 PetscMPIInt size; 1729 PetscBool isdense,issbaij; 1730 PetscErrorCode ierr; 1731 1732 PetscFunctionBegin; 1733 ierr = MPI_Comm_size(PetscObjectComm((PetscObject)A),&size);CHKERRQ(ierr); 1734 ierr = MatGetSize(A,&rows,&cols);CHKERRQ(ierr); 1735 ierr = MatGetBlockSize(A,&bs);CHKERRQ(ierr); 1736 ierr = MatGetSize(matis->A,&local_rows,&local_cols);CHKERRQ(ierr); 1737 ierr = PetscObjectTypeCompare((PetscObject)matis->A,MATSEQDENSE,&isdense);CHKERRQ(ierr); 1738 ierr = PetscObjectTypeCompare((PetscObject)matis->A,MATSEQSBAIJ,&issbaij);CHKERRQ(ierr); 1739 ierr = ISLocalToGlobalMappingGetIndices(A->rmap->mapping,&global_indices_r);CHKERRQ(ierr); 1740 if (A->rmap->mapping != A->cmap->mapping) { 1741 ierr = ISLocalToGlobalMappingGetIndices(A->cmap->mapping,&global_indices_c);CHKERRQ(ierr); 1742 } else { 1743 global_indices_c = global_indices_r; 1744 } 1745 1746 if (issbaij) { 1747 ierr = MatGetRowUpperTriangular(matis->A);CHKERRQ(ierr); 1748 } 1749 /* 1750 An SF reduce is needed to sum up properly on shared rows. 1751 Note that generally preallocation is not exact, since it overestimates nonzeros 1752 */ 1753 ierr = MatGetLocalSize(A,&lrows,&lcols);CHKERRQ(ierr); 1754 ierr = MatPreallocateInitialize(PetscObjectComm((PetscObject)A),lrows,lcols,dnz,onz);CHKERRQ(ierr); 1755 /* All processes need to compute entire row ownership */ 1756 ierr = PetscMalloc1(rows,&row_ownership);CHKERRQ(ierr); 1757 ierr = MatGetOwnershipRanges(A,(const PetscInt**)&mat_ranges);CHKERRQ(ierr); 1758 for (i=0;i<size;i++) { 1759 for (j=mat_ranges[i];j<mat_ranges[i+1];j++) { 1760 row_ownership[j] = i; 1761 } 1762 } 1763 ierr = MatGetOwnershipRangesColumn(A,(const PetscInt**)&mat_ranges);CHKERRQ(ierr); 1764 1765 /* 1766 my_dnz and my_onz contains exact contribution to preallocation from each local mat 1767 then, they will be summed up properly. This way, preallocation is always sufficient 1768 */ 1769 ierr = PetscCalloc2(local_rows,&my_dnz,local_rows,&my_onz);CHKERRQ(ierr); 1770 /* preallocation as a MATAIJ */ 1771 if (isdense) { /* special case for dense local matrices */ 1772 for (i=0;i<local_rows;i++) { 1773 PetscInt owner = row_ownership[global_indices_r[i]]; 1774 for (j=0;j<local_cols;j++) { 1775 PetscInt index_col = global_indices_c[j]; 1776 if (index_col > mat_ranges[owner]-1 && index_col < mat_ranges[owner+1] ) { /* diag block */ 1777 my_dnz[i] += 1; 1778 } else { /* offdiag block */ 1779 my_onz[i] += 1; 1780 } 1781 } 1782 } 1783 } else if (matis->A->ops->getrowij) { 1784 const PetscInt *ii,*jj,*jptr; 1785 PetscBool done; 1786 ierr = MatGetRowIJ(matis->A,0,PETSC_FALSE,PETSC_FALSE,&local_rows,&ii,&jj,&done);CHKERRQ(ierr); 1787 if (!done) SETERRQ(PetscObjectComm((PetscObject)(matis->A)),PETSC_ERR_PLIB,"Error in MatGetRowIJ"); 1788 jptr = jj; 1789 for (i=0;i<local_rows;i++) { 1790 PetscInt index_row = global_indices_r[i]; 1791 for (j=0;j<ii[i+1]-ii[i];j++,jptr++) { 1792 PetscInt owner = row_ownership[index_row]; 1793 PetscInt index_col = global_indices_c[*jptr]; 1794 if (index_col > mat_ranges[owner]-1 && index_col < mat_ranges[owner+1] ) { /* diag block */ 1795 my_dnz[i] += 1; 1796 } else { /* offdiag block */ 1797 my_onz[i] += 1; 1798 } 1799 /* same as before, interchanging rows and cols */ 1800 if (issbaij && index_col != index_row) { 1801 owner = row_ownership[index_col]; 1802 if (index_row > mat_ranges[owner]-1 && index_row < mat_ranges[owner+1] ) { 1803 my_dnz[*jptr] += 1; 1804 } else { 1805 my_onz[*jptr] += 1; 1806 } 1807 } 1808 } 1809 } 1810 ierr = MatRestoreRowIJ(matis->A,0,PETSC_FALSE,PETSC_FALSE,&local_rows,&ii,&jj,&done);CHKERRQ(ierr); 1811 if (!done) SETERRQ(PetscObjectComm((PetscObject)(matis->A)),PETSC_ERR_PLIB,"Error in MatRestoreRowIJ"); 1812 } else { /* loop over rows and use MatGetRow */ 1813 for (i=0;i<local_rows;i++) { 1814 const PetscInt *cols; 1815 PetscInt ncols,index_row = global_indices_r[i]; 1816 ierr = MatGetRow(matis->A,i,&ncols,&cols,NULL);CHKERRQ(ierr); 1817 for (j=0;j<ncols;j++) { 1818 PetscInt owner = row_ownership[index_row]; 1819 PetscInt index_col = global_indices_c[cols[j]]; 1820 if (index_col > mat_ranges[owner]-1 && index_col < mat_ranges[owner+1] ) { /* diag block */ 1821 my_dnz[i] += 1; 1822 } else { /* offdiag block */ 1823 my_onz[i] += 1; 1824 } 1825 /* same as before, interchanging rows and cols */ 1826 if (issbaij && index_col != index_row) { 1827 owner = row_ownership[index_col]; 1828 if (index_row > mat_ranges[owner]-1 && index_row < mat_ranges[owner+1] ) { 1829 my_dnz[cols[j]] += 1; 1830 } else { 1831 my_onz[cols[j]] += 1; 1832 } 1833 } 1834 } 1835 ierr = MatRestoreRow(matis->A,i,&ncols,&cols,NULL);CHKERRQ(ierr); 1836 } 1837 } 1838 if (global_indices_c != global_indices_r) { 1839 ierr = ISLocalToGlobalMappingRestoreIndices(A->cmap->mapping,&global_indices_c);CHKERRQ(ierr); 1840 } 1841 ierr = ISLocalToGlobalMappingRestoreIndices(A->rmap->mapping,&global_indices_r);CHKERRQ(ierr); 1842 ierr = PetscFree(row_ownership);CHKERRQ(ierr); 1843 1844 /* Reduce my_dnz and my_onz */ 1845 if (maxreduce) { 1846 ierr = PetscSFReduceBegin(matis->sf,MPIU_INT,my_dnz,dnz,MPI_MAX);CHKERRQ(ierr); 1847 ierr = PetscSFReduceBegin(matis->sf,MPIU_INT,my_onz,onz,MPI_MAX);CHKERRQ(ierr); 1848 ierr = PetscSFReduceEnd(matis->sf,MPIU_INT,my_dnz,dnz,MPI_MAX);CHKERRQ(ierr); 1849 ierr = PetscSFReduceEnd(matis->sf,MPIU_INT,my_onz,onz,MPI_MAX);CHKERRQ(ierr); 1850 } else { 1851 ierr = PetscSFReduceBegin(matis->sf,MPIU_INT,my_dnz,dnz,MPI_SUM);CHKERRQ(ierr); 1852 ierr = PetscSFReduceBegin(matis->sf,MPIU_INT,my_onz,onz,MPI_SUM);CHKERRQ(ierr); 1853 ierr = PetscSFReduceEnd(matis->sf,MPIU_INT,my_dnz,dnz,MPI_SUM);CHKERRQ(ierr); 1854 ierr = PetscSFReduceEnd(matis->sf,MPIU_INT,my_onz,onz,MPI_SUM);CHKERRQ(ierr); 1855 } 1856 ierr = PetscFree2(my_dnz,my_onz);CHKERRQ(ierr); 1857 1858 /* Resize preallocation if overestimated */ 1859 for (i=0;i<lrows;i++) { 1860 dnz[i] = PetscMin(dnz[i],lcols); 1861 onz[i] = PetscMin(onz[i],cols-lcols); 1862 } 1863 1864 /* Set preallocation */ 1865 ierr = MatSeqAIJSetPreallocation(B,0,dnz);CHKERRQ(ierr); 1866 ierr = MatMPIAIJSetPreallocation(B,0,dnz,0,onz);CHKERRQ(ierr); 1867 for (i=0;i<lrows;i+=bs) { 1868 PetscInt b, d = dnz[i],o = onz[i]; 1869 1870 for (b=1;b<bs;b++) { 1871 d = PetscMax(d,dnz[i+b]); 1872 o = PetscMax(o,onz[i+b]); 1873 } 1874 dnz[i/bs] = PetscMin(d/bs + d%bs,lcols/bs); 1875 onz[i/bs] = PetscMin(o/bs + o%bs,(cols-lcols)/bs); 1876 } 1877 ierr = MatSeqBAIJSetPreallocation(B,bs,0,dnz);CHKERRQ(ierr); 1878 ierr = MatMPIBAIJSetPreallocation(B,bs,0,dnz,0,onz);CHKERRQ(ierr); 1879 ierr = MatMPISBAIJSetPreallocation(B,bs,0,dnz,0,onz);CHKERRQ(ierr); 1880 ierr = MatPreallocateFinalize(dnz,onz);CHKERRQ(ierr); 1881 if (issbaij) { 1882 ierr = MatRestoreRowUpperTriangular(matis->A);CHKERRQ(ierr); 1883 } 1884 ierr = MatSetOption(B,MAT_NEW_NONZERO_ALLOCATION_ERR,PETSC_TRUE);CHKERRQ(ierr); 1885 PetscFunctionReturn(0); 1886 } 1887 1888 PETSC_INTERN PetscErrorCode MatConvert_IS_XAIJ(Mat mat, MatType mtype, MatReuse reuse, Mat *M) 1889 { 1890 Mat_IS *matis = (Mat_IS*)(mat->data); 1891 Mat local_mat,MT; 1892 PetscInt rbs,cbs,rows,cols,lrows,lcols; 1893 PetscInt local_rows,local_cols; 1894 PetscBool isseqdense,isseqsbaij,isseqaij,isseqbaij; 1895 #if defined (PETSC_USE_DEBUG) 1896 PetscBool lb[4],bb[4]; 1897 #endif 1898 PetscMPIInt size; 1899 PetscScalar *array; 1900 PetscErrorCode ierr; 1901 1902 PetscFunctionBegin; 1903 ierr = MPI_Comm_size(PetscObjectComm((PetscObject)mat),&size);CHKERRQ(ierr); 1904 if (size == 1 && mat->rmap->N == matis->A->rmap->N && mat->cmap->N == matis->A->cmap->N) { 1905 Mat B; 1906 IS irows = NULL,icols = NULL; 1907 PetscInt rbs,cbs; 1908 1909 ierr = ISLocalToGlobalMappingGetBlockSize(mat->rmap->mapping,&rbs);CHKERRQ(ierr); 1910 ierr = ISLocalToGlobalMappingGetBlockSize(mat->cmap->mapping,&cbs);CHKERRQ(ierr); 1911 if (reuse != MAT_REUSE_MATRIX) { /* check if l2g maps are one-to-one */ 1912 IS rows,cols; 1913 const PetscInt *ridxs,*cidxs; 1914 PetscInt i,nw,*work; 1915 1916 ierr = ISLocalToGlobalMappingGetBlockIndices(mat->rmap->mapping,&ridxs);CHKERRQ(ierr); 1917 ierr = ISLocalToGlobalMappingGetSize(mat->rmap->mapping,&nw);CHKERRQ(ierr); 1918 nw = nw/rbs; 1919 ierr = PetscCalloc1(nw,&work);CHKERRQ(ierr); 1920 for (i=0;i<nw;i++) work[ridxs[i]] += 1; 1921 for (i=0;i<nw;i++) if (!work[i] || work[i] > 1) break; 1922 if (i == nw) { 1923 ierr = ISCreateBlock(PETSC_COMM_SELF,rbs,nw,ridxs,PETSC_USE_POINTER,&rows);CHKERRQ(ierr); 1924 ierr = ISSetPermutation(rows);CHKERRQ(ierr); 1925 ierr = ISInvertPermutation(rows,PETSC_DECIDE,&irows);CHKERRQ(ierr); 1926 ierr = ISDestroy(&rows);CHKERRQ(ierr); 1927 } 1928 ierr = ISLocalToGlobalMappingRestoreBlockIndices(mat->rmap->mapping,&ridxs);CHKERRQ(ierr); 1929 ierr = PetscFree(work);CHKERRQ(ierr); 1930 if (irows && mat->rmap->mapping != mat->cmap->mapping) { 1931 ierr = ISLocalToGlobalMappingGetBlockIndices(mat->cmap->mapping,&cidxs);CHKERRQ(ierr); 1932 ierr = ISLocalToGlobalMappingGetSize(mat->cmap->mapping,&nw);CHKERRQ(ierr); 1933 nw = nw/cbs; 1934 ierr = PetscCalloc1(nw,&work);CHKERRQ(ierr); 1935 for (i=0;i<nw;i++) work[cidxs[i]] += 1; 1936 for (i=0;i<nw;i++) if (!work[i] || work[i] > 1) break; 1937 if (i == nw) { 1938 ierr = ISCreateBlock(PETSC_COMM_SELF,cbs,nw,cidxs,PETSC_USE_POINTER,&cols);CHKERRQ(ierr); 1939 ierr = ISSetPermutation(cols);CHKERRQ(ierr); 1940 ierr = ISInvertPermutation(cols,PETSC_DECIDE,&icols);CHKERRQ(ierr); 1941 ierr = ISDestroy(&cols);CHKERRQ(ierr); 1942 } 1943 ierr = ISLocalToGlobalMappingRestoreBlockIndices(mat->cmap->mapping,&cidxs);CHKERRQ(ierr); 1944 ierr = PetscFree(work);CHKERRQ(ierr); 1945 } else if (irows) { 1946 ierr = PetscObjectReference((PetscObject)irows);CHKERRQ(ierr); 1947 icols = irows; 1948 } 1949 } else { 1950 ierr = PetscObjectQuery((PetscObject)(*M),"_MatIS_IS_XAIJ_irows",(PetscObject*)&irows);CHKERRQ(ierr); 1951 ierr = PetscObjectQuery((PetscObject)(*M),"_MatIS_IS_XAIJ_icols",(PetscObject*)&icols);CHKERRQ(ierr); 1952 if (irows) { ierr = PetscObjectReference((PetscObject)irows);CHKERRQ(ierr); } 1953 if (icols) { ierr = PetscObjectReference((PetscObject)icols);CHKERRQ(ierr); } 1954 } 1955 if (!irows || !icols) { 1956 ierr = ISDestroy(&icols);CHKERRQ(ierr); 1957 ierr = ISDestroy(&irows);CHKERRQ(ierr); 1958 goto general_assembly; 1959 } 1960 ierr = MatConvert(matis->A,(rbs == cbs && rbs > 1) ? MATSEQBAIJ : MATSEQAIJ,MAT_INITIAL_MATRIX,&B);CHKERRQ(ierr); 1961 if (reuse != MAT_INPLACE_MATRIX) { 1962 ierr = MatCreateSubMatrix(B,irows,icols,reuse,M);CHKERRQ(ierr); 1963 ierr = PetscObjectCompose((PetscObject)(*M),"_MatIS_IS_XAIJ_irows",(PetscObject)irows);CHKERRQ(ierr); 1964 ierr = PetscObjectCompose((PetscObject)(*M),"_MatIS_IS_XAIJ_icols",(PetscObject)icols);CHKERRQ(ierr); 1965 } else { 1966 Mat C; 1967 1968 ierr = MatCreateSubMatrix(B,irows,icols,MAT_INITIAL_MATRIX,&C);CHKERRQ(ierr); 1969 ierr = MatHeaderReplace(mat,&C);CHKERRQ(ierr); 1970 } 1971 ierr = MatDestroy(&B);CHKERRQ(ierr); 1972 ierr = ISDestroy(&icols);CHKERRQ(ierr); 1973 ierr = ISDestroy(&irows);CHKERRQ(ierr); 1974 PetscFunctionReturn(0); 1975 } 1976 general_assembly: 1977 ierr = MatGetSize(mat,&rows,&cols);CHKERRQ(ierr); 1978 ierr = ISLocalToGlobalMappingGetBlockSize(mat->rmap->mapping,&rbs);CHKERRQ(ierr); 1979 ierr = ISLocalToGlobalMappingGetBlockSize(mat->cmap->mapping,&cbs);CHKERRQ(ierr); 1980 ierr = MatGetLocalSize(mat,&lrows,&lcols);CHKERRQ(ierr); 1981 ierr = MatGetSize(matis->A,&local_rows,&local_cols);CHKERRQ(ierr); 1982 ierr = PetscObjectTypeCompare((PetscObject)matis->A,MATSEQDENSE,&isseqdense);CHKERRQ(ierr); 1983 ierr = PetscObjectBaseTypeCompare((PetscObject)matis->A,MATSEQAIJ,&isseqaij);CHKERRQ(ierr); 1984 ierr = PetscObjectTypeCompare((PetscObject)matis->A,MATSEQBAIJ,&isseqbaij);CHKERRQ(ierr); 1985 ierr = PetscObjectTypeCompare((PetscObject)matis->A,MATSEQSBAIJ,&isseqsbaij);CHKERRQ(ierr); 1986 if (!isseqdense && !isseqaij && !isseqbaij && !isseqsbaij) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_SUP,"Not for matrix type %s",((PetscObject)(matis->A))->type_name); 1987 #if defined (PETSC_USE_DEBUG) 1988 lb[0] = isseqdense; 1989 lb[1] = isseqaij; 1990 lb[2] = isseqbaij; 1991 lb[3] = isseqsbaij; 1992 ierr = MPIU_Allreduce(lb,bb,4,MPIU_BOOL,MPI_LAND,PetscObjectComm((PetscObject)mat));CHKERRQ(ierr); 1993 if (!bb[0] && !bb[1] && !bb[2] && !bb[3]) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Local matrices must have the same type"); 1994 #endif 1995 1996 if (reuse != MAT_REUSE_MATRIX) { 1997 ierr = MatCreate(PetscObjectComm((PetscObject)mat),&MT);CHKERRQ(ierr); 1998 ierr = MatSetSizes(MT,lrows,lcols,rows,cols);CHKERRQ(ierr); 1999 ierr = MatSetType(MT,mtype);CHKERRQ(ierr); 2000 ierr = MatSetBlockSizes(MT,rbs,cbs);CHKERRQ(ierr); 2001 ierr = MatISSetMPIXAIJPreallocation_Private(mat,MT,PETSC_FALSE);CHKERRQ(ierr); 2002 } else { 2003 PetscInt mrbs,mcbs,mrows,mcols,mlrows,mlcols; 2004 2005 /* some checks */ 2006 MT = *M; 2007 ierr = MatGetBlockSizes(MT,&mrbs,&mcbs);CHKERRQ(ierr); 2008 ierr = MatGetSize(MT,&mrows,&mcols);CHKERRQ(ierr); 2009 ierr = MatGetLocalSize(MT,&mlrows,&mlcols);CHKERRQ(ierr); 2010 if (mrows != rows) SETERRQ2(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse matrix. Wrong number of rows (%d != %d)",rows,mrows); 2011 if (mcols != cols) SETERRQ2(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse matrix. Wrong number of cols (%d != %d)",cols,mcols); 2012 if (mlrows != lrows) SETERRQ2(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse matrix. Wrong number of local rows (%d != %d)",lrows,mlrows); 2013 if (mlcols != lcols) SETERRQ2(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse matrix. Wrong number of local cols (%d != %d)",lcols,mlcols); 2014 if (mrbs != rbs) SETERRQ2(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse matrix. Wrong row block size (%d != %d)",rbs,mrbs); 2015 if (mcbs != cbs) SETERRQ2(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse matrix. Wrong col block size (%d != %d)",cbs,mcbs); 2016 ierr = MatZeroEntries(MT);CHKERRQ(ierr); 2017 } 2018 2019 if (isseqsbaij || isseqbaij) { 2020 ierr = MatConvert(matis->A,MATSEQAIJ,MAT_INITIAL_MATRIX,&local_mat);CHKERRQ(ierr); 2021 isseqaij = PETSC_TRUE; 2022 } else { 2023 ierr = PetscObjectReference((PetscObject)matis->A);CHKERRQ(ierr); 2024 local_mat = matis->A; 2025 } 2026 2027 /* Set values */ 2028 ierr = MatSetLocalToGlobalMapping(MT,mat->rmap->mapping,mat->cmap->mapping);CHKERRQ(ierr); 2029 if (isseqdense) { /* special case for dense local matrices */ 2030 PetscInt i,*dummy; 2031 2032 ierr = PetscMalloc1(PetscMax(local_rows,local_cols),&dummy);CHKERRQ(ierr); 2033 for (i=0;i<PetscMax(local_rows,local_cols);i++) dummy[i] = i; 2034 ierr = MatSetOption(MT,MAT_ROW_ORIENTED,PETSC_FALSE);CHKERRQ(ierr); 2035 ierr = MatDenseGetArray(local_mat,&array);CHKERRQ(ierr); 2036 ierr = MatSetValuesLocal(MT,local_rows,dummy,local_cols,dummy,array,ADD_VALUES);CHKERRQ(ierr); 2037 ierr = MatDenseRestoreArray(local_mat,&array);CHKERRQ(ierr); 2038 ierr = PetscFree(dummy);CHKERRQ(ierr); 2039 } else if (isseqaij) { 2040 const PetscInt *blocks; 2041 PetscInt i,nvtxs,*xadj,*adjncy, nb; 2042 PetscBool done; 2043 2044 ierr = MatGetRowIJ(local_mat,0,PETSC_FALSE,PETSC_FALSE,&nvtxs,(const PetscInt**)&xadj,(const PetscInt**)&adjncy,&done);CHKERRQ(ierr); 2045 if (!done) SETERRQ(PetscObjectComm((PetscObject)local_mat),PETSC_ERR_PLIB,"Error in MatGetRowIJ"); 2046 ierr = MatSeqAIJGetArray(local_mat,&array);CHKERRQ(ierr); 2047 ierr = MatGetVariableBlockSizes(local_mat,&nb,&blocks);CHKERRQ(ierr); 2048 if (nb) { /* speed up assembly for special blocked matrices (used by BDDC) */ 2049 PetscInt sum; 2050 2051 for (i=0,sum=0;i<nb;i++) sum += blocks[i]; 2052 if (sum == nvtxs) { 2053 PetscInt r; 2054 2055 for (i=0,r=0;i<nb;i++) { 2056 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]); 2057 ierr = MatSetValuesLocal(MT,blocks[i],adjncy+xadj[r],blocks[i],adjncy+xadj[r],array+xadj[r],ADD_VALUES);CHKERRQ(ierr); 2058 r += blocks[i]; 2059 } 2060 } else { 2061 for (i=0;i<nvtxs;i++) { 2062 ierr = MatSetValuesLocal(MT,1,&i,xadj[i+1]-xadj[i],adjncy+xadj[i],array+xadj[i],ADD_VALUES);CHKERRQ(ierr); 2063 } 2064 } 2065 } else { 2066 for (i=0;i<nvtxs;i++) { 2067 ierr = MatSetValuesLocal(MT,1,&i,xadj[i+1]-xadj[i],adjncy+xadj[i],array+xadj[i],ADD_VALUES);CHKERRQ(ierr); 2068 } 2069 } 2070 ierr = MatRestoreRowIJ(local_mat,0,PETSC_FALSE,PETSC_FALSE,&nvtxs,(const PetscInt**)&xadj,(const PetscInt**)&adjncy,&done);CHKERRQ(ierr); 2071 if (!done) SETERRQ(PetscObjectComm((PetscObject)local_mat),PETSC_ERR_PLIB,"Error in MatRestoreRowIJ"); 2072 ierr = MatSeqAIJRestoreArray(local_mat,&array);CHKERRQ(ierr); 2073 } else { /* very basic values insertion for all other matrix types */ 2074 PetscInt i; 2075 2076 for (i=0;i<local_rows;i++) { 2077 PetscInt j; 2078 const PetscInt *local_indices_cols; 2079 2080 ierr = MatGetRow(local_mat,i,&j,&local_indices_cols,(const PetscScalar**)&array);CHKERRQ(ierr); 2081 ierr = MatSetValuesLocal(MT,1,&i,j,local_indices_cols,array,ADD_VALUES);CHKERRQ(ierr); 2082 ierr = MatRestoreRow(local_mat,i,&j,&local_indices_cols,(const PetscScalar**)&array);CHKERRQ(ierr); 2083 } 2084 } 2085 ierr = MatAssemblyBegin(MT,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 2086 ierr = MatDestroy(&local_mat);CHKERRQ(ierr); 2087 ierr = MatAssemblyEnd(MT,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 2088 if (isseqdense) { 2089 ierr = MatSetOption(MT,MAT_ROW_ORIENTED,PETSC_TRUE);CHKERRQ(ierr); 2090 } 2091 if (reuse == MAT_INPLACE_MATRIX) { 2092 ierr = MatHeaderReplace(mat,&MT);CHKERRQ(ierr); 2093 } else if (reuse == MAT_INITIAL_MATRIX) { 2094 *M = MT; 2095 } 2096 PetscFunctionReturn(0); 2097 } 2098 2099 /*@ 2100 MatISGetMPIXAIJ - Converts MATIS matrix into a parallel AIJ format 2101 2102 Input Parameter: 2103 . mat - the matrix (should be of type MATIS) 2104 . reuse - either MAT_INITIAL_MATRIX or MAT_REUSE_MATRIX 2105 2106 Output Parameter: 2107 . newmat - the matrix in AIJ format 2108 2109 Level: developer 2110 2111 Notes: 2112 This function has been deprecated and it will be removed in future releases. Update your code to use the MatConvert() interface. 2113 2114 .seealso: MATIS, MatConvert() 2115 @*/ 2116 PetscErrorCode MatISGetMPIXAIJ(Mat mat, MatReuse reuse, Mat *newmat) 2117 { 2118 PetscErrorCode ierr; 2119 2120 PetscFunctionBegin; 2121 PetscValidHeaderSpecific(mat,MAT_CLASSID,1); 2122 PetscValidLogicalCollectiveEnum(mat,reuse,2); 2123 PetscValidPointer(newmat,3); 2124 if (reuse == MAT_REUSE_MATRIX) { 2125 PetscValidHeaderSpecific(*newmat,MAT_CLASSID,3); 2126 PetscCheckSameComm(mat,1,*newmat,3); 2127 if (mat == *newmat) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse the same matrix"); 2128 } 2129 ierr = PetscUseMethod(mat,"MatISGetMPIXAIJ_C",(Mat,MatType,MatReuse,Mat*),(mat,MATAIJ,reuse,newmat));CHKERRQ(ierr); 2130 PetscFunctionReturn(0); 2131 } 2132 2133 PetscErrorCode MatDuplicate_IS(Mat mat,MatDuplicateOption op,Mat *newmat) 2134 { 2135 PetscErrorCode ierr; 2136 Mat_IS *matis = (Mat_IS*)(mat->data); 2137 PetscInt rbs,cbs,m,n,M,N; 2138 Mat B,localmat; 2139 2140 PetscFunctionBegin; 2141 ierr = ISLocalToGlobalMappingGetBlockSize(mat->rmap->mapping,&rbs);CHKERRQ(ierr); 2142 ierr = ISLocalToGlobalMappingGetBlockSize(mat->cmap->mapping,&cbs);CHKERRQ(ierr); 2143 ierr = MatGetSize(mat,&M,&N);CHKERRQ(ierr); 2144 ierr = MatGetLocalSize(mat,&m,&n);CHKERRQ(ierr); 2145 ierr = MatCreate(PetscObjectComm((PetscObject)mat),&B);CHKERRQ(ierr); 2146 ierr = MatSetSizes(B,m,n,M,N);CHKERRQ(ierr); 2147 ierr = MatSetBlockSize(B,rbs == cbs ? rbs : 1);CHKERRQ(ierr); 2148 ierr = MatSetType(B,MATIS);CHKERRQ(ierr); 2149 ierr = MatISSetLocalMatType(B,matis->lmattype);CHKERRQ(ierr); 2150 ierr = MatSetLocalToGlobalMapping(B,mat->rmap->mapping,mat->cmap->mapping);CHKERRQ(ierr); 2151 ierr = MatDuplicate(matis->A,op,&localmat);CHKERRQ(ierr); 2152 ierr = MatISSetLocalMat(B,localmat);CHKERRQ(ierr); 2153 ierr = MatDestroy(&localmat);CHKERRQ(ierr); 2154 ierr = MatAssemblyBegin(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 2155 ierr = MatAssemblyEnd(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 2156 *newmat = B; 2157 PetscFunctionReturn(0); 2158 } 2159 2160 static PetscErrorCode MatIsHermitian_IS(Mat A,PetscReal tol,PetscBool *flg) 2161 { 2162 PetscErrorCode ierr; 2163 Mat_IS *matis = (Mat_IS*)A->data; 2164 PetscBool local_sym; 2165 2166 PetscFunctionBegin; 2167 ierr = MatIsHermitian(matis->A,tol,&local_sym);CHKERRQ(ierr); 2168 ierr = MPIU_Allreduce(&local_sym,flg,1,MPIU_BOOL,MPI_LAND,PetscObjectComm((PetscObject)A));CHKERRQ(ierr); 2169 PetscFunctionReturn(0); 2170 } 2171 2172 static PetscErrorCode MatIsSymmetric_IS(Mat A,PetscReal tol,PetscBool *flg) 2173 { 2174 PetscErrorCode ierr; 2175 Mat_IS *matis = (Mat_IS*)A->data; 2176 PetscBool local_sym; 2177 2178 PetscFunctionBegin; 2179 ierr = MatIsSymmetric(matis->A,tol,&local_sym);CHKERRQ(ierr); 2180 ierr = MPIU_Allreduce(&local_sym,flg,1,MPIU_BOOL,MPI_LAND,PetscObjectComm((PetscObject)A));CHKERRQ(ierr); 2181 PetscFunctionReturn(0); 2182 } 2183 2184 static PetscErrorCode MatIsStructurallySymmetric_IS(Mat A,PetscBool *flg) 2185 { 2186 PetscErrorCode ierr; 2187 Mat_IS *matis = (Mat_IS*)A->data; 2188 PetscBool local_sym; 2189 2190 PetscFunctionBegin; 2191 if (A->rmap->mapping != A->cmap->mapping) { 2192 *flg = PETSC_FALSE; 2193 PetscFunctionReturn(0); 2194 } 2195 ierr = MatIsStructurallySymmetric(matis->A,&local_sym);CHKERRQ(ierr); 2196 ierr = MPIU_Allreduce(&local_sym,flg,1,MPIU_BOOL,MPI_LAND,PetscObjectComm((PetscObject)A));CHKERRQ(ierr); 2197 PetscFunctionReturn(0); 2198 } 2199 2200 static PetscErrorCode MatDestroy_IS(Mat A) 2201 { 2202 PetscErrorCode ierr; 2203 Mat_IS *b = (Mat_IS*)A->data; 2204 2205 PetscFunctionBegin; 2206 ierr = PetscFree(b->bdiag);CHKERRQ(ierr); 2207 ierr = PetscFree(b->lmattype);CHKERRQ(ierr); 2208 ierr = MatDestroy(&b->A);CHKERRQ(ierr); 2209 ierr = VecScatterDestroy(&b->cctx);CHKERRQ(ierr); 2210 ierr = VecScatterDestroy(&b->rctx);CHKERRQ(ierr); 2211 ierr = VecDestroy(&b->x);CHKERRQ(ierr); 2212 ierr = VecDestroy(&b->y);CHKERRQ(ierr); 2213 ierr = VecDestroy(&b->counter);CHKERRQ(ierr); 2214 ierr = ISDestroy(&b->getsub_ris);CHKERRQ(ierr); 2215 ierr = ISDestroy(&b->getsub_cis);CHKERRQ(ierr); 2216 if (b->sf != b->csf) { 2217 ierr = PetscSFDestroy(&b->csf);CHKERRQ(ierr); 2218 ierr = PetscFree2(b->csf_rootdata,b->csf_leafdata);CHKERRQ(ierr); 2219 } else b->csf = NULL; 2220 ierr = PetscSFDestroy(&b->sf);CHKERRQ(ierr); 2221 ierr = PetscFree2(b->sf_rootdata,b->sf_leafdata);CHKERRQ(ierr); 2222 ierr = PetscFree(A->data);CHKERRQ(ierr); 2223 ierr = PetscObjectChangeTypeName((PetscObject)A,0);CHKERRQ(ierr); 2224 ierr = PetscObjectComposeFunction((PetscObject)A,"MatISSetLocalMatType_C",NULL);CHKERRQ(ierr); 2225 ierr = PetscObjectComposeFunction((PetscObject)A,"MatISGetLocalMat_C",NULL);CHKERRQ(ierr); 2226 ierr = PetscObjectComposeFunction((PetscObject)A,"MatISSetLocalMat_C",NULL);CHKERRQ(ierr); 2227 ierr = PetscObjectComposeFunction((PetscObject)A,"MatISGetMPIXAIJ_C",NULL);CHKERRQ(ierr); 2228 ierr = PetscObjectComposeFunction((PetscObject)A,"MatISSetPreallocation_C",NULL);CHKERRQ(ierr); 2229 ierr = PetscObjectComposeFunction((PetscObject)A,"MatISStoreL2L_C",NULL);CHKERRQ(ierr); 2230 ierr = PetscObjectComposeFunction((PetscObject)A,"MatISFixLocalEmpty_C",NULL);CHKERRQ(ierr); 2231 ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_is_mpiaij_C",NULL);CHKERRQ(ierr); 2232 ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_is_mpibaij_C",NULL);CHKERRQ(ierr); 2233 ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_is_mpisbaij_C",NULL);CHKERRQ(ierr); 2234 ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_is_seqaij_C",NULL);CHKERRQ(ierr); 2235 ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_is_seqbaij_C",NULL);CHKERRQ(ierr); 2236 ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_is_seqsbaij_C",NULL);CHKERRQ(ierr); 2237 ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_is_aij_C",NULL);CHKERRQ(ierr); 2238 PetscFunctionReturn(0); 2239 } 2240 2241 static PetscErrorCode MatMult_IS(Mat A,Vec x,Vec y) 2242 { 2243 PetscErrorCode ierr; 2244 Mat_IS *is = (Mat_IS*)A->data; 2245 PetscScalar zero = 0.0; 2246 2247 PetscFunctionBegin; 2248 /* scatter the global vector x into the local work vector */ 2249 ierr = VecScatterBegin(is->cctx,x,is->x,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 2250 ierr = VecScatterEnd(is->cctx,x,is->x,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 2251 2252 /* multiply the local matrix */ 2253 ierr = MatMult(is->A,is->x,is->y);CHKERRQ(ierr); 2254 2255 /* scatter product back into global memory */ 2256 ierr = VecSet(y,zero);CHKERRQ(ierr); 2257 ierr = VecScatterBegin(is->rctx,is->y,y,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 2258 ierr = VecScatterEnd(is->rctx,is->y,y,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 2259 PetscFunctionReturn(0); 2260 } 2261 2262 static PetscErrorCode MatMultAdd_IS(Mat A,Vec v1,Vec v2,Vec v3) 2263 { 2264 Vec temp_vec; 2265 PetscErrorCode ierr; 2266 2267 PetscFunctionBegin; /* v3 = v2 + A * v1.*/ 2268 if (v3 != v2) { 2269 ierr = MatMult(A,v1,v3);CHKERRQ(ierr); 2270 ierr = VecAXPY(v3,1.0,v2);CHKERRQ(ierr); 2271 } else { 2272 ierr = VecDuplicate(v2,&temp_vec);CHKERRQ(ierr); 2273 ierr = MatMult(A,v1,temp_vec);CHKERRQ(ierr); 2274 ierr = VecAXPY(temp_vec,1.0,v2);CHKERRQ(ierr); 2275 ierr = VecCopy(temp_vec,v3);CHKERRQ(ierr); 2276 ierr = VecDestroy(&temp_vec);CHKERRQ(ierr); 2277 } 2278 PetscFunctionReturn(0); 2279 } 2280 2281 static PetscErrorCode MatMultTranspose_IS(Mat A,Vec y,Vec x) 2282 { 2283 Mat_IS *is = (Mat_IS*)A->data; 2284 PetscErrorCode ierr; 2285 2286 PetscFunctionBegin; 2287 /* scatter the global vector x into the local work vector */ 2288 ierr = VecScatterBegin(is->rctx,y,is->y,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 2289 ierr = VecScatterEnd(is->rctx,y,is->y,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 2290 2291 /* multiply the local matrix */ 2292 ierr = MatMultTranspose(is->A,is->y,is->x);CHKERRQ(ierr); 2293 2294 /* scatter product back into global vector */ 2295 ierr = VecSet(x,0);CHKERRQ(ierr); 2296 ierr = VecScatterBegin(is->cctx,is->x,x,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 2297 ierr = VecScatterEnd(is->cctx,is->x,x,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 2298 PetscFunctionReturn(0); 2299 } 2300 2301 static PetscErrorCode MatMultTransposeAdd_IS(Mat A,Vec v1,Vec v2,Vec v3) 2302 { 2303 Vec temp_vec; 2304 PetscErrorCode ierr; 2305 2306 PetscFunctionBegin; /* v3 = v2 + A' * v1.*/ 2307 if (v3 != v2) { 2308 ierr = MatMultTranspose(A,v1,v3);CHKERRQ(ierr); 2309 ierr = VecAXPY(v3,1.0,v2);CHKERRQ(ierr); 2310 } else { 2311 ierr = VecDuplicate(v2,&temp_vec);CHKERRQ(ierr); 2312 ierr = MatMultTranspose(A,v1,temp_vec);CHKERRQ(ierr); 2313 ierr = VecAXPY(temp_vec,1.0,v2);CHKERRQ(ierr); 2314 ierr = VecCopy(temp_vec,v3);CHKERRQ(ierr); 2315 ierr = VecDestroy(&temp_vec);CHKERRQ(ierr); 2316 } 2317 PetscFunctionReturn(0); 2318 } 2319 2320 static PetscErrorCode MatView_IS(Mat A,PetscViewer viewer) 2321 { 2322 Mat_IS *a = (Mat_IS*)A->data; 2323 PetscErrorCode ierr; 2324 PetscViewer sviewer; 2325 PetscBool isascii,view = PETSC_TRUE; 2326 2327 PetscFunctionBegin; 2328 ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&isascii);CHKERRQ(ierr); 2329 if (isascii) { 2330 PetscViewerFormat format; 2331 2332 ierr = PetscViewerGetFormat(viewer,&format);CHKERRQ(ierr); 2333 if (format == PETSC_VIEWER_ASCII_INFO) view = PETSC_FALSE; 2334 } 2335 if (!view) PetscFunctionReturn(0); 2336 ierr = PetscViewerGetSubViewer(viewer,PETSC_COMM_SELF,&sviewer);CHKERRQ(ierr); 2337 ierr = MatView(a->A,sviewer);CHKERRQ(ierr); 2338 ierr = PetscViewerRestoreSubViewer(viewer,PETSC_COMM_SELF,&sviewer);CHKERRQ(ierr); 2339 ierr = PetscViewerFlush(viewer);CHKERRQ(ierr); 2340 PetscFunctionReturn(0); 2341 } 2342 2343 static PetscErrorCode MatInvertBlockDiagonal_IS(Mat mat,const PetscScalar **values) 2344 { 2345 Mat_IS *is = (Mat_IS*)mat->data; 2346 MPI_Datatype nodeType; 2347 const PetscScalar *lv; 2348 PetscInt bs; 2349 PetscErrorCode ierr; 2350 2351 PetscFunctionBegin; 2352 ierr = MatGetBlockSize(mat,&bs);CHKERRQ(ierr); 2353 ierr = MatSetBlockSize(is->A,bs);CHKERRQ(ierr); 2354 ierr = MatInvertBlockDiagonal(is->A,&lv);CHKERRQ(ierr); 2355 if (!is->bdiag) { 2356 ierr = PetscMalloc1(bs*mat->rmap->n,&is->bdiag);CHKERRQ(ierr); 2357 } 2358 ierr = MPI_Type_contiguous(bs,MPIU_SCALAR,&nodeType);CHKERRQ(ierr); 2359 ierr = MPI_Type_commit(&nodeType);CHKERRQ(ierr); 2360 ierr = PetscSFReduceBegin(is->sf,nodeType,lv,is->bdiag,MPIU_REPLACE);CHKERRQ(ierr); 2361 ierr = PetscSFReduceEnd(is->sf,nodeType,lv,is->bdiag,MPIU_REPLACE);CHKERRQ(ierr); 2362 ierr = MPI_Type_free(&nodeType);CHKERRQ(ierr); 2363 if (values) *values = is->bdiag; 2364 PetscFunctionReturn(0); 2365 } 2366 2367 static PetscErrorCode MatISSetUpScatters_Private(Mat A) 2368 { 2369 Vec cglobal,rglobal; 2370 IS from; 2371 Mat_IS *is = (Mat_IS*)A->data; 2372 PetscScalar sum; 2373 const PetscInt *garray; 2374 PetscInt nr,rbs,nc,cbs; 2375 PetscBool iscuda; 2376 PetscErrorCode ierr; 2377 2378 PetscFunctionBegin; 2379 ierr = ISLocalToGlobalMappingGetSize(A->rmap->mapping,&nr);CHKERRQ(ierr); 2380 ierr = ISLocalToGlobalMappingGetBlockSize(A->rmap->mapping,&rbs);CHKERRQ(ierr); 2381 ierr = ISLocalToGlobalMappingGetSize(A->cmap->mapping,&nc);CHKERRQ(ierr); 2382 ierr = ISLocalToGlobalMappingGetBlockSize(A->cmap->mapping,&cbs);CHKERRQ(ierr); 2383 ierr = VecDestroy(&is->x);CHKERRQ(ierr); 2384 ierr = VecDestroy(&is->y);CHKERRQ(ierr); 2385 ierr = VecDestroy(&is->counter);CHKERRQ(ierr); 2386 ierr = VecScatterDestroy(&is->rctx);CHKERRQ(ierr); 2387 ierr = VecScatterDestroy(&is->cctx);CHKERRQ(ierr); 2388 ierr = MatCreateVecs(is->A,&is->x,&is->y);CHKERRQ(ierr); 2389 ierr = PetscObjectTypeCompare((PetscObject)is->y,VECSEQCUDA,&iscuda);CHKERRQ(ierr); 2390 if (iscuda) { 2391 ierr = PetscFree(A->defaultvectype);CHKERRQ(ierr); 2392 ierr = PetscStrallocpy(VECCUDA,&A->defaultvectype);CHKERRQ(ierr); 2393 } 2394 ierr = MatCreateVecs(A,&cglobal,&rglobal);CHKERRQ(ierr); 2395 ierr = ISLocalToGlobalMappingGetBlockIndices(A->rmap->mapping,&garray);CHKERRQ(ierr); 2396 ierr = ISCreateBlock(PetscObjectComm((PetscObject)A),rbs,nr/rbs,garray,PETSC_USE_POINTER,&from);CHKERRQ(ierr); 2397 ierr = VecScatterCreate(rglobal,from,is->y,NULL,&is->rctx);CHKERRQ(ierr); 2398 ierr = ISLocalToGlobalMappingRestoreBlockIndices(A->rmap->mapping,&garray);CHKERRQ(ierr); 2399 ierr = ISDestroy(&from);CHKERRQ(ierr); 2400 if (A->rmap->mapping != A->cmap->mapping) { 2401 ierr = ISLocalToGlobalMappingGetBlockIndices(A->cmap->mapping,&garray);CHKERRQ(ierr); 2402 ierr = ISCreateBlock(PetscObjectComm((PetscObject)A),cbs,nc/cbs,garray,PETSC_USE_POINTER,&from);CHKERRQ(ierr); 2403 ierr = VecScatterCreate(cglobal,from,is->x,NULL,&is->cctx);CHKERRQ(ierr); 2404 ierr = ISLocalToGlobalMappingRestoreBlockIndices(A->cmap->mapping,&garray);CHKERRQ(ierr); 2405 ierr = ISDestroy(&from);CHKERRQ(ierr); 2406 } else { 2407 ierr = PetscObjectReference((PetscObject)is->rctx);CHKERRQ(ierr); 2408 is->cctx = is->rctx; 2409 } 2410 ierr = VecDestroy(&cglobal);CHKERRQ(ierr); 2411 2412 /* interface counter vector (local) */ 2413 ierr = VecDuplicate(is->y,&is->counter);CHKERRQ(ierr); 2414 ierr = VecSet(is->y,1.);CHKERRQ(ierr); 2415 ierr = VecScatterBegin(is->rctx,is->y,rglobal,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 2416 ierr = VecScatterEnd(is->rctx,is->y,rglobal,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 2417 ierr = VecScatterBegin(is->rctx,rglobal,is->counter,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 2418 ierr = VecScatterEnd(is->rctx,rglobal,is->counter,INSERT_VALUES,SCATTER_FORWARD);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 = PetscMemcmp(idxs1,idxs2,(nr/rbs)*sizeof(PetscInt),&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 = PetscMemzero(matis->sf_leafdata,nl*sizeof(PetscInt));CHKERRQ(ierr); 2657 ierr = PetscMemzero(matis->sf_rootdata,A->rmap->n*sizeof(PetscInt));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