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 12d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatScale_SubMatrix(Mat N, PetscScalar a) 13d71ae5a4SJacob Faibussowitsch { 14bddd1ffdSAlp Dener Mat_SubVirtual *Na = (Mat_SubVirtual *)N->data; 15bddd1ffdSAlp Dener 16bddd1ffdSAlp Dener PetscFunctionBegin; 179566063dSJacob Faibussowitsch PetscCall(MatScale(Na->A, a)); 18bddd1ffdSAlp Dener PetscFunctionReturn(0); 19bddd1ffdSAlp Dener } 20bddd1ffdSAlp Dener 21d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatShift_SubMatrix(Mat N, PetscScalar a) 22d71ae5a4SJacob Faibussowitsch { 23bddd1ffdSAlp Dener Mat_SubVirtual *Na = (Mat_SubVirtual *)N->data; 24bddd1ffdSAlp Dener 25bddd1ffdSAlp Dener PetscFunctionBegin; 269566063dSJacob Faibussowitsch PetscCall(MatShift(Na->A, a)); 27ee1cef2cSJed Brown PetscFunctionReturn(0); 28ee1cef2cSJed Brown } 29ee1cef2cSJed Brown 30d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatDiagonalScale_SubMatrix(Mat N, Vec left, Vec right) 31d71ae5a4SJacob Faibussowitsch { 3254e05e6cSHong Zhang Mat_SubVirtual *Na = (Mat_SubVirtual *)N->data; 33ee1cef2cSJed Brown 34ee1cef2cSJed Brown PetscFunctionBegin; 35ee1cef2cSJed Brown if (right) { 369566063dSJacob Faibussowitsch PetscCall(VecZeroEntries(Na->rwork)); 379566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(Na->rprolong, right, Na->rwork, INSERT_VALUES, SCATTER_FORWARD)); 389566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(Na->rprolong, right, Na->rwork, INSERT_VALUES, SCATTER_FORWARD)); 39ee1cef2cSJed Brown } 4011c5f74dSStefano Zampini if (left) { 419566063dSJacob Faibussowitsch PetscCall(VecZeroEntries(Na->lwork)); 429566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(Na->lrestrict, left, Na->lwork, INSERT_VALUES, SCATTER_REVERSE)); 439566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(Na->lrestrict, left, Na->lwork, INSERT_VALUES, SCATTER_REVERSE)); 44ee1cef2cSJed Brown } 459566063dSJacob Faibussowitsch PetscCall(MatDiagonalScale(Na->A, left ? Na->lwork : NULL, right ? Na->rwork : NULL)); 4611c5f74dSStefano Zampini PetscFunctionReturn(0); 4711c5f74dSStefano Zampini } 4811c5f74dSStefano Zampini 49d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatGetDiagonal_SubMatrix(Mat N, Vec d) 50d71ae5a4SJacob Faibussowitsch { 5111c5f74dSStefano Zampini Mat_SubVirtual *Na = (Mat_SubVirtual *)N->data; 5211c5f74dSStefano Zampini 5311c5f74dSStefano Zampini PetscFunctionBegin; 549566063dSJacob Faibussowitsch PetscCall(MatGetDiagonal(Na->A, Na->rwork)); 559566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(Na->rprolong, Na->rwork, d, INSERT_VALUES, SCATTER_REVERSE)); 569566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(Na->rprolong, Na->rwork, d, INSERT_VALUES, SCATTER_REVERSE)); 57ee1cef2cSJed Brown PetscFunctionReturn(0); 58ee1cef2cSJed Brown } 59ee1cef2cSJed Brown 60d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatMult_SubMatrix(Mat N, Vec x, Vec y) 61d71ae5a4SJacob Faibussowitsch { 6254e05e6cSHong Zhang Mat_SubVirtual *Na = (Mat_SubVirtual *)N->data; 63ee1cef2cSJed Brown 64ee1cef2cSJed Brown PetscFunctionBegin; 659566063dSJacob Faibussowitsch PetscCall(VecZeroEntries(Na->rwork)); 669566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(Na->rprolong, x, Na->rwork, INSERT_VALUES, SCATTER_FORWARD)); 679566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(Na->rprolong, x, Na->rwork, INSERT_VALUES, SCATTER_FORWARD)); 689566063dSJacob Faibussowitsch PetscCall(MatMult(Na->A, Na->rwork, Na->lwork)); 699566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(Na->lrestrict, Na->lwork, y, INSERT_VALUES, SCATTER_FORWARD)); 709566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(Na->lrestrict, Na->lwork, y, INSERT_VALUES, SCATTER_FORWARD)); 71ee1cef2cSJed Brown PetscFunctionReturn(0); 72ee1cef2cSJed Brown } 73ee1cef2cSJed Brown 74d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatMultAdd_SubMatrix(Mat N, Vec v1, Vec v2, Vec v3) 75d71ae5a4SJacob Faibussowitsch { 7654e05e6cSHong Zhang Mat_SubVirtual *Na = (Mat_SubVirtual *)N->data; 77ee1cef2cSJed Brown 78ee1cef2cSJed Brown PetscFunctionBegin; 799566063dSJacob Faibussowitsch PetscCall(VecZeroEntries(Na->rwork)); 809566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(Na->rprolong, v1, Na->rwork, INSERT_VALUES, SCATTER_FORWARD)); 819566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(Na->rprolong, v1, Na->rwork, INSERT_VALUES, SCATTER_FORWARD)); 8211c5f74dSStefano Zampini if (v1 == v2) { 839566063dSJacob Faibussowitsch PetscCall(MatMultAdd(Na->A, Na->rwork, Na->rwork, Na->lwork)); 8411c5f74dSStefano Zampini } else if (v2 == v3) { 859566063dSJacob Faibussowitsch PetscCall(VecZeroEntries(Na->lwork)); 869566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(Na->lrestrict, v2, Na->lwork, INSERT_VALUES, SCATTER_REVERSE)); 879566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(Na->lrestrict, v2, Na->lwork, INSERT_VALUES, SCATTER_REVERSE)); 889566063dSJacob Faibussowitsch PetscCall(MatMultAdd(Na->A, Na->rwork, Na->lwork, Na->lwork)); 891e7f0bbdSJed Brown } else { 9011c5f74dSStefano Zampini if (!Na->lwork2) { 919566063dSJacob Faibussowitsch PetscCall(VecDuplicate(Na->lwork, &Na->lwork2)); 9211c5f74dSStefano Zampini } else { 939566063dSJacob Faibussowitsch PetscCall(VecZeroEntries(Na->lwork2)); 9411c5f74dSStefano Zampini } 959566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(Na->lrestrict, v2, Na->lwork2, INSERT_VALUES, SCATTER_REVERSE)); 969566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(Na->lrestrict, v2, Na->lwork2, INSERT_VALUES, SCATTER_REVERSE)); 979566063dSJacob Faibussowitsch PetscCall(MatMultAdd(Na->A, Na->rwork, Na->lwork2, Na->lwork)); 9811c5f74dSStefano Zampini } 999566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(Na->lrestrict, Na->lwork, v3, INSERT_VALUES, SCATTER_FORWARD)); 1009566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(Na->lrestrict, Na->lwork, v3, INSERT_VALUES, SCATTER_FORWARD)); 101ee1cef2cSJed Brown PetscFunctionReturn(0); 102ee1cef2cSJed Brown } 103ee1cef2cSJed Brown 104d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatMultTranspose_SubMatrix(Mat N, Vec x, Vec y) 105d71ae5a4SJacob Faibussowitsch { 10654e05e6cSHong Zhang Mat_SubVirtual *Na = (Mat_SubVirtual *)N->data; 107ee1cef2cSJed Brown 108ee1cef2cSJed Brown PetscFunctionBegin; 1099566063dSJacob Faibussowitsch PetscCall(VecZeroEntries(Na->lwork)); 1109566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(Na->lrestrict, x, Na->lwork, INSERT_VALUES, SCATTER_REVERSE)); 1119566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(Na->lrestrict, x, Na->lwork, INSERT_VALUES, SCATTER_REVERSE)); 1129566063dSJacob Faibussowitsch PetscCall(MatMultTranspose(Na->A, Na->lwork, Na->rwork)); 1139566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(Na->rprolong, Na->rwork, y, INSERT_VALUES, SCATTER_REVERSE)); 1149566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(Na->rprolong, Na->rwork, y, INSERT_VALUES, SCATTER_REVERSE)); 115ee1cef2cSJed Brown PetscFunctionReturn(0); 116ee1cef2cSJed Brown } 117ee1cef2cSJed Brown 118d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatMultTransposeAdd_SubMatrix(Mat N, Vec v1, Vec v2, Vec v3) 119d71ae5a4SJacob Faibussowitsch { 12054e05e6cSHong Zhang Mat_SubVirtual *Na = (Mat_SubVirtual *)N->data; 121ee1cef2cSJed Brown 122ee1cef2cSJed Brown PetscFunctionBegin; 1239566063dSJacob Faibussowitsch PetscCall(VecZeroEntries(Na->lwork)); 1249566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(Na->lrestrict, v1, Na->lwork, INSERT_VALUES, SCATTER_REVERSE)); 1259566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(Na->lrestrict, v1, Na->lwork, INSERT_VALUES, SCATTER_REVERSE)); 12611c5f74dSStefano Zampini if (v1 == v2) { 1279566063dSJacob Faibussowitsch PetscCall(MatMultTransposeAdd(Na->A, Na->lwork, Na->lwork, Na->rwork)); 12811c5f74dSStefano Zampini } else if (v2 == v3) { 1299566063dSJacob Faibussowitsch PetscCall(VecZeroEntries(Na->rwork)); 1309566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(Na->rprolong, v2, Na->rwork, INSERT_VALUES, SCATTER_FORWARD)); 1319566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(Na->rprolong, v2, Na->rwork, INSERT_VALUES, SCATTER_FORWARD)); 1329566063dSJacob Faibussowitsch PetscCall(MatMultTransposeAdd(Na->A, Na->lwork, Na->rwork, Na->rwork)); 1331e7f0bbdSJed Brown } else { 13411c5f74dSStefano Zampini if (!Na->rwork2) { 1359566063dSJacob Faibussowitsch PetscCall(VecDuplicate(Na->rwork, &Na->rwork2)); 13611c5f74dSStefano Zampini } else { 1379566063dSJacob Faibussowitsch PetscCall(VecZeroEntries(Na->rwork2)); 13811c5f74dSStefano Zampini } 1399566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(Na->rprolong, v2, Na->rwork2, INSERT_VALUES, SCATTER_FORWARD)); 1409566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(Na->rprolong, v2, Na->rwork2, INSERT_VALUES, SCATTER_FORWARD)); 1419566063dSJacob Faibussowitsch PetscCall(MatMultTransposeAdd(Na->A, Na->lwork, Na->rwork2, Na->rwork)); 14211c5f74dSStefano Zampini } 1439566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(Na->rprolong, Na->rwork, v3, INSERT_VALUES, SCATTER_REVERSE)); 1449566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(Na->rprolong, Na->rwork, v3, INSERT_VALUES, SCATTER_REVERSE)); 145ee1cef2cSJed Brown PetscFunctionReturn(0); 146ee1cef2cSJed Brown } 147ee1cef2cSJed Brown 148d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatDestroy_SubMatrix(Mat N) 149d71ae5a4SJacob Faibussowitsch { 15054e05e6cSHong Zhang Mat_SubVirtual *Na = (Mat_SubVirtual *)N->data; 151ee1cef2cSJed Brown 152ee1cef2cSJed Brown PetscFunctionBegin; 1539566063dSJacob Faibussowitsch PetscCall(ISDestroy(&Na->isrow)); 1549566063dSJacob Faibussowitsch PetscCall(ISDestroy(&Na->iscol)); 1559566063dSJacob Faibussowitsch PetscCall(VecDestroy(&Na->lwork)); 1569566063dSJacob Faibussowitsch PetscCall(VecDestroy(&Na->rwork)); 1579566063dSJacob Faibussowitsch PetscCall(VecDestroy(&Na->lwork2)); 1589566063dSJacob Faibussowitsch PetscCall(VecDestroy(&Na->rwork2)); 1599566063dSJacob Faibussowitsch PetscCall(VecScatterDestroy(&Na->lrestrict)); 1609566063dSJacob Faibussowitsch PetscCall(VecScatterDestroy(&Na->rprolong)); 1619566063dSJacob Faibussowitsch PetscCall(MatDestroy(&Na->A)); 1629566063dSJacob Faibussowitsch PetscCall(PetscFree(N->data)); 163ee1cef2cSJed Brown PetscFunctionReturn(0); 164ee1cef2cSJed Brown } 165ee1cef2cSJed Brown 166ee1cef2cSJed Brown /*@ 16711a5261eSBarry Smith MatCreateSubMatrixVirtual - Creates a virtual matrix `MATSUBMATRIX` that acts as a submatrix 168ee1cef2cSJed Brown 169*c3339decSBarry Smith Collective 170ee1cef2cSJed Brown 171ee1cef2cSJed Brown Input Parameters: 172ee1cef2cSJed Brown + A - matrix that we will extract a submatrix of 173ee1cef2cSJed Brown . isrow - rows to be present in the submatrix 174ee1cef2cSJed Brown - iscol - columns to be present in the submatrix 175ee1cef2cSJed Brown 176ee1cef2cSJed Brown Output Parameters: 177ee1cef2cSJed Brown . newmat - new matrix 178ee1cef2cSJed Brown 179ee1cef2cSJed Brown Level: developer 180ee1cef2cSJed Brown 18111a5261eSBarry Smith Note: 18211a5261eSBarry Smith Most will use `MatCreateSubMatrix()` which provides a more efficient representation if it is available. 183ee1cef2cSJed Brown 18411a5261eSBarry Smith Developer Note: 18511a5261eSBarry Smith The `MatType` is `MATSUBMATRIX` but the routines associated have `SubMatrixVirtual` in them, the `MatType` should likely be changed 18611a5261eSBarry Smith 18711a5261eSBarry Smith .seealso: `MATSUBMATRIX`, `MATLOCALREF`, `MatCreateLocalRef()`, `MatCreateSubMatrix()`, `MatSubMatrixVirtualUpdate()` 188ee1cef2cSJed Brown @*/ 189d71ae5a4SJacob Faibussowitsch PetscErrorCode MatCreateSubMatrixVirtual(Mat A, IS isrow, IS iscol, Mat *newmat) 190d71ae5a4SJacob Faibussowitsch { 191ee1cef2cSJed Brown Vec left, right; 192ee1cef2cSJed Brown PetscInt m, n; 193ee1cef2cSJed Brown Mat N; 19454e05e6cSHong Zhang Mat_SubVirtual *Na; 195ee1cef2cSJed Brown 196ee1cef2cSJed Brown PetscFunctionBegin; 1970700a824SBarry Smith PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 1980700a824SBarry Smith PetscValidHeaderSpecific(isrow, IS_CLASSID, 2); 1990700a824SBarry Smith PetscValidHeaderSpecific(iscol, IS_CLASSID, 3); 200ee1cef2cSJed Brown PetscValidPointer(newmat, 4); 201f4259b30SLisandro Dalcin *newmat = NULL; 202ee1cef2cSJed Brown 2039566063dSJacob Faibussowitsch PetscCall(MatCreate(PetscObjectComm((PetscObject)A), &N)); 2049566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(isrow, &m)); 2059566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(iscol, &n)); 2069566063dSJacob Faibussowitsch PetscCall(MatSetSizes(N, m, n, PETSC_DETERMINE, PETSC_DETERMINE)); 2079566063dSJacob Faibussowitsch PetscCall(PetscObjectChangeTypeName((PetscObject)N, MATSUBMATRIX)); 208ee1cef2cSJed Brown 2094dfa11a4SJacob Faibussowitsch PetscCall(PetscNew(&Na)); 210ee1cef2cSJed Brown N->data = (void *)Na; 21111c5f74dSStefano Zampini 2129566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)isrow)); 2139566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)iscol)); 214ee1cef2cSJed Brown Na->isrow = isrow; 215ee1cef2cSJed Brown Na->iscol = iscol; 21611c5f74dSStefano Zampini 2179566063dSJacob Faibussowitsch PetscCall(PetscFree(N->defaultvectype)); 2189566063dSJacob Faibussowitsch PetscCall(PetscStrallocpy(A->defaultvectype, &N->defaultvectype)); 21911c5f74dSStefano Zampini /* Do not use MatConvert directly since MatShell has a duplicate operation which does not increase 22011c5f74dSStefano Zampini the reference count of the context. This is a problem if A is already of type MATSHELL */ 2219566063dSJacob Faibussowitsch PetscCall(MatConvertFrom_Shell(A, MATSHELL, MAT_INITIAL_MATRIX, &Na->A)); 222ee1cef2cSJed Brown 223ee1cef2cSJed Brown N->ops->destroy = MatDestroy_SubMatrix; 224ee1cef2cSJed Brown N->ops->mult = MatMult_SubMatrix; 225ee1cef2cSJed Brown N->ops->multadd = MatMultAdd_SubMatrix; 226ee1cef2cSJed Brown N->ops->multtranspose = MatMultTranspose_SubMatrix; 227ee1cef2cSJed Brown N->ops->multtransposeadd = MatMultTransposeAdd_SubMatrix; 228ee1cef2cSJed Brown N->ops->scale = MatScale_SubMatrix; 229ee1cef2cSJed Brown N->ops->diagonalscale = MatDiagonalScale_SubMatrix; 230bddd1ffdSAlp Dener N->ops->shift = MatShift_SubMatrix; 23111c5f74dSStefano Zampini N->ops->convert = MatConvert_Shell; 23211c5f74dSStefano Zampini N->ops->getdiagonal = MatGetDiagonal_SubMatrix; 233ee1cef2cSJed Brown 2349566063dSJacob Faibussowitsch PetscCall(MatSetBlockSizesFromMats(N, A, A)); 2359566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetUp(N->rmap)); 2369566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetUp(N->cmap)); 237ee1cef2cSJed Brown 2389566063dSJacob Faibussowitsch PetscCall(MatCreateVecs(A, &Na->rwork, &Na->lwork)); 2399566063dSJacob Faibussowitsch PetscCall(MatCreateVecs(N, &right, &left)); 2409566063dSJacob Faibussowitsch PetscCall(VecScatterCreate(Na->lwork, isrow, left, NULL, &Na->lrestrict)); 2419566063dSJacob Faibussowitsch PetscCall(VecScatterCreate(right, NULL, Na->rwork, iscol, &Na->rprolong)); 2429566063dSJacob Faibussowitsch PetscCall(VecDestroy(&left)); 2439566063dSJacob Faibussowitsch PetscCall(VecDestroy(&right)); 2449566063dSJacob Faibussowitsch PetscCall(MatSetUp(N)); 24526fbe8dcSKarl Rupp 24611c5f74dSStefano Zampini N->assembled = PETSC_TRUE; 247ee1cef2cSJed Brown *newmat = N; 248ee1cef2cSJed Brown PetscFunctionReturn(0); 249ee1cef2cSJed Brown } 250ee1cef2cSJed Brown 25111a5261eSBarry Smith /*MC 25211a5261eSBarry Smith MATSUBMATRIX - "submatrix" - A matrix type that represents a virtual submatrix of a matrix 253ee1cef2cSJed Brown 25411a5261eSBarry Smith Level: advanced 25511a5261eSBarry Smith 25611a5261eSBarry Smith Developer Note: 25711a5261eSBarry Smith This should be named `MATSUBMATRIXVIRTUAL` 25811a5261eSBarry Smith 25911a5261eSBarry Smith .seealso: `Mat`, `MatCreateSubMatrixVirtual()`, `MatCreateSubMatrixVirtual()`, `MatCreateSubMatrix()` 26011a5261eSBarry Smith M*/ 26111a5261eSBarry Smith 26211a5261eSBarry Smith /*@ 26311a5261eSBarry Smith MatSubMatrixVirtualUpdate - Updates a `MATSUBMATRIX` virtual submatrix 26411a5261eSBarry Smith 265*c3339decSBarry Smith Collective 266ee1cef2cSJed Brown 267ee1cef2cSJed Brown Input Parameters: 268ee1cef2cSJed Brown + N - submatrix to update 269ee1cef2cSJed Brown . A - full matrix in the submatrix 270ee1cef2cSJed Brown . isrow - rows in the update (same as the first time the submatrix was created) 271ee1cef2cSJed Brown - iscol - columns in the update (same as the first time the submatrix was created) 272ee1cef2cSJed Brown 273ee1cef2cSJed Brown Level: developer 274ee1cef2cSJed Brown 27511a5261eSBarry Smith Note: 27611a5261eSBarry Smith Most will use `MatCreateSubMatrix()` which provides a more efficient representation if it is available. 277ee1cef2cSJed Brown 27811a5261eSBarry Smith .seealso: MATSUBMATRIX`, `MatCreateSubMatrixVirtual()` 279ee1cef2cSJed Brown @*/ 280d71ae5a4SJacob Faibussowitsch PetscErrorCode MatSubMatrixVirtualUpdate(Mat N, Mat A, IS isrow, IS iscol) 281d71ae5a4SJacob Faibussowitsch { 282ace3abfcSBarry Smith PetscBool flg; 28354e05e6cSHong Zhang Mat_SubVirtual *Na; 284ee1cef2cSJed Brown 285ee1cef2cSJed Brown PetscFunctionBegin; 2860700a824SBarry Smith PetscValidHeaderSpecific(N, MAT_CLASSID, 1); 2870700a824SBarry Smith PetscValidHeaderSpecific(A, MAT_CLASSID, 2); 2880700a824SBarry Smith PetscValidHeaderSpecific(isrow, IS_CLASSID, 3); 2890700a824SBarry Smith PetscValidHeaderSpecific(iscol, IS_CLASSID, 4); 2909566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)N, MATSUBMATRIX, &flg)); 29128b400f6SJacob Faibussowitsch PetscCheck(flg, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONG, "Matrix has wrong type"); 292ee1cef2cSJed Brown 29354e05e6cSHong Zhang Na = (Mat_SubVirtual *)N->data; 2949566063dSJacob Faibussowitsch PetscCall(ISEqual(isrow, Na->isrow, &flg)); 29528b400f6SJacob Faibussowitsch PetscCheck(flg, PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, "Cannot update submatrix with different row indices"); 2969566063dSJacob Faibussowitsch PetscCall(ISEqual(iscol, Na->iscol, &flg)); 29728b400f6SJacob Faibussowitsch PetscCheck(flg, PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, "Cannot update submatrix with different column indices"); 298ee1cef2cSJed Brown 2999566063dSJacob Faibussowitsch PetscCall(PetscFree(N->defaultvectype)); 3009566063dSJacob Faibussowitsch PetscCall(PetscStrallocpy(A->defaultvectype, &N->defaultvectype)); 3019566063dSJacob Faibussowitsch PetscCall(MatDestroy(&Na->A)); 30211c5f74dSStefano Zampini /* Do not use MatConvert directly since MatShell has a duplicate operation which does not increase 30311c5f74dSStefano Zampini the reference count of the context. This is a problem if A is already of type MATSHELL */ 3049566063dSJacob Faibussowitsch PetscCall(MatConvertFrom_Shell(A, MATSHELL, MAT_INITIAL_MATRIX, &Na->A)); 305ee1cef2cSJed Brown PetscFunctionReturn(0); 306ee1cef2cSJed Brown } 307