xref: /petsc/src/mat/impls/dense/seq/dense.c (revision d016bdde269de9549a736fe23cc3868ea52c341b)
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>
114186a4bbSPierre Jolivet #include <petsc/private/vecimpl.h>
12b2573a8aSBarry Smith 
13d71ae5a4SJacob Faibussowitsch PetscErrorCode MatSeqDenseSymmetrize_Private(Mat A, PetscBool hermitian)
14d71ae5a4SJacob Faibussowitsch {
158c178816SStefano Zampini   Mat_SeqDense *mat = (Mat_SeqDense *)A->data;
168c178816SStefano Zampini   PetscInt      j, k, n = A->rmap->n;
17ca15aa20SStefano Zampini   PetscScalar  *v;
188c178816SStefano Zampini 
198c178816SStefano Zampini   PetscFunctionBegin;
2008401ef6SPierre Jolivet   PetscCheck(A->rmap->n == A->cmap->n, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Cannot symmetrize a rectangular matrix");
219566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArray(A, &v));
228c178816SStefano Zampini   if (!hermitian) {
238c178816SStefano Zampini     for (k = 0; k < n; k++) {
24ad540459SPierre Jolivet       for (j = k; j < n; j++) v[j * mat->lda + k] = v[k * mat->lda + j];
258c178816SStefano Zampini     }
268c178816SStefano Zampini   } else {
278c178816SStefano Zampini     for (k = 0; k < n; k++) {
28ad540459SPierre Jolivet       for (j = k; j < n; j++) v[j * mat->lda + k] = PetscConj(v[k * mat->lda + j]);
298c178816SStefano Zampini     }
308c178816SStefano Zampini   }
319566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArray(A, &v));
323ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
338c178816SStefano Zampini }
348c178816SStefano Zampini 
35ff6a9541SJacob Faibussowitsch PetscErrorCode MatSeqDenseInvertFactors_Private(Mat A)
36d71ae5a4SJacob Faibussowitsch {
378c178816SStefano Zampini   Mat_SeqDense *mat = (Mat_SeqDense *)A->data;
388c178816SStefano Zampini   PetscBLASInt  info, n;
398c178816SStefano Zampini 
408c178816SStefano Zampini   PetscFunctionBegin;
413ba16761SJacob Faibussowitsch   if (!A->rmap->n || !A->cmap->n) PetscFunctionReturn(PETSC_SUCCESS);
429566063dSJacob Faibussowitsch   PetscCall(PetscBLASIntCast(A->cmap->n, &n));
438c178816SStefano Zampini   if (A->factortype == MAT_FACTOR_LU) {
4428b400f6SJacob Faibussowitsch     PetscCheck(mat->pivots, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Pivots not present");
458c178816SStefano Zampini     if (!mat->fwork) {
468c178816SStefano Zampini       mat->lfwork = n;
479566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(mat->lfwork, &mat->fwork));
488c178816SStefano Zampini     }
499566063dSJacob Faibussowitsch     PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF));
50792fecdfSBarry Smith     PetscCallBLAS("LAPACKgetri", LAPACKgetri_(&n, mat->v, &mat->lda, mat->pivots, mat->fwork, &mat->lfwork, &info));
519566063dSJacob Faibussowitsch     PetscCall(PetscFPTrapPop());
529566063dSJacob Faibussowitsch     PetscCall(PetscLogFlops((1.0 * A->cmap->n * A->cmap->n * A->cmap->n) / 3.0));
538c178816SStefano Zampini   } else if (A->factortype == MAT_FACTOR_CHOLESKY) {
54b94d7dedSBarry Smith     if (A->spd == PETSC_BOOL3_TRUE) {
559566063dSJacob Faibussowitsch       PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF));
56792fecdfSBarry Smith       PetscCallBLAS("LAPACKpotri", LAPACKpotri_("L", &n, mat->v, &mat->lda, &info));
579566063dSJacob Faibussowitsch       PetscCall(PetscFPTrapPop());
589566063dSJacob Faibussowitsch       PetscCall(MatSeqDenseSymmetrize_Private(A, PETSC_TRUE));
598c178816SStefano Zampini #if defined(PETSC_USE_COMPLEX)
60b94d7dedSBarry Smith     } else if (A->hermitian == PETSC_BOOL3_TRUE) {
6128b400f6SJacob Faibussowitsch       PetscCheck(mat->pivots, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Pivots not present");
6228b400f6SJacob Faibussowitsch       PetscCheck(mat->fwork, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Fwork not present");
639566063dSJacob Faibussowitsch       PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF));
64792fecdfSBarry Smith       PetscCallBLAS("LAPACKhetri", LAPACKhetri_("L", &n, mat->v, &mat->lda, mat->pivots, mat->fwork, &info));
659566063dSJacob Faibussowitsch       PetscCall(PetscFPTrapPop());
669566063dSJacob Faibussowitsch       PetscCall(MatSeqDenseSymmetrize_Private(A, PETSC_TRUE));
678c178816SStefano Zampini #endif
688c178816SStefano Zampini     } else { /* symmetric case */
6928b400f6SJacob Faibussowitsch       PetscCheck(mat->pivots, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Pivots not present");
7028b400f6SJacob Faibussowitsch       PetscCheck(mat->fwork, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Fwork not present");
719566063dSJacob Faibussowitsch       PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF));
72792fecdfSBarry Smith       PetscCallBLAS("LAPACKsytri", LAPACKsytri_("L", &n, mat->v, &mat->lda, mat->pivots, mat->fwork, &info));
739566063dSJacob Faibussowitsch       PetscCall(PetscFPTrapPop());
749566063dSJacob Faibussowitsch       PetscCall(MatSeqDenseSymmetrize_Private(A, PETSC_FALSE));
758c178816SStefano Zampini     }
76835f2295SStefano Zampini     PetscCheck(!info, PETSC_COMM_SELF, PETSC_ERR_MAT_CH_ZRPVT, "Bad Inversion: zero pivot in row %" PetscBLASInt_FMT, info - 1);
779566063dSJacob Faibussowitsch     PetscCall(PetscLogFlops((1.0 * A->cmap->n * A->cmap->n * A->cmap->n) / 3.0));
788c178816SStefano Zampini   } else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Matrix must be factored to solve");
798c178816SStefano Zampini 
808c178816SStefano Zampini   A->ops->solve             = NULL;
818c178816SStefano Zampini   A->ops->matsolve          = NULL;
828c178816SStefano Zampini   A->ops->solvetranspose    = NULL;
838c178816SStefano Zampini   A->ops->matsolvetranspose = NULL;
848c178816SStefano Zampini   A->ops->solveadd          = NULL;
858c178816SStefano Zampini   A->ops->solvetransposeadd = NULL;
868c178816SStefano Zampini   A->factortype             = MAT_FACTOR_NONE;
879566063dSJacob Faibussowitsch   PetscCall(PetscFree(A->solvertype));
883ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
898c178816SStefano Zampini }
908c178816SStefano Zampini 
9166976f2fSJacob Faibussowitsch static PetscErrorCode MatZeroRowsColumns_SeqDense(Mat A, PetscInt N, const PetscInt rows[], PetscScalar diag, Vec x, Vec b)
92d71ae5a4SJacob Faibussowitsch {
933f49a652SStefano Zampini   Mat_SeqDense      *l = (Mat_SeqDense *)A->data;
943f49a652SStefano Zampini   PetscInt           m = l->lda, n = A->cmap->n, r = A->rmap->n, i, j;
95ca15aa20SStefano Zampini   PetscScalar       *slot, *bb, *v;
963f49a652SStefano Zampini   const PetscScalar *xx;
973f49a652SStefano Zampini 
983f49a652SStefano Zampini   PetscFunctionBegin;
9976bd3646SJed Brown   if (PetscDefined(USE_DEBUG)) {
1003f49a652SStefano Zampini     for (i = 0; i < N; i++) {
10108401ef6SPierre Jolivet       PetscCheck(rows[i] >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Negative row requested to be zeroed");
10208401ef6SPierre 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);
10308401ef6SPierre 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);
1043f49a652SStefano Zampini     }
10576bd3646SJed Brown   }
1063ba16761SJacob Faibussowitsch   if (!N) PetscFunctionReturn(PETSC_SUCCESS);
1073f49a652SStefano Zampini 
108dd8e379bSPierre Jolivet   /* fix right-hand side if needed */
1093f49a652SStefano Zampini   if (x && b) {
1106c4d906cSStefano Zampini     Vec xt;
1116c4d906cSStefano Zampini 
11208401ef6SPierre Jolivet     PetscCheck(A->rmap->n == A->cmap->n, PETSC_COMM_SELF, PETSC_ERR_SUP, "Only coded for square matrices");
1139566063dSJacob Faibussowitsch     PetscCall(VecDuplicate(x, &xt));
1149566063dSJacob Faibussowitsch     PetscCall(VecCopy(x, xt));
1159566063dSJacob Faibussowitsch     PetscCall(VecScale(xt, -1.0));
1169566063dSJacob Faibussowitsch     PetscCall(MatMultAdd(A, xt, b, b));
1179566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&xt));
1189566063dSJacob Faibussowitsch     PetscCall(VecGetArrayRead(x, &xx));
1199566063dSJacob Faibussowitsch     PetscCall(VecGetArray(b, &bb));
1203f49a652SStefano Zampini     for (i = 0; i < N; i++) bb[rows[i]] = diag * xx[rows[i]];
1219566063dSJacob Faibussowitsch     PetscCall(VecRestoreArrayRead(x, &xx));
1229566063dSJacob Faibussowitsch     PetscCall(VecRestoreArray(b, &bb));
1233f49a652SStefano Zampini   }
1243f49a652SStefano Zampini 
1259566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArray(A, &v));
1263f49a652SStefano Zampini   for (i = 0; i < N; i++) {
127ca15aa20SStefano Zampini     slot = v + rows[i] * m;
1289566063dSJacob Faibussowitsch     PetscCall(PetscArrayzero(slot, r));
1293f49a652SStefano Zampini   }
1303f49a652SStefano Zampini   for (i = 0; i < N; i++) {
131ca15aa20SStefano Zampini     slot = v + rows[i];
1329371c9d4SSatish Balay     for (j = 0; j < n; j++) {
1339371c9d4SSatish Balay       *slot = 0.0;
1349371c9d4SSatish Balay       slot += m;
1359371c9d4SSatish Balay     }
1363f49a652SStefano Zampini   }
1373f49a652SStefano Zampini   if (diag != 0.0) {
13808401ef6SPierre Jolivet     PetscCheck(A->rmap->n == A->cmap->n, PETSC_COMM_SELF, PETSC_ERR_SUP, "Only coded for square matrices");
1393f49a652SStefano Zampini     for (i = 0; i < N; i++) {
140ca15aa20SStefano Zampini       slot  = v + (m + 1) * rows[i];
1413f49a652SStefano Zampini       *slot = diag;
1423f49a652SStefano Zampini     }
1433f49a652SStefano Zampini   }
1449566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArray(A, &v));
1453ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1463f49a652SStefano Zampini }
1473f49a652SStefano Zampini 
148d71ae5a4SJacob Faibussowitsch PETSC_INTERN PetscErrorCode MatConvert_SeqAIJ_SeqDense(Mat A, MatType newtype, MatReuse reuse, Mat *newmat)
149d71ae5a4SJacob Faibussowitsch {
150a13144ffSStefano Zampini   Mat              B = NULL;
151b49cda9fSStefano Zampini   Mat_SeqAIJ      *a = (Mat_SeqAIJ *)A->data;
152b49cda9fSStefano Zampini   Mat_SeqDense    *b;
153b49cda9fSStefano Zampini   PetscInt        *ai = a->i, *aj = a->j, m = A->rmap->N, n = A->cmap->N, i;
1542e5835c6SStefano Zampini   const MatScalar *av;
155a13144ffSStefano Zampini   PetscBool        isseqdense;
156b49cda9fSStefano Zampini 
157b49cda9fSStefano Zampini   PetscFunctionBegin;
158a13144ffSStefano Zampini   if (reuse == MAT_REUSE_MATRIX) {
1599566063dSJacob Faibussowitsch     PetscCall(PetscObjectTypeCompare((PetscObject)*newmat, MATSEQDENSE, &isseqdense));
160f4f49eeaSPierre Jolivet     PetscCheck(isseqdense, PetscObjectComm((PetscObject)*newmat), PETSC_ERR_USER, "Cannot reuse matrix of type %s", ((PetscObject)*newmat)->type_name);
161a13144ffSStefano Zampini   }
162a13144ffSStefano Zampini   if (reuse != MAT_REUSE_MATRIX) {
1639566063dSJacob Faibussowitsch     PetscCall(MatCreate(PetscObjectComm((PetscObject)A), &B));
1649566063dSJacob Faibussowitsch     PetscCall(MatSetSizes(B, m, n, m, n));
1659566063dSJacob Faibussowitsch     PetscCall(MatSetType(B, MATSEQDENSE));
1669566063dSJacob Faibussowitsch     PetscCall(MatSeqDenseSetPreallocation(B, NULL));
167f4f49eeaSPierre Jolivet     b = (Mat_SeqDense *)B->data;
168a13144ffSStefano Zampini   } else {
169a13144ffSStefano Zampini     b = (Mat_SeqDense *)((*newmat)->data);
170e1ea5af7SJose E. Roman     for (i = 0; i < n; i++) PetscCall(PetscArrayzero(b->v + i * b->lda, m));
171a13144ffSStefano Zampini   }
1729566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJGetArrayRead(A, &av));
173b49cda9fSStefano Zampini   for (i = 0; i < m; i++) {
174b49cda9fSStefano Zampini     PetscInt j;
175b49cda9fSStefano Zampini     for (j = 0; j < ai[1] - ai[0]; j++) {
176e1ea5af7SJose E. Roman       b->v[*aj * b->lda + i] = *av;
177b49cda9fSStefano Zampini       aj++;
178b49cda9fSStefano Zampini       av++;
179b49cda9fSStefano Zampini     }
180b49cda9fSStefano Zampini     ai++;
181b49cda9fSStefano Zampini   }
1829566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJRestoreArrayRead(A, &av));
183b49cda9fSStefano Zampini 
184511c6705SHong Zhang   if (reuse == MAT_INPLACE_MATRIX) {
1859566063dSJacob Faibussowitsch     PetscCall(MatAssemblyBegin(B, MAT_FINAL_ASSEMBLY));
1869566063dSJacob Faibussowitsch     PetscCall(MatAssemblyEnd(B, MAT_FINAL_ASSEMBLY));
1879566063dSJacob Faibussowitsch     PetscCall(MatHeaderReplace(A, &B));
188b49cda9fSStefano Zampini   } else {
189a13144ffSStefano Zampini     if (B) *newmat = B;
1909566063dSJacob Faibussowitsch     PetscCall(MatAssemblyBegin(*newmat, MAT_FINAL_ASSEMBLY));
1919566063dSJacob Faibussowitsch     PetscCall(MatAssemblyEnd(*newmat, MAT_FINAL_ASSEMBLY));
192b49cda9fSStefano Zampini   }
1933ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
194b49cda9fSStefano Zampini }
195b49cda9fSStefano Zampini 
196d71ae5a4SJacob Faibussowitsch PETSC_INTERN PetscErrorCode MatConvert_SeqDense_SeqAIJ(Mat A, MatType newtype, MatReuse reuse, Mat *newmat)
197d71ae5a4SJacob Faibussowitsch {
1986d4ec7b0SPierre Jolivet   Mat           B = NULL;
1996a63e612SBarry Smith   Mat_SeqDense *a = (Mat_SeqDense *)A->data;
2009399e1b8SMatthew G. Knepley   PetscInt      i, j;
2019399e1b8SMatthew G. Knepley   PetscInt     *rows, *nnz;
2029399e1b8SMatthew G. Knepley   MatScalar    *aa = a->v, *vals;
2036a63e612SBarry Smith 
2046a63e612SBarry Smith   PetscFunctionBegin;
2059566063dSJacob Faibussowitsch   PetscCall(PetscCalloc3(A->rmap->n, &rows, A->rmap->n, &nnz, A->rmap->n, &vals));
2066d4ec7b0SPierre Jolivet   if (reuse != MAT_REUSE_MATRIX) {
2079566063dSJacob Faibussowitsch     PetscCall(MatCreate(PetscObjectComm((PetscObject)A), &B));
2089566063dSJacob Faibussowitsch     PetscCall(MatSetSizes(B, A->rmap->n, A->cmap->n, A->rmap->N, A->cmap->N));
2099566063dSJacob Faibussowitsch     PetscCall(MatSetType(B, MATSEQAIJ));
2109399e1b8SMatthew G. Knepley     for (j = 0; j < A->cmap->n; j++) {
2119371c9d4SSatish Balay       for (i = 0; i < A->rmap->n; i++)
2129371c9d4SSatish Balay         if (aa[i] != 0.0 || (i == j && A->cmap->n == A->rmap->n)) ++nnz[i];
2136a63e612SBarry Smith       aa += a->lda;
2146a63e612SBarry Smith     }
2159566063dSJacob Faibussowitsch     PetscCall(MatSeqAIJSetPreallocation(B, PETSC_DETERMINE, nnz));
2166d4ec7b0SPierre Jolivet   } else B = *newmat;
2179399e1b8SMatthew G. Knepley   aa = a->v;
2189399e1b8SMatthew G. Knepley   for (j = 0; j < A->cmap->n; j++) {
2199399e1b8SMatthew G. Knepley     PetscInt numRows = 0;
2209371c9d4SSatish Balay     for (i = 0; i < A->rmap->n; i++)
2219371c9d4SSatish Balay       if (aa[i] != 0.0 || (i == j && A->cmap->n == A->rmap->n)) {
2229371c9d4SSatish Balay         rows[numRows]   = i;
2239371c9d4SSatish Balay         vals[numRows++] = aa[i];
2249371c9d4SSatish Balay       }
2259566063dSJacob Faibussowitsch     PetscCall(MatSetValues(B, numRows, rows, 1, &j, vals, INSERT_VALUES));
2269399e1b8SMatthew G. Knepley     aa += a->lda;
2279399e1b8SMatthew G. Knepley   }
2289566063dSJacob Faibussowitsch   PetscCall(PetscFree3(rows, nnz, vals));
2299566063dSJacob Faibussowitsch   PetscCall(MatAssemblyBegin(B, MAT_FINAL_ASSEMBLY));
2309566063dSJacob Faibussowitsch   PetscCall(MatAssemblyEnd(B, MAT_FINAL_ASSEMBLY));
2316a63e612SBarry Smith 
232511c6705SHong Zhang   if (reuse == MAT_INPLACE_MATRIX) {
2339566063dSJacob Faibussowitsch     PetscCall(MatHeaderReplace(A, &B));
2346d4ec7b0SPierre Jolivet   } else if (reuse != MAT_REUSE_MATRIX) *newmat = B;
2353ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2366a63e612SBarry Smith }
2376a63e612SBarry Smith 
238d71ae5a4SJacob Faibussowitsch PetscErrorCode MatAXPY_SeqDense(Mat Y, PetscScalar alpha, Mat X, MatStructure str)
239d71ae5a4SJacob Faibussowitsch {
2401987afe7SBarry Smith   Mat_SeqDense      *x = (Mat_SeqDense *)X->data, *y = (Mat_SeqDense *)Y->data;
241ca15aa20SStefano Zampini   const PetscScalar *xv;
242ca15aa20SStefano Zampini   PetscScalar       *yv;
24323fff9afSBarry Smith   PetscBLASInt       N, m, ldax = 0, lday = 0, one = 1;
2443a40ed3dSBarry Smith 
2453a40ed3dSBarry Smith   PetscFunctionBegin;
2469566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArrayRead(X, &xv));
2479566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArray(Y, &yv));
2489566063dSJacob Faibussowitsch   PetscCall(PetscBLASIntCast(X->rmap->n * X->cmap->n, &N));
2499566063dSJacob Faibussowitsch   PetscCall(PetscBLASIntCast(X->rmap->n, &m));
2509566063dSJacob Faibussowitsch   PetscCall(PetscBLASIntCast(x->lda, &ldax));
2519566063dSJacob Faibussowitsch   PetscCall(PetscBLASIntCast(y->lda, &lday));
252a5ce6ee0Svictorle   if (ldax > m || lday > m) {
2538e3a54c0SPierre Jolivet     for (PetscInt j = 0; j < X->cmap->n; j++) PetscCallBLAS("BLASaxpy", BLASaxpy_(&m, &alpha, PetscSafePointerPlusOffset(xv, j * ldax), &one, PetscSafePointerPlusOffset(yv, j * lday), &one));
254a5ce6ee0Svictorle   } else {
255792fecdfSBarry Smith     PetscCallBLAS("BLASaxpy", BLASaxpy_(&N, &alpha, xv, &one, yv, &one));
256a5ce6ee0Svictorle   }
2579566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArrayRead(X, &xv));
2589566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArray(Y, &yv));
2599566063dSJacob Faibussowitsch   PetscCall(PetscLogFlops(PetscMax(2.0 * N - 1, 0)));
2603ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2611987afe7SBarry Smith }
2621987afe7SBarry Smith 
263d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatGetInfo_SeqDense(Mat A, MatInfoType flag, MatInfo *info)
264d71ae5a4SJacob Faibussowitsch {
265ca15aa20SStefano Zampini   PetscLogDouble N = A->rmap->n * A->cmap->n;
2663a40ed3dSBarry Smith 
2673a40ed3dSBarry Smith   PetscFunctionBegin;
2684e220ebcSLois Curfman McInnes   info->block_size        = 1.0;
269ca15aa20SStefano Zampini   info->nz_allocated      = N;
270ca15aa20SStefano Zampini   info->nz_used           = N;
271ca15aa20SStefano Zampini   info->nz_unneeded       = 0;
272ca15aa20SStefano Zampini   info->assemblies        = A->num_ass;
2734e220ebcSLois Curfman McInnes   info->mallocs           = 0;
2744dfa11a4SJacob Faibussowitsch   info->memory            = 0; /* REVIEW ME */
2754e220ebcSLois Curfman McInnes   info->fill_ratio_given  = 0;
2764e220ebcSLois Curfman McInnes   info->fill_ratio_needed = 0;
2774e220ebcSLois Curfman McInnes   info->factor_mallocs    = 0;
2783ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
279289bc588SBarry Smith }
280289bc588SBarry Smith 
281d71ae5a4SJacob Faibussowitsch PetscErrorCode MatScale_SeqDense(Mat A, PetscScalar alpha)
282d71ae5a4SJacob Faibussowitsch {
283273d9f13SBarry Smith   Mat_SeqDense *a = (Mat_SeqDense *)A->data;
284ca15aa20SStefano Zampini   PetscScalar  *v;
28523fff9afSBarry Smith   PetscBLASInt  one = 1, j, nz, lda = 0;
28680cd9d93SLois Curfman McInnes 
2873a40ed3dSBarry Smith   PetscFunctionBegin;
2889566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArray(A, &v));
2899566063dSJacob Faibussowitsch   PetscCall(PetscBLASIntCast(a->lda, &lda));
290d0f46423SBarry Smith   if (lda > A->rmap->n) {
2919566063dSJacob Faibussowitsch     PetscCall(PetscBLASIntCast(A->rmap->n, &nz));
29248a46eb9SPierre Jolivet     for (j = 0; j < A->cmap->n; j++) PetscCallBLAS("BLASscal", BLASscal_(&nz, &alpha, v + j * lda, &one));
293a5ce6ee0Svictorle   } else {
2949566063dSJacob Faibussowitsch     PetscCall(PetscBLASIntCast(A->rmap->n * A->cmap->n, &nz));
295792fecdfSBarry Smith     PetscCallBLAS("BLASscal", BLASscal_(&nz, &alpha, v, &one));
296a5ce6ee0Svictorle   }
29704cbc005SJose E. Roman   PetscCall(PetscLogFlops(A->rmap->n * A->cmap->n));
2989566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArray(A, &v));
2993ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
30080cd9d93SLois Curfman McInnes }
30180cd9d93SLois Curfman McInnes 
302d71ae5a4SJacob Faibussowitsch PetscErrorCode MatShift_SeqDense(Mat A, PetscScalar alpha)
303d71ae5a4SJacob Faibussowitsch {
3042f605a99SJose E. Roman   Mat_SeqDense *a = (Mat_SeqDense *)A->data;
3052f605a99SJose E. Roman   PetscScalar  *v;
3062f605a99SJose E. Roman   PetscInt      j, k;
3072f605a99SJose E. Roman 
3082f605a99SJose E. Roman   PetscFunctionBegin;
3092f605a99SJose E. Roman   PetscCall(MatDenseGetArray(A, &v));
3102f605a99SJose E. Roman   k = PetscMin(A->rmap->n, A->cmap->n);
3112f605a99SJose E. Roman   for (j = 0; j < k; j++) v[j + j * a->lda] += alpha;
3122f605a99SJose E. Roman   PetscCall(PetscLogFlops(k));
3132f605a99SJose E. Roman   PetscCall(MatDenseRestoreArray(A, &v));
3143ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3152f605a99SJose E. Roman }
3162f605a99SJose E. Roman 
317d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatIsHermitian_SeqDense(Mat A, PetscReal rtol, PetscBool *fl)
318d71ae5a4SJacob Faibussowitsch {
3191cbb95d3SBarry Smith   Mat_SeqDense      *a = (Mat_SeqDense *)A->data;
320ca15aa20SStefano Zampini   PetscInt           i, j, m = A->rmap->n, N = a->lda;
321ca15aa20SStefano Zampini   const PetscScalar *v;
3221cbb95d3SBarry Smith 
3231cbb95d3SBarry Smith   PetscFunctionBegin;
3241cbb95d3SBarry Smith   *fl = PETSC_FALSE;
3253ba16761SJacob Faibussowitsch   if (A->rmap->n != A->cmap->n) PetscFunctionReturn(PETSC_SUCCESS);
3269566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArrayRead(A, &v));
3271cbb95d3SBarry Smith   for (i = 0; i < m; i++) {
328ca15aa20SStefano Zampini     for (j = i; j < m; j++) {
329ad540459SPierre Jolivet       if (PetscAbsScalar(v[i + j * N] - PetscConj(v[j + i * N])) > rtol) goto restore;
3301cbb95d3SBarry Smith     }
331637a0070SStefano Zampini   }
3321cbb95d3SBarry Smith   *fl = PETSC_TRUE;
333637a0070SStefano Zampini restore:
3349566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArrayRead(A, &v));
3353ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
336637a0070SStefano Zampini }
337637a0070SStefano Zampini 
338d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatIsSymmetric_SeqDense(Mat A, PetscReal rtol, PetscBool *fl)
339d71ae5a4SJacob Faibussowitsch {
340637a0070SStefano Zampini   Mat_SeqDense      *a = (Mat_SeqDense *)A->data;
341637a0070SStefano Zampini   PetscInt           i, j, m = A->rmap->n, N = a->lda;
342637a0070SStefano Zampini   const PetscScalar *v;
343637a0070SStefano Zampini 
344637a0070SStefano Zampini   PetscFunctionBegin;
345637a0070SStefano Zampini   *fl = PETSC_FALSE;
3463ba16761SJacob Faibussowitsch   if (A->rmap->n != A->cmap->n) PetscFunctionReturn(PETSC_SUCCESS);
3479566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArrayRead(A, &v));
348637a0070SStefano Zampini   for (i = 0; i < m; i++) {
349637a0070SStefano Zampini     for (j = i; j < m; j++) {
350ad540459SPierre Jolivet       if (PetscAbsScalar(v[i + j * N] - v[j + i * N]) > rtol) goto restore;
351637a0070SStefano Zampini     }
352637a0070SStefano Zampini   }
353637a0070SStefano Zampini   *fl = PETSC_TRUE;
354637a0070SStefano Zampini restore:
3559566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArrayRead(A, &v));
3563ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3571cbb95d3SBarry Smith }
3581cbb95d3SBarry Smith 
359d71ae5a4SJacob Faibussowitsch PetscErrorCode MatDuplicateNoCreate_SeqDense(Mat newi, Mat A, MatDuplicateOption cpvalues)
360d71ae5a4SJacob Faibussowitsch {
361ca15aa20SStefano Zampini   Mat_SeqDense *mat = (Mat_SeqDense *)A->data;
362835f2295SStefano Zampini   PetscInt      lda = mat->lda, j, m, nlda = lda;
36375f6d85dSStefano Zampini   PetscBool     isdensecpu;
364b24902e0SBarry Smith 
365b24902e0SBarry Smith   PetscFunctionBegin;
3669566063dSJacob Faibussowitsch   PetscCall(PetscLayoutReference(A->rmap, &newi->rmap));
3679566063dSJacob Faibussowitsch   PetscCall(PetscLayoutReference(A->cmap, &newi->cmap));
36823fc5dcaSStefano Zampini   if (cpvalues == MAT_SHARE_NONZERO_PATTERN) { /* propagate LDA */
3699566063dSJacob Faibussowitsch     PetscCall(MatDenseSetLDA(newi, lda));
37023fc5dcaSStefano Zampini   }
3719566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)newi, MATSEQDENSE, &isdensecpu));
3729566063dSJacob Faibussowitsch   if (isdensecpu) PetscCall(MatSeqDenseSetPreallocation(newi, NULL));
373b24902e0SBarry Smith   if (cpvalues == MAT_COPY_VALUES) {
374ca15aa20SStefano Zampini     const PetscScalar *av;
375ca15aa20SStefano Zampini     PetscScalar       *v;
376ca15aa20SStefano Zampini 
3779566063dSJacob Faibussowitsch     PetscCall(MatDenseGetArrayRead(A, &av));
3789566063dSJacob Faibussowitsch     PetscCall(MatDenseGetArrayWrite(newi, &v));
3799566063dSJacob Faibussowitsch     PetscCall(MatDenseGetLDA(newi, &nlda));
380d0f46423SBarry Smith     m = A->rmap->n;
38123fc5dcaSStefano Zampini     if (lda > m || nlda > m) {
3828e3a54c0SPierre Jolivet       for (j = 0; j < A->cmap->n; j++) PetscCall(PetscArraycpy(PetscSafePointerPlusOffset(v, j * nlda), PetscSafePointerPlusOffset(av, j * lda), m));
383b24902e0SBarry Smith     } else {
3849566063dSJacob Faibussowitsch       PetscCall(PetscArraycpy(v, av, A->rmap->n * A->cmap->n));
385b24902e0SBarry Smith     }
3869566063dSJacob Faibussowitsch     PetscCall(MatDenseRestoreArrayWrite(newi, &v));
3879566063dSJacob Faibussowitsch     PetscCall(MatDenseRestoreArrayRead(A, &av));
388c956ced0SPierre Jolivet     PetscCall(MatPropagateSymmetryOptions(A, newi));
389b24902e0SBarry Smith   }
3903ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
391b24902e0SBarry Smith }
392b24902e0SBarry Smith 
393d71ae5a4SJacob Faibussowitsch PetscErrorCode MatDuplicate_SeqDense(Mat A, MatDuplicateOption cpvalues, Mat *newmat)
394d71ae5a4SJacob Faibussowitsch {
3953a40ed3dSBarry Smith   PetscFunctionBegin;
3969566063dSJacob Faibussowitsch   PetscCall(MatCreate(PetscObjectComm((PetscObject)A), newmat));
3979566063dSJacob Faibussowitsch   PetscCall(MatSetSizes(*newmat, A->rmap->n, A->cmap->n, A->rmap->n, A->cmap->n));
3989566063dSJacob Faibussowitsch   PetscCall(MatSetType(*newmat, ((PetscObject)A)->type_name));
3999566063dSJacob Faibussowitsch   PetscCall(MatDuplicateNoCreate_SeqDense(*newmat, A, cpvalues));
4003ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
401b24902e0SBarry Smith }
402b24902e0SBarry Smith 
403d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatSolve_SeqDense_Internal_LU(Mat A, PetscScalar *x, PetscBLASInt ldx, PetscBLASInt m, PetscBLASInt nrhs, PetscBLASInt k, PetscBool T)
404d71ae5a4SJacob Faibussowitsch {
405c0bbcb79SLois Curfman McInnes   Mat_SeqDense *mat = (Mat_SeqDense *)A->data;
4064396437dSToby Isaac   PetscBLASInt  info;
40767e560aaSBarry Smith 
4083a40ed3dSBarry Smith   PetscFunctionBegin;
4099566063dSJacob Faibussowitsch   PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF));
410792fecdfSBarry Smith   PetscCallBLAS("LAPACKgetrs", LAPACKgetrs_(T ? "T" : "N", &m, &nrhs, mat->v, &mat->lda, mat->pivots, x, &m, &info));
4119566063dSJacob Faibussowitsch   PetscCall(PetscFPTrapPop());
412835f2295SStefano Zampini   PetscCheck(!info, PETSC_COMM_SELF, PETSC_ERR_LIB, "GETRS - Bad solve %" PetscBLASInt_FMT, info);
4139566063dSJacob Faibussowitsch   PetscCall(PetscLogFlops(nrhs * (2.0 * m * m - m)));
4143ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4154396437dSToby Isaac }
4164396437dSToby Isaac 
417d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatSolve_SeqDense_Internal_Cholesky(Mat A, PetscScalar *x, PetscBLASInt ldx, PetscBLASInt m, PetscBLASInt nrhs, PetscBLASInt k, PetscBool T)
418d71ae5a4SJacob Faibussowitsch {
4194396437dSToby Isaac   Mat_SeqDense *mat = (Mat_SeqDense *)A->data;
4204396437dSToby Isaac   PetscBLASInt  info;
4214396437dSToby Isaac 
4224396437dSToby Isaac   PetscFunctionBegin;
423b94d7dedSBarry Smith   if (A->spd == PETSC_BOOL3_TRUE) {
4249566063dSJacob Faibussowitsch     if (PetscDefined(USE_COMPLEX) && T) PetscCall(MatConjugate_SeqDense(A));
4259566063dSJacob Faibussowitsch     PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF));
426792fecdfSBarry Smith     PetscCallBLAS("LAPACKpotrs", LAPACKpotrs_("L", &m, &nrhs, mat->v, &mat->lda, x, &m, &info));
4279566063dSJacob Faibussowitsch     PetscCall(PetscFPTrapPop());
428835f2295SStefano Zampini     PetscCheck(!info, PETSC_COMM_SELF, PETSC_ERR_LIB, "POTRS Bad solve %" PetscBLASInt_FMT, info);
4299566063dSJacob Faibussowitsch     if (PetscDefined(USE_COMPLEX) && T) PetscCall(MatConjugate_SeqDense(A));
430a49dc2a2SStefano Zampini #if defined(PETSC_USE_COMPLEX)
431b94d7dedSBarry Smith   } else if (A->hermitian == PETSC_BOOL3_TRUE) {
4329566063dSJacob Faibussowitsch     if (T) PetscCall(MatConjugate_SeqDense(A));
4339566063dSJacob Faibussowitsch     PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF));
434792fecdfSBarry Smith     PetscCallBLAS("LAPACKhetrs", LAPACKhetrs_("L", &m, &nrhs, mat->v, &mat->lda, mat->pivots, x, &m, &info));
4359566063dSJacob Faibussowitsch     PetscCall(PetscFPTrapPop());
436835f2295SStefano Zampini     PetscCheck(!info, PETSC_COMM_SELF, PETSC_ERR_LIB, "HETRS Bad solve %" PetscBLASInt_FMT, info);
4379566063dSJacob Faibussowitsch     if (T) PetscCall(MatConjugate_SeqDense(A));
438a49dc2a2SStefano Zampini #endif
439a49dc2a2SStefano Zampini   } else { /* symmetric case */
4409566063dSJacob Faibussowitsch     PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF));
441792fecdfSBarry Smith     PetscCallBLAS("LAPACKsytrs", LAPACKsytrs_("L", &m, &nrhs, mat->v, &mat->lda, mat->pivots, x, &m, &info));
4429566063dSJacob Faibussowitsch     PetscCall(PetscFPTrapPop());
443835f2295SStefano Zampini     PetscCheck(!info, PETSC_COMM_SELF, PETSC_ERR_LIB, "SYTRS Bad solve %" PetscBLASInt_FMT, info);
444a49dc2a2SStefano Zampini   }
4459566063dSJacob Faibussowitsch   PetscCall(PetscLogFlops(nrhs * (2.0 * m * m - m)));
4463ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4474396437dSToby Isaac }
44885e2c93fSHong Zhang 
449d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatSolve_SeqDense_Internal_QR(Mat A, PetscScalar *x, PetscBLASInt ldx, PetscBLASInt m, PetscBLASInt nrhs, PetscBLASInt k)
450d71ae5a4SJacob Faibussowitsch {
4514396437dSToby Isaac   Mat_SeqDense *mat = (Mat_SeqDense *)A->data;
4524396437dSToby Isaac   PetscBLASInt  info;
4534396437dSToby Isaac   char          trans;
4544396437dSToby Isaac 
4554396437dSToby Isaac   PetscFunctionBegin;
4564905a7bcSToby Isaac   if (PetscDefined(USE_COMPLEX)) {
4574905a7bcSToby Isaac     trans = 'C';
4584905a7bcSToby Isaac   } else {
4594905a7bcSToby Isaac     trans = 'T';
4604905a7bcSToby Isaac   }
4619566063dSJacob Faibussowitsch   PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF));
46205fcb23eSStefano Zampini   { /* lwork depends on the number of right-hand sides */
46305fcb23eSStefano Zampini     PetscBLASInt nlfwork, lfwork = -1;
46405fcb23eSStefano Zampini     PetscScalar  fwork;
46505fcb23eSStefano Zampini 
466792fecdfSBarry Smith     PetscCallBLAS("LAPACKormqr", LAPACKormqr_("L", &trans, &m, &nrhs, &mat->rank, mat->v, &mat->lda, mat->tau, x, &ldx, &fwork, &lfwork, &info));
46705fcb23eSStefano Zampini     nlfwork = (PetscBLASInt)PetscRealPart(fwork);
46805fcb23eSStefano Zampini     if (nlfwork > mat->lfwork) {
46905fcb23eSStefano Zampini       mat->lfwork = nlfwork;
47005fcb23eSStefano Zampini       PetscCall(PetscFree(mat->fwork));
47105fcb23eSStefano Zampini       PetscCall(PetscMalloc1(mat->lfwork, &mat->fwork));
47205fcb23eSStefano Zampini     }
47305fcb23eSStefano Zampini   }
474792fecdfSBarry Smith   PetscCallBLAS("LAPACKormqr", LAPACKormqr_("L", &trans, &m, &nrhs, &mat->rank, mat->v, &mat->lda, mat->tau, x, &ldx, mat->fwork, &mat->lfwork, &info));
4759566063dSJacob Faibussowitsch   PetscCall(PetscFPTrapPop());
476835f2295SStefano Zampini   PetscCheck(!info, PETSC_COMM_SELF, PETSC_ERR_LIB, "ORMQR - Bad orthogonal transform %" PetscBLASInt_FMT, info);
4779566063dSJacob Faibussowitsch   PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF));
478792fecdfSBarry Smith   PetscCallBLAS("LAPACKtrtrs", LAPACKtrtrs_("U", "N", "N", &mat->rank, &nrhs, mat->v, &mat->lda, x, &ldx, &info));
4799566063dSJacob Faibussowitsch   PetscCall(PetscFPTrapPop());
480835f2295SStefano Zampini   PetscCheck(!info, PETSC_COMM_SELF, PETSC_ERR_LIB, "TRTRS - Bad triangular solve %" PetscBLASInt_FMT, info);
4814905a7bcSToby Isaac   for (PetscInt j = 0; j < nrhs; j++) {
482ad540459SPierre Jolivet     for (PetscInt i = mat->rank; i < k; i++) x[j * ldx + i] = 0.;
4834905a7bcSToby Isaac   }
4849566063dSJacob Faibussowitsch   PetscCall(PetscLogFlops(nrhs * (4.0 * m * mat->rank - PetscSqr(mat->rank))));
4853ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4864905a7bcSToby Isaac }
4874905a7bcSToby Isaac 
488d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatSolveTranspose_SeqDense_Internal_QR(Mat A, PetscScalar *x, PetscBLASInt ldx, PetscBLASInt m, PetscBLASInt nrhs, PetscBLASInt k)
489d71ae5a4SJacob Faibussowitsch {
4904396437dSToby Isaac   Mat_SeqDense *mat = (Mat_SeqDense *)A->data;
4914396437dSToby Isaac   PetscBLASInt  info;
4924396437dSToby Isaac 
4934396437dSToby Isaac   PetscFunctionBegin;
4944396437dSToby Isaac   if (A->rmap->n == A->cmap->n && mat->rank == A->rmap->n) {
4959566063dSJacob Faibussowitsch     PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF));
496792fecdfSBarry Smith     PetscCallBLAS("LAPACKtrtrs", LAPACKtrtrs_("U", "T", "N", &m, &nrhs, mat->v, &mat->lda, x, &ldx, &info));
4979566063dSJacob Faibussowitsch     PetscCall(PetscFPTrapPop());
498835f2295SStefano Zampini     PetscCheck(!info, PETSC_COMM_SELF, PETSC_ERR_LIB, "TRTRS - Bad triangular solve %" PetscBLASInt_FMT, info);
4999566063dSJacob Faibussowitsch     if (PetscDefined(USE_COMPLEX)) PetscCall(MatConjugate_SeqDense(A));
50005fcb23eSStefano Zampini     { /* lwork depends on the number of right-hand sides */
50105fcb23eSStefano Zampini       PetscBLASInt nlfwork, lfwork = -1;
50205fcb23eSStefano Zampini       PetscScalar  fwork;
50305fcb23eSStefano Zampini 
504792fecdfSBarry Smith       PetscCallBLAS("LAPACKormqr", LAPACKormqr_("L", "N", &m, &nrhs, &mat->rank, mat->v, &mat->lda, mat->tau, x, &ldx, &fwork, &lfwork, &info));
50505fcb23eSStefano Zampini       nlfwork = (PetscBLASInt)PetscRealPart(fwork);
50605fcb23eSStefano Zampini       if (nlfwork > mat->lfwork) {
50705fcb23eSStefano Zampini         mat->lfwork = nlfwork;
50805fcb23eSStefano Zampini         PetscCall(PetscFree(mat->fwork));
50905fcb23eSStefano Zampini         PetscCall(PetscMalloc1(mat->lfwork, &mat->fwork));
51005fcb23eSStefano Zampini       }
51105fcb23eSStefano Zampini     }
5129566063dSJacob Faibussowitsch     PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF));
513792fecdfSBarry Smith     PetscCallBLAS("LAPACKormqr", LAPACKormqr_("L", "N", &m, &nrhs, &mat->rank, mat->v, &mat->lda, mat->tau, x, &ldx, mat->fwork, &mat->lfwork, &info));
5149566063dSJacob Faibussowitsch     PetscCall(PetscFPTrapPop());
515835f2295SStefano Zampini     PetscCheck(!info, PETSC_COMM_SELF, PETSC_ERR_LIB, "ORMQR - Bad orthogonal transform %" PetscBLASInt_FMT, info);
5169566063dSJacob Faibussowitsch     if (PetscDefined(USE_COMPLEX)) PetscCall(MatConjugate_SeqDense(A));
5174396437dSToby Isaac   } else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "QR factored matrix cannot be used for transpose solve");
5189566063dSJacob Faibussowitsch   PetscCall(PetscLogFlops(nrhs * (4.0 * m * mat->rank - PetscSqr(mat->rank))));
5193ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5204396437dSToby Isaac }
5214396437dSToby Isaac 
522d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatSolve_SeqDense_SetUp(Mat A, Vec xx, Vec yy, PetscScalar **_y, PetscBLASInt *_m, PetscBLASInt *_k)
523d71ae5a4SJacob Faibussowitsch {
5244396437dSToby Isaac   Mat_SeqDense *mat = (Mat_SeqDense *)A->data;
5254905a7bcSToby Isaac   PetscScalar  *y;
5264905a7bcSToby Isaac   PetscBLASInt  m = 0, k = 0;
5274905a7bcSToby Isaac 
5284905a7bcSToby Isaac   PetscFunctionBegin;
5299566063dSJacob Faibussowitsch   PetscCall(PetscBLASIntCast(A->rmap->n, &m));
5309566063dSJacob Faibussowitsch   PetscCall(PetscBLASIntCast(A->cmap->n, &k));
5314905a7bcSToby Isaac   if (k < m) {
5329566063dSJacob Faibussowitsch     PetscCall(VecCopy(xx, mat->qrrhs));
5339566063dSJacob Faibussowitsch     PetscCall(VecGetArray(mat->qrrhs, &y));
5344905a7bcSToby Isaac   } else {
5359566063dSJacob Faibussowitsch     PetscCall(VecCopy(xx, yy));
5369566063dSJacob Faibussowitsch     PetscCall(VecGetArray(yy, &y));
5374905a7bcSToby Isaac   }
5384396437dSToby Isaac   *_y = y;
5394396437dSToby Isaac   *_k = k;
5404396437dSToby Isaac   *_m = m;
5413ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5424396437dSToby Isaac }
5434396437dSToby Isaac 
544d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatSolve_SeqDense_TearDown(Mat A, Vec xx, Vec yy, PetscScalar **_y, PetscBLASInt *_m, PetscBLASInt *_k)
545d71ae5a4SJacob Faibussowitsch {
5464396437dSToby Isaac   Mat_SeqDense *mat = (Mat_SeqDense *)A->data;
54742e9364cSSatish Balay   PetscScalar  *y   = NULL;
5484396437dSToby Isaac   PetscBLASInt  m, k;
5494396437dSToby Isaac 
5504396437dSToby Isaac   PetscFunctionBegin;
5514396437dSToby Isaac   y   = *_y;
5524396437dSToby Isaac   *_y = NULL;
5534396437dSToby Isaac   k   = *_k;
5544396437dSToby Isaac   m   = *_m;
5554905a7bcSToby Isaac   if (k < m) {
5564905a7bcSToby Isaac     PetscScalar *yv;
5579566063dSJacob Faibussowitsch     PetscCall(VecGetArray(yy, &yv));
5589566063dSJacob Faibussowitsch     PetscCall(PetscArraycpy(yv, y, k));
5599566063dSJacob Faibussowitsch     PetscCall(VecRestoreArray(yy, &yv));
5609566063dSJacob Faibussowitsch     PetscCall(VecRestoreArray(mat->qrrhs, &y));
5614905a7bcSToby Isaac   } else {
5629566063dSJacob Faibussowitsch     PetscCall(VecRestoreArray(yy, &y));
5634905a7bcSToby Isaac   }
5643ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5654905a7bcSToby Isaac }
5664905a7bcSToby Isaac 
567d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatSolve_SeqDense_LU(Mat A, Vec xx, Vec yy)
568d71ae5a4SJacob Faibussowitsch {
56942e9364cSSatish Balay   PetscScalar *y = NULL;
57042e9364cSSatish Balay   PetscBLASInt m = 0, k = 0;
5714396437dSToby Isaac 
5724396437dSToby Isaac   PetscFunctionBegin;
5739566063dSJacob Faibussowitsch   PetscCall(MatSolve_SeqDense_SetUp(A, xx, yy, &y, &m, &k));
5749566063dSJacob Faibussowitsch   PetscCall(MatSolve_SeqDense_Internal_LU(A, y, m, m, 1, k, PETSC_FALSE));
5759566063dSJacob Faibussowitsch   PetscCall(MatSolve_SeqDense_TearDown(A, xx, yy, &y, &m, &k));
5763ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5774396437dSToby Isaac }
5784396437dSToby Isaac 
579d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatSolveTranspose_SeqDense_LU(Mat A, Vec xx, Vec yy)
580d71ae5a4SJacob Faibussowitsch {
58142e9364cSSatish Balay   PetscScalar *y = NULL;
58242e9364cSSatish Balay   PetscBLASInt m = 0, k = 0;
5834396437dSToby Isaac 
5844396437dSToby Isaac   PetscFunctionBegin;
5859566063dSJacob Faibussowitsch   PetscCall(MatSolve_SeqDense_SetUp(A, xx, yy, &y, &m, &k));
5869566063dSJacob Faibussowitsch   PetscCall(MatSolve_SeqDense_Internal_LU(A, y, m, m, 1, k, PETSC_TRUE));
5879566063dSJacob Faibussowitsch   PetscCall(MatSolve_SeqDense_TearDown(A, xx, yy, &y, &m, &k));
5883ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5894396437dSToby Isaac }
5904396437dSToby Isaac 
591d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatSolve_SeqDense_Cholesky(Mat A, Vec xx, Vec yy)
592d71ae5a4SJacob Faibussowitsch {
593e54beecaSStefano Zampini   PetscScalar *y = NULL;
594e54beecaSStefano Zampini   PetscBLASInt m = 0, k = 0;
5954396437dSToby Isaac 
5964396437dSToby Isaac   PetscFunctionBegin;
5979566063dSJacob Faibussowitsch   PetscCall(MatSolve_SeqDense_SetUp(A, xx, yy, &y, &m, &k));
5989566063dSJacob Faibussowitsch   PetscCall(MatSolve_SeqDense_Internal_Cholesky(A, y, m, m, 1, k, PETSC_FALSE));
5999566063dSJacob Faibussowitsch   PetscCall(MatSolve_SeqDense_TearDown(A, xx, yy, &y, &m, &k));
6003ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
6014396437dSToby Isaac }
6024396437dSToby Isaac 
603d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatSolveTranspose_SeqDense_Cholesky(Mat A, Vec xx, Vec yy)
604d71ae5a4SJacob Faibussowitsch {
605e54beecaSStefano Zampini   PetscScalar *y = NULL;
606e54beecaSStefano Zampini   PetscBLASInt m = 0, k = 0;
6074396437dSToby Isaac 
6084396437dSToby Isaac   PetscFunctionBegin;
6099566063dSJacob Faibussowitsch   PetscCall(MatSolve_SeqDense_SetUp(A, xx, yy, &y, &m, &k));
6109566063dSJacob Faibussowitsch   PetscCall(MatSolve_SeqDense_Internal_Cholesky(A, y, m, m, 1, k, PETSC_TRUE));
6119566063dSJacob Faibussowitsch   PetscCall(MatSolve_SeqDense_TearDown(A, xx, yy, &y, &m, &k));
6123ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
6134396437dSToby Isaac }
6144396437dSToby Isaac 
615d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatSolve_SeqDense_QR(Mat A, Vec xx, Vec yy)
616d71ae5a4SJacob Faibussowitsch {
617e54beecaSStefano Zampini   PetscScalar *y = NULL;
618e54beecaSStefano Zampini   PetscBLASInt m = 0, k = 0;
6194396437dSToby Isaac 
6204396437dSToby Isaac   PetscFunctionBegin;
6219566063dSJacob Faibussowitsch   PetscCall(MatSolve_SeqDense_SetUp(A, xx, yy, &y, &m, &k));
6229566063dSJacob Faibussowitsch   PetscCall(MatSolve_SeqDense_Internal_QR(A, y, PetscMax(m, k), m, 1, k));
6239566063dSJacob Faibussowitsch   PetscCall(MatSolve_SeqDense_TearDown(A, xx, yy, &y, &m, &k));
6243ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
6254396437dSToby Isaac }
6264396437dSToby Isaac 
627d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatSolveTranspose_SeqDense_QR(Mat A, Vec xx, Vec yy)
628d71ae5a4SJacob Faibussowitsch {
62942e9364cSSatish Balay   PetscScalar *y = NULL;
63042e9364cSSatish Balay   PetscBLASInt m = 0, k = 0;
6314396437dSToby Isaac 
6324396437dSToby Isaac   PetscFunctionBegin;
6339566063dSJacob Faibussowitsch   PetscCall(MatSolve_SeqDense_SetUp(A, xx, yy, &y, &m, &k));
6349566063dSJacob Faibussowitsch   PetscCall(MatSolveTranspose_SeqDense_Internal_QR(A, y, PetscMax(m, k), m, 1, k));
6359566063dSJacob Faibussowitsch   PetscCall(MatSolve_SeqDense_TearDown(A, xx, yy, &y, &m, &k));
6363ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
6374396437dSToby Isaac }
6384396437dSToby Isaac 
639d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatMatSolve_SeqDense_SetUp(Mat A, Mat B, Mat X, PetscScalar **_y, PetscBLASInt *_ldy, PetscBLASInt *_m, PetscBLASInt *_nrhs, PetscBLASInt *_k)
640d71ae5a4SJacob Faibussowitsch {
6414905a7bcSToby Isaac   const PetscScalar *b;
6424396437dSToby Isaac   PetscScalar       *y;
643bf5a80bcSToby Isaac   PetscInt           n, _ldb, _ldx;
644bf5a80bcSToby Isaac   PetscBLASInt       nrhs = 0, m = 0, k = 0, ldb = 0, ldx = 0, ldy = 0;
6454905a7bcSToby Isaac 
6464905a7bcSToby Isaac   PetscFunctionBegin;
6479371c9d4SSatish Balay   *_ldy  = 0;
6489371c9d4SSatish Balay   *_m    = 0;
6499371c9d4SSatish Balay   *_nrhs = 0;
6509371c9d4SSatish Balay   *_k    = 0;
6519371c9d4SSatish Balay   *_y    = NULL;
6529566063dSJacob Faibussowitsch   PetscCall(PetscBLASIntCast(A->rmap->n, &m));
6539566063dSJacob Faibussowitsch   PetscCall(PetscBLASIntCast(A->cmap->n, &k));
6549566063dSJacob Faibussowitsch   PetscCall(MatGetSize(B, NULL, &n));
6559566063dSJacob Faibussowitsch   PetscCall(PetscBLASIntCast(n, &nrhs));
6569566063dSJacob Faibussowitsch   PetscCall(MatDenseGetLDA(B, &_ldb));
6579566063dSJacob Faibussowitsch   PetscCall(PetscBLASIntCast(_ldb, &ldb));
6589566063dSJacob Faibussowitsch   PetscCall(MatDenseGetLDA(X, &_ldx));
6599566063dSJacob Faibussowitsch   PetscCall(PetscBLASIntCast(_ldx, &ldx));
660bf5a80bcSToby Isaac   if (ldx < m) {
6619566063dSJacob Faibussowitsch     PetscCall(MatDenseGetArrayRead(B, &b));
6629566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(nrhs * m, &y));
663bf5a80bcSToby Isaac     if (ldb == m) {
6649566063dSJacob Faibussowitsch       PetscCall(PetscArraycpy(y, b, ldb * nrhs));
6654905a7bcSToby Isaac     } else {
66648a46eb9SPierre Jolivet       for (PetscInt j = 0; j < nrhs; j++) PetscCall(PetscArraycpy(&y[j * m], &b[j * ldb], m));
6674905a7bcSToby Isaac     }
668bf5a80bcSToby Isaac     ldy = m;
6699566063dSJacob Faibussowitsch     PetscCall(MatDenseRestoreArrayRead(B, &b));
6704905a7bcSToby Isaac   } else {
671bf5a80bcSToby Isaac     if (ldb == ldx) {
6729566063dSJacob Faibussowitsch       PetscCall(MatCopy(B, X, SAME_NONZERO_PATTERN));
6739566063dSJacob Faibussowitsch       PetscCall(MatDenseGetArray(X, &y));
6744905a7bcSToby Isaac     } else {
6759566063dSJacob Faibussowitsch       PetscCall(MatDenseGetArray(X, &y));
6769566063dSJacob Faibussowitsch       PetscCall(MatDenseGetArrayRead(B, &b));
67748a46eb9SPierre Jolivet       for (PetscInt j = 0; j < nrhs; j++) PetscCall(PetscArraycpy(&y[j * ldx], &b[j * ldb], m));
6789566063dSJacob Faibussowitsch       PetscCall(MatDenseRestoreArrayRead(B, &b));
6794905a7bcSToby Isaac     }
680bf5a80bcSToby Isaac     ldy = ldx;
6814905a7bcSToby Isaac   }
6824396437dSToby Isaac   *_y    = y;
683bf5a80bcSToby Isaac   *_ldy  = ldy;
6844396437dSToby Isaac   *_k    = k;
6854396437dSToby Isaac   *_m    = m;
6864396437dSToby Isaac   *_nrhs = nrhs;
6873ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
6884396437dSToby Isaac }
6894396437dSToby Isaac 
690d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatMatSolve_SeqDense_TearDown(Mat A, Mat B, Mat X, PetscScalar **_y, PetscBLASInt *_ldy, PetscBLASInt *_m, PetscBLASInt *_nrhs, PetscBLASInt *_k)
691d71ae5a4SJacob Faibussowitsch {
6924396437dSToby Isaac   PetscScalar *y;
693bf5a80bcSToby Isaac   PetscInt     _ldx;
694bf5a80bcSToby Isaac   PetscBLASInt k, ldy, nrhs, ldx = 0;
6954396437dSToby Isaac 
6964396437dSToby Isaac   PetscFunctionBegin;
6974396437dSToby Isaac   y    = *_y;
6984396437dSToby Isaac   *_y  = NULL;
6994396437dSToby Isaac   k    = *_k;
700bf5a80bcSToby Isaac   ldy  = *_ldy;
7014396437dSToby Isaac   nrhs = *_nrhs;
7029566063dSJacob Faibussowitsch   PetscCall(MatDenseGetLDA(X, &_ldx));
7039566063dSJacob Faibussowitsch   PetscCall(PetscBLASIntCast(_ldx, &ldx));
704bf5a80bcSToby Isaac   if (ldx != ldy) {
7054905a7bcSToby Isaac     PetscScalar *xv;
7069566063dSJacob Faibussowitsch     PetscCall(MatDenseGetArray(X, &xv));
70748a46eb9SPierre Jolivet     for (PetscInt j = 0; j < nrhs; j++) PetscCall(PetscArraycpy(&xv[j * ldx], &y[j * ldy], k));
7089566063dSJacob Faibussowitsch     PetscCall(MatDenseRestoreArray(X, &xv));
7099566063dSJacob Faibussowitsch     PetscCall(PetscFree(y));
7104905a7bcSToby Isaac   } else {
7119566063dSJacob Faibussowitsch     PetscCall(MatDenseRestoreArray(X, &y));
7124905a7bcSToby Isaac   }
7133ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
71485e2c93fSHong Zhang }
71585e2c93fSHong Zhang 
716d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatMatSolve_SeqDense_LU(Mat A, Mat B, Mat X)
717d71ae5a4SJacob Faibussowitsch {
7184396437dSToby Isaac   PetscScalar *y;
719bf5a80bcSToby Isaac   PetscBLASInt m, k, ldy, nrhs;
7204396437dSToby Isaac 
7214396437dSToby Isaac   PetscFunctionBegin;
7229566063dSJacob Faibussowitsch   PetscCall(MatMatSolve_SeqDense_SetUp(A, B, X, &y, &ldy, &m, &nrhs, &k));
7239566063dSJacob Faibussowitsch   PetscCall(MatSolve_SeqDense_Internal_LU(A, y, ldy, m, nrhs, k, PETSC_FALSE));
7249566063dSJacob Faibussowitsch   PetscCall(MatMatSolve_SeqDense_TearDown(A, B, X, &y, &ldy, &m, &nrhs, &k));
7253ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
7264396437dSToby Isaac }
7274396437dSToby Isaac 
728d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatMatSolveTranspose_SeqDense_LU(Mat A, Mat B, Mat X)
729d71ae5a4SJacob Faibussowitsch {
7304396437dSToby Isaac   PetscScalar *y;
731bf5a80bcSToby Isaac   PetscBLASInt m, k, ldy, nrhs;
7324396437dSToby Isaac 
7334396437dSToby Isaac   PetscFunctionBegin;
7349566063dSJacob Faibussowitsch   PetscCall(MatMatSolve_SeqDense_SetUp(A, B, X, &y, &ldy, &m, &nrhs, &k));
7359566063dSJacob Faibussowitsch   PetscCall(MatSolve_SeqDense_Internal_LU(A, y, ldy, m, nrhs, k, PETSC_TRUE));
7369566063dSJacob Faibussowitsch   PetscCall(MatMatSolve_SeqDense_TearDown(A, B, X, &y, &ldy, &m, &nrhs, &k));
7373ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
7384396437dSToby Isaac }
7394396437dSToby Isaac 
740d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatMatSolve_SeqDense_Cholesky(Mat A, Mat B, Mat X)
741d71ae5a4SJacob Faibussowitsch {
7424396437dSToby Isaac   PetscScalar *y;
743bf5a80bcSToby Isaac   PetscBLASInt m, k, ldy, nrhs;
7444396437dSToby Isaac 
7454396437dSToby Isaac   PetscFunctionBegin;
7469566063dSJacob Faibussowitsch   PetscCall(MatMatSolve_SeqDense_SetUp(A, B, X, &y, &ldy, &m, &nrhs, &k));
7479566063dSJacob Faibussowitsch   PetscCall(MatSolve_SeqDense_Internal_Cholesky(A, y, ldy, m, nrhs, k, PETSC_FALSE));
7489566063dSJacob Faibussowitsch   PetscCall(MatMatSolve_SeqDense_TearDown(A, B, X, &y, &ldy, &m, &nrhs, &k));
7493ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
7504396437dSToby Isaac }
7514396437dSToby Isaac 
752d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatMatSolveTranspose_SeqDense_Cholesky(Mat A, Mat B, Mat X)
753d71ae5a4SJacob Faibussowitsch {
7544396437dSToby Isaac   PetscScalar *y;
755bf5a80bcSToby Isaac   PetscBLASInt m, k, ldy, nrhs;
7564396437dSToby Isaac 
7574396437dSToby Isaac   PetscFunctionBegin;
7589566063dSJacob Faibussowitsch   PetscCall(MatMatSolve_SeqDense_SetUp(A, B, X, &y, &ldy, &m, &nrhs, &k));
7599566063dSJacob Faibussowitsch   PetscCall(MatSolve_SeqDense_Internal_Cholesky(A, y, ldy, m, nrhs, k, PETSC_TRUE));
7609566063dSJacob Faibussowitsch   PetscCall(MatMatSolve_SeqDense_TearDown(A, B, X, &y, &ldy, &m, &nrhs, &k));
7613ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
7624396437dSToby Isaac }
7634396437dSToby Isaac 
764d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatMatSolve_SeqDense_QR(Mat A, Mat B, Mat X)
765d71ae5a4SJacob Faibussowitsch {
7664396437dSToby Isaac   PetscScalar *y;
767bf5a80bcSToby Isaac   PetscBLASInt m, k, ldy, nrhs;
7684396437dSToby Isaac 
7694396437dSToby Isaac   PetscFunctionBegin;
7709566063dSJacob Faibussowitsch   PetscCall(MatMatSolve_SeqDense_SetUp(A, B, X, &y, &ldy, &m, &nrhs, &k));
7719566063dSJacob Faibussowitsch   PetscCall(MatSolve_SeqDense_Internal_QR(A, y, ldy, m, nrhs, k));
7729566063dSJacob Faibussowitsch   PetscCall(MatMatSolve_SeqDense_TearDown(A, B, X, &y, &ldy, &m, &nrhs, &k));
7733ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
7744396437dSToby Isaac }
7754396437dSToby Isaac 
776d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatMatSolveTranspose_SeqDense_QR(Mat A, Mat B, Mat X)
777d71ae5a4SJacob Faibussowitsch {
7784396437dSToby Isaac   PetscScalar *y;
779bf5a80bcSToby Isaac   PetscBLASInt m, k, ldy, nrhs;
7804396437dSToby Isaac 
7814396437dSToby Isaac   PetscFunctionBegin;
7829566063dSJacob Faibussowitsch   PetscCall(MatMatSolve_SeqDense_SetUp(A, B, X, &y, &ldy, &m, &nrhs, &k));
7839566063dSJacob Faibussowitsch   PetscCall(MatSolveTranspose_SeqDense_Internal_QR(A, y, ldy, m, nrhs, k));
7849566063dSJacob Faibussowitsch   PetscCall(MatMatSolve_SeqDense_TearDown(A, B, X, &y, &ldy, &m, &nrhs, &k));
7853ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
7864396437dSToby Isaac }
7874396437dSToby Isaac 
788db4efbfdSBarry Smith /* COMMENT: I have chosen to hide row permutation in the pivots,
789db4efbfdSBarry Smith    rather than put it in the Mat->row slot.*/
790d71ae5a4SJacob Faibussowitsch PetscErrorCode MatLUFactor_SeqDense(Mat A, IS row, IS col, const MatFactorInfo *minfo)
791d71ae5a4SJacob Faibussowitsch {
792db4efbfdSBarry Smith   Mat_SeqDense *mat = (Mat_SeqDense *)A->data;
793db4efbfdSBarry Smith   PetscBLASInt  n, m, info;
794db4efbfdSBarry Smith 
795db4efbfdSBarry Smith   PetscFunctionBegin;
7969566063dSJacob Faibussowitsch   PetscCall(PetscBLASIntCast(A->cmap->n, &n));
7979566063dSJacob Faibussowitsch   PetscCall(PetscBLASIntCast(A->rmap->n, &m));
7984dfa11a4SJacob Faibussowitsch   if (!mat->pivots) { PetscCall(PetscMalloc1(A->rmap->n, &mat->pivots)); }
7993ba16761SJacob Faibussowitsch   if (!A->rmap->n || !A->cmap->n) PetscFunctionReturn(PETSC_SUCCESS);
8009566063dSJacob Faibussowitsch   PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF));
801792fecdfSBarry Smith   PetscCallBLAS("LAPACKgetrf", LAPACKgetrf_(&m, &n, mat->v, &mat->lda, mat->pivots, &info));
8029566063dSJacob Faibussowitsch   PetscCall(PetscFPTrapPop());
8038e57ea43SSatish Balay 
804835f2295SStefano Zampini   PetscCheck(info >= 0, PETSC_COMM_SELF, PETSC_ERR_LIB, "Bad argument to LU factorization %" PetscBLASInt_FMT, info);
805835f2295SStefano Zampini   PetscCheck(info <= 0, PETSC_COMM_SELF, PETSC_ERR_MAT_LU_ZRPVT, "Bad LU factorization %" PetscBLASInt_FMT, info);
8068208b9aeSStefano Zampini 
8074396437dSToby Isaac   A->ops->solve             = MatSolve_SeqDense_LU;
8084396437dSToby Isaac   A->ops->matsolve          = MatMatSolve_SeqDense_LU;
8094396437dSToby Isaac   A->ops->solvetranspose    = MatSolveTranspose_SeqDense_LU;
8104396437dSToby Isaac   A->ops->matsolvetranspose = MatMatSolveTranspose_SeqDense_LU;
811d5f3da31SBarry Smith   A->factortype             = MAT_FACTOR_LU;
812db4efbfdSBarry Smith 
8139566063dSJacob Faibussowitsch   PetscCall(PetscFree(A->solvertype));
8149566063dSJacob Faibussowitsch   PetscCall(PetscStrallocpy(MATSOLVERPETSC, &A->solvertype));
815f6224b95SHong Zhang 
8169566063dSJacob Faibussowitsch   PetscCall(PetscLogFlops((2.0 * A->cmap->n * A->cmap->n * A->cmap->n) / 3));
8173ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
818db4efbfdSBarry Smith }
819db4efbfdSBarry Smith 
820d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatLUFactorNumeric_SeqDense(Mat fact, Mat A, const MatFactorInfo *info_dummy)
821d71ae5a4SJacob Faibussowitsch {
8224396437dSToby Isaac   MatFactorInfo info;
8234396437dSToby Isaac 
8244396437dSToby Isaac   PetscFunctionBegin;
8259566063dSJacob Faibussowitsch   PetscCall(MatDuplicateNoCreate_SeqDense(fact, A, MAT_COPY_VALUES));
826dbbe0bcdSBarry Smith   PetscUseTypeMethod(fact, lufactor, NULL, NULL, &info);
8273ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
8284396437dSToby Isaac }
8294396437dSToby Isaac 
830d71ae5a4SJacob Faibussowitsch PetscErrorCode MatLUFactorSymbolic_SeqDense(Mat fact, Mat A, IS row, IS col, const MatFactorInfo *info)
831d71ae5a4SJacob Faibussowitsch {
8324396437dSToby Isaac   PetscFunctionBegin;
8334396437dSToby Isaac   fact->preallocated         = PETSC_TRUE;
8344396437dSToby Isaac   fact->assembled            = PETSC_TRUE;
8354396437dSToby Isaac   fact->ops->lufactornumeric = MatLUFactorNumeric_SeqDense;
8363ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
8374396437dSToby Isaac }
8384396437dSToby Isaac 
839a49dc2a2SStefano Zampini /* Cholesky as L*L^T or L*D*L^T and the symmetric/hermitian complex variants */
840d71ae5a4SJacob Faibussowitsch PetscErrorCode MatCholeskyFactor_SeqDense(Mat A, IS perm, const MatFactorInfo *factinfo)
841d71ae5a4SJacob Faibussowitsch {
842db4efbfdSBarry Smith   Mat_SeqDense *mat = (Mat_SeqDense *)A->data;
843c5df96a5SBarry Smith   PetscBLASInt  info, n;
844db4efbfdSBarry Smith 
845db4efbfdSBarry Smith   PetscFunctionBegin;
8469566063dSJacob Faibussowitsch   PetscCall(PetscBLASIntCast(A->cmap->n, &n));
8473ba16761SJacob Faibussowitsch   if (!A->rmap->n || !A->cmap->n) PetscFunctionReturn(PETSC_SUCCESS);
848b94d7dedSBarry Smith   if (A->spd == PETSC_BOOL3_TRUE) {
8499566063dSJacob Faibussowitsch     PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF));
850792fecdfSBarry Smith     PetscCallBLAS("LAPACKpotrf", LAPACKpotrf_("L", &n, mat->v, &mat->lda, &info));
8519566063dSJacob Faibussowitsch     PetscCall(PetscFPTrapPop());
852a49dc2a2SStefano Zampini #if defined(PETSC_USE_COMPLEX)
853b94d7dedSBarry Smith   } else if (A->hermitian == PETSC_BOOL3_TRUE) {
8544dfa11a4SJacob Faibussowitsch     if (!mat->pivots) { PetscCall(PetscMalloc1(A->rmap->n, &mat->pivots)); }
855a49dc2a2SStefano Zampini     if (!mat->fwork) {
856a49dc2a2SStefano Zampini       PetscScalar dummy;
857a49dc2a2SStefano Zampini 
858a49dc2a2SStefano Zampini       mat->lfwork = -1;
8599566063dSJacob Faibussowitsch       PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF));
860792fecdfSBarry Smith       PetscCallBLAS("LAPACKhetrf", LAPACKhetrf_("L", &n, mat->v, &mat->lda, mat->pivots, &dummy, &mat->lfwork, &info));
8619566063dSJacob Faibussowitsch       PetscCall(PetscFPTrapPop());
86207c83e99SJose E. Roman       PetscCall(PetscBLASIntCast((PetscCount)(PetscRealPart(dummy)), &mat->lfwork));
8639566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(mat->lfwork, &mat->fwork));
864a49dc2a2SStefano Zampini     }
8659566063dSJacob Faibussowitsch     PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF));
866792fecdfSBarry Smith     PetscCallBLAS("LAPACKhetrf", LAPACKhetrf_("L", &n, mat->v, &mat->lda, mat->pivots, mat->fwork, &mat->lfwork, &info));
8679566063dSJacob Faibussowitsch     PetscCall(PetscFPTrapPop());
868a49dc2a2SStefano Zampini #endif
869a49dc2a2SStefano Zampini   } else { /* symmetric case */
8704dfa11a4SJacob Faibussowitsch     if (!mat->pivots) { PetscCall(PetscMalloc1(A->rmap->n, &mat->pivots)); }
871a49dc2a2SStefano Zampini     if (!mat->fwork) {
872a49dc2a2SStefano Zampini       PetscScalar dummy;
873a49dc2a2SStefano Zampini 
874a49dc2a2SStefano Zampini       mat->lfwork = -1;
8759566063dSJacob Faibussowitsch       PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF));
876792fecdfSBarry Smith       PetscCallBLAS("LAPACKsytrf", LAPACKsytrf_("L", &n, mat->v, &mat->lda, mat->pivots, &dummy, &mat->lfwork, &info));
8779566063dSJacob Faibussowitsch       PetscCall(PetscFPTrapPop());
8786497c311SBarry Smith       PetscCall(PetscBLASIntCast((PetscCount)(PetscRealPart(dummy)), &mat->lfwork));
8799566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(mat->lfwork, &mat->fwork));
880a49dc2a2SStefano Zampini     }
8819566063dSJacob Faibussowitsch     PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF));
882792fecdfSBarry Smith     PetscCallBLAS("LAPACKsytrf", LAPACKsytrf_("L", &n, mat->v, &mat->lda, mat->pivots, mat->fwork, &mat->lfwork, &info));
8839566063dSJacob Faibussowitsch     PetscCall(PetscFPTrapPop());
884a49dc2a2SStefano Zampini   }
885835f2295SStefano Zampini   PetscCheck(!info, PETSC_COMM_SELF, PETSC_ERR_MAT_CH_ZRPVT, "Bad factorization: zero pivot in row %" PetscBLASInt_FMT, info - 1);
8868208b9aeSStefano Zampini 
8874396437dSToby Isaac   A->ops->solve             = MatSolve_SeqDense_Cholesky;
8884396437dSToby Isaac   A->ops->matsolve          = MatMatSolve_SeqDense_Cholesky;
8894396437dSToby Isaac   A->ops->solvetranspose    = MatSolveTranspose_SeqDense_Cholesky;
8904396437dSToby Isaac   A->ops->matsolvetranspose = MatMatSolveTranspose_SeqDense_Cholesky;
891d5f3da31SBarry Smith   A->factortype             = MAT_FACTOR_CHOLESKY;
8922205254eSKarl Rupp 
8939566063dSJacob Faibussowitsch   PetscCall(PetscFree(A->solvertype));
8949566063dSJacob Faibussowitsch   PetscCall(PetscStrallocpy(MATSOLVERPETSC, &A->solvertype));
895f6224b95SHong Zhang 
8969566063dSJacob Faibussowitsch   PetscCall(PetscLogFlops((1.0 * A->cmap->n * A->cmap->n * A->cmap->n) / 3.0));
8973ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
898db4efbfdSBarry Smith }
899db4efbfdSBarry Smith 
900d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatCholeskyFactorNumeric_SeqDense(Mat fact, Mat A, const MatFactorInfo *info_dummy)
901d71ae5a4SJacob Faibussowitsch {
902db4efbfdSBarry Smith   MatFactorInfo info;
903db4efbfdSBarry Smith 
904db4efbfdSBarry Smith   PetscFunctionBegin;
905db4efbfdSBarry Smith   info.fill = 1.0;
9062205254eSKarl Rupp 
9079566063dSJacob Faibussowitsch   PetscCall(MatDuplicateNoCreate_SeqDense(fact, A, MAT_COPY_VALUES));
908dbbe0bcdSBarry Smith   PetscUseTypeMethod(fact, choleskyfactor, NULL, &info);
9093ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
910db4efbfdSBarry Smith }
911db4efbfdSBarry Smith 
912d71ae5a4SJacob Faibussowitsch PetscErrorCode MatCholeskyFactorSymbolic_SeqDense(Mat fact, Mat A, IS row, const MatFactorInfo *info)
913d71ae5a4SJacob Faibussowitsch {
914db4efbfdSBarry Smith   PetscFunctionBegin;
915c3ef05f6SHong Zhang   fact->assembled                  = PETSC_TRUE;
9161bbcc794SSatish Balay   fact->preallocated               = PETSC_TRUE;
917719d5645SBarry Smith   fact->ops->choleskyfactornumeric = MatCholeskyFactorNumeric_SeqDense;
9183ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
919db4efbfdSBarry Smith }
920db4efbfdSBarry Smith 
921d71ae5a4SJacob Faibussowitsch PetscErrorCode MatQRFactor_SeqDense(Mat A, IS col, const MatFactorInfo *minfo)
922d71ae5a4SJacob Faibussowitsch {
9234905a7bcSToby Isaac   Mat_SeqDense *mat = (Mat_SeqDense *)A->data;
9244905a7bcSToby Isaac   PetscBLASInt  n, m, info, min, max;
9254905a7bcSToby Isaac 
9264905a7bcSToby Isaac   PetscFunctionBegin;
9279566063dSJacob Faibussowitsch   PetscCall(PetscBLASIntCast(A->cmap->n, &n));
9289566063dSJacob Faibussowitsch   PetscCall(PetscBLASIntCast(A->rmap->n, &m));
9294396437dSToby Isaac   max = PetscMax(m, n);
9304396437dSToby Isaac   min = PetscMin(m, n);
9314dfa11a4SJacob Faibussowitsch   if (!mat->tau) { PetscCall(PetscMalloc1(min, &mat->tau)); }
9324dfa11a4SJacob Faibussowitsch   if (!mat->pivots) { PetscCall(PetscMalloc1(n, &mat->pivots)); }
933f4f49eeaSPierre Jolivet   if (!mat->qrrhs) PetscCall(MatCreateVecs(A, NULL, &mat->qrrhs));
9343ba16761SJacob Faibussowitsch   if (!A->rmap->n || !A->cmap->n) PetscFunctionReturn(PETSC_SUCCESS);
9354905a7bcSToby Isaac   if (!mat->fwork) {
9364905a7bcSToby Isaac     PetscScalar dummy;
9374905a7bcSToby Isaac 
9384905a7bcSToby Isaac     mat->lfwork = -1;
9399566063dSJacob Faibussowitsch     PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF));
940792fecdfSBarry Smith     PetscCallBLAS("LAPACKgeqrf", LAPACKgeqrf_(&m, &n, mat->v, &mat->lda, mat->tau, &dummy, &mat->lfwork, &info));
9419566063dSJacob Faibussowitsch     PetscCall(PetscFPTrapPop());
9426497c311SBarry Smith     PetscCall(PetscBLASIntCast((PetscCount)(PetscRealPart(dummy)), &mat->lfwork));
9439566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(mat->lfwork, &mat->fwork));
9444905a7bcSToby Isaac   }
9459566063dSJacob Faibussowitsch   PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF));
946792fecdfSBarry Smith   PetscCallBLAS("LAPACKgeqrf", LAPACKgeqrf_(&m, &n, mat->v, &mat->lda, mat->tau, mat->fwork, &mat->lfwork, &info));
9479566063dSJacob Faibussowitsch   PetscCall(PetscFPTrapPop());
948835f2295SStefano Zampini   PetscCheck(!info, PETSC_COMM_SELF, PETSC_ERR_LIB, "Bad argument to QR factorization %" PetscBLASInt_FMT, info);
9494905a7bcSToby 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
9504905a7bcSToby Isaac   mat->rank = min;
9514905a7bcSToby Isaac 
9524396437dSToby Isaac   A->ops->solve    = MatSolve_SeqDense_QR;
9534396437dSToby Isaac   A->ops->matsolve = MatMatSolve_SeqDense_QR;
9544905a7bcSToby Isaac   A->factortype    = MAT_FACTOR_QR;
9554905a7bcSToby Isaac   if (m == n) {
9564396437dSToby Isaac     A->ops->solvetranspose    = MatSolveTranspose_SeqDense_QR;
9574396437dSToby Isaac     A->ops->matsolvetranspose = MatMatSolveTranspose_SeqDense_QR;
9584905a7bcSToby Isaac   }
9594905a7bcSToby Isaac 
9609566063dSJacob Faibussowitsch   PetscCall(PetscFree(A->solvertype));
9619566063dSJacob Faibussowitsch   PetscCall(PetscStrallocpy(MATSOLVERPETSC, &A->solvertype));
9624905a7bcSToby Isaac 
9639566063dSJacob Faibussowitsch   PetscCall(PetscLogFlops(2.0 * min * min * (max - min / 3.0)));
9643ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
9654905a7bcSToby Isaac }
9664905a7bcSToby Isaac 
967d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatQRFactorNumeric_SeqDense(Mat fact, Mat A, const MatFactorInfo *info_dummy)
968d71ae5a4SJacob Faibussowitsch {
9694905a7bcSToby Isaac   MatFactorInfo info;
9704905a7bcSToby Isaac 
9714905a7bcSToby Isaac   PetscFunctionBegin;
9724905a7bcSToby Isaac   info.fill = 1.0;
9734905a7bcSToby Isaac 
9749566063dSJacob Faibussowitsch   PetscCall(MatDuplicateNoCreate_SeqDense(fact, A, MAT_COPY_VALUES));
975cac4c232SBarry Smith   PetscUseMethod(fact, "MatQRFactor_C", (Mat, IS, const MatFactorInfo *), (fact, NULL, &info));
9763ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
9774905a7bcSToby Isaac }
9784905a7bcSToby Isaac 
979d71ae5a4SJacob Faibussowitsch PetscErrorCode MatQRFactorSymbolic_SeqDense(Mat fact, Mat A, IS row, const MatFactorInfo *info)
980d71ae5a4SJacob Faibussowitsch {
9814905a7bcSToby Isaac   PetscFunctionBegin;
9824905a7bcSToby Isaac   fact->assembled    = PETSC_TRUE;
9834905a7bcSToby Isaac   fact->preallocated = PETSC_TRUE;
9849566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)fact, "MatQRFactorNumeric_C", MatQRFactorNumeric_SeqDense));
9853ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
9864905a7bcSToby Isaac }
9874905a7bcSToby Isaac 
988ca15aa20SStefano Zampini /* uses LAPACK */
989d71ae5a4SJacob Faibussowitsch PETSC_INTERN PetscErrorCode MatGetFactor_seqdense_petsc(Mat A, MatFactorType ftype, Mat *fact)
990d71ae5a4SJacob Faibussowitsch {
991db4efbfdSBarry Smith   PetscFunctionBegin;
9929566063dSJacob Faibussowitsch   PetscCall(MatCreate(PetscObjectComm((PetscObject)A), fact));
9939566063dSJacob Faibussowitsch   PetscCall(MatSetSizes(*fact, A->rmap->n, A->cmap->n, A->rmap->n, A->cmap->n));
9949566063dSJacob Faibussowitsch   PetscCall(MatSetType(*fact, MATDENSE));
99566e17bc3SBarry Smith   (*fact)->trivialsymbolic = PETSC_TRUE;
9962a350339SBarry Smith   if (ftype == MAT_FACTOR_LU || ftype == MAT_FACTOR_ILU) {
997db4efbfdSBarry Smith     (*fact)->ops->lufactorsymbolic  = MatLUFactorSymbolic_SeqDense;
9982a350339SBarry Smith     (*fact)->ops->ilufactorsymbolic = MatLUFactorSymbolic_SeqDense;
999bf5a80bcSToby Isaac   } else if (ftype == MAT_FACTOR_CHOLESKY || ftype == MAT_FACTOR_ICC) {
1000db4efbfdSBarry Smith     (*fact)->ops->choleskyfactorsymbolic = MatCholeskyFactorSymbolic_SeqDense;
1001bf5a80bcSToby Isaac   } else if (ftype == MAT_FACTOR_QR) {
1002f4f49eeaSPierre Jolivet     PetscCall(PetscObjectComposeFunction((PetscObject)*fact, "MatQRFactorSymbolic_C", MatQRFactorSymbolic_SeqDense));
1003db4efbfdSBarry Smith   }
1004d5f3da31SBarry Smith   (*fact)->factortype = ftype;
100500c67f3bSHong Zhang 
10069566063dSJacob Faibussowitsch   PetscCall(PetscFree((*fact)->solvertype));
10079566063dSJacob Faibussowitsch   PetscCall(PetscStrallocpy(MATSOLVERPETSC, &(*fact)->solvertype));
10089566063dSJacob Faibussowitsch   PetscCall(PetscStrallocpy(MATORDERINGEXTERNAL, (char **)&(*fact)->preferredordering[MAT_FACTOR_LU]));
10099566063dSJacob Faibussowitsch   PetscCall(PetscStrallocpy(MATORDERINGEXTERNAL, (char **)&(*fact)->preferredordering[MAT_FACTOR_ILU]));
10109566063dSJacob Faibussowitsch   PetscCall(PetscStrallocpy(MATORDERINGEXTERNAL, (char **)&(*fact)->preferredordering[MAT_FACTOR_CHOLESKY]));
10119566063dSJacob Faibussowitsch   PetscCall(PetscStrallocpy(MATORDERINGEXTERNAL, (char **)&(*fact)->preferredordering[MAT_FACTOR_ICC]));
10123ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1013db4efbfdSBarry Smith }
1014db4efbfdSBarry Smith 
1015d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatSOR_SeqDense(Mat A, Vec bb, PetscReal omega, MatSORType flag, PetscReal shift, PetscInt its, PetscInt lits, Vec xx)
1016d71ae5a4SJacob Faibussowitsch {
1017c0bbcb79SLois Curfman McInnes   Mat_SeqDense      *mat = (Mat_SeqDense *)A->data;
1018d9ca1df4SBarry Smith   PetscScalar       *x, *v = mat->v, zero = 0.0, xt;
1019d9ca1df4SBarry Smith   const PetscScalar *b;
1020d0f46423SBarry Smith   PetscInt           m = A->rmap->n, i;
102123fff9afSBarry Smith   PetscBLASInt       o = 1, bm = 0;
1022289bc588SBarry Smith 
10233a40ed3dSBarry Smith   PetscFunctionBegin;
102447d993e7Ssuyashtn #if defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
102508401ef6SPierre Jolivet   PetscCheck(A->offloadmask != PETSC_OFFLOAD_GPU, PETSC_COMM_SELF, PETSC_ERR_SUP, "Not implemented");
1026ca15aa20SStefano Zampini #endif
1027422a814eSBarry Smith   if (shift == -1) shift = 0.0; /* negative shift indicates do not error on zero diagonal; this code never zeros on zero diagonal */
10289566063dSJacob Faibussowitsch   PetscCall(PetscBLASIntCast(m, &bm));
1029289bc588SBarry Smith   if (flag & SOR_ZERO_INITIAL_GUESS) {
10303bffc371SBarry Smith     /* this is a hack fix, should have another version without the second BLASdotu */
10319566063dSJacob Faibussowitsch     PetscCall(VecSet(xx, zero));
1032289bc588SBarry Smith   }
10339566063dSJacob Faibussowitsch   PetscCall(VecGetArray(xx, &x));
10349566063dSJacob Faibussowitsch   PetscCall(VecGetArrayRead(bb, &b));
1035b965ef7fSBarry Smith   its = its * lits;
103608401ef6SPierre 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);
1037289bc588SBarry Smith   while (its--) {
1038fccaa45eSBarry Smith     if (flag & SOR_FORWARD_SWEEP || flag & SOR_LOCAL_FORWARD_SWEEP) {
1039289bc588SBarry Smith       for (i = 0; i < m; i++) {
1040792fecdfSBarry Smith         PetscCallBLAS("BLASdotu", xt = b[i] - BLASdotu_(&bm, v + i, &bm, x, &o));
1041883424caSPierre Jolivet         x[i] = (1. - omega) * x[i] + (xt + v[i + i * m] * x[i]) * omega / (v[i + i * m] + shift);
1042289bc588SBarry Smith       }
1043289bc588SBarry Smith     }
1044fccaa45eSBarry Smith     if (flag & SOR_BACKWARD_SWEEP || flag & SOR_LOCAL_BACKWARD_SWEEP) {
1045289bc588SBarry Smith       for (i = m - 1; i >= 0; i--) {
1046792fecdfSBarry Smith         PetscCallBLAS("BLASdotu", xt = b[i] - BLASdotu_(&bm, v + i, &bm, x, &o));
1047883424caSPierre Jolivet         x[i] = (1. - omega) * x[i] + (xt + v[i + i * m] * x[i]) * omega / (v[i + i * m] + shift);
1048289bc588SBarry Smith       }
1049289bc588SBarry Smith     }
1050289bc588SBarry Smith   }
10519566063dSJacob Faibussowitsch   PetscCall(VecRestoreArrayRead(bb, &b));
10529566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(xx, &x));
10533ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1054289bc588SBarry Smith }
1055289bc588SBarry Smith 
1056*d016bddeSToby Isaac PETSC_INTERN PetscErrorCode MatMultColumnRangeKernel_SeqDense(Mat A, Vec xx, Vec yy, PetscInt c_start, PetscInt c_end, PetscBool trans, PetscBool herm)
1057d71ae5a4SJacob Faibussowitsch {
1058c0bbcb79SLois Curfman McInnes   Mat_SeqDense      *mat = (Mat_SeqDense *)A->data;
1059d9ca1df4SBarry Smith   PetscScalar       *y, _DOne = 1.0, _DZero = 0.0;
10600805154bSBarry Smith   PetscBLASInt       m, n, _One             = 1;
1061d9ca1df4SBarry Smith   const PetscScalar *v = mat->v, *x;
10623a40ed3dSBarry Smith 
10633a40ed3dSBarry Smith   PetscFunctionBegin;
10649566063dSJacob Faibussowitsch   PetscCall(PetscBLASIntCast(A->rmap->n, &m));
10650be0d8bdSHansol Suh   PetscCall(PetscBLASIntCast(c_end - c_start, &n));
10669566063dSJacob Faibussowitsch   PetscCall(VecGetArrayRead(xx, &x));
10679566063dSJacob Faibussowitsch   PetscCall(VecGetArrayWrite(yy, &y));
10680be0d8bdSHansol Suh   if (!m || !n) {
10695ac36cfcSBarry Smith     PetscBLASInt i;
1070459e8d23SBlanca Mellado Pinto     if (trans)
1071459e8d23SBlanca Mellado Pinto       for (i = 0; i < n; i++) y[i] = 0.0;
1072459e8d23SBlanca Mellado Pinto     else
10735ac36cfcSBarry Smith       for (i = 0; i < m; i++) y[i] = 0.0;
10745ac36cfcSBarry Smith   } else {
1075459e8d23SBlanca Mellado Pinto     if (trans) {
10760be0d8bdSHansol Suh       if (herm) PetscCallBLAS("BLASgemv", BLASgemv_("C", &m, &n, &_DOne, v + c_start * mat->lda, &mat->lda, x, &_One, &_DZero, y + c_start, &_One));
10770be0d8bdSHansol Suh       else PetscCallBLAS("BLASgemv", BLASgemv_("T", &m, &n, &_DOne, v + c_start * mat->lda, &mat->lda, x, &_One, &_DZero, y + c_start, &_One));
1078459e8d23SBlanca Mellado Pinto     } else {
10790be0d8bdSHansol Suh       PetscCallBLAS("BLASgemv", BLASgemv_("N", &m, &n, &_DOne, v + c_start * mat->lda, &mat->lda, x + c_start, &_One, &_DZero, y, &_One));
1080459e8d23SBlanca Mellado Pinto     }
10810be0d8bdSHansol Suh     PetscCall(PetscLogFlops(2.0 * m * n - n));
10825ac36cfcSBarry Smith   }
10839566063dSJacob Faibussowitsch   PetscCall(VecRestoreArrayRead(xx, &x));
10849566063dSJacob Faibussowitsch   PetscCall(VecRestoreArrayWrite(yy, &y));
10853ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1086289bc588SBarry Smith }
10876ee01492SSatish Balay 
10880be0d8bdSHansol Suh PetscErrorCode MatMultHermitianTransposeColumnRange_SeqDense(Mat A, Vec xx, Vec yy, PetscInt c_start, PetscInt c_end)
10890be0d8bdSHansol Suh {
10900be0d8bdSHansol Suh   PetscFunctionBegin;
10910be0d8bdSHansol Suh   PetscCall(MatMultColumnRangeKernel_SeqDense(A, xx, yy, c_start, c_end, PETSC_TRUE, PETSC_TRUE));
10920be0d8bdSHansol Suh   PetscFunctionReturn(PETSC_SUCCESS);
10930be0d8bdSHansol Suh }
10940be0d8bdSHansol Suh 
1095459e8d23SBlanca Mellado Pinto PetscErrorCode MatMult_SeqDense(Mat A, Vec xx, Vec yy)
1096459e8d23SBlanca Mellado Pinto {
1097459e8d23SBlanca Mellado Pinto   PetscFunctionBegin;
10980be0d8bdSHansol Suh   PetscCall(MatMultColumnRangeKernel_SeqDense(A, xx, yy, 0, A->cmap->n, PETSC_FALSE, PETSC_FALSE));
1099459e8d23SBlanca Mellado Pinto   PetscFunctionReturn(PETSC_SUCCESS);
1100459e8d23SBlanca Mellado Pinto }
1101459e8d23SBlanca Mellado Pinto 
1102459e8d23SBlanca Mellado Pinto PetscErrorCode MatMultTranspose_SeqDense(Mat A, Vec xx, Vec yy)
1103459e8d23SBlanca Mellado Pinto {
1104459e8d23SBlanca Mellado Pinto   PetscFunctionBegin;
11050be0d8bdSHansol Suh   PetscCall(MatMultColumnRangeKernel_SeqDense(A, xx, yy, 0, A->cmap->n, PETSC_TRUE, PETSC_FALSE));
1106459e8d23SBlanca Mellado Pinto   PetscFunctionReturn(PETSC_SUCCESS);
1107459e8d23SBlanca Mellado Pinto }
1108459e8d23SBlanca Mellado Pinto 
1109459e8d23SBlanca Mellado Pinto PetscErrorCode MatMultHermitianTranspose_SeqDense(Mat A, Vec xx, Vec yy)
1110459e8d23SBlanca Mellado Pinto {
1111459e8d23SBlanca Mellado Pinto   PetscFunctionBegin;
11120be0d8bdSHansol Suh   PetscCall(MatMultColumnRangeKernel_SeqDense(A, xx, yy, 0, A->cmap->n, PETSC_TRUE, PETSC_TRUE));
1113459e8d23SBlanca Mellado Pinto   PetscFunctionReturn(PETSC_SUCCESS);
1114459e8d23SBlanca Mellado Pinto }
1115459e8d23SBlanca Mellado Pinto 
1116*d016bddeSToby Isaac PETSC_INTERN PetscErrorCode MatMultAddColumnRangeKernel_SeqDense(Mat A, Vec xx, Vec zz, Vec yy, PetscInt c_start, PetscInt c_end, PetscBool trans, PetscBool herm)
1117d71ae5a4SJacob Faibussowitsch {
1118c0bbcb79SLois Curfman McInnes   Mat_SeqDense      *mat = (Mat_SeqDense *)A->data;
1119d9ca1df4SBarry Smith   const PetscScalar *v   = mat->v, *x;
1120d9ca1df4SBarry Smith   PetscScalar       *y, _DOne = 1.0;
11210805154bSBarry Smith   PetscBLASInt       m, n, _One = 1;
11223a40ed3dSBarry Smith 
11233a40ed3dSBarry Smith   PetscFunctionBegin;
11249566063dSJacob Faibussowitsch   PetscCall(PetscBLASIntCast(A->rmap->n, &m));
11250be0d8bdSHansol Suh   PetscCall(PetscBLASIntCast(c_end - c_start, &n));
11269566063dSJacob Faibussowitsch   PetscCall(VecCopy(zz, yy));
11270be0d8bdSHansol Suh   if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS);
11289566063dSJacob Faibussowitsch   PetscCall(VecGetArray(yy, &y));
1129459e8d23SBlanca Mellado Pinto   PetscCall(VecGetArrayRead(xx, &x));
1130459e8d23SBlanca Mellado Pinto   if (trans) {
11310be0d8bdSHansol Suh     if (herm) PetscCallBLAS("BLASgemv", BLASgemv_("C", &m, &n, &_DOne, v + c_start * mat->lda, &mat->lda, x, &_One, &_DOne, y + c_start, &_One));
11320be0d8bdSHansol Suh     else PetscCallBLAS("BLASgemv", BLASgemv_("T", &m, &n, &_DOne, v + c_start * mat->lda, &mat->lda, x, &_One, &_DOne, y + c_start, &_One));
1133459e8d23SBlanca Mellado Pinto   } else {
11340be0d8bdSHansol Suh     PetscCallBLAS("BLASgemv", BLASgemv_("N", &m, &n, &_DOne, v + c_start * mat->lda, &mat->lda, x + c_start, &_One, &_DOne, y, &_One));
1135459e8d23SBlanca Mellado Pinto   }
11369566063dSJacob Faibussowitsch   PetscCall(VecRestoreArrayRead(xx, &x));
11379566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(yy, &y));
11380be0d8bdSHansol Suh   PetscCall(PetscLogFlops(2.0 * m * n));
11390be0d8bdSHansol Suh   PetscFunctionReturn(PETSC_SUCCESS);
11400be0d8bdSHansol Suh }
11410be0d8bdSHansol Suh 
1142*d016bddeSToby Isaac PetscErrorCode MatMultColumnRange_SeqDense(Mat A, Vec xx, Vec yy, PetscInt c_start, PetscInt c_end)
1143*d016bddeSToby Isaac {
1144*d016bddeSToby Isaac   PetscFunctionBegin;
1145*d016bddeSToby Isaac   PetscCall(MatMultColumnRangeKernel_SeqDense(A, xx, yy, c_start, c_end, PETSC_FALSE, PETSC_FALSE));
1146*d016bddeSToby Isaac   PetscFunctionReturn(PETSC_SUCCESS);
1147*d016bddeSToby Isaac }
1148*d016bddeSToby Isaac 
11490be0d8bdSHansol Suh PetscErrorCode MatMultAddColumnRange_SeqDense(Mat A, Vec xx, Vec zz, Vec yy, PetscInt c_start, PetscInt c_end)
11500be0d8bdSHansol Suh {
11510be0d8bdSHansol Suh   PetscFunctionBegin;
11520be0d8bdSHansol Suh   PetscCall(MatMultAddColumnRangeKernel_SeqDense(A, xx, zz, yy, c_start, c_end, PETSC_FALSE, PETSC_FALSE));
11530be0d8bdSHansol Suh   PetscFunctionReturn(PETSC_SUCCESS);
11540be0d8bdSHansol Suh }
11550be0d8bdSHansol Suh 
11560be0d8bdSHansol Suh PetscErrorCode MatMultHermitianTransposeAddColumnRange_SeqDense(Mat A, Vec xx, Vec zz, Vec yy, PetscInt c_start, PetscInt c_end)
11570be0d8bdSHansol Suh {
11580be0d8bdSHansol Suh   PetscFunctionBegin;
11590be0d8bdSHansol Suh   PetscMPIInt rank;
11600be0d8bdSHansol Suh   PetscCallMPI(MPI_Comm_rank(MPI_COMM_WORLD, &rank));
11610be0d8bdSHansol Suh   PetscCall(MatMultAddColumnRangeKernel_SeqDense(A, xx, zz, yy, c_start, c_end, PETSC_TRUE, PETSC_TRUE));
11623ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1163289bc588SBarry Smith }
11646ee01492SSatish Balay 
1165459e8d23SBlanca Mellado Pinto PetscErrorCode MatMultAdd_SeqDense(Mat A, Vec xx, Vec zz, Vec yy)
1166459e8d23SBlanca Mellado Pinto {
1167459e8d23SBlanca Mellado Pinto   PetscFunctionBegin;
11680be0d8bdSHansol Suh   PetscCall(MatMultAddColumnRangeKernel_SeqDense(A, xx, zz, yy, 0, A->cmap->n, PETSC_FALSE, PETSC_FALSE));
1169459e8d23SBlanca Mellado Pinto   PetscFunctionReturn(PETSC_SUCCESS);
1170459e8d23SBlanca Mellado Pinto }
1171459e8d23SBlanca Mellado Pinto 
1172d71ae5a4SJacob Faibussowitsch PetscErrorCode MatMultTransposeAdd_SeqDense(Mat A, Vec xx, Vec zz, Vec yy)
1173d71ae5a4SJacob Faibussowitsch {
11743a40ed3dSBarry Smith   PetscFunctionBegin;
11750be0d8bdSHansol Suh   PetscCall(MatMultAddColumnRangeKernel_SeqDense(A, xx, zz, yy, 0, A->cmap->n, PETSC_TRUE, PETSC_FALSE));
1176459e8d23SBlanca Mellado Pinto   PetscFunctionReturn(PETSC_SUCCESS);
1177459e8d23SBlanca Mellado Pinto }
1178459e8d23SBlanca Mellado Pinto 
1179459e8d23SBlanca Mellado Pinto PetscErrorCode MatMultHermitianTransposeAdd_SeqDense(Mat A, Vec xx, Vec zz, Vec yy)
1180459e8d23SBlanca Mellado Pinto {
1181459e8d23SBlanca Mellado Pinto   PetscFunctionBegin;
11820be0d8bdSHansol Suh   PetscCall(MatMultAddColumnRangeKernel_SeqDense(A, xx, zz, yy, 0, A->cmap->n, PETSC_TRUE, PETSC_TRUE));
11833ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1184289bc588SBarry Smith }
1185289bc588SBarry Smith 
1186d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatGetRow_SeqDense(Mat A, PetscInt row, PetscInt *ncols, PetscInt **cols, PetscScalar **vals)
1187d71ae5a4SJacob Faibussowitsch {
1188c0bbcb79SLois Curfman McInnes   Mat_SeqDense *mat = (Mat_SeqDense *)A->data;
118913f74950SBarry Smith   PetscInt      i;
119067e560aaSBarry Smith 
11913a40ed3dSBarry Smith   PetscFunctionBegin;
1192c3e1b152SPierre Jolivet   if (ncols) *ncols = A->cmap->n;
1193289bc588SBarry Smith   if (cols) {
11949566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(A->cmap->n, cols));
1195d0f46423SBarry Smith     for (i = 0; i < A->cmap->n; i++) (*cols)[i] = i;
1196289bc588SBarry Smith   }
1197289bc588SBarry Smith   if (vals) {
1198ca15aa20SStefano Zampini     const PetscScalar *v;
1199ca15aa20SStefano Zampini 
12009566063dSJacob Faibussowitsch     PetscCall(MatDenseGetArrayRead(A, &v));
12019566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(A->cmap->n, vals));
1202ca15aa20SStefano Zampini     v += row;
12039371c9d4SSatish Balay     for (i = 0; i < A->cmap->n; i++) {
12049371c9d4SSatish Balay       (*vals)[i] = *v;
12059371c9d4SSatish Balay       v += mat->lda;
12069371c9d4SSatish Balay     }
12079566063dSJacob Faibussowitsch     PetscCall(MatDenseRestoreArrayRead(A, &v));
1208289bc588SBarry Smith   }
12093ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1210289bc588SBarry Smith }
12116ee01492SSatish Balay 
1212d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatRestoreRow_SeqDense(Mat A, PetscInt row, PetscInt *ncols, PetscInt **cols, PetscScalar **vals)
1213d71ae5a4SJacob Faibussowitsch {
1214606d414cSSatish Balay   PetscFunctionBegin;
12159566063dSJacob Faibussowitsch   if (cols) PetscCall(PetscFree(*cols));
12169566063dSJacob Faibussowitsch   if (vals) PetscCall(PetscFree(*vals));
12173ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1218289bc588SBarry Smith }
12192ef1f0ffSBarry Smith 
1220d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatSetValues_SeqDense(Mat A, PetscInt m, const PetscInt indexm[], PetscInt n, const PetscInt indexn[], const PetscScalar v[], InsertMode addv)
1221d71ae5a4SJacob Faibussowitsch {
1222c0bbcb79SLois Curfman McInnes   Mat_SeqDense *mat = (Mat_SeqDense *)A->data;
1223ca15aa20SStefano Zampini   PetscScalar  *av;
122413f74950SBarry Smith   PetscInt      i, j, idx = 0;
122547d993e7Ssuyashtn #if defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
1226c70f7ee4SJunchao Zhang   PetscOffloadMask oldf;
1227ca15aa20SStefano Zampini #endif
1228d6dfbf8fSBarry Smith 
12293a40ed3dSBarry Smith   PetscFunctionBegin;
12309566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArray(A, &av));
1231289bc588SBarry Smith   if (!mat->roworiented) {
1232dbb450caSBarry Smith     if (addv == INSERT_VALUES) {
1233289bc588SBarry Smith       for (j = 0; j < n; j++) {
12349371c9d4SSatish Balay         if (indexn[j] < 0) {
12359371c9d4SSatish Balay           idx += m;
12369371c9d4SSatish Balay           continue;
12379371c9d4SSatish Balay         }
12386bdcaf15SBarry 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);
1239289bc588SBarry Smith         for (i = 0; i < m; i++) {
12409371c9d4SSatish Balay           if (indexm[i] < 0) {
12419371c9d4SSatish Balay             idx++;
12429371c9d4SSatish Balay             continue;
12439371c9d4SSatish Balay           }
12446bdcaf15SBarry 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);
12458c4a67a0SStefano Zampini           av[indexn[j] * mat->lda + indexm[i]] = v ? v[idx++] : (idx++, 0.0);
1246289bc588SBarry Smith         }
1247289bc588SBarry Smith       }
12480be0d8bdSHansol Suh     } else {
1249289bc588SBarry Smith       for (j = 0; j < n; j++) {
12509371c9d4SSatish Balay         if (indexn[j] < 0) {
12519371c9d4SSatish Balay           idx += m;
12529371c9d4SSatish Balay           continue;
12539371c9d4SSatish Balay         }
12546bdcaf15SBarry 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);
1255289bc588SBarry Smith         for (i = 0; i < m; i++) {
12569371c9d4SSatish Balay           if (indexm[i] < 0) {
12579371c9d4SSatish Balay             idx++;
12589371c9d4SSatish Balay             continue;
12599371c9d4SSatish Balay           }
12606bdcaf15SBarry 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);
12618c4a67a0SStefano Zampini           av[indexn[j] * mat->lda + indexm[i]] += v ? v[idx++] : (idx++, 0.0);
1262289bc588SBarry Smith         }
1263289bc588SBarry Smith       }
1264289bc588SBarry Smith     }
12653a40ed3dSBarry Smith   } else {
1266dbb450caSBarry Smith     if (addv == INSERT_VALUES) {
1267e8d4e0b9SBarry Smith       for (i = 0; i < m; i++) {
12689371c9d4SSatish Balay         if (indexm[i] < 0) {
12699371c9d4SSatish Balay           idx += n;
12709371c9d4SSatish Balay           continue;
12719371c9d4SSatish Balay         }
12726bdcaf15SBarry 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);
1273e8d4e0b9SBarry Smith         for (j = 0; j < n; j++) {
12749371c9d4SSatish Balay           if (indexn[j] < 0) {
12759371c9d4SSatish Balay             idx++;
12769371c9d4SSatish Balay             continue;
12779371c9d4SSatish Balay           }
12786bdcaf15SBarry 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);
12798c4a67a0SStefano Zampini           av[indexn[j] * mat->lda + indexm[i]] = v ? v[idx++] : (idx++, 0.0);
1280e8d4e0b9SBarry Smith         }
1281e8d4e0b9SBarry Smith       }
12820be0d8bdSHansol Suh     } else {
1283289bc588SBarry Smith       for (i = 0; i < m; i++) {
12849371c9d4SSatish Balay         if (indexm[i] < 0) {
12859371c9d4SSatish Balay           idx += n;
12869371c9d4SSatish Balay           continue;
12879371c9d4SSatish Balay         }
12886bdcaf15SBarry 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);
1289289bc588SBarry Smith         for (j = 0; j < n; j++) {
12909371c9d4SSatish Balay           if (indexn[j] < 0) {
12919371c9d4SSatish Balay             idx++;
12929371c9d4SSatish Balay             continue;
12939371c9d4SSatish Balay           }
12946bdcaf15SBarry 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);
12958c4a67a0SStefano Zampini           av[indexn[j] * mat->lda + indexm[i]] += v ? v[idx++] : (idx++, 0.0);
1296289bc588SBarry Smith         }
1297289bc588SBarry Smith       }
1298289bc588SBarry Smith     }
1299e8d4e0b9SBarry Smith   }
1300ca15aa20SStefano Zampini   /* hack to prevent unneeded copy to the GPU while returning the array */
130147d993e7Ssuyashtn #if defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
1302c70f7ee4SJunchao Zhang   oldf           = A->offloadmask;
1303c70f7ee4SJunchao Zhang   A->offloadmask = PETSC_OFFLOAD_GPU;
1304ca15aa20SStefano Zampini #endif
13059566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArray(A, &av));
130647d993e7Ssuyashtn #if defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
1307c70f7ee4SJunchao Zhang   A->offloadmask = (oldf == PETSC_OFFLOAD_UNALLOCATED ? PETSC_OFFLOAD_UNALLOCATED : PETSC_OFFLOAD_CPU);
1308ca15aa20SStefano Zampini #endif
13093ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1310289bc588SBarry Smith }
1311e8d4e0b9SBarry Smith 
1312d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatGetValues_SeqDense(Mat A, PetscInt m, const PetscInt indexm[], PetscInt n, const PetscInt indexn[], PetscScalar v[])
1313d71ae5a4SJacob Faibussowitsch {
1314ae80bb75SLois Curfman McInnes   Mat_SeqDense      *mat = (Mat_SeqDense *)A->data;
1315ca15aa20SStefano Zampini   const PetscScalar *vv;
131613f74950SBarry Smith   PetscInt           i, j;
1317ae80bb75SLois Curfman McInnes 
13183a40ed3dSBarry Smith   PetscFunctionBegin;
13199566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArrayRead(A, &vv));
1320ae80bb75SLois Curfman McInnes   /* row-oriented output */
1321ae80bb75SLois Curfman McInnes   for (i = 0; i < m; i++) {
13229371c9d4SSatish Balay     if (indexm[i] < 0) {
13239371c9d4SSatish Balay       v += n;
13249371c9d4SSatish Balay       continue;
13259371c9d4SSatish Balay     }
132608401ef6SPierre 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);
1327ae80bb75SLois Curfman McInnes     for (j = 0; j < n; j++) {
13289371c9d4SSatish Balay       if (indexn[j] < 0) {
13299371c9d4SSatish Balay         v++;
13309371c9d4SSatish Balay         continue;
13319371c9d4SSatish Balay       }
133208401ef6SPierre 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);
1333ca15aa20SStefano Zampini       *v++ = vv[indexn[j] * mat->lda + indexm[i]];
1334ae80bb75SLois Curfman McInnes     }
1335ae80bb75SLois Curfman McInnes   }
13369566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArrayRead(A, &vv));
13373ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1338ae80bb75SLois Curfman McInnes }
1339ae80bb75SLois Curfman McInnes 
1340d71ae5a4SJacob Faibussowitsch PetscErrorCode MatView_Dense_Binary(Mat mat, PetscViewer viewer)
1341d71ae5a4SJacob Faibussowitsch {
13428491ab44SLisandro Dalcin   PetscBool          skipHeader;
13438491ab44SLisandro Dalcin   PetscViewerFormat  format;
13443e1d7bceSPierre Jolivet   PetscInt           header[4], M, N, m, lda, i, j;
13453e1d7bceSPierre Jolivet   PetscCount         k;
13468491ab44SLisandro Dalcin   const PetscScalar *v;
13478491ab44SLisandro Dalcin   PetscScalar       *vwork;
1348aabbc4fbSShri Abhyankar 
1349aabbc4fbSShri Abhyankar   PetscFunctionBegin;
13509566063dSJacob Faibussowitsch   PetscCall(PetscViewerSetUp(viewer));
13519566063dSJacob Faibussowitsch   PetscCall(PetscViewerBinaryGetSkipHeader(viewer, &skipHeader));
13529566063dSJacob Faibussowitsch   PetscCall(PetscViewerGetFormat(viewer, &format));
13538491ab44SLisandro Dalcin   if (skipHeader) format = PETSC_VIEWER_NATIVE;
1354aabbc4fbSShri Abhyankar 
13559566063dSJacob Faibussowitsch   PetscCall(MatGetSize(mat, &M, &N));
13568491ab44SLisandro Dalcin 
13578491ab44SLisandro Dalcin   /* write matrix header */
13589371c9d4SSatish Balay   header[0] = MAT_FILE_CLASSID;
13599371c9d4SSatish Balay   header[1] = M;
13609371c9d4SSatish Balay   header[2] = N;
13618491ab44SLisandro Dalcin   header[3] = (format == PETSC_VIEWER_NATIVE) ? MATRIX_BINARY_FORMAT_DENSE : M * N;
13629566063dSJacob Faibussowitsch   if (!skipHeader) PetscCall(PetscViewerBinaryWrite(viewer, header, 4, PETSC_INT));
13638491ab44SLisandro Dalcin 
13649566063dSJacob Faibussowitsch   PetscCall(MatGetLocalSize(mat, &m, NULL));
13658491ab44SLisandro Dalcin   if (format != PETSC_VIEWER_NATIVE) {
13668491ab44SLisandro Dalcin     PetscInt nnz = m * N, *iwork;
13678491ab44SLisandro Dalcin     /* store row lengths for each row */
13689566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(nnz, &iwork));
13698491ab44SLisandro Dalcin     for (i = 0; i < m; i++) iwork[i] = N;
13709566063dSJacob Faibussowitsch     PetscCall(PetscViewerBinaryWriteAll(viewer, iwork, m, PETSC_DETERMINE, PETSC_DETERMINE, PETSC_INT));
13718491ab44SLisandro Dalcin     /* store column indices (zero start index) */
13728491ab44SLisandro Dalcin     for (k = 0, i = 0; i < m; i++)
13739371c9d4SSatish Balay       for (j = 0; j < N; j++, k++) iwork[k] = j;
13749566063dSJacob Faibussowitsch     PetscCall(PetscViewerBinaryWriteAll(viewer, iwork, nnz, PETSC_DETERMINE, PETSC_DETERMINE, PETSC_INT));
13759566063dSJacob Faibussowitsch     PetscCall(PetscFree(iwork));
13768491ab44SLisandro Dalcin   }
13778491ab44SLisandro Dalcin   /* store matrix values as a dense matrix in row major order */
13789566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(m * N, &vwork));
13799566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArrayRead(mat, &v));
13809566063dSJacob Faibussowitsch   PetscCall(MatDenseGetLDA(mat, &lda));
13818491ab44SLisandro Dalcin   for (k = 0, i = 0; i < m; i++)
13823e1d7bceSPierre Jolivet     for (j = 0; j < N; j++, k++) vwork[k] = v[i + (size_t)lda * j];
13839566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArrayRead(mat, &v));
13849566063dSJacob Faibussowitsch   PetscCall(PetscViewerBinaryWriteAll(viewer, vwork, m * N, PETSC_DETERMINE, PETSC_DETERMINE, PETSC_SCALAR));
13859566063dSJacob Faibussowitsch   PetscCall(PetscFree(vwork));
13863ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
13878491ab44SLisandro Dalcin }
13888491ab44SLisandro Dalcin 
1389d71ae5a4SJacob Faibussowitsch PetscErrorCode MatLoad_Dense_Binary(Mat mat, PetscViewer viewer)
1390d71ae5a4SJacob Faibussowitsch {
13918491ab44SLisandro Dalcin   PetscBool    skipHeader;
13928491ab44SLisandro Dalcin   PetscInt     header[4], M, N, m, nz, lda, i, j, k;
13938491ab44SLisandro Dalcin   PetscInt     rows, cols;
13948491ab44SLisandro Dalcin   PetscScalar *v, *vwork;
13958491ab44SLisandro Dalcin 
13968491ab44SLisandro Dalcin   PetscFunctionBegin;
13979566063dSJacob Faibussowitsch   PetscCall(PetscViewerSetUp(viewer));
13989566063dSJacob Faibussowitsch   PetscCall(PetscViewerBinaryGetSkipHeader(viewer, &skipHeader));
13998491ab44SLisandro Dalcin 
14008491ab44SLisandro Dalcin   if (!skipHeader) {
14019566063dSJacob Faibussowitsch     PetscCall(PetscViewerBinaryRead(viewer, header, 4, NULL, PETSC_INT));
140208401ef6SPierre Jolivet     PetscCheck(header[0] == MAT_FILE_CLASSID, PetscObjectComm((PetscObject)viewer), PETSC_ERR_FILE_UNEXPECTED, "Not a matrix object in file");
14039371c9d4SSatish Balay     M = header[1];
14049371c9d4SSatish Balay     N = header[2];
140508401ef6SPierre Jolivet     PetscCheck(M >= 0, PetscObjectComm((PetscObject)viewer), PETSC_ERR_FILE_UNEXPECTED, "Matrix row size (%" PetscInt_FMT ") in file is negative", M);
140608401ef6SPierre Jolivet     PetscCheck(N >= 0, PetscObjectComm((PetscObject)viewer), PETSC_ERR_FILE_UNEXPECTED, "Matrix column size (%" PetscInt_FMT ") in file is negative", N);
14078491ab44SLisandro Dalcin     nz = header[3];
1408aed4548fSBarry Smith     PetscCheck(nz == MATRIX_BINARY_FORMAT_DENSE || nz >= 0, PetscObjectComm((PetscObject)viewer), PETSC_ERR_FILE_UNEXPECTED, "Unknown matrix format %" PetscInt_FMT " in file", nz);
1409aabbc4fbSShri Abhyankar   } else {
14109566063dSJacob Faibussowitsch     PetscCall(MatGetSize(mat, &M, &N));
1411aed4548fSBarry 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");
14128491ab44SLisandro Dalcin     nz = MATRIX_BINARY_FORMAT_DENSE;
1413e6324fbbSBarry Smith   }
1414aabbc4fbSShri Abhyankar 
14158491ab44SLisandro Dalcin   /* setup global sizes if not set */
14168491ab44SLisandro Dalcin   if (mat->rmap->N < 0) mat->rmap->N = M;
14178491ab44SLisandro Dalcin   if (mat->cmap->N < 0) mat->cmap->N = N;
14189566063dSJacob Faibussowitsch   PetscCall(MatSetUp(mat));
14198491ab44SLisandro Dalcin   /* check if global sizes are correct */
14209566063dSJacob Faibussowitsch   PetscCall(MatGetSize(mat, &rows, &cols));
1421aed4548fSBarry 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);
1422aabbc4fbSShri Abhyankar 
14239566063dSJacob Faibussowitsch   PetscCall(MatGetSize(mat, NULL, &N));
14249566063dSJacob Faibussowitsch   PetscCall(MatGetLocalSize(mat, &m, NULL));
14259566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArray(mat, &v));
14269566063dSJacob Faibussowitsch   PetscCall(MatDenseGetLDA(mat, &lda));
14278491ab44SLisandro Dalcin   if (nz == MATRIX_BINARY_FORMAT_DENSE) { /* matrix in file is dense format */
14283e1d7bceSPierre Jolivet     PetscCount nnz = (size_t)m * N;
14298491ab44SLisandro Dalcin     /* read in matrix values */
14309566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(nnz, &vwork));
14319566063dSJacob Faibussowitsch     PetscCall(PetscViewerBinaryReadAll(viewer, vwork, nnz, PETSC_DETERMINE, PETSC_DETERMINE, PETSC_SCALAR));
14328491ab44SLisandro Dalcin     /* store values in column major order */
14338491ab44SLisandro Dalcin     for (j = 0; j < N; j++)
14343e1d7bceSPierre Jolivet       for (i = 0; i < m; i++) v[i + (size_t)lda * j] = vwork[(size_t)i * N + j];
14359566063dSJacob Faibussowitsch     PetscCall(PetscFree(vwork));
14368491ab44SLisandro Dalcin   } else { /* matrix in file is sparse format */
14378491ab44SLisandro Dalcin     PetscInt nnz = 0, *rlens, *icols;
14388491ab44SLisandro Dalcin     /* read in row lengths */
14399566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(m, &rlens));
14409566063dSJacob Faibussowitsch     PetscCall(PetscViewerBinaryReadAll(viewer, rlens, m, PETSC_DETERMINE, PETSC_DETERMINE, PETSC_INT));
14418491ab44SLisandro Dalcin     for (i = 0; i < m; i++) nnz += rlens[i];
14428491ab44SLisandro Dalcin     /* read in column indices and values */
14439566063dSJacob Faibussowitsch     PetscCall(PetscMalloc2(nnz, &icols, nnz, &vwork));
14449566063dSJacob Faibussowitsch     PetscCall(PetscViewerBinaryReadAll(viewer, icols, nnz, PETSC_DETERMINE, PETSC_DETERMINE, PETSC_INT));
14459566063dSJacob Faibussowitsch     PetscCall(PetscViewerBinaryReadAll(viewer, vwork, nnz, PETSC_DETERMINE, PETSC_DETERMINE, PETSC_SCALAR));
14468491ab44SLisandro Dalcin     /* store values in column major order */
14478491ab44SLisandro Dalcin     for (k = 0, i = 0; i < m; i++)
14489371c9d4SSatish Balay       for (j = 0; j < rlens[i]; j++, k++) v[i + lda * icols[k]] = vwork[k];
14499566063dSJacob Faibussowitsch     PetscCall(PetscFree(rlens));
14509566063dSJacob Faibussowitsch     PetscCall(PetscFree2(icols, vwork));
1451aabbc4fbSShri Abhyankar   }
14529566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArray(mat, &v));
14539566063dSJacob Faibussowitsch   PetscCall(MatAssemblyBegin(mat, MAT_FINAL_ASSEMBLY));
14549566063dSJacob Faibussowitsch   PetscCall(MatAssemblyEnd(mat, MAT_FINAL_ASSEMBLY));
14553ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1456aabbc4fbSShri Abhyankar }
1457aabbc4fbSShri Abhyankar 
145866976f2fSJacob Faibussowitsch static PetscErrorCode MatLoad_SeqDense(Mat newMat, PetscViewer viewer)
1459d71ae5a4SJacob Faibussowitsch {
1460eb91f321SVaclav Hapla   PetscBool isbinary, ishdf5;
1461eb91f321SVaclav Hapla 
1462eb91f321SVaclav Hapla   PetscFunctionBegin;
1463eb91f321SVaclav Hapla   PetscValidHeaderSpecific(newMat, MAT_CLASSID, 1);
1464eb91f321SVaclav Hapla   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
1465eb91f321SVaclav Hapla   /* force binary viewer to load .info file if it has not yet done so */
14669566063dSJacob Faibussowitsch   PetscCall(PetscViewerSetUp(viewer));
14679566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERBINARY, &isbinary));
14689566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5));
1469eb91f321SVaclav Hapla   if (isbinary) {
14709566063dSJacob Faibussowitsch     PetscCall(MatLoad_Dense_Binary(newMat, viewer));
1471eb91f321SVaclav Hapla   } else if (ishdf5) {
1472eb91f321SVaclav Hapla #if defined(PETSC_HAVE_HDF5)
14739566063dSJacob Faibussowitsch     PetscCall(MatLoad_Dense_HDF5(newMat, viewer));
1474eb91f321SVaclav Hapla #else
1475eb91f321SVaclav Hapla     SETERRQ(PetscObjectComm((PetscObject)newMat), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5");
1476eb91f321SVaclav Hapla #endif
1477eb91f321SVaclav Hapla   } else {
147898921bdaSJacob 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);
1479eb91f321SVaclav Hapla   }
14803ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1481eb91f321SVaclav Hapla }
1482eb91f321SVaclav Hapla 
1483d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatView_SeqDense_ASCII(Mat A, PetscViewer viewer)
1484d71ae5a4SJacob Faibussowitsch {
1485932b0c3eSLois Curfman McInnes   Mat_SeqDense     *a = (Mat_SeqDense *)A->data;
148613f74950SBarry Smith   PetscInt          i, j;
14872dcb1b2aSMatthew Knepley   const char       *name;
1488ca15aa20SStefano Zampini   PetscScalar      *v, *av;
1489f3ef73ceSBarry Smith   PetscViewerFormat format;
14905f481a85SSatish Balay #if defined(PETSC_USE_COMPLEX)
1491ace3abfcSBarry Smith   PetscBool allreal = PETSC_TRUE;
14925f481a85SSatish Balay #endif
1493932b0c3eSLois Curfman McInnes 
14943a40ed3dSBarry Smith   PetscFunctionBegin;
14959566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArrayRead(A, (const PetscScalar **)&av));
14969566063dSJacob Faibussowitsch   PetscCall(PetscViewerGetFormat(viewer, &format));
1497456192e2SBarry Smith   if (format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL) {
14983ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS); /* do nothing for now */
1499fb9695e5SSatish Balay   } else if (format == PETSC_VIEWER_ASCII_COMMON) {
15009566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIUseTabs(viewer, PETSC_FALSE));
1501d0f46423SBarry Smith     for (i = 0; i < A->rmap->n; i++) {
1502ca15aa20SStefano Zampini       v = av + i;
15039566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "row %" PetscInt_FMT ":", i));
1504d0f46423SBarry Smith       for (j = 0; j < A->cmap->n; j++) {
1505aa482453SBarry Smith #if defined(PETSC_USE_COMPLEX)
1506329f5518SBarry Smith         if (PetscRealPart(*v) != 0.0 && PetscImaginaryPart(*v) != 0.0) {
15079566063dSJacob Faibussowitsch           PetscCall(PetscViewerASCIIPrintf(viewer, " (%" PetscInt_FMT ", %g + %g i) ", j, (double)PetscRealPart(*v), (double)PetscImaginaryPart(*v)));
1508329f5518SBarry Smith         } else if (PetscRealPart(*v)) {
15099566063dSJacob Faibussowitsch           PetscCall(PetscViewerASCIIPrintf(viewer, " (%" PetscInt_FMT ", %g) ", j, (double)PetscRealPart(*v)));
15106831982aSBarry Smith         }
151180cd9d93SLois Curfman McInnes #else
151248a46eb9SPierre Jolivet         if (*v) PetscCall(PetscViewerASCIIPrintf(viewer, " (%" PetscInt_FMT ", %g) ", j, (double)*v));
151380cd9d93SLois Curfman McInnes #endif
15141b807ce4Svictorle         v += a->lda;
151580cd9d93SLois Curfman McInnes       }
15169566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "\n"));
151780cd9d93SLois Curfman McInnes     }
15189566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIUseTabs(viewer, PETSC_TRUE));
15193a40ed3dSBarry Smith   } else {
15209566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIUseTabs(viewer, PETSC_FALSE));
1521aa482453SBarry Smith #if defined(PETSC_USE_COMPLEX)
152247989497SBarry Smith     /* determine if matrix has all real values */
1523bcd8d3a4SJose E. Roman     for (j = 0; j < A->cmap->n; j++) {
1524bcd8d3a4SJose E. Roman       v = av + j * a->lda;
1525bcd8d3a4SJose E. Roman       for (i = 0; i < A->rmap->n; i++) {
15269371c9d4SSatish Balay         if (PetscImaginaryPart(v[i])) {
15279371c9d4SSatish Balay           allreal = PETSC_FALSE;
15289371c9d4SSatish Balay           break;
15299371c9d4SSatish Balay         }
153047989497SBarry Smith       }
1531bcd8d3a4SJose E. Roman     }
153247989497SBarry Smith #endif
1533fb9695e5SSatish Balay     if (format == PETSC_VIEWER_ASCII_MATLAB) {
15349566063dSJacob Faibussowitsch       PetscCall(PetscObjectGetName((PetscObject)A, &name));
15359566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "%% Size = %" PetscInt_FMT " %" PetscInt_FMT " \n", A->rmap->n, A->cmap->n));
15369566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "%s = zeros(%" PetscInt_FMT ",%" PetscInt_FMT ");\n", name, A->rmap->n, A->cmap->n));
15379566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "%s = [\n", name));
1538ffac6cdbSBarry Smith     }
1539ffac6cdbSBarry Smith 
1540d0f46423SBarry Smith     for (i = 0; i < A->rmap->n; i++) {
1541ca15aa20SStefano Zampini       v = av + i;
1542d0f46423SBarry Smith       for (j = 0; j < A->cmap->n; j++) {
1543aa482453SBarry Smith #if defined(PETSC_USE_COMPLEX)
154447989497SBarry Smith         if (allreal) {
15459566063dSJacob Faibussowitsch           PetscCall(PetscViewerASCIIPrintf(viewer, "%18.16e ", (double)PetscRealPart(*v)));
154647989497SBarry Smith         } else {
15479566063dSJacob Faibussowitsch           PetscCall(PetscViewerASCIIPrintf(viewer, "%18.16e + %18.16ei ", (double)PetscRealPart(*v), (double)PetscImaginaryPart(*v)));
154847989497SBarry Smith         }
1549289bc588SBarry Smith #else
15509566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, "%18.16e ", (double)*v));
1551289bc588SBarry Smith #endif
15521b807ce4Svictorle         v += a->lda;
1553289bc588SBarry Smith       }
15549566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "\n"));
1555289bc588SBarry Smith     }
155648a46eb9SPierre Jolivet     if (format == PETSC_VIEWER_ASCII_MATLAB) PetscCall(PetscViewerASCIIPrintf(viewer, "];\n"));
15579566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIUseTabs(viewer, PETSC_TRUE));
1558da3a660dSBarry Smith   }
15599566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArrayRead(A, (const PetscScalar **)&av));
15609566063dSJacob Faibussowitsch   PetscCall(PetscViewerFlush(viewer));
15613ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1562289bc588SBarry Smith }
1563289bc588SBarry Smith 
15649804daf3SBarry Smith #include <petscdraw.h>
1565d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatView_SeqDense_Draw_Zoom(PetscDraw draw, void *Aa)
1566d71ae5a4SJacob Faibussowitsch {
1567f1af5d2fSBarry Smith   Mat                A = (Mat)Aa;
1568383922c3SLisandro Dalcin   PetscInt           m = A->rmap->n, n = A->cmap->n, i, j;
1569383922c3SLisandro Dalcin   int                color = PETSC_DRAW_WHITE;
1570ca15aa20SStefano Zampini   const PetscScalar *v;
1571b0a32e0cSBarry Smith   PetscViewer        viewer;
1572b05fc000SLisandro Dalcin   PetscReal          xl, yl, xr, yr, x_l, x_r, y_l, y_r;
1573f3ef73ceSBarry Smith   PetscViewerFormat  format;
1574f1af5d2fSBarry Smith 
1575f1af5d2fSBarry Smith   PetscFunctionBegin;
15769566063dSJacob Faibussowitsch   PetscCall(PetscObjectQuery((PetscObject)A, "Zoomviewer", (PetscObject *)&viewer));
15779566063dSJacob Faibussowitsch   PetscCall(PetscViewerGetFormat(viewer, &format));
15789566063dSJacob Faibussowitsch   PetscCall(PetscDrawGetCoordinates(draw, &xl, &yl, &xr, &yr));
1579f1af5d2fSBarry Smith 
1580f1af5d2fSBarry Smith   /* Loop over matrix elements drawing boxes */
15819566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArrayRead(A, &v));
1582fb9695e5SSatish Balay   if (format != PETSC_VIEWER_DRAW_CONTOUR) {
1583d0609cedSBarry Smith     PetscDrawCollectiveBegin(draw);
1584f1af5d2fSBarry Smith     /* Blue for negative and Red for positive */
1585f1af5d2fSBarry Smith     for (j = 0; j < n; j++) {
15869371c9d4SSatish Balay       x_l = j;
15879371c9d4SSatish Balay       x_r = x_l + 1.0;
1588f1af5d2fSBarry Smith       for (i = 0; i < m; i++) {
1589f1af5d2fSBarry Smith         y_l = m - i - 1.0;
1590f1af5d2fSBarry Smith         y_r = y_l + 1.0;
1591ca15aa20SStefano Zampini         if (PetscRealPart(v[j * m + i]) > 0.) color = PETSC_DRAW_RED;
1592ca15aa20SStefano Zampini         else if (PetscRealPart(v[j * m + i]) < 0.) color = PETSC_DRAW_BLUE;
1593ca15aa20SStefano Zampini         else continue;
15949566063dSJacob Faibussowitsch         PetscCall(PetscDrawRectangle(draw, x_l, y_l, x_r, y_r, color, color, color, color));
1595f1af5d2fSBarry Smith       }
1596f1af5d2fSBarry Smith     }
1597d0609cedSBarry Smith     PetscDrawCollectiveEnd(draw);
1598f1af5d2fSBarry Smith   } else {
1599f1af5d2fSBarry Smith     /* use contour shading to indicate magnitude of values */
1600f1af5d2fSBarry Smith     /* first determine max of all nonzero values */
1601b05fc000SLisandro Dalcin     PetscReal minv = 0.0, maxv = 0.0;
1602b05fc000SLisandro Dalcin     PetscDraw popup;
1603b05fc000SLisandro Dalcin 
1604f1af5d2fSBarry Smith     for (i = 0; i < m * n; i++) {
1605f1af5d2fSBarry Smith       if (PetscAbsScalar(v[i]) > maxv) maxv = PetscAbsScalar(v[i]);
1606f1af5d2fSBarry Smith     }
1607383922c3SLisandro Dalcin     if (minv >= maxv) maxv = minv + PETSC_SMALL;
16089566063dSJacob Faibussowitsch     PetscCall(PetscDrawGetPopup(draw, &popup));
16099566063dSJacob Faibussowitsch     PetscCall(PetscDrawScalePopup(popup, minv, maxv));
1610383922c3SLisandro Dalcin 
1611d0609cedSBarry Smith     PetscDrawCollectiveBegin(draw);
1612f1af5d2fSBarry Smith     for (j = 0; j < n; j++) {
1613f1af5d2fSBarry Smith       x_l = j;
1614f1af5d2fSBarry Smith       x_r = x_l + 1.0;
1615f1af5d2fSBarry Smith       for (i = 0; i < m; i++) {
1616f1af5d2fSBarry Smith         y_l   = m - i - 1.0;
1617f1af5d2fSBarry Smith         y_r   = y_l + 1.0;
1618b05fc000SLisandro Dalcin         color = PetscDrawRealToColor(PetscAbsScalar(v[j * m + i]), minv, maxv);
16199566063dSJacob Faibussowitsch         PetscCall(PetscDrawRectangle(draw, x_l, y_l, x_r, y_r, color, color, color, color));
1620f1af5d2fSBarry Smith       }
1621f1af5d2fSBarry Smith     }
1622d0609cedSBarry Smith     PetscDrawCollectiveEnd(draw);
1623f1af5d2fSBarry Smith   }
16249566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArrayRead(A, &v));
16253ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1626f1af5d2fSBarry Smith }
1627f1af5d2fSBarry Smith 
1628d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatView_SeqDense_Draw(Mat A, PetscViewer viewer)
1629d71ae5a4SJacob Faibussowitsch {
1630b0a32e0cSBarry Smith   PetscDraw draw;
1631ace3abfcSBarry Smith   PetscBool isnull;
1632329f5518SBarry Smith   PetscReal xr, yr, xl, yl, h, w;
1633f1af5d2fSBarry Smith 
1634f1af5d2fSBarry Smith   PetscFunctionBegin;
16359566063dSJacob Faibussowitsch   PetscCall(PetscViewerDrawGetDraw(viewer, 0, &draw));
16369566063dSJacob Faibussowitsch   PetscCall(PetscDrawIsNull(draw, &isnull));
16373ba16761SJacob Faibussowitsch   if (isnull) PetscFunctionReturn(PETSC_SUCCESS);
1638f1af5d2fSBarry Smith 
16399371c9d4SSatish Balay   xr = A->cmap->n;
16409371c9d4SSatish Balay   yr = A->rmap->n;
16419371c9d4SSatish Balay   h  = yr / 10.0;
16429371c9d4SSatish Balay   w  = xr / 10.0;
16439371c9d4SSatish Balay   xr += w;
16449371c9d4SSatish Balay   yr += h;
16459371c9d4SSatish Balay   xl = -w;
16469371c9d4SSatish Balay   yl = -h;
16479566063dSJacob Faibussowitsch   PetscCall(PetscDrawSetCoordinates(draw, xl, yl, xr, yr));
16489566063dSJacob Faibussowitsch   PetscCall(PetscObjectCompose((PetscObject)A, "Zoomviewer", (PetscObject)viewer));
16499566063dSJacob Faibussowitsch   PetscCall(PetscDrawZoom(draw, MatView_SeqDense_Draw_Zoom, A));
16509566063dSJacob Faibussowitsch   PetscCall(PetscObjectCompose((PetscObject)A, "Zoomviewer", NULL));
16519566063dSJacob Faibussowitsch   PetscCall(PetscDrawSave(draw));
16523ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1653f1af5d2fSBarry Smith }
1654f1af5d2fSBarry Smith 
1655d71ae5a4SJacob Faibussowitsch PetscErrorCode MatView_SeqDense(Mat A, PetscViewer viewer)
1656d71ae5a4SJacob Faibussowitsch {
1657ace3abfcSBarry Smith   PetscBool iascii, isbinary, isdraw;
1658932b0c3eSLois Curfman McInnes 
16593a40ed3dSBarry Smith   PetscFunctionBegin;
16609566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
16619566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERBINARY, &isbinary));
16629566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERDRAW, &isdraw));
16631baa6e33SBarry Smith   if (iascii) PetscCall(MatView_SeqDense_ASCII(A, viewer));
16641baa6e33SBarry Smith   else if (isbinary) PetscCall(MatView_Dense_Binary(A, viewer));
16651baa6e33SBarry Smith   else if (isdraw) PetscCall(MatView_SeqDense_Draw(A, viewer));
16663ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1667932b0c3eSLois Curfman McInnes }
1668289bc588SBarry Smith 
1669d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatDensePlaceArray_SeqDense(Mat A, const PetscScalar *array)
1670d71ae5a4SJacob Faibussowitsch {
1671d3042a70SBarry Smith   Mat_SeqDense *a = (Mat_SeqDense *)A->data;
1672d3042a70SBarry Smith 
1673d3042a70SBarry Smith   PetscFunctionBegin;
167428b400f6SJacob Faibussowitsch   PetscCheck(!a->vecinuse, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Need to call MatDenseRestoreColumnVec() first");
167528b400f6SJacob Faibussowitsch   PetscCheck(!a->matinuse, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Need to call MatDenseRestoreSubMatrix() first");
16766635c364SPierre Jolivet   PetscCheck(!a->unplacedarray, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Need to call MatDenseResetArray() first");
1677d3042a70SBarry Smith   a->unplacedarray       = a->v;
1678d3042a70SBarry Smith   a->unplaced_user_alloc = a->user_alloc;
1679d3042a70SBarry Smith   a->v                   = (PetscScalar *)array;
1680637a0070SStefano Zampini   a->user_alloc          = PETSC_TRUE;
168147d993e7Ssuyashtn #if defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
1682c70f7ee4SJunchao Zhang   A->offloadmask = PETSC_OFFLOAD_CPU;
1683ca15aa20SStefano Zampini #endif
16843ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1685d3042a70SBarry Smith }
1686d3042a70SBarry Smith 
1687d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatDenseResetArray_SeqDense(Mat A)
1688d71ae5a4SJacob Faibussowitsch {
1689d3042a70SBarry Smith   Mat_SeqDense *a = (Mat_SeqDense *)A->data;
1690d3042a70SBarry Smith 
1691d3042a70SBarry Smith   PetscFunctionBegin;
169228b400f6SJacob Faibussowitsch   PetscCheck(!a->vecinuse, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Need to call MatDenseRestoreColumnVec() first");
169328b400f6SJacob Faibussowitsch   PetscCheck(!a->matinuse, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Need to call MatDenseRestoreSubMatrix() first");
1694d3042a70SBarry Smith   a->v             = a->unplacedarray;
1695d3042a70SBarry Smith   a->user_alloc    = a->unplaced_user_alloc;
1696d3042a70SBarry Smith   a->unplacedarray = NULL;
169747d993e7Ssuyashtn #if defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
1698c70f7ee4SJunchao Zhang   A->offloadmask = PETSC_OFFLOAD_CPU;
1699ca15aa20SStefano Zampini #endif
17003ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1701d3042a70SBarry Smith }
1702d3042a70SBarry Smith 
1703d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatDenseReplaceArray_SeqDense(Mat A, const PetscScalar *array)
1704d71ae5a4SJacob Faibussowitsch {
1705d5ea218eSStefano Zampini   Mat_SeqDense *a = (Mat_SeqDense *)A->data;
1706d5ea218eSStefano Zampini 
1707d5ea218eSStefano Zampini   PetscFunctionBegin;
170828b400f6SJacob Faibussowitsch   PetscCheck(!a->vecinuse, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Need to call MatDenseRestoreColumnVec() first");
170928b400f6SJacob Faibussowitsch   PetscCheck(!a->matinuse, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Need to call MatDenseRestoreSubMatrix() first");
17109566063dSJacob Faibussowitsch   if (!a->user_alloc) PetscCall(PetscFree(a->v));
1711d5ea218eSStefano Zampini   a->v          = (PetscScalar *)array;
1712d5ea218eSStefano Zampini   a->user_alloc = PETSC_FALSE;
171347d993e7Ssuyashtn #if defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
1714d5ea218eSStefano Zampini   A->offloadmask = PETSC_OFFLOAD_CPU;
1715d5ea218eSStefano Zampini #endif
17163ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1717d5ea218eSStefano Zampini }
1718d5ea218eSStefano Zampini 
1719d71ae5a4SJacob Faibussowitsch PetscErrorCode MatDestroy_SeqDense(Mat mat)
1720d71ae5a4SJacob Faibussowitsch {
1721ec8511deSBarry Smith   Mat_SeqDense *l = (Mat_SeqDense *)mat->data;
172290f02eecSBarry Smith 
17233a40ed3dSBarry Smith   PetscFunctionBegin;
17243ba16761SJacob Faibussowitsch   PetscCall(PetscLogObjectState((PetscObject)mat, "Rows %" PetscInt_FMT " Cols %" PetscInt_FMT, mat->rmap->n, mat->cmap->n));
1725f4f49eeaSPierre Jolivet   PetscCall(VecDestroy(&l->qrrhs));
17269566063dSJacob Faibussowitsch   PetscCall(PetscFree(l->tau));
17279566063dSJacob Faibussowitsch   PetscCall(PetscFree(l->pivots));
17289566063dSJacob Faibussowitsch   PetscCall(PetscFree(l->fwork));
17299566063dSJacob Faibussowitsch   if (!l->user_alloc) PetscCall(PetscFree(l->v));
17309566063dSJacob Faibussowitsch   if (!l->unplaced_user_alloc) PetscCall(PetscFree(l->unplacedarray));
173128b400f6SJacob Faibussowitsch   PetscCheck(!l->vecinuse, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Need to call MatDenseRestoreColumnVec() first");
173228b400f6SJacob Faibussowitsch   PetscCheck(!l->matinuse, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Need to call MatDenseRestoreSubMatrix() first");
17339566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&l->cvec));
17349566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&l->cmat));
17359566063dSJacob Faibussowitsch   PetscCall(PetscFree(mat->data));
1736dbd8c25aSHong Zhang 
17379566063dSJacob Faibussowitsch   PetscCall(PetscObjectChangeTypeName((PetscObject)mat, NULL));
17389566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatQRFactor_C", NULL));
17392e956fe4SStefano Zampini   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatQRFactorSymbolic_C", NULL));
17402e956fe4SStefano Zampini   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatQRFactorNumeric_C", NULL));
17419566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatDenseGetLDA_C", NULL));
17429566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatDenseSetLDA_C", NULL));
17439566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatDenseGetArray_C", NULL));
17449566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatDenseRestoreArray_C", NULL));
17459566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatDensePlaceArray_C", NULL));
17469566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatDenseResetArray_C", NULL));
17479566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatDenseReplaceArray_C", NULL));
17489566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatDenseGetArrayRead_C", NULL));
17499566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatDenseRestoreArrayRead_C", NULL));
17509566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatDenseGetArrayWrite_C", NULL));
17519566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatDenseRestoreArrayWrite_C", NULL));
17529566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatConvert_seqdense_seqaij_C", NULL));
17538baccfbdSHong Zhang #if defined(PETSC_HAVE_ELEMENTAL)
17549566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatConvert_seqdense_elemental_C", NULL));
17558baccfbdSHong Zhang #endif
1756d24d4204SJose E. Roman #if defined(PETSC_HAVE_SCALAPACK)
17579566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatConvert_seqdense_scalapack_C", NULL));
1758d24d4204SJose E. Roman #endif
17592bf066beSStefano Zampini #if defined(PETSC_HAVE_CUDA)
17609566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatConvert_seqdense_seqdensecuda_C", NULL));
17619566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatProductSetFromOptions_seqdensecuda_seqdensecuda_C", NULL));
17629566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatProductSetFromOptions_seqdensecuda_seqdense_C", NULL));
17632e956fe4SStefano Zampini   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatProductSetFromOptions_seqdense_seqdensecuda_C", NULL));
17642bf066beSStefano Zampini #endif
176547d993e7Ssuyashtn #if defined(PETSC_HAVE_HIP)
176647d993e7Ssuyashtn   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatConvert_seqdense_seqdensehip_C", NULL));
176747d993e7Ssuyashtn   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatProductSetFromOptions_seqdensehip_seqdensehip_C", NULL));
176847d993e7Ssuyashtn   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatProductSetFromOptions_seqdensehip_seqdense_C", NULL));
176947d993e7Ssuyashtn   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatProductSetFromOptions_seqdense_seqdensehip_C", NULL));
177047d993e7Ssuyashtn #endif
17719566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatSeqDenseSetPreallocation_C", NULL));
17729566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatProductSetFromOptions_seqaij_seqdense_C", NULL));
17739566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatProductSetFromOptions_seqdense_seqdense_C", NULL));
17749566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatProductSetFromOptions_seqbaij_seqdense_C", NULL));
17759566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatProductSetFromOptions_seqsbaij_seqdense_C", NULL));
177652c5f739Sprj- 
17779566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatDenseGetColumn_C", NULL));
17789566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatDenseRestoreColumn_C", NULL));
17799566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatDenseGetColumnVec_C", NULL));
17809566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatDenseRestoreColumnVec_C", NULL));
17819566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatDenseGetColumnVecRead_C", NULL));
17829566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatDenseRestoreColumnVecRead_C", NULL));
17839566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatDenseGetColumnVecWrite_C", NULL));
17849566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatDenseRestoreColumnVecWrite_C", NULL));
17859566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatDenseGetSubMatrix_C", NULL));
17869566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatDenseRestoreSubMatrix_C", NULL));
1787*d016bddeSToby Isaac   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatMultColumnRange_C", NULL));
17880be0d8bdSHansol Suh   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatMultAddColumnRange_C", NULL));
17890be0d8bdSHansol Suh   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatMultHermitianTransposeColumnRange_C", NULL));
17900be0d8bdSHansol Suh   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatMultHermitianTransposeAddColumnRange_C", NULL));
17913ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1792289bc588SBarry Smith }
1793289bc588SBarry Smith 
1794d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatTranspose_SeqDense(Mat A, MatReuse reuse, Mat *matout)
1795d71ae5a4SJacob Faibussowitsch {
1796c0bbcb79SLois Curfman McInnes   Mat_SeqDense *mat = (Mat_SeqDense *)A->data;
17976536e3caSStefano Zampini   PetscInt      k, j, m = A->rmap->n, M = mat->lda, n = A->cmap->n;
179887828ca2SBarry Smith   PetscScalar  *v, tmp;
179948b35521SBarry Smith 
18003a40ed3dSBarry Smith   PetscFunctionBegin;
18017fb60732SBarry Smith   if (reuse == MAT_REUSE_MATRIX) PetscCall(MatTransposeCheckNonzeroState_Private(A, *matout));
18026536e3caSStefano Zampini   if (reuse == MAT_INPLACE_MATRIX) {
18036536e3caSStefano Zampini     if (m == n) { /* in place transpose */
18049566063dSJacob Faibussowitsch       PetscCall(MatDenseGetArray(A, &v));
1805d3e5ee88SLois Curfman McInnes       for (j = 0; j < m; j++) {
1806289bc588SBarry Smith         for (k = 0; k < j; k++) {
18071b807ce4Svictorle           tmp          = v[j + k * M];
18081b807ce4Svictorle           v[j + k * M] = v[k + j * M];
18091b807ce4Svictorle           v[k + j * M] = tmp;
1810289bc588SBarry Smith         }
1811289bc588SBarry Smith       }
18129566063dSJacob Faibussowitsch       PetscCall(MatDenseRestoreArray(A, &v));
18136536e3caSStefano Zampini     } else { /* reuse memory, temporary allocates new memory */
18146536e3caSStefano Zampini       PetscScalar *v2;
18156536e3caSStefano Zampini       PetscLayout  tmplayout;
18166536e3caSStefano Zampini 
18179566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1((size_t)m * n, &v2));
18189566063dSJacob Faibussowitsch       PetscCall(MatDenseGetArray(A, &v));
18196536e3caSStefano Zampini       for (j = 0; j < n; j++) {
18206536e3caSStefano Zampini         for (k = 0; k < m; k++) v2[j + (size_t)k * n] = v[k + (size_t)j * M];
18216536e3caSStefano Zampini       }
18229566063dSJacob Faibussowitsch       PetscCall(PetscArraycpy(v, v2, (size_t)m * n));
18239566063dSJacob Faibussowitsch       PetscCall(PetscFree(v2));
18249566063dSJacob Faibussowitsch       PetscCall(MatDenseRestoreArray(A, &v));
18256536e3caSStefano Zampini       /* cleanup size dependent quantities */
18269566063dSJacob Faibussowitsch       PetscCall(VecDestroy(&mat->cvec));
18279566063dSJacob Faibussowitsch       PetscCall(MatDestroy(&mat->cmat));
18289566063dSJacob Faibussowitsch       PetscCall(PetscFree(mat->pivots));
18299566063dSJacob Faibussowitsch       PetscCall(PetscFree(mat->fwork));
18306536e3caSStefano Zampini       /* swap row/col layouts */
18316497c311SBarry Smith       PetscCall(PetscBLASIntCast(n, &mat->lda));
18326536e3caSStefano Zampini       tmplayout = A->rmap;
18336536e3caSStefano Zampini       A->rmap   = A->cmap;
18346536e3caSStefano Zampini       A->cmap   = tmplayout;
18356536e3caSStefano Zampini     }
18363a40ed3dSBarry Smith   } else { /* out-of-place transpose */
1837d3e5ee88SLois Curfman McInnes     Mat           tmat;
1838ec8511deSBarry Smith     Mat_SeqDense *tmatd;
183987828ca2SBarry Smith     PetscScalar  *v2;
1840af36a384SStefano Zampini     PetscInt      M2;
1841ea709b57SSatish Balay 
18426536e3caSStefano Zampini     if (reuse == MAT_INITIAL_MATRIX) {
18439566063dSJacob Faibussowitsch       PetscCall(MatCreate(PetscObjectComm((PetscObject)A), &tmat));
18449566063dSJacob Faibussowitsch       PetscCall(MatSetSizes(tmat, A->cmap->n, A->rmap->n, A->cmap->n, A->rmap->n));
18459566063dSJacob Faibussowitsch       PetscCall(MatSetType(tmat, ((PetscObject)A)->type_name));
18469566063dSJacob Faibussowitsch       PetscCall(MatSeqDenseSetPreallocation(tmat, NULL));
1847ca15aa20SStefano Zampini     } else tmat = *matout;
1848ca15aa20SStefano Zampini 
18499566063dSJacob Faibussowitsch     PetscCall(MatDenseGetArrayRead(A, (const PetscScalar **)&v));
18509566063dSJacob Faibussowitsch     PetscCall(MatDenseGetArray(tmat, &v2));
1851ec8511deSBarry Smith     tmatd = (Mat_SeqDense *)tmat->data;
1852ca15aa20SStefano Zampini     M2    = tmatd->lda;
1853d3e5ee88SLois Curfman McInnes     for (j = 0; j < n; j++) {
1854af36a384SStefano Zampini       for (k = 0; k < m; k++) v2[j + k * M2] = v[k + j * M];
1855d3e5ee88SLois Curfman McInnes     }
18569566063dSJacob Faibussowitsch     PetscCall(MatDenseRestoreArray(tmat, &v2));
18579566063dSJacob Faibussowitsch     PetscCall(MatDenseRestoreArrayRead(A, (const PetscScalar **)&v));
18589566063dSJacob Faibussowitsch     PetscCall(MatAssemblyBegin(tmat, MAT_FINAL_ASSEMBLY));
18599566063dSJacob Faibussowitsch     PetscCall(MatAssemblyEnd(tmat, MAT_FINAL_ASSEMBLY));
18606536e3caSStefano Zampini     *matout = tmat;
186148b35521SBarry Smith   }
18623ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1863289bc588SBarry Smith }
1864289bc588SBarry Smith 
1865d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatEqual_SeqDense(Mat A1, Mat A2, PetscBool *flg)
1866d71ae5a4SJacob Faibussowitsch {
1867c0bbcb79SLois Curfman McInnes   Mat_SeqDense      *mat1 = (Mat_SeqDense *)A1->data;
1868c0bbcb79SLois Curfman McInnes   Mat_SeqDense      *mat2 = (Mat_SeqDense *)A2->data;
1869ca15aa20SStefano Zampini   PetscInt           i;
1870ca15aa20SStefano Zampini   const PetscScalar *v1, *v2;
18719ea5d5aeSSatish Balay 
18723a40ed3dSBarry Smith   PetscFunctionBegin;
18739371c9d4SSatish Balay   if (A1->rmap->n != A2->rmap->n) {
18749371c9d4SSatish Balay     *flg = PETSC_FALSE;
18753ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
18769371c9d4SSatish Balay   }
18779371c9d4SSatish Balay   if (A1->cmap->n != A2->cmap->n) {
18789371c9d4SSatish Balay     *flg = PETSC_FALSE;
18793ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
18809371c9d4SSatish Balay   }
18819566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArrayRead(A1, &v1));
18829566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArrayRead(A2, &v2));
1883ca15aa20SStefano Zampini   for (i = 0; i < A1->cmap->n; i++) {
18849566063dSJacob Faibussowitsch     PetscCall(PetscArraycmp(v1, v2, A1->rmap->n, flg));
18853ba16761SJacob Faibussowitsch     if (*flg == PETSC_FALSE) PetscFunctionReturn(PETSC_SUCCESS);
1886ca15aa20SStefano Zampini     v1 += mat1->lda;
1887ca15aa20SStefano Zampini     v2 += mat2->lda;
18881b807ce4Svictorle   }
18899566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArrayRead(A1, &v1));
18909566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArrayRead(A2, &v2));
189177c4ece6SBarry Smith   *flg = PETSC_TRUE;
18923ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1893289bc588SBarry Smith }
1894289bc588SBarry Smith 
189514277c92SJacob Faibussowitsch PetscErrorCode MatGetDiagonal_SeqDense(Mat A, Vec v)
1896d71ae5a4SJacob Faibussowitsch {
1897c0bbcb79SLois Curfman McInnes   Mat_SeqDense      *mat = (Mat_SeqDense *)A->data;
189813f74950SBarry Smith   PetscInt           i, n, len;
1899ca15aa20SStefano Zampini   PetscScalar       *x;
1900ca15aa20SStefano Zampini   const PetscScalar *vv;
190144cd7ae7SLois Curfman McInnes 
19023a40ed3dSBarry Smith   PetscFunctionBegin;
19039566063dSJacob Faibussowitsch   PetscCall(VecGetSize(v, &n));
19049566063dSJacob Faibussowitsch   PetscCall(VecGetArray(v, &x));
1905d0f46423SBarry Smith   len = PetscMin(A->rmap->n, A->cmap->n);
19069566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArrayRead(A, &vv));
190708401ef6SPierre Jolivet   PetscCheck(n == A->rmap->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Nonconforming mat and vec");
1908ad540459SPierre Jolivet   for (i = 0; i < len; i++) x[i] = vv[i * mat->lda + i];
19099566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArrayRead(A, &vv));
19109566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(v, &x));
19113ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1912289bc588SBarry Smith }
1913289bc588SBarry Smith 
1914d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatDiagonalScale_SeqDense(Mat A, Vec ll, Vec rr)
1915d71ae5a4SJacob Faibussowitsch {
1916c0bbcb79SLois Curfman McInnes   Mat_SeqDense      *mat = (Mat_SeqDense *)A->data;
1917f1ceaac6SMatthew G. Knepley   const PetscScalar *l, *r;
1918ca15aa20SStefano Zampini   PetscScalar        x, *v, *vv;
1919d0f46423SBarry Smith   PetscInt           i, j, m = A->rmap->n, n = A->cmap->n;
192055659b69SBarry Smith 
19213a40ed3dSBarry Smith   PetscFunctionBegin;
19229566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArray(A, &vv));
192328988994SBarry Smith   if (ll) {
19249566063dSJacob Faibussowitsch     PetscCall(VecGetSize(ll, &m));
19259566063dSJacob Faibussowitsch     PetscCall(VecGetArrayRead(ll, &l));
192608401ef6SPierre Jolivet     PetscCheck(m == A->rmap->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Left scaling vec wrong size");
1927da3a660dSBarry Smith     for (i = 0; i < m; i++) {
1928da3a660dSBarry Smith       x = l[i];
1929ca15aa20SStefano Zampini       v = vv + i;
19309371c9d4SSatish Balay       for (j = 0; j < n; j++) {
19319371c9d4SSatish Balay         (*v) *= x;
19329371c9d4SSatish Balay         v += mat->lda;
19339371c9d4SSatish Balay       }
1934da3a660dSBarry Smith     }
19359566063dSJacob Faibussowitsch     PetscCall(VecRestoreArrayRead(ll, &l));
19369566063dSJacob Faibussowitsch     PetscCall(PetscLogFlops(1.0 * n * m));
1937da3a660dSBarry Smith   }
193828988994SBarry Smith   if (rr) {
19399566063dSJacob Faibussowitsch     PetscCall(VecGetSize(rr, &n));
19409566063dSJacob Faibussowitsch     PetscCall(VecGetArrayRead(rr, &r));
194108401ef6SPierre Jolivet     PetscCheck(n == A->cmap->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Right scaling vec wrong size");
1942da3a660dSBarry Smith     for (i = 0; i < n; i++) {
1943da3a660dSBarry Smith       x = r[i];
1944ca15aa20SStefano Zampini       v = vv + i * mat->lda;
19452205254eSKarl Rupp       for (j = 0; j < m; j++) (*v++) *= x;
1946da3a660dSBarry Smith     }
19479566063dSJacob Faibussowitsch     PetscCall(VecRestoreArrayRead(rr, &r));
19489566063dSJacob Faibussowitsch     PetscCall(PetscLogFlops(1.0 * n * m));
1949da3a660dSBarry Smith   }
19509566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArray(A, &vv));
19513ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1952289bc588SBarry Smith }
1953289bc588SBarry Smith 
1954d71ae5a4SJacob Faibussowitsch PetscErrorCode MatNorm_SeqDense(Mat A, NormType type, PetscReal *nrm)
1955d71ae5a4SJacob Faibussowitsch {
1956c0bbcb79SLois Curfman McInnes   Mat_SeqDense *mat = (Mat_SeqDense *)A->data;
1957ca15aa20SStefano Zampini   PetscScalar  *v, *vv;
1958329f5518SBarry Smith   PetscReal     sum = 0.0;
195975f6d85dSStefano Zampini   PetscInt      lda, m = A->rmap->n, i, j;
196055659b69SBarry Smith 
19613a40ed3dSBarry Smith   PetscFunctionBegin;
19629566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArrayRead(A, (const PetscScalar **)&vv));
19639566063dSJacob Faibussowitsch   PetscCall(MatDenseGetLDA(A, &lda));
1964ca15aa20SStefano Zampini   v = vv;
1965289bc588SBarry Smith   if (type == NORM_FROBENIUS) {
1966a5ce6ee0Svictorle     if (lda > m) {
1967d0f46423SBarry Smith       for (j = 0; j < A->cmap->n; j++) {
1968ca15aa20SStefano Zampini         v = vv + j * lda;
1969a5ce6ee0Svictorle         for (i = 0; i < m; i++) {
19709371c9d4SSatish Balay           sum += PetscRealPart(PetscConj(*v) * (*v));
19719371c9d4SSatish Balay           v++;
1972a5ce6ee0Svictorle         }
1973a5ce6ee0Svictorle       }
1974a5ce6ee0Svictorle     } else {
1975570b7f6dSBarry Smith #if defined(PETSC_USE_REAL___FP16)
1976570b7f6dSBarry Smith       PetscBLASInt one = 1, cnt = A->cmap->n * A->rmap->n;
1977792fecdfSBarry Smith       PetscCallBLAS("BLASnrm2", *nrm = BLASnrm2_(&cnt, v, &one));
1978570b7f6dSBarry Smith     }
1979570b7f6dSBarry Smith #else
1980d0f46423SBarry Smith       for (i = 0; i < A->cmap->n * A->rmap->n; i++) {
19819371c9d4SSatish Balay         sum += PetscRealPart(PetscConj(*v) * (*v));
19829371c9d4SSatish Balay         v++;
1983289bc588SBarry Smith       }
1984a5ce6ee0Svictorle     }
19858f1a2a5eSBarry Smith     *nrm = PetscSqrtReal(sum);
1986570b7f6dSBarry Smith #endif
19879566063dSJacob Faibussowitsch     PetscCall(PetscLogFlops(2.0 * A->cmap->n * A->rmap->n));
19883a40ed3dSBarry Smith   } else if (type == NORM_1) {
1989064f8208SBarry Smith     *nrm = 0.0;
1990d0f46423SBarry Smith     for (j = 0; j < A->cmap->n; j++) {
1991ca15aa20SStefano Zampini       v   = vv + j * mat->lda;
1992289bc588SBarry Smith       sum = 0.0;
1993d0f46423SBarry Smith       for (i = 0; i < A->rmap->n; i++) {
19949371c9d4SSatish Balay         sum += PetscAbsScalar(*v);
19959371c9d4SSatish Balay         v++;
1996289bc588SBarry Smith       }
1997064f8208SBarry Smith       if (sum > *nrm) *nrm = sum;
1998289bc588SBarry Smith     }
19999566063dSJacob Faibussowitsch     PetscCall(PetscLogFlops(1.0 * A->cmap->n * A->rmap->n));
20003a40ed3dSBarry Smith   } else if (type == NORM_INFINITY) {
2001064f8208SBarry Smith     *nrm = 0.0;
2002d0f46423SBarry Smith     for (j = 0; j < A->rmap->n; j++) {
2003ca15aa20SStefano Zampini       v   = vv + j;
2004289bc588SBarry Smith       sum = 0.0;
2005d0f46423SBarry Smith       for (i = 0; i < A->cmap->n; i++) {
20069371c9d4SSatish Balay         sum += PetscAbsScalar(*v);
20079371c9d4SSatish Balay         v += mat->lda;
2008289bc588SBarry Smith       }
2009064f8208SBarry Smith       if (sum > *nrm) *nrm = sum;
2010289bc588SBarry Smith     }
20119566063dSJacob Faibussowitsch     PetscCall(PetscLogFlops(1.0 * A->cmap->n * A->rmap->n));
2012e7e72b3dSBarry Smith   } else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "No two norm");
20139566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArrayRead(A, (const PetscScalar **)&vv));
20143ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2015289bc588SBarry Smith }
2016289bc588SBarry Smith 
2017d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatSetOption_SeqDense(Mat A, MatOption op, PetscBool flg)
2018d71ae5a4SJacob Faibussowitsch {
2019c0bbcb79SLois Curfman McInnes   Mat_SeqDense *aij = (Mat_SeqDense *)A->data;
202067e560aaSBarry Smith 
20213a40ed3dSBarry Smith   PetscFunctionBegin;
2022b5a2b587SKris Buschelman   switch (op) {
2023d71ae5a4SJacob Faibussowitsch   case MAT_ROW_ORIENTED:
2024d71ae5a4SJacob Faibussowitsch     aij->roworiented = flg;
2025d71ae5a4SJacob Faibussowitsch     break;
2026d71ae5a4SJacob Faibussowitsch   default:
2027888c827cSStefano Zampini     break;
20283a40ed3dSBarry Smith   }
20293ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2030289bc588SBarry Smith }
2031289bc588SBarry Smith 
2032d71ae5a4SJacob Faibussowitsch PetscErrorCode MatZeroEntries_SeqDense(Mat A)
2033d71ae5a4SJacob Faibussowitsch {
2034ec8511deSBarry Smith   Mat_SeqDense *l   = (Mat_SeqDense *)A->data;
20353d8925e7SStefano Zampini   PetscInt      lda = l->lda, m = A->rmap->n, n = A->cmap->n, j;
2036ca15aa20SStefano Zampini   PetscScalar  *v;
20373a40ed3dSBarry Smith 
20383a40ed3dSBarry Smith   PetscFunctionBegin;
20399566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArrayWrite(A, &v));
2040a5ce6ee0Svictorle   if (lda > m) {
204148a46eb9SPierre Jolivet     for (j = 0; j < n; j++) PetscCall(PetscArrayzero(v + j * lda, m));
2042a5ce6ee0Svictorle   } else {
20439566063dSJacob Faibussowitsch     PetscCall(PetscArrayzero(v, PetscInt64Mult(m, n)));
2044a5ce6ee0Svictorle   }
20459566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArrayWrite(A, &v));
20463ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
20476f0a148fSBarry Smith }
20486f0a148fSBarry Smith 
2049d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatZeroRows_SeqDense(Mat A, PetscInt N, const PetscInt rows[], PetscScalar diag, Vec x, Vec b)
2050d71ae5a4SJacob Faibussowitsch {
2051ec8511deSBarry Smith   Mat_SeqDense      *l = (Mat_SeqDense *)A->data;
2052b9679d65SBarry Smith   PetscInt           m = l->lda, n = A->cmap->n, i, j;
2053ca15aa20SStefano Zampini   PetscScalar       *slot, *bb, *v;
205497b48c8fSBarry Smith   const PetscScalar *xx;
205555659b69SBarry Smith 
20563a40ed3dSBarry Smith   PetscFunctionBegin;
205776bd3646SJed Brown   if (PetscDefined(USE_DEBUG)) {
2058b9679d65SBarry Smith     for (i = 0; i < N; i++) {
205908401ef6SPierre Jolivet       PetscCheck(rows[i] >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Negative row requested to be zeroed");
206008401ef6SPierre 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);
2061b9679d65SBarry Smith     }
206276bd3646SJed Brown   }
20633ba16761SJacob Faibussowitsch   if (!N) PetscFunctionReturn(PETSC_SUCCESS);
2064b9679d65SBarry Smith 
2065dd8e379bSPierre Jolivet   /* fix right-hand side if needed */
206697b48c8fSBarry Smith   if (x && b) {
20679566063dSJacob Faibussowitsch     PetscCall(VecGetArrayRead(x, &xx));
20689566063dSJacob Faibussowitsch     PetscCall(VecGetArray(b, &bb));
20692205254eSKarl Rupp     for (i = 0; i < N; i++) bb[rows[i]] = diag * xx[rows[i]];
20709566063dSJacob Faibussowitsch     PetscCall(VecRestoreArrayRead(x, &xx));
20719566063dSJacob Faibussowitsch     PetscCall(VecRestoreArray(b, &bb));
207297b48c8fSBarry Smith   }
207397b48c8fSBarry Smith 
20749566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArray(A, &v));
20756f0a148fSBarry Smith   for (i = 0; i < N; i++) {
2076ca15aa20SStefano Zampini     slot = v + rows[i];
20779371c9d4SSatish Balay     for (j = 0; j < n; j++) {
20789371c9d4SSatish Balay       *slot = 0.0;
20799371c9d4SSatish Balay       slot += m;
20809371c9d4SSatish Balay     }
20816f0a148fSBarry Smith   }
2082f4df32b1SMatthew Knepley   if (diag != 0.0) {
208308401ef6SPierre Jolivet     PetscCheck(A->rmap->n == A->cmap->n, PETSC_COMM_SELF, PETSC_ERR_SUP, "Only coded for square matrices");
20846f0a148fSBarry Smith     for (i = 0; i < N; i++) {
2085ca15aa20SStefano Zampini       slot  = v + (m + 1) * rows[i];
2086f4df32b1SMatthew Knepley       *slot = diag;
20876f0a148fSBarry Smith     }
20886f0a148fSBarry Smith   }
20899566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArray(A, &v));
20903ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
20916f0a148fSBarry Smith }
2092557bce09SLois Curfman McInnes 
2093d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatDenseGetLDA_SeqDense(Mat A, PetscInt *lda)
2094d71ae5a4SJacob Faibussowitsch {
209549a6ff4bSBarry Smith   Mat_SeqDense *mat = (Mat_SeqDense *)A->data;
209649a6ff4bSBarry Smith 
209749a6ff4bSBarry Smith   PetscFunctionBegin;
209849a6ff4bSBarry Smith   *lda = mat->lda;
20993ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
210049a6ff4bSBarry Smith }
210149a6ff4bSBarry Smith 
2102d71ae5a4SJacob Faibussowitsch PetscErrorCode MatDenseGetArray_SeqDense(Mat A, PetscScalar **array)
2103d71ae5a4SJacob Faibussowitsch {
2104c0bbcb79SLois Curfman McInnes   Mat_SeqDense *mat = (Mat_SeqDense *)A->data;
21053a40ed3dSBarry Smith 
21063a40ed3dSBarry Smith   PetscFunctionBegin;
210728b400f6SJacob Faibussowitsch   PetscCheck(!mat->matinuse, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Need to call MatDenseRestoreSubMatrix() first");
210864e87e97SBarry Smith   *array = mat->v;
21093ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
211064e87e97SBarry Smith }
21110754003eSLois Curfman McInnes 
2112d71ae5a4SJacob Faibussowitsch PetscErrorCode MatDenseRestoreArray_SeqDense(Mat A, PetscScalar **array)
2113d71ae5a4SJacob Faibussowitsch {
21143a40ed3dSBarry Smith   PetscFunctionBegin;
211575f6d85dSStefano Zampini   if (array) *array = NULL;
21163ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2117ff14e315SSatish Balay }
21180754003eSLois Curfman McInnes 
21190f74d2c1SSatish Balay /*@
212011a5261eSBarry Smith   MatDenseGetLDA - gets the leading dimension of the array returned from `MatDenseGetArray()`
212149a6ff4bSBarry Smith 
21222ef1f0ffSBarry Smith   Not Collective
212349a6ff4bSBarry Smith 
212449a6ff4bSBarry Smith   Input Parameter:
2125fe59aa6dSJacob Faibussowitsch . A - a `MATDENSE` or `MATDENSECUDA` matrix
212649a6ff4bSBarry Smith 
212749a6ff4bSBarry Smith   Output Parameter:
212849a6ff4bSBarry Smith . lda - the leading dimension
212949a6ff4bSBarry Smith 
213049a6ff4bSBarry Smith   Level: intermediate
213149a6ff4bSBarry Smith 
21321cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATDENSE`, `MATDENSECUDA`, `MatDenseGetArray()`, `MatDenseRestoreArray()`, `MatDenseGetArrayRead()`, `MatDenseRestoreArrayRead()`, `MatDenseSetLDA()`
213349a6ff4bSBarry Smith @*/
2134d71ae5a4SJacob Faibussowitsch PetscErrorCode MatDenseGetLDA(Mat A, PetscInt *lda)
2135d71ae5a4SJacob Faibussowitsch {
213649a6ff4bSBarry Smith   PetscFunctionBegin;
2137d5ea218eSStefano Zampini   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
21384f572ea9SToby Isaac   PetscAssertPointer(lda, 2);
213975f6d85dSStefano Zampini   MatCheckPreallocated(A, 1);
2140cac4c232SBarry Smith   PetscUseMethod(A, "MatDenseGetLDA_C", (Mat, PetscInt *), (A, lda));
21413ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
214249a6ff4bSBarry Smith }
214349a6ff4bSBarry Smith 
21440f74d2c1SSatish Balay /*@
214511a5261eSBarry Smith   MatDenseSetLDA - Sets the leading dimension of the array used by the `MATDENSE` matrix
2146ad16ce7aSStefano Zampini 
21472323109cSBarry Smith   Collective if the matrix layouts have not yet been setup
2148ad16ce7aSStefano Zampini 
2149d8d19677SJose E. Roman   Input Parameters:
2150fe59aa6dSJacob Faibussowitsch + A   - a `MATDENSE` or `MATDENSECUDA` matrix
2151ad16ce7aSStefano Zampini - lda - the leading dimension
2152ad16ce7aSStefano Zampini 
2153ad16ce7aSStefano Zampini   Level: intermediate
2154ad16ce7aSStefano Zampini 
21551cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATDENSE`, `MATDENSECUDA`, `MatDenseGetArray()`, `MatDenseRestoreArray()`, `MatDenseGetArrayRead()`, `MatDenseRestoreArrayRead()`, `MatDenseGetLDA()`
2156ad16ce7aSStefano Zampini @*/
2157d71ae5a4SJacob Faibussowitsch PetscErrorCode MatDenseSetLDA(Mat A, PetscInt lda)
2158d71ae5a4SJacob Faibussowitsch {
2159ad16ce7aSStefano Zampini   PetscFunctionBegin;
2160ad16ce7aSStefano Zampini   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
2161cac4c232SBarry Smith   PetscTryMethod(A, "MatDenseSetLDA_C", (Mat, PetscInt), (A, lda));
21623ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2163ad16ce7aSStefano Zampini }
2164ad16ce7aSStefano Zampini 
2165ad16ce7aSStefano Zampini /*@C
216611a5261eSBarry Smith   MatDenseGetArray - gives read-write access to the array where the data for a `MATDENSE` matrix is stored
216773a71a0fSBarry Smith 
2168c3339decSBarry Smith   Logically Collective
216973a71a0fSBarry Smith 
217073a71a0fSBarry Smith   Input Parameter:
2171fe59aa6dSJacob Faibussowitsch . A - a dense matrix
217273a71a0fSBarry Smith 
217373a71a0fSBarry Smith   Output Parameter:
217473a71a0fSBarry Smith . array - pointer to the data
217573a71a0fSBarry Smith 
217673a71a0fSBarry Smith   Level: intermediate
217773a71a0fSBarry Smith 
21781cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATDENSE`, `MatDenseRestoreArray()`, `MatDenseGetArrayRead()`, `MatDenseRestoreArrayRead()`, `MatDenseGetArrayWrite()`, `MatDenseRestoreArrayWrite()`
217973a71a0fSBarry Smith @*/
2180ce78bad3SBarry Smith PetscErrorCode MatDenseGetArray(Mat A, PetscScalar *array[]) PeNS
2181d71ae5a4SJacob Faibussowitsch {
218273a71a0fSBarry Smith   PetscFunctionBegin;
2183d5ea218eSStefano Zampini   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
21844f572ea9SToby Isaac   PetscAssertPointer(array, 2);
2185cac4c232SBarry Smith   PetscUseMethod(A, "MatDenseGetArray_C", (Mat, PetscScalar **), (A, array));
21863ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
218773a71a0fSBarry Smith }
218873a71a0fSBarry Smith 
2189dec5eb66SMatthew G Knepley /*@C
219011a5261eSBarry Smith   MatDenseRestoreArray - returns access to the array where the data for a `MATDENSE` matrix is stored obtained by `MatDenseGetArray()`
219173a71a0fSBarry Smith 
2192c3339decSBarry Smith   Logically Collective
21938572280aSBarry Smith 
21948572280aSBarry Smith   Input Parameters:
2195fe59aa6dSJacob Faibussowitsch + A     - a dense matrix
21962ef1f0ffSBarry Smith - array - pointer to the data (may be `NULL`)
21978572280aSBarry Smith 
21988572280aSBarry Smith   Level: intermediate
21998572280aSBarry Smith 
22001cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATDENSE`, `MatDenseGetArray()`, `MatDenseGetArrayRead()`, `MatDenseRestoreArrayRead()`, `MatDenseGetArrayWrite()`, `MatDenseRestoreArrayWrite()`
22018572280aSBarry Smith @*/
2202ce78bad3SBarry Smith PetscErrorCode MatDenseRestoreArray(Mat A, PetscScalar *array[]) PeNS
2203d71ae5a4SJacob Faibussowitsch {
22048572280aSBarry Smith   PetscFunctionBegin;
2205d5ea218eSStefano Zampini   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
22064f572ea9SToby Isaac   if (array) PetscAssertPointer(array, 2);
2207cac4c232SBarry Smith   PetscUseMethod(A, "MatDenseRestoreArray_C", (Mat, PetscScalar **), (A, array));
22089566063dSJacob Faibussowitsch   PetscCall(PetscObjectStateIncrease((PetscObject)A));
220947d993e7Ssuyashtn #if defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
2210637a0070SStefano Zampini   A->offloadmask = PETSC_OFFLOAD_CPU;
2211637a0070SStefano Zampini #endif
22123ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
22138572280aSBarry Smith }
22148572280aSBarry Smith 
22158572280aSBarry Smith /*@C
221611a5261eSBarry Smith   MatDenseGetArrayRead - gives read-only access to the array where the data for a `MATDENSE` matrix is stored
22178572280aSBarry Smith 
2218fb850c59SBarry Smith   Not Collective
22198572280aSBarry Smith 
22208572280aSBarry Smith   Input Parameter:
2221fe59aa6dSJacob Faibussowitsch . A - a dense matrix
22228572280aSBarry Smith 
22238572280aSBarry Smith   Output Parameter:
22248572280aSBarry Smith . array - pointer to the data
22258572280aSBarry Smith 
22268572280aSBarry Smith   Level: intermediate
22278572280aSBarry Smith 
22281cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATDENSE`, `MatDenseRestoreArrayRead()`, `MatDenseGetArray()`, `MatDenseRestoreArray()`, `MatDenseGetArrayWrite()`, `MatDenseRestoreArrayWrite()`
22298572280aSBarry Smith @*/
2230ce78bad3SBarry Smith PetscErrorCode MatDenseGetArrayRead(Mat A, const PetscScalar *array[]) PeNS
2231d71ae5a4SJacob Faibussowitsch {
22328572280aSBarry Smith   PetscFunctionBegin;
2233d5ea218eSStefano Zampini   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
22344f572ea9SToby Isaac   PetscAssertPointer(array, 2);
22355c0db29aSPierre Jolivet   PetscUseMethod(A, "MatDenseGetArrayRead_C", (Mat, PetscScalar **), (A, (PetscScalar **)array));
22363ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
22378572280aSBarry Smith }
22388572280aSBarry Smith 
22398572280aSBarry Smith /*@C
224011a5261eSBarry Smith   MatDenseRestoreArrayRead - returns access to the array where the data for a `MATDENSE` matrix is stored obtained by `MatDenseGetArrayRead()`
22418572280aSBarry Smith 
2242fb850c59SBarry Smith   Not Collective
224373a71a0fSBarry Smith 
224473a71a0fSBarry Smith   Input Parameters:
2245fe59aa6dSJacob Faibussowitsch + A     - a dense matrix
22462ef1f0ffSBarry Smith - array - pointer to the data (may be `NULL`)
224773a71a0fSBarry Smith 
224873a71a0fSBarry Smith   Level: intermediate
224973a71a0fSBarry Smith 
22501cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATDENSE`, `MatDenseGetArrayRead()`, `MatDenseGetArray()`, `MatDenseRestoreArray()`, `MatDenseGetArrayWrite()`, `MatDenseRestoreArrayWrite()`
225173a71a0fSBarry Smith @*/
2252ce78bad3SBarry Smith PetscErrorCode MatDenseRestoreArrayRead(Mat A, const PetscScalar *array[]) PeNS
2253d71ae5a4SJacob Faibussowitsch {
225473a71a0fSBarry Smith   PetscFunctionBegin;
2255d5ea218eSStefano Zampini   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
22564f572ea9SToby Isaac   if (array) PetscAssertPointer(array, 2);
22575c0db29aSPierre Jolivet   PetscUseMethod(A, "MatDenseRestoreArrayRead_C", (Mat, PetscScalar **), (A, (PetscScalar **)array));
22583ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
225973a71a0fSBarry Smith }
226073a71a0fSBarry Smith 
22616947451fSStefano Zampini /*@C
226211a5261eSBarry Smith   MatDenseGetArrayWrite - gives write-only access to the array where the data for a `MATDENSE` matrix is stored
22636947451fSStefano Zampini 
2264fb850c59SBarry Smith   Not Collective
22656947451fSStefano Zampini 
22666947451fSStefano Zampini   Input Parameter:
2267fe59aa6dSJacob Faibussowitsch . A - a dense matrix
22686947451fSStefano Zampini 
22696947451fSStefano Zampini   Output Parameter:
22706947451fSStefano Zampini . array - pointer to the data
22716947451fSStefano Zampini 
22726947451fSStefano Zampini   Level: intermediate
22736947451fSStefano Zampini 
22741cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATDENSE`, `MatDenseRestoreArrayWrite()`, `MatDenseGetArray()`, `MatDenseRestoreArray()`, `MatDenseGetArrayRead()`, `MatDenseRestoreArrayRead()`
22756947451fSStefano Zampini @*/
2276ce78bad3SBarry Smith PetscErrorCode MatDenseGetArrayWrite(Mat A, PetscScalar *array[]) PeNS
2277d71ae5a4SJacob Faibussowitsch {
22786947451fSStefano Zampini   PetscFunctionBegin;
2279d5ea218eSStefano Zampini   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
22804f572ea9SToby Isaac   PetscAssertPointer(array, 2);
2281cac4c232SBarry Smith   PetscUseMethod(A, "MatDenseGetArrayWrite_C", (Mat, PetscScalar **), (A, array));
22823ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
22836947451fSStefano Zampini }
22846947451fSStefano Zampini 
22856947451fSStefano Zampini /*@C
228611a5261eSBarry Smith   MatDenseRestoreArrayWrite - returns access to the array where the data for a `MATDENSE` matrix is stored obtained by `MatDenseGetArrayWrite()`
22876947451fSStefano Zampini 
2288fb850c59SBarry Smith   Not Collective
22896947451fSStefano Zampini 
22906947451fSStefano Zampini   Input Parameters:
2291fe59aa6dSJacob Faibussowitsch + A     - a dense matrix
22922ef1f0ffSBarry Smith - array - pointer to the data (may be `NULL`)
22936947451fSStefano Zampini 
22946947451fSStefano Zampini   Level: intermediate
22956947451fSStefano Zampini 
22961cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATDENSE`, `MatDenseGetArrayWrite()`, `MatDenseGetArray()`, `MatDenseRestoreArray()`, `MatDenseGetArrayRead()`, `MatDenseRestoreArrayRead()`
22976947451fSStefano Zampini @*/
2298ce78bad3SBarry Smith PetscErrorCode MatDenseRestoreArrayWrite(Mat A, PetscScalar *array[]) PeNS
2299d71ae5a4SJacob Faibussowitsch {
23006947451fSStefano Zampini   PetscFunctionBegin;
2301d5ea218eSStefano Zampini   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
23024f572ea9SToby Isaac   if (array) PetscAssertPointer(array, 2);
2303cac4c232SBarry Smith   PetscUseMethod(A, "MatDenseRestoreArrayWrite_C", (Mat, PetscScalar **), (A, array));
23049566063dSJacob Faibussowitsch   PetscCall(PetscObjectStateIncrease((PetscObject)A));
230547d993e7Ssuyashtn #if defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
23066947451fSStefano Zampini   A->offloadmask = PETSC_OFFLOAD_CPU;
23076947451fSStefano Zampini #endif
23083ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
23096947451fSStefano Zampini }
23106947451fSStefano Zampini 
2311cd3f9d89SJunchao Zhang /*@C
2312cd3f9d89SJunchao Zhang   MatDenseGetArrayAndMemType - gives read-write access to the array where the data for a `MATDENSE` matrix is stored
2313cd3f9d89SJunchao Zhang 
2314cd3f9d89SJunchao Zhang   Logically Collective
2315cd3f9d89SJunchao Zhang 
2316cd3f9d89SJunchao Zhang   Input Parameter:
2317fe59aa6dSJacob Faibussowitsch . A - a dense matrix
2318cd3f9d89SJunchao Zhang 
2319cd3f9d89SJunchao Zhang   Output Parameters:
2320cd3f9d89SJunchao Zhang + array - pointer to the data
2321cd3f9d89SJunchao Zhang - mtype - memory type of the returned pointer
2322cd3f9d89SJunchao Zhang 
2323cd3f9d89SJunchao Zhang   Level: intermediate
2324cd3f9d89SJunchao Zhang 
2325fb850c59SBarry Smith   Note:
23262ef1f0ffSBarry Smith   If the matrix is of a device type such as `MATDENSECUDA`, `MATDENSEHIP`, etc.,
23272ef1f0ffSBarry Smith   an array on device is always returned and is guaranteed to contain the matrix's latest data.
23282ef1f0ffSBarry Smith 
23291cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATDENSE`, `MatDenseRestoreArrayAndMemType()`, `MatDenseGetArrayReadAndMemType()`, `MatDenseGetArrayWriteAndMemType()`, `MatDenseGetArrayRead()`,
2330cd3f9d89SJunchao Zhang    `MatDenseRestoreArrayRead()`, `MatDenseGetArrayWrite()`, `MatDenseRestoreArrayWrite()`, `MatSeqAIJGetCSRAndMemType()`
2331cd3f9d89SJunchao Zhang @*/
23325d83a8b1SBarry Smith PetscErrorCode MatDenseGetArrayAndMemType(Mat A, PetscScalar *array[], PetscMemType *mtype)
2333cd3f9d89SJunchao Zhang {
2334cd3f9d89SJunchao Zhang   PetscBool isMPI;
2335cd3f9d89SJunchao Zhang 
2336cd3f9d89SJunchao Zhang   PetscFunctionBegin;
2337cd3f9d89SJunchao Zhang   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
23384f572ea9SToby Isaac   PetscAssertPointer(array, 2);
2339e865de01SJunchao 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 */
2340cd3f9d89SJunchao Zhang   PetscCall(PetscObjectBaseTypeCompare((PetscObject)A, MATMPIDENSE, &isMPI));
2341cd3f9d89SJunchao Zhang   if (isMPI) {
2342cd3f9d89SJunchao Zhang     /* Dispatch here so that the code can be reused for all subclasses of MATDENSE */
2343cd3f9d89SJunchao Zhang     PetscCall(MatDenseGetArrayAndMemType(((Mat_MPIDense *)A->data)->A, array, mtype));
2344cd3f9d89SJunchao Zhang   } else {
2345cd3f9d89SJunchao Zhang     PetscErrorCode (*fptr)(Mat, PetscScalar **, PetscMemType *);
23463ba16761SJacob Faibussowitsch 
23473ba16761SJacob Faibussowitsch     PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatDenseGetArrayAndMemType_C", &fptr));
2348cd3f9d89SJunchao Zhang     if (fptr) {
2349cd3f9d89SJunchao Zhang       PetscCall((*fptr)(A, array, mtype));
2350cd3f9d89SJunchao Zhang     } else {
2351cd3f9d89SJunchao Zhang       PetscUseMethod(A, "MatDenseGetArray_C", (Mat, PetscScalar **), (A, array));
2352cd3f9d89SJunchao Zhang       if (mtype) *mtype = PETSC_MEMTYPE_HOST;
2353cd3f9d89SJunchao Zhang     }
2354cd3f9d89SJunchao Zhang   }
23553ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2356cd3f9d89SJunchao Zhang }
2357cd3f9d89SJunchao Zhang 
2358cd3f9d89SJunchao Zhang /*@C
2359cd3f9d89SJunchao Zhang   MatDenseRestoreArrayAndMemType - returns access to the array that is obtained by `MatDenseGetArrayAndMemType()`
2360cd3f9d89SJunchao Zhang 
2361cd3f9d89SJunchao Zhang   Logically Collective
2362cd3f9d89SJunchao Zhang 
2363cd3f9d89SJunchao Zhang   Input Parameters:
2364fe59aa6dSJacob Faibussowitsch + A     - a dense matrix
2365cd3f9d89SJunchao Zhang - array - pointer to the data
2366cd3f9d89SJunchao Zhang 
2367cd3f9d89SJunchao Zhang   Level: intermediate
2368cd3f9d89SJunchao Zhang 
23691cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATDENSE`, `MatDenseGetArrayAndMemType()`, `MatDenseGetArray()`, `MatDenseGetArrayRead()`, `MatDenseRestoreArrayRead()`, `MatDenseGetArrayWrite()`, `MatDenseRestoreArrayWrite()`
2370cd3f9d89SJunchao Zhang @*/
23715d83a8b1SBarry Smith PetscErrorCode MatDenseRestoreArrayAndMemType(Mat A, PetscScalar *array[])
2372cd3f9d89SJunchao Zhang {
2373cd3f9d89SJunchao Zhang   PetscBool isMPI;
2374cd3f9d89SJunchao Zhang 
2375cd3f9d89SJunchao Zhang   PetscFunctionBegin;
2376cd3f9d89SJunchao Zhang   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
23774f572ea9SToby Isaac   PetscAssertPointer(array, 2);
2378cd3f9d89SJunchao Zhang   PetscCall(PetscObjectBaseTypeCompare((PetscObject)A, MATMPIDENSE, &isMPI));
2379cd3f9d89SJunchao Zhang   if (isMPI) {
2380cd3f9d89SJunchao Zhang     PetscCall(MatDenseRestoreArrayAndMemType(((Mat_MPIDense *)A->data)->A, array));
2381cd3f9d89SJunchao Zhang   } else {
2382cd3f9d89SJunchao Zhang     PetscErrorCode (*fptr)(Mat, PetscScalar **);
23833ba16761SJacob Faibussowitsch 
23843ba16761SJacob Faibussowitsch     PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatDenseRestoreArrayAndMemType_C", &fptr));
2385cd3f9d89SJunchao Zhang     if (fptr) {
2386cd3f9d89SJunchao Zhang       PetscCall((*fptr)(A, array));
2387cd3f9d89SJunchao Zhang     } else {
2388cd3f9d89SJunchao Zhang       PetscUseMethod(A, "MatDenseRestoreArray_C", (Mat, PetscScalar **), (A, array));
2389cd3f9d89SJunchao Zhang     }
2390cd3f9d89SJunchao Zhang     *array = NULL;
2391cd3f9d89SJunchao Zhang   }
2392cd3f9d89SJunchao Zhang   PetscCall(PetscObjectStateIncrease((PetscObject)A));
23933ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2394cd3f9d89SJunchao Zhang }
2395cd3f9d89SJunchao Zhang 
2396cd3f9d89SJunchao Zhang /*@C
2397cd3f9d89SJunchao Zhang   MatDenseGetArrayReadAndMemType - gives read-only access to the array where the data for a `MATDENSE` matrix is stored
2398cd3f9d89SJunchao Zhang 
2399cd3f9d89SJunchao Zhang   Logically Collective
2400cd3f9d89SJunchao Zhang 
2401cd3f9d89SJunchao Zhang   Input Parameter:
2402fe59aa6dSJacob Faibussowitsch . A - a dense matrix
2403cd3f9d89SJunchao Zhang 
2404cd3f9d89SJunchao Zhang   Output Parameters:
2405cd3f9d89SJunchao Zhang + array - pointer to the data
2406cd3f9d89SJunchao Zhang - mtype - memory type of the returned pointer
2407cd3f9d89SJunchao Zhang 
2408cd3f9d89SJunchao Zhang   Level: intermediate
2409cd3f9d89SJunchao Zhang 
2410fb850c59SBarry Smith   Note:
24112ef1f0ffSBarry Smith   If the matrix is of a device type such as `MATDENSECUDA`, `MATDENSEHIP`, etc.,
24122ef1f0ffSBarry Smith   an array on device is always returned and is guaranteed to contain the matrix's latest data.
24132ef1f0ffSBarry Smith 
24141cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATDENSE`, `MatDenseRestoreArrayReadAndMemType()`, `MatDenseGetArrayWriteAndMemType()`,
2415cd3f9d89SJunchao Zhang    `MatDenseGetArrayRead()`, `MatDenseRestoreArrayRead()`, `MatDenseGetArrayWrite()`, `MatDenseRestoreArrayWrite()`, `MatSeqAIJGetCSRAndMemType()`
2416cd3f9d89SJunchao Zhang @*/
24175d83a8b1SBarry Smith PetscErrorCode MatDenseGetArrayReadAndMemType(Mat A, const PetscScalar *array[], PetscMemType *mtype)
2418cd3f9d89SJunchao Zhang {
2419cd3f9d89SJunchao Zhang   PetscBool isMPI;
2420cd3f9d89SJunchao Zhang 
2421cd3f9d89SJunchao Zhang   PetscFunctionBegin;
2422cd3f9d89SJunchao Zhang   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
24234f572ea9SToby Isaac   PetscAssertPointer(array, 2);
2424e865de01SJunchao 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 */
2425cd3f9d89SJunchao Zhang   PetscCall(PetscObjectBaseTypeCompare((PetscObject)A, MATMPIDENSE, &isMPI));
2426cd3f9d89SJunchao Zhang   if (isMPI) { /* Dispatch here so that the code can be reused for all subclasses of MATDENSE */
2427cd3f9d89SJunchao Zhang     PetscCall(MatDenseGetArrayReadAndMemType(((Mat_MPIDense *)A->data)->A, array, mtype));
2428cd3f9d89SJunchao Zhang   } else {
2429cd3f9d89SJunchao Zhang     PetscErrorCode (*fptr)(Mat, const PetscScalar **, PetscMemType *);
24303ba16761SJacob Faibussowitsch 
24313ba16761SJacob Faibussowitsch     PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatDenseGetArrayReadAndMemType_C", &fptr));
2432cd3f9d89SJunchao Zhang     if (fptr) {
2433cd3f9d89SJunchao Zhang       PetscCall((*fptr)(A, array, mtype));
2434cd3f9d89SJunchao Zhang     } else {
24355c0db29aSPierre Jolivet       PetscUseMethod(A, "MatDenseGetArrayRead_C", (Mat, PetscScalar **), (A, (PetscScalar **)array));
2436cd3f9d89SJunchao Zhang       if (mtype) *mtype = PETSC_MEMTYPE_HOST;
2437cd3f9d89SJunchao Zhang     }
2438cd3f9d89SJunchao Zhang   }
24393ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2440cd3f9d89SJunchao Zhang }
2441cd3f9d89SJunchao Zhang 
2442cd3f9d89SJunchao Zhang /*@C
2443cd3f9d89SJunchao Zhang   MatDenseRestoreArrayReadAndMemType - returns access to the array that is obtained by `MatDenseGetArrayReadAndMemType()`
2444cd3f9d89SJunchao Zhang 
2445cd3f9d89SJunchao Zhang   Logically Collective
2446cd3f9d89SJunchao Zhang 
2447cd3f9d89SJunchao Zhang   Input Parameters:
2448fe59aa6dSJacob Faibussowitsch + A     - a dense matrix
2449cd3f9d89SJunchao Zhang - array - pointer to the data
2450cd3f9d89SJunchao Zhang 
2451cd3f9d89SJunchao Zhang   Level: intermediate
2452cd3f9d89SJunchao Zhang 
24531cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATDENSE`, `MatDenseGetArrayReadAndMemType()`, `MatDenseGetArray()`, `MatDenseGetArrayRead()`, `MatDenseRestoreArrayRead()`, `MatDenseGetArrayWrite()`, `MatDenseRestoreArrayWrite()`
2454cd3f9d89SJunchao Zhang @*/
24555d83a8b1SBarry Smith PetscErrorCode MatDenseRestoreArrayReadAndMemType(Mat A, const PetscScalar *array[])
2456cd3f9d89SJunchao Zhang {
2457cd3f9d89SJunchao Zhang   PetscBool isMPI;
2458cd3f9d89SJunchao Zhang 
2459cd3f9d89SJunchao Zhang   PetscFunctionBegin;
2460cd3f9d89SJunchao Zhang   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
24614f572ea9SToby Isaac   PetscAssertPointer(array, 2);
2462cd3f9d89SJunchao Zhang   PetscCall(PetscObjectBaseTypeCompare((PetscObject)A, MATMPIDENSE, &isMPI));
2463cd3f9d89SJunchao Zhang   if (isMPI) {
2464cd3f9d89SJunchao Zhang     PetscCall(MatDenseRestoreArrayReadAndMemType(((Mat_MPIDense *)A->data)->A, array));
2465cd3f9d89SJunchao Zhang   } else {
2466cd3f9d89SJunchao Zhang     PetscErrorCode (*fptr)(Mat, const PetscScalar **);
24673ba16761SJacob Faibussowitsch 
24683ba16761SJacob Faibussowitsch     PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatDenseRestoreArrayReadAndMemType_C", &fptr));
2469cd3f9d89SJunchao Zhang     if (fptr) {
2470cd3f9d89SJunchao Zhang       PetscCall((*fptr)(A, array));
2471cd3f9d89SJunchao Zhang     } else {
24725c0db29aSPierre Jolivet       PetscUseMethod(A, "MatDenseRestoreArrayRead_C", (Mat, PetscScalar **), (A, (PetscScalar **)array));
2473cd3f9d89SJunchao Zhang     }
2474cd3f9d89SJunchao Zhang     *array = NULL;
2475cd3f9d89SJunchao Zhang   }
24763ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2477cd3f9d89SJunchao Zhang }
2478cd3f9d89SJunchao Zhang 
2479cd3f9d89SJunchao Zhang /*@C
2480cd3f9d89SJunchao Zhang   MatDenseGetArrayWriteAndMemType - gives write-only access to the array where the data for a `MATDENSE` matrix is stored
2481cd3f9d89SJunchao Zhang 
2482cd3f9d89SJunchao Zhang   Logically Collective
2483cd3f9d89SJunchao Zhang 
2484cd3f9d89SJunchao Zhang   Input Parameter:
2485fe59aa6dSJacob Faibussowitsch . A - a dense matrix
2486cd3f9d89SJunchao Zhang 
2487cd3f9d89SJunchao Zhang   Output Parameters:
2488cd3f9d89SJunchao Zhang + array - pointer to the data
2489cd3f9d89SJunchao Zhang - mtype - memory type of the returned pointer
2490cd3f9d89SJunchao Zhang 
2491cd3f9d89SJunchao Zhang   Level: intermediate
2492cd3f9d89SJunchao Zhang 
2493fb850c59SBarry Smith   Note:
24942ef1f0ffSBarry Smith   If the matrix is of a device type such as `MATDENSECUDA`, `MATDENSEHIP`, etc.,
24952ef1f0ffSBarry Smith   an array on device is always returned and is guaranteed to contain the matrix's latest data.
24962ef1f0ffSBarry Smith 
24971cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATDENSE`, `MatDenseRestoreArrayWriteAndMemType()`, `MatDenseGetArrayReadAndMemType()`, `MatDenseGetArrayRead()`,
2498cd3f9d89SJunchao Zhang   `MatDenseRestoreArrayRead()`, `MatDenseGetArrayWrite()`, `MatDenseRestoreArrayWrite()`, `MatSeqAIJGetCSRAndMemType()`
2499cd3f9d89SJunchao Zhang @*/
25005d83a8b1SBarry Smith PetscErrorCode MatDenseGetArrayWriteAndMemType(Mat A, PetscScalar *array[], PetscMemType *mtype)
2501cd3f9d89SJunchao Zhang {
2502cd3f9d89SJunchao Zhang   PetscBool isMPI;
2503cd3f9d89SJunchao Zhang 
2504cd3f9d89SJunchao Zhang   PetscFunctionBegin;
2505cd3f9d89SJunchao Zhang   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
25064f572ea9SToby Isaac   PetscAssertPointer(array, 2);
2507e865de01SJunchao 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 */
2508cd3f9d89SJunchao Zhang   PetscCall(PetscObjectBaseTypeCompare((PetscObject)A, MATMPIDENSE, &isMPI));
2509cd3f9d89SJunchao Zhang   if (isMPI) {
2510cd3f9d89SJunchao Zhang     PetscCall(MatDenseGetArrayWriteAndMemType(((Mat_MPIDense *)A->data)->A, array, mtype));
2511cd3f9d89SJunchao Zhang   } else {
2512cd3f9d89SJunchao Zhang     PetscErrorCode (*fptr)(Mat, PetscScalar **, PetscMemType *);
25133ba16761SJacob Faibussowitsch 
25143ba16761SJacob Faibussowitsch     PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatDenseGetArrayWriteAndMemType_C", &fptr));
2515cd3f9d89SJunchao Zhang     if (fptr) {
2516cd3f9d89SJunchao Zhang       PetscCall((*fptr)(A, array, mtype));
2517cd3f9d89SJunchao Zhang     } else {
2518cd3f9d89SJunchao Zhang       PetscUseMethod(A, "MatDenseGetArrayWrite_C", (Mat, PetscScalar **), (A, array));
2519cd3f9d89SJunchao Zhang       if (mtype) *mtype = PETSC_MEMTYPE_HOST;
2520cd3f9d89SJunchao Zhang     }
2521cd3f9d89SJunchao Zhang   }
25223ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2523cd3f9d89SJunchao Zhang }
2524cd3f9d89SJunchao Zhang 
2525cd3f9d89SJunchao Zhang /*@C
2526cd3f9d89SJunchao Zhang   MatDenseRestoreArrayWriteAndMemType - returns access to the array that is obtained by `MatDenseGetArrayReadAndMemType()`
2527cd3f9d89SJunchao Zhang 
2528cd3f9d89SJunchao Zhang   Logically Collective
2529cd3f9d89SJunchao Zhang 
2530cd3f9d89SJunchao Zhang   Input Parameters:
2531fe59aa6dSJacob Faibussowitsch + A     - a dense matrix
2532cd3f9d89SJunchao Zhang - array - pointer to the data
2533cd3f9d89SJunchao Zhang 
2534cd3f9d89SJunchao Zhang   Level: intermediate
2535cd3f9d89SJunchao Zhang 
25361cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATDENSE`, `MatDenseGetArrayWriteAndMemType()`, `MatDenseGetArray()`, `MatDenseGetArrayRead()`, `MatDenseRestoreArrayRead()`, `MatDenseGetArrayWrite()`, `MatDenseRestoreArrayWrite()`
2537cd3f9d89SJunchao Zhang @*/
25385d83a8b1SBarry Smith PetscErrorCode MatDenseRestoreArrayWriteAndMemType(Mat A, PetscScalar *array[])
2539cd3f9d89SJunchao Zhang {
2540cd3f9d89SJunchao Zhang   PetscBool isMPI;
2541cd3f9d89SJunchao Zhang 
2542cd3f9d89SJunchao Zhang   PetscFunctionBegin;
2543cd3f9d89SJunchao Zhang   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
25444f572ea9SToby Isaac   PetscAssertPointer(array, 2);
2545cd3f9d89SJunchao Zhang   PetscCall(PetscObjectBaseTypeCompare((PetscObject)A, MATMPIDENSE, &isMPI));
2546cd3f9d89SJunchao Zhang   if (isMPI) {
2547cd3f9d89SJunchao Zhang     PetscCall(MatDenseRestoreArrayWriteAndMemType(((Mat_MPIDense *)A->data)->A, array));
2548cd3f9d89SJunchao Zhang   } else {
2549cd3f9d89SJunchao Zhang     PetscErrorCode (*fptr)(Mat, PetscScalar **);
25503ba16761SJacob Faibussowitsch 
25513ba16761SJacob Faibussowitsch     PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatDenseRestoreArrayWriteAndMemType_C", &fptr));
2552cd3f9d89SJunchao Zhang     if (fptr) {
2553cd3f9d89SJunchao Zhang       PetscCall((*fptr)(A, array));
2554cd3f9d89SJunchao Zhang     } else {
2555cd3f9d89SJunchao Zhang       PetscUseMethod(A, "MatDenseRestoreArrayWrite_C", (Mat, PetscScalar **), (A, array));
2556cd3f9d89SJunchao Zhang     }
2557cd3f9d89SJunchao Zhang     *array = NULL;
2558cd3f9d89SJunchao Zhang   }
2559cd3f9d89SJunchao Zhang   PetscCall(PetscObjectStateIncrease((PetscObject)A));
25603ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2561cd3f9d89SJunchao Zhang }
2562cd3f9d89SJunchao Zhang 
2563d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatCreateSubMatrix_SeqDense(Mat A, IS isrow, IS iscol, MatReuse scall, Mat *B)
2564d71ae5a4SJacob Faibussowitsch {
2565c0bbcb79SLois Curfman McInnes   Mat_SeqDense   *mat = (Mat_SeqDense *)A->data;
2566bf5a80bcSToby Isaac   PetscInt        i, j, nrows, ncols, ldb;
25675d0c19d7SBarry Smith   const PetscInt *irow, *icol;
256887828ca2SBarry Smith   PetscScalar    *av, *bv, *v = mat->v;
25690754003eSLois Curfman McInnes   Mat             newmat;
25700754003eSLois Curfman McInnes 
25713a40ed3dSBarry Smith   PetscFunctionBegin;
25729566063dSJacob Faibussowitsch   PetscCall(ISGetIndices(isrow, &irow));
25739566063dSJacob Faibussowitsch   PetscCall(ISGetIndices(iscol, &icol));
25749566063dSJacob Faibussowitsch   PetscCall(ISGetLocalSize(isrow, &nrows));
25759566063dSJacob Faibussowitsch   PetscCall(ISGetLocalSize(iscol, &ncols));
25760754003eSLois Curfman McInnes 
2577182d2002SSatish Balay   /* Check submatrixcall */
2578182d2002SSatish Balay   if (scall == MAT_REUSE_MATRIX) {
257913f74950SBarry Smith     PetscInt n_cols, n_rows;
25809566063dSJacob Faibussowitsch     PetscCall(MatGetSize(*B, &n_rows, &n_cols));
258121a2c019SBarry Smith     if (n_rows != nrows || n_cols != ncols) {
2582f746d493SDmitry Karpeev       /* resize the result matrix to match number of requested rows/columns */
25839566063dSJacob Faibussowitsch       PetscCall(MatSetSizes(*B, nrows, ncols, nrows, ncols));
258421a2c019SBarry Smith     }
2585182d2002SSatish Balay     newmat = *B;
2586182d2002SSatish Balay   } else {
25870754003eSLois Curfman McInnes     /* Create and fill new matrix */
25889566063dSJacob Faibussowitsch     PetscCall(MatCreate(PetscObjectComm((PetscObject)A), &newmat));
25899566063dSJacob Faibussowitsch     PetscCall(MatSetSizes(newmat, nrows, ncols, nrows, ncols));
25909566063dSJacob Faibussowitsch     PetscCall(MatSetType(newmat, ((PetscObject)A)->type_name));
25919566063dSJacob Faibussowitsch     PetscCall(MatSeqDenseSetPreallocation(newmat, NULL));
2592182d2002SSatish Balay   }
2593182d2002SSatish Balay 
2594182d2002SSatish Balay   /* Now extract the data pointers and do the copy,column at a time */
25959566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArray(newmat, &bv));
25969566063dSJacob Faibussowitsch   PetscCall(MatDenseGetLDA(newmat, &ldb));
2597182d2002SSatish Balay   for (i = 0; i < ncols; i++) {
25986de62eeeSBarry Smith     av = v + mat->lda * icol[i];
2599ca15aa20SStefano Zampini     for (j = 0; j < nrows; j++) bv[j] = av[irow[j]];
2600bf5a80bcSToby Isaac     bv += ldb;
26010754003eSLois Curfman McInnes   }
26029566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArray(newmat, &bv));
2603182d2002SSatish Balay 
2604182d2002SSatish Balay   /* Assemble the matrices so that the correct flags are set */
26059566063dSJacob Faibussowitsch   PetscCall(MatAssemblyBegin(newmat, MAT_FINAL_ASSEMBLY));
26069566063dSJacob Faibussowitsch   PetscCall(MatAssemblyEnd(newmat, MAT_FINAL_ASSEMBLY));
26070754003eSLois Curfman McInnes 
26080754003eSLois Curfman McInnes   /* Free work space */
26099566063dSJacob Faibussowitsch   PetscCall(ISRestoreIndices(isrow, &irow));
26109566063dSJacob Faibussowitsch   PetscCall(ISRestoreIndices(iscol, &icol));
2611182d2002SSatish Balay   *B = newmat;
26123ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
26130754003eSLois Curfman McInnes }
26140754003eSLois Curfman McInnes 
2615d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatCreateSubMatrices_SeqDense(Mat A, PetscInt n, const IS irow[], const IS icol[], MatReuse scall, Mat *B[])
2616d71ae5a4SJacob Faibussowitsch {
261713f74950SBarry Smith   PetscInt i;
2618905e6a2fSBarry Smith 
26193a40ed3dSBarry Smith   PetscFunctionBegin;
262048a46eb9SPierre Jolivet   if (scall == MAT_INITIAL_MATRIX) PetscCall(PetscCalloc1(n, B));
2621905e6a2fSBarry Smith 
262248a46eb9SPierre Jolivet   for (i = 0; i < n; i++) PetscCall(MatCreateSubMatrix_SeqDense(A, irow[i], icol[i], scall, &(*B)[i]));
26233ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2624905e6a2fSBarry Smith }
2625905e6a2fSBarry Smith 
2626d71ae5a4SJacob Faibussowitsch PetscErrorCode MatCopy_SeqDense(Mat A, Mat B, MatStructure str)
2627d71ae5a4SJacob Faibussowitsch {
26284b0e389bSBarry Smith   Mat_SeqDense      *a = (Mat_SeqDense *)A->data, *b = (Mat_SeqDense *)B->data;
2629ca15aa20SStefano Zampini   const PetscScalar *va;
2630ca15aa20SStefano Zampini   PetscScalar       *vb;
2631d0f46423SBarry Smith   PetscInt           lda1 = a->lda, lda2 = b->lda, m = A->rmap->n, n = A->cmap->n, j;
26323a40ed3dSBarry Smith 
26333a40ed3dSBarry Smith   PetscFunctionBegin;
263433f4a19fSKris Buschelman   /* If the two matrices don't have the same copy implementation, they aren't compatible for fast copy. */
263533f4a19fSKris Buschelman   if (A->ops->copy != B->ops->copy) {
26369566063dSJacob Faibussowitsch     PetscCall(MatCopy_Basic(A, B, str));
26373ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
26383a40ed3dSBarry Smith   }
2639aed4548fSBarry Smith   PetscCheck(m == B->rmap->n && n == B->cmap->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "size(B) != size(A)");
26409566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArrayRead(A, &va));
26419566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArray(B, &vb));
2642a5ce6ee0Svictorle   if (lda1 > m || lda2 > m) {
264348a46eb9SPierre Jolivet     for (j = 0; j < n; j++) PetscCall(PetscArraycpy(vb + j * lda2, va + j * lda1, m));
2644a5ce6ee0Svictorle   } else {
26459566063dSJacob Faibussowitsch     PetscCall(PetscArraycpy(vb, va, A->rmap->n * A->cmap->n));
2646a5ce6ee0Svictorle   }
26479566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArray(B, &vb));
26489566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArrayRead(A, &va));
26499566063dSJacob Faibussowitsch   PetscCall(MatAssemblyBegin(B, MAT_FINAL_ASSEMBLY));
26509566063dSJacob Faibussowitsch   PetscCall(MatAssemblyEnd(B, MAT_FINAL_ASSEMBLY));
26513ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2652273d9f13SBarry Smith }
2653273d9f13SBarry Smith 
2654d71ae5a4SJacob Faibussowitsch PetscErrorCode MatSetUp_SeqDense(Mat A)
2655d71ae5a4SJacob Faibussowitsch {
2656273d9f13SBarry Smith   PetscFunctionBegin;
26579566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetUp(A->rmap));
26589566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetUp(A->cmap));
265948a46eb9SPierre Jolivet   if (!A->preallocated) PetscCall(MatSeqDenseSetPreallocation(A, NULL));
26603ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
26614b0e389bSBarry Smith }
26624b0e389bSBarry Smith 
26633853def2SToby Isaac PetscErrorCode MatConjugate_SeqDense(Mat A)
2664d71ae5a4SJacob Faibussowitsch {
26654396437dSToby Isaac   Mat_SeqDense *mat = (Mat_SeqDense *)A->data;
266606c5243aSJose E. Roman   PetscInt      i, j;
26674396437dSToby Isaac   PetscInt      min = PetscMin(A->rmap->n, A->cmap->n);
2668ca15aa20SStefano Zampini   PetscScalar  *aa;
2669ba337c44SJed Brown 
2670ba337c44SJed Brown   PetscFunctionBegin;
26719566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArray(A, &aa));
267206c5243aSJose E. Roman   for (j = 0; j < A->cmap->n; j++) {
267306c5243aSJose E. Roman     for (i = 0; i < A->rmap->n; i++) aa[i + j * mat->lda] = PetscConj(aa[i + j * mat->lda]);
267406c5243aSJose E. Roman   }
26759566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArray(A, &aa));
26769371c9d4SSatish Balay   if (mat->tau)
26779371c9d4SSatish Balay     for (i = 0; i < min; i++) mat->tau[i] = PetscConj(mat->tau[i]);
26783ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2679ba337c44SJed Brown }
2680ba337c44SJed Brown 
2681d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatRealPart_SeqDense(Mat A)
2682d71ae5a4SJacob Faibussowitsch {
268306c5243aSJose E. Roman   Mat_SeqDense *mat = (Mat_SeqDense *)A->data;
268406c5243aSJose E. Roman   PetscInt      i, j;
2685ca15aa20SStefano Zampini   PetscScalar  *aa;
2686ba337c44SJed Brown 
2687ba337c44SJed Brown   PetscFunctionBegin;
26889566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArray(A, &aa));
268906c5243aSJose E. Roman   for (j = 0; j < A->cmap->n; j++) {
269006c5243aSJose E. Roman     for (i = 0; i < A->rmap->n; i++) aa[i + j * mat->lda] = PetscRealPart(aa[i + j * mat->lda]);
269106c5243aSJose E. Roman   }
26929566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArray(A, &aa));
26933ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2694ba337c44SJed Brown }
2695ba337c44SJed Brown 
2696d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatImaginaryPart_SeqDense(Mat A)
2697d71ae5a4SJacob Faibussowitsch {
269806c5243aSJose E. Roman   Mat_SeqDense *mat = (Mat_SeqDense *)A->data;
269906c5243aSJose E. Roman   PetscInt      i, j;
2700ca15aa20SStefano Zampini   PetscScalar  *aa;
2701ba337c44SJed Brown 
2702ba337c44SJed Brown   PetscFunctionBegin;
27039566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArray(A, &aa));
270406c5243aSJose E. Roman   for (j = 0; j < A->cmap->n; j++) {
270506c5243aSJose E. Roman     for (i = 0; i < A->rmap->n; i++) aa[i + j * mat->lda] = PetscImaginaryPart(aa[i + j * mat->lda]);
270606c5243aSJose E. Roman   }
27079566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArray(A, &aa));
27083ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2709ba337c44SJed Brown }
2710284134d9SBarry Smith 
2711d71ae5a4SJacob Faibussowitsch PetscErrorCode MatMatMultSymbolic_SeqDense_SeqDense(Mat A, Mat B, PetscReal fill, Mat C)
2712d71ae5a4SJacob Faibussowitsch {
2713d0f46423SBarry Smith   PetscInt  m = A->rmap->n, n = B->cmap->n;
271447d993e7Ssuyashtn   PetscBool cisdense = PETSC_FALSE;
2715a9fe9ddaSSatish Balay 
2716ee16a9a1SHong Zhang   PetscFunctionBegin;
27179566063dSJacob Faibussowitsch   PetscCall(MatSetSizes(C, m, n, m, n));
271847d993e7Ssuyashtn #if defined(PETSC_HAVE_CUDA)
27199566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompareAny((PetscObject)C, &cisdense, MATSEQDENSE, MATSEQDENSECUDA, ""));
272047d993e7Ssuyashtn #endif
272147d993e7Ssuyashtn #if defined(PETSC_HAVE_HIP)
272247d993e7Ssuyashtn   PetscCall(PetscObjectTypeCompareAny((PetscObject)C, &cisdense, MATSEQDENSE, MATSEQDENSEHIP, ""));
272347d993e7Ssuyashtn #endif
27247a3c3d58SStefano Zampini   if (!cisdense) {
27257a3c3d58SStefano Zampini     PetscBool flg;
27267a3c3d58SStefano Zampini 
27279566063dSJacob Faibussowitsch     PetscCall(PetscObjectTypeCompare((PetscObject)B, ((PetscObject)A)->type_name, &flg));
27289566063dSJacob Faibussowitsch     PetscCall(MatSetType(C, flg ? ((PetscObject)A)->type_name : MATDENSE));
27297a3c3d58SStefano Zampini   }
27309566063dSJacob Faibussowitsch   PetscCall(MatSetUp(C));
27313ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2732ee16a9a1SHong Zhang }
2733a9fe9ddaSSatish Balay 
2734d71ae5a4SJacob Faibussowitsch PetscErrorCode MatMatMultNumeric_SeqDense_SeqDense(Mat A, Mat B, Mat C)
2735d71ae5a4SJacob Faibussowitsch {
27366718818eSStefano Zampini   Mat_SeqDense      *a = (Mat_SeqDense *)A->data, *b = (Mat_SeqDense *)B->data, *c = (Mat_SeqDense *)C->data;
27370805154bSBarry Smith   PetscBLASInt       m, n, k;
2738ca15aa20SStefano Zampini   const PetscScalar *av, *bv;
2739ca15aa20SStefano Zampini   PetscScalar       *cv;
2740a9fe9ddaSSatish Balay   PetscScalar        _DOne = 1.0, _DZero = 0.0;
2741a9fe9ddaSSatish Balay 
2742a9fe9ddaSSatish Balay   PetscFunctionBegin;
27439566063dSJacob Faibussowitsch   PetscCall(PetscBLASIntCast(C->rmap->n, &m));
27449566063dSJacob Faibussowitsch   PetscCall(PetscBLASIntCast(C->cmap->n, &n));
27459566063dSJacob Faibussowitsch   PetscCall(PetscBLASIntCast(A->cmap->n, &k));
27463ba16761SJacob Faibussowitsch   if (!m || !n || !k) PetscFunctionReturn(PETSC_SUCCESS);
27479566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArrayRead(A, &av));
27489566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArrayRead(B, &bv));
27499566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArrayWrite(C, &cv));
2750792fecdfSBarry Smith   PetscCallBLAS("BLASgemm", BLASgemm_("N", "N", &m, &n, &k, &_DOne, av, &a->lda, bv, &b->lda, &_DZero, cv, &c->lda));
27519566063dSJacob Faibussowitsch   PetscCall(PetscLogFlops(1.0 * m * n * k + 1.0 * m * n * (k - 1)));
27529566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArrayRead(A, &av));
27539566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArrayRead(B, &bv));
27549566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArrayWrite(C, &cv));
27553ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2756a9fe9ddaSSatish Balay }
2757a9fe9ddaSSatish Balay 
2758d71ae5a4SJacob Faibussowitsch PetscErrorCode MatMatTransposeMultSymbolic_SeqDense_SeqDense(Mat A, Mat B, PetscReal fill, Mat C)
2759d71ae5a4SJacob Faibussowitsch {
276069f65d41SStefano Zampini   PetscInt  m = A->rmap->n, n = B->rmap->n;
276147d993e7Ssuyashtn   PetscBool cisdense = PETSC_FALSE;
276269f65d41SStefano Zampini 
276369f65d41SStefano Zampini   PetscFunctionBegin;
27649566063dSJacob Faibussowitsch   PetscCall(MatSetSizes(C, m, n, m, n));
276547d993e7Ssuyashtn #if defined(PETSC_HAVE_CUDA)
27669566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompareAny((PetscObject)C, &cisdense, MATSEQDENSE, MATSEQDENSECUDA, ""));
276747d993e7Ssuyashtn #endif
276847d993e7Ssuyashtn #if defined(PETSC_HAVE_HIP)
276947d993e7Ssuyashtn   PetscCall(PetscObjectTypeCompareAny((PetscObject)C, &cisdense, MATSEQDENSE, MATSEQDENSEHIP, ""));
277047d993e7Ssuyashtn #endif
27717a3c3d58SStefano Zampini   if (!cisdense) {
27727a3c3d58SStefano Zampini     PetscBool flg;
27737a3c3d58SStefano Zampini 
27749566063dSJacob Faibussowitsch     PetscCall(PetscObjectTypeCompare((PetscObject)B, ((PetscObject)A)->type_name, &flg));
27759566063dSJacob Faibussowitsch     PetscCall(MatSetType(C, flg ? ((PetscObject)A)->type_name : MATDENSE));
27767a3c3d58SStefano Zampini   }
27779566063dSJacob Faibussowitsch   PetscCall(MatSetUp(C));
27783ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
277969f65d41SStefano Zampini }
278069f65d41SStefano Zampini 
2781d71ae5a4SJacob Faibussowitsch PetscErrorCode MatMatTransposeMultNumeric_SeqDense_SeqDense(Mat A, Mat B, Mat C)
2782d71ae5a4SJacob Faibussowitsch {
278369f65d41SStefano Zampini   Mat_SeqDense      *a = (Mat_SeqDense *)A->data;
278469f65d41SStefano Zampini   Mat_SeqDense      *b = (Mat_SeqDense *)B->data;
278569f65d41SStefano Zampini   Mat_SeqDense      *c = (Mat_SeqDense *)C->data;
27866718818eSStefano Zampini   const PetscScalar *av, *bv;
27876718818eSStefano Zampini   PetscScalar       *cv;
278869f65d41SStefano Zampini   PetscBLASInt       m, n, k;
278969f65d41SStefano Zampini   PetscScalar        _DOne = 1.0, _DZero = 0.0;
279069f65d41SStefano Zampini 
279169f65d41SStefano Zampini   PetscFunctionBegin;
27929566063dSJacob Faibussowitsch   PetscCall(PetscBLASIntCast(C->rmap->n, &m));
27939566063dSJacob Faibussowitsch   PetscCall(PetscBLASIntCast(C->cmap->n, &n));
27949566063dSJacob Faibussowitsch   PetscCall(PetscBLASIntCast(A->cmap->n, &k));
27953ba16761SJacob Faibussowitsch   if (!m || !n || !k) PetscFunctionReturn(PETSC_SUCCESS);
27969566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArrayRead(A, &av));
27979566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArrayRead(B, &bv));
27989566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArrayWrite(C, &cv));
2799792fecdfSBarry Smith   PetscCallBLAS("BLASgemm", BLASgemm_("N", "T", &m, &n, &k, &_DOne, av, &a->lda, bv, &b->lda, &_DZero, cv, &c->lda));
28009566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArrayRead(A, &av));
28019566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArrayRead(B, &bv));
28029566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArrayWrite(C, &cv));
28039566063dSJacob Faibussowitsch   PetscCall(PetscLogFlops(1.0 * m * n * k + 1.0 * m * n * (k - 1)));
28043ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
280569f65d41SStefano Zampini }
280669f65d41SStefano Zampini 
2807d71ae5a4SJacob Faibussowitsch PetscErrorCode MatTransposeMatMultSymbolic_SeqDense_SeqDense(Mat A, Mat B, PetscReal fill, Mat C)
2808d71ae5a4SJacob Faibussowitsch {
2809d0f46423SBarry Smith   PetscInt  m = A->cmap->n, n = B->cmap->n;
281047d993e7Ssuyashtn   PetscBool cisdense = PETSC_FALSE;
2811a9fe9ddaSSatish Balay 
2812ee16a9a1SHong Zhang   PetscFunctionBegin;
28139566063dSJacob Faibussowitsch   PetscCall(MatSetSizes(C, m, n, m, n));
281447d993e7Ssuyashtn #if defined(PETSC_HAVE_CUDA)
28159566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompareAny((PetscObject)C, &cisdense, MATSEQDENSE, MATSEQDENSECUDA, ""));
281647d993e7Ssuyashtn #endif
281747d993e7Ssuyashtn #if defined(PETSC_HAVE_HIP)
281847d993e7Ssuyashtn   PetscCall(PetscObjectTypeCompareAny((PetscObject)C, &cisdense, MATSEQDENSE, MATSEQDENSEHIP, ""));
281947d993e7Ssuyashtn #endif
28207a3c3d58SStefano Zampini   if (!cisdense) {
28217a3c3d58SStefano Zampini     PetscBool flg;
28227a3c3d58SStefano Zampini 
28239566063dSJacob Faibussowitsch     PetscCall(PetscObjectTypeCompare((PetscObject)B, ((PetscObject)A)->type_name, &flg));
28249566063dSJacob Faibussowitsch     PetscCall(MatSetType(C, flg ? ((PetscObject)A)->type_name : MATDENSE));
28257a3c3d58SStefano Zampini   }
28269566063dSJacob Faibussowitsch   PetscCall(MatSetUp(C));
28273ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2828ee16a9a1SHong Zhang }
2829a9fe9ddaSSatish Balay 
2830d71ae5a4SJacob Faibussowitsch PetscErrorCode MatTransposeMatMultNumeric_SeqDense_SeqDense(Mat A, Mat B, Mat C)
2831d71ae5a4SJacob Faibussowitsch {
2832a9fe9ddaSSatish Balay   Mat_SeqDense      *a = (Mat_SeqDense *)A->data;
2833a9fe9ddaSSatish Balay   Mat_SeqDense      *b = (Mat_SeqDense *)B->data;
2834a9fe9ddaSSatish Balay   Mat_SeqDense      *c = (Mat_SeqDense *)C->data;
28356718818eSStefano Zampini   const PetscScalar *av, *bv;
28366718818eSStefano Zampini   PetscScalar       *cv;
28370805154bSBarry Smith   PetscBLASInt       m, n, k;
2838a9fe9ddaSSatish Balay   PetscScalar        _DOne = 1.0, _DZero = 0.0;
2839a9fe9ddaSSatish Balay 
2840a9fe9ddaSSatish Balay   PetscFunctionBegin;
28419566063dSJacob Faibussowitsch   PetscCall(PetscBLASIntCast(C->rmap->n, &m));
28429566063dSJacob Faibussowitsch   PetscCall(PetscBLASIntCast(C->cmap->n, &n));
28439566063dSJacob Faibussowitsch   PetscCall(PetscBLASIntCast(A->rmap->n, &k));
28443ba16761SJacob Faibussowitsch   if (!m || !n || !k) PetscFunctionReturn(PETSC_SUCCESS);
28459566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArrayRead(A, &av));
28469566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArrayRead(B, &bv));
28479566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArrayWrite(C, &cv));
2848792fecdfSBarry Smith   PetscCallBLAS("BLASgemm", BLASgemm_("T", "N", &m, &n, &k, &_DOne, av, &a->lda, bv, &b->lda, &_DZero, cv, &c->lda));
28499566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArrayRead(A, &av));
28509566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArrayRead(B, &bv));
28519566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArrayWrite(C, &cv));
28529566063dSJacob Faibussowitsch   PetscCall(PetscLogFlops(1.0 * m * n * k + 1.0 * m * n * (k - 1)));
28533ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2854a9fe9ddaSSatish Balay }
2855985db425SBarry Smith 
2856d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatProductSetFromOptions_SeqDense_AB(Mat C)
2857d71ae5a4SJacob Faibussowitsch {
28584222ddf1SHong Zhang   PetscFunctionBegin;
28594222ddf1SHong Zhang   C->ops->matmultsymbolic = MatMatMultSymbolic_SeqDense_SeqDense;
28604222ddf1SHong Zhang   C->ops->productsymbolic = MatProductSymbolic_AB;
28613ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
28624222ddf1SHong Zhang }
28634222ddf1SHong Zhang 
2864d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatProductSetFromOptions_SeqDense_AtB(Mat C)
2865d71ae5a4SJacob Faibussowitsch {
28664222ddf1SHong Zhang   PetscFunctionBegin;
28674222ddf1SHong Zhang   C->ops->transposematmultsymbolic = MatTransposeMatMultSymbolic_SeqDense_SeqDense;
28684222ddf1SHong Zhang   C->ops->productsymbolic          = MatProductSymbolic_AtB;
28693ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
28704222ddf1SHong Zhang }
28714222ddf1SHong Zhang 
2872d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatProductSetFromOptions_SeqDense_ABt(Mat C)
2873d71ae5a4SJacob Faibussowitsch {
28744222ddf1SHong Zhang   PetscFunctionBegin;
28754222ddf1SHong Zhang   C->ops->mattransposemultsymbolic = MatMatTransposeMultSymbolic_SeqDense_SeqDense;
28764222ddf1SHong Zhang   C->ops->productsymbolic          = MatProductSymbolic_ABt;
28773ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
28784222ddf1SHong Zhang }
28794222ddf1SHong Zhang 
2880d71ae5a4SJacob Faibussowitsch PETSC_INTERN PetscErrorCode MatProductSetFromOptions_SeqDense(Mat C)
2881d71ae5a4SJacob Faibussowitsch {
28824222ddf1SHong Zhang   Mat_Product *product = C->product;
28834222ddf1SHong Zhang 
28844222ddf1SHong Zhang   PetscFunctionBegin;
28854222ddf1SHong Zhang   switch (product->type) {
2886d71ae5a4SJacob Faibussowitsch   case MATPRODUCT_AB:
2887d71ae5a4SJacob Faibussowitsch     PetscCall(MatProductSetFromOptions_SeqDense_AB(C));
2888d71ae5a4SJacob Faibussowitsch     break;
2889d71ae5a4SJacob Faibussowitsch   case MATPRODUCT_AtB:
2890d71ae5a4SJacob Faibussowitsch     PetscCall(MatProductSetFromOptions_SeqDense_AtB(C));
2891d71ae5a4SJacob Faibussowitsch     break;
2892d71ae5a4SJacob Faibussowitsch   case MATPRODUCT_ABt:
2893d71ae5a4SJacob Faibussowitsch     PetscCall(MatProductSetFromOptions_SeqDense_ABt(C));
2894d71ae5a4SJacob Faibussowitsch     break;
2895d71ae5a4SJacob Faibussowitsch   default:
2896d71ae5a4SJacob Faibussowitsch     break;
28974222ddf1SHong Zhang   }
28983ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
28994222ddf1SHong Zhang }
29004222ddf1SHong Zhang 
2901d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatGetRowMax_SeqDense(Mat A, Vec v, PetscInt idx[])
2902d71ae5a4SJacob Faibussowitsch {
2903985db425SBarry Smith   Mat_SeqDense      *a = (Mat_SeqDense *)A->data;
2904d0f46423SBarry Smith   PetscInt           i, j, m = A->rmap->n, n = A->cmap->n, p;
2905985db425SBarry Smith   PetscScalar       *x;
2906ca15aa20SStefano Zampini   const PetscScalar *aa;
2907985db425SBarry Smith 
2908985db425SBarry Smith   PetscFunctionBegin;
290928b400f6SJacob Faibussowitsch   PetscCheck(!A->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
29109566063dSJacob Faibussowitsch   PetscCall(VecGetArray(v, &x));
29119566063dSJacob Faibussowitsch   PetscCall(VecGetLocalSize(v, &p));
29129566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArrayRead(A, &aa));
291308401ef6SPierre Jolivet   PetscCheck(p == A->rmap->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Nonconforming matrix and vector");
2914985db425SBarry Smith   for (i = 0; i < m; i++) {
29159371c9d4SSatish Balay     x[i] = aa[i];
29169371c9d4SSatish Balay     if (idx) idx[i] = 0;
2917985db425SBarry Smith     for (j = 1; j < n; j++) {
29189371c9d4SSatish Balay       if (PetscRealPart(x[i]) < PetscRealPart(aa[i + a->lda * j])) {
29199371c9d4SSatish Balay         x[i] = aa[i + a->lda * j];
29209371c9d4SSatish Balay         if (idx) idx[i] = j;
29219371c9d4SSatish Balay       }
2922985db425SBarry Smith     }
2923985db425SBarry Smith   }
29249566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArrayRead(A, &aa));
29259566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(v, &x));
29263ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2927985db425SBarry Smith }
2928985db425SBarry Smith 
2929d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatGetRowMaxAbs_SeqDense(Mat A, Vec v, PetscInt idx[])
2930d71ae5a4SJacob Faibussowitsch {
2931985db425SBarry Smith   Mat_SeqDense      *a = (Mat_SeqDense *)A->data;
2932d0f46423SBarry Smith   PetscInt           i, j, m = A->rmap->n, n = A->cmap->n, p;
2933985db425SBarry Smith   PetscScalar       *x;
2934985db425SBarry Smith   PetscReal          atmp;
2935ca15aa20SStefano Zampini   const PetscScalar *aa;
2936985db425SBarry Smith 
2937985db425SBarry Smith   PetscFunctionBegin;
293828b400f6SJacob Faibussowitsch   PetscCheck(!A->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
29399566063dSJacob Faibussowitsch   PetscCall(VecGetArray(v, &x));
29409566063dSJacob Faibussowitsch   PetscCall(VecGetLocalSize(v, &p));
29419566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArrayRead(A, &aa));
294208401ef6SPierre Jolivet   PetscCheck(p == A->rmap->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Nonconforming matrix and vector");
2943985db425SBarry Smith   for (i = 0; i < m; i++) {
29449189402eSHong Zhang     x[i] = PetscAbsScalar(aa[i]);
2945985db425SBarry Smith     for (j = 1; j < n; j++) {
2946ca15aa20SStefano Zampini       atmp = PetscAbsScalar(aa[i + a->lda * j]);
29479371c9d4SSatish Balay       if (PetscAbsScalar(x[i]) < atmp) {
29489371c9d4SSatish Balay         x[i] = atmp;
29499371c9d4SSatish Balay         if (idx) idx[i] = j;
29509371c9d4SSatish Balay       }
2951985db425SBarry Smith     }
2952985db425SBarry Smith   }
29539566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArrayRead(A, &aa));
29549566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(v, &x));
29553ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2956985db425SBarry Smith }
2957985db425SBarry Smith 
2958d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatGetRowMin_SeqDense(Mat A, Vec v, PetscInt idx[])
2959d71ae5a4SJacob Faibussowitsch {
2960985db425SBarry Smith   Mat_SeqDense      *a = (Mat_SeqDense *)A->data;
2961d0f46423SBarry Smith   PetscInt           i, j, m = A->rmap->n, n = A->cmap->n, p;
2962985db425SBarry Smith   PetscScalar       *x;
2963ca15aa20SStefano Zampini   const PetscScalar *aa;
2964985db425SBarry Smith 
2965985db425SBarry Smith   PetscFunctionBegin;
296628b400f6SJacob Faibussowitsch   PetscCheck(!A->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
29679566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArrayRead(A, &aa));
29689566063dSJacob Faibussowitsch   PetscCall(VecGetArray(v, &x));
29699566063dSJacob Faibussowitsch   PetscCall(VecGetLocalSize(v, &p));
297008401ef6SPierre Jolivet   PetscCheck(p == A->rmap->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Nonconforming matrix and vector");
2971985db425SBarry Smith   for (i = 0; i < m; i++) {
29729371c9d4SSatish Balay     x[i] = aa[i];
29739371c9d4SSatish Balay     if (idx) idx[i] = 0;
2974985db425SBarry Smith     for (j = 1; j < n; j++) {
29759371c9d4SSatish Balay       if (PetscRealPart(x[i]) > PetscRealPart(aa[i + a->lda * j])) {
29769371c9d4SSatish Balay         x[i] = aa[i + a->lda * j];
29779371c9d4SSatish Balay         if (idx) idx[i] = j;
29789371c9d4SSatish Balay       }
2979985db425SBarry Smith     }
2980985db425SBarry Smith   }
29819566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(v, &x));
29829566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArrayRead(A, &aa));
29833ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2984985db425SBarry Smith }
2985985db425SBarry Smith 
2986d71ae5a4SJacob Faibussowitsch PetscErrorCode MatGetColumnVector_SeqDense(Mat A, Vec v, PetscInt col)
2987d71ae5a4SJacob Faibussowitsch {
29888d0534beSBarry Smith   Mat_SeqDense      *a = (Mat_SeqDense *)A->data;
29898d0534beSBarry Smith   PetscScalar       *x;
2990ca15aa20SStefano Zampini   const PetscScalar *aa;
29918d0534beSBarry Smith 
29928d0534beSBarry Smith   PetscFunctionBegin;
299328b400f6SJacob Faibussowitsch   PetscCheck(!A->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
29949566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArrayRead(A, &aa));
29959566063dSJacob Faibussowitsch   PetscCall(VecGetArray(v, &x));
29969566063dSJacob Faibussowitsch   PetscCall(PetscArraycpy(x, aa + col * a->lda, A->rmap->n));
29979566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(v, &x));
29989566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArrayRead(A, &aa));
29993ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
30008d0534beSBarry Smith }
30018d0534beSBarry Smith 
3002d71ae5a4SJacob Faibussowitsch PETSC_INTERN PetscErrorCode MatGetColumnReductions_SeqDense(Mat A, PetscInt type, PetscReal *reductions)
3003d71ae5a4SJacob Faibussowitsch {
30040716a85fSBarry Smith   PetscInt           i, j, m, n;
30051683a169SBarry Smith   const PetscScalar *a;
30060716a85fSBarry Smith 
30070716a85fSBarry Smith   PetscFunctionBegin;
30089566063dSJacob Faibussowitsch   PetscCall(MatGetSize(A, &m, &n));
30099566063dSJacob Faibussowitsch   PetscCall(PetscArrayzero(reductions, n));
30109566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArrayRead(A, &a));
3011857cbf51SRichard Tran Mills   if (type == NORM_2) {
30120716a85fSBarry Smith     for (i = 0; i < n; i++) {
3013ad540459SPierre Jolivet       for (j = 0; j < m; j++) reductions[i] += PetscAbsScalar(a[j] * a[j]);
301416cd844bSPierre Jolivet       a = PetscSafePointerPlusOffset(a, m);
30150716a85fSBarry Smith     }
3016857cbf51SRichard Tran Mills   } else if (type == NORM_1) {
30170716a85fSBarry Smith     for (i = 0; i < n; i++) {
3018ad540459SPierre Jolivet       for (j = 0; j < m; j++) reductions[i] += PetscAbsScalar(a[j]);
301916cd844bSPierre Jolivet       a = PetscSafePointerPlusOffset(a, m);
30200716a85fSBarry Smith     }
3021857cbf51SRichard Tran Mills   } else if (type == NORM_INFINITY) {
30220716a85fSBarry Smith     for (i = 0; i < n; i++) {
3023ad540459SPierre Jolivet       for (j = 0; j < m; j++) reductions[i] = PetscMax(PetscAbsScalar(a[j]), reductions[i]);
302416cd844bSPierre Jolivet       a = PetscSafePointerPlusOffset(a, m);
30250716a85fSBarry Smith     }
3026857cbf51SRichard Tran Mills   } else if (type == REDUCTION_SUM_REALPART || type == REDUCTION_MEAN_REALPART) {
3027a873a8cdSSam Reynolds     for (i = 0; i < n; i++) {
3028ad540459SPierre Jolivet       for (j = 0; j < m; j++) reductions[i] += PetscRealPart(a[j]);
302916cd844bSPierre Jolivet       a = PetscSafePointerPlusOffset(a, m);
3030a873a8cdSSam Reynolds     }
3031857cbf51SRichard Tran Mills   } else if (type == REDUCTION_SUM_IMAGINARYPART || type == REDUCTION_MEAN_IMAGINARYPART) {
3032857cbf51SRichard Tran Mills     for (i = 0; i < n; i++) {
3033ad540459SPierre Jolivet       for (j = 0; j < m; j++) reductions[i] += PetscImaginaryPart(a[j]);
303416cd844bSPierre Jolivet       a = PetscSafePointerPlusOffset(a, m);
3035857cbf51SRichard Tran Mills     }
3036857cbf51SRichard Tran Mills   } else SETERRQ(PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONG, "Unknown reduction type");
30379566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArrayRead(A, &a));
3038857cbf51SRichard Tran Mills   if (type == NORM_2) {
3039a873a8cdSSam Reynolds     for (i = 0; i < n; i++) reductions[i] = PetscSqrtReal(reductions[i]);
3040857cbf51SRichard Tran Mills   } else if (type == REDUCTION_MEAN_REALPART || type == REDUCTION_MEAN_IMAGINARYPART) {
3041a873a8cdSSam Reynolds     for (i = 0; i < n; i++) reductions[i] /= m;
30420716a85fSBarry Smith   }
30433ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
30440716a85fSBarry Smith }
30450716a85fSBarry Smith 
3046d71ae5a4SJacob Faibussowitsch PetscErrorCode MatSetRandom_SeqDense(Mat x, PetscRandom rctx)
3047d71ae5a4SJacob Faibussowitsch {
304873a71a0fSBarry Smith   PetscScalar *a;
3049637a0070SStefano Zampini   PetscInt     lda, m, n, i, j;
305073a71a0fSBarry Smith 
305173a71a0fSBarry Smith   PetscFunctionBegin;
30529566063dSJacob Faibussowitsch   PetscCall(MatGetSize(x, &m, &n));
30539566063dSJacob Faibussowitsch   PetscCall(MatDenseGetLDA(x, &lda));
30543faff063SStefano Zampini   PetscCall(MatDenseGetArrayWrite(x, &a));
3055637a0070SStefano Zampini   for (j = 0; j < n; j++) {
305648a46eb9SPierre Jolivet     for (i = 0; i < m; i++) PetscCall(PetscRandomGetValue(rctx, a + j * lda + i));
305773a71a0fSBarry Smith   }
30583faff063SStefano Zampini   PetscCall(MatDenseRestoreArrayWrite(x, &a));
30593ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
306073a71a0fSBarry Smith }
306173a71a0fSBarry Smith 
3062d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatMissingDiagonal_SeqDense(Mat A, PetscBool *missing, PetscInt *d)
3063d71ae5a4SJacob Faibussowitsch {
30643b49f96aSBarry Smith   PetscFunctionBegin;
30653b49f96aSBarry Smith   *missing = PETSC_FALSE;
30663ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
30673b49f96aSBarry Smith }
306873a71a0fSBarry Smith 
3069ca15aa20SStefano Zampini /* vals is not const */
3070d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatDenseGetColumn_SeqDense(Mat A, PetscInt col, PetscScalar **vals)
3071d71ae5a4SJacob Faibussowitsch {
307286aefd0dSHong Zhang   Mat_SeqDense *a = (Mat_SeqDense *)A->data;
3073ca15aa20SStefano Zampini   PetscScalar  *v;
307486aefd0dSHong Zhang 
307586aefd0dSHong Zhang   PetscFunctionBegin;
307628b400f6SJacob Faibussowitsch   PetscCheck(!A->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
30779566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArray(A, &v));
3078ca15aa20SStefano Zampini   *vals = v + col * a->lda;
30799566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArray(A, &v));
30803ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
308186aefd0dSHong Zhang }
308286aefd0dSHong Zhang 
3083d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatDenseRestoreColumn_SeqDense(Mat A, PetscScalar **vals)
3084d71ae5a4SJacob Faibussowitsch {
308586aefd0dSHong Zhang   PetscFunctionBegin;
3086742765d3SMatthew Knepley   if (vals) *vals = NULL; /* user cannot accidentally use the array later */
30873ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
308886aefd0dSHong Zhang }
3089abc3b08eSStefano Zampini 
3090a5ae1ecdSBarry Smith static struct _MatOps MatOps_Values = {MatSetValues_SeqDense,
3091905e6a2fSBarry Smith                                        MatGetRow_SeqDense,
3092905e6a2fSBarry Smith                                        MatRestoreRow_SeqDense,
3093905e6a2fSBarry Smith                                        MatMult_SeqDense,
309497304618SKris Buschelman                                        /*  4*/ MatMultAdd_SeqDense,
30957c922b88SBarry Smith                                        MatMultTranspose_SeqDense,
30967c922b88SBarry Smith                                        MatMultTransposeAdd_SeqDense,
3097f4259b30SLisandro Dalcin                                        NULL,
3098f4259b30SLisandro Dalcin                                        NULL,
3099f4259b30SLisandro Dalcin                                        NULL,
3100f4259b30SLisandro Dalcin                                        /* 10*/ NULL,
3101905e6a2fSBarry Smith                                        MatLUFactor_SeqDense,
3102905e6a2fSBarry Smith                                        MatCholeskyFactor_SeqDense,
310341f059aeSBarry Smith                                        MatSOR_SeqDense,
3104ec8511deSBarry Smith                                        MatTranspose_SeqDense,
310597304618SKris Buschelman                                        /* 15*/ MatGetInfo_SeqDense,
3106905e6a2fSBarry Smith                                        MatEqual_SeqDense,
3107905e6a2fSBarry Smith                                        MatGetDiagonal_SeqDense,
3108905e6a2fSBarry Smith                                        MatDiagonalScale_SeqDense,
3109905e6a2fSBarry Smith                                        MatNorm_SeqDense,
3110b7103cf4SPierre Jolivet                                        /* 20*/ NULL,
3111b7103cf4SPierre Jolivet                                        NULL,
3112905e6a2fSBarry Smith                                        MatSetOption_SeqDense,
3113905e6a2fSBarry Smith                                        MatZeroEntries_SeqDense,
3114d519adbfSMatthew Knepley                                        /* 24*/ MatZeroRows_SeqDense,
3115f4259b30SLisandro Dalcin                                        NULL,
3116f4259b30SLisandro Dalcin                                        NULL,
3117f4259b30SLisandro Dalcin                                        NULL,
3118f4259b30SLisandro Dalcin                                        NULL,
31194994cf47SJed Brown                                        /* 29*/ MatSetUp_SeqDense,
3120f4259b30SLisandro Dalcin                                        NULL,
3121f4259b30SLisandro Dalcin                                        NULL,
3122f4259b30SLisandro Dalcin                                        NULL,
3123f4259b30SLisandro Dalcin                                        NULL,
3124d519adbfSMatthew Knepley                                        /* 34*/ MatDuplicate_SeqDense,
3125f4259b30SLisandro Dalcin                                        NULL,
3126f4259b30SLisandro Dalcin                                        NULL,
3127f4259b30SLisandro Dalcin                                        NULL,
3128f4259b30SLisandro Dalcin                                        NULL,
3129d519adbfSMatthew Knepley                                        /* 39*/ MatAXPY_SeqDense,
31307dae84e0SHong Zhang                                        MatCreateSubMatrices_SeqDense,
3131f4259b30SLisandro Dalcin                                        NULL,
31324b0e389bSBarry Smith                                        MatGetValues_SeqDense,
3133a5ae1ecdSBarry Smith                                        MatCopy_SeqDense,
3134d519adbfSMatthew Knepley                                        /* 44*/ MatGetRowMax_SeqDense,
3135a5ae1ecdSBarry Smith                                        MatScale_SeqDense,
31362f605a99SJose E. Roman                                        MatShift_SeqDense,
3137f4259b30SLisandro Dalcin                                        NULL,
31383f49a652SStefano Zampini                                        MatZeroRowsColumns_SeqDense,
313973a71a0fSBarry Smith                                        /* 49*/ MatSetRandom_SeqDense,
3140f4259b30SLisandro Dalcin                                        NULL,
3141f4259b30SLisandro Dalcin                                        NULL,
3142f4259b30SLisandro Dalcin                                        NULL,
3143f4259b30SLisandro Dalcin                                        NULL,
3144f4259b30SLisandro Dalcin                                        /* 54*/ NULL,
3145f4259b30SLisandro Dalcin                                        NULL,
3146f4259b30SLisandro Dalcin                                        NULL,
3147f4259b30SLisandro Dalcin                                        NULL,
3148f4259b30SLisandro Dalcin                                        NULL,
3149023c16fcSToby Isaac                                        /* 59*/ MatCreateSubMatrix_SeqDense,
3150e03a110bSBarry Smith                                        MatDestroy_SeqDense,
3151e03a110bSBarry Smith                                        MatView_SeqDense,
3152f4259b30SLisandro Dalcin                                        NULL,
3153f4259b30SLisandro Dalcin                                        NULL,
3154f4259b30SLisandro Dalcin                                        /* 64*/ NULL,
3155f4259b30SLisandro Dalcin                                        NULL,
3156f4259b30SLisandro Dalcin                                        NULL,
3157f4259b30SLisandro Dalcin                                        NULL,
3158f4259b30SLisandro Dalcin                                        NULL,
3159d519adbfSMatthew Knepley                                        /* 69*/ MatGetRowMaxAbs_SeqDense,
3160f4259b30SLisandro Dalcin                                        NULL,
3161f4259b30SLisandro Dalcin                                        NULL,
3162f4259b30SLisandro Dalcin                                        NULL,
3163f4259b30SLisandro Dalcin                                        NULL,
3164f4259b30SLisandro Dalcin                                        /* 74*/ NULL,
3165f4259b30SLisandro Dalcin                                        NULL,
3166f4259b30SLisandro Dalcin                                        NULL,
3167f4259b30SLisandro Dalcin                                        NULL,
3168f4259b30SLisandro Dalcin                                        NULL,
3169f4259b30SLisandro Dalcin                                        /* 79*/ NULL,
3170f4259b30SLisandro Dalcin                                        NULL,
3171f4259b30SLisandro Dalcin                                        NULL,
3172f4259b30SLisandro Dalcin                                        NULL,
31735bba2384SShri Abhyankar                                        /* 83*/ MatLoad_SeqDense,
3174637a0070SStefano Zampini                                        MatIsSymmetric_SeqDense,
31751cbb95d3SBarry Smith                                        MatIsHermitian_SeqDense,
3176f4259b30SLisandro Dalcin                                        NULL,
3177f4259b30SLisandro Dalcin                                        NULL,
3178f4259b30SLisandro Dalcin                                        NULL,
3179f4259b30SLisandro Dalcin                                        /* 89*/ NULL,
3180f4259b30SLisandro Dalcin                                        NULL,
3181a9fe9ddaSSatish Balay                                        MatMatMultNumeric_SeqDense_SeqDense,
3182f4259b30SLisandro Dalcin                                        NULL,
3183f4259b30SLisandro Dalcin                                        NULL,
3184f4259b30SLisandro Dalcin                                        /* 94*/ NULL,
3185f4259b30SLisandro Dalcin                                        NULL,
3186f4259b30SLisandro Dalcin                                        NULL,
318769f65d41SStefano Zampini                                        MatMatTransposeMultNumeric_SeqDense_SeqDense,
3188f4259b30SLisandro Dalcin                                        NULL,
31894222ddf1SHong Zhang                                        /* 99*/ MatProductSetFromOptions_SeqDense,
3190f4259b30SLisandro Dalcin                                        NULL,
3191f4259b30SLisandro Dalcin                                        NULL,
3192ba337c44SJed Brown                                        MatConjugate_SeqDense,
3193f4259b30SLisandro Dalcin                                        NULL,
3194f4259b30SLisandro Dalcin                                        /*104*/ NULL,
3195ba337c44SJed Brown                                        MatRealPart_SeqDense,
3196ba337c44SJed Brown                                        MatImaginaryPart_SeqDense,
3197f4259b30SLisandro Dalcin                                        NULL,
3198f4259b30SLisandro Dalcin                                        NULL,
3199f4259b30SLisandro Dalcin                                        /*109*/ NULL,
3200f4259b30SLisandro Dalcin                                        NULL,
32018d0534beSBarry Smith                                        MatGetRowMin_SeqDense,
3202aabbc4fbSShri Abhyankar                                        MatGetColumnVector_SeqDense,
32033b49f96aSBarry Smith                                        MatMissingDiagonal_SeqDense,
3204f4259b30SLisandro Dalcin                                        /*114*/ NULL,
3205f4259b30SLisandro Dalcin                                        NULL,
3206f4259b30SLisandro Dalcin                                        NULL,
3207f4259b30SLisandro Dalcin                                        NULL,
3208f4259b30SLisandro Dalcin                                        NULL,
3209f4259b30SLisandro Dalcin                                        /*119*/ NULL,
3210f4259b30SLisandro Dalcin                                        NULL,
3211459e8d23SBlanca Mellado Pinto                                        MatMultHermitianTranspose_SeqDense,
3212459e8d23SBlanca Mellado Pinto                                        MatMultHermitianTransposeAdd_SeqDense,
3213f4259b30SLisandro Dalcin                                        NULL,
3214f4259b30SLisandro Dalcin                                        /*124*/ NULL,
3215a873a8cdSSam Reynolds                                        MatGetColumnReductions_SeqDense,
3216f4259b30SLisandro Dalcin                                        NULL,
3217f4259b30SLisandro Dalcin                                        NULL,
3218f4259b30SLisandro Dalcin                                        NULL,
3219f4259b30SLisandro Dalcin                                        /*129*/ NULL,
3220f4259b30SLisandro Dalcin                                        NULL,
3221f4259b30SLisandro Dalcin                                        NULL,
322275648e8dSHong Zhang                                        MatTransposeMatMultNumeric_SeqDense_SeqDense,
3223f4259b30SLisandro Dalcin                                        NULL,
3224f4259b30SLisandro Dalcin                                        /*134*/ NULL,
3225f4259b30SLisandro Dalcin                                        NULL,
3226f4259b30SLisandro Dalcin                                        NULL,
3227f4259b30SLisandro Dalcin                                        NULL,
3228f4259b30SLisandro Dalcin                                        NULL,
3229f4259b30SLisandro Dalcin                                        /*139*/ NULL,
3230f4259b30SLisandro Dalcin                                        NULL,
3231f4259b30SLisandro Dalcin                                        NULL,
3232f4259b30SLisandro Dalcin                                        NULL,
3233f4259b30SLisandro Dalcin                                        NULL,
32344222ddf1SHong Zhang                                        MatCreateMPIMatConcatenateSeqMat_SeqDense,
3235f4259b30SLisandro Dalcin                                        /*145*/ NULL,
3236f4259b30SLisandro Dalcin                                        NULL,
323799a7f59eSMark Adams                                        NULL,
323899a7f59eSMark Adams                                        NULL,
32397fb60732SBarry Smith                                        NULL,
3240dec0b466SHong Zhang                                        /*150*/ NULL,
3241eede4a3fSMark Adams                                        NULL,
32424cc2b5b5SPierre Jolivet                                        NULL,
324342ce410bSJunchao Zhang                                        NULL,
324442ce410bSJunchao Zhang                                        NULL,
3245fe1fc275SAlexander                                        /*155*/ NULL,
3246dec0b466SHong Zhang                                        NULL};
324790ace30eSBarry Smith 
32485d83a8b1SBarry Smith /*@
324911a5261eSBarry Smith   MatCreateSeqDense - Creates a `MATSEQDENSE` that
3250fb850c59SBarry Smith   is stored in column major order (the usual Fortran format).
3251289bc588SBarry Smith 
3252d083f849SBarry Smith   Collective
3253db81eaa0SLois Curfman McInnes 
325420563c6bSBarry Smith   Input Parameters:
325511a5261eSBarry Smith + comm - MPI communicator, set to `PETSC_COMM_SELF`
32560c775827SLois Curfman McInnes . m    - number of rows
325718f449edSLois Curfman McInnes . n    - number of columns
32582ef1f0ffSBarry Smith - data - optional location of matrix data in column major order.  Use `NULL` for PETSc
3259dfc5480cSLois Curfman McInnes          to control all matrix memory allocation.
326020563c6bSBarry Smith 
326120563c6bSBarry Smith   Output Parameter:
326244cd7ae7SLois Curfman McInnes . A - the matrix
326320563c6bSBarry Smith 
32642ef1f0ffSBarry Smith   Level: intermediate
32652ef1f0ffSBarry Smith 
326611a5261eSBarry Smith   Note:
326718f449edSLois Curfman McInnes   The data input variable is intended primarily for Fortran programmers
326818f449edSLois Curfman McInnes   who wish to allocate their own matrix memory space.  Most users should
32692ef1f0ffSBarry Smith   set `data` = `NULL`.
327018f449edSLois Curfman McInnes 
3271fb850c59SBarry Smith   Developer Note:
3272fb850c59SBarry Smith   Many of the matrix operations for this variant use the BLAS and LAPACK routines.
3273fb850c59SBarry Smith 
32741cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATSEQDENSE`, `MatCreate()`, `MatCreateDense()`, `MatSetValues()`
327520563c6bSBarry Smith @*/
32765d83a8b1SBarry Smith PetscErrorCode MatCreateSeqDense(MPI_Comm comm, PetscInt m, PetscInt n, PetscScalar data[], Mat *A)
3277d71ae5a4SJacob Faibussowitsch {
32783a40ed3dSBarry Smith   PetscFunctionBegin;
32799566063dSJacob Faibussowitsch   PetscCall(MatCreate(comm, A));
32809566063dSJacob Faibussowitsch   PetscCall(MatSetSizes(*A, m, n, m, n));
32819566063dSJacob Faibussowitsch   PetscCall(MatSetType(*A, MATSEQDENSE));
32829566063dSJacob Faibussowitsch   PetscCall(MatSeqDenseSetPreallocation(*A, data));
32833ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3284273d9f13SBarry Smith }
3285273d9f13SBarry Smith 
32865d83a8b1SBarry Smith /*@
328711a5261eSBarry Smith   MatSeqDenseSetPreallocation - Sets the array used for storing the matrix elements of a `MATSEQDENSE` matrix
3288273d9f13SBarry Smith 
3289d083f849SBarry Smith   Collective
3290273d9f13SBarry Smith 
3291273d9f13SBarry Smith   Input Parameters:
32921c4f3114SJed Brown + B    - the matrix
32932ef1f0ffSBarry Smith - data - the array (or `NULL`)
32942ef1f0ffSBarry Smith 
32952ef1f0ffSBarry Smith   Level: intermediate
3296273d9f13SBarry Smith 
329711a5261eSBarry Smith   Note:
3298273d9f13SBarry Smith   The data input variable is intended primarily for Fortran programmers
3299273d9f13SBarry Smith   who wish to allocate their own matrix memory space.  Most users should
3300284134d9SBarry Smith   need not call this routine.
3301273d9f13SBarry Smith 
33021cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATSEQDENSE`, `MatCreate()`, `MatCreateDense()`, `MatSetValues()`, `MatDenseSetLDA()`
3303273d9f13SBarry Smith @*/
3304d71ae5a4SJacob Faibussowitsch PetscErrorCode MatSeqDenseSetPreallocation(Mat B, PetscScalar data[])
3305d71ae5a4SJacob Faibussowitsch {
3306a23d5eceSKris Buschelman   PetscFunctionBegin;
3307d5ea218eSStefano Zampini   PetscValidHeaderSpecific(B, MAT_CLASSID, 1);
3308cac4c232SBarry Smith   PetscTryMethod(B, "MatSeqDenseSetPreallocation_C", (Mat, PetscScalar[]), (B, data));
33093ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3310a23d5eceSKris Buschelman }
3311a23d5eceSKris Buschelman 
3312d71ae5a4SJacob Faibussowitsch PetscErrorCode MatSeqDenseSetPreallocation_SeqDense(Mat B, PetscScalar *data)
3313d71ae5a4SJacob Faibussowitsch {
3314ad16ce7aSStefano Zampini   Mat_SeqDense *b = (Mat_SeqDense *)B->data;
3315273d9f13SBarry Smith 
3316273d9f13SBarry Smith   PetscFunctionBegin;
331728b400f6SJacob Faibussowitsch   PetscCheck(!b->matinuse, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Need to call MatDenseRestoreSubMatrix() first");
3318273d9f13SBarry Smith   B->preallocated = PETSC_TRUE;
3319a868139aSShri Abhyankar 
33209566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetUp(B->rmap));
33219566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetUp(B->cmap));
332234ef9618SShri Abhyankar 
33236497c311SBarry Smith   if (b->lda <= 0) PetscCall(PetscBLASIntCast(B->rmap->n, &b->lda));
332486d161a7SShri Abhyankar 
33259e8f95c4SLisandro Dalcin   if (!data) { /* petsc-allocated storage */
33269566063dSJacob Faibussowitsch     if (!b->user_alloc) PetscCall(PetscFree(b->v));
33279566063dSJacob Faibussowitsch     PetscCall(PetscCalloc1((size_t)b->lda * B->cmap->n, &b->v));
33282205254eSKarl Rupp 
33299e8f95c4SLisandro Dalcin     b->user_alloc = PETSC_FALSE;
3330273d9f13SBarry Smith   } else { /* user-allocated storage */
33319566063dSJacob Faibussowitsch     if (!b->user_alloc) PetscCall(PetscFree(b->v));
3332273d9f13SBarry Smith     b->v          = data;
3333273d9f13SBarry Smith     b->user_alloc = PETSC_TRUE;
3334273d9f13SBarry Smith   }
33350450473dSBarry Smith   B->assembled = PETSC_TRUE;
33363ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3337273d9f13SBarry Smith }
3338273d9f13SBarry Smith 
333965b80a83SHong Zhang #if defined(PETSC_HAVE_ELEMENTAL)
3340d71ae5a4SJacob Faibussowitsch PETSC_INTERN PetscErrorCode MatConvert_SeqDense_Elemental(Mat A, MatType newtype, MatReuse reuse, Mat *newmat)
3341d71ae5a4SJacob Faibussowitsch {
3342d77f618aSHong Zhang   Mat                mat_elemental;
33431683a169SBarry Smith   const PetscScalar *array;
33441683a169SBarry Smith   PetscScalar       *v_colwise;
3345d77f618aSHong Zhang   PetscInt           M = A->rmap->N, N = A->cmap->N, i, j, k, *rows, *cols;
3346d77f618aSHong Zhang 
33478baccfbdSHong Zhang   PetscFunctionBegin;
33489566063dSJacob Faibussowitsch   PetscCall(PetscMalloc3(M * N, &v_colwise, M, &rows, N, &cols));
33499566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArrayRead(A, &array));
3350d77f618aSHong Zhang   /* convert column-wise array into row-wise v_colwise, see MatSetValues_Elemental() */
3351d77f618aSHong Zhang   k = 0;
3352d77f618aSHong Zhang   for (j = 0; j < N; j++) {
3353d77f618aSHong Zhang     cols[j] = j;
3354ad540459SPierre Jolivet     for (i = 0; i < M; i++) v_colwise[j * M + i] = array[k++];
3355d77f618aSHong Zhang   }
3356ad540459SPierre Jolivet   for (i = 0; i < M; i++) rows[i] = i;
33579566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArrayRead(A, &array));
3358d77f618aSHong Zhang 
33599566063dSJacob Faibussowitsch   PetscCall(MatCreate(PetscObjectComm((PetscObject)A), &mat_elemental));
33609566063dSJacob Faibussowitsch   PetscCall(MatSetSizes(mat_elemental, PETSC_DECIDE, PETSC_DECIDE, M, N));
33619566063dSJacob Faibussowitsch   PetscCall(MatSetType(mat_elemental, MATELEMENTAL));
33629566063dSJacob Faibussowitsch   PetscCall(MatSetUp(mat_elemental));
3363d77f618aSHong Zhang 
3364d77f618aSHong Zhang   /* PETSc-Elemental interaface uses axpy for setting off-processor entries, only ADD_VALUES is allowed */
33659566063dSJacob Faibussowitsch   PetscCall(MatSetValues(mat_elemental, M, rows, N, cols, v_colwise, ADD_VALUES));
33669566063dSJacob Faibussowitsch   PetscCall(MatAssemblyBegin(mat_elemental, MAT_FINAL_ASSEMBLY));
33679566063dSJacob Faibussowitsch   PetscCall(MatAssemblyEnd(mat_elemental, MAT_FINAL_ASSEMBLY));
33689566063dSJacob Faibussowitsch   PetscCall(PetscFree3(v_colwise, rows, cols));
3369d77f618aSHong Zhang 
3370511c6705SHong Zhang   if (reuse == MAT_INPLACE_MATRIX) {
33719566063dSJacob Faibussowitsch     PetscCall(MatHeaderReplace(A, &mat_elemental));
3372d77f618aSHong Zhang   } else {
3373d77f618aSHong Zhang     *newmat = mat_elemental;
3374d77f618aSHong Zhang   }
33753ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
33768baccfbdSHong Zhang }
337765b80a83SHong Zhang #endif
33788baccfbdSHong Zhang 
3379d71ae5a4SJacob Faibussowitsch PetscErrorCode MatDenseSetLDA_SeqDense(Mat B, PetscInt lda)
3380d71ae5a4SJacob Faibussowitsch {
33811b807ce4Svictorle   Mat_SeqDense *b = (Mat_SeqDense *)B->data;
33827422da62SJose E. Roman   PetscBool     data;
338321a2c019SBarry Smith 
33841b807ce4Svictorle   PetscFunctionBegin;
3385835f2295SStefano Zampini   data = (B->rmap->n > 0 && B->cmap->n > 0) ? (b->v ? PETSC_TRUE : PETSC_FALSE) : PETSC_FALSE;
3386aed4548fSBarry Smith   PetscCheck(b->user_alloc || !data || b->lda == lda, PETSC_COMM_SELF, PETSC_ERR_ORDER, "LDA cannot be changed after allocation of internal storage");
338708401ef6SPierre 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);
33886497c311SBarry Smith   PetscCall(PetscBLASIntCast(lda, &b->lda));
33893ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
33901b807ce4Svictorle }
33911b807ce4Svictorle 
3392d71ae5a4SJacob Faibussowitsch PetscErrorCode MatCreateMPIMatConcatenateSeqMat_SeqDense(MPI_Comm comm, Mat inmat, PetscInt n, MatReuse scall, Mat *outmat)
3393d71ae5a4SJacob Faibussowitsch {
3394d528f656SJakub Kruzik   PetscFunctionBegin;
33959566063dSJacob Faibussowitsch   PetscCall(MatCreateMPIMatConcatenateSeqMat_MPIDense(comm, inmat, n, scall, outmat));
33963ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3397d528f656SJakub Kruzik }
3398d528f656SJakub Kruzik 
3399d16ceb75SStefano Zampini PetscErrorCode MatDenseCreateColumnVec_Private(Mat A, Vec *v)
3400d16ceb75SStefano Zampini {
3401d16ceb75SStefano Zampini   PetscBool   isstd, iskok, iscuda, iship;
3402d16ceb75SStefano Zampini   PetscMPIInt size;
3403d16ceb75SStefano Zampini #if PetscDefined(HAVE_CUDA) || PetscDefined(HAVE_HIP)
3404d16ceb75SStefano Zampini   /* we pass the data of A, to prevent allocating needless GPU memory the first time VecCUPMPlaceArray is called. */
3405d16ceb75SStefano Zampini   const PetscScalar *a;
3406d16ceb75SStefano Zampini #endif
3407d16ceb75SStefano Zampini 
3408d16ceb75SStefano Zampini   PetscFunctionBegin;
3409d16ceb75SStefano Zampini   *v = NULL;
3410d16ceb75SStefano Zampini   PetscCall(PetscStrcmpAny(A->defaultvectype, &isstd, VECSTANDARD, VECSEQ, VECMPI, ""));
3411d16ceb75SStefano Zampini   PetscCall(PetscStrcmpAny(A->defaultvectype, &iskok, VECKOKKOS, VECSEQKOKKOS, VECMPIKOKKOS, ""));
3412d16ceb75SStefano Zampini   PetscCall(PetscStrcmpAny(A->defaultvectype, &iscuda, VECCUDA, VECSEQCUDA, VECMPICUDA, ""));
3413d16ceb75SStefano Zampini   PetscCall(PetscStrcmpAny(A->defaultvectype, &iship, VECHIP, VECSEQHIP, VECMPIHIP, ""));
3414d16ceb75SStefano Zampini   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)A), &size));
3415d16ceb75SStefano Zampini   if (isstd) {
3416d16ceb75SStefano Zampini     if (size > 1) PetscCall(VecCreateMPIWithArray(PetscObjectComm((PetscObject)A), A->rmap->bs, A->rmap->n, A->rmap->N, NULL, v));
3417d16ceb75SStefano Zampini     else PetscCall(VecCreateSeqWithArray(PetscObjectComm((PetscObject)A), A->rmap->bs, A->rmap->n, NULL, v));
3418d16ceb75SStefano Zampini   } else if (iskok) {
3419d16ceb75SStefano Zampini     PetscCheck(PetscDefined(HAVE_KOKKOS_KERNELS), PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Reconfigure using KOKKOS kernels support");
3420d16ceb75SStefano Zampini #if PetscDefined(HAVE_KOKKOS_KERNELS)
3421d16ceb75SStefano Zampini     if (size > 1) PetscCall(VecCreateMPIKokkosWithArray(PetscObjectComm((PetscObject)A), A->rmap->bs, A->rmap->n, A->rmap->N, NULL, v));
3422d16ceb75SStefano Zampini     else PetscCall(VecCreateSeqKokkosWithArray(PetscObjectComm((PetscObject)A), A->rmap->bs, A->rmap->n, NULL, v));
3423d16ceb75SStefano Zampini #endif
3424d16ceb75SStefano Zampini   } else if (iscuda) {
3425d16ceb75SStefano Zampini     PetscCheck(PetscDefined(HAVE_CUDA), PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Reconfigure using CUDA support");
3426d16ceb75SStefano Zampini #if PetscDefined(HAVE_CUDA)
3427d16ceb75SStefano Zampini     PetscCall(MatDenseCUDAGetArrayRead(A, &a));
3428d16ceb75SStefano Zampini     if (size > 1) PetscCall(VecCreateMPICUDAWithArrays(PetscObjectComm((PetscObject)A), A->rmap->bs, A->rmap->n, A->rmap->N, NULL, a, v));
3429d16ceb75SStefano Zampini     else PetscCall(VecCreateSeqCUDAWithArrays(PetscObjectComm((PetscObject)A), A->rmap->bs, A->rmap->n, NULL, a, v));
3430d16ceb75SStefano Zampini #endif
3431d16ceb75SStefano Zampini   } else if (iship) {
3432d16ceb75SStefano Zampini     PetscCheck(PetscDefined(HAVE_HIP), PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Reconfigure using HIP support");
3433d16ceb75SStefano Zampini #if PetscDefined(HAVE_HIP)
3434d16ceb75SStefano Zampini     PetscCall(MatDenseHIPGetArrayRead(A, &a));
3435d16ceb75SStefano Zampini     if (size > 1) PetscCall(VecCreateMPIHIPWithArrays(PetscObjectComm((PetscObject)A), A->rmap->bs, A->rmap->n, A->rmap->N, NULL, a, v));
3436d16ceb75SStefano Zampini     else PetscCall(VecCreateSeqHIPWithArrays(PetscObjectComm((PetscObject)A), A->rmap->bs, A->rmap->n, NULL, a, v));
3437d16ceb75SStefano Zampini #endif
3438d16ceb75SStefano Zampini   }
3439d16ceb75SStefano Zampini   PetscCheck(*v, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Not coded for type %s", A->defaultvectype);
3440d16ceb75SStefano Zampini   PetscFunctionReturn(PETSC_SUCCESS);
3441d16ceb75SStefano Zampini }
3442d16ceb75SStefano Zampini 
3443d71ae5a4SJacob Faibussowitsch PetscErrorCode MatDenseGetColumnVec_SeqDense(Mat A, PetscInt col, Vec *v)
3444d71ae5a4SJacob Faibussowitsch {
34456947451fSStefano Zampini   Mat_SeqDense *a = (Mat_SeqDense *)A->data;
34466947451fSStefano Zampini 
34476947451fSStefano Zampini   PetscFunctionBegin;
344828b400f6SJacob Faibussowitsch   PetscCheck(!a->vecinuse, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Need to call MatDenseRestoreColumnVec() first");
344928b400f6SJacob Faibussowitsch   PetscCheck(!a->matinuse, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Need to call MatDenseRestoreSubMatrix() first");
3450d16ceb75SStefano Zampini   if (!a->cvec) PetscCall(MatDenseCreateColumnVec_Private(A, &a->cvec));
34516947451fSStefano Zampini   a->vecinuse = col + 1;
34529566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArray(A, (PetscScalar **)&a->ptrinuse));
34539566063dSJacob Faibussowitsch   PetscCall(VecPlaceArray(a->cvec, a->ptrinuse + (size_t)col * (size_t)a->lda));
34546947451fSStefano Zampini   *v = a->cvec;
34553ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
34566947451fSStefano Zampini }
34576947451fSStefano Zampini 
3458d71ae5a4SJacob Faibussowitsch PetscErrorCode MatDenseRestoreColumnVec_SeqDense(Mat A, PetscInt col, Vec *v)
3459d71ae5a4SJacob Faibussowitsch {
34606947451fSStefano Zampini   Mat_SeqDense *a = (Mat_SeqDense *)A->data;
34616947451fSStefano Zampini 
34626947451fSStefano Zampini   PetscFunctionBegin;
346328b400f6SJacob Faibussowitsch   PetscCheck(a->vecinuse, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Need to call MatDenseGetColumnVec() first");
346428b400f6SJacob Faibussowitsch   PetscCheck(a->cvec, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Missing internal column vector");
34654186a4bbSPierre Jolivet   VecCheckAssembled(a->cvec);
34666947451fSStefano Zampini   a->vecinuse = 0;
34679566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArray(A, (PetscScalar **)&a->ptrinuse));
34689566063dSJacob Faibussowitsch   PetscCall(VecResetArray(a->cvec));
346975f6d85dSStefano Zampini   if (v) *v = NULL;
34703ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
34716947451fSStefano Zampini }
34726947451fSStefano Zampini 
3473d71ae5a4SJacob Faibussowitsch PetscErrorCode MatDenseGetColumnVecRead_SeqDense(Mat A, PetscInt col, Vec *v)
3474d71ae5a4SJacob Faibussowitsch {
34756947451fSStefano Zampini   Mat_SeqDense *a = (Mat_SeqDense *)A->data;
34766947451fSStefano Zampini 
34776947451fSStefano Zampini   PetscFunctionBegin;
347828b400f6SJacob Faibussowitsch   PetscCheck(!a->vecinuse, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Need to call MatDenseRestoreColumnVec() first");
347928b400f6SJacob Faibussowitsch   PetscCheck(!a->matinuse, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Need to call MatDenseRestoreSubMatrix() first");
3480d16ceb75SStefano Zampini   if (!a->cvec) PetscCall(MatDenseCreateColumnVec_Private(A, &a->cvec));
34816947451fSStefano Zampini   a->vecinuse = col + 1;
34829566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArrayRead(A, &a->ptrinuse));
34838e3a54c0SPierre Jolivet   PetscCall(VecPlaceArray(a->cvec, PetscSafePointerPlusOffset(a->ptrinuse, (size_t)col * (size_t)a->lda)));
34849566063dSJacob Faibussowitsch   PetscCall(VecLockReadPush(a->cvec));
34856947451fSStefano Zampini   *v = a->cvec;
34863ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
34876947451fSStefano Zampini }
34886947451fSStefano Zampini 
3489d71ae5a4SJacob Faibussowitsch PetscErrorCode MatDenseRestoreColumnVecRead_SeqDense(Mat A, PetscInt col, Vec *v)
3490d71ae5a4SJacob Faibussowitsch {
34916947451fSStefano Zampini   Mat_SeqDense *a = (Mat_SeqDense *)A->data;
34926947451fSStefano Zampini 
34936947451fSStefano Zampini   PetscFunctionBegin;
349428b400f6SJacob Faibussowitsch   PetscCheck(a->vecinuse, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Need to call MatDenseGetColumnVec() first");
349528b400f6SJacob Faibussowitsch   PetscCheck(a->cvec, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Missing internal column vector");
34964186a4bbSPierre Jolivet   VecCheckAssembled(a->cvec);
34976947451fSStefano Zampini   a->vecinuse = 0;
34989566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArrayRead(A, &a->ptrinuse));
34999566063dSJacob Faibussowitsch   PetscCall(VecLockReadPop(a->cvec));
35009566063dSJacob Faibussowitsch   PetscCall(VecResetArray(a->cvec));
350175f6d85dSStefano Zampini   if (v) *v = NULL;
35023ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
35036947451fSStefano Zampini }
35046947451fSStefano Zampini 
3505d71ae5a4SJacob Faibussowitsch PetscErrorCode MatDenseGetColumnVecWrite_SeqDense(Mat A, PetscInt col, Vec *v)
3506d71ae5a4SJacob Faibussowitsch {
35076947451fSStefano Zampini   Mat_SeqDense *a = (Mat_SeqDense *)A->data;
35086947451fSStefano Zampini 
35096947451fSStefano Zampini   PetscFunctionBegin;
351028b400f6SJacob Faibussowitsch   PetscCheck(!a->vecinuse, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Need to call MatDenseRestoreColumnVec() first");
351128b400f6SJacob Faibussowitsch   PetscCheck(!a->matinuse, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Need to call MatDenseRestoreSubMatrix() first");
3512d16ceb75SStefano Zampini   if (!a->cvec) PetscCall(MatDenseCreateColumnVec_Private(A, &a->cvec));
35136947451fSStefano Zampini   a->vecinuse = col + 1;
35149566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArrayWrite(A, (PetscScalar **)&a->ptrinuse));
35158e3a54c0SPierre Jolivet   PetscCall(VecPlaceArray(a->cvec, PetscSafePointerPlusOffset(a->ptrinuse, (size_t)col * (size_t)a->lda)));
35166947451fSStefano Zampini   *v = a->cvec;
35173ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
35186947451fSStefano Zampini }
35196947451fSStefano Zampini 
3520d71ae5a4SJacob Faibussowitsch PetscErrorCode MatDenseRestoreColumnVecWrite_SeqDense(Mat A, PetscInt col, Vec *v)
3521d71ae5a4SJacob Faibussowitsch {
35226947451fSStefano Zampini   Mat_SeqDense *a = (Mat_SeqDense *)A->data;
35236947451fSStefano Zampini 
35246947451fSStefano Zampini   PetscFunctionBegin;
352528b400f6SJacob Faibussowitsch   PetscCheck(a->vecinuse, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Need to call MatDenseGetColumnVec() first");
352628b400f6SJacob Faibussowitsch   PetscCheck(a->cvec, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Missing internal column vector");
35274186a4bbSPierre Jolivet   VecCheckAssembled(a->cvec);
35286947451fSStefano Zampini   a->vecinuse = 0;
35299566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArrayWrite(A, (PetscScalar **)&a->ptrinuse));
35309566063dSJacob Faibussowitsch   PetscCall(VecResetArray(a->cvec));
353175f6d85dSStefano Zampini   if (v) *v = NULL;
35323ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
35336947451fSStefano Zampini }
35346947451fSStefano Zampini 
3535d71ae5a4SJacob Faibussowitsch PetscErrorCode MatDenseGetSubMatrix_SeqDense(Mat A, PetscInt rbegin, PetscInt rend, PetscInt cbegin, PetscInt cend, Mat *v)
3536d71ae5a4SJacob Faibussowitsch {
35375ea7661aSPierre Jolivet   Mat_SeqDense *a = (Mat_SeqDense *)A->data;
35385ea7661aSPierre Jolivet 
35395ea7661aSPierre Jolivet   PetscFunctionBegin;
354028b400f6SJacob Faibussowitsch   PetscCheck(!a->vecinuse, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Need to call MatDenseRestoreColumnVec() first");
354128b400f6SJacob Faibussowitsch   PetscCheck(!a->matinuse, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Need to call MatDenseRestoreSubMatrix() first");
3542a2748737SPierre Jolivet   if (a->cmat && (cend - cbegin != a->cmat->cmap->N || rend - rbegin != a->cmat->rmap->N)) PetscCall(MatDestroy(&a->cmat));
35435ea7661aSPierre Jolivet   if (!a->cmat) {
35448e3a54c0SPierre Jolivet     PetscCall(MatCreateDense(PetscObjectComm((PetscObject)A), rend - rbegin, PETSC_DECIDE, rend - rbegin, cend - cbegin, PetscSafePointerPlusOffset(a->v, rbegin + (size_t)cbegin * a->lda), &a->cmat));
35455ea7661aSPierre Jolivet   } else {
35468e3a54c0SPierre Jolivet     PetscCall(MatDensePlaceArray(a->cmat, PetscSafePointerPlusOffset(a->v, rbegin + (size_t)cbegin * a->lda)));
35475ea7661aSPierre Jolivet   }
35489566063dSJacob Faibussowitsch   PetscCall(MatDenseSetLDA(a->cmat, a->lda));
35495ea7661aSPierre Jolivet   a->matinuse = cbegin + 1;
35505ea7661aSPierre Jolivet   *v          = a->cmat;
355147d993e7Ssuyashtn #if defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
355275f6d85dSStefano Zampini   A->offloadmask = PETSC_OFFLOAD_CPU;
355375f6d85dSStefano Zampini #endif
35543ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
35555ea7661aSPierre Jolivet }
35565ea7661aSPierre Jolivet 
3557d71ae5a4SJacob Faibussowitsch PetscErrorCode MatDenseRestoreSubMatrix_SeqDense(Mat A, Mat *v)
3558d71ae5a4SJacob Faibussowitsch {
35595ea7661aSPierre Jolivet   Mat_SeqDense *a = (Mat_SeqDense *)A->data;
35605ea7661aSPierre Jolivet 
35615ea7661aSPierre Jolivet   PetscFunctionBegin;
356228b400f6SJacob Faibussowitsch   PetscCheck(a->matinuse, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Need to call MatDenseGetSubMatrix() first");
356328b400f6SJacob Faibussowitsch   PetscCheck(a->cmat, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Missing internal column matrix");
356408401ef6SPierre Jolivet   PetscCheck(*v == a->cmat, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Not the matrix obtained from MatDenseGetSubMatrix()");
35655ea7661aSPierre Jolivet   a->matinuse = 0;
35669566063dSJacob Faibussowitsch   PetscCall(MatDenseResetArray(a->cmat));
3567742765d3SMatthew Knepley   if (v) *v = NULL;
356847d993e7Ssuyashtn #if defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
35693faff063SStefano Zampini   A->offloadmask = PETSC_OFFLOAD_CPU;
35703faff063SStefano Zampini #endif
35713ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
35725ea7661aSPierre Jolivet }
35735ea7661aSPierre Jolivet 
35740bad9183SKris Buschelman /*MC
3575fafad747SKris Buschelman    MATSEQDENSE - MATSEQDENSE = "seqdense" - A matrix type to be used for sequential dense matrices.
35760bad9183SKris Buschelman 
35772ef1f0ffSBarry Smith    Options Database Key:
357811a5261eSBarry Smith . -mat_type seqdense - sets the matrix type to `MATSEQDENSE` during a call to `MatSetFromOptions()`
35790bad9183SKris Buschelman 
35800bad9183SKris Buschelman   Level: beginner
35810bad9183SKris Buschelman 
35821cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATSEQDENSE`, `MatCreateSeqDense()`
35830bad9183SKris Buschelman M*/
3584d71ae5a4SJacob Faibussowitsch PetscErrorCode MatCreate_SeqDense(Mat B)
3585d71ae5a4SJacob Faibussowitsch {
3586273d9f13SBarry Smith   Mat_SeqDense *b;
35877c334f02SBarry Smith   PetscMPIInt   size;
3588273d9f13SBarry Smith 
3589273d9f13SBarry Smith   PetscFunctionBegin;
35909566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)B), &size));
359108401ef6SPierre Jolivet   PetscCheck(size <= 1, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Comm must be of size 1");
359255659b69SBarry Smith 
35934dfa11a4SJacob Faibussowitsch   PetscCall(PetscNew(&b));
359444cd7ae7SLois Curfman McInnes   B->data   = (void *)b;
3595aea10558SJacob Faibussowitsch   B->ops[0] = MatOps_Values;
359618f449edSLois Curfman McInnes 
3597273d9f13SBarry Smith   b->roworiented = PETSC_TRUE;
35984e220ebcSLois Curfman McInnes 
35999566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatQRFactor_C", MatQRFactor_SeqDense));
36009566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatDenseGetLDA_C", MatDenseGetLDA_SeqDense));
36019566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatDenseSetLDA_C", MatDenseSetLDA_SeqDense));
36029566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatDenseGetArray_C", MatDenseGetArray_SeqDense));
36039566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatDenseRestoreArray_C", MatDenseRestoreArray_SeqDense));
36049566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatDensePlaceArray_C", MatDensePlaceArray_SeqDense));
36059566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatDenseResetArray_C", MatDenseResetArray_SeqDense));
36069566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatDenseReplaceArray_C", MatDenseReplaceArray_SeqDense));
36079566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatDenseGetArrayRead_C", MatDenseGetArray_SeqDense));
36089566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatDenseRestoreArrayRead_C", MatDenseRestoreArray_SeqDense));
36099566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatDenseGetArrayWrite_C", MatDenseGetArray_SeqDense));
36109566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatDenseRestoreArrayWrite_C", MatDenseRestoreArray_SeqDense));
36119566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatConvert_seqdense_seqaij_C", MatConvert_SeqDense_SeqAIJ));
36128baccfbdSHong Zhang #if defined(PETSC_HAVE_ELEMENTAL)
36139566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatConvert_seqdense_elemental_C", MatConvert_SeqDense_Elemental));
36148baccfbdSHong Zhang #endif
3615d24d4204SJose E. Roman #if defined(PETSC_HAVE_SCALAPACK)
36169566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatConvert_seqdense_scalapack_C", MatConvert_Dense_ScaLAPACK));
3617d24d4204SJose E. Roman #endif
36182bf066beSStefano Zampini #if defined(PETSC_HAVE_CUDA)
36199566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatConvert_seqdense_seqdensecuda_C", MatConvert_SeqDense_SeqDenseCUDA));
36209566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatProductSetFromOptions_seqdensecuda_seqdensecuda_C", MatProductSetFromOptions_SeqDense));
36219566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatProductSetFromOptions_seqdensecuda_seqdense_C", MatProductSetFromOptions_SeqDense));
36229566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatProductSetFromOptions_seqdense_seqdensecuda_C", MatProductSetFromOptions_SeqDense));
36232bf066beSStefano Zampini #endif
362447d993e7Ssuyashtn #if defined(PETSC_HAVE_HIP)
362547d993e7Ssuyashtn   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatConvert_seqdense_seqdensehip_C", MatConvert_SeqDense_SeqDenseHIP));
362647d993e7Ssuyashtn   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatProductSetFromOptions_seqdensehip_seqdensehip_C", MatProductSetFromOptions_SeqDense));
362747d993e7Ssuyashtn   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatProductSetFromOptions_seqdensehip_seqdense_C", MatProductSetFromOptions_SeqDense));
362847d993e7Ssuyashtn   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatProductSetFromOptions_seqdense_seqdensehip_C", MatProductSetFromOptions_SeqDense));
362947d993e7Ssuyashtn #endif
36309566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatSeqDenseSetPreallocation_C", MatSeqDenseSetPreallocation_SeqDense));
36319566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatProductSetFromOptions_seqaij_seqdense_C", MatProductSetFromOptions_SeqAIJ_SeqDense));
36329566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatProductSetFromOptions_seqdense_seqdense_C", MatProductSetFromOptions_SeqDense));
36339566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatProductSetFromOptions_seqbaij_seqdense_C", MatProductSetFromOptions_SeqXBAIJ_SeqDense));
36349566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatProductSetFromOptions_seqsbaij_seqdense_C", MatProductSetFromOptions_SeqXBAIJ_SeqDense));
363596e6d5c4SRichard Tran Mills 
36369566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatDenseGetColumn_C", MatDenseGetColumn_SeqDense));
36379566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatDenseRestoreColumn_C", MatDenseRestoreColumn_SeqDense));
36389566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatDenseGetColumnVec_C", MatDenseGetColumnVec_SeqDense));
36399566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatDenseRestoreColumnVec_C", MatDenseRestoreColumnVec_SeqDense));
36409566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatDenseGetColumnVecRead_C", MatDenseGetColumnVecRead_SeqDense));
36419566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatDenseRestoreColumnVecRead_C", MatDenseRestoreColumnVecRead_SeqDense));
36429566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatDenseGetColumnVecWrite_C", MatDenseGetColumnVecWrite_SeqDense));
36439566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatDenseRestoreColumnVecWrite_C", MatDenseRestoreColumnVecWrite_SeqDense));
36449566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatDenseGetSubMatrix_C", MatDenseGetSubMatrix_SeqDense));
36459566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatDenseRestoreSubMatrix_C", MatDenseRestoreSubMatrix_SeqDense));
3646*d016bddeSToby Isaac   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatMultColumnRange_C", MatMultColumnRange_SeqDense));
36470be0d8bdSHansol Suh   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatMultAddColumnRange_C", MatMultAddColumnRange_SeqDense));
36480be0d8bdSHansol Suh   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatMultHermitianTransposeColumnRange_C", MatMultHermitianTransposeColumnRange_SeqDense));
36490be0d8bdSHansol Suh   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatMultHermitianTransposeAddColumnRange_C", MatMultHermitianTransposeAddColumnRange_SeqDense));
36509566063dSJacob Faibussowitsch   PetscCall(PetscObjectChangeTypeName((PetscObject)B, MATSEQDENSE));
36513ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3652289bc588SBarry Smith }
365386aefd0dSHong Zhang 
365486aefd0dSHong Zhang /*@C
365511a5261eSBarry 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.
365686aefd0dSHong Zhang 
365786aefd0dSHong Zhang   Not Collective
365886aefd0dSHong Zhang 
36595ea7661aSPierre Jolivet   Input Parameters:
3660fe59aa6dSJacob Faibussowitsch + A   - a `MATSEQDENSE` or `MATMPIDENSE` matrix
366186aefd0dSHong Zhang - col - column index
366286aefd0dSHong Zhang 
366386aefd0dSHong Zhang   Output Parameter:
366486aefd0dSHong Zhang . vals - pointer to the data
366586aefd0dSHong Zhang 
366686aefd0dSHong Zhang   Level: intermediate
366786aefd0dSHong Zhang 
366811a5261eSBarry Smith   Note:
366911a5261eSBarry Smith   Use `MatDenseGetColumnVec()` to get access to a column of a `MATDENSE` treated as a `Vec`
367011a5261eSBarry Smith 
36711cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATDENSE`, `MatDenseRestoreColumn()`, `MatDenseGetColumnVec()`
367286aefd0dSHong Zhang @*/
36735d83a8b1SBarry Smith PetscErrorCode MatDenseGetColumn(Mat A, PetscInt col, PetscScalar *vals[])
3674d71ae5a4SJacob Faibussowitsch {
367586aefd0dSHong Zhang   PetscFunctionBegin;
3676d5ea218eSStefano Zampini   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
3677d5ea218eSStefano Zampini   PetscValidLogicalCollectiveInt(A, col, 2);
36784f572ea9SToby Isaac   PetscAssertPointer(vals, 3);
3679cac4c232SBarry Smith   PetscUseMethod(A, "MatDenseGetColumn_C", (Mat, PetscInt, PetscScalar **), (A, col, vals));
36803ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
368186aefd0dSHong Zhang }
368286aefd0dSHong Zhang 
368386aefd0dSHong Zhang /*@C
368411a5261eSBarry Smith   MatDenseRestoreColumn - returns access to a column of a `MATDENSE` matrix which is returned by `MatDenseGetColumn()`.
368586aefd0dSHong Zhang 
368686aefd0dSHong Zhang   Not Collective
368786aefd0dSHong Zhang 
3688742765d3SMatthew Knepley   Input Parameters:
3689fe59aa6dSJacob Faibussowitsch + A    - a `MATSEQDENSE` or `MATMPIDENSE` matrix
36902ef1f0ffSBarry Smith - vals - pointer to the data (may be `NULL`)
369186aefd0dSHong Zhang 
369286aefd0dSHong Zhang   Level: intermediate
369386aefd0dSHong Zhang 
36941cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATDENSE`, `MatDenseGetColumn()`
369586aefd0dSHong Zhang @*/
36965d83a8b1SBarry Smith PetscErrorCode MatDenseRestoreColumn(Mat A, PetscScalar *vals[])
3697d71ae5a4SJacob Faibussowitsch {
369886aefd0dSHong Zhang   PetscFunctionBegin;
3699d5ea218eSStefano Zampini   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
37004f572ea9SToby Isaac   PetscAssertPointer(vals, 2);
3701cac4c232SBarry Smith   PetscUseMethod(A, "MatDenseRestoreColumn_C", (Mat, PetscScalar **), (A, vals));
37023ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
370386aefd0dSHong Zhang }
37046947451fSStefano Zampini 
37050f74d2c1SSatish Balay /*@
370611a5261eSBarry Smith   MatDenseGetColumnVec - Gives read-write access to a column of a `MATDENSE` matrix, represented as a `Vec`.
37076947451fSStefano Zampini 
37086947451fSStefano Zampini   Collective
37096947451fSStefano Zampini 
37105ea7661aSPierre Jolivet   Input Parameters:
3711fe59aa6dSJacob Faibussowitsch + A   - the `Mat` object
37126947451fSStefano Zampini - col - the column index
37136947451fSStefano Zampini 
37146947451fSStefano Zampini   Output Parameter:
37156947451fSStefano Zampini . v - the vector
37166947451fSStefano Zampini 
37172ef1f0ffSBarry Smith   Level: intermediate
37182ef1f0ffSBarry Smith 
37196947451fSStefano Zampini   Notes:
372011a5261eSBarry Smith   The vector is owned by PETSc. Users need to call `MatDenseRestoreColumnVec()` when the vector is no longer needed.
372111a5261eSBarry Smith 
372211a5261eSBarry Smith   Use `MatDenseGetColumnVecRead()` to obtain read-only access or `MatDenseGetColumnVecWrite()` for write-only access.
37236947451fSStefano Zampini 
37241cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATDENSE`, `MATDENSECUDA`, `MATDENSEHIP`, `MatDenseGetColumnVecRead()`, `MatDenseGetColumnVecWrite()`, `MatDenseRestoreColumnVec()`, `MatDenseRestoreColumnVecRead()`, `MatDenseRestoreColumnVecWrite()`, `MatDenseGetColumn()`
37256947451fSStefano Zampini @*/
3726d71ae5a4SJacob Faibussowitsch PetscErrorCode MatDenseGetColumnVec(Mat A, PetscInt col, Vec *v)
3727d71ae5a4SJacob Faibussowitsch {
37286947451fSStefano Zampini   PetscFunctionBegin;
37296947451fSStefano Zampini   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
37306947451fSStefano Zampini   PetscValidType(A, 1);
37316947451fSStefano Zampini   PetscValidLogicalCollectiveInt(A, col, 2);
37324f572ea9SToby Isaac   PetscAssertPointer(v, 3);
373328b400f6SJacob Faibussowitsch   PetscCheck(A->preallocated, PetscObjectComm((PetscObject)A), PETSC_ERR_ORDER, "Matrix not preallocated");
37342cf15c64SPierre 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);
3735cac4c232SBarry Smith   PetscUseMethod(A, "MatDenseGetColumnVec_C", (Mat, PetscInt, Vec *), (A, col, v));
37363ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
37376947451fSStefano Zampini }
37386947451fSStefano Zampini 
37390f74d2c1SSatish Balay /*@
3740fb850c59SBarry Smith   MatDenseRestoreColumnVec - Returns access to a column of a dense matrix obtained from `MatDenseGetColumnVec()`.
37416947451fSStefano Zampini 
37426947451fSStefano Zampini   Collective
37436947451fSStefano Zampini 
37445ea7661aSPierre Jolivet   Input Parameters:
3745fb850c59SBarry Smith + A   - the `Mat` object
37466947451fSStefano Zampini . col - the column index
3747fb850c59SBarry Smith - v   - the `Vec` object (may be `NULL`)
37486947451fSStefano Zampini 
37496947451fSStefano Zampini   Level: intermediate
37506947451fSStefano Zampini 
37511cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATDENSE`, `MATDENSECUDA`, `MATDENSEHIP`, `MatDenseGetColumnVec()`, `MatDenseGetColumnVecRead()`, `MatDenseGetColumnVecWrite()`, `MatDenseRestoreColumnVecRead()`, `MatDenseRestoreColumnVecWrite()`
37526947451fSStefano Zampini @*/
3753d71ae5a4SJacob Faibussowitsch PetscErrorCode MatDenseRestoreColumnVec(Mat A, PetscInt col, Vec *v)
3754d71ae5a4SJacob Faibussowitsch {
37556947451fSStefano Zampini   PetscFunctionBegin;
37566947451fSStefano Zampini   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
37576947451fSStefano Zampini   PetscValidType(A, 1);
37586947451fSStefano Zampini   PetscValidLogicalCollectiveInt(A, col, 2);
375908401ef6SPierre Jolivet   PetscCheck(A->preallocated, PetscObjectComm((PetscObject)A), PETSC_ERR_ORDER, "Matrix not preallocated");
37602cf15c64SPierre 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);
3761cac4c232SBarry Smith   PetscUseMethod(A, "MatDenseRestoreColumnVec_C", (Mat, PetscInt, Vec *), (A, col, v));
37623ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
37636947451fSStefano Zampini }
37646947451fSStefano Zampini 
37650f74d2c1SSatish Balay /*@
3766fb850c59SBarry Smith   MatDenseGetColumnVecRead - Gives read-only access to a column of a dense matrix, represented as a `Vec`.
37676947451fSStefano Zampini 
37686947451fSStefano Zampini   Collective
37696947451fSStefano Zampini 
37705ea7661aSPierre Jolivet   Input Parameters:
3771fe59aa6dSJacob Faibussowitsch + A   - the `Mat` object
37726947451fSStefano Zampini - col - the column index
37736947451fSStefano Zampini 
37746947451fSStefano Zampini   Output Parameter:
37756947451fSStefano Zampini . v - the vector
37766947451fSStefano Zampini 
37772ef1f0ffSBarry Smith   Level: intermediate
37782ef1f0ffSBarry Smith 
37796947451fSStefano Zampini   Notes:
37806947451fSStefano Zampini   The vector is owned by PETSc and users cannot modify it.
378111a5261eSBarry Smith 
37822ef1f0ffSBarry Smith   Users need to call `MatDenseRestoreColumnVecRead()` when the vector is no longer needed.
378311a5261eSBarry Smith 
37842ef1f0ffSBarry Smith   Use `MatDenseGetColumnVec()` to obtain read-write access or `MatDenseGetColumnVecWrite()` for write-only access.
37856947451fSStefano Zampini 
37861cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATDENSE`, `MATDENSECUDA`, `MATDENSEHIP`, `MatDenseGetColumnVec()`, `MatDenseGetColumnVecWrite()`, `MatDenseRestoreColumnVec()`, `MatDenseRestoreColumnVecRead()`, `MatDenseRestoreColumnVecWrite()`
37876947451fSStefano Zampini @*/
3788d71ae5a4SJacob Faibussowitsch PetscErrorCode MatDenseGetColumnVecRead(Mat A, PetscInt col, Vec *v)
3789d71ae5a4SJacob Faibussowitsch {
37906947451fSStefano Zampini   PetscFunctionBegin;
37916947451fSStefano Zampini   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
37926947451fSStefano Zampini   PetscValidType(A, 1);
37936947451fSStefano Zampini   PetscValidLogicalCollectiveInt(A, col, 2);
37944f572ea9SToby Isaac   PetscAssertPointer(v, 3);
379528b400f6SJacob Faibussowitsch   PetscCheck(A->preallocated, PetscObjectComm((PetscObject)A), PETSC_ERR_ORDER, "Matrix not preallocated");
37962cf15c64SPierre 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);
3797cac4c232SBarry Smith   PetscUseMethod(A, "MatDenseGetColumnVecRead_C", (Mat, PetscInt, Vec *), (A, col, v));
37983ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
37996947451fSStefano Zampini }
38006947451fSStefano Zampini 
38010f74d2c1SSatish Balay /*@
3802fb850c59SBarry Smith   MatDenseRestoreColumnVecRead - Returns access to a column of a dense matrix obtained from `MatDenseGetColumnVecRead()`.
38036947451fSStefano Zampini 
38046947451fSStefano Zampini   Collective
38056947451fSStefano Zampini 
38065ea7661aSPierre Jolivet   Input Parameters:
3807fe59aa6dSJacob Faibussowitsch + A   - the `Mat` object
38086947451fSStefano Zampini . col - the column index
3809fb850c59SBarry Smith - v   - the `Vec` object (may be `NULL`)
38106947451fSStefano Zampini 
38116947451fSStefano Zampini   Level: intermediate
38126947451fSStefano Zampini 
38131cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATDENSE`, `MATDENSECUDA`, `MATDENSEHIP`, `MatDenseGetColumnVec()`, `MatDenseGetColumnVecRead()`, `MatDenseGetColumnVecWrite()`, `MatDenseRestoreColumnVec()`, `MatDenseRestoreColumnVecWrite()`
38146947451fSStefano Zampini @*/
3815d71ae5a4SJacob Faibussowitsch PetscErrorCode MatDenseRestoreColumnVecRead(Mat A, PetscInt col, Vec *v)
3816d71ae5a4SJacob Faibussowitsch {
38176947451fSStefano Zampini   PetscFunctionBegin;
38186947451fSStefano Zampini   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
38196947451fSStefano Zampini   PetscValidType(A, 1);
38206947451fSStefano Zampini   PetscValidLogicalCollectiveInt(A, col, 2);
382108401ef6SPierre Jolivet   PetscCheck(A->preallocated, PetscObjectComm((PetscObject)A), PETSC_ERR_ORDER, "Matrix not preallocated");
38222cf15c64SPierre 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);
3823cac4c232SBarry Smith   PetscUseMethod(A, "MatDenseRestoreColumnVecRead_C", (Mat, PetscInt, Vec *), (A, col, v));
38243ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
38256947451fSStefano Zampini }
38266947451fSStefano Zampini 
38270f74d2c1SSatish Balay /*@
3828fb850c59SBarry Smith   MatDenseGetColumnVecWrite - Gives write-only access to a column of a dense matrix, represented as a `Vec`.
38296947451fSStefano Zampini 
38306947451fSStefano Zampini   Collective
38316947451fSStefano Zampini 
38325ea7661aSPierre Jolivet   Input Parameters:
3833fe59aa6dSJacob Faibussowitsch + A   - the `Mat` object
38346947451fSStefano Zampini - col - the column index
38356947451fSStefano Zampini 
38366947451fSStefano Zampini   Output Parameter:
38376947451fSStefano Zampini . v - the vector
38386947451fSStefano Zampini 
38396947451fSStefano Zampini   Level: intermediate
38406947451fSStefano Zampini 
38412ef1f0ffSBarry Smith   Notes:
38422ef1f0ffSBarry Smith   The vector is owned by PETSc. Users need to call `MatDenseRestoreColumnVecWrite()` when the vector is no longer needed.
38432ef1f0ffSBarry Smith 
38442ef1f0ffSBarry Smith   Use `MatDenseGetColumnVec()` to obtain read-write access or `MatDenseGetColumnVecRead()` for read-only access.
38452ef1f0ffSBarry Smith 
38461cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATDENSE`, `MATDENSECUDA`, `MATDENSEHIP`, `MatDenseGetColumnVec()`, `MatDenseGetColumnVecRead()`, `MatDenseRestoreColumnVec()`, `MatDenseRestoreColumnVecRead()`, `MatDenseRestoreColumnVecWrite()`
38476947451fSStefano Zampini @*/
3848d71ae5a4SJacob Faibussowitsch PetscErrorCode MatDenseGetColumnVecWrite(Mat A, PetscInt col, Vec *v)
3849d71ae5a4SJacob Faibussowitsch {
38506947451fSStefano Zampini   PetscFunctionBegin;
38516947451fSStefano Zampini   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
38526947451fSStefano Zampini   PetscValidType(A, 1);
38536947451fSStefano Zampini   PetscValidLogicalCollectiveInt(A, col, 2);
38544f572ea9SToby Isaac   PetscAssertPointer(v, 3);
385528b400f6SJacob Faibussowitsch   PetscCheck(A->preallocated, PetscObjectComm((PetscObject)A), PETSC_ERR_ORDER, "Matrix not preallocated");
3856aed4548fSBarry 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);
3857cac4c232SBarry Smith   PetscUseMethod(A, "MatDenseGetColumnVecWrite_C", (Mat, PetscInt, Vec *), (A, col, v));
38583ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
38596947451fSStefano Zampini }
38606947451fSStefano Zampini 
38610f74d2c1SSatish Balay /*@
3862fb850c59SBarry Smith   MatDenseRestoreColumnVecWrite - Returns access to a column of a dense matrix obtained from `MatDenseGetColumnVecWrite()`.
38636947451fSStefano Zampini 
38646947451fSStefano Zampini   Collective
38656947451fSStefano Zampini 
38665ea7661aSPierre Jolivet   Input Parameters:
3867fe59aa6dSJacob Faibussowitsch + A   - the `Mat` object
38686947451fSStefano Zampini . col - the column index
38692ef1f0ffSBarry Smith - v   - the `Vec` object (may be `NULL`)
38706947451fSStefano Zampini 
38716947451fSStefano Zampini   Level: intermediate
38726947451fSStefano Zampini 
38731cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATDENSE`, `MATDENSECUDA`, `MATDENSEHIP`, `MatDenseGetColumnVec()`, `MatDenseGetColumnVecRead()`, `MatDenseGetColumnVecWrite()`, `MatDenseRestoreColumnVec()`, `MatDenseRestoreColumnVecRead()`
38746947451fSStefano Zampini @*/
3875d71ae5a4SJacob Faibussowitsch PetscErrorCode MatDenseRestoreColumnVecWrite(Mat A, PetscInt col, Vec *v)
3876d71ae5a4SJacob Faibussowitsch {
38776947451fSStefano Zampini   PetscFunctionBegin;
38786947451fSStefano Zampini   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
38796947451fSStefano Zampini   PetscValidType(A, 1);
38806947451fSStefano Zampini   PetscValidLogicalCollectiveInt(A, col, 2);
388108401ef6SPierre Jolivet   PetscCheck(A->preallocated, PetscObjectComm((PetscObject)A), PETSC_ERR_ORDER, "Matrix not preallocated");
3882aed4548fSBarry 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);
3883cac4c232SBarry Smith   PetscUseMethod(A, "MatDenseRestoreColumnVecWrite_C", (Mat, PetscInt, Vec *), (A, col, v));
38843ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
38856947451fSStefano Zampini }
38865ea7661aSPierre Jolivet 
38870f74d2c1SSatish Balay /*@
3888fb850c59SBarry Smith   MatDenseGetSubMatrix - Gives access to a block of rows and columns of a dense matrix, represented as a `Mat`.
38895ea7661aSPierre Jolivet 
38905ea7661aSPierre Jolivet   Collective
38915ea7661aSPierre Jolivet 
38925ea7661aSPierre Jolivet   Input Parameters:
3893fb850c59SBarry Smith + A      - the `Mat` object
38942ef1f0ffSBarry Smith . rbegin - the first global row index in the block (if `PETSC_DECIDE`, is 0)
38952ef1f0ffSBarry Smith . rend   - the global row index past the last one in the block (if `PETSC_DECIDE`, is `M`)
38962ef1f0ffSBarry Smith . cbegin - the first global column index in the block (if `PETSC_DECIDE`, is 0)
38972ef1f0ffSBarry Smith - cend   - the global column index past the last one in the block (if `PETSC_DECIDE`, is `N`)
38985ea7661aSPierre Jolivet 
38995ea7661aSPierre Jolivet   Output Parameter:
39005ea7661aSPierre Jolivet . v - the matrix
39015ea7661aSPierre Jolivet 
39025ea7661aSPierre Jolivet   Level: intermediate
39035ea7661aSPierre Jolivet 
39042ef1f0ffSBarry Smith   Notes:
39052ef1f0ffSBarry Smith   The matrix is owned by PETSc. Users need to call `MatDenseRestoreSubMatrix()` when the matrix is no longer needed.
39062ef1f0ffSBarry Smith 
39072ef1f0ffSBarry 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.
39082ef1f0ffSBarry Smith 
39091cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATDENSE`, `MATDENSECUDA`, `MATDENSEHIP`, `MatDenseGetColumnVec()`, `MatDenseRestoreColumnVec()`, `MatDenseRestoreSubMatrix()`
39105ea7661aSPierre Jolivet @*/
3911d71ae5a4SJacob Faibussowitsch PetscErrorCode MatDenseGetSubMatrix(Mat A, PetscInt rbegin, PetscInt rend, PetscInt cbegin, PetscInt cend, Mat *v)
3912d71ae5a4SJacob Faibussowitsch {
39135ea7661aSPierre Jolivet   PetscFunctionBegin;
39145ea7661aSPierre Jolivet   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
39155ea7661aSPierre Jolivet   PetscValidType(A, 1);
3916a2748737SPierre Jolivet   PetscValidLogicalCollectiveInt(A, rbegin, 2);
3917a2748737SPierre Jolivet   PetscValidLogicalCollectiveInt(A, rend, 3);
3918a2748737SPierre Jolivet   PetscValidLogicalCollectiveInt(A, cbegin, 4);
3919a2748737SPierre Jolivet   PetscValidLogicalCollectiveInt(A, cend, 5);
39204f572ea9SToby Isaac   PetscAssertPointer(v, 6);
3921a2748737SPierre Jolivet   if (rbegin == PETSC_DECIDE) rbegin = 0;
3922a2748737SPierre Jolivet   if (rend == PETSC_DECIDE) rend = A->rmap->N;
3923a2748737SPierre Jolivet   if (cbegin == PETSC_DECIDE) cbegin = 0;
3924a2748737SPierre Jolivet   if (cend == PETSC_DECIDE) cend = A->cmap->N;
392528b400f6SJacob Faibussowitsch   PetscCheck(A->preallocated, PetscObjectComm((PetscObject)A), PETSC_ERR_ORDER, "Matrix not preallocated");
3926a2748737SPierre 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);
3927a2748737SPierre 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);
3928a2748737SPierre 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);
3929a2748737SPierre 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);
3930a2748737SPierre Jolivet   PetscUseMethod(A, "MatDenseGetSubMatrix_C", (Mat, PetscInt, PetscInt, PetscInt, PetscInt, Mat *), (A, rbegin, rend, cbegin, cend, v));
39313ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
39325ea7661aSPierre Jolivet }
39335ea7661aSPierre Jolivet 
39340f74d2c1SSatish Balay /*@
3935fb850c59SBarry Smith   MatDenseRestoreSubMatrix - Returns access to a block of columns of a dense matrix obtained from `MatDenseGetSubMatrix()`.
39365ea7661aSPierre Jolivet 
39375ea7661aSPierre Jolivet   Collective
39385ea7661aSPierre Jolivet 
39395ea7661aSPierre Jolivet   Input Parameters:
3940fe59aa6dSJacob Faibussowitsch + A - the `Mat` object
39412ef1f0ffSBarry Smith - v - the `Mat` object (may be `NULL`)
39425ea7661aSPierre Jolivet 
39435ea7661aSPierre Jolivet   Level: intermediate
39445ea7661aSPierre Jolivet 
39451cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATDENSE`, `MATDENSECUDA`, `MATDENSEHIP`, `MatDenseGetColumnVec()`, `MatDenseRestoreColumnVec()`, `MatDenseGetSubMatrix()`
39465ea7661aSPierre Jolivet @*/
3947d71ae5a4SJacob Faibussowitsch PetscErrorCode MatDenseRestoreSubMatrix(Mat A, Mat *v)
3948d71ae5a4SJacob Faibussowitsch {
39495ea7661aSPierre Jolivet   PetscFunctionBegin;
39505ea7661aSPierre Jolivet   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
39515ea7661aSPierre Jolivet   PetscValidType(A, 1);
39524f572ea9SToby Isaac   PetscAssertPointer(v, 2);
3953cac4c232SBarry Smith   PetscUseMethod(A, "MatDenseRestoreSubMatrix_C", (Mat, Mat *), (A, v));
39543ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
39555ea7661aSPierre Jolivet }
39568a9c020eSBarry Smith 
39578a9c020eSBarry Smith #include <petscblaslapack.h>
39588a9c020eSBarry Smith #include <petsc/private/kernels/blockinvert.h>
39598a9c020eSBarry Smith 
3960d71ae5a4SJacob Faibussowitsch PetscErrorCode MatSeqDenseInvert(Mat A)
3961d71ae5a4SJacob Faibussowitsch {
3962d63b1753SJacob Faibussowitsch   PetscInt        m;
39638a9c020eSBarry Smith   const PetscReal shift = 0.0;
3964d63b1753SJacob Faibussowitsch   PetscBool       allowzeropivot, zeropivotdetected = PETSC_FALSE;
3965d63b1753SJacob Faibussowitsch   PetscScalar    *values;
39668a9c020eSBarry Smith 
39678a9c020eSBarry Smith   PetscFunctionBegin;
3968d63b1753SJacob Faibussowitsch   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
3969d63b1753SJacob Faibussowitsch   PetscCall(MatDenseGetArray(A, &values));
3970d63b1753SJacob Faibussowitsch   PetscCall(MatGetLocalSize(A, &m, NULL));
3971d63b1753SJacob Faibussowitsch   allowzeropivot = PetscNot(A->erroriffailure);
39728a9c020eSBarry Smith   /* factor and invert each block */
3973d63b1753SJacob Faibussowitsch   switch (m) {
3974d71ae5a4SJacob Faibussowitsch   case 1:
3975d71ae5a4SJacob Faibussowitsch     values[0] = (PetscScalar)1.0 / (values[0] + shift);
3976d71ae5a4SJacob Faibussowitsch     break;
39778a9c020eSBarry Smith   case 2:
39788a9c020eSBarry Smith     PetscCall(PetscKernel_A_gets_inverse_A_2(values, shift, allowzeropivot, &zeropivotdetected));
39798a9c020eSBarry Smith     if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
39808a9c020eSBarry Smith     break;
39818a9c020eSBarry Smith   case 3:
39828a9c020eSBarry Smith     PetscCall(PetscKernel_A_gets_inverse_A_3(values, shift, allowzeropivot, &zeropivotdetected));
39838a9c020eSBarry Smith     if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
39848a9c020eSBarry Smith     break;
39858a9c020eSBarry Smith   case 4:
39868a9c020eSBarry Smith     PetscCall(PetscKernel_A_gets_inverse_A_4(values, shift, allowzeropivot, &zeropivotdetected));
39878a9c020eSBarry Smith     if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
39888a9c020eSBarry Smith     break;
39899371c9d4SSatish Balay   case 5: {
39908a9c020eSBarry Smith     PetscScalar work[25];
39918a9c020eSBarry Smith     PetscInt    ipvt[5];
39928a9c020eSBarry Smith 
39938a9c020eSBarry Smith     PetscCall(PetscKernel_A_gets_inverse_A_5(values, ipvt, work, shift, allowzeropivot, &zeropivotdetected));
39948a9c020eSBarry Smith     if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
39959371c9d4SSatish Balay   } break;
39968a9c020eSBarry Smith   case 6:
39978a9c020eSBarry Smith     PetscCall(PetscKernel_A_gets_inverse_A_6(values, shift, allowzeropivot, &zeropivotdetected));
39988a9c020eSBarry Smith     if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
39998a9c020eSBarry Smith     break;
40008a9c020eSBarry Smith   case 7:
40018a9c020eSBarry Smith     PetscCall(PetscKernel_A_gets_inverse_A_7(values, shift, allowzeropivot, &zeropivotdetected));
40028a9c020eSBarry Smith     if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
40038a9c020eSBarry Smith     break;
40049371c9d4SSatish Balay   default: {
40058a9c020eSBarry Smith     PetscInt    *v_pivots, *IJ, j;
40068a9c020eSBarry Smith     PetscScalar *v_work;
40078a9c020eSBarry Smith 
4008d63b1753SJacob Faibussowitsch     PetscCall(PetscMalloc3(m, &v_work, m, &v_pivots, m, &IJ));
4009d63b1753SJacob Faibussowitsch     for (j = 0; j < m; j++) IJ[j] = j;
4010d63b1753SJacob Faibussowitsch     PetscCall(PetscKernel_A_gets_inverse_A(m, values, v_pivots, v_work, allowzeropivot, &zeropivotdetected));
40118a9c020eSBarry Smith     if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
40128a9c020eSBarry Smith     PetscCall(PetscFree3(v_work, v_pivots, IJ));
40138a9c020eSBarry Smith   }
40148a9c020eSBarry Smith   }
4015d63b1753SJacob Faibussowitsch   PetscCall(MatDenseRestoreArray(A, &values));
40163ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
40178a9c020eSBarry Smith }
4018