1 #define PETSCMAT_DLL 2 3 #include "matnestimpl.h" /*I "petscmat.h" I*/ 4 5 /* private functions */ 6 #undef __FUNCT__ 7 #define __FUNCT__ "MatNestGetSize_Recursive" 8 static PetscErrorCode MatNestGetSize_Recursive(Mat A,PetscBool globalsize,PetscInt *M,PetscInt *N) 9 { 10 Mat_Nest *bA = (Mat_Nest*)A->data; 11 PetscInt sizeM,sizeN,i,j,index = -1; 12 PetscErrorCode ierr; 13 14 PetscFunctionBegin; 15 /* rows */ 16 /* now descend recursively */ 17 for (i=0; i<bA->nr; i++) { 18 for (j=0; j<bA->nc; j++) { 19 if (bA->m[i][j]) { index = j; break; } 20 } 21 if (bA->m[i][index]) { 22 if (globalsize) { ierr = MatGetSize(bA->m[i][index],&sizeM,&sizeN);CHKERRQ(ierr); } 23 else { ierr = MatGetLocalSize(bA->m[i][index],&sizeM,&sizeN);CHKERRQ(ierr); } 24 *M = *M + sizeM; 25 } 26 } 27 28 /* cols */ 29 /* now descend recursively */ 30 for (j=0; j<bA->nc; j++) { 31 for (i=0; i<bA->nr; i++) { 32 if (bA->m[i][j]) { index = i; break; } 33 } 34 if (bA->m[index][j]) { 35 if (globalsize) { ierr = MatGetSize(bA->m[index][j],&sizeM,&sizeN);CHKERRQ(ierr); } 36 else { ierr = MatGetLocalSize(bA->m[index][j],&sizeM,&sizeN);CHKERRQ(ierr); } 37 *N = *N + sizeN; 38 } 39 } 40 PetscFunctionReturn(0); 41 } 42 43 #undef __FUNCT__ 44 #define __FUNCT__ "PETSc_MatNest_CheckMatVecCompatibility2" 45 PETSC_UNUSED 46 static PetscErrorCode PETSc_MatNest_CheckMatVecCompatibility2(Mat A,Vec x,Vec y) 47 { 48 PetscBool isANest, isxNest, isyNest; 49 PetscErrorCode ierr; 50 51 PetscFunctionBegin; 52 isANest = isxNest = isyNest = PETSC_FALSE; 53 ierr = PetscTypeCompare( (PetscObject)A, MATNEST, &isANest );CHKERRQ(ierr); 54 ierr = PetscTypeCompare( (PetscObject)x, VECNEST, &isxNest );CHKERRQ(ierr); 55 ierr = PetscTypeCompare( (PetscObject)y, VECNEST, &isyNest );CHKERRQ(ierr); 56 57 if (isANest && isxNest && isyNest) { 58 PetscFunctionReturn(0); 59 } else { 60 SETERRQ( ((PetscObject)A)->comm, PETSC_ERR_SUP, "Operation only valid for Mat(Nest)-Vec(Nest) combinations"); 61 PetscFunctionReturn(0); 62 } 63 PetscFunctionReturn(0); 64 } 65 66 /* 67 This function is called every time we insert a sub matrix the Nest. 68 It ensures that every Nest along row r, and col c has the same dimensions 69 as the submat being inserted. 70 */ 71 #undef __FUNCT__ 72 #define __FUNCT__ "PETSc_MatNest_CheckConsistency" 73 PETSC_UNUSED 74 static PetscErrorCode PETSc_MatNest_CheckConsistency(Mat A,Mat submat,PetscInt r,PetscInt c) 75 { 76 Mat_Nest *b = (Mat_Nest*)A->data; 77 PetscInt i,j; 78 PetscInt nr,nc; 79 PetscInt sM,sN,M,N; 80 Mat mat; 81 PetscErrorCode ierr; 82 83 PetscFunctionBegin; 84 nr = b->nr; 85 nc = b->nc; 86 ierr = MatGetSize(submat,&sM,&sN);CHKERRQ(ierr); 87 for (i=0; i<nr; i++) { 88 mat = b->m[i][c]; 89 if (mat) { 90 ierr = MatGetSize(mat,&M,&N);CHKERRQ(ierr); 91 /* Check columns match */ 92 if (sN != N) { 93 SETERRQ3(((PetscObject)A)->comm,PETSC_ERR_SUP,"Inserted incompatible submatrix into Nest at (%D,%D). Submatrix must have %D rows",r,c,N ); 94 } 95 } 96 } 97 98 for (j=0; j<nc; j++) { 99 mat = b->m[r][j]; 100 if (mat) { 101 ierr = MatGetSize(mat,&M,&N);CHKERRQ(ierr); 102 /* Check rows match */ 103 if (sM != M) { 104 SETERRQ3(((PetscObject)A)->comm,PETSC_ERR_SUP,"Inserted incompatible submatrix into Nest at (%D,%D). Submatrix must have %D cols",r,c,M ); 105 } 106 } 107 } 108 PetscFunctionReturn(0); 109 } 110 111 /* 112 Checks if the row/col's contain a complete set of IS's. 113 Once they are filled, the offsets are computed. This saves having to update 114 the index set entries each time we insert something new. 115 */ 116 #undef __FUNCT__ 117 #define __FUNCT__ "PETSc_MatNest_UpdateStructure" 118 PETSC_UNUSED 119 static PetscErrorCode PETSc_MatNest_UpdateStructure(Mat A,PetscInt ridx,PetscInt cidx) 120 { 121 Mat_Nest *b = (Mat_Nest*)A->data; 122 PetscInt m,n,i,j; 123 PetscBool fullrow,fullcol; 124 PetscErrorCode ierr; 125 126 PetscFunctionBegin; 127 ierr = MatGetLocalSize(b->m[ridx][cidx],&m,&n);CHKERRQ(ierr); 128 b->row_len[ridx] = m; 129 b->col_len[cidx] = n; 130 131 fullrow = PETSC_TRUE; 132 for (i=0; i<b->nr; i++) { 133 if (b->row_len[i]==-1) { fullrow = PETSC_FALSE; break; } 134 } 135 if ( (fullrow) && (!b->isglobal.row[0]) ){ 136 PetscInt cnt = 0; 137 for (i=0; i<b->nr; i++) { 138 ierr = ISCreateStride(PETSC_COMM_SELF,b->row_len[i],cnt,1,&b->isglobal.row[i]);CHKERRQ(ierr); 139 cnt = cnt + b->row_len[i]; 140 } 141 } 142 143 fullcol = PETSC_TRUE; 144 for (j=0; j<b->nc; j++) { 145 if (b->col_len[j]==-1) { fullcol = PETSC_FALSE; break; } 146 } 147 if( (fullcol) && (!b->isglobal.col[0]) ){ 148 PetscInt cnt = 0; 149 for (j=0; j<b->nc; j++) { 150 ierr = ISCreateStride(PETSC_COMM_SELF,b->col_len[j],cnt,1,&b->isglobal.col[j]);CHKERRQ(ierr); 151 cnt = cnt + b->col_len[j]; 152 } 153 } 154 PetscFunctionReturn(0); 155 } 156 157 /* operations */ 158 #undef __FUNCT__ 159 #define __FUNCT__ "MatMult_Nest" 160 static PetscErrorCode MatMult_Nest(Mat A,Vec x,Vec y) 161 { 162 Mat_Nest *bA = (Mat_Nest*)A->data; 163 Vec *bx = bA->right,*by = bA->left; 164 PetscInt i,j,nr = bA->nr,nc = bA->nc; 165 PetscErrorCode ierr; 166 167 PetscFunctionBegin; 168 for (i=0; i<nr; i++) {ierr = VecGetSubVector(y,bA->isglobal.row[i],&by[i]);CHKERRQ(ierr);} 169 for (i=0; i<nc; i++) {ierr = VecGetSubVector(x,bA->isglobal.col[i],&bx[i]);CHKERRQ(ierr);} 170 for (i=0; i<nr; i++) { 171 ierr = VecZeroEntries(by[i]);CHKERRQ(ierr); 172 for (j=0; j<nc; j++) { 173 if (!bA->m[i][j]) continue; 174 /* y[i] <- y[i] + A[i][j] * x[j] */ 175 ierr = MatMultAdd(bA->m[i][j],bx[j],by[i],by[i]);CHKERRQ(ierr); 176 } 177 } 178 for (i=0; i<nr; i++) {ierr = VecRestoreSubVector(y,bA->isglobal.row[i],&by[i]);CHKERRQ(ierr);} 179 for (i=0; i<nc; i++) {ierr = VecRestoreSubVector(x,bA->isglobal.col[i],&bx[i]);CHKERRQ(ierr);} 180 PetscFunctionReturn(0); 181 } 182 183 #undef __FUNCT__ 184 #define __FUNCT__ "MatMultTranspose_Nest" 185 static PetscErrorCode MatMultTranspose_Nest(Mat A,Vec x,Vec y) 186 { 187 Mat_Nest *bA = (Mat_Nest*)A->data; 188 Vec *bx = bA->left,*by = bA->right; 189 PetscInt i,j,nr = bA->nr,nc = bA->nc; 190 PetscErrorCode ierr; 191 192 PetscFunctionBegin; 193 if (A->symmetric) { 194 ierr = MatMult_Nest(A,x,y);CHKERRQ(ierr); 195 PetscFunctionReturn(0); 196 } 197 for (i=0; i<nr; i++) {ierr = VecGetSubVector(y,bA->isglobal.row[i],&bx[i]);CHKERRQ(ierr);} 198 for (i=0; i<nc; i++) {ierr = VecGetSubVector(x,bA->isglobal.col[i],&by[i]);CHKERRQ(ierr);} 199 for (i=0; i<nr; i++) { 200 ierr = VecZeroEntries(by[i]);CHKERRQ(ierr); 201 for (j=0; j<nc; j++) { 202 if (!bA->m[j][i]) continue; 203 /* y[i] <- y[i] + A^T[i][j] * x[j], so we swap i,j in mat[][] */ 204 ierr = MatMultTransposeAdd(bA->m[j][i],bx[j],by[i],by[i]);CHKERRQ(ierr); 205 } 206 } 207 for (i=0; i<nr; i++) {ierr = VecRestoreSubVector(y,bA->isglobal.row[i],&bx[i]);CHKERRQ(ierr);} 208 for (i=0; i<nc; i++) {ierr = VecRestoreSubVector(x,bA->isglobal.col[i],&by[i]);CHKERRQ(ierr);} 209 PetscFunctionReturn(0); 210 } 211 212 #undef __FUNCT__ 213 #define __FUNCT__ "MatNestDestroyISList" 214 static PetscErrorCode MatNestDestroyISList(PetscInt n,IS **list) 215 { 216 PetscErrorCode ierr; 217 IS *lst = *list; 218 PetscInt i; 219 220 PetscFunctionBegin; 221 if (!lst) PetscFunctionReturn(0); 222 for (i=0; i<n; i++) if (lst[i]) {ierr = ISDestroy(lst[i]);CHKERRQ(ierr);} 223 ierr = PetscFree(lst);CHKERRQ(ierr); 224 *list = PETSC_NULL; 225 PetscFunctionReturn(0); 226 } 227 228 #undef __FUNCT__ 229 #define __FUNCT__ "MatDestroy_Nest" 230 static PetscErrorCode MatDestroy_Nest(Mat A) 231 { 232 Mat_Nest *vs = (Mat_Nest*)A->data; 233 PetscInt i,j; 234 PetscErrorCode ierr; 235 236 PetscFunctionBegin; 237 /* release the matrices and the place holders */ 238 ierr = MatNestDestroyISList(vs->nr,&vs->isglobal.row);CHKERRQ(ierr); 239 ierr = MatNestDestroyISList(vs->nc,&vs->isglobal.col);CHKERRQ(ierr); 240 ierr = MatNestDestroyISList(vs->nr,&vs->islocal.row);CHKERRQ(ierr); 241 ierr = MatNestDestroyISList(vs->nc,&vs->islocal.col);CHKERRQ(ierr); 242 243 ierr = PetscFree(vs->row_len);CHKERRQ(ierr); 244 ierr = PetscFree(vs->col_len);CHKERRQ(ierr); 245 246 ierr = PetscFree2(vs->left,vs->right);CHKERRQ(ierr); 247 248 /* release the matrices and the place holders */ 249 if (vs->m) { 250 for (i=0; i<vs->nr; i++) { 251 for (j=0; j<vs->nc; j++) { 252 253 if (vs->m[i][j]) { 254 ierr = MatDestroy(vs->m[i][j]);CHKERRQ(ierr); 255 vs->m[i][j] = PETSC_NULL; 256 } 257 } 258 ierr = PetscFree( vs->m[i] );CHKERRQ(ierr); 259 vs->m[i] = PETSC_NULL; 260 } 261 ierr = PetscFree(vs->m);CHKERRQ(ierr); 262 vs->m = PETSC_NULL; 263 } 264 ierr = PetscFree(vs);CHKERRQ(ierr); 265 266 PetscFunctionReturn(0); 267 } 268 269 #undef __FUNCT__ 270 #define __FUNCT__ "MatAssemblyBegin_Nest" 271 static PetscErrorCode MatAssemblyBegin_Nest(Mat A,MatAssemblyType type) 272 { 273 Mat_Nest *vs = (Mat_Nest*)A->data; 274 PetscInt i,j; 275 PetscErrorCode ierr; 276 277 PetscFunctionBegin; 278 for (i=0; i<vs->nr; i++) { 279 for (j=0; j<vs->nc; j++) { 280 if (vs->m[i][j]) { ierr = MatAssemblyBegin(vs->m[i][j],type);CHKERRQ(ierr); } 281 } 282 } 283 PetscFunctionReturn(0); 284 } 285 286 #undef __FUNCT__ 287 #define __FUNCT__ "MatAssemblyEnd_Nest" 288 static PetscErrorCode MatAssemblyEnd_Nest(Mat A, MatAssemblyType type) 289 { 290 Mat_Nest *vs = (Mat_Nest*)A->data; 291 PetscInt i,j; 292 PetscErrorCode ierr; 293 294 PetscFunctionBegin; 295 for (i=0; i<vs->nr; i++) { 296 for (j=0; j<vs->nc; j++) { 297 if (vs->m[i][j]) { ierr = MatAssemblyEnd(vs->m[i][j],type);CHKERRQ(ierr); } 298 } 299 } 300 PetscFunctionReturn(0); 301 } 302 303 #undef __FUNCT__ 304 #define __FUNCT__ "MatNestFindNonzeroSubMatRow" 305 static PetscErrorCode MatNestFindNonzeroSubMatRow(Mat A,PetscInt row,Mat *B) 306 { 307 PetscErrorCode ierr; 308 Mat_Nest *vs = (Mat_Nest*)A->data; 309 PetscInt j; 310 Mat sub; 311 312 PetscFunctionBegin; 313 sub = vs->m[row][row]; /* Prefer to find on the diagonal */ 314 for (j=0; !sub && j<vs->nc; j++) sub = vs->m[row][j]; 315 if (!sub) SETERRQ1(((PetscObject)A)->comm,PETSC_ERR_ARG_WRONG,"No nonzero submatrix in row %D",row); 316 ierr = MatPreallocated(sub);CHKERRQ(ierr); /* Ensure that the sizes are available */ 317 *B = sub; 318 PetscFunctionReturn(0); 319 } 320 321 #undef __FUNCT__ 322 #define __FUNCT__ "MatNestFindNonzeroSubMatCol" 323 static PetscErrorCode MatNestFindNonzeroSubMatCol(Mat A,PetscInt col,Mat *B) 324 { 325 PetscErrorCode ierr; 326 Mat_Nest *vs = (Mat_Nest*)A->data; 327 PetscInt i; 328 Mat sub; 329 330 PetscFunctionBegin; 331 sub = vs->m[col][col]; /* Prefer to find on the diagonal */ 332 for (i=0; !sub && i<vs->nr; i++) sub = vs->m[i][col]; 333 if (!sub) SETERRQ1(((PetscObject)A)->comm,PETSC_ERR_ARG_WRONG,"No nonzero submatrix in column %D",col); 334 ierr = MatPreallocated(sub);CHKERRQ(ierr); /* Ensure that the sizes are available */ 335 *B = sub; 336 PetscFunctionReturn(0); 337 } 338 339 #undef __FUNCT__ 340 #define __FUNCT__ "MatNestFindIS" 341 static PetscErrorCode MatNestFindIS(Mat A,PetscInt n,const IS list[],IS is,PetscInt *found) 342 { 343 PetscErrorCode ierr; 344 PetscInt i; 345 PetscBool flg; 346 347 PetscFunctionBegin; 348 PetscValidPointer(list,3); 349 PetscValidHeaderSpecific(is,IS_CLASSID,4); 350 PetscValidIntPointer(found,5); 351 *found = -1; 352 for (i=0; i<n; i++) { 353 if (!list[i]) continue; 354 ierr = ISEqual(list[i],is,&flg);CHKERRQ(ierr); 355 if (flg) { 356 *found = i; 357 PetscFunctionReturn(0); 358 } 359 } 360 SETERRQ(((PetscObject)A)->comm,PETSC_ERR_ARG_INCOMP,"Could not find index set"); 361 PetscFunctionReturn(0); 362 } 363 364 #undef __FUNCT__ 365 #define __FUNCT__ "MatNestFindSubMat" 366 static PetscErrorCode MatNestFindSubMat(Mat A,struct MatNestISPair *is,IS isrow,IS iscol,Mat *B) 367 { 368 PetscErrorCode ierr; 369 Mat_Nest *vs = (Mat_Nest*)A->data; 370 PetscInt row,col; 371 372 PetscFunctionBegin; 373 ierr = MatNestFindIS(A,vs->nr,is->row,isrow,&row);CHKERRQ(ierr); 374 ierr = MatNestFindIS(A,vs->nc,is->col,iscol,&col);CHKERRQ(ierr); 375 *B = vs->m[row][col]; 376 PetscFunctionReturn(0); 377 } 378 379 #undef __FUNCT__ 380 #define __FUNCT__ "MatGetSubMatrix_Nest" 381 static PetscErrorCode MatGetSubMatrix_Nest(Mat A,IS isrow,IS iscol,MatReuse reuse,Mat *B) 382 { 383 PetscErrorCode ierr; 384 Mat_Nest *vs = (Mat_Nest*)A->data; 385 Mat sub; 386 387 PetscFunctionBegin; 388 ierr = MatNestFindSubMat(A,&vs->isglobal,isrow,iscol,&sub);CHKERRQ(ierr); 389 switch (reuse) { 390 case MAT_INITIAL_MATRIX: 391 ierr = PetscObjectReference((PetscObject)sub);CHKERRQ(ierr); 392 *B = sub; 393 break; 394 case MAT_REUSE_MATRIX: 395 if (sub != *B) SETERRQ(((PetscObject)A)->comm,PETSC_ERR_ARG_WRONGSTATE,"Submatrix was not used before in this call"); 396 break; 397 case MAT_IGNORE_MATRIX: /* Nothing to do */ 398 break; 399 } 400 PetscFunctionReturn(0); 401 } 402 403 #undef __FUNCT__ 404 #define __FUNCT__ "MatGetLocalSubMatrix_Nest" 405 PetscErrorCode MatGetLocalSubMatrix_Nest(Mat A,IS isrow,IS iscol,Mat *B) 406 { 407 PetscErrorCode ierr; 408 Mat_Nest *vs = (Mat_Nest*)A->data; 409 Mat sub; 410 411 PetscFunctionBegin; 412 ierr = MatNestFindSubMat(A,&vs->islocal,isrow,iscol,&sub);CHKERRQ(ierr); 413 /* We allow the submatrix to be NULL, perhaps it would be better for the user to return an empty matrix instead */ 414 if (sub) {ierr = PetscObjectReference((PetscObject)sub);CHKERRQ(ierr);} 415 *B = sub; 416 PetscFunctionReturn(0); 417 } 418 419 #undef __FUNCT__ 420 #define __FUNCT__ "MatRestoreLocalSubMatrix_Nest" 421 static PetscErrorCode MatRestoreLocalSubMatrix_Nest(Mat A,IS isrow,IS iscol,Mat *B) 422 { 423 PetscErrorCode ierr; 424 Mat_Nest *vs = (Mat_Nest*)A->data; 425 Mat sub; 426 427 PetscFunctionBegin; 428 ierr = MatNestFindSubMat(A,&vs->islocal,isrow,iscol,&sub);CHKERRQ(ierr); 429 if (*B != sub) SETERRQ(((PetscObject)A)->comm,PETSC_ERR_ARG_WRONGSTATE,"Local submatrix has not been gotten"); 430 if (sub) { 431 if (((PetscObject)sub)->refct <= 1) SETERRQ(((PetscObject)A)->comm,PETSC_ERR_ARG_WRONGSTATE,"Local submatrix has had reference count decremented too many times"); 432 ierr = MatDestroy(*B);CHKERRQ(ierr); 433 } 434 *B = PETSC_NULL; 435 PetscFunctionReturn(0); 436 } 437 438 #undef __FUNCT__ 439 #define __FUNCT__ "MatGetVecs_Nest" 440 static PetscErrorCode MatGetVecs_Nest(Mat A,Vec *right,Vec *left) 441 { 442 Mat_Nest *bA = (Mat_Nest*)A->data; 443 Vec *L,*R; 444 MPI_Comm comm; 445 PetscInt i,j; 446 PetscErrorCode ierr; 447 448 PetscFunctionBegin; 449 comm = ((PetscObject)A)->comm; 450 if (right) { 451 /* allocate R */ 452 ierr = PetscMalloc( sizeof(Vec) * bA->nc, &R );CHKERRQ(ierr); 453 /* Create the right vectors */ 454 for (j=0; j<bA->nc; j++) { 455 for (i=0; i<bA->nr; i++) { 456 if (bA->m[i][j]) { 457 ierr = MatGetVecs(bA->m[i][j],&R[j],PETSC_NULL);CHKERRQ(ierr); 458 break; 459 } 460 } 461 if (i==bA->nr) { 462 /* have an empty column */ 463 SETERRQ( ((PetscObject)A)->comm, PETSC_ERR_ARG_WRONG, "Mat(Nest) contains a null column."); 464 } 465 } 466 ierr = VecCreateNest(comm,bA->nc,bA->isglobal.col,R,right);CHKERRQ(ierr); 467 /* hand back control to the nest vector */ 468 for (j=0; j<bA->nc; j++) { 469 ierr = VecDestroy(R[j]);CHKERRQ(ierr); 470 } 471 ierr = PetscFree(R);CHKERRQ(ierr); 472 } 473 474 if (left) { 475 /* allocate L */ 476 ierr = PetscMalloc( sizeof(Vec) * bA->nr, &L );CHKERRQ(ierr); 477 /* Create the left vectors */ 478 for (i=0; i<bA->nr; i++) { 479 for (j=0; j<bA->nc; j++) { 480 if (bA->m[i][j]) { 481 ierr = MatGetVecs(bA->m[i][j],PETSC_NULL,&L[i]);CHKERRQ(ierr); 482 break; 483 } 484 } 485 if (j==bA->nc) { 486 /* have an empty row */ 487 SETERRQ( ((PetscObject)A)->comm, PETSC_ERR_ARG_WRONG, "Mat(Nest) contains a null row."); 488 } 489 } 490 491 ierr = VecCreateNest(comm,bA->nr,bA->isglobal.row,L,left);CHKERRQ(ierr); 492 for (i=0; i<bA->nr; i++) { 493 ierr = VecDestroy(L[i]);CHKERRQ(ierr); 494 } 495 496 ierr = PetscFree(L);CHKERRQ(ierr); 497 } 498 PetscFunctionReturn(0); 499 } 500 501 #undef __FUNCT__ 502 #define __FUNCT__ "MatView_Nest" 503 static PetscErrorCode MatView_Nest(Mat A,PetscViewer viewer) 504 { 505 Mat_Nest *bA = (Mat_Nest*)A->data; 506 PetscBool isascii; 507 PetscInt i,j; 508 PetscErrorCode ierr; 509 510 PetscFunctionBegin; 511 ierr = PetscTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&isascii);CHKERRQ(ierr); 512 if (isascii) { 513 514 PetscViewerASCIIPrintf(viewer,"Matrix object: \n" ); 515 PetscViewerASCIIPushTab( viewer ); /* push0 */ 516 PetscViewerASCIIPrintf( viewer, "type=nest, rows=%d, cols=%d \n",bA->nr,bA->nc); 517 518 PetscViewerASCIIPrintf(viewer,"MatNest structure: \n" ); 519 for (i=0; i<bA->nr; i++) { 520 for (j=0; j<bA->nc; j++) { 521 const MatType type; 522 const char *name; 523 PetscInt NR,NC; 524 PetscBool isNest = PETSC_FALSE; 525 526 if (!bA->m[i][j]) { 527 PetscViewerASCIIPrintf( viewer, "(%D,%D) : PETSC_NULL \n",i,j); 528 continue; 529 } 530 ierr = MatGetSize(bA->m[i][j],&NR,&NC);CHKERRQ(ierr); 531 ierr = MatGetType( bA->m[i][j], &type );CHKERRQ(ierr); 532 name = ((PetscObject)bA->m[i][j])->prefix; 533 ierr = PetscTypeCompare((PetscObject)bA->m[i][j],MATNEST,&isNest);CHKERRQ(ierr); 534 535 PetscViewerASCIIPrintf( viewer, "(%D,%D) : name=\"%s\", type=%s, rows=%D, cols=%D \n",i,j,name,type,NR,NC); 536 537 if (isNest) { 538 PetscViewerASCIIPushTab( viewer ); /* push1 */ 539 ierr = MatView( bA->m[i][j], viewer );CHKERRQ(ierr); 540 PetscViewerASCIIPopTab(viewer); /* pop1 */ 541 } 542 } 543 } 544 PetscViewerASCIIPopTab(viewer); /* pop0 */ 545 } 546 PetscFunctionReturn(0); 547 } 548 549 #undef __FUNCT__ 550 #define __FUNCT__ "MatZeroEntries_Nest" 551 static PetscErrorCode MatZeroEntries_Nest(Mat A) 552 { 553 Mat_Nest *bA = (Mat_Nest*)A->data; 554 PetscInt i,j; 555 PetscErrorCode ierr; 556 557 PetscFunctionBegin; 558 for (i=0; i<bA->nr; i++) { 559 for (j=0; j<bA->nc; j++) { 560 if (!bA->m[i][j]) continue; 561 ierr = MatZeroEntries(bA->m[i][j]);CHKERRQ(ierr); 562 } 563 } 564 PetscFunctionReturn(0); 565 } 566 567 #undef __FUNCT__ 568 #define __FUNCT__ "MatDuplicate_Nest" 569 static PetscErrorCode MatDuplicate_Nest(Mat A,MatDuplicateOption op,Mat *B) 570 { 571 Mat_Nest *bA = (Mat_Nest*)A->data; 572 Mat *b; 573 PetscInt i,j,nr = bA->nr,nc = bA->nc; 574 PetscErrorCode ierr; 575 576 PetscFunctionBegin; 577 ierr = PetscMalloc(nr*nc*sizeof(Mat),&b);CHKERRQ(ierr); 578 for (i=0; i<nr; i++) { 579 for (j=0; j<nc; j++) { 580 if (bA->m[i][j]) { 581 ierr = MatDuplicate(bA->m[i][j],op,&b[i*nc+j]);CHKERRQ(ierr); 582 } else { 583 b[i*nc+j] = PETSC_NULL; 584 } 585 } 586 } 587 ierr = MatCreateNest(((PetscObject)A)->comm,nr,bA->isglobal.row,nc,bA->isglobal.col,b,B);CHKERRQ(ierr); 588 /* Give the new MatNest exclusive ownership */ 589 for (i=0; i<nr*nc; i++) { 590 if (b[i]) {ierr = MatDestroy(b[i]);CHKERRQ(ierr);} 591 } 592 ierr = PetscFree(b);CHKERRQ(ierr); 593 594 ierr = MatAssemblyBegin(*B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 595 ierr = MatAssemblyEnd(*B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 596 PetscFunctionReturn(0); 597 } 598 599 /* nest api */ 600 EXTERN_C_BEGIN 601 #undef __FUNCT__ 602 #define __FUNCT__ "MatNestGetSubMat_Nest" 603 PetscErrorCode MatNestGetSubMat_Nest(Mat A,PetscInt idxm,PetscInt jdxm,Mat *mat) 604 { 605 Mat_Nest *bA = (Mat_Nest*)A->data; 606 PetscFunctionBegin; 607 if (idxm >= bA->nr) SETERRQ2(((PetscObject)A)->comm,PETSC_ERR_ARG_OUTOFRANGE,"Row too large: row %D max %D",idxm,bA->nr-1); 608 if (jdxm >= bA->nc) SETERRQ2(((PetscObject)A)->comm,PETSC_ERR_ARG_OUTOFRANGE,"Col too large: row %D max %D",jdxm,bA->nc-1); 609 *mat = bA->m[idxm][jdxm]; 610 PetscFunctionReturn(0); 611 } 612 EXTERN_C_END 613 614 #undef __FUNCT__ 615 #define __FUNCT__ "MatNestGetSubMat" 616 /*@C 617 MatNestGetSubMat - Returns a single, sub-matrix from a nest matrix. 618 619 Not collective 620 621 Input Parameters: 622 . A - nest matrix 623 . idxm - index of the matrix within the nest matrix 624 . jdxm - index of the matrix within the nest matrix 625 626 Output Parameter: 627 . sub - matrix at index idxm,jdxm within the nest matrix 628 629 Notes: 630 631 Level: developer 632 633 .seealso: MatNestGetSize(), MatNestGetSubMats() 634 @*/ 635 PetscErrorCode MatNestGetSubMat(Mat A,PetscInt idxm,PetscInt jdxm,Mat *sub) 636 { 637 PetscErrorCode ierr; 638 639 PetscFunctionBegin; 640 ierr = PetscUseMethod(A,"MatNestGetSubMat_C",(Mat,PetscInt,PetscInt,Mat*),(A,idxm,jdxm,sub));CHKERRQ(ierr); 641 PetscFunctionReturn(0); 642 } 643 644 EXTERN_C_BEGIN 645 #undef __FUNCT__ 646 #define __FUNCT__ "MatNestGetSubMats_Nest" 647 PetscErrorCode MatNestGetSubMats_Nest(Mat A,PetscInt *M,PetscInt *N,Mat ***mat) 648 { 649 Mat_Nest *bA = (Mat_Nest*)A->data; 650 PetscFunctionBegin; 651 if (M) { *M = bA->nr; } 652 if (N) { *N = bA->nc; } 653 if (mat) { *mat = bA->m; } 654 PetscFunctionReturn(0); 655 } 656 EXTERN_C_END 657 658 #undef __FUNCT__ 659 #define __FUNCT__ "MatNestGetSubMats" 660 /*@C 661 MatNestGetSubMats - Returns the entire two dimensional array of matrices defining a nest matrix. 662 663 Not collective 664 665 Input Parameters: 666 . A - nest matri 667 668 Output Parameter: 669 . M - number of rows in the nest matrix 670 . N - number of cols in the nest matrix 671 . mat - 2d array of matrices 672 673 Notes: 674 675 The user should not free the array mat. 676 677 Level: developer 678 679 .seealso: MatNestGetSize(), MatNestGetSubMat() 680 @*/ 681 PetscErrorCode MatNestGetSubMats(Mat A,PetscInt *M,PetscInt *N,Mat ***mat) 682 { 683 PetscErrorCode ierr; 684 685 PetscFunctionBegin; 686 ierr = PetscUseMethod(A,"MatNestGetSubMats_C",(Mat,PetscInt*,PetscInt*,Mat***),(A,M,N,mat));CHKERRQ(ierr); 687 PetscFunctionReturn(0); 688 } 689 690 EXTERN_C_BEGIN 691 #undef __FUNCT__ 692 #define __FUNCT__ "MatNestGetSize_Nest" 693 PetscErrorCode MatNestGetSize_Nest(Mat A,PetscInt *M,PetscInt *N) 694 { 695 Mat_Nest *bA = (Mat_Nest*)A->data; 696 697 PetscFunctionBegin; 698 if (M) { *M = bA->nr; } 699 if (N) { *N = bA->nc; } 700 PetscFunctionReturn(0); 701 } 702 EXTERN_C_END 703 704 #undef __FUNCT__ 705 #define __FUNCT__ "MatNestGetSize" 706 /*@C 707 MatNestGetSize - Returns the size of the nest matrix. 708 709 Not collective 710 711 Input Parameters: 712 . A - nest matrix 713 714 Output Parameter: 715 . M - number of rows in the nested mat 716 . N - number of cols in the nested mat 717 718 Notes: 719 720 Level: developer 721 722 .seealso: MatNestGetSubMat(), MatNestGetSubMats() 723 @*/ 724 PetscErrorCode MatNestGetSize(Mat A,PetscInt *M,PetscInt *N) 725 { 726 PetscErrorCode ierr; 727 728 PetscFunctionBegin; 729 ierr = PetscUseMethod(A,"MatNestGetSize_C",(Mat,PetscInt*,PetscInt*),(A,M,N));CHKERRQ(ierr); 730 PetscFunctionReturn(0); 731 } 732 733 EXTERN_C_BEGIN 734 #undef __FUNCT__ 735 #define __FUNCT__ "MatNestSetVecType_Nest" 736 PetscErrorCode MatNestSetVecType_Nest(Mat A,const VecType vtype) 737 { 738 PetscErrorCode ierr; 739 PetscBool flg; 740 741 PetscFunctionBegin; 742 ierr = PetscStrcmp(vtype,VECNEST,&flg);CHKERRQ(ierr); 743 /* In reality, this only distinguishes VECNEST and "other" */ 744 A->ops->getvecs = flg ? MatGetVecs_Nest : 0; 745 PetscFunctionReturn(0); 746 } 747 EXTERN_C_END 748 749 #undef __FUNCT__ 750 #define __FUNCT__ "MatNestSetVecType" 751 /*@C 752 MatNestSetVecType - Sets the type of Vec returned by MatGetVecs() 753 754 Not collective 755 756 Input Parameters: 757 + A - nest matrix 758 - vtype - type to use for creating vectors 759 760 Notes: 761 762 Level: developer 763 764 .seealso: MatGetVecs() 765 @*/ 766 PetscErrorCode MatNestSetVecType(Mat A,const VecType vtype) 767 { 768 PetscErrorCode ierr; 769 770 PetscFunctionBegin; 771 ierr = PetscTryMethod(A,"MatNestSetVecType_C",(Mat,const VecType),(A,vtype));CHKERRQ(ierr); 772 PetscFunctionReturn(0); 773 } 774 775 /* constructor */ 776 #undef __FUNCT__ 777 #define __FUNCT__ "MatNestSetOps_Private" 778 static PetscErrorCode MatNestSetOps_Private(struct _MatOps* ops) 779 { 780 PetscFunctionBegin; 781 /* 0*/ 782 ops->setvalues = 0; 783 ops->getrow = 0; 784 ops->restorerow = 0; 785 ops->mult = MatMult_Nest; 786 ops->multadd = 0; 787 /* 5*/ 788 ops->multtranspose = MatMultTranspose_Nest; 789 ops->multtransposeadd = 0; 790 ops->solve = 0; 791 ops->solveadd = 0; 792 ops->solvetranspose = 0; 793 /*10*/ 794 ops->solvetransposeadd = 0; 795 ops->lufactor = 0; 796 ops->choleskyfactor = 0; 797 ops->sor = 0; 798 ops->transpose = 0; 799 /*15*/ 800 ops->getinfo = 0; 801 ops->equal = 0; 802 ops->getdiagonal = 0; 803 ops->diagonalscale = 0; 804 ops->norm = 0; 805 /*20*/ 806 ops->assemblybegin = MatAssemblyBegin_Nest; 807 ops->assemblyend = MatAssemblyEnd_Nest; 808 ops->setoption = 0; 809 ops->zeroentries = MatZeroEntries_Nest; 810 /*24*/ 811 ops->zerorows = 0; 812 ops->lufactorsymbolic = 0; 813 ops->lufactornumeric = 0; 814 ops->choleskyfactorsymbolic = 0; 815 ops->choleskyfactornumeric = 0; 816 /*29*/ 817 ops->setuppreallocation = 0; 818 ops->ilufactorsymbolic = 0; 819 ops->iccfactorsymbolic = 0; 820 ops->getarray = 0; 821 ops->restorearray = 0; 822 /*34*/ 823 ops->duplicate = MatDuplicate_Nest; 824 ops->forwardsolve = 0; 825 ops->backwardsolve = 0; 826 ops->ilufactor = 0; 827 ops->iccfactor = 0; 828 /*39*/ 829 ops->axpy = 0; 830 ops->getsubmatrices = 0; 831 ops->increaseoverlap = 0; 832 ops->getvalues = 0; 833 ops->copy = 0; 834 /*44*/ 835 ops->getrowmax = 0; 836 ops->scale = 0; 837 ops->shift = 0; 838 ops->diagonalset = 0; 839 ops->zerorowscolumns = 0; 840 /*49*/ 841 ops->setblocksize = 0; 842 ops->getrowij = 0; 843 ops->restorerowij = 0; 844 ops->getcolumnij = 0; 845 ops->restorecolumnij = 0; 846 /*54*/ 847 ops->fdcoloringcreate = 0; 848 ops->coloringpatch = 0; 849 ops->setunfactored = 0; 850 ops->permute = 0; 851 ops->setvaluesblocked = 0; 852 /*59*/ 853 ops->getsubmatrix = MatGetSubMatrix_Nest; 854 ops->destroy = MatDestroy_Nest; 855 ops->view = MatView_Nest; 856 ops->convertfrom = 0; 857 ops->usescaledform = 0; 858 /*64*/ 859 ops->scalesystem = 0; 860 ops->unscalesystem = 0; 861 ops->setlocaltoglobalmapping = 0; 862 ops->setvalueslocal = 0; 863 ops->zerorowslocal = 0; 864 /*69*/ 865 ops->getrowmaxabs = 0; 866 ops->getrowminabs = 0; 867 ops->convert = 0; 868 ops->setcoloring = 0; 869 ops->setvaluesadic = 0; 870 /* 74 */ 871 ops->setvaluesadifor = 0; 872 ops->fdcoloringapply = 0; 873 ops->setfromoptions = 0; 874 ops->multconstrained = 0; 875 ops->multtransposeconstrained = 0; 876 /*79*/ 877 ops->findzerodiagonals = 0; 878 ops->mults = 0; 879 ops->solves = 0; 880 ops->getinertia = 0; 881 ops->load = 0; 882 /*84*/ 883 ops->issymmetric = 0; 884 ops->ishermitian = 0; 885 ops->isstructurallysymmetric = 0; 886 ops->dummy4 = 0; 887 ops->getvecs = 0; /* Use VECNEST by calling MatNestSetVecType(A,VECNEST) */ 888 /*89*/ 889 ops->matmult = 0; 890 ops->matmultsymbolic = 0; 891 ops->matmultnumeric = 0; 892 ops->ptap = 0; 893 ops->ptapsymbolic = 0; 894 /*94*/ 895 ops->ptapnumeric = 0; 896 ops->matmulttranspose = 0; 897 ops->matmulttransposesymbolic = 0; 898 ops->matmulttransposenumeric = 0; 899 ops->ptapsymbolic_seqaij = 0; 900 /*99*/ 901 ops->ptapnumeric_seqaij = 0; 902 ops->ptapsymbolic_mpiaij = 0; 903 ops->ptapnumeric_mpiaij = 0; 904 ops->conjugate = 0; 905 ops->setsizes = 0; 906 /*104*/ 907 ops->setvaluesrow = 0; 908 ops->realpart = 0; 909 ops->imaginarypart = 0; 910 ops->getrowuppertriangular = 0; 911 ops->restorerowuppertriangular = 0; 912 /*109*/ 913 ops->matsolve = 0; 914 ops->getredundantmatrix = 0; 915 ops->getrowmin = 0; 916 ops->getcolumnvector = 0; 917 ops->missingdiagonal = 0; 918 /* 114 */ 919 ops->getseqnonzerostructure = 0; 920 ops->create = 0; 921 ops->getghosts = 0; 922 ops->getlocalsubmatrix = MatGetLocalSubMatrix_Nest; 923 ops->restorelocalsubmatrix = MatRestoreLocalSubMatrix_Nest; 924 /* 119 */ 925 ops->multdiagonalblock = 0; 926 ops->hermitiantranspose = 0; 927 ops->multhermitiantranspose = 0; 928 ops->multhermitiantransposeadd = 0; 929 ops->getmultiprocblock = 0; 930 /* 124 */ 931 932 ops->dummy2 = 0; 933 ops->dummy3 = 0; 934 ops->dummy4 = 0; 935 ops->getsubmatricesparallel = 0; 936 937 PetscFunctionReturn(0); 938 } 939 940 #undef __FUNCT__ 941 #define __FUNCT__ "MatSetUp_Nest_Private" 942 static PetscErrorCode MatSetUp_Nest_Private(Mat A,PetscInt nr,PetscInt nc,const Mat *sub) 943 { 944 Mat_Nest *ctx = (Mat_Nest*)A->data; 945 PetscInt i,j; 946 PetscErrorCode ierr; 947 948 PetscFunctionBegin; 949 if(ctx->setup_called) PetscFunctionReturn(0); 950 951 ctx->nr = nr; 952 ctx->nc = nc; 953 954 /* Create space */ 955 ierr = PetscMalloc(sizeof(Mat*)*ctx->nr,&ctx->m);CHKERRQ(ierr); 956 for (i=0; i<ctx->nr; i++) { 957 ierr = PetscMalloc(sizeof(Mat)*ctx->nc,&ctx->m[i]);CHKERRQ(ierr); 958 } 959 for (i=0; i<ctx->nr; i++) { 960 for (j=0; j<ctx->nc; j++) { 961 ctx->m[i][j] = sub[i*nc+j]; 962 if (sub[i*nc+j]) { 963 ierr = PetscObjectReference((PetscObject)sub[i*nc+j]);CHKERRQ(ierr); 964 } 965 } 966 } 967 968 ierr = PetscMalloc(sizeof(IS)*ctx->nr,&ctx->isglobal.row);CHKERRQ(ierr); 969 ierr = PetscMalloc(sizeof(IS)*ctx->nc,&ctx->isglobal.col);CHKERRQ(ierr); 970 971 ierr = PetscMalloc(sizeof(PetscInt)*ctx->nr,&ctx->row_len);CHKERRQ(ierr); 972 ierr = PetscMalloc(sizeof(PetscInt)*ctx->nc,&ctx->col_len);CHKERRQ(ierr); 973 for (i=0;i<ctx->nr;i++) ctx->row_len[i]=-1; 974 for (j=0;j<ctx->nc;j++) ctx->col_len[j]=-1; 975 976 ctx->setup_called = PETSC_TRUE; 977 978 PetscFunctionReturn(0); 979 } 980 981 982 /* If an IS was provided, there is nothing Nest needs to do, otherwise Nest will build a strided IS */ 983 /* 984 nprocessors = NP 985 Nest x^T = ( (g_0,g_1,...g_nprocs-1), (h_0,h_1,...h_NP-1) ) 986 proc 0: => (g_0,h_0,) 987 proc 1: => (g_1,h_1,) 988 ... 989 proc nprocs-1: => (g_NP-1,h_NP-1,) 990 991 proc 0: proc 1: proc nprocs-1: 992 is[0] = ( 0,1,2,...,nlocal(g_0)-1 ) ( 0,1,...,nlocal(g_1)-1 ) ( 0,1,...,nlocal(g_NP-1) ) 993 994 proc 0: 995 is[1] = ( nlocal(g_0),nlocal(g_0)+1,...,nlocal(g_0)+nlocal(h_0)-1 ) 996 proc 1: 997 is[1] = ( nlocal(g_1),nlocal(g_1)+1,...,nlocal(g_1)+nlocal(h_1)-1 ) 998 999 proc NP-1: 1000 is[1] = ( nlocal(g_NP-1),nlocal(g_NP-1)+1,...,nlocal(g_NP-1)+nlocal(h_NP-1)-1 ) 1001 */ 1002 #undef __FUNCT__ 1003 #define __FUNCT__ "MatSetUp_NestIS_Private" 1004 static PetscErrorCode MatSetUp_NestIS_Private(Mat A,PetscInt nr,const IS is_row[],PetscInt nc,const IS is_col[]) 1005 { 1006 Mat_Nest *vs = (Mat_Nest*)A->data; 1007 PetscInt i,j,offset,n,bs; 1008 PetscErrorCode ierr; 1009 Mat sub; 1010 1011 PetscFunctionBegin; 1012 if (is_row) { /* valid IS is passed in */ 1013 /* refs on is[] are incremeneted */ 1014 for (i=0; i<vs->nr; i++) { 1015 ierr = PetscObjectReference((PetscObject)is_row[i]);CHKERRQ(ierr); 1016 vs->isglobal.row[i] = is_row[i]; 1017 } 1018 } else { /* Create the ISs by inspecting sizes of a submatrix in each row */ 1019 offset = A->rmap->rstart; 1020 for (i=0; i<vs->nr; i++) { 1021 ierr = MatNestFindNonzeroSubMatRow(A,i,&sub);CHKERRQ(ierr); 1022 ierr = MatGetLocalSize(sub,&n,PETSC_NULL);CHKERRQ(ierr); 1023 if (n < 0) SETERRQ(((PetscObject)A)->comm,PETSC_ERR_ARG_WRONGSTATE,"Sizes have not yet been set for submatrix"); 1024 ierr = MatGetBlockSize(sub,&bs);CHKERRQ(ierr); 1025 ierr = ISCreateStride(((PetscObject)sub)->comm,n,offset,1,&vs->isglobal.row[i]);CHKERRQ(ierr); 1026 ierr = ISSetBlockSize(vs->isglobal.row[i],bs);CHKERRQ(ierr); 1027 offset += n; 1028 } 1029 } 1030 1031 if (is_col) { /* valid IS is passed in */ 1032 /* refs on is[] are incremeneted */ 1033 for (j=0; j<vs->nc; j++) { 1034 ierr = PetscObjectReference((PetscObject)is_col[j]);CHKERRQ(ierr); 1035 vs->isglobal.col[j] = is_col[j]; 1036 } 1037 } else { /* Create the ISs by inspecting sizes of a submatrix in each column */ 1038 offset = A->cmap->rstart; 1039 for (j=0; j<vs->nc; j++) { 1040 ierr = MatNestFindNonzeroSubMatCol(A,j,&sub);CHKERRQ(ierr); 1041 ierr = MatGetLocalSize(sub,PETSC_NULL,&n);CHKERRQ(ierr); 1042 if (n < 0) SETERRQ(((PetscObject)A)->comm,PETSC_ERR_ARG_WRONGSTATE,"Sizes have not yet been set for submatrix"); 1043 ierr = MatGetBlockSize(sub,&bs);CHKERRQ(ierr); 1044 ierr = ISCreateStride(((PetscObject)sub)->comm,n,offset,1,&vs->isglobal.col[j]);CHKERRQ(ierr); 1045 ierr = ISSetBlockSize(vs->isglobal.col[j],bs);CHKERRQ(ierr); 1046 offset += n; 1047 } 1048 } 1049 1050 /* Set up the local ISs */ 1051 ierr = PetscMalloc(vs->nr*sizeof(IS),&vs->islocal.row);CHKERRQ(ierr); 1052 ierr = PetscMalloc(vs->nc*sizeof(IS),&vs->islocal.col);CHKERRQ(ierr); 1053 for (i=0,offset=0; i<vs->nr; i++) { 1054 IS isloc; 1055 ISLocalToGlobalMapping rmap; 1056 PetscInt nlocal,bs; 1057 ierr = MatNestFindNonzeroSubMatRow(A,i,&sub);CHKERRQ(ierr); 1058 ierr = MatGetLocalToGlobalMapping(sub,&rmap,PETSC_NULL);CHKERRQ(ierr); 1059 if (rmap) { 1060 ierr = MatGetBlockSize(sub,&bs);CHKERRQ(ierr); 1061 ierr = ISLocalToGlobalMappingGetSize(rmap,&nlocal);CHKERRQ(ierr); 1062 ierr = ISCreateStride(PETSC_COMM_SELF,nlocal,offset,1,&isloc);CHKERRQ(ierr); 1063 ierr = ISSetBlockSize(isloc,bs);CHKERRQ(ierr); 1064 } else { 1065 nlocal = 0; 1066 isloc = PETSC_NULL; 1067 } 1068 vs->islocal.row[i] = isloc; 1069 offset += nlocal; 1070 } 1071 for (i=0,offset=0; i<vs->nr; i++) { 1072 IS isloc; 1073 ISLocalToGlobalMapping cmap; 1074 PetscInt nlocal,bs; 1075 ierr = MatNestFindNonzeroSubMatCol(A,i,&sub);CHKERRQ(ierr); 1076 ierr = MatGetLocalToGlobalMapping(sub,PETSC_NULL,&cmap);CHKERRQ(ierr); 1077 if (cmap) { 1078 ierr = MatGetBlockSize(sub,&bs);CHKERRQ(ierr); 1079 ierr = ISLocalToGlobalMappingGetSize(cmap,&nlocal);CHKERRQ(ierr); 1080 ierr = ISCreateStride(PETSC_COMM_SELF,nlocal,offset,1,&isloc);CHKERRQ(ierr); 1081 ierr = ISSetBlockSize(isloc,bs);CHKERRQ(ierr); 1082 } else { 1083 nlocal = 0; 1084 isloc = PETSC_NULL; 1085 } 1086 vs->islocal.col[i] = isloc; 1087 offset += nlocal; 1088 } 1089 PetscFunctionReturn(0); 1090 } 1091 1092 #undef __FUNCT__ 1093 #define __FUNCT__ "MatCreateNest" 1094 /*@ 1095 MatCreateNest - Creates a new matrix containing several nested submatrices, each stored separately 1096 1097 Collective on Mat 1098 1099 Input Parameter: 1100 + comm - Communicator for the new Mat 1101 . nr - number of nested row blocks 1102 . is_row - index sets for each nested row block, or PETSC_NULL to make contiguous 1103 . nc - number of nested column blocks 1104 . is_col - index sets for each nested column block, or PETSC_NULL to make contiguous 1105 - a - row-aligned array of nr*nc submatrices, empty submatrices can be passed using PETSC_NULL 1106 1107 Output Parameter: 1108 . B - new matrix 1109 1110 Level: advanced 1111 1112 .seealso: MatCreate(), VecCreateNest(), DMGetMatrix(), MATNEST 1113 @*/ 1114 PetscErrorCode MatCreateNest(MPI_Comm comm,PetscInt nr,const IS is_row[],PetscInt nc,const IS is_col[],const Mat a[],Mat *B) 1115 { 1116 Mat A; 1117 Mat_Nest *s; 1118 PetscInt i,m,n,M,N; 1119 PetscErrorCode ierr; 1120 1121 PetscFunctionBegin; 1122 if (nr < 0) SETERRQ(comm,PETSC_ERR_ARG_OUTOFRANGE,"Number of rows cannot be negative"); 1123 if (nr && is_row) { 1124 PetscValidPointer(is_row,3); 1125 for (i=0; i<nr; i++) PetscValidHeaderSpecific(is_row[i],IS_CLASSID,3); 1126 } 1127 if (nc < 0) SETERRQ(comm,PETSC_ERR_ARG_OUTOFRANGE,"Number of columns cannot be negative"); 1128 if (nc && is_row) { 1129 PetscValidPointer(is_col,5); 1130 for (i=0; i<nr; i++) PetscValidHeaderSpecific(is_col[i],IS_CLASSID,5); 1131 } 1132 if (nr*nc) PetscValidPointer(a,6); 1133 PetscValidPointer(B,7); 1134 1135 ierr = MatCreate(comm,&A);CHKERRQ(ierr); 1136 1137 ierr = PetscMalloc( sizeof(Mat_Nest), &s );CHKERRQ(ierr); 1138 ierr = PetscMemzero( s, sizeof(Mat_Nest) );CHKERRQ(ierr); 1139 A->data = (void*)s; 1140 s->setup_called = PETSC_FALSE; 1141 s->nr = s->nc = -1; 1142 s->m = PETSC_NULL; 1143 1144 /* define the operations */ 1145 ierr = MatNestSetOps_Private(A->ops);CHKERRQ(ierr); 1146 A->spptr = 0; 1147 A->same_nonzero = PETSC_FALSE; 1148 A->assembled = PETSC_FALSE; 1149 1150 ierr = PetscObjectChangeTypeName((PetscObject) A, MATNEST );CHKERRQ(ierr); 1151 ierr = MatSetUp_Nest_Private(A,nr,nc,a);CHKERRQ(ierr); 1152 1153 m = n = 0; 1154 M = N = 0; 1155 ierr = MatNestGetSize_Recursive(A,PETSC_TRUE,&M,&N);CHKERRQ(ierr); 1156 ierr = MatNestGetSize_Recursive(A,PETSC_FALSE,&m,&n);CHKERRQ(ierr); 1157 1158 ierr = PetscLayoutSetSize(A->rmap,M);CHKERRQ(ierr); 1159 ierr = PetscLayoutSetLocalSize(A->rmap,m);CHKERRQ(ierr); 1160 ierr = PetscLayoutSetBlockSize(A->rmap,1);CHKERRQ(ierr); 1161 ierr = PetscLayoutSetSize(A->cmap,N);CHKERRQ(ierr); 1162 ierr = PetscLayoutSetLocalSize(A->cmap,n);CHKERRQ(ierr); 1163 ierr = PetscLayoutSetBlockSize(A->cmap,1);CHKERRQ(ierr); 1164 1165 ierr = PetscLayoutSetUp(A->rmap);CHKERRQ(ierr); 1166 ierr = PetscLayoutSetUp(A->cmap);CHKERRQ(ierr); 1167 1168 ierr = MatSetUp_NestIS_Private(A,nr,is_row,nc,is_col);CHKERRQ(ierr); 1169 ierr = PetscMalloc2(nr,Vec,&s->left,nc,Vec,&s->right);CHKERRQ(ierr); 1170 1171 /* expose Nest api's */ 1172 ierr = PetscObjectComposeFunctionDynamic((PetscObject)A,"MatNestGetSubMat_C","MatNestGetSubMat_Nest",MatNestGetSubMat_Nest);CHKERRQ(ierr); 1173 ierr = PetscObjectComposeFunctionDynamic((PetscObject)A,"MatNestGetSubMats_C","MatNestGetSubMats_Nest",MatNestGetSubMats_Nest);CHKERRQ(ierr); 1174 ierr = PetscObjectComposeFunctionDynamic((PetscObject)A,"MatNestGetSize_C","MatNestGetSize_Nest",MatNestGetSize_Nest);CHKERRQ(ierr); 1175 ierr = PetscObjectComposeFunctionDynamic((PetscObject)A,"MatNestSetVecType_C","MatNestSetVecType_Nest",MatNestSetVecType_Nest);CHKERRQ(ierr); 1176 1177 *B = A; 1178 PetscFunctionReturn(0); 1179 } 1180 1181 /*MC 1182 MATNEST - MATNEST = "nest" - Matrix type consisting of nested submatrices, each stored separately. 1183 1184 Level: intermediate 1185 1186 Notes: 1187 This matrix type permits scalable use of PCFieldSplit and avoids the large memory costs of extracting submatrices. 1188 It allows the use of symmetric and block formats for parts of multi-physics simulations. 1189 It is usually used with DMComposite and DMGetMatrix() 1190 1191 .seealso: MatCreate(), MatType, MatCreateNest() 1192 M*/ 1193