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 12*9371c9d4SSatish Balay static PetscErrorCode MatScale_SubMatrix(Mat N, PetscScalar a) { 13bddd1ffdSAlp Dener Mat_SubVirtual *Na = (Mat_SubVirtual *)N->data; 14bddd1ffdSAlp Dener 15bddd1ffdSAlp Dener PetscFunctionBegin; 169566063dSJacob Faibussowitsch PetscCall(MatScale(Na->A, a)); 17bddd1ffdSAlp Dener PetscFunctionReturn(0); 18bddd1ffdSAlp Dener } 19bddd1ffdSAlp Dener 20*9371c9d4SSatish Balay static PetscErrorCode MatShift_SubMatrix(Mat N, PetscScalar a) { 21bddd1ffdSAlp Dener Mat_SubVirtual *Na = (Mat_SubVirtual *)N->data; 22bddd1ffdSAlp Dener 23bddd1ffdSAlp Dener PetscFunctionBegin; 249566063dSJacob Faibussowitsch PetscCall(MatShift(Na->A, a)); 25ee1cef2cSJed Brown PetscFunctionReturn(0); 26ee1cef2cSJed Brown } 27ee1cef2cSJed Brown 28*9371c9d4SSatish Balay static PetscErrorCode MatDiagonalScale_SubMatrix(Mat N, Vec left, Vec right) { 2954e05e6cSHong Zhang Mat_SubVirtual *Na = (Mat_SubVirtual *)N->data; 30ee1cef2cSJed Brown 31ee1cef2cSJed Brown PetscFunctionBegin; 32ee1cef2cSJed Brown if (right) { 339566063dSJacob Faibussowitsch PetscCall(VecZeroEntries(Na->rwork)); 349566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(Na->rprolong, right, Na->rwork, INSERT_VALUES, SCATTER_FORWARD)); 359566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(Na->rprolong, right, Na->rwork, INSERT_VALUES, SCATTER_FORWARD)); 36ee1cef2cSJed Brown } 3711c5f74dSStefano Zampini if (left) { 389566063dSJacob Faibussowitsch PetscCall(VecZeroEntries(Na->lwork)); 399566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(Na->lrestrict, left, Na->lwork, INSERT_VALUES, SCATTER_REVERSE)); 409566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(Na->lrestrict, left, Na->lwork, INSERT_VALUES, SCATTER_REVERSE)); 41ee1cef2cSJed Brown } 429566063dSJacob Faibussowitsch PetscCall(MatDiagonalScale(Na->A, left ? Na->lwork : NULL, right ? Na->rwork : NULL)); 4311c5f74dSStefano Zampini PetscFunctionReturn(0); 4411c5f74dSStefano Zampini } 4511c5f74dSStefano Zampini 46*9371c9d4SSatish Balay static PetscErrorCode MatGetDiagonal_SubMatrix(Mat N, Vec d) { 4711c5f74dSStefano Zampini Mat_SubVirtual *Na = (Mat_SubVirtual *)N->data; 4811c5f74dSStefano Zampini 4911c5f74dSStefano Zampini PetscFunctionBegin; 509566063dSJacob Faibussowitsch PetscCall(MatGetDiagonal(Na->A, Na->rwork)); 519566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(Na->rprolong, Na->rwork, d, INSERT_VALUES, SCATTER_REVERSE)); 529566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(Na->rprolong, Na->rwork, d, INSERT_VALUES, SCATTER_REVERSE)); 53ee1cef2cSJed Brown PetscFunctionReturn(0); 54ee1cef2cSJed Brown } 55ee1cef2cSJed Brown 56*9371c9d4SSatish Balay static PetscErrorCode MatMult_SubMatrix(Mat N, Vec x, Vec y) { 5754e05e6cSHong Zhang Mat_SubVirtual *Na = (Mat_SubVirtual *)N->data; 58ee1cef2cSJed Brown 59ee1cef2cSJed Brown PetscFunctionBegin; 609566063dSJacob Faibussowitsch PetscCall(VecZeroEntries(Na->rwork)); 619566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(Na->rprolong, x, Na->rwork, INSERT_VALUES, SCATTER_FORWARD)); 629566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(Na->rprolong, x, Na->rwork, INSERT_VALUES, SCATTER_FORWARD)); 639566063dSJacob Faibussowitsch PetscCall(MatMult(Na->A, Na->rwork, Na->lwork)); 649566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(Na->lrestrict, Na->lwork, y, INSERT_VALUES, SCATTER_FORWARD)); 659566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(Na->lrestrict, Na->lwork, y, INSERT_VALUES, SCATTER_FORWARD)); 66ee1cef2cSJed Brown PetscFunctionReturn(0); 67ee1cef2cSJed Brown } 68ee1cef2cSJed Brown 69*9371c9d4SSatish Balay static PetscErrorCode MatMultAdd_SubMatrix(Mat N, Vec v1, Vec v2, Vec v3) { 7054e05e6cSHong Zhang Mat_SubVirtual *Na = (Mat_SubVirtual *)N->data; 71ee1cef2cSJed Brown 72ee1cef2cSJed Brown PetscFunctionBegin; 739566063dSJacob Faibussowitsch PetscCall(VecZeroEntries(Na->rwork)); 749566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(Na->rprolong, v1, Na->rwork, INSERT_VALUES, SCATTER_FORWARD)); 759566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(Na->rprolong, v1, Na->rwork, INSERT_VALUES, SCATTER_FORWARD)); 7611c5f74dSStefano Zampini if (v1 == v2) { 779566063dSJacob Faibussowitsch PetscCall(MatMultAdd(Na->A, Na->rwork, Na->rwork, Na->lwork)); 7811c5f74dSStefano Zampini } else if (v2 == v3) { 799566063dSJacob Faibussowitsch PetscCall(VecZeroEntries(Na->lwork)); 809566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(Na->lrestrict, v2, Na->lwork, INSERT_VALUES, SCATTER_REVERSE)); 819566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(Na->lrestrict, v2, Na->lwork, INSERT_VALUES, SCATTER_REVERSE)); 829566063dSJacob Faibussowitsch PetscCall(MatMultAdd(Na->A, Na->rwork, Na->lwork, Na->lwork)); 831e7f0bbdSJed Brown } else { 8411c5f74dSStefano Zampini if (!Na->lwork2) { 859566063dSJacob Faibussowitsch PetscCall(VecDuplicate(Na->lwork, &Na->lwork2)); 8611c5f74dSStefano Zampini } else { 879566063dSJacob Faibussowitsch PetscCall(VecZeroEntries(Na->lwork2)); 8811c5f74dSStefano Zampini } 899566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(Na->lrestrict, v2, Na->lwork2, INSERT_VALUES, SCATTER_REVERSE)); 909566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(Na->lrestrict, v2, Na->lwork2, INSERT_VALUES, SCATTER_REVERSE)); 919566063dSJacob Faibussowitsch PetscCall(MatMultAdd(Na->A, Na->rwork, Na->lwork2, Na->lwork)); 9211c5f74dSStefano Zampini } 939566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(Na->lrestrict, Na->lwork, v3, INSERT_VALUES, SCATTER_FORWARD)); 949566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(Na->lrestrict, Na->lwork, v3, INSERT_VALUES, SCATTER_FORWARD)); 95ee1cef2cSJed Brown PetscFunctionReturn(0); 96ee1cef2cSJed Brown } 97ee1cef2cSJed Brown 98*9371c9d4SSatish Balay static PetscErrorCode MatMultTranspose_SubMatrix(Mat N, Vec x, Vec y) { 9954e05e6cSHong Zhang Mat_SubVirtual *Na = (Mat_SubVirtual *)N->data; 100ee1cef2cSJed Brown 101ee1cef2cSJed Brown PetscFunctionBegin; 1029566063dSJacob Faibussowitsch PetscCall(VecZeroEntries(Na->lwork)); 1039566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(Na->lrestrict, x, Na->lwork, INSERT_VALUES, SCATTER_REVERSE)); 1049566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(Na->lrestrict, x, Na->lwork, INSERT_VALUES, SCATTER_REVERSE)); 1059566063dSJacob Faibussowitsch PetscCall(MatMultTranspose(Na->A, Na->lwork, Na->rwork)); 1069566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(Na->rprolong, Na->rwork, y, INSERT_VALUES, SCATTER_REVERSE)); 1079566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(Na->rprolong, Na->rwork, y, INSERT_VALUES, SCATTER_REVERSE)); 108ee1cef2cSJed Brown PetscFunctionReturn(0); 109ee1cef2cSJed Brown } 110ee1cef2cSJed Brown 111*9371c9d4SSatish Balay static PetscErrorCode MatMultTransposeAdd_SubMatrix(Mat N, Vec v1, Vec v2, Vec v3) { 11254e05e6cSHong Zhang Mat_SubVirtual *Na = (Mat_SubVirtual *)N->data; 113ee1cef2cSJed Brown 114ee1cef2cSJed Brown PetscFunctionBegin; 1159566063dSJacob Faibussowitsch PetscCall(VecZeroEntries(Na->lwork)); 1169566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(Na->lrestrict, v1, Na->lwork, INSERT_VALUES, SCATTER_REVERSE)); 1179566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(Na->lrestrict, v1, Na->lwork, INSERT_VALUES, SCATTER_REVERSE)); 11811c5f74dSStefano Zampini if (v1 == v2) { 1199566063dSJacob Faibussowitsch PetscCall(MatMultTransposeAdd(Na->A, Na->lwork, Na->lwork, Na->rwork)); 12011c5f74dSStefano Zampini } else if (v2 == v3) { 1219566063dSJacob Faibussowitsch PetscCall(VecZeroEntries(Na->rwork)); 1229566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(Na->rprolong, v2, Na->rwork, INSERT_VALUES, SCATTER_FORWARD)); 1239566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(Na->rprolong, v2, Na->rwork, INSERT_VALUES, SCATTER_FORWARD)); 1249566063dSJacob Faibussowitsch PetscCall(MatMultTransposeAdd(Na->A, Na->lwork, Na->rwork, Na->rwork)); 1251e7f0bbdSJed Brown } else { 12611c5f74dSStefano Zampini if (!Na->rwork2) { 1279566063dSJacob Faibussowitsch PetscCall(VecDuplicate(Na->rwork, &Na->rwork2)); 12811c5f74dSStefano Zampini } else { 1299566063dSJacob Faibussowitsch PetscCall(VecZeroEntries(Na->rwork2)); 13011c5f74dSStefano Zampini } 1319566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(Na->rprolong, v2, Na->rwork2, INSERT_VALUES, SCATTER_FORWARD)); 1329566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(Na->rprolong, v2, Na->rwork2, INSERT_VALUES, SCATTER_FORWARD)); 1339566063dSJacob Faibussowitsch PetscCall(MatMultTransposeAdd(Na->A, Na->lwork, Na->rwork2, Na->rwork)); 13411c5f74dSStefano Zampini } 1359566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(Na->rprolong, Na->rwork, v3, INSERT_VALUES, SCATTER_REVERSE)); 1369566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(Na->rprolong, Na->rwork, v3, INSERT_VALUES, SCATTER_REVERSE)); 137ee1cef2cSJed Brown PetscFunctionReturn(0); 138ee1cef2cSJed Brown } 139ee1cef2cSJed Brown 140*9371c9d4SSatish Balay static PetscErrorCode MatDestroy_SubMatrix(Mat N) { 14154e05e6cSHong Zhang Mat_SubVirtual *Na = (Mat_SubVirtual *)N->data; 142ee1cef2cSJed Brown 143ee1cef2cSJed Brown PetscFunctionBegin; 1449566063dSJacob Faibussowitsch PetscCall(ISDestroy(&Na->isrow)); 1459566063dSJacob Faibussowitsch PetscCall(ISDestroy(&Na->iscol)); 1469566063dSJacob Faibussowitsch PetscCall(VecDestroy(&Na->lwork)); 1479566063dSJacob Faibussowitsch PetscCall(VecDestroy(&Na->rwork)); 1489566063dSJacob Faibussowitsch PetscCall(VecDestroy(&Na->lwork2)); 1499566063dSJacob Faibussowitsch PetscCall(VecDestroy(&Na->rwork2)); 1509566063dSJacob Faibussowitsch PetscCall(VecScatterDestroy(&Na->lrestrict)); 1519566063dSJacob Faibussowitsch PetscCall(VecScatterDestroy(&Na->rprolong)); 1529566063dSJacob Faibussowitsch PetscCall(MatDestroy(&Na->A)); 1539566063dSJacob Faibussowitsch PetscCall(PetscFree(N->data)); 154ee1cef2cSJed Brown PetscFunctionReturn(0); 155ee1cef2cSJed Brown } 156ee1cef2cSJed Brown 157ee1cef2cSJed Brown /*@ 15854e05e6cSHong Zhang MatCreateSubMatrixVirtual - Creates a virtual matrix that acts as a submatrix 159ee1cef2cSJed Brown 160ee1cef2cSJed Brown Collective on Mat 161ee1cef2cSJed Brown 162ee1cef2cSJed Brown Input Parameters: 163ee1cef2cSJed Brown + A - matrix that we will extract a submatrix of 164ee1cef2cSJed Brown . isrow - rows to be present in the submatrix 165ee1cef2cSJed Brown - iscol - columns to be present in the submatrix 166ee1cef2cSJed Brown 167ee1cef2cSJed Brown Output Parameters: 168ee1cef2cSJed Brown . newmat - new matrix 169ee1cef2cSJed Brown 170ee1cef2cSJed Brown Level: developer 171ee1cef2cSJed Brown 172ee1cef2cSJed Brown Notes: 1737dae84e0SHong Zhang Most will use MatCreateSubMatrix which provides a more efficient representation if it is available. 174ee1cef2cSJed Brown 175db781477SPatrick Sanan .seealso: `MatCreateSubMatrix()`, `MatSubMatrixVirtualUpdate()` 176ee1cef2cSJed Brown @*/ 177*9371c9d4SSatish Balay PetscErrorCode MatCreateSubMatrixVirtual(Mat A, IS isrow, IS iscol, Mat *newmat) { 178ee1cef2cSJed Brown Vec left, right; 179ee1cef2cSJed Brown PetscInt m, n; 180ee1cef2cSJed Brown Mat N; 18154e05e6cSHong Zhang Mat_SubVirtual *Na; 182ee1cef2cSJed Brown 183ee1cef2cSJed Brown PetscFunctionBegin; 1840700a824SBarry Smith PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 1850700a824SBarry Smith PetscValidHeaderSpecific(isrow, IS_CLASSID, 2); 1860700a824SBarry Smith PetscValidHeaderSpecific(iscol, IS_CLASSID, 3); 187ee1cef2cSJed Brown PetscValidPointer(newmat, 4); 188f4259b30SLisandro Dalcin *newmat = NULL; 189ee1cef2cSJed Brown 1909566063dSJacob Faibussowitsch PetscCall(MatCreate(PetscObjectComm((PetscObject)A), &N)); 1919566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(isrow, &m)); 1929566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(iscol, &n)); 1939566063dSJacob Faibussowitsch PetscCall(MatSetSizes(N, m, n, PETSC_DETERMINE, PETSC_DETERMINE)); 1949566063dSJacob Faibussowitsch PetscCall(PetscObjectChangeTypeName((PetscObject)N, MATSUBMATRIX)); 195ee1cef2cSJed Brown 1969566063dSJacob Faibussowitsch PetscCall(PetscNewLog(N, &Na)); 197ee1cef2cSJed Brown N->data = (void *)Na; 19811c5f74dSStefano Zampini 1999566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)isrow)); 2009566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)iscol)); 201ee1cef2cSJed Brown Na->isrow = isrow; 202ee1cef2cSJed Brown Na->iscol = iscol; 20311c5f74dSStefano Zampini 2049566063dSJacob Faibussowitsch PetscCall(PetscFree(N->defaultvectype)); 2059566063dSJacob Faibussowitsch PetscCall(PetscStrallocpy(A->defaultvectype, &N->defaultvectype)); 20611c5f74dSStefano Zampini /* Do not use MatConvert directly since MatShell has a duplicate operation which does not increase 20711c5f74dSStefano Zampini the reference count of the context. This is a problem if A is already of type MATSHELL */ 2089566063dSJacob Faibussowitsch PetscCall(MatConvertFrom_Shell(A, MATSHELL, MAT_INITIAL_MATRIX, &Na->A)); 209ee1cef2cSJed Brown 210ee1cef2cSJed Brown N->ops->destroy = MatDestroy_SubMatrix; 211ee1cef2cSJed Brown N->ops->mult = MatMult_SubMatrix; 212ee1cef2cSJed Brown N->ops->multadd = MatMultAdd_SubMatrix; 213ee1cef2cSJed Brown N->ops->multtranspose = MatMultTranspose_SubMatrix; 214ee1cef2cSJed Brown N->ops->multtransposeadd = MatMultTransposeAdd_SubMatrix; 215ee1cef2cSJed Brown N->ops->scale = MatScale_SubMatrix; 216ee1cef2cSJed Brown N->ops->diagonalscale = MatDiagonalScale_SubMatrix; 217bddd1ffdSAlp Dener N->ops->shift = MatShift_SubMatrix; 21811c5f74dSStefano Zampini N->ops->convert = MatConvert_Shell; 21911c5f74dSStefano Zampini N->ops->getdiagonal = MatGetDiagonal_SubMatrix; 220ee1cef2cSJed Brown 2219566063dSJacob Faibussowitsch PetscCall(MatSetBlockSizesFromMats(N, A, A)); 2229566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetUp(N->rmap)); 2239566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetUp(N->cmap)); 224ee1cef2cSJed Brown 2259566063dSJacob Faibussowitsch PetscCall(MatCreateVecs(A, &Na->rwork, &Na->lwork)); 2269566063dSJacob Faibussowitsch PetscCall(MatCreateVecs(N, &right, &left)); 2279566063dSJacob Faibussowitsch PetscCall(VecScatterCreate(Na->lwork, isrow, left, NULL, &Na->lrestrict)); 2289566063dSJacob Faibussowitsch PetscCall(VecScatterCreate(right, NULL, Na->rwork, iscol, &Na->rprolong)); 2299566063dSJacob Faibussowitsch PetscCall(VecDestroy(&left)); 2309566063dSJacob Faibussowitsch PetscCall(VecDestroy(&right)); 2319566063dSJacob Faibussowitsch PetscCall(MatSetUp(N)); 23226fbe8dcSKarl Rupp 23311c5f74dSStefano Zampini N->assembled = PETSC_TRUE; 234ee1cef2cSJed Brown *newmat = N; 235ee1cef2cSJed Brown PetscFunctionReturn(0); 236ee1cef2cSJed Brown } 237ee1cef2cSJed Brown 238ee1cef2cSJed Brown /*@ 23954e05e6cSHong Zhang MatSubMatrixVirtualUpdate - Updates a submatrix 240ee1cef2cSJed Brown 241ee1cef2cSJed Brown Collective on Mat 242ee1cef2cSJed Brown 243ee1cef2cSJed Brown Input Parameters: 244ee1cef2cSJed Brown + N - submatrix to update 245ee1cef2cSJed Brown . A - full matrix in the submatrix 246ee1cef2cSJed Brown . isrow - rows in the update (same as the first time the submatrix was created) 247ee1cef2cSJed Brown - iscol - columns in the update (same as the first time the submatrix was created) 248ee1cef2cSJed Brown 249ee1cef2cSJed Brown Level: developer 250ee1cef2cSJed Brown 251ee1cef2cSJed Brown Notes: 2527dae84e0SHong Zhang Most will use MatCreateSubMatrix which provides a more efficient representation if it is available. 253ee1cef2cSJed Brown 254db781477SPatrick Sanan .seealso: `MatCreateSubMatrixVirtual()` 255ee1cef2cSJed Brown @*/ 256*9371c9d4SSatish Balay PetscErrorCode MatSubMatrixVirtualUpdate(Mat N, Mat A, IS isrow, IS iscol) { 257ace3abfcSBarry Smith PetscBool flg; 25854e05e6cSHong Zhang Mat_SubVirtual *Na; 259ee1cef2cSJed Brown 260ee1cef2cSJed Brown PetscFunctionBegin; 2610700a824SBarry Smith PetscValidHeaderSpecific(N, MAT_CLASSID, 1); 2620700a824SBarry Smith PetscValidHeaderSpecific(A, MAT_CLASSID, 2); 2630700a824SBarry Smith PetscValidHeaderSpecific(isrow, IS_CLASSID, 3); 2640700a824SBarry Smith PetscValidHeaderSpecific(iscol, IS_CLASSID, 4); 2659566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)N, MATSUBMATRIX, &flg)); 26628b400f6SJacob Faibussowitsch PetscCheck(flg, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONG, "Matrix has wrong type"); 267ee1cef2cSJed Brown 26854e05e6cSHong Zhang Na = (Mat_SubVirtual *)N->data; 2699566063dSJacob Faibussowitsch PetscCall(ISEqual(isrow, Na->isrow, &flg)); 27028b400f6SJacob Faibussowitsch PetscCheck(flg, PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, "Cannot update submatrix with different row indices"); 2719566063dSJacob Faibussowitsch PetscCall(ISEqual(iscol, Na->iscol, &flg)); 27228b400f6SJacob Faibussowitsch PetscCheck(flg, PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, "Cannot update submatrix with different column indices"); 273ee1cef2cSJed Brown 2749566063dSJacob Faibussowitsch PetscCall(PetscFree(N->defaultvectype)); 2759566063dSJacob Faibussowitsch PetscCall(PetscStrallocpy(A->defaultvectype, &N->defaultvectype)); 2769566063dSJacob Faibussowitsch PetscCall(MatDestroy(&Na->A)); 27711c5f74dSStefano Zampini /* Do not use MatConvert directly since MatShell has a duplicate operation which does not increase 27811c5f74dSStefano Zampini the reference count of the context. This is a problem if A is already of type MATSHELL */ 2799566063dSJacob Faibussowitsch PetscCall(MatConvertFrom_Shell(A, MATSHELL, MAT_INITIAL_MATRIX, &Na->A)); 280ee1cef2cSJed Brown PetscFunctionReturn(0); 281ee1cef2cSJed Brown } 282