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)); 183ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 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)); 273ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 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)); 463ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 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)); 573ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 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)); 713ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 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)); 1013ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 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)); 1153ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 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)); 1453ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 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)); 1633ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 164ee1cef2cSJed Brown } 165ee1cef2cSJed Brown 166ee1cef2cSJed Brown /*@ 16711a5261eSBarry Smith MatCreateSubMatrixVirtual - Creates a virtual matrix `MATSUBMATRIX` that acts as a submatrix 168ee1cef2cSJed Brown 169c3339decSBarry 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 1762fe279fdSBarry Smith Output Parameter: 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 184*1cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATSUBMATRIX`, `MATLOCALREF`, `MatCreateLocalRef()`, `MatCreateSubMatrix()`, `MatSubMatrixVirtualUpdate()` 185ee1cef2cSJed Brown @*/ 186d71ae5a4SJacob Faibussowitsch PetscErrorCode MatCreateSubMatrixVirtual(Mat A, IS isrow, IS iscol, Mat *newmat) 187d71ae5a4SJacob Faibussowitsch { 188ee1cef2cSJed Brown Vec left, right; 189ee1cef2cSJed Brown PetscInt m, n; 190ee1cef2cSJed Brown Mat N; 19154e05e6cSHong Zhang Mat_SubVirtual *Na; 192ee1cef2cSJed Brown 193ee1cef2cSJed Brown PetscFunctionBegin; 1940700a824SBarry Smith PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 1950700a824SBarry Smith PetscValidHeaderSpecific(isrow, IS_CLASSID, 2); 1960700a824SBarry Smith PetscValidHeaderSpecific(iscol, IS_CLASSID, 3); 197ee1cef2cSJed Brown PetscValidPointer(newmat, 4); 198f4259b30SLisandro Dalcin *newmat = NULL; 199ee1cef2cSJed Brown 2009566063dSJacob Faibussowitsch PetscCall(MatCreate(PetscObjectComm((PetscObject)A), &N)); 2019566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(isrow, &m)); 2029566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(iscol, &n)); 2039566063dSJacob Faibussowitsch PetscCall(MatSetSizes(N, m, n, PETSC_DETERMINE, PETSC_DETERMINE)); 2049566063dSJacob Faibussowitsch PetscCall(PetscObjectChangeTypeName((PetscObject)N, MATSUBMATRIX)); 205ee1cef2cSJed Brown 2064dfa11a4SJacob Faibussowitsch PetscCall(PetscNew(&Na)); 207ee1cef2cSJed Brown N->data = (void *)Na; 20811c5f74dSStefano Zampini 2099566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)isrow)); 2109566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)iscol)); 211ee1cef2cSJed Brown Na->isrow = isrow; 212ee1cef2cSJed Brown Na->iscol = iscol; 21311c5f74dSStefano Zampini 2149566063dSJacob Faibussowitsch PetscCall(PetscFree(N->defaultvectype)); 2159566063dSJacob Faibussowitsch PetscCall(PetscStrallocpy(A->defaultvectype, &N->defaultvectype)); 21611c5f74dSStefano Zampini /* Do not use MatConvert directly since MatShell has a duplicate operation which does not increase 21711c5f74dSStefano Zampini the reference count of the context. This is a problem if A is already of type MATSHELL */ 2189566063dSJacob Faibussowitsch PetscCall(MatConvertFrom_Shell(A, MATSHELL, MAT_INITIAL_MATRIX, &Na->A)); 219ee1cef2cSJed Brown 220ee1cef2cSJed Brown N->ops->destroy = MatDestroy_SubMatrix; 221ee1cef2cSJed Brown N->ops->mult = MatMult_SubMatrix; 222ee1cef2cSJed Brown N->ops->multadd = MatMultAdd_SubMatrix; 223ee1cef2cSJed Brown N->ops->multtranspose = MatMultTranspose_SubMatrix; 224ee1cef2cSJed Brown N->ops->multtransposeadd = MatMultTransposeAdd_SubMatrix; 225ee1cef2cSJed Brown N->ops->scale = MatScale_SubMatrix; 226ee1cef2cSJed Brown N->ops->diagonalscale = MatDiagonalScale_SubMatrix; 227bddd1ffdSAlp Dener N->ops->shift = MatShift_SubMatrix; 22811c5f74dSStefano Zampini N->ops->convert = MatConvert_Shell; 22911c5f74dSStefano Zampini N->ops->getdiagonal = MatGetDiagonal_SubMatrix; 230ee1cef2cSJed Brown 2319566063dSJacob Faibussowitsch PetscCall(MatSetBlockSizesFromMats(N, A, A)); 2329566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetUp(N->rmap)); 2339566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetUp(N->cmap)); 234ee1cef2cSJed Brown 2359566063dSJacob Faibussowitsch PetscCall(MatCreateVecs(A, &Na->rwork, &Na->lwork)); 2369566063dSJacob Faibussowitsch PetscCall(MatCreateVecs(N, &right, &left)); 2379566063dSJacob Faibussowitsch PetscCall(VecScatterCreate(Na->lwork, isrow, left, NULL, &Na->lrestrict)); 2389566063dSJacob Faibussowitsch PetscCall(VecScatterCreate(right, NULL, Na->rwork, iscol, &Na->rprolong)); 2399566063dSJacob Faibussowitsch PetscCall(VecDestroy(&left)); 2409566063dSJacob Faibussowitsch PetscCall(VecDestroy(&right)); 2419566063dSJacob Faibussowitsch PetscCall(MatSetUp(N)); 24226fbe8dcSKarl Rupp 24311c5f74dSStefano Zampini N->assembled = PETSC_TRUE; 244ee1cef2cSJed Brown *newmat = N; 2453ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 246ee1cef2cSJed Brown } 247ee1cef2cSJed Brown 24811a5261eSBarry Smith /*MC 24911a5261eSBarry Smith MATSUBMATRIX - "submatrix" - A matrix type that represents a virtual submatrix of a matrix 250ee1cef2cSJed Brown 25111a5261eSBarry Smith Level: advanced 25211a5261eSBarry Smith 25311a5261eSBarry Smith Developer Note: 2542ef1f0ffSBarry Smith The `MatType` is `MATSUBMATRIX` but the routines associated have `SubMatrixVirtual` in them, the `MatType` name should likely be changed to 2552ef1f0ffSBarry Smith `MATSUBMATRIXVIRTUAL` 25611a5261eSBarry Smith 257*1cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MatCreateSubMatrixVirtual()`, `MatCreateSubMatrixVirtual()`, `MatCreateSubMatrix()` 25811a5261eSBarry Smith M*/ 25911a5261eSBarry Smith 26011a5261eSBarry Smith /*@ 26111a5261eSBarry Smith MatSubMatrixVirtualUpdate - Updates a `MATSUBMATRIX` virtual submatrix 26211a5261eSBarry Smith 263c3339decSBarry Smith Collective 264ee1cef2cSJed Brown 265ee1cef2cSJed Brown Input Parameters: 266ee1cef2cSJed Brown + N - submatrix to update 267ee1cef2cSJed Brown . A - full matrix in the submatrix 268ee1cef2cSJed Brown . isrow - rows in the update (same as the first time the submatrix was created) 269ee1cef2cSJed Brown - iscol - columns in the update (same as the first time the submatrix was created) 270ee1cef2cSJed Brown 271ee1cef2cSJed Brown Level: developer 272ee1cef2cSJed Brown 27311a5261eSBarry Smith Note: 27411a5261eSBarry Smith Most will use `MatCreateSubMatrix()` which provides a more efficient representation if it is available. 275ee1cef2cSJed Brown 276*1cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATSUBMATRIX`, `MatCreateSubMatrixVirtual()` 277ee1cef2cSJed Brown @*/ 278d71ae5a4SJacob Faibussowitsch PetscErrorCode MatSubMatrixVirtualUpdate(Mat N, Mat A, IS isrow, IS iscol) 279d71ae5a4SJacob Faibussowitsch { 280ace3abfcSBarry Smith PetscBool flg; 28154e05e6cSHong Zhang Mat_SubVirtual *Na; 282ee1cef2cSJed Brown 283ee1cef2cSJed Brown PetscFunctionBegin; 2840700a824SBarry Smith PetscValidHeaderSpecific(N, MAT_CLASSID, 1); 2850700a824SBarry Smith PetscValidHeaderSpecific(A, MAT_CLASSID, 2); 2860700a824SBarry Smith PetscValidHeaderSpecific(isrow, IS_CLASSID, 3); 2870700a824SBarry Smith PetscValidHeaderSpecific(iscol, IS_CLASSID, 4); 2889566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)N, MATSUBMATRIX, &flg)); 28928b400f6SJacob Faibussowitsch PetscCheck(flg, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONG, "Matrix has wrong type"); 290ee1cef2cSJed Brown 29154e05e6cSHong Zhang Na = (Mat_SubVirtual *)N->data; 2929566063dSJacob Faibussowitsch PetscCall(ISEqual(isrow, Na->isrow, &flg)); 29328b400f6SJacob Faibussowitsch PetscCheck(flg, PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, "Cannot update submatrix with different row indices"); 2949566063dSJacob Faibussowitsch PetscCall(ISEqual(iscol, Na->iscol, &flg)); 29528b400f6SJacob Faibussowitsch PetscCheck(flg, PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, "Cannot update submatrix with different column indices"); 296ee1cef2cSJed Brown 2979566063dSJacob Faibussowitsch PetscCall(PetscFree(N->defaultvectype)); 2989566063dSJacob Faibussowitsch PetscCall(PetscStrallocpy(A->defaultvectype, &N->defaultvectype)); 2999566063dSJacob Faibussowitsch PetscCall(MatDestroy(&Na->A)); 30011c5f74dSStefano Zampini /* Do not use MatConvert directly since MatShell has a duplicate operation which does not increase 30111c5f74dSStefano Zampini the reference count of the context. This is a problem if A is already of type MATSHELL */ 3029566063dSJacob Faibussowitsch PetscCall(MatConvertFrom_Shell(A, MATSHELL, MAT_INITIAL_MATRIX, &Na->A)); 3033ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 304ee1cef2cSJed Brown } 305