1d8588912SDave May 2aaa7dc30SBarry Smith #include <../src/mat/impls/nest/matnestimpl.h> /*I "petscmat.h" I*/ 3b68353e5Sstefano_zampini #include <../src/mat/impls/aij/seq/aij.h> 40c312b8eSJed Brown #include <petscsf.h> 5d8588912SDave May 6c8883902SJed Brown static PetscErrorCode MatSetUp_NestIS_Private(Mat,PetscInt,const IS[],PetscInt,const IS[]); 706a1af2fSStefano Zampini static PetscErrorCode MatCreateVecs_Nest(Mat,Vec*,Vec*); 806a1af2fSStefano Zampini static PetscErrorCode MatReset_Nest(Mat); 906a1af2fSStefano Zampini 105e3038f0Sstefano_zampini PETSC_INTERN PetscErrorCode MatConvert_Nest_IS(Mat,MatType,MatReuse,Mat*); 11c8883902SJed Brown 12d8588912SDave May /* private functions */ 138188e55aSJed Brown static PetscErrorCode MatNestGetSizes_Private(Mat A,PetscInt *m,PetscInt *n,PetscInt *M,PetscInt *N) 14d8588912SDave May { 15d8588912SDave May Mat_Nest *bA = (Mat_Nest*)A->data; 168188e55aSJed Brown PetscInt i,j; 17d8588912SDave May PetscErrorCode ierr; 18d8588912SDave May 19d8588912SDave May PetscFunctionBegin; 208188e55aSJed Brown *m = *n = *M = *N = 0; 218188e55aSJed Brown for (i=0; i<bA->nr; i++) { /* rows */ 228188e55aSJed Brown PetscInt sm,sM; 238188e55aSJed Brown ierr = ISGetLocalSize(bA->isglobal.row[i],&sm);CHKERRQ(ierr); 248188e55aSJed Brown ierr = ISGetSize(bA->isglobal.row[i],&sM);CHKERRQ(ierr); 258188e55aSJed Brown *m += sm; 268188e55aSJed Brown *M += sM; 27d8588912SDave May } 288188e55aSJed Brown for (j=0; j<bA->nc; j++) { /* cols */ 298188e55aSJed Brown PetscInt sn,sN; 308188e55aSJed Brown ierr = ISGetLocalSize(bA->isglobal.col[j],&sn);CHKERRQ(ierr); 318188e55aSJed Brown ierr = ISGetSize(bA->isglobal.col[j],&sN);CHKERRQ(ierr); 328188e55aSJed Brown *n += sn; 338188e55aSJed Brown *N += sN; 34d8588912SDave May } 35d8588912SDave May PetscFunctionReturn(0); 36d8588912SDave May } 37d8588912SDave May 38d8588912SDave May /* operations */ 39207556f9SJed Brown static PetscErrorCode MatMult_Nest(Mat A,Vec x,Vec y) 40d8588912SDave May { 41d8588912SDave May Mat_Nest *bA = (Mat_Nest*)A->data; 42207556f9SJed Brown Vec *bx = bA->right,*by = bA->left; 43207556f9SJed Brown PetscInt i,j,nr = bA->nr,nc = bA->nc; 44d8588912SDave May PetscErrorCode ierr; 45d8588912SDave May 46d8588912SDave May PetscFunctionBegin; 47207556f9SJed Brown for (i=0; i<nr; i++) {ierr = VecGetSubVector(y,bA->isglobal.row[i],&by[i]);CHKERRQ(ierr);} 48207556f9SJed Brown for (i=0; i<nc; i++) {ierr = VecGetSubVector(x,bA->isglobal.col[i],&bx[i]);CHKERRQ(ierr);} 49207556f9SJed Brown for (i=0; i<nr; i++) { 50d8588912SDave May ierr = VecZeroEntries(by[i]);CHKERRQ(ierr); 51207556f9SJed Brown for (j=0; j<nc; j++) { 52207556f9SJed Brown if (!bA->m[i][j]) continue; 53d8588912SDave May /* y[i] <- y[i] + A[i][j] * x[j] */ 54d8588912SDave May ierr = MatMultAdd(bA->m[i][j],bx[j],by[i],by[i]);CHKERRQ(ierr); 55d8588912SDave May } 56d8588912SDave May } 57207556f9SJed Brown for (i=0; i<nr; i++) {ierr = VecRestoreSubVector(y,bA->isglobal.row[i],&by[i]);CHKERRQ(ierr);} 58207556f9SJed Brown for (i=0; i<nc; i++) {ierr = VecRestoreSubVector(x,bA->isglobal.col[i],&bx[i]);CHKERRQ(ierr);} 59d8588912SDave May PetscFunctionReturn(0); 60d8588912SDave May } 61d8588912SDave May 629194d70fSJed Brown static PetscErrorCode MatMultAdd_Nest(Mat A,Vec x,Vec y,Vec z) 639194d70fSJed Brown { 649194d70fSJed Brown Mat_Nest *bA = (Mat_Nest*)A->data; 659194d70fSJed Brown Vec *bx = bA->right,*bz = bA->left; 669194d70fSJed Brown PetscInt i,j,nr = bA->nr,nc = bA->nc; 679194d70fSJed Brown PetscErrorCode ierr; 689194d70fSJed Brown 699194d70fSJed Brown PetscFunctionBegin; 709194d70fSJed Brown for (i=0; i<nr; i++) {ierr = VecGetSubVector(z,bA->isglobal.row[i],&bz[i]);CHKERRQ(ierr);} 719194d70fSJed Brown for (i=0; i<nc; i++) {ierr = VecGetSubVector(x,bA->isglobal.col[i],&bx[i]);CHKERRQ(ierr);} 729194d70fSJed Brown for (i=0; i<nr; i++) { 739194d70fSJed Brown if (y != z) { 749194d70fSJed Brown Vec by; 759194d70fSJed Brown ierr = VecGetSubVector(y,bA->isglobal.row[i],&by);CHKERRQ(ierr); 769194d70fSJed Brown ierr = VecCopy(by,bz[i]);CHKERRQ(ierr); 77336d21e7SJed Brown ierr = VecRestoreSubVector(y,bA->isglobal.row[i],&by);CHKERRQ(ierr); 789194d70fSJed Brown } 799194d70fSJed Brown for (j=0; j<nc; j++) { 809194d70fSJed Brown if (!bA->m[i][j]) continue; 819194d70fSJed Brown /* y[i] <- y[i] + A[i][j] * x[j] */ 829194d70fSJed Brown ierr = MatMultAdd(bA->m[i][j],bx[j],bz[i],bz[i]);CHKERRQ(ierr); 839194d70fSJed Brown } 849194d70fSJed Brown } 859194d70fSJed Brown for (i=0; i<nr; i++) {ierr = VecRestoreSubVector(z,bA->isglobal.row[i],&bz[i]);CHKERRQ(ierr);} 869194d70fSJed Brown for (i=0; i<nc; i++) {ierr = VecRestoreSubVector(x,bA->isglobal.col[i],&bx[i]);CHKERRQ(ierr);} 879194d70fSJed Brown PetscFunctionReturn(0); 889194d70fSJed Brown } 899194d70fSJed Brown 90207556f9SJed Brown static PetscErrorCode MatMultTranspose_Nest(Mat A,Vec x,Vec y) 91d8588912SDave May { 92d8588912SDave May Mat_Nest *bA = (Mat_Nest*)A->data; 93207556f9SJed Brown Vec *bx = bA->left,*by = bA->right; 94207556f9SJed Brown PetscInt i,j,nr = bA->nr,nc = bA->nc; 95d8588912SDave May PetscErrorCode ierr; 96d8588912SDave May 97d8588912SDave May PetscFunctionBegin; 98609e31cbSJed Brown for (i=0; i<nr; i++) {ierr = VecGetSubVector(x,bA->isglobal.row[i],&bx[i]);CHKERRQ(ierr);} 99609e31cbSJed Brown for (i=0; i<nc; i++) {ierr = VecGetSubVector(y,bA->isglobal.col[i],&by[i]);CHKERRQ(ierr);} 100207556f9SJed Brown for (j=0; j<nc; j++) { 101609e31cbSJed Brown ierr = VecZeroEntries(by[j]);CHKERRQ(ierr); 102609e31cbSJed Brown for (i=0; i<nr; i++) { 1036c75ac25SJed Brown if (!bA->m[i][j]) continue; 104609e31cbSJed Brown /* y[j] <- y[j] + (A[i][j])^T * x[i] */ 105609e31cbSJed Brown ierr = MatMultTransposeAdd(bA->m[i][j],bx[i],by[j],by[j]);CHKERRQ(ierr); 106d8588912SDave May } 107d8588912SDave May } 108609e31cbSJed Brown for (i=0; i<nr; i++) {ierr = VecRestoreSubVector(x,bA->isglobal.row[i],&bx[i]);CHKERRQ(ierr);} 109609e31cbSJed Brown for (i=0; i<nc; i++) {ierr = VecRestoreSubVector(y,bA->isglobal.col[i],&by[i]);CHKERRQ(ierr);} 110d8588912SDave May PetscFunctionReturn(0); 111d8588912SDave May } 112d8588912SDave May 1139194d70fSJed Brown static PetscErrorCode MatMultTransposeAdd_Nest(Mat A,Vec x,Vec y,Vec z) 1149194d70fSJed Brown { 1159194d70fSJed Brown Mat_Nest *bA = (Mat_Nest*)A->data; 1169194d70fSJed Brown Vec *bx = bA->left,*bz = bA->right; 1179194d70fSJed Brown PetscInt i,j,nr = bA->nr,nc = bA->nc; 1189194d70fSJed Brown PetscErrorCode ierr; 1199194d70fSJed Brown 1209194d70fSJed Brown PetscFunctionBegin; 1219194d70fSJed Brown for (i=0; i<nr; i++) {ierr = VecGetSubVector(x,bA->isglobal.row[i],&bx[i]);CHKERRQ(ierr);} 1229194d70fSJed Brown for (i=0; i<nc; i++) {ierr = VecGetSubVector(z,bA->isglobal.col[i],&bz[i]);CHKERRQ(ierr);} 1239194d70fSJed Brown for (j=0; j<nc; j++) { 1249194d70fSJed Brown if (y != z) { 1259194d70fSJed Brown Vec by; 1269194d70fSJed Brown ierr = VecGetSubVector(y,bA->isglobal.col[j],&by);CHKERRQ(ierr); 1279194d70fSJed Brown ierr = VecCopy(by,bz[j]);CHKERRQ(ierr); 1289194d70fSJed Brown ierr = VecRestoreSubVector(y,bA->isglobal.col[j],&by);CHKERRQ(ierr); 1299194d70fSJed Brown } 1309194d70fSJed Brown for (i=0; i<nr; i++) { 1316c75ac25SJed Brown if (!bA->m[i][j]) continue; 1329194d70fSJed Brown /* z[j] <- y[j] + (A[i][j])^T * x[i] */ 1339194d70fSJed Brown ierr = MatMultTransposeAdd(bA->m[i][j],bx[i],bz[j],bz[j]);CHKERRQ(ierr); 1349194d70fSJed Brown } 1359194d70fSJed Brown } 1369194d70fSJed Brown for (i=0; i<nr; i++) {ierr = VecRestoreSubVector(x,bA->isglobal.row[i],&bx[i]);CHKERRQ(ierr);} 1379194d70fSJed Brown for (i=0; i<nc; i++) {ierr = VecRestoreSubVector(z,bA->isglobal.col[i],&bz[i]);CHKERRQ(ierr);} 1389194d70fSJed Brown PetscFunctionReturn(0); 1399194d70fSJed Brown } 1409194d70fSJed Brown 141f8170845SAlex Fikl static PetscErrorCode MatTranspose_Nest(Mat A,MatReuse reuse,Mat *B) 142f8170845SAlex Fikl { 143f8170845SAlex Fikl Mat_Nest *bA = (Mat_Nest*)A->data, *bC; 144f8170845SAlex Fikl Mat C; 145f8170845SAlex Fikl PetscInt i,j,nr = bA->nr,nc = bA->nc; 146f8170845SAlex Fikl PetscErrorCode ierr; 147f8170845SAlex Fikl 148f8170845SAlex Fikl PetscFunctionBegin; 149cf37664fSBarry Smith if (reuse == MAT_INPLACE_MATRIX && nr != nc) SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_SIZ,"Square nested matrix only for in-place"); 150f8170845SAlex Fikl 151cf37664fSBarry Smith if (reuse == MAT_INITIAL_MATRIX || reuse == MAT_INPLACE_MATRIX) { 152f8170845SAlex Fikl Mat *subs; 153f8170845SAlex Fikl IS *is_row,*is_col; 154f8170845SAlex Fikl 155f8170845SAlex Fikl ierr = PetscCalloc1(nr * nc,&subs);CHKERRQ(ierr); 156f8170845SAlex Fikl ierr = PetscMalloc2(nr,&is_row,nc,&is_col);CHKERRQ(ierr); 157f8170845SAlex Fikl ierr = MatNestGetISs(A,is_row,is_col);CHKERRQ(ierr); 158cf37664fSBarry Smith if (reuse == MAT_INPLACE_MATRIX) { 159ddeb9bd8SAlex Fikl for (i=0; i<nr; i++) { 160ddeb9bd8SAlex Fikl for (j=0; j<nc; j++) { 161ddeb9bd8SAlex Fikl subs[i + nr * j] = bA->m[i][j]; 162ddeb9bd8SAlex Fikl } 163ddeb9bd8SAlex Fikl } 164ddeb9bd8SAlex Fikl } 165ddeb9bd8SAlex Fikl 166f8170845SAlex Fikl ierr = MatCreateNest(PetscObjectComm((PetscObject)A),nc,is_col,nr,is_row,subs,&C);CHKERRQ(ierr); 167f8170845SAlex Fikl ierr = PetscFree(subs);CHKERRQ(ierr); 1683d994f23SBarry Smith ierr = PetscFree2(is_row,is_col);CHKERRQ(ierr); 169f8170845SAlex Fikl } else { 170f8170845SAlex Fikl C = *B; 171f8170845SAlex Fikl } 172f8170845SAlex Fikl 173f8170845SAlex Fikl bC = (Mat_Nest*)C->data; 174f8170845SAlex Fikl for (i=0; i<nr; i++) { 175f8170845SAlex Fikl for (j=0; j<nc; j++) { 176f8170845SAlex Fikl if (bA->m[i][j]) { 177f8170845SAlex Fikl ierr = MatTranspose(bA->m[i][j], reuse, &(bC->m[j][i]));CHKERRQ(ierr); 178f8170845SAlex Fikl } else { 179f8170845SAlex Fikl bC->m[j][i] = NULL; 180f8170845SAlex Fikl } 181f8170845SAlex Fikl } 182f8170845SAlex Fikl } 183f8170845SAlex Fikl 184cf37664fSBarry Smith if (reuse == MAT_INITIAL_MATRIX || reuse == MAT_REUSE_MATRIX) { 185f8170845SAlex Fikl *B = C; 186f8170845SAlex Fikl } else { 187f8170845SAlex Fikl ierr = MatHeaderMerge(A, &C);CHKERRQ(ierr); 188f8170845SAlex Fikl } 189f8170845SAlex Fikl PetscFunctionReturn(0); 190f8170845SAlex Fikl } 191f8170845SAlex Fikl 192e2d7f03fSJed Brown static PetscErrorCode MatNestDestroyISList(PetscInt n,IS **list) 193e2d7f03fSJed Brown { 194e2d7f03fSJed Brown PetscErrorCode ierr; 195e2d7f03fSJed Brown IS *lst = *list; 196e2d7f03fSJed Brown PetscInt i; 197e2d7f03fSJed Brown 198e2d7f03fSJed Brown PetscFunctionBegin; 199e2d7f03fSJed Brown if (!lst) PetscFunctionReturn(0); 2006bf464f9SBarry Smith for (i=0; i<n; i++) if (lst[i]) {ierr = ISDestroy(&lst[i]);CHKERRQ(ierr);} 201e2d7f03fSJed Brown ierr = PetscFree(lst);CHKERRQ(ierr); 2020298fd71SBarry Smith *list = NULL; 203e2d7f03fSJed Brown PetscFunctionReturn(0); 204e2d7f03fSJed Brown } 205e2d7f03fSJed Brown 20606a1af2fSStefano Zampini static PetscErrorCode MatReset_Nest(Mat A) 207d8588912SDave May { 208d8588912SDave May Mat_Nest *vs = (Mat_Nest*)A->data; 209d8588912SDave May PetscInt i,j; 210d8588912SDave May PetscErrorCode ierr; 211d8588912SDave May 212d8588912SDave May PetscFunctionBegin; 213d8588912SDave May /* release the matrices and the place holders */ 214e2d7f03fSJed Brown ierr = MatNestDestroyISList(vs->nr,&vs->isglobal.row);CHKERRQ(ierr); 215e2d7f03fSJed Brown ierr = MatNestDestroyISList(vs->nc,&vs->isglobal.col);CHKERRQ(ierr); 216e2d7f03fSJed Brown ierr = MatNestDestroyISList(vs->nr,&vs->islocal.row);CHKERRQ(ierr); 217e2d7f03fSJed Brown ierr = MatNestDestroyISList(vs->nc,&vs->islocal.col);CHKERRQ(ierr); 218d8588912SDave May 219d8588912SDave May ierr = PetscFree(vs->row_len);CHKERRQ(ierr); 220d8588912SDave May ierr = PetscFree(vs->col_len);CHKERRQ(ierr); 22106a1af2fSStefano Zampini ierr = PetscFree(vs->nnzstate);CHKERRQ(ierr); 222d8588912SDave May 223207556f9SJed Brown ierr = PetscFree2(vs->left,vs->right);CHKERRQ(ierr); 224207556f9SJed Brown 225d8588912SDave May /* release the matrices and the place holders */ 226d8588912SDave May if (vs->m) { 227d8588912SDave May for (i=0; i<vs->nr; i++) { 228d8588912SDave May for (j=0; j<vs->nc; j++) { 2296bf464f9SBarry Smith ierr = MatDestroy(&vs->m[i][j]);CHKERRQ(ierr); 230d8588912SDave May } 231d8588912SDave May ierr = PetscFree(vs->m[i]);CHKERRQ(ierr); 232d8588912SDave May } 233d8588912SDave May ierr = PetscFree(vs->m);CHKERRQ(ierr); 234d8588912SDave May } 23506a1af2fSStefano Zampini 23606a1af2fSStefano Zampini /* restore defaults */ 23706a1af2fSStefano Zampini vs->nr = 0; 23806a1af2fSStefano Zampini vs->nc = 0; 23906a1af2fSStefano Zampini vs->splitassembly = PETSC_FALSE; 24006a1af2fSStefano Zampini PetscFunctionReturn(0); 24106a1af2fSStefano Zampini } 24206a1af2fSStefano Zampini 24306a1af2fSStefano Zampini static PetscErrorCode MatDestroy_Nest(Mat A) 24406a1af2fSStefano Zampini { 24506a1af2fSStefano Zampini PetscErrorCode ierr; 24606a1af2fSStefano Zampini 24706a1af2fSStefano Zampini ierr = MatReset_Nest(A);CHKERRQ(ierr); 248bf0cc555SLisandro Dalcin ierr = PetscFree(A->data);CHKERRQ(ierr); 249d8588912SDave May 250bdf89e91SBarry Smith ierr = PetscObjectComposeFunction((PetscObject)A,"MatNestGetSubMat_C",0);CHKERRQ(ierr); 251bdf89e91SBarry Smith ierr = PetscObjectComposeFunction((PetscObject)A,"MatNestSetSubMat_C",0);CHKERRQ(ierr); 252bdf89e91SBarry Smith ierr = PetscObjectComposeFunction((PetscObject)A,"MatNestGetSubMats_C",0);CHKERRQ(ierr); 253bdf89e91SBarry Smith ierr = PetscObjectComposeFunction((PetscObject)A,"MatNestGetSize_C",0);CHKERRQ(ierr); 254bdf89e91SBarry Smith ierr = PetscObjectComposeFunction((PetscObject)A,"MatNestGetISs_C",0);CHKERRQ(ierr); 255bdf89e91SBarry Smith ierr = PetscObjectComposeFunction((PetscObject)A,"MatNestGetLocalISs_C",0);CHKERRQ(ierr); 256bdf89e91SBarry Smith ierr = PetscObjectComposeFunction((PetscObject)A,"MatNestSetVecType_C",0);CHKERRQ(ierr); 257bdf89e91SBarry Smith ierr = PetscObjectComposeFunction((PetscObject)A,"MatNestSetSubMats_C",0);CHKERRQ(ierr); 2580899c546SStefano Zampini ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_nest_mpiaij_C",0);CHKERRQ(ierr); 2590899c546SStefano Zampini ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_nest_seqaij_C",0);CHKERRQ(ierr); 2605e3038f0Sstefano_zampini ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_nest_aij_C",0);CHKERRQ(ierr); 2615e3038f0Sstefano_zampini ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_nest_is_C",0);CHKERRQ(ierr); 262d8588912SDave May PetscFunctionReturn(0); 263d8588912SDave May } 264d8588912SDave May 265207556f9SJed Brown static PetscErrorCode MatAssemblyBegin_Nest(Mat A,MatAssemblyType type) 266d8588912SDave May { 267d8588912SDave May Mat_Nest *vs = (Mat_Nest*)A->data; 268d8588912SDave May PetscInt i,j; 269d8588912SDave May PetscErrorCode ierr; 27006a1af2fSStefano Zampini PetscBool nnzstate = PETSC_FALSE; 271d8588912SDave May 272d8588912SDave May PetscFunctionBegin; 273d8588912SDave May for (i=0; i<vs->nr; i++) { 274d8588912SDave May for (j=0; j<vs->nc; j++) { 27506a1af2fSStefano Zampini PetscObjectState subnnzstate = 0; 276e7c19651SJed Brown if (vs->m[i][j]) { 277e7c19651SJed Brown ierr = MatAssemblyBegin(vs->m[i][j],type);CHKERRQ(ierr); 278e7c19651SJed Brown if (!vs->splitassembly) { 279e7c19651SJed Brown /* Note: split assembly will fail if the same block appears more than once (even indirectly through a nested 280e7c19651SJed Brown * sub-block). This could be fixed by adding a flag to Mat so that there was a way to check if a Mat was 281e7c19651SJed Brown * already performing an assembly, but the result would by more complicated and appears to offer less 282e7c19651SJed Brown * potential for diagnostics and correctness checking. Split assembly should be fixed once there is an 283e7c19651SJed Brown * interface for libraries to make asynchronous progress in "user-defined non-blocking collectives". 284e7c19651SJed Brown */ 285e7c19651SJed Brown ierr = MatAssemblyEnd(vs->m[i][j],type);CHKERRQ(ierr); 28606a1af2fSStefano Zampini ierr = MatGetNonzeroState(vs->m[i][j],&subnnzstate);CHKERRQ(ierr); 287e7c19651SJed Brown } 288e7c19651SJed Brown } 28906a1af2fSStefano Zampini nnzstate = (PetscBool)(nnzstate || vs->nnzstate[i*vs->nc+j] != subnnzstate); 29006a1af2fSStefano Zampini vs->nnzstate[i*vs->nc+j] = subnnzstate; 291d8588912SDave May } 292d8588912SDave May } 29306a1af2fSStefano Zampini if (nnzstate) A->nonzerostate++; 294d8588912SDave May PetscFunctionReturn(0); 295d8588912SDave May } 296d8588912SDave May 297207556f9SJed Brown static PetscErrorCode MatAssemblyEnd_Nest(Mat A, MatAssemblyType type) 298d8588912SDave May { 299d8588912SDave May Mat_Nest *vs = (Mat_Nest*)A->data; 300d8588912SDave May PetscInt i,j; 301d8588912SDave May PetscErrorCode ierr; 302d8588912SDave May 303d8588912SDave May PetscFunctionBegin; 304d8588912SDave May for (i=0; i<vs->nr; i++) { 305d8588912SDave May for (j=0; j<vs->nc; j++) { 306e7c19651SJed Brown if (vs->m[i][j]) { 307e7c19651SJed Brown if (vs->splitassembly) { 308e7c19651SJed Brown ierr = MatAssemblyEnd(vs->m[i][j],type);CHKERRQ(ierr); 309e7c19651SJed Brown } 310e7c19651SJed Brown } 311d8588912SDave May } 312d8588912SDave May } 313d8588912SDave May PetscFunctionReturn(0); 314d8588912SDave May } 315d8588912SDave May 316f349c1fdSJed Brown static PetscErrorCode MatNestFindNonzeroSubMatRow(Mat A,PetscInt row,Mat *B) 317d8588912SDave May { 318207556f9SJed Brown PetscErrorCode ierr; 319f349c1fdSJed Brown Mat_Nest *vs = (Mat_Nest*)A->data; 320f349c1fdSJed Brown PetscInt j; 321f349c1fdSJed Brown Mat sub; 322d8588912SDave May 323d8588912SDave May PetscFunctionBegin; 3240298fd71SBarry Smith sub = (row < vs->nc) ? vs->m[row][row] : (Mat)NULL; /* Prefer to find on the diagonal */ 325f349c1fdSJed Brown for (j=0; !sub && j<vs->nc; j++) sub = vs->m[row][j]; 3264994cf47SJed Brown if (sub) {ierr = MatSetUp(sub);CHKERRQ(ierr);} /* Ensure that the sizes are available */ 327f349c1fdSJed Brown *B = sub; 328f349c1fdSJed Brown PetscFunctionReturn(0); 329d8588912SDave May } 330d8588912SDave May 331f349c1fdSJed Brown static PetscErrorCode MatNestFindNonzeroSubMatCol(Mat A,PetscInt col,Mat *B) 332f349c1fdSJed Brown { 333207556f9SJed Brown PetscErrorCode ierr; 334f349c1fdSJed Brown Mat_Nest *vs = (Mat_Nest*)A->data; 335f349c1fdSJed Brown PetscInt i; 336f349c1fdSJed Brown Mat sub; 337f349c1fdSJed Brown 338f349c1fdSJed Brown PetscFunctionBegin; 3390298fd71SBarry Smith sub = (col < vs->nr) ? vs->m[col][col] : (Mat)NULL; /* Prefer to find on the diagonal */ 340f349c1fdSJed Brown for (i=0; !sub && i<vs->nr; i++) sub = vs->m[i][col]; 3414994cf47SJed Brown if (sub) {ierr = MatSetUp(sub);CHKERRQ(ierr);} /* Ensure that the sizes are available */ 342f349c1fdSJed Brown *B = sub; 343f349c1fdSJed Brown PetscFunctionReturn(0); 344d8588912SDave May } 345d8588912SDave May 346f349c1fdSJed Brown static PetscErrorCode MatNestFindIS(Mat A,PetscInt n,const IS list[],IS is,PetscInt *found) 347f349c1fdSJed Brown { 348f349c1fdSJed Brown PetscErrorCode ierr; 349f349c1fdSJed Brown PetscInt i; 350f349c1fdSJed Brown PetscBool flg; 351f349c1fdSJed Brown 352f349c1fdSJed Brown PetscFunctionBegin; 353f349c1fdSJed Brown PetscValidPointer(list,3); 354f349c1fdSJed Brown PetscValidHeaderSpecific(is,IS_CLASSID,4); 355f349c1fdSJed Brown PetscValidIntPointer(found,5); 356f349c1fdSJed Brown *found = -1; 357f349c1fdSJed Brown for (i=0; i<n; i++) { 358207556f9SJed Brown if (!list[i]) continue; 359*320466b0SStefano Zampini ierr = ISEqualUnsorted(list[i],is,&flg);CHKERRQ(ierr); 360f349c1fdSJed Brown if (flg) { 361f349c1fdSJed Brown *found = i; 362f349c1fdSJed Brown PetscFunctionReturn(0); 363f349c1fdSJed Brown } 364f349c1fdSJed Brown } 365ce94432eSBarry Smith SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_INCOMP,"Could not find index set"); 366f349c1fdSJed Brown PetscFunctionReturn(0); 367f349c1fdSJed Brown } 368f349c1fdSJed Brown 3698188e55aSJed Brown /* Get a block row as a new MatNest */ 3708188e55aSJed Brown static PetscErrorCode MatNestGetRow(Mat A,PetscInt row,Mat *B) 3718188e55aSJed Brown { 3728188e55aSJed Brown Mat_Nest *vs = (Mat_Nest*)A->data; 3738188e55aSJed Brown char keyname[256]; 3748188e55aSJed Brown PetscErrorCode ierr; 3758188e55aSJed Brown 3768188e55aSJed Brown PetscFunctionBegin; 3770298fd71SBarry Smith *B = NULL; 3788caf3d72SBarry Smith ierr = PetscSNPrintf(keyname,sizeof(keyname),"NestRow_%D",row);CHKERRQ(ierr); 3798188e55aSJed Brown ierr = PetscObjectQuery((PetscObject)A,keyname,(PetscObject*)B);CHKERRQ(ierr); 3808188e55aSJed Brown if (*B) PetscFunctionReturn(0); 3818188e55aSJed Brown 382ce94432eSBarry Smith ierr = MatCreateNest(PetscObjectComm((PetscObject)A),1,NULL,vs->nc,vs->isglobal.col,vs->m[row],B);CHKERRQ(ierr); 38326fbe8dcSKarl Rupp 3848188e55aSJed Brown (*B)->assembled = A->assembled; 38526fbe8dcSKarl Rupp 3868188e55aSJed Brown ierr = PetscObjectCompose((PetscObject)A,keyname,(PetscObject)*B);CHKERRQ(ierr); 3878188e55aSJed Brown ierr = PetscObjectDereference((PetscObject)*B);CHKERRQ(ierr); /* Leave the only remaining reference in the composition */ 3888188e55aSJed Brown PetscFunctionReturn(0); 3898188e55aSJed Brown } 3908188e55aSJed Brown 391f349c1fdSJed Brown static PetscErrorCode MatNestFindSubMat(Mat A,struct MatNestISPair *is,IS isrow,IS iscol,Mat *B) 392f349c1fdSJed Brown { 393f349c1fdSJed Brown Mat_Nest *vs = (Mat_Nest*)A->data; 3948188e55aSJed Brown PetscErrorCode ierr; 3956b3a5b13SJed Brown PetscInt row,col; 396e072481dSJed Brown PetscBool same,isFullCol,isFullColGlobal; 397f349c1fdSJed Brown 398f349c1fdSJed Brown PetscFunctionBegin; 3998188e55aSJed Brown /* Check if full column space. This is a hack */ 4008188e55aSJed Brown isFullCol = PETSC_FALSE; 401251f4c67SDmitry Karpeev ierr = PetscObjectTypeCompare((PetscObject)iscol,ISSTRIDE,&same);CHKERRQ(ierr); 4028188e55aSJed Brown if (same) { 40377019fcaSJed Brown PetscInt n,first,step,i,an,am,afirst,astep; 4048188e55aSJed Brown ierr = ISStrideGetInfo(iscol,&first,&step);CHKERRQ(ierr); 4058188e55aSJed Brown ierr = ISGetLocalSize(iscol,&n);CHKERRQ(ierr); 40677019fcaSJed Brown isFullCol = PETSC_TRUE; 40705ce4453SJed Brown for (i=0,an=A->cmap->rstart; i<vs->nc; i++) { 40806a1af2fSStefano Zampini ierr = PetscObjectTypeCompare((PetscObject)is->col[i],ISSTRIDE,&same);CHKERRQ(ierr); 40977019fcaSJed Brown ierr = ISGetLocalSize(is->col[i],&am);CHKERRQ(ierr); 41006a1af2fSStefano Zampini if (same) { 41106a1af2fSStefano Zampini ierr = ISStrideGetInfo(is->col[i],&afirst,&astep);CHKERRQ(ierr); 41277019fcaSJed Brown if (afirst != an || astep != step) isFullCol = PETSC_FALSE; 41306a1af2fSStefano Zampini } else isFullCol = PETSC_FALSE; 41477019fcaSJed Brown an += am; 41577019fcaSJed Brown } 41605ce4453SJed Brown if (an != A->cmap->rstart+n) isFullCol = PETSC_FALSE; 4178188e55aSJed Brown } 418b2566f29SBarry Smith ierr = MPIU_Allreduce(&isFullCol,&isFullColGlobal,1,MPIU_BOOL,MPI_LAND,PetscObjectComm((PetscObject)iscol));CHKERRQ(ierr); 4198188e55aSJed Brown 420427230ceSLisandro Dalcin if (isFullColGlobal && vs->nc > 1) { 4218188e55aSJed Brown PetscInt row; 4228188e55aSJed Brown ierr = MatNestFindIS(A,vs->nr,is->row,isrow,&row);CHKERRQ(ierr); 4238188e55aSJed Brown ierr = MatNestGetRow(A,row,B);CHKERRQ(ierr); 4248188e55aSJed Brown } else { 425f349c1fdSJed Brown ierr = MatNestFindIS(A,vs->nr,is->row,isrow,&row);CHKERRQ(ierr); 426f349c1fdSJed Brown ierr = MatNestFindIS(A,vs->nc,is->col,iscol,&col);CHKERRQ(ierr); 427b6480e04SStefano Zampini if (!vs->m[row][col]) { 428b6480e04SStefano Zampini PetscInt lr,lc; 429b6480e04SStefano Zampini 430b6480e04SStefano Zampini ierr = MatCreate(PetscObjectComm((PetscObject)A),&vs->m[row][col]);CHKERRQ(ierr); 431b6480e04SStefano Zampini ierr = ISGetLocalSize(vs->isglobal.row[row],&lr);CHKERRQ(ierr); 432b6480e04SStefano Zampini ierr = ISGetLocalSize(vs->isglobal.col[col],&lc);CHKERRQ(ierr); 433b6480e04SStefano Zampini ierr = MatSetSizes(vs->m[row][col],lr,lc,PETSC_DECIDE,PETSC_DECIDE);CHKERRQ(ierr); 434fa9f0909SStefano Zampini ierr = MatSetType(vs->m[row][col],MATAIJ);CHKERRQ(ierr); 435fa9f0909SStefano Zampini ierr = MatSeqAIJSetPreallocation(vs->m[row][col],0,NULL);CHKERRQ(ierr); 436fa9f0909SStefano Zampini ierr = MatMPIAIJSetPreallocation(vs->m[row][col],0,NULL,0,NULL);CHKERRQ(ierr); 437b6480e04SStefano Zampini ierr = MatSetUp(vs->m[row][col]);CHKERRQ(ierr); 438b6480e04SStefano Zampini ierr = MatAssemblyBegin(vs->m[row][col],MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 439b6480e04SStefano Zampini ierr = MatAssemblyEnd(vs->m[row][col],MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 440b6480e04SStefano Zampini } 441f349c1fdSJed Brown *B = vs->m[row][col]; 4428188e55aSJed Brown } 443f349c1fdSJed Brown PetscFunctionReturn(0); 444f349c1fdSJed Brown } 445f349c1fdSJed Brown 44606a1af2fSStefano Zampini /* 44706a1af2fSStefano Zampini TODO: This does not actually returns a submatrix we can modify 44806a1af2fSStefano Zampini */ 4497dae84e0SHong Zhang static PetscErrorCode MatCreateSubMatrix_Nest(Mat A,IS isrow,IS iscol,MatReuse reuse,Mat *B) 450f349c1fdSJed Brown { 451f349c1fdSJed Brown PetscErrorCode ierr; 452f349c1fdSJed Brown Mat_Nest *vs = (Mat_Nest*)A->data; 453f349c1fdSJed Brown Mat sub; 454f349c1fdSJed Brown 455f349c1fdSJed Brown PetscFunctionBegin; 456f349c1fdSJed Brown ierr = MatNestFindSubMat(A,&vs->isglobal,isrow,iscol,&sub);CHKERRQ(ierr); 457f349c1fdSJed Brown switch (reuse) { 458f349c1fdSJed Brown case MAT_INITIAL_MATRIX: 4597874fa86SDave May if (sub) { ierr = PetscObjectReference((PetscObject)sub);CHKERRQ(ierr); } 460f349c1fdSJed Brown *B = sub; 461f349c1fdSJed Brown break; 462f349c1fdSJed Brown case MAT_REUSE_MATRIX: 463ce94432eSBarry Smith if (sub != *B) SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_WRONGSTATE,"Submatrix was not used before in this call"); 464f349c1fdSJed Brown break; 465f349c1fdSJed Brown case MAT_IGNORE_MATRIX: /* Nothing to do */ 466f349c1fdSJed Brown break; 467511c6705SHong Zhang case MAT_INPLACE_MATRIX: /* Nothing to do */ 468511c6705SHong Zhang SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_SUP,"MAT_INPLACE_MATRIX is not supported yet"); 469511c6705SHong Zhang break; 470f349c1fdSJed Brown } 471f349c1fdSJed Brown PetscFunctionReturn(0); 472f349c1fdSJed Brown } 473f349c1fdSJed Brown 474f349c1fdSJed Brown PetscErrorCode MatGetLocalSubMatrix_Nest(Mat A,IS isrow,IS iscol,Mat *B) 475f349c1fdSJed Brown { 476f349c1fdSJed Brown PetscErrorCode ierr; 477f349c1fdSJed Brown Mat_Nest *vs = (Mat_Nest*)A->data; 478f349c1fdSJed Brown Mat sub; 479f349c1fdSJed Brown 480f349c1fdSJed Brown PetscFunctionBegin; 481f349c1fdSJed Brown ierr = MatNestFindSubMat(A,&vs->islocal,isrow,iscol,&sub);CHKERRQ(ierr); 482f349c1fdSJed Brown /* We allow the submatrix to be NULL, perhaps it would be better for the user to return an empty matrix instead */ 483f349c1fdSJed Brown if (sub) {ierr = PetscObjectReference((PetscObject)sub);CHKERRQ(ierr);} 484f349c1fdSJed Brown *B = sub; 485d8588912SDave May PetscFunctionReturn(0); 486d8588912SDave May } 487d8588912SDave May 488207556f9SJed Brown static PetscErrorCode MatRestoreLocalSubMatrix_Nest(Mat A,IS isrow,IS iscol,Mat *B) 489d8588912SDave May { 490d8588912SDave May PetscErrorCode ierr; 491f349c1fdSJed Brown Mat_Nest *vs = (Mat_Nest*)A->data; 492f349c1fdSJed Brown Mat sub; 493d8588912SDave May 494d8588912SDave May PetscFunctionBegin; 495f349c1fdSJed Brown ierr = MatNestFindSubMat(A,&vs->islocal,isrow,iscol,&sub);CHKERRQ(ierr); 496ce94432eSBarry Smith if (*B != sub) SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_WRONGSTATE,"Local submatrix has not been gotten"); 497f349c1fdSJed Brown if (sub) { 498ce94432eSBarry Smith if (((PetscObject)sub)->refct <= 1) SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_WRONGSTATE,"Local submatrix has had reference count decremented too many times"); 4996bf464f9SBarry Smith ierr = MatDestroy(B);CHKERRQ(ierr); 500d8588912SDave May } 501d8588912SDave May PetscFunctionReturn(0); 502d8588912SDave May } 503d8588912SDave May 5047874fa86SDave May static PetscErrorCode MatGetDiagonal_Nest(Mat A,Vec v) 5057874fa86SDave May { 5067874fa86SDave May Mat_Nest *bA = (Mat_Nest*)A->data; 5077874fa86SDave May PetscInt i; 5087874fa86SDave May PetscErrorCode ierr; 5097874fa86SDave May 5107874fa86SDave May PetscFunctionBegin; 5117874fa86SDave May for (i=0; i<bA->nr; i++) { 512429bac76SJed Brown Vec bv; 513429bac76SJed Brown ierr = VecGetSubVector(v,bA->isglobal.row[i],&bv);CHKERRQ(ierr); 5147874fa86SDave May if (bA->m[i][i]) { 515429bac76SJed Brown ierr = MatGetDiagonal(bA->m[i][i],bv);CHKERRQ(ierr); 5167874fa86SDave May } else { 5175159a857SMatthew G. Knepley ierr = VecSet(bv,0.0);CHKERRQ(ierr); 5187874fa86SDave May } 519429bac76SJed Brown ierr = VecRestoreSubVector(v,bA->isglobal.row[i],&bv);CHKERRQ(ierr); 5207874fa86SDave May } 5217874fa86SDave May PetscFunctionReturn(0); 5227874fa86SDave May } 5237874fa86SDave May 5247874fa86SDave May static PetscErrorCode MatDiagonalScale_Nest(Mat A,Vec l,Vec r) 5257874fa86SDave May { 5267874fa86SDave May Mat_Nest *bA = (Mat_Nest*)A->data; 527429bac76SJed Brown Vec bl,*br; 5287874fa86SDave May PetscInt i,j; 5297874fa86SDave May PetscErrorCode ierr; 5307874fa86SDave May 5317874fa86SDave May PetscFunctionBegin; 5323f800ebeSJed Brown ierr = PetscCalloc1(bA->nc,&br);CHKERRQ(ierr); 5332e6472ebSElliott Sales de Andrade if (r) { 534429bac76SJed Brown for (j=0; j<bA->nc; j++) {ierr = VecGetSubVector(r,bA->isglobal.col[j],&br[j]);CHKERRQ(ierr);} 5352e6472ebSElliott Sales de Andrade } 5362e6472ebSElliott Sales de Andrade bl = NULL; 5377874fa86SDave May for (i=0; i<bA->nr; i++) { 5382e6472ebSElliott Sales de Andrade if (l) { 539429bac76SJed Brown ierr = VecGetSubVector(l,bA->isglobal.row[i],&bl);CHKERRQ(ierr); 5402e6472ebSElliott Sales de Andrade } 5417874fa86SDave May for (j=0; j<bA->nc; j++) { 5427874fa86SDave May if (bA->m[i][j]) { 543429bac76SJed Brown ierr = MatDiagonalScale(bA->m[i][j],bl,br[j]);CHKERRQ(ierr); 5447874fa86SDave May } 5457874fa86SDave May } 5462e6472ebSElliott Sales de Andrade if (l) { 547a061e289SJed Brown ierr = VecRestoreSubVector(l,bA->isglobal.row[i],&bl);CHKERRQ(ierr); 5487874fa86SDave May } 5492e6472ebSElliott Sales de Andrade } 5502e6472ebSElliott Sales de Andrade if (r) { 551429bac76SJed Brown for (j=0; j<bA->nc; j++) {ierr = VecRestoreSubVector(r,bA->isglobal.col[j],&br[j]);CHKERRQ(ierr);} 5522e6472ebSElliott Sales de Andrade } 553429bac76SJed Brown ierr = PetscFree(br);CHKERRQ(ierr); 5547874fa86SDave May PetscFunctionReturn(0); 5557874fa86SDave May } 5567874fa86SDave May 557a061e289SJed Brown static PetscErrorCode MatScale_Nest(Mat A,PetscScalar a) 558a061e289SJed Brown { 559a061e289SJed Brown Mat_Nest *bA = (Mat_Nest*)A->data; 560a061e289SJed Brown PetscInt i,j; 561a061e289SJed Brown PetscErrorCode ierr; 562a061e289SJed Brown 563a061e289SJed Brown PetscFunctionBegin; 564a061e289SJed Brown for (i=0; i<bA->nr; i++) { 565a061e289SJed Brown for (j=0; j<bA->nc; j++) { 566a061e289SJed Brown if (bA->m[i][j]) { 567a061e289SJed Brown ierr = MatScale(bA->m[i][j],a);CHKERRQ(ierr); 568a061e289SJed Brown } 569a061e289SJed Brown } 570a061e289SJed Brown } 571a061e289SJed Brown PetscFunctionReturn(0); 572a061e289SJed Brown } 573a061e289SJed Brown 574a061e289SJed Brown static PetscErrorCode MatShift_Nest(Mat A,PetscScalar a) 575a061e289SJed Brown { 576a061e289SJed Brown Mat_Nest *bA = (Mat_Nest*)A->data; 577a061e289SJed Brown PetscInt i; 578a061e289SJed Brown PetscErrorCode ierr; 57906a1af2fSStefano Zampini PetscBool nnzstate = PETSC_FALSE; 580a061e289SJed Brown 581a061e289SJed Brown PetscFunctionBegin; 582a061e289SJed Brown for (i=0; i<bA->nr; i++) { 58306a1af2fSStefano Zampini PetscObjectState subnnzstate = 0; 584ce94432eSBarry Smith if (!bA->m[i][i]) SETERRQ2(PetscObjectComm((PetscObject)A),PETSC_ERR_SUP,"No support for shifting an empty diagonal block, insert a matrix in block (%D,%D)",i,i); 585a061e289SJed Brown ierr = MatShift(bA->m[i][i],a);CHKERRQ(ierr); 58606a1af2fSStefano Zampini ierr = MatGetNonzeroState(bA->m[i][i],&subnnzstate);CHKERRQ(ierr); 58706a1af2fSStefano Zampini nnzstate = (PetscBool)(nnzstate || bA->nnzstate[i*bA->nc+i] != subnnzstate); 58806a1af2fSStefano Zampini bA->nnzstate[i*bA->nc+i] = subnnzstate; 589a061e289SJed Brown } 59006a1af2fSStefano Zampini if (nnzstate) A->nonzerostate++; 591a061e289SJed Brown PetscFunctionReturn(0); 592a061e289SJed Brown } 593a061e289SJed Brown 59413135bc6SAlex Fikl static PetscErrorCode MatDiagonalSet_Nest(Mat A,Vec D,InsertMode is) 59513135bc6SAlex Fikl { 59613135bc6SAlex Fikl Mat_Nest *bA = (Mat_Nest*)A->data; 59713135bc6SAlex Fikl PetscInt i; 59813135bc6SAlex Fikl PetscErrorCode ierr; 59906a1af2fSStefano Zampini PetscBool nnzstate = PETSC_FALSE; 60013135bc6SAlex Fikl 60113135bc6SAlex Fikl PetscFunctionBegin; 60213135bc6SAlex Fikl for (i=0; i<bA->nr; i++) { 60306a1af2fSStefano Zampini PetscObjectState subnnzstate = 0; 60413135bc6SAlex Fikl Vec bv; 60513135bc6SAlex Fikl ierr = VecGetSubVector(D,bA->isglobal.row[i],&bv);CHKERRQ(ierr); 60613135bc6SAlex Fikl if (bA->m[i][i]) { 60713135bc6SAlex Fikl ierr = MatDiagonalSet(bA->m[i][i],bv,is);CHKERRQ(ierr); 60806a1af2fSStefano Zampini ierr = MatGetNonzeroState(bA->m[i][i],&subnnzstate);CHKERRQ(ierr); 60913135bc6SAlex Fikl } 61013135bc6SAlex Fikl ierr = VecRestoreSubVector(D,bA->isglobal.row[i],&bv);CHKERRQ(ierr); 61106a1af2fSStefano Zampini nnzstate = (PetscBool)(nnzstate || bA->nnzstate[i*bA->nc+i] != subnnzstate); 61206a1af2fSStefano Zampini bA->nnzstate[i*bA->nc+i] = subnnzstate; 61313135bc6SAlex Fikl } 61406a1af2fSStefano Zampini if (nnzstate) A->nonzerostate++; 61513135bc6SAlex Fikl PetscFunctionReturn(0); 61613135bc6SAlex Fikl } 61713135bc6SAlex Fikl 618f8170845SAlex Fikl static PetscErrorCode MatSetRandom_Nest(Mat A,PetscRandom rctx) 619f8170845SAlex Fikl { 620f8170845SAlex Fikl Mat_Nest *bA = (Mat_Nest*)A->data; 621f8170845SAlex Fikl PetscInt i,j; 622f8170845SAlex Fikl PetscErrorCode ierr; 623f8170845SAlex Fikl 624f8170845SAlex Fikl PetscFunctionBegin; 625f8170845SAlex Fikl for (i=0; i<bA->nr; i++) { 626f8170845SAlex Fikl for (j=0; j<bA->nc; j++) { 627f8170845SAlex Fikl if (bA->m[i][j]) { 628f8170845SAlex Fikl ierr = MatSetRandom(bA->m[i][j],rctx);CHKERRQ(ierr); 629f8170845SAlex Fikl } 630f8170845SAlex Fikl } 631f8170845SAlex Fikl } 632f8170845SAlex Fikl PetscFunctionReturn(0); 633f8170845SAlex Fikl } 634f8170845SAlex Fikl 6352a7a6963SBarry Smith static PetscErrorCode MatCreateVecs_Nest(Mat A,Vec *right,Vec *left) 636d8588912SDave May { 637d8588912SDave May Mat_Nest *bA = (Mat_Nest*)A->data; 638d8588912SDave May Vec *L,*R; 639d8588912SDave May MPI_Comm comm; 640d8588912SDave May PetscInt i,j; 641d8588912SDave May PetscErrorCode ierr; 642d8588912SDave May 643d8588912SDave May PetscFunctionBegin; 644ce94432eSBarry Smith ierr = PetscObjectGetComm((PetscObject)A,&comm);CHKERRQ(ierr); 645d8588912SDave May if (right) { 646d8588912SDave May /* allocate R */ 647854ce69bSBarry Smith ierr = PetscMalloc1(bA->nc, &R);CHKERRQ(ierr); 648d8588912SDave May /* Create the right vectors */ 649d8588912SDave May for (j=0; j<bA->nc; j++) { 650d8588912SDave May for (i=0; i<bA->nr; i++) { 651d8588912SDave May if (bA->m[i][j]) { 6522a7a6963SBarry Smith ierr = MatCreateVecs(bA->m[i][j],&R[j],NULL);CHKERRQ(ierr); 653d8588912SDave May break; 654d8588912SDave May } 655d8588912SDave May } 6566c4ed002SBarry Smith if (i==bA->nr) SETERRQ(PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONG, "Mat(Nest) contains a null column."); 657d8588912SDave May } 658f349c1fdSJed Brown ierr = VecCreateNest(comm,bA->nc,bA->isglobal.col,R,right);CHKERRQ(ierr); 659d8588912SDave May /* hand back control to the nest vector */ 660d8588912SDave May for (j=0; j<bA->nc; j++) { 6616bf464f9SBarry Smith ierr = VecDestroy(&R[j]);CHKERRQ(ierr); 662d8588912SDave May } 663d8588912SDave May ierr = PetscFree(R);CHKERRQ(ierr); 664d8588912SDave May } 665d8588912SDave May 666d8588912SDave May if (left) { 667d8588912SDave May /* allocate L */ 668854ce69bSBarry Smith ierr = PetscMalloc1(bA->nr, &L);CHKERRQ(ierr); 669d8588912SDave May /* Create the left vectors */ 670d8588912SDave May for (i=0; i<bA->nr; i++) { 671d8588912SDave May for (j=0; j<bA->nc; j++) { 672d8588912SDave May if (bA->m[i][j]) { 6732a7a6963SBarry Smith ierr = MatCreateVecs(bA->m[i][j],NULL,&L[i]);CHKERRQ(ierr); 674d8588912SDave May break; 675d8588912SDave May } 676d8588912SDave May } 6776c4ed002SBarry Smith if (j==bA->nc) SETERRQ(PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONG, "Mat(Nest) contains a null row."); 678d8588912SDave May } 679d8588912SDave May 680f349c1fdSJed Brown ierr = VecCreateNest(comm,bA->nr,bA->isglobal.row,L,left);CHKERRQ(ierr); 681d8588912SDave May for (i=0; i<bA->nr; i++) { 6826bf464f9SBarry Smith ierr = VecDestroy(&L[i]);CHKERRQ(ierr); 683d8588912SDave May } 684d8588912SDave May 685d8588912SDave May ierr = PetscFree(L);CHKERRQ(ierr); 686d8588912SDave May } 687d8588912SDave May PetscFunctionReturn(0); 688d8588912SDave May } 689d8588912SDave May 690207556f9SJed Brown static PetscErrorCode MatView_Nest(Mat A,PetscViewer viewer) 691d8588912SDave May { 692d8588912SDave May Mat_Nest *bA = (Mat_Nest*)A->data; 69329e60adbSStefano Zampini PetscBool isascii,viewSub = PETSC_FALSE; 694d8588912SDave May PetscInt i,j; 695d8588912SDave May PetscErrorCode ierr; 696d8588912SDave May 697d8588912SDave May PetscFunctionBegin; 698251f4c67SDmitry Karpeev ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&isascii);CHKERRQ(ierr); 699d8588912SDave May if (isascii) { 700d8588912SDave May 70129e60adbSStefano Zampini ierr = PetscOptionsGetBool(((PetscObject)A)->options,((PetscObject)A)->prefix,"-mat_view_nest_sub",&viewSub,NULL);CHKERRQ(ierr); 702d86155a6SBarry Smith ierr = PetscViewerASCIIPrintf(viewer,"Matrix object: \n");CHKERRQ(ierr); 703d86155a6SBarry Smith ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr); 704d86155a6SBarry Smith ierr = PetscViewerASCIIPrintf(viewer, "type=nest, rows=%D, cols=%D \n",bA->nr,bA->nc);CHKERRQ(ierr); 705d8588912SDave May 706d86155a6SBarry Smith ierr = PetscViewerASCIIPrintf(viewer,"MatNest structure: \n");CHKERRQ(ierr); 707d8588912SDave May for (i=0; i<bA->nr; i++) { 708d8588912SDave May for (j=0; j<bA->nc; j++) { 70919fd82e9SBarry Smith MatType type; 710270f95d7SJed Brown char name[256] = "",prefix[256] = ""; 711d8588912SDave May PetscInt NR,NC; 712d8588912SDave May PetscBool isNest = PETSC_FALSE; 713d8588912SDave May 714d8588912SDave May if (!bA->m[i][j]) { 715d86155a6SBarry Smith CHKERRQ(ierr);PetscViewerASCIIPrintf(viewer, "(%D,%D) : NULL \n",i,j);CHKERRQ(ierr); 716d8588912SDave May continue; 717d8588912SDave May } 718d8588912SDave May ierr = MatGetSize(bA->m[i][j],&NR,&NC);CHKERRQ(ierr); 719d8588912SDave May ierr = MatGetType(bA->m[i][j], &type);CHKERRQ(ierr); 7208caf3d72SBarry Smith if (((PetscObject)bA->m[i][j])->name) {ierr = PetscSNPrintf(name,sizeof(name),"name=\"%s\", ",((PetscObject)bA->m[i][j])->name);CHKERRQ(ierr);} 7218caf3d72SBarry Smith if (((PetscObject)bA->m[i][j])->prefix) {ierr = PetscSNPrintf(prefix,sizeof(prefix),"prefix=\"%s\", ",((PetscObject)bA->m[i][j])->prefix);CHKERRQ(ierr);} 722251f4c67SDmitry Karpeev ierr = PetscObjectTypeCompare((PetscObject)bA->m[i][j],MATNEST,&isNest);CHKERRQ(ierr); 723d8588912SDave May 724270f95d7SJed Brown ierr = PetscViewerASCIIPrintf(viewer,"(%D,%D) : %s%stype=%s, rows=%D, cols=%D \n",i,j,name,prefix,type,NR,NC);CHKERRQ(ierr); 725d8588912SDave May 72629e60adbSStefano Zampini if (isNest || viewSub) { 727270f95d7SJed Brown ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr); /* push1 */ 728d8588912SDave May ierr = MatView(bA->m[i][j],viewer);CHKERRQ(ierr); 729270f95d7SJed Brown ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr); /* pop1 */ 730d8588912SDave May } 731d8588912SDave May } 732d8588912SDave May } 733d86155a6SBarry Smith ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr); /* pop0 */ 734d8588912SDave May } 735d8588912SDave May PetscFunctionReturn(0); 736d8588912SDave May } 737d8588912SDave May 738207556f9SJed Brown static PetscErrorCode MatZeroEntries_Nest(Mat A) 739d8588912SDave May { 740d8588912SDave May Mat_Nest *bA = (Mat_Nest*)A->data; 741d8588912SDave May PetscInt i,j; 742d8588912SDave May PetscErrorCode ierr; 743d8588912SDave May 744d8588912SDave May PetscFunctionBegin; 745d8588912SDave May for (i=0; i<bA->nr; i++) { 746d8588912SDave May for (j=0; j<bA->nc; j++) { 747d8588912SDave May if (!bA->m[i][j]) continue; 748d8588912SDave May ierr = MatZeroEntries(bA->m[i][j]);CHKERRQ(ierr); 749d8588912SDave May } 750d8588912SDave May } 751d8588912SDave May PetscFunctionReturn(0); 752d8588912SDave May } 753d8588912SDave May 754c222c20dSDavid Ham static PetscErrorCode MatCopy_Nest(Mat A,Mat B,MatStructure str) 755c222c20dSDavid Ham { 756c222c20dSDavid Ham Mat_Nest *bA = (Mat_Nest*)A->data,*bB = (Mat_Nest*)B->data; 757c222c20dSDavid Ham PetscInt i,j,nr = bA->nr,nc = bA->nc; 758c222c20dSDavid Ham PetscErrorCode ierr; 75906a1af2fSStefano Zampini PetscBool nnzstate = PETSC_FALSE; 760c222c20dSDavid Ham 761c222c20dSDavid Ham PetscFunctionBegin; 762c222c20dSDavid Ham if (nr != bB->nr || nc != bB->nc) SETERRQ4(PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_INCOMP,"Cannot copy a Mat_Nest of block size (%D,%D) to a Mat_Nest of block size (%D,%D)",bB->nr,bB->nc,nr,nc); 763c222c20dSDavid Ham for (i=0; i<nr; i++) { 764c222c20dSDavid Ham for (j=0; j<nc; j++) { 76506a1af2fSStefano Zampini PetscObjectState subnnzstate = 0; 76646a2b97cSJed Brown if (bA->m[i][j] && bB->m[i][j]) { 767c222c20dSDavid Ham ierr = MatCopy(bA->m[i][j],bB->m[i][j],str);CHKERRQ(ierr); 76846a2b97cSJed Brown } else if (bA->m[i][j] || bB->m[i][j]) SETERRQ2(PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_INCOMP,"Matrix block does not exist at %D,%D",i,j); 76906a1af2fSStefano Zampini ierr = MatGetNonzeroState(bB->m[i][j],&subnnzstate);CHKERRQ(ierr); 77006a1af2fSStefano Zampini nnzstate = (PetscBool)(nnzstate || bB->nnzstate[i*nc+j] != subnnzstate); 77106a1af2fSStefano Zampini bB->nnzstate[i*nc+j] = subnnzstate; 772c222c20dSDavid Ham } 773c222c20dSDavid Ham } 77406a1af2fSStefano Zampini if (nnzstate) B->nonzerostate++; 775c222c20dSDavid Ham PetscFunctionReturn(0); 776c222c20dSDavid Ham } 777c222c20dSDavid Ham 7786e76ffeaSPierre Jolivet static PetscErrorCode MatAXPY_Nest(Mat Y,PetscScalar a,Mat X,MatStructure str) 7796e76ffeaSPierre Jolivet { 7806e76ffeaSPierre Jolivet Mat_Nest *bY = (Mat_Nest*)Y->data,*bX = (Mat_Nest*)X->data; 7816e76ffeaSPierre Jolivet PetscInt i,j,nr = bY->nr,nc = bY->nc; 7826e76ffeaSPierre Jolivet PetscErrorCode ierr; 78306a1af2fSStefano Zampini PetscBool nnzstate = PETSC_FALSE; 7846e76ffeaSPierre Jolivet 7856e76ffeaSPierre Jolivet PetscFunctionBegin; 7866e76ffeaSPierre Jolivet if (nr != bX->nr || nc != bX->nc) SETERRQ4(PetscObjectComm((PetscObject)Y),PETSC_ERR_ARG_INCOMP,"Cannot AXPY a MatNest of block size (%D,%D) with a MatNest of block size (%D,%D)",bX->nr,bX->nc,nr,nc); 7876e76ffeaSPierre Jolivet for (i=0; i<nr; i++) { 7886e76ffeaSPierre Jolivet for (j=0; j<nc; j++) { 78906a1af2fSStefano Zampini PetscObjectState subnnzstate = 0; 7906e76ffeaSPierre Jolivet if (bY->m[i][j] && bX->m[i][j]) { 7916e76ffeaSPierre Jolivet ierr = MatAXPY(bY->m[i][j],a,bX->m[i][j],str);CHKERRQ(ierr); 792c066aebcSStefano Zampini } else if (bX->m[i][j]) { 793c066aebcSStefano Zampini Mat M; 794c066aebcSStefano Zampini 795c066aebcSStefano Zampini if (str != DIFFERENT_NONZERO_PATTERN) SETERRQ2(PetscObjectComm((PetscObject)Y),PETSC_ERR_ARG_INCOMP,"Matrix block does not exist at %D,%D",i,j); 796c066aebcSStefano Zampini ierr = MatDuplicate(bX->m[i][j],MAT_COPY_VALUES,&M);CHKERRQ(ierr); 797c066aebcSStefano Zampini ierr = MatNestSetSubMat(Y,i,j,M);CHKERRQ(ierr); 798c066aebcSStefano Zampini ierr = MatDestroy(&M);CHKERRQ(ierr); 799c066aebcSStefano Zampini } 80006a1af2fSStefano Zampini ierr = MatGetNonzeroState(bY->m[i][j],&subnnzstate);CHKERRQ(ierr); 80106a1af2fSStefano Zampini nnzstate = (PetscBool)(nnzstate || bY->nnzstate[i*nc+j] != subnnzstate); 80206a1af2fSStefano Zampini bY->nnzstate[i*nc+j] = subnnzstate; 8036e76ffeaSPierre Jolivet } 8046e76ffeaSPierre Jolivet } 80506a1af2fSStefano Zampini if (nnzstate) Y->nonzerostate++; 8066e76ffeaSPierre Jolivet PetscFunctionReturn(0); 8076e76ffeaSPierre Jolivet } 8086e76ffeaSPierre Jolivet 809207556f9SJed Brown static PetscErrorCode MatDuplicate_Nest(Mat A,MatDuplicateOption op,Mat *B) 810d8588912SDave May { 811d8588912SDave May Mat_Nest *bA = (Mat_Nest*)A->data; 812841e96a3SJed Brown Mat *b; 813841e96a3SJed Brown PetscInt i,j,nr = bA->nr,nc = bA->nc; 814d8588912SDave May PetscErrorCode ierr; 815d8588912SDave May 816d8588912SDave May PetscFunctionBegin; 817785e854fSJed Brown ierr = PetscMalloc1(nr*nc,&b);CHKERRQ(ierr); 818841e96a3SJed Brown for (i=0; i<nr; i++) { 819841e96a3SJed Brown for (j=0; j<nc; j++) { 820841e96a3SJed Brown if (bA->m[i][j]) { 821841e96a3SJed Brown ierr = MatDuplicate(bA->m[i][j],op,&b[i*nc+j]);CHKERRQ(ierr); 822841e96a3SJed Brown } else { 8230298fd71SBarry Smith b[i*nc+j] = NULL; 824d8588912SDave May } 825d8588912SDave May } 826d8588912SDave May } 827ce94432eSBarry Smith ierr = MatCreateNest(PetscObjectComm((PetscObject)A),nr,bA->isglobal.row,nc,bA->isglobal.col,b,B);CHKERRQ(ierr); 828841e96a3SJed Brown /* Give the new MatNest exclusive ownership */ 829841e96a3SJed Brown for (i=0; i<nr*nc; i++) { 8306bf464f9SBarry Smith ierr = MatDestroy(&b[i]);CHKERRQ(ierr); 831d8588912SDave May } 832d8588912SDave May ierr = PetscFree(b);CHKERRQ(ierr); 833d8588912SDave May 834841e96a3SJed Brown ierr = MatAssemblyBegin(*B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 835841e96a3SJed Brown ierr = MatAssemblyEnd(*B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 836d8588912SDave May PetscFunctionReturn(0); 837d8588912SDave May } 838d8588912SDave May 839d8588912SDave May /* nest api */ 840d8588912SDave May PetscErrorCode MatNestGetSubMat_Nest(Mat A,PetscInt idxm,PetscInt jdxm,Mat *mat) 841d8588912SDave May { 842d8588912SDave May Mat_Nest *bA = (Mat_Nest*)A->data; 8435fd66863SKarl Rupp 844d8588912SDave May PetscFunctionBegin; 845ce94432eSBarry Smith if (idxm >= bA->nr) SETERRQ2(PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_OUTOFRANGE,"Row too large: row %D max %D",idxm,bA->nr-1); 846ce94432eSBarry Smith if (jdxm >= bA->nc) SETERRQ2(PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_OUTOFRANGE,"Col too large: row %D max %D",jdxm,bA->nc-1); 847d8588912SDave May *mat = bA->m[idxm][jdxm]; 848d8588912SDave May PetscFunctionReturn(0); 849d8588912SDave May } 850d8588912SDave May 8519ba0d327SJed Brown /*@ 852d8588912SDave May MatNestGetSubMat - Returns a single, sub-matrix from a nest matrix. 853d8588912SDave May 854d8588912SDave May Not collective 855d8588912SDave May 856d8588912SDave May Input Parameters: 857629881c0SJed Brown + A - nest matrix 858d8588912SDave May . idxm - index of the matrix within the nest matrix 859629881c0SJed Brown - jdxm - index of the matrix within the nest matrix 860d8588912SDave May 861d8588912SDave May Output Parameter: 862d8588912SDave May . sub - matrix at index idxm,jdxm within the nest matrix 863d8588912SDave May 864d8588912SDave May Level: developer 865d8588912SDave May 866d8588912SDave May .seealso: MatNestGetSize(), MatNestGetSubMats() 867d8588912SDave May @*/ 8687087cfbeSBarry Smith PetscErrorCode MatNestGetSubMat(Mat A,PetscInt idxm,PetscInt jdxm,Mat *sub) 869d8588912SDave May { 870699a902aSJed Brown PetscErrorCode ierr; 871d8588912SDave May 872d8588912SDave May PetscFunctionBegin; 873699a902aSJed Brown ierr = PetscUseMethod(A,"MatNestGetSubMat_C",(Mat,PetscInt,PetscInt,Mat*),(A,idxm,jdxm,sub));CHKERRQ(ierr); 874d8588912SDave May PetscFunctionReturn(0); 875d8588912SDave May } 876d8588912SDave May 8770782ca92SJed Brown PetscErrorCode MatNestSetSubMat_Nest(Mat A,PetscInt idxm,PetscInt jdxm,Mat mat) 8780782ca92SJed Brown { 8790782ca92SJed Brown Mat_Nest *bA = (Mat_Nest*)A->data; 8800782ca92SJed Brown PetscInt m,n,M,N,mi,ni,Mi,Ni; 8810782ca92SJed Brown PetscErrorCode ierr; 8820782ca92SJed Brown 8830782ca92SJed Brown PetscFunctionBegin; 884ce94432eSBarry Smith if (idxm >= bA->nr) SETERRQ2(PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_OUTOFRANGE,"Row too large: row %D max %D",idxm,bA->nr-1); 885ce94432eSBarry Smith if (jdxm >= bA->nc) SETERRQ2(PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_OUTOFRANGE,"Col too large: row %D max %D",jdxm,bA->nc-1); 8860782ca92SJed Brown ierr = MatGetLocalSize(mat,&m,&n);CHKERRQ(ierr); 8870782ca92SJed Brown ierr = MatGetSize(mat,&M,&N);CHKERRQ(ierr); 8880782ca92SJed Brown ierr = ISGetLocalSize(bA->isglobal.row[idxm],&mi);CHKERRQ(ierr); 8890782ca92SJed Brown ierr = ISGetSize(bA->isglobal.row[idxm],&Mi);CHKERRQ(ierr); 8900782ca92SJed Brown ierr = ISGetLocalSize(bA->isglobal.col[jdxm],&ni);CHKERRQ(ierr); 8910782ca92SJed Brown ierr = ISGetSize(bA->isglobal.col[jdxm],&Ni);CHKERRQ(ierr); 892ce94432eSBarry Smith if (M != Mi || N != Ni) SETERRQ4(PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_INCOMP,"Submatrix dimension (%D,%D) incompatible with nest block (%D,%D)",M,N,Mi,Ni); 893ce94432eSBarry Smith if (m != mi || n != ni) SETERRQ4(PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_INCOMP,"Submatrix local dimension (%D,%D) incompatible with nest block (%D,%D)",m,n,mi,ni); 89426fbe8dcSKarl Rupp 89506a1af2fSStefano Zampini /* do not increase object state */ 89606a1af2fSStefano Zampini if (mat == bA->m[idxm][jdxm]) PetscFunctionReturn(0); 89706a1af2fSStefano Zampini 8980782ca92SJed Brown ierr = PetscObjectReference((PetscObject)mat);CHKERRQ(ierr); 8990782ca92SJed Brown ierr = MatDestroy(&bA->m[idxm][jdxm]);CHKERRQ(ierr); 9000782ca92SJed Brown bA->m[idxm][jdxm] = mat; 90106a1af2fSStefano Zampini ierr = PetscObjectStateIncrease((PetscObject)A);CHKERRQ(ierr); 90206a1af2fSStefano Zampini ierr = MatGetNonzeroState(mat,&bA->nnzstate[idxm*bA->nc+jdxm]);CHKERRQ(ierr); 90306a1af2fSStefano Zampini A->nonzerostate++; 9040782ca92SJed Brown PetscFunctionReturn(0); 9050782ca92SJed Brown } 9060782ca92SJed Brown 9079ba0d327SJed Brown /*@ 9080782ca92SJed Brown MatNestSetSubMat - Set a single submatrix in the nest matrix. 9090782ca92SJed Brown 9100782ca92SJed Brown Logically collective on the submatrix communicator 9110782ca92SJed Brown 9120782ca92SJed Brown Input Parameters: 9130782ca92SJed Brown + A - nest matrix 9140782ca92SJed Brown . idxm - index of the matrix within the nest matrix 9150782ca92SJed Brown . jdxm - index of the matrix within the nest matrix 9160782ca92SJed Brown - sub - matrix at index idxm,jdxm within the nest matrix 9170782ca92SJed Brown 9180782ca92SJed Brown Notes: 9190782ca92SJed Brown The new submatrix must have the same size and communicator as that block of the nest. 9200782ca92SJed Brown 9210782ca92SJed Brown This increments the reference count of the submatrix. 9220782ca92SJed Brown 9230782ca92SJed Brown Level: developer 9240782ca92SJed Brown 925d5dfb694SBarry Smith .seealso: MatNestSetSubMats(), MatNestGetSubMats() 9260782ca92SJed Brown @*/ 9270782ca92SJed Brown PetscErrorCode MatNestSetSubMat(Mat A,PetscInt idxm,PetscInt jdxm,Mat sub) 9280782ca92SJed Brown { 9290782ca92SJed Brown PetscErrorCode ierr; 9300782ca92SJed Brown 9310782ca92SJed Brown PetscFunctionBegin; 9320782ca92SJed Brown ierr = PetscUseMethod(A,"MatNestSetSubMat_C",(Mat,PetscInt,PetscInt,Mat),(A,idxm,jdxm,sub));CHKERRQ(ierr); 9330782ca92SJed Brown PetscFunctionReturn(0); 9340782ca92SJed Brown } 9350782ca92SJed Brown 936d8588912SDave May PetscErrorCode MatNestGetSubMats_Nest(Mat A,PetscInt *M,PetscInt *N,Mat ***mat) 937d8588912SDave May { 938d8588912SDave May Mat_Nest *bA = (Mat_Nest*)A->data; 9395fd66863SKarl Rupp 940d8588912SDave May PetscFunctionBegin; 94126fbe8dcSKarl Rupp if (M) *M = bA->nr; 94226fbe8dcSKarl Rupp if (N) *N = bA->nc; 94326fbe8dcSKarl Rupp if (mat) *mat = bA->m; 944d8588912SDave May PetscFunctionReturn(0); 945d8588912SDave May } 946d8588912SDave May 947d8588912SDave May /*@C 948d8588912SDave May MatNestGetSubMats - Returns the entire two dimensional array of matrices defining a nest matrix. 949d8588912SDave May 950d8588912SDave May Not collective 951d8588912SDave May 952d8588912SDave May Input Parameters: 953629881c0SJed Brown . A - nest matrix 954d8588912SDave May 955d8588912SDave May Output Parameter: 956629881c0SJed Brown + M - number of rows in the nest matrix 957d8588912SDave May . N - number of cols in the nest matrix 958629881c0SJed Brown - mat - 2d array of matrices 959d8588912SDave May 960d8588912SDave May Notes: 961d8588912SDave May 962d8588912SDave May The user should not free the array mat. 963d8588912SDave May 964351962e3SVincent Le Chenadec In Fortran, this routine has a calling sequence 965351962e3SVincent Le Chenadec $ call MatNestGetSubMats(A, M, N, mat, ierr) 966351962e3SVincent Le Chenadec where the space allocated for the optional argument mat is assumed large enough (if provided). 967351962e3SVincent Le Chenadec 968d8588912SDave May Level: developer 969d8588912SDave May 970d8588912SDave May .seealso: MatNestGetSize(), MatNestGetSubMat() 971d8588912SDave May @*/ 9727087cfbeSBarry Smith PetscErrorCode MatNestGetSubMats(Mat A,PetscInt *M,PetscInt *N,Mat ***mat) 973d8588912SDave May { 974699a902aSJed Brown PetscErrorCode ierr; 975d8588912SDave May 976d8588912SDave May PetscFunctionBegin; 977699a902aSJed Brown ierr = PetscUseMethod(A,"MatNestGetSubMats_C",(Mat,PetscInt*,PetscInt*,Mat***),(A,M,N,mat));CHKERRQ(ierr); 978d8588912SDave May PetscFunctionReturn(0); 979d8588912SDave May } 980d8588912SDave May 9817087cfbeSBarry Smith PetscErrorCode MatNestGetSize_Nest(Mat A,PetscInt *M,PetscInt *N) 982d8588912SDave May { 983d8588912SDave May Mat_Nest *bA = (Mat_Nest*)A->data; 984d8588912SDave May 985d8588912SDave May PetscFunctionBegin; 98626fbe8dcSKarl Rupp if (M) *M = bA->nr; 98726fbe8dcSKarl Rupp if (N) *N = bA->nc; 988d8588912SDave May PetscFunctionReturn(0); 989d8588912SDave May } 990d8588912SDave May 9919ba0d327SJed Brown /*@ 992d8588912SDave May MatNestGetSize - Returns the size of the nest matrix. 993d8588912SDave May 994d8588912SDave May Not collective 995d8588912SDave May 996d8588912SDave May Input Parameters: 997d8588912SDave May . A - nest matrix 998d8588912SDave May 999d8588912SDave May Output Parameter: 1000629881c0SJed Brown + M - number of rows in the nested mat 1001629881c0SJed Brown - N - number of cols in the nested mat 1002d8588912SDave May 1003d8588912SDave May Notes: 1004d8588912SDave May 1005d8588912SDave May Level: developer 1006d8588912SDave May 1007d8588912SDave May .seealso: MatNestGetSubMat(), MatNestGetSubMats() 1008d8588912SDave May @*/ 10097087cfbeSBarry Smith PetscErrorCode MatNestGetSize(Mat A,PetscInt *M,PetscInt *N) 1010d8588912SDave May { 1011699a902aSJed Brown PetscErrorCode ierr; 1012d8588912SDave May 1013d8588912SDave May PetscFunctionBegin; 1014699a902aSJed Brown ierr = PetscUseMethod(A,"MatNestGetSize_C",(Mat,PetscInt*,PetscInt*),(A,M,N));CHKERRQ(ierr); 1015d8588912SDave May PetscFunctionReturn(0); 1016d8588912SDave May } 1017d8588912SDave May 1018f7a08781SBarry Smith static PetscErrorCode MatNestGetISs_Nest(Mat A,IS rows[],IS cols[]) 1019900e7ff2SJed Brown { 1020900e7ff2SJed Brown Mat_Nest *vs = (Mat_Nest*)A->data; 1021900e7ff2SJed Brown PetscInt i; 1022900e7ff2SJed Brown 1023900e7ff2SJed Brown PetscFunctionBegin; 1024900e7ff2SJed Brown if (rows) for (i=0; i<vs->nr; i++) rows[i] = vs->isglobal.row[i]; 1025900e7ff2SJed Brown if (cols) for (i=0; i<vs->nc; i++) cols[i] = vs->isglobal.col[i]; 1026900e7ff2SJed Brown PetscFunctionReturn(0); 1027900e7ff2SJed Brown } 1028900e7ff2SJed Brown 10293a4d7b9aSSatish Balay /*@C 1030900e7ff2SJed Brown MatNestGetISs - Returns the index sets partitioning the row and column spaces 1031900e7ff2SJed Brown 1032900e7ff2SJed Brown Not collective 1033900e7ff2SJed Brown 1034900e7ff2SJed Brown Input Parameters: 1035900e7ff2SJed Brown . A - nest matrix 1036900e7ff2SJed Brown 1037900e7ff2SJed Brown Output Parameter: 1038900e7ff2SJed Brown + rows - array of row index sets 1039900e7ff2SJed Brown - cols - array of column index sets 1040900e7ff2SJed Brown 1041900e7ff2SJed Brown Level: advanced 1042900e7ff2SJed Brown 1043900e7ff2SJed Brown Notes: 1044900e7ff2SJed Brown The user must have allocated arrays of the correct size. The reference count is not increased on the returned ISs. 1045900e7ff2SJed Brown 1046900e7ff2SJed Brown .seealso: MatNestGetSubMat(), MatNestGetSubMats(), MatNestGetSize(), MatNestGetLocalISs() 1047900e7ff2SJed Brown @*/ 1048900e7ff2SJed Brown PetscErrorCode MatNestGetISs(Mat A,IS rows[],IS cols[]) 1049900e7ff2SJed Brown { 1050900e7ff2SJed Brown PetscErrorCode ierr; 1051900e7ff2SJed Brown 1052900e7ff2SJed Brown PetscFunctionBegin; 1053900e7ff2SJed Brown PetscValidHeaderSpecific(A,MAT_CLASSID,1); 1054900e7ff2SJed Brown ierr = PetscUseMethod(A,"MatNestGetISs_C",(Mat,IS[],IS[]),(A,rows,cols));CHKERRQ(ierr); 1055900e7ff2SJed Brown PetscFunctionReturn(0); 1056900e7ff2SJed Brown } 1057900e7ff2SJed Brown 1058f7a08781SBarry Smith static PetscErrorCode MatNestGetLocalISs_Nest(Mat A,IS rows[],IS cols[]) 1059900e7ff2SJed Brown { 1060900e7ff2SJed Brown Mat_Nest *vs = (Mat_Nest*)A->data; 1061900e7ff2SJed Brown PetscInt i; 1062900e7ff2SJed Brown 1063900e7ff2SJed Brown PetscFunctionBegin; 1064900e7ff2SJed Brown if (rows) for (i=0; i<vs->nr; i++) rows[i] = vs->islocal.row[i]; 1065900e7ff2SJed Brown if (cols) for (i=0; i<vs->nc; i++) cols[i] = vs->islocal.col[i]; 1066900e7ff2SJed Brown PetscFunctionReturn(0); 1067900e7ff2SJed Brown } 1068900e7ff2SJed Brown 1069900e7ff2SJed Brown /*@C 1070900e7ff2SJed Brown MatNestGetLocalISs - Returns the index sets partitioning the row and column spaces 1071900e7ff2SJed Brown 1072900e7ff2SJed Brown Not collective 1073900e7ff2SJed Brown 1074900e7ff2SJed Brown Input Parameters: 1075900e7ff2SJed Brown . A - nest matrix 1076900e7ff2SJed Brown 1077900e7ff2SJed Brown Output Parameter: 10780298fd71SBarry Smith + rows - array of row index sets (or NULL to ignore) 10790298fd71SBarry Smith - cols - array of column index sets (or NULL to ignore) 1080900e7ff2SJed Brown 1081900e7ff2SJed Brown Level: advanced 1082900e7ff2SJed Brown 1083900e7ff2SJed Brown Notes: 1084900e7ff2SJed Brown The user must have allocated arrays of the correct size. The reference count is not increased on the returned ISs. 1085900e7ff2SJed Brown 1086900e7ff2SJed Brown .seealso: MatNestGetSubMat(), MatNestGetSubMats(), MatNestGetSize(), MatNestGetISs() 1087900e7ff2SJed Brown @*/ 1088900e7ff2SJed Brown PetscErrorCode MatNestGetLocalISs(Mat A,IS rows[],IS cols[]) 1089900e7ff2SJed Brown { 1090900e7ff2SJed Brown PetscErrorCode ierr; 1091900e7ff2SJed Brown 1092900e7ff2SJed Brown PetscFunctionBegin; 1093900e7ff2SJed Brown PetscValidHeaderSpecific(A,MAT_CLASSID,1); 1094900e7ff2SJed Brown ierr = PetscUseMethod(A,"MatNestGetLocalISs_C",(Mat,IS[],IS[]),(A,rows,cols));CHKERRQ(ierr); 1095900e7ff2SJed Brown PetscFunctionReturn(0); 1096900e7ff2SJed Brown } 1097900e7ff2SJed Brown 109819fd82e9SBarry Smith PetscErrorCode MatNestSetVecType_Nest(Mat A,VecType vtype) 1099207556f9SJed Brown { 1100207556f9SJed Brown PetscErrorCode ierr; 1101207556f9SJed Brown PetscBool flg; 1102207556f9SJed Brown 1103207556f9SJed Brown PetscFunctionBegin; 1104207556f9SJed Brown ierr = PetscStrcmp(vtype,VECNEST,&flg);CHKERRQ(ierr); 1105207556f9SJed Brown /* In reality, this only distinguishes VECNEST and "other" */ 11062a7a6963SBarry Smith if (flg) A->ops->getvecs = MatCreateVecs_Nest; 110712b53f24SSatish Balay else A->ops->getvecs = (PetscErrorCode (*)(Mat,Vec*,Vec*)) 0; 1108207556f9SJed Brown PetscFunctionReturn(0); 1109207556f9SJed Brown } 1110207556f9SJed Brown 1111207556f9SJed Brown /*@C 11122a7a6963SBarry Smith MatNestSetVecType - Sets the type of Vec returned by MatCreateVecs() 1113207556f9SJed Brown 1114207556f9SJed Brown Not collective 1115207556f9SJed Brown 1116207556f9SJed Brown Input Parameters: 1117207556f9SJed Brown + A - nest matrix 1118207556f9SJed Brown - vtype - type to use for creating vectors 1119207556f9SJed Brown 1120207556f9SJed Brown Notes: 1121207556f9SJed Brown 1122207556f9SJed Brown Level: developer 1123207556f9SJed Brown 11242a7a6963SBarry Smith .seealso: MatCreateVecs() 1125207556f9SJed Brown @*/ 112619fd82e9SBarry Smith PetscErrorCode MatNestSetVecType(Mat A,VecType vtype) 1127207556f9SJed Brown { 1128207556f9SJed Brown PetscErrorCode ierr; 1129207556f9SJed Brown 1130207556f9SJed Brown PetscFunctionBegin; 113119fd82e9SBarry Smith ierr = PetscTryMethod(A,"MatNestSetVecType_C",(Mat,VecType),(A,vtype));CHKERRQ(ierr); 1132207556f9SJed Brown PetscFunctionReturn(0); 1133207556f9SJed Brown } 1134207556f9SJed Brown 1135c8883902SJed Brown PetscErrorCode MatNestSetSubMats_Nest(Mat A,PetscInt nr,const IS is_row[],PetscInt nc,const IS is_col[],const Mat a[]) 1136d8588912SDave May { 1137c8883902SJed Brown Mat_Nest *s = (Mat_Nest*)A->data; 1138c8883902SJed Brown PetscInt i,j,m,n,M,N; 1139d8588912SDave May PetscErrorCode ierr; 114006a1af2fSStefano Zampini PetscBool cong; 1141d8588912SDave May 1142d8588912SDave May PetscFunctionBegin; 114306a1af2fSStefano Zampini ierr = MatReset_Nest(A);CHKERRQ(ierr); 114406a1af2fSStefano Zampini 1145c8883902SJed Brown s->nr = nr; 1146c8883902SJed Brown s->nc = nc; 1147d8588912SDave May 1148c8883902SJed Brown /* Create space for submatrices */ 1149854ce69bSBarry Smith ierr = PetscMalloc1(nr,&s->m);CHKERRQ(ierr); 1150c8883902SJed Brown for (i=0; i<nr; i++) { 1151854ce69bSBarry Smith ierr = PetscMalloc1(nc,&s->m[i]);CHKERRQ(ierr); 1152d8588912SDave May } 1153c8883902SJed Brown for (i=0; i<nr; i++) { 1154c8883902SJed Brown for (j=0; j<nc; j++) { 1155c8883902SJed Brown s->m[i][j] = a[i*nc+j]; 1156c8883902SJed Brown if (a[i*nc+j]) { 1157c8883902SJed Brown ierr = PetscObjectReference((PetscObject)a[i*nc+j]);CHKERRQ(ierr); 1158d8588912SDave May } 1159d8588912SDave May } 1160d8588912SDave May } 1161d8588912SDave May 11628188e55aSJed Brown ierr = MatSetUp_NestIS_Private(A,nr,is_row,nc,is_col);CHKERRQ(ierr); 1163d8588912SDave May 1164854ce69bSBarry Smith ierr = PetscMalloc1(nr,&s->row_len);CHKERRQ(ierr); 1165854ce69bSBarry Smith ierr = PetscMalloc1(nc,&s->col_len);CHKERRQ(ierr); 1166c8883902SJed Brown for (i=0; i<nr; i++) s->row_len[i]=-1; 1167c8883902SJed Brown for (j=0; j<nc; j++) s->col_len[j]=-1; 1168d8588912SDave May 116906a1af2fSStefano Zampini ierr = PetscCalloc1(nr*nc,&s->nnzstate);CHKERRQ(ierr); 117006a1af2fSStefano Zampini for (i=0; i<nr; i++) { 117106a1af2fSStefano Zampini for (j=0; j<nc; j++) { 117206a1af2fSStefano Zampini if (s->m[i][j]) { 117306a1af2fSStefano Zampini ierr = MatGetNonzeroState(s->m[i][j],&s->nnzstate[i*nc+j]);CHKERRQ(ierr); 117406a1af2fSStefano Zampini } 117506a1af2fSStefano Zampini } 117606a1af2fSStefano Zampini } 117706a1af2fSStefano Zampini 11788188e55aSJed Brown ierr = MatNestGetSizes_Private(A,&m,&n,&M,&N);CHKERRQ(ierr); 1179d8588912SDave May 1180c8883902SJed Brown ierr = PetscLayoutSetSize(A->rmap,M);CHKERRQ(ierr); 1181c8883902SJed Brown ierr = PetscLayoutSetLocalSize(A->rmap,m);CHKERRQ(ierr); 1182c8883902SJed Brown ierr = PetscLayoutSetSize(A->cmap,N);CHKERRQ(ierr); 1183c8883902SJed Brown ierr = PetscLayoutSetLocalSize(A->cmap,n);CHKERRQ(ierr); 1184c8883902SJed Brown 1185c8883902SJed Brown ierr = PetscLayoutSetUp(A->rmap);CHKERRQ(ierr); 1186c8883902SJed Brown ierr = PetscLayoutSetUp(A->cmap);CHKERRQ(ierr); 1187c8883902SJed Brown 118806a1af2fSStefano Zampini /* disable operations that are not supported for non-square matrices, 118906a1af2fSStefano Zampini or matrices for which is_row != is_col */ 119006a1af2fSStefano Zampini ierr = MatHasCongruentLayouts(A,&cong);CHKERRQ(ierr); 119106a1af2fSStefano Zampini if (cong && nr != nc) cong = PETSC_FALSE; 119206a1af2fSStefano Zampini if (cong) { 119306a1af2fSStefano Zampini for (i = 0; cong && i < nr; i++) { 1194*320466b0SStefano Zampini ierr = ISEqualUnsorted(s->isglobal.row[i],s->isglobal.col[i],&cong);CHKERRQ(ierr); 119506a1af2fSStefano Zampini } 119606a1af2fSStefano Zampini } 119706a1af2fSStefano Zampini if (!cong) { 119806a1af2fSStefano Zampini A->ops->getdiagonal = NULL; 119906a1af2fSStefano Zampini A->ops->shift = NULL; 120006a1af2fSStefano Zampini A->ops->diagonalset = NULL; 120106a1af2fSStefano Zampini } 120206a1af2fSStefano Zampini 12031795a4d1SJed Brown ierr = PetscCalloc2(nr,&s->left,nc,&s->right);CHKERRQ(ierr); 120406a1af2fSStefano Zampini ierr = PetscObjectStateIncrease((PetscObject)A);CHKERRQ(ierr); 120506a1af2fSStefano Zampini A->nonzerostate++; 1206d8588912SDave May PetscFunctionReturn(0); 1207d8588912SDave May } 1208d8588912SDave May 1209c8883902SJed Brown /*@ 1210c8883902SJed Brown MatNestSetSubMats - Sets the nested submatrices 1211c8883902SJed Brown 1212c8883902SJed Brown Collective on Mat 1213c8883902SJed Brown 1214c8883902SJed Brown Input Parameter: 1215ffd6319bSRichard Tran Mills + A - nested matrix 1216c8883902SJed Brown . nr - number of nested row blocks 12170298fd71SBarry Smith . is_row - index sets for each nested row block, or NULL to make contiguous 1218c8883902SJed Brown . nc - number of nested column blocks 12190298fd71SBarry Smith . is_col - index sets for each nested column block, or NULL to make contiguous 12200298fd71SBarry Smith - a - row-aligned array of nr*nc submatrices, empty submatrices can be passed using NULL 1221c8883902SJed Brown 122206a1af2fSStefano Zampini Notes: this always resets any submatrix information previously set 122306a1af2fSStefano Zampini 1224c8883902SJed Brown Level: advanced 1225c8883902SJed Brown 1226c8883902SJed Brown .seealso: MatCreateNest(), MATNEST 1227c8883902SJed Brown @*/ 1228c8883902SJed Brown PetscErrorCode MatNestSetSubMats(Mat A,PetscInt nr,const IS is_row[],PetscInt nc,const IS is_col[],const Mat a[]) 1229c8883902SJed Brown { 1230c8883902SJed Brown PetscErrorCode ierr; 123106a1af2fSStefano Zampini PetscInt i; 1232c8883902SJed Brown 1233c8883902SJed Brown PetscFunctionBegin; 1234c8883902SJed Brown PetscValidHeaderSpecific(A,MAT_CLASSID,1); 1235ce94432eSBarry Smith if (nr < 0) SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_OUTOFRANGE,"Number of rows cannot be negative"); 1236c8883902SJed Brown if (nr && is_row) { 1237c8883902SJed Brown PetscValidPointer(is_row,3); 1238c8883902SJed Brown for (i=0; i<nr; i++) PetscValidHeaderSpecific(is_row[i],IS_CLASSID,3); 1239c8883902SJed Brown } 1240ce94432eSBarry Smith if (nc < 0) SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_OUTOFRANGE,"Number of columns cannot be negative"); 12411664e352SJed Brown if (nc && is_col) { 1242c8883902SJed Brown PetscValidPointer(is_col,5); 12439b30a8f6SBarry Smith for (i=0; i<nc; i++) PetscValidHeaderSpecific(is_col[i],IS_CLASSID,5); 1244c8883902SJed Brown } 124506a1af2fSStefano Zampini if (nr*nc > 0) PetscValidPointer(a,6); 1246c8883902SJed Brown ierr = PetscUseMethod(A,"MatNestSetSubMats_C",(Mat,PetscInt,const IS[],PetscInt,const IS[],const Mat[]),(A,nr,is_row,nc,is_col,a));CHKERRQ(ierr); 1247c8883902SJed Brown PetscFunctionReturn(0); 1248c8883902SJed Brown } 1249d8588912SDave May 125045b6f7e9SBarry Smith static PetscErrorCode MatNestCreateAggregateL2G_Private(Mat A,PetscInt n,const IS islocal[],const IS isglobal[],PetscBool colflg,ISLocalToGlobalMapping *ltog) 125177019fcaSJed Brown { 125277019fcaSJed Brown PetscErrorCode ierr; 125377019fcaSJed Brown PetscBool flg; 125477019fcaSJed Brown PetscInt i,j,m,mi,*ix; 125577019fcaSJed Brown 125677019fcaSJed Brown PetscFunctionBegin; 125777019fcaSJed Brown for (i=0,m=0,flg=PETSC_FALSE; i<n; i++) { 125877019fcaSJed Brown if (islocal[i]) { 125977019fcaSJed Brown ierr = ISGetSize(islocal[i],&mi);CHKERRQ(ierr); 126077019fcaSJed Brown flg = PETSC_TRUE; /* We found a non-trivial entry */ 126177019fcaSJed Brown } else { 126277019fcaSJed Brown ierr = ISGetSize(isglobal[i],&mi);CHKERRQ(ierr); 126377019fcaSJed Brown } 126477019fcaSJed Brown m += mi; 126577019fcaSJed Brown } 126677019fcaSJed Brown if (flg) { 1267785e854fSJed Brown ierr = PetscMalloc1(m,&ix);CHKERRQ(ierr); 1268165cd838SBarry Smith for (i=0,m=0; i<n; i++) { 12690298fd71SBarry Smith ISLocalToGlobalMapping smap = NULL; 1270e108cb99SStefano Zampini Mat sub = NULL; 1271f6d38dbbSStefano Zampini PetscSF sf; 1272f6d38dbbSStefano Zampini PetscLayout map; 1273f6d38dbbSStefano Zampini PetscInt *ix2; 127477019fcaSJed Brown 1275165cd838SBarry Smith if (!colflg) { 127677019fcaSJed Brown ierr = MatNestFindNonzeroSubMatRow(A,i,&sub);CHKERRQ(ierr); 127777019fcaSJed Brown } else { 127877019fcaSJed Brown ierr = MatNestFindNonzeroSubMatCol(A,i,&sub);CHKERRQ(ierr); 127977019fcaSJed Brown } 1280191fd14bSBarry Smith if (sub) { 1281191fd14bSBarry Smith if (!colflg) { 1282191fd14bSBarry Smith ierr = MatGetLocalToGlobalMapping(sub,&smap,NULL);CHKERRQ(ierr); 1283191fd14bSBarry Smith } else { 1284191fd14bSBarry Smith ierr = MatGetLocalToGlobalMapping(sub,NULL,&smap);CHKERRQ(ierr); 1285191fd14bSBarry Smith } 1286191fd14bSBarry Smith } 128777019fcaSJed Brown if (islocal[i]) { 128877019fcaSJed Brown ierr = ISGetSize(islocal[i],&mi);CHKERRQ(ierr); 128977019fcaSJed Brown } else { 129077019fcaSJed Brown ierr = ISGetSize(isglobal[i],&mi);CHKERRQ(ierr); 129177019fcaSJed Brown } 129277019fcaSJed Brown for (j=0; j<mi; j++) ix[m+j] = j; 129377019fcaSJed Brown if (smap) {ierr = ISLocalToGlobalMappingApply(smap,mi,ix+m,ix+m);CHKERRQ(ierr);} 1294165cd838SBarry Smith 129577019fcaSJed Brown /* 129677019fcaSJed Brown Now we need to extract the monolithic global indices that correspond to the given split global indices. 129777019fcaSJed Brown In many/most cases, we only want MatGetLocalSubMatrix() to work, in which case we only need to know the size of the local spaces. 129877019fcaSJed Brown */ 1299f6d38dbbSStefano Zampini ierr = PetscMalloc1(mi,&ix2);CHKERRQ(ierr); 1300f6d38dbbSStefano Zampini ierr = PetscSFCreate(((PetscObject)isglobal[i])->comm,&sf);CHKERRQ(ierr); 1301f6d38dbbSStefano Zampini ierr = PetscLayoutCreate(((PetscObject)isglobal[i])->comm,&map);CHKERRQ(ierr); 1302f6d38dbbSStefano Zampini ierr = PetscLayoutSetLocalSize(map,mi);CHKERRQ(ierr); 1303f6d38dbbSStefano Zampini ierr = PetscLayoutSetUp(map);CHKERRQ(ierr); 1304f6d38dbbSStefano Zampini ierr = PetscSFSetGraphLayout(sf,map,mi,NULL,PETSC_USE_POINTER,ix+m);CHKERRQ(ierr); 1305f6d38dbbSStefano Zampini ierr = PetscLayoutDestroy(&map);CHKERRQ(ierr); 1306f6d38dbbSStefano Zampini for (j=0; j<mi; j++) ix2[j] = ix[m+j]; 1307f6d38dbbSStefano Zampini ierr = PetscSFBcastBegin(sf,MPIU_INT,ix2,ix + m);CHKERRQ(ierr); 1308f6d38dbbSStefano Zampini ierr = PetscSFBcastEnd(sf,MPIU_INT,ix2,ix + m);CHKERRQ(ierr); 1309f6d38dbbSStefano Zampini ierr = PetscSFDestroy(&sf);CHKERRQ(ierr); 1310f6d38dbbSStefano Zampini ierr = PetscFree(ix2);CHKERRQ(ierr); 131177019fcaSJed Brown m += mi; 131277019fcaSJed Brown } 1313f0413b6fSBarry Smith ierr = ISLocalToGlobalMappingCreate(PetscObjectComm((PetscObject)A),1,m,ix,PETSC_OWN_POINTER,ltog);CHKERRQ(ierr); 131477019fcaSJed Brown } else { 13150298fd71SBarry Smith *ltog = NULL; 131677019fcaSJed Brown } 131777019fcaSJed Brown PetscFunctionReturn(0); 131877019fcaSJed Brown } 131977019fcaSJed Brown 132077019fcaSJed Brown 1321d8588912SDave May /* If an IS was provided, there is nothing Nest needs to do, otherwise Nest will build a strided IS */ 1322d8588912SDave May /* 1323d8588912SDave May nprocessors = NP 1324d8588912SDave May Nest x^T = ((g_0,g_1,...g_nprocs-1), (h_0,h_1,...h_NP-1)) 1325d8588912SDave May proc 0: => (g_0,h_0,) 1326d8588912SDave May proc 1: => (g_1,h_1,) 1327d8588912SDave May ... 1328d8588912SDave May proc nprocs-1: => (g_NP-1,h_NP-1,) 1329d8588912SDave May 1330d8588912SDave May proc 0: proc 1: proc nprocs-1: 1331d8588912SDave May is[0] = (0,1,2,...,nlocal(g_0)-1) (0,1,...,nlocal(g_1)-1) (0,1,...,nlocal(g_NP-1)) 1332d8588912SDave May 1333d8588912SDave May proc 0: 1334d8588912SDave May is[1] = (nlocal(g_0),nlocal(g_0)+1,...,nlocal(g_0)+nlocal(h_0)-1) 1335d8588912SDave May proc 1: 1336d8588912SDave May is[1] = (nlocal(g_1),nlocal(g_1)+1,...,nlocal(g_1)+nlocal(h_1)-1) 1337d8588912SDave May 1338d8588912SDave May proc NP-1: 1339d8588912SDave May is[1] = (nlocal(g_NP-1),nlocal(g_NP-1)+1,...,nlocal(g_NP-1)+nlocal(h_NP-1)-1) 1340d8588912SDave May */ 1341841e96a3SJed Brown static PetscErrorCode MatSetUp_NestIS_Private(Mat A,PetscInt nr,const IS is_row[],PetscInt nc,const IS is_col[]) 1342d8588912SDave May { 1343e2d7f03fSJed Brown Mat_Nest *vs = (Mat_Nest*)A->data; 13448188e55aSJed Brown PetscInt i,j,offset,n,nsum,bs; 1345d8588912SDave May PetscErrorCode ierr; 13460298fd71SBarry Smith Mat sub = NULL; 1347d8588912SDave May 1348d8588912SDave May PetscFunctionBegin; 1349854ce69bSBarry Smith ierr = PetscMalloc1(nr,&vs->isglobal.row);CHKERRQ(ierr); 1350854ce69bSBarry Smith ierr = PetscMalloc1(nc,&vs->isglobal.col);CHKERRQ(ierr); 1351d8588912SDave May if (is_row) { /* valid IS is passed in */ 1352d8588912SDave May /* refs on is[] are incremeneted */ 1353e2d7f03fSJed Brown for (i=0; i<vs->nr; i++) { 1354d8588912SDave May ierr = PetscObjectReference((PetscObject)is_row[i]);CHKERRQ(ierr); 135526fbe8dcSKarl Rupp 1356e2d7f03fSJed Brown vs->isglobal.row[i] = is_row[i]; 1357d8588912SDave May } 13582ae74bdbSJed Brown } else { /* Create the ISs by inspecting sizes of a submatrix in each row */ 13598188e55aSJed Brown nsum = 0; 13608188e55aSJed Brown for (i=0; i<vs->nr; i++) { /* Add up the local sizes to compute the aggregate offset */ 13618188e55aSJed Brown ierr = MatNestFindNonzeroSubMatRow(A,i,&sub);CHKERRQ(ierr); 1362ce94432eSBarry Smith if (!sub) SETERRQ1(PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_WRONG,"No nonzero submatrix in row %D",i); 13630298fd71SBarry Smith ierr = MatGetLocalSize(sub,&n,NULL);CHKERRQ(ierr); 1364ce94432eSBarry Smith if (n < 0) SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_WRONGSTATE,"Sizes have not yet been set for submatrix"); 13658188e55aSJed Brown nsum += n; 13668188e55aSJed Brown } 1367ce94432eSBarry Smith ierr = MPI_Scan(&nsum,&offset,1,MPIU_INT,MPI_SUM,PetscObjectComm((PetscObject)A));CHKERRQ(ierr); 136830bc264bSJed Brown offset -= nsum; 1369e2d7f03fSJed Brown for (i=0; i<vs->nr; i++) { 1370f349c1fdSJed Brown ierr = MatNestFindNonzeroSubMatRow(A,i,&sub);CHKERRQ(ierr); 13710298fd71SBarry Smith ierr = MatGetLocalSize(sub,&n,NULL);CHKERRQ(ierr); 13722ae74bdbSJed Brown ierr = MatGetBlockSize(sub,&bs);CHKERRQ(ierr); 1373ce94432eSBarry Smith ierr = ISCreateStride(PetscObjectComm((PetscObject)sub),n,offset,1,&vs->isglobal.row[i]);CHKERRQ(ierr); 1374e2d7f03fSJed Brown ierr = ISSetBlockSize(vs->isglobal.row[i],bs);CHKERRQ(ierr); 13752ae74bdbSJed Brown offset += n; 1376d8588912SDave May } 1377d8588912SDave May } 1378d8588912SDave May 1379d8588912SDave May if (is_col) { /* valid IS is passed in */ 1380d8588912SDave May /* refs on is[] are incremeneted */ 1381e2d7f03fSJed Brown for (j=0; j<vs->nc; j++) { 1382d8588912SDave May ierr = PetscObjectReference((PetscObject)is_col[j]);CHKERRQ(ierr); 138326fbe8dcSKarl Rupp 1384e2d7f03fSJed Brown vs->isglobal.col[j] = is_col[j]; 1385d8588912SDave May } 13862ae74bdbSJed Brown } else { /* Create the ISs by inspecting sizes of a submatrix in each column */ 13872ae74bdbSJed Brown offset = A->cmap->rstart; 13888188e55aSJed Brown nsum = 0; 13898188e55aSJed Brown for (j=0; j<vs->nc; j++) { 13908188e55aSJed Brown ierr = MatNestFindNonzeroSubMatCol(A,j,&sub);CHKERRQ(ierr); 1391ce94432eSBarry Smith if (!sub) SETERRQ1(PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_WRONG,"No nonzero submatrix in column %D",i); 13920298fd71SBarry Smith ierr = MatGetLocalSize(sub,NULL,&n);CHKERRQ(ierr); 1393ce94432eSBarry Smith if (n < 0) SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_WRONGSTATE,"Sizes have not yet been set for submatrix"); 13948188e55aSJed Brown nsum += n; 13958188e55aSJed Brown } 1396ce94432eSBarry Smith ierr = MPI_Scan(&nsum,&offset,1,MPIU_INT,MPI_SUM,PetscObjectComm((PetscObject)A));CHKERRQ(ierr); 139730bc264bSJed Brown offset -= nsum; 1398e2d7f03fSJed Brown for (j=0; j<vs->nc; j++) { 1399f349c1fdSJed Brown ierr = MatNestFindNonzeroSubMatCol(A,j,&sub);CHKERRQ(ierr); 14000298fd71SBarry Smith ierr = MatGetLocalSize(sub,NULL,&n);CHKERRQ(ierr); 14012ae74bdbSJed Brown ierr = MatGetBlockSize(sub,&bs);CHKERRQ(ierr); 1402ce94432eSBarry Smith ierr = ISCreateStride(PetscObjectComm((PetscObject)sub),n,offset,1,&vs->isglobal.col[j]);CHKERRQ(ierr); 1403e2d7f03fSJed Brown ierr = ISSetBlockSize(vs->isglobal.col[j],bs);CHKERRQ(ierr); 14042ae74bdbSJed Brown offset += n; 1405d8588912SDave May } 1406d8588912SDave May } 1407e2d7f03fSJed Brown 1408e2d7f03fSJed Brown /* Set up the local ISs */ 1409785e854fSJed Brown ierr = PetscMalloc1(vs->nr,&vs->islocal.row);CHKERRQ(ierr); 1410785e854fSJed Brown ierr = PetscMalloc1(vs->nc,&vs->islocal.col);CHKERRQ(ierr); 1411e2d7f03fSJed Brown for (i=0,offset=0; i<vs->nr; i++) { 1412e2d7f03fSJed Brown IS isloc; 14130298fd71SBarry Smith ISLocalToGlobalMapping rmap = NULL; 1414e2d7f03fSJed Brown PetscInt nlocal,bs; 1415e2d7f03fSJed Brown ierr = MatNestFindNonzeroSubMatRow(A,i,&sub);CHKERRQ(ierr); 14160298fd71SBarry Smith if (sub) {ierr = MatGetLocalToGlobalMapping(sub,&rmap,NULL);CHKERRQ(ierr);} 1417207556f9SJed Brown if (rmap) { 1418e2d7f03fSJed Brown ierr = MatGetBlockSize(sub,&bs);CHKERRQ(ierr); 1419e2d7f03fSJed Brown ierr = ISLocalToGlobalMappingGetSize(rmap,&nlocal);CHKERRQ(ierr); 1420e2d7f03fSJed Brown ierr = ISCreateStride(PETSC_COMM_SELF,nlocal,offset,1,&isloc);CHKERRQ(ierr); 1421e2d7f03fSJed Brown ierr = ISSetBlockSize(isloc,bs);CHKERRQ(ierr); 1422207556f9SJed Brown } else { 1423207556f9SJed Brown nlocal = 0; 14240298fd71SBarry Smith isloc = NULL; 1425207556f9SJed Brown } 1426e2d7f03fSJed Brown vs->islocal.row[i] = isloc; 1427e2d7f03fSJed Brown offset += nlocal; 1428e2d7f03fSJed Brown } 14298188e55aSJed Brown for (i=0,offset=0; i<vs->nc; i++) { 1430e2d7f03fSJed Brown IS isloc; 14310298fd71SBarry Smith ISLocalToGlobalMapping cmap = NULL; 1432e2d7f03fSJed Brown PetscInt nlocal,bs; 1433e2d7f03fSJed Brown ierr = MatNestFindNonzeroSubMatCol(A,i,&sub);CHKERRQ(ierr); 14340298fd71SBarry Smith if (sub) {ierr = MatGetLocalToGlobalMapping(sub,NULL,&cmap);CHKERRQ(ierr);} 1435207556f9SJed Brown if (cmap) { 1436e2d7f03fSJed Brown ierr = MatGetBlockSize(sub,&bs);CHKERRQ(ierr); 1437e2d7f03fSJed Brown ierr = ISLocalToGlobalMappingGetSize(cmap,&nlocal);CHKERRQ(ierr); 1438e2d7f03fSJed Brown ierr = ISCreateStride(PETSC_COMM_SELF,nlocal,offset,1,&isloc);CHKERRQ(ierr); 1439e2d7f03fSJed Brown ierr = ISSetBlockSize(isloc,bs);CHKERRQ(ierr); 1440207556f9SJed Brown } else { 1441207556f9SJed Brown nlocal = 0; 14420298fd71SBarry Smith isloc = NULL; 1443207556f9SJed Brown } 1444e2d7f03fSJed Brown vs->islocal.col[i] = isloc; 1445e2d7f03fSJed Brown offset += nlocal; 1446e2d7f03fSJed Brown } 14470189643fSJed Brown 144877019fcaSJed Brown /* Set up the aggregate ISLocalToGlobalMapping */ 144977019fcaSJed Brown { 145045b6f7e9SBarry Smith ISLocalToGlobalMapping rmap,cmap; 145145b6f7e9SBarry Smith ierr = MatNestCreateAggregateL2G_Private(A,vs->nr,vs->islocal.row,vs->isglobal.row,PETSC_FALSE,&rmap);CHKERRQ(ierr); 145245b6f7e9SBarry Smith ierr = MatNestCreateAggregateL2G_Private(A,vs->nc,vs->islocal.col,vs->isglobal.col,PETSC_TRUE,&cmap);CHKERRQ(ierr); 145377019fcaSJed Brown if (rmap && cmap) {ierr = MatSetLocalToGlobalMapping(A,rmap,cmap);CHKERRQ(ierr);} 145477019fcaSJed Brown ierr = ISLocalToGlobalMappingDestroy(&rmap);CHKERRQ(ierr); 145577019fcaSJed Brown ierr = ISLocalToGlobalMappingDestroy(&cmap);CHKERRQ(ierr); 145677019fcaSJed Brown } 145777019fcaSJed Brown 14580189643fSJed Brown #if defined(PETSC_USE_DEBUG) 14590189643fSJed Brown for (i=0; i<vs->nr; i++) { 14600189643fSJed Brown for (j=0; j<vs->nc; j++) { 14610189643fSJed Brown PetscInt m,n,M,N,mi,ni,Mi,Ni; 14620189643fSJed Brown Mat B = vs->m[i][j]; 14630189643fSJed Brown if (!B) continue; 14640189643fSJed Brown ierr = MatGetSize(B,&M,&N);CHKERRQ(ierr); 14650189643fSJed Brown ierr = MatGetLocalSize(B,&m,&n);CHKERRQ(ierr); 14660189643fSJed Brown ierr = ISGetSize(vs->isglobal.row[i],&Mi);CHKERRQ(ierr); 14670189643fSJed Brown ierr = ISGetSize(vs->isglobal.col[j],&Ni);CHKERRQ(ierr); 14680189643fSJed Brown ierr = ISGetLocalSize(vs->isglobal.row[i],&mi);CHKERRQ(ierr); 14690189643fSJed Brown ierr = ISGetLocalSize(vs->isglobal.col[j],&ni);CHKERRQ(ierr); 1470ce94432eSBarry Smith if (M != Mi || N != Ni) SETERRQ6(PetscObjectComm((PetscObject)sub),PETSC_ERR_ARG_INCOMP,"Global sizes (%D,%D) of nested submatrix (%D,%D) do not agree with space defined by index sets (%D,%D)",M,N,i,j,Mi,Ni); 1471ce94432eSBarry Smith if (m != mi || n != ni) SETERRQ6(PetscObjectComm((PetscObject)sub),PETSC_ERR_ARG_INCOMP,"Local sizes (%D,%D) of nested submatrix (%D,%D) do not agree with space defined by index sets (%D,%D)",m,n,i,j,mi,ni); 14720189643fSJed Brown } 14730189643fSJed Brown } 14740189643fSJed Brown #endif 1475a061e289SJed Brown 1476a061e289SJed Brown /* Set A->assembled if all non-null blocks are currently assembled */ 1477a061e289SJed Brown for (i=0; i<vs->nr; i++) { 1478a061e289SJed Brown for (j=0; j<vs->nc; j++) { 1479a061e289SJed Brown if (vs->m[i][j] && !vs->m[i][j]->assembled) PetscFunctionReturn(0); 1480a061e289SJed Brown } 1481a061e289SJed Brown } 1482a061e289SJed Brown A->assembled = PETSC_TRUE; 1483d8588912SDave May PetscFunctionReturn(0); 1484d8588912SDave May } 1485d8588912SDave May 148645c38901SJed Brown /*@C 1487659c6bb0SJed Brown MatCreateNest - Creates a new matrix containing several nested submatrices, each stored separately 1488659c6bb0SJed Brown 1489659c6bb0SJed Brown Collective on Mat 1490659c6bb0SJed Brown 1491659c6bb0SJed Brown Input Parameter: 1492659c6bb0SJed Brown + comm - Communicator for the new Mat 1493659c6bb0SJed Brown . nr - number of nested row blocks 14940298fd71SBarry Smith . is_row - index sets for each nested row block, or NULL to make contiguous 1495659c6bb0SJed Brown . nc - number of nested column blocks 14960298fd71SBarry Smith . is_col - index sets for each nested column block, or NULL to make contiguous 14970298fd71SBarry Smith - a - row-aligned array of nr*nc submatrices, empty submatrices can be passed using NULL 1498659c6bb0SJed Brown 1499659c6bb0SJed Brown Output Parameter: 1500659c6bb0SJed Brown . B - new matrix 1501659c6bb0SJed Brown 1502659c6bb0SJed Brown Level: advanced 1503659c6bb0SJed Brown 1504950540a4SJed Brown .seealso: MatCreate(), VecCreateNest(), DMCreateMatrix(), MATNEST 1505659c6bb0SJed Brown @*/ 15067087cfbeSBarry Smith PetscErrorCode MatCreateNest(MPI_Comm comm,PetscInt nr,const IS is_row[],PetscInt nc,const IS is_col[],const Mat a[],Mat *B) 1507d8588912SDave May { 1508d8588912SDave May Mat A; 1509d8588912SDave May PetscErrorCode ierr; 1510d8588912SDave May 1511d8588912SDave May PetscFunctionBegin; 1512c8883902SJed Brown *B = 0; 1513d8588912SDave May ierr = MatCreate(comm,&A);CHKERRQ(ierr); 1514c8883902SJed Brown ierr = MatSetType(A,MATNEST);CHKERRQ(ierr); 151591a28eb3SBarry Smith A->preallocated = PETSC_TRUE; 1516c8883902SJed Brown ierr = MatNestSetSubMats(A,nr,is_row,nc,is_col,a);CHKERRQ(ierr); 1517d8588912SDave May *B = A; 1518d8588912SDave May PetscFunctionReturn(0); 1519d8588912SDave May } 1520659c6bb0SJed Brown 1521b68353e5Sstefano_zampini static PetscErrorCode MatConvert_Nest_SeqAIJ_fast(Mat A,MatType newtype,MatReuse reuse,Mat *newmat) 1522b68353e5Sstefano_zampini { 1523b68353e5Sstefano_zampini Mat_Nest *nest = (Mat_Nest*)A->data; 152423875855Sstefano_zampini Mat *trans; 1525b68353e5Sstefano_zampini PetscScalar **avv; 1526b68353e5Sstefano_zampini PetscScalar *vv; 1527b68353e5Sstefano_zampini PetscInt **aii,**ajj; 1528b68353e5Sstefano_zampini PetscInt *ii,*jj,*ci; 1529b68353e5Sstefano_zampini PetscInt nr,nc,nnz,i,j; 1530b68353e5Sstefano_zampini PetscBool done; 1531b68353e5Sstefano_zampini PetscErrorCode ierr; 1532b68353e5Sstefano_zampini 1533b68353e5Sstefano_zampini PetscFunctionBegin; 1534b68353e5Sstefano_zampini ierr = MatGetSize(A,&nr,&nc);CHKERRQ(ierr); 1535b68353e5Sstefano_zampini if (reuse == MAT_REUSE_MATRIX) { 1536b68353e5Sstefano_zampini PetscInt rnr; 1537b68353e5Sstefano_zampini 1538b68353e5Sstefano_zampini ierr = MatGetRowIJ(*newmat,0,PETSC_FALSE,PETSC_FALSE,&rnr,(const PetscInt**)&ii,(const PetscInt**)&jj,&done);CHKERRQ(ierr); 1539b68353e5Sstefano_zampini if (!done) SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_PLIB,"MatGetRowIJ"); 1540b68353e5Sstefano_zampini if (rnr != nr) SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_USER,"Cannot reuse matrix, wrong number of rows"); 1541b68353e5Sstefano_zampini ierr = MatSeqAIJGetArray(*newmat,&vv);CHKERRQ(ierr); 1542b68353e5Sstefano_zampini } 1543b68353e5Sstefano_zampini /* extract CSR for nested SeqAIJ matrices */ 1544b68353e5Sstefano_zampini nnz = 0; 154523875855Sstefano_zampini ierr = PetscCalloc4(nest->nr*nest->nc,&aii,nest->nr*nest->nc,&ajj,nest->nr*nest->nc,&avv,nest->nr*nest->nc,&trans);CHKERRQ(ierr); 1546b68353e5Sstefano_zampini for (i=0; i<nest->nr; ++i) { 1547b68353e5Sstefano_zampini for (j=0; j<nest->nc; ++j) { 1548b68353e5Sstefano_zampini Mat B = nest->m[i][j]; 1549b68353e5Sstefano_zampini if (B) { 1550b68353e5Sstefano_zampini PetscScalar *naa; 1551b68353e5Sstefano_zampini PetscInt *nii,*njj,nnr; 155223875855Sstefano_zampini PetscBool istrans; 1553b68353e5Sstefano_zampini 155423875855Sstefano_zampini ierr = PetscObjectTypeCompare((PetscObject)B,MATTRANSPOSEMAT,&istrans);CHKERRQ(ierr); 155523875855Sstefano_zampini if (istrans) { 155623875855Sstefano_zampini Mat Bt; 155723875855Sstefano_zampini 155823875855Sstefano_zampini ierr = MatTransposeGetMat(B,&Bt);CHKERRQ(ierr); 155923875855Sstefano_zampini ierr = MatTranspose(Bt,MAT_INITIAL_MATRIX,&trans[i*nest->nc+j]);CHKERRQ(ierr); 156023875855Sstefano_zampini B = trans[i*nest->nc+j]; 156123875855Sstefano_zampini } 1562b68353e5Sstefano_zampini ierr = MatGetRowIJ(B,0,PETSC_FALSE,PETSC_FALSE,&nnr,(const PetscInt**)&nii,(const PetscInt**)&njj,&done);CHKERRQ(ierr); 1563b68353e5Sstefano_zampini if (!done) SETERRQ(PetscObjectComm((PetscObject)B),PETSC_ERR_PLIB,"MatGetRowIJ"); 1564b68353e5Sstefano_zampini ierr = MatSeqAIJGetArray(B,&naa);CHKERRQ(ierr); 1565b68353e5Sstefano_zampini nnz += nii[nnr]; 1566b68353e5Sstefano_zampini 1567b68353e5Sstefano_zampini aii[i*nest->nc+j] = nii; 1568b68353e5Sstefano_zampini ajj[i*nest->nc+j] = njj; 1569b68353e5Sstefano_zampini avv[i*nest->nc+j] = naa; 1570b68353e5Sstefano_zampini } 1571b68353e5Sstefano_zampini } 1572b68353e5Sstefano_zampini } 1573b68353e5Sstefano_zampini if (reuse != MAT_REUSE_MATRIX) { 1574b68353e5Sstefano_zampini ierr = PetscMalloc1(nr+1,&ii);CHKERRQ(ierr); 1575b68353e5Sstefano_zampini ierr = PetscMalloc1(nnz,&jj);CHKERRQ(ierr); 1576b68353e5Sstefano_zampini ierr = PetscMalloc1(nnz,&vv);CHKERRQ(ierr); 1577b68353e5Sstefano_zampini } else { 1578b68353e5Sstefano_zampini if (nnz != ii[nr]) SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_USER,"Cannot reuse matrix, wrong number of nonzeros"); 1579b68353e5Sstefano_zampini } 1580b68353e5Sstefano_zampini 1581b68353e5Sstefano_zampini /* new row pointer */ 1582580bdb30SBarry Smith ierr = PetscArrayzero(ii,nr+1);CHKERRQ(ierr); 1583b68353e5Sstefano_zampini for (i=0; i<nest->nr; ++i) { 1584b68353e5Sstefano_zampini PetscInt ncr,rst; 1585b68353e5Sstefano_zampini 1586b68353e5Sstefano_zampini ierr = ISStrideGetInfo(nest->isglobal.row[i],&rst,NULL);CHKERRQ(ierr); 1587b68353e5Sstefano_zampini ierr = ISGetLocalSize(nest->isglobal.row[i],&ncr);CHKERRQ(ierr); 1588b68353e5Sstefano_zampini for (j=0; j<nest->nc; ++j) { 1589b68353e5Sstefano_zampini if (aii[i*nest->nc+j]) { 1590b68353e5Sstefano_zampini PetscInt *nii = aii[i*nest->nc+j]; 1591b68353e5Sstefano_zampini PetscInt ir; 1592b68353e5Sstefano_zampini 1593b68353e5Sstefano_zampini for (ir=rst; ir<ncr+rst; ++ir) { 1594b68353e5Sstefano_zampini ii[ir+1] += nii[1]-nii[0]; 1595b68353e5Sstefano_zampini nii++; 1596b68353e5Sstefano_zampini } 1597b68353e5Sstefano_zampini } 1598b68353e5Sstefano_zampini } 1599b68353e5Sstefano_zampini } 1600b68353e5Sstefano_zampini for (i=0; i<nr; i++) ii[i+1] += ii[i]; 1601b68353e5Sstefano_zampini 1602b68353e5Sstefano_zampini /* construct CSR for the new matrix */ 1603b68353e5Sstefano_zampini ierr = PetscCalloc1(nr,&ci);CHKERRQ(ierr); 1604b68353e5Sstefano_zampini for (i=0; i<nest->nr; ++i) { 1605b68353e5Sstefano_zampini PetscInt ncr,rst; 1606b68353e5Sstefano_zampini 1607b68353e5Sstefano_zampini ierr = ISStrideGetInfo(nest->isglobal.row[i],&rst,NULL);CHKERRQ(ierr); 1608b68353e5Sstefano_zampini ierr = ISGetLocalSize(nest->isglobal.row[i],&ncr);CHKERRQ(ierr); 1609b68353e5Sstefano_zampini for (j=0; j<nest->nc; ++j) { 1610b68353e5Sstefano_zampini if (aii[i*nest->nc+j]) { 1611b68353e5Sstefano_zampini PetscScalar *nvv = avv[i*nest->nc+j]; 1612b68353e5Sstefano_zampini PetscInt *nii = aii[i*nest->nc+j]; 1613b68353e5Sstefano_zampini PetscInt *njj = ajj[i*nest->nc+j]; 1614b68353e5Sstefano_zampini PetscInt ir,cst; 1615b68353e5Sstefano_zampini 1616b68353e5Sstefano_zampini ierr = ISStrideGetInfo(nest->isglobal.col[j],&cst,NULL);CHKERRQ(ierr); 1617b68353e5Sstefano_zampini for (ir=rst; ir<ncr+rst; ++ir) { 1618b68353e5Sstefano_zampini PetscInt ij,rsize = nii[1]-nii[0],ist = ii[ir]+ci[ir]; 1619b68353e5Sstefano_zampini 1620b68353e5Sstefano_zampini for (ij=0;ij<rsize;ij++) { 1621b68353e5Sstefano_zampini jj[ist+ij] = *njj+cst; 1622b68353e5Sstefano_zampini vv[ist+ij] = *nvv; 1623b68353e5Sstefano_zampini njj++; 1624b68353e5Sstefano_zampini nvv++; 1625b68353e5Sstefano_zampini } 1626b68353e5Sstefano_zampini ci[ir] += rsize; 1627b68353e5Sstefano_zampini nii++; 1628b68353e5Sstefano_zampini } 1629b68353e5Sstefano_zampini } 1630b68353e5Sstefano_zampini } 1631b68353e5Sstefano_zampini } 1632b68353e5Sstefano_zampini ierr = PetscFree(ci);CHKERRQ(ierr); 1633b68353e5Sstefano_zampini 1634b68353e5Sstefano_zampini /* restore info */ 1635b68353e5Sstefano_zampini for (i=0; i<nest->nr; ++i) { 1636b68353e5Sstefano_zampini for (j=0; j<nest->nc; ++j) { 1637b68353e5Sstefano_zampini Mat B = nest->m[i][j]; 1638b68353e5Sstefano_zampini if (B) { 1639b68353e5Sstefano_zampini PetscInt nnr = 0, k = i*nest->nc+j; 164023875855Sstefano_zampini 164123875855Sstefano_zampini B = (trans[k] ? trans[k] : B); 1642b68353e5Sstefano_zampini ierr = MatRestoreRowIJ(B,0,PETSC_FALSE,PETSC_FALSE,&nnr,(const PetscInt**)&aii[k],(const PetscInt**)&ajj[k],&done);CHKERRQ(ierr); 1643b68353e5Sstefano_zampini if (!done) SETERRQ(PetscObjectComm((PetscObject)B),PETSC_ERR_PLIB,"MatRestoreRowIJ"); 1644b68353e5Sstefano_zampini ierr = MatSeqAIJRestoreArray(B,&avv[k]);CHKERRQ(ierr); 164523875855Sstefano_zampini ierr = MatDestroy(&trans[k]);CHKERRQ(ierr); 1646b68353e5Sstefano_zampini } 1647b68353e5Sstefano_zampini } 1648b68353e5Sstefano_zampini } 164923875855Sstefano_zampini ierr = PetscFree4(aii,ajj,avv,trans);CHKERRQ(ierr); 1650b68353e5Sstefano_zampini 1651b68353e5Sstefano_zampini /* finalize newmat */ 1652b68353e5Sstefano_zampini if (reuse == MAT_INITIAL_MATRIX) { 1653b68353e5Sstefano_zampini ierr = MatCreateSeqAIJWithArrays(PetscObjectComm((PetscObject)A),nr,nc,ii,jj,vv,newmat);CHKERRQ(ierr); 1654b68353e5Sstefano_zampini } else if (reuse == MAT_INPLACE_MATRIX) { 1655b68353e5Sstefano_zampini Mat B; 1656b68353e5Sstefano_zampini 1657b68353e5Sstefano_zampini ierr = MatCreateSeqAIJWithArrays(PetscObjectComm((PetscObject)A),nr,nc,ii,jj,vv,&B);CHKERRQ(ierr); 1658b68353e5Sstefano_zampini ierr = MatHeaderReplace(A,&B);CHKERRQ(ierr); 1659b68353e5Sstefano_zampini } 1660b68353e5Sstefano_zampini ierr = MatAssemblyBegin(*newmat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 1661b68353e5Sstefano_zampini ierr = MatAssemblyEnd(*newmat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 1662b68353e5Sstefano_zampini { 1663b68353e5Sstefano_zampini Mat_SeqAIJ *a = (Mat_SeqAIJ*)((*newmat)->data); 1664b68353e5Sstefano_zampini a->free_a = PETSC_TRUE; 1665b68353e5Sstefano_zampini a->free_ij = PETSC_TRUE; 1666b68353e5Sstefano_zampini } 1667b68353e5Sstefano_zampini PetscFunctionReturn(0); 1668b68353e5Sstefano_zampini } 1669b68353e5Sstefano_zampini 1670cc2e6a90SBarry Smith PETSC_INTERN PetscErrorCode MatConvert_Nest_AIJ(Mat A,MatType newtype,MatReuse reuse,Mat *newmat) 1671629c3df2SDmitry Karpeev { 1672629c3df2SDmitry Karpeev PetscErrorCode ierr; 1673629c3df2SDmitry Karpeev Mat_Nest *nest = (Mat_Nest*)A->data; 167483b1a929SMark Adams PetscInt m,n,M,N,i,j,k,*dnnz,*onnz,rstart; 1675649b366bSFande Kong PetscInt cstart,cend; 1676b68353e5Sstefano_zampini PetscMPIInt size; 1677629c3df2SDmitry Karpeev Mat C; 1678629c3df2SDmitry Karpeev 1679629c3df2SDmitry Karpeev PetscFunctionBegin; 1680b68353e5Sstefano_zampini ierr = MPI_Comm_size(PetscObjectComm((PetscObject)A),&size);CHKERRQ(ierr); 1681b68353e5Sstefano_zampini if (size == 1) { /* look for a special case with SeqAIJ matrices and strided-1, contiguous, blocks */ 1682b68353e5Sstefano_zampini PetscInt nf; 1683b68353e5Sstefano_zampini PetscBool fast; 1684b68353e5Sstefano_zampini 1685b68353e5Sstefano_zampini ierr = PetscStrcmp(newtype,MATAIJ,&fast);CHKERRQ(ierr); 1686b68353e5Sstefano_zampini if (!fast) { 1687b68353e5Sstefano_zampini ierr = PetscStrcmp(newtype,MATSEQAIJ,&fast);CHKERRQ(ierr); 1688b68353e5Sstefano_zampini } 1689b68353e5Sstefano_zampini for (i=0; i<nest->nr && fast; ++i) { 1690b68353e5Sstefano_zampini for (j=0; j<nest->nc && fast; ++j) { 1691b68353e5Sstefano_zampini Mat B = nest->m[i][j]; 1692b68353e5Sstefano_zampini if (B) { 1693b68353e5Sstefano_zampini ierr = PetscObjectTypeCompare((PetscObject)B,MATSEQAIJ,&fast);CHKERRQ(ierr); 169423875855Sstefano_zampini if (!fast) { 169523875855Sstefano_zampini PetscBool istrans; 169623875855Sstefano_zampini 169723875855Sstefano_zampini ierr = PetscObjectTypeCompare((PetscObject)B,MATTRANSPOSEMAT,&istrans);CHKERRQ(ierr); 169823875855Sstefano_zampini if (istrans) { 169923875855Sstefano_zampini Mat Bt; 170023875855Sstefano_zampini 170123875855Sstefano_zampini ierr = MatTransposeGetMat(B,&Bt);CHKERRQ(ierr); 170223875855Sstefano_zampini ierr = PetscObjectTypeCompare((PetscObject)Bt,MATSEQAIJ,&fast);CHKERRQ(ierr); 170323875855Sstefano_zampini } 1704b68353e5Sstefano_zampini } 1705b68353e5Sstefano_zampini } 1706b68353e5Sstefano_zampini } 1707b68353e5Sstefano_zampini } 1708b68353e5Sstefano_zampini for (i=0, nf=0; i<nest->nr && fast; ++i) { 1709b68353e5Sstefano_zampini ierr = PetscObjectTypeCompare((PetscObject)nest->isglobal.row[i],ISSTRIDE,&fast);CHKERRQ(ierr); 1710b68353e5Sstefano_zampini if (fast) { 1711b68353e5Sstefano_zampini PetscInt f,s; 1712b68353e5Sstefano_zampini 1713b68353e5Sstefano_zampini ierr = ISStrideGetInfo(nest->isglobal.row[i],&f,&s);CHKERRQ(ierr); 1714b68353e5Sstefano_zampini if (f != nf || s != 1) { fast = PETSC_FALSE; } 1715b68353e5Sstefano_zampini else { 1716b68353e5Sstefano_zampini ierr = ISGetSize(nest->isglobal.row[i],&f);CHKERRQ(ierr); 1717b68353e5Sstefano_zampini nf += f; 1718b68353e5Sstefano_zampini } 1719b68353e5Sstefano_zampini } 1720b68353e5Sstefano_zampini } 1721b68353e5Sstefano_zampini for (i=0, nf=0; i<nest->nc && fast; ++i) { 1722b68353e5Sstefano_zampini ierr = PetscObjectTypeCompare((PetscObject)nest->isglobal.col[i],ISSTRIDE,&fast);CHKERRQ(ierr); 1723b68353e5Sstefano_zampini if (fast) { 1724b68353e5Sstefano_zampini PetscInt f,s; 1725b68353e5Sstefano_zampini 1726b68353e5Sstefano_zampini ierr = ISStrideGetInfo(nest->isglobal.col[i],&f,&s);CHKERRQ(ierr); 1727b68353e5Sstefano_zampini if (f != nf || s != 1) { fast = PETSC_FALSE; } 1728b68353e5Sstefano_zampini else { 1729b68353e5Sstefano_zampini ierr = ISGetSize(nest->isglobal.col[i],&f);CHKERRQ(ierr); 1730b68353e5Sstefano_zampini nf += f; 1731b68353e5Sstefano_zampini } 1732b68353e5Sstefano_zampini } 1733b68353e5Sstefano_zampini } 1734b68353e5Sstefano_zampini if (fast) { 1735b68353e5Sstefano_zampini ierr = MatConvert_Nest_SeqAIJ_fast(A,newtype,reuse,newmat);CHKERRQ(ierr); 1736b68353e5Sstefano_zampini PetscFunctionReturn(0); 1737b68353e5Sstefano_zampini } 1738b68353e5Sstefano_zampini } 1739629c3df2SDmitry Karpeev ierr = MatGetSize(A,&M,&N);CHKERRQ(ierr); 1740629c3df2SDmitry Karpeev ierr = MatGetLocalSize(A,&m,&n);CHKERRQ(ierr); 1741649b366bSFande Kong ierr = MatGetOwnershipRangeColumn(A,&cstart,&cend);CHKERRQ(ierr); 1742629c3df2SDmitry Karpeev switch (reuse) { 1743629c3df2SDmitry Karpeev case MAT_INITIAL_MATRIX: 1744ce94432eSBarry Smith ierr = MatCreate(PetscObjectComm((PetscObject)A),&C);CHKERRQ(ierr); 1745629c3df2SDmitry Karpeev ierr = MatSetType(C,newtype);CHKERRQ(ierr); 1746629c3df2SDmitry Karpeev ierr = MatSetSizes(C,m,n,M,N);CHKERRQ(ierr); 1747629c3df2SDmitry Karpeev *newmat = C; 1748629c3df2SDmitry Karpeev break; 1749629c3df2SDmitry Karpeev case MAT_REUSE_MATRIX: 1750629c3df2SDmitry Karpeev C = *newmat; 1751629c3df2SDmitry Karpeev break; 1752ce94432eSBarry Smith default: SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_SUP,"MatReuse"); 1753629c3df2SDmitry Karpeev } 1754785e854fSJed Brown ierr = PetscMalloc1(2*m,&dnnz);CHKERRQ(ierr); 1755629c3df2SDmitry Karpeev onnz = dnnz + m; 1756629c3df2SDmitry Karpeev for (k=0; k<m; k++) { 1757629c3df2SDmitry Karpeev dnnz[k] = 0; 1758629c3df2SDmitry Karpeev onnz[k] = 0; 1759629c3df2SDmitry Karpeev } 1760629c3df2SDmitry Karpeev for (j=0; j<nest->nc; ++j) { 1761629c3df2SDmitry Karpeev IS bNis; 1762629c3df2SDmitry Karpeev PetscInt bN; 1763629c3df2SDmitry Karpeev const PetscInt *bNindices; 1764629c3df2SDmitry Karpeev /* Using global column indices and ISAllGather() is not scalable. */ 1765629c3df2SDmitry Karpeev ierr = ISAllGather(nest->isglobal.col[j], &bNis);CHKERRQ(ierr); 1766629c3df2SDmitry Karpeev ierr = ISGetSize(bNis, &bN);CHKERRQ(ierr); 1767629c3df2SDmitry Karpeev ierr = ISGetIndices(bNis,&bNindices);CHKERRQ(ierr); 1768629c3df2SDmitry Karpeev for (i=0; i<nest->nr; ++i) { 1769629c3df2SDmitry Karpeev PetscSF bmsf; 1770649b366bSFande Kong PetscSFNode *iremote; 1771629c3df2SDmitry Karpeev Mat B; 1772649b366bSFande Kong PetscInt bm, *sub_dnnz,*sub_onnz, br; 1773629c3df2SDmitry Karpeev const PetscInt *bmindices; 1774629c3df2SDmitry Karpeev B = nest->m[i][j]; 1775629c3df2SDmitry Karpeev if (!B) continue; 1776629c3df2SDmitry Karpeev ierr = ISGetLocalSize(nest->isglobal.row[i],&bm);CHKERRQ(ierr); 1777629c3df2SDmitry Karpeev ierr = ISGetIndices(nest->isglobal.row[i],&bmindices);CHKERRQ(ierr); 1778ce94432eSBarry Smith ierr = PetscSFCreate(PetscObjectComm((PetscObject)A), &bmsf);CHKERRQ(ierr); 1779649b366bSFande Kong ierr = PetscMalloc1(bm,&iremote);CHKERRQ(ierr); 1780649b366bSFande Kong ierr = PetscMalloc1(bm,&sub_dnnz);CHKERRQ(ierr); 1781649b366bSFande Kong ierr = PetscMalloc1(bm,&sub_onnz);CHKERRQ(ierr); 1782649b366bSFande Kong for (k = 0; k < bm; ++k){ 1783649b366bSFande Kong sub_dnnz[k] = 0; 1784649b366bSFande Kong sub_onnz[k] = 0; 1785649b366bSFande Kong } 1786629c3df2SDmitry Karpeev /* 1787629c3df2SDmitry Karpeev Locate the owners for all of the locally-owned global row indices for this row block. 1788629c3df2SDmitry Karpeev These determine the roots of PetscSF used to communicate preallocation data to row owners. 1789629c3df2SDmitry Karpeev The roots correspond to the dnnz and onnz entries; thus, there are two roots per row. 1790629c3df2SDmitry Karpeev */ 179183b1a929SMark Adams ierr = MatGetOwnershipRange(B,&rstart,NULL);CHKERRQ(ierr); 1792629c3df2SDmitry Karpeev for (br = 0; br < bm; ++br) { 1793649b366bSFande Kong PetscInt row = bmindices[br], rowowner = 0, brncols, col; 1794629c3df2SDmitry Karpeev const PetscInt *brcols; 1795a4b3d3acSMatthew G Knepley PetscInt rowrel = 0; /* row's relative index on its owner rank */ 1796629c3df2SDmitry Karpeev ierr = PetscLayoutFindOwnerIndex(A->rmap,row,&rowowner,&rowrel);CHKERRQ(ierr); 1797649b366bSFande Kong /* how many roots */ 1798649b366bSFande Kong iremote[br].rank = rowowner; iremote[br].index = rowrel; /* edge from bmdnnz to dnnz */ 1799649b366bSFande Kong /* get nonzero pattern */ 180083b1a929SMark Adams ierr = MatGetRow(B,br+rstart,&brncols,&brcols,NULL);CHKERRQ(ierr); 1801629c3df2SDmitry Karpeev for (k=0; k<brncols; k++) { 1802629c3df2SDmitry Karpeev col = bNindices[brcols[k]]; 1803649b366bSFande Kong if (col>=A->cmap->range[rowowner] && col<A->cmap->range[rowowner+1]) { 1804649b366bSFande Kong sub_dnnz[br]++; 1805649b366bSFande Kong } else { 1806649b366bSFande Kong sub_onnz[br]++; 1807649b366bSFande Kong } 1808629c3df2SDmitry Karpeev } 180983b1a929SMark Adams ierr = MatRestoreRow(B,br+rstart,&brncols,&brcols,NULL);CHKERRQ(ierr); 1810629c3df2SDmitry Karpeev } 1811629c3df2SDmitry Karpeev ierr = ISRestoreIndices(nest->isglobal.row[i],&bmindices);CHKERRQ(ierr); 1812629c3df2SDmitry Karpeev /* bsf will have to take care of disposing of bedges. */ 1813649b366bSFande Kong ierr = PetscSFSetGraph(bmsf,m,bm,NULL,PETSC_OWN_POINTER,iremote,PETSC_OWN_POINTER);CHKERRQ(ierr); 1814649b366bSFande Kong ierr = PetscSFReduceBegin(bmsf,MPIU_INT,sub_dnnz,dnnz,MPI_SUM);CHKERRQ(ierr); 1815649b366bSFande Kong ierr = PetscSFReduceEnd(bmsf,MPIU_INT,sub_dnnz,dnnz,MPI_SUM);CHKERRQ(ierr); 1816649b366bSFande Kong ierr = PetscSFReduceBegin(bmsf,MPIU_INT,sub_onnz,onnz,MPI_SUM);CHKERRQ(ierr); 1817649b366bSFande Kong ierr = PetscSFReduceEnd(bmsf,MPIU_INT,sub_onnz,onnz,MPI_SUM);CHKERRQ(ierr); 1818649b366bSFande Kong ierr = PetscFree(sub_dnnz);CHKERRQ(ierr); 1819649b366bSFande Kong ierr = PetscFree(sub_onnz);CHKERRQ(ierr); 1820629c3df2SDmitry Karpeev ierr = PetscSFDestroy(&bmsf);CHKERRQ(ierr); 1821629c3df2SDmitry Karpeev } 182222d28d08SBarry Smith ierr = ISRestoreIndices(bNis,&bNindices);CHKERRQ(ierr); 1823629c3df2SDmitry Karpeev ierr = ISDestroy(&bNis);CHKERRQ(ierr); 182465a4a0a3Sstefano_zampini } 182565a4a0a3Sstefano_zampini /* Resize preallocation if overestimated */ 182665a4a0a3Sstefano_zampini for (i=0;i<m;i++) { 182765a4a0a3Sstefano_zampini dnnz[i] = PetscMin(dnnz[i],A->cmap->n); 182865a4a0a3Sstefano_zampini onnz[i] = PetscMin(onnz[i],A->cmap->N - A->cmap->n); 1829629c3df2SDmitry Karpeev } 1830629c3df2SDmitry Karpeev ierr = MatSeqAIJSetPreallocation(C,0,dnnz);CHKERRQ(ierr); 1831629c3df2SDmitry Karpeev ierr = MatMPIAIJSetPreallocation(C,0,dnnz,0,onnz);CHKERRQ(ierr); 1832629c3df2SDmitry Karpeev ierr = PetscFree(dnnz);CHKERRQ(ierr); 1833629c3df2SDmitry Karpeev 1834629c3df2SDmitry Karpeev /* Fill by row */ 1835629c3df2SDmitry Karpeev for (j=0; j<nest->nc; ++j) { 1836629c3df2SDmitry Karpeev /* Using global column indices and ISAllGather() is not scalable. */ 1837629c3df2SDmitry Karpeev IS bNis; 1838629c3df2SDmitry Karpeev PetscInt bN; 1839629c3df2SDmitry Karpeev const PetscInt *bNindices; 1840629c3df2SDmitry Karpeev ierr = ISAllGather(nest->isglobal.col[j], &bNis);CHKERRQ(ierr); 1841629c3df2SDmitry Karpeev ierr = ISGetSize(bNis,&bN);CHKERRQ(ierr); 1842629c3df2SDmitry Karpeev ierr = ISGetIndices(bNis,&bNindices);CHKERRQ(ierr); 1843629c3df2SDmitry Karpeev for (i=0; i<nest->nr; ++i) { 1844629c3df2SDmitry Karpeev Mat B; 1845629c3df2SDmitry Karpeev PetscInt bm, br; 1846629c3df2SDmitry Karpeev const PetscInt *bmindices; 1847629c3df2SDmitry Karpeev B = nest->m[i][j]; 1848629c3df2SDmitry Karpeev if (!B) continue; 1849629c3df2SDmitry Karpeev ierr = ISGetLocalSize(nest->isglobal.row[i],&bm);CHKERRQ(ierr); 1850629c3df2SDmitry Karpeev ierr = ISGetIndices(nest->isglobal.row[i],&bmindices);CHKERRQ(ierr); 185183b1a929SMark Adams ierr = MatGetOwnershipRange(B,&rstart,NULL);CHKERRQ(ierr); 1852629c3df2SDmitry Karpeev for (br = 0; br < bm; ++br) { 1853629c3df2SDmitry Karpeev PetscInt row = bmindices[br], brncols, *cols; 1854629c3df2SDmitry Karpeev const PetscInt *brcols; 1855629c3df2SDmitry Karpeev const PetscScalar *brcoldata; 185683b1a929SMark Adams ierr = MatGetRow(B,br+rstart,&brncols,&brcols,&brcoldata);CHKERRQ(ierr); 1857785e854fSJed Brown ierr = PetscMalloc1(brncols,&cols);CHKERRQ(ierr); 185826fbe8dcSKarl Rupp for (k=0; k<brncols; k++) cols[k] = bNindices[brcols[k]]; 1859629c3df2SDmitry Karpeev /* 1860629c3df2SDmitry Karpeev Nest blocks are required to be nonoverlapping -- otherwise nest and monolithic index layouts wouldn't match. 1861629c3df2SDmitry Karpeev Thus, we could use INSERT_VALUES, but I prefer ADD_VALUES. 1862629c3df2SDmitry Karpeev */ 1863a2ea699eSBarry Smith ierr = MatSetValues(C,1,&row,brncols,cols,brcoldata,ADD_VALUES);CHKERRQ(ierr); 186483b1a929SMark Adams ierr = MatRestoreRow(B,br+rstart,&brncols,&brcols,&brcoldata);CHKERRQ(ierr); 1865629c3df2SDmitry Karpeev ierr = PetscFree(cols);CHKERRQ(ierr); 1866629c3df2SDmitry Karpeev } 1867629c3df2SDmitry Karpeev ierr = ISRestoreIndices(nest->isglobal.row[i],&bmindices);CHKERRQ(ierr); 1868629c3df2SDmitry Karpeev } 1869a2ea699eSBarry Smith ierr = ISRestoreIndices(bNis,&bNindices);CHKERRQ(ierr); 1870629c3df2SDmitry Karpeev ierr = ISDestroy(&bNis);CHKERRQ(ierr); 1871629c3df2SDmitry Karpeev } 1872629c3df2SDmitry Karpeev ierr = MatAssemblyBegin(C,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 1873629c3df2SDmitry Karpeev ierr = MatAssemblyEnd(C,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 1874629c3df2SDmitry Karpeev PetscFunctionReturn(0); 1875629c3df2SDmitry Karpeev } 1876629c3df2SDmitry Karpeev 18778b7d3b4bSBarry Smith PetscErrorCode MatHasOperation_Nest(Mat mat,MatOperation op,PetscBool *has) 18788b7d3b4bSBarry Smith { 18798b7d3b4bSBarry Smith PetscFunctionBegin; 18808b7d3b4bSBarry Smith *has = PETSC_FALSE; 18818b7d3b4bSBarry Smith if (op == MATOP_MULT_TRANSPOSE) { 18828b7d3b4bSBarry Smith Mat_Nest *bA = (Mat_Nest*)mat->data; 18838b7d3b4bSBarry Smith PetscInt i,j,nr = bA->nr,nc = bA->nc; 18848b7d3b4bSBarry Smith PetscErrorCode ierr; 18858b7d3b4bSBarry Smith PetscBool flg; 18868b7d3b4bSBarry Smith 18878b7d3b4bSBarry Smith for (j=0; j<nc; j++) { 18888b7d3b4bSBarry Smith for (i=0; i<nr; i++) { 18898b7d3b4bSBarry Smith if (!bA->m[i][j]) continue; 18908b7d3b4bSBarry Smith ierr = MatHasOperation(bA->m[i][j],MATOP_MULT_TRANSPOSE_ADD,&flg);CHKERRQ(ierr); 18918b7d3b4bSBarry Smith if (!flg) PetscFunctionReturn(0); 18928b7d3b4bSBarry Smith } 18938b7d3b4bSBarry Smith } 18948b7d3b4bSBarry Smith } 18958b7d3b4bSBarry Smith if (((void**)mat->ops)[op]) *has = PETSC_TRUE; 18968b7d3b4bSBarry Smith PetscFunctionReturn(0); 18978b7d3b4bSBarry Smith } 18988b7d3b4bSBarry Smith 1899659c6bb0SJed Brown /*MC 1900659c6bb0SJed Brown MATNEST - MATNEST = "nest" - Matrix type consisting of nested submatrices, each stored separately. 1901659c6bb0SJed Brown 1902659c6bb0SJed Brown Level: intermediate 1903659c6bb0SJed Brown 1904659c6bb0SJed Brown Notes: 1905659c6bb0SJed Brown This matrix type permits scalable use of PCFieldSplit and avoids the large memory costs of extracting submatrices. 1906659c6bb0SJed Brown It allows the use of symmetric and block formats for parts of multi-physics simulations. 1907950540a4SJed Brown It is usually used with DMComposite and DMCreateMatrix() 1908659c6bb0SJed Brown 19098b7d3b4bSBarry Smith Each of the submatrices lives on the same MPI communicator as the original nest matrix (though they can have zero 19108b7d3b4bSBarry Smith rows/columns on some processes.) Thus this is not meant for cases where the submatrices live on far fewer processes 19118b7d3b4bSBarry Smith than the nest matrix. 19128b7d3b4bSBarry Smith 1913659c6bb0SJed Brown .seealso: MatCreate(), MatType, MatCreateNest() 1914659c6bb0SJed Brown M*/ 19158cc058d9SJed Brown PETSC_EXTERN PetscErrorCode MatCreate_Nest(Mat A) 1916c8883902SJed Brown { 1917c8883902SJed Brown Mat_Nest *s; 1918c8883902SJed Brown PetscErrorCode ierr; 1919c8883902SJed Brown 1920c8883902SJed Brown PetscFunctionBegin; 1921b00a9115SJed Brown ierr = PetscNewLog(A,&s);CHKERRQ(ierr); 1922c8883902SJed Brown A->data = (void*)s; 1923e7c19651SJed Brown 1924e7c19651SJed Brown s->nr = -1; 1925e7c19651SJed Brown s->nc = -1; 19260298fd71SBarry Smith s->m = NULL; 1927e7c19651SJed Brown s->splitassembly = PETSC_FALSE; 1928c8883902SJed Brown 1929c8883902SJed Brown ierr = PetscMemzero(A->ops,sizeof(*A->ops));CHKERRQ(ierr); 193026fbe8dcSKarl Rupp 1931c8883902SJed Brown A->ops->mult = MatMult_Nest; 19329194d70fSJed Brown A->ops->multadd = MatMultAdd_Nest; 1933c8883902SJed Brown A->ops->multtranspose = MatMultTranspose_Nest; 19349194d70fSJed Brown A->ops->multtransposeadd = MatMultTransposeAdd_Nest; 1935f8170845SAlex Fikl A->ops->transpose = MatTranspose_Nest; 1936c8883902SJed Brown A->ops->assemblybegin = MatAssemblyBegin_Nest; 1937c8883902SJed Brown A->ops->assemblyend = MatAssemblyEnd_Nest; 1938c8883902SJed Brown A->ops->zeroentries = MatZeroEntries_Nest; 1939c222c20dSDavid Ham A->ops->copy = MatCopy_Nest; 19406e76ffeaSPierre Jolivet A->ops->axpy = MatAXPY_Nest; 1941c8883902SJed Brown A->ops->duplicate = MatDuplicate_Nest; 19427dae84e0SHong Zhang A->ops->createsubmatrix = MatCreateSubMatrix_Nest; 1943c8883902SJed Brown A->ops->destroy = MatDestroy_Nest; 1944c8883902SJed Brown A->ops->view = MatView_Nest; 1945c8883902SJed Brown A->ops->getvecs = 0; /* Use VECNEST by calling MatNestSetVecType(A,VECNEST) */ 1946c8883902SJed Brown A->ops->getlocalsubmatrix = MatGetLocalSubMatrix_Nest; 1947c8883902SJed Brown A->ops->restorelocalsubmatrix = MatRestoreLocalSubMatrix_Nest; 1948429bac76SJed Brown A->ops->getdiagonal = MatGetDiagonal_Nest; 1949429bac76SJed Brown A->ops->diagonalscale = MatDiagonalScale_Nest; 1950a061e289SJed Brown A->ops->scale = MatScale_Nest; 1951a061e289SJed Brown A->ops->shift = MatShift_Nest; 195213135bc6SAlex Fikl A->ops->diagonalset = MatDiagonalSet_Nest; 1953f8170845SAlex Fikl A->ops->setrandom = MatSetRandom_Nest; 19548b7d3b4bSBarry Smith A->ops->hasoperation = MatHasOperation_Nest; 1955c8883902SJed Brown 1956c8883902SJed Brown A->spptr = 0; 1957c8883902SJed Brown A->assembled = PETSC_FALSE; 1958c8883902SJed Brown 1959c8883902SJed Brown /* expose Nest api's */ 1960bdf89e91SBarry Smith ierr = PetscObjectComposeFunction((PetscObject)A,"MatNestGetSubMat_C", MatNestGetSubMat_Nest);CHKERRQ(ierr); 1961bdf89e91SBarry Smith ierr = PetscObjectComposeFunction((PetscObject)A,"MatNestSetSubMat_C", MatNestSetSubMat_Nest);CHKERRQ(ierr); 1962bdf89e91SBarry Smith ierr = PetscObjectComposeFunction((PetscObject)A,"MatNestGetSubMats_C", MatNestGetSubMats_Nest);CHKERRQ(ierr); 1963bdf89e91SBarry Smith ierr = PetscObjectComposeFunction((PetscObject)A,"MatNestGetSize_C", MatNestGetSize_Nest);CHKERRQ(ierr); 1964bdf89e91SBarry Smith ierr = PetscObjectComposeFunction((PetscObject)A,"MatNestGetISs_C", MatNestGetISs_Nest);CHKERRQ(ierr); 1965bdf89e91SBarry Smith ierr = PetscObjectComposeFunction((PetscObject)A,"MatNestGetLocalISs_C", MatNestGetLocalISs_Nest);CHKERRQ(ierr); 1966bdf89e91SBarry Smith ierr = PetscObjectComposeFunction((PetscObject)A,"MatNestSetVecType_C", MatNestSetVecType_Nest);CHKERRQ(ierr); 1967bdf89e91SBarry Smith ierr = PetscObjectComposeFunction((PetscObject)A,"MatNestSetSubMats_C", MatNestSetSubMats_Nest);CHKERRQ(ierr); 19680899c546SStefano Zampini ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_nest_mpiaij_C",MatConvert_Nest_AIJ);CHKERRQ(ierr); 19690899c546SStefano Zampini ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_nest_seqaij_C",MatConvert_Nest_AIJ);CHKERRQ(ierr); 197083b1a929SMark Adams ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_nest_aij_C", MatConvert_Nest_AIJ);CHKERRQ(ierr); 19715e3038f0Sstefano_zampini ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_nest_is_C", MatConvert_Nest_IS);CHKERRQ(ierr); 1972c8883902SJed Brown 1973c8883902SJed Brown ierr = PetscObjectChangeTypeName((PetscObject)A,MATNEST);CHKERRQ(ierr); 1974c8883902SJed Brown PetscFunctionReturn(0); 1975c8883902SJed Brown } 1976