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 .seealso: MatCreate(), MatCreateIS(), MatISSetPreallocation(), MatPtAP() 1568 @*/ 1569 PetscErrorCode MatISStoreL2L(Mat A, PetscBool store) 1570 { 1571 PetscErrorCode ierr; 1572 1573 PetscFunctionBegin; 1574 PetscValidHeaderSpecific(A,MAT_CLASSID,1); 1575 PetscValidType(A,1); 1576 PetscValidLogicalCollectiveBool(A,store,2); 1577 ierr = PetscTryMethod(A,"MatISStoreL2L_C",(Mat,PetscBool),(A,store));CHKERRQ(ierr); 1578 PetscFunctionReturn(0); 1579 } 1580 1581 static PetscErrorCode MatISStoreL2L_IS(Mat A, PetscBool store) 1582 { 1583 Mat_IS *matis = (Mat_IS*)(A->data); 1584 PetscErrorCode ierr; 1585 1586 PetscFunctionBegin; 1587 matis->storel2l = store; 1588 if (!store) { 1589 ierr = PetscObjectCompose((PetscObject)(A),"_MatIS_PtAP_l2l",NULL);CHKERRQ(ierr); 1590 } 1591 PetscFunctionReturn(0); 1592 } 1593 1594 /*@ 1595 MatISFixLocalEmpty - Compress out zero local rows from the local matrices 1596 1597 Collective on MPI_Comm 1598 1599 Input Parameters: 1600 + A - the matrix 1601 - fix - the boolean flag 1602 1603 Level: advanced 1604 1605 Notes: When fix is true, new local matrices and l2g maps are generated during the final assembly process. 1606 1607 .seealso: MatCreate(), MatCreateIS(), MatISSetPreallocation(), MatAssemblyEnd(), MAT_FINAL_ASSEMBLY 1608 @*/ 1609 PetscErrorCode MatISFixLocalEmpty(Mat A, PetscBool fix) 1610 { 1611 PetscErrorCode ierr; 1612 1613 PetscFunctionBegin; 1614 PetscValidHeaderSpecific(A,MAT_CLASSID,1); 1615 PetscValidType(A,1); 1616 PetscValidLogicalCollectiveBool(A,fix,2); 1617 ierr = PetscTryMethod(A,"MatISFixLocalEmpty_C",(Mat,PetscBool),(A,fix));CHKERRQ(ierr); 1618 PetscFunctionReturn(0); 1619 } 1620 1621 static PetscErrorCode MatISFixLocalEmpty_IS(Mat A, PetscBool fix) 1622 { 1623 Mat_IS *matis = (Mat_IS*)(A->data); 1624 1625 PetscFunctionBegin; 1626 matis->locempty = fix; 1627 PetscFunctionReturn(0); 1628 } 1629 1630 /*@ 1631 MatISSetPreallocation - Preallocates memory for a MATIS parallel matrix. 1632 1633 Collective on MPI_Comm 1634 1635 Input Parameters: 1636 + B - the matrix 1637 . d_nz - number of nonzeros per row in DIAGONAL portion of local submatrix 1638 (same value is used for all local rows) 1639 . d_nnz - array containing the number of nonzeros in the various rows of the 1640 DIAGONAL portion of the local submatrix (possibly different for each row) 1641 or NULL, if d_nz is used to specify the nonzero structure. 1642 The size of this array is equal to the number of local rows, i.e 'm'. 1643 For matrices that will be factored, you must leave room for (and set) 1644 the diagonal entry even if it is zero. 1645 . o_nz - number of nonzeros per row in the OFF-DIAGONAL portion of local 1646 submatrix (same value is used for all local rows). 1647 - o_nnz - array containing the number of nonzeros in the various rows of the 1648 OFF-DIAGONAL portion of the local submatrix (possibly different for 1649 each row) or NULL, if o_nz is used to specify the nonzero 1650 structure. The size of this array is equal to the number 1651 of local rows, i.e 'm'. 1652 1653 If the *_nnz parameter is given then the *_nz parameter is ignored 1654 1655 Level: intermediate 1656 1657 Notes: 1658 This function has the same interface as the MPIAIJ preallocation routine in order to simplify the transition 1659 from the asssembled format to the unassembled one. It overestimates the preallocation of MATIS local 1660 matrices; for exact preallocation, the user should set the preallocation directly on local matrix objects. 1661 1662 .seealso: MatCreate(), MatCreateIS(), MatMPIAIJSetPreallocation(), MatISGetLocalMat(), MATIS 1663 @*/ 1664 PetscErrorCode MatISSetPreallocation(Mat B,PetscInt d_nz,const PetscInt d_nnz[],PetscInt o_nz,const PetscInt o_nnz[]) 1665 { 1666 PetscErrorCode ierr; 1667 1668 PetscFunctionBegin; 1669 PetscValidHeaderSpecific(B,MAT_CLASSID,1); 1670 PetscValidType(B,1); 1671 ierr = PetscTryMethod(B,"MatISSetPreallocation_C",(Mat,PetscInt,const PetscInt[],PetscInt,const PetscInt[]),(B,d_nz,d_nnz,o_nz,o_nnz));CHKERRQ(ierr); 1672 PetscFunctionReturn(0); 1673 } 1674 1675 /* this is used by DMDA */ 1676 PETSC_EXTERN PetscErrorCode MatISSetPreallocation_IS(Mat B,PetscInt d_nz,const PetscInt d_nnz[],PetscInt o_nz,const PetscInt o_nnz[]) 1677 { 1678 Mat_IS *matis = (Mat_IS*)(B->data); 1679 PetscInt bs,i,nlocalcols; 1680 PetscErrorCode ierr; 1681 1682 PetscFunctionBegin; 1683 if (!matis->A) SETERRQ(PetscObjectComm((PetscObject)B),PETSC_ERR_SUP,"You should first call MatSetLocalToGlobalMapping"); 1684 1685 if (!d_nnz) for (i=0;i<matis->sf->nroots;i++) matis->sf_rootdata[i] = d_nz; 1686 else for (i=0;i<matis->sf->nroots;i++) matis->sf_rootdata[i] = d_nnz[i]; 1687 1688 if (!o_nnz) for (i=0;i<matis->sf->nroots;i++) matis->sf_rootdata[i] += o_nz; 1689 else for (i=0;i<matis->sf->nroots;i++) matis->sf_rootdata[i] += o_nnz[i]; 1690 1691 ierr = PetscSFBcastBegin(matis->sf,MPIU_INT,matis->sf_rootdata,matis->sf_leafdata);CHKERRQ(ierr); 1692 ierr = MatGetSize(matis->A,NULL,&nlocalcols);CHKERRQ(ierr); 1693 ierr = MatGetBlockSize(matis->A,&bs);CHKERRQ(ierr); 1694 ierr = PetscSFBcastEnd(matis->sf,MPIU_INT,matis->sf_rootdata,matis->sf_leafdata);CHKERRQ(ierr); 1695 1696 for (i=0;i<matis->sf->nleaves;i++) matis->sf_leafdata[i] = PetscMin(matis->sf_leafdata[i],nlocalcols); 1697 ierr = MatSeqAIJSetPreallocation(matis->A,0,matis->sf_leafdata);CHKERRQ(ierr); 1698 #if defined(PETSC_HAVE_HYPRE) 1699 ierr = MatHYPRESetPreallocation(matis->A,0,matis->sf_leafdata,0,NULL);CHKERRQ(ierr); 1700 #endif 1701 1702 for (i=0;i<matis->sf->nleaves/bs;i++) matis->sf_leafdata[i] = matis->sf_leafdata[i*bs]/bs; 1703 ierr = MatSeqBAIJSetPreallocation(matis->A,bs,0,matis->sf_leafdata);CHKERRQ(ierr); 1704 1705 nlocalcols /= bs; 1706 for (i=0;i<matis->sf->nleaves/bs;i++) matis->sf_leafdata[i] = PetscMin(matis->sf_leafdata[i],nlocalcols - i); 1707 ierr = MatSeqSBAIJSetPreallocation(matis->A,bs,0,matis->sf_leafdata);CHKERRQ(ierr); 1708 1709 /* for other matrix types */ 1710 ierr = MatSetUp(matis->A);CHKERRQ(ierr); 1711 PetscFunctionReturn(0); 1712 } 1713 1714 PETSC_EXTERN PetscErrorCode MatISSetMPIXAIJPreallocation_Private(Mat A, Mat B, PetscBool maxreduce) 1715 { 1716 Mat_IS *matis = (Mat_IS*)(A->data); 1717 PetscInt *my_dnz,*my_onz,*dnz,*onz,*mat_ranges,*row_ownership; 1718 const PetscInt *global_indices_r,*global_indices_c; 1719 PetscInt i,j,bs,rows,cols; 1720 PetscInt lrows,lcols; 1721 PetscInt local_rows,local_cols; 1722 PetscMPIInt size; 1723 PetscBool isdense,issbaij; 1724 PetscErrorCode ierr; 1725 1726 PetscFunctionBegin; 1727 ierr = MPI_Comm_size(PetscObjectComm((PetscObject)A),&size);CHKERRQ(ierr); 1728 ierr = MatGetSize(A,&rows,&cols);CHKERRQ(ierr); 1729 ierr = MatGetBlockSize(A,&bs);CHKERRQ(ierr); 1730 ierr = MatGetSize(matis->A,&local_rows,&local_cols);CHKERRQ(ierr); 1731 ierr = PetscObjectTypeCompare((PetscObject)matis->A,MATSEQDENSE,&isdense);CHKERRQ(ierr); 1732 ierr = PetscObjectTypeCompare((PetscObject)matis->A,MATSEQSBAIJ,&issbaij);CHKERRQ(ierr); 1733 ierr = ISLocalToGlobalMappingGetIndices(A->rmap->mapping,&global_indices_r);CHKERRQ(ierr); 1734 if (A->rmap->mapping != A->cmap->mapping) { 1735 ierr = ISLocalToGlobalMappingGetIndices(A->cmap->mapping,&global_indices_c);CHKERRQ(ierr); 1736 } else { 1737 global_indices_c = global_indices_r; 1738 } 1739 1740 if (issbaij) { 1741 ierr = MatGetRowUpperTriangular(matis->A);CHKERRQ(ierr); 1742 } 1743 /* 1744 An SF reduce is needed to sum up properly on shared rows. 1745 Note that generally preallocation is not exact, since it overestimates nonzeros 1746 */ 1747 ierr = MatGetLocalSize(A,&lrows,&lcols);CHKERRQ(ierr); 1748 ierr = MatPreallocateInitialize(PetscObjectComm((PetscObject)A),lrows,lcols,dnz,onz);CHKERRQ(ierr); 1749 /* All processes need to compute entire row ownership */ 1750 ierr = PetscMalloc1(rows,&row_ownership);CHKERRQ(ierr); 1751 ierr = MatGetOwnershipRanges(A,(const PetscInt**)&mat_ranges);CHKERRQ(ierr); 1752 for (i=0;i<size;i++) { 1753 for (j=mat_ranges[i];j<mat_ranges[i+1];j++) { 1754 row_ownership[j] = i; 1755 } 1756 } 1757 ierr = MatGetOwnershipRangesColumn(A,(const PetscInt**)&mat_ranges);CHKERRQ(ierr); 1758 1759 /* 1760 my_dnz and my_onz contains exact contribution to preallocation from each local mat 1761 then, they will be summed up properly. This way, preallocation is always sufficient 1762 */ 1763 ierr = PetscCalloc2(local_rows,&my_dnz,local_rows,&my_onz);CHKERRQ(ierr); 1764 /* preallocation as a MATAIJ */ 1765 if (isdense) { /* special case for dense local matrices */ 1766 for (i=0;i<local_rows;i++) { 1767 PetscInt owner = row_ownership[global_indices_r[i]]; 1768 for (j=0;j<local_cols;j++) { 1769 PetscInt index_col = global_indices_c[j]; 1770 if (index_col > mat_ranges[owner]-1 && index_col < mat_ranges[owner+1] ) { /* diag block */ 1771 my_dnz[i] += 1; 1772 } else { /* offdiag block */ 1773 my_onz[i] += 1; 1774 } 1775 } 1776 } 1777 } else if (matis->A->ops->getrowij) { 1778 const PetscInt *ii,*jj,*jptr; 1779 PetscBool done; 1780 ierr = MatGetRowIJ(matis->A,0,PETSC_FALSE,PETSC_FALSE,&local_rows,&ii,&jj,&done);CHKERRQ(ierr); 1781 if (!done) SETERRQ(PetscObjectComm((PetscObject)(matis->A)),PETSC_ERR_PLIB,"Error in MatGetRowIJ"); 1782 jptr = jj; 1783 for (i=0;i<local_rows;i++) { 1784 PetscInt index_row = global_indices_r[i]; 1785 for (j=0;j<ii[i+1]-ii[i];j++,jptr++) { 1786 PetscInt owner = row_ownership[index_row]; 1787 PetscInt index_col = global_indices_c[*jptr]; 1788 if (index_col > mat_ranges[owner]-1 && index_col < mat_ranges[owner+1] ) { /* diag block */ 1789 my_dnz[i] += 1; 1790 } else { /* offdiag block */ 1791 my_onz[i] += 1; 1792 } 1793 /* same as before, interchanging rows and cols */ 1794 if (issbaij && index_col != index_row) { 1795 owner = row_ownership[index_col]; 1796 if (index_row > mat_ranges[owner]-1 && index_row < mat_ranges[owner+1] ) { 1797 my_dnz[*jptr] += 1; 1798 } else { 1799 my_onz[*jptr] += 1; 1800 } 1801 } 1802 } 1803 } 1804 ierr = MatRestoreRowIJ(matis->A,0,PETSC_FALSE,PETSC_FALSE,&local_rows,&ii,&jj,&done);CHKERRQ(ierr); 1805 if (!done) SETERRQ(PetscObjectComm((PetscObject)(matis->A)),PETSC_ERR_PLIB,"Error in MatRestoreRowIJ"); 1806 } else { /* loop over rows and use MatGetRow */ 1807 for (i=0;i<local_rows;i++) { 1808 const PetscInt *cols; 1809 PetscInt ncols,index_row = global_indices_r[i]; 1810 ierr = MatGetRow(matis->A,i,&ncols,&cols,NULL);CHKERRQ(ierr); 1811 for (j=0;j<ncols;j++) { 1812 PetscInt owner = row_ownership[index_row]; 1813 PetscInt index_col = global_indices_c[cols[j]]; 1814 if (index_col > mat_ranges[owner]-1 && index_col < mat_ranges[owner+1] ) { /* diag block */ 1815 my_dnz[i] += 1; 1816 } else { /* offdiag block */ 1817 my_onz[i] += 1; 1818 } 1819 /* same as before, interchanging rows and cols */ 1820 if (issbaij && index_col != index_row) { 1821 owner = row_ownership[index_col]; 1822 if (index_row > mat_ranges[owner]-1 && index_row < mat_ranges[owner+1] ) { 1823 my_dnz[cols[j]] += 1; 1824 } else { 1825 my_onz[cols[j]] += 1; 1826 } 1827 } 1828 } 1829 ierr = MatRestoreRow(matis->A,i,&ncols,&cols,NULL);CHKERRQ(ierr); 1830 } 1831 } 1832 if (global_indices_c != global_indices_r) { 1833 ierr = ISLocalToGlobalMappingRestoreIndices(A->cmap->mapping,&global_indices_c);CHKERRQ(ierr); 1834 } 1835 ierr = ISLocalToGlobalMappingRestoreIndices(A->rmap->mapping,&global_indices_r);CHKERRQ(ierr); 1836 ierr = PetscFree(row_ownership);CHKERRQ(ierr); 1837 1838 /* Reduce my_dnz and my_onz */ 1839 if (maxreduce) { 1840 ierr = PetscSFReduceBegin(matis->sf,MPIU_INT,my_dnz,dnz,MPI_MAX);CHKERRQ(ierr); 1841 ierr = PetscSFReduceBegin(matis->sf,MPIU_INT,my_onz,onz,MPI_MAX);CHKERRQ(ierr); 1842 ierr = PetscSFReduceEnd(matis->sf,MPIU_INT,my_dnz,dnz,MPI_MAX);CHKERRQ(ierr); 1843 ierr = PetscSFReduceEnd(matis->sf,MPIU_INT,my_onz,onz,MPI_MAX);CHKERRQ(ierr); 1844 } else { 1845 ierr = PetscSFReduceBegin(matis->sf,MPIU_INT,my_dnz,dnz,MPI_SUM);CHKERRQ(ierr); 1846 ierr = PetscSFReduceBegin(matis->sf,MPIU_INT,my_onz,onz,MPI_SUM);CHKERRQ(ierr); 1847 ierr = PetscSFReduceEnd(matis->sf,MPIU_INT,my_dnz,dnz,MPI_SUM);CHKERRQ(ierr); 1848 ierr = PetscSFReduceEnd(matis->sf,MPIU_INT,my_onz,onz,MPI_SUM);CHKERRQ(ierr); 1849 } 1850 ierr = PetscFree2(my_dnz,my_onz);CHKERRQ(ierr); 1851 1852 /* Resize preallocation if overestimated */ 1853 for (i=0;i<lrows;i++) { 1854 dnz[i] = PetscMin(dnz[i],lcols); 1855 onz[i] = PetscMin(onz[i],cols-lcols); 1856 } 1857 1858 /* Set preallocation */ 1859 ierr = MatSeqAIJSetPreallocation(B,0,dnz);CHKERRQ(ierr); 1860 ierr = MatMPIAIJSetPreallocation(B,0,dnz,0,onz);CHKERRQ(ierr); 1861 for (i=0;i<lrows;i+=bs) { 1862 PetscInt b, d = dnz[i],o = onz[i]; 1863 1864 for (b=1;b<bs;b++) { 1865 d = PetscMax(d,dnz[i+b]); 1866 o = PetscMax(o,onz[i+b]); 1867 } 1868 dnz[i/bs] = PetscMin(d/bs + d%bs,lcols/bs); 1869 onz[i/bs] = PetscMin(o/bs + o%bs,(cols-lcols)/bs); 1870 } 1871 ierr = MatSeqBAIJSetPreallocation(B,bs,0,dnz);CHKERRQ(ierr); 1872 ierr = MatMPIBAIJSetPreallocation(B,bs,0,dnz,0,onz);CHKERRQ(ierr); 1873 ierr = MatMPISBAIJSetPreallocation(B,bs,0,dnz,0,onz);CHKERRQ(ierr); 1874 ierr = MatPreallocateFinalize(dnz,onz);CHKERRQ(ierr); 1875 if (issbaij) { 1876 ierr = MatRestoreRowUpperTriangular(matis->A);CHKERRQ(ierr); 1877 } 1878 ierr = MatSetOption(B,MAT_NEW_NONZERO_ALLOCATION_ERR,PETSC_TRUE);CHKERRQ(ierr); 1879 PetscFunctionReturn(0); 1880 } 1881 1882 PETSC_INTERN PetscErrorCode MatConvert_IS_XAIJ(Mat mat, MatType mtype, MatReuse reuse, Mat *M) 1883 { 1884 Mat_IS *matis = (Mat_IS*)(mat->data); 1885 Mat local_mat,MT; 1886 PetscInt rbs,cbs,rows,cols,lrows,lcols; 1887 PetscInt local_rows,local_cols; 1888 PetscBool isseqdense,isseqsbaij,isseqaij,isseqbaij; 1889 #if defined (PETSC_USE_DEBUG) 1890 PetscBool lb[4],bb[4]; 1891 #endif 1892 PetscMPIInt size; 1893 const PetscScalar *array; 1894 PetscErrorCode ierr; 1895 1896 PetscFunctionBegin; 1897 ierr = MPI_Comm_size(PetscObjectComm((PetscObject)mat),&size);CHKERRQ(ierr); 1898 if (size == 1 && mat->rmap->N == matis->A->rmap->N && mat->cmap->N == matis->A->cmap->N) { 1899 Mat B; 1900 IS irows = NULL,icols = NULL; 1901 PetscInt rbs,cbs; 1902 1903 ierr = ISLocalToGlobalMappingGetBlockSize(mat->rmap->mapping,&rbs);CHKERRQ(ierr); 1904 ierr = ISLocalToGlobalMappingGetBlockSize(mat->cmap->mapping,&cbs);CHKERRQ(ierr); 1905 if (reuse != MAT_REUSE_MATRIX) { /* check if l2g maps are one-to-one */ 1906 IS rows,cols; 1907 const PetscInt *ridxs,*cidxs; 1908 PetscInt i,nw,*work; 1909 1910 ierr = ISLocalToGlobalMappingGetBlockIndices(mat->rmap->mapping,&ridxs);CHKERRQ(ierr); 1911 ierr = ISLocalToGlobalMappingGetSize(mat->rmap->mapping,&nw);CHKERRQ(ierr); 1912 nw = nw/rbs; 1913 ierr = PetscCalloc1(nw,&work);CHKERRQ(ierr); 1914 for (i=0;i<nw;i++) work[ridxs[i]] += 1; 1915 for (i=0;i<nw;i++) if (!work[i] || work[i] > 1) break; 1916 if (i == nw) { 1917 ierr = ISCreateBlock(PETSC_COMM_SELF,rbs,nw,ridxs,PETSC_USE_POINTER,&rows);CHKERRQ(ierr); 1918 ierr = ISSetPermutation(rows);CHKERRQ(ierr); 1919 ierr = ISInvertPermutation(rows,PETSC_DECIDE,&irows);CHKERRQ(ierr); 1920 ierr = ISDestroy(&rows);CHKERRQ(ierr); 1921 } 1922 ierr = ISLocalToGlobalMappingRestoreBlockIndices(mat->rmap->mapping,&ridxs);CHKERRQ(ierr); 1923 ierr = PetscFree(work);CHKERRQ(ierr); 1924 if (irows && mat->rmap->mapping != mat->cmap->mapping) { 1925 ierr = ISLocalToGlobalMappingGetBlockIndices(mat->cmap->mapping,&cidxs);CHKERRQ(ierr); 1926 ierr = ISLocalToGlobalMappingGetSize(mat->cmap->mapping,&nw);CHKERRQ(ierr); 1927 nw = nw/cbs; 1928 ierr = PetscCalloc1(nw,&work);CHKERRQ(ierr); 1929 for (i=0;i<nw;i++) work[cidxs[i]] += 1; 1930 for (i=0;i<nw;i++) if (!work[i] || work[i] > 1) break; 1931 if (i == nw) { 1932 ierr = ISCreateBlock(PETSC_COMM_SELF,cbs,nw,cidxs,PETSC_USE_POINTER,&cols);CHKERRQ(ierr); 1933 ierr = ISSetPermutation(cols);CHKERRQ(ierr); 1934 ierr = ISInvertPermutation(cols,PETSC_DECIDE,&icols);CHKERRQ(ierr); 1935 ierr = ISDestroy(&cols);CHKERRQ(ierr); 1936 } 1937 ierr = ISLocalToGlobalMappingRestoreBlockIndices(mat->cmap->mapping,&cidxs);CHKERRQ(ierr); 1938 ierr = PetscFree(work);CHKERRQ(ierr); 1939 } else if (irows) { 1940 ierr = PetscObjectReference((PetscObject)irows);CHKERRQ(ierr); 1941 icols = irows; 1942 } 1943 } else { 1944 ierr = PetscObjectQuery((PetscObject)(*M),"_MatIS_IS_XAIJ_irows",(PetscObject*)&irows);CHKERRQ(ierr); 1945 ierr = PetscObjectQuery((PetscObject)(*M),"_MatIS_IS_XAIJ_icols",(PetscObject*)&icols);CHKERRQ(ierr); 1946 if (irows) { ierr = PetscObjectReference((PetscObject)irows);CHKERRQ(ierr); } 1947 if (icols) { ierr = PetscObjectReference((PetscObject)icols);CHKERRQ(ierr); } 1948 } 1949 if (!irows || !icols) { 1950 ierr = ISDestroy(&icols);CHKERRQ(ierr); 1951 ierr = ISDestroy(&irows);CHKERRQ(ierr); 1952 goto general_assembly; 1953 } 1954 ierr = MatConvert(matis->A,(rbs == cbs && rbs > 1) ? MATSEQBAIJ : MATSEQAIJ,MAT_INITIAL_MATRIX,&B);CHKERRQ(ierr); 1955 if (reuse != MAT_INPLACE_MATRIX) { 1956 ierr = MatCreateSubMatrix(B,irows,icols,reuse,M);CHKERRQ(ierr); 1957 ierr = PetscObjectCompose((PetscObject)(*M),"_MatIS_IS_XAIJ_irows",(PetscObject)irows);CHKERRQ(ierr); 1958 ierr = PetscObjectCompose((PetscObject)(*M),"_MatIS_IS_XAIJ_icols",(PetscObject)icols);CHKERRQ(ierr); 1959 } else { 1960 Mat C; 1961 1962 ierr = MatCreateSubMatrix(B,irows,icols,MAT_INITIAL_MATRIX,&C);CHKERRQ(ierr); 1963 ierr = MatHeaderReplace(mat,&C);CHKERRQ(ierr); 1964 } 1965 ierr = MatDestroy(&B);CHKERRQ(ierr); 1966 ierr = ISDestroy(&icols);CHKERRQ(ierr); 1967 ierr = ISDestroy(&irows);CHKERRQ(ierr); 1968 PetscFunctionReturn(0); 1969 } 1970 general_assembly: 1971 ierr = MatGetSize(mat,&rows,&cols);CHKERRQ(ierr); 1972 ierr = ISLocalToGlobalMappingGetBlockSize(mat->rmap->mapping,&rbs);CHKERRQ(ierr); 1973 ierr = ISLocalToGlobalMappingGetBlockSize(mat->cmap->mapping,&cbs);CHKERRQ(ierr); 1974 ierr = MatGetLocalSize(mat,&lrows,&lcols);CHKERRQ(ierr); 1975 ierr = MatGetSize(matis->A,&local_rows,&local_cols);CHKERRQ(ierr); 1976 ierr = PetscObjectTypeCompare((PetscObject)matis->A,MATSEQDENSE,&isseqdense);CHKERRQ(ierr); 1977 ierr = PetscObjectBaseTypeCompare((PetscObject)matis->A,MATSEQAIJ,&isseqaij);CHKERRQ(ierr); 1978 ierr = PetscObjectTypeCompare((PetscObject)matis->A,MATSEQBAIJ,&isseqbaij);CHKERRQ(ierr); 1979 ierr = PetscObjectTypeCompare((PetscObject)matis->A,MATSEQSBAIJ,&isseqsbaij);CHKERRQ(ierr); 1980 if (!isseqdense && !isseqaij && !isseqbaij && !isseqsbaij) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_SUP,"Not for matrix type %s",((PetscObject)(matis->A))->type_name); 1981 #if defined (PETSC_USE_DEBUG) 1982 lb[0] = isseqdense; 1983 lb[1] = isseqaij; 1984 lb[2] = isseqbaij; 1985 lb[3] = isseqsbaij; 1986 ierr = MPIU_Allreduce(lb,bb,4,MPIU_BOOL,MPI_LAND,PetscObjectComm((PetscObject)mat));CHKERRQ(ierr); 1987 if (!bb[0] && !bb[1] && !bb[2] && !bb[3]) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Local matrices must have the same type"); 1988 #endif 1989 1990 if (reuse != MAT_REUSE_MATRIX) { 1991 ierr = MatCreate(PetscObjectComm((PetscObject)mat),&MT);CHKERRQ(ierr); 1992 ierr = MatSetSizes(MT,lrows,lcols,rows,cols);CHKERRQ(ierr); 1993 ierr = MatSetType(MT,mtype);CHKERRQ(ierr); 1994 ierr = MatSetBlockSizes(MT,rbs,cbs);CHKERRQ(ierr); 1995 ierr = MatISSetMPIXAIJPreallocation_Private(mat,MT,PETSC_FALSE);CHKERRQ(ierr); 1996 } else { 1997 PetscInt mrbs,mcbs,mrows,mcols,mlrows,mlcols; 1998 1999 /* some checks */ 2000 MT = *M; 2001 ierr = MatGetBlockSizes(MT,&mrbs,&mcbs);CHKERRQ(ierr); 2002 ierr = MatGetSize(MT,&mrows,&mcols);CHKERRQ(ierr); 2003 ierr = MatGetLocalSize(MT,&mlrows,&mlcols);CHKERRQ(ierr); 2004 if (mrows != rows) SETERRQ2(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse matrix. Wrong number of rows (%d != %d)",rows,mrows); 2005 if (mcols != cols) SETERRQ2(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse matrix. Wrong number of cols (%d != %d)",cols,mcols); 2006 if (mlrows != lrows) SETERRQ2(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse matrix. Wrong number of local rows (%d != %d)",lrows,mlrows); 2007 if (mlcols != lcols) SETERRQ2(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse matrix. Wrong number of local cols (%d != %d)",lcols,mlcols); 2008 if (mrbs != rbs) SETERRQ2(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse matrix. Wrong row block size (%d != %d)",rbs,mrbs); 2009 if (mcbs != cbs) SETERRQ2(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse matrix. Wrong col block size (%d != %d)",cbs,mcbs); 2010 ierr = MatZeroEntries(MT);CHKERRQ(ierr); 2011 } 2012 2013 if (isseqsbaij || isseqbaij) { 2014 ierr = MatConvert(matis->A,MATSEQAIJ,MAT_INITIAL_MATRIX,&local_mat);CHKERRQ(ierr); 2015 isseqaij = PETSC_TRUE; 2016 } else { 2017 ierr = PetscObjectReference((PetscObject)matis->A);CHKERRQ(ierr); 2018 local_mat = matis->A; 2019 } 2020 2021 /* Set values */ 2022 ierr = MatSetLocalToGlobalMapping(MT,mat->rmap->mapping,mat->cmap->mapping);CHKERRQ(ierr); 2023 if (isseqdense) { /* special case for dense local matrices */ 2024 PetscInt i,*dummy; 2025 2026 ierr = PetscMalloc1(PetscMax(local_rows,local_cols),&dummy);CHKERRQ(ierr); 2027 for (i=0;i<PetscMax(local_rows,local_cols);i++) dummy[i] = i; 2028 ierr = MatSetOption(MT,MAT_ROW_ORIENTED,PETSC_FALSE);CHKERRQ(ierr); 2029 ierr = MatDenseGetArrayRead(local_mat,&array);CHKERRQ(ierr); 2030 ierr = MatSetValuesLocal(MT,local_rows,dummy,local_cols,dummy,array,ADD_VALUES);CHKERRQ(ierr); 2031 ierr = MatDenseRestoreArrayRead(local_mat,&array);CHKERRQ(ierr); 2032 ierr = PetscFree(dummy);CHKERRQ(ierr); 2033 } else if (isseqaij) { 2034 const PetscInt *blocks; 2035 PetscInt i,nvtxs,*xadj,*adjncy, nb; 2036 PetscBool done; 2037 PetscScalar *sarray; 2038 2039 ierr = MatGetRowIJ(local_mat,0,PETSC_FALSE,PETSC_FALSE,&nvtxs,(const PetscInt**)&xadj,(const PetscInt**)&adjncy,&done);CHKERRQ(ierr); 2040 if (!done) SETERRQ(PetscObjectComm((PetscObject)local_mat),PETSC_ERR_PLIB,"Error in MatGetRowIJ"); 2041 ierr = MatSeqAIJGetArray(local_mat,&sarray);CHKERRQ(ierr); 2042 ierr = MatGetVariableBlockSizes(local_mat,&nb,&blocks);CHKERRQ(ierr); 2043 if (nb) { /* speed up assembly for special blocked matrices (used by BDDC) */ 2044 PetscInt sum; 2045 2046 for (i=0,sum=0;i<nb;i++) sum += blocks[i]; 2047 if (sum == nvtxs) { 2048 PetscInt r; 2049 2050 for (i=0,r=0;i<nb;i++) { 2051 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]); 2052 ierr = MatSetValuesLocal(MT,blocks[i],adjncy+xadj[r],blocks[i],adjncy+xadj[r],sarray+xadj[r],ADD_VALUES);CHKERRQ(ierr); 2053 r += blocks[i]; 2054 } 2055 } else { 2056 for (i=0;i<nvtxs;i++) { 2057 ierr = MatSetValuesLocal(MT,1,&i,xadj[i+1]-xadj[i],adjncy+xadj[i],sarray+xadj[i],ADD_VALUES);CHKERRQ(ierr); 2058 } 2059 } 2060 } else { 2061 for (i=0;i<nvtxs;i++) { 2062 ierr = MatSetValuesLocal(MT,1,&i,xadj[i+1]-xadj[i],adjncy+xadj[i],sarray+xadj[i],ADD_VALUES);CHKERRQ(ierr); 2063 } 2064 } 2065 ierr = MatRestoreRowIJ(local_mat,0,PETSC_FALSE,PETSC_FALSE,&nvtxs,(const PetscInt**)&xadj,(const PetscInt**)&adjncy,&done);CHKERRQ(ierr); 2066 if (!done) SETERRQ(PetscObjectComm((PetscObject)local_mat),PETSC_ERR_PLIB,"Error in MatRestoreRowIJ"); 2067 ierr = MatSeqAIJRestoreArray(local_mat,&sarray);CHKERRQ(ierr); 2068 } else { /* very basic values insertion for all other matrix types */ 2069 PetscInt i; 2070 2071 for (i=0;i<local_rows;i++) { 2072 PetscInt j; 2073 const PetscInt *local_indices_cols; 2074 2075 ierr = MatGetRow(local_mat,i,&j,&local_indices_cols,&array);CHKERRQ(ierr); 2076 ierr = MatSetValuesLocal(MT,1,&i,j,local_indices_cols,array,ADD_VALUES);CHKERRQ(ierr); 2077 ierr = MatRestoreRow(local_mat,i,&j,&local_indices_cols,&array);CHKERRQ(ierr); 2078 } 2079 } 2080 ierr = MatAssemblyBegin(MT,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 2081 ierr = MatDestroy(&local_mat);CHKERRQ(ierr); 2082 ierr = MatAssemblyEnd(MT,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 2083 if (isseqdense) { 2084 ierr = MatSetOption(MT,MAT_ROW_ORIENTED,PETSC_TRUE);CHKERRQ(ierr); 2085 } 2086 if (reuse == MAT_INPLACE_MATRIX) { 2087 ierr = MatHeaderReplace(mat,&MT);CHKERRQ(ierr); 2088 } else if (reuse == MAT_INITIAL_MATRIX) { 2089 *M = MT; 2090 } 2091 PetscFunctionReturn(0); 2092 } 2093 2094 /*@ 2095 MatISGetMPIXAIJ - Converts MATIS matrix into a parallel AIJ format 2096 2097 Input Parameter: 2098 . mat - the matrix (should be of type MATIS) 2099 . reuse - either MAT_INITIAL_MATRIX or MAT_REUSE_MATRIX 2100 2101 Output Parameter: 2102 . newmat - the matrix in AIJ format 2103 2104 Level: developer 2105 2106 Notes: 2107 This function has been deprecated and it will be removed in future releases. Update your code to use the MatConvert() interface. 2108 2109 .seealso: MATIS, MatConvert() 2110 @*/ 2111 PetscErrorCode MatISGetMPIXAIJ(Mat mat, MatReuse reuse, Mat *newmat) 2112 { 2113 PetscErrorCode ierr; 2114 2115 PetscFunctionBegin; 2116 PetscValidHeaderSpecific(mat,MAT_CLASSID,1); 2117 PetscValidLogicalCollectiveEnum(mat,reuse,2); 2118 PetscValidPointer(newmat,3); 2119 if (reuse == MAT_REUSE_MATRIX) { 2120 PetscValidHeaderSpecific(*newmat,MAT_CLASSID,3); 2121 PetscCheckSameComm(mat,1,*newmat,3); 2122 if (mat == *newmat) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse the same matrix"); 2123 } 2124 ierr = PetscUseMethod(mat,"MatISGetMPIXAIJ_C",(Mat,MatType,MatReuse,Mat*),(mat,MATAIJ,reuse,newmat));CHKERRQ(ierr); 2125 PetscFunctionReturn(0); 2126 } 2127 2128 PetscErrorCode MatDuplicate_IS(Mat mat,MatDuplicateOption op,Mat *newmat) 2129 { 2130 PetscErrorCode ierr; 2131 Mat_IS *matis = (Mat_IS*)(mat->data); 2132 PetscInt rbs,cbs,m,n,M,N; 2133 Mat B,localmat; 2134 2135 PetscFunctionBegin; 2136 ierr = ISLocalToGlobalMappingGetBlockSize(mat->rmap->mapping,&rbs);CHKERRQ(ierr); 2137 ierr = ISLocalToGlobalMappingGetBlockSize(mat->cmap->mapping,&cbs);CHKERRQ(ierr); 2138 ierr = MatGetSize(mat,&M,&N);CHKERRQ(ierr); 2139 ierr = MatGetLocalSize(mat,&m,&n);CHKERRQ(ierr); 2140 ierr = MatCreate(PetscObjectComm((PetscObject)mat),&B);CHKERRQ(ierr); 2141 ierr = MatSetSizes(B,m,n,M,N);CHKERRQ(ierr); 2142 ierr = MatSetBlockSize(B,rbs == cbs ? rbs : 1);CHKERRQ(ierr); 2143 ierr = MatSetType(B,MATIS);CHKERRQ(ierr); 2144 ierr = MatISSetLocalMatType(B,matis->lmattype);CHKERRQ(ierr); 2145 ierr = MatSetLocalToGlobalMapping(B,mat->rmap->mapping,mat->cmap->mapping);CHKERRQ(ierr); 2146 ierr = MatDuplicate(matis->A,op,&localmat);CHKERRQ(ierr); 2147 ierr = MatISSetLocalMat(B,localmat);CHKERRQ(ierr); 2148 ierr = MatDestroy(&localmat);CHKERRQ(ierr); 2149 ierr = MatAssemblyBegin(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 2150 ierr = MatAssemblyEnd(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 2151 *newmat = B; 2152 PetscFunctionReturn(0); 2153 } 2154 2155 static PetscErrorCode MatIsHermitian_IS(Mat A,PetscReal tol,PetscBool *flg) 2156 { 2157 PetscErrorCode ierr; 2158 Mat_IS *matis = (Mat_IS*)A->data; 2159 PetscBool local_sym; 2160 2161 PetscFunctionBegin; 2162 ierr = MatIsHermitian(matis->A,tol,&local_sym);CHKERRQ(ierr); 2163 ierr = MPIU_Allreduce(&local_sym,flg,1,MPIU_BOOL,MPI_LAND,PetscObjectComm((PetscObject)A));CHKERRQ(ierr); 2164 PetscFunctionReturn(0); 2165 } 2166 2167 static PetscErrorCode MatIsSymmetric_IS(Mat A,PetscReal tol,PetscBool *flg) 2168 { 2169 PetscErrorCode ierr; 2170 Mat_IS *matis = (Mat_IS*)A->data; 2171 PetscBool local_sym; 2172 2173 PetscFunctionBegin; 2174 ierr = MatIsSymmetric(matis->A,tol,&local_sym);CHKERRQ(ierr); 2175 ierr = MPIU_Allreduce(&local_sym,flg,1,MPIU_BOOL,MPI_LAND,PetscObjectComm((PetscObject)A));CHKERRQ(ierr); 2176 PetscFunctionReturn(0); 2177 } 2178 2179 static PetscErrorCode MatIsStructurallySymmetric_IS(Mat A,PetscBool *flg) 2180 { 2181 PetscErrorCode ierr; 2182 Mat_IS *matis = (Mat_IS*)A->data; 2183 PetscBool local_sym; 2184 2185 PetscFunctionBegin; 2186 if (A->rmap->mapping != A->cmap->mapping) { 2187 *flg = PETSC_FALSE; 2188 PetscFunctionReturn(0); 2189 } 2190 ierr = MatIsStructurallySymmetric(matis->A,&local_sym);CHKERRQ(ierr); 2191 ierr = MPIU_Allreduce(&local_sym,flg,1,MPIU_BOOL,MPI_LAND,PetscObjectComm((PetscObject)A));CHKERRQ(ierr); 2192 PetscFunctionReturn(0); 2193 } 2194 2195 static PetscErrorCode MatDestroy_IS(Mat A) 2196 { 2197 PetscErrorCode ierr; 2198 Mat_IS *b = (Mat_IS*)A->data; 2199 2200 PetscFunctionBegin; 2201 ierr = PetscFree(b->bdiag);CHKERRQ(ierr); 2202 ierr = PetscFree(b->lmattype);CHKERRQ(ierr); 2203 ierr = MatDestroy(&b->A);CHKERRQ(ierr); 2204 ierr = VecScatterDestroy(&b->cctx);CHKERRQ(ierr); 2205 ierr = VecScatterDestroy(&b->rctx);CHKERRQ(ierr); 2206 ierr = VecDestroy(&b->x);CHKERRQ(ierr); 2207 ierr = VecDestroy(&b->y);CHKERRQ(ierr); 2208 ierr = VecDestroy(&b->counter);CHKERRQ(ierr); 2209 ierr = ISDestroy(&b->getsub_ris);CHKERRQ(ierr); 2210 ierr = ISDestroy(&b->getsub_cis);CHKERRQ(ierr); 2211 if (b->sf != b->csf) { 2212 ierr = PetscSFDestroy(&b->csf);CHKERRQ(ierr); 2213 ierr = PetscFree2(b->csf_rootdata,b->csf_leafdata);CHKERRQ(ierr); 2214 } else b->csf = NULL; 2215 ierr = PetscSFDestroy(&b->sf);CHKERRQ(ierr); 2216 ierr = PetscFree2(b->sf_rootdata,b->sf_leafdata);CHKERRQ(ierr); 2217 ierr = PetscFree(A->data);CHKERRQ(ierr); 2218 ierr = PetscObjectChangeTypeName((PetscObject)A,0);CHKERRQ(ierr); 2219 ierr = PetscObjectComposeFunction((PetscObject)A,"MatISSetLocalMatType_C",NULL);CHKERRQ(ierr); 2220 ierr = PetscObjectComposeFunction((PetscObject)A,"MatISGetLocalMat_C",NULL);CHKERRQ(ierr); 2221 ierr = PetscObjectComposeFunction((PetscObject)A,"MatISSetLocalMat_C",NULL);CHKERRQ(ierr); 2222 ierr = PetscObjectComposeFunction((PetscObject)A,"MatISGetMPIXAIJ_C",NULL);CHKERRQ(ierr); 2223 ierr = PetscObjectComposeFunction((PetscObject)A,"MatISSetPreallocation_C",NULL);CHKERRQ(ierr); 2224 ierr = PetscObjectComposeFunction((PetscObject)A,"MatISStoreL2L_C",NULL);CHKERRQ(ierr); 2225 ierr = PetscObjectComposeFunction((PetscObject)A,"MatISFixLocalEmpty_C",NULL);CHKERRQ(ierr); 2226 ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_is_mpiaij_C",NULL);CHKERRQ(ierr); 2227 ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_is_mpibaij_C",NULL);CHKERRQ(ierr); 2228 ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_is_mpisbaij_C",NULL);CHKERRQ(ierr); 2229 ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_is_seqaij_C",NULL);CHKERRQ(ierr); 2230 ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_is_seqbaij_C",NULL);CHKERRQ(ierr); 2231 ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_is_seqsbaij_C",NULL);CHKERRQ(ierr); 2232 ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_is_aij_C",NULL);CHKERRQ(ierr); 2233 PetscFunctionReturn(0); 2234 } 2235 2236 static PetscErrorCode MatMult_IS(Mat A,Vec x,Vec y) 2237 { 2238 PetscErrorCode ierr; 2239 Mat_IS *is = (Mat_IS*)A->data; 2240 PetscScalar zero = 0.0; 2241 2242 PetscFunctionBegin; 2243 /* scatter the global vector x into the local work vector */ 2244 ierr = VecScatterBegin(is->cctx,x,is->x,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 2245 ierr = VecScatterEnd(is->cctx,x,is->x,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 2246 2247 /* multiply the local matrix */ 2248 ierr = MatMult(is->A,is->x,is->y);CHKERRQ(ierr); 2249 2250 /* scatter product back into global memory */ 2251 ierr = VecSet(y,zero);CHKERRQ(ierr); 2252 ierr = VecScatterBegin(is->rctx,is->y,y,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 2253 ierr = VecScatterEnd(is->rctx,is->y,y,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 2254 PetscFunctionReturn(0); 2255 } 2256 2257 static PetscErrorCode MatMultAdd_IS(Mat A,Vec v1,Vec v2,Vec v3) 2258 { 2259 Vec temp_vec; 2260 PetscErrorCode ierr; 2261 2262 PetscFunctionBegin; /* v3 = v2 + A * v1.*/ 2263 if (v3 != v2) { 2264 ierr = MatMult(A,v1,v3);CHKERRQ(ierr); 2265 ierr = VecAXPY(v3,1.0,v2);CHKERRQ(ierr); 2266 } else { 2267 ierr = VecDuplicate(v2,&temp_vec);CHKERRQ(ierr); 2268 ierr = MatMult(A,v1,temp_vec);CHKERRQ(ierr); 2269 ierr = VecAXPY(temp_vec,1.0,v2);CHKERRQ(ierr); 2270 ierr = VecCopy(temp_vec,v3);CHKERRQ(ierr); 2271 ierr = VecDestroy(&temp_vec);CHKERRQ(ierr); 2272 } 2273 PetscFunctionReturn(0); 2274 } 2275 2276 static PetscErrorCode MatMultTranspose_IS(Mat A,Vec y,Vec x) 2277 { 2278 Mat_IS *is = (Mat_IS*)A->data; 2279 PetscErrorCode ierr; 2280 2281 PetscFunctionBegin; 2282 /* scatter the global vector x into the local work vector */ 2283 ierr = VecScatterBegin(is->rctx,y,is->y,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 2284 ierr = VecScatterEnd(is->rctx,y,is->y,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 2285 2286 /* multiply the local matrix */ 2287 ierr = MatMultTranspose(is->A,is->y,is->x);CHKERRQ(ierr); 2288 2289 /* scatter product back into global vector */ 2290 ierr = VecSet(x,0);CHKERRQ(ierr); 2291 ierr = VecScatterBegin(is->cctx,is->x,x,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 2292 ierr = VecScatterEnd(is->cctx,is->x,x,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 2293 PetscFunctionReturn(0); 2294 } 2295 2296 static PetscErrorCode MatMultTransposeAdd_IS(Mat A,Vec v1,Vec v2,Vec v3) 2297 { 2298 Vec temp_vec; 2299 PetscErrorCode ierr; 2300 2301 PetscFunctionBegin; /* v3 = v2 + A' * v1.*/ 2302 if (v3 != v2) { 2303 ierr = MatMultTranspose(A,v1,v3);CHKERRQ(ierr); 2304 ierr = VecAXPY(v3,1.0,v2);CHKERRQ(ierr); 2305 } else { 2306 ierr = VecDuplicate(v2,&temp_vec);CHKERRQ(ierr); 2307 ierr = MatMultTranspose(A,v1,temp_vec);CHKERRQ(ierr); 2308 ierr = VecAXPY(temp_vec,1.0,v2);CHKERRQ(ierr); 2309 ierr = VecCopy(temp_vec,v3);CHKERRQ(ierr); 2310 ierr = VecDestroy(&temp_vec);CHKERRQ(ierr); 2311 } 2312 PetscFunctionReturn(0); 2313 } 2314 2315 static PetscErrorCode MatView_IS(Mat A,PetscViewer viewer) 2316 { 2317 Mat_IS *a = (Mat_IS*)A->data; 2318 PetscErrorCode ierr; 2319 PetscViewer sviewer; 2320 PetscBool isascii,view = PETSC_TRUE; 2321 2322 PetscFunctionBegin; 2323 ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&isascii);CHKERRQ(ierr); 2324 if (isascii) { 2325 PetscViewerFormat format; 2326 2327 ierr = PetscViewerGetFormat(viewer,&format);CHKERRQ(ierr); 2328 if (format == PETSC_VIEWER_ASCII_INFO) view = PETSC_FALSE; 2329 } 2330 if (!view) PetscFunctionReturn(0); 2331 ierr = PetscViewerGetSubViewer(viewer,PETSC_COMM_SELF,&sviewer);CHKERRQ(ierr); 2332 ierr = MatView(a->A,sviewer);CHKERRQ(ierr); 2333 ierr = PetscViewerRestoreSubViewer(viewer,PETSC_COMM_SELF,&sviewer);CHKERRQ(ierr); 2334 ierr = PetscViewerFlush(viewer);CHKERRQ(ierr); 2335 PetscFunctionReturn(0); 2336 } 2337 2338 static PetscErrorCode MatInvertBlockDiagonal_IS(Mat mat,const PetscScalar **values) 2339 { 2340 Mat_IS *is = (Mat_IS*)mat->data; 2341 MPI_Datatype nodeType; 2342 const PetscScalar *lv; 2343 PetscInt bs; 2344 PetscErrorCode ierr; 2345 2346 PetscFunctionBegin; 2347 ierr = MatGetBlockSize(mat,&bs);CHKERRQ(ierr); 2348 ierr = MatSetBlockSize(is->A,bs);CHKERRQ(ierr); 2349 ierr = MatInvertBlockDiagonal(is->A,&lv);CHKERRQ(ierr); 2350 if (!is->bdiag) { 2351 ierr = PetscMalloc1(bs*mat->rmap->n,&is->bdiag);CHKERRQ(ierr); 2352 } 2353 ierr = MPI_Type_contiguous(bs,MPIU_SCALAR,&nodeType);CHKERRQ(ierr); 2354 ierr = MPI_Type_commit(&nodeType);CHKERRQ(ierr); 2355 ierr = PetscSFReduceBegin(is->sf,nodeType,lv,is->bdiag,MPIU_REPLACE);CHKERRQ(ierr); 2356 ierr = PetscSFReduceEnd(is->sf,nodeType,lv,is->bdiag,MPIU_REPLACE);CHKERRQ(ierr); 2357 ierr = MPI_Type_free(&nodeType);CHKERRQ(ierr); 2358 if (values) *values = is->bdiag; 2359 PetscFunctionReturn(0); 2360 } 2361 2362 static PetscErrorCode MatISSetUpScatters_Private(Mat A) 2363 { 2364 Vec cglobal,rglobal; 2365 IS from; 2366 Mat_IS *is = (Mat_IS*)A->data; 2367 PetscScalar sum; 2368 const PetscInt *garray; 2369 PetscInt nr,rbs,nc,cbs; 2370 PetscBool iscuda; 2371 PetscErrorCode ierr; 2372 2373 PetscFunctionBegin; 2374 ierr = ISLocalToGlobalMappingGetSize(A->rmap->mapping,&nr);CHKERRQ(ierr); 2375 ierr = ISLocalToGlobalMappingGetBlockSize(A->rmap->mapping,&rbs);CHKERRQ(ierr); 2376 ierr = ISLocalToGlobalMappingGetSize(A->cmap->mapping,&nc);CHKERRQ(ierr); 2377 ierr = ISLocalToGlobalMappingGetBlockSize(A->cmap->mapping,&cbs);CHKERRQ(ierr); 2378 ierr = VecDestroy(&is->x);CHKERRQ(ierr); 2379 ierr = VecDestroy(&is->y);CHKERRQ(ierr); 2380 ierr = VecDestroy(&is->counter);CHKERRQ(ierr); 2381 ierr = VecScatterDestroy(&is->rctx);CHKERRQ(ierr); 2382 ierr = VecScatterDestroy(&is->cctx);CHKERRQ(ierr); 2383 ierr = MatCreateVecs(is->A,&is->x,&is->y);CHKERRQ(ierr); 2384 ierr = PetscObjectTypeCompare((PetscObject)is->y,VECSEQCUDA,&iscuda);CHKERRQ(ierr); 2385 if (iscuda) { 2386 ierr = PetscFree(A->defaultvectype);CHKERRQ(ierr); 2387 ierr = PetscStrallocpy(VECCUDA,&A->defaultvectype);CHKERRQ(ierr); 2388 } 2389 ierr = MatCreateVecs(A,&cglobal,&rglobal);CHKERRQ(ierr); 2390 ierr = ISLocalToGlobalMappingGetBlockIndices(A->rmap->mapping,&garray);CHKERRQ(ierr); 2391 ierr = ISCreateBlock(PetscObjectComm((PetscObject)A),rbs,nr/rbs,garray,PETSC_USE_POINTER,&from);CHKERRQ(ierr); 2392 ierr = VecScatterCreate(rglobal,from,is->y,NULL,&is->rctx);CHKERRQ(ierr); 2393 ierr = ISLocalToGlobalMappingRestoreBlockIndices(A->rmap->mapping,&garray);CHKERRQ(ierr); 2394 ierr = ISDestroy(&from);CHKERRQ(ierr); 2395 if (A->rmap->mapping != A->cmap->mapping) { 2396 ierr = ISLocalToGlobalMappingGetBlockIndices(A->cmap->mapping,&garray);CHKERRQ(ierr); 2397 ierr = ISCreateBlock(PetscObjectComm((PetscObject)A),cbs,nc/cbs,garray,PETSC_USE_POINTER,&from);CHKERRQ(ierr); 2398 ierr = VecScatterCreate(cglobal,from,is->x,NULL,&is->cctx);CHKERRQ(ierr); 2399 ierr = ISLocalToGlobalMappingRestoreBlockIndices(A->cmap->mapping,&garray);CHKERRQ(ierr); 2400 ierr = ISDestroy(&from);CHKERRQ(ierr); 2401 } else { 2402 ierr = PetscObjectReference((PetscObject)is->rctx);CHKERRQ(ierr); 2403 is->cctx = is->rctx; 2404 } 2405 ierr = VecDestroy(&cglobal);CHKERRQ(ierr); 2406 2407 /* interface counter vector (local) */ 2408 ierr = VecDuplicate(is->y,&is->counter);CHKERRQ(ierr); 2409 ierr = VecSet(is->y,1.);CHKERRQ(ierr); 2410 ierr = VecScatterBegin(is->rctx,is->y,rglobal,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 2411 ierr = VecScatterEnd(is->rctx,is->y,rglobal,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 2412 ierr = VecScatterBegin(is->rctx,rglobal,is->counter,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 2413 ierr = VecScatterEnd(is->rctx,rglobal,is->counter,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 2414 2415 /* special functions for block-diagonal matrices */ 2416 ierr = VecSum(rglobal,&sum);CHKERRQ(ierr); 2417 if ((PetscInt)(PetscRealPart(sum)) == A->rmap->N && A->rmap->N == A->cmap->N && A->rmap->mapping == A->cmap->mapping) { 2418 A->ops->invertblockdiagonal = MatInvertBlockDiagonal_IS; 2419 } else { 2420 A->ops->invertblockdiagonal = NULL; 2421 } 2422 ierr = VecDestroy(&rglobal);CHKERRQ(ierr); 2423 2424 /* setup SF for general purpose shared indices based communications */ 2425 ierr = MatISSetUpSF_IS(A);CHKERRQ(ierr); 2426 PetscFunctionReturn(0); 2427 } 2428 2429 static PetscErrorCode MatSetLocalToGlobalMapping_IS(Mat A,ISLocalToGlobalMapping rmapping,ISLocalToGlobalMapping cmapping) 2430 { 2431 PetscErrorCode ierr; 2432 PetscInt nr,rbs,nc,cbs; 2433 Mat_IS *is = (Mat_IS*)A->data; 2434 2435 PetscFunctionBegin; 2436 PetscCheckSameComm(A,1,rmapping,2); 2437 PetscCheckSameComm(A,1,cmapping,3); 2438 ierr = MatDestroy(&is->A);CHKERRQ(ierr); 2439 if (is->csf != is->sf) { 2440 ierr = PetscSFDestroy(&is->csf);CHKERRQ(ierr); 2441 ierr = PetscFree2(is->csf_rootdata,is->csf_leafdata);CHKERRQ(ierr); 2442 } else is->csf = NULL; 2443 ierr = PetscSFDestroy(&is->sf);CHKERRQ(ierr); 2444 ierr = PetscFree2(is->sf_rootdata,is->sf_leafdata);CHKERRQ(ierr); 2445 ierr = PetscFree(is->bdiag);CHKERRQ(ierr); 2446 2447 /* Setup Layout and set local to global maps */ 2448 ierr = PetscLayoutSetUp(A->rmap);CHKERRQ(ierr); 2449 ierr = PetscLayoutSetUp(A->cmap);CHKERRQ(ierr); 2450 ierr = ISLocalToGlobalMappingGetSize(rmapping,&nr);CHKERRQ(ierr); 2451 ierr = ISLocalToGlobalMappingGetBlockSize(rmapping,&rbs);CHKERRQ(ierr); 2452 ierr = ISLocalToGlobalMappingGetSize(cmapping,&nc);CHKERRQ(ierr); 2453 ierr = ISLocalToGlobalMappingGetBlockSize(cmapping,&cbs);CHKERRQ(ierr); 2454 /* check if the two mappings are actually the same for square matrices (DOLFIN passes 2 different objects) */ 2455 if (rmapping != cmapping && A->rmap->N == A->cmap->N) { 2456 PetscBool same,gsame; 2457 2458 same = PETSC_FALSE; 2459 if (nr == nc && cbs == rbs) { 2460 const PetscInt *idxs1,*idxs2; 2461 2462 ierr = ISLocalToGlobalMappingGetBlockIndices(rmapping,&idxs1);CHKERRQ(ierr); 2463 ierr = ISLocalToGlobalMappingGetBlockIndices(cmapping,&idxs2);CHKERRQ(ierr); 2464 ierr = PetscMemcmp(idxs1,idxs2,(nr/rbs)*sizeof(PetscInt),&same);CHKERRQ(ierr); 2465 ierr = ISLocalToGlobalMappingRestoreBlockIndices(rmapping,&idxs1);CHKERRQ(ierr); 2466 ierr = ISLocalToGlobalMappingRestoreBlockIndices(cmapping,&idxs2);CHKERRQ(ierr); 2467 } 2468 ierr = MPIU_Allreduce(&same,&gsame,1,MPIU_BOOL,MPI_LAND,PetscObjectComm((PetscObject)A));CHKERRQ(ierr); 2469 if (gsame) cmapping = rmapping; 2470 } 2471 ierr = PetscLayoutSetBlockSize(A->rmap,rbs);CHKERRQ(ierr); 2472 ierr = PetscLayoutSetBlockSize(A->cmap,cbs);CHKERRQ(ierr); 2473 ierr = PetscLayoutSetISLocalToGlobalMapping(A->rmap,rmapping);CHKERRQ(ierr); 2474 ierr = PetscLayoutSetISLocalToGlobalMapping(A->cmap,cmapping);CHKERRQ(ierr); 2475 2476 /* Create the local matrix A */ 2477 ierr = MatCreate(PETSC_COMM_SELF,&is->A);CHKERRQ(ierr); 2478 ierr = MatSetType(is->A,is->lmattype);CHKERRQ(ierr); 2479 ierr = MatSetSizes(is->A,nr,nc,nr,nc);CHKERRQ(ierr); 2480 ierr = MatSetBlockSizes(is->A,rbs,cbs);CHKERRQ(ierr); 2481 ierr = MatSetOptionsPrefix(is->A,"is_");CHKERRQ(ierr); 2482 ierr = MatAppendOptionsPrefix(is->A,((PetscObject)A)->prefix);CHKERRQ(ierr); 2483 ierr = PetscLayoutSetUp(is->A->rmap);CHKERRQ(ierr); 2484 ierr = PetscLayoutSetUp(is->A->cmap);CHKERRQ(ierr); 2485 2486 if (!is->islocalref) { /* setup scatters and local vectors for MatMult */ 2487 ierr = MatISSetUpScatters_Private(A);CHKERRQ(ierr); 2488 } 2489 ierr = MatSetUp(A);CHKERRQ(ierr); 2490 PetscFunctionReturn(0); 2491 } 2492 2493 static PetscErrorCode MatSetValues_IS(Mat mat, PetscInt m,const PetscInt *rows, PetscInt n,const PetscInt *cols, const PetscScalar *values, InsertMode addv) 2494 { 2495 Mat_IS *is = (Mat_IS*)mat->data; 2496 PetscErrorCode ierr; 2497 #if defined(PETSC_USE_DEBUG) 2498 PetscInt i,zm,zn; 2499 #endif 2500 PetscInt rows_l[MATIS_MAX_ENTRIES_INSERTION],cols_l[MATIS_MAX_ENTRIES_INSERTION]; 2501 2502 PetscFunctionBegin; 2503 #if defined(PETSC_USE_DEBUG) 2504 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); 2505 /* count negative indices */ 2506 for (i=0,zm=0;i<m;i++) if (rows[i] < 0) zm++; 2507 for (i=0,zn=0;i<n;i++) if (cols[i] < 0) zn++; 2508 #endif 2509 ierr = ISGlobalToLocalMappingApply(mat->rmap->mapping,IS_GTOLM_MASK,m,rows,&m,rows_l);CHKERRQ(ierr); 2510 ierr = ISGlobalToLocalMappingApply(mat->cmap->mapping,IS_GTOLM_MASK,n,cols,&n,cols_l);CHKERRQ(ierr); 2511 #if defined(PETSC_USE_DEBUG) 2512 /* count negative indices (should be the same as before) */ 2513 for (i=0;i<m;i++) if (rows_l[i] < 0) zm--; 2514 for (i=0;i<n;i++) if (cols_l[i] < 0) zn--; 2515 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"); 2516 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"); 2517 #endif 2518 ierr = MatSetValues(is->A,m,rows_l,n,cols_l,values,addv);CHKERRQ(ierr); 2519 PetscFunctionReturn(0); 2520 } 2521 2522 static PetscErrorCode MatSetValuesBlocked_IS(Mat mat, PetscInt m,const PetscInt *rows, PetscInt n,const PetscInt *cols, const PetscScalar *values, InsertMode addv) 2523 { 2524 Mat_IS *is = (Mat_IS*)mat->data; 2525 PetscErrorCode ierr; 2526 #if defined(PETSC_USE_DEBUG) 2527 PetscInt i,zm,zn; 2528 #endif 2529 PetscInt rows_l[MATIS_MAX_ENTRIES_INSERTION],cols_l[MATIS_MAX_ENTRIES_INSERTION]; 2530 2531 PetscFunctionBegin; 2532 #if defined(PETSC_USE_DEBUG) 2533 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); 2534 /* count negative indices */ 2535 for (i=0,zm=0;i<m;i++) if (rows[i] < 0) zm++; 2536 for (i=0,zn=0;i<n;i++) if (cols[i] < 0) zn++; 2537 #endif 2538 ierr = ISGlobalToLocalMappingApplyBlock(mat->rmap->mapping,IS_GTOLM_MASK,m,rows,&m,rows_l);CHKERRQ(ierr); 2539 ierr = ISGlobalToLocalMappingApplyBlock(mat->cmap->mapping,IS_GTOLM_MASK,n,cols,&n,cols_l);CHKERRQ(ierr); 2540 #if defined(PETSC_USE_DEBUG) 2541 /* count negative indices (should be the same as before) */ 2542 for (i=0;i<m;i++) if (rows_l[i] < 0) zm--; 2543 for (i=0;i<n;i++) if (cols_l[i] < 0) zn--; 2544 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"); 2545 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"); 2546 #endif 2547 ierr = MatSetValuesBlocked(is->A,m,rows_l,n,cols_l,values,addv);CHKERRQ(ierr); 2548 PetscFunctionReturn(0); 2549 } 2550 2551 static PetscErrorCode MatSetValuesLocal_IS(Mat A,PetscInt m,const PetscInt *rows, PetscInt n,const PetscInt *cols,const PetscScalar *values,InsertMode addv) 2552 { 2553 PetscErrorCode ierr; 2554 Mat_IS *is = (Mat_IS*)A->data; 2555 2556 PetscFunctionBegin; 2557 if (is->A->rmap->mapping) { 2558 ierr = MatSetValuesLocal(is->A,m,rows,n,cols,values,addv);CHKERRQ(ierr); 2559 } else { 2560 ierr = MatSetValues(is->A,m,rows,n,cols,values,addv);CHKERRQ(ierr); 2561 } 2562 PetscFunctionReturn(0); 2563 } 2564 2565 static PetscErrorCode MatSetValuesBlockedLocal_IS(Mat A,PetscInt m,const PetscInt *rows, PetscInt n,const PetscInt *cols,const PetscScalar *values,InsertMode addv) 2566 { 2567 PetscErrorCode ierr; 2568 Mat_IS *is = (Mat_IS*)A->data; 2569 2570 PetscFunctionBegin; 2571 if (is->A->rmap->mapping) { 2572 #if defined(PETSC_USE_DEBUG) 2573 PetscInt ibs,bs; 2574 2575 ierr = ISLocalToGlobalMappingGetBlockSize(is->A->rmap->mapping,&ibs);CHKERRQ(ierr); 2576 ierr = MatGetBlockSize(is->A,&bs);CHKERRQ(ierr); 2577 if (ibs != bs) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_SUP,"Different block sizes! local mat %D, local l2g map %D",bs,ibs); 2578 #endif 2579 ierr = MatSetValuesBlockedLocal(is->A,m,rows,n,cols,values,addv);CHKERRQ(ierr); 2580 } else { 2581 ierr = MatSetValuesBlocked(is->A,m,rows,n,cols,values,addv);CHKERRQ(ierr); 2582 } 2583 PetscFunctionReturn(0); 2584 } 2585 2586 static PetscErrorCode MatISZeroRowsColumnsLocal_Private(Mat A,PetscInt n,const PetscInt rows[],PetscScalar diag,PetscBool columns) 2587 { 2588 Mat_IS *is = (Mat_IS*)A->data; 2589 PetscErrorCode ierr; 2590 2591 PetscFunctionBegin; 2592 if (!n) { 2593 is->pure_neumann = PETSC_TRUE; 2594 } else { 2595 PetscInt i; 2596 is->pure_neumann = PETSC_FALSE; 2597 2598 if (columns) { 2599 ierr = MatZeroRowsColumns(is->A,n,rows,diag,0,0);CHKERRQ(ierr); 2600 } else { 2601 ierr = MatZeroRows(is->A,n,rows,diag,0,0);CHKERRQ(ierr); 2602 } 2603 if (diag != 0.) { 2604 const PetscScalar *array; 2605 ierr = VecGetArrayRead(is->counter,&array);CHKERRQ(ierr); 2606 for (i=0; i<n; i++) { 2607 ierr = MatSetValue(is->A,rows[i],rows[i],diag/(array[rows[i]]),INSERT_VALUES);CHKERRQ(ierr); 2608 } 2609 ierr = VecRestoreArrayRead(is->counter,&array);CHKERRQ(ierr); 2610 } 2611 ierr = MatAssemblyBegin(is->A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 2612 ierr = MatAssemblyEnd(is->A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 2613 } 2614 PetscFunctionReturn(0); 2615 } 2616 2617 static PetscErrorCode MatZeroRowsColumns_Private_IS(Mat A,PetscInt n,const PetscInt rows[],PetscScalar diag,Vec x,Vec b,PetscBool columns) 2618 { 2619 Mat_IS *matis = (Mat_IS*)A->data; 2620 PetscInt nr,nl,len,i; 2621 PetscInt *lrows; 2622 PetscErrorCode ierr; 2623 2624 PetscFunctionBegin; 2625 #if defined(PETSC_USE_DEBUG) 2626 if (columns || diag != 0. || (x && b)) { 2627 PetscBool cong; 2628 2629 ierr = PetscLayoutCompare(A->rmap,A->cmap,&cong);CHKERRQ(ierr); 2630 cong = (PetscBool)(cong && matis->sf == matis->csf); 2631 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"); 2632 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"); 2633 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"); 2634 } 2635 #endif 2636 /* get locally owned rows */ 2637 ierr = PetscLayoutMapLocal(A->rmap,n,rows,&len,&lrows,NULL);CHKERRQ(ierr); 2638 /* fix right hand side if needed */ 2639 if (x && b) { 2640 const PetscScalar *xx; 2641 PetscScalar *bb; 2642 2643 ierr = VecGetArrayRead(x, &xx);CHKERRQ(ierr); 2644 ierr = VecGetArray(b, &bb);CHKERRQ(ierr); 2645 for (i=0;i<len;++i) bb[lrows[i]] = diag*xx[lrows[i]]; 2646 ierr = VecRestoreArrayRead(x, &xx);CHKERRQ(ierr); 2647 ierr = VecRestoreArray(b, &bb);CHKERRQ(ierr); 2648 } 2649 /* get rows associated to the local matrices */ 2650 ierr = MatGetSize(matis->A,&nl,NULL);CHKERRQ(ierr); 2651 ierr = PetscMemzero(matis->sf_leafdata,nl*sizeof(PetscInt));CHKERRQ(ierr); 2652 ierr = PetscMemzero(matis->sf_rootdata,A->rmap->n*sizeof(PetscInt));CHKERRQ(ierr); 2653 for (i=0;i<len;i++) matis->sf_rootdata[lrows[i]] = 1; 2654 ierr = PetscFree(lrows);CHKERRQ(ierr); 2655 ierr = PetscSFBcastBegin(matis->sf,MPIU_INT,matis->sf_rootdata,matis->sf_leafdata);CHKERRQ(ierr); 2656 ierr = PetscSFBcastEnd(matis->sf,MPIU_INT,matis->sf_rootdata,matis->sf_leafdata);CHKERRQ(ierr); 2657 ierr = PetscMalloc1(nl,&lrows);CHKERRQ(ierr); 2658 for (i=0,nr=0;i<nl;i++) if (matis->sf_leafdata[i]) lrows[nr++] = i; 2659 ierr = MatISZeroRowsColumnsLocal_Private(A,nr,lrows,diag,columns);CHKERRQ(ierr); 2660 ierr = PetscFree(lrows);CHKERRQ(ierr); 2661 PetscFunctionReturn(0); 2662 } 2663 2664 static PetscErrorCode MatZeroRows_IS(Mat A,PetscInt n,const PetscInt rows[],PetscScalar diag,Vec x,Vec b) 2665 { 2666 PetscErrorCode ierr; 2667 2668 PetscFunctionBegin; 2669 ierr = MatZeroRowsColumns_Private_IS(A,n,rows,diag,x,b,PETSC_FALSE);CHKERRQ(ierr); 2670 PetscFunctionReturn(0); 2671 } 2672 2673 static PetscErrorCode MatZeroRowsColumns_IS(Mat A,PetscInt n,const PetscInt rows[],PetscScalar diag,Vec x,Vec b) 2674 { 2675 PetscErrorCode ierr; 2676 2677 PetscFunctionBegin; 2678 ierr = MatZeroRowsColumns_Private_IS(A,n,rows,diag,x,b,PETSC_TRUE);CHKERRQ(ierr); 2679 PetscFunctionReturn(0); 2680 } 2681 2682 static PetscErrorCode MatAssemblyBegin_IS(Mat A,MatAssemblyType type) 2683 { 2684 Mat_IS *is = (Mat_IS*)A->data; 2685 PetscErrorCode ierr; 2686 2687 PetscFunctionBegin; 2688 ierr = MatAssemblyBegin(is->A,type);CHKERRQ(ierr); 2689 PetscFunctionReturn(0); 2690 } 2691 2692 static PetscErrorCode MatAssemblyEnd_IS(Mat A,MatAssemblyType type) 2693 { 2694 Mat_IS *is = (Mat_IS*)A->data; 2695 PetscErrorCode ierr; 2696 2697 PetscFunctionBegin; 2698 ierr = MatAssemblyEnd(is->A,type);CHKERRQ(ierr); 2699 /* fix for local empty rows/cols */ 2700 if (is->locempty && type == MAT_FINAL_ASSEMBLY) { 2701 Mat newlA; 2702 ISLocalToGlobalMapping rl2g,cl2g; 2703 IS nzr,nzc; 2704 PetscInt nr,nc,nnzr,nnzc; 2705 PetscBool lnewl2g,newl2g; 2706 2707 ierr = MatGetSize(is->A,&nr,&nc);CHKERRQ(ierr); 2708 ierr = MatFindNonzeroRowsOrCols_Basic(is->A,PETSC_FALSE,PETSC_SMALL,&nzr);CHKERRQ(ierr); 2709 if (!nzr) { 2710 ierr = ISCreateStride(PetscObjectComm((PetscObject)is->A),nr,0,1,&nzr);CHKERRQ(ierr); 2711 } 2712 ierr = MatFindNonzeroRowsOrCols_Basic(is->A,PETSC_TRUE,PETSC_SMALL,&nzc);CHKERRQ(ierr); 2713 if (!nzc) { 2714 ierr = ISCreateStride(PetscObjectComm((PetscObject)is->A),nc,0,1,&nzc);CHKERRQ(ierr); 2715 } 2716 ierr = ISGetSize(nzr,&nnzr);CHKERRQ(ierr); 2717 ierr = ISGetSize(nzc,&nnzc);CHKERRQ(ierr); 2718 if (nnzr != nr || nnzc != nc) { 2719 ISLocalToGlobalMapping l2g; 2720 IS is1,is2; 2721 2722 /* need new global l2g map */ 2723 lnewl2g = PETSC_TRUE; 2724 ierr = MPI_Allreduce(&lnewl2g,&newl2g,1,MPIU_BOOL,MPI_LOR,PetscObjectComm((PetscObject)A));CHKERRQ(ierr); 2725 2726 /* extract valid submatrix */ 2727 ierr = MatCreateSubMatrix(is->A,nzr,nzc,MAT_INITIAL_MATRIX,&newlA);CHKERRQ(ierr); 2728 2729 /* attach local l2g maps for successive calls of MatSetValues on the local matrix */ 2730 ierr = ISLocalToGlobalMappingCreateIS(nzr,&l2g);CHKERRQ(ierr); 2731 ierr = ISCreateStride(PetscObjectComm((PetscObject)is->A),nr,0,1,&is1);CHKERRQ(ierr); 2732 ierr = ISGlobalToLocalMappingApplyIS(l2g,IS_GTOLM_MASK,is1,&is2);CHKERRQ(ierr); 2733 ierr = ISLocalToGlobalMappingDestroy(&l2g);CHKERRQ(ierr); 2734 if (is->A->rmap->mapping) { /* the matrix has a local-to-local map already attached (probably DMDA generated) */ 2735 const PetscInt *idxs1,*idxs2; 2736 PetscInt j,i,nl,*tidxs; 2737 2738 ierr = ISLocalToGlobalMappingGetSize(is->A->rmap->mapping,&nl);CHKERRQ(ierr); 2739 ierr = ISLocalToGlobalMappingGetIndices(is->A->rmap->mapping,&idxs1);CHKERRQ(ierr); 2740 ierr = PetscMalloc1(nl,&tidxs);CHKERRQ(ierr); 2741 ierr = ISGetIndices(is2,&idxs2);CHKERRQ(ierr); 2742 for (i=0,j=0;i<nl;i++) tidxs[i] = idxs1[i] < 0 ? -1 : idxs2[j++]; 2743 if (j != nr) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Unexpected count %D != %D",j,nr); 2744 ierr = ISLocalToGlobalMappingRestoreIndices(is->A->rmap->mapping,&idxs1);CHKERRQ(ierr); 2745 ierr = ISRestoreIndices(is2,&idxs2);CHKERRQ(ierr); 2746 ierr = ISDestroy(&is2);CHKERRQ(ierr); 2747 ierr = ISCreateGeneral(PetscObjectComm((PetscObject)is->A->rmap->mapping),nl,tidxs,PETSC_OWN_POINTER,&is2);CHKERRQ(ierr); 2748 } 2749 ierr = ISLocalToGlobalMappingCreateIS(is2,&rl2g);CHKERRQ(ierr); 2750 ierr = ISDestroy(&is1);CHKERRQ(ierr); 2751 ierr = ISDestroy(&is2);CHKERRQ(ierr); 2752 2753 ierr = ISLocalToGlobalMappingCreateIS(nzc,&l2g);CHKERRQ(ierr); 2754 ierr = ISCreateStride(PetscObjectComm((PetscObject)is->A),nc,0,1,&is1);CHKERRQ(ierr); 2755 ierr = ISGlobalToLocalMappingApplyIS(l2g,IS_GTOLM_MASK,is1,&is2);CHKERRQ(ierr); 2756 ierr = ISLocalToGlobalMappingDestroy(&l2g);CHKERRQ(ierr); 2757 if (is->A->cmap->mapping) { /* the matrix has a local-to-local map already attached (probably DMDA generated) */ 2758 const PetscInt *idxs1,*idxs2; 2759 PetscInt j,i,nl,*tidxs; 2760 2761 ierr = ISLocalToGlobalMappingGetSize(is->A->cmap->mapping,&nl);CHKERRQ(ierr); 2762 ierr = ISLocalToGlobalMappingGetIndices(is->A->cmap->mapping,&idxs1);CHKERRQ(ierr); 2763 ierr = PetscMalloc1(nl,&tidxs);CHKERRQ(ierr); 2764 ierr = ISGetIndices(is2,&idxs2);CHKERRQ(ierr); 2765 for (i=0,j=0;i<nl;i++) tidxs[i] = idxs1[i] < 0 ? -1 : idxs2[j++]; 2766 if (j != nc) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Unexpected count %D != %D",j,nc); 2767 ierr = ISLocalToGlobalMappingRestoreIndices(is->A->cmap->mapping,&idxs1);CHKERRQ(ierr); 2768 ierr = ISRestoreIndices(is2,&idxs2);CHKERRQ(ierr); 2769 ierr = ISDestroy(&is2);CHKERRQ(ierr); 2770 ierr = ISCreateGeneral(PetscObjectComm((PetscObject)is->A->cmap->mapping),nl,tidxs,PETSC_OWN_POINTER,&is2);CHKERRQ(ierr); 2771 } 2772 ierr = ISLocalToGlobalMappingCreateIS(is2,&cl2g);CHKERRQ(ierr); 2773 ierr = ISDestroy(&is1);CHKERRQ(ierr); 2774 ierr = ISDestroy(&is2);CHKERRQ(ierr); 2775 2776 ierr = MatSetLocalToGlobalMapping(newlA,rl2g,cl2g);CHKERRQ(ierr); 2777 2778 ierr = ISLocalToGlobalMappingDestroy(&rl2g);CHKERRQ(ierr); 2779 ierr = ISLocalToGlobalMappingDestroy(&cl2g);CHKERRQ(ierr); 2780 } else { /* local matrix fully populated */ 2781 lnewl2g = PETSC_FALSE; 2782 ierr = MPI_Allreduce(&lnewl2g,&newl2g,1,MPIU_BOOL,MPI_LOR,PetscObjectComm((PetscObject)A));CHKERRQ(ierr); 2783 ierr = PetscObjectReference((PetscObject)is->A);CHKERRQ(ierr); 2784 newlA = is->A; 2785 } 2786 /* attach new global l2g map if needed */ 2787 if (newl2g) { 2788 IS gnzr,gnzc; 2789 const PetscInt *grid,*gcid; 2790 2791 ierr = ISLocalToGlobalMappingApplyIS(A->rmap->mapping,nzr,&gnzr);CHKERRQ(ierr); 2792 ierr = ISLocalToGlobalMappingApplyIS(A->cmap->mapping,nzc,&gnzc);CHKERRQ(ierr); 2793 ierr = ISGetIndices(gnzr,&grid);CHKERRQ(ierr); 2794 ierr = ISGetIndices(gnzc,&gcid);CHKERRQ(ierr); 2795 ierr = ISLocalToGlobalMappingCreate(PetscObjectComm((PetscObject)A),1,nnzr,grid,PETSC_COPY_VALUES,&rl2g);CHKERRQ(ierr); 2796 ierr = ISLocalToGlobalMappingCreate(PetscObjectComm((PetscObject)A),1,nnzc,gcid,PETSC_COPY_VALUES,&cl2g);CHKERRQ(ierr); 2797 ierr = ISRestoreIndices(gnzr,&grid);CHKERRQ(ierr); 2798 ierr = ISRestoreIndices(gnzc,&gcid);CHKERRQ(ierr); 2799 ierr = ISDestroy(&gnzr);CHKERRQ(ierr); 2800 ierr = ISDestroy(&gnzc);CHKERRQ(ierr); 2801 ierr = MatSetLocalToGlobalMapping(A,rl2g,cl2g);CHKERRQ(ierr); 2802 ierr = ISLocalToGlobalMappingDestroy(&rl2g);CHKERRQ(ierr); 2803 ierr = ISLocalToGlobalMappingDestroy(&cl2g);CHKERRQ(ierr); 2804 } 2805 ierr = MatISSetLocalMat(A,newlA);CHKERRQ(ierr); 2806 ierr = MatDestroy(&newlA);CHKERRQ(ierr); 2807 ierr = ISDestroy(&nzr);CHKERRQ(ierr); 2808 ierr = ISDestroy(&nzc);CHKERRQ(ierr); 2809 is->locempty = PETSC_FALSE; 2810 } 2811 PetscFunctionReturn(0); 2812 } 2813 2814 static PetscErrorCode MatISGetLocalMat_IS(Mat mat,Mat *local) 2815 { 2816 Mat_IS *is = (Mat_IS*)mat->data; 2817 2818 PetscFunctionBegin; 2819 *local = is->A; 2820 PetscFunctionReturn(0); 2821 } 2822 2823 static PetscErrorCode MatISRestoreLocalMat_IS(Mat mat,Mat *local) 2824 { 2825 PetscFunctionBegin; 2826 *local = NULL; 2827 PetscFunctionReturn(0); 2828 } 2829 2830 /*@ 2831 MatISGetLocalMat - Gets the local matrix stored inside a MATIS matrix. 2832 2833 Input Parameter: 2834 . mat - the matrix 2835 2836 Output Parameter: 2837 . local - the local matrix 2838 2839 Level: advanced 2840 2841 Notes: 2842 This can be called if you have precomputed the nonzero structure of the 2843 matrix and want to provide it to the inner matrix object to improve the performance 2844 of the MatSetValues() operation. 2845 2846 Call MatISRestoreLocalMat() when finished with the local matrix. 2847 2848 .seealso: MATIS 2849 @*/ 2850 PetscErrorCode MatISGetLocalMat(Mat mat,Mat *local) 2851 { 2852 PetscErrorCode ierr; 2853 2854 PetscFunctionBegin; 2855 PetscValidHeaderSpecific(mat,MAT_CLASSID,1); 2856 PetscValidPointer(local,2); 2857 ierr = PetscUseMethod(mat,"MatISGetLocalMat_C",(Mat,Mat*),(mat,local));CHKERRQ(ierr); 2858 PetscFunctionReturn(0); 2859 } 2860 2861 /*@ 2862 MatISRestoreLocalMat - Restores the local matrix obtained with MatISGetLocalMat() 2863 2864 Input Parameter: 2865 . mat - the matrix 2866 2867 Output Parameter: 2868 . local - the local matrix 2869 2870 Level: advanced 2871 2872 .seealso: MATIS 2873 @*/ 2874 PetscErrorCode MatISRestoreLocalMat(Mat mat,Mat *local) 2875 { 2876 PetscErrorCode ierr; 2877 2878 PetscFunctionBegin; 2879 PetscValidHeaderSpecific(mat,MAT_CLASSID,1); 2880 PetscValidPointer(local,2); 2881 ierr = PetscUseMethod(mat,"MatISRestoreLocalMat_C",(Mat,Mat*),(mat,local));CHKERRQ(ierr); 2882 PetscFunctionReturn(0); 2883 } 2884 2885 static PetscErrorCode MatISSetLocalMatType_IS(Mat mat,MatType mtype) 2886 { 2887 Mat_IS *is = (Mat_IS*)mat->data; 2888 PetscErrorCode ierr; 2889 2890 PetscFunctionBegin; 2891 if (is->A) { 2892 ierr = MatSetType(is->A,mtype);CHKERRQ(ierr); 2893 } 2894 ierr = PetscFree(is->lmattype);CHKERRQ(ierr); 2895 ierr = PetscStrallocpy(mtype,&is->lmattype);CHKERRQ(ierr); 2896 PetscFunctionReturn(0); 2897 } 2898 2899 /*@ 2900 MatISSetLocalMatType - Specifies the type of local matrix 2901 2902 Input Parameter: 2903 . mat - the matrix 2904 . mtype - the local matrix type 2905 2906 Output Parameter: 2907 2908 Level: advanced 2909 2910 .seealso: MATIS, MatSetType(), MatType 2911 @*/ 2912 PetscErrorCode MatISSetLocalMatType(Mat mat,MatType mtype) 2913 { 2914 PetscErrorCode ierr; 2915 2916 PetscFunctionBegin; 2917 PetscValidHeaderSpecific(mat,MAT_CLASSID,1); 2918 ierr = PetscUseMethod(mat,"MatISSetLocalMatType_C",(Mat,MatType),(mat,mtype));CHKERRQ(ierr); 2919 PetscFunctionReturn(0); 2920 } 2921 2922 static PetscErrorCode MatISSetLocalMat_IS(Mat mat,Mat local) 2923 { 2924 Mat_IS *is = (Mat_IS*)mat->data; 2925 PetscInt nrows,ncols,orows,ocols; 2926 PetscErrorCode ierr; 2927 MatType mtype,otype; 2928 PetscBool sametype = PETSC_TRUE; 2929 2930 PetscFunctionBegin; 2931 if (is->A) { 2932 ierr = MatGetSize(is->A,&orows,&ocols);CHKERRQ(ierr); 2933 ierr = MatGetSize(local,&nrows,&ncols);CHKERRQ(ierr); 2934 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); 2935 ierr = MatGetType(local,&mtype);CHKERRQ(ierr); 2936 ierr = MatGetType(is->A,&otype);CHKERRQ(ierr); 2937 ierr = PetscStrcmp(mtype,otype,&sametype);CHKERRQ(ierr); 2938 } 2939 ierr = PetscObjectReference((PetscObject)local);CHKERRQ(ierr); 2940 ierr = MatDestroy(&is->A);CHKERRQ(ierr); 2941 is->A = local; 2942 ierr = MatGetType(is->A,&mtype);CHKERRQ(ierr); 2943 ierr = MatISSetLocalMatType(mat,mtype);CHKERRQ(ierr); 2944 if (!sametype && !is->islocalref) { 2945 ierr = MatISSetUpScatters_Private(mat);CHKERRQ(ierr); 2946 } 2947 PetscFunctionReturn(0); 2948 } 2949 2950 /*@ 2951 MatISSetLocalMat - Replace the local matrix stored inside a MATIS object. 2952 2953 Collective on Mat 2954 2955 Input Parameter: 2956 . mat - the matrix 2957 . local - the local matrix 2958 2959 Output Parameter: 2960 2961 Level: advanced 2962 2963 Notes: 2964 This can be called if you have precomputed the local matrix and 2965 want to provide it to the matrix object MATIS. 2966 2967 .seealso: MATIS 2968 @*/ 2969 PetscErrorCode MatISSetLocalMat(Mat mat,Mat local) 2970 { 2971 PetscErrorCode ierr; 2972 2973 PetscFunctionBegin; 2974 PetscValidHeaderSpecific(mat,MAT_CLASSID,1); 2975 PetscValidHeaderSpecific(local,MAT_CLASSID,2); 2976 ierr = PetscUseMethod(mat,"MatISSetLocalMat_C",(Mat,Mat),(mat,local));CHKERRQ(ierr); 2977 PetscFunctionReturn(0); 2978 } 2979 2980 static PetscErrorCode MatZeroEntries_IS(Mat A) 2981 { 2982 Mat_IS *a = (Mat_IS*)A->data; 2983 PetscErrorCode ierr; 2984 2985 PetscFunctionBegin; 2986 ierr = MatZeroEntries(a->A);CHKERRQ(ierr); 2987 PetscFunctionReturn(0); 2988 } 2989 2990 static PetscErrorCode MatScale_IS(Mat A,PetscScalar a) 2991 { 2992 Mat_IS *is = (Mat_IS*)A->data; 2993 PetscErrorCode ierr; 2994 2995 PetscFunctionBegin; 2996 ierr = MatScale(is->A,a);CHKERRQ(ierr); 2997 PetscFunctionReturn(0); 2998 } 2999 3000 static PetscErrorCode MatGetDiagonal_IS(Mat A, Vec v) 3001 { 3002 Mat_IS *is = (Mat_IS*)A->data; 3003 PetscErrorCode ierr; 3004 3005 PetscFunctionBegin; 3006 /* get diagonal of the local matrix */ 3007 ierr = MatGetDiagonal(is->A,is->y);CHKERRQ(ierr); 3008 3009 /* scatter diagonal back into global vector */ 3010 ierr = VecSet(v,0);CHKERRQ(ierr); 3011 ierr = VecScatterBegin(is->rctx,is->y,v,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 3012 ierr = VecScatterEnd(is->rctx,is->y,v,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 3013 PetscFunctionReturn(0); 3014 } 3015 3016 static PetscErrorCode MatSetOption_IS(Mat A,MatOption op,PetscBool flg) 3017 { 3018 Mat_IS *a = (Mat_IS*)A->data; 3019 PetscErrorCode ierr; 3020 3021 PetscFunctionBegin; 3022 ierr = MatSetOption(a->A,op,flg);CHKERRQ(ierr); 3023 PetscFunctionReturn(0); 3024 } 3025 3026 static PetscErrorCode MatAXPY_IS(Mat Y,PetscScalar a,Mat X,MatStructure str) 3027 { 3028 Mat_IS *y = (Mat_IS*)Y->data; 3029 Mat_IS *x; 3030 #if defined(PETSC_USE_DEBUG) 3031 PetscBool ismatis; 3032 #endif 3033 PetscErrorCode ierr; 3034 3035 PetscFunctionBegin; 3036 #if defined(PETSC_USE_DEBUG) 3037 ierr = PetscObjectTypeCompare((PetscObject)X,MATIS,&ismatis);CHKERRQ(ierr); 3038 if (!ismatis) SETERRQ(PetscObjectComm((PetscObject)Y),PETSC_ERR_SUP,"Cannot call MatAXPY(Y,a,X,str) with X not of type MATIS"); 3039 #endif 3040 x = (Mat_IS*)X->data; 3041 ierr = MatAXPY(y->A,a,x->A,str);CHKERRQ(ierr); 3042 PetscFunctionReturn(0); 3043 } 3044 3045 static PetscErrorCode MatGetLocalSubMatrix_IS(Mat A,IS row,IS col,Mat *submat) 3046 { 3047 Mat lA; 3048 Mat_IS *matis; 3049 ISLocalToGlobalMapping rl2g,cl2g; 3050 IS is; 3051 const PetscInt *rg,*rl; 3052 PetscInt nrg; 3053 PetscInt N,M,nrl,i,*idxs; 3054 PetscErrorCode ierr; 3055 3056 PetscFunctionBegin; 3057 ierr = ISLocalToGlobalMappingGetIndices(A->rmap->mapping,&rg);CHKERRQ(ierr); 3058 ierr = ISGetLocalSize(row,&nrl);CHKERRQ(ierr); 3059 ierr = ISGetIndices(row,&rl);CHKERRQ(ierr); 3060 ierr = ISLocalToGlobalMappingGetSize(A->rmap->mapping,&nrg);CHKERRQ(ierr); 3061 #if defined(PETSC_USE_DEBUG) 3062 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); 3063 #endif 3064 ierr = PetscMalloc1(nrg,&idxs);CHKERRQ(ierr); 3065 /* map from [0,nrl) to row */ 3066 for (i=0;i<nrl;i++) idxs[i] = rl[i]; 3067 for (i=nrl;i<nrg;i++) idxs[i] = -1; 3068 ierr = ISRestoreIndices(row,&rl);CHKERRQ(ierr); 3069 ierr = ISLocalToGlobalMappingRestoreIndices(A->rmap->mapping,&rg);CHKERRQ(ierr); 3070 ierr = ISCreateGeneral(PetscObjectComm((PetscObject)A),nrg,idxs,PETSC_OWN_POINTER,&is);CHKERRQ(ierr); 3071 ierr = ISLocalToGlobalMappingCreateIS(is,&rl2g);CHKERRQ(ierr); 3072 ierr = ISDestroy(&is);CHKERRQ(ierr); 3073 /* compute new l2g map for columns */ 3074 if (col != row || A->rmap->mapping != A->cmap->mapping) { 3075 const PetscInt *cg,*cl; 3076 PetscInt ncg; 3077 PetscInt ncl; 3078 3079 ierr = ISLocalToGlobalMappingGetIndices(A->cmap->mapping,&cg);CHKERRQ(ierr); 3080 ierr = ISGetLocalSize(col,&ncl);CHKERRQ(ierr); 3081 ierr = ISGetIndices(col,&cl);CHKERRQ(ierr); 3082 ierr = ISLocalToGlobalMappingGetSize(A->cmap->mapping,&ncg);CHKERRQ(ierr); 3083 #if defined(PETSC_USE_DEBUG) 3084 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); 3085 #endif 3086 ierr = PetscMalloc1(ncg,&idxs);CHKERRQ(ierr); 3087 /* map from [0,ncl) to col */ 3088 for (i=0;i<ncl;i++) idxs[i] = cl[i]; 3089 for (i=ncl;i<ncg;i++) idxs[i] = -1; 3090 ierr = ISRestoreIndices(col,&cl);CHKERRQ(ierr); 3091 ierr = ISLocalToGlobalMappingRestoreIndices(A->cmap->mapping,&cg);CHKERRQ(ierr); 3092 ierr = ISCreateGeneral(PetscObjectComm((PetscObject)A),ncg,idxs,PETSC_OWN_POINTER,&is);CHKERRQ(ierr); 3093 ierr = ISLocalToGlobalMappingCreateIS(is,&cl2g);CHKERRQ(ierr); 3094 ierr = ISDestroy(&is);CHKERRQ(ierr); 3095 } else { 3096 ierr = PetscObjectReference((PetscObject)rl2g);CHKERRQ(ierr); 3097 cl2g = rl2g; 3098 } 3099 /* create the MATIS submatrix */ 3100 ierr = MatGetSize(A,&M,&N);CHKERRQ(ierr); 3101 ierr = MatCreate(PetscObjectComm((PetscObject)A),submat);CHKERRQ(ierr); 3102 ierr = MatSetSizes(*submat,PETSC_DECIDE,PETSC_DECIDE,M,N);CHKERRQ(ierr); 3103 ierr = MatSetType(*submat,MATIS);CHKERRQ(ierr); 3104 matis = (Mat_IS*)((*submat)->data); 3105 matis->islocalref = PETSC_TRUE; 3106 ierr = MatSetLocalToGlobalMapping(*submat,rl2g,cl2g);CHKERRQ(ierr); 3107 ierr = MatISGetLocalMat(A,&lA);CHKERRQ(ierr); 3108 ierr = MatISSetLocalMat(*submat,lA);CHKERRQ(ierr); 3109 ierr = MatSetUp(*submat);CHKERRQ(ierr); 3110 ierr = MatAssemblyBegin(*submat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 3111 ierr = MatAssemblyEnd(*submat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 3112 ierr = ISLocalToGlobalMappingDestroy(&rl2g);CHKERRQ(ierr); 3113 ierr = ISLocalToGlobalMappingDestroy(&cl2g);CHKERRQ(ierr); 3114 /* remove unsupported ops */ 3115 ierr = PetscMemzero((*submat)->ops,sizeof(struct _MatOps));CHKERRQ(ierr); 3116 (*submat)->ops->destroy = MatDestroy_IS; 3117 (*submat)->ops->setvalueslocal = MatSetValuesLocal_SubMat_IS; 3118 (*submat)->ops->setvaluesblockedlocal = MatSetValuesBlockedLocal_SubMat_IS; 3119 (*submat)->ops->assemblybegin = MatAssemblyBegin_IS; 3120 (*submat)->ops->assemblyend = MatAssemblyEnd_IS; 3121 PetscFunctionReturn(0); 3122 } 3123 3124 static PetscErrorCode MatSetFromOptions_IS(PetscOptionItems *PetscOptionsObject, Mat A) 3125 { 3126 Mat_IS *a = (Mat_IS*)A->data; 3127 char type[256]; 3128 PetscBool flg; 3129 PetscErrorCode ierr; 3130 3131 PetscFunctionBegin; 3132 ierr = PetscOptionsHead(PetscOptionsObject,"MATIS options");CHKERRQ(ierr); 3133 ierr = PetscOptionsBool("-matis_fixempty","Fix local matrices in case of empty local rows/columns","MatISFixLocalEmpty",a->locempty,&a->locempty,NULL);CHKERRQ(ierr); 3134 ierr = PetscOptionsBool("-matis_storel2l","Store local-to-local matrices generated from PtAP operations","MatISStoreL2L",a->storel2l,&a->storel2l,NULL);CHKERRQ(ierr); 3135 ierr = PetscOptionsFList("-matis_localmat_type","Matrix type","MatISSetLocalMatType",MatList,a->lmattype,type,256,&flg);CHKERRQ(ierr); 3136 if (flg) { 3137 ierr = MatISSetLocalMatType(A,type);CHKERRQ(ierr); 3138 } 3139 if (a->A) { 3140 ierr = MatSetFromOptions(a->A);CHKERRQ(ierr); 3141 } 3142 ierr = PetscOptionsTail();CHKERRQ(ierr); 3143 PetscFunctionReturn(0); 3144 } 3145 3146 /*@ 3147 MatCreateIS - Creates a "process" unassembled matrix, assembled on each 3148 process but not across processes. 3149 3150 Input Parameters: 3151 + comm - MPI communicator that will share the matrix 3152 . bs - block size of the matrix 3153 . m,n,M,N - local and/or global sizes of the left and right vector used in matrix vector products 3154 . rmap - local to global map for rows 3155 - cmap - local to global map for cols 3156 3157 Output Parameter: 3158 . A - the resulting matrix 3159 3160 Level: advanced 3161 3162 Notes: 3163 See MATIS for more details. 3164 m and n are NOT related to the size of the map; they represent the size of the local parts of the vectors 3165 used in MatMult operations. The sizes of rmap and cmap define the size of the local matrices. 3166 If either rmap or cmap are NULL, then the matrix is assumed to be square. 3167 3168 .seealso: MATIS, MatSetLocalToGlobalMapping() 3169 @*/ 3170 PetscErrorCode MatCreateIS(MPI_Comm comm,PetscInt bs,PetscInt m,PetscInt n,PetscInt M,PetscInt N,ISLocalToGlobalMapping rmap,ISLocalToGlobalMapping cmap,Mat *A) 3171 { 3172 PetscErrorCode ierr; 3173 3174 PetscFunctionBegin; 3175 if (!rmap && !cmap) SETERRQ(comm,PETSC_ERR_USER,"You need to provide at least one of the mappings"); 3176 ierr = MatCreate(comm,A);CHKERRQ(ierr); 3177 ierr = MatSetSizes(*A,m,n,M,N);CHKERRQ(ierr); 3178 if (bs > 0) { 3179 ierr = MatSetBlockSize(*A,bs);CHKERRQ(ierr); 3180 } 3181 ierr = MatSetType(*A,MATIS);CHKERRQ(ierr); 3182 if (rmap && cmap) { 3183 ierr = MatSetLocalToGlobalMapping(*A,rmap,cmap);CHKERRQ(ierr); 3184 } else if (!rmap) { 3185 ierr = MatSetLocalToGlobalMapping(*A,cmap,cmap);CHKERRQ(ierr); 3186 } else { 3187 ierr = MatSetLocalToGlobalMapping(*A,rmap,rmap);CHKERRQ(ierr); 3188 } 3189 PetscFunctionReturn(0); 3190 } 3191 3192 /*MC 3193 MATIS - MATIS = "is" - A matrix type to be used for using the non-overlapping domain decomposition methods (e.g. PCBDDC or KSPFETIDP). 3194 This stores the matrices in globally unassembled form. Each processor assembles only its local Neumann problem and the parallel matrix vector 3195 product is handled "implicitly". 3196 3197 Options Database Keys: 3198 + -mat_type is - sets the matrix type to "is" during a call to MatSetFromOptions() 3199 . -matis_fixempty - Fixes local matrices in case of empty local rows/columns. 3200 - -matis_storel2l - stores the local-to-local operators generated by the Galerkin process of MatPtAP(). 3201 3202 Notes: 3203 Options prefix for the inner matrix are given by -is_mat_xxx 3204 3205 You must call MatSetLocalToGlobalMapping() before using this matrix type. 3206 3207 You can do matrix preallocation on the local matrix after you obtain it with 3208 MatISGetLocalMat(); otherwise, you could use MatISSetPreallocation() 3209 3210 Level: advanced 3211 3212 .seealso: Mat, MatISGetLocalMat(), MatSetLocalToGlobalMapping(), MatISSetPreallocation(), MatCreateIS(), PCBDDC, KSPFETIDP 3213 3214 M*/ 3215 3216 PETSC_EXTERN PetscErrorCode MatCreate_IS(Mat A) 3217 { 3218 PetscErrorCode ierr; 3219 Mat_IS *b; 3220 3221 PetscFunctionBegin; 3222 ierr = PetscNewLog(A,&b);CHKERRQ(ierr); 3223 ierr = PetscStrallocpy(MATAIJ,&b->lmattype);CHKERRQ(ierr); 3224 A->data = (void*)b; 3225 3226 /* matrix ops */ 3227 ierr = PetscMemzero(A->ops,sizeof(struct _MatOps));CHKERRQ(ierr); 3228 A->ops->mult = MatMult_IS; 3229 A->ops->multadd = MatMultAdd_IS; 3230 A->ops->multtranspose = MatMultTranspose_IS; 3231 A->ops->multtransposeadd = MatMultTransposeAdd_IS; 3232 A->ops->destroy = MatDestroy_IS; 3233 A->ops->setlocaltoglobalmapping = MatSetLocalToGlobalMapping_IS; 3234 A->ops->setvalues = MatSetValues_IS; 3235 A->ops->setvaluesblocked = MatSetValuesBlocked_IS; 3236 A->ops->setvalueslocal = MatSetValuesLocal_IS; 3237 A->ops->setvaluesblockedlocal = MatSetValuesBlockedLocal_IS; 3238 A->ops->zerorows = MatZeroRows_IS; 3239 A->ops->zerorowscolumns = MatZeroRowsColumns_IS; 3240 A->ops->assemblybegin = MatAssemblyBegin_IS; 3241 A->ops->assemblyend = MatAssemblyEnd_IS; 3242 A->ops->view = MatView_IS; 3243 A->ops->zeroentries = MatZeroEntries_IS; 3244 A->ops->scale = MatScale_IS; 3245 A->ops->getdiagonal = MatGetDiagonal_IS; 3246 A->ops->setoption = MatSetOption_IS; 3247 A->ops->ishermitian = MatIsHermitian_IS; 3248 A->ops->issymmetric = MatIsSymmetric_IS; 3249 A->ops->isstructurallysymmetric = MatIsStructurallySymmetric_IS; 3250 A->ops->duplicate = MatDuplicate_IS; 3251 A->ops->missingdiagonal = MatMissingDiagonal_IS; 3252 A->ops->copy = MatCopy_IS; 3253 A->ops->getlocalsubmatrix = MatGetLocalSubMatrix_IS; 3254 A->ops->createsubmatrix = MatCreateSubMatrix_IS; 3255 A->ops->axpy = MatAXPY_IS; 3256 A->ops->diagonalset = MatDiagonalSet_IS; 3257 A->ops->shift = MatShift_IS; 3258 A->ops->transpose = MatTranspose_IS; 3259 A->ops->getinfo = MatGetInfo_IS; 3260 A->ops->diagonalscale = MatDiagonalScale_IS; 3261 A->ops->setfromoptions = MatSetFromOptions_IS; 3262 3263 /* special MATIS functions */ 3264 ierr = PetscObjectComposeFunction((PetscObject)A,"MatISSetLocalMatType_C",MatISSetLocalMatType_IS);CHKERRQ(ierr); 3265 ierr = PetscObjectComposeFunction((PetscObject)A,"MatISGetLocalMat_C",MatISGetLocalMat_IS);CHKERRQ(ierr); 3266 ierr = PetscObjectComposeFunction((PetscObject)A,"MatISRestoreLocalMat_C",MatISRestoreLocalMat_IS);CHKERRQ(ierr); 3267 ierr = PetscObjectComposeFunction((PetscObject)A,"MatISSetLocalMat_C",MatISSetLocalMat_IS);CHKERRQ(ierr); 3268 ierr = PetscObjectComposeFunction((PetscObject)A,"MatISGetMPIXAIJ_C",MatConvert_IS_XAIJ);CHKERRQ(ierr); 3269 ierr = PetscObjectComposeFunction((PetscObject)A,"MatISSetPreallocation_C",MatISSetPreallocation_IS);CHKERRQ(ierr); 3270 ierr = PetscObjectComposeFunction((PetscObject)A,"MatISStoreL2L_C",MatISStoreL2L_IS);CHKERRQ(ierr); 3271 ierr = PetscObjectComposeFunction((PetscObject)A,"MatISFixLocalEmpty_C",MatISFixLocalEmpty_IS);CHKERRQ(ierr); 3272 ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_is_mpiaij_C",MatConvert_IS_XAIJ);CHKERRQ(ierr); 3273 ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_is_mpibaij_C",MatConvert_IS_XAIJ);CHKERRQ(ierr); 3274 ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_is_mpisbaij_C",MatConvert_IS_XAIJ);CHKERRQ(ierr); 3275 ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_is_seqaij_C",MatConvert_IS_XAIJ);CHKERRQ(ierr); 3276 ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_is_seqbaij_C",MatConvert_IS_XAIJ);CHKERRQ(ierr); 3277 ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_is_seqsbaij_C",MatConvert_IS_XAIJ);CHKERRQ(ierr); 3278 ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_is_aij_C",MatConvert_IS_XAIJ);CHKERRQ(ierr); 3279 ierr = PetscObjectChangeTypeName((PetscObject)A,MATIS);CHKERRQ(ierr); 3280 PetscFunctionReturn(0); 3281 } 3282