xref: /petsc/src/mat/impls/dense/seq/dense.c (revision 89a8e22d45cf8ef376b46ea5983ec24985e49039)
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] + omega * (xt + v[i + i * m] * x[i]) / (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] + omega * (xt + v[i + i * m] * x[i]) / (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   Fortran Notes:
2173   `MatDenseGetArray()` Fortran binding is deprecated (since PETSc 3.19), use `MatDenseGetArrayF90()`
2174 
2175 .seealso: [](ch_matrices), `Mat`, `MATDENSE`, `MatDenseRestoreArray()`, `MatDenseGetArrayRead()`, `MatDenseRestoreArrayRead()`, `MatDenseGetArrayWrite()`, `MatDenseRestoreArrayWrite()`
2176 @*/
2177 PetscErrorCode MatDenseGetArray(Mat A, PetscScalar *array[])
2178 {
2179   PetscFunctionBegin;
2180   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
2181   PetscAssertPointer(array, 2);
2182   PetscUseMethod(A, "MatDenseGetArray_C", (Mat, PetscScalar **), (A, array));
2183   PetscFunctionReturn(PETSC_SUCCESS);
2184 }
2185 
2186 /*@C
2187   MatDenseRestoreArray - returns access to the array where the data for a `MATDENSE` matrix is stored obtained by `MatDenseGetArray()`
2188 
2189   Logically Collective
2190 
2191   Input Parameters:
2192 + A     - a dense matrix
2193 - array - pointer to the data (may be `NULL`)
2194 
2195   Level: intermediate
2196 
2197   Fortran Notes:
2198   `MatDenseRestoreArray()` Fortran binding is deprecated (since PETSc 3.19), use `MatDenseRestoreArrayF90()`
2199 
2200 .seealso: [](ch_matrices), `Mat`, `MATDENSE`, `MatDenseGetArray()`, `MatDenseGetArrayRead()`, `MatDenseRestoreArrayRead()`, `MatDenseGetArrayWrite()`, `MatDenseRestoreArrayWrite()`
2201 @*/
2202 PetscErrorCode MatDenseRestoreArray(Mat A, PetscScalar *array[])
2203 {
2204   PetscFunctionBegin;
2205   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
2206   if (array) PetscAssertPointer(array, 2);
2207   PetscUseMethod(A, "MatDenseRestoreArray_C", (Mat, PetscScalar **), (A, array));
2208   PetscCall(PetscObjectStateIncrease((PetscObject)A));
2209 #if defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
2210   A->offloadmask = PETSC_OFFLOAD_CPU;
2211 #endif
2212   PetscFunctionReturn(PETSC_SUCCESS);
2213 }
2214 
2215 /*@C
2216   MatDenseGetArrayRead - gives read-only access to the array where the data for a `MATDENSE` matrix is stored
2217 
2218   Not Collective
2219 
2220   Input Parameter:
2221 . A - a dense matrix
2222 
2223   Output Parameter:
2224 . array - pointer to the data
2225 
2226   Level: intermediate
2227 
2228 .seealso: [](ch_matrices), `Mat`, `MATDENSE`, `MatDenseRestoreArrayRead()`, `MatDenseGetArray()`, `MatDenseRestoreArray()`, `MatDenseGetArrayWrite()`, `MatDenseRestoreArrayWrite()`
2229 @*/
2230 PetscErrorCode MatDenseGetArrayRead(Mat A, const PetscScalar *array[])
2231 {
2232   PetscFunctionBegin;
2233   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
2234   PetscAssertPointer(array, 2);
2235   PetscUseMethod(A, "MatDenseGetArrayRead_C", (Mat, PetscScalar **), (A, (PetscScalar **)array));
2236   PetscFunctionReturn(PETSC_SUCCESS);
2237 }
2238 
2239 /*@C
2240   MatDenseRestoreArrayRead - returns access to the array where the data for a `MATDENSE` matrix is stored obtained by `MatDenseGetArrayRead()`
2241 
2242   Not Collective
2243 
2244   Input Parameters:
2245 + A     - a dense matrix
2246 - array - pointer to the data (may be `NULL`)
2247 
2248   Level: intermediate
2249 
2250 .seealso: [](ch_matrices), `Mat`, `MATDENSE`, `MatDenseGetArrayRead()`, `MatDenseGetArray()`, `MatDenseRestoreArray()`, `MatDenseGetArrayWrite()`, `MatDenseRestoreArrayWrite()`
2251 @*/
2252 PetscErrorCode MatDenseRestoreArrayRead(Mat A, const PetscScalar *array[])
2253 {
2254   PetscFunctionBegin;
2255   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
2256   if (array) PetscAssertPointer(array, 2);
2257   PetscUseMethod(A, "MatDenseRestoreArrayRead_C", (Mat, PetscScalar **), (A, (PetscScalar **)array));
2258   PetscFunctionReturn(PETSC_SUCCESS);
2259 }
2260 
2261 /*@C
2262   MatDenseGetArrayWrite - gives write-only access to the array where the data for a `MATDENSE` matrix is stored
2263 
2264   Not Collective
2265 
2266   Input Parameter:
2267 . A - a dense matrix
2268 
2269   Output Parameter:
2270 . array - pointer to the data
2271 
2272   Level: intermediate
2273 
2274 .seealso: [](ch_matrices), `Mat`, `MATDENSE`, `MatDenseRestoreArrayWrite()`, `MatDenseGetArray()`, `MatDenseRestoreArray()`, `MatDenseGetArrayRead()`, `MatDenseRestoreArrayRead()`
2275 @*/
2276 PetscErrorCode MatDenseGetArrayWrite(Mat A, PetscScalar *array[])
2277 {
2278   PetscFunctionBegin;
2279   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
2280   PetscAssertPointer(array, 2);
2281   PetscUseMethod(A, "MatDenseGetArrayWrite_C", (Mat, PetscScalar **), (A, array));
2282   PetscFunctionReturn(PETSC_SUCCESS);
2283 }
2284 
2285 /*@C
2286   MatDenseRestoreArrayWrite - returns access to the array where the data for a `MATDENSE` matrix is stored obtained by `MatDenseGetArrayWrite()`
2287 
2288   Not Collective
2289 
2290   Input Parameters:
2291 + A     - a dense matrix
2292 - array - pointer to the data (may be `NULL`)
2293 
2294   Level: intermediate
2295 
2296 .seealso: [](ch_matrices), `Mat`, `MATDENSE`, `MatDenseGetArrayWrite()`, `MatDenseGetArray()`, `MatDenseRestoreArray()`, `MatDenseGetArrayRead()`, `MatDenseRestoreArrayRead()`
2297 @*/
2298 PetscErrorCode MatDenseRestoreArrayWrite(Mat A, PetscScalar *array[])
2299 {
2300   PetscFunctionBegin;
2301   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
2302   if (array) PetscAssertPointer(array, 2);
2303   PetscUseMethod(A, "MatDenseRestoreArrayWrite_C", (Mat, PetscScalar **), (A, array));
2304   PetscCall(PetscObjectStateIncrease((PetscObject)A));
2305 #if defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
2306   A->offloadmask = PETSC_OFFLOAD_CPU;
2307 #endif
2308   PetscFunctionReturn(PETSC_SUCCESS);
2309 }
2310 
2311 /*@C
2312   MatDenseGetArrayAndMemType - gives read-write access to the array where the data for a `MATDENSE` matrix is stored
2313 
2314   Logically Collective
2315 
2316   Input Parameter:
2317 . A - a dense matrix
2318 
2319   Output Parameters:
2320 + array - pointer to the data
2321 - mtype - memory type of the returned pointer
2322 
2323   Level: intermediate
2324 
2325   Note:
2326   If the matrix is of a device type such as `MATDENSECUDA`, `MATDENSEHIP`, etc.,
2327   an array on device is always returned and is guaranteed to contain the matrix's latest data.
2328 
2329 .seealso: [](ch_matrices), `Mat`, `MATDENSE`, `MatDenseRestoreArrayAndMemType()`, `MatDenseGetArrayReadAndMemType()`, `MatDenseGetArrayWriteAndMemType()`, `MatDenseGetArrayRead()`,
2330    `MatDenseRestoreArrayRead()`, `MatDenseGetArrayWrite()`, `MatDenseRestoreArrayWrite()`, `MatSeqAIJGetCSRAndMemType()`
2331 @*/
2332 PetscErrorCode MatDenseGetArrayAndMemType(Mat A, PetscScalar *array[], PetscMemType *mtype)
2333 {
2334   PetscBool isMPI;
2335 
2336   PetscFunctionBegin;
2337   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
2338   PetscAssertPointer(array, 2);
2339   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 */
2340   PetscCall(PetscObjectBaseTypeCompare((PetscObject)A, MATMPIDENSE, &isMPI));
2341   if (isMPI) {
2342     /* Dispatch here so that the code can be reused for all subclasses of MATDENSE */
2343     PetscCall(MatDenseGetArrayAndMemType(((Mat_MPIDense *)A->data)->A, array, mtype));
2344   } else {
2345     PetscErrorCode (*fptr)(Mat, PetscScalar **, PetscMemType *);
2346 
2347     PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatDenseGetArrayAndMemType_C", &fptr));
2348     if (fptr) {
2349       PetscCall((*fptr)(A, array, mtype));
2350     } else {
2351       PetscUseMethod(A, "MatDenseGetArray_C", (Mat, PetscScalar **), (A, array));
2352       if (mtype) *mtype = PETSC_MEMTYPE_HOST;
2353     }
2354   }
2355   PetscFunctionReturn(PETSC_SUCCESS);
2356 }
2357 
2358 /*@C
2359   MatDenseRestoreArrayAndMemType - returns access to the array that is obtained by `MatDenseGetArrayAndMemType()`
2360 
2361   Logically Collective
2362 
2363   Input Parameters:
2364 + A     - a dense matrix
2365 - array - pointer to the data
2366 
2367   Level: intermediate
2368 
2369 .seealso: [](ch_matrices), `Mat`, `MATDENSE`, `MatDenseGetArrayAndMemType()`, `MatDenseGetArray()`, `MatDenseGetArrayRead()`, `MatDenseRestoreArrayRead()`, `MatDenseGetArrayWrite()`, `MatDenseRestoreArrayWrite()`
2370 @*/
2371 PetscErrorCode MatDenseRestoreArrayAndMemType(Mat A, PetscScalar *array[])
2372 {
2373   PetscBool isMPI;
2374 
2375   PetscFunctionBegin;
2376   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
2377   PetscAssertPointer(array, 2);
2378   PetscCall(PetscObjectBaseTypeCompare((PetscObject)A, MATMPIDENSE, &isMPI));
2379   if (isMPI) {
2380     PetscCall(MatDenseRestoreArrayAndMemType(((Mat_MPIDense *)A->data)->A, array));
2381   } else {
2382     PetscErrorCode (*fptr)(Mat, PetscScalar **);
2383 
2384     PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatDenseRestoreArrayAndMemType_C", &fptr));
2385     if (fptr) {
2386       PetscCall((*fptr)(A, array));
2387     } else {
2388       PetscUseMethod(A, "MatDenseRestoreArray_C", (Mat, PetscScalar **), (A, array));
2389     }
2390     *array = NULL;
2391   }
2392   PetscCall(PetscObjectStateIncrease((PetscObject)A));
2393   PetscFunctionReturn(PETSC_SUCCESS);
2394 }
2395 
2396 /*@C
2397   MatDenseGetArrayReadAndMemType - gives read-only access to the array where the data for a `MATDENSE` matrix is stored
2398 
2399   Logically Collective
2400 
2401   Input Parameter:
2402 . A - a dense matrix
2403 
2404   Output Parameters:
2405 + array - pointer to the data
2406 - mtype - memory type of the returned pointer
2407 
2408   Level: intermediate
2409 
2410   Note:
2411   If the matrix is of a device type such as `MATDENSECUDA`, `MATDENSEHIP`, etc.,
2412   an array on device is always returned and is guaranteed to contain the matrix's latest data.
2413 
2414 .seealso: [](ch_matrices), `Mat`, `MATDENSE`, `MatDenseRestoreArrayReadAndMemType()`, `MatDenseGetArrayWriteAndMemType()`,
2415    `MatDenseGetArrayRead()`, `MatDenseRestoreArrayRead()`, `MatDenseGetArrayWrite()`, `MatDenseRestoreArrayWrite()`, `MatSeqAIJGetCSRAndMemType()`
2416 @*/
2417 PetscErrorCode MatDenseGetArrayReadAndMemType(Mat A, const PetscScalar *array[], PetscMemType *mtype)
2418 {
2419   PetscBool isMPI;
2420 
2421   PetscFunctionBegin;
2422   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
2423   PetscAssertPointer(array, 2);
2424   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 */
2425   PetscCall(PetscObjectBaseTypeCompare((PetscObject)A, MATMPIDENSE, &isMPI));
2426   if (isMPI) { /* Dispatch here so that the code can be reused for all subclasses of MATDENSE */
2427     PetscCall(MatDenseGetArrayReadAndMemType(((Mat_MPIDense *)A->data)->A, array, mtype));
2428   } else {
2429     PetscErrorCode (*fptr)(Mat, const PetscScalar **, PetscMemType *);
2430 
2431     PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatDenseGetArrayReadAndMemType_C", &fptr));
2432     if (fptr) {
2433       PetscCall((*fptr)(A, array, mtype));
2434     } else {
2435       PetscUseMethod(A, "MatDenseGetArrayRead_C", (Mat, PetscScalar **), (A, (PetscScalar **)array));
2436       if (mtype) *mtype = PETSC_MEMTYPE_HOST;
2437     }
2438   }
2439   PetscFunctionReturn(PETSC_SUCCESS);
2440 }
2441 
2442 /*@C
2443   MatDenseRestoreArrayReadAndMemType - returns access to the array that is obtained by `MatDenseGetArrayReadAndMemType()`
2444 
2445   Logically Collective
2446 
2447   Input Parameters:
2448 + A     - a dense matrix
2449 - array - pointer to the data
2450 
2451   Level: intermediate
2452 
2453 .seealso: [](ch_matrices), `Mat`, `MATDENSE`, `MatDenseGetArrayReadAndMemType()`, `MatDenseGetArray()`, `MatDenseGetArrayRead()`, `MatDenseRestoreArrayRead()`, `MatDenseGetArrayWrite()`, `MatDenseRestoreArrayWrite()`
2454 @*/
2455 PetscErrorCode MatDenseRestoreArrayReadAndMemType(Mat A, const PetscScalar *array[])
2456 {
2457   PetscBool isMPI;
2458 
2459   PetscFunctionBegin;
2460   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
2461   PetscAssertPointer(array, 2);
2462   PetscCall(PetscObjectBaseTypeCompare((PetscObject)A, MATMPIDENSE, &isMPI));
2463   if (isMPI) {
2464     PetscCall(MatDenseRestoreArrayReadAndMemType(((Mat_MPIDense *)A->data)->A, array));
2465   } else {
2466     PetscErrorCode (*fptr)(Mat, const PetscScalar **);
2467 
2468     PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatDenseRestoreArrayReadAndMemType_C", &fptr));
2469     if (fptr) {
2470       PetscCall((*fptr)(A, array));
2471     } else {
2472       PetscUseMethod(A, "MatDenseRestoreArrayRead_C", (Mat, PetscScalar **), (A, (PetscScalar **)array));
2473     }
2474     *array = NULL;
2475   }
2476   PetscFunctionReturn(PETSC_SUCCESS);
2477 }
2478 
2479 /*@C
2480   MatDenseGetArrayWriteAndMemType - gives write-only access to the array where the data for a `MATDENSE` matrix is stored
2481 
2482   Logically Collective
2483 
2484   Input Parameter:
2485 . A - a dense matrix
2486 
2487   Output Parameters:
2488 + array - pointer to the data
2489 - mtype - memory type of the returned pointer
2490 
2491   Level: intermediate
2492 
2493   Note:
2494   If the matrix is of a device type such as `MATDENSECUDA`, `MATDENSEHIP`, etc.,
2495   an array on device is always returned and is guaranteed to contain the matrix's latest data.
2496 
2497 .seealso: [](ch_matrices), `Mat`, `MATDENSE`, `MatDenseRestoreArrayWriteAndMemType()`, `MatDenseGetArrayReadAndMemType()`, `MatDenseGetArrayRead()`,
2498   `MatDenseRestoreArrayRead()`, `MatDenseGetArrayWrite()`, `MatDenseRestoreArrayWrite()`, `MatSeqAIJGetCSRAndMemType()`
2499 @*/
2500 PetscErrorCode MatDenseGetArrayWriteAndMemType(Mat A, PetscScalar *array[], PetscMemType *mtype)
2501 {
2502   PetscBool isMPI;
2503 
2504   PetscFunctionBegin;
2505   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
2506   PetscAssertPointer(array, 2);
2507   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 */
2508   PetscCall(PetscObjectBaseTypeCompare((PetscObject)A, MATMPIDENSE, &isMPI));
2509   if (isMPI) {
2510     PetscCall(MatDenseGetArrayWriteAndMemType(((Mat_MPIDense *)A->data)->A, array, mtype));
2511   } else {
2512     PetscErrorCode (*fptr)(Mat, PetscScalar **, PetscMemType *);
2513 
2514     PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatDenseGetArrayWriteAndMemType_C", &fptr));
2515     if (fptr) {
2516       PetscCall((*fptr)(A, array, mtype));
2517     } else {
2518       PetscUseMethod(A, "MatDenseGetArrayWrite_C", (Mat, PetscScalar **), (A, array));
2519       if (mtype) *mtype = PETSC_MEMTYPE_HOST;
2520     }
2521   }
2522   PetscFunctionReturn(PETSC_SUCCESS);
2523 }
2524 
2525 /*@C
2526   MatDenseRestoreArrayWriteAndMemType - returns access to the array that is obtained by `MatDenseGetArrayReadAndMemType()`
2527 
2528   Logically Collective
2529 
2530   Input Parameters:
2531 + A     - a dense matrix
2532 - array - pointer to the data
2533 
2534   Level: intermediate
2535 
2536 .seealso: [](ch_matrices), `Mat`, `MATDENSE`, `MatDenseGetArrayWriteAndMemType()`, `MatDenseGetArray()`, `MatDenseGetArrayRead()`, `MatDenseRestoreArrayRead()`, `MatDenseGetArrayWrite()`, `MatDenseRestoreArrayWrite()`
2537 @*/
2538 PetscErrorCode MatDenseRestoreArrayWriteAndMemType(Mat A, PetscScalar *array[])
2539 {
2540   PetscBool isMPI;
2541 
2542   PetscFunctionBegin;
2543   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
2544   PetscAssertPointer(array, 2);
2545   PetscCall(PetscObjectBaseTypeCompare((PetscObject)A, MATMPIDENSE, &isMPI));
2546   if (isMPI) {
2547     PetscCall(MatDenseRestoreArrayWriteAndMemType(((Mat_MPIDense *)A->data)->A, array));
2548   } else {
2549     PetscErrorCode (*fptr)(Mat, PetscScalar **);
2550 
2551     PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatDenseRestoreArrayWriteAndMemType_C", &fptr));
2552     if (fptr) {
2553       PetscCall((*fptr)(A, array));
2554     } else {
2555       PetscUseMethod(A, "MatDenseRestoreArrayWrite_C", (Mat, PetscScalar **), (A, array));
2556     }
2557     *array = NULL;
2558   }
2559   PetscCall(PetscObjectStateIncrease((PetscObject)A));
2560   PetscFunctionReturn(PETSC_SUCCESS);
2561 }
2562 
2563 static PetscErrorCode MatCreateSubMatrix_SeqDense(Mat A, IS isrow, IS iscol, MatReuse scall, Mat *B)
2564 {
2565   Mat_SeqDense   *mat = (Mat_SeqDense *)A->data;
2566   PetscInt        i, j, nrows, ncols, ldb;
2567   const PetscInt *irow, *icol;
2568   PetscScalar    *av, *bv, *v = mat->v;
2569   Mat             newmat;
2570 
2571   PetscFunctionBegin;
2572   PetscCall(ISGetIndices(isrow, &irow));
2573   PetscCall(ISGetIndices(iscol, &icol));
2574   PetscCall(ISGetLocalSize(isrow, &nrows));
2575   PetscCall(ISGetLocalSize(iscol, &ncols));
2576 
2577   /* Check submatrixcall */
2578   if (scall == MAT_REUSE_MATRIX) {
2579     PetscInt n_cols, n_rows;
2580     PetscCall(MatGetSize(*B, &n_rows, &n_cols));
2581     if (n_rows != nrows || n_cols != ncols) {
2582       /* resize the result matrix to match number of requested rows/columns */
2583       PetscCall(MatSetSizes(*B, nrows, ncols, nrows, ncols));
2584     }
2585     newmat = *B;
2586   } else {
2587     /* Create and fill new matrix */
2588     PetscCall(MatCreate(PetscObjectComm((PetscObject)A), &newmat));
2589     PetscCall(MatSetSizes(newmat, nrows, ncols, nrows, ncols));
2590     PetscCall(MatSetType(newmat, ((PetscObject)A)->type_name));
2591     PetscCall(MatSeqDenseSetPreallocation(newmat, NULL));
2592   }
2593 
2594   /* Now extract the data pointers and do the copy,column at a time */
2595   PetscCall(MatDenseGetArray(newmat, &bv));
2596   PetscCall(MatDenseGetLDA(newmat, &ldb));
2597   for (i = 0; i < ncols; i++) {
2598     av = v + mat->lda * icol[i];
2599     for (j = 0; j < nrows; j++) bv[j] = av[irow[j]];
2600     bv += ldb;
2601   }
2602   PetscCall(MatDenseRestoreArray(newmat, &bv));
2603 
2604   /* Assemble the matrices so that the correct flags are set */
2605   PetscCall(MatAssemblyBegin(newmat, MAT_FINAL_ASSEMBLY));
2606   PetscCall(MatAssemblyEnd(newmat, MAT_FINAL_ASSEMBLY));
2607 
2608   /* Free work space */
2609   PetscCall(ISRestoreIndices(isrow, &irow));
2610   PetscCall(ISRestoreIndices(iscol, &icol));
2611   *B = newmat;
2612   PetscFunctionReturn(PETSC_SUCCESS);
2613 }
2614 
2615 static PetscErrorCode MatCreateSubMatrices_SeqDense(Mat A, PetscInt n, const IS irow[], const IS icol[], MatReuse scall, Mat *B[])
2616 {
2617   PetscInt i;
2618 
2619   PetscFunctionBegin;
2620   if (scall == MAT_INITIAL_MATRIX) PetscCall(PetscCalloc1(n, B));
2621 
2622   for (i = 0; i < n; i++) PetscCall(MatCreateSubMatrix_SeqDense(A, irow[i], icol[i], scall, &(*B)[i]));
2623   PetscFunctionReturn(PETSC_SUCCESS);
2624 }
2625 
2626 PetscErrorCode MatCopy_SeqDense(Mat A, Mat B, MatStructure str)
2627 {
2628   Mat_SeqDense      *a = (Mat_SeqDense *)A->data, *b = (Mat_SeqDense *)B->data;
2629   const PetscScalar *va;
2630   PetscScalar       *vb;
2631   PetscInt           lda1 = a->lda, lda2 = b->lda, m = A->rmap->n, n = A->cmap->n, j;
2632 
2633   PetscFunctionBegin;
2634   /* If the two matrices don't have the same copy implementation, they aren't compatible for fast copy. */
2635   if (A->ops->copy != B->ops->copy) {
2636     PetscCall(MatCopy_Basic(A, B, str));
2637     PetscFunctionReturn(PETSC_SUCCESS);
2638   }
2639   PetscCheck(m == B->rmap->n && n == B->cmap->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "size(B) != size(A)");
2640   PetscCall(MatDenseGetArrayRead(A, &va));
2641   PetscCall(MatDenseGetArray(B, &vb));
2642   if (lda1 > m || lda2 > m) {
2643     for (j = 0; j < n; j++) PetscCall(PetscArraycpy(vb + j * lda2, va + j * lda1, m));
2644   } else {
2645     PetscCall(PetscArraycpy(vb, va, A->rmap->n * A->cmap->n));
2646   }
2647   PetscCall(MatDenseRestoreArray(B, &vb));
2648   PetscCall(MatDenseRestoreArrayRead(A, &va));
2649   PetscCall(MatAssemblyBegin(B, MAT_FINAL_ASSEMBLY));
2650   PetscCall(MatAssemblyEnd(B, MAT_FINAL_ASSEMBLY));
2651   PetscFunctionReturn(PETSC_SUCCESS);
2652 }
2653 
2654 PetscErrorCode MatSetUp_SeqDense(Mat A)
2655 {
2656   PetscFunctionBegin;
2657   PetscCall(PetscLayoutSetUp(A->rmap));
2658   PetscCall(PetscLayoutSetUp(A->cmap));
2659   if (!A->preallocated) PetscCall(MatSeqDenseSetPreallocation(A, NULL));
2660   PetscFunctionReturn(PETSC_SUCCESS);
2661 }
2662 
2663 static PetscErrorCode MatConjugate_SeqDense(Mat A)
2664 {
2665   Mat_SeqDense *mat = (Mat_SeqDense *)A->data;
2666   PetscInt      i, j;
2667   PetscInt      min = PetscMin(A->rmap->n, A->cmap->n);
2668   PetscScalar  *aa;
2669 
2670   PetscFunctionBegin;
2671   PetscCall(MatDenseGetArray(A, &aa));
2672   for (j = 0; j < A->cmap->n; j++) {
2673     for (i = 0; i < A->rmap->n; i++) aa[i + j * mat->lda] = PetscConj(aa[i + j * mat->lda]);
2674   }
2675   PetscCall(MatDenseRestoreArray(A, &aa));
2676   if (mat->tau)
2677     for (i = 0; i < min; i++) mat->tau[i] = PetscConj(mat->tau[i]);
2678   PetscFunctionReturn(PETSC_SUCCESS);
2679 }
2680 
2681 static PetscErrorCode MatRealPart_SeqDense(Mat A)
2682 {
2683   Mat_SeqDense *mat = (Mat_SeqDense *)A->data;
2684   PetscInt      i, j;
2685   PetscScalar  *aa;
2686 
2687   PetscFunctionBegin;
2688   PetscCall(MatDenseGetArray(A, &aa));
2689   for (j = 0; j < A->cmap->n; j++) {
2690     for (i = 0; i < A->rmap->n; i++) aa[i + j * mat->lda] = PetscRealPart(aa[i + j * mat->lda]);
2691   }
2692   PetscCall(MatDenseRestoreArray(A, &aa));
2693   PetscFunctionReturn(PETSC_SUCCESS);
2694 }
2695 
2696 static PetscErrorCode MatImaginaryPart_SeqDense(Mat A)
2697 {
2698   Mat_SeqDense *mat = (Mat_SeqDense *)A->data;
2699   PetscInt      i, j;
2700   PetscScalar  *aa;
2701 
2702   PetscFunctionBegin;
2703   PetscCall(MatDenseGetArray(A, &aa));
2704   for (j = 0; j < A->cmap->n; j++) {
2705     for (i = 0; i < A->rmap->n; i++) aa[i + j * mat->lda] = PetscImaginaryPart(aa[i + j * mat->lda]);
2706   }
2707   PetscCall(MatDenseRestoreArray(A, &aa));
2708   PetscFunctionReturn(PETSC_SUCCESS);
2709 }
2710 
2711 PetscErrorCode MatMatMultSymbolic_SeqDense_SeqDense(Mat A, Mat B, PetscReal fill, Mat C)
2712 {
2713   PetscInt  m = A->rmap->n, n = B->cmap->n;
2714   PetscBool cisdense = PETSC_FALSE;
2715 
2716   PetscFunctionBegin;
2717   PetscCall(MatSetSizes(C, m, n, m, n));
2718 #if defined(PETSC_HAVE_CUDA)
2719   PetscCall(PetscObjectTypeCompareAny((PetscObject)C, &cisdense, MATSEQDENSE, MATSEQDENSECUDA, ""));
2720 #endif
2721 #if defined(PETSC_HAVE_HIP)
2722   PetscCall(PetscObjectTypeCompareAny((PetscObject)C, &cisdense, MATSEQDENSE, MATSEQDENSEHIP, ""));
2723 #endif
2724   if (!cisdense) {
2725     PetscBool flg;
2726 
2727     PetscCall(PetscObjectTypeCompare((PetscObject)B, ((PetscObject)A)->type_name, &flg));
2728     PetscCall(MatSetType(C, flg ? ((PetscObject)A)->type_name : MATDENSE));
2729   }
2730   PetscCall(MatSetUp(C));
2731   PetscFunctionReturn(PETSC_SUCCESS);
2732 }
2733 
2734 PetscErrorCode MatMatMultNumeric_SeqDense_SeqDense(Mat A, Mat B, Mat C)
2735 {
2736   Mat_SeqDense      *a = (Mat_SeqDense *)A->data, *b = (Mat_SeqDense *)B->data, *c = (Mat_SeqDense *)C->data;
2737   PetscBLASInt       m, n, k;
2738   const PetscScalar *av, *bv;
2739   PetscScalar       *cv;
2740   PetscScalar        _DOne = 1.0, _DZero = 0.0;
2741 
2742   PetscFunctionBegin;
2743   PetscCall(PetscBLASIntCast(C->rmap->n, &m));
2744   PetscCall(PetscBLASIntCast(C->cmap->n, &n));
2745   PetscCall(PetscBLASIntCast(A->cmap->n, &k));
2746   if (!m || !n || !k) PetscFunctionReturn(PETSC_SUCCESS);
2747   PetscCall(MatDenseGetArrayRead(A, &av));
2748   PetscCall(MatDenseGetArrayRead(B, &bv));
2749   PetscCall(MatDenseGetArrayWrite(C, &cv));
2750   PetscCallBLAS("BLASgemm", BLASgemm_("N", "N", &m, &n, &k, &_DOne, av, &a->lda, bv, &b->lda, &_DZero, cv, &c->lda));
2751   PetscCall(PetscLogFlops(1.0 * m * n * k + 1.0 * m * n * (k - 1)));
2752   PetscCall(MatDenseRestoreArrayRead(A, &av));
2753   PetscCall(MatDenseRestoreArrayRead(B, &bv));
2754   PetscCall(MatDenseRestoreArrayWrite(C, &cv));
2755   PetscFunctionReturn(PETSC_SUCCESS);
2756 }
2757 
2758 PetscErrorCode MatMatTransposeMultSymbolic_SeqDense_SeqDense(Mat A, Mat B, PetscReal fill, Mat C)
2759 {
2760   PetscInt  m = A->rmap->n, n = B->rmap->n;
2761   PetscBool cisdense = PETSC_FALSE;
2762 
2763   PetscFunctionBegin;
2764   PetscCall(MatSetSizes(C, m, n, m, n));
2765 #if defined(PETSC_HAVE_CUDA)
2766   PetscCall(PetscObjectTypeCompareAny((PetscObject)C, &cisdense, MATSEQDENSE, MATSEQDENSECUDA, ""));
2767 #endif
2768 #if defined(PETSC_HAVE_HIP)
2769   PetscCall(PetscObjectTypeCompareAny((PetscObject)C, &cisdense, MATSEQDENSE, MATSEQDENSEHIP, ""));
2770 #endif
2771   if (!cisdense) {
2772     PetscBool flg;
2773 
2774     PetscCall(PetscObjectTypeCompare((PetscObject)B, ((PetscObject)A)->type_name, &flg));
2775     PetscCall(MatSetType(C, flg ? ((PetscObject)A)->type_name : MATDENSE));
2776   }
2777   PetscCall(MatSetUp(C));
2778   PetscFunctionReturn(PETSC_SUCCESS);
2779 }
2780 
2781 PetscErrorCode MatMatTransposeMultNumeric_SeqDense_SeqDense(Mat A, Mat B, Mat C)
2782 {
2783   Mat_SeqDense      *a = (Mat_SeqDense *)A->data;
2784   Mat_SeqDense      *b = (Mat_SeqDense *)B->data;
2785   Mat_SeqDense      *c = (Mat_SeqDense *)C->data;
2786   const PetscScalar *av, *bv;
2787   PetscScalar       *cv;
2788   PetscBLASInt       m, n, k;
2789   PetscScalar        _DOne = 1.0, _DZero = 0.0;
2790 
2791   PetscFunctionBegin;
2792   PetscCall(PetscBLASIntCast(C->rmap->n, &m));
2793   PetscCall(PetscBLASIntCast(C->cmap->n, &n));
2794   PetscCall(PetscBLASIntCast(A->cmap->n, &k));
2795   if (!m || !n || !k) PetscFunctionReturn(PETSC_SUCCESS);
2796   PetscCall(MatDenseGetArrayRead(A, &av));
2797   PetscCall(MatDenseGetArrayRead(B, &bv));
2798   PetscCall(MatDenseGetArrayWrite(C, &cv));
2799   PetscCallBLAS("BLASgemm", BLASgemm_("N", "T", &m, &n, &k, &_DOne, av, &a->lda, bv, &b->lda, &_DZero, cv, &c->lda));
2800   PetscCall(MatDenseRestoreArrayRead(A, &av));
2801   PetscCall(MatDenseRestoreArrayRead(B, &bv));
2802   PetscCall(MatDenseRestoreArrayWrite(C, &cv));
2803   PetscCall(PetscLogFlops(1.0 * m * n * k + 1.0 * m * n * (k - 1)));
2804   PetscFunctionReturn(PETSC_SUCCESS);
2805 }
2806 
2807 PetscErrorCode MatTransposeMatMultSymbolic_SeqDense_SeqDense(Mat A, Mat B, PetscReal fill, Mat C)
2808 {
2809   PetscInt  m = A->cmap->n, n = B->cmap->n;
2810   PetscBool cisdense = PETSC_FALSE;
2811 
2812   PetscFunctionBegin;
2813   PetscCall(MatSetSizes(C, m, n, m, n));
2814 #if defined(PETSC_HAVE_CUDA)
2815   PetscCall(PetscObjectTypeCompareAny((PetscObject)C, &cisdense, MATSEQDENSE, MATSEQDENSECUDA, ""));
2816 #endif
2817 #if defined(PETSC_HAVE_HIP)
2818   PetscCall(PetscObjectTypeCompareAny((PetscObject)C, &cisdense, MATSEQDENSE, MATSEQDENSEHIP, ""));
2819 #endif
2820   if (!cisdense) {
2821     PetscBool flg;
2822 
2823     PetscCall(PetscObjectTypeCompare((PetscObject)B, ((PetscObject)A)->type_name, &flg));
2824     PetscCall(MatSetType(C, flg ? ((PetscObject)A)->type_name : MATDENSE));
2825   }
2826   PetscCall(MatSetUp(C));
2827   PetscFunctionReturn(PETSC_SUCCESS);
2828 }
2829 
2830 PetscErrorCode MatTransposeMatMultNumeric_SeqDense_SeqDense(Mat A, Mat B, Mat C)
2831 {
2832   Mat_SeqDense      *a = (Mat_SeqDense *)A->data;
2833   Mat_SeqDense      *b = (Mat_SeqDense *)B->data;
2834   Mat_SeqDense      *c = (Mat_SeqDense *)C->data;
2835   const PetscScalar *av, *bv;
2836   PetscScalar       *cv;
2837   PetscBLASInt       m, n, k;
2838   PetscScalar        _DOne = 1.0, _DZero = 0.0;
2839 
2840   PetscFunctionBegin;
2841   PetscCall(PetscBLASIntCast(C->rmap->n, &m));
2842   PetscCall(PetscBLASIntCast(C->cmap->n, &n));
2843   PetscCall(PetscBLASIntCast(A->rmap->n, &k));
2844   if (!m || !n || !k) PetscFunctionReturn(PETSC_SUCCESS);
2845   PetscCall(MatDenseGetArrayRead(A, &av));
2846   PetscCall(MatDenseGetArrayRead(B, &bv));
2847   PetscCall(MatDenseGetArrayWrite(C, &cv));
2848   PetscCallBLAS("BLASgemm", BLASgemm_("T", "N", &m, &n, &k, &_DOne, av, &a->lda, bv, &b->lda, &_DZero, cv, &c->lda));
2849   PetscCall(MatDenseRestoreArrayRead(A, &av));
2850   PetscCall(MatDenseRestoreArrayRead(B, &bv));
2851   PetscCall(MatDenseRestoreArrayWrite(C, &cv));
2852   PetscCall(PetscLogFlops(1.0 * m * n * k + 1.0 * m * n * (k - 1)));
2853   PetscFunctionReturn(PETSC_SUCCESS);
2854 }
2855 
2856 static PetscErrorCode MatProductSetFromOptions_SeqDense_AB(Mat C)
2857 {
2858   PetscFunctionBegin;
2859   C->ops->matmultsymbolic = MatMatMultSymbolic_SeqDense_SeqDense;
2860   C->ops->productsymbolic = MatProductSymbolic_AB;
2861   PetscFunctionReturn(PETSC_SUCCESS);
2862 }
2863 
2864 static PetscErrorCode MatProductSetFromOptions_SeqDense_AtB(Mat C)
2865 {
2866   PetscFunctionBegin;
2867   C->ops->transposematmultsymbolic = MatTransposeMatMultSymbolic_SeqDense_SeqDense;
2868   C->ops->productsymbolic          = MatProductSymbolic_AtB;
2869   PetscFunctionReturn(PETSC_SUCCESS);
2870 }
2871 
2872 static PetscErrorCode MatProductSetFromOptions_SeqDense_ABt(Mat C)
2873 {
2874   PetscFunctionBegin;
2875   C->ops->mattransposemultsymbolic = MatMatTransposeMultSymbolic_SeqDense_SeqDense;
2876   C->ops->productsymbolic          = MatProductSymbolic_ABt;
2877   PetscFunctionReturn(PETSC_SUCCESS);
2878 }
2879 
2880 PETSC_INTERN PetscErrorCode MatProductSetFromOptions_SeqDense(Mat C)
2881 {
2882   Mat_Product *product = C->product;
2883 
2884   PetscFunctionBegin;
2885   switch (product->type) {
2886   case MATPRODUCT_AB:
2887     PetscCall(MatProductSetFromOptions_SeqDense_AB(C));
2888     break;
2889   case MATPRODUCT_AtB:
2890     PetscCall(MatProductSetFromOptions_SeqDense_AtB(C));
2891     break;
2892   case MATPRODUCT_ABt:
2893     PetscCall(MatProductSetFromOptions_SeqDense_ABt(C));
2894     break;
2895   default:
2896     break;
2897   }
2898   PetscFunctionReturn(PETSC_SUCCESS);
2899 }
2900 
2901 static PetscErrorCode MatGetRowMax_SeqDense(Mat A, Vec v, PetscInt idx[])
2902 {
2903   Mat_SeqDense      *a = (Mat_SeqDense *)A->data;
2904   PetscInt           i, j, m = A->rmap->n, n = A->cmap->n, p;
2905   PetscScalar       *x;
2906   const PetscScalar *aa;
2907 
2908   PetscFunctionBegin;
2909   PetscCheck(!A->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2910   PetscCall(VecGetArray(v, &x));
2911   PetscCall(VecGetLocalSize(v, &p));
2912   PetscCall(MatDenseGetArrayRead(A, &aa));
2913   PetscCheck(p == A->rmap->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Nonconforming matrix and vector");
2914   for (i = 0; i < m; i++) {
2915     x[i] = aa[i];
2916     if (idx) idx[i] = 0;
2917     for (j = 1; j < n; j++) {
2918       if (PetscRealPart(x[i]) < PetscRealPart(aa[i + a->lda * j])) {
2919         x[i] = aa[i + a->lda * j];
2920         if (idx) idx[i] = j;
2921       }
2922     }
2923   }
2924   PetscCall(MatDenseRestoreArrayRead(A, &aa));
2925   PetscCall(VecRestoreArray(v, &x));
2926   PetscFunctionReturn(PETSC_SUCCESS);
2927 }
2928 
2929 static PetscErrorCode MatGetRowMaxAbs_SeqDense(Mat A, Vec v, PetscInt idx[])
2930 {
2931   Mat_SeqDense      *a = (Mat_SeqDense *)A->data;
2932   PetscInt           i, j, m = A->rmap->n, n = A->cmap->n, p;
2933   PetscScalar       *x;
2934   PetscReal          atmp;
2935   const PetscScalar *aa;
2936 
2937   PetscFunctionBegin;
2938   PetscCheck(!A->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2939   PetscCall(VecGetArray(v, &x));
2940   PetscCall(VecGetLocalSize(v, &p));
2941   PetscCall(MatDenseGetArrayRead(A, &aa));
2942   PetscCheck(p == A->rmap->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Nonconforming matrix and vector");
2943   for (i = 0; i < m; i++) {
2944     x[i] = PetscAbsScalar(aa[i]);
2945     for (j = 1; j < n; j++) {
2946       atmp = PetscAbsScalar(aa[i + a->lda * j]);
2947       if (PetscAbsScalar(x[i]) < atmp) {
2948         x[i] = atmp;
2949         if (idx) idx[i] = j;
2950       }
2951     }
2952   }
2953   PetscCall(MatDenseRestoreArrayRead(A, &aa));
2954   PetscCall(VecRestoreArray(v, &x));
2955   PetscFunctionReturn(PETSC_SUCCESS);
2956 }
2957 
2958 static PetscErrorCode MatGetRowMin_SeqDense(Mat A, Vec v, PetscInt idx[])
2959 {
2960   Mat_SeqDense      *a = (Mat_SeqDense *)A->data;
2961   PetscInt           i, j, m = A->rmap->n, n = A->cmap->n, p;
2962   PetscScalar       *x;
2963   const PetscScalar *aa;
2964 
2965   PetscFunctionBegin;
2966   PetscCheck(!A->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2967   PetscCall(MatDenseGetArrayRead(A, &aa));
2968   PetscCall(VecGetArray(v, &x));
2969   PetscCall(VecGetLocalSize(v, &p));
2970   PetscCheck(p == A->rmap->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Nonconforming matrix and vector");
2971   for (i = 0; i < m; i++) {
2972     x[i] = aa[i];
2973     if (idx) idx[i] = 0;
2974     for (j = 1; j < n; j++) {
2975       if (PetscRealPart(x[i]) > PetscRealPart(aa[i + a->lda * j])) {
2976         x[i] = aa[i + a->lda * j];
2977         if (idx) idx[i] = j;
2978       }
2979     }
2980   }
2981   PetscCall(VecRestoreArray(v, &x));
2982   PetscCall(MatDenseRestoreArrayRead(A, &aa));
2983   PetscFunctionReturn(PETSC_SUCCESS);
2984 }
2985 
2986 PetscErrorCode MatGetColumnVector_SeqDense(Mat A, Vec v, PetscInt col)
2987 {
2988   Mat_SeqDense      *a = (Mat_SeqDense *)A->data;
2989   PetscScalar       *x;
2990   const PetscScalar *aa;
2991 
2992   PetscFunctionBegin;
2993   PetscCheck(!A->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2994   PetscCall(MatDenseGetArrayRead(A, &aa));
2995   PetscCall(VecGetArray(v, &x));
2996   PetscCall(PetscArraycpy(x, aa + col * a->lda, A->rmap->n));
2997   PetscCall(VecRestoreArray(v, &x));
2998   PetscCall(MatDenseRestoreArrayRead(A, &aa));
2999   PetscFunctionReturn(PETSC_SUCCESS);
3000 }
3001 
3002 PETSC_INTERN PetscErrorCode MatGetColumnReductions_SeqDense(Mat A, PetscInt type, PetscReal *reductions)
3003 {
3004   PetscInt           i, j, m, n;
3005   const PetscScalar *a;
3006 
3007   PetscFunctionBegin;
3008   PetscCall(MatGetSize(A, &m, &n));
3009   PetscCall(PetscArrayzero(reductions, n));
3010   PetscCall(MatDenseGetArrayRead(A, &a));
3011   if (type == NORM_2) {
3012     for (i = 0; i < n; i++) {
3013       for (j = 0; j < m; j++) reductions[i] += PetscAbsScalar(a[j] * a[j]);
3014       a = PetscSafePointerPlusOffset(a, m);
3015     }
3016   } else if (type == NORM_1) {
3017     for (i = 0; i < n; i++) {
3018       for (j = 0; j < m; j++) reductions[i] += PetscAbsScalar(a[j]);
3019       a = PetscSafePointerPlusOffset(a, m);
3020     }
3021   } else if (type == NORM_INFINITY) {
3022     for (i = 0; i < n; i++) {
3023       for (j = 0; j < m; j++) reductions[i] = PetscMax(PetscAbsScalar(a[j]), reductions[i]);
3024       a = PetscSafePointerPlusOffset(a, m);
3025     }
3026   } else if (type == REDUCTION_SUM_REALPART || type == REDUCTION_MEAN_REALPART) {
3027     for (i = 0; i < n; i++) {
3028       for (j = 0; j < m; j++) reductions[i] += PetscRealPart(a[j]);
3029       a = PetscSafePointerPlusOffset(a, m);
3030     }
3031   } else if (type == REDUCTION_SUM_IMAGINARYPART || type == REDUCTION_MEAN_IMAGINARYPART) {
3032     for (i = 0; i < n; i++) {
3033       for (j = 0; j < m; j++) reductions[i] += PetscImaginaryPart(a[j]);
3034       a = PetscSafePointerPlusOffset(a, m);
3035     }
3036   } else SETERRQ(PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONG, "Unknown reduction type");
3037   PetscCall(MatDenseRestoreArrayRead(A, &a));
3038   if (type == NORM_2) {
3039     for (i = 0; i < n; i++) reductions[i] = PetscSqrtReal(reductions[i]);
3040   } else if (type == REDUCTION_MEAN_REALPART || type == REDUCTION_MEAN_IMAGINARYPART) {
3041     for (i = 0; i < n; i++) reductions[i] /= m;
3042   }
3043   PetscFunctionReturn(PETSC_SUCCESS);
3044 }
3045 
3046 PetscErrorCode MatSetRandom_SeqDense(Mat x, PetscRandom rctx)
3047 {
3048   PetscScalar *a;
3049   PetscInt     lda, m, n, i, j;
3050 
3051   PetscFunctionBegin;
3052   PetscCall(MatGetSize(x, &m, &n));
3053   PetscCall(MatDenseGetLDA(x, &lda));
3054   PetscCall(MatDenseGetArrayWrite(x, &a));
3055   for (j = 0; j < n; j++) {
3056     for (i = 0; i < m; i++) PetscCall(PetscRandomGetValue(rctx, a + j * lda + i));
3057   }
3058   PetscCall(MatDenseRestoreArrayWrite(x, &a));
3059   PetscFunctionReturn(PETSC_SUCCESS);
3060 }
3061 
3062 static PetscErrorCode MatMissingDiagonal_SeqDense(Mat A, PetscBool *missing, PetscInt *d)
3063 {
3064   PetscFunctionBegin;
3065   *missing = PETSC_FALSE;
3066   PetscFunctionReturn(PETSC_SUCCESS);
3067 }
3068 
3069 /* vals is not const */
3070 static PetscErrorCode MatDenseGetColumn_SeqDense(Mat A, PetscInt col, PetscScalar **vals)
3071 {
3072   Mat_SeqDense *a = (Mat_SeqDense *)A->data;
3073   PetscScalar  *v;
3074 
3075   PetscFunctionBegin;
3076   PetscCheck(!A->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3077   PetscCall(MatDenseGetArray(A, &v));
3078   *vals = v + col * a->lda;
3079   PetscCall(MatDenseRestoreArray(A, &v));
3080   PetscFunctionReturn(PETSC_SUCCESS);
3081 }
3082 
3083 static PetscErrorCode MatDenseRestoreColumn_SeqDense(Mat A, PetscScalar **vals)
3084 {
3085   PetscFunctionBegin;
3086   if (vals) *vals = NULL; /* user cannot accidentally use the array later */
3087   PetscFunctionReturn(PETSC_SUCCESS);
3088 }
3089 
3090 static struct _MatOps MatOps_Values = {MatSetValues_SeqDense,
3091                                        MatGetRow_SeqDense,
3092                                        MatRestoreRow_SeqDense,
3093                                        MatMult_SeqDense,
3094                                        /*  4*/ MatMultAdd_SeqDense,
3095                                        MatMultTranspose_SeqDense,
3096                                        MatMultTransposeAdd_SeqDense,
3097                                        NULL,
3098                                        NULL,
3099                                        NULL,
3100                                        /* 10*/ NULL,
3101                                        MatLUFactor_SeqDense,
3102                                        MatCholeskyFactor_SeqDense,
3103                                        MatSOR_SeqDense,
3104                                        MatTranspose_SeqDense,
3105                                        /* 15*/ MatGetInfo_SeqDense,
3106                                        MatEqual_SeqDense,
3107                                        MatGetDiagonal_SeqDense,
3108                                        MatDiagonalScale_SeqDense,
3109                                        MatNorm_SeqDense,
3110                                        /* 20*/ NULL,
3111                                        NULL,
3112                                        MatSetOption_SeqDense,
3113                                        MatZeroEntries_SeqDense,
3114                                        /* 24*/ MatZeroRows_SeqDense,
3115                                        NULL,
3116                                        NULL,
3117                                        NULL,
3118                                        NULL,
3119                                        /* 29*/ MatSetUp_SeqDense,
3120                                        NULL,
3121                                        NULL,
3122                                        NULL,
3123                                        NULL,
3124                                        /* 34*/ MatDuplicate_SeqDense,
3125                                        NULL,
3126                                        NULL,
3127                                        NULL,
3128                                        NULL,
3129                                        /* 39*/ MatAXPY_SeqDense,
3130                                        MatCreateSubMatrices_SeqDense,
3131                                        NULL,
3132                                        MatGetValues_SeqDense,
3133                                        MatCopy_SeqDense,
3134                                        /* 44*/ MatGetRowMax_SeqDense,
3135                                        MatScale_SeqDense,
3136                                        MatShift_SeqDense,
3137                                        NULL,
3138                                        MatZeroRowsColumns_SeqDense,
3139                                        /* 49*/ MatSetRandom_SeqDense,
3140                                        NULL,
3141                                        NULL,
3142                                        NULL,
3143                                        NULL,
3144                                        /* 54*/ NULL,
3145                                        NULL,
3146                                        NULL,
3147                                        NULL,
3148                                        NULL,
3149                                        /* 59*/ MatCreateSubMatrix_SeqDense,
3150                                        MatDestroy_SeqDense,
3151                                        MatView_SeqDense,
3152                                        NULL,
3153                                        NULL,
3154                                        /* 64*/ NULL,
3155                                        NULL,
3156                                        NULL,
3157                                        NULL,
3158                                        NULL,
3159                                        /* 69*/ MatGetRowMaxAbs_SeqDense,
3160                                        NULL,
3161                                        NULL,
3162                                        NULL,
3163                                        NULL,
3164                                        /* 74*/ NULL,
3165                                        NULL,
3166                                        NULL,
3167                                        NULL,
3168                                        NULL,
3169                                        /* 79*/ NULL,
3170                                        NULL,
3171                                        NULL,
3172                                        NULL,
3173                                        /* 83*/ MatLoad_SeqDense,
3174                                        MatIsSymmetric_SeqDense,
3175                                        MatIsHermitian_SeqDense,
3176                                        NULL,
3177                                        NULL,
3178                                        NULL,
3179                                        /* 89*/ NULL,
3180                                        NULL,
3181                                        MatMatMultNumeric_SeqDense_SeqDense,
3182                                        NULL,
3183                                        NULL,
3184                                        /* 94*/ NULL,
3185                                        NULL,
3186                                        NULL,
3187                                        MatMatTransposeMultNumeric_SeqDense_SeqDense,
3188                                        NULL,
3189                                        /* 99*/ MatProductSetFromOptions_SeqDense,
3190                                        NULL,
3191                                        NULL,
3192                                        MatConjugate_SeqDense,
3193                                        NULL,
3194                                        /*104*/ NULL,
3195                                        MatRealPart_SeqDense,
3196                                        MatImaginaryPart_SeqDense,
3197                                        NULL,
3198                                        NULL,
3199                                        /*109*/ NULL,
3200                                        NULL,
3201                                        MatGetRowMin_SeqDense,
3202                                        MatGetColumnVector_SeqDense,
3203                                        MatMissingDiagonal_SeqDense,
3204                                        /*114*/ NULL,
3205                                        NULL,
3206                                        NULL,
3207                                        NULL,
3208                                        NULL,
3209                                        /*119*/ NULL,
3210                                        NULL,
3211                                        MatMultHermitianTranspose_SeqDense,
3212                                        MatMultHermitianTransposeAdd_SeqDense,
3213                                        NULL,
3214                                        /*124*/ NULL,
3215                                        MatGetColumnReductions_SeqDense,
3216                                        NULL,
3217                                        NULL,
3218                                        NULL,
3219                                        /*129*/ NULL,
3220                                        NULL,
3221                                        NULL,
3222                                        MatTransposeMatMultNumeric_SeqDense_SeqDense,
3223                                        NULL,
3224                                        /*134*/ NULL,
3225                                        NULL,
3226                                        NULL,
3227                                        NULL,
3228                                        NULL,
3229                                        /*139*/ NULL,
3230                                        NULL,
3231                                        NULL,
3232                                        NULL,
3233                                        NULL,
3234                                        MatCreateMPIMatConcatenateSeqMat_SeqDense,
3235                                        /*145*/ NULL,
3236                                        NULL,
3237                                        NULL,
3238                                        NULL,
3239                                        NULL,
3240                                        /*150*/ NULL,
3241                                        NULL,
3242                                        NULL,
3243                                        NULL,
3244                                        NULL,
3245                                        /*155*/ NULL,
3246                                        NULL};
3247 
3248 /*@
3249   MatCreateSeqDense - Creates a `MATSEQDENSE` that
3250   is stored in column major order (the usual Fortran format).
3251 
3252   Collective
3253 
3254   Input Parameters:
3255 + comm - MPI communicator, set to `PETSC_COMM_SELF`
3256 . m    - number of rows
3257 . n    - number of columns
3258 - data - optional location of matrix data in column major order.  Use `NULL` for PETSc
3259          to control all matrix memory allocation.
3260 
3261   Output Parameter:
3262 . A - the matrix
3263 
3264   Level: intermediate
3265 
3266   Note:
3267   The data input variable is intended primarily for Fortran programmers
3268   who wish to allocate their own matrix memory space.  Most users should
3269   set `data` = `NULL`.
3270 
3271   Developer Note:
3272   Many of the matrix operations for this variant use the BLAS and LAPACK routines.
3273 
3274 .seealso: [](ch_matrices), `Mat`, `MATSEQDENSE`, `MatCreate()`, `MatCreateDense()`, `MatSetValues()`
3275 @*/
3276 PetscErrorCode MatCreateSeqDense(MPI_Comm comm, PetscInt m, PetscInt n, PetscScalar data[], Mat *A)
3277 {
3278   PetscFunctionBegin;
3279   PetscCall(MatCreate(comm, A));
3280   PetscCall(MatSetSizes(*A, m, n, m, n));
3281   PetscCall(MatSetType(*A, MATSEQDENSE));
3282   PetscCall(MatSeqDenseSetPreallocation(*A, data));
3283   PetscFunctionReturn(PETSC_SUCCESS);
3284 }
3285 
3286 /*@
3287   MatSeqDenseSetPreallocation - Sets the array used for storing the matrix elements of a `MATSEQDENSE` matrix
3288 
3289   Collective
3290 
3291   Input Parameters:
3292 + B    - the matrix
3293 - data - the array (or `NULL`)
3294 
3295   Level: intermediate
3296 
3297   Note:
3298   The data input variable is intended primarily for Fortran programmers
3299   who wish to allocate their own matrix memory space.  Most users should
3300   need not call this routine.
3301 
3302 .seealso: [](ch_matrices), `Mat`, `MATSEQDENSE`, `MatCreate()`, `MatCreateDense()`, `MatSetValues()`, `MatDenseSetLDA()`
3303 @*/
3304 PetscErrorCode MatSeqDenseSetPreallocation(Mat B, PetscScalar data[])
3305 {
3306   PetscFunctionBegin;
3307   PetscValidHeaderSpecific(B, MAT_CLASSID, 1);
3308   PetscTryMethod(B, "MatSeqDenseSetPreallocation_C", (Mat, PetscScalar[]), (B, data));
3309   PetscFunctionReturn(PETSC_SUCCESS);
3310 }
3311 
3312 PetscErrorCode MatSeqDenseSetPreallocation_SeqDense(Mat B, PetscScalar *data)
3313 {
3314   Mat_SeqDense *b = (Mat_SeqDense *)B->data;
3315 
3316   PetscFunctionBegin;
3317   PetscCheck(!b->matinuse, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Need to call MatDenseRestoreSubMatrix() first");
3318   B->preallocated = PETSC_TRUE;
3319 
3320   PetscCall(PetscLayoutSetUp(B->rmap));
3321   PetscCall(PetscLayoutSetUp(B->cmap));
3322 
3323   if (b->lda <= 0) PetscCall(PetscBLASIntCast(B->rmap->n, &b->lda));
3324 
3325   if (!data) { /* petsc-allocated storage */
3326     if (!b->user_alloc) PetscCall(PetscFree(b->v));
3327     PetscCall(PetscCalloc1((size_t)b->lda * B->cmap->n, &b->v));
3328 
3329     b->user_alloc = PETSC_FALSE;
3330   } else { /* user-allocated storage */
3331     if (!b->user_alloc) PetscCall(PetscFree(b->v));
3332     b->v          = data;
3333     b->user_alloc = PETSC_TRUE;
3334   }
3335   B->assembled = PETSC_TRUE;
3336   PetscFunctionReturn(PETSC_SUCCESS);
3337 }
3338 
3339 #if defined(PETSC_HAVE_ELEMENTAL)
3340 PETSC_INTERN PetscErrorCode MatConvert_SeqDense_Elemental(Mat A, MatType newtype, MatReuse reuse, Mat *newmat)
3341 {
3342   Mat                mat_elemental;
3343   const PetscScalar *array;
3344   PetscScalar       *v_colwise;
3345   PetscInt           M = A->rmap->N, N = A->cmap->N, i, j, k, *rows, *cols;
3346 
3347   PetscFunctionBegin;
3348   PetscCall(PetscMalloc3(M * N, &v_colwise, M, &rows, N, &cols));
3349   PetscCall(MatDenseGetArrayRead(A, &array));
3350   /* convert column-wise array into row-wise v_colwise, see MatSetValues_Elemental() */
3351   k = 0;
3352   for (j = 0; j < N; j++) {
3353     cols[j] = j;
3354     for (i = 0; i < M; i++) v_colwise[j * M + i] = array[k++];
3355   }
3356   for (i = 0; i < M; i++) rows[i] = i;
3357   PetscCall(MatDenseRestoreArrayRead(A, &array));
3358 
3359   PetscCall(MatCreate(PetscObjectComm((PetscObject)A), &mat_elemental));
3360   PetscCall(MatSetSizes(mat_elemental, PETSC_DECIDE, PETSC_DECIDE, M, N));
3361   PetscCall(MatSetType(mat_elemental, MATELEMENTAL));
3362   PetscCall(MatSetUp(mat_elemental));
3363 
3364   /* PETSc-Elemental interaface uses axpy for setting off-processor entries, only ADD_VALUES is allowed */
3365   PetscCall(MatSetValues(mat_elemental, M, rows, N, cols, v_colwise, ADD_VALUES));
3366   PetscCall(MatAssemblyBegin(mat_elemental, MAT_FINAL_ASSEMBLY));
3367   PetscCall(MatAssemblyEnd(mat_elemental, MAT_FINAL_ASSEMBLY));
3368   PetscCall(PetscFree3(v_colwise, rows, cols));
3369 
3370   if (reuse == MAT_INPLACE_MATRIX) {
3371     PetscCall(MatHeaderReplace(A, &mat_elemental));
3372   } else {
3373     *newmat = mat_elemental;
3374   }
3375   PetscFunctionReturn(PETSC_SUCCESS);
3376 }
3377 #endif
3378 
3379 PetscErrorCode MatDenseSetLDA_SeqDense(Mat B, PetscInt lda)
3380 {
3381   Mat_SeqDense *b = (Mat_SeqDense *)B->data;
3382   PetscBool     data;
3383 
3384   PetscFunctionBegin;
3385   data = (B->rmap->n > 0 && B->cmap->n > 0) ? (b->v ? PETSC_TRUE : PETSC_FALSE) : PETSC_FALSE;
3386   PetscCheck(b->user_alloc || !data || b->lda == lda, PETSC_COMM_SELF, PETSC_ERR_ORDER, "LDA cannot be changed after allocation of internal storage");
3387   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);
3388   PetscCall(PetscBLASIntCast(lda, &b->lda));
3389   PetscFunctionReturn(PETSC_SUCCESS);
3390 }
3391 
3392 PetscErrorCode MatCreateMPIMatConcatenateSeqMat_SeqDense(MPI_Comm comm, Mat inmat, PetscInt n, MatReuse scall, Mat *outmat)
3393 {
3394   PetscFunctionBegin;
3395   PetscCall(MatCreateMPIMatConcatenateSeqMat_MPIDense(comm, inmat, n, scall, outmat));
3396   PetscFunctionReturn(PETSC_SUCCESS);
3397 }
3398 
3399 PetscErrorCode MatDenseCreateColumnVec_Private(Mat A, Vec *v)
3400 {
3401   PetscBool   isstd, iskok, iscuda, iship;
3402   PetscMPIInt size;
3403 #if PetscDefined(HAVE_CUDA) || PetscDefined(HAVE_HIP)
3404   /* we pass the data of A, to prevent allocating needless GPU memory the first time VecCUPMPlaceArray is called. */
3405   const PetscScalar *a;
3406 #endif
3407 
3408   PetscFunctionBegin;
3409   *v = NULL;
3410   PetscCall(PetscStrcmpAny(A->defaultvectype, &isstd, VECSTANDARD, VECSEQ, VECMPI, ""));
3411   PetscCall(PetscStrcmpAny(A->defaultvectype, &iskok, VECKOKKOS, VECSEQKOKKOS, VECMPIKOKKOS, ""));
3412   PetscCall(PetscStrcmpAny(A->defaultvectype, &iscuda, VECCUDA, VECSEQCUDA, VECMPICUDA, ""));
3413   PetscCall(PetscStrcmpAny(A->defaultvectype, &iship, VECHIP, VECSEQHIP, VECMPIHIP, ""));
3414   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)A), &size));
3415   if (isstd) {
3416     if (size > 1) PetscCall(VecCreateMPIWithArray(PetscObjectComm((PetscObject)A), A->rmap->bs, A->rmap->n, A->rmap->N, NULL, v));
3417     else PetscCall(VecCreateSeqWithArray(PetscObjectComm((PetscObject)A), A->rmap->bs, A->rmap->n, NULL, v));
3418   } else if (iskok) {
3419     PetscCheck(PetscDefined(HAVE_KOKKOS_KERNELS), PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Reconfigure using KOKKOS kernels support");
3420 #if PetscDefined(HAVE_KOKKOS_KERNELS)
3421     if (size > 1) PetscCall(VecCreateMPIKokkosWithArray(PetscObjectComm((PetscObject)A), A->rmap->bs, A->rmap->n, A->rmap->N, NULL, v));
3422     else PetscCall(VecCreateSeqKokkosWithArray(PetscObjectComm((PetscObject)A), A->rmap->bs, A->rmap->n, NULL, v));
3423 #endif
3424   } else if (iscuda) {
3425     PetscCheck(PetscDefined(HAVE_CUDA), PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Reconfigure using CUDA support");
3426 #if PetscDefined(HAVE_CUDA)
3427     PetscCall(MatDenseCUDAGetArrayRead(A, &a));
3428     if (size > 1) PetscCall(VecCreateMPICUDAWithArrays(PetscObjectComm((PetscObject)A), A->rmap->bs, A->rmap->n, A->rmap->N, NULL, a, v));
3429     else PetscCall(VecCreateSeqCUDAWithArrays(PetscObjectComm((PetscObject)A), A->rmap->bs, A->rmap->n, NULL, a, v));
3430 #endif
3431   } else if (iship) {
3432     PetscCheck(PetscDefined(HAVE_HIP), PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Reconfigure using HIP support");
3433 #if PetscDefined(HAVE_HIP)
3434     PetscCall(MatDenseHIPGetArrayRead(A, &a));
3435     if (size > 1) PetscCall(VecCreateMPIHIPWithArrays(PetscObjectComm((PetscObject)A), A->rmap->bs, A->rmap->n, A->rmap->N, NULL, a, v));
3436     else PetscCall(VecCreateSeqHIPWithArrays(PetscObjectComm((PetscObject)A), A->rmap->bs, A->rmap->n, NULL, a, v));
3437 #endif
3438   }
3439   PetscCheck(*v, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Not coded for type %s", A->defaultvectype);
3440   PetscFunctionReturn(PETSC_SUCCESS);
3441 }
3442 
3443 PetscErrorCode MatDenseGetColumnVec_SeqDense(Mat A, PetscInt col, Vec *v)
3444 {
3445   Mat_SeqDense *a = (Mat_SeqDense *)A->data;
3446 
3447   PetscFunctionBegin;
3448   PetscCheck(!a->vecinuse, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Need to call MatDenseRestoreColumnVec() first");
3449   PetscCheck(!a->matinuse, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Need to call MatDenseRestoreSubMatrix() first");
3450   if (!a->cvec) PetscCall(MatDenseCreateColumnVec_Private(A, &a->cvec));
3451   a->vecinuse = col + 1;
3452   PetscCall(MatDenseGetArray(A, (PetscScalar **)&a->ptrinuse));
3453   PetscCall(VecPlaceArray(a->cvec, a->ptrinuse + (size_t)col * (size_t)a->lda));
3454   *v = a->cvec;
3455   PetscFunctionReturn(PETSC_SUCCESS);
3456 }
3457 
3458 PetscErrorCode MatDenseRestoreColumnVec_SeqDense(Mat A, PetscInt col, Vec *v)
3459 {
3460   Mat_SeqDense *a = (Mat_SeqDense *)A->data;
3461 
3462   PetscFunctionBegin;
3463   PetscCheck(a->vecinuse, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Need to call MatDenseGetColumnVec() first");
3464   PetscCheck(a->cvec, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Missing internal column vector");
3465   VecCheckAssembled(a->cvec);
3466   a->vecinuse = 0;
3467   PetscCall(MatDenseRestoreArray(A, (PetscScalar **)&a->ptrinuse));
3468   PetscCall(VecResetArray(a->cvec));
3469   if (v) *v = NULL;
3470   PetscFunctionReturn(PETSC_SUCCESS);
3471 }
3472 
3473 PetscErrorCode MatDenseGetColumnVecRead_SeqDense(Mat A, PetscInt col, Vec *v)
3474 {
3475   Mat_SeqDense *a = (Mat_SeqDense *)A->data;
3476 
3477   PetscFunctionBegin;
3478   PetscCheck(!a->vecinuse, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Need to call MatDenseRestoreColumnVec() first");
3479   PetscCheck(!a->matinuse, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Need to call MatDenseRestoreSubMatrix() first");
3480   if (!a->cvec) PetscCall(MatDenseCreateColumnVec_Private(A, &a->cvec));
3481   a->vecinuse = col + 1;
3482   PetscCall(MatDenseGetArrayRead(A, &a->ptrinuse));
3483   PetscCall(VecPlaceArray(a->cvec, PetscSafePointerPlusOffset(a->ptrinuse, (size_t)col * (size_t)a->lda)));
3484   PetscCall(VecLockReadPush(a->cvec));
3485   *v = a->cvec;
3486   PetscFunctionReturn(PETSC_SUCCESS);
3487 }
3488 
3489 PetscErrorCode MatDenseRestoreColumnVecRead_SeqDense(Mat A, PetscInt col, Vec *v)
3490 {
3491   Mat_SeqDense *a = (Mat_SeqDense *)A->data;
3492 
3493   PetscFunctionBegin;
3494   PetscCheck(a->vecinuse, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Need to call MatDenseGetColumnVec() first");
3495   PetscCheck(a->cvec, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Missing internal column vector");
3496   VecCheckAssembled(a->cvec);
3497   a->vecinuse = 0;
3498   PetscCall(MatDenseRestoreArrayRead(A, &a->ptrinuse));
3499   PetscCall(VecLockReadPop(a->cvec));
3500   PetscCall(VecResetArray(a->cvec));
3501   if (v) *v = NULL;
3502   PetscFunctionReturn(PETSC_SUCCESS);
3503 }
3504 
3505 PetscErrorCode MatDenseGetColumnVecWrite_SeqDense(Mat A, PetscInt col, Vec *v)
3506 {
3507   Mat_SeqDense *a = (Mat_SeqDense *)A->data;
3508 
3509   PetscFunctionBegin;
3510   PetscCheck(!a->vecinuse, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Need to call MatDenseRestoreColumnVec() first");
3511   PetscCheck(!a->matinuse, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Need to call MatDenseRestoreSubMatrix() first");
3512   if (!a->cvec) PetscCall(MatDenseCreateColumnVec_Private(A, &a->cvec));
3513   a->vecinuse = col + 1;
3514   PetscCall(MatDenseGetArrayWrite(A, (PetscScalar **)&a->ptrinuse));
3515   PetscCall(VecPlaceArray(a->cvec, PetscSafePointerPlusOffset(a->ptrinuse, (size_t)col * (size_t)a->lda)));
3516   *v = a->cvec;
3517   PetscFunctionReturn(PETSC_SUCCESS);
3518 }
3519 
3520 PetscErrorCode MatDenseRestoreColumnVecWrite_SeqDense(Mat A, PetscInt col, Vec *v)
3521 {
3522   Mat_SeqDense *a = (Mat_SeqDense *)A->data;
3523 
3524   PetscFunctionBegin;
3525   PetscCheck(a->vecinuse, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Need to call MatDenseGetColumnVec() first");
3526   PetscCheck(a->cvec, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Missing internal column vector");
3527   VecCheckAssembled(a->cvec);
3528   a->vecinuse = 0;
3529   PetscCall(MatDenseRestoreArrayWrite(A, (PetscScalar **)&a->ptrinuse));
3530   PetscCall(VecResetArray(a->cvec));
3531   if (v) *v = NULL;
3532   PetscFunctionReturn(PETSC_SUCCESS);
3533 }
3534 
3535 PetscErrorCode MatDenseGetSubMatrix_SeqDense(Mat A, PetscInt rbegin, PetscInt rend, PetscInt cbegin, PetscInt cend, Mat *v)
3536 {
3537   Mat_SeqDense *a = (Mat_SeqDense *)A->data;
3538 
3539   PetscFunctionBegin;
3540   PetscCheck(!a->vecinuse, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Need to call MatDenseRestoreColumnVec() first");
3541   PetscCheck(!a->matinuse, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Need to call MatDenseRestoreSubMatrix() first");
3542   if (a->cmat && (cend - cbegin != a->cmat->cmap->N || rend - rbegin != a->cmat->rmap->N)) PetscCall(MatDestroy(&a->cmat));
3543   if (!a->cmat) {
3544     PetscCall(MatCreateDense(PetscObjectComm((PetscObject)A), rend - rbegin, PETSC_DECIDE, rend - rbegin, cend - cbegin, PetscSafePointerPlusOffset(a->v, rbegin + (size_t)cbegin * a->lda), &a->cmat));
3545   } else {
3546     PetscCall(MatDensePlaceArray(a->cmat, PetscSafePointerPlusOffset(a->v, rbegin + (size_t)cbegin * a->lda)));
3547   }
3548   PetscCall(MatDenseSetLDA(a->cmat, a->lda));
3549   a->matinuse = cbegin + 1;
3550   *v          = a->cmat;
3551 #if defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
3552   A->offloadmask = PETSC_OFFLOAD_CPU;
3553 #endif
3554   PetscFunctionReturn(PETSC_SUCCESS);
3555 }
3556 
3557 PetscErrorCode MatDenseRestoreSubMatrix_SeqDense(Mat A, Mat *v)
3558 {
3559   Mat_SeqDense *a = (Mat_SeqDense *)A->data;
3560 
3561   PetscFunctionBegin;
3562   PetscCheck(a->matinuse, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Need to call MatDenseGetSubMatrix() first");
3563   PetscCheck(a->cmat, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Missing internal column matrix");
3564   PetscCheck(*v == a->cmat, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Not the matrix obtained from MatDenseGetSubMatrix()");
3565   a->matinuse = 0;
3566   PetscCall(MatDenseResetArray(a->cmat));
3567   if (v) *v = NULL;
3568 #if defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
3569   A->offloadmask = PETSC_OFFLOAD_CPU;
3570 #endif
3571   PetscFunctionReturn(PETSC_SUCCESS);
3572 }
3573 
3574 /*MC
3575    MATSEQDENSE - MATSEQDENSE = "seqdense" - A matrix type to be used for sequential dense matrices.
3576 
3577    Options Database Key:
3578 . -mat_type seqdense - sets the matrix type to `MATSEQDENSE` during a call to `MatSetFromOptions()`
3579 
3580   Level: beginner
3581 
3582 .seealso: [](ch_matrices), `Mat`, `MATSEQDENSE`, `MatCreateSeqDense()`
3583 M*/
3584 PetscErrorCode MatCreate_SeqDense(Mat B)
3585 {
3586   Mat_SeqDense *b;
3587   PetscMPIInt   size;
3588 
3589   PetscFunctionBegin;
3590   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)B), &size));
3591   PetscCheck(size <= 1, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Comm must be of size 1");
3592 
3593   PetscCall(PetscNew(&b));
3594   B->data   = (void *)b;
3595   B->ops[0] = MatOps_Values;
3596 
3597   b->roworiented = PETSC_TRUE;
3598 
3599   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatQRFactor_C", MatQRFactor_SeqDense));
3600   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatDenseGetLDA_C", MatDenseGetLDA_SeqDense));
3601   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatDenseSetLDA_C", MatDenseSetLDA_SeqDense));
3602   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatDenseGetArray_C", MatDenseGetArray_SeqDense));
3603   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatDenseRestoreArray_C", MatDenseRestoreArray_SeqDense));
3604   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatDensePlaceArray_C", MatDensePlaceArray_SeqDense));
3605   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatDenseResetArray_C", MatDenseResetArray_SeqDense));
3606   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatDenseReplaceArray_C", MatDenseReplaceArray_SeqDense));
3607   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatDenseGetArrayRead_C", MatDenseGetArray_SeqDense));
3608   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatDenseRestoreArrayRead_C", MatDenseRestoreArray_SeqDense));
3609   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatDenseGetArrayWrite_C", MatDenseGetArray_SeqDense));
3610   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatDenseRestoreArrayWrite_C", MatDenseRestoreArray_SeqDense));
3611   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatConvert_seqdense_seqaij_C", MatConvert_SeqDense_SeqAIJ));
3612 #if defined(PETSC_HAVE_ELEMENTAL)
3613   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatConvert_seqdense_elemental_C", MatConvert_SeqDense_Elemental));
3614 #endif
3615 #if defined(PETSC_HAVE_SCALAPACK)
3616   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatConvert_seqdense_scalapack_C", MatConvert_Dense_ScaLAPACK));
3617 #endif
3618 #if defined(PETSC_HAVE_CUDA)
3619   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatConvert_seqdense_seqdensecuda_C", MatConvert_SeqDense_SeqDenseCUDA));
3620   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatProductSetFromOptions_seqdensecuda_seqdensecuda_C", MatProductSetFromOptions_SeqDense));
3621   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatProductSetFromOptions_seqdensecuda_seqdense_C", MatProductSetFromOptions_SeqDense));
3622   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatProductSetFromOptions_seqdense_seqdensecuda_C", MatProductSetFromOptions_SeqDense));
3623 #endif
3624 #if defined(PETSC_HAVE_HIP)
3625   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatConvert_seqdense_seqdensehip_C", MatConvert_SeqDense_SeqDenseHIP));
3626   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatProductSetFromOptions_seqdensehip_seqdensehip_C", MatProductSetFromOptions_SeqDense));
3627   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatProductSetFromOptions_seqdensehip_seqdense_C", MatProductSetFromOptions_SeqDense));
3628   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatProductSetFromOptions_seqdense_seqdensehip_C", MatProductSetFromOptions_SeqDense));
3629 #endif
3630   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatSeqDenseSetPreallocation_C", MatSeqDenseSetPreallocation_SeqDense));
3631   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatProductSetFromOptions_seqaij_seqdense_C", MatProductSetFromOptions_SeqAIJ_SeqDense));
3632   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatProductSetFromOptions_seqdense_seqdense_C", MatProductSetFromOptions_SeqDense));
3633   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatProductSetFromOptions_seqbaij_seqdense_C", MatProductSetFromOptions_SeqXBAIJ_SeqDense));
3634   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatProductSetFromOptions_seqsbaij_seqdense_C", MatProductSetFromOptions_SeqXBAIJ_SeqDense));
3635 
3636   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatDenseGetColumn_C", MatDenseGetColumn_SeqDense));
3637   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatDenseRestoreColumn_C", MatDenseRestoreColumn_SeqDense));
3638   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatDenseGetColumnVec_C", MatDenseGetColumnVec_SeqDense));
3639   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatDenseRestoreColumnVec_C", MatDenseRestoreColumnVec_SeqDense));
3640   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatDenseGetColumnVecRead_C", MatDenseGetColumnVecRead_SeqDense));
3641   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatDenseRestoreColumnVecRead_C", MatDenseRestoreColumnVecRead_SeqDense));
3642   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatDenseGetColumnVecWrite_C", MatDenseGetColumnVecWrite_SeqDense));
3643   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatDenseRestoreColumnVecWrite_C", MatDenseRestoreColumnVecWrite_SeqDense));
3644   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatDenseGetSubMatrix_C", MatDenseGetSubMatrix_SeqDense));
3645   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatDenseRestoreSubMatrix_C", MatDenseRestoreSubMatrix_SeqDense));
3646   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatMultAddColumnRange_C", MatMultAddColumnRange_SeqDense));
3647   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatMultHermitianTransposeColumnRange_C", MatMultHermitianTransposeColumnRange_SeqDense));
3648   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatMultHermitianTransposeAddColumnRange_C", MatMultHermitianTransposeAddColumnRange_SeqDense));
3649   PetscCall(PetscObjectChangeTypeName((PetscObject)B, MATSEQDENSE));
3650   PetscFunctionReturn(PETSC_SUCCESS);
3651 }
3652 
3653 /*@C
3654   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.
3655 
3656   Not Collective
3657 
3658   Input Parameters:
3659 + A   - a `MATSEQDENSE` or `MATMPIDENSE` matrix
3660 - col - column index
3661 
3662   Output Parameter:
3663 . vals - pointer to the data
3664 
3665   Level: intermediate
3666 
3667   Note:
3668   Use `MatDenseGetColumnVec()` to get access to a column of a `MATDENSE` treated as a `Vec`
3669 
3670 .seealso: [](ch_matrices), `Mat`, `MATDENSE`, `MatDenseRestoreColumn()`, `MatDenseGetColumnVec()`
3671 @*/
3672 PetscErrorCode MatDenseGetColumn(Mat A, PetscInt col, PetscScalar *vals[])
3673 {
3674   PetscFunctionBegin;
3675   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
3676   PetscValidLogicalCollectiveInt(A, col, 2);
3677   PetscAssertPointer(vals, 3);
3678   PetscUseMethod(A, "MatDenseGetColumn_C", (Mat, PetscInt, PetscScalar **), (A, col, vals));
3679   PetscFunctionReturn(PETSC_SUCCESS);
3680 }
3681 
3682 /*@C
3683   MatDenseRestoreColumn - returns access to a column of a `MATDENSE` matrix which is returned by `MatDenseGetColumn()`.
3684 
3685   Not Collective
3686 
3687   Input Parameters:
3688 + A    - a `MATSEQDENSE` or `MATMPIDENSE` matrix
3689 - vals - pointer to the data (may be `NULL`)
3690 
3691   Level: intermediate
3692 
3693 .seealso: [](ch_matrices), `Mat`, `MATDENSE`, `MatDenseGetColumn()`
3694 @*/
3695 PetscErrorCode MatDenseRestoreColumn(Mat A, PetscScalar *vals[])
3696 {
3697   PetscFunctionBegin;
3698   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
3699   PetscAssertPointer(vals, 2);
3700   PetscUseMethod(A, "MatDenseRestoreColumn_C", (Mat, PetscScalar **), (A, vals));
3701   PetscFunctionReturn(PETSC_SUCCESS);
3702 }
3703 
3704 /*@
3705   MatDenseGetColumnVec - Gives read-write access to a column of a `MATDENSE` matrix, represented as a `Vec`.
3706 
3707   Collective
3708 
3709   Input Parameters:
3710 + A   - the `Mat` object
3711 - col - the column index
3712 
3713   Output Parameter:
3714 . v - the vector
3715 
3716   Level: intermediate
3717 
3718   Notes:
3719   The vector is owned by PETSc. Users need to call `MatDenseRestoreColumnVec()` when the vector is no longer needed.
3720 
3721   Use `MatDenseGetColumnVecRead()` to obtain read-only access or `MatDenseGetColumnVecWrite()` for write-only access.
3722 
3723 .seealso: [](ch_matrices), `Mat`, `MATDENSE`, `MATDENSECUDA`, `MATDENSEHIP`, `MatDenseGetColumnVecRead()`, `MatDenseGetColumnVecWrite()`, `MatDenseRestoreColumnVec()`, `MatDenseRestoreColumnVecRead()`, `MatDenseRestoreColumnVecWrite()`, `MatDenseGetColumn()`
3724 @*/
3725 PetscErrorCode MatDenseGetColumnVec(Mat A, PetscInt col, Vec *v)
3726 {
3727   PetscFunctionBegin;
3728   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
3729   PetscValidType(A, 1);
3730   PetscValidLogicalCollectiveInt(A, col, 2);
3731   PetscAssertPointer(v, 3);
3732   PetscCheck(A->preallocated, PetscObjectComm((PetscObject)A), PETSC_ERR_ORDER, "Matrix not preallocated");
3733   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);
3734   PetscUseMethod(A, "MatDenseGetColumnVec_C", (Mat, PetscInt, Vec *), (A, col, v));
3735   PetscFunctionReturn(PETSC_SUCCESS);
3736 }
3737 
3738 /*@
3739   MatDenseRestoreColumnVec - Returns access to a column of a dense matrix obtained from `MatDenseGetColumnVec()`.
3740 
3741   Collective
3742 
3743   Input Parameters:
3744 + A   - the `Mat` object
3745 . col - the column index
3746 - v   - the `Vec` object (may be `NULL`)
3747 
3748   Level: intermediate
3749 
3750 .seealso: [](ch_matrices), `Mat`, `MATDENSE`, `MATDENSECUDA`, `MATDENSEHIP`, `MatDenseGetColumnVec()`, `MatDenseGetColumnVecRead()`, `MatDenseGetColumnVecWrite()`, `MatDenseRestoreColumnVecRead()`, `MatDenseRestoreColumnVecWrite()`
3751 @*/
3752 PetscErrorCode MatDenseRestoreColumnVec(Mat A, PetscInt col, Vec *v)
3753 {
3754   PetscFunctionBegin;
3755   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
3756   PetscValidType(A, 1);
3757   PetscValidLogicalCollectiveInt(A, col, 2);
3758   PetscCheck(A->preallocated, PetscObjectComm((PetscObject)A), PETSC_ERR_ORDER, "Matrix not preallocated");
3759   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);
3760   PetscUseMethod(A, "MatDenseRestoreColumnVec_C", (Mat, PetscInt, Vec *), (A, col, v));
3761   PetscFunctionReturn(PETSC_SUCCESS);
3762 }
3763 
3764 /*@
3765   MatDenseGetColumnVecRead - Gives read-only access to a column of a dense matrix, represented as a `Vec`.
3766 
3767   Collective
3768 
3769   Input Parameters:
3770 + A   - the `Mat` object
3771 - col - the column index
3772 
3773   Output Parameter:
3774 . v - the vector
3775 
3776   Level: intermediate
3777 
3778   Notes:
3779   The vector is owned by PETSc and users cannot modify it.
3780 
3781   Users need to call `MatDenseRestoreColumnVecRead()` when the vector is no longer needed.
3782 
3783   Use `MatDenseGetColumnVec()` to obtain read-write access or `MatDenseGetColumnVecWrite()` for write-only access.
3784 
3785 .seealso: [](ch_matrices), `Mat`, `MATDENSE`, `MATDENSECUDA`, `MATDENSEHIP`, `MatDenseGetColumnVec()`, `MatDenseGetColumnVecWrite()`, `MatDenseRestoreColumnVec()`, `MatDenseRestoreColumnVecRead()`, `MatDenseRestoreColumnVecWrite()`
3786 @*/
3787 PetscErrorCode MatDenseGetColumnVecRead(Mat A, PetscInt col, Vec *v)
3788 {
3789   PetscFunctionBegin;
3790   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
3791   PetscValidType(A, 1);
3792   PetscValidLogicalCollectiveInt(A, col, 2);
3793   PetscAssertPointer(v, 3);
3794   PetscCheck(A->preallocated, PetscObjectComm((PetscObject)A), PETSC_ERR_ORDER, "Matrix not preallocated");
3795   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);
3796   PetscUseMethod(A, "MatDenseGetColumnVecRead_C", (Mat, PetscInt, Vec *), (A, col, v));
3797   PetscFunctionReturn(PETSC_SUCCESS);
3798 }
3799 
3800 /*@
3801   MatDenseRestoreColumnVecRead - Returns access to a column of a dense matrix obtained from `MatDenseGetColumnVecRead()`.
3802 
3803   Collective
3804 
3805   Input Parameters:
3806 + A   - the `Mat` object
3807 . col - the column index
3808 - v   - the `Vec` object (may be `NULL`)
3809 
3810   Level: intermediate
3811 
3812 .seealso: [](ch_matrices), `Mat`, `MATDENSE`, `MATDENSECUDA`, `MATDENSEHIP`, `MatDenseGetColumnVec()`, `MatDenseGetColumnVecRead()`, `MatDenseGetColumnVecWrite()`, `MatDenseRestoreColumnVec()`, `MatDenseRestoreColumnVecWrite()`
3813 @*/
3814 PetscErrorCode MatDenseRestoreColumnVecRead(Mat A, PetscInt col, Vec *v)
3815 {
3816   PetscFunctionBegin;
3817   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
3818   PetscValidType(A, 1);
3819   PetscValidLogicalCollectiveInt(A, col, 2);
3820   PetscCheck(A->preallocated, PetscObjectComm((PetscObject)A), PETSC_ERR_ORDER, "Matrix not preallocated");
3821   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);
3822   PetscUseMethod(A, "MatDenseRestoreColumnVecRead_C", (Mat, PetscInt, Vec *), (A, col, v));
3823   PetscFunctionReturn(PETSC_SUCCESS);
3824 }
3825 
3826 /*@
3827   MatDenseGetColumnVecWrite - Gives write-only access to a column of a dense matrix, represented as a `Vec`.
3828 
3829   Collective
3830 
3831   Input Parameters:
3832 + A   - the `Mat` object
3833 - col - the column index
3834 
3835   Output Parameter:
3836 . v - the vector
3837 
3838   Level: intermediate
3839 
3840   Notes:
3841   The vector is owned by PETSc. Users need to call `MatDenseRestoreColumnVecWrite()` when the vector is no longer needed.
3842 
3843   Use `MatDenseGetColumnVec()` to obtain read-write access or `MatDenseGetColumnVecRead()` for read-only access.
3844 
3845 .seealso: [](ch_matrices), `Mat`, `MATDENSE`, `MATDENSECUDA`, `MATDENSEHIP`, `MatDenseGetColumnVec()`, `MatDenseGetColumnVecRead()`, `MatDenseRestoreColumnVec()`, `MatDenseRestoreColumnVecRead()`, `MatDenseRestoreColumnVecWrite()`
3846 @*/
3847 PetscErrorCode MatDenseGetColumnVecWrite(Mat A, PetscInt col, Vec *v)
3848 {
3849   PetscFunctionBegin;
3850   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
3851   PetscValidType(A, 1);
3852   PetscValidLogicalCollectiveInt(A, col, 2);
3853   PetscAssertPointer(v, 3);
3854   PetscCheck(A->preallocated, PetscObjectComm((PetscObject)A), PETSC_ERR_ORDER, "Matrix not preallocated");
3855   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);
3856   PetscUseMethod(A, "MatDenseGetColumnVecWrite_C", (Mat, PetscInt, Vec *), (A, col, v));
3857   PetscFunctionReturn(PETSC_SUCCESS);
3858 }
3859 
3860 /*@
3861   MatDenseRestoreColumnVecWrite - Returns access to a column of a dense matrix obtained from `MatDenseGetColumnVecWrite()`.
3862 
3863   Collective
3864 
3865   Input Parameters:
3866 + A   - the `Mat` object
3867 . col - the column index
3868 - v   - the `Vec` object (may be `NULL`)
3869 
3870   Level: intermediate
3871 
3872 .seealso: [](ch_matrices), `Mat`, `MATDENSE`, `MATDENSECUDA`, `MATDENSEHIP`, `MatDenseGetColumnVec()`, `MatDenseGetColumnVecRead()`, `MatDenseGetColumnVecWrite()`, `MatDenseRestoreColumnVec()`, `MatDenseRestoreColumnVecRead()`
3873 @*/
3874 PetscErrorCode MatDenseRestoreColumnVecWrite(Mat A, PetscInt col, Vec *v)
3875 {
3876   PetscFunctionBegin;
3877   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
3878   PetscValidType(A, 1);
3879   PetscValidLogicalCollectiveInt(A, col, 2);
3880   PetscCheck(A->preallocated, PetscObjectComm((PetscObject)A), PETSC_ERR_ORDER, "Matrix not preallocated");
3881   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);
3882   PetscUseMethod(A, "MatDenseRestoreColumnVecWrite_C", (Mat, PetscInt, Vec *), (A, col, v));
3883   PetscFunctionReturn(PETSC_SUCCESS);
3884 }
3885 
3886 /*@
3887   MatDenseGetSubMatrix - Gives access to a block of rows and columns of a dense matrix, represented as a `Mat`.
3888 
3889   Collective
3890 
3891   Input Parameters:
3892 + A      - the `Mat` object
3893 . rbegin - the first global row index in the block (if `PETSC_DECIDE`, is 0)
3894 . rend   - the global row index past the last one in the block (if `PETSC_DECIDE`, is `M`)
3895 . cbegin - the first global column index in the block (if `PETSC_DECIDE`, is 0)
3896 - cend   - the global column index past the last one in the block (if `PETSC_DECIDE`, is `N`)
3897 
3898   Output Parameter:
3899 . v - the matrix
3900 
3901   Level: intermediate
3902 
3903   Notes:
3904   The matrix is owned by PETSc. Users need to call `MatDenseRestoreSubMatrix()` when the matrix is no longer needed.
3905 
3906   The output matrix is not redistributed by PETSc, so depending on the values of `rbegin` and `rend`, some processes may have no local rows.
3907 
3908 .seealso: [](ch_matrices), `Mat`, `MATDENSE`, `MATDENSECUDA`, `MATDENSEHIP`, `MatDenseGetColumnVec()`, `MatDenseRestoreColumnVec()`, `MatDenseRestoreSubMatrix()`
3909 @*/
3910 PetscErrorCode MatDenseGetSubMatrix(Mat A, PetscInt rbegin, PetscInt rend, PetscInt cbegin, PetscInt cend, Mat *v)
3911 {
3912   PetscFunctionBegin;
3913   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
3914   PetscValidType(A, 1);
3915   PetscValidLogicalCollectiveInt(A, rbegin, 2);
3916   PetscValidLogicalCollectiveInt(A, rend, 3);
3917   PetscValidLogicalCollectiveInt(A, cbegin, 4);
3918   PetscValidLogicalCollectiveInt(A, cend, 5);
3919   PetscAssertPointer(v, 6);
3920   if (rbegin == PETSC_DECIDE) rbegin = 0;
3921   if (rend == PETSC_DECIDE) rend = A->rmap->N;
3922   if (cbegin == PETSC_DECIDE) cbegin = 0;
3923   if (cend == PETSC_DECIDE) cend = A->cmap->N;
3924   PetscCheck(A->preallocated, PetscObjectComm((PetscObject)A), PETSC_ERR_ORDER, "Matrix not preallocated");
3925   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);
3926   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);
3927   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);
3928   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);
3929   PetscUseMethod(A, "MatDenseGetSubMatrix_C", (Mat, PetscInt, PetscInt, PetscInt, PetscInt, Mat *), (A, rbegin, rend, cbegin, cend, v));
3930   PetscFunctionReturn(PETSC_SUCCESS);
3931 }
3932 
3933 /*@
3934   MatDenseRestoreSubMatrix - Returns access to a block of columns of a dense matrix obtained from `MatDenseGetSubMatrix()`.
3935 
3936   Collective
3937 
3938   Input Parameters:
3939 + A - the `Mat` object
3940 - v - the `Mat` object (may be `NULL`)
3941 
3942   Level: intermediate
3943 
3944 .seealso: [](ch_matrices), `Mat`, `MATDENSE`, `MATDENSECUDA`, `MATDENSEHIP`, `MatDenseGetColumnVec()`, `MatDenseRestoreColumnVec()`, `MatDenseGetSubMatrix()`
3945 @*/
3946 PetscErrorCode MatDenseRestoreSubMatrix(Mat A, Mat *v)
3947 {
3948   PetscFunctionBegin;
3949   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
3950   PetscValidType(A, 1);
3951   PetscAssertPointer(v, 2);
3952   PetscUseMethod(A, "MatDenseRestoreSubMatrix_C", (Mat, Mat *), (A, v));
3953   PetscFunctionReturn(PETSC_SUCCESS);
3954 }
3955 
3956 #include <petscblaslapack.h>
3957 #include <petsc/private/kernels/blockinvert.h>
3958 
3959 PetscErrorCode MatSeqDenseInvert(Mat A)
3960 {
3961   PetscInt        m;
3962   const PetscReal shift = 0.0;
3963   PetscBool       allowzeropivot, zeropivotdetected = PETSC_FALSE;
3964   PetscScalar    *values;
3965 
3966   PetscFunctionBegin;
3967   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
3968   PetscCall(MatDenseGetArray(A, &values));
3969   PetscCall(MatGetLocalSize(A, &m, NULL));
3970   allowzeropivot = PetscNot(A->erroriffailure);
3971   /* factor and invert each block */
3972   switch (m) {
3973   case 1:
3974     values[0] = (PetscScalar)1.0 / (values[0] + shift);
3975     break;
3976   case 2:
3977     PetscCall(PetscKernel_A_gets_inverse_A_2(values, shift, allowzeropivot, &zeropivotdetected));
3978     if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
3979     break;
3980   case 3:
3981     PetscCall(PetscKernel_A_gets_inverse_A_3(values, shift, allowzeropivot, &zeropivotdetected));
3982     if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
3983     break;
3984   case 4:
3985     PetscCall(PetscKernel_A_gets_inverse_A_4(values, shift, allowzeropivot, &zeropivotdetected));
3986     if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
3987     break;
3988   case 5: {
3989     PetscScalar work[25];
3990     PetscInt    ipvt[5];
3991 
3992     PetscCall(PetscKernel_A_gets_inverse_A_5(values, ipvt, work, shift, allowzeropivot, &zeropivotdetected));
3993     if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
3994   } break;
3995   case 6:
3996     PetscCall(PetscKernel_A_gets_inverse_A_6(values, shift, allowzeropivot, &zeropivotdetected));
3997     if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
3998     break;
3999   case 7:
4000     PetscCall(PetscKernel_A_gets_inverse_A_7(values, shift, allowzeropivot, &zeropivotdetected));
4001     if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
4002     break;
4003   default: {
4004     PetscInt    *v_pivots, *IJ, j;
4005     PetscScalar *v_work;
4006 
4007     PetscCall(PetscMalloc3(m, &v_work, m, &v_pivots, m, &IJ));
4008     for (j = 0; j < m; j++) IJ[j] = j;
4009     PetscCall(PetscKernel_A_gets_inverse_A(m, values, v_pivots, v_work, allowzeropivot, &zeropivotdetected));
4010     if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
4011     PetscCall(PetscFree3(v_work, v_pivots, IJ));
4012   }
4013   }
4014   PetscCall(MatDenseRestoreArray(A, &values));
4015   PetscFunctionReturn(PETSC_SUCCESS);
4016 }
4017