xref: /petsc/src/mat/impls/dense/seq/dense.c (revision fd5c2d83f005b51d832c5005170af290f2bb23a9)
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 
4174396437dSToby Isaac static PetscErrorCode MatConjugate_SeqDense(Mat);
4184396437dSToby Isaac 
419d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatSolve_SeqDense_Internal_Cholesky(Mat A, PetscScalar *x, PetscBLASInt ldx, PetscBLASInt m, PetscBLASInt nrhs, PetscBLASInt k, PetscBool T)
420d71ae5a4SJacob Faibussowitsch {
4214396437dSToby Isaac   Mat_SeqDense *mat = (Mat_SeqDense *)A->data;
4224396437dSToby Isaac   PetscBLASInt  info;
4234396437dSToby Isaac 
4244396437dSToby Isaac   PetscFunctionBegin;
425b94d7dedSBarry Smith   if (A->spd == PETSC_BOOL3_TRUE) {
4269566063dSJacob Faibussowitsch     if (PetscDefined(USE_COMPLEX) && T) PetscCall(MatConjugate_SeqDense(A));
4279566063dSJacob Faibussowitsch     PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF));
428792fecdfSBarry Smith     PetscCallBLAS("LAPACKpotrs", LAPACKpotrs_("L", &m, &nrhs, mat->v, &mat->lda, x, &m, &info));
4299566063dSJacob Faibussowitsch     PetscCall(PetscFPTrapPop());
430835f2295SStefano Zampini     PetscCheck(!info, PETSC_COMM_SELF, PETSC_ERR_LIB, "POTRS Bad solve %" PetscBLASInt_FMT, info);
4319566063dSJacob Faibussowitsch     if (PetscDefined(USE_COMPLEX) && T) PetscCall(MatConjugate_SeqDense(A));
432a49dc2a2SStefano Zampini #if defined(PETSC_USE_COMPLEX)
433b94d7dedSBarry Smith   } else if (A->hermitian == PETSC_BOOL3_TRUE) {
4349566063dSJacob Faibussowitsch     if (T) PetscCall(MatConjugate_SeqDense(A));
4359566063dSJacob Faibussowitsch     PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF));
436792fecdfSBarry Smith     PetscCallBLAS("LAPACKhetrs", LAPACKhetrs_("L", &m, &nrhs, mat->v, &mat->lda, mat->pivots, x, &m, &info));
4379566063dSJacob Faibussowitsch     PetscCall(PetscFPTrapPop());
438835f2295SStefano Zampini     PetscCheck(!info, PETSC_COMM_SELF, PETSC_ERR_LIB, "HETRS Bad solve %" PetscBLASInt_FMT, info);
4399566063dSJacob Faibussowitsch     if (T) PetscCall(MatConjugate_SeqDense(A));
440a49dc2a2SStefano Zampini #endif
441a49dc2a2SStefano Zampini   } else { /* symmetric case */
4429566063dSJacob Faibussowitsch     PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF));
443792fecdfSBarry Smith     PetscCallBLAS("LAPACKsytrs", LAPACKsytrs_("L", &m, &nrhs, mat->v, &mat->lda, mat->pivots, x, &m, &info));
4449566063dSJacob Faibussowitsch     PetscCall(PetscFPTrapPop());
445835f2295SStefano Zampini     PetscCheck(!info, PETSC_COMM_SELF, PETSC_ERR_LIB, "SYTRS Bad solve %" PetscBLASInt_FMT, info);
446a49dc2a2SStefano Zampini   }
4479566063dSJacob Faibussowitsch   PetscCall(PetscLogFlops(nrhs * (2.0 * m * m - m)));
4483ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4494396437dSToby Isaac }
45085e2c93fSHong Zhang 
451d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatSolve_SeqDense_Internal_QR(Mat A, PetscScalar *x, PetscBLASInt ldx, PetscBLASInt m, PetscBLASInt nrhs, PetscBLASInt k)
452d71ae5a4SJacob Faibussowitsch {
4534396437dSToby Isaac   Mat_SeqDense *mat = (Mat_SeqDense *)A->data;
4544396437dSToby Isaac   PetscBLASInt  info;
4554396437dSToby Isaac   char          trans;
4564396437dSToby Isaac 
4574396437dSToby Isaac   PetscFunctionBegin;
4584905a7bcSToby Isaac   if (PetscDefined(USE_COMPLEX)) {
4594905a7bcSToby Isaac     trans = 'C';
4604905a7bcSToby Isaac   } else {
4614905a7bcSToby Isaac     trans = 'T';
4624905a7bcSToby Isaac   }
4639566063dSJacob Faibussowitsch   PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF));
46405fcb23eSStefano Zampini   { /* lwork depends on the number of right-hand sides */
46505fcb23eSStefano Zampini     PetscBLASInt nlfwork, lfwork = -1;
46605fcb23eSStefano Zampini     PetscScalar  fwork;
46705fcb23eSStefano Zampini 
468792fecdfSBarry Smith     PetscCallBLAS("LAPACKormqr", LAPACKormqr_("L", &trans, &m, &nrhs, &mat->rank, mat->v, &mat->lda, mat->tau, x, &ldx, &fwork, &lfwork, &info));
46905fcb23eSStefano Zampini     nlfwork = (PetscBLASInt)PetscRealPart(fwork);
47005fcb23eSStefano Zampini     if (nlfwork > mat->lfwork) {
47105fcb23eSStefano Zampini       mat->lfwork = nlfwork;
47205fcb23eSStefano Zampini       PetscCall(PetscFree(mat->fwork));
47305fcb23eSStefano Zampini       PetscCall(PetscMalloc1(mat->lfwork, &mat->fwork));
47405fcb23eSStefano Zampini     }
47505fcb23eSStefano Zampini   }
476792fecdfSBarry Smith   PetscCallBLAS("LAPACKormqr", LAPACKormqr_("L", &trans, &m, &nrhs, &mat->rank, mat->v, &mat->lda, mat->tau, x, &ldx, mat->fwork, &mat->lfwork, &info));
4779566063dSJacob Faibussowitsch   PetscCall(PetscFPTrapPop());
478835f2295SStefano Zampini   PetscCheck(!info, PETSC_COMM_SELF, PETSC_ERR_LIB, "ORMQR - Bad orthogonal transform %" PetscBLASInt_FMT, info);
4799566063dSJacob Faibussowitsch   PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF));
480792fecdfSBarry Smith   PetscCallBLAS("LAPACKtrtrs", LAPACKtrtrs_("U", "N", "N", &mat->rank, &nrhs, mat->v, &mat->lda, x, &ldx, &info));
4819566063dSJacob Faibussowitsch   PetscCall(PetscFPTrapPop());
482835f2295SStefano Zampini   PetscCheck(!info, PETSC_COMM_SELF, PETSC_ERR_LIB, "TRTRS - Bad triangular solve %" PetscBLASInt_FMT, info);
4834905a7bcSToby Isaac   for (PetscInt j = 0; j < nrhs; j++) {
484ad540459SPierre Jolivet     for (PetscInt i = mat->rank; i < k; i++) x[j * ldx + i] = 0.;
4854905a7bcSToby Isaac   }
4869566063dSJacob Faibussowitsch   PetscCall(PetscLogFlops(nrhs * (4.0 * m * mat->rank - PetscSqr(mat->rank))));
4873ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4884905a7bcSToby Isaac }
4894905a7bcSToby Isaac 
490d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatSolveTranspose_SeqDense_Internal_QR(Mat A, PetscScalar *x, PetscBLASInt ldx, PetscBLASInt m, PetscBLASInt nrhs, PetscBLASInt k)
491d71ae5a4SJacob Faibussowitsch {
4924396437dSToby Isaac   Mat_SeqDense *mat = (Mat_SeqDense *)A->data;
4934396437dSToby Isaac   PetscBLASInt  info;
4944396437dSToby Isaac 
4954396437dSToby Isaac   PetscFunctionBegin;
4964396437dSToby Isaac   if (A->rmap->n == A->cmap->n && mat->rank == A->rmap->n) {
4979566063dSJacob Faibussowitsch     PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF));
498792fecdfSBarry Smith     PetscCallBLAS("LAPACKtrtrs", LAPACKtrtrs_("U", "T", "N", &m, &nrhs, mat->v, &mat->lda, x, &ldx, &info));
4999566063dSJacob Faibussowitsch     PetscCall(PetscFPTrapPop());
500835f2295SStefano Zampini     PetscCheck(!info, PETSC_COMM_SELF, PETSC_ERR_LIB, "TRTRS - Bad triangular solve %" PetscBLASInt_FMT, info);
5019566063dSJacob Faibussowitsch     if (PetscDefined(USE_COMPLEX)) PetscCall(MatConjugate_SeqDense(A));
50205fcb23eSStefano Zampini     { /* lwork depends on the number of right-hand sides */
50305fcb23eSStefano Zampini       PetscBLASInt nlfwork, lfwork = -1;
50405fcb23eSStefano Zampini       PetscScalar  fwork;
50505fcb23eSStefano Zampini 
506792fecdfSBarry Smith       PetscCallBLAS("LAPACKormqr", LAPACKormqr_("L", "N", &m, &nrhs, &mat->rank, mat->v, &mat->lda, mat->tau, x, &ldx, &fwork, &lfwork, &info));
50705fcb23eSStefano Zampini       nlfwork = (PetscBLASInt)PetscRealPart(fwork);
50805fcb23eSStefano Zampini       if (nlfwork > mat->lfwork) {
50905fcb23eSStefano Zampini         mat->lfwork = nlfwork;
51005fcb23eSStefano Zampini         PetscCall(PetscFree(mat->fwork));
51105fcb23eSStefano Zampini         PetscCall(PetscMalloc1(mat->lfwork, &mat->fwork));
51205fcb23eSStefano Zampini       }
51305fcb23eSStefano Zampini     }
5149566063dSJacob Faibussowitsch     PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF));
515792fecdfSBarry Smith     PetscCallBLAS("LAPACKormqr", LAPACKormqr_("L", "N", &m, &nrhs, &mat->rank, mat->v, &mat->lda, mat->tau, x, &ldx, mat->fwork, &mat->lfwork, &info));
5169566063dSJacob Faibussowitsch     PetscCall(PetscFPTrapPop());
517835f2295SStefano Zampini     PetscCheck(!info, PETSC_COMM_SELF, PETSC_ERR_LIB, "ORMQR - Bad orthogonal transform %" PetscBLASInt_FMT, info);
5189566063dSJacob Faibussowitsch     if (PetscDefined(USE_COMPLEX)) PetscCall(MatConjugate_SeqDense(A));
5194396437dSToby Isaac   } else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "QR factored matrix cannot be used for transpose solve");
5209566063dSJacob Faibussowitsch   PetscCall(PetscLogFlops(nrhs * (4.0 * m * mat->rank - PetscSqr(mat->rank))));
5213ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5224396437dSToby Isaac }
5234396437dSToby Isaac 
524d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatSolve_SeqDense_SetUp(Mat A, Vec xx, Vec yy, PetscScalar **_y, PetscBLASInt *_m, PetscBLASInt *_k)
525d71ae5a4SJacob Faibussowitsch {
5264396437dSToby Isaac   Mat_SeqDense *mat = (Mat_SeqDense *)A->data;
5274905a7bcSToby Isaac   PetscScalar  *y;
5284905a7bcSToby Isaac   PetscBLASInt  m = 0, k = 0;
5294905a7bcSToby Isaac 
5304905a7bcSToby Isaac   PetscFunctionBegin;
5319566063dSJacob Faibussowitsch   PetscCall(PetscBLASIntCast(A->rmap->n, &m));
5329566063dSJacob Faibussowitsch   PetscCall(PetscBLASIntCast(A->cmap->n, &k));
5334905a7bcSToby Isaac   if (k < m) {
5349566063dSJacob Faibussowitsch     PetscCall(VecCopy(xx, mat->qrrhs));
5359566063dSJacob Faibussowitsch     PetscCall(VecGetArray(mat->qrrhs, &y));
5364905a7bcSToby Isaac   } else {
5379566063dSJacob Faibussowitsch     PetscCall(VecCopy(xx, yy));
5389566063dSJacob Faibussowitsch     PetscCall(VecGetArray(yy, &y));
5394905a7bcSToby Isaac   }
5404396437dSToby Isaac   *_y = y;
5414396437dSToby Isaac   *_k = k;
5424396437dSToby Isaac   *_m = m;
5433ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5444396437dSToby Isaac }
5454396437dSToby Isaac 
546d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatSolve_SeqDense_TearDown(Mat A, Vec xx, Vec yy, PetscScalar **_y, PetscBLASInt *_m, PetscBLASInt *_k)
547d71ae5a4SJacob Faibussowitsch {
5484396437dSToby Isaac   Mat_SeqDense *mat = (Mat_SeqDense *)A->data;
54942e9364cSSatish Balay   PetscScalar  *y   = NULL;
5504396437dSToby Isaac   PetscBLASInt  m, k;
5514396437dSToby Isaac 
5524396437dSToby Isaac   PetscFunctionBegin;
5534396437dSToby Isaac   y   = *_y;
5544396437dSToby Isaac   *_y = NULL;
5554396437dSToby Isaac   k   = *_k;
5564396437dSToby Isaac   m   = *_m;
5574905a7bcSToby Isaac   if (k < m) {
5584905a7bcSToby Isaac     PetscScalar *yv;
5599566063dSJacob Faibussowitsch     PetscCall(VecGetArray(yy, &yv));
5609566063dSJacob Faibussowitsch     PetscCall(PetscArraycpy(yv, y, k));
5619566063dSJacob Faibussowitsch     PetscCall(VecRestoreArray(yy, &yv));
5629566063dSJacob Faibussowitsch     PetscCall(VecRestoreArray(mat->qrrhs, &y));
5634905a7bcSToby Isaac   } else {
5649566063dSJacob Faibussowitsch     PetscCall(VecRestoreArray(yy, &y));
5654905a7bcSToby Isaac   }
5663ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5674905a7bcSToby Isaac }
5684905a7bcSToby Isaac 
569d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatSolve_SeqDense_LU(Mat A, Vec xx, Vec yy)
570d71ae5a4SJacob Faibussowitsch {
57142e9364cSSatish Balay   PetscScalar *y = NULL;
57242e9364cSSatish Balay   PetscBLASInt m = 0, k = 0;
5734396437dSToby Isaac 
5744396437dSToby Isaac   PetscFunctionBegin;
5759566063dSJacob Faibussowitsch   PetscCall(MatSolve_SeqDense_SetUp(A, xx, yy, &y, &m, &k));
5769566063dSJacob Faibussowitsch   PetscCall(MatSolve_SeqDense_Internal_LU(A, y, m, m, 1, k, PETSC_FALSE));
5779566063dSJacob Faibussowitsch   PetscCall(MatSolve_SeqDense_TearDown(A, xx, yy, &y, &m, &k));
5783ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5794396437dSToby Isaac }
5804396437dSToby Isaac 
581d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatSolveTranspose_SeqDense_LU(Mat A, Vec xx, Vec yy)
582d71ae5a4SJacob Faibussowitsch {
58342e9364cSSatish Balay   PetscScalar *y = NULL;
58442e9364cSSatish Balay   PetscBLASInt m = 0, k = 0;
5854396437dSToby Isaac 
5864396437dSToby Isaac   PetscFunctionBegin;
5879566063dSJacob Faibussowitsch   PetscCall(MatSolve_SeqDense_SetUp(A, xx, yy, &y, &m, &k));
5889566063dSJacob Faibussowitsch   PetscCall(MatSolve_SeqDense_Internal_LU(A, y, m, m, 1, k, PETSC_TRUE));
5899566063dSJacob Faibussowitsch   PetscCall(MatSolve_SeqDense_TearDown(A, xx, yy, &y, &m, &k));
5903ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5914396437dSToby Isaac }
5924396437dSToby Isaac 
593d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatSolve_SeqDense_Cholesky(Mat A, Vec xx, Vec yy)
594d71ae5a4SJacob Faibussowitsch {
595e54beecaSStefano Zampini   PetscScalar *y = NULL;
596e54beecaSStefano Zampini   PetscBLASInt m = 0, k = 0;
5974396437dSToby Isaac 
5984396437dSToby Isaac   PetscFunctionBegin;
5999566063dSJacob Faibussowitsch   PetscCall(MatSolve_SeqDense_SetUp(A, xx, yy, &y, &m, &k));
6009566063dSJacob Faibussowitsch   PetscCall(MatSolve_SeqDense_Internal_Cholesky(A, y, m, m, 1, k, PETSC_FALSE));
6019566063dSJacob Faibussowitsch   PetscCall(MatSolve_SeqDense_TearDown(A, xx, yy, &y, &m, &k));
6023ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
6034396437dSToby Isaac }
6044396437dSToby Isaac 
605d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatSolveTranspose_SeqDense_Cholesky(Mat A, Vec xx, Vec yy)
606d71ae5a4SJacob Faibussowitsch {
607e54beecaSStefano Zampini   PetscScalar *y = NULL;
608e54beecaSStefano Zampini   PetscBLASInt m = 0, k = 0;
6094396437dSToby Isaac 
6104396437dSToby Isaac   PetscFunctionBegin;
6119566063dSJacob Faibussowitsch   PetscCall(MatSolve_SeqDense_SetUp(A, xx, yy, &y, &m, &k));
6129566063dSJacob Faibussowitsch   PetscCall(MatSolve_SeqDense_Internal_Cholesky(A, y, m, m, 1, k, PETSC_TRUE));
6139566063dSJacob Faibussowitsch   PetscCall(MatSolve_SeqDense_TearDown(A, xx, yy, &y, &m, &k));
6143ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
6154396437dSToby Isaac }
6164396437dSToby Isaac 
617d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatSolve_SeqDense_QR(Mat A, Vec xx, Vec yy)
618d71ae5a4SJacob Faibussowitsch {
619e54beecaSStefano Zampini   PetscScalar *y = NULL;
620e54beecaSStefano Zampini   PetscBLASInt m = 0, k = 0;
6214396437dSToby Isaac 
6224396437dSToby Isaac   PetscFunctionBegin;
6239566063dSJacob Faibussowitsch   PetscCall(MatSolve_SeqDense_SetUp(A, xx, yy, &y, &m, &k));
6249566063dSJacob Faibussowitsch   PetscCall(MatSolve_SeqDense_Internal_QR(A, y, PetscMax(m, k), m, 1, k));
6259566063dSJacob Faibussowitsch   PetscCall(MatSolve_SeqDense_TearDown(A, xx, yy, &y, &m, &k));
6263ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
6274396437dSToby Isaac }
6284396437dSToby Isaac 
629d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatSolveTranspose_SeqDense_QR(Mat A, Vec xx, Vec yy)
630d71ae5a4SJacob Faibussowitsch {
63142e9364cSSatish Balay   PetscScalar *y = NULL;
63242e9364cSSatish Balay   PetscBLASInt m = 0, k = 0;
6334396437dSToby Isaac 
6344396437dSToby Isaac   PetscFunctionBegin;
6359566063dSJacob Faibussowitsch   PetscCall(MatSolve_SeqDense_SetUp(A, xx, yy, &y, &m, &k));
6369566063dSJacob Faibussowitsch   PetscCall(MatSolveTranspose_SeqDense_Internal_QR(A, y, PetscMax(m, k), m, 1, k));
6379566063dSJacob Faibussowitsch   PetscCall(MatSolve_SeqDense_TearDown(A, xx, yy, &y, &m, &k));
6383ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
6394396437dSToby Isaac }
6404396437dSToby Isaac 
641d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatMatSolve_SeqDense_SetUp(Mat A, Mat B, Mat X, PetscScalar **_y, PetscBLASInt *_ldy, PetscBLASInt *_m, PetscBLASInt *_nrhs, PetscBLASInt *_k)
642d71ae5a4SJacob Faibussowitsch {
6434905a7bcSToby Isaac   const PetscScalar *b;
6444396437dSToby Isaac   PetscScalar       *y;
645bf5a80bcSToby Isaac   PetscInt           n, _ldb, _ldx;
646bf5a80bcSToby Isaac   PetscBLASInt       nrhs = 0, m = 0, k = 0, ldb = 0, ldx = 0, ldy = 0;
6474905a7bcSToby Isaac 
6484905a7bcSToby Isaac   PetscFunctionBegin;
6499371c9d4SSatish Balay   *_ldy  = 0;
6509371c9d4SSatish Balay   *_m    = 0;
6519371c9d4SSatish Balay   *_nrhs = 0;
6529371c9d4SSatish Balay   *_k    = 0;
6539371c9d4SSatish Balay   *_y    = NULL;
6549566063dSJacob Faibussowitsch   PetscCall(PetscBLASIntCast(A->rmap->n, &m));
6559566063dSJacob Faibussowitsch   PetscCall(PetscBLASIntCast(A->cmap->n, &k));
6569566063dSJacob Faibussowitsch   PetscCall(MatGetSize(B, NULL, &n));
6579566063dSJacob Faibussowitsch   PetscCall(PetscBLASIntCast(n, &nrhs));
6589566063dSJacob Faibussowitsch   PetscCall(MatDenseGetLDA(B, &_ldb));
6599566063dSJacob Faibussowitsch   PetscCall(PetscBLASIntCast(_ldb, &ldb));
6609566063dSJacob Faibussowitsch   PetscCall(MatDenseGetLDA(X, &_ldx));
6619566063dSJacob Faibussowitsch   PetscCall(PetscBLASIntCast(_ldx, &ldx));
662bf5a80bcSToby Isaac   if (ldx < m) {
6639566063dSJacob Faibussowitsch     PetscCall(MatDenseGetArrayRead(B, &b));
6649566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(nrhs * m, &y));
665bf5a80bcSToby Isaac     if (ldb == m) {
6669566063dSJacob Faibussowitsch       PetscCall(PetscArraycpy(y, b, ldb * nrhs));
6674905a7bcSToby Isaac     } else {
66848a46eb9SPierre Jolivet       for (PetscInt j = 0; j < nrhs; j++) PetscCall(PetscArraycpy(&y[j * m], &b[j * ldb], m));
6694905a7bcSToby Isaac     }
670bf5a80bcSToby Isaac     ldy = m;
6719566063dSJacob Faibussowitsch     PetscCall(MatDenseRestoreArrayRead(B, &b));
6724905a7bcSToby Isaac   } else {
673bf5a80bcSToby Isaac     if (ldb == ldx) {
6749566063dSJacob Faibussowitsch       PetscCall(MatCopy(B, X, SAME_NONZERO_PATTERN));
6759566063dSJacob Faibussowitsch       PetscCall(MatDenseGetArray(X, &y));
6764905a7bcSToby Isaac     } else {
6779566063dSJacob Faibussowitsch       PetscCall(MatDenseGetArray(X, &y));
6789566063dSJacob Faibussowitsch       PetscCall(MatDenseGetArrayRead(B, &b));
67948a46eb9SPierre Jolivet       for (PetscInt j = 0; j < nrhs; j++) PetscCall(PetscArraycpy(&y[j * ldx], &b[j * ldb], m));
6809566063dSJacob Faibussowitsch       PetscCall(MatDenseRestoreArrayRead(B, &b));
6814905a7bcSToby Isaac     }
682bf5a80bcSToby Isaac     ldy = ldx;
6834905a7bcSToby Isaac   }
6844396437dSToby Isaac   *_y    = y;
685bf5a80bcSToby Isaac   *_ldy  = ldy;
6864396437dSToby Isaac   *_k    = k;
6874396437dSToby Isaac   *_m    = m;
6884396437dSToby Isaac   *_nrhs = nrhs;
6893ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
6904396437dSToby Isaac }
6914396437dSToby Isaac 
692d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatMatSolve_SeqDense_TearDown(Mat A, Mat B, Mat X, PetscScalar **_y, PetscBLASInt *_ldy, PetscBLASInt *_m, PetscBLASInt *_nrhs, PetscBLASInt *_k)
693d71ae5a4SJacob Faibussowitsch {
6944396437dSToby Isaac   PetscScalar *y;
695bf5a80bcSToby Isaac   PetscInt     _ldx;
696bf5a80bcSToby Isaac   PetscBLASInt k, ldy, nrhs, ldx = 0;
6974396437dSToby Isaac 
6984396437dSToby Isaac   PetscFunctionBegin;
6994396437dSToby Isaac   y    = *_y;
7004396437dSToby Isaac   *_y  = NULL;
7014396437dSToby Isaac   k    = *_k;
702bf5a80bcSToby Isaac   ldy  = *_ldy;
7034396437dSToby Isaac   nrhs = *_nrhs;
7049566063dSJacob Faibussowitsch   PetscCall(MatDenseGetLDA(X, &_ldx));
7059566063dSJacob Faibussowitsch   PetscCall(PetscBLASIntCast(_ldx, &ldx));
706bf5a80bcSToby Isaac   if (ldx != ldy) {
7074905a7bcSToby Isaac     PetscScalar *xv;
7089566063dSJacob Faibussowitsch     PetscCall(MatDenseGetArray(X, &xv));
70948a46eb9SPierre Jolivet     for (PetscInt j = 0; j < nrhs; j++) PetscCall(PetscArraycpy(&xv[j * ldx], &y[j * ldy], k));
7109566063dSJacob Faibussowitsch     PetscCall(MatDenseRestoreArray(X, &xv));
7119566063dSJacob Faibussowitsch     PetscCall(PetscFree(y));
7124905a7bcSToby Isaac   } else {
7139566063dSJacob Faibussowitsch     PetscCall(MatDenseRestoreArray(X, &y));
7144905a7bcSToby Isaac   }
7153ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
71685e2c93fSHong Zhang }
71785e2c93fSHong Zhang 
718d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatMatSolve_SeqDense_LU(Mat A, Mat B, Mat X)
719d71ae5a4SJacob Faibussowitsch {
7204396437dSToby Isaac   PetscScalar *y;
721bf5a80bcSToby Isaac   PetscBLASInt m, k, ldy, nrhs;
7224396437dSToby Isaac 
7234396437dSToby Isaac   PetscFunctionBegin;
7249566063dSJacob Faibussowitsch   PetscCall(MatMatSolve_SeqDense_SetUp(A, B, X, &y, &ldy, &m, &nrhs, &k));
7259566063dSJacob Faibussowitsch   PetscCall(MatSolve_SeqDense_Internal_LU(A, y, ldy, m, nrhs, k, PETSC_FALSE));
7269566063dSJacob Faibussowitsch   PetscCall(MatMatSolve_SeqDense_TearDown(A, B, X, &y, &ldy, &m, &nrhs, &k));
7273ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
7284396437dSToby Isaac }
7294396437dSToby Isaac 
730d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatMatSolveTranspose_SeqDense_LU(Mat A, Mat B, Mat X)
731d71ae5a4SJacob Faibussowitsch {
7324396437dSToby Isaac   PetscScalar *y;
733bf5a80bcSToby Isaac   PetscBLASInt m, k, ldy, nrhs;
7344396437dSToby Isaac 
7354396437dSToby Isaac   PetscFunctionBegin;
7369566063dSJacob Faibussowitsch   PetscCall(MatMatSolve_SeqDense_SetUp(A, B, X, &y, &ldy, &m, &nrhs, &k));
7379566063dSJacob Faibussowitsch   PetscCall(MatSolve_SeqDense_Internal_LU(A, y, ldy, m, nrhs, k, PETSC_TRUE));
7389566063dSJacob Faibussowitsch   PetscCall(MatMatSolve_SeqDense_TearDown(A, B, X, &y, &ldy, &m, &nrhs, &k));
7393ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
7404396437dSToby Isaac }
7414396437dSToby Isaac 
742d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatMatSolve_SeqDense_Cholesky(Mat A, Mat B, Mat X)
743d71ae5a4SJacob Faibussowitsch {
7444396437dSToby Isaac   PetscScalar *y;
745bf5a80bcSToby Isaac   PetscBLASInt m, k, ldy, nrhs;
7464396437dSToby Isaac 
7474396437dSToby Isaac   PetscFunctionBegin;
7489566063dSJacob Faibussowitsch   PetscCall(MatMatSolve_SeqDense_SetUp(A, B, X, &y, &ldy, &m, &nrhs, &k));
7499566063dSJacob Faibussowitsch   PetscCall(MatSolve_SeqDense_Internal_Cholesky(A, y, ldy, m, nrhs, k, PETSC_FALSE));
7509566063dSJacob Faibussowitsch   PetscCall(MatMatSolve_SeqDense_TearDown(A, B, X, &y, &ldy, &m, &nrhs, &k));
7513ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
7524396437dSToby Isaac }
7534396437dSToby Isaac 
754d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatMatSolveTranspose_SeqDense_Cholesky(Mat A, Mat B, Mat X)
755d71ae5a4SJacob Faibussowitsch {
7564396437dSToby Isaac   PetscScalar *y;
757bf5a80bcSToby Isaac   PetscBLASInt m, k, ldy, nrhs;
7584396437dSToby Isaac 
7594396437dSToby Isaac   PetscFunctionBegin;
7609566063dSJacob Faibussowitsch   PetscCall(MatMatSolve_SeqDense_SetUp(A, B, X, &y, &ldy, &m, &nrhs, &k));
7619566063dSJacob Faibussowitsch   PetscCall(MatSolve_SeqDense_Internal_Cholesky(A, y, ldy, m, nrhs, k, PETSC_TRUE));
7629566063dSJacob Faibussowitsch   PetscCall(MatMatSolve_SeqDense_TearDown(A, B, X, &y, &ldy, &m, &nrhs, &k));
7633ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
7644396437dSToby Isaac }
7654396437dSToby Isaac 
766d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatMatSolve_SeqDense_QR(Mat A, Mat B, Mat X)
767d71ae5a4SJacob Faibussowitsch {
7684396437dSToby Isaac   PetscScalar *y;
769bf5a80bcSToby Isaac   PetscBLASInt m, k, ldy, nrhs;
7704396437dSToby Isaac 
7714396437dSToby Isaac   PetscFunctionBegin;
7729566063dSJacob Faibussowitsch   PetscCall(MatMatSolve_SeqDense_SetUp(A, B, X, &y, &ldy, &m, &nrhs, &k));
7739566063dSJacob Faibussowitsch   PetscCall(MatSolve_SeqDense_Internal_QR(A, y, ldy, m, nrhs, k));
7749566063dSJacob Faibussowitsch   PetscCall(MatMatSolve_SeqDense_TearDown(A, B, X, &y, &ldy, &m, &nrhs, &k));
7753ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
7764396437dSToby Isaac }
7774396437dSToby Isaac 
778d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatMatSolveTranspose_SeqDense_QR(Mat A, Mat B, Mat X)
779d71ae5a4SJacob Faibussowitsch {
7804396437dSToby Isaac   PetscScalar *y;
781bf5a80bcSToby Isaac   PetscBLASInt m, k, ldy, nrhs;
7824396437dSToby Isaac 
7834396437dSToby Isaac   PetscFunctionBegin;
7849566063dSJacob Faibussowitsch   PetscCall(MatMatSolve_SeqDense_SetUp(A, B, X, &y, &ldy, &m, &nrhs, &k));
7859566063dSJacob Faibussowitsch   PetscCall(MatSolveTranspose_SeqDense_Internal_QR(A, y, ldy, m, nrhs, k));
7869566063dSJacob Faibussowitsch   PetscCall(MatMatSolve_SeqDense_TearDown(A, B, X, &y, &ldy, &m, &nrhs, &k));
7873ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
7884396437dSToby Isaac }
7894396437dSToby Isaac 
790db4efbfdSBarry Smith /* COMMENT: I have chosen to hide row permutation in the pivots,
791db4efbfdSBarry Smith    rather than put it in the Mat->row slot.*/
792d71ae5a4SJacob Faibussowitsch PetscErrorCode MatLUFactor_SeqDense(Mat A, IS row, IS col, const MatFactorInfo *minfo)
793d71ae5a4SJacob Faibussowitsch {
794db4efbfdSBarry Smith   Mat_SeqDense *mat = (Mat_SeqDense *)A->data;
795db4efbfdSBarry Smith   PetscBLASInt  n, m, info;
796db4efbfdSBarry Smith 
797db4efbfdSBarry Smith   PetscFunctionBegin;
7989566063dSJacob Faibussowitsch   PetscCall(PetscBLASIntCast(A->cmap->n, &n));
7999566063dSJacob Faibussowitsch   PetscCall(PetscBLASIntCast(A->rmap->n, &m));
8004dfa11a4SJacob Faibussowitsch   if (!mat->pivots) { PetscCall(PetscMalloc1(A->rmap->n, &mat->pivots)); }
8013ba16761SJacob Faibussowitsch   if (!A->rmap->n || !A->cmap->n) PetscFunctionReturn(PETSC_SUCCESS);
8029566063dSJacob Faibussowitsch   PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF));
803792fecdfSBarry Smith   PetscCallBLAS("LAPACKgetrf", LAPACKgetrf_(&m, &n, mat->v, &mat->lda, mat->pivots, &info));
8049566063dSJacob Faibussowitsch   PetscCall(PetscFPTrapPop());
8058e57ea43SSatish Balay 
806835f2295SStefano Zampini   PetscCheck(info >= 0, PETSC_COMM_SELF, PETSC_ERR_LIB, "Bad argument to LU factorization %" PetscBLASInt_FMT, info);
807835f2295SStefano Zampini   PetscCheck(info <= 0, PETSC_COMM_SELF, PETSC_ERR_MAT_LU_ZRPVT, "Bad LU factorization %" PetscBLASInt_FMT, info);
8088208b9aeSStefano Zampini 
8094396437dSToby Isaac   A->ops->solve             = MatSolve_SeqDense_LU;
8104396437dSToby Isaac   A->ops->matsolve          = MatMatSolve_SeqDense_LU;
8114396437dSToby Isaac   A->ops->solvetranspose    = MatSolveTranspose_SeqDense_LU;
8124396437dSToby Isaac   A->ops->matsolvetranspose = MatMatSolveTranspose_SeqDense_LU;
813d5f3da31SBarry Smith   A->factortype             = MAT_FACTOR_LU;
814db4efbfdSBarry Smith 
8159566063dSJacob Faibussowitsch   PetscCall(PetscFree(A->solvertype));
8169566063dSJacob Faibussowitsch   PetscCall(PetscStrallocpy(MATSOLVERPETSC, &A->solvertype));
817f6224b95SHong Zhang 
8189566063dSJacob Faibussowitsch   PetscCall(PetscLogFlops((2.0 * A->cmap->n * A->cmap->n * A->cmap->n) / 3));
8193ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
820db4efbfdSBarry Smith }
821db4efbfdSBarry Smith 
822d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatLUFactorNumeric_SeqDense(Mat fact, Mat A, const MatFactorInfo *info_dummy)
823d71ae5a4SJacob Faibussowitsch {
8244396437dSToby Isaac   MatFactorInfo info;
8254396437dSToby Isaac 
8264396437dSToby Isaac   PetscFunctionBegin;
8279566063dSJacob Faibussowitsch   PetscCall(MatDuplicateNoCreate_SeqDense(fact, A, MAT_COPY_VALUES));
828dbbe0bcdSBarry Smith   PetscUseTypeMethod(fact, lufactor, NULL, NULL, &info);
8293ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
8304396437dSToby Isaac }
8314396437dSToby Isaac 
832d71ae5a4SJacob Faibussowitsch PetscErrorCode MatLUFactorSymbolic_SeqDense(Mat fact, Mat A, IS row, IS col, const MatFactorInfo *info)
833d71ae5a4SJacob Faibussowitsch {
8344396437dSToby Isaac   PetscFunctionBegin;
8354396437dSToby Isaac   fact->preallocated         = PETSC_TRUE;
8364396437dSToby Isaac   fact->assembled            = PETSC_TRUE;
8374396437dSToby Isaac   fact->ops->lufactornumeric = MatLUFactorNumeric_SeqDense;
8383ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
8394396437dSToby Isaac }
8404396437dSToby Isaac 
841a49dc2a2SStefano Zampini /* Cholesky as L*L^T or L*D*L^T and the symmetric/hermitian complex variants */
842d71ae5a4SJacob Faibussowitsch PetscErrorCode MatCholeskyFactor_SeqDense(Mat A, IS perm, const MatFactorInfo *factinfo)
843d71ae5a4SJacob Faibussowitsch {
844db4efbfdSBarry Smith   Mat_SeqDense *mat = (Mat_SeqDense *)A->data;
845c5df96a5SBarry Smith   PetscBLASInt  info, n;
846db4efbfdSBarry Smith 
847db4efbfdSBarry Smith   PetscFunctionBegin;
8489566063dSJacob Faibussowitsch   PetscCall(PetscBLASIntCast(A->cmap->n, &n));
8493ba16761SJacob Faibussowitsch   if (!A->rmap->n || !A->cmap->n) PetscFunctionReturn(PETSC_SUCCESS);
850b94d7dedSBarry Smith   if (A->spd == PETSC_BOOL3_TRUE) {
8519566063dSJacob Faibussowitsch     PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF));
852792fecdfSBarry Smith     PetscCallBLAS("LAPACKpotrf", LAPACKpotrf_("L", &n, mat->v, &mat->lda, &info));
8539566063dSJacob Faibussowitsch     PetscCall(PetscFPTrapPop());
854a49dc2a2SStefano Zampini #if defined(PETSC_USE_COMPLEX)
855b94d7dedSBarry Smith   } else if (A->hermitian == PETSC_BOOL3_TRUE) {
8564dfa11a4SJacob Faibussowitsch     if (!mat->pivots) { PetscCall(PetscMalloc1(A->rmap->n, &mat->pivots)); }
857a49dc2a2SStefano Zampini     if (!mat->fwork) {
858a49dc2a2SStefano Zampini       PetscScalar dummy;
859a49dc2a2SStefano Zampini 
860a49dc2a2SStefano Zampini       mat->lfwork = -1;
8619566063dSJacob Faibussowitsch       PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF));
862792fecdfSBarry Smith       PetscCallBLAS("LAPACKhetrf", LAPACKhetrf_("L", &n, mat->v, &mat->lda, mat->pivots, &dummy, &mat->lfwork, &info));
8639566063dSJacob Faibussowitsch       PetscCall(PetscFPTrapPop());
86407c83e99SJose E. Roman       PetscCall(PetscBLASIntCast((PetscCount)(PetscRealPart(dummy)), &mat->lfwork));
8659566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(mat->lfwork, &mat->fwork));
866a49dc2a2SStefano Zampini     }
8679566063dSJacob Faibussowitsch     PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF));
868792fecdfSBarry Smith     PetscCallBLAS("LAPACKhetrf", LAPACKhetrf_("L", &n, mat->v, &mat->lda, mat->pivots, mat->fwork, &mat->lfwork, &info));
8699566063dSJacob Faibussowitsch     PetscCall(PetscFPTrapPop());
870a49dc2a2SStefano Zampini #endif
871a49dc2a2SStefano Zampini   } else { /* symmetric case */
8724dfa11a4SJacob Faibussowitsch     if (!mat->pivots) { PetscCall(PetscMalloc1(A->rmap->n, &mat->pivots)); }
873a49dc2a2SStefano Zampini     if (!mat->fwork) {
874a49dc2a2SStefano Zampini       PetscScalar dummy;
875a49dc2a2SStefano Zampini 
876a49dc2a2SStefano Zampini       mat->lfwork = -1;
8779566063dSJacob Faibussowitsch       PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF));
878792fecdfSBarry Smith       PetscCallBLAS("LAPACKsytrf", LAPACKsytrf_("L", &n, mat->v, &mat->lda, mat->pivots, &dummy, &mat->lfwork, &info));
8799566063dSJacob Faibussowitsch       PetscCall(PetscFPTrapPop());
8806497c311SBarry Smith       PetscCall(PetscBLASIntCast((PetscCount)(PetscRealPart(dummy)), &mat->lfwork));
8819566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(mat->lfwork, &mat->fwork));
882a49dc2a2SStefano Zampini     }
8839566063dSJacob Faibussowitsch     PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF));
884792fecdfSBarry Smith     PetscCallBLAS("LAPACKsytrf", LAPACKsytrf_("L", &n, mat->v, &mat->lda, mat->pivots, mat->fwork, &mat->lfwork, &info));
8859566063dSJacob Faibussowitsch     PetscCall(PetscFPTrapPop());
886a49dc2a2SStefano Zampini   }
887835f2295SStefano Zampini   PetscCheck(!info, PETSC_COMM_SELF, PETSC_ERR_MAT_CH_ZRPVT, "Bad factorization: zero pivot in row %" PetscBLASInt_FMT, info - 1);
8888208b9aeSStefano Zampini 
8894396437dSToby Isaac   A->ops->solve             = MatSolve_SeqDense_Cholesky;
8904396437dSToby Isaac   A->ops->matsolve          = MatMatSolve_SeqDense_Cholesky;
8914396437dSToby Isaac   A->ops->solvetranspose    = MatSolveTranspose_SeqDense_Cholesky;
8924396437dSToby Isaac   A->ops->matsolvetranspose = MatMatSolveTranspose_SeqDense_Cholesky;
893d5f3da31SBarry Smith   A->factortype             = MAT_FACTOR_CHOLESKY;
8942205254eSKarl Rupp 
8959566063dSJacob Faibussowitsch   PetscCall(PetscFree(A->solvertype));
8969566063dSJacob Faibussowitsch   PetscCall(PetscStrallocpy(MATSOLVERPETSC, &A->solvertype));
897f6224b95SHong Zhang 
8989566063dSJacob Faibussowitsch   PetscCall(PetscLogFlops((1.0 * A->cmap->n * A->cmap->n * A->cmap->n) / 3.0));
8993ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
900db4efbfdSBarry Smith }
901db4efbfdSBarry Smith 
902d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatCholeskyFactorNumeric_SeqDense(Mat fact, Mat A, const MatFactorInfo *info_dummy)
903d71ae5a4SJacob Faibussowitsch {
904db4efbfdSBarry Smith   MatFactorInfo info;
905db4efbfdSBarry Smith 
906db4efbfdSBarry Smith   PetscFunctionBegin;
907db4efbfdSBarry Smith   info.fill = 1.0;
9082205254eSKarl Rupp 
9099566063dSJacob Faibussowitsch   PetscCall(MatDuplicateNoCreate_SeqDense(fact, A, MAT_COPY_VALUES));
910dbbe0bcdSBarry Smith   PetscUseTypeMethod(fact, choleskyfactor, NULL, &info);
9113ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
912db4efbfdSBarry Smith }
913db4efbfdSBarry Smith 
914d71ae5a4SJacob Faibussowitsch PetscErrorCode MatCholeskyFactorSymbolic_SeqDense(Mat fact, Mat A, IS row, const MatFactorInfo *info)
915d71ae5a4SJacob Faibussowitsch {
916db4efbfdSBarry Smith   PetscFunctionBegin;
917c3ef05f6SHong Zhang   fact->assembled                  = PETSC_TRUE;
9181bbcc794SSatish Balay   fact->preallocated               = PETSC_TRUE;
919719d5645SBarry Smith   fact->ops->choleskyfactornumeric = MatCholeskyFactorNumeric_SeqDense;
9203ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
921db4efbfdSBarry Smith }
922db4efbfdSBarry Smith 
923d71ae5a4SJacob Faibussowitsch PetscErrorCode MatQRFactor_SeqDense(Mat A, IS col, const MatFactorInfo *minfo)
924d71ae5a4SJacob Faibussowitsch {
9254905a7bcSToby Isaac   Mat_SeqDense *mat = (Mat_SeqDense *)A->data;
9264905a7bcSToby Isaac   PetscBLASInt  n, m, info, min, max;
9274905a7bcSToby Isaac 
9284905a7bcSToby Isaac   PetscFunctionBegin;
9299566063dSJacob Faibussowitsch   PetscCall(PetscBLASIntCast(A->cmap->n, &n));
9309566063dSJacob Faibussowitsch   PetscCall(PetscBLASIntCast(A->rmap->n, &m));
9314396437dSToby Isaac   max = PetscMax(m, n);
9324396437dSToby Isaac   min = PetscMin(m, n);
9334dfa11a4SJacob Faibussowitsch   if (!mat->tau) { PetscCall(PetscMalloc1(min, &mat->tau)); }
9344dfa11a4SJacob Faibussowitsch   if (!mat->pivots) { PetscCall(PetscMalloc1(n, &mat->pivots)); }
935f4f49eeaSPierre Jolivet   if (!mat->qrrhs) PetscCall(MatCreateVecs(A, NULL, &mat->qrrhs));
9363ba16761SJacob Faibussowitsch   if (!A->rmap->n || !A->cmap->n) PetscFunctionReturn(PETSC_SUCCESS);
9374905a7bcSToby Isaac   if (!mat->fwork) {
9384905a7bcSToby Isaac     PetscScalar dummy;
9394905a7bcSToby Isaac 
9404905a7bcSToby Isaac     mat->lfwork = -1;
9419566063dSJacob Faibussowitsch     PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF));
942792fecdfSBarry Smith     PetscCallBLAS("LAPACKgeqrf", LAPACKgeqrf_(&m, &n, mat->v, &mat->lda, mat->tau, &dummy, &mat->lfwork, &info));
9439566063dSJacob Faibussowitsch     PetscCall(PetscFPTrapPop());
9446497c311SBarry Smith     PetscCall(PetscBLASIntCast((PetscCount)(PetscRealPart(dummy)), &mat->lfwork));
9459566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(mat->lfwork, &mat->fwork));
9464905a7bcSToby Isaac   }
9479566063dSJacob Faibussowitsch   PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF));
948792fecdfSBarry Smith   PetscCallBLAS("LAPACKgeqrf", LAPACKgeqrf_(&m, &n, mat->v, &mat->lda, mat->tau, mat->fwork, &mat->lfwork, &info));
9499566063dSJacob Faibussowitsch   PetscCall(PetscFPTrapPop());
950835f2295SStefano Zampini   PetscCheck(!info, PETSC_COMM_SELF, PETSC_ERR_LIB, "Bad argument to QR factorization %" PetscBLASInt_FMT, info);
9514905a7bcSToby 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
9524905a7bcSToby Isaac   mat->rank = min;
9534905a7bcSToby Isaac 
9544396437dSToby Isaac   A->ops->solve    = MatSolve_SeqDense_QR;
9554396437dSToby Isaac   A->ops->matsolve = MatMatSolve_SeqDense_QR;
9564905a7bcSToby Isaac   A->factortype    = MAT_FACTOR_QR;
9574905a7bcSToby Isaac   if (m == n) {
9584396437dSToby Isaac     A->ops->solvetranspose    = MatSolveTranspose_SeqDense_QR;
9594396437dSToby Isaac     A->ops->matsolvetranspose = MatMatSolveTranspose_SeqDense_QR;
9604905a7bcSToby Isaac   }
9614905a7bcSToby Isaac 
9629566063dSJacob Faibussowitsch   PetscCall(PetscFree(A->solvertype));
9639566063dSJacob Faibussowitsch   PetscCall(PetscStrallocpy(MATSOLVERPETSC, &A->solvertype));
9644905a7bcSToby Isaac 
9659566063dSJacob Faibussowitsch   PetscCall(PetscLogFlops(2.0 * min * min * (max - min / 3.0)));
9663ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
9674905a7bcSToby Isaac }
9684905a7bcSToby Isaac 
969d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatQRFactorNumeric_SeqDense(Mat fact, Mat A, const MatFactorInfo *info_dummy)
970d71ae5a4SJacob Faibussowitsch {
9714905a7bcSToby Isaac   MatFactorInfo info;
9724905a7bcSToby Isaac 
9734905a7bcSToby Isaac   PetscFunctionBegin;
9744905a7bcSToby Isaac   info.fill = 1.0;
9754905a7bcSToby Isaac 
9769566063dSJacob Faibussowitsch   PetscCall(MatDuplicateNoCreate_SeqDense(fact, A, MAT_COPY_VALUES));
977cac4c232SBarry Smith   PetscUseMethod(fact, "MatQRFactor_C", (Mat, IS, const MatFactorInfo *), (fact, NULL, &info));
9783ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
9794905a7bcSToby Isaac }
9804905a7bcSToby Isaac 
981d71ae5a4SJacob Faibussowitsch PetscErrorCode MatQRFactorSymbolic_SeqDense(Mat fact, Mat A, IS row, const MatFactorInfo *info)
982d71ae5a4SJacob Faibussowitsch {
9834905a7bcSToby Isaac   PetscFunctionBegin;
9844905a7bcSToby Isaac   fact->assembled    = PETSC_TRUE;
9854905a7bcSToby Isaac   fact->preallocated = PETSC_TRUE;
9869566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)fact, "MatQRFactorNumeric_C", MatQRFactorNumeric_SeqDense));
9873ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
9884905a7bcSToby Isaac }
9894905a7bcSToby Isaac 
990ca15aa20SStefano Zampini /* uses LAPACK */
991d71ae5a4SJacob Faibussowitsch PETSC_INTERN PetscErrorCode MatGetFactor_seqdense_petsc(Mat A, MatFactorType ftype, Mat *fact)
992d71ae5a4SJacob Faibussowitsch {
993db4efbfdSBarry Smith   PetscFunctionBegin;
9949566063dSJacob Faibussowitsch   PetscCall(MatCreate(PetscObjectComm((PetscObject)A), fact));
9959566063dSJacob Faibussowitsch   PetscCall(MatSetSizes(*fact, A->rmap->n, A->cmap->n, A->rmap->n, A->cmap->n));
9969566063dSJacob Faibussowitsch   PetscCall(MatSetType(*fact, MATDENSE));
99766e17bc3SBarry Smith   (*fact)->trivialsymbolic = PETSC_TRUE;
9982a350339SBarry Smith   if (ftype == MAT_FACTOR_LU || ftype == MAT_FACTOR_ILU) {
999db4efbfdSBarry Smith     (*fact)->ops->lufactorsymbolic  = MatLUFactorSymbolic_SeqDense;
10002a350339SBarry Smith     (*fact)->ops->ilufactorsymbolic = MatLUFactorSymbolic_SeqDense;
1001bf5a80bcSToby Isaac   } else if (ftype == MAT_FACTOR_CHOLESKY || ftype == MAT_FACTOR_ICC) {
1002db4efbfdSBarry Smith     (*fact)->ops->choleskyfactorsymbolic = MatCholeskyFactorSymbolic_SeqDense;
1003bf5a80bcSToby Isaac   } else if (ftype == MAT_FACTOR_QR) {
1004f4f49eeaSPierre Jolivet     PetscCall(PetscObjectComposeFunction((PetscObject)*fact, "MatQRFactorSymbolic_C", MatQRFactorSymbolic_SeqDense));
1005db4efbfdSBarry Smith   }
1006d5f3da31SBarry Smith   (*fact)->factortype = ftype;
100700c67f3bSHong Zhang 
10089566063dSJacob Faibussowitsch   PetscCall(PetscFree((*fact)->solvertype));
10099566063dSJacob Faibussowitsch   PetscCall(PetscStrallocpy(MATSOLVERPETSC, &(*fact)->solvertype));
10109566063dSJacob Faibussowitsch   PetscCall(PetscStrallocpy(MATORDERINGEXTERNAL, (char **)&(*fact)->preferredordering[MAT_FACTOR_LU]));
10119566063dSJacob Faibussowitsch   PetscCall(PetscStrallocpy(MATORDERINGEXTERNAL, (char **)&(*fact)->preferredordering[MAT_FACTOR_ILU]));
10129566063dSJacob Faibussowitsch   PetscCall(PetscStrallocpy(MATORDERINGEXTERNAL, (char **)&(*fact)->preferredordering[MAT_FACTOR_CHOLESKY]));
10139566063dSJacob Faibussowitsch   PetscCall(PetscStrallocpy(MATORDERINGEXTERNAL, (char **)&(*fact)->preferredordering[MAT_FACTOR_ICC]));
10143ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1015db4efbfdSBarry Smith }
1016db4efbfdSBarry Smith 
1017d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatSOR_SeqDense(Mat A, Vec bb, PetscReal omega, MatSORType flag, PetscReal shift, PetscInt its, PetscInt lits, Vec xx)
1018d71ae5a4SJacob Faibussowitsch {
1019c0bbcb79SLois Curfman McInnes   Mat_SeqDense      *mat = (Mat_SeqDense *)A->data;
1020d9ca1df4SBarry Smith   PetscScalar       *x, *v = mat->v, zero = 0.0, xt;
1021d9ca1df4SBarry Smith   const PetscScalar *b;
1022d0f46423SBarry Smith   PetscInt           m = A->rmap->n, i;
102323fff9afSBarry Smith   PetscBLASInt       o = 1, bm = 0;
1024289bc588SBarry Smith 
10253a40ed3dSBarry Smith   PetscFunctionBegin;
102647d993e7Ssuyashtn #if defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
102708401ef6SPierre Jolivet   PetscCheck(A->offloadmask != PETSC_OFFLOAD_GPU, PETSC_COMM_SELF, PETSC_ERR_SUP, "Not implemented");
1028ca15aa20SStefano Zampini #endif
1029422a814eSBarry Smith   if (shift == -1) shift = 0.0; /* negative shift indicates do not error on zero diagonal; this code never zeros on zero diagonal */
10309566063dSJacob Faibussowitsch   PetscCall(PetscBLASIntCast(m, &bm));
1031289bc588SBarry Smith   if (flag & SOR_ZERO_INITIAL_GUESS) {
10323bffc371SBarry Smith     /* this is a hack fix, should have another version without the second BLASdotu */
10339566063dSJacob Faibussowitsch     PetscCall(VecSet(xx, zero));
1034289bc588SBarry Smith   }
10359566063dSJacob Faibussowitsch   PetscCall(VecGetArray(xx, &x));
10369566063dSJacob Faibussowitsch   PetscCall(VecGetArrayRead(bb, &b));
1037b965ef7fSBarry Smith   its = its * lits;
103808401ef6SPierre 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);
1039289bc588SBarry Smith   while (its--) {
1040fccaa45eSBarry Smith     if (flag & SOR_FORWARD_SWEEP || flag & SOR_LOCAL_FORWARD_SWEEP) {
1041289bc588SBarry Smith       for (i = 0; i < m; i++) {
1042792fecdfSBarry Smith         PetscCallBLAS("BLASdotu", xt = b[i] - BLASdotu_(&bm, v + i, &bm, x, &o));
1043883424caSPierre Jolivet         x[i] = (1. - omega) * x[i] + (xt + v[i + i * m] * x[i]) * omega / (v[i + i * m] + shift);
1044289bc588SBarry Smith       }
1045289bc588SBarry Smith     }
1046fccaa45eSBarry Smith     if (flag & SOR_BACKWARD_SWEEP || flag & SOR_LOCAL_BACKWARD_SWEEP) {
1047289bc588SBarry Smith       for (i = m - 1; i >= 0; i--) {
1048792fecdfSBarry Smith         PetscCallBLAS("BLASdotu", xt = b[i] - BLASdotu_(&bm, v + i, &bm, x, &o));
1049883424caSPierre Jolivet         x[i] = (1. - omega) * x[i] + (xt + v[i + i * m] * x[i]) * omega / (v[i + i * m] + shift);
1050289bc588SBarry Smith       }
1051289bc588SBarry Smith     }
1052289bc588SBarry Smith   }
10539566063dSJacob Faibussowitsch   PetscCall(VecRestoreArrayRead(bb, &b));
10549566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(xx, &x));
10553ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1056289bc588SBarry Smith }
1057289bc588SBarry Smith 
10580be0d8bdSHansol Suh static PetscErrorCode MatMultColumnRangeKernel_SeqDense(Mat A, Vec xx, Vec yy, PetscInt c_start, PetscInt c_end, PetscBool trans, PetscBool herm)
1059d71ae5a4SJacob Faibussowitsch {
1060c0bbcb79SLois Curfman McInnes   Mat_SeqDense      *mat = (Mat_SeqDense *)A->data;
1061d9ca1df4SBarry Smith   PetscScalar       *y, _DOne = 1.0, _DZero = 0.0;
10620805154bSBarry Smith   PetscBLASInt       m, n, _One             = 1;
1063d9ca1df4SBarry Smith   const PetscScalar *v = mat->v, *x;
10643a40ed3dSBarry Smith 
10653a40ed3dSBarry Smith   PetscFunctionBegin;
10669566063dSJacob Faibussowitsch   PetscCall(PetscBLASIntCast(A->rmap->n, &m));
10670be0d8bdSHansol Suh   PetscCall(PetscBLASIntCast(c_end - c_start, &n));
10689566063dSJacob Faibussowitsch   PetscCall(VecGetArrayRead(xx, &x));
10699566063dSJacob Faibussowitsch   PetscCall(VecGetArrayWrite(yy, &y));
10700be0d8bdSHansol Suh   if (!m || !n) {
10715ac36cfcSBarry Smith     PetscBLASInt i;
1072459e8d23SBlanca Mellado Pinto     if (trans)
1073459e8d23SBlanca Mellado Pinto       for (i = 0; i < n; i++) y[i] = 0.0;
1074459e8d23SBlanca Mellado Pinto     else
10755ac36cfcSBarry Smith       for (i = 0; i < m; i++) y[i] = 0.0;
10765ac36cfcSBarry Smith   } else {
1077459e8d23SBlanca Mellado Pinto     if (trans) {
10780be0d8bdSHansol Suh       if (herm) PetscCallBLAS("BLASgemv", BLASgemv_("C", &m, &n, &_DOne, v + c_start * mat->lda, &mat->lda, x, &_One, &_DZero, y + c_start, &_One));
10790be0d8bdSHansol Suh       else PetscCallBLAS("BLASgemv", BLASgemv_("T", &m, &n, &_DOne, v + c_start * mat->lda, &mat->lda, x, &_One, &_DZero, y + c_start, &_One));
1080459e8d23SBlanca Mellado Pinto     } else {
10810be0d8bdSHansol Suh       PetscCallBLAS("BLASgemv", BLASgemv_("N", &m, &n, &_DOne, v + c_start * mat->lda, &mat->lda, x + c_start, &_One, &_DZero, y, &_One));
1082459e8d23SBlanca Mellado Pinto     }
10830be0d8bdSHansol Suh     PetscCall(PetscLogFlops(2.0 * m * n - n));
10845ac36cfcSBarry Smith   }
10859566063dSJacob Faibussowitsch   PetscCall(VecRestoreArrayRead(xx, &x));
10869566063dSJacob Faibussowitsch   PetscCall(VecRestoreArrayWrite(yy, &y));
10873ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1088289bc588SBarry Smith }
10896ee01492SSatish Balay 
10900be0d8bdSHansol Suh PetscErrorCode MatMultHermitianTransposeColumnRange_SeqDense(Mat A, Vec xx, Vec yy, PetscInt c_start, PetscInt c_end)
10910be0d8bdSHansol Suh {
10920be0d8bdSHansol Suh   PetscFunctionBegin;
10930be0d8bdSHansol Suh   PetscCall(MatMultColumnRangeKernel_SeqDense(A, xx, yy, c_start, c_end, PETSC_TRUE, PETSC_TRUE));
10940be0d8bdSHansol Suh   PetscFunctionReturn(PETSC_SUCCESS);
10950be0d8bdSHansol Suh }
10960be0d8bdSHansol Suh 
1097459e8d23SBlanca Mellado Pinto PetscErrorCode MatMult_SeqDense(Mat A, Vec xx, Vec yy)
1098459e8d23SBlanca Mellado Pinto {
1099459e8d23SBlanca Mellado Pinto   PetscFunctionBegin;
11000be0d8bdSHansol Suh   PetscCall(MatMultColumnRangeKernel_SeqDense(A, xx, yy, 0, A->cmap->n, PETSC_FALSE, PETSC_FALSE));
1101459e8d23SBlanca Mellado Pinto   PetscFunctionReturn(PETSC_SUCCESS);
1102459e8d23SBlanca Mellado Pinto }
1103459e8d23SBlanca Mellado Pinto 
1104459e8d23SBlanca Mellado Pinto PetscErrorCode MatMultTranspose_SeqDense(Mat A, Vec xx, Vec yy)
1105459e8d23SBlanca Mellado Pinto {
1106459e8d23SBlanca Mellado Pinto   PetscFunctionBegin;
11070be0d8bdSHansol Suh   PetscCall(MatMultColumnRangeKernel_SeqDense(A, xx, yy, 0, A->cmap->n, PETSC_TRUE, PETSC_FALSE));
1108459e8d23SBlanca Mellado Pinto   PetscFunctionReturn(PETSC_SUCCESS);
1109459e8d23SBlanca Mellado Pinto }
1110459e8d23SBlanca Mellado Pinto 
1111459e8d23SBlanca Mellado Pinto PetscErrorCode MatMultHermitianTranspose_SeqDense(Mat A, Vec xx, Vec yy)
1112459e8d23SBlanca Mellado Pinto {
1113459e8d23SBlanca Mellado Pinto   PetscFunctionBegin;
11140be0d8bdSHansol Suh   PetscCall(MatMultColumnRangeKernel_SeqDense(A, xx, yy, 0, A->cmap->n, PETSC_TRUE, PETSC_TRUE));
1115459e8d23SBlanca Mellado Pinto   PetscFunctionReturn(PETSC_SUCCESS);
1116459e8d23SBlanca Mellado Pinto }
1117459e8d23SBlanca Mellado Pinto 
11180be0d8bdSHansol Suh static PetscErrorCode MatMultAddColumnRangeKernel_SeqDense(Mat A, Vec xx, Vec zz, Vec yy, PetscInt c_start, PetscInt c_end, PetscBool trans, PetscBool herm)
1119d71ae5a4SJacob Faibussowitsch {
1120c0bbcb79SLois Curfman McInnes   Mat_SeqDense      *mat = (Mat_SeqDense *)A->data;
1121d9ca1df4SBarry Smith   const PetscScalar *v   = mat->v, *x;
1122d9ca1df4SBarry Smith   PetscScalar       *y, _DOne = 1.0;
11230805154bSBarry Smith   PetscBLASInt       m, n, _One = 1;
11243a40ed3dSBarry Smith 
11253a40ed3dSBarry Smith   PetscFunctionBegin;
11269566063dSJacob Faibussowitsch   PetscCall(PetscBLASIntCast(A->rmap->n, &m));
11270be0d8bdSHansol Suh   PetscCall(PetscBLASIntCast(c_end - c_start, &n));
11289566063dSJacob Faibussowitsch   PetscCall(VecCopy(zz, yy));
11290be0d8bdSHansol Suh   if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS);
11309566063dSJacob Faibussowitsch   PetscCall(VecGetArray(yy, &y));
1131459e8d23SBlanca Mellado Pinto   PetscCall(VecGetArrayRead(xx, &x));
1132459e8d23SBlanca Mellado Pinto   if (trans) {
11330be0d8bdSHansol Suh     if (herm) PetscCallBLAS("BLASgemv", BLASgemv_("C", &m, &n, &_DOne, v + c_start * mat->lda, &mat->lda, x, &_One, &_DOne, y + c_start, &_One));
11340be0d8bdSHansol Suh     else PetscCallBLAS("BLASgemv", BLASgemv_("T", &m, &n, &_DOne, v + c_start * mat->lda, &mat->lda, x, &_One, &_DOne, y + c_start, &_One));
1135459e8d23SBlanca Mellado Pinto   } else {
11360be0d8bdSHansol Suh     PetscCallBLAS("BLASgemv", BLASgemv_("N", &m, &n, &_DOne, v + c_start * mat->lda, &mat->lda, x + c_start, &_One, &_DOne, y, &_One));
1137459e8d23SBlanca Mellado Pinto   }
11389566063dSJacob Faibussowitsch   PetscCall(VecRestoreArrayRead(xx, &x));
11399566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(yy, &y));
11400be0d8bdSHansol Suh   PetscCall(PetscLogFlops(2.0 * m * n));
11410be0d8bdSHansol Suh   PetscFunctionReturn(PETSC_SUCCESS);
11420be0d8bdSHansol Suh }
11430be0d8bdSHansol Suh 
11440be0d8bdSHansol Suh PetscErrorCode MatMultAddColumnRange_SeqDense(Mat A, Vec xx, Vec zz, Vec yy, PetscInt c_start, PetscInt c_end)
11450be0d8bdSHansol Suh {
11460be0d8bdSHansol Suh   PetscFunctionBegin;
11470be0d8bdSHansol Suh   PetscCall(MatMultAddColumnRangeKernel_SeqDense(A, xx, zz, yy, c_start, c_end, PETSC_FALSE, PETSC_FALSE));
11480be0d8bdSHansol Suh   PetscFunctionReturn(PETSC_SUCCESS);
11490be0d8bdSHansol Suh }
11500be0d8bdSHansol Suh 
11510be0d8bdSHansol Suh PetscErrorCode MatMultHermitianTransposeAddColumnRange_SeqDense(Mat A, Vec xx, Vec zz, Vec yy, PetscInt c_start, PetscInt c_end)
11520be0d8bdSHansol Suh {
11530be0d8bdSHansol Suh   PetscFunctionBegin;
11540be0d8bdSHansol Suh   PetscMPIInt rank;
11550be0d8bdSHansol Suh   PetscCallMPI(MPI_Comm_rank(MPI_COMM_WORLD, &rank));
11560be0d8bdSHansol Suh   PetscCall(MatMultAddColumnRangeKernel_SeqDense(A, xx, zz, yy, c_start, c_end, PETSC_TRUE, PETSC_TRUE));
11573ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1158289bc588SBarry Smith }
11596ee01492SSatish Balay 
1160459e8d23SBlanca Mellado Pinto PetscErrorCode MatMultAdd_SeqDense(Mat A, Vec xx, Vec zz, Vec yy)
1161459e8d23SBlanca Mellado Pinto {
1162459e8d23SBlanca Mellado Pinto   PetscFunctionBegin;
11630be0d8bdSHansol Suh   PetscCall(MatMultAddColumnRangeKernel_SeqDense(A, xx, zz, yy, 0, A->cmap->n, PETSC_FALSE, PETSC_FALSE));
1164459e8d23SBlanca Mellado Pinto   PetscFunctionReturn(PETSC_SUCCESS);
1165459e8d23SBlanca Mellado Pinto }
1166459e8d23SBlanca Mellado Pinto 
1167d71ae5a4SJacob Faibussowitsch PetscErrorCode MatMultTransposeAdd_SeqDense(Mat A, Vec xx, Vec zz, Vec yy)
1168d71ae5a4SJacob Faibussowitsch {
11693a40ed3dSBarry Smith   PetscFunctionBegin;
11700be0d8bdSHansol Suh   PetscCall(MatMultAddColumnRangeKernel_SeqDense(A, xx, zz, yy, 0, A->cmap->n, PETSC_TRUE, PETSC_FALSE));
1171459e8d23SBlanca Mellado Pinto   PetscFunctionReturn(PETSC_SUCCESS);
1172459e8d23SBlanca Mellado Pinto }
1173459e8d23SBlanca Mellado Pinto 
1174459e8d23SBlanca Mellado Pinto PetscErrorCode MatMultHermitianTransposeAdd_SeqDense(Mat A, Vec xx, Vec zz, Vec yy)
1175459e8d23SBlanca Mellado Pinto {
1176459e8d23SBlanca Mellado Pinto   PetscFunctionBegin;
11770be0d8bdSHansol Suh   PetscCall(MatMultAddColumnRangeKernel_SeqDense(A, xx, zz, yy, 0, A->cmap->n, PETSC_TRUE, PETSC_TRUE));
11783ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1179289bc588SBarry Smith }
1180289bc588SBarry Smith 
1181d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatGetRow_SeqDense(Mat A, PetscInt row, PetscInt *ncols, PetscInt **cols, PetscScalar **vals)
1182d71ae5a4SJacob Faibussowitsch {
1183c0bbcb79SLois Curfman McInnes   Mat_SeqDense *mat = (Mat_SeqDense *)A->data;
118413f74950SBarry Smith   PetscInt      i;
118567e560aaSBarry Smith 
11863a40ed3dSBarry Smith   PetscFunctionBegin;
1187c3e1b152SPierre Jolivet   if (ncols) *ncols = A->cmap->n;
1188289bc588SBarry Smith   if (cols) {
11899566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(A->cmap->n, cols));
1190d0f46423SBarry Smith     for (i = 0; i < A->cmap->n; i++) (*cols)[i] = i;
1191289bc588SBarry Smith   }
1192289bc588SBarry Smith   if (vals) {
1193ca15aa20SStefano Zampini     const PetscScalar *v;
1194ca15aa20SStefano Zampini 
11959566063dSJacob Faibussowitsch     PetscCall(MatDenseGetArrayRead(A, &v));
11969566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(A->cmap->n, vals));
1197ca15aa20SStefano Zampini     v += row;
11989371c9d4SSatish Balay     for (i = 0; i < A->cmap->n; i++) {
11999371c9d4SSatish Balay       (*vals)[i] = *v;
12009371c9d4SSatish Balay       v += mat->lda;
12019371c9d4SSatish Balay     }
12029566063dSJacob Faibussowitsch     PetscCall(MatDenseRestoreArrayRead(A, &v));
1203289bc588SBarry Smith   }
12043ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1205289bc588SBarry Smith }
12066ee01492SSatish Balay 
1207d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatRestoreRow_SeqDense(Mat A, PetscInt row, PetscInt *ncols, PetscInt **cols, PetscScalar **vals)
1208d71ae5a4SJacob Faibussowitsch {
1209606d414cSSatish Balay   PetscFunctionBegin;
12109566063dSJacob Faibussowitsch   if (cols) PetscCall(PetscFree(*cols));
12119566063dSJacob Faibussowitsch   if (vals) PetscCall(PetscFree(*vals));
12123ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1213289bc588SBarry Smith }
12142ef1f0ffSBarry Smith 
1215d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatSetValues_SeqDense(Mat A, PetscInt m, const PetscInt indexm[], PetscInt n, const PetscInt indexn[], const PetscScalar v[], InsertMode addv)
1216d71ae5a4SJacob Faibussowitsch {
1217c0bbcb79SLois Curfman McInnes   Mat_SeqDense *mat = (Mat_SeqDense *)A->data;
1218ca15aa20SStefano Zampini   PetscScalar  *av;
121913f74950SBarry Smith   PetscInt      i, j, idx = 0;
122047d993e7Ssuyashtn #if defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
1221c70f7ee4SJunchao Zhang   PetscOffloadMask oldf;
1222ca15aa20SStefano Zampini #endif
1223d6dfbf8fSBarry Smith 
12243a40ed3dSBarry Smith   PetscFunctionBegin;
12259566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArray(A, &av));
1226289bc588SBarry Smith   if (!mat->roworiented) {
1227dbb450caSBarry Smith     if (addv == INSERT_VALUES) {
1228289bc588SBarry Smith       for (j = 0; j < n; j++) {
12299371c9d4SSatish Balay         if (indexn[j] < 0) {
12309371c9d4SSatish Balay           idx += m;
12319371c9d4SSatish Balay           continue;
12329371c9d4SSatish Balay         }
12336bdcaf15SBarry 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);
1234289bc588SBarry Smith         for (i = 0; i < m; i++) {
12359371c9d4SSatish Balay           if (indexm[i] < 0) {
12369371c9d4SSatish Balay             idx++;
12379371c9d4SSatish Balay             continue;
12389371c9d4SSatish Balay           }
12396bdcaf15SBarry 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);
12408c4a67a0SStefano Zampini           av[indexn[j] * mat->lda + indexm[i]] = v ? v[idx++] : (idx++, 0.0);
1241289bc588SBarry Smith         }
1242289bc588SBarry Smith       }
12430be0d8bdSHansol Suh     } else {
1244289bc588SBarry Smith       for (j = 0; j < n; j++) {
12459371c9d4SSatish Balay         if (indexn[j] < 0) {
12469371c9d4SSatish Balay           idx += m;
12479371c9d4SSatish Balay           continue;
12489371c9d4SSatish Balay         }
12496bdcaf15SBarry 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);
1250289bc588SBarry Smith         for (i = 0; i < m; i++) {
12519371c9d4SSatish Balay           if (indexm[i] < 0) {
12529371c9d4SSatish Balay             idx++;
12539371c9d4SSatish Balay             continue;
12549371c9d4SSatish Balay           }
12556bdcaf15SBarry 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);
12568c4a67a0SStefano Zampini           av[indexn[j] * mat->lda + indexm[i]] += v ? v[idx++] : (idx++, 0.0);
1257289bc588SBarry Smith         }
1258289bc588SBarry Smith       }
1259289bc588SBarry Smith     }
12603a40ed3dSBarry Smith   } else {
1261dbb450caSBarry Smith     if (addv == INSERT_VALUES) {
1262e8d4e0b9SBarry Smith       for (i = 0; i < m; i++) {
12639371c9d4SSatish Balay         if (indexm[i] < 0) {
12649371c9d4SSatish Balay           idx += n;
12659371c9d4SSatish Balay           continue;
12669371c9d4SSatish Balay         }
12676bdcaf15SBarry 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);
1268e8d4e0b9SBarry Smith         for (j = 0; j < n; j++) {
12699371c9d4SSatish Balay           if (indexn[j] < 0) {
12709371c9d4SSatish Balay             idx++;
12719371c9d4SSatish Balay             continue;
12729371c9d4SSatish Balay           }
12736bdcaf15SBarry 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);
12748c4a67a0SStefano Zampini           av[indexn[j] * mat->lda + indexm[i]] = v ? v[idx++] : (idx++, 0.0);
1275e8d4e0b9SBarry Smith         }
1276e8d4e0b9SBarry Smith       }
12770be0d8bdSHansol Suh     } else {
1278289bc588SBarry Smith       for (i = 0; i < m; i++) {
12799371c9d4SSatish Balay         if (indexm[i] < 0) {
12809371c9d4SSatish Balay           idx += n;
12819371c9d4SSatish Balay           continue;
12829371c9d4SSatish Balay         }
12836bdcaf15SBarry 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);
1284289bc588SBarry Smith         for (j = 0; j < n; j++) {
12859371c9d4SSatish Balay           if (indexn[j] < 0) {
12869371c9d4SSatish Balay             idx++;
12879371c9d4SSatish Balay             continue;
12889371c9d4SSatish Balay           }
12896bdcaf15SBarry 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);
12908c4a67a0SStefano Zampini           av[indexn[j] * mat->lda + indexm[i]] += v ? v[idx++] : (idx++, 0.0);
1291289bc588SBarry Smith         }
1292289bc588SBarry Smith       }
1293289bc588SBarry Smith     }
1294e8d4e0b9SBarry Smith   }
1295ca15aa20SStefano Zampini   /* hack to prevent unneeded copy to the GPU while returning the array */
129647d993e7Ssuyashtn #if defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
1297c70f7ee4SJunchao Zhang   oldf           = A->offloadmask;
1298c70f7ee4SJunchao Zhang   A->offloadmask = PETSC_OFFLOAD_GPU;
1299ca15aa20SStefano Zampini #endif
13009566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArray(A, &av));
130147d993e7Ssuyashtn #if defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
1302c70f7ee4SJunchao Zhang   A->offloadmask = (oldf == PETSC_OFFLOAD_UNALLOCATED ? PETSC_OFFLOAD_UNALLOCATED : PETSC_OFFLOAD_CPU);
1303ca15aa20SStefano Zampini #endif
13043ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1305289bc588SBarry Smith }
1306e8d4e0b9SBarry Smith 
1307d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatGetValues_SeqDense(Mat A, PetscInt m, const PetscInt indexm[], PetscInt n, const PetscInt indexn[], PetscScalar v[])
1308d71ae5a4SJacob Faibussowitsch {
1309ae80bb75SLois Curfman McInnes   Mat_SeqDense      *mat = (Mat_SeqDense *)A->data;
1310ca15aa20SStefano Zampini   const PetscScalar *vv;
131113f74950SBarry Smith   PetscInt           i, j;
1312ae80bb75SLois Curfman McInnes 
13133a40ed3dSBarry Smith   PetscFunctionBegin;
13149566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArrayRead(A, &vv));
1315ae80bb75SLois Curfman McInnes   /* row-oriented output */
1316ae80bb75SLois Curfman McInnes   for (i = 0; i < m; i++) {
13179371c9d4SSatish Balay     if (indexm[i] < 0) {
13189371c9d4SSatish Balay       v += n;
13199371c9d4SSatish Balay       continue;
13209371c9d4SSatish Balay     }
132108401ef6SPierre 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);
1322ae80bb75SLois Curfman McInnes     for (j = 0; j < n; j++) {
13239371c9d4SSatish Balay       if (indexn[j] < 0) {
13249371c9d4SSatish Balay         v++;
13259371c9d4SSatish Balay         continue;
13269371c9d4SSatish Balay       }
132708401ef6SPierre 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);
1328ca15aa20SStefano Zampini       *v++ = vv[indexn[j] * mat->lda + indexm[i]];
1329ae80bb75SLois Curfman McInnes     }
1330ae80bb75SLois Curfman McInnes   }
13319566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArrayRead(A, &vv));
13323ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1333ae80bb75SLois Curfman McInnes }
1334ae80bb75SLois Curfman McInnes 
1335d71ae5a4SJacob Faibussowitsch PetscErrorCode MatView_Dense_Binary(Mat mat, PetscViewer viewer)
1336d71ae5a4SJacob Faibussowitsch {
13378491ab44SLisandro Dalcin   PetscBool          skipHeader;
13388491ab44SLisandro Dalcin   PetscViewerFormat  format;
13393e1d7bceSPierre Jolivet   PetscInt           header[4], M, N, m, lda, i, j;
13403e1d7bceSPierre Jolivet   PetscCount         k;
13418491ab44SLisandro Dalcin   const PetscScalar *v;
13428491ab44SLisandro Dalcin   PetscScalar       *vwork;
1343aabbc4fbSShri Abhyankar 
1344aabbc4fbSShri Abhyankar   PetscFunctionBegin;
13459566063dSJacob Faibussowitsch   PetscCall(PetscViewerSetUp(viewer));
13469566063dSJacob Faibussowitsch   PetscCall(PetscViewerBinaryGetSkipHeader(viewer, &skipHeader));
13479566063dSJacob Faibussowitsch   PetscCall(PetscViewerGetFormat(viewer, &format));
13488491ab44SLisandro Dalcin   if (skipHeader) format = PETSC_VIEWER_NATIVE;
1349aabbc4fbSShri Abhyankar 
13509566063dSJacob Faibussowitsch   PetscCall(MatGetSize(mat, &M, &N));
13518491ab44SLisandro Dalcin 
13528491ab44SLisandro Dalcin   /* write matrix header */
13539371c9d4SSatish Balay   header[0] = MAT_FILE_CLASSID;
13549371c9d4SSatish Balay   header[1] = M;
13559371c9d4SSatish Balay   header[2] = N;
13568491ab44SLisandro Dalcin   header[3] = (format == PETSC_VIEWER_NATIVE) ? MATRIX_BINARY_FORMAT_DENSE : M * N;
13579566063dSJacob Faibussowitsch   if (!skipHeader) PetscCall(PetscViewerBinaryWrite(viewer, header, 4, PETSC_INT));
13588491ab44SLisandro Dalcin 
13599566063dSJacob Faibussowitsch   PetscCall(MatGetLocalSize(mat, &m, NULL));
13608491ab44SLisandro Dalcin   if (format != PETSC_VIEWER_NATIVE) {
13618491ab44SLisandro Dalcin     PetscInt nnz = m * N, *iwork;
13628491ab44SLisandro Dalcin     /* store row lengths for each row */
13639566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(nnz, &iwork));
13648491ab44SLisandro Dalcin     for (i = 0; i < m; i++) iwork[i] = N;
13659566063dSJacob Faibussowitsch     PetscCall(PetscViewerBinaryWriteAll(viewer, iwork, m, PETSC_DETERMINE, PETSC_DETERMINE, PETSC_INT));
13668491ab44SLisandro Dalcin     /* store column indices (zero start index) */
13678491ab44SLisandro Dalcin     for (k = 0, i = 0; i < m; i++)
13689371c9d4SSatish Balay       for (j = 0; j < N; j++, k++) iwork[k] = j;
13699566063dSJacob Faibussowitsch     PetscCall(PetscViewerBinaryWriteAll(viewer, iwork, nnz, PETSC_DETERMINE, PETSC_DETERMINE, PETSC_INT));
13709566063dSJacob Faibussowitsch     PetscCall(PetscFree(iwork));
13718491ab44SLisandro Dalcin   }
13728491ab44SLisandro Dalcin   /* store matrix values as a dense matrix in row major order */
13739566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(m * N, &vwork));
13749566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArrayRead(mat, &v));
13759566063dSJacob Faibussowitsch   PetscCall(MatDenseGetLDA(mat, &lda));
13768491ab44SLisandro Dalcin   for (k = 0, i = 0; i < m; i++)
13773e1d7bceSPierre Jolivet     for (j = 0; j < N; j++, k++) vwork[k] = v[i + (size_t)lda * j];
13789566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArrayRead(mat, &v));
13799566063dSJacob Faibussowitsch   PetscCall(PetscViewerBinaryWriteAll(viewer, vwork, m * N, PETSC_DETERMINE, PETSC_DETERMINE, PETSC_SCALAR));
13809566063dSJacob Faibussowitsch   PetscCall(PetscFree(vwork));
13813ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
13828491ab44SLisandro Dalcin }
13838491ab44SLisandro Dalcin 
1384d71ae5a4SJacob Faibussowitsch PetscErrorCode MatLoad_Dense_Binary(Mat mat, PetscViewer viewer)
1385d71ae5a4SJacob Faibussowitsch {
13868491ab44SLisandro Dalcin   PetscBool    skipHeader;
13878491ab44SLisandro Dalcin   PetscInt     header[4], M, N, m, nz, lda, i, j, k;
13888491ab44SLisandro Dalcin   PetscInt     rows, cols;
13898491ab44SLisandro Dalcin   PetscScalar *v, *vwork;
13908491ab44SLisandro Dalcin 
13918491ab44SLisandro Dalcin   PetscFunctionBegin;
13929566063dSJacob Faibussowitsch   PetscCall(PetscViewerSetUp(viewer));
13939566063dSJacob Faibussowitsch   PetscCall(PetscViewerBinaryGetSkipHeader(viewer, &skipHeader));
13948491ab44SLisandro Dalcin 
13958491ab44SLisandro Dalcin   if (!skipHeader) {
13969566063dSJacob Faibussowitsch     PetscCall(PetscViewerBinaryRead(viewer, header, 4, NULL, PETSC_INT));
139708401ef6SPierre Jolivet     PetscCheck(header[0] == MAT_FILE_CLASSID, PetscObjectComm((PetscObject)viewer), PETSC_ERR_FILE_UNEXPECTED, "Not a matrix object in file");
13989371c9d4SSatish Balay     M = header[1];
13999371c9d4SSatish Balay     N = header[2];
140008401ef6SPierre Jolivet     PetscCheck(M >= 0, PetscObjectComm((PetscObject)viewer), PETSC_ERR_FILE_UNEXPECTED, "Matrix row size (%" PetscInt_FMT ") in file is negative", M);
140108401ef6SPierre Jolivet     PetscCheck(N >= 0, PetscObjectComm((PetscObject)viewer), PETSC_ERR_FILE_UNEXPECTED, "Matrix column size (%" PetscInt_FMT ") in file is negative", N);
14028491ab44SLisandro Dalcin     nz = header[3];
1403aed4548fSBarry Smith     PetscCheck(nz == MATRIX_BINARY_FORMAT_DENSE || nz >= 0, PetscObjectComm((PetscObject)viewer), PETSC_ERR_FILE_UNEXPECTED, "Unknown matrix format %" PetscInt_FMT " in file", nz);
1404aabbc4fbSShri Abhyankar   } else {
14059566063dSJacob Faibussowitsch     PetscCall(MatGetSize(mat, &M, &N));
1406aed4548fSBarry 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");
14078491ab44SLisandro Dalcin     nz = MATRIX_BINARY_FORMAT_DENSE;
1408e6324fbbSBarry Smith   }
1409aabbc4fbSShri Abhyankar 
14108491ab44SLisandro Dalcin   /* setup global sizes if not set */
14118491ab44SLisandro Dalcin   if (mat->rmap->N < 0) mat->rmap->N = M;
14128491ab44SLisandro Dalcin   if (mat->cmap->N < 0) mat->cmap->N = N;
14139566063dSJacob Faibussowitsch   PetscCall(MatSetUp(mat));
14148491ab44SLisandro Dalcin   /* check if global sizes are correct */
14159566063dSJacob Faibussowitsch   PetscCall(MatGetSize(mat, &rows, &cols));
1416aed4548fSBarry 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);
1417aabbc4fbSShri Abhyankar 
14189566063dSJacob Faibussowitsch   PetscCall(MatGetSize(mat, NULL, &N));
14199566063dSJacob Faibussowitsch   PetscCall(MatGetLocalSize(mat, &m, NULL));
14209566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArray(mat, &v));
14219566063dSJacob Faibussowitsch   PetscCall(MatDenseGetLDA(mat, &lda));
14228491ab44SLisandro Dalcin   if (nz == MATRIX_BINARY_FORMAT_DENSE) { /* matrix in file is dense format */
14233e1d7bceSPierre Jolivet     PetscCount nnz = (size_t)m * N;
14248491ab44SLisandro Dalcin     /* read in matrix values */
14259566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(nnz, &vwork));
14269566063dSJacob Faibussowitsch     PetscCall(PetscViewerBinaryReadAll(viewer, vwork, nnz, PETSC_DETERMINE, PETSC_DETERMINE, PETSC_SCALAR));
14278491ab44SLisandro Dalcin     /* store values in column major order */
14288491ab44SLisandro Dalcin     for (j = 0; j < N; j++)
14293e1d7bceSPierre Jolivet       for (i = 0; i < m; i++) v[i + (size_t)lda * j] = vwork[(size_t)i * N + j];
14309566063dSJacob Faibussowitsch     PetscCall(PetscFree(vwork));
14318491ab44SLisandro Dalcin   } else { /* matrix in file is sparse format */
14328491ab44SLisandro Dalcin     PetscInt nnz = 0, *rlens, *icols;
14338491ab44SLisandro Dalcin     /* read in row lengths */
14349566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(m, &rlens));
14359566063dSJacob Faibussowitsch     PetscCall(PetscViewerBinaryReadAll(viewer, rlens, m, PETSC_DETERMINE, PETSC_DETERMINE, PETSC_INT));
14368491ab44SLisandro Dalcin     for (i = 0; i < m; i++) nnz += rlens[i];
14378491ab44SLisandro Dalcin     /* read in column indices and values */
14389566063dSJacob Faibussowitsch     PetscCall(PetscMalloc2(nnz, &icols, nnz, &vwork));
14399566063dSJacob Faibussowitsch     PetscCall(PetscViewerBinaryReadAll(viewer, icols, nnz, PETSC_DETERMINE, PETSC_DETERMINE, PETSC_INT));
14409566063dSJacob Faibussowitsch     PetscCall(PetscViewerBinaryReadAll(viewer, vwork, nnz, PETSC_DETERMINE, PETSC_DETERMINE, PETSC_SCALAR));
14418491ab44SLisandro Dalcin     /* store values in column major order */
14428491ab44SLisandro Dalcin     for (k = 0, i = 0; i < m; i++)
14439371c9d4SSatish Balay       for (j = 0; j < rlens[i]; j++, k++) v[i + lda * icols[k]] = vwork[k];
14449566063dSJacob Faibussowitsch     PetscCall(PetscFree(rlens));
14459566063dSJacob Faibussowitsch     PetscCall(PetscFree2(icols, vwork));
1446aabbc4fbSShri Abhyankar   }
14479566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArray(mat, &v));
14489566063dSJacob Faibussowitsch   PetscCall(MatAssemblyBegin(mat, MAT_FINAL_ASSEMBLY));
14499566063dSJacob Faibussowitsch   PetscCall(MatAssemblyEnd(mat, MAT_FINAL_ASSEMBLY));
14503ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1451aabbc4fbSShri Abhyankar }
1452aabbc4fbSShri Abhyankar 
145366976f2fSJacob Faibussowitsch static PetscErrorCode MatLoad_SeqDense(Mat newMat, PetscViewer viewer)
1454d71ae5a4SJacob Faibussowitsch {
1455eb91f321SVaclav Hapla   PetscBool isbinary, ishdf5;
1456eb91f321SVaclav Hapla 
1457eb91f321SVaclav Hapla   PetscFunctionBegin;
1458eb91f321SVaclav Hapla   PetscValidHeaderSpecific(newMat, MAT_CLASSID, 1);
1459eb91f321SVaclav Hapla   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
1460eb91f321SVaclav Hapla   /* force binary viewer to load .info file if it has not yet done so */
14619566063dSJacob Faibussowitsch   PetscCall(PetscViewerSetUp(viewer));
14629566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERBINARY, &isbinary));
14639566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5));
1464eb91f321SVaclav Hapla   if (isbinary) {
14659566063dSJacob Faibussowitsch     PetscCall(MatLoad_Dense_Binary(newMat, viewer));
1466eb91f321SVaclav Hapla   } else if (ishdf5) {
1467eb91f321SVaclav Hapla #if defined(PETSC_HAVE_HDF5)
14689566063dSJacob Faibussowitsch     PetscCall(MatLoad_Dense_HDF5(newMat, viewer));
1469eb91f321SVaclav Hapla #else
1470eb91f321SVaclav Hapla     SETERRQ(PetscObjectComm((PetscObject)newMat), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5");
1471eb91f321SVaclav Hapla #endif
1472eb91f321SVaclav Hapla   } else {
147398921bdaSJacob 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);
1474eb91f321SVaclav Hapla   }
14753ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1476eb91f321SVaclav Hapla }
1477eb91f321SVaclav Hapla 
1478d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatView_SeqDense_ASCII(Mat A, PetscViewer viewer)
1479d71ae5a4SJacob Faibussowitsch {
1480932b0c3eSLois Curfman McInnes   Mat_SeqDense     *a = (Mat_SeqDense *)A->data;
148113f74950SBarry Smith   PetscInt          i, j;
14822dcb1b2aSMatthew Knepley   const char       *name;
1483ca15aa20SStefano Zampini   PetscScalar      *v, *av;
1484f3ef73ceSBarry Smith   PetscViewerFormat format;
14855f481a85SSatish Balay #if defined(PETSC_USE_COMPLEX)
1486ace3abfcSBarry Smith   PetscBool allreal = PETSC_TRUE;
14875f481a85SSatish Balay #endif
1488932b0c3eSLois Curfman McInnes 
14893a40ed3dSBarry Smith   PetscFunctionBegin;
14909566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArrayRead(A, (const PetscScalar **)&av));
14919566063dSJacob Faibussowitsch   PetscCall(PetscViewerGetFormat(viewer, &format));
1492456192e2SBarry Smith   if (format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL) {
14933ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS); /* do nothing for now */
1494fb9695e5SSatish Balay   } else if (format == PETSC_VIEWER_ASCII_COMMON) {
14959566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIUseTabs(viewer, PETSC_FALSE));
1496d0f46423SBarry Smith     for (i = 0; i < A->rmap->n; i++) {
1497ca15aa20SStefano Zampini       v = av + i;
14989566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "row %" PetscInt_FMT ":", i));
1499d0f46423SBarry Smith       for (j = 0; j < A->cmap->n; j++) {
1500aa482453SBarry Smith #if defined(PETSC_USE_COMPLEX)
1501329f5518SBarry Smith         if (PetscRealPart(*v) != 0.0 && PetscImaginaryPart(*v) != 0.0) {
15029566063dSJacob Faibussowitsch           PetscCall(PetscViewerASCIIPrintf(viewer, " (%" PetscInt_FMT ", %g + %g i) ", j, (double)PetscRealPart(*v), (double)PetscImaginaryPart(*v)));
1503329f5518SBarry Smith         } else if (PetscRealPart(*v)) {
15049566063dSJacob Faibussowitsch           PetscCall(PetscViewerASCIIPrintf(viewer, " (%" PetscInt_FMT ", %g) ", j, (double)PetscRealPart(*v)));
15056831982aSBarry Smith         }
150680cd9d93SLois Curfman McInnes #else
150748a46eb9SPierre Jolivet         if (*v) PetscCall(PetscViewerASCIIPrintf(viewer, " (%" PetscInt_FMT ", %g) ", j, (double)*v));
150880cd9d93SLois Curfman McInnes #endif
15091b807ce4Svictorle         v += a->lda;
151080cd9d93SLois Curfman McInnes       }
15119566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "\n"));
151280cd9d93SLois Curfman McInnes     }
15139566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIUseTabs(viewer, PETSC_TRUE));
15143a40ed3dSBarry Smith   } else {
15159566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIUseTabs(viewer, PETSC_FALSE));
1516aa482453SBarry Smith #if defined(PETSC_USE_COMPLEX)
151747989497SBarry Smith     /* determine if matrix has all real values */
1518bcd8d3a4SJose E. Roman     for (j = 0; j < A->cmap->n; j++) {
1519bcd8d3a4SJose E. Roman       v = av + j * a->lda;
1520bcd8d3a4SJose E. Roman       for (i = 0; i < A->rmap->n; i++) {
15219371c9d4SSatish Balay         if (PetscImaginaryPart(v[i])) {
15229371c9d4SSatish Balay           allreal = PETSC_FALSE;
15239371c9d4SSatish Balay           break;
15249371c9d4SSatish Balay         }
152547989497SBarry Smith       }
1526bcd8d3a4SJose E. Roman     }
152747989497SBarry Smith #endif
1528fb9695e5SSatish Balay     if (format == PETSC_VIEWER_ASCII_MATLAB) {
15299566063dSJacob Faibussowitsch       PetscCall(PetscObjectGetName((PetscObject)A, &name));
15309566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "%% Size = %" PetscInt_FMT " %" PetscInt_FMT " \n", A->rmap->n, A->cmap->n));
15319566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "%s = zeros(%" PetscInt_FMT ",%" PetscInt_FMT ");\n", name, A->rmap->n, A->cmap->n));
15329566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "%s = [\n", name));
1533ffac6cdbSBarry Smith     }
1534ffac6cdbSBarry Smith 
1535d0f46423SBarry Smith     for (i = 0; i < A->rmap->n; i++) {
1536ca15aa20SStefano Zampini       v = av + i;
1537d0f46423SBarry Smith       for (j = 0; j < A->cmap->n; j++) {
1538aa482453SBarry Smith #if defined(PETSC_USE_COMPLEX)
153947989497SBarry Smith         if (allreal) {
15409566063dSJacob Faibussowitsch           PetscCall(PetscViewerASCIIPrintf(viewer, "%18.16e ", (double)PetscRealPart(*v)));
154147989497SBarry Smith         } else {
15429566063dSJacob Faibussowitsch           PetscCall(PetscViewerASCIIPrintf(viewer, "%18.16e + %18.16ei ", (double)PetscRealPart(*v), (double)PetscImaginaryPart(*v)));
154347989497SBarry Smith         }
1544289bc588SBarry Smith #else
15459566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, "%18.16e ", (double)*v));
1546289bc588SBarry Smith #endif
15471b807ce4Svictorle         v += a->lda;
1548289bc588SBarry Smith       }
15499566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "\n"));
1550289bc588SBarry Smith     }
155148a46eb9SPierre Jolivet     if (format == PETSC_VIEWER_ASCII_MATLAB) PetscCall(PetscViewerASCIIPrintf(viewer, "];\n"));
15529566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIUseTabs(viewer, PETSC_TRUE));
1553da3a660dSBarry Smith   }
15549566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArrayRead(A, (const PetscScalar **)&av));
15559566063dSJacob Faibussowitsch   PetscCall(PetscViewerFlush(viewer));
15563ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1557289bc588SBarry Smith }
1558289bc588SBarry Smith 
15599804daf3SBarry Smith #include <petscdraw.h>
1560d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatView_SeqDense_Draw_Zoom(PetscDraw draw, void *Aa)
1561d71ae5a4SJacob Faibussowitsch {
1562f1af5d2fSBarry Smith   Mat                A = (Mat)Aa;
1563383922c3SLisandro Dalcin   PetscInt           m = A->rmap->n, n = A->cmap->n, i, j;
1564383922c3SLisandro Dalcin   int                color = PETSC_DRAW_WHITE;
1565ca15aa20SStefano Zampini   const PetscScalar *v;
1566b0a32e0cSBarry Smith   PetscViewer        viewer;
1567b05fc000SLisandro Dalcin   PetscReal          xl, yl, xr, yr, x_l, x_r, y_l, y_r;
1568f3ef73ceSBarry Smith   PetscViewerFormat  format;
1569f1af5d2fSBarry Smith 
1570f1af5d2fSBarry Smith   PetscFunctionBegin;
15719566063dSJacob Faibussowitsch   PetscCall(PetscObjectQuery((PetscObject)A, "Zoomviewer", (PetscObject *)&viewer));
15729566063dSJacob Faibussowitsch   PetscCall(PetscViewerGetFormat(viewer, &format));
15739566063dSJacob Faibussowitsch   PetscCall(PetscDrawGetCoordinates(draw, &xl, &yl, &xr, &yr));
1574f1af5d2fSBarry Smith 
1575f1af5d2fSBarry Smith   /* Loop over matrix elements drawing boxes */
15769566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArrayRead(A, &v));
1577fb9695e5SSatish Balay   if (format != PETSC_VIEWER_DRAW_CONTOUR) {
1578d0609cedSBarry Smith     PetscDrawCollectiveBegin(draw);
1579f1af5d2fSBarry Smith     /* Blue for negative and Red for positive */
1580f1af5d2fSBarry Smith     for (j = 0; j < n; j++) {
15819371c9d4SSatish Balay       x_l = j;
15829371c9d4SSatish Balay       x_r = x_l + 1.0;
1583f1af5d2fSBarry Smith       for (i = 0; i < m; i++) {
1584f1af5d2fSBarry Smith         y_l = m - i - 1.0;
1585f1af5d2fSBarry Smith         y_r = y_l + 1.0;
1586ca15aa20SStefano Zampini         if (PetscRealPart(v[j * m + i]) > 0.) color = PETSC_DRAW_RED;
1587ca15aa20SStefano Zampini         else if (PetscRealPart(v[j * m + i]) < 0.) color = PETSC_DRAW_BLUE;
1588ca15aa20SStefano Zampini         else continue;
15899566063dSJacob Faibussowitsch         PetscCall(PetscDrawRectangle(draw, x_l, y_l, x_r, y_r, color, color, color, color));
1590f1af5d2fSBarry Smith       }
1591f1af5d2fSBarry Smith     }
1592d0609cedSBarry Smith     PetscDrawCollectiveEnd(draw);
1593f1af5d2fSBarry Smith   } else {
1594f1af5d2fSBarry Smith     /* use contour shading to indicate magnitude of values */
1595f1af5d2fSBarry Smith     /* first determine max of all nonzero values */
1596b05fc000SLisandro Dalcin     PetscReal minv = 0.0, maxv = 0.0;
1597b05fc000SLisandro Dalcin     PetscDraw popup;
1598b05fc000SLisandro Dalcin 
1599f1af5d2fSBarry Smith     for (i = 0; i < m * n; i++) {
1600f1af5d2fSBarry Smith       if (PetscAbsScalar(v[i]) > maxv) maxv = PetscAbsScalar(v[i]);
1601f1af5d2fSBarry Smith     }
1602383922c3SLisandro Dalcin     if (minv >= maxv) maxv = minv + PETSC_SMALL;
16039566063dSJacob Faibussowitsch     PetscCall(PetscDrawGetPopup(draw, &popup));
16049566063dSJacob Faibussowitsch     PetscCall(PetscDrawScalePopup(popup, minv, maxv));
1605383922c3SLisandro Dalcin 
1606d0609cedSBarry Smith     PetscDrawCollectiveBegin(draw);
1607f1af5d2fSBarry Smith     for (j = 0; j < n; j++) {
1608f1af5d2fSBarry Smith       x_l = j;
1609f1af5d2fSBarry Smith       x_r = x_l + 1.0;
1610f1af5d2fSBarry Smith       for (i = 0; i < m; i++) {
1611f1af5d2fSBarry Smith         y_l   = m - i - 1.0;
1612f1af5d2fSBarry Smith         y_r   = y_l + 1.0;
1613b05fc000SLisandro Dalcin         color = PetscDrawRealToColor(PetscAbsScalar(v[j * m + i]), minv, maxv);
16149566063dSJacob Faibussowitsch         PetscCall(PetscDrawRectangle(draw, x_l, y_l, x_r, y_r, color, color, color, color));
1615f1af5d2fSBarry Smith       }
1616f1af5d2fSBarry Smith     }
1617d0609cedSBarry Smith     PetscDrawCollectiveEnd(draw);
1618f1af5d2fSBarry Smith   }
16199566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArrayRead(A, &v));
16203ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1621f1af5d2fSBarry Smith }
1622f1af5d2fSBarry Smith 
1623d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatView_SeqDense_Draw(Mat A, PetscViewer viewer)
1624d71ae5a4SJacob Faibussowitsch {
1625b0a32e0cSBarry Smith   PetscDraw draw;
1626ace3abfcSBarry Smith   PetscBool isnull;
1627329f5518SBarry Smith   PetscReal xr, yr, xl, yl, h, w;
1628f1af5d2fSBarry Smith 
1629f1af5d2fSBarry Smith   PetscFunctionBegin;
16309566063dSJacob Faibussowitsch   PetscCall(PetscViewerDrawGetDraw(viewer, 0, &draw));
16319566063dSJacob Faibussowitsch   PetscCall(PetscDrawIsNull(draw, &isnull));
16323ba16761SJacob Faibussowitsch   if (isnull) PetscFunctionReturn(PETSC_SUCCESS);
1633f1af5d2fSBarry Smith 
16349371c9d4SSatish Balay   xr = A->cmap->n;
16359371c9d4SSatish Balay   yr = A->rmap->n;
16369371c9d4SSatish Balay   h  = yr / 10.0;
16379371c9d4SSatish Balay   w  = xr / 10.0;
16389371c9d4SSatish Balay   xr += w;
16399371c9d4SSatish Balay   yr += h;
16409371c9d4SSatish Balay   xl = -w;
16419371c9d4SSatish Balay   yl = -h;
16429566063dSJacob Faibussowitsch   PetscCall(PetscDrawSetCoordinates(draw, xl, yl, xr, yr));
16439566063dSJacob Faibussowitsch   PetscCall(PetscObjectCompose((PetscObject)A, "Zoomviewer", (PetscObject)viewer));
16449566063dSJacob Faibussowitsch   PetscCall(PetscDrawZoom(draw, MatView_SeqDense_Draw_Zoom, A));
16459566063dSJacob Faibussowitsch   PetscCall(PetscObjectCompose((PetscObject)A, "Zoomviewer", NULL));
16469566063dSJacob Faibussowitsch   PetscCall(PetscDrawSave(draw));
16473ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1648f1af5d2fSBarry Smith }
1649f1af5d2fSBarry Smith 
1650d71ae5a4SJacob Faibussowitsch PetscErrorCode MatView_SeqDense(Mat A, PetscViewer viewer)
1651d71ae5a4SJacob Faibussowitsch {
1652ace3abfcSBarry Smith   PetscBool iascii, isbinary, isdraw;
1653932b0c3eSLois Curfman McInnes 
16543a40ed3dSBarry Smith   PetscFunctionBegin;
16559566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
16569566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERBINARY, &isbinary));
16579566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERDRAW, &isdraw));
16581baa6e33SBarry Smith   if (iascii) PetscCall(MatView_SeqDense_ASCII(A, viewer));
16591baa6e33SBarry Smith   else if (isbinary) PetscCall(MatView_Dense_Binary(A, viewer));
16601baa6e33SBarry Smith   else if (isdraw) PetscCall(MatView_SeqDense_Draw(A, viewer));
16613ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1662932b0c3eSLois Curfman McInnes }
1663289bc588SBarry Smith 
1664d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatDensePlaceArray_SeqDense(Mat A, const PetscScalar *array)
1665d71ae5a4SJacob Faibussowitsch {
1666d3042a70SBarry Smith   Mat_SeqDense *a = (Mat_SeqDense *)A->data;
1667d3042a70SBarry Smith 
1668d3042a70SBarry Smith   PetscFunctionBegin;
166928b400f6SJacob Faibussowitsch   PetscCheck(!a->vecinuse, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Need to call MatDenseRestoreColumnVec() first");
167028b400f6SJacob Faibussowitsch   PetscCheck(!a->matinuse, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Need to call MatDenseRestoreSubMatrix() first");
16716635c364SPierre Jolivet   PetscCheck(!a->unplacedarray, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Need to call MatDenseResetArray() first");
1672d3042a70SBarry Smith   a->unplacedarray       = a->v;
1673d3042a70SBarry Smith   a->unplaced_user_alloc = a->user_alloc;
1674d3042a70SBarry Smith   a->v                   = (PetscScalar *)array;
1675637a0070SStefano Zampini   a->user_alloc          = PETSC_TRUE;
167647d993e7Ssuyashtn #if defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
1677c70f7ee4SJunchao Zhang   A->offloadmask = PETSC_OFFLOAD_CPU;
1678ca15aa20SStefano Zampini #endif
16793ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1680d3042a70SBarry Smith }
1681d3042a70SBarry Smith 
1682d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatDenseResetArray_SeqDense(Mat A)
1683d71ae5a4SJacob Faibussowitsch {
1684d3042a70SBarry Smith   Mat_SeqDense *a = (Mat_SeqDense *)A->data;
1685d3042a70SBarry Smith 
1686d3042a70SBarry Smith   PetscFunctionBegin;
168728b400f6SJacob Faibussowitsch   PetscCheck(!a->vecinuse, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Need to call MatDenseRestoreColumnVec() first");
168828b400f6SJacob Faibussowitsch   PetscCheck(!a->matinuse, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Need to call MatDenseRestoreSubMatrix() first");
1689d3042a70SBarry Smith   a->v             = a->unplacedarray;
1690d3042a70SBarry Smith   a->user_alloc    = a->unplaced_user_alloc;
1691d3042a70SBarry Smith   a->unplacedarray = NULL;
169247d993e7Ssuyashtn #if defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
1693c70f7ee4SJunchao Zhang   A->offloadmask = PETSC_OFFLOAD_CPU;
1694ca15aa20SStefano Zampini #endif
16953ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1696d3042a70SBarry Smith }
1697d3042a70SBarry Smith 
1698d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatDenseReplaceArray_SeqDense(Mat A, const PetscScalar *array)
1699d71ae5a4SJacob Faibussowitsch {
1700d5ea218eSStefano Zampini   Mat_SeqDense *a = (Mat_SeqDense *)A->data;
1701d5ea218eSStefano Zampini 
1702d5ea218eSStefano Zampini   PetscFunctionBegin;
170328b400f6SJacob Faibussowitsch   PetscCheck(!a->vecinuse, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Need to call MatDenseRestoreColumnVec() first");
170428b400f6SJacob Faibussowitsch   PetscCheck(!a->matinuse, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Need to call MatDenseRestoreSubMatrix() first");
17059566063dSJacob Faibussowitsch   if (!a->user_alloc) PetscCall(PetscFree(a->v));
1706d5ea218eSStefano Zampini   a->v          = (PetscScalar *)array;
1707d5ea218eSStefano Zampini   a->user_alloc = PETSC_FALSE;
170847d993e7Ssuyashtn #if defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
1709d5ea218eSStefano Zampini   A->offloadmask = PETSC_OFFLOAD_CPU;
1710d5ea218eSStefano Zampini #endif
17113ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1712d5ea218eSStefano Zampini }
1713d5ea218eSStefano Zampini 
1714d71ae5a4SJacob Faibussowitsch PetscErrorCode MatDestroy_SeqDense(Mat mat)
1715d71ae5a4SJacob Faibussowitsch {
1716ec8511deSBarry Smith   Mat_SeqDense *l = (Mat_SeqDense *)mat->data;
171790f02eecSBarry Smith 
17183a40ed3dSBarry Smith   PetscFunctionBegin;
17193ba16761SJacob Faibussowitsch   PetscCall(PetscLogObjectState((PetscObject)mat, "Rows %" PetscInt_FMT " Cols %" PetscInt_FMT, mat->rmap->n, mat->cmap->n));
1720f4f49eeaSPierre Jolivet   PetscCall(VecDestroy(&l->qrrhs));
17219566063dSJacob Faibussowitsch   PetscCall(PetscFree(l->tau));
17229566063dSJacob Faibussowitsch   PetscCall(PetscFree(l->pivots));
17239566063dSJacob Faibussowitsch   PetscCall(PetscFree(l->fwork));
17249566063dSJacob Faibussowitsch   if (!l->user_alloc) PetscCall(PetscFree(l->v));
17259566063dSJacob Faibussowitsch   if (!l->unplaced_user_alloc) PetscCall(PetscFree(l->unplacedarray));
172628b400f6SJacob Faibussowitsch   PetscCheck(!l->vecinuse, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Need to call MatDenseRestoreColumnVec() first");
172728b400f6SJacob Faibussowitsch   PetscCheck(!l->matinuse, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Need to call MatDenseRestoreSubMatrix() first");
17289566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&l->cvec));
17299566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&l->cmat));
17309566063dSJacob Faibussowitsch   PetscCall(PetscFree(mat->data));
1731dbd8c25aSHong Zhang 
17329566063dSJacob Faibussowitsch   PetscCall(PetscObjectChangeTypeName((PetscObject)mat, NULL));
17339566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatQRFactor_C", NULL));
17342e956fe4SStefano Zampini   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatQRFactorSymbolic_C", NULL));
17352e956fe4SStefano Zampini   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatQRFactorNumeric_C", NULL));
17369566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatDenseGetLDA_C", NULL));
17379566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatDenseSetLDA_C", NULL));
17389566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatDenseGetArray_C", NULL));
17399566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatDenseRestoreArray_C", NULL));
17409566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatDensePlaceArray_C", NULL));
17419566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatDenseResetArray_C", NULL));
17429566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatDenseReplaceArray_C", NULL));
17439566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatDenseGetArrayRead_C", NULL));
17449566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatDenseRestoreArrayRead_C", NULL));
17459566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatDenseGetArrayWrite_C", NULL));
17469566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatDenseRestoreArrayWrite_C", NULL));
17479566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatConvert_seqdense_seqaij_C", NULL));
17488baccfbdSHong Zhang #if defined(PETSC_HAVE_ELEMENTAL)
17499566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatConvert_seqdense_elemental_C", NULL));
17508baccfbdSHong Zhang #endif
1751d24d4204SJose E. Roman #if defined(PETSC_HAVE_SCALAPACK)
17529566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatConvert_seqdense_scalapack_C", NULL));
1753d24d4204SJose E. Roman #endif
17542bf066beSStefano Zampini #if defined(PETSC_HAVE_CUDA)
17559566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatConvert_seqdense_seqdensecuda_C", NULL));
17569566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatProductSetFromOptions_seqdensecuda_seqdensecuda_C", NULL));
17579566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatProductSetFromOptions_seqdensecuda_seqdense_C", NULL));
17582e956fe4SStefano Zampini   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatProductSetFromOptions_seqdense_seqdensecuda_C", NULL));
17592bf066beSStefano Zampini #endif
176047d993e7Ssuyashtn #if defined(PETSC_HAVE_HIP)
176147d993e7Ssuyashtn   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatConvert_seqdense_seqdensehip_C", NULL));
176247d993e7Ssuyashtn   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatProductSetFromOptions_seqdensehip_seqdensehip_C", NULL));
176347d993e7Ssuyashtn   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatProductSetFromOptions_seqdensehip_seqdense_C", NULL));
176447d993e7Ssuyashtn   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatProductSetFromOptions_seqdense_seqdensehip_C", NULL));
176547d993e7Ssuyashtn #endif
17669566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatSeqDenseSetPreallocation_C", NULL));
17679566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatProductSetFromOptions_seqaij_seqdense_C", NULL));
17689566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatProductSetFromOptions_seqdense_seqdense_C", NULL));
17699566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatProductSetFromOptions_seqbaij_seqdense_C", NULL));
17709566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatProductSetFromOptions_seqsbaij_seqdense_C", NULL));
177152c5f739Sprj- 
17729566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatDenseGetColumn_C", NULL));
17739566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatDenseRestoreColumn_C", NULL));
17749566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatDenseGetColumnVec_C", NULL));
17759566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatDenseRestoreColumnVec_C", NULL));
17769566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatDenseGetColumnVecRead_C", NULL));
17779566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatDenseRestoreColumnVecRead_C", NULL));
17789566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatDenseGetColumnVecWrite_C", NULL));
17799566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatDenseRestoreColumnVecWrite_C", NULL));
17809566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatDenseGetSubMatrix_C", NULL));
17819566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatDenseRestoreSubMatrix_C", NULL));
17820be0d8bdSHansol Suh   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatMultAddColumnRange_C", NULL));
17830be0d8bdSHansol Suh   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatMultHermitianTransposeColumnRange_C", NULL));
17840be0d8bdSHansol Suh   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatMultHermitianTransposeAddColumnRange_C", NULL));
17853ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1786289bc588SBarry Smith }
1787289bc588SBarry Smith 
1788d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatTranspose_SeqDense(Mat A, MatReuse reuse, Mat *matout)
1789d71ae5a4SJacob Faibussowitsch {
1790c0bbcb79SLois Curfman McInnes   Mat_SeqDense *mat = (Mat_SeqDense *)A->data;
17916536e3caSStefano Zampini   PetscInt      k, j, m = A->rmap->n, M = mat->lda, n = A->cmap->n;
179287828ca2SBarry Smith   PetscScalar  *v, tmp;
179348b35521SBarry Smith 
17943a40ed3dSBarry Smith   PetscFunctionBegin;
17957fb60732SBarry Smith   if (reuse == MAT_REUSE_MATRIX) PetscCall(MatTransposeCheckNonzeroState_Private(A, *matout));
17966536e3caSStefano Zampini   if (reuse == MAT_INPLACE_MATRIX) {
17976536e3caSStefano Zampini     if (m == n) { /* in place transpose */
17989566063dSJacob Faibussowitsch       PetscCall(MatDenseGetArray(A, &v));
1799d3e5ee88SLois Curfman McInnes       for (j = 0; j < m; j++) {
1800289bc588SBarry Smith         for (k = 0; k < j; k++) {
18011b807ce4Svictorle           tmp          = v[j + k * M];
18021b807ce4Svictorle           v[j + k * M] = v[k + j * M];
18031b807ce4Svictorle           v[k + j * M] = tmp;
1804289bc588SBarry Smith         }
1805289bc588SBarry Smith       }
18069566063dSJacob Faibussowitsch       PetscCall(MatDenseRestoreArray(A, &v));
18076536e3caSStefano Zampini     } else { /* reuse memory, temporary allocates new memory */
18086536e3caSStefano Zampini       PetscScalar *v2;
18096536e3caSStefano Zampini       PetscLayout  tmplayout;
18106536e3caSStefano Zampini 
18119566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1((size_t)m * n, &v2));
18129566063dSJacob Faibussowitsch       PetscCall(MatDenseGetArray(A, &v));
18136536e3caSStefano Zampini       for (j = 0; j < n; j++) {
18146536e3caSStefano Zampini         for (k = 0; k < m; k++) v2[j + (size_t)k * n] = v[k + (size_t)j * M];
18156536e3caSStefano Zampini       }
18169566063dSJacob Faibussowitsch       PetscCall(PetscArraycpy(v, v2, (size_t)m * n));
18179566063dSJacob Faibussowitsch       PetscCall(PetscFree(v2));
18189566063dSJacob Faibussowitsch       PetscCall(MatDenseRestoreArray(A, &v));
18196536e3caSStefano Zampini       /* cleanup size dependent quantities */
18209566063dSJacob Faibussowitsch       PetscCall(VecDestroy(&mat->cvec));
18219566063dSJacob Faibussowitsch       PetscCall(MatDestroy(&mat->cmat));
18229566063dSJacob Faibussowitsch       PetscCall(PetscFree(mat->pivots));
18239566063dSJacob Faibussowitsch       PetscCall(PetscFree(mat->fwork));
18246536e3caSStefano Zampini       /* swap row/col layouts */
18256497c311SBarry Smith       PetscCall(PetscBLASIntCast(n, &mat->lda));
18266536e3caSStefano Zampini       tmplayout = A->rmap;
18276536e3caSStefano Zampini       A->rmap   = A->cmap;
18286536e3caSStefano Zampini       A->cmap   = tmplayout;
18296536e3caSStefano Zampini     }
18303a40ed3dSBarry Smith   } else { /* out-of-place transpose */
1831d3e5ee88SLois Curfman McInnes     Mat           tmat;
1832ec8511deSBarry Smith     Mat_SeqDense *tmatd;
183387828ca2SBarry Smith     PetscScalar  *v2;
1834af36a384SStefano Zampini     PetscInt      M2;
1835ea709b57SSatish Balay 
18366536e3caSStefano Zampini     if (reuse == MAT_INITIAL_MATRIX) {
18379566063dSJacob Faibussowitsch       PetscCall(MatCreate(PetscObjectComm((PetscObject)A), &tmat));
18389566063dSJacob Faibussowitsch       PetscCall(MatSetSizes(tmat, A->cmap->n, A->rmap->n, A->cmap->n, A->rmap->n));
18399566063dSJacob Faibussowitsch       PetscCall(MatSetType(tmat, ((PetscObject)A)->type_name));
18409566063dSJacob Faibussowitsch       PetscCall(MatSeqDenseSetPreallocation(tmat, NULL));
1841ca15aa20SStefano Zampini     } else tmat = *matout;
1842ca15aa20SStefano Zampini 
18439566063dSJacob Faibussowitsch     PetscCall(MatDenseGetArrayRead(A, (const PetscScalar **)&v));
18449566063dSJacob Faibussowitsch     PetscCall(MatDenseGetArray(tmat, &v2));
1845ec8511deSBarry Smith     tmatd = (Mat_SeqDense *)tmat->data;
1846ca15aa20SStefano Zampini     M2    = tmatd->lda;
1847d3e5ee88SLois Curfman McInnes     for (j = 0; j < n; j++) {
1848af36a384SStefano Zampini       for (k = 0; k < m; k++) v2[j + k * M2] = v[k + j * M];
1849d3e5ee88SLois Curfman McInnes     }
18509566063dSJacob Faibussowitsch     PetscCall(MatDenseRestoreArray(tmat, &v2));
18519566063dSJacob Faibussowitsch     PetscCall(MatDenseRestoreArrayRead(A, (const PetscScalar **)&v));
18529566063dSJacob Faibussowitsch     PetscCall(MatAssemblyBegin(tmat, MAT_FINAL_ASSEMBLY));
18539566063dSJacob Faibussowitsch     PetscCall(MatAssemblyEnd(tmat, MAT_FINAL_ASSEMBLY));
18546536e3caSStefano Zampini     *matout = tmat;
185548b35521SBarry Smith   }
18563ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1857289bc588SBarry Smith }
1858289bc588SBarry Smith 
1859d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatEqual_SeqDense(Mat A1, Mat A2, PetscBool *flg)
1860d71ae5a4SJacob Faibussowitsch {
1861c0bbcb79SLois Curfman McInnes   Mat_SeqDense      *mat1 = (Mat_SeqDense *)A1->data;
1862c0bbcb79SLois Curfman McInnes   Mat_SeqDense      *mat2 = (Mat_SeqDense *)A2->data;
1863ca15aa20SStefano Zampini   PetscInt           i;
1864ca15aa20SStefano Zampini   const PetscScalar *v1, *v2;
18659ea5d5aeSSatish Balay 
18663a40ed3dSBarry Smith   PetscFunctionBegin;
18679371c9d4SSatish Balay   if (A1->rmap->n != A2->rmap->n) {
18689371c9d4SSatish Balay     *flg = PETSC_FALSE;
18693ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
18709371c9d4SSatish Balay   }
18719371c9d4SSatish Balay   if (A1->cmap->n != A2->cmap->n) {
18729371c9d4SSatish Balay     *flg = PETSC_FALSE;
18733ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
18749371c9d4SSatish Balay   }
18759566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArrayRead(A1, &v1));
18769566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArrayRead(A2, &v2));
1877ca15aa20SStefano Zampini   for (i = 0; i < A1->cmap->n; i++) {
18789566063dSJacob Faibussowitsch     PetscCall(PetscArraycmp(v1, v2, A1->rmap->n, flg));
18793ba16761SJacob Faibussowitsch     if (*flg == PETSC_FALSE) PetscFunctionReturn(PETSC_SUCCESS);
1880ca15aa20SStefano Zampini     v1 += mat1->lda;
1881ca15aa20SStefano Zampini     v2 += mat2->lda;
18821b807ce4Svictorle   }
18839566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArrayRead(A1, &v1));
18849566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArrayRead(A2, &v2));
188577c4ece6SBarry Smith   *flg = PETSC_TRUE;
18863ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1887289bc588SBarry Smith }
1888289bc588SBarry Smith 
188914277c92SJacob Faibussowitsch PetscErrorCode MatGetDiagonal_SeqDense(Mat A, Vec v)
1890d71ae5a4SJacob Faibussowitsch {
1891c0bbcb79SLois Curfman McInnes   Mat_SeqDense      *mat = (Mat_SeqDense *)A->data;
189213f74950SBarry Smith   PetscInt           i, n, len;
1893ca15aa20SStefano Zampini   PetscScalar       *x;
1894ca15aa20SStefano Zampini   const PetscScalar *vv;
189544cd7ae7SLois Curfman McInnes 
18963a40ed3dSBarry Smith   PetscFunctionBegin;
18979566063dSJacob Faibussowitsch   PetscCall(VecGetSize(v, &n));
18989566063dSJacob Faibussowitsch   PetscCall(VecGetArray(v, &x));
1899d0f46423SBarry Smith   len = PetscMin(A->rmap->n, A->cmap->n);
19009566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArrayRead(A, &vv));
190108401ef6SPierre Jolivet   PetscCheck(n == A->rmap->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Nonconforming mat and vec");
1902ad540459SPierre Jolivet   for (i = 0; i < len; i++) x[i] = vv[i * mat->lda + i];
19039566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArrayRead(A, &vv));
19049566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(v, &x));
19053ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1906289bc588SBarry Smith }
1907289bc588SBarry Smith 
1908d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatDiagonalScale_SeqDense(Mat A, Vec ll, Vec rr)
1909d71ae5a4SJacob Faibussowitsch {
1910c0bbcb79SLois Curfman McInnes   Mat_SeqDense      *mat = (Mat_SeqDense *)A->data;
1911f1ceaac6SMatthew G. Knepley   const PetscScalar *l, *r;
1912ca15aa20SStefano Zampini   PetscScalar        x, *v, *vv;
1913d0f46423SBarry Smith   PetscInt           i, j, m = A->rmap->n, n = A->cmap->n;
191455659b69SBarry Smith 
19153a40ed3dSBarry Smith   PetscFunctionBegin;
19169566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArray(A, &vv));
191728988994SBarry Smith   if (ll) {
19189566063dSJacob Faibussowitsch     PetscCall(VecGetSize(ll, &m));
19199566063dSJacob Faibussowitsch     PetscCall(VecGetArrayRead(ll, &l));
192008401ef6SPierre Jolivet     PetscCheck(m == A->rmap->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Left scaling vec wrong size");
1921da3a660dSBarry Smith     for (i = 0; i < m; i++) {
1922da3a660dSBarry Smith       x = l[i];
1923ca15aa20SStefano Zampini       v = vv + i;
19249371c9d4SSatish Balay       for (j = 0; j < n; j++) {
19259371c9d4SSatish Balay         (*v) *= x;
19269371c9d4SSatish Balay         v += mat->lda;
19279371c9d4SSatish Balay       }
1928da3a660dSBarry Smith     }
19299566063dSJacob Faibussowitsch     PetscCall(VecRestoreArrayRead(ll, &l));
19309566063dSJacob Faibussowitsch     PetscCall(PetscLogFlops(1.0 * n * m));
1931da3a660dSBarry Smith   }
193228988994SBarry Smith   if (rr) {
19339566063dSJacob Faibussowitsch     PetscCall(VecGetSize(rr, &n));
19349566063dSJacob Faibussowitsch     PetscCall(VecGetArrayRead(rr, &r));
193508401ef6SPierre Jolivet     PetscCheck(n == A->cmap->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Right scaling vec wrong size");
1936da3a660dSBarry Smith     for (i = 0; i < n; i++) {
1937da3a660dSBarry Smith       x = r[i];
1938ca15aa20SStefano Zampini       v = vv + i * mat->lda;
19392205254eSKarl Rupp       for (j = 0; j < m; j++) (*v++) *= x;
1940da3a660dSBarry Smith     }
19419566063dSJacob Faibussowitsch     PetscCall(VecRestoreArrayRead(rr, &r));
19429566063dSJacob Faibussowitsch     PetscCall(PetscLogFlops(1.0 * n * m));
1943da3a660dSBarry Smith   }
19449566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArray(A, &vv));
19453ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1946289bc588SBarry Smith }
1947289bc588SBarry Smith 
1948d71ae5a4SJacob Faibussowitsch PetscErrorCode MatNorm_SeqDense(Mat A, NormType type, PetscReal *nrm)
1949d71ae5a4SJacob Faibussowitsch {
1950c0bbcb79SLois Curfman McInnes   Mat_SeqDense *mat = (Mat_SeqDense *)A->data;
1951ca15aa20SStefano Zampini   PetscScalar  *v, *vv;
1952329f5518SBarry Smith   PetscReal     sum = 0.0;
195375f6d85dSStefano Zampini   PetscInt      lda, m = A->rmap->n, i, j;
195455659b69SBarry Smith 
19553a40ed3dSBarry Smith   PetscFunctionBegin;
19569566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArrayRead(A, (const PetscScalar **)&vv));
19579566063dSJacob Faibussowitsch   PetscCall(MatDenseGetLDA(A, &lda));
1958ca15aa20SStefano Zampini   v = vv;
1959289bc588SBarry Smith   if (type == NORM_FROBENIUS) {
1960a5ce6ee0Svictorle     if (lda > m) {
1961d0f46423SBarry Smith       for (j = 0; j < A->cmap->n; j++) {
1962ca15aa20SStefano Zampini         v = vv + j * lda;
1963a5ce6ee0Svictorle         for (i = 0; i < m; i++) {
19649371c9d4SSatish Balay           sum += PetscRealPart(PetscConj(*v) * (*v));
19659371c9d4SSatish Balay           v++;
1966a5ce6ee0Svictorle         }
1967a5ce6ee0Svictorle       }
1968a5ce6ee0Svictorle     } else {
1969570b7f6dSBarry Smith #if defined(PETSC_USE_REAL___FP16)
1970570b7f6dSBarry Smith       PetscBLASInt one = 1, cnt = A->cmap->n * A->rmap->n;
1971792fecdfSBarry Smith       PetscCallBLAS("BLASnrm2", *nrm = BLASnrm2_(&cnt, v, &one));
1972570b7f6dSBarry Smith     }
1973570b7f6dSBarry Smith #else
1974d0f46423SBarry Smith       for (i = 0; i < A->cmap->n * A->rmap->n; i++) {
19759371c9d4SSatish Balay         sum += PetscRealPart(PetscConj(*v) * (*v));
19769371c9d4SSatish Balay         v++;
1977289bc588SBarry Smith       }
1978a5ce6ee0Svictorle     }
19798f1a2a5eSBarry Smith     *nrm = PetscSqrtReal(sum);
1980570b7f6dSBarry Smith #endif
19819566063dSJacob Faibussowitsch     PetscCall(PetscLogFlops(2.0 * A->cmap->n * A->rmap->n));
19823a40ed3dSBarry Smith   } else if (type == NORM_1) {
1983064f8208SBarry Smith     *nrm = 0.0;
1984d0f46423SBarry Smith     for (j = 0; j < A->cmap->n; j++) {
1985ca15aa20SStefano Zampini       v   = vv + j * mat->lda;
1986289bc588SBarry Smith       sum = 0.0;
1987d0f46423SBarry Smith       for (i = 0; i < A->rmap->n; i++) {
19889371c9d4SSatish Balay         sum += PetscAbsScalar(*v);
19899371c9d4SSatish Balay         v++;
1990289bc588SBarry Smith       }
1991064f8208SBarry Smith       if (sum > *nrm) *nrm = sum;
1992289bc588SBarry Smith     }
19939566063dSJacob Faibussowitsch     PetscCall(PetscLogFlops(1.0 * A->cmap->n * A->rmap->n));
19943a40ed3dSBarry Smith   } else if (type == NORM_INFINITY) {
1995064f8208SBarry Smith     *nrm = 0.0;
1996d0f46423SBarry Smith     for (j = 0; j < A->rmap->n; j++) {
1997ca15aa20SStefano Zampini       v   = vv + j;
1998289bc588SBarry Smith       sum = 0.0;
1999d0f46423SBarry Smith       for (i = 0; i < A->cmap->n; i++) {
20009371c9d4SSatish Balay         sum += PetscAbsScalar(*v);
20019371c9d4SSatish Balay         v += mat->lda;
2002289bc588SBarry Smith       }
2003064f8208SBarry Smith       if (sum > *nrm) *nrm = sum;
2004289bc588SBarry Smith     }
20059566063dSJacob Faibussowitsch     PetscCall(PetscLogFlops(1.0 * A->cmap->n * A->rmap->n));
2006e7e72b3dSBarry Smith   } else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "No two norm");
20079566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArrayRead(A, (const PetscScalar **)&vv));
20083ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2009289bc588SBarry Smith }
2010289bc588SBarry Smith 
2011d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatSetOption_SeqDense(Mat A, MatOption op, PetscBool flg)
2012d71ae5a4SJacob Faibussowitsch {
2013c0bbcb79SLois Curfman McInnes   Mat_SeqDense *aij = (Mat_SeqDense *)A->data;
201467e560aaSBarry Smith 
20153a40ed3dSBarry Smith   PetscFunctionBegin;
2016b5a2b587SKris Buschelman   switch (op) {
2017d71ae5a4SJacob Faibussowitsch   case MAT_ROW_ORIENTED:
2018d71ae5a4SJacob Faibussowitsch     aij->roworiented = flg;
2019d71ae5a4SJacob Faibussowitsch     break;
2020d71ae5a4SJacob Faibussowitsch   default:
2021888c827cSStefano Zampini     break;
20223a40ed3dSBarry Smith   }
20233ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2024289bc588SBarry Smith }
2025289bc588SBarry Smith 
2026d71ae5a4SJacob Faibussowitsch PetscErrorCode MatZeroEntries_SeqDense(Mat A)
2027d71ae5a4SJacob Faibussowitsch {
2028ec8511deSBarry Smith   Mat_SeqDense *l   = (Mat_SeqDense *)A->data;
20293d8925e7SStefano Zampini   PetscInt      lda = l->lda, m = A->rmap->n, n = A->cmap->n, j;
2030ca15aa20SStefano Zampini   PetscScalar  *v;
20313a40ed3dSBarry Smith 
20323a40ed3dSBarry Smith   PetscFunctionBegin;
20339566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArrayWrite(A, &v));
2034a5ce6ee0Svictorle   if (lda > m) {
203548a46eb9SPierre Jolivet     for (j = 0; j < n; j++) PetscCall(PetscArrayzero(v + j * lda, m));
2036a5ce6ee0Svictorle   } else {
20379566063dSJacob Faibussowitsch     PetscCall(PetscArrayzero(v, PetscInt64Mult(m, n)));
2038a5ce6ee0Svictorle   }
20399566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArrayWrite(A, &v));
20403ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
20416f0a148fSBarry Smith }
20426f0a148fSBarry Smith 
2043d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatZeroRows_SeqDense(Mat A, PetscInt N, const PetscInt rows[], PetscScalar diag, Vec x, Vec b)
2044d71ae5a4SJacob Faibussowitsch {
2045ec8511deSBarry Smith   Mat_SeqDense      *l = (Mat_SeqDense *)A->data;
2046b9679d65SBarry Smith   PetscInt           m = l->lda, n = A->cmap->n, i, j;
2047ca15aa20SStefano Zampini   PetscScalar       *slot, *bb, *v;
204897b48c8fSBarry Smith   const PetscScalar *xx;
204955659b69SBarry Smith 
20503a40ed3dSBarry Smith   PetscFunctionBegin;
205176bd3646SJed Brown   if (PetscDefined(USE_DEBUG)) {
2052b9679d65SBarry Smith     for (i = 0; i < N; i++) {
205308401ef6SPierre Jolivet       PetscCheck(rows[i] >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Negative row requested to be zeroed");
205408401ef6SPierre 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);
2055b9679d65SBarry Smith     }
205676bd3646SJed Brown   }
20573ba16761SJacob Faibussowitsch   if (!N) PetscFunctionReturn(PETSC_SUCCESS);
2058b9679d65SBarry Smith 
2059dd8e379bSPierre Jolivet   /* fix right-hand side if needed */
206097b48c8fSBarry Smith   if (x && b) {
20619566063dSJacob Faibussowitsch     PetscCall(VecGetArrayRead(x, &xx));
20629566063dSJacob Faibussowitsch     PetscCall(VecGetArray(b, &bb));
20632205254eSKarl Rupp     for (i = 0; i < N; i++) bb[rows[i]] = diag * xx[rows[i]];
20649566063dSJacob Faibussowitsch     PetscCall(VecRestoreArrayRead(x, &xx));
20659566063dSJacob Faibussowitsch     PetscCall(VecRestoreArray(b, &bb));
206697b48c8fSBarry Smith   }
206797b48c8fSBarry Smith 
20689566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArray(A, &v));
20696f0a148fSBarry Smith   for (i = 0; i < N; i++) {
2070ca15aa20SStefano Zampini     slot = v + rows[i];
20719371c9d4SSatish Balay     for (j = 0; j < n; j++) {
20729371c9d4SSatish Balay       *slot = 0.0;
20739371c9d4SSatish Balay       slot += m;
20749371c9d4SSatish Balay     }
20756f0a148fSBarry Smith   }
2076f4df32b1SMatthew Knepley   if (diag != 0.0) {
207708401ef6SPierre Jolivet     PetscCheck(A->rmap->n == A->cmap->n, PETSC_COMM_SELF, PETSC_ERR_SUP, "Only coded for square matrices");
20786f0a148fSBarry Smith     for (i = 0; i < N; i++) {
2079ca15aa20SStefano Zampini       slot  = v + (m + 1) * rows[i];
2080f4df32b1SMatthew Knepley       *slot = diag;
20816f0a148fSBarry Smith     }
20826f0a148fSBarry Smith   }
20839566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArray(A, &v));
20843ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
20856f0a148fSBarry Smith }
2086557bce09SLois Curfman McInnes 
2087d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatDenseGetLDA_SeqDense(Mat A, PetscInt *lda)
2088d71ae5a4SJacob Faibussowitsch {
208949a6ff4bSBarry Smith   Mat_SeqDense *mat = (Mat_SeqDense *)A->data;
209049a6ff4bSBarry Smith 
209149a6ff4bSBarry Smith   PetscFunctionBegin;
209249a6ff4bSBarry Smith   *lda = mat->lda;
20933ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
209449a6ff4bSBarry Smith }
209549a6ff4bSBarry Smith 
2096d71ae5a4SJacob Faibussowitsch PetscErrorCode MatDenseGetArray_SeqDense(Mat A, PetscScalar **array)
2097d71ae5a4SJacob Faibussowitsch {
2098c0bbcb79SLois Curfman McInnes   Mat_SeqDense *mat = (Mat_SeqDense *)A->data;
20993a40ed3dSBarry Smith 
21003a40ed3dSBarry Smith   PetscFunctionBegin;
210128b400f6SJacob Faibussowitsch   PetscCheck(!mat->matinuse, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Need to call MatDenseRestoreSubMatrix() first");
210264e87e97SBarry Smith   *array = mat->v;
21033ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
210464e87e97SBarry Smith }
21050754003eSLois Curfman McInnes 
2106d71ae5a4SJacob Faibussowitsch PetscErrorCode MatDenseRestoreArray_SeqDense(Mat A, PetscScalar **array)
2107d71ae5a4SJacob Faibussowitsch {
21083a40ed3dSBarry Smith   PetscFunctionBegin;
210975f6d85dSStefano Zampini   if (array) *array = NULL;
21103ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2111ff14e315SSatish Balay }
21120754003eSLois Curfman McInnes 
21130f74d2c1SSatish Balay /*@
211411a5261eSBarry Smith   MatDenseGetLDA - gets the leading dimension of the array returned from `MatDenseGetArray()`
211549a6ff4bSBarry Smith 
21162ef1f0ffSBarry Smith   Not Collective
211749a6ff4bSBarry Smith 
211849a6ff4bSBarry Smith   Input Parameter:
2119fe59aa6dSJacob Faibussowitsch . A - a `MATDENSE` or `MATDENSECUDA` matrix
212049a6ff4bSBarry Smith 
212149a6ff4bSBarry Smith   Output Parameter:
212249a6ff4bSBarry Smith . lda - the leading dimension
212349a6ff4bSBarry Smith 
212449a6ff4bSBarry Smith   Level: intermediate
212549a6ff4bSBarry Smith 
21261cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATDENSE`, `MATDENSECUDA`, `MatDenseGetArray()`, `MatDenseRestoreArray()`, `MatDenseGetArrayRead()`, `MatDenseRestoreArrayRead()`, `MatDenseSetLDA()`
212749a6ff4bSBarry Smith @*/
2128d71ae5a4SJacob Faibussowitsch PetscErrorCode MatDenseGetLDA(Mat A, PetscInt *lda)
2129d71ae5a4SJacob Faibussowitsch {
213049a6ff4bSBarry Smith   PetscFunctionBegin;
2131d5ea218eSStefano Zampini   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
21324f572ea9SToby Isaac   PetscAssertPointer(lda, 2);
213375f6d85dSStefano Zampini   MatCheckPreallocated(A, 1);
2134cac4c232SBarry Smith   PetscUseMethod(A, "MatDenseGetLDA_C", (Mat, PetscInt *), (A, lda));
21353ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
213649a6ff4bSBarry Smith }
213749a6ff4bSBarry Smith 
21380f74d2c1SSatish Balay /*@
213911a5261eSBarry Smith   MatDenseSetLDA - Sets the leading dimension of the array used by the `MATDENSE` matrix
2140ad16ce7aSStefano Zampini 
21412323109cSBarry Smith   Collective if the matrix layouts have not yet been setup
2142ad16ce7aSStefano Zampini 
2143d8d19677SJose E. Roman   Input Parameters:
2144fe59aa6dSJacob Faibussowitsch + A   - a `MATDENSE` or `MATDENSECUDA` matrix
2145ad16ce7aSStefano Zampini - lda - the leading dimension
2146ad16ce7aSStefano Zampini 
2147ad16ce7aSStefano Zampini   Level: intermediate
2148ad16ce7aSStefano Zampini 
21491cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATDENSE`, `MATDENSECUDA`, `MatDenseGetArray()`, `MatDenseRestoreArray()`, `MatDenseGetArrayRead()`, `MatDenseRestoreArrayRead()`, `MatDenseGetLDA()`
2150ad16ce7aSStefano Zampini @*/
2151d71ae5a4SJacob Faibussowitsch PetscErrorCode MatDenseSetLDA(Mat A, PetscInt lda)
2152d71ae5a4SJacob Faibussowitsch {
2153ad16ce7aSStefano Zampini   PetscFunctionBegin;
2154ad16ce7aSStefano Zampini   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
2155cac4c232SBarry Smith   PetscTryMethod(A, "MatDenseSetLDA_C", (Mat, PetscInt), (A, lda));
21563ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2157ad16ce7aSStefano Zampini }
2158ad16ce7aSStefano Zampini 
2159ad16ce7aSStefano Zampini /*@C
216011a5261eSBarry Smith   MatDenseGetArray - gives read-write access to the array where the data for a `MATDENSE` matrix is stored
216173a71a0fSBarry Smith 
2162c3339decSBarry Smith   Logically Collective
216373a71a0fSBarry Smith 
216473a71a0fSBarry Smith   Input Parameter:
2165fe59aa6dSJacob Faibussowitsch . A - a dense matrix
216673a71a0fSBarry Smith 
216773a71a0fSBarry Smith   Output Parameter:
216873a71a0fSBarry Smith . array - pointer to the data
216973a71a0fSBarry Smith 
217073a71a0fSBarry Smith   Level: intermediate
217173a71a0fSBarry Smith 
21721cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATDENSE`, `MatDenseRestoreArray()`, `MatDenseGetArrayRead()`, `MatDenseRestoreArrayRead()`, `MatDenseGetArrayWrite()`, `MatDenseRestoreArrayWrite()`
217373a71a0fSBarry Smith @*/
2174ce78bad3SBarry Smith PetscErrorCode MatDenseGetArray(Mat A, PetscScalar *array[]) PeNS
2175d71ae5a4SJacob Faibussowitsch {
217673a71a0fSBarry Smith   PetscFunctionBegin;
2177d5ea218eSStefano Zampini   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
21784f572ea9SToby Isaac   PetscAssertPointer(array, 2);
2179cac4c232SBarry Smith   PetscUseMethod(A, "MatDenseGetArray_C", (Mat, PetscScalar **), (A, array));
21803ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
218173a71a0fSBarry Smith }
218273a71a0fSBarry Smith 
2183dec5eb66SMatthew G Knepley /*@C
218411a5261eSBarry Smith   MatDenseRestoreArray - returns access to the array where the data for a `MATDENSE` matrix is stored obtained by `MatDenseGetArray()`
218573a71a0fSBarry Smith 
2186c3339decSBarry Smith   Logically Collective
21878572280aSBarry Smith 
21888572280aSBarry Smith   Input Parameters:
2189fe59aa6dSJacob Faibussowitsch + A     - a dense matrix
21902ef1f0ffSBarry Smith - array - pointer to the data (may be `NULL`)
21918572280aSBarry Smith 
21928572280aSBarry Smith   Level: intermediate
21938572280aSBarry Smith 
21941cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATDENSE`, `MatDenseGetArray()`, `MatDenseGetArrayRead()`, `MatDenseRestoreArrayRead()`, `MatDenseGetArrayWrite()`, `MatDenseRestoreArrayWrite()`
21958572280aSBarry Smith @*/
2196ce78bad3SBarry Smith PetscErrorCode MatDenseRestoreArray(Mat A, PetscScalar *array[]) PeNS
2197d71ae5a4SJacob Faibussowitsch {
21988572280aSBarry Smith   PetscFunctionBegin;
2199d5ea218eSStefano Zampini   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
22004f572ea9SToby Isaac   if (array) PetscAssertPointer(array, 2);
2201cac4c232SBarry Smith   PetscUseMethod(A, "MatDenseRestoreArray_C", (Mat, PetscScalar **), (A, array));
22029566063dSJacob Faibussowitsch   PetscCall(PetscObjectStateIncrease((PetscObject)A));
220347d993e7Ssuyashtn #if defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
2204637a0070SStefano Zampini   A->offloadmask = PETSC_OFFLOAD_CPU;
2205637a0070SStefano Zampini #endif
22063ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
22078572280aSBarry Smith }
22088572280aSBarry Smith 
22098572280aSBarry Smith /*@C
221011a5261eSBarry Smith   MatDenseGetArrayRead - gives read-only access to the array where the data for a `MATDENSE` matrix is stored
22118572280aSBarry Smith 
2212fb850c59SBarry Smith   Not Collective
22138572280aSBarry Smith 
22148572280aSBarry Smith   Input Parameter:
2215fe59aa6dSJacob Faibussowitsch . A - a dense matrix
22168572280aSBarry Smith 
22178572280aSBarry Smith   Output Parameter:
22188572280aSBarry Smith . array - pointer to the data
22198572280aSBarry Smith 
22208572280aSBarry Smith   Level: intermediate
22218572280aSBarry Smith 
22221cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATDENSE`, `MatDenseRestoreArrayRead()`, `MatDenseGetArray()`, `MatDenseRestoreArray()`, `MatDenseGetArrayWrite()`, `MatDenseRestoreArrayWrite()`
22238572280aSBarry Smith @*/
2224ce78bad3SBarry Smith PetscErrorCode MatDenseGetArrayRead(Mat A, const PetscScalar *array[]) PeNS
2225d71ae5a4SJacob Faibussowitsch {
22268572280aSBarry Smith   PetscFunctionBegin;
2227d5ea218eSStefano Zampini   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
22284f572ea9SToby Isaac   PetscAssertPointer(array, 2);
22295c0db29aSPierre Jolivet   PetscUseMethod(A, "MatDenseGetArrayRead_C", (Mat, PetscScalar **), (A, (PetscScalar **)array));
22303ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
22318572280aSBarry Smith }
22328572280aSBarry Smith 
22338572280aSBarry Smith /*@C
223411a5261eSBarry Smith   MatDenseRestoreArrayRead - returns access to the array where the data for a `MATDENSE` matrix is stored obtained by `MatDenseGetArrayRead()`
22358572280aSBarry Smith 
2236fb850c59SBarry Smith   Not Collective
223773a71a0fSBarry Smith 
223873a71a0fSBarry Smith   Input Parameters:
2239fe59aa6dSJacob Faibussowitsch + A     - a dense matrix
22402ef1f0ffSBarry Smith - array - pointer to the data (may be `NULL`)
224173a71a0fSBarry Smith 
224273a71a0fSBarry Smith   Level: intermediate
224373a71a0fSBarry Smith 
22441cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATDENSE`, `MatDenseGetArrayRead()`, `MatDenseGetArray()`, `MatDenseRestoreArray()`, `MatDenseGetArrayWrite()`, `MatDenseRestoreArrayWrite()`
224573a71a0fSBarry Smith @*/
2246ce78bad3SBarry Smith PetscErrorCode MatDenseRestoreArrayRead(Mat A, const PetscScalar *array[]) PeNS
2247d71ae5a4SJacob Faibussowitsch {
224873a71a0fSBarry Smith   PetscFunctionBegin;
2249d5ea218eSStefano Zampini   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
22504f572ea9SToby Isaac   if (array) PetscAssertPointer(array, 2);
22515c0db29aSPierre Jolivet   PetscUseMethod(A, "MatDenseRestoreArrayRead_C", (Mat, PetscScalar **), (A, (PetscScalar **)array));
22523ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
225373a71a0fSBarry Smith }
225473a71a0fSBarry Smith 
22556947451fSStefano Zampini /*@C
225611a5261eSBarry Smith   MatDenseGetArrayWrite - gives write-only access to the array where the data for a `MATDENSE` matrix is stored
22576947451fSStefano Zampini 
2258fb850c59SBarry Smith   Not Collective
22596947451fSStefano Zampini 
22606947451fSStefano Zampini   Input Parameter:
2261fe59aa6dSJacob Faibussowitsch . A - a dense matrix
22626947451fSStefano Zampini 
22636947451fSStefano Zampini   Output Parameter:
22646947451fSStefano Zampini . array - pointer to the data
22656947451fSStefano Zampini 
22666947451fSStefano Zampini   Level: intermediate
22676947451fSStefano Zampini 
22681cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATDENSE`, `MatDenseRestoreArrayWrite()`, `MatDenseGetArray()`, `MatDenseRestoreArray()`, `MatDenseGetArrayRead()`, `MatDenseRestoreArrayRead()`
22696947451fSStefano Zampini @*/
2270ce78bad3SBarry Smith PetscErrorCode MatDenseGetArrayWrite(Mat A, PetscScalar *array[]) PeNS
2271d71ae5a4SJacob Faibussowitsch {
22726947451fSStefano Zampini   PetscFunctionBegin;
2273d5ea218eSStefano Zampini   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
22744f572ea9SToby Isaac   PetscAssertPointer(array, 2);
2275cac4c232SBarry Smith   PetscUseMethod(A, "MatDenseGetArrayWrite_C", (Mat, PetscScalar **), (A, array));
22763ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
22776947451fSStefano Zampini }
22786947451fSStefano Zampini 
22796947451fSStefano Zampini /*@C
228011a5261eSBarry Smith   MatDenseRestoreArrayWrite - returns access to the array where the data for a `MATDENSE` matrix is stored obtained by `MatDenseGetArrayWrite()`
22816947451fSStefano Zampini 
2282fb850c59SBarry Smith   Not Collective
22836947451fSStefano Zampini 
22846947451fSStefano Zampini   Input Parameters:
2285fe59aa6dSJacob Faibussowitsch + A     - a dense matrix
22862ef1f0ffSBarry Smith - array - pointer to the data (may be `NULL`)
22876947451fSStefano Zampini 
22886947451fSStefano Zampini   Level: intermediate
22896947451fSStefano Zampini 
22901cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATDENSE`, `MatDenseGetArrayWrite()`, `MatDenseGetArray()`, `MatDenseRestoreArray()`, `MatDenseGetArrayRead()`, `MatDenseRestoreArrayRead()`
22916947451fSStefano Zampini @*/
2292ce78bad3SBarry Smith PetscErrorCode MatDenseRestoreArrayWrite(Mat A, PetscScalar *array[]) PeNS
2293d71ae5a4SJacob Faibussowitsch {
22946947451fSStefano Zampini   PetscFunctionBegin;
2295d5ea218eSStefano Zampini   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
22964f572ea9SToby Isaac   if (array) PetscAssertPointer(array, 2);
2297cac4c232SBarry Smith   PetscUseMethod(A, "MatDenseRestoreArrayWrite_C", (Mat, PetscScalar **), (A, array));
22989566063dSJacob Faibussowitsch   PetscCall(PetscObjectStateIncrease((PetscObject)A));
229947d993e7Ssuyashtn #if defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
23006947451fSStefano Zampini   A->offloadmask = PETSC_OFFLOAD_CPU;
23016947451fSStefano Zampini #endif
23023ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
23036947451fSStefano Zampini }
23046947451fSStefano Zampini 
2305cd3f9d89SJunchao Zhang /*@C
2306cd3f9d89SJunchao Zhang   MatDenseGetArrayAndMemType - gives read-write access to the array where the data for a `MATDENSE` matrix is stored
2307cd3f9d89SJunchao Zhang 
2308cd3f9d89SJunchao Zhang   Logically Collective
2309cd3f9d89SJunchao Zhang 
2310cd3f9d89SJunchao Zhang   Input Parameter:
2311fe59aa6dSJacob Faibussowitsch . A - a dense matrix
2312cd3f9d89SJunchao Zhang 
2313cd3f9d89SJunchao Zhang   Output Parameters:
2314cd3f9d89SJunchao Zhang + array - pointer to the data
2315cd3f9d89SJunchao Zhang - mtype - memory type of the returned pointer
2316cd3f9d89SJunchao Zhang 
2317cd3f9d89SJunchao Zhang   Level: intermediate
2318cd3f9d89SJunchao Zhang 
2319fb850c59SBarry Smith   Note:
23202ef1f0ffSBarry Smith   If the matrix is of a device type such as `MATDENSECUDA`, `MATDENSEHIP`, etc.,
23212ef1f0ffSBarry Smith   an array on device is always returned and is guaranteed to contain the matrix's latest data.
23222ef1f0ffSBarry Smith 
23231cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATDENSE`, `MatDenseRestoreArrayAndMemType()`, `MatDenseGetArrayReadAndMemType()`, `MatDenseGetArrayWriteAndMemType()`, `MatDenseGetArrayRead()`,
2324cd3f9d89SJunchao Zhang    `MatDenseRestoreArrayRead()`, `MatDenseGetArrayWrite()`, `MatDenseRestoreArrayWrite()`, `MatSeqAIJGetCSRAndMemType()`
2325cd3f9d89SJunchao Zhang @*/
23265d83a8b1SBarry Smith PetscErrorCode MatDenseGetArrayAndMemType(Mat A, PetscScalar *array[], PetscMemType *mtype)
2327cd3f9d89SJunchao Zhang {
2328cd3f9d89SJunchao Zhang   PetscBool isMPI;
2329cd3f9d89SJunchao Zhang 
2330cd3f9d89SJunchao Zhang   PetscFunctionBegin;
2331cd3f9d89SJunchao Zhang   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
23324f572ea9SToby Isaac   PetscAssertPointer(array, 2);
2333e865de01SJunchao 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 */
2334cd3f9d89SJunchao Zhang   PetscCall(PetscObjectBaseTypeCompare((PetscObject)A, MATMPIDENSE, &isMPI));
2335cd3f9d89SJunchao Zhang   if (isMPI) {
2336cd3f9d89SJunchao Zhang     /* Dispatch here so that the code can be reused for all subclasses of MATDENSE */
2337cd3f9d89SJunchao Zhang     PetscCall(MatDenseGetArrayAndMemType(((Mat_MPIDense *)A->data)->A, array, mtype));
2338cd3f9d89SJunchao Zhang   } else {
2339cd3f9d89SJunchao Zhang     PetscErrorCode (*fptr)(Mat, PetscScalar **, PetscMemType *);
23403ba16761SJacob Faibussowitsch 
23413ba16761SJacob Faibussowitsch     PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatDenseGetArrayAndMemType_C", &fptr));
2342cd3f9d89SJunchao Zhang     if (fptr) {
2343cd3f9d89SJunchao Zhang       PetscCall((*fptr)(A, array, mtype));
2344cd3f9d89SJunchao Zhang     } else {
2345cd3f9d89SJunchao Zhang       PetscUseMethod(A, "MatDenseGetArray_C", (Mat, PetscScalar **), (A, array));
2346cd3f9d89SJunchao Zhang       if (mtype) *mtype = PETSC_MEMTYPE_HOST;
2347cd3f9d89SJunchao Zhang     }
2348cd3f9d89SJunchao Zhang   }
23493ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2350cd3f9d89SJunchao Zhang }
2351cd3f9d89SJunchao Zhang 
2352cd3f9d89SJunchao Zhang /*@C
2353cd3f9d89SJunchao Zhang   MatDenseRestoreArrayAndMemType - returns access to the array that is obtained by `MatDenseGetArrayAndMemType()`
2354cd3f9d89SJunchao Zhang 
2355cd3f9d89SJunchao Zhang   Logically Collective
2356cd3f9d89SJunchao Zhang 
2357cd3f9d89SJunchao Zhang   Input Parameters:
2358fe59aa6dSJacob Faibussowitsch + A     - a dense matrix
2359cd3f9d89SJunchao Zhang - array - pointer to the data
2360cd3f9d89SJunchao Zhang 
2361cd3f9d89SJunchao Zhang   Level: intermediate
2362cd3f9d89SJunchao Zhang 
23631cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATDENSE`, `MatDenseGetArrayAndMemType()`, `MatDenseGetArray()`, `MatDenseGetArrayRead()`, `MatDenseRestoreArrayRead()`, `MatDenseGetArrayWrite()`, `MatDenseRestoreArrayWrite()`
2364cd3f9d89SJunchao Zhang @*/
23655d83a8b1SBarry Smith PetscErrorCode MatDenseRestoreArrayAndMemType(Mat A, PetscScalar *array[])
2366cd3f9d89SJunchao Zhang {
2367cd3f9d89SJunchao Zhang   PetscBool isMPI;
2368cd3f9d89SJunchao Zhang 
2369cd3f9d89SJunchao Zhang   PetscFunctionBegin;
2370cd3f9d89SJunchao Zhang   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
2371*fd5c2d83SStefano Zampini   if (array) PetscAssertPointer(array, 2);
2372cd3f9d89SJunchao Zhang   PetscCall(PetscObjectBaseTypeCompare((PetscObject)A, MATMPIDENSE, &isMPI));
2373cd3f9d89SJunchao Zhang   if (isMPI) {
2374cd3f9d89SJunchao Zhang     PetscCall(MatDenseRestoreArrayAndMemType(((Mat_MPIDense *)A->data)->A, array));
2375cd3f9d89SJunchao Zhang   } else {
2376cd3f9d89SJunchao Zhang     PetscErrorCode (*fptr)(Mat, PetscScalar **);
23773ba16761SJacob Faibussowitsch 
23783ba16761SJacob Faibussowitsch     PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatDenseRestoreArrayAndMemType_C", &fptr));
2379cd3f9d89SJunchao Zhang     if (fptr) {
2380cd3f9d89SJunchao Zhang       PetscCall((*fptr)(A, array));
2381cd3f9d89SJunchao Zhang     } else {
2382cd3f9d89SJunchao Zhang       PetscUseMethod(A, "MatDenseRestoreArray_C", (Mat, PetscScalar **), (A, array));
2383cd3f9d89SJunchao Zhang     }
2384*fd5c2d83SStefano Zampini     if (array) *array = NULL;
2385cd3f9d89SJunchao Zhang   }
2386cd3f9d89SJunchao Zhang   PetscCall(PetscObjectStateIncrease((PetscObject)A));
23873ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2388cd3f9d89SJunchao Zhang }
2389cd3f9d89SJunchao Zhang 
2390cd3f9d89SJunchao Zhang /*@C
2391cd3f9d89SJunchao Zhang   MatDenseGetArrayReadAndMemType - gives read-only access to the array where the data for a `MATDENSE` matrix is stored
2392cd3f9d89SJunchao Zhang 
2393cd3f9d89SJunchao Zhang   Logically Collective
2394cd3f9d89SJunchao Zhang 
2395cd3f9d89SJunchao Zhang   Input Parameter:
2396fe59aa6dSJacob Faibussowitsch . A - a dense matrix
2397cd3f9d89SJunchao Zhang 
2398cd3f9d89SJunchao Zhang   Output Parameters:
2399cd3f9d89SJunchao Zhang + array - pointer to the data
2400cd3f9d89SJunchao Zhang - mtype - memory type of the returned pointer
2401cd3f9d89SJunchao Zhang 
2402cd3f9d89SJunchao Zhang   Level: intermediate
2403cd3f9d89SJunchao Zhang 
2404fb850c59SBarry Smith   Note:
24052ef1f0ffSBarry Smith   If the matrix is of a device type such as `MATDENSECUDA`, `MATDENSEHIP`, etc.,
24062ef1f0ffSBarry Smith   an array on device is always returned and is guaranteed to contain the matrix's latest data.
24072ef1f0ffSBarry Smith 
24081cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATDENSE`, `MatDenseRestoreArrayReadAndMemType()`, `MatDenseGetArrayWriteAndMemType()`,
2409cd3f9d89SJunchao Zhang    `MatDenseGetArrayRead()`, `MatDenseRestoreArrayRead()`, `MatDenseGetArrayWrite()`, `MatDenseRestoreArrayWrite()`, `MatSeqAIJGetCSRAndMemType()`
2410cd3f9d89SJunchao Zhang @*/
24115d83a8b1SBarry Smith PetscErrorCode MatDenseGetArrayReadAndMemType(Mat A, const PetscScalar *array[], PetscMemType *mtype)
2412cd3f9d89SJunchao Zhang {
2413cd3f9d89SJunchao Zhang   PetscBool isMPI;
2414cd3f9d89SJunchao Zhang 
2415cd3f9d89SJunchao Zhang   PetscFunctionBegin;
2416cd3f9d89SJunchao Zhang   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
24174f572ea9SToby Isaac   PetscAssertPointer(array, 2);
2418e865de01SJunchao 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 */
2419cd3f9d89SJunchao Zhang   PetscCall(PetscObjectBaseTypeCompare((PetscObject)A, MATMPIDENSE, &isMPI));
2420cd3f9d89SJunchao Zhang   if (isMPI) { /* Dispatch here so that the code can be reused for all subclasses of MATDENSE */
2421cd3f9d89SJunchao Zhang     PetscCall(MatDenseGetArrayReadAndMemType(((Mat_MPIDense *)A->data)->A, array, mtype));
2422cd3f9d89SJunchao Zhang   } else {
2423cd3f9d89SJunchao Zhang     PetscErrorCode (*fptr)(Mat, const PetscScalar **, PetscMemType *);
24243ba16761SJacob Faibussowitsch 
24253ba16761SJacob Faibussowitsch     PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatDenseGetArrayReadAndMemType_C", &fptr));
2426cd3f9d89SJunchao Zhang     if (fptr) {
2427cd3f9d89SJunchao Zhang       PetscCall((*fptr)(A, array, mtype));
2428cd3f9d89SJunchao Zhang     } else {
24295c0db29aSPierre Jolivet       PetscUseMethod(A, "MatDenseGetArrayRead_C", (Mat, PetscScalar **), (A, (PetscScalar **)array));
2430cd3f9d89SJunchao Zhang       if (mtype) *mtype = PETSC_MEMTYPE_HOST;
2431cd3f9d89SJunchao Zhang     }
2432cd3f9d89SJunchao Zhang   }
24333ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2434cd3f9d89SJunchao Zhang }
2435cd3f9d89SJunchao Zhang 
2436cd3f9d89SJunchao Zhang /*@C
2437cd3f9d89SJunchao Zhang   MatDenseRestoreArrayReadAndMemType - returns access to the array that is obtained by `MatDenseGetArrayReadAndMemType()`
2438cd3f9d89SJunchao Zhang 
2439cd3f9d89SJunchao Zhang   Logically Collective
2440cd3f9d89SJunchao Zhang 
2441cd3f9d89SJunchao Zhang   Input Parameters:
2442fe59aa6dSJacob Faibussowitsch + A     - a dense matrix
2443cd3f9d89SJunchao Zhang - array - pointer to the data
2444cd3f9d89SJunchao Zhang 
2445cd3f9d89SJunchao Zhang   Level: intermediate
2446cd3f9d89SJunchao Zhang 
24471cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATDENSE`, `MatDenseGetArrayReadAndMemType()`, `MatDenseGetArray()`, `MatDenseGetArrayRead()`, `MatDenseRestoreArrayRead()`, `MatDenseGetArrayWrite()`, `MatDenseRestoreArrayWrite()`
2448cd3f9d89SJunchao Zhang @*/
24495d83a8b1SBarry Smith PetscErrorCode MatDenseRestoreArrayReadAndMemType(Mat A, const PetscScalar *array[])
2450cd3f9d89SJunchao Zhang {
2451cd3f9d89SJunchao Zhang   PetscBool isMPI;
2452cd3f9d89SJunchao Zhang 
2453cd3f9d89SJunchao Zhang   PetscFunctionBegin;
2454cd3f9d89SJunchao Zhang   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
2455*fd5c2d83SStefano Zampini   if (array) PetscAssertPointer(array, 2);
2456cd3f9d89SJunchao Zhang   PetscCall(PetscObjectBaseTypeCompare((PetscObject)A, MATMPIDENSE, &isMPI));
2457cd3f9d89SJunchao Zhang   if (isMPI) {
2458cd3f9d89SJunchao Zhang     PetscCall(MatDenseRestoreArrayReadAndMemType(((Mat_MPIDense *)A->data)->A, array));
2459cd3f9d89SJunchao Zhang   } else {
2460cd3f9d89SJunchao Zhang     PetscErrorCode (*fptr)(Mat, const PetscScalar **);
24613ba16761SJacob Faibussowitsch 
24623ba16761SJacob Faibussowitsch     PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatDenseRestoreArrayReadAndMemType_C", &fptr));
2463cd3f9d89SJunchao Zhang     if (fptr) {
2464cd3f9d89SJunchao Zhang       PetscCall((*fptr)(A, array));
2465cd3f9d89SJunchao Zhang     } else {
24665c0db29aSPierre Jolivet       PetscUseMethod(A, "MatDenseRestoreArrayRead_C", (Mat, PetscScalar **), (A, (PetscScalar **)array));
2467cd3f9d89SJunchao Zhang     }
2468*fd5c2d83SStefano Zampini     if (array) *array = NULL;
2469cd3f9d89SJunchao Zhang   }
24703ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2471cd3f9d89SJunchao Zhang }
2472cd3f9d89SJunchao Zhang 
2473cd3f9d89SJunchao Zhang /*@C
2474cd3f9d89SJunchao Zhang   MatDenseGetArrayWriteAndMemType - gives write-only access to the array where the data for a `MATDENSE` matrix is stored
2475cd3f9d89SJunchao Zhang 
2476cd3f9d89SJunchao Zhang   Logically Collective
2477cd3f9d89SJunchao Zhang 
2478cd3f9d89SJunchao Zhang   Input Parameter:
2479fe59aa6dSJacob Faibussowitsch . A - a dense matrix
2480cd3f9d89SJunchao Zhang 
2481cd3f9d89SJunchao Zhang   Output Parameters:
2482cd3f9d89SJunchao Zhang + array - pointer to the data
2483cd3f9d89SJunchao Zhang - mtype - memory type of the returned pointer
2484cd3f9d89SJunchao Zhang 
2485cd3f9d89SJunchao Zhang   Level: intermediate
2486cd3f9d89SJunchao Zhang 
2487fb850c59SBarry Smith   Note:
24882ef1f0ffSBarry Smith   If the matrix is of a device type such as `MATDENSECUDA`, `MATDENSEHIP`, etc.,
24892ef1f0ffSBarry Smith   an array on device is always returned and is guaranteed to contain the matrix's latest data.
24902ef1f0ffSBarry Smith 
24911cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATDENSE`, `MatDenseRestoreArrayWriteAndMemType()`, `MatDenseGetArrayReadAndMemType()`, `MatDenseGetArrayRead()`,
2492cd3f9d89SJunchao Zhang   `MatDenseRestoreArrayRead()`, `MatDenseGetArrayWrite()`, `MatDenseRestoreArrayWrite()`, `MatSeqAIJGetCSRAndMemType()`
2493cd3f9d89SJunchao Zhang @*/
24945d83a8b1SBarry Smith PetscErrorCode MatDenseGetArrayWriteAndMemType(Mat A, PetscScalar *array[], PetscMemType *mtype)
2495cd3f9d89SJunchao Zhang {
2496cd3f9d89SJunchao Zhang   PetscBool isMPI;
2497cd3f9d89SJunchao Zhang 
2498cd3f9d89SJunchao Zhang   PetscFunctionBegin;
2499cd3f9d89SJunchao Zhang   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
25004f572ea9SToby Isaac   PetscAssertPointer(array, 2);
2501e865de01SJunchao 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 */
2502cd3f9d89SJunchao Zhang   PetscCall(PetscObjectBaseTypeCompare((PetscObject)A, MATMPIDENSE, &isMPI));
2503cd3f9d89SJunchao Zhang   if (isMPI) {
2504cd3f9d89SJunchao Zhang     PetscCall(MatDenseGetArrayWriteAndMemType(((Mat_MPIDense *)A->data)->A, array, mtype));
2505cd3f9d89SJunchao Zhang   } else {
2506cd3f9d89SJunchao Zhang     PetscErrorCode (*fptr)(Mat, PetscScalar **, PetscMemType *);
25073ba16761SJacob Faibussowitsch 
25083ba16761SJacob Faibussowitsch     PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatDenseGetArrayWriteAndMemType_C", &fptr));
2509cd3f9d89SJunchao Zhang     if (fptr) {
2510cd3f9d89SJunchao Zhang       PetscCall((*fptr)(A, array, mtype));
2511cd3f9d89SJunchao Zhang     } else {
2512cd3f9d89SJunchao Zhang       PetscUseMethod(A, "MatDenseGetArrayWrite_C", (Mat, PetscScalar **), (A, array));
2513cd3f9d89SJunchao Zhang       if (mtype) *mtype = PETSC_MEMTYPE_HOST;
2514cd3f9d89SJunchao Zhang     }
2515cd3f9d89SJunchao Zhang   }
25163ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2517cd3f9d89SJunchao Zhang }
2518cd3f9d89SJunchao Zhang 
2519cd3f9d89SJunchao Zhang /*@C
2520cd3f9d89SJunchao Zhang   MatDenseRestoreArrayWriteAndMemType - returns access to the array that is obtained by `MatDenseGetArrayReadAndMemType()`
2521cd3f9d89SJunchao Zhang 
2522cd3f9d89SJunchao Zhang   Logically Collective
2523cd3f9d89SJunchao Zhang 
2524cd3f9d89SJunchao Zhang   Input Parameters:
2525fe59aa6dSJacob Faibussowitsch + A     - a dense matrix
2526cd3f9d89SJunchao Zhang - array - pointer to the data
2527cd3f9d89SJunchao Zhang 
2528cd3f9d89SJunchao Zhang   Level: intermediate
2529cd3f9d89SJunchao Zhang 
25301cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATDENSE`, `MatDenseGetArrayWriteAndMemType()`, `MatDenseGetArray()`, `MatDenseGetArrayRead()`, `MatDenseRestoreArrayRead()`, `MatDenseGetArrayWrite()`, `MatDenseRestoreArrayWrite()`
2531cd3f9d89SJunchao Zhang @*/
25325d83a8b1SBarry Smith PetscErrorCode MatDenseRestoreArrayWriteAndMemType(Mat A, PetscScalar *array[])
2533cd3f9d89SJunchao Zhang {
2534cd3f9d89SJunchao Zhang   PetscBool isMPI;
2535cd3f9d89SJunchao Zhang 
2536cd3f9d89SJunchao Zhang   PetscFunctionBegin;
2537cd3f9d89SJunchao Zhang   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
2538*fd5c2d83SStefano Zampini   if (array) PetscAssertPointer(array, 2);
2539cd3f9d89SJunchao Zhang   PetscCall(PetscObjectBaseTypeCompare((PetscObject)A, MATMPIDENSE, &isMPI));
2540cd3f9d89SJunchao Zhang   if (isMPI) {
2541cd3f9d89SJunchao Zhang     PetscCall(MatDenseRestoreArrayWriteAndMemType(((Mat_MPIDense *)A->data)->A, array));
2542cd3f9d89SJunchao Zhang   } else {
2543cd3f9d89SJunchao Zhang     PetscErrorCode (*fptr)(Mat, PetscScalar **);
25443ba16761SJacob Faibussowitsch 
25453ba16761SJacob Faibussowitsch     PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatDenseRestoreArrayWriteAndMemType_C", &fptr));
2546cd3f9d89SJunchao Zhang     if (fptr) {
2547cd3f9d89SJunchao Zhang       PetscCall((*fptr)(A, array));
2548cd3f9d89SJunchao Zhang     } else {
2549cd3f9d89SJunchao Zhang       PetscUseMethod(A, "MatDenseRestoreArrayWrite_C", (Mat, PetscScalar **), (A, array));
2550cd3f9d89SJunchao Zhang     }
2551*fd5c2d83SStefano Zampini     if (array) *array = NULL;
2552cd3f9d89SJunchao Zhang   }
2553cd3f9d89SJunchao Zhang   PetscCall(PetscObjectStateIncrease((PetscObject)A));
25543ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2555cd3f9d89SJunchao Zhang }
2556cd3f9d89SJunchao Zhang 
2557d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatCreateSubMatrix_SeqDense(Mat A, IS isrow, IS iscol, MatReuse scall, Mat *B)
2558d71ae5a4SJacob Faibussowitsch {
2559c0bbcb79SLois Curfman McInnes   Mat_SeqDense   *mat = (Mat_SeqDense *)A->data;
2560bf5a80bcSToby Isaac   PetscInt        i, j, nrows, ncols, ldb;
25615d0c19d7SBarry Smith   const PetscInt *irow, *icol;
256287828ca2SBarry Smith   PetscScalar    *av, *bv, *v = mat->v;
25630754003eSLois Curfman McInnes   Mat             newmat;
25640754003eSLois Curfman McInnes 
25653a40ed3dSBarry Smith   PetscFunctionBegin;
25669566063dSJacob Faibussowitsch   PetscCall(ISGetIndices(isrow, &irow));
25679566063dSJacob Faibussowitsch   PetscCall(ISGetIndices(iscol, &icol));
25689566063dSJacob Faibussowitsch   PetscCall(ISGetLocalSize(isrow, &nrows));
25699566063dSJacob Faibussowitsch   PetscCall(ISGetLocalSize(iscol, &ncols));
25700754003eSLois Curfman McInnes 
2571182d2002SSatish Balay   /* Check submatrixcall */
2572182d2002SSatish Balay   if (scall == MAT_REUSE_MATRIX) {
257313f74950SBarry Smith     PetscInt n_cols, n_rows;
25749566063dSJacob Faibussowitsch     PetscCall(MatGetSize(*B, &n_rows, &n_cols));
257521a2c019SBarry Smith     if (n_rows != nrows || n_cols != ncols) {
2576f746d493SDmitry Karpeev       /* resize the result matrix to match number of requested rows/columns */
25779566063dSJacob Faibussowitsch       PetscCall(MatSetSizes(*B, nrows, ncols, nrows, ncols));
257821a2c019SBarry Smith     }
2579182d2002SSatish Balay     newmat = *B;
2580182d2002SSatish Balay   } else {
25810754003eSLois Curfman McInnes     /* Create and fill new matrix */
25829566063dSJacob Faibussowitsch     PetscCall(MatCreate(PetscObjectComm((PetscObject)A), &newmat));
25839566063dSJacob Faibussowitsch     PetscCall(MatSetSizes(newmat, nrows, ncols, nrows, ncols));
25849566063dSJacob Faibussowitsch     PetscCall(MatSetType(newmat, ((PetscObject)A)->type_name));
25859566063dSJacob Faibussowitsch     PetscCall(MatSeqDenseSetPreallocation(newmat, NULL));
2586182d2002SSatish Balay   }
2587182d2002SSatish Balay 
2588182d2002SSatish Balay   /* Now extract the data pointers and do the copy,column at a time */
25899566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArray(newmat, &bv));
25909566063dSJacob Faibussowitsch   PetscCall(MatDenseGetLDA(newmat, &ldb));
2591182d2002SSatish Balay   for (i = 0; i < ncols; i++) {
25926de62eeeSBarry Smith     av = v + mat->lda * icol[i];
2593ca15aa20SStefano Zampini     for (j = 0; j < nrows; j++) bv[j] = av[irow[j]];
2594bf5a80bcSToby Isaac     bv += ldb;
25950754003eSLois Curfman McInnes   }
25969566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArray(newmat, &bv));
2597182d2002SSatish Balay 
2598182d2002SSatish Balay   /* Assemble the matrices so that the correct flags are set */
25999566063dSJacob Faibussowitsch   PetscCall(MatAssemblyBegin(newmat, MAT_FINAL_ASSEMBLY));
26009566063dSJacob Faibussowitsch   PetscCall(MatAssemblyEnd(newmat, MAT_FINAL_ASSEMBLY));
26010754003eSLois Curfman McInnes 
26020754003eSLois Curfman McInnes   /* Free work space */
26039566063dSJacob Faibussowitsch   PetscCall(ISRestoreIndices(isrow, &irow));
26049566063dSJacob Faibussowitsch   PetscCall(ISRestoreIndices(iscol, &icol));
2605182d2002SSatish Balay   *B = newmat;
26063ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
26070754003eSLois Curfman McInnes }
26080754003eSLois Curfman McInnes 
2609d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatCreateSubMatrices_SeqDense(Mat A, PetscInt n, const IS irow[], const IS icol[], MatReuse scall, Mat *B[])
2610d71ae5a4SJacob Faibussowitsch {
261113f74950SBarry Smith   PetscInt i;
2612905e6a2fSBarry Smith 
26133a40ed3dSBarry Smith   PetscFunctionBegin;
261448a46eb9SPierre Jolivet   if (scall == MAT_INITIAL_MATRIX) PetscCall(PetscCalloc1(n, B));
2615905e6a2fSBarry Smith 
261648a46eb9SPierre Jolivet   for (i = 0; i < n; i++) PetscCall(MatCreateSubMatrix_SeqDense(A, irow[i], icol[i], scall, &(*B)[i]));
26173ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2618905e6a2fSBarry Smith }
2619905e6a2fSBarry Smith 
2620d71ae5a4SJacob Faibussowitsch PetscErrorCode MatCopy_SeqDense(Mat A, Mat B, MatStructure str)
2621d71ae5a4SJacob Faibussowitsch {
26224b0e389bSBarry Smith   Mat_SeqDense      *a = (Mat_SeqDense *)A->data, *b = (Mat_SeqDense *)B->data;
2623ca15aa20SStefano Zampini   const PetscScalar *va;
2624ca15aa20SStefano Zampini   PetscScalar       *vb;
2625d0f46423SBarry Smith   PetscInt           lda1 = a->lda, lda2 = b->lda, m = A->rmap->n, n = A->cmap->n, j;
26263a40ed3dSBarry Smith 
26273a40ed3dSBarry Smith   PetscFunctionBegin;
262833f4a19fSKris Buschelman   /* If the two matrices don't have the same copy implementation, they aren't compatible for fast copy. */
262933f4a19fSKris Buschelman   if (A->ops->copy != B->ops->copy) {
26309566063dSJacob Faibussowitsch     PetscCall(MatCopy_Basic(A, B, str));
26313ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
26323a40ed3dSBarry Smith   }
2633aed4548fSBarry Smith   PetscCheck(m == B->rmap->n && n == B->cmap->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "size(B) != size(A)");
26349566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArrayRead(A, &va));
26359566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArray(B, &vb));
2636a5ce6ee0Svictorle   if (lda1 > m || lda2 > m) {
263748a46eb9SPierre Jolivet     for (j = 0; j < n; j++) PetscCall(PetscArraycpy(vb + j * lda2, va + j * lda1, m));
2638a5ce6ee0Svictorle   } else {
26399566063dSJacob Faibussowitsch     PetscCall(PetscArraycpy(vb, va, A->rmap->n * A->cmap->n));
2640a5ce6ee0Svictorle   }
26419566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArray(B, &vb));
26429566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArrayRead(A, &va));
26439566063dSJacob Faibussowitsch   PetscCall(MatAssemblyBegin(B, MAT_FINAL_ASSEMBLY));
26449566063dSJacob Faibussowitsch   PetscCall(MatAssemblyEnd(B, MAT_FINAL_ASSEMBLY));
26453ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2646273d9f13SBarry Smith }
2647273d9f13SBarry Smith 
2648d71ae5a4SJacob Faibussowitsch PetscErrorCode MatSetUp_SeqDense(Mat A)
2649d71ae5a4SJacob Faibussowitsch {
2650273d9f13SBarry Smith   PetscFunctionBegin;
26519566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetUp(A->rmap));
26529566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetUp(A->cmap));
265348a46eb9SPierre Jolivet   if (!A->preallocated) PetscCall(MatSeqDenseSetPreallocation(A, NULL));
26543ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
26554b0e389bSBarry Smith }
26564b0e389bSBarry Smith 
2657d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatConjugate_SeqDense(Mat A)
2658d71ae5a4SJacob Faibussowitsch {
26594396437dSToby Isaac   Mat_SeqDense *mat = (Mat_SeqDense *)A->data;
266006c5243aSJose E. Roman   PetscInt      i, j;
26614396437dSToby Isaac   PetscInt      min = PetscMin(A->rmap->n, A->cmap->n);
2662ca15aa20SStefano Zampini   PetscScalar  *aa;
2663ba337c44SJed Brown 
2664ba337c44SJed Brown   PetscFunctionBegin;
26659566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArray(A, &aa));
266606c5243aSJose E. Roman   for (j = 0; j < A->cmap->n; j++) {
266706c5243aSJose E. Roman     for (i = 0; i < A->rmap->n; i++) aa[i + j * mat->lda] = PetscConj(aa[i + j * mat->lda]);
266806c5243aSJose E. Roman   }
26699566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArray(A, &aa));
26709371c9d4SSatish Balay   if (mat->tau)
26719371c9d4SSatish Balay     for (i = 0; i < min; i++) mat->tau[i] = PetscConj(mat->tau[i]);
26723ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2673ba337c44SJed Brown }
2674ba337c44SJed Brown 
2675d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatRealPart_SeqDense(Mat A)
2676d71ae5a4SJacob Faibussowitsch {
267706c5243aSJose E. Roman   Mat_SeqDense *mat = (Mat_SeqDense *)A->data;
267806c5243aSJose E. Roman   PetscInt      i, j;
2679ca15aa20SStefano Zampini   PetscScalar  *aa;
2680ba337c44SJed Brown 
2681ba337c44SJed Brown   PetscFunctionBegin;
26829566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArray(A, &aa));
268306c5243aSJose E. Roman   for (j = 0; j < A->cmap->n; j++) {
268406c5243aSJose E. Roman     for (i = 0; i < A->rmap->n; i++) aa[i + j * mat->lda] = PetscRealPart(aa[i + j * mat->lda]);
268506c5243aSJose E. Roman   }
26869566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArray(A, &aa));
26873ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2688ba337c44SJed Brown }
2689ba337c44SJed Brown 
2690d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatImaginaryPart_SeqDense(Mat A)
2691d71ae5a4SJacob Faibussowitsch {
269206c5243aSJose E. Roman   Mat_SeqDense *mat = (Mat_SeqDense *)A->data;
269306c5243aSJose E. Roman   PetscInt      i, j;
2694ca15aa20SStefano Zampini   PetscScalar  *aa;
2695ba337c44SJed Brown 
2696ba337c44SJed Brown   PetscFunctionBegin;
26979566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArray(A, &aa));
269806c5243aSJose E. Roman   for (j = 0; j < A->cmap->n; j++) {
269906c5243aSJose E. Roman     for (i = 0; i < A->rmap->n; i++) aa[i + j * mat->lda] = PetscImaginaryPart(aa[i + j * mat->lda]);
270006c5243aSJose E. Roman   }
27019566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArray(A, &aa));
27023ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2703ba337c44SJed Brown }
2704284134d9SBarry Smith 
2705d71ae5a4SJacob Faibussowitsch PetscErrorCode MatMatMultSymbolic_SeqDense_SeqDense(Mat A, Mat B, PetscReal fill, Mat C)
2706d71ae5a4SJacob Faibussowitsch {
2707d0f46423SBarry Smith   PetscInt  m = A->rmap->n, n = B->cmap->n;
270847d993e7Ssuyashtn   PetscBool cisdense = PETSC_FALSE;
2709a9fe9ddaSSatish Balay 
2710ee16a9a1SHong Zhang   PetscFunctionBegin;
27119566063dSJacob Faibussowitsch   PetscCall(MatSetSizes(C, m, n, m, n));
271247d993e7Ssuyashtn #if defined(PETSC_HAVE_CUDA)
27139566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompareAny((PetscObject)C, &cisdense, MATSEQDENSE, MATSEQDENSECUDA, ""));
271447d993e7Ssuyashtn #endif
271547d993e7Ssuyashtn #if defined(PETSC_HAVE_HIP)
271647d993e7Ssuyashtn   PetscCall(PetscObjectTypeCompareAny((PetscObject)C, &cisdense, MATSEQDENSE, MATSEQDENSEHIP, ""));
271747d993e7Ssuyashtn #endif
27187a3c3d58SStefano Zampini   if (!cisdense) {
27197a3c3d58SStefano Zampini     PetscBool flg;
27207a3c3d58SStefano Zampini 
27219566063dSJacob Faibussowitsch     PetscCall(PetscObjectTypeCompare((PetscObject)B, ((PetscObject)A)->type_name, &flg));
27229566063dSJacob Faibussowitsch     PetscCall(MatSetType(C, flg ? ((PetscObject)A)->type_name : MATDENSE));
27237a3c3d58SStefano Zampini   }
27249566063dSJacob Faibussowitsch   PetscCall(MatSetUp(C));
27253ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2726ee16a9a1SHong Zhang }
2727a9fe9ddaSSatish Balay 
2728d71ae5a4SJacob Faibussowitsch PetscErrorCode MatMatMultNumeric_SeqDense_SeqDense(Mat A, Mat B, Mat C)
2729d71ae5a4SJacob Faibussowitsch {
27306718818eSStefano Zampini   Mat_SeqDense      *a = (Mat_SeqDense *)A->data, *b = (Mat_SeqDense *)B->data, *c = (Mat_SeqDense *)C->data;
27310805154bSBarry Smith   PetscBLASInt       m, n, k;
2732ca15aa20SStefano Zampini   const PetscScalar *av, *bv;
2733ca15aa20SStefano Zampini   PetscScalar       *cv;
2734a9fe9ddaSSatish Balay   PetscScalar        _DOne = 1.0, _DZero = 0.0;
2735a9fe9ddaSSatish Balay 
2736a9fe9ddaSSatish Balay   PetscFunctionBegin;
27379566063dSJacob Faibussowitsch   PetscCall(PetscBLASIntCast(C->rmap->n, &m));
27389566063dSJacob Faibussowitsch   PetscCall(PetscBLASIntCast(C->cmap->n, &n));
27399566063dSJacob Faibussowitsch   PetscCall(PetscBLASIntCast(A->cmap->n, &k));
27403ba16761SJacob Faibussowitsch   if (!m || !n || !k) PetscFunctionReturn(PETSC_SUCCESS);
27419566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArrayRead(A, &av));
27429566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArrayRead(B, &bv));
27439566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArrayWrite(C, &cv));
2744792fecdfSBarry Smith   PetscCallBLAS("BLASgemm", BLASgemm_("N", "N", &m, &n, &k, &_DOne, av, &a->lda, bv, &b->lda, &_DZero, cv, &c->lda));
27459566063dSJacob Faibussowitsch   PetscCall(PetscLogFlops(1.0 * m * n * k + 1.0 * m * n * (k - 1)));
27469566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArrayRead(A, &av));
27479566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArrayRead(B, &bv));
27489566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArrayWrite(C, &cv));
27493ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2750a9fe9ddaSSatish Balay }
2751a9fe9ddaSSatish Balay 
2752d71ae5a4SJacob Faibussowitsch PetscErrorCode MatMatTransposeMultSymbolic_SeqDense_SeqDense(Mat A, Mat B, PetscReal fill, Mat C)
2753d71ae5a4SJacob Faibussowitsch {
275469f65d41SStefano Zampini   PetscInt  m = A->rmap->n, n = B->rmap->n;
275547d993e7Ssuyashtn   PetscBool cisdense = PETSC_FALSE;
275669f65d41SStefano Zampini 
275769f65d41SStefano Zampini   PetscFunctionBegin;
27589566063dSJacob Faibussowitsch   PetscCall(MatSetSizes(C, m, n, m, n));
275947d993e7Ssuyashtn #if defined(PETSC_HAVE_CUDA)
27609566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompareAny((PetscObject)C, &cisdense, MATSEQDENSE, MATSEQDENSECUDA, ""));
276147d993e7Ssuyashtn #endif
276247d993e7Ssuyashtn #if defined(PETSC_HAVE_HIP)
276347d993e7Ssuyashtn   PetscCall(PetscObjectTypeCompareAny((PetscObject)C, &cisdense, MATSEQDENSE, MATSEQDENSEHIP, ""));
276447d993e7Ssuyashtn #endif
27657a3c3d58SStefano Zampini   if (!cisdense) {
27667a3c3d58SStefano Zampini     PetscBool flg;
27677a3c3d58SStefano Zampini 
27689566063dSJacob Faibussowitsch     PetscCall(PetscObjectTypeCompare((PetscObject)B, ((PetscObject)A)->type_name, &flg));
27699566063dSJacob Faibussowitsch     PetscCall(MatSetType(C, flg ? ((PetscObject)A)->type_name : MATDENSE));
27707a3c3d58SStefano Zampini   }
27719566063dSJacob Faibussowitsch   PetscCall(MatSetUp(C));
27723ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
277369f65d41SStefano Zampini }
277469f65d41SStefano Zampini 
2775d71ae5a4SJacob Faibussowitsch PetscErrorCode MatMatTransposeMultNumeric_SeqDense_SeqDense(Mat A, Mat B, Mat C)
2776d71ae5a4SJacob Faibussowitsch {
277769f65d41SStefano Zampini   Mat_SeqDense      *a = (Mat_SeqDense *)A->data;
277869f65d41SStefano Zampini   Mat_SeqDense      *b = (Mat_SeqDense *)B->data;
277969f65d41SStefano Zampini   Mat_SeqDense      *c = (Mat_SeqDense *)C->data;
27806718818eSStefano Zampini   const PetscScalar *av, *bv;
27816718818eSStefano Zampini   PetscScalar       *cv;
278269f65d41SStefano Zampini   PetscBLASInt       m, n, k;
278369f65d41SStefano Zampini   PetscScalar        _DOne = 1.0, _DZero = 0.0;
278469f65d41SStefano Zampini 
278569f65d41SStefano Zampini   PetscFunctionBegin;
27869566063dSJacob Faibussowitsch   PetscCall(PetscBLASIntCast(C->rmap->n, &m));
27879566063dSJacob Faibussowitsch   PetscCall(PetscBLASIntCast(C->cmap->n, &n));
27889566063dSJacob Faibussowitsch   PetscCall(PetscBLASIntCast(A->cmap->n, &k));
27893ba16761SJacob Faibussowitsch   if (!m || !n || !k) PetscFunctionReturn(PETSC_SUCCESS);
27909566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArrayRead(A, &av));
27919566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArrayRead(B, &bv));
27929566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArrayWrite(C, &cv));
2793792fecdfSBarry Smith   PetscCallBLAS("BLASgemm", BLASgemm_("N", "T", &m, &n, &k, &_DOne, av, &a->lda, bv, &b->lda, &_DZero, cv, &c->lda));
27949566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArrayRead(A, &av));
27959566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArrayRead(B, &bv));
27969566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArrayWrite(C, &cv));
27979566063dSJacob Faibussowitsch   PetscCall(PetscLogFlops(1.0 * m * n * k + 1.0 * m * n * (k - 1)));
27983ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
279969f65d41SStefano Zampini }
280069f65d41SStefano Zampini 
2801d71ae5a4SJacob Faibussowitsch PetscErrorCode MatTransposeMatMultSymbolic_SeqDense_SeqDense(Mat A, Mat B, PetscReal fill, Mat C)
2802d71ae5a4SJacob Faibussowitsch {
2803d0f46423SBarry Smith   PetscInt  m = A->cmap->n, n = B->cmap->n;
280447d993e7Ssuyashtn   PetscBool cisdense = PETSC_FALSE;
2805a9fe9ddaSSatish Balay 
2806ee16a9a1SHong Zhang   PetscFunctionBegin;
28079566063dSJacob Faibussowitsch   PetscCall(MatSetSizes(C, m, n, m, n));
280847d993e7Ssuyashtn #if defined(PETSC_HAVE_CUDA)
28099566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompareAny((PetscObject)C, &cisdense, MATSEQDENSE, MATSEQDENSECUDA, ""));
281047d993e7Ssuyashtn #endif
281147d993e7Ssuyashtn #if defined(PETSC_HAVE_HIP)
281247d993e7Ssuyashtn   PetscCall(PetscObjectTypeCompareAny((PetscObject)C, &cisdense, MATSEQDENSE, MATSEQDENSEHIP, ""));
281347d993e7Ssuyashtn #endif
28147a3c3d58SStefano Zampini   if (!cisdense) {
28157a3c3d58SStefano Zampini     PetscBool flg;
28167a3c3d58SStefano Zampini 
28179566063dSJacob Faibussowitsch     PetscCall(PetscObjectTypeCompare((PetscObject)B, ((PetscObject)A)->type_name, &flg));
28189566063dSJacob Faibussowitsch     PetscCall(MatSetType(C, flg ? ((PetscObject)A)->type_name : MATDENSE));
28197a3c3d58SStefano Zampini   }
28209566063dSJacob Faibussowitsch   PetscCall(MatSetUp(C));
28213ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2822ee16a9a1SHong Zhang }
2823a9fe9ddaSSatish Balay 
2824d71ae5a4SJacob Faibussowitsch PetscErrorCode MatTransposeMatMultNumeric_SeqDense_SeqDense(Mat A, Mat B, Mat C)
2825d71ae5a4SJacob Faibussowitsch {
2826a9fe9ddaSSatish Balay   Mat_SeqDense      *a = (Mat_SeqDense *)A->data;
2827a9fe9ddaSSatish Balay   Mat_SeqDense      *b = (Mat_SeqDense *)B->data;
2828a9fe9ddaSSatish Balay   Mat_SeqDense      *c = (Mat_SeqDense *)C->data;
28296718818eSStefano Zampini   const PetscScalar *av, *bv;
28306718818eSStefano Zampini   PetscScalar       *cv;
28310805154bSBarry Smith   PetscBLASInt       m, n, k;
2832a9fe9ddaSSatish Balay   PetscScalar        _DOne = 1.0, _DZero = 0.0;
2833a9fe9ddaSSatish Balay 
2834a9fe9ddaSSatish Balay   PetscFunctionBegin;
28359566063dSJacob Faibussowitsch   PetscCall(PetscBLASIntCast(C->rmap->n, &m));
28369566063dSJacob Faibussowitsch   PetscCall(PetscBLASIntCast(C->cmap->n, &n));
28379566063dSJacob Faibussowitsch   PetscCall(PetscBLASIntCast(A->rmap->n, &k));
28383ba16761SJacob Faibussowitsch   if (!m || !n || !k) PetscFunctionReturn(PETSC_SUCCESS);
28399566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArrayRead(A, &av));
28409566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArrayRead(B, &bv));
28419566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArrayWrite(C, &cv));
2842792fecdfSBarry Smith   PetscCallBLAS("BLASgemm", BLASgemm_("T", "N", &m, &n, &k, &_DOne, av, &a->lda, bv, &b->lda, &_DZero, cv, &c->lda));
28439566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArrayRead(A, &av));
28449566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArrayRead(B, &bv));
28459566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArrayWrite(C, &cv));
28469566063dSJacob Faibussowitsch   PetscCall(PetscLogFlops(1.0 * m * n * k + 1.0 * m * n * (k - 1)));
28473ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2848a9fe9ddaSSatish Balay }
2849985db425SBarry Smith 
2850d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatProductSetFromOptions_SeqDense_AB(Mat C)
2851d71ae5a4SJacob Faibussowitsch {
28524222ddf1SHong Zhang   PetscFunctionBegin;
28534222ddf1SHong Zhang   C->ops->matmultsymbolic = MatMatMultSymbolic_SeqDense_SeqDense;
28544222ddf1SHong Zhang   C->ops->productsymbolic = MatProductSymbolic_AB;
28553ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
28564222ddf1SHong Zhang }
28574222ddf1SHong Zhang 
2858d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatProductSetFromOptions_SeqDense_AtB(Mat C)
2859d71ae5a4SJacob Faibussowitsch {
28604222ddf1SHong Zhang   PetscFunctionBegin;
28614222ddf1SHong Zhang   C->ops->transposematmultsymbolic = MatTransposeMatMultSymbolic_SeqDense_SeqDense;
28624222ddf1SHong Zhang   C->ops->productsymbolic          = MatProductSymbolic_AtB;
28633ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
28644222ddf1SHong Zhang }
28654222ddf1SHong Zhang 
2866d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatProductSetFromOptions_SeqDense_ABt(Mat C)
2867d71ae5a4SJacob Faibussowitsch {
28684222ddf1SHong Zhang   PetscFunctionBegin;
28694222ddf1SHong Zhang   C->ops->mattransposemultsymbolic = MatMatTransposeMultSymbolic_SeqDense_SeqDense;
28704222ddf1SHong Zhang   C->ops->productsymbolic          = MatProductSymbolic_ABt;
28713ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
28724222ddf1SHong Zhang }
28734222ddf1SHong Zhang 
2874d71ae5a4SJacob Faibussowitsch PETSC_INTERN PetscErrorCode MatProductSetFromOptions_SeqDense(Mat C)
2875d71ae5a4SJacob Faibussowitsch {
28764222ddf1SHong Zhang   Mat_Product *product = C->product;
28774222ddf1SHong Zhang 
28784222ddf1SHong Zhang   PetscFunctionBegin;
28794222ddf1SHong Zhang   switch (product->type) {
2880d71ae5a4SJacob Faibussowitsch   case MATPRODUCT_AB:
2881d71ae5a4SJacob Faibussowitsch     PetscCall(MatProductSetFromOptions_SeqDense_AB(C));
2882d71ae5a4SJacob Faibussowitsch     break;
2883d71ae5a4SJacob Faibussowitsch   case MATPRODUCT_AtB:
2884d71ae5a4SJacob Faibussowitsch     PetscCall(MatProductSetFromOptions_SeqDense_AtB(C));
2885d71ae5a4SJacob Faibussowitsch     break;
2886d71ae5a4SJacob Faibussowitsch   case MATPRODUCT_ABt:
2887d71ae5a4SJacob Faibussowitsch     PetscCall(MatProductSetFromOptions_SeqDense_ABt(C));
2888d71ae5a4SJacob Faibussowitsch     break;
2889d71ae5a4SJacob Faibussowitsch   default:
2890d71ae5a4SJacob Faibussowitsch     break;
28914222ddf1SHong Zhang   }
28923ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
28934222ddf1SHong Zhang }
28944222ddf1SHong Zhang 
2895d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatGetRowMax_SeqDense(Mat A, Vec v, PetscInt idx[])
2896d71ae5a4SJacob Faibussowitsch {
2897985db425SBarry Smith   Mat_SeqDense      *a = (Mat_SeqDense *)A->data;
2898d0f46423SBarry Smith   PetscInt           i, j, m = A->rmap->n, n = A->cmap->n, p;
2899985db425SBarry Smith   PetscScalar       *x;
2900ca15aa20SStefano Zampini   const PetscScalar *aa;
2901985db425SBarry Smith 
2902985db425SBarry Smith   PetscFunctionBegin;
290328b400f6SJacob Faibussowitsch   PetscCheck(!A->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
29049566063dSJacob Faibussowitsch   PetscCall(VecGetArray(v, &x));
29059566063dSJacob Faibussowitsch   PetscCall(VecGetLocalSize(v, &p));
29069566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArrayRead(A, &aa));
290708401ef6SPierre Jolivet   PetscCheck(p == A->rmap->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Nonconforming matrix and vector");
2908985db425SBarry Smith   for (i = 0; i < m; i++) {
29099371c9d4SSatish Balay     x[i] = aa[i];
29109371c9d4SSatish Balay     if (idx) idx[i] = 0;
2911985db425SBarry Smith     for (j = 1; j < n; j++) {
29129371c9d4SSatish Balay       if (PetscRealPart(x[i]) < PetscRealPart(aa[i + a->lda * j])) {
29139371c9d4SSatish Balay         x[i] = aa[i + a->lda * j];
29149371c9d4SSatish Balay         if (idx) idx[i] = j;
29159371c9d4SSatish Balay       }
2916985db425SBarry Smith     }
2917985db425SBarry Smith   }
29189566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArrayRead(A, &aa));
29199566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(v, &x));
29203ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2921985db425SBarry Smith }
2922985db425SBarry Smith 
2923d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatGetRowMaxAbs_SeqDense(Mat A, Vec v, PetscInt idx[])
2924d71ae5a4SJacob Faibussowitsch {
2925985db425SBarry Smith   Mat_SeqDense      *a = (Mat_SeqDense *)A->data;
2926d0f46423SBarry Smith   PetscInt           i, j, m = A->rmap->n, n = A->cmap->n, p;
2927985db425SBarry Smith   PetscScalar       *x;
2928985db425SBarry Smith   PetscReal          atmp;
2929ca15aa20SStefano Zampini   const PetscScalar *aa;
2930985db425SBarry Smith 
2931985db425SBarry Smith   PetscFunctionBegin;
293228b400f6SJacob Faibussowitsch   PetscCheck(!A->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
29339566063dSJacob Faibussowitsch   PetscCall(VecGetArray(v, &x));
29349566063dSJacob Faibussowitsch   PetscCall(VecGetLocalSize(v, &p));
29359566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArrayRead(A, &aa));
293608401ef6SPierre Jolivet   PetscCheck(p == A->rmap->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Nonconforming matrix and vector");
2937985db425SBarry Smith   for (i = 0; i < m; i++) {
29389189402eSHong Zhang     x[i] = PetscAbsScalar(aa[i]);
2939985db425SBarry Smith     for (j = 1; j < n; j++) {
2940ca15aa20SStefano Zampini       atmp = PetscAbsScalar(aa[i + a->lda * j]);
29419371c9d4SSatish Balay       if (PetscAbsScalar(x[i]) < atmp) {
29429371c9d4SSatish Balay         x[i] = atmp;
29439371c9d4SSatish Balay         if (idx) idx[i] = j;
29449371c9d4SSatish Balay       }
2945985db425SBarry Smith     }
2946985db425SBarry Smith   }
29479566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArrayRead(A, &aa));
29489566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(v, &x));
29493ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2950985db425SBarry Smith }
2951985db425SBarry Smith 
2952d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatGetRowMin_SeqDense(Mat A, Vec v, PetscInt idx[])
2953d71ae5a4SJacob Faibussowitsch {
2954985db425SBarry Smith   Mat_SeqDense      *a = (Mat_SeqDense *)A->data;
2955d0f46423SBarry Smith   PetscInt           i, j, m = A->rmap->n, n = A->cmap->n, p;
2956985db425SBarry Smith   PetscScalar       *x;
2957ca15aa20SStefano Zampini   const PetscScalar *aa;
2958985db425SBarry Smith 
2959985db425SBarry Smith   PetscFunctionBegin;
296028b400f6SJacob Faibussowitsch   PetscCheck(!A->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
29619566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArrayRead(A, &aa));
29629566063dSJacob Faibussowitsch   PetscCall(VecGetArray(v, &x));
29639566063dSJacob Faibussowitsch   PetscCall(VecGetLocalSize(v, &p));
296408401ef6SPierre Jolivet   PetscCheck(p == A->rmap->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Nonconforming matrix and vector");
2965985db425SBarry Smith   for (i = 0; i < m; i++) {
29669371c9d4SSatish Balay     x[i] = aa[i];
29679371c9d4SSatish Balay     if (idx) idx[i] = 0;
2968985db425SBarry Smith     for (j = 1; j < n; j++) {
29699371c9d4SSatish Balay       if (PetscRealPart(x[i]) > PetscRealPart(aa[i + a->lda * j])) {
29709371c9d4SSatish Balay         x[i] = aa[i + a->lda * j];
29719371c9d4SSatish Balay         if (idx) idx[i] = j;
29729371c9d4SSatish Balay       }
2973985db425SBarry Smith     }
2974985db425SBarry Smith   }
29759566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(v, &x));
29769566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArrayRead(A, &aa));
29773ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2978985db425SBarry Smith }
2979985db425SBarry Smith 
2980d71ae5a4SJacob Faibussowitsch PetscErrorCode MatGetColumnVector_SeqDense(Mat A, Vec v, PetscInt col)
2981d71ae5a4SJacob Faibussowitsch {
29828d0534beSBarry Smith   Mat_SeqDense      *a = (Mat_SeqDense *)A->data;
29838d0534beSBarry Smith   PetscScalar       *x;
2984ca15aa20SStefano Zampini   const PetscScalar *aa;
29858d0534beSBarry Smith 
29868d0534beSBarry Smith   PetscFunctionBegin;
298728b400f6SJacob Faibussowitsch   PetscCheck(!A->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
29889566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArrayRead(A, &aa));
29899566063dSJacob Faibussowitsch   PetscCall(VecGetArray(v, &x));
29909566063dSJacob Faibussowitsch   PetscCall(PetscArraycpy(x, aa + col * a->lda, A->rmap->n));
29919566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(v, &x));
29929566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArrayRead(A, &aa));
29933ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
29948d0534beSBarry Smith }
29958d0534beSBarry Smith 
2996d71ae5a4SJacob Faibussowitsch PETSC_INTERN PetscErrorCode MatGetColumnReductions_SeqDense(Mat A, PetscInt type, PetscReal *reductions)
2997d71ae5a4SJacob Faibussowitsch {
29980716a85fSBarry Smith   PetscInt           i, j, m, n;
29991683a169SBarry Smith   const PetscScalar *a;
30000716a85fSBarry Smith 
30010716a85fSBarry Smith   PetscFunctionBegin;
30029566063dSJacob Faibussowitsch   PetscCall(MatGetSize(A, &m, &n));
30039566063dSJacob Faibussowitsch   PetscCall(PetscArrayzero(reductions, n));
30049566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArrayRead(A, &a));
3005857cbf51SRichard Tran Mills   if (type == NORM_2) {
30060716a85fSBarry Smith     for (i = 0; i < n; i++) {
3007ad540459SPierre Jolivet       for (j = 0; j < m; j++) reductions[i] += PetscAbsScalar(a[j] * a[j]);
300816cd844bSPierre Jolivet       a = PetscSafePointerPlusOffset(a, m);
30090716a85fSBarry Smith     }
3010857cbf51SRichard Tran Mills   } else if (type == NORM_1) {
30110716a85fSBarry Smith     for (i = 0; i < n; i++) {
3012ad540459SPierre Jolivet       for (j = 0; j < m; j++) reductions[i] += PetscAbsScalar(a[j]);
301316cd844bSPierre Jolivet       a = PetscSafePointerPlusOffset(a, m);
30140716a85fSBarry Smith     }
3015857cbf51SRichard Tran Mills   } else if (type == NORM_INFINITY) {
30160716a85fSBarry Smith     for (i = 0; i < n; i++) {
3017ad540459SPierre Jolivet       for (j = 0; j < m; j++) reductions[i] = PetscMax(PetscAbsScalar(a[j]), reductions[i]);
301816cd844bSPierre Jolivet       a = PetscSafePointerPlusOffset(a, m);
30190716a85fSBarry Smith     }
3020857cbf51SRichard Tran Mills   } else if (type == REDUCTION_SUM_REALPART || type == REDUCTION_MEAN_REALPART) {
3021a873a8cdSSam Reynolds     for (i = 0; i < n; i++) {
3022ad540459SPierre Jolivet       for (j = 0; j < m; j++) reductions[i] += PetscRealPart(a[j]);
302316cd844bSPierre Jolivet       a = PetscSafePointerPlusOffset(a, m);
3024a873a8cdSSam Reynolds     }
3025857cbf51SRichard Tran Mills   } else if (type == REDUCTION_SUM_IMAGINARYPART || type == REDUCTION_MEAN_IMAGINARYPART) {
3026857cbf51SRichard Tran Mills     for (i = 0; i < n; i++) {
3027ad540459SPierre Jolivet       for (j = 0; j < m; j++) reductions[i] += PetscImaginaryPart(a[j]);
302816cd844bSPierre Jolivet       a = PetscSafePointerPlusOffset(a, m);
3029857cbf51SRichard Tran Mills     }
3030857cbf51SRichard Tran Mills   } else SETERRQ(PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONG, "Unknown reduction type");
30319566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArrayRead(A, &a));
3032857cbf51SRichard Tran Mills   if (type == NORM_2) {
3033a873a8cdSSam Reynolds     for (i = 0; i < n; i++) reductions[i] = PetscSqrtReal(reductions[i]);
3034857cbf51SRichard Tran Mills   } else if (type == REDUCTION_MEAN_REALPART || type == REDUCTION_MEAN_IMAGINARYPART) {
3035a873a8cdSSam Reynolds     for (i = 0; i < n; i++) reductions[i] /= m;
30360716a85fSBarry Smith   }
30373ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
30380716a85fSBarry Smith }
30390716a85fSBarry Smith 
3040d71ae5a4SJacob Faibussowitsch PetscErrorCode MatSetRandom_SeqDense(Mat x, PetscRandom rctx)
3041d71ae5a4SJacob Faibussowitsch {
304273a71a0fSBarry Smith   PetscScalar *a;
3043637a0070SStefano Zampini   PetscInt     lda, m, n, i, j;
304473a71a0fSBarry Smith 
304573a71a0fSBarry Smith   PetscFunctionBegin;
30469566063dSJacob Faibussowitsch   PetscCall(MatGetSize(x, &m, &n));
30479566063dSJacob Faibussowitsch   PetscCall(MatDenseGetLDA(x, &lda));
30483faff063SStefano Zampini   PetscCall(MatDenseGetArrayWrite(x, &a));
3049637a0070SStefano Zampini   for (j = 0; j < n; j++) {
305048a46eb9SPierre Jolivet     for (i = 0; i < m; i++) PetscCall(PetscRandomGetValue(rctx, a + j * lda + i));
305173a71a0fSBarry Smith   }
30523faff063SStefano Zampini   PetscCall(MatDenseRestoreArrayWrite(x, &a));
30533ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
305473a71a0fSBarry Smith }
305573a71a0fSBarry Smith 
3056d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatMissingDiagonal_SeqDense(Mat A, PetscBool *missing, PetscInt *d)
3057d71ae5a4SJacob Faibussowitsch {
30583b49f96aSBarry Smith   PetscFunctionBegin;
30593b49f96aSBarry Smith   *missing = PETSC_FALSE;
30603ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
30613b49f96aSBarry Smith }
306273a71a0fSBarry Smith 
3063ca15aa20SStefano Zampini /* vals is not const */
3064d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatDenseGetColumn_SeqDense(Mat A, PetscInt col, PetscScalar **vals)
3065d71ae5a4SJacob Faibussowitsch {
306686aefd0dSHong Zhang   Mat_SeqDense *a = (Mat_SeqDense *)A->data;
3067ca15aa20SStefano Zampini   PetscScalar  *v;
306886aefd0dSHong Zhang 
306986aefd0dSHong Zhang   PetscFunctionBegin;
307028b400f6SJacob Faibussowitsch   PetscCheck(!A->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
30719566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArray(A, &v));
3072ca15aa20SStefano Zampini   *vals = v + col * a->lda;
30739566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArray(A, &v));
30743ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
307586aefd0dSHong Zhang }
307686aefd0dSHong Zhang 
3077d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatDenseRestoreColumn_SeqDense(Mat A, PetscScalar **vals)
3078d71ae5a4SJacob Faibussowitsch {
307986aefd0dSHong Zhang   PetscFunctionBegin;
3080742765d3SMatthew Knepley   if (vals) *vals = NULL; /* user cannot accidentally use the array later */
30813ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
308286aefd0dSHong Zhang }
3083abc3b08eSStefano Zampini 
3084a5ae1ecdSBarry Smith static struct _MatOps MatOps_Values = {MatSetValues_SeqDense,
3085905e6a2fSBarry Smith                                        MatGetRow_SeqDense,
3086905e6a2fSBarry Smith                                        MatRestoreRow_SeqDense,
3087905e6a2fSBarry Smith                                        MatMult_SeqDense,
308897304618SKris Buschelman                                        /*  4*/ MatMultAdd_SeqDense,
30897c922b88SBarry Smith                                        MatMultTranspose_SeqDense,
30907c922b88SBarry Smith                                        MatMultTransposeAdd_SeqDense,
3091f4259b30SLisandro Dalcin                                        NULL,
3092f4259b30SLisandro Dalcin                                        NULL,
3093f4259b30SLisandro Dalcin                                        NULL,
3094f4259b30SLisandro Dalcin                                        /* 10*/ NULL,
3095905e6a2fSBarry Smith                                        MatLUFactor_SeqDense,
3096905e6a2fSBarry Smith                                        MatCholeskyFactor_SeqDense,
309741f059aeSBarry Smith                                        MatSOR_SeqDense,
3098ec8511deSBarry Smith                                        MatTranspose_SeqDense,
309997304618SKris Buschelman                                        /* 15*/ MatGetInfo_SeqDense,
3100905e6a2fSBarry Smith                                        MatEqual_SeqDense,
3101905e6a2fSBarry Smith                                        MatGetDiagonal_SeqDense,
3102905e6a2fSBarry Smith                                        MatDiagonalScale_SeqDense,
3103905e6a2fSBarry Smith                                        MatNorm_SeqDense,
3104b7103cf4SPierre Jolivet                                        /* 20*/ NULL,
3105b7103cf4SPierre Jolivet                                        NULL,
3106905e6a2fSBarry Smith                                        MatSetOption_SeqDense,
3107905e6a2fSBarry Smith                                        MatZeroEntries_SeqDense,
3108d519adbfSMatthew Knepley                                        /* 24*/ MatZeroRows_SeqDense,
3109f4259b30SLisandro Dalcin                                        NULL,
3110f4259b30SLisandro Dalcin                                        NULL,
3111f4259b30SLisandro Dalcin                                        NULL,
3112f4259b30SLisandro Dalcin                                        NULL,
31134994cf47SJed Brown                                        /* 29*/ MatSetUp_SeqDense,
3114f4259b30SLisandro Dalcin                                        NULL,
3115f4259b30SLisandro Dalcin                                        NULL,
3116f4259b30SLisandro Dalcin                                        NULL,
3117f4259b30SLisandro Dalcin                                        NULL,
3118d519adbfSMatthew Knepley                                        /* 34*/ MatDuplicate_SeqDense,
3119f4259b30SLisandro Dalcin                                        NULL,
3120f4259b30SLisandro Dalcin                                        NULL,
3121f4259b30SLisandro Dalcin                                        NULL,
3122f4259b30SLisandro Dalcin                                        NULL,
3123d519adbfSMatthew Knepley                                        /* 39*/ MatAXPY_SeqDense,
31247dae84e0SHong Zhang                                        MatCreateSubMatrices_SeqDense,
3125f4259b30SLisandro Dalcin                                        NULL,
31264b0e389bSBarry Smith                                        MatGetValues_SeqDense,
3127a5ae1ecdSBarry Smith                                        MatCopy_SeqDense,
3128d519adbfSMatthew Knepley                                        /* 44*/ MatGetRowMax_SeqDense,
3129a5ae1ecdSBarry Smith                                        MatScale_SeqDense,
31302f605a99SJose E. Roman                                        MatShift_SeqDense,
3131f4259b30SLisandro Dalcin                                        NULL,
31323f49a652SStefano Zampini                                        MatZeroRowsColumns_SeqDense,
313373a71a0fSBarry Smith                                        /* 49*/ MatSetRandom_SeqDense,
3134f4259b30SLisandro Dalcin                                        NULL,
3135f4259b30SLisandro Dalcin                                        NULL,
3136f4259b30SLisandro Dalcin                                        NULL,
3137f4259b30SLisandro Dalcin                                        NULL,
3138f4259b30SLisandro Dalcin                                        /* 54*/ NULL,
3139f4259b30SLisandro Dalcin                                        NULL,
3140f4259b30SLisandro Dalcin                                        NULL,
3141f4259b30SLisandro Dalcin                                        NULL,
3142f4259b30SLisandro Dalcin                                        NULL,
3143023c16fcSToby Isaac                                        /* 59*/ MatCreateSubMatrix_SeqDense,
3144e03a110bSBarry Smith                                        MatDestroy_SeqDense,
3145e03a110bSBarry Smith                                        MatView_SeqDense,
3146f4259b30SLisandro Dalcin                                        NULL,
3147f4259b30SLisandro Dalcin                                        NULL,
3148f4259b30SLisandro Dalcin                                        /* 64*/ NULL,
3149f4259b30SLisandro Dalcin                                        NULL,
3150f4259b30SLisandro Dalcin                                        NULL,
3151f4259b30SLisandro Dalcin                                        NULL,
3152f4259b30SLisandro Dalcin                                        NULL,
3153d519adbfSMatthew Knepley                                        /* 69*/ MatGetRowMaxAbs_SeqDense,
3154f4259b30SLisandro Dalcin                                        NULL,
3155f4259b30SLisandro Dalcin                                        NULL,
3156f4259b30SLisandro Dalcin                                        NULL,
3157f4259b30SLisandro Dalcin                                        NULL,
3158f4259b30SLisandro Dalcin                                        /* 74*/ NULL,
3159f4259b30SLisandro Dalcin                                        NULL,
3160f4259b30SLisandro Dalcin                                        NULL,
3161f4259b30SLisandro Dalcin                                        NULL,
3162f4259b30SLisandro Dalcin                                        NULL,
3163f4259b30SLisandro Dalcin                                        /* 79*/ NULL,
3164f4259b30SLisandro Dalcin                                        NULL,
3165f4259b30SLisandro Dalcin                                        NULL,
3166f4259b30SLisandro Dalcin                                        NULL,
31675bba2384SShri Abhyankar                                        /* 83*/ MatLoad_SeqDense,
3168637a0070SStefano Zampini                                        MatIsSymmetric_SeqDense,
31691cbb95d3SBarry Smith                                        MatIsHermitian_SeqDense,
3170f4259b30SLisandro Dalcin                                        NULL,
3171f4259b30SLisandro Dalcin                                        NULL,
3172f4259b30SLisandro Dalcin                                        NULL,
3173f4259b30SLisandro Dalcin                                        /* 89*/ NULL,
3174f4259b30SLisandro Dalcin                                        NULL,
3175a9fe9ddaSSatish Balay                                        MatMatMultNumeric_SeqDense_SeqDense,
3176f4259b30SLisandro Dalcin                                        NULL,
3177f4259b30SLisandro Dalcin                                        NULL,
3178f4259b30SLisandro Dalcin                                        /* 94*/ NULL,
3179f4259b30SLisandro Dalcin                                        NULL,
3180f4259b30SLisandro Dalcin                                        NULL,
318169f65d41SStefano Zampini                                        MatMatTransposeMultNumeric_SeqDense_SeqDense,
3182f4259b30SLisandro Dalcin                                        NULL,
31834222ddf1SHong Zhang                                        /* 99*/ MatProductSetFromOptions_SeqDense,
3184f4259b30SLisandro Dalcin                                        NULL,
3185f4259b30SLisandro Dalcin                                        NULL,
3186ba337c44SJed Brown                                        MatConjugate_SeqDense,
3187f4259b30SLisandro Dalcin                                        NULL,
3188f4259b30SLisandro Dalcin                                        /*104*/ NULL,
3189ba337c44SJed Brown                                        MatRealPart_SeqDense,
3190ba337c44SJed Brown                                        MatImaginaryPart_SeqDense,
3191f4259b30SLisandro Dalcin                                        NULL,
3192f4259b30SLisandro Dalcin                                        NULL,
3193f4259b30SLisandro Dalcin                                        /*109*/ NULL,
3194f4259b30SLisandro Dalcin                                        NULL,
31958d0534beSBarry Smith                                        MatGetRowMin_SeqDense,
3196aabbc4fbSShri Abhyankar                                        MatGetColumnVector_SeqDense,
31973b49f96aSBarry Smith                                        MatMissingDiagonal_SeqDense,
3198f4259b30SLisandro Dalcin                                        /*114*/ NULL,
3199f4259b30SLisandro Dalcin                                        NULL,
3200f4259b30SLisandro Dalcin                                        NULL,
3201f4259b30SLisandro Dalcin                                        NULL,
3202f4259b30SLisandro Dalcin                                        NULL,
3203f4259b30SLisandro Dalcin                                        /*119*/ NULL,
3204f4259b30SLisandro Dalcin                                        NULL,
3205459e8d23SBlanca Mellado Pinto                                        MatMultHermitianTranspose_SeqDense,
3206459e8d23SBlanca Mellado Pinto                                        MatMultHermitianTransposeAdd_SeqDense,
3207f4259b30SLisandro Dalcin                                        NULL,
3208f4259b30SLisandro Dalcin                                        /*124*/ NULL,
3209a873a8cdSSam Reynolds                                        MatGetColumnReductions_SeqDense,
3210f4259b30SLisandro Dalcin                                        NULL,
3211f4259b30SLisandro Dalcin                                        NULL,
3212f4259b30SLisandro Dalcin                                        NULL,
3213f4259b30SLisandro Dalcin                                        /*129*/ NULL,
3214f4259b30SLisandro Dalcin                                        NULL,
3215f4259b30SLisandro Dalcin                                        NULL,
321675648e8dSHong Zhang                                        MatTransposeMatMultNumeric_SeqDense_SeqDense,
3217f4259b30SLisandro Dalcin                                        NULL,
3218f4259b30SLisandro Dalcin                                        /*134*/ NULL,
3219f4259b30SLisandro Dalcin                                        NULL,
3220f4259b30SLisandro Dalcin                                        NULL,
3221f4259b30SLisandro Dalcin                                        NULL,
3222f4259b30SLisandro Dalcin                                        NULL,
3223f4259b30SLisandro Dalcin                                        /*139*/ NULL,
3224f4259b30SLisandro Dalcin                                        NULL,
3225f4259b30SLisandro Dalcin                                        NULL,
3226f4259b30SLisandro Dalcin                                        NULL,
3227f4259b30SLisandro Dalcin                                        NULL,
32284222ddf1SHong Zhang                                        MatCreateMPIMatConcatenateSeqMat_SeqDense,
3229f4259b30SLisandro Dalcin                                        /*145*/ NULL,
3230f4259b30SLisandro Dalcin                                        NULL,
323199a7f59eSMark Adams                                        NULL,
323299a7f59eSMark Adams                                        NULL,
32337fb60732SBarry Smith                                        NULL,
3234dec0b466SHong Zhang                                        /*150*/ NULL,
3235eede4a3fSMark Adams                                        NULL,
32364cc2b5b5SPierre Jolivet                                        NULL,
323742ce410bSJunchao Zhang                                        NULL,
323842ce410bSJunchao Zhang                                        NULL,
3239fe1fc275SAlexander                                        /*155*/ NULL,
3240dec0b466SHong Zhang                                        NULL};
324190ace30eSBarry Smith 
32425d83a8b1SBarry Smith /*@
324311a5261eSBarry Smith   MatCreateSeqDense - Creates a `MATSEQDENSE` that
3244fb850c59SBarry Smith   is stored in column major order (the usual Fortran format).
3245289bc588SBarry Smith 
3246d083f849SBarry Smith   Collective
3247db81eaa0SLois Curfman McInnes 
324820563c6bSBarry Smith   Input Parameters:
324911a5261eSBarry Smith + comm - MPI communicator, set to `PETSC_COMM_SELF`
32500c775827SLois Curfman McInnes . m    - number of rows
325118f449edSLois Curfman McInnes . n    - number of columns
32522ef1f0ffSBarry Smith - data - optional location of matrix data in column major order.  Use `NULL` for PETSc
3253dfc5480cSLois Curfman McInnes          to control all matrix memory allocation.
325420563c6bSBarry Smith 
325520563c6bSBarry Smith   Output Parameter:
325644cd7ae7SLois Curfman McInnes . A - the matrix
325720563c6bSBarry Smith 
32582ef1f0ffSBarry Smith   Level: intermediate
32592ef1f0ffSBarry Smith 
326011a5261eSBarry Smith   Note:
326118f449edSLois Curfman McInnes   The data input variable is intended primarily for Fortran programmers
326218f449edSLois Curfman McInnes   who wish to allocate their own matrix memory space.  Most users should
32632ef1f0ffSBarry Smith   set `data` = `NULL`.
326418f449edSLois Curfman McInnes 
3265fb850c59SBarry Smith   Developer Note:
3266fb850c59SBarry Smith   Many of the matrix operations for this variant use the BLAS and LAPACK routines.
3267fb850c59SBarry Smith 
32681cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATSEQDENSE`, `MatCreate()`, `MatCreateDense()`, `MatSetValues()`
326920563c6bSBarry Smith @*/
32705d83a8b1SBarry Smith PetscErrorCode MatCreateSeqDense(MPI_Comm comm, PetscInt m, PetscInt n, PetscScalar data[], Mat *A)
3271d71ae5a4SJacob Faibussowitsch {
32723a40ed3dSBarry Smith   PetscFunctionBegin;
32739566063dSJacob Faibussowitsch   PetscCall(MatCreate(comm, A));
32749566063dSJacob Faibussowitsch   PetscCall(MatSetSizes(*A, m, n, m, n));
32759566063dSJacob Faibussowitsch   PetscCall(MatSetType(*A, MATSEQDENSE));
32769566063dSJacob Faibussowitsch   PetscCall(MatSeqDenseSetPreallocation(*A, data));
32773ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3278273d9f13SBarry Smith }
3279273d9f13SBarry Smith 
32805d83a8b1SBarry Smith /*@
328111a5261eSBarry Smith   MatSeqDenseSetPreallocation - Sets the array used for storing the matrix elements of a `MATSEQDENSE` matrix
3282273d9f13SBarry Smith 
3283d083f849SBarry Smith   Collective
3284273d9f13SBarry Smith 
3285273d9f13SBarry Smith   Input Parameters:
32861c4f3114SJed Brown + B    - the matrix
32872ef1f0ffSBarry Smith - data - the array (or `NULL`)
32882ef1f0ffSBarry Smith 
32892ef1f0ffSBarry Smith   Level: intermediate
3290273d9f13SBarry Smith 
329111a5261eSBarry Smith   Note:
3292273d9f13SBarry Smith   The data input variable is intended primarily for Fortran programmers
3293273d9f13SBarry Smith   who wish to allocate their own matrix memory space.  Most users should
3294284134d9SBarry Smith   need not call this routine.
3295273d9f13SBarry Smith 
32961cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATSEQDENSE`, `MatCreate()`, `MatCreateDense()`, `MatSetValues()`, `MatDenseSetLDA()`
3297273d9f13SBarry Smith @*/
3298d71ae5a4SJacob Faibussowitsch PetscErrorCode MatSeqDenseSetPreallocation(Mat B, PetscScalar data[])
3299d71ae5a4SJacob Faibussowitsch {
3300a23d5eceSKris Buschelman   PetscFunctionBegin;
3301d5ea218eSStefano Zampini   PetscValidHeaderSpecific(B, MAT_CLASSID, 1);
3302cac4c232SBarry Smith   PetscTryMethod(B, "MatSeqDenseSetPreallocation_C", (Mat, PetscScalar[]), (B, data));
33033ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3304a23d5eceSKris Buschelman }
3305a23d5eceSKris Buschelman 
3306d71ae5a4SJacob Faibussowitsch PetscErrorCode MatSeqDenseSetPreallocation_SeqDense(Mat B, PetscScalar *data)
3307d71ae5a4SJacob Faibussowitsch {
3308ad16ce7aSStefano Zampini   Mat_SeqDense *b = (Mat_SeqDense *)B->data;
3309273d9f13SBarry Smith 
3310273d9f13SBarry Smith   PetscFunctionBegin;
331128b400f6SJacob Faibussowitsch   PetscCheck(!b->matinuse, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Need to call MatDenseRestoreSubMatrix() first");
3312273d9f13SBarry Smith   B->preallocated = PETSC_TRUE;
3313a868139aSShri Abhyankar 
33149566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetUp(B->rmap));
33159566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetUp(B->cmap));
331634ef9618SShri Abhyankar 
33176497c311SBarry Smith   if (b->lda <= 0) PetscCall(PetscBLASIntCast(B->rmap->n, &b->lda));
331886d161a7SShri Abhyankar 
33199e8f95c4SLisandro Dalcin   if (!data) { /* petsc-allocated storage */
33209566063dSJacob Faibussowitsch     if (!b->user_alloc) PetscCall(PetscFree(b->v));
33219566063dSJacob Faibussowitsch     PetscCall(PetscCalloc1((size_t)b->lda * B->cmap->n, &b->v));
33222205254eSKarl Rupp 
33239e8f95c4SLisandro Dalcin     b->user_alloc = PETSC_FALSE;
3324273d9f13SBarry Smith   } else { /* user-allocated storage */
33259566063dSJacob Faibussowitsch     if (!b->user_alloc) PetscCall(PetscFree(b->v));
3326273d9f13SBarry Smith     b->v          = data;
3327273d9f13SBarry Smith     b->user_alloc = PETSC_TRUE;
3328273d9f13SBarry Smith   }
33290450473dSBarry Smith   B->assembled = PETSC_TRUE;
33303ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3331273d9f13SBarry Smith }
3332273d9f13SBarry Smith 
333365b80a83SHong Zhang #if defined(PETSC_HAVE_ELEMENTAL)
3334d71ae5a4SJacob Faibussowitsch PETSC_INTERN PetscErrorCode MatConvert_SeqDense_Elemental(Mat A, MatType newtype, MatReuse reuse, Mat *newmat)
3335d71ae5a4SJacob Faibussowitsch {
3336d77f618aSHong Zhang   Mat                mat_elemental;
33371683a169SBarry Smith   const PetscScalar *array;
33381683a169SBarry Smith   PetscScalar       *v_colwise;
3339d77f618aSHong Zhang   PetscInt           M = A->rmap->N, N = A->cmap->N, i, j, k, *rows, *cols;
3340d77f618aSHong Zhang 
33418baccfbdSHong Zhang   PetscFunctionBegin;
33429566063dSJacob Faibussowitsch   PetscCall(PetscMalloc3(M * N, &v_colwise, M, &rows, N, &cols));
33439566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArrayRead(A, &array));
3344d77f618aSHong Zhang   /* convert column-wise array into row-wise v_colwise, see MatSetValues_Elemental() */
3345d77f618aSHong Zhang   k = 0;
3346d77f618aSHong Zhang   for (j = 0; j < N; j++) {
3347d77f618aSHong Zhang     cols[j] = j;
3348ad540459SPierre Jolivet     for (i = 0; i < M; i++) v_colwise[j * M + i] = array[k++];
3349d77f618aSHong Zhang   }
3350ad540459SPierre Jolivet   for (i = 0; i < M; i++) rows[i] = i;
33519566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArrayRead(A, &array));
3352d77f618aSHong Zhang 
33539566063dSJacob Faibussowitsch   PetscCall(MatCreate(PetscObjectComm((PetscObject)A), &mat_elemental));
33549566063dSJacob Faibussowitsch   PetscCall(MatSetSizes(mat_elemental, PETSC_DECIDE, PETSC_DECIDE, M, N));
33559566063dSJacob Faibussowitsch   PetscCall(MatSetType(mat_elemental, MATELEMENTAL));
33569566063dSJacob Faibussowitsch   PetscCall(MatSetUp(mat_elemental));
3357d77f618aSHong Zhang 
3358d77f618aSHong Zhang   /* PETSc-Elemental interaface uses axpy for setting off-processor entries, only ADD_VALUES is allowed */
33599566063dSJacob Faibussowitsch   PetscCall(MatSetValues(mat_elemental, M, rows, N, cols, v_colwise, ADD_VALUES));
33609566063dSJacob Faibussowitsch   PetscCall(MatAssemblyBegin(mat_elemental, MAT_FINAL_ASSEMBLY));
33619566063dSJacob Faibussowitsch   PetscCall(MatAssemblyEnd(mat_elemental, MAT_FINAL_ASSEMBLY));
33629566063dSJacob Faibussowitsch   PetscCall(PetscFree3(v_colwise, rows, cols));
3363d77f618aSHong Zhang 
3364511c6705SHong Zhang   if (reuse == MAT_INPLACE_MATRIX) {
33659566063dSJacob Faibussowitsch     PetscCall(MatHeaderReplace(A, &mat_elemental));
3366d77f618aSHong Zhang   } else {
3367d77f618aSHong Zhang     *newmat = mat_elemental;
3368d77f618aSHong Zhang   }
33693ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
33708baccfbdSHong Zhang }
337165b80a83SHong Zhang #endif
33728baccfbdSHong Zhang 
3373d71ae5a4SJacob Faibussowitsch PetscErrorCode MatDenseSetLDA_SeqDense(Mat B, PetscInt lda)
3374d71ae5a4SJacob Faibussowitsch {
33751b807ce4Svictorle   Mat_SeqDense *b = (Mat_SeqDense *)B->data;
33767422da62SJose E. Roman   PetscBool     data;
337721a2c019SBarry Smith 
33781b807ce4Svictorle   PetscFunctionBegin;
3379835f2295SStefano Zampini   data = (B->rmap->n > 0 && B->cmap->n > 0) ? (b->v ? PETSC_TRUE : PETSC_FALSE) : PETSC_FALSE;
3380aed4548fSBarry Smith   PetscCheck(b->user_alloc || !data || b->lda == lda, PETSC_COMM_SELF, PETSC_ERR_ORDER, "LDA cannot be changed after allocation of internal storage");
338108401ef6SPierre 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);
33826497c311SBarry Smith   PetscCall(PetscBLASIntCast(lda, &b->lda));
33833ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
33841b807ce4Svictorle }
33851b807ce4Svictorle 
3386d71ae5a4SJacob Faibussowitsch PetscErrorCode MatCreateMPIMatConcatenateSeqMat_SeqDense(MPI_Comm comm, Mat inmat, PetscInt n, MatReuse scall, Mat *outmat)
3387d71ae5a4SJacob Faibussowitsch {
3388d528f656SJakub Kruzik   PetscFunctionBegin;
33899566063dSJacob Faibussowitsch   PetscCall(MatCreateMPIMatConcatenateSeqMat_MPIDense(comm, inmat, n, scall, outmat));
33903ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3391d528f656SJakub Kruzik }
3392d528f656SJakub Kruzik 
3393d16ceb75SStefano Zampini PetscErrorCode MatDenseCreateColumnVec_Private(Mat A, Vec *v)
3394d16ceb75SStefano Zampini {
3395d16ceb75SStefano Zampini   PetscBool   isstd, iskok, iscuda, iship;
3396d16ceb75SStefano Zampini   PetscMPIInt size;
3397d16ceb75SStefano Zampini #if PetscDefined(HAVE_CUDA) || PetscDefined(HAVE_HIP)
3398d16ceb75SStefano Zampini   /* we pass the data of A, to prevent allocating needless GPU memory the first time VecCUPMPlaceArray is called. */
3399d16ceb75SStefano Zampini   const PetscScalar *a;
3400d16ceb75SStefano Zampini #endif
3401d16ceb75SStefano Zampini 
3402d16ceb75SStefano Zampini   PetscFunctionBegin;
3403d16ceb75SStefano Zampini   *v = NULL;
3404d16ceb75SStefano Zampini   PetscCall(PetscStrcmpAny(A->defaultvectype, &isstd, VECSTANDARD, VECSEQ, VECMPI, ""));
3405d16ceb75SStefano Zampini   PetscCall(PetscStrcmpAny(A->defaultvectype, &iskok, VECKOKKOS, VECSEQKOKKOS, VECMPIKOKKOS, ""));
3406d16ceb75SStefano Zampini   PetscCall(PetscStrcmpAny(A->defaultvectype, &iscuda, VECCUDA, VECSEQCUDA, VECMPICUDA, ""));
3407d16ceb75SStefano Zampini   PetscCall(PetscStrcmpAny(A->defaultvectype, &iship, VECHIP, VECSEQHIP, VECMPIHIP, ""));
3408d16ceb75SStefano Zampini   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)A), &size));
3409d16ceb75SStefano Zampini   if (isstd) {
3410d16ceb75SStefano Zampini     if (size > 1) PetscCall(VecCreateMPIWithArray(PetscObjectComm((PetscObject)A), A->rmap->bs, A->rmap->n, A->rmap->N, NULL, v));
3411d16ceb75SStefano Zampini     else PetscCall(VecCreateSeqWithArray(PetscObjectComm((PetscObject)A), A->rmap->bs, A->rmap->n, NULL, v));
3412d16ceb75SStefano Zampini   } else if (iskok) {
3413d16ceb75SStefano Zampini     PetscCheck(PetscDefined(HAVE_KOKKOS_KERNELS), PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Reconfigure using KOKKOS kernels support");
3414d16ceb75SStefano Zampini #if PetscDefined(HAVE_KOKKOS_KERNELS)
3415d16ceb75SStefano Zampini     if (size > 1) PetscCall(VecCreateMPIKokkosWithArray(PetscObjectComm((PetscObject)A), A->rmap->bs, A->rmap->n, A->rmap->N, NULL, v));
3416d16ceb75SStefano Zampini     else PetscCall(VecCreateSeqKokkosWithArray(PetscObjectComm((PetscObject)A), A->rmap->bs, A->rmap->n, NULL, v));
3417d16ceb75SStefano Zampini #endif
3418d16ceb75SStefano Zampini   } else if (iscuda) {
3419d16ceb75SStefano Zampini     PetscCheck(PetscDefined(HAVE_CUDA), PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Reconfigure using CUDA support");
3420d16ceb75SStefano Zampini #if PetscDefined(HAVE_CUDA)
3421d16ceb75SStefano Zampini     PetscCall(MatDenseCUDAGetArrayRead(A, &a));
3422d16ceb75SStefano Zampini     if (size > 1) PetscCall(VecCreateMPICUDAWithArrays(PetscObjectComm((PetscObject)A), A->rmap->bs, A->rmap->n, A->rmap->N, NULL, a, v));
3423d16ceb75SStefano Zampini     else PetscCall(VecCreateSeqCUDAWithArrays(PetscObjectComm((PetscObject)A), A->rmap->bs, A->rmap->n, NULL, a, v));
3424d16ceb75SStefano Zampini #endif
3425d16ceb75SStefano Zampini   } else if (iship) {
3426d16ceb75SStefano Zampini     PetscCheck(PetscDefined(HAVE_HIP), PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Reconfigure using HIP support");
3427d16ceb75SStefano Zampini #if PetscDefined(HAVE_HIP)
3428d16ceb75SStefano Zampini     PetscCall(MatDenseHIPGetArrayRead(A, &a));
3429d16ceb75SStefano Zampini     if (size > 1) PetscCall(VecCreateMPIHIPWithArrays(PetscObjectComm((PetscObject)A), A->rmap->bs, A->rmap->n, A->rmap->N, NULL, a, v));
3430d16ceb75SStefano Zampini     else PetscCall(VecCreateSeqHIPWithArrays(PetscObjectComm((PetscObject)A), A->rmap->bs, A->rmap->n, NULL, a, v));
3431d16ceb75SStefano Zampini #endif
3432d16ceb75SStefano Zampini   }
3433d16ceb75SStefano Zampini   PetscCheck(*v, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Not coded for type %s", A->defaultvectype);
3434d16ceb75SStefano Zampini   PetscFunctionReturn(PETSC_SUCCESS);
3435d16ceb75SStefano Zampini }
3436d16ceb75SStefano Zampini 
3437d71ae5a4SJacob Faibussowitsch PetscErrorCode MatDenseGetColumnVec_SeqDense(Mat A, PetscInt col, Vec *v)
3438d71ae5a4SJacob Faibussowitsch {
34396947451fSStefano Zampini   Mat_SeqDense *a = (Mat_SeqDense *)A->data;
34406947451fSStefano Zampini 
34416947451fSStefano Zampini   PetscFunctionBegin;
344228b400f6SJacob Faibussowitsch   PetscCheck(!a->vecinuse, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Need to call MatDenseRestoreColumnVec() first");
344328b400f6SJacob Faibussowitsch   PetscCheck(!a->matinuse, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Need to call MatDenseRestoreSubMatrix() first");
3444d16ceb75SStefano Zampini   if (!a->cvec) PetscCall(MatDenseCreateColumnVec_Private(A, &a->cvec));
34456947451fSStefano Zampini   a->vecinuse = col + 1;
34469566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArray(A, (PetscScalar **)&a->ptrinuse));
34479566063dSJacob Faibussowitsch   PetscCall(VecPlaceArray(a->cvec, a->ptrinuse + (size_t)col * (size_t)a->lda));
34486947451fSStefano Zampini   *v = a->cvec;
34493ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
34506947451fSStefano Zampini }
34516947451fSStefano Zampini 
3452d71ae5a4SJacob Faibussowitsch PetscErrorCode MatDenseRestoreColumnVec_SeqDense(Mat A, PetscInt col, Vec *v)
3453d71ae5a4SJacob Faibussowitsch {
34546947451fSStefano Zampini   Mat_SeqDense *a = (Mat_SeqDense *)A->data;
34556947451fSStefano Zampini 
34566947451fSStefano Zampini   PetscFunctionBegin;
345728b400f6SJacob Faibussowitsch   PetscCheck(a->vecinuse, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Need to call MatDenseGetColumnVec() first");
345828b400f6SJacob Faibussowitsch   PetscCheck(a->cvec, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Missing internal column vector");
34594186a4bbSPierre Jolivet   VecCheckAssembled(a->cvec);
34606947451fSStefano Zampini   a->vecinuse = 0;
34619566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArray(A, (PetscScalar **)&a->ptrinuse));
34629566063dSJacob Faibussowitsch   PetscCall(VecResetArray(a->cvec));
346375f6d85dSStefano Zampini   if (v) *v = NULL;
34643ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
34656947451fSStefano Zampini }
34666947451fSStefano Zampini 
3467d71ae5a4SJacob Faibussowitsch PetscErrorCode MatDenseGetColumnVecRead_SeqDense(Mat A, PetscInt col, Vec *v)
3468d71ae5a4SJacob Faibussowitsch {
34696947451fSStefano Zampini   Mat_SeqDense *a = (Mat_SeqDense *)A->data;
34706947451fSStefano Zampini 
34716947451fSStefano Zampini   PetscFunctionBegin;
347228b400f6SJacob Faibussowitsch   PetscCheck(!a->vecinuse, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Need to call MatDenseRestoreColumnVec() first");
347328b400f6SJacob Faibussowitsch   PetscCheck(!a->matinuse, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Need to call MatDenseRestoreSubMatrix() first");
3474d16ceb75SStefano Zampini   if (!a->cvec) PetscCall(MatDenseCreateColumnVec_Private(A, &a->cvec));
34756947451fSStefano Zampini   a->vecinuse = col + 1;
34769566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArrayRead(A, &a->ptrinuse));
34778e3a54c0SPierre Jolivet   PetscCall(VecPlaceArray(a->cvec, PetscSafePointerPlusOffset(a->ptrinuse, (size_t)col * (size_t)a->lda)));
34789566063dSJacob Faibussowitsch   PetscCall(VecLockReadPush(a->cvec));
34796947451fSStefano Zampini   *v = a->cvec;
34803ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
34816947451fSStefano Zampini }
34826947451fSStefano Zampini 
3483d71ae5a4SJacob Faibussowitsch PetscErrorCode MatDenseRestoreColumnVecRead_SeqDense(Mat A, PetscInt col, Vec *v)
3484d71ae5a4SJacob Faibussowitsch {
34856947451fSStefano Zampini   Mat_SeqDense *a = (Mat_SeqDense *)A->data;
34866947451fSStefano Zampini 
34876947451fSStefano Zampini   PetscFunctionBegin;
348828b400f6SJacob Faibussowitsch   PetscCheck(a->vecinuse, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Need to call MatDenseGetColumnVec() first");
348928b400f6SJacob Faibussowitsch   PetscCheck(a->cvec, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Missing internal column vector");
34904186a4bbSPierre Jolivet   VecCheckAssembled(a->cvec);
34916947451fSStefano Zampini   a->vecinuse = 0;
34929566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArrayRead(A, &a->ptrinuse));
34939566063dSJacob Faibussowitsch   PetscCall(VecLockReadPop(a->cvec));
34949566063dSJacob Faibussowitsch   PetscCall(VecResetArray(a->cvec));
349575f6d85dSStefano Zampini   if (v) *v = NULL;
34963ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
34976947451fSStefano Zampini }
34986947451fSStefano Zampini 
3499d71ae5a4SJacob Faibussowitsch PetscErrorCode MatDenseGetColumnVecWrite_SeqDense(Mat A, PetscInt col, Vec *v)
3500d71ae5a4SJacob Faibussowitsch {
35016947451fSStefano Zampini   Mat_SeqDense *a = (Mat_SeqDense *)A->data;
35026947451fSStefano Zampini 
35036947451fSStefano Zampini   PetscFunctionBegin;
350428b400f6SJacob Faibussowitsch   PetscCheck(!a->vecinuse, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Need to call MatDenseRestoreColumnVec() first");
350528b400f6SJacob Faibussowitsch   PetscCheck(!a->matinuse, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Need to call MatDenseRestoreSubMatrix() first");
3506d16ceb75SStefano Zampini   if (!a->cvec) PetscCall(MatDenseCreateColumnVec_Private(A, &a->cvec));
35076947451fSStefano Zampini   a->vecinuse = col + 1;
35089566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArrayWrite(A, (PetscScalar **)&a->ptrinuse));
35098e3a54c0SPierre Jolivet   PetscCall(VecPlaceArray(a->cvec, PetscSafePointerPlusOffset(a->ptrinuse, (size_t)col * (size_t)a->lda)));
35106947451fSStefano Zampini   *v = a->cvec;
35113ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
35126947451fSStefano Zampini }
35136947451fSStefano Zampini 
3514d71ae5a4SJacob Faibussowitsch PetscErrorCode MatDenseRestoreColumnVecWrite_SeqDense(Mat A, PetscInt col, Vec *v)
3515d71ae5a4SJacob Faibussowitsch {
35166947451fSStefano Zampini   Mat_SeqDense *a = (Mat_SeqDense *)A->data;
35176947451fSStefano Zampini 
35186947451fSStefano Zampini   PetscFunctionBegin;
351928b400f6SJacob Faibussowitsch   PetscCheck(a->vecinuse, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Need to call MatDenseGetColumnVec() first");
352028b400f6SJacob Faibussowitsch   PetscCheck(a->cvec, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Missing internal column vector");
35214186a4bbSPierre Jolivet   VecCheckAssembled(a->cvec);
35226947451fSStefano Zampini   a->vecinuse = 0;
35239566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArrayWrite(A, (PetscScalar **)&a->ptrinuse));
35249566063dSJacob Faibussowitsch   PetscCall(VecResetArray(a->cvec));
352575f6d85dSStefano Zampini   if (v) *v = NULL;
35263ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
35276947451fSStefano Zampini }
35286947451fSStefano Zampini 
3529d71ae5a4SJacob Faibussowitsch PetscErrorCode MatDenseGetSubMatrix_SeqDense(Mat A, PetscInt rbegin, PetscInt rend, PetscInt cbegin, PetscInt cend, Mat *v)
3530d71ae5a4SJacob Faibussowitsch {
35315ea7661aSPierre Jolivet   Mat_SeqDense *a = (Mat_SeqDense *)A->data;
35325ea7661aSPierre Jolivet 
35335ea7661aSPierre Jolivet   PetscFunctionBegin;
353428b400f6SJacob Faibussowitsch   PetscCheck(!a->vecinuse, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Need to call MatDenseRestoreColumnVec() first");
353528b400f6SJacob Faibussowitsch   PetscCheck(!a->matinuse, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Need to call MatDenseRestoreSubMatrix() first");
3536a2748737SPierre Jolivet   if (a->cmat && (cend - cbegin != a->cmat->cmap->N || rend - rbegin != a->cmat->rmap->N)) PetscCall(MatDestroy(&a->cmat));
35375ea7661aSPierre Jolivet   if (!a->cmat) {
35388e3a54c0SPierre 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));
35395ea7661aSPierre Jolivet   } else {
35408e3a54c0SPierre Jolivet     PetscCall(MatDensePlaceArray(a->cmat, PetscSafePointerPlusOffset(a->v, rbegin + (size_t)cbegin * a->lda)));
35415ea7661aSPierre Jolivet   }
35429566063dSJacob Faibussowitsch   PetscCall(MatDenseSetLDA(a->cmat, a->lda));
35435ea7661aSPierre Jolivet   a->matinuse = cbegin + 1;
35445ea7661aSPierre Jolivet   *v          = a->cmat;
354547d993e7Ssuyashtn #if defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
354675f6d85dSStefano Zampini   A->offloadmask = PETSC_OFFLOAD_CPU;
354775f6d85dSStefano Zampini #endif
35483ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
35495ea7661aSPierre Jolivet }
35505ea7661aSPierre Jolivet 
3551d71ae5a4SJacob Faibussowitsch PetscErrorCode MatDenseRestoreSubMatrix_SeqDense(Mat A, Mat *v)
3552d71ae5a4SJacob Faibussowitsch {
35535ea7661aSPierre Jolivet   Mat_SeqDense *a = (Mat_SeqDense *)A->data;
35545ea7661aSPierre Jolivet 
35555ea7661aSPierre Jolivet   PetscFunctionBegin;
355628b400f6SJacob Faibussowitsch   PetscCheck(a->matinuse, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Need to call MatDenseGetSubMatrix() first");
355728b400f6SJacob Faibussowitsch   PetscCheck(a->cmat, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Missing internal column matrix");
355808401ef6SPierre Jolivet   PetscCheck(*v == a->cmat, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Not the matrix obtained from MatDenseGetSubMatrix()");
35595ea7661aSPierre Jolivet   a->matinuse = 0;
35609566063dSJacob Faibussowitsch   PetscCall(MatDenseResetArray(a->cmat));
3561742765d3SMatthew Knepley   if (v) *v = NULL;
356247d993e7Ssuyashtn #if defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
35633faff063SStefano Zampini   A->offloadmask = PETSC_OFFLOAD_CPU;
35643faff063SStefano Zampini #endif
35653ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
35665ea7661aSPierre Jolivet }
35675ea7661aSPierre Jolivet 
35680bad9183SKris Buschelman /*MC
3569fafad747SKris Buschelman    MATSEQDENSE - MATSEQDENSE = "seqdense" - A matrix type to be used for sequential dense matrices.
35700bad9183SKris Buschelman 
35712ef1f0ffSBarry Smith    Options Database Key:
357211a5261eSBarry Smith . -mat_type seqdense - sets the matrix type to `MATSEQDENSE` during a call to `MatSetFromOptions()`
35730bad9183SKris Buschelman 
35740bad9183SKris Buschelman   Level: beginner
35750bad9183SKris Buschelman 
35761cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATSEQDENSE`, `MatCreateSeqDense()`
35770bad9183SKris Buschelman M*/
3578d71ae5a4SJacob Faibussowitsch PetscErrorCode MatCreate_SeqDense(Mat B)
3579d71ae5a4SJacob Faibussowitsch {
3580273d9f13SBarry Smith   Mat_SeqDense *b;
35817c334f02SBarry Smith   PetscMPIInt   size;
3582273d9f13SBarry Smith 
3583273d9f13SBarry Smith   PetscFunctionBegin;
35849566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)B), &size));
358508401ef6SPierre Jolivet   PetscCheck(size <= 1, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Comm must be of size 1");
358655659b69SBarry Smith 
35874dfa11a4SJacob Faibussowitsch   PetscCall(PetscNew(&b));
358844cd7ae7SLois Curfman McInnes   B->data   = (void *)b;
3589aea10558SJacob Faibussowitsch   B->ops[0] = MatOps_Values;
359018f449edSLois Curfman McInnes 
3591273d9f13SBarry Smith   b->roworiented = PETSC_TRUE;
35924e220ebcSLois Curfman McInnes 
35939566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatQRFactor_C", MatQRFactor_SeqDense));
35949566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatDenseGetLDA_C", MatDenseGetLDA_SeqDense));
35959566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatDenseSetLDA_C", MatDenseSetLDA_SeqDense));
35969566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatDenseGetArray_C", MatDenseGetArray_SeqDense));
35979566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatDenseRestoreArray_C", MatDenseRestoreArray_SeqDense));
35989566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatDensePlaceArray_C", MatDensePlaceArray_SeqDense));
35999566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatDenseResetArray_C", MatDenseResetArray_SeqDense));
36009566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatDenseReplaceArray_C", MatDenseReplaceArray_SeqDense));
36019566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatDenseGetArrayRead_C", MatDenseGetArray_SeqDense));
36029566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatDenseRestoreArrayRead_C", MatDenseRestoreArray_SeqDense));
36039566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatDenseGetArrayWrite_C", MatDenseGetArray_SeqDense));
36049566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatDenseRestoreArrayWrite_C", MatDenseRestoreArray_SeqDense));
36059566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatConvert_seqdense_seqaij_C", MatConvert_SeqDense_SeqAIJ));
36068baccfbdSHong Zhang #if defined(PETSC_HAVE_ELEMENTAL)
36079566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatConvert_seqdense_elemental_C", MatConvert_SeqDense_Elemental));
36088baccfbdSHong Zhang #endif
3609d24d4204SJose E. Roman #if defined(PETSC_HAVE_SCALAPACK)
36109566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatConvert_seqdense_scalapack_C", MatConvert_Dense_ScaLAPACK));
3611d24d4204SJose E. Roman #endif
36122bf066beSStefano Zampini #if defined(PETSC_HAVE_CUDA)
36139566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatConvert_seqdense_seqdensecuda_C", MatConvert_SeqDense_SeqDenseCUDA));
36149566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatProductSetFromOptions_seqdensecuda_seqdensecuda_C", MatProductSetFromOptions_SeqDense));
36159566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatProductSetFromOptions_seqdensecuda_seqdense_C", MatProductSetFromOptions_SeqDense));
36169566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatProductSetFromOptions_seqdense_seqdensecuda_C", MatProductSetFromOptions_SeqDense));
36172bf066beSStefano Zampini #endif
361847d993e7Ssuyashtn #if defined(PETSC_HAVE_HIP)
361947d993e7Ssuyashtn   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatConvert_seqdense_seqdensehip_C", MatConvert_SeqDense_SeqDenseHIP));
362047d993e7Ssuyashtn   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatProductSetFromOptions_seqdensehip_seqdensehip_C", MatProductSetFromOptions_SeqDense));
362147d993e7Ssuyashtn   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatProductSetFromOptions_seqdensehip_seqdense_C", MatProductSetFromOptions_SeqDense));
362247d993e7Ssuyashtn   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatProductSetFromOptions_seqdense_seqdensehip_C", MatProductSetFromOptions_SeqDense));
362347d993e7Ssuyashtn #endif
36249566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatSeqDenseSetPreallocation_C", MatSeqDenseSetPreallocation_SeqDense));
36259566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatProductSetFromOptions_seqaij_seqdense_C", MatProductSetFromOptions_SeqAIJ_SeqDense));
36269566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatProductSetFromOptions_seqdense_seqdense_C", MatProductSetFromOptions_SeqDense));
36279566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatProductSetFromOptions_seqbaij_seqdense_C", MatProductSetFromOptions_SeqXBAIJ_SeqDense));
36289566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatProductSetFromOptions_seqsbaij_seqdense_C", MatProductSetFromOptions_SeqXBAIJ_SeqDense));
362996e6d5c4SRichard Tran Mills 
36309566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatDenseGetColumn_C", MatDenseGetColumn_SeqDense));
36319566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatDenseRestoreColumn_C", MatDenseRestoreColumn_SeqDense));
36329566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatDenseGetColumnVec_C", MatDenseGetColumnVec_SeqDense));
36339566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatDenseRestoreColumnVec_C", MatDenseRestoreColumnVec_SeqDense));
36349566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatDenseGetColumnVecRead_C", MatDenseGetColumnVecRead_SeqDense));
36359566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatDenseRestoreColumnVecRead_C", MatDenseRestoreColumnVecRead_SeqDense));
36369566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatDenseGetColumnVecWrite_C", MatDenseGetColumnVecWrite_SeqDense));
36379566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatDenseRestoreColumnVecWrite_C", MatDenseRestoreColumnVecWrite_SeqDense));
36389566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatDenseGetSubMatrix_C", MatDenseGetSubMatrix_SeqDense));
36399566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatDenseRestoreSubMatrix_C", MatDenseRestoreSubMatrix_SeqDense));
36400be0d8bdSHansol Suh   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatMultAddColumnRange_C", MatMultAddColumnRange_SeqDense));
36410be0d8bdSHansol Suh   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatMultHermitianTransposeColumnRange_C", MatMultHermitianTransposeColumnRange_SeqDense));
36420be0d8bdSHansol Suh   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatMultHermitianTransposeAddColumnRange_C", MatMultHermitianTransposeAddColumnRange_SeqDense));
36439566063dSJacob Faibussowitsch   PetscCall(PetscObjectChangeTypeName((PetscObject)B, MATSEQDENSE));
36443ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3645289bc588SBarry Smith }
364686aefd0dSHong Zhang 
364786aefd0dSHong Zhang /*@C
364811a5261eSBarry 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.
364986aefd0dSHong Zhang 
365086aefd0dSHong Zhang   Not Collective
365186aefd0dSHong Zhang 
36525ea7661aSPierre Jolivet   Input Parameters:
3653fe59aa6dSJacob Faibussowitsch + A   - a `MATSEQDENSE` or `MATMPIDENSE` matrix
365486aefd0dSHong Zhang - col - column index
365586aefd0dSHong Zhang 
365686aefd0dSHong Zhang   Output Parameter:
365786aefd0dSHong Zhang . vals - pointer to the data
365886aefd0dSHong Zhang 
365986aefd0dSHong Zhang   Level: intermediate
366086aefd0dSHong Zhang 
366111a5261eSBarry Smith   Note:
366211a5261eSBarry Smith   Use `MatDenseGetColumnVec()` to get access to a column of a `MATDENSE` treated as a `Vec`
366311a5261eSBarry Smith 
36641cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATDENSE`, `MatDenseRestoreColumn()`, `MatDenseGetColumnVec()`
366586aefd0dSHong Zhang @*/
36665d83a8b1SBarry Smith PetscErrorCode MatDenseGetColumn(Mat A, PetscInt col, PetscScalar *vals[])
3667d71ae5a4SJacob Faibussowitsch {
366886aefd0dSHong Zhang   PetscFunctionBegin;
3669d5ea218eSStefano Zampini   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
3670d5ea218eSStefano Zampini   PetscValidLogicalCollectiveInt(A, col, 2);
36714f572ea9SToby Isaac   PetscAssertPointer(vals, 3);
3672cac4c232SBarry Smith   PetscUseMethod(A, "MatDenseGetColumn_C", (Mat, PetscInt, PetscScalar **), (A, col, vals));
36733ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
367486aefd0dSHong Zhang }
367586aefd0dSHong Zhang 
367686aefd0dSHong Zhang /*@C
367711a5261eSBarry Smith   MatDenseRestoreColumn - returns access to a column of a `MATDENSE` matrix which is returned by `MatDenseGetColumn()`.
367886aefd0dSHong Zhang 
367986aefd0dSHong Zhang   Not Collective
368086aefd0dSHong Zhang 
3681742765d3SMatthew Knepley   Input Parameters:
3682fe59aa6dSJacob Faibussowitsch + A    - a `MATSEQDENSE` or `MATMPIDENSE` matrix
36832ef1f0ffSBarry Smith - vals - pointer to the data (may be `NULL`)
368486aefd0dSHong Zhang 
368586aefd0dSHong Zhang   Level: intermediate
368686aefd0dSHong Zhang 
36871cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATDENSE`, `MatDenseGetColumn()`
368886aefd0dSHong Zhang @*/
36895d83a8b1SBarry Smith PetscErrorCode MatDenseRestoreColumn(Mat A, PetscScalar *vals[])
3690d71ae5a4SJacob Faibussowitsch {
369186aefd0dSHong Zhang   PetscFunctionBegin;
3692d5ea218eSStefano Zampini   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
36934f572ea9SToby Isaac   PetscAssertPointer(vals, 2);
3694cac4c232SBarry Smith   PetscUseMethod(A, "MatDenseRestoreColumn_C", (Mat, PetscScalar **), (A, vals));
36953ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
369686aefd0dSHong Zhang }
36976947451fSStefano Zampini 
36980f74d2c1SSatish Balay /*@
369911a5261eSBarry Smith   MatDenseGetColumnVec - Gives read-write access to a column of a `MATDENSE` matrix, represented as a `Vec`.
37006947451fSStefano Zampini 
37016947451fSStefano Zampini   Collective
37026947451fSStefano Zampini 
37035ea7661aSPierre Jolivet   Input Parameters:
3704fe59aa6dSJacob Faibussowitsch + A   - the `Mat` object
37056947451fSStefano Zampini - col - the column index
37066947451fSStefano Zampini 
37076947451fSStefano Zampini   Output Parameter:
37086947451fSStefano Zampini . v - the vector
37096947451fSStefano Zampini 
37102ef1f0ffSBarry Smith   Level: intermediate
37112ef1f0ffSBarry Smith 
37126947451fSStefano Zampini   Notes:
371311a5261eSBarry Smith   The vector is owned by PETSc. Users need to call `MatDenseRestoreColumnVec()` when the vector is no longer needed.
371411a5261eSBarry Smith 
371511a5261eSBarry Smith   Use `MatDenseGetColumnVecRead()` to obtain read-only access or `MatDenseGetColumnVecWrite()` for write-only access.
37166947451fSStefano Zampini 
37171cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATDENSE`, `MATDENSECUDA`, `MATDENSEHIP`, `MatDenseGetColumnVecRead()`, `MatDenseGetColumnVecWrite()`, `MatDenseRestoreColumnVec()`, `MatDenseRestoreColumnVecRead()`, `MatDenseRestoreColumnVecWrite()`, `MatDenseGetColumn()`
37186947451fSStefano Zampini @*/
3719d71ae5a4SJacob Faibussowitsch PetscErrorCode MatDenseGetColumnVec(Mat A, PetscInt col, Vec *v)
3720d71ae5a4SJacob Faibussowitsch {
37216947451fSStefano Zampini   PetscFunctionBegin;
37226947451fSStefano Zampini   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
37236947451fSStefano Zampini   PetscValidType(A, 1);
37246947451fSStefano Zampini   PetscValidLogicalCollectiveInt(A, col, 2);
37254f572ea9SToby Isaac   PetscAssertPointer(v, 3);
372628b400f6SJacob Faibussowitsch   PetscCheck(A->preallocated, PetscObjectComm((PetscObject)A), PETSC_ERR_ORDER, "Matrix not preallocated");
37272cf15c64SPierre 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);
3728cac4c232SBarry Smith   PetscUseMethod(A, "MatDenseGetColumnVec_C", (Mat, PetscInt, Vec *), (A, col, v));
37293ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
37306947451fSStefano Zampini }
37316947451fSStefano Zampini 
37320f74d2c1SSatish Balay /*@
3733fb850c59SBarry Smith   MatDenseRestoreColumnVec - Returns access to a column of a dense matrix obtained from `MatDenseGetColumnVec()`.
37346947451fSStefano Zampini 
37356947451fSStefano Zampini   Collective
37366947451fSStefano Zampini 
37375ea7661aSPierre Jolivet   Input Parameters:
3738fb850c59SBarry Smith + A   - the `Mat` object
37396947451fSStefano Zampini . col - the column index
3740fb850c59SBarry Smith - v   - the `Vec` object (may be `NULL`)
37416947451fSStefano Zampini 
37426947451fSStefano Zampini   Level: intermediate
37436947451fSStefano Zampini 
37441cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATDENSE`, `MATDENSECUDA`, `MATDENSEHIP`, `MatDenseGetColumnVec()`, `MatDenseGetColumnVecRead()`, `MatDenseGetColumnVecWrite()`, `MatDenseRestoreColumnVecRead()`, `MatDenseRestoreColumnVecWrite()`
37456947451fSStefano Zampini @*/
3746d71ae5a4SJacob Faibussowitsch PetscErrorCode MatDenseRestoreColumnVec(Mat A, PetscInt col, Vec *v)
3747d71ae5a4SJacob Faibussowitsch {
37486947451fSStefano Zampini   PetscFunctionBegin;
37496947451fSStefano Zampini   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
37506947451fSStefano Zampini   PetscValidType(A, 1);
37516947451fSStefano Zampini   PetscValidLogicalCollectiveInt(A, col, 2);
375208401ef6SPierre Jolivet   PetscCheck(A->preallocated, PetscObjectComm((PetscObject)A), PETSC_ERR_ORDER, "Matrix not preallocated");
37532cf15c64SPierre 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);
3754cac4c232SBarry Smith   PetscUseMethod(A, "MatDenseRestoreColumnVec_C", (Mat, PetscInt, Vec *), (A, col, v));
37553ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
37566947451fSStefano Zampini }
37576947451fSStefano Zampini 
37580f74d2c1SSatish Balay /*@
3759fb850c59SBarry Smith   MatDenseGetColumnVecRead - Gives read-only access to a column of a dense matrix, represented as a `Vec`.
37606947451fSStefano Zampini 
37616947451fSStefano Zampini   Collective
37626947451fSStefano Zampini 
37635ea7661aSPierre Jolivet   Input Parameters:
3764fe59aa6dSJacob Faibussowitsch + A   - the `Mat` object
37656947451fSStefano Zampini - col - the column index
37666947451fSStefano Zampini 
37676947451fSStefano Zampini   Output Parameter:
37686947451fSStefano Zampini . v - the vector
37696947451fSStefano Zampini 
37702ef1f0ffSBarry Smith   Level: intermediate
37712ef1f0ffSBarry Smith 
37726947451fSStefano Zampini   Notes:
37736947451fSStefano Zampini   The vector is owned by PETSc and users cannot modify it.
377411a5261eSBarry Smith 
37752ef1f0ffSBarry Smith   Users need to call `MatDenseRestoreColumnVecRead()` when the vector is no longer needed.
377611a5261eSBarry Smith 
37772ef1f0ffSBarry Smith   Use `MatDenseGetColumnVec()` to obtain read-write access or `MatDenseGetColumnVecWrite()` for write-only access.
37786947451fSStefano Zampini 
37791cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATDENSE`, `MATDENSECUDA`, `MATDENSEHIP`, `MatDenseGetColumnVec()`, `MatDenseGetColumnVecWrite()`, `MatDenseRestoreColumnVec()`, `MatDenseRestoreColumnVecRead()`, `MatDenseRestoreColumnVecWrite()`
37806947451fSStefano Zampini @*/
3781d71ae5a4SJacob Faibussowitsch PetscErrorCode MatDenseGetColumnVecRead(Mat A, PetscInt col, Vec *v)
3782d71ae5a4SJacob Faibussowitsch {
37836947451fSStefano Zampini   PetscFunctionBegin;
37846947451fSStefano Zampini   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
37856947451fSStefano Zampini   PetscValidType(A, 1);
37866947451fSStefano Zampini   PetscValidLogicalCollectiveInt(A, col, 2);
37874f572ea9SToby Isaac   PetscAssertPointer(v, 3);
378828b400f6SJacob Faibussowitsch   PetscCheck(A->preallocated, PetscObjectComm((PetscObject)A), PETSC_ERR_ORDER, "Matrix not preallocated");
37892cf15c64SPierre 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);
3790cac4c232SBarry Smith   PetscUseMethod(A, "MatDenseGetColumnVecRead_C", (Mat, PetscInt, Vec *), (A, col, v));
37913ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
37926947451fSStefano Zampini }
37936947451fSStefano Zampini 
37940f74d2c1SSatish Balay /*@
3795fb850c59SBarry Smith   MatDenseRestoreColumnVecRead - Returns access to a column of a dense matrix obtained from `MatDenseGetColumnVecRead()`.
37966947451fSStefano Zampini 
37976947451fSStefano Zampini   Collective
37986947451fSStefano Zampini 
37995ea7661aSPierre Jolivet   Input Parameters:
3800fe59aa6dSJacob Faibussowitsch + A   - the `Mat` object
38016947451fSStefano Zampini . col - the column index
3802fb850c59SBarry Smith - v   - the `Vec` object (may be `NULL`)
38036947451fSStefano Zampini 
38046947451fSStefano Zampini   Level: intermediate
38056947451fSStefano Zampini 
38061cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATDENSE`, `MATDENSECUDA`, `MATDENSEHIP`, `MatDenseGetColumnVec()`, `MatDenseGetColumnVecRead()`, `MatDenseGetColumnVecWrite()`, `MatDenseRestoreColumnVec()`, `MatDenseRestoreColumnVecWrite()`
38076947451fSStefano Zampini @*/
3808d71ae5a4SJacob Faibussowitsch PetscErrorCode MatDenseRestoreColumnVecRead(Mat A, PetscInt col, Vec *v)
3809d71ae5a4SJacob Faibussowitsch {
38106947451fSStefano Zampini   PetscFunctionBegin;
38116947451fSStefano Zampini   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
38126947451fSStefano Zampini   PetscValidType(A, 1);
38136947451fSStefano Zampini   PetscValidLogicalCollectiveInt(A, col, 2);
381408401ef6SPierre Jolivet   PetscCheck(A->preallocated, PetscObjectComm((PetscObject)A), PETSC_ERR_ORDER, "Matrix not preallocated");
38152cf15c64SPierre 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);
3816cac4c232SBarry Smith   PetscUseMethod(A, "MatDenseRestoreColumnVecRead_C", (Mat, PetscInt, Vec *), (A, col, v));
38173ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
38186947451fSStefano Zampini }
38196947451fSStefano Zampini 
38200f74d2c1SSatish Balay /*@
3821fb850c59SBarry Smith   MatDenseGetColumnVecWrite - Gives write-only access to a column of a dense matrix, represented as a `Vec`.
38226947451fSStefano Zampini 
38236947451fSStefano Zampini   Collective
38246947451fSStefano Zampini 
38255ea7661aSPierre Jolivet   Input Parameters:
3826fe59aa6dSJacob Faibussowitsch + A   - the `Mat` object
38276947451fSStefano Zampini - col - the column index
38286947451fSStefano Zampini 
38296947451fSStefano Zampini   Output Parameter:
38306947451fSStefano Zampini . v - the vector
38316947451fSStefano Zampini 
38326947451fSStefano Zampini   Level: intermediate
38336947451fSStefano Zampini 
38342ef1f0ffSBarry Smith   Notes:
38352ef1f0ffSBarry Smith   The vector is owned by PETSc. Users need to call `MatDenseRestoreColumnVecWrite()` when the vector is no longer needed.
38362ef1f0ffSBarry Smith 
38372ef1f0ffSBarry Smith   Use `MatDenseGetColumnVec()` to obtain read-write access or `MatDenseGetColumnVecRead()` for read-only access.
38382ef1f0ffSBarry Smith 
38391cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATDENSE`, `MATDENSECUDA`, `MATDENSEHIP`, `MatDenseGetColumnVec()`, `MatDenseGetColumnVecRead()`, `MatDenseRestoreColumnVec()`, `MatDenseRestoreColumnVecRead()`, `MatDenseRestoreColumnVecWrite()`
38406947451fSStefano Zampini @*/
3841d71ae5a4SJacob Faibussowitsch PetscErrorCode MatDenseGetColumnVecWrite(Mat A, PetscInt col, Vec *v)
3842d71ae5a4SJacob Faibussowitsch {
38436947451fSStefano Zampini   PetscFunctionBegin;
38446947451fSStefano Zampini   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
38456947451fSStefano Zampini   PetscValidType(A, 1);
38466947451fSStefano Zampini   PetscValidLogicalCollectiveInt(A, col, 2);
38474f572ea9SToby Isaac   PetscAssertPointer(v, 3);
384828b400f6SJacob Faibussowitsch   PetscCheck(A->preallocated, PetscObjectComm((PetscObject)A), PETSC_ERR_ORDER, "Matrix not preallocated");
3849aed4548fSBarry 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);
3850cac4c232SBarry Smith   PetscUseMethod(A, "MatDenseGetColumnVecWrite_C", (Mat, PetscInt, Vec *), (A, col, v));
38513ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
38526947451fSStefano Zampini }
38536947451fSStefano Zampini 
38540f74d2c1SSatish Balay /*@
3855fb850c59SBarry Smith   MatDenseRestoreColumnVecWrite - Returns access to a column of a dense matrix obtained from `MatDenseGetColumnVecWrite()`.
38566947451fSStefano Zampini 
38576947451fSStefano Zampini   Collective
38586947451fSStefano Zampini 
38595ea7661aSPierre Jolivet   Input Parameters:
3860fe59aa6dSJacob Faibussowitsch + A   - the `Mat` object
38616947451fSStefano Zampini . col - the column index
38622ef1f0ffSBarry Smith - v   - the `Vec` object (may be `NULL`)
38636947451fSStefano Zampini 
38646947451fSStefano Zampini   Level: intermediate
38656947451fSStefano Zampini 
38661cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATDENSE`, `MATDENSECUDA`, `MATDENSEHIP`, `MatDenseGetColumnVec()`, `MatDenseGetColumnVecRead()`, `MatDenseGetColumnVecWrite()`, `MatDenseRestoreColumnVec()`, `MatDenseRestoreColumnVecRead()`
38676947451fSStefano Zampini @*/
3868d71ae5a4SJacob Faibussowitsch PetscErrorCode MatDenseRestoreColumnVecWrite(Mat A, PetscInt col, Vec *v)
3869d71ae5a4SJacob Faibussowitsch {
38706947451fSStefano Zampini   PetscFunctionBegin;
38716947451fSStefano Zampini   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
38726947451fSStefano Zampini   PetscValidType(A, 1);
38736947451fSStefano Zampini   PetscValidLogicalCollectiveInt(A, col, 2);
387408401ef6SPierre Jolivet   PetscCheck(A->preallocated, PetscObjectComm((PetscObject)A), PETSC_ERR_ORDER, "Matrix not preallocated");
3875aed4548fSBarry 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);
3876cac4c232SBarry Smith   PetscUseMethod(A, "MatDenseRestoreColumnVecWrite_C", (Mat, PetscInt, Vec *), (A, col, v));
38773ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
38786947451fSStefano Zampini }
38795ea7661aSPierre Jolivet 
38800f74d2c1SSatish Balay /*@
3881fb850c59SBarry Smith   MatDenseGetSubMatrix - Gives access to a block of rows and columns of a dense matrix, represented as a `Mat`.
38825ea7661aSPierre Jolivet 
38835ea7661aSPierre Jolivet   Collective
38845ea7661aSPierre Jolivet 
38855ea7661aSPierre Jolivet   Input Parameters:
3886fb850c59SBarry Smith + A      - the `Mat` object
38872ef1f0ffSBarry Smith . rbegin - the first global row index in the block (if `PETSC_DECIDE`, is 0)
38882ef1f0ffSBarry Smith . rend   - the global row index past the last one in the block (if `PETSC_DECIDE`, is `M`)
38892ef1f0ffSBarry Smith . cbegin - the first global column index in the block (if `PETSC_DECIDE`, is 0)
38902ef1f0ffSBarry Smith - cend   - the global column index past the last one in the block (if `PETSC_DECIDE`, is `N`)
38915ea7661aSPierre Jolivet 
38925ea7661aSPierre Jolivet   Output Parameter:
38935ea7661aSPierre Jolivet . v - the matrix
38945ea7661aSPierre Jolivet 
38955ea7661aSPierre Jolivet   Level: intermediate
38965ea7661aSPierre Jolivet 
38972ef1f0ffSBarry Smith   Notes:
38982ef1f0ffSBarry Smith   The matrix is owned by PETSc. Users need to call `MatDenseRestoreSubMatrix()` when the matrix is no longer needed.
38992ef1f0ffSBarry Smith 
39002ef1f0ffSBarry 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.
39012ef1f0ffSBarry Smith 
39021cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATDENSE`, `MATDENSECUDA`, `MATDENSEHIP`, `MatDenseGetColumnVec()`, `MatDenseRestoreColumnVec()`, `MatDenseRestoreSubMatrix()`
39035ea7661aSPierre Jolivet @*/
3904d71ae5a4SJacob Faibussowitsch PetscErrorCode MatDenseGetSubMatrix(Mat A, PetscInt rbegin, PetscInt rend, PetscInt cbegin, PetscInt cend, Mat *v)
3905d71ae5a4SJacob Faibussowitsch {
39065ea7661aSPierre Jolivet   PetscFunctionBegin;
39075ea7661aSPierre Jolivet   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
39085ea7661aSPierre Jolivet   PetscValidType(A, 1);
3909a2748737SPierre Jolivet   PetscValidLogicalCollectiveInt(A, rbegin, 2);
3910a2748737SPierre Jolivet   PetscValidLogicalCollectiveInt(A, rend, 3);
3911a2748737SPierre Jolivet   PetscValidLogicalCollectiveInt(A, cbegin, 4);
3912a2748737SPierre Jolivet   PetscValidLogicalCollectiveInt(A, cend, 5);
39134f572ea9SToby Isaac   PetscAssertPointer(v, 6);
3914a2748737SPierre Jolivet   if (rbegin == PETSC_DECIDE) rbegin = 0;
3915a2748737SPierre Jolivet   if (rend == PETSC_DECIDE) rend = A->rmap->N;
3916a2748737SPierre Jolivet   if (cbegin == PETSC_DECIDE) cbegin = 0;
3917a2748737SPierre Jolivet   if (cend == PETSC_DECIDE) cend = A->cmap->N;
391828b400f6SJacob Faibussowitsch   PetscCheck(A->preallocated, PetscObjectComm((PetscObject)A), PETSC_ERR_ORDER, "Matrix not preallocated");
3919a2748737SPierre 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);
3920a2748737SPierre 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);
3921a2748737SPierre 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);
3922a2748737SPierre 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);
3923a2748737SPierre Jolivet   PetscUseMethod(A, "MatDenseGetSubMatrix_C", (Mat, PetscInt, PetscInt, PetscInt, PetscInt, Mat *), (A, rbegin, rend, cbegin, cend, v));
39243ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
39255ea7661aSPierre Jolivet }
39265ea7661aSPierre Jolivet 
39270f74d2c1SSatish Balay /*@
3928fb850c59SBarry Smith   MatDenseRestoreSubMatrix - Returns access to a block of columns of a dense matrix obtained from `MatDenseGetSubMatrix()`.
39295ea7661aSPierre Jolivet 
39305ea7661aSPierre Jolivet   Collective
39315ea7661aSPierre Jolivet 
39325ea7661aSPierre Jolivet   Input Parameters:
3933fe59aa6dSJacob Faibussowitsch + A - the `Mat` object
39342ef1f0ffSBarry Smith - v - the `Mat` object (may be `NULL`)
39355ea7661aSPierre Jolivet 
39365ea7661aSPierre Jolivet   Level: intermediate
39375ea7661aSPierre Jolivet 
39381cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATDENSE`, `MATDENSECUDA`, `MATDENSEHIP`, `MatDenseGetColumnVec()`, `MatDenseRestoreColumnVec()`, `MatDenseGetSubMatrix()`
39395ea7661aSPierre Jolivet @*/
3940d71ae5a4SJacob Faibussowitsch PetscErrorCode MatDenseRestoreSubMatrix(Mat A, Mat *v)
3941d71ae5a4SJacob Faibussowitsch {
39425ea7661aSPierre Jolivet   PetscFunctionBegin;
39435ea7661aSPierre Jolivet   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
39445ea7661aSPierre Jolivet   PetscValidType(A, 1);
39454f572ea9SToby Isaac   PetscAssertPointer(v, 2);
3946cac4c232SBarry Smith   PetscUseMethod(A, "MatDenseRestoreSubMatrix_C", (Mat, Mat *), (A, v));
39473ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
39485ea7661aSPierre Jolivet }
39498a9c020eSBarry Smith 
39508a9c020eSBarry Smith #include <petscblaslapack.h>
39518a9c020eSBarry Smith #include <petsc/private/kernels/blockinvert.h>
39528a9c020eSBarry Smith 
3953d71ae5a4SJacob Faibussowitsch PetscErrorCode MatSeqDenseInvert(Mat A)
3954d71ae5a4SJacob Faibussowitsch {
3955d63b1753SJacob Faibussowitsch   PetscInt        m;
39568a9c020eSBarry Smith   const PetscReal shift = 0.0;
3957d63b1753SJacob Faibussowitsch   PetscBool       allowzeropivot, zeropivotdetected = PETSC_FALSE;
3958d63b1753SJacob Faibussowitsch   PetscScalar    *values;
39598a9c020eSBarry Smith 
39608a9c020eSBarry Smith   PetscFunctionBegin;
3961d63b1753SJacob Faibussowitsch   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
3962d63b1753SJacob Faibussowitsch   PetscCall(MatDenseGetArray(A, &values));
3963d63b1753SJacob Faibussowitsch   PetscCall(MatGetLocalSize(A, &m, NULL));
3964d63b1753SJacob Faibussowitsch   allowzeropivot = PetscNot(A->erroriffailure);
39658a9c020eSBarry Smith   /* factor and invert each block */
3966d63b1753SJacob Faibussowitsch   switch (m) {
3967d71ae5a4SJacob Faibussowitsch   case 1:
3968d71ae5a4SJacob Faibussowitsch     values[0] = (PetscScalar)1.0 / (values[0] + shift);
3969d71ae5a4SJacob Faibussowitsch     break;
39708a9c020eSBarry Smith   case 2:
39718a9c020eSBarry Smith     PetscCall(PetscKernel_A_gets_inverse_A_2(values, shift, allowzeropivot, &zeropivotdetected));
39728a9c020eSBarry Smith     if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
39738a9c020eSBarry Smith     break;
39748a9c020eSBarry Smith   case 3:
39758a9c020eSBarry Smith     PetscCall(PetscKernel_A_gets_inverse_A_3(values, shift, allowzeropivot, &zeropivotdetected));
39768a9c020eSBarry Smith     if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
39778a9c020eSBarry Smith     break;
39788a9c020eSBarry Smith   case 4:
39798a9c020eSBarry Smith     PetscCall(PetscKernel_A_gets_inverse_A_4(values, shift, allowzeropivot, &zeropivotdetected));
39808a9c020eSBarry Smith     if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
39818a9c020eSBarry Smith     break;
39829371c9d4SSatish Balay   case 5: {
39838a9c020eSBarry Smith     PetscScalar work[25];
39848a9c020eSBarry Smith     PetscInt    ipvt[5];
39858a9c020eSBarry Smith 
39868a9c020eSBarry Smith     PetscCall(PetscKernel_A_gets_inverse_A_5(values, ipvt, work, shift, allowzeropivot, &zeropivotdetected));
39878a9c020eSBarry Smith     if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
39889371c9d4SSatish Balay   } break;
39898a9c020eSBarry Smith   case 6:
39908a9c020eSBarry Smith     PetscCall(PetscKernel_A_gets_inverse_A_6(values, shift, allowzeropivot, &zeropivotdetected));
39918a9c020eSBarry Smith     if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
39928a9c020eSBarry Smith     break;
39938a9c020eSBarry Smith   case 7:
39948a9c020eSBarry Smith     PetscCall(PetscKernel_A_gets_inverse_A_7(values, shift, allowzeropivot, &zeropivotdetected));
39958a9c020eSBarry Smith     if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
39968a9c020eSBarry Smith     break;
39979371c9d4SSatish Balay   default: {
39988a9c020eSBarry Smith     PetscInt    *v_pivots, *IJ, j;
39998a9c020eSBarry Smith     PetscScalar *v_work;
40008a9c020eSBarry Smith 
4001d63b1753SJacob Faibussowitsch     PetscCall(PetscMalloc3(m, &v_work, m, &v_pivots, m, &IJ));
4002d63b1753SJacob Faibussowitsch     for (j = 0; j < m; j++) IJ[j] = j;
4003d63b1753SJacob Faibussowitsch     PetscCall(PetscKernel_A_gets_inverse_A(m, values, v_pivots, v_work, allowzeropivot, &zeropivotdetected));
40048a9c020eSBarry Smith     if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
40058a9c020eSBarry Smith     PetscCall(PetscFree3(v_work, v_pivots, IJ));
40068a9c020eSBarry Smith   }
40078a9c020eSBarry Smith   }
4008d63b1753SJacob Faibussowitsch   PetscCall(MatDenseRestoreArray(A, &values));
40093ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
40108a9c020eSBarry Smith }
4011