1aaa7dc30SBarry Smith #include <../src/mat/impls/nest/matnestimpl.h> /*I "petscmat.h" I*/ 2b68353e5Sstefano_zampini #include <../src/mat/impls/aij/seq/aij.h> 30c312b8eSJed Brown #include <petscsf.h> 4d8588912SDave May 5c8883902SJed Brown static PetscErrorCode MatSetUp_NestIS_Private(Mat,PetscInt,const IS[],PetscInt,const IS[]); 606a1af2fSStefano Zampini static PetscErrorCode MatCreateVecs_Nest(Mat,Vec*,Vec*); 706a1af2fSStefano Zampini static PetscErrorCode MatReset_Nest(Mat); 806a1af2fSStefano Zampini 95e3038f0Sstefano_zampini PETSC_INTERN PetscErrorCode MatConvert_Nest_IS(Mat,MatType,MatReuse,Mat*); 10c8883902SJed Brown 11d8588912SDave May /* private functions */ 128188e55aSJed Brown static PetscErrorCode MatNestGetSizes_Private(Mat A,PetscInt *m,PetscInt *n,PetscInt *M,PetscInt *N) 13d8588912SDave May { 14d8588912SDave May Mat_Nest *bA = (Mat_Nest*)A->data; 158188e55aSJed Brown PetscInt i,j; 16d8588912SDave May PetscErrorCode ierr; 17d8588912SDave May 18d8588912SDave May PetscFunctionBegin; 198188e55aSJed Brown *m = *n = *M = *N = 0; 208188e55aSJed Brown for (i=0; i<bA->nr; i++) { /* rows */ 218188e55aSJed Brown PetscInt sm,sM; 228188e55aSJed Brown ierr = ISGetLocalSize(bA->isglobal.row[i],&sm);CHKERRQ(ierr); 238188e55aSJed Brown ierr = ISGetSize(bA->isglobal.row[i],&sM);CHKERRQ(ierr); 248188e55aSJed Brown *m += sm; 258188e55aSJed Brown *M += sM; 26d8588912SDave May } 278188e55aSJed Brown for (j=0; j<bA->nc; j++) { /* cols */ 288188e55aSJed Brown PetscInt sn,sN; 298188e55aSJed Brown ierr = ISGetLocalSize(bA->isglobal.col[j],&sn);CHKERRQ(ierr); 308188e55aSJed Brown ierr = ISGetSize(bA->isglobal.col[j],&sN);CHKERRQ(ierr); 318188e55aSJed Brown *n += sn; 328188e55aSJed Brown *N += sN; 33d8588912SDave May } 34d8588912SDave May PetscFunctionReturn(0); 35d8588912SDave May } 36d8588912SDave May 37d8588912SDave May /* operations */ 38207556f9SJed Brown static PetscErrorCode MatMult_Nest(Mat A,Vec x,Vec y) 39d8588912SDave May { 40d8588912SDave May Mat_Nest *bA = (Mat_Nest*)A->data; 41207556f9SJed Brown Vec *bx = bA->right,*by = bA->left; 42207556f9SJed Brown PetscInt i,j,nr = bA->nr,nc = bA->nc; 43d8588912SDave May PetscErrorCode ierr; 44d8588912SDave May 45d8588912SDave May PetscFunctionBegin; 46207556f9SJed Brown for (i=0; i<nr; i++) {ierr = VecGetSubVector(y,bA->isglobal.row[i],&by[i]);CHKERRQ(ierr);} 47207556f9SJed Brown for (i=0; i<nc; i++) {ierr = VecGetSubVector(x,bA->isglobal.col[i],&bx[i]);CHKERRQ(ierr);} 48207556f9SJed Brown for (i=0; i<nr; i++) { 49d8588912SDave May ierr = VecZeroEntries(by[i]);CHKERRQ(ierr); 50207556f9SJed Brown for (j=0; j<nc; j++) { 51207556f9SJed Brown if (!bA->m[i][j]) continue; 52d8588912SDave May /* y[i] <- y[i] + A[i][j] * x[j] */ 53d8588912SDave May ierr = MatMultAdd(bA->m[i][j],bx[j],by[i],by[i]);CHKERRQ(ierr); 54d8588912SDave May } 55d8588912SDave May } 56207556f9SJed Brown for (i=0; i<nr; i++) {ierr = VecRestoreSubVector(y,bA->isglobal.row[i],&by[i]);CHKERRQ(ierr);} 57207556f9SJed Brown for (i=0; i<nc; i++) {ierr = VecRestoreSubVector(x,bA->isglobal.col[i],&bx[i]);CHKERRQ(ierr);} 58d8588912SDave May PetscFunctionReturn(0); 59d8588912SDave May } 60d8588912SDave May 619194d70fSJed Brown static PetscErrorCode MatMultAdd_Nest(Mat A,Vec x,Vec y,Vec z) 629194d70fSJed Brown { 639194d70fSJed Brown Mat_Nest *bA = (Mat_Nest*)A->data; 649194d70fSJed Brown Vec *bx = bA->right,*bz = bA->left; 659194d70fSJed Brown PetscInt i,j,nr = bA->nr,nc = bA->nc; 669194d70fSJed Brown PetscErrorCode ierr; 679194d70fSJed Brown 689194d70fSJed Brown PetscFunctionBegin; 699194d70fSJed Brown for (i=0; i<nr; i++) {ierr = VecGetSubVector(z,bA->isglobal.row[i],&bz[i]);CHKERRQ(ierr);} 709194d70fSJed Brown for (i=0; i<nc; i++) {ierr = VecGetSubVector(x,bA->isglobal.col[i],&bx[i]);CHKERRQ(ierr);} 719194d70fSJed Brown for (i=0; i<nr; i++) { 729194d70fSJed Brown if (y != z) { 739194d70fSJed Brown Vec by; 749194d70fSJed Brown ierr = VecGetSubVector(y,bA->isglobal.row[i],&by);CHKERRQ(ierr); 759194d70fSJed Brown ierr = VecCopy(by,bz[i]);CHKERRQ(ierr); 76336d21e7SJed Brown ierr = VecRestoreSubVector(y,bA->isglobal.row[i],&by);CHKERRQ(ierr); 779194d70fSJed Brown } 789194d70fSJed Brown for (j=0; j<nc; j++) { 799194d70fSJed Brown if (!bA->m[i][j]) continue; 809194d70fSJed Brown /* y[i] <- y[i] + A[i][j] * x[j] */ 819194d70fSJed Brown ierr = MatMultAdd(bA->m[i][j],bx[j],bz[i],bz[i]);CHKERRQ(ierr); 829194d70fSJed Brown } 839194d70fSJed Brown } 849194d70fSJed Brown for (i=0; i<nr; i++) {ierr = VecRestoreSubVector(z,bA->isglobal.row[i],&bz[i]);CHKERRQ(ierr);} 859194d70fSJed Brown for (i=0; i<nc; i++) {ierr = VecRestoreSubVector(x,bA->isglobal.col[i],&bx[i]);CHKERRQ(ierr);} 869194d70fSJed Brown PetscFunctionReturn(0); 879194d70fSJed Brown } 889194d70fSJed Brown 8952c5f739Sprj- typedef struct { 9052c5f739Sprj- Mat *workC; /* array of Mat with specific containers depending on the underlying MatMatMult implementation */ 9152c5f739Sprj- PetscScalar *tarray; /* buffer for storing all temporary products A[i][j] B[j] */ 9252c5f739Sprj- PetscInt *dm,*dn,k; /* displacements and number of submatrices */ 9352c5f739Sprj- } Nest_Dense; 9452c5f739Sprj- 9552c5f739Sprj- PETSC_INTERN PetscErrorCode MatMatMultNumeric_Nest_Dense(Mat A,Mat B,Mat C) 9652c5f739Sprj- { 9752c5f739Sprj- Mat_Nest *bA = (Mat_Nest*)A->data; 9852c5f739Sprj- PetscContainer container; 9952c5f739Sprj- Nest_Dense *contents; 10052c5f739Sprj- Mat viewB,viewC,seq; 10152c5f739Sprj- const PetscScalar *barray; 10252c5f739Sprj- PetscScalar *carray; 10352c5f739Sprj- PetscInt i,j,M,N,nr = bA->nr,nc = bA->nc,ldb,ldc; 10452c5f739Sprj- PetscErrorCode ierr; 10552c5f739Sprj- 10652c5f739Sprj- PetscFunctionBegin; 10752c5f739Sprj- ierr = PetscObjectQuery((PetscObject)C,"workC",(PetscObject*)&container);CHKERRQ(ierr); 10852c5f739Sprj- if (!container) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Container does not exist"); 10952c5f739Sprj- ierr = PetscContainerGetPointer(container,(void**)&contents);CHKERRQ(ierr); 11052c5f739Sprj- ierr = MatDenseGetLDA(B,&ldb);CHKERRQ(ierr); 11152c5f739Sprj- ierr = MatDenseGetLDA(C,&ldc);CHKERRQ(ierr); 11252c5f739Sprj- ierr = MatGetSize(B,NULL,&N);CHKERRQ(ierr); 11352c5f739Sprj- ierr = MatZeroEntries(C);CHKERRQ(ierr); 11452c5f739Sprj- ierr = MatDenseGetArrayRead(B,&barray);CHKERRQ(ierr); 11552c5f739Sprj- ierr = MatDenseGetArray(C,&carray);CHKERRQ(ierr); 11652c5f739Sprj- for (i=0; i<nr; i++) { 11752c5f739Sprj- ierr = ISGetSize(bA->isglobal.row[i],&M);CHKERRQ(ierr); 11852c5f739Sprj- ierr = MatCreateDense(PetscObjectComm((PetscObject)A),contents->dm[i+1]-contents->dm[i],PETSC_DECIDE,M,N,carray+contents->dm[i],&viewC);CHKERRQ(ierr); 11952c5f739Sprj- ierr = MatDenseGetLocalMatrix(viewC,&seq);CHKERRQ(ierr); 12052c5f739Sprj- ierr = MatSeqDenseSetLDA(seq,ldc);CHKERRQ(ierr); 12152c5f739Sprj- for (j=0; j<nc; j++) { 12252c5f739Sprj- if (!bA->m[i][j]) continue; 12352c5f739Sprj- ierr = ISGetSize(bA->isglobal.col[j],&M);CHKERRQ(ierr); 12452c5f739Sprj- ierr = MatCreateDense(PetscObjectComm((PetscObject)A),contents->dn[j+1]-contents->dn[j],PETSC_DECIDE,M,N,(PetscScalar*)(barray+contents->dn[j]),&viewB);CHKERRQ(ierr); 12552c5f739Sprj- ierr = MatDenseGetLocalMatrix(viewB,&seq);CHKERRQ(ierr); 12652c5f739Sprj- ierr = MatSeqDenseSetLDA(seq,ldb);CHKERRQ(ierr); 12752c5f739Sprj- /* workC <- A[i][j] * B[j] */ 12852c5f739Sprj- ierr = MatMatMultNumeric(bA->m[i][j],viewB,contents->workC[i*nc + j]);CHKERRQ(ierr); 12952c5f739Sprj- ierr = MatDestroy(&viewB);CHKERRQ(ierr); 13052c5f739Sprj- /* C[i] <- workC + C[i] */ 13152c5f739Sprj- ierr = MatAXPY(viewC,1.0,contents->workC[i*nc + j],SAME_NONZERO_PATTERN);CHKERRQ(ierr); 13252c5f739Sprj- } 13352c5f739Sprj- ierr = MatDestroy(&viewC);CHKERRQ(ierr); 13452c5f739Sprj- } 13552c5f739Sprj- ierr = MatDenseRestoreArray(C,&carray);CHKERRQ(ierr); 13652c5f739Sprj- ierr = MatDenseRestoreArrayRead(B,&barray);CHKERRQ(ierr); 13752c5f739Sprj- PetscFunctionReturn(0); 13852c5f739Sprj- } 13952c5f739Sprj- 14052c5f739Sprj- PetscErrorCode MatNest_DenseDestroy(void *ctx) 14152c5f739Sprj- { 14252c5f739Sprj- Nest_Dense *contents = (Nest_Dense*)ctx; 14352c5f739Sprj- PetscInt i; 14452c5f739Sprj- PetscErrorCode ierr; 14552c5f739Sprj- 14652c5f739Sprj- PetscFunctionBegin; 14752c5f739Sprj- ierr = PetscFree(contents->tarray);CHKERRQ(ierr); 14852c5f739Sprj- for (i=0; i<contents->k; i++) { 14952c5f739Sprj- ierr = MatDestroy(contents->workC + i);CHKERRQ(ierr); 15052c5f739Sprj- } 15152c5f739Sprj- ierr = PetscFree3(contents->dm,contents->dn,contents->workC);CHKERRQ(ierr); 15252c5f739Sprj- ierr = PetscFree(contents);CHKERRQ(ierr); 15352c5f739Sprj- PetscFunctionReturn(0); 15452c5f739Sprj- } 15552c5f739Sprj- 15652c5f739Sprj- PETSC_INTERN PetscErrorCode MatMatMultSymbolic_Nest_Dense(Mat A,Mat B,PetscReal fill,Mat *C) 15752c5f739Sprj- { 15852c5f739Sprj- Mat_Nest *bA = (Mat_Nest*)A->data; 15952c5f739Sprj- Mat viewB,viewSeq; 16052c5f739Sprj- const PetscScalar *barray; 16152c5f739Sprj- PetscInt i,j,M,N,m,nr = bA->nr,nc = bA->nc,maxm = 0,ldb; 16252c5f739Sprj- PetscContainer container; 16352c5f739Sprj- Nest_Dense *contents; 16452c5f739Sprj- PetscErrorCode ierr; 16552c5f739Sprj- 16652c5f739Sprj- PetscFunctionBegin; 16752c5f739Sprj- ierr = MatGetSize(B,NULL,&N);CHKERRQ(ierr); 16852c5f739Sprj- if (!(*C)) { 16952c5f739Sprj- ierr = MatGetLocalSize(A,&m,NULL);CHKERRQ(ierr); 17052c5f739Sprj- ierr = MatGetSize(A,&M,NULL);CHKERRQ(ierr); 17152c5f739Sprj- ierr = MatCreateDense(PetscObjectComm((PetscObject)A),m,PETSC_DECIDE,M,N,NULL,C);CHKERRQ(ierr); 17252c5f739Sprj- } else { 17352c5f739Sprj- 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); 17452c5f739Sprj- 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); 17552c5f739Sprj- } 17652c5f739Sprj- 17752c5f739Sprj- ierr = PetscNew(&contents);CHKERRQ(ierr); 17852c5f739Sprj- ierr = PetscContainerCreate(PetscObjectComm((PetscObject)A),&container);CHKERRQ(ierr); 17952c5f739Sprj- ierr = PetscContainerSetPointer(container,contents);CHKERRQ(ierr); 18052c5f739Sprj- ierr = PetscContainerSetUserDestroy(container,MatNest_DenseDestroy);CHKERRQ(ierr); 18152c5f739Sprj- ierr = PetscObjectCompose((PetscObject)*C,"workC",(PetscObject)container);CHKERRQ(ierr); 18252c5f739Sprj- ierr = PetscContainerDestroy(&container);CHKERRQ(ierr); 18352c5f739Sprj- ierr = PetscCalloc3(nr+1,&contents->dm,nc+1,&contents->dn,nr*nc,&contents->workC);CHKERRQ(ierr); 18452c5f739Sprj- contents->k = nr*nc; 18552c5f739Sprj- for (i=0; i<nr; i++) { 18652c5f739Sprj- ierr = ISGetLocalSize(bA->isglobal.row[i],contents->dm + i+1);CHKERRQ(ierr); 18752c5f739Sprj- maxm = PetscMax(maxm,contents->dm[i+1]); 18852c5f739Sprj- contents->dm[i+1] += contents->dm[i]; 18952c5f739Sprj- } 19052c5f739Sprj- for (i=0; i<nc; i++) { 19152c5f739Sprj- ierr = ISGetLocalSize(bA->isglobal.col[i],contents->dn + i+1);CHKERRQ(ierr); 19252c5f739Sprj- contents->dn[i+1] += contents->dn[i]; 19352c5f739Sprj- } 19452c5f739Sprj- ierr = PetscMalloc1(maxm*N,&contents->tarray);CHKERRQ(ierr); 19552c5f739Sprj- ierr = MatDenseGetLDA(B,&ldb);CHKERRQ(ierr); 19652c5f739Sprj- ierr = MatGetSize(B,NULL,&N);CHKERRQ(ierr); 19752c5f739Sprj- ierr = MatDenseGetArrayRead(B,&barray);CHKERRQ(ierr); 19852c5f739Sprj- /* loops are permuted compared to MatMatMultNumeric so that viewB is created only once per column of A */ 19952c5f739Sprj- for (j=0; j<nc; j++) { 20052c5f739Sprj- ierr = ISGetSize(bA->isglobal.col[j],&M);CHKERRQ(ierr); 20152c5f739Sprj- ierr = MatCreateDense(PetscObjectComm((PetscObject)A),contents->dn[j+1]-contents->dn[j],PETSC_DECIDE,M,N,(PetscScalar*)(barray+contents->dn[j]),&viewB);CHKERRQ(ierr); 20252c5f739Sprj- ierr = MatDenseGetLocalMatrix(viewB,&viewSeq);CHKERRQ(ierr); 20352c5f739Sprj- ierr = MatSeqDenseSetLDA(viewSeq,ldb);CHKERRQ(ierr); 20452c5f739Sprj- for (i=0; i<nr; i++) { 20552c5f739Sprj- if (!bA->m[i][j]) continue; 20652c5f739Sprj- /* MatMatMultSymbolic may attach a specific container (depending on MatType of bA->m[i][j]) to workC[i][j] */ 20752c5f739Sprj- ierr = MatMatMultSymbolic(bA->m[i][j],viewB,fill,contents->workC + i*nc + j);CHKERRQ(ierr); 20852c5f739Sprj- ierr = MatDenseGetLocalMatrix(contents->workC[i*nc + j],&viewSeq);CHKERRQ(ierr); 20952c5f739Sprj- /* free the memory allocated in MatMatMultSymbolic, since tarray will be shared by all Mat */ 21052c5f739Sprj- ierr = MatSeqDenseSetPreallocation(viewSeq,contents->tarray);CHKERRQ(ierr); 21152c5f739Sprj- } 21252c5f739Sprj- ierr = MatDestroy(&viewB);CHKERRQ(ierr); 21352c5f739Sprj- } 21452c5f739Sprj- ierr = MatDenseRestoreArrayRead(B,&barray);CHKERRQ(ierr); 21552c5f739Sprj- 21652c5f739Sprj- (*C)->ops->matmultnumeric = MatMatMultNumeric_Nest_Dense; 21752c5f739Sprj- PetscFunctionReturn(0); 21852c5f739Sprj- } 21952c5f739Sprj- 22052c5f739Sprj- PETSC_INTERN PetscErrorCode MatMatMult_Nest_Dense(Mat A,Mat B,MatReuse scall,PetscReal fill,Mat *C) 22152c5f739Sprj- { 22252c5f739Sprj- PetscErrorCode ierr; 22352c5f739Sprj- 22452c5f739Sprj- PetscFunctionBegin; 22552c5f739Sprj- if (scall == MAT_INITIAL_MATRIX) { 22652c5f739Sprj- *C = NULL; 22752c5f739Sprj- ierr = PetscLogEventBegin(MAT_MatMultSymbolic,A,B,0,0);CHKERRQ(ierr); 22852c5f739Sprj- ierr = MatMatMultSymbolic_Nest_Dense(A,B,fill,C);CHKERRQ(ierr); 22952c5f739Sprj- ierr = PetscLogEventEnd(MAT_MatMultSymbolic,A,B,0,0);CHKERRQ(ierr); 23052c5f739Sprj- } 23152c5f739Sprj- ierr = PetscLogEventBegin(MAT_MatMultNumeric,A,B,0,0);CHKERRQ(ierr); 23252c5f739Sprj- ierr = MatMatMultNumeric_Nest_Dense(A,B,*C);CHKERRQ(ierr); 23352c5f739Sprj- ierr = PetscLogEventEnd(MAT_MatMultNumeric,A,B,0,0);CHKERRQ(ierr); 23452c5f739Sprj- PetscFunctionReturn(0); 23552c5f739Sprj- } 23652c5f739Sprj- 237207556f9SJed Brown static PetscErrorCode MatMultTranspose_Nest(Mat A,Vec x,Vec y) 238d8588912SDave May { 239d8588912SDave May Mat_Nest *bA = (Mat_Nest*)A->data; 240207556f9SJed Brown Vec *bx = bA->left,*by = bA->right; 241207556f9SJed Brown PetscInt i,j,nr = bA->nr,nc = bA->nc; 242d8588912SDave May PetscErrorCode ierr; 243d8588912SDave May 244d8588912SDave May PetscFunctionBegin; 245609e31cbSJed Brown for (i=0; i<nr; i++) {ierr = VecGetSubVector(x,bA->isglobal.row[i],&bx[i]);CHKERRQ(ierr);} 246609e31cbSJed Brown for (i=0; i<nc; i++) {ierr = VecGetSubVector(y,bA->isglobal.col[i],&by[i]);CHKERRQ(ierr);} 247207556f9SJed Brown for (j=0; j<nc; j++) { 248609e31cbSJed Brown ierr = VecZeroEntries(by[j]);CHKERRQ(ierr); 249609e31cbSJed Brown for (i=0; i<nr; i++) { 2506c75ac25SJed Brown if (!bA->m[i][j]) continue; 251609e31cbSJed Brown /* y[j] <- y[j] + (A[i][j])^T * x[i] */ 252609e31cbSJed Brown ierr = MatMultTransposeAdd(bA->m[i][j],bx[i],by[j],by[j]);CHKERRQ(ierr); 253d8588912SDave May } 254d8588912SDave May } 255609e31cbSJed Brown for (i=0; i<nr; i++) {ierr = VecRestoreSubVector(x,bA->isglobal.row[i],&bx[i]);CHKERRQ(ierr);} 256609e31cbSJed Brown for (i=0; i<nc; i++) {ierr = VecRestoreSubVector(y,bA->isglobal.col[i],&by[i]);CHKERRQ(ierr);} 257d8588912SDave May PetscFunctionReturn(0); 258d8588912SDave May } 259d8588912SDave May 2609194d70fSJed Brown static PetscErrorCode MatMultTransposeAdd_Nest(Mat A,Vec x,Vec y,Vec z) 2619194d70fSJed Brown { 2629194d70fSJed Brown Mat_Nest *bA = (Mat_Nest*)A->data; 2639194d70fSJed Brown Vec *bx = bA->left,*bz = bA->right; 2649194d70fSJed Brown PetscInt i,j,nr = bA->nr,nc = bA->nc; 2659194d70fSJed Brown PetscErrorCode ierr; 2669194d70fSJed Brown 2679194d70fSJed Brown PetscFunctionBegin; 2689194d70fSJed Brown for (i=0; i<nr; i++) {ierr = VecGetSubVector(x,bA->isglobal.row[i],&bx[i]);CHKERRQ(ierr);} 2699194d70fSJed Brown for (i=0; i<nc; i++) {ierr = VecGetSubVector(z,bA->isglobal.col[i],&bz[i]);CHKERRQ(ierr);} 2709194d70fSJed Brown for (j=0; j<nc; j++) { 2719194d70fSJed Brown if (y != z) { 2729194d70fSJed Brown Vec by; 2739194d70fSJed Brown ierr = VecGetSubVector(y,bA->isglobal.col[j],&by);CHKERRQ(ierr); 2749194d70fSJed Brown ierr = VecCopy(by,bz[j]);CHKERRQ(ierr); 2759194d70fSJed Brown ierr = VecRestoreSubVector(y,bA->isglobal.col[j],&by);CHKERRQ(ierr); 2769194d70fSJed Brown } 2779194d70fSJed Brown for (i=0; i<nr; i++) { 2786c75ac25SJed Brown if (!bA->m[i][j]) continue; 2799194d70fSJed Brown /* z[j] <- y[j] + (A[i][j])^T * x[i] */ 2809194d70fSJed Brown ierr = MatMultTransposeAdd(bA->m[i][j],bx[i],bz[j],bz[j]);CHKERRQ(ierr); 2819194d70fSJed Brown } 2829194d70fSJed Brown } 2839194d70fSJed Brown for (i=0; i<nr; i++) {ierr = VecRestoreSubVector(x,bA->isglobal.row[i],&bx[i]);CHKERRQ(ierr);} 2849194d70fSJed Brown for (i=0; i<nc; i++) {ierr = VecRestoreSubVector(z,bA->isglobal.col[i],&bz[i]);CHKERRQ(ierr);} 2859194d70fSJed Brown PetscFunctionReturn(0); 2869194d70fSJed Brown } 2879194d70fSJed Brown 288f8170845SAlex Fikl static PetscErrorCode MatTranspose_Nest(Mat A,MatReuse reuse,Mat *B) 289f8170845SAlex Fikl { 290f8170845SAlex Fikl Mat_Nest *bA = (Mat_Nest*)A->data, *bC; 291f8170845SAlex Fikl Mat C; 292f8170845SAlex Fikl PetscInt i,j,nr = bA->nr,nc = bA->nc; 293f8170845SAlex Fikl PetscErrorCode ierr; 294f8170845SAlex Fikl 295f8170845SAlex Fikl PetscFunctionBegin; 296cf37664fSBarry Smith if (reuse == MAT_INPLACE_MATRIX && nr != nc) SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_SIZ,"Square nested matrix only for in-place"); 297f8170845SAlex Fikl 298cf37664fSBarry Smith if (reuse == MAT_INITIAL_MATRIX || reuse == MAT_INPLACE_MATRIX) { 299f8170845SAlex Fikl Mat *subs; 300f8170845SAlex Fikl IS *is_row,*is_col; 301f8170845SAlex Fikl 302f8170845SAlex Fikl ierr = PetscCalloc1(nr * nc,&subs);CHKERRQ(ierr); 303f8170845SAlex Fikl ierr = PetscMalloc2(nr,&is_row,nc,&is_col);CHKERRQ(ierr); 304f8170845SAlex Fikl ierr = MatNestGetISs(A,is_row,is_col);CHKERRQ(ierr); 305cf37664fSBarry Smith if (reuse == MAT_INPLACE_MATRIX) { 306ddeb9bd8SAlex Fikl for (i=0; i<nr; i++) { 307ddeb9bd8SAlex Fikl for (j=0; j<nc; j++) { 308ddeb9bd8SAlex Fikl subs[i + nr * j] = bA->m[i][j]; 309ddeb9bd8SAlex Fikl } 310ddeb9bd8SAlex Fikl } 311ddeb9bd8SAlex Fikl } 312ddeb9bd8SAlex Fikl 313f8170845SAlex Fikl ierr = MatCreateNest(PetscObjectComm((PetscObject)A),nc,is_col,nr,is_row,subs,&C);CHKERRQ(ierr); 314f8170845SAlex Fikl ierr = PetscFree(subs);CHKERRQ(ierr); 3153d994f23SBarry Smith ierr = PetscFree2(is_row,is_col);CHKERRQ(ierr); 316f8170845SAlex Fikl } else { 317f8170845SAlex Fikl C = *B; 318f8170845SAlex Fikl } 319f8170845SAlex Fikl 320f8170845SAlex Fikl bC = (Mat_Nest*)C->data; 321f8170845SAlex Fikl for (i=0; i<nr; i++) { 322f8170845SAlex Fikl for (j=0; j<nc; j++) { 323f8170845SAlex Fikl if (bA->m[i][j]) { 324f8170845SAlex Fikl ierr = MatTranspose(bA->m[i][j], reuse, &(bC->m[j][i]));CHKERRQ(ierr); 325f8170845SAlex Fikl } else { 326f8170845SAlex Fikl bC->m[j][i] = NULL; 327f8170845SAlex Fikl } 328f8170845SAlex Fikl } 329f8170845SAlex Fikl } 330f8170845SAlex Fikl 331cf37664fSBarry Smith if (reuse == MAT_INITIAL_MATRIX || reuse == MAT_REUSE_MATRIX) { 332f8170845SAlex Fikl *B = C; 333f8170845SAlex Fikl } else { 334f8170845SAlex Fikl ierr = MatHeaderMerge(A, &C);CHKERRQ(ierr); 335f8170845SAlex Fikl } 336f8170845SAlex Fikl PetscFunctionReturn(0); 337f8170845SAlex Fikl } 338f8170845SAlex Fikl 339e2d7f03fSJed Brown static PetscErrorCode MatNestDestroyISList(PetscInt n,IS **list) 340e2d7f03fSJed Brown { 341e2d7f03fSJed Brown PetscErrorCode ierr; 342e2d7f03fSJed Brown IS *lst = *list; 343e2d7f03fSJed Brown PetscInt i; 344e2d7f03fSJed Brown 345e2d7f03fSJed Brown PetscFunctionBegin; 346e2d7f03fSJed Brown if (!lst) PetscFunctionReturn(0); 3476bf464f9SBarry Smith for (i=0; i<n; i++) if (lst[i]) {ierr = ISDestroy(&lst[i]);CHKERRQ(ierr);} 348e2d7f03fSJed Brown ierr = PetscFree(lst);CHKERRQ(ierr); 3490298fd71SBarry Smith *list = NULL; 350e2d7f03fSJed Brown PetscFunctionReturn(0); 351e2d7f03fSJed Brown } 352e2d7f03fSJed Brown 35306a1af2fSStefano Zampini static PetscErrorCode MatReset_Nest(Mat A) 354d8588912SDave May { 355d8588912SDave May Mat_Nest *vs = (Mat_Nest*)A->data; 356d8588912SDave May PetscInt i,j; 357d8588912SDave May PetscErrorCode ierr; 358d8588912SDave May 359d8588912SDave May PetscFunctionBegin; 360d8588912SDave May /* release the matrices and the place holders */ 361e2d7f03fSJed Brown ierr = MatNestDestroyISList(vs->nr,&vs->isglobal.row);CHKERRQ(ierr); 362e2d7f03fSJed Brown ierr = MatNestDestroyISList(vs->nc,&vs->isglobal.col);CHKERRQ(ierr); 363e2d7f03fSJed Brown ierr = MatNestDestroyISList(vs->nr,&vs->islocal.row);CHKERRQ(ierr); 364e2d7f03fSJed Brown ierr = MatNestDestroyISList(vs->nc,&vs->islocal.col);CHKERRQ(ierr); 365d8588912SDave May 366d8588912SDave May ierr = PetscFree(vs->row_len);CHKERRQ(ierr); 367d8588912SDave May ierr = PetscFree(vs->col_len);CHKERRQ(ierr); 36806a1af2fSStefano Zampini ierr = PetscFree(vs->nnzstate);CHKERRQ(ierr); 369d8588912SDave May 370207556f9SJed Brown ierr = PetscFree2(vs->left,vs->right);CHKERRQ(ierr); 371207556f9SJed Brown 372d8588912SDave May /* release the matrices and the place holders */ 373d8588912SDave May if (vs->m) { 374d8588912SDave May for (i=0; i<vs->nr; i++) { 375d8588912SDave May for (j=0; j<vs->nc; j++) { 3766bf464f9SBarry Smith ierr = MatDestroy(&vs->m[i][j]);CHKERRQ(ierr); 377d8588912SDave May } 378d8588912SDave May ierr = PetscFree(vs->m[i]);CHKERRQ(ierr); 379d8588912SDave May } 380d8588912SDave May ierr = PetscFree(vs->m);CHKERRQ(ierr); 381d8588912SDave May } 38206a1af2fSStefano Zampini 38306a1af2fSStefano Zampini /* restore defaults */ 38406a1af2fSStefano Zampini vs->nr = 0; 38506a1af2fSStefano Zampini vs->nc = 0; 38606a1af2fSStefano Zampini vs->splitassembly = PETSC_FALSE; 38706a1af2fSStefano Zampini PetscFunctionReturn(0); 38806a1af2fSStefano Zampini } 38906a1af2fSStefano Zampini 39006a1af2fSStefano Zampini static PetscErrorCode MatDestroy_Nest(Mat A) 39106a1af2fSStefano Zampini { 39206a1af2fSStefano Zampini PetscErrorCode ierr; 39306a1af2fSStefano Zampini 39406a1af2fSStefano Zampini ierr = MatReset_Nest(A);CHKERRQ(ierr); 395bf0cc555SLisandro Dalcin ierr = PetscFree(A->data);CHKERRQ(ierr); 396d8588912SDave May 397bdf89e91SBarry Smith ierr = PetscObjectComposeFunction((PetscObject)A,"MatNestGetSubMat_C",0);CHKERRQ(ierr); 398bdf89e91SBarry Smith ierr = PetscObjectComposeFunction((PetscObject)A,"MatNestSetSubMat_C",0);CHKERRQ(ierr); 399bdf89e91SBarry Smith ierr = PetscObjectComposeFunction((PetscObject)A,"MatNestGetSubMats_C",0);CHKERRQ(ierr); 400bdf89e91SBarry Smith ierr = PetscObjectComposeFunction((PetscObject)A,"MatNestGetSize_C",0);CHKERRQ(ierr); 401bdf89e91SBarry Smith ierr = PetscObjectComposeFunction((PetscObject)A,"MatNestGetISs_C",0);CHKERRQ(ierr); 402bdf89e91SBarry Smith ierr = PetscObjectComposeFunction((PetscObject)A,"MatNestGetLocalISs_C",0);CHKERRQ(ierr); 403bdf89e91SBarry Smith ierr = PetscObjectComposeFunction((PetscObject)A,"MatNestSetVecType_C",0);CHKERRQ(ierr); 404bdf89e91SBarry Smith ierr = PetscObjectComposeFunction((PetscObject)A,"MatNestSetSubMats_C",0);CHKERRQ(ierr); 4050899c546SStefano Zampini ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_nest_mpiaij_C",0);CHKERRQ(ierr); 4060899c546SStefano Zampini ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_nest_seqaij_C",0);CHKERRQ(ierr); 4075e3038f0Sstefano_zampini ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_nest_aij_C",0);CHKERRQ(ierr); 4085e3038f0Sstefano_zampini ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_nest_is_C",0);CHKERRQ(ierr); 40952c5f739Sprj- ierr = PetscObjectComposeFunction((PetscObject)A,"MatMatMult_nest_mpidense_C",0);CHKERRQ(ierr); 41052c5f739Sprj- ierr = PetscObjectComposeFunction((PetscObject)A,"MatMatMult_nest_seqdense_C",0);CHKERRQ(ierr); 41152c5f739Sprj- ierr = PetscObjectComposeFunction((PetscObject)A,"MatMatMult_nest_dense_C",0);CHKERRQ(ierr); 412d8588912SDave May PetscFunctionReturn(0); 413d8588912SDave May } 414d8588912SDave May 415*381b8e50SStefano Zampini static PetscErrorCode MatMissingDiagonal_Nest(Mat mat,PetscBool *missing,PetscInt *dd) 416*381b8e50SStefano Zampini { 417*381b8e50SStefano Zampini Mat_Nest *vs = (Mat_Nest*)mat->data; 418*381b8e50SStefano Zampini PetscInt i; 419*381b8e50SStefano Zampini PetscErrorCode ierr; 420*381b8e50SStefano Zampini 421*381b8e50SStefano Zampini PetscFunctionBegin; 422*381b8e50SStefano Zampini if (dd) *dd = 0; 423*381b8e50SStefano Zampini if (!vs->nr) { 424*381b8e50SStefano Zampini *missing = PETSC_TRUE; 425*381b8e50SStefano Zampini PetscFunctionReturn(0); 426*381b8e50SStefano Zampini } 427*381b8e50SStefano Zampini *missing = PETSC_FALSE; 428*381b8e50SStefano Zampini for (i = 0; i < vs->nr && !(*missing); i++) { 429*381b8e50SStefano Zampini *missing = PETSC_TRUE; 430*381b8e50SStefano Zampini if (vs->m[i][i]) { 431*381b8e50SStefano Zampini ierr = MatMissingDiagonal(vs->m[i][i],missing,NULL);CHKERRQ(ierr); 432*381b8e50SStefano Zampini if (*missing && dd) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"First missing entry not yet implemented"); 433*381b8e50SStefano Zampini } 434*381b8e50SStefano Zampini } 435*381b8e50SStefano Zampini PetscFunctionReturn(0); 436*381b8e50SStefano Zampini } 437*381b8e50SStefano Zampini 438207556f9SJed Brown static PetscErrorCode MatAssemblyBegin_Nest(Mat A,MatAssemblyType type) 439d8588912SDave May { 440d8588912SDave May Mat_Nest *vs = (Mat_Nest*)A->data; 441d8588912SDave May PetscInt i,j; 442d8588912SDave May PetscErrorCode ierr; 44306a1af2fSStefano Zampini PetscBool nnzstate = PETSC_FALSE; 444d8588912SDave May 445d8588912SDave May PetscFunctionBegin; 446d8588912SDave May for (i=0; i<vs->nr; i++) { 447d8588912SDave May for (j=0; j<vs->nc; j++) { 44806a1af2fSStefano Zampini PetscObjectState subnnzstate = 0; 449e7c19651SJed Brown if (vs->m[i][j]) { 450e7c19651SJed Brown ierr = MatAssemblyBegin(vs->m[i][j],type);CHKERRQ(ierr); 451e7c19651SJed Brown if (!vs->splitassembly) { 452e7c19651SJed Brown /* Note: split assembly will fail if the same block appears more than once (even indirectly through a nested 453e7c19651SJed 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 454e7c19651SJed Brown * already performing an assembly, but the result would by more complicated and appears to offer less 455e7c19651SJed Brown * potential for diagnostics and correctness checking. Split assembly should be fixed once there is an 456e7c19651SJed Brown * interface for libraries to make asynchronous progress in "user-defined non-blocking collectives". 457e7c19651SJed Brown */ 458e7c19651SJed Brown ierr = MatAssemblyEnd(vs->m[i][j],type);CHKERRQ(ierr); 45906a1af2fSStefano Zampini ierr = MatGetNonzeroState(vs->m[i][j],&subnnzstate);CHKERRQ(ierr); 460e7c19651SJed Brown } 461e7c19651SJed Brown } 46206a1af2fSStefano Zampini nnzstate = (PetscBool)(nnzstate || vs->nnzstate[i*vs->nc+j] != subnnzstate); 46306a1af2fSStefano Zampini vs->nnzstate[i*vs->nc+j] = subnnzstate; 464d8588912SDave May } 465d8588912SDave May } 46606a1af2fSStefano Zampini if (nnzstate) A->nonzerostate++; 467d8588912SDave May PetscFunctionReturn(0); 468d8588912SDave May } 469d8588912SDave May 470207556f9SJed Brown static PetscErrorCode MatAssemblyEnd_Nest(Mat A, MatAssemblyType type) 471d8588912SDave May { 472d8588912SDave May Mat_Nest *vs = (Mat_Nest*)A->data; 473d8588912SDave May PetscInt i,j; 474d8588912SDave May PetscErrorCode ierr; 475d8588912SDave May 476d8588912SDave May PetscFunctionBegin; 477d8588912SDave May for (i=0; i<vs->nr; i++) { 478d8588912SDave May for (j=0; j<vs->nc; j++) { 479e7c19651SJed Brown if (vs->m[i][j]) { 480e7c19651SJed Brown if (vs->splitassembly) { 481e7c19651SJed Brown ierr = MatAssemblyEnd(vs->m[i][j],type);CHKERRQ(ierr); 482e7c19651SJed Brown } 483e7c19651SJed Brown } 484d8588912SDave May } 485d8588912SDave May } 486d8588912SDave May PetscFunctionReturn(0); 487d8588912SDave May } 488d8588912SDave May 489f349c1fdSJed Brown static PetscErrorCode MatNestFindNonzeroSubMatRow(Mat A,PetscInt row,Mat *B) 490d8588912SDave May { 491207556f9SJed Brown PetscErrorCode ierr; 492f349c1fdSJed Brown Mat_Nest *vs = (Mat_Nest*)A->data; 493f349c1fdSJed Brown PetscInt j; 494f349c1fdSJed Brown Mat sub; 495d8588912SDave May 496d8588912SDave May PetscFunctionBegin; 4970298fd71SBarry Smith sub = (row < vs->nc) ? vs->m[row][row] : (Mat)NULL; /* Prefer to find on the diagonal */ 498f349c1fdSJed Brown for (j=0; !sub && j<vs->nc; j++) sub = vs->m[row][j]; 4994994cf47SJed Brown if (sub) {ierr = MatSetUp(sub);CHKERRQ(ierr);} /* Ensure that the sizes are available */ 500f349c1fdSJed Brown *B = sub; 501f349c1fdSJed Brown PetscFunctionReturn(0); 502d8588912SDave May } 503d8588912SDave May 504f349c1fdSJed Brown static PetscErrorCode MatNestFindNonzeroSubMatCol(Mat A,PetscInt col,Mat *B) 505f349c1fdSJed Brown { 506207556f9SJed Brown PetscErrorCode ierr; 507f349c1fdSJed Brown Mat_Nest *vs = (Mat_Nest*)A->data; 508f349c1fdSJed Brown PetscInt i; 509f349c1fdSJed Brown Mat sub; 510f349c1fdSJed Brown 511f349c1fdSJed Brown PetscFunctionBegin; 5120298fd71SBarry Smith sub = (col < vs->nr) ? vs->m[col][col] : (Mat)NULL; /* Prefer to find on the diagonal */ 513f349c1fdSJed Brown for (i=0; !sub && i<vs->nr; i++) sub = vs->m[i][col]; 5144994cf47SJed Brown if (sub) {ierr = MatSetUp(sub);CHKERRQ(ierr);} /* Ensure that the sizes are available */ 515f349c1fdSJed Brown *B = sub; 516f349c1fdSJed Brown PetscFunctionReturn(0); 517d8588912SDave May } 518d8588912SDave May 519f349c1fdSJed Brown static PetscErrorCode MatNestFindIS(Mat A,PetscInt n,const IS list[],IS is,PetscInt *found) 520f349c1fdSJed Brown { 521f349c1fdSJed Brown PetscErrorCode ierr; 522f349c1fdSJed Brown PetscInt i; 523f349c1fdSJed Brown PetscBool flg; 524f349c1fdSJed Brown 525f349c1fdSJed Brown PetscFunctionBegin; 526f349c1fdSJed Brown PetscValidPointer(list,3); 527f349c1fdSJed Brown PetscValidHeaderSpecific(is,IS_CLASSID,4); 528f349c1fdSJed Brown PetscValidIntPointer(found,5); 529f349c1fdSJed Brown *found = -1; 530f349c1fdSJed Brown for (i=0; i<n; i++) { 531207556f9SJed Brown if (!list[i]) continue; 532320466b0SStefano Zampini ierr = ISEqualUnsorted(list[i],is,&flg);CHKERRQ(ierr); 533f349c1fdSJed Brown if (flg) { 534f349c1fdSJed Brown *found = i; 535f349c1fdSJed Brown PetscFunctionReturn(0); 536f349c1fdSJed Brown } 537f349c1fdSJed Brown } 538ce94432eSBarry Smith SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_INCOMP,"Could not find index set"); 539f349c1fdSJed Brown PetscFunctionReturn(0); 540f349c1fdSJed Brown } 541f349c1fdSJed Brown 5428188e55aSJed Brown /* Get a block row as a new MatNest */ 5438188e55aSJed Brown static PetscErrorCode MatNestGetRow(Mat A,PetscInt row,Mat *B) 5448188e55aSJed Brown { 5458188e55aSJed Brown Mat_Nest *vs = (Mat_Nest*)A->data; 5468188e55aSJed Brown char keyname[256]; 5478188e55aSJed Brown PetscErrorCode ierr; 5488188e55aSJed Brown 5498188e55aSJed Brown PetscFunctionBegin; 5500298fd71SBarry Smith *B = NULL; 5518caf3d72SBarry Smith ierr = PetscSNPrintf(keyname,sizeof(keyname),"NestRow_%D",row);CHKERRQ(ierr); 5528188e55aSJed Brown ierr = PetscObjectQuery((PetscObject)A,keyname,(PetscObject*)B);CHKERRQ(ierr); 5538188e55aSJed Brown if (*B) PetscFunctionReturn(0); 5548188e55aSJed Brown 555ce94432eSBarry Smith ierr = MatCreateNest(PetscObjectComm((PetscObject)A),1,NULL,vs->nc,vs->isglobal.col,vs->m[row],B);CHKERRQ(ierr); 55626fbe8dcSKarl Rupp 5578188e55aSJed Brown (*B)->assembled = A->assembled; 55826fbe8dcSKarl Rupp 5598188e55aSJed Brown ierr = PetscObjectCompose((PetscObject)A,keyname,(PetscObject)*B);CHKERRQ(ierr); 5608188e55aSJed Brown ierr = PetscObjectDereference((PetscObject)*B);CHKERRQ(ierr); /* Leave the only remaining reference in the composition */ 5618188e55aSJed Brown PetscFunctionReturn(0); 5628188e55aSJed Brown } 5638188e55aSJed Brown 564f349c1fdSJed Brown static PetscErrorCode MatNestFindSubMat(Mat A,struct MatNestISPair *is,IS isrow,IS iscol,Mat *B) 565f349c1fdSJed Brown { 566f349c1fdSJed Brown Mat_Nest *vs = (Mat_Nest*)A->data; 5678188e55aSJed Brown PetscErrorCode ierr; 5686b3a5b13SJed Brown PetscInt row,col; 569e072481dSJed Brown PetscBool same,isFullCol,isFullColGlobal; 570f349c1fdSJed Brown 571f349c1fdSJed Brown PetscFunctionBegin; 5728188e55aSJed Brown /* Check if full column space. This is a hack */ 5738188e55aSJed Brown isFullCol = PETSC_FALSE; 574251f4c67SDmitry Karpeev ierr = PetscObjectTypeCompare((PetscObject)iscol,ISSTRIDE,&same);CHKERRQ(ierr); 5758188e55aSJed Brown if (same) { 57677019fcaSJed Brown PetscInt n,first,step,i,an,am,afirst,astep; 5778188e55aSJed Brown ierr = ISStrideGetInfo(iscol,&first,&step);CHKERRQ(ierr); 5788188e55aSJed Brown ierr = ISGetLocalSize(iscol,&n);CHKERRQ(ierr); 57977019fcaSJed Brown isFullCol = PETSC_TRUE; 58005ce4453SJed Brown for (i=0,an=A->cmap->rstart; i<vs->nc; i++) { 58106a1af2fSStefano Zampini ierr = PetscObjectTypeCompare((PetscObject)is->col[i],ISSTRIDE,&same);CHKERRQ(ierr); 58277019fcaSJed Brown ierr = ISGetLocalSize(is->col[i],&am);CHKERRQ(ierr); 58306a1af2fSStefano Zampini if (same) { 58406a1af2fSStefano Zampini ierr = ISStrideGetInfo(is->col[i],&afirst,&astep);CHKERRQ(ierr); 58577019fcaSJed Brown if (afirst != an || astep != step) isFullCol = PETSC_FALSE; 58606a1af2fSStefano Zampini } else isFullCol = PETSC_FALSE; 58777019fcaSJed Brown an += am; 58877019fcaSJed Brown } 58905ce4453SJed Brown if (an != A->cmap->rstart+n) isFullCol = PETSC_FALSE; 5908188e55aSJed Brown } 591b2566f29SBarry Smith ierr = MPIU_Allreduce(&isFullCol,&isFullColGlobal,1,MPIU_BOOL,MPI_LAND,PetscObjectComm((PetscObject)iscol));CHKERRQ(ierr); 5928188e55aSJed Brown 593427230ceSLisandro Dalcin if (isFullColGlobal && vs->nc > 1) { 5948188e55aSJed Brown PetscInt row; 5958188e55aSJed Brown ierr = MatNestFindIS(A,vs->nr,is->row,isrow,&row);CHKERRQ(ierr); 5968188e55aSJed Brown ierr = MatNestGetRow(A,row,B);CHKERRQ(ierr); 5978188e55aSJed Brown } else { 598f349c1fdSJed Brown ierr = MatNestFindIS(A,vs->nr,is->row,isrow,&row);CHKERRQ(ierr); 599f349c1fdSJed Brown ierr = MatNestFindIS(A,vs->nc,is->col,iscol,&col);CHKERRQ(ierr); 600b6480e04SStefano Zampini if (!vs->m[row][col]) { 601b6480e04SStefano Zampini PetscInt lr,lc; 602b6480e04SStefano Zampini 603b6480e04SStefano Zampini ierr = MatCreate(PetscObjectComm((PetscObject)A),&vs->m[row][col]);CHKERRQ(ierr); 604b6480e04SStefano Zampini ierr = ISGetLocalSize(vs->isglobal.row[row],&lr);CHKERRQ(ierr); 605b6480e04SStefano Zampini ierr = ISGetLocalSize(vs->isglobal.col[col],&lc);CHKERRQ(ierr); 606b6480e04SStefano Zampini ierr = MatSetSizes(vs->m[row][col],lr,lc,PETSC_DECIDE,PETSC_DECIDE);CHKERRQ(ierr); 607fa9f0909SStefano Zampini ierr = MatSetType(vs->m[row][col],MATAIJ);CHKERRQ(ierr); 608fa9f0909SStefano Zampini ierr = MatSeqAIJSetPreallocation(vs->m[row][col],0,NULL);CHKERRQ(ierr); 609fa9f0909SStefano Zampini ierr = MatMPIAIJSetPreallocation(vs->m[row][col],0,NULL,0,NULL);CHKERRQ(ierr); 610b6480e04SStefano Zampini ierr = MatSetUp(vs->m[row][col]);CHKERRQ(ierr); 611b6480e04SStefano Zampini ierr = MatAssemblyBegin(vs->m[row][col],MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 612b6480e04SStefano Zampini ierr = MatAssemblyEnd(vs->m[row][col],MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 613b6480e04SStefano Zampini } 614f349c1fdSJed Brown *B = vs->m[row][col]; 6158188e55aSJed Brown } 616f349c1fdSJed Brown PetscFunctionReturn(0); 617f349c1fdSJed Brown } 618f349c1fdSJed Brown 61906a1af2fSStefano Zampini /* 62006a1af2fSStefano Zampini TODO: This does not actually returns a submatrix we can modify 62106a1af2fSStefano Zampini */ 6227dae84e0SHong Zhang static PetscErrorCode MatCreateSubMatrix_Nest(Mat A,IS isrow,IS iscol,MatReuse reuse,Mat *B) 623f349c1fdSJed Brown { 624f349c1fdSJed Brown PetscErrorCode ierr; 625f349c1fdSJed Brown Mat_Nest *vs = (Mat_Nest*)A->data; 626f349c1fdSJed Brown Mat sub; 627f349c1fdSJed Brown 628f349c1fdSJed Brown PetscFunctionBegin; 629f349c1fdSJed Brown ierr = MatNestFindSubMat(A,&vs->isglobal,isrow,iscol,&sub);CHKERRQ(ierr); 630f349c1fdSJed Brown switch (reuse) { 631f349c1fdSJed Brown case MAT_INITIAL_MATRIX: 6327874fa86SDave May if (sub) { ierr = PetscObjectReference((PetscObject)sub);CHKERRQ(ierr); } 633f349c1fdSJed Brown *B = sub; 634f349c1fdSJed Brown break; 635f349c1fdSJed Brown case MAT_REUSE_MATRIX: 636ce94432eSBarry Smith if (sub != *B) SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_WRONGSTATE,"Submatrix was not used before in this call"); 637f349c1fdSJed Brown break; 638f349c1fdSJed Brown case MAT_IGNORE_MATRIX: /* Nothing to do */ 639f349c1fdSJed Brown break; 640511c6705SHong Zhang case MAT_INPLACE_MATRIX: /* Nothing to do */ 641511c6705SHong Zhang SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_SUP,"MAT_INPLACE_MATRIX is not supported yet"); 642511c6705SHong Zhang break; 643f349c1fdSJed Brown } 644f349c1fdSJed Brown PetscFunctionReturn(0); 645f349c1fdSJed Brown } 646f349c1fdSJed Brown 647f349c1fdSJed Brown PetscErrorCode MatGetLocalSubMatrix_Nest(Mat A,IS isrow,IS iscol,Mat *B) 648f349c1fdSJed Brown { 649f349c1fdSJed Brown PetscErrorCode ierr; 650f349c1fdSJed Brown Mat_Nest *vs = (Mat_Nest*)A->data; 651f349c1fdSJed Brown Mat sub; 652f349c1fdSJed Brown 653f349c1fdSJed Brown PetscFunctionBegin; 654f349c1fdSJed Brown ierr = MatNestFindSubMat(A,&vs->islocal,isrow,iscol,&sub);CHKERRQ(ierr); 655f349c1fdSJed Brown /* We allow the submatrix to be NULL, perhaps it would be better for the user to return an empty matrix instead */ 656f349c1fdSJed Brown if (sub) {ierr = PetscObjectReference((PetscObject)sub);CHKERRQ(ierr);} 657f349c1fdSJed Brown *B = sub; 658d8588912SDave May PetscFunctionReturn(0); 659d8588912SDave May } 660d8588912SDave May 661207556f9SJed Brown static PetscErrorCode MatRestoreLocalSubMatrix_Nest(Mat A,IS isrow,IS iscol,Mat *B) 662d8588912SDave May { 663d8588912SDave May PetscErrorCode ierr; 664f349c1fdSJed Brown Mat_Nest *vs = (Mat_Nest*)A->data; 665f349c1fdSJed Brown Mat sub; 666d8588912SDave May 667d8588912SDave May PetscFunctionBegin; 668f349c1fdSJed Brown ierr = MatNestFindSubMat(A,&vs->islocal,isrow,iscol,&sub);CHKERRQ(ierr); 669ce94432eSBarry Smith if (*B != sub) SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_WRONGSTATE,"Local submatrix has not been gotten"); 670f349c1fdSJed Brown if (sub) { 671ce94432eSBarry Smith if (((PetscObject)sub)->refct <= 1) SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_WRONGSTATE,"Local submatrix has had reference count decremented too many times"); 6726bf464f9SBarry Smith ierr = MatDestroy(B);CHKERRQ(ierr); 673d8588912SDave May } 674d8588912SDave May PetscFunctionReturn(0); 675d8588912SDave May } 676d8588912SDave May 6777874fa86SDave May static PetscErrorCode MatGetDiagonal_Nest(Mat A,Vec v) 6787874fa86SDave May { 6797874fa86SDave May Mat_Nest *bA = (Mat_Nest*)A->data; 6807874fa86SDave May PetscInt i; 6817874fa86SDave May PetscErrorCode ierr; 6827874fa86SDave May 6837874fa86SDave May PetscFunctionBegin; 6847874fa86SDave May for (i=0; i<bA->nr; i++) { 685429bac76SJed Brown Vec bv; 686429bac76SJed Brown ierr = VecGetSubVector(v,bA->isglobal.row[i],&bv);CHKERRQ(ierr); 6877874fa86SDave May if (bA->m[i][i]) { 688429bac76SJed Brown ierr = MatGetDiagonal(bA->m[i][i],bv);CHKERRQ(ierr); 6897874fa86SDave May } else { 6905159a857SMatthew G. Knepley ierr = VecSet(bv,0.0);CHKERRQ(ierr); 6917874fa86SDave May } 692429bac76SJed Brown ierr = VecRestoreSubVector(v,bA->isglobal.row[i],&bv);CHKERRQ(ierr); 6937874fa86SDave May } 6947874fa86SDave May PetscFunctionReturn(0); 6957874fa86SDave May } 6967874fa86SDave May 6977874fa86SDave May static PetscErrorCode MatDiagonalScale_Nest(Mat A,Vec l,Vec r) 6987874fa86SDave May { 6997874fa86SDave May Mat_Nest *bA = (Mat_Nest*)A->data; 700429bac76SJed Brown Vec bl,*br; 7017874fa86SDave May PetscInt i,j; 7027874fa86SDave May PetscErrorCode ierr; 7037874fa86SDave May 7047874fa86SDave May PetscFunctionBegin; 7053f800ebeSJed Brown ierr = PetscCalloc1(bA->nc,&br);CHKERRQ(ierr); 7062e6472ebSElliott Sales de Andrade if (r) { 707429bac76SJed Brown for (j=0; j<bA->nc; j++) {ierr = VecGetSubVector(r,bA->isglobal.col[j],&br[j]);CHKERRQ(ierr);} 7082e6472ebSElliott Sales de Andrade } 7092e6472ebSElliott Sales de Andrade bl = NULL; 7107874fa86SDave May for (i=0; i<bA->nr; i++) { 7112e6472ebSElliott Sales de Andrade if (l) { 712429bac76SJed Brown ierr = VecGetSubVector(l,bA->isglobal.row[i],&bl);CHKERRQ(ierr); 7132e6472ebSElliott Sales de Andrade } 7147874fa86SDave May for (j=0; j<bA->nc; j++) { 7157874fa86SDave May if (bA->m[i][j]) { 716429bac76SJed Brown ierr = MatDiagonalScale(bA->m[i][j],bl,br[j]);CHKERRQ(ierr); 7177874fa86SDave May } 7187874fa86SDave May } 7192e6472ebSElliott Sales de Andrade if (l) { 720a061e289SJed Brown ierr = VecRestoreSubVector(l,bA->isglobal.row[i],&bl);CHKERRQ(ierr); 7217874fa86SDave May } 7222e6472ebSElliott Sales de Andrade } 7232e6472ebSElliott Sales de Andrade if (r) { 724429bac76SJed Brown for (j=0; j<bA->nc; j++) {ierr = VecRestoreSubVector(r,bA->isglobal.col[j],&br[j]);CHKERRQ(ierr);} 7252e6472ebSElliott Sales de Andrade } 726429bac76SJed Brown ierr = PetscFree(br);CHKERRQ(ierr); 7277874fa86SDave May PetscFunctionReturn(0); 7287874fa86SDave May } 7297874fa86SDave May 730a061e289SJed Brown static PetscErrorCode MatScale_Nest(Mat A,PetscScalar a) 731a061e289SJed Brown { 732a061e289SJed Brown Mat_Nest *bA = (Mat_Nest*)A->data; 733a061e289SJed Brown PetscInt i,j; 734a061e289SJed Brown PetscErrorCode ierr; 735a061e289SJed Brown 736a061e289SJed Brown PetscFunctionBegin; 737a061e289SJed Brown for (i=0; i<bA->nr; i++) { 738a061e289SJed Brown for (j=0; j<bA->nc; j++) { 739a061e289SJed Brown if (bA->m[i][j]) { 740a061e289SJed Brown ierr = MatScale(bA->m[i][j],a);CHKERRQ(ierr); 741a061e289SJed Brown } 742a061e289SJed Brown } 743a061e289SJed Brown } 744a061e289SJed Brown PetscFunctionReturn(0); 745a061e289SJed Brown } 746a061e289SJed Brown 747a061e289SJed Brown static PetscErrorCode MatShift_Nest(Mat A,PetscScalar a) 748a061e289SJed Brown { 749a061e289SJed Brown Mat_Nest *bA = (Mat_Nest*)A->data; 750a061e289SJed Brown PetscInt i; 751a061e289SJed Brown PetscErrorCode ierr; 75206a1af2fSStefano Zampini PetscBool nnzstate = PETSC_FALSE; 753a061e289SJed Brown 754a061e289SJed Brown PetscFunctionBegin; 755a061e289SJed Brown for (i=0; i<bA->nr; i++) { 75606a1af2fSStefano Zampini PetscObjectState subnnzstate = 0; 757ce94432eSBarry 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); 758a061e289SJed Brown ierr = MatShift(bA->m[i][i],a);CHKERRQ(ierr); 75906a1af2fSStefano Zampini ierr = MatGetNonzeroState(bA->m[i][i],&subnnzstate);CHKERRQ(ierr); 76006a1af2fSStefano Zampini nnzstate = (PetscBool)(nnzstate || bA->nnzstate[i*bA->nc+i] != subnnzstate); 76106a1af2fSStefano Zampini bA->nnzstate[i*bA->nc+i] = subnnzstate; 762a061e289SJed Brown } 76306a1af2fSStefano Zampini if (nnzstate) A->nonzerostate++; 764a061e289SJed Brown PetscFunctionReturn(0); 765a061e289SJed Brown } 766a061e289SJed Brown 76713135bc6SAlex Fikl static PetscErrorCode MatDiagonalSet_Nest(Mat A,Vec D,InsertMode is) 76813135bc6SAlex Fikl { 76913135bc6SAlex Fikl Mat_Nest *bA = (Mat_Nest*)A->data; 77013135bc6SAlex Fikl PetscInt i; 77113135bc6SAlex Fikl PetscErrorCode ierr; 77206a1af2fSStefano Zampini PetscBool nnzstate = PETSC_FALSE; 77313135bc6SAlex Fikl 77413135bc6SAlex Fikl PetscFunctionBegin; 77513135bc6SAlex Fikl for (i=0; i<bA->nr; i++) { 77606a1af2fSStefano Zampini PetscObjectState subnnzstate = 0; 77713135bc6SAlex Fikl Vec bv; 77813135bc6SAlex Fikl ierr = VecGetSubVector(D,bA->isglobal.row[i],&bv);CHKERRQ(ierr); 77913135bc6SAlex Fikl if (bA->m[i][i]) { 78013135bc6SAlex Fikl ierr = MatDiagonalSet(bA->m[i][i],bv,is);CHKERRQ(ierr); 78106a1af2fSStefano Zampini ierr = MatGetNonzeroState(bA->m[i][i],&subnnzstate);CHKERRQ(ierr); 78213135bc6SAlex Fikl } 78313135bc6SAlex Fikl ierr = VecRestoreSubVector(D,bA->isglobal.row[i],&bv);CHKERRQ(ierr); 78406a1af2fSStefano Zampini nnzstate = (PetscBool)(nnzstate || bA->nnzstate[i*bA->nc+i] != subnnzstate); 78506a1af2fSStefano Zampini bA->nnzstate[i*bA->nc+i] = subnnzstate; 78613135bc6SAlex Fikl } 78706a1af2fSStefano Zampini if (nnzstate) A->nonzerostate++; 78813135bc6SAlex Fikl PetscFunctionReturn(0); 78913135bc6SAlex Fikl } 79013135bc6SAlex Fikl 791f8170845SAlex Fikl static PetscErrorCode MatSetRandom_Nest(Mat A,PetscRandom rctx) 792f8170845SAlex Fikl { 793f8170845SAlex Fikl Mat_Nest *bA = (Mat_Nest*)A->data; 794f8170845SAlex Fikl PetscInt i,j; 795f8170845SAlex Fikl PetscErrorCode ierr; 796f8170845SAlex Fikl 797f8170845SAlex Fikl PetscFunctionBegin; 798f8170845SAlex Fikl for (i=0; i<bA->nr; i++) { 799f8170845SAlex Fikl for (j=0; j<bA->nc; j++) { 800f8170845SAlex Fikl if (bA->m[i][j]) { 801f8170845SAlex Fikl ierr = MatSetRandom(bA->m[i][j],rctx);CHKERRQ(ierr); 802f8170845SAlex Fikl } 803f8170845SAlex Fikl } 804f8170845SAlex Fikl } 805f8170845SAlex Fikl PetscFunctionReturn(0); 806f8170845SAlex Fikl } 807f8170845SAlex Fikl 8082a7a6963SBarry Smith static PetscErrorCode MatCreateVecs_Nest(Mat A,Vec *right,Vec *left) 809d8588912SDave May { 810d8588912SDave May Mat_Nest *bA = (Mat_Nest*)A->data; 811d8588912SDave May Vec *L,*R; 812d8588912SDave May MPI_Comm comm; 813d8588912SDave May PetscInt i,j; 814d8588912SDave May PetscErrorCode ierr; 815d8588912SDave May 816d8588912SDave May PetscFunctionBegin; 817ce94432eSBarry Smith ierr = PetscObjectGetComm((PetscObject)A,&comm);CHKERRQ(ierr); 818d8588912SDave May if (right) { 819d8588912SDave May /* allocate R */ 820854ce69bSBarry Smith ierr = PetscMalloc1(bA->nc, &R);CHKERRQ(ierr); 821d8588912SDave May /* Create the right vectors */ 822d8588912SDave May for (j=0; j<bA->nc; j++) { 823d8588912SDave May for (i=0; i<bA->nr; i++) { 824d8588912SDave May if (bA->m[i][j]) { 8252a7a6963SBarry Smith ierr = MatCreateVecs(bA->m[i][j],&R[j],NULL);CHKERRQ(ierr); 826d8588912SDave May break; 827d8588912SDave May } 828d8588912SDave May } 8296c4ed002SBarry Smith if (i==bA->nr) SETERRQ(PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONG, "Mat(Nest) contains a null column."); 830d8588912SDave May } 831f349c1fdSJed Brown ierr = VecCreateNest(comm,bA->nc,bA->isglobal.col,R,right);CHKERRQ(ierr); 832d8588912SDave May /* hand back control to the nest vector */ 833d8588912SDave May for (j=0; j<bA->nc; j++) { 8346bf464f9SBarry Smith ierr = VecDestroy(&R[j]);CHKERRQ(ierr); 835d8588912SDave May } 836d8588912SDave May ierr = PetscFree(R);CHKERRQ(ierr); 837d8588912SDave May } 838d8588912SDave May 839d8588912SDave May if (left) { 840d8588912SDave May /* allocate L */ 841854ce69bSBarry Smith ierr = PetscMalloc1(bA->nr, &L);CHKERRQ(ierr); 842d8588912SDave May /* Create the left vectors */ 843d8588912SDave May for (i=0; i<bA->nr; i++) { 844d8588912SDave May for (j=0; j<bA->nc; j++) { 845d8588912SDave May if (bA->m[i][j]) { 8462a7a6963SBarry Smith ierr = MatCreateVecs(bA->m[i][j],NULL,&L[i]);CHKERRQ(ierr); 847d8588912SDave May break; 848d8588912SDave May } 849d8588912SDave May } 8506c4ed002SBarry Smith if (j==bA->nc) SETERRQ(PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONG, "Mat(Nest) contains a null row."); 851d8588912SDave May } 852d8588912SDave May 853f349c1fdSJed Brown ierr = VecCreateNest(comm,bA->nr,bA->isglobal.row,L,left);CHKERRQ(ierr); 854d8588912SDave May for (i=0; i<bA->nr; i++) { 8556bf464f9SBarry Smith ierr = VecDestroy(&L[i]);CHKERRQ(ierr); 856d8588912SDave May } 857d8588912SDave May 858d8588912SDave May ierr = PetscFree(L);CHKERRQ(ierr); 859d8588912SDave May } 860d8588912SDave May PetscFunctionReturn(0); 861d8588912SDave May } 862d8588912SDave May 863207556f9SJed Brown static PetscErrorCode MatView_Nest(Mat A,PetscViewer viewer) 864d8588912SDave May { 865d8588912SDave May Mat_Nest *bA = (Mat_Nest*)A->data; 86629e60adbSStefano Zampini PetscBool isascii,viewSub = PETSC_FALSE; 867d8588912SDave May PetscInt i,j; 868d8588912SDave May PetscErrorCode ierr; 869d8588912SDave May 870d8588912SDave May PetscFunctionBegin; 871251f4c67SDmitry Karpeev ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&isascii);CHKERRQ(ierr); 872d8588912SDave May if (isascii) { 873d8588912SDave May 87429e60adbSStefano Zampini ierr = PetscOptionsGetBool(((PetscObject)A)->options,((PetscObject)A)->prefix,"-mat_view_nest_sub",&viewSub,NULL);CHKERRQ(ierr); 875d86155a6SBarry Smith ierr = PetscViewerASCIIPrintf(viewer,"Matrix object: \n");CHKERRQ(ierr); 876d86155a6SBarry Smith ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr); 877d86155a6SBarry Smith ierr = PetscViewerASCIIPrintf(viewer, "type=nest, rows=%D, cols=%D \n",bA->nr,bA->nc);CHKERRQ(ierr); 878d8588912SDave May 879d86155a6SBarry Smith ierr = PetscViewerASCIIPrintf(viewer,"MatNest structure: \n");CHKERRQ(ierr); 880d8588912SDave May for (i=0; i<bA->nr; i++) { 881d8588912SDave May for (j=0; j<bA->nc; j++) { 88219fd82e9SBarry Smith MatType type; 883270f95d7SJed Brown char name[256] = "",prefix[256] = ""; 884d8588912SDave May PetscInt NR,NC; 885d8588912SDave May PetscBool isNest = PETSC_FALSE; 886d8588912SDave May 887d8588912SDave May if (!bA->m[i][j]) { 888d86155a6SBarry Smith CHKERRQ(ierr);PetscViewerASCIIPrintf(viewer, "(%D,%D) : NULL \n",i,j);CHKERRQ(ierr); 889d8588912SDave May continue; 890d8588912SDave May } 891d8588912SDave May ierr = MatGetSize(bA->m[i][j],&NR,&NC);CHKERRQ(ierr); 892d8588912SDave May ierr = MatGetType(bA->m[i][j], &type);CHKERRQ(ierr); 8938caf3d72SBarry Smith if (((PetscObject)bA->m[i][j])->name) {ierr = PetscSNPrintf(name,sizeof(name),"name=\"%s\", ",((PetscObject)bA->m[i][j])->name);CHKERRQ(ierr);} 8948caf3d72SBarry Smith if (((PetscObject)bA->m[i][j])->prefix) {ierr = PetscSNPrintf(prefix,sizeof(prefix),"prefix=\"%s\", ",((PetscObject)bA->m[i][j])->prefix);CHKERRQ(ierr);} 895251f4c67SDmitry Karpeev ierr = PetscObjectTypeCompare((PetscObject)bA->m[i][j],MATNEST,&isNest);CHKERRQ(ierr); 896d8588912SDave May 897270f95d7SJed Brown ierr = PetscViewerASCIIPrintf(viewer,"(%D,%D) : %s%stype=%s, rows=%D, cols=%D \n",i,j,name,prefix,type,NR,NC);CHKERRQ(ierr); 898d8588912SDave May 89929e60adbSStefano Zampini if (isNest || viewSub) { 900270f95d7SJed Brown ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr); /* push1 */ 901d8588912SDave May ierr = MatView(bA->m[i][j],viewer);CHKERRQ(ierr); 902270f95d7SJed Brown ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr); /* pop1 */ 903d8588912SDave May } 904d8588912SDave May } 905d8588912SDave May } 906d86155a6SBarry Smith ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr); /* pop0 */ 907d8588912SDave May } 908d8588912SDave May PetscFunctionReturn(0); 909d8588912SDave May } 910d8588912SDave May 911207556f9SJed Brown static PetscErrorCode MatZeroEntries_Nest(Mat A) 912d8588912SDave May { 913d8588912SDave May Mat_Nest *bA = (Mat_Nest*)A->data; 914d8588912SDave May PetscInt i,j; 915d8588912SDave May PetscErrorCode ierr; 916d8588912SDave May 917d8588912SDave May PetscFunctionBegin; 918d8588912SDave May for (i=0; i<bA->nr; i++) { 919d8588912SDave May for (j=0; j<bA->nc; j++) { 920d8588912SDave May if (!bA->m[i][j]) continue; 921d8588912SDave May ierr = MatZeroEntries(bA->m[i][j]);CHKERRQ(ierr); 922d8588912SDave May } 923d8588912SDave May } 924d8588912SDave May PetscFunctionReturn(0); 925d8588912SDave May } 926d8588912SDave May 927c222c20dSDavid Ham static PetscErrorCode MatCopy_Nest(Mat A,Mat B,MatStructure str) 928c222c20dSDavid Ham { 929c222c20dSDavid Ham Mat_Nest *bA = (Mat_Nest*)A->data,*bB = (Mat_Nest*)B->data; 930c222c20dSDavid Ham PetscInt i,j,nr = bA->nr,nc = bA->nc; 931c222c20dSDavid Ham PetscErrorCode ierr; 93206a1af2fSStefano Zampini PetscBool nnzstate = PETSC_FALSE; 933c222c20dSDavid Ham 934c222c20dSDavid Ham PetscFunctionBegin; 935c222c20dSDavid 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); 936c222c20dSDavid Ham for (i=0; i<nr; i++) { 937c222c20dSDavid Ham for (j=0; j<nc; j++) { 93806a1af2fSStefano Zampini PetscObjectState subnnzstate = 0; 93946a2b97cSJed Brown if (bA->m[i][j] && bB->m[i][j]) { 940c222c20dSDavid Ham ierr = MatCopy(bA->m[i][j],bB->m[i][j],str);CHKERRQ(ierr); 94146a2b97cSJed 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); 94206a1af2fSStefano Zampini ierr = MatGetNonzeroState(bB->m[i][j],&subnnzstate);CHKERRQ(ierr); 94306a1af2fSStefano Zampini nnzstate = (PetscBool)(nnzstate || bB->nnzstate[i*nc+j] != subnnzstate); 94406a1af2fSStefano Zampini bB->nnzstate[i*nc+j] = subnnzstate; 945c222c20dSDavid Ham } 946c222c20dSDavid Ham } 94706a1af2fSStefano Zampini if (nnzstate) B->nonzerostate++; 948c222c20dSDavid Ham PetscFunctionReturn(0); 949c222c20dSDavid Ham } 950c222c20dSDavid Ham 9516e76ffeaSPierre Jolivet static PetscErrorCode MatAXPY_Nest(Mat Y,PetscScalar a,Mat X,MatStructure str) 9526e76ffeaSPierre Jolivet { 9536e76ffeaSPierre Jolivet Mat_Nest *bY = (Mat_Nest*)Y->data,*bX = (Mat_Nest*)X->data; 9546e76ffeaSPierre Jolivet PetscInt i,j,nr = bY->nr,nc = bY->nc; 9556e76ffeaSPierre Jolivet PetscErrorCode ierr; 95606a1af2fSStefano Zampini PetscBool nnzstate = PETSC_FALSE; 9576e76ffeaSPierre Jolivet 9586e76ffeaSPierre Jolivet PetscFunctionBegin; 9596e76ffeaSPierre 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); 9606e76ffeaSPierre Jolivet for (i=0; i<nr; i++) { 9616e76ffeaSPierre Jolivet for (j=0; j<nc; j++) { 96206a1af2fSStefano Zampini PetscObjectState subnnzstate = 0; 9636e76ffeaSPierre Jolivet if (bY->m[i][j] && bX->m[i][j]) { 9646e76ffeaSPierre Jolivet ierr = MatAXPY(bY->m[i][j],a,bX->m[i][j],str);CHKERRQ(ierr); 965c066aebcSStefano Zampini } else if (bX->m[i][j]) { 966c066aebcSStefano Zampini Mat M; 967c066aebcSStefano Zampini 968060bfc19SStefano Zampini if (str != DIFFERENT_NONZERO_PATTERN) SETERRQ2(PetscObjectComm((PetscObject)Y),PETSC_ERR_ARG_INCOMP,"Matrix block does not exist at %D,%D. Use DIFFERENT_NONZERO_PATTERN",i,j); 969c066aebcSStefano Zampini ierr = MatDuplicate(bX->m[i][j],MAT_COPY_VALUES,&M);CHKERRQ(ierr); 970c066aebcSStefano Zampini ierr = MatNestSetSubMat(Y,i,j,M);CHKERRQ(ierr); 971c066aebcSStefano Zampini ierr = MatDestroy(&M);CHKERRQ(ierr); 972c066aebcSStefano Zampini } 973060bfc19SStefano Zampini if (bY->m[i][j]) { ierr = MatGetNonzeroState(bY->m[i][j],&subnnzstate);CHKERRQ(ierr); } 97406a1af2fSStefano Zampini nnzstate = (PetscBool)(nnzstate || bY->nnzstate[i*nc+j] != subnnzstate); 97506a1af2fSStefano Zampini bY->nnzstate[i*nc+j] = subnnzstate; 9766e76ffeaSPierre Jolivet } 9776e76ffeaSPierre Jolivet } 97806a1af2fSStefano Zampini if (nnzstate) Y->nonzerostate++; 9796e76ffeaSPierre Jolivet PetscFunctionReturn(0); 9806e76ffeaSPierre Jolivet } 9816e76ffeaSPierre Jolivet 982207556f9SJed Brown static PetscErrorCode MatDuplicate_Nest(Mat A,MatDuplicateOption op,Mat *B) 983d8588912SDave May { 984d8588912SDave May Mat_Nest *bA = (Mat_Nest*)A->data; 985841e96a3SJed Brown Mat *b; 986841e96a3SJed Brown PetscInt i,j,nr = bA->nr,nc = bA->nc; 987d8588912SDave May PetscErrorCode ierr; 988d8588912SDave May 989d8588912SDave May PetscFunctionBegin; 990785e854fSJed Brown ierr = PetscMalloc1(nr*nc,&b);CHKERRQ(ierr); 991841e96a3SJed Brown for (i=0; i<nr; i++) { 992841e96a3SJed Brown for (j=0; j<nc; j++) { 993841e96a3SJed Brown if (bA->m[i][j]) { 994841e96a3SJed Brown ierr = MatDuplicate(bA->m[i][j],op,&b[i*nc+j]);CHKERRQ(ierr); 995841e96a3SJed Brown } else { 9960298fd71SBarry Smith b[i*nc+j] = NULL; 997d8588912SDave May } 998d8588912SDave May } 999d8588912SDave May } 1000ce94432eSBarry Smith ierr = MatCreateNest(PetscObjectComm((PetscObject)A),nr,bA->isglobal.row,nc,bA->isglobal.col,b,B);CHKERRQ(ierr); 1001841e96a3SJed Brown /* Give the new MatNest exclusive ownership */ 1002841e96a3SJed Brown for (i=0; i<nr*nc; i++) { 10036bf464f9SBarry Smith ierr = MatDestroy(&b[i]);CHKERRQ(ierr); 1004d8588912SDave May } 1005d8588912SDave May ierr = PetscFree(b);CHKERRQ(ierr); 1006d8588912SDave May 1007841e96a3SJed Brown ierr = MatAssemblyBegin(*B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 1008841e96a3SJed Brown ierr = MatAssemblyEnd(*B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 1009d8588912SDave May PetscFunctionReturn(0); 1010d8588912SDave May } 1011d8588912SDave May 1012d8588912SDave May /* nest api */ 1013d8588912SDave May PetscErrorCode MatNestGetSubMat_Nest(Mat A,PetscInt idxm,PetscInt jdxm,Mat *mat) 1014d8588912SDave May { 1015d8588912SDave May Mat_Nest *bA = (Mat_Nest*)A->data; 10165fd66863SKarl Rupp 1017d8588912SDave May PetscFunctionBegin; 1018ce94432eSBarry Smith if (idxm >= bA->nr) SETERRQ2(PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_OUTOFRANGE,"Row too large: row %D max %D",idxm,bA->nr-1); 1019ce94432eSBarry Smith if (jdxm >= bA->nc) SETERRQ2(PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_OUTOFRANGE,"Col too large: row %D max %D",jdxm,bA->nc-1); 1020d8588912SDave May *mat = bA->m[idxm][jdxm]; 1021d8588912SDave May PetscFunctionReturn(0); 1022d8588912SDave May } 1023d8588912SDave May 10249ba0d327SJed Brown /*@ 1025d8588912SDave May MatNestGetSubMat - Returns a single, sub-matrix from a nest matrix. 1026d8588912SDave May 1027d8588912SDave May Not collective 1028d8588912SDave May 1029d8588912SDave May Input Parameters: 1030629881c0SJed Brown + A - nest matrix 1031d8588912SDave May . idxm - index of the matrix within the nest matrix 1032629881c0SJed Brown - jdxm - index of the matrix within the nest matrix 1033d8588912SDave May 1034d8588912SDave May Output Parameter: 1035d8588912SDave May . sub - matrix at index idxm,jdxm within the nest matrix 1036d8588912SDave May 1037d8588912SDave May Level: developer 1038d8588912SDave May 103979798668SBarry Smith .seealso: MatNestGetSize(), MatNestGetSubMats(), MatNestCreate(), MATNEST, MatNestSetSubMat(), 104079798668SBarry Smith MatNestGetLocalISs(), MatNestGetISs() 1041d8588912SDave May @*/ 10427087cfbeSBarry Smith PetscErrorCode MatNestGetSubMat(Mat A,PetscInt idxm,PetscInt jdxm,Mat *sub) 1043d8588912SDave May { 1044699a902aSJed Brown PetscErrorCode ierr; 1045d8588912SDave May 1046d8588912SDave May PetscFunctionBegin; 1047699a902aSJed Brown ierr = PetscUseMethod(A,"MatNestGetSubMat_C",(Mat,PetscInt,PetscInt,Mat*),(A,idxm,jdxm,sub));CHKERRQ(ierr); 1048d8588912SDave May PetscFunctionReturn(0); 1049d8588912SDave May } 1050d8588912SDave May 10510782ca92SJed Brown PetscErrorCode MatNestSetSubMat_Nest(Mat A,PetscInt idxm,PetscInt jdxm,Mat mat) 10520782ca92SJed Brown { 10530782ca92SJed Brown Mat_Nest *bA = (Mat_Nest*)A->data; 10540782ca92SJed Brown PetscInt m,n,M,N,mi,ni,Mi,Ni; 10550782ca92SJed Brown PetscErrorCode ierr; 10560782ca92SJed Brown 10570782ca92SJed Brown PetscFunctionBegin; 1058ce94432eSBarry Smith if (idxm >= bA->nr) SETERRQ2(PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_OUTOFRANGE,"Row too large: row %D max %D",idxm,bA->nr-1); 1059ce94432eSBarry Smith if (jdxm >= bA->nc) SETERRQ2(PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_OUTOFRANGE,"Col too large: row %D max %D",jdxm,bA->nc-1); 10600782ca92SJed Brown ierr = MatGetLocalSize(mat,&m,&n);CHKERRQ(ierr); 10610782ca92SJed Brown ierr = MatGetSize(mat,&M,&N);CHKERRQ(ierr); 10620782ca92SJed Brown ierr = ISGetLocalSize(bA->isglobal.row[idxm],&mi);CHKERRQ(ierr); 10630782ca92SJed Brown ierr = ISGetSize(bA->isglobal.row[idxm],&Mi);CHKERRQ(ierr); 10640782ca92SJed Brown ierr = ISGetLocalSize(bA->isglobal.col[jdxm],&ni);CHKERRQ(ierr); 10650782ca92SJed Brown ierr = ISGetSize(bA->isglobal.col[jdxm],&Ni);CHKERRQ(ierr); 1066ce94432eSBarry 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); 1067ce94432eSBarry 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); 106826fbe8dcSKarl Rupp 106906a1af2fSStefano Zampini /* do not increase object state */ 107006a1af2fSStefano Zampini if (mat == bA->m[idxm][jdxm]) PetscFunctionReturn(0); 107106a1af2fSStefano Zampini 10720782ca92SJed Brown ierr = PetscObjectReference((PetscObject)mat);CHKERRQ(ierr); 10730782ca92SJed Brown ierr = MatDestroy(&bA->m[idxm][jdxm]);CHKERRQ(ierr); 10740782ca92SJed Brown bA->m[idxm][jdxm] = mat; 107506a1af2fSStefano Zampini ierr = PetscObjectStateIncrease((PetscObject)A);CHKERRQ(ierr); 107606a1af2fSStefano Zampini ierr = MatGetNonzeroState(mat,&bA->nnzstate[idxm*bA->nc+jdxm]);CHKERRQ(ierr); 107706a1af2fSStefano Zampini A->nonzerostate++; 10780782ca92SJed Brown PetscFunctionReturn(0); 10790782ca92SJed Brown } 10800782ca92SJed Brown 10819ba0d327SJed Brown /*@ 10820782ca92SJed Brown MatNestSetSubMat - Set a single submatrix in the nest matrix. 10830782ca92SJed Brown 10840782ca92SJed Brown Logically collective on the submatrix communicator 10850782ca92SJed Brown 10860782ca92SJed Brown Input Parameters: 10870782ca92SJed Brown + A - nest matrix 10880782ca92SJed Brown . idxm - index of the matrix within the nest matrix 10890782ca92SJed Brown . jdxm - index of the matrix within the nest matrix 10900782ca92SJed Brown - sub - matrix at index idxm,jdxm within the nest matrix 10910782ca92SJed Brown 10920782ca92SJed Brown Notes: 10930782ca92SJed Brown The new submatrix must have the same size and communicator as that block of the nest. 10940782ca92SJed Brown 10950782ca92SJed Brown This increments the reference count of the submatrix. 10960782ca92SJed Brown 10970782ca92SJed Brown Level: developer 10980782ca92SJed Brown 109979798668SBarry Smith .seealso: MatNestSetSubMats(), MatNestGetSubMats(), MatNestGetLocalISs(), MATNEST, MatNestCreate(), 110079798668SBarry Smith MatNestGetSubMat(), MatNestGetISs(), MatNestGetSize() 11010782ca92SJed Brown @*/ 11020782ca92SJed Brown PetscErrorCode MatNestSetSubMat(Mat A,PetscInt idxm,PetscInt jdxm,Mat sub) 11030782ca92SJed Brown { 11040782ca92SJed Brown PetscErrorCode ierr; 11050782ca92SJed Brown 11060782ca92SJed Brown PetscFunctionBegin; 11070782ca92SJed Brown ierr = PetscUseMethod(A,"MatNestSetSubMat_C",(Mat,PetscInt,PetscInt,Mat),(A,idxm,jdxm,sub));CHKERRQ(ierr); 11080782ca92SJed Brown PetscFunctionReturn(0); 11090782ca92SJed Brown } 11100782ca92SJed Brown 1111d8588912SDave May PetscErrorCode MatNestGetSubMats_Nest(Mat A,PetscInt *M,PetscInt *N,Mat ***mat) 1112d8588912SDave May { 1113d8588912SDave May Mat_Nest *bA = (Mat_Nest*)A->data; 11145fd66863SKarl Rupp 1115d8588912SDave May PetscFunctionBegin; 111626fbe8dcSKarl Rupp if (M) *M = bA->nr; 111726fbe8dcSKarl Rupp if (N) *N = bA->nc; 111826fbe8dcSKarl Rupp if (mat) *mat = bA->m; 1119d8588912SDave May PetscFunctionReturn(0); 1120d8588912SDave May } 1121d8588912SDave May 1122d8588912SDave May /*@C 1123d8588912SDave May MatNestGetSubMats - Returns the entire two dimensional array of matrices defining a nest matrix. 1124d8588912SDave May 1125d8588912SDave May Not collective 1126d8588912SDave May 1127d8588912SDave May Input Parameters: 1128629881c0SJed Brown . A - nest matrix 1129d8588912SDave May 1130d8588912SDave May Output Parameter: 1131629881c0SJed Brown + M - number of rows in the nest matrix 1132d8588912SDave May . N - number of cols in the nest matrix 1133629881c0SJed Brown - mat - 2d array of matrices 1134d8588912SDave May 1135d8588912SDave May Notes: 1136d8588912SDave May 1137d8588912SDave May The user should not free the array mat. 1138d8588912SDave May 1139351962e3SVincent Le Chenadec In Fortran, this routine has a calling sequence 1140351962e3SVincent Le Chenadec $ call MatNestGetSubMats(A, M, N, mat, ierr) 1141351962e3SVincent Le Chenadec where the space allocated for the optional argument mat is assumed large enough (if provided). 1142351962e3SVincent Le Chenadec 1143d8588912SDave May Level: developer 1144d8588912SDave May 114579798668SBarry Smith .seealso: MatNestGetSize(), MatNestGetSubMat(), MatNestGetLocalISs(), MATNEST, MatNestCreate(), 114679798668SBarry Smith MatNestSetSubMats(), MatNestGetISs(), MatNestSetSubMat() 1147d8588912SDave May @*/ 11487087cfbeSBarry Smith PetscErrorCode MatNestGetSubMats(Mat A,PetscInt *M,PetscInt *N,Mat ***mat) 1149d8588912SDave May { 1150699a902aSJed Brown PetscErrorCode ierr; 1151d8588912SDave May 1152d8588912SDave May PetscFunctionBegin; 1153699a902aSJed Brown ierr = PetscUseMethod(A,"MatNestGetSubMats_C",(Mat,PetscInt*,PetscInt*,Mat***),(A,M,N,mat));CHKERRQ(ierr); 1154d8588912SDave May PetscFunctionReturn(0); 1155d8588912SDave May } 1156d8588912SDave May 11577087cfbeSBarry Smith PetscErrorCode MatNestGetSize_Nest(Mat A,PetscInt *M,PetscInt *N) 1158d8588912SDave May { 1159d8588912SDave May Mat_Nest *bA = (Mat_Nest*)A->data; 1160d8588912SDave May 1161d8588912SDave May PetscFunctionBegin; 116226fbe8dcSKarl Rupp if (M) *M = bA->nr; 116326fbe8dcSKarl Rupp if (N) *N = bA->nc; 1164d8588912SDave May PetscFunctionReturn(0); 1165d8588912SDave May } 1166d8588912SDave May 11679ba0d327SJed Brown /*@ 1168d8588912SDave May MatNestGetSize - Returns the size of the nest matrix. 1169d8588912SDave May 1170d8588912SDave May Not collective 1171d8588912SDave May 1172d8588912SDave May Input Parameters: 1173d8588912SDave May . A - nest matrix 1174d8588912SDave May 1175d8588912SDave May Output Parameter: 1176629881c0SJed Brown + M - number of rows in the nested mat 1177629881c0SJed Brown - N - number of cols in the nested mat 1178d8588912SDave May 1179d8588912SDave May Notes: 1180d8588912SDave May 1181d8588912SDave May Level: developer 1182d8588912SDave May 118379798668SBarry Smith .seealso: MatNestGetSubMat(), MatNestGetSubMats(), MATNEST, MatNestCreate(), MatNestGetLocalISs(), 118479798668SBarry Smith MatNestGetISs() 1185d8588912SDave May @*/ 11867087cfbeSBarry Smith PetscErrorCode MatNestGetSize(Mat A,PetscInt *M,PetscInt *N) 1187d8588912SDave May { 1188699a902aSJed Brown PetscErrorCode ierr; 1189d8588912SDave May 1190d8588912SDave May PetscFunctionBegin; 1191699a902aSJed Brown ierr = PetscUseMethod(A,"MatNestGetSize_C",(Mat,PetscInt*,PetscInt*),(A,M,N));CHKERRQ(ierr); 1192d8588912SDave May PetscFunctionReturn(0); 1193d8588912SDave May } 1194d8588912SDave May 1195f7a08781SBarry Smith static PetscErrorCode MatNestGetISs_Nest(Mat A,IS rows[],IS cols[]) 1196900e7ff2SJed Brown { 1197900e7ff2SJed Brown Mat_Nest *vs = (Mat_Nest*)A->data; 1198900e7ff2SJed Brown PetscInt i; 1199900e7ff2SJed Brown 1200900e7ff2SJed Brown PetscFunctionBegin; 1201900e7ff2SJed Brown if (rows) for (i=0; i<vs->nr; i++) rows[i] = vs->isglobal.row[i]; 1202900e7ff2SJed Brown if (cols) for (i=0; i<vs->nc; i++) cols[i] = vs->isglobal.col[i]; 1203900e7ff2SJed Brown PetscFunctionReturn(0); 1204900e7ff2SJed Brown } 1205900e7ff2SJed Brown 12063a4d7b9aSSatish Balay /*@C 1207900e7ff2SJed Brown MatNestGetISs - Returns the index sets partitioning the row and column spaces 1208900e7ff2SJed Brown 1209900e7ff2SJed Brown Not collective 1210900e7ff2SJed Brown 1211900e7ff2SJed Brown Input Parameters: 1212900e7ff2SJed Brown . A - nest matrix 1213900e7ff2SJed Brown 1214900e7ff2SJed Brown Output Parameter: 1215900e7ff2SJed Brown + rows - array of row index sets 1216900e7ff2SJed Brown - cols - array of column index sets 1217900e7ff2SJed Brown 1218900e7ff2SJed Brown Level: advanced 1219900e7ff2SJed Brown 1220900e7ff2SJed Brown Notes: 1221900e7ff2SJed Brown The user must have allocated arrays of the correct size. The reference count is not increased on the returned ISs. 1222900e7ff2SJed Brown 122379798668SBarry Smith .seealso: MatNestGetSubMat(), MatNestGetSubMats(), MatNestGetSize(), MatNestGetLocalISs(), MATNEST, 122479798668SBarry Smith MatNestCreate(), MatNestGetSubMats(), MatNestSetSubMats() 1225900e7ff2SJed Brown @*/ 1226900e7ff2SJed Brown PetscErrorCode MatNestGetISs(Mat A,IS rows[],IS cols[]) 1227900e7ff2SJed Brown { 1228900e7ff2SJed Brown PetscErrorCode ierr; 1229900e7ff2SJed Brown 1230900e7ff2SJed Brown PetscFunctionBegin; 1231900e7ff2SJed Brown PetscValidHeaderSpecific(A,MAT_CLASSID,1); 1232900e7ff2SJed Brown ierr = PetscUseMethod(A,"MatNestGetISs_C",(Mat,IS[],IS[]),(A,rows,cols));CHKERRQ(ierr); 1233900e7ff2SJed Brown PetscFunctionReturn(0); 1234900e7ff2SJed Brown } 1235900e7ff2SJed Brown 1236f7a08781SBarry Smith static PetscErrorCode MatNestGetLocalISs_Nest(Mat A,IS rows[],IS cols[]) 1237900e7ff2SJed Brown { 1238900e7ff2SJed Brown Mat_Nest *vs = (Mat_Nest*)A->data; 1239900e7ff2SJed Brown PetscInt i; 1240900e7ff2SJed Brown 1241900e7ff2SJed Brown PetscFunctionBegin; 1242900e7ff2SJed Brown if (rows) for (i=0; i<vs->nr; i++) rows[i] = vs->islocal.row[i]; 1243900e7ff2SJed Brown if (cols) for (i=0; i<vs->nc; i++) cols[i] = vs->islocal.col[i]; 1244900e7ff2SJed Brown PetscFunctionReturn(0); 1245900e7ff2SJed Brown } 1246900e7ff2SJed Brown 1247900e7ff2SJed Brown /*@C 1248900e7ff2SJed Brown MatNestGetLocalISs - Returns the index sets partitioning the row and column spaces 1249900e7ff2SJed Brown 1250900e7ff2SJed Brown Not collective 1251900e7ff2SJed Brown 1252900e7ff2SJed Brown Input Parameters: 1253900e7ff2SJed Brown . A - nest matrix 1254900e7ff2SJed Brown 1255900e7ff2SJed Brown Output Parameter: 12560298fd71SBarry Smith + rows - array of row index sets (or NULL to ignore) 12570298fd71SBarry Smith - cols - array of column index sets (or NULL to ignore) 1258900e7ff2SJed Brown 1259900e7ff2SJed Brown Level: advanced 1260900e7ff2SJed Brown 1261900e7ff2SJed Brown Notes: 1262900e7ff2SJed Brown The user must have allocated arrays of the correct size. The reference count is not increased on the returned ISs. 1263900e7ff2SJed Brown 126479798668SBarry Smith .seealso: MatNestGetSubMat(), MatNestGetSubMats(), MatNestGetSize(), MatNestGetISs(), MatNestCreate(), 126579798668SBarry Smith MATNEST, MatNestSetSubMats(), MatNestSetSubMat() 1266900e7ff2SJed Brown @*/ 1267900e7ff2SJed Brown PetscErrorCode MatNestGetLocalISs(Mat A,IS rows[],IS cols[]) 1268900e7ff2SJed Brown { 1269900e7ff2SJed Brown PetscErrorCode ierr; 1270900e7ff2SJed Brown 1271900e7ff2SJed Brown PetscFunctionBegin; 1272900e7ff2SJed Brown PetscValidHeaderSpecific(A,MAT_CLASSID,1); 1273900e7ff2SJed Brown ierr = PetscUseMethod(A,"MatNestGetLocalISs_C",(Mat,IS[],IS[]),(A,rows,cols));CHKERRQ(ierr); 1274900e7ff2SJed Brown PetscFunctionReturn(0); 1275900e7ff2SJed Brown } 1276900e7ff2SJed Brown 127719fd82e9SBarry Smith PetscErrorCode MatNestSetVecType_Nest(Mat A,VecType vtype) 1278207556f9SJed Brown { 1279207556f9SJed Brown PetscErrorCode ierr; 1280207556f9SJed Brown PetscBool flg; 1281207556f9SJed Brown 1282207556f9SJed Brown PetscFunctionBegin; 1283207556f9SJed Brown ierr = PetscStrcmp(vtype,VECNEST,&flg);CHKERRQ(ierr); 1284207556f9SJed Brown /* In reality, this only distinguishes VECNEST and "other" */ 12852a7a6963SBarry Smith if (flg) A->ops->getvecs = MatCreateVecs_Nest; 128612b53f24SSatish Balay else A->ops->getvecs = (PetscErrorCode (*)(Mat,Vec*,Vec*)) 0; 1287207556f9SJed Brown PetscFunctionReturn(0); 1288207556f9SJed Brown } 1289207556f9SJed Brown 1290207556f9SJed Brown /*@C 12912a7a6963SBarry Smith MatNestSetVecType - Sets the type of Vec returned by MatCreateVecs() 1292207556f9SJed Brown 1293207556f9SJed Brown Not collective 1294207556f9SJed Brown 1295207556f9SJed Brown Input Parameters: 1296207556f9SJed Brown + A - nest matrix 1297207556f9SJed Brown - vtype - type to use for creating vectors 1298207556f9SJed Brown 1299207556f9SJed Brown Notes: 1300207556f9SJed Brown 1301207556f9SJed Brown Level: developer 1302207556f9SJed Brown 130379798668SBarry Smith .seealso: MatCreateVecs(), MATNEST, MatNestCreate() 1304207556f9SJed Brown @*/ 130519fd82e9SBarry Smith PetscErrorCode MatNestSetVecType(Mat A,VecType vtype) 1306207556f9SJed Brown { 1307207556f9SJed Brown PetscErrorCode ierr; 1308207556f9SJed Brown 1309207556f9SJed Brown PetscFunctionBegin; 131019fd82e9SBarry Smith ierr = PetscTryMethod(A,"MatNestSetVecType_C",(Mat,VecType),(A,vtype));CHKERRQ(ierr); 1311207556f9SJed Brown PetscFunctionReturn(0); 1312207556f9SJed Brown } 1313207556f9SJed Brown 1314c8883902SJed Brown PetscErrorCode MatNestSetSubMats_Nest(Mat A,PetscInt nr,const IS is_row[],PetscInt nc,const IS is_col[],const Mat a[]) 1315d8588912SDave May { 1316c8883902SJed Brown Mat_Nest *s = (Mat_Nest*)A->data; 1317c8883902SJed Brown PetscInt i,j,m,n,M,N; 1318d8588912SDave May PetscErrorCode ierr; 131906a1af2fSStefano Zampini PetscBool cong; 1320d8588912SDave May 1321d8588912SDave May PetscFunctionBegin; 132206a1af2fSStefano Zampini ierr = MatReset_Nest(A);CHKERRQ(ierr); 132306a1af2fSStefano Zampini 1324c8883902SJed Brown s->nr = nr; 1325c8883902SJed Brown s->nc = nc; 1326d8588912SDave May 1327c8883902SJed Brown /* Create space for submatrices */ 1328854ce69bSBarry Smith ierr = PetscMalloc1(nr,&s->m);CHKERRQ(ierr); 1329c8883902SJed Brown for (i=0; i<nr; i++) { 1330854ce69bSBarry Smith ierr = PetscMalloc1(nc,&s->m[i]);CHKERRQ(ierr); 1331d8588912SDave May } 1332c8883902SJed Brown for (i=0; i<nr; i++) { 1333c8883902SJed Brown for (j=0; j<nc; j++) { 1334c8883902SJed Brown s->m[i][j] = a[i*nc+j]; 1335c8883902SJed Brown if (a[i*nc+j]) { 1336c8883902SJed Brown ierr = PetscObjectReference((PetscObject)a[i*nc+j]);CHKERRQ(ierr); 1337d8588912SDave May } 1338d8588912SDave May } 1339d8588912SDave May } 1340d8588912SDave May 13418188e55aSJed Brown ierr = MatSetUp_NestIS_Private(A,nr,is_row,nc,is_col);CHKERRQ(ierr); 1342d8588912SDave May 1343854ce69bSBarry Smith ierr = PetscMalloc1(nr,&s->row_len);CHKERRQ(ierr); 1344854ce69bSBarry Smith ierr = PetscMalloc1(nc,&s->col_len);CHKERRQ(ierr); 1345c8883902SJed Brown for (i=0; i<nr; i++) s->row_len[i]=-1; 1346c8883902SJed Brown for (j=0; j<nc; j++) s->col_len[j]=-1; 1347d8588912SDave May 134806a1af2fSStefano Zampini ierr = PetscCalloc1(nr*nc,&s->nnzstate);CHKERRQ(ierr); 134906a1af2fSStefano Zampini for (i=0; i<nr; i++) { 135006a1af2fSStefano Zampini for (j=0; j<nc; j++) { 135106a1af2fSStefano Zampini if (s->m[i][j]) { 135206a1af2fSStefano Zampini ierr = MatGetNonzeroState(s->m[i][j],&s->nnzstate[i*nc+j]);CHKERRQ(ierr); 135306a1af2fSStefano Zampini } 135406a1af2fSStefano Zampini } 135506a1af2fSStefano Zampini } 135606a1af2fSStefano Zampini 13578188e55aSJed Brown ierr = MatNestGetSizes_Private(A,&m,&n,&M,&N);CHKERRQ(ierr); 1358d8588912SDave May 1359c8883902SJed Brown ierr = PetscLayoutSetSize(A->rmap,M);CHKERRQ(ierr); 1360c8883902SJed Brown ierr = PetscLayoutSetLocalSize(A->rmap,m);CHKERRQ(ierr); 1361c8883902SJed Brown ierr = PetscLayoutSetSize(A->cmap,N);CHKERRQ(ierr); 1362c8883902SJed Brown ierr = PetscLayoutSetLocalSize(A->cmap,n);CHKERRQ(ierr); 1363c8883902SJed Brown 1364c8883902SJed Brown ierr = PetscLayoutSetUp(A->rmap);CHKERRQ(ierr); 1365c8883902SJed Brown ierr = PetscLayoutSetUp(A->cmap);CHKERRQ(ierr); 1366c8883902SJed Brown 136706a1af2fSStefano Zampini /* disable operations that are not supported for non-square matrices, 136806a1af2fSStefano Zampini or matrices for which is_row != is_col */ 136906a1af2fSStefano Zampini ierr = MatHasCongruentLayouts(A,&cong);CHKERRQ(ierr); 137006a1af2fSStefano Zampini if (cong && nr != nc) cong = PETSC_FALSE; 137106a1af2fSStefano Zampini if (cong) { 137206a1af2fSStefano Zampini for (i = 0; cong && i < nr; i++) { 1373320466b0SStefano Zampini ierr = ISEqualUnsorted(s->isglobal.row[i],s->isglobal.col[i],&cong);CHKERRQ(ierr); 137406a1af2fSStefano Zampini } 137506a1af2fSStefano Zampini } 137606a1af2fSStefano Zampini if (!cong) { 1377*381b8e50SStefano Zampini A->ops->missingdiagonal = NULL; 137806a1af2fSStefano Zampini A->ops->getdiagonal = NULL; 137906a1af2fSStefano Zampini A->ops->shift = NULL; 138006a1af2fSStefano Zampini A->ops->diagonalset = NULL; 138106a1af2fSStefano Zampini } 138206a1af2fSStefano Zampini 13831795a4d1SJed Brown ierr = PetscCalloc2(nr,&s->left,nc,&s->right);CHKERRQ(ierr); 138406a1af2fSStefano Zampini ierr = PetscObjectStateIncrease((PetscObject)A);CHKERRQ(ierr); 138506a1af2fSStefano Zampini A->nonzerostate++; 1386d8588912SDave May PetscFunctionReturn(0); 1387d8588912SDave May } 1388d8588912SDave May 1389c8883902SJed Brown /*@ 1390c8883902SJed Brown MatNestSetSubMats - Sets the nested submatrices 1391c8883902SJed Brown 1392c8883902SJed Brown Collective on Mat 1393c8883902SJed Brown 1394c8883902SJed Brown Input Parameter: 1395ffd6319bSRichard Tran Mills + A - nested matrix 1396c8883902SJed Brown . nr - number of nested row blocks 13970298fd71SBarry Smith . is_row - index sets for each nested row block, or NULL to make contiguous 1398c8883902SJed Brown . nc - number of nested column blocks 13990298fd71SBarry Smith . is_col - index sets for each nested column block, or NULL to make contiguous 14000298fd71SBarry Smith - a - row-aligned array of nr*nc submatrices, empty submatrices can be passed using NULL 1401c8883902SJed Brown 140206a1af2fSStefano Zampini Notes: this always resets any submatrix information previously set 140306a1af2fSStefano Zampini 1404c8883902SJed Brown Level: advanced 1405c8883902SJed Brown 140679798668SBarry Smith .seealso: MatCreateNest(), MATNEST, MatNestSetSubMat(), MatNestGetSubMat(), MatNestGetSubMats() 1407c8883902SJed Brown @*/ 1408c8883902SJed Brown PetscErrorCode MatNestSetSubMats(Mat A,PetscInt nr,const IS is_row[],PetscInt nc,const IS is_col[],const Mat a[]) 1409c8883902SJed Brown { 1410c8883902SJed Brown PetscErrorCode ierr; 141106a1af2fSStefano Zampini PetscInt i; 1412c8883902SJed Brown 1413c8883902SJed Brown PetscFunctionBegin; 1414c8883902SJed Brown PetscValidHeaderSpecific(A,MAT_CLASSID,1); 1415ce94432eSBarry Smith if (nr < 0) SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_OUTOFRANGE,"Number of rows cannot be negative"); 1416c8883902SJed Brown if (nr && is_row) { 1417c8883902SJed Brown PetscValidPointer(is_row,3); 1418c8883902SJed Brown for (i=0; i<nr; i++) PetscValidHeaderSpecific(is_row[i],IS_CLASSID,3); 1419c8883902SJed Brown } 1420ce94432eSBarry Smith if (nc < 0) SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_OUTOFRANGE,"Number of columns cannot be negative"); 14211664e352SJed Brown if (nc && is_col) { 1422c8883902SJed Brown PetscValidPointer(is_col,5); 14239b30a8f6SBarry Smith for (i=0; i<nc; i++) PetscValidHeaderSpecific(is_col[i],IS_CLASSID,5); 1424c8883902SJed Brown } 142506a1af2fSStefano Zampini if (nr*nc > 0) PetscValidPointer(a,6); 1426c8883902SJed 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); 1427c8883902SJed Brown PetscFunctionReturn(0); 1428c8883902SJed Brown } 1429d8588912SDave May 143045b6f7e9SBarry Smith static PetscErrorCode MatNestCreateAggregateL2G_Private(Mat A,PetscInt n,const IS islocal[],const IS isglobal[],PetscBool colflg,ISLocalToGlobalMapping *ltog) 143177019fcaSJed Brown { 143277019fcaSJed Brown PetscErrorCode ierr; 143377019fcaSJed Brown PetscBool flg; 143477019fcaSJed Brown PetscInt i,j,m,mi,*ix; 143577019fcaSJed Brown 143677019fcaSJed Brown PetscFunctionBegin; 1437aea6d515SStefano Zampini *ltog = NULL; 143877019fcaSJed Brown for (i=0,m=0,flg=PETSC_FALSE; i<n; i++) { 143977019fcaSJed Brown if (islocal[i]) { 1440aea6d515SStefano Zampini ierr = ISGetLocalSize(islocal[i],&mi);CHKERRQ(ierr); 144177019fcaSJed Brown flg = PETSC_TRUE; /* We found a non-trivial entry */ 144277019fcaSJed Brown } else { 1443aea6d515SStefano Zampini ierr = ISGetLocalSize(isglobal[i],&mi);CHKERRQ(ierr); 144477019fcaSJed Brown } 144577019fcaSJed Brown m += mi; 144677019fcaSJed Brown } 1447aea6d515SStefano Zampini if (!flg) PetscFunctionReturn(0); 1448aea6d515SStefano Zampini 1449785e854fSJed Brown ierr = PetscMalloc1(m,&ix);CHKERRQ(ierr); 1450165cd838SBarry Smith for (i=0,m=0; i<n; i++) { 14510298fd71SBarry Smith ISLocalToGlobalMapping smap = NULL; 1452e108cb99SStefano Zampini Mat sub = NULL; 1453f6d38dbbSStefano Zampini PetscSF sf; 1454f6d38dbbSStefano Zampini PetscLayout map; 1455aea6d515SStefano Zampini const PetscInt *ix2; 145677019fcaSJed Brown 1457165cd838SBarry Smith if (!colflg) { 145877019fcaSJed Brown ierr = MatNestFindNonzeroSubMatRow(A,i,&sub);CHKERRQ(ierr); 145977019fcaSJed Brown } else { 146077019fcaSJed Brown ierr = MatNestFindNonzeroSubMatCol(A,i,&sub);CHKERRQ(ierr); 146177019fcaSJed Brown } 1462191fd14bSBarry Smith if (sub) { 1463191fd14bSBarry Smith if (!colflg) { 1464191fd14bSBarry Smith ierr = MatGetLocalToGlobalMapping(sub,&smap,NULL);CHKERRQ(ierr); 1465191fd14bSBarry Smith } else { 1466191fd14bSBarry Smith ierr = MatGetLocalToGlobalMapping(sub,NULL,&smap);CHKERRQ(ierr); 1467191fd14bSBarry Smith } 1468191fd14bSBarry Smith } 146977019fcaSJed Brown /* 147077019fcaSJed Brown Now we need to extract the monolithic global indices that correspond to the given split global indices. 147177019fcaSJed 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. 147277019fcaSJed Brown */ 1473aea6d515SStefano Zampini ierr = ISGetIndices(isglobal[i],&ix2);CHKERRQ(ierr); 1474aea6d515SStefano Zampini if (islocal[i]) { 1475aea6d515SStefano Zampini PetscInt *ilocal,*iremote; 1476aea6d515SStefano Zampini PetscInt mil,nleaves; 1477aea6d515SStefano Zampini 1478aea6d515SStefano Zampini ierr = ISGetLocalSize(islocal[i],&mi);CHKERRQ(ierr); 1479aea6d515SStefano Zampini if (!smap) SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_PLIB,"Missing local to global map"); 1480aea6d515SStefano Zampini for (j=0; j<mi; j++) ix[m+j] = j; 1481aea6d515SStefano Zampini ierr = ISLocalToGlobalMappingApply(smap,mi,ix+m,ix+m);CHKERRQ(ierr); 1482aea6d515SStefano Zampini 1483aea6d515SStefano Zampini /* PetscSFSetGraphLayout does not like negative indices */ 1484aea6d515SStefano Zampini ierr = PetscMalloc2(mi,&ilocal,mi,&iremote);CHKERRQ(ierr); 1485aea6d515SStefano Zampini for (j=0, nleaves = 0; j<mi; j++) { 1486aea6d515SStefano Zampini if (ix[m+j] < 0) continue; 1487aea6d515SStefano Zampini ilocal[nleaves] = j; 1488aea6d515SStefano Zampini iremote[nleaves] = ix[m+j]; 1489aea6d515SStefano Zampini nleaves++; 1490aea6d515SStefano Zampini } 1491aea6d515SStefano Zampini ierr = ISGetLocalSize(isglobal[i],&mil);CHKERRQ(ierr); 1492aea6d515SStefano Zampini ierr = PetscSFCreate(PetscObjectComm((PetscObject)A),&sf);CHKERRQ(ierr); 1493aea6d515SStefano Zampini ierr = PetscLayoutCreate(PetscObjectComm((PetscObject)A),&map);CHKERRQ(ierr); 1494aea6d515SStefano Zampini ierr = PetscLayoutSetLocalSize(map,mil);CHKERRQ(ierr); 1495f6d38dbbSStefano Zampini ierr = PetscLayoutSetUp(map);CHKERRQ(ierr); 1496aea6d515SStefano Zampini ierr = PetscSFSetGraphLayout(sf,map,nleaves,ilocal,PETSC_USE_POINTER,iremote);CHKERRQ(ierr); 1497f6d38dbbSStefano Zampini ierr = PetscLayoutDestroy(&map);CHKERRQ(ierr); 1498f6d38dbbSStefano Zampini ierr = PetscSFBcastBegin(sf,MPIU_INT,ix2,ix + m);CHKERRQ(ierr); 1499f6d38dbbSStefano Zampini ierr = PetscSFBcastEnd(sf,MPIU_INT,ix2,ix + m);CHKERRQ(ierr); 1500f6d38dbbSStefano Zampini ierr = PetscSFDestroy(&sf);CHKERRQ(ierr); 1501aea6d515SStefano Zampini ierr = PetscFree2(ilocal,iremote);CHKERRQ(ierr); 1502aea6d515SStefano Zampini } else { 1503aea6d515SStefano Zampini ierr = ISGetLocalSize(isglobal[i],&mi);CHKERRQ(ierr); 1504aea6d515SStefano Zampini for (j=0; j<mi; j++) ix[m+j] = ix2[i]; 1505aea6d515SStefano Zampini } 1506aea6d515SStefano Zampini ierr = ISRestoreIndices(isglobal[i],&ix2);CHKERRQ(ierr); 150777019fcaSJed Brown m += mi; 150877019fcaSJed Brown } 1509f0413b6fSBarry Smith ierr = ISLocalToGlobalMappingCreate(PetscObjectComm((PetscObject)A),1,m,ix,PETSC_OWN_POINTER,ltog);CHKERRQ(ierr); 151077019fcaSJed Brown PetscFunctionReturn(0); 151177019fcaSJed Brown } 151277019fcaSJed Brown 151377019fcaSJed Brown 1514d8588912SDave May /* If an IS was provided, there is nothing Nest needs to do, otherwise Nest will build a strided IS */ 1515d8588912SDave May /* 1516d8588912SDave May nprocessors = NP 1517d8588912SDave May Nest x^T = ((g_0,g_1,...g_nprocs-1), (h_0,h_1,...h_NP-1)) 1518d8588912SDave May proc 0: => (g_0,h_0,) 1519d8588912SDave May proc 1: => (g_1,h_1,) 1520d8588912SDave May ... 1521d8588912SDave May proc nprocs-1: => (g_NP-1,h_NP-1,) 1522d8588912SDave May 1523d8588912SDave May proc 0: proc 1: proc nprocs-1: 1524d8588912SDave May is[0] = (0,1,2,...,nlocal(g_0)-1) (0,1,...,nlocal(g_1)-1) (0,1,...,nlocal(g_NP-1)) 1525d8588912SDave May 1526d8588912SDave May proc 0: 1527d8588912SDave May is[1] = (nlocal(g_0),nlocal(g_0)+1,...,nlocal(g_0)+nlocal(h_0)-1) 1528d8588912SDave May proc 1: 1529d8588912SDave May is[1] = (nlocal(g_1),nlocal(g_1)+1,...,nlocal(g_1)+nlocal(h_1)-1) 1530d8588912SDave May 1531d8588912SDave May proc NP-1: 1532d8588912SDave May is[1] = (nlocal(g_NP-1),nlocal(g_NP-1)+1,...,nlocal(g_NP-1)+nlocal(h_NP-1)-1) 1533d8588912SDave May */ 1534841e96a3SJed Brown static PetscErrorCode MatSetUp_NestIS_Private(Mat A,PetscInt nr,const IS is_row[],PetscInt nc,const IS is_col[]) 1535d8588912SDave May { 1536e2d7f03fSJed Brown Mat_Nest *vs = (Mat_Nest*)A->data; 15378188e55aSJed Brown PetscInt i,j,offset,n,nsum,bs; 1538d8588912SDave May PetscErrorCode ierr; 15390298fd71SBarry Smith Mat sub = NULL; 1540d8588912SDave May 1541d8588912SDave May PetscFunctionBegin; 1542854ce69bSBarry Smith ierr = PetscMalloc1(nr,&vs->isglobal.row);CHKERRQ(ierr); 1543854ce69bSBarry Smith ierr = PetscMalloc1(nc,&vs->isglobal.col);CHKERRQ(ierr); 1544d8588912SDave May if (is_row) { /* valid IS is passed in */ 1545d8588912SDave May /* refs on is[] are incremeneted */ 1546e2d7f03fSJed Brown for (i=0; i<vs->nr; i++) { 1547d8588912SDave May ierr = PetscObjectReference((PetscObject)is_row[i]);CHKERRQ(ierr); 154826fbe8dcSKarl Rupp 1549e2d7f03fSJed Brown vs->isglobal.row[i] = is_row[i]; 1550d8588912SDave May } 15512ae74bdbSJed Brown } else { /* Create the ISs by inspecting sizes of a submatrix in each row */ 15528188e55aSJed Brown nsum = 0; 15538188e55aSJed Brown for (i=0; i<vs->nr; i++) { /* Add up the local sizes to compute the aggregate offset */ 15548188e55aSJed Brown ierr = MatNestFindNonzeroSubMatRow(A,i,&sub);CHKERRQ(ierr); 1555ce94432eSBarry Smith if (!sub) SETERRQ1(PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_WRONG,"No nonzero submatrix in row %D",i); 15560298fd71SBarry Smith ierr = MatGetLocalSize(sub,&n,NULL);CHKERRQ(ierr); 1557ce94432eSBarry Smith if (n < 0) SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_WRONGSTATE,"Sizes have not yet been set for submatrix"); 15588188e55aSJed Brown nsum += n; 15598188e55aSJed Brown } 1560ce94432eSBarry Smith ierr = MPI_Scan(&nsum,&offset,1,MPIU_INT,MPI_SUM,PetscObjectComm((PetscObject)A));CHKERRQ(ierr); 156130bc264bSJed Brown offset -= nsum; 1562e2d7f03fSJed Brown for (i=0; i<vs->nr; i++) { 1563f349c1fdSJed Brown ierr = MatNestFindNonzeroSubMatRow(A,i,&sub);CHKERRQ(ierr); 15640298fd71SBarry Smith ierr = MatGetLocalSize(sub,&n,NULL);CHKERRQ(ierr); 15652ae74bdbSJed Brown ierr = MatGetBlockSize(sub,&bs);CHKERRQ(ierr); 1566ce94432eSBarry Smith ierr = ISCreateStride(PetscObjectComm((PetscObject)sub),n,offset,1,&vs->isglobal.row[i]);CHKERRQ(ierr); 1567e2d7f03fSJed Brown ierr = ISSetBlockSize(vs->isglobal.row[i],bs);CHKERRQ(ierr); 15682ae74bdbSJed Brown offset += n; 1569d8588912SDave May } 1570d8588912SDave May } 1571d8588912SDave May 1572d8588912SDave May if (is_col) { /* valid IS is passed in */ 1573d8588912SDave May /* refs on is[] are incremeneted */ 1574e2d7f03fSJed Brown for (j=0; j<vs->nc; j++) { 1575d8588912SDave May ierr = PetscObjectReference((PetscObject)is_col[j]);CHKERRQ(ierr); 157626fbe8dcSKarl Rupp 1577e2d7f03fSJed Brown vs->isglobal.col[j] = is_col[j]; 1578d8588912SDave May } 15792ae74bdbSJed Brown } else { /* Create the ISs by inspecting sizes of a submatrix in each column */ 15802ae74bdbSJed Brown offset = A->cmap->rstart; 15818188e55aSJed Brown nsum = 0; 15828188e55aSJed Brown for (j=0; j<vs->nc; j++) { 15838188e55aSJed Brown ierr = MatNestFindNonzeroSubMatCol(A,j,&sub);CHKERRQ(ierr); 1584ce94432eSBarry Smith if (!sub) SETERRQ1(PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_WRONG,"No nonzero submatrix in column %D",i); 15850298fd71SBarry Smith ierr = MatGetLocalSize(sub,NULL,&n);CHKERRQ(ierr); 1586ce94432eSBarry Smith if (n < 0) SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_WRONGSTATE,"Sizes have not yet been set for submatrix"); 15878188e55aSJed Brown nsum += n; 15888188e55aSJed Brown } 1589ce94432eSBarry Smith ierr = MPI_Scan(&nsum,&offset,1,MPIU_INT,MPI_SUM,PetscObjectComm((PetscObject)A));CHKERRQ(ierr); 159030bc264bSJed Brown offset -= nsum; 1591e2d7f03fSJed Brown for (j=0; j<vs->nc; j++) { 1592f349c1fdSJed Brown ierr = MatNestFindNonzeroSubMatCol(A,j,&sub);CHKERRQ(ierr); 15930298fd71SBarry Smith ierr = MatGetLocalSize(sub,NULL,&n);CHKERRQ(ierr); 15942ae74bdbSJed Brown ierr = MatGetBlockSize(sub,&bs);CHKERRQ(ierr); 1595ce94432eSBarry Smith ierr = ISCreateStride(PetscObjectComm((PetscObject)sub),n,offset,1,&vs->isglobal.col[j]);CHKERRQ(ierr); 1596e2d7f03fSJed Brown ierr = ISSetBlockSize(vs->isglobal.col[j],bs);CHKERRQ(ierr); 15972ae74bdbSJed Brown offset += n; 1598d8588912SDave May } 1599d8588912SDave May } 1600e2d7f03fSJed Brown 1601e2d7f03fSJed Brown /* Set up the local ISs */ 1602785e854fSJed Brown ierr = PetscMalloc1(vs->nr,&vs->islocal.row);CHKERRQ(ierr); 1603785e854fSJed Brown ierr = PetscMalloc1(vs->nc,&vs->islocal.col);CHKERRQ(ierr); 1604e2d7f03fSJed Brown for (i=0,offset=0; i<vs->nr; i++) { 1605e2d7f03fSJed Brown IS isloc; 16060298fd71SBarry Smith ISLocalToGlobalMapping rmap = NULL; 1607e2d7f03fSJed Brown PetscInt nlocal,bs; 1608e2d7f03fSJed Brown ierr = MatNestFindNonzeroSubMatRow(A,i,&sub);CHKERRQ(ierr); 16090298fd71SBarry Smith if (sub) {ierr = MatGetLocalToGlobalMapping(sub,&rmap,NULL);CHKERRQ(ierr);} 1610207556f9SJed Brown if (rmap) { 1611e2d7f03fSJed Brown ierr = MatGetBlockSize(sub,&bs);CHKERRQ(ierr); 1612e2d7f03fSJed Brown ierr = ISLocalToGlobalMappingGetSize(rmap,&nlocal);CHKERRQ(ierr); 1613e2d7f03fSJed Brown ierr = ISCreateStride(PETSC_COMM_SELF,nlocal,offset,1,&isloc);CHKERRQ(ierr); 1614e2d7f03fSJed Brown ierr = ISSetBlockSize(isloc,bs);CHKERRQ(ierr); 1615207556f9SJed Brown } else { 1616207556f9SJed Brown nlocal = 0; 16170298fd71SBarry Smith isloc = NULL; 1618207556f9SJed Brown } 1619e2d7f03fSJed Brown vs->islocal.row[i] = isloc; 1620e2d7f03fSJed Brown offset += nlocal; 1621e2d7f03fSJed Brown } 16228188e55aSJed Brown for (i=0,offset=0; i<vs->nc; i++) { 1623e2d7f03fSJed Brown IS isloc; 16240298fd71SBarry Smith ISLocalToGlobalMapping cmap = NULL; 1625e2d7f03fSJed Brown PetscInt nlocal,bs; 1626e2d7f03fSJed Brown ierr = MatNestFindNonzeroSubMatCol(A,i,&sub);CHKERRQ(ierr); 16270298fd71SBarry Smith if (sub) {ierr = MatGetLocalToGlobalMapping(sub,NULL,&cmap);CHKERRQ(ierr);} 1628207556f9SJed Brown if (cmap) { 1629e2d7f03fSJed Brown ierr = MatGetBlockSize(sub,&bs);CHKERRQ(ierr); 1630e2d7f03fSJed Brown ierr = ISLocalToGlobalMappingGetSize(cmap,&nlocal);CHKERRQ(ierr); 1631e2d7f03fSJed Brown ierr = ISCreateStride(PETSC_COMM_SELF,nlocal,offset,1,&isloc);CHKERRQ(ierr); 1632e2d7f03fSJed Brown ierr = ISSetBlockSize(isloc,bs);CHKERRQ(ierr); 1633207556f9SJed Brown } else { 1634207556f9SJed Brown nlocal = 0; 16350298fd71SBarry Smith isloc = NULL; 1636207556f9SJed Brown } 1637e2d7f03fSJed Brown vs->islocal.col[i] = isloc; 1638e2d7f03fSJed Brown offset += nlocal; 1639e2d7f03fSJed Brown } 16400189643fSJed Brown 164177019fcaSJed Brown /* Set up the aggregate ISLocalToGlobalMapping */ 164277019fcaSJed Brown { 164345b6f7e9SBarry Smith ISLocalToGlobalMapping rmap,cmap; 164445b6f7e9SBarry Smith ierr = MatNestCreateAggregateL2G_Private(A,vs->nr,vs->islocal.row,vs->isglobal.row,PETSC_FALSE,&rmap);CHKERRQ(ierr); 164545b6f7e9SBarry Smith ierr = MatNestCreateAggregateL2G_Private(A,vs->nc,vs->islocal.col,vs->isglobal.col,PETSC_TRUE,&cmap);CHKERRQ(ierr); 164677019fcaSJed Brown if (rmap && cmap) {ierr = MatSetLocalToGlobalMapping(A,rmap,cmap);CHKERRQ(ierr);} 164777019fcaSJed Brown ierr = ISLocalToGlobalMappingDestroy(&rmap);CHKERRQ(ierr); 164877019fcaSJed Brown ierr = ISLocalToGlobalMappingDestroy(&cmap);CHKERRQ(ierr); 164977019fcaSJed Brown } 165077019fcaSJed Brown 16510189643fSJed Brown #if defined(PETSC_USE_DEBUG) 16520189643fSJed Brown for (i=0; i<vs->nr; i++) { 16530189643fSJed Brown for (j=0; j<vs->nc; j++) { 16540189643fSJed Brown PetscInt m,n,M,N,mi,ni,Mi,Ni; 16550189643fSJed Brown Mat B = vs->m[i][j]; 16560189643fSJed Brown if (!B) continue; 16570189643fSJed Brown ierr = MatGetSize(B,&M,&N);CHKERRQ(ierr); 16580189643fSJed Brown ierr = MatGetLocalSize(B,&m,&n);CHKERRQ(ierr); 16590189643fSJed Brown ierr = ISGetSize(vs->isglobal.row[i],&Mi);CHKERRQ(ierr); 16600189643fSJed Brown ierr = ISGetSize(vs->isglobal.col[j],&Ni);CHKERRQ(ierr); 16610189643fSJed Brown ierr = ISGetLocalSize(vs->isglobal.row[i],&mi);CHKERRQ(ierr); 16620189643fSJed Brown ierr = ISGetLocalSize(vs->isglobal.col[j],&ni);CHKERRQ(ierr); 1663ce94432eSBarry 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); 1664ce94432eSBarry 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); 16650189643fSJed Brown } 16660189643fSJed Brown } 16670189643fSJed Brown #endif 1668a061e289SJed Brown 1669a061e289SJed Brown /* Set A->assembled if all non-null blocks are currently assembled */ 1670a061e289SJed Brown for (i=0; i<vs->nr; i++) { 1671a061e289SJed Brown for (j=0; j<vs->nc; j++) { 1672a061e289SJed Brown if (vs->m[i][j] && !vs->m[i][j]->assembled) PetscFunctionReturn(0); 1673a061e289SJed Brown } 1674a061e289SJed Brown } 1675a061e289SJed Brown A->assembled = PETSC_TRUE; 1676d8588912SDave May PetscFunctionReturn(0); 1677d8588912SDave May } 1678d8588912SDave May 167945c38901SJed Brown /*@C 1680659c6bb0SJed Brown MatCreateNest - Creates a new matrix containing several nested submatrices, each stored separately 1681659c6bb0SJed Brown 1682659c6bb0SJed Brown Collective on Mat 1683659c6bb0SJed Brown 1684659c6bb0SJed Brown Input Parameter: 1685659c6bb0SJed Brown + comm - Communicator for the new Mat 1686659c6bb0SJed Brown . nr - number of nested row blocks 16870298fd71SBarry Smith . is_row - index sets for each nested row block, or NULL to make contiguous 1688659c6bb0SJed Brown . nc - number of nested column blocks 16890298fd71SBarry Smith . is_col - index sets for each nested column block, or NULL to make contiguous 16900298fd71SBarry Smith - a - row-aligned array of nr*nc submatrices, empty submatrices can be passed using NULL 1691659c6bb0SJed Brown 1692659c6bb0SJed Brown Output Parameter: 1693659c6bb0SJed Brown . B - new matrix 1694659c6bb0SJed Brown 1695659c6bb0SJed Brown Level: advanced 1696659c6bb0SJed Brown 169779798668SBarry Smith .seealso: MatCreate(), VecCreateNest(), DMCreateMatrix(), MATNEST, MatNestSetSubMat(), 169879798668SBarry Smith MatNestGetSubMat(), MatNestGetLocalISs(), MatNestGetSize(), 169979798668SBarry Smith MatNestGetISs(), MatNestSetSubMats(), MatNestGetSubMats() 1700659c6bb0SJed Brown @*/ 17017087cfbeSBarry Smith PetscErrorCode MatCreateNest(MPI_Comm comm,PetscInt nr,const IS is_row[],PetscInt nc,const IS is_col[],const Mat a[],Mat *B) 1702d8588912SDave May { 1703d8588912SDave May Mat A; 1704d8588912SDave May PetscErrorCode ierr; 1705d8588912SDave May 1706d8588912SDave May PetscFunctionBegin; 1707c8883902SJed Brown *B = 0; 1708d8588912SDave May ierr = MatCreate(comm,&A);CHKERRQ(ierr); 1709c8883902SJed Brown ierr = MatSetType(A,MATNEST);CHKERRQ(ierr); 171091a28eb3SBarry Smith A->preallocated = PETSC_TRUE; 1711c8883902SJed Brown ierr = MatNestSetSubMats(A,nr,is_row,nc,is_col,a);CHKERRQ(ierr); 1712d8588912SDave May *B = A; 1713d8588912SDave May PetscFunctionReturn(0); 1714d8588912SDave May } 1715659c6bb0SJed Brown 1716b68353e5Sstefano_zampini static PetscErrorCode MatConvert_Nest_SeqAIJ_fast(Mat A,MatType newtype,MatReuse reuse,Mat *newmat) 1717b68353e5Sstefano_zampini { 1718b68353e5Sstefano_zampini Mat_Nest *nest = (Mat_Nest*)A->data; 171923875855Sstefano_zampini Mat *trans; 1720b68353e5Sstefano_zampini PetscScalar **avv; 1721b68353e5Sstefano_zampini PetscScalar *vv; 1722b68353e5Sstefano_zampini PetscInt **aii,**ajj; 1723b68353e5Sstefano_zampini PetscInt *ii,*jj,*ci; 1724b68353e5Sstefano_zampini PetscInt nr,nc,nnz,i,j; 1725b68353e5Sstefano_zampini PetscBool done; 1726b68353e5Sstefano_zampini PetscErrorCode ierr; 1727b68353e5Sstefano_zampini 1728b68353e5Sstefano_zampini PetscFunctionBegin; 1729b68353e5Sstefano_zampini ierr = MatGetSize(A,&nr,&nc);CHKERRQ(ierr); 1730b68353e5Sstefano_zampini if (reuse == MAT_REUSE_MATRIX) { 1731b68353e5Sstefano_zampini PetscInt rnr; 1732b68353e5Sstefano_zampini 1733b68353e5Sstefano_zampini ierr = MatGetRowIJ(*newmat,0,PETSC_FALSE,PETSC_FALSE,&rnr,(const PetscInt**)&ii,(const PetscInt**)&jj,&done);CHKERRQ(ierr); 1734b68353e5Sstefano_zampini if (!done) SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_PLIB,"MatGetRowIJ"); 1735b68353e5Sstefano_zampini if (rnr != nr) SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_USER,"Cannot reuse matrix, wrong number of rows"); 1736b68353e5Sstefano_zampini ierr = MatSeqAIJGetArray(*newmat,&vv);CHKERRQ(ierr); 1737b68353e5Sstefano_zampini } 1738b68353e5Sstefano_zampini /* extract CSR for nested SeqAIJ matrices */ 1739b68353e5Sstefano_zampini nnz = 0; 174023875855Sstefano_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); 1741b68353e5Sstefano_zampini for (i=0; i<nest->nr; ++i) { 1742b68353e5Sstefano_zampini for (j=0; j<nest->nc; ++j) { 1743b68353e5Sstefano_zampini Mat B = nest->m[i][j]; 1744b68353e5Sstefano_zampini if (B) { 1745b68353e5Sstefano_zampini PetscScalar *naa; 1746b68353e5Sstefano_zampini PetscInt *nii,*njj,nnr; 174723875855Sstefano_zampini PetscBool istrans; 1748b68353e5Sstefano_zampini 174923875855Sstefano_zampini ierr = PetscObjectTypeCompare((PetscObject)B,MATTRANSPOSEMAT,&istrans);CHKERRQ(ierr); 175023875855Sstefano_zampini if (istrans) { 175123875855Sstefano_zampini Mat Bt; 175223875855Sstefano_zampini 175323875855Sstefano_zampini ierr = MatTransposeGetMat(B,&Bt);CHKERRQ(ierr); 175423875855Sstefano_zampini ierr = MatTranspose(Bt,MAT_INITIAL_MATRIX,&trans[i*nest->nc+j]);CHKERRQ(ierr); 175523875855Sstefano_zampini B = trans[i*nest->nc+j]; 175623875855Sstefano_zampini } 1757b68353e5Sstefano_zampini ierr = MatGetRowIJ(B,0,PETSC_FALSE,PETSC_FALSE,&nnr,(const PetscInt**)&nii,(const PetscInt**)&njj,&done);CHKERRQ(ierr); 1758b68353e5Sstefano_zampini if (!done) SETERRQ(PetscObjectComm((PetscObject)B),PETSC_ERR_PLIB,"MatGetRowIJ"); 1759b68353e5Sstefano_zampini ierr = MatSeqAIJGetArray(B,&naa);CHKERRQ(ierr); 1760b68353e5Sstefano_zampini nnz += nii[nnr]; 1761b68353e5Sstefano_zampini 1762b68353e5Sstefano_zampini aii[i*nest->nc+j] = nii; 1763b68353e5Sstefano_zampini ajj[i*nest->nc+j] = njj; 1764b68353e5Sstefano_zampini avv[i*nest->nc+j] = naa; 1765b68353e5Sstefano_zampini } 1766b68353e5Sstefano_zampini } 1767b68353e5Sstefano_zampini } 1768b68353e5Sstefano_zampini if (reuse != MAT_REUSE_MATRIX) { 1769b68353e5Sstefano_zampini ierr = PetscMalloc1(nr+1,&ii);CHKERRQ(ierr); 1770b68353e5Sstefano_zampini ierr = PetscMalloc1(nnz,&jj);CHKERRQ(ierr); 1771b68353e5Sstefano_zampini ierr = PetscMalloc1(nnz,&vv);CHKERRQ(ierr); 1772b68353e5Sstefano_zampini } else { 1773b68353e5Sstefano_zampini if (nnz != ii[nr]) SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_USER,"Cannot reuse matrix, wrong number of nonzeros"); 1774b68353e5Sstefano_zampini } 1775b68353e5Sstefano_zampini 1776b68353e5Sstefano_zampini /* new row pointer */ 1777580bdb30SBarry Smith ierr = PetscArrayzero(ii,nr+1);CHKERRQ(ierr); 1778b68353e5Sstefano_zampini for (i=0; i<nest->nr; ++i) { 1779b68353e5Sstefano_zampini PetscInt ncr,rst; 1780b68353e5Sstefano_zampini 1781b68353e5Sstefano_zampini ierr = ISStrideGetInfo(nest->isglobal.row[i],&rst,NULL);CHKERRQ(ierr); 1782b68353e5Sstefano_zampini ierr = ISGetLocalSize(nest->isglobal.row[i],&ncr);CHKERRQ(ierr); 1783b68353e5Sstefano_zampini for (j=0; j<nest->nc; ++j) { 1784b68353e5Sstefano_zampini if (aii[i*nest->nc+j]) { 1785b68353e5Sstefano_zampini PetscInt *nii = aii[i*nest->nc+j]; 1786b68353e5Sstefano_zampini PetscInt ir; 1787b68353e5Sstefano_zampini 1788b68353e5Sstefano_zampini for (ir=rst; ir<ncr+rst; ++ir) { 1789b68353e5Sstefano_zampini ii[ir+1] += nii[1]-nii[0]; 1790b68353e5Sstefano_zampini nii++; 1791b68353e5Sstefano_zampini } 1792b68353e5Sstefano_zampini } 1793b68353e5Sstefano_zampini } 1794b68353e5Sstefano_zampini } 1795b68353e5Sstefano_zampini for (i=0; i<nr; i++) ii[i+1] += ii[i]; 1796b68353e5Sstefano_zampini 1797b68353e5Sstefano_zampini /* construct CSR for the new matrix */ 1798b68353e5Sstefano_zampini ierr = PetscCalloc1(nr,&ci);CHKERRQ(ierr); 1799b68353e5Sstefano_zampini for (i=0; i<nest->nr; ++i) { 1800b68353e5Sstefano_zampini PetscInt ncr,rst; 1801b68353e5Sstefano_zampini 1802b68353e5Sstefano_zampini ierr = ISStrideGetInfo(nest->isglobal.row[i],&rst,NULL);CHKERRQ(ierr); 1803b68353e5Sstefano_zampini ierr = ISGetLocalSize(nest->isglobal.row[i],&ncr);CHKERRQ(ierr); 1804b68353e5Sstefano_zampini for (j=0; j<nest->nc; ++j) { 1805b68353e5Sstefano_zampini if (aii[i*nest->nc+j]) { 1806b68353e5Sstefano_zampini PetscScalar *nvv = avv[i*nest->nc+j]; 1807b68353e5Sstefano_zampini PetscInt *nii = aii[i*nest->nc+j]; 1808b68353e5Sstefano_zampini PetscInt *njj = ajj[i*nest->nc+j]; 1809b68353e5Sstefano_zampini PetscInt ir,cst; 1810b68353e5Sstefano_zampini 1811b68353e5Sstefano_zampini ierr = ISStrideGetInfo(nest->isglobal.col[j],&cst,NULL);CHKERRQ(ierr); 1812b68353e5Sstefano_zampini for (ir=rst; ir<ncr+rst; ++ir) { 1813b68353e5Sstefano_zampini PetscInt ij,rsize = nii[1]-nii[0],ist = ii[ir]+ci[ir]; 1814b68353e5Sstefano_zampini 1815b68353e5Sstefano_zampini for (ij=0;ij<rsize;ij++) { 1816b68353e5Sstefano_zampini jj[ist+ij] = *njj+cst; 1817b68353e5Sstefano_zampini vv[ist+ij] = *nvv; 1818b68353e5Sstefano_zampini njj++; 1819b68353e5Sstefano_zampini nvv++; 1820b68353e5Sstefano_zampini } 1821b68353e5Sstefano_zampini ci[ir] += rsize; 1822b68353e5Sstefano_zampini nii++; 1823b68353e5Sstefano_zampini } 1824b68353e5Sstefano_zampini } 1825b68353e5Sstefano_zampini } 1826b68353e5Sstefano_zampini } 1827b68353e5Sstefano_zampini ierr = PetscFree(ci);CHKERRQ(ierr); 1828b68353e5Sstefano_zampini 1829b68353e5Sstefano_zampini /* restore info */ 1830b68353e5Sstefano_zampini for (i=0; i<nest->nr; ++i) { 1831b68353e5Sstefano_zampini for (j=0; j<nest->nc; ++j) { 1832b68353e5Sstefano_zampini Mat B = nest->m[i][j]; 1833b68353e5Sstefano_zampini if (B) { 1834b68353e5Sstefano_zampini PetscInt nnr = 0, k = i*nest->nc+j; 183523875855Sstefano_zampini 183623875855Sstefano_zampini B = (trans[k] ? trans[k] : B); 1837b68353e5Sstefano_zampini ierr = MatRestoreRowIJ(B,0,PETSC_FALSE,PETSC_FALSE,&nnr,(const PetscInt**)&aii[k],(const PetscInt**)&ajj[k],&done);CHKERRQ(ierr); 1838b68353e5Sstefano_zampini if (!done) SETERRQ(PetscObjectComm((PetscObject)B),PETSC_ERR_PLIB,"MatRestoreRowIJ"); 1839b68353e5Sstefano_zampini ierr = MatSeqAIJRestoreArray(B,&avv[k]);CHKERRQ(ierr); 184023875855Sstefano_zampini ierr = MatDestroy(&trans[k]);CHKERRQ(ierr); 1841b68353e5Sstefano_zampini } 1842b68353e5Sstefano_zampini } 1843b68353e5Sstefano_zampini } 184423875855Sstefano_zampini ierr = PetscFree4(aii,ajj,avv,trans);CHKERRQ(ierr); 1845b68353e5Sstefano_zampini 1846b68353e5Sstefano_zampini /* finalize newmat */ 1847b68353e5Sstefano_zampini if (reuse == MAT_INITIAL_MATRIX) { 1848b68353e5Sstefano_zampini ierr = MatCreateSeqAIJWithArrays(PetscObjectComm((PetscObject)A),nr,nc,ii,jj,vv,newmat);CHKERRQ(ierr); 1849b68353e5Sstefano_zampini } else if (reuse == MAT_INPLACE_MATRIX) { 1850b68353e5Sstefano_zampini Mat B; 1851b68353e5Sstefano_zampini 1852b68353e5Sstefano_zampini ierr = MatCreateSeqAIJWithArrays(PetscObjectComm((PetscObject)A),nr,nc,ii,jj,vv,&B);CHKERRQ(ierr); 1853b68353e5Sstefano_zampini ierr = MatHeaderReplace(A,&B);CHKERRQ(ierr); 1854b68353e5Sstefano_zampini } 1855b68353e5Sstefano_zampini ierr = MatAssemblyBegin(*newmat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 1856b68353e5Sstefano_zampini ierr = MatAssemblyEnd(*newmat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 1857b68353e5Sstefano_zampini { 1858b68353e5Sstefano_zampini Mat_SeqAIJ *a = (Mat_SeqAIJ*)((*newmat)->data); 1859b68353e5Sstefano_zampini a->free_a = PETSC_TRUE; 1860b68353e5Sstefano_zampini a->free_ij = PETSC_TRUE; 1861b68353e5Sstefano_zampini } 1862b68353e5Sstefano_zampini PetscFunctionReturn(0); 1863b68353e5Sstefano_zampini } 1864b68353e5Sstefano_zampini 1865cc2e6a90SBarry Smith PETSC_INTERN PetscErrorCode MatConvert_Nest_AIJ(Mat A,MatType newtype,MatReuse reuse,Mat *newmat) 1866629c3df2SDmitry Karpeev { 1867629c3df2SDmitry Karpeev PetscErrorCode ierr; 1868629c3df2SDmitry Karpeev Mat_Nest *nest = (Mat_Nest*)A->data; 186983b1a929SMark Adams PetscInt m,n,M,N,i,j,k,*dnnz,*onnz,rstart; 1870649b366bSFande Kong PetscInt cstart,cend; 1871b68353e5Sstefano_zampini PetscMPIInt size; 1872629c3df2SDmitry Karpeev Mat C; 1873629c3df2SDmitry Karpeev 1874629c3df2SDmitry Karpeev PetscFunctionBegin; 1875b68353e5Sstefano_zampini ierr = MPI_Comm_size(PetscObjectComm((PetscObject)A),&size);CHKERRQ(ierr); 1876b68353e5Sstefano_zampini if (size == 1) { /* look for a special case with SeqAIJ matrices and strided-1, contiguous, blocks */ 1877b68353e5Sstefano_zampini PetscInt nf; 1878b68353e5Sstefano_zampini PetscBool fast; 1879b68353e5Sstefano_zampini 1880b68353e5Sstefano_zampini ierr = PetscStrcmp(newtype,MATAIJ,&fast);CHKERRQ(ierr); 1881b68353e5Sstefano_zampini if (!fast) { 1882b68353e5Sstefano_zampini ierr = PetscStrcmp(newtype,MATSEQAIJ,&fast);CHKERRQ(ierr); 1883b68353e5Sstefano_zampini } 1884b68353e5Sstefano_zampini for (i=0; i<nest->nr && fast; ++i) { 1885b68353e5Sstefano_zampini for (j=0; j<nest->nc && fast; ++j) { 1886b68353e5Sstefano_zampini Mat B = nest->m[i][j]; 1887b68353e5Sstefano_zampini if (B) { 1888b68353e5Sstefano_zampini ierr = PetscObjectTypeCompare((PetscObject)B,MATSEQAIJ,&fast);CHKERRQ(ierr); 188923875855Sstefano_zampini if (!fast) { 189023875855Sstefano_zampini PetscBool istrans; 189123875855Sstefano_zampini 189223875855Sstefano_zampini ierr = PetscObjectTypeCompare((PetscObject)B,MATTRANSPOSEMAT,&istrans);CHKERRQ(ierr); 189323875855Sstefano_zampini if (istrans) { 189423875855Sstefano_zampini Mat Bt; 189523875855Sstefano_zampini 189623875855Sstefano_zampini ierr = MatTransposeGetMat(B,&Bt);CHKERRQ(ierr); 189723875855Sstefano_zampini ierr = PetscObjectTypeCompare((PetscObject)Bt,MATSEQAIJ,&fast);CHKERRQ(ierr); 189823875855Sstefano_zampini } 1899b68353e5Sstefano_zampini } 1900b68353e5Sstefano_zampini } 1901b68353e5Sstefano_zampini } 1902b68353e5Sstefano_zampini } 1903b68353e5Sstefano_zampini for (i=0, nf=0; i<nest->nr && fast; ++i) { 1904b68353e5Sstefano_zampini ierr = PetscObjectTypeCompare((PetscObject)nest->isglobal.row[i],ISSTRIDE,&fast);CHKERRQ(ierr); 1905b68353e5Sstefano_zampini if (fast) { 1906b68353e5Sstefano_zampini PetscInt f,s; 1907b68353e5Sstefano_zampini 1908b68353e5Sstefano_zampini ierr = ISStrideGetInfo(nest->isglobal.row[i],&f,&s);CHKERRQ(ierr); 1909b68353e5Sstefano_zampini if (f != nf || s != 1) { fast = PETSC_FALSE; } 1910b68353e5Sstefano_zampini else { 1911b68353e5Sstefano_zampini ierr = ISGetSize(nest->isglobal.row[i],&f);CHKERRQ(ierr); 1912b68353e5Sstefano_zampini nf += f; 1913b68353e5Sstefano_zampini } 1914b68353e5Sstefano_zampini } 1915b68353e5Sstefano_zampini } 1916b68353e5Sstefano_zampini for (i=0, nf=0; i<nest->nc && fast; ++i) { 1917b68353e5Sstefano_zampini ierr = PetscObjectTypeCompare((PetscObject)nest->isglobal.col[i],ISSTRIDE,&fast);CHKERRQ(ierr); 1918b68353e5Sstefano_zampini if (fast) { 1919b68353e5Sstefano_zampini PetscInt f,s; 1920b68353e5Sstefano_zampini 1921b68353e5Sstefano_zampini ierr = ISStrideGetInfo(nest->isglobal.col[i],&f,&s);CHKERRQ(ierr); 1922b68353e5Sstefano_zampini if (f != nf || s != 1) { fast = PETSC_FALSE; } 1923b68353e5Sstefano_zampini else { 1924b68353e5Sstefano_zampini ierr = ISGetSize(nest->isglobal.col[i],&f);CHKERRQ(ierr); 1925b68353e5Sstefano_zampini nf += f; 1926b68353e5Sstefano_zampini } 1927b68353e5Sstefano_zampini } 1928b68353e5Sstefano_zampini } 1929b68353e5Sstefano_zampini if (fast) { 1930b68353e5Sstefano_zampini ierr = MatConvert_Nest_SeqAIJ_fast(A,newtype,reuse,newmat);CHKERRQ(ierr); 1931b68353e5Sstefano_zampini PetscFunctionReturn(0); 1932b68353e5Sstefano_zampini } 1933b68353e5Sstefano_zampini } 1934629c3df2SDmitry Karpeev ierr = MatGetSize(A,&M,&N);CHKERRQ(ierr); 1935629c3df2SDmitry Karpeev ierr = MatGetLocalSize(A,&m,&n);CHKERRQ(ierr); 1936649b366bSFande Kong ierr = MatGetOwnershipRangeColumn(A,&cstart,&cend);CHKERRQ(ierr); 1937629c3df2SDmitry Karpeev switch (reuse) { 1938629c3df2SDmitry Karpeev case MAT_INITIAL_MATRIX: 1939ce94432eSBarry Smith ierr = MatCreate(PetscObjectComm((PetscObject)A),&C);CHKERRQ(ierr); 1940629c3df2SDmitry Karpeev ierr = MatSetType(C,newtype);CHKERRQ(ierr); 1941629c3df2SDmitry Karpeev ierr = MatSetSizes(C,m,n,M,N);CHKERRQ(ierr); 1942629c3df2SDmitry Karpeev *newmat = C; 1943629c3df2SDmitry Karpeev break; 1944629c3df2SDmitry Karpeev case MAT_REUSE_MATRIX: 1945629c3df2SDmitry Karpeev C = *newmat; 1946629c3df2SDmitry Karpeev break; 1947ce94432eSBarry Smith default: SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_SUP,"MatReuse"); 1948629c3df2SDmitry Karpeev } 1949785e854fSJed Brown ierr = PetscMalloc1(2*m,&dnnz);CHKERRQ(ierr); 1950629c3df2SDmitry Karpeev onnz = dnnz + m; 1951629c3df2SDmitry Karpeev for (k=0; k<m; k++) { 1952629c3df2SDmitry Karpeev dnnz[k] = 0; 1953629c3df2SDmitry Karpeev onnz[k] = 0; 1954629c3df2SDmitry Karpeev } 1955629c3df2SDmitry Karpeev for (j=0; j<nest->nc; ++j) { 1956629c3df2SDmitry Karpeev IS bNis; 1957629c3df2SDmitry Karpeev PetscInt bN; 1958629c3df2SDmitry Karpeev const PetscInt *bNindices; 1959629c3df2SDmitry Karpeev /* Using global column indices and ISAllGather() is not scalable. */ 1960629c3df2SDmitry Karpeev ierr = ISAllGather(nest->isglobal.col[j], &bNis);CHKERRQ(ierr); 1961629c3df2SDmitry Karpeev ierr = ISGetSize(bNis, &bN);CHKERRQ(ierr); 1962629c3df2SDmitry Karpeev ierr = ISGetIndices(bNis,&bNindices);CHKERRQ(ierr); 1963629c3df2SDmitry Karpeev for (i=0; i<nest->nr; ++i) { 1964629c3df2SDmitry Karpeev PetscSF bmsf; 1965649b366bSFande Kong PetscSFNode *iremote; 1966629c3df2SDmitry Karpeev Mat B; 1967649b366bSFande Kong PetscInt bm, *sub_dnnz,*sub_onnz, br; 1968629c3df2SDmitry Karpeev const PetscInt *bmindices; 1969629c3df2SDmitry Karpeev B = nest->m[i][j]; 1970629c3df2SDmitry Karpeev if (!B) continue; 1971629c3df2SDmitry Karpeev ierr = ISGetLocalSize(nest->isglobal.row[i],&bm);CHKERRQ(ierr); 1972629c3df2SDmitry Karpeev ierr = ISGetIndices(nest->isglobal.row[i],&bmindices);CHKERRQ(ierr); 1973ce94432eSBarry Smith ierr = PetscSFCreate(PetscObjectComm((PetscObject)A), &bmsf);CHKERRQ(ierr); 1974649b366bSFande Kong ierr = PetscMalloc1(bm,&iremote);CHKERRQ(ierr); 1975649b366bSFande Kong ierr = PetscMalloc1(bm,&sub_dnnz);CHKERRQ(ierr); 1976649b366bSFande Kong ierr = PetscMalloc1(bm,&sub_onnz);CHKERRQ(ierr); 1977649b366bSFande Kong for (k = 0; k < bm; ++k){ 1978649b366bSFande Kong sub_dnnz[k] = 0; 1979649b366bSFande Kong sub_onnz[k] = 0; 1980649b366bSFande Kong } 1981629c3df2SDmitry Karpeev /* 1982629c3df2SDmitry Karpeev Locate the owners for all of the locally-owned global row indices for this row block. 1983629c3df2SDmitry Karpeev These determine the roots of PetscSF used to communicate preallocation data to row owners. 1984629c3df2SDmitry Karpeev The roots correspond to the dnnz and onnz entries; thus, there are two roots per row. 1985629c3df2SDmitry Karpeev */ 198683b1a929SMark Adams ierr = MatGetOwnershipRange(B,&rstart,NULL);CHKERRQ(ierr); 1987629c3df2SDmitry Karpeev for (br = 0; br < bm; ++br) { 1988131c27b5Sprj- PetscInt row = bmindices[br], brncols, col; 1989629c3df2SDmitry Karpeev const PetscInt *brcols; 1990a4b3d3acSMatthew G Knepley PetscInt rowrel = 0; /* row's relative index on its owner rank */ 1991131c27b5Sprj- PetscMPIInt rowowner = 0; 1992629c3df2SDmitry Karpeev ierr = PetscLayoutFindOwnerIndex(A->rmap,row,&rowowner,&rowrel);CHKERRQ(ierr); 1993649b366bSFande Kong /* how many roots */ 1994649b366bSFande Kong iremote[br].rank = rowowner; iremote[br].index = rowrel; /* edge from bmdnnz to dnnz */ 1995649b366bSFande Kong /* get nonzero pattern */ 199683b1a929SMark Adams ierr = MatGetRow(B,br+rstart,&brncols,&brcols,NULL);CHKERRQ(ierr); 1997629c3df2SDmitry Karpeev for (k=0; k<brncols; k++) { 1998629c3df2SDmitry Karpeev col = bNindices[brcols[k]]; 1999649b366bSFande Kong if (col>=A->cmap->range[rowowner] && col<A->cmap->range[rowowner+1]) { 2000649b366bSFande Kong sub_dnnz[br]++; 2001649b366bSFande Kong } else { 2002649b366bSFande Kong sub_onnz[br]++; 2003649b366bSFande Kong } 2004629c3df2SDmitry Karpeev } 200583b1a929SMark Adams ierr = MatRestoreRow(B,br+rstart,&brncols,&brcols,NULL);CHKERRQ(ierr); 2006629c3df2SDmitry Karpeev } 2007629c3df2SDmitry Karpeev ierr = ISRestoreIndices(nest->isglobal.row[i],&bmindices);CHKERRQ(ierr); 2008629c3df2SDmitry Karpeev /* bsf will have to take care of disposing of bedges. */ 2009649b366bSFande Kong ierr = PetscSFSetGraph(bmsf,m,bm,NULL,PETSC_OWN_POINTER,iremote,PETSC_OWN_POINTER);CHKERRQ(ierr); 2010649b366bSFande Kong ierr = PetscSFReduceBegin(bmsf,MPIU_INT,sub_dnnz,dnnz,MPI_SUM);CHKERRQ(ierr); 2011649b366bSFande Kong ierr = PetscSFReduceEnd(bmsf,MPIU_INT,sub_dnnz,dnnz,MPI_SUM);CHKERRQ(ierr); 2012649b366bSFande Kong ierr = PetscSFReduceBegin(bmsf,MPIU_INT,sub_onnz,onnz,MPI_SUM);CHKERRQ(ierr); 2013649b366bSFande Kong ierr = PetscSFReduceEnd(bmsf,MPIU_INT,sub_onnz,onnz,MPI_SUM);CHKERRQ(ierr); 2014649b366bSFande Kong ierr = PetscFree(sub_dnnz);CHKERRQ(ierr); 2015649b366bSFande Kong ierr = PetscFree(sub_onnz);CHKERRQ(ierr); 2016629c3df2SDmitry Karpeev ierr = PetscSFDestroy(&bmsf);CHKERRQ(ierr); 2017629c3df2SDmitry Karpeev } 201822d28d08SBarry Smith ierr = ISRestoreIndices(bNis,&bNindices);CHKERRQ(ierr); 2019629c3df2SDmitry Karpeev ierr = ISDestroy(&bNis);CHKERRQ(ierr); 202065a4a0a3Sstefano_zampini } 202165a4a0a3Sstefano_zampini /* Resize preallocation if overestimated */ 202265a4a0a3Sstefano_zampini for (i=0;i<m;i++) { 202365a4a0a3Sstefano_zampini dnnz[i] = PetscMin(dnnz[i],A->cmap->n); 202465a4a0a3Sstefano_zampini onnz[i] = PetscMin(onnz[i],A->cmap->N - A->cmap->n); 2025629c3df2SDmitry Karpeev } 2026629c3df2SDmitry Karpeev ierr = MatSeqAIJSetPreallocation(C,0,dnnz);CHKERRQ(ierr); 2027629c3df2SDmitry Karpeev ierr = MatMPIAIJSetPreallocation(C,0,dnnz,0,onnz);CHKERRQ(ierr); 2028629c3df2SDmitry Karpeev ierr = PetscFree(dnnz);CHKERRQ(ierr); 2029629c3df2SDmitry Karpeev 2030629c3df2SDmitry Karpeev /* Fill by row */ 2031629c3df2SDmitry Karpeev for (j=0; j<nest->nc; ++j) { 2032629c3df2SDmitry Karpeev /* Using global column indices and ISAllGather() is not scalable. */ 2033629c3df2SDmitry Karpeev IS bNis; 2034629c3df2SDmitry Karpeev PetscInt bN; 2035629c3df2SDmitry Karpeev const PetscInt *bNindices; 2036629c3df2SDmitry Karpeev ierr = ISAllGather(nest->isglobal.col[j], &bNis);CHKERRQ(ierr); 2037629c3df2SDmitry Karpeev ierr = ISGetSize(bNis,&bN);CHKERRQ(ierr); 2038629c3df2SDmitry Karpeev ierr = ISGetIndices(bNis,&bNindices);CHKERRQ(ierr); 2039629c3df2SDmitry Karpeev for (i=0; i<nest->nr; ++i) { 2040629c3df2SDmitry Karpeev Mat B; 2041629c3df2SDmitry Karpeev PetscInt bm, br; 2042629c3df2SDmitry Karpeev const PetscInt *bmindices; 2043629c3df2SDmitry Karpeev B = nest->m[i][j]; 2044629c3df2SDmitry Karpeev if (!B) continue; 2045629c3df2SDmitry Karpeev ierr = ISGetLocalSize(nest->isglobal.row[i],&bm);CHKERRQ(ierr); 2046629c3df2SDmitry Karpeev ierr = ISGetIndices(nest->isglobal.row[i],&bmindices);CHKERRQ(ierr); 204783b1a929SMark Adams ierr = MatGetOwnershipRange(B,&rstart,NULL);CHKERRQ(ierr); 2048629c3df2SDmitry Karpeev for (br = 0; br < bm; ++br) { 2049629c3df2SDmitry Karpeev PetscInt row = bmindices[br], brncols, *cols; 2050629c3df2SDmitry Karpeev const PetscInt *brcols; 2051629c3df2SDmitry Karpeev const PetscScalar *brcoldata; 205283b1a929SMark Adams ierr = MatGetRow(B,br+rstart,&brncols,&brcols,&brcoldata);CHKERRQ(ierr); 2053785e854fSJed Brown ierr = PetscMalloc1(brncols,&cols);CHKERRQ(ierr); 205426fbe8dcSKarl Rupp for (k=0; k<brncols; k++) cols[k] = bNindices[brcols[k]]; 2055629c3df2SDmitry Karpeev /* 2056629c3df2SDmitry Karpeev Nest blocks are required to be nonoverlapping -- otherwise nest and monolithic index layouts wouldn't match. 2057629c3df2SDmitry Karpeev Thus, we could use INSERT_VALUES, but I prefer ADD_VALUES. 2058629c3df2SDmitry Karpeev */ 2059a2ea699eSBarry Smith ierr = MatSetValues(C,1,&row,brncols,cols,brcoldata,ADD_VALUES);CHKERRQ(ierr); 206083b1a929SMark Adams ierr = MatRestoreRow(B,br+rstart,&brncols,&brcols,&brcoldata);CHKERRQ(ierr); 2061629c3df2SDmitry Karpeev ierr = PetscFree(cols);CHKERRQ(ierr); 2062629c3df2SDmitry Karpeev } 2063629c3df2SDmitry Karpeev ierr = ISRestoreIndices(nest->isglobal.row[i],&bmindices);CHKERRQ(ierr); 2064629c3df2SDmitry Karpeev } 2065a2ea699eSBarry Smith ierr = ISRestoreIndices(bNis,&bNindices);CHKERRQ(ierr); 2066629c3df2SDmitry Karpeev ierr = ISDestroy(&bNis);CHKERRQ(ierr); 2067629c3df2SDmitry Karpeev } 2068629c3df2SDmitry Karpeev ierr = MatAssemblyBegin(C,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 2069629c3df2SDmitry Karpeev ierr = MatAssemblyEnd(C,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 2070629c3df2SDmitry Karpeev PetscFunctionReturn(0); 2071629c3df2SDmitry Karpeev } 2072629c3df2SDmitry Karpeev 20738b7d3b4bSBarry Smith PetscErrorCode MatHasOperation_Nest(Mat mat,MatOperation op,PetscBool *has) 20748b7d3b4bSBarry Smith { 20758b7d3b4bSBarry Smith Mat_Nest *bA = (Mat_Nest*)mat->data; 20768b7d3b4bSBarry Smith PetscInt i,j,nr = bA->nr,nc = bA->nc; 20778b7d3b4bSBarry Smith PetscBool flg; 207852c5f739Sprj- PetscErrorCode ierr; 207952c5f739Sprj- PetscFunctionBegin; 20808b7d3b4bSBarry Smith 208152c5f739Sprj- *has = PETSC_FALSE; 208252c5f739Sprj- if (op == MATOP_MULT_TRANSPOSE || op == MATOP_MAT_MULT) { 20838b7d3b4bSBarry Smith for (j=0; j<nc; j++) { 20848b7d3b4bSBarry Smith for (i=0; i<nr; i++) { 20858b7d3b4bSBarry Smith if (!bA->m[i][j]) continue; 208652c5f739Sprj- ierr = MatHasOperation(bA->m[i][j],op,&flg);CHKERRQ(ierr); 20878b7d3b4bSBarry Smith if (!flg) PetscFunctionReturn(0); 20888b7d3b4bSBarry Smith } 20898b7d3b4bSBarry Smith } 20908b7d3b4bSBarry Smith } 209152c5f739Sprj- if (((void**)mat->ops)[op] || (op == MATOP_MAT_MULT && flg)) *has = PETSC_TRUE; 20928b7d3b4bSBarry Smith PetscFunctionReturn(0); 20938b7d3b4bSBarry Smith } 20948b7d3b4bSBarry Smith 2095659c6bb0SJed Brown /*MC 2096659c6bb0SJed Brown MATNEST - MATNEST = "nest" - Matrix type consisting of nested submatrices, each stored separately. 2097659c6bb0SJed Brown 2098659c6bb0SJed Brown Level: intermediate 2099659c6bb0SJed Brown 2100659c6bb0SJed Brown Notes: 2101659c6bb0SJed Brown This matrix type permits scalable use of PCFieldSplit and avoids the large memory costs of extracting submatrices. 2102659c6bb0SJed Brown It allows the use of symmetric and block formats for parts of multi-physics simulations. 2103950540a4SJed Brown It is usually used with DMComposite and DMCreateMatrix() 2104659c6bb0SJed Brown 21058b7d3b4bSBarry Smith Each of the submatrices lives on the same MPI communicator as the original nest matrix (though they can have zero 21068b7d3b4bSBarry Smith rows/columns on some processes.) Thus this is not meant for cases where the submatrices live on far fewer processes 21078b7d3b4bSBarry Smith than the nest matrix. 21088b7d3b4bSBarry Smith 210979798668SBarry Smith .seealso: MatCreate(), MatType, MatCreateNest(), MatNestSetSubMat(), MatNestGetSubMat(), 211079798668SBarry Smith VecCreateNest(), DMCreateMatrix(), DMCOMPOSITE, MatNestSetVecType(), MatNestGetLocalISs(), 211179798668SBarry Smith MatNestGetISs(), MatNestSetSubMats(), MatNestGetSubMats() 2112659c6bb0SJed Brown M*/ 21138cc058d9SJed Brown PETSC_EXTERN PetscErrorCode MatCreate_Nest(Mat A) 2114c8883902SJed Brown { 2115c8883902SJed Brown Mat_Nest *s; 2116c8883902SJed Brown PetscErrorCode ierr; 2117c8883902SJed Brown 2118c8883902SJed Brown PetscFunctionBegin; 2119b00a9115SJed Brown ierr = PetscNewLog(A,&s);CHKERRQ(ierr); 2120c8883902SJed Brown A->data = (void*)s; 2121e7c19651SJed Brown 2122e7c19651SJed Brown s->nr = -1; 2123e7c19651SJed Brown s->nc = -1; 21240298fd71SBarry Smith s->m = NULL; 2125e7c19651SJed Brown s->splitassembly = PETSC_FALSE; 2126c8883902SJed Brown 2127c8883902SJed Brown ierr = PetscMemzero(A->ops,sizeof(*A->ops));CHKERRQ(ierr); 212826fbe8dcSKarl Rupp 2129c8883902SJed Brown A->ops->mult = MatMult_Nest; 21309194d70fSJed Brown A->ops->multadd = MatMultAdd_Nest; 2131c8883902SJed Brown A->ops->multtranspose = MatMultTranspose_Nest; 21329194d70fSJed Brown A->ops->multtransposeadd = MatMultTransposeAdd_Nest; 2133f8170845SAlex Fikl A->ops->transpose = MatTranspose_Nest; 2134c8883902SJed Brown A->ops->assemblybegin = MatAssemblyBegin_Nest; 2135c8883902SJed Brown A->ops->assemblyend = MatAssemblyEnd_Nest; 2136c8883902SJed Brown A->ops->zeroentries = MatZeroEntries_Nest; 2137c222c20dSDavid Ham A->ops->copy = MatCopy_Nest; 21386e76ffeaSPierre Jolivet A->ops->axpy = MatAXPY_Nest; 2139c8883902SJed Brown A->ops->duplicate = MatDuplicate_Nest; 21407dae84e0SHong Zhang A->ops->createsubmatrix = MatCreateSubMatrix_Nest; 2141c8883902SJed Brown A->ops->destroy = MatDestroy_Nest; 2142c8883902SJed Brown A->ops->view = MatView_Nest; 2143c8883902SJed Brown A->ops->getvecs = 0; /* Use VECNEST by calling MatNestSetVecType(A,VECNEST) */ 2144c8883902SJed Brown A->ops->getlocalsubmatrix = MatGetLocalSubMatrix_Nest; 2145c8883902SJed Brown A->ops->restorelocalsubmatrix = MatRestoreLocalSubMatrix_Nest; 2146429bac76SJed Brown A->ops->getdiagonal = MatGetDiagonal_Nest; 2147429bac76SJed Brown A->ops->diagonalscale = MatDiagonalScale_Nest; 2148a061e289SJed Brown A->ops->scale = MatScale_Nest; 2149a061e289SJed Brown A->ops->shift = MatShift_Nest; 215013135bc6SAlex Fikl A->ops->diagonalset = MatDiagonalSet_Nest; 2151f8170845SAlex Fikl A->ops->setrandom = MatSetRandom_Nest; 21528b7d3b4bSBarry Smith A->ops->hasoperation = MatHasOperation_Nest; 2153*381b8e50SStefano Zampini A->ops->missingdiagonal = MatMissingDiagonal_Nest; 2154c8883902SJed Brown 2155c8883902SJed Brown A->spptr = 0; 2156c8883902SJed Brown A->assembled = PETSC_FALSE; 2157c8883902SJed Brown 2158c8883902SJed Brown /* expose Nest api's */ 2159bdf89e91SBarry Smith ierr = PetscObjectComposeFunction((PetscObject)A,"MatNestGetSubMat_C", MatNestGetSubMat_Nest);CHKERRQ(ierr); 2160bdf89e91SBarry Smith ierr = PetscObjectComposeFunction((PetscObject)A,"MatNestSetSubMat_C", MatNestSetSubMat_Nest);CHKERRQ(ierr); 2161bdf89e91SBarry Smith ierr = PetscObjectComposeFunction((PetscObject)A,"MatNestGetSubMats_C", MatNestGetSubMats_Nest);CHKERRQ(ierr); 2162bdf89e91SBarry Smith ierr = PetscObjectComposeFunction((PetscObject)A,"MatNestGetSize_C", MatNestGetSize_Nest);CHKERRQ(ierr); 2163bdf89e91SBarry Smith ierr = PetscObjectComposeFunction((PetscObject)A,"MatNestGetISs_C", MatNestGetISs_Nest);CHKERRQ(ierr); 2164bdf89e91SBarry Smith ierr = PetscObjectComposeFunction((PetscObject)A,"MatNestGetLocalISs_C", MatNestGetLocalISs_Nest);CHKERRQ(ierr); 2165bdf89e91SBarry Smith ierr = PetscObjectComposeFunction((PetscObject)A,"MatNestSetVecType_C", MatNestSetVecType_Nest);CHKERRQ(ierr); 2166bdf89e91SBarry Smith ierr = PetscObjectComposeFunction((PetscObject)A,"MatNestSetSubMats_C", MatNestSetSubMats_Nest);CHKERRQ(ierr); 21670899c546SStefano Zampini ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_nest_mpiaij_C", MatConvert_Nest_AIJ);CHKERRQ(ierr); 21680899c546SStefano Zampini ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_nest_seqaij_C", MatConvert_Nest_AIJ);CHKERRQ(ierr); 216983b1a929SMark Adams ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_nest_aij_C", MatConvert_Nest_AIJ);CHKERRQ(ierr); 21705e3038f0Sstefano_zampini ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_nest_is_C", MatConvert_Nest_IS);CHKERRQ(ierr); 217152c5f739Sprj- ierr = PetscObjectComposeFunction((PetscObject)A,"MatMatMult_nest_mpidense_C",MatMatMult_Nest_Dense);CHKERRQ(ierr); 217252c5f739Sprj- ierr = PetscObjectComposeFunction((PetscObject)A,"MatMatMult_nest_seqdense_C",MatMatMult_Nest_Dense);CHKERRQ(ierr); 217352c5f739Sprj- ierr = PetscObjectComposeFunction((PetscObject)A,"MatMatMult_nest_dense_C", MatMatMult_Nest_Dense);CHKERRQ(ierr); 2174c8883902SJed Brown 2175c8883902SJed Brown ierr = PetscObjectChangeTypeName((PetscObject)A,MATNEST);CHKERRQ(ierr); 2176c8883902SJed Brown PetscFunctionReturn(0); 2177c8883902SJed Brown } 2178