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[]); 72a7a6963SBarry Smith static PetscErrorCode MatCreateVecs_Nest(Mat A,Vec *right,Vec *left); 85e3038f0Sstefano_zampini PETSC_INTERN PetscErrorCode MatConvert_Nest_IS(Mat,MatType,MatReuse,Mat*); 9c8883902SJed Brown 10d8588912SDave May /* private functions */ 118188e55aSJed Brown static PetscErrorCode MatNestGetSizes_Private(Mat A,PetscInt *m,PetscInt *n,PetscInt *M,PetscInt *N) 12d8588912SDave May { 13d8588912SDave May Mat_Nest *bA = (Mat_Nest*)A->data; 148188e55aSJed Brown PetscInt i,j; 15d8588912SDave May PetscErrorCode ierr; 16d8588912SDave May 17d8588912SDave May PetscFunctionBegin; 188188e55aSJed Brown *m = *n = *M = *N = 0; 198188e55aSJed Brown for (i=0; i<bA->nr; i++) { /* rows */ 208188e55aSJed Brown PetscInt sm,sM; 218188e55aSJed Brown ierr = ISGetLocalSize(bA->isglobal.row[i],&sm);CHKERRQ(ierr); 228188e55aSJed Brown ierr = ISGetSize(bA->isglobal.row[i],&sM);CHKERRQ(ierr); 238188e55aSJed Brown *m += sm; 248188e55aSJed Brown *M += sM; 25d8588912SDave May } 268188e55aSJed Brown for (j=0; j<bA->nc; j++) { /* cols */ 278188e55aSJed Brown PetscInt sn,sN; 288188e55aSJed Brown ierr = ISGetLocalSize(bA->isglobal.col[j],&sn);CHKERRQ(ierr); 298188e55aSJed Brown ierr = ISGetSize(bA->isglobal.col[j],&sN);CHKERRQ(ierr); 308188e55aSJed Brown *n += sn; 318188e55aSJed Brown *N += sN; 32d8588912SDave May } 33d8588912SDave May PetscFunctionReturn(0); 34d8588912SDave May } 35d8588912SDave May 36d8588912SDave May /* operations */ 37207556f9SJed Brown static PetscErrorCode MatMult_Nest(Mat A,Vec x,Vec y) 38d8588912SDave May { 39d8588912SDave May Mat_Nest *bA = (Mat_Nest*)A->data; 40207556f9SJed Brown Vec *bx = bA->right,*by = bA->left; 41207556f9SJed Brown PetscInt i,j,nr = bA->nr,nc = bA->nc; 42d8588912SDave May PetscErrorCode ierr; 43d8588912SDave May 44d8588912SDave May PetscFunctionBegin; 45207556f9SJed Brown for (i=0; i<nr; i++) {ierr = VecGetSubVector(y,bA->isglobal.row[i],&by[i]);CHKERRQ(ierr);} 46207556f9SJed Brown for (i=0; i<nc; i++) {ierr = VecGetSubVector(x,bA->isglobal.col[i],&bx[i]);CHKERRQ(ierr);} 47207556f9SJed Brown for (i=0; i<nr; i++) { 48d8588912SDave May ierr = VecZeroEntries(by[i]);CHKERRQ(ierr); 49207556f9SJed Brown for (j=0; j<nc; j++) { 50207556f9SJed Brown if (!bA->m[i][j]) continue; 51d8588912SDave May /* y[i] <- y[i] + A[i][j] * x[j] */ 52d8588912SDave May ierr = MatMultAdd(bA->m[i][j],bx[j],by[i],by[i]);CHKERRQ(ierr); 53d8588912SDave May } 54d8588912SDave May } 55207556f9SJed Brown for (i=0; i<nr; i++) {ierr = VecRestoreSubVector(y,bA->isglobal.row[i],&by[i]);CHKERRQ(ierr);} 56207556f9SJed Brown for (i=0; i<nc; i++) {ierr = VecRestoreSubVector(x,bA->isglobal.col[i],&bx[i]);CHKERRQ(ierr);} 57d8588912SDave May PetscFunctionReturn(0); 58d8588912SDave May } 59d8588912SDave May 609194d70fSJed Brown static PetscErrorCode MatMultAdd_Nest(Mat A,Vec x,Vec y,Vec z) 619194d70fSJed Brown { 629194d70fSJed Brown Mat_Nest *bA = (Mat_Nest*)A->data; 639194d70fSJed Brown Vec *bx = bA->right,*bz = bA->left; 649194d70fSJed Brown PetscInt i,j,nr = bA->nr,nc = bA->nc; 659194d70fSJed Brown PetscErrorCode ierr; 669194d70fSJed Brown 679194d70fSJed Brown PetscFunctionBegin; 689194d70fSJed Brown for (i=0; i<nr; i++) {ierr = VecGetSubVector(z,bA->isglobal.row[i],&bz[i]);CHKERRQ(ierr);} 699194d70fSJed Brown for (i=0; i<nc; i++) {ierr = VecGetSubVector(x,bA->isglobal.col[i],&bx[i]);CHKERRQ(ierr);} 709194d70fSJed Brown for (i=0; i<nr; i++) { 719194d70fSJed Brown if (y != z) { 729194d70fSJed Brown Vec by; 739194d70fSJed Brown ierr = VecGetSubVector(y,bA->isglobal.row[i],&by);CHKERRQ(ierr); 749194d70fSJed Brown ierr = VecCopy(by,bz[i]);CHKERRQ(ierr); 75336d21e7SJed Brown ierr = VecRestoreSubVector(y,bA->isglobal.row[i],&by);CHKERRQ(ierr); 769194d70fSJed Brown } 779194d70fSJed Brown for (j=0; j<nc; j++) { 789194d70fSJed Brown if (!bA->m[i][j]) continue; 799194d70fSJed Brown /* y[i] <- y[i] + A[i][j] * x[j] */ 809194d70fSJed Brown ierr = MatMultAdd(bA->m[i][j],bx[j],bz[i],bz[i]);CHKERRQ(ierr); 819194d70fSJed Brown } 829194d70fSJed Brown } 839194d70fSJed Brown for (i=0; i<nr; i++) {ierr = VecRestoreSubVector(z,bA->isglobal.row[i],&bz[i]);CHKERRQ(ierr);} 849194d70fSJed Brown for (i=0; i<nc; i++) {ierr = VecRestoreSubVector(x,bA->isglobal.col[i],&bx[i]);CHKERRQ(ierr);} 859194d70fSJed Brown PetscFunctionReturn(0); 869194d70fSJed Brown } 879194d70fSJed Brown 8852c5f739Sprj- typedef struct { 8952c5f739Sprj- Mat *workC; /* array of Mat with specific containers depending on the underlying MatMatMult implementation */ 9052c5f739Sprj- PetscScalar *tarray; /* buffer for storing all temporary products A[i][j] B[j] */ 9152c5f739Sprj- PetscInt *dm,*dn,k; /* displacements and number of submatrices */ 9252c5f739Sprj- } Nest_Dense; 9352c5f739Sprj- 9452c5f739Sprj- PETSC_INTERN PetscErrorCode MatMatMultNumeric_Nest_Dense(Mat A,Mat B,Mat C) 9552c5f739Sprj- { 9652c5f739Sprj- Mat_Nest *bA = (Mat_Nest*)A->data; 9752c5f739Sprj- PetscContainer container; 9852c5f739Sprj- Nest_Dense *contents; 9952c5f739Sprj- Mat viewB,viewC,seq; 10052c5f739Sprj- const PetscScalar *barray; 10152c5f739Sprj- PetscScalar *carray; 10252c5f739Sprj- PetscInt i,j,M,N,nr = bA->nr,nc = bA->nc,ldb,ldc; 10352c5f739Sprj- PetscErrorCode ierr; 10452c5f739Sprj- 10552c5f739Sprj- PetscFunctionBegin; 10652c5f739Sprj- ierr = PetscObjectQuery((PetscObject)C,"workC",(PetscObject*)&container);CHKERRQ(ierr); 10752c5f739Sprj- if (!container) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Container does not exist"); 10852c5f739Sprj- ierr = PetscContainerGetPointer(container,(void**)&contents);CHKERRQ(ierr); 10952c5f739Sprj- ierr = MatDenseGetLDA(B,&ldb);CHKERRQ(ierr); 11052c5f739Sprj- ierr = MatDenseGetLDA(C,&ldc);CHKERRQ(ierr); 11152c5f739Sprj- ierr = MatGetSize(B,NULL,&N);CHKERRQ(ierr); 11252c5f739Sprj- ierr = MatZeroEntries(C);CHKERRQ(ierr); 11352c5f739Sprj- ierr = MatDenseGetArrayRead(B,&barray);CHKERRQ(ierr); 11452c5f739Sprj- ierr = MatDenseGetArray(C,&carray);CHKERRQ(ierr); 11552c5f739Sprj- for (i=0; i<nr; i++) { 11652c5f739Sprj- ierr = ISGetSize(bA->isglobal.row[i],&M);CHKERRQ(ierr); 11752c5f739Sprj- ierr = MatCreateDense(PetscObjectComm((PetscObject)A),contents->dm[i+1]-contents->dm[i],PETSC_DECIDE,M,N,carray+contents->dm[i],&viewC);CHKERRQ(ierr); 11852c5f739Sprj- ierr = MatDenseGetLocalMatrix(viewC,&seq);CHKERRQ(ierr); 11952c5f739Sprj- ierr = MatSeqDenseSetLDA(seq,ldc);CHKERRQ(ierr); 12052c5f739Sprj- for (j=0; j<nc; j++) { 12152c5f739Sprj- if (!bA->m[i][j]) continue; 12252c5f739Sprj- ierr = ISGetSize(bA->isglobal.col[j],&M);CHKERRQ(ierr); 12352c5f739Sprj- ierr = MatCreateDense(PetscObjectComm((PetscObject)A),contents->dn[j+1]-contents->dn[j],PETSC_DECIDE,M,N,(PetscScalar*)(barray+contents->dn[j]),&viewB);CHKERRQ(ierr); 12452c5f739Sprj- ierr = MatDenseGetLocalMatrix(viewB,&seq);CHKERRQ(ierr); 12552c5f739Sprj- ierr = MatSeqDenseSetLDA(seq,ldb);CHKERRQ(ierr); 12652c5f739Sprj- /* workC <- A[i][j] * B[j] */ 12752c5f739Sprj- ierr = MatMatMultNumeric(bA->m[i][j],viewB,contents->workC[i*nc + j]);CHKERRQ(ierr); 12852c5f739Sprj- ierr = MatDestroy(&viewB);CHKERRQ(ierr); 12952c5f739Sprj- /* C[i] <- workC + C[i] */ 13052c5f739Sprj- ierr = MatAXPY(viewC,1.0,contents->workC[i*nc + j],SAME_NONZERO_PATTERN);CHKERRQ(ierr); 13152c5f739Sprj- } 13252c5f739Sprj- ierr = MatDestroy(&viewC);CHKERRQ(ierr); 13352c5f739Sprj- } 13452c5f739Sprj- ierr = MatDenseRestoreArray(C,&carray);CHKERRQ(ierr); 13552c5f739Sprj- ierr = MatDenseRestoreArrayRead(B,&barray);CHKERRQ(ierr); 13652c5f739Sprj- PetscFunctionReturn(0); 13752c5f739Sprj- } 13852c5f739Sprj- 13952c5f739Sprj- PetscErrorCode MatNest_DenseDestroy(void *ctx) 14052c5f739Sprj- { 14152c5f739Sprj- Nest_Dense *contents = (Nest_Dense*)ctx; 14252c5f739Sprj- PetscInt i; 14352c5f739Sprj- PetscErrorCode ierr; 14452c5f739Sprj- 14552c5f739Sprj- PetscFunctionBegin; 14652c5f739Sprj- ierr = PetscFree(contents->tarray);CHKERRQ(ierr); 14752c5f739Sprj- for (i=0; i<contents->k; i++) { 14852c5f739Sprj- ierr = MatDestroy(contents->workC + i);CHKERRQ(ierr); 14952c5f739Sprj- } 15052c5f739Sprj- ierr = PetscFree3(contents->dm,contents->dn,contents->workC);CHKERRQ(ierr); 15152c5f739Sprj- ierr = PetscFree(contents);CHKERRQ(ierr); 15252c5f739Sprj- PetscFunctionReturn(0); 15352c5f739Sprj- } 15452c5f739Sprj- 15552c5f739Sprj- PETSC_INTERN PetscErrorCode MatMatMultSymbolic_Nest_Dense(Mat A,Mat B,PetscReal fill,Mat *C) 15652c5f739Sprj- { 15752c5f739Sprj- Mat_Nest *bA = (Mat_Nest*)A->data; 15852c5f739Sprj- Mat viewB,viewSeq; 15952c5f739Sprj- const PetscScalar *barray; 16052c5f739Sprj- PetscInt i,j,M,N,m,nr = bA->nr,nc = bA->nc,maxm = 0,ldb; 16152c5f739Sprj- PetscContainer container; 16252c5f739Sprj- Nest_Dense *contents; 16352c5f739Sprj- PetscErrorCode ierr; 16452c5f739Sprj- 16552c5f739Sprj- PetscFunctionBegin; 16652c5f739Sprj- ierr = MatGetSize(B,NULL,&N);CHKERRQ(ierr); 16752c5f739Sprj- if (!(*C)) { 16852c5f739Sprj- ierr = MatGetLocalSize(A,&m,NULL);CHKERRQ(ierr); 16952c5f739Sprj- ierr = MatGetSize(A,&M,NULL);CHKERRQ(ierr); 17052c5f739Sprj- ierr = MatCreateDense(PetscObjectComm((PetscObject)A),m,PETSC_DECIDE,M,N,NULL,C);CHKERRQ(ierr); 17152c5f739Sprj- } else { 17252c5f739Sprj- if ((*C)->rmap->n != A->rmap->n) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Matrix local row dimensions are incompatible, %D != %D",(*C)->rmap->n,A->rmap->n); 17352c5f739Sprj- if ((*C)->cmap->n != B->cmap->n) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Matrix local column dimensions are incompatible, %D != %D",(*C)->cmap->n,B->cmap->n); 17452c5f739Sprj- } 17552c5f739Sprj- 17652c5f739Sprj- ierr = PetscNew(&contents);CHKERRQ(ierr); 17752c5f739Sprj- ierr = PetscContainerCreate(PetscObjectComm((PetscObject)A),&container);CHKERRQ(ierr); 17852c5f739Sprj- ierr = PetscContainerSetPointer(container,contents);CHKERRQ(ierr); 17952c5f739Sprj- ierr = PetscContainerSetUserDestroy(container,MatNest_DenseDestroy);CHKERRQ(ierr); 18052c5f739Sprj- ierr = PetscObjectCompose((PetscObject)*C,"workC",(PetscObject)container);CHKERRQ(ierr); 18152c5f739Sprj- ierr = PetscContainerDestroy(&container);CHKERRQ(ierr); 18252c5f739Sprj- ierr = PetscCalloc3(nr+1,&contents->dm,nc+1,&contents->dn,nr*nc,&contents->workC);CHKERRQ(ierr); 18352c5f739Sprj- contents->k = nr*nc; 18452c5f739Sprj- for (i=0; i<nr; i++) { 18552c5f739Sprj- ierr = ISGetLocalSize(bA->isglobal.row[i],contents->dm + i+1);CHKERRQ(ierr); 18652c5f739Sprj- maxm = PetscMax(maxm,contents->dm[i+1]); 18752c5f739Sprj- contents->dm[i+1] += contents->dm[i]; 18852c5f739Sprj- } 18952c5f739Sprj- for (i=0; i<nc; i++) { 19052c5f739Sprj- ierr = ISGetLocalSize(bA->isglobal.col[i],contents->dn + i+1);CHKERRQ(ierr); 19152c5f739Sprj- contents->dn[i+1] += contents->dn[i]; 19252c5f739Sprj- } 19352c5f739Sprj- ierr = PetscMalloc1(maxm*N,&contents->tarray);CHKERRQ(ierr); 19452c5f739Sprj- ierr = MatDenseGetLDA(B,&ldb);CHKERRQ(ierr); 19552c5f739Sprj- ierr = MatGetSize(B,NULL,&N);CHKERRQ(ierr); 19652c5f739Sprj- ierr = MatDenseGetArrayRead(B,&barray);CHKERRQ(ierr); 19752c5f739Sprj- /* loops are permuted compared to MatMatMultNumeric so that viewB is created only once per column of A */ 19852c5f739Sprj- for (j=0; j<nc; j++) { 19952c5f739Sprj- ierr = ISGetSize(bA->isglobal.col[j],&M);CHKERRQ(ierr); 20052c5f739Sprj- ierr = MatCreateDense(PetscObjectComm((PetscObject)A),contents->dn[j+1]-contents->dn[j],PETSC_DECIDE,M,N,(PetscScalar*)(barray+contents->dn[j]),&viewB);CHKERRQ(ierr); 20152c5f739Sprj- ierr = MatDenseGetLocalMatrix(viewB,&viewSeq);CHKERRQ(ierr); 20252c5f739Sprj- ierr = MatSeqDenseSetLDA(viewSeq,ldb);CHKERRQ(ierr); 20352c5f739Sprj- for (i=0; i<nr; i++) { 20452c5f739Sprj- if (!bA->m[i][j]) continue; 20552c5f739Sprj- /* MatMatMultSymbolic may attach a specific container (depending on MatType of bA->m[i][j]) to workC[i][j] */ 20652c5f739Sprj- ierr = MatMatMultSymbolic(bA->m[i][j],viewB,fill,contents->workC + i*nc + j);CHKERRQ(ierr); 20752c5f739Sprj- ierr = MatDenseGetLocalMatrix(contents->workC[i*nc + j],&viewSeq);CHKERRQ(ierr); 20852c5f739Sprj- /* free the memory allocated in MatMatMultSymbolic, since tarray will be shared by all Mat */ 20952c5f739Sprj- ierr = MatSeqDenseSetPreallocation(viewSeq,contents->tarray);CHKERRQ(ierr); 21052c5f739Sprj- } 21152c5f739Sprj- ierr = MatDestroy(&viewB);CHKERRQ(ierr); 21252c5f739Sprj- } 21352c5f739Sprj- ierr = MatDenseRestoreArrayRead(B,&barray);CHKERRQ(ierr); 21452c5f739Sprj- 21552c5f739Sprj- (*C)->ops->matmultnumeric = MatMatMultNumeric_Nest_Dense; 21652c5f739Sprj- PetscFunctionReturn(0); 21752c5f739Sprj- } 21852c5f739Sprj- 21952c5f739Sprj- PETSC_INTERN PetscErrorCode MatMatMult_Nest_Dense(Mat A,Mat B,MatReuse scall,PetscReal fill,Mat *C) 22052c5f739Sprj- { 22152c5f739Sprj- PetscErrorCode ierr; 22252c5f739Sprj- 22352c5f739Sprj- PetscFunctionBegin; 22452c5f739Sprj- if (scall == MAT_INITIAL_MATRIX) { 22552c5f739Sprj- *C = NULL; 22652c5f739Sprj- ierr = PetscLogEventBegin(MAT_MatMultSymbolic,A,B,0,0);CHKERRQ(ierr); 22752c5f739Sprj- ierr = MatMatMultSymbolic_Nest_Dense(A,B,fill,C);CHKERRQ(ierr); 22852c5f739Sprj- ierr = PetscLogEventEnd(MAT_MatMultSymbolic,A,B,0,0);CHKERRQ(ierr); 22952c5f739Sprj- } 23052c5f739Sprj- ierr = PetscLogEventBegin(MAT_MatMultNumeric,A,B,0,0);CHKERRQ(ierr); 23152c5f739Sprj- ierr = MatMatMultNumeric_Nest_Dense(A,B,*C);CHKERRQ(ierr); 23252c5f739Sprj- ierr = PetscLogEventEnd(MAT_MatMultNumeric,A,B,0,0);CHKERRQ(ierr); 23352c5f739Sprj- PetscFunctionReturn(0); 23452c5f739Sprj- } 23552c5f739Sprj- 236207556f9SJed Brown static PetscErrorCode MatMultTranspose_Nest(Mat A,Vec x,Vec y) 237d8588912SDave May { 238d8588912SDave May Mat_Nest *bA = (Mat_Nest*)A->data; 239207556f9SJed Brown Vec *bx = bA->left,*by = bA->right; 240207556f9SJed Brown PetscInt i,j,nr = bA->nr,nc = bA->nc; 241d8588912SDave May PetscErrorCode ierr; 242d8588912SDave May 243d8588912SDave May PetscFunctionBegin; 244609e31cbSJed Brown for (i=0; i<nr; i++) {ierr = VecGetSubVector(x,bA->isglobal.row[i],&bx[i]);CHKERRQ(ierr);} 245609e31cbSJed Brown for (i=0; i<nc; i++) {ierr = VecGetSubVector(y,bA->isglobal.col[i],&by[i]);CHKERRQ(ierr);} 246207556f9SJed Brown for (j=0; j<nc; j++) { 247609e31cbSJed Brown ierr = VecZeroEntries(by[j]);CHKERRQ(ierr); 248609e31cbSJed Brown for (i=0; i<nr; i++) { 2496c75ac25SJed Brown if (!bA->m[i][j]) continue; 250609e31cbSJed Brown /* y[j] <- y[j] + (A[i][j])^T * x[i] */ 251609e31cbSJed Brown ierr = MatMultTransposeAdd(bA->m[i][j],bx[i],by[j],by[j]);CHKERRQ(ierr); 252d8588912SDave May } 253d8588912SDave May } 254609e31cbSJed Brown for (i=0; i<nr; i++) {ierr = VecRestoreSubVector(x,bA->isglobal.row[i],&bx[i]);CHKERRQ(ierr);} 255609e31cbSJed Brown for (i=0; i<nc; i++) {ierr = VecRestoreSubVector(y,bA->isglobal.col[i],&by[i]);CHKERRQ(ierr);} 256d8588912SDave May PetscFunctionReturn(0); 257d8588912SDave May } 258d8588912SDave May 2599194d70fSJed Brown static PetscErrorCode MatMultTransposeAdd_Nest(Mat A,Vec x,Vec y,Vec z) 2609194d70fSJed Brown { 2619194d70fSJed Brown Mat_Nest *bA = (Mat_Nest*)A->data; 2629194d70fSJed Brown Vec *bx = bA->left,*bz = bA->right; 2639194d70fSJed Brown PetscInt i,j,nr = bA->nr,nc = bA->nc; 2649194d70fSJed Brown PetscErrorCode ierr; 2659194d70fSJed Brown 2669194d70fSJed Brown PetscFunctionBegin; 2679194d70fSJed Brown for (i=0; i<nr; i++) {ierr = VecGetSubVector(x,bA->isglobal.row[i],&bx[i]);CHKERRQ(ierr);} 2689194d70fSJed Brown for (i=0; i<nc; i++) {ierr = VecGetSubVector(z,bA->isglobal.col[i],&bz[i]);CHKERRQ(ierr);} 2699194d70fSJed Brown for (j=0; j<nc; j++) { 2709194d70fSJed Brown if (y != z) { 2719194d70fSJed Brown Vec by; 2729194d70fSJed Brown ierr = VecGetSubVector(y,bA->isglobal.col[j],&by);CHKERRQ(ierr); 2739194d70fSJed Brown ierr = VecCopy(by,bz[j]);CHKERRQ(ierr); 2749194d70fSJed Brown ierr = VecRestoreSubVector(y,bA->isglobal.col[j],&by);CHKERRQ(ierr); 2759194d70fSJed Brown } 2769194d70fSJed Brown for (i=0; i<nr; i++) { 2776c75ac25SJed Brown if (!bA->m[i][j]) continue; 2789194d70fSJed Brown /* z[j] <- y[j] + (A[i][j])^T * x[i] */ 2799194d70fSJed Brown ierr = MatMultTransposeAdd(bA->m[i][j],bx[i],bz[j],bz[j]);CHKERRQ(ierr); 2809194d70fSJed Brown } 2819194d70fSJed Brown } 2829194d70fSJed Brown for (i=0; i<nr; i++) {ierr = VecRestoreSubVector(x,bA->isglobal.row[i],&bx[i]);CHKERRQ(ierr);} 2839194d70fSJed Brown for (i=0; i<nc; i++) {ierr = VecRestoreSubVector(z,bA->isglobal.col[i],&bz[i]);CHKERRQ(ierr);} 2849194d70fSJed Brown PetscFunctionReturn(0); 2859194d70fSJed Brown } 2869194d70fSJed Brown 287f8170845SAlex Fikl static PetscErrorCode MatTranspose_Nest(Mat A,MatReuse reuse,Mat *B) 288f8170845SAlex Fikl { 289f8170845SAlex Fikl Mat_Nest *bA = (Mat_Nest*)A->data, *bC; 290f8170845SAlex Fikl Mat C; 291f8170845SAlex Fikl PetscInt i,j,nr = bA->nr,nc = bA->nc; 292f8170845SAlex Fikl PetscErrorCode ierr; 293f8170845SAlex Fikl 294f8170845SAlex Fikl PetscFunctionBegin; 295cf37664fSBarry Smith if (reuse == MAT_INPLACE_MATRIX && nr != nc) SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_SIZ,"Square nested matrix only for in-place"); 296f8170845SAlex Fikl 297cf37664fSBarry Smith if (reuse == MAT_INITIAL_MATRIX || reuse == MAT_INPLACE_MATRIX) { 298f8170845SAlex Fikl Mat *subs; 299f8170845SAlex Fikl IS *is_row,*is_col; 300f8170845SAlex Fikl 301f8170845SAlex Fikl ierr = PetscCalloc1(nr * nc,&subs);CHKERRQ(ierr); 302f8170845SAlex Fikl ierr = PetscMalloc2(nr,&is_row,nc,&is_col);CHKERRQ(ierr); 303f8170845SAlex Fikl ierr = MatNestGetISs(A,is_row,is_col);CHKERRQ(ierr); 304cf37664fSBarry Smith if (reuse == MAT_INPLACE_MATRIX) { 305ddeb9bd8SAlex Fikl for (i=0; i<nr; i++) { 306ddeb9bd8SAlex Fikl for (j=0; j<nc; j++) { 307ddeb9bd8SAlex Fikl subs[i + nr * j] = bA->m[i][j]; 308ddeb9bd8SAlex Fikl } 309ddeb9bd8SAlex Fikl } 310ddeb9bd8SAlex Fikl } 311ddeb9bd8SAlex Fikl 312f8170845SAlex Fikl ierr = MatCreateNest(PetscObjectComm((PetscObject)A),nc,is_col,nr,is_row,subs,&C);CHKERRQ(ierr); 313f8170845SAlex Fikl ierr = PetscFree(subs);CHKERRQ(ierr); 3143d994f23SBarry Smith ierr = PetscFree2(is_row,is_col);CHKERRQ(ierr); 315f8170845SAlex Fikl } else { 316f8170845SAlex Fikl C = *B; 317f8170845SAlex Fikl } 318f8170845SAlex Fikl 319f8170845SAlex Fikl bC = (Mat_Nest*)C->data; 320f8170845SAlex Fikl for (i=0; i<nr; i++) { 321f8170845SAlex Fikl for (j=0; j<nc; j++) { 322f8170845SAlex Fikl if (bA->m[i][j]) { 323f8170845SAlex Fikl ierr = MatTranspose(bA->m[i][j], reuse, &(bC->m[j][i]));CHKERRQ(ierr); 324f8170845SAlex Fikl } else { 325f8170845SAlex Fikl bC->m[j][i] = NULL; 326f8170845SAlex Fikl } 327f8170845SAlex Fikl } 328f8170845SAlex Fikl } 329f8170845SAlex Fikl 330cf37664fSBarry Smith if (reuse == MAT_INITIAL_MATRIX || reuse == MAT_REUSE_MATRIX) { 331f8170845SAlex Fikl *B = C; 332f8170845SAlex Fikl } else { 333f8170845SAlex Fikl ierr = MatHeaderMerge(A, &C);CHKERRQ(ierr); 334f8170845SAlex Fikl } 335f8170845SAlex Fikl PetscFunctionReturn(0); 336f8170845SAlex Fikl } 337f8170845SAlex Fikl 338e2d7f03fSJed Brown static PetscErrorCode MatNestDestroyISList(PetscInt n,IS **list) 339e2d7f03fSJed Brown { 340e2d7f03fSJed Brown PetscErrorCode ierr; 341e2d7f03fSJed Brown IS *lst = *list; 342e2d7f03fSJed Brown PetscInt i; 343e2d7f03fSJed Brown 344e2d7f03fSJed Brown PetscFunctionBegin; 345e2d7f03fSJed Brown if (!lst) PetscFunctionReturn(0); 3466bf464f9SBarry Smith for (i=0; i<n; i++) if (lst[i]) {ierr = ISDestroy(&lst[i]);CHKERRQ(ierr);} 347e2d7f03fSJed Brown ierr = PetscFree(lst);CHKERRQ(ierr); 3480298fd71SBarry Smith *list = NULL; 349e2d7f03fSJed Brown PetscFunctionReturn(0); 350e2d7f03fSJed Brown } 351e2d7f03fSJed Brown 352207556f9SJed Brown static PetscErrorCode MatDestroy_Nest(Mat A) 353d8588912SDave May { 354d8588912SDave May Mat_Nest *vs = (Mat_Nest*)A->data; 355d8588912SDave May PetscInt i,j; 356d8588912SDave May PetscErrorCode ierr; 357d8588912SDave May 358d8588912SDave May PetscFunctionBegin; 359d8588912SDave May /* release the matrices and the place holders */ 360e2d7f03fSJed Brown ierr = MatNestDestroyISList(vs->nr,&vs->isglobal.row);CHKERRQ(ierr); 361e2d7f03fSJed Brown ierr = MatNestDestroyISList(vs->nc,&vs->isglobal.col);CHKERRQ(ierr); 362e2d7f03fSJed Brown ierr = MatNestDestroyISList(vs->nr,&vs->islocal.row);CHKERRQ(ierr); 363e2d7f03fSJed Brown ierr = MatNestDestroyISList(vs->nc,&vs->islocal.col);CHKERRQ(ierr); 364d8588912SDave May 365d8588912SDave May ierr = PetscFree(vs->row_len);CHKERRQ(ierr); 366d8588912SDave May ierr = PetscFree(vs->col_len);CHKERRQ(ierr); 367d8588912SDave May 368207556f9SJed Brown ierr = PetscFree2(vs->left,vs->right);CHKERRQ(ierr); 369207556f9SJed Brown 370d8588912SDave May /* release the matrices and the place holders */ 371d8588912SDave May if (vs->m) { 372d8588912SDave May for (i=0; i<vs->nr; i++) { 373d8588912SDave May for (j=0; j<vs->nc; j++) { 3746bf464f9SBarry Smith ierr = MatDestroy(&vs->m[i][j]);CHKERRQ(ierr); 375d8588912SDave May } 376d8588912SDave May ierr = PetscFree(vs->m[i]);CHKERRQ(ierr); 377d8588912SDave May } 378d8588912SDave May ierr = PetscFree(vs->m);CHKERRQ(ierr); 379d8588912SDave May } 380bf0cc555SLisandro Dalcin ierr = PetscFree(A->data);CHKERRQ(ierr); 381d8588912SDave May 382bdf89e91SBarry Smith ierr = PetscObjectComposeFunction((PetscObject)A,"MatNestGetSubMat_C",0);CHKERRQ(ierr); 383bdf89e91SBarry Smith ierr = PetscObjectComposeFunction((PetscObject)A,"MatNestSetSubMat_C",0);CHKERRQ(ierr); 384bdf89e91SBarry Smith ierr = PetscObjectComposeFunction((PetscObject)A,"MatNestGetSubMats_C",0);CHKERRQ(ierr); 385bdf89e91SBarry Smith ierr = PetscObjectComposeFunction((PetscObject)A,"MatNestGetSize_C",0);CHKERRQ(ierr); 386bdf89e91SBarry Smith ierr = PetscObjectComposeFunction((PetscObject)A,"MatNestGetISs_C",0);CHKERRQ(ierr); 387bdf89e91SBarry Smith ierr = PetscObjectComposeFunction((PetscObject)A,"MatNestGetLocalISs_C",0);CHKERRQ(ierr); 388bdf89e91SBarry Smith ierr = PetscObjectComposeFunction((PetscObject)A,"MatNestSetVecType_C",0);CHKERRQ(ierr); 389bdf89e91SBarry Smith ierr = PetscObjectComposeFunction((PetscObject)A,"MatNestSetSubMats_C",0);CHKERRQ(ierr); 3900899c546SStefano Zampini ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_nest_mpiaij_C",0);CHKERRQ(ierr); 3910899c546SStefano Zampini ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_nest_seqaij_C",0);CHKERRQ(ierr); 3925e3038f0Sstefano_zampini ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_nest_aij_C",0);CHKERRQ(ierr); 3935e3038f0Sstefano_zampini ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_nest_is_C",0);CHKERRQ(ierr); 39452c5f739Sprj- ierr = PetscObjectComposeFunction((PetscObject)A,"MatMatMult_nest_mpidense_C",0);CHKERRQ(ierr); 39552c5f739Sprj- ierr = PetscObjectComposeFunction((PetscObject)A,"MatMatMult_nest_seqdense_C",0);CHKERRQ(ierr); 39652c5f739Sprj- ierr = PetscObjectComposeFunction((PetscObject)A,"MatMatMult_nest_dense_C",0);CHKERRQ(ierr); 397d8588912SDave May PetscFunctionReturn(0); 398d8588912SDave May } 399d8588912SDave May 400207556f9SJed Brown static PetscErrorCode MatAssemblyBegin_Nest(Mat A,MatAssemblyType type) 401d8588912SDave May { 402d8588912SDave May Mat_Nest *vs = (Mat_Nest*)A->data; 403d8588912SDave May PetscInt i,j; 404d8588912SDave May PetscErrorCode ierr; 405d8588912SDave May 406d8588912SDave May PetscFunctionBegin; 407d8588912SDave May for (i=0; i<vs->nr; i++) { 408d8588912SDave May for (j=0; j<vs->nc; j++) { 409e7c19651SJed Brown if (vs->m[i][j]) { 410e7c19651SJed Brown ierr = MatAssemblyBegin(vs->m[i][j],type);CHKERRQ(ierr); 411e7c19651SJed Brown if (!vs->splitassembly) { 412e7c19651SJed Brown /* Note: split assembly will fail if the same block appears more than once (even indirectly through a nested 413e7c19651SJed 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 414e7c19651SJed Brown * already performing an assembly, but the result would by more complicated and appears to offer less 415e7c19651SJed Brown * potential for diagnostics and correctness checking. Split assembly should be fixed once there is an 416e7c19651SJed Brown * interface for libraries to make asynchronous progress in "user-defined non-blocking collectives". 417e7c19651SJed Brown */ 418e7c19651SJed Brown ierr = MatAssemblyEnd(vs->m[i][j],type);CHKERRQ(ierr); 419e7c19651SJed Brown } 420e7c19651SJed Brown } 421d8588912SDave May } 422d8588912SDave May } 423d8588912SDave May PetscFunctionReturn(0); 424d8588912SDave May } 425d8588912SDave May 426207556f9SJed Brown static PetscErrorCode MatAssemblyEnd_Nest(Mat A, MatAssemblyType type) 427d8588912SDave May { 428d8588912SDave May Mat_Nest *vs = (Mat_Nest*)A->data; 429d8588912SDave May PetscInt i,j; 430d8588912SDave May PetscErrorCode ierr; 431d8588912SDave May 432d8588912SDave May PetscFunctionBegin; 433d8588912SDave May for (i=0; i<vs->nr; i++) { 434d8588912SDave May for (j=0; j<vs->nc; j++) { 435e7c19651SJed Brown if (vs->m[i][j]) { 436e7c19651SJed Brown if (vs->splitassembly) { 437e7c19651SJed Brown ierr = MatAssemblyEnd(vs->m[i][j],type);CHKERRQ(ierr); 438e7c19651SJed Brown } 439e7c19651SJed Brown } 440d8588912SDave May } 441d8588912SDave May } 442d8588912SDave May PetscFunctionReturn(0); 443d8588912SDave May } 444d8588912SDave May 445f349c1fdSJed Brown static PetscErrorCode MatNestFindNonzeroSubMatRow(Mat A,PetscInt row,Mat *B) 446d8588912SDave May { 447207556f9SJed Brown PetscErrorCode ierr; 448f349c1fdSJed Brown Mat_Nest *vs = (Mat_Nest*)A->data; 449f349c1fdSJed Brown PetscInt j; 450f349c1fdSJed Brown Mat sub; 451d8588912SDave May 452d8588912SDave May PetscFunctionBegin; 4530298fd71SBarry Smith sub = (row < vs->nc) ? vs->m[row][row] : (Mat)NULL; /* Prefer to find on the diagonal */ 454f349c1fdSJed Brown for (j=0; !sub && j<vs->nc; j++) sub = vs->m[row][j]; 4554994cf47SJed Brown if (sub) {ierr = MatSetUp(sub);CHKERRQ(ierr);} /* Ensure that the sizes are available */ 456f349c1fdSJed Brown *B = sub; 457f349c1fdSJed Brown PetscFunctionReturn(0); 458d8588912SDave May } 459d8588912SDave May 460f349c1fdSJed Brown static PetscErrorCode MatNestFindNonzeroSubMatCol(Mat A,PetscInt col,Mat *B) 461f349c1fdSJed Brown { 462207556f9SJed Brown PetscErrorCode ierr; 463f349c1fdSJed Brown Mat_Nest *vs = (Mat_Nest*)A->data; 464f349c1fdSJed Brown PetscInt i; 465f349c1fdSJed Brown Mat sub; 466f349c1fdSJed Brown 467f349c1fdSJed Brown PetscFunctionBegin; 4680298fd71SBarry Smith sub = (col < vs->nr) ? vs->m[col][col] : (Mat)NULL; /* Prefer to find on the diagonal */ 469f349c1fdSJed Brown for (i=0; !sub && i<vs->nr; i++) sub = vs->m[i][col]; 4704994cf47SJed Brown if (sub) {ierr = MatSetUp(sub);CHKERRQ(ierr);} /* Ensure that the sizes are available */ 471f349c1fdSJed Brown *B = sub; 472f349c1fdSJed Brown PetscFunctionReturn(0); 473d8588912SDave May } 474d8588912SDave May 475f349c1fdSJed Brown static PetscErrorCode MatNestFindIS(Mat A,PetscInt n,const IS list[],IS is,PetscInt *found) 476f349c1fdSJed Brown { 477f349c1fdSJed Brown PetscErrorCode ierr; 478f349c1fdSJed Brown PetscInt i; 479f349c1fdSJed Brown PetscBool flg; 480f349c1fdSJed Brown 481f349c1fdSJed Brown PetscFunctionBegin; 482f349c1fdSJed Brown PetscValidPointer(list,3); 483f349c1fdSJed Brown PetscValidHeaderSpecific(is,IS_CLASSID,4); 484f349c1fdSJed Brown PetscValidIntPointer(found,5); 485f349c1fdSJed Brown *found = -1; 486f349c1fdSJed Brown for (i=0; i<n; i++) { 487207556f9SJed Brown if (!list[i]) continue; 488f349c1fdSJed Brown ierr = ISEqual(list[i],is,&flg);CHKERRQ(ierr); 489f349c1fdSJed Brown if (flg) { 490f349c1fdSJed Brown *found = i; 491f349c1fdSJed Brown PetscFunctionReturn(0); 492f349c1fdSJed Brown } 493f349c1fdSJed Brown } 494ce94432eSBarry Smith SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_INCOMP,"Could not find index set"); 495f349c1fdSJed Brown PetscFunctionReturn(0); 496f349c1fdSJed Brown } 497f349c1fdSJed Brown 4988188e55aSJed Brown /* Get a block row as a new MatNest */ 4998188e55aSJed Brown static PetscErrorCode MatNestGetRow(Mat A,PetscInt row,Mat *B) 5008188e55aSJed Brown { 5018188e55aSJed Brown Mat_Nest *vs = (Mat_Nest*)A->data; 5028188e55aSJed Brown char keyname[256]; 5038188e55aSJed Brown PetscErrorCode ierr; 5048188e55aSJed Brown 5058188e55aSJed Brown PetscFunctionBegin; 5060298fd71SBarry Smith *B = NULL; 5078caf3d72SBarry Smith ierr = PetscSNPrintf(keyname,sizeof(keyname),"NestRow_%D",row);CHKERRQ(ierr); 5088188e55aSJed Brown ierr = PetscObjectQuery((PetscObject)A,keyname,(PetscObject*)B);CHKERRQ(ierr); 5098188e55aSJed Brown if (*B) PetscFunctionReturn(0); 5108188e55aSJed Brown 511ce94432eSBarry Smith ierr = MatCreateNest(PetscObjectComm((PetscObject)A),1,NULL,vs->nc,vs->isglobal.col,vs->m[row],B);CHKERRQ(ierr); 51226fbe8dcSKarl Rupp 5138188e55aSJed Brown (*B)->assembled = A->assembled; 51426fbe8dcSKarl Rupp 5158188e55aSJed Brown ierr = PetscObjectCompose((PetscObject)A,keyname,(PetscObject)*B);CHKERRQ(ierr); 5168188e55aSJed Brown ierr = PetscObjectDereference((PetscObject)*B);CHKERRQ(ierr); /* Leave the only remaining reference in the composition */ 5178188e55aSJed Brown PetscFunctionReturn(0); 5188188e55aSJed Brown } 5198188e55aSJed Brown 520f349c1fdSJed Brown static PetscErrorCode MatNestFindSubMat(Mat A,struct MatNestISPair *is,IS isrow,IS iscol,Mat *B) 521f349c1fdSJed Brown { 522f349c1fdSJed Brown Mat_Nest *vs = (Mat_Nest*)A->data; 5238188e55aSJed Brown PetscErrorCode ierr; 5246b3a5b13SJed Brown PetscInt row,col; 525e072481dSJed Brown PetscBool same,isFullCol,isFullColGlobal; 526f349c1fdSJed Brown 527f349c1fdSJed Brown PetscFunctionBegin; 5288188e55aSJed Brown /* Check if full column space. This is a hack */ 5298188e55aSJed Brown isFullCol = PETSC_FALSE; 530251f4c67SDmitry Karpeev ierr = PetscObjectTypeCompare((PetscObject)iscol,ISSTRIDE,&same);CHKERRQ(ierr); 5318188e55aSJed Brown if (same) { 53277019fcaSJed Brown PetscInt n,first,step,i,an,am,afirst,astep; 5338188e55aSJed Brown ierr = ISStrideGetInfo(iscol,&first,&step);CHKERRQ(ierr); 5348188e55aSJed Brown ierr = ISGetLocalSize(iscol,&n);CHKERRQ(ierr); 53577019fcaSJed Brown isFullCol = PETSC_TRUE; 53605ce4453SJed Brown for (i=0,an=A->cmap->rstart; i<vs->nc; i++) { 53777019fcaSJed Brown ierr = ISStrideGetInfo(is->col[i],&afirst,&astep);CHKERRQ(ierr); 53877019fcaSJed Brown ierr = ISGetLocalSize(is->col[i],&am);CHKERRQ(ierr); 53977019fcaSJed Brown if (afirst != an || astep != step) isFullCol = PETSC_FALSE; 54077019fcaSJed Brown an += am; 54177019fcaSJed Brown } 54205ce4453SJed Brown if (an != A->cmap->rstart+n) isFullCol = PETSC_FALSE; 5438188e55aSJed Brown } 544b2566f29SBarry Smith ierr = MPIU_Allreduce(&isFullCol,&isFullColGlobal,1,MPIU_BOOL,MPI_LAND,PetscObjectComm((PetscObject)iscol));CHKERRQ(ierr); 5458188e55aSJed Brown 546427230ceSLisandro Dalcin if (isFullColGlobal && vs->nc > 1) { 5478188e55aSJed Brown PetscInt row; 5488188e55aSJed Brown ierr = MatNestFindIS(A,vs->nr,is->row,isrow,&row);CHKERRQ(ierr); 5498188e55aSJed Brown ierr = MatNestGetRow(A,row,B);CHKERRQ(ierr); 5508188e55aSJed Brown } else { 551f349c1fdSJed Brown ierr = MatNestFindIS(A,vs->nr,is->row,isrow,&row);CHKERRQ(ierr); 552f349c1fdSJed Brown ierr = MatNestFindIS(A,vs->nc,is->col,iscol,&col);CHKERRQ(ierr); 553b6480e04SStefano Zampini if (!vs->m[row][col]) { 554b6480e04SStefano Zampini PetscInt lr,lc; 555b6480e04SStefano Zampini 556b6480e04SStefano Zampini ierr = MatCreate(PetscObjectComm((PetscObject)A),&vs->m[row][col]);CHKERRQ(ierr); 557b6480e04SStefano Zampini ierr = ISGetLocalSize(vs->isglobal.row[row],&lr);CHKERRQ(ierr); 558b6480e04SStefano Zampini ierr = ISGetLocalSize(vs->isglobal.col[col],&lc);CHKERRQ(ierr); 559b6480e04SStefano Zampini ierr = MatSetSizes(vs->m[row][col],lr,lc,PETSC_DECIDE,PETSC_DECIDE);CHKERRQ(ierr); 560b6480e04SStefano Zampini ierr = MatSetUp(vs->m[row][col]);CHKERRQ(ierr); 561b6480e04SStefano Zampini ierr = MatAssemblyBegin(vs->m[row][col],MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 562b6480e04SStefano Zampini ierr = MatAssemblyEnd(vs->m[row][col],MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 563b6480e04SStefano Zampini } 564f349c1fdSJed Brown *B = vs->m[row][col]; 5658188e55aSJed Brown } 566f349c1fdSJed Brown PetscFunctionReturn(0); 567f349c1fdSJed Brown } 568f349c1fdSJed Brown 5697dae84e0SHong Zhang static PetscErrorCode MatCreateSubMatrix_Nest(Mat A,IS isrow,IS iscol,MatReuse reuse,Mat *B) 570f349c1fdSJed Brown { 571f349c1fdSJed Brown PetscErrorCode ierr; 572f349c1fdSJed Brown Mat_Nest *vs = (Mat_Nest*)A->data; 573f349c1fdSJed Brown Mat sub; 574f349c1fdSJed Brown 575f349c1fdSJed Brown PetscFunctionBegin; 576f349c1fdSJed Brown ierr = MatNestFindSubMat(A,&vs->isglobal,isrow,iscol,&sub);CHKERRQ(ierr); 577f349c1fdSJed Brown switch (reuse) { 578f349c1fdSJed Brown case MAT_INITIAL_MATRIX: 5797874fa86SDave May if (sub) { ierr = PetscObjectReference((PetscObject)sub);CHKERRQ(ierr); } 580f349c1fdSJed Brown *B = sub; 581f349c1fdSJed Brown break; 582f349c1fdSJed Brown case MAT_REUSE_MATRIX: 583ce94432eSBarry Smith if (sub != *B) SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_WRONGSTATE,"Submatrix was not used before in this call"); 584f349c1fdSJed Brown break; 585f349c1fdSJed Brown case MAT_IGNORE_MATRIX: /* Nothing to do */ 586f349c1fdSJed Brown break; 587511c6705SHong Zhang case MAT_INPLACE_MATRIX: /* Nothing to do */ 588511c6705SHong Zhang SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_SUP,"MAT_INPLACE_MATRIX is not supported yet"); 589511c6705SHong Zhang break; 590f349c1fdSJed Brown } 591f349c1fdSJed Brown PetscFunctionReturn(0); 592f349c1fdSJed Brown } 593f349c1fdSJed Brown 594f349c1fdSJed Brown PetscErrorCode MatGetLocalSubMatrix_Nest(Mat A,IS isrow,IS iscol,Mat *B) 595f349c1fdSJed Brown { 596f349c1fdSJed Brown PetscErrorCode ierr; 597f349c1fdSJed Brown Mat_Nest *vs = (Mat_Nest*)A->data; 598f349c1fdSJed Brown Mat sub; 599f349c1fdSJed Brown 600f349c1fdSJed Brown PetscFunctionBegin; 601f349c1fdSJed Brown ierr = MatNestFindSubMat(A,&vs->islocal,isrow,iscol,&sub);CHKERRQ(ierr); 602f349c1fdSJed Brown /* We allow the submatrix to be NULL, perhaps it would be better for the user to return an empty matrix instead */ 603f349c1fdSJed Brown if (sub) {ierr = PetscObjectReference((PetscObject)sub);CHKERRQ(ierr);} 604f349c1fdSJed Brown *B = sub; 605d8588912SDave May PetscFunctionReturn(0); 606d8588912SDave May } 607d8588912SDave May 608207556f9SJed Brown static PetscErrorCode MatRestoreLocalSubMatrix_Nest(Mat A,IS isrow,IS iscol,Mat *B) 609d8588912SDave May { 610d8588912SDave May PetscErrorCode ierr; 611f349c1fdSJed Brown Mat_Nest *vs = (Mat_Nest*)A->data; 612f349c1fdSJed Brown Mat sub; 613d8588912SDave May 614d8588912SDave May PetscFunctionBegin; 615f349c1fdSJed Brown ierr = MatNestFindSubMat(A,&vs->islocal,isrow,iscol,&sub);CHKERRQ(ierr); 616ce94432eSBarry Smith if (*B != sub) SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_WRONGSTATE,"Local submatrix has not been gotten"); 617f349c1fdSJed Brown if (sub) { 618ce94432eSBarry Smith if (((PetscObject)sub)->refct <= 1) SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_WRONGSTATE,"Local submatrix has had reference count decremented too many times"); 6196bf464f9SBarry Smith ierr = MatDestroy(B);CHKERRQ(ierr); 620d8588912SDave May } 621d8588912SDave May PetscFunctionReturn(0); 622d8588912SDave May } 623d8588912SDave May 6247874fa86SDave May static PetscErrorCode MatGetDiagonal_Nest(Mat A,Vec v) 6257874fa86SDave May { 6267874fa86SDave May Mat_Nest *bA = (Mat_Nest*)A->data; 6277874fa86SDave May PetscInt i; 6287874fa86SDave May PetscErrorCode ierr; 6297874fa86SDave May 6307874fa86SDave May PetscFunctionBegin; 6317874fa86SDave May for (i=0; i<bA->nr; i++) { 632429bac76SJed Brown Vec bv; 633429bac76SJed Brown ierr = VecGetSubVector(v,bA->isglobal.row[i],&bv);CHKERRQ(ierr); 6347874fa86SDave May if (bA->m[i][i]) { 635429bac76SJed Brown ierr = MatGetDiagonal(bA->m[i][i],bv);CHKERRQ(ierr); 6367874fa86SDave May } else { 6375159a857SMatthew G. Knepley ierr = VecSet(bv,0.0);CHKERRQ(ierr); 6387874fa86SDave May } 639429bac76SJed Brown ierr = VecRestoreSubVector(v,bA->isglobal.row[i],&bv);CHKERRQ(ierr); 6407874fa86SDave May } 6417874fa86SDave May PetscFunctionReturn(0); 6427874fa86SDave May } 6437874fa86SDave May 6447874fa86SDave May static PetscErrorCode MatDiagonalScale_Nest(Mat A,Vec l,Vec r) 6457874fa86SDave May { 6467874fa86SDave May Mat_Nest *bA = (Mat_Nest*)A->data; 647429bac76SJed Brown Vec bl,*br; 6487874fa86SDave May PetscInt i,j; 6497874fa86SDave May PetscErrorCode ierr; 6507874fa86SDave May 6517874fa86SDave May PetscFunctionBegin; 6523f800ebeSJed Brown ierr = PetscCalloc1(bA->nc,&br);CHKERRQ(ierr); 6532e6472ebSElliott Sales de Andrade if (r) { 654429bac76SJed Brown for (j=0; j<bA->nc; j++) {ierr = VecGetSubVector(r,bA->isglobal.col[j],&br[j]);CHKERRQ(ierr);} 6552e6472ebSElliott Sales de Andrade } 6562e6472ebSElliott Sales de Andrade bl = NULL; 6577874fa86SDave May for (i=0; i<bA->nr; i++) { 6582e6472ebSElliott Sales de Andrade if (l) { 659429bac76SJed Brown ierr = VecGetSubVector(l,bA->isglobal.row[i],&bl);CHKERRQ(ierr); 6602e6472ebSElliott Sales de Andrade } 6617874fa86SDave May for (j=0; j<bA->nc; j++) { 6627874fa86SDave May if (bA->m[i][j]) { 663429bac76SJed Brown ierr = MatDiagonalScale(bA->m[i][j],bl,br[j]);CHKERRQ(ierr); 6647874fa86SDave May } 6657874fa86SDave May } 6662e6472ebSElliott Sales de Andrade if (l) { 667a061e289SJed Brown ierr = VecRestoreSubVector(l,bA->isglobal.row[i],&bl);CHKERRQ(ierr); 6687874fa86SDave May } 6692e6472ebSElliott Sales de Andrade } 6702e6472ebSElliott Sales de Andrade if (r) { 671429bac76SJed Brown for (j=0; j<bA->nc; j++) {ierr = VecRestoreSubVector(r,bA->isglobal.col[j],&br[j]);CHKERRQ(ierr);} 6722e6472ebSElliott Sales de Andrade } 673429bac76SJed Brown ierr = PetscFree(br);CHKERRQ(ierr); 6747874fa86SDave May PetscFunctionReturn(0); 6757874fa86SDave May } 6767874fa86SDave May 677a061e289SJed Brown static PetscErrorCode MatScale_Nest(Mat A,PetscScalar a) 678a061e289SJed Brown { 679a061e289SJed Brown Mat_Nest *bA = (Mat_Nest*)A->data; 680a061e289SJed Brown PetscInt i,j; 681a061e289SJed Brown PetscErrorCode ierr; 682a061e289SJed Brown 683a061e289SJed Brown PetscFunctionBegin; 684a061e289SJed Brown for (i=0; i<bA->nr; i++) { 685a061e289SJed Brown for (j=0; j<bA->nc; j++) { 686a061e289SJed Brown if (bA->m[i][j]) { 687a061e289SJed Brown ierr = MatScale(bA->m[i][j],a);CHKERRQ(ierr); 688a061e289SJed Brown } 689a061e289SJed Brown } 690a061e289SJed Brown } 691a061e289SJed Brown PetscFunctionReturn(0); 692a061e289SJed Brown } 693a061e289SJed Brown 694a061e289SJed Brown static PetscErrorCode MatShift_Nest(Mat A,PetscScalar a) 695a061e289SJed Brown { 696a061e289SJed Brown Mat_Nest *bA = (Mat_Nest*)A->data; 697a061e289SJed Brown PetscInt i; 698a061e289SJed Brown PetscErrorCode ierr; 699a061e289SJed Brown 700a061e289SJed Brown PetscFunctionBegin; 701a061e289SJed Brown for (i=0; i<bA->nr; i++) { 702ce94432eSBarry 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); 703a061e289SJed Brown ierr = MatShift(bA->m[i][i],a);CHKERRQ(ierr); 704a061e289SJed Brown } 705a061e289SJed Brown PetscFunctionReturn(0); 706a061e289SJed Brown } 707a061e289SJed Brown 70813135bc6SAlex Fikl static PetscErrorCode MatDiagonalSet_Nest(Mat A,Vec D,InsertMode is) 70913135bc6SAlex Fikl { 71013135bc6SAlex Fikl Mat_Nest *bA = (Mat_Nest*)A->data; 71113135bc6SAlex Fikl PetscInt i; 71213135bc6SAlex Fikl PetscErrorCode ierr; 71313135bc6SAlex Fikl 71413135bc6SAlex Fikl PetscFunctionBegin; 71513135bc6SAlex Fikl for (i=0; i<bA->nr; i++) { 71613135bc6SAlex Fikl Vec bv; 71713135bc6SAlex Fikl ierr = VecGetSubVector(D,bA->isglobal.row[i],&bv);CHKERRQ(ierr); 71813135bc6SAlex Fikl if (bA->m[i][i]) { 71913135bc6SAlex Fikl ierr = MatDiagonalSet(bA->m[i][i],bv,is);CHKERRQ(ierr); 72013135bc6SAlex Fikl } 72113135bc6SAlex Fikl ierr = VecRestoreSubVector(D,bA->isglobal.row[i],&bv);CHKERRQ(ierr); 72213135bc6SAlex Fikl } 72313135bc6SAlex Fikl PetscFunctionReturn(0); 72413135bc6SAlex Fikl } 72513135bc6SAlex Fikl 726f8170845SAlex Fikl static PetscErrorCode MatSetRandom_Nest(Mat A,PetscRandom rctx) 727f8170845SAlex Fikl { 728f8170845SAlex Fikl Mat_Nest *bA = (Mat_Nest*)A->data; 729f8170845SAlex Fikl PetscInt i,j; 730f8170845SAlex Fikl PetscErrorCode ierr; 731f8170845SAlex Fikl 732f8170845SAlex Fikl PetscFunctionBegin; 733f8170845SAlex Fikl for (i=0; i<bA->nr; i++) { 734f8170845SAlex Fikl for (j=0; j<bA->nc; j++) { 735f8170845SAlex Fikl if (bA->m[i][j]) { 736f8170845SAlex Fikl ierr = MatSetRandom(bA->m[i][j],rctx);CHKERRQ(ierr); 737f8170845SAlex Fikl } 738f8170845SAlex Fikl } 739f8170845SAlex Fikl } 740f8170845SAlex Fikl PetscFunctionReturn(0); 741f8170845SAlex Fikl } 742f8170845SAlex Fikl 7432a7a6963SBarry Smith static PetscErrorCode MatCreateVecs_Nest(Mat A,Vec *right,Vec *left) 744d8588912SDave May { 745d8588912SDave May Mat_Nest *bA = (Mat_Nest*)A->data; 746d8588912SDave May Vec *L,*R; 747d8588912SDave May MPI_Comm comm; 748d8588912SDave May PetscInt i,j; 749d8588912SDave May PetscErrorCode ierr; 750d8588912SDave May 751d8588912SDave May PetscFunctionBegin; 752ce94432eSBarry Smith ierr = PetscObjectGetComm((PetscObject)A,&comm);CHKERRQ(ierr); 753d8588912SDave May if (right) { 754d8588912SDave May /* allocate R */ 755854ce69bSBarry Smith ierr = PetscMalloc1(bA->nc, &R);CHKERRQ(ierr); 756d8588912SDave May /* Create the right vectors */ 757d8588912SDave May for (j=0; j<bA->nc; j++) { 758d8588912SDave May for (i=0; i<bA->nr; i++) { 759d8588912SDave May if (bA->m[i][j]) { 7602a7a6963SBarry Smith ierr = MatCreateVecs(bA->m[i][j],&R[j],NULL);CHKERRQ(ierr); 761d8588912SDave May break; 762d8588912SDave May } 763d8588912SDave May } 7646c4ed002SBarry Smith if (i==bA->nr) SETERRQ(PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONG, "Mat(Nest) contains a null column."); 765d8588912SDave May } 766f349c1fdSJed Brown ierr = VecCreateNest(comm,bA->nc,bA->isglobal.col,R,right);CHKERRQ(ierr); 767d8588912SDave May /* hand back control to the nest vector */ 768d8588912SDave May for (j=0; j<bA->nc; j++) { 7696bf464f9SBarry Smith ierr = VecDestroy(&R[j]);CHKERRQ(ierr); 770d8588912SDave May } 771d8588912SDave May ierr = PetscFree(R);CHKERRQ(ierr); 772d8588912SDave May } 773d8588912SDave May 774d8588912SDave May if (left) { 775d8588912SDave May /* allocate L */ 776854ce69bSBarry Smith ierr = PetscMalloc1(bA->nr, &L);CHKERRQ(ierr); 777d8588912SDave May /* Create the left vectors */ 778d8588912SDave May for (i=0; i<bA->nr; i++) { 779d8588912SDave May for (j=0; j<bA->nc; j++) { 780d8588912SDave May if (bA->m[i][j]) { 7812a7a6963SBarry Smith ierr = MatCreateVecs(bA->m[i][j],NULL,&L[i]);CHKERRQ(ierr); 782d8588912SDave May break; 783d8588912SDave May } 784d8588912SDave May } 7856c4ed002SBarry Smith if (j==bA->nc) SETERRQ(PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONG, "Mat(Nest) contains a null row."); 786d8588912SDave May } 787d8588912SDave May 788f349c1fdSJed Brown ierr = VecCreateNest(comm,bA->nr,bA->isglobal.row,L,left);CHKERRQ(ierr); 789d8588912SDave May for (i=0; i<bA->nr; i++) { 7906bf464f9SBarry Smith ierr = VecDestroy(&L[i]);CHKERRQ(ierr); 791d8588912SDave May } 792d8588912SDave May 793d8588912SDave May ierr = PetscFree(L);CHKERRQ(ierr); 794d8588912SDave May } 795d8588912SDave May PetscFunctionReturn(0); 796d8588912SDave May } 797d8588912SDave May 798207556f9SJed Brown static PetscErrorCode MatView_Nest(Mat A,PetscViewer viewer) 799d8588912SDave May { 800d8588912SDave May Mat_Nest *bA = (Mat_Nest*)A->data; 80129e60adbSStefano Zampini PetscBool isascii,viewSub = PETSC_FALSE; 802d8588912SDave May PetscInt i,j; 803d8588912SDave May PetscErrorCode ierr; 804d8588912SDave May 805d8588912SDave May PetscFunctionBegin; 806251f4c67SDmitry Karpeev ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&isascii);CHKERRQ(ierr); 807d8588912SDave May if (isascii) { 808d8588912SDave May 80929e60adbSStefano Zampini ierr = PetscOptionsGetBool(((PetscObject)A)->options,((PetscObject)A)->prefix,"-mat_view_nest_sub",&viewSub,NULL);CHKERRQ(ierr); 810d86155a6SBarry Smith ierr = PetscViewerASCIIPrintf(viewer,"Matrix object: \n");CHKERRQ(ierr); 811d86155a6SBarry Smith ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr); 812d86155a6SBarry Smith ierr = PetscViewerASCIIPrintf(viewer, "type=nest, rows=%D, cols=%D \n",bA->nr,bA->nc);CHKERRQ(ierr); 813d8588912SDave May 814d86155a6SBarry Smith ierr = PetscViewerASCIIPrintf(viewer,"MatNest structure: \n");CHKERRQ(ierr); 815d8588912SDave May for (i=0; i<bA->nr; i++) { 816d8588912SDave May for (j=0; j<bA->nc; j++) { 81719fd82e9SBarry Smith MatType type; 818270f95d7SJed Brown char name[256] = "",prefix[256] = ""; 819d8588912SDave May PetscInt NR,NC; 820d8588912SDave May PetscBool isNest = PETSC_FALSE; 821d8588912SDave May 822d8588912SDave May if (!bA->m[i][j]) { 823d86155a6SBarry Smith CHKERRQ(ierr);PetscViewerASCIIPrintf(viewer, "(%D,%D) : NULL \n",i,j);CHKERRQ(ierr); 824d8588912SDave May continue; 825d8588912SDave May } 826d8588912SDave May ierr = MatGetSize(bA->m[i][j],&NR,&NC);CHKERRQ(ierr); 827d8588912SDave May ierr = MatGetType(bA->m[i][j], &type);CHKERRQ(ierr); 8288caf3d72SBarry Smith if (((PetscObject)bA->m[i][j])->name) {ierr = PetscSNPrintf(name,sizeof(name),"name=\"%s\", ",((PetscObject)bA->m[i][j])->name);CHKERRQ(ierr);} 8298caf3d72SBarry Smith if (((PetscObject)bA->m[i][j])->prefix) {ierr = PetscSNPrintf(prefix,sizeof(prefix),"prefix=\"%s\", ",((PetscObject)bA->m[i][j])->prefix);CHKERRQ(ierr);} 830251f4c67SDmitry Karpeev ierr = PetscObjectTypeCompare((PetscObject)bA->m[i][j],MATNEST,&isNest);CHKERRQ(ierr); 831d8588912SDave May 832270f95d7SJed Brown ierr = PetscViewerASCIIPrintf(viewer,"(%D,%D) : %s%stype=%s, rows=%D, cols=%D \n",i,j,name,prefix,type,NR,NC);CHKERRQ(ierr); 833d8588912SDave May 83429e60adbSStefano Zampini if (isNest || viewSub) { 835270f95d7SJed Brown ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr); /* push1 */ 836d8588912SDave May ierr = MatView(bA->m[i][j],viewer);CHKERRQ(ierr); 837270f95d7SJed Brown ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr); /* pop1 */ 838d8588912SDave May } 839d8588912SDave May } 840d8588912SDave May } 841d86155a6SBarry Smith ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr); /* pop0 */ 842d8588912SDave May } 843d8588912SDave May PetscFunctionReturn(0); 844d8588912SDave May } 845d8588912SDave May 846207556f9SJed Brown static PetscErrorCode MatZeroEntries_Nest(Mat A) 847d8588912SDave May { 848d8588912SDave May Mat_Nest *bA = (Mat_Nest*)A->data; 849d8588912SDave May PetscInt i,j; 850d8588912SDave May PetscErrorCode ierr; 851d8588912SDave May 852d8588912SDave May PetscFunctionBegin; 853d8588912SDave May for (i=0; i<bA->nr; i++) { 854d8588912SDave May for (j=0; j<bA->nc; j++) { 855d8588912SDave May if (!bA->m[i][j]) continue; 856d8588912SDave May ierr = MatZeroEntries(bA->m[i][j]);CHKERRQ(ierr); 857d8588912SDave May } 858d8588912SDave May } 859d8588912SDave May PetscFunctionReturn(0); 860d8588912SDave May } 861d8588912SDave May 862c222c20dSDavid Ham static PetscErrorCode MatCopy_Nest(Mat A,Mat B,MatStructure str) 863c222c20dSDavid Ham { 864c222c20dSDavid Ham Mat_Nest *bA = (Mat_Nest*)A->data,*bB = (Mat_Nest*)B->data; 865c222c20dSDavid Ham PetscInt i,j,nr = bA->nr,nc = bA->nc; 866c222c20dSDavid Ham PetscErrorCode ierr; 867c222c20dSDavid Ham 868c222c20dSDavid Ham PetscFunctionBegin; 869c222c20dSDavid 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); 870c222c20dSDavid Ham for (i=0; i<nr; i++) { 871c222c20dSDavid Ham for (j=0; j<nc; j++) { 87246a2b97cSJed Brown if (bA->m[i][j] && bB->m[i][j]) { 873c222c20dSDavid Ham ierr = MatCopy(bA->m[i][j],bB->m[i][j],str);CHKERRQ(ierr); 87446a2b97cSJed 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); 875c222c20dSDavid Ham } 876c222c20dSDavid Ham } 877cdc753b6SBarry Smith ierr = PetscObjectStateIncrease((PetscObject)B);CHKERRQ(ierr); 878c222c20dSDavid Ham PetscFunctionReturn(0); 879c222c20dSDavid Ham } 880c222c20dSDavid Ham 8816e76ffeaSPierre Jolivet static PetscErrorCode MatAXPY_Nest(Mat Y,PetscScalar a,Mat X,MatStructure str) 8826e76ffeaSPierre Jolivet { 8836e76ffeaSPierre Jolivet Mat_Nest *bY = (Mat_Nest*)Y->data,*bX = (Mat_Nest*)X->data; 8846e76ffeaSPierre Jolivet PetscInt i,j,nr = bY->nr,nc = bY->nc; 8856e76ffeaSPierre Jolivet PetscErrorCode ierr; 8866e76ffeaSPierre Jolivet 8876e76ffeaSPierre Jolivet PetscFunctionBegin; 8886e76ffeaSPierre 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); 8896e76ffeaSPierre Jolivet for (i=0; i<nr; i++) { 8906e76ffeaSPierre Jolivet for (j=0; j<nc; j++) { 8916e76ffeaSPierre Jolivet if (bY->m[i][j] && bX->m[i][j]) { 8926e76ffeaSPierre Jolivet ierr = MatAXPY(bY->m[i][j],a,bX->m[i][j],str);CHKERRQ(ierr); 893c066aebcSStefano Zampini } else if (bX->m[i][j]) { 894c066aebcSStefano Zampini Mat M; 895c066aebcSStefano Zampini 896c066aebcSStefano Zampini if (str != DIFFERENT_NONZERO_PATTERN) SETERRQ2(PetscObjectComm((PetscObject)Y),PETSC_ERR_ARG_INCOMP,"Matrix block does not exist at %D,%D",i,j); 897c066aebcSStefano Zampini ierr = MatDuplicate(bX->m[i][j],MAT_COPY_VALUES,&M);CHKERRQ(ierr); 898c066aebcSStefano Zampini ierr = MatNestSetSubMat(Y,i,j,M);CHKERRQ(ierr); 899c066aebcSStefano Zampini ierr = MatDestroy(&M);CHKERRQ(ierr); 900c066aebcSStefano Zampini } 9016e76ffeaSPierre Jolivet } 9026e76ffeaSPierre Jolivet } 9036e76ffeaSPierre Jolivet PetscFunctionReturn(0); 9046e76ffeaSPierre Jolivet } 9056e76ffeaSPierre Jolivet 906207556f9SJed Brown static PetscErrorCode MatDuplicate_Nest(Mat A,MatDuplicateOption op,Mat *B) 907d8588912SDave May { 908d8588912SDave May Mat_Nest *bA = (Mat_Nest*)A->data; 909841e96a3SJed Brown Mat *b; 910841e96a3SJed Brown PetscInt i,j,nr = bA->nr,nc = bA->nc; 911d8588912SDave May PetscErrorCode ierr; 912d8588912SDave May 913d8588912SDave May PetscFunctionBegin; 914785e854fSJed Brown ierr = PetscMalloc1(nr*nc,&b);CHKERRQ(ierr); 915841e96a3SJed Brown for (i=0; i<nr; i++) { 916841e96a3SJed Brown for (j=0; j<nc; j++) { 917841e96a3SJed Brown if (bA->m[i][j]) { 918841e96a3SJed Brown ierr = MatDuplicate(bA->m[i][j],op,&b[i*nc+j]);CHKERRQ(ierr); 919841e96a3SJed Brown } else { 9200298fd71SBarry Smith b[i*nc+j] = NULL; 921d8588912SDave May } 922d8588912SDave May } 923d8588912SDave May } 924ce94432eSBarry Smith ierr = MatCreateNest(PetscObjectComm((PetscObject)A),nr,bA->isglobal.row,nc,bA->isglobal.col,b,B);CHKERRQ(ierr); 925841e96a3SJed Brown /* Give the new MatNest exclusive ownership */ 926841e96a3SJed Brown for (i=0; i<nr*nc; i++) { 9276bf464f9SBarry Smith ierr = MatDestroy(&b[i]);CHKERRQ(ierr); 928d8588912SDave May } 929d8588912SDave May ierr = PetscFree(b);CHKERRQ(ierr); 930d8588912SDave May 931841e96a3SJed Brown ierr = MatAssemblyBegin(*B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 932841e96a3SJed Brown ierr = MatAssemblyEnd(*B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 933d8588912SDave May PetscFunctionReturn(0); 934d8588912SDave May } 935d8588912SDave May 936d8588912SDave May /* nest api */ 937d8588912SDave May PetscErrorCode MatNestGetSubMat_Nest(Mat A,PetscInt idxm,PetscInt jdxm,Mat *mat) 938d8588912SDave May { 939d8588912SDave May Mat_Nest *bA = (Mat_Nest*)A->data; 9405fd66863SKarl Rupp 941d8588912SDave May PetscFunctionBegin; 942ce94432eSBarry Smith if (idxm >= bA->nr) SETERRQ2(PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_OUTOFRANGE,"Row too large: row %D max %D",idxm,bA->nr-1); 943ce94432eSBarry Smith if (jdxm >= bA->nc) SETERRQ2(PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_OUTOFRANGE,"Col too large: row %D max %D",jdxm,bA->nc-1); 944d8588912SDave May *mat = bA->m[idxm][jdxm]; 945d8588912SDave May PetscFunctionReturn(0); 946d8588912SDave May } 947d8588912SDave May 9489ba0d327SJed Brown /*@ 949d8588912SDave May MatNestGetSubMat - Returns a single, sub-matrix from a nest matrix. 950d8588912SDave May 951d8588912SDave May Not collective 952d8588912SDave May 953d8588912SDave May Input Parameters: 954629881c0SJed Brown + A - nest matrix 955d8588912SDave May . idxm - index of the matrix within the nest matrix 956629881c0SJed Brown - jdxm - index of the matrix within the nest matrix 957d8588912SDave May 958d8588912SDave May Output Parameter: 959d8588912SDave May . sub - matrix at index idxm,jdxm within the nest matrix 960d8588912SDave May 961d8588912SDave May Level: developer 962d8588912SDave May 963d8588912SDave May .seealso: MatNestGetSize(), MatNestGetSubMats() 964d8588912SDave May @*/ 9657087cfbeSBarry Smith PetscErrorCode MatNestGetSubMat(Mat A,PetscInt idxm,PetscInt jdxm,Mat *sub) 966d8588912SDave May { 967699a902aSJed Brown PetscErrorCode ierr; 968d8588912SDave May 969d8588912SDave May PetscFunctionBegin; 970699a902aSJed Brown ierr = PetscUseMethod(A,"MatNestGetSubMat_C",(Mat,PetscInt,PetscInt,Mat*),(A,idxm,jdxm,sub));CHKERRQ(ierr); 971d8588912SDave May PetscFunctionReturn(0); 972d8588912SDave May } 973d8588912SDave May 9740782ca92SJed Brown PetscErrorCode MatNestSetSubMat_Nest(Mat A,PetscInt idxm,PetscInt jdxm,Mat mat) 9750782ca92SJed Brown { 9760782ca92SJed Brown Mat_Nest *bA = (Mat_Nest*)A->data; 9770782ca92SJed Brown PetscInt m,n,M,N,mi,ni,Mi,Ni; 9780782ca92SJed Brown PetscErrorCode ierr; 9790782ca92SJed Brown 9800782ca92SJed Brown PetscFunctionBegin; 981ce94432eSBarry Smith if (idxm >= bA->nr) SETERRQ2(PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_OUTOFRANGE,"Row too large: row %D max %D",idxm,bA->nr-1); 982ce94432eSBarry Smith if (jdxm >= bA->nc) SETERRQ2(PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_OUTOFRANGE,"Col too large: row %D max %D",jdxm,bA->nc-1); 9830782ca92SJed Brown ierr = MatGetLocalSize(mat,&m,&n);CHKERRQ(ierr); 9840782ca92SJed Brown ierr = MatGetSize(mat,&M,&N);CHKERRQ(ierr); 9850782ca92SJed Brown ierr = ISGetLocalSize(bA->isglobal.row[idxm],&mi);CHKERRQ(ierr); 9860782ca92SJed Brown ierr = ISGetSize(bA->isglobal.row[idxm],&Mi);CHKERRQ(ierr); 9870782ca92SJed Brown ierr = ISGetLocalSize(bA->isglobal.col[jdxm],&ni);CHKERRQ(ierr); 9880782ca92SJed Brown ierr = ISGetSize(bA->isglobal.col[jdxm],&Ni);CHKERRQ(ierr); 989ce94432eSBarry 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); 990ce94432eSBarry 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); 99126fbe8dcSKarl Rupp 9920782ca92SJed Brown ierr = PetscObjectReference((PetscObject)mat);CHKERRQ(ierr); 9930782ca92SJed Brown ierr = MatDestroy(&bA->m[idxm][jdxm]);CHKERRQ(ierr); 9940782ca92SJed Brown bA->m[idxm][jdxm] = mat; 9950782ca92SJed Brown PetscFunctionReturn(0); 9960782ca92SJed Brown } 9970782ca92SJed Brown 9989ba0d327SJed Brown /*@ 9990782ca92SJed Brown MatNestSetSubMat - Set a single submatrix in the nest matrix. 10000782ca92SJed Brown 10010782ca92SJed Brown Logically collective on the submatrix communicator 10020782ca92SJed Brown 10030782ca92SJed Brown Input Parameters: 10040782ca92SJed Brown + A - nest matrix 10050782ca92SJed Brown . idxm - index of the matrix within the nest matrix 10060782ca92SJed Brown . jdxm - index of the matrix within the nest matrix 10070782ca92SJed Brown - sub - matrix at index idxm,jdxm within the nest matrix 10080782ca92SJed Brown 10090782ca92SJed Brown Notes: 10100782ca92SJed Brown The new submatrix must have the same size and communicator as that block of the nest. 10110782ca92SJed Brown 10120782ca92SJed Brown This increments the reference count of the submatrix. 10130782ca92SJed Brown 10140782ca92SJed Brown Level: developer 10150782ca92SJed Brown 1016d5dfb694SBarry Smith .seealso: MatNestSetSubMats(), MatNestGetSubMats() 10170782ca92SJed Brown @*/ 10180782ca92SJed Brown PetscErrorCode MatNestSetSubMat(Mat A,PetscInt idxm,PetscInt jdxm,Mat sub) 10190782ca92SJed Brown { 10200782ca92SJed Brown PetscErrorCode ierr; 10210782ca92SJed Brown 10220782ca92SJed Brown PetscFunctionBegin; 10230782ca92SJed Brown ierr = PetscUseMethod(A,"MatNestSetSubMat_C",(Mat,PetscInt,PetscInt,Mat),(A,idxm,jdxm,sub));CHKERRQ(ierr); 10240782ca92SJed Brown PetscFunctionReturn(0); 10250782ca92SJed Brown } 10260782ca92SJed Brown 1027d8588912SDave May PetscErrorCode MatNestGetSubMats_Nest(Mat A,PetscInt *M,PetscInt *N,Mat ***mat) 1028d8588912SDave May { 1029d8588912SDave May Mat_Nest *bA = (Mat_Nest*)A->data; 10305fd66863SKarl Rupp 1031d8588912SDave May PetscFunctionBegin; 103226fbe8dcSKarl Rupp if (M) *M = bA->nr; 103326fbe8dcSKarl Rupp if (N) *N = bA->nc; 103426fbe8dcSKarl Rupp if (mat) *mat = bA->m; 1035d8588912SDave May PetscFunctionReturn(0); 1036d8588912SDave May } 1037d8588912SDave May 1038d8588912SDave May /*@C 1039d8588912SDave May MatNestGetSubMats - Returns the entire two dimensional array of matrices defining a nest matrix. 1040d8588912SDave May 1041d8588912SDave May Not collective 1042d8588912SDave May 1043d8588912SDave May Input Parameters: 1044629881c0SJed Brown . A - nest matrix 1045d8588912SDave May 1046d8588912SDave May Output Parameter: 1047629881c0SJed Brown + M - number of rows in the nest matrix 1048d8588912SDave May . N - number of cols in the nest matrix 1049629881c0SJed Brown - mat - 2d array of matrices 1050d8588912SDave May 1051d8588912SDave May Notes: 1052d8588912SDave May 1053d8588912SDave May The user should not free the array mat. 1054d8588912SDave May 1055351962e3SVincent Le Chenadec In Fortran, this routine has a calling sequence 1056351962e3SVincent Le Chenadec $ call MatNestGetSubMats(A, M, N, mat, ierr) 1057351962e3SVincent Le Chenadec where the space allocated for the optional argument mat is assumed large enough (if provided). 1058351962e3SVincent Le Chenadec 1059d8588912SDave May Level: developer 1060d8588912SDave May 1061d8588912SDave May .seealso: MatNestGetSize(), MatNestGetSubMat() 1062d8588912SDave May @*/ 10637087cfbeSBarry Smith PetscErrorCode MatNestGetSubMats(Mat A,PetscInt *M,PetscInt *N,Mat ***mat) 1064d8588912SDave May { 1065699a902aSJed Brown PetscErrorCode ierr; 1066d8588912SDave May 1067d8588912SDave May PetscFunctionBegin; 1068699a902aSJed Brown ierr = PetscUseMethod(A,"MatNestGetSubMats_C",(Mat,PetscInt*,PetscInt*,Mat***),(A,M,N,mat));CHKERRQ(ierr); 1069d8588912SDave May PetscFunctionReturn(0); 1070d8588912SDave May } 1071d8588912SDave May 10727087cfbeSBarry Smith PetscErrorCode MatNestGetSize_Nest(Mat A,PetscInt *M,PetscInt *N) 1073d8588912SDave May { 1074d8588912SDave May Mat_Nest *bA = (Mat_Nest*)A->data; 1075d8588912SDave May 1076d8588912SDave May PetscFunctionBegin; 107726fbe8dcSKarl Rupp if (M) *M = bA->nr; 107826fbe8dcSKarl Rupp if (N) *N = bA->nc; 1079d8588912SDave May PetscFunctionReturn(0); 1080d8588912SDave May } 1081d8588912SDave May 10829ba0d327SJed Brown /*@ 1083d8588912SDave May MatNestGetSize - Returns the size of the nest matrix. 1084d8588912SDave May 1085d8588912SDave May Not collective 1086d8588912SDave May 1087d8588912SDave May Input Parameters: 1088d8588912SDave May . A - nest matrix 1089d8588912SDave May 1090d8588912SDave May Output Parameter: 1091629881c0SJed Brown + M - number of rows in the nested mat 1092629881c0SJed Brown - N - number of cols in the nested mat 1093d8588912SDave May 1094d8588912SDave May Notes: 1095d8588912SDave May 1096d8588912SDave May Level: developer 1097d8588912SDave May 1098d8588912SDave May .seealso: MatNestGetSubMat(), MatNestGetSubMats() 1099d8588912SDave May @*/ 11007087cfbeSBarry Smith PetscErrorCode MatNestGetSize(Mat A,PetscInt *M,PetscInt *N) 1101d8588912SDave May { 1102699a902aSJed Brown PetscErrorCode ierr; 1103d8588912SDave May 1104d8588912SDave May PetscFunctionBegin; 1105699a902aSJed Brown ierr = PetscUseMethod(A,"MatNestGetSize_C",(Mat,PetscInt*,PetscInt*),(A,M,N));CHKERRQ(ierr); 1106d8588912SDave May PetscFunctionReturn(0); 1107d8588912SDave May } 1108d8588912SDave May 1109f7a08781SBarry Smith static PetscErrorCode MatNestGetISs_Nest(Mat A,IS rows[],IS cols[]) 1110900e7ff2SJed Brown { 1111900e7ff2SJed Brown Mat_Nest *vs = (Mat_Nest*)A->data; 1112900e7ff2SJed Brown PetscInt i; 1113900e7ff2SJed Brown 1114900e7ff2SJed Brown PetscFunctionBegin; 1115900e7ff2SJed Brown if (rows) for (i=0; i<vs->nr; i++) rows[i] = vs->isglobal.row[i]; 1116900e7ff2SJed Brown if (cols) for (i=0; i<vs->nc; i++) cols[i] = vs->isglobal.col[i]; 1117900e7ff2SJed Brown PetscFunctionReturn(0); 1118900e7ff2SJed Brown } 1119900e7ff2SJed Brown 11203a4d7b9aSSatish Balay /*@C 1121900e7ff2SJed Brown MatNestGetISs - Returns the index sets partitioning the row and column spaces 1122900e7ff2SJed Brown 1123900e7ff2SJed Brown Not collective 1124900e7ff2SJed Brown 1125900e7ff2SJed Brown Input Parameters: 1126900e7ff2SJed Brown . A - nest matrix 1127900e7ff2SJed Brown 1128900e7ff2SJed Brown Output Parameter: 1129900e7ff2SJed Brown + rows - array of row index sets 1130900e7ff2SJed Brown - cols - array of column index sets 1131900e7ff2SJed Brown 1132900e7ff2SJed Brown Level: advanced 1133900e7ff2SJed Brown 1134900e7ff2SJed Brown Notes: 1135900e7ff2SJed Brown The user must have allocated arrays of the correct size. The reference count is not increased on the returned ISs. 1136900e7ff2SJed Brown 1137900e7ff2SJed Brown .seealso: MatNestGetSubMat(), MatNestGetSubMats(), MatNestGetSize(), MatNestGetLocalISs() 1138900e7ff2SJed Brown @*/ 1139900e7ff2SJed Brown PetscErrorCode MatNestGetISs(Mat A,IS rows[],IS cols[]) 1140900e7ff2SJed Brown { 1141900e7ff2SJed Brown PetscErrorCode ierr; 1142900e7ff2SJed Brown 1143900e7ff2SJed Brown PetscFunctionBegin; 1144900e7ff2SJed Brown PetscValidHeaderSpecific(A,MAT_CLASSID,1); 1145900e7ff2SJed Brown ierr = PetscUseMethod(A,"MatNestGetISs_C",(Mat,IS[],IS[]),(A,rows,cols));CHKERRQ(ierr); 1146900e7ff2SJed Brown PetscFunctionReturn(0); 1147900e7ff2SJed Brown } 1148900e7ff2SJed Brown 1149f7a08781SBarry Smith static PetscErrorCode MatNestGetLocalISs_Nest(Mat A,IS rows[],IS cols[]) 1150900e7ff2SJed Brown { 1151900e7ff2SJed Brown Mat_Nest *vs = (Mat_Nest*)A->data; 1152900e7ff2SJed Brown PetscInt i; 1153900e7ff2SJed Brown 1154900e7ff2SJed Brown PetscFunctionBegin; 1155900e7ff2SJed Brown if (rows) for (i=0; i<vs->nr; i++) rows[i] = vs->islocal.row[i]; 1156900e7ff2SJed Brown if (cols) for (i=0; i<vs->nc; i++) cols[i] = vs->islocal.col[i]; 1157900e7ff2SJed Brown PetscFunctionReturn(0); 1158900e7ff2SJed Brown } 1159900e7ff2SJed Brown 1160900e7ff2SJed Brown /*@C 1161900e7ff2SJed Brown MatNestGetLocalISs - Returns the index sets partitioning the row and column spaces 1162900e7ff2SJed Brown 1163900e7ff2SJed Brown Not collective 1164900e7ff2SJed Brown 1165900e7ff2SJed Brown Input Parameters: 1166900e7ff2SJed Brown . A - nest matrix 1167900e7ff2SJed Brown 1168900e7ff2SJed Brown Output Parameter: 11690298fd71SBarry Smith + rows - array of row index sets (or NULL to ignore) 11700298fd71SBarry Smith - cols - array of column index sets (or NULL to ignore) 1171900e7ff2SJed Brown 1172900e7ff2SJed Brown Level: advanced 1173900e7ff2SJed Brown 1174900e7ff2SJed Brown Notes: 1175900e7ff2SJed Brown The user must have allocated arrays of the correct size. The reference count is not increased on the returned ISs. 1176900e7ff2SJed Brown 1177900e7ff2SJed Brown .seealso: MatNestGetSubMat(), MatNestGetSubMats(), MatNestGetSize(), MatNestGetISs() 1178900e7ff2SJed Brown @*/ 1179900e7ff2SJed Brown PetscErrorCode MatNestGetLocalISs(Mat A,IS rows[],IS cols[]) 1180900e7ff2SJed Brown { 1181900e7ff2SJed Brown PetscErrorCode ierr; 1182900e7ff2SJed Brown 1183900e7ff2SJed Brown PetscFunctionBegin; 1184900e7ff2SJed Brown PetscValidHeaderSpecific(A,MAT_CLASSID,1); 1185900e7ff2SJed Brown ierr = PetscUseMethod(A,"MatNestGetLocalISs_C",(Mat,IS[],IS[]),(A,rows,cols));CHKERRQ(ierr); 1186900e7ff2SJed Brown PetscFunctionReturn(0); 1187900e7ff2SJed Brown } 1188900e7ff2SJed Brown 118919fd82e9SBarry Smith PetscErrorCode MatNestSetVecType_Nest(Mat A,VecType vtype) 1190207556f9SJed Brown { 1191207556f9SJed Brown PetscErrorCode ierr; 1192207556f9SJed Brown PetscBool flg; 1193207556f9SJed Brown 1194207556f9SJed Brown PetscFunctionBegin; 1195207556f9SJed Brown ierr = PetscStrcmp(vtype,VECNEST,&flg);CHKERRQ(ierr); 1196207556f9SJed Brown /* In reality, this only distinguishes VECNEST and "other" */ 11972a7a6963SBarry Smith if (flg) A->ops->getvecs = MatCreateVecs_Nest; 119812b53f24SSatish Balay else A->ops->getvecs = (PetscErrorCode (*)(Mat,Vec*,Vec*)) 0; 1199207556f9SJed Brown PetscFunctionReturn(0); 1200207556f9SJed Brown } 1201207556f9SJed Brown 1202207556f9SJed Brown /*@C 12032a7a6963SBarry Smith MatNestSetVecType - Sets the type of Vec returned by MatCreateVecs() 1204207556f9SJed Brown 1205207556f9SJed Brown Not collective 1206207556f9SJed Brown 1207207556f9SJed Brown Input Parameters: 1208207556f9SJed Brown + A - nest matrix 1209207556f9SJed Brown - vtype - type to use for creating vectors 1210207556f9SJed Brown 1211207556f9SJed Brown Notes: 1212207556f9SJed Brown 1213207556f9SJed Brown Level: developer 1214207556f9SJed Brown 12152a7a6963SBarry Smith .seealso: MatCreateVecs() 1216207556f9SJed Brown @*/ 121719fd82e9SBarry Smith PetscErrorCode MatNestSetVecType(Mat A,VecType vtype) 1218207556f9SJed Brown { 1219207556f9SJed Brown PetscErrorCode ierr; 1220207556f9SJed Brown 1221207556f9SJed Brown PetscFunctionBegin; 122219fd82e9SBarry Smith ierr = PetscTryMethod(A,"MatNestSetVecType_C",(Mat,VecType),(A,vtype));CHKERRQ(ierr); 1223207556f9SJed Brown PetscFunctionReturn(0); 1224207556f9SJed Brown } 1225207556f9SJed Brown 1226c8883902SJed Brown PetscErrorCode MatNestSetSubMats_Nest(Mat A,PetscInt nr,const IS is_row[],PetscInt nc,const IS is_col[],const Mat a[]) 1227d8588912SDave May { 1228c8883902SJed Brown Mat_Nest *s = (Mat_Nest*)A->data; 1229c8883902SJed Brown PetscInt i,j,m,n,M,N; 1230d8588912SDave May PetscErrorCode ierr; 1231d8588912SDave May 1232d8588912SDave May PetscFunctionBegin; 1233c8883902SJed Brown s->nr = nr; 1234c8883902SJed Brown s->nc = nc; 1235d8588912SDave May 1236c8883902SJed Brown /* Create space for submatrices */ 1237854ce69bSBarry Smith ierr = PetscMalloc1(nr,&s->m);CHKERRQ(ierr); 1238c8883902SJed Brown for (i=0; i<nr; i++) { 1239854ce69bSBarry Smith ierr = PetscMalloc1(nc,&s->m[i]);CHKERRQ(ierr); 1240d8588912SDave May } 1241c8883902SJed Brown for (i=0; i<nr; i++) { 1242c8883902SJed Brown for (j=0; j<nc; j++) { 1243c8883902SJed Brown s->m[i][j] = a[i*nc+j]; 1244c8883902SJed Brown if (a[i*nc+j]) { 1245c8883902SJed Brown ierr = PetscObjectReference((PetscObject)a[i*nc+j]);CHKERRQ(ierr); 1246d8588912SDave May } 1247d8588912SDave May } 1248d8588912SDave May } 1249d8588912SDave May 12508188e55aSJed Brown ierr = MatSetUp_NestIS_Private(A,nr,is_row,nc,is_col);CHKERRQ(ierr); 1251d8588912SDave May 1252854ce69bSBarry Smith ierr = PetscMalloc1(nr,&s->row_len);CHKERRQ(ierr); 1253854ce69bSBarry Smith ierr = PetscMalloc1(nc,&s->col_len);CHKERRQ(ierr); 1254c8883902SJed Brown for (i=0; i<nr; i++) s->row_len[i]=-1; 1255c8883902SJed Brown for (j=0; j<nc; j++) s->col_len[j]=-1; 1256d8588912SDave May 12578188e55aSJed Brown ierr = MatNestGetSizes_Private(A,&m,&n,&M,&N);CHKERRQ(ierr); 1258d8588912SDave May 1259c8883902SJed Brown ierr = PetscLayoutSetSize(A->rmap,M);CHKERRQ(ierr); 1260c8883902SJed Brown ierr = PetscLayoutSetLocalSize(A->rmap,m);CHKERRQ(ierr); 1261c8883902SJed Brown ierr = PetscLayoutSetSize(A->cmap,N);CHKERRQ(ierr); 1262c8883902SJed Brown ierr = PetscLayoutSetLocalSize(A->cmap,n);CHKERRQ(ierr); 1263c8883902SJed Brown 1264c8883902SJed Brown ierr = PetscLayoutSetUp(A->rmap);CHKERRQ(ierr); 1265c8883902SJed Brown ierr = PetscLayoutSetUp(A->cmap);CHKERRQ(ierr); 1266c8883902SJed Brown 12671795a4d1SJed Brown ierr = PetscCalloc2(nr,&s->left,nc,&s->right);CHKERRQ(ierr); 1268d8588912SDave May PetscFunctionReturn(0); 1269d8588912SDave May } 1270d8588912SDave May 1271c8883902SJed Brown /*@ 1272c8883902SJed Brown MatNestSetSubMats - Sets the nested submatrices 1273c8883902SJed Brown 1274c8883902SJed Brown Collective on Mat 1275c8883902SJed Brown 1276c8883902SJed Brown Input Parameter: 1277ffd6319bSRichard Tran Mills + A - nested matrix 1278c8883902SJed Brown . nr - number of nested row blocks 12790298fd71SBarry Smith . is_row - index sets for each nested row block, or NULL to make contiguous 1280c8883902SJed Brown . nc - number of nested column blocks 12810298fd71SBarry Smith . is_col - index sets for each nested column block, or NULL to make contiguous 12820298fd71SBarry Smith - a - row-aligned array of nr*nc submatrices, empty submatrices can be passed using NULL 1283c8883902SJed Brown 1284c8883902SJed Brown Level: advanced 1285c8883902SJed Brown 1286c8883902SJed Brown .seealso: MatCreateNest(), MATNEST 1287c8883902SJed Brown @*/ 1288c8883902SJed Brown PetscErrorCode MatNestSetSubMats(Mat A,PetscInt nr,const IS is_row[],PetscInt nc,const IS is_col[],const Mat a[]) 1289c8883902SJed Brown { 1290c8883902SJed Brown PetscErrorCode ierr; 1291eb6c2100SSatish Balay PetscInt i,nr_nc; 1292c8883902SJed Brown 1293c8883902SJed Brown PetscFunctionBegin; 1294c8883902SJed Brown PetscValidHeaderSpecific(A,MAT_CLASSID,1); 1295ce94432eSBarry Smith if (nr < 0) SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_OUTOFRANGE,"Number of rows cannot be negative"); 1296c8883902SJed Brown if (nr && is_row) { 1297c8883902SJed Brown PetscValidPointer(is_row,3); 1298c8883902SJed Brown for (i=0; i<nr; i++) PetscValidHeaderSpecific(is_row[i],IS_CLASSID,3); 1299c8883902SJed Brown } 1300ce94432eSBarry Smith if (nc < 0) SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_OUTOFRANGE,"Number of columns cannot be negative"); 13011664e352SJed Brown if (nc && is_col) { 1302c8883902SJed Brown PetscValidPointer(is_col,5); 13039b30a8f6SBarry Smith for (i=0; i<nc; i++) PetscValidHeaderSpecific(is_col[i],IS_CLASSID,5); 1304c8883902SJed Brown } 1305eb6c2100SSatish Balay nr_nc=nr*nc; 1306eb6c2100SSatish Balay if (nr_nc) PetscValidPointer(a,6); 1307c8883902SJed 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); 1308c8883902SJed Brown PetscFunctionReturn(0); 1309c8883902SJed Brown } 1310d8588912SDave May 131145b6f7e9SBarry Smith static PetscErrorCode MatNestCreateAggregateL2G_Private(Mat A,PetscInt n,const IS islocal[],const IS isglobal[],PetscBool colflg,ISLocalToGlobalMapping *ltog) 131277019fcaSJed Brown { 131377019fcaSJed Brown PetscErrorCode ierr; 131477019fcaSJed Brown PetscBool flg; 131577019fcaSJed Brown PetscInt i,j,m,mi,*ix; 131677019fcaSJed Brown 131777019fcaSJed Brown PetscFunctionBegin; 131877019fcaSJed Brown for (i=0,m=0,flg=PETSC_FALSE; i<n; i++) { 131977019fcaSJed Brown if (islocal[i]) { 132077019fcaSJed Brown ierr = ISGetSize(islocal[i],&mi);CHKERRQ(ierr); 132177019fcaSJed Brown flg = PETSC_TRUE; /* We found a non-trivial entry */ 132277019fcaSJed Brown } else { 132377019fcaSJed Brown ierr = ISGetSize(isglobal[i],&mi);CHKERRQ(ierr); 132477019fcaSJed Brown } 132577019fcaSJed Brown m += mi; 132677019fcaSJed Brown } 132777019fcaSJed Brown if (flg) { 1328785e854fSJed Brown ierr = PetscMalloc1(m,&ix);CHKERRQ(ierr); 1329165cd838SBarry Smith for (i=0,m=0; i<n; i++) { 13300298fd71SBarry Smith ISLocalToGlobalMapping smap = NULL; 1331e108cb99SStefano Zampini Mat sub = NULL; 1332f6d38dbbSStefano Zampini PetscSF sf; 1333f6d38dbbSStefano Zampini PetscLayout map; 1334f6d38dbbSStefano Zampini PetscInt *ix2; 133577019fcaSJed Brown 1336165cd838SBarry Smith if (!colflg) { 133777019fcaSJed Brown ierr = MatNestFindNonzeroSubMatRow(A,i,&sub);CHKERRQ(ierr); 133877019fcaSJed Brown } else { 133977019fcaSJed Brown ierr = MatNestFindNonzeroSubMatCol(A,i,&sub);CHKERRQ(ierr); 134077019fcaSJed Brown } 1341191fd14bSBarry Smith if (sub) { 1342191fd14bSBarry Smith if (!colflg) { 1343191fd14bSBarry Smith ierr = MatGetLocalToGlobalMapping(sub,&smap,NULL);CHKERRQ(ierr); 1344191fd14bSBarry Smith } else { 1345191fd14bSBarry Smith ierr = MatGetLocalToGlobalMapping(sub,NULL,&smap);CHKERRQ(ierr); 1346191fd14bSBarry Smith } 1347191fd14bSBarry Smith } 134877019fcaSJed Brown if (islocal[i]) { 134977019fcaSJed Brown ierr = ISGetSize(islocal[i],&mi);CHKERRQ(ierr); 135077019fcaSJed Brown } else { 135177019fcaSJed Brown ierr = ISGetSize(isglobal[i],&mi);CHKERRQ(ierr); 135277019fcaSJed Brown } 135377019fcaSJed Brown for (j=0; j<mi; j++) ix[m+j] = j; 135477019fcaSJed Brown if (smap) {ierr = ISLocalToGlobalMappingApply(smap,mi,ix+m,ix+m);CHKERRQ(ierr);} 1355165cd838SBarry Smith 135677019fcaSJed Brown /* 135777019fcaSJed Brown Now we need to extract the monolithic global indices that correspond to the given split global indices. 135877019fcaSJed 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. 135977019fcaSJed Brown */ 1360f6d38dbbSStefano Zampini ierr = PetscMalloc1(mi,&ix2);CHKERRQ(ierr); 1361f6d38dbbSStefano Zampini ierr = PetscSFCreate(((PetscObject)isglobal[i])->comm,&sf);CHKERRQ(ierr); 1362f6d38dbbSStefano Zampini ierr = PetscLayoutCreate(((PetscObject)isglobal[i])->comm,&map);CHKERRQ(ierr); 1363f6d38dbbSStefano Zampini ierr = PetscLayoutSetLocalSize(map,mi);CHKERRQ(ierr); 1364f6d38dbbSStefano Zampini ierr = PetscLayoutSetUp(map);CHKERRQ(ierr); 1365f6d38dbbSStefano Zampini ierr = PetscSFSetGraphLayout(sf,map,mi,NULL,PETSC_USE_POINTER,ix+m);CHKERRQ(ierr); 1366f6d38dbbSStefano Zampini ierr = PetscLayoutDestroy(&map);CHKERRQ(ierr); 1367f6d38dbbSStefano Zampini for (j=0; j<mi; j++) ix2[j] = ix[m+j]; 1368f6d38dbbSStefano Zampini ierr = PetscSFBcastBegin(sf,MPIU_INT,ix2,ix + m);CHKERRQ(ierr); 1369f6d38dbbSStefano Zampini ierr = PetscSFBcastEnd(sf,MPIU_INT,ix2,ix + m);CHKERRQ(ierr); 1370f6d38dbbSStefano Zampini ierr = PetscSFDestroy(&sf);CHKERRQ(ierr); 1371f6d38dbbSStefano Zampini ierr = PetscFree(ix2);CHKERRQ(ierr); 137277019fcaSJed Brown m += mi; 137377019fcaSJed Brown } 1374f0413b6fSBarry Smith ierr = ISLocalToGlobalMappingCreate(PetscObjectComm((PetscObject)A),1,m,ix,PETSC_OWN_POINTER,ltog);CHKERRQ(ierr); 137577019fcaSJed Brown } else { 13760298fd71SBarry Smith *ltog = NULL; 137777019fcaSJed Brown } 137877019fcaSJed Brown PetscFunctionReturn(0); 137977019fcaSJed Brown } 138077019fcaSJed Brown 138177019fcaSJed Brown 1382d8588912SDave May /* If an IS was provided, there is nothing Nest needs to do, otherwise Nest will build a strided IS */ 1383d8588912SDave May /* 1384d8588912SDave May nprocessors = NP 1385d8588912SDave May Nest x^T = ((g_0,g_1,...g_nprocs-1), (h_0,h_1,...h_NP-1)) 1386d8588912SDave May proc 0: => (g_0,h_0,) 1387d8588912SDave May proc 1: => (g_1,h_1,) 1388d8588912SDave May ... 1389d8588912SDave May proc nprocs-1: => (g_NP-1,h_NP-1,) 1390d8588912SDave May 1391d8588912SDave May proc 0: proc 1: proc nprocs-1: 1392d8588912SDave May is[0] = (0,1,2,...,nlocal(g_0)-1) (0,1,...,nlocal(g_1)-1) (0,1,...,nlocal(g_NP-1)) 1393d8588912SDave May 1394d8588912SDave May proc 0: 1395d8588912SDave May is[1] = (nlocal(g_0),nlocal(g_0)+1,...,nlocal(g_0)+nlocal(h_0)-1) 1396d8588912SDave May proc 1: 1397d8588912SDave May is[1] = (nlocal(g_1),nlocal(g_1)+1,...,nlocal(g_1)+nlocal(h_1)-1) 1398d8588912SDave May 1399d8588912SDave May proc NP-1: 1400d8588912SDave May is[1] = (nlocal(g_NP-1),nlocal(g_NP-1)+1,...,nlocal(g_NP-1)+nlocal(h_NP-1)-1) 1401d8588912SDave May */ 1402841e96a3SJed Brown static PetscErrorCode MatSetUp_NestIS_Private(Mat A,PetscInt nr,const IS is_row[],PetscInt nc,const IS is_col[]) 1403d8588912SDave May { 1404e2d7f03fSJed Brown Mat_Nest *vs = (Mat_Nest*)A->data; 14058188e55aSJed Brown PetscInt i,j,offset,n,nsum,bs; 1406d8588912SDave May PetscErrorCode ierr; 14070298fd71SBarry Smith Mat sub = NULL; 1408d8588912SDave May 1409d8588912SDave May PetscFunctionBegin; 1410854ce69bSBarry Smith ierr = PetscMalloc1(nr,&vs->isglobal.row);CHKERRQ(ierr); 1411854ce69bSBarry Smith ierr = PetscMalloc1(nc,&vs->isglobal.col);CHKERRQ(ierr); 1412d8588912SDave May if (is_row) { /* valid IS is passed in */ 1413d8588912SDave May /* refs on is[] are incremeneted */ 1414e2d7f03fSJed Brown for (i=0; i<vs->nr; i++) { 1415d8588912SDave May ierr = PetscObjectReference((PetscObject)is_row[i]);CHKERRQ(ierr); 141626fbe8dcSKarl Rupp 1417e2d7f03fSJed Brown vs->isglobal.row[i] = is_row[i]; 1418d8588912SDave May } 14192ae74bdbSJed Brown } else { /* Create the ISs by inspecting sizes of a submatrix in each row */ 14208188e55aSJed Brown nsum = 0; 14218188e55aSJed Brown for (i=0; i<vs->nr; i++) { /* Add up the local sizes to compute the aggregate offset */ 14228188e55aSJed Brown ierr = MatNestFindNonzeroSubMatRow(A,i,&sub);CHKERRQ(ierr); 1423ce94432eSBarry Smith if (!sub) SETERRQ1(PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_WRONG,"No nonzero submatrix in row %D",i); 14240298fd71SBarry Smith ierr = MatGetLocalSize(sub,&n,NULL);CHKERRQ(ierr); 1425ce94432eSBarry Smith if (n < 0) SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_WRONGSTATE,"Sizes have not yet been set for submatrix"); 14268188e55aSJed Brown nsum += n; 14278188e55aSJed Brown } 1428ce94432eSBarry Smith ierr = MPI_Scan(&nsum,&offset,1,MPIU_INT,MPI_SUM,PetscObjectComm((PetscObject)A));CHKERRQ(ierr); 142930bc264bSJed Brown offset -= nsum; 1430e2d7f03fSJed Brown for (i=0; i<vs->nr; i++) { 1431f349c1fdSJed Brown ierr = MatNestFindNonzeroSubMatRow(A,i,&sub);CHKERRQ(ierr); 14320298fd71SBarry Smith ierr = MatGetLocalSize(sub,&n,NULL);CHKERRQ(ierr); 14332ae74bdbSJed Brown ierr = MatGetBlockSize(sub,&bs);CHKERRQ(ierr); 1434ce94432eSBarry Smith ierr = ISCreateStride(PetscObjectComm((PetscObject)sub),n,offset,1,&vs->isglobal.row[i]);CHKERRQ(ierr); 1435e2d7f03fSJed Brown ierr = ISSetBlockSize(vs->isglobal.row[i],bs);CHKERRQ(ierr); 14362ae74bdbSJed Brown offset += n; 1437d8588912SDave May } 1438d8588912SDave May } 1439d8588912SDave May 1440d8588912SDave May if (is_col) { /* valid IS is passed in */ 1441d8588912SDave May /* refs on is[] are incremeneted */ 1442e2d7f03fSJed Brown for (j=0; j<vs->nc; j++) { 1443d8588912SDave May ierr = PetscObjectReference((PetscObject)is_col[j]);CHKERRQ(ierr); 144426fbe8dcSKarl Rupp 1445e2d7f03fSJed Brown vs->isglobal.col[j] = is_col[j]; 1446d8588912SDave May } 14472ae74bdbSJed Brown } else { /* Create the ISs by inspecting sizes of a submatrix in each column */ 14482ae74bdbSJed Brown offset = A->cmap->rstart; 14498188e55aSJed Brown nsum = 0; 14508188e55aSJed Brown for (j=0; j<vs->nc; j++) { 14518188e55aSJed Brown ierr = MatNestFindNonzeroSubMatCol(A,j,&sub);CHKERRQ(ierr); 1452ce94432eSBarry Smith if (!sub) SETERRQ1(PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_WRONG,"No nonzero submatrix in column %D",i); 14530298fd71SBarry Smith ierr = MatGetLocalSize(sub,NULL,&n);CHKERRQ(ierr); 1454ce94432eSBarry Smith if (n < 0) SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_WRONGSTATE,"Sizes have not yet been set for submatrix"); 14558188e55aSJed Brown nsum += n; 14568188e55aSJed Brown } 1457ce94432eSBarry Smith ierr = MPI_Scan(&nsum,&offset,1,MPIU_INT,MPI_SUM,PetscObjectComm((PetscObject)A));CHKERRQ(ierr); 145830bc264bSJed Brown offset -= nsum; 1459e2d7f03fSJed Brown for (j=0; j<vs->nc; j++) { 1460f349c1fdSJed Brown ierr = MatNestFindNonzeroSubMatCol(A,j,&sub);CHKERRQ(ierr); 14610298fd71SBarry Smith ierr = MatGetLocalSize(sub,NULL,&n);CHKERRQ(ierr); 14622ae74bdbSJed Brown ierr = MatGetBlockSize(sub,&bs);CHKERRQ(ierr); 1463ce94432eSBarry Smith ierr = ISCreateStride(PetscObjectComm((PetscObject)sub),n,offset,1,&vs->isglobal.col[j]);CHKERRQ(ierr); 1464e2d7f03fSJed Brown ierr = ISSetBlockSize(vs->isglobal.col[j],bs);CHKERRQ(ierr); 14652ae74bdbSJed Brown offset += n; 1466d8588912SDave May } 1467d8588912SDave May } 1468e2d7f03fSJed Brown 1469e2d7f03fSJed Brown /* Set up the local ISs */ 1470785e854fSJed Brown ierr = PetscMalloc1(vs->nr,&vs->islocal.row);CHKERRQ(ierr); 1471785e854fSJed Brown ierr = PetscMalloc1(vs->nc,&vs->islocal.col);CHKERRQ(ierr); 1472e2d7f03fSJed Brown for (i=0,offset=0; i<vs->nr; i++) { 1473e2d7f03fSJed Brown IS isloc; 14740298fd71SBarry Smith ISLocalToGlobalMapping rmap = NULL; 1475e2d7f03fSJed Brown PetscInt nlocal,bs; 1476e2d7f03fSJed Brown ierr = MatNestFindNonzeroSubMatRow(A,i,&sub);CHKERRQ(ierr); 14770298fd71SBarry Smith if (sub) {ierr = MatGetLocalToGlobalMapping(sub,&rmap,NULL);CHKERRQ(ierr);} 1478207556f9SJed Brown if (rmap) { 1479e2d7f03fSJed Brown ierr = MatGetBlockSize(sub,&bs);CHKERRQ(ierr); 1480e2d7f03fSJed Brown ierr = ISLocalToGlobalMappingGetSize(rmap,&nlocal);CHKERRQ(ierr); 1481e2d7f03fSJed Brown ierr = ISCreateStride(PETSC_COMM_SELF,nlocal,offset,1,&isloc);CHKERRQ(ierr); 1482e2d7f03fSJed Brown ierr = ISSetBlockSize(isloc,bs);CHKERRQ(ierr); 1483207556f9SJed Brown } else { 1484207556f9SJed Brown nlocal = 0; 14850298fd71SBarry Smith isloc = NULL; 1486207556f9SJed Brown } 1487e2d7f03fSJed Brown vs->islocal.row[i] = isloc; 1488e2d7f03fSJed Brown offset += nlocal; 1489e2d7f03fSJed Brown } 14908188e55aSJed Brown for (i=0,offset=0; i<vs->nc; i++) { 1491e2d7f03fSJed Brown IS isloc; 14920298fd71SBarry Smith ISLocalToGlobalMapping cmap = NULL; 1493e2d7f03fSJed Brown PetscInt nlocal,bs; 1494e2d7f03fSJed Brown ierr = MatNestFindNonzeroSubMatCol(A,i,&sub);CHKERRQ(ierr); 14950298fd71SBarry Smith if (sub) {ierr = MatGetLocalToGlobalMapping(sub,NULL,&cmap);CHKERRQ(ierr);} 1496207556f9SJed Brown if (cmap) { 1497e2d7f03fSJed Brown ierr = MatGetBlockSize(sub,&bs);CHKERRQ(ierr); 1498e2d7f03fSJed Brown ierr = ISLocalToGlobalMappingGetSize(cmap,&nlocal);CHKERRQ(ierr); 1499e2d7f03fSJed Brown ierr = ISCreateStride(PETSC_COMM_SELF,nlocal,offset,1,&isloc);CHKERRQ(ierr); 1500e2d7f03fSJed Brown ierr = ISSetBlockSize(isloc,bs);CHKERRQ(ierr); 1501207556f9SJed Brown } else { 1502207556f9SJed Brown nlocal = 0; 15030298fd71SBarry Smith isloc = NULL; 1504207556f9SJed Brown } 1505e2d7f03fSJed Brown vs->islocal.col[i] = isloc; 1506e2d7f03fSJed Brown offset += nlocal; 1507e2d7f03fSJed Brown } 15080189643fSJed Brown 150977019fcaSJed Brown /* Set up the aggregate ISLocalToGlobalMapping */ 151077019fcaSJed Brown { 151145b6f7e9SBarry Smith ISLocalToGlobalMapping rmap,cmap; 151245b6f7e9SBarry Smith ierr = MatNestCreateAggregateL2G_Private(A,vs->nr,vs->islocal.row,vs->isglobal.row,PETSC_FALSE,&rmap);CHKERRQ(ierr); 151345b6f7e9SBarry Smith ierr = MatNestCreateAggregateL2G_Private(A,vs->nc,vs->islocal.col,vs->isglobal.col,PETSC_TRUE,&cmap);CHKERRQ(ierr); 151477019fcaSJed Brown if (rmap && cmap) {ierr = MatSetLocalToGlobalMapping(A,rmap,cmap);CHKERRQ(ierr);} 151577019fcaSJed Brown ierr = ISLocalToGlobalMappingDestroy(&rmap);CHKERRQ(ierr); 151677019fcaSJed Brown ierr = ISLocalToGlobalMappingDestroy(&cmap);CHKERRQ(ierr); 151777019fcaSJed Brown } 151877019fcaSJed Brown 15190189643fSJed Brown #if defined(PETSC_USE_DEBUG) 15200189643fSJed Brown for (i=0; i<vs->nr; i++) { 15210189643fSJed Brown for (j=0; j<vs->nc; j++) { 15220189643fSJed Brown PetscInt m,n,M,N,mi,ni,Mi,Ni; 15230189643fSJed Brown Mat B = vs->m[i][j]; 15240189643fSJed Brown if (!B) continue; 15250189643fSJed Brown ierr = MatGetSize(B,&M,&N);CHKERRQ(ierr); 15260189643fSJed Brown ierr = MatGetLocalSize(B,&m,&n);CHKERRQ(ierr); 15270189643fSJed Brown ierr = ISGetSize(vs->isglobal.row[i],&Mi);CHKERRQ(ierr); 15280189643fSJed Brown ierr = ISGetSize(vs->isglobal.col[j],&Ni);CHKERRQ(ierr); 15290189643fSJed Brown ierr = ISGetLocalSize(vs->isglobal.row[i],&mi);CHKERRQ(ierr); 15300189643fSJed Brown ierr = ISGetLocalSize(vs->isglobal.col[j],&ni);CHKERRQ(ierr); 1531ce94432eSBarry 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); 1532ce94432eSBarry 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); 15330189643fSJed Brown } 15340189643fSJed Brown } 15350189643fSJed Brown #endif 1536a061e289SJed Brown 1537a061e289SJed Brown /* Set A->assembled if all non-null blocks are currently assembled */ 1538a061e289SJed Brown for (i=0; i<vs->nr; i++) { 1539a061e289SJed Brown for (j=0; j<vs->nc; j++) { 1540a061e289SJed Brown if (vs->m[i][j] && !vs->m[i][j]->assembled) PetscFunctionReturn(0); 1541a061e289SJed Brown } 1542a061e289SJed Brown } 1543a061e289SJed Brown A->assembled = PETSC_TRUE; 1544d8588912SDave May PetscFunctionReturn(0); 1545d8588912SDave May } 1546d8588912SDave May 154745c38901SJed Brown /*@C 1548659c6bb0SJed Brown MatCreateNest - Creates a new matrix containing several nested submatrices, each stored separately 1549659c6bb0SJed Brown 1550659c6bb0SJed Brown Collective on Mat 1551659c6bb0SJed Brown 1552659c6bb0SJed Brown Input Parameter: 1553659c6bb0SJed Brown + comm - Communicator for the new Mat 1554659c6bb0SJed Brown . nr - number of nested row blocks 15550298fd71SBarry Smith . is_row - index sets for each nested row block, or NULL to make contiguous 1556659c6bb0SJed Brown . nc - number of nested column blocks 15570298fd71SBarry Smith . is_col - index sets for each nested column block, or NULL to make contiguous 15580298fd71SBarry Smith - a - row-aligned array of nr*nc submatrices, empty submatrices can be passed using NULL 1559659c6bb0SJed Brown 1560659c6bb0SJed Brown Output Parameter: 1561659c6bb0SJed Brown . B - new matrix 1562659c6bb0SJed Brown 1563659c6bb0SJed Brown Level: advanced 1564659c6bb0SJed Brown 1565950540a4SJed Brown .seealso: MatCreate(), VecCreateNest(), DMCreateMatrix(), MATNEST 1566659c6bb0SJed Brown @*/ 15677087cfbeSBarry Smith PetscErrorCode MatCreateNest(MPI_Comm comm,PetscInt nr,const IS is_row[],PetscInt nc,const IS is_col[],const Mat a[],Mat *B) 1568d8588912SDave May { 1569d8588912SDave May Mat A; 1570d8588912SDave May PetscErrorCode ierr; 1571d8588912SDave May 1572d8588912SDave May PetscFunctionBegin; 1573c8883902SJed Brown *B = 0; 1574d8588912SDave May ierr = MatCreate(comm,&A);CHKERRQ(ierr); 1575c8883902SJed Brown ierr = MatSetType(A,MATNEST);CHKERRQ(ierr); 157691a28eb3SBarry Smith A->preallocated = PETSC_TRUE; 1577c8883902SJed Brown ierr = MatNestSetSubMats(A,nr,is_row,nc,is_col,a);CHKERRQ(ierr); 1578d8588912SDave May *B = A; 1579d8588912SDave May PetscFunctionReturn(0); 1580d8588912SDave May } 1581659c6bb0SJed Brown 1582b68353e5Sstefano_zampini static PetscErrorCode MatConvert_Nest_SeqAIJ_fast(Mat A,MatType newtype,MatReuse reuse,Mat *newmat) 1583b68353e5Sstefano_zampini { 1584b68353e5Sstefano_zampini Mat_Nest *nest = (Mat_Nest*)A->data; 158523875855Sstefano_zampini Mat *trans; 1586b68353e5Sstefano_zampini PetscScalar **avv; 1587b68353e5Sstefano_zampini PetscScalar *vv; 1588b68353e5Sstefano_zampini PetscInt **aii,**ajj; 1589b68353e5Sstefano_zampini PetscInt *ii,*jj,*ci; 1590b68353e5Sstefano_zampini PetscInt nr,nc,nnz,i,j; 1591b68353e5Sstefano_zampini PetscBool done; 1592b68353e5Sstefano_zampini PetscErrorCode ierr; 1593b68353e5Sstefano_zampini 1594b68353e5Sstefano_zampini PetscFunctionBegin; 1595b68353e5Sstefano_zampini ierr = MatGetSize(A,&nr,&nc);CHKERRQ(ierr); 1596b68353e5Sstefano_zampini if (reuse == MAT_REUSE_MATRIX) { 1597b68353e5Sstefano_zampini PetscInt rnr; 1598b68353e5Sstefano_zampini 1599b68353e5Sstefano_zampini ierr = MatGetRowIJ(*newmat,0,PETSC_FALSE,PETSC_FALSE,&rnr,(const PetscInt**)&ii,(const PetscInt**)&jj,&done);CHKERRQ(ierr); 1600b68353e5Sstefano_zampini if (!done) SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_PLIB,"MatGetRowIJ"); 1601b68353e5Sstefano_zampini if (rnr != nr) SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_USER,"Cannot reuse matrix, wrong number of rows"); 1602b68353e5Sstefano_zampini ierr = MatSeqAIJGetArray(*newmat,&vv);CHKERRQ(ierr); 1603b68353e5Sstefano_zampini } 1604b68353e5Sstefano_zampini /* extract CSR for nested SeqAIJ matrices */ 1605b68353e5Sstefano_zampini nnz = 0; 160623875855Sstefano_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); 1607b68353e5Sstefano_zampini for (i=0; i<nest->nr; ++i) { 1608b68353e5Sstefano_zampini for (j=0; j<nest->nc; ++j) { 1609b68353e5Sstefano_zampini Mat B = nest->m[i][j]; 1610b68353e5Sstefano_zampini if (B) { 1611b68353e5Sstefano_zampini PetscScalar *naa; 1612b68353e5Sstefano_zampini PetscInt *nii,*njj,nnr; 161323875855Sstefano_zampini PetscBool istrans; 1614b68353e5Sstefano_zampini 161523875855Sstefano_zampini ierr = PetscObjectTypeCompare((PetscObject)B,MATTRANSPOSEMAT,&istrans);CHKERRQ(ierr); 161623875855Sstefano_zampini if (istrans) { 161723875855Sstefano_zampini Mat Bt; 161823875855Sstefano_zampini 161923875855Sstefano_zampini ierr = MatTransposeGetMat(B,&Bt);CHKERRQ(ierr); 162023875855Sstefano_zampini ierr = MatTranspose(Bt,MAT_INITIAL_MATRIX,&trans[i*nest->nc+j]);CHKERRQ(ierr); 162123875855Sstefano_zampini B = trans[i*nest->nc+j]; 162223875855Sstefano_zampini } 1623b68353e5Sstefano_zampini ierr = MatGetRowIJ(B,0,PETSC_FALSE,PETSC_FALSE,&nnr,(const PetscInt**)&nii,(const PetscInt**)&njj,&done);CHKERRQ(ierr); 1624b68353e5Sstefano_zampini if (!done) SETERRQ(PetscObjectComm((PetscObject)B),PETSC_ERR_PLIB,"MatGetRowIJ"); 1625b68353e5Sstefano_zampini ierr = MatSeqAIJGetArray(B,&naa);CHKERRQ(ierr); 1626b68353e5Sstefano_zampini nnz += nii[nnr]; 1627b68353e5Sstefano_zampini 1628b68353e5Sstefano_zampini aii[i*nest->nc+j] = nii; 1629b68353e5Sstefano_zampini ajj[i*nest->nc+j] = njj; 1630b68353e5Sstefano_zampini avv[i*nest->nc+j] = naa; 1631b68353e5Sstefano_zampini } 1632b68353e5Sstefano_zampini } 1633b68353e5Sstefano_zampini } 1634b68353e5Sstefano_zampini if (reuse != MAT_REUSE_MATRIX) { 1635b68353e5Sstefano_zampini ierr = PetscMalloc1(nr+1,&ii);CHKERRQ(ierr); 1636b68353e5Sstefano_zampini ierr = PetscMalloc1(nnz,&jj);CHKERRQ(ierr); 1637b68353e5Sstefano_zampini ierr = PetscMalloc1(nnz,&vv);CHKERRQ(ierr); 1638b68353e5Sstefano_zampini } else { 1639b68353e5Sstefano_zampini if (nnz != ii[nr]) SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_USER,"Cannot reuse matrix, wrong number of nonzeros"); 1640b68353e5Sstefano_zampini } 1641b68353e5Sstefano_zampini 1642b68353e5Sstefano_zampini /* new row pointer */ 1643580bdb30SBarry Smith ierr = PetscArrayzero(ii,nr+1);CHKERRQ(ierr); 1644b68353e5Sstefano_zampini for (i=0; i<nest->nr; ++i) { 1645b68353e5Sstefano_zampini PetscInt ncr,rst; 1646b68353e5Sstefano_zampini 1647b68353e5Sstefano_zampini ierr = ISStrideGetInfo(nest->isglobal.row[i],&rst,NULL);CHKERRQ(ierr); 1648b68353e5Sstefano_zampini ierr = ISGetLocalSize(nest->isglobal.row[i],&ncr);CHKERRQ(ierr); 1649b68353e5Sstefano_zampini for (j=0; j<nest->nc; ++j) { 1650b68353e5Sstefano_zampini if (aii[i*nest->nc+j]) { 1651b68353e5Sstefano_zampini PetscInt *nii = aii[i*nest->nc+j]; 1652b68353e5Sstefano_zampini PetscInt ir; 1653b68353e5Sstefano_zampini 1654b68353e5Sstefano_zampini for (ir=rst; ir<ncr+rst; ++ir) { 1655b68353e5Sstefano_zampini ii[ir+1] += nii[1]-nii[0]; 1656b68353e5Sstefano_zampini nii++; 1657b68353e5Sstefano_zampini } 1658b68353e5Sstefano_zampini } 1659b68353e5Sstefano_zampini } 1660b68353e5Sstefano_zampini } 1661b68353e5Sstefano_zampini for (i=0; i<nr; i++) ii[i+1] += ii[i]; 1662b68353e5Sstefano_zampini 1663b68353e5Sstefano_zampini /* construct CSR for the new matrix */ 1664b68353e5Sstefano_zampini ierr = PetscCalloc1(nr,&ci);CHKERRQ(ierr); 1665b68353e5Sstefano_zampini for (i=0; i<nest->nr; ++i) { 1666b68353e5Sstefano_zampini PetscInt ncr,rst; 1667b68353e5Sstefano_zampini 1668b68353e5Sstefano_zampini ierr = ISStrideGetInfo(nest->isglobal.row[i],&rst,NULL);CHKERRQ(ierr); 1669b68353e5Sstefano_zampini ierr = ISGetLocalSize(nest->isglobal.row[i],&ncr);CHKERRQ(ierr); 1670b68353e5Sstefano_zampini for (j=0; j<nest->nc; ++j) { 1671b68353e5Sstefano_zampini if (aii[i*nest->nc+j]) { 1672b68353e5Sstefano_zampini PetscScalar *nvv = avv[i*nest->nc+j]; 1673b68353e5Sstefano_zampini PetscInt *nii = aii[i*nest->nc+j]; 1674b68353e5Sstefano_zampini PetscInt *njj = ajj[i*nest->nc+j]; 1675b68353e5Sstefano_zampini PetscInt ir,cst; 1676b68353e5Sstefano_zampini 1677b68353e5Sstefano_zampini ierr = ISStrideGetInfo(nest->isglobal.col[j],&cst,NULL);CHKERRQ(ierr); 1678b68353e5Sstefano_zampini for (ir=rst; ir<ncr+rst; ++ir) { 1679b68353e5Sstefano_zampini PetscInt ij,rsize = nii[1]-nii[0],ist = ii[ir]+ci[ir]; 1680b68353e5Sstefano_zampini 1681b68353e5Sstefano_zampini for (ij=0;ij<rsize;ij++) { 1682b68353e5Sstefano_zampini jj[ist+ij] = *njj+cst; 1683b68353e5Sstefano_zampini vv[ist+ij] = *nvv; 1684b68353e5Sstefano_zampini njj++; 1685b68353e5Sstefano_zampini nvv++; 1686b68353e5Sstefano_zampini } 1687b68353e5Sstefano_zampini ci[ir] += rsize; 1688b68353e5Sstefano_zampini nii++; 1689b68353e5Sstefano_zampini } 1690b68353e5Sstefano_zampini } 1691b68353e5Sstefano_zampini } 1692b68353e5Sstefano_zampini } 1693b68353e5Sstefano_zampini ierr = PetscFree(ci);CHKERRQ(ierr); 1694b68353e5Sstefano_zampini 1695b68353e5Sstefano_zampini /* restore info */ 1696b68353e5Sstefano_zampini for (i=0; i<nest->nr; ++i) { 1697b68353e5Sstefano_zampini for (j=0; j<nest->nc; ++j) { 1698b68353e5Sstefano_zampini Mat B = nest->m[i][j]; 1699b68353e5Sstefano_zampini if (B) { 1700b68353e5Sstefano_zampini PetscInt nnr = 0, k = i*nest->nc+j; 170123875855Sstefano_zampini 170223875855Sstefano_zampini B = (trans[k] ? trans[k] : B); 1703b68353e5Sstefano_zampini ierr = MatRestoreRowIJ(B,0,PETSC_FALSE,PETSC_FALSE,&nnr,(const PetscInt**)&aii[k],(const PetscInt**)&ajj[k],&done);CHKERRQ(ierr); 1704b68353e5Sstefano_zampini if (!done) SETERRQ(PetscObjectComm((PetscObject)B),PETSC_ERR_PLIB,"MatRestoreRowIJ"); 1705b68353e5Sstefano_zampini ierr = MatSeqAIJRestoreArray(B,&avv[k]);CHKERRQ(ierr); 170623875855Sstefano_zampini ierr = MatDestroy(&trans[k]);CHKERRQ(ierr); 1707b68353e5Sstefano_zampini } 1708b68353e5Sstefano_zampini } 1709b68353e5Sstefano_zampini } 171023875855Sstefano_zampini ierr = PetscFree4(aii,ajj,avv,trans);CHKERRQ(ierr); 1711b68353e5Sstefano_zampini 1712b68353e5Sstefano_zampini /* finalize newmat */ 1713b68353e5Sstefano_zampini if (reuse == MAT_INITIAL_MATRIX) { 1714b68353e5Sstefano_zampini ierr = MatCreateSeqAIJWithArrays(PetscObjectComm((PetscObject)A),nr,nc,ii,jj,vv,newmat);CHKERRQ(ierr); 1715b68353e5Sstefano_zampini } else if (reuse == MAT_INPLACE_MATRIX) { 1716b68353e5Sstefano_zampini Mat B; 1717b68353e5Sstefano_zampini 1718b68353e5Sstefano_zampini ierr = MatCreateSeqAIJWithArrays(PetscObjectComm((PetscObject)A),nr,nc,ii,jj,vv,&B);CHKERRQ(ierr); 1719b68353e5Sstefano_zampini ierr = MatHeaderReplace(A,&B);CHKERRQ(ierr); 1720b68353e5Sstefano_zampini } 1721b68353e5Sstefano_zampini ierr = MatAssemblyBegin(*newmat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 1722b68353e5Sstefano_zampini ierr = MatAssemblyEnd(*newmat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 1723b68353e5Sstefano_zampini { 1724b68353e5Sstefano_zampini Mat_SeqAIJ *a = (Mat_SeqAIJ*)((*newmat)->data); 1725b68353e5Sstefano_zampini a->free_a = PETSC_TRUE; 1726b68353e5Sstefano_zampini a->free_ij = PETSC_TRUE; 1727b68353e5Sstefano_zampini } 1728b68353e5Sstefano_zampini PetscFunctionReturn(0); 1729b68353e5Sstefano_zampini } 1730b68353e5Sstefano_zampini 1731cc2e6a90SBarry Smith PETSC_INTERN PetscErrorCode MatConvert_Nest_AIJ(Mat A,MatType newtype,MatReuse reuse,Mat *newmat) 1732629c3df2SDmitry Karpeev { 1733629c3df2SDmitry Karpeev PetscErrorCode ierr; 1734629c3df2SDmitry Karpeev Mat_Nest *nest = (Mat_Nest*)A->data; 173583b1a929SMark Adams PetscInt m,n,M,N,i,j,k,*dnnz,*onnz,rstart; 1736649b366bSFande Kong PetscInt cstart,cend; 1737b68353e5Sstefano_zampini PetscMPIInt size; 1738629c3df2SDmitry Karpeev Mat C; 1739629c3df2SDmitry Karpeev 1740629c3df2SDmitry Karpeev PetscFunctionBegin; 1741b68353e5Sstefano_zampini ierr = MPI_Comm_size(PetscObjectComm((PetscObject)A),&size);CHKERRQ(ierr); 1742b68353e5Sstefano_zampini if (size == 1) { /* look for a special case with SeqAIJ matrices and strided-1, contiguous, blocks */ 1743b68353e5Sstefano_zampini PetscInt nf; 1744b68353e5Sstefano_zampini PetscBool fast; 1745b68353e5Sstefano_zampini 1746b68353e5Sstefano_zampini ierr = PetscStrcmp(newtype,MATAIJ,&fast);CHKERRQ(ierr); 1747b68353e5Sstefano_zampini if (!fast) { 1748b68353e5Sstefano_zampini ierr = PetscStrcmp(newtype,MATSEQAIJ,&fast);CHKERRQ(ierr); 1749b68353e5Sstefano_zampini } 1750b68353e5Sstefano_zampini for (i=0; i<nest->nr && fast; ++i) { 1751b68353e5Sstefano_zampini for (j=0; j<nest->nc && fast; ++j) { 1752b68353e5Sstefano_zampini Mat B = nest->m[i][j]; 1753b68353e5Sstefano_zampini if (B) { 1754b68353e5Sstefano_zampini ierr = PetscObjectTypeCompare((PetscObject)B,MATSEQAIJ,&fast);CHKERRQ(ierr); 175523875855Sstefano_zampini if (!fast) { 175623875855Sstefano_zampini PetscBool istrans; 175723875855Sstefano_zampini 175823875855Sstefano_zampini ierr = PetscObjectTypeCompare((PetscObject)B,MATTRANSPOSEMAT,&istrans);CHKERRQ(ierr); 175923875855Sstefano_zampini if (istrans) { 176023875855Sstefano_zampini Mat Bt; 176123875855Sstefano_zampini 176223875855Sstefano_zampini ierr = MatTransposeGetMat(B,&Bt);CHKERRQ(ierr); 176323875855Sstefano_zampini ierr = PetscObjectTypeCompare((PetscObject)Bt,MATSEQAIJ,&fast);CHKERRQ(ierr); 176423875855Sstefano_zampini } 1765b68353e5Sstefano_zampini } 1766b68353e5Sstefano_zampini } 1767b68353e5Sstefano_zampini } 1768b68353e5Sstefano_zampini } 1769b68353e5Sstefano_zampini for (i=0, nf=0; i<nest->nr && fast; ++i) { 1770b68353e5Sstefano_zampini ierr = PetscObjectTypeCompare((PetscObject)nest->isglobal.row[i],ISSTRIDE,&fast);CHKERRQ(ierr); 1771b68353e5Sstefano_zampini if (fast) { 1772b68353e5Sstefano_zampini PetscInt f,s; 1773b68353e5Sstefano_zampini 1774b68353e5Sstefano_zampini ierr = ISStrideGetInfo(nest->isglobal.row[i],&f,&s);CHKERRQ(ierr); 1775b68353e5Sstefano_zampini if (f != nf || s != 1) { fast = PETSC_FALSE; } 1776b68353e5Sstefano_zampini else { 1777b68353e5Sstefano_zampini ierr = ISGetSize(nest->isglobal.row[i],&f);CHKERRQ(ierr); 1778b68353e5Sstefano_zampini nf += f; 1779b68353e5Sstefano_zampini } 1780b68353e5Sstefano_zampini } 1781b68353e5Sstefano_zampini } 1782b68353e5Sstefano_zampini for (i=0, nf=0; i<nest->nc && fast; ++i) { 1783b68353e5Sstefano_zampini ierr = PetscObjectTypeCompare((PetscObject)nest->isglobal.col[i],ISSTRIDE,&fast);CHKERRQ(ierr); 1784b68353e5Sstefano_zampini if (fast) { 1785b68353e5Sstefano_zampini PetscInt f,s; 1786b68353e5Sstefano_zampini 1787b68353e5Sstefano_zampini ierr = ISStrideGetInfo(nest->isglobal.col[i],&f,&s);CHKERRQ(ierr); 1788b68353e5Sstefano_zampini if (f != nf || s != 1) { fast = PETSC_FALSE; } 1789b68353e5Sstefano_zampini else { 1790b68353e5Sstefano_zampini ierr = ISGetSize(nest->isglobal.col[i],&f);CHKERRQ(ierr); 1791b68353e5Sstefano_zampini nf += f; 1792b68353e5Sstefano_zampini } 1793b68353e5Sstefano_zampini } 1794b68353e5Sstefano_zampini } 1795b68353e5Sstefano_zampini if (fast) { 1796b68353e5Sstefano_zampini ierr = MatConvert_Nest_SeqAIJ_fast(A,newtype,reuse,newmat);CHKERRQ(ierr); 1797b68353e5Sstefano_zampini PetscFunctionReturn(0); 1798b68353e5Sstefano_zampini } 1799b68353e5Sstefano_zampini } 1800629c3df2SDmitry Karpeev ierr = MatGetSize(A,&M,&N);CHKERRQ(ierr); 1801629c3df2SDmitry Karpeev ierr = MatGetLocalSize(A,&m,&n);CHKERRQ(ierr); 1802649b366bSFande Kong ierr = MatGetOwnershipRangeColumn(A,&cstart,&cend);CHKERRQ(ierr); 1803629c3df2SDmitry Karpeev switch (reuse) { 1804629c3df2SDmitry Karpeev case MAT_INITIAL_MATRIX: 1805ce94432eSBarry Smith ierr = MatCreate(PetscObjectComm((PetscObject)A),&C);CHKERRQ(ierr); 1806629c3df2SDmitry Karpeev ierr = MatSetType(C,newtype);CHKERRQ(ierr); 1807629c3df2SDmitry Karpeev ierr = MatSetSizes(C,m,n,M,N);CHKERRQ(ierr); 1808629c3df2SDmitry Karpeev *newmat = C; 1809629c3df2SDmitry Karpeev break; 1810629c3df2SDmitry Karpeev case MAT_REUSE_MATRIX: 1811629c3df2SDmitry Karpeev C = *newmat; 1812629c3df2SDmitry Karpeev break; 1813ce94432eSBarry Smith default: SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_SUP,"MatReuse"); 1814629c3df2SDmitry Karpeev } 1815785e854fSJed Brown ierr = PetscMalloc1(2*m,&dnnz);CHKERRQ(ierr); 1816629c3df2SDmitry Karpeev onnz = dnnz + m; 1817629c3df2SDmitry Karpeev for (k=0; k<m; k++) { 1818629c3df2SDmitry Karpeev dnnz[k] = 0; 1819629c3df2SDmitry Karpeev onnz[k] = 0; 1820629c3df2SDmitry Karpeev } 1821629c3df2SDmitry Karpeev for (j=0; j<nest->nc; ++j) { 1822629c3df2SDmitry Karpeev IS bNis; 1823629c3df2SDmitry Karpeev PetscInt bN; 1824629c3df2SDmitry Karpeev const PetscInt *bNindices; 1825629c3df2SDmitry Karpeev /* Using global column indices and ISAllGather() is not scalable. */ 1826629c3df2SDmitry Karpeev ierr = ISAllGather(nest->isglobal.col[j], &bNis);CHKERRQ(ierr); 1827629c3df2SDmitry Karpeev ierr = ISGetSize(bNis, &bN);CHKERRQ(ierr); 1828629c3df2SDmitry Karpeev ierr = ISGetIndices(bNis,&bNindices);CHKERRQ(ierr); 1829629c3df2SDmitry Karpeev for (i=0; i<nest->nr; ++i) { 1830629c3df2SDmitry Karpeev PetscSF bmsf; 1831649b366bSFande Kong PetscSFNode *iremote; 1832629c3df2SDmitry Karpeev Mat B; 1833649b366bSFande Kong PetscInt bm, *sub_dnnz,*sub_onnz, br; 1834629c3df2SDmitry Karpeev const PetscInt *bmindices; 1835629c3df2SDmitry Karpeev B = nest->m[i][j]; 1836629c3df2SDmitry Karpeev if (!B) continue; 1837629c3df2SDmitry Karpeev ierr = ISGetLocalSize(nest->isglobal.row[i],&bm);CHKERRQ(ierr); 1838629c3df2SDmitry Karpeev ierr = ISGetIndices(nest->isglobal.row[i],&bmindices);CHKERRQ(ierr); 1839ce94432eSBarry Smith ierr = PetscSFCreate(PetscObjectComm((PetscObject)A), &bmsf);CHKERRQ(ierr); 1840649b366bSFande Kong ierr = PetscMalloc1(bm,&iremote);CHKERRQ(ierr); 1841649b366bSFande Kong ierr = PetscMalloc1(bm,&sub_dnnz);CHKERRQ(ierr); 1842649b366bSFande Kong ierr = PetscMalloc1(bm,&sub_onnz);CHKERRQ(ierr); 1843649b366bSFande Kong for (k = 0; k < bm; ++k){ 1844649b366bSFande Kong sub_dnnz[k] = 0; 1845649b366bSFande Kong sub_onnz[k] = 0; 1846649b366bSFande Kong } 1847629c3df2SDmitry Karpeev /* 1848629c3df2SDmitry Karpeev Locate the owners for all of the locally-owned global row indices for this row block. 1849629c3df2SDmitry Karpeev These determine the roots of PetscSF used to communicate preallocation data to row owners. 1850629c3df2SDmitry Karpeev The roots correspond to the dnnz and onnz entries; thus, there are two roots per row. 1851629c3df2SDmitry Karpeev */ 185283b1a929SMark Adams ierr = MatGetOwnershipRange(B,&rstart,NULL);CHKERRQ(ierr); 1853629c3df2SDmitry Karpeev for (br = 0; br < bm; ++br) { 1854*131c27b5Sprj- PetscInt row = bmindices[br], brncols, col; 1855629c3df2SDmitry Karpeev const PetscInt *brcols; 1856a4b3d3acSMatthew G Knepley PetscInt rowrel = 0; /* row's relative index on its owner rank */ 1857*131c27b5Sprj- PetscMPIInt rowowner = 0; 1858629c3df2SDmitry Karpeev ierr = PetscLayoutFindOwnerIndex(A->rmap,row,&rowowner,&rowrel);CHKERRQ(ierr); 1859649b366bSFande Kong /* how many roots */ 1860649b366bSFande Kong iremote[br].rank = rowowner; iremote[br].index = rowrel; /* edge from bmdnnz to dnnz */ 1861649b366bSFande Kong /* get nonzero pattern */ 186283b1a929SMark Adams ierr = MatGetRow(B,br+rstart,&brncols,&brcols,NULL);CHKERRQ(ierr); 1863629c3df2SDmitry Karpeev for (k=0; k<brncols; k++) { 1864629c3df2SDmitry Karpeev col = bNindices[brcols[k]]; 1865649b366bSFande Kong if (col>=A->cmap->range[rowowner] && col<A->cmap->range[rowowner+1]) { 1866649b366bSFande Kong sub_dnnz[br]++; 1867649b366bSFande Kong } else { 1868649b366bSFande Kong sub_onnz[br]++; 1869649b366bSFande Kong } 1870629c3df2SDmitry Karpeev } 187183b1a929SMark Adams ierr = MatRestoreRow(B,br+rstart,&brncols,&brcols,NULL);CHKERRQ(ierr); 1872629c3df2SDmitry Karpeev } 1873629c3df2SDmitry Karpeev ierr = ISRestoreIndices(nest->isglobal.row[i],&bmindices);CHKERRQ(ierr); 1874629c3df2SDmitry Karpeev /* bsf will have to take care of disposing of bedges. */ 1875649b366bSFande Kong ierr = PetscSFSetGraph(bmsf,m,bm,NULL,PETSC_OWN_POINTER,iremote,PETSC_OWN_POINTER);CHKERRQ(ierr); 1876649b366bSFande Kong ierr = PetscSFReduceBegin(bmsf,MPIU_INT,sub_dnnz,dnnz,MPI_SUM);CHKERRQ(ierr); 1877649b366bSFande Kong ierr = PetscSFReduceEnd(bmsf,MPIU_INT,sub_dnnz,dnnz,MPI_SUM);CHKERRQ(ierr); 1878649b366bSFande Kong ierr = PetscSFReduceBegin(bmsf,MPIU_INT,sub_onnz,onnz,MPI_SUM);CHKERRQ(ierr); 1879649b366bSFande Kong ierr = PetscSFReduceEnd(bmsf,MPIU_INT,sub_onnz,onnz,MPI_SUM);CHKERRQ(ierr); 1880649b366bSFande Kong ierr = PetscFree(sub_dnnz);CHKERRQ(ierr); 1881649b366bSFande Kong ierr = PetscFree(sub_onnz);CHKERRQ(ierr); 1882629c3df2SDmitry Karpeev ierr = PetscSFDestroy(&bmsf);CHKERRQ(ierr); 1883629c3df2SDmitry Karpeev } 188422d28d08SBarry Smith ierr = ISRestoreIndices(bNis,&bNindices);CHKERRQ(ierr); 1885629c3df2SDmitry Karpeev ierr = ISDestroy(&bNis);CHKERRQ(ierr); 188665a4a0a3Sstefano_zampini } 188765a4a0a3Sstefano_zampini /* Resize preallocation if overestimated */ 188865a4a0a3Sstefano_zampini for (i=0;i<m;i++) { 188965a4a0a3Sstefano_zampini dnnz[i] = PetscMin(dnnz[i],A->cmap->n); 189065a4a0a3Sstefano_zampini onnz[i] = PetscMin(onnz[i],A->cmap->N - A->cmap->n); 1891629c3df2SDmitry Karpeev } 1892629c3df2SDmitry Karpeev ierr = MatSeqAIJSetPreallocation(C,0,dnnz);CHKERRQ(ierr); 1893629c3df2SDmitry Karpeev ierr = MatMPIAIJSetPreallocation(C,0,dnnz,0,onnz);CHKERRQ(ierr); 1894629c3df2SDmitry Karpeev ierr = PetscFree(dnnz);CHKERRQ(ierr); 1895629c3df2SDmitry Karpeev 1896629c3df2SDmitry Karpeev /* Fill by row */ 1897629c3df2SDmitry Karpeev for (j=0; j<nest->nc; ++j) { 1898629c3df2SDmitry Karpeev /* Using global column indices and ISAllGather() is not scalable. */ 1899629c3df2SDmitry Karpeev IS bNis; 1900629c3df2SDmitry Karpeev PetscInt bN; 1901629c3df2SDmitry Karpeev const PetscInt *bNindices; 1902629c3df2SDmitry Karpeev ierr = ISAllGather(nest->isglobal.col[j], &bNis);CHKERRQ(ierr); 1903629c3df2SDmitry Karpeev ierr = ISGetSize(bNis,&bN);CHKERRQ(ierr); 1904629c3df2SDmitry Karpeev ierr = ISGetIndices(bNis,&bNindices);CHKERRQ(ierr); 1905629c3df2SDmitry Karpeev for (i=0; i<nest->nr; ++i) { 1906629c3df2SDmitry Karpeev Mat B; 1907629c3df2SDmitry Karpeev PetscInt bm, br; 1908629c3df2SDmitry Karpeev const PetscInt *bmindices; 1909629c3df2SDmitry Karpeev B = nest->m[i][j]; 1910629c3df2SDmitry Karpeev if (!B) continue; 1911629c3df2SDmitry Karpeev ierr = ISGetLocalSize(nest->isglobal.row[i],&bm);CHKERRQ(ierr); 1912629c3df2SDmitry Karpeev ierr = ISGetIndices(nest->isglobal.row[i],&bmindices);CHKERRQ(ierr); 191383b1a929SMark Adams ierr = MatGetOwnershipRange(B,&rstart,NULL);CHKERRQ(ierr); 1914629c3df2SDmitry Karpeev for (br = 0; br < bm; ++br) { 1915629c3df2SDmitry Karpeev PetscInt row = bmindices[br], brncols, *cols; 1916629c3df2SDmitry Karpeev const PetscInt *brcols; 1917629c3df2SDmitry Karpeev const PetscScalar *brcoldata; 191883b1a929SMark Adams ierr = MatGetRow(B,br+rstart,&brncols,&brcols,&brcoldata);CHKERRQ(ierr); 1919785e854fSJed Brown ierr = PetscMalloc1(brncols,&cols);CHKERRQ(ierr); 192026fbe8dcSKarl Rupp for (k=0; k<brncols; k++) cols[k] = bNindices[brcols[k]]; 1921629c3df2SDmitry Karpeev /* 1922629c3df2SDmitry Karpeev Nest blocks are required to be nonoverlapping -- otherwise nest and monolithic index layouts wouldn't match. 1923629c3df2SDmitry Karpeev Thus, we could use INSERT_VALUES, but I prefer ADD_VALUES. 1924629c3df2SDmitry Karpeev */ 1925a2ea699eSBarry Smith ierr = MatSetValues(C,1,&row,brncols,cols,brcoldata,ADD_VALUES);CHKERRQ(ierr); 192683b1a929SMark Adams ierr = MatRestoreRow(B,br+rstart,&brncols,&brcols,&brcoldata);CHKERRQ(ierr); 1927629c3df2SDmitry Karpeev ierr = PetscFree(cols);CHKERRQ(ierr); 1928629c3df2SDmitry Karpeev } 1929629c3df2SDmitry Karpeev ierr = ISRestoreIndices(nest->isglobal.row[i],&bmindices);CHKERRQ(ierr); 1930629c3df2SDmitry Karpeev } 1931a2ea699eSBarry Smith ierr = ISRestoreIndices(bNis,&bNindices);CHKERRQ(ierr); 1932629c3df2SDmitry Karpeev ierr = ISDestroy(&bNis);CHKERRQ(ierr); 1933629c3df2SDmitry Karpeev } 1934629c3df2SDmitry Karpeev ierr = MatAssemblyBegin(C,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 1935629c3df2SDmitry Karpeev ierr = MatAssemblyEnd(C,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 1936629c3df2SDmitry Karpeev PetscFunctionReturn(0); 1937629c3df2SDmitry Karpeev } 1938629c3df2SDmitry Karpeev 19398b7d3b4bSBarry Smith PetscErrorCode MatHasOperation_Nest(Mat mat,MatOperation op,PetscBool *has) 19408b7d3b4bSBarry Smith { 19418b7d3b4bSBarry Smith Mat_Nest *bA = (Mat_Nest*)mat->data; 19428b7d3b4bSBarry Smith PetscInt i,j,nr = bA->nr,nc = bA->nc; 19438b7d3b4bSBarry Smith PetscBool flg; 194452c5f739Sprj- PetscErrorCode ierr; 194552c5f739Sprj- PetscFunctionBegin; 19468b7d3b4bSBarry Smith 194752c5f739Sprj- *has = PETSC_FALSE; 194852c5f739Sprj- if (op == MATOP_MULT_TRANSPOSE || op == MATOP_MAT_MULT) { 19498b7d3b4bSBarry Smith for (j=0; j<nc; j++) { 19508b7d3b4bSBarry Smith for (i=0; i<nr; i++) { 19518b7d3b4bSBarry Smith if (!bA->m[i][j]) continue; 195252c5f739Sprj- ierr = MatHasOperation(bA->m[i][j],op,&flg);CHKERRQ(ierr); 19538b7d3b4bSBarry Smith if (!flg) PetscFunctionReturn(0); 19548b7d3b4bSBarry Smith } 19558b7d3b4bSBarry Smith } 19568b7d3b4bSBarry Smith } 195752c5f739Sprj- if (((void**)mat->ops)[op] || (op == MATOP_MAT_MULT && flg)) *has = PETSC_TRUE; 19588b7d3b4bSBarry Smith PetscFunctionReturn(0); 19598b7d3b4bSBarry Smith } 19608b7d3b4bSBarry Smith 1961659c6bb0SJed Brown /*MC 1962659c6bb0SJed Brown MATNEST - MATNEST = "nest" - Matrix type consisting of nested submatrices, each stored separately. 1963659c6bb0SJed Brown 1964659c6bb0SJed Brown Level: intermediate 1965659c6bb0SJed Brown 1966659c6bb0SJed Brown Notes: 1967659c6bb0SJed Brown This matrix type permits scalable use of PCFieldSplit and avoids the large memory costs of extracting submatrices. 1968659c6bb0SJed Brown It allows the use of symmetric and block formats for parts of multi-physics simulations. 1969950540a4SJed Brown It is usually used with DMComposite and DMCreateMatrix() 1970659c6bb0SJed Brown 19718b7d3b4bSBarry Smith Each of the submatrices lives on the same MPI communicator as the original nest matrix (though they can have zero 19728b7d3b4bSBarry Smith rows/columns on some processes.) Thus this is not meant for cases where the submatrices live on far fewer processes 19738b7d3b4bSBarry Smith than the nest matrix. 19748b7d3b4bSBarry Smith 1975659c6bb0SJed Brown .seealso: MatCreate(), MatType, MatCreateNest() 1976659c6bb0SJed Brown M*/ 19778cc058d9SJed Brown PETSC_EXTERN PetscErrorCode MatCreate_Nest(Mat A) 1978c8883902SJed Brown { 1979c8883902SJed Brown Mat_Nest *s; 1980c8883902SJed Brown PetscErrorCode ierr; 1981c8883902SJed Brown 1982c8883902SJed Brown PetscFunctionBegin; 1983b00a9115SJed Brown ierr = PetscNewLog(A,&s);CHKERRQ(ierr); 1984c8883902SJed Brown A->data = (void*)s; 1985e7c19651SJed Brown 1986e7c19651SJed Brown s->nr = -1; 1987e7c19651SJed Brown s->nc = -1; 19880298fd71SBarry Smith s->m = NULL; 1989e7c19651SJed Brown s->splitassembly = PETSC_FALSE; 1990c8883902SJed Brown 1991c8883902SJed Brown ierr = PetscMemzero(A->ops,sizeof(*A->ops));CHKERRQ(ierr); 199226fbe8dcSKarl Rupp 1993c8883902SJed Brown A->ops->mult = MatMult_Nest; 19949194d70fSJed Brown A->ops->multadd = MatMultAdd_Nest; 1995c8883902SJed Brown A->ops->multtranspose = MatMultTranspose_Nest; 19969194d70fSJed Brown A->ops->multtransposeadd = MatMultTransposeAdd_Nest; 1997f8170845SAlex Fikl A->ops->transpose = MatTranspose_Nest; 1998c8883902SJed Brown A->ops->assemblybegin = MatAssemblyBegin_Nest; 1999c8883902SJed Brown A->ops->assemblyend = MatAssemblyEnd_Nest; 2000c8883902SJed Brown A->ops->zeroentries = MatZeroEntries_Nest; 2001c222c20dSDavid Ham A->ops->copy = MatCopy_Nest; 20026e76ffeaSPierre Jolivet A->ops->axpy = MatAXPY_Nest; 2003c8883902SJed Brown A->ops->duplicate = MatDuplicate_Nest; 20047dae84e0SHong Zhang A->ops->createsubmatrix = MatCreateSubMatrix_Nest; 2005c8883902SJed Brown A->ops->destroy = MatDestroy_Nest; 2006c8883902SJed Brown A->ops->view = MatView_Nest; 2007c8883902SJed Brown A->ops->getvecs = 0; /* Use VECNEST by calling MatNestSetVecType(A,VECNEST) */ 2008c8883902SJed Brown A->ops->getlocalsubmatrix = MatGetLocalSubMatrix_Nest; 2009c8883902SJed Brown A->ops->restorelocalsubmatrix = MatRestoreLocalSubMatrix_Nest; 2010429bac76SJed Brown A->ops->getdiagonal = MatGetDiagonal_Nest; 2011429bac76SJed Brown A->ops->diagonalscale = MatDiagonalScale_Nest; 2012a061e289SJed Brown A->ops->scale = MatScale_Nest; 2013a061e289SJed Brown A->ops->shift = MatShift_Nest; 201413135bc6SAlex Fikl A->ops->diagonalset = MatDiagonalSet_Nest; 2015f8170845SAlex Fikl A->ops->setrandom = MatSetRandom_Nest; 20168b7d3b4bSBarry Smith A->ops->hasoperation = MatHasOperation_Nest; 2017c8883902SJed Brown 2018c8883902SJed Brown A->spptr = 0; 2019c8883902SJed Brown A->assembled = PETSC_FALSE; 2020c8883902SJed Brown 2021c8883902SJed Brown /* expose Nest api's */ 2022bdf89e91SBarry Smith ierr = PetscObjectComposeFunction((PetscObject)A,"MatNestGetSubMat_C", MatNestGetSubMat_Nest);CHKERRQ(ierr); 2023bdf89e91SBarry Smith ierr = PetscObjectComposeFunction((PetscObject)A,"MatNestSetSubMat_C", MatNestSetSubMat_Nest);CHKERRQ(ierr); 2024bdf89e91SBarry Smith ierr = PetscObjectComposeFunction((PetscObject)A,"MatNestGetSubMats_C", MatNestGetSubMats_Nest);CHKERRQ(ierr); 2025bdf89e91SBarry Smith ierr = PetscObjectComposeFunction((PetscObject)A,"MatNestGetSize_C", MatNestGetSize_Nest);CHKERRQ(ierr); 2026bdf89e91SBarry Smith ierr = PetscObjectComposeFunction((PetscObject)A,"MatNestGetISs_C", MatNestGetISs_Nest);CHKERRQ(ierr); 2027bdf89e91SBarry Smith ierr = PetscObjectComposeFunction((PetscObject)A,"MatNestGetLocalISs_C", MatNestGetLocalISs_Nest);CHKERRQ(ierr); 2028bdf89e91SBarry Smith ierr = PetscObjectComposeFunction((PetscObject)A,"MatNestSetVecType_C", MatNestSetVecType_Nest);CHKERRQ(ierr); 2029bdf89e91SBarry Smith ierr = PetscObjectComposeFunction((PetscObject)A,"MatNestSetSubMats_C", MatNestSetSubMats_Nest);CHKERRQ(ierr); 20300899c546SStefano Zampini ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_nest_mpiaij_C", MatConvert_Nest_AIJ);CHKERRQ(ierr); 20310899c546SStefano Zampini ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_nest_seqaij_C", MatConvert_Nest_AIJ);CHKERRQ(ierr); 203283b1a929SMark Adams ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_nest_aij_C", MatConvert_Nest_AIJ);CHKERRQ(ierr); 20335e3038f0Sstefano_zampini ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_nest_is_C", MatConvert_Nest_IS);CHKERRQ(ierr); 203452c5f739Sprj- ierr = PetscObjectComposeFunction((PetscObject)A,"MatMatMult_nest_mpidense_C",MatMatMult_Nest_Dense);CHKERRQ(ierr); 203552c5f739Sprj- ierr = PetscObjectComposeFunction((PetscObject)A,"MatMatMult_nest_seqdense_C",MatMatMult_Nest_Dense);CHKERRQ(ierr); 203652c5f739Sprj- ierr = PetscObjectComposeFunction((PetscObject)A,"MatMatMult_nest_dense_C", MatMatMult_Nest_Dense);CHKERRQ(ierr); 2037c8883902SJed Brown 2038c8883902SJed Brown ierr = PetscObjectChangeTypeName((PetscObject)A,MATNEST);CHKERRQ(ierr); 2039c8883902SJed Brown PetscFunctionReturn(0); 2040c8883902SJed Brown } 2041