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; 359320466b0SStefano 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 795*060bfc19SStefano Zampini if (str != DIFFERENT_NONZERO_PATTERN) SETERRQ2(PetscObjectComm((PetscObject)Y),PETSC_ERR_ARG_INCOMP,"Matrix block does not exist at %D,%D. Use DIFFERENT_NONZERO_PATTERN",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 } 800*060bfc19SStefano Zampini if (bY->m[i][j]) { 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++) { 1194320466b0SStefano 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; 1257aea6d515SStefano Zampini *ltog = NULL; 125877019fcaSJed Brown for (i=0,m=0,flg=PETSC_FALSE; i<n; i++) { 125977019fcaSJed Brown if (islocal[i]) { 1260aea6d515SStefano Zampini ierr = ISGetLocalSize(islocal[i],&mi);CHKERRQ(ierr); 126177019fcaSJed Brown flg = PETSC_TRUE; /* We found a non-trivial entry */ 126277019fcaSJed Brown } else { 1263aea6d515SStefano Zampini ierr = ISGetLocalSize(isglobal[i],&mi);CHKERRQ(ierr); 126477019fcaSJed Brown } 126577019fcaSJed Brown m += mi; 126677019fcaSJed Brown } 1267aea6d515SStefano Zampini if (!flg) PetscFunctionReturn(0); 1268aea6d515SStefano Zampini 1269785e854fSJed Brown ierr = PetscMalloc1(m,&ix);CHKERRQ(ierr); 1270165cd838SBarry Smith for (i=0,m=0; i<n; i++) { 12710298fd71SBarry Smith ISLocalToGlobalMapping smap = NULL; 1272e108cb99SStefano Zampini Mat sub = NULL; 1273f6d38dbbSStefano Zampini PetscSF sf; 1274f6d38dbbSStefano Zampini PetscLayout map; 1275aea6d515SStefano Zampini const PetscInt *ix2; 127677019fcaSJed Brown 1277165cd838SBarry Smith if (!colflg) { 127877019fcaSJed Brown ierr = MatNestFindNonzeroSubMatRow(A,i,&sub);CHKERRQ(ierr); 127977019fcaSJed Brown } else { 128077019fcaSJed Brown ierr = MatNestFindNonzeroSubMatCol(A,i,&sub);CHKERRQ(ierr); 128177019fcaSJed Brown } 1282191fd14bSBarry Smith if (sub) { 1283191fd14bSBarry Smith if (!colflg) { 1284191fd14bSBarry Smith ierr = MatGetLocalToGlobalMapping(sub,&smap,NULL);CHKERRQ(ierr); 1285191fd14bSBarry Smith } else { 1286191fd14bSBarry Smith ierr = MatGetLocalToGlobalMapping(sub,NULL,&smap);CHKERRQ(ierr); 1287191fd14bSBarry Smith } 1288191fd14bSBarry Smith } 128977019fcaSJed Brown /* 129077019fcaSJed Brown Now we need to extract the monolithic global indices that correspond to the given split global indices. 129177019fcaSJed 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. 129277019fcaSJed Brown */ 1293aea6d515SStefano Zampini ierr = ISGetIndices(isglobal[i],&ix2);CHKERRQ(ierr); 1294aea6d515SStefano Zampini if (islocal[i]) { 1295aea6d515SStefano Zampini PetscInt *ilocal,*iremote; 1296aea6d515SStefano Zampini PetscInt mil,nleaves; 1297aea6d515SStefano Zampini 1298aea6d515SStefano Zampini ierr = ISGetLocalSize(islocal[i],&mi);CHKERRQ(ierr); 1299aea6d515SStefano Zampini if (!smap) SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_PLIB,"Missing local to global map"); 1300aea6d515SStefano Zampini for (j=0; j<mi; j++) ix[m+j] = j; 1301aea6d515SStefano Zampini ierr = ISLocalToGlobalMappingApply(smap,mi,ix+m,ix+m);CHKERRQ(ierr); 1302aea6d515SStefano Zampini 1303aea6d515SStefano Zampini /* PetscSFSetGraphLayout does not like negative indices */ 1304aea6d515SStefano Zampini ierr = PetscMalloc2(mi,&ilocal,mi,&iremote);CHKERRQ(ierr); 1305aea6d515SStefano Zampini for (j=0, nleaves = 0; j<mi; j++) { 1306aea6d515SStefano Zampini if (ix[m+j] < 0) continue; 1307aea6d515SStefano Zampini ilocal[nleaves] = j; 1308aea6d515SStefano Zampini iremote[nleaves] = ix[m+j]; 1309aea6d515SStefano Zampini nleaves++; 1310aea6d515SStefano Zampini } 1311aea6d515SStefano Zampini ierr = ISGetLocalSize(isglobal[i],&mil);CHKERRQ(ierr); 1312aea6d515SStefano Zampini ierr = PetscSFCreate(PetscObjectComm((PetscObject)A),&sf);CHKERRQ(ierr); 1313aea6d515SStefano Zampini ierr = PetscLayoutCreate(PetscObjectComm((PetscObject)A),&map);CHKERRQ(ierr); 1314aea6d515SStefano Zampini ierr = PetscLayoutSetLocalSize(map,mil);CHKERRQ(ierr); 1315f6d38dbbSStefano Zampini ierr = PetscLayoutSetUp(map);CHKERRQ(ierr); 1316aea6d515SStefano Zampini ierr = PetscSFSetGraphLayout(sf,map,nleaves,ilocal,PETSC_USE_POINTER,iremote);CHKERRQ(ierr); 1317f6d38dbbSStefano Zampini ierr = PetscLayoutDestroy(&map);CHKERRQ(ierr); 1318f6d38dbbSStefano Zampini ierr = PetscSFBcastBegin(sf,MPIU_INT,ix2,ix + m);CHKERRQ(ierr); 1319f6d38dbbSStefano Zampini ierr = PetscSFBcastEnd(sf,MPIU_INT,ix2,ix + m);CHKERRQ(ierr); 1320f6d38dbbSStefano Zampini ierr = PetscSFDestroy(&sf);CHKERRQ(ierr); 1321aea6d515SStefano Zampini ierr = PetscFree2(ilocal,iremote);CHKERRQ(ierr); 1322aea6d515SStefano Zampini } else { 1323aea6d515SStefano Zampini ierr = ISGetLocalSize(isglobal[i],&mi);CHKERRQ(ierr); 1324aea6d515SStefano Zampini for (j=0; j<mi; j++) ix[m+j] = ix2[i]; 1325aea6d515SStefano Zampini } 1326aea6d515SStefano Zampini ierr = ISRestoreIndices(isglobal[i],&ix2);CHKERRQ(ierr); 132777019fcaSJed Brown m += mi; 132877019fcaSJed Brown } 1329f0413b6fSBarry Smith ierr = ISLocalToGlobalMappingCreate(PetscObjectComm((PetscObject)A),1,m,ix,PETSC_OWN_POINTER,ltog);CHKERRQ(ierr); 133077019fcaSJed Brown PetscFunctionReturn(0); 133177019fcaSJed Brown } 133277019fcaSJed Brown 133377019fcaSJed Brown 1334d8588912SDave May /* If an IS was provided, there is nothing Nest needs to do, otherwise Nest will build a strided IS */ 1335d8588912SDave May /* 1336d8588912SDave May nprocessors = NP 1337d8588912SDave May Nest x^T = ((g_0,g_1,...g_nprocs-1), (h_0,h_1,...h_NP-1)) 1338d8588912SDave May proc 0: => (g_0,h_0,) 1339d8588912SDave May proc 1: => (g_1,h_1,) 1340d8588912SDave May ... 1341d8588912SDave May proc nprocs-1: => (g_NP-1,h_NP-1,) 1342d8588912SDave May 1343d8588912SDave May proc 0: proc 1: proc nprocs-1: 1344d8588912SDave May is[0] = (0,1,2,...,nlocal(g_0)-1) (0,1,...,nlocal(g_1)-1) (0,1,...,nlocal(g_NP-1)) 1345d8588912SDave May 1346d8588912SDave May proc 0: 1347d8588912SDave May is[1] = (nlocal(g_0),nlocal(g_0)+1,...,nlocal(g_0)+nlocal(h_0)-1) 1348d8588912SDave May proc 1: 1349d8588912SDave May is[1] = (nlocal(g_1),nlocal(g_1)+1,...,nlocal(g_1)+nlocal(h_1)-1) 1350d8588912SDave May 1351d8588912SDave May proc NP-1: 1352d8588912SDave May is[1] = (nlocal(g_NP-1),nlocal(g_NP-1)+1,...,nlocal(g_NP-1)+nlocal(h_NP-1)-1) 1353d8588912SDave May */ 1354841e96a3SJed Brown static PetscErrorCode MatSetUp_NestIS_Private(Mat A,PetscInt nr,const IS is_row[],PetscInt nc,const IS is_col[]) 1355d8588912SDave May { 1356e2d7f03fSJed Brown Mat_Nest *vs = (Mat_Nest*)A->data; 13578188e55aSJed Brown PetscInt i,j,offset,n,nsum,bs; 1358d8588912SDave May PetscErrorCode ierr; 13590298fd71SBarry Smith Mat sub = NULL; 1360d8588912SDave May 1361d8588912SDave May PetscFunctionBegin; 1362854ce69bSBarry Smith ierr = PetscMalloc1(nr,&vs->isglobal.row);CHKERRQ(ierr); 1363854ce69bSBarry Smith ierr = PetscMalloc1(nc,&vs->isglobal.col);CHKERRQ(ierr); 1364d8588912SDave May if (is_row) { /* valid IS is passed in */ 1365d8588912SDave May /* refs on is[] are incremeneted */ 1366e2d7f03fSJed Brown for (i=0; i<vs->nr; i++) { 1367d8588912SDave May ierr = PetscObjectReference((PetscObject)is_row[i]);CHKERRQ(ierr); 136826fbe8dcSKarl Rupp 1369e2d7f03fSJed Brown vs->isglobal.row[i] = is_row[i]; 1370d8588912SDave May } 13712ae74bdbSJed Brown } else { /* Create the ISs by inspecting sizes of a submatrix in each row */ 13728188e55aSJed Brown nsum = 0; 13738188e55aSJed Brown for (i=0; i<vs->nr; i++) { /* Add up the local sizes to compute the aggregate offset */ 13748188e55aSJed Brown ierr = MatNestFindNonzeroSubMatRow(A,i,&sub);CHKERRQ(ierr); 1375ce94432eSBarry Smith if (!sub) SETERRQ1(PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_WRONG,"No nonzero submatrix in row %D",i); 13760298fd71SBarry Smith ierr = MatGetLocalSize(sub,&n,NULL);CHKERRQ(ierr); 1377ce94432eSBarry Smith if (n < 0) SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_WRONGSTATE,"Sizes have not yet been set for submatrix"); 13788188e55aSJed Brown nsum += n; 13798188e55aSJed Brown } 1380ce94432eSBarry Smith ierr = MPI_Scan(&nsum,&offset,1,MPIU_INT,MPI_SUM,PetscObjectComm((PetscObject)A));CHKERRQ(ierr); 138130bc264bSJed Brown offset -= nsum; 1382e2d7f03fSJed Brown for (i=0; i<vs->nr; i++) { 1383f349c1fdSJed Brown ierr = MatNestFindNonzeroSubMatRow(A,i,&sub);CHKERRQ(ierr); 13840298fd71SBarry Smith ierr = MatGetLocalSize(sub,&n,NULL);CHKERRQ(ierr); 13852ae74bdbSJed Brown ierr = MatGetBlockSize(sub,&bs);CHKERRQ(ierr); 1386ce94432eSBarry Smith ierr = ISCreateStride(PetscObjectComm((PetscObject)sub),n,offset,1,&vs->isglobal.row[i]);CHKERRQ(ierr); 1387e2d7f03fSJed Brown ierr = ISSetBlockSize(vs->isglobal.row[i],bs);CHKERRQ(ierr); 13882ae74bdbSJed Brown offset += n; 1389d8588912SDave May } 1390d8588912SDave May } 1391d8588912SDave May 1392d8588912SDave May if (is_col) { /* valid IS is passed in */ 1393d8588912SDave May /* refs on is[] are incremeneted */ 1394e2d7f03fSJed Brown for (j=0; j<vs->nc; j++) { 1395d8588912SDave May ierr = PetscObjectReference((PetscObject)is_col[j]);CHKERRQ(ierr); 139626fbe8dcSKarl Rupp 1397e2d7f03fSJed Brown vs->isglobal.col[j] = is_col[j]; 1398d8588912SDave May } 13992ae74bdbSJed Brown } else { /* Create the ISs by inspecting sizes of a submatrix in each column */ 14002ae74bdbSJed Brown offset = A->cmap->rstart; 14018188e55aSJed Brown nsum = 0; 14028188e55aSJed Brown for (j=0; j<vs->nc; j++) { 14038188e55aSJed Brown ierr = MatNestFindNonzeroSubMatCol(A,j,&sub);CHKERRQ(ierr); 1404ce94432eSBarry Smith if (!sub) SETERRQ1(PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_WRONG,"No nonzero submatrix in column %D",i); 14050298fd71SBarry Smith ierr = MatGetLocalSize(sub,NULL,&n);CHKERRQ(ierr); 1406ce94432eSBarry Smith if (n < 0) SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_WRONGSTATE,"Sizes have not yet been set for submatrix"); 14078188e55aSJed Brown nsum += n; 14088188e55aSJed Brown } 1409ce94432eSBarry Smith ierr = MPI_Scan(&nsum,&offset,1,MPIU_INT,MPI_SUM,PetscObjectComm((PetscObject)A));CHKERRQ(ierr); 141030bc264bSJed Brown offset -= nsum; 1411e2d7f03fSJed Brown for (j=0; j<vs->nc; j++) { 1412f349c1fdSJed Brown ierr = MatNestFindNonzeroSubMatCol(A,j,&sub);CHKERRQ(ierr); 14130298fd71SBarry Smith ierr = MatGetLocalSize(sub,NULL,&n);CHKERRQ(ierr); 14142ae74bdbSJed Brown ierr = MatGetBlockSize(sub,&bs);CHKERRQ(ierr); 1415ce94432eSBarry Smith ierr = ISCreateStride(PetscObjectComm((PetscObject)sub),n,offset,1,&vs->isglobal.col[j]);CHKERRQ(ierr); 1416e2d7f03fSJed Brown ierr = ISSetBlockSize(vs->isglobal.col[j],bs);CHKERRQ(ierr); 14172ae74bdbSJed Brown offset += n; 1418d8588912SDave May } 1419d8588912SDave May } 1420e2d7f03fSJed Brown 1421e2d7f03fSJed Brown /* Set up the local ISs */ 1422785e854fSJed Brown ierr = PetscMalloc1(vs->nr,&vs->islocal.row);CHKERRQ(ierr); 1423785e854fSJed Brown ierr = PetscMalloc1(vs->nc,&vs->islocal.col);CHKERRQ(ierr); 1424e2d7f03fSJed Brown for (i=0,offset=0; i<vs->nr; i++) { 1425e2d7f03fSJed Brown IS isloc; 14260298fd71SBarry Smith ISLocalToGlobalMapping rmap = NULL; 1427e2d7f03fSJed Brown PetscInt nlocal,bs; 1428e2d7f03fSJed Brown ierr = MatNestFindNonzeroSubMatRow(A,i,&sub);CHKERRQ(ierr); 14290298fd71SBarry Smith if (sub) {ierr = MatGetLocalToGlobalMapping(sub,&rmap,NULL);CHKERRQ(ierr);} 1430207556f9SJed Brown if (rmap) { 1431e2d7f03fSJed Brown ierr = MatGetBlockSize(sub,&bs);CHKERRQ(ierr); 1432e2d7f03fSJed Brown ierr = ISLocalToGlobalMappingGetSize(rmap,&nlocal);CHKERRQ(ierr); 1433e2d7f03fSJed Brown ierr = ISCreateStride(PETSC_COMM_SELF,nlocal,offset,1,&isloc);CHKERRQ(ierr); 1434e2d7f03fSJed Brown ierr = ISSetBlockSize(isloc,bs);CHKERRQ(ierr); 1435207556f9SJed Brown } else { 1436207556f9SJed Brown nlocal = 0; 14370298fd71SBarry Smith isloc = NULL; 1438207556f9SJed Brown } 1439e2d7f03fSJed Brown vs->islocal.row[i] = isloc; 1440e2d7f03fSJed Brown offset += nlocal; 1441e2d7f03fSJed Brown } 14428188e55aSJed Brown for (i=0,offset=0; i<vs->nc; i++) { 1443e2d7f03fSJed Brown IS isloc; 14440298fd71SBarry Smith ISLocalToGlobalMapping cmap = NULL; 1445e2d7f03fSJed Brown PetscInt nlocal,bs; 1446e2d7f03fSJed Brown ierr = MatNestFindNonzeroSubMatCol(A,i,&sub);CHKERRQ(ierr); 14470298fd71SBarry Smith if (sub) {ierr = MatGetLocalToGlobalMapping(sub,NULL,&cmap);CHKERRQ(ierr);} 1448207556f9SJed Brown if (cmap) { 1449e2d7f03fSJed Brown ierr = MatGetBlockSize(sub,&bs);CHKERRQ(ierr); 1450e2d7f03fSJed Brown ierr = ISLocalToGlobalMappingGetSize(cmap,&nlocal);CHKERRQ(ierr); 1451e2d7f03fSJed Brown ierr = ISCreateStride(PETSC_COMM_SELF,nlocal,offset,1,&isloc);CHKERRQ(ierr); 1452e2d7f03fSJed Brown ierr = ISSetBlockSize(isloc,bs);CHKERRQ(ierr); 1453207556f9SJed Brown } else { 1454207556f9SJed Brown nlocal = 0; 14550298fd71SBarry Smith isloc = NULL; 1456207556f9SJed Brown } 1457e2d7f03fSJed Brown vs->islocal.col[i] = isloc; 1458e2d7f03fSJed Brown offset += nlocal; 1459e2d7f03fSJed Brown } 14600189643fSJed Brown 146177019fcaSJed Brown /* Set up the aggregate ISLocalToGlobalMapping */ 146277019fcaSJed Brown { 146345b6f7e9SBarry Smith ISLocalToGlobalMapping rmap,cmap; 146445b6f7e9SBarry Smith ierr = MatNestCreateAggregateL2G_Private(A,vs->nr,vs->islocal.row,vs->isglobal.row,PETSC_FALSE,&rmap);CHKERRQ(ierr); 146545b6f7e9SBarry Smith ierr = MatNestCreateAggregateL2G_Private(A,vs->nc,vs->islocal.col,vs->isglobal.col,PETSC_TRUE,&cmap);CHKERRQ(ierr); 146677019fcaSJed Brown if (rmap && cmap) {ierr = MatSetLocalToGlobalMapping(A,rmap,cmap);CHKERRQ(ierr);} 146777019fcaSJed Brown ierr = ISLocalToGlobalMappingDestroy(&rmap);CHKERRQ(ierr); 146877019fcaSJed Brown ierr = ISLocalToGlobalMappingDestroy(&cmap);CHKERRQ(ierr); 146977019fcaSJed Brown } 147077019fcaSJed Brown 14710189643fSJed Brown #if defined(PETSC_USE_DEBUG) 14720189643fSJed Brown for (i=0; i<vs->nr; i++) { 14730189643fSJed Brown for (j=0; j<vs->nc; j++) { 14740189643fSJed Brown PetscInt m,n,M,N,mi,ni,Mi,Ni; 14750189643fSJed Brown Mat B = vs->m[i][j]; 14760189643fSJed Brown if (!B) continue; 14770189643fSJed Brown ierr = MatGetSize(B,&M,&N);CHKERRQ(ierr); 14780189643fSJed Brown ierr = MatGetLocalSize(B,&m,&n);CHKERRQ(ierr); 14790189643fSJed Brown ierr = ISGetSize(vs->isglobal.row[i],&Mi);CHKERRQ(ierr); 14800189643fSJed Brown ierr = ISGetSize(vs->isglobal.col[j],&Ni);CHKERRQ(ierr); 14810189643fSJed Brown ierr = ISGetLocalSize(vs->isglobal.row[i],&mi);CHKERRQ(ierr); 14820189643fSJed Brown ierr = ISGetLocalSize(vs->isglobal.col[j],&ni);CHKERRQ(ierr); 1483ce94432eSBarry 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); 1484ce94432eSBarry 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); 14850189643fSJed Brown } 14860189643fSJed Brown } 14870189643fSJed Brown #endif 1488a061e289SJed Brown 1489a061e289SJed Brown /* Set A->assembled if all non-null blocks are currently assembled */ 1490a061e289SJed Brown for (i=0; i<vs->nr; i++) { 1491a061e289SJed Brown for (j=0; j<vs->nc; j++) { 1492a061e289SJed Brown if (vs->m[i][j] && !vs->m[i][j]->assembled) PetscFunctionReturn(0); 1493a061e289SJed Brown } 1494a061e289SJed Brown } 1495a061e289SJed Brown A->assembled = PETSC_TRUE; 1496d8588912SDave May PetscFunctionReturn(0); 1497d8588912SDave May } 1498d8588912SDave May 149945c38901SJed Brown /*@C 1500659c6bb0SJed Brown MatCreateNest - Creates a new matrix containing several nested submatrices, each stored separately 1501659c6bb0SJed Brown 1502659c6bb0SJed Brown Collective on Mat 1503659c6bb0SJed Brown 1504659c6bb0SJed Brown Input Parameter: 1505659c6bb0SJed Brown + comm - Communicator for the new Mat 1506659c6bb0SJed Brown . nr - number of nested row blocks 15070298fd71SBarry Smith . is_row - index sets for each nested row block, or NULL to make contiguous 1508659c6bb0SJed Brown . nc - number of nested column blocks 15090298fd71SBarry Smith . is_col - index sets for each nested column block, or NULL to make contiguous 15100298fd71SBarry Smith - a - row-aligned array of nr*nc submatrices, empty submatrices can be passed using NULL 1511659c6bb0SJed Brown 1512659c6bb0SJed Brown Output Parameter: 1513659c6bb0SJed Brown . B - new matrix 1514659c6bb0SJed Brown 1515659c6bb0SJed Brown Level: advanced 1516659c6bb0SJed Brown 1517950540a4SJed Brown .seealso: MatCreate(), VecCreateNest(), DMCreateMatrix(), MATNEST 1518659c6bb0SJed Brown @*/ 15197087cfbeSBarry Smith PetscErrorCode MatCreateNest(MPI_Comm comm,PetscInt nr,const IS is_row[],PetscInt nc,const IS is_col[],const Mat a[],Mat *B) 1520d8588912SDave May { 1521d8588912SDave May Mat A; 1522d8588912SDave May PetscErrorCode ierr; 1523d8588912SDave May 1524d8588912SDave May PetscFunctionBegin; 1525c8883902SJed Brown *B = 0; 1526d8588912SDave May ierr = MatCreate(comm,&A);CHKERRQ(ierr); 1527c8883902SJed Brown ierr = MatSetType(A,MATNEST);CHKERRQ(ierr); 152891a28eb3SBarry Smith A->preallocated = PETSC_TRUE; 1529c8883902SJed Brown ierr = MatNestSetSubMats(A,nr,is_row,nc,is_col,a);CHKERRQ(ierr); 1530d8588912SDave May *B = A; 1531d8588912SDave May PetscFunctionReturn(0); 1532d8588912SDave May } 1533659c6bb0SJed Brown 1534b68353e5Sstefano_zampini static PetscErrorCode MatConvert_Nest_SeqAIJ_fast(Mat A,MatType newtype,MatReuse reuse,Mat *newmat) 1535b68353e5Sstefano_zampini { 1536b68353e5Sstefano_zampini Mat_Nest *nest = (Mat_Nest*)A->data; 153723875855Sstefano_zampini Mat *trans; 1538b68353e5Sstefano_zampini PetscScalar **avv; 1539b68353e5Sstefano_zampini PetscScalar *vv; 1540b68353e5Sstefano_zampini PetscInt **aii,**ajj; 1541b68353e5Sstefano_zampini PetscInt *ii,*jj,*ci; 1542b68353e5Sstefano_zampini PetscInt nr,nc,nnz,i,j; 1543b68353e5Sstefano_zampini PetscBool done; 1544b68353e5Sstefano_zampini PetscErrorCode ierr; 1545b68353e5Sstefano_zampini 1546b68353e5Sstefano_zampini PetscFunctionBegin; 1547b68353e5Sstefano_zampini ierr = MatGetSize(A,&nr,&nc);CHKERRQ(ierr); 1548b68353e5Sstefano_zampini if (reuse == MAT_REUSE_MATRIX) { 1549b68353e5Sstefano_zampini PetscInt rnr; 1550b68353e5Sstefano_zampini 1551b68353e5Sstefano_zampini ierr = MatGetRowIJ(*newmat,0,PETSC_FALSE,PETSC_FALSE,&rnr,(const PetscInt**)&ii,(const PetscInt**)&jj,&done);CHKERRQ(ierr); 1552b68353e5Sstefano_zampini if (!done) SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_PLIB,"MatGetRowIJ"); 1553b68353e5Sstefano_zampini if (rnr != nr) SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_USER,"Cannot reuse matrix, wrong number of rows"); 1554b68353e5Sstefano_zampini ierr = MatSeqAIJGetArray(*newmat,&vv);CHKERRQ(ierr); 1555b68353e5Sstefano_zampini } 1556b68353e5Sstefano_zampini /* extract CSR for nested SeqAIJ matrices */ 1557b68353e5Sstefano_zampini nnz = 0; 155823875855Sstefano_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); 1559b68353e5Sstefano_zampini for (i=0; i<nest->nr; ++i) { 1560b68353e5Sstefano_zampini for (j=0; j<nest->nc; ++j) { 1561b68353e5Sstefano_zampini Mat B = nest->m[i][j]; 1562b68353e5Sstefano_zampini if (B) { 1563b68353e5Sstefano_zampini PetscScalar *naa; 1564b68353e5Sstefano_zampini PetscInt *nii,*njj,nnr; 156523875855Sstefano_zampini PetscBool istrans; 1566b68353e5Sstefano_zampini 156723875855Sstefano_zampini ierr = PetscObjectTypeCompare((PetscObject)B,MATTRANSPOSEMAT,&istrans);CHKERRQ(ierr); 156823875855Sstefano_zampini if (istrans) { 156923875855Sstefano_zampini Mat Bt; 157023875855Sstefano_zampini 157123875855Sstefano_zampini ierr = MatTransposeGetMat(B,&Bt);CHKERRQ(ierr); 157223875855Sstefano_zampini ierr = MatTranspose(Bt,MAT_INITIAL_MATRIX,&trans[i*nest->nc+j]);CHKERRQ(ierr); 157323875855Sstefano_zampini B = trans[i*nest->nc+j]; 157423875855Sstefano_zampini } 1575b68353e5Sstefano_zampini ierr = MatGetRowIJ(B,0,PETSC_FALSE,PETSC_FALSE,&nnr,(const PetscInt**)&nii,(const PetscInt**)&njj,&done);CHKERRQ(ierr); 1576b68353e5Sstefano_zampini if (!done) SETERRQ(PetscObjectComm((PetscObject)B),PETSC_ERR_PLIB,"MatGetRowIJ"); 1577b68353e5Sstefano_zampini ierr = MatSeqAIJGetArray(B,&naa);CHKERRQ(ierr); 1578b68353e5Sstefano_zampini nnz += nii[nnr]; 1579b68353e5Sstefano_zampini 1580b68353e5Sstefano_zampini aii[i*nest->nc+j] = nii; 1581b68353e5Sstefano_zampini ajj[i*nest->nc+j] = njj; 1582b68353e5Sstefano_zampini avv[i*nest->nc+j] = naa; 1583b68353e5Sstefano_zampini } 1584b68353e5Sstefano_zampini } 1585b68353e5Sstefano_zampini } 1586b68353e5Sstefano_zampini if (reuse != MAT_REUSE_MATRIX) { 1587b68353e5Sstefano_zampini ierr = PetscMalloc1(nr+1,&ii);CHKERRQ(ierr); 1588b68353e5Sstefano_zampini ierr = PetscMalloc1(nnz,&jj);CHKERRQ(ierr); 1589b68353e5Sstefano_zampini ierr = PetscMalloc1(nnz,&vv);CHKERRQ(ierr); 1590b68353e5Sstefano_zampini } else { 1591b68353e5Sstefano_zampini if (nnz != ii[nr]) SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_USER,"Cannot reuse matrix, wrong number of nonzeros"); 1592b68353e5Sstefano_zampini } 1593b68353e5Sstefano_zampini 1594b68353e5Sstefano_zampini /* new row pointer */ 1595580bdb30SBarry Smith ierr = PetscArrayzero(ii,nr+1);CHKERRQ(ierr); 1596b68353e5Sstefano_zampini for (i=0; i<nest->nr; ++i) { 1597b68353e5Sstefano_zampini PetscInt ncr,rst; 1598b68353e5Sstefano_zampini 1599b68353e5Sstefano_zampini ierr = ISStrideGetInfo(nest->isglobal.row[i],&rst,NULL);CHKERRQ(ierr); 1600b68353e5Sstefano_zampini ierr = ISGetLocalSize(nest->isglobal.row[i],&ncr);CHKERRQ(ierr); 1601b68353e5Sstefano_zampini for (j=0; j<nest->nc; ++j) { 1602b68353e5Sstefano_zampini if (aii[i*nest->nc+j]) { 1603b68353e5Sstefano_zampini PetscInt *nii = aii[i*nest->nc+j]; 1604b68353e5Sstefano_zampini PetscInt ir; 1605b68353e5Sstefano_zampini 1606b68353e5Sstefano_zampini for (ir=rst; ir<ncr+rst; ++ir) { 1607b68353e5Sstefano_zampini ii[ir+1] += nii[1]-nii[0]; 1608b68353e5Sstefano_zampini nii++; 1609b68353e5Sstefano_zampini } 1610b68353e5Sstefano_zampini } 1611b68353e5Sstefano_zampini } 1612b68353e5Sstefano_zampini } 1613b68353e5Sstefano_zampini for (i=0; i<nr; i++) ii[i+1] += ii[i]; 1614b68353e5Sstefano_zampini 1615b68353e5Sstefano_zampini /* construct CSR for the new matrix */ 1616b68353e5Sstefano_zampini ierr = PetscCalloc1(nr,&ci);CHKERRQ(ierr); 1617b68353e5Sstefano_zampini for (i=0; i<nest->nr; ++i) { 1618b68353e5Sstefano_zampini PetscInt ncr,rst; 1619b68353e5Sstefano_zampini 1620b68353e5Sstefano_zampini ierr = ISStrideGetInfo(nest->isglobal.row[i],&rst,NULL);CHKERRQ(ierr); 1621b68353e5Sstefano_zampini ierr = ISGetLocalSize(nest->isglobal.row[i],&ncr);CHKERRQ(ierr); 1622b68353e5Sstefano_zampini for (j=0; j<nest->nc; ++j) { 1623b68353e5Sstefano_zampini if (aii[i*nest->nc+j]) { 1624b68353e5Sstefano_zampini PetscScalar *nvv = avv[i*nest->nc+j]; 1625b68353e5Sstefano_zampini PetscInt *nii = aii[i*nest->nc+j]; 1626b68353e5Sstefano_zampini PetscInt *njj = ajj[i*nest->nc+j]; 1627b68353e5Sstefano_zampini PetscInt ir,cst; 1628b68353e5Sstefano_zampini 1629b68353e5Sstefano_zampini ierr = ISStrideGetInfo(nest->isglobal.col[j],&cst,NULL);CHKERRQ(ierr); 1630b68353e5Sstefano_zampini for (ir=rst; ir<ncr+rst; ++ir) { 1631b68353e5Sstefano_zampini PetscInt ij,rsize = nii[1]-nii[0],ist = ii[ir]+ci[ir]; 1632b68353e5Sstefano_zampini 1633b68353e5Sstefano_zampini for (ij=0;ij<rsize;ij++) { 1634b68353e5Sstefano_zampini jj[ist+ij] = *njj+cst; 1635b68353e5Sstefano_zampini vv[ist+ij] = *nvv; 1636b68353e5Sstefano_zampini njj++; 1637b68353e5Sstefano_zampini nvv++; 1638b68353e5Sstefano_zampini } 1639b68353e5Sstefano_zampini ci[ir] += rsize; 1640b68353e5Sstefano_zampini nii++; 1641b68353e5Sstefano_zampini } 1642b68353e5Sstefano_zampini } 1643b68353e5Sstefano_zampini } 1644b68353e5Sstefano_zampini } 1645b68353e5Sstefano_zampini ierr = PetscFree(ci);CHKERRQ(ierr); 1646b68353e5Sstefano_zampini 1647b68353e5Sstefano_zampini /* restore info */ 1648b68353e5Sstefano_zampini for (i=0; i<nest->nr; ++i) { 1649b68353e5Sstefano_zampini for (j=0; j<nest->nc; ++j) { 1650b68353e5Sstefano_zampini Mat B = nest->m[i][j]; 1651b68353e5Sstefano_zampini if (B) { 1652b68353e5Sstefano_zampini PetscInt nnr = 0, k = i*nest->nc+j; 165323875855Sstefano_zampini 165423875855Sstefano_zampini B = (trans[k] ? trans[k] : B); 1655b68353e5Sstefano_zampini ierr = MatRestoreRowIJ(B,0,PETSC_FALSE,PETSC_FALSE,&nnr,(const PetscInt**)&aii[k],(const PetscInt**)&ajj[k],&done);CHKERRQ(ierr); 1656b68353e5Sstefano_zampini if (!done) SETERRQ(PetscObjectComm((PetscObject)B),PETSC_ERR_PLIB,"MatRestoreRowIJ"); 1657b68353e5Sstefano_zampini ierr = MatSeqAIJRestoreArray(B,&avv[k]);CHKERRQ(ierr); 165823875855Sstefano_zampini ierr = MatDestroy(&trans[k]);CHKERRQ(ierr); 1659b68353e5Sstefano_zampini } 1660b68353e5Sstefano_zampini } 1661b68353e5Sstefano_zampini } 166223875855Sstefano_zampini ierr = PetscFree4(aii,ajj,avv,trans);CHKERRQ(ierr); 1663b68353e5Sstefano_zampini 1664b68353e5Sstefano_zampini /* finalize newmat */ 1665b68353e5Sstefano_zampini if (reuse == MAT_INITIAL_MATRIX) { 1666b68353e5Sstefano_zampini ierr = MatCreateSeqAIJWithArrays(PetscObjectComm((PetscObject)A),nr,nc,ii,jj,vv,newmat);CHKERRQ(ierr); 1667b68353e5Sstefano_zampini } else if (reuse == MAT_INPLACE_MATRIX) { 1668b68353e5Sstefano_zampini Mat B; 1669b68353e5Sstefano_zampini 1670b68353e5Sstefano_zampini ierr = MatCreateSeqAIJWithArrays(PetscObjectComm((PetscObject)A),nr,nc,ii,jj,vv,&B);CHKERRQ(ierr); 1671b68353e5Sstefano_zampini ierr = MatHeaderReplace(A,&B);CHKERRQ(ierr); 1672b68353e5Sstefano_zampini } 1673b68353e5Sstefano_zampini ierr = MatAssemblyBegin(*newmat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 1674b68353e5Sstefano_zampini ierr = MatAssemblyEnd(*newmat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 1675b68353e5Sstefano_zampini { 1676b68353e5Sstefano_zampini Mat_SeqAIJ *a = (Mat_SeqAIJ*)((*newmat)->data); 1677b68353e5Sstefano_zampini a->free_a = PETSC_TRUE; 1678b68353e5Sstefano_zampini a->free_ij = PETSC_TRUE; 1679b68353e5Sstefano_zampini } 1680b68353e5Sstefano_zampini PetscFunctionReturn(0); 1681b68353e5Sstefano_zampini } 1682b68353e5Sstefano_zampini 1683cc2e6a90SBarry Smith PETSC_INTERN PetscErrorCode MatConvert_Nest_AIJ(Mat A,MatType newtype,MatReuse reuse,Mat *newmat) 1684629c3df2SDmitry Karpeev { 1685629c3df2SDmitry Karpeev PetscErrorCode ierr; 1686629c3df2SDmitry Karpeev Mat_Nest *nest = (Mat_Nest*)A->data; 168783b1a929SMark Adams PetscInt m,n,M,N,i,j,k,*dnnz,*onnz,rstart; 1688649b366bSFande Kong PetscInt cstart,cend; 1689b68353e5Sstefano_zampini PetscMPIInt size; 1690629c3df2SDmitry Karpeev Mat C; 1691629c3df2SDmitry Karpeev 1692629c3df2SDmitry Karpeev PetscFunctionBegin; 1693b68353e5Sstefano_zampini ierr = MPI_Comm_size(PetscObjectComm((PetscObject)A),&size);CHKERRQ(ierr); 1694b68353e5Sstefano_zampini if (size == 1) { /* look for a special case with SeqAIJ matrices and strided-1, contiguous, blocks */ 1695b68353e5Sstefano_zampini PetscInt nf; 1696b68353e5Sstefano_zampini PetscBool fast; 1697b68353e5Sstefano_zampini 1698b68353e5Sstefano_zampini ierr = PetscStrcmp(newtype,MATAIJ,&fast);CHKERRQ(ierr); 1699b68353e5Sstefano_zampini if (!fast) { 1700b68353e5Sstefano_zampini ierr = PetscStrcmp(newtype,MATSEQAIJ,&fast);CHKERRQ(ierr); 1701b68353e5Sstefano_zampini } 1702b68353e5Sstefano_zampini for (i=0; i<nest->nr && fast; ++i) { 1703b68353e5Sstefano_zampini for (j=0; j<nest->nc && fast; ++j) { 1704b68353e5Sstefano_zampini Mat B = nest->m[i][j]; 1705b68353e5Sstefano_zampini if (B) { 1706b68353e5Sstefano_zampini ierr = PetscObjectTypeCompare((PetscObject)B,MATSEQAIJ,&fast);CHKERRQ(ierr); 170723875855Sstefano_zampini if (!fast) { 170823875855Sstefano_zampini PetscBool istrans; 170923875855Sstefano_zampini 171023875855Sstefano_zampini ierr = PetscObjectTypeCompare((PetscObject)B,MATTRANSPOSEMAT,&istrans);CHKERRQ(ierr); 171123875855Sstefano_zampini if (istrans) { 171223875855Sstefano_zampini Mat Bt; 171323875855Sstefano_zampini 171423875855Sstefano_zampini ierr = MatTransposeGetMat(B,&Bt);CHKERRQ(ierr); 171523875855Sstefano_zampini ierr = PetscObjectTypeCompare((PetscObject)Bt,MATSEQAIJ,&fast);CHKERRQ(ierr); 171623875855Sstefano_zampini } 1717b68353e5Sstefano_zampini } 1718b68353e5Sstefano_zampini } 1719b68353e5Sstefano_zampini } 1720b68353e5Sstefano_zampini } 1721b68353e5Sstefano_zampini for (i=0, nf=0; i<nest->nr && fast; ++i) { 1722b68353e5Sstefano_zampini ierr = PetscObjectTypeCompare((PetscObject)nest->isglobal.row[i],ISSTRIDE,&fast);CHKERRQ(ierr); 1723b68353e5Sstefano_zampini if (fast) { 1724b68353e5Sstefano_zampini PetscInt f,s; 1725b68353e5Sstefano_zampini 1726b68353e5Sstefano_zampini ierr = ISStrideGetInfo(nest->isglobal.row[i],&f,&s);CHKERRQ(ierr); 1727b68353e5Sstefano_zampini if (f != nf || s != 1) { fast = PETSC_FALSE; } 1728b68353e5Sstefano_zampini else { 1729b68353e5Sstefano_zampini ierr = ISGetSize(nest->isglobal.row[i],&f);CHKERRQ(ierr); 1730b68353e5Sstefano_zampini nf += f; 1731b68353e5Sstefano_zampini } 1732b68353e5Sstefano_zampini } 1733b68353e5Sstefano_zampini } 1734b68353e5Sstefano_zampini for (i=0, nf=0; i<nest->nc && fast; ++i) { 1735b68353e5Sstefano_zampini ierr = PetscObjectTypeCompare((PetscObject)nest->isglobal.col[i],ISSTRIDE,&fast);CHKERRQ(ierr); 1736b68353e5Sstefano_zampini if (fast) { 1737b68353e5Sstefano_zampini PetscInt f,s; 1738b68353e5Sstefano_zampini 1739b68353e5Sstefano_zampini ierr = ISStrideGetInfo(nest->isglobal.col[i],&f,&s);CHKERRQ(ierr); 1740b68353e5Sstefano_zampini if (f != nf || s != 1) { fast = PETSC_FALSE; } 1741b68353e5Sstefano_zampini else { 1742b68353e5Sstefano_zampini ierr = ISGetSize(nest->isglobal.col[i],&f);CHKERRQ(ierr); 1743b68353e5Sstefano_zampini nf += f; 1744b68353e5Sstefano_zampini } 1745b68353e5Sstefano_zampini } 1746b68353e5Sstefano_zampini } 1747b68353e5Sstefano_zampini if (fast) { 1748b68353e5Sstefano_zampini ierr = MatConvert_Nest_SeqAIJ_fast(A,newtype,reuse,newmat);CHKERRQ(ierr); 1749b68353e5Sstefano_zampini PetscFunctionReturn(0); 1750b68353e5Sstefano_zampini } 1751b68353e5Sstefano_zampini } 1752629c3df2SDmitry Karpeev ierr = MatGetSize(A,&M,&N);CHKERRQ(ierr); 1753629c3df2SDmitry Karpeev ierr = MatGetLocalSize(A,&m,&n);CHKERRQ(ierr); 1754649b366bSFande Kong ierr = MatGetOwnershipRangeColumn(A,&cstart,&cend);CHKERRQ(ierr); 1755629c3df2SDmitry Karpeev switch (reuse) { 1756629c3df2SDmitry Karpeev case MAT_INITIAL_MATRIX: 1757ce94432eSBarry Smith ierr = MatCreate(PetscObjectComm((PetscObject)A),&C);CHKERRQ(ierr); 1758629c3df2SDmitry Karpeev ierr = MatSetType(C,newtype);CHKERRQ(ierr); 1759629c3df2SDmitry Karpeev ierr = MatSetSizes(C,m,n,M,N);CHKERRQ(ierr); 1760629c3df2SDmitry Karpeev *newmat = C; 1761629c3df2SDmitry Karpeev break; 1762629c3df2SDmitry Karpeev case MAT_REUSE_MATRIX: 1763629c3df2SDmitry Karpeev C = *newmat; 1764629c3df2SDmitry Karpeev break; 1765ce94432eSBarry Smith default: SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_SUP,"MatReuse"); 1766629c3df2SDmitry Karpeev } 1767785e854fSJed Brown ierr = PetscMalloc1(2*m,&dnnz);CHKERRQ(ierr); 1768629c3df2SDmitry Karpeev onnz = dnnz + m; 1769629c3df2SDmitry Karpeev for (k=0; k<m; k++) { 1770629c3df2SDmitry Karpeev dnnz[k] = 0; 1771629c3df2SDmitry Karpeev onnz[k] = 0; 1772629c3df2SDmitry Karpeev } 1773629c3df2SDmitry Karpeev for (j=0; j<nest->nc; ++j) { 1774629c3df2SDmitry Karpeev IS bNis; 1775629c3df2SDmitry Karpeev PetscInt bN; 1776629c3df2SDmitry Karpeev const PetscInt *bNindices; 1777629c3df2SDmitry Karpeev /* Using global column indices and ISAllGather() is not scalable. */ 1778629c3df2SDmitry Karpeev ierr = ISAllGather(nest->isglobal.col[j], &bNis);CHKERRQ(ierr); 1779629c3df2SDmitry Karpeev ierr = ISGetSize(bNis, &bN);CHKERRQ(ierr); 1780629c3df2SDmitry Karpeev ierr = ISGetIndices(bNis,&bNindices);CHKERRQ(ierr); 1781629c3df2SDmitry Karpeev for (i=0; i<nest->nr; ++i) { 1782629c3df2SDmitry Karpeev PetscSF bmsf; 1783649b366bSFande Kong PetscSFNode *iremote; 1784629c3df2SDmitry Karpeev Mat B; 1785649b366bSFande Kong PetscInt bm, *sub_dnnz,*sub_onnz, br; 1786629c3df2SDmitry Karpeev const PetscInt *bmindices; 1787629c3df2SDmitry Karpeev B = nest->m[i][j]; 1788629c3df2SDmitry Karpeev if (!B) continue; 1789629c3df2SDmitry Karpeev ierr = ISGetLocalSize(nest->isglobal.row[i],&bm);CHKERRQ(ierr); 1790629c3df2SDmitry Karpeev ierr = ISGetIndices(nest->isglobal.row[i],&bmindices);CHKERRQ(ierr); 1791ce94432eSBarry Smith ierr = PetscSFCreate(PetscObjectComm((PetscObject)A), &bmsf);CHKERRQ(ierr); 1792649b366bSFande Kong ierr = PetscMalloc1(bm,&iremote);CHKERRQ(ierr); 1793649b366bSFande Kong ierr = PetscMalloc1(bm,&sub_dnnz);CHKERRQ(ierr); 1794649b366bSFande Kong ierr = PetscMalloc1(bm,&sub_onnz);CHKERRQ(ierr); 1795649b366bSFande Kong for (k = 0; k < bm; ++k){ 1796649b366bSFande Kong sub_dnnz[k] = 0; 1797649b366bSFande Kong sub_onnz[k] = 0; 1798649b366bSFande Kong } 1799629c3df2SDmitry Karpeev /* 1800629c3df2SDmitry Karpeev Locate the owners for all of the locally-owned global row indices for this row block. 1801629c3df2SDmitry Karpeev These determine the roots of PetscSF used to communicate preallocation data to row owners. 1802629c3df2SDmitry Karpeev The roots correspond to the dnnz and onnz entries; thus, there are two roots per row. 1803629c3df2SDmitry Karpeev */ 180483b1a929SMark Adams ierr = MatGetOwnershipRange(B,&rstart,NULL);CHKERRQ(ierr); 1805629c3df2SDmitry Karpeev for (br = 0; br < bm; ++br) { 1806649b366bSFande Kong PetscInt row = bmindices[br], rowowner = 0, brncols, col; 1807629c3df2SDmitry Karpeev const PetscInt *brcols; 1808a4b3d3acSMatthew G Knepley PetscInt rowrel = 0; /* row's relative index on its owner rank */ 1809629c3df2SDmitry Karpeev ierr = PetscLayoutFindOwnerIndex(A->rmap,row,&rowowner,&rowrel);CHKERRQ(ierr); 1810649b366bSFande Kong /* how many roots */ 1811649b366bSFande Kong iremote[br].rank = rowowner; iremote[br].index = rowrel; /* edge from bmdnnz to dnnz */ 1812649b366bSFande Kong /* get nonzero pattern */ 181383b1a929SMark Adams ierr = MatGetRow(B,br+rstart,&brncols,&brcols,NULL);CHKERRQ(ierr); 1814629c3df2SDmitry Karpeev for (k=0; k<brncols; k++) { 1815629c3df2SDmitry Karpeev col = bNindices[brcols[k]]; 1816649b366bSFande Kong if (col>=A->cmap->range[rowowner] && col<A->cmap->range[rowowner+1]) { 1817649b366bSFande Kong sub_dnnz[br]++; 1818649b366bSFande Kong } else { 1819649b366bSFande Kong sub_onnz[br]++; 1820649b366bSFande Kong } 1821629c3df2SDmitry Karpeev } 182283b1a929SMark Adams ierr = MatRestoreRow(B,br+rstart,&brncols,&brcols,NULL);CHKERRQ(ierr); 1823629c3df2SDmitry Karpeev } 1824629c3df2SDmitry Karpeev ierr = ISRestoreIndices(nest->isglobal.row[i],&bmindices);CHKERRQ(ierr); 1825629c3df2SDmitry Karpeev /* bsf will have to take care of disposing of bedges. */ 1826649b366bSFande Kong ierr = PetscSFSetGraph(bmsf,m,bm,NULL,PETSC_OWN_POINTER,iremote,PETSC_OWN_POINTER);CHKERRQ(ierr); 1827649b366bSFande Kong ierr = PetscSFReduceBegin(bmsf,MPIU_INT,sub_dnnz,dnnz,MPI_SUM);CHKERRQ(ierr); 1828649b366bSFande Kong ierr = PetscSFReduceEnd(bmsf,MPIU_INT,sub_dnnz,dnnz,MPI_SUM);CHKERRQ(ierr); 1829649b366bSFande Kong ierr = PetscSFReduceBegin(bmsf,MPIU_INT,sub_onnz,onnz,MPI_SUM);CHKERRQ(ierr); 1830649b366bSFande Kong ierr = PetscSFReduceEnd(bmsf,MPIU_INT,sub_onnz,onnz,MPI_SUM);CHKERRQ(ierr); 1831649b366bSFande Kong ierr = PetscFree(sub_dnnz);CHKERRQ(ierr); 1832649b366bSFande Kong ierr = PetscFree(sub_onnz);CHKERRQ(ierr); 1833629c3df2SDmitry Karpeev ierr = PetscSFDestroy(&bmsf);CHKERRQ(ierr); 1834629c3df2SDmitry Karpeev } 183522d28d08SBarry Smith ierr = ISRestoreIndices(bNis,&bNindices);CHKERRQ(ierr); 1836629c3df2SDmitry Karpeev ierr = ISDestroy(&bNis);CHKERRQ(ierr); 183765a4a0a3Sstefano_zampini } 183865a4a0a3Sstefano_zampini /* Resize preallocation if overestimated */ 183965a4a0a3Sstefano_zampini for (i=0;i<m;i++) { 184065a4a0a3Sstefano_zampini dnnz[i] = PetscMin(dnnz[i],A->cmap->n); 184165a4a0a3Sstefano_zampini onnz[i] = PetscMin(onnz[i],A->cmap->N - A->cmap->n); 1842629c3df2SDmitry Karpeev } 1843629c3df2SDmitry Karpeev ierr = MatSeqAIJSetPreallocation(C,0,dnnz);CHKERRQ(ierr); 1844629c3df2SDmitry Karpeev ierr = MatMPIAIJSetPreallocation(C,0,dnnz,0,onnz);CHKERRQ(ierr); 1845629c3df2SDmitry Karpeev ierr = PetscFree(dnnz);CHKERRQ(ierr); 1846629c3df2SDmitry Karpeev 1847629c3df2SDmitry Karpeev /* Fill by row */ 1848629c3df2SDmitry Karpeev for (j=0; j<nest->nc; ++j) { 1849629c3df2SDmitry Karpeev /* Using global column indices and ISAllGather() is not scalable. */ 1850629c3df2SDmitry Karpeev IS bNis; 1851629c3df2SDmitry Karpeev PetscInt bN; 1852629c3df2SDmitry Karpeev const PetscInt *bNindices; 1853629c3df2SDmitry Karpeev ierr = ISAllGather(nest->isglobal.col[j], &bNis);CHKERRQ(ierr); 1854629c3df2SDmitry Karpeev ierr = ISGetSize(bNis,&bN);CHKERRQ(ierr); 1855629c3df2SDmitry Karpeev ierr = ISGetIndices(bNis,&bNindices);CHKERRQ(ierr); 1856629c3df2SDmitry Karpeev for (i=0; i<nest->nr; ++i) { 1857629c3df2SDmitry Karpeev Mat B; 1858629c3df2SDmitry Karpeev PetscInt bm, br; 1859629c3df2SDmitry Karpeev const PetscInt *bmindices; 1860629c3df2SDmitry Karpeev B = nest->m[i][j]; 1861629c3df2SDmitry Karpeev if (!B) continue; 1862629c3df2SDmitry Karpeev ierr = ISGetLocalSize(nest->isglobal.row[i],&bm);CHKERRQ(ierr); 1863629c3df2SDmitry Karpeev ierr = ISGetIndices(nest->isglobal.row[i],&bmindices);CHKERRQ(ierr); 186483b1a929SMark Adams ierr = MatGetOwnershipRange(B,&rstart,NULL);CHKERRQ(ierr); 1865629c3df2SDmitry Karpeev for (br = 0; br < bm; ++br) { 1866629c3df2SDmitry Karpeev PetscInt row = bmindices[br], brncols, *cols; 1867629c3df2SDmitry Karpeev const PetscInt *brcols; 1868629c3df2SDmitry Karpeev const PetscScalar *brcoldata; 186983b1a929SMark Adams ierr = MatGetRow(B,br+rstart,&brncols,&brcols,&brcoldata);CHKERRQ(ierr); 1870785e854fSJed Brown ierr = PetscMalloc1(brncols,&cols);CHKERRQ(ierr); 187126fbe8dcSKarl Rupp for (k=0; k<brncols; k++) cols[k] = bNindices[brcols[k]]; 1872629c3df2SDmitry Karpeev /* 1873629c3df2SDmitry Karpeev Nest blocks are required to be nonoverlapping -- otherwise nest and monolithic index layouts wouldn't match. 1874629c3df2SDmitry Karpeev Thus, we could use INSERT_VALUES, but I prefer ADD_VALUES. 1875629c3df2SDmitry Karpeev */ 1876a2ea699eSBarry Smith ierr = MatSetValues(C,1,&row,brncols,cols,brcoldata,ADD_VALUES);CHKERRQ(ierr); 187783b1a929SMark Adams ierr = MatRestoreRow(B,br+rstart,&brncols,&brcols,&brcoldata);CHKERRQ(ierr); 1878629c3df2SDmitry Karpeev ierr = PetscFree(cols);CHKERRQ(ierr); 1879629c3df2SDmitry Karpeev } 1880629c3df2SDmitry Karpeev ierr = ISRestoreIndices(nest->isglobal.row[i],&bmindices);CHKERRQ(ierr); 1881629c3df2SDmitry Karpeev } 1882a2ea699eSBarry Smith ierr = ISRestoreIndices(bNis,&bNindices);CHKERRQ(ierr); 1883629c3df2SDmitry Karpeev ierr = ISDestroy(&bNis);CHKERRQ(ierr); 1884629c3df2SDmitry Karpeev } 1885629c3df2SDmitry Karpeev ierr = MatAssemblyBegin(C,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 1886629c3df2SDmitry Karpeev ierr = MatAssemblyEnd(C,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 1887629c3df2SDmitry Karpeev PetscFunctionReturn(0); 1888629c3df2SDmitry Karpeev } 1889629c3df2SDmitry Karpeev 18908b7d3b4bSBarry Smith PetscErrorCode MatHasOperation_Nest(Mat mat,MatOperation op,PetscBool *has) 18918b7d3b4bSBarry Smith { 18928b7d3b4bSBarry Smith PetscFunctionBegin; 18938b7d3b4bSBarry Smith *has = PETSC_FALSE; 18948b7d3b4bSBarry Smith if (op == MATOP_MULT_TRANSPOSE) { 18958b7d3b4bSBarry Smith Mat_Nest *bA = (Mat_Nest*)mat->data; 18968b7d3b4bSBarry Smith PetscInt i,j,nr = bA->nr,nc = bA->nc; 18978b7d3b4bSBarry Smith PetscErrorCode ierr; 18988b7d3b4bSBarry Smith PetscBool flg; 18998b7d3b4bSBarry Smith 19008b7d3b4bSBarry Smith for (j=0; j<nc; j++) { 19018b7d3b4bSBarry Smith for (i=0; i<nr; i++) { 19028b7d3b4bSBarry Smith if (!bA->m[i][j]) continue; 19038b7d3b4bSBarry Smith ierr = MatHasOperation(bA->m[i][j],MATOP_MULT_TRANSPOSE_ADD,&flg);CHKERRQ(ierr); 19048b7d3b4bSBarry Smith if (!flg) PetscFunctionReturn(0); 19058b7d3b4bSBarry Smith } 19068b7d3b4bSBarry Smith } 19078b7d3b4bSBarry Smith } 19088b7d3b4bSBarry Smith if (((void**)mat->ops)[op]) *has = PETSC_TRUE; 19098b7d3b4bSBarry Smith PetscFunctionReturn(0); 19108b7d3b4bSBarry Smith } 19118b7d3b4bSBarry Smith 1912659c6bb0SJed Brown /*MC 1913659c6bb0SJed Brown MATNEST - MATNEST = "nest" - Matrix type consisting of nested submatrices, each stored separately. 1914659c6bb0SJed Brown 1915659c6bb0SJed Brown Level: intermediate 1916659c6bb0SJed Brown 1917659c6bb0SJed Brown Notes: 1918659c6bb0SJed Brown This matrix type permits scalable use of PCFieldSplit and avoids the large memory costs of extracting submatrices. 1919659c6bb0SJed Brown It allows the use of symmetric and block formats for parts of multi-physics simulations. 1920950540a4SJed Brown It is usually used with DMComposite and DMCreateMatrix() 1921659c6bb0SJed Brown 19228b7d3b4bSBarry Smith Each of the submatrices lives on the same MPI communicator as the original nest matrix (though they can have zero 19238b7d3b4bSBarry Smith rows/columns on some processes.) Thus this is not meant for cases where the submatrices live on far fewer processes 19248b7d3b4bSBarry Smith than the nest matrix. 19258b7d3b4bSBarry Smith 1926659c6bb0SJed Brown .seealso: MatCreate(), MatType, MatCreateNest() 1927659c6bb0SJed Brown M*/ 19288cc058d9SJed Brown PETSC_EXTERN PetscErrorCode MatCreate_Nest(Mat A) 1929c8883902SJed Brown { 1930c8883902SJed Brown Mat_Nest *s; 1931c8883902SJed Brown PetscErrorCode ierr; 1932c8883902SJed Brown 1933c8883902SJed Brown PetscFunctionBegin; 1934b00a9115SJed Brown ierr = PetscNewLog(A,&s);CHKERRQ(ierr); 1935c8883902SJed Brown A->data = (void*)s; 1936e7c19651SJed Brown 1937e7c19651SJed Brown s->nr = -1; 1938e7c19651SJed Brown s->nc = -1; 19390298fd71SBarry Smith s->m = NULL; 1940e7c19651SJed Brown s->splitassembly = PETSC_FALSE; 1941c8883902SJed Brown 1942c8883902SJed Brown ierr = PetscMemzero(A->ops,sizeof(*A->ops));CHKERRQ(ierr); 194326fbe8dcSKarl Rupp 1944c8883902SJed Brown A->ops->mult = MatMult_Nest; 19459194d70fSJed Brown A->ops->multadd = MatMultAdd_Nest; 1946c8883902SJed Brown A->ops->multtranspose = MatMultTranspose_Nest; 19479194d70fSJed Brown A->ops->multtransposeadd = MatMultTransposeAdd_Nest; 1948f8170845SAlex Fikl A->ops->transpose = MatTranspose_Nest; 1949c8883902SJed Brown A->ops->assemblybegin = MatAssemblyBegin_Nest; 1950c8883902SJed Brown A->ops->assemblyend = MatAssemblyEnd_Nest; 1951c8883902SJed Brown A->ops->zeroentries = MatZeroEntries_Nest; 1952c222c20dSDavid Ham A->ops->copy = MatCopy_Nest; 19536e76ffeaSPierre Jolivet A->ops->axpy = MatAXPY_Nest; 1954c8883902SJed Brown A->ops->duplicate = MatDuplicate_Nest; 19557dae84e0SHong Zhang A->ops->createsubmatrix = MatCreateSubMatrix_Nest; 1956c8883902SJed Brown A->ops->destroy = MatDestroy_Nest; 1957c8883902SJed Brown A->ops->view = MatView_Nest; 1958c8883902SJed Brown A->ops->getvecs = 0; /* Use VECNEST by calling MatNestSetVecType(A,VECNEST) */ 1959c8883902SJed Brown A->ops->getlocalsubmatrix = MatGetLocalSubMatrix_Nest; 1960c8883902SJed Brown A->ops->restorelocalsubmatrix = MatRestoreLocalSubMatrix_Nest; 1961429bac76SJed Brown A->ops->getdiagonal = MatGetDiagonal_Nest; 1962429bac76SJed Brown A->ops->diagonalscale = MatDiagonalScale_Nest; 1963a061e289SJed Brown A->ops->scale = MatScale_Nest; 1964a061e289SJed Brown A->ops->shift = MatShift_Nest; 196513135bc6SAlex Fikl A->ops->diagonalset = MatDiagonalSet_Nest; 1966f8170845SAlex Fikl A->ops->setrandom = MatSetRandom_Nest; 19678b7d3b4bSBarry Smith A->ops->hasoperation = MatHasOperation_Nest; 1968c8883902SJed Brown 1969c8883902SJed Brown A->spptr = 0; 1970c8883902SJed Brown A->assembled = PETSC_FALSE; 1971c8883902SJed Brown 1972c8883902SJed Brown /* expose Nest api's */ 1973bdf89e91SBarry Smith ierr = PetscObjectComposeFunction((PetscObject)A,"MatNestGetSubMat_C", MatNestGetSubMat_Nest);CHKERRQ(ierr); 1974bdf89e91SBarry Smith ierr = PetscObjectComposeFunction((PetscObject)A,"MatNestSetSubMat_C", MatNestSetSubMat_Nest);CHKERRQ(ierr); 1975bdf89e91SBarry Smith ierr = PetscObjectComposeFunction((PetscObject)A,"MatNestGetSubMats_C", MatNestGetSubMats_Nest);CHKERRQ(ierr); 1976bdf89e91SBarry Smith ierr = PetscObjectComposeFunction((PetscObject)A,"MatNestGetSize_C", MatNestGetSize_Nest);CHKERRQ(ierr); 1977bdf89e91SBarry Smith ierr = PetscObjectComposeFunction((PetscObject)A,"MatNestGetISs_C", MatNestGetISs_Nest);CHKERRQ(ierr); 1978bdf89e91SBarry Smith ierr = PetscObjectComposeFunction((PetscObject)A,"MatNestGetLocalISs_C", MatNestGetLocalISs_Nest);CHKERRQ(ierr); 1979bdf89e91SBarry Smith ierr = PetscObjectComposeFunction((PetscObject)A,"MatNestSetVecType_C", MatNestSetVecType_Nest);CHKERRQ(ierr); 1980bdf89e91SBarry Smith ierr = PetscObjectComposeFunction((PetscObject)A,"MatNestSetSubMats_C", MatNestSetSubMats_Nest);CHKERRQ(ierr); 19810899c546SStefano Zampini ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_nest_mpiaij_C",MatConvert_Nest_AIJ);CHKERRQ(ierr); 19820899c546SStefano Zampini ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_nest_seqaij_C",MatConvert_Nest_AIJ);CHKERRQ(ierr); 198383b1a929SMark Adams ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_nest_aij_C", MatConvert_Nest_AIJ);CHKERRQ(ierr); 19845e3038f0Sstefano_zampini ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_nest_is_C", MatConvert_Nest_IS);CHKERRQ(ierr); 1985c8883902SJed Brown 1986c8883902SJed Brown ierr = PetscObjectChangeTypeName((PetscObject)A,MATNEST);CHKERRQ(ierr); 1987c8883902SJed Brown PetscFunctionReturn(0); 1988c8883902SJed Brown } 1989