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