1345a4b08SToby Isaac #include <petsc/private/matimpl.h> /*I "petscmat.h" I*/ 2345a4b08SToby Isaac 3345a4b08SToby Isaac typedef struct { 4345a4b08SToby Isaac Vec diag; 5345a4b08SToby Isaac PetscBool diag_valid; 6345a4b08SToby Isaac Vec inv_diag; 7345a4b08SToby Isaac PetscBool inv_diag_valid; 8345a4b08SToby Isaac PetscObjectState diag_state, inv_diag_state; 9c3e1b152SPierre Jolivet PetscInt *col; 10c3e1b152SPierre Jolivet PetscScalar *val; 11345a4b08SToby Isaac } Mat_Diagonal; 12345a4b08SToby Isaac 13345a4b08SToby Isaac static PetscErrorCode MatDiagonalSetUpDiagonal(Mat A) 14345a4b08SToby Isaac { 15345a4b08SToby Isaac Mat_Diagonal *ctx = (Mat_Diagonal *)A->data; 16345a4b08SToby Isaac 17345a4b08SToby Isaac PetscFunctionBegin; 18345a4b08SToby Isaac if (!ctx->diag_valid) { 19345a4b08SToby Isaac PetscAssert(ctx->inv_diag_valid, PetscObjectComm((PetscObject)A), PETSC_ERR_PLIB, "Neither diagonal nor inverse diagonal is in a valid state"); 20345a4b08SToby Isaac PetscCall(VecCopy(ctx->inv_diag, ctx->diag)); 21345a4b08SToby Isaac PetscCall(VecReciprocal(ctx->diag)); 22345a4b08SToby Isaac ctx->diag_valid = PETSC_TRUE; 23345a4b08SToby Isaac } 24345a4b08SToby Isaac PetscFunctionReturn(PETSC_SUCCESS); 25345a4b08SToby Isaac } 26345a4b08SToby Isaac 27345a4b08SToby Isaac static PetscErrorCode MatDiagonalSetUpInverseDiagonal(Mat A) 28345a4b08SToby Isaac { 29345a4b08SToby Isaac Mat_Diagonal *ctx = (Mat_Diagonal *)A->data; 30345a4b08SToby Isaac 31345a4b08SToby Isaac PetscFunctionBegin; 32345a4b08SToby Isaac if (!ctx->inv_diag_valid) { 33345a4b08SToby Isaac PetscAssert(ctx->diag_valid, PetscObjectComm((PetscObject)A), PETSC_ERR_PLIB, "Neither diagonal nor inverse diagonal is in a valid state"); 34345a4b08SToby Isaac PetscCall(VecCopy(ctx->diag, ctx->inv_diag)); 35345a4b08SToby Isaac PetscCall(VecReciprocal(ctx->inv_diag)); 36345a4b08SToby Isaac ctx->inv_diag_valid = PETSC_TRUE; 37345a4b08SToby Isaac } 38345a4b08SToby Isaac PetscFunctionReturn(PETSC_SUCCESS); 39345a4b08SToby Isaac } 40345a4b08SToby Isaac 41345a4b08SToby Isaac static PetscErrorCode MatAXPY_Diagonal(Mat Y, PetscScalar a, Mat X, MatStructure str) 42345a4b08SToby Isaac { 43345a4b08SToby Isaac Mat_Diagonal *yctx = (Mat_Diagonal *)Y->data; 44345a4b08SToby Isaac Mat_Diagonal *xctx = (Mat_Diagonal *)X->data; 45345a4b08SToby Isaac 46345a4b08SToby Isaac PetscFunctionBegin; 47345a4b08SToby Isaac PetscCall(MatDiagonalSetUpDiagonal(Y)); 48345a4b08SToby Isaac PetscCall(MatDiagonalSetUpDiagonal(X)); 49345a4b08SToby Isaac PetscCall(VecAXPY(yctx->diag, a, xctx->diag)); 50345a4b08SToby Isaac yctx->inv_diag_valid = PETSC_FALSE; 51345a4b08SToby Isaac PetscFunctionReturn(PETSC_SUCCESS); 52345a4b08SToby Isaac } 53345a4b08SToby Isaac 54c3e1b152SPierre Jolivet static PetscErrorCode MatGetRow_Diagonal(Mat A, PetscInt row, PetscInt *ncols, PetscInt **cols, PetscScalar **vals) 55c3e1b152SPierre Jolivet { 56c3e1b152SPierre Jolivet Mat_Diagonal *mat = (Mat_Diagonal *)A->data; 57*09a7ae42SPierre Jolivet PetscInt rstart = A->rmap->rstart, rend = A->rmap->rend; 58c3e1b152SPierre Jolivet 59c3e1b152SPierre Jolivet PetscFunctionBegin; 60*09a7ae42SPierre Jolivet PetscCheck(row >= rstart && row < rend, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Only local rows"); 61c3e1b152SPierre Jolivet if (ncols) *ncols = 1; 62c3e1b152SPierre Jolivet if (cols) { 63c3e1b152SPierre Jolivet if (!mat->col) PetscCall(PetscMalloc1(1, &mat->col)); 64c3e1b152SPierre Jolivet *mat->col = row; 65c3e1b152SPierre Jolivet *cols = mat->col; 66c3e1b152SPierre Jolivet } 67c3e1b152SPierre Jolivet if (vals) { 68c3e1b152SPierre Jolivet const PetscScalar *v; 69c3e1b152SPierre Jolivet 70c3e1b152SPierre Jolivet if (!mat->val) PetscCall(PetscMalloc1(1, &mat->val)); 71c3e1b152SPierre Jolivet PetscCall(VecGetArrayRead(mat->diag, &v)); 72*09a7ae42SPierre Jolivet *mat->val = v[row - rstart]; 73c3e1b152SPierre Jolivet *vals = mat->val; 74c3e1b152SPierre Jolivet PetscCall(VecRestoreArrayRead(mat->diag, &v)); 75c3e1b152SPierre Jolivet } 76c3e1b152SPierre Jolivet PetscFunctionReturn(PETSC_SUCCESS); 77c3e1b152SPierre Jolivet } 78c3e1b152SPierre Jolivet 79345a4b08SToby Isaac static PetscErrorCode MatMult_Diagonal(Mat A, Vec x, Vec y) 80345a4b08SToby Isaac { 81345a4b08SToby Isaac Mat_Diagonal *ctx = (Mat_Diagonal *)A->data; 82345a4b08SToby Isaac 83345a4b08SToby Isaac PetscFunctionBegin; 84345a4b08SToby Isaac PetscCall(MatDiagonalSetUpDiagonal(A)); 85345a4b08SToby Isaac PetscCall(VecPointwiseMult(y, ctx->diag, x)); 86345a4b08SToby Isaac PetscFunctionReturn(PETSC_SUCCESS); 87345a4b08SToby Isaac } 88345a4b08SToby Isaac 89345a4b08SToby Isaac static PetscErrorCode MatMultAdd_Diagonal(Mat mat, Vec v1, Vec v2, Vec v3) 90345a4b08SToby Isaac { 91345a4b08SToby Isaac Mat_Diagonal *ctx = (Mat_Diagonal *)mat->data; 92345a4b08SToby Isaac 93345a4b08SToby Isaac PetscFunctionBegin; 94345a4b08SToby Isaac PetscCall(MatDiagonalSetUpDiagonal(mat)); 95345a4b08SToby Isaac if (v2 != v3) { 96345a4b08SToby Isaac PetscCall(VecPointwiseMult(v3, ctx->diag, v1)); 97345a4b08SToby Isaac PetscCall(VecAXPY(v3, 1.0, v2)); 98345a4b08SToby Isaac } else { 99345a4b08SToby Isaac Vec w; 100345a4b08SToby Isaac PetscCall(VecDuplicate(v3, &w)); 101345a4b08SToby Isaac PetscCall(VecPointwiseMult(w, ctx->diag, v1)); 102345a4b08SToby Isaac PetscCall(VecAXPY(v3, 1.0, w)); 103345a4b08SToby Isaac PetscCall(VecDestroy(&w)); 104345a4b08SToby Isaac } 105345a4b08SToby Isaac PetscFunctionReturn(PETSC_SUCCESS); 106345a4b08SToby Isaac } 107345a4b08SToby Isaac 108345a4b08SToby Isaac static PetscErrorCode MatNorm_Diagonal(Mat A, NormType type, PetscReal *nrm) 109345a4b08SToby Isaac { 110345a4b08SToby Isaac Mat_Diagonal *ctx = (Mat_Diagonal *)A->data; 111345a4b08SToby Isaac 112345a4b08SToby Isaac PetscFunctionBegin; 113345a4b08SToby Isaac PetscCall(MatDiagonalSetUpDiagonal(A)); 114345a4b08SToby Isaac type = (type == NORM_FROBENIUS) ? NORM_2 : NORM_INFINITY; 115345a4b08SToby Isaac PetscCall(VecNorm(ctx->diag, type, nrm)); 116345a4b08SToby Isaac PetscFunctionReturn(PETSC_SUCCESS); 117345a4b08SToby Isaac } 118345a4b08SToby Isaac 119345a4b08SToby Isaac static PetscErrorCode MatDuplicate_Diagonal(Mat A, MatDuplicateOption op, Mat *B) 120345a4b08SToby Isaac { 121345a4b08SToby Isaac Mat_Diagonal *actx = (Mat_Diagonal *)A->data; 122345a4b08SToby Isaac 123345a4b08SToby Isaac PetscFunctionBegin; 124345a4b08SToby Isaac PetscCall(MatCreate(PetscObjectComm((PetscObject)A), B)); 125345a4b08SToby Isaac PetscCall(MatSetSizes(*B, A->rmap->n, A->cmap->n, A->rmap->N, A->cmap->N)); 126345a4b08SToby Isaac PetscCall(MatSetBlockSizesFromMats(*B, A, A)); 127345a4b08SToby Isaac PetscCall(MatSetType(*B, MATDIAGONAL)); 128345a4b08SToby Isaac PetscCall(PetscLayoutReference(A->rmap, &(*B)->rmap)); 129345a4b08SToby Isaac PetscCall(PetscLayoutReference(A->cmap, &(*B)->cmap)); 130345a4b08SToby Isaac if (op == MAT_COPY_VALUES) { 131345a4b08SToby Isaac Mat_Diagonal *bctx = (Mat_Diagonal *)(*B)->data; 132345a4b08SToby Isaac 133345a4b08SToby Isaac PetscCall(MatSetUp(A)); 134345a4b08SToby Isaac PetscCall(MatSetUp(*B)); 135345a4b08SToby Isaac PetscCall(VecCopy(actx->diag, bctx->diag)); 136345a4b08SToby Isaac PetscCall(VecCopy(actx->inv_diag, bctx->inv_diag)); 137345a4b08SToby Isaac bctx->diag_valid = actx->diag_valid; 138345a4b08SToby Isaac bctx->inv_diag_valid = actx->inv_diag_valid; 139345a4b08SToby Isaac } 140345a4b08SToby Isaac PetscFunctionReturn(PETSC_SUCCESS); 141345a4b08SToby Isaac } 142345a4b08SToby Isaac 143345a4b08SToby Isaac /*@ 144345a4b08SToby Isaac MatDiagonalGetDiagonal - Get the diagonal of a `MATDIAGONAL` 145345a4b08SToby Isaac 146345a4b08SToby Isaac Input Parameter: 147345a4b08SToby Isaac . A - the `MATDIAGONAL` 148345a4b08SToby Isaac 149345a4b08SToby Isaac Output Parameter: 150345a4b08SToby Isaac . diag - the `Vec` that defines the diagonal 151345a4b08SToby Isaac 152345a4b08SToby Isaac Level: developer 153345a4b08SToby Isaac 154345a4b08SToby Isaac Note: 155345a4b08SToby Isaac The user must call 156345a4b08SToby Isaac `MatDiagonalRestoreDiagonal()` before using the matrix again. 157345a4b08SToby Isaac 158345a4b08SToby Isaac For a copy of the diagonal values, rather than a reference, use `MatGetDiagonal()` 159345a4b08SToby Isaac 160345a4b08SToby Isaac Any changes to the obtained vector immediately change the action of the `Mat`. The matrix can be changed more efficiently by accessing this vector and changing its values, instead of filling a work vector and using `MatDiagonalSet()` 161345a4b08SToby Isaac 162be50c303SSatish Balay .seealso: [](ch_matrices), `MATDIAGONAL`, `MatCreateDiagonal()`, `MatDiagonalRestoreDiagonal()`, `MatDiagonalGetInverseDiagonal()`, `MatGetDiagonal()` 163345a4b08SToby Isaac @*/ 164345a4b08SToby Isaac PetscErrorCode MatDiagonalGetDiagonal(Mat A, Vec *diag) 165345a4b08SToby Isaac { 166345a4b08SToby Isaac PetscFunctionBegin; 167345a4b08SToby Isaac PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 1684f572ea9SToby Isaac PetscAssertPointer(diag, 2); 169345a4b08SToby Isaac *diag = NULL; 170835f2295SStefano Zampini PetscUseMethod(A, "MatDiagonalGetDiagonal_C", (Mat, Vec *), (A, diag)); 171345a4b08SToby Isaac PetscFunctionReturn(PETSC_SUCCESS); 172345a4b08SToby Isaac } 173345a4b08SToby Isaac 174345a4b08SToby Isaac static PetscErrorCode MatDiagonalGetDiagonal_Diagonal(Mat A, Vec *diag) 175345a4b08SToby Isaac { 176345a4b08SToby Isaac Mat_Diagonal *ctx = (Mat_Diagonal *)A->data; 177345a4b08SToby Isaac 178345a4b08SToby Isaac PetscFunctionBegin; 179345a4b08SToby Isaac PetscCall(MatSetUp(A)); 180345a4b08SToby Isaac PetscCall(MatDiagonalSetUpDiagonal(A)); 181345a4b08SToby Isaac *diag = ctx->diag; 182345a4b08SToby Isaac PetscCall(PetscObjectStateGet((PetscObject)*diag, &ctx->diag_state)); 183345a4b08SToby Isaac PetscFunctionReturn(PETSC_SUCCESS); 184345a4b08SToby Isaac } 185345a4b08SToby Isaac 186345a4b08SToby Isaac /*@ 187345a4b08SToby Isaac MatDiagonalRestoreDiagonal - Restore the diagonal of a `MATDIAGONAL` 188345a4b08SToby Isaac 189345a4b08SToby Isaac Input Parameters: 190345a4b08SToby Isaac + A - the `MATDIAGONAL` 191345a4b08SToby Isaac - diag - the `Vec` obtained from `MatDiagonalGetDiagonal()` 192345a4b08SToby Isaac 193345a4b08SToby Isaac Level: developer 194345a4b08SToby Isaac 195345a4b08SToby Isaac Note: 196345a4b08SToby Isaac Use `MatDiagonalSet()` to change the values by copy, rather than reference. 197345a4b08SToby Isaac 198be50c303SSatish Balay .seealso: [](ch_matrices), `MATDIAGONAL`, `MatCreateDiagonal()`, `MatDiagonalGetDiagonal()` 199345a4b08SToby Isaac @*/ 200345a4b08SToby Isaac PetscErrorCode MatDiagonalRestoreDiagonal(Mat A, Vec *diag) 201345a4b08SToby Isaac { 202345a4b08SToby Isaac PetscFunctionBegin; 203345a4b08SToby Isaac PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 2044f572ea9SToby Isaac PetscAssertPointer(diag, 2); 205835f2295SStefano Zampini PetscUseMethod(A, "MatDiagonalRestoreDiagonal_C", (Mat, Vec *), (A, diag)); 206345a4b08SToby Isaac PetscFunctionReturn(PETSC_SUCCESS); 207345a4b08SToby Isaac } 208345a4b08SToby Isaac 209345a4b08SToby Isaac static PetscErrorCode MatDiagonalRestoreDiagonal_Diagonal(Mat A, Vec *diag) 210345a4b08SToby Isaac { 211345a4b08SToby Isaac Mat_Diagonal *ctx = (Mat_Diagonal *)A->data; 212345a4b08SToby Isaac PetscObjectState diag_state; 213345a4b08SToby Isaac 214345a4b08SToby Isaac PetscFunctionBegin; 215345a4b08SToby Isaac PetscCheck(ctx->diag == *diag, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONG, "Restored a different diagonal vector"); 216345a4b08SToby Isaac ctx->diag_valid = PETSC_TRUE; 217345a4b08SToby Isaac PetscCall(PetscObjectStateGet((PetscObject)*diag, &diag_state)); 218345a4b08SToby Isaac if (ctx->diag_state != diag_state) { 219345a4b08SToby Isaac PetscCall(PetscObjectStateIncrease((PetscObject)A)); 220345a4b08SToby Isaac ctx->inv_diag_valid = PETSC_FALSE; 221345a4b08SToby Isaac } 222345a4b08SToby Isaac *diag = NULL; 223345a4b08SToby Isaac PetscFunctionReturn(PETSC_SUCCESS); 224345a4b08SToby Isaac } 225345a4b08SToby Isaac 226345a4b08SToby Isaac /*@ 227345a4b08SToby Isaac MatDiagonalGetInverseDiagonal - Get the inverse diagonal of a `MATDIAGONAL` 228345a4b08SToby Isaac 229345a4b08SToby Isaac Input Parameter: 230345a4b08SToby Isaac . A - the `MATDIAGONAL` 231345a4b08SToby Isaac 232345a4b08SToby Isaac Output Parameter: 233345a4b08SToby Isaac . inv_diag - the `Vec` that defines the inverse diagonal 234345a4b08SToby Isaac 235345a4b08SToby Isaac Level: developer 236345a4b08SToby Isaac 237345a4b08SToby Isaac Note: 238345a4b08SToby Isaac The user must call 239345a4b08SToby Isaac `MatDiagonalRestoreInverseDiagonal()` before using the matrix again. 240345a4b08SToby Isaac 241345a4b08SToby Isaac If a matrix is created only to call `MatSolve()` (which happens for `MATLMVMDIAGBROYDEN`), 242345a4b08SToby Isaac using `MatDiagonalGetInverseDiagonal()` and `MatDiagonalRestoreInverseDiagonal()` avoids copies 243345a4b08SToby Isaac and avoids any call to `VecReciprocal()`. 244345a4b08SToby Isaac 245be50c303SSatish Balay .seealso: [](ch_matrices), `MATDIAGONAL`, `MatCreateDiagonal()`, `MatDiagonalRestoreInverseDiagonal()`, `MatDiagonalGetDiagonal()`, `MATLMVMBROYDEN`, `MatSolve()` 246345a4b08SToby Isaac @*/ 247345a4b08SToby Isaac PetscErrorCode MatDiagonalGetInverseDiagonal(Mat A, Vec *inv_diag) 248345a4b08SToby Isaac { 249345a4b08SToby Isaac PetscFunctionBegin; 250345a4b08SToby Isaac PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 2514f572ea9SToby Isaac PetscAssertPointer(inv_diag, 2); 252345a4b08SToby Isaac *inv_diag = NULL; 253835f2295SStefano Zampini PetscUseMethod(A, "MatDiagonalGetInverseDiagonal_C", (Mat, Vec *), (A, inv_diag)); 254345a4b08SToby Isaac PetscFunctionReturn(PETSC_SUCCESS); 255345a4b08SToby Isaac } 256345a4b08SToby Isaac 257345a4b08SToby Isaac static PetscErrorCode MatDiagonalGetInverseDiagonal_Diagonal(Mat A, Vec *inv_diag) 258345a4b08SToby Isaac { 259345a4b08SToby Isaac Mat_Diagonal *ctx = (Mat_Diagonal *)A->data; 260345a4b08SToby Isaac 261345a4b08SToby Isaac PetscFunctionBegin; 262345a4b08SToby Isaac PetscCall(MatSetUp(A)); 263345a4b08SToby Isaac PetscCall(MatDiagonalSetUpInverseDiagonal(A)); 264345a4b08SToby Isaac *inv_diag = ctx->inv_diag; 265345a4b08SToby Isaac PetscCall(PetscObjectStateGet((PetscObject)*inv_diag, &ctx->inv_diag_state)); 266345a4b08SToby Isaac PetscFunctionReturn(PETSC_SUCCESS); 267345a4b08SToby Isaac } 268345a4b08SToby Isaac 269345a4b08SToby Isaac /*@ 270345a4b08SToby Isaac MatDiagonalRestoreInverseDiagonal - Restore the inverse diagonal of a `MATDIAGONAL` 271345a4b08SToby Isaac 272345a4b08SToby Isaac Input Parameters: 273345a4b08SToby Isaac + A - the `MATDIAGONAL` 274345a4b08SToby Isaac - inv_diag - the `Vec` obtained from `MatDiagonalGetInverseDiagonal()` 275345a4b08SToby Isaac 276345a4b08SToby Isaac Level: developer 277345a4b08SToby Isaac 278be50c303SSatish Balay .seealso: [](ch_matrices), `MATDIAGONAL`, `MatCreateDiagonal()`, `MatDiagonalGetInverseDiagonal()` 279345a4b08SToby Isaac @*/ 280345a4b08SToby Isaac PetscErrorCode MatDiagonalRestoreInverseDiagonal(Mat A, Vec *inv_diag) 281345a4b08SToby Isaac { 282345a4b08SToby Isaac PetscFunctionBegin; 283345a4b08SToby Isaac PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 2844f572ea9SToby Isaac PetscAssertPointer(inv_diag, 2); 285835f2295SStefano Zampini PetscUseMethod(A, "MatDiagonalRestoreInverseDiagonal_C", (Mat, Vec *), (A, inv_diag)); 286345a4b08SToby Isaac PetscFunctionReturn(PETSC_SUCCESS); 287345a4b08SToby Isaac } 288345a4b08SToby Isaac 289345a4b08SToby Isaac static PetscErrorCode MatDiagonalRestoreInverseDiagonal_Diagonal(Mat A, Vec *inv_diag) 290345a4b08SToby Isaac { 291345a4b08SToby Isaac Mat_Diagonal *ctx = (Mat_Diagonal *)A->data; 292345a4b08SToby Isaac PetscObjectState inv_diag_state; 293345a4b08SToby Isaac 294345a4b08SToby Isaac PetscFunctionBegin; 295345a4b08SToby Isaac PetscCheck(ctx->inv_diag == *inv_diag, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONG, "Restored a different diagonal vector"); 296345a4b08SToby Isaac ctx->inv_diag_valid = PETSC_TRUE; 297345a4b08SToby Isaac PetscCall(PetscObjectStateGet((PetscObject)*inv_diag, &inv_diag_state)); 298345a4b08SToby Isaac if (ctx->inv_diag_state != inv_diag_state) { 299345a4b08SToby Isaac PetscCall(PetscObjectStateIncrease((PetscObject)A)); 300345a4b08SToby Isaac ctx->diag_valid = PETSC_FALSE; 301345a4b08SToby Isaac } 302345a4b08SToby Isaac *inv_diag = NULL; 303345a4b08SToby Isaac PetscFunctionReturn(PETSC_SUCCESS); 304345a4b08SToby Isaac } 305345a4b08SToby Isaac 306ee8a0a41SPierre Jolivet static PetscErrorCode MatPermute_Diagonal(Mat A, IS rowp, IS colp, Mat *B) 307ee8a0a41SPierre Jolivet { 308ee8a0a41SPierre Jolivet Mat_Diagonal *ctx = (Mat_Diagonal *)A->data; 309ee8a0a41SPierre Jolivet Vec v; 310ee8a0a41SPierre Jolivet 311ee8a0a41SPierre Jolivet PetscFunctionBegin; 312ee8a0a41SPierre Jolivet PetscCheck(rowp == colp, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_INCOMP, "Row permutation and column permutation must be the same"); 313ee8a0a41SPierre Jolivet PetscCall(VecDuplicate(ctx->diag, &v)); 314ee8a0a41SPierre Jolivet PetscCall(VecCopy(ctx->diag, v)); 315ee8a0a41SPierre Jolivet PetscCall(VecPermute(v, rowp, PETSC_FALSE)); 316ee8a0a41SPierre Jolivet PetscCall(MatCreateDiagonal(v, B)); 317ee8a0a41SPierre Jolivet PetscCall(VecDestroy(&v)); 318ee8a0a41SPierre Jolivet PetscFunctionReturn(PETSC_SUCCESS); 319ee8a0a41SPierre Jolivet } 320ee8a0a41SPierre Jolivet 3218a1df862SToby Isaac static PetscErrorCode MatSetRandom_Diagonal(Mat A, PetscRandom rand) 3228a1df862SToby Isaac { 3238a1df862SToby Isaac Vec d; 3248a1df862SToby Isaac 3258a1df862SToby Isaac PetscFunctionBegin; 3268a1df862SToby Isaac PetscCall(MatDiagonalGetDiagonal(A, &d)); 3278a1df862SToby Isaac PetscCall(VecSetRandom(d, rand)); 3288a1df862SToby Isaac PetscCall(MatDiagonalRestoreDiagonal(A, &d)); 3298a1df862SToby Isaac PetscFunctionReturn(PETSC_SUCCESS); 3308a1df862SToby Isaac } 3318a1df862SToby Isaac 332345a4b08SToby Isaac static PetscErrorCode MatDestroy_Diagonal(Mat mat) 333345a4b08SToby Isaac { 334345a4b08SToby Isaac Mat_Diagonal *ctx = (Mat_Diagonal *)mat->data; 335345a4b08SToby Isaac 336345a4b08SToby Isaac PetscFunctionBegin; 337345a4b08SToby Isaac PetscCall(VecDestroy(&ctx->diag)); 338345a4b08SToby Isaac PetscCall(VecDestroy(&ctx->inv_diag)); 339c3e1b152SPierre Jolivet PetscCall(PetscFree(ctx->col)); 340c3e1b152SPierre Jolivet PetscCall(PetscFree(ctx->val)); 341345a4b08SToby Isaac PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatDiagonalGetDiagonal_C", NULL)); 342345a4b08SToby Isaac PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatDiagonalRestoreDiagonal_C", NULL)); 343345a4b08SToby Isaac PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatDiagonalGetInverseDiagonal_C", NULL)); 344345a4b08SToby Isaac PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatDiagonalRestoreInverseDiagonal_C", NULL)); 345e27ab85cSPierre Jolivet PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatProductSetFromOptions_diagonal_seqdense_C", NULL)); 346e27ab85cSPierre Jolivet PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatProductSetFromOptions_diagonal_mpidense_C", NULL)); 347345a4b08SToby Isaac PetscCall(PetscFree(mat->data)); 348345a4b08SToby Isaac mat->structural_symmetry_eternal = PETSC_FALSE; 349345a4b08SToby Isaac mat->symmetry_eternal = PETSC_FALSE; 350345a4b08SToby Isaac PetscFunctionReturn(PETSC_SUCCESS); 351345a4b08SToby Isaac } 352345a4b08SToby Isaac 353345a4b08SToby Isaac static PetscErrorCode MatView_Diagonal(Mat J, PetscViewer viewer) 354345a4b08SToby Isaac { 355345a4b08SToby Isaac Mat_Diagonal *ctx = (Mat_Diagonal *)J->data; 3569f196a02SMartin Diehl PetscBool isascii; 357345a4b08SToby Isaac 358345a4b08SToby Isaac PetscFunctionBegin; 3599f196a02SMartin Diehl PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii)); 3609f196a02SMartin Diehl if (isascii) { 361345a4b08SToby Isaac PetscViewerFormat format; 362345a4b08SToby Isaac 363345a4b08SToby Isaac PetscCall(MatDiagonalSetUpDiagonal(J)); 3648a1df862SToby Isaac PetscCall(PetscViewerGetFormat(viewer, &format)); 3658a1df862SToby Isaac if (format == PETSC_VIEWER_ASCII_FACTOR_INFO || format == PETSC_VIEWER_ASCII_INFO) { 3668a1df862SToby Isaac PetscCall(PetscObjectPrintClassNamePrefixType((PetscObject)ctx->diag, viewer)); 3678a1df862SToby Isaac PetscFunctionReturn(PETSC_SUCCESS); 3688a1df862SToby Isaac } 369345a4b08SToby Isaac PetscCall(VecView(ctx->diag, viewer)); 370345a4b08SToby Isaac } 371345a4b08SToby Isaac PetscFunctionReturn(PETSC_SUCCESS); 372345a4b08SToby Isaac } 373345a4b08SToby Isaac 374345a4b08SToby Isaac static PetscErrorCode MatGetDiagonal_Diagonal(Mat J, Vec x) 375345a4b08SToby Isaac { 376345a4b08SToby Isaac Mat_Diagonal *ctx = (Mat_Diagonal *)J->data; 377345a4b08SToby Isaac 378345a4b08SToby Isaac PetscFunctionBegin; 379345a4b08SToby Isaac PetscCall(MatDiagonalSetUpDiagonal(J)); 380345a4b08SToby Isaac PetscCall(VecCopy(ctx->diag, x)); 381345a4b08SToby Isaac PetscFunctionReturn(PETSC_SUCCESS); 382345a4b08SToby Isaac } 383345a4b08SToby Isaac 384345a4b08SToby Isaac static PetscErrorCode MatDiagonalSet_Diagonal(Mat J, Vec D, InsertMode is) 385345a4b08SToby Isaac { 386345a4b08SToby Isaac Mat_Diagonal *ctx = (Mat_Diagonal *)J->data; 387345a4b08SToby Isaac 388345a4b08SToby Isaac PetscFunctionBegin; 389345a4b08SToby Isaac switch (is) { 390345a4b08SToby Isaac case ADD_VALUES: 391345a4b08SToby Isaac case ADD_ALL_VALUES: 392345a4b08SToby Isaac case ADD_BC_VALUES: 393345a4b08SToby Isaac PetscCall(MatDiagonalSetUpDiagonal(J)); 394345a4b08SToby Isaac PetscCall(VecAXPY(ctx->diag, 1.0, D)); 395345a4b08SToby Isaac ctx->inv_diag_valid = PETSC_FALSE; 396345a4b08SToby Isaac break; 397345a4b08SToby Isaac case INSERT_VALUES: 398345a4b08SToby Isaac case INSERT_BC_VALUES: 399345a4b08SToby Isaac case INSERT_ALL_VALUES: 400345a4b08SToby Isaac PetscCall(MatSetUp(J)); 401345a4b08SToby Isaac PetscCall(VecCopy(D, ctx->diag)); 402345a4b08SToby Isaac ctx->diag_valid = PETSC_TRUE; 403345a4b08SToby Isaac ctx->inv_diag_valid = PETSC_FALSE; 404345a4b08SToby Isaac break; 405345a4b08SToby Isaac case MAX_VALUES: 406345a4b08SToby Isaac PetscCall(MatDiagonalSetUpDiagonal(J)); 407345a4b08SToby Isaac PetscCall(VecPointwiseMax(ctx->diag, D, ctx->diag)); 408345a4b08SToby Isaac ctx->inv_diag_valid = PETSC_FALSE; 409345a4b08SToby Isaac break; 410345a4b08SToby Isaac case MIN_VALUES: 411345a4b08SToby Isaac PetscCall(MatDiagonalSetUpDiagonal(J)); 412345a4b08SToby Isaac PetscCall(VecPointwiseMin(ctx->diag, D, ctx->diag)); 413345a4b08SToby Isaac ctx->inv_diag_valid = PETSC_FALSE; 414345a4b08SToby Isaac break; 415345a4b08SToby Isaac case NOT_SET_VALUES: 416345a4b08SToby Isaac break; 417345a4b08SToby Isaac } 418345a4b08SToby Isaac PetscFunctionReturn(PETSC_SUCCESS); 419345a4b08SToby Isaac } 420345a4b08SToby Isaac 421345a4b08SToby Isaac static PetscErrorCode MatShift_Diagonal(Mat Y, PetscScalar a) 422345a4b08SToby Isaac { 423345a4b08SToby Isaac Mat_Diagonal *ctx = (Mat_Diagonal *)Y->data; 424345a4b08SToby Isaac 425345a4b08SToby Isaac PetscFunctionBegin; 426345a4b08SToby Isaac PetscCall(MatDiagonalSetUpDiagonal(Y)); 427345a4b08SToby Isaac PetscCall(VecShift(ctx->diag, a)); 428345a4b08SToby Isaac ctx->inv_diag_valid = PETSC_FALSE; 429345a4b08SToby Isaac PetscFunctionReturn(PETSC_SUCCESS); 430345a4b08SToby Isaac } 431345a4b08SToby Isaac 432345a4b08SToby Isaac static PetscErrorCode MatScale_Diagonal(Mat Y, PetscScalar a) 433345a4b08SToby Isaac { 434345a4b08SToby Isaac Mat_Diagonal *ctx = (Mat_Diagonal *)Y->data; 435345a4b08SToby Isaac 436345a4b08SToby Isaac PetscFunctionBegin; 437345a4b08SToby Isaac PetscCall(MatSetUp(Y)); 438345a4b08SToby Isaac PetscCall(MatDiagonalSetUpDiagonal(Y)); 439345a4b08SToby Isaac PetscCall(VecScale(ctx->diag, a)); 440345a4b08SToby Isaac ctx->inv_diag_valid = PETSC_FALSE; 441345a4b08SToby Isaac PetscFunctionReturn(PETSC_SUCCESS); 442345a4b08SToby Isaac } 443345a4b08SToby Isaac 444345a4b08SToby Isaac static PetscErrorCode MatDiagonalScale_Diagonal(Mat Y, Vec l, Vec r) 445345a4b08SToby Isaac { 446345a4b08SToby Isaac Mat_Diagonal *ctx = (Mat_Diagonal *)Y->data; 447345a4b08SToby Isaac 448345a4b08SToby Isaac PetscFunctionBegin; 449345a4b08SToby Isaac PetscCall(MatDiagonalSetUpDiagonal(Y)); 450345a4b08SToby Isaac if (l) { 451345a4b08SToby Isaac PetscCall(VecPointwiseMult(ctx->diag, ctx->diag, l)); 452345a4b08SToby Isaac ctx->inv_diag_valid = PETSC_FALSE; 453345a4b08SToby Isaac } 454345a4b08SToby Isaac if (r) { 455345a4b08SToby Isaac PetscCall(VecPointwiseMult(ctx->diag, ctx->diag, r)); 456345a4b08SToby Isaac ctx->inv_diag_valid = PETSC_FALSE; 457345a4b08SToby Isaac } 458345a4b08SToby Isaac PetscFunctionReturn(PETSC_SUCCESS); 459345a4b08SToby Isaac } 460345a4b08SToby Isaac 4618a1df862SToby Isaac static PetscErrorCode MatConjugate_Diagonal(Mat Y) 4628a1df862SToby Isaac { 4638a1df862SToby Isaac PetscFunctionBegin; 4648a1df862SToby Isaac Mat_Diagonal *ctx = (Mat_Diagonal *)Y->data; 4658a1df862SToby Isaac 4668a1df862SToby Isaac if (ctx->diag_valid) { 4678a1df862SToby Isaac PetscCall(VecConjugate(ctx->diag)); 4688a1df862SToby Isaac PetscCall(PetscObjectStateGet((PetscObject)ctx->diag, &ctx->diag_state)); 4698a1df862SToby Isaac } 4708a1df862SToby Isaac if (ctx->inv_diag_valid) { 4718a1df862SToby Isaac PetscCall(VecConjugate(ctx->inv_diag)); 4728a1df862SToby Isaac PetscCall(PetscObjectStateGet((PetscObject)ctx->inv_diag, &ctx->inv_diag_state)); 4738a1df862SToby Isaac } 4748a1df862SToby Isaac PetscFunctionReturn(PETSC_SUCCESS); 4758a1df862SToby Isaac } 4768a1df862SToby Isaac 4778a1df862SToby Isaac static PetscErrorCode MatTranspose_Diagonal(Mat A, MatReuse reuse, Mat *matout) 4788a1df862SToby Isaac { 4798a1df862SToby Isaac PetscFunctionBegin; 4808a1df862SToby Isaac if (reuse == MAT_INPLACE_MATRIX) { 4818a1df862SToby Isaac PetscLayout tmplayout = A->rmap; 4828a1df862SToby Isaac 4838a1df862SToby Isaac A->rmap = A->cmap; 4848a1df862SToby Isaac A->cmap = tmplayout; 4858a1df862SToby Isaac } else { 4868a1df862SToby Isaac Vec diag, newdiag; 4878a1df862SToby Isaac if (reuse == MAT_INITIAL_MATRIX) { 4888a1df862SToby Isaac PetscCall(MatDiagonalGetDiagonal(A, &diag)); 4898a1df862SToby Isaac PetscCall(VecDuplicate(diag, &newdiag)); 4908a1df862SToby Isaac PetscCall(VecCopy(diag, newdiag)); 4918a1df862SToby Isaac PetscCall(MatDiagonalRestoreDiagonal(A, &diag)); 4928a1df862SToby Isaac PetscCall(MatCreateDiagonal(newdiag, matout)); 4938a1df862SToby Isaac PetscCall(VecDestroy(&newdiag)); 4948a1df862SToby Isaac } else { 4958a1df862SToby Isaac PetscCall(MatDiagonalGetDiagonal(A, &diag)); 4968a1df862SToby Isaac PetscCall(MatDiagonalGetDiagonal(*matout, &newdiag)); 4978a1df862SToby Isaac PetscCall(VecCopy(diag, newdiag)); 4988a1df862SToby Isaac PetscCall(MatDiagonalRestoreDiagonal(*matout, &newdiag)); 4998a1df862SToby Isaac PetscCall(MatDiagonalRestoreDiagonal(A, &diag)); 5008a1df862SToby Isaac } 5018a1df862SToby Isaac } 5028a1df862SToby Isaac PetscFunctionReturn(PETSC_SUCCESS); 5038a1df862SToby Isaac } 5048a1df862SToby Isaac 505345a4b08SToby Isaac static PetscErrorCode MatSetUp_Diagonal(Mat A) 506345a4b08SToby Isaac { 507345a4b08SToby Isaac Mat_Diagonal *ctx = (Mat_Diagonal *)A->data; 508345a4b08SToby Isaac 509345a4b08SToby Isaac PetscFunctionBegin; 510345a4b08SToby Isaac if (!ctx->diag) { 511345a4b08SToby Isaac PetscCall(PetscLayoutSetUp(A->cmap)); 512345a4b08SToby Isaac PetscCall(PetscLayoutSetUp(A->rmap)); 513345a4b08SToby Isaac PetscCall(MatCreateVecs(A, &ctx->diag, NULL)); 514345a4b08SToby Isaac PetscCall(VecDuplicate(ctx->diag, &ctx->inv_diag)); 515345a4b08SToby Isaac PetscCall(VecZeroEntries(ctx->diag)); 516345a4b08SToby Isaac ctx->diag_valid = PETSC_TRUE; 517345a4b08SToby Isaac } 518345a4b08SToby Isaac A->assembled = PETSC_TRUE; 519345a4b08SToby Isaac PetscFunctionReturn(PETSC_SUCCESS); 520345a4b08SToby Isaac } 521345a4b08SToby Isaac 522345a4b08SToby Isaac static PetscErrorCode MatZeroEntries_Diagonal(Mat Y) 523345a4b08SToby Isaac { 524345a4b08SToby Isaac Mat_Diagonal *ctx = (Mat_Diagonal *)Y->data; 525345a4b08SToby Isaac 526345a4b08SToby Isaac PetscFunctionBegin; 527345a4b08SToby Isaac PetscCall(MatSetUp(Y)); 528345a4b08SToby Isaac PetscCall(VecZeroEntries(ctx->diag)); 529345a4b08SToby Isaac ctx->diag_valid = PETSC_TRUE; 530345a4b08SToby Isaac ctx->inv_diag_valid = PETSC_FALSE; 531345a4b08SToby Isaac PetscFunctionReturn(PETSC_SUCCESS); 532345a4b08SToby Isaac } 533345a4b08SToby Isaac 53466976f2fSJacob Faibussowitsch static PetscErrorCode MatSolve_Diagonal(Mat matin, Vec b, Vec x) 535345a4b08SToby Isaac { 536345a4b08SToby Isaac Mat_Diagonal *ctx = (Mat_Diagonal *)matin->data; 537345a4b08SToby Isaac 538345a4b08SToby Isaac PetscFunctionBegin; 539345a4b08SToby Isaac PetscCall(MatDiagonalSetUpInverseDiagonal(matin)); 540345a4b08SToby Isaac PetscCall(VecPointwiseMult(x, b, ctx->inv_diag)); 541345a4b08SToby Isaac PetscFunctionReturn(PETSC_SUCCESS); 542345a4b08SToby Isaac } 543345a4b08SToby Isaac 54466976f2fSJacob Faibussowitsch static PetscErrorCode MatGetInfo_Diagonal(Mat A, MatInfoType flag, MatInfo *info) 545345a4b08SToby Isaac { 546345a4b08SToby Isaac PetscFunctionBegin; 547345a4b08SToby Isaac info->block_size = 1.0; 548345a4b08SToby Isaac info->nz_allocated = A->cmap->N; 549345a4b08SToby Isaac info->nz_used = A->cmap->N; 550345a4b08SToby Isaac info->nz_unneeded = 0.0; 551345a4b08SToby Isaac info->assemblies = A->num_ass; 552345a4b08SToby Isaac info->mallocs = 0.0; 553345a4b08SToby Isaac info->memory = 0; 554345a4b08SToby Isaac info->fill_ratio_given = 0; 555345a4b08SToby Isaac info->fill_ratio_needed = 0; 556345a4b08SToby Isaac info->factor_mallocs = 0; 557345a4b08SToby Isaac PetscFunctionReturn(PETSC_SUCCESS); 558345a4b08SToby Isaac } 559345a4b08SToby Isaac 560345a4b08SToby Isaac /*@ 561345a4b08SToby Isaac MatCreateDiagonal - Creates a matrix defined by a given vector along its diagonal. 562345a4b08SToby Isaac 563345a4b08SToby Isaac Collective 564345a4b08SToby Isaac 565345a4b08SToby Isaac Input Parameter: 566345a4b08SToby Isaac . diag - vector for the diagonal 567345a4b08SToby Isaac 568345a4b08SToby Isaac Output Parameter: 569345a4b08SToby Isaac . J - the diagonal matrix 570345a4b08SToby Isaac 571345a4b08SToby Isaac Level: advanced 572345a4b08SToby Isaac 573345a4b08SToby Isaac Notes: 574345a4b08SToby Isaac Only supports square matrices with the same number of local rows and columns. 575345a4b08SToby Isaac 576345a4b08SToby Isaac The input vector `diag` will be referenced internally: any changes to `diag` 577345a4b08SToby Isaac will affect the matrix `J`. 578345a4b08SToby Isaac 579be50c303SSatish Balay .seealso: [](ch_matrices), `Mat`, `MatDestroy()`, `MATCONSTANTDIAGONAL`, `MatScale()`, `MatShift()`, `MatMult()`, `MatGetDiagonal()`, `MatSolve()` 580345a4b08SToby Isaac `MatDiagonalRestoreInverseDiagonal()`, `MatDiagonalGetDiagonal()`, `MatDiagonalRestoreDiagonal()`, `MatDiagonalGetInverseDiagonal()` 581345a4b08SToby Isaac @*/ 582345a4b08SToby Isaac PetscErrorCode MatCreateDiagonal(Vec diag, Mat *J) 583345a4b08SToby Isaac { 584345a4b08SToby Isaac PetscFunctionBegin; 585345a4b08SToby Isaac PetscValidHeaderSpecific(diag, VEC_CLASSID, 1); 586345a4b08SToby Isaac PetscCall(MatCreate(PetscObjectComm((PetscObject)diag), J)); 587345a4b08SToby Isaac PetscInt m, M; 588345a4b08SToby Isaac PetscCall(VecGetLocalSize(diag, &m)); 589345a4b08SToby Isaac PetscCall(VecGetSize(diag, &M)); 590345a4b08SToby Isaac PetscCall(MatSetSizes(*J, m, m, M, M)); 591345a4b08SToby Isaac PetscCall(MatSetType(*J, MATDIAGONAL)); 592345a4b08SToby Isaac 593345a4b08SToby Isaac PetscLayout map; 594345a4b08SToby Isaac PetscCall(VecGetLayout(diag, &map)); 595345a4b08SToby Isaac PetscCall(MatSetLayouts(*J, map, map)); 596345a4b08SToby Isaac Mat_Diagonal *ctx = (Mat_Diagonal *)(*J)->data; 597345a4b08SToby Isaac PetscCall(PetscObjectReference((PetscObject)diag)); 598345a4b08SToby Isaac PetscCall(VecDestroy(&ctx->diag)); 599345a4b08SToby Isaac PetscCall(VecDestroy(&ctx->inv_diag)); 600345a4b08SToby Isaac ctx->diag = diag; 601345a4b08SToby Isaac ctx->diag_valid = PETSC_TRUE; 602345a4b08SToby Isaac ctx->inv_diag_valid = PETSC_FALSE; 603345a4b08SToby Isaac VecType type; 604345a4b08SToby Isaac PetscCall(VecDuplicate(ctx->diag, &ctx->inv_diag)); 605345a4b08SToby Isaac PetscCall(VecGetType(diag, &type)); 606345a4b08SToby Isaac PetscCall(PetscFree((*J)->defaultvectype)); 607345a4b08SToby Isaac PetscCall(PetscStrallocpy(type, &(*J)->defaultvectype)); 608345a4b08SToby Isaac PetscCall(MatSetUp(*J)); 609c3e1b152SPierre Jolivet ctx->col = NULL; 610c3e1b152SPierre Jolivet ctx->val = NULL; 611345a4b08SToby Isaac PetscFunctionReturn(PETSC_SUCCESS); 612345a4b08SToby Isaac } 613345a4b08SToby Isaac 614e27ab85cSPierre Jolivet static PetscErrorCode MatProductNumeric_Diagonal_Dense(Mat C) 615e27ab85cSPierre Jolivet { 616e27ab85cSPierre Jolivet Mat A, B; 617e27ab85cSPierre Jolivet Mat_Diagonal *a; 618e27ab85cSPierre Jolivet PetscScalar *c; 619e27ab85cSPierre Jolivet const PetscScalar *b, *alpha; 620e27ab85cSPierre Jolivet PetscInt ldb, ldc; 621e27ab85cSPierre Jolivet 622e27ab85cSPierre Jolivet PetscFunctionBegin; 623e27ab85cSPierre Jolivet MatCheckProduct(C, 1); 624e27ab85cSPierre Jolivet A = C->product->A; 625e27ab85cSPierre Jolivet B = C->product->B; 626e27ab85cSPierre Jolivet a = (Mat_Diagonal *)A->data; 627e27ab85cSPierre Jolivet PetscCall(VecGetArrayRead(a->diag, &alpha)); 628e27ab85cSPierre Jolivet PetscCall(MatDenseGetLDA(B, &ldb)); 629e27ab85cSPierre Jolivet PetscCall(MatDenseGetLDA(C, &ldc)); 630e27ab85cSPierre Jolivet PetscCall(MatDenseGetArrayRead(B, &b)); 631e27ab85cSPierre Jolivet PetscCall(MatDenseGetArrayWrite(C, &c)); 632e27ab85cSPierre Jolivet for (PetscInt j = 0; j < B->cmap->N; j++) 633e27ab85cSPierre Jolivet for (PetscInt i = 0; i < B->rmap->n; i++) c[i + j * ldc] = alpha[i] * b[i + j * ldb]; 634e27ab85cSPierre Jolivet PetscCall(MatDenseRestoreArrayWrite(C, &c)); 635e27ab85cSPierre Jolivet PetscCall(MatDenseRestoreArrayRead(B, &b)); 636e27ab85cSPierre Jolivet PetscCall(VecRestoreArrayRead(a->diag, &alpha)); 637e27ab85cSPierre Jolivet PetscCall(PetscLogFlops(B->cmap->N * B->rmap->n)); 638e27ab85cSPierre Jolivet PetscFunctionReturn(PETSC_SUCCESS); 639e27ab85cSPierre Jolivet } 640e27ab85cSPierre Jolivet 641e27ab85cSPierre Jolivet static PetscErrorCode MatProductSymbolic_Diagonal_Dense(Mat C) 642e27ab85cSPierre Jolivet { 643e27ab85cSPierre Jolivet Mat A, B; 644e27ab85cSPierre Jolivet PetscInt n, N, m, M; 645e27ab85cSPierre Jolivet 646e27ab85cSPierre Jolivet PetscFunctionBegin; 647e27ab85cSPierre Jolivet MatCheckProduct(C, 1); 648e27ab85cSPierre Jolivet PetscCheck(!C->product->data, PetscObjectComm((PetscObject)C), PETSC_ERR_PLIB, "Product data not empty"); 649e27ab85cSPierre Jolivet A = C->product->A; 650e27ab85cSPierre Jolivet B = C->product->B; 651e27ab85cSPierre Jolivet PetscCall(MatDiagonalSetUpDiagonal(A)); 652e27ab85cSPierre Jolivet PetscCall(MatGetLocalSize(C, &m, &n)); 653e27ab85cSPierre Jolivet PetscCall(MatGetSize(C, &M, &N)); 654e27ab85cSPierre Jolivet if (m == PETSC_DECIDE || n == PETSC_DECIDE || M == PETSC_DECIDE || N == PETSC_DECIDE) { 655e27ab85cSPierre Jolivet PetscCall(MatGetLocalSize(B, NULL, &n)); 656e27ab85cSPierre Jolivet PetscCall(MatGetSize(B, NULL, &N)); 657e27ab85cSPierre Jolivet PetscCall(MatGetLocalSize(A, &m, NULL)); 658e27ab85cSPierre Jolivet PetscCall(MatGetSize(A, &M, NULL)); 659e27ab85cSPierre Jolivet PetscCall(MatSetSizes(C, m, n, M, N)); 660e27ab85cSPierre Jolivet } 661e27ab85cSPierre Jolivet PetscCall(MatSetType(C, ((PetscObject)B)->type_name)); 662e27ab85cSPierre Jolivet PetscCall(MatSetUp(C)); 663e27ab85cSPierre Jolivet C->ops->productnumeric = MatProductNumeric_Diagonal_Dense; 664e27ab85cSPierre Jolivet PetscFunctionReturn(PETSC_SUCCESS); 665e27ab85cSPierre Jolivet } 666e27ab85cSPierre Jolivet 667e27ab85cSPierre Jolivet static PetscErrorCode MatProductSetFromOptions_Diagonal_Dense_AB(Mat C) 668e27ab85cSPierre Jolivet { 669e27ab85cSPierre Jolivet PetscFunctionBegin; 670e27ab85cSPierre Jolivet C->ops->productsymbolic = MatProductSymbolic_Diagonal_Dense; 671e27ab85cSPierre Jolivet PetscFunctionReturn(PETSC_SUCCESS); 672e27ab85cSPierre Jolivet } 673e27ab85cSPierre Jolivet 674e27ab85cSPierre Jolivet static PetscErrorCode MatProductSetFromOptions_Diagonal_Dense(Mat C) 675e27ab85cSPierre Jolivet { 676e27ab85cSPierre Jolivet Mat_Product *product = C->product; 677e27ab85cSPierre Jolivet 678e27ab85cSPierre Jolivet PetscFunctionBegin; 679e27ab85cSPierre Jolivet if (product->type == MATPRODUCT_AB || product->type == MATPRODUCT_AtB) PetscCall(MatProductSetFromOptions_Diagonal_Dense_AB(C)); 680e27ab85cSPierre Jolivet PetscFunctionReturn(PETSC_SUCCESS); 681e27ab85cSPierre Jolivet } 682e27ab85cSPierre Jolivet 683345a4b08SToby Isaac /*MC 684345a4b08SToby Isaac MATDIAGONAL - MATDIAGONAL = "diagonal" - A diagonal matrix type with the diagonal implemented as a `Vec`. Useful for 685345a4b08SToby Isaac cases where `VecPointwiseMult()` or `VecPointwiseDivide()` should be thought of as the actions of a linear operator. 686345a4b08SToby Isaac 687345a4b08SToby Isaac Level: advanced 688345a4b08SToby Isaac 689be50c303SSatish Balay .seealso: [](ch_matrices), `Mat`, `MatCreateDiagonal()`, `MatDiagonalRestoreInverseDiagonal()`, `MatDiagonalGetDiagonal()`, `MatDiagonalRestoreDiagonal()`, `MatDiagonalGetInverseDiagonal()` 690345a4b08SToby Isaac M*/ 691345a4b08SToby Isaac PETSC_INTERN PetscErrorCode MatCreate_Diagonal(Mat A) 692345a4b08SToby Isaac { 693345a4b08SToby Isaac Mat_Diagonal *ctx; 694345a4b08SToby Isaac 695345a4b08SToby Isaac PetscFunctionBegin; 696345a4b08SToby Isaac PetscCall(PetscNew(&ctx)); 697345a4b08SToby Isaac A->data = (void *)ctx; 698345a4b08SToby Isaac 699345a4b08SToby Isaac A->structurally_symmetric = PETSC_BOOL3_TRUE; 700345a4b08SToby Isaac A->structural_symmetry_eternal = PETSC_TRUE; 701345a4b08SToby Isaac A->symmetry_eternal = PETSC_TRUE; 702345a4b08SToby Isaac A->symmetric = PETSC_BOOL3_TRUE; 703345a4b08SToby Isaac if (!PetscDefined(USE_COMPLEX)) A->hermitian = PETSC_BOOL3_TRUE; 704345a4b08SToby Isaac 705c3e1b152SPierre Jolivet A->ops->getrow = MatGetRow_Diagonal; 706345a4b08SToby Isaac A->ops->mult = MatMult_Diagonal; 707345a4b08SToby Isaac A->ops->multadd = MatMultAdd_Diagonal; 708345a4b08SToby Isaac A->ops->multtranspose = MatMult_Diagonal; 709345a4b08SToby Isaac A->ops->multtransposeadd = MatMultAdd_Diagonal; 710345a4b08SToby Isaac A->ops->norm = MatNorm_Diagonal; 711345a4b08SToby Isaac A->ops->duplicate = MatDuplicate_Diagonal; 712345a4b08SToby Isaac A->ops->solve = MatSolve_Diagonal; 713345a4b08SToby Isaac A->ops->solvetranspose = MatSolve_Diagonal; 714345a4b08SToby Isaac A->ops->shift = MatShift_Diagonal; 715345a4b08SToby Isaac A->ops->scale = MatScale_Diagonal; 716345a4b08SToby Isaac A->ops->diagonalscale = MatDiagonalScale_Diagonal; 717345a4b08SToby Isaac A->ops->getdiagonal = MatGetDiagonal_Diagonal; 718345a4b08SToby Isaac A->ops->diagonalset = MatDiagonalSet_Diagonal; 719345a4b08SToby Isaac A->ops->view = MatView_Diagonal; 720345a4b08SToby Isaac A->ops->zeroentries = MatZeroEntries_Diagonal; 721345a4b08SToby Isaac A->ops->destroy = MatDestroy_Diagonal; 722345a4b08SToby Isaac A->ops->getinfo = MatGetInfo_Diagonal; 723345a4b08SToby Isaac A->ops->axpy = MatAXPY_Diagonal; 724345a4b08SToby Isaac A->ops->setup = MatSetUp_Diagonal; 725ee8a0a41SPierre Jolivet A->ops->permute = MatPermute_Diagonal; 7268a1df862SToby Isaac A->ops->setrandom = MatSetRandom_Diagonal; 7278a1df862SToby Isaac A->ops->conjugate = MatConjugate_Diagonal; 7288a1df862SToby Isaac A->ops->transpose = MatTranspose_Diagonal; 729345a4b08SToby Isaac 730345a4b08SToby Isaac PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatDiagonalGetDiagonal_C", MatDiagonalGetDiagonal_Diagonal)); 731345a4b08SToby Isaac PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatDiagonalRestoreDiagonal_C", MatDiagonalRestoreDiagonal_Diagonal)); 732345a4b08SToby Isaac PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatDiagonalGetInverseDiagonal_C", MatDiagonalGetInverseDiagonal_Diagonal)); 733345a4b08SToby Isaac PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatDiagonalRestoreInverseDiagonal_C", MatDiagonalRestoreInverseDiagonal_Diagonal)); 734e27ab85cSPierre Jolivet PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatProductSetFromOptions_diagonal_seqdense_C", MatProductSetFromOptions_Diagonal_Dense)); 735e27ab85cSPierre Jolivet PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatProductSetFromOptions_diagonal_mpidense_C", MatProductSetFromOptions_Diagonal_Dense)); 736345a4b08SToby Isaac PetscCall(PetscObjectChangeTypeName((PetscObject)A, MATDIAGONAL)); 737345a4b08SToby Isaac PetscFunctionReturn(PETSC_SUCCESS); 738345a4b08SToby Isaac } 739