xref: /petsc/src/mat/impls/submat/submat.c (revision 2c71b3e237ead271e4f3aa1505f92bf476e3413d)
1ee1cef2cSJed Brown 
2af0996ceSBarry Smith #include <petsc/private/matimpl.h>          /*I "petscmat.h" I*/
3ee1cef2cSJed Brown 
4ee1cef2cSJed Brown typedef struct {
5ee1cef2cSJed Brown   IS          isrow,iscol;      /* rows and columns in submatrix, only used to check consistency */
6ee1cef2cSJed Brown   Vec         lwork,rwork;      /* work vectors inside the scatters */
711c5f74dSStefano Zampini   Vec         lwork2,rwork2;    /* work vectors inside the scatters */
8ee1cef2cSJed Brown   VecScatter  lrestrict,rprolong;
9ee1cef2cSJed Brown   Mat         A;
1054e05e6cSHong Zhang } Mat_SubVirtual;
11ee1cef2cSJed Brown 
12bddd1ffdSAlp Dener static PetscErrorCode MatScale_SubMatrix(Mat N,PetscScalar a)
13bddd1ffdSAlp Dener {
14bddd1ffdSAlp Dener   Mat_SubVirtual *Na = (Mat_SubVirtual*)N->data;
15bddd1ffdSAlp Dener   PetscErrorCode ierr;
16bddd1ffdSAlp Dener 
17bddd1ffdSAlp Dener   PetscFunctionBegin;
1811c5f74dSStefano Zampini   ierr = MatScale(Na->A,a);CHKERRQ(ierr);
19bddd1ffdSAlp Dener   PetscFunctionReturn(0);
20bddd1ffdSAlp Dener }
21bddd1ffdSAlp Dener 
22bddd1ffdSAlp Dener static PetscErrorCode MatShift_SubMatrix(Mat N,PetscScalar a)
23bddd1ffdSAlp Dener {
24bddd1ffdSAlp Dener   Mat_SubVirtual *Na = (Mat_SubVirtual*)N->data;
25bddd1ffdSAlp Dener   PetscErrorCode ierr;
26bddd1ffdSAlp Dener 
27bddd1ffdSAlp Dener   PetscFunctionBegin;
2811c5f74dSStefano Zampini   ierr = MatShift(Na->A,a);CHKERRQ(ierr);
29ee1cef2cSJed Brown   PetscFunctionReturn(0);
30ee1cef2cSJed Brown }
31ee1cef2cSJed Brown 
32ee1cef2cSJed Brown static PetscErrorCode MatDiagonalScale_SubMatrix(Mat N,Vec left,Vec right)
33ee1cef2cSJed Brown {
3454e05e6cSHong Zhang   Mat_SubVirtual *Na = (Mat_SubVirtual*)N->data;
35ee1cef2cSJed Brown   PetscErrorCode ierr;
36ee1cef2cSJed Brown 
37ee1cef2cSJed Brown   PetscFunctionBegin;
38ee1cef2cSJed Brown   if (right) {
3911c5f74dSStefano Zampini     ierr = VecZeroEntries(Na->rwork);CHKERRQ(ierr);
4011c5f74dSStefano Zampini     ierr = VecScatterBegin(Na->rprolong,right,Na->rwork,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
4111c5f74dSStefano Zampini     ierr = VecScatterEnd(Na->rprolong,right,Na->rwork,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
42ee1cef2cSJed Brown   }
4311c5f74dSStefano Zampini   if (left) {
4411c5f74dSStefano Zampini     ierr = VecZeroEntries(Na->lwork);CHKERRQ(ierr);
4511c5f74dSStefano Zampini     ierr = VecScatterBegin(Na->lrestrict,left,Na->lwork,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
4611c5f74dSStefano Zampini     ierr = VecScatterEnd(Na->lrestrict,left,Na->lwork,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
47ee1cef2cSJed Brown   }
4811c5f74dSStefano Zampini   ierr = MatDiagonalScale(Na->A,left ? Na->lwork : NULL,right ? Na->rwork : NULL);CHKERRQ(ierr);
4911c5f74dSStefano Zampini   PetscFunctionReturn(0);
5011c5f74dSStefano Zampini }
5111c5f74dSStefano Zampini 
5211c5f74dSStefano Zampini static PetscErrorCode MatGetDiagonal_SubMatrix(Mat N,Vec d)
5311c5f74dSStefano Zampini {
5411c5f74dSStefano Zampini   Mat_SubVirtual *Na = (Mat_SubVirtual*)N->data;
5511c5f74dSStefano Zampini   PetscErrorCode ierr;
5611c5f74dSStefano Zampini 
5711c5f74dSStefano Zampini   PetscFunctionBegin;
5811c5f74dSStefano Zampini   ierr = MatGetDiagonal(Na->A,Na->rwork);CHKERRQ(ierr);
5911c5f74dSStefano Zampini   ierr = VecScatterBegin(Na->rprolong,Na->rwork,d,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
6011c5f74dSStefano Zampini   ierr = VecScatterEnd(Na->rprolong,Na->rwork,d,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
61ee1cef2cSJed Brown   PetscFunctionReturn(0);
62ee1cef2cSJed Brown }
63ee1cef2cSJed Brown 
64ee1cef2cSJed Brown static PetscErrorCode MatMult_SubMatrix(Mat N,Vec x,Vec y)
65ee1cef2cSJed Brown {
6654e05e6cSHong Zhang   Mat_SubVirtual *Na = (Mat_SubVirtual*)N->data;
67ee1cef2cSJed Brown   PetscErrorCode ierr;
68ee1cef2cSJed Brown 
69ee1cef2cSJed Brown   PetscFunctionBegin;
70ee1cef2cSJed Brown   ierr = VecZeroEntries(Na->rwork);CHKERRQ(ierr);
7111c5f74dSStefano Zampini   ierr = VecScatterBegin(Na->rprolong,x,Na->rwork,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
7211c5f74dSStefano Zampini   ierr = VecScatterEnd(Na->rprolong,x,Na->rwork,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
73ee1cef2cSJed Brown   ierr = MatMult(Na->A,Na->rwork,Na->lwork);CHKERRQ(ierr);
74ee1cef2cSJed Brown   ierr = VecScatterBegin(Na->lrestrict,Na->lwork,y,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
75ee1cef2cSJed Brown   ierr = VecScatterEnd(Na->lrestrict,Na->lwork,y,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
76ee1cef2cSJed Brown   PetscFunctionReturn(0);
77ee1cef2cSJed Brown }
78ee1cef2cSJed Brown 
79ee1cef2cSJed Brown static PetscErrorCode MatMultAdd_SubMatrix(Mat N,Vec v1,Vec v2,Vec v3)
80ee1cef2cSJed Brown {
8154e05e6cSHong Zhang   Mat_SubVirtual *Na = (Mat_SubVirtual*)N->data;
82ee1cef2cSJed Brown   PetscErrorCode ierr;
83ee1cef2cSJed Brown 
84ee1cef2cSJed Brown   PetscFunctionBegin;
85ee1cef2cSJed Brown   ierr = VecZeroEntries(Na->rwork);CHKERRQ(ierr);
8611c5f74dSStefano Zampini   ierr = VecScatterBegin(Na->rprolong,v1,Na->rwork,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
8711c5f74dSStefano Zampini   ierr = VecScatterEnd(Na->rprolong,v1,Na->rwork,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
8811c5f74dSStefano Zampini   if (v1 == v2) {
8911c5f74dSStefano Zampini     ierr = MatMultAdd(Na->A,Na->rwork,Na->rwork,Na->lwork);CHKERRQ(ierr);
9011c5f74dSStefano Zampini   } else if (v2 == v3) {
9111c5f74dSStefano Zampini     ierr = VecZeroEntries(Na->lwork);CHKERRQ(ierr);
9211c5f74dSStefano Zampini     ierr = VecScatterBegin(Na->lrestrict,v2,Na->lwork,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
9311c5f74dSStefano Zampini     ierr = VecScatterEnd(Na->lrestrict,v2,Na->lwork,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
9411c5f74dSStefano Zampini     ierr = MatMultAdd(Na->A,Na->rwork,Na->lwork,Na->lwork);CHKERRQ(ierr);
951e7f0bbdSJed Brown   } else {
9611c5f74dSStefano Zampini     if (!Na->lwork2) {
9711c5f74dSStefano Zampini       ierr = VecDuplicate(Na->lwork,&Na->lwork2);CHKERRQ(ierr);
9811c5f74dSStefano Zampini     } else {
9911c5f74dSStefano Zampini       ierr = VecZeroEntries(Na->lwork2);CHKERRQ(ierr);
10011c5f74dSStefano Zampini     }
10111c5f74dSStefano Zampini     ierr = VecScatterBegin(Na->lrestrict,v2,Na->lwork2,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
10211c5f74dSStefano Zampini     ierr = VecScatterEnd(Na->lrestrict,v2,Na->lwork2,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
10311c5f74dSStefano Zampini     ierr = MatMultAdd(Na->A,Na->rwork,Na->lwork2,Na->lwork);CHKERRQ(ierr);
10411c5f74dSStefano Zampini   }
105ee1cef2cSJed Brown   ierr = VecScatterBegin(Na->lrestrict,Na->lwork,v3,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
106ee1cef2cSJed Brown   ierr = VecScatterEnd(Na->lrestrict,Na->lwork,v3,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
107ee1cef2cSJed Brown   PetscFunctionReturn(0);
108ee1cef2cSJed Brown }
109ee1cef2cSJed Brown 
110ee1cef2cSJed Brown static PetscErrorCode MatMultTranspose_SubMatrix(Mat N,Vec x,Vec y)
111ee1cef2cSJed Brown {
11254e05e6cSHong Zhang   Mat_SubVirtual *Na = (Mat_SubVirtual*)N->data;
113ee1cef2cSJed Brown   PetscErrorCode ierr;
114ee1cef2cSJed Brown 
115ee1cef2cSJed Brown   PetscFunctionBegin;
116ee1cef2cSJed Brown   ierr = VecZeroEntries(Na->lwork);CHKERRQ(ierr);
11711c5f74dSStefano Zampini   ierr = VecScatterBegin(Na->lrestrict,x,Na->lwork,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
11811c5f74dSStefano Zampini   ierr = VecScatterEnd(Na->lrestrict,x,Na->lwork,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
119ee1cef2cSJed Brown   ierr = MatMultTranspose(Na->A,Na->lwork,Na->rwork);CHKERRQ(ierr);
1201e7f0bbdSJed Brown   ierr = VecScatterBegin(Na->rprolong,Na->rwork,y,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1211e7f0bbdSJed Brown   ierr = VecScatterEnd(Na->rprolong,Na->rwork,y,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
122ee1cef2cSJed Brown   PetscFunctionReturn(0);
123ee1cef2cSJed Brown }
124ee1cef2cSJed Brown 
125ee1cef2cSJed Brown static PetscErrorCode MatMultTransposeAdd_SubMatrix(Mat N,Vec v1,Vec v2,Vec v3)
126ee1cef2cSJed Brown {
12754e05e6cSHong Zhang   Mat_SubVirtual *Na = (Mat_SubVirtual*)N->data;
128ee1cef2cSJed Brown   PetscErrorCode ierr;
129ee1cef2cSJed Brown 
130ee1cef2cSJed Brown   PetscFunctionBegin;
131ee1cef2cSJed Brown   ierr = VecZeroEntries(Na->lwork);CHKERRQ(ierr);
13211c5f74dSStefano Zampini   ierr = VecScatterBegin(Na->lrestrict,v1,Na->lwork,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
13311c5f74dSStefano Zampini   ierr = VecScatterEnd(Na->lrestrict,v1,Na->lwork,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
13411c5f74dSStefano Zampini   if (v1 == v2) {
13511c5f74dSStefano Zampini     ierr = MatMultTransposeAdd(Na->A,Na->lwork,Na->lwork,Na->rwork);CHKERRQ(ierr);
13611c5f74dSStefano Zampini   } else if (v2 == v3) {
13711c5f74dSStefano Zampini     ierr = VecZeroEntries(Na->rwork);CHKERRQ(ierr);
13811c5f74dSStefano Zampini     ierr = VecScatterBegin(Na->rprolong,v2,Na->rwork,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
13911c5f74dSStefano Zampini     ierr = VecScatterEnd(Na->rprolong,v2,Na->rwork,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
14011c5f74dSStefano Zampini     ierr = MatMultTransposeAdd(Na->A,Na->lwork,Na->rwork,Na->rwork);CHKERRQ(ierr);
1411e7f0bbdSJed Brown   } else {
14211c5f74dSStefano Zampini     if (!Na->rwork2) {
14311c5f74dSStefano Zampini       ierr = VecDuplicate(Na->rwork,&Na->rwork2);CHKERRQ(ierr);
14411c5f74dSStefano Zampini     } else {
14511c5f74dSStefano Zampini       ierr = VecZeroEntries(Na->rwork2);CHKERRQ(ierr);
14611c5f74dSStefano Zampini     }
14711c5f74dSStefano Zampini     ierr = VecScatterBegin(Na->rprolong,v2,Na->rwork2,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
14811c5f74dSStefano Zampini     ierr = VecScatterEnd(Na->rprolong,v2,Na->rwork2,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
14911c5f74dSStefano Zampini     ierr = MatMultTransposeAdd(Na->A,Na->lwork,Na->rwork2,Na->rwork);CHKERRQ(ierr);
15011c5f74dSStefano Zampini   }
1511e7f0bbdSJed Brown   ierr = VecScatterBegin(Na->rprolong,Na->rwork,v3,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1521e7f0bbdSJed Brown   ierr = VecScatterEnd(Na->rprolong,Na->rwork,v3,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
153ee1cef2cSJed Brown   PetscFunctionReturn(0);
154ee1cef2cSJed Brown }
155ee1cef2cSJed Brown 
156ee1cef2cSJed Brown static PetscErrorCode MatDestroy_SubMatrix(Mat N)
157ee1cef2cSJed Brown {
15854e05e6cSHong Zhang   Mat_SubVirtual *Na = (Mat_SubVirtual*)N->data;
159ee1cef2cSJed Brown   PetscErrorCode ierr;
160ee1cef2cSJed Brown 
161ee1cef2cSJed Brown   PetscFunctionBegin;
1626bf464f9SBarry Smith   ierr = ISDestroy(&Na->isrow);CHKERRQ(ierr);
1636bf464f9SBarry Smith   ierr = ISDestroy(&Na->iscol);CHKERRQ(ierr);
1646bf464f9SBarry Smith   ierr = VecDestroy(&Na->lwork);CHKERRQ(ierr);
1656bf464f9SBarry Smith   ierr = VecDestroy(&Na->rwork);CHKERRQ(ierr);
16611c5f74dSStefano Zampini   ierr = VecDestroy(&Na->lwork2);CHKERRQ(ierr);
16711c5f74dSStefano Zampini   ierr = VecDestroy(&Na->rwork2);CHKERRQ(ierr);
1686bf464f9SBarry Smith   ierr = VecScatterDestroy(&Na->lrestrict);CHKERRQ(ierr);
1696bf464f9SBarry Smith   ierr = VecScatterDestroy(&Na->rprolong);CHKERRQ(ierr);
1706bf464f9SBarry Smith   ierr = MatDestroy(&Na->A);CHKERRQ(ierr);
1716bf464f9SBarry Smith   ierr = PetscFree(N->data);CHKERRQ(ierr);
172ee1cef2cSJed Brown   PetscFunctionReturn(0);
173ee1cef2cSJed Brown }
174ee1cef2cSJed Brown 
175ee1cef2cSJed Brown /*@
17654e05e6cSHong Zhang    MatCreateSubMatrixVirtual - Creates a virtual matrix that acts as a submatrix
177ee1cef2cSJed Brown 
178ee1cef2cSJed Brown    Collective on Mat
179ee1cef2cSJed Brown 
180ee1cef2cSJed Brown    Input Parameters:
181ee1cef2cSJed Brown +  A - matrix that we will extract a submatrix of
182ee1cef2cSJed Brown .  isrow - rows to be present in the submatrix
183ee1cef2cSJed Brown -  iscol - columns to be present in the submatrix
184ee1cef2cSJed Brown 
185ee1cef2cSJed Brown    Output Parameters:
186ee1cef2cSJed Brown .  newmat - new matrix
187ee1cef2cSJed Brown 
188ee1cef2cSJed Brown    Level: developer
189ee1cef2cSJed Brown 
190ee1cef2cSJed Brown    Notes:
1917dae84e0SHong Zhang    Most will use MatCreateSubMatrix which provides a more efficient representation if it is available.
192ee1cef2cSJed Brown 
19354e05e6cSHong Zhang .seealso: MatCreateSubMatrix(), MatSubMatrixVirtualUpdate()
194ee1cef2cSJed Brown @*/
19554e05e6cSHong Zhang PetscErrorCode MatCreateSubMatrixVirtual(Mat A,IS isrow,IS iscol,Mat *newmat)
196ee1cef2cSJed Brown {
197ee1cef2cSJed Brown   Vec            left,right;
198ee1cef2cSJed Brown   PetscInt       m,n;
199ee1cef2cSJed Brown   Mat            N;
20054e05e6cSHong Zhang   Mat_SubVirtual *Na;
201ee1cef2cSJed Brown   PetscErrorCode ierr;
202ee1cef2cSJed Brown 
203ee1cef2cSJed Brown   PetscFunctionBegin;
2040700a824SBarry Smith   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
2050700a824SBarry Smith   PetscValidHeaderSpecific(isrow,IS_CLASSID,2);
2060700a824SBarry Smith   PetscValidHeaderSpecific(iscol,IS_CLASSID,3);
207ee1cef2cSJed Brown   PetscValidPointer(newmat,4);
208f4259b30SLisandro Dalcin   *newmat = NULL;
209ee1cef2cSJed Brown 
210ce94432eSBarry Smith   ierr = MatCreate(PetscObjectComm((PetscObject)A),&N);CHKERRQ(ierr);
211ee1cef2cSJed Brown   ierr = ISGetLocalSize(isrow,&m);CHKERRQ(ierr);
212ee1cef2cSJed Brown   ierr = ISGetLocalSize(iscol,&n);CHKERRQ(ierr);
213ee1cef2cSJed Brown   ierr = MatSetSizes(N,m,n,PETSC_DETERMINE,PETSC_DETERMINE);CHKERRQ(ierr);
214ee1cef2cSJed Brown   ierr = PetscObjectChangeTypeName((PetscObject)N,MATSUBMATRIX);CHKERRQ(ierr);
215ee1cef2cSJed Brown 
216b00a9115SJed Brown   ierr      = PetscNewLog(N,&Na);CHKERRQ(ierr);
217ee1cef2cSJed Brown   N->data   = (void*)Na;
21811c5f74dSStefano Zampini 
219ee1cef2cSJed Brown   ierr      = PetscObjectReference((PetscObject)isrow);CHKERRQ(ierr);
220ee1cef2cSJed Brown   ierr      = PetscObjectReference((PetscObject)iscol);CHKERRQ(ierr);
221ee1cef2cSJed Brown   Na->isrow = isrow;
222ee1cef2cSJed Brown   Na->iscol = iscol;
22311c5f74dSStefano Zampini 
22411c5f74dSStefano Zampini   ierr = PetscFree(N->defaultvectype);CHKERRQ(ierr);
22511c5f74dSStefano Zampini   ierr = PetscStrallocpy(A->defaultvectype,&N->defaultvectype);CHKERRQ(ierr);
22611c5f74dSStefano Zampini   /* Do not use MatConvert directly since MatShell has a duplicate operation which does not increase
22711c5f74dSStefano Zampini      the reference count of the context. This is a problem if A is already of type MATSHELL */
22811c5f74dSStefano Zampini   ierr = MatConvertFrom_Shell(A,MATSHELL,MAT_INITIAL_MATRIX,&Na->A);CHKERRQ(ierr);
229ee1cef2cSJed Brown 
230ee1cef2cSJed Brown   N->ops->destroy          = MatDestroy_SubMatrix;
231ee1cef2cSJed Brown   N->ops->mult             = MatMult_SubMatrix;
232ee1cef2cSJed Brown   N->ops->multadd          = MatMultAdd_SubMatrix;
233ee1cef2cSJed Brown   N->ops->multtranspose    = MatMultTranspose_SubMatrix;
234ee1cef2cSJed Brown   N->ops->multtransposeadd = MatMultTransposeAdd_SubMatrix;
235ee1cef2cSJed Brown   N->ops->scale            = MatScale_SubMatrix;
236ee1cef2cSJed Brown   N->ops->diagonalscale    = MatDiagonalScale_SubMatrix;
237bddd1ffdSAlp Dener   N->ops->shift            = MatShift_SubMatrix;
23811c5f74dSStefano Zampini   N->ops->convert          = MatConvert_Shell;
23911c5f74dSStefano Zampini   N->ops->getdiagonal      = MatGetDiagonal_SubMatrix;
240ee1cef2cSJed Brown 
24133d57670SJed Brown   ierr = MatSetBlockSizesFromMats(N,A,A);CHKERRQ(ierr);
24226283091SBarry Smith   ierr = PetscLayoutSetUp(N->rmap);CHKERRQ(ierr);
24326283091SBarry Smith   ierr = PetscLayoutSetUp(N->cmap);CHKERRQ(ierr);
244ee1cef2cSJed Brown 
2452a7a6963SBarry Smith   ierr = MatCreateVecs(A,&Na->rwork,&Na->lwork);CHKERRQ(ierr);
24611c5f74dSStefano Zampini   ierr = MatCreateVecs(N,&right,&left);CHKERRQ(ierr);
2479448b7f1SJunchao Zhang   ierr = VecScatterCreate(Na->lwork,isrow,left,NULL,&Na->lrestrict);CHKERRQ(ierr);
2489448b7f1SJunchao Zhang   ierr = VecScatterCreate(right,NULL,Na->rwork,iscol,&Na->rprolong);CHKERRQ(ierr);
2496bf464f9SBarry Smith   ierr = VecDestroy(&left);CHKERRQ(ierr);
2506bf464f9SBarry Smith   ierr = VecDestroy(&right);CHKERRQ(ierr);
251be7c243fSJed Brown   ierr = MatSetUp(N);CHKERRQ(ierr);
25226fbe8dcSKarl Rupp 
25311c5f74dSStefano Zampini   N->assembled = PETSC_TRUE;
254ee1cef2cSJed Brown   *newmat      = N;
255ee1cef2cSJed Brown   PetscFunctionReturn(0);
256ee1cef2cSJed Brown }
257ee1cef2cSJed Brown 
258ee1cef2cSJed Brown /*@
25954e05e6cSHong Zhang    MatSubMatrixVirtualUpdate - Updates a submatrix
260ee1cef2cSJed Brown 
261ee1cef2cSJed Brown    Collective on Mat
262ee1cef2cSJed Brown 
263ee1cef2cSJed Brown    Input Parameters:
264ee1cef2cSJed Brown +  N - submatrix to update
265ee1cef2cSJed Brown .  A - full matrix in the submatrix
266ee1cef2cSJed Brown .  isrow - rows in the update (same as the first time the submatrix was created)
267ee1cef2cSJed Brown -  iscol - columns in the update (same as the first time the submatrix was created)
268ee1cef2cSJed Brown 
269ee1cef2cSJed Brown    Level: developer
270ee1cef2cSJed Brown 
271ee1cef2cSJed Brown    Notes:
2727dae84e0SHong Zhang    Most will use MatCreateSubMatrix which provides a more efficient representation if it is available.
273ee1cef2cSJed Brown 
27454e05e6cSHong Zhang .seealso: MatCreateSubMatrixVirtual()
275ee1cef2cSJed Brown @*/
27654e05e6cSHong Zhang PetscErrorCode  MatSubMatrixVirtualUpdate(Mat N,Mat A,IS isrow,IS iscol)
277ee1cef2cSJed Brown {
278ee1cef2cSJed Brown   PetscErrorCode ierr;
279ace3abfcSBarry Smith   PetscBool      flg;
28054e05e6cSHong Zhang   Mat_SubVirtual *Na;
281ee1cef2cSJed Brown 
282ee1cef2cSJed Brown   PetscFunctionBegin;
2830700a824SBarry Smith   PetscValidHeaderSpecific(N,MAT_CLASSID,1);
2840700a824SBarry Smith   PetscValidHeaderSpecific(A,MAT_CLASSID,2);
2850700a824SBarry Smith   PetscValidHeaderSpecific(isrow,IS_CLASSID,3);
2860700a824SBarry Smith   PetscValidHeaderSpecific(iscol,IS_CLASSID,4);
287251f4c67SDmitry Karpeev   ierr = PetscObjectTypeCompare((PetscObject)N,MATSUBMATRIX,&flg);CHKERRQ(ierr);
288*2c71b3e2SJacob Faibussowitsch   PetscCheckFalse(!flg,PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_WRONG,"Matrix has wrong type");
289ee1cef2cSJed Brown 
29054e05e6cSHong Zhang   Na   = (Mat_SubVirtual*)N->data;
291ee1cef2cSJed Brown   ierr = ISEqual(isrow,Na->isrow,&flg);CHKERRQ(ierr);
292*2c71b3e2SJacob Faibussowitsch   PetscCheckFalse(!flg,PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Cannot update submatrix with different row indices");
293ee1cef2cSJed Brown   ierr = ISEqual(iscol,Na->iscol,&flg);CHKERRQ(ierr);
294*2c71b3e2SJacob Faibussowitsch   PetscCheckFalse(!flg,PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Cannot update submatrix with different column indices");
295ee1cef2cSJed Brown 
29611c5f74dSStefano Zampini   ierr = PetscFree(N->defaultvectype);CHKERRQ(ierr);
29711c5f74dSStefano Zampini   ierr = PetscStrallocpy(A->defaultvectype,&N->defaultvectype);CHKERRQ(ierr);
2986bf464f9SBarry Smith   ierr = MatDestroy(&Na->A);CHKERRQ(ierr);
29911c5f74dSStefano Zampini   /* Do not use MatConvert directly since MatShell has a duplicate operation which does not increase
30011c5f74dSStefano Zampini      the reference count of the context. This is a problem if A is already of type MATSHELL */
30111c5f74dSStefano Zampini   ierr = MatConvertFrom_Shell(A,MATSHELL,MAT_INITIAL_MATRIX,&Na->A);CHKERRQ(ierr);
302ee1cef2cSJed Brown   PetscFunctionReturn(0);
303ee1cef2cSJed Brown }
304