xref: /petsc/src/mat/impls/diagonal/diagonal.c (revision 8bb6a241cc2b8f6ed3ced698b43bc00095eff8a0)
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 
MatDiagonalSetUpDiagonal(Mat A)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 
MatDiagonalSetUpInverseDiagonal(Mat A)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 
MatAXPY_Diagonal(Mat Y,PetscScalar a,Mat X,MatStructure str)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 
MatGetRow_Diagonal(Mat A,PetscInt row,PetscInt * ncols,PetscInt ** cols,PetscScalar ** vals)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 
MatMult_Diagonal(Mat A,Vec x,Vec y)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 
MatMultAdd_Diagonal(Mat mat,Vec v1,Vec v2,Vec v3)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 
MatNorm_Diagonal(Mat A,NormType type,PetscReal * nrm)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 
MatDuplicate_Diagonal(Mat A,MatDuplicateOption op,Mat * B)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 @*/
MatDiagonalGetDiagonal(Mat A,Vec * diag)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 
MatDiagonalGetDiagonal_Diagonal(Mat A,Vec * diag)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 @*/
MatDiagonalRestoreDiagonal(Mat A,Vec * diag)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 
MatDiagonalRestoreDiagonal_Diagonal(Mat A,Vec * diag)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 @*/
MatDiagonalGetInverseDiagonal(Mat A,Vec * inv_diag)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 
MatDiagonalGetInverseDiagonal_Diagonal(Mat A,Vec * inv_diag)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 @*/
MatDiagonalRestoreInverseDiagonal(Mat A,Vec * inv_diag)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 
MatDiagonalRestoreInverseDiagonal_Diagonal(Mat A,Vec * inv_diag)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 
MatPermute_Diagonal(Mat A,IS rowp,IS colp,Mat * B)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 
MatSetRandom_Diagonal(Mat A,PetscRandom rand)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 
MatDestroy_Diagonal(Mat mat)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   PetscFunctionReturn(PETSC_SUCCESS);
349345a4b08SToby Isaac }
350345a4b08SToby Isaac 
MatView_Diagonal(Mat J,PetscViewer viewer)351345a4b08SToby Isaac static PetscErrorCode MatView_Diagonal(Mat J, PetscViewer viewer)
352345a4b08SToby Isaac {
353345a4b08SToby Isaac   Mat_Diagonal *ctx = (Mat_Diagonal *)J->data;
3549f196a02SMartin Diehl   PetscBool     isascii;
355345a4b08SToby Isaac 
356345a4b08SToby Isaac   PetscFunctionBegin;
3579f196a02SMartin Diehl   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii));
3589f196a02SMartin Diehl   if (isascii) {
359345a4b08SToby Isaac     PetscViewerFormat format;
360345a4b08SToby Isaac 
361345a4b08SToby Isaac     PetscCall(MatDiagonalSetUpDiagonal(J));
3628a1df862SToby Isaac     PetscCall(PetscViewerGetFormat(viewer, &format));
3638a1df862SToby Isaac     if (format == PETSC_VIEWER_ASCII_FACTOR_INFO || format == PETSC_VIEWER_ASCII_INFO) {
3648a1df862SToby Isaac       PetscCall(PetscObjectPrintClassNamePrefixType((PetscObject)ctx->diag, viewer));
3658a1df862SToby Isaac       PetscFunctionReturn(PETSC_SUCCESS);
3668a1df862SToby Isaac     }
367345a4b08SToby Isaac     PetscCall(VecView(ctx->diag, viewer));
368345a4b08SToby Isaac   }
369345a4b08SToby Isaac   PetscFunctionReturn(PETSC_SUCCESS);
370345a4b08SToby Isaac }
371345a4b08SToby Isaac 
MatGetDiagonal_Diagonal(Mat J,Vec x)372345a4b08SToby Isaac static PetscErrorCode MatGetDiagonal_Diagonal(Mat J, Vec x)
373345a4b08SToby Isaac {
374345a4b08SToby Isaac   Mat_Diagonal *ctx = (Mat_Diagonal *)J->data;
375345a4b08SToby Isaac 
376345a4b08SToby Isaac   PetscFunctionBegin;
377345a4b08SToby Isaac   PetscCall(MatDiagonalSetUpDiagonal(J));
378345a4b08SToby Isaac   PetscCall(VecCopy(ctx->diag, x));
379345a4b08SToby Isaac   PetscFunctionReturn(PETSC_SUCCESS);
380345a4b08SToby Isaac }
381345a4b08SToby Isaac 
MatDiagonalSet_Diagonal(Mat J,Vec D,InsertMode is)382345a4b08SToby Isaac static PetscErrorCode MatDiagonalSet_Diagonal(Mat J, Vec D, InsertMode is)
383345a4b08SToby Isaac {
384345a4b08SToby Isaac   Mat_Diagonal *ctx = (Mat_Diagonal *)J->data;
385345a4b08SToby Isaac 
386345a4b08SToby Isaac   PetscFunctionBegin;
387345a4b08SToby Isaac   switch (is) {
388345a4b08SToby Isaac   case ADD_VALUES:
389345a4b08SToby Isaac   case ADD_ALL_VALUES:
390345a4b08SToby Isaac   case ADD_BC_VALUES:
391345a4b08SToby Isaac     PetscCall(MatDiagonalSetUpDiagonal(J));
392345a4b08SToby Isaac     PetscCall(VecAXPY(ctx->diag, 1.0, D));
393345a4b08SToby Isaac     ctx->inv_diag_valid = PETSC_FALSE;
394345a4b08SToby Isaac     break;
395345a4b08SToby Isaac   case INSERT_VALUES:
396345a4b08SToby Isaac   case INSERT_BC_VALUES:
397345a4b08SToby Isaac   case INSERT_ALL_VALUES:
398345a4b08SToby Isaac     PetscCall(MatSetUp(J));
399345a4b08SToby Isaac     PetscCall(VecCopy(D, ctx->diag));
400345a4b08SToby Isaac     ctx->diag_valid     = PETSC_TRUE;
401345a4b08SToby Isaac     ctx->inv_diag_valid = PETSC_FALSE;
402345a4b08SToby Isaac     break;
403345a4b08SToby Isaac   case MAX_VALUES:
404345a4b08SToby Isaac     PetscCall(MatDiagonalSetUpDiagonal(J));
405345a4b08SToby Isaac     PetscCall(VecPointwiseMax(ctx->diag, D, ctx->diag));
406345a4b08SToby Isaac     ctx->inv_diag_valid = PETSC_FALSE;
407345a4b08SToby Isaac     break;
408345a4b08SToby Isaac   case MIN_VALUES:
409345a4b08SToby Isaac     PetscCall(MatDiagonalSetUpDiagonal(J));
410345a4b08SToby Isaac     PetscCall(VecPointwiseMin(ctx->diag, D, ctx->diag));
411345a4b08SToby Isaac     ctx->inv_diag_valid = PETSC_FALSE;
412345a4b08SToby Isaac     break;
413345a4b08SToby Isaac   case NOT_SET_VALUES:
414345a4b08SToby Isaac     break;
415345a4b08SToby Isaac   }
416345a4b08SToby Isaac   PetscFunctionReturn(PETSC_SUCCESS);
417345a4b08SToby Isaac }
418345a4b08SToby Isaac 
MatShift_Diagonal(Mat Y,PetscScalar a)419345a4b08SToby Isaac static PetscErrorCode MatShift_Diagonal(Mat Y, PetscScalar a)
420345a4b08SToby Isaac {
421345a4b08SToby Isaac   Mat_Diagonal *ctx = (Mat_Diagonal *)Y->data;
422345a4b08SToby Isaac 
423345a4b08SToby Isaac   PetscFunctionBegin;
424345a4b08SToby Isaac   PetscCall(MatDiagonalSetUpDiagonal(Y));
425345a4b08SToby Isaac   PetscCall(VecShift(ctx->diag, a));
426345a4b08SToby Isaac   ctx->inv_diag_valid = PETSC_FALSE;
427345a4b08SToby Isaac   PetscFunctionReturn(PETSC_SUCCESS);
428345a4b08SToby Isaac }
429345a4b08SToby Isaac 
MatScale_Diagonal(Mat Y,PetscScalar a)430345a4b08SToby Isaac static PetscErrorCode MatScale_Diagonal(Mat Y, PetscScalar a)
431345a4b08SToby Isaac {
432345a4b08SToby Isaac   Mat_Diagonal *ctx = (Mat_Diagonal *)Y->data;
433345a4b08SToby Isaac 
434345a4b08SToby Isaac   PetscFunctionBegin;
435345a4b08SToby Isaac   PetscCall(MatSetUp(Y));
436345a4b08SToby Isaac   PetscCall(MatDiagonalSetUpDiagonal(Y));
437345a4b08SToby Isaac   PetscCall(VecScale(ctx->diag, a));
438345a4b08SToby Isaac   ctx->inv_diag_valid = PETSC_FALSE;
439345a4b08SToby Isaac   PetscFunctionReturn(PETSC_SUCCESS);
440345a4b08SToby Isaac }
441345a4b08SToby Isaac 
MatDiagonalScale_Diagonal(Mat Y,Vec l,Vec r)442345a4b08SToby Isaac static PetscErrorCode MatDiagonalScale_Diagonal(Mat Y, Vec l, Vec r)
443345a4b08SToby Isaac {
444345a4b08SToby Isaac   Mat_Diagonal *ctx = (Mat_Diagonal *)Y->data;
445345a4b08SToby Isaac 
446345a4b08SToby Isaac   PetscFunctionBegin;
447345a4b08SToby Isaac   PetscCall(MatDiagonalSetUpDiagonal(Y));
448345a4b08SToby Isaac   if (l) {
449345a4b08SToby Isaac     PetscCall(VecPointwiseMult(ctx->diag, ctx->diag, l));
450345a4b08SToby Isaac     ctx->inv_diag_valid = PETSC_FALSE;
451345a4b08SToby Isaac   }
452345a4b08SToby Isaac   if (r) {
453345a4b08SToby Isaac     PetscCall(VecPointwiseMult(ctx->diag, ctx->diag, r));
454345a4b08SToby Isaac     ctx->inv_diag_valid = PETSC_FALSE;
455345a4b08SToby Isaac   }
456345a4b08SToby Isaac   PetscFunctionReturn(PETSC_SUCCESS);
457345a4b08SToby Isaac }
458345a4b08SToby Isaac 
MatConjugate_Diagonal(Mat Y)4598a1df862SToby Isaac static PetscErrorCode MatConjugate_Diagonal(Mat Y)
4608a1df862SToby Isaac {
4618a1df862SToby Isaac   PetscFunctionBegin;
4628a1df862SToby Isaac   Mat_Diagonal *ctx = (Mat_Diagonal *)Y->data;
4638a1df862SToby Isaac 
4648a1df862SToby Isaac   if (ctx->diag_valid) {
4658a1df862SToby Isaac     PetscCall(VecConjugate(ctx->diag));
4668a1df862SToby Isaac     PetscCall(PetscObjectStateGet((PetscObject)ctx->diag, &ctx->diag_state));
4678a1df862SToby Isaac   }
4688a1df862SToby Isaac   if (ctx->inv_diag_valid) {
4698a1df862SToby Isaac     PetscCall(VecConjugate(ctx->inv_diag));
4708a1df862SToby Isaac     PetscCall(PetscObjectStateGet((PetscObject)ctx->inv_diag, &ctx->inv_diag_state));
4718a1df862SToby Isaac   }
4728a1df862SToby Isaac   PetscFunctionReturn(PETSC_SUCCESS);
4738a1df862SToby Isaac }
4748a1df862SToby Isaac 
MatTranspose_Diagonal(Mat A,MatReuse reuse,Mat * matout)4758a1df862SToby Isaac static PetscErrorCode MatTranspose_Diagonal(Mat A, MatReuse reuse, Mat *matout)
4768a1df862SToby Isaac {
4778a1df862SToby Isaac   PetscFunctionBegin;
4788a1df862SToby Isaac   if (reuse == MAT_INPLACE_MATRIX) {
4798a1df862SToby Isaac     PetscLayout tmplayout = A->rmap;
4808a1df862SToby Isaac 
4818a1df862SToby Isaac     A->rmap = A->cmap;
4828a1df862SToby Isaac     A->cmap = tmplayout;
4838a1df862SToby Isaac   } else {
4848a1df862SToby Isaac     Vec diag, newdiag;
4858a1df862SToby Isaac     if (reuse == MAT_INITIAL_MATRIX) {
4868a1df862SToby Isaac       PetscCall(MatDiagonalGetDiagonal(A, &diag));
4878a1df862SToby Isaac       PetscCall(VecDuplicate(diag, &newdiag));
4888a1df862SToby Isaac       PetscCall(VecCopy(diag, newdiag));
4898a1df862SToby Isaac       PetscCall(MatDiagonalRestoreDiagonal(A, &diag));
4908a1df862SToby Isaac       PetscCall(MatCreateDiagonal(newdiag, matout));
4918a1df862SToby Isaac       PetscCall(VecDestroy(&newdiag));
4928a1df862SToby Isaac     } else {
4938a1df862SToby Isaac       PetscCall(MatDiagonalGetDiagonal(A, &diag));
4948a1df862SToby Isaac       PetscCall(MatDiagonalGetDiagonal(*matout, &newdiag));
4958a1df862SToby Isaac       PetscCall(VecCopy(diag, newdiag));
4968a1df862SToby Isaac       PetscCall(MatDiagonalRestoreDiagonal(*matout, &newdiag));
4978a1df862SToby Isaac       PetscCall(MatDiagonalRestoreDiagonal(A, &diag));
4988a1df862SToby Isaac     }
4998a1df862SToby Isaac   }
5008a1df862SToby Isaac   PetscFunctionReturn(PETSC_SUCCESS);
5018a1df862SToby Isaac }
5028a1df862SToby Isaac 
MatSetUp_Diagonal(Mat A)503345a4b08SToby Isaac static PetscErrorCode MatSetUp_Diagonal(Mat A)
504345a4b08SToby Isaac {
505345a4b08SToby Isaac   Mat_Diagonal *ctx = (Mat_Diagonal *)A->data;
506345a4b08SToby Isaac 
507345a4b08SToby Isaac   PetscFunctionBegin;
508345a4b08SToby Isaac   if (!ctx->diag) {
509345a4b08SToby Isaac     PetscCall(PetscLayoutSetUp(A->cmap));
510345a4b08SToby Isaac     PetscCall(PetscLayoutSetUp(A->rmap));
511345a4b08SToby Isaac     PetscCall(MatCreateVecs(A, &ctx->diag, NULL));
512345a4b08SToby Isaac     PetscCall(VecDuplicate(ctx->diag, &ctx->inv_diag));
513345a4b08SToby Isaac     PetscCall(VecZeroEntries(ctx->diag));
514345a4b08SToby Isaac     ctx->diag_valid = PETSC_TRUE;
515345a4b08SToby Isaac   }
516345a4b08SToby Isaac   A->assembled = PETSC_TRUE;
517345a4b08SToby Isaac   PetscFunctionReturn(PETSC_SUCCESS);
518345a4b08SToby Isaac }
519345a4b08SToby Isaac 
MatZeroEntries_Diagonal(Mat Y)520345a4b08SToby Isaac static PetscErrorCode MatZeroEntries_Diagonal(Mat Y)
521345a4b08SToby Isaac {
522345a4b08SToby Isaac   Mat_Diagonal *ctx = (Mat_Diagonal *)Y->data;
523345a4b08SToby Isaac 
524345a4b08SToby Isaac   PetscFunctionBegin;
525345a4b08SToby Isaac   PetscCall(MatSetUp(Y));
526345a4b08SToby Isaac   PetscCall(VecZeroEntries(ctx->diag));
527345a4b08SToby Isaac   ctx->diag_valid     = PETSC_TRUE;
528345a4b08SToby Isaac   ctx->inv_diag_valid = PETSC_FALSE;
529345a4b08SToby Isaac   PetscFunctionReturn(PETSC_SUCCESS);
530345a4b08SToby Isaac }
531345a4b08SToby Isaac 
MatSolve_Diagonal(Mat matin,Vec b,Vec x)53266976f2fSJacob Faibussowitsch static PetscErrorCode MatSolve_Diagonal(Mat matin, Vec b, Vec x)
533345a4b08SToby Isaac {
534345a4b08SToby Isaac   Mat_Diagonal *ctx = (Mat_Diagonal *)matin->data;
535345a4b08SToby Isaac 
536345a4b08SToby Isaac   PetscFunctionBegin;
537345a4b08SToby Isaac   PetscCall(MatDiagonalSetUpInverseDiagonal(matin));
538345a4b08SToby Isaac   PetscCall(VecPointwiseMult(x, b, ctx->inv_diag));
539345a4b08SToby Isaac   PetscFunctionReturn(PETSC_SUCCESS);
540345a4b08SToby Isaac }
541345a4b08SToby Isaac 
MatGetInfo_Diagonal(Mat A,MatInfoType flag,MatInfo * info)54266976f2fSJacob Faibussowitsch static PetscErrorCode MatGetInfo_Diagonal(Mat A, MatInfoType flag, MatInfo *info)
543345a4b08SToby Isaac {
544345a4b08SToby Isaac   PetscFunctionBegin;
545345a4b08SToby Isaac   info->block_size        = 1.0;
546345a4b08SToby Isaac   info->nz_allocated      = A->cmap->N;
547345a4b08SToby Isaac   info->nz_used           = A->cmap->N;
548345a4b08SToby Isaac   info->nz_unneeded       = 0.0;
549345a4b08SToby Isaac   info->assemblies        = A->num_ass;
550345a4b08SToby Isaac   info->mallocs           = 0.0;
551345a4b08SToby Isaac   info->memory            = 0;
552345a4b08SToby Isaac   info->fill_ratio_given  = 0;
553345a4b08SToby Isaac   info->fill_ratio_needed = 0;
554345a4b08SToby Isaac   info->factor_mallocs    = 0;
555345a4b08SToby Isaac   PetscFunctionReturn(PETSC_SUCCESS);
556345a4b08SToby Isaac }
557345a4b08SToby Isaac 
558345a4b08SToby Isaac /*@
559345a4b08SToby Isaac   MatCreateDiagonal - Creates a matrix defined by a given vector along its diagonal.
560345a4b08SToby Isaac 
561345a4b08SToby Isaac   Collective
562345a4b08SToby Isaac 
563345a4b08SToby Isaac   Input Parameter:
564345a4b08SToby Isaac . diag - vector for the diagonal
565345a4b08SToby Isaac 
566345a4b08SToby Isaac   Output Parameter:
567345a4b08SToby Isaac . J - the diagonal matrix
568345a4b08SToby Isaac 
569345a4b08SToby Isaac   Level: advanced
570345a4b08SToby Isaac 
571345a4b08SToby Isaac   Notes:
572345a4b08SToby Isaac   Only supports square matrices with the same number of local rows and columns.
573345a4b08SToby Isaac 
574345a4b08SToby Isaac   The input vector `diag` will be referenced internally: any changes to `diag`
575345a4b08SToby Isaac   will affect the matrix `J`.
576345a4b08SToby Isaac 
577be50c303SSatish Balay .seealso: [](ch_matrices), `Mat`, `MatDestroy()`, `MATCONSTANTDIAGONAL`, `MatScale()`, `MatShift()`, `MatMult()`, `MatGetDiagonal()`, `MatSolve()`
578345a4b08SToby Isaac           `MatDiagonalRestoreInverseDiagonal()`, `MatDiagonalGetDiagonal()`, `MatDiagonalRestoreDiagonal()`, `MatDiagonalGetInverseDiagonal()`
579345a4b08SToby Isaac @*/
MatCreateDiagonal(Vec diag,Mat * J)580345a4b08SToby Isaac PetscErrorCode MatCreateDiagonal(Vec diag, Mat *J)
581345a4b08SToby Isaac {
582345a4b08SToby Isaac   PetscFunctionBegin;
583345a4b08SToby Isaac   PetscValidHeaderSpecific(diag, VEC_CLASSID, 1);
584345a4b08SToby Isaac   PetscCall(MatCreate(PetscObjectComm((PetscObject)diag), J));
585345a4b08SToby Isaac   PetscInt m, M;
586345a4b08SToby Isaac   PetscCall(VecGetLocalSize(diag, &m));
587345a4b08SToby Isaac   PetscCall(VecGetSize(diag, &M));
588345a4b08SToby Isaac   PetscCall(MatSetSizes(*J, m, m, M, M));
589345a4b08SToby Isaac   PetscCall(MatSetType(*J, MATDIAGONAL));
590345a4b08SToby Isaac 
591345a4b08SToby Isaac   PetscLayout map;
592345a4b08SToby Isaac   PetscCall(VecGetLayout(diag, &map));
593345a4b08SToby Isaac   PetscCall(MatSetLayouts(*J, map, map));
594345a4b08SToby Isaac   Mat_Diagonal *ctx = (Mat_Diagonal *)(*J)->data;
595345a4b08SToby Isaac   PetscCall(PetscObjectReference((PetscObject)diag));
596345a4b08SToby Isaac   PetscCall(VecDestroy(&ctx->diag));
597345a4b08SToby Isaac   PetscCall(VecDestroy(&ctx->inv_diag));
598345a4b08SToby Isaac   ctx->diag           = diag;
599345a4b08SToby Isaac   ctx->diag_valid     = PETSC_TRUE;
600345a4b08SToby Isaac   ctx->inv_diag_valid = PETSC_FALSE;
601345a4b08SToby Isaac   VecType type;
602345a4b08SToby Isaac   PetscCall(VecDuplicate(ctx->diag, &ctx->inv_diag));
603345a4b08SToby Isaac   PetscCall(VecGetType(diag, &type));
604345a4b08SToby Isaac   PetscCall(PetscFree((*J)->defaultvectype));
605345a4b08SToby Isaac   PetscCall(PetscStrallocpy(type, &(*J)->defaultvectype));
606345a4b08SToby Isaac   PetscCall(MatSetUp(*J));
607c3e1b152SPierre Jolivet   ctx->col = NULL;
608c3e1b152SPierre Jolivet   ctx->val = NULL;
609345a4b08SToby Isaac   PetscFunctionReturn(PETSC_SUCCESS);
610345a4b08SToby Isaac }
611345a4b08SToby Isaac 
MatProductNumeric_Diagonal_Dense(Mat C)612e27ab85cSPierre Jolivet static PetscErrorCode MatProductNumeric_Diagonal_Dense(Mat C)
613e27ab85cSPierre Jolivet {
614e27ab85cSPierre Jolivet   Mat                A, B;
615e27ab85cSPierre Jolivet   Mat_Diagonal      *a;
616e27ab85cSPierre Jolivet   PetscScalar       *c;
617e27ab85cSPierre Jolivet   const PetscScalar *b, *alpha;
618e27ab85cSPierre Jolivet   PetscInt           ldb, ldc;
619e27ab85cSPierre Jolivet 
620e27ab85cSPierre Jolivet   PetscFunctionBegin;
621e27ab85cSPierre Jolivet   MatCheckProduct(C, 1);
622e27ab85cSPierre Jolivet   A = C->product->A;
623e27ab85cSPierre Jolivet   B = C->product->B;
624e27ab85cSPierre Jolivet   a = (Mat_Diagonal *)A->data;
625e27ab85cSPierre Jolivet   PetscCall(VecGetArrayRead(a->diag, &alpha));
626e27ab85cSPierre Jolivet   PetscCall(MatDenseGetLDA(B, &ldb));
627e27ab85cSPierre Jolivet   PetscCall(MatDenseGetLDA(C, &ldc));
628e27ab85cSPierre Jolivet   PetscCall(MatDenseGetArrayRead(B, &b));
629e27ab85cSPierre Jolivet   PetscCall(MatDenseGetArrayWrite(C, &c));
630e27ab85cSPierre Jolivet   for (PetscInt j = 0; j < B->cmap->N; j++)
631e27ab85cSPierre Jolivet     for (PetscInt i = 0; i < B->rmap->n; i++) c[i + j * ldc] = alpha[i] * b[i + j * ldb];
632e27ab85cSPierre Jolivet   PetscCall(MatDenseRestoreArrayWrite(C, &c));
633e27ab85cSPierre Jolivet   PetscCall(MatDenseRestoreArrayRead(B, &b));
634e27ab85cSPierre Jolivet   PetscCall(VecRestoreArrayRead(a->diag, &alpha));
635e27ab85cSPierre Jolivet   PetscCall(PetscLogFlops(B->cmap->N * B->rmap->n));
636e27ab85cSPierre Jolivet   PetscFunctionReturn(PETSC_SUCCESS);
637e27ab85cSPierre Jolivet }
638e27ab85cSPierre Jolivet 
MatProductSymbolic_Diagonal_Dense(Mat C)639e27ab85cSPierre Jolivet static PetscErrorCode MatProductSymbolic_Diagonal_Dense(Mat C)
640e27ab85cSPierre Jolivet {
641e27ab85cSPierre Jolivet   Mat      A, B;
642e27ab85cSPierre Jolivet   PetscInt n, N, m, M;
643e27ab85cSPierre Jolivet 
644e27ab85cSPierre Jolivet   PetscFunctionBegin;
645e27ab85cSPierre Jolivet   MatCheckProduct(C, 1);
646e27ab85cSPierre Jolivet   PetscCheck(!C->product->data, PetscObjectComm((PetscObject)C), PETSC_ERR_PLIB, "Product data not empty");
647e27ab85cSPierre Jolivet   A = C->product->A;
648e27ab85cSPierre Jolivet   B = C->product->B;
649e27ab85cSPierre Jolivet   PetscCall(MatDiagonalSetUpDiagonal(A));
650e27ab85cSPierre Jolivet   PetscCall(MatGetLocalSize(C, &m, &n));
651e27ab85cSPierre Jolivet   PetscCall(MatGetSize(C, &M, &N));
652e27ab85cSPierre Jolivet   if (m == PETSC_DECIDE || n == PETSC_DECIDE || M == PETSC_DECIDE || N == PETSC_DECIDE) {
653e27ab85cSPierre Jolivet     PetscCall(MatGetLocalSize(B, NULL, &n));
654e27ab85cSPierre Jolivet     PetscCall(MatGetSize(B, NULL, &N));
655e27ab85cSPierre Jolivet     PetscCall(MatGetLocalSize(A, &m, NULL));
656e27ab85cSPierre Jolivet     PetscCall(MatGetSize(A, &M, NULL));
657e27ab85cSPierre Jolivet     PetscCall(MatSetSizes(C, m, n, M, N));
658e27ab85cSPierre Jolivet   }
659e27ab85cSPierre Jolivet   PetscCall(MatSetType(C, ((PetscObject)B)->type_name));
660e27ab85cSPierre Jolivet   PetscCall(MatSetUp(C));
661e27ab85cSPierre Jolivet   C->ops->productnumeric = MatProductNumeric_Diagonal_Dense;
662e27ab85cSPierre Jolivet   PetscFunctionReturn(PETSC_SUCCESS);
663e27ab85cSPierre Jolivet }
664e27ab85cSPierre Jolivet 
MatProductSetFromOptions_Diagonal_Dense_AB(Mat C)665e27ab85cSPierre Jolivet static PetscErrorCode MatProductSetFromOptions_Diagonal_Dense_AB(Mat C)
666e27ab85cSPierre Jolivet {
667e27ab85cSPierre Jolivet   PetscFunctionBegin;
668e27ab85cSPierre Jolivet   C->ops->productsymbolic = MatProductSymbolic_Diagonal_Dense;
669e27ab85cSPierre Jolivet   PetscFunctionReturn(PETSC_SUCCESS);
670e27ab85cSPierre Jolivet }
671e27ab85cSPierre Jolivet 
MatProductSetFromOptions_Diagonal_Dense(Mat C)672e27ab85cSPierre Jolivet static PetscErrorCode MatProductSetFromOptions_Diagonal_Dense(Mat C)
673e27ab85cSPierre Jolivet {
674e27ab85cSPierre Jolivet   Mat_Product *product = C->product;
675e27ab85cSPierre Jolivet 
676e27ab85cSPierre Jolivet   PetscFunctionBegin;
677e27ab85cSPierre Jolivet   if (product->type == MATPRODUCT_AB || product->type == MATPRODUCT_AtB) PetscCall(MatProductSetFromOptions_Diagonal_Dense_AB(C));
678e27ab85cSPierre Jolivet   PetscFunctionReturn(PETSC_SUCCESS);
679e27ab85cSPierre Jolivet }
680e27ab85cSPierre Jolivet 
681345a4b08SToby Isaac /*MC
682345a4b08SToby Isaac    MATDIAGONAL - MATDIAGONAL = "diagonal" - A diagonal matrix type with the diagonal implemented as a `Vec`.  Useful for
683345a4b08SToby Isaac    cases where `VecPointwiseMult()` or `VecPointwiseDivide()` should be thought of as the actions of a linear operator.
684345a4b08SToby Isaac 
685345a4b08SToby Isaac   Level: advanced
686345a4b08SToby Isaac 
687be50c303SSatish Balay .seealso: [](ch_matrices), `Mat`, `MatCreateDiagonal()`, `MatDiagonalRestoreInverseDiagonal()`, `MatDiagonalGetDiagonal()`, `MatDiagonalRestoreDiagonal()`, `MatDiagonalGetInverseDiagonal()`
688345a4b08SToby Isaac M*/
MatCreate_Diagonal(Mat A)689345a4b08SToby Isaac PETSC_INTERN PetscErrorCode MatCreate_Diagonal(Mat A)
690345a4b08SToby Isaac {
691345a4b08SToby Isaac   Mat_Diagonal *ctx;
692345a4b08SToby Isaac 
693345a4b08SToby Isaac   PetscFunctionBegin;
694345a4b08SToby Isaac   PetscCall(PetscNew(&ctx));
695345a4b08SToby Isaac   A->data = (void *)ctx;
696345a4b08SToby Isaac 
697345a4b08SToby Isaac   A->structurally_symmetric      = PETSC_BOOL3_TRUE;
698345a4b08SToby Isaac   A->structural_symmetry_eternal = PETSC_TRUE;
699345a4b08SToby Isaac   A->symmetry_eternal            = PETSC_TRUE;
700345a4b08SToby Isaac   A->symmetric                   = PETSC_BOOL3_TRUE;
701345a4b08SToby Isaac   if (!PetscDefined(USE_COMPLEX)) A->hermitian = PETSC_BOOL3_TRUE;
702345a4b08SToby Isaac 
703c3e1b152SPierre Jolivet   A->ops->getrow           = MatGetRow_Diagonal;
704345a4b08SToby Isaac   A->ops->mult             = MatMult_Diagonal;
705345a4b08SToby Isaac   A->ops->multadd          = MatMultAdd_Diagonal;
706345a4b08SToby Isaac   A->ops->multtranspose    = MatMult_Diagonal;
707345a4b08SToby Isaac   A->ops->multtransposeadd = MatMultAdd_Diagonal;
708345a4b08SToby Isaac   A->ops->norm             = MatNorm_Diagonal;
709345a4b08SToby Isaac   A->ops->duplicate        = MatDuplicate_Diagonal;
710345a4b08SToby Isaac   A->ops->solve            = MatSolve_Diagonal;
711345a4b08SToby Isaac   A->ops->solvetranspose   = MatSolve_Diagonal;
712345a4b08SToby Isaac   A->ops->shift            = MatShift_Diagonal;
713345a4b08SToby Isaac   A->ops->scale            = MatScale_Diagonal;
714345a4b08SToby Isaac   A->ops->diagonalscale    = MatDiagonalScale_Diagonal;
715345a4b08SToby Isaac   A->ops->getdiagonal      = MatGetDiagonal_Diagonal;
716345a4b08SToby Isaac   A->ops->diagonalset      = MatDiagonalSet_Diagonal;
717345a4b08SToby Isaac   A->ops->view             = MatView_Diagonal;
718345a4b08SToby Isaac   A->ops->zeroentries      = MatZeroEntries_Diagonal;
719345a4b08SToby Isaac   A->ops->destroy          = MatDestroy_Diagonal;
720345a4b08SToby Isaac   A->ops->getinfo          = MatGetInfo_Diagonal;
721345a4b08SToby Isaac   A->ops->axpy             = MatAXPY_Diagonal;
722345a4b08SToby Isaac   A->ops->setup            = MatSetUp_Diagonal;
723ee8a0a41SPierre Jolivet   A->ops->permute          = MatPermute_Diagonal;
7248a1df862SToby Isaac   A->ops->setrandom        = MatSetRandom_Diagonal;
7258a1df862SToby Isaac   A->ops->conjugate        = MatConjugate_Diagonal;
7268a1df862SToby Isaac   A->ops->transpose        = MatTranspose_Diagonal;
727345a4b08SToby Isaac 
728345a4b08SToby Isaac   PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatDiagonalGetDiagonal_C", MatDiagonalGetDiagonal_Diagonal));
729345a4b08SToby Isaac   PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatDiagonalRestoreDiagonal_C", MatDiagonalRestoreDiagonal_Diagonal));
730345a4b08SToby Isaac   PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatDiagonalGetInverseDiagonal_C", MatDiagonalGetInverseDiagonal_Diagonal));
731345a4b08SToby Isaac   PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatDiagonalRestoreInverseDiagonal_C", MatDiagonalRestoreInverseDiagonal_Diagonal));
732e27ab85cSPierre Jolivet   PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatProductSetFromOptions_diagonal_seqdense_C", MatProductSetFromOptions_Diagonal_Dense));
733e27ab85cSPierre Jolivet   PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatProductSetFromOptions_diagonal_mpidense_C", MatProductSetFromOptions_Diagonal_Dense));
734345a4b08SToby Isaac   PetscCall(PetscObjectChangeTypeName((PetscObject)A, MATDIAGONAL));
735345a4b08SToby Isaac   PetscFunctionReturn(PETSC_SUCCESS);
736345a4b08SToby Isaac }
737