xref: /petsc/src/mat/impls/dense/seq/dense.c (revision 2ef1f0ff6e3530e8731eb06ad663081f5844f49f)
167e560aaSBarry Smith /*
267e560aaSBarry Smith      Defines the basic matrix operations for sequential dense.
347d993e7Ssuyashtn      Portions of this code are under:
447d993e7Ssuyashtn      Copyright (c) 2022 Advanced Micro Devices, Inc. All rights reserved.
567e560aaSBarry Smith */
6289bc588SBarry Smith 
7dec5eb66SMatthew G Knepley #include <../src/mat/impls/dense/seq/dense.h> /*I "petscmat.h" I*/
8cd3f9d89SJunchao Zhang #include <../src/mat/impls/dense/mpi/mpidense.h>
9c6db04a5SJed Brown #include <petscblaslapack.h>
106a63e612SBarry Smith #include <../src/mat/impls/aij/seq/aij.h>
11b2573a8aSBarry Smith 
12d71ae5a4SJacob Faibussowitsch PetscErrorCode MatSeqDenseSymmetrize_Private(Mat A, PetscBool hermitian)
13d71ae5a4SJacob Faibussowitsch {
148c178816SStefano Zampini   Mat_SeqDense *mat = (Mat_SeqDense *)A->data;
158c178816SStefano Zampini   PetscInt      j, k, n = A->rmap->n;
16ca15aa20SStefano Zampini   PetscScalar  *v;
178c178816SStefano Zampini 
188c178816SStefano Zampini   PetscFunctionBegin;
1908401ef6SPierre Jolivet   PetscCheck(A->rmap->n == A->cmap->n, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Cannot symmetrize a rectangular matrix");
209566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArray(A, &v));
218c178816SStefano Zampini   if (!hermitian) {
228c178816SStefano Zampini     for (k = 0; k < n; k++) {
23ad540459SPierre Jolivet       for (j = k; j < n; j++) v[j * mat->lda + k] = v[k * mat->lda + j];
248c178816SStefano Zampini     }
258c178816SStefano Zampini   } else {
268c178816SStefano Zampini     for (k = 0; k < n; k++) {
27ad540459SPierre Jolivet       for (j = k; j < n; j++) v[j * mat->lda + k] = PetscConj(v[k * mat->lda + j]);
288c178816SStefano Zampini     }
298c178816SStefano Zampini   }
309566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArray(A, &v));
313ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
328c178816SStefano Zampini }
338c178816SStefano Zampini 
34ff6a9541SJacob Faibussowitsch PetscErrorCode MatSeqDenseInvertFactors_Private(Mat A)
35d71ae5a4SJacob Faibussowitsch {
368c178816SStefano Zampini   Mat_SeqDense *mat = (Mat_SeqDense *)A->data;
378c178816SStefano Zampini   PetscBLASInt  info, n;
388c178816SStefano Zampini 
398c178816SStefano Zampini   PetscFunctionBegin;
403ba16761SJacob Faibussowitsch   if (!A->rmap->n || !A->cmap->n) PetscFunctionReturn(PETSC_SUCCESS);
419566063dSJacob Faibussowitsch   PetscCall(PetscBLASIntCast(A->cmap->n, &n));
428c178816SStefano Zampini   if (A->factortype == MAT_FACTOR_LU) {
4328b400f6SJacob Faibussowitsch     PetscCheck(mat->pivots, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Pivots not present");
448c178816SStefano Zampini     if (!mat->fwork) {
458c178816SStefano Zampini       mat->lfwork = n;
469566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(mat->lfwork, &mat->fwork));
478c178816SStefano Zampini     }
489566063dSJacob Faibussowitsch     PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF));
49792fecdfSBarry Smith     PetscCallBLAS("LAPACKgetri", LAPACKgetri_(&n, mat->v, &mat->lda, mat->pivots, mat->fwork, &mat->lfwork, &info));
509566063dSJacob Faibussowitsch     PetscCall(PetscFPTrapPop());
519566063dSJacob Faibussowitsch     PetscCall(PetscLogFlops((1.0 * A->cmap->n * A->cmap->n * A->cmap->n) / 3.0));
528c178816SStefano Zampini   } else if (A->factortype == MAT_FACTOR_CHOLESKY) {
53b94d7dedSBarry Smith     if (A->spd == PETSC_BOOL3_TRUE) {
549566063dSJacob Faibussowitsch       PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF));
55792fecdfSBarry Smith       PetscCallBLAS("LAPACKpotri", LAPACKpotri_("L", &n, mat->v, &mat->lda, &info));
569566063dSJacob Faibussowitsch       PetscCall(PetscFPTrapPop());
579566063dSJacob Faibussowitsch       PetscCall(MatSeqDenseSymmetrize_Private(A, PETSC_TRUE));
588c178816SStefano Zampini #if defined(PETSC_USE_COMPLEX)
59b94d7dedSBarry Smith     } else if (A->hermitian == PETSC_BOOL3_TRUE) {
6028b400f6SJacob Faibussowitsch       PetscCheck(mat->pivots, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Pivots not present");
6128b400f6SJacob Faibussowitsch       PetscCheck(mat->fwork, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Fwork not present");
629566063dSJacob Faibussowitsch       PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF));
63792fecdfSBarry Smith       PetscCallBLAS("LAPACKhetri", LAPACKhetri_("L", &n, mat->v, &mat->lda, mat->pivots, mat->fwork, &info));
649566063dSJacob Faibussowitsch       PetscCall(PetscFPTrapPop());
659566063dSJacob Faibussowitsch       PetscCall(MatSeqDenseSymmetrize_Private(A, PETSC_TRUE));
668c178816SStefano Zampini #endif
678c178816SStefano Zampini     } else { /* symmetric case */
6828b400f6SJacob Faibussowitsch       PetscCheck(mat->pivots, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Pivots not present");
6928b400f6SJacob Faibussowitsch       PetscCheck(mat->fwork, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Fwork not present");
709566063dSJacob Faibussowitsch       PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF));
71792fecdfSBarry Smith       PetscCallBLAS("LAPACKsytri", LAPACKsytri_("L", &n, mat->v, &mat->lda, mat->pivots, mat->fwork, &info));
729566063dSJacob Faibussowitsch       PetscCall(PetscFPTrapPop());
739566063dSJacob Faibussowitsch       PetscCall(MatSeqDenseSymmetrize_Private(A, PETSC_FALSE));
748c178816SStefano Zampini     }
7528b400f6SJacob Faibussowitsch     PetscCheck(!info, PETSC_COMM_SELF, PETSC_ERR_MAT_CH_ZRPVT, "Bad Inversion: zero pivot in row %" PetscInt_FMT, (PetscInt)info - 1);
769566063dSJacob Faibussowitsch     PetscCall(PetscLogFlops((1.0 * A->cmap->n * A->cmap->n * A->cmap->n) / 3.0));
778c178816SStefano Zampini   } else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Matrix must be factored to solve");
788c178816SStefano Zampini 
798c178816SStefano Zampini   A->ops->solve             = NULL;
808c178816SStefano Zampini   A->ops->matsolve          = NULL;
818c178816SStefano Zampini   A->ops->solvetranspose    = NULL;
828c178816SStefano Zampini   A->ops->matsolvetranspose = NULL;
838c178816SStefano Zampini   A->ops->solveadd          = NULL;
848c178816SStefano Zampini   A->ops->solvetransposeadd = NULL;
858c178816SStefano Zampini   A->factortype             = MAT_FACTOR_NONE;
869566063dSJacob Faibussowitsch   PetscCall(PetscFree(A->solvertype));
873ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
888c178816SStefano Zampini }
898c178816SStefano Zampini 
90d71ae5a4SJacob Faibussowitsch PetscErrorCode MatZeroRowsColumns_SeqDense(Mat A, PetscInt N, const PetscInt rows[], PetscScalar diag, Vec x, Vec b)
91d71ae5a4SJacob Faibussowitsch {
923f49a652SStefano Zampini   Mat_SeqDense      *l = (Mat_SeqDense *)A->data;
933f49a652SStefano Zampini   PetscInt           m = l->lda, n = A->cmap->n, r = A->rmap->n, i, j;
94ca15aa20SStefano Zampini   PetscScalar       *slot, *bb, *v;
953f49a652SStefano Zampini   const PetscScalar *xx;
963f49a652SStefano Zampini 
973f49a652SStefano Zampini   PetscFunctionBegin;
9876bd3646SJed Brown   if (PetscDefined(USE_DEBUG)) {
993f49a652SStefano Zampini     for (i = 0; i < N; i++) {
10008401ef6SPierre Jolivet       PetscCheck(rows[i] >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Negative row requested to be zeroed");
10108401ef6SPierre Jolivet       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);
10208401ef6SPierre Jolivet       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);
1033f49a652SStefano Zampini     }
10476bd3646SJed Brown   }
1053ba16761SJacob Faibussowitsch   if (!N) PetscFunctionReturn(PETSC_SUCCESS);
1063f49a652SStefano Zampini 
1073f49a652SStefano Zampini   /* fix right hand side if needed */
1083f49a652SStefano Zampini   if (x && b) {
1096c4d906cSStefano Zampini     Vec xt;
1106c4d906cSStefano Zampini 
11108401ef6SPierre Jolivet     PetscCheck(A->rmap->n == A->cmap->n, PETSC_COMM_SELF, PETSC_ERR_SUP, "Only coded for square matrices");
1129566063dSJacob Faibussowitsch     PetscCall(VecDuplicate(x, &xt));
1139566063dSJacob Faibussowitsch     PetscCall(VecCopy(x, xt));
1149566063dSJacob Faibussowitsch     PetscCall(VecScale(xt, -1.0));
1159566063dSJacob Faibussowitsch     PetscCall(MatMultAdd(A, xt, b, b));
1169566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&xt));
1179566063dSJacob Faibussowitsch     PetscCall(VecGetArrayRead(x, &xx));
1189566063dSJacob Faibussowitsch     PetscCall(VecGetArray(b, &bb));
1193f49a652SStefano Zampini     for (i = 0; i < N; i++) bb[rows[i]] = diag * xx[rows[i]];
1209566063dSJacob Faibussowitsch     PetscCall(VecRestoreArrayRead(x, &xx));
1219566063dSJacob Faibussowitsch     PetscCall(VecRestoreArray(b, &bb));
1223f49a652SStefano Zampini   }
1233f49a652SStefano Zampini 
1249566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArray(A, &v));
1253f49a652SStefano Zampini   for (i = 0; i < N; i++) {
126ca15aa20SStefano Zampini     slot = v + rows[i] * m;
1279566063dSJacob Faibussowitsch     PetscCall(PetscArrayzero(slot, r));
1283f49a652SStefano Zampini   }
1293f49a652SStefano Zampini   for (i = 0; i < N; i++) {
130ca15aa20SStefano Zampini     slot = v + rows[i];
1319371c9d4SSatish Balay     for (j = 0; j < n; j++) {
1329371c9d4SSatish Balay       *slot = 0.0;
1339371c9d4SSatish Balay       slot += m;
1349371c9d4SSatish Balay     }
1353f49a652SStefano Zampini   }
1363f49a652SStefano Zampini   if (diag != 0.0) {
13708401ef6SPierre Jolivet     PetscCheck(A->rmap->n == A->cmap->n, PETSC_COMM_SELF, PETSC_ERR_SUP, "Only coded for square matrices");
1383f49a652SStefano Zampini     for (i = 0; i < N; i++) {
139ca15aa20SStefano Zampini       slot  = v + (m + 1) * rows[i];
1403f49a652SStefano Zampini       *slot = diag;
1413f49a652SStefano Zampini     }
1423f49a652SStefano Zampini   }
1439566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArray(A, &v));
1443ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1453f49a652SStefano Zampini }
1463f49a652SStefano Zampini 
147d71ae5a4SJacob Faibussowitsch PetscErrorCode MatPtAPNumeric_SeqDense_SeqDense(Mat A, Mat P, Mat C)
148d71ae5a4SJacob Faibussowitsch {
149abc3b08eSStefano Zampini   Mat_SeqDense *c = (Mat_SeqDense *)(C->data);
150abc3b08eSStefano Zampini 
151abc3b08eSStefano Zampini   PetscFunctionBegin;
152ca15aa20SStefano Zampini   if (c->ptapwork) {
1539566063dSJacob Faibussowitsch     PetscCall((*C->ops->matmultnumeric)(A, P, c->ptapwork));
1549566063dSJacob Faibussowitsch     PetscCall((*C->ops->transposematmultnumeric)(P, c->ptapwork, C));
1554222ddf1SHong Zhang   } else SETERRQ(PetscObjectComm((PetscObject)C), PETSC_ERR_SUP, "Must call MatPtAPSymbolic_SeqDense_SeqDense() first");
1563ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
157abc3b08eSStefano Zampini }
158abc3b08eSStefano Zampini 
159d71ae5a4SJacob Faibussowitsch PetscErrorCode MatPtAPSymbolic_SeqDense_SeqDense(Mat A, Mat P, PetscReal fill, Mat C)
160d71ae5a4SJacob Faibussowitsch {
161abc3b08eSStefano Zampini   Mat_SeqDense *c;
16247d993e7Ssuyashtn   PetscBool     cisdense = PETSC_FALSE;
163abc3b08eSStefano Zampini 
164abc3b08eSStefano Zampini   PetscFunctionBegin;
1659566063dSJacob Faibussowitsch   PetscCall(MatSetSizes(C, P->cmap->n, P->cmap->n, P->cmap->N, P->cmap->N));
16647d993e7Ssuyashtn #if defined(PETSC_HAVE_CUDA)
1679566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompareAny((PetscObject)C, &cisdense, MATSEQDENSE, MATSEQDENSECUDA, ""));
16847d993e7Ssuyashtn #elif (PETSC_HAVE_HIP)
16947d993e7Ssuyashtn   PetscCall(PetscObjectTypeCompareAny((PetscObject)C, &cisdense, MATSEQDENSE, MATSEQDENSEHIP, ""));
17047d993e7Ssuyashtn #endif
17147d993e7Ssuyashtn 
1727a3c3d58SStefano Zampini   if (!cisdense) {
1737a3c3d58SStefano Zampini     PetscBool flg;
1747a3c3d58SStefano Zampini 
1759566063dSJacob Faibussowitsch     PetscCall(PetscObjectTypeCompare((PetscObject)P, ((PetscObject)A)->type_name, &flg));
1769566063dSJacob Faibussowitsch     PetscCall(MatSetType(C, flg ? ((PetscObject)A)->type_name : MATDENSE));
1777a3c3d58SStefano Zampini   }
1789566063dSJacob Faibussowitsch   PetscCall(MatSetUp(C));
1794222ddf1SHong Zhang   c = (Mat_SeqDense *)C->data;
1809566063dSJacob Faibussowitsch   PetscCall(MatCreate(PetscObjectComm((PetscObject)A), &c->ptapwork));
1819566063dSJacob Faibussowitsch   PetscCall(MatSetSizes(c->ptapwork, A->rmap->n, P->cmap->n, A->rmap->N, P->cmap->N));
1829566063dSJacob Faibussowitsch   PetscCall(MatSetType(c->ptapwork, ((PetscObject)C)->type_name));
1839566063dSJacob Faibussowitsch   PetscCall(MatSetUp(c->ptapwork));
1843ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
185abc3b08eSStefano Zampini }
186abc3b08eSStefano Zampini 
187d71ae5a4SJacob Faibussowitsch PETSC_INTERN PetscErrorCode MatConvert_SeqAIJ_SeqDense(Mat A, MatType newtype, MatReuse reuse, Mat *newmat)
188d71ae5a4SJacob Faibussowitsch {
189a13144ffSStefano Zampini   Mat              B = NULL;
190b49cda9fSStefano Zampini   Mat_SeqAIJ      *a = (Mat_SeqAIJ *)A->data;
191b49cda9fSStefano Zampini   Mat_SeqDense    *b;
192b49cda9fSStefano Zampini   PetscInt        *ai = a->i, *aj = a->j, m = A->rmap->N, n = A->cmap->N, i;
1932e5835c6SStefano Zampini   const MatScalar *av;
194a13144ffSStefano Zampini   PetscBool        isseqdense;
195b49cda9fSStefano Zampini 
196b49cda9fSStefano Zampini   PetscFunctionBegin;
197a13144ffSStefano Zampini   if (reuse == MAT_REUSE_MATRIX) {
1989566063dSJacob Faibussowitsch     PetscCall(PetscObjectTypeCompare((PetscObject)*newmat, MATSEQDENSE, &isseqdense));
19928b400f6SJacob Faibussowitsch     PetscCheck(isseqdense, PetscObjectComm((PetscObject)*newmat), PETSC_ERR_USER, "Cannot reuse matrix of type %s", ((PetscObject)(*newmat))->type_name);
200a13144ffSStefano Zampini   }
201a13144ffSStefano Zampini   if (reuse != MAT_REUSE_MATRIX) {
2029566063dSJacob Faibussowitsch     PetscCall(MatCreate(PetscObjectComm((PetscObject)A), &B));
2039566063dSJacob Faibussowitsch     PetscCall(MatSetSizes(B, m, n, m, n));
2049566063dSJacob Faibussowitsch     PetscCall(MatSetType(B, MATSEQDENSE));
2059566063dSJacob Faibussowitsch     PetscCall(MatSeqDenseSetPreallocation(B, NULL));
206b49cda9fSStefano Zampini     b = (Mat_SeqDense *)(B->data);
207a13144ffSStefano Zampini   } else {
208a13144ffSStefano Zampini     b = (Mat_SeqDense *)((*newmat)->data);
2099566063dSJacob Faibussowitsch     PetscCall(PetscArrayzero(b->v, m * n));
210a13144ffSStefano Zampini   }
2119566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJGetArrayRead(A, &av));
212b49cda9fSStefano Zampini   for (i = 0; i < m; i++) {
213b49cda9fSStefano Zampini     PetscInt j;
214b49cda9fSStefano Zampini     for (j = 0; j < ai[1] - ai[0]; j++) {
215b49cda9fSStefano Zampini       b->v[*aj * m + i] = *av;
216b49cda9fSStefano Zampini       aj++;
217b49cda9fSStefano Zampini       av++;
218b49cda9fSStefano Zampini     }
219b49cda9fSStefano Zampini     ai++;
220b49cda9fSStefano Zampini   }
2219566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJRestoreArrayRead(A, &av));
222b49cda9fSStefano Zampini 
223511c6705SHong Zhang   if (reuse == MAT_INPLACE_MATRIX) {
2249566063dSJacob Faibussowitsch     PetscCall(MatAssemblyBegin(B, MAT_FINAL_ASSEMBLY));
2259566063dSJacob Faibussowitsch     PetscCall(MatAssemblyEnd(B, MAT_FINAL_ASSEMBLY));
2269566063dSJacob Faibussowitsch     PetscCall(MatHeaderReplace(A, &B));
227b49cda9fSStefano Zampini   } else {
228a13144ffSStefano Zampini     if (B) *newmat = B;
2299566063dSJacob Faibussowitsch     PetscCall(MatAssemblyBegin(*newmat, MAT_FINAL_ASSEMBLY));
2309566063dSJacob Faibussowitsch     PetscCall(MatAssemblyEnd(*newmat, MAT_FINAL_ASSEMBLY));
231b49cda9fSStefano Zampini   }
2323ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
233b49cda9fSStefano Zampini }
234b49cda9fSStefano Zampini 
235d71ae5a4SJacob Faibussowitsch PETSC_INTERN PetscErrorCode MatConvert_SeqDense_SeqAIJ(Mat A, MatType newtype, MatReuse reuse, Mat *newmat)
236d71ae5a4SJacob Faibussowitsch {
2376d4ec7b0SPierre Jolivet   Mat           B = NULL;
2386a63e612SBarry Smith   Mat_SeqDense *a = (Mat_SeqDense *)A->data;
2399399e1b8SMatthew G. Knepley   PetscInt      i, j;
2409399e1b8SMatthew G. Knepley   PetscInt     *rows, *nnz;
2419399e1b8SMatthew G. Knepley   MatScalar    *aa = a->v, *vals;
2426a63e612SBarry Smith 
2436a63e612SBarry Smith   PetscFunctionBegin;
2449566063dSJacob Faibussowitsch   PetscCall(PetscCalloc3(A->rmap->n, &rows, A->rmap->n, &nnz, A->rmap->n, &vals));
2456d4ec7b0SPierre Jolivet   if (reuse != MAT_REUSE_MATRIX) {
2469566063dSJacob Faibussowitsch     PetscCall(MatCreate(PetscObjectComm((PetscObject)A), &B));
2479566063dSJacob Faibussowitsch     PetscCall(MatSetSizes(B, A->rmap->n, A->cmap->n, A->rmap->N, A->cmap->N));
2489566063dSJacob Faibussowitsch     PetscCall(MatSetType(B, MATSEQAIJ));
2499399e1b8SMatthew G. Knepley     for (j = 0; j < A->cmap->n; j++) {
2509371c9d4SSatish Balay       for (i = 0; i < A->rmap->n; i++)
2519371c9d4SSatish Balay         if (aa[i] != 0.0 || (i == j && A->cmap->n == A->rmap->n)) ++nnz[i];
2526a63e612SBarry Smith       aa += a->lda;
2536a63e612SBarry Smith     }
2549566063dSJacob Faibussowitsch     PetscCall(MatSeqAIJSetPreallocation(B, PETSC_DETERMINE, nnz));
2556d4ec7b0SPierre Jolivet   } else B = *newmat;
2569399e1b8SMatthew G. Knepley   aa = a->v;
2579399e1b8SMatthew G. Knepley   for (j = 0; j < A->cmap->n; j++) {
2589399e1b8SMatthew G. Knepley     PetscInt numRows = 0;
2599371c9d4SSatish Balay     for (i = 0; i < A->rmap->n; i++)
2609371c9d4SSatish Balay       if (aa[i] != 0.0 || (i == j && A->cmap->n == A->rmap->n)) {
2619371c9d4SSatish Balay         rows[numRows]   = i;
2629371c9d4SSatish Balay         vals[numRows++] = aa[i];
2639371c9d4SSatish Balay       }
2649566063dSJacob Faibussowitsch     PetscCall(MatSetValues(B, numRows, rows, 1, &j, vals, INSERT_VALUES));
2659399e1b8SMatthew G. Knepley     aa += a->lda;
2669399e1b8SMatthew G. Knepley   }
2679566063dSJacob Faibussowitsch   PetscCall(PetscFree3(rows, nnz, vals));
2689566063dSJacob Faibussowitsch   PetscCall(MatAssemblyBegin(B, MAT_FINAL_ASSEMBLY));
2699566063dSJacob Faibussowitsch   PetscCall(MatAssemblyEnd(B, MAT_FINAL_ASSEMBLY));
2706a63e612SBarry Smith 
271511c6705SHong Zhang   if (reuse == MAT_INPLACE_MATRIX) {
2729566063dSJacob Faibussowitsch     PetscCall(MatHeaderReplace(A, &B));
2736d4ec7b0SPierre Jolivet   } else if (reuse != MAT_REUSE_MATRIX) *newmat = B;
2743ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2756a63e612SBarry Smith }
2766a63e612SBarry Smith 
277d71ae5a4SJacob Faibussowitsch PetscErrorCode MatAXPY_SeqDense(Mat Y, PetscScalar alpha, Mat X, MatStructure str)
278d71ae5a4SJacob Faibussowitsch {
2791987afe7SBarry Smith   Mat_SeqDense      *x = (Mat_SeqDense *)X->data, *y = (Mat_SeqDense *)Y->data;
280ca15aa20SStefano Zampini   const PetscScalar *xv;
281ca15aa20SStefano Zampini   PetscScalar       *yv;
28223fff9afSBarry Smith   PetscBLASInt       N, m, ldax = 0, lday = 0, one = 1;
2833a40ed3dSBarry Smith 
2843a40ed3dSBarry Smith   PetscFunctionBegin;
2859566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArrayRead(X, &xv));
2869566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArray(Y, &yv));
2879566063dSJacob Faibussowitsch   PetscCall(PetscBLASIntCast(X->rmap->n * X->cmap->n, &N));
2889566063dSJacob Faibussowitsch   PetscCall(PetscBLASIntCast(X->rmap->n, &m));
2899566063dSJacob Faibussowitsch   PetscCall(PetscBLASIntCast(x->lda, &ldax));
2909566063dSJacob Faibussowitsch   PetscCall(PetscBLASIntCast(y->lda, &lday));
291a5ce6ee0Svictorle   if (ldax > m || lday > m) {
292ca15aa20SStefano Zampini     PetscInt j;
293ca15aa20SStefano Zampini 
29448a46eb9SPierre Jolivet     for (j = 0; j < X->cmap->n; j++) PetscCallBLAS("BLASaxpy", BLASaxpy_(&m, &alpha, xv + j * ldax, &one, yv + j * lday, &one));
295a5ce6ee0Svictorle   } else {
296792fecdfSBarry Smith     PetscCallBLAS("BLASaxpy", BLASaxpy_(&N, &alpha, xv, &one, yv, &one));
297a5ce6ee0Svictorle   }
2989566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArrayRead(X, &xv));
2999566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArray(Y, &yv));
3009566063dSJacob Faibussowitsch   PetscCall(PetscLogFlops(PetscMax(2.0 * N - 1, 0)));
3013ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3021987afe7SBarry Smith }
3031987afe7SBarry Smith 
304d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatGetInfo_SeqDense(Mat A, MatInfoType flag, MatInfo *info)
305d71ae5a4SJacob Faibussowitsch {
306ca15aa20SStefano Zampini   PetscLogDouble N = A->rmap->n * A->cmap->n;
3073a40ed3dSBarry Smith 
3083a40ed3dSBarry Smith   PetscFunctionBegin;
3094e220ebcSLois Curfman McInnes   info->block_size        = 1.0;
310ca15aa20SStefano Zampini   info->nz_allocated      = N;
311ca15aa20SStefano Zampini   info->nz_used           = N;
312ca15aa20SStefano Zampini   info->nz_unneeded       = 0;
313ca15aa20SStefano Zampini   info->assemblies        = A->num_ass;
3144e220ebcSLois Curfman McInnes   info->mallocs           = 0;
3154dfa11a4SJacob Faibussowitsch   info->memory            = 0; /* REVIEW ME */
3164e220ebcSLois Curfman McInnes   info->fill_ratio_given  = 0;
3174e220ebcSLois Curfman McInnes   info->fill_ratio_needed = 0;
3184e220ebcSLois Curfman McInnes   info->factor_mallocs    = 0;
3193ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
320289bc588SBarry Smith }
321289bc588SBarry Smith 
322d71ae5a4SJacob Faibussowitsch PetscErrorCode MatScale_SeqDense(Mat A, PetscScalar alpha)
323d71ae5a4SJacob Faibussowitsch {
324273d9f13SBarry Smith   Mat_SeqDense *a = (Mat_SeqDense *)A->data;
325ca15aa20SStefano Zampini   PetscScalar  *v;
32623fff9afSBarry Smith   PetscBLASInt  one = 1, j, nz, lda = 0;
32780cd9d93SLois Curfman McInnes 
3283a40ed3dSBarry Smith   PetscFunctionBegin;
3299566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArray(A, &v));
3309566063dSJacob Faibussowitsch   PetscCall(PetscBLASIntCast(a->lda, &lda));
331d0f46423SBarry Smith   if (lda > A->rmap->n) {
3329566063dSJacob Faibussowitsch     PetscCall(PetscBLASIntCast(A->rmap->n, &nz));
33348a46eb9SPierre Jolivet     for (j = 0; j < A->cmap->n; j++) PetscCallBLAS("BLASscal", BLASscal_(&nz, &alpha, v + j * lda, &one));
334a5ce6ee0Svictorle   } else {
3359566063dSJacob Faibussowitsch     PetscCall(PetscBLASIntCast(A->rmap->n * A->cmap->n, &nz));
336792fecdfSBarry Smith     PetscCallBLAS("BLASscal", BLASscal_(&nz, &alpha, v, &one));
337a5ce6ee0Svictorle   }
33804cbc005SJose E. Roman   PetscCall(PetscLogFlops(A->rmap->n * A->cmap->n));
3399566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArray(A, &v));
3403ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
34180cd9d93SLois Curfman McInnes }
34280cd9d93SLois Curfman McInnes 
343d71ae5a4SJacob Faibussowitsch PetscErrorCode MatShift_SeqDense(Mat A, PetscScalar alpha)
344d71ae5a4SJacob Faibussowitsch {
3452f605a99SJose E. Roman   Mat_SeqDense *a = (Mat_SeqDense *)A->data;
3462f605a99SJose E. Roman   PetscScalar  *v;
3472f605a99SJose E. Roman   PetscInt      j, k;
3482f605a99SJose E. Roman 
3492f605a99SJose E. Roman   PetscFunctionBegin;
3502f605a99SJose E. Roman   PetscCall(MatDenseGetArray(A, &v));
3512f605a99SJose E. Roman   k = PetscMin(A->rmap->n, A->cmap->n);
3522f605a99SJose E. Roman   for (j = 0; j < k; j++) v[j + j * a->lda] += alpha;
3532f605a99SJose E. Roman   PetscCall(PetscLogFlops(k));
3542f605a99SJose E. Roman   PetscCall(MatDenseRestoreArray(A, &v));
3553ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3562f605a99SJose E. Roman }
3572f605a99SJose E. Roman 
358d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatIsHermitian_SeqDense(Mat A, PetscReal rtol, PetscBool *fl)
359d71ae5a4SJacob Faibussowitsch {
3601cbb95d3SBarry Smith   Mat_SeqDense      *a = (Mat_SeqDense *)A->data;
361ca15aa20SStefano Zampini   PetscInt           i, j, m = A->rmap->n, N = a->lda;
362ca15aa20SStefano Zampini   const PetscScalar *v;
3631cbb95d3SBarry Smith 
3641cbb95d3SBarry Smith   PetscFunctionBegin;
3651cbb95d3SBarry Smith   *fl = PETSC_FALSE;
3663ba16761SJacob Faibussowitsch   if (A->rmap->n != A->cmap->n) PetscFunctionReturn(PETSC_SUCCESS);
3679566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArrayRead(A, &v));
3681cbb95d3SBarry Smith   for (i = 0; i < m; i++) {
369ca15aa20SStefano Zampini     for (j = i; j < m; j++) {
370ad540459SPierre Jolivet       if (PetscAbsScalar(v[i + j * N] - PetscConj(v[j + i * N])) > rtol) goto restore;
3711cbb95d3SBarry Smith     }
372637a0070SStefano Zampini   }
3731cbb95d3SBarry Smith   *fl = PETSC_TRUE;
374637a0070SStefano Zampini restore:
3759566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArrayRead(A, &v));
3763ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
377637a0070SStefano Zampini }
378637a0070SStefano Zampini 
379d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatIsSymmetric_SeqDense(Mat A, PetscReal rtol, PetscBool *fl)
380d71ae5a4SJacob Faibussowitsch {
381637a0070SStefano Zampini   Mat_SeqDense      *a = (Mat_SeqDense *)A->data;
382637a0070SStefano Zampini   PetscInt           i, j, m = A->rmap->n, N = a->lda;
383637a0070SStefano Zampini   const PetscScalar *v;
384637a0070SStefano Zampini 
385637a0070SStefano Zampini   PetscFunctionBegin;
386637a0070SStefano Zampini   *fl = PETSC_FALSE;
3873ba16761SJacob Faibussowitsch   if (A->rmap->n != A->cmap->n) PetscFunctionReturn(PETSC_SUCCESS);
3889566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArrayRead(A, &v));
389637a0070SStefano Zampini   for (i = 0; i < m; i++) {
390637a0070SStefano Zampini     for (j = i; j < m; j++) {
391ad540459SPierre Jolivet       if (PetscAbsScalar(v[i + j * N] - v[j + i * N]) > rtol) goto restore;
392637a0070SStefano Zampini     }
393637a0070SStefano Zampini   }
394637a0070SStefano Zampini   *fl = PETSC_TRUE;
395637a0070SStefano Zampini restore:
3969566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArrayRead(A, &v));
3973ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3981cbb95d3SBarry Smith }
3991cbb95d3SBarry Smith 
400d71ae5a4SJacob Faibussowitsch PetscErrorCode MatDuplicateNoCreate_SeqDense(Mat newi, Mat A, MatDuplicateOption cpvalues)
401d71ae5a4SJacob Faibussowitsch {
402ca15aa20SStefano Zampini   Mat_SeqDense *mat = (Mat_SeqDense *)A->data;
40323fc5dcaSStefano Zampini   PetscInt      lda = (PetscInt)mat->lda, j, m, nlda = lda;
40475f6d85dSStefano Zampini   PetscBool     isdensecpu;
405b24902e0SBarry Smith 
406b24902e0SBarry Smith   PetscFunctionBegin;
4079566063dSJacob Faibussowitsch   PetscCall(PetscLayoutReference(A->rmap, &newi->rmap));
4089566063dSJacob Faibussowitsch   PetscCall(PetscLayoutReference(A->cmap, &newi->cmap));
40923fc5dcaSStefano Zampini   if (cpvalues == MAT_SHARE_NONZERO_PATTERN) { /* propagate LDA */
4109566063dSJacob Faibussowitsch     PetscCall(MatDenseSetLDA(newi, lda));
41123fc5dcaSStefano Zampini   }
4129566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)newi, MATSEQDENSE, &isdensecpu));
4139566063dSJacob Faibussowitsch   if (isdensecpu) PetscCall(MatSeqDenseSetPreallocation(newi, NULL));
414b24902e0SBarry Smith   if (cpvalues == MAT_COPY_VALUES) {
415ca15aa20SStefano Zampini     const PetscScalar *av;
416ca15aa20SStefano Zampini     PetscScalar       *v;
417ca15aa20SStefano Zampini 
4189566063dSJacob Faibussowitsch     PetscCall(MatDenseGetArrayRead(A, &av));
4199566063dSJacob Faibussowitsch     PetscCall(MatDenseGetArrayWrite(newi, &v));
4209566063dSJacob Faibussowitsch     PetscCall(MatDenseGetLDA(newi, &nlda));
421d0f46423SBarry Smith     m = A->rmap->n;
42223fc5dcaSStefano Zampini     if (lda > m || nlda > m) {
42348a46eb9SPierre Jolivet       for (j = 0; j < A->cmap->n; j++) PetscCall(PetscArraycpy(v + j * nlda, av + j * lda, m));
424b24902e0SBarry Smith     } else {
4259566063dSJacob Faibussowitsch       PetscCall(PetscArraycpy(v, av, A->rmap->n * A->cmap->n));
426b24902e0SBarry Smith     }
4279566063dSJacob Faibussowitsch     PetscCall(MatDenseRestoreArrayWrite(newi, &v));
4289566063dSJacob Faibussowitsch     PetscCall(MatDenseRestoreArrayRead(A, &av));
429b24902e0SBarry Smith   }
4303ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
431b24902e0SBarry Smith }
432b24902e0SBarry Smith 
433d71ae5a4SJacob Faibussowitsch PetscErrorCode MatDuplicate_SeqDense(Mat A, MatDuplicateOption cpvalues, Mat *newmat)
434d71ae5a4SJacob Faibussowitsch {
4353a40ed3dSBarry Smith   PetscFunctionBegin;
4369566063dSJacob Faibussowitsch   PetscCall(MatCreate(PetscObjectComm((PetscObject)A), newmat));
4379566063dSJacob Faibussowitsch   PetscCall(MatSetSizes(*newmat, A->rmap->n, A->cmap->n, A->rmap->n, A->cmap->n));
4389566063dSJacob Faibussowitsch   PetscCall(MatSetType(*newmat, ((PetscObject)A)->type_name));
4399566063dSJacob Faibussowitsch   PetscCall(MatDuplicateNoCreate_SeqDense(*newmat, A, cpvalues));
4403ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
441b24902e0SBarry Smith }
442b24902e0SBarry Smith 
443d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatSolve_SeqDense_Internal_LU(Mat A, PetscScalar *x, PetscBLASInt ldx, PetscBLASInt m, PetscBLASInt nrhs, PetscBLASInt k, PetscBool T)
444d71ae5a4SJacob Faibussowitsch {
445c0bbcb79SLois Curfman McInnes   Mat_SeqDense *mat = (Mat_SeqDense *)A->data;
4464396437dSToby Isaac   PetscBLASInt  info;
44767e560aaSBarry Smith 
4483a40ed3dSBarry Smith   PetscFunctionBegin;
4499566063dSJacob Faibussowitsch   PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF));
450792fecdfSBarry Smith   PetscCallBLAS("LAPACKgetrs", LAPACKgetrs_(T ? "T" : "N", &m, &nrhs, mat->v, &mat->lda, mat->pivots, x, &m, &info));
4519566063dSJacob Faibussowitsch   PetscCall(PetscFPTrapPop());
45205fcb23eSStefano Zampini   PetscCheck(!info, PETSC_COMM_SELF, PETSC_ERR_LIB, "GETRS - Bad solve %d", (int)info);
4539566063dSJacob Faibussowitsch   PetscCall(PetscLogFlops(nrhs * (2.0 * m * m - m)));
4543ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4554396437dSToby Isaac }
4564396437dSToby Isaac 
4574396437dSToby Isaac static PetscErrorCode MatConjugate_SeqDense(Mat);
4584396437dSToby Isaac 
459d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatSolve_SeqDense_Internal_Cholesky(Mat A, PetscScalar *x, PetscBLASInt ldx, PetscBLASInt m, PetscBLASInt nrhs, PetscBLASInt k, PetscBool T)
460d71ae5a4SJacob Faibussowitsch {
4614396437dSToby Isaac   Mat_SeqDense *mat = (Mat_SeqDense *)A->data;
4624396437dSToby Isaac   PetscBLASInt  info;
4634396437dSToby Isaac 
4644396437dSToby Isaac   PetscFunctionBegin;
465b94d7dedSBarry Smith   if (A->spd == PETSC_BOOL3_TRUE) {
4669566063dSJacob Faibussowitsch     if (PetscDefined(USE_COMPLEX) && T) PetscCall(MatConjugate_SeqDense(A));
4679566063dSJacob Faibussowitsch     PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF));
468792fecdfSBarry Smith     PetscCallBLAS("LAPACKpotrs", LAPACKpotrs_("L", &m, &nrhs, mat->v, &mat->lda, x, &m, &info));
4699566063dSJacob Faibussowitsch     PetscCall(PetscFPTrapPop());
47005fcb23eSStefano Zampini     PetscCheck(!info, PETSC_COMM_SELF, PETSC_ERR_LIB, "POTRS Bad solve %d", (int)info);
4719566063dSJacob Faibussowitsch     if (PetscDefined(USE_COMPLEX) && T) PetscCall(MatConjugate_SeqDense(A));
472a49dc2a2SStefano Zampini #if defined(PETSC_USE_COMPLEX)
473b94d7dedSBarry Smith   } else if (A->hermitian == PETSC_BOOL3_TRUE) {
4749566063dSJacob Faibussowitsch     if (T) PetscCall(MatConjugate_SeqDense(A));
4759566063dSJacob Faibussowitsch     PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF));
476792fecdfSBarry Smith     PetscCallBLAS("LAPACKhetrs", LAPACKhetrs_("L", &m, &nrhs, mat->v, &mat->lda, mat->pivots, x, &m, &info));
4779566063dSJacob Faibussowitsch     PetscCall(PetscFPTrapPop());
47805fcb23eSStefano Zampini     PetscCheck(!info, PETSC_COMM_SELF, PETSC_ERR_LIB, "HETRS Bad solve %d", (int)info);
4799566063dSJacob Faibussowitsch     if (T) PetscCall(MatConjugate_SeqDense(A));
480a49dc2a2SStefano Zampini #endif
481a49dc2a2SStefano Zampini   } else { /* symmetric case */
4829566063dSJacob Faibussowitsch     PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF));
483792fecdfSBarry Smith     PetscCallBLAS("LAPACKsytrs", LAPACKsytrs_("L", &m, &nrhs, mat->v, &mat->lda, mat->pivots, x, &m, &info));
4849566063dSJacob Faibussowitsch     PetscCall(PetscFPTrapPop());
48505fcb23eSStefano Zampini     PetscCheck(!info, PETSC_COMM_SELF, PETSC_ERR_LIB, "SYTRS Bad solve %d", (int)info);
486a49dc2a2SStefano Zampini   }
4879566063dSJacob Faibussowitsch   PetscCall(PetscLogFlops(nrhs * (2.0 * m * m - m)));
4883ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4894396437dSToby Isaac }
49085e2c93fSHong Zhang 
491d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatSolve_SeqDense_Internal_QR(Mat A, PetscScalar *x, PetscBLASInt ldx, PetscBLASInt m, PetscBLASInt nrhs, PetscBLASInt k)
492d71ae5a4SJacob Faibussowitsch {
4934396437dSToby Isaac   Mat_SeqDense *mat = (Mat_SeqDense *)A->data;
4944396437dSToby Isaac   PetscBLASInt  info;
4954396437dSToby Isaac   char          trans;
4964396437dSToby Isaac 
4974396437dSToby Isaac   PetscFunctionBegin;
4984905a7bcSToby Isaac   if (PetscDefined(USE_COMPLEX)) {
4994905a7bcSToby Isaac     trans = 'C';
5004905a7bcSToby Isaac   } else {
5014905a7bcSToby Isaac     trans = 'T';
5024905a7bcSToby Isaac   }
5039566063dSJacob Faibussowitsch   PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF));
50405fcb23eSStefano Zampini   { /* lwork depends on the number of right-hand sides */
50505fcb23eSStefano Zampini     PetscBLASInt nlfwork, lfwork = -1;
50605fcb23eSStefano Zampini     PetscScalar  fwork;
50705fcb23eSStefano Zampini 
508792fecdfSBarry Smith     PetscCallBLAS("LAPACKormqr", LAPACKormqr_("L", &trans, &m, &nrhs, &mat->rank, mat->v, &mat->lda, mat->tau, x, &ldx, &fwork, &lfwork, &info));
50905fcb23eSStefano Zampini     nlfwork = (PetscBLASInt)PetscRealPart(fwork);
51005fcb23eSStefano Zampini     if (nlfwork > mat->lfwork) {
51105fcb23eSStefano Zampini       mat->lfwork = nlfwork;
51205fcb23eSStefano Zampini       PetscCall(PetscFree(mat->fwork));
51305fcb23eSStefano Zampini       PetscCall(PetscMalloc1(mat->lfwork, &mat->fwork));
51405fcb23eSStefano Zampini     }
51505fcb23eSStefano Zampini   }
516792fecdfSBarry Smith   PetscCallBLAS("LAPACKormqr", LAPACKormqr_("L", &trans, &m, &nrhs, &mat->rank, mat->v, &mat->lda, mat->tau, x, &ldx, mat->fwork, &mat->lfwork, &info));
5179566063dSJacob Faibussowitsch   PetscCall(PetscFPTrapPop());
51805fcb23eSStefano Zampini   PetscCheck(!info, PETSC_COMM_SELF, PETSC_ERR_LIB, "ORMQR - Bad orthogonal transform %d", (int)info);
5199566063dSJacob Faibussowitsch   PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF));
520792fecdfSBarry Smith   PetscCallBLAS("LAPACKtrtrs", LAPACKtrtrs_("U", "N", "N", &mat->rank, &nrhs, mat->v, &mat->lda, x, &ldx, &info));
5219566063dSJacob Faibussowitsch   PetscCall(PetscFPTrapPop());
52205fcb23eSStefano Zampini   PetscCheck(!info, PETSC_COMM_SELF, PETSC_ERR_LIB, "TRTRS - Bad triangular solve %d", (int)info);
5234905a7bcSToby Isaac   for (PetscInt j = 0; j < nrhs; j++) {
524ad540459SPierre Jolivet     for (PetscInt i = mat->rank; i < k; i++) x[j * ldx + i] = 0.;
5254905a7bcSToby Isaac   }
5269566063dSJacob Faibussowitsch   PetscCall(PetscLogFlops(nrhs * (4.0 * m * mat->rank - PetscSqr(mat->rank))));
5273ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5284905a7bcSToby Isaac }
5294905a7bcSToby Isaac 
530d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatSolveTranspose_SeqDense_Internal_QR(Mat A, PetscScalar *x, PetscBLASInt ldx, PetscBLASInt m, PetscBLASInt nrhs, PetscBLASInt k)
531d71ae5a4SJacob Faibussowitsch {
5324396437dSToby Isaac   Mat_SeqDense *mat = (Mat_SeqDense *)A->data;
5334396437dSToby Isaac   PetscBLASInt  info;
5344396437dSToby Isaac 
5354396437dSToby Isaac   PetscFunctionBegin;
5364396437dSToby Isaac   if (A->rmap->n == A->cmap->n && mat->rank == A->rmap->n) {
5379566063dSJacob Faibussowitsch     PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF));
538792fecdfSBarry Smith     PetscCallBLAS("LAPACKtrtrs", LAPACKtrtrs_("U", "T", "N", &m, &nrhs, mat->v, &mat->lda, x, &ldx, &info));
5399566063dSJacob Faibussowitsch     PetscCall(PetscFPTrapPop());
54005fcb23eSStefano Zampini     PetscCheck(!info, PETSC_COMM_SELF, PETSC_ERR_LIB, "TRTRS - Bad triangular solve %d", (int)info);
5419566063dSJacob Faibussowitsch     if (PetscDefined(USE_COMPLEX)) PetscCall(MatConjugate_SeqDense(A));
54205fcb23eSStefano Zampini     { /* lwork depends on the number of right-hand sides */
54305fcb23eSStefano Zampini       PetscBLASInt nlfwork, lfwork = -1;
54405fcb23eSStefano Zampini       PetscScalar  fwork;
54505fcb23eSStefano Zampini 
546792fecdfSBarry Smith       PetscCallBLAS("LAPACKormqr", LAPACKormqr_("L", "N", &m, &nrhs, &mat->rank, mat->v, &mat->lda, mat->tau, x, &ldx, &fwork, &lfwork, &info));
54705fcb23eSStefano Zampini       nlfwork = (PetscBLASInt)PetscRealPart(fwork);
54805fcb23eSStefano Zampini       if (nlfwork > mat->lfwork) {
54905fcb23eSStefano Zampini         mat->lfwork = nlfwork;
55005fcb23eSStefano Zampini         PetscCall(PetscFree(mat->fwork));
55105fcb23eSStefano Zampini         PetscCall(PetscMalloc1(mat->lfwork, &mat->fwork));
55205fcb23eSStefano Zampini       }
55305fcb23eSStefano Zampini     }
5549566063dSJacob Faibussowitsch     PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF));
555792fecdfSBarry Smith     PetscCallBLAS("LAPACKormqr", LAPACKormqr_("L", "N", &m, &nrhs, &mat->rank, mat->v, &mat->lda, mat->tau, x, &ldx, mat->fwork, &mat->lfwork, &info));
5569566063dSJacob Faibussowitsch     PetscCall(PetscFPTrapPop());
55705fcb23eSStefano Zampini     PetscCheck(!info, PETSC_COMM_SELF, PETSC_ERR_LIB, "ORMQR - Bad orthogonal transform %d", (int)info);
5589566063dSJacob Faibussowitsch     if (PetscDefined(USE_COMPLEX)) PetscCall(MatConjugate_SeqDense(A));
5594396437dSToby Isaac   } else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "QR factored matrix cannot be used for transpose solve");
5609566063dSJacob Faibussowitsch   PetscCall(PetscLogFlops(nrhs * (4.0 * m * mat->rank - PetscSqr(mat->rank))));
5613ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5624396437dSToby Isaac }
5634396437dSToby Isaac 
564d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatSolve_SeqDense_SetUp(Mat A, Vec xx, Vec yy, PetscScalar **_y, PetscBLASInt *_m, PetscBLASInt *_k)
565d71ae5a4SJacob Faibussowitsch {
5664396437dSToby Isaac   Mat_SeqDense *mat = (Mat_SeqDense *)A->data;
5674905a7bcSToby Isaac   PetscScalar  *y;
5684905a7bcSToby Isaac   PetscBLASInt  m = 0, k = 0;
5694905a7bcSToby Isaac 
5704905a7bcSToby Isaac   PetscFunctionBegin;
5719566063dSJacob Faibussowitsch   PetscCall(PetscBLASIntCast(A->rmap->n, &m));
5729566063dSJacob Faibussowitsch   PetscCall(PetscBLASIntCast(A->cmap->n, &k));
5734905a7bcSToby Isaac   if (k < m) {
5749566063dSJacob Faibussowitsch     PetscCall(VecCopy(xx, mat->qrrhs));
5759566063dSJacob Faibussowitsch     PetscCall(VecGetArray(mat->qrrhs, &y));
5764905a7bcSToby Isaac   } else {
5779566063dSJacob Faibussowitsch     PetscCall(VecCopy(xx, yy));
5789566063dSJacob Faibussowitsch     PetscCall(VecGetArray(yy, &y));
5794905a7bcSToby Isaac   }
5804396437dSToby Isaac   *_y = y;
5814396437dSToby Isaac   *_k = k;
5824396437dSToby Isaac   *_m = m;
5833ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5844396437dSToby Isaac }
5854396437dSToby Isaac 
586d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatSolve_SeqDense_TearDown(Mat A, Vec xx, Vec yy, PetscScalar **_y, PetscBLASInt *_m, PetscBLASInt *_k)
587d71ae5a4SJacob Faibussowitsch {
5884396437dSToby Isaac   Mat_SeqDense *mat = (Mat_SeqDense *)A->data;
58942e9364cSSatish Balay   PetscScalar  *y   = NULL;
5904396437dSToby Isaac   PetscBLASInt  m, k;
5914396437dSToby Isaac 
5924396437dSToby Isaac   PetscFunctionBegin;
5934396437dSToby Isaac   y   = *_y;
5944396437dSToby Isaac   *_y = NULL;
5954396437dSToby Isaac   k   = *_k;
5964396437dSToby Isaac   m   = *_m;
5974905a7bcSToby Isaac   if (k < m) {
5984905a7bcSToby Isaac     PetscScalar *yv;
5999566063dSJacob Faibussowitsch     PetscCall(VecGetArray(yy, &yv));
6009566063dSJacob Faibussowitsch     PetscCall(PetscArraycpy(yv, y, k));
6019566063dSJacob Faibussowitsch     PetscCall(VecRestoreArray(yy, &yv));
6029566063dSJacob Faibussowitsch     PetscCall(VecRestoreArray(mat->qrrhs, &y));
6034905a7bcSToby Isaac   } else {
6049566063dSJacob Faibussowitsch     PetscCall(VecRestoreArray(yy, &y));
6054905a7bcSToby Isaac   }
6063ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
6074905a7bcSToby Isaac }
6084905a7bcSToby Isaac 
609d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatSolve_SeqDense_LU(Mat A, Vec xx, Vec yy)
610d71ae5a4SJacob Faibussowitsch {
61142e9364cSSatish Balay   PetscScalar *y = NULL;
61242e9364cSSatish Balay   PetscBLASInt m = 0, k = 0;
6134396437dSToby Isaac 
6144396437dSToby Isaac   PetscFunctionBegin;
6159566063dSJacob Faibussowitsch   PetscCall(MatSolve_SeqDense_SetUp(A, xx, yy, &y, &m, &k));
6169566063dSJacob Faibussowitsch   PetscCall(MatSolve_SeqDense_Internal_LU(A, y, m, m, 1, k, PETSC_FALSE));
6179566063dSJacob Faibussowitsch   PetscCall(MatSolve_SeqDense_TearDown(A, xx, yy, &y, &m, &k));
6183ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
6194396437dSToby Isaac }
6204396437dSToby Isaac 
621d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatSolveTranspose_SeqDense_LU(Mat A, Vec xx, Vec yy)
622d71ae5a4SJacob Faibussowitsch {
62342e9364cSSatish Balay   PetscScalar *y = NULL;
62442e9364cSSatish Balay   PetscBLASInt m = 0, k = 0;
6254396437dSToby Isaac 
6264396437dSToby Isaac   PetscFunctionBegin;
6279566063dSJacob Faibussowitsch   PetscCall(MatSolve_SeqDense_SetUp(A, xx, yy, &y, &m, &k));
6289566063dSJacob Faibussowitsch   PetscCall(MatSolve_SeqDense_Internal_LU(A, y, m, m, 1, k, PETSC_TRUE));
6299566063dSJacob Faibussowitsch   PetscCall(MatSolve_SeqDense_TearDown(A, xx, yy, &y, &m, &k));
6303ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
6314396437dSToby Isaac }
6324396437dSToby Isaac 
633d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatSolve_SeqDense_Cholesky(Mat A, Vec xx, Vec yy)
634d71ae5a4SJacob Faibussowitsch {
635e54beecaSStefano Zampini   PetscScalar *y = NULL;
636e54beecaSStefano Zampini   PetscBLASInt m = 0, k = 0;
6374396437dSToby Isaac 
6384396437dSToby Isaac   PetscFunctionBegin;
6399566063dSJacob Faibussowitsch   PetscCall(MatSolve_SeqDense_SetUp(A, xx, yy, &y, &m, &k));
6409566063dSJacob Faibussowitsch   PetscCall(MatSolve_SeqDense_Internal_Cholesky(A, y, m, m, 1, k, PETSC_FALSE));
6419566063dSJacob Faibussowitsch   PetscCall(MatSolve_SeqDense_TearDown(A, xx, yy, &y, &m, &k));
6423ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
6434396437dSToby Isaac }
6444396437dSToby Isaac 
645d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatSolveTranspose_SeqDense_Cholesky(Mat A, Vec xx, Vec yy)
646d71ae5a4SJacob Faibussowitsch {
647e54beecaSStefano Zampini   PetscScalar *y = NULL;
648e54beecaSStefano Zampini   PetscBLASInt m = 0, k = 0;
6494396437dSToby Isaac 
6504396437dSToby Isaac   PetscFunctionBegin;
6519566063dSJacob Faibussowitsch   PetscCall(MatSolve_SeqDense_SetUp(A, xx, yy, &y, &m, &k));
6529566063dSJacob Faibussowitsch   PetscCall(MatSolve_SeqDense_Internal_Cholesky(A, y, m, m, 1, k, PETSC_TRUE));
6539566063dSJacob Faibussowitsch   PetscCall(MatSolve_SeqDense_TearDown(A, xx, yy, &y, &m, &k));
6543ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
6554396437dSToby Isaac }
6564396437dSToby Isaac 
657d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatSolve_SeqDense_QR(Mat A, Vec xx, Vec yy)
658d71ae5a4SJacob Faibussowitsch {
659e54beecaSStefano Zampini   PetscScalar *y = NULL;
660e54beecaSStefano Zampini   PetscBLASInt m = 0, k = 0;
6614396437dSToby Isaac 
6624396437dSToby Isaac   PetscFunctionBegin;
6639566063dSJacob Faibussowitsch   PetscCall(MatSolve_SeqDense_SetUp(A, xx, yy, &y, &m, &k));
6649566063dSJacob Faibussowitsch   PetscCall(MatSolve_SeqDense_Internal_QR(A, y, PetscMax(m, k), m, 1, k));
6659566063dSJacob Faibussowitsch   PetscCall(MatSolve_SeqDense_TearDown(A, xx, yy, &y, &m, &k));
6663ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
6674396437dSToby Isaac }
6684396437dSToby Isaac 
669d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatSolveTranspose_SeqDense_QR(Mat A, Vec xx, Vec yy)
670d71ae5a4SJacob Faibussowitsch {
67142e9364cSSatish Balay   PetscScalar *y = NULL;
67242e9364cSSatish Balay   PetscBLASInt m = 0, k = 0;
6734396437dSToby Isaac 
6744396437dSToby Isaac   PetscFunctionBegin;
6759566063dSJacob Faibussowitsch   PetscCall(MatSolve_SeqDense_SetUp(A, xx, yy, &y, &m, &k));
6769566063dSJacob Faibussowitsch   PetscCall(MatSolveTranspose_SeqDense_Internal_QR(A, y, PetscMax(m, k), m, 1, k));
6779566063dSJacob Faibussowitsch   PetscCall(MatSolve_SeqDense_TearDown(A, xx, yy, &y, &m, &k));
6783ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
6794396437dSToby Isaac }
6804396437dSToby Isaac 
681d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatMatSolve_SeqDense_SetUp(Mat A, Mat B, Mat X, PetscScalar **_y, PetscBLASInt *_ldy, PetscBLASInt *_m, PetscBLASInt *_nrhs, PetscBLASInt *_k)
682d71ae5a4SJacob Faibussowitsch {
6834905a7bcSToby Isaac   const PetscScalar *b;
6844396437dSToby Isaac   PetscScalar       *y;
685bf5a80bcSToby Isaac   PetscInt           n, _ldb, _ldx;
686bf5a80bcSToby Isaac   PetscBLASInt       nrhs = 0, m = 0, k = 0, ldb = 0, ldx = 0, ldy = 0;
6874905a7bcSToby Isaac 
6884905a7bcSToby Isaac   PetscFunctionBegin;
6899371c9d4SSatish Balay   *_ldy  = 0;
6909371c9d4SSatish Balay   *_m    = 0;
6919371c9d4SSatish Balay   *_nrhs = 0;
6929371c9d4SSatish Balay   *_k    = 0;
6939371c9d4SSatish Balay   *_y    = NULL;
6949566063dSJacob Faibussowitsch   PetscCall(PetscBLASIntCast(A->rmap->n, &m));
6959566063dSJacob Faibussowitsch   PetscCall(PetscBLASIntCast(A->cmap->n, &k));
6969566063dSJacob Faibussowitsch   PetscCall(MatGetSize(B, NULL, &n));
6979566063dSJacob Faibussowitsch   PetscCall(PetscBLASIntCast(n, &nrhs));
6989566063dSJacob Faibussowitsch   PetscCall(MatDenseGetLDA(B, &_ldb));
6999566063dSJacob Faibussowitsch   PetscCall(PetscBLASIntCast(_ldb, &ldb));
7009566063dSJacob Faibussowitsch   PetscCall(MatDenseGetLDA(X, &_ldx));
7019566063dSJacob Faibussowitsch   PetscCall(PetscBLASIntCast(_ldx, &ldx));
702bf5a80bcSToby Isaac   if (ldx < m) {
7039566063dSJacob Faibussowitsch     PetscCall(MatDenseGetArrayRead(B, &b));
7049566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(nrhs * m, &y));
705bf5a80bcSToby Isaac     if (ldb == m) {
7069566063dSJacob Faibussowitsch       PetscCall(PetscArraycpy(y, b, ldb * nrhs));
7074905a7bcSToby Isaac     } else {
70848a46eb9SPierre Jolivet       for (PetscInt j = 0; j < nrhs; j++) PetscCall(PetscArraycpy(&y[j * m], &b[j * ldb], m));
7094905a7bcSToby Isaac     }
710bf5a80bcSToby Isaac     ldy = m;
7119566063dSJacob Faibussowitsch     PetscCall(MatDenseRestoreArrayRead(B, &b));
7124905a7bcSToby Isaac   } else {
713bf5a80bcSToby Isaac     if (ldb == ldx) {
7149566063dSJacob Faibussowitsch       PetscCall(MatCopy(B, X, SAME_NONZERO_PATTERN));
7159566063dSJacob Faibussowitsch       PetscCall(MatDenseGetArray(X, &y));
7164905a7bcSToby Isaac     } else {
7179566063dSJacob Faibussowitsch       PetscCall(MatDenseGetArray(X, &y));
7189566063dSJacob Faibussowitsch       PetscCall(MatDenseGetArrayRead(B, &b));
71948a46eb9SPierre Jolivet       for (PetscInt j = 0; j < nrhs; j++) PetscCall(PetscArraycpy(&y[j * ldx], &b[j * ldb], m));
7209566063dSJacob Faibussowitsch       PetscCall(MatDenseRestoreArrayRead(B, &b));
7214905a7bcSToby Isaac     }
722bf5a80bcSToby Isaac     ldy = ldx;
7234905a7bcSToby Isaac   }
7244396437dSToby Isaac   *_y    = y;
725bf5a80bcSToby Isaac   *_ldy  = ldy;
7264396437dSToby Isaac   *_k    = k;
7274396437dSToby Isaac   *_m    = m;
7284396437dSToby Isaac   *_nrhs = nrhs;
7293ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
7304396437dSToby Isaac }
7314396437dSToby Isaac 
732d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatMatSolve_SeqDense_TearDown(Mat A, Mat B, Mat X, PetscScalar **_y, PetscBLASInt *_ldy, PetscBLASInt *_m, PetscBLASInt *_nrhs, PetscBLASInt *_k)
733d71ae5a4SJacob Faibussowitsch {
7344396437dSToby Isaac   PetscScalar *y;
735bf5a80bcSToby Isaac   PetscInt     _ldx;
736bf5a80bcSToby Isaac   PetscBLASInt k, ldy, nrhs, ldx = 0;
7374396437dSToby Isaac 
7384396437dSToby Isaac   PetscFunctionBegin;
7394396437dSToby Isaac   y    = *_y;
7404396437dSToby Isaac   *_y  = NULL;
7414396437dSToby Isaac   k    = *_k;
742bf5a80bcSToby Isaac   ldy  = *_ldy;
7434396437dSToby Isaac   nrhs = *_nrhs;
7449566063dSJacob Faibussowitsch   PetscCall(MatDenseGetLDA(X, &_ldx));
7459566063dSJacob Faibussowitsch   PetscCall(PetscBLASIntCast(_ldx, &ldx));
746bf5a80bcSToby Isaac   if (ldx != ldy) {
7474905a7bcSToby Isaac     PetscScalar *xv;
7489566063dSJacob Faibussowitsch     PetscCall(MatDenseGetArray(X, &xv));
74948a46eb9SPierre Jolivet     for (PetscInt j = 0; j < nrhs; j++) PetscCall(PetscArraycpy(&xv[j * ldx], &y[j * ldy], k));
7509566063dSJacob Faibussowitsch     PetscCall(MatDenseRestoreArray(X, &xv));
7519566063dSJacob Faibussowitsch     PetscCall(PetscFree(y));
7524905a7bcSToby Isaac   } else {
7539566063dSJacob Faibussowitsch     PetscCall(MatDenseRestoreArray(X, &y));
7544905a7bcSToby Isaac   }
7553ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
75685e2c93fSHong Zhang }
75785e2c93fSHong Zhang 
758d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatMatSolve_SeqDense_LU(Mat A, Mat B, Mat X)
759d71ae5a4SJacob Faibussowitsch {
7604396437dSToby Isaac   PetscScalar *y;
761bf5a80bcSToby Isaac   PetscBLASInt m, k, ldy, nrhs;
7624396437dSToby Isaac 
7634396437dSToby Isaac   PetscFunctionBegin;
7649566063dSJacob Faibussowitsch   PetscCall(MatMatSolve_SeqDense_SetUp(A, B, X, &y, &ldy, &m, &nrhs, &k));
7659566063dSJacob Faibussowitsch   PetscCall(MatSolve_SeqDense_Internal_LU(A, y, ldy, m, nrhs, k, PETSC_FALSE));
7669566063dSJacob Faibussowitsch   PetscCall(MatMatSolve_SeqDense_TearDown(A, B, X, &y, &ldy, &m, &nrhs, &k));
7673ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
7684396437dSToby Isaac }
7694396437dSToby Isaac 
770d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatMatSolveTranspose_SeqDense_LU(Mat A, Mat B, Mat X)
771d71ae5a4SJacob Faibussowitsch {
7724396437dSToby Isaac   PetscScalar *y;
773bf5a80bcSToby Isaac   PetscBLASInt m, k, ldy, nrhs;
7744396437dSToby Isaac 
7754396437dSToby Isaac   PetscFunctionBegin;
7769566063dSJacob Faibussowitsch   PetscCall(MatMatSolve_SeqDense_SetUp(A, B, X, &y, &ldy, &m, &nrhs, &k));
7779566063dSJacob Faibussowitsch   PetscCall(MatSolve_SeqDense_Internal_LU(A, y, ldy, m, nrhs, k, PETSC_TRUE));
7789566063dSJacob Faibussowitsch   PetscCall(MatMatSolve_SeqDense_TearDown(A, B, X, &y, &ldy, &m, &nrhs, &k));
7793ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
7804396437dSToby Isaac }
7814396437dSToby Isaac 
782d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatMatSolve_SeqDense_Cholesky(Mat A, Mat B, Mat X)
783d71ae5a4SJacob Faibussowitsch {
7844396437dSToby Isaac   PetscScalar *y;
785bf5a80bcSToby Isaac   PetscBLASInt m, k, ldy, nrhs;
7864396437dSToby Isaac 
7874396437dSToby Isaac   PetscFunctionBegin;
7889566063dSJacob Faibussowitsch   PetscCall(MatMatSolve_SeqDense_SetUp(A, B, X, &y, &ldy, &m, &nrhs, &k));
7899566063dSJacob Faibussowitsch   PetscCall(MatSolve_SeqDense_Internal_Cholesky(A, y, ldy, m, nrhs, k, PETSC_FALSE));
7909566063dSJacob Faibussowitsch   PetscCall(MatMatSolve_SeqDense_TearDown(A, B, X, &y, &ldy, &m, &nrhs, &k));
7913ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
7924396437dSToby Isaac }
7934396437dSToby Isaac 
794d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatMatSolveTranspose_SeqDense_Cholesky(Mat A, Mat B, Mat X)
795d71ae5a4SJacob Faibussowitsch {
7964396437dSToby Isaac   PetscScalar *y;
797bf5a80bcSToby Isaac   PetscBLASInt m, k, ldy, nrhs;
7984396437dSToby Isaac 
7994396437dSToby Isaac   PetscFunctionBegin;
8009566063dSJacob Faibussowitsch   PetscCall(MatMatSolve_SeqDense_SetUp(A, B, X, &y, &ldy, &m, &nrhs, &k));
8019566063dSJacob Faibussowitsch   PetscCall(MatSolve_SeqDense_Internal_Cholesky(A, y, ldy, m, nrhs, k, PETSC_TRUE));
8029566063dSJacob Faibussowitsch   PetscCall(MatMatSolve_SeqDense_TearDown(A, B, X, &y, &ldy, &m, &nrhs, &k));
8033ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
8044396437dSToby Isaac }
8054396437dSToby Isaac 
806d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatMatSolve_SeqDense_QR(Mat A, Mat B, Mat X)
807d71ae5a4SJacob Faibussowitsch {
8084396437dSToby Isaac   PetscScalar *y;
809bf5a80bcSToby Isaac   PetscBLASInt m, k, ldy, nrhs;
8104396437dSToby Isaac 
8114396437dSToby Isaac   PetscFunctionBegin;
8129566063dSJacob Faibussowitsch   PetscCall(MatMatSolve_SeqDense_SetUp(A, B, X, &y, &ldy, &m, &nrhs, &k));
8139566063dSJacob Faibussowitsch   PetscCall(MatSolve_SeqDense_Internal_QR(A, y, ldy, m, nrhs, k));
8149566063dSJacob Faibussowitsch   PetscCall(MatMatSolve_SeqDense_TearDown(A, B, X, &y, &ldy, &m, &nrhs, &k));
8153ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
8164396437dSToby Isaac }
8174396437dSToby Isaac 
818d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatMatSolveTranspose_SeqDense_QR(Mat A, Mat B, Mat X)
819d71ae5a4SJacob Faibussowitsch {
8204396437dSToby Isaac   PetscScalar *y;
821bf5a80bcSToby Isaac   PetscBLASInt m, k, ldy, nrhs;
8224396437dSToby Isaac 
8234396437dSToby Isaac   PetscFunctionBegin;
8249566063dSJacob Faibussowitsch   PetscCall(MatMatSolve_SeqDense_SetUp(A, B, X, &y, &ldy, &m, &nrhs, &k));
8259566063dSJacob Faibussowitsch   PetscCall(MatSolveTranspose_SeqDense_Internal_QR(A, y, ldy, m, nrhs, k));
8269566063dSJacob Faibussowitsch   PetscCall(MatMatSolve_SeqDense_TearDown(A, B, X, &y, &ldy, &m, &nrhs, &k));
8273ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
8284396437dSToby Isaac }
8294396437dSToby Isaac 
830db4efbfdSBarry Smith /* COMMENT: I have chosen to hide row permutation in the pivots,
831db4efbfdSBarry Smith    rather than put it in the Mat->row slot.*/
832d71ae5a4SJacob Faibussowitsch PetscErrorCode MatLUFactor_SeqDense(Mat A, IS row, IS col, const MatFactorInfo *minfo)
833d71ae5a4SJacob Faibussowitsch {
834db4efbfdSBarry Smith   Mat_SeqDense *mat = (Mat_SeqDense *)A->data;
835db4efbfdSBarry Smith   PetscBLASInt  n, m, info;
836db4efbfdSBarry Smith 
837db4efbfdSBarry Smith   PetscFunctionBegin;
8389566063dSJacob Faibussowitsch   PetscCall(PetscBLASIntCast(A->cmap->n, &n));
8399566063dSJacob Faibussowitsch   PetscCall(PetscBLASIntCast(A->rmap->n, &m));
8404dfa11a4SJacob Faibussowitsch   if (!mat->pivots) { PetscCall(PetscMalloc1(A->rmap->n, &mat->pivots)); }
8413ba16761SJacob Faibussowitsch   if (!A->rmap->n || !A->cmap->n) PetscFunctionReturn(PETSC_SUCCESS);
8429566063dSJacob Faibussowitsch   PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF));
843792fecdfSBarry Smith   PetscCallBLAS("LAPACKgetrf", LAPACKgetrf_(&m, &n, mat->v, &mat->lda, mat->pivots, &info));
8449566063dSJacob Faibussowitsch   PetscCall(PetscFPTrapPop());
8458e57ea43SSatish Balay 
84605fcb23eSStefano Zampini   PetscCheck(info >= 0, PETSC_COMM_SELF, PETSC_ERR_LIB, "Bad argument to LU factorization %d", (int)info);
84705fcb23eSStefano Zampini   PetscCheck(info <= 0, PETSC_COMM_SELF, PETSC_ERR_MAT_LU_ZRPVT, "Bad LU factorization %d", (int)info);
8488208b9aeSStefano Zampini 
8494396437dSToby Isaac   A->ops->solve             = MatSolve_SeqDense_LU;
8504396437dSToby Isaac   A->ops->matsolve          = MatMatSolve_SeqDense_LU;
8514396437dSToby Isaac   A->ops->solvetranspose    = MatSolveTranspose_SeqDense_LU;
8524396437dSToby Isaac   A->ops->matsolvetranspose = MatMatSolveTranspose_SeqDense_LU;
853d5f3da31SBarry Smith   A->factortype             = MAT_FACTOR_LU;
854db4efbfdSBarry Smith 
8559566063dSJacob Faibussowitsch   PetscCall(PetscFree(A->solvertype));
8569566063dSJacob Faibussowitsch   PetscCall(PetscStrallocpy(MATSOLVERPETSC, &A->solvertype));
857f6224b95SHong Zhang 
8589566063dSJacob Faibussowitsch   PetscCall(PetscLogFlops((2.0 * A->cmap->n * A->cmap->n * A->cmap->n) / 3));
8593ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
860db4efbfdSBarry Smith }
861db4efbfdSBarry Smith 
862d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatLUFactorNumeric_SeqDense(Mat fact, Mat A, const MatFactorInfo *info_dummy)
863d71ae5a4SJacob Faibussowitsch {
8644396437dSToby Isaac   MatFactorInfo info;
8654396437dSToby Isaac 
8664396437dSToby Isaac   PetscFunctionBegin;
8679566063dSJacob Faibussowitsch   PetscCall(MatDuplicateNoCreate_SeqDense(fact, A, MAT_COPY_VALUES));
868dbbe0bcdSBarry Smith   PetscUseTypeMethod(fact, lufactor, NULL, NULL, &info);
8693ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
8704396437dSToby Isaac }
8714396437dSToby Isaac 
872d71ae5a4SJacob Faibussowitsch PetscErrorCode MatLUFactorSymbolic_SeqDense(Mat fact, Mat A, IS row, IS col, const MatFactorInfo *info)
873d71ae5a4SJacob Faibussowitsch {
8744396437dSToby Isaac   PetscFunctionBegin;
8754396437dSToby Isaac   fact->preallocated         = PETSC_TRUE;
8764396437dSToby Isaac   fact->assembled            = PETSC_TRUE;
8774396437dSToby Isaac   fact->ops->lufactornumeric = MatLUFactorNumeric_SeqDense;
8783ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
8794396437dSToby Isaac }
8804396437dSToby Isaac 
881a49dc2a2SStefano Zampini /* Cholesky as L*L^T or L*D*L^T and the symmetric/hermitian complex variants */
882d71ae5a4SJacob Faibussowitsch PetscErrorCode MatCholeskyFactor_SeqDense(Mat A, IS perm, const MatFactorInfo *factinfo)
883d71ae5a4SJacob Faibussowitsch {
884db4efbfdSBarry Smith   Mat_SeqDense *mat = (Mat_SeqDense *)A->data;
885c5df96a5SBarry Smith   PetscBLASInt  info, n;
886db4efbfdSBarry Smith 
887db4efbfdSBarry Smith   PetscFunctionBegin;
8889566063dSJacob Faibussowitsch   PetscCall(PetscBLASIntCast(A->cmap->n, &n));
8893ba16761SJacob Faibussowitsch   if (!A->rmap->n || !A->cmap->n) PetscFunctionReturn(PETSC_SUCCESS);
890b94d7dedSBarry Smith   if (A->spd == PETSC_BOOL3_TRUE) {
8919566063dSJacob Faibussowitsch     PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF));
892792fecdfSBarry Smith     PetscCallBLAS("LAPACKpotrf", LAPACKpotrf_("L", &n, mat->v, &mat->lda, &info));
8939566063dSJacob Faibussowitsch     PetscCall(PetscFPTrapPop());
894a49dc2a2SStefano Zampini #if defined(PETSC_USE_COMPLEX)
895b94d7dedSBarry Smith   } else if (A->hermitian == PETSC_BOOL3_TRUE) {
8964dfa11a4SJacob Faibussowitsch     if (!mat->pivots) { PetscCall(PetscMalloc1(A->rmap->n, &mat->pivots)); }
897a49dc2a2SStefano Zampini     if (!mat->fwork) {
898a49dc2a2SStefano Zampini       PetscScalar dummy;
899a49dc2a2SStefano Zampini 
900a49dc2a2SStefano Zampini       mat->lfwork = -1;
9019566063dSJacob Faibussowitsch       PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF));
902792fecdfSBarry Smith       PetscCallBLAS("LAPACKhetrf", LAPACKhetrf_("L", &n, mat->v, &mat->lda, mat->pivots, &dummy, &mat->lfwork, &info));
9039566063dSJacob Faibussowitsch       PetscCall(PetscFPTrapPop());
904a49dc2a2SStefano Zampini       mat->lfwork = (PetscInt)PetscRealPart(dummy);
9059566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(mat->lfwork, &mat->fwork));
906a49dc2a2SStefano Zampini     }
9079566063dSJacob Faibussowitsch     PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF));
908792fecdfSBarry Smith     PetscCallBLAS("LAPACKhetrf", LAPACKhetrf_("L", &n, mat->v, &mat->lda, mat->pivots, mat->fwork, &mat->lfwork, &info));
9099566063dSJacob Faibussowitsch     PetscCall(PetscFPTrapPop());
910a49dc2a2SStefano Zampini #endif
911a49dc2a2SStefano Zampini   } else { /* symmetric case */
9124dfa11a4SJacob Faibussowitsch     if (!mat->pivots) { PetscCall(PetscMalloc1(A->rmap->n, &mat->pivots)); }
913a49dc2a2SStefano Zampini     if (!mat->fwork) {
914a49dc2a2SStefano Zampini       PetscScalar dummy;
915a49dc2a2SStefano Zampini 
916a49dc2a2SStefano Zampini       mat->lfwork = -1;
9179566063dSJacob Faibussowitsch       PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF));
918792fecdfSBarry Smith       PetscCallBLAS("LAPACKsytrf", LAPACKsytrf_("L", &n, mat->v, &mat->lda, mat->pivots, &dummy, &mat->lfwork, &info));
9199566063dSJacob Faibussowitsch       PetscCall(PetscFPTrapPop());
920a49dc2a2SStefano Zampini       mat->lfwork = (PetscInt)PetscRealPart(dummy);
9219566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(mat->lfwork, &mat->fwork));
922a49dc2a2SStefano Zampini     }
9239566063dSJacob Faibussowitsch     PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF));
924792fecdfSBarry Smith     PetscCallBLAS("LAPACKsytrf", LAPACKsytrf_("L", &n, mat->v, &mat->lda, mat->pivots, mat->fwork, &mat->lfwork, &info));
9259566063dSJacob Faibussowitsch     PetscCall(PetscFPTrapPop());
926a49dc2a2SStefano Zampini   }
92728b400f6SJacob Faibussowitsch   PetscCheck(!info, PETSC_COMM_SELF, PETSC_ERR_MAT_CH_ZRPVT, "Bad factorization: zero pivot in row %" PetscInt_FMT, (PetscInt)info - 1);
9288208b9aeSStefano Zampini 
9294396437dSToby Isaac   A->ops->solve             = MatSolve_SeqDense_Cholesky;
9304396437dSToby Isaac   A->ops->matsolve          = MatMatSolve_SeqDense_Cholesky;
9314396437dSToby Isaac   A->ops->solvetranspose    = MatSolveTranspose_SeqDense_Cholesky;
9324396437dSToby Isaac   A->ops->matsolvetranspose = MatMatSolveTranspose_SeqDense_Cholesky;
933d5f3da31SBarry Smith   A->factortype             = MAT_FACTOR_CHOLESKY;
9342205254eSKarl Rupp 
9359566063dSJacob Faibussowitsch   PetscCall(PetscFree(A->solvertype));
9369566063dSJacob Faibussowitsch   PetscCall(PetscStrallocpy(MATSOLVERPETSC, &A->solvertype));
937f6224b95SHong Zhang 
9389566063dSJacob Faibussowitsch   PetscCall(PetscLogFlops((1.0 * A->cmap->n * A->cmap->n * A->cmap->n) / 3.0));
9393ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
940db4efbfdSBarry Smith }
941db4efbfdSBarry Smith 
942d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatCholeskyFactorNumeric_SeqDense(Mat fact, Mat A, const MatFactorInfo *info_dummy)
943d71ae5a4SJacob Faibussowitsch {
944db4efbfdSBarry Smith   MatFactorInfo info;
945db4efbfdSBarry Smith 
946db4efbfdSBarry Smith   PetscFunctionBegin;
947db4efbfdSBarry Smith   info.fill = 1.0;
9482205254eSKarl Rupp 
9499566063dSJacob Faibussowitsch   PetscCall(MatDuplicateNoCreate_SeqDense(fact, A, MAT_COPY_VALUES));
950dbbe0bcdSBarry Smith   PetscUseTypeMethod(fact, choleskyfactor, NULL, &info);
9513ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
952db4efbfdSBarry Smith }
953db4efbfdSBarry Smith 
954d71ae5a4SJacob Faibussowitsch PetscErrorCode MatCholeskyFactorSymbolic_SeqDense(Mat fact, Mat A, IS row, const MatFactorInfo *info)
955d71ae5a4SJacob Faibussowitsch {
956db4efbfdSBarry Smith   PetscFunctionBegin;
957c3ef05f6SHong Zhang   fact->assembled                  = PETSC_TRUE;
9581bbcc794SSatish Balay   fact->preallocated               = PETSC_TRUE;
959719d5645SBarry Smith   fact->ops->choleskyfactornumeric = MatCholeskyFactorNumeric_SeqDense;
9603ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
961db4efbfdSBarry Smith }
962db4efbfdSBarry Smith 
963d71ae5a4SJacob Faibussowitsch PetscErrorCode MatQRFactor_SeqDense(Mat A, IS col, const MatFactorInfo *minfo)
964d71ae5a4SJacob Faibussowitsch {
9654905a7bcSToby Isaac   Mat_SeqDense *mat = (Mat_SeqDense *)A->data;
9664905a7bcSToby Isaac   PetscBLASInt  n, m, info, min, max;
9674905a7bcSToby Isaac 
9684905a7bcSToby Isaac   PetscFunctionBegin;
9699566063dSJacob Faibussowitsch   PetscCall(PetscBLASIntCast(A->cmap->n, &n));
9709566063dSJacob Faibussowitsch   PetscCall(PetscBLASIntCast(A->rmap->n, &m));
9714396437dSToby Isaac   max = PetscMax(m, n);
9724396437dSToby Isaac   min = PetscMin(m, n);
9734dfa11a4SJacob Faibussowitsch   if (!mat->tau) { PetscCall(PetscMalloc1(min, &mat->tau)); }
9744dfa11a4SJacob Faibussowitsch   if (!mat->pivots) { PetscCall(PetscMalloc1(n, &mat->pivots)); }
97548a46eb9SPierre Jolivet   if (!mat->qrrhs) PetscCall(MatCreateVecs(A, NULL, &(mat->qrrhs)));
9763ba16761SJacob Faibussowitsch   if (!A->rmap->n || !A->cmap->n) PetscFunctionReturn(PETSC_SUCCESS);
9774905a7bcSToby Isaac   if (!mat->fwork) {
9784905a7bcSToby Isaac     PetscScalar dummy;
9794905a7bcSToby Isaac 
9804905a7bcSToby Isaac     mat->lfwork = -1;
9819566063dSJacob Faibussowitsch     PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF));
982792fecdfSBarry Smith     PetscCallBLAS("LAPACKgeqrf", LAPACKgeqrf_(&m, &n, mat->v, &mat->lda, mat->tau, &dummy, &mat->lfwork, &info));
9839566063dSJacob Faibussowitsch     PetscCall(PetscFPTrapPop());
9844905a7bcSToby Isaac     mat->lfwork = (PetscInt)PetscRealPart(dummy);
9859566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(mat->lfwork, &mat->fwork));
9864905a7bcSToby Isaac   }
9879566063dSJacob Faibussowitsch   PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF));
988792fecdfSBarry Smith   PetscCallBLAS("LAPACKgeqrf", LAPACKgeqrf_(&m, &n, mat->v, &mat->lda, mat->tau, mat->fwork, &mat->lfwork, &info));
9899566063dSJacob Faibussowitsch   PetscCall(PetscFPTrapPop());
99005fcb23eSStefano Zampini   PetscCheck(!info, PETSC_COMM_SELF, PETSC_ERR_LIB, "Bad argument to QR factorization %d", (int)info);
9914905a7bcSToby Isaac   // 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
9924905a7bcSToby Isaac   mat->rank = min;
9934905a7bcSToby Isaac 
9944396437dSToby Isaac   A->ops->solve    = MatSolve_SeqDense_QR;
9954396437dSToby Isaac   A->ops->matsolve = MatMatSolve_SeqDense_QR;
9964905a7bcSToby Isaac   A->factortype    = MAT_FACTOR_QR;
9974905a7bcSToby Isaac   if (m == n) {
9984396437dSToby Isaac     A->ops->solvetranspose    = MatSolveTranspose_SeqDense_QR;
9994396437dSToby Isaac     A->ops->matsolvetranspose = MatMatSolveTranspose_SeqDense_QR;
10004905a7bcSToby Isaac   }
10014905a7bcSToby Isaac 
10029566063dSJacob Faibussowitsch   PetscCall(PetscFree(A->solvertype));
10039566063dSJacob Faibussowitsch   PetscCall(PetscStrallocpy(MATSOLVERPETSC, &A->solvertype));
10044905a7bcSToby Isaac 
10059566063dSJacob Faibussowitsch   PetscCall(PetscLogFlops(2.0 * min * min * (max - min / 3.0)));
10063ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
10074905a7bcSToby Isaac }
10084905a7bcSToby Isaac 
1009d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatQRFactorNumeric_SeqDense(Mat fact, Mat A, const MatFactorInfo *info_dummy)
1010d71ae5a4SJacob Faibussowitsch {
10114905a7bcSToby Isaac   MatFactorInfo info;
10124905a7bcSToby Isaac 
10134905a7bcSToby Isaac   PetscFunctionBegin;
10144905a7bcSToby Isaac   info.fill = 1.0;
10154905a7bcSToby Isaac 
10169566063dSJacob Faibussowitsch   PetscCall(MatDuplicateNoCreate_SeqDense(fact, A, MAT_COPY_VALUES));
1017cac4c232SBarry Smith   PetscUseMethod(fact, "MatQRFactor_C", (Mat, IS, const MatFactorInfo *), (fact, NULL, &info));
10183ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
10194905a7bcSToby Isaac }
10204905a7bcSToby Isaac 
1021d71ae5a4SJacob Faibussowitsch PetscErrorCode MatQRFactorSymbolic_SeqDense(Mat fact, Mat A, IS row, const MatFactorInfo *info)
1022d71ae5a4SJacob Faibussowitsch {
10234905a7bcSToby Isaac   PetscFunctionBegin;
10244905a7bcSToby Isaac   fact->assembled    = PETSC_TRUE;
10254905a7bcSToby Isaac   fact->preallocated = PETSC_TRUE;
10269566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)fact, "MatQRFactorNumeric_C", MatQRFactorNumeric_SeqDense));
10273ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
10284905a7bcSToby Isaac }
10294905a7bcSToby Isaac 
1030ca15aa20SStefano Zampini /* uses LAPACK */
1031d71ae5a4SJacob Faibussowitsch PETSC_INTERN PetscErrorCode MatGetFactor_seqdense_petsc(Mat A, MatFactorType ftype, Mat *fact)
1032d71ae5a4SJacob Faibussowitsch {
1033db4efbfdSBarry Smith   PetscFunctionBegin;
10349566063dSJacob Faibussowitsch   PetscCall(MatCreate(PetscObjectComm((PetscObject)A), fact));
10359566063dSJacob Faibussowitsch   PetscCall(MatSetSizes(*fact, A->rmap->n, A->cmap->n, A->rmap->n, A->cmap->n));
10369566063dSJacob Faibussowitsch   PetscCall(MatSetType(*fact, MATDENSE));
103766e17bc3SBarry Smith   (*fact)->trivialsymbolic = PETSC_TRUE;
10382a350339SBarry Smith   if (ftype == MAT_FACTOR_LU || ftype == MAT_FACTOR_ILU) {
1039db4efbfdSBarry Smith     (*fact)->ops->lufactorsymbolic  = MatLUFactorSymbolic_SeqDense;
10402a350339SBarry Smith     (*fact)->ops->ilufactorsymbolic = MatLUFactorSymbolic_SeqDense;
1041bf5a80bcSToby Isaac   } else if (ftype == MAT_FACTOR_CHOLESKY || ftype == MAT_FACTOR_ICC) {
1042db4efbfdSBarry Smith     (*fact)->ops->choleskyfactorsymbolic = MatCholeskyFactorSymbolic_SeqDense;
1043bf5a80bcSToby Isaac   } else if (ftype == MAT_FACTOR_QR) {
10449566063dSJacob Faibussowitsch     PetscCall(PetscObjectComposeFunction((PetscObject)(*fact), "MatQRFactorSymbolic_C", MatQRFactorSymbolic_SeqDense));
1045db4efbfdSBarry Smith   }
1046d5f3da31SBarry Smith   (*fact)->factortype = ftype;
104700c67f3bSHong Zhang 
10489566063dSJacob Faibussowitsch   PetscCall(PetscFree((*fact)->solvertype));
10499566063dSJacob Faibussowitsch   PetscCall(PetscStrallocpy(MATSOLVERPETSC, &(*fact)->solvertype));
10509566063dSJacob Faibussowitsch   PetscCall(PetscStrallocpy(MATORDERINGEXTERNAL, (char **)&(*fact)->preferredordering[MAT_FACTOR_LU]));
10519566063dSJacob Faibussowitsch   PetscCall(PetscStrallocpy(MATORDERINGEXTERNAL, (char **)&(*fact)->preferredordering[MAT_FACTOR_ILU]));
10529566063dSJacob Faibussowitsch   PetscCall(PetscStrallocpy(MATORDERINGEXTERNAL, (char **)&(*fact)->preferredordering[MAT_FACTOR_CHOLESKY]));
10539566063dSJacob Faibussowitsch   PetscCall(PetscStrallocpy(MATORDERINGEXTERNAL, (char **)&(*fact)->preferredordering[MAT_FACTOR_ICC]));
10543ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1055db4efbfdSBarry Smith }
1056db4efbfdSBarry Smith 
1057d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatSOR_SeqDense(Mat A, Vec bb, PetscReal omega, MatSORType flag, PetscReal shift, PetscInt its, PetscInt lits, Vec xx)
1058d71ae5a4SJacob Faibussowitsch {
1059c0bbcb79SLois Curfman McInnes   Mat_SeqDense      *mat = (Mat_SeqDense *)A->data;
1060d9ca1df4SBarry Smith   PetscScalar       *x, *v = mat->v, zero = 0.0, xt;
1061d9ca1df4SBarry Smith   const PetscScalar *b;
1062d0f46423SBarry Smith   PetscInt           m = A->rmap->n, i;
106323fff9afSBarry Smith   PetscBLASInt       o = 1, bm = 0;
1064289bc588SBarry Smith 
10653a40ed3dSBarry Smith   PetscFunctionBegin;
106647d993e7Ssuyashtn #if defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
106708401ef6SPierre Jolivet   PetscCheck(A->offloadmask != PETSC_OFFLOAD_GPU, PETSC_COMM_SELF, PETSC_ERR_SUP, "Not implemented");
1068ca15aa20SStefano Zampini #endif
1069422a814eSBarry Smith   if (shift == -1) shift = 0.0; /* negative shift indicates do not error on zero diagonal; this code never zeros on zero diagonal */
10709566063dSJacob Faibussowitsch   PetscCall(PetscBLASIntCast(m, &bm));
1071289bc588SBarry Smith   if (flag & SOR_ZERO_INITIAL_GUESS) {
10723bffc371SBarry Smith     /* this is a hack fix, should have another version without the second BLASdotu */
10739566063dSJacob Faibussowitsch     PetscCall(VecSet(xx, zero));
1074289bc588SBarry Smith   }
10759566063dSJacob Faibussowitsch   PetscCall(VecGetArray(xx, &x));
10769566063dSJacob Faibussowitsch   PetscCall(VecGetArrayRead(bb, &b));
1077b965ef7fSBarry Smith   its = its * lits;
107808401ef6SPierre Jolivet   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);
1079289bc588SBarry Smith   while (its--) {
1080fccaa45eSBarry Smith     if (flag & SOR_FORWARD_SWEEP || flag & SOR_LOCAL_FORWARD_SWEEP) {
1081289bc588SBarry Smith       for (i = 0; i < m; i++) {
1082792fecdfSBarry Smith         PetscCallBLAS("BLASdotu", xt = b[i] - BLASdotu_(&bm, v + i, &bm, x, &o));
108355a1b374SBarry Smith         x[i] = (1. - omega) * x[i] + omega * (xt + v[i + i * m] * x[i]) / (v[i + i * m] + shift);
1084289bc588SBarry Smith       }
1085289bc588SBarry Smith     }
1086fccaa45eSBarry Smith     if (flag & SOR_BACKWARD_SWEEP || flag & SOR_LOCAL_BACKWARD_SWEEP) {
1087289bc588SBarry Smith       for (i = m - 1; i >= 0; i--) {
1088792fecdfSBarry Smith         PetscCallBLAS("BLASdotu", xt = b[i] - BLASdotu_(&bm, v + i, &bm, x, &o));
108955a1b374SBarry Smith         x[i] = (1. - omega) * x[i] + omega * (xt + v[i + i * m] * x[i]) / (v[i + i * m] + shift);
1090289bc588SBarry Smith       }
1091289bc588SBarry Smith     }
1092289bc588SBarry Smith   }
10939566063dSJacob Faibussowitsch   PetscCall(VecRestoreArrayRead(bb, &b));
10949566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(xx, &x));
10953ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1096289bc588SBarry Smith }
1097289bc588SBarry Smith 
1098d71ae5a4SJacob Faibussowitsch PetscErrorCode MatMultTranspose_SeqDense(Mat A, Vec xx, Vec yy)
1099d71ae5a4SJacob Faibussowitsch {
1100c0bbcb79SLois Curfman McInnes   Mat_SeqDense      *mat = (Mat_SeqDense *)A->data;
1101d9ca1df4SBarry Smith   const PetscScalar *v   = mat->v, *x;
1102d9ca1df4SBarry Smith   PetscScalar       *y;
11030805154bSBarry Smith   PetscBLASInt       m, n, _One = 1;
1104ea709b57SSatish Balay   PetscScalar        _DOne = 1.0, _DZero = 0.0;
11053a40ed3dSBarry Smith 
11063a40ed3dSBarry Smith   PetscFunctionBegin;
11079566063dSJacob Faibussowitsch   PetscCall(PetscBLASIntCast(A->rmap->n, &m));
11089566063dSJacob Faibussowitsch   PetscCall(PetscBLASIntCast(A->cmap->n, &n));
11099566063dSJacob Faibussowitsch   PetscCall(VecGetArrayRead(xx, &x));
11109566063dSJacob Faibussowitsch   PetscCall(VecGetArrayWrite(yy, &y));
11115ac36cfcSBarry Smith   if (!A->rmap->n || !A->cmap->n) {
11125ac36cfcSBarry Smith     PetscBLASInt i;
11135ac36cfcSBarry Smith     for (i = 0; i < n; i++) y[i] = 0.0;
11145ac36cfcSBarry Smith   } else {
1115792fecdfSBarry Smith     PetscCallBLAS("BLASgemv", BLASgemv_("T", &m, &n, &_DOne, v, &mat->lda, x, &_One, &_DZero, y, &_One));
11169566063dSJacob Faibussowitsch     PetscCall(PetscLogFlops(2.0 * A->rmap->n * A->cmap->n - A->cmap->n));
11175ac36cfcSBarry Smith   }
11189566063dSJacob Faibussowitsch   PetscCall(VecRestoreArrayRead(xx, &x));
11199566063dSJacob Faibussowitsch   PetscCall(VecRestoreArrayWrite(yy, &y));
11203ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1121289bc588SBarry Smith }
1122800995b7SMatthew Knepley 
1123d71ae5a4SJacob Faibussowitsch PetscErrorCode MatMult_SeqDense(Mat A, Vec xx, Vec yy)
1124d71ae5a4SJacob Faibussowitsch {
1125c0bbcb79SLois Curfman McInnes   Mat_SeqDense      *mat = (Mat_SeqDense *)A->data;
1126d9ca1df4SBarry Smith   PetscScalar       *y, _DOne = 1.0, _DZero = 0.0;
11270805154bSBarry Smith   PetscBLASInt       m, n, _One             = 1;
1128d9ca1df4SBarry Smith   const PetscScalar *v = mat->v, *x;
11293a40ed3dSBarry Smith 
11303a40ed3dSBarry Smith   PetscFunctionBegin;
11319566063dSJacob Faibussowitsch   PetscCall(PetscBLASIntCast(A->rmap->n, &m));
11329566063dSJacob Faibussowitsch   PetscCall(PetscBLASIntCast(A->cmap->n, &n));
11339566063dSJacob Faibussowitsch   PetscCall(VecGetArrayRead(xx, &x));
11349566063dSJacob Faibussowitsch   PetscCall(VecGetArrayWrite(yy, &y));
11355ac36cfcSBarry Smith   if (!A->rmap->n || !A->cmap->n) {
11365ac36cfcSBarry Smith     PetscBLASInt i;
11375ac36cfcSBarry Smith     for (i = 0; i < m; i++) y[i] = 0.0;
11385ac36cfcSBarry Smith   } else {
1139792fecdfSBarry Smith     PetscCallBLAS("BLASgemv", BLASgemv_("N", &m, &n, &_DOne, v, &(mat->lda), x, &_One, &_DZero, y, &_One));
11409566063dSJacob Faibussowitsch     PetscCall(PetscLogFlops(2.0 * A->rmap->n * A->cmap->n - A->rmap->n));
11415ac36cfcSBarry Smith   }
11429566063dSJacob Faibussowitsch   PetscCall(VecRestoreArrayRead(xx, &x));
11439566063dSJacob Faibussowitsch   PetscCall(VecRestoreArrayWrite(yy, &y));
11443ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1145289bc588SBarry Smith }
11466ee01492SSatish Balay 
1147d71ae5a4SJacob Faibussowitsch PetscErrorCode MatMultAdd_SeqDense(Mat A, Vec xx, Vec zz, Vec yy)
1148d71ae5a4SJacob Faibussowitsch {
1149c0bbcb79SLois Curfman McInnes   Mat_SeqDense      *mat = (Mat_SeqDense *)A->data;
1150d9ca1df4SBarry Smith   const PetscScalar *v   = mat->v, *x;
1151d9ca1df4SBarry Smith   PetscScalar       *y, _DOne = 1.0;
11520805154bSBarry Smith   PetscBLASInt       m, n, _One = 1;
11533a40ed3dSBarry Smith 
11543a40ed3dSBarry Smith   PetscFunctionBegin;
11559566063dSJacob Faibussowitsch   PetscCall(PetscBLASIntCast(A->rmap->n, &m));
11569566063dSJacob Faibussowitsch   PetscCall(PetscBLASIntCast(A->cmap->n, &n));
11579566063dSJacob Faibussowitsch   PetscCall(VecCopy(zz, yy));
11583ba16761SJacob Faibussowitsch   if (!A->rmap->n || !A->cmap->n) PetscFunctionReturn(PETSC_SUCCESS);
11599566063dSJacob Faibussowitsch   PetscCall(VecGetArrayRead(xx, &x));
11609566063dSJacob Faibussowitsch   PetscCall(VecGetArray(yy, &y));
1161792fecdfSBarry Smith   PetscCallBLAS("BLASgemv", BLASgemv_("N", &m, &n, &_DOne, v, &(mat->lda), x, &_One, &_DOne, y, &_One));
11629566063dSJacob Faibussowitsch   PetscCall(VecRestoreArrayRead(xx, &x));
11639566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(yy, &y));
11649566063dSJacob Faibussowitsch   PetscCall(PetscLogFlops(2.0 * A->rmap->n * A->cmap->n));
11653ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1166289bc588SBarry Smith }
11676ee01492SSatish Balay 
1168d71ae5a4SJacob Faibussowitsch PetscErrorCode MatMultTransposeAdd_SeqDense(Mat A, Vec xx, Vec zz, Vec yy)
1169d71ae5a4SJacob Faibussowitsch {
1170c0bbcb79SLois Curfman McInnes   Mat_SeqDense      *mat = (Mat_SeqDense *)A->data;
1171d9ca1df4SBarry Smith   const PetscScalar *v   = mat->v, *x;
1172d9ca1df4SBarry Smith   PetscScalar       *y;
11730805154bSBarry Smith   PetscBLASInt       m, n, _One = 1;
117487828ca2SBarry Smith   PetscScalar        _DOne = 1.0;
11753a40ed3dSBarry Smith 
11763a40ed3dSBarry Smith   PetscFunctionBegin;
11779566063dSJacob Faibussowitsch   PetscCall(PetscBLASIntCast(A->rmap->n, &m));
11789566063dSJacob Faibussowitsch   PetscCall(PetscBLASIntCast(A->cmap->n, &n));
11799566063dSJacob Faibussowitsch   PetscCall(VecCopy(zz, yy));
11803ba16761SJacob Faibussowitsch   if (!A->rmap->n || !A->cmap->n) PetscFunctionReturn(PETSC_SUCCESS);
11819566063dSJacob Faibussowitsch   PetscCall(VecGetArrayRead(xx, &x));
11829566063dSJacob Faibussowitsch   PetscCall(VecGetArray(yy, &y));
1183792fecdfSBarry Smith   PetscCallBLAS("BLASgemv", BLASgemv_("T", &m, &n, &_DOne, v, &(mat->lda), x, &_One, &_DOne, y, &_One));
11849566063dSJacob Faibussowitsch   PetscCall(VecRestoreArrayRead(xx, &x));
11859566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(yy, &y));
11869566063dSJacob Faibussowitsch   PetscCall(PetscLogFlops(2.0 * A->rmap->n * A->cmap->n));
11873ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1188289bc588SBarry Smith }
1189289bc588SBarry Smith 
1190d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatGetRow_SeqDense(Mat A, PetscInt row, PetscInt *ncols, PetscInt **cols, PetscScalar **vals)
1191d71ae5a4SJacob Faibussowitsch {
1192c0bbcb79SLois Curfman McInnes   Mat_SeqDense *mat = (Mat_SeqDense *)A->data;
119313f74950SBarry Smith   PetscInt      i;
119467e560aaSBarry Smith 
11953a40ed3dSBarry Smith   PetscFunctionBegin;
1196d0f46423SBarry Smith   *ncols = A->cmap->n;
1197289bc588SBarry Smith   if (cols) {
11989566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(A->cmap->n, cols));
1199d0f46423SBarry Smith     for (i = 0; i < A->cmap->n; i++) (*cols)[i] = i;
1200289bc588SBarry Smith   }
1201289bc588SBarry Smith   if (vals) {
1202ca15aa20SStefano Zampini     const PetscScalar *v;
1203ca15aa20SStefano Zampini 
12049566063dSJacob Faibussowitsch     PetscCall(MatDenseGetArrayRead(A, &v));
12059566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(A->cmap->n, vals));
1206ca15aa20SStefano Zampini     v += row;
12079371c9d4SSatish Balay     for (i = 0; i < A->cmap->n; i++) {
12089371c9d4SSatish Balay       (*vals)[i] = *v;
12099371c9d4SSatish Balay       v += mat->lda;
12109371c9d4SSatish Balay     }
12119566063dSJacob Faibussowitsch     PetscCall(MatDenseRestoreArrayRead(A, &v));
1212289bc588SBarry Smith   }
12133ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1214289bc588SBarry Smith }
12156ee01492SSatish Balay 
1216d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatRestoreRow_SeqDense(Mat A, PetscInt row, PetscInt *ncols, PetscInt **cols, PetscScalar **vals)
1217d71ae5a4SJacob Faibussowitsch {
1218606d414cSSatish Balay   PetscFunctionBegin;
1219cb4a9cd9SHong Zhang   if (ncols) *ncols = 0;
12209566063dSJacob Faibussowitsch   if (cols) PetscCall(PetscFree(*cols));
12219566063dSJacob Faibussowitsch   if (vals) PetscCall(PetscFree(*vals));
12223ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1223289bc588SBarry Smith }
1224*2ef1f0ffSBarry Smith 
1225d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatSetValues_SeqDense(Mat A, PetscInt m, const PetscInt indexm[], PetscInt n, const PetscInt indexn[], const PetscScalar v[], InsertMode addv)
1226d71ae5a4SJacob Faibussowitsch {
1227c0bbcb79SLois Curfman McInnes   Mat_SeqDense *mat = (Mat_SeqDense *)A->data;
1228ca15aa20SStefano Zampini   PetscScalar  *av;
122913f74950SBarry Smith   PetscInt      i, j, idx = 0;
123047d993e7Ssuyashtn #if defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
1231c70f7ee4SJunchao Zhang   PetscOffloadMask oldf;
1232ca15aa20SStefano Zampini #endif
1233d6dfbf8fSBarry Smith 
12343a40ed3dSBarry Smith   PetscFunctionBegin;
12359566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArray(A, &av));
1236289bc588SBarry Smith   if (!mat->roworiented) {
1237dbb450caSBarry Smith     if (addv == INSERT_VALUES) {
1238289bc588SBarry Smith       for (j = 0; j < n; j++) {
12399371c9d4SSatish Balay         if (indexn[j] < 0) {
12409371c9d4SSatish Balay           idx += m;
12419371c9d4SSatish Balay           continue;
12429371c9d4SSatish Balay         }
12436bdcaf15SBarry Smith         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);
1244289bc588SBarry Smith         for (i = 0; i < m; i++) {
12459371c9d4SSatish Balay           if (indexm[i] < 0) {
12469371c9d4SSatish Balay             idx++;
12479371c9d4SSatish Balay             continue;
12489371c9d4SSatish Balay           }
12496bdcaf15SBarry Smith           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);
1250ca15aa20SStefano Zampini           av[indexn[j] * mat->lda + indexm[i]] = v[idx++];
1251289bc588SBarry Smith         }
1252289bc588SBarry Smith       }
12533a40ed3dSBarry Smith     } else {
1254289bc588SBarry Smith       for (j = 0; j < n; j++) {
12559371c9d4SSatish Balay         if (indexn[j] < 0) {
12569371c9d4SSatish Balay           idx += m;
12579371c9d4SSatish Balay           continue;
12589371c9d4SSatish Balay         }
12596bdcaf15SBarry Smith         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);
1260289bc588SBarry Smith         for (i = 0; i < m; i++) {
12619371c9d4SSatish Balay           if (indexm[i] < 0) {
12629371c9d4SSatish Balay             idx++;
12639371c9d4SSatish Balay             continue;
12649371c9d4SSatish Balay           }
12656bdcaf15SBarry Smith           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);
1266ca15aa20SStefano Zampini           av[indexn[j] * mat->lda + indexm[i]] += v[idx++];
1267289bc588SBarry Smith         }
1268289bc588SBarry Smith       }
1269289bc588SBarry Smith     }
12703a40ed3dSBarry Smith   } else {
1271dbb450caSBarry Smith     if (addv == INSERT_VALUES) {
1272e8d4e0b9SBarry Smith       for (i = 0; i < m; i++) {
12739371c9d4SSatish Balay         if (indexm[i] < 0) {
12749371c9d4SSatish Balay           idx += n;
12759371c9d4SSatish Balay           continue;
12769371c9d4SSatish Balay         }
12776bdcaf15SBarry Smith         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);
1278e8d4e0b9SBarry Smith         for (j = 0; j < n; j++) {
12799371c9d4SSatish Balay           if (indexn[j] < 0) {
12809371c9d4SSatish Balay             idx++;
12819371c9d4SSatish Balay             continue;
12829371c9d4SSatish Balay           }
12836bdcaf15SBarry Smith           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);
1284ca15aa20SStefano Zampini           av[indexn[j] * mat->lda + indexm[i]] = v[idx++];
1285e8d4e0b9SBarry Smith         }
1286e8d4e0b9SBarry Smith       }
12873a40ed3dSBarry Smith     } else {
1288289bc588SBarry Smith       for (i = 0; i < m; i++) {
12899371c9d4SSatish Balay         if (indexm[i] < 0) {
12909371c9d4SSatish Balay           idx += n;
12919371c9d4SSatish Balay           continue;
12929371c9d4SSatish Balay         }
12936bdcaf15SBarry Smith         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);
1294289bc588SBarry Smith         for (j = 0; j < n; j++) {
12959371c9d4SSatish Balay           if (indexn[j] < 0) {
12969371c9d4SSatish Balay             idx++;
12979371c9d4SSatish Balay             continue;
12989371c9d4SSatish Balay           }
12996bdcaf15SBarry Smith           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);
1300ca15aa20SStefano Zampini           av[indexn[j] * mat->lda + indexm[i]] += v[idx++];
1301289bc588SBarry Smith         }
1302289bc588SBarry Smith       }
1303289bc588SBarry Smith     }
1304e8d4e0b9SBarry Smith   }
1305ca15aa20SStefano Zampini   /* hack to prevent unneeded copy to the GPU while returning the array */
130647d993e7Ssuyashtn #if defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
1307c70f7ee4SJunchao Zhang   oldf           = A->offloadmask;
1308c70f7ee4SJunchao Zhang   A->offloadmask = PETSC_OFFLOAD_GPU;
1309ca15aa20SStefano Zampini #endif
13109566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArray(A, &av));
131147d993e7Ssuyashtn #if defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
1312c70f7ee4SJunchao Zhang   A->offloadmask = (oldf == PETSC_OFFLOAD_UNALLOCATED ? PETSC_OFFLOAD_UNALLOCATED : PETSC_OFFLOAD_CPU);
1313ca15aa20SStefano Zampini #endif
13143ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1315289bc588SBarry Smith }
1316e8d4e0b9SBarry Smith 
1317d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatGetValues_SeqDense(Mat A, PetscInt m, const PetscInt indexm[], PetscInt n, const PetscInt indexn[], PetscScalar v[])
1318d71ae5a4SJacob Faibussowitsch {
1319ae80bb75SLois Curfman McInnes   Mat_SeqDense      *mat = (Mat_SeqDense *)A->data;
1320ca15aa20SStefano Zampini   const PetscScalar *vv;
132113f74950SBarry Smith   PetscInt           i, j;
1322ae80bb75SLois Curfman McInnes 
13233a40ed3dSBarry Smith   PetscFunctionBegin;
13249566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArrayRead(A, &vv));
1325ae80bb75SLois Curfman McInnes   /* row-oriented output */
1326ae80bb75SLois Curfman McInnes   for (i = 0; i < m; i++) {
13279371c9d4SSatish Balay     if (indexm[i] < 0) {
13289371c9d4SSatish Balay       v += n;
13299371c9d4SSatish Balay       continue;
13309371c9d4SSatish Balay     }
133108401ef6SPierre Jolivet     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);
1332ae80bb75SLois Curfman McInnes     for (j = 0; j < n; j++) {
13339371c9d4SSatish Balay       if (indexn[j] < 0) {
13349371c9d4SSatish Balay         v++;
13359371c9d4SSatish Balay         continue;
13369371c9d4SSatish Balay       }
133708401ef6SPierre Jolivet       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);
1338ca15aa20SStefano Zampini       *v++ = vv[indexn[j] * mat->lda + indexm[i]];
1339ae80bb75SLois Curfman McInnes     }
1340ae80bb75SLois Curfman McInnes   }
13419566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArrayRead(A, &vv));
13423ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1343ae80bb75SLois Curfman McInnes }
1344ae80bb75SLois Curfman McInnes 
1345d71ae5a4SJacob Faibussowitsch PetscErrorCode MatView_Dense_Binary(Mat mat, PetscViewer viewer)
1346d71ae5a4SJacob Faibussowitsch {
13478491ab44SLisandro Dalcin   PetscBool          skipHeader;
13488491ab44SLisandro Dalcin   PetscViewerFormat  format;
13498491ab44SLisandro Dalcin   PetscInt           header[4], M, N, m, lda, i, j, k;
13508491ab44SLisandro Dalcin   const PetscScalar *v;
13518491ab44SLisandro Dalcin   PetscScalar       *vwork;
1352aabbc4fbSShri Abhyankar 
1353aabbc4fbSShri Abhyankar   PetscFunctionBegin;
13549566063dSJacob Faibussowitsch   PetscCall(PetscViewerSetUp(viewer));
13559566063dSJacob Faibussowitsch   PetscCall(PetscViewerBinaryGetSkipHeader(viewer, &skipHeader));
13569566063dSJacob Faibussowitsch   PetscCall(PetscViewerGetFormat(viewer, &format));
13578491ab44SLisandro Dalcin   if (skipHeader) format = PETSC_VIEWER_NATIVE;
1358aabbc4fbSShri Abhyankar 
13599566063dSJacob Faibussowitsch   PetscCall(MatGetSize(mat, &M, &N));
13608491ab44SLisandro Dalcin 
13618491ab44SLisandro Dalcin   /* write matrix header */
13629371c9d4SSatish Balay   header[0] = MAT_FILE_CLASSID;
13639371c9d4SSatish Balay   header[1] = M;
13649371c9d4SSatish Balay   header[2] = N;
13658491ab44SLisandro Dalcin   header[3] = (format == PETSC_VIEWER_NATIVE) ? MATRIX_BINARY_FORMAT_DENSE : M * N;
13669566063dSJacob Faibussowitsch   if (!skipHeader) PetscCall(PetscViewerBinaryWrite(viewer, header, 4, PETSC_INT));
13678491ab44SLisandro Dalcin 
13689566063dSJacob Faibussowitsch   PetscCall(MatGetLocalSize(mat, &m, NULL));
13698491ab44SLisandro Dalcin   if (format != PETSC_VIEWER_NATIVE) {
13708491ab44SLisandro Dalcin     PetscInt nnz = m * N, *iwork;
13718491ab44SLisandro Dalcin     /* store row lengths for each row */
13729566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(nnz, &iwork));
13738491ab44SLisandro Dalcin     for (i = 0; i < m; i++) iwork[i] = N;
13749566063dSJacob Faibussowitsch     PetscCall(PetscViewerBinaryWriteAll(viewer, iwork, m, PETSC_DETERMINE, PETSC_DETERMINE, PETSC_INT));
13758491ab44SLisandro Dalcin     /* store column indices (zero start index) */
13768491ab44SLisandro Dalcin     for (k = 0, i = 0; i < m; i++)
13779371c9d4SSatish Balay       for (j = 0; j < N; j++, k++) iwork[k] = j;
13789566063dSJacob Faibussowitsch     PetscCall(PetscViewerBinaryWriteAll(viewer, iwork, nnz, PETSC_DETERMINE, PETSC_DETERMINE, PETSC_INT));
13799566063dSJacob Faibussowitsch     PetscCall(PetscFree(iwork));
13808491ab44SLisandro Dalcin   }
13818491ab44SLisandro Dalcin   /* store matrix values as a dense matrix in row major order */
13829566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(m * N, &vwork));
13839566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArrayRead(mat, &v));
13849566063dSJacob Faibussowitsch   PetscCall(MatDenseGetLDA(mat, &lda));
13858491ab44SLisandro Dalcin   for (k = 0, i = 0; i < m; i++)
13869371c9d4SSatish Balay     for (j = 0; j < N; j++, k++) vwork[k] = v[i + lda * j];
13879566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArrayRead(mat, &v));
13889566063dSJacob Faibussowitsch   PetscCall(PetscViewerBinaryWriteAll(viewer, vwork, m * N, PETSC_DETERMINE, PETSC_DETERMINE, PETSC_SCALAR));
13899566063dSJacob Faibussowitsch   PetscCall(PetscFree(vwork));
13903ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
13918491ab44SLisandro Dalcin }
13928491ab44SLisandro Dalcin 
1393d71ae5a4SJacob Faibussowitsch PetscErrorCode MatLoad_Dense_Binary(Mat mat, PetscViewer viewer)
1394d71ae5a4SJacob Faibussowitsch {
13958491ab44SLisandro Dalcin   PetscBool    skipHeader;
13968491ab44SLisandro Dalcin   PetscInt     header[4], M, N, m, nz, lda, i, j, k;
13978491ab44SLisandro Dalcin   PetscInt     rows, cols;
13988491ab44SLisandro Dalcin   PetscScalar *v, *vwork;
13998491ab44SLisandro Dalcin 
14008491ab44SLisandro Dalcin   PetscFunctionBegin;
14019566063dSJacob Faibussowitsch   PetscCall(PetscViewerSetUp(viewer));
14029566063dSJacob Faibussowitsch   PetscCall(PetscViewerBinaryGetSkipHeader(viewer, &skipHeader));
14038491ab44SLisandro Dalcin 
14048491ab44SLisandro Dalcin   if (!skipHeader) {
14059566063dSJacob Faibussowitsch     PetscCall(PetscViewerBinaryRead(viewer, header, 4, NULL, PETSC_INT));
140608401ef6SPierre Jolivet     PetscCheck(header[0] == MAT_FILE_CLASSID, PetscObjectComm((PetscObject)viewer), PETSC_ERR_FILE_UNEXPECTED, "Not a matrix object in file");
14079371c9d4SSatish Balay     M = header[1];
14089371c9d4SSatish Balay     N = header[2];
140908401ef6SPierre Jolivet     PetscCheck(M >= 0, PetscObjectComm((PetscObject)viewer), PETSC_ERR_FILE_UNEXPECTED, "Matrix row size (%" PetscInt_FMT ") in file is negative", M);
141008401ef6SPierre Jolivet     PetscCheck(N >= 0, PetscObjectComm((PetscObject)viewer), PETSC_ERR_FILE_UNEXPECTED, "Matrix column size (%" PetscInt_FMT ") in file is negative", N);
14118491ab44SLisandro Dalcin     nz = header[3];
1412aed4548fSBarry Smith     PetscCheck(nz == MATRIX_BINARY_FORMAT_DENSE || nz >= 0, PetscObjectComm((PetscObject)viewer), PETSC_ERR_FILE_UNEXPECTED, "Unknown matrix format %" PetscInt_FMT " in file", nz);
1413aabbc4fbSShri Abhyankar   } else {
14149566063dSJacob Faibussowitsch     PetscCall(MatGetSize(mat, &M, &N));
1415aed4548fSBarry Smith     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");
14168491ab44SLisandro Dalcin     nz = MATRIX_BINARY_FORMAT_DENSE;
1417e6324fbbSBarry Smith   }
1418aabbc4fbSShri Abhyankar 
14198491ab44SLisandro Dalcin   /* setup global sizes if not set */
14208491ab44SLisandro Dalcin   if (mat->rmap->N < 0) mat->rmap->N = M;
14218491ab44SLisandro Dalcin   if (mat->cmap->N < 0) mat->cmap->N = N;
14229566063dSJacob Faibussowitsch   PetscCall(MatSetUp(mat));
14238491ab44SLisandro Dalcin   /* check if global sizes are correct */
14249566063dSJacob Faibussowitsch   PetscCall(MatGetSize(mat, &rows, &cols));
1425aed4548fSBarry Smith   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);
1426aabbc4fbSShri Abhyankar 
14279566063dSJacob Faibussowitsch   PetscCall(MatGetSize(mat, NULL, &N));
14289566063dSJacob Faibussowitsch   PetscCall(MatGetLocalSize(mat, &m, NULL));
14299566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArray(mat, &v));
14309566063dSJacob Faibussowitsch   PetscCall(MatDenseGetLDA(mat, &lda));
14318491ab44SLisandro Dalcin   if (nz == MATRIX_BINARY_FORMAT_DENSE) { /* matrix in file is dense format */
14328491ab44SLisandro Dalcin     PetscInt nnz = m * N;
14338491ab44SLisandro Dalcin     /* read in matrix values */
14349566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(nnz, &vwork));
14359566063dSJacob Faibussowitsch     PetscCall(PetscViewerBinaryReadAll(viewer, vwork, nnz, PETSC_DETERMINE, PETSC_DETERMINE, PETSC_SCALAR));
14368491ab44SLisandro Dalcin     /* store values in column major order */
14378491ab44SLisandro Dalcin     for (j = 0; j < N; j++)
14389371c9d4SSatish Balay       for (i = 0; i < m; i++) v[i + lda * j] = vwork[i * N + j];
14399566063dSJacob Faibussowitsch     PetscCall(PetscFree(vwork));
14408491ab44SLisandro Dalcin   } else { /* matrix in file is sparse format */
14418491ab44SLisandro Dalcin     PetscInt nnz = 0, *rlens, *icols;
14428491ab44SLisandro Dalcin     /* read in row lengths */
14439566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(m, &rlens));
14449566063dSJacob Faibussowitsch     PetscCall(PetscViewerBinaryReadAll(viewer, rlens, m, PETSC_DETERMINE, PETSC_DETERMINE, PETSC_INT));
14458491ab44SLisandro Dalcin     for (i = 0; i < m; i++) nnz += rlens[i];
14468491ab44SLisandro Dalcin     /* read in column indices and values */
14479566063dSJacob Faibussowitsch     PetscCall(PetscMalloc2(nnz, &icols, nnz, &vwork));
14489566063dSJacob Faibussowitsch     PetscCall(PetscViewerBinaryReadAll(viewer, icols, nnz, PETSC_DETERMINE, PETSC_DETERMINE, PETSC_INT));
14499566063dSJacob Faibussowitsch     PetscCall(PetscViewerBinaryReadAll(viewer, vwork, nnz, PETSC_DETERMINE, PETSC_DETERMINE, PETSC_SCALAR));
14508491ab44SLisandro Dalcin     /* store values in column major order */
14518491ab44SLisandro Dalcin     for (k = 0, i = 0; i < m; i++)
14529371c9d4SSatish Balay       for (j = 0; j < rlens[i]; j++, k++) v[i + lda * icols[k]] = vwork[k];
14539566063dSJacob Faibussowitsch     PetscCall(PetscFree(rlens));
14549566063dSJacob Faibussowitsch     PetscCall(PetscFree2(icols, vwork));
1455aabbc4fbSShri Abhyankar   }
14569566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArray(mat, &v));
14579566063dSJacob Faibussowitsch   PetscCall(MatAssemblyBegin(mat, MAT_FINAL_ASSEMBLY));
14589566063dSJacob Faibussowitsch   PetscCall(MatAssemblyEnd(mat, MAT_FINAL_ASSEMBLY));
14593ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1460aabbc4fbSShri Abhyankar }
1461aabbc4fbSShri Abhyankar 
1462d71ae5a4SJacob Faibussowitsch PetscErrorCode MatLoad_SeqDense(Mat newMat, PetscViewer viewer)
1463d71ae5a4SJacob Faibussowitsch {
1464eb91f321SVaclav Hapla   PetscBool isbinary, ishdf5;
1465eb91f321SVaclav Hapla 
1466eb91f321SVaclav Hapla   PetscFunctionBegin;
1467eb91f321SVaclav Hapla   PetscValidHeaderSpecific(newMat, MAT_CLASSID, 1);
1468eb91f321SVaclav Hapla   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
1469eb91f321SVaclav Hapla   /* force binary viewer to load .info file if it has not yet done so */
14709566063dSJacob Faibussowitsch   PetscCall(PetscViewerSetUp(viewer));
14719566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERBINARY, &isbinary));
14729566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5));
1473eb91f321SVaclav Hapla   if (isbinary) {
14749566063dSJacob Faibussowitsch     PetscCall(MatLoad_Dense_Binary(newMat, viewer));
1475eb91f321SVaclav Hapla   } else if (ishdf5) {
1476eb91f321SVaclav Hapla #if defined(PETSC_HAVE_HDF5)
14779566063dSJacob Faibussowitsch     PetscCall(MatLoad_Dense_HDF5(newMat, viewer));
1478eb91f321SVaclav Hapla #else
1479eb91f321SVaclav Hapla     SETERRQ(PetscObjectComm((PetscObject)newMat), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5");
1480eb91f321SVaclav Hapla #endif
1481eb91f321SVaclav Hapla   } else {
148298921bdaSJacob Faibussowitsch     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);
1483eb91f321SVaclav Hapla   }
14843ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1485eb91f321SVaclav Hapla }
1486eb91f321SVaclav Hapla 
1487d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatView_SeqDense_ASCII(Mat A, PetscViewer viewer)
1488d71ae5a4SJacob Faibussowitsch {
1489932b0c3eSLois Curfman McInnes   Mat_SeqDense     *a = (Mat_SeqDense *)A->data;
149013f74950SBarry Smith   PetscInt          i, j;
14912dcb1b2aSMatthew Knepley   const char       *name;
1492ca15aa20SStefano Zampini   PetscScalar      *v, *av;
1493f3ef73ceSBarry Smith   PetscViewerFormat format;
14945f481a85SSatish Balay #if defined(PETSC_USE_COMPLEX)
1495ace3abfcSBarry Smith   PetscBool allreal = PETSC_TRUE;
14965f481a85SSatish Balay #endif
1497932b0c3eSLois Curfman McInnes 
14983a40ed3dSBarry Smith   PetscFunctionBegin;
14999566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArrayRead(A, (const PetscScalar **)&av));
15009566063dSJacob Faibussowitsch   PetscCall(PetscViewerGetFormat(viewer, &format));
1501456192e2SBarry Smith   if (format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL) {
15023ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS); /* do nothing for now */
1503fb9695e5SSatish Balay   } else if (format == PETSC_VIEWER_ASCII_COMMON) {
15049566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIUseTabs(viewer, PETSC_FALSE));
1505d0f46423SBarry Smith     for (i = 0; i < A->rmap->n; i++) {
1506ca15aa20SStefano Zampini       v = av + i;
15079566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "row %" PetscInt_FMT ":", i));
1508d0f46423SBarry Smith       for (j = 0; j < A->cmap->n; j++) {
1509aa482453SBarry Smith #if defined(PETSC_USE_COMPLEX)
1510329f5518SBarry Smith         if (PetscRealPart(*v) != 0.0 && PetscImaginaryPart(*v) != 0.0) {
15119566063dSJacob Faibussowitsch           PetscCall(PetscViewerASCIIPrintf(viewer, " (%" PetscInt_FMT ", %g + %g i) ", j, (double)PetscRealPart(*v), (double)PetscImaginaryPart(*v)));
1512329f5518SBarry Smith         } else if (PetscRealPart(*v)) {
15139566063dSJacob Faibussowitsch           PetscCall(PetscViewerASCIIPrintf(viewer, " (%" PetscInt_FMT ", %g) ", j, (double)PetscRealPart(*v)));
15146831982aSBarry Smith         }
151580cd9d93SLois Curfman McInnes #else
151648a46eb9SPierre Jolivet         if (*v) PetscCall(PetscViewerASCIIPrintf(viewer, " (%" PetscInt_FMT ", %g) ", j, (double)*v));
151780cd9d93SLois Curfman McInnes #endif
15181b807ce4Svictorle         v += a->lda;
151980cd9d93SLois Curfman McInnes       }
15209566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "\n"));
152180cd9d93SLois Curfman McInnes     }
15229566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIUseTabs(viewer, PETSC_TRUE));
15233a40ed3dSBarry Smith   } else {
15249566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIUseTabs(viewer, PETSC_FALSE));
1525aa482453SBarry Smith #if defined(PETSC_USE_COMPLEX)
152647989497SBarry Smith     /* determine if matrix has all real values */
1527bcd8d3a4SJose E. Roman     for (j = 0; j < A->cmap->n; j++) {
1528bcd8d3a4SJose E. Roman       v = av + j * a->lda;
1529bcd8d3a4SJose E. Roman       for (i = 0; i < A->rmap->n; i++) {
15309371c9d4SSatish Balay         if (PetscImaginaryPart(v[i])) {
15319371c9d4SSatish Balay           allreal = PETSC_FALSE;
15329371c9d4SSatish Balay           break;
15339371c9d4SSatish Balay         }
153447989497SBarry Smith       }
1535bcd8d3a4SJose E. Roman     }
153647989497SBarry Smith #endif
1537fb9695e5SSatish Balay     if (format == PETSC_VIEWER_ASCII_MATLAB) {
15389566063dSJacob Faibussowitsch       PetscCall(PetscObjectGetName((PetscObject)A, &name));
15399566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "%% Size = %" PetscInt_FMT " %" PetscInt_FMT " \n", A->rmap->n, A->cmap->n));
15409566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "%s = zeros(%" PetscInt_FMT ",%" PetscInt_FMT ");\n", name, A->rmap->n, A->cmap->n));
15419566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "%s = [\n", name));
1542ffac6cdbSBarry Smith     }
1543ffac6cdbSBarry Smith 
1544d0f46423SBarry Smith     for (i = 0; i < A->rmap->n; i++) {
1545ca15aa20SStefano Zampini       v = av + i;
1546d0f46423SBarry Smith       for (j = 0; j < A->cmap->n; j++) {
1547aa482453SBarry Smith #if defined(PETSC_USE_COMPLEX)
154847989497SBarry Smith         if (allreal) {
15499566063dSJacob Faibussowitsch           PetscCall(PetscViewerASCIIPrintf(viewer, "%18.16e ", (double)PetscRealPart(*v)));
155047989497SBarry Smith         } else {
15519566063dSJacob Faibussowitsch           PetscCall(PetscViewerASCIIPrintf(viewer, "%18.16e + %18.16ei ", (double)PetscRealPart(*v), (double)PetscImaginaryPart(*v)));
155247989497SBarry Smith         }
1553289bc588SBarry Smith #else
15549566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, "%18.16e ", (double)*v));
1555289bc588SBarry Smith #endif
15561b807ce4Svictorle         v += a->lda;
1557289bc588SBarry Smith       }
15589566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "\n"));
1559289bc588SBarry Smith     }
156048a46eb9SPierre Jolivet     if (format == PETSC_VIEWER_ASCII_MATLAB) PetscCall(PetscViewerASCIIPrintf(viewer, "];\n"));
15619566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIUseTabs(viewer, PETSC_TRUE));
1562da3a660dSBarry Smith   }
15639566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArrayRead(A, (const PetscScalar **)&av));
15649566063dSJacob Faibussowitsch   PetscCall(PetscViewerFlush(viewer));
15653ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1566289bc588SBarry Smith }
1567289bc588SBarry Smith 
15689804daf3SBarry Smith #include <petscdraw.h>
1569d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatView_SeqDense_Draw_Zoom(PetscDraw draw, void *Aa)
1570d71ae5a4SJacob Faibussowitsch {
1571f1af5d2fSBarry Smith   Mat                A = (Mat)Aa;
1572383922c3SLisandro Dalcin   PetscInt           m = A->rmap->n, n = A->cmap->n, i, j;
1573383922c3SLisandro Dalcin   int                color = PETSC_DRAW_WHITE;
1574ca15aa20SStefano Zampini   const PetscScalar *v;
1575b0a32e0cSBarry Smith   PetscViewer        viewer;
1576b05fc000SLisandro Dalcin   PetscReal          xl, yl, xr, yr, x_l, x_r, y_l, y_r;
1577f3ef73ceSBarry Smith   PetscViewerFormat  format;
1578f1af5d2fSBarry Smith 
1579f1af5d2fSBarry Smith   PetscFunctionBegin;
15809566063dSJacob Faibussowitsch   PetscCall(PetscObjectQuery((PetscObject)A, "Zoomviewer", (PetscObject *)&viewer));
15819566063dSJacob Faibussowitsch   PetscCall(PetscViewerGetFormat(viewer, &format));
15829566063dSJacob Faibussowitsch   PetscCall(PetscDrawGetCoordinates(draw, &xl, &yl, &xr, &yr));
1583f1af5d2fSBarry Smith 
1584f1af5d2fSBarry Smith   /* Loop over matrix elements drawing boxes */
15859566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArrayRead(A, &v));
1586fb9695e5SSatish Balay   if (format != PETSC_VIEWER_DRAW_CONTOUR) {
1587d0609cedSBarry Smith     PetscDrawCollectiveBegin(draw);
1588f1af5d2fSBarry Smith     /* Blue for negative and Red for positive */
1589f1af5d2fSBarry Smith     for (j = 0; j < n; j++) {
15909371c9d4SSatish Balay       x_l = j;
15919371c9d4SSatish Balay       x_r = x_l + 1.0;
1592f1af5d2fSBarry Smith       for (i = 0; i < m; i++) {
1593f1af5d2fSBarry Smith         y_l = m - i - 1.0;
1594f1af5d2fSBarry Smith         y_r = y_l + 1.0;
1595ca15aa20SStefano Zampini         if (PetscRealPart(v[j * m + i]) > 0.) color = PETSC_DRAW_RED;
1596ca15aa20SStefano Zampini         else if (PetscRealPart(v[j * m + i]) < 0.) color = PETSC_DRAW_BLUE;
1597ca15aa20SStefano Zampini         else continue;
15989566063dSJacob Faibussowitsch         PetscCall(PetscDrawRectangle(draw, x_l, y_l, x_r, y_r, color, color, color, color));
1599f1af5d2fSBarry Smith       }
1600f1af5d2fSBarry Smith     }
1601d0609cedSBarry Smith     PetscDrawCollectiveEnd(draw);
1602f1af5d2fSBarry Smith   } else {
1603f1af5d2fSBarry Smith     /* use contour shading to indicate magnitude of values */
1604f1af5d2fSBarry Smith     /* first determine max of all nonzero values */
1605b05fc000SLisandro Dalcin     PetscReal minv = 0.0, maxv = 0.0;
1606b05fc000SLisandro Dalcin     PetscDraw popup;
1607b05fc000SLisandro Dalcin 
1608f1af5d2fSBarry Smith     for (i = 0; i < m * n; i++) {
1609f1af5d2fSBarry Smith       if (PetscAbsScalar(v[i]) > maxv) maxv = PetscAbsScalar(v[i]);
1610f1af5d2fSBarry Smith     }
1611383922c3SLisandro Dalcin     if (minv >= maxv) maxv = minv + PETSC_SMALL;
16129566063dSJacob Faibussowitsch     PetscCall(PetscDrawGetPopup(draw, &popup));
16139566063dSJacob Faibussowitsch     PetscCall(PetscDrawScalePopup(popup, minv, maxv));
1614383922c3SLisandro Dalcin 
1615d0609cedSBarry Smith     PetscDrawCollectiveBegin(draw);
1616f1af5d2fSBarry Smith     for (j = 0; j < n; j++) {
1617f1af5d2fSBarry Smith       x_l = j;
1618f1af5d2fSBarry Smith       x_r = x_l + 1.0;
1619f1af5d2fSBarry Smith       for (i = 0; i < m; i++) {
1620f1af5d2fSBarry Smith         y_l   = m - i - 1.0;
1621f1af5d2fSBarry Smith         y_r   = y_l + 1.0;
1622b05fc000SLisandro Dalcin         color = PetscDrawRealToColor(PetscAbsScalar(v[j * m + i]), minv, maxv);
16239566063dSJacob Faibussowitsch         PetscCall(PetscDrawRectangle(draw, x_l, y_l, x_r, y_r, color, color, color, color));
1624f1af5d2fSBarry Smith       }
1625f1af5d2fSBarry Smith     }
1626d0609cedSBarry Smith     PetscDrawCollectiveEnd(draw);
1627f1af5d2fSBarry Smith   }
16289566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArrayRead(A, &v));
16293ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1630f1af5d2fSBarry Smith }
1631f1af5d2fSBarry Smith 
1632d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatView_SeqDense_Draw(Mat A, PetscViewer viewer)
1633d71ae5a4SJacob Faibussowitsch {
1634b0a32e0cSBarry Smith   PetscDraw draw;
1635ace3abfcSBarry Smith   PetscBool isnull;
1636329f5518SBarry Smith   PetscReal xr, yr, xl, yl, h, w;
1637f1af5d2fSBarry Smith 
1638f1af5d2fSBarry Smith   PetscFunctionBegin;
16399566063dSJacob Faibussowitsch   PetscCall(PetscViewerDrawGetDraw(viewer, 0, &draw));
16409566063dSJacob Faibussowitsch   PetscCall(PetscDrawIsNull(draw, &isnull));
16413ba16761SJacob Faibussowitsch   if (isnull) PetscFunctionReturn(PETSC_SUCCESS);
1642f1af5d2fSBarry Smith 
16439371c9d4SSatish Balay   xr = A->cmap->n;
16449371c9d4SSatish Balay   yr = A->rmap->n;
16459371c9d4SSatish Balay   h  = yr / 10.0;
16469371c9d4SSatish Balay   w  = xr / 10.0;
16479371c9d4SSatish Balay   xr += w;
16489371c9d4SSatish Balay   yr += h;
16499371c9d4SSatish Balay   xl = -w;
16509371c9d4SSatish Balay   yl = -h;
16519566063dSJacob Faibussowitsch   PetscCall(PetscDrawSetCoordinates(draw, xl, yl, xr, yr));
16529566063dSJacob Faibussowitsch   PetscCall(PetscObjectCompose((PetscObject)A, "Zoomviewer", (PetscObject)viewer));
16539566063dSJacob Faibussowitsch   PetscCall(PetscDrawZoom(draw, MatView_SeqDense_Draw_Zoom, A));
16549566063dSJacob Faibussowitsch   PetscCall(PetscObjectCompose((PetscObject)A, "Zoomviewer", NULL));
16559566063dSJacob Faibussowitsch   PetscCall(PetscDrawSave(draw));
16563ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1657f1af5d2fSBarry Smith }
1658f1af5d2fSBarry Smith 
1659d71ae5a4SJacob Faibussowitsch PetscErrorCode MatView_SeqDense(Mat A, PetscViewer viewer)
1660d71ae5a4SJacob Faibussowitsch {
1661ace3abfcSBarry Smith   PetscBool iascii, isbinary, isdraw;
1662932b0c3eSLois Curfman McInnes 
16633a40ed3dSBarry Smith   PetscFunctionBegin;
16649566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
16659566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERBINARY, &isbinary));
16669566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERDRAW, &isdraw));
16671baa6e33SBarry Smith   if (iascii) PetscCall(MatView_SeqDense_ASCII(A, viewer));
16681baa6e33SBarry Smith   else if (isbinary) PetscCall(MatView_Dense_Binary(A, viewer));
16691baa6e33SBarry Smith   else if (isdraw) PetscCall(MatView_SeqDense_Draw(A, viewer));
16703ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1671932b0c3eSLois Curfman McInnes }
1672289bc588SBarry Smith 
1673d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatDensePlaceArray_SeqDense(Mat A, const PetscScalar *array)
1674d71ae5a4SJacob Faibussowitsch {
1675d3042a70SBarry Smith   Mat_SeqDense *a = (Mat_SeqDense *)A->data;
1676d3042a70SBarry Smith 
1677d3042a70SBarry Smith   PetscFunctionBegin;
167828b400f6SJacob Faibussowitsch   PetscCheck(!a->vecinuse, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Need to call MatDenseRestoreColumnVec() first");
167928b400f6SJacob Faibussowitsch   PetscCheck(!a->matinuse, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Need to call MatDenseRestoreSubMatrix() first");
168028b400f6SJacob Faibussowitsch   PetscCheck(!a->unplacedarray, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Need to call MatDenseRestoreArray() first");
1681d3042a70SBarry Smith   a->unplacedarray       = a->v;
1682d3042a70SBarry Smith   a->unplaced_user_alloc = a->user_alloc;
1683d3042a70SBarry Smith   a->v                   = (PetscScalar *)array;
1684637a0070SStefano Zampini   a->user_alloc          = PETSC_TRUE;
168547d993e7Ssuyashtn #if defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
1686c70f7ee4SJunchao Zhang   A->offloadmask = PETSC_OFFLOAD_CPU;
1687ca15aa20SStefano Zampini #endif
16883ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1689d3042a70SBarry Smith }
1690d3042a70SBarry Smith 
1691d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatDenseResetArray_SeqDense(Mat A)
1692d71ae5a4SJacob Faibussowitsch {
1693d3042a70SBarry Smith   Mat_SeqDense *a = (Mat_SeqDense *)A->data;
1694d3042a70SBarry Smith 
1695d3042a70SBarry Smith   PetscFunctionBegin;
169628b400f6SJacob Faibussowitsch   PetscCheck(!a->vecinuse, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Need to call MatDenseRestoreColumnVec() first");
169728b400f6SJacob Faibussowitsch   PetscCheck(!a->matinuse, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Need to call MatDenseRestoreSubMatrix() first");
1698d3042a70SBarry Smith   a->v             = a->unplacedarray;
1699d3042a70SBarry Smith   a->user_alloc    = a->unplaced_user_alloc;
1700d3042a70SBarry Smith   a->unplacedarray = NULL;
170147d993e7Ssuyashtn #if defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
1702c70f7ee4SJunchao Zhang   A->offloadmask = PETSC_OFFLOAD_CPU;
1703ca15aa20SStefano Zampini #endif
17043ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1705d3042a70SBarry Smith }
1706d3042a70SBarry Smith 
1707d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatDenseReplaceArray_SeqDense(Mat A, const PetscScalar *array)
1708d71ae5a4SJacob Faibussowitsch {
1709d5ea218eSStefano Zampini   Mat_SeqDense *a = (Mat_SeqDense *)A->data;
1710d5ea218eSStefano Zampini 
1711d5ea218eSStefano Zampini   PetscFunctionBegin;
171228b400f6SJacob Faibussowitsch   PetscCheck(!a->vecinuse, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Need to call MatDenseRestoreColumnVec() first");
171328b400f6SJacob Faibussowitsch   PetscCheck(!a->matinuse, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Need to call MatDenseRestoreSubMatrix() first");
17149566063dSJacob Faibussowitsch   if (!a->user_alloc) PetscCall(PetscFree(a->v));
1715d5ea218eSStefano Zampini   a->v          = (PetscScalar *)array;
1716d5ea218eSStefano Zampini   a->user_alloc = PETSC_FALSE;
171747d993e7Ssuyashtn #if defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
1718d5ea218eSStefano Zampini   A->offloadmask = PETSC_OFFLOAD_CPU;
1719d5ea218eSStefano Zampini #endif
17203ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1721d5ea218eSStefano Zampini }
1722d5ea218eSStefano Zampini 
1723d71ae5a4SJacob Faibussowitsch PetscErrorCode MatDestroy_SeqDense(Mat mat)
1724d71ae5a4SJacob Faibussowitsch {
1725ec8511deSBarry Smith   Mat_SeqDense *l = (Mat_SeqDense *)mat->data;
172690f02eecSBarry Smith 
17273a40ed3dSBarry Smith   PetscFunctionBegin;
1728aa482453SBarry Smith #if defined(PETSC_USE_LOG)
17293ba16761SJacob Faibussowitsch   PetscCall(PetscLogObjectState((PetscObject)mat, "Rows %" PetscInt_FMT " Cols %" PetscInt_FMT, mat->rmap->n, mat->cmap->n));
1730a5a9c739SBarry Smith #endif
17319566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&(l->qrrhs)));
17329566063dSJacob Faibussowitsch   PetscCall(PetscFree(l->tau));
17339566063dSJacob Faibussowitsch   PetscCall(PetscFree(l->pivots));
17349566063dSJacob Faibussowitsch   PetscCall(PetscFree(l->fwork));
17359566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&l->ptapwork));
17369566063dSJacob Faibussowitsch   if (!l->user_alloc) PetscCall(PetscFree(l->v));
17379566063dSJacob Faibussowitsch   if (!l->unplaced_user_alloc) PetscCall(PetscFree(l->unplacedarray));
173828b400f6SJacob Faibussowitsch   PetscCheck(!l->vecinuse, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Need to call MatDenseRestoreColumnVec() first");
173928b400f6SJacob Faibussowitsch   PetscCheck(!l->matinuse, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Need to call MatDenseRestoreSubMatrix() first");
17409566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&l->cvec));
17419566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&l->cmat));
17429566063dSJacob Faibussowitsch   PetscCall(PetscFree(mat->data));
1743dbd8c25aSHong Zhang 
17449566063dSJacob Faibussowitsch   PetscCall(PetscObjectChangeTypeName((PetscObject)mat, NULL));
17459566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatQRFactor_C", NULL));
17462e956fe4SStefano Zampini   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatQRFactorSymbolic_C", NULL));
17472e956fe4SStefano Zampini   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatQRFactorNumeric_C", NULL));
17489566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatDenseGetLDA_C", NULL));
17499566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatDenseSetLDA_C", NULL));
17509566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatDenseGetArray_C", NULL));
17519566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatDenseRestoreArray_C", NULL));
17529566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatDensePlaceArray_C", NULL));
17539566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatDenseResetArray_C", NULL));
17549566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatDenseReplaceArray_C", NULL));
17559566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatDenseGetArrayRead_C", NULL));
17569566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatDenseRestoreArrayRead_C", NULL));
17579566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatDenseGetArrayWrite_C", NULL));
17589566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatDenseRestoreArrayWrite_C", NULL));
17599566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatConvert_seqdense_seqaij_C", NULL));
17608baccfbdSHong Zhang #if defined(PETSC_HAVE_ELEMENTAL)
17619566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatConvert_seqdense_elemental_C", NULL));
17628baccfbdSHong Zhang #endif
1763d24d4204SJose E. Roman #if defined(PETSC_HAVE_SCALAPACK)
17649566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatConvert_seqdense_scalapack_C", NULL));
1765d24d4204SJose E. Roman #endif
17662bf066beSStefano Zampini #if defined(PETSC_HAVE_CUDA)
17679566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatConvert_seqdense_seqdensecuda_C", NULL));
17689566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatProductSetFromOptions_seqdensecuda_seqdensecuda_C", NULL));
17699566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatProductSetFromOptions_seqdensecuda_seqdense_C", NULL));
17702e956fe4SStefano Zampini   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatProductSetFromOptions_seqdense_seqdensecuda_C", NULL));
17712bf066beSStefano Zampini #endif
177247d993e7Ssuyashtn #if defined(PETSC_HAVE_HIP)
177347d993e7Ssuyashtn   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatConvert_seqdense_seqdensehip_C", NULL));
177447d993e7Ssuyashtn   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatProductSetFromOptions_seqdensehip_seqdensehip_C", NULL));
177547d993e7Ssuyashtn   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatProductSetFromOptions_seqdensehip_seqdense_C", NULL));
177647d993e7Ssuyashtn   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatProductSetFromOptions_seqdense_seqdensehip_C", NULL));
177747d993e7Ssuyashtn #endif
17789566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatSeqDenseSetPreallocation_C", NULL));
17799566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatProductSetFromOptions_seqaij_seqdense_C", NULL));
17809566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatProductSetFromOptions_seqdense_seqdense_C", NULL));
17819566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatProductSetFromOptions_seqbaij_seqdense_C", NULL));
17829566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatProductSetFromOptions_seqsbaij_seqdense_C", NULL));
178352c5f739Sprj- 
17849566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatDenseGetColumn_C", NULL));
17859566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatDenseRestoreColumn_C", NULL));
17869566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatDenseGetColumnVec_C", NULL));
17879566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatDenseRestoreColumnVec_C", NULL));
17889566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatDenseGetColumnVecRead_C", NULL));
17899566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatDenseRestoreColumnVecRead_C", NULL));
17909566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatDenseGetColumnVecWrite_C", NULL));
17919566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatDenseRestoreColumnVecWrite_C", NULL));
17929566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatDenseGetSubMatrix_C", NULL));
17939566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatDenseRestoreSubMatrix_C", NULL));
17943ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1795289bc588SBarry Smith }
1796289bc588SBarry Smith 
1797d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatTranspose_SeqDense(Mat A, MatReuse reuse, Mat *matout)
1798d71ae5a4SJacob Faibussowitsch {
1799c0bbcb79SLois Curfman McInnes   Mat_SeqDense *mat = (Mat_SeqDense *)A->data;
18006536e3caSStefano Zampini   PetscInt      k, j, m = A->rmap->n, M = mat->lda, n = A->cmap->n;
180187828ca2SBarry Smith   PetscScalar  *v, tmp;
180248b35521SBarry Smith 
18033a40ed3dSBarry Smith   PetscFunctionBegin;
18047fb60732SBarry Smith   if (reuse == MAT_REUSE_MATRIX) PetscCall(MatTransposeCheckNonzeroState_Private(A, *matout));
18056536e3caSStefano Zampini   if (reuse == MAT_INPLACE_MATRIX) {
18066536e3caSStefano Zampini     if (m == n) { /* in place transpose */
18079566063dSJacob Faibussowitsch       PetscCall(MatDenseGetArray(A, &v));
1808d3e5ee88SLois Curfman McInnes       for (j = 0; j < m; j++) {
1809289bc588SBarry Smith         for (k = 0; k < j; k++) {
18101b807ce4Svictorle           tmp          = v[j + k * M];
18111b807ce4Svictorle           v[j + k * M] = v[k + j * M];
18121b807ce4Svictorle           v[k + j * M] = tmp;
1813289bc588SBarry Smith         }
1814289bc588SBarry Smith       }
18159566063dSJacob Faibussowitsch       PetscCall(MatDenseRestoreArray(A, &v));
18166536e3caSStefano Zampini     } else { /* reuse memory, temporary allocates new memory */
18176536e3caSStefano Zampini       PetscScalar *v2;
18186536e3caSStefano Zampini       PetscLayout  tmplayout;
18196536e3caSStefano Zampini 
18209566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1((size_t)m * n, &v2));
18219566063dSJacob Faibussowitsch       PetscCall(MatDenseGetArray(A, &v));
18226536e3caSStefano Zampini       for (j = 0; j < n; j++) {
18236536e3caSStefano Zampini         for (k = 0; k < m; k++) v2[j + (size_t)k * n] = v[k + (size_t)j * M];
18246536e3caSStefano Zampini       }
18259566063dSJacob Faibussowitsch       PetscCall(PetscArraycpy(v, v2, (size_t)m * n));
18269566063dSJacob Faibussowitsch       PetscCall(PetscFree(v2));
18279566063dSJacob Faibussowitsch       PetscCall(MatDenseRestoreArray(A, &v));
18286536e3caSStefano Zampini       /* cleanup size dependent quantities */
18299566063dSJacob Faibussowitsch       PetscCall(VecDestroy(&mat->cvec));
18309566063dSJacob Faibussowitsch       PetscCall(MatDestroy(&mat->cmat));
18319566063dSJacob Faibussowitsch       PetscCall(PetscFree(mat->pivots));
18329566063dSJacob Faibussowitsch       PetscCall(PetscFree(mat->fwork));
18339566063dSJacob Faibussowitsch       PetscCall(MatDestroy(&mat->ptapwork));
18346536e3caSStefano Zampini       /* swap row/col layouts */
18356536e3caSStefano Zampini       mat->lda  = n;
18366536e3caSStefano Zampini       tmplayout = A->rmap;
18376536e3caSStefano Zampini       A->rmap   = A->cmap;
18386536e3caSStefano Zampini       A->cmap   = tmplayout;
18396536e3caSStefano Zampini     }
18403a40ed3dSBarry Smith   } else { /* out-of-place transpose */
1841d3e5ee88SLois Curfman McInnes     Mat           tmat;
1842ec8511deSBarry Smith     Mat_SeqDense *tmatd;
184387828ca2SBarry Smith     PetscScalar  *v2;
1844af36a384SStefano Zampini     PetscInt      M2;
1845ea709b57SSatish Balay 
18466536e3caSStefano Zampini     if (reuse == MAT_INITIAL_MATRIX) {
18479566063dSJacob Faibussowitsch       PetscCall(MatCreate(PetscObjectComm((PetscObject)A), &tmat));
18489566063dSJacob Faibussowitsch       PetscCall(MatSetSizes(tmat, A->cmap->n, A->rmap->n, A->cmap->n, A->rmap->n));
18499566063dSJacob Faibussowitsch       PetscCall(MatSetType(tmat, ((PetscObject)A)->type_name));
18509566063dSJacob Faibussowitsch       PetscCall(MatSeqDenseSetPreallocation(tmat, NULL));
1851ca15aa20SStefano Zampini     } else tmat = *matout;
1852ca15aa20SStefano Zampini 
18539566063dSJacob Faibussowitsch     PetscCall(MatDenseGetArrayRead(A, (const PetscScalar **)&v));
18549566063dSJacob Faibussowitsch     PetscCall(MatDenseGetArray(tmat, &v2));
1855ec8511deSBarry Smith     tmatd = (Mat_SeqDense *)tmat->data;
1856ca15aa20SStefano Zampini     M2    = tmatd->lda;
1857d3e5ee88SLois Curfman McInnes     for (j = 0; j < n; j++) {
1858af36a384SStefano Zampini       for (k = 0; k < m; k++) v2[j + k * M2] = v[k + j * M];
1859d3e5ee88SLois Curfman McInnes     }
18609566063dSJacob Faibussowitsch     PetscCall(MatDenseRestoreArray(tmat, &v2));
18619566063dSJacob Faibussowitsch     PetscCall(MatDenseRestoreArrayRead(A, (const PetscScalar **)&v));
18629566063dSJacob Faibussowitsch     PetscCall(MatAssemblyBegin(tmat, MAT_FINAL_ASSEMBLY));
18639566063dSJacob Faibussowitsch     PetscCall(MatAssemblyEnd(tmat, MAT_FINAL_ASSEMBLY));
18646536e3caSStefano Zampini     *matout = tmat;
186548b35521SBarry Smith   }
18663ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1867289bc588SBarry Smith }
1868289bc588SBarry Smith 
1869d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatEqual_SeqDense(Mat A1, Mat A2, PetscBool *flg)
1870d71ae5a4SJacob Faibussowitsch {
1871c0bbcb79SLois Curfman McInnes   Mat_SeqDense      *mat1 = (Mat_SeqDense *)A1->data;
1872c0bbcb79SLois Curfman McInnes   Mat_SeqDense      *mat2 = (Mat_SeqDense *)A2->data;
1873ca15aa20SStefano Zampini   PetscInt           i;
1874ca15aa20SStefano Zampini   const PetscScalar *v1, *v2;
18759ea5d5aeSSatish Balay 
18763a40ed3dSBarry Smith   PetscFunctionBegin;
18779371c9d4SSatish Balay   if (A1->rmap->n != A2->rmap->n) {
18789371c9d4SSatish Balay     *flg = PETSC_FALSE;
18793ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
18809371c9d4SSatish Balay   }
18819371c9d4SSatish Balay   if (A1->cmap->n != A2->cmap->n) {
18829371c9d4SSatish Balay     *flg = PETSC_FALSE;
18833ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
18849371c9d4SSatish Balay   }
18859566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArrayRead(A1, &v1));
18869566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArrayRead(A2, &v2));
1887ca15aa20SStefano Zampini   for (i = 0; i < A1->cmap->n; i++) {
18889566063dSJacob Faibussowitsch     PetscCall(PetscArraycmp(v1, v2, A1->rmap->n, flg));
18893ba16761SJacob Faibussowitsch     if (*flg == PETSC_FALSE) PetscFunctionReturn(PETSC_SUCCESS);
1890ca15aa20SStefano Zampini     v1 += mat1->lda;
1891ca15aa20SStefano Zampini     v2 += mat2->lda;
18921b807ce4Svictorle   }
18939566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArrayRead(A1, &v1));
18949566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArrayRead(A2, &v2));
189577c4ece6SBarry Smith   *flg = PETSC_TRUE;
18963ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1897289bc588SBarry Smith }
1898289bc588SBarry Smith 
1899d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatGetDiagonal_SeqDense(Mat A, Vec v)
1900d71ae5a4SJacob Faibussowitsch {
1901c0bbcb79SLois Curfman McInnes   Mat_SeqDense      *mat = (Mat_SeqDense *)A->data;
190213f74950SBarry Smith   PetscInt           i, n, len;
1903ca15aa20SStefano Zampini   PetscScalar       *x;
1904ca15aa20SStefano Zampini   const PetscScalar *vv;
190544cd7ae7SLois Curfman McInnes 
19063a40ed3dSBarry Smith   PetscFunctionBegin;
19079566063dSJacob Faibussowitsch   PetscCall(VecGetSize(v, &n));
19089566063dSJacob Faibussowitsch   PetscCall(VecGetArray(v, &x));
1909d0f46423SBarry Smith   len = PetscMin(A->rmap->n, A->cmap->n);
19109566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArrayRead(A, &vv));
191108401ef6SPierre Jolivet   PetscCheck(n == A->rmap->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Nonconforming mat and vec");
1912ad540459SPierre Jolivet   for (i = 0; i < len; i++) x[i] = vv[i * mat->lda + i];
19139566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArrayRead(A, &vv));
19149566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(v, &x));
19153ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1916289bc588SBarry Smith }
1917289bc588SBarry Smith 
1918d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatDiagonalScale_SeqDense(Mat A, Vec ll, Vec rr)
1919d71ae5a4SJacob Faibussowitsch {
1920c0bbcb79SLois Curfman McInnes   Mat_SeqDense      *mat = (Mat_SeqDense *)A->data;
1921f1ceaac6SMatthew G. Knepley   const PetscScalar *l, *r;
1922ca15aa20SStefano Zampini   PetscScalar        x, *v, *vv;
1923d0f46423SBarry Smith   PetscInt           i, j, m = A->rmap->n, n = A->cmap->n;
192455659b69SBarry Smith 
19253a40ed3dSBarry Smith   PetscFunctionBegin;
19269566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArray(A, &vv));
192728988994SBarry Smith   if (ll) {
19289566063dSJacob Faibussowitsch     PetscCall(VecGetSize(ll, &m));
19299566063dSJacob Faibussowitsch     PetscCall(VecGetArrayRead(ll, &l));
193008401ef6SPierre Jolivet     PetscCheck(m == A->rmap->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Left scaling vec wrong size");
1931da3a660dSBarry Smith     for (i = 0; i < m; i++) {
1932da3a660dSBarry Smith       x = l[i];
1933ca15aa20SStefano Zampini       v = vv + i;
19349371c9d4SSatish Balay       for (j = 0; j < n; j++) {
19359371c9d4SSatish Balay         (*v) *= x;
19369371c9d4SSatish Balay         v += mat->lda;
19379371c9d4SSatish Balay       }
1938da3a660dSBarry Smith     }
19399566063dSJacob Faibussowitsch     PetscCall(VecRestoreArrayRead(ll, &l));
19409566063dSJacob Faibussowitsch     PetscCall(PetscLogFlops(1.0 * n * m));
1941da3a660dSBarry Smith   }
194228988994SBarry Smith   if (rr) {
19439566063dSJacob Faibussowitsch     PetscCall(VecGetSize(rr, &n));
19449566063dSJacob Faibussowitsch     PetscCall(VecGetArrayRead(rr, &r));
194508401ef6SPierre Jolivet     PetscCheck(n == A->cmap->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Right scaling vec wrong size");
1946da3a660dSBarry Smith     for (i = 0; i < n; i++) {
1947da3a660dSBarry Smith       x = r[i];
1948ca15aa20SStefano Zampini       v = vv + i * mat->lda;
19492205254eSKarl Rupp       for (j = 0; j < m; j++) (*v++) *= x;
1950da3a660dSBarry Smith     }
19519566063dSJacob Faibussowitsch     PetscCall(VecRestoreArrayRead(rr, &r));
19529566063dSJacob Faibussowitsch     PetscCall(PetscLogFlops(1.0 * n * m));
1953da3a660dSBarry Smith   }
19549566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArray(A, &vv));
19553ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1956289bc588SBarry Smith }
1957289bc588SBarry Smith 
1958d71ae5a4SJacob Faibussowitsch PetscErrorCode MatNorm_SeqDense(Mat A, NormType type, PetscReal *nrm)
1959d71ae5a4SJacob Faibussowitsch {
1960c0bbcb79SLois Curfman McInnes   Mat_SeqDense *mat = (Mat_SeqDense *)A->data;
1961ca15aa20SStefano Zampini   PetscScalar  *v, *vv;
1962329f5518SBarry Smith   PetscReal     sum = 0.0;
196375f6d85dSStefano Zampini   PetscInt      lda, m = A->rmap->n, i, j;
196455659b69SBarry Smith 
19653a40ed3dSBarry Smith   PetscFunctionBegin;
19669566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArrayRead(A, (const PetscScalar **)&vv));
19679566063dSJacob Faibussowitsch   PetscCall(MatDenseGetLDA(A, &lda));
1968ca15aa20SStefano Zampini   v = vv;
1969289bc588SBarry Smith   if (type == NORM_FROBENIUS) {
1970a5ce6ee0Svictorle     if (lda > m) {
1971d0f46423SBarry Smith       for (j = 0; j < A->cmap->n; j++) {
1972ca15aa20SStefano Zampini         v = vv + j * lda;
1973a5ce6ee0Svictorle         for (i = 0; i < m; i++) {
19749371c9d4SSatish Balay           sum += PetscRealPart(PetscConj(*v) * (*v));
19759371c9d4SSatish Balay           v++;
1976a5ce6ee0Svictorle         }
1977a5ce6ee0Svictorle       }
1978a5ce6ee0Svictorle     } else {
1979570b7f6dSBarry Smith #if defined(PETSC_USE_REAL___FP16)
1980570b7f6dSBarry Smith       PetscBLASInt one = 1, cnt = A->cmap->n * A->rmap->n;
1981792fecdfSBarry Smith       PetscCallBLAS("BLASnrm2", *nrm = BLASnrm2_(&cnt, v, &one));
1982570b7f6dSBarry Smith     }
1983570b7f6dSBarry Smith #else
1984d0f46423SBarry Smith       for (i = 0; i < A->cmap->n * A->rmap->n; i++) {
19859371c9d4SSatish Balay         sum += PetscRealPart(PetscConj(*v) * (*v));
19869371c9d4SSatish Balay         v++;
1987289bc588SBarry Smith       }
1988a5ce6ee0Svictorle     }
19898f1a2a5eSBarry Smith     *nrm = PetscSqrtReal(sum);
1990570b7f6dSBarry Smith #endif
19919566063dSJacob Faibussowitsch     PetscCall(PetscLogFlops(2.0 * A->cmap->n * A->rmap->n));
19923a40ed3dSBarry Smith   } else if (type == NORM_1) {
1993064f8208SBarry Smith     *nrm = 0.0;
1994d0f46423SBarry Smith     for (j = 0; j < A->cmap->n; j++) {
1995ca15aa20SStefano Zampini       v   = vv + j * mat->lda;
1996289bc588SBarry Smith       sum = 0.0;
1997d0f46423SBarry Smith       for (i = 0; i < A->rmap->n; i++) {
19989371c9d4SSatish Balay         sum += PetscAbsScalar(*v);
19999371c9d4SSatish Balay         v++;
2000289bc588SBarry Smith       }
2001064f8208SBarry Smith       if (sum > *nrm) *nrm = sum;
2002289bc588SBarry Smith     }
20039566063dSJacob Faibussowitsch     PetscCall(PetscLogFlops(1.0 * A->cmap->n * A->rmap->n));
20043a40ed3dSBarry Smith   } else if (type == NORM_INFINITY) {
2005064f8208SBarry Smith     *nrm = 0.0;
2006d0f46423SBarry Smith     for (j = 0; j < A->rmap->n; j++) {
2007ca15aa20SStefano Zampini       v   = vv + j;
2008289bc588SBarry Smith       sum = 0.0;
2009d0f46423SBarry Smith       for (i = 0; i < A->cmap->n; i++) {
20109371c9d4SSatish Balay         sum += PetscAbsScalar(*v);
20119371c9d4SSatish Balay         v += mat->lda;
2012289bc588SBarry Smith       }
2013064f8208SBarry Smith       if (sum > *nrm) *nrm = sum;
2014289bc588SBarry Smith     }
20159566063dSJacob Faibussowitsch     PetscCall(PetscLogFlops(1.0 * A->cmap->n * A->rmap->n));
2016e7e72b3dSBarry Smith   } else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "No two norm");
20179566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArrayRead(A, (const PetscScalar **)&vv));
20183ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2019289bc588SBarry Smith }
2020289bc588SBarry Smith 
2021d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatSetOption_SeqDense(Mat A, MatOption op, PetscBool flg)
2022d71ae5a4SJacob Faibussowitsch {
2023c0bbcb79SLois Curfman McInnes   Mat_SeqDense *aij = (Mat_SeqDense *)A->data;
202467e560aaSBarry Smith 
20253a40ed3dSBarry Smith   PetscFunctionBegin;
2026b5a2b587SKris Buschelman   switch (op) {
2027d71ae5a4SJacob Faibussowitsch   case MAT_ROW_ORIENTED:
2028d71ae5a4SJacob Faibussowitsch     aij->roworiented = flg;
2029d71ae5a4SJacob Faibussowitsch     break;
2030512a5fc5SBarry Smith   case MAT_NEW_NONZERO_LOCATIONS:
2031b5a2b587SKris Buschelman   case MAT_NEW_NONZERO_LOCATION_ERR:
20323971808eSMatthew Knepley   case MAT_NEW_NONZERO_ALLOCATION_ERR:
20338c78258cSHong Zhang   case MAT_FORCE_DIAGONAL_ENTRIES:
203413fa8e87SLisandro Dalcin   case MAT_KEEP_NONZERO_PATTERN:
2035b5a2b587SKris Buschelman   case MAT_IGNORE_OFF_PROC_ENTRIES:
2036b5a2b587SKris Buschelman   case MAT_USE_HASH_TABLE:
20370f8fb01aSBarry Smith   case MAT_IGNORE_ZERO_ENTRIES:
20385021d80fSJed Brown   case MAT_IGNORE_LOWER_TRIANGULAR:
2039d71ae5a4SJacob Faibussowitsch   case MAT_SORTED_FULL:
2040d71ae5a4SJacob Faibussowitsch     PetscCall(PetscInfo(A, "Option %s ignored\n", MatOptions[op]));
2041d71ae5a4SJacob Faibussowitsch     break;
20425021d80fSJed Brown   case MAT_SPD:
204377e54ba9SKris Buschelman   case MAT_SYMMETRIC:
204477e54ba9SKris Buschelman   case MAT_STRUCTURALLY_SYMMETRIC:
20459a4540c5SBarry Smith   case MAT_HERMITIAN:
20469a4540c5SBarry Smith   case MAT_SYMMETRY_ETERNAL:
2047b94d7dedSBarry Smith   case MAT_STRUCTURAL_SYMMETRY_ETERNAL:
2048d71ae5a4SJacob Faibussowitsch   case MAT_SPD_ETERNAL:
2049d71ae5a4SJacob Faibussowitsch     break;
2050d71ae5a4SJacob Faibussowitsch   default:
2051d71ae5a4SJacob Faibussowitsch     SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "unknown option %s", MatOptions[op]);
20523a40ed3dSBarry Smith   }
20533ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2054289bc588SBarry Smith }
2055289bc588SBarry Smith 
2056d71ae5a4SJacob Faibussowitsch PetscErrorCode MatZeroEntries_SeqDense(Mat A)
2057d71ae5a4SJacob Faibussowitsch {
2058ec8511deSBarry Smith   Mat_SeqDense *l   = (Mat_SeqDense *)A->data;
20593d8925e7SStefano Zampini   PetscInt      lda = l->lda, m = A->rmap->n, n = A->cmap->n, j;
2060ca15aa20SStefano Zampini   PetscScalar  *v;
20613a40ed3dSBarry Smith 
20623a40ed3dSBarry Smith   PetscFunctionBegin;
20639566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArrayWrite(A, &v));
2064a5ce6ee0Svictorle   if (lda > m) {
206548a46eb9SPierre Jolivet     for (j = 0; j < n; j++) PetscCall(PetscArrayzero(v + j * lda, m));
2066a5ce6ee0Svictorle   } else {
20679566063dSJacob Faibussowitsch     PetscCall(PetscArrayzero(v, PetscInt64Mult(m, n)));
2068a5ce6ee0Svictorle   }
20699566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArrayWrite(A, &v));
20703ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
20716f0a148fSBarry Smith }
20726f0a148fSBarry Smith 
2073d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatZeroRows_SeqDense(Mat A, PetscInt N, const PetscInt rows[], PetscScalar diag, Vec x, Vec b)
2074d71ae5a4SJacob Faibussowitsch {
2075ec8511deSBarry Smith   Mat_SeqDense      *l = (Mat_SeqDense *)A->data;
2076b9679d65SBarry Smith   PetscInt           m = l->lda, n = A->cmap->n, i, j;
2077ca15aa20SStefano Zampini   PetscScalar       *slot, *bb, *v;
207897b48c8fSBarry Smith   const PetscScalar *xx;
207955659b69SBarry Smith 
20803a40ed3dSBarry Smith   PetscFunctionBegin;
208176bd3646SJed Brown   if (PetscDefined(USE_DEBUG)) {
2082b9679d65SBarry Smith     for (i = 0; i < N; i++) {
208308401ef6SPierre Jolivet       PetscCheck(rows[i] >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Negative row requested to be zeroed");
208408401ef6SPierre Jolivet       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);
2085b9679d65SBarry Smith     }
208676bd3646SJed Brown   }
20873ba16761SJacob Faibussowitsch   if (!N) PetscFunctionReturn(PETSC_SUCCESS);
2088b9679d65SBarry Smith 
208997b48c8fSBarry Smith   /* fix right hand side if needed */
209097b48c8fSBarry Smith   if (x && b) {
20919566063dSJacob Faibussowitsch     PetscCall(VecGetArrayRead(x, &xx));
20929566063dSJacob Faibussowitsch     PetscCall(VecGetArray(b, &bb));
20932205254eSKarl Rupp     for (i = 0; i < N; i++) bb[rows[i]] = diag * xx[rows[i]];
20949566063dSJacob Faibussowitsch     PetscCall(VecRestoreArrayRead(x, &xx));
20959566063dSJacob Faibussowitsch     PetscCall(VecRestoreArray(b, &bb));
209697b48c8fSBarry Smith   }
209797b48c8fSBarry Smith 
20989566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArray(A, &v));
20996f0a148fSBarry Smith   for (i = 0; i < N; i++) {
2100ca15aa20SStefano Zampini     slot = v + rows[i];
21019371c9d4SSatish Balay     for (j = 0; j < n; j++) {
21029371c9d4SSatish Balay       *slot = 0.0;
21039371c9d4SSatish Balay       slot += m;
21049371c9d4SSatish Balay     }
21056f0a148fSBarry Smith   }
2106f4df32b1SMatthew Knepley   if (diag != 0.0) {
210708401ef6SPierre Jolivet     PetscCheck(A->rmap->n == A->cmap->n, PETSC_COMM_SELF, PETSC_ERR_SUP, "Only coded for square matrices");
21086f0a148fSBarry Smith     for (i = 0; i < N; i++) {
2109ca15aa20SStefano Zampini       slot  = v + (m + 1) * rows[i];
2110f4df32b1SMatthew Knepley       *slot = diag;
21116f0a148fSBarry Smith     }
21126f0a148fSBarry Smith   }
21139566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArray(A, &v));
21143ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
21156f0a148fSBarry Smith }
2116557bce09SLois Curfman McInnes 
2117d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatDenseGetLDA_SeqDense(Mat A, PetscInt *lda)
2118d71ae5a4SJacob Faibussowitsch {
211949a6ff4bSBarry Smith   Mat_SeqDense *mat = (Mat_SeqDense *)A->data;
212049a6ff4bSBarry Smith 
212149a6ff4bSBarry Smith   PetscFunctionBegin;
212249a6ff4bSBarry Smith   *lda = mat->lda;
21233ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
212449a6ff4bSBarry Smith }
212549a6ff4bSBarry Smith 
2126d71ae5a4SJacob Faibussowitsch PetscErrorCode MatDenseGetArray_SeqDense(Mat A, PetscScalar **array)
2127d71ae5a4SJacob Faibussowitsch {
2128c0bbcb79SLois Curfman McInnes   Mat_SeqDense *mat = (Mat_SeqDense *)A->data;
21293a40ed3dSBarry Smith 
21303a40ed3dSBarry Smith   PetscFunctionBegin;
213128b400f6SJacob Faibussowitsch   PetscCheck(!mat->matinuse, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Need to call MatDenseRestoreSubMatrix() first");
213264e87e97SBarry Smith   *array = mat->v;
21333ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
213464e87e97SBarry Smith }
21350754003eSLois Curfman McInnes 
2136d71ae5a4SJacob Faibussowitsch PetscErrorCode MatDenseRestoreArray_SeqDense(Mat A, PetscScalar **array)
2137d71ae5a4SJacob Faibussowitsch {
21383a40ed3dSBarry Smith   PetscFunctionBegin;
213975f6d85dSStefano Zampini   if (array) *array = NULL;
21403ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2141ff14e315SSatish Balay }
21420754003eSLois Curfman McInnes 
21430f74d2c1SSatish Balay /*@
214411a5261eSBarry Smith    MatDenseGetLDA - gets the leading dimension of the array returned from `MatDenseGetArray()`
214549a6ff4bSBarry Smith 
2146*2ef1f0ffSBarry Smith    Not Collective
214749a6ff4bSBarry Smith 
214849a6ff4bSBarry Smith    Input Parameter:
214911a5261eSBarry Smith .  mat - a `MATDENSE` or `MATDENSECUDA` matrix
215049a6ff4bSBarry Smith 
215149a6ff4bSBarry Smith    Output Parameter:
215249a6ff4bSBarry Smith .   lda - the leading dimension
215349a6ff4bSBarry Smith 
215449a6ff4bSBarry Smith    Level: intermediate
215549a6ff4bSBarry Smith 
2156*2ef1f0ffSBarry Smith .seealso: [](chapter_matrices), `Mat`, `MATDENSE`, `MATDENSECUDA`, `MatDenseGetArray()`, `MatDenseRestoreArray()`, `MatDenseGetArrayRead()`, `MatDenseRestoreArrayRead()`, `MatDenseSetLDA()`
215749a6ff4bSBarry Smith @*/
2158d71ae5a4SJacob Faibussowitsch PetscErrorCode MatDenseGetLDA(Mat A, PetscInt *lda)
2159d71ae5a4SJacob Faibussowitsch {
216049a6ff4bSBarry Smith   PetscFunctionBegin;
2161d5ea218eSStefano Zampini   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
2162dadcf809SJacob Faibussowitsch   PetscValidIntPointer(lda, 2);
216375f6d85dSStefano Zampini   MatCheckPreallocated(A, 1);
2164cac4c232SBarry Smith   PetscUseMethod(A, "MatDenseGetLDA_C", (Mat, PetscInt *), (A, lda));
21653ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
216649a6ff4bSBarry Smith }
216749a6ff4bSBarry Smith 
21680f74d2c1SSatish Balay /*@
216911a5261eSBarry Smith    MatDenseSetLDA - Sets the leading dimension of the array used by the `MATDENSE` matrix
2170ad16ce7aSStefano Zampini 
2171*2ef1f0ffSBarry Smith    Not Collective
2172ad16ce7aSStefano Zampini 
2173d8d19677SJose E. Roman    Input Parameters:
217411a5261eSBarry Smith +  mat - a `MATDENSE` or `MATDENSECUDA` matrix
2175ad16ce7aSStefano Zampini -  lda - the leading dimension
2176ad16ce7aSStefano Zampini 
2177ad16ce7aSStefano Zampini    Level: intermediate
2178ad16ce7aSStefano Zampini 
2179*2ef1f0ffSBarry Smith .seealso: [](chapter_matrices), `Mat`, `MATDENSE`, `MATDENSECUDA`, `MatDenseGetArray()`, `MatDenseRestoreArray()`, `MatDenseGetArrayRead()`, `MatDenseRestoreArrayRead()`, `MatDenseGetLDA()`
2180ad16ce7aSStefano Zampini @*/
2181d71ae5a4SJacob Faibussowitsch PetscErrorCode MatDenseSetLDA(Mat A, PetscInt lda)
2182d71ae5a4SJacob Faibussowitsch {
2183ad16ce7aSStefano Zampini   PetscFunctionBegin;
2184ad16ce7aSStefano Zampini   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
2185cac4c232SBarry Smith   PetscTryMethod(A, "MatDenseSetLDA_C", (Mat, PetscInt), (A, lda));
21863ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2187ad16ce7aSStefano Zampini }
2188ad16ce7aSStefano Zampini 
2189ad16ce7aSStefano Zampini /*@C
219011a5261eSBarry Smith    MatDenseGetArray - gives read-write access to the array where the data for a `MATDENSE` matrix is stored
219173a71a0fSBarry Smith 
2192c3339decSBarry Smith    Logically Collective
219373a71a0fSBarry Smith 
219473a71a0fSBarry Smith    Input Parameter:
21956947451fSStefano Zampini .  mat - a dense matrix
219673a71a0fSBarry Smith 
219773a71a0fSBarry Smith    Output Parameter:
219873a71a0fSBarry Smith .   array - pointer to the data
219973a71a0fSBarry Smith 
220073a71a0fSBarry Smith    Level: intermediate
220173a71a0fSBarry Smith 
22020ab4885dSBarry Smith    Fortran Note:
22030ab4885dSBarry Smith    `MatDenseGetArray()` Fortran binding is deprecated (since PETSc 3.19), use `MatDenseGetArrayF90()`
22040ab4885dSBarry Smith 
2205*2ef1f0ffSBarry Smith .seealso: [](chapter_matrices), `Mat`, `MATDENSE`, `MatDenseRestoreArray()`, `MatDenseGetArrayRead()`, `MatDenseRestoreArrayRead()`, `MatDenseGetArrayWrite()`, `MatDenseRestoreArrayWrite()`
220673a71a0fSBarry Smith @*/
2207d71ae5a4SJacob Faibussowitsch PetscErrorCode MatDenseGetArray(Mat A, PetscScalar **array)
2208d71ae5a4SJacob Faibussowitsch {
220973a71a0fSBarry Smith   PetscFunctionBegin;
2210d5ea218eSStefano Zampini   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
2211d5ea218eSStefano Zampini   PetscValidPointer(array, 2);
2212cac4c232SBarry Smith   PetscUseMethod(A, "MatDenseGetArray_C", (Mat, PetscScalar **), (A, array));
22133ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
221473a71a0fSBarry Smith }
221573a71a0fSBarry Smith 
2216dec5eb66SMatthew G Knepley /*@C
221711a5261eSBarry Smith    MatDenseRestoreArray - returns access to the array where the data for a `MATDENSE` matrix is stored obtained by `MatDenseGetArray()`
221873a71a0fSBarry Smith 
2219c3339decSBarry Smith    Logically Collective
22208572280aSBarry Smith 
22218572280aSBarry Smith    Input Parameters:
22226947451fSStefano Zampini +  mat - a dense matrix
2223*2ef1f0ffSBarry Smith -  array - pointer to the data (may be `NULL`)
22248572280aSBarry Smith 
22258572280aSBarry Smith    Level: intermediate
22268572280aSBarry Smith 
22270ab4885dSBarry Smith    Fortran Note:
22280ab4885dSBarry Smith    `MatDenseRestoreArray()` Fortran binding is deprecated (since PETSc 3.19), use `MatDenseRestoreArrayF90()`
22290ab4885dSBarry Smith 
2230*2ef1f0ffSBarry Smith .seealso: [](chapter_matrices), `Mat`, `MATDENSE`, `MatDenseGetArray()`, `MatDenseGetArrayRead()`, `MatDenseRestoreArrayRead()`, `MatDenseGetArrayWrite()`, `MatDenseRestoreArrayWrite()`
22318572280aSBarry Smith @*/
2232d71ae5a4SJacob Faibussowitsch PetscErrorCode MatDenseRestoreArray(Mat A, PetscScalar **array)
2233d71ae5a4SJacob Faibussowitsch {
22348572280aSBarry Smith   PetscFunctionBegin;
2235d5ea218eSStefano Zampini   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
2236d5ea218eSStefano Zampini   PetscValidPointer(array, 2);
2237cac4c232SBarry Smith   PetscUseMethod(A, "MatDenseRestoreArray_C", (Mat, PetscScalar **), (A, array));
22389566063dSJacob Faibussowitsch   PetscCall(PetscObjectStateIncrease((PetscObject)A));
223947d993e7Ssuyashtn #if defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
2240637a0070SStefano Zampini   A->offloadmask = PETSC_OFFLOAD_CPU;
2241637a0070SStefano Zampini #endif
22423ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
22438572280aSBarry Smith }
22448572280aSBarry Smith 
22458572280aSBarry Smith /*@C
224611a5261eSBarry Smith   MatDenseGetArrayRead - gives read-only access to the array where the data for a `MATDENSE`  matrix is stored
22478572280aSBarry Smith 
22480ab4885dSBarry Smith    Not Collective; No Fortran Support
22498572280aSBarry Smith 
22508572280aSBarry Smith    Input Parameter:
22516947451fSStefano Zampini .  mat - a dense matrix
22528572280aSBarry Smith 
22538572280aSBarry Smith    Output Parameter:
22548572280aSBarry Smith .   array - pointer to the data
22558572280aSBarry Smith 
22568572280aSBarry Smith    Level: intermediate
22578572280aSBarry Smith 
2258*2ef1f0ffSBarry Smith .seealso: [](chapter_matrices), `Mat`, `MATDENSE`, `MatDenseRestoreArrayRead()`, `MatDenseGetArray()`, `MatDenseRestoreArray()`, `MatDenseGetArrayWrite()`, `MatDenseRestoreArrayWrite()`
22598572280aSBarry Smith @*/
2260d71ae5a4SJacob Faibussowitsch PetscErrorCode MatDenseGetArrayRead(Mat A, const PetscScalar **array)
2261d71ae5a4SJacob Faibussowitsch {
22628572280aSBarry Smith   PetscFunctionBegin;
2263d5ea218eSStefano Zampini   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
2264d5ea218eSStefano Zampini   PetscValidPointer(array, 2);
2265cac4c232SBarry Smith   PetscUseMethod(A, "MatDenseGetArrayRead_C", (Mat, const PetscScalar **), (A, array));
22663ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
22678572280aSBarry Smith }
22688572280aSBarry Smith 
22698572280aSBarry Smith /*@C
227011a5261eSBarry Smith    MatDenseRestoreArrayRead - returns access to the array where the data for a `MATDENSE` matrix is stored obtained by `MatDenseGetArrayRead()`
22718572280aSBarry Smith 
22720ab4885dSBarry Smith    Not Collective; No Fortran Support
227373a71a0fSBarry Smith 
227473a71a0fSBarry Smith    Input Parameters:
22756947451fSStefano Zampini +  mat - a dense matrix
2276*2ef1f0ffSBarry Smith -  array - pointer to the data (may be `NULL`)
227773a71a0fSBarry Smith 
227873a71a0fSBarry Smith    Level: intermediate
227973a71a0fSBarry Smith 
2280*2ef1f0ffSBarry Smith .seealso: [](chapter_matrices), `Mat`, `MATDENSE`, `MatDenseGetArrayRead()`, `MatDenseGetArray()`, `MatDenseRestoreArray()`, `MatDenseGetArrayWrite()`, `MatDenseRestoreArrayWrite()`
228173a71a0fSBarry Smith @*/
2282d71ae5a4SJacob Faibussowitsch PetscErrorCode MatDenseRestoreArrayRead(Mat A, const PetscScalar **array)
2283d71ae5a4SJacob Faibussowitsch {
228473a71a0fSBarry Smith   PetscFunctionBegin;
2285d5ea218eSStefano Zampini   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
2286d5ea218eSStefano Zampini   PetscValidPointer(array, 2);
2287cac4c232SBarry Smith   PetscUseMethod(A, "MatDenseRestoreArrayRead_C", (Mat, const PetscScalar **), (A, array));
22883ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
228973a71a0fSBarry Smith }
229073a71a0fSBarry Smith 
22916947451fSStefano Zampini /*@C
229211a5261eSBarry Smith    MatDenseGetArrayWrite - gives write-only access to the array where the data for a `MATDENSE` matrix is stored
22936947451fSStefano Zampini 
22940ab4885dSBarry Smith    Not Collective; No Fortran Support
22956947451fSStefano Zampini 
22966947451fSStefano Zampini    Input Parameter:
22976947451fSStefano Zampini .  mat - a dense matrix
22986947451fSStefano Zampini 
22996947451fSStefano Zampini    Output Parameter:
23006947451fSStefano Zampini .   array - pointer to the data
23016947451fSStefano Zampini 
23026947451fSStefano Zampini    Level: intermediate
23036947451fSStefano Zampini 
2304*2ef1f0ffSBarry Smith .seealso: [](chapter_matrices), `Mat`, `MATDENSE`, `MatDenseRestoreArrayWrite()`, `MatDenseGetArray()`, `MatDenseRestoreArray()`, `MatDenseGetArrayRead()`, `MatDenseRestoreArrayRead()`
23056947451fSStefano Zampini @*/
2306d71ae5a4SJacob Faibussowitsch PetscErrorCode MatDenseGetArrayWrite(Mat A, PetscScalar **array)
2307d71ae5a4SJacob Faibussowitsch {
23086947451fSStefano Zampini   PetscFunctionBegin;
2309d5ea218eSStefano Zampini   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
2310d5ea218eSStefano Zampini   PetscValidPointer(array, 2);
2311cac4c232SBarry Smith   PetscUseMethod(A, "MatDenseGetArrayWrite_C", (Mat, PetscScalar **), (A, array));
23123ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
23136947451fSStefano Zampini }
23146947451fSStefano Zampini 
23156947451fSStefano Zampini /*@C
231611a5261eSBarry Smith    MatDenseRestoreArrayWrite - returns access to the array where the data for a `MATDENSE` matrix is stored obtained by `MatDenseGetArrayWrite()`
23176947451fSStefano Zampini 
23180ab4885dSBarry Smith    Not Collective; No Fortran Support
23196947451fSStefano Zampini 
23206947451fSStefano Zampini    Input Parameters:
23216947451fSStefano Zampini +  mat - a dense matrix
2322*2ef1f0ffSBarry Smith -  array - pointer to the data (may be `NULL`)
23236947451fSStefano Zampini 
23246947451fSStefano Zampini    Level: intermediate
23256947451fSStefano Zampini 
2326*2ef1f0ffSBarry Smith .seealso: [](chapter_matrices), `Mat`, `MATDENSE`, `MatDenseGetArrayWrite()`, `MatDenseGetArray()`, `MatDenseRestoreArray()`, `MatDenseGetArrayRead()`, `MatDenseRestoreArrayRead()`
23276947451fSStefano Zampini @*/
2328d71ae5a4SJacob Faibussowitsch PetscErrorCode MatDenseRestoreArrayWrite(Mat A, PetscScalar **array)
2329d71ae5a4SJacob Faibussowitsch {
23306947451fSStefano Zampini   PetscFunctionBegin;
2331d5ea218eSStefano Zampini   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
2332d5ea218eSStefano Zampini   PetscValidPointer(array, 2);
2333cac4c232SBarry Smith   PetscUseMethod(A, "MatDenseRestoreArrayWrite_C", (Mat, PetscScalar **), (A, array));
23349566063dSJacob Faibussowitsch   PetscCall(PetscObjectStateIncrease((PetscObject)A));
233547d993e7Ssuyashtn #if defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
23366947451fSStefano Zampini   A->offloadmask = PETSC_OFFLOAD_CPU;
23376947451fSStefano Zampini #endif
23383ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
23396947451fSStefano Zampini }
23406947451fSStefano Zampini 
2341cd3f9d89SJunchao Zhang /*@C
2342cd3f9d89SJunchao Zhang    MatDenseGetArrayAndMemType - gives read-write access to the array where the data for a `MATDENSE` matrix is stored
2343cd3f9d89SJunchao Zhang 
2344cd3f9d89SJunchao Zhang    Logically Collective
2345cd3f9d89SJunchao Zhang 
2346cd3f9d89SJunchao Zhang    Input Parameter:
2347cd3f9d89SJunchao Zhang .  mat - a dense matrix
2348cd3f9d89SJunchao Zhang 
2349cd3f9d89SJunchao Zhang    Output Parameters:
2350cd3f9d89SJunchao Zhang +  array - pointer to the data
2351cd3f9d89SJunchao Zhang -  mtype - memory type of the returned pointer
2352cd3f9d89SJunchao Zhang 
2353cd3f9d89SJunchao Zhang    Level: intermediate
2354cd3f9d89SJunchao Zhang 
2355*2ef1f0ffSBarry Smith    Notes:
2356*2ef1f0ffSBarry Smith    If the matrix is of a device type such as `MATDENSECUDA`, `MATDENSEHIP`, etc.,
2357*2ef1f0ffSBarry Smith    an array on device is always returned and is guaranteed to contain the matrix's latest data.
2358*2ef1f0ffSBarry Smith 
2359*2ef1f0ffSBarry Smith .seealso: [](chapter_matrices), `Mat`, `MATDENSE`, `MatDenseRestoreArrayAndMemType()`, `MatDenseGetArrayReadAndMemType()`, `MatDenseGetArrayWriteAndMemType()`, `MatDenseGetArrayRead()`,
2360cd3f9d89SJunchao Zhang    `MatDenseRestoreArrayRead()`, `MatDenseGetArrayWrite()`, `MatDenseRestoreArrayWrite()`, `MatSeqAIJGetCSRAndMemType()`
2361cd3f9d89SJunchao Zhang @*/
2362cd3f9d89SJunchao Zhang PetscErrorCode MatDenseGetArrayAndMemType(Mat A, PetscScalar **array, PetscMemType *mtype)
2363cd3f9d89SJunchao Zhang {
2364cd3f9d89SJunchao Zhang   PetscBool isMPI;
2365cd3f9d89SJunchao Zhang 
2366cd3f9d89SJunchao Zhang   PetscFunctionBegin;
2367cd3f9d89SJunchao Zhang   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
2368cd3f9d89SJunchao Zhang   PetscValidPointer(array, 2);
2369e865de01SJunchao Zhang   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 */
2370cd3f9d89SJunchao Zhang   PetscCall(PetscObjectBaseTypeCompare((PetscObject)A, MATMPIDENSE, &isMPI));
2371cd3f9d89SJunchao Zhang   if (isMPI) {
2372cd3f9d89SJunchao Zhang     /* Dispatch here so that the code can be reused for all subclasses of MATDENSE */
2373cd3f9d89SJunchao Zhang     PetscCall(MatDenseGetArrayAndMemType(((Mat_MPIDense *)A->data)->A, array, mtype));
2374cd3f9d89SJunchao Zhang   } else {
2375cd3f9d89SJunchao Zhang     PetscErrorCode (*fptr)(Mat, PetscScalar **, PetscMemType *);
23763ba16761SJacob Faibussowitsch 
23773ba16761SJacob Faibussowitsch     PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatDenseGetArrayAndMemType_C", &fptr));
2378cd3f9d89SJunchao Zhang     if (fptr) {
2379cd3f9d89SJunchao Zhang       PetscCall((*fptr)(A, array, mtype));
2380cd3f9d89SJunchao Zhang     } else {
2381cd3f9d89SJunchao Zhang       PetscUseMethod(A, "MatDenseGetArray_C", (Mat, PetscScalar **), (A, array));
2382cd3f9d89SJunchao Zhang       if (mtype) *mtype = PETSC_MEMTYPE_HOST;
2383cd3f9d89SJunchao Zhang     }
2384cd3f9d89SJunchao Zhang   }
23853ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2386cd3f9d89SJunchao Zhang }
2387cd3f9d89SJunchao Zhang 
2388cd3f9d89SJunchao Zhang /*@C
2389cd3f9d89SJunchao Zhang    MatDenseRestoreArrayAndMemType - returns access to the array that is obtained by `MatDenseGetArrayAndMemType()`
2390cd3f9d89SJunchao Zhang 
2391cd3f9d89SJunchao Zhang    Logically Collective
2392cd3f9d89SJunchao Zhang 
2393cd3f9d89SJunchao Zhang    Input Parameters:
2394cd3f9d89SJunchao Zhang +  mat - a dense matrix
2395cd3f9d89SJunchao Zhang -  array - pointer to the data
2396cd3f9d89SJunchao Zhang 
2397cd3f9d89SJunchao Zhang    Level: intermediate
2398cd3f9d89SJunchao Zhang 
2399*2ef1f0ffSBarry Smith .seealso: [](chapter_matrices), `Mat`, `MATDENSE`, `MatDenseGetArrayAndMemType()`, `MatDenseGetArray()`, `MatDenseGetArrayRead()`, `MatDenseRestoreArrayRead()`, `MatDenseGetArrayWrite()`, `MatDenseRestoreArrayWrite()`
2400cd3f9d89SJunchao Zhang @*/
2401cd3f9d89SJunchao Zhang PetscErrorCode MatDenseRestoreArrayAndMemType(Mat A, PetscScalar **array)
2402cd3f9d89SJunchao Zhang {
2403cd3f9d89SJunchao Zhang   PetscBool isMPI;
2404cd3f9d89SJunchao Zhang 
2405cd3f9d89SJunchao Zhang   PetscFunctionBegin;
2406cd3f9d89SJunchao Zhang   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
2407cd3f9d89SJunchao Zhang   PetscValidPointer(array, 2);
2408cd3f9d89SJunchao Zhang   PetscCall(PetscObjectBaseTypeCompare((PetscObject)A, MATMPIDENSE, &isMPI));
2409cd3f9d89SJunchao Zhang   if (isMPI) {
2410cd3f9d89SJunchao Zhang     PetscCall(MatDenseRestoreArrayAndMemType(((Mat_MPIDense *)A->data)->A, array));
2411cd3f9d89SJunchao Zhang   } else {
2412cd3f9d89SJunchao Zhang     PetscErrorCode (*fptr)(Mat, PetscScalar **);
24133ba16761SJacob Faibussowitsch 
24143ba16761SJacob Faibussowitsch     PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatDenseRestoreArrayAndMemType_C", &fptr));
2415cd3f9d89SJunchao Zhang     if (fptr) {
2416cd3f9d89SJunchao Zhang       PetscCall((*fptr)(A, array));
2417cd3f9d89SJunchao Zhang     } else {
2418cd3f9d89SJunchao Zhang       PetscUseMethod(A, "MatDenseRestoreArray_C", (Mat, PetscScalar **), (A, array));
2419cd3f9d89SJunchao Zhang     }
2420cd3f9d89SJunchao Zhang     *array = NULL;
2421cd3f9d89SJunchao Zhang   }
2422cd3f9d89SJunchao Zhang   PetscCall(PetscObjectStateIncrease((PetscObject)A));
24233ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2424cd3f9d89SJunchao Zhang }
2425cd3f9d89SJunchao Zhang 
2426cd3f9d89SJunchao Zhang /*@C
2427cd3f9d89SJunchao Zhang    MatDenseGetArrayReadAndMemType - gives read-only access to the array where the data for a `MATDENSE` matrix is stored
2428cd3f9d89SJunchao Zhang 
2429cd3f9d89SJunchao Zhang    Logically Collective
2430cd3f9d89SJunchao Zhang 
2431cd3f9d89SJunchao Zhang    Input Parameter:
2432cd3f9d89SJunchao Zhang .  mat - a dense matrix
2433cd3f9d89SJunchao Zhang 
2434cd3f9d89SJunchao Zhang    Output Parameters:
2435cd3f9d89SJunchao Zhang +  array - pointer to the data
2436cd3f9d89SJunchao Zhang -  mtype - memory type of the returned pointer
2437cd3f9d89SJunchao Zhang 
2438cd3f9d89SJunchao Zhang    Level: intermediate
2439cd3f9d89SJunchao Zhang 
2440*2ef1f0ffSBarry Smith    Notes:
2441*2ef1f0ffSBarry Smith    If the matrix is of a device type such as `MATDENSECUDA`, `MATDENSEHIP`, etc.,
2442*2ef1f0ffSBarry Smith    an array on device is always returned and is guaranteed to contain the matrix's latest data.
2443*2ef1f0ffSBarry Smith 
2444*2ef1f0ffSBarry Smith .seealso: [](chapter_matrices), `Mat`, `MATDENSE`, `MatDenseRestoreArrayReadAndMemType()`, `MatDenseGetArrayWriteAndMemType()`,
2445cd3f9d89SJunchao Zhang    `MatDenseGetArrayRead()`, `MatDenseRestoreArrayRead()`, `MatDenseGetArrayWrite()`, `MatDenseRestoreArrayWrite()`, `MatSeqAIJGetCSRAndMemType()`
2446cd3f9d89SJunchao Zhang @*/
2447cd3f9d89SJunchao Zhang PetscErrorCode MatDenseGetArrayReadAndMemType(Mat A, const PetscScalar **array, PetscMemType *mtype)
2448cd3f9d89SJunchao Zhang {
2449cd3f9d89SJunchao Zhang   PetscBool isMPI;
2450cd3f9d89SJunchao Zhang 
2451cd3f9d89SJunchao Zhang   PetscFunctionBegin;
2452cd3f9d89SJunchao Zhang   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
2453cd3f9d89SJunchao Zhang   PetscValidPointer(array, 2);
2454e865de01SJunchao Zhang   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 */
2455cd3f9d89SJunchao Zhang   PetscCall(PetscObjectBaseTypeCompare((PetscObject)A, MATMPIDENSE, &isMPI));
2456cd3f9d89SJunchao Zhang   if (isMPI) { /* Dispatch here so that the code can be reused for all subclasses of MATDENSE */
2457cd3f9d89SJunchao Zhang     PetscCall(MatDenseGetArrayReadAndMemType(((Mat_MPIDense *)A->data)->A, array, mtype));
2458cd3f9d89SJunchao Zhang   } else {
2459cd3f9d89SJunchao Zhang     PetscErrorCode (*fptr)(Mat, const PetscScalar **, PetscMemType *);
24603ba16761SJacob Faibussowitsch 
24613ba16761SJacob Faibussowitsch     PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatDenseGetArrayReadAndMemType_C", &fptr));
2462cd3f9d89SJunchao Zhang     if (fptr) {
2463cd3f9d89SJunchao Zhang       PetscCall((*fptr)(A, array, mtype));
2464cd3f9d89SJunchao Zhang     } else {
2465cd3f9d89SJunchao Zhang       PetscUseMethod(A, "MatDenseGetArrayRead_C", (Mat, const PetscScalar **), (A, array));
2466cd3f9d89SJunchao Zhang       if (mtype) *mtype = PETSC_MEMTYPE_HOST;
2467cd3f9d89SJunchao Zhang     }
2468cd3f9d89SJunchao Zhang   }
24693ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2470cd3f9d89SJunchao Zhang }
2471cd3f9d89SJunchao Zhang 
2472cd3f9d89SJunchao Zhang /*@C
2473cd3f9d89SJunchao Zhang    MatDenseRestoreArrayReadAndMemType - returns access to the array that is obtained by `MatDenseGetArrayReadAndMemType()`
2474cd3f9d89SJunchao Zhang 
2475cd3f9d89SJunchao Zhang    Logically Collective
2476cd3f9d89SJunchao Zhang 
2477cd3f9d89SJunchao Zhang    Input Parameters:
2478cd3f9d89SJunchao Zhang +  mat - a dense matrix
2479cd3f9d89SJunchao Zhang -  array - pointer to the data
2480cd3f9d89SJunchao Zhang 
2481cd3f9d89SJunchao Zhang    Level: intermediate
2482cd3f9d89SJunchao Zhang 
2483*2ef1f0ffSBarry Smith .seealso: [](chapter_matrices), `Mat`, `MATDENSE`, `MatDenseGetArrayReadAndMemType()`, `MatDenseGetArray()`, `MatDenseGetArrayRead()`, `MatDenseRestoreArrayRead()`, `MatDenseGetArrayWrite()`, `MatDenseRestoreArrayWrite()`
2484cd3f9d89SJunchao Zhang @*/
2485cd3f9d89SJunchao Zhang PetscErrorCode MatDenseRestoreArrayReadAndMemType(Mat A, const PetscScalar **array)
2486cd3f9d89SJunchao Zhang {
2487cd3f9d89SJunchao Zhang   PetscBool isMPI;
2488cd3f9d89SJunchao Zhang 
2489cd3f9d89SJunchao Zhang   PetscFunctionBegin;
2490cd3f9d89SJunchao Zhang   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
2491cd3f9d89SJunchao Zhang   PetscValidPointer(array, 2);
2492cd3f9d89SJunchao Zhang   PetscCall(PetscObjectBaseTypeCompare((PetscObject)A, MATMPIDENSE, &isMPI));
2493cd3f9d89SJunchao Zhang   if (isMPI) {
2494cd3f9d89SJunchao Zhang     PetscCall(MatDenseRestoreArrayReadAndMemType(((Mat_MPIDense *)A->data)->A, array));
2495cd3f9d89SJunchao Zhang   } else {
2496cd3f9d89SJunchao Zhang     PetscErrorCode (*fptr)(Mat, const PetscScalar **);
24973ba16761SJacob Faibussowitsch 
24983ba16761SJacob Faibussowitsch     PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatDenseRestoreArrayReadAndMemType_C", &fptr));
2499cd3f9d89SJunchao Zhang     if (fptr) {
2500cd3f9d89SJunchao Zhang       PetscCall((*fptr)(A, array));
2501cd3f9d89SJunchao Zhang     } else {
2502cd3f9d89SJunchao Zhang       PetscUseMethod(A, "MatDenseRestoreArrayRead_C", (Mat, const PetscScalar **), (A, array));
2503cd3f9d89SJunchao Zhang     }
2504cd3f9d89SJunchao Zhang     *array = NULL;
2505cd3f9d89SJunchao Zhang   }
25063ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2507cd3f9d89SJunchao Zhang }
2508cd3f9d89SJunchao Zhang 
2509cd3f9d89SJunchao Zhang /*@C
2510cd3f9d89SJunchao Zhang    MatDenseGetArrayWriteAndMemType - gives write-only access to the array where the data for a `MATDENSE` matrix is stored
2511cd3f9d89SJunchao Zhang 
2512cd3f9d89SJunchao Zhang    Logically Collective
2513cd3f9d89SJunchao Zhang 
2514cd3f9d89SJunchao Zhang    Input Parameter:
2515cd3f9d89SJunchao Zhang .  mat - a dense matrix
2516cd3f9d89SJunchao Zhang 
2517cd3f9d89SJunchao Zhang    Output Parameters:
2518cd3f9d89SJunchao Zhang +  array - pointer to the data
2519cd3f9d89SJunchao Zhang -  mtype - memory type of the returned pointer
2520cd3f9d89SJunchao Zhang 
2521cd3f9d89SJunchao Zhang    Level: intermediate
2522cd3f9d89SJunchao Zhang 
2523*2ef1f0ffSBarry Smith    Notes:
2524*2ef1f0ffSBarry Smith    If the matrix is of a device type such as `MATDENSECUDA`, `MATDENSEHIP`, etc.,
2525*2ef1f0ffSBarry Smith    an array on device is always returned and is guaranteed to contain the matrix's latest data.
2526*2ef1f0ffSBarry Smith 
2527*2ef1f0ffSBarry Smith .seealso: [](chapter_matrices), `Mat`, `MATDENSE`, `MatDenseRestoreArrayWriteAndMemType()`, `MatDenseGetArrayReadAndMemType()`, `MatDenseGetArrayRead()`,
2528cd3f9d89SJunchao Zhang   `MatDenseRestoreArrayRead()`, `MatDenseGetArrayWrite()`, `MatDenseRestoreArrayWrite()`, `MatSeqAIJGetCSRAndMemType()`
2529cd3f9d89SJunchao Zhang @*/
2530cd3f9d89SJunchao Zhang PetscErrorCode MatDenseGetArrayWriteAndMemType(Mat A, PetscScalar **array, PetscMemType *mtype)
2531cd3f9d89SJunchao Zhang {
2532cd3f9d89SJunchao Zhang   PetscBool isMPI;
2533cd3f9d89SJunchao Zhang 
2534cd3f9d89SJunchao Zhang   PetscFunctionBegin;
2535cd3f9d89SJunchao Zhang   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
2536cd3f9d89SJunchao Zhang   PetscValidPointer(array, 2);
2537e865de01SJunchao Zhang   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 */
2538cd3f9d89SJunchao Zhang   PetscCall(PetscObjectBaseTypeCompare((PetscObject)A, MATMPIDENSE, &isMPI));
2539cd3f9d89SJunchao Zhang   if (isMPI) {
2540cd3f9d89SJunchao Zhang     PetscCall(MatDenseGetArrayWriteAndMemType(((Mat_MPIDense *)A->data)->A, array, mtype));
2541cd3f9d89SJunchao Zhang   } else {
2542cd3f9d89SJunchao Zhang     PetscErrorCode (*fptr)(Mat, PetscScalar **, PetscMemType *);
25433ba16761SJacob Faibussowitsch 
25443ba16761SJacob Faibussowitsch     PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatDenseGetArrayWriteAndMemType_C", &fptr));
2545cd3f9d89SJunchao Zhang     if (fptr) {
2546cd3f9d89SJunchao Zhang       PetscCall((*fptr)(A, array, mtype));
2547cd3f9d89SJunchao Zhang     } else {
2548cd3f9d89SJunchao Zhang       PetscUseMethod(A, "MatDenseGetArrayWrite_C", (Mat, PetscScalar **), (A, array));
2549cd3f9d89SJunchao Zhang       if (mtype) *mtype = PETSC_MEMTYPE_HOST;
2550cd3f9d89SJunchao Zhang     }
2551cd3f9d89SJunchao Zhang   }
25523ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2553cd3f9d89SJunchao Zhang }
2554cd3f9d89SJunchao Zhang 
2555cd3f9d89SJunchao Zhang /*@C
2556cd3f9d89SJunchao Zhang    MatDenseRestoreArrayWriteAndMemType - returns access to the array that is obtained by `MatDenseGetArrayReadAndMemType()`
2557cd3f9d89SJunchao Zhang 
2558cd3f9d89SJunchao Zhang    Logically Collective
2559cd3f9d89SJunchao Zhang 
2560cd3f9d89SJunchao Zhang    Input Parameters:
2561cd3f9d89SJunchao Zhang +  mat - a dense matrix
2562cd3f9d89SJunchao Zhang -  array - pointer to the data
2563cd3f9d89SJunchao Zhang 
2564cd3f9d89SJunchao Zhang    Level: intermediate
2565cd3f9d89SJunchao Zhang 
2566*2ef1f0ffSBarry Smith .seealso: [](chapter_matrices), `Mat`, `MATDENSE`, `MatDenseGetArrayWriteAndMemType()`, `MatDenseGetArray()`, `MatDenseGetArrayRead()`, `MatDenseRestoreArrayRead()`, `MatDenseGetArrayWrite()`, `MatDenseRestoreArrayWrite()`
2567cd3f9d89SJunchao Zhang @*/
2568cd3f9d89SJunchao Zhang PetscErrorCode MatDenseRestoreArrayWriteAndMemType(Mat A, PetscScalar **array)
2569cd3f9d89SJunchao Zhang {
2570cd3f9d89SJunchao Zhang   PetscBool isMPI;
2571cd3f9d89SJunchao Zhang 
2572cd3f9d89SJunchao Zhang   PetscFunctionBegin;
2573cd3f9d89SJunchao Zhang   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
2574cd3f9d89SJunchao Zhang   PetscValidPointer(array, 2);
2575cd3f9d89SJunchao Zhang   PetscCall(PetscObjectBaseTypeCompare((PetscObject)A, MATMPIDENSE, &isMPI));
2576cd3f9d89SJunchao Zhang   if (isMPI) {
2577cd3f9d89SJunchao Zhang     PetscCall(MatDenseRestoreArrayWriteAndMemType(((Mat_MPIDense *)A->data)->A, array));
2578cd3f9d89SJunchao Zhang   } else {
2579cd3f9d89SJunchao Zhang     PetscErrorCode (*fptr)(Mat, PetscScalar **);
25803ba16761SJacob Faibussowitsch 
25813ba16761SJacob Faibussowitsch     PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatDenseRestoreArrayWriteAndMemType_C", &fptr));
2582cd3f9d89SJunchao Zhang     if (fptr) {
2583cd3f9d89SJunchao Zhang       PetscCall((*fptr)(A, array));
2584cd3f9d89SJunchao Zhang     } else {
2585cd3f9d89SJunchao Zhang       PetscUseMethod(A, "MatDenseRestoreArrayWrite_C", (Mat, PetscScalar **), (A, array));
2586cd3f9d89SJunchao Zhang     }
2587cd3f9d89SJunchao Zhang     *array = NULL;
2588cd3f9d89SJunchao Zhang   }
2589cd3f9d89SJunchao Zhang   PetscCall(PetscObjectStateIncrease((PetscObject)A));
25903ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2591cd3f9d89SJunchao Zhang }
2592cd3f9d89SJunchao Zhang 
2593d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatCreateSubMatrix_SeqDense(Mat A, IS isrow, IS iscol, MatReuse scall, Mat *B)
2594d71ae5a4SJacob Faibussowitsch {
2595c0bbcb79SLois Curfman McInnes   Mat_SeqDense   *mat = (Mat_SeqDense *)A->data;
2596bf5a80bcSToby Isaac   PetscInt        i, j, nrows, ncols, ldb;
25975d0c19d7SBarry Smith   const PetscInt *irow, *icol;
259887828ca2SBarry Smith   PetscScalar    *av, *bv, *v = mat->v;
25990754003eSLois Curfman McInnes   Mat             newmat;
26000754003eSLois Curfman McInnes 
26013a40ed3dSBarry Smith   PetscFunctionBegin;
26029566063dSJacob Faibussowitsch   PetscCall(ISGetIndices(isrow, &irow));
26039566063dSJacob Faibussowitsch   PetscCall(ISGetIndices(iscol, &icol));
26049566063dSJacob Faibussowitsch   PetscCall(ISGetLocalSize(isrow, &nrows));
26059566063dSJacob Faibussowitsch   PetscCall(ISGetLocalSize(iscol, &ncols));
26060754003eSLois Curfman McInnes 
2607182d2002SSatish Balay   /* Check submatrixcall */
2608182d2002SSatish Balay   if (scall == MAT_REUSE_MATRIX) {
260913f74950SBarry Smith     PetscInt n_cols, n_rows;
26109566063dSJacob Faibussowitsch     PetscCall(MatGetSize(*B, &n_rows, &n_cols));
261121a2c019SBarry Smith     if (n_rows != nrows || n_cols != ncols) {
2612f746d493SDmitry Karpeev       /* resize the result matrix to match number of requested rows/columns */
26139566063dSJacob Faibussowitsch       PetscCall(MatSetSizes(*B, nrows, ncols, nrows, ncols));
261421a2c019SBarry Smith     }
2615182d2002SSatish Balay     newmat = *B;
2616182d2002SSatish Balay   } else {
26170754003eSLois Curfman McInnes     /* Create and fill new matrix */
26189566063dSJacob Faibussowitsch     PetscCall(MatCreate(PetscObjectComm((PetscObject)A), &newmat));
26199566063dSJacob Faibussowitsch     PetscCall(MatSetSizes(newmat, nrows, ncols, nrows, ncols));
26209566063dSJacob Faibussowitsch     PetscCall(MatSetType(newmat, ((PetscObject)A)->type_name));
26219566063dSJacob Faibussowitsch     PetscCall(MatSeqDenseSetPreallocation(newmat, NULL));
2622182d2002SSatish Balay   }
2623182d2002SSatish Balay 
2624182d2002SSatish Balay   /* Now extract the data pointers and do the copy,column at a time */
26259566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArray(newmat, &bv));
26269566063dSJacob Faibussowitsch   PetscCall(MatDenseGetLDA(newmat, &ldb));
2627182d2002SSatish Balay   for (i = 0; i < ncols; i++) {
26286de62eeeSBarry Smith     av = v + mat->lda * icol[i];
2629ca15aa20SStefano Zampini     for (j = 0; j < nrows; j++) bv[j] = av[irow[j]];
2630bf5a80bcSToby Isaac     bv += ldb;
26310754003eSLois Curfman McInnes   }
26329566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArray(newmat, &bv));
2633182d2002SSatish Balay 
2634182d2002SSatish Balay   /* Assemble the matrices so that the correct flags are set */
26359566063dSJacob Faibussowitsch   PetscCall(MatAssemblyBegin(newmat, MAT_FINAL_ASSEMBLY));
26369566063dSJacob Faibussowitsch   PetscCall(MatAssemblyEnd(newmat, MAT_FINAL_ASSEMBLY));
26370754003eSLois Curfman McInnes 
26380754003eSLois Curfman McInnes   /* Free work space */
26399566063dSJacob Faibussowitsch   PetscCall(ISRestoreIndices(isrow, &irow));
26409566063dSJacob Faibussowitsch   PetscCall(ISRestoreIndices(iscol, &icol));
2641182d2002SSatish Balay   *B = newmat;
26423ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
26430754003eSLois Curfman McInnes }
26440754003eSLois Curfman McInnes 
2645d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatCreateSubMatrices_SeqDense(Mat A, PetscInt n, const IS irow[], const IS icol[], MatReuse scall, Mat *B[])
2646d71ae5a4SJacob Faibussowitsch {
264713f74950SBarry Smith   PetscInt i;
2648905e6a2fSBarry Smith 
26493a40ed3dSBarry Smith   PetscFunctionBegin;
265048a46eb9SPierre Jolivet   if (scall == MAT_INITIAL_MATRIX) PetscCall(PetscCalloc1(n, B));
2651905e6a2fSBarry Smith 
265248a46eb9SPierre Jolivet   for (i = 0; i < n; i++) PetscCall(MatCreateSubMatrix_SeqDense(A, irow[i], icol[i], scall, &(*B)[i]));
26533ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2654905e6a2fSBarry Smith }
2655905e6a2fSBarry Smith 
2656d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatAssemblyBegin_SeqDense(Mat mat, MatAssemblyType mode)
2657d71ae5a4SJacob Faibussowitsch {
2658c0aa2d19SHong Zhang   PetscFunctionBegin;
26593ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2660c0aa2d19SHong Zhang }
2661c0aa2d19SHong Zhang 
2662d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatAssemblyEnd_SeqDense(Mat mat, MatAssemblyType mode)
2663d71ae5a4SJacob Faibussowitsch {
2664c0aa2d19SHong Zhang   PetscFunctionBegin;
26653ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2666c0aa2d19SHong Zhang }
2667c0aa2d19SHong Zhang 
2668d71ae5a4SJacob Faibussowitsch PetscErrorCode MatCopy_SeqDense(Mat A, Mat B, MatStructure str)
2669d71ae5a4SJacob Faibussowitsch {
26704b0e389bSBarry Smith   Mat_SeqDense      *a = (Mat_SeqDense *)A->data, *b = (Mat_SeqDense *)B->data;
2671ca15aa20SStefano Zampini   const PetscScalar *va;
2672ca15aa20SStefano Zampini   PetscScalar       *vb;
2673d0f46423SBarry Smith   PetscInt           lda1 = a->lda, lda2 = b->lda, m = A->rmap->n, n = A->cmap->n, j;
26743a40ed3dSBarry Smith 
26753a40ed3dSBarry Smith   PetscFunctionBegin;
267633f4a19fSKris Buschelman   /* If the two matrices don't have the same copy implementation, they aren't compatible for fast copy. */
267733f4a19fSKris Buschelman   if (A->ops->copy != B->ops->copy) {
26789566063dSJacob Faibussowitsch     PetscCall(MatCopy_Basic(A, B, str));
26793ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
26803a40ed3dSBarry Smith   }
2681aed4548fSBarry Smith   PetscCheck(m == B->rmap->n && n == B->cmap->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "size(B) != size(A)");
26829566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArrayRead(A, &va));
26839566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArray(B, &vb));
2684a5ce6ee0Svictorle   if (lda1 > m || lda2 > m) {
268548a46eb9SPierre Jolivet     for (j = 0; j < n; j++) PetscCall(PetscArraycpy(vb + j * lda2, va + j * lda1, m));
2686a5ce6ee0Svictorle   } else {
26879566063dSJacob Faibussowitsch     PetscCall(PetscArraycpy(vb, va, A->rmap->n * A->cmap->n));
2688a5ce6ee0Svictorle   }
26899566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArray(B, &vb));
26909566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArrayRead(A, &va));
26919566063dSJacob Faibussowitsch   PetscCall(MatAssemblyBegin(B, MAT_FINAL_ASSEMBLY));
26929566063dSJacob Faibussowitsch   PetscCall(MatAssemblyEnd(B, MAT_FINAL_ASSEMBLY));
26933ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2694273d9f13SBarry Smith }
2695273d9f13SBarry Smith 
2696d71ae5a4SJacob Faibussowitsch PetscErrorCode MatSetUp_SeqDense(Mat A)
2697d71ae5a4SJacob Faibussowitsch {
2698273d9f13SBarry Smith   PetscFunctionBegin;
26999566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetUp(A->rmap));
27009566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetUp(A->cmap));
270148a46eb9SPierre Jolivet   if (!A->preallocated) PetscCall(MatSeqDenseSetPreallocation(A, NULL));
27023ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
27034b0e389bSBarry Smith }
27044b0e389bSBarry Smith 
2705d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatConjugate_SeqDense(Mat A)
2706d71ae5a4SJacob Faibussowitsch {
27074396437dSToby Isaac   Mat_SeqDense *mat = (Mat_SeqDense *)A->data;
270806c5243aSJose E. Roman   PetscInt      i, j;
27094396437dSToby Isaac   PetscInt      min = PetscMin(A->rmap->n, A->cmap->n);
2710ca15aa20SStefano Zampini   PetscScalar  *aa;
2711ba337c44SJed Brown 
2712ba337c44SJed Brown   PetscFunctionBegin;
27139566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArray(A, &aa));
271406c5243aSJose E. Roman   for (j = 0; j < A->cmap->n; j++) {
271506c5243aSJose E. Roman     for (i = 0; i < A->rmap->n; i++) aa[i + j * mat->lda] = PetscConj(aa[i + j * mat->lda]);
271606c5243aSJose E. Roman   }
27179566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArray(A, &aa));
27189371c9d4SSatish Balay   if (mat->tau)
27199371c9d4SSatish Balay     for (i = 0; i < min; i++) mat->tau[i] = PetscConj(mat->tau[i]);
27203ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2721ba337c44SJed Brown }
2722ba337c44SJed Brown 
2723d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatRealPart_SeqDense(Mat A)
2724d71ae5a4SJacob Faibussowitsch {
272506c5243aSJose E. Roman   Mat_SeqDense *mat = (Mat_SeqDense *)A->data;
272606c5243aSJose E. Roman   PetscInt      i, j;
2727ca15aa20SStefano Zampini   PetscScalar  *aa;
2728ba337c44SJed Brown 
2729ba337c44SJed Brown   PetscFunctionBegin;
27309566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArray(A, &aa));
273106c5243aSJose E. Roman   for (j = 0; j < A->cmap->n; j++) {
273206c5243aSJose E. Roman     for (i = 0; i < A->rmap->n; i++) aa[i + j * mat->lda] = PetscRealPart(aa[i + j * mat->lda]);
273306c5243aSJose E. Roman   }
27349566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArray(A, &aa));
27353ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2736ba337c44SJed Brown }
2737ba337c44SJed Brown 
2738d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatImaginaryPart_SeqDense(Mat A)
2739d71ae5a4SJacob Faibussowitsch {
274006c5243aSJose E. Roman   Mat_SeqDense *mat = (Mat_SeqDense *)A->data;
274106c5243aSJose E. Roman   PetscInt      i, j;
2742ca15aa20SStefano Zampini   PetscScalar  *aa;
2743ba337c44SJed Brown 
2744ba337c44SJed Brown   PetscFunctionBegin;
27459566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArray(A, &aa));
274606c5243aSJose E. Roman   for (j = 0; j < A->cmap->n; j++) {
274706c5243aSJose E. Roman     for (i = 0; i < A->rmap->n; i++) aa[i + j * mat->lda] = PetscImaginaryPart(aa[i + j * mat->lda]);
274806c5243aSJose E. Roman   }
27499566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArray(A, &aa));
27503ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2751ba337c44SJed Brown }
2752284134d9SBarry Smith 
2753d71ae5a4SJacob Faibussowitsch PetscErrorCode MatMatMultSymbolic_SeqDense_SeqDense(Mat A, Mat B, PetscReal fill, Mat C)
2754d71ae5a4SJacob Faibussowitsch {
2755d0f46423SBarry Smith   PetscInt  m = A->rmap->n, n = B->cmap->n;
275647d993e7Ssuyashtn   PetscBool cisdense = PETSC_FALSE;
2757a9fe9ddaSSatish Balay 
2758ee16a9a1SHong Zhang   PetscFunctionBegin;
27599566063dSJacob Faibussowitsch   PetscCall(MatSetSizes(C, m, n, m, n));
276047d993e7Ssuyashtn #if defined(PETSC_HAVE_CUDA)
27619566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompareAny((PetscObject)C, &cisdense, MATSEQDENSE, MATSEQDENSECUDA, ""));
276247d993e7Ssuyashtn #endif
276347d993e7Ssuyashtn #if defined(PETSC_HAVE_HIP)
276447d993e7Ssuyashtn   PetscCall(PetscObjectTypeCompareAny((PetscObject)C, &cisdense, MATSEQDENSE, MATSEQDENSEHIP, ""));
276547d993e7Ssuyashtn #endif
27667a3c3d58SStefano Zampini   if (!cisdense) {
27677a3c3d58SStefano Zampini     PetscBool flg;
27687a3c3d58SStefano Zampini 
27699566063dSJacob Faibussowitsch     PetscCall(PetscObjectTypeCompare((PetscObject)B, ((PetscObject)A)->type_name, &flg));
27709566063dSJacob Faibussowitsch     PetscCall(MatSetType(C, flg ? ((PetscObject)A)->type_name : MATDENSE));
27717a3c3d58SStefano Zampini   }
27729566063dSJacob Faibussowitsch   PetscCall(MatSetUp(C));
27733ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2774ee16a9a1SHong Zhang }
2775a9fe9ddaSSatish Balay 
2776d71ae5a4SJacob Faibussowitsch PetscErrorCode MatMatMultNumeric_SeqDense_SeqDense(Mat A, Mat B, Mat C)
2777d71ae5a4SJacob Faibussowitsch {
27786718818eSStefano Zampini   Mat_SeqDense      *a = (Mat_SeqDense *)A->data, *b = (Mat_SeqDense *)B->data, *c = (Mat_SeqDense *)C->data;
27790805154bSBarry Smith   PetscBLASInt       m, n, k;
2780ca15aa20SStefano Zampini   const PetscScalar *av, *bv;
2781ca15aa20SStefano Zampini   PetscScalar       *cv;
2782a9fe9ddaSSatish Balay   PetscScalar        _DOne = 1.0, _DZero = 0.0;
2783a9fe9ddaSSatish Balay 
2784a9fe9ddaSSatish Balay   PetscFunctionBegin;
27859566063dSJacob Faibussowitsch   PetscCall(PetscBLASIntCast(C->rmap->n, &m));
27869566063dSJacob Faibussowitsch   PetscCall(PetscBLASIntCast(C->cmap->n, &n));
27879566063dSJacob Faibussowitsch   PetscCall(PetscBLASIntCast(A->cmap->n, &k));
27883ba16761SJacob Faibussowitsch   if (!m || !n || !k) PetscFunctionReturn(PETSC_SUCCESS);
27899566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArrayRead(A, &av));
27909566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArrayRead(B, &bv));
27919566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArrayWrite(C, &cv));
2792792fecdfSBarry Smith   PetscCallBLAS("BLASgemm", BLASgemm_("N", "N", &m, &n, &k, &_DOne, av, &a->lda, bv, &b->lda, &_DZero, cv, &c->lda));
27939566063dSJacob Faibussowitsch   PetscCall(PetscLogFlops(1.0 * m * n * k + 1.0 * m * n * (k - 1)));
27949566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArrayRead(A, &av));
27959566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArrayRead(B, &bv));
27969566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArrayWrite(C, &cv));
27973ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2798a9fe9ddaSSatish Balay }
2799a9fe9ddaSSatish Balay 
2800d71ae5a4SJacob Faibussowitsch PetscErrorCode MatMatTransposeMultSymbolic_SeqDense_SeqDense(Mat A, Mat B, PetscReal fill, Mat C)
2801d71ae5a4SJacob Faibussowitsch {
280269f65d41SStefano Zampini   PetscInt  m = A->rmap->n, n = B->rmap->n;
280347d993e7Ssuyashtn   PetscBool cisdense = PETSC_FALSE;
280469f65d41SStefano Zampini 
280569f65d41SStefano Zampini   PetscFunctionBegin;
28069566063dSJacob Faibussowitsch   PetscCall(MatSetSizes(C, m, n, m, n));
280747d993e7Ssuyashtn #if defined(PETSC_HAVE_CUDA)
28089566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompareAny((PetscObject)C, &cisdense, MATSEQDENSE, MATSEQDENSECUDA, ""));
280947d993e7Ssuyashtn #endif
281047d993e7Ssuyashtn #if defined(PETSC_HAVE_HIP)
281147d993e7Ssuyashtn   PetscCall(PetscObjectTypeCompareAny((PetscObject)C, &cisdense, MATSEQDENSE, MATSEQDENSEHIP, ""));
281247d993e7Ssuyashtn #endif
28137a3c3d58SStefano Zampini   if (!cisdense) {
28147a3c3d58SStefano Zampini     PetscBool flg;
28157a3c3d58SStefano Zampini 
28169566063dSJacob Faibussowitsch     PetscCall(PetscObjectTypeCompare((PetscObject)B, ((PetscObject)A)->type_name, &flg));
28179566063dSJacob Faibussowitsch     PetscCall(MatSetType(C, flg ? ((PetscObject)A)->type_name : MATDENSE));
28187a3c3d58SStefano Zampini   }
28199566063dSJacob Faibussowitsch   PetscCall(MatSetUp(C));
28203ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
282169f65d41SStefano Zampini }
282269f65d41SStefano Zampini 
2823d71ae5a4SJacob Faibussowitsch PetscErrorCode MatMatTransposeMultNumeric_SeqDense_SeqDense(Mat A, Mat B, Mat C)
2824d71ae5a4SJacob Faibussowitsch {
282569f65d41SStefano Zampini   Mat_SeqDense      *a = (Mat_SeqDense *)A->data;
282669f65d41SStefano Zampini   Mat_SeqDense      *b = (Mat_SeqDense *)B->data;
282769f65d41SStefano Zampini   Mat_SeqDense      *c = (Mat_SeqDense *)C->data;
28286718818eSStefano Zampini   const PetscScalar *av, *bv;
28296718818eSStefano Zampini   PetscScalar       *cv;
283069f65d41SStefano Zampini   PetscBLASInt       m, n, k;
283169f65d41SStefano Zampini   PetscScalar        _DOne = 1.0, _DZero = 0.0;
283269f65d41SStefano Zampini 
283369f65d41SStefano Zampini   PetscFunctionBegin;
28349566063dSJacob Faibussowitsch   PetscCall(PetscBLASIntCast(C->rmap->n, &m));
28359566063dSJacob Faibussowitsch   PetscCall(PetscBLASIntCast(C->cmap->n, &n));
28369566063dSJacob Faibussowitsch   PetscCall(PetscBLASIntCast(A->cmap->n, &k));
28373ba16761SJacob Faibussowitsch   if (!m || !n || !k) PetscFunctionReturn(PETSC_SUCCESS);
28389566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArrayRead(A, &av));
28399566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArrayRead(B, &bv));
28409566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArrayWrite(C, &cv));
2841792fecdfSBarry Smith   PetscCallBLAS("BLASgemm", BLASgemm_("N", "T", &m, &n, &k, &_DOne, av, &a->lda, bv, &b->lda, &_DZero, cv, &c->lda));
28429566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArrayRead(A, &av));
28439566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArrayRead(B, &bv));
28449566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArrayWrite(C, &cv));
28459566063dSJacob Faibussowitsch   PetscCall(PetscLogFlops(1.0 * m * n * k + 1.0 * m * n * (k - 1)));
28463ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
284769f65d41SStefano Zampini }
284869f65d41SStefano Zampini 
2849d71ae5a4SJacob Faibussowitsch PetscErrorCode MatTransposeMatMultSymbolic_SeqDense_SeqDense(Mat A, Mat B, PetscReal fill, Mat C)
2850d71ae5a4SJacob Faibussowitsch {
2851d0f46423SBarry Smith   PetscInt  m = A->cmap->n, n = B->cmap->n;
285247d993e7Ssuyashtn   PetscBool cisdense = PETSC_FALSE;
2853a9fe9ddaSSatish Balay 
2854ee16a9a1SHong Zhang   PetscFunctionBegin;
28559566063dSJacob Faibussowitsch   PetscCall(MatSetSizes(C, m, n, m, n));
285647d993e7Ssuyashtn #if defined(PETSC_HAVE_CUDA)
28579566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompareAny((PetscObject)C, &cisdense, MATSEQDENSE, MATSEQDENSECUDA, ""));
285847d993e7Ssuyashtn #endif
285947d993e7Ssuyashtn #if defined(PETSC_HAVE_HIP)
286047d993e7Ssuyashtn   PetscCall(PetscObjectTypeCompareAny((PetscObject)C, &cisdense, MATSEQDENSE, MATSEQDENSEHIP, ""));
286147d993e7Ssuyashtn #endif
28627a3c3d58SStefano Zampini   if (!cisdense) {
28637a3c3d58SStefano Zampini     PetscBool flg;
28647a3c3d58SStefano Zampini 
28659566063dSJacob Faibussowitsch     PetscCall(PetscObjectTypeCompare((PetscObject)B, ((PetscObject)A)->type_name, &flg));
28669566063dSJacob Faibussowitsch     PetscCall(MatSetType(C, flg ? ((PetscObject)A)->type_name : MATDENSE));
28677a3c3d58SStefano Zampini   }
28689566063dSJacob Faibussowitsch   PetscCall(MatSetUp(C));
28693ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2870ee16a9a1SHong Zhang }
2871a9fe9ddaSSatish Balay 
2872d71ae5a4SJacob Faibussowitsch PetscErrorCode MatTransposeMatMultNumeric_SeqDense_SeqDense(Mat A, Mat B, Mat C)
2873d71ae5a4SJacob Faibussowitsch {
2874a9fe9ddaSSatish Balay   Mat_SeqDense      *a = (Mat_SeqDense *)A->data;
2875a9fe9ddaSSatish Balay   Mat_SeqDense      *b = (Mat_SeqDense *)B->data;
2876a9fe9ddaSSatish Balay   Mat_SeqDense      *c = (Mat_SeqDense *)C->data;
28776718818eSStefano Zampini   const PetscScalar *av, *bv;
28786718818eSStefano Zampini   PetscScalar       *cv;
28790805154bSBarry Smith   PetscBLASInt       m, n, k;
2880a9fe9ddaSSatish Balay   PetscScalar        _DOne = 1.0, _DZero = 0.0;
2881a9fe9ddaSSatish Balay 
2882a9fe9ddaSSatish Balay   PetscFunctionBegin;
28839566063dSJacob Faibussowitsch   PetscCall(PetscBLASIntCast(C->rmap->n, &m));
28849566063dSJacob Faibussowitsch   PetscCall(PetscBLASIntCast(C->cmap->n, &n));
28859566063dSJacob Faibussowitsch   PetscCall(PetscBLASIntCast(A->rmap->n, &k));
28863ba16761SJacob Faibussowitsch   if (!m || !n || !k) PetscFunctionReturn(PETSC_SUCCESS);
28879566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArrayRead(A, &av));
28889566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArrayRead(B, &bv));
28899566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArrayWrite(C, &cv));
2890792fecdfSBarry Smith   PetscCallBLAS("BLASgemm", BLASgemm_("T", "N", &m, &n, &k, &_DOne, av, &a->lda, bv, &b->lda, &_DZero, cv, &c->lda));
28919566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArrayRead(A, &av));
28929566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArrayRead(B, &bv));
28939566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArrayWrite(C, &cv));
28949566063dSJacob Faibussowitsch   PetscCall(PetscLogFlops(1.0 * m * n * k + 1.0 * m * n * (k - 1)));
28953ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2896a9fe9ddaSSatish Balay }
2897985db425SBarry Smith 
2898d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatProductSetFromOptions_SeqDense_AB(Mat C)
2899d71ae5a4SJacob Faibussowitsch {
29004222ddf1SHong Zhang   PetscFunctionBegin;
29014222ddf1SHong Zhang   C->ops->matmultsymbolic = MatMatMultSymbolic_SeqDense_SeqDense;
29024222ddf1SHong Zhang   C->ops->productsymbolic = MatProductSymbolic_AB;
29033ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
29044222ddf1SHong Zhang }
29054222ddf1SHong Zhang 
2906d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatProductSetFromOptions_SeqDense_AtB(Mat C)
2907d71ae5a4SJacob Faibussowitsch {
29084222ddf1SHong Zhang   PetscFunctionBegin;
29094222ddf1SHong Zhang   C->ops->transposematmultsymbolic = MatTransposeMatMultSymbolic_SeqDense_SeqDense;
29104222ddf1SHong Zhang   C->ops->productsymbolic          = MatProductSymbolic_AtB;
29113ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
29124222ddf1SHong Zhang }
29134222ddf1SHong Zhang 
2914d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatProductSetFromOptions_SeqDense_ABt(Mat C)
2915d71ae5a4SJacob Faibussowitsch {
29164222ddf1SHong Zhang   PetscFunctionBegin;
29174222ddf1SHong Zhang   C->ops->mattransposemultsymbolic = MatMatTransposeMultSymbolic_SeqDense_SeqDense;
29184222ddf1SHong Zhang   C->ops->productsymbolic          = MatProductSymbolic_ABt;
29193ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
29204222ddf1SHong Zhang }
29214222ddf1SHong Zhang 
2922d71ae5a4SJacob Faibussowitsch PETSC_INTERN PetscErrorCode MatProductSetFromOptions_SeqDense(Mat C)
2923d71ae5a4SJacob Faibussowitsch {
29244222ddf1SHong Zhang   Mat_Product *product = C->product;
29254222ddf1SHong Zhang 
29264222ddf1SHong Zhang   PetscFunctionBegin;
29274222ddf1SHong Zhang   switch (product->type) {
2928d71ae5a4SJacob Faibussowitsch   case MATPRODUCT_AB:
2929d71ae5a4SJacob Faibussowitsch     PetscCall(MatProductSetFromOptions_SeqDense_AB(C));
2930d71ae5a4SJacob Faibussowitsch     break;
2931d71ae5a4SJacob Faibussowitsch   case MATPRODUCT_AtB:
2932d71ae5a4SJacob Faibussowitsch     PetscCall(MatProductSetFromOptions_SeqDense_AtB(C));
2933d71ae5a4SJacob Faibussowitsch     break;
2934d71ae5a4SJacob Faibussowitsch   case MATPRODUCT_ABt:
2935d71ae5a4SJacob Faibussowitsch     PetscCall(MatProductSetFromOptions_SeqDense_ABt(C));
2936d71ae5a4SJacob Faibussowitsch     break;
2937d71ae5a4SJacob Faibussowitsch   default:
2938d71ae5a4SJacob Faibussowitsch     break;
29394222ddf1SHong Zhang   }
29403ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
29414222ddf1SHong Zhang }
29424222ddf1SHong Zhang 
2943d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatGetRowMax_SeqDense(Mat A, Vec v, PetscInt idx[])
2944d71ae5a4SJacob Faibussowitsch {
2945985db425SBarry Smith   Mat_SeqDense      *a = (Mat_SeqDense *)A->data;
2946d0f46423SBarry Smith   PetscInt           i, j, m = A->rmap->n, n = A->cmap->n, p;
2947985db425SBarry Smith   PetscScalar       *x;
2948ca15aa20SStefano Zampini   const PetscScalar *aa;
2949985db425SBarry Smith 
2950985db425SBarry Smith   PetscFunctionBegin;
295128b400f6SJacob Faibussowitsch   PetscCheck(!A->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
29529566063dSJacob Faibussowitsch   PetscCall(VecGetArray(v, &x));
29539566063dSJacob Faibussowitsch   PetscCall(VecGetLocalSize(v, &p));
29549566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArrayRead(A, &aa));
295508401ef6SPierre Jolivet   PetscCheck(p == A->rmap->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Nonconforming matrix and vector");
2956985db425SBarry Smith   for (i = 0; i < m; i++) {
29579371c9d4SSatish Balay     x[i] = aa[i];
29589371c9d4SSatish Balay     if (idx) idx[i] = 0;
2959985db425SBarry Smith     for (j = 1; j < n; j++) {
29609371c9d4SSatish Balay       if (PetscRealPart(x[i]) < PetscRealPart(aa[i + a->lda * j])) {
29619371c9d4SSatish Balay         x[i] = aa[i + a->lda * j];
29629371c9d4SSatish Balay         if (idx) idx[i] = j;
29639371c9d4SSatish Balay       }
2964985db425SBarry Smith     }
2965985db425SBarry Smith   }
29669566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArrayRead(A, &aa));
29679566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(v, &x));
29683ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2969985db425SBarry Smith }
2970985db425SBarry Smith 
2971d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatGetRowMaxAbs_SeqDense(Mat A, Vec v, PetscInt idx[])
2972d71ae5a4SJacob Faibussowitsch {
2973985db425SBarry Smith   Mat_SeqDense      *a = (Mat_SeqDense *)A->data;
2974d0f46423SBarry Smith   PetscInt           i, j, m = A->rmap->n, n = A->cmap->n, p;
2975985db425SBarry Smith   PetscScalar       *x;
2976985db425SBarry Smith   PetscReal          atmp;
2977ca15aa20SStefano Zampini   const PetscScalar *aa;
2978985db425SBarry Smith 
2979985db425SBarry Smith   PetscFunctionBegin;
298028b400f6SJacob Faibussowitsch   PetscCheck(!A->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
29819566063dSJacob Faibussowitsch   PetscCall(VecGetArray(v, &x));
29829566063dSJacob Faibussowitsch   PetscCall(VecGetLocalSize(v, &p));
29839566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArrayRead(A, &aa));
298408401ef6SPierre Jolivet   PetscCheck(p == A->rmap->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Nonconforming matrix and vector");
2985985db425SBarry Smith   for (i = 0; i < m; i++) {
29869189402eSHong Zhang     x[i] = PetscAbsScalar(aa[i]);
2987985db425SBarry Smith     for (j = 1; j < n; j++) {
2988ca15aa20SStefano Zampini       atmp = PetscAbsScalar(aa[i + a->lda * j]);
29899371c9d4SSatish Balay       if (PetscAbsScalar(x[i]) < atmp) {
29909371c9d4SSatish Balay         x[i] = atmp;
29919371c9d4SSatish Balay         if (idx) idx[i] = j;
29929371c9d4SSatish Balay       }
2993985db425SBarry Smith     }
2994985db425SBarry Smith   }
29959566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArrayRead(A, &aa));
29969566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(v, &x));
29973ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2998985db425SBarry Smith }
2999985db425SBarry Smith 
3000d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatGetRowMin_SeqDense(Mat A, Vec v, PetscInt idx[])
3001d71ae5a4SJacob Faibussowitsch {
3002985db425SBarry Smith   Mat_SeqDense      *a = (Mat_SeqDense *)A->data;
3003d0f46423SBarry Smith   PetscInt           i, j, m = A->rmap->n, n = A->cmap->n, p;
3004985db425SBarry Smith   PetscScalar       *x;
3005ca15aa20SStefano Zampini   const PetscScalar *aa;
3006985db425SBarry Smith 
3007985db425SBarry Smith   PetscFunctionBegin;
300828b400f6SJacob Faibussowitsch   PetscCheck(!A->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
30099566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArrayRead(A, &aa));
30109566063dSJacob Faibussowitsch   PetscCall(VecGetArray(v, &x));
30119566063dSJacob Faibussowitsch   PetscCall(VecGetLocalSize(v, &p));
301208401ef6SPierre Jolivet   PetscCheck(p == A->rmap->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Nonconforming matrix and vector");
3013985db425SBarry Smith   for (i = 0; i < m; i++) {
30149371c9d4SSatish Balay     x[i] = aa[i];
30159371c9d4SSatish Balay     if (idx) idx[i] = 0;
3016985db425SBarry Smith     for (j = 1; j < n; j++) {
30179371c9d4SSatish Balay       if (PetscRealPart(x[i]) > PetscRealPart(aa[i + a->lda * j])) {
30189371c9d4SSatish Balay         x[i] = aa[i + a->lda * j];
30199371c9d4SSatish Balay         if (idx) idx[i] = j;
30209371c9d4SSatish Balay       }
3021985db425SBarry Smith     }
3022985db425SBarry Smith   }
30239566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(v, &x));
30249566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArrayRead(A, &aa));
30253ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3026985db425SBarry Smith }
3027985db425SBarry Smith 
3028d71ae5a4SJacob Faibussowitsch PetscErrorCode MatGetColumnVector_SeqDense(Mat A, Vec v, PetscInt col)
3029d71ae5a4SJacob Faibussowitsch {
30308d0534beSBarry Smith   Mat_SeqDense      *a = (Mat_SeqDense *)A->data;
30318d0534beSBarry Smith   PetscScalar       *x;
3032ca15aa20SStefano Zampini   const PetscScalar *aa;
30338d0534beSBarry Smith 
30348d0534beSBarry Smith   PetscFunctionBegin;
303528b400f6SJacob Faibussowitsch   PetscCheck(!A->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
30369566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArrayRead(A, &aa));
30379566063dSJacob Faibussowitsch   PetscCall(VecGetArray(v, &x));
30389566063dSJacob Faibussowitsch   PetscCall(PetscArraycpy(x, aa + col * a->lda, A->rmap->n));
30399566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(v, &x));
30409566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArrayRead(A, &aa));
30413ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
30428d0534beSBarry Smith }
30438d0534beSBarry Smith 
3044d71ae5a4SJacob Faibussowitsch PETSC_INTERN PetscErrorCode MatGetColumnReductions_SeqDense(Mat A, PetscInt type, PetscReal *reductions)
3045d71ae5a4SJacob Faibussowitsch {
30460716a85fSBarry Smith   PetscInt           i, j, m, n;
30471683a169SBarry Smith   const PetscScalar *a;
30480716a85fSBarry Smith 
30490716a85fSBarry Smith   PetscFunctionBegin;
30509566063dSJacob Faibussowitsch   PetscCall(MatGetSize(A, &m, &n));
30519566063dSJacob Faibussowitsch   PetscCall(PetscArrayzero(reductions, n));
30529566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArrayRead(A, &a));
3053857cbf51SRichard Tran Mills   if (type == NORM_2) {
30540716a85fSBarry Smith     for (i = 0; i < n; i++) {
3055ad540459SPierre Jolivet       for (j = 0; j < m; j++) reductions[i] += PetscAbsScalar(a[j] * a[j]);
30560716a85fSBarry Smith       a += m;
30570716a85fSBarry Smith     }
3058857cbf51SRichard Tran Mills   } else if (type == NORM_1) {
30590716a85fSBarry Smith     for (i = 0; i < n; i++) {
3060ad540459SPierre Jolivet       for (j = 0; j < m; j++) reductions[i] += PetscAbsScalar(a[j]);
30610716a85fSBarry Smith       a += m;
30620716a85fSBarry Smith     }
3063857cbf51SRichard Tran Mills   } else if (type == NORM_INFINITY) {
30640716a85fSBarry Smith     for (i = 0; i < n; i++) {
3065ad540459SPierre Jolivet       for (j = 0; j < m; j++) reductions[i] = PetscMax(PetscAbsScalar(a[j]), reductions[i]);
30660716a85fSBarry Smith       a += m;
30670716a85fSBarry Smith     }
3068857cbf51SRichard Tran Mills   } else if (type == REDUCTION_SUM_REALPART || type == REDUCTION_MEAN_REALPART) {
3069a873a8cdSSam Reynolds     for (i = 0; i < n; i++) {
3070ad540459SPierre Jolivet       for (j = 0; j < m; j++) reductions[i] += PetscRealPart(a[j]);
3071a873a8cdSSam Reynolds       a += m;
3072a873a8cdSSam Reynolds     }
3073857cbf51SRichard Tran Mills   } else if (type == REDUCTION_SUM_IMAGINARYPART || type == REDUCTION_MEAN_IMAGINARYPART) {
3074857cbf51SRichard Tran Mills     for (i = 0; i < n; i++) {
3075ad540459SPierre Jolivet       for (j = 0; j < m; j++) reductions[i] += PetscImaginaryPart(a[j]);
3076857cbf51SRichard Tran Mills       a += m;
3077857cbf51SRichard Tran Mills     }
3078857cbf51SRichard Tran Mills   } else SETERRQ(PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONG, "Unknown reduction type");
30799566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArrayRead(A, &a));
3080857cbf51SRichard Tran Mills   if (type == NORM_2) {
3081a873a8cdSSam Reynolds     for (i = 0; i < n; i++) reductions[i] = PetscSqrtReal(reductions[i]);
3082857cbf51SRichard Tran Mills   } else if (type == REDUCTION_MEAN_REALPART || type == REDUCTION_MEAN_IMAGINARYPART) {
3083a873a8cdSSam Reynolds     for (i = 0; i < n; i++) reductions[i] /= m;
30840716a85fSBarry Smith   }
30853ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
30860716a85fSBarry Smith }
30870716a85fSBarry Smith 
3088d71ae5a4SJacob Faibussowitsch PetscErrorCode MatSetRandom_SeqDense(Mat x, PetscRandom rctx)
3089d71ae5a4SJacob Faibussowitsch {
309073a71a0fSBarry Smith   PetscScalar *a;
3091637a0070SStefano Zampini   PetscInt     lda, m, n, i, j;
309273a71a0fSBarry Smith 
309373a71a0fSBarry Smith   PetscFunctionBegin;
30949566063dSJacob Faibussowitsch   PetscCall(MatGetSize(x, &m, &n));
30959566063dSJacob Faibussowitsch   PetscCall(MatDenseGetLDA(x, &lda));
30963faff063SStefano Zampini   PetscCall(MatDenseGetArrayWrite(x, &a));
3097637a0070SStefano Zampini   for (j = 0; j < n; j++) {
309848a46eb9SPierre Jolivet     for (i = 0; i < m; i++) PetscCall(PetscRandomGetValue(rctx, a + j * lda + i));
309973a71a0fSBarry Smith   }
31003faff063SStefano Zampini   PetscCall(MatDenseRestoreArrayWrite(x, &a));
31013ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
310273a71a0fSBarry Smith }
310373a71a0fSBarry Smith 
3104d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatMissingDiagonal_SeqDense(Mat A, PetscBool *missing, PetscInt *d)
3105d71ae5a4SJacob Faibussowitsch {
31063b49f96aSBarry Smith   PetscFunctionBegin;
31073b49f96aSBarry Smith   *missing = PETSC_FALSE;
31083ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
31093b49f96aSBarry Smith }
311073a71a0fSBarry Smith 
3111ca15aa20SStefano Zampini /* vals is not const */
3112d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatDenseGetColumn_SeqDense(Mat A, PetscInt col, PetscScalar **vals)
3113d71ae5a4SJacob Faibussowitsch {
311486aefd0dSHong Zhang   Mat_SeqDense *a = (Mat_SeqDense *)A->data;
3115ca15aa20SStefano Zampini   PetscScalar  *v;
311686aefd0dSHong Zhang 
311786aefd0dSHong Zhang   PetscFunctionBegin;
311828b400f6SJacob Faibussowitsch   PetscCheck(!A->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
31199566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArray(A, &v));
3120ca15aa20SStefano Zampini   *vals = v + col * a->lda;
31219566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArray(A, &v));
31223ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
312386aefd0dSHong Zhang }
312486aefd0dSHong Zhang 
3125d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatDenseRestoreColumn_SeqDense(Mat A, PetscScalar **vals)
3126d71ae5a4SJacob Faibussowitsch {
312786aefd0dSHong Zhang   PetscFunctionBegin;
3128742765d3SMatthew Knepley   if (vals) *vals = NULL; /* user cannot accidentally use the array later */
31293ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
313086aefd0dSHong Zhang }
3131abc3b08eSStefano Zampini 
3132a5ae1ecdSBarry Smith static struct _MatOps MatOps_Values = {MatSetValues_SeqDense,
3133905e6a2fSBarry Smith                                        MatGetRow_SeqDense,
3134905e6a2fSBarry Smith                                        MatRestoreRow_SeqDense,
3135905e6a2fSBarry Smith                                        MatMult_SeqDense,
313697304618SKris Buschelman                                        /*  4*/ MatMultAdd_SeqDense,
31377c922b88SBarry Smith                                        MatMultTranspose_SeqDense,
31387c922b88SBarry Smith                                        MatMultTransposeAdd_SeqDense,
3139f4259b30SLisandro Dalcin                                        NULL,
3140f4259b30SLisandro Dalcin                                        NULL,
3141f4259b30SLisandro Dalcin                                        NULL,
3142f4259b30SLisandro Dalcin                                        /* 10*/ NULL,
3143905e6a2fSBarry Smith                                        MatLUFactor_SeqDense,
3144905e6a2fSBarry Smith                                        MatCholeskyFactor_SeqDense,
314541f059aeSBarry Smith                                        MatSOR_SeqDense,
3146ec8511deSBarry Smith                                        MatTranspose_SeqDense,
314797304618SKris Buschelman                                        /* 15*/ MatGetInfo_SeqDense,
3148905e6a2fSBarry Smith                                        MatEqual_SeqDense,
3149905e6a2fSBarry Smith                                        MatGetDiagonal_SeqDense,
3150905e6a2fSBarry Smith                                        MatDiagonalScale_SeqDense,
3151905e6a2fSBarry Smith                                        MatNorm_SeqDense,
3152c0aa2d19SHong Zhang                                        /* 20*/ MatAssemblyBegin_SeqDense,
3153c0aa2d19SHong Zhang                                        MatAssemblyEnd_SeqDense,
3154905e6a2fSBarry Smith                                        MatSetOption_SeqDense,
3155905e6a2fSBarry Smith                                        MatZeroEntries_SeqDense,
3156d519adbfSMatthew Knepley                                        /* 24*/ MatZeroRows_SeqDense,
3157f4259b30SLisandro Dalcin                                        NULL,
3158f4259b30SLisandro Dalcin                                        NULL,
3159f4259b30SLisandro Dalcin                                        NULL,
3160f4259b30SLisandro Dalcin                                        NULL,
31614994cf47SJed Brown                                        /* 29*/ MatSetUp_SeqDense,
3162f4259b30SLisandro Dalcin                                        NULL,
3163f4259b30SLisandro Dalcin                                        NULL,
3164f4259b30SLisandro Dalcin                                        NULL,
3165f4259b30SLisandro Dalcin                                        NULL,
3166d519adbfSMatthew Knepley                                        /* 34*/ MatDuplicate_SeqDense,
3167f4259b30SLisandro Dalcin                                        NULL,
3168f4259b30SLisandro Dalcin                                        NULL,
3169f4259b30SLisandro Dalcin                                        NULL,
3170f4259b30SLisandro Dalcin                                        NULL,
3171d519adbfSMatthew Knepley                                        /* 39*/ MatAXPY_SeqDense,
31727dae84e0SHong Zhang                                        MatCreateSubMatrices_SeqDense,
3173f4259b30SLisandro Dalcin                                        NULL,
31744b0e389bSBarry Smith                                        MatGetValues_SeqDense,
3175a5ae1ecdSBarry Smith                                        MatCopy_SeqDense,
3176d519adbfSMatthew Knepley                                        /* 44*/ MatGetRowMax_SeqDense,
3177a5ae1ecdSBarry Smith                                        MatScale_SeqDense,
31782f605a99SJose E. Roman                                        MatShift_SeqDense,
3179f4259b30SLisandro Dalcin                                        NULL,
31803f49a652SStefano Zampini                                        MatZeroRowsColumns_SeqDense,
318173a71a0fSBarry Smith                                        /* 49*/ MatSetRandom_SeqDense,
3182f4259b30SLisandro Dalcin                                        NULL,
3183f4259b30SLisandro Dalcin                                        NULL,
3184f4259b30SLisandro Dalcin                                        NULL,
3185f4259b30SLisandro Dalcin                                        NULL,
3186f4259b30SLisandro Dalcin                                        /* 54*/ NULL,
3187f4259b30SLisandro Dalcin                                        NULL,
3188f4259b30SLisandro Dalcin                                        NULL,
3189f4259b30SLisandro Dalcin                                        NULL,
3190f4259b30SLisandro Dalcin                                        NULL,
3191023c16fcSToby Isaac                                        /* 59*/ MatCreateSubMatrix_SeqDense,
3192e03a110bSBarry Smith                                        MatDestroy_SeqDense,
3193e03a110bSBarry Smith                                        MatView_SeqDense,
3194f4259b30SLisandro Dalcin                                        NULL,
3195f4259b30SLisandro Dalcin                                        NULL,
3196f4259b30SLisandro Dalcin                                        /* 64*/ NULL,
3197f4259b30SLisandro Dalcin                                        NULL,
3198f4259b30SLisandro Dalcin                                        NULL,
3199f4259b30SLisandro Dalcin                                        NULL,
3200f4259b30SLisandro Dalcin                                        NULL,
3201d519adbfSMatthew Knepley                                        /* 69*/ MatGetRowMaxAbs_SeqDense,
3202f4259b30SLisandro Dalcin                                        NULL,
3203f4259b30SLisandro Dalcin                                        NULL,
3204f4259b30SLisandro Dalcin                                        NULL,
3205f4259b30SLisandro Dalcin                                        NULL,
3206f4259b30SLisandro Dalcin                                        /* 74*/ NULL,
3207f4259b30SLisandro Dalcin                                        NULL,
3208f4259b30SLisandro Dalcin                                        NULL,
3209f4259b30SLisandro Dalcin                                        NULL,
3210f4259b30SLisandro Dalcin                                        NULL,
3211f4259b30SLisandro Dalcin                                        /* 79*/ NULL,
3212f4259b30SLisandro Dalcin                                        NULL,
3213f4259b30SLisandro Dalcin                                        NULL,
3214f4259b30SLisandro Dalcin                                        NULL,
32155bba2384SShri Abhyankar                                        /* 83*/ MatLoad_SeqDense,
3216637a0070SStefano Zampini                                        MatIsSymmetric_SeqDense,
32171cbb95d3SBarry Smith                                        MatIsHermitian_SeqDense,
3218f4259b30SLisandro Dalcin                                        NULL,
3219f4259b30SLisandro Dalcin                                        NULL,
3220f4259b30SLisandro Dalcin                                        NULL,
3221f4259b30SLisandro Dalcin                                        /* 89*/ NULL,
3222f4259b30SLisandro Dalcin                                        NULL,
3223a9fe9ddaSSatish Balay                                        MatMatMultNumeric_SeqDense_SeqDense,
3224f4259b30SLisandro Dalcin                                        NULL,
3225f4259b30SLisandro Dalcin                                        NULL,
3226f4259b30SLisandro Dalcin                                        /* 94*/ NULL,
3227f4259b30SLisandro Dalcin                                        NULL,
3228f4259b30SLisandro Dalcin                                        NULL,
322969f65d41SStefano Zampini                                        MatMatTransposeMultNumeric_SeqDense_SeqDense,
3230f4259b30SLisandro Dalcin                                        NULL,
32314222ddf1SHong Zhang                                        /* 99*/ MatProductSetFromOptions_SeqDense,
3232f4259b30SLisandro Dalcin                                        NULL,
3233f4259b30SLisandro Dalcin                                        NULL,
3234ba337c44SJed Brown                                        MatConjugate_SeqDense,
3235f4259b30SLisandro Dalcin                                        NULL,
3236f4259b30SLisandro Dalcin                                        /*104*/ NULL,
3237ba337c44SJed Brown                                        MatRealPart_SeqDense,
3238ba337c44SJed Brown                                        MatImaginaryPart_SeqDense,
3239f4259b30SLisandro Dalcin                                        NULL,
3240f4259b30SLisandro Dalcin                                        NULL,
3241f4259b30SLisandro Dalcin                                        /*109*/ NULL,
3242f4259b30SLisandro Dalcin                                        NULL,
32438d0534beSBarry Smith                                        MatGetRowMin_SeqDense,
3244aabbc4fbSShri Abhyankar                                        MatGetColumnVector_SeqDense,
32453b49f96aSBarry Smith                                        MatMissingDiagonal_SeqDense,
3246f4259b30SLisandro Dalcin                                        /*114*/ NULL,
3247f4259b30SLisandro Dalcin                                        NULL,
3248f4259b30SLisandro Dalcin                                        NULL,
3249f4259b30SLisandro Dalcin                                        NULL,
3250f4259b30SLisandro Dalcin                                        NULL,
3251f4259b30SLisandro Dalcin                                        /*119*/ NULL,
3252f4259b30SLisandro Dalcin                                        NULL,
3253f4259b30SLisandro Dalcin                                        NULL,
3254f4259b30SLisandro Dalcin                                        NULL,
3255f4259b30SLisandro Dalcin                                        NULL,
3256f4259b30SLisandro Dalcin                                        /*124*/ NULL,
3257a873a8cdSSam Reynolds                                        MatGetColumnReductions_SeqDense,
3258f4259b30SLisandro Dalcin                                        NULL,
3259f4259b30SLisandro Dalcin                                        NULL,
3260f4259b30SLisandro Dalcin                                        NULL,
3261f4259b30SLisandro Dalcin                                        /*129*/ NULL,
3262f4259b30SLisandro Dalcin                                        NULL,
3263f4259b30SLisandro Dalcin                                        NULL,
326475648e8dSHong Zhang                                        MatTransposeMatMultNumeric_SeqDense_SeqDense,
3265f4259b30SLisandro Dalcin                                        NULL,
3266f4259b30SLisandro Dalcin                                        /*134*/ NULL,
3267f4259b30SLisandro Dalcin                                        NULL,
3268f4259b30SLisandro Dalcin                                        NULL,
3269f4259b30SLisandro Dalcin                                        NULL,
3270f4259b30SLisandro Dalcin                                        NULL,
3271f4259b30SLisandro Dalcin                                        /*139*/ NULL,
3272f4259b30SLisandro Dalcin                                        NULL,
3273f4259b30SLisandro Dalcin                                        NULL,
3274f4259b30SLisandro Dalcin                                        NULL,
3275f4259b30SLisandro Dalcin                                        NULL,
32764222ddf1SHong Zhang                                        MatCreateMPIMatConcatenateSeqMat_SeqDense,
3277f4259b30SLisandro Dalcin                                        /*145*/ NULL,
3278f4259b30SLisandro Dalcin                                        NULL,
327999a7f59eSMark Adams                                        NULL,
328099a7f59eSMark Adams                                        NULL,
32817fb60732SBarry Smith                                        NULL,
3282dec0b466SHong Zhang                                        /*150*/ NULL,
3283dec0b466SHong Zhang                                        NULL};
328490ace30eSBarry Smith 
32854b828684SBarry Smith /*@C
328611a5261eSBarry Smith    MatCreateSeqDense - Creates a `MATSEQDENSE` that
3287*2ef1f0ffSBarry Smith    is stored in column major order (the usual Fortran manner). Many
3288d65003e9SLois Curfman McInnes    of the matrix operations use the BLAS and LAPACK routines.
3289289bc588SBarry Smith 
3290d083f849SBarry Smith    Collective
3291db81eaa0SLois Curfman McInnes 
329220563c6bSBarry Smith    Input Parameters:
329311a5261eSBarry Smith +  comm - MPI communicator, set to `PETSC_COMM_SELF`
32940c775827SLois Curfman McInnes .  m - number of rows
329518f449edSLois Curfman McInnes .  n - number of columns
3296*2ef1f0ffSBarry Smith -  data - optional location of matrix data in column major order.  Use `NULL` for PETSc
3297dfc5480cSLois Curfman McInnes    to control all matrix memory allocation.
329820563c6bSBarry Smith 
329920563c6bSBarry Smith    Output Parameter:
330044cd7ae7SLois Curfman McInnes .  A - the matrix
330120563c6bSBarry Smith 
3302*2ef1f0ffSBarry Smith    Level: intermediate
3303*2ef1f0ffSBarry Smith 
330411a5261eSBarry Smith    Note:
330518f449edSLois Curfman McInnes    The data input variable is intended primarily for Fortran programmers
330618f449edSLois Curfman McInnes    who wish to allocate their own matrix memory space.  Most users should
3307*2ef1f0ffSBarry Smith    set `data` = `NULL`.
330818f449edSLois Curfman McInnes 
3309*2ef1f0ffSBarry Smith .seealso: [](chapter_matrices), `Mat`, `MATSEQDENSE`, `MatCreate()`, `MatCreateDense()`, `MatSetValues()`
331020563c6bSBarry Smith @*/
3311d71ae5a4SJacob Faibussowitsch PetscErrorCode MatCreateSeqDense(MPI_Comm comm, PetscInt m, PetscInt n, PetscScalar *data, Mat *A)
3312d71ae5a4SJacob Faibussowitsch {
33133a40ed3dSBarry Smith   PetscFunctionBegin;
33149566063dSJacob Faibussowitsch   PetscCall(MatCreate(comm, A));
33159566063dSJacob Faibussowitsch   PetscCall(MatSetSizes(*A, m, n, m, n));
33169566063dSJacob Faibussowitsch   PetscCall(MatSetType(*A, MATSEQDENSE));
33179566063dSJacob Faibussowitsch   PetscCall(MatSeqDenseSetPreallocation(*A, data));
33183ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3319273d9f13SBarry Smith }
3320273d9f13SBarry Smith 
3321273d9f13SBarry Smith /*@C
332211a5261eSBarry Smith    MatSeqDenseSetPreallocation - Sets the array used for storing the matrix elements of a `MATSEQDENSE` matrix
3323273d9f13SBarry Smith 
3324d083f849SBarry Smith    Collective
3325273d9f13SBarry Smith 
3326273d9f13SBarry Smith    Input Parameters:
33271c4f3114SJed Brown +  B - the matrix
3328*2ef1f0ffSBarry Smith -  data - the array (or `NULL`)
3329*2ef1f0ffSBarry Smith 
3330*2ef1f0ffSBarry Smith    Level: intermediate
3331273d9f13SBarry Smith 
333211a5261eSBarry Smith    Note:
3333273d9f13SBarry Smith    The data input variable is intended primarily for Fortran programmers
3334273d9f13SBarry Smith    who wish to allocate their own matrix memory space.  Most users should
3335284134d9SBarry Smith    need not call this routine.
3336273d9f13SBarry Smith 
3337*2ef1f0ffSBarry Smith .seealso: [](chapter_matrices), `Mat`, `MATSEQDENSE`, `MatCreate()`, `MatCreateDense()`, `MatSetValues()`, `MatDenseSetLDA()`
3338273d9f13SBarry Smith @*/
3339d71ae5a4SJacob Faibussowitsch PetscErrorCode MatSeqDenseSetPreallocation(Mat B, PetscScalar data[])
3340d71ae5a4SJacob Faibussowitsch {
3341a23d5eceSKris Buschelman   PetscFunctionBegin;
3342d5ea218eSStefano Zampini   PetscValidHeaderSpecific(B, MAT_CLASSID, 1);
3343cac4c232SBarry Smith   PetscTryMethod(B, "MatSeqDenseSetPreallocation_C", (Mat, PetscScalar[]), (B, data));
33443ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3345a23d5eceSKris Buschelman }
3346a23d5eceSKris Buschelman 
3347d71ae5a4SJacob Faibussowitsch PetscErrorCode MatSeqDenseSetPreallocation_SeqDense(Mat B, PetscScalar *data)
3348d71ae5a4SJacob Faibussowitsch {
3349ad16ce7aSStefano Zampini   Mat_SeqDense *b = (Mat_SeqDense *)B->data;
3350273d9f13SBarry Smith 
3351273d9f13SBarry Smith   PetscFunctionBegin;
335228b400f6SJacob Faibussowitsch   PetscCheck(!b->matinuse, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Need to call MatDenseRestoreSubMatrix() first");
3353273d9f13SBarry Smith   B->preallocated = PETSC_TRUE;
3354a868139aSShri Abhyankar 
33559566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetUp(B->rmap));
33569566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetUp(B->cmap));
335734ef9618SShri Abhyankar 
3358ad16ce7aSStefano Zampini   if (b->lda <= 0) b->lda = B->rmap->n;
335986d161a7SShri Abhyankar 
33609e8f95c4SLisandro Dalcin   if (!data) { /* petsc-allocated storage */
33619566063dSJacob Faibussowitsch     if (!b->user_alloc) PetscCall(PetscFree(b->v));
33629566063dSJacob Faibussowitsch     PetscCall(PetscCalloc1((size_t)b->lda * B->cmap->n, &b->v));
33632205254eSKarl Rupp 
33649e8f95c4SLisandro Dalcin     b->user_alloc = PETSC_FALSE;
3365273d9f13SBarry Smith   } else { /* user-allocated storage */
33669566063dSJacob Faibussowitsch     if (!b->user_alloc) PetscCall(PetscFree(b->v));
3367273d9f13SBarry Smith     b->v          = data;
3368273d9f13SBarry Smith     b->user_alloc = PETSC_TRUE;
3369273d9f13SBarry Smith   }
33700450473dSBarry Smith   B->assembled = PETSC_TRUE;
33713ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3372273d9f13SBarry Smith }
3373273d9f13SBarry Smith 
337465b80a83SHong Zhang #if defined(PETSC_HAVE_ELEMENTAL)
3375d71ae5a4SJacob Faibussowitsch PETSC_INTERN PetscErrorCode MatConvert_SeqDense_Elemental(Mat A, MatType newtype, MatReuse reuse, Mat *newmat)
3376d71ae5a4SJacob Faibussowitsch {
3377d77f618aSHong Zhang   Mat                mat_elemental;
33781683a169SBarry Smith   const PetscScalar *array;
33791683a169SBarry Smith   PetscScalar       *v_colwise;
3380d77f618aSHong Zhang   PetscInt           M = A->rmap->N, N = A->cmap->N, i, j, k, *rows, *cols;
3381d77f618aSHong Zhang 
33828baccfbdSHong Zhang   PetscFunctionBegin;
33839566063dSJacob Faibussowitsch   PetscCall(PetscMalloc3(M * N, &v_colwise, M, &rows, N, &cols));
33849566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArrayRead(A, &array));
3385d77f618aSHong Zhang   /* convert column-wise array into row-wise v_colwise, see MatSetValues_Elemental() */
3386d77f618aSHong Zhang   k = 0;
3387d77f618aSHong Zhang   for (j = 0; j < N; j++) {
3388d77f618aSHong Zhang     cols[j] = j;
3389ad540459SPierre Jolivet     for (i = 0; i < M; i++) v_colwise[j * M + i] = array[k++];
3390d77f618aSHong Zhang   }
3391ad540459SPierre Jolivet   for (i = 0; i < M; i++) rows[i] = i;
33929566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArrayRead(A, &array));
3393d77f618aSHong Zhang 
33949566063dSJacob Faibussowitsch   PetscCall(MatCreate(PetscObjectComm((PetscObject)A), &mat_elemental));
33959566063dSJacob Faibussowitsch   PetscCall(MatSetSizes(mat_elemental, PETSC_DECIDE, PETSC_DECIDE, M, N));
33969566063dSJacob Faibussowitsch   PetscCall(MatSetType(mat_elemental, MATELEMENTAL));
33979566063dSJacob Faibussowitsch   PetscCall(MatSetUp(mat_elemental));
3398d77f618aSHong Zhang 
3399d77f618aSHong Zhang   /* PETSc-Elemental interaface uses axpy for setting off-processor entries, only ADD_VALUES is allowed */
34009566063dSJacob Faibussowitsch   PetscCall(MatSetValues(mat_elemental, M, rows, N, cols, v_colwise, ADD_VALUES));
34019566063dSJacob Faibussowitsch   PetscCall(MatAssemblyBegin(mat_elemental, MAT_FINAL_ASSEMBLY));
34029566063dSJacob Faibussowitsch   PetscCall(MatAssemblyEnd(mat_elemental, MAT_FINAL_ASSEMBLY));
34039566063dSJacob Faibussowitsch   PetscCall(PetscFree3(v_colwise, rows, cols));
3404d77f618aSHong Zhang 
3405511c6705SHong Zhang   if (reuse == MAT_INPLACE_MATRIX) {
34069566063dSJacob Faibussowitsch     PetscCall(MatHeaderReplace(A, &mat_elemental));
3407d77f618aSHong Zhang   } else {
3408d77f618aSHong Zhang     *newmat = mat_elemental;
3409d77f618aSHong Zhang   }
34103ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
34118baccfbdSHong Zhang }
341265b80a83SHong Zhang #endif
34138baccfbdSHong Zhang 
3414d71ae5a4SJacob Faibussowitsch PetscErrorCode MatDenseSetLDA_SeqDense(Mat B, PetscInt lda)
3415d71ae5a4SJacob Faibussowitsch {
34161b807ce4Svictorle   Mat_SeqDense *b = (Mat_SeqDense *)B->data;
34177422da62SJose E. Roman   PetscBool     data;
341821a2c019SBarry Smith 
34191b807ce4Svictorle   PetscFunctionBegin;
34207422da62SJose E. Roman   data = (PetscBool)((B->rmap->n > 0 && B->cmap->n > 0) ? (b->v ? PETSC_TRUE : PETSC_FALSE) : PETSC_FALSE);
3421aed4548fSBarry Smith   PetscCheck(b->user_alloc || !data || b->lda == lda, PETSC_COMM_SELF, PETSC_ERR_ORDER, "LDA cannot be changed after allocation of internal storage");
342208401ef6SPierre Jolivet   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);
34231b807ce4Svictorle   b->lda = lda;
34243ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
34251b807ce4Svictorle }
34261b807ce4Svictorle 
3427d71ae5a4SJacob Faibussowitsch PetscErrorCode MatCreateMPIMatConcatenateSeqMat_SeqDense(MPI_Comm comm, Mat inmat, PetscInt n, MatReuse scall, Mat *outmat)
3428d71ae5a4SJacob Faibussowitsch {
3429d528f656SJakub Kruzik   PetscFunctionBegin;
34309566063dSJacob Faibussowitsch   PetscCall(MatCreateMPIMatConcatenateSeqMat_MPIDense(comm, inmat, n, scall, outmat));
34313ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3432d528f656SJakub Kruzik }
3433d528f656SJakub Kruzik 
3434d71ae5a4SJacob Faibussowitsch PetscErrorCode MatDenseGetColumnVec_SeqDense(Mat A, PetscInt col, Vec *v)
3435d71ae5a4SJacob Faibussowitsch {
34366947451fSStefano Zampini   Mat_SeqDense *a = (Mat_SeqDense *)A->data;
34376947451fSStefano Zampini 
34386947451fSStefano Zampini   PetscFunctionBegin;
343928b400f6SJacob Faibussowitsch   PetscCheck(!a->vecinuse, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Need to call MatDenseRestoreColumnVec() first");
344028b400f6SJacob Faibussowitsch   PetscCheck(!a->matinuse, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Need to call MatDenseRestoreSubMatrix() first");
34414dfa11a4SJacob Faibussowitsch   if (!a->cvec) { PetscCall(VecCreateSeqWithArray(PetscObjectComm((PetscObject)A), A->rmap->bs, A->rmap->n, NULL, &a->cvec)); }
34426947451fSStefano Zampini   a->vecinuse = col + 1;
34439566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArray(A, (PetscScalar **)&a->ptrinuse));
34449566063dSJacob Faibussowitsch   PetscCall(VecPlaceArray(a->cvec, a->ptrinuse + (size_t)col * (size_t)a->lda));
34456947451fSStefano Zampini   *v = a->cvec;
34463ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
34476947451fSStefano Zampini }
34486947451fSStefano Zampini 
3449d71ae5a4SJacob Faibussowitsch PetscErrorCode MatDenseRestoreColumnVec_SeqDense(Mat A, PetscInt col, Vec *v)
3450d71ae5a4SJacob Faibussowitsch {
34516947451fSStefano Zampini   Mat_SeqDense *a = (Mat_SeqDense *)A->data;
34526947451fSStefano Zampini 
34536947451fSStefano Zampini   PetscFunctionBegin;
345428b400f6SJacob Faibussowitsch   PetscCheck(a->vecinuse, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Need to call MatDenseGetColumnVec() first");
345528b400f6SJacob Faibussowitsch   PetscCheck(a->cvec, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Missing internal column vector");
34566947451fSStefano Zampini   a->vecinuse = 0;
34579566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArray(A, (PetscScalar **)&a->ptrinuse));
34589566063dSJacob Faibussowitsch   PetscCall(VecResetArray(a->cvec));
345975f6d85dSStefano Zampini   if (v) *v = NULL;
34603ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
34616947451fSStefano Zampini }
34626947451fSStefano Zampini 
3463d71ae5a4SJacob Faibussowitsch PetscErrorCode MatDenseGetColumnVecRead_SeqDense(Mat A, PetscInt col, Vec *v)
3464d71ae5a4SJacob Faibussowitsch {
34656947451fSStefano Zampini   Mat_SeqDense *a = (Mat_SeqDense *)A->data;
34666947451fSStefano Zampini 
34676947451fSStefano Zampini   PetscFunctionBegin;
346828b400f6SJacob Faibussowitsch   PetscCheck(!a->vecinuse, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Need to call MatDenseRestoreColumnVec() first");
346928b400f6SJacob Faibussowitsch   PetscCheck(!a->matinuse, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Need to call MatDenseRestoreSubMatrix() first");
34704dfa11a4SJacob Faibussowitsch   if (!a->cvec) { PetscCall(VecCreateSeqWithArray(PetscObjectComm((PetscObject)A), A->rmap->bs, A->rmap->n, NULL, &a->cvec)); }
34716947451fSStefano Zampini   a->vecinuse = col + 1;
34729566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArrayRead(A, &a->ptrinuse));
34739566063dSJacob Faibussowitsch   PetscCall(VecPlaceArray(a->cvec, a->ptrinuse + (size_t)col * (size_t)a->lda));
34749566063dSJacob Faibussowitsch   PetscCall(VecLockReadPush(a->cvec));
34756947451fSStefano Zampini   *v = a->cvec;
34763ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
34776947451fSStefano Zampini }
34786947451fSStefano Zampini 
3479d71ae5a4SJacob Faibussowitsch PetscErrorCode MatDenseRestoreColumnVecRead_SeqDense(Mat A, PetscInt col, Vec *v)
3480d71ae5a4SJacob Faibussowitsch {
34816947451fSStefano Zampini   Mat_SeqDense *a = (Mat_SeqDense *)A->data;
34826947451fSStefano Zampini 
34836947451fSStefano Zampini   PetscFunctionBegin;
348428b400f6SJacob Faibussowitsch   PetscCheck(a->vecinuse, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Need to call MatDenseGetColumnVec() first");
348528b400f6SJacob Faibussowitsch   PetscCheck(a->cvec, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Missing internal column vector");
34866947451fSStefano Zampini   a->vecinuse = 0;
34879566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArrayRead(A, &a->ptrinuse));
34889566063dSJacob Faibussowitsch   PetscCall(VecLockReadPop(a->cvec));
34899566063dSJacob Faibussowitsch   PetscCall(VecResetArray(a->cvec));
349075f6d85dSStefano Zampini   if (v) *v = NULL;
34913ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
34926947451fSStefano Zampini }
34936947451fSStefano Zampini 
3494d71ae5a4SJacob Faibussowitsch PetscErrorCode MatDenseGetColumnVecWrite_SeqDense(Mat A, PetscInt col, Vec *v)
3495d71ae5a4SJacob Faibussowitsch {
34966947451fSStefano Zampini   Mat_SeqDense *a = (Mat_SeqDense *)A->data;
34976947451fSStefano Zampini 
34986947451fSStefano Zampini   PetscFunctionBegin;
349928b400f6SJacob Faibussowitsch   PetscCheck(!a->vecinuse, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Need to call MatDenseRestoreColumnVec() first");
350028b400f6SJacob Faibussowitsch   PetscCheck(!a->matinuse, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Need to call MatDenseRestoreSubMatrix() first");
3501aa624791SPierre Jolivet   if (!a->cvec) PetscCall(VecCreateSeqWithArray(PetscObjectComm((PetscObject)A), A->rmap->bs, A->rmap->n, NULL, &a->cvec));
35026947451fSStefano Zampini   a->vecinuse = col + 1;
35039566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArrayWrite(A, (PetscScalar **)&a->ptrinuse));
35049566063dSJacob Faibussowitsch   PetscCall(VecPlaceArray(a->cvec, a->ptrinuse + (size_t)col * (size_t)a->lda));
35056947451fSStefano Zampini   *v = a->cvec;
35063ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
35076947451fSStefano Zampini }
35086947451fSStefano Zampini 
3509d71ae5a4SJacob Faibussowitsch PetscErrorCode MatDenseRestoreColumnVecWrite_SeqDense(Mat A, PetscInt col, Vec *v)
3510d71ae5a4SJacob Faibussowitsch {
35116947451fSStefano Zampini   Mat_SeqDense *a = (Mat_SeqDense *)A->data;
35126947451fSStefano Zampini 
35136947451fSStefano Zampini   PetscFunctionBegin;
351428b400f6SJacob Faibussowitsch   PetscCheck(a->vecinuse, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Need to call MatDenseGetColumnVec() first");
351528b400f6SJacob Faibussowitsch   PetscCheck(a->cvec, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Missing internal column vector");
35166947451fSStefano Zampini   a->vecinuse = 0;
35179566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArrayWrite(A, (PetscScalar **)&a->ptrinuse));
35189566063dSJacob Faibussowitsch   PetscCall(VecResetArray(a->cvec));
351975f6d85dSStefano Zampini   if (v) *v = NULL;
35203ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
35216947451fSStefano Zampini }
35226947451fSStefano Zampini 
3523d71ae5a4SJacob Faibussowitsch PetscErrorCode MatDenseGetSubMatrix_SeqDense(Mat A, PetscInt rbegin, PetscInt rend, PetscInt cbegin, PetscInt cend, Mat *v)
3524d71ae5a4SJacob Faibussowitsch {
35255ea7661aSPierre Jolivet   Mat_SeqDense *a = (Mat_SeqDense *)A->data;
35265ea7661aSPierre Jolivet 
35275ea7661aSPierre Jolivet   PetscFunctionBegin;
352828b400f6SJacob Faibussowitsch   PetscCheck(!a->vecinuse, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Need to call MatDenseRestoreColumnVec() first");
352928b400f6SJacob Faibussowitsch   PetscCheck(!a->matinuse, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Need to call MatDenseRestoreSubMatrix() first");
3530a2748737SPierre Jolivet   if (a->cmat && (cend - cbegin != a->cmat->cmap->N || rend - rbegin != a->cmat->rmap->N)) PetscCall(MatDestroy(&a->cmat));
35315ea7661aSPierre Jolivet   if (!a->cmat) {
3532a2748737SPierre Jolivet     PetscCall(MatCreateDense(PetscObjectComm((PetscObject)A), rend - rbegin, PETSC_DECIDE, rend - rbegin, cend - cbegin, a->v + rbegin + (size_t)cbegin * a->lda, &a->cmat));
35335ea7661aSPierre Jolivet   } else {
3534a2748737SPierre Jolivet     PetscCall(MatDensePlaceArray(a->cmat, a->v + rbegin + (size_t)cbegin * a->lda));
35355ea7661aSPierre Jolivet   }
35369566063dSJacob Faibussowitsch   PetscCall(MatDenseSetLDA(a->cmat, a->lda));
35375ea7661aSPierre Jolivet   a->matinuse = cbegin + 1;
35385ea7661aSPierre Jolivet   *v          = a->cmat;
353947d993e7Ssuyashtn #if defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
354075f6d85dSStefano Zampini   A->offloadmask = PETSC_OFFLOAD_CPU;
354175f6d85dSStefano Zampini #endif
35423ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
35435ea7661aSPierre Jolivet }
35445ea7661aSPierre Jolivet 
3545d71ae5a4SJacob Faibussowitsch PetscErrorCode MatDenseRestoreSubMatrix_SeqDense(Mat A, Mat *v)
3546d71ae5a4SJacob Faibussowitsch {
35475ea7661aSPierre Jolivet   Mat_SeqDense *a = (Mat_SeqDense *)A->data;
35485ea7661aSPierre Jolivet 
35495ea7661aSPierre Jolivet   PetscFunctionBegin;
355028b400f6SJacob Faibussowitsch   PetscCheck(a->matinuse, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Need to call MatDenseGetSubMatrix() first");
355128b400f6SJacob Faibussowitsch   PetscCheck(a->cmat, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Missing internal column matrix");
355208401ef6SPierre Jolivet   PetscCheck(*v == a->cmat, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Not the matrix obtained from MatDenseGetSubMatrix()");
35535ea7661aSPierre Jolivet   a->matinuse = 0;
35549566063dSJacob Faibussowitsch   PetscCall(MatDenseResetArray(a->cmat));
3555742765d3SMatthew Knepley   if (v) *v = NULL;
355647d993e7Ssuyashtn #if defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
35573faff063SStefano Zampini   A->offloadmask = PETSC_OFFLOAD_CPU;
35583faff063SStefano Zampini #endif
35593ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
35605ea7661aSPierre Jolivet }
35615ea7661aSPierre Jolivet 
35620bad9183SKris Buschelman /*MC
3563fafad747SKris Buschelman    MATSEQDENSE - MATSEQDENSE = "seqdense" - A matrix type to be used for sequential dense matrices.
35640bad9183SKris Buschelman 
3565*2ef1f0ffSBarry Smith    Options Database Key:
356611a5261eSBarry Smith . -mat_type seqdense - sets the matrix type to `MATSEQDENSE` during a call to `MatSetFromOptions()`
35670bad9183SKris Buschelman 
35680bad9183SKris Buschelman   Level: beginner
35690bad9183SKris Buschelman 
3570*2ef1f0ffSBarry Smith .seealso: [](chapter_matrices), `Mat`, `MATSEQDENSE`, `MatCreateSeqDense()`
35710bad9183SKris Buschelman M*/
3572d71ae5a4SJacob Faibussowitsch PetscErrorCode MatCreate_SeqDense(Mat B)
3573d71ae5a4SJacob Faibussowitsch {
3574273d9f13SBarry Smith   Mat_SeqDense *b;
35757c334f02SBarry Smith   PetscMPIInt   size;
3576273d9f13SBarry Smith 
3577273d9f13SBarry Smith   PetscFunctionBegin;
35789566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)B), &size));
357908401ef6SPierre Jolivet   PetscCheck(size <= 1, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Comm must be of size 1");
358055659b69SBarry Smith 
35814dfa11a4SJacob Faibussowitsch   PetscCall(PetscNew(&b));
35829566063dSJacob Faibussowitsch   PetscCall(PetscMemcpy(B->ops, &MatOps_Values, sizeof(struct _MatOps)));
358344cd7ae7SLois Curfman McInnes   B->data = (void *)b;
358418f449edSLois Curfman McInnes 
3585273d9f13SBarry Smith   b->roworiented = PETSC_TRUE;
35864e220ebcSLois Curfman McInnes 
35879566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatQRFactor_C", MatQRFactor_SeqDense));
35889566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatDenseGetLDA_C", MatDenseGetLDA_SeqDense));
35899566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatDenseSetLDA_C", MatDenseSetLDA_SeqDense));
35909566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatDenseGetArray_C", MatDenseGetArray_SeqDense));
35919566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatDenseRestoreArray_C", MatDenseRestoreArray_SeqDense));
35929566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatDensePlaceArray_C", MatDensePlaceArray_SeqDense));
35939566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatDenseResetArray_C", MatDenseResetArray_SeqDense));
35949566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatDenseReplaceArray_C", MatDenseReplaceArray_SeqDense));
35959566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatDenseGetArrayRead_C", MatDenseGetArray_SeqDense));
35969566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatDenseRestoreArrayRead_C", MatDenseRestoreArray_SeqDense));
35979566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatDenseGetArrayWrite_C", MatDenseGetArray_SeqDense));
35989566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatDenseRestoreArrayWrite_C", MatDenseRestoreArray_SeqDense));
35999566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatConvert_seqdense_seqaij_C", MatConvert_SeqDense_SeqAIJ));
36008baccfbdSHong Zhang #if defined(PETSC_HAVE_ELEMENTAL)
36019566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatConvert_seqdense_elemental_C", MatConvert_SeqDense_Elemental));
36028baccfbdSHong Zhang #endif
3603d24d4204SJose E. Roman #if defined(PETSC_HAVE_SCALAPACK)
36049566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatConvert_seqdense_scalapack_C", MatConvert_Dense_ScaLAPACK));
3605d24d4204SJose E. Roman #endif
36062bf066beSStefano Zampini #if defined(PETSC_HAVE_CUDA)
36079566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatConvert_seqdense_seqdensecuda_C", MatConvert_SeqDense_SeqDenseCUDA));
36089566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatProductSetFromOptions_seqdensecuda_seqdensecuda_C", MatProductSetFromOptions_SeqDense));
36099566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatProductSetFromOptions_seqdensecuda_seqdense_C", MatProductSetFromOptions_SeqDense));
36109566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatProductSetFromOptions_seqdense_seqdensecuda_C", MatProductSetFromOptions_SeqDense));
36112bf066beSStefano Zampini #endif
361247d993e7Ssuyashtn #if defined(PETSC_HAVE_HIP)
361347d993e7Ssuyashtn   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatConvert_seqdense_seqdensehip_C", MatConvert_SeqDense_SeqDenseHIP));
361447d993e7Ssuyashtn   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatProductSetFromOptions_seqdensehip_seqdensehip_C", MatProductSetFromOptions_SeqDense));
361547d993e7Ssuyashtn   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatProductSetFromOptions_seqdensehip_seqdense_C", MatProductSetFromOptions_SeqDense));
361647d993e7Ssuyashtn   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatProductSetFromOptions_seqdense_seqdensehip_C", MatProductSetFromOptions_SeqDense));
361747d993e7Ssuyashtn #endif
36189566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatSeqDenseSetPreallocation_C", MatSeqDenseSetPreallocation_SeqDense));
36199566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatProductSetFromOptions_seqaij_seqdense_C", MatProductSetFromOptions_SeqAIJ_SeqDense));
36209566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatProductSetFromOptions_seqdense_seqdense_C", MatProductSetFromOptions_SeqDense));
36219566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatProductSetFromOptions_seqbaij_seqdense_C", MatProductSetFromOptions_SeqXBAIJ_SeqDense));
36229566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatProductSetFromOptions_seqsbaij_seqdense_C", MatProductSetFromOptions_SeqXBAIJ_SeqDense));
362396e6d5c4SRichard Tran Mills 
36249566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatDenseGetColumn_C", MatDenseGetColumn_SeqDense));
36259566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatDenseRestoreColumn_C", MatDenseRestoreColumn_SeqDense));
36269566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatDenseGetColumnVec_C", MatDenseGetColumnVec_SeqDense));
36279566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatDenseRestoreColumnVec_C", MatDenseRestoreColumnVec_SeqDense));
36289566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatDenseGetColumnVecRead_C", MatDenseGetColumnVecRead_SeqDense));
36299566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatDenseRestoreColumnVecRead_C", MatDenseRestoreColumnVecRead_SeqDense));
36309566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatDenseGetColumnVecWrite_C", MatDenseGetColumnVecWrite_SeqDense));
36319566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatDenseRestoreColumnVecWrite_C", MatDenseRestoreColumnVecWrite_SeqDense));
36329566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatDenseGetSubMatrix_C", MatDenseGetSubMatrix_SeqDense));
36339566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatDenseRestoreSubMatrix_C", MatDenseRestoreSubMatrix_SeqDense));
36349566063dSJacob Faibussowitsch   PetscCall(PetscObjectChangeTypeName((PetscObject)B, MATSEQDENSE));
36353ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3636289bc588SBarry Smith }
363786aefd0dSHong Zhang 
363886aefd0dSHong Zhang /*@C
363911a5261eSBarry Smith    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.
364086aefd0dSHong Zhang 
364186aefd0dSHong Zhang    Not Collective
364286aefd0dSHong Zhang 
36435ea7661aSPierre Jolivet    Input Parameters:
364411a5261eSBarry Smith +  mat - a `MATSEQDENSE` or `MATMPIDENSE` matrix
364586aefd0dSHong Zhang -  col - column index
364686aefd0dSHong Zhang 
364786aefd0dSHong Zhang    Output Parameter:
364886aefd0dSHong Zhang .  vals - pointer to the data
364986aefd0dSHong Zhang 
365086aefd0dSHong Zhang    Level: intermediate
365186aefd0dSHong Zhang 
365211a5261eSBarry Smith    Note:
365311a5261eSBarry Smith    Use `MatDenseGetColumnVec()` to get access to a column of a `MATDENSE` treated as a `Vec`
365411a5261eSBarry Smith 
3655*2ef1f0ffSBarry Smith .seealso: [](chapter_matrices), `Mat`, `MATDENSE`, `MatDenseRestoreColumn()`, `MatDenseGetColumnVec()`
365686aefd0dSHong Zhang @*/
3657d71ae5a4SJacob Faibussowitsch PetscErrorCode MatDenseGetColumn(Mat A, PetscInt col, PetscScalar **vals)
3658d71ae5a4SJacob Faibussowitsch {
365986aefd0dSHong Zhang   PetscFunctionBegin;
3660d5ea218eSStefano Zampini   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
3661d5ea218eSStefano Zampini   PetscValidLogicalCollectiveInt(A, col, 2);
3662d5ea218eSStefano Zampini   PetscValidPointer(vals, 3);
3663cac4c232SBarry Smith   PetscUseMethod(A, "MatDenseGetColumn_C", (Mat, PetscInt, PetscScalar **), (A, col, vals));
36643ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
366586aefd0dSHong Zhang }
366686aefd0dSHong Zhang 
366786aefd0dSHong Zhang /*@C
366811a5261eSBarry Smith    MatDenseRestoreColumn - returns access to a column of a `MATDENSE` matrix which is returned by `MatDenseGetColumn()`.
366986aefd0dSHong Zhang 
367086aefd0dSHong Zhang    Not Collective
367186aefd0dSHong Zhang 
3672742765d3SMatthew Knepley    Input Parameters:
367311a5261eSBarry Smith +  mat - a `MATSEQDENSE` or `MATMPIDENSE` matrix
3674*2ef1f0ffSBarry Smith -  vals - pointer to the data (may be `NULL`)
367586aefd0dSHong Zhang 
367686aefd0dSHong Zhang    Level: intermediate
367786aefd0dSHong Zhang 
3678*2ef1f0ffSBarry Smith .seealso: [](chapter_matrices), `Mat`, `MATDENSE`, `MatDenseGetColumn()`
367986aefd0dSHong Zhang @*/
3680d71ae5a4SJacob Faibussowitsch PetscErrorCode MatDenseRestoreColumn(Mat A, PetscScalar **vals)
3681d71ae5a4SJacob Faibussowitsch {
368286aefd0dSHong Zhang   PetscFunctionBegin;
3683d5ea218eSStefano Zampini   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
3684d5ea218eSStefano Zampini   PetscValidPointer(vals, 2);
3685cac4c232SBarry Smith   PetscUseMethod(A, "MatDenseRestoreColumn_C", (Mat, PetscScalar **), (A, vals));
36863ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
368786aefd0dSHong Zhang }
36886947451fSStefano Zampini 
36890f74d2c1SSatish Balay /*@
369011a5261eSBarry Smith    MatDenseGetColumnVec - Gives read-write access to a column of a `MATDENSE` matrix, represented as a `Vec`.
36916947451fSStefano Zampini 
36926947451fSStefano Zampini    Collective
36936947451fSStefano Zampini 
36945ea7661aSPierre Jolivet    Input Parameters:
369511a5261eSBarry Smith +  mat - the `Mat` object
36966947451fSStefano Zampini -  col - the column index
36976947451fSStefano Zampini 
36986947451fSStefano Zampini    Output Parameter:
36996947451fSStefano Zampini .  v - the vector
37006947451fSStefano Zampini 
3701*2ef1f0ffSBarry Smith    Level: intermediate
3702*2ef1f0ffSBarry Smith 
37036947451fSStefano Zampini    Notes:
370411a5261eSBarry Smith      The vector is owned by PETSc. Users need to call `MatDenseRestoreColumnVec()` when the vector is no longer needed.
370511a5261eSBarry Smith 
370611a5261eSBarry Smith      Use `MatDenseGetColumnVecRead()` to obtain read-only access or `MatDenseGetColumnVecWrite()` for write-only access.
37076947451fSStefano Zampini 
3708*2ef1f0ffSBarry Smith .seealso: [](chapter_matrices), `Mat`, `MATDENSE`, `MATDENSECUDA`, `MATDENSEHIP`, `MatDenseGetColumnVecRead()`, `MatDenseGetColumnVecWrite()`, `MatDenseRestoreColumnVec()`, `MatDenseRestoreColumnVecRead()`, `MatDenseRestoreColumnVecWrite()`, `MatDenseGetColumn()`
37096947451fSStefano Zampini @*/
3710d71ae5a4SJacob Faibussowitsch PetscErrorCode MatDenseGetColumnVec(Mat A, PetscInt col, Vec *v)
3711d71ae5a4SJacob Faibussowitsch {
37126947451fSStefano Zampini   PetscFunctionBegin;
37136947451fSStefano Zampini   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
37146947451fSStefano Zampini   PetscValidType(A, 1);
37156947451fSStefano Zampini   PetscValidLogicalCollectiveInt(A, col, 2);
37166947451fSStefano Zampini   PetscValidPointer(v, 3);
371728b400f6SJacob Faibussowitsch   PetscCheck(A->preallocated, PetscObjectComm((PetscObject)A), PETSC_ERR_ORDER, "Matrix not preallocated");
37182cf15c64SPierre Jolivet   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);
3719cac4c232SBarry Smith   PetscUseMethod(A, "MatDenseGetColumnVec_C", (Mat, PetscInt, Vec *), (A, col, v));
37203ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
37216947451fSStefano Zampini }
37226947451fSStefano Zampini 
37230f74d2c1SSatish Balay /*@
37246947451fSStefano Zampini    MatDenseRestoreColumnVec - Returns access to a column of a dense matrix obtained from MatDenseGetColumnVec().
37256947451fSStefano Zampini 
37266947451fSStefano Zampini    Collective
37276947451fSStefano Zampini 
37285ea7661aSPierre Jolivet    Input Parameters:
37296947451fSStefano Zampini +  mat - the Mat object
37306947451fSStefano Zampini .  col - the column index
3731*2ef1f0ffSBarry Smith -  v - the Vec object (may be `NULL`)
37326947451fSStefano Zampini 
37336947451fSStefano Zampini    Level: intermediate
37346947451fSStefano Zampini 
3735*2ef1f0ffSBarry Smith .seealso: [](chapter_matrices), `Mat`, `MATDENSE`, `MATDENSECUDA`, `MATDENSEHIP`, `MatDenseGetColumnVec()`, `MatDenseGetColumnVecRead()`, `MatDenseGetColumnVecWrite()`, `MatDenseRestoreColumnVecRead()`, `MatDenseRestoreColumnVecWrite()`
37366947451fSStefano Zampini @*/
3737d71ae5a4SJacob Faibussowitsch PetscErrorCode MatDenseRestoreColumnVec(Mat A, PetscInt col, Vec *v)
3738d71ae5a4SJacob Faibussowitsch {
37396947451fSStefano Zampini   PetscFunctionBegin;
37406947451fSStefano Zampini   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
37416947451fSStefano Zampini   PetscValidType(A, 1);
37426947451fSStefano Zampini   PetscValidLogicalCollectiveInt(A, col, 2);
374308401ef6SPierre Jolivet   PetscCheck(A->preallocated, PetscObjectComm((PetscObject)A), PETSC_ERR_ORDER, "Matrix not preallocated");
37442cf15c64SPierre Jolivet   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);
3745cac4c232SBarry Smith   PetscUseMethod(A, "MatDenseRestoreColumnVec_C", (Mat, PetscInt, Vec *), (A, col, v));
37463ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
37476947451fSStefano Zampini }
37486947451fSStefano Zampini 
37490f74d2c1SSatish Balay /*@
37506947451fSStefano Zampini    MatDenseGetColumnVecRead - Gives read-only access to a column of a dense matrix, represented as a Vec.
37516947451fSStefano Zampini 
37526947451fSStefano Zampini    Collective
37536947451fSStefano Zampini 
37545ea7661aSPierre Jolivet    Input Parameters:
3755*2ef1f0ffSBarry Smith +  mat - the `Mat` object
37566947451fSStefano Zampini -  col - the column index
37576947451fSStefano Zampini 
37586947451fSStefano Zampini    Output Parameter:
37596947451fSStefano Zampini .  v - the vector
37606947451fSStefano Zampini 
3761*2ef1f0ffSBarry Smith    Level: intermediate
3762*2ef1f0ffSBarry Smith 
37636947451fSStefano Zampini    Notes:
37646947451fSStefano Zampini      The vector is owned by PETSc and users cannot modify it.
376511a5261eSBarry Smith 
3766*2ef1f0ffSBarry Smith      Users need to call `MatDenseRestoreColumnVecRead()` when the vector is no longer needed.
376711a5261eSBarry Smith 
3768*2ef1f0ffSBarry Smith      Use `MatDenseGetColumnVec()` to obtain read-write access or `MatDenseGetColumnVecWrite()` for write-only access.
37696947451fSStefano Zampini 
3770*2ef1f0ffSBarry Smith .seealso: [](chapter_matrices), `Mat`, `MATDENSE`, `MATDENSECUDA`, `MATDENSEHIP`, `MatDenseGetColumnVec()`, `MatDenseGetColumnVecWrite()`, `MatDenseRestoreColumnVec()`, `MatDenseRestoreColumnVecRead()`, `MatDenseRestoreColumnVecWrite()`
37716947451fSStefano Zampini @*/
3772d71ae5a4SJacob Faibussowitsch PetscErrorCode MatDenseGetColumnVecRead(Mat A, PetscInt col, Vec *v)
3773d71ae5a4SJacob Faibussowitsch {
37746947451fSStefano Zampini   PetscFunctionBegin;
37756947451fSStefano Zampini   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
37766947451fSStefano Zampini   PetscValidType(A, 1);
37776947451fSStefano Zampini   PetscValidLogicalCollectiveInt(A, col, 2);
37786947451fSStefano Zampini   PetscValidPointer(v, 3);
377928b400f6SJacob Faibussowitsch   PetscCheck(A->preallocated, PetscObjectComm((PetscObject)A), PETSC_ERR_ORDER, "Matrix not preallocated");
37802cf15c64SPierre Jolivet   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);
3781cac4c232SBarry Smith   PetscUseMethod(A, "MatDenseGetColumnVecRead_C", (Mat, PetscInt, Vec *), (A, col, v));
37823ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
37836947451fSStefano Zampini }
37846947451fSStefano Zampini 
37850f74d2c1SSatish Balay /*@
37866947451fSStefano Zampini    MatDenseRestoreColumnVecRead - Returns access to a column of a dense matrix obtained from MatDenseGetColumnVecRead().
37876947451fSStefano Zampini 
37886947451fSStefano Zampini    Collective
37896947451fSStefano Zampini 
37905ea7661aSPierre Jolivet    Input Parameters:
3791*2ef1f0ffSBarry Smith +  mat - the `Mat` object
37926947451fSStefano Zampini .  col - the column index
3793*2ef1f0ffSBarry Smith -  v - the Vec object (may be `NULL`)
37946947451fSStefano Zampini 
37956947451fSStefano Zampini    Level: intermediate
37966947451fSStefano Zampini 
3797*2ef1f0ffSBarry Smith .seealso: [](chapter_matrices), `Mat`, `MATDENSE`, `MATDENSECUDA`, `MATDENSEHIP`, `MatDenseGetColumnVec()`, `MatDenseGetColumnVecRead()`, `MatDenseGetColumnVecWrite()`, `MatDenseRestoreColumnVec()`, `MatDenseRestoreColumnVecWrite()`
37986947451fSStefano Zampini @*/
3799d71ae5a4SJacob Faibussowitsch PetscErrorCode MatDenseRestoreColumnVecRead(Mat A, PetscInt col, Vec *v)
3800d71ae5a4SJacob Faibussowitsch {
38016947451fSStefano Zampini   PetscFunctionBegin;
38026947451fSStefano Zampini   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
38036947451fSStefano Zampini   PetscValidType(A, 1);
38046947451fSStefano Zampini   PetscValidLogicalCollectiveInt(A, col, 2);
380508401ef6SPierre Jolivet   PetscCheck(A->preallocated, PetscObjectComm((PetscObject)A), PETSC_ERR_ORDER, "Matrix not preallocated");
38062cf15c64SPierre Jolivet   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);
3807cac4c232SBarry Smith   PetscUseMethod(A, "MatDenseRestoreColumnVecRead_C", (Mat, PetscInt, Vec *), (A, col, v));
38083ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
38096947451fSStefano Zampini }
38106947451fSStefano Zampini 
38110f74d2c1SSatish Balay /*@
38126947451fSStefano Zampini    MatDenseGetColumnVecWrite - Gives write-only access to a column of a dense matrix, represented as a Vec.
38136947451fSStefano Zampini 
38146947451fSStefano Zampini    Collective
38156947451fSStefano Zampini 
38165ea7661aSPierre Jolivet    Input Parameters:
3817*2ef1f0ffSBarry Smith +  mat - the `Mat` object
38186947451fSStefano Zampini -  col - the column index
38196947451fSStefano Zampini 
38206947451fSStefano Zampini    Output Parameter:
38216947451fSStefano Zampini .  v - the vector
38226947451fSStefano Zampini 
38236947451fSStefano Zampini    Level: intermediate
38246947451fSStefano Zampini 
3825*2ef1f0ffSBarry Smith    Notes:
3826*2ef1f0ffSBarry Smith      The vector is owned by PETSc. Users need to call `MatDenseRestoreColumnVecWrite()` when the vector is no longer needed.
3827*2ef1f0ffSBarry Smith 
3828*2ef1f0ffSBarry Smith      Use `MatDenseGetColumnVec()` to obtain read-write access or `MatDenseGetColumnVecRead()` for read-only access.
3829*2ef1f0ffSBarry Smith 
3830*2ef1f0ffSBarry Smith .seealso: [](chapter_matrices), `Mat`, `MATDENSE`, `MATDENSECUDA`, `MATDENSEHIP`, `MatDenseGetColumnVec()`, `MatDenseGetColumnVecRead()`, `MatDenseRestoreColumnVec()`, `MatDenseRestoreColumnVecRead()`, `MatDenseRestoreColumnVecWrite()`
38316947451fSStefano Zampini @*/
3832d71ae5a4SJacob Faibussowitsch PetscErrorCode MatDenseGetColumnVecWrite(Mat A, PetscInt col, Vec *v)
3833d71ae5a4SJacob Faibussowitsch {
38346947451fSStefano Zampini   PetscFunctionBegin;
38356947451fSStefano Zampini   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
38366947451fSStefano Zampini   PetscValidType(A, 1);
38376947451fSStefano Zampini   PetscValidLogicalCollectiveInt(A, col, 2);
38386947451fSStefano Zampini   PetscValidPointer(v, 3);
383928b400f6SJacob Faibussowitsch   PetscCheck(A->preallocated, PetscObjectComm((PetscObject)A), PETSC_ERR_ORDER, "Matrix not preallocated");
3840aed4548fSBarry Smith   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);
3841cac4c232SBarry Smith   PetscUseMethod(A, "MatDenseGetColumnVecWrite_C", (Mat, PetscInt, Vec *), (A, col, v));
38423ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
38436947451fSStefano Zampini }
38446947451fSStefano Zampini 
38450f74d2c1SSatish Balay /*@
38466947451fSStefano Zampini    MatDenseRestoreColumnVecWrite - Returns access to a column of a dense matrix obtained from MatDenseGetColumnVecWrite().
38476947451fSStefano Zampini 
38486947451fSStefano Zampini    Collective
38496947451fSStefano Zampini 
38505ea7661aSPierre Jolivet    Input Parameters:
3851*2ef1f0ffSBarry Smith +  mat - the `Mat` object
38526947451fSStefano Zampini .  col - the column index
3853*2ef1f0ffSBarry Smith -  v - the `Vec` object (may be `NULL`)
38546947451fSStefano Zampini 
38556947451fSStefano Zampini    Level: intermediate
38566947451fSStefano Zampini 
3857*2ef1f0ffSBarry Smith .seealso: [](chapter_matrices), `Mat`, `MATDENSE`, `MATDENSECUDA`, `MATDENSEHIP`, `MatDenseGetColumnVec()`, `MatDenseGetColumnVecRead()`, `MatDenseGetColumnVecWrite()`, `MatDenseRestoreColumnVec()`, `MatDenseRestoreColumnVecRead()`
38586947451fSStefano Zampini @*/
3859d71ae5a4SJacob Faibussowitsch PetscErrorCode MatDenseRestoreColumnVecWrite(Mat A, PetscInt col, Vec *v)
3860d71ae5a4SJacob Faibussowitsch {
38616947451fSStefano Zampini   PetscFunctionBegin;
38626947451fSStefano Zampini   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
38636947451fSStefano Zampini   PetscValidType(A, 1);
38646947451fSStefano Zampini   PetscValidLogicalCollectiveInt(A, col, 2);
386508401ef6SPierre Jolivet   PetscCheck(A->preallocated, PetscObjectComm((PetscObject)A), PETSC_ERR_ORDER, "Matrix not preallocated");
3866aed4548fSBarry Smith   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);
3867cac4c232SBarry Smith   PetscUseMethod(A, "MatDenseRestoreColumnVecWrite_C", (Mat, PetscInt, Vec *), (A, col, v));
38683ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
38696947451fSStefano Zampini }
38705ea7661aSPierre Jolivet 
38710f74d2c1SSatish Balay /*@
3872a2748737SPierre Jolivet    MatDenseGetSubMatrix - Gives access to a block of rows and columns of a dense matrix, represented as a Mat.
38735ea7661aSPierre Jolivet 
38745ea7661aSPierre Jolivet    Collective
38755ea7661aSPierre Jolivet 
38765ea7661aSPierre Jolivet    Input Parameters:
38775ea7661aSPierre Jolivet +  mat - the Mat object
3878*2ef1f0ffSBarry Smith .  rbegin - the first global row index in the block (if `PETSC_DECIDE`, is 0)
3879*2ef1f0ffSBarry Smith .  rend - the global row index past the last one in the block (if `PETSC_DECIDE`, is `M`)
3880*2ef1f0ffSBarry Smith .  cbegin - the first global column index in the block (if `PETSC_DECIDE`, is 0)
3881*2ef1f0ffSBarry Smith -  cend - the global column index past the last one in the block (if `PETSC_DECIDE`, is `N`)
38825ea7661aSPierre Jolivet 
38835ea7661aSPierre Jolivet    Output Parameter:
38845ea7661aSPierre Jolivet .  v - the matrix
38855ea7661aSPierre Jolivet 
38865ea7661aSPierre Jolivet    Level: intermediate
38875ea7661aSPierre Jolivet 
3888*2ef1f0ffSBarry Smith    Notes:
3889*2ef1f0ffSBarry Smith      The matrix is owned by PETSc. Users need to call `MatDenseRestoreSubMatrix()` when the matrix is no longer needed.
3890*2ef1f0ffSBarry Smith 
3891*2ef1f0ffSBarry Smith      The output matrix is not redistributed by PETSc, so depending on the values of `rbegin` and `rend`, some processes may have no local rows.
3892*2ef1f0ffSBarry Smith 
3893*2ef1f0ffSBarry Smith .seealso: [](chapter_matrices), `Mat`, `MATDENSE`, `MATDENSECUDA`, `MATDENSEHIP`, `MatDenseGetColumnVec()`, `MatDenseRestoreColumnVec()`, `MatDenseRestoreSubMatrix()`
38945ea7661aSPierre Jolivet @*/
3895d71ae5a4SJacob Faibussowitsch PetscErrorCode MatDenseGetSubMatrix(Mat A, PetscInt rbegin, PetscInt rend, PetscInt cbegin, PetscInt cend, Mat *v)
3896d71ae5a4SJacob Faibussowitsch {
38975ea7661aSPierre Jolivet   PetscFunctionBegin;
38985ea7661aSPierre Jolivet   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
38995ea7661aSPierre Jolivet   PetscValidType(A, 1);
3900a2748737SPierre Jolivet   PetscValidLogicalCollectiveInt(A, rbegin, 2);
3901a2748737SPierre Jolivet   PetscValidLogicalCollectiveInt(A, rend, 3);
3902a2748737SPierre Jolivet   PetscValidLogicalCollectiveInt(A, cbegin, 4);
3903a2748737SPierre Jolivet   PetscValidLogicalCollectiveInt(A, cend, 5);
3904a2748737SPierre Jolivet   PetscValidPointer(v, 6);
3905a2748737SPierre Jolivet   if (rbegin == PETSC_DECIDE) rbegin = 0;
3906a2748737SPierre Jolivet   if (rend == PETSC_DECIDE) rend = A->rmap->N;
3907a2748737SPierre Jolivet   if (cbegin == PETSC_DECIDE) cbegin = 0;
3908a2748737SPierre Jolivet   if (cend == PETSC_DECIDE) cend = A->cmap->N;
390928b400f6SJacob Faibussowitsch   PetscCheck(A->preallocated, PetscObjectComm((PetscObject)A), PETSC_ERR_ORDER, "Matrix not preallocated");
3910a2748737SPierre Jolivet   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);
3911a2748737SPierre Jolivet   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);
3912a2748737SPierre Jolivet   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);
3913a2748737SPierre Jolivet   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);
3914a2748737SPierre Jolivet   PetscUseMethod(A, "MatDenseGetSubMatrix_C", (Mat, PetscInt, PetscInt, PetscInt, PetscInt, Mat *), (A, rbegin, rend, cbegin, cend, v));
39153ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
39165ea7661aSPierre Jolivet }
39175ea7661aSPierre Jolivet 
39180f74d2c1SSatish Balay /*@
39195ea7661aSPierre Jolivet    MatDenseRestoreSubMatrix - Returns access to a block of columns of a dense matrix obtained from MatDenseGetSubMatrix().
39205ea7661aSPierre Jolivet 
39215ea7661aSPierre Jolivet    Collective
39225ea7661aSPierre Jolivet 
39235ea7661aSPierre Jolivet    Input Parameters:
3924*2ef1f0ffSBarry Smith +  mat - the `Mat` object
3925*2ef1f0ffSBarry Smith -  v - the `Mat` object (may be `NULL`)
39265ea7661aSPierre Jolivet 
39275ea7661aSPierre Jolivet    Level: intermediate
39285ea7661aSPierre Jolivet 
3929*2ef1f0ffSBarry Smith .seealso: [](chapter_matrices), `Mat`, `MATDENSE`, `MATDENSECUDA`, `MATDENSEHIP`, `MatDenseGetColumnVec()`, `MatDenseRestoreColumnVec()`, `MatDenseGetSubMatrix()`
39305ea7661aSPierre Jolivet @*/
3931d71ae5a4SJacob Faibussowitsch PetscErrorCode MatDenseRestoreSubMatrix(Mat A, Mat *v)
3932d71ae5a4SJacob Faibussowitsch {
39335ea7661aSPierre Jolivet   PetscFunctionBegin;
39345ea7661aSPierre Jolivet   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
39355ea7661aSPierre Jolivet   PetscValidType(A, 1);
39365ea7661aSPierre Jolivet   PetscValidPointer(v, 2);
3937cac4c232SBarry Smith   PetscUseMethod(A, "MatDenseRestoreSubMatrix_C", (Mat, Mat *), (A, v));
39383ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
39395ea7661aSPierre Jolivet }
39408a9c020eSBarry Smith 
39418a9c020eSBarry Smith #include <petscblaslapack.h>
39428a9c020eSBarry Smith #include <petsc/private/kernels/blockinvert.h>
39438a9c020eSBarry Smith 
3944d71ae5a4SJacob Faibussowitsch PetscErrorCode MatSeqDenseInvert(Mat A)
3945d71ae5a4SJacob Faibussowitsch {
39468a9c020eSBarry Smith   Mat_SeqDense   *a              = (Mat_SeqDense *)A->data;
39478a9c020eSBarry Smith   PetscInt        bs             = A->rmap->n;
39488a9c020eSBarry Smith   MatScalar      *values         = a->v;
39498a9c020eSBarry Smith   const PetscReal shift          = 0.0;
39508a9c020eSBarry Smith   PetscBool       allowzeropivot = PetscNot(A->erroriffailure), zeropivotdetected = PETSC_FALSE;
39518a9c020eSBarry Smith 
39528a9c020eSBarry Smith   PetscFunctionBegin;
39538a9c020eSBarry Smith   /* factor and invert each block */
39548a9c020eSBarry Smith   switch (bs) {
3955d71ae5a4SJacob Faibussowitsch   case 1:
3956d71ae5a4SJacob Faibussowitsch     values[0] = (PetscScalar)1.0 / (values[0] + shift);
3957d71ae5a4SJacob Faibussowitsch     break;
39588a9c020eSBarry Smith   case 2:
39598a9c020eSBarry Smith     PetscCall(PetscKernel_A_gets_inverse_A_2(values, shift, allowzeropivot, &zeropivotdetected));
39608a9c020eSBarry Smith     if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
39618a9c020eSBarry Smith     break;
39628a9c020eSBarry Smith   case 3:
39638a9c020eSBarry Smith     PetscCall(PetscKernel_A_gets_inverse_A_3(values, shift, allowzeropivot, &zeropivotdetected));
39648a9c020eSBarry Smith     if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
39658a9c020eSBarry Smith     break;
39668a9c020eSBarry Smith   case 4:
39678a9c020eSBarry Smith     PetscCall(PetscKernel_A_gets_inverse_A_4(values, shift, allowzeropivot, &zeropivotdetected));
39688a9c020eSBarry Smith     if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
39698a9c020eSBarry Smith     break;
39709371c9d4SSatish Balay   case 5: {
39718a9c020eSBarry Smith     PetscScalar work[25];
39728a9c020eSBarry Smith     PetscInt    ipvt[5];
39738a9c020eSBarry Smith 
39748a9c020eSBarry Smith     PetscCall(PetscKernel_A_gets_inverse_A_5(values, ipvt, work, shift, allowzeropivot, &zeropivotdetected));
39758a9c020eSBarry Smith     if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
39769371c9d4SSatish Balay   } break;
39778a9c020eSBarry Smith   case 6:
39788a9c020eSBarry Smith     PetscCall(PetscKernel_A_gets_inverse_A_6(values, shift, allowzeropivot, &zeropivotdetected));
39798a9c020eSBarry Smith     if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
39808a9c020eSBarry Smith     break;
39818a9c020eSBarry Smith   case 7:
39828a9c020eSBarry Smith     PetscCall(PetscKernel_A_gets_inverse_A_7(values, shift, allowzeropivot, &zeropivotdetected));
39838a9c020eSBarry Smith     if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
39848a9c020eSBarry Smith     break;
39859371c9d4SSatish Balay   default: {
39868a9c020eSBarry Smith     PetscInt    *v_pivots, *IJ, j;
39878a9c020eSBarry Smith     PetscScalar *v_work;
39888a9c020eSBarry Smith 
39898a9c020eSBarry Smith     PetscCall(PetscMalloc3(bs, &v_work, bs, &v_pivots, bs, &IJ));
3990ad540459SPierre Jolivet     for (j = 0; j < bs; j++) IJ[j] = j;
39918a9c020eSBarry Smith     PetscCall(PetscKernel_A_gets_inverse_A(bs, values, v_pivots, v_work, allowzeropivot, &zeropivotdetected));
39928a9c020eSBarry Smith     if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
39938a9c020eSBarry Smith     PetscCall(PetscFree3(v_work, v_pivots, IJ));
39948a9c020eSBarry Smith   }
39958a9c020eSBarry Smith   }
39963ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
39978a9c020eSBarry Smith }
3998