xref: /petsc/src/mat/impls/dense/seq/dense.c (revision 07c83e99bc22b531fe50602e7d003b6c4ab90fa3)
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     }
7628b400f6SJacob Faibussowitsch     PetscCheck(!info, PETSC_COMM_SELF, PETSC_ERR_MAT_CH_ZRPVT, "Bad Inversion: zero pivot in row %" PetscInt_FMT, (PetscInt)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;
36223fc5dcaSStefano Zampini   PetscInt      lda = (PetscInt)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());
41205fcb23eSStefano Zampini   PetscCheck(!info, PETSC_COMM_SELF, PETSC_ERR_LIB, "GETRS - Bad solve %d", (int)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());
43005fcb23eSStefano Zampini     PetscCheck(!info, PETSC_COMM_SELF, PETSC_ERR_LIB, "POTRS Bad solve %d", (int)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());
43805fcb23eSStefano Zampini     PetscCheck(!info, PETSC_COMM_SELF, PETSC_ERR_LIB, "HETRS Bad solve %d", (int)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());
44505fcb23eSStefano Zampini     PetscCheck(!info, PETSC_COMM_SELF, PETSC_ERR_LIB, "SYTRS Bad solve %d", (int)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());
47805fcb23eSStefano Zampini   PetscCheck(!info, PETSC_COMM_SELF, PETSC_ERR_LIB, "ORMQR - Bad orthogonal transform %d", (int)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());
48205fcb23eSStefano Zampini   PetscCheck(!info, PETSC_COMM_SELF, PETSC_ERR_LIB, "TRTRS - Bad triangular solve %d", (int)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());
50005fcb23eSStefano Zampini     PetscCheck(!info, PETSC_COMM_SELF, PETSC_ERR_LIB, "TRTRS - Bad triangular solve %d", (int)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());
51705fcb23eSStefano Zampini     PetscCheck(!info, PETSC_COMM_SELF, PETSC_ERR_LIB, "ORMQR - Bad orthogonal transform %d", (int)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 
80605fcb23eSStefano Zampini   PetscCheck(info >= 0, PETSC_COMM_SELF, PETSC_ERR_LIB, "Bad argument to LU factorization %d", (int)info);
80705fcb23eSStefano Zampini   PetscCheck(info <= 0, PETSC_COMM_SELF, PETSC_ERR_MAT_LU_ZRPVT, "Bad LU factorization %d", (int)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());
864*07c83e99SJose 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   }
88728b400f6SJacob Faibussowitsch   PetscCheck(!info, PETSC_COMM_SELF, PETSC_ERR_MAT_CH_ZRPVT, "Bad factorization: zero pivot in row %" PetscInt_FMT, (PetscInt)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());
95005fcb23eSStefano Zampini   PetscCheck(!info, PETSC_COMM_SELF, PETSC_ERR_LIB, "Bad argument to QR factorization %d", (int)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));
104355a1b374SBarry Smith         x[i] = (1. - omega) * x[i] + omega * (xt + v[i + i * m] * x[i]) / (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));
104955a1b374SBarry Smith         x[i] = (1. - omega) * x[i] + omega * (xt + v[i + i * m] * x[i]) / (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;
13398491ab44SLisandro Dalcin   PetscInt           header[4], M, N, m, lda, i, j, k;
13408491ab44SLisandro Dalcin   const PetscScalar *v;
13418491ab44SLisandro Dalcin   PetscScalar       *vwork;
1342aabbc4fbSShri Abhyankar 
1343aabbc4fbSShri Abhyankar   PetscFunctionBegin;
13449566063dSJacob Faibussowitsch   PetscCall(PetscViewerSetUp(viewer));
13459566063dSJacob Faibussowitsch   PetscCall(PetscViewerBinaryGetSkipHeader(viewer, &skipHeader));
13469566063dSJacob Faibussowitsch   PetscCall(PetscViewerGetFormat(viewer, &format));
13478491ab44SLisandro Dalcin   if (skipHeader) format = PETSC_VIEWER_NATIVE;
1348aabbc4fbSShri Abhyankar 
13499566063dSJacob Faibussowitsch   PetscCall(MatGetSize(mat, &M, &N));
13508491ab44SLisandro Dalcin 
13518491ab44SLisandro Dalcin   /* write matrix header */
13529371c9d4SSatish Balay   header[0] = MAT_FILE_CLASSID;
13539371c9d4SSatish Balay   header[1] = M;
13549371c9d4SSatish Balay   header[2] = N;
13558491ab44SLisandro Dalcin   header[3] = (format == PETSC_VIEWER_NATIVE) ? MATRIX_BINARY_FORMAT_DENSE : M * N;
13569566063dSJacob Faibussowitsch   if (!skipHeader) PetscCall(PetscViewerBinaryWrite(viewer, header, 4, PETSC_INT));
13578491ab44SLisandro Dalcin 
13589566063dSJacob Faibussowitsch   PetscCall(MatGetLocalSize(mat, &m, NULL));
13598491ab44SLisandro Dalcin   if (format != PETSC_VIEWER_NATIVE) {
13608491ab44SLisandro Dalcin     PetscInt nnz = m * N, *iwork;
13618491ab44SLisandro Dalcin     /* store row lengths for each row */
13629566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(nnz, &iwork));
13638491ab44SLisandro Dalcin     for (i = 0; i < m; i++) iwork[i] = N;
13649566063dSJacob Faibussowitsch     PetscCall(PetscViewerBinaryWriteAll(viewer, iwork, m, PETSC_DETERMINE, PETSC_DETERMINE, PETSC_INT));
13658491ab44SLisandro Dalcin     /* store column indices (zero start index) */
13668491ab44SLisandro Dalcin     for (k = 0, i = 0; i < m; i++)
13679371c9d4SSatish Balay       for (j = 0; j < N; j++, k++) iwork[k] = j;
13689566063dSJacob Faibussowitsch     PetscCall(PetscViewerBinaryWriteAll(viewer, iwork, nnz, PETSC_DETERMINE, PETSC_DETERMINE, PETSC_INT));
13699566063dSJacob Faibussowitsch     PetscCall(PetscFree(iwork));
13708491ab44SLisandro Dalcin   }
13718491ab44SLisandro Dalcin   /* store matrix values as a dense matrix in row major order */
13729566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(m * N, &vwork));
13739566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArrayRead(mat, &v));
13749566063dSJacob Faibussowitsch   PetscCall(MatDenseGetLDA(mat, &lda));
13758491ab44SLisandro Dalcin   for (k = 0, i = 0; i < m; i++)
13769371c9d4SSatish Balay     for (j = 0; j < N; j++, k++) vwork[k] = v[i + lda * j];
13779566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArrayRead(mat, &v));
13789566063dSJacob Faibussowitsch   PetscCall(PetscViewerBinaryWriteAll(viewer, vwork, m * N, PETSC_DETERMINE, PETSC_DETERMINE, PETSC_SCALAR));
13799566063dSJacob Faibussowitsch   PetscCall(PetscFree(vwork));
13803ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
13818491ab44SLisandro Dalcin }
13828491ab44SLisandro Dalcin 
1383d71ae5a4SJacob Faibussowitsch PetscErrorCode MatLoad_Dense_Binary(Mat mat, PetscViewer viewer)
1384d71ae5a4SJacob Faibussowitsch {
13858491ab44SLisandro Dalcin   PetscBool    skipHeader;
13868491ab44SLisandro Dalcin   PetscInt     header[4], M, N, m, nz, lda, i, j, k;
13878491ab44SLisandro Dalcin   PetscInt     rows, cols;
13888491ab44SLisandro Dalcin   PetscScalar *v, *vwork;
13898491ab44SLisandro Dalcin 
13908491ab44SLisandro Dalcin   PetscFunctionBegin;
13919566063dSJacob Faibussowitsch   PetscCall(PetscViewerSetUp(viewer));
13929566063dSJacob Faibussowitsch   PetscCall(PetscViewerBinaryGetSkipHeader(viewer, &skipHeader));
13938491ab44SLisandro Dalcin 
13948491ab44SLisandro Dalcin   if (!skipHeader) {
13959566063dSJacob Faibussowitsch     PetscCall(PetscViewerBinaryRead(viewer, header, 4, NULL, PETSC_INT));
139608401ef6SPierre Jolivet     PetscCheck(header[0] == MAT_FILE_CLASSID, PetscObjectComm((PetscObject)viewer), PETSC_ERR_FILE_UNEXPECTED, "Not a matrix object in file");
13979371c9d4SSatish Balay     M = header[1];
13989371c9d4SSatish Balay     N = header[2];
139908401ef6SPierre Jolivet     PetscCheck(M >= 0, PetscObjectComm((PetscObject)viewer), PETSC_ERR_FILE_UNEXPECTED, "Matrix row size (%" PetscInt_FMT ") in file is negative", M);
140008401ef6SPierre Jolivet     PetscCheck(N >= 0, PetscObjectComm((PetscObject)viewer), PETSC_ERR_FILE_UNEXPECTED, "Matrix column size (%" PetscInt_FMT ") in file is negative", N);
14018491ab44SLisandro Dalcin     nz = header[3];
1402aed4548fSBarry Smith     PetscCheck(nz == MATRIX_BINARY_FORMAT_DENSE || nz >= 0, PetscObjectComm((PetscObject)viewer), PETSC_ERR_FILE_UNEXPECTED, "Unknown matrix format %" PetscInt_FMT " in file", nz);
1403aabbc4fbSShri Abhyankar   } else {
14049566063dSJacob Faibussowitsch     PetscCall(MatGetSize(mat, &M, &N));
1405aed4548fSBarry 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");
14068491ab44SLisandro Dalcin     nz = MATRIX_BINARY_FORMAT_DENSE;
1407e6324fbbSBarry Smith   }
1408aabbc4fbSShri Abhyankar 
14098491ab44SLisandro Dalcin   /* setup global sizes if not set */
14108491ab44SLisandro Dalcin   if (mat->rmap->N < 0) mat->rmap->N = M;
14118491ab44SLisandro Dalcin   if (mat->cmap->N < 0) mat->cmap->N = N;
14129566063dSJacob Faibussowitsch   PetscCall(MatSetUp(mat));
14138491ab44SLisandro Dalcin   /* check if global sizes are correct */
14149566063dSJacob Faibussowitsch   PetscCall(MatGetSize(mat, &rows, &cols));
1415aed4548fSBarry 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);
1416aabbc4fbSShri Abhyankar 
14179566063dSJacob Faibussowitsch   PetscCall(MatGetSize(mat, NULL, &N));
14189566063dSJacob Faibussowitsch   PetscCall(MatGetLocalSize(mat, &m, NULL));
14199566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArray(mat, &v));
14209566063dSJacob Faibussowitsch   PetscCall(MatDenseGetLDA(mat, &lda));
14218491ab44SLisandro Dalcin   if (nz == MATRIX_BINARY_FORMAT_DENSE) { /* matrix in file is dense format */
14228491ab44SLisandro Dalcin     PetscInt nnz = m * N;
14238491ab44SLisandro Dalcin     /* read in matrix values */
14249566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(nnz, &vwork));
14259566063dSJacob Faibussowitsch     PetscCall(PetscViewerBinaryReadAll(viewer, vwork, nnz, PETSC_DETERMINE, PETSC_DETERMINE, PETSC_SCALAR));
14268491ab44SLisandro Dalcin     /* store values in column major order */
14278491ab44SLisandro Dalcin     for (j = 0; j < N; j++)
14289371c9d4SSatish Balay       for (i = 0; i < m; i++) v[i + lda * j] = vwork[i * N + j];
14299566063dSJacob Faibussowitsch     PetscCall(PetscFree(vwork));
14308491ab44SLisandro Dalcin   } else { /* matrix in file is sparse format */
14318491ab44SLisandro Dalcin     PetscInt nnz = 0, *rlens, *icols;
14328491ab44SLisandro Dalcin     /* read in row lengths */
14339566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(m, &rlens));
14349566063dSJacob Faibussowitsch     PetscCall(PetscViewerBinaryReadAll(viewer, rlens, m, PETSC_DETERMINE, PETSC_DETERMINE, PETSC_INT));
14358491ab44SLisandro Dalcin     for (i = 0; i < m; i++) nnz += rlens[i];
14368491ab44SLisandro Dalcin     /* read in column indices and values */
14379566063dSJacob Faibussowitsch     PetscCall(PetscMalloc2(nnz, &icols, nnz, &vwork));
14389566063dSJacob Faibussowitsch     PetscCall(PetscViewerBinaryReadAll(viewer, icols, nnz, PETSC_DETERMINE, PETSC_DETERMINE, PETSC_INT));
14399566063dSJacob Faibussowitsch     PetscCall(PetscViewerBinaryReadAll(viewer, vwork, nnz, PETSC_DETERMINE, PETSC_DETERMINE, PETSC_SCALAR));
14408491ab44SLisandro Dalcin     /* store values in column major order */
14418491ab44SLisandro Dalcin     for (k = 0, i = 0; i < m; i++)
14429371c9d4SSatish Balay       for (j = 0; j < rlens[i]; j++, k++) v[i + lda * icols[k]] = vwork[k];
14439566063dSJacob Faibussowitsch     PetscCall(PetscFree(rlens));
14449566063dSJacob Faibussowitsch     PetscCall(PetscFree2(icols, vwork));
1445aabbc4fbSShri Abhyankar   }
14469566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArray(mat, &v));
14479566063dSJacob Faibussowitsch   PetscCall(MatAssemblyBegin(mat, MAT_FINAL_ASSEMBLY));
14489566063dSJacob Faibussowitsch   PetscCall(MatAssemblyEnd(mat, MAT_FINAL_ASSEMBLY));
14493ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1450aabbc4fbSShri Abhyankar }
1451aabbc4fbSShri Abhyankar 
145266976f2fSJacob Faibussowitsch static PetscErrorCode MatLoad_SeqDense(Mat newMat, PetscViewer viewer)
1453d71ae5a4SJacob Faibussowitsch {
1454eb91f321SVaclav Hapla   PetscBool isbinary, ishdf5;
1455eb91f321SVaclav Hapla 
1456eb91f321SVaclav Hapla   PetscFunctionBegin;
1457eb91f321SVaclav Hapla   PetscValidHeaderSpecific(newMat, MAT_CLASSID, 1);
1458eb91f321SVaclav Hapla   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
1459eb91f321SVaclav Hapla   /* force binary viewer to load .info file if it has not yet done so */
14609566063dSJacob Faibussowitsch   PetscCall(PetscViewerSetUp(viewer));
14619566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERBINARY, &isbinary));
14629566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5));
1463eb91f321SVaclav Hapla   if (isbinary) {
14649566063dSJacob Faibussowitsch     PetscCall(MatLoad_Dense_Binary(newMat, viewer));
1465eb91f321SVaclav Hapla   } else if (ishdf5) {
1466eb91f321SVaclav Hapla #if defined(PETSC_HAVE_HDF5)
14679566063dSJacob Faibussowitsch     PetscCall(MatLoad_Dense_HDF5(newMat, viewer));
1468eb91f321SVaclav Hapla #else
1469eb91f321SVaclav Hapla     SETERRQ(PetscObjectComm((PetscObject)newMat), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5");
1470eb91f321SVaclav Hapla #endif
1471eb91f321SVaclav Hapla   } else {
147298921bdaSJacob 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);
1473eb91f321SVaclav Hapla   }
14743ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1475eb91f321SVaclav Hapla }
1476eb91f321SVaclav Hapla 
1477d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatView_SeqDense_ASCII(Mat A, PetscViewer viewer)
1478d71ae5a4SJacob Faibussowitsch {
1479932b0c3eSLois Curfman McInnes   Mat_SeqDense     *a = (Mat_SeqDense *)A->data;
148013f74950SBarry Smith   PetscInt          i, j;
14812dcb1b2aSMatthew Knepley   const char       *name;
1482ca15aa20SStefano Zampini   PetscScalar      *v, *av;
1483f3ef73ceSBarry Smith   PetscViewerFormat format;
14845f481a85SSatish Balay #if defined(PETSC_USE_COMPLEX)
1485ace3abfcSBarry Smith   PetscBool allreal = PETSC_TRUE;
14865f481a85SSatish Balay #endif
1487932b0c3eSLois Curfman McInnes 
14883a40ed3dSBarry Smith   PetscFunctionBegin;
14899566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArrayRead(A, (const PetscScalar **)&av));
14909566063dSJacob Faibussowitsch   PetscCall(PetscViewerGetFormat(viewer, &format));
1491456192e2SBarry Smith   if (format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL) {
14923ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS); /* do nothing for now */
1493fb9695e5SSatish Balay   } else if (format == PETSC_VIEWER_ASCII_COMMON) {
14949566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIUseTabs(viewer, PETSC_FALSE));
1495d0f46423SBarry Smith     for (i = 0; i < A->rmap->n; i++) {
1496ca15aa20SStefano Zampini       v = av + i;
14979566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "row %" PetscInt_FMT ":", i));
1498d0f46423SBarry Smith       for (j = 0; j < A->cmap->n; j++) {
1499aa482453SBarry Smith #if defined(PETSC_USE_COMPLEX)
1500329f5518SBarry Smith         if (PetscRealPart(*v) != 0.0 && PetscImaginaryPart(*v) != 0.0) {
15019566063dSJacob Faibussowitsch           PetscCall(PetscViewerASCIIPrintf(viewer, " (%" PetscInt_FMT ", %g + %g i) ", j, (double)PetscRealPart(*v), (double)PetscImaginaryPart(*v)));
1502329f5518SBarry Smith         } else if (PetscRealPart(*v)) {
15039566063dSJacob Faibussowitsch           PetscCall(PetscViewerASCIIPrintf(viewer, " (%" PetscInt_FMT ", %g) ", j, (double)PetscRealPart(*v)));
15046831982aSBarry Smith         }
150580cd9d93SLois Curfman McInnes #else
150648a46eb9SPierre Jolivet         if (*v) PetscCall(PetscViewerASCIIPrintf(viewer, " (%" PetscInt_FMT ", %g) ", j, (double)*v));
150780cd9d93SLois Curfman McInnes #endif
15081b807ce4Svictorle         v += a->lda;
150980cd9d93SLois Curfman McInnes       }
15109566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "\n"));
151180cd9d93SLois Curfman McInnes     }
15129566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIUseTabs(viewer, PETSC_TRUE));
15133a40ed3dSBarry Smith   } else {
15149566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIUseTabs(viewer, PETSC_FALSE));
1515aa482453SBarry Smith #if defined(PETSC_USE_COMPLEX)
151647989497SBarry Smith     /* determine if matrix has all real values */
1517bcd8d3a4SJose E. Roman     for (j = 0; j < A->cmap->n; j++) {
1518bcd8d3a4SJose E. Roman       v = av + j * a->lda;
1519bcd8d3a4SJose E. Roman       for (i = 0; i < A->rmap->n; i++) {
15209371c9d4SSatish Balay         if (PetscImaginaryPart(v[i])) {
15219371c9d4SSatish Balay           allreal = PETSC_FALSE;
15229371c9d4SSatish Balay           break;
15239371c9d4SSatish Balay         }
152447989497SBarry Smith       }
1525bcd8d3a4SJose E. Roman     }
152647989497SBarry Smith #endif
1527fb9695e5SSatish Balay     if (format == PETSC_VIEWER_ASCII_MATLAB) {
15289566063dSJacob Faibussowitsch       PetscCall(PetscObjectGetName((PetscObject)A, &name));
15299566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "%% Size = %" PetscInt_FMT " %" PetscInt_FMT " \n", A->rmap->n, A->cmap->n));
15309566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "%s = zeros(%" PetscInt_FMT ",%" PetscInt_FMT ");\n", name, A->rmap->n, A->cmap->n));
15319566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "%s = [\n", name));
1532ffac6cdbSBarry Smith     }
1533ffac6cdbSBarry Smith 
1534d0f46423SBarry Smith     for (i = 0; i < A->rmap->n; i++) {
1535ca15aa20SStefano Zampini       v = av + i;
1536d0f46423SBarry Smith       for (j = 0; j < A->cmap->n; j++) {
1537aa482453SBarry Smith #if defined(PETSC_USE_COMPLEX)
153847989497SBarry Smith         if (allreal) {
15399566063dSJacob Faibussowitsch           PetscCall(PetscViewerASCIIPrintf(viewer, "%18.16e ", (double)PetscRealPart(*v)));
154047989497SBarry Smith         } else {
15419566063dSJacob Faibussowitsch           PetscCall(PetscViewerASCIIPrintf(viewer, "%18.16e + %18.16ei ", (double)PetscRealPart(*v), (double)PetscImaginaryPart(*v)));
154247989497SBarry Smith         }
1543289bc588SBarry Smith #else
15449566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, "%18.16e ", (double)*v));
1545289bc588SBarry Smith #endif
15461b807ce4Svictorle         v += a->lda;
1547289bc588SBarry Smith       }
15489566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "\n"));
1549289bc588SBarry Smith     }
155048a46eb9SPierre Jolivet     if (format == PETSC_VIEWER_ASCII_MATLAB) PetscCall(PetscViewerASCIIPrintf(viewer, "];\n"));
15519566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIUseTabs(viewer, PETSC_TRUE));
1552da3a660dSBarry Smith   }
15539566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArrayRead(A, (const PetscScalar **)&av));
15549566063dSJacob Faibussowitsch   PetscCall(PetscViewerFlush(viewer));
15553ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1556289bc588SBarry Smith }
1557289bc588SBarry Smith 
15589804daf3SBarry Smith #include <petscdraw.h>
1559d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatView_SeqDense_Draw_Zoom(PetscDraw draw, void *Aa)
1560d71ae5a4SJacob Faibussowitsch {
1561f1af5d2fSBarry Smith   Mat                A = (Mat)Aa;
1562383922c3SLisandro Dalcin   PetscInt           m = A->rmap->n, n = A->cmap->n, i, j;
1563383922c3SLisandro Dalcin   int                color = PETSC_DRAW_WHITE;
1564ca15aa20SStefano Zampini   const PetscScalar *v;
1565b0a32e0cSBarry Smith   PetscViewer        viewer;
1566b05fc000SLisandro Dalcin   PetscReal          xl, yl, xr, yr, x_l, x_r, y_l, y_r;
1567f3ef73ceSBarry Smith   PetscViewerFormat  format;
1568f1af5d2fSBarry Smith 
1569f1af5d2fSBarry Smith   PetscFunctionBegin;
15709566063dSJacob Faibussowitsch   PetscCall(PetscObjectQuery((PetscObject)A, "Zoomviewer", (PetscObject *)&viewer));
15719566063dSJacob Faibussowitsch   PetscCall(PetscViewerGetFormat(viewer, &format));
15729566063dSJacob Faibussowitsch   PetscCall(PetscDrawGetCoordinates(draw, &xl, &yl, &xr, &yr));
1573f1af5d2fSBarry Smith 
1574f1af5d2fSBarry Smith   /* Loop over matrix elements drawing boxes */
15759566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArrayRead(A, &v));
1576fb9695e5SSatish Balay   if (format != PETSC_VIEWER_DRAW_CONTOUR) {
1577d0609cedSBarry Smith     PetscDrawCollectiveBegin(draw);
1578f1af5d2fSBarry Smith     /* Blue for negative and Red for positive */
1579f1af5d2fSBarry Smith     for (j = 0; j < n; j++) {
15809371c9d4SSatish Balay       x_l = j;
15819371c9d4SSatish Balay       x_r = x_l + 1.0;
1582f1af5d2fSBarry Smith       for (i = 0; i < m; i++) {
1583f1af5d2fSBarry Smith         y_l = m - i - 1.0;
1584f1af5d2fSBarry Smith         y_r = y_l + 1.0;
1585ca15aa20SStefano Zampini         if (PetscRealPart(v[j * m + i]) > 0.) color = PETSC_DRAW_RED;
1586ca15aa20SStefano Zampini         else if (PetscRealPart(v[j * m + i]) < 0.) color = PETSC_DRAW_BLUE;
1587ca15aa20SStefano Zampini         else continue;
15889566063dSJacob Faibussowitsch         PetscCall(PetscDrawRectangle(draw, x_l, y_l, x_r, y_r, color, color, color, color));
1589f1af5d2fSBarry Smith       }
1590f1af5d2fSBarry Smith     }
1591d0609cedSBarry Smith     PetscDrawCollectiveEnd(draw);
1592f1af5d2fSBarry Smith   } else {
1593f1af5d2fSBarry Smith     /* use contour shading to indicate magnitude of values */
1594f1af5d2fSBarry Smith     /* first determine max of all nonzero values */
1595b05fc000SLisandro Dalcin     PetscReal minv = 0.0, maxv = 0.0;
1596b05fc000SLisandro Dalcin     PetscDraw popup;
1597b05fc000SLisandro Dalcin 
1598f1af5d2fSBarry Smith     for (i = 0; i < m * n; i++) {
1599f1af5d2fSBarry Smith       if (PetscAbsScalar(v[i]) > maxv) maxv = PetscAbsScalar(v[i]);
1600f1af5d2fSBarry Smith     }
1601383922c3SLisandro Dalcin     if (minv >= maxv) maxv = minv + PETSC_SMALL;
16029566063dSJacob Faibussowitsch     PetscCall(PetscDrawGetPopup(draw, &popup));
16039566063dSJacob Faibussowitsch     PetscCall(PetscDrawScalePopup(popup, minv, maxv));
1604383922c3SLisandro Dalcin 
1605d0609cedSBarry Smith     PetscDrawCollectiveBegin(draw);
1606f1af5d2fSBarry Smith     for (j = 0; j < n; j++) {
1607f1af5d2fSBarry Smith       x_l = j;
1608f1af5d2fSBarry Smith       x_r = x_l + 1.0;
1609f1af5d2fSBarry Smith       for (i = 0; i < m; i++) {
1610f1af5d2fSBarry Smith         y_l   = m - i - 1.0;
1611f1af5d2fSBarry Smith         y_r   = y_l + 1.0;
1612b05fc000SLisandro Dalcin         color = PetscDrawRealToColor(PetscAbsScalar(v[j * m + i]), minv, maxv);
16139566063dSJacob Faibussowitsch         PetscCall(PetscDrawRectangle(draw, x_l, y_l, x_r, y_r, color, color, color, color));
1614f1af5d2fSBarry Smith       }
1615f1af5d2fSBarry Smith     }
1616d0609cedSBarry Smith     PetscDrawCollectiveEnd(draw);
1617f1af5d2fSBarry Smith   }
16189566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArrayRead(A, &v));
16193ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1620f1af5d2fSBarry Smith }
1621f1af5d2fSBarry Smith 
1622d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatView_SeqDense_Draw(Mat A, PetscViewer viewer)
1623d71ae5a4SJacob Faibussowitsch {
1624b0a32e0cSBarry Smith   PetscDraw draw;
1625ace3abfcSBarry Smith   PetscBool isnull;
1626329f5518SBarry Smith   PetscReal xr, yr, xl, yl, h, w;
1627f1af5d2fSBarry Smith 
1628f1af5d2fSBarry Smith   PetscFunctionBegin;
16299566063dSJacob Faibussowitsch   PetscCall(PetscViewerDrawGetDraw(viewer, 0, &draw));
16309566063dSJacob Faibussowitsch   PetscCall(PetscDrawIsNull(draw, &isnull));
16313ba16761SJacob Faibussowitsch   if (isnull) PetscFunctionReturn(PETSC_SUCCESS);
1632f1af5d2fSBarry Smith 
16339371c9d4SSatish Balay   xr = A->cmap->n;
16349371c9d4SSatish Balay   yr = A->rmap->n;
16359371c9d4SSatish Balay   h  = yr / 10.0;
16369371c9d4SSatish Balay   w  = xr / 10.0;
16379371c9d4SSatish Balay   xr += w;
16389371c9d4SSatish Balay   yr += h;
16399371c9d4SSatish Balay   xl = -w;
16409371c9d4SSatish Balay   yl = -h;
16419566063dSJacob Faibussowitsch   PetscCall(PetscDrawSetCoordinates(draw, xl, yl, xr, yr));
16429566063dSJacob Faibussowitsch   PetscCall(PetscObjectCompose((PetscObject)A, "Zoomviewer", (PetscObject)viewer));
16439566063dSJacob Faibussowitsch   PetscCall(PetscDrawZoom(draw, MatView_SeqDense_Draw_Zoom, A));
16449566063dSJacob Faibussowitsch   PetscCall(PetscObjectCompose((PetscObject)A, "Zoomviewer", NULL));
16459566063dSJacob Faibussowitsch   PetscCall(PetscDrawSave(draw));
16463ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1647f1af5d2fSBarry Smith }
1648f1af5d2fSBarry Smith 
1649d71ae5a4SJacob Faibussowitsch PetscErrorCode MatView_SeqDense(Mat A, PetscViewer viewer)
1650d71ae5a4SJacob Faibussowitsch {
1651ace3abfcSBarry Smith   PetscBool iascii, isbinary, isdraw;
1652932b0c3eSLois Curfman McInnes 
16533a40ed3dSBarry Smith   PetscFunctionBegin;
16549566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
16559566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERBINARY, &isbinary));
16569566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERDRAW, &isdraw));
16571baa6e33SBarry Smith   if (iascii) PetscCall(MatView_SeqDense_ASCII(A, viewer));
16581baa6e33SBarry Smith   else if (isbinary) PetscCall(MatView_Dense_Binary(A, viewer));
16591baa6e33SBarry Smith   else if (isdraw) PetscCall(MatView_SeqDense_Draw(A, viewer));
16603ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1661932b0c3eSLois Curfman McInnes }
1662289bc588SBarry Smith 
1663d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatDensePlaceArray_SeqDense(Mat A, const PetscScalar *array)
1664d71ae5a4SJacob Faibussowitsch {
1665d3042a70SBarry Smith   Mat_SeqDense *a = (Mat_SeqDense *)A->data;
1666d3042a70SBarry Smith 
1667d3042a70SBarry Smith   PetscFunctionBegin;
166828b400f6SJacob Faibussowitsch   PetscCheck(!a->vecinuse, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Need to call MatDenseRestoreColumnVec() first");
166928b400f6SJacob Faibussowitsch   PetscCheck(!a->matinuse, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Need to call MatDenseRestoreSubMatrix() first");
16706635c364SPierre Jolivet   PetscCheck(!a->unplacedarray, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Need to call MatDenseResetArray() first");
1671d3042a70SBarry Smith   a->unplacedarray       = a->v;
1672d3042a70SBarry Smith   a->unplaced_user_alloc = a->user_alloc;
1673d3042a70SBarry Smith   a->v                   = (PetscScalar *)array;
1674637a0070SStefano Zampini   a->user_alloc          = PETSC_TRUE;
167547d993e7Ssuyashtn #if defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
1676c70f7ee4SJunchao Zhang   A->offloadmask = PETSC_OFFLOAD_CPU;
1677ca15aa20SStefano Zampini #endif
16783ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1679d3042a70SBarry Smith }
1680d3042a70SBarry Smith 
1681d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatDenseResetArray_SeqDense(Mat A)
1682d71ae5a4SJacob Faibussowitsch {
1683d3042a70SBarry Smith   Mat_SeqDense *a = (Mat_SeqDense *)A->data;
1684d3042a70SBarry Smith 
1685d3042a70SBarry Smith   PetscFunctionBegin;
168628b400f6SJacob Faibussowitsch   PetscCheck(!a->vecinuse, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Need to call MatDenseRestoreColumnVec() first");
168728b400f6SJacob Faibussowitsch   PetscCheck(!a->matinuse, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Need to call MatDenseRestoreSubMatrix() first");
1688d3042a70SBarry Smith   a->v             = a->unplacedarray;
1689d3042a70SBarry Smith   a->user_alloc    = a->unplaced_user_alloc;
1690d3042a70SBarry Smith   a->unplacedarray = NULL;
169147d993e7Ssuyashtn #if defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
1692c70f7ee4SJunchao Zhang   A->offloadmask = PETSC_OFFLOAD_CPU;
1693ca15aa20SStefano Zampini #endif
16943ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1695d3042a70SBarry Smith }
1696d3042a70SBarry Smith 
1697d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatDenseReplaceArray_SeqDense(Mat A, const PetscScalar *array)
1698d71ae5a4SJacob Faibussowitsch {
1699d5ea218eSStefano Zampini   Mat_SeqDense *a = (Mat_SeqDense *)A->data;
1700d5ea218eSStefano Zampini 
1701d5ea218eSStefano Zampini   PetscFunctionBegin;
170228b400f6SJacob Faibussowitsch   PetscCheck(!a->vecinuse, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Need to call MatDenseRestoreColumnVec() first");
170328b400f6SJacob Faibussowitsch   PetscCheck(!a->matinuse, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Need to call MatDenseRestoreSubMatrix() first");
17049566063dSJacob Faibussowitsch   if (!a->user_alloc) PetscCall(PetscFree(a->v));
1705d5ea218eSStefano Zampini   a->v          = (PetscScalar *)array;
1706d5ea218eSStefano Zampini   a->user_alloc = PETSC_FALSE;
170747d993e7Ssuyashtn #if defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
1708d5ea218eSStefano Zampini   A->offloadmask = PETSC_OFFLOAD_CPU;
1709d5ea218eSStefano Zampini #endif
17103ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1711d5ea218eSStefano Zampini }
1712d5ea218eSStefano Zampini 
1713d71ae5a4SJacob Faibussowitsch PetscErrorCode MatDestroy_SeqDense(Mat mat)
1714d71ae5a4SJacob Faibussowitsch {
1715ec8511deSBarry Smith   Mat_SeqDense *l = (Mat_SeqDense *)mat->data;
171690f02eecSBarry Smith 
17173a40ed3dSBarry Smith   PetscFunctionBegin;
17183ba16761SJacob Faibussowitsch   PetscCall(PetscLogObjectState((PetscObject)mat, "Rows %" PetscInt_FMT " Cols %" PetscInt_FMT, mat->rmap->n, mat->cmap->n));
1719f4f49eeaSPierre Jolivet   PetscCall(VecDestroy(&l->qrrhs));
17209566063dSJacob Faibussowitsch   PetscCall(PetscFree(l->tau));
17219566063dSJacob Faibussowitsch   PetscCall(PetscFree(l->pivots));
17229566063dSJacob Faibussowitsch   PetscCall(PetscFree(l->fwork));
17239566063dSJacob Faibussowitsch   if (!l->user_alloc) PetscCall(PetscFree(l->v));
17249566063dSJacob Faibussowitsch   if (!l->unplaced_user_alloc) PetscCall(PetscFree(l->unplacedarray));
172528b400f6SJacob Faibussowitsch   PetscCheck(!l->vecinuse, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Need to call MatDenseRestoreColumnVec() first");
172628b400f6SJacob Faibussowitsch   PetscCheck(!l->matinuse, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Need to call MatDenseRestoreSubMatrix() first");
17279566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&l->cvec));
17289566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&l->cmat));
17299566063dSJacob Faibussowitsch   PetscCall(PetscFree(mat->data));
1730dbd8c25aSHong Zhang 
17319566063dSJacob Faibussowitsch   PetscCall(PetscObjectChangeTypeName((PetscObject)mat, NULL));
17329566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatQRFactor_C", NULL));
17332e956fe4SStefano Zampini   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatQRFactorSymbolic_C", NULL));
17342e956fe4SStefano Zampini   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatQRFactorNumeric_C", NULL));
17359566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatDenseGetLDA_C", NULL));
17369566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatDenseSetLDA_C", NULL));
17379566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatDenseGetArray_C", NULL));
17389566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatDenseRestoreArray_C", NULL));
17399566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatDensePlaceArray_C", NULL));
17409566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatDenseResetArray_C", NULL));
17419566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatDenseReplaceArray_C", NULL));
17429566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatDenseGetArrayRead_C", NULL));
17439566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatDenseRestoreArrayRead_C", NULL));
17449566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatDenseGetArrayWrite_C", NULL));
17459566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatDenseRestoreArrayWrite_C", NULL));
17469566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatConvert_seqdense_seqaij_C", NULL));
17478baccfbdSHong Zhang #if defined(PETSC_HAVE_ELEMENTAL)
17489566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatConvert_seqdense_elemental_C", NULL));
17498baccfbdSHong Zhang #endif
1750d24d4204SJose E. Roman #if defined(PETSC_HAVE_SCALAPACK)
17519566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatConvert_seqdense_scalapack_C", NULL));
1752d24d4204SJose E. Roman #endif
17532bf066beSStefano Zampini #if defined(PETSC_HAVE_CUDA)
17549566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatConvert_seqdense_seqdensecuda_C", NULL));
17559566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatProductSetFromOptions_seqdensecuda_seqdensecuda_C", NULL));
17569566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatProductSetFromOptions_seqdensecuda_seqdense_C", NULL));
17572e956fe4SStefano Zampini   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatProductSetFromOptions_seqdense_seqdensecuda_C", NULL));
17582bf066beSStefano Zampini #endif
175947d993e7Ssuyashtn #if defined(PETSC_HAVE_HIP)
176047d993e7Ssuyashtn   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatConvert_seqdense_seqdensehip_C", NULL));
176147d993e7Ssuyashtn   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatProductSetFromOptions_seqdensehip_seqdensehip_C", NULL));
176247d993e7Ssuyashtn   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatProductSetFromOptions_seqdensehip_seqdense_C", NULL));
176347d993e7Ssuyashtn   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatProductSetFromOptions_seqdense_seqdensehip_C", NULL));
176447d993e7Ssuyashtn #endif
17659566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatSeqDenseSetPreallocation_C", NULL));
17669566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatProductSetFromOptions_seqaij_seqdense_C", NULL));
17679566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatProductSetFromOptions_seqdense_seqdense_C", NULL));
17689566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatProductSetFromOptions_seqbaij_seqdense_C", NULL));
17699566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatProductSetFromOptions_seqsbaij_seqdense_C", NULL));
177052c5f739Sprj- 
17719566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatDenseGetColumn_C", NULL));
17729566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatDenseRestoreColumn_C", NULL));
17739566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatDenseGetColumnVec_C", NULL));
17749566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatDenseRestoreColumnVec_C", NULL));
17759566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatDenseGetColumnVecRead_C", NULL));
17769566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatDenseRestoreColumnVecRead_C", NULL));
17779566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatDenseGetColumnVecWrite_C", NULL));
17789566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatDenseRestoreColumnVecWrite_C", NULL));
17799566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatDenseGetSubMatrix_C", NULL));
17809566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatDenseRestoreSubMatrix_C", NULL));
17810be0d8bdSHansol Suh   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatMultAddColumnRange_C", NULL));
17820be0d8bdSHansol Suh   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatMultHermitianTransposeColumnRange_C", NULL));
17830be0d8bdSHansol Suh   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatMultHermitianTransposeAddColumnRange_C", NULL));
17843ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1785289bc588SBarry Smith }
1786289bc588SBarry Smith 
1787d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatTranspose_SeqDense(Mat A, MatReuse reuse, Mat *matout)
1788d71ae5a4SJacob Faibussowitsch {
1789c0bbcb79SLois Curfman McInnes   Mat_SeqDense *mat = (Mat_SeqDense *)A->data;
17906536e3caSStefano Zampini   PetscInt      k, j, m = A->rmap->n, M = mat->lda, n = A->cmap->n;
179187828ca2SBarry Smith   PetscScalar  *v, tmp;
179248b35521SBarry Smith 
17933a40ed3dSBarry Smith   PetscFunctionBegin;
17947fb60732SBarry Smith   if (reuse == MAT_REUSE_MATRIX) PetscCall(MatTransposeCheckNonzeroState_Private(A, *matout));
17956536e3caSStefano Zampini   if (reuse == MAT_INPLACE_MATRIX) {
17966536e3caSStefano Zampini     if (m == n) { /* in place transpose */
17979566063dSJacob Faibussowitsch       PetscCall(MatDenseGetArray(A, &v));
1798d3e5ee88SLois Curfman McInnes       for (j = 0; j < m; j++) {
1799289bc588SBarry Smith         for (k = 0; k < j; k++) {
18001b807ce4Svictorle           tmp          = v[j + k * M];
18011b807ce4Svictorle           v[j + k * M] = v[k + j * M];
18021b807ce4Svictorle           v[k + j * M] = tmp;
1803289bc588SBarry Smith         }
1804289bc588SBarry Smith       }
18059566063dSJacob Faibussowitsch       PetscCall(MatDenseRestoreArray(A, &v));
18066536e3caSStefano Zampini     } else { /* reuse memory, temporary allocates new memory */
18076536e3caSStefano Zampini       PetscScalar *v2;
18086536e3caSStefano Zampini       PetscLayout  tmplayout;
18096536e3caSStefano Zampini 
18109566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1((size_t)m * n, &v2));
18119566063dSJacob Faibussowitsch       PetscCall(MatDenseGetArray(A, &v));
18126536e3caSStefano Zampini       for (j = 0; j < n; j++) {
18136536e3caSStefano Zampini         for (k = 0; k < m; k++) v2[j + (size_t)k * n] = v[k + (size_t)j * M];
18146536e3caSStefano Zampini       }
18159566063dSJacob Faibussowitsch       PetscCall(PetscArraycpy(v, v2, (size_t)m * n));
18169566063dSJacob Faibussowitsch       PetscCall(PetscFree(v2));
18179566063dSJacob Faibussowitsch       PetscCall(MatDenseRestoreArray(A, &v));
18186536e3caSStefano Zampini       /* cleanup size dependent quantities */
18199566063dSJacob Faibussowitsch       PetscCall(VecDestroy(&mat->cvec));
18209566063dSJacob Faibussowitsch       PetscCall(MatDestroy(&mat->cmat));
18219566063dSJacob Faibussowitsch       PetscCall(PetscFree(mat->pivots));
18229566063dSJacob Faibussowitsch       PetscCall(PetscFree(mat->fwork));
18236536e3caSStefano Zampini       /* swap row/col layouts */
18246497c311SBarry Smith       PetscCall(PetscBLASIntCast(n, &mat->lda));
18256536e3caSStefano Zampini       tmplayout = A->rmap;
18266536e3caSStefano Zampini       A->rmap   = A->cmap;
18276536e3caSStefano Zampini       A->cmap   = tmplayout;
18286536e3caSStefano Zampini     }
18293a40ed3dSBarry Smith   } else { /* out-of-place transpose */
1830d3e5ee88SLois Curfman McInnes     Mat           tmat;
1831ec8511deSBarry Smith     Mat_SeqDense *tmatd;
183287828ca2SBarry Smith     PetscScalar  *v2;
1833af36a384SStefano Zampini     PetscInt      M2;
1834ea709b57SSatish Balay 
18356536e3caSStefano Zampini     if (reuse == MAT_INITIAL_MATRIX) {
18369566063dSJacob Faibussowitsch       PetscCall(MatCreate(PetscObjectComm((PetscObject)A), &tmat));
18379566063dSJacob Faibussowitsch       PetscCall(MatSetSizes(tmat, A->cmap->n, A->rmap->n, A->cmap->n, A->rmap->n));
18389566063dSJacob Faibussowitsch       PetscCall(MatSetType(tmat, ((PetscObject)A)->type_name));
18399566063dSJacob Faibussowitsch       PetscCall(MatSeqDenseSetPreallocation(tmat, NULL));
1840ca15aa20SStefano Zampini     } else tmat = *matout;
1841ca15aa20SStefano Zampini 
18429566063dSJacob Faibussowitsch     PetscCall(MatDenseGetArrayRead(A, (const PetscScalar **)&v));
18439566063dSJacob Faibussowitsch     PetscCall(MatDenseGetArray(tmat, &v2));
1844ec8511deSBarry Smith     tmatd = (Mat_SeqDense *)tmat->data;
1845ca15aa20SStefano Zampini     M2    = tmatd->lda;
1846d3e5ee88SLois Curfman McInnes     for (j = 0; j < n; j++) {
1847af36a384SStefano Zampini       for (k = 0; k < m; k++) v2[j + k * M2] = v[k + j * M];
1848d3e5ee88SLois Curfman McInnes     }
18499566063dSJacob Faibussowitsch     PetscCall(MatDenseRestoreArray(tmat, &v2));
18509566063dSJacob Faibussowitsch     PetscCall(MatDenseRestoreArrayRead(A, (const PetscScalar **)&v));
18519566063dSJacob Faibussowitsch     PetscCall(MatAssemblyBegin(tmat, MAT_FINAL_ASSEMBLY));
18529566063dSJacob Faibussowitsch     PetscCall(MatAssemblyEnd(tmat, MAT_FINAL_ASSEMBLY));
18536536e3caSStefano Zampini     *matout = tmat;
185448b35521SBarry Smith   }
18553ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1856289bc588SBarry Smith }
1857289bc588SBarry Smith 
1858d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatEqual_SeqDense(Mat A1, Mat A2, PetscBool *flg)
1859d71ae5a4SJacob Faibussowitsch {
1860c0bbcb79SLois Curfman McInnes   Mat_SeqDense      *mat1 = (Mat_SeqDense *)A1->data;
1861c0bbcb79SLois Curfman McInnes   Mat_SeqDense      *mat2 = (Mat_SeqDense *)A2->data;
1862ca15aa20SStefano Zampini   PetscInt           i;
1863ca15aa20SStefano Zampini   const PetscScalar *v1, *v2;
18649ea5d5aeSSatish Balay 
18653a40ed3dSBarry Smith   PetscFunctionBegin;
18669371c9d4SSatish Balay   if (A1->rmap->n != A2->rmap->n) {
18679371c9d4SSatish Balay     *flg = PETSC_FALSE;
18683ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
18699371c9d4SSatish Balay   }
18709371c9d4SSatish Balay   if (A1->cmap->n != A2->cmap->n) {
18719371c9d4SSatish Balay     *flg = PETSC_FALSE;
18723ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
18739371c9d4SSatish Balay   }
18749566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArrayRead(A1, &v1));
18759566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArrayRead(A2, &v2));
1876ca15aa20SStefano Zampini   for (i = 0; i < A1->cmap->n; i++) {
18779566063dSJacob Faibussowitsch     PetscCall(PetscArraycmp(v1, v2, A1->rmap->n, flg));
18783ba16761SJacob Faibussowitsch     if (*flg == PETSC_FALSE) PetscFunctionReturn(PETSC_SUCCESS);
1879ca15aa20SStefano Zampini     v1 += mat1->lda;
1880ca15aa20SStefano Zampini     v2 += mat2->lda;
18811b807ce4Svictorle   }
18829566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArrayRead(A1, &v1));
18839566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArrayRead(A2, &v2));
188477c4ece6SBarry Smith   *flg = PETSC_TRUE;
18853ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1886289bc588SBarry Smith }
1887289bc588SBarry Smith 
188814277c92SJacob Faibussowitsch PetscErrorCode MatGetDiagonal_SeqDense(Mat A, Vec v)
1889d71ae5a4SJacob Faibussowitsch {
1890c0bbcb79SLois Curfman McInnes   Mat_SeqDense      *mat = (Mat_SeqDense *)A->data;
189113f74950SBarry Smith   PetscInt           i, n, len;
1892ca15aa20SStefano Zampini   PetscScalar       *x;
1893ca15aa20SStefano Zampini   const PetscScalar *vv;
189444cd7ae7SLois Curfman McInnes 
18953a40ed3dSBarry Smith   PetscFunctionBegin;
18969566063dSJacob Faibussowitsch   PetscCall(VecGetSize(v, &n));
18979566063dSJacob Faibussowitsch   PetscCall(VecGetArray(v, &x));
1898d0f46423SBarry Smith   len = PetscMin(A->rmap->n, A->cmap->n);
18999566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArrayRead(A, &vv));
190008401ef6SPierre Jolivet   PetscCheck(n == A->rmap->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Nonconforming mat and vec");
1901ad540459SPierre Jolivet   for (i = 0; i < len; i++) x[i] = vv[i * mat->lda + i];
19029566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArrayRead(A, &vv));
19039566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(v, &x));
19043ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1905289bc588SBarry Smith }
1906289bc588SBarry Smith 
1907d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatDiagonalScale_SeqDense(Mat A, Vec ll, Vec rr)
1908d71ae5a4SJacob Faibussowitsch {
1909c0bbcb79SLois Curfman McInnes   Mat_SeqDense      *mat = (Mat_SeqDense *)A->data;
1910f1ceaac6SMatthew G. Knepley   const PetscScalar *l, *r;
1911ca15aa20SStefano Zampini   PetscScalar        x, *v, *vv;
1912d0f46423SBarry Smith   PetscInt           i, j, m = A->rmap->n, n = A->cmap->n;
191355659b69SBarry Smith 
19143a40ed3dSBarry Smith   PetscFunctionBegin;
19159566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArray(A, &vv));
191628988994SBarry Smith   if (ll) {
19179566063dSJacob Faibussowitsch     PetscCall(VecGetSize(ll, &m));
19189566063dSJacob Faibussowitsch     PetscCall(VecGetArrayRead(ll, &l));
191908401ef6SPierre Jolivet     PetscCheck(m == A->rmap->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Left scaling vec wrong size");
1920da3a660dSBarry Smith     for (i = 0; i < m; i++) {
1921da3a660dSBarry Smith       x = l[i];
1922ca15aa20SStefano Zampini       v = vv + i;
19239371c9d4SSatish Balay       for (j = 0; j < n; j++) {
19249371c9d4SSatish Balay         (*v) *= x;
19259371c9d4SSatish Balay         v += mat->lda;
19269371c9d4SSatish Balay       }
1927da3a660dSBarry Smith     }
19289566063dSJacob Faibussowitsch     PetscCall(VecRestoreArrayRead(ll, &l));
19299566063dSJacob Faibussowitsch     PetscCall(PetscLogFlops(1.0 * n * m));
1930da3a660dSBarry Smith   }
193128988994SBarry Smith   if (rr) {
19329566063dSJacob Faibussowitsch     PetscCall(VecGetSize(rr, &n));
19339566063dSJacob Faibussowitsch     PetscCall(VecGetArrayRead(rr, &r));
193408401ef6SPierre Jolivet     PetscCheck(n == A->cmap->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Right scaling vec wrong size");
1935da3a660dSBarry Smith     for (i = 0; i < n; i++) {
1936da3a660dSBarry Smith       x = r[i];
1937ca15aa20SStefano Zampini       v = vv + i * mat->lda;
19382205254eSKarl Rupp       for (j = 0; j < m; j++) (*v++) *= x;
1939da3a660dSBarry Smith     }
19409566063dSJacob Faibussowitsch     PetscCall(VecRestoreArrayRead(rr, &r));
19419566063dSJacob Faibussowitsch     PetscCall(PetscLogFlops(1.0 * n * m));
1942da3a660dSBarry Smith   }
19439566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArray(A, &vv));
19443ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1945289bc588SBarry Smith }
1946289bc588SBarry Smith 
1947d71ae5a4SJacob Faibussowitsch PetscErrorCode MatNorm_SeqDense(Mat A, NormType type, PetscReal *nrm)
1948d71ae5a4SJacob Faibussowitsch {
1949c0bbcb79SLois Curfman McInnes   Mat_SeqDense *mat = (Mat_SeqDense *)A->data;
1950ca15aa20SStefano Zampini   PetscScalar  *v, *vv;
1951329f5518SBarry Smith   PetscReal     sum = 0.0;
195275f6d85dSStefano Zampini   PetscInt      lda, m = A->rmap->n, i, j;
195355659b69SBarry Smith 
19543a40ed3dSBarry Smith   PetscFunctionBegin;
19559566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArrayRead(A, (const PetscScalar **)&vv));
19569566063dSJacob Faibussowitsch   PetscCall(MatDenseGetLDA(A, &lda));
1957ca15aa20SStefano Zampini   v = vv;
1958289bc588SBarry Smith   if (type == NORM_FROBENIUS) {
1959a5ce6ee0Svictorle     if (lda > m) {
1960d0f46423SBarry Smith       for (j = 0; j < A->cmap->n; j++) {
1961ca15aa20SStefano Zampini         v = vv + j * lda;
1962a5ce6ee0Svictorle         for (i = 0; i < m; i++) {
19639371c9d4SSatish Balay           sum += PetscRealPart(PetscConj(*v) * (*v));
19649371c9d4SSatish Balay           v++;
1965a5ce6ee0Svictorle         }
1966a5ce6ee0Svictorle       }
1967a5ce6ee0Svictorle     } else {
1968570b7f6dSBarry Smith #if defined(PETSC_USE_REAL___FP16)
1969570b7f6dSBarry Smith       PetscBLASInt one = 1, cnt = A->cmap->n * A->rmap->n;
1970792fecdfSBarry Smith       PetscCallBLAS("BLASnrm2", *nrm = BLASnrm2_(&cnt, v, &one));
1971570b7f6dSBarry Smith     }
1972570b7f6dSBarry Smith #else
1973d0f46423SBarry Smith       for (i = 0; i < A->cmap->n * A->rmap->n; i++) {
19749371c9d4SSatish Balay         sum += PetscRealPart(PetscConj(*v) * (*v));
19759371c9d4SSatish Balay         v++;
1976289bc588SBarry Smith       }
1977a5ce6ee0Svictorle     }
19788f1a2a5eSBarry Smith     *nrm = PetscSqrtReal(sum);
1979570b7f6dSBarry Smith #endif
19809566063dSJacob Faibussowitsch     PetscCall(PetscLogFlops(2.0 * A->cmap->n * A->rmap->n));
19813a40ed3dSBarry Smith   } else if (type == NORM_1) {
1982064f8208SBarry Smith     *nrm = 0.0;
1983d0f46423SBarry Smith     for (j = 0; j < A->cmap->n; j++) {
1984ca15aa20SStefano Zampini       v   = vv + j * mat->lda;
1985289bc588SBarry Smith       sum = 0.0;
1986d0f46423SBarry Smith       for (i = 0; i < A->rmap->n; i++) {
19879371c9d4SSatish Balay         sum += PetscAbsScalar(*v);
19889371c9d4SSatish Balay         v++;
1989289bc588SBarry Smith       }
1990064f8208SBarry Smith       if (sum > *nrm) *nrm = sum;
1991289bc588SBarry Smith     }
19929566063dSJacob Faibussowitsch     PetscCall(PetscLogFlops(1.0 * A->cmap->n * A->rmap->n));
19933a40ed3dSBarry Smith   } else if (type == NORM_INFINITY) {
1994064f8208SBarry Smith     *nrm = 0.0;
1995d0f46423SBarry Smith     for (j = 0; j < A->rmap->n; j++) {
1996ca15aa20SStefano Zampini       v   = vv + j;
1997289bc588SBarry Smith       sum = 0.0;
1998d0f46423SBarry Smith       for (i = 0; i < A->cmap->n; i++) {
19999371c9d4SSatish Balay         sum += PetscAbsScalar(*v);
20009371c9d4SSatish Balay         v += mat->lda;
2001289bc588SBarry Smith       }
2002064f8208SBarry Smith       if (sum > *nrm) *nrm = sum;
2003289bc588SBarry Smith     }
20049566063dSJacob Faibussowitsch     PetscCall(PetscLogFlops(1.0 * A->cmap->n * A->rmap->n));
2005e7e72b3dSBarry Smith   } else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "No two norm");
20069566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArrayRead(A, (const PetscScalar **)&vv));
20073ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2008289bc588SBarry Smith }
2009289bc588SBarry Smith 
2010d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatSetOption_SeqDense(Mat A, MatOption op, PetscBool flg)
2011d71ae5a4SJacob Faibussowitsch {
2012c0bbcb79SLois Curfman McInnes   Mat_SeqDense *aij = (Mat_SeqDense *)A->data;
201367e560aaSBarry Smith 
20143a40ed3dSBarry Smith   PetscFunctionBegin;
2015b5a2b587SKris Buschelman   switch (op) {
2016d71ae5a4SJacob Faibussowitsch   case MAT_ROW_ORIENTED:
2017d71ae5a4SJacob Faibussowitsch     aij->roworiented = flg;
2018d71ae5a4SJacob Faibussowitsch     break;
2019512a5fc5SBarry Smith   case MAT_NEW_NONZERO_LOCATIONS:
2020b5a2b587SKris Buschelman   case MAT_NEW_NONZERO_LOCATION_ERR:
20213971808eSMatthew Knepley   case MAT_NEW_NONZERO_ALLOCATION_ERR:
20228c78258cSHong Zhang   case MAT_FORCE_DIAGONAL_ENTRIES:
202313fa8e87SLisandro Dalcin   case MAT_KEEP_NONZERO_PATTERN:
2024b5a2b587SKris Buschelman   case MAT_IGNORE_OFF_PROC_ENTRIES:
2025b5a2b587SKris Buschelman   case MAT_USE_HASH_TABLE:
20260f8fb01aSBarry Smith   case MAT_IGNORE_ZERO_ENTRIES:
20275021d80fSJed Brown   case MAT_IGNORE_LOWER_TRIANGULAR:
2028d71ae5a4SJacob Faibussowitsch   case MAT_SORTED_FULL:
2029d71ae5a4SJacob Faibussowitsch     PetscCall(PetscInfo(A, "Option %s ignored\n", MatOptions[op]));
2030d71ae5a4SJacob Faibussowitsch     break;
20315021d80fSJed Brown   case MAT_SPD:
203277e54ba9SKris Buschelman   case MAT_SYMMETRIC:
203377e54ba9SKris Buschelman   case MAT_STRUCTURALLY_SYMMETRIC:
20349a4540c5SBarry Smith   case MAT_HERMITIAN:
20359a4540c5SBarry Smith   case MAT_SYMMETRY_ETERNAL:
2036b94d7dedSBarry Smith   case MAT_STRUCTURAL_SYMMETRY_ETERNAL:
2037d71ae5a4SJacob Faibussowitsch   case MAT_SPD_ETERNAL:
2038d71ae5a4SJacob Faibussowitsch     break;
2039d71ae5a4SJacob Faibussowitsch   default:
2040d71ae5a4SJacob Faibussowitsch     SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "unknown option %s", MatOptions[op]);
20413a40ed3dSBarry Smith   }
20423ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2043289bc588SBarry Smith }
2044289bc588SBarry Smith 
2045d71ae5a4SJacob Faibussowitsch PetscErrorCode MatZeroEntries_SeqDense(Mat A)
2046d71ae5a4SJacob Faibussowitsch {
2047ec8511deSBarry Smith   Mat_SeqDense *l   = (Mat_SeqDense *)A->data;
20483d8925e7SStefano Zampini   PetscInt      lda = l->lda, m = A->rmap->n, n = A->cmap->n, j;
2049ca15aa20SStefano Zampini   PetscScalar  *v;
20503a40ed3dSBarry Smith 
20513a40ed3dSBarry Smith   PetscFunctionBegin;
20529566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArrayWrite(A, &v));
2053a5ce6ee0Svictorle   if (lda > m) {
205448a46eb9SPierre Jolivet     for (j = 0; j < n; j++) PetscCall(PetscArrayzero(v + j * lda, m));
2055a5ce6ee0Svictorle   } else {
20569566063dSJacob Faibussowitsch     PetscCall(PetscArrayzero(v, PetscInt64Mult(m, n)));
2057a5ce6ee0Svictorle   }
20589566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArrayWrite(A, &v));
20593ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
20606f0a148fSBarry Smith }
20616f0a148fSBarry Smith 
2062d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatZeroRows_SeqDense(Mat A, PetscInt N, const PetscInt rows[], PetscScalar diag, Vec x, Vec b)
2063d71ae5a4SJacob Faibussowitsch {
2064ec8511deSBarry Smith   Mat_SeqDense      *l = (Mat_SeqDense *)A->data;
2065b9679d65SBarry Smith   PetscInt           m = l->lda, n = A->cmap->n, i, j;
2066ca15aa20SStefano Zampini   PetscScalar       *slot, *bb, *v;
206797b48c8fSBarry Smith   const PetscScalar *xx;
206855659b69SBarry Smith 
20693a40ed3dSBarry Smith   PetscFunctionBegin;
207076bd3646SJed Brown   if (PetscDefined(USE_DEBUG)) {
2071b9679d65SBarry Smith     for (i = 0; i < N; i++) {
207208401ef6SPierre Jolivet       PetscCheck(rows[i] >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Negative row requested to be zeroed");
207308401ef6SPierre 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);
2074b9679d65SBarry Smith     }
207576bd3646SJed Brown   }
20763ba16761SJacob Faibussowitsch   if (!N) PetscFunctionReturn(PETSC_SUCCESS);
2077b9679d65SBarry Smith 
2078dd8e379bSPierre Jolivet   /* fix right-hand side if needed */
207997b48c8fSBarry Smith   if (x && b) {
20809566063dSJacob Faibussowitsch     PetscCall(VecGetArrayRead(x, &xx));
20819566063dSJacob Faibussowitsch     PetscCall(VecGetArray(b, &bb));
20822205254eSKarl Rupp     for (i = 0; i < N; i++) bb[rows[i]] = diag * xx[rows[i]];
20839566063dSJacob Faibussowitsch     PetscCall(VecRestoreArrayRead(x, &xx));
20849566063dSJacob Faibussowitsch     PetscCall(VecRestoreArray(b, &bb));
208597b48c8fSBarry Smith   }
208697b48c8fSBarry Smith 
20879566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArray(A, &v));
20886f0a148fSBarry Smith   for (i = 0; i < N; i++) {
2089ca15aa20SStefano Zampini     slot = v + rows[i];
20909371c9d4SSatish Balay     for (j = 0; j < n; j++) {
20919371c9d4SSatish Balay       *slot = 0.0;
20929371c9d4SSatish Balay       slot += m;
20939371c9d4SSatish Balay     }
20946f0a148fSBarry Smith   }
2095f4df32b1SMatthew Knepley   if (diag != 0.0) {
209608401ef6SPierre Jolivet     PetscCheck(A->rmap->n == A->cmap->n, PETSC_COMM_SELF, PETSC_ERR_SUP, "Only coded for square matrices");
20976f0a148fSBarry Smith     for (i = 0; i < N; i++) {
2098ca15aa20SStefano Zampini       slot  = v + (m + 1) * rows[i];
2099f4df32b1SMatthew Knepley       *slot = diag;
21006f0a148fSBarry Smith     }
21016f0a148fSBarry Smith   }
21029566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArray(A, &v));
21033ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
21046f0a148fSBarry Smith }
2105557bce09SLois Curfman McInnes 
2106d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatDenseGetLDA_SeqDense(Mat A, PetscInt *lda)
2107d71ae5a4SJacob Faibussowitsch {
210849a6ff4bSBarry Smith   Mat_SeqDense *mat = (Mat_SeqDense *)A->data;
210949a6ff4bSBarry Smith 
211049a6ff4bSBarry Smith   PetscFunctionBegin;
211149a6ff4bSBarry Smith   *lda = mat->lda;
21123ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
211349a6ff4bSBarry Smith }
211449a6ff4bSBarry Smith 
2115d71ae5a4SJacob Faibussowitsch PetscErrorCode MatDenseGetArray_SeqDense(Mat A, PetscScalar **array)
2116d71ae5a4SJacob Faibussowitsch {
2117c0bbcb79SLois Curfman McInnes   Mat_SeqDense *mat = (Mat_SeqDense *)A->data;
21183a40ed3dSBarry Smith 
21193a40ed3dSBarry Smith   PetscFunctionBegin;
212028b400f6SJacob Faibussowitsch   PetscCheck(!mat->matinuse, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Need to call MatDenseRestoreSubMatrix() first");
212164e87e97SBarry Smith   *array = mat->v;
21223ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
212364e87e97SBarry Smith }
21240754003eSLois Curfman McInnes 
2125d71ae5a4SJacob Faibussowitsch PetscErrorCode MatDenseRestoreArray_SeqDense(Mat A, PetscScalar **array)
2126d71ae5a4SJacob Faibussowitsch {
21273a40ed3dSBarry Smith   PetscFunctionBegin;
212875f6d85dSStefano Zampini   if (array) *array = NULL;
21293ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2130ff14e315SSatish Balay }
21310754003eSLois Curfman McInnes 
21320f74d2c1SSatish Balay /*@
213311a5261eSBarry Smith   MatDenseGetLDA - gets the leading dimension of the array returned from `MatDenseGetArray()`
213449a6ff4bSBarry Smith 
21352ef1f0ffSBarry Smith   Not Collective
213649a6ff4bSBarry Smith 
213749a6ff4bSBarry Smith   Input Parameter:
2138fe59aa6dSJacob Faibussowitsch . A - a `MATDENSE` or `MATDENSECUDA` matrix
213949a6ff4bSBarry Smith 
214049a6ff4bSBarry Smith   Output Parameter:
214149a6ff4bSBarry Smith . lda - the leading dimension
214249a6ff4bSBarry Smith 
214349a6ff4bSBarry Smith   Level: intermediate
214449a6ff4bSBarry Smith 
21451cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATDENSE`, `MATDENSECUDA`, `MatDenseGetArray()`, `MatDenseRestoreArray()`, `MatDenseGetArrayRead()`, `MatDenseRestoreArrayRead()`, `MatDenseSetLDA()`
214649a6ff4bSBarry Smith @*/
2147d71ae5a4SJacob Faibussowitsch PetscErrorCode MatDenseGetLDA(Mat A, PetscInt *lda)
2148d71ae5a4SJacob Faibussowitsch {
214949a6ff4bSBarry Smith   PetscFunctionBegin;
2150d5ea218eSStefano Zampini   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
21514f572ea9SToby Isaac   PetscAssertPointer(lda, 2);
215275f6d85dSStefano Zampini   MatCheckPreallocated(A, 1);
2153cac4c232SBarry Smith   PetscUseMethod(A, "MatDenseGetLDA_C", (Mat, PetscInt *), (A, lda));
21543ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
215549a6ff4bSBarry Smith }
215649a6ff4bSBarry Smith 
21570f74d2c1SSatish Balay /*@
215811a5261eSBarry Smith   MatDenseSetLDA - Sets the leading dimension of the array used by the `MATDENSE` matrix
2159ad16ce7aSStefano Zampini 
21602323109cSBarry Smith   Collective if the matrix layouts have not yet been setup
2161ad16ce7aSStefano Zampini 
2162d8d19677SJose E. Roman   Input Parameters:
2163fe59aa6dSJacob Faibussowitsch + A   - a `MATDENSE` or `MATDENSECUDA` matrix
2164ad16ce7aSStefano Zampini - lda - the leading dimension
2165ad16ce7aSStefano Zampini 
2166ad16ce7aSStefano Zampini   Level: intermediate
2167ad16ce7aSStefano Zampini 
21681cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATDENSE`, `MATDENSECUDA`, `MatDenseGetArray()`, `MatDenseRestoreArray()`, `MatDenseGetArrayRead()`, `MatDenseRestoreArrayRead()`, `MatDenseGetLDA()`
2169ad16ce7aSStefano Zampini @*/
2170d71ae5a4SJacob Faibussowitsch PetscErrorCode MatDenseSetLDA(Mat A, PetscInt lda)
2171d71ae5a4SJacob Faibussowitsch {
2172ad16ce7aSStefano Zampini   PetscFunctionBegin;
2173ad16ce7aSStefano Zampini   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
2174cac4c232SBarry Smith   PetscTryMethod(A, "MatDenseSetLDA_C", (Mat, PetscInt), (A, lda));
21753ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2176ad16ce7aSStefano Zampini }
2177ad16ce7aSStefano Zampini 
2178ad16ce7aSStefano Zampini /*@C
217911a5261eSBarry Smith   MatDenseGetArray - gives read-write access to the array where the data for a `MATDENSE` matrix is stored
218073a71a0fSBarry Smith 
2181c3339decSBarry Smith   Logically Collective
218273a71a0fSBarry Smith 
218373a71a0fSBarry Smith   Input Parameter:
2184fe59aa6dSJacob Faibussowitsch . A - a dense matrix
218573a71a0fSBarry Smith 
218673a71a0fSBarry Smith   Output Parameter:
218773a71a0fSBarry Smith . array - pointer to the data
218873a71a0fSBarry Smith 
218973a71a0fSBarry Smith   Level: intermediate
219073a71a0fSBarry Smith 
2191fe59aa6dSJacob Faibussowitsch   Fortran Notes:
21920ab4885dSBarry Smith   `MatDenseGetArray()` Fortran binding is deprecated (since PETSc 3.19), use `MatDenseGetArrayF90()`
21930ab4885dSBarry Smith 
21941cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATDENSE`, `MatDenseRestoreArray()`, `MatDenseGetArrayRead()`, `MatDenseRestoreArrayRead()`, `MatDenseGetArrayWrite()`, `MatDenseRestoreArrayWrite()`
219573a71a0fSBarry Smith @*/
21965d83a8b1SBarry Smith PetscErrorCode MatDenseGetArray(Mat A, PetscScalar *array[])
2197d71ae5a4SJacob Faibussowitsch {
219873a71a0fSBarry Smith   PetscFunctionBegin;
2199d5ea218eSStefano Zampini   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
22004f572ea9SToby Isaac   PetscAssertPointer(array, 2);
2201cac4c232SBarry Smith   PetscUseMethod(A, "MatDenseGetArray_C", (Mat, PetscScalar **), (A, array));
22023ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
220373a71a0fSBarry Smith }
220473a71a0fSBarry Smith 
2205dec5eb66SMatthew G Knepley /*@C
220611a5261eSBarry Smith   MatDenseRestoreArray - returns access to the array where the data for a `MATDENSE` matrix is stored obtained by `MatDenseGetArray()`
220773a71a0fSBarry Smith 
2208c3339decSBarry Smith   Logically Collective
22098572280aSBarry Smith 
22108572280aSBarry Smith   Input Parameters:
2211fe59aa6dSJacob Faibussowitsch + A     - a dense matrix
22122ef1f0ffSBarry Smith - array - pointer to the data (may be `NULL`)
22138572280aSBarry Smith 
22148572280aSBarry Smith   Level: intermediate
22158572280aSBarry Smith 
2216fe59aa6dSJacob Faibussowitsch   Fortran Notes:
22170ab4885dSBarry Smith   `MatDenseRestoreArray()` Fortran binding is deprecated (since PETSc 3.19), use `MatDenseRestoreArrayF90()`
22180ab4885dSBarry Smith 
22191cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATDENSE`, `MatDenseGetArray()`, `MatDenseGetArrayRead()`, `MatDenseRestoreArrayRead()`, `MatDenseGetArrayWrite()`, `MatDenseRestoreArrayWrite()`
22208572280aSBarry Smith @*/
22215d83a8b1SBarry Smith PetscErrorCode MatDenseRestoreArray(Mat A, PetscScalar *array[])
2222d71ae5a4SJacob Faibussowitsch {
22238572280aSBarry Smith   PetscFunctionBegin;
2224d5ea218eSStefano Zampini   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
22254f572ea9SToby Isaac   if (array) PetscAssertPointer(array, 2);
2226cac4c232SBarry Smith   PetscUseMethod(A, "MatDenseRestoreArray_C", (Mat, PetscScalar **), (A, array));
22279566063dSJacob Faibussowitsch   PetscCall(PetscObjectStateIncrease((PetscObject)A));
222847d993e7Ssuyashtn #if defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
2229637a0070SStefano Zampini   A->offloadmask = PETSC_OFFLOAD_CPU;
2230637a0070SStefano Zampini #endif
22313ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
22328572280aSBarry Smith }
22338572280aSBarry Smith 
22348572280aSBarry Smith /*@C
223511a5261eSBarry Smith   MatDenseGetArrayRead - gives read-only access to the array where the data for a `MATDENSE` matrix is stored
22368572280aSBarry Smith 
2237fb850c59SBarry Smith   Not Collective
22388572280aSBarry Smith 
22398572280aSBarry Smith   Input Parameter:
2240fe59aa6dSJacob Faibussowitsch . A - a dense matrix
22418572280aSBarry Smith 
22428572280aSBarry Smith   Output Parameter:
22438572280aSBarry Smith . array - pointer to the data
22448572280aSBarry Smith 
22458572280aSBarry Smith   Level: intermediate
22468572280aSBarry Smith 
22471cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATDENSE`, `MatDenseRestoreArrayRead()`, `MatDenseGetArray()`, `MatDenseRestoreArray()`, `MatDenseGetArrayWrite()`, `MatDenseRestoreArrayWrite()`
22488572280aSBarry Smith @*/
22495d83a8b1SBarry Smith PetscErrorCode MatDenseGetArrayRead(Mat A, const PetscScalar *array[])
2250d71ae5a4SJacob Faibussowitsch {
22518572280aSBarry Smith   PetscFunctionBegin;
2252d5ea218eSStefano Zampini   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
22534f572ea9SToby Isaac   PetscAssertPointer(array, 2);
22545c0db29aSPierre Jolivet   PetscUseMethod(A, "MatDenseGetArrayRead_C", (Mat, PetscScalar **), (A, (PetscScalar **)array));
22553ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
22568572280aSBarry Smith }
22578572280aSBarry Smith 
22588572280aSBarry Smith /*@C
225911a5261eSBarry Smith   MatDenseRestoreArrayRead - returns access to the array where the data for a `MATDENSE` matrix is stored obtained by `MatDenseGetArrayRead()`
22608572280aSBarry Smith 
2261fb850c59SBarry Smith   Not Collective
226273a71a0fSBarry Smith 
226373a71a0fSBarry Smith   Input Parameters:
2264fe59aa6dSJacob Faibussowitsch + A     - a dense matrix
22652ef1f0ffSBarry Smith - array - pointer to the data (may be `NULL`)
226673a71a0fSBarry Smith 
226773a71a0fSBarry Smith   Level: intermediate
226873a71a0fSBarry Smith 
22691cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATDENSE`, `MatDenseGetArrayRead()`, `MatDenseGetArray()`, `MatDenseRestoreArray()`, `MatDenseGetArrayWrite()`, `MatDenseRestoreArrayWrite()`
227073a71a0fSBarry Smith @*/
22715d83a8b1SBarry Smith PetscErrorCode MatDenseRestoreArrayRead(Mat A, const PetscScalar *array[])
2272d71ae5a4SJacob Faibussowitsch {
227373a71a0fSBarry Smith   PetscFunctionBegin;
2274d5ea218eSStefano Zampini   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
22754f572ea9SToby Isaac   if (array) PetscAssertPointer(array, 2);
22765c0db29aSPierre Jolivet   PetscUseMethod(A, "MatDenseRestoreArrayRead_C", (Mat, PetscScalar **), (A, (PetscScalar **)array));
22773ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
227873a71a0fSBarry Smith }
227973a71a0fSBarry Smith 
22806947451fSStefano Zampini /*@C
228111a5261eSBarry Smith   MatDenseGetArrayWrite - gives write-only access to the array where the data for a `MATDENSE` matrix is stored
22826947451fSStefano Zampini 
2283fb850c59SBarry Smith   Not Collective
22846947451fSStefano Zampini 
22856947451fSStefano Zampini   Input Parameter:
2286fe59aa6dSJacob Faibussowitsch . A - a dense matrix
22876947451fSStefano Zampini 
22886947451fSStefano Zampini   Output Parameter:
22896947451fSStefano Zampini . array - pointer to the data
22906947451fSStefano Zampini 
22916947451fSStefano Zampini   Level: intermediate
22926947451fSStefano Zampini 
22931cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATDENSE`, `MatDenseRestoreArrayWrite()`, `MatDenseGetArray()`, `MatDenseRestoreArray()`, `MatDenseGetArrayRead()`, `MatDenseRestoreArrayRead()`
22946947451fSStefano Zampini @*/
22955d83a8b1SBarry Smith PetscErrorCode MatDenseGetArrayWrite(Mat A, PetscScalar *array[])
2296d71ae5a4SJacob Faibussowitsch {
22976947451fSStefano Zampini   PetscFunctionBegin;
2298d5ea218eSStefano Zampini   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
22994f572ea9SToby Isaac   PetscAssertPointer(array, 2);
2300cac4c232SBarry Smith   PetscUseMethod(A, "MatDenseGetArrayWrite_C", (Mat, PetscScalar **), (A, array));
23013ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
23026947451fSStefano Zampini }
23036947451fSStefano Zampini 
23046947451fSStefano Zampini /*@C
230511a5261eSBarry Smith   MatDenseRestoreArrayWrite - returns access to the array where the data for a `MATDENSE` matrix is stored obtained by `MatDenseGetArrayWrite()`
23066947451fSStefano Zampini 
2307fb850c59SBarry Smith   Not Collective
23086947451fSStefano Zampini 
23096947451fSStefano Zampini   Input Parameters:
2310fe59aa6dSJacob Faibussowitsch + A     - a dense matrix
23112ef1f0ffSBarry Smith - array - pointer to the data (may be `NULL`)
23126947451fSStefano Zampini 
23136947451fSStefano Zampini   Level: intermediate
23146947451fSStefano Zampini 
23151cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATDENSE`, `MatDenseGetArrayWrite()`, `MatDenseGetArray()`, `MatDenseRestoreArray()`, `MatDenseGetArrayRead()`, `MatDenseRestoreArrayRead()`
23166947451fSStefano Zampini @*/
23175d83a8b1SBarry Smith PetscErrorCode MatDenseRestoreArrayWrite(Mat A, PetscScalar *array[])
2318d71ae5a4SJacob Faibussowitsch {
23196947451fSStefano Zampini   PetscFunctionBegin;
2320d5ea218eSStefano Zampini   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
23214f572ea9SToby Isaac   if (array) PetscAssertPointer(array, 2);
2322cac4c232SBarry Smith   PetscUseMethod(A, "MatDenseRestoreArrayWrite_C", (Mat, PetscScalar **), (A, array));
23239566063dSJacob Faibussowitsch   PetscCall(PetscObjectStateIncrease((PetscObject)A));
232447d993e7Ssuyashtn #if defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
23256947451fSStefano Zampini   A->offloadmask = PETSC_OFFLOAD_CPU;
23266947451fSStefano Zampini #endif
23273ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
23286947451fSStefano Zampini }
23296947451fSStefano Zampini 
2330cd3f9d89SJunchao Zhang /*@C
2331cd3f9d89SJunchao Zhang   MatDenseGetArrayAndMemType - gives read-write access to the array where the data for a `MATDENSE` matrix is stored
2332cd3f9d89SJunchao Zhang 
2333cd3f9d89SJunchao Zhang   Logically Collective
2334cd3f9d89SJunchao Zhang 
2335cd3f9d89SJunchao Zhang   Input Parameter:
2336fe59aa6dSJacob Faibussowitsch . A - a dense matrix
2337cd3f9d89SJunchao Zhang 
2338cd3f9d89SJunchao Zhang   Output Parameters:
2339cd3f9d89SJunchao Zhang + array - pointer to the data
2340cd3f9d89SJunchao Zhang - mtype - memory type of the returned pointer
2341cd3f9d89SJunchao Zhang 
2342cd3f9d89SJunchao Zhang   Level: intermediate
2343cd3f9d89SJunchao Zhang 
2344fb850c59SBarry Smith   Note:
23452ef1f0ffSBarry Smith   If the matrix is of a device type such as `MATDENSECUDA`, `MATDENSEHIP`, etc.,
23462ef1f0ffSBarry Smith   an array on device is always returned and is guaranteed to contain the matrix's latest data.
23472ef1f0ffSBarry Smith 
23481cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATDENSE`, `MatDenseRestoreArrayAndMemType()`, `MatDenseGetArrayReadAndMemType()`, `MatDenseGetArrayWriteAndMemType()`, `MatDenseGetArrayRead()`,
2349cd3f9d89SJunchao Zhang    `MatDenseRestoreArrayRead()`, `MatDenseGetArrayWrite()`, `MatDenseRestoreArrayWrite()`, `MatSeqAIJGetCSRAndMemType()`
2350cd3f9d89SJunchao Zhang @*/
23515d83a8b1SBarry Smith PetscErrorCode MatDenseGetArrayAndMemType(Mat A, PetscScalar *array[], PetscMemType *mtype)
2352cd3f9d89SJunchao Zhang {
2353cd3f9d89SJunchao Zhang   PetscBool isMPI;
2354cd3f9d89SJunchao Zhang 
2355cd3f9d89SJunchao Zhang   PetscFunctionBegin;
2356cd3f9d89SJunchao Zhang   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
23574f572ea9SToby Isaac   PetscAssertPointer(array, 2);
2358e865de01SJunchao 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 */
2359cd3f9d89SJunchao Zhang   PetscCall(PetscObjectBaseTypeCompare((PetscObject)A, MATMPIDENSE, &isMPI));
2360cd3f9d89SJunchao Zhang   if (isMPI) {
2361cd3f9d89SJunchao Zhang     /* Dispatch here so that the code can be reused for all subclasses of MATDENSE */
2362cd3f9d89SJunchao Zhang     PetscCall(MatDenseGetArrayAndMemType(((Mat_MPIDense *)A->data)->A, array, mtype));
2363cd3f9d89SJunchao Zhang   } else {
2364cd3f9d89SJunchao Zhang     PetscErrorCode (*fptr)(Mat, PetscScalar **, PetscMemType *);
23653ba16761SJacob Faibussowitsch 
23663ba16761SJacob Faibussowitsch     PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatDenseGetArrayAndMemType_C", &fptr));
2367cd3f9d89SJunchao Zhang     if (fptr) {
2368cd3f9d89SJunchao Zhang       PetscCall((*fptr)(A, array, mtype));
2369cd3f9d89SJunchao Zhang     } else {
2370cd3f9d89SJunchao Zhang       PetscUseMethod(A, "MatDenseGetArray_C", (Mat, PetscScalar **), (A, array));
2371cd3f9d89SJunchao Zhang       if (mtype) *mtype = PETSC_MEMTYPE_HOST;
2372cd3f9d89SJunchao Zhang     }
2373cd3f9d89SJunchao Zhang   }
23743ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2375cd3f9d89SJunchao Zhang }
2376cd3f9d89SJunchao Zhang 
2377cd3f9d89SJunchao Zhang /*@C
2378cd3f9d89SJunchao Zhang   MatDenseRestoreArrayAndMemType - returns access to the array that is obtained by `MatDenseGetArrayAndMemType()`
2379cd3f9d89SJunchao Zhang 
2380cd3f9d89SJunchao Zhang   Logically Collective
2381cd3f9d89SJunchao Zhang 
2382cd3f9d89SJunchao Zhang   Input Parameters:
2383fe59aa6dSJacob Faibussowitsch + A     - a dense matrix
2384cd3f9d89SJunchao Zhang - array - pointer to the data
2385cd3f9d89SJunchao Zhang 
2386cd3f9d89SJunchao Zhang   Level: intermediate
2387cd3f9d89SJunchao Zhang 
23881cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATDENSE`, `MatDenseGetArrayAndMemType()`, `MatDenseGetArray()`, `MatDenseGetArrayRead()`, `MatDenseRestoreArrayRead()`, `MatDenseGetArrayWrite()`, `MatDenseRestoreArrayWrite()`
2389cd3f9d89SJunchao Zhang @*/
23905d83a8b1SBarry Smith PetscErrorCode MatDenseRestoreArrayAndMemType(Mat A, PetscScalar *array[])
2391cd3f9d89SJunchao Zhang {
2392cd3f9d89SJunchao Zhang   PetscBool isMPI;
2393cd3f9d89SJunchao Zhang 
2394cd3f9d89SJunchao Zhang   PetscFunctionBegin;
2395cd3f9d89SJunchao Zhang   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
23964f572ea9SToby Isaac   PetscAssertPointer(array, 2);
2397cd3f9d89SJunchao Zhang   PetscCall(PetscObjectBaseTypeCompare((PetscObject)A, MATMPIDENSE, &isMPI));
2398cd3f9d89SJunchao Zhang   if (isMPI) {
2399cd3f9d89SJunchao Zhang     PetscCall(MatDenseRestoreArrayAndMemType(((Mat_MPIDense *)A->data)->A, array));
2400cd3f9d89SJunchao Zhang   } else {
2401cd3f9d89SJunchao Zhang     PetscErrorCode (*fptr)(Mat, PetscScalar **);
24023ba16761SJacob Faibussowitsch 
24033ba16761SJacob Faibussowitsch     PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatDenseRestoreArrayAndMemType_C", &fptr));
2404cd3f9d89SJunchao Zhang     if (fptr) {
2405cd3f9d89SJunchao Zhang       PetscCall((*fptr)(A, array));
2406cd3f9d89SJunchao Zhang     } else {
2407cd3f9d89SJunchao Zhang       PetscUseMethod(A, "MatDenseRestoreArray_C", (Mat, PetscScalar **), (A, array));
2408cd3f9d89SJunchao Zhang     }
2409cd3f9d89SJunchao Zhang     *array = NULL;
2410cd3f9d89SJunchao Zhang   }
2411cd3f9d89SJunchao Zhang   PetscCall(PetscObjectStateIncrease((PetscObject)A));
24123ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2413cd3f9d89SJunchao Zhang }
2414cd3f9d89SJunchao Zhang 
2415cd3f9d89SJunchao Zhang /*@C
2416cd3f9d89SJunchao Zhang   MatDenseGetArrayReadAndMemType - gives read-only access to the array where the data for a `MATDENSE` matrix is stored
2417cd3f9d89SJunchao Zhang 
2418cd3f9d89SJunchao Zhang   Logically Collective
2419cd3f9d89SJunchao Zhang 
2420cd3f9d89SJunchao Zhang   Input Parameter:
2421fe59aa6dSJacob Faibussowitsch . A - a dense matrix
2422cd3f9d89SJunchao Zhang 
2423cd3f9d89SJunchao Zhang   Output Parameters:
2424cd3f9d89SJunchao Zhang + array - pointer to the data
2425cd3f9d89SJunchao Zhang - mtype - memory type of the returned pointer
2426cd3f9d89SJunchao Zhang 
2427cd3f9d89SJunchao Zhang   Level: intermediate
2428cd3f9d89SJunchao Zhang 
2429fb850c59SBarry Smith   Note:
24302ef1f0ffSBarry Smith   If the matrix is of a device type such as `MATDENSECUDA`, `MATDENSEHIP`, etc.,
24312ef1f0ffSBarry Smith   an array on device is always returned and is guaranteed to contain the matrix's latest data.
24322ef1f0ffSBarry Smith 
24331cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATDENSE`, `MatDenseRestoreArrayReadAndMemType()`, `MatDenseGetArrayWriteAndMemType()`,
2434cd3f9d89SJunchao Zhang    `MatDenseGetArrayRead()`, `MatDenseRestoreArrayRead()`, `MatDenseGetArrayWrite()`, `MatDenseRestoreArrayWrite()`, `MatSeqAIJGetCSRAndMemType()`
2435cd3f9d89SJunchao Zhang @*/
24365d83a8b1SBarry Smith PetscErrorCode MatDenseGetArrayReadAndMemType(Mat A, const PetscScalar *array[], PetscMemType *mtype)
2437cd3f9d89SJunchao Zhang {
2438cd3f9d89SJunchao Zhang   PetscBool isMPI;
2439cd3f9d89SJunchao Zhang 
2440cd3f9d89SJunchao Zhang   PetscFunctionBegin;
2441cd3f9d89SJunchao Zhang   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
24424f572ea9SToby Isaac   PetscAssertPointer(array, 2);
2443e865de01SJunchao 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 */
2444cd3f9d89SJunchao Zhang   PetscCall(PetscObjectBaseTypeCompare((PetscObject)A, MATMPIDENSE, &isMPI));
2445cd3f9d89SJunchao Zhang   if (isMPI) { /* Dispatch here so that the code can be reused for all subclasses of MATDENSE */
2446cd3f9d89SJunchao Zhang     PetscCall(MatDenseGetArrayReadAndMemType(((Mat_MPIDense *)A->data)->A, array, mtype));
2447cd3f9d89SJunchao Zhang   } else {
2448cd3f9d89SJunchao Zhang     PetscErrorCode (*fptr)(Mat, const PetscScalar **, PetscMemType *);
24493ba16761SJacob Faibussowitsch 
24503ba16761SJacob Faibussowitsch     PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatDenseGetArrayReadAndMemType_C", &fptr));
2451cd3f9d89SJunchao Zhang     if (fptr) {
2452cd3f9d89SJunchao Zhang       PetscCall((*fptr)(A, array, mtype));
2453cd3f9d89SJunchao Zhang     } else {
24545c0db29aSPierre Jolivet       PetscUseMethod(A, "MatDenseGetArrayRead_C", (Mat, PetscScalar **), (A, (PetscScalar **)array));
2455cd3f9d89SJunchao Zhang       if (mtype) *mtype = PETSC_MEMTYPE_HOST;
2456cd3f9d89SJunchao Zhang     }
2457cd3f9d89SJunchao Zhang   }
24583ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2459cd3f9d89SJunchao Zhang }
2460cd3f9d89SJunchao Zhang 
2461cd3f9d89SJunchao Zhang /*@C
2462cd3f9d89SJunchao Zhang   MatDenseRestoreArrayReadAndMemType - returns access to the array that is obtained by `MatDenseGetArrayReadAndMemType()`
2463cd3f9d89SJunchao Zhang 
2464cd3f9d89SJunchao Zhang   Logically Collective
2465cd3f9d89SJunchao Zhang 
2466cd3f9d89SJunchao Zhang   Input Parameters:
2467fe59aa6dSJacob Faibussowitsch + A     - a dense matrix
2468cd3f9d89SJunchao Zhang - array - pointer to the data
2469cd3f9d89SJunchao Zhang 
2470cd3f9d89SJunchao Zhang   Level: intermediate
2471cd3f9d89SJunchao Zhang 
24721cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATDENSE`, `MatDenseGetArrayReadAndMemType()`, `MatDenseGetArray()`, `MatDenseGetArrayRead()`, `MatDenseRestoreArrayRead()`, `MatDenseGetArrayWrite()`, `MatDenseRestoreArrayWrite()`
2473cd3f9d89SJunchao Zhang @*/
24745d83a8b1SBarry Smith PetscErrorCode MatDenseRestoreArrayReadAndMemType(Mat A, const PetscScalar *array[])
2475cd3f9d89SJunchao Zhang {
2476cd3f9d89SJunchao Zhang   PetscBool isMPI;
2477cd3f9d89SJunchao Zhang 
2478cd3f9d89SJunchao Zhang   PetscFunctionBegin;
2479cd3f9d89SJunchao Zhang   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
24804f572ea9SToby Isaac   PetscAssertPointer(array, 2);
2481cd3f9d89SJunchao Zhang   PetscCall(PetscObjectBaseTypeCompare((PetscObject)A, MATMPIDENSE, &isMPI));
2482cd3f9d89SJunchao Zhang   if (isMPI) {
2483cd3f9d89SJunchao Zhang     PetscCall(MatDenseRestoreArrayReadAndMemType(((Mat_MPIDense *)A->data)->A, array));
2484cd3f9d89SJunchao Zhang   } else {
2485cd3f9d89SJunchao Zhang     PetscErrorCode (*fptr)(Mat, const PetscScalar **);
24863ba16761SJacob Faibussowitsch 
24873ba16761SJacob Faibussowitsch     PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatDenseRestoreArrayReadAndMemType_C", &fptr));
2488cd3f9d89SJunchao Zhang     if (fptr) {
2489cd3f9d89SJunchao Zhang       PetscCall((*fptr)(A, array));
2490cd3f9d89SJunchao Zhang     } else {
24915c0db29aSPierre Jolivet       PetscUseMethod(A, "MatDenseRestoreArrayRead_C", (Mat, PetscScalar **), (A, (PetscScalar **)array));
2492cd3f9d89SJunchao Zhang     }
2493cd3f9d89SJunchao Zhang     *array = NULL;
2494cd3f9d89SJunchao Zhang   }
24953ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2496cd3f9d89SJunchao Zhang }
2497cd3f9d89SJunchao Zhang 
2498cd3f9d89SJunchao Zhang /*@C
2499cd3f9d89SJunchao Zhang   MatDenseGetArrayWriteAndMemType - gives write-only access to the array where the data for a `MATDENSE` matrix is stored
2500cd3f9d89SJunchao Zhang 
2501cd3f9d89SJunchao Zhang   Logically Collective
2502cd3f9d89SJunchao Zhang 
2503cd3f9d89SJunchao Zhang   Input Parameter:
2504fe59aa6dSJacob Faibussowitsch . A - a dense matrix
2505cd3f9d89SJunchao Zhang 
2506cd3f9d89SJunchao Zhang   Output Parameters:
2507cd3f9d89SJunchao Zhang + array - pointer to the data
2508cd3f9d89SJunchao Zhang - mtype - memory type of the returned pointer
2509cd3f9d89SJunchao Zhang 
2510cd3f9d89SJunchao Zhang   Level: intermediate
2511cd3f9d89SJunchao Zhang 
2512fb850c59SBarry Smith   Note:
25132ef1f0ffSBarry Smith   If the matrix is of a device type such as `MATDENSECUDA`, `MATDENSEHIP`, etc.,
25142ef1f0ffSBarry Smith   an array on device is always returned and is guaranteed to contain the matrix's latest data.
25152ef1f0ffSBarry Smith 
25161cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATDENSE`, `MatDenseRestoreArrayWriteAndMemType()`, `MatDenseGetArrayReadAndMemType()`, `MatDenseGetArrayRead()`,
2517cd3f9d89SJunchao Zhang   `MatDenseRestoreArrayRead()`, `MatDenseGetArrayWrite()`, `MatDenseRestoreArrayWrite()`, `MatSeqAIJGetCSRAndMemType()`
2518cd3f9d89SJunchao Zhang @*/
25195d83a8b1SBarry Smith PetscErrorCode MatDenseGetArrayWriteAndMemType(Mat A, PetscScalar *array[], PetscMemType *mtype)
2520cd3f9d89SJunchao Zhang {
2521cd3f9d89SJunchao Zhang   PetscBool isMPI;
2522cd3f9d89SJunchao Zhang 
2523cd3f9d89SJunchao Zhang   PetscFunctionBegin;
2524cd3f9d89SJunchao Zhang   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
25254f572ea9SToby Isaac   PetscAssertPointer(array, 2);
2526e865de01SJunchao 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 */
2527cd3f9d89SJunchao Zhang   PetscCall(PetscObjectBaseTypeCompare((PetscObject)A, MATMPIDENSE, &isMPI));
2528cd3f9d89SJunchao Zhang   if (isMPI) {
2529cd3f9d89SJunchao Zhang     PetscCall(MatDenseGetArrayWriteAndMemType(((Mat_MPIDense *)A->data)->A, array, mtype));
2530cd3f9d89SJunchao Zhang   } else {
2531cd3f9d89SJunchao Zhang     PetscErrorCode (*fptr)(Mat, PetscScalar **, PetscMemType *);
25323ba16761SJacob Faibussowitsch 
25333ba16761SJacob Faibussowitsch     PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatDenseGetArrayWriteAndMemType_C", &fptr));
2534cd3f9d89SJunchao Zhang     if (fptr) {
2535cd3f9d89SJunchao Zhang       PetscCall((*fptr)(A, array, mtype));
2536cd3f9d89SJunchao Zhang     } else {
2537cd3f9d89SJunchao Zhang       PetscUseMethod(A, "MatDenseGetArrayWrite_C", (Mat, PetscScalar **), (A, array));
2538cd3f9d89SJunchao Zhang       if (mtype) *mtype = PETSC_MEMTYPE_HOST;
2539cd3f9d89SJunchao Zhang     }
2540cd3f9d89SJunchao Zhang   }
25413ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2542cd3f9d89SJunchao Zhang }
2543cd3f9d89SJunchao Zhang 
2544cd3f9d89SJunchao Zhang /*@C
2545cd3f9d89SJunchao Zhang   MatDenseRestoreArrayWriteAndMemType - returns access to the array that is obtained by `MatDenseGetArrayReadAndMemType()`
2546cd3f9d89SJunchao Zhang 
2547cd3f9d89SJunchao Zhang   Logically Collective
2548cd3f9d89SJunchao Zhang 
2549cd3f9d89SJunchao Zhang   Input Parameters:
2550fe59aa6dSJacob Faibussowitsch + A     - a dense matrix
2551cd3f9d89SJunchao Zhang - array - pointer to the data
2552cd3f9d89SJunchao Zhang 
2553cd3f9d89SJunchao Zhang   Level: intermediate
2554cd3f9d89SJunchao Zhang 
25551cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATDENSE`, `MatDenseGetArrayWriteAndMemType()`, `MatDenseGetArray()`, `MatDenseGetArrayRead()`, `MatDenseRestoreArrayRead()`, `MatDenseGetArrayWrite()`, `MatDenseRestoreArrayWrite()`
2556cd3f9d89SJunchao Zhang @*/
25575d83a8b1SBarry Smith PetscErrorCode MatDenseRestoreArrayWriteAndMemType(Mat A, PetscScalar *array[])
2558cd3f9d89SJunchao Zhang {
2559cd3f9d89SJunchao Zhang   PetscBool isMPI;
2560cd3f9d89SJunchao Zhang 
2561cd3f9d89SJunchao Zhang   PetscFunctionBegin;
2562cd3f9d89SJunchao Zhang   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
25634f572ea9SToby Isaac   PetscAssertPointer(array, 2);
2564cd3f9d89SJunchao Zhang   PetscCall(PetscObjectBaseTypeCompare((PetscObject)A, MATMPIDENSE, &isMPI));
2565cd3f9d89SJunchao Zhang   if (isMPI) {
2566cd3f9d89SJunchao Zhang     PetscCall(MatDenseRestoreArrayWriteAndMemType(((Mat_MPIDense *)A->data)->A, array));
2567cd3f9d89SJunchao Zhang   } else {
2568cd3f9d89SJunchao Zhang     PetscErrorCode (*fptr)(Mat, PetscScalar **);
25693ba16761SJacob Faibussowitsch 
25703ba16761SJacob Faibussowitsch     PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatDenseRestoreArrayWriteAndMemType_C", &fptr));
2571cd3f9d89SJunchao Zhang     if (fptr) {
2572cd3f9d89SJunchao Zhang       PetscCall((*fptr)(A, array));
2573cd3f9d89SJunchao Zhang     } else {
2574cd3f9d89SJunchao Zhang       PetscUseMethod(A, "MatDenseRestoreArrayWrite_C", (Mat, PetscScalar **), (A, array));
2575cd3f9d89SJunchao Zhang     }
2576cd3f9d89SJunchao Zhang     *array = NULL;
2577cd3f9d89SJunchao Zhang   }
2578cd3f9d89SJunchao Zhang   PetscCall(PetscObjectStateIncrease((PetscObject)A));
25793ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2580cd3f9d89SJunchao Zhang }
2581cd3f9d89SJunchao Zhang 
2582d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatCreateSubMatrix_SeqDense(Mat A, IS isrow, IS iscol, MatReuse scall, Mat *B)
2583d71ae5a4SJacob Faibussowitsch {
2584c0bbcb79SLois Curfman McInnes   Mat_SeqDense   *mat = (Mat_SeqDense *)A->data;
2585bf5a80bcSToby Isaac   PetscInt        i, j, nrows, ncols, ldb;
25865d0c19d7SBarry Smith   const PetscInt *irow, *icol;
258787828ca2SBarry Smith   PetscScalar    *av, *bv, *v = mat->v;
25880754003eSLois Curfman McInnes   Mat             newmat;
25890754003eSLois Curfman McInnes 
25903a40ed3dSBarry Smith   PetscFunctionBegin;
25919566063dSJacob Faibussowitsch   PetscCall(ISGetIndices(isrow, &irow));
25929566063dSJacob Faibussowitsch   PetscCall(ISGetIndices(iscol, &icol));
25939566063dSJacob Faibussowitsch   PetscCall(ISGetLocalSize(isrow, &nrows));
25949566063dSJacob Faibussowitsch   PetscCall(ISGetLocalSize(iscol, &ncols));
25950754003eSLois Curfman McInnes 
2596182d2002SSatish Balay   /* Check submatrixcall */
2597182d2002SSatish Balay   if (scall == MAT_REUSE_MATRIX) {
259813f74950SBarry Smith     PetscInt n_cols, n_rows;
25999566063dSJacob Faibussowitsch     PetscCall(MatGetSize(*B, &n_rows, &n_cols));
260021a2c019SBarry Smith     if (n_rows != nrows || n_cols != ncols) {
2601f746d493SDmitry Karpeev       /* resize the result matrix to match number of requested rows/columns */
26029566063dSJacob Faibussowitsch       PetscCall(MatSetSizes(*B, nrows, ncols, nrows, ncols));
260321a2c019SBarry Smith     }
2604182d2002SSatish Balay     newmat = *B;
2605182d2002SSatish Balay   } else {
26060754003eSLois Curfman McInnes     /* Create and fill new matrix */
26079566063dSJacob Faibussowitsch     PetscCall(MatCreate(PetscObjectComm((PetscObject)A), &newmat));
26089566063dSJacob Faibussowitsch     PetscCall(MatSetSizes(newmat, nrows, ncols, nrows, ncols));
26099566063dSJacob Faibussowitsch     PetscCall(MatSetType(newmat, ((PetscObject)A)->type_name));
26109566063dSJacob Faibussowitsch     PetscCall(MatSeqDenseSetPreallocation(newmat, NULL));
2611182d2002SSatish Balay   }
2612182d2002SSatish Balay 
2613182d2002SSatish Balay   /* Now extract the data pointers and do the copy,column at a time */
26149566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArray(newmat, &bv));
26159566063dSJacob Faibussowitsch   PetscCall(MatDenseGetLDA(newmat, &ldb));
2616182d2002SSatish Balay   for (i = 0; i < ncols; i++) {
26176de62eeeSBarry Smith     av = v + mat->lda * icol[i];
2618ca15aa20SStefano Zampini     for (j = 0; j < nrows; j++) bv[j] = av[irow[j]];
2619bf5a80bcSToby Isaac     bv += ldb;
26200754003eSLois Curfman McInnes   }
26219566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArray(newmat, &bv));
2622182d2002SSatish Balay 
2623182d2002SSatish Balay   /* Assemble the matrices so that the correct flags are set */
26249566063dSJacob Faibussowitsch   PetscCall(MatAssemblyBegin(newmat, MAT_FINAL_ASSEMBLY));
26259566063dSJacob Faibussowitsch   PetscCall(MatAssemblyEnd(newmat, MAT_FINAL_ASSEMBLY));
26260754003eSLois Curfman McInnes 
26270754003eSLois Curfman McInnes   /* Free work space */
26289566063dSJacob Faibussowitsch   PetscCall(ISRestoreIndices(isrow, &irow));
26299566063dSJacob Faibussowitsch   PetscCall(ISRestoreIndices(iscol, &icol));
2630182d2002SSatish Balay   *B = newmat;
26313ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
26320754003eSLois Curfman McInnes }
26330754003eSLois Curfman McInnes 
2634d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatCreateSubMatrices_SeqDense(Mat A, PetscInt n, const IS irow[], const IS icol[], MatReuse scall, Mat *B[])
2635d71ae5a4SJacob Faibussowitsch {
263613f74950SBarry Smith   PetscInt i;
2637905e6a2fSBarry Smith 
26383a40ed3dSBarry Smith   PetscFunctionBegin;
263948a46eb9SPierre Jolivet   if (scall == MAT_INITIAL_MATRIX) PetscCall(PetscCalloc1(n, B));
2640905e6a2fSBarry Smith 
264148a46eb9SPierre Jolivet   for (i = 0; i < n; i++) PetscCall(MatCreateSubMatrix_SeqDense(A, irow[i], icol[i], scall, &(*B)[i]));
26423ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2643905e6a2fSBarry Smith }
2644905e6a2fSBarry Smith 
2645d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatAssemblyBegin_SeqDense(Mat mat, MatAssemblyType mode)
2646d71ae5a4SJacob Faibussowitsch {
2647c0aa2d19SHong Zhang   PetscFunctionBegin;
26483ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2649c0aa2d19SHong Zhang }
2650c0aa2d19SHong Zhang 
2651d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatAssemblyEnd_SeqDense(Mat mat, MatAssemblyType mode)
2652d71ae5a4SJacob Faibussowitsch {
2653c0aa2d19SHong Zhang   PetscFunctionBegin;
26543ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2655c0aa2d19SHong Zhang }
2656c0aa2d19SHong Zhang 
2657d71ae5a4SJacob Faibussowitsch PetscErrorCode MatCopy_SeqDense(Mat A, Mat B, MatStructure str)
2658d71ae5a4SJacob Faibussowitsch {
26594b0e389bSBarry Smith   Mat_SeqDense      *a = (Mat_SeqDense *)A->data, *b = (Mat_SeqDense *)B->data;
2660ca15aa20SStefano Zampini   const PetscScalar *va;
2661ca15aa20SStefano Zampini   PetscScalar       *vb;
2662d0f46423SBarry Smith   PetscInt           lda1 = a->lda, lda2 = b->lda, m = A->rmap->n, n = A->cmap->n, j;
26633a40ed3dSBarry Smith 
26643a40ed3dSBarry Smith   PetscFunctionBegin;
266533f4a19fSKris Buschelman   /* If the two matrices don't have the same copy implementation, they aren't compatible for fast copy. */
266633f4a19fSKris Buschelman   if (A->ops->copy != B->ops->copy) {
26679566063dSJacob Faibussowitsch     PetscCall(MatCopy_Basic(A, B, str));
26683ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
26693a40ed3dSBarry Smith   }
2670aed4548fSBarry Smith   PetscCheck(m == B->rmap->n && n == B->cmap->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "size(B) != size(A)");
26719566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArrayRead(A, &va));
26729566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArray(B, &vb));
2673a5ce6ee0Svictorle   if (lda1 > m || lda2 > m) {
267448a46eb9SPierre Jolivet     for (j = 0; j < n; j++) PetscCall(PetscArraycpy(vb + j * lda2, va + j * lda1, m));
2675a5ce6ee0Svictorle   } else {
26769566063dSJacob Faibussowitsch     PetscCall(PetscArraycpy(vb, va, A->rmap->n * A->cmap->n));
2677a5ce6ee0Svictorle   }
26789566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArray(B, &vb));
26799566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArrayRead(A, &va));
26809566063dSJacob Faibussowitsch   PetscCall(MatAssemblyBegin(B, MAT_FINAL_ASSEMBLY));
26819566063dSJacob Faibussowitsch   PetscCall(MatAssemblyEnd(B, MAT_FINAL_ASSEMBLY));
26823ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2683273d9f13SBarry Smith }
2684273d9f13SBarry Smith 
2685d71ae5a4SJacob Faibussowitsch PetscErrorCode MatSetUp_SeqDense(Mat A)
2686d71ae5a4SJacob Faibussowitsch {
2687273d9f13SBarry Smith   PetscFunctionBegin;
26889566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetUp(A->rmap));
26899566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetUp(A->cmap));
269048a46eb9SPierre Jolivet   if (!A->preallocated) PetscCall(MatSeqDenseSetPreallocation(A, NULL));
26913ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
26924b0e389bSBarry Smith }
26934b0e389bSBarry Smith 
2694d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatConjugate_SeqDense(Mat A)
2695d71ae5a4SJacob Faibussowitsch {
26964396437dSToby Isaac   Mat_SeqDense *mat = (Mat_SeqDense *)A->data;
269706c5243aSJose E. Roman   PetscInt      i, j;
26984396437dSToby Isaac   PetscInt      min = PetscMin(A->rmap->n, A->cmap->n);
2699ca15aa20SStefano Zampini   PetscScalar  *aa;
2700ba337c44SJed Brown 
2701ba337c44SJed Brown   PetscFunctionBegin;
27029566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArray(A, &aa));
270306c5243aSJose E. Roman   for (j = 0; j < A->cmap->n; j++) {
270406c5243aSJose E. Roman     for (i = 0; i < A->rmap->n; i++) aa[i + j * mat->lda] = PetscConj(aa[i + j * mat->lda]);
270506c5243aSJose E. Roman   }
27069566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArray(A, &aa));
27079371c9d4SSatish Balay   if (mat->tau)
27089371c9d4SSatish Balay     for (i = 0; i < min; i++) mat->tau[i] = PetscConj(mat->tau[i]);
27093ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2710ba337c44SJed Brown }
2711ba337c44SJed Brown 
2712d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatRealPart_SeqDense(Mat A)
2713d71ae5a4SJacob Faibussowitsch {
271406c5243aSJose E. Roman   Mat_SeqDense *mat = (Mat_SeqDense *)A->data;
271506c5243aSJose E. Roman   PetscInt      i, j;
2716ca15aa20SStefano Zampini   PetscScalar  *aa;
2717ba337c44SJed Brown 
2718ba337c44SJed Brown   PetscFunctionBegin;
27199566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArray(A, &aa));
272006c5243aSJose E. Roman   for (j = 0; j < A->cmap->n; j++) {
272106c5243aSJose E. Roman     for (i = 0; i < A->rmap->n; i++) aa[i + j * mat->lda] = PetscRealPart(aa[i + j * mat->lda]);
272206c5243aSJose E. Roman   }
27239566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArray(A, &aa));
27243ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2725ba337c44SJed Brown }
2726ba337c44SJed Brown 
2727d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatImaginaryPart_SeqDense(Mat A)
2728d71ae5a4SJacob Faibussowitsch {
272906c5243aSJose E. Roman   Mat_SeqDense *mat = (Mat_SeqDense *)A->data;
273006c5243aSJose E. Roman   PetscInt      i, j;
2731ca15aa20SStefano Zampini   PetscScalar  *aa;
2732ba337c44SJed Brown 
2733ba337c44SJed Brown   PetscFunctionBegin;
27349566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArray(A, &aa));
273506c5243aSJose E. Roman   for (j = 0; j < A->cmap->n; j++) {
273606c5243aSJose E. Roman     for (i = 0; i < A->rmap->n; i++) aa[i + j * mat->lda] = PetscImaginaryPart(aa[i + j * mat->lda]);
273706c5243aSJose E. Roman   }
27389566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArray(A, &aa));
27393ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2740ba337c44SJed Brown }
2741284134d9SBarry Smith 
2742d71ae5a4SJacob Faibussowitsch PetscErrorCode MatMatMultSymbolic_SeqDense_SeqDense(Mat A, Mat B, PetscReal fill, Mat C)
2743d71ae5a4SJacob Faibussowitsch {
2744d0f46423SBarry Smith   PetscInt  m = A->rmap->n, n = B->cmap->n;
274547d993e7Ssuyashtn   PetscBool cisdense = PETSC_FALSE;
2746a9fe9ddaSSatish Balay 
2747ee16a9a1SHong Zhang   PetscFunctionBegin;
27489566063dSJacob Faibussowitsch   PetscCall(MatSetSizes(C, m, n, m, n));
274947d993e7Ssuyashtn #if defined(PETSC_HAVE_CUDA)
27509566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompareAny((PetscObject)C, &cisdense, MATSEQDENSE, MATSEQDENSECUDA, ""));
275147d993e7Ssuyashtn #endif
275247d993e7Ssuyashtn #if defined(PETSC_HAVE_HIP)
275347d993e7Ssuyashtn   PetscCall(PetscObjectTypeCompareAny((PetscObject)C, &cisdense, MATSEQDENSE, MATSEQDENSEHIP, ""));
275447d993e7Ssuyashtn #endif
27557a3c3d58SStefano Zampini   if (!cisdense) {
27567a3c3d58SStefano Zampini     PetscBool flg;
27577a3c3d58SStefano Zampini 
27589566063dSJacob Faibussowitsch     PetscCall(PetscObjectTypeCompare((PetscObject)B, ((PetscObject)A)->type_name, &flg));
27599566063dSJacob Faibussowitsch     PetscCall(MatSetType(C, flg ? ((PetscObject)A)->type_name : MATDENSE));
27607a3c3d58SStefano Zampini   }
27619566063dSJacob Faibussowitsch   PetscCall(MatSetUp(C));
27623ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2763ee16a9a1SHong Zhang }
2764a9fe9ddaSSatish Balay 
2765d71ae5a4SJacob Faibussowitsch PetscErrorCode MatMatMultNumeric_SeqDense_SeqDense(Mat A, Mat B, Mat C)
2766d71ae5a4SJacob Faibussowitsch {
27676718818eSStefano Zampini   Mat_SeqDense      *a = (Mat_SeqDense *)A->data, *b = (Mat_SeqDense *)B->data, *c = (Mat_SeqDense *)C->data;
27680805154bSBarry Smith   PetscBLASInt       m, n, k;
2769ca15aa20SStefano Zampini   const PetscScalar *av, *bv;
2770ca15aa20SStefano Zampini   PetscScalar       *cv;
2771a9fe9ddaSSatish Balay   PetscScalar        _DOne = 1.0, _DZero = 0.0;
2772a9fe9ddaSSatish Balay 
2773a9fe9ddaSSatish Balay   PetscFunctionBegin;
27749566063dSJacob Faibussowitsch   PetscCall(PetscBLASIntCast(C->rmap->n, &m));
27759566063dSJacob Faibussowitsch   PetscCall(PetscBLASIntCast(C->cmap->n, &n));
27769566063dSJacob Faibussowitsch   PetscCall(PetscBLASIntCast(A->cmap->n, &k));
27773ba16761SJacob Faibussowitsch   if (!m || !n || !k) PetscFunctionReturn(PETSC_SUCCESS);
27789566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArrayRead(A, &av));
27799566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArrayRead(B, &bv));
27809566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArrayWrite(C, &cv));
2781792fecdfSBarry Smith   PetscCallBLAS("BLASgemm", BLASgemm_("N", "N", &m, &n, &k, &_DOne, av, &a->lda, bv, &b->lda, &_DZero, cv, &c->lda));
27829566063dSJacob Faibussowitsch   PetscCall(PetscLogFlops(1.0 * m * n * k + 1.0 * m * n * (k - 1)));
27839566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArrayRead(A, &av));
27849566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArrayRead(B, &bv));
27859566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArrayWrite(C, &cv));
27863ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2787a9fe9ddaSSatish Balay }
2788a9fe9ddaSSatish Balay 
2789d71ae5a4SJacob Faibussowitsch PetscErrorCode MatMatTransposeMultSymbolic_SeqDense_SeqDense(Mat A, Mat B, PetscReal fill, Mat C)
2790d71ae5a4SJacob Faibussowitsch {
279169f65d41SStefano Zampini   PetscInt  m = A->rmap->n, n = B->rmap->n;
279247d993e7Ssuyashtn   PetscBool cisdense = PETSC_FALSE;
279369f65d41SStefano Zampini 
279469f65d41SStefano Zampini   PetscFunctionBegin;
27959566063dSJacob Faibussowitsch   PetscCall(MatSetSizes(C, m, n, m, n));
279647d993e7Ssuyashtn #if defined(PETSC_HAVE_CUDA)
27979566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompareAny((PetscObject)C, &cisdense, MATSEQDENSE, MATSEQDENSECUDA, ""));
279847d993e7Ssuyashtn #endif
279947d993e7Ssuyashtn #if defined(PETSC_HAVE_HIP)
280047d993e7Ssuyashtn   PetscCall(PetscObjectTypeCompareAny((PetscObject)C, &cisdense, MATSEQDENSE, MATSEQDENSEHIP, ""));
280147d993e7Ssuyashtn #endif
28027a3c3d58SStefano Zampini   if (!cisdense) {
28037a3c3d58SStefano Zampini     PetscBool flg;
28047a3c3d58SStefano Zampini 
28059566063dSJacob Faibussowitsch     PetscCall(PetscObjectTypeCompare((PetscObject)B, ((PetscObject)A)->type_name, &flg));
28069566063dSJacob Faibussowitsch     PetscCall(MatSetType(C, flg ? ((PetscObject)A)->type_name : MATDENSE));
28077a3c3d58SStefano Zampini   }
28089566063dSJacob Faibussowitsch   PetscCall(MatSetUp(C));
28093ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
281069f65d41SStefano Zampini }
281169f65d41SStefano Zampini 
2812d71ae5a4SJacob Faibussowitsch PetscErrorCode MatMatTransposeMultNumeric_SeqDense_SeqDense(Mat A, Mat B, Mat C)
2813d71ae5a4SJacob Faibussowitsch {
281469f65d41SStefano Zampini   Mat_SeqDense      *a = (Mat_SeqDense *)A->data;
281569f65d41SStefano Zampini   Mat_SeqDense      *b = (Mat_SeqDense *)B->data;
281669f65d41SStefano Zampini   Mat_SeqDense      *c = (Mat_SeqDense *)C->data;
28176718818eSStefano Zampini   const PetscScalar *av, *bv;
28186718818eSStefano Zampini   PetscScalar       *cv;
281969f65d41SStefano Zampini   PetscBLASInt       m, n, k;
282069f65d41SStefano Zampini   PetscScalar        _DOne = 1.0, _DZero = 0.0;
282169f65d41SStefano Zampini 
282269f65d41SStefano Zampini   PetscFunctionBegin;
28239566063dSJacob Faibussowitsch   PetscCall(PetscBLASIntCast(C->rmap->n, &m));
28249566063dSJacob Faibussowitsch   PetscCall(PetscBLASIntCast(C->cmap->n, &n));
28259566063dSJacob Faibussowitsch   PetscCall(PetscBLASIntCast(A->cmap->n, &k));
28263ba16761SJacob Faibussowitsch   if (!m || !n || !k) PetscFunctionReturn(PETSC_SUCCESS);
28279566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArrayRead(A, &av));
28289566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArrayRead(B, &bv));
28299566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArrayWrite(C, &cv));
2830792fecdfSBarry Smith   PetscCallBLAS("BLASgemm", BLASgemm_("N", "T", &m, &n, &k, &_DOne, av, &a->lda, bv, &b->lda, &_DZero, cv, &c->lda));
28319566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArrayRead(A, &av));
28329566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArrayRead(B, &bv));
28339566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArrayWrite(C, &cv));
28349566063dSJacob Faibussowitsch   PetscCall(PetscLogFlops(1.0 * m * n * k + 1.0 * m * n * (k - 1)));
28353ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
283669f65d41SStefano Zampini }
283769f65d41SStefano Zampini 
2838d71ae5a4SJacob Faibussowitsch PetscErrorCode MatTransposeMatMultSymbolic_SeqDense_SeqDense(Mat A, Mat B, PetscReal fill, Mat C)
2839d71ae5a4SJacob Faibussowitsch {
2840d0f46423SBarry Smith   PetscInt  m = A->cmap->n, n = B->cmap->n;
284147d993e7Ssuyashtn   PetscBool cisdense = PETSC_FALSE;
2842a9fe9ddaSSatish Balay 
2843ee16a9a1SHong Zhang   PetscFunctionBegin;
28449566063dSJacob Faibussowitsch   PetscCall(MatSetSizes(C, m, n, m, n));
284547d993e7Ssuyashtn #if defined(PETSC_HAVE_CUDA)
28469566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompareAny((PetscObject)C, &cisdense, MATSEQDENSE, MATSEQDENSECUDA, ""));
284747d993e7Ssuyashtn #endif
284847d993e7Ssuyashtn #if defined(PETSC_HAVE_HIP)
284947d993e7Ssuyashtn   PetscCall(PetscObjectTypeCompareAny((PetscObject)C, &cisdense, MATSEQDENSE, MATSEQDENSEHIP, ""));
285047d993e7Ssuyashtn #endif
28517a3c3d58SStefano Zampini   if (!cisdense) {
28527a3c3d58SStefano Zampini     PetscBool flg;
28537a3c3d58SStefano Zampini 
28549566063dSJacob Faibussowitsch     PetscCall(PetscObjectTypeCompare((PetscObject)B, ((PetscObject)A)->type_name, &flg));
28559566063dSJacob Faibussowitsch     PetscCall(MatSetType(C, flg ? ((PetscObject)A)->type_name : MATDENSE));
28567a3c3d58SStefano Zampini   }
28579566063dSJacob Faibussowitsch   PetscCall(MatSetUp(C));
28583ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2859ee16a9a1SHong Zhang }
2860a9fe9ddaSSatish Balay 
2861d71ae5a4SJacob Faibussowitsch PetscErrorCode MatTransposeMatMultNumeric_SeqDense_SeqDense(Mat A, Mat B, Mat C)
2862d71ae5a4SJacob Faibussowitsch {
2863a9fe9ddaSSatish Balay   Mat_SeqDense      *a = (Mat_SeqDense *)A->data;
2864a9fe9ddaSSatish Balay   Mat_SeqDense      *b = (Mat_SeqDense *)B->data;
2865a9fe9ddaSSatish Balay   Mat_SeqDense      *c = (Mat_SeqDense *)C->data;
28666718818eSStefano Zampini   const PetscScalar *av, *bv;
28676718818eSStefano Zampini   PetscScalar       *cv;
28680805154bSBarry Smith   PetscBLASInt       m, n, k;
2869a9fe9ddaSSatish Balay   PetscScalar        _DOne = 1.0, _DZero = 0.0;
2870a9fe9ddaSSatish Balay 
2871a9fe9ddaSSatish Balay   PetscFunctionBegin;
28729566063dSJacob Faibussowitsch   PetscCall(PetscBLASIntCast(C->rmap->n, &m));
28739566063dSJacob Faibussowitsch   PetscCall(PetscBLASIntCast(C->cmap->n, &n));
28749566063dSJacob Faibussowitsch   PetscCall(PetscBLASIntCast(A->rmap->n, &k));
28753ba16761SJacob Faibussowitsch   if (!m || !n || !k) PetscFunctionReturn(PETSC_SUCCESS);
28769566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArrayRead(A, &av));
28779566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArrayRead(B, &bv));
28789566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArrayWrite(C, &cv));
2879792fecdfSBarry Smith   PetscCallBLAS("BLASgemm", BLASgemm_("T", "N", &m, &n, &k, &_DOne, av, &a->lda, bv, &b->lda, &_DZero, cv, &c->lda));
28809566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArrayRead(A, &av));
28819566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArrayRead(B, &bv));
28829566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArrayWrite(C, &cv));
28839566063dSJacob Faibussowitsch   PetscCall(PetscLogFlops(1.0 * m * n * k + 1.0 * m * n * (k - 1)));
28843ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2885a9fe9ddaSSatish Balay }
2886985db425SBarry Smith 
2887d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatProductSetFromOptions_SeqDense_AB(Mat C)
2888d71ae5a4SJacob Faibussowitsch {
28894222ddf1SHong Zhang   PetscFunctionBegin;
28904222ddf1SHong Zhang   C->ops->matmultsymbolic = MatMatMultSymbolic_SeqDense_SeqDense;
28914222ddf1SHong Zhang   C->ops->productsymbolic = MatProductSymbolic_AB;
28923ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
28934222ddf1SHong Zhang }
28944222ddf1SHong Zhang 
2895d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatProductSetFromOptions_SeqDense_AtB(Mat C)
2896d71ae5a4SJacob Faibussowitsch {
28974222ddf1SHong Zhang   PetscFunctionBegin;
28984222ddf1SHong Zhang   C->ops->transposematmultsymbolic = MatTransposeMatMultSymbolic_SeqDense_SeqDense;
28994222ddf1SHong Zhang   C->ops->productsymbolic          = MatProductSymbolic_AtB;
29003ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
29014222ddf1SHong Zhang }
29024222ddf1SHong Zhang 
2903d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatProductSetFromOptions_SeqDense_ABt(Mat C)
2904d71ae5a4SJacob Faibussowitsch {
29054222ddf1SHong Zhang   PetscFunctionBegin;
29064222ddf1SHong Zhang   C->ops->mattransposemultsymbolic = MatMatTransposeMultSymbolic_SeqDense_SeqDense;
29074222ddf1SHong Zhang   C->ops->productsymbolic          = MatProductSymbolic_ABt;
29083ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
29094222ddf1SHong Zhang }
29104222ddf1SHong Zhang 
2911d71ae5a4SJacob Faibussowitsch PETSC_INTERN PetscErrorCode MatProductSetFromOptions_SeqDense(Mat C)
2912d71ae5a4SJacob Faibussowitsch {
29134222ddf1SHong Zhang   Mat_Product *product = C->product;
29144222ddf1SHong Zhang 
29154222ddf1SHong Zhang   PetscFunctionBegin;
29164222ddf1SHong Zhang   switch (product->type) {
2917d71ae5a4SJacob Faibussowitsch   case MATPRODUCT_AB:
2918d71ae5a4SJacob Faibussowitsch     PetscCall(MatProductSetFromOptions_SeqDense_AB(C));
2919d71ae5a4SJacob Faibussowitsch     break;
2920d71ae5a4SJacob Faibussowitsch   case MATPRODUCT_AtB:
2921d71ae5a4SJacob Faibussowitsch     PetscCall(MatProductSetFromOptions_SeqDense_AtB(C));
2922d71ae5a4SJacob Faibussowitsch     break;
2923d71ae5a4SJacob Faibussowitsch   case MATPRODUCT_ABt:
2924d71ae5a4SJacob Faibussowitsch     PetscCall(MatProductSetFromOptions_SeqDense_ABt(C));
2925d71ae5a4SJacob Faibussowitsch     break;
2926d71ae5a4SJacob Faibussowitsch   default:
2927d71ae5a4SJacob Faibussowitsch     break;
29284222ddf1SHong Zhang   }
29293ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
29304222ddf1SHong Zhang }
29314222ddf1SHong Zhang 
2932d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatGetRowMax_SeqDense(Mat A, Vec v, PetscInt idx[])
2933d71ae5a4SJacob Faibussowitsch {
2934985db425SBarry Smith   Mat_SeqDense      *a = (Mat_SeqDense *)A->data;
2935d0f46423SBarry Smith   PetscInt           i, j, m = A->rmap->n, n = A->cmap->n, p;
2936985db425SBarry Smith   PetscScalar       *x;
2937ca15aa20SStefano Zampini   const PetscScalar *aa;
2938985db425SBarry Smith 
2939985db425SBarry Smith   PetscFunctionBegin;
294028b400f6SJacob Faibussowitsch   PetscCheck(!A->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
29419566063dSJacob Faibussowitsch   PetscCall(VecGetArray(v, &x));
29429566063dSJacob Faibussowitsch   PetscCall(VecGetLocalSize(v, &p));
29439566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArrayRead(A, &aa));
294408401ef6SPierre Jolivet   PetscCheck(p == A->rmap->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Nonconforming matrix and vector");
2945985db425SBarry Smith   for (i = 0; i < m; i++) {
29469371c9d4SSatish Balay     x[i] = aa[i];
29479371c9d4SSatish Balay     if (idx) idx[i] = 0;
2948985db425SBarry Smith     for (j = 1; j < n; j++) {
29499371c9d4SSatish Balay       if (PetscRealPart(x[i]) < PetscRealPart(aa[i + a->lda * j])) {
29509371c9d4SSatish Balay         x[i] = aa[i + a->lda * j];
29519371c9d4SSatish Balay         if (idx) idx[i] = j;
29529371c9d4SSatish Balay       }
2953985db425SBarry Smith     }
2954985db425SBarry Smith   }
29559566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArrayRead(A, &aa));
29569566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(v, &x));
29573ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2958985db425SBarry Smith }
2959985db425SBarry Smith 
2960d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatGetRowMaxAbs_SeqDense(Mat A, Vec v, PetscInt idx[])
2961d71ae5a4SJacob Faibussowitsch {
2962985db425SBarry Smith   Mat_SeqDense      *a = (Mat_SeqDense *)A->data;
2963d0f46423SBarry Smith   PetscInt           i, j, m = A->rmap->n, n = A->cmap->n, p;
2964985db425SBarry Smith   PetscScalar       *x;
2965985db425SBarry Smith   PetscReal          atmp;
2966ca15aa20SStefano Zampini   const PetscScalar *aa;
2967985db425SBarry Smith 
2968985db425SBarry Smith   PetscFunctionBegin;
296928b400f6SJacob Faibussowitsch   PetscCheck(!A->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
29709566063dSJacob Faibussowitsch   PetscCall(VecGetArray(v, &x));
29719566063dSJacob Faibussowitsch   PetscCall(VecGetLocalSize(v, &p));
29729566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArrayRead(A, &aa));
297308401ef6SPierre Jolivet   PetscCheck(p == A->rmap->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Nonconforming matrix and vector");
2974985db425SBarry Smith   for (i = 0; i < m; i++) {
29759189402eSHong Zhang     x[i] = PetscAbsScalar(aa[i]);
2976985db425SBarry Smith     for (j = 1; j < n; j++) {
2977ca15aa20SStefano Zampini       atmp = PetscAbsScalar(aa[i + a->lda * j]);
29789371c9d4SSatish Balay       if (PetscAbsScalar(x[i]) < atmp) {
29799371c9d4SSatish Balay         x[i] = atmp;
29809371c9d4SSatish Balay         if (idx) idx[i] = j;
29819371c9d4SSatish Balay       }
2982985db425SBarry Smith     }
2983985db425SBarry Smith   }
29849566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArrayRead(A, &aa));
29859566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(v, &x));
29863ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2987985db425SBarry Smith }
2988985db425SBarry Smith 
2989d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatGetRowMin_SeqDense(Mat A, Vec v, PetscInt idx[])
2990d71ae5a4SJacob Faibussowitsch {
2991985db425SBarry Smith   Mat_SeqDense      *a = (Mat_SeqDense *)A->data;
2992d0f46423SBarry Smith   PetscInt           i, j, m = A->rmap->n, n = A->cmap->n, p;
2993985db425SBarry Smith   PetscScalar       *x;
2994ca15aa20SStefano Zampini   const PetscScalar *aa;
2995985db425SBarry Smith 
2996985db425SBarry Smith   PetscFunctionBegin;
299728b400f6SJacob Faibussowitsch   PetscCheck(!A->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
29989566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArrayRead(A, &aa));
29999566063dSJacob Faibussowitsch   PetscCall(VecGetArray(v, &x));
30009566063dSJacob Faibussowitsch   PetscCall(VecGetLocalSize(v, &p));
300108401ef6SPierre Jolivet   PetscCheck(p == A->rmap->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Nonconforming matrix and vector");
3002985db425SBarry Smith   for (i = 0; i < m; i++) {
30039371c9d4SSatish Balay     x[i] = aa[i];
30049371c9d4SSatish Balay     if (idx) idx[i] = 0;
3005985db425SBarry Smith     for (j = 1; j < n; j++) {
30069371c9d4SSatish Balay       if (PetscRealPart(x[i]) > PetscRealPart(aa[i + a->lda * j])) {
30079371c9d4SSatish Balay         x[i] = aa[i + a->lda * j];
30089371c9d4SSatish Balay         if (idx) idx[i] = j;
30099371c9d4SSatish Balay       }
3010985db425SBarry Smith     }
3011985db425SBarry Smith   }
30129566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(v, &x));
30139566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArrayRead(A, &aa));
30143ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3015985db425SBarry Smith }
3016985db425SBarry Smith 
3017d71ae5a4SJacob Faibussowitsch PetscErrorCode MatGetColumnVector_SeqDense(Mat A, Vec v, PetscInt col)
3018d71ae5a4SJacob Faibussowitsch {
30198d0534beSBarry Smith   Mat_SeqDense      *a = (Mat_SeqDense *)A->data;
30208d0534beSBarry Smith   PetscScalar       *x;
3021ca15aa20SStefano Zampini   const PetscScalar *aa;
30228d0534beSBarry Smith 
30238d0534beSBarry Smith   PetscFunctionBegin;
302428b400f6SJacob Faibussowitsch   PetscCheck(!A->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
30259566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArrayRead(A, &aa));
30269566063dSJacob Faibussowitsch   PetscCall(VecGetArray(v, &x));
30279566063dSJacob Faibussowitsch   PetscCall(PetscArraycpy(x, aa + col * a->lda, A->rmap->n));
30289566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(v, &x));
30299566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArrayRead(A, &aa));
30303ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
30318d0534beSBarry Smith }
30328d0534beSBarry Smith 
3033d71ae5a4SJacob Faibussowitsch PETSC_INTERN PetscErrorCode MatGetColumnReductions_SeqDense(Mat A, PetscInt type, PetscReal *reductions)
3034d71ae5a4SJacob Faibussowitsch {
30350716a85fSBarry Smith   PetscInt           i, j, m, n;
30361683a169SBarry Smith   const PetscScalar *a;
30370716a85fSBarry Smith 
30380716a85fSBarry Smith   PetscFunctionBegin;
30399566063dSJacob Faibussowitsch   PetscCall(MatGetSize(A, &m, &n));
30409566063dSJacob Faibussowitsch   PetscCall(PetscArrayzero(reductions, n));
30419566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArrayRead(A, &a));
3042857cbf51SRichard Tran Mills   if (type == NORM_2) {
30430716a85fSBarry Smith     for (i = 0; i < n; i++) {
3044ad540459SPierre Jolivet       for (j = 0; j < m; j++) reductions[i] += PetscAbsScalar(a[j] * a[j]);
304516cd844bSPierre Jolivet       a = PetscSafePointerPlusOffset(a, m);
30460716a85fSBarry Smith     }
3047857cbf51SRichard Tran Mills   } else if (type == NORM_1) {
30480716a85fSBarry Smith     for (i = 0; i < n; i++) {
3049ad540459SPierre Jolivet       for (j = 0; j < m; j++) reductions[i] += PetscAbsScalar(a[j]);
305016cd844bSPierre Jolivet       a = PetscSafePointerPlusOffset(a, m);
30510716a85fSBarry Smith     }
3052857cbf51SRichard Tran Mills   } else if (type == NORM_INFINITY) {
30530716a85fSBarry Smith     for (i = 0; i < n; i++) {
3054ad540459SPierre Jolivet       for (j = 0; j < m; j++) reductions[i] = PetscMax(PetscAbsScalar(a[j]), reductions[i]);
305516cd844bSPierre Jolivet       a = PetscSafePointerPlusOffset(a, m);
30560716a85fSBarry Smith     }
3057857cbf51SRichard Tran Mills   } else if (type == REDUCTION_SUM_REALPART || type == REDUCTION_MEAN_REALPART) {
3058a873a8cdSSam Reynolds     for (i = 0; i < n; i++) {
3059ad540459SPierre Jolivet       for (j = 0; j < m; j++) reductions[i] += PetscRealPart(a[j]);
306016cd844bSPierre Jolivet       a = PetscSafePointerPlusOffset(a, m);
3061a873a8cdSSam Reynolds     }
3062857cbf51SRichard Tran Mills   } else if (type == REDUCTION_SUM_IMAGINARYPART || type == REDUCTION_MEAN_IMAGINARYPART) {
3063857cbf51SRichard Tran Mills     for (i = 0; i < n; i++) {
3064ad540459SPierre Jolivet       for (j = 0; j < m; j++) reductions[i] += PetscImaginaryPart(a[j]);
306516cd844bSPierre Jolivet       a = PetscSafePointerPlusOffset(a, m);
3066857cbf51SRichard Tran Mills     }
3067857cbf51SRichard Tran Mills   } else SETERRQ(PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONG, "Unknown reduction type");
30689566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArrayRead(A, &a));
3069857cbf51SRichard Tran Mills   if (type == NORM_2) {
3070a873a8cdSSam Reynolds     for (i = 0; i < n; i++) reductions[i] = PetscSqrtReal(reductions[i]);
3071857cbf51SRichard Tran Mills   } else if (type == REDUCTION_MEAN_REALPART || type == REDUCTION_MEAN_IMAGINARYPART) {
3072a873a8cdSSam Reynolds     for (i = 0; i < n; i++) reductions[i] /= m;
30730716a85fSBarry Smith   }
30743ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
30750716a85fSBarry Smith }
30760716a85fSBarry Smith 
3077d71ae5a4SJacob Faibussowitsch PetscErrorCode MatSetRandom_SeqDense(Mat x, PetscRandom rctx)
3078d71ae5a4SJacob Faibussowitsch {
307973a71a0fSBarry Smith   PetscScalar *a;
3080637a0070SStefano Zampini   PetscInt     lda, m, n, i, j;
308173a71a0fSBarry Smith 
308273a71a0fSBarry Smith   PetscFunctionBegin;
30839566063dSJacob Faibussowitsch   PetscCall(MatGetSize(x, &m, &n));
30849566063dSJacob Faibussowitsch   PetscCall(MatDenseGetLDA(x, &lda));
30853faff063SStefano Zampini   PetscCall(MatDenseGetArrayWrite(x, &a));
3086637a0070SStefano Zampini   for (j = 0; j < n; j++) {
308748a46eb9SPierre Jolivet     for (i = 0; i < m; i++) PetscCall(PetscRandomGetValue(rctx, a + j * lda + i));
308873a71a0fSBarry Smith   }
30893faff063SStefano Zampini   PetscCall(MatDenseRestoreArrayWrite(x, &a));
30903ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
309173a71a0fSBarry Smith }
309273a71a0fSBarry Smith 
3093d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatMissingDiagonal_SeqDense(Mat A, PetscBool *missing, PetscInt *d)
3094d71ae5a4SJacob Faibussowitsch {
30953b49f96aSBarry Smith   PetscFunctionBegin;
30963b49f96aSBarry Smith   *missing = PETSC_FALSE;
30973ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
30983b49f96aSBarry Smith }
309973a71a0fSBarry Smith 
3100ca15aa20SStefano Zampini /* vals is not const */
3101d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatDenseGetColumn_SeqDense(Mat A, PetscInt col, PetscScalar **vals)
3102d71ae5a4SJacob Faibussowitsch {
310386aefd0dSHong Zhang   Mat_SeqDense *a = (Mat_SeqDense *)A->data;
3104ca15aa20SStefano Zampini   PetscScalar  *v;
310586aefd0dSHong Zhang 
310686aefd0dSHong Zhang   PetscFunctionBegin;
310728b400f6SJacob Faibussowitsch   PetscCheck(!A->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
31089566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArray(A, &v));
3109ca15aa20SStefano Zampini   *vals = v + col * a->lda;
31109566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArray(A, &v));
31113ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
311286aefd0dSHong Zhang }
311386aefd0dSHong Zhang 
3114d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatDenseRestoreColumn_SeqDense(Mat A, PetscScalar **vals)
3115d71ae5a4SJacob Faibussowitsch {
311686aefd0dSHong Zhang   PetscFunctionBegin;
3117742765d3SMatthew Knepley   if (vals) *vals = NULL; /* user cannot accidentally use the array later */
31183ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
311986aefd0dSHong Zhang }
3120abc3b08eSStefano Zampini 
3121a5ae1ecdSBarry Smith static struct _MatOps MatOps_Values = {MatSetValues_SeqDense,
3122905e6a2fSBarry Smith                                        MatGetRow_SeqDense,
3123905e6a2fSBarry Smith                                        MatRestoreRow_SeqDense,
3124905e6a2fSBarry Smith                                        MatMult_SeqDense,
312597304618SKris Buschelman                                        /*  4*/ MatMultAdd_SeqDense,
31267c922b88SBarry Smith                                        MatMultTranspose_SeqDense,
31277c922b88SBarry Smith                                        MatMultTransposeAdd_SeqDense,
3128f4259b30SLisandro Dalcin                                        NULL,
3129f4259b30SLisandro Dalcin                                        NULL,
3130f4259b30SLisandro Dalcin                                        NULL,
3131f4259b30SLisandro Dalcin                                        /* 10*/ NULL,
3132905e6a2fSBarry Smith                                        MatLUFactor_SeqDense,
3133905e6a2fSBarry Smith                                        MatCholeskyFactor_SeqDense,
313441f059aeSBarry Smith                                        MatSOR_SeqDense,
3135ec8511deSBarry Smith                                        MatTranspose_SeqDense,
313697304618SKris Buschelman                                        /* 15*/ MatGetInfo_SeqDense,
3137905e6a2fSBarry Smith                                        MatEqual_SeqDense,
3138905e6a2fSBarry Smith                                        MatGetDiagonal_SeqDense,
3139905e6a2fSBarry Smith                                        MatDiagonalScale_SeqDense,
3140905e6a2fSBarry Smith                                        MatNorm_SeqDense,
3141c0aa2d19SHong Zhang                                        /* 20*/ MatAssemblyBegin_SeqDense,
3142c0aa2d19SHong Zhang                                        MatAssemblyEnd_SeqDense,
3143905e6a2fSBarry Smith                                        MatSetOption_SeqDense,
3144905e6a2fSBarry Smith                                        MatZeroEntries_SeqDense,
3145d519adbfSMatthew Knepley                                        /* 24*/ MatZeroRows_SeqDense,
3146f4259b30SLisandro Dalcin                                        NULL,
3147f4259b30SLisandro Dalcin                                        NULL,
3148f4259b30SLisandro Dalcin                                        NULL,
3149f4259b30SLisandro Dalcin                                        NULL,
31504994cf47SJed Brown                                        /* 29*/ MatSetUp_SeqDense,
3151f4259b30SLisandro Dalcin                                        NULL,
3152f4259b30SLisandro Dalcin                                        NULL,
3153f4259b30SLisandro Dalcin                                        NULL,
3154f4259b30SLisandro Dalcin                                        NULL,
3155d519adbfSMatthew Knepley                                        /* 34*/ MatDuplicate_SeqDense,
3156f4259b30SLisandro Dalcin                                        NULL,
3157f4259b30SLisandro Dalcin                                        NULL,
3158f4259b30SLisandro Dalcin                                        NULL,
3159f4259b30SLisandro Dalcin                                        NULL,
3160d519adbfSMatthew Knepley                                        /* 39*/ MatAXPY_SeqDense,
31617dae84e0SHong Zhang                                        MatCreateSubMatrices_SeqDense,
3162f4259b30SLisandro Dalcin                                        NULL,
31634b0e389bSBarry Smith                                        MatGetValues_SeqDense,
3164a5ae1ecdSBarry Smith                                        MatCopy_SeqDense,
3165d519adbfSMatthew Knepley                                        /* 44*/ MatGetRowMax_SeqDense,
3166a5ae1ecdSBarry Smith                                        MatScale_SeqDense,
31672f605a99SJose E. Roman                                        MatShift_SeqDense,
3168f4259b30SLisandro Dalcin                                        NULL,
31693f49a652SStefano Zampini                                        MatZeroRowsColumns_SeqDense,
317073a71a0fSBarry Smith                                        /* 49*/ MatSetRandom_SeqDense,
3171f4259b30SLisandro Dalcin                                        NULL,
3172f4259b30SLisandro Dalcin                                        NULL,
3173f4259b30SLisandro Dalcin                                        NULL,
3174f4259b30SLisandro Dalcin                                        NULL,
3175f4259b30SLisandro Dalcin                                        /* 54*/ NULL,
3176f4259b30SLisandro Dalcin                                        NULL,
3177f4259b30SLisandro Dalcin                                        NULL,
3178f4259b30SLisandro Dalcin                                        NULL,
3179f4259b30SLisandro Dalcin                                        NULL,
3180023c16fcSToby Isaac                                        /* 59*/ MatCreateSubMatrix_SeqDense,
3181e03a110bSBarry Smith                                        MatDestroy_SeqDense,
3182e03a110bSBarry Smith                                        MatView_SeqDense,
3183f4259b30SLisandro Dalcin                                        NULL,
3184f4259b30SLisandro Dalcin                                        NULL,
3185f4259b30SLisandro Dalcin                                        /* 64*/ NULL,
3186f4259b30SLisandro Dalcin                                        NULL,
3187f4259b30SLisandro Dalcin                                        NULL,
3188f4259b30SLisandro Dalcin                                        NULL,
3189f4259b30SLisandro Dalcin                                        NULL,
3190d519adbfSMatthew Knepley                                        /* 69*/ MatGetRowMaxAbs_SeqDense,
3191f4259b30SLisandro Dalcin                                        NULL,
3192f4259b30SLisandro Dalcin                                        NULL,
3193f4259b30SLisandro Dalcin                                        NULL,
3194f4259b30SLisandro Dalcin                                        NULL,
3195f4259b30SLisandro Dalcin                                        /* 74*/ NULL,
3196f4259b30SLisandro Dalcin                                        NULL,
3197f4259b30SLisandro Dalcin                                        NULL,
3198f4259b30SLisandro Dalcin                                        NULL,
3199f4259b30SLisandro Dalcin                                        NULL,
3200f4259b30SLisandro Dalcin                                        /* 79*/ NULL,
3201f4259b30SLisandro Dalcin                                        NULL,
3202f4259b30SLisandro Dalcin                                        NULL,
3203f4259b30SLisandro Dalcin                                        NULL,
32045bba2384SShri Abhyankar                                        /* 83*/ MatLoad_SeqDense,
3205637a0070SStefano Zampini                                        MatIsSymmetric_SeqDense,
32061cbb95d3SBarry Smith                                        MatIsHermitian_SeqDense,
3207f4259b30SLisandro Dalcin                                        NULL,
3208f4259b30SLisandro Dalcin                                        NULL,
3209f4259b30SLisandro Dalcin                                        NULL,
3210f4259b30SLisandro Dalcin                                        /* 89*/ NULL,
3211f4259b30SLisandro Dalcin                                        NULL,
3212a9fe9ddaSSatish Balay                                        MatMatMultNumeric_SeqDense_SeqDense,
3213f4259b30SLisandro Dalcin                                        NULL,
3214f4259b30SLisandro Dalcin                                        NULL,
3215f4259b30SLisandro Dalcin                                        /* 94*/ NULL,
3216f4259b30SLisandro Dalcin                                        NULL,
3217f4259b30SLisandro Dalcin                                        NULL,
321869f65d41SStefano Zampini                                        MatMatTransposeMultNumeric_SeqDense_SeqDense,
3219f4259b30SLisandro Dalcin                                        NULL,
32204222ddf1SHong Zhang                                        /* 99*/ MatProductSetFromOptions_SeqDense,
3221f4259b30SLisandro Dalcin                                        NULL,
3222f4259b30SLisandro Dalcin                                        NULL,
3223ba337c44SJed Brown                                        MatConjugate_SeqDense,
3224f4259b30SLisandro Dalcin                                        NULL,
3225f4259b30SLisandro Dalcin                                        /*104*/ NULL,
3226ba337c44SJed Brown                                        MatRealPart_SeqDense,
3227ba337c44SJed Brown                                        MatImaginaryPart_SeqDense,
3228f4259b30SLisandro Dalcin                                        NULL,
3229f4259b30SLisandro Dalcin                                        NULL,
3230f4259b30SLisandro Dalcin                                        /*109*/ NULL,
3231f4259b30SLisandro Dalcin                                        NULL,
32328d0534beSBarry Smith                                        MatGetRowMin_SeqDense,
3233aabbc4fbSShri Abhyankar                                        MatGetColumnVector_SeqDense,
32343b49f96aSBarry Smith                                        MatMissingDiagonal_SeqDense,
3235f4259b30SLisandro Dalcin                                        /*114*/ NULL,
3236f4259b30SLisandro Dalcin                                        NULL,
3237f4259b30SLisandro Dalcin                                        NULL,
3238f4259b30SLisandro Dalcin                                        NULL,
3239f4259b30SLisandro Dalcin                                        NULL,
3240f4259b30SLisandro Dalcin                                        /*119*/ NULL,
3241f4259b30SLisandro Dalcin                                        NULL,
3242459e8d23SBlanca Mellado Pinto                                        MatMultHermitianTranspose_SeqDense,
3243459e8d23SBlanca Mellado Pinto                                        MatMultHermitianTransposeAdd_SeqDense,
3244f4259b30SLisandro Dalcin                                        NULL,
3245f4259b30SLisandro Dalcin                                        /*124*/ NULL,
3246a873a8cdSSam Reynolds                                        MatGetColumnReductions_SeqDense,
3247f4259b30SLisandro Dalcin                                        NULL,
3248f4259b30SLisandro Dalcin                                        NULL,
3249f4259b30SLisandro Dalcin                                        NULL,
3250f4259b30SLisandro Dalcin                                        /*129*/ NULL,
3251f4259b30SLisandro Dalcin                                        NULL,
3252f4259b30SLisandro Dalcin                                        NULL,
325375648e8dSHong Zhang                                        MatTransposeMatMultNumeric_SeqDense_SeqDense,
3254f4259b30SLisandro Dalcin                                        NULL,
3255f4259b30SLisandro Dalcin                                        /*134*/ NULL,
3256f4259b30SLisandro Dalcin                                        NULL,
3257f4259b30SLisandro Dalcin                                        NULL,
3258f4259b30SLisandro Dalcin                                        NULL,
3259f4259b30SLisandro Dalcin                                        NULL,
3260f4259b30SLisandro Dalcin                                        /*139*/ NULL,
3261f4259b30SLisandro Dalcin                                        NULL,
3262f4259b30SLisandro Dalcin                                        NULL,
3263f4259b30SLisandro Dalcin                                        NULL,
3264f4259b30SLisandro Dalcin                                        NULL,
32654222ddf1SHong Zhang                                        MatCreateMPIMatConcatenateSeqMat_SeqDense,
3266f4259b30SLisandro Dalcin                                        /*145*/ NULL,
3267f4259b30SLisandro Dalcin                                        NULL,
326899a7f59eSMark Adams                                        NULL,
326999a7f59eSMark Adams                                        NULL,
32707fb60732SBarry Smith                                        NULL,
3271dec0b466SHong Zhang                                        /*150*/ NULL,
3272eede4a3fSMark Adams                                        NULL,
32734cc2b5b5SPierre Jolivet                                        NULL,
327442ce410bSJunchao Zhang                                        NULL,
327542ce410bSJunchao Zhang                                        NULL,
3276dec0b466SHong Zhang                                        NULL};
327790ace30eSBarry Smith 
32785d83a8b1SBarry Smith /*@
327911a5261eSBarry Smith   MatCreateSeqDense - Creates a `MATSEQDENSE` that
3280fb850c59SBarry Smith   is stored in column major order (the usual Fortran format).
3281289bc588SBarry Smith 
3282d083f849SBarry Smith   Collective
3283db81eaa0SLois Curfman McInnes 
328420563c6bSBarry Smith   Input Parameters:
328511a5261eSBarry Smith + comm - MPI communicator, set to `PETSC_COMM_SELF`
32860c775827SLois Curfman McInnes . m    - number of rows
328718f449edSLois Curfman McInnes . n    - number of columns
32882ef1f0ffSBarry Smith - data - optional location of matrix data in column major order.  Use `NULL` for PETSc
3289dfc5480cSLois Curfman McInnes          to control all matrix memory allocation.
329020563c6bSBarry Smith 
329120563c6bSBarry Smith   Output Parameter:
329244cd7ae7SLois Curfman McInnes . A - the matrix
329320563c6bSBarry Smith 
32942ef1f0ffSBarry Smith   Level: intermediate
32952ef1f0ffSBarry Smith 
329611a5261eSBarry Smith   Note:
329718f449edSLois Curfman McInnes   The data input variable is intended primarily for Fortran programmers
329818f449edSLois Curfman McInnes   who wish to allocate their own matrix memory space.  Most users should
32992ef1f0ffSBarry Smith   set `data` = `NULL`.
330018f449edSLois Curfman McInnes 
3301fb850c59SBarry Smith   Developer Note:
3302fb850c59SBarry Smith   Many of the matrix operations for this variant use the BLAS and LAPACK routines.
3303fb850c59SBarry Smith 
33041cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATSEQDENSE`, `MatCreate()`, `MatCreateDense()`, `MatSetValues()`
330520563c6bSBarry Smith @*/
33065d83a8b1SBarry Smith PetscErrorCode MatCreateSeqDense(MPI_Comm comm, PetscInt m, PetscInt n, PetscScalar data[], Mat *A)
3307d71ae5a4SJacob Faibussowitsch {
33083a40ed3dSBarry Smith   PetscFunctionBegin;
33099566063dSJacob Faibussowitsch   PetscCall(MatCreate(comm, A));
33109566063dSJacob Faibussowitsch   PetscCall(MatSetSizes(*A, m, n, m, n));
33119566063dSJacob Faibussowitsch   PetscCall(MatSetType(*A, MATSEQDENSE));
33129566063dSJacob Faibussowitsch   PetscCall(MatSeqDenseSetPreallocation(*A, data));
33133ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3314273d9f13SBarry Smith }
3315273d9f13SBarry Smith 
33165d83a8b1SBarry Smith /*@
331711a5261eSBarry Smith   MatSeqDenseSetPreallocation - Sets the array used for storing the matrix elements of a `MATSEQDENSE` matrix
3318273d9f13SBarry Smith 
3319d083f849SBarry Smith   Collective
3320273d9f13SBarry Smith 
3321273d9f13SBarry Smith   Input Parameters:
33221c4f3114SJed Brown + B    - the matrix
33232ef1f0ffSBarry Smith - data - the array (or `NULL`)
33242ef1f0ffSBarry Smith 
33252ef1f0ffSBarry Smith   Level: intermediate
3326273d9f13SBarry Smith 
332711a5261eSBarry Smith   Note:
3328273d9f13SBarry Smith   The data input variable is intended primarily for Fortran programmers
3329273d9f13SBarry Smith   who wish to allocate their own matrix memory space.  Most users should
3330284134d9SBarry Smith   need not call this routine.
3331273d9f13SBarry Smith 
33321cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATSEQDENSE`, `MatCreate()`, `MatCreateDense()`, `MatSetValues()`, `MatDenseSetLDA()`
3333273d9f13SBarry Smith @*/
3334d71ae5a4SJacob Faibussowitsch PetscErrorCode MatSeqDenseSetPreallocation(Mat B, PetscScalar data[])
3335d71ae5a4SJacob Faibussowitsch {
3336a23d5eceSKris Buschelman   PetscFunctionBegin;
3337d5ea218eSStefano Zampini   PetscValidHeaderSpecific(B, MAT_CLASSID, 1);
3338cac4c232SBarry Smith   PetscTryMethod(B, "MatSeqDenseSetPreallocation_C", (Mat, PetscScalar[]), (B, data));
33393ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3340a23d5eceSKris Buschelman }
3341a23d5eceSKris Buschelman 
3342d71ae5a4SJacob Faibussowitsch PetscErrorCode MatSeqDenseSetPreallocation_SeqDense(Mat B, PetscScalar *data)
3343d71ae5a4SJacob Faibussowitsch {
3344ad16ce7aSStefano Zampini   Mat_SeqDense *b = (Mat_SeqDense *)B->data;
3345273d9f13SBarry Smith 
3346273d9f13SBarry Smith   PetscFunctionBegin;
334728b400f6SJacob Faibussowitsch   PetscCheck(!b->matinuse, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Need to call MatDenseRestoreSubMatrix() first");
3348273d9f13SBarry Smith   B->preallocated = PETSC_TRUE;
3349a868139aSShri Abhyankar 
33509566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetUp(B->rmap));
33519566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetUp(B->cmap));
335234ef9618SShri Abhyankar 
33536497c311SBarry Smith   if (b->lda <= 0) PetscCall(PetscBLASIntCast(B->rmap->n, &b->lda));
335486d161a7SShri Abhyankar 
33559e8f95c4SLisandro Dalcin   if (!data) { /* petsc-allocated storage */
33569566063dSJacob Faibussowitsch     if (!b->user_alloc) PetscCall(PetscFree(b->v));
33579566063dSJacob Faibussowitsch     PetscCall(PetscCalloc1((size_t)b->lda * B->cmap->n, &b->v));
33582205254eSKarl Rupp 
33599e8f95c4SLisandro Dalcin     b->user_alloc = PETSC_FALSE;
3360273d9f13SBarry Smith   } else { /* user-allocated storage */
33619566063dSJacob Faibussowitsch     if (!b->user_alloc) PetscCall(PetscFree(b->v));
3362273d9f13SBarry Smith     b->v          = data;
3363273d9f13SBarry Smith     b->user_alloc = PETSC_TRUE;
3364273d9f13SBarry Smith   }
33650450473dSBarry Smith   B->assembled = PETSC_TRUE;
33663ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3367273d9f13SBarry Smith }
3368273d9f13SBarry Smith 
336965b80a83SHong Zhang #if defined(PETSC_HAVE_ELEMENTAL)
3370d71ae5a4SJacob Faibussowitsch PETSC_INTERN PetscErrorCode MatConvert_SeqDense_Elemental(Mat A, MatType newtype, MatReuse reuse, Mat *newmat)
3371d71ae5a4SJacob Faibussowitsch {
3372d77f618aSHong Zhang   Mat                mat_elemental;
33731683a169SBarry Smith   const PetscScalar *array;
33741683a169SBarry Smith   PetscScalar       *v_colwise;
3375d77f618aSHong Zhang   PetscInt           M = A->rmap->N, N = A->cmap->N, i, j, k, *rows, *cols;
3376d77f618aSHong Zhang 
33778baccfbdSHong Zhang   PetscFunctionBegin;
33789566063dSJacob Faibussowitsch   PetscCall(PetscMalloc3(M * N, &v_colwise, M, &rows, N, &cols));
33799566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArrayRead(A, &array));
3380d77f618aSHong Zhang   /* convert column-wise array into row-wise v_colwise, see MatSetValues_Elemental() */
3381d77f618aSHong Zhang   k = 0;
3382d77f618aSHong Zhang   for (j = 0; j < N; j++) {
3383d77f618aSHong Zhang     cols[j] = j;
3384ad540459SPierre Jolivet     for (i = 0; i < M; i++) v_colwise[j * M + i] = array[k++];
3385d77f618aSHong Zhang   }
3386ad540459SPierre Jolivet   for (i = 0; i < M; i++) rows[i] = i;
33879566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArrayRead(A, &array));
3388d77f618aSHong Zhang 
33899566063dSJacob Faibussowitsch   PetscCall(MatCreate(PetscObjectComm((PetscObject)A), &mat_elemental));
33909566063dSJacob Faibussowitsch   PetscCall(MatSetSizes(mat_elemental, PETSC_DECIDE, PETSC_DECIDE, M, N));
33919566063dSJacob Faibussowitsch   PetscCall(MatSetType(mat_elemental, MATELEMENTAL));
33929566063dSJacob Faibussowitsch   PetscCall(MatSetUp(mat_elemental));
3393d77f618aSHong Zhang 
3394d77f618aSHong Zhang   /* PETSc-Elemental interaface uses axpy for setting off-processor entries, only ADD_VALUES is allowed */
33959566063dSJacob Faibussowitsch   PetscCall(MatSetValues(mat_elemental, M, rows, N, cols, v_colwise, ADD_VALUES));
33969566063dSJacob Faibussowitsch   PetscCall(MatAssemblyBegin(mat_elemental, MAT_FINAL_ASSEMBLY));
33979566063dSJacob Faibussowitsch   PetscCall(MatAssemblyEnd(mat_elemental, MAT_FINAL_ASSEMBLY));
33989566063dSJacob Faibussowitsch   PetscCall(PetscFree3(v_colwise, rows, cols));
3399d77f618aSHong Zhang 
3400511c6705SHong Zhang   if (reuse == MAT_INPLACE_MATRIX) {
34019566063dSJacob Faibussowitsch     PetscCall(MatHeaderReplace(A, &mat_elemental));
3402d77f618aSHong Zhang   } else {
3403d77f618aSHong Zhang     *newmat = mat_elemental;
3404d77f618aSHong Zhang   }
34053ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
34068baccfbdSHong Zhang }
340765b80a83SHong Zhang #endif
34088baccfbdSHong Zhang 
3409d71ae5a4SJacob Faibussowitsch PetscErrorCode MatDenseSetLDA_SeqDense(Mat B, PetscInt lda)
3410d71ae5a4SJacob Faibussowitsch {
34111b807ce4Svictorle   Mat_SeqDense *b = (Mat_SeqDense *)B->data;
34127422da62SJose E. Roman   PetscBool     data;
341321a2c019SBarry Smith 
34141b807ce4Svictorle   PetscFunctionBegin;
34157422da62SJose E. Roman   data = (PetscBool)((B->rmap->n > 0 && B->cmap->n > 0) ? (b->v ? PETSC_TRUE : PETSC_FALSE) : PETSC_FALSE);
3416aed4548fSBarry Smith   PetscCheck(b->user_alloc || !data || b->lda == lda, PETSC_COMM_SELF, PETSC_ERR_ORDER, "LDA cannot be changed after allocation of internal storage");
341708401ef6SPierre 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);
34186497c311SBarry Smith   PetscCall(PetscBLASIntCast(lda, &b->lda));
34193ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
34201b807ce4Svictorle }
34211b807ce4Svictorle 
3422d71ae5a4SJacob Faibussowitsch PetscErrorCode MatCreateMPIMatConcatenateSeqMat_SeqDense(MPI_Comm comm, Mat inmat, PetscInt n, MatReuse scall, Mat *outmat)
3423d71ae5a4SJacob Faibussowitsch {
3424d528f656SJakub Kruzik   PetscFunctionBegin;
34259566063dSJacob Faibussowitsch   PetscCall(MatCreateMPIMatConcatenateSeqMat_MPIDense(comm, inmat, n, scall, outmat));
34263ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3427d528f656SJakub Kruzik }
3428d528f656SJakub Kruzik 
3429d16ceb75SStefano Zampini PetscErrorCode MatDenseCreateColumnVec_Private(Mat A, Vec *v)
3430d16ceb75SStefano Zampini {
3431d16ceb75SStefano Zampini   PetscBool   isstd, iskok, iscuda, iship;
3432d16ceb75SStefano Zampini   PetscMPIInt size;
3433d16ceb75SStefano Zampini #if PetscDefined(HAVE_CUDA) || PetscDefined(HAVE_HIP)
3434d16ceb75SStefano Zampini   /* we pass the data of A, to prevent allocating needless GPU memory the first time VecCUPMPlaceArray is called. */
3435d16ceb75SStefano Zampini   const PetscScalar *a;
3436d16ceb75SStefano Zampini #endif
3437d16ceb75SStefano Zampini 
3438d16ceb75SStefano Zampini   PetscFunctionBegin;
3439d16ceb75SStefano Zampini   *v = NULL;
3440d16ceb75SStefano Zampini   PetscCall(PetscStrcmpAny(A->defaultvectype, &isstd, VECSTANDARD, VECSEQ, VECMPI, ""));
3441d16ceb75SStefano Zampini   PetscCall(PetscStrcmpAny(A->defaultvectype, &iskok, VECKOKKOS, VECSEQKOKKOS, VECMPIKOKKOS, ""));
3442d16ceb75SStefano Zampini   PetscCall(PetscStrcmpAny(A->defaultvectype, &iscuda, VECCUDA, VECSEQCUDA, VECMPICUDA, ""));
3443d16ceb75SStefano Zampini   PetscCall(PetscStrcmpAny(A->defaultvectype, &iship, VECHIP, VECSEQHIP, VECMPIHIP, ""));
3444d16ceb75SStefano Zampini   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)A), &size));
3445d16ceb75SStefano Zampini   if (isstd) {
3446d16ceb75SStefano Zampini     if (size > 1) PetscCall(VecCreateMPIWithArray(PetscObjectComm((PetscObject)A), A->rmap->bs, A->rmap->n, A->rmap->N, NULL, v));
3447d16ceb75SStefano Zampini     else PetscCall(VecCreateSeqWithArray(PetscObjectComm((PetscObject)A), A->rmap->bs, A->rmap->n, NULL, v));
3448d16ceb75SStefano Zampini   } else if (iskok) {
3449d16ceb75SStefano Zampini     PetscCheck(PetscDefined(HAVE_KOKKOS_KERNELS), PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Reconfigure using KOKKOS kernels support");
3450d16ceb75SStefano Zampini #if PetscDefined(HAVE_KOKKOS_KERNELS)
3451d16ceb75SStefano Zampini     if (size > 1) PetscCall(VecCreateMPIKokkosWithArray(PetscObjectComm((PetscObject)A), A->rmap->bs, A->rmap->n, A->rmap->N, NULL, v));
3452d16ceb75SStefano Zampini     else PetscCall(VecCreateSeqKokkosWithArray(PetscObjectComm((PetscObject)A), A->rmap->bs, A->rmap->n, NULL, v));
3453d16ceb75SStefano Zampini #endif
3454d16ceb75SStefano Zampini   } else if (iscuda) {
3455d16ceb75SStefano Zampini     PetscCheck(PetscDefined(HAVE_CUDA), PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Reconfigure using CUDA support");
3456d16ceb75SStefano Zampini #if PetscDefined(HAVE_CUDA)
3457d16ceb75SStefano Zampini     PetscCall(MatDenseCUDAGetArrayRead(A, &a));
3458d16ceb75SStefano Zampini     if (size > 1) PetscCall(VecCreateMPICUDAWithArrays(PetscObjectComm((PetscObject)A), A->rmap->bs, A->rmap->n, A->rmap->N, NULL, a, v));
3459d16ceb75SStefano Zampini     else PetscCall(VecCreateSeqCUDAWithArrays(PetscObjectComm((PetscObject)A), A->rmap->bs, A->rmap->n, NULL, a, v));
3460d16ceb75SStefano Zampini #endif
3461d16ceb75SStefano Zampini   } else if (iship) {
3462d16ceb75SStefano Zampini     PetscCheck(PetscDefined(HAVE_HIP), PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Reconfigure using HIP support");
3463d16ceb75SStefano Zampini #if PetscDefined(HAVE_HIP)
3464d16ceb75SStefano Zampini     PetscCall(MatDenseHIPGetArrayRead(A, &a));
3465d16ceb75SStefano Zampini     if (size > 1) PetscCall(VecCreateMPIHIPWithArrays(PetscObjectComm((PetscObject)A), A->rmap->bs, A->rmap->n, A->rmap->N, NULL, a, v));
3466d16ceb75SStefano Zampini     else PetscCall(VecCreateSeqHIPWithArrays(PetscObjectComm((PetscObject)A), A->rmap->bs, A->rmap->n, NULL, a, v));
3467d16ceb75SStefano Zampini #endif
3468d16ceb75SStefano Zampini   }
3469d16ceb75SStefano Zampini   PetscCheck(*v, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Not coded for type %s", A->defaultvectype);
3470d16ceb75SStefano Zampini   PetscFunctionReturn(PETSC_SUCCESS);
3471d16ceb75SStefano Zampini }
3472d16ceb75SStefano Zampini 
3473d71ae5a4SJacob Faibussowitsch PetscErrorCode MatDenseGetColumnVec_SeqDense(Mat A, PetscInt col, Vec *v)
3474d71ae5a4SJacob Faibussowitsch {
34756947451fSStefano Zampini   Mat_SeqDense *a = (Mat_SeqDense *)A->data;
34766947451fSStefano Zampini 
34776947451fSStefano Zampini   PetscFunctionBegin;
347828b400f6SJacob Faibussowitsch   PetscCheck(!a->vecinuse, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Need to call MatDenseRestoreColumnVec() first");
347928b400f6SJacob Faibussowitsch   PetscCheck(!a->matinuse, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Need to call MatDenseRestoreSubMatrix() first");
3480d16ceb75SStefano Zampini   if (!a->cvec) PetscCall(MatDenseCreateColumnVec_Private(A, &a->cvec));
34816947451fSStefano Zampini   a->vecinuse = col + 1;
34829566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArray(A, (PetscScalar **)&a->ptrinuse));
34839566063dSJacob Faibussowitsch   PetscCall(VecPlaceArray(a->cvec, a->ptrinuse + (size_t)col * (size_t)a->lda));
34846947451fSStefano Zampini   *v = a->cvec;
34853ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
34866947451fSStefano Zampini }
34876947451fSStefano Zampini 
3488d71ae5a4SJacob Faibussowitsch PetscErrorCode MatDenseRestoreColumnVec_SeqDense(Mat A, PetscInt col, Vec *v)
3489d71ae5a4SJacob Faibussowitsch {
34906947451fSStefano Zampini   Mat_SeqDense *a = (Mat_SeqDense *)A->data;
34916947451fSStefano Zampini 
34926947451fSStefano Zampini   PetscFunctionBegin;
349328b400f6SJacob Faibussowitsch   PetscCheck(a->vecinuse, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Need to call MatDenseGetColumnVec() first");
349428b400f6SJacob Faibussowitsch   PetscCheck(a->cvec, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Missing internal column vector");
34954186a4bbSPierre Jolivet   VecCheckAssembled(a->cvec);
34966947451fSStefano Zampini   a->vecinuse = 0;
34979566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArray(A, (PetscScalar **)&a->ptrinuse));
34989566063dSJacob Faibussowitsch   PetscCall(VecResetArray(a->cvec));
349975f6d85dSStefano Zampini   if (v) *v = NULL;
35003ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
35016947451fSStefano Zampini }
35026947451fSStefano Zampini 
3503d71ae5a4SJacob Faibussowitsch PetscErrorCode MatDenseGetColumnVecRead_SeqDense(Mat A, PetscInt col, Vec *v)
3504d71ae5a4SJacob Faibussowitsch {
35056947451fSStefano Zampini   Mat_SeqDense *a = (Mat_SeqDense *)A->data;
35066947451fSStefano Zampini 
35076947451fSStefano Zampini   PetscFunctionBegin;
350828b400f6SJacob Faibussowitsch   PetscCheck(!a->vecinuse, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Need to call MatDenseRestoreColumnVec() first");
350928b400f6SJacob Faibussowitsch   PetscCheck(!a->matinuse, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Need to call MatDenseRestoreSubMatrix() first");
3510d16ceb75SStefano Zampini   if (!a->cvec) PetscCall(MatDenseCreateColumnVec_Private(A, &a->cvec));
35116947451fSStefano Zampini   a->vecinuse = col + 1;
35129566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArrayRead(A, &a->ptrinuse));
35138e3a54c0SPierre Jolivet   PetscCall(VecPlaceArray(a->cvec, PetscSafePointerPlusOffset(a->ptrinuse, (size_t)col * (size_t)a->lda)));
35149566063dSJacob Faibussowitsch   PetscCall(VecLockReadPush(a->cvec));
35156947451fSStefano Zampini   *v = a->cvec;
35163ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
35176947451fSStefano Zampini }
35186947451fSStefano Zampini 
3519d71ae5a4SJacob Faibussowitsch PetscErrorCode MatDenseRestoreColumnVecRead_SeqDense(Mat A, PetscInt col, Vec *v)
3520d71ae5a4SJacob Faibussowitsch {
35216947451fSStefano Zampini   Mat_SeqDense *a = (Mat_SeqDense *)A->data;
35226947451fSStefano Zampini 
35236947451fSStefano Zampini   PetscFunctionBegin;
352428b400f6SJacob Faibussowitsch   PetscCheck(a->vecinuse, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Need to call MatDenseGetColumnVec() first");
352528b400f6SJacob Faibussowitsch   PetscCheck(a->cvec, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Missing internal column vector");
35264186a4bbSPierre Jolivet   VecCheckAssembled(a->cvec);
35276947451fSStefano Zampini   a->vecinuse = 0;
35289566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArrayRead(A, &a->ptrinuse));
35299566063dSJacob Faibussowitsch   PetscCall(VecLockReadPop(a->cvec));
35309566063dSJacob Faibussowitsch   PetscCall(VecResetArray(a->cvec));
353175f6d85dSStefano Zampini   if (v) *v = NULL;
35323ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
35336947451fSStefano Zampini }
35346947451fSStefano Zampini 
3535d71ae5a4SJacob Faibussowitsch PetscErrorCode MatDenseGetColumnVecWrite_SeqDense(Mat A, PetscInt col, Vec *v)
3536d71ae5a4SJacob Faibussowitsch {
35376947451fSStefano Zampini   Mat_SeqDense *a = (Mat_SeqDense *)A->data;
35386947451fSStefano Zampini 
35396947451fSStefano Zampini   PetscFunctionBegin;
354028b400f6SJacob Faibussowitsch   PetscCheck(!a->vecinuse, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Need to call MatDenseRestoreColumnVec() first");
354128b400f6SJacob Faibussowitsch   PetscCheck(!a->matinuse, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Need to call MatDenseRestoreSubMatrix() first");
3542d16ceb75SStefano Zampini   if (!a->cvec) PetscCall(MatDenseCreateColumnVec_Private(A, &a->cvec));
35436947451fSStefano Zampini   a->vecinuse = col + 1;
35449566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArrayWrite(A, (PetscScalar **)&a->ptrinuse));
35458e3a54c0SPierre Jolivet   PetscCall(VecPlaceArray(a->cvec, PetscSafePointerPlusOffset(a->ptrinuse, (size_t)col * (size_t)a->lda)));
35466947451fSStefano Zampini   *v = a->cvec;
35473ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
35486947451fSStefano Zampini }
35496947451fSStefano Zampini 
3550d71ae5a4SJacob Faibussowitsch PetscErrorCode MatDenseRestoreColumnVecWrite_SeqDense(Mat A, PetscInt col, Vec *v)
3551d71ae5a4SJacob Faibussowitsch {
35526947451fSStefano Zampini   Mat_SeqDense *a = (Mat_SeqDense *)A->data;
35536947451fSStefano Zampini 
35546947451fSStefano Zampini   PetscFunctionBegin;
355528b400f6SJacob Faibussowitsch   PetscCheck(a->vecinuse, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Need to call MatDenseGetColumnVec() first");
355628b400f6SJacob Faibussowitsch   PetscCheck(a->cvec, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Missing internal column vector");
35574186a4bbSPierre Jolivet   VecCheckAssembled(a->cvec);
35586947451fSStefano Zampini   a->vecinuse = 0;
35599566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArrayWrite(A, (PetscScalar **)&a->ptrinuse));
35609566063dSJacob Faibussowitsch   PetscCall(VecResetArray(a->cvec));
356175f6d85dSStefano Zampini   if (v) *v = NULL;
35623ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
35636947451fSStefano Zampini }
35646947451fSStefano Zampini 
3565d71ae5a4SJacob Faibussowitsch PetscErrorCode MatDenseGetSubMatrix_SeqDense(Mat A, PetscInt rbegin, PetscInt rend, PetscInt cbegin, PetscInt cend, Mat *v)
3566d71ae5a4SJacob Faibussowitsch {
35675ea7661aSPierre Jolivet   Mat_SeqDense *a = (Mat_SeqDense *)A->data;
35685ea7661aSPierre Jolivet 
35695ea7661aSPierre Jolivet   PetscFunctionBegin;
357028b400f6SJacob Faibussowitsch   PetscCheck(!a->vecinuse, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Need to call MatDenseRestoreColumnVec() first");
357128b400f6SJacob Faibussowitsch   PetscCheck(!a->matinuse, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Need to call MatDenseRestoreSubMatrix() first");
3572a2748737SPierre Jolivet   if (a->cmat && (cend - cbegin != a->cmat->cmap->N || rend - rbegin != a->cmat->rmap->N)) PetscCall(MatDestroy(&a->cmat));
35735ea7661aSPierre Jolivet   if (!a->cmat) {
35748e3a54c0SPierre 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));
35755ea7661aSPierre Jolivet   } else {
35768e3a54c0SPierre Jolivet     PetscCall(MatDensePlaceArray(a->cmat, PetscSafePointerPlusOffset(a->v, rbegin + (size_t)cbegin * a->lda)));
35775ea7661aSPierre Jolivet   }
35789566063dSJacob Faibussowitsch   PetscCall(MatDenseSetLDA(a->cmat, a->lda));
35795ea7661aSPierre Jolivet   a->matinuse = cbegin + 1;
35805ea7661aSPierre Jolivet   *v          = a->cmat;
358147d993e7Ssuyashtn #if defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
358275f6d85dSStefano Zampini   A->offloadmask = PETSC_OFFLOAD_CPU;
358375f6d85dSStefano Zampini #endif
35843ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
35855ea7661aSPierre Jolivet }
35865ea7661aSPierre Jolivet 
3587d71ae5a4SJacob Faibussowitsch PetscErrorCode MatDenseRestoreSubMatrix_SeqDense(Mat A, Mat *v)
3588d71ae5a4SJacob Faibussowitsch {
35895ea7661aSPierre Jolivet   Mat_SeqDense *a = (Mat_SeqDense *)A->data;
35905ea7661aSPierre Jolivet 
35915ea7661aSPierre Jolivet   PetscFunctionBegin;
359228b400f6SJacob Faibussowitsch   PetscCheck(a->matinuse, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Need to call MatDenseGetSubMatrix() first");
359328b400f6SJacob Faibussowitsch   PetscCheck(a->cmat, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Missing internal column matrix");
359408401ef6SPierre Jolivet   PetscCheck(*v == a->cmat, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Not the matrix obtained from MatDenseGetSubMatrix()");
35955ea7661aSPierre Jolivet   a->matinuse = 0;
35969566063dSJacob Faibussowitsch   PetscCall(MatDenseResetArray(a->cmat));
3597742765d3SMatthew Knepley   if (v) *v = NULL;
359847d993e7Ssuyashtn #if defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
35993faff063SStefano Zampini   A->offloadmask = PETSC_OFFLOAD_CPU;
36003faff063SStefano Zampini #endif
36013ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
36025ea7661aSPierre Jolivet }
36035ea7661aSPierre Jolivet 
36040bad9183SKris Buschelman /*MC
3605fafad747SKris Buschelman    MATSEQDENSE - MATSEQDENSE = "seqdense" - A matrix type to be used for sequential dense matrices.
36060bad9183SKris Buschelman 
36072ef1f0ffSBarry Smith    Options Database Key:
360811a5261eSBarry Smith . -mat_type seqdense - sets the matrix type to `MATSEQDENSE` during a call to `MatSetFromOptions()`
36090bad9183SKris Buschelman 
36100bad9183SKris Buschelman   Level: beginner
36110bad9183SKris Buschelman 
36121cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATSEQDENSE`, `MatCreateSeqDense()`
36130bad9183SKris Buschelman M*/
3614d71ae5a4SJacob Faibussowitsch PetscErrorCode MatCreate_SeqDense(Mat B)
3615d71ae5a4SJacob Faibussowitsch {
3616273d9f13SBarry Smith   Mat_SeqDense *b;
36177c334f02SBarry Smith   PetscMPIInt   size;
3618273d9f13SBarry Smith 
3619273d9f13SBarry Smith   PetscFunctionBegin;
36209566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)B), &size));
362108401ef6SPierre Jolivet   PetscCheck(size <= 1, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Comm must be of size 1");
362255659b69SBarry Smith 
36234dfa11a4SJacob Faibussowitsch   PetscCall(PetscNew(&b));
362444cd7ae7SLois Curfman McInnes   B->data   = (void *)b;
3625aea10558SJacob Faibussowitsch   B->ops[0] = MatOps_Values;
362618f449edSLois Curfman McInnes 
3627273d9f13SBarry Smith   b->roworiented = PETSC_TRUE;
36284e220ebcSLois Curfman McInnes 
36299566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatQRFactor_C", MatQRFactor_SeqDense));
36309566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatDenseGetLDA_C", MatDenseGetLDA_SeqDense));
36319566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatDenseSetLDA_C", MatDenseSetLDA_SeqDense));
36329566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatDenseGetArray_C", MatDenseGetArray_SeqDense));
36339566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatDenseRestoreArray_C", MatDenseRestoreArray_SeqDense));
36349566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatDensePlaceArray_C", MatDensePlaceArray_SeqDense));
36359566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatDenseResetArray_C", MatDenseResetArray_SeqDense));
36369566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatDenseReplaceArray_C", MatDenseReplaceArray_SeqDense));
36379566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatDenseGetArrayRead_C", MatDenseGetArray_SeqDense));
36389566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatDenseRestoreArrayRead_C", MatDenseRestoreArray_SeqDense));
36399566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatDenseGetArrayWrite_C", MatDenseGetArray_SeqDense));
36409566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatDenseRestoreArrayWrite_C", MatDenseRestoreArray_SeqDense));
36419566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatConvert_seqdense_seqaij_C", MatConvert_SeqDense_SeqAIJ));
36428baccfbdSHong Zhang #if defined(PETSC_HAVE_ELEMENTAL)
36439566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatConvert_seqdense_elemental_C", MatConvert_SeqDense_Elemental));
36448baccfbdSHong Zhang #endif
3645d24d4204SJose E. Roman #if defined(PETSC_HAVE_SCALAPACK)
36469566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatConvert_seqdense_scalapack_C", MatConvert_Dense_ScaLAPACK));
3647d24d4204SJose E. Roman #endif
36482bf066beSStefano Zampini #if defined(PETSC_HAVE_CUDA)
36499566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatConvert_seqdense_seqdensecuda_C", MatConvert_SeqDense_SeqDenseCUDA));
36509566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatProductSetFromOptions_seqdensecuda_seqdensecuda_C", MatProductSetFromOptions_SeqDense));
36519566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatProductSetFromOptions_seqdensecuda_seqdense_C", MatProductSetFromOptions_SeqDense));
36529566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatProductSetFromOptions_seqdense_seqdensecuda_C", MatProductSetFromOptions_SeqDense));
36532bf066beSStefano Zampini #endif
365447d993e7Ssuyashtn #if defined(PETSC_HAVE_HIP)
365547d993e7Ssuyashtn   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatConvert_seqdense_seqdensehip_C", MatConvert_SeqDense_SeqDenseHIP));
365647d993e7Ssuyashtn   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatProductSetFromOptions_seqdensehip_seqdensehip_C", MatProductSetFromOptions_SeqDense));
365747d993e7Ssuyashtn   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatProductSetFromOptions_seqdensehip_seqdense_C", MatProductSetFromOptions_SeqDense));
365847d993e7Ssuyashtn   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatProductSetFromOptions_seqdense_seqdensehip_C", MatProductSetFromOptions_SeqDense));
365947d993e7Ssuyashtn #endif
36609566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatSeqDenseSetPreallocation_C", MatSeqDenseSetPreallocation_SeqDense));
36619566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatProductSetFromOptions_seqaij_seqdense_C", MatProductSetFromOptions_SeqAIJ_SeqDense));
36629566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatProductSetFromOptions_seqdense_seqdense_C", MatProductSetFromOptions_SeqDense));
36639566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatProductSetFromOptions_seqbaij_seqdense_C", MatProductSetFromOptions_SeqXBAIJ_SeqDense));
36649566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatProductSetFromOptions_seqsbaij_seqdense_C", MatProductSetFromOptions_SeqXBAIJ_SeqDense));
366596e6d5c4SRichard Tran Mills 
36669566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatDenseGetColumn_C", MatDenseGetColumn_SeqDense));
36679566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatDenseRestoreColumn_C", MatDenseRestoreColumn_SeqDense));
36689566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatDenseGetColumnVec_C", MatDenseGetColumnVec_SeqDense));
36699566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatDenseRestoreColumnVec_C", MatDenseRestoreColumnVec_SeqDense));
36709566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatDenseGetColumnVecRead_C", MatDenseGetColumnVecRead_SeqDense));
36719566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatDenseRestoreColumnVecRead_C", MatDenseRestoreColumnVecRead_SeqDense));
36729566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatDenseGetColumnVecWrite_C", MatDenseGetColumnVecWrite_SeqDense));
36739566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatDenseRestoreColumnVecWrite_C", MatDenseRestoreColumnVecWrite_SeqDense));
36749566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatDenseGetSubMatrix_C", MatDenseGetSubMatrix_SeqDense));
36759566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatDenseRestoreSubMatrix_C", MatDenseRestoreSubMatrix_SeqDense));
36760be0d8bdSHansol Suh   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatMultAddColumnRange_C", MatMultAddColumnRange_SeqDense));
36770be0d8bdSHansol Suh   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatMultHermitianTransposeColumnRange_C", MatMultHermitianTransposeColumnRange_SeqDense));
36780be0d8bdSHansol Suh   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatMultHermitianTransposeAddColumnRange_C", MatMultHermitianTransposeAddColumnRange_SeqDense));
36799566063dSJacob Faibussowitsch   PetscCall(PetscObjectChangeTypeName((PetscObject)B, MATSEQDENSE));
36803ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3681289bc588SBarry Smith }
368286aefd0dSHong Zhang 
368386aefd0dSHong Zhang /*@C
368411a5261eSBarry 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.
368586aefd0dSHong Zhang 
368686aefd0dSHong Zhang   Not Collective
368786aefd0dSHong Zhang 
36885ea7661aSPierre Jolivet   Input Parameters:
3689fe59aa6dSJacob Faibussowitsch + A   - a `MATSEQDENSE` or `MATMPIDENSE` matrix
369086aefd0dSHong Zhang - col - column index
369186aefd0dSHong Zhang 
369286aefd0dSHong Zhang   Output Parameter:
369386aefd0dSHong Zhang . vals - pointer to the data
369486aefd0dSHong Zhang 
369586aefd0dSHong Zhang   Level: intermediate
369686aefd0dSHong Zhang 
369711a5261eSBarry Smith   Note:
369811a5261eSBarry Smith   Use `MatDenseGetColumnVec()` to get access to a column of a `MATDENSE` treated as a `Vec`
369911a5261eSBarry Smith 
37001cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATDENSE`, `MatDenseRestoreColumn()`, `MatDenseGetColumnVec()`
370186aefd0dSHong Zhang @*/
37025d83a8b1SBarry Smith PetscErrorCode MatDenseGetColumn(Mat A, PetscInt col, PetscScalar *vals[])
3703d71ae5a4SJacob Faibussowitsch {
370486aefd0dSHong Zhang   PetscFunctionBegin;
3705d5ea218eSStefano Zampini   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
3706d5ea218eSStefano Zampini   PetscValidLogicalCollectiveInt(A, col, 2);
37074f572ea9SToby Isaac   PetscAssertPointer(vals, 3);
3708cac4c232SBarry Smith   PetscUseMethod(A, "MatDenseGetColumn_C", (Mat, PetscInt, PetscScalar **), (A, col, vals));
37093ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
371086aefd0dSHong Zhang }
371186aefd0dSHong Zhang 
371286aefd0dSHong Zhang /*@C
371311a5261eSBarry Smith   MatDenseRestoreColumn - returns access to a column of a `MATDENSE` matrix which is returned by `MatDenseGetColumn()`.
371486aefd0dSHong Zhang 
371586aefd0dSHong Zhang   Not Collective
371686aefd0dSHong Zhang 
3717742765d3SMatthew Knepley   Input Parameters:
3718fe59aa6dSJacob Faibussowitsch + A    - a `MATSEQDENSE` or `MATMPIDENSE` matrix
37192ef1f0ffSBarry Smith - vals - pointer to the data (may be `NULL`)
372086aefd0dSHong Zhang 
372186aefd0dSHong Zhang   Level: intermediate
372286aefd0dSHong Zhang 
37231cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATDENSE`, `MatDenseGetColumn()`
372486aefd0dSHong Zhang @*/
37255d83a8b1SBarry Smith PetscErrorCode MatDenseRestoreColumn(Mat A, PetscScalar *vals[])
3726d71ae5a4SJacob Faibussowitsch {
372786aefd0dSHong Zhang   PetscFunctionBegin;
3728d5ea218eSStefano Zampini   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
37294f572ea9SToby Isaac   PetscAssertPointer(vals, 2);
3730cac4c232SBarry Smith   PetscUseMethod(A, "MatDenseRestoreColumn_C", (Mat, PetscScalar **), (A, vals));
37313ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
373286aefd0dSHong Zhang }
37336947451fSStefano Zampini 
37340f74d2c1SSatish Balay /*@
373511a5261eSBarry Smith   MatDenseGetColumnVec - Gives read-write access to a column of a `MATDENSE` matrix, represented as a `Vec`.
37366947451fSStefano Zampini 
37376947451fSStefano Zampini   Collective
37386947451fSStefano Zampini 
37395ea7661aSPierre Jolivet   Input Parameters:
3740fe59aa6dSJacob Faibussowitsch + A   - the `Mat` object
37416947451fSStefano Zampini - col - the column index
37426947451fSStefano Zampini 
37436947451fSStefano Zampini   Output Parameter:
37446947451fSStefano Zampini . v - the vector
37456947451fSStefano Zampini 
37462ef1f0ffSBarry Smith   Level: intermediate
37472ef1f0ffSBarry Smith 
37486947451fSStefano Zampini   Notes:
374911a5261eSBarry Smith   The vector is owned by PETSc. Users need to call `MatDenseRestoreColumnVec()` when the vector is no longer needed.
375011a5261eSBarry Smith 
375111a5261eSBarry Smith   Use `MatDenseGetColumnVecRead()` to obtain read-only access or `MatDenseGetColumnVecWrite()` for write-only access.
37526947451fSStefano Zampini 
37531cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATDENSE`, `MATDENSECUDA`, `MATDENSEHIP`, `MatDenseGetColumnVecRead()`, `MatDenseGetColumnVecWrite()`, `MatDenseRestoreColumnVec()`, `MatDenseRestoreColumnVecRead()`, `MatDenseRestoreColumnVecWrite()`, `MatDenseGetColumn()`
37546947451fSStefano Zampini @*/
3755d71ae5a4SJacob Faibussowitsch PetscErrorCode MatDenseGetColumnVec(Mat A, PetscInt col, Vec *v)
3756d71ae5a4SJacob Faibussowitsch {
37576947451fSStefano Zampini   PetscFunctionBegin;
37586947451fSStefano Zampini   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
37596947451fSStefano Zampini   PetscValidType(A, 1);
37606947451fSStefano Zampini   PetscValidLogicalCollectiveInt(A, col, 2);
37614f572ea9SToby Isaac   PetscAssertPointer(v, 3);
376228b400f6SJacob Faibussowitsch   PetscCheck(A->preallocated, PetscObjectComm((PetscObject)A), PETSC_ERR_ORDER, "Matrix not preallocated");
37632cf15c64SPierre 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);
3764cac4c232SBarry Smith   PetscUseMethod(A, "MatDenseGetColumnVec_C", (Mat, PetscInt, Vec *), (A, col, v));
37653ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
37666947451fSStefano Zampini }
37676947451fSStefano Zampini 
37680f74d2c1SSatish Balay /*@
3769fb850c59SBarry Smith   MatDenseRestoreColumnVec - Returns access to a column of a dense matrix obtained from `MatDenseGetColumnVec()`.
37706947451fSStefano Zampini 
37716947451fSStefano Zampini   Collective
37726947451fSStefano Zampini 
37735ea7661aSPierre Jolivet   Input Parameters:
3774fb850c59SBarry Smith + A   - the `Mat` object
37756947451fSStefano Zampini . col - the column index
3776fb850c59SBarry Smith - v   - the `Vec` object (may be `NULL`)
37776947451fSStefano Zampini 
37786947451fSStefano Zampini   Level: intermediate
37796947451fSStefano Zampini 
37801cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATDENSE`, `MATDENSECUDA`, `MATDENSEHIP`, `MatDenseGetColumnVec()`, `MatDenseGetColumnVecRead()`, `MatDenseGetColumnVecWrite()`, `MatDenseRestoreColumnVecRead()`, `MatDenseRestoreColumnVecWrite()`
37816947451fSStefano Zampini @*/
3782d71ae5a4SJacob Faibussowitsch PetscErrorCode MatDenseRestoreColumnVec(Mat A, PetscInt col, Vec *v)
3783d71ae5a4SJacob Faibussowitsch {
37846947451fSStefano Zampini   PetscFunctionBegin;
37856947451fSStefano Zampini   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
37866947451fSStefano Zampini   PetscValidType(A, 1);
37876947451fSStefano Zampini   PetscValidLogicalCollectiveInt(A, col, 2);
378808401ef6SPierre Jolivet   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, "MatDenseRestoreColumnVec_C", (Mat, PetscInt, Vec *), (A, col, v));
37913ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
37926947451fSStefano Zampini }
37936947451fSStefano Zampini 
37940f74d2c1SSatish Balay /*@
3795fb850c59SBarry Smith   MatDenseGetColumnVecRead - Gives read-only access to a column of a dense matrix, represented as a `Vec`.
37966947451fSStefano Zampini 
37976947451fSStefano Zampini   Collective
37986947451fSStefano Zampini 
37995ea7661aSPierre Jolivet   Input Parameters:
3800fe59aa6dSJacob Faibussowitsch + A   - the `Mat` object
38016947451fSStefano Zampini - col - the column index
38026947451fSStefano Zampini 
38036947451fSStefano Zampini   Output Parameter:
38046947451fSStefano Zampini . v - the vector
38056947451fSStefano Zampini 
38062ef1f0ffSBarry Smith   Level: intermediate
38072ef1f0ffSBarry Smith 
38086947451fSStefano Zampini   Notes:
38096947451fSStefano Zampini   The vector is owned by PETSc and users cannot modify it.
381011a5261eSBarry Smith 
38112ef1f0ffSBarry Smith   Users need to call `MatDenseRestoreColumnVecRead()` when the vector is no longer needed.
381211a5261eSBarry Smith 
38132ef1f0ffSBarry Smith   Use `MatDenseGetColumnVec()` to obtain read-write access or `MatDenseGetColumnVecWrite()` for write-only access.
38146947451fSStefano Zampini 
38151cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATDENSE`, `MATDENSECUDA`, `MATDENSEHIP`, `MatDenseGetColumnVec()`, `MatDenseGetColumnVecWrite()`, `MatDenseRestoreColumnVec()`, `MatDenseRestoreColumnVecRead()`, `MatDenseRestoreColumnVecWrite()`
38166947451fSStefano Zampini @*/
3817d71ae5a4SJacob Faibussowitsch PetscErrorCode MatDenseGetColumnVecRead(Mat A, PetscInt col, Vec *v)
3818d71ae5a4SJacob Faibussowitsch {
38196947451fSStefano Zampini   PetscFunctionBegin;
38206947451fSStefano Zampini   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
38216947451fSStefano Zampini   PetscValidType(A, 1);
38226947451fSStefano Zampini   PetscValidLogicalCollectiveInt(A, col, 2);
38234f572ea9SToby Isaac   PetscAssertPointer(v, 3);
382428b400f6SJacob Faibussowitsch   PetscCheck(A->preallocated, PetscObjectComm((PetscObject)A), PETSC_ERR_ORDER, "Matrix not preallocated");
38252cf15c64SPierre 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);
3826cac4c232SBarry Smith   PetscUseMethod(A, "MatDenseGetColumnVecRead_C", (Mat, PetscInt, Vec *), (A, col, v));
38273ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
38286947451fSStefano Zampini }
38296947451fSStefano Zampini 
38300f74d2c1SSatish Balay /*@
3831fb850c59SBarry Smith   MatDenseRestoreColumnVecRead - Returns access to a column of a dense matrix obtained from `MatDenseGetColumnVecRead()`.
38326947451fSStefano Zampini 
38336947451fSStefano Zampini   Collective
38346947451fSStefano Zampini 
38355ea7661aSPierre Jolivet   Input Parameters:
3836fe59aa6dSJacob Faibussowitsch + A   - the `Mat` object
38376947451fSStefano Zampini . col - the column index
3838fb850c59SBarry Smith - v   - the `Vec` object (may be `NULL`)
38396947451fSStefano Zampini 
38406947451fSStefano Zampini   Level: intermediate
38416947451fSStefano Zampini 
38421cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATDENSE`, `MATDENSECUDA`, `MATDENSEHIP`, `MatDenseGetColumnVec()`, `MatDenseGetColumnVecRead()`, `MatDenseGetColumnVecWrite()`, `MatDenseRestoreColumnVec()`, `MatDenseRestoreColumnVecWrite()`
38436947451fSStefano Zampini @*/
3844d71ae5a4SJacob Faibussowitsch PetscErrorCode MatDenseRestoreColumnVecRead(Mat A, PetscInt col, Vec *v)
3845d71ae5a4SJacob Faibussowitsch {
38466947451fSStefano Zampini   PetscFunctionBegin;
38476947451fSStefano Zampini   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
38486947451fSStefano Zampini   PetscValidType(A, 1);
38496947451fSStefano Zampini   PetscValidLogicalCollectiveInt(A, col, 2);
385008401ef6SPierre Jolivet   PetscCheck(A->preallocated, PetscObjectComm((PetscObject)A), PETSC_ERR_ORDER, "Matrix not preallocated");
38512cf15c64SPierre 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);
3852cac4c232SBarry Smith   PetscUseMethod(A, "MatDenseRestoreColumnVecRead_C", (Mat, PetscInt, Vec *), (A, col, v));
38533ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
38546947451fSStefano Zampini }
38556947451fSStefano Zampini 
38560f74d2c1SSatish Balay /*@
3857fb850c59SBarry Smith   MatDenseGetColumnVecWrite - Gives write-only access to a column of a dense matrix, represented as a `Vec`.
38586947451fSStefano Zampini 
38596947451fSStefano Zampini   Collective
38606947451fSStefano Zampini 
38615ea7661aSPierre Jolivet   Input Parameters:
3862fe59aa6dSJacob Faibussowitsch + A   - the `Mat` object
38636947451fSStefano Zampini - col - the column index
38646947451fSStefano Zampini 
38656947451fSStefano Zampini   Output Parameter:
38666947451fSStefano Zampini . v - the vector
38676947451fSStefano Zampini 
38686947451fSStefano Zampini   Level: intermediate
38696947451fSStefano Zampini 
38702ef1f0ffSBarry Smith   Notes:
38712ef1f0ffSBarry Smith   The vector is owned by PETSc. Users need to call `MatDenseRestoreColumnVecWrite()` when the vector is no longer needed.
38722ef1f0ffSBarry Smith 
38732ef1f0ffSBarry Smith   Use `MatDenseGetColumnVec()` to obtain read-write access or `MatDenseGetColumnVecRead()` for read-only access.
38742ef1f0ffSBarry Smith 
38751cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATDENSE`, `MATDENSECUDA`, `MATDENSEHIP`, `MatDenseGetColumnVec()`, `MatDenseGetColumnVecRead()`, `MatDenseRestoreColumnVec()`, `MatDenseRestoreColumnVecRead()`, `MatDenseRestoreColumnVecWrite()`
38766947451fSStefano Zampini @*/
3877d71ae5a4SJacob Faibussowitsch PetscErrorCode MatDenseGetColumnVecWrite(Mat A, PetscInt col, Vec *v)
3878d71ae5a4SJacob Faibussowitsch {
38796947451fSStefano Zampini   PetscFunctionBegin;
38806947451fSStefano Zampini   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
38816947451fSStefano Zampini   PetscValidType(A, 1);
38826947451fSStefano Zampini   PetscValidLogicalCollectiveInt(A, col, 2);
38834f572ea9SToby Isaac   PetscAssertPointer(v, 3);
388428b400f6SJacob Faibussowitsch   PetscCheck(A->preallocated, PetscObjectComm((PetscObject)A), PETSC_ERR_ORDER, "Matrix not preallocated");
3885aed4548fSBarry 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);
3886cac4c232SBarry Smith   PetscUseMethod(A, "MatDenseGetColumnVecWrite_C", (Mat, PetscInt, Vec *), (A, col, v));
38873ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
38886947451fSStefano Zampini }
38896947451fSStefano Zampini 
38900f74d2c1SSatish Balay /*@
3891fb850c59SBarry Smith   MatDenseRestoreColumnVecWrite - Returns access to a column of a dense matrix obtained from `MatDenseGetColumnVecWrite()`.
38926947451fSStefano Zampini 
38936947451fSStefano Zampini   Collective
38946947451fSStefano Zampini 
38955ea7661aSPierre Jolivet   Input Parameters:
3896fe59aa6dSJacob Faibussowitsch + A   - the `Mat` object
38976947451fSStefano Zampini . col - the column index
38982ef1f0ffSBarry Smith - v   - the `Vec` object (may be `NULL`)
38996947451fSStefano Zampini 
39006947451fSStefano Zampini   Level: intermediate
39016947451fSStefano Zampini 
39021cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATDENSE`, `MATDENSECUDA`, `MATDENSEHIP`, `MatDenseGetColumnVec()`, `MatDenseGetColumnVecRead()`, `MatDenseGetColumnVecWrite()`, `MatDenseRestoreColumnVec()`, `MatDenseRestoreColumnVecRead()`
39036947451fSStefano Zampini @*/
3904d71ae5a4SJacob Faibussowitsch PetscErrorCode MatDenseRestoreColumnVecWrite(Mat A, PetscInt col, Vec *v)
3905d71ae5a4SJacob Faibussowitsch {
39066947451fSStefano Zampini   PetscFunctionBegin;
39076947451fSStefano Zampini   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
39086947451fSStefano Zampini   PetscValidType(A, 1);
39096947451fSStefano Zampini   PetscValidLogicalCollectiveInt(A, col, 2);
391008401ef6SPierre Jolivet   PetscCheck(A->preallocated, PetscObjectComm((PetscObject)A), PETSC_ERR_ORDER, "Matrix not preallocated");
3911aed4548fSBarry 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);
3912cac4c232SBarry Smith   PetscUseMethod(A, "MatDenseRestoreColumnVecWrite_C", (Mat, PetscInt, Vec *), (A, col, v));
39133ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
39146947451fSStefano Zampini }
39155ea7661aSPierre Jolivet 
39160f74d2c1SSatish Balay /*@
3917fb850c59SBarry Smith   MatDenseGetSubMatrix - Gives access to a block of rows and columns of a dense matrix, represented as a `Mat`.
39185ea7661aSPierre Jolivet 
39195ea7661aSPierre Jolivet   Collective
39205ea7661aSPierre Jolivet 
39215ea7661aSPierre Jolivet   Input Parameters:
3922fb850c59SBarry Smith + A      - the `Mat` object
39232ef1f0ffSBarry Smith . rbegin - the first global row index in the block (if `PETSC_DECIDE`, is 0)
39242ef1f0ffSBarry Smith . rend   - the global row index past the last one in the block (if `PETSC_DECIDE`, is `M`)
39252ef1f0ffSBarry Smith . cbegin - the first global column index in the block (if `PETSC_DECIDE`, is 0)
39262ef1f0ffSBarry Smith - cend   - the global column index past the last one in the block (if `PETSC_DECIDE`, is `N`)
39275ea7661aSPierre Jolivet 
39285ea7661aSPierre Jolivet   Output Parameter:
39295ea7661aSPierre Jolivet . v - the matrix
39305ea7661aSPierre Jolivet 
39315ea7661aSPierre Jolivet   Level: intermediate
39325ea7661aSPierre Jolivet 
39332ef1f0ffSBarry Smith   Notes:
39342ef1f0ffSBarry Smith   The matrix is owned by PETSc. Users need to call `MatDenseRestoreSubMatrix()` when the matrix is no longer needed.
39352ef1f0ffSBarry Smith 
39362ef1f0ffSBarry 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.
39372ef1f0ffSBarry Smith 
39381cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATDENSE`, `MATDENSECUDA`, `MATDENSEHIP`, `MatDenseGetColumnVec()`, `MatDenseRestoreColumnVec()`, `MatDenseRestoreSubMatrix()`
39395ea7661aSPierre Jolivet @*/
3940d71ae5a4SJacob Faibussowitsch PetscErrorCode MatDenseGetSubMatrix(Mat A, PetscInt rbegin, PetscInt rend, PetscInt cbegin, PetscInt cend, Mat *v)
3941d71ae5a4SJacob Faibussowitsch {
39425ea7661aSPierre Jolivet   PetscFunctionBegin;
39435ea7661aSPierre Jolivet   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
39445ea7661aSPierre Jolivet   PetscValidType(A, 1);
3945a2748737SPierre Jolivet   PetscValidLogicalCollectiveInt(A, rbegin, 2);
3946a2748737SPierre Jolivet   PetscValidLogicalCollectiveInt(A, rend, 3);
3947a2748737SPierre Jolivet   PetscValidLogicalCollectiveInt(A, cbegin, 4);
3948a2748737SPierre Jolivet   PetscValidLogicalCollectiveInt(A, cend, 5);
39494f572ea9SToby Isaac   PetscAssertPointer(v, 6);
3950a2748737SPierre Jolivet   if (rbegin == PETSC_DECIDE) rbegin = 0;
3951a2748737SPierre Jolivet   if (rend == PETSC_DECIDE) rend = A->rmap->N;
3952a2748737SPierre Jolivet   if (cbegin == PETSC_DECIDE) cbegin = 0;
3953a2748737SPierre Jolivet   if (cend == PETSC_DECIDE) cend = A->cmap->N;
395428b400f6SJacob Faibussowitsch   PetscCheck(A->preallocated, PetscObjectComm((PetscObject)A), PETSC_ERR_ORDER, "Matrix not preallocated");
3955a2748737SPierre 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);
3956a2748737SPierre 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);
3957a2748737SPierre 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);
3958a2748737SPierre 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);
3959a2748737SPierre Jolivet   PetscUseMethod(A, "MatDenseGetSubMatrix_C", (Mat, PetscInt, PetscInt, PetscInt, PetscInt, Mat *), (A, rbegin, rend, cbegin, cend, v));
39603ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
39615ea7661aSPierre Jolivet }
39625ea7661aSPierre Jolivet 
39630f74d2c1SSatish Balay /*@
3964fb850c59SBarry Smith   MatDenseRestoreSubMatrix - Returns access to a block of columns of a dense matrix obtained from `MatDenseGetSubMatrix()`.
39655ea7661aSPierre Jolivet 
39665ea7661aSPierre Jolivet   Collective
39675ea7661aSPierre Jolivet 
39685ea7661aSPierre Jolivet   Input Parameters:
3969fe59aa6dSJacob Faibussowitsch + A - the `Mat` object
39702ef1f0ffSBarry Smith - v - the `Mat` object (may be `NULL`)
39715ea7661aSPierre Jolivet 
39725ea7661aSPierre Jolivet   Level: intermediate
39735ea7661aSPierre Jolivet 
39741cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATDENSE`, `MATDENSECUDA`, `MATDENSEHIP`, `MatDenseGetColumnVec()`, `MatDenseRestoreColumnVec()`, `MatDenseGetSubMatrix()`
39755ea7661aSPierre Jolivet @*/
3976d71ae5a4SJacob Faibussowitsch PetscErrorCode MatDenseRestoreSubMatrix(Mat A, Mat *v)
3977d71ae5a4SJacob Faibussowitsch {
39785ea7661aSPierre Jolivet   PetscFunctionBegin;
39795ea7661aSPierre Jolivet   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
39805ea7661aSPierre Jolivet   PetscValidType(A, 1);
39814f572ea9SToby Isaac   PetscAssertPointer(v, 2);
3982cac4c232SBarry Smith   PetscUseMethod(A, "MatDenseRestoreSubMatrix_C", (Mat, Mat *), (A, v));
39833ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
39845ea7661aSPierre Jolivet }
39858a9c020eSBarry Smith 
39868a9c020eSBarry Smith #include <petscblaslapack.h>
39878a9c020eSBarry Smith #include <petsc/private/kernels/blockinvert.h>
39888a9c020eSBarry Smith 
3989d71ae5a4SJacob Faibussowitsch PetscErrorCode MatSeqDenseInvert(Mat A)
3990d71ae5a4SJacob Faibussowitsch {
3991d63b1753SJacob Faibussowitsch   PetscInt        m;
39928a9c020eSBarry Smith   const PetscReal shift = 0.0;
3993d63b1753SJacob Faibussowitsch   PetscBool       allowzeropivot, zeropivotdetected = PETSC_FALSE;
3994d63b1753SJacob Faibussowitsch   PetscScalar    *values;
39958a9c020eSBarry Smith 
39968a9c020eSBarry Smith   PetscFunctionBegin;
3997d63b1753SJacob Faibussowitsch   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
3998d63b1753SJacob Faibussowitsch   PetscCall(MatDenseGetArray(A, &values));
3999d63b1753SJacob Faibussowitsch   PetscCall(MatGetLocalSize(A, &m, NULL));
4000d63b1753SJacob Faibussowitsch   allowzeropivot = PetscNot(A->erroriffailure);
40018a9c020eSBarry Smith   /* factor and invert each block */
4002d63b1753SJacob Faibussowitsch   switch (m) {
4003d71ae5a4SJacob Faibussowitsch   case 1:
4004d71ae5a4SJacob Faibussowitsch     values[0] = (PetscScalar)1.0 / (values[0] + shift);
4005d71ae5a4SJacob Faibussowitsch     break;
40068a9c020eSBarry Smith   case 2:
40078a9c020eSBarry Smith     PetscCall(PetscKernel_A_gets_inverse_A_2(values, shift, allowzeropivot, &zeropivotdetected));
40088a9c020eSBarry Smith     if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
40098a9c020eSBarry Smith     break;
40108a9c020eSBarry Smith   case 3:
40118a9c020eSBarry Smith     PetscCall(PetscKernel_A_gets_inverse_A_3(values, shift, allowzeropivot, &zeropivotdetected));
40128a9c020eSBarry Smith     if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
40138a9c020eSBarry Smith     break;
40148a9c020eSBarry Smith   case 4:
40158a9c020eSBarry Smith     PetscCall(PetscKernel_A_gets_inverse_A_4(values, shift, allowzeropivot, &zeropivotdetected));
40168a9c020eSBarry Smith     if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
40178a9c020eSBarry Smith     break;
40189371c9d4SSatish Balay   case 5: {
40198a9c020eSBarry Smith     PetscScalar work[25];
40208a9c020eSBarry Smith     PetscInt    ipvt[5];
40218a9c020eSBarry Smith 
40228a9c020eSBarry Smith     PetscCall(PetscKernel_A_gets_inverse_A_5(values, ipvt, work, shift, allowzeropivot, &zeropivotdetected));
40238a9c020eSBarry Smith     if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
40249371c9d4SSatish Balay   } break;
40258a9c020eSBarry Smith   case 6:
40268a9c020eSBarry Smith     PetscCall(PetscKernel_A_gets_inverse_A_6(values, shift, allowzeropivot, &zeropivotdetected));
40278a9c020eSBarry Smith     if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
40288a9c020eSBarry Smith     break;
40298a9c020eSBarry Smith   case 7:
40308a9c020eSBarry Smith     PetscCall(PetscKernel_A_gets_inverse_A_7(values, shift, allowzeropivot, &zeropivotdetected));
40318a9c020eSBarry Smith     if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
40328a9c020eSBarry Smith     break;
40339371c9d4SSatish Balay   default: {
40348a9c020eSBarry Smith     PetscInt    *v_pivots, *IJ, j;
40358a9c020eSBarry Smith     PetscScalar *v_work;
40368a9c020eSBarry Smith 
4037d63b1753SJacob Faibussowitsch     PetscCall(PetscMalloc3(m, &v_work, m, &v_pivots, m, &IJ));
4038d63b1753SJacob Faibussowitsch     for (j = 0; j < m; j++) IJ[j] = j;
4039d63b1753SJacob Faibussowitsch     PetscCall(PetscKernel_A_gets_inverse_A(m, values, v_pivots, v_work, allowzeropivot, &zeropivotdetected));
40408a9c020eSBarry Smith     if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
40418a9c020eSBarry Smith     PetscCall(PetscFree3(v_work, v_pivots, IJ));
40428a9c020eSBarry Smith   }
40438a9c020eSBarry Smith   }
4044d63b1753SJacob Faibussowitsch   PetscCall(MatDenseRestoreArray(A, &values));
40453ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
40468a9c020eSBarry Smith }
4047