xref: /petsc/src/mat/impls/dense/seq/dense.c (revision f8b9f887efa5534f423807e37a1fe2e87d779bac)
1 /*
2      Defines the basic matrix operations for sequential dense.
3      Portions of this code are under:
4      Copyright (c) 2022 Advanced Micro Devices, Inc. All rights reserved.
5 */
6 
7 #include <../src/mat/impls/dense/seq/dense.h> /*I "petscmat.h" I*/
8 #include <../src/mat/impls/dense/mpi/mpidense.h>
9 #include <petscblaslapack.h>
10 #include <../src/mat/impls/aij/seq/aij.h>
11 #include <petsc/private/vecimpl.h>
12 
13 PetscErrorCode MatSeqDenseSymmetrize_Private(Mat A, PetscBool hermitian)
14 {
15   Mat_SeqDense *mat = (Mat_SeqDense *)A->data;
16   PetscInt      j, k, n = A->rmap->n;
17   PetscScalar  *v;
18 
19   PetscFunctionBegin;
20   PetscCheck(A->rmap->n == A->cmap->n, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Cannot symmetrize a rectangular matrix");
21   PetscCall(MatDenseGetArray(A, &v));
22   if (!hermitian) {
23     for (k = 0; k < n; k++) {
24       for (j = k; j < n; j++) v[j * mat->lda + k] = v[k * mat->lda + j];
25     }
26   } else {
27     for (k = 0; k < n; k++) {
28       for (j = k; j < n; j++) v[j * mat->lda + k] = PetscConj(v[k * mat->lda + j]);
29     }
30   }
31   PetscCall(MatDenseRestoreArray(A, &v));
32   PetscFunctionReturn(PETSC_SUCCESS);
33 }
34 
35 PetscErrorCode MatSeqDenseInvertFactors_Private(Mat A)
36 {
37   Mat_SeqDense *mat = (Mat_SeqDense *)A->data;
38   PetscBLASInt  info, n;
39 
40   PetscFunctionBegin;
41   if (!A->rmap->n || !A->cmap->n) PetscFunctionReturn(PETSC_SUCCESS);
42   PetscCall(PetscBLASIntCast(A->cmap->n, &n));
43   if (A->factortype == MAT_FACTOR_LU) {
44     PetscCheck(mat->pivots, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Pivots not present");
45     if (!mat->fwork) {
46       mat->lfwork = n;
47       PetscCall(PetscMalloc1(mat->lfwork, &mat->fwork));
48     }
49     PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF));
50     PetscCallBLAS("LAPACKgetri", LAPACKgetri_(&n, mat->v, &mat->lda, mat->pivots, mat->fwork, &mat->lfwork, &info));
51     PetscCall(PetscFPTrapPop());
52     PetscCall(PetscLogFlops((1.0 * A->cmap->n * A->cmap->n * A->cmap->n) / 3.0));
53   } else if (A->factortype == MAT_FACTOR_CHOLESKY) {
54     if (A->spd == PETSC_BOOL3_TRUE) {
55       PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF));
56       PetscCallBLAS("LAPACKpotri", LAPACKpotri_("L", &n, mat->v, &mat->lda, &info));
57       PetscCall(PetscFPTrapPop());
58       PetscCall(MatSeqDenseSymmetrize_Private(A, PETSC_TRUE));
59 #if defined(PETSC_USE_COMPLEX)
60     } else if (A->hermitian == PETSC_BOOL3_TRUE) {
61       PetscCheck(mat->pivots, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Pivots not present");
62       PetscCheck(mat->fwork, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Fwork not present");
63       PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF));
64       PetscCallBLAS("LAPACKhetri", LAPACKhetri_("L", &n, mat->v, &mat->lda, mat->pivots, mat->fwork, &info));
65       PetscCall(PetscFPTrapPop());
66       PetscCall(MatSeqDenseSymmetrize_Private(A, PETSC_TRUE));
67 #endif
68     } else { /* symmetric case */
69       PetscCheck(mat->pivots, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Pivots not present");
70       PetscCheck(mat->fwork, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Fwork not present");
71       PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF));
72       PetscCallBLAS("LAPACKsytri", LAPACKsytri_("L", &n, mat->v, &mat->lda, mat->pivots, mat->fwork, &info));
73       PetscCall(PetscFPTrapPop());
74       PetscCall(MatSeqDenseSymmetrize_Private(A, PETSC_FALSE));
75     }
76     PetscCheck(!info, PETSC_COMM_SELF, PETSC_ERR_MAT_CH_ZRPVT, "Bad Inversion: zero pivot in row %" PetscBLASInt_FMT, info - 1);
77     PetscCall(PetscLogFlops((1.0 * A->cmap->n * A->cmap->n * A->cmap->n) / 3.0));
78   } else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Matrix must be factored to solve");
79 
80   A->ops->solve             = NULL;
81   A->ops->matsolve          = NULL;
82   A->ops->solvetranspose    = NULL;
83   A->ops->matsolvetranspose = NULL;
84   A->ops->solveadd          = NULL;
85   A->ops->solvetransposeadd = NULL;
86   A->factortype             = MAT_FACTOR_NONE;
87   PetscCall(PetscFree(A->solvertype));
88   PetscFunctionReturn(PETSC_SUCCESS);
89 }
90 
91 static PetscErrorCode MatZeroRowsColumns_SeqDense(Mat A, PetscInt N, const PetscInt rows[], PetscScalar diag, Vec x, Vec b)
92 {
93   Mat_SeqDense      *l = (Mat_SeqDense *)A->data;
94   PetscInt           m = l->lda, n = A->cmap->n, r = A->rmap->n, i, j;
95   PetscScalar       *slot, *bb, *v;
96   const PetscScalar *xx;
97 
98   PetscFunctionBegin;
99   if (PetscDefined(USE_DEBUG)) {
100     for (i = 0; i < N; i++) {
101       PetscCheck(rows[i] >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Negative row requested to be zeroed");
102       PetscCheck(rows[i] < A->rmap->n, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Row %" PetscInt_FMT " requested to be zeroed greater than or equal number of rows %" PetscInt_FMT, rows[i], A->rmap->n);
103       PetscCheck(rows[i] < A->cmap->n, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Col %" PetscInt_FMT " requested to be zeroed greater than or equal number of cols %" PetscInt_FMT, rows[i], A->cmap->n);
104     }
105   }
106   if (!N) PetscFunctionReturn(PETSC_SUCCESS);
107 
108   /* fix right-hand side if needed */
109   if (x && b) {
110     Vec xt;
111 
112     PetscCheck(A->rmap->n == A->cmap->n, PETSC_COMM_SELF, PETSC_ERR_SUP, "Only coded for square matrices");
113     PetscCall(VecDuplicate(x, &xt));
114     PetscCall(VecCopy(x, xt));
115     PetscCall(VecScale(xt, -1.0));
116     PetscCall(MatMultAdd(A, xt, b, b));
117     PetscCall(VecDestroy(&xt));
118     PetscCall(VecGetArrayRead(x, &xx));
119     PetscCall(VecGetArray(b, &bb));
120     for (i = 0; i < N; i++) bb[rows[i]] = diag * xx[rows[i]];
121     PetscCall(VecRestoreArrayRead(x, &xx));
122     PetscCall(VecRestoreArray(b, &bb));
123   }
124 
125   PetscCall(MatDenseGetArray(A, &v));
126   for (i = 0; i < N; i++) {
127     slot = v + rows[i] * m;
128     PetscCall(PetscArrayzero(slot, r));
129   }
130   for (i = 0; i < N; i++) {
131     slot = v + rows[i];
132     for (j = 0; j < n; j++) {
133       *slot = 0.0;
134       slot += m;
135     }
136   }
137   if (diag != 0.0) {
138     PetscCheck(A->rmap->n == A->cmap->n, PETSC_COMM_SELF, PETSC_ERR_SUP, "Only coded for square matrices");
139     for (i = 0; i < N; i++) {
140       slot  = v + (m + 1) * rows[i];
141       *slot = diag;
142     }
143   }
144   PetscCall(MatDenseRestoreArray(A, &v));
145   PetscFunctionReturn(PETSC_SUCCESS);
146 }
147 
148 PETSC_INTERN PetscErrorCode MatConvert_SeqAIJ_SeqDense(Mat A, MatType newtype, MatReuse reuse, Mat *newmat)
149 {
150   Mat              B = NULL;
151   Mat_SeqAIJ      *a = (Mat_SeqAIJ *)A->data;
152   Mat_SeqDense    *b;
153   PetscInt        *ai = a->i, *aj = a->j, m = A->rmap->N, n = A->cmap->N, i;
154   const MatScalar *av;
155   PetscBool        isseqdense;
156 
157   PetscFunctionBegin;
158   if (reuse == MAT_REUSE_MATRIX) {
159     PetscCall(PetscObjectTypeCompare((PetscObject)*newmat, MATSEQDENSE, &isseqdense));
160     PetscCheck(isseqdense, PetscObjectComm((PetscObject)*newmat), PETSC_ERR_USER, "Cannot reuse matrix of type %s", ((PetscObject)*newmat)->type_name);
161   }
162   if (reuse != MAT_REUSE_MATRIX) {
163     PetscCall(MatCreate(PetscObjectComm((PetscObject)A), &B));
164     PetscCall(MatSetSizes(B, m, n, m, n));
165     PetscCall(MatSetType(B, MATSEQDENSE));
166     PetscCall(MatSeqDenseSetPreallocation(B, NULL));
167     b = (Mat_SeqDense *)B->data;
168   } else {
169     b = (Mat_SeqDense *)((*newmat)->data);
170     for (i = 0; i < n; i++) PetscCall(PetscArrayzero(b->v + i * b->lda, m));
171   }
172   PetscCall(MatSeqAIJGetArrayRead(A, &av));
173   for (i = 0; i < m; i++) {
174     PetscInt j;
175     for (j = 0; j < ai[1] - ai[0]; j++) {
176       b->v[*aj * b->lda + i] = *av;
177       aj++;
178       av++;
179     }
180     ai++;
181   }
182   PetscCall(MatSeqAIJRestoreArrayRead(A, &av));
183 
184   if (reuse == MAT_INPLACE_MATRIX) {
185     PetscCall(MatAssemblyBegin(B, MAT_FINAL_ASSEMBLY));
186     PetscCall(MatAssemblyEnd(B, MAT_FINAL_ASSEMBLY));
187     PetscCall(MatHeaderReplace(A, &B));
188   } else {
189     if (B) *newmat = B;
190     PetscCall(MatAssemblyBegin(*newmat, MAT_FINAL_ASSEMBLY));
191     PetscCall(MatAssemblyEnd(*newmat, MAT_FINAL_ASSEMBLY));
192   }
193   PetscFunctionReturn(PETSC_SUCCESS);
194 }
195 
196 PETSC_INTERN PetscErrorCode MatConvert_SeqDense_SeqAIJ(Mat A, MatType newtype, MatReuse reuse, Mat *newmat)
197 {
198   Mat           B = NULL;
199   Mat_SeqDense *a = (Mat_SeqDense *)A->data;
200   PetscInt      i, j;
201   PetscInt     *rows, *nnz;
202   MatScalar    *aa = a->v, *vals;
203 
204   PetscFunctionBegin;
205   PetscCall(PetscCalloc3(A->rmap->n, &rows, A->rmap->n, &nnz, A->rmap->n, &vals));
206   if (reuse != MAT_REUSE_MATRIX) {
207     PetscCall(MatCreate(PetscObjectComm((PetscObject)A), &B));
208     PetscCall(MatSetSizes(B, A->rmap->n, A->cmap->n, A->rmap->N, A->cmap->N));
209     PetscCall(MatSetType(B, MATSEQAIJ));
210     for (j = 0; j < A->cmap->n; j++) {
211       for (i = 0; i < A->rmap->n; i++)
212         if (aa[i] != 0.0 || (i == j && A->cmap->n == A->rmap->n)) ++nnz[i];
213       aa += a->lda;
214     }
215     PetscCall(MatSeqAIJSetPreallocation(B, PETSC_DETERMINE, nnz));
216   } else B = *newmat;
217   aa = a->v;
218   for (j = 0; j < A->cmap->n; j++) {
219     PetscInt numRows = 0;
220     for (i = 0; i < A->rmap->n; i++)
221       if (aa[i] != 0.0 || (i == j && A->cmap->n == A->rmap->n)) {
222         rows[numRows]   = i;
223         vals[numRows++] = aa[i];
224       }
225     PetscCall(MatSetValues(B, numRows, rows, 1, &j, vals, INSERT_VALUES));
226     aa += a->lda;
227   }
228   PetscCall(PetscFree3(rows, nnz, vals));
229   PetscCall(MatAssemblyBegin(B, MAT_FINAL_ASSEMBLY));
230   PetscCall(MatAssemblyEnd(B, MAT_FINAL_ASSEMBLY));
231 
232   if (reuse == MAT_INPLACE_MATRIX) {
233     PetscCall(MatHeaderReplace(A, &B));
234   } else if (reuse != MAT_REUSE_MATRIX) *newmat = B;
235   PetscFunctionReturn(PETSC_SUCCESS);
236 }
237 
238 PetscErrorCode MatAXPY_SeqDense(Mat Y, PetscScalar alpha, Mat X, MatStructure str)
239 {
240   Mat_SeqDense      *x = (Mat_SeqDense *)X->data, *y = (Mat_SeqDense *)Y->data;
241   const PetscScalar *xv;
242   PetscScalar       *yv;
243   PetscBLASInt       N, m, ldax = 0, lday = 0, one = 1;
244 
245   PetscFunctionBegin;
246   PetscCall(MatDenseGetArrayRead(X, &xv));
247   PetscCall(MatDenseGetArray(Y, &yv));
248   PetscCall(PetscBLASIntCast(X->rmap->n * X->cmap->n, &N));
249   PetscCall(PetscBLASIntCast(X->rmap->n, &m));
250   PetscCall(PetscBLASIntCast(x->lda, &ldax));
251   PetscCall(PetscBLASIntCast(y->lda, &lday));
252   if (ldax > m || lday > m) {
253     for (PetscInt j = 0; j < X->cmap->n; j++) PetscCallBLAS("BLASaxpy", BLASaxpy_(&m, &alpha, PetscSafePointerPlusOffset(xv, j * ldax), &one, PetscSafePointerPlusOffset(yv, j * lday), &one));
254   } else {
255     PetscCallBLAS("BLASaxpy", BLASaxpy_(&N, &alpha, xv, &one, yv, &one));
256   }
257   PetscCall(MatDenseRestoreArrayRead(X, &xv));
258   PetscCall(MatDenseRestoreArray(Y, &yv));
259   PetscCall(PetscLogFlops(PetscMax(2.0 * N - 1, 0)));
260   PetscFunctionReturn(PETSC_SUCCESS);
261 }
262 
263 static PetscErrorCode MatGetInfo_SeqDense(Mat A, MatInfoType flag, MatInfo *info)
264 {
265   PetscLogDouble N = A->rmap->n * A->cmap->n;
266 
267   PetscFunctionBegin;
268   info->block_size        = 1.0;
269   info->nz_allocated      = N;
270   info->nz_used           = N;
271   info->nz_unneeded       = 0;
272   info->assemblies        = A->num_ass;
273   info->mallocs           = 0;
274   info->memory            = 0; /* REVIEW ME */
275   info->fill_ratio_given  = 0;
276   info->fill_ratio_needed = 0;
277   info->factor_mallocs    = 0;
278   PetscFunctionReturn(PETSC_SUCCESS);
279 }
280 
281 PetscErrorCode MatScale_SeqDense(Mat A, PetscScalar alpha)
282 {
283   Mat_SeqDense *a = (Mat_SeqDense *)A->data;
284   PetscScalar  *v;
285   PetscBLASInt  one = 1, j, nz, lda = 0;
286 
287   PetscFunctionBegin;
288   PetscCall(MatDenseGetArray(A, &v));
289   PetscCall(PetscBLASIntCast(a->lda, &lda));
290   if (lda > A->rmap->n) {
291     PetscCall(PetscBLASIntCast(A->rmap->n, &nz));
292     for (j = 0; j < A->cmap->n; j++) PetscCallBLAS("BLASscal", BLASscal_(&nz, &alpha, v + j * lda, &one));
293   } else {
294     PetscCall(PetscBLASIntCast(A->rmap->n * A->cmap->n, &nz));
295     PetscCallBLAS("BLASscal", BLASscal_(&nz, &alpha, v, &one));
296   }
297   PetscCall(PetscLogFlops(A->rmap->n * A->cmap->n));
298   PetscCall(MatDenseRestoreArray(A, &v));
299   PetscFunctionReturn(PETSC_SUCCESS);
300 }
301 
302 PetscErrorCode MatShift_SeqDense(Mat A, PetscScalar alpha)
303 {
304   Mat_SeqDense *a = (Mat_SeqDense *)A->data;
305   PetscScalar  *v;
306   PetscInt      j, k;
307 
308   PetscFunctionBegin;
309   PetscCall(MatDenseGetArray(A, &v));
310   k = PetscMin(A->rmap->n, A->cmap->n);
311   for (j = 0; j < k; j++) v[j + j * a->lda] += alpha;
312   PetscCall(PetscLogFlops(k));
313   PetscCall(MatDenseRestoreArray(A, &v));
314   PetscFunctionReturn(PETSC_SUCCESS);
315 }
316 
317 static PetscErrorCode MatIsHermitian_SeqDense(Mat A, PetscReal rtol, PetscBool *fl)
318 {
319   Mat_SeqDense      *a = (Mat_SeqDense *)A->data;
320   PetscInt           i, j, m = A->rmap->n, N = a->lda;
321   const PetscScalar *v;
322 
323   PetscFunctionBegin;
324   *fl = PETSC_FALSE;
325   if (A->rmap->n != A->cmap->n) PetscFunctionReturn(PETSC_SUCCESS);
326   PetscCall(MatDenseGetArrayRead(A, &v));
327   for (i = 0; i < m; i++) {
328     for (j = i; j < m; j++) {
329       if (PetscAbsScalar(v[i + j * N] - PetscConj(v[j + i * N])) > rtol) goto restore;
330     }
331   }
332   *fl = PETSC_TRUE;
333 restore:
334   PetscCall(MatDenseRestoreArrayRead(A, &v));
335   PetscFunctionReturn(PETSC_SUCCESS);
336 }
337 
338 static PetscErrorCode MatIsSymmetric_SeqDense(Mat A, PetscReal rtol, PetscBool *fl)
339 {
340   Mat_SeqDense      *a = (Mat_SeqDense *)A->data;
341   PetscInt           i, j, m = A->rmap->n, N = a->lda;
342   const PetscScalar *v;
343 
344   PetscFunctionBegin;
345   *fl = PETSC_FALSE;
346   if (A->rmap->n != A->cmap->n) PetscFunctionReturn(PETSC_SUCCESS);
347   PetscCall(MatDenseGetArrayRead(A, &v));
348   for (i = 0; i < m; i++) {
349     for (j = i; j < m; j++) {
350       if (PetscAbsScalar(v[i + j * N] - v[j + i * N]) > rtol) goto restore;
351     }
352   }
353   *fl = PETSC_TRUE;
354 restore:
355   PetscCall(MatDenseRestoreArrayRead(A, &v));
356   PetscFunctionReturn(PETSC_SUCCESS);
357 }
358 
359 PetscErrorCode MatDuplicateNoCreate_SeqDense(Mat newi, Mat A, MatDuplicateOption cpvalues)
360 {
361   Mat_SeqDense *mat = (Mat_SeqDense *)A->data;
362   PetscInt      lda = mat->lda, j, m, nlda = lda;
363   PetscBool     isdensecpu;
364 
365   PetscFunctionBegin;
366   PetscCall(PetscLayoutReference(A->rmap, &newi->rmap));
367   PetscCall(PetscLayoutReference(A->cmap, &newi->cmap));
368   if (cpvalues == MAT_SHARE_NONZERO_PATTERN) { /* propagate LDA */
369     PetscCall(MatDenseSetLDA(newi, lda));
370   }
371   PetscCall(PetscObjectTypeCompare((PetscObject)newi, MATSEQDENSE, &isdensecpu));
372   if (isdensecpu) PetscCall(MatSeqDenseSetPreallocation(newi, NULL));
373   if (cpvalues == MAT_COPY_VALUES) {
374     const PetscScalar *av;
375     PetscScalar       *v;
376 
377     PetscCall(MatDenseGetArrayRead(A, &av));
378     PetscCall(MatDenseGetArrayWrite(newi, &v));
379     PetscCall(MatDenseGetLDA(newi, &nlda));
380     m = A->rmap->n;
381     if (lda > m || nlda > m) {
382       for (j = 0; j < A->cmap->n; j++) PetscCall(PetscArraycpy(PetscSafePointerPlusOffset(v, j * nlda), PetscSafePointerPlusOffset(av, j * lda), m));
383     } else {
384       PetscCall(PetscArraycpy(v, av, A->rmap->n * A->cmap->n));
385     }
386     PetscCall(MatDenseRestoreArrayWrite(newi, &v));
387     PetscCall(MatDenseRestoreArrayRead(A, &av));
388     PetscCall(MatPropagateSymmetryOptions(A, newi));
389   }
390   PetscFunctionReturn(PETSC_SUCCESS);
391 }
392 
393 PetscErrorCode MatDuplicate_SeqDense(Mat A, MatDuplicateOption cpvalues, Mat *newmat)
394 {
395   PetscFunctionBegin;
396   PetscCall(MatCreate(PetscObjectComm((PetscObject)A), newmat));
397   PetscCall(MatSetSizes(*newmat, A->rmap->n, A->cmap->n, A->rmap->n, A->cmap->n));
398   PetscCall(MatSetType(*newmat, ((PetscObject)A)->type_name));
399   PetscCall(MatDuplicateNoCreate_SeqDense(*newmat, A, cpvalues));
400   PetscFunctionReturn(PETSC_SUCCESS);
401 }
402 
403 static PetscErrorCode MatSolve_SeqDense_Internal_LU(Mat A, PetscScalar *x, PetscBLASInt ldx, PetscBLASInt m, PetscBLASInt nrhs, PetscBLASInt k, PetscBool T)
404 {
405   Mat_SeqDense *mat = (Mat_SeqDense *)A->data;
406   PetscBLASInt  info;
407 
408   PetscFunctionBegin;
409   PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF));
410   PetscCallBLAS("LAPACKgetrs", LAPACKgetrs_(T ? "T" : "N", &m, &nrhs, mat->v, &mat->lda, mat->pivots, x, &m, &info));
411   PetscCall(PetscFPTrapPop());
412   PetscCheck(!info, PETSC_COMM_SELF, PETSC_ERR_LIB, "GETRS - Bad solve %" PetscBLASInt_FMT, info);
413   PetscCall(PetscLogFlops(nrhs * (2.0 * m * m - m)));
414   PetscFunctionReturn(PETSC_SUCCESS);
415 }
416 
417 static PetscErrorCode MatConjugate_SeqDense(Mat);
418 
419 static PetscErrorCode MatSolve_SeqDense_Internal_Cholesky(Mat A, PetscScalar *x, PetscBLASInt ldx, PetscBLASInt m, PetscBLASInt nrhs, PetscBLASInt k, PetscBool T)
420 {
421   Mat_SeqDense *mat = (Mat_SeqDense *)A->data;
422   PetscBLASInt  info;
423 
424   PetscFunctionBegin;
425   if (A->spd == PETSC_BOOL3_TRUE) {
426     if (PetscDefined(USE_COMPLEX) && T) PetscCall(MatConjugate_SeqDense(A));
427     PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF));
428     PetscCallBLAS("LAPACKpotrs", LAPACKpotrs_("L", &m, &nrhs, mat->v, &mat->lda, x, &m, &info));
429     PetscCall(PetscFPTrapPop());
430     PetscCheck(!info, PETSC_COMM_SELF, PETSC_ERR_LIB, "POTRS Bad solve %" PetscBLASInt_FMT, info);
431     if (PetscDefined(USE_COMPLEX) && T) PetscCall(MatConjugate_SeqDense(A));
432 #if defined(PETSC_USE_COMPLEX)
433   } else if (A->hermitian == PETSC_BOOL3_TRUE) {
434     if (T) PetscCall(MatConjugate_SeqDense(A));
435     PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF));
436     PetscCallBLAS("LAPACKhetrs", LAPACKhetrs_("L", &m, &nrhs, mat->v, &mat->lda, mat->pivots, x, &m, &info));
437     PetscCall(PetscFPTrapPop());
438     PetscCheck(!info, PETSC_COMM_SELF, PETSC_ERR_LIB, "HETRS Bad solve %" PetscBLASInt_FMT, info);
439     if (T) PetscCall(MatConjugate_SeqDense(A));
440 #endif
441   } else { /* symmetric case */
442     PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF));
443     PetscCallBLAS("LAPACKsytrs", LAPACKsytrs_("L", &m, &nrhs, mat->v, &mat->lda, mat->pivots, x, &m, &info));
444     PetscCall(PetscFPTrapPop());
445     PetscCheck(!info, PETSC_COMM_SELF, PETSC_ERR_LIB, "SYTRS Bad solve %" PetscBLASInt_FMT, info);
446   }
447   PetscCall(PetscLogFlops(nrhs * (2.0 * m * m - m)));
448   PetscFunctionReturn(PETSC_SUCCESS);
449 }
450 
451 static PetscErrorCode MatSolve_SeqDense_Internal_QR(Mat A, PetscScalar *x, PetscBLASInt ldx, PetscBLASInt m, PetscBLASInt nrhs, PetscBLASInt k)
452 {
453   Mat_SeqDense *mat = (Mat_SeqDense *)A->data;
454   PetscBLASInt  info;
455   char          trans;
456 
457   PetscFunctionBegin;
458   if (PetscDefined(USE_COMPLEX)) {
459     trans = 'C';
460   } else {
461     trans = 'T';
462   }
463   PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF));
464   { /* lwork depends on the number of right-hand sides */
465     PetscBLASInt nlfwork, lfwork = -1;
466     PetscScalar  fwork;
467 
468     PetscCallBLAS("LAPACKormqr", LAPACKormqr_("L", &trans, &m, &nrhs, &mat->rank, mat->v, &mat->lda, mat->tau, x, &ldx, &fwork, &lfwork, &info));
469     nlfwork = (PetscBLASInt)PetscRealPart(fwork);
470     if (nlfwork > mat->lfwork) {
471       mat->lfwork = nlfwork;
472       PetscCall(PetscFree(mat->fwork));
473       PetscCall(PetscMalloc1(mat->lfwork, &mat->fwork));
474     }
475   }
476   PetscCallBLAS("LAPACKormqr", LAPACKormqr_("L", &trans, &m, &nrhs, &mat->rank, mat->v, &mat->lda, mat->tau, x, &ldx, mat->fwork, &mat->lfwork, &info));
477   PetscCall(PetscFPTrapPop());
478   PetscCheck(!info, PETSC_COMM_SELF, PETSC_ERR_LIB, "ORMQR - Bad orthogonal transform %" PetscBLASInt_FMT, info);
479   PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF));
480   PetscCallBLAS("LAPACKtrtrs", LAPACKtrtrs_("U", "N", "N", &mat->rank, &nrhs, mat->v, &mat->lda, x, &ldx, &info));
481   PetscCall(PetscFPTrapPop());
482   PetscCheck(!info, PETSC_COMM_SELF, PETSC_ERR_LIB, "TRTRS - Bad triangular solve %" PetscBLASInt_FMT, info);
483   for (PetscInt j = 0; j < nrhs; j++) {
484     for (PetscInt i = mat->rank; i < k; i++) x[j * ldx + i] = 0.;
485   }
486   PetscCall(PetscLogFlops(nrhs * (4.0 * m * mat->rank - PetscSqr(mat->rank))));
487   PetscFunctionReturn(PETSC_SUCCESS);
488 }
489 
490 static PetscErrorCode MatSolveTranspose_SeqDense_Internal_QR(Mat A, PetscScalar *x, PetscBLASInt ldx, PetscBLASInt m, PetscBLASInt nrhs, PetscBLASInt k)
491 {
492   Mat_SeqDense *mat = (Mat_SeqDense *)A->data;
493   PetscBLASInt  info;
494 
495   PetscFunctionBegin;
496   if (A->rmap->n == A->cmap->n && mat->rank == A->rmap->n) {
497     PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF));
498     PetscCallBLAS("LAPACKtrtrs", LAPACKtrtrs_("U", "T", "N", &m, &nrhs, mat->v, &mat->lda, x, &ldx, &info));
499     PetscCall(PetscFPTrapPop());
500     PetscCheck(!info, PETSC_COMM_SELF, PETSC_ERR_LIB, "TRTRS - Bad triangular solve %" PetscBLASInt_FMT, info);
501     if (PetscDefined(USE_COMPLEX)) PetscCall(MatConjugate_SeqDense(A));
502     { /* lwork depends on the number of right-hand sides */
503       PetscBLASInt nlfwork, lfwork = -1;
504       PetscScalar  fwork;
505 
506       PetscCallBLAS("LAPACKormqr", LAPACKormqr_("L", "N", &m, &nrhs, &mat->rank, mat->v, &mat->lda, mat->tau, x, &ldx, &fwork, &lfwork, &info));
507       nlfwork = (PetscBLASInt)PetscRealPart(fwork);
508       if (nlfwork > mat->lfwork) {
509         mat->lfwork = nlfwork;
510         PetscCall(PetscFree(mat->fwork));
511         PetscCall(PetscMalloc1(mat->lfwork, &mat->fwork));
512       }
513     }
514     PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF));
515     PetscCallBLAS("LAPACKormqr", LAPACKormqr_("L", "N", &m, &nrhs, &mat->rank, mat->v, &mat->lda, mat->tau, x, &ldx, mat->fwork, &mat->lfwork, &info));
516     PetscCall(PetscFPTrapPop());
517     PetscCheck(!info, PETSC_COMM_SELF, PETSC_ERR_LIB, "ORMQR - Bad orthogonal transform %" PetscBLASInt_FMT, info);
518     if (PetscDefined(USE_COMPLEX)) PetscCall(MatConjugate_SeqDense(A));
519   } else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "QR factored matrix cannot be used for transpose solve");
520   PetscCall(PetscLogFlops(nrhs * (4.0 * m * mat->rank - PetscSqr(mat->rank))));
521   PetscFunctionReturn(PETSC_SUCCESS);
522 }
523 
524 static PetscErrorCode MatSolve_SeqDense_SetUp(Mat A, Vec xx, Vec yy, PetscScalar **_y, PetscBLASInt *_m, PetscBLASInt *_k)
525 {
526   Mat_SeqDense *mat = (Mat_SeqDense *)A->data;
527   PetscScalar  *y;
528   PetscBLASInt  m = 0, k = 0;
529 
530   PetscFunctionBegin;
531   PetscCall(PetscBLASIntCast(A->rmap->n, &m));
532   PetscCall(PetscBLASIntCast(A->cmap->n, &k));
533   if (k < m) {
534     PetscCall(VecCopy(xx, mat->qrrhs));
535     PetscCall(VecGetArray(mat->qrrhs, &y));
536   } else {
537     PetscCall(VecCopy(xx, yy));
538     PetscCall(VecGetArray(yy, &y));
539   }
540   *_y = y;
541   *_k = k;
542   *_m = m;
543   PetscFunctionReturn(PETSC_SUCCESS);
544 }
545 
546 static PetscErrorCode MatSolve_SeqDense_TearDown(Mat A, Vec xx, Vec yy, PetscScalar **_y, PetscBLASInt *_m, PetscBLASInt *_k)
547 {
548   Mat_SeqDense *mat = (Mat_SeqDense *)A->data;
549   PetscScalar  *y   = NULL;
550   PetscBLASInt  m, k;
551 
552   PetscFunctionBegin;
553   y   = *_y;
554   *_y = NULL;
555   k   = *_k;
556   m   = *_m;
557   if (k < m) {
558     PetscScalar *yv;
559     PetscCall(VecGetArray(yy, &yv));
560     PetscCall(PetscArraycpy(yv, y, k));
561     PetscCall(VecRestoreArray(yy, &yv));
562     PetscCall(VecRestoreArray(mat->qrrhs, &y));
563   } else {
564     PetscCall(VecRestoreArray(yy, &y));
565   }
566   PetscFunctionReturn(PETSC_SUCCESS);
567 }
568 
569 static PetscErrorCode MatSolve_SeqDense_LU(Mat A, Vec xx, Vec yy)
570 {
571   PetscScalar *y = NULL;
572   PetscBLASInt m = 0, k = 0;
573 
574   PetscFunctionBegin;
575   PetscCall(MatSolve_SeqDense_SetUp(A, xx, yy, &y, &m, &k));
576   PetscCall(MatSolve_SeqDense_Internal_LU(A, y, m, m, 1, k, PETSC_FALSE));
577   PetscCall(MatSolve_SeqDense_TearDown(A, xx, yy, &y, &m, &k));
578   PetscFunctionReturn(PETSC_SUCCESS);
579 }
580 
581 static PetscErrorCode MatSolveTranspose_SeqDense_LU(Mat A, Vec xx, Vec yy)
582 {
583   PetscScalar *y = NULL;
584   PetscBLASInt m = 0, k = 0;
585 
586   PetscFunctionBegin;
587   PetscCall(MatSolve_SeqDense_SetUp(A, xx, yy, &y, &m, &k));
588   PetscCall(MatSolve_SeqDense_Internal_LU(A, y, m, m, 1, k, PETSC_TRUE));
589   PetscCall(MatSolve_SeqDense_TearDown(A, xx, yy, &y, &m, &k));
590   PetscFunctionReturn(PETSC_SUCCESS);
591 }
592 
593 static PetscErrorCode MatSolve_SeqDense_Cholesky(Mat A, Vec xx, Vec yy)
594 {
595   PetscScalar *y = NULL;
596   PetscBLASInt m = 0, k = 0;
597 
598   PetscFunctionBegin;
599   PetscCall(MatSolve_SeqDense_SetUp(A, xx, yy, &y, &m, &k));
600   PetscCall(MatSolve_SeqDense_Internal_Cholesky(A, y, m, m, 1, k, PETSC_FALSE));
601   PetscCall(MatSolve_SeqDense_TearDown(A, xx, yy, &y, &m, &k));
602   PetscFunctionReturn(PETSC_SUCCESS);
603 }
604 
605 static PetscErrorCode MatSolveTranspose_SeqDense_Cholesky(Mat A, Vec xx, Vec yy)
606 {
607   PetscScalar *y = NULL;
608   PetscBLASInt m = 0, k = 0;
609 
610   PetscFunctionBegin;
611   PetscCall(MatSolve_SeqDense_SetUp(A, xx, yy, &y, &m, &k));
612   PetscCall(MatSolve_SeqDense_Internal_Cholesky(A, y, m, m, 1, k, PETSC_TRUE));
613   PetscCall(MatSolve_SeqDense_TearDown(A, xx, yy, &y, &m, &k));
614   PetscFunctionReturn(PETSC_SUCCESS);
615 }
616 
617 static PetscErrorCode MatSolve_SeqDense_QR(Mat A, Vec xx, Vec yy)
618 {
619   PetscScalar *y = NULL;
620   PetscBLASInt m = 0, k = 0;
621 
622   PetscFunctionBegin;
623   PetscCall(MatSolve_SeqDense_SetUp(A, xx, yy, &y, &m, &k));
624   PetscCall(MatSolve_SeqDense_Internal_QR(A, y, PetscMax(m, k), m, 1, k));
625   PetscCall(MatSolve_SeqDense_TearDown(A, xx, yy, &y, &m, &k));
626   PetscFunctionReturn(PETSC_SUCCESS);
627 }
628 
629 static PetscErrorCode MatSolveTranspose_SeqDense_QR(Mat A, Vec xx, Vec yy)
630 {
631   PetscScalar *y = NULL;
632   PetscBLASInt m = 0, k = 0;
633 
634   PetscFunctionBegin;
635   PetscCall(MatSolve_SeqDense_SetUp(A, xx, yy, &y, &m, &k));
636   PetscCall(MatSolveTranspose_SeqDense_Internal_QR(A, y, PetscMax(m, k), m, 1, k));
637   PetscCall(MatSolve_SeqDense_TearDown(A, xx, yy, &y, &m, &k));
638   PetscFunctionReturn(PETSC_SUCCESS);
639 }
640 
641 static PetscErrorCode MatMatSolve_SeqDense_SetUp(Mat A, Mat B, Mat X, PetscScalar **_y, PetscBLASInt *_ldy, PetscBLASInt *_m, PetscBLASInt *_nrhs, PetscBLASInt *_k)
642 {
643   const PetscScalar *b;
644   PetscScalar       *y;
645   PetscInt           n, _ldb, _ldx;
646   PetscBLASInt       nrhs = 0, m = 0, k = 0, ldb = 0, ldx = 0, ldy = 0;
647 
648   PetscFunctionBegin;
649   *_ldy  = 0;
650   *_m    = 0;
651   *_nrhs = 0;
652   *_k    = 0;
653   *_y    = NULL;
654   PetscCall(PetscBLASIntCast(A->rmap->n, &m));
655   PetscCall(PetscBLASIntCast(A->cmap->n, &k));
656   PetscCall(MatGetSize(B, NULL, &n));
657   PetscCall(PetscBLASIntCast(n, &nrhs));
658   PetscCall(MatDenseGetLDA(B, &_ldb));
659   PetscCall(PetscBLASIntCast(_ldb, &ldb));
660   PetscCall(MatDenseGetLDA(X, &_ldx));
661   PetscCall(PetscBLASIntCast(_ldx, &ldx));
662   if (ldx < m) {
663     PetscCall(MatDenseGetArrayRead(B, &b));
664     PetscCall(PetscMalloc1(nrhs * m, &y));
665     if (ldb == m) {
666       PetscCall(PetscArraycpy(y, b, ldb * nrhs));
667     } else {
668       for (PetscInt j = 0; j < nrhs; j++) PetscCall(PetscArraycpy(&y[j * m], &b[j * ldb], m));
669     }
670     ldy = m;
671     PetscCall(MatDenseRestoreArrayRead(B, &b));
672   } else {
673     if (ldb == ldx) {
674       PetscCall(MatCopy(B, X, SAME_NONZERO_PATTERN));
675       PetscCall(MatDenseGetArray(X, &y));
676     } else {
677       PetscCall(MatDenseGetArray(X, &y));
678       PetscCall(MatDenseGetArrayRead(B, &b));
679       for (PetscInt j = 0; j < nrhs; j++) PetscCall(PetscArraycpy(&y[j * ldx], &b[j * ldb], m));
680       PetscCall(MatDenseRestoreArrayRead(B, &b));
681     }
682     ldy = ldx;
683   }
684   *_y    = y;
685   *_ldy  = ldy;
686   *_k    = k;
687   *_m    = m;
688   *_nrhs = nrhs;
689   PetscFunctionReturn(PETSC_SUCCESS);
690 }
691 
692 static PetscErrorCode MatMatSolve_SeqDense_TearDown(Mat A, Mat B, Mat X, PetscScalar **_y, PetscBLASInt *_ldy, PetscBLASInt *_m, PetscBLASInt *_nrhs, PetscBLASInt *_k)
693 {
694   PetscScalar *y;
695   PetscInt     _ldx;
696   PetscBLASInt k, ldy, nrhs, ldx = 0;
697 
698   PetscFunctionBegin;
699   y    = *_y;
700   *_y  = NULL;
701   k    = *_k;
702   ldy  = *_ldy;
703   nrhs = *_nrhs;
704   PetscCall(MatDenseGetLDA(X, &_ldx));
705   PetscCall(PetscBLASIntCast(_ldx, &ldx));
706   if (ldx != ldy) {
707     PetscScalar *xv;
708     PetscCall(MatDenseGetArray(X, &xv));
709     for (PetscInt j = 0; j < nrhs; j++) PetscCall(PetscArraycpy(&xv[j * ldx], &y[j * ldy], k));
710     PetscCall(MatDenseRestoreArray(X, &xv));
711     PetscCall(PetscFree(y));
712   } else {
713     PetscCall(MatDenseRestoreArray(X, &y));
714   }
715   PetscFunctionReturn(PETSC_SUCCESS);
716 }
717 
718 static PetscErrorCode MatMatSolve_SeqDense_LU(Mat A, Mat B, Mat X)
719 {
720   PetscScalar *y;
721   PetscBLASInt m, k, ldy, nrhs;
722 
723   PetscFunctionBegin;
724   PetscCall(MatMatSolve_SeqDense_SetUp(A, B, X, &y, &ldy, &m, &nrhs, &k));
725   PetscCall(MatSolve_SeqDense_Internal_LU(A, y, ldy, m, nrhs, k, PETSC_FALSE));
726   PetscCall(MatMatSolve_SeqDense_TearDown(A, B, X, &y, &ldy, &m, &nrhs, &k));
727   PetscFunctionReturn(PETSC_SUCCESS);
728 }
729 
730 static PetscErrorCode MatMatSolveTranspose_SeqDense_LU(Mat A, Mat B, Mat X)
731 {
732   PetscScalar *y;
733   PetscBLASInt m, k, ldy, nrhs;
734 
735   PetscFunctionBegin;
736   PetscCall(MatMatSolve_SeqDense_SetUp(A, B, X, &y, &ldy, &m, &nrhs, &k));
737   PetscCall(MatSolve_SeqDense_Internal_LU(A, y, ldy, m, nrhs, k, PETSC_TRUE));
738   PetscCall(MatMatSolve_SeqDense_TearDown(A, B, X, &y, &ldy, &m, &nrhs, &k));
739   PetscFunctionReturn(PETSC_SUCCESS);
740 }
741 
742 static PetscErrorCode MatMatSolve_SeqDense_Cholesky(Mat A, Mat B, Mat X)
743 {
744   PetscScalar *y;
745   PetscBLASInt m, k, ldy, nrhs;
746 
747   PetscFunctionBegin;
748   PetscCall(MatMatSolve_SeqDense_SetUp(A, B, X, &y, &ldy, &m, &nrhs, &k));
749   PetscCall(MatSolve_SeqDense_Internal_Cholesky(A, y, ldy, m, nrhs, k, PETSC_FALSE));
750   PetscCall(MatMatSolve_SeqDense_TearDown(A, B, X, &y, &ldy, &m, &nrhs, &k));
751   PetscFunctionReturn(PETSC_SUCCESS);
752 }
753 
754 static PetscErrorCode MatMatSolveTranspose_SeqDense_Cholesky(Mat A, Mat B, Mat X)
755 {
756   PetscScalar *y;
757   PetscBLASInt m, k, ldy, nrhs;
758 
759   PetscFunctionBegin;
760   PetscCall(MatMatSolve_SeqDense_SetUp(A, B, X, &y, &ldy, &m, &nrhs, &k));
761   PetscCall(MatSolve_SeqDense_Internal_Cholesky(A, y, ldy, m, nrhs, k, PETSC_TRUE));
762   PetscCall(MatMatSolve_SeqDense_TearDown(A, B, X, &y, &ldy, &m, &nrhs, &k));
763   PetscFunctionReturn(PETSC_SUCCESS);
764 }
765 
766 static PetscErrorCode MatMatSolve_SeqDense_QR(Mat A, Mat B, Mat X)
767 {
768   PetscScalar *y;
769   PetscBLASInt m, k, ldy, nrhs;
770 
771   PetscFunctionBegin;
772   PetscCall(MatMatSolve_SeqDense_SetUp(A, B, X, &y, &ldy, &m, &nrhs, &k));
773   PetscCall(MatSolve_SeqDense_Internal_QR(A, y, ldy, m, nrhs, k));
774   PetscCall(MatMatSolve_SeqDense_TearDown(A, B, X, &y, &ldy, &m, &nrhs, &k));
775   PetscFunctionReturn(PETSC_SUCCESS);
776 }
777 
778 static PetscErrorCode MatMatSolveTranspose_SeqDense_QR(Mat A, Mat B, Mat X)
779 {
780   PetscScalar *y;
781   PetscBLASInt m, k, ldy, nrhs;
782 
783   PetscFunctionBegin;
784   PetscCall(MatMatSolve_SeqDense_SetUp(A, B, X, &y, &ldy, &m, &nrhs, &k));
785   PetscCall(MatSolveTranspose_SeqDense_Internal_QR(A, y, ldy, m, nrhs, k));
786   PetscCall(MatMatSolve_SeqDense_TearDown(A, B, X, &y, &ldy, &m, &nrhs, &k));
787   PetscFunctionReturn(PETSC_SUCCESS);
788 }
789 
790 /* COMMENT: I have chosen to hide row permutation in the pivots,
791    rather than put it in the Mat->row slot.*/
792 PetscErrorCode MatLUFactor_SeqDense(Mat A, IS row, IS col, const MatFactorInfo *minfo)
793 {
794   Mat_SeqDense *mat = (Mat_SeqDense *)A->data;
795   PetscBLASInt  n, m, info;
796 
797   PetscFunctionBegin;
798   PetscCall(PetscBLASIntCast(A->cmap->n, &n));
799   PetscCall(PetscBLASIntCast(A->rmap->n, &m));
800   if (!mat->pivots) { PetscCall(PetscMalloc1(A->rmap->n, &mat->pivots)); }
801   if (!A->rmap->n || !A->cmap->n) PetscFunctionReturn(PETSC_SUCCESS);
802   PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF));
803   PetscCallBLAS("LAPACKgetrf", LAPACKgetrf_(&m, &n, mat->v, &mat->lda, mat->pivots, &info));
804   PetscCall(PetscFPTrapPop());
805 
806   PetscCheck(info >= 0, PETSC_COMM_SELF, PETSC_ERR_LIB, "Bad argument to LU factorization %" PetscBLASInt_FMT, info);
807   PetscCheck(info <= 0, PETSC_COMM_SELF, PETSC_ERR_MAT_LU_ZRPVT, "Bad LU factorization %" PetscBLASInt_FMT, info);
808 
809   A->ops->solve             = MatSolve_SeqDense_LU;
810   A->ops->matsolve          = MatMatSolve_SeqDense_LU;
811   A->ops->solvetranspose    = MatSolveTranspose_SeqDense_LU;
812   A->ops->matsolvetranspose = MatMatSolveTranspose_SeqDense_LU;
813   A->factortype             = MAT_FACTOR_LU;
814 
815   PetscCall(PetscFree(A->solvertype));
816   PetscCall(PetscStrallocpy(MATSOLVERPETSC, &A->solvertype));
817 
818   PetscCall(PetscLogFlops((2.0 * A->cmap->n * A->cmap->n * A->cmap->n) / 3));
819   PetscFunctionReturn(PETSC_SUCCESS);
820 }
821 
822 static PetscErrorCode MatLUFactorNumeric_SeqDense(Mat fact, Mat A, const MatFactorInfo *info_dummy)
823 {
824   MatFactorInfo info;
825 
826   PetscFunctionBegin;
827   PetscCall(MatDuplicateNoCreate_SeqDense(fact, A, MAT_COPY_VALUES));
828   PetscUseTypeMethod(fact, lufactor, NULL, NULL, &info);
829   PetscFunctionReturn(PETSC_SUCCESS);
830 }
831 
832 PetscErrorCode MatLUFactorSymbolic_SeqDense(Mat fact, Mat A, IS row, IS col, const MatFactorInfo *info)
833 {
834   PetscFunctionBegin;
835   fact->preallocated         = PETSC_TRUE;
836   fact->assembled            = PETSC_TRUE;
837   fact->ops->lufactornumeric = MatLUFactorNumeric_SeqDense;
838   PetscFunctionReturn(PETSC_SUCCESS);
839 }
840 
841 /* Cholesky as L*L^T or L*D*L^T and the symmetric/hermitian complex variants */
842 PetscErrorCode MatCholeskyFactor_SeqDense(Mat A, IS perm, const MatFactorInfo *factinfo)
843 {
844   Mat_SeqDense *mat = (Mat_SeqDense *)A->data;
845   PetscBLASInt  info, n;
846 
847   PetscFunctionBegin;
848   PetscCall(PetscBLASIntCast(A->cmap->n, &n));
849   if (!A->rmap->n || !A->cmap->n) PetscFunctionReturn(PETSC_SUCCESS);
850   if (A->spd == PETSC_BOOL3_TRUE) {
851     PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF));
852     PetscCallBLAS("LAPACKpotrf", LAPACKpotrf_("L", &n, mat->v, &mat->lda, &info));
853     PetscCall(PetscFPTrapPop());
854 #if defined(PETSC_USE_COMPLEX)
855   } else if (A->hermitian == PETSC_BOOL3_TRUE) {
856     if (!mat->pivots) { PetscCall(PetscMalloc1(A->rmap->n, &mat->pivots)); }
857     if (!mat->fwork) {
858       PetscScalar dummy;
859 
860       mat->lfwork = -1;
861       PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF));
862       PetscCallBLAS("LAPACKhetrf", LAPACKhetrf_("L", &n, mat->v, &mat->lda, mat->pivots, &dummy, &mat->lfwork, &info));
863       PetscCall(PetscFPTrapPop());
864       PetscCall(PetscBLASIntCast((PetscCount)(PetscRealPart(dummy)), &mat->lfwork));
865       PetscCall(PetscMalloc1(mat->lfwork, &mat->fwork));
866     }
867     PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF));
868     PetscCallBLAS("LAPACKhetrf", LAPACKhetrf_("L", &n, mat->v, &mat->lda, mat->pivots, mat->fwork, &mat->lfwork, &info));
869     PetscCall(PetscFPTrapPop());
870 #endif
871   } else { /* symmetric case */
872     if (!mat->pivots) { PetscCall(PetscMalloc1(A->rmap->n, &mat->pivots)); }
873     if (!mat->fwork) {
874       PetscScalar dummy;
875 
876       mat->lfwork = -1;
877       PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF));
878       PetscCallBLAS("LAPACKsytrf", LAPACKsytrf_("L", &n, mat->v, &mat->lda, mat->pivots, &dummy, &mat->lfwork, &info));
879       PetscCall(PetscFPTrapPop());
880       PetscCall(PetscBLASIntCast((PetscCount)(PetscRealPart(dummy)), &mat->lfwork));
881       PetscCall(PetscMalloc1(mat->lfwork, &mat->fwork));
882     }
883     PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF));
884     PetscCallBLAS("LAPACKsytrf", LAPACKsytrf_("L", &n, mat->v, &mat->lda, mat->pivots, mat->fwork, &mat->lfwork, &info));
885     PetscCall(PetscFPTrapPop());
886   }
887   PetscCheck(!info, PETSC_COMM_SELF, PETSC_ERR_MAT_CH_ZRPVT, "Bad factorization: zero pivot in row %" PetscBLASInt_FMT, info - 1);
888 
889   A->ops->solve             = MatSolve_SeqDense_Cholesky;
890   A->ops->matsolve          = MatMatSolve_SeqDense_Cholesky;
891   A->ops->solvetranspose    = MatSolveTranspose_SeqDense_Cholesky;
892   A->ops->matsolvetranspose = MatMatSolveTranspose_SeqDense_Cholesky;
893   A->factortype             = MAT_FACTOR_CHOLESKY;
894 
895   PetscCall(PetscFree(A->solvertype));
896   PetscCall(PetscStrallocpy(MATSOLVERPETSC, &A->solvertype));
897 
898   PetscCall(PetscLogFlops((1.0 * A->cmap->n * A->cmap->n * A->cmap->n) / 3.0));
899   PetscFunctionReturn(PETSC_SUCCESS);
900 }
901 
902 static PetscErrorCode MatCholeskyFactorNumeric_SeqDense(Mat fact, Mat A, const MatFactorInfo *info_dummy)
903 {
904   MatFactorInfo info;
905 
906   PetscFunctionBegin;
907   info.fill = 1.0;
908 
909   PetscCall(MatDuplicateNoCreate_SeqDense(fact, A, MAT_COPY_VALUES));
910   PetscUseTypeMethod(fact, choleskyfactor, NULL, &info);
911   PetscFunctionReturn(PETSC_SUCCESS);
912 }
913 
914 PetscErrorCode MatCholeskyFactorSymbolic_SeqDense(Mat fact, Mat A, IS row, const MatFactorInfo *info)
915 {
916   PetscFunctionBegin;
917   fact->assembled                  = PETSC_TRUE;
918   fact->preallocated               = PETSC_TRUE;
919   fact->ops->choleskyfactornumeric = MatCholeskyFactorNumeric_SeqDense;
920   PetscFunctionReturn(PETSC_SUCCESS);
921 }
922 
923 PetscErrorCode MatQRFactor_SeqDense(Mat A, IS col, const MatFactorInfo *minfo)
924 {
925   Mat_SeqDense *mat = (Mat_SeqDense *)A->data;
926   PetscBLASInt  n, m, info, min, max;
927 
928   PetscFunctionBegin;
929   PetscCall(PetscBLASIntCast(A->cmap->n, &n));
930   PetscCall(PetscBLASIntCast(A->rmap->n, &m));
931   max = PetscMax(m, n);
932   min = PetscMin(m, n);
933   if (!mat->tau) { PetscCall(PetscMalloc1(min, &mat->tau)); }
934   if (!mat->pivots) { PetscCall(PetscMalloc1(n, &mat->pivots)); }
935   if (!mat->qrrhs) PetscCall(MatCreateVecs(A, NULL, &mat->qrrhs));
936   if (!A->rmap->n || !A->cmap->n) PetscFunctionReturn(PETSC_SUCCESS);
937   if (!mat->fwork) {
938     PetscScalar dummy;
939 
940     mat->lfwork = -1;
941     PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF));
942     PetscCallBLAS("LAPACKgeqrf", LAPACKgeqrf_(&m, &n, mat->v, &mat->lda, mat->tau, &dummy, &mat->lfwork, &info));
943     PetscCall(PetscFPTrapPop());
944     PetscCall(PetscBLASIntCast((PetscCount)(PetscRealPart(dummy)), &mat->lfwork));
945     PetscCall(PetscMalloc1(mat->lfwork, &mat->fwork));
946   }
947   PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF));
948   PetscCallBLAS("LAPACKgeqrf", LAPACKgeqrf_(&m, &n, mat->v, &mat->lda, mat->tau, mat->fwork, &mat->lfwork, &info));
949   PetscCall(PetscFPTrapPop());
950   PetscCheck(!info, PETSC_COMM_SELF, PETSC_ERR_LIB, "Bad argument to QR factorization %" PetscBLASInt_FMT, info);
951   // TODO: try to estimate rank or test for and use geqp3 for rank revealing QR.  For now just say rank is min of m and n
952   mat->rank = min;
953 
954   A->ops->solve    = MatSolve_SeqDense_QR;
955   A->ops->matsolve = MatMatSolve_SeqDense_QR;
956   A->factortype    = MAT_FACTOR_QR;
957   if (m == n) {
958     A->ops->solvetranspose    = MatSolveTranspose_SeqDense_QR;
959     A->ops->matsolvetranspose = MatMatSolveTranspose_SeqDense_QR;
960   }
961 
962   PetscCall(PetscFree(A->solvertype));
963   PetscCall(PetscStrallocpy(MATSOLVERPETSC, &A->solvertype));
964 
965   PetscCall(PetscLogFlops(2.0 * min * min * (max - min / 3.0)));
966   PetscFunctionReturn(PETSC_SUCCESS);
967 }
968 
969 static PetscErrorCode MatQRFactorNumeric_SeqDense(Mat fact, Mat A, const MatFactorInfo *info_dummy)
970 {
971   MatFactorInfo info;
972 
973   PetscFunctionBegin;
974   info.fill = 1.0;
975 
976   PetscCall(MatDuplicateNoCreate_SeqDense(fact, A, MAT_COPY_VALUES));
977   PetscUseMethod(fact, "MatQRFactor_C", (Mat, IS, const MatFactorInfo *), (fact, NULL, &info));
978   PetscFunctionReturn(PETSC_SUCCESS);
979 }
980 
981 PetscErrorCode MatQRFactorSymbolic_SeqDense(Mat fact, Mat A, IS row, const MatFactorInfo *info)
982 {
983   PetscFunctionBegin;
984   fact->assembled    = PETSC_TRUE;
985   fact->preallocated = PETSC_TRUE;
986   PetscCall(PetscObjectComposeFunction((PetscObject)fact, "MatQRFactorNumeric_C", MatQRFactorNumeric_SeqDense));
987   PetscFunctionReturn(PETSC_SUCCESS);
988 }
989 
990 /* uses LAPACK */
991 PETSC_INTERN PetscErrorCode MatGetFactor_seqdense_petsc(Mat A, MatFactorType ftype, Mat *fact)
992 {
993   PetscFunctionBegin;
994   PetscCall(MatCreate(PetscObjectComm((PetscObject)A), fact));
995   PetscCall(MatSetSizes(*fact, A->rmap->n, A->cmap->n, A->rmap->n, A->cmap->n));
996   PetscCall(MatSetType(*fact, MATDENSE));
997   (*fact)->trivialsymbolic = PETSC_TRUE;
998   if (ftype == MAT_FACTOR_LU || ftype == MAT_FACTOR_ILU) {
999     (*fact)->ops->lufactorsymbolic  = MatLUFactorSymbolic_SeqDense;
1000     (*fact)->ops->ilufactorsymbolic = MatLUFactorSymbolic_SeqDense;
1001   } else if (ftype == MAT_FACTOR_CHOLESKY || ftype == MAT_FACTOR_ICC) {
1002     (*fact)->ops->choleskyfactorsymbolic = MatCholeskyFactorSymbolic_SeqDense;
1003   } else if (ftype == MAT_FACTOR_QR) {
1004     PetscCall(PetscObjectComposeFunction((PetscObject)*fact, "MatQRFactorSymbolic_C", MatQRFactorSymbolic_SeqDense));
1005   }
1006   (*fact)->factortype = ftype;
1007 
1008   PetscCall(PetscFree((*fact)->solvertype));
1009   PetscCall(PetscStrallocpy(MATSOLVERPETSC, &(*fact)->solvertype));
1010   PetscCall(PetscStrallocpy(MATORDERINGEXTERNAL, (char **)&(*fact)->preferredordering[MAT_FACTOR_LU]));
1011   PetscCall(PetscStrallocpy(MATORDERINGEXTERNAL, (char **)&(*fact)->preferredordering[MAT_FACTOR_ILU]));
1012   PetscCall(PetscStrallocpy(MATORDERINGEXTERNAL, (char **)&(*fact)->preferredordering[MAT_FACTOR_CHOLESKY]));
1013   PetscCall(PetscStrallocpy(MATORDERINGEXTERNAL, (char **)&(*fact)->preferredordering[MAT_FACTOR_ICC]));
1014   PetscFunctionReturn(PETSC_SUCCESS);
1015 }
1016 
1017 static PetscErrorCode MatSOR_SeqDense(Mat A, Vec bb, PetscReal omega, MatSORType flag, PetscReal shift, PetscInt its, PetscInt lits, Vec xx)
1018 {
1019   Mat_SeqDense      *mat = (Mat_SeqDense *)A->data;
1020   PetscScalar       *x, *v = mat->v, zero = 0.0, xt;
1021   const PetscScalar *b;
1022   PetscInt           m = A->rmap->n, i;
1023   PetscBLASInt       o = 1, bm = 0;
1024 
1025   PetscFunctionBegin;
1026 #if defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
1027   PetscCheck(A->offloadmask != PETSC_OFFLOAD_GPU, PETSC_COMM_SELF, PETSC_ERR_SUP, "Not implemented");
1028 #endif
1029   if (shift == -1) shift = 0.0; /* negative shift indicates do not error on zero diagonal; this code never zeros on zero diagonal */
1030   PetscCall(PetscBLASIntCast(m, &bm));
1031   if (flag & SOR_ZERO_INITIAL_GUESS) {
1032     /* this is a hack fix, should have another version without the second BLASdotu */
1033     PetscCall(VecSet(xx, zero));
1034   }
1035   PetscCall(VecGetArray(xx, &x));
1036   PetscCall(VecGetArrayRead(bb, &b));
1037   its = its * lits;
1038   PetscCheck(its > 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Relaxation requires global its %" PetscInt_FMT " and local its %" PetscInt_FMT " both positive", its, lits);
1039   while (its--) {
1040     if (flag & SOR_FORWARD_SWEEP || flag & SOR_LOCAL_FORWARD_SWEEP) {
1041       for (i = 0; i < m; i++) {
1042         PetscCallBLAS("BLASdotu", xt = b[i] - BLASdotu_(&bm, v + i, &bm, x, &o));
1043         x[i] = (1. - omega) * x[i] + (xt + v[i + i * m] * x[i]) * omega / (v[i + i * m] + shift);
1044       }
1045     }
1046     if (flag & SOR_BACKWARD_SWEEP || flag & SOR_LOCAL_BACKWARD_SWEEP) {
1047       for (i = m - 1; i >= 0; i--) {
1048         PetscCallBLAS("BLASdotu", xt = b[i] - BLASdotu_(&bm, v + i, &bm, x, &o));
1049         x[i] = (1. - omega) * x[i] + (xt + v[i + i * m] * x[i]) * omega / (v[i + i * m] + shift);
1050       }
1051     }
1052   }
1053   PetscCall(VecRestoreArrayRead(bb, &b));
1054   PetscCall(VecRestoreArray(xx, &x));
1055   PetscFunctionReturn(PETSC_SUCCESS);
1056 }
1057 
1058 static PetscErrorCode MatMultColumnRangeKernel_SeqDense(Mat A, Vec xx, Vec yy, PetscInt c_start, PetscInt c_end, PetscBool trans, PetscBool herm)
1059 {
1060   Mat_SeqDense      *mat = (Mat_SeqDense *)A->data;
1061   PetscScalar       *y, _DOne = 1.0, _DZero = 0.0;
1062   PetscBLASInt       m, n, _One             = 1;
1063   const PetscScalar *v = mat->v, *x;
1064 
1065   PetscFunctionBegin;
1066   PetscCall(PetscBLASIntCast(A->rmap->n, &m));
1067   PetscCall(PetscBLASIntCast(c_end - c_start, &n));
1068   PetscCall(VecGetArrayRead(xx, &x));
1069   PetscCall(VecGetArrayWrite(yy, &y));
1070   if (!m || !n) {
1071     PetscBLASInt i;
1072     if (trans)
1073       for (i = 0; i < n; i++) y[i] = 0.0;
1074     else
1075       for (i = 0; i < m; i++) y[i] = 0.0;
1076   } else {
1077     if (trans) {
1078       if (herm) PetscCallBLAS("BLASgemv", BLASgemv_("C", &m, &n, &_DOne, v + c_start * mat->lda, &mat->lda, x, &_One, &_DZero, y + c_start, &_One));
1079       else PetscCallBLAS("BLASgemv", BLASgemv_("T", &m, &n, &_DOne, v + c_start * mat->lda, &mat->lda, x, &_One, &_DZero, y + c_start, &_One));
1080     } else {
1081       PetscCallBLAS("BLASgemv", BLASgemv_("N", &m, &n, &_DOne, v + c_start * mat->lda, &mat->lda, x + c_start, &_One, &_DZero, y, &_One));
1082     }
1083     PetscCall(PetscLogFlops(2.0 * m * n - n));
1084   }
1085   PetscCall(VecRestoreArrayRead(xx, &x));
1086   PetscCall(VecRestoreArrayWrite(yy, &y));
1087   PetscFunctionReturn(PETSC_SUCCESS);
1088 }
1089 
1090 PetscErrorCode MatMultHermitianTransposeColumnRange_SeqDense(Mat A, Vec xx, Vec yy, PetscInt c_start, PetscInt c_end)
1091 {
1092   PetscFunctionBegin;
1093   PetscCall(MatMultColumnRangeKernel_SeqDense(A, xx, yy, c_start, c_end, PETSC_TRUE, PETSC_TRUE));
1094   PetscFunctionReturn(PETSC_SUCCESS);
1095 }
1096 
1097 PetscErrorCode MatMult_SeqDense(Mat A, Vec xx, Vec yy)
1098 {
1099   PetscFunctionBegin;
1100   PetscCall(MatMultColumnRangeKernel_SeqDense(A, xx, yy, 0, A->cmap->n, PETSC_FALSE, PETSC_FALSE));
1101   PetscFunctionReturn(PETSC_SUCCESS);
1102 }
1103 
1104 PetscErrorCode MatMultTranspose_SeqDense(Mat A, Vec xx, Vec yy)
1105 {
1106   PetscFunctionBegin;
1107   PetscCall(MatMultColumnRangeKernel_SeqDense(A, xx, yy, 0, A->cmap->n, PETSC_TRUE, PETSC_FALSE));
1108   PetscFunctionReturn(PETSC_SUCCESS);
1109 }
1110 
1111 PetscErrorCode MatMultHermitianTranspose_SeqDense(Mat A, Vec xx, Vec yy)
1112 {
1113   PetscFunctionBegin;
1114   PetscCall(MatMultColumnRangeKernel_SeqDense(A, xx, yy, 0, A->cmap->n, PETSC_TRUE, PETSC_TRUE));
1115   PetscFunctionReturn(PETSC_SUCCESS);
1116 }
1117 
1118 static PetscErrorCode MatMultAddColumnRangeKernel_SeqDense(Mat A, Vec xx, Vec zz, Vec yy, PetscInt c_start, PetscInt c_end, PetscBool trans, PetscBool herm)
1119 {
1120   Mat_SeqDense      *mat = (Mat_SeqDense *)A->data;
1121   const PetscScalar *v   = mat->v, *x;
1122   PetscScalar       *y, _DOne = 1.0;
1123   PetscBLASInt       m, n, _One = 1;
1124 
1125   PetscFunctionBegin;
1126   PetscCall(PetscBLASIntCast(A->rmap->n, &m));
1127   PetscCall(PetscBLASIntCast(c_end - c_start, &n));
1128   PetscCall(VecCopy(zz, yy));
1129   if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS);
1130   PetscCall(VecGetArray(yy, &y));
1131   PetscCall(VecGetArrayRead(xx, &x));
1132   if (trans) {
1133     if (herm) PetscCallBLAS("BLASgemv", BLASgemv_("C", &m, &n, &_DOne, v + c_start * mat->lda, &mat->lda, x, &_One, &_DOne, y + c_start, &_One));
1134     else PetscCallBLAS("BLASgemv", BLASgemv_("T", &m, &n, &_DOne, v + c_start * mat->lda, &mat->lda, x, &_One, &_DOne, y + c_start, &_One));
1135   } else {
1136     PetscCallBLAS("BLASgemv", BLASgemv_("N", &m, &n, &_DOne, v + c_start * mat->lda, &mat->lda, x + c_start, &_One, &_DOne, y, &_One));
1137   }
1138   PetscCall(VecRestoreArrayRead(xx, &x));
1139   PetscCall(VecRestoreArray(yy, &y));
1140   PetscCall(PetscLogFlops(2.0 * m * n));
1141   PetscFunctionReturn(PETSC_SUCCESS);
1142 }
1143 
1144 PetscErrorCode MatMultAddColumnRange_SeqDense(Mat A, Vec xx, Vec zz, Vec yy, PetscInt c_start, PetscInt c_end)
1145 {
1146   PetscFunctionBegin;
1147   PetscCall(MatMultAddColumnRangeKernel_SeqDense(A, xx, zz, yy, c_start, c_end, PETSC_FALSE, PETSC_FALSE));
1148   PetscFunctionReturn(PETSC_SUCCESS);
1149 }
1150 
1151 PetscErrorCode MatMultHermitianTransposeAddColumnRange_SeqDense(Mat A, Vec xx, Vec zz, Vec yy, PetscInt c_start, PetscInt c_end)
1152 {
1153   PetscFunctionBegin;
1154   PetscMPIInt rank;
1155   PetscCallMPI(MPI_Comm_rank(MPI_COMM_WORLD, &rank));
1156   PetscCall(MatMultAddColumnRangeKernel_SeqDense(A, xx, zz, yy, c_start, c_end, PETSC_TRUE, PETSC_TRUE));
1157   PetscFunctionReturn(PETSC_SUCCESS);
1158 }
1159 
1160 PetscErrorCode MatMultAdd_SeqDense(Mat A, Vec xx, Vec zz, Vec yy)
1161 {
1162   PetscFunctionBegin;
1163   PetscCall(MatMultAddColumnRangeKernel_SeqDense(A, xx, zz, yy, 0, A->cmap->n, PETSC_FALSE, PETSC_FALSE));
1164   PetscFunctionReturn(PETSC_SUCCESS);
1165 }
1166 
1167 PetscErrorCode MatMultTransposeAdd_SeqDense(Mat A, Vec xx, Vec zz, Vec yy)
1168 {
1169   PetscFunctionBegin;
1170   PetscCall(MatMultAddColumnRangeKernel_SeqDense(A, xx, zz, yy, 0, A->cmap->n, PETSC_TRUE, PETSC_FALSE));
1171   PetscFunctionReturn(PETSC_SUCCESS);
1172 }
1173 
1174 PetscErrorCode MatMultHermitianTransposeAdd_SeqDense(Mat A, Vec xx, Vec zz, Vec yy)
1175 {
1176   PetscFunctionBegin;
1177   PetscCall(MatMultAddColumnRangeKernel_SeqDense(A, xx, zz, yy, 0, A->cmap->n, PETSC_TRUE, PETSC_TRUE));
1178   PetscFunctionReturn(PETSC_SUCCESS);
1179 }
1180 
1181 static PetscErrorCode MatGetRow_SeqDense(Mat A, PetscInt row, PetscInt *ncols, PetscInt **cols, PetscScalar **vals)
1182 {
1183   Mat_SeqDense *mat = (Mat_SeqDense *)A->data;
1184   PetscInt      i;
1185 
1186   PetscFunctionBegin;
1187   if (ncols) *ncols = A->cmap->n;
1188   if (cols) {
1189     PetscCall(PetscMalloc1(A->cmap->n, cols));
1190     for (i = 0; i < A->cmap->n; i++) (*cols)[i] = i;
1191   }
1192   if (vals) {
1193     const PetscScalar *v;
1194 
1195     PetscCall(MatDenseGetArrayRead(A, &v));
1196     PetscCall(PetscMalloc1(A->cmap->n, vals));
1197     v += row;
1198     for (i = 0; i < A->cmap->n; i++) {
1199       (*vals)[i] = *v;
1200       v += mat->lda;
1201     }
1202     PetscCall(MatDenseRestoreArrayRead(A, &v));
1203   }
1204   PetscFunctionReturn(PETSC_SUCCESS);
1205 }
1206 
1207 static PetscErrorCode MatRestoreRow_SeqDense(Mat A, PetscInt row, PetscInt *ncols, PetscInt **cols, PetscScalar **vals)
1208 {
1209   PetscFunctionBegin;
1210   if (cols) PetscCall(PetscFree(*cols));
1211   if (vals) PetscCall(PetscFree(*vals));
1212   PetscFunctionReturn(PETSC_SUCCESS);
1213 }
1214 
1215 static PetscErrorCode MatSetValues_SeqDense(Mat A, PetscInt m, const PetscInt indexm[], PetscInt n, const PetscInt indexn[], const PetscScalar v[], InsertMode addv)
1216 {
1217   Mat_SeqDense *mat = (Mat_SeqDense *)A->data;
1218   PetscScalar  *av;
1219   PetscInt      i, j, idx = 0;
1220 #if defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
1221   PetscOffloadMask oldf;
1222 #endif
1223 
1224   PetscFunctionBegin;
1225   PetscCall(MatDenseGetArray(A, &av));
1226   if (!mat->roworiented) {
1227     if (addv == INSERT_VALUES) {
1228       for (j = 0; j < n; j++) {
1229         if (indexn[j] < 0) {
1230           idx += m;
1231           continue;
1232         }
1233         PetscCheck(indexn[j] < A->cmap->n, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Column too large: col %" PetscInt_FMT " max %" PetscInt_FMT, indexn[j], A->cmap->n - 1);
1234         for (i = 0; i < m; i++) {
1235           if (indexm[i] < 0) {
1236             idx++;
1237             continue;
1238           }
1239           PetscCheck(indexm[i] < A->rmap->n, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Row too large: row %" PetscInt_FMT " max %" PetscInt_FMT, indexm[i], A->rmap->n - 1);
1240           av[indexn[j] * mat->lda + indexm[i]] = v ? v[idx++] : (idx++, 0.0);
1241         }
1242       }
1243     } else {
1244       for (j = 0; j < n; j++) {
1245         if (indexn[j] < 0) {
1246           idx += m;
1247           continue;
1248         }
1249         PetscCheck(indexn[j] < A->cmap->n, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Column too large: col %" PetscInt_FMT " max %" PetscInt_FMT, indexn[j], A->cmap->n - 1);
1250         for (i = 0; i < m; i++) {
1251           if (indexm[i] < 0) {
1252             idx++;
1253             continue;
1254           }
1255           PetscCheck(indexm[i] < A->rmap->n, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Row too large: row %" PetscInt_FMT " max %" PetscInt_FMT, indexm[i], A->rmap->n - 1);
1256           av[indexn[j] * mat->lda + indexm[i]] += v ? v[idx++] : (idx++, 0.0);
1257         }
1258       }
1259     }
1260   } else {
1261     if (addv == INSERT_VALUES) {
1262       for (i = 0; i < m; i++) {
1263         if (indexm[i] < 0) {
1264           idx += n;
1265           continue;
1266         }
1267         PetscCheck(indexm[i] < A->rmap->n, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Row too large: row %" PetscInt_FMT " max %" PetscInt_FMT, indexm[i], A->rmap->n - 1);
1268         for (j = 0; j < n; j++) {
1269           if (indexn[j] < 0) {
1270             idx++;
1271             continue;
1272           }
1273           PetscCheck(indexn[j] < A->cmap->n, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Column too large: col %" PetscInt_FMT " max %" PetscInt_FMT, indexn[j], A->cmap->n - 1);
1274           av[indexn[j] * mat->lda + indexm[i]] = v ? v[idx++] : (idx++, 0.0);
1275         }
1276       }
1277     } else {
1278       for (i = 0; i < m; i++) {
1279         if (indexm[i] < 0) {
1280           idx += n;
1281           continue;
1282         }
1283         PetscCheck(indexm[i] < A->rmap->n, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Row too large: row %" PetscInt_FMT " max %" PetscInt_FMT, indexm[i], A->rmap->n - 1);
1284         for (j = 0; j < n; j++) {
1285           if (indexn[j] < 0) {
1286             idx++;
1287             continue;
1288           }
1289           PetscCheck(indexn[j] < A->cmap->n, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Column too large: col %" PetscInt_FMT " max %" PetscInt_FMT, indexn[j], A->cmap->n - 1);
1290           av[indexn[j] * mat->lda + indexm[i]] += v ? v[idx++] : (idx++, 0.0);
1291         }
1292       }
1293     }
1294   }
1295   /* hack to prevent unneeded copy to the GPU while returning the array */
1296 #if defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
1297   oldf           = A->offloadmask;
1298   A->offloadmask = PETSC_OFFLOAD_GPU;
1299 #endif
1300   PetscCall(MatDenseRestoreArray(A, &av));
1301 #if defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
1302   A->offloadmask = (oldf == PETSC_OFFLOAD_UNALLOCATED ? PETSC_OFFLOAD_UNALLOCATED : PETSC_OFFLOAD_CPU);
1303 #endif
1304   PetscFunctionReturn(PETSC_SUCCESS);
1305 }
1306 
1307 static PetscErrorCode MatGetValues_SeqDense(Mat A, PetscInt m, const PetscInt indexm[], PetscInt n, const PetscInt indexn[], PetscScalar v[])
1308 {
1309   Mat_SeqDense      *mat = (Mat_SeqDense *)A->data;
1310   const PetscScalar *vv;
1311   PetscInt           i, j;
1312 
1313   PetscFunctionBegin;
1314   PetscCall(MatDenseGetArrayRead(A, &vv));
1315   /* row-oriented output */
1316   for (i = 0; i < m; i++) {
1317     if (indexm[i] < 0) {
1318       v += n;
1319       continue;
1320     }
1321     PetscCheck(indexm[i] < A->rmap->n, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Row %" PetscInt_FMT " requested larger than number rows %" PetscInt_FMT, indexm[i], A->rmap->n);
1322     for (j = 0; j < n; j++) {
1323       if (indexn[j] < 0) {
1324         v++;
1325         continue;
1326       }
1327       PetscCheck(indexn[j] < A->cmap->n, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Column %" PetscInt_FMT " requested larger than number columns %" PetscInt_FMT, indexn[j], A->cmap->n);
1328       *v++ = vv[indexn[j] * mat->lda + indexm[i]];
1329     }
1330   }
1331   PetscCall(MatDenseRestoreArrayRead(A, &vv));
1332   PetscFunctionReturn(PETSC_SUCCESS);
1333 }
1334 
1335 PetscErrorCode MatView_Dense_Binary(Mat mat, PetscViewer viewer)
1336 {
1337   PetscBool          skipHeader;
1338   PetscViewerFormat  format;
1339   PetscInt           header[4], M, N, m, lda, i, j;
1340   PetscCount         k;
1341   const PetscScalar *v;
1342   PetscScalar       *vwork;
1343 
1344   PetscFunctionBegin;
1345   PetscCall(PetscViewerSetUp(viewer));
1346   PetscCall(PetscViewerBinaryGetSkipHeader(viewer, &skipHeader));
1347   PetscCall(PetscViewerGetFormat(viewer, &format));
1348   if (skipHeader) format = PETSC_VIEWER_NATIVE;
1349 
1350   PetscCall(MatGetSize(mat, &M, &N));
1351 
1352   /* write matrix header */
1353   header[0] = MAT_FILE_CLASSID;
1354   header[1] = M;
1355   header[2] = N;
1356   header[3] = (format == PETSC_VIEWER_NATIVE) ? MATRIX_BINARY_FORMAT_DENSE : M * N;
1357   if (!skipHeader) PetscCall(PetscViewerBinaryWrite(viewer, header, 4, PETSC_INT));
1358 
1359   PetscCall(MatGetLocalSize(mat, &m, NULL));
1360   if (format != PETSC_VIEWER_NATIVE) {
1361     PetscInt nnz = m * N, *iwork;
1362     /* store row lengths for each row */
1363     PetscCall(PetscMalloc1(nnz, &iwork));
1364     for (i = 0; i < m; i++) iwork[i] = N;
1365     PetscCall(PetscViewerBinaryWriteAll(viewer, iwork, m, PETSC_DETERMINE, PETSC_DETERMINE, PETSC_INT));
1366     /* store column indices (zero start index) */
1367     for (k = 0, i = 0; i < m; i++)
1368       for (j = 0; j < N; j++, k++) iwork[k] = j;
1369     PetscCall(PetscViewerBinaryWriteAll(viewer, iwork, nnz, PETSC_DETERMINE, PETSC_DETERMINE, PETSC_INT));
1370     PetscCall(PetscFree(iwork));
1371   }
1372   /* store matrix values as a dense matrix in row major order */
1373   PetscCall(PetscMalloc1(m * N, &vwork));
1374   PetscCall(MatDenseGetArrayRead(mat, &v));
1375   PetscCall(MatDenseGetLDA(mat, &lda));
1376   for (k = 0, i = 0; i < m; i++)
1377     for (j = 0; j < N; j++, k++) vwork[k] = v[i + (size_t)lda * j];
1378   PetscCall(MatDenseRestoreArrayRead(mat, &v));
1379   PetscCall(PetscViewerBinaryWriteAll(viewer, vwork, m * N, PETSC_DETERMINE, PETSC_DETERMINE, PETSC_SCALAR));
1380   PetscCall(PetscFree(vwork));
1381   PetscFunctionReturn(PETSC_SUCCESS);
1382 }
1383 
1384 PetscErrorCode MatLoad_Dense_Binary(Mat mat, PetscViewer viewer)
1385 {
1386   PetscBool    skipHeader;
1387   PetscInt     header[4], M, N, m, nz, lda, i, j, k;
1388   PetscInt     rows, cols;
1389   PetscScalar *v, *vwork;
1390 
1391   PetscFunctionBegin;
1392   PetscCall(PetscViewerSetUp(viewer));
1393   PetscCall(PetscViewerBinaryGetSkipHeader(viewer, &skipHeader));
1394 
1395   if (!skipHeader) {
1396     PetscCall(PetscViewerBinaryRead(viewer, header, 4, NULL, PETSC_INT));
1397     PetscCheck(header[0] == MAT_FILE_CLASSID, PetscObjectComm((PetscObject)viewer), PETSC_ERR_FILE_UNEXPECTED, "Not a matrix object in file");
1398     M = header[1];
1399     N = header[2];
1400     PetscCheck(M >= 0, PetscObjectComm((PetscObject)viewer), PETSC_ERR_FILE_UNEXPECTED, "Matrix row size (%" PetscInt_FMT ") in file is negative", M);
1401     PetscCheck(N >= 0, PetscObjectComm((PetscObject)viewer), PETSC_ERR_FILE_UNEXPECTED, "Matrix column size (%" PetscInt_FMT ") in file is negative", N);
1402     nz = header[3];
1403     PetscCheck(nz == MATRIX_BINARY_FORMAT_DENSE || nz >= 0, PetscObjectComm((PetscObject)viewer), PETSC_ERR_FILE_UNEXPECTED, "Unknown matrix format %" PetscInt_FMT " in file", nz);
1404   } else {
1405     PetscCall(MatGetSize(mat, &M, &N));
1406     PetscCheck(M >= 0 && N >= 0, PETSC_COMM_SELF, PETSC_ERR_USER, "Matrix binary file header was skipped, thus the user must specify the global sizes of input matrix");
1407     nz = MATRIX_BINARY_FORMAT_DENSE;
1408   }
1409 
1410   /* setup global sizes if not set */
1411   if (mat->rmap->N < 0) mat->rmap->N = M;
1412   if (mat->cmap->N < 0) mat->cmap->N = N;
1413   PetscCall(MatSetUp(mat));
1414   /* check if global sizes are correct */
1415   PetscCall(MatGetSize(mat, &rows, &cols));
1416   PetscCheck(M == rows && N == cols, PetscObjectComm((PetscObject)viewer), PETSC_ERR_FILE_UNEXPECTED, "Matrix in file of different sizes (%" PetscInt_FMT ", %" PetscInt_FMT ") than the input matrix (%" PetscInt_FMT ", %" PetscInt_FMT ")", M, N, rows, cols);
1417 
1418   PetscCall(MatGetSize(mat, NULL, &N));
1419   PetscCall(MatGetLocalSize(mat, &m, NULL));
1420   PetscCall(MatDenseGetArray(mat, &v));
1421   PetscCall(MatDenseGetLDA(mat, &lda));
1422   if (nz == MATRIX_BINARY_FORMAT_DENSE) { /* matrix in file is dense format */
1423     PetscCount nnz = (size_t)m * N;
1424     /* read in matrix values */
1425     PetscCall(PetscMalloc1(nnz, &vwork));
1426     PetscCall(PetscViewerBinaryReadAll(viewer, vwork, nnz, PETSC_DETERMINE, PETSC_DETERMINE, PETSC_SCALAR));
1427     /* store values in column major order */
1428     for (j = 0; j < N; j++)
1429       for (i = 0; i < m; i++) v[i + (size_t)lda * j] = vwork[(size_t)i * N + j];
1430     PetscCall(PetscFree(vwork));
1431   } else { /* matrix in file is sparse format */
1432     PetscInt nnz = 0, *rlens, *icols;
1433     /* read in row lengths */
1434     PetscCall(PetscMalloc1(m, &rlens));
1435     PetscCall(PetscViewerBinaryReadAll(viewer, rlens, m, PETSC_DETERMINE, PETSC_DETERMINE, PETSC_INT));
1436     for (i = 0; i < m; i++) nnz += rlens[i];
1437     /* read in column indices and values */
1438     PetscCall(PetscMalloc2(nnz, &icols, nnz, &vwork));
1439     PetscCall(PetscViewerBinaryReadAll(viewer, icols, nnz, PETSC_DETERMINE, PETSC_DETERMINE, PETSC_INT));
1440     PetscCall(PetscViewerBinaryReadAll(viewer, vwork, nnz, PETSC_DETERMINE, PETSC_DETERMINE, PETSC_SCALAR));
1441     /* store values in column major order */
1442     for (k = 0, i = 0; i < m; i++)
1443       for (j = 0; j < rlens[i]; j++, k++) v[i + lda * icols[k]] = vwork[k];
1444     PetscCall(PetscFree(rlens));
1445     PetscCall(PetscFree2(icols, vwork));
1446   }
1447   PetscCall(MatDenseRestoreArray(mat, &v));
1448   PetscCall(MatAssemblyBegin(mat, MAT_FINAL_ASSEMBLY));
1449   PetscCall(MatAssemblyEnd(mat, MAT_FINAL_ASSEMBLY));
1450   PetscFunctionReturn(PETSC_SUCCESS);
1451 }
1452 
1453 static PetscErrorCode MatLoad_SeqDense(Mat newMat, PetscViewer viewer)
1454 {
1455   PetscBool isbinary, ishdf5;
1456 
1457   PetscFunctionBegin;
1458   PetscValidHeaderSpecific(newMat, MAT_CLASSID, 1);
1459   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
1460   /* force binary viewer to load .info file if it has not yet done so */
1461   PetscCall(PetscViewerSetUp(viewer));
1462   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERBINARY, &isbinary));
1463   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5));
1464   if (isbinary) {
1465     PetscCall(MatLoad_Dense_Binary(newMat, viewer));
1466   } else if (ishdf5) {
1467 #if defined(PETSC_HAVE_HDF5)
1468     PetscCall(MatLoad_Dense_HDF5(newMat, viewer));
1469 #else
1470     SETERRQ(PetscObjectComm((PetscObject)newMat), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5");
1471 #endif
1472   } else {
1473     SETERRQ(PetscObjectComm((PetscObject)newMat), PETSC_ERR_SUP, "Viewer type %s not yet supported for reading %s matrices", ((PetscObject)viewer)->type_name, ((PetscObject)newMat)->type_name);
1474   }
1475   PetscFunctionReturn(PETSC_SUCCESS);
1476 }
1477 
1478 static PetscErrorCode MatView_SeqDense_ASCII(Mat A, PetscViewer viewer)
1479 {
1480   Mat_SeqDense     *a = (Mat_SeqDense *)A->data;
1481   PetscInt          i, j;
1482   const char       *name;
1483   PetscScalar      *v, *av;
1484   PetscViewerFormat format;
1485 #if defined(PETSC_USE_COMPLEX)
1486   PetscBool allreal = PETSC_TRUE;
1487 #endif
1488 
1489   PetscFunctionBegin;
1490   PetscCall(MatDenseGetArrayRead(A, (const PetscScalar **)&av));
1491   PetscCall(PetscViewerGetFormat(viewer, &format));
1492   if (format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL) {
1493     PetscFunctionReturn(PETSC_SUCCESS); /* do nothing for now */
1494   } else if (format == PETSC_VIEWER_ASCII_COMMON) {
1495     PetscCall(PetscViewerASCIIUseTabs(viewer, PETSC_FALSE));
1496     for (i = 0; i < A->rmap->n; i++) {
1497       v = av + i;
1498       PetscCall(PetscViewerASCIIPrintf(viewer, "row %" PetscInt_FMT ":", i));
1499       for (j = 0; j < A->cmap->n; j++) {
1500 #if defined(PETSC_USE_COMPLEX)
1501         if (PetscRealPart(*v) != 0.0 && PetscImaginaryPart(*v) != 0.0) {
1502           PetscCall(PetscViewerASCIIPrintf(viewer, " (%" PetscInt_FMT ", %g + %g i) ", j, (double)PetscRealPart(*v), (double)PetscImaginaryPart(*v)));
1503         } else if (PetscRealPart(*v)) {
1504           PetscCall(PetscViewerASCIIPrintf(viewer, " (%" PetscInt_FMT ", %g) ", j, (double)PetscRealPart(*v)));
1505         }
1506 #else
1507         if (*v) PetscCall(PetscViewerASCIIPrintf(viewer, " (%" PetscInt_FMT ", %g) ", j, (double)*v));
1508 #endif
1509         v += a->lda;
1510       }
1511       PetscCall(PetscViewerASCIIPrintf(viewer, "\n"));
1512     }
1513     PetscCall(PetscViewerASCIIUseTabs(viewer, PETSC_TRUE));
1514   } else {
1515     PetscCall(PetscViewerASCIIUseTabs(viewer, PETSC_FALSE));
1516 #if defined(PETSC_USE_COMPLEX)
1517     /* determine if matrix has all real values */
1518     for (j = 0; j < A->cmap->n; j++) {
1519       v = av + j * a->lda;
1520       for (i = 0; i < A->rmap->n; i++) {
1521         if (PetscImaginaryPart(v[i])) {
1522           allreal = PETSC_FALSE;
1523           break;
1524         }
1525       }
1526     }
1527 #endif
1528     if (format == PETSC_VIEWER_ASCII_MATLAB) {
1529       PetscCall(PetscObjectGetName((PetscObject)A, &name));
1530       PetscCall(PetscViewerASCIIPrintf(viewer, "%% Size = %" PetscInt_FMT " %" PetscInt_FMT " \n", A->rmap->n, A->cmap->n));
1531       PetscCall(PetscViewerASCIIPrintf(viewer, "%s = zeros(%" PetscInt_FMT ",%" PetscInt_FMT ");\n", name, A->rmap->n, A->cmap->n));
1532       PetscCall(PetscViewerASCIIPrintf(viewer, "%s = [\n", name));
1533     }
1534 
1535     for (i = 0; i < A->rmap->n; i++) {
1536       v = av + i;
1537       for (j = 0; j < A->cmap->n; j++) {
1538 #if defined(PETSC_USE_COMPLEX)
1539         if (allreal) {
1540           PetscCall(PetscViewerASCIIPrintf(viewer, "%18.16e ", (double)PetscRealPart(*v)));
1541         } else {
1542           PetscCall(PetscViewerASCIIPrintf(viewer, "%18.16e + %18.16ei ", (double)PetscRealPart(*v), (double)PetscImaginaryPart(*v)));
1543         }
1544 #else
1545         PetscCall(PetscViewerASCIIPrintf(viewer, "%18.16e ", (double)*v));
1546 #endif
1547         v += a->lda;
1548       }
1549       PetscCall(PetscViewerASCIIPrintf(viewer, "\n"));
1550     }
1551     if (format == PETSC_VIEWER_ASCII_MATLAB) PetscCall(PetscViewerASCIIPrintf(viewer, "];\n"));
1552     PetscCall(PetscViewerASCIIUseTabs(viewer, PETSC_TRUE));
1553   }
1554   PetscCall(MatDenseRestoreArrayRead(A, (const PetscScalar **)&av));
1555   PetscCall(PetscViewerFlush(viewer));
1556   PetscFunctionReturn(PETSC_SUCCESS);
1557 }
1558 
1559 #include <petscdraw.h>
1560 static PetscErrorCode MatView_SeqDense_Draw_Zoom(PetscDraw draw, void *Aa)
1561 {
1562   Mat                A = (Mat)Aa;
1563   PetscInt           m = A->rmap->n, n = A->cmap->n, i, j;
1564   int                color = PETSC_DRAW_WHITE;
1565   const PetscScalar *v;
1566   PetscViewer        viewer;
1567   PetscReal          xl, yl, xr, yr, x_l, x_r, y_l, y_r;
1568   PetscViewerFormat  format;
1569 
1570   PetscFunctionBegin;
1571   PetscCall(PetscObjectQuery((PetscObject)A, "Zoomviewer", (PetscObject *)&viewer));
1572   PetscCall(PetscViewerGetFormat(viewer, &format));
1573   PetscCall(PetscDrawGetCoordinates(draw, &xl, &yl, &xr, &yr));
1574 
1575   /* Loop over matrix elements drawing boxes */
1576   PetscCall(MatDenseGetArrayRead(A, &v));
1577   if (format != PETSC_VIEWER_DRAW_CONTOUR) {
1578     PetscDrawCollectiveBegin(draw);
1579     /* Blue for negative and Red for positive */
1580     for (j = 0; j < n; j++) {
1581       x_l = j;
1582       x_r = x_l + 1.0;
1583       for (i = 0; i < m; i++) {
1584         y_l = m - i - 1.0;
1585         y_r = y_l + 1.0;
1586         if (PetscRealPart(v[j * m + i]) > 0.) color = PETSC_DRAW_RED;
1587         else if (PetscRealPart(v[j * m + i]) < 0.) color = PETSC_DRAW_BLUE;
1588         else continue;
1589         PetscCall(PetscDrawRectangle(draw, x_l, y_l, x_r, y_r, color, color, color, color));
1590       }
1591     }
1592     PetscDrawCollectiveEnd(draw);
1593   } else {
1594     /* use contour shading to indicate magnitude of values */
1595     /* first determine max of all nonzero values */
1596     PetscReal minv = 0.0, maxv = 0.0;
1597     PetscDraw popup;
1598 
1599     for (i = 0; i < m * n; i++) {
1600       if (PetscAbsScalar(v[i]) > maxv) maxv = PetscAbsScalar(v[i]);
1601     }
1602     if (minv >= maxv) maxv = minv + PETSC_SMALL;
1603     PetscCall(PetscDrawGetPopup(draw, &popup));
1604     PetscCall(PetscDrawScalePopup(popup, minv, maxv));
1605 
1606     PetscDrawCollectiveBegin(draw);
1607     for (j = 0; j < n; j++) {
1608       x_l = j;
1609       x_r = x_l + 1.0;
1610       for (i = 0; i < m; i++) {
1611         y_l   = m - i - 1.0;
1612         y_r   = y_l + 1.0;
1613         color = PetscDrawRealToColor(PetscAbsScalar(v[j * m + i]), minv, maxv);
1614         PetscCall(PetscDrawRectangle(draw, x_l, y_l, x_r, y_r, color, color, color, color));
1615       }
1616     }
1617     PetscDrawCollectiveEnd(draw);
1618   }
1619   PetscCall(MatDenseRestoreArrayRead(A, &v));
1620   PetscFunctionReturn(PETSC_SUCCESS);
1621 }
1622 
1623 static PetscErrorCode MatView_SeqDense_Draw(Mat A, PetscViewer viewer)
1624 {
1625   PetscDraw draw;
1626   PetscBool isnull;
1627   PetscReal xr, yr, xl, yl, h, w;
1628 
1629   PetscFunctionBegin;
1630   PetscCall(PetscViewerDrawGetDraw(viewer, 0, &draw));
1631   PetscCall(PetscDrawIsNull(draw, &isnull));
1632   if (isnull) PetscFunctionReturn(PETSC_SUCCESS);
1633 
1634   xr = A->cmap->n;
1635   yr = A->rmap->n;
1636   h  = yr / 10.0;
1637   w  = xr / 10.0;
1638   xr += w;
1639   yr += h;
1640   xl = -w;
1641   yl = -h;
1642   PetscCall(PetscDrawSetCoordinates(draw, xl, yl, xr, yr));
1643   PetscCall(PetscObjectCompose((PetscObject)A, "Zoomviewer", (PetscObject)viewer));
1644   PetscCall(PetscDrawZoom(draw, MatView_SeqDense_Draw_Zoom, A));
1645   PetscCall(PetscObjectCompose((PetscObject)A, "Zoomviewer", NULL));
1646   PetscCall(PetscDrawSave(draw));
1647   PetscFunctionReturn(PETSC_SUCCESS);
1648 }
1649 
1650 PetscErrorCode MatView_SeqDense(Mat A, PetscViewer viewer)
1651 {
1652   PetscBool iascii, isbinary, isdraw;
1653 
1654   PetscFunctionBegin;
1655   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
1656   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERBINARY, &isbinary));
1657   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERDRAW, &isdraw));
1658   if (iascii) PetscCall(MatView_SeqDense_ASCII(A, viewer));
1659   else if (isbinary) PetscCall(MatView_Dense_Binary(A, viewer));
1660   else if (isdraw) PetscCall(MatView_SeqDense_Draw(A, viewer));
1661   PetscFunctionReturn(PETSC_SUCCESS);
1662 }
1663 
1664 static PetscErrorCode MatDensePlaceArray_SeqDense(Mat A, const PetscScalar *array)
1665 {
1666   Mat_SeqDense *a = (Mat_SeqDense *)A->data;
1667 
1668   PetscFunctionBegin;
1669   PetscCheck(!a->vecinuse, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Need to call MatDenseRestoreColumnVec() first");
1670   PetscCheck(!a->matinuse, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Need to call MatDenseRestoreSubMatrix() first");
1671   PetscCheck(!a->unplacedarray, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Need to call MatDenseResetArray() first");
1672   a->unplacedarray       = a->v;
1673   a->unplaced_user_alloc = a->user_alloc;
1674   a->v                   = (PetscScalar *)array;
1675   a->user_alloc          = PETSC_TRUE;
1676 #if defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
1677   A->offloadmask = PETSC_OFFLOAD_CPU;
1678 #endif
1679   PetscFunctionReturn(PETSC_SUCCESS);
1680 }
1681 
1682 static PetscErrorCode MatDenseResetArray_SeqDense(Mat A)
1683 {
1684   Mat_SeqDense *a = (Mat_SeqDense *)A->data;
1685 
1686   PetscFunctionBegin;
1687   PetscCheck(!a->vecinuse, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Need to call MatDenseRestoreColumnVec() first");
1688   PetscCheck(!a->matinuse, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Need to call MatDenseRestoreSubMatrix() first");
1689   a->v             = a->unplacedarray;
1690   a->user_alloc    = a->unplaced_user_alloc;
1691   a->unplacedarray = NULL;
1692 #if defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
1693   A->offloadmask = PETSC_OFFLOAD_CPU;
1694 #endif
1695   PetscFunctionReturn(PETSC_SUCCESS);
1696 }
1697 
1698 static PetscErrorCode MatDenseReplaceArray_SeqDense(Mat A, const PetscScalar *array)
1699 {
1700   Mat_SeqDense *a = (Mat_SeqDense *)A->data;
1701 
1702   PetscFunctionBegin;
1703   PetscCheck(!a->vecinuse, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Need to call MatDenseRestoreColumnVec() first");
1704   PetscCheck(!a->matinuse, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Need to call MatDenseRestoreSubMatrix() first");
1705   if (!a->user_alloc) PetscCall(PetscFree(a->v));
1706   a->v          = (PetscScalar *)array;
1707   a->user_alloc = PETSC_FALSE;
1708 #if defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
1709   A->offloadmask = PETSC_OFFLOAD_CPU;
1710 #endif
1711   PetscFunctionReturn(PETSC_SUCCESS);
1712 }
1713 
1714 PetscErrorCode MatDestroy_SeqDense(Mat mat)
1715 {
1716   Mat_SeqDense *l = (Mat_SeqDense *)mat->data;
1717 
1718   PetscFunctionBegin;
1719   PetscCall(PetscLogObjectState((PetscObject)mat, "Rows %" PetscInt_FMT " Cols %" PetscInt_FMT, mat->rmap->n, mat->cmap->n));
1720   PetscCall(VecDestroy(&l->qrrhs));
1721   PetscCall(PetscFree(l->tau));
1722   PetscCall(PetscFree(l->pivots));
1723   PetscCall(PetscFree(l->fwork));
1724   if (!l->user_alloc) PetscCall(PetscFree(l->v));
1725   if (!l->unplaced_user_alloc) PetscCall(PetscFree(l->unplacedarray));
1726   PetscCheck(!l->vecinuse, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Need to call MatDenseRestoreColumnVec() first");
1727   PetscCheck(!l->matinuse, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Need to call MatDenseRestoreSubMatrix() first");
1728   PetscCall(VecDestroy(&l->cvec));
1729   PetscCall(MatDestroy(&l->cmat));
1730   PetscCall(PetscFree(mat->data));
1731 
1732   PetscCall(PetscObjectChangeTypeName((PetscObject)mat, NULL));
1733   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatQRFactor_C", NULL));
1734   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatQRFactorSymbolic_C", NULL));
1735   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatQRFactorNumeric_C", NULL));
1736   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatDenseGetLDA_C", NULL));
1737   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatDenseSetLDA_C", NULL));
1738   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatDenseGetArray_C", NULL));
1739   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatDenseRestoreArray_C", NULL));
1740   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatDensePlaceArray_C", NULL));
1741   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatDenseResetArray_C", NULL));
1742   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatDenseReplaceArray_C", NULL));
1743   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatDenseGetArrayRead_C", NULL));
1744   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatDenseRestoreArrayRead_C", NULL));
1745   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatDenseGetArrayWrite_C", NULL));
1746   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatDenseRestoreArrayWrite_C", NULL));
1747   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatConvert_seqdense_seqaij_C", NULL));
1748 #if defined(PETSC_HAVE_ELEMENTAL)
1749   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatConvert_seqdense_elemental_C", NULL));
1750 #endif
1751 #if defined(PETSC_HAVE_SCALAPACK)
1752   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatConvert_seqdense_scalapack_C", NULL));
1753 #endif
1754 #if defined(PETSC_HAVE_CUDA)
1755   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatConvert_seqdense_seqdensecuda_C", NULL));
1756   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatProductSetFromOptions_seqdensecuda_seqdensecuda_C", NULL));
1757   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatProductSetFromOptions_seqdensecuda_seqdense_C", NULL));
1758   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatProductSetFromOptions_seqdense_seqdensecuda_C", NULL));
1759 #endif
1760 #if defined(PETSC_HAVE_HIP)
1761   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatConvert_seqdense_seqdensehip_C", NULL));
1762   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatProductSetFromOptions_seqdensehip_seqdensehip_C", NULL));
1763   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatProductSetFromOptions_seqdensehip_seqdense_C", NULL));
1764   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatProductSetFromOptions_seqdense_seqdensehip_C", NULL));
1765 #endif
1766   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatSeqDenseSetPreallocation_C", NULL));
1767   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatProductSetFromOptions_seqaij_seqdense_C", NULL));
1768   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatProductSetFromOptions_seqdense_seqdense_C", NULL));
1769   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatProductSetFromOptions_seqbaij_seqdense_C", NULL));
1770   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatProductSetFromOptions_seqsbaij_seqdense_C", NULL));
1771 
1772   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatDenseGetColumn_C", NULL));
1773   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatDenseRestoreColumn_C", NULL));
1774   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatDenseGetColumnVec_C", NULL));
1775   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatDenseRestoreColumnVec_C", NULL));
1776   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatDenseGetColumnVecRead_C", NULL));
1777   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatDenseRestoreColumnVecRead_C", NULL));
1778   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatDenseGetColumnVecWrite_C", NULL));
1779   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatDenseRestoreColumnVecWrite_C", NULL));
1780   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatDenseGetSubMatrix_C", NULL));
1781   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatDenseRestoreSubMatrix_C", NULL));
1782   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatMultAddColumnRange_C", NULL));
1783   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatMultHermitianTransposeColumnRange_C", NULL));
1784   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatMultHermitianTransposeAddColumnRange_C", NULL));
1785   PetscFunctionReturn(PETSC_SUCCESS);
1786 }
1787 
1788 static PetscErrorCode MatTranspose_SeqDense(Mat A, MatReuse reuse, Mat *matout)
1789 {
1790   Mat_SeqDense *mat = (Mat_SeqDense *)A->data;
1791   PetscInt      k, j, m = A->rmap->n, M = mat->lda, n = A->cmap->n;
1792   PetscScalar  *v, tmp;
1793 
1794   PetscFunctionBegin;
1795   if (reuse == MAT_REUSE_MATRIX) PetscCall(MatTransposeCheckNonzeroState_Private(A, *matout));
1796   if (reuse == MAT_INPLACE_MATRIX) {
1797     if (m == n) { /* in place transpose */
1798       PetscCall(MatDenseGetArray(A, &v));
1799       for (j = 0; j < m; j++) {
1800         for (k = 0; k < j; k++) {
1801           tmp          = v[j + k * M];
1802           v[j + k * M] = v[k + j * M];
1803           v[k + j * M] = tmp;
1804         }
1805       }
1806       PetscCall(MatDenseRestoreArray(A, &v));
1807     } else { /* reuse memory, temporary allocates new memory */
1808       PetscScalar *v2;
1809       PetscLayout  tmplayout;
1810 
1811       PetscCall(PetscMalloc1((size_t)m * n, &v2));
1812       PetscCall(MatDenseGetArray(A, &v));
1813       for (j = 0; j < n; j++) {
1814         for (k = 0; k < m; k++) v2[j + (size_t)k * n] = v[k + (size_t)j * M];
1815       }
1816       PetscCall(PetscArraycpy(v, v2, (size_t)m * n));
1817       PetscCall(PetscFree(v2));
1818       PetscCall(MatDenseRestoreArray(A, &v));
1819       /* cleanup size dependent quantities */
1820       PetscCall(VecDestroy(&mat->cvec));
1821       PetscCall(MatDestroy(&mat->cmat));
1822       PetscCall(PetscFree(mat->pivots));
1823       PetscCall(PetscFree(mat->fwork));
1824       /* swap row/col layouts */
1825       PetscCall(PetscBLASIntCast(n, &mat->lda));
1826       tmplayout = A->rmap;
1827       A->rmap   = A->cmap;
1828       A->cmap   = tmplayout;
1829     }
1830   } else { /* out-of-place transpose */
1831     Mat           tmat;
1832     Mat_SeqDense *tmatd;
1833     PetscScalar  *v2;
1834     PetscInt      M2;
1835 
1836     if (reuse == MAT_INITIAL_MATRIX) {
1837       PetscCall(MatCreate(PetscObjectComm((PetscObject)A), &tmat));
1838       PetscCall(MatSetSizes(tmat, A->cmap->n, A->rmap->n, A->cmap->n, A->rmap->n));
1839       PetscCall(MatSetType(tmat, ((PetscObject)A)->type_name));
1840       PetscCall(MatSeqDenseSetPreallocation(tmat, NULL));
1841     } else tmat = *matout;
1842 
1843     PetscCall(MatDenseGetArrayRead(A, (const PetscScalar **)&v));
1844     PetscCall(MatDenseGetArray(tmat, &v2));
1845     tmatd = (Mat_SeqDense *)tmat->data;
1846     M2    = tmatd->lda;
1847     for (j = 0; j < n; j++) {
1848       for (k = 0; k < m; k++) v2[j + k * M2] = v[k + j * M];
1849     }
1850     PetscCall(MatDenseRestoreArray(tmat, &v2));
1851     PetscCall(MatDenseRestoreArrayRead(A, (const PetscScalar **)&v));
1852     PetscCall(MatAssemblyBegin(tmat, MAT_FINAL_ASSEMBLY));
1853     PetscCall(MatAssemblyEnd(tmat, MAT_FINAL_ASSEMBLY));
1854     *matout = tmat;
1855   }
1856   PetscFunctionReturn(PETSC_SUCCESS);
1857 }
1858 
1859 static PetscErrorCode MatEqual_SeqDense(Mat A1, Mat A2, PetscBool *flg)
1860 {
1861   Mat_SeqDense      *mat1 = (Mat_SeqDense *)A1->data;
1862   Mat_SeqDense      *mat2 = (Mat_SeqDense *)A2->data;
1863   PetscInt           i;
1864   const PetscScalar *v1, *v2;
1865 
1866   PetscFunctionBegin;
1867   if (A1->rmap->n != A2->rmap->n) {
1868     *flg = PETSC_FALSE;
1869     PetscFunctionReturn(PETSC_SUCCESS);
1870   }
1871   if (A1->cmap->n != A2->cmap->n) {
1872     *flg = PETSC_FALSE;
1873     PetscFunctionReturn(PETSC_SUCCESS);
1874   }
1875   PetscCall(MatDenseGetArrayRead(A1, &v1));
1876   PetscCall(MatDenseGetArrayRead(A2, &v2));
1877   for (i = 0; i < A1->cmap->n; i++) {
1878     PetscCall(PetscArraycmp(v1, v2, A1->rmap->n, flg));
1879     if (*flg == PETSC_FALSE) PetscFunctionReturn(PETSC_SUCCESS);
1880     v1 += mat1->lda;
1881     v2 += mat2->lda;
1882   }
1883   PetscCall(MatDenseRestoreArrayRead(A1, &v1));
1884   PetscCall(MatDenseRestoreArrayRead(A2, &v2));
1885   *flg = PETSC_TRUE;
1886   PetscFunctionReturn(PETSC_SUCCESS);
1887 }
1888 
1889 PetscErrorCode MatGetDiagonal_SeqDense(Mat A, Vec v)
1890 {
1891   Mat_SeqDense      *mat = (Mat_SeqDense *)A->data;
1892   PetscInt           i, n, len;
1893   PetscScalar       *x;
1894   const PetscScalar *vv;
1895 
1896   PetscFunctionBegin;
1897   PetscCall(VecGetSize(v, &n));
1898   PetscCall(VecGetArray(v, &x));
1899   len = PetscMin(A->rmap->n, A->cmap->n);
1900   PetscCall(MatDenseGetArrayRead(A, &vv));
1901   PetscCheck(n == A->rmap->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Nonconforming mat and vec");
1902   for (i = 0; i < len; i++) x[i] = vv[i * mat->lda + i];
1903   PetscCall(MatDenseRestoreArrayRead(A, &vv));
1904   PetscCall(VecRestoreArray(v, &x));
1905   PetscFunctionReturn(PETSC_SUCCESS);
1906 }
1907 
1908 static PetscErrorCode MatDiagonalScale_SeqDense(Mat A, Vec ll, Vec rr)
1909 {
1910   Mat_SeqDense      *mat = (Mat_SeqDense *)A->data;
1911   const PetscScalar *l, *r;
1912   PetscScalar        x, *v, *vv;
1913   PetscInt           i, j, m = A->rmap->n, n = A->cmap->n;
1914 
1915   PetscFunctionBegin;
1916   PetscCall(MatDenseGetArray(A, &vv));
1917   if (ll) {
1918     PetscCall(VecGetSize(ll, &m));
1919     PetscCall(VecGetArrayRead(ll, &l));
1920     PetscCheck(m == A->rmap->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Left scaling vec wrong size");
1921     for (i = 0; i < m; i++) {
1922       x = l[i];
1923       v = vv + i;
1924       for (j = 0; j < n; j++) {
1925         (*v) *= x;
1926         v += mat->lda;
1927       }
1928     }
1929     PetscCall(VecRestoreArrayRead(ll, &l));
1930     PetscCall(PetscLogFlops(1.0 * n * m));
1931   }
1932   if (rr) {
1933     PetscCall(VecGetSize(rr, &n));
1934     PetscCall(VecGetArrayRead(rr, &r));
1935     PetscCheck(n == A->cmap->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Right scaling vec wrong size");
1936     for (i = 0; i < n; i++) {
1937       x = r[i];
1938       v = vv + i * mat->lda;
1939       for (j = 0; j < m; j++) (*v++) *= x;
1940     }
1941     PetscCall(VecRestoreArrayRead(rr, &r));
1942     PetscCall(PetscLogFlops(1.0 * n * m));
1943   }
1944   PetscCall(MatDenseRestoreArray(A, &vv));
1945   PetscFunctionReturn(PETSC_SUCCESS);
1946 }
1947 
1948 PetscErrorCode MatNorm_SeqDense(Mat A, NormType type, PetscReal *nrm)
1949 {
1950   Mat_SeqDense *mat = (Mat_SeqDense *)A->data;
1951   PetscScalar  *v, *vv;
1952   PetscReal     sum = 0.0;
1953   PetscInt      lda, m = A->rmap->n, i, j;
1954 
1955   PetscFunctionBegin;
1956   PetscCall(MatDenseGetArrayRead(A, (const PetscScalar **)&vv));
1957   PetscCall(MatDenseGetLDA(A, &lda));
1958   v = vv;
1959   if (type == NORM_FROBENIUS) {
1960     if (lda > m) {
1961       for (j = 0; j < A->cmap->n; j++) {
1962         v = vv + j * lda;
1963         for (i = 0; i < m; i++) {
1964           sum += PetscRealPart(PetscConj(*v) * (*v));
1965           v++;
1966         }
1967       }
1968     } else {
1969 #if defined(PETSC_USE_REAL___FP16)
1970       PetscBLASInt one = 1, cnt = A->cmap->n * A->rmap->n;
1971       PetscCallBLAS("BLASnrm2", *nrm = BLASnrm2_(&cnt, v, &one));
1972     }
1973 #else
1974       for (i = 0; i < A->cmap->n * A->rmap->n; i++) {
1975         sum += PetscRealPart(PetscConj(*v) * (*v));
1976         v++;
1977       }
1978     }
1979     *nrm = PetscSqrtReal(sum);
1980 #endif
1981     PetscCall(PetscLogFlops(2.0 * A->cmap->n * A->rmap->n));
1982   } else if (type == NORM_1) {
1983     *nrm = 0.0;
1984     for (j = 0; j < A->cmap->n; j++) {
1985       v   = vv + j * mat->lda;
1986       sum = 0.0;
1987       for (i = 0; i < A->rmap->n; i++) {
1988         sum += PetscAbsScalar(*v);
1989         v++;
1990       }
1991       if (sum > *nrm) *nrm = sum;
1992     }
1993     PetscCall(PetscLogFlops(1.0 * A->cmap->n * A->rmap->n));
1994   } else if (type == NORM_INFINITY) {
1995     *nrm = 0.0;
1996     for (j = 0; j < A->rmap->n; j++) {
1997       v   = vv + j;
1998       sum = 0.0;
1999       for (i = 0; i < A->cmap->n; i++) {
2000         sum += PetscAbsScalar(*v);
2001         v += mat->lda;
2002       }
2003       if (sum > *nrm) *nrm = sum;
2004     }
2005     PetscCall(PetscLogFlops(1.0 * A->cmap->n * A->rmap->n));
2006   } else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "No two norm");
2007   PetscCall(MatDenseRestoreArrayRead(A, (const PetscScalar **)&vv));
2008   PetscFunctionReturn(PETSC_SUCCESS);
2009 }
2010 
2011 static PetscErrorCode MatSetOption_SeqDense(Mat A, MatOption op, PetscBool flg)
2012 {
2013   Mat_SeqDense *aij = (Mat_SeqDense *)A->data;
2014 
2015   PetscFunctionBegin;
2016   switch (op) {
2017   case MAT_ROW_ORIENTED:
2018     aij->roworiented = flg;
2019     break;
2020   default:
2021     break;
2022   }
2023   PetscFunctionReturn(PETSC_SUCCESS);
2024 }
2025 
2026 PetscErrorCode MatZeroEntries_SeqDense(Mat A)
2027 {
2028   Mat_SeqDense *l   = (Mat_SeqDense *)A->data;
2029   PetscInt      lda = l->lda, m = A->rmap->n, n = A->cmap->n, j;
2030   PetscScalar  *v;
2031 
2032   PetscFunctionBegin;
2033   PetscCall(MatDenseGetArrayWrite(A, &v));
2034   if (lda > m) {
2035     for (j = 0; j < n; j++) PetscCall(PetscArrayzero(v + j * lda, m));
2036   } else {
2037     PetscCall(PetscArrayzero(v, PetscInt64Mult(m, n)));
2038   }
2039   PetscCall(MatDenseRestoreArrayWrite(A, &v));
2040   PetscFunctionReturn(PETSC_SUCCESS);
2041 }
2042 
2043 static PetscErrorCode MatZeroRows_SeqDense(Mat A, PetscInt N, const PetscInt rows[], PetscScalar diag, Vec x, Vec b)
2044 {
2045   Mat_SeqDense      *l = (Mat_SeqDense *)A->data;
2046   PetscInt           m = l->lda, n = A->cmap->n, i, j;
2047   PetscScalar       *slot, *bb, *v;
2048   const PetscScalar *xx;
2049 
2050   PetscFunctionBegin;
2051   if (PetscDefined(USE_DEBUG)) {
2052     for (i = 0; i < N; i++) {
2053       PetscCheck(rows[i] >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Negative row requested to be zeroed");
2054       PetscCheck(rows[i] < A->rmap->n, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Row %" PetscInt_FMT " requested to be zeroed greater than or equal number of rows %" PetscInt_FMT, rows[i], A->rmap->n);
2055     }
2056   }
2057   if (!N) PetscFunctionReturn(PETSC_SUCCESS);
2058 
2059   /* fix right-hand side if needed */
2060   if (x && b) {
2061     PetscCall(VecGetArrayRead(x, &xx));
2062     PetscCall(VecGetArray(b, &bb));
2063     for (i = 0; i < N; i++) bb[rows[i]] = diag * xx[rows[i]];
2064     PetscCall(VecRestoreArrayRead(x, &xx));
2065     PetscCall(VecRestoreArray(b, &bb));
2066   }
2067 
2068   PetscCall(MatDenseGetArray(A, &v));
2069   for (i = 0; i < N; i++) {
2070     slot = v + rows[i];
2071     for (j = 0; j < n; j++) {
2072       *slot = 0.0;
2073       slot += m;
2074     }
2075   }
2076   if (diag != 0.0) {
2077     PetscCheck(A->rmap->n == A->cmap->n, PETSC_COMM_SELF, PETSC_ERR_SUP, "Only coded for square matrices");
2078     for (i = 0; i < N; i++) {
2079       slot  = v + (m + 1) * rows[i];
2080       *slot = diag;
2081     }
2082   }
2083   PetscCall(MatDenseRestoreArray(A, &v));
2084   PetscFunctionReturn(PETSC_SUCCESS);
2085 }
2086 
2087 static PetscErrorCode MatDenseGetLDA_SeqDense(Mat A, PetscInt *lda)
2088 {
2089   Mat_SeqDense *mat = (Mat_SeqDense *)A->data;
2090 
2091   PetscFunctionBegin;
2092   *lda = mat->lda;
2093   PetscFunctionReturn(PETSC_SUCCESS);
2094 }
2095 
2096 PetscErrorCode MatDenseGetArray_SeqDense(Mat A, PetscScalar **array)
2097 {
2098   Mat_SeqDense *mat = (Mat_SeqDense *)A->data;
2099 
2100   PetscFunctionBegin;
2101   PetscCheck(!mat->matinuse, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Need to call MatDenseRestoreSubMatrix() first");
2102   *array = mat->v;
2103   PetscFunctionReturn(PETSC_SUCCESS);
2104 }
2105 
2106 PetscErrorCode MatDenseRestoreArray_SeqDense(Mat A, PetscScalar **array)
2107 {
2108   PetscFunctionBegin;
2109   if (array) *array = NULL;
2110   PetscFunctionReturn(PETSC_SUCCESS);
2111 }
2112 
2113 /*@
2114   MatDenseGetLDA - gets the leading dimension of the array returned from `MatDenseGetArray()`
2115 
2116   Not Collective
2117 
2118   Input Parameter:
2119 . A - a `MATDENSE` or `MATDENSECUDA` matrix
2120 
2121   Output Parameter:
2122 . lda - the leading dimension
2123 
2124   Level: intermediate
2125 
2126 .seealso: [](ch_matrices), `Mat`, `MATDENSE`, `MATDENSECUDA`, `MatDenseGetArray()`, `MatDenseRestoreArray()`, `MatDenseGetArrayRead()`, `MatDenseRestoreArrayRead()`, `MatDenseSetLDA()`
2127 @*/
2128 PetscErrorCode MatDenseGetLDA(Mat A, PetscInt *lda)
2129 {
2130   PetscFunctionBegin;
2131   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
2132   PetscAssertPointer(lda, 2);
2133   MatCheckPreallocated(A, 1);
2134   PetscUseMethod(A, "MatDenseGetLDA_C", (Mat, PetscInt *), (A, lda));
2135   PetscFunctionReturn(PETSC_SUCCESS);
2136 }
2137 
2138 /*@
2139   MatDenseSetLDA - Sets the leading dimension of the array used by the `MATDENSE` matrix
2140 
2141   Collective if the matrix layouts have not yet been setup
2142 
2143   Input Parameters:
2144 + A   - a `MATDENSE` or `MATDENSECUDA` matrix
2145 - lda - the leading dimension
2146 
2147   Level: intermediate
2148 
2149 .seealso: [](ch_matrices), `Mat`, `MATDENSE`, `MATDENSECUDA`, `MatDenseGetArray()`, `MatDenseRestoreArray()`, `MatDenseGetArrayRead()`, `MatDenseRestoreArrayRead()`, `MatDenseGetLDA()`
2150 @*/
2151 PetscErrorCode MatDenseSetLDA(Mat A, PetscInt lda)
2152 {
2153   PetscFunctionBegin;
2154   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
2155   PetscTryMethod(A, "MatDenseSetLDA_C", (Mat, PetscInt), (A, lda));
2156   PetscFunctionReturn(PETSC_SUCCESS);
2157 }
2158 
2159 /*@C
2160   MatDenseGetArray - gives read-write access to the array where the data for a `MATDENSE` matrix is stored
2161 
2162   Logically Collective
2163 
2164   Input Parameter:
2165 . A - a dense matrix
2166 
2167   Output Parameter:
2168 . array - pointer to the data
2169 
2170   Level: intermediate
2171 
2172 .seealso: [](ch_matrices), `Mat`, `MATDENSE`, `MatDenseRestoreArray()`, `MatDenseGetArrayRead()`, `MatDenseRestoreArrayRead()`, `MatDenseGetArrayWrite()`, `MatDenseRestoreArrayWrite()`
2173 @*/
2174 PetscErrorCode MatDenseGetArray(Mat A, PetscScalar *array[]) PeNS
2175 {
2176   PetscFunctionBegin;
2177   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
2178   PetscAssertPointer(array, 2);
2179   PetscUseMethod(A, "MatDenseGetArray_C", (Mat, PetscScalar **), (A, array));
2180   PetscFunctionReturn(PETSC_SUCCESS);
2181 }
2182 
2183 /*@C
2184   MatDenseRestoreArray - returns access to the array where the data for a `MATDENSE` matrix is stored obtained by `MatDenseGetArray()`
2185 
2186   Logically Collective
2187 
2188   Input Parameters:
2189 + A     - a dense matrix
2190 - array - pointer to the data (may be `NULL`)
2191 
2192   Level: intermediate
2193 
2194 .seealso: [](ch_matrices), `Mat`, `MATDENSE`, `MatDenseGetArray()`, `MatDenseGetArrayRead()`, `MatDenseRestoreArrayRead()`, `MatDenseGetArrayWrite()`, `MatDenseRestoreArrayWrite()`
2195 @*/
2196 PetscErrorCode MatDenseRestoreArray(Mat A, PetscScalar *array[]) PeNS
2197 {
2198   PetscFunctionBegin;
2199   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
2200   if (array) PetscAssertPointer(array, 2);
2201   PetscUseMethod(A, "MatDenseRestoreArray_C", (Mat, PetscScalar **), (A, array));
2202   PetscCall(PetscObjectStateIncrease((PetscObject)A));
2203 #if defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
2204   A->offloadmask = PETSC_OFFLOAD_CPU;
2205 #endif
2206   PetscFunctionReturn(PETSC_SUCCESS);
2207 }
2208 
2209 /*@C
2210   MatDenseGetArrayRead - gives read-only access to the array where the data for a `MATDENSE` matrix is stored
2211 
2212   Not Collective
2213 
2214   Input Parameter:
2215 . A - a dense matrix
2216 
2217   Output Parameter:
2218 . array - pointer to the data
2219 
2220   Level: intermediate
2221 
2222 .seealso: [](ch_matrices), `Mat`, `MATDENSE`, `MatDenseRestoreArrayRead()`, `MatDenseGetArray()`, `MatDenseRestoreArray()`, `MatDenseGetArrayWrite()`, `MatDenseRestoreArrayWrite()`
2223 @*/
2224 PetscErrorCode MatDenseGetArrayRead(Mat A, const PetscScalar *array[]) PeNS
2225 {
2226   PetscFunctionBegin;
2227   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
2228   PetscAssertPointer(array, 2);
2229   PetscUseMethod(A, "MatDenseGetArrayRead_C", (Mat, PetscScalar **), (A, (PetscScalar **)array));
2230   PetscFunctionReturn(PETSC_SUCCESS);
2231 }
2232 
2233 /*@C
2234   MatDenseRestoreArrayRead - returns access to the array where the data for a `MATDENSE` matrix is stored obtained by `MatDenseGetArrayRead()`
2235 
2236   Not Collective
2237 
2238   Input Parameters:
2239 + A     - a dense matrix
2240 - array - pointer to the data (may be `NULL`)
2241 
2242   Level: intermediate
2243 
2244 .seealso: [](ch_matrices), `Mat`, `MATDENSE`, `MatDenseGetArrayRead()`, `MatDenseGetArray()`, `MatDenseRestoreArray()`, `MatDenseGetArrayWrite()`, `MatDenseRestoreArrayWrite()`
2245 @*/
2246 PetscErrorCode MatDenseRestoreArrayRead(Mat A, const PetscScalar *array[]) PeNS
2247 {
2248   PetscFunctionBegin;
2249   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
2250   if (array) PetscAssertPointer(array, 2);
2251   PetscUseMethod(A, "MatDenseRestoreArrayRead_C", (Mat, PetscScalar **), (A, (PetscScalar **)array));
2252   PetscFunctionReturn(PETSC_SUCCESS);
2253 }
2254 
2255 /*@C
2256   MatDenseGetArrayWrite - gives write-only access to the array where the data for a `MATDENSE` matrix is stored
2257 
2258   Not Collective
2259 
2260   Input Parameter:
2261 . A - a dense matrix
2262 
2263   Output Parameter:
2264 . array - pointer to the data
2265 
2266   Level: intermediate
2267 
2268 .seealso: [](ch_matrices), `Mat`, `MATDENSE`, `MatDenseRestoreArrayWrite()`, `MatDenseGetArray()`, `MatDenseRestoreArray()`, `MatDenseGetArrayRead()`, `MatDenseRestoreArrayRead()`
2269 @*/
2270 PetscErrorCode MatDenseGetArrayWrite(Mat A, PetscScalar *array[]) PeNS
2271 {
2272   PetscFunctionBegin;
2273   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
2274   PetscAssertPointer(array, 2);
2275   PetscUseMethod(A, "MatDenseGetArrayWrite_C", (Mat, PetscScalar **), (A, array));
2276   PetscFunctionReturn(PETSC_SUCCESS);
2277 }
2278 
2279 /*@C
2280   MatDenseRestoreArrayWrite - returns access to the array where the data for a `MATDENSE` matrix is stored obtained by `MatDenseGetArrayWrite()`
2281 
2282   Not Collective
2283 
2284   Input Parameters:
2285 + A     - a dense matrix
2286 - array - pointer to the data (may be `NULL`)
2287 
2288   Level: intermediate
2289 
2290 .seealso: [](ch_matrices), `Mat`, `MATDENSE`, `MatDenseGetArrayWrite()`, `MatDenseGetArray()`, `MatDenseRestoreArray()`, `MatDenseGetArrayRead()`, `MatDenseRestoreArrayRead()`
2291 @*/
2292 PetscErrorCode MatDenseRestoreArrayWrite(Mat A, PetscScalar *array[]) PeNS
2293 {
2294   PetscFunctionBegin;
2295   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
2296   if (array) PetscAssertPointer(array, 2);
2297   PetscUseMethod(A, "MatDenseRestoreArrayWrite_C", (Mat, PetscScalar **), (A, array));
2298   PetscCall(PetscObjectStateIncrease((PetscObject)A));
2299 #if defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
2300   A->offloadmask = PETSC_OFFLOAD_CPU;
2301 #endif
2302   PetscFunctionReturn(PETSC_SUCCESS);
2303 }
2304 
2305 /*@C
2306   MatDenseGetArrayAndMemType - gives read-write access to the array where the data for a `MATDENSE` matrix is stored
2307 
2308   Logically Collective
2309 
2310   Input Parameter:
2311 . A - a dense matrix
2312 
2313   Output Parameters:
2314 + array - pointer to the data
2315 - mtype - memory type of the returned pointer
2316 
2317   Level: intermediate
2318 
2319   Note:
2320   If the matrix is of a device type such as `MATDENSECUDA`, `MATDENSEHIP`, etc.,
2321   an array on device is always returned and is guaranteed to contain the matrix's latest data.
2322 
2323 .seealso: [](ch_matrices), `Mat`, `MATDENSE`, `MatDenseRestoreArrayAndMemType()`, `MatDenseGetArrayReadAndMemType()`, `MatDenseGetArrayWriteAndMemType()`, `MatDenseGetArrayRead()`,
2324    `MatDenseRestoreArrayRead()`, `MatDenseGetArrayWrite()`, `MatDenseRestoreArrayWrite()`, `MatSeqAIJGetCSRAndMemType()`
2325 @*/
2326 PetscErrorCode MatDenseGetArrayAndMemType(Mat A, PetscScalar *array[], PetscMemType *mtype)
2327 {
2328   PetscBool isMPI;
2329 
2330   PetscFunctionBegin;
2331   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
2332   PetscAssertPointer(array, 2);
2333   PetscCall(MatBindToCPU(A, PETSC_FALSE)); /* We want device matrices to always return device arrays, so we unbind the matrix if it is bound to CPU */
2334   PetscCall(PetscObjectBaseTypeCompare((PetscObject)A, MATMPIDENSE, &isMPI));
2335   if (isMPI) {
2336     /* Dispatch here so that the code can be reused for all subclasses of MATDENSE */
2337     PetscCall(MatDenseGetArrayAndMemType(((Mat_MPIDense *)A->data)->A, array, mtype));
2338   } else {
2339     PetscErrorCode (*fptr)(Mat, PetscScalar **, PetscMemType *);
2340 
2341     PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatDenseGetArrayAndMemType_C", &fptr));
2342     if (fptr) {
2343       PetscCall((*fptr)(A, array, mtype));
2344     } else {
2345       PetscUseMethod(A, "MatDenseGetArray_C", (Mat, PetscScalar **), (A, array));
2346       if (mtype) *mtype = PETSC_MEMTYPE_HOST;
2347     }
2348   }
2349   PetscFunctionReturn(PETSC_SUCCESS);
2350 }
2351 
2352 /*@C
2353   MatDenseRestoreArrayAndMemType - returns access to the array that is obtained by `MatDenseGetArrayAndMemType()`
2354 
2355   Logically Collective
2356 
2357   Input Parameters:
2358 + A     - a dense matrix
2359 - array - pointer to the data
2360 
2361   Level: intermediate
2362 
2363 .seealso: [](ch_matrices), `Mat`, `MATDENSE`, `MatDenseGetArrayAndMemType()`, `MatDenseGetArray()`, `MatDenseGetArrayRead()`, `MatDenseRestoreArrayRead()`, `MatDenseGetArrayWrite()`, `MatDenseRestoreArrayWrite()`
2364 @*/
2365 PetscErrorCode MatDenseRestoreArrayAndMemType(Mat A, PetscScalar *array[])
2366 {
2367   PetscBool isMPI;
2368 
2369   PetscFunctionBegin;
2370   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
2371   PetscAssertPointer(array, 2);
2372   PetscCall(PetscObjectBaseTypeCompare((PetscObject)A, MATMPIDENSE, &isMPI));
2373   if (isMPI) {
2374     PetscCall(MatDenseRestoreArrayAndMemType(((Mat_MPIDense *)A->data)->A, array));
2375   } else {
2376     PetscErrorCode (*fptr)(Mat, PetscScalar **);
2377 
2378     PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatDenseRestoreArrayAndMemType_C", &fptr));
2379     if (fptr) {
2380       PetscCall((*fptr)(A, array));
2381     } else {
2382       PetscUseMethod(A, "MatDenseRestoreArray_C", (Mat, PetscScalar **), (A, array));
2383     }
2384     *array = NULL;
2385   }
2386   PetscCall(PetscObjectStateIncrease((PetscObject)A));
2387   PetscFunctionReturn(PETSC_SUCCESS);
2388 }
2389 
2390 /*@C
2391   MatDenseGetArrayReadAndMemType - gives read-only access to the array where the data for a `MATDENSE` matrix is stored
2392 
2393   Logically Collective
2394 
2395   Input Parameter:
2396 . A - a dense matrix
2397 
2398   Output Parameters:
2399 + array - pointer to the data
2400 - mtype - memory type of the returned pointer
2401 
2402   Level: intermediate
2403 
2404   Note:
2405   If the matrix is of a device type such as `MATDENSECUDA`, `MATDENSEHIP`, etc.,
2406   an array on device is always returned and is guaranteed to contain the matrix's latest data.
2407 
2408 .seealso: [](ch_matrices), `Mat`, `MATDENSE`, `MatDenseRestoreArrayReadAndMemType()`, `MatDenseGetArrayWriteAndMemType()`,
2409    `MatDenseGetArrayRead()`, `MatDenseRestoreArrayRead()`, `MatDenseGetArrayWrite()`, `MatDenseRestoreArrayWrite()`, `MatSeqAIJGetCSRAndMemType()`
2410 @*/
2411 PetscErrorCode MatDenseGetArrayReadAndMemType(Mat A, const PetscScalar *array[], PetscMemType *mtype)
2412 {
2413   PetscBool isMPI;
2414 
2415   PetscFunctionBegin;
2416   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
2417   PetscAssertPointer(array, 2);
2418   PetscCall(MatBindToCPU(A, PETSC_FALSE)); /* We want device matrices to always return device arrays, so we unbind the matrix if it is bound to CPU */
2419   PetscCall(PetscObjectBaseTypeCompare((PetscObject)A, MATMPIDENSE, &isMPI));
2420   if (isMPI) { /* Dispatch here so that the code can be reused for all subclasses of MATDENSE */
2421     PetscCall(MatDenseGetArrayReadAndMemType(((Mat_MPIDense *)A->data)->A, array, mtype));
2422   } else {
2423     PetscErrorCode (*fptr)(Mat, const PetscScalar **, PetscMemType *);
2424 
2425     PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatDenseGetArrayReadAndMemType_C", &fptr));
2426     if (fptr) {
2427       PetscCall((*fptr)(A, array, mtype));
2428     } else {
2429       PetscUseMethod(A, "MatDenseGetArrayRead_C", (Mat, PetscScalar **), (A, (PetscScalar **)array));
2430       if (mtype) *mtype = PETSC_MEMTYPE_HOST;
2431     }
2432   }
2433   PetscFunctionReturn(PETSC_SUCCESS);
2434 }
2435 
2436 /*@C
2437   MatDenseRestoreArrayReadAndMemType - returns access to the array that is obtained by `MatDenseGetArrayReadAndMemType()`
2438 
2439   Logically Collective
2440 
2441   Input Parameters:
2442 + A     - a dense matrix
2443 - array - pointer to the data
2444 
2445   Level: intermediate
2446 
2447 .seealso: [](ch_matrices), `Mat`, `MATDENSE`, `MatDenseGetArrayReadAndMemType()`, `MatDenseGetArray()`, `MatDenseGetArrayRead()`, `MatDenseRestoreArrayRead()`, `MatDenseGetArrayWrite()`, `MatDenseRestoreArrayWrite()`
2448 @*/
2449 PetscErrorCode MatDenseRestoreArrayReadAndMemType(Mat A, const PetscScalar *array[])
2450 {
2451   PetscBool isMPI;
2452 
2453   PetscFunctionBegin;
2454   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
2455   PetscAssertPointer(array, 2);
2456   PetscCall(PetscObjectBaseTypeCompare((PetscObject)A, MATMPIDENSE, &isMPI));
2457   if (isMPI) {
2458     PetscCall(MatDenseRestoreArrayReadAndMemType(((Mat_MPIDense *)A->data)->A, array));
2459   } else {
2460     PetscErrorCode (*fptr)(Mat, const PetscScalar **);
2461 
2462     PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatDenseRestoreArrayReadAndMemType_C", &fptr));
2463     if (fptr) {
2464       PetscCall((*fptr)(A, array));
2465     } else {
2466       PetscUseMethod(A, "MatDenseRestoreArrayRead_C", (Mat, PetscScalar **), (A, (PetscScalar **)array));
2467     }
2468     *array = NULL;
2469   }
2470   PetscFunctionReturn(PETSC_SUCCESS);
2471 }
2472 
2473 /*@C
2474   MatDenseGetArrayWriteAndMemType - gives write-only access to the array where the data for a `MATDENSE` matrix is stored
2475 
2476   Logically Collective
2477 
2478   Input Parameter:
2479 . A - a dense matrix
2480 
2481   Output Parameters:
2482 + array - pointer to the data
2483 - mtype - memory type of the returned pointer
2484 
2485   Level: intermediate
2486 
2487   Note:
2488   If the matrix is of a device type such as `MATDENSECUDA`, `MATDENSEHIP`, etc.,
2489   an array on device is always returned and is guaranteed to contain the matrix's latest data.
2490 
2491 .seealso: [](ch_matrices), `Mat`, `MATDENSE`, `MatDenseRestoreArrayWriteAndMemType()`, `MatDenseGetArrayReadAndMemType()`, `MatDenseGetArrayRead()`,
2492   `MatDenseRestoreArrayRead()`, `MatDenseGetArrayWrite()`, `MatDenseRestoreArrayWrite()`, `MatSeqAIJGetCSRAndMemType()`
2493 @*/
2494 PetscErrorCode MatDenseGetArrayWriteAndMemType(Mat A, PetscScalar *array[], PetscMemType *mtype)
2495 {
2496   PetscBool isMPI;
2497 
2498   PetscFunctionBegin;
2499   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
2500   PetscAssertPointer(array, 2);
2501   PetscCall(MatBindToCPU(A, PETSC_FALSE)); /* We want device matrices to always return device arrays, so we unbind the matrix if it is bound to CPU */
2502   PetscCall(PetscObjectBaseTypeCompare((PetscObject)A, MATMPIDENSE, &isMPI));
2503   if (isMPI) {
2504     PetscCall(MatDenseGetArrayWriteAndMemType(((Mat_MPIDense *)A->data)->A, array, mtype));
2505   } else {
2506     PetscErrorCode (*fptr)(Mat, PetscScalar **, PetscMemType *);
2507 
2508     PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatDenseGetArrayWriteAndMemType_C", &fptr));
2509     if (fptr) {
2510       PetscCall((*fptr)(A, array, mtype));
2511     } else {
2512       PetscUseMethod(A, "MatDenseGetArrayWrite_C", (Mat, PetscScalar **), (A, array));
2513       if (mtype) *mtype = PETSC_MEMTYPE_HOST;
2514     }
2515   }
2516   PetscFunctionReturn(PETSC_SUCCESS);
2517 }
2518 
2519 /*@C
2520   MatDenseRestoreArrayWriteAndMemType - returns access to the array that is obtained by `MatDenseGetArrayReadAndMemType()`
2521 
2522   Logically Collective
2523 
2524   Input Parameters:
2525 + A     - a dense matrix
2526 - array - pointer to the data
2527 
2528   Level: intermediate
2529 
2530 .seealso: [](ch_matrices), `Mat`, `MATDENSE`, `MatDenseGetArrayWriteAndMemType()`, `MatDenseGetArray()`, `MatDenseGetArrayRead()`, `MatDenseRestoreArrayRead()`, `MatDenseGetArrayWrite()`, `MatDenseRestoreArrayWrite()`
2531 @*/
2532 PetscErrorCode MatDenseRestoreArrayWriteAndMemType(Mat A, PetscScalar *array[])
2533 {
2534   PetscBool isMPI;
2535 
2536   PetscFunctionBegin;
2537   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
2538   PetscAssertPointer(array, 2);
2539   PetscCall(PetscObjectBaseTypeCompare((PetscObject)A, MATMPIDENSE, &isMPI));
2540   if (isMPI) {
2541     PetscCall(MatDenseRestoreArrayWriteAndMemType(((Mat_MPIDense *)A->data)->A, array));
2542   } else {
2543     PetscErrorCode (*fptr)(Mat, PetscScalar **);
2544 
2545     PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatDenseRestoreArrayWriteAndMemType_C", &fptr));
2546     if (fptr) {
2547       PetscCall((*fptr)(A, array));
2548     } else {
2549       PetscUseMethod(A, "MatDenseRestoreArrayWrite_C", (Mat, PetscScalar **), (A, array));
2550     }
2551     *array = NULL;
2552   }
2553   PetscCall(PetscObjectStateIncrease((PetscObject)A));
2554   PetscFunctionReturn(PETSC_SUCCESS);
2555 }
2556 
2557 static PetscErrorCode MatCreateSubMatrix_SeqDense(Mat A, IS isrow, IS iscol, MatReuse scall, Mat *B)
2558 {
2559   Mat_SeqDense   *mat = (Mat_SeqDense *)A->data;
2560   PetscInt        i, j, nrows, ncols, ldb;
2561   const PetscInt *irow, *icol;
2562   PetscScalar    *av, *bv, *v = mat->v;
2563   Mat             newmat;
2564 
2565   PetscFunctionBegin;
2566   PetscCall(ISGetIndices(isrow, &irow));
2567   PetscCall(ISGetIndices(iscol, &icol));
2568   PetscCall(ISGetLocalSize(isrow, &nrows));
2569   PetscCall(ISGetLocalSize(iscol, &ncols));
2570 
2571   /* Check submatrixcall */
2572   if (scall == MAT_REUSE_MATRIX) {
2573     PetscInt n_cols, n_rows;
2574     PetscCall(MatGetSize(*B, &n_rows, &n_cols));
2575     if (n_rows != nrows || n_cols != ncols) {
2576       /* resize the result matrix to match number of requested rows/columns */
2577       PetscCall(MatSetSizes(*B, nrows, ncols, nrows, ncols));
2578     }
2579     newmat = *B;
2580   } else {
2581     /* Create and fill new matrix */
2582     PetscCall(MatCreate(PetscObjectComm((PetscObject)A), &newmat));
2583     PetscCall(MatSetSizes(newmat, nrows, ncols, nrows, ncols));
2584     PetscCall(MatSetType(newmat, ((PetscObject)A)->type_name));
2585     PetscCall(MatSeqDenseSetPreallocation(newmat, NULL));
2586   }
2587 
2588   /* Now extract the data pointers and do the copy,column at a time */
2589   PetscCall(MatDenseGetArray(newmat, &bv));
2590   PetscCall(MatDenseGetLDA(newmat, &ldb));
2591   for (i = 0; i < ncols; i++) {
2592     av = v + mat->lda * icol[i];
2593     for (j = 0; j < nrows; j++) bv[j] = av[irow[j]];
2594     bv += ldb;
2595   }
2596   PetscCall(MatDenseRestoreArray(newmat, &bv));
2597 
2598   /* Assemble the matrices so that the correct flags are set */
2599   PetscCall(MatAssemblyBegin(newmat, MAT_FINAL_ASSEMBLY));
2600   PetscCall(MatAssemblyEnd(newmat, MAT_FINAL_ASSEMBLY));
2601 
2602   /* Free work space */
2603   PetscCall(ISRestoreIndices(isrow, &irow));
2604   PetscCall(ISRestoreIndices(iscol, &icol));
2605   *B = newmat;
2606   PetscFunctionReturn(PETSC_SUCCESS);
2607 }
2608 
2609 static PetscErrorCode MatCreateSubMatrices_SeqDense(Mat A, PetscInt n, const IS irow[], const IS icol[], MatReuse scall, Mat *B[])
2610 {
2611   PetscInt i;
2612 
2613   PetscFunctionBegin;
2614   if (scall == MAT_INITIAL_MATRIX) PetscCall(PetscCalloc1(n, B));
2615 
2616   for (i = 0; i < n; i++) PetscCall(MatCreateSubMatrix_SeqDense(A, irow[i], icol[i], scall, &(*B)[i]));
2617   PetscFunctionReturn(PETSC_SUCCESS);
2618 }
2619 
2620 PetscErrorCode MatCopy_SeqDense(Mat A, Mat B, MatStructure str)
2621 {
2622   Mat_SeqDense      *a = (Mat_SeqDense *)A->data, *b = (Mat_SeqDense *)B->data;
2623   const PetscScalar *va;
2624   PetscScalar       *vb;
2625   PetscInt           lda1 = a->lda, lda2 = b->lda, m = A->rmap->n, n = A->cmap->n, j;
2626 
2627   PetscFunctionBegin;
2628   /* If the two matrices don't have the same copy implementation, they aren't compatible for fast copy. */
2629   if (A->ops->copy != B->ops->copy) {
2630     PetscCall(MatCopy_Basic(A, B, str));
2631     PetscFunctionReturn(PETSC_SUCCESS);
2632   }
2633   PetscCheck(m == B->rmap->n && n == B->cmap->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "size(B) != size(A)");
2634   PetscCall(MatDenseGetArrayRead(A, &va));
2635   PetscCall(MatDenseGetArray(B, &vb));
2636   if (lda1 > m || lda2 > m) {
2637     for (j = 0; j < n; j++) PetscCall(PetscArraycpy(vb + j * lda2, va + j * lda1, m));
2638   } else {
2639     PetscCall(PetscArraycpy(vb, va, A->rmap->n * A->cmap->n));
2640   }
2641   PetscCall(MatDenseRestoreArray(B, &vb));
2642   PetscCall(MatDenseRestoreArrayRead(A, &va));
2643   PetscCall(MatAssemblyBegin(B, MAT_FINAL_ASSEMBLY));
2644   PetscCall(MatAssemblyEnd(B, MAT_FINAL_ASSEMBLY));
2645   PetscFunctionReturn(PETSC_SUCCESS);
2646 }
2647 
2648 PetscErrorCode MatSetUp_SeqDense(Mat A)
2649 {
2650   PetscFunctionBegin;
2651   PetscCall(PetscLayoutSetUp(A->rmap));
2652   PetscCall(PetscLayoutSetUp(A->cmap));
2653   if (!A->preallocated) PetscCall(MatSeqDenseSetPreallocation(A, NULL));
2654   PetscFunctionReturn(PETSC_SUCCESS);
2655 }
2656 
2657 static PetscErrorCode MatConjugate_SeqDense(Mat A)
2658 {
2659   Mat_SeqDense *mat = (Mat_SeqDense *)A->data;
2660   PetscInt      i, j;
2661   PetscInt      min = PetscMin(A->rmap->n, A->cmap->n);
2662   PetscScalar  *aa;
2663 
2664   PetscFunctionBegin;
2665   PetscCall(MatDenseGetArray(A, &aa));
2666   for (j = 0; j < A->cmap->n; j++) {
2667     for (i = 0; i < A->rmap->n; i++) aa[i + j * mat->lda] = PetscConj(aa[i + j * mat->lda]);
2668   }
2669   PetscCall(MatDenseRestoreArray(A, &aa));
2670   if (mat->tau)
2671     for (i = 0; i < min; i++) mat->tau[i] = PetscConj(mat->tau[i]);
2672   PetscFunctionReturn(PETSC_SUCCESS);
2673 }
2674 
2675 static PetscErrorCode MatRealPart_SeqDense(Mat A)
2676 {
2677   Mat_SeqDense *mat = (Mat_SeqDense *)A->data;
2678   PetscInt      i, j;
2679   PetscScalar  *aa;
2680 
2681   PetscFunctionBegin;
2682   PetscCall(MatDenseGetArray(A, &aa));
2683   for (j = 0; j < A->cmap->n; j++) {
2684     for (i = 0; i < A->rmap->n; i++) aa[i + j * mat->lda] = PetscRealPart(aa[i + j * mat->lda]);
2685   }
2686   PetscCall(MatDenseRestoreArray(A, &aa));
2687   PetscFunctionReturn(PETSC_SUCCESS);
2688 }
2689 
2690 static PetscErrorCode MatImaginaryPart_SeqDense(Mat A)
2691 {
2692   Mat_SeqDense *mat = (Mat_SeqDense *)A->data;
2693   PetscInt      i, j;
2694   PetscScalar  *aa;
2695 
2696   PetscFunctionBegin;
2697   PetscCall(MatDenseGetArray(A, &aa));
2698   for (j = 0; j < A->cmap->n; j++) {
2699     for (i = 0; i < A->rmap->n; i++) aa[i + j * mat->lda] = PetscImaginaryPart(aa[i + j * mat->lda]);
2700   }
2701   PetscCall(MatDenseRestoreArray(A, &aa));
2702   PetscFunctionReturn(PETSC_SUCCESS);
2703 }
2704 
2705 PetscErrorCode MatMatMultSymbolic_SeqDense_SeqDense(Mat A, Mat B, PetscReal fill, Mat C)
2706 {
2707   PetscInt  m = A->rmap->n, n = B->cmap->n;
2708   PetscBool cisdense = PETSC_FALSE;
2709 
2710   PetscFunctionBegin;
2711   PetscCall(MatSetSizes(C, m, n, m, n));
2712 #if defined(PETSC_HAVE_CUDA)
2713   PetscCall(PetscObjectTypeCompareAny((PetscObject)C, &cisdense, MATSEQDENSE, MATSEQDENSECUDA, ""));
2714 #endif
2715 #if defined(PETSC_HAVE_HIP)
2716   PetscCall(PetscObjectTypeCompareAny((PetscObject)C, &cisdense, MATSEQDENSE, MATSEQDENSEHIP, ""));
2717 #endif
2718   if (!cisdense) {
2719     PetscBool flg;
2720 
2721     PetscCall(PetscObjectTypeCompare((PetscObject)B, ((PetscObject)A)->type_name, &flg));
2722     PetscCall(MatSetType(C, flg ? ((PetscObject)A)->type_name : MATDENSE));
2723   }
2724   PetscCall(MatSetUp(C));
2725   PetscFunctionReturn(PETSC_SUCCESS);
2726 }
2727 
2728 PetscErrorCode MatMatMultNumeric_SeqDense_SeqDense(Mat A, Mat B, Mat C)
2729 {
2730   Mat_SeqDense      *a = (Mat_SeqDense *)A->data, *b = (Mat_SeqDense *)B->data, *c = (Mat_SeqDense *)C->data;
2731   PetscBLASInt       m, n, k;
2732   const PetscScalar *av, *bv;
2733   PetscScalar       *cv;
2734   PetscScalar        _DOne = 1.0, _DZero = 0.0;
2735 
2736   PetscFunctionBegin;
2737   PetscCall(PetscBLASIntCast(C->rmap->n, &m));
2738   PetscCall(PetscBLASIntCast(C->cmap->n, &n));
2739   PetscCall(PetscBLASIntCast(A->cmap->n, &k));
2740   if (!m || !n || !k) PetscFunctionReturn(PETSC_SUCCESS);
2741   PetscCall(MatDenseGetArrayRead(A, &av));
2742   PetscCall(MatDenseGetArrayRead(B, &bv));
2743   PetscCall(MatDenseGetArrayWrite(C, &cv));
2744   PetscCallBLAS("BLASgemm", BLASgemm_("N", "N", &m, &n, &k, &_DOne, av, &a->lda, bv, &b->lda, &_DZero, cv, &c->lda));
2745   PetscCall(PetscLogFlops(1.0 * m * n * k + 1.0 * m * n * (k - 1)));
2746   PetscCall(MatDenseRestoreArrayRead(A, &av));
2747   PetscCall(MatDenseRestoreArrayRead(B, &bv));
2748   PetscCall(MatDenseRestoreArrayWrite(C, &cv));
2749   PetscFunctionReturn(PETSC_SUCCESS);
2750 }
2751 
2752 PetscErrorCode MatMatTransposeMultSymbolic_SeqDense_SeqDense(Mat A, Mat B, PetscReal fill, Mat C)
2753 {
2754   PetscInt  m = A->rmap->n, n = B->rmap->n;
2755   PetscBool cisdense = PETSC_FALSE;
2756 
2757   PetscFunctionBegin;
2758   PetscCall(MatSetSizes(C, m, n, m, n));
2759 #if defined(PETSC_HAVE_CUDA)
2760   PetscCall(PetscObjectTypeCompareAny((PetscObject)C, &cisdense, MATSEQDENSE, MATSEQDENSECUDA, ""));
2761 #endif
2762 #if defined(PETSC_HAVE_HIP)
2763   PetscCall(PetscObjectTypeCompareAny((PetscObject)C, &cisdense, MATSEQDENSE, MATSEQDENSEHIP, ""));
2764 #endif
2765   if (!cisdense) {
2766     PetscBool flg;
2767 
2768     PetscCall(PetscObjectTypeCompare((PetscObject)B, ((PetscObject)A)->type_name, &flg));
2769     PetscCall(MatSetType(C, flg ? ((PetscObject)A)->type_name : MATDENSE));
2770   }
2771   PetscCall(MatSetUp(C));
2772   PetscFunctionReturn(PETSC_SUCCESS);
2773 }
2774 
2775 PetscErrorCode MatMatTransposeMultNumeric_SeqDense_SeqDense(Mat A, Mat B, Mat C)
2776 {
2777   Mat_SeqDense      *a = (Mat_SeqDense *)A->data;
2778   Mat_SeqDense      *b = (Mat_SeqDense *)B->data;
2779   Mat_SeqDense      *c = (Mat_SeqDense *)C->data;
2780   const PetscScalar *av, *bv;
2781   PetscScalar       *cv;
2782   PetscBLASInt       m, n, k;
2783   PetscScalar        _DOne = 1.0, _DZero = 0.0;
2784 
2785   PetscFunctionBegin;
2786   PetscCall(PetscBLASIntCast(C->rmap->n, &m));
2787   PetscCall(PetscBLASIntCast(C->cmap->n, &n));
2788   PetscCall(PetscBLASIntCast(A->cmap->n, &k));
2789   if (!m || !n || !k) PetscFunctionReturn(PETSC_SUCCESS);
2790   PetscCall(MatDenseGetArrayRead(A, &av));
2791   PetscCall(MatDenseGetArrayRead(B, &bv));
2792   PetscCall(MatDenseGetArrayWrite(C, &cv));
2793   PetscCallBLAS("BLASgemm", BLASgemm_("N", "T", &m, &n, &k, &_DOne, av, &a->lda, bv, &b->lda, &_DZero, cv, &c->lda));
2794   PetscCall(MatDenseRestoreArrayRead(A, &av));
2795   PetscCall(MatDenseRestoreArrayRead(B, &bv));
2796   PetscCall(MatDenseRestoreArrayWrite(C, &cv));
2797   PetscCall(PetscLogFlops(1.0 * m * n * k + 1.0 * m * n * (k - 1)));
2798   PetscFunctionReturn(PETSC_SUCCESS);
2799 }
2800 
2801 PetscErrorCode MatTransposeMatMultSymbolic_SeqDense_SeqDense(Mat A, Mat B, PetscReal fill, Mat C)
2802 {
2803   PetscInt  m = A->cmap->n, n = B->cmap->n;
2804   PetscBool cisdense = PETSC_FALSE;
2805 
2806   PetscFunctionBegin;
2807   PetscCall(MatSetSizes(C, m, n, m, n));
2808 #if defined(PETSC_HAVE_CUDA)
2809   PetscCall(PetscObjectTypeCompareAny((PetscObject)C, &cisdense, MATSEQDENSE, MATSEQDENSECUDA, ""));
2810 #endif
2811 #if defined(PETSC_HAVE_HIP)
2812   PetscCall(PetscObjectTypeCompareAny((PetscObject)C, &cisdense, MATSEQDENSE, MATSEQDENSEHIP, ""));
2813 #endif
2814   if (!cisdense) {
2815     PetscBool flg;
2816 
2817     PetscCall(PetscObjectTypeCompare((PetscObject)B, ((PetscObject)A)->type_name, &flg));
2818     PetscCall(MatSetType(C, flg ? ((PetscObject)A)->type_name : MATDENSE));
2819   }
2820   PetscCall(MatSetUp(C));
2821   PetscFunctionReturn(PETSC_SUCCESS);
2822 }
2823 
2824 PetscErrorCode MatTransposeMatMultNumeric_SeqDense_SeqDense(Mat A, Mat B, Mat C)
2825 {
2826   Mat_SeqDense      *a = (Mat_SeqDense *)A->data;
2827   Mat_SeqDense      *b = (Mat_SeqDense *)B->data;
2828   Mat_SeqDense      *c = (Mat_SeqDense *)C->data;
2829   const PetscScalar *av, *bv;
2830   PetscScalar       *cv;
2831   PetscBLASInt       m, n, k;
2832   PetscScalar        _DOne = 1.0, _DZero = 0.0;
2833 
2834   PetscFunctionBegin;
2835   PetscCall(PetscBLASIntCast(C->rmap->n, &m));
2836   PetscCall(PetscBLASIntCast(C->cmap->n, &n));
2837   PetscCall(PetscBLASIntCast(A->rmap->n, &k));
2838   if (!m || !n || !k) PetscFunctionReturn(PETSC_SUCCESS);
2839   PetscCall(MatDenseGetArrayRead(A, &av));
2840   PetscCall(MatDenseGetArrayRead(B, &bv));
2841   PetscCall(MatDenseGetArrayWrite(C, &cv));
2842   PetscCallBLAS("BLASgemm", BLASgemm_("T", "N", &m, &n, &k, &_DOne, av, &a->lda, bv, &b->lda, &_DZero, cv, &c->lda));
2843   PetscCall(MatDenseRestoreArrayRead(A, &av));
2844   PetscCall(MatDenseRestoreArrayRead(B, &bv));
2845   PetscCall(MatDenseRestoreArrayWrite(C, &cv));
2846   PetscCall(PetscLogFlops(1.0 * m * n * k + 1.0 * m * n * (k - 1)));
2847   PetscFunctionReturn(PETSC_SUCCESS);
2848 }
2849 
2850 static PetscErrorCode MatProductSetFromOptions_SeqDense_AB(Mat C)
2851 {
2852   PetscFunctionBegin;
2853   C->ops->matmultsymbolic = MatMatMultSymbolic_SeqDense_SeqDense;
2854   C->ops->productsymbolic = MatProductSymbolic_AB;
2855   PetscFunctionReturn(PETSC_SUCCESS);
2856 }
2857 
2858 static PetscErrorCode MatProductSetFromOptions_SeqDense_AtB(Mat C)
2859 {
2860   PetscFunctionBegin;
2861   C->ops->transposematmultsymbolic = MatTransposeMatMultSymbolic_SeqDense_SeqDense;
2862   C->ops->productsymbolic          = MatProductSymbolic_AtB;
2863   PetscFunctionReturn(PETSC_SUCCESS);
2864 }
2865 
2866 static PetscErrorCode MatProductSetFromOptions_SeqDense_ABt(Mat C)
2867 {
2868   PetscFunctionBegin;
2869   C->ops->mattransposemultsymbolic = MatMatTransposeMultSymbolic_SeqDense_SeqDense;
2870   C->ops->productsymbolic          = MatProductSymbolic_ABt;
2871   PetscFunctionReturn(PETSC_SUCCESS);
2872 }
2873 
2874 PETSC_INTERN PetscErrorCode MatProductSetFromOptions_SeqDense(Mat C)
2875 {
2876   Mat_Product *product = C->product;
2877 
2878   PetscFunctionBegin;
2879   switch (product->type) {
2880   case MATPRODUCT_AB:
2881     PetscCall(MatProductSetFromOptions_SeqDense_AB(C));
2882     break;
2883   case MATPRODUCT_AtB:
2884     PetscCall(MatProductSetFromOptions_SeqDense_AtB(C));
2885     break;
2886   case MATPRODUCT_ABt:
2887     PetscCall(MatProductSetFromOptions_SeqDense_ABt(C));
2888     break;
2889   default:
2890     break;
2891   }
2892   PetscFunctionReturn(PETSC_SUCCESS);
2893 }
2894 
2895 static PetscErrorCode MatGetRowMax_SeqDense(Mat A, Vec v, PetscInt idx[])
2896 {
2897   Mat_SeqDense      *a = (Mat_SeqDense *)A->data;
2898   PetscInt           i, j, m = A->rmap->n, n = A->cmap->n, p;
2899   PetscScalar       *x;
2900   const PetscScalar *aa;
2901 
2902   PetscFunctionBegin;
2903   PetscCheck(!A->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2904   PetscCall(VecGetArray(v, &x));
2905   PetscCall(VecGetLocalSize(v, &p));
2906   PetscCall(MatDenseGetArrayRead(A, &aa));
2907   PetscCheck(p == A->rmap->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Nonconforming matrix and vector");
2908   for (i = 0; i < m; i++) {
2909     x[i] = aa[i];
2910     if (idx) idx[i] = 0;
2911     for (j = 1; j < n; j++) {
2912       if (PetscRealPart(x[i]) < PetscRealPart(aa[i + a->lda * j])) {
2913         x[i] = aa[i + a->lda * j];
2914         if (idx) idx[i] = j;
2915       }
2916     }
2917   }
2918   PetscCall(MatDenseRestoreArrayRead(A, &aa));
2919   PetscCall(VecRestoreArray(v, &x));
2920   PetscFunctionReturn(PETSC_SUCCESS);
2921 }
2922 
2923 static PetscErrorCode MatGetRowMaxAbs_SeqDense(Mat A, Vec v, PetscInt idx[])
2924 {
2925   Mat_SeqDense      *a = (Mat_SeqDense *)A->data;
2926   PetscInt           i, j, m = A->rmap->n, n = A->cmap->n, p;
2927   PetscScalar       *x;
2928   PetscReal          atmp;
2929   const PetscScalar *aa;
2930 
2931   PetscFunctionBegin;
2932   PetscCheck(!A->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2933   PetscCall(VecGetArray(v, &x));
2934   PetscCall(VecGetLocalSize(v, &p));
2935   PetscCall(MatDenseGetArrayRead(A, &aa));
2936   PetscCheck(p == A->rmap->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Nonconforming matrix and vector");
2937   for (i = 0; i < m; i++) {
2938     x[i] = PetscAbsScalar(aa[i]);
2939     for (j = 1; j < n; j++) {
2940       atmp = PetscAbsScalar(aa[i + a->lda * j]);
2941       if (PetscAbsScalar(x[i]) < atmp) {
2942         x[i] = atmp;
2943         if (idx) idx[i] = j;
2944       }
2945     }
2946   }
2947   PetscCall(MatDenseRestoreArrayRead(A, &aa));
2948   PetscCall(VecRestoreArray(v, &x));
2949   PetscFunctionReturn(PETSC_SUCCESS);
2950 }
2951 
2952 static PetscErrorCode MatGetRowMin_SeqDense(Mat A, Vec v, PetscInt idx[])
2953 {
2954   Mat_SeqDense      *a = (Mat_SeqDense *)A->data;
2955   PetscInt           i, j, m = A->rmap->n, n = A->cmap->n, p;
2956   PetscScalar       *x;
2957   const PetscScalar *aa;
2958 
2959   PetscFunctionBegin;
2960   PetscCheck(!A->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2961   PetscCall(MatDenseGetArrayRead(A, &aa));
2962   PetscCall(VecGetArray(v, &x));
2963   PetscCall(VecGetLocalSize(v, &p));
2964   PetscCheck(p == A->rmap->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Nonconforming matrix and vector");
2965   for (i = 0; i < m; i++) {
2966     x[i] = aa[i];
2967     if (idx) idx[i] = 0;
2968     for (j = 1; j < n; j++) {
2969       if (PetscRealPart(x[i]) > PetscRealPart(aa[i + a->lda * j])) {
2970         x[i] = aa[i + a->lda * j];
2971         if (idx) idx[i] = j;
2972       }
2973     }
2974   }
2975   PetscCall(VecRestoreArray(v, &x));
2976   PetscCall(MatDenseRestoreArrayRead(A, &aa));
2977   PetscFunctionReturn(PETSC_SUCCESS);
2978 }
2979 
2980 PetscErrorCode MatGetColumnVector_SeqDense(Mat A, Vec v, PetscInt col)
2981 {
2982   Mat_SeqDense      *a = (Mat_SeqDense *)A->data;
2983   PetscScalar       *x;
2984   const PetscScalar *aa;
2985 
2986   PetscFunctionBegin;
2987   PetscCheck(!A->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2988   PetscCall(MatDenseGetArrayRead(A, &aa));
2989   PetscCall(VecGetArray(v, &x));
2990   PetscCall(PetscArraycpy(x, aa + col * a->lda, A->rmap->n));
2991   PetscCall(VecRestoreArray(v, &x));
2992   PetscCall(MatDenseRestoreArrayRead(A, &aa));
2993   PetscFunctionReturn(PETSC_SUCCESS);
2994 }
2995 
2996 PETSC_INTERN PetscErrorCode MatGetColumnReductions_SeqDense(Mat A, PetscInt type, PetscReal *reductions)
2997 {
2998   PetscInt           i, j, m, n;
2999   const PetscScalar *a;
3000 
3001   PetscFunctionBegin;
3002   PetscCall(MatGetSize(A, &m, &n));
3003   PetscCall(PetscArrayzero(reductions, n));
3004   PetscCall(MatDenseGetArrayRead(A, &a));
3005   if (type == NORM_2) {
3006     for (i = 0; i < n; i++) {
3007       for (j = 0; j < m; j++) reductions[i] += PetscAbsScalar(a[j] * a[j]);
3008       a = PetscSafePointerPlusOffset(a, m);
3009     }
3010   } else if (type == NORM_1) {
3011     for (i = 0; i < n; i++) {
3012       for (j = 0; j < m; j++) reductions[i] += PetscAbsScalar(a[j]);
3013       a = PetscSafePointerPlusOffset(a, m);
3014     }
3015   } else if (type == NORM_INFINITY) {
3016     for (i = 0; i < n; i++) {
3017       for (j = 0; j < m; j++) reductions[i] = PetscMax(PetscAbsScalar(a[j]), reductions[i]);
3018       a = PetscSafePointerPlusOffset(a, m);
3019     }
3020   } else if (type == REDUCTION_SUM_REALPART || type == REDUCTION_MEAN_REALPART) {
3021     for (i = 0; i < n; i++) {
3022       for (j = 0; j < m; j++) reductions[i] += PetscRealPart(a[j]);
3023       a = PetscSafePointerPlusOffset(a, m);
3024     }
3025   } else if (type == REDUCTION_SUM_IMAGINARYPART || type == REDUCTION_MEAN_IMAGINARYPART) {
3026     for (i = 0; i < n; i++) {
3027       for (j = 0; j < m; j++) reductions[i] += PetscImaginaryPart(a[j]);
3028       a = PetscSafePointerPlusOffset(a, m);
3029     }
3030   } else SETERRQ(PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONG, "Unknown reduction type");
3031   PetscCall(MatDenseRestoreArrayRead(A, &a));
3032   if (type == NORM_2) {
3033     for (i = 0; i < n; i++) reductions[i] = PetscSqrtReal(reductions[i]);
3034   } else if (type == REDUCTION_MEAN_REALPART || type == REDUCTION_MEAN_IMAGINARYPART) {
3035     for (i = 0; i < n; i++) reductions[i] /= m;
3036   }
3037   PetscFunctionReturn(PETSC_SUCCESS);
3038 }
3039 
3040 PetscErrorCode MatSetRandom_SeqDense(Mat x, PetscRandom rctx)
3041 {
3042   PetscScalar *a;
3043   PetscInt     lda, m, n, i, j;
3044 
3045   PetscFunctionBegin;
3046   PetscCall(MatGetSize(x, &m, &n));
3047   PetscCall(MatDenseGetLDA(x, &lda));
3048   PetscCall(MatDenseGetArrayWrite(x, &a));
3049   for (j = 0; j < n; j++) {
3050     for (i = 0; i < m; i++) PetscCall(PetscRandomGetValue(rctx, a + j * lda + i));
3051   }
3052   PetscCall(MatDenseRestoreArrayWrite(x, &a));
3053   PetscFunctionReturn(PETSC_SUCCESS);
3054 }
3055 
3056 static PetscErrorCode MatMissingDiagonal_SeqDense(Mat A, PetscBool *missing, PetscInt *d)
3057 {
3058   PetscFunctionBegin;
3059   *missing = PETSC_FALSE;
3060   PetscFunctionReturn(PETSC_SUCCESS);
3061 }
3062 
3063 /* vals is not const */
3064 static PetscErrorCode MatDenseGetColumn_SeqDense(Mat A, PetscInt col, PetscScalar **vals)
3065 {
3066   Mat_SeqDense *a = (Mat_SeqDense *)A->data;
3067   PetscScalar  *v;
3068 
3069   PetscFunctionBegin;
3070   PetscCheck(!A->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3071   PetscCall(MatDenseGetArray(A, &v));
3072   *vals = v + col * a->lda;
3073   PetscCall(MatDenseRestoreArray(A, &v));
3074   PetscFunctionReturn(PETSC_SUCCESS);
3075 }
3076 
3077 static PetscErrorCode MatDenseRestoreColumn_SeqDense(Mat A, PetscScalar **vals)
3078 {
3079   PetscFunctionBegin;
3080   if (vals) *vals = NULL; /* user cannot accidentally use the array later */
3081   PetscFunctionReturn(PETSC_SUCCESS);
3082 }
3083 
3084 static struct _MatOps MatOps_Values = {MatSetValues_SeqDense,
3085                                        MatGetRow_SeqDense,
3086                                        MatRestoreRow_SeqDense,
3087                                        MatMult_SeqDense,
3088                                        /*  4*/ MatMultAdd_SeqDense,
3089                                        MatMultTranspose_SeqDense,
3090                                        MatMultTransposeAdd_SeqDense,
3091                                        NULL,
3092                                        NULL,
3093                                        NULL,
3094                                        /* 10*/ NULL,
3095                                        MatLUFactor_SeqDense,
3096                                        MatCholeskyFactor_SeqDense,
3097                                        MatSOR_SeqDense,
3098                                        MatTranspose_SeqDense,
3099                                        /* 15*/ MatGetInfo_SeqDense,
3100                                        MatEqual_SeqDense,
3101                                        MatGetDiagonal_SeqDense,
3102                                        MatDiagonalScale_SeqDense,
3103                                        MatNorm_SeqDense,
3104                                        /* 20*/ NULL,
3105                                        NULL,
3106                                        MatSetOption_SeqDense,
3107                                        MatZeroEntries_SeqDense,
3108                                        /* 24*/ MatZeroRows_SeqDense,
3109                                        NULL,
3110                                        NULL,
3111                                        NULL,
3112                                        NULL,
3113                                        /* 29*/ MatSetUp_SeqDense,
3114                                        NULL,
3115                                        NULL,
3116                                        NULL,
3117                                        NULL,
3118                                        /* 34*/ MatDuplicate_SeqDense,
3119                                        NULL,
3120                                        NULL,
3121                                        NULL,
3122                                        NULL,
3123                                        /* 39*/ MatAXPY_SeqDense,
3124                                        MatCreateSubMatrices_SeqDense,
3125                                        NULL,
3126                                        MatGetValues_SeqDense,
3127                                        MatCopy_SeqDense,
3128                                        /* 44*/ MatGetRowMax_SeqDense,
3129                                        MatScale_SeqDense,
3130                                        MatShift_SeqDense,
3131                                        NULL,
3132                                        MatZeroRowsColumns_SeqDense,
3133                                        /* 49*/ MatSetRandom_SeqDense,
3134                                        NULL,
3135                                        NULL,
3136                                        NULL,
3137                                        NULL,
3138                                        /* 54*/ NULL,
3139                                        NULL,
3140                                        NULL,
3141                                        NULL,
3142                                        NULL,
3143                                        /* 59*/ MatCreateSubMatrix_SeqDense,
3144                                        MatDestroy_SeqDense,
3145                                        MatView_SeqDense,
3146                                        NULL,
3147                                        NULL,
3148                                        /* 64*/ NULL,
3149                                        NULL,
3150                                        NULL,
3151                                        NULL,
3152                                        NULL,
3153                                        /* 69*/ MatGetRowMaxAbs_SeqDense,
3154                                        NULL,
3155                                        NULL,
3156                                        NULL,
3157                                        NULL,
3158                                        /* 74*/ NULL,
3159                                        NULL,
3160                                        NULL,
3161                                        NULL,
3162                                        NULL,
3163                                        /* 79*/ NULL,
3164                                        NULL,
3165                                        NULL,
3166                                        NULL,
3167                                        /* 83*/ MatLoad_SeqDense,
3168                                        MatIsSymmetric_SeqDense,
3169                                        MatIsHermitian_SeqDense,
3170                                        NULL,
3171                                        NULL,
3172                                        NULL,
3173                                        /* 89*/ NULL,
3174                                        NULL,
3175                                        MatMatMultNumeric_SeqDense_SeqDense,
3176                                        NULL,
3177                                        NULL,
3178                                        /* 94*/ NULL,
3179                                        NULL,
3180                                        NULL,
3181                                        MatMatTransposeMultNumeric_SeqDense_SeqDense,
3182                                        NULL,
3183                                        /* 99*/ MatProductSetFromOptions_SeqDense,
3184                                        NULL,
3185                                        NULL,
3186                                        MatConjugate_SeqDense,
3187                                        NULL,
3188                                        /*104*/ NULL,
3189                                        MatRealPart_SeqDense,
3190                                        MatImaginaryPart_SeqDense,
3191                                        NULL,
3192                                        NULL,
3193                                        /*109*/ NULL,
3194                                        NULL,
3195                                        MatGetRowMin_SeqDense,
3196                                        MatGetColumnVector_SeqDense,
3197                                        MatMissingDiagonal_SeqDense,
3198                                        /*114*/ NULL,
3199                                        NULL,
3200                                        NULL,
3201                                        NULL,
3202                                        NULL,
3203                                        /*119*/ NULL,
3204                                        NULL,
3205                                        MatMultHermitianTranspose_SeqDense,
3206                                        MatMultHermitianTransposeAdd_SeqDense,
3207                                        NULL,
3208                                        /*124*/ NULL,
3209                                        MatGetColumnReductions_SeqDense,
3210                                        NULL,
3211                                        NULL,
3212                                        NULL,
3213                                        /*129*/ NULL,
3214                                        NULL,
3215                                        NULL,
3216                                        MatTransposeMatMultNumeric_SeqDense_SeqDense,
3217                                        NULL,
3218                                        /*134*/ NULL,
3219                                        NULL,
3220                                        NULL,
3221                                        NULL,
3222                                        NULL,
3223                                        /*139*/ NULL,
3224                                        NULL,
3225                                        NULL,
3226                                        NULL,
3227                                        NULL,
3228                                        MatCreateMPIMatConcatenateSeqMat_SeqDense,
3229                                        /*145*/ NULL,
3230                                        NULL,
3231                                        NULL,
3232                                        NULL,
3233                                        NULL,
3234                                        /*150*/ NULL,
3235                                        NULL,
3236                                        NULL,
3237                                        NULL,
3238                                        NULL,
3239                                        /*155*/ NULL,
3240                                        NULL};
3241 
3242 /*@
3243   MatCreateSeqDense - Creates a `MATSEQDENSE` that
3244   is stored in column major order (the usual Fortran format).
3245 
3246   Collective
3247 
3248   Input Parameters:
3249 + comm - MPI communicator, set to `PETSC_COMM_SELF`
3250 . m    - number of rows
3251 . n    - number of columns
3252 - data - optional location of matrix data in column major order.  Use `NULL` for PETSc
3253          to control all matrix memory allocation.
3254 
3255   Output Parameter:
3256 . A - the matrix
3257 
3258   Level: intermediate
3259 
3260   Note:
3261   The data input variable is intended primarily for Fortran programmers
3262   who wish to allocate their own matrix memory space.  Most users should
3263   set `data` = `NULL`.
3264 
3265   Developer Note:
3266   Many of the matrix operations for this variant use the BLAS and LAPACK routines.
3267 
3268 .seealso: [](ch_matrices), `Mat`, `MATSEQDENSE`, `MatCreate()`, `MatCreateDense()`, `MatSetValues()`
3269 @*/
3270 PetscErrorCode MatCreateSeqDense(MPI_Comm comm, PetscInt m, PetscInt n, PetscScalar data[], Mat *A)
3271 {
3272   PetscFunctionBegin;
3273   PetscCall(MatCreate(comm, A));
3274   PetscCall(MatSetSizes(*A, m, n, m, n));
3275   PetscCall(MatSetType(*A, MATSEQDENSE));
3276   PetscCall(MatSeqDenseSetPreallocation(*A, data));
3277   PetscFunctionReturn(PETSC_SUCCESS);
3278 }
3279 
3280 /*@
3281   MatSeqDenseSetPreallocation - Sets the array used for storing the matrix elements of a `MATSEQDENSE` matrix
3282 
3283   Collective
3284 
3285   Input Parameters:
3286 + B    - the matrix
3287 - data - the array (or `NULL`)
3288 
3289   Level: intermediate
3290 
3291   Note:
3292   The data input variable is intended primarily for Fortran programmers
3293   who wish to allocate their own matrix memory space.  Most users should
3294   need not call this routine.
3295 
3296 .seealso: [](ch_matrices), `Mat`, `MATSEQDENSE`, `MatCreate()`, `MatCreateDense()`, `MatSetValues()`, `MatDenseSetLDA()`
3297 @*/
3298 PetscErrorCode MatSeqDenseSetPreallocation(Mat B, PetscScalar data[])
3299 {
3300   PetscFunctionBegin;
3301   PetscValidHeaderSpecific(B, MAT_CLASSID, 1);
3302   PetscTryMethod(B, "MatSeqDenseSetPreallocation_C", (Mat, PetscScalar[]), (B, data));
3303   PetscFunctionReturn(PETSC_SUCCESS);
3304 }
3305 
3306 PetscErrorCode MatSeqDenseSetPreallocation_SeqDense(Mat B, PetscScalar *data)
3307 {
3308   Mat_SeqDense *b = (Mat_SeqDense *)B->data;
3309 
3310   PetscFunctionBegin;
3311   PetscCheck(!b->matinuse, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Need to call MatDenseRestoreSubMatrix() first");
3312   B->preallocated = PETSC_TRUE;
3313 
3314   PetscCall(PetscLayoutSetUp(B->rmap));
3315   PetscCall(PetscLayoutSetUp(B->cmap));
3316 
3317   if (b->lda <= 0) PetscCall(PetscBLASIntCast(B->rmap->n, &b->lda));
3318 
3319   if (!data) { /* petsc-allocated storage */
3320     if (!b->user_alloc) PetscCall(PetscFree(b->v));
3321     PetscCall(PetscCalloc1((size_t)b->lda * B->cmap->n, &b->v));
3322 
3323     b->user_alloc = PETSC_FALSE;
3324   } else { /* user-allocated storage */
3325     if (!b->user_alloc) PetscCall(PetscFree(b->v));
3326     b->v          = data;
3327     b->user_alloc = PETSC_TRUE;
3328   }
3329   B->assembled = PETSC_TRUE;
3330   PetscFunctionReturn(PETSC_SUCCESS);
3331 }
3332 
3333 #if defined(PETSC_HAVE_ELEMENTAL)
3334 PETSC_INTERN PetscErrorCode MatConvert_SeqDense_Elemental(Mat A, MatType newtype, MatReuse reuse, Mat *newmat)
3335 {
3336   Mat                mat_elemental;
3337   const PetscScalar *array;
3338   PetscScalar       *v_colwise;
3339   PetscInt           M = A->rmap->N, N = A->cmap->N, i, j, k, *rows, *cols;
3340 
3341   PetscFunctionBegin;
3342   PetscCall(PetscMalloc3(M * N, &v_colwise, M, &rows, N, &cols));
3343   PetscCall(MatDenseGetArrayRead(A, &array));
3344   /* convert column-wise array into row-wise v_colwise, see MatSetValues_Elemental() */
3345   k = 0;
3346   for (j = 0; j < N; j++) {
3347     cols[j] = j;
3348     for (i = 0; i < M; i++) v_colwise[j * M + i] = array[k++];
3349   }
3350   for (i = 0; i < M; i++) rows[i] = i;
3351   PetscCall(MatDenseRestoreArrayRead(A, &array));
3352 
3353   PetscCall(MatCreate(PetscObjectComm((PetscObject)A), &mat_elemental));
3354   PetscCall(MatSetSizes(mat_elemental, PETSC_DECIDE, PETSC_DECIDE, M, N));
3355   PetscCall(MatSetType(mat_elemental, MATELEMENTAL));
3356   PetscCall(MatSetUp(mat_elemental));
3357 
3358   /* PETSc-Elemental interaface uses axpy for setting off-processor entries, only ADD_VALUES is allowed */
3359   PetscCall(MatSetValues(mat_elemental, M, rows, N, cols, v_colwise, ADD_VALUES));
3360   PetscCall(MatAssemblyBegin(mat_elemental, MAT_FINAL_ASSEMBLY));
3361   PetscCall(MatAssemblyEnd(mat_elemental, MAT_FINAL_ASSEMBLY));
3362   PetscCall(PetscFree3(v_colwise, rows, cols));
3363 
3364   if (reuse == MAT_INPLACE_MATRIX) {
3365     PetscCall(MatHeaderReplace(A, &mat_elemental));
3366   } else {
3367     *newmat = mat_elemental;
3368   }
3369   PetscFunctionReturn(PETSC_SUCCESS);
3370 }
3371 #endif
3372 
3373 PetscErrorCode MatDenseSetLDA_SeqDense(Mat B, PetscInt lda)
3374 {
3375   Mat_SeqDense *b = (Mat_SeqDense *)B->data;
3376   PetscBool     data;
3377 
3378   PetscFunctionBegin;
3379   data = (B->rmap->n > 0 && B->cmap->n > 0) ? (b->v ? PETSC_TRUE : PETSC_FALSE) : PETSC_FALSE;
3380   PetscCheck(b->user_alloc || !data || b->lda == lda, PETSC_COMM_SELF, PETSC_ERR_ORDER, "LDA cannot be changed after allocation of internal storage");
3381   PetscCheck(lda >= B->rmap->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "LDA %" PetscInt_FMT " must be at least matrix dimension %" PetscInt_FMT, lda, B->rmap->n);
3382   PetscCall(PetscBLASIntCast(lda, &b->lda));
3383   PetscFunctionReturn(PETSC_SUCCESS);
3384 }
3385 
3386 PetscErrorCode MatCreateMPIMatConcatenateSeqMat_SeqDense(MPI_Comm comm, Mat inmat, PetscInt n, MatReuse scall, Mat *outmat)
3387 {
3388   PetscFunctionBegin;
3389   PetscCall(MatCreateMPIMatConcatenateSeqMat_MPIDense(comm, inmat, n, scall, outmat));
3390   PetscFunctionReturn(PETSC_SUCCESS);
3391 }
3392 
3393 PetscErrorCode MatDenseCreateColumnVec_Private(Mat A, Vec *v)
3394 {
3395   PetscBool   isstd, iskok, iscuda, iship;
3396   PetscMPIInt size;
3397 #if PetscDefined(HAVE_CUDA) || PetscDefined(HAVE_HIP)
3398   /* we pass the data of A, to prevent allocating needless GPU memory the first time VecCUPMPlaceArray is called. */
3399   const PetscScalar *a;
3400 #endif
3401 
3402   PetscFunctionBegin;
3403   *v = NULL;
3404   PetscCall(PetscStrcmpAny(A->defaultvectype, &isstd, VECSTANDARD, VECSEQ, VECMPI, ""));
3405   PetscCall(PetscStrcmpAny(A->defaultvectype, &iskok, VECKOKKOS, VECSEQKOKKOS, VECMPIKOKKOS, ""));
3406   PetscCall(PetscStrcmpAny(A->defaultvectype, &iscuda, VECCUDA, VECSEQCUDA, VECMPICUDA, ""));
3407   PetscCall(PetscStrcmpAny(A->defaultvectype, &iship, VECHIP, VECSEQHIP, VECMPIHIP, ""));
3408   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)A), &size));
3409   if (isstd) {
3410     if (size > 1) PetscCall(VecCreateMPIWithArray(PetscObjectComm((PetscObject)A), A->rmap->bs, A->rmap->n, A->rmap->N, NULL, v));
3411     else PetscCall(VecCreateSeqWithArray(PetscObjectComm((PetscObject)A), A->rmap->bs, A->rmap->n, NULL, v));
3412   } else if (iskok) {
3413     PetscCheck(PetscDefined(HAVE_KOKKOS_KERNELS), PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Reconfigure using KOKKOS kernels support");
3414 #if PetscDefined(HAVE_KOKKOS_KERNELS)
3415     if (size > 1) PetscCall(VecCreateMPIKokkosWithArray(PetscObjectComm((PetscObject)A), A->rmap->bs, A->rmap->n, A->rmap->N, NULL, v));
3416     else PetscCall(VecCreateSeqKokkosWithArray(PetscObjectComm((PetscObject)A), A->rmap->bs, A->rmap->n, NULL, v));
3417 #endif
3418   } else if (iscuda) {
3419     PetscCheck(PetscDefined(HAVE_CUDA), PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Reconfigure using CUDA support");
3420 #if PetscDefined(HAVE_CUDA)
3421     PetscCall(MatDenseCUDAGetArrayRead(A, &a));
3422     if (size > 1) PetscCall(VecCreateMPICUDAWithArrays(PetscObjectComm((PetscObject)A), A->rmap->bs, A->rmap->n, A->rmap->N, NULL, a, v));
3423     else PetscCall(VecCreateSeqCUDAWithArrays(PetscObjectComm((PetscObject)A), A->rmap->bs, A->rmap->n, NULL, a, v));
3424 #endif
3425   } else if (iship) {
3426     PetscCheck(PetscDefined(HAVE_HIP), PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Reconfigure using HIP support");
3427 #if PetscDefined(HAVE_HIP)
3428     PetscCall(MatDenseHIPGetArrayRead(A, &a));
3429     if (size > 1) PetscCall(VecCreateMPIHIPWithArrays(PetscObjectComm((PetscObject)A), A->rmap->bs, A->rmap->n, A->rmap->N, NULL, a, v));
3430     else PetscCall(VecCreateSeqHIPWithArrays(PetscObjectComm((PetscObject)A), A->rmap->bs, A->rmap->n, NULL, a, v));
3431 #endif
3432   }
3433   PetscCheck(*v, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Not coded for type %s", A->defaultvectype);
3434   PetscFunctionReturn(PETSC_SUCCESS);
3435 }
3436 
3437 PetscErrorCode MatDenseGetColumnVec_SeqDense(Mat A, PetscInt col, Vec *v)
3438 {
3439   Mat_SeqDense *a = (Mat_SeqDense *)A->data;
3440 
3441   PetscFunctionBegin;
3442   PetscCheck(!a->vecinuse, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Need to call MatDenseRestoreColumnVec() first");
3443   PetscCheck(!a->matinuse, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Need to call MatDenseRestoreSubMatrix() first");
3444   if (!a->cvec) PetscCall(MatDenseCreateColumnVec_Private(A, &a->cvec));
3445   a->vecinuse = col + 1;
3446   PetscCall(MatDenseGetArray(A, (PetscScalar **)&a->ptrinuse));
3447   PetscCall(VecPlaceArray(a->cvec, a->ptrinuse + (size_t)col * (size_t)a->lda));
3448   *v = a->cvec;
3449   PetscFunctionReturn(PETSC_SUCCESS);
3450 }
3451 
3452 PetscErrorCode MatDenseRestoreColumnVec_SeqDense(Mat A, PetscInt col, Vec *v)
3453 {
3454   Mat_SeqDense *a = (Mat_SeqDense *)A->data;
3455 
3456   PetscFunctionBegin;
3457   PetscCheck(a->vecinuse, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Need to call MatDenseGetColumnVec() first");
3458   PetscCheck(a->cvec, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Missing internal column vector");
3459   VecCheckAssembled(a->cvec);
3460   a->vecinuse = 0;
3461   PetscCall(MatDenseRestoreArray(A, (PetscScalar **)&a->ptrinuse));
3462   PetscCall(VecResetArray(a->cvec));
3463   if (v) *v = NULL;
3464   PetscFunctionReturn(PETSC_SUCCESS);
3465 }
3466 
3467 PetscErrorCode MatDenseGetColumnVecRead_SeqDense(Mat A, PetscInt col, Vec *v)
3468 {
3469   Mat_SeqDense *a = (Mat_SeqDense *)A->data;
3470 
3471   PetscFunctionBegin;
3472   PetscCheck(!a->vecinuse, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Need to call MatDenseRestoreColumnVec() first");
3473   PetscCheck(!a->matinuse, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Need to call MatDenseRestoreSubMatrix() first");
3474   if (!a->cvec) PetscCall(MatDenseCreateColumnVec_Private(A, &a->cvec));
3475   a->vecinuse = col + 1;
3476   PetscCall(MatDenseGetArrayRead(A, &a->ptrinuse));
3477   PetscCall(VecPlaceArray(a->cvec, PetscSafePointerPlusOffset(a->ptrinuse, (size_t)col * (size_t)a->lda)));
3478   PetscCall(VecLockReadPush(a->cvec));
3479   *v = a->cvec;
3480   PetscFunctionReturn(PETSC_SUCCESS);
3481 }
3482 
3483 PetscErrorCode MatDenseRestoreColumnVecRead_SeqDense(Mat A, PetscInt col, Vec *v)
3484 {
3485   Mat_SeqDense *a = (Mat_SeqDense *)A->data;
3486 
3487   PetscFunctionBegin;
3488   PetscCheck(a->vecinuse, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Need to call MatDenseGetColumnVec() first");
3489   PetscCheck(a->cvec, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Missing internal column vector");
3490   VecCheckAssembled(a->cvec);
3491   a->vecinuse = 0;
3492   PetscCall(MatDenseRestoreArrayRead(A, &a->ptrinuse));
3493   PetscCall(VecLockReadPop(a->cvec));
3494   PetscCall(VecResetArray(a->cvec));
3495   if (v) *v = NULL;
3496   PetscFunctionReturn(PETSC_SUCCESS);
3497 }
3498 
3499 PetscErrorCode MatDenseGetColumnVecWrite_SeqDense(Mat A, PetscInt col, Vec *v)
3500 {
3501   Mat_SeqDense *a = (Mat_SeqDense *)A->data;
3502 
3503   PetscFunctionBegin;
3504   PetscCheck(!a->vecinuse, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Need to call MatDenseRestoreColumnVec() first");
3505   PetscCheck(!a->matinuse, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Need to call MatDenseRestoreSubMatrix() first");
3506   if (!a->cvec) PetscCall(MatDenseCreateColumnVec_Private(A, &a->cvec));
3507   a->vecinuse = col + 1;
3508   PetscCall(MatDenseGetArrayWrite(A, (PetscScalar **)&a->ptrinuse));
3509   PetscCall(VecPlaceArray(a->cvec, PetscSafePointerPlusOffset(a->ptrinuse, (size_t)col * (size_t)a->lda)));
3510   *v = a->cvec;
3511   PetscFunctionReturn(PETSC_SUCCESS);
3512 }
3513 
3514 PetscErrorCode MatDenseRestoreColumnVecWrite_SeqDense(Mat A, PetscInt col, Vec *v)
3515 {
3516   Mat_SeqDense *a = (Mat_SeqDense *)A->data;
3517 
3518   PetscFunctionBegin;
3519   PetscCheck(a->vecinuse, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Need to call MatDenseGetColumnVec() first");
3520   PetscCheck(a->cvec, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Missing internal column vector");
3521   VecCheckAssembled(a->cvec);
3522   a->vecinuse = 0;
3523   PetscCall(MatDenseRestoreArrayWrite(A, (PetscScalar **)&a->ptrinuse));
3524   PetscCall(VecResetArray(a->cvec));
3525   if (v) *v = NULL;
3526   PetscFunctionReturn(PETSC_SUCCESS);
3527 }
3528 
3529 PetscErrorCode MatDenseGetSubMatrix_SeqDense(Mat A, PetscInt rbegin, PetscInt rend, PetscInt cbegin, PetscInt cend, Mat *v)
3530 {
3531   Mat_SeqDense *a = (Mat_SeqDense *)A->data;
3532 
3533   PetscFunctionBegin;
3534   PetscCheck(!a->vecinuse, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Need to call MatDenseRestoreColumnVec() first");
3535   PetscCheck(!a->matinuse, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Need to call MatDenseRestoreSubMatrix() first");
3536   if (a->cmat && (cend - cbegin != a->cmat->cmap->N || rend - rbegin != a->cmat->rmap->N)) PetscCall(MatDestroy(&a->cmat));
3537   if (!a->cmat) {
3538     PetscCall(MatCreateDense(PetscObjectComm((PetscObject)A), rend - rbegin, PETSC_DECIDE, rend - rbegin, cend - cbegin, PetscSafePointerPlusOffset(a->v, rbegin + (size_t)cbegin * a->lda), &a->cmat));
3539   } else {
3540     PetscCall(MatDensePlaceArray(a->cmat, PetscSafePointerPlusOffset(a->v, rbegin + (size_t)cbegin * a->lda)));
3541   }
3542   PetscCall(MatDenseSetLDA(a->cmat, a->lda));
3543   a->matinuse = cbegin + 1;
3544   *v          = a->cmat;
3545 #if defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
3546   A->offloadmask = PETSC_OFFLOAD_CPU;
3547 #endif
3548   PetscFunctionReturn(PETSC_SUCCESS);
3549 }
3550 
3551 PetscErrorCode MatDenseRestoreSubMatrix_SeqDense(Mat A, Mat *v)
3552 {
3553   Mat_SeqDense *a = (Mat_SeqDense *)A->data;
3554 
3555   PetscFunctionBegin;
3556   PetscCheck(a->matinuse, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Need to call MatDenseGetSubMatrix() first");
3557   PetscCheck(a->cmat, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Missing internal column matrix");
3558   PetscCheck(*v == a->cmat, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Not the matrix obtained from MatDenseGetSubMatrix()");
3559   a->matinuse = 0;
3560   PetscCall(MatDenseResetArray(a->cmat));
3561   if (v) *v = NULL;
3562 #if defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
3563   A->offloadmask = PETSC_OFFLOAD_CPU;
3564 #endif
3565   PetscFunctionReturn(PETSC_SUCCESS);
3566 }
3567 
3568 /*MC
3569    MATSEQDENSE - MATSEQDENSE = "seqdense" - A matrix type to be used for sequential dense matrices.
3570 
3571    Options Database Key:
3572 . -mat_type seqdense - sets the matrix type to `MATSEQDENSE` during a call to `MatSetFromOptions()`
3573 
3574   Level: beginner
3575 
3576 .seealso: [](ch_matrices), `Mat`, `MATSEQDENSE`, `MatCreateSeqDense()`
3577 M*/
3578 PetscErrorCode MatCreate_SeqDense(Mat B)
3579 {
3580   Mat_SeqDense *b;
3581   PetscMPIInt   size;
3582 
3583   PetscFunctionBegin;
3584   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)B), &size));
3585   PetscCheck(size <= 1, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Comm must be of size 1");
3586 
3587   PetscCall(PetscNew(&b));
3588   B->data   = (void *)b;
3589   B->ops[0] = MatOps_Values;
3590 
3591   b->roworiented = PETSC_TRUE;
3592 
3593   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatQRFactor_C", MatQRFactor_SeqDense));
3594   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatDenseGetLDA_C", MatDenseGetLDA_SeqDense));
3595   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatDenseSetLDA_C", MatDenseSetLDA_SeqDense));
3596   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatDenseGetArray_C", MatDenseGetArray_SeqDense));
3597   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatDenseRestoreArray_C", MatDenseRestoreArray_SeqDense));
3598   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatDensePlaceArray_C", MatDensePlaceArray_SeqDense));
3599   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatDenseResetArray_C", MatDenseResetArray_SeqDense));
3600   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatDenseReplaceArray_C", MatDenseReplaceArray_SeqDense));
3601   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatDenseGetArrayRead_C", MatDenseGetArray_SeqDense));
3602   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatDenseRestoreArrayRead_C", MatDenseRestoreArray_SeqDense));
3603   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatDenseGetArrayWrite_C", MatDenseGetArray_SeqDense));
3604   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatDenseRestoreArrayWrite_C", MatDenseRestoreArray_SeqDense));
3605   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatConvert_seqdense_seqaij_C", MatConvert_SeqDense_SeqAIJ));
3606 #if defined(PETSC_HAVE_ELEMENTAL)
3607   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatConvert_seqdense_elemental_C", MatConvert_SeqDense_Elemental));
3608 #endif
3609 #if defined(PETSC_HAVE_SCALAPACK)
3610   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatConvert_seqdense_scalapack_C", MatConvert_Dense_ScaLAPACK));
3611 #endif
3612 #if defined(PETSC_HAVE_CUDA)
3613   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatConvert_seqdense_seqdensecuda_C", MatConvert_SeqDense_SeqDenseCUDA));
3614   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatProductSetFromOptions_seqdensecuda_seqdensecuda_C", MatProductSetFromOptions_SeqDense));
3615   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatProductSetFromOptions_seqdensecuda_seqdense_C", MatProductSetFromOptions_SeqDense));
3616   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatProductSetFromOptions_seqdense_seqdensecuda_C", MatProductSetFromOptions_SeqDense));
3617 #endif
3618 #if defined(PETSC_HAVE_HIP)
3619   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatConvert_seqdense_seqdensehip_C", MatConvert_SeqDense_SeqDenseHIP));
3620   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatProductSetFromOptions_seqdensehip_seqdensehip_C", MatProductSetFromOptions_SeqDense));
3621   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatProductSetFromOptions_seqdensehip_seqdense_C", MatProductSetFromOptions_SeqDense));
3622   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatProductSetFromOptions_seqdense_seqdensehip_C", MatProductSetFromOptions_SeqDense));
3623 #endif
3624   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatSeqDenseSetPreallocation_C", MatSeqDenseSetPreallocation_SeqDense));
3625   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatProductSetFromOptions_seqaij_seqdense_C", MatProductSetFromOptions_SeqAIJ_SeqDense));
3626   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatProductSetFromOptions_seqdense_seqdense_C", MatProductSetFromOptions_SeqDense));
3627   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatProductSetFromOptions_seqbaij_seqdense_C", MatProductSetFromOptions_SeqXBAIJ_SeqDense));
3628   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatProductSetFromOptions_seqsbaij_seqdense_C", MatProductSetFromOptions_SeqXBAIJ_SeqDense));
3629 
3630   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatDenseGetColumn_C", MatDenseGetColumn_SeqDense));
3631   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatDenseRestoreColumn_C", MatDenseRestoreColumn_SeqDense));
3632   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatDenseGetColumnVec_C", MatDenseGetColumnVec_SeqDense));
3633   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatDenseRestoreColumnVec_C", MatDenseRestoreColumnVec_SeqDense));
3634   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatDenseGetColumnVecRead_C", MatDenseGetColumnVecRead_SeqDense));
3635   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatDenseRestoreColumnVecRead_C", MatDenseRestoreColumnVecRead_SeqDense));
3636   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatDenseGetColumnVecWrite_C", MatDenseGetColumnVecWrite_SeqDense));
3637   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatDenseRestoreColumnVecWrite_C", MatDenseRestoreColumnVecWrite_SeqDense));
3638   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatDenseGetSubMatrix_C", MatDenseGetSubMatrix_SeqDense));
3639   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatDenseRestoreSubMatrix_C", MatDenseRestoreSubMatrix_SeqDense));
3640   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatMultAddColumnRange_C", MatMultAddColumnRange_SeqDense));
3641   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatMultHermitianTransposeColumnRange_C", MatMultHermitianTransposeColumnRange_SeqDense));
3642   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatMultHermitianTransposeAddColumnRange_C", MatMultHermitianTransposeAddColumnRange_SeqDense));
3643   PetscCall(PetscObjectChangeTypeName((PetscObject)B, MATSEQDENSE));
3644   PetscFunctionReturn(PETSC_SUCCESS);
3645 }
3646 
3647 /*@C
3648   MatDenseGetColumn - gives access to a column of a dense matrix. This is only the local part of the column. You MUST call `MatDenseRestoreColumn()` to avoid memory bleeding.
3649 
3650   Not Collective
3651 
3652   Input Parameters:
3653 + A   - a `MATSEQDENSE` or `MATMPIDENSE` matrix
3654 - col - column index
3655 
3656   Output Parameter:
3657 . vals - pointer to the data
3658 
3659   Level: intermediate
3660 
3661   Note:
3662   Use `MatDenseGetColumnVec()` to get access to a column of a `MATDENSE` treated as a `Vec`
3663 
3664 .seealso: [](ch_matrices), `Mat`, `MATDENSE`, `MatDenseRestoreColumn()`, `MatDenseGetColumnVec()`
3665 @*/
3666 PetscErrorCode MatDenseGetColumn(Mat A, PetscInt col, PetscScalar *vals[])
3667 {
3668   PetscFunctionBegin;
3669   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
3670   PetscValidLogicalCollectiveInt(A, col, 2);
3671   PetscAssertPointer(vals, 3);
3672   PetscUseMethod(A, "MatDenseGetColumn_C", (Mat, PetscInt, PetscScalar **), (A, col, vals));
3673   PetscFunctionReturn(PETSC_SUCCESS);
3674 }
3675 
3676 /*@C
3677   MatDenseRestoreColumn - returns access to a column of a `MATDENSE` matrix which is returned by `MatDenseGetColumn()`.
3678 
3679   Not Collective
3680 
3681   Input Parameters:
3682 + A    - a `MATSEQDENSE` or `MATMPIDENSE` matrix
3683 - vals - pointer to the data (may be `NULL`)
3684 
3685   Level: intermediate
3686 
3687 .seealso: [](ch_matrices), `Mat`, `MATDENSE`, `MatDenseGetColumn()`
3688 @*/
3689 PetscErrorCode MatDenseRestoreColumn(Mat A, PetscScalar *vals[])
3690 {
3691   PetscFunctionBegin;
3692   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
3693   PetscAssertPointer(vals, 2);
3694   PetscUseMethod(A, "MatDenseRestoreColumn_C", (Mat, PetscScalar **), (A, vals));
3695   PetscFunctionReturn(PETSC_SUCCESS);
3696 }
3697 
3698 /*@
3699   MatDenseGetColumnVec - Gives read-write access to a column of a `MATDENSE` matrix, represented as a `Vec`.
3700 
3701   Collective
3702 
3703   Input Parameters:
3704 + A   - the `Mat` object
3705 - col - the column index
3706 
3707   Output Parameter:
3708 . v - the vector
3709 
3710   Level: intermediate
3711 
3712   Notes:
3713   The vector is owned by PETSc. Users need to call `MatDenseRestoreColumnVec()` when the vector is no longer needed.
3714 
3715   Use `MatDenseGetColumnVecRead()` to obtain read-only access or `MatDenseGetColumnVecWrite()` for write-only access.
3716 
3717 .seealso: [](ch_matrices), `Mat`, `MATDENSE`, `MATDENSECUDA`, `MATDENSEHIP`, `MatDenseGetColumnVecRead()`, `MatDenseGetColumnVecWrite()`, `MatDenseRestoreColumnVec()`, `MatDenseRestoreColumnVecRead()`, `MatDenseRestoreColumnVecWrite()`, `MatDenseGetColumn()`
3718 @*/
3719 PetscErrorCode MatDenseGetColumnVec(Mat A, PetscInt col, Vec *v)
3720 {
3721   PetscFunctionBegin;
3722   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
3723   PetscValidType(A, 1);
3724   PetscValidLogicalCollectiveInt(A, col, 2);
3725   PetscAssertPointer(v, 3);
3726   PetscCheck(A->preallocated, PetscObjectComm((PetscObject)A), PETSC_ERR_ORDER, "Matrix not preallocated");
3727   PetscCheck(col >= 0 && col < A->cmap->N, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONG, "Invalid col %" PetscInt_FMT ", should be in [0,%" PetscInt_FMT ")", col, A->cmap->N);
3728   PetscUseMethod(A, "MatDenseGetColumnVec_C", (Mat, PetscInt, Vec *), (A, col, v));
3729   PetscFunctionReturn(PETSC_SUCCESS);
3730 }
3731 
3732 /*@
3733   MatDenseRestoreColumnVec - Returns access to a column of a dense matrix obtained from `MatDenseGetColumnVec()`.
3734 
3735   Collective
3736 
3737   Input Parameters:
3738 + A   - the `Mat` object
3739 . col - the column index
3740 - v   - the `Vec` object (may be `NULL`)
3741 
3742   Level: intermediate
3743 
3744 .seealso: [](ch_matrices), `Mat`, `MATDENSE`, `MATDENSECUDA`, `MATDENSEHIP`, `MatDenseGetColumnVec()`, `MatDenseGetColumnVecRead()`, `MatDenseGetColumnVecWrite()`, `MatDenseRestoreColumnVecRead()`, `MatDenseRestoreColumnVecWrite()`
3745 @*/
3746 PetscErrorCode MatDenseRestoreColumnVec(Mat A, PetscInt col, Vec *v)
3747 {
3748   PetscFunctionBegin;
3749   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
3750   PetscValidType(A, 1);
3751   PetscValidLogicalCollectiveInt(A, col, 2);
3752   PetscCheck(A->preallocated, PetscObjectComm((PetscObject)A), PETSC_ERR_ORDER, "Matrix not preallocated");
3753   PetscCheck(col >= 0 && col < A->cmap->N, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONG, "Invalid col %" PetscInt_FMT ", should be in [0,%" PetscInt_FMT ")", col, A->cmap->N);
3754   PetscUseMethod(A, "MatDenseRestoreColumnVec_C", (Mat, PetscInt, Vec *), (A, col, v));
3755   PetscFunctionReturn(PETSC_SUCCESS);
3756 }
3757 
3758 /*@
3759   MatDenseGetColumnVecRead - Gives read-only access to a column of a dense matrix, represented as a `Vec`.
3760 
3761   Collective
3762 
3763   Input Parameters:
3764 + A   - the `Mat` object
3765 - col - the column index
3766 
3767   Output Parameter:
3768 . v - the vector
3769 
3770   Level: intermediate
3771 
3772   Notes:
3773   The vector is owned by PETSc and users cannot modify it.
3774 
3775   Users need to call `MatDenseRestoreColumnVecRead()` when the vector is no longer needed.
3776 
3777   Use `MatDenseGetColumnVec()` to obtain read-write access or `MatDenseGetColumnVecWrite()` for write-only access.
3778 
3779 .seealso: [](ch_matrices), `Mat`, `MATDENSE`, `MATDENSECUDA`, `MATDENSEHIP`, `MatDenseGetColumnVec()`, `MatDenseGetColumnVecWrite()`, `MatDenseRestoreColumnVec()`, `MatDenseRestoreColumnVecRead()`, `MatDenseRestoreColumnVecWrite()`
3780 @*/
3781 PetscErrorCode MatDenseGetColumnVecRead(Mat A, PetscInt col, Vec *v)
3782 {
3783   PetscFunctionBegin;
3784   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
3785   PetscValidType(A, 1);
3786   PetscValidLogicalCollectiveInt(A, col, 2);
3787   PetscAssertPointer(v, 3);
3788   PetscCheck(A->preallocated, PetscObjectComm((PetscObject)A), PETSC_ERR_ORDER, "Matrix not preallocated");
3789   PetscCheck(col >= 0 && col < A->cmap->N, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONG, "Invalid col %" PetscInt_FMT ", should be in [0,%" PetscInt_FMT ")", col, A->cmap->N);
3790   PetscUseMethod(A, "MatDenseGetColumnVecRead_C", (Mat, PetscInt, Vec *), (A, col, v));
3791   PetscFunctionReturn(PETSC_SUCCESS);
3792 }
3793 
3794 /*@
3795   MatDenseRestoreColumnVecRead - Returns access to a column of a dense matrix obtained from `MatDenseGetColumnVecRead()`.
3796 
3797   Collective
3798 
3799   Input Parameters:
3800 + A   - the `Mat` object
3801 . col - the column index
3802 - v   - the `Vec` object (may be `NULL`)
3803 
3804   Level: intermediate
3805 
3806 .seealso: [](ch_matrices), `Mat`, `MATDENSE`, `MATDENSECUDA`, `MATDENSEHIP`, `MatDenseGetColumnVec()`, `MatDenseGetColumnVecRead()`, `MatDenseGetColumnVecWrite()`, `MatDenseRestoreColumnVec()`, `MatDenseRestoreColumnVecWrite()`
3807 @*/
3808 PetscErrorCode MatDenseRestoreColumnVecRead(Mat A, PetscInt col, Vec *v)
3809 {
3810   PetscFunctionBegin;
3811   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
3812   PetscValidType(A, 1);
3813   PetscValidLogicalCollectiveInt(A, col, 2);
3814   PetscCheck(A->preallocated, PetscObjectComm((PetscObject)A), PETSC_ERR_ORDER, "Matrix not preallocated");
3815   PetscCheck(col >= 0 && col < A->cmap->N, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONG, "Invalid col %" PetscInt_FMT ", should be in [0,%" PetscInt_FMT ")", col, A->cmap->N);
3816   PetscUseMethod(A, "MatDenseRestoreColumnVecRead_C", (Mat, PetscInt, Vec *), (A, col, v));
3817   PetscFunctionReturn(PETSC_SUCCESS);
3818 }
3819 
3820 /*@
3821   MatDenseGetColumnVecWrite - Gives write-only access to a column of a dense matrix, represented as a `Vec`.
3822 
3823   Collective
3824 
3825   Input Parameters:
3826 + A   - the `Mat` object
3827 - col - the column index
3828 
3829   Output Parameter:
3830 . v - the vector
3831 
3832   Level: intermediate
3833 
3834   Notes:
3835   The vector is owned by PETSc. Users need to call `MatDenseRestoreColumnVecWrite()` when the vector is no longer needed.
3836 
3837   Use `MatDenseGetColumnVec()` to obtain read-write access or `MatDenseGetColumnVecRead()` for read-only access.
3838 
3839 .seealso: [](ch_matrices), `Mat`, `MATDENSE`, `MATDENSECUDA`, `MATDENSEHIP`, `MatDenseGetColumnVec()`, `MatDenseGetColumnVecRead()`, `MatDenseRestoreColumnVec()`, `MatDenseRestoreColumnVecRead()`, `MatDenseRestoreColumnVecWrite()`
3840 @*/
3841 PetscErrorCode MatDenseGetColumnVecWrite(Mat A, PetscInt col, Vec *v)
3842 {
3843   PetscFunctionBegin;
3844   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
3845   PetscValidType(A, 1);
3846   PetscValidLogicalCollectiveInt(A, col, 2);
3847   PetscAssertPointer(v, 3);
3848   PetscCheck(A->preallocated, PetscObjectComm((PetscObject)A), PETSC_ERR_ORDER, "Matrix not preallocated");
3849   PetscCheck(col >= 0 && col < A->cmap->N, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONG, "Invalid col %" PetscInt_FMT ", should be in [0,%" PetscInt_FMT ")", col, A->cmap->N);
3850   PetscUseMethod(A, "MatDenseGetColumnVecWrite_C", (Mat, PetscInt, Vec *), (A, col, v));
3851   PetscFunctionReturn(PETSC_SUCCESS);
3852 }
3853 
3854 /*@
3855   MatDenseRestoreColumnVecWrite - Returns access to a column of a dense matrix obtained from `MatDenseGetColumnVecWrite()`.
3856 
3857   Collective
3858 
3859   Input Parameters:
3860 + A   - the `Mat` object
3861 . col - the column index
3862 - v   - the `Vec` object (may be `NULL`)
3863 
3864   Level: intermediate
3865 
3866 .seealso: [](ch_matrices), `Mat`, `MATDENSE`, `MATDENSECUDA`, `MATDENSEHIP`, `MatDenseGetColumnVec()`, `MatDenseGetColumnVecRead()`, `MatDenseGetColumnVecWrite()`, `MatDenseRestoreColumnVec()`, `MatDenseRestoreColumnVecRead()`
3867 @*/
3868 PetscErrorCode MatDenseRestoreColumnVecWrite(Mat A, PetscInt col, Vec *v)
3869 {
3870   PetscFunctionBegin;
3871   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
3872   PetscValidType(A, 1);
3873   PetscValidLogicalCollectiveInt(A, col, 2);
3874   PetscCheck(A->preallocated, PetscObjectComm((PetscObject)A), PETSC_ERR_ORDER, "Matrix not preallocated");
3875   PetscCheck(col >= 0 && col < A->cmap->N, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONG, "Invalid col %" PetscInt_FMT ", should be in [0,%" PetscInt_FMT ")", col, A->cmap->N);
3876   PetscUseMethod(A, "MatDenseRestoreColumnVecWrite_C", (Mat, PetscInt, Vec *), (A, col, v));
3877   PetscFunctionReturn(PETSC_SUCCESS);
3878 }
3879 
3880 /*@
3881   MatDenseGetSubMatrix - Gives access to a block of rows and columns of a dense matrix, represented as a `Mat`.
3882 
3883   Collective
3884 
3885   Input Parameters:
3886 + A      - the `Mat` object
3887 . rbegin - the first global row index in the block (if `PETSC_DECIDE`, is 0)
3888 . rend   - the global row index past the last one in the block (if `PETSC_DECIDE`, is `M`)
3889 . cbegin - the first global column index in the block (if `PETSC_DECIDE`, is 0)
3890 - cend   - the global column index past the last one in the block (if `PETSC_DECIDE`, is `N`)
3891 
3892   Output Parameter:
3893 . v - the matrix
3894 
3895   Level: intermediate
3896 
3897   Notes:
3898   The matrix is owned by PETSc. Users need to call `MatDenseRestoreSubMatrix()` when the matrix is no longer needed.
3899 
3900   The output matrix is not redistributed by PETSc, so depending on the values of `rbegin` and `rend`, some processes may have no local rows.
3901 
3902 .seealso: [](ch_matrices), `Mat`, `MATDENSE`, `MATDENSECUDA`, `MATDENSEHIP`, `MatDenseGetColumnVec()`, `MatDenseRestoreColumnVec()`, `MatDenseRestoreSubMatrix()`
3903 @*/
3904 PetscErrorCode MatDenseGetSubMatrix(Mat A, PetscInt rbegin, PetscInt rend, PetscInt cbegin, PetscInt cend, Mat *v)
3905 {
3906   PetscFunctionBegin;
3907   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
3908   PetscValidType(A, 1);
3909   PetscValidLogicalCollectiveInt(A, rbegin, 2);
3910   PetscValidLogicalCollectiveInt(A, rend, 3);
3911   PetscValidLogicalCollectiveInt(A, cbegin, 4);
3912   PetscValidLogicalCollectiveInt(A, cend, 5);
3913   PetscAssertPointer(v, 6);
3914   if (rbegin == PETSC_DECIDE) rbegin = 0;
3915   if (rend == PETSC_DECIDE) rend = A->rmap->N;
3916   if (cbegin == PETSC_DECIDE) cbegin = 0;
3917   if (cend == PETSC_DECIDE) cend = A->cmap->N;
3918   PetscCheck(A->preallocated, PetscObjectComm((PetscObject)A), PETSC_ERR_ORDER, "Matrix not preallocated");
3919   PetscCheck(rbegin >= 0 && rbegin <= A->rmap->N, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONG, "Invalid rbegin %" PetscInt_FMT ", should be in [0,%" PetscInt_FMT "]", rbegin, A->rmap->N);
3920   PetscCheck(rend >= rbegin && rend <= A->rmap->N, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONG, "Invalid rend %" PetscInt_FMT ", should be in [%" PetscInt_FMT ",%" PetscInt_FMT "]", rend, rbegin, A->rmap->N);
3921   PetscCheck(cbegin >= 0 && cbegin <= A->cmap->N, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONG, "Invalid cbegin %" PetscInt_FMT ", should be in [0,%" PetscInt_FMT "]", cbegin, A->cmap->N);
3922   PetscCheck(cend >= cbegin && cend <= A->cmap->N, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONG, "Invalid cend %" PetscInt_FMT ", should be in [%" PetscInt_FMT ",%" PetscInt_FMT "]", cend, cbegin, A->cmap->N);
3923   PetscUseMethod(A, "MatDenseGetSubMatrix_C", (Mat, PetscInt, PetscInt, PetscInt, PetscInt, Mat *), (A, rbegin, rend, cbegin, cend, v));
3924   PetscFunctionReturn(PETSC_SUCCESS);
3925 }
3926 
3927 /*@
3928   MatDenseRestoreSubMatrix - Returns access to a block of columns of a dense matrix obtained from `MatDenseGetSubMatrix()`.
3929 
3930   Collective
3931 
3932   Input Parameters:
3933 + A - the `Mat` object
3934 - v - the `Mat` object (may be `NULL`)
3935 
3936   Level: intermediate
3937 
3938 .seealso: [](ch_matrices), `Mat`, `MATDENSE`, `MATDENSECUDA`, `MATDENSEHIP`, `MatDenseGetColumnVec()`, `MatDenseRestoreColumnVec()`, `MatDenseGetSubMatrix()`
3939 @*/
3940 PetscErrorCode MatDenseRestoreSubMatrix(Mat A, Mat *v)
3941 {
3942   PetscFunctionBegin;
3943   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
3944   PetscValidType(A, 1);
3945   PetscAssertPointer(v, 2);
3946   PetscUseMethod(A, "MatDenseRestoreSubMatrix_C", (Mat, Mat *), (A, v));
3947   PetscFunctionReturn(PETSC_SUCCESS);
3948 }
3949 
3950 #include <petscblaslapack.h>
3951 #include <petsc/private/kernels/blockinvert.h>
3952 
3953 PetscErrorCode MatSeqDenseInvert(Mat A)
3954 {
3955   PetscInt        m;
3956   const PetscReal shift = 0.0;
3957   PetscBool       allowzeropivot, zeropivotdetected = PETSC_FALSE;
3958   PetscScalar    *values;
3959 
3960   PetscFunctionBegin;
3961   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
3962   PetscCall(MatDenseGetArray(A, &values));
3963   PetscCall(MatGetLocalSize(A, &m, NULL));
3964   allowzeropivot = PetscNot(A->erroriffailure);
3965   /* factor and invert each block */
3966   switch (m) {
3967   case 1:
3968     values[0] = (PetscScalar)1.0 / (values[0] + shift);
3969     break;
3970   case 2:
3971     PetscCall(PetscKernel_A_gets_inverse_A_2(values, shift, allowzeropivot, &zeropivotdetected));
3972     if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
3973     break;
3974   case 3:
3975     PetscCall(PetscKernel_A_gets_inverse_A_3(values, shift, allowzeropivot, &zeropivotdetected));
3976     if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
3977     break;
3978   case 4:
3979     PetscCall(PetscKernel_A_gets_inverse_A_4(values, shift, allowzeropivot, &zeropivotdetected));
3980     if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
3981     break;
3982   case 5: {
3983     PetscScalar work[25];
3984     PetscInt    ipvt[5];
3985 
3986     PetscCall(PetscKernel_A_gets_inverse_A_5(values, ipvt, work, shift, allowzeropivot, &zeropivotdetected));
3987     if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
3988   } break;
3989   case 6:
3990     PetscCall(PetscKernel_A_gets_inverse_A_6(values, shift, allowzeropivot, &zeropivotdetected));
3991     if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
3992     break;
3993   case 7:
3994     PetscCall(PetscKernel_A_gets_inverse_A_7(values, shift, allowzeropivot, &zeropivotdetected));
3995     if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
3996     break;
3997   default: {
3998     PetscInt    *v_pivots, *IJ, j;
3999     PetscScalar *v_work;
4000 
4001     PetscCall(PetscMalloc3(m, &v_work, m, &v_pivots, m, &IJ));
4002     for (j = 0; j < m; j++) IJ[j] = j;
4003     PetscCall(PetscKernel_A_gets_inverse_A(m, values, v_pivots, v_work, allowzeropivot, &zeropivotdetected));
4004     if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
4005     PetscCall(PetscFree3(v_work, v_pivots, IJ));
4006   }
4007   }
4008   PetscCall(MatDenseRestoreArray(A, &values));
4009   PetscFunctionReturn(PETSC_SUCCESS);
4010 }
4011