xref: /petsc/src/mat/impls/dense/seq/dense.c (revision 0be0d8bde7cbed9986facbcd3689d3188b7894db)
167e560aaSBarry Smith /*
267e560aaSBarry Smith      Defines the basic matrix operations for sequential dense.
347d993e7Ssuyashtn      Portions of this code are under:
447d993e7Ssuyashtn      Copyright (c) 2022 Advanced Micro Devices, Inc. All rights reserved.
567e560aaSBarry Smith */
6289bc588SBarry Smith 
7dec5eb66SMatthew G Knepley #include <../src/mat/impls/dense/seq/dense.h> /*I "petscmat.h" I*/
8cd3f9d89SJunchao Zhang #include <../src/mat/impls/dense/mpi/mpidense.h>
9c6db04a5SJed Brown #include <petscblaslapack.h>
106a63e612SBarry Smith #include <../src/mat/impls/aij/seq/aij.h>
11b2573a8aSBarry Smith 
12d71ae5a4SJacob Faibussowitsch PetscErrorCode MatSeqDenseSymmetrize_Private(Mat A, PetscBool hermitian)
13d71ae5a4SJacob Faibussowitsch {
148c178816SStefano Zampini   Mat_SeqDense *mat = (Mat_SeqDense *)A->data;
158c178816SStefano Zampini   PetscInt      j, k, n = A->rmap->n;
16ca15aa20SStefano Zampini   PetscScalar  *v;
178c178816SStefano Zampini 
188c178816SStefano Zampini   PetscFunctionBegin;
1908401ef6SPierre Jolivet   PetscCheck(A->rmap->n == A->cmap->n, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Cannot symmetrize a rectangular matrix");
209566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArray(A, &v));
218c178816SStefano Zampini   if (!hermitian) {
228c178816SStefano Zampini     for (k = 0; k < n; k++) {
23ad540459SPierre Jolivet       for (j = k; j < n; j++) v[j * mat->lda + k] = v[k * mat->lda + j];
248c178816SStefano Zampini     }
258c178816SStefano Zampini   } else {
268c178816SStefano Zampini     for (k = 0; k < n; k++) {
27ad540459SPierre Jolivet       for (j = k; j < n; j++) v[j * mat->lda + k] = PetscConj(v[k * mat->lda + j]);
288c178816SStefano Zampini     }
298c178816SStefano Zampini   }
309566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArray(A, &v));
313ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
328c178816SStefano Zampini }
338c178816SStefano Zampini 
34ff6a9541SJacob Faibussowitsch PetscErrorCode MatSeqDenseInvertFactors_Private(Mat A)
35d71ae5a4SJacob Faibussowitsch {
368c178816SStefano Zampini   Mat_SeqDense *mat = (Mat_SeqDense *)A->data;
378c178816SStefano Zampini   PetscBLASInt  info, n;
388c178816SStefano Zampini 
398c178816SStefano Zampini   PetscFunctionBegin;
403ba16761SJacob Faibussowitsch   if (!A->rmap->n || !A->cmap->n) PetscFunctionReturn(PETSC_SUCCESS);
419566063dSJacob Faibussowitsch   PetscCall(PetscBLASIntCast(A->cmap->n, &n));
428c178816SStefano Zampini   if (A->factortype == MAT_FACTOR_LU) {
4328b400f6SJacob Faibussowitsch     PetscCheck(mat->pivots, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Pivots not present");
448c178816SStefano Zampini     if (!mat->fwork) {
458c178816SStefano Zampini       mat->lfwork = n;
469566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(mat->lfwork, &mat->fwork));
478c178816SStefano Zampini     }
489566063dSJacob Faibussowitsch     PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF));
49792fecdfSBarry Smith     PetscCallBLAS("LAPACKgetri", LAPACKgetri_(&n, mat->v, &mat->lda, mat->pivots, mat->fwork, &mat->lfwork, &info));
509566063dSJacob Faibussowitsch     PetscCall(PetscFPTrapPop());
519566063dSJacob Faibussowitsch     PetscCall(PetscLogFlops((1.0 * A->cmap->n * A->cmap->n * A->cmap->n) / 3.0));
528c178816SStefano Zampini   } else if (A->factortype == MAT_FACTOR_CHOLESKY) {
53b94d7dedSBarry Smith     if (A->spd == PETSC_BOOL3_TRUE) {
549566063dSJacob Faibussowitsch       PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF));
55792fecdfSBarry Smith       PetscCallBLAS("LAPACKpotri", LAPACKpotri_("L", &n, mat->v, &mat->lda, &info));
569566063dSJacob Faibussowitsch       PetscCall(PetscFPTrapPop());
579566063dSJacob Faibussowitsch       PetscCall(MatSeqDenseSymmetrize_Private(A, PETSC_TRUE));
588c178816SStefano Zampini #if defined(PETSC_USE_COMPLEX)
59b94d7dedSBarry Smith     } else if (A->hermitian == PETSC_BOOL3_TRUE) {
6028b400f6SJacob Faibussowitsch       PetscCheck(mat->pivots, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Pivots not present");
6128b400f6SJacob Faibussowitsch       PetscCheck(mat->fwork, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Fwork not present");
629566063dSJacob Faibussowitsch       PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF));
63792fecdfSBarry Smith       PetscCallBLAS("LAPACKhetri", LAPACKhetri_("L", &n, mat->v, &mat->lda, mat->pivots, mat->fwork, &info));
649566063dSJacob Faibussowitsch       PetscCall(PetscFPTrapPop());
659566063dSJacob Faibussowitsch       PetscCall(MatSeqDenseSymmetrize_Private(A, PETSC_TRUE));
668c178816SStefano Zampini #endif
678c178816SStefano Zampini     } else { /* symmetric case */
6828b400f6SJacob Faibussowitsch       PetscCheck(mat->pivots, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Pivots not present");
6928b400f6SJacob Faibussowitsch       PetscCheck(mat->fwork, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Fwork not present");
709566063dSJacob Faibussowitsch       PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF));
71792fecdfSBarry Smith       PetscCallBLAS("LAPACKsytri", LAPACKsytri_("L", &n, mat->v, &mat->lda, mat->pivots, mat->fwork, &info));
729566063dSJacob Faibussowitsch       PetscCall(PetscFPTrapPop());
739566063dSJacob Faibussowitsch       PetscCall(MatSeqDenseSymmetrize_Private(A, PETSC_FALSE));
748c178816SStefano Zampini     }
7528b400f6SJacob Faibussowitsch     PetscCheck(!info, PETSC_COMM_SELF, PETSC_ERR_MAT_CH_ZRPVT, "Bad Inversion: zero pivot in row %" PetscInt_FMT, (PetscInt)info - 1);
769566063dSJacob Faibussowitsch     PetscCall(PetscLogFlops((1.0 * A->cmap->n * A->cmap->n * A->cmap->n) / 3.0));
778c178816SStefano Zampini   } else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Matrix must be factored to solve");
788c178816SStefano Zampini 
798c178816SStefano Zampini   A->ops->solve             = NULL;
808c178816SStefano Zampini   A->ops->matsolve          = NULL;
818c178816SStefano Zampini   A->ops->solvetranspose    = NULL;
828c178816SStefano Zampini   A->ops->matsolvetranspose = NULL;
838c178816SStefano Zampini   A->ops->solveadd          = NULL;
848c178816SStefano Zampini   A->ops->solvetransposeadd = NULL;
858c178816SStefano Zampini   A->factortype             = MAT_FACTOR_NONE;
869566063dSJacob Faibussowitsch   PetscCall(PetscFree(A->solvertype));
873ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
888c178816SStefano Zampini }
898c178816SStefano Zampini 
9066976f2fSJacob Faibussowitsch static PetscErrorCode MatZeroRowsColumns_SeqDense(Mat A, PetscInt N, const PetscInt rows[], PetscScalar diag, Vec x, Vec b)
91d71ae5a4SJacob Faibussowitsch {
923f49a652SStefano Zampini   Mat_SeqDense      *l = (Mat_SeqDense *)A->data;
933f49a652SStefano Zampini   PetscInt           m = l->lda, n = A->cmap->n, r = A->rmap->n, i, j;
94ca15aa20SStefano Zampini   PetscScalar       *slot, *bb, *v;
953f49a652SStefano Zampini   const PetscScalar *xx;
963f49a652SStefano Zampini 
973f49a652SStefano Zampini   PetscFunctionBegin;
9876bd3646SJed Brown   if (PetscDefined(USE_DEBUG)) {
993f49a652SStefano Zampini     for (i = 0; i < N; i++) {
10008401ef6SPierre Jolivet       PetscCheck(rows[i] >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Negative row requested to be zeroed");
10108401ef6SPierre Jolivet       PetscCheck(rows[i] < A->rmap->n, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Row %" PetscInt_FMT " requested to be zeroed greater than or equal number of rows %" PetscInt_FMT, rows[i], A->rmap->n);
10208401ef6SPierre Jolivet       PetscCheck(rows[i] < A->cmap->n, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Col %" PetscInt_FMT " requested to be zeroed greater than or equal number of cols %" PetscInt_FMT, rows[i], A->cmap->n);
1033f49a652SStefano Zampini     }
10476bd3646SJed Brown   }
1053ba16761SJacob Faibussowitsch   if (!N) PetscFunctionReturn(PETSC_SUCCESS);
1063f49a652SStefano Zampini 
107dd8e379bSPierre Jolivet   /* fix right-hand side if needed */
1083f49a652SStefano Zampini   if (x && b) {
1096c4d906cSStefano Zampini     Vec xt;
1106c4d906cSStefano Zampini 
11108401ef6SPierre Jolivet     PetscCheck(A->rmap->n == A->cmap->n, PETSC_COMM_SELF, PETSC_ERR_SUP, "Only coded for square matrices");
1129566063dSJacob Faibussowitsch     PetscCall(VecDuplicate(x, &xt));
1139566063dSJacob Faibussowitsch     PetscCall(VecCopy(x, xt));
1149566063dSJacob Faibussowitsch     PetscCall(VecScale(xt, -1.0));
1159566063dSJacob Faibussowitsch     PetscCall(MatMultAdd(A, xt, b, b));
1169566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&xt));
1179566063dSJacob Faibussowitsch     PetscCall(VecGetArrayRead(x, &xx));
1189566063dSJacob Faibussowitsch     PetscCall(VecGetArray(b, &bb));
1193f49a652SStefano Zampini     for (i = 0; i < N; i++) bb[rows[i]] = diag * xx[rows[i]];
1209566063dSJacob Faibussowitsch     PetscCall(VecRestoreArrayRead(x, &xx));
1219566063dSJacob Faibussowitsch     PetscCall(VecRestoreArray(b, &bb));
1223f49a652SStefano Zampini   }
1233f49a652SStefano Zampini 
1249566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArray(A, &v));
1253f49a652SStefano Zampini   for (i = 0; i < N; i++) {
126ca15aa20SStefano Zampini     slot = v + rows[i] * m;
1279566063dSJacob Faibussowitsch     PetscCall(PetscArrayzero(slot, r));
1283f49a652SStefano Zampini   }
1293f49a652SStefano Zampini   for (i = 0; i < N; i++) {
130ca15aa20SStefano Zampini     slot = v + rows[i];
1319371c9d4SSatish Balay     for (j = 0; j < n; j++) {
1329371c9d4SSatish Balay       *slot = 0.0;
1339371c9d4SSatish Balay       slot += m;
1349371c9d4SSatish Balay     }
1353f49a652SStefano Zampini   }
1363f49a652SStefano Zampini   if (diag != 0.0) {
13708401ef6SPierre Jolivet     PetscCheck(A->rmap->n == A->cmap->n, PETSC_COMM_SELF, PETSC_ERR_SUP, "Only coded for square matrices");
1383f49a652SStefano Zampini     for (i = 0; i < N; i++) {
139ca15aa20SStefano Zampini       slot  = v + (m + 1) * rows[i];
1403f49a652SStefano Zampini       *slot = diag;
1413f49a652SStefano Zampini     }
1423f49a652SStefano Zampini   }
1439566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArray(A, &v));
1443ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1453f49a652SStefano Zampini }
1463f49a652SStefano Zampini 
147d71ae5a4SJacob Faibussowitsch PETSC_INTERN PetscErrorCode MatConvert_SeqAIJ_SeqDense(Mat A, MatType newtype, MatReuse reuse, Mat *newmat)
148d71ae5a4SJacob Faibussowitsch {
149a13144ffSStefano Zampini   Mat              B = NULL;
150b49cda9fSStefano Zampini   Mat_SeqAIJ      *a = (Mat_SeqAIJ *)A->data;
151b49cda9fSStefano Zampini   Mat_SeqDense    *b;
152b49cda9fSStefano Zampini   PetscInt        *ai = a->i, *aj = a->j, m = A->rmap->N, n = A->cmap->N, i;
1532e5835c6SStefano Zampini   const MatScalar *av;
154a13144ffSStefano Zampini   PetscBool        isseqdense;
155b49cda9fSStefano Zampini 
156b49cda9fSStefano Zampini   PetscFunctionBegin;
157a13144ffSStefano Zampini   if (reuse == MAT_REUSE_MATRIX) {
1589566063dSJacob Faibussowitsch     PetscCall(PetscObjectTypeCompare((PetscObject)*newmat, MATSEQDENSE, &isseqdense));
159f4f49eeaSPierre Jolivet     PetscCheck(isseqdense, PetscObjectComm((PetscObject)*newmat), PETSC_ERR_USER, "Cannot reuse matrix of type %s", ((PetscObject)*newmat)->type_name);
160a13144ffSStefano Zampini   }
161a13144ffSStefano Zampini   if (reuse != MAT_REUSE_MATRIX) {
1629566063dSJacob Faibussowitsch     PetscCall(MatCreate(PetscObjectComm((PetscObject)A), &B));
1639566063dSJacob Faibussowitsch     PetscCall(MatSetSizes(B, m, n, m, n));
1649566063dSJacob Faibussowitsch     PetscCall(MatSetType(B, MATSEQDENSE));
1659566063dSJacob Faibussowitsch     PetscCall(MatSeqDenseSetPreallocation(B, NULL));
166f4f49eeaSPierre Jolivet     b = (Mat_SeqDense *)B->data;
167a13144ffSStefano Zampini   } else {
168a13144ffSStefano Zampini     b = (Mat_SeqDense *)((*newmat)->data);
169e1ea5af7SJose E. Roman     for (i = 0; i < n; i++) PetscCall(PetscArrayzero(b->v + i * b->lda, m));
170a13144ffSStefano Zampini   }
1719566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJGetArrayRead(A, &av));
172b49cda9fSStefano Zampini   for (i = 0; i < m; i++) {
173b49cda9fSStefano Zampini     PetscInt j;
174b49cda9fSStefano Zampini     for (j = 0; j < ai[1] - ai[0]; j++) {
175e1ea5af7SJose E. Roman       b->v[*aj * b->lda + i] = *av;
176b49cda9fSStefano Zampini       aj++;
177b49cda9fSStefano Zampini       av++;
178b49cda9fSStefano Zampini     }
179b49cda9fSStefano Zampini     ai++;
180b49cda9fSStefano Zampini   }
1819566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJRestoreArrayRead(A, &av));
182b49cda9fSStefano Zampini 
183511c6705SHong Zhang   if (reuse == MAT_INPLACE_MATRIX) {
1849566063dSJacob Faibussowitsch     PetscCall(MatAssemblyBegin(B, MAT_FINAL_ASSEMBLY));
1859566063dSJacob Faibussowitsch     PetscCall(MatAssemblyEnd(B, MAT_FINAL_ASSEMBLY));
1869566063dSJacob Faibussowitsch     PetscCall(MatHeaderReplace(A, &B));
187b49cda9fSStefano Zampini   } else {
188a13144ffSStefano Zampini     if (B) *newmat = B;
1899566063dSJacob Faibussowitsch     PetscCall(MatAssemblyBegin(*newmat, MAT_FINAL_ASSEMBLY));
1909566063dSJacob Faibussowitsch     PetscCall(MatAssemblyEnd(*newmat, MAT_FINAL_ASSEMBLY));
191b49cda9fSStefano Zampini   }
1923ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
193b49cda9fSStefano Zampini }
194b49cda9fSStefano Zampini 
195d71ae5a4SJacob Faibussowitsch PETSC_INTERN PetscErrorCode MatConvert_SeqDense_SeqAIJ(Mat A, MatType newtype, MatReuse reuse, Mat *newmat)
196d71ae5a4SJacob Faibussowitsch {
1976d4ec7b0SPierre Jolivet   Mat           B = NULL;
1986a63e612SBarry Smith   Mat_SeqDense *a = (Mat_SeqDense *)A->data;
1999399e1b8SMatthew G. Knepley   PetscInt      i, j;
2009399e1b8SMatthew G. Knepley   PetscInt     *rows, *nnz;
2019399e1b8SMatthew G. Knepley   MatScalar    *aa = a->v, *vals;
2026a63e612SBarry Smith 
2036a63e612SBarry Smith   PetscFunctionBegin;
2049566063dSJacob Faibussowitsch   PetscCall(PetscCalloc3(A->rmap->n, &rows, A->rmap->n, &nnz, A->rmap->n, &vals));
2056d4ec7b0SPierre Jolivet   if (reuse != MAT_REUSE_MATRIX) {
2069566063dSJacob Faibussowitsch     PetscCall(MatCreate(PetscObjectComm((PetscObject)A), &B));
2079566063dSJacob Faibussowitsch     PetscCall(MatSetSizes(B, A->rmap->n, A->cmap->n, A->rmap->N, A->cmap->N));
2089566063dSJacob Faibussowitsch     PetscCall(MatSetType(B, MATSEQAIJ));
2099399e1b8SMatthew G. Knepley     for (j = 0; j < A->cmap->n; j++) {
2109371c9d4SSatish Balay       for (i = 0; i < A->rmap->n; i++)
2119371c9d4SSatish Balay         if (aa[i] != 0.0 || (i == j && A->cmap->n == A->rmap->n)) ++nnz[i];
2126a63e612SBarry Smith       aa += a->lda;
2136a63e612SBarry Smith     }
2149566063dSJacob Faibussowitsch     PetscCall(MatSeqAIJSetPreallocation(B, PETSC_DETERMINE, nnz));
2156d4ec7b0SPierre Jolivet   } else B = *newmat;
2169399e1b8SMatthew G. Knepley   aa = a->v;
2179399e1b8SMatthew G. Knepley   for (j = 0; j < A->cmap->n; j++) {
2189399e1b8SMatthew G. Knepley     PetscInt numRows = 0;
2199371c9d4SSatish Balay     for (i = 0; i < A->rmap->n; i++)
2209371c9d4SSatish Balay       if (aa[i] != 0.0 || (i == j && A->cmap->n == A->rmap->n)) {
2219371c9d4SSatish Balay         rows[numRows]   = i;
2229371c9d4SSatish Balay         vals[numRows++] = aa[i];
2239371c9d4SSatish Balay       }
2249566063dSJacob Faibussowitsch     PetscCall(MatSetValues(B, numRows, rows, 1, &j, vals, INSERT_VALUES));
2259399e1b8SMatthew G. Knepley     aa += a->lda;
2269399e1b8SMatthew G. Knepley   }
2279566063dSJacob Faibussowitsch   PetscCall(PetscFree3(rows, nnz, vals));
2289566063dSJacob Faibussowitsch   PetscCall(MatAssemblyBegin(B, MAT_FINAL_ASSEMBLY));
2299566063dSJacob Faibussowitsch   PetscCall(MatAssemblyEnd(B, MAT_FINAL_ASSEMBLY));
2306a63e612SBarry Smith 
231511c6705SHong Zhang   if (reuse == MAT_INPLACE_MATRIX) {
2329566063dSJacob Faibussowitsch     PetscCall(MatHeaderReplace(A, &B));
2336d4ec7b0SPierre Jolivet   } else if (reuse != MAT_REUSE_MATRIX) *newmat = B;
2343ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2356a63e612SBarry Smith }
2366a63e612SBarry Smith 
237d71ae5a4SJacob Faibussowitsch PetscErrorCode MatAXPY_SeqDense(Mat Y, PetscScalar alpha, Mat X, MatStructure str)
238d71ae5a4SJacob Faibussowitsch {
2391987afe7SBarry Smith   Mat_SeqDense      *x = (Mat_SeqDense *)X->data, *y = (Mat_SeqDense *)Y->data;
240ca15aa20SStefano Zampini   const PetscScalar *xv;
241ca15aa20SStefano Zampini   PetscScalar       *yv;
24223fff9afSBarry Smith   PetscBLASInt       N, m, ldax = 0, lday = 0, one = 1;
2433a40ed3dSBarry Smith 
2443a40ed3dSBarry Smith   PetscFunctionBegin;
2459566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArrayRead(X, &xv));
2469566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArray(Y, &yv));
2479566063dSJacob Faibussowitsch   PetscCall(PetscBLASIntCast(X->rmap->n * X->cmap->n, &N));
2489566063dSJacob Faibussowitsch   PetscCall(PetscBLASIntCast(X->rmap->n, &m));
2499566063dSJacob Faibussowitsch   PetscCall(PetscBLASIntCast(x->lda, &ldax));
2509566063dSJacob Faibussowitsch   PetscCall(PetscBLASIntCast(y->lda, &lday));
251a5ce6ee0Svictorle   if (ldax > m || lday > m) {
2528e3a54c0SPierre 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));
253a5ce6ee0Svictorle   } else {
254792fecdfSBarry Smith     PetscCallBLAS("BLASaxpy", BLASaxpy_(&N, &alpha, xv, &one, yv, &one));
255a5ce6ee0Svictorle   }
2569566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArrayRead(X, &xv));
2579566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArray(Y, &yv));
2589566063dSJacob Faibussowitsch   PetscCall(PetscLogFlops(PetscMax(2.0 * N - 1, 0)));
2593ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2601987afe7SBarry Smith }
2611987afe7SBarry Smith 
262d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatGetInfo_SeqDense(Mat A, MatInfoType flag, MatInfo *info)
263d71ae5a4SJacob Faibussowitsch {
264ca15aa20SStefano Zampini   PetscLogDouble N = A->rmap->n * A->cmap->n;
2653a40ed3dSBarry Smith 
2663a40ed3dSBarry Smith   PetscFunctionBegin;
2674e220ebcSLois Curfman McInnes   info->block_size        = 1.0;
268ca15aa20SStefano Zampini   info->nz_allocated      = N;
269ca15aa20SStefano Zampini   info->nz_used           = N;
270ca15aa20SStefano Zampini   info->nz_unneeded       = 0;
271ca15aa20SStefano Zampini   info->assemblies        = A->num_ass;
2724e220ebcSLois Curfman McInnes   info->mallocs           = 0;
2734dfa11a4SJacob Faibussowitsch   info->memory            = 0; /* REVIEW ME */
2744e220ebcSLois Curfman McInnes   info->fill_ratio_given  = 0;
2754e220ebcSLois Curfman McInnes   info->fill_ratio_needed = 0;
2764e220ebcSLois Curfman McInnes   info->factor_mallocs    = 0;
2773ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
278289bc588SBarry Smith }
279289bc588SBarry Smith 
280d71ae5a4SJacob Faibussowitsch PetscErrorCode MatScale_SeqDense(Mat A, PetscScalar alpha)
281d71ae5a4SJacob Faibussowitsch {
282273d9f13SBarry Smith   Mat_SeqDense *a = (Mat_SeqDense *)A->data;
283ca15aa20SStefano Zampini   PetscScalar  *v;
28423fff9afSBarry Smith   PetscBLASInt  one = 1, j, nz, lda = 0;
28580cd9d93SLois Curfman McInnes 
2863a40ed3dSBarry Smith   PetscFunctionBegin;
2879566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArray(A, &v));
2889566063dSJacob Faibussowitsch   PetscCall(PetscBLASIntCast(a->lda, &lda));
289d0f46423SBarry Smith   if (lda > A->rmap->n) {
2909566063dSJacob Faibussowitsch     PetscCall(PetscBLASIntCast(A->rmap->n, &nz));
29148a46eb9SPierre Jolivet     for (j = 0; j < A->cmap->n; j++) PetscCallBLAS("BLASscal", BLASscal_(&nz, &alpha, v + j * lda, &one));
292a5ce6ee0Svictorle   } else {
2939566063dSJacob Faibussowitsch     PetscCall(PetscBLASIntCast(A->rmap->n * A->cmap->n, &nz));
294792fecdfSBarry Smith     PetscCallBLAS("BLASscal", BLASscal_(&nz, &alpha, v, &one));
295a5ce6ee0Svictorle   }
29604cbc005SJose E. Roman   PetscCall(PetscLogFlops(A->rmap->n * A->cmap->n));
2979566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArray(A, &v));
2983ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
29980cd9d93SLois Curfman McInnes }
30080cd9d93SLois Curfman McInnes 
301d71ae5a4SJacob Faibussowitsch PetscErrorCode MatShift_SeqDense(Mat A, PetscScalar alpha)
302d71ae5a4SJacob Faibussowitsch {
3032f605a99SJose E. Roman   Mat_SeqDense *a = (Mat_SeqDense *)A->data;
3042f605a99SJose E. Roman   PetscScalar  *v;
3052f605a99SJose E. Roman   PetscInt      j, k;
3062f605a99SJose E. Roman 
3072f605a99SJose E. Roman   PetscFunctionBegin;
3082f605a99SJose E. Roman   PetscCall(MatDenseGetArray(A, &v));
3092f605a99SJose E. Roman   k = PetscMin(A->rmap->n, A->cmap->n);
3102f605a99SJose E. Roman   for (j = 0; j < k; j++) v[j + j * a->lda] += alpha;
3112f605a99SJose E. Roman   PetscCall(PetscLogFlops(k));
3122f605a99SJose E. Roman   PetscCall(MatDenseRestoreArray(A, &v));
3133ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3142f605a99SJose E. Roman }
3152f605a99SJose E. Roman 
316d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatIsHermitian_SeqDense(Mat A, PetscReal rtol, PetscBool *fl)
317d71ae5a4SJacob Faibussowitsch {
3181cbb95d3SBarry Smith   Mat_SeqDense      *a = (Mat_SeqDense *)A->data;
319ca15aa20SStefano Zampini   PetscInt           i, j, m = A->rmap->n, N = a->lda;
320ca15aa20SStefano Zampini   const PetscScalar *v;
3211cbb95d3SBarry Smith 
3221cbb95d3SBarry Smith   PetscFunctionBegin;
3231cbb95d3SBarry Smith   *fl = PETSC_FALSE;
3243ba16761SJacob Faibussowitsch   if (A->rmap->n != A->cmap->n) PetscFunctionReturn(PETSC_SUCCESS);
3259566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArrayRead(A, &v));
3261cbb95d3SBarry Smith   for (i = 0; i < m; i++) {
327ca15aa20SStefano Zampini     for (j = i; j < m; j++) {
328ad540459SPierre Jolivet       if (PetscAbsScalar(v[i + j * N] - PetscConj(v[j + i * N])) > rtol) goto restore;
3291cbb95d3SBarry Smith     }
330637a0070SStefano Zampini   }
3311cbb95d3SBarry Smith   *fl = PETSC_TRUE;
332637a0070SStefano Zampini restore:
3339566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArrayRead(A, &v));
3343ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
335637a0070SStefano Zampini }
336637a0070SStefano Zampini 
337d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatIsSymmetric_SeqDense(Mat A, PetscReal rtol, PetscBool *fl)
338d71ae5a4SJacob Faibussowitsch {
339637a0070SStefano Zampini   Mat_SeqDense      *a = (Mat_SeqDense *)A->data;
340637a0070SStefano Zampini   PetscInt           i, j, m = A->rmap->n, N = a->lda;
341637a0070SStefano Zampini   const PetscScalar *v;
342637a0070SStefano Zampini 
343637a0070SStefano Zampini   PetscFunctionBegin;
344637a0070SStefano Zampini   *fl = PETSC_FALSE;
3453ba16761SJacob Faibussowitsch   if (A->rmap->n != A->cmap->n) PetscFunctionReturn(PETSC_SUCCESS);
3469566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArrayRead(A, &v));
347637a0070SStefano Zampini   for (i = 0; i < m; i++) {
348637a0070SStefano Zampini     for (j = i; j < m; j++) {
349ad540459SPierre Jolivet       if (PetscAbsScalar(v[i + j * N] - v[j + i * N]) > rtol) goto restore;
350637a0070SStefano Zampini     }
351637a0070SStefano Zampini   }
352637a0070SStefano Zampini   *fl = PETSC_TRUE;
353637a0070SStefano Zampini restore:
3549566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArrayRead(A, &v));
3553ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3561cbb95d3SBarry Smith }
3571cbb95d3SBarry Smith 
358d71ae5a4SJacob Faibussowitsch PetscErrorCode MatDuplicateNoCreate_SeqDense(Mat newi, Mat A, MatDuplicateOption cpvalues)
359d71ae5a4SJacob Faibussowitsch {
360ca15aa20SStefano Zampini   Mat_SeqDense *mat = (Mat_SeqDense *)A->data;
36123fc5dcaSStefano Zampini   PetscInt      lda = (PetscInt)mat->lda, j, m, nlda = lda;
36275f6d85dSStefano Zampini   PetscBool     isdensecpu;
363b24902e0SBarry Smith 
364b24902e0SBarry Smith   PetscFunctionBegin;
3659566063dSJacob Faibussowitsch   PetscCall(PetscLayoutReference(A->rmap, &newi->rmap));
3669566063dSJacob Faibussowitsch   PetscCall(PetscLayoutReference(A->cmap, &newi->cmap));
36723fc5dcaSStefano Zampini   if (cpvalues == MAT_SHARE_NONZERO_PATTERN) { /* propagate LDA */
3689566063dSJacob Faibussowitsch     PetscCall(MatDenseSetLDA(newi, lda));
36923fc5dcaSStefano Zampini   }
3709566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)newi, MATSEQDENSE, &isdensecpu));
3719566063dSJacob Faibussowitsch   if (isdensecpu) PetscCall(MatSeqDenseSetPreallocation(newi, NULL));
372b24902e0SBarry Smith   if (cpvalues == MAT_COPY_VALUES) {
373ca15aa20SStefano Zampini     const PetscScalar *av;
374ca15aa20SStefano Zampini     PetscScalar       *v;
375ca15aa20SStefano Zampini 
3769566063dSJacob Faibussowitsch     PetscCall(MatDenseGetArrayRead(A, &av));
3779566063dSJacob Faibussowitsch     PetscCall(MatDenseGetArrayWrite(newi, &v));
3789566063dSJacob Faibussowitsch     PetscCall(MatDenseGetLDA(newi, &nlda));
379d0f46423SBarry Smith     m = A->rmap->n;
38023fc5dcaSStefano Zampini     if (lda > m || nlda > m) {
3818e3a54c0SPierre Jolivet       for (j = 0; j < A->cmap->n; j++) PetscCall(PetscArraycpy(PetscSafePointerPlusOffset(v, j * nlda), PetscSafePointerPlusOffset(av, j * lda), m));
382b24902e0SBarry Smith     } else {
3839566063dSJacob Faibussowitsch       PetscCall(PetscArraycpy(v, av, A->rmap->n * A->cmap->n));
384b24902e0SBarry Smith     }
3859566063dSJacob Faibussowitsch     PetscCall(MatDenseRestoreArrayWrite(newi, &v));
3869566063dSJacob Faibussowitsch     PetscCall(MatDenseRestoreArrayRead(A, &av));
387b24902e0SBarry Smith   }
3883ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
389b24902e0SBarry Smith }
390b24902e0SBarry Smith 
391d71ae5a4SJacob Faibussowitsch PetscErrorCode MatDuplicate_SeqDense(Mat A, MatDuplicateOption cpvalues, Mat *newmat)
392d71ae5a4SJacob Faibussowitsch {
3933a40ed3dSBarry Smith   PetscFunctionBegin;
3949566063dSJacob Faibussowitsch   PetscCall(MatCreate(PetscObjectComm((PetscObject)A), newmat));
3959566063dSJacob Faibussowitsch   PetscCall(MatSetSizes(*newmat, A->rmap->n, A->cmap->n, A->rmap->n, A->cmap->n));
3969566063dSJacob Faibussowitsch   PetscCall(MatSetType(*newmat, ((PetscObject)A)->type_name));
3979566063dSJacob Faibussowitsch   PetscCall(MatDuplicateNoCreate_SeqDense(*newmat, A, cpvalues));
3983ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
399b24902e0SBarry Smith }
400b24902e0SBarry Smith 
401d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatSolve_SeqDense_Internal_LU(Mat A, PetscScalar *x, PetscBLASInt ldx, PetscBLASInt m, PetscBLASInt nrhs, PetscBLASInt k, PetscBool T)
402d71ae5a4SJacob Faibussowitsch {
403c0bbcb79SLois Curfman McInnes   Mat_SeqDense *mat = (Mat_SeqDense *)A->data;
4044396437dSToby Isaac   PetscBLASInt  info;
40567e560aaSBarry Smith 
4063a40ed3dSBarry Smith   PetscFunctionBegin;
4079566063dSJacob Faibussowitsch   PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF));
408792fecdfSBarry Smith   PetscCallBLAS("LAPACKgetrs", LAPACKgetrs_(T ? "T" : "N", &m, &nrhs, mat->v, &mat->lda, mat->pivots, x, &m, &info));
4099566063dSJacob Faibussowitsch   PetscCall(PetscFPTrapPop());
41005fcb23eSStefano Zampini   PetscCheck(!info, PETSC_COMM_SELF, PETSC_ERR_LIB, "GETRS - Bad solve %d", (int)info);
4119566063dSJacob Faibussowitsch   PetscCall(PetscLogFlops(nrhs * (2.0 * m * m - m)));
4123ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4134396437dSToby Isaac }
4144396437dSToby Isaac 
4154396437dSToby Isaac static PetscErrorCode MatConjugate_SeqDense(Mat);
4164396437dSToby Isaac 
417d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatSolve_SeqDense_Internal_Cholesky(Mat A, PetscScalar *x, PetscBLASInt ldx, PetscBLASInt m, PetscBLASInt nrhs, PetscBLASInt k, PetscBool T)
418d71ae5a4SJacob Faibussowitsch {
4194396437dSToby Isaac   Mat_SeqDense *mat = (Mat_SeqDense *)A->data;
4204396437dSToby Isaac   PetscBLASInt  info;
4214396437dSToby Isaac 
4224396437dSToby Isaac   PetscFunctionBegin;
423b94d7dedSBarry Smith   if (A->spd == PETSC_BOOL3_TRUE) {
4249566063dSJacob Faibussowitsch     if (PetscDefined(USE_COMPLEX) && T) PetscCall(MatConjugate_SeqDense(A));
4259566063dSJacob Faibussowitsch     PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF));
426792fecdfSBarry Smith     PetscCallBLAS("LAPACKpotrs", LAPACKpotrs_("L", &m, &nrhs, mat->v, &mat->lda, x, &m, &info));
4279566063dSJacob Faibussowitsch     PetscCall(PetscFPTrapPop());
42805fcb23eSStefano Zampini     PetscCheck(!info, PETSC_COMM_SELF, PETSC_ERR_LIB, "POTRS Bad solve %d", (int)info);
4299566063dSJacob Faibussowitsch     if (PetscDefined(USE_COMPLEX) && T) PetscCall(MatConjugate_SeqDense(A));
430a49dc2a2SStefano Zampini #if defined(PETSC_USE_COMPLEX)
431b94d7dedSBarry Smith   } else if (A->hermitian == PETSC_BOOL3_TRUE) {
4329566063dSJacob Faibussowitsch     if (T) PetscCall(MatConjugate_SeqDense(A));
4339566063dSJacob Faibussowitsch     PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF));
434792fecdfSBarry Smith     PetscCallBLAS("LAPACKhetrs", LAPACKhetrs_("L", &m, &nrhs, mat->v, &mat->lda, mat->pivots, x, &m, &info));
4359566063dSJacob Faibussowitsch     PetscCall(PetscFPTrapPop());
43605fcb23eSStefano Zampini     PetscCheck(!info, PETSC_COMM_SELF, PETSC_ERR_LIB, "HETRS Bad solve %d", (int)info);
4379566063dSJacob Faibussowitsch     if (T) PetscCall(MatConjugate_SeqDense(A));
438a49dc2a2SStefano Zampini #endif
439a49dc2a2SStefano Zampini   } else { /* symmetric case */
4409566063dSJacob Faibussowitsch     PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF));
441792fecdfSBarry Smith     PetscCallBLAS("LAPACKsytrs", LAPACKsytrs_("L", &m, &nrhs, mat->v, &mat->lda, mat->pivots, x, &m, &info));
4429566063dSJacob Faibussowitsch     PetscCall(PetscFPTrapPop());
44305fcb23eSStefano Zampini     PetscCheck(!info, PETSC_COMM_SELF, PETSC_ERR_LIB, "SYTRS Bad solve %d", (int)info);
444a49dc2a2SStefano Zampini   }
4459566063dSJacob Faibussowitsch   PetscCall(PetscLogFlops(nrhs * (2.0 * m * m - m)));
4463ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4474396437dSToby Isaac }
44885e2c93fSHong Zhang 
449d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatSolve_SeqDense_Internal_QR(Mat A, PetscScalar *x, PetscBLASInt ldx, PetscBLASInt m, PetscBLASInt nrhs, PetscBLASInt k)
450d71ae5a4SJacob Faibussowitsch {
4514396437dSToby Isaac   Mat_SeqDense *mat = (Mat_SeqDense *)A->data;
4524396437dSToby Isaac   PetscBLASInt  info;
4534396437dSToby Isaac   char          trans;
4544396437dSToby Isaac 
4554396437dSToby Isaac   PetscFunctionBegin;
4564905a7bcSToby Isaac   if (PetscDefined(USE_COMPLEX)) {
4574905a7bcSToby Isaac     trans = 'C';
4584905a7bcSToby Isaac   } else {
4594905a7bcSToby Isaac     trans = 'T';
4604905a7bcSToby Isaac   }
4619566063dSJacob Faibussowitsch   PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF));
46205fcb23eSStefano Zampini   { /* lwork depends on the number of right-hand sides */
46305fcb23eSStefano Zampini     PetscBLASInt nlfwork, lfwork = -1;
46405fcb23eSStefano Zampini     PetscScalar  fwork;
46505fcb23eSStefano Zampini 
466792fecdfSBarry Smith     PetscCallBLAS("LAPACKormqr", LAPACKormqr_("L", &trans, &m, &nrhs, &mat->rank, mat->v, &mat->lda, mat->tau, x, &ldx, &fwork, &lfwork, &info));
46705fcb23eSStefano Zampini     nlfwork = (PetscBLASInt)PetscRealPart(fwork);
46805fcb23eSStefano Zampini     if (nlfwork > mat->lfwork) {
46905fcb23eSStefano Zampini       mat->lfwork = nlfwork;
47005fcb23eSStefano Zampini       PetscCall(PetscFree(mat->fwork));
47105fcb23eSStefano Zampini       PetscCall(PetscMalloc1(mat->lfwork, &mat->fwork));
47205fcb23eSStefano Zampini     }
47305fcb23eSStefano Zampini   }
474792fecdfSBarry Smith   PetscCallBLAS("LAPACKormqr", LAPACKormqr_("L", &trans, &m, &nrhs, &mat->rank, mat->v, &mat->lda, mat->tau, x, &ldx, mat->fwork, &mat->lfwork, &info));
4759566063dSJacob Faibussowitsch   PetscCall(PetscFPTrapPop());
47605fcb23eSStefano Zampini   PetscCheck(!info, PETSC_COMM_SELF, PETSC_ERR_LIB, "ORMQR - Bad orthogonal transform %d", (int)info);
4779566063dSJacob Faibussowitsch   PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF));
478792fecdfSBarry Smith   PetscCallBLAS("LAPACKtrtrs", LAPACKtrtrs_("U", "N", "N", &mat->rank, &nrhs, mat->v, &mat->lda, x, &ldx, &info));
4799566063dSJacob Faibussowitsch   PetscCall(PetscFPTrapPop());
48005fcb23eSStefano Zampini   PetscCheck(!info, PETSC_COMM_SELF, PETSC_ERR_LIB, "TRTRS - Bad triangular solve %d", (int)info);
4814905a7bcSToby Isaac   for (PetscInt j = 0; j < nrhs; j++) {
482ad540459SPierre Jolivet     for (PetscInt i = mat->rank; i < k; i++) x[j * ldx + i] = 0.;
4834905a7bcSToby Isaac   }
4849566063dSJacob Faibussowitsch   PetscCall(PetscLogFlops(nrhs * (4.0 * m * mat->rank - PetscSqr(mat->rank))));
4853ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4864905a7bcSToby Isaac }
4874905a7bcSToby Isaac 
488d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatSolveTranspose_SeqDense_Internal_QR(Mat A, PetscScalar *x, PetscBLASInt ldx, PetscBLASInt m, PetscBLASInt nrhs, PetscBLASInt k)
489d71ae5a4SJacob Faibussowitsch {
4904396437dSToby Isaac   Mat_SeqDense *mat = (Mat_SeqDense *)A->data;
4914396437dSToby Isaac   PetscBLASInt  info;
4924396437dSToby Isaac 
4934396437dSToby Isaac   PetscFunctionBegin;
4944396437dSToby Isaac   if (A->rmap->n == A->cmap->n && mat->rank == A->rmap->n) {
4959566063dSJacob Faibussowitsch     PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF));
496792fecdfSBarry Smith     PetscCallBLAS("LAPACKtrtrs", LAPACKtrtrs_("U", "T", "N", &m, &nrhs, mat->v, &mat->lda, x, &ldx, &info));
4979566063dSJacob Faibussowitsch     PetscCall(PetscFPTrapPop());
49805fcb23eSStefano Zampini     PetscCheck(!info, PETSC_COMM_SELF, PETSC_ERR_LIB, "TRTRS - Bad triangular solve %d", (int)info);
4999566063dSJacob Faibussowitsch     if (PetscDefined(USE_COMPLEX)) PetscCall(MatConjugate_SeqDense(A));
50005fcb23eSStefano Zampini     { /* lwork depends on the number of right-hand sides */
50105fcb23eSStefano Zampini       PetscBLASInt nlfwork, lfwork = -1;
50205fcb23eSStefano Zampini       PetscScalar  fwork;
50305fcb23eSStefano Zampini 
504792fecdfSBarry Smith       PetscCallBLAS("LAPACKormqr", LAPACKormqr_("L", "N", &m, &nrhs, &mat->rank, mat->v, &mat->lda, mat->tau, x, &ldx, &fwork, &lfwork, &info));
50505fcb23eSStefano Zampini       nlfwork = (PetscBLASInt)PetscRealPart(fwork);
50605fcb23eSStefano Zampini       if (nlfwork > mat->lfwork) {
50705fcb23eSStefano Zampini         mat->lfwork = nlfwork;
50805fcb23eSStefano Zampini         PetscCall(PetscFree(mat->fwork));
50905fcb23eSStefano Zampini         PetscCall(PetscMalloc1(mat->lfwork, &mat->fwork));
51005fcb23eSStefano Zampini       }
51105fcb23eSStefano Zampini     }
5129566063dSJacob Faibussowitsch     PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF));
513792fecdfSBarry Smith     PetscCallBLAS("LAPACKormqr", LAPACKormqr_("L", "N", &m, &nrhs, &mat->rank, mat->v, &mat->lda, mat->tau, x, &ldx, mat->fwork, &mat->lfwork, &info));
5149566063dSJacob Faibussowitsch     PetscCall(PetscFPTrapPop());
51505fcb23eSStefano Zampini     PetscCheck(!info, PETSC_COMM_SELF, PETSC_ERR_LIB, "ORMQR - Bad orthogonal transform %d", (int)info);
5169566063dSJacob Faibussowitsch     if (PetscDefined(USE_COMPLEX)) PetscCall(MatConjugate_SeqDense(A));
5174396437dSToby Isaac   } else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "QR factored matrix cannot be used for transpose solve");
5189566063dSJacob Faibussowitsch   PetscCall(PetscLogFlops(nrhs * (4.0 * m * mat->rank - PetscSqr(mat->rank))));
5193ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5204396437dSToby Isaac }
5214396437dSToby Isaac 
522d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatSolve_SeqDense_SetUp(Mat A, Vec xx, Vec yy, PetscScalar **_y, PetscBLASInt *_m, PetscBLASInt *_k)
523d71ae5a4SJacob Faibussowitsch {
5244396437dSToby Isaac   Mat_SeqDense *mat = (Mat_SeqDense *)A->data;
5254905a7bcSToby Isaac   PetscScalar  *y;
5264905a7bcSToby Isaac   PetscBLASInt  m = 0, k = 0;
5274905a7bcSToby Isaac 
5284905a7bcSToby Isaac   PetscFunctionBegin;
5299566063dSJacob Faibussowitsch   PetscCall(PetscBLASIntCast(A->rmap->n, &m));
5309566063dSJacob Faibussowitsch   PetscCall(PetscBLASIntCast(A->cmap->n, &k));
5314905a7bcSToby Isaac   if (k < m) {
5329566063dSJacob Faibussowitsch     PetscCall(VecCopy(xx, mat->qrrhs));
5339566063dSJacob Faibussowitsch     PetscCall(VecGetArray(mat->qrrhs, &y));
5344905a7bcSToby Isaac   } else {
5359566063dSJacob Faibussowitsch     PetscCall(VecCopy(xx, yy));
5369566063dSJacob Faibussowitsch     PetscCall(VecGetArray(yy, &y));
5374905a7bcSToby Isaac   }
5384396437dSToby Isaac   *_y = y;
5394396437dSToby Isaac   *_k = k;
5404396437dSToby Isaac   *_m = m;
5413ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5424396437dSToby Isaac }
5434396437dSToby Isaac 
544d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatSolve_SeqDense_TearDown(Mat A, Vec xx, Vec yy, PetscScalar **_y, PetscBLASInt *_m, PetscBLASInt *_k)
545d71ae5a4SJacob Faibussowitsch {
5464396437dSToby Isaac   Mat_SeqDense *mat = (Mat_SeqDense *)A->data;
54742e9364cSSatish Balay   PetscScalar  *y   = NULL;
5484396437dSToby Isaac   PetscBLASInt  m, k;
5494396437dSToby Isaac 
5504396437dSToby Isaac   PetscFunctionBegin;
5514396437dSToby Isaac   y   = *_y;
5524396437dSToby Isaac   *_y = NULL;
5534396437dSToby Isaac   k   = *_k;
5544396437dSToby Isaac   m   = *_m;
5554905a7bcSToby Isaac   if (k < m) {
5564905a7bcSToby Isaac     PetscScalar *yv;
5579566063dSJacob Faibussowitsch     PetscCall(VecGetArray(yy, &yv));
5589566063dSJacob Faibussowitsch     PetscCall(PetscArraycpy(yv, y, k));
5599566063dSJacob Faibussowitsch     PetscCall(VecRestoreArray(yy, &yv));
5609566063dSJacob Faibussowitsch     PetscCall(VecRestoreArray(mat->qrrhs, &y));
5614905a7bcSToby Isaac   } else {
5629566063dSJacob Faibussowitsch     PetscCall(VecRestoreArray(yy, &y));
5634905a7bcSToby Isaac   }
5643ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5654905a7bcSToby Isaac }
5664905a7bcSToby Isaac 
567d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatSolve_SeqDense_LU(Mat A, Vec xx, Vec yy)
568d71ae5a4SJacob Faibussowitsch {
56942e9364cSSatish Balay   PetscScalar *y = NULL;
57042e9364cSSatish Balay   PetscBLASInt m = 0, k = 0;
5714396437dSToby Isaac 
5724396437dSToby Isaac   PetscFunctionBegin;
5739566063dSJacob Faibussowitsch   PetscCall(MatSolve_SeqDense_SetUp(A, xx, yy, &y, &m, &k));
5749566063dSJacob Faibussowitsch   PetscCall(MatSolve_SeqDense_Internal_LU(A, y, m, m, 1, k, PETSC_FALSE));
5759566063dSJacob Faibussowitsch   PetscCall(MatSolve_SeqDense_TearDown(A, xx, yy, &y, &m, &k));
5763ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5774396437dSToby Isaac }
5784396437dSToby Isaac 
579d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatSolveTranspose_SeqDense_LU(Mat A, Vec xx, Vec yy)
580d71ae5a4SJacob Faibussowitsch {
58142e9364cSSatish Balay   PetscScalar *y = NULL;
58242e9364cSSatish Balay   PetscBLASInt m = 0, k = 0;
5834396437dSToby Isaac 
5844396437dSToby Isaac   PetscFunctionBegin;
5859566063dSJacob Faibussowitsch   PetscCall(MatSolve_SeqDense_SetUp(A, xx, yy, &y, &m, &k));
5869566063dSJacob Faibussowitsch   PetscCall(MatSolve_SeqDense_Internal_LU(A, y, m, m, 1, k, PETSC_TRUE));
5879566063dSJacob Faibussowitsch   PetscCall(MatSolve_SeqDense_TearDown(A, xx, yy, &y, &m, &k));
5883ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5894396437dSToby Isaac }
5904396437dSToby Isaac 
591d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatSolve_SeqDense_Cholesky(Mat A, Vec xx, Vec yy)
592d71ae5a4SJacob Faibussowitsch {
593e54beecaSStefano Zampini   PetscScalar *y = NULL;
594e54beecaSStefano Zampini   PetscBLASInt m = 0, k = 0;
5954396437dSToby Isaac 
5964396437dSToby Isaac   PetscFunctionBegin;
5979566063dSJacob Faibussowitsch   PetscCall(MatSolve_SeqDense_SetUp(A, xx, yy, &y, &m, &k));
5989566063dSJacob Faibussowitsch   PetscCall(MatSolve_SeqDense_Internal_Cholesky(A, y, m, m, 1, k, PETSC_FALSE));
5999566063dSJacob Faibussowitsch   PetscCall(MatSolve_SeqDense_TearDown(A, xx, yy, &y, &m, &k));
6003ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
6014396437dSToby Isaac }
6024396437dSToby Isaac 
603d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatSolveTranspose_SeqDense_Cholesky(Mat A, Vec xx, Vec yy)
604d71ae5a4SJacob Faibussowitsch {
605e54beecaSStefano Zampini   PetscScalar *y = NULL;
606e54beecaSStefano Zampini   PetscBLASInt m = 0, k = 0;
6074396437dSToby Isaac 
6084396437dSToby Isaac   PetscFunctionBegin;
6099566063dSJacob Faibussowitsch   PetscCall(MatSolve_SeqDense_SetUp(A, xx, yy, &y, &m, &k));
6109566063dSJacob Faibussowitsch   PetscCall(MatSolve_SeqDense_Internal_Cholesky(A, y, m, m, 1, k, PETSC_TRUE));
6119566063dSJacob Faibussowitsch   PetscCall(MatSolve_SeqDense_TearDown(A, xx, yy, &y, &m, &k));
6123ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
6134396437dSToby Isaac }
6144396437dSToby Isaac 
615d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatSolve_SeqDense_QR(Mat A, Vec xx, Vec yy)
616d71ae5a4SJacob Faibussowitsch {
617e54beecaSStefano Zampini   PetscScalar *y = NULL;
618e54beecaSStefano Zampini   PetscBLASInt m = 0, k = 0;
6194396437dSToby Isaac 
6204396437dSToby Isaac   PetscFunctionBegin;
6219566063dSJacob Faibussowitsch   PetscCall(MatSolve_SeqDense_SetUp(A, xx, yy, &y, &m, &k));
6229566063dSJacob Faibussowitsch   PetscCall(MatSolve_SeqDense_Internal_QR(A, y, PetscMax(m, k), m, 1, k));
6239566063dSJacob Faibussowitsch   PetscCall(MatSolve_SeqDense_TearDown(A, xx, yy, &y, &m, &k));
6243ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
6254396437dSToby Isaac }
6264396437dSToby Isaac 
627d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatSolveTranspose_SeqDense_QR(Mat A, Vec xx, Vec yy)
628d71ae5a4SJacob Faibussowitsch {
62942e9364cSSatish Balay   PetscScalar *y = NULL;
63042e9364cSSatish Balay   PetscBLASInt m = 0, k = 0;
6314396437dSToby Isaac 
6324396437dSToby Isaac   PetscFunctionBegin;
6339566063dSJacob Faibussowitsch   PetscCall(MatSolve_SeqDense_SetUp(A, xx, yy, &y, &m, &k));
6349566063dSJacob Faibussowitsch   PetscCall(MatSolveTranspose_SeqDense_Internal_QR(A, y, PetscMax(m, k), m, 1, k));
6359566063dSJacob Faibussowitsch   PetscCall(MatSolve_SeqDense_TearDown(A, xx, yy, &y, &m, &k));
6363ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
6374396437dSToby Isaac }
6384396437dSToby Isaac 
639d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatMatSolve_SeqDense_SetUp(Mat A, Mat B, Mat X, PetscScalar **_y, PetscBLASInt *_ldy, PetscBLASInt *_m, PetscBLASInt *_nrhs, PetscBLASInt *_k)
640d71ae5a4SJacob Faibussowitsch {
6414905a7bcSToby Isaac   const PetscScalar *b;
6424396437dSToby Isaac   PetscScalar       *y;
643bf5a80bcSToby Isaac   PetscInt           n, _ldb, _ldx;
644bf5a80bcSToby Isaac   PetscBLASInt       nrhs = 0, m = 0, k = 0, ldb = 0, ldx = 0, ldy = 0;
6454905a7bcSToby Isaac 
6464905a7bcSToby Isaac   PetscFunctionBegin;
6479371c9d4SSatish Balay   *_ldy  = 0;
6489371c9d4SSatish Balay   *_m    = 0;
6499371c9d4SSatish Balay   *_nrhs = 0;
6509371c9d4SSatish Balay   *_k    = 0;
6519371c9d4SSatish Balay   *_y    = NULL;
6529566063dSJacob Faibussowitsch   PetscCall(PetscBLASIntCast(A->rmap->n, &m));
6539566063dSJacob Faibussowitsch   PetscCall(PetscBLASIntCast(A->cmap->n, &k));
6549566063dSJacob Faibussowitsch   PetscCall(MatGetSize(B, NULL, &n));
6559566063dSJacob Faibussowitsch   PetscCall(PetscBLASIntCast(n, &nrhs));
6569566063dSJacob Faibussowitsch   PetscCall(MatDenseGetLDA(B, &_ldb));
6579566063dSJacob Faibussowitsch   PetscCall(PetscBLASIntCast(_ldb, &ldb));
6589566063dSJacob Faibussowitsch   PetscCall(MatDenseGetLDA(X, &_ldx));
6599566063dSJacob Faibussowitsch   PetscCall(PetscBLASIntCast(_ldx, &ldx));
660bf5a80bcSToby Isaac   if (ldx < m) {
6619566063dSJacob Faibussowitsch     PetscCall(MatDenseGetArrayRead(B, &b));
6629566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(nrhs * m, &y));
663bf5a80bcSToby Isaac     if (ldb == m) {
6649566063dSJacob Faibussowitsch       PetscCall(PetscArraycpy(y, b, ldb * nrhs));
6654905a7bcSToby Isaac     } else {
66648a46eb9SPierre Jolivet       for (PetscInt j = 0; j < nrhs; j++) PetscCall(PetscArraycpy(&y[j * m], &b[j * ldb], m));
6674905a7bcSToby Isaac     }
668bf5a80bcSToby Isaac     ldy = m;
6699566063dSJacob Faibussowitsch     PetscCall(MatDenseRestoreArrayRead(B, &b));
6704905a7bcSToby Isaac   } else {
671bf5a80bcSToby Isaac     if (ldb == ldx) {
6729566063dSJacob Faibussowitsch       PetscCall(MatCopy(B, X, SAME_NONZERO_PATTERN));
6739566063dSJacob Faibussowitsch       PetscCall(MatDenseGetArray(X, &y));
6744905a7bcSToby Isaac     } else {
6759566063dSJacob Faibussowitsch       PetscCall(MatDenseGetArray(X, &y));
6769566063dSJacob Faibussowitsch       PetscCall(MatDenseGetArrayRead(B, &b));
67748a46eb9SPierre Jolivet       for (PetscInt j = 0; j < nrhs; j++) PetscCall(PetscArraycpy(&y[j * ldx], &b[j * ldb], m));
6789566063dSJacob Faibussowitsch       PetscCall(MatDenseRestoreArrayRead(B, &b));
6794905a7bcSToby Isaac     }
680bf5a80bcSToby Isaac     ldy = ldx;
6814905a7bcSToby Isaac   }
6824396437dSToby Isaac   *_y    = y;
683bf5a80bcSToby Isaac   *_ldy  = ldy;
6844396437dSToby Isaac   *_k    = k;
6854396437dSToby Isaac   *_m    = m;
6864396437dSToby Isaac   *_nrhs = nrhs;
6873ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
6884396437dSToby Isaac }
6894396437dSToby Isaac 
690d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatMatSolve_SeqDense_TearDown(Mat A, Mat B, Mat X, PetscScalar **_y, PetscBLASInt *_ldy, PetscBLASInt *_m, PetscBLASInt *_nrhs, PetscBLASInt *_k)
691d71ae5a4SJacob Faibussowitsch {
6924396437dSToby Isaac   PetscScalar *y;
693bf5a80bcSToby Isaac   PetscInt     _ldx;
694bf5a80bcSToby Isaac   PetscBLASInt k, ldy, nrhs, ldx = 0;
6954396437dSToby Isaac 
6964396437dSToby Isaac   PetscFunctionBegin;
6974396437dSToby Isaac   y    = *_y;
6984396437dSToby Isaac   *_y  = NULL;
6994396437dSToby Isaac   k    = *_k;
700bf5a80bcSToby Isaac   ldy  = *_ldy;
7014396437dSToby Isaac   nrhs = *_nrhs;
7029566063dSJacob Faibussowitsch   PetscCall(MatDenseGetLDA(X, &_ldx));
7039566063dSJacob Faibussowitsch   PetscCall(PetscBLASIntCast(_ldx, &ldx));
704bf5a80bcSToby Isaac   if (ldx != ldy) {
7054905a7bcSToby Isaac     PetscScalar *xv;
7069566063dSJacob Faibussowitsch     PetscCall(MatDenseGetArray(X, &xv));
70748a46eb9SPierre Jolivet     for (PetscInt j = 0; j < nrhs; j++) PetscCall(PetscArraycpy(&xv[j * ldx], &y[j * ldy], k));
7089566063dSJacob Faibussowitsch     PetscCall(MatDenseRestoreArray(X, &xv));
7099566063dSJacob Faibussowitsch     PetscCall(PetscFree(y));
7104905a7bcSToby Isaac   } else {
7119566063dSJacob Faibussowitsch     PetscCall(MatDenseRestoreArray(X, &y));
7124905a7bcSToby Isaac   }
7133ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
71485e2c93fSHong Zhang }
71585e2c93fSHong Zhang 
716d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatMatSolve_SeqDense_LU(Mat A, Mat B, Mat X)
717d71ae5a4SJacob Faibussowitsch {
7184396437dSToby Isaac   PetscScalar *y;
719bf5a80bcSToby Isaac   PetscBLASInt m, k, ldy, nrhs;
7204396437dSToby Isaac 
7214396437dSToby Isaac   PetscFunctionBegin;
7229566063dSJacob Faibussowitsch   PetscCall(MatMatSolve_SeqDense_SetUp(A, B, X, &y, &ldy, &m, &nrhs, &k));
7239566063dSJacob Faibussowitsch   PetscCall(MatSolve_SeqDense_Internal_LU(A, y, ldy, m, nrhs, k, PETSC_FALSE));
7249566063dSJacob Faibussowitsch   PetscCall(MatMatSolve_SeqDense_TearDown(A, B, X, &y, &ldy, &m, &nrhs, &k));
7253ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
7264396437dSToby Isaac }
7274396437dSToby Isaac 
728d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatMatSolveTranspose_SeqDense_LU(Mat A, Mat B, Mat X)
729d71ae5a4SJacob Faibussowitsch {
7304396437dSToby Isaac   PetscScalar *y;
731bf5a80bcSToby Isaac   PetscBLASInt m, k, ldy, nrhs;
7324396437dSToby Isaac 
7334396437dSToby Isaac   PetscFunctionBegin;
7349566063dSJacob Faibussowitsch   PetscCall(MatMatSolve_SeqDense_SetUp(A, B, X, &y, &ldy, &m, &nrhs, &k));
7359566063dSJacob Faibussowitsch   PetscCall(MatSolve_SeqDense_Internal_LU(A, y, ldy, m, nrhs, k, PETSC_TRUE));
7369566063dSJacob Faibussowitsch   PetscCall(MatMatSolve_SeqDense_TearDown(A, B, X, &y, &ldy, &m, &nrhs, &k));
7373ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
7384396437dSToby Isaac }
7394396437dSToby Isaac 
740d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatMatSolve_SeqDense_Cholesky(Mat A, Mat B, Mat X)
741d71ae5a4SJacob Faibussowitsch {
7424396437dSToby Isaac   PetscScalar *y;
743bf5a80bcSToby Isaac   PetscBLASInt m, k, ldy, nrhs;
7444396437dSToby Isaac 
7454396437dSToby Isaac   PetscFunctionBegin;
7469566063dSJacob Faibussowitsch   PetscCall(MatMatSolve_SeqDense_SetUp(A, B, X, &y, &ldy, &m, &nrhs, &k));
7479566063dSJacob Faibussowitsch   PetscCall(MatSolve_SeqDense_Internal_Cholesky(A, y, ldy, m, nrhs, k, PETSC_FALSE));
7489566063dSJacob Faibussowitsch   PetscCall(MatMatSolve_SeqDense_TearDown(A, B, X, &y, &ldy, &m, &nrhs, &k));
7493ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
7504396437dSToby Isaac }
7514396437dSToby Isaac 
752d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatMatSolveTranspose_SeqDense_Cholesky(Mat A, Mat B, Mat X)
753d71ae5a4SJacob Faibussowitsch {
7544396437dSToby Isaac   PetscScalar *y;
755bf5a80bcSToby Isaac   PetscBLASInt m, k, ldy, nrhs;
7564396437dSToby Isaac 
7574396437dSToby Isaac   PetscFunctionBegin;
7589566063dSJacob Faibussowitsch   PetscCall(MatMatSolve_SeqDense_SetUp(A, B, X, &y, &ldy, &m, &nrhs, &k));
7599566063dSJacob Faibussowitsch   PetscCall(MatSolve_SeqDense_Internal_Cholesky(A, y, ldy, m, nrhs, k, PETSC_TRUE));
7609566063dSJacob Faibussowitsch   PetscCall(MatMatSolve_SeqDense_TearDown(A, B, X, &y, &ldy, &m, &nrhs, &k));
7613ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
7624396437dSToby Isaac }
7634396437dSToby Isaac 
764d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatMatSolve_SeqDense_QR(Mat A, Mat B, Mat X)
765d71ae5a4SJacob Faibussowitsch {
7664396437dSToby Isaac   PetscScalar *y;
767bf5a80bcSToby Isaac   PetscBLASInt m, k, ldy, nrhs;
7684396437dSToby Isaac 
7694396437dSToby Isaac   PetscFunctionBegin;
7709566063dSJacob Faibussowitsch   PetscCall(MatMatSolve_SeqDense_SetUp(A, B, X, &y, &ldy, &m, &nrhs, &k));
7719566063dSJacob Faibussowitsch   PetscCall(MatSolve_SeqDense_Internal_QR(A, y, ldy, m, nrhs, k));
7729566063dSJacob Faibussowitsch   PetscCall(MatMatSolve_SeqDense_TearDown(A, B, X, &y, &ldy, &m, &nrhs, &k));
7733ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
7744396437dSToby Isaac }
7754396437dSToby Isaac 
776d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatMatSolveTranspose_SeqDense_QR(Mat A, Mat B, Mat X)
777d71ae5a4SJacob Faibussowitsch {
7784396437dSToby Isaac   PetscScalar *y;
779bf5a80bcSToby Isaac   PetscBLASInt m, k, ldy, nrhs;
7804396437dSToby Isaac 
7814396437dSToby Isaac   PetscFunctionBegin;
7829566063dSJacob Faibussowitsch   PetscCall(MatMatSolve_SeqDense_SetUp(A, B, X, &y, &ldy, &m, &nrhs, &k));
7839566063dSJacob Faibussowitsch   PetscCall(MatSolveTranspose_SeqDense_Internal_QR(A, y, ldy, m, nrhs, k));
7849566063dSJacob Faibussowitsch   PetscCall(MatMatSolve_SeqDense_TearDown(A, B, X, &y, &ldy, &m, &nrhs, &k));
7853ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
7864396437dSToby Isaac }
7874396437dSToby Isaac 
788db4efbfdSBarry Smith /* COMMENT: I have chosen to hide row permutation in the pivots,
789db4efbfdSBarry Smith    rather than put it in the Mat->row slot.*/
790d71ae5a4SJacob Faibussowitsch PetscErrorCode MatLUFactor_SeqDense(Mat A, IS row, IS col, const MatFactorInfo *minfo)
791d71ae5a4SJacob Faibussowitsch {
792db4efbfdSBarry Smith   Mat_SeqDense *mat = (Mat_SeqDense *)A->data;
793db4efbfdSBarry Smith   PetscBLASInt  n, m, info;
794db4efbfdSBarry Smith 
795db4efbfdSBarry Smith   PetscFunctionBegin;
7969566063dSJacob Faibussowitsch   PetscCall(PetscBLASIntCast(A->cmap->n, &n));
7979566063dSJacob Faibussowitsch   PetscCall(PetscBLASIntCast(A->rmap->n, &m));
7984dfa11a4SJacob Faibussowitsch   if (!mat->pivots) { PetscCall(PetscMalloc1(A->rmap->n, &mat->pivots)); }
7993ba16761SJacob Faibussowitsch   if (!A->rmap->n || !A->cmap->n) PetscFunctionReturn(PETSC_SUCCESS);
8009566063dSJacob Faibussowitsch   PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF));
801792fecdfSBarry Smith   PetscCallBLAS("LAPACKgetrf", LAPACKgetrf_(&m, &n, mat->v, &mat->lda, mat->pivots, &info));
8029566063dSJacob Faibussowitsch   PetscCall(PetscFPTrapPop());
8038e57ea43SSatish Balay 
80405fcb23eSStefano Zampini   PetscCheck(info >= 0, PETSC_COMM_SELF, PETSC_ERR_LIB, "Bad argument to LU factorization %d", (int)info);
80505fcb23eSStefano Zampini   PetscCheck(info <= 0, PETSC_COMM_SELF, PETSC_ERR_MAT_LU_ZRPVT, "Bad LU factorization %d", (int)info);
8068208b9aeSStefano Zampini 
8074396437dSToby Isaac   A->ops->solve             = MatSolve_SeqDense_LU;
8084396437dSToby Isaac   A->ops->matsolve          = MatMatSolve_SeqDense_LU;
8094396437dSToby Isaac   A->ops->solvetranspose    = MatSolveTranspose_SeqDense_LU;
8104396437dSToby Isaac   A->ops->matsolvetranspose = MatMatSolveTranspose_SeqDense_LU;
811d5f3da31SBarry Smith   A->factortype             = MAT_FACTOR_LU;
812db4efbfdSBarry Smith 
8139566063dSJacob Faibussowitsch   PetscCall(PetscFree(A->solvertype));
8149566063dSJacob Faibussowitsch   PetscCall(PetscStrallocpy(MATSOLVERPETSC, &A->solvertype));
815f6224b95SHong Zhang 
8169566063dSJacob Faibussowitsch   PetscCall(PetscLogFlops((2.0 * A->cmap->n * A->cmap->n * A->cmap->n) / 3));
8173ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
818db4efbfdSBarry Smith }
819db4efbfdSBarry Smith 
820d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatLUFactorNumeric_SeqDense(Mat fact, Mat A, const MatFactorInfo *info_dummy)
821d71ae5a4SJacob Faibussowitsch {
8224396437dSToby Isaac   MatFactorInfo info;
8234396437dSToby Isaac 
8244396437dSToby Isaac   PetscFunctionBegin;
8259566063dSJacob Faibussowitsch   PetscCall(MatDuplicateNoCreate_SeqDense(fact, A, MAT_COPY_VALUES));
826dbbe0bcdSBarry Smith   PetscUseTypeMethod(fact, lufactor, NULL, NULL, &info);
8273ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
8284396437dSToby Isaac }
8294396437dSToby Isaac 
830d71ae5a4SJacob Faibussowitsch PetscErrorCode MatLUFactorSymbolic_SeqDense(Mat fact, Mat A, IS row, IS col, const MatFactorInfo *info)
831d71ae5a4SJacob Faibussowitsch {
8324396437dSToby Isaac   PetscFunctionBegin;
8334396437dSToby Isaac   fact->preallocated         = PETSC_TRUE;
8344396437dSToby Isaac   fact->assembled            = PETSC_TRUE;
8354396437dSToby Isaac   fact->ops->lufactornumeric = MatLUFactorNumeric_SeqDense;
8363ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
8374396437dSToby Isaac }
8384396437dSToby Isaac 
839a49dc2a2SStefano Zampini /* Cholesky as L*L^T or L*D*L^T and the symmetric/hermitian complex variants */
840d71ae5a4SJacob Faibussowitsch PetscErrorCode MatCholeskyFactor_SeqDense(Mat A, IS perm, const MatFactorInfo *factinfo)
841d71ae5a4SJacob Faibussowitsch {
842db4efbfdSBarry Smith   Mat_SeqDense *mat = (Mat_SeqDense *)A->data;
843c5df96a5SBarry Smith   PetscBLASInt  info, n;
844db4efbfdSBarry Smith 
845db4efbfdSBarry Smith   PetscFunctionBegin;
8469566063dSJacob Faibussowitsch   PetscCall(PetscBLASIntCast(A->cmap->n, &n));
8473ba16761SJacob Faibussowitsch   if (!A->rmap->n || !A->cmap->n) PetscFunctionReturn(PETSC_SUCCESS);
848b94d7dedSBarry Smith   if (A->spd == PETSC_BOOL3_TRUE) {
8499566063dSJacob Faibussowitsch     PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF));
850792fecdfSBarry Smith     PetscCallBLAS("LAPACKpotrf", LAPACKpotrf_("L", &n, mat->v, &mat->lda, &info));
8519566063dSJacob Faibussowitsch     PetscCall(PetscFPTrapPop());
852a49dc2a2SStefano Zampini #if defined(PETSC_USE_COMPLEX)
853b94d7dedSBarry Smith   } else if (A->hermitian == PETSC_BOOL3_TRUE) {
8544dfa11a4SJacob Faibussowitsch     if (!mat->pivots) { PetscCall(PetscMalloc1(A->rmap->n, &mat->pivots)); }
855a49dc2a2SStefano Zampini     if (!mat->fwork) {
856a49dc2a2SStefano Zampini       PetscScalar dummy;
857a49dc2a2SStefano Zampini 
858a49dc2a2SStefano Zampini       mat->lfwork = -1;
8599566063dSJacob Faibussowitsch       PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF));
860792fecdfSBarry Smith       PetscCallBLAS("LAPACKhetrf", LAPACKhetrf_("L", &n, mat->v, &mat->lda, mat->pivots, &dummy, &mat->lfwork, &info));
8619566063dSJacob Faibussowitsch       PetscCall(PetscFPTrapPop());
862a49dc2a2SStefano Zampini       mat->lfwork = (PetscInt)PetscRealPart(dummy);
8639566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(mat->lfwork, &mat->fwork));
864a49dc2a2SStefano Zampini     }
8659566063dSJacob Faibussowitsch     PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF));
866792fecdfSBarry Smith     PetscCallBLAS("LAPACKhetrf", LAPACKhetrf_("L", &n, mat->v, &mat->lda, mat->pivots, mat->fwork, &mat->lfwork, &info));
8679566063dSJacob Faibussowitsch     PetscCall(PetscFPTrapPop());
868a49dc2a2SStefano Zampini #endif
869a49dc2a2SStefano Zampini   } else { /* symmetric case */
8704dfa11a4SJacob Faibussowitsch     if (!mat->pivots) { PetscCall(PetscMalloc1(A->rmap->n, &mat->pivots)); }
871a49dc2a2SStefano Zampini     if (!mat->fwork) {
872a49dc2a2SStefano Zampini       PetscScalar dummy;
873a49dc2a2SStefano Zampini 
874a49dc2a2SStefano Zampini       mat->lfwork = -1;
8759566063dSJacob Faibussowitsch       PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF));
876792fecdfSBarry Smith       PetscCallBLAS("LAPACKsytrf", LAPACKsytrf_("L", &n, mat->v, &mat->lda, mat->pivots, &dummy, &mat->lfwork, &info));
8779566063dSJacob Faibussowitsch       PetscCall(PetscFPTrapPop());
878a49dc2a2SStefano Zampini       mat->lfwork = (PetscInt)PetscRealPart(dummy);
8799566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(mat->lfwork, &mat->fwork));
880a49dc2a2SStefano Zampini     }
8819566063dSJacob Faibussowitsch     PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF));
882792fecdfSBarry Smith     PetscCallBLAS("LAPACKsytrf", LAPACKsytrf_("L", &n, mat->v, &mat->lda, mat->pivots, mat->fwork, &mat->lfwork, &info));
8839566063dSJacob Faibussowitsch     PetscCall(PetscFPTrapPop());
884a49dc2a2SStefano Zampini   }
88528b400f6SJacob Faibussowitsch   PetscCheck(!info, PETSC_COMM_SELF, PETSC_ERR_MAT_CH_ZRPVT, "Bad factorization: zero pivot in row %" PetscInt_FMT, (PetscInt)info - 1);
8868208b9aeSStefano Zampini 
8874396437dSToby Isaac   A->ops->solve             = MatSolve_SeqDense_Cholesky;
8884396437dSToby Isaac   A->ops->matsolve          = MatMatSolve_SeqDense_Cholesky;
8894396437dSToby Isaac   A->ops->solvetranspose    = MatSolveTranspose_SeqDense_Cholesky;
8904396437dSToby Isaac   A->ops->matsolvetranspose = MatMatSolveTranspose_SeqDense_Cholesky;
891d5f3da31SBarry Smith   A->factortype             = MAT_FACTOR_CHOLESKY;
8922205254eSKarl Rupp 
8939566063dSJacob Faibussowitsch   PetscCall(PetscFree(A->solvertype));
8949566063dSJacob Faibussowitsch   PetscCall(PetscStrallocpy(MATSOLVERPETSC, &A->solvertype));
895f6224b95SHong Zhang 
8969566063dSJacob Faibussowitsch   PetscCall(PetscLogFlops((1.0 * A->cmap->n * A->cmap->n * A->cmap->n) / 3.0));
8973ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
898db4efbfdSBarry Smith }
899db4efbfdSBarry Smith 
900d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatCholeskyFactorNumeric_SeqDense(Mat fact, Mat A, const MatFactorInfo *info_dummy)
901d71ae5a4SJacob Faibussowitsch {
902db4efbfdSBarry Smith   MatFactorInfo info;
903db4efbfdSBarry Smith 
904db4efbfdSBarry Smith   PetscFunctionBegin;
905db4efbfdSBarry Smith   info.fill = 1.0;
9062205254eSKarl Rupp 
9079566063dSJacob Faibussowitsch   PetscCall(MatDuplicateNoCreate_SeqDense(fact, A, MAT_COPY_VALUES));
908dbbe0bcdSBarry Smith   PetscUseTypeMethod(fact, choleskyfactor, NULL, &info);
9093ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
910db4efbfdSBarry Smith }
911db4efbfdSBarry Smith 
912d71ae5a4SJacob Faibussowitsch PetscErrorCode MatCholeskyFactorSymbolic_SeqDense(Mat fact, Mat A, IS row, const MatFactorInfo *info)
913d71ae5a4SJacob Faibussowitsch {
914db4efbfdSBarry Smith   PetscFunctionBegin;
915c3ef05f6SHong Zhang   fact->assembled                  = PETSC_TRUE;
9161bbcc794SSatish Balay   fact->preallocated               = PETSC_TRUE;
917719d5645SBarry Smith   fact->ops->choleskyfactornumeric = MatCholeskyFactorNumeric_SeqDense;
9183ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
919db4efbfdSBarry Smith }
920db4efbfdSBarry Smith 
921d71ae5a4SJacob Faibussowitsch PetscErrorCode MatQRFactor_SeqDense(Mat A, IS col, const MatFactorInfo *minfo)
922d71ae5a4SJacob Faibussowitsch {
9234905a7bcSToby Isaac   Mat_SeqDense *mat = (Mat_SeqDense *)A->data;
9244905a7bcSToby Isaac   PetscBLASInt  n, m, info, min, max;
9254905a7bcSToby Isaac 
9264905a7bcSToby Isaac   PetscFunctionBegin;
9279566063dSJacob Faibussowitsch   PetscCall(PetscBLASIntCast(A->cmap->n, &n));
9289566063dSJacob Faibussowitsch   PetscCall(PetscBLASIntCast(A->rmap->n, &m));
9294396437dSToby Isaac   max = PetscMax(m, n);
9304396437dSToby Isaac   min = PetscMin(m, n);
9314dfa11a4SJacob Faibussowitsch   if (!mat->tau) { PetscCall(PetscMalloc1(min, &mat->tau)); }
9324dfa11a4SJacob Faibussowitsch   if (!mat->pivots) { PetscCall(PetscMalloc1(n, &mat->pivots)); }
933f4f49eeaSPierre Jolivet   if (!mat->qrrhs) PetscCall(MatCreateVecs(A, NULL, &mat->qrrhs));
9343ba16761SJacob Faibussowitsch   if (!A->rmap->n || !A->cmap->n) PetscFunctionReturn(PETSC_SUCCESS);
9354905a7bcSToby Isaac   if (!mat->fwork) {
9364905a7bcSToby Isaac     PetscScalar dummy;
9374905a7bcSToby Isaac 
9384905a7bcSToby Isaac     mat->lfwork = -1;
9399566063dSJacob Faibussowitsch     PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF));
940792fecdfSBarry Smith     PetscCallBLAS("LAPACKgeqrf", LAPACKgeqrf_(&m, &n, mat->v, &mat->lda, mat->tau, &dummy, &mat->lfwork, &info));
9419566063dSJacob Faibussowitsch     PetscCall(PetscFPTrapPop());
9424905a7bcSToby Isaac     mat->lfwork = (PetscInt)PetscRealPart(dummy);
9439566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(mat->lfwork, &mat->fwork));
9444905a7bcSToby Isaac   }
9459566063dSJacob Faibussowitsch   PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF));
946792fecdfSBarry Smith   PetscCallBLAS("LAPACKgeqrf", LAPACKgeqrf_(&m, &n, mat->v, &mat->lda, mat->tau, mat->fwork, &mat->lfwork, &info));
9479566063dSJacob Faibussowitsch   PetscCall(PetscFPTrapPop());
94805fcb23eSStefano Zampini   PetscCheck(!info, PETSC_COMM_SELF, PETSC_ERR_LIB, "Bad argument to QR factorization %d", (int)info);
9494905a7bcSToby Isaac   // TODO: try to estimate rank or test for and use geqp3 for rank revealing QR.  For now just say rank is min of m and n
9504905a7bcSToby Isaac   mat->rank = min;
9514905a7bcSToby Isaac 
9524396437dSToby Isaac   A->ops->solve    = MatSolve_SeqDense_QR;
9534396437dSToby Isaac   A->ops->matsolve = MatMatSolve_SeqDense_QR;
9544905a7bcSToby Isaac   A->factortype    = MAT_FACTOR_QR;
9554905a7bcSToby Isaac   if (m == n) {
9564396437dSToby Isaac     A->ops->solvetranspose    = MatSolveTranspose_SeqDense_QR;
9574396437dSToby Isaac     A->ops->matsolvetranspose = MatMatSolveTranspose_SeqDense_QR;
9584905a7bcSToby Isaac   }
9594905a7bcSToby Isaac 
9609566063dSJacob Faibussowitsch   PetscCall(PetscFree(A->solvertype));
9619566063dSJacob Faibussowitsch   PetscCall(PetscStrallocpy(MATSOLVERPETSC, &A->solvertype));
9624905a7bcSToby Isaac 
9639566063dSJacob Faibussowitsch   PetscCall(PetscLogFlops(2.0 * min * min * (max - min / 3.0)));
9643ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
9654905a7bcSToby Isaac }
9664905a7bcSToby Isaac 
967d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatQRFactorNumeric_SeqDense(Mat fact, Mat A, const MatFactorInfo *info_dummy)
968d71ae5a4SJacob Faibussowitsch {
9694905a7bcSToby Isaac   MatFactorInfo info;
9704905a7bcSToby Isaac 
9714905a7bcSToby Isaac   PetscFunctionBegin;
9724905a7bcSToby Isaac   info.fill = 1.0;
9734905a7bcSToby Isaac 
9749566063dSJacob Faibussowitsch   PetscCall(MatDuplicateNoCreate_SeqDense(fact, A, MAT_COPY_VALUES));
975cac4c232SBarry Smith   PetscUseMethod(fact, "MatQRFactor_C", (Mat, IS, const MatFactorInfo *), (fact, NULL, &info));
9763ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
9774905a7bcSToby Isaac }
9784905a7bcSToby Isaac 
979d71ae5a4SJacob Faibussowitsch PetscErrorCode MatQRFactorSymbolic_SeqDense(Mat fact, Mat A, IS row, const MatFactorInfo *info)
980d71ae5a4SJacob Faibussowitsch {
9814905a7bcSToby Isaac   PetscFunctionBegin;
9824905a7bcSToby Isaac   fact->assembled    = PETSC_TRUE;
9834905a7bcSToby Isaac   fact->preallocated = PETSC_TRUE;
9849566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)fact, "MatQRFactorNumeric_C", MatQRFactorNumeric_SeqDense));
9853ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
9864905a7bcSToby Isaac }
9874905a7bcSToby Isaac 
988ca15aa20SStefano Zampini /* uses LAPACK */
989d71ae5a4SJacob Faibussowitsch PETSC_INTERN PetscErrorCode MatGetFactor_seqdense_petsc(Mat A, MatFactorType ftype, Mat *fact)
990d71ae5a4SJacob Faibussowitsch {
991db4efbfdSBarry Smith   PetscFunctionBegin;
9929566063dSJacob Faibussowitsch   PetscCall(MatCreate(PetscObjectComm((PetscObject)A), fact));
9939566063dSJacob Faibussowitsch   PetscCall(MatSetSizes(*fact, A->rmap->n, A->cmap->n, A->rmap->n, A->cmap->n));
9949566063dSJacob Faibussowitsch   PetscCall(MatSetType(*fact, MATDENSE));
99566e17bc3SBarry Smith   (*fact)->trivialsymbolic = PETSC_TRUE;
9962a350339SBarry Smith   if (ftype == MAT_FACTOR_LU || ftype == MAT_FACTOR_ILU) {
997db4efbfdSBarry Smith     (*fact)->ops->lufactorsymbolic  = MatLUFactorSymbolic_SeqDense;
9982a350339SBarry Smith     (*fact)->ops->ilufactorsymbolic = MatLUFactorSymbolic_SeqDense;
999bf5a80bcSToby Isaac   } else if (ftype == MAT_FACTOR_CHOLESKY || ftype == MAT_FACTOR_ICC) {
1000db4efbfdSBarry Smith     (*fact)->ops->choleskyfactorsymbolic = MatCholeskyFactorSymbolic_SeqDense;
1001bf5a80bcSToby Isaac   } else if (ftype == MAT_FACTOR_QR) {
1002f4f49eeaSPierre Jolivet     PetscCall(PetscObjectComposeFunction((PetscObject)*fact, "MatQRFactorSymbolic_C", MatQRFactorSymbolic_SeqDense));
1003db4efbfdSBarry Smith   }
1004d5f3da31SBarry Smith   (*fact)->factortype = ftype;
100500c67f3bSHong Zhang 
10069566063dSJacob Faibussowitsch   PetscCall(PetscFree((*fact)->solvertype));
10079566063dSJacob Faibussowitsch   PetscCall(PetscStrallocpy(MATSOLVERPETSC, &(*fact)->solvertype));
10089566063dSJacob Faibussowitsch   PetscCall(PetscStrallocpy(MATORDERINGEXTERNAL, (char **)&(*fact)->preferredordering[MAT_FACTOR_LU]));
10099566063dSJacob Faibussowitsch   PetscCall(PetscStrallocpy(MATORDERINGEXTERNAL, (char **)&(*fact)->preferredordering[MAT_FACTOR_ILU]));
10109566063dSJacob Faibussowitsch   PetscCall(PetscStrallocpy(MATORDERINGEXTERNAL, (char **)&(*fact)->preferredordering[MAT_FACTOR_CHOLESKY]));
10119566063dSJacob Faibussowitsch   PetscCall(PetscStrallocpy(MATORDERINGEXTERNAL, (char **)&(*fact)->preferredordering[MAT_FACTOR_ICC]));
10123ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1013db4efbfdSBarry Smith }
1014db4efbfdSBarry Smith 
1015d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatSOR_SeqDense(Mat A, Vec bb, PetscReal omega, MatSORType flag, PetscReal shift, PetscInt its, PetscInt lits, Vec xx)
1016d71ae5a4SJacob Faibussowitsch {
1017c0bbcb79SLois Curfman McInnes   Mat_SeqDense      *mat = (Mat_SeqDense *)A->data;
1018d9ca1df4SBarry Smith   PetscScalar       *x, *v = mat->v, zero = 0.0, xt;
1019d9ca1df4SBarry Smith   const PetscScalar *b;
1020d0f46423SBarry Smith   PetscInt           m = A->rmap->n, i;
102123fff9afSBarry Smith   PetscBLASInt       o = 1, bm = 0;
1022289bc588SBarry Smith 
10233a40ed3dSBarry Smith   PetscFunctionBegin;
102447d993e7Ssuyashtn #if defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
102508401ef6SPierre Jolivet   PetscCheck(A->offloadmask != PETSC_OFFLOAD_GPU, PETSC_COMM_SELF, PETSC_ERR_SUP, "Not implemented");
1026ca15aa20SStefano Zampini #endif
1027422a814eSBarry Smith   if (shift == -1) shift = 0.0; /* negative shift indicates do not error on zero diagonal; this code never zeros on zero diagonal */
10289566063dSJacob Faibussowitsch   PetscCall(PetscBLASIntCast(m, &bm));
1029289bc588SBarry Smith   if (flag & SOR_ZERO_INITIAL_GUESS) {
10303bffc371SBarry Smith     /* this is a hack fix, should have another version without the second BLASdotu */
10319566063dSJacob Faibussowitsch     PetscCall(VecSet(xx, zero));
1032289bc588SBarry Smith   }
10339566063dSJacob Faibussowitsch   PetscCall(VecGetArray(xx, &x));
10349566063dSJacob Faibussowitsch   PetscCall(VecGetArrayRead(bb, &b));
1035b965ef7fSBarry Smith   its = its * lits;
103608401ef6SPierre Jolivet   PetscCheck(its > 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Relaxation requires global its %" PetscInt_FMT " and local its %" PetscInt_FMT " both positive", its, lits);
1037289bc588SBarry Smith   while (its--) {
1038fccaa45eSBarry Smith     if (flag & SOR_FORWARD_SWEEP || flag & SOR_LOCAL_FORWARD_SWEEP) {
1039289bc588SBarry Smith       for (i = 0; i < m; i++) {
1040792fecdfSBarry Smith         PetscCallBLAS("BLASdotu", xt = b[i] - BLASdotu_(&bm, v + i, &bm, x, &o));
104155a1b374SBarry Smith         x[i] = (1. - omega) * x[i] + omega * (xt + v[i + i * m] * x[i]) / (v[i + i * m] + shift);
1042289bc588SBarry Smith       }
1043289bc588SBarry Smith     }
1044fccaa45eSBarry Smith     if (flag & SOR_BACKWARD_SWEEP || flag & SOR_LOCAL_BACKWARD_SWEEP) {
1045289bc588SBarry Smith       for (i = m - 1; i >= 0; i--) {
1046792fecdfSBarry Smith         PetscCallBLAS("BLASdotu", xt = b[i] - BLASdotu_(&bm, v + i, &bm, x, &o));
104755a1b374SBarry Smith         x[i] = (1. - omega) * x[i] + omega * (xt + v[i + i * m] * x[i]) / (v[i + i * m] + shift);
1048289bc588SBarry Smith       }
1049289bc588SBarry Smith     }
1050289bc588SBarry Smith   }
10519566063dSJacob Faibussowitsch   PetscCall(VecRestoreArrayRead(bb, &b));
10529566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(xx, &x));
10533ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1054289bc588SBarry Smith }
1055289bc588SBarry Smith 
1056*0be0d8bdSHansol Suh static PetscErrorCode MatMultColumnRangeKernel_SeqDense(Mat A, Vec xx, Vec yy, PetscInt c_start, PetscInt c_end, PetscBool trans, PetscBool herm)
1057d71ae5a4SJacob Faibussowitsch {
1058c0bbcb79SLois Curfman McInnes   Mat_SeqDense      *mat = (Mat_SeqDense *)A->data;
1059d9ca1df4SBarry Smith   PetscScalar       *y, _DOne = 1.0, _DZero = 0.0;
10600805154bSBarry Smith   PetscBLASInt       m, n, _One             = 1;
1061d9ca1df4SBarry Smith   const PetscScalar *v = mat->v, *x;
10623a40ed3dSBarry Smith 
10633a40ed3dSBarry Smith   PetscFunctionBegin;
10649566063dSJacob Faibussowitsch   PetscCall(PetscBLASIntCast(A->rmap->n, &m));
1065*0be0d8bdSHansol Suh   PetscCall(PetscBLASIntCast(c_end - c_start, &n));
10669566063dSJacob Faibussowitsch   PetscCall(VecGetArrayRead(xx, &x));
10679566063dSJacob Faibussowitsch   PetscCall(VecGetArrayWrite(yy, &y));
1068*0be0d8bdSHansol Suh   if (!m || !n) {
10695ac36cfcSBarry Smith     PetscBLASInt i;
1070459e8d23SBlanca Mellado Pinto     if (trans)
1071459e8d23SBlanca Mellado Pinto       for (i = 0; i < n; i++) y[i] = 0.0;
1072459e8d23SBlanca Mellado Pinto     else
10735ac36cfcSBarry Smith       for (i = 0; i < m; i++) y[i] = 0.0;
10745ac36cfcSBarry Smith   } else {
1075459e8d23SBlanca Mellado Pinto     if (trans) {
1076*0be0d8bdSHansol Suh       if (herm) PetscCallBLAS("BLASgemv", BLASgemv_("C", &m, &n, &_DOne, v + c_start * mat->lda, &mat->lda, x, &_One, &_DZero, y + c_start, &_One));
1077*0be0d8bdSHansol Suh       else PetscCallBLAS("BLASgemv", BLASgemv_("T", &m, &n, &_DOne, v + c_start * mat->lda, &mat->lda, x, &_One, &_DZero, y + c_start, &_One));
1078459e8d23SBlanca Mellado Pinto     } else {
1079*0be0d8bdSHansol Suh       PetscCallBLAS("BLASgemv", BLASgemv_("N", &m, &n, &_DOne, v + c_start * mat->lda, &mat->lda, x + c_start, &_One, &_DZero, y, &_One));
1080459e8d23SBlanca Mellado Pinto     }
1081*0be0d8bdSHansol Suh     PetscCall(PetscLogFlops(2.0 * m * n - n));
10825ac36cfcSBarry Smith   }
10839566063dSJacob Faibussowitsch   PetscCall(VecRestoreArrayRead(xx, &x));
10849566063dSJacob Faibussowitsch   PetscCall(VecRestoreArrayWrite(yy, &y));
10853ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1086289bc588SBarry Smith }
10876ee01492SSatish Balay 
1088*0be0d8bdSHansol Suh PetscErrorCode MatMultHermitianTransposeColumnRange_SeqDense(Mat A, Vec xx, Vec yy, PetscInt c_start, PetscInt c_end)
1089*0be0d8bdSHansol Suh {
1090*0be0d8bdSHansol Suh   PetscFunctionBegin;
1091*0be0d8bdSHansol Suh   PetscCall(MatMultColumnRangeKernel_SeqDense(A, xx, yy, c_start, c_end, PETSC_TRUE, PETSC_TRUE));
1092*0be0d8bdSHansol Suh   PetscFunctionReturn(PETSC_SUCCESS);
1093*0be0d8bdSHansol Suh }
1094*0be0d8bdSHansol Suh 
1095459e8d23SBlanca Mellado Pinto PetscErrorCode MatMult_SeqDense(Mat A, Vec xx, Vec yy)
1096459e8d23SBlanca Mellado Pinto {
1097459e8d23SBlanca Mellado Pinto   PetscFunctionBegin;
1098*0be0d8bdSHansol Suh   PetscCall(MatMultColumnRangeKernel_SeqDense(A, xx, yy, 0, A->cmap->n, PETSC_FALSE, PETSC_FALSE));
1099459e8d23SBlanca Mellado Pinto   PetscFunctionReturn(PETSC_SUCCESS);
1100459e8d23SBlanca Mellado Pinto }
1101459e8d23SBlanca Mellado Pinto 
1102459e8d23SBlanca Mellado Pinto PetscErrorCode MatMultTranspose_SeqDense(Mat A, Vec xx, Vec yy)
1103459e8d23SBlanca Mellado Pinto {
1104459e8d23SBlanca Mellado Pinto   PetscFunctionBegin;
1105*0be0d8bdSHansol Suh   PetscCall(MatMultColumnRangeKernel_SeqDense(A, xx, yy, 0, A->cmap->n, PETSC_TRUE, PETSC_FALSE));
1106459e8d23SBlanca Mellado Pinto   PetscFunctionReturn(PETSC_SUCCESS);
1107459e8d23SBlanca Mellado Pinto }
1108459e8d23SBlanca Mellado Pinto 
1109459e8d23SBlanca Mellado Pinto PetscErrorCode MatMultHermitianTranspose_SeqDense(Mat A, Vec xx, Vec yy)
1110459e8d23SBlanca Mellado Pinto {
1111459e8d23SBlanca Mellado Pinto   PetscFunctionBegin;
1112*0be0d8bdSHansol Suh   PetscCall(MatMultColumnRangeKernel_SeqDense(A, xx, yy, 0, A->cmap->n, PETSC_TRUE, PETSC_TRUE));
1113459e8d23SBlanca Mellado Pinto   PetscFunctionReturn(PETSC_SUCCESS);
1114459e8d23SBlanca Mellado Pinto }
1115459e8d23SBlanca Mellado Pinto 
1116*0be0d8bdSHansol Suh static PetscErrorCode MatMultAddColumnRangeKernel_SeqDense(Mat A, Vec xx, Vec zz, Vec yy, PetscInt c_start, PetscInt c_end, PetscBool trans, PetscBool herm)
1117d71ae5a4SJacob Faibussowitsch {
1118c0bbcb79SLois Curfman McInnes   Mat_SeqDense      *mat = (Mat_SeqDense *)A->data;
1119d9ca1df4SBarry Smith   const PetscScalar *v   = mat->v, *x;
1120d9ca1df4SBarry Smith   PetscScalar       *y, _DOne = 1.0;
11210805154bSBarry Smith   PetscBLASInt       m, n, _One = 1;
11223a40ed3dSBarry Smith 
11233a40ed3dSBarry Smith   PetscFunctionBegin;
11249566063dSJacob Faibussowitsch   PetscCall(PetscBLASIntCast(A->rmap->n, &m));
1125*0be0d8bdSHansol Suh   PetscCall(PetscBLASIntCast(c_end - c_start, &n));
11269566063dSJacob Faibussowitsch   PetscCall(VecCopy(zz, yy));
1127*0be0d8bdSHansol Suh   if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS);
11289566063dSJacob Faibussowitsch   PetscCall(VecGetArray(yy, &y));
1129459e8d23SBlanca Mellado Pinto   PetscCall(VecGetArrayRead(xx, &x));
1130459e8d23SBlanca Mellado Pinto   if (trans) {
1131*0be0d8bdSHansol Suh     if (herm) PetscCallBLAS("BLASgemv", BLASgemv_("C", &m, &n, &_DOne, v + c_start * mat->lda, &mat->lda, x, &_One, &_DOne, y + c_start, &_One));
1132*0be0d8bdSHansol Suh     else PetscCallBLAS("BLASgemv", BLASgemv_("T", &m, &n, &_DOne, v + c_start * mat->lda, &mat->lda, x, &_One, &_DOne, y + c_start, &_One));
1133459e8d23SBlanca Mellado Pinto   } else {
1134*0be0d8bdSHansol Suh     PetscCallBLAS("BLASgemv", BLASgemv_("N", &m, &n, &_DOne, v + c_start * mat->lda, &mat->lda, x + c_start, &_One, &_DOne, y, &_One));
1135459e8d23SBlanca Mellado Pinto   }
11369566063dSJacob Faibussowitsch   PetscCall(VecRestoreArrayRead(xx, &x));
11379566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(yy, &y));
1138*0be0d8bdSHansol Suh   PetscCall(PetscLogFlops(2.0 * m * n));
1139*0be0d8bdSHansol Suh   PetscFunctionReturn(PETSC_SUCCESS);
1140*0be0d8bdSHansol Suh }
1141*0be0d8bdSHansol Suh 
1142*0be0d8bdSHansol Suh PetscErrorCode MatMultAddColumnRange_SeqDense(Mat A, Vec xx, Vec zz, Vec yy, PetscInt c_start, PetscInt c_end)
1143*0be0d8bdSHansol Suh {
1144*0be0d8bdSHansol Suh   PetscFunctionBegin;
1145*0be0d8bdSHansol Suh   PetscCall(MatMultAddColumnRangeKernel_SeqDense(A, xx, zz, yy, c_start, c_end, PETSC_FALSE, PETSC_FALSE));
1146*0be0d8bdSHansol Suh   PetscFunctionReturn(PETSC_SUCCESS);
1147*0be0d8bdSHansol Suh }
1148*0be0d8bdSHansol Suh 
1149*0be0d8bdSHansol Suh PetscErrorCode MatMultHermitianTransposeAddColumnRange_SeqDense(Mat A, Vec xx, Vec zz, Vec yy, PetscInt c_start, PetscInt c_end)
1150*0be0d8bdSHansol Suh {
1151*0be0d8bdSHansol Suh   PetscFunctionBegin;
1152*0be0d8bdSHansol Suh   PetscMPIInt rank;
1153*0be0d8bdSHansol Suh   PetscCallMPI(MPI_Comm_rank(MPI_COMM_WORLD, &rank));
1154*0be0d8bdSHansol Suh   PetscCall(MatMultAddColumnRangeKernel_SeqDense(A, xx, zz, yy, c_start, c_end, PETSC_TRUE, PETSC_TRUE));
11553ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1156289bc588SBarry Smith }
11576ee01492SSatish Balay 
1158459e8d23SBlanca Mellado Pinto PetscErrorCode MatMultAdd_SeqDense(Mat A, Vec xx, Vec zz, Vec yy)
1159459e8d23SBlanca Mellado Pinto {
1160459e8d23SBlanca Mellado Pinto   PetscFunctionBegin;
1161*0be0d8bdSHansol Suh   PetscCall(MatMultAddColumnRangeKernel_SeqDense(A, xx, zz, yy, 0, A->cmap->n, PETSC_FALSE, PETSC_FALSE));
1162459e8d23SBlanca Mellado Pinto   PetscFunctionReturn(PETSC_SUCCESS);
1163459e8d23SBlanca Mellado Pinto }
1164459e8d23SBlanca Mellado Pinto 
1165d71ae5a4SJacob Faibussowitsch PetscErrorCode MatMultTransposeAdd_SeqDense(Mat A, Vec xx, Vec zz, Vec yy)
1166d71ae5a4SJacob Faibussowitsch {
11673a40ed3dSBarry Smith   PetscFunctionBegin;
1168*0be0d8bdSHansol Suh   PetscCall(MatMultAddColumnRangeKernel_SeqDense(A, xx, zz, yy, 0, A->cmap->n, PETSC_TRUE, PETSC_FALSE));
1169459e8d23SBlanca Mellado Pinto   PetscFunctionReturn(PETSC_SUCCESS);
1170459e8d23SBlanca Mellado Pinto }
1171459e8d23SBlanca Mellado Pinto 
1172459e8d23SBlanca Mellado Pinto PetscErrorCode MatMultHermitianTransposeAdd_SeqDense(Mat A, Vec xx, Vec zz, Vec yy)
1173459e8d23SBlanca Mellado Pinto {
1174459e8d23SBlanca Mellado Pinto   PetscFunctionBegin;
1175*0be0d8bdSHansol Suh   PetscCall(MatMultAddColumnRangeKernel_SeqDense(A, xx, zz, yy, 0, A->cmap->n, PETSC_TRUE, PETSC_TRUE));
11763ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1177289bc588SBarry Smith }
1178289bc588SBarry Smith 
1179d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatGetRow_SeqDense(Mat A, PetscInt row, PetscInt *ncols, PetscInt **cols, PetscScalar **vals)
1180d71ae5a4SJacob Faibussowitsch {
1181c0bbcb79SLois Curfman McInnes   Mat_SeqDense *mat = (Mat_SeqDense *)A->data;
118213f74950SBarry Smith   PetscInt      i;
118367e560aaSBarry Smith 
11843a40ed3dSBarry Smith   PetscFunctionBegin;
1185c3e1b152SPierre Jolivet   if (ncols) *ncols = A->cmap->n;
1186289bc588SBarry Smith   if (cols) {
11879566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(A->cmap->n, cols));
1188d0f46423SBarry Smith     for (i = 0; i < A->cmap->n; i++) (*cols)[i] = i;
1189289bc588SBarry Smith   }
1190289bc588SBarry Smith   if (vals) {
1191ca15aa20SStefano Zampini     const PetscScalar *v;
1192ca15aa20SStefano Zampini 
11939566063dSJacob Faibussowitsch     PetscCall(MatDenseGetArrayRead(A, &v));
11949566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(A->cmap->n, vals));
1195ca15aa20SStefano Zampini     v += row;
11969371c9d4SSatish Balay     for (i = 0; i < A->cmap->n; i++) {
11979371c9d4SSatish Balay       (*vals)[i] = *v;
11989371c9d4SSatish Balay       v += mat->lda;
11999371c9d4SSatish Balay     }
12009566063dSJacob Faibussowitsch     PetscCall(MatDenseRestoreArrayRead(A, &v));
1201289bc588SBarry Smith   }
12023ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1203289bc588SBarry Smith }
12046ee01492SSatish Balay 
1205d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatRestoreRow_SeqDense(Mat A, PetscInt row, PetscInt *ncols, PetscInt **cols, PetscScalar **vals)
1206d71ae5a4SJacob Faibussowitsch {
1207606d414cSSatish Balay   PetscFunctionBegin;
12089566063dSJacob Faibussowitsch   if (cols) PetscCall(PetscFree(*cols));
12099566063dSJacob Faibussowitsch   if (vals) PetscCall(PetscFree(*vals));
12103ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1211289bc588SBarry Smith }
12122ef1f0ffSBarry Smith 
1213d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatSetValues_SeqDense(Mat A, PetscInt m, const PetscInt indexm[], PetscInt n, const PetscInt indexn[], const PetscScalar v[], InsertMode addv)
1214d71ae5a4SJacob Faibussowitsch {
1215c0bbcb79SLois Curfman McInnes   Mat_SeqDense *mat = (Mat_SeqDense *)A->data;
1216ca15aa20SStefano Zampini   PetscScalar  *av;
121713f74950SBarry Smith   PetscInt      i, j, idx = 0;
121847d993e7Ssuyashtn #if defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
1219c70f7ee4SJunchao Zhang   PetscOffloadMask oldf;
1220ca15aa20SStefano Zampini #endif
1221d6dfbf8fSBarry Smith 
12223a40ed3dSBarry Smith   PetscFunctionBegin;
12239566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArray(A, &av));
1224289bc588SBarry Smith   if (!mat->roworiented) {
1225dbb450caSBarry Smith     if (addv == INSERT_VALUES) {
1226289bc588SBarry Smith       for (j = 0; j < n; j++) {
12279371c9d4SSatish Balay         if (indexn[j] < 0) {
12289371c9d4SSatish Balay           idx += m;
12299371c9d4SSatish Balay           continue;
12309371c9d4SSatish Balay         }
12316bdcaf15SBarry 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);
1232289bc588SBarry Smith         for (i = 0; i < m; i++) {
12339371c9d4SSatish Balay           if (indexm[i] < 0) {
12349371c9d4SSatish Balay             idx++;
12359371c9d4SSatish Balay             continue;
12369371c9d4SSatish Balay           }
12376bdcaf15SBarry 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);
1238*0be0d8bdSHansol Suh           av[indexn[j] * mat->lda + indexm[i]] = v[idx++];
1239289bc588SBarry Smith         }
1240289bc588SBarry Smith       }
1241*0be0d8bdSHansol Suh     } else {
1242289bc588SBarry Smith       for (j = 0; j < n; j++) {
12439371c9d4SSatish Balay         if (indexn[j] < 0) {
12449371c9d4SSatish Balay           idx += m;
12459371c9d4SSatish Balay           continue;
12469371c9d4SSatish Balay         }
12476bdcaf15SBarry 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);
1248289bc588SBarry Smith         for (i = 0; i < m; i++) {
12499371c9d4SSatish Balay           if (indexm[i] < 0) {
12509371c9d4SSatish Balay             idx++;
12519371c9d4SSatish Balay             continue;
12529371c9d4SSatish Balay           }
12536bdcaf15SBarry 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);
1254ca15aa20SStefano Zampini           av[indexn[j] * mat->lda + indexm[i]] += v[idx++];
1255289bc588SBarry Smith         }
1256289bc588SBarry Smith       }
1257289bc588SBarry Smith     }
12583a40ed3dSBarry Smith   } else {
1259dbb450caSBarry Smith     if (addv == INSERT_VALUES) {
1260e8d4e0b9SBarry Smith       for (i = 0; i < m; i++) {
12619371c9d4SSatish Balay         if (indexm[i] < 0) {
12629371c9d4SSatish Balay           idx += n;
12639371c9d4SSatish Balay           continue;
12649371c9d4SSatish Balay         }
12656bdcaf15SBarry Smith         PetscCheck(indexm[i] < A->rmap->n, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Row too large: row %" PetscInt_FMT " max %" PetscInt_FMT, indexm[i], A->rmap->n - 1);
1266e8d4e0b9SBarry Smith         for (j = 0; j < n; j++) {
12679371c9d4SSatish Balay           if (indexn[j] < 0) {
12689371c9d4SSatish Balay             idx++;
12699371c9d4SSatish Balay             continue;
12709371c9d4SSatish Balay           }
12716bdcaf15SBarry 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);
1272*0be0d8bdSHansol Suh           av[indexn[j] * mat->lda + indexm[i]] = v[idx++];
1273e8d4e0b9SBarry Smith         }
1274e8d4e0b9SBarry Smith       }
1275*0be0d8bdSHansol Suh     } else {
1276289bc588SBarry Smith       for (i = 0; i < m; i++) {
12779371c9d4SSatish Balay         if (indexm[i] < 0) {
12789371c9d4SSatish Balay           idx += n;
12799371c9d4SSatish Balay           continue;
12809371c9d4SSatish Balay         }
12816bdcaf15SBarry 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);
1282289bc588SBarry Smith         for (j = 0; j < n; j++) {
12839371c9d4SSatish Balay           if (indexn[j] < 0) {
12849371c9d4SSatish Balay             idx++;
12859371c9d4SSatish Balay             continue;
12869371c9d4SSatish Balay           }
12876bdcaf15SBarry 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);
1288ca15aa20SStefano Zampini           av[indexn[j] * mat->lda + indexm[i]] += v[idx++];
1289289bc588SBarry Smith         }
1290289bc588SBarry Smith       }
1291289bc588SBarry Smith     }
1292e8d4e0b9SBarry Smith   }
1293ca15aa20SStefano Zampini   /* hack to prevent unneeded copy to the GPU while returning the array */
129447d993e7Ssuyashtn #if defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
1295c70f7ee4SJunchao Zhang   oldf           = A->offloadmask;
1296c70f7ee4SJunchao Zhang   A->offloadmask = PETSC_OFFLOAD_GPU;
1297ca15aa20SStefano Zampini #endif
12989566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArray(A, &av));
129947d993e7Ssuyashtn #if defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
1300c70f7ee4SJunchao Zhang   A->offloadmask = (oldf == PETSC_OFFLOAD_UNALLOCATED ? PETSC_OFFLOAD_UNALLOCATED : PETSC_OFFLOAD_CPU);
1301ca15aa20SStefano Zampini #endif
13023ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1303289bc588SBarry Smith }
1304e8d4e0b9SBarry Smith 
1305d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatGetValues_SeqDense(Mat A, PetscInt m, const PetscInt indexm[], PetscInt n, const PetscInt indexn[], PetscScalar v[])
1306d71ae5a4SJacob Faibussowitsch {
1307ae80bb75SLois Curfman McInnes   Mat_SeqDense      *mat = (Mat_SeqDense *)A->data;
1308ca15aa20SStefano Zampini   const PetscScalar *vv;
130913f74950SBarry Smith   PetscInt           i, j;
1310ae80bb75SLois Curfman McInnes 
13113a40ed3dSBarry Smith   PetscFunctionBegin;
13129566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArrayRead(A, &vv));
1313ae80bb75SLois Curfman McInnes   /* row-oriented output */
1314ae80bb75SLois Curfman McInnes   for (i = 0; i < m; i++) {
13159371c9d4SSatish Balay     if (indexm[i] < 0) {
13169371c9d4SSatish Balay       v += n;
13179371c9d4SSatish Balay       continue;
13189371c9d4SSatish Balay     }
131908401ef6SPierre 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);
1320ae80bb75SLois Curfman McInnes     for (j = 0; j < n; j++) {
13219371c9d4SSatish Balay       if (indexn[j] < 0) {
13229371c9d4SSatish Balay         v++;
13239371c9d4SSatish Balay         continue;
13249371c9d4SSatish Balay       }
132508401ef6SPierre 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);
1326ca15aa20SStefano Zampini       *v++ = vv[indexn[j] * mat->lda + indexm[i]];
1327ae80bb75SLois Curfman McInnes     }
1328ae80bb75SLois Curfman McInnes   }
13299566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArrayRead(A, &vv));
13303ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1331ae80bb75SLois Curfman McInnes }
1332ae80bb75SLois Curfman McInnes 
1333d71ae5a4SJacob Faibussowitsch PetscErrorCode MatView_Dense_Binary(Mat mat, PetscViewer viewer)
1334d71ae5a4SJacob Faibussowitsch {
13358491ab44SLisandro Dalcin   PetscBool          skipHeader;
13368491ab44SLisandro Dalcin   PetscViewerFormat  format;
13378491ab44SLisandro Dalcin   PetscInt           header[4], M, N, m, lda, i, j, k;
13388491ab44SLisandro Dalcin   const PetscScalar *v;
13398491ab44SLisandro Dalcin   PetscScalar       *vwork;
1340aabbc4fbSShri Abhyankar 
1341aabbc4fbSShri Abhyankar   PetscFunctionBegin;
13429566063dSJacob Faibussowitsch   PetscCall(PetscViewerSetUp(viewer));
13439566063dSJacob Faibussowitsch   PetscCall(PetscViewerBinaryGetSkipHeader(viewer, &skipHeader));
13449566063dSJacob Faibussowitsch   PetscCall(PetscViewerGetFormat(viewer, &format));
13458491ab44SLisandro Dalcin   if (skipHeader) format = PETSC_VIEWER_NATIVE;
1346aabbc4fbSShri Abhyankar 
13479566063dSJacob Faibussowitsch   PetscCall(MatGetSize(mat, &M, &N));
13488491ab44SLisandro Dalcin 
13498491ab44SLisandro Dalcin   /* write matrix header */
13509371c9d4SSatish Balay   header[0] = MAT_FILE_CLASSID;
13519371c9d4SSatish Balay   header[1] = M;
13529371c9d4SSatish Balay   header[2] = N;
13538491ab44SLisandro Dalcin   header[3] = (format == PETSC_VIEWER_NATIVE) ? MATRIX_BINARY_FORMAT_DENSE : M * N;
13549566063dSJacob Faibussowitsch   if (!skipHeader) PetscCall(PetscViewerBinaryWrite(viewer, header, 4, PETSC_INT));
13558491ab44SLisandro Dalcin 
13569566063dSJacob Faibussowitsch   PetscCall(MatGetLocalSize(mat, &m, NULL));
13578491ab44SLisandro Dalcin   if (format != PETSC_VIEWER_NATIVE) {
13588491ab44SLisandro Dalcin     PetscInt nnz = m * N, *iwork;
13598491ab44SLisandro Dalcin     /* store row lengths for each row */
13609566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(nnz, &iwork));
13618491ab44SLisandro Dalcin     for (i = 0; i < m; i++) iwork[i] = N;
13629566063dSJacob Faibussowitsch     PetscCall(PetscViewerBinaryWriteAll(viewer, iwork, m, PETSC_DETERMINE, PETSC_DETERMINE, PETSC_INT));
13638491ab44SLisandro Dalcin     /* store column indices (zero start index) */
13648491ab44SLisandro Dalcin     for (k = 0, i = 0; i < m; i++)
13659371c9d4SSatish Balay       for (j = 0; j < N; j++, k++) iwork[k] = j;
13669566063dSJacob Faibussowitsch     PetscCall(PetscViewerBinaryWriteAll(viewer, iwork, nnz, PETSC_DETERMINE, PETSC_DETERMINE, PETSC_INT));
13679566063dSJacob Faibussowitsch     PetscCall(PetscFree(iwork));
13688491ab44SLisandro Dalcin   }
13698491ab44SLisandro Dalcin   /* store matrix values as a dense matrix in row major order */
13709566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(m * N, &vwork));
13719566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArrayRead(mat, &v));
13729566063dSJacob Faibussowitsch   PetscCall(MatDenseGetLDA(mat, &lda));
13738491ab44SLisandro Dalcin   for (k = 0, i = 0; i < m; i++)
13749371c9d4SSatish Balay     for (j = 0; j < N; j++, k++) vwork[k] = v[i + lda * j];
13759566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArrayRead(mat, &v));
13769566063dSJacob Faibussowitsch   PetscCall(PetscViewerBinaryWriteAll(viewer, vwork, m * N, PETSC_DETERMINE, PETSC_DETERMINE, PETSC_SCALAR));
13779566063dSJacob Faibussowitsch   PetscCall(PetscFree(vwork));
13783ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
13798491ab44SLisandro Dalcin }
13808491ab44SLisandro Dalcin 
1381d71ae5a4SJacob Faibussowitsch PetscErrorCode MatLoad_Dense_Binary(Mat mat, PetscViewer viewer)
1382d71ae5a4SJacob Faibussowitsch {
13838491ab44SLisandro Dalcin   PetscBool    skipHeader;
13848491ab44SLisandro Dalcin   PetscInt     header[4], M, N, m, nz, lda, i, j, k;
13858491ab44SLisandro Dalcin   PetscInt     rows, cols;
13868491ab44SLisandro Dalcin   PetscScalar *v, *vwork;
13878491ab44SLisandro Dalcin 
13888491ab44SLisandro Dalcin   PetscFunctionBegin;
13899566063dSJacob Faibussowitsch   PetscCall(PetscViewerSetUp(viewer));
13909566063dSJacob Faibussowitsch   PetscCall(PetscViewerBinaryGetSkipHeader(viewer, &skipHeader));
13918491ab44SLisandro Dalcin 
13928491ab44SLisandro Dalcin   if (!skipHeader) {
13939566063dSJacob Faibussowitsch     PetscCall(PetscViewerBinaryRead(viewer, header, 4, NULL, PETSC_INT));
139408401ef6SPierre Jolivet     PetscCheck(header[0] == MAT_FILE_CLASSID, PetscObjectComm((PetscObject)viewer), PETSC_ERR_FILE_UNEXPECTED, "Not a matrix object in file");
13959371c9d4SSatish Balay     M = header[1];
13969371c9d4SSatish Balay     N = header[2];
139708401ef6SPierre Jolivet     PetscCheck(M >= 0, PetscObjectComm((PetscObject)viewer), PETSC_ERR_FILE_UNEXPECTED, "Matrix row size (%" PetscInt_FMT ") in file is negative", M);
139808401ef6SPierre Jolivet     PetscCheck(N >= 0, PetscObjectComm((PetscObject)viewer), PETSC_ERR_FILE_UNEXPECTED, "Matrix column size (%" PetscInt_FMT ") in file is negative", N);
13998491ab44SLisandro Dalcin     nz = header[3];
1400aed4548fSBarry Smith     PetscCheck(nz == MATRIX_BINARY_FORMAT_DENSE || nz >= 0, PetscObjectComm((PetscObject)viewer), PETSC_ERR_FILE_UNEXPECTED, "Unknown matrix format %" PetscInt_FMT " in file", nz);
1401aabbc4fbSShri Abhyankar   } else {
14029566063dSJacob Faibussowitsch     PetscCall(MatGetSize(mat, &M, &N));
1403aed4548fSBarry 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");
14048491ab44SLisandro Dalcin     nz = MATRIX_BINARY_FORMAT_DENSE;
1405e6324fbbSBarry Smith   }
1406aabbc4fbSShri Abhyankar 
14078491ab44SLisandro Dalcin   /* setup global sizes if not set */
14088491ab44SLisandro Dalcin   if (mat->rmap->N < 0) mat->rmap->N = M;
14098491ab44SLisandro Dalcin   if (mat->cmap->N < 0) mat->cmap->N = N;
14109566063dSJacob Faibussowitsch   PetscCall(MatSetUp(mat));
14118491ab44SLisandro Dalcin   /* check if global sizes are correct */
14129566063dSJacob Faibussowitsch   PetscCall(MatGetSize(mat, &rows, &cols));
1413aed4548fSBarry 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);
1414aabbc4fbSShri Abhyankar 
14159566063dSJacob Faibussowitsch   PetscCall(MatGetSize(mat, NULL, &N));
14169566063dSJacob Faibussowitsch   PetscCall(MatGetLocalSize(mat, &m, NULL));
14179566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArray(mat, &v));
14189566063dSJacob Faibussowitsch   PetscCall(MatDenseGetLDA(mat, &lda));
14198491ab44SLisandro Dalcin   if (nz == MATRIX_BINARY_FORMAT_DENSE) { /* matrix in file is dense format */
14208491ab44SLisandro Dalcin     PetscInt nnz = m * N;
14218491ab44SLisandro Dalcin     /* read in matrix values */
14229566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(nnz, &vwork));
14239566063dSJacob Faibussowitsch     PetscCall(PetscViewerBinaryReadAll(viewer, vwork, nnz, PETSC_DETERMINE, PETSC_DETERMINE, PETSC_SCALAR));
14248491ab44SLisandro Dalcin     /* store values in column major order */
14258491ab44SLisandro Dalcin     for (j = 0; j < N; j++)
14269371c9d4SSatish Balay       for (i = 0; i < m; i++) v[i + lda * j] = vwork[i * N + j];
14279566063dSJacob Faibussowitsch     PetscCall(PetscFree(vwork));
14288491ab44SLisandro Dalcin   } else { /* matrix in file is sparse format */
14298491ab44SLisandro Dalcin     PetscInt nnz = 0, *rlens, *icols;
14308491ab44SLisandro Dalcin     /* read in row lengths */
14319566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(m, &rlens));
14329566063dSJacob Faibussowitsch     PetscCall(PetscViewerBinaryReadAll(viewer, rlens, m, PETSC_DETERMINE, PETSC_DETERMINE, PETSC_INT));
14338491ab44SLisandro Dalcin     for (i = 0; i < m; i++) nnz += rlens[i];
14348491ab44SLisandro Dalcin     /* read in column indices and values */
14359566063dSJacob Faibussowitsch     PetscCall(PetscMalloc2(nnz, &icols, nnz, &vwork));
14369566063dSJacob Faibussowitsch     PetscCall(PetscViewerBinaryReadAll(viewer, icols, nnz, PETSC_DETERMINE, PETSC_DETERMINE, PETSC_INT));
14379566063dSJacob Faibussowitsch     PetscCall(PetscViewerBinaryReadAll(viewer, vwork, nnz, PETSC_DETERMINE, PETSC_DETERMINE, PETSC_SCALAR));
14388491ab44SLisandro Dalcin     /* store values in column major order */
14398491ab44SLisandro Dalcin     for (k = 0, i = 0; i < m; i++)
14409371c9d4SSatish Balay       for (j = 0; j < rlens[i]; j++, k++) v[i + lda * icols[k]] = vwork[k];
14419566063dSJacob Faibussowitsch     PetscCall(PetscFree(rlens));
14429566063dSJacob Faibussowitsch     PetscCall(PetscFree2(icols, vwork));
1443aabbc4fbSShri Abhyankar   }
14449566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArray(mat, &v));
14459566063dSJacob Faibussowitsch   PetscCall(MatAssemblyBegin(mat, MAT_FINAL_ASSEMBLY));
14469566063dSJacob Faibussowitsch   PetscCall(MatAssemblyEnd(mat, MAT_FINAL_ASSEMBLY));
14473ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1448aabbc4fbSShri Abhyankar }
1449aabbc4fbSShri Abhyankar 
145066976f2fSJacob Faibussowitsch static PetscErrorCode MatLoad_SeqDense(Mat newMat, PetscViewer viewer)
1451d71ae5a4SJacob Faibussowitsch {
1452eb91f321SVaclav Hapla   PetscBool isbinary, ishdf5;
1453eb91f321SVaclav Hapla 
1454eb91f321SVaclav Hapla   PetscFunctionBegin;
1455eb91f321SVaclav Hapla   PetscValidHeaderSpecific(newMat, MAT_CLASSID, 1);
1456eb91f321SVaclav Hapla   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
1457eb91f321SVaclav Hapla   /* force binary viewer to load .info file if it has not yet done so */
14589566063dSJacob Faibussowitsch   PetscCall(PetscViewerSetUp(viewer));
14599566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERBINARY, &isbinary));
14609566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5));
1461eb91f321SVaclav Hapla   if (isbinary) {
14629566063dSJacob Faibussowitsch     PetscCall(MatLoad_Dense_Binary(newMat, viewer));
1463eb91f321SVaclav Hapla   } else if (ishdf5) {
1464eb91f321SVaclav Hapla #if defined(PETSC_HAVE_HDF5)
14659566063dSJacob Faibussowitsch     PetscCall(MatLoad_Dense_HDF5(newMat, viewer));
1466eb91f321SVaclav Hapla #else
1467eb91f321SVaclav Hapla     SETERRQ(PetscObjectComm((PetscObject)newMat), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5");
1468eb91f321SVaclav Hapla #endif
1469eb91f321SVaclav Hapla   } else {
147098921bdaSJacob 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);
1471eb91f321SVaclav Hapla   }
14723ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1473eb91f321SVaclav Hapla }
1474eb91f321SVaclav Hapla 
1475d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatView_SeqDense_ASCII(Mat A, PetscViewer viewer)
1476d71ae5a4SJacob Faibussowitsch {
1477932b0c3eSLois Curfman McInnes   Mat_SeqDense     *a = (Mat_SeqDense *)A->data;
147813f74950SBarry Smith   PetscInt          i, j;
14792dcb1b2aSMatthew Knepley   const char       *name;
1480ca15aa20SStefano Zampini   PetscScalar      *v, *av;
1481f3ef73ceSBarry Smith   PetscViewerFormat format;
14825f481a85SSatish Balay #if defined(PETSC_USE_COMPLEX)
1483ace3abfcSBarry Smith   PetscBool allreal = PETSC_TRUE;
14845f481a85SSatish Balay #endif
1485932b0c3eSLois Curfman McInnes 
14863a40ed3dSBarry Smith   PetscFunctionBegin;
14879566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArrayRead(A, (const PetscScalar **)&av));
14889566063dSJacob Faibussowitsch   PetscCall(PetscViewerGetFormat(viewer, &format));
1489456192e2SBarry Smith   if (format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL) {
14903ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS); /* do nothing for now */
1491fb9695e5SSatish Balay   } else if (format == PETSC_VIEWER_ASCII_COMMON) {
14929566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIUseTabs(viewer, PETSC_FALSE));
1493d0f46423SBarry Smith     for (i = 0; i < A->rmap->n; i++) {
1494ca15aa20SStefano Zampini       v = av + i;
14959566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "row %" PetscInt_FMT ":", i));
1496d0f46423SBarry Smith       for (j = 0; j < A->cmap->n; j++) {
1497aa482453SBarry Smith #if defined(PETSC_USE_COMPLEX)
1498329f5518SBarry Smith         if (PetscRealPart(*v) != 0.0 && PetscImaginaryPart(*v) != 0.0) {
14999566063dSJacob Faibussowitsch           PetscCall(PetscViewerASCIIPrintf(viewer, " (%" PetscInt_FMT ", %g + %g i) ", j, (double)PetscRealPart(*v), (double)PetscImaginaryPart(*v)));
1500329f5518SBarry Smith         } else if (PetscRealPart(*v)) {
15019566063dSJacob Faibussowitsch           PetscCall(PetscViewerASCIIPrintf(viewer, " (%" PetscInt_FMT ", %g) ", j, (double)PetscRealPart(*v)));
15026831982aSBarry Smith         }
150380cd9d93SLois Curfman McInnes #else
150448a46eb9SPierre Jolivet         if (*v) PetscCall(PetscViewerASCIIPrintf(viewer, " (%" PetscInt_FMT ", %g) ", j, (double)*v));
150580cd9d93SLois Curfman McInnes #endif
15061b807ce4Svictorle         v += a->lda;
150780cd9d93SLois Curfman McInnes       }
15089566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "\n"));
150980cd9d93SLois Curfman McInnes     }
15109566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIUseTabs(viewer, PETSC_TRUE));
15113a40ed3dSBarry Smith   } else {
15129566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIUseTabs(viewer, PETSC_FALSE));
1513aa482453SBarry Smith #if defined(PETSC_USE_COMPLEX)
151447989497SBarry Smith     /* determine if matrix has all real values */
1515bcd8d3a4SJose E. Roman     for (j = 0; j < A->cmap->n; j++) {
1516bcd8d3a4SJose E. Roman       v = av + j * a->lda;
1517bcd8d3a4SJose E. Roman       for (i = 0; i < A->rmap->n; i++) {
15189371c9d4SSatish Balay         if (PetscImaginaryPart(v[i])) {
15199371c9d4SSatish Balay           allreal = PETSC_FALSE;
15209371c9d4SSatish Balay           break;
15219371c9d4SSatish Balay         }
152247989497SBarry Smith       }
1523bcd8d3a4SJose E. Roman     }
152447989497SBarry Smith #endif
1525fb9695e5SSatish Balay     if (format == PETSC_VIEWER_ASCII_MATLAB) {
15269566063dSJacob Faibussowitsch       PetscCall(PetscObjectGetName((PetscObject)A, &name));
15279566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "%% Size = %" PetscInt_FMT " %" PetscInt_FMT " \n", A->rmap->n, A->cmap->n));
15289566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "%s = zeros(%" PetscInt_FMT ",%" PetscInt_FMT ");\n", name, A->rmap->n, A->cmap->n));
15299566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "%s = [\n", name));
1530ffac6cdbSBarry Smith     }
1531ffac6cdbSBarry Smith 
1532d0f46423SBarry Smith     for (i = 0; i < A->rmap->n; i++) {
1533ca15aa20SStefano Zampini       v = av + i;
1534d0f46423SBarry Smith       for (j = 0; j < A->cmap->n; j++) {
1535aa482453SBarry Smith #if defined(PETSC_USE_COMPLEX)
153647989497SBarry Smith         if (allreal) {
15379566063dSJacob Faibussowitsch           PetscCall(PetscViewerASCIIPrintf(viewer, "%18.16e ", (double)PetscRealPart(*v)));
153847989497SBarry Smith         } else {
15399566063dSJacob Faibussowitsch           PetscCall(PetscViewerASCIIPrintf(viewer, "%18.16e + %18.16ei ", (double)PetscRealPart(*v), (double)PetscImaginaryPart(*v)));
154047989497SBarry Smith         }
1541289bc588SBarry Smith #else
15429566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, "%18.16e ", (double)*v));
1543289bc588SBarry Smith #endif
15441b807ce4Svictorle         v += a->lda;
1545289bc588SBarry Smith       }
15469566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "\n"));
1547289bc588SBarry Smith     }
154848a46eb9SPierre Jolivet     if (format == PETSC_VIEWER_ASCII_MATLAB) PetscCall(PetscViewerASCIIPrintf(viewer, "];\n"));
15499566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIUseTabs(viewer, PETSC_TRUE));
1550da3a660dSBarry Smith   }
15519566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArrayRead(A, (const PetscScalar **)&av));
15529566063dSJacob Faibussowitsch   PetscCall(PetscViewerFlush(viewer));
15533ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1554289bc588SBarry Smith }
1555289bc588SBarry Smith 
15569804daf3SBarry Smith #include <petscdraw.h>
1557d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatView_SeqDense_Draw_Zoom(PetscDraw draw, void *Aa)
1558d71ae5a4SJacob Faibussowitsch {
1559f1af5d2fSBarry Smith   Mat                A = (Mat)Aa;
1560383922c3SLisandro Dalcin   PetscInt           m = A->rmap->n, n = A->cmap->n, i, j;
1561383922c3SLisandro Dalcin   int                color = PETSC_DRAW_WHITE;
1562ca15aa20SStefano Zampini   const PetscScalar *v;
1563b0a32e0cSBarry Smith   PetscViewer        viewer;
1564b05fc000SLisandro Dalcin   PetscReal          xl, yl, xr, yr, x_l, x_r, y_l, y_r;
1565f3ef73ceSBarry Smith   PetscViewerFormat  format;
1566f1af5d2fSBarry Smith 
1567f1af5d2fSBarry Smith   PetscFunctionBegin;
15689566063dSJacob Faibussowitsch   PetscCall(PetscObjectQuery((PetscObject)A, "Zoomviewer", (PetscObject *)&viewer));
15699566063dSJacob Faibussowitsch   PetscCall(PetscViewerGetFormat(viewer, &format));
15709566063dSJacob Faibussowitsch   PetscCall(PetscDrawGetCoordinates(draw, &xl, &yl, &xr, &yr));
1571f1af5d2fSBarry Smith 
1572f1af5d2fSBarry Smith   /* Loop over matrix elements drawing boxes */
15739566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArrayRead(A, &v));
1574fb9695e5SSatish Balay   if (format != PETSC_VIEWER_DRAW_CONTOUR) {
1575d0609cedSBarry Smith     PetscDrawCollectiveBegin(draw);
1576f1af5d2fSBarry Smith     /* Blue for negative and Red for positive */
1577f1af5d2fSBarry Smith     for (j = 0; j < n; j++) {
15789371c9d4SSatish Balay       x_l = j;
15799371c9d4SSatish Balay       x_r = x_l + 1.0;
1580f1af5d2fSBarry Smith       for (i = 0; i < m; i++) {
1581f1af5d2fSBarry Smith         y_l = m - i - 1.0;
1582f1af5d2fSBarry Smith         y_r = y_l + 1.0;
1583ca15aa20SStefano Zampini         if (PetscRealPart(v[j * m + i]) > 0.) color = PETSC_DRAW_RED;
1584ca15aa20SStefano Zampini         else if (PetscRealPart(v[j * m + i]) < 0.) color = PETSC_DRAW_BLUE;
1585ca15aa20SStefano Zampini         else continue;
15869566063dSJacob Faibussowitsch         PetscCall(PetscDrawRectangle(draw, x_l, y_l, x_r, y_r, color, color, color, color));
1587f1af5d2fSBarry Smith       }
1588f1af5d2fSBarry Smith     }
1589d0609cedSBarry Smith     PetscDrawCollectiveEnd(draw);
1590f1af5d2fSBarry Smith   } else {
1591f1af5d2fSBarry Smith     /* use contour shading to indicate magnitude of values */
1592f1af5d2fSBarry Smith     /* first determine max of all nonzero values */
1593b05fc000SLisandro Dalcin     PetscReal minv = 0.0, maxv = 0.0;
1594b05fc000SLisandro Dalcin     PetscDraw popup;
1595b05fc000SLisandro Dalcin 
1596f1af5d2fSBarry Smith     for (i = 0; i < m * n; i++) {
1597f1af5d2fSBarry Smith       if (PetscAbsScalar(v[i]) > maxv) maxv = PetscAbsScalar(v[i]);
1598f1af5d2fSBarry Smith     }
1599383922c3SLisandro Dalcin     if (minv >= maxv) maxv = minv + PETSC_SMALL;
16009566063dSJacob Faibussowitsch     PetscCall(PetscDrawGetPopup(draw, &popup));
16019566063dSJacob Faibussowitsch     PetscCall(PetscDrawScalePopup(popup, minv, maxv));
1602383922c3SLisandro Dalcin 
1603d0609cedSBarry Smith     PetscDrawCollectiveBegin(draw);
1604f1af5d2fSBarry Smith     for (j = 0; j < n; j++) {
1605f1af5d2fSBarry Smith       x_l = j;
1606f1af5d2fSBarry Smith       x_r = x_l + 1.0;
1607f1af5d2fSBarry Smith       for (i = 0; i < m; i++) {
1608f1af5d2fSBarry Smith         y_l   = m - i - 1.0;
1609f1af5d2fSBarry Smith         y_r   = y_l + 1.0;
1610b05fc000SLisandro Dalcin         color = PetscDrawRealToColor(PetscAbsScalar(v[j * m + i]), minv, maxv);
16119566063dSJacob Faibussowitsch         PetscCall(PetscDrawRectangle(draw, x_l, y_l, x_r, y_r, color, color, color, color));
1612f1af5d2fSBarry Smith       }
1613f1af5d2fSBarry Smith     }
1614d0609cedSBarry Smith     PetscDrawCollectiveEnd(draw);
1615f1af5d2fSBarry Smith   }
16169566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArrayRead(A, &v));
16173ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1618f1af5d2fSBarry Smith }
1619f1af5d2fSBarry Smith 
1620d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatView_SeqDense_Draw(Mat A, PetscViewer viewer)
1621d71ae5a4SJacob Faibussowitsch {
1622b0a32e0cSBarry Smith   PetscDraw draw;
1623ace3abfcSBarry Smith   PetscBool isnull;
1624329f5518SBarry Smith   PetscReal xr, yr, xl, yl, h, w;
1625f1af5d2fSBarry Smith 
1626f1af5d2fSBarry Smith   PetscFunctionBegin;
16279566063dSJacob Faibussowitsch   PetscCall(PetscViewerDrawGetDraw(viewer, 0, &draw));
16289566063dSJacob Faibussowitsch   PetscCall(PetscDrawIsNull(draw, &isnull));
16293ba16761SJacob Faibussowitsch   if (isnull) PetscFunctionReturn(PETSC_SUCCESS);
1630f1af5d2fSBarry Smith 
16319371c9d4SSatish Balay   xr = A->cmap->n;
16329371c9d4SSatish Balay   yr = A->rmap->n;
16339371c9d4SSatish Balay   h  = yr / 10.0;
16349371c9d4SSatish Balay   w  = xr / 10.0;
16359371c9d4SSatish Balay   xr += w;
16369371c9d4SSatish Balay   yr += h;
16379371c9d4SSatish Balay   xl = -w;
16389371c9d4SSatish Balay   yl = -h;
16399566063dSJacob Faibussowitsch   PetscCall(PetscDrawSetCoordinates(draw, xl, yl, xr, yr));
16409566063dSJacob Faibussowitsch   PetscCall(PetscObjectCompose((PetscObject)A, "Zoomviewer", (PetscObject)viewer));
16419566063dSJacob Faibussowitsch   PetscCall(PetscDrawZoom(draw, MatView_SeqDense_Draw_Zoom, A));
16429566063dSJacob Faibussowitsch   PetscCall(PetscObjectCompose((PetscObject)A, "Zoomviewer", NULL));
16439566063dSJacob Faibussowitsch   PetscCall(PetscDrawSave(draw));
16443ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1645f1af5d2fSBarry Smith }
1646f1af5d2fSBarry Smith 
1647d71ae5a4SJacob Faibussowitsch PetscErrorCode MatView_SeqDense(Mat A, PetscViewer viewer)
1648d71ae5a4SJacob Faibussowitsch {
1649ace3abfcSBarry Smith   PetscBool iascii, isbinary, isdraw;
1650932b0c3eSLois Curfman McInnes 
16513a40ed3dSBarry Smith   PetscFunctionBegin;
16529566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
16539566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERBINARY, &isbinary));
16549566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERDRAW, &isdraw));
16551baa6e33SBarry Smith   if (iascii) PetscCall(MatView_SeqDense_ASCII(A, viewer));
16561baa6e33SBarry Smith   else if (isbinary) PetscCall(MatView_Dense_Binary(A, viewer));
16571baa6e33SBarry Smith   else if (isdraw) PetscCall(MatView_SeqDense_Draw(A, viewer));
16583ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1659932b0c3eSLois Curfman McInnes }
1660289bc588SBarry Smith 
1661d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatDensePlaceArray_SeqDense(Mat A, const PetscScalar *array)
1662d71ae5a4SJacob Faibussowitsch {
1663d3042a70SBarry Smith   Mat_SeqDense *a = (Mat_SeqDense *)A->data;
1664d3042a70SBarry Smith 
1665d3042a70SBarry Smith   PetscFunctionBegin;
166628b400f6SJacob Faibussowitsch   PetscCheck(!a->vecinuse, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Need to call MatDenseRestoreColumnVec() first");
166728b400f6SJacob Faibussowitsch   PetscCheck(!a->matinuse, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Need to call MatDenseRestoreSubMatrix() first");
166828b400f6SJacob Faibussowitsch   PetscCheck(!a->unplacedarray, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Need to call MatDenseRestoreArray() first");
1669d3042a70SBarry Smith   a->unplacedarray       = a->v;
1670d3042a70SBarry Smith   a->unplaced_user_alloc = a->user_alloc;
1671d3042a70SBarry Smith   a->v                   = (PetscScalar *)array;
1672637a0070SStefano Zampini   a->user_alloc          = PETSC_TRUE;
167347d993e7Ssuyashtn #if defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
1674c70f7ee4SJunchao Zhang   A->offloadmask = PETSC_OFFLOAD_CPU;
1675ca15aa20SStefano Zampini #endif
16763ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1677d3042a70SBarry Smith }
1678d3042a70SBarry Smith 
1679d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatDenseResetArray_SeqDense(Mat A)
1680d71ae5a4SJacob Faibussowitsch {
1681d3042a70SBarry Smith   Mat_SeqDense *a = (Mat_SeqDense *)A->data;
1682d3042a70SBarry Smith 
1683d3042a70SBarry Smith   PetscFunctionBegin;
168428b400f6SJacob Faibussowitsch   PetscCheck(!a->vecinuse, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Need to call MatDenseRestoreColumnVec() first");
168528b400f6SJacob Faibussowitsch   PetscCheck(!a->matinuse, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Need to call MatDenseRestoreSubMatrix() first");
1686d3042a70SBarry Smith   a->v             = a->unplacedarray;
1687d3042a70SBarry Smith   a->user_alloc    = a->unplaced_user_alloc;
1688d3042a70SBarry Smith   a->unplacedarray = NULL;
168947d993e7Ssuyashtn #if defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
1690c70f7ee4SJunchao Zhang   A->offloadmask = PETSC_OFFLOAD_CPU;
1691ca15aa20SStefano Zampini #endif
16923ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1693d3042a70SBarry Smith }
1694d3042a70SBarry Smith 
1695d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatDenseReplaceArray_SeqDense(Mat A, const PetscScalar *array)
1696d71ae5a4SJacob Faibussowitsch {
1697d5ea218eSStefano Zampini   Mat_SeqDense *a = (Mat_SeqDense *)A->data;
1698d5ea218eSStefano Zampini 
1699d5ea218eSStefano Zampini   PetscFunctionBegin;
170028b400f6SJacob Faibussowitsch   PetscCheck(!a->vecinuse, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Need to call MatDenseRestoreColumnVec() first");
170128b400f6SJacob Faibussowitsch   PetscCheck(!a->matinuse, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Need to call MatDenseRestoreSubMatrix() first");
17029566063dSJacob Faibussowitsch   if (!a->user_alloc) PetscCall(PetscFree(a->v));
1703d5ea218eSStefano Zampini   a->v          = (PetscScalar *)array;
1704d5ea218eSStefano Zampini   a->user_alloc = PETSC_FALSE;
170547d993e7Ssuyashtn #if defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
1706d5ea218eSStefano Zampini   A->offloadmask = PETSC_OFFLOAD_CPU;
1707d5ea218eSStefano Zampini #endif
17083ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1709d5ea218eSStefano Zampini }
1710d5ea218eSStefano Zampini 
1711d71ae5a4SJacob Faibussowitsch PetscErrorCode MatDestroy_SeqDense(Mat mat)
1712d71ae5a4SJacob Faibussowitsch {
1713ec8511deSBarry Smith   Mat_SeqDense *l = (Mat_SeqDense *)mat->data;
171490f02eecSBarry Smith 
17153a40ed3dSBarry Smith   PetscFunctionBegin;
17163ba16761SJacob Faibussowitsch   PetscCall(PetscLogObjectState((PetscObject)mat, "Rows %" PetscInt_FMT " Cols %" PetscInt_FMT, mat->rmap->n, mat->cmap->n));
1717f4f49eeaSPierre Jolivet   PetscCall(VecDestroy(&l->qrrhs));
17189566063dSJacob Faibussowitsch   PetscCall(PetscFree(l->tau));
17199566063dSJacob Faibussowitsch   PetscCall(PetscFree(l->pivots));
17209566063dSJacob Faibussowitsch   PetscCall(PetscFree(l->fwork));
17219566063dSJacob Faibussowitsch   if (!l->user_alloc) PetscCall(PetscFree(l->v));
17229566063dSJacob Faibussowitsch   if (!l->unplaced_user_alloc) PetscCall(PetscFree(l->unplacedarray));
172328b400f6SJacob Faibussowitsch   PetscCheck(!l->vecinuse, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Need to call MatDenseRestoreColumnVec() first");
172428b400f6SJacob Faibussowitsch   PetscCheck(!l->matinuse, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Need to call MatDenseRestoreSubMatrix() first");
17259566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&l->cvec));
17269566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&l->cmat));
17279566063dSJacob Faibussowitsch   PetscCall(PetscFree(mat->data));
1728dbd8c25aSHong Zhang 
17299566063dSJacob Faibussowitsch   PetscCall(PetscObjectChangeTypeName((PetscObject)mat, NULL));
17309566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatQRFactor_C", NULL));
17312e956fe4SStefano Zampini   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatQRFactorSymbolic_C", NULL));
17322e956fe4SStefano Zampini   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatQRFactorNumeric_C", NULL));
17339566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatDenseGetLDA_C", NULL));
17349566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatDenseSetLDA_C", NULL));
17359566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatDenseGetArray_C", NULL));
17369566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatDenseRestoreArray_C", NULL));
17379566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatDensePlaceArray_C", NULL));
17389566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatDenseResetArray_C", NULL));
17399566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatDenseReplaceArray_C", NULL));
17409566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatDenseGetArrayRead_C", NULL));
17419566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatDenseRestoreArrayRead_C", NULL));
17429566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatDenseGetArrayWrite_C", NULL));
17439566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatDenseRestoreArrayWrite_C", NULL));
17449566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatConvert_seqdense_seqaij_C", NULL));
17458baccfbdSHong Zhang #if defined(PETSC_HAVE_ELEMENTAL)
17469566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatConvert_seqdense_elemental_C", NULL));
17478baccfbdSHong Zhang #endif
1748d24d4204SJose E. Roman #if defined(PETSC_HAVE_SCALAPACK)
17499566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatConvert_seqdense_scalapack_C", NULL));
1750d24d4204SJose E. Roman #endif
17512bf066beSStefano Zampini #if defined(PETSC_HAVE_CUDA)
17529566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatConvert_seqdense_seqdensecuda_C", NULL));
17539566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatProductSetFromOptions_seqdensecuda_seqdensecuda_C", NULL));
17549566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatProductSetFromOptions_seqdensecuda_seqdense_C", NULL));
17552e956fe4SStefano Zampini   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatProductSetFromOptions_seqdense_seqdensecuda_C", NULL));
17562bf066beSStefano Zampini #endif
175747d993e7Ssuyashtn #if defined(PETSC_HAVE_HIP)
175847d993e7Ssuyashtn   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatConvert_seqdense_seqdensehip_C", NULL));
175947d993e7Ssuyashtn   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatProductSetFromOptions_seqdensehip_seqdensehip_C", NULL));
176047d993e7Ssuyashtn   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatProductSetFromOptions_seqdensehip_seqdense_C", NULL));
176147d993e7Ssuyashtn   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatProductSetFromOptions_seqdense_seqdensehip_C", NULL));
176247d993e7Ssuyashtn #endif
17639566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatSeqDenseSetPreallocation_C", NULL));
17649566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatProductSetFromOptions_seqaij_seqdense_C", NULL));
17659566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatProductSetFromOptions_seqdense_seqdense_C", NULL));
17669566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatProductSetFromOptions_seqbaij_seqdense_C", NULL));
17679566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatProductSetFromOptions_seqsbaij_seqdense_C", NULL));
176852c5f739Sprj- 
17699566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatDenseGetColumn_C", NULL));
17709566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatDenseRestoreColumn_C", NULL));
17719566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatDenseGetColumnVec_C", NULL));
17729566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatDenseRestoreColumnVec_C", NULL));
17739566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatDenseGetColumnVecRead_C", NULL));
17749566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatDenseRestoreColumnVecRead_C", NULL));
17759566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatDenseGetColumnVecWrite_C", NULL));
17769566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatDenseRestoreColumnVecWrite_C", NULL));
17779566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatDenseGetSubMatrix_C", NULL));
17789566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatDenseRestoreSubMatrix_C", NULL));
1779*0be0d8bdSHansol Suh   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatMultAddColumnRange_C", NULL));
1780*0be0d8bdSHansol Suh   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatMultHermitianTransposeColumnRange_C", NULL));
1781*0be0d8bdSHansol Suh   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatMultHermitianTransposeAddColumnRange_C", NULL));
17823ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1783289bc588SBarry Smith }
1784289bc588SBarry Smith 
1785d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatTranspose_SeqDense(Mat A, MatReuse reuse, Mat *matout)
1786d71ae5a4SJacob Faibussowitsch {
1787c0bbcb79SLois Curfman McInnes   Mat_SeqDense *mat = (Mat_SeqDense *)A->data;
17886536e3caSStefano Zampini   PetscInt      k, j, m = A->rmap->n, M = mat->lda, n = A->cmap->n;
178987828ca2SBarry Smith   PetscScalar  *v, tmp;
179048b35521SBarry Smith 
17913a40ed3dSBarry Smith   PetscFunctionBegin;
17927fb60732SBarry Smith   if (reuse == MAT_REUSE_MATRIX) PetscCall(MatTransposeCheckNonzeroState_Private(A, *matout));
17936536e3caSStefano Zampini   if (reuse == MAT_INPLACE_MATRIX) {
17946536e3caSStefano Zampini     if (m == n) { /* in place transpose */
17959566063dSJacob Faibussowitsch       PetscCall(MatDenseGetArray(A, &v));
1796d3e5ee88SLois Curfman McInnes       for (j = 0; j < m; j++) {
1797289bc588SBarry Smith         for (k = 0; k < j; k++) {
17981b807ce4Svictorle           tmp          = v[j + k * M];
17991b807ce4Svictorle           v[j + k * M] = v[k + j * M];
18001b807ce4Svictorle           v[k + j * M] = tmp;
1801289bc588SBarry Smith         }
1802289bc588SBarry Smith       }
18039566063dSJacob Faibussowitsch       PetscCall(MatDenseRestoreArray(A, &v));
18046536e3caSStefano Zampini     } else { /* reuse memory, temporary allocates new memory */
18056536e3caSStefano Zampini       PetscScalar *v2;
18066536e3caSStefano Zampini       PetscLayout  tmplayout;
18076536e3caSStefano Zampini 
18089566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1((size_t)m * n, &v2));
18099566063dSJacob Faibussowitsch       PetscCall(MatDenseGetArray(A, &v));
18106536e3caSStefano Zampini       for (j = 0; j < n; j++) {
18116536e3caSStefano Zampini         for (k = 0; k < m; k++) v2[j + (size_t)k * n] = v[k + (size_t)j * M];
18126536e3caSStefano Zampini       }
18139566063dSJacob Faibussowitsch       PetscCall(PetscArraycpy(v, v2, (size_t)m * n));
18149566063dSJacob Faibussowitsch       PetscCall(PetscFree(v2));
18159566063dSJacob Faibussowitsch       PetscCall(MatDenseRestoreArray(A, &v));
18166536e3caSStefano Zampini       /* cleanup size dependent quantities */
18179566063dSJacob Faibussowitsch       PetscCall(VecDestroy(&mat->cvec));
18189566063dSJacob Faibussowitsch       PetscCall(MatDestroy(&mat->cmat));
18199566063dSJacob Faibussowitsch       PetscCall(PetscFree(mat->pivots));
18209566063dSJacob Faibussowitsch       PetscCall(PetscFree(mat->fwork));
18216536e3caSStefano Zampini       /* swap row/col layouts */
18226536e3caSStefano Zampini       mat->lda  = n;
18236536e3caSStefano Zampini       tmplayout = A->rmap;
18246536e3caSStefano Zampini       A->rmap   = A->cmap;
18256536e3caSStefano Zampini       A->cmap   = tmplayout;
18266536e3caSStefano Zampini     }
18273a40ed3dSBarry Smith   } else { /* out-of-place transpose */
1828d3e5ee88SLois Curfman McInnes     Mat           tmat;
1829ec8511deSBarry Smith     Mat_SeqDense *tmatd;
183087828ca2SBarry Smith     PetscScalar  *v2;
1831af36a384SStefano Zampini     PetscInt      M2;
1832ea709b57SSatish Balay 
18336536e3caSStefano Zampini     if (reuse == MAT_INITIAL_MATRIX) {
18349566063dSJacob Faibussowitsch       PetscCall(MatCreate(PetscObjectComm((PetscObject)A), &tmat));
18359566063dSJacob Faibussowitsch       PetscCall(MatSetSizes(tmat, A->cmap->n, A->rmap->n, A->cmap->n, A->rmap->n));
18369566063dSJacob Faibussowitsch       PetscCall(MatSetType(tmat, ((PetscObject)A)->type_name));
18379566063dSJacob Faibussowitsch       PetscCall(MatSeqDenseSetPreallocation(tmat, NULL));
1838ca15aa20SStefano Zampini     } else tmat = *matout;
1839ca15aa20SStefano Zampini 
18409566063dSJacob Faibussowitsch     PetscCall(MatDenseGetArrayRead(A, (const PetscScalar **)&v));
18419566063dSJacob Faibussowitsch     PetscCall(MatDenseGetArray(tmat, &v2));
1842ec8511deSBarry Smith     tmatd = (Mat_SeqDense *)tmat->data;
1843ca15aa20SStefano Zampini     M2    = tmatd->lda;
1844d3e5ee88SLois Curfman McInnes     for (j = 0; j < n; j++) {
1845af36a384SStefano Zampini       for (k = 0; k < m; k++) v2[j + k * M2] = v[k + j * M];
1846d3e5ee88SLois Curfman McInnes     }
18479566063dSJacob Faibussowitsch     PetscCall(MatDenseRestoreArray(tmat, &v2));
18489566063dSJacob Faibussowitsch     PetscCall(MatDenseRestoreArrayRead(A, (const PetscScalar **)&v));
18499566063dSJacob Faibussowitsch     PetscCall(MatAssemblyBegin(tmat, MAT_FINAL_ASSEMBLY));
18509566063dSJacob Faibussowitsch     PetscCall(MatAssemblyEnd(tmat, MAT_FINAL_ASSEMBLY));
18516536e3caSStefano Zampini     *matout = tmat;
185248b35521SBarry Smith   }
18533ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1854289bc588SBarry Smith }
1855289bc588SBarry Smith 
1856d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatEqual_SeqDense(Mat A1, Mat A2, PetscBool *flg)
1857d71ae5a4SJacob Faibussowitsch {
1858c0bbcb79SLois Curfman McInnes   Mat_SeqDense      *mat1 = (Mat_SeqDense *)A1->data;
1859c0bbcb79SLois Curfman McInnes   Mat_SeqDense      *mat2 = (Mat_SeqDense *)A2->data;
1860ca15aa20SStefano Zampini   PetscInt           i;
1861ca15aa20SStefano Zampini   const PetscScalar *v1, *v2;
18629ea5d5aeSSatish Balay 
18633a40ed3dSBarry Smith   PetscFunctionBegin;
18649371c9d4SSatish Balay   if (A1->rmap->n != A2->rmap->n) {
18659371c9d4SSatish Balay     *flg = PETSC_FALSE;
18663ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
18679371c9d4SSatish Balay   }
18689371c9d4SSatish Balay   if (A1->cmap->n != A2->cmap->n) {
18699371c9d4SSatish Balay     *flg = PETSC_FALSE;
18703ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
18719371c9d4SSatish Balay   }
18729566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArrayRead(A1, &v1));
18739566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArrayRead(A2, &v2));
1874ca15aa20SStefano Zampini   for (i = 0; i < A1->cmap->n; i++) {
18759566063dSJacob Faibussowitsch     PetscCall(PetscArraycmp(v1, v2, A1->rmap->n, flg));
18763ba16761SJacob Faibussowitsch     if (*flg == PETSC_FALSE) PetscFunctionReturn(PETSC_SUCCESS);
1877ca15aa20SStefano Zampini     v1 += mat1->lda;
1878ca15aa20SStefano Zampini     v2 += mat2->lda;
18791b807ce4Svictorle   }
18809566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArrayRead(A1, &v1));
18819566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArrayRead(A2, &v2));
188277c4ece6SBarry Smith   *flg = PETSC_TRUE;
18833ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1884289bc588SBarry Smith }
1885289bc588SBarry Smith 
188614277c92SJacob Faibussowitsch PetscErrorCode MatGetDiagonal_SeqDense(Mat A, Vec v)
1887d71ae5a4SJacob Faibussowitsch {
1888c0bbcb79SLois Curfman McInnes   Mat_SeqDense      *mat = (Mat_SeqDense *)A->data;
188913f74950SBarry Smith   PetscInt           i, n, len;
1890ca15aa20SStefano Zampini   PetscScalar       *x;
1891ca15aa20SStefano Zampini   const PetscScalar *vv;
189244cd7ae7SLois Curfman McInnes 
18933a40ed3dSBarry Smith   PetscFunctionBegin;
18949566063dSJacob Faibussowitsch   PetscCall(VecGetSize(v, &n));
18959566063dSJacob Faibussowitsch   PetscCall(VecGetArray(v, &x));
1896d0f46423SBarry Smith   len = PetscMin(A->rmap->n, A->cmap->n);
18979566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArrayRead(A, &vv));
189808401ef6SPierre Jolivet   PetscCheck(n == A->rmap->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Nonconforming mat and vec");
1899ad540459SPierre Jolivet   for (i = 0; i < len; i++) x[i] = vv[i * mat->lda + i];
19009566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArrayRead(A, &vv));
19019566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(v, &x));
19023ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1903289bc588SBarry Smith }
1904289bc588SBarry Smith 
1905d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatDiagonalScale_SeqDense(Mat A, Vec ll, Vec rr)
1906d71ae5a4SJacob Faibussowitsch {
1907c0bbcb79SLois Curfman McInnes   Mat_SeqDense      *mat = (Mat_SeqDense *)A->data;
1908f1ceaac6SMatthew G. Knepley   const PetscScalar *l, *r;
1909ca15aa20SStefano Zampini   PetscScalar        x, *v, *vv;
1910d0f46423SBarry Smith   PetscInt           i, j, m = A->rmap->n, n = A->cmap->n;
191155659b69SBarry Smith 
19123a40ed3dSBarry Smith   PetscFunctionBegin;
19139566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArray(A, &vv));
191428988994SBarry Smith   if (ll) {
19159566063dSJacob Faibussowitsch     PetscCall(VecGetSize(ll, &m));
19169566063dSJacob Faibussowitsch     PetscCall(VecGetArrayRead(ll, &l));
191708401ef6SPierre Jolivet     PetscCheck(m == A->rmap->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Left scaling vec wrong size");
1918da3a660dSBarry Smith     for (i = 0; i < m; i++) {
1919da3a660dSBarry Smith       x = l[i];
1920ca15aa20SStefano Zampini       v = vv + i;
19219371c9d4SSatish Balay       for (j = 0; j < n; j++) {
19229371c9d4SSatish Balay         (*v) *= x;
19239371c9d4SSatish Balay         v += mat->lda;
19249371c9d4SSatish Balay       }
1925da3a660dSBarry Smith     }
19269566063dSJacob Faibussowitsch     PetscCall(VecRestoreArrayRead(ll, &l));
19279566063dSJacob Faibussowitsch     PetscCall(PetscLogFlops(1.0 * n * m));
1928da3a660dSBarry Smith   }
192928988994SBarry Smith   if (rr) {
19309566063dSJacob Faibussowitsch     PetscCall(VecGetSize(rr, &n));
19319566063dSJacob Faibussowitsch     PetscCall(VecGetArrayRead(rr, &r));
193208401ef6SPierre Jolivet     PetscCheck(n == A->cmap->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Right scaling vec wrong size");
1933da3a660dSBarry Smith     for (i = 0; i < n; i++) {
1934da3a660dSBarry Smith       x = r[i];
1935ca15aa20SStefano Zampini       v = vv + i * mat->lda;
19362205254eSKarl Rupp       for (j = 0; j < m; j++) (*v++) *= x;
1937da3a660dSBarry Smith     }
19389566063dSJacob Faibussowitsch     PetscCall(VecRestoreArrayRead(rr, &r));
19399566063dSJacob Faibussowitsch     PetscCall(PetscLogFlops(1.0 * n * m));
1940da3a660dSBarry Smith   }
19419566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArray(A, &vv));
19423ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1943289bc588SBarry Smith }
1944289bc588SBarry Smith 
1945d71ae5a4SJacob Faibussowitsch PetscErrorCode MatNorm_SeqDense(Mat A, NormType type, PetscReal *nrm)
1946d71ae5a4SJacob Faibussowitsch {
1947c0bbcb79SLois Curfman McInnes   Mat_SeqDense *mat = (Mat_SeqDense *)A->data;
1948ca15aa20SStefano Zampini   PetscScalar  *v, *vv;
1949329f5518SBarry Smith   PetscReal     sum = 0.0;
195075f6d85dSStefano Zampini   PetscInt      lda, m = A->rmap->n, i, j;
195155659b69SBarry Smith 
19523a40ed3dSBarry Smith   PetscFunctionBegin;
19539566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArrayRead(A, (const PetscScalar **)&vv));
19549566063dSJacob Faibussowitsch   PetscCall(MatDenseGetLDA(A, &lda));
1955ca15aa20SStefano Zampini   v = vv;
1956289bc588SBarry Smith   if (type == NORM_FROBENIUS) {
1957a5ce6ee0Svictorle     if (lda > m) {
1958d0f46423SBarry Smith       for (j = 0; j < A->cmap->n; j++) {
1959ca15aa20SStefano Zampini         v = vv + j * lda;
1960a5ce6ee0Svictorle         for (i = 0; i < m; i++) {
19619371c9d4SSatish Balay           sum += PetscRealPart(PetscConj(*v) * (*v));
19629371c9d4SSatish Balay           v++;
1963a5ce6ee0Svictorle         }
1964a5ce6ee0Svictorle       }
1965a5ce6ee0Svictorle     } else {
1966570b7f6dSBarry Smith #if defined(PETSC_USE_REAL___FP16)
1967570b7f6dSBarry Smith       PetscBLASInt one = 1, cnt = A->cmap->n * A->rmap->n;
1968792fecdfSBarry Smith       PetscCallBLAS("BLASnrm2", *nrm = BLASnrm2_(&cnt, v, &one));
1969570b7f6dSBarry Smith     }
1970570b7f6dSBarry Smith #else
1971d0f46423SBarry Smith       for (i = 0; i < A->cmap->n * A->rmap->n; i++) {
19729371c9d4SSatish Balay         sum += PetscRealPart(PetscConj(*v) * (*v));
19739371c9d4SSatish Balay         v++;
1974289bc588SBarry Smith       }
1975a5ce6ee0Svictorle     }
19768f1a2a5eSBarry Smith     *nrm = PetscSqrtReal(sum);
1977570b7f6dSBarry Smith #endif
19789566063dSJacob Faibussowitsch     PetscCall(PetscLogFlops(2.0 * A->cmap->n * A->rmap->n));
19793a40ed3dSBarry Smith   } else if (type == NORM_1) {
1980064f8208SBarry Smith     *nrm = 0.0;
1981d0f46423SBarry Smith     for (j = 0; j < A->cmap->n; j++) {
1982ca15aa20SStefano Zampini       v   = vv + j * mat->lda;
1983289bc588SBarry Smith       sum = 0.0;
1984d0f46423SBarry Smith       for (i = 0; i < A->rmap->n; i++) {
19859371c9d4SSatish Balay         sum += PetscAbsScalar(*v);
19869371c9d4SSatish Balay         v++;
1987289bc588SBarry Smith       }
1988064f8208SBarry Smith       if (sum > *nrm) *nrm = sum;
1989289bc588SBarry Smith     }
19909566063dSJacob Faibussowitsch     PetscCall(PetscLogFlops(1.0 * A->cmap->n * A->rmap->n));
19913a40ed3dSBarry Smith   } else if (type == NORM_INFINITY) {
1992064f8208SBarry Smith     *nrm = 0.0;
1993d0f46423SBarry Smith     for (j = 0; j < A->rmap->n; j++) {
1994ca15aa20SStefano Zampini       v   = vv + j;
1995289bc588SBarry Smith       sum = 0.0;
1996d0f46423SBarry Smith       for (i = 0; i < A->cmap->n; i++) {
19979371c9d4SSatish Balay         sum += PetscAbsScalar(*v);
19989371c9d4SSatish Balay         v += mat->lda;
1999289bc588SBarry Smith       }
2000064f8208SBarry Smith       if (sum > *nrm) *nrm = sum;
2001289bc588SBarry Smith     }
20029566063dSJacob Faibussowitsch     PetscCall(PetscLogFlops(1.0 * A->cmap->n * A->rmap->n));
2003e7e72b3dSBarry Smith   } else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "No two norm");
20049566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArrayRead(A, (const PetscScalar **)&vv));
20053ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2006289bc588SBarry Smith }
2007289bc588SBarry Smith 
2008d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatSetOption_SeqDense(Mat A, MatOption op, PetscBool flg)
2009d71ae5a4SJacob Faibussowitsch {
2010c0bbcb79SLois Curfman McInnes   Mat_SeqDense *aij = (Mat_SeqDense *)A->data;
201167e560aaSBarry Smith 
20123a40ed3dSBarry Smith   PetscFunctionBegin;
2013b5a2b587SKris Buschelman   switch (op) {
2014d71ae5a4SJacob Faibussowitsch   case MAT_ROW_ORIENTED:
2015d71ae5a4SJacob Faibussowitsch     aij->roworiented = flg;
2016d71ae5a4SJacob Faibussowitsch     break;
2017512a5fc5SBarry Smith   case MAT_NEW_NONZERO_LOCATIONS:
2018b5a2b587SKris Buschelman   case MAT_NEW_NONZERO_LOCATION_ERR:
20193971808eSMatthew Knepley   case MAT_NEW_NONZERO_ALLOCATION_ERR:
20208c78258cSHong Zhang   case MAT_FORCE_DIAGONAL_ENTRIES:
202113fa8e87SLisandro Dalcin   case MAT_KEEP_NONZERO_PATTERN:
2022b5a2b587SKris Buschelman   case MAT_IGNORE_OFF_PROC_ENTRIES:
2023b5a2b587SKris Buschelman   case MAT_USE_HASH_TABLE:
20240f8fb01aSBarry Smith   case MAT_IGNORE_ZERO_ENTRIES:
20255021d80fSJed Brown   case MAT_IGNORE_LOWER_TRIANGULAR:
2026d71ae5a4SJacob Faibussowitsch   case MAT_SORTED_FULL:
2027d71ae5a4SJacob Faibussowitsch     PetscCall(PetscInfo(A, "Option %s ignored\n", MatOptions[op]));
2028d71ae5a4SJacob Faibussowitsch     break;
20295021d80fSJed Brown   case MAT_SPD:
203077e54ba9SKris Buschelman   case MAT_SYMMETRIC:
203177e54ba9SKris Buschelman   case MAT_STRUCTURALLY_SYMMETRIC:
20329a4540c5SBarry Smith   case MAT_HERMITIAN:
20339a4540c5SBarry Smith   case MAT_SYMMETRY_ETERNAL:
2034b94d7dedSBarry Smith   case MAT_STRUCTURAL_SYMMETRY_ETERNAL:
2035d71ae5a4SJacob Faibussowitsch   case MAT_SPD_ETERNAL:
2036d71ae5a4SJacob Faibussowitsch     break;
2037d71ae5a4SJacob Faibussowitsch   default:
2038d71ae5a4SJacob Faibussowitsch     SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "unknown option %s", MatOptions[op]);
20393a40ed3dSBarry Smith   }
20403ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2041289bc588SBarry Smith }
2042289bc588SBarry Smith 
2043d71ae5a4SJacob Faibussowitsch PetscErrorCode MatZeroEntries_SeqDense(Mat A)
2044d71ae5a4SJacob Faibussowitsch {
2045ec8511deSBarry Smith   Mat_SeqDense *l   = (Mat_SeqDense *)A->data;
20463d8925e7SStefano Zampini   PetscInt      lda = l->lda, m = A->rmap->n, n = A->cmap->n, j;
2047ca15aa20SStefano Zampini   PetscScalar  *v;
20483a40ed3dSBarry Smith 
20493a40ed3dSBarry Smith   PetscFunctionBegin;
20509566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArrayWrite(A, &v));
2051a5ce6ee0Svictorle   if (lda > m) {
205248a46eb9SPierre Jolivet     for (j = 0; j < n; j++) PetscCall(PetscArrayzero(v + j * lda, m));
2053a5ce6ee0Svictorle   } else {
20549566063dSJacob Faibussowitsch     PetscCall(PetscArrayzero(v, PetscInt64Mult(m, n)));
2055a5ce6ee0Svictorle   }
20569566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArrayWrite(A, &v));
20573ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
20586f0a148fSBarry Smith }
20596f0a148fSBarry Smith 
2060d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatZeroRows_SeqDense(Mat A, PetscInt N, const PetscInt rows[], PetscScalar diag, Vec x, Vec b)
2061d71ae5a4SJacob Faibussowitsch {
2062ec8511deSBarry Smith   Mat_SeqDense      *l = (Mat_SeqDense *)A->data;
2063b9679d65SBarry Smith   PetscInt           m = l->lda, n = A->cmap->n, i, j;
2064ca15aa20SStefano Zampini   PetscScalar       *slot, *bb, *v;
206597b48c8fSBarry Smith   const PetscScalar *xx;
206655659b69SBarry Smith 
20673a40ed3dSBarry Smith   PetscFunctionBegin;
206876bd3646SJed Brown   if (PetscDefined(USE_DEBUG)) {
2069b9679d65SBarry Smith     for (i = 0; i < N; i++) {
207008401ef6SPierre Jolivet       PetscCheck(rows[i] >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Negative row requested to be zeroed");
207108401ef6SPierre 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);
2072b9679d65SBarry Smith     }
207376bd3646SJed Brown   }
20743ba16761SJacob Faibussowitsch   if (!N) PetscFunctionReturn(PETSC_SUCCESS);
2075b9679d65SBarry Smith 
2076dd8e379bSPierre Jolivet   /* fix right-hand side if needed */
207797b48c8fSBarry Smith   if (x && b) {
20789566063dSJacob Faibussowitsch     PetscCall(VecGetArrayRead(x, &xx));
20799566063dSJacob Faibussowitsch     PetscCall(VecGetArray(b, &bb));
20802205254eSKarl Rupp     for (i = 0; i < N; i++) bb[rows[i]] = diag * xx[rows[i]];
20819566063dSJacob Faibussowitsch     PetscCall(VecRestoreArrayRead(x, &xx));
20829566063dSJacob Faibussowitsch     PetscCall(VecRestoreArray(b, &bb));
208397b48c8fSBarry Smith   }
208497b48c8fSBarry Smith 
20859566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArray(A, &v));
20866f0a148fSBarry Smith   for (i = 0; i < N; i++) {
2087ca15aa20SStefano Zampini     slot = v + rows[i];
20889371c9d4SSatish Balay     for (j = 0; j < n; j++) {
20899371c9d4SSatish Balay       *slot = 0.0;
20909371c9d4SSatish Balay       slot += m;
20919371c9d4SSatish Balay     }
20926f0a148fSBarry Smith   }
2093f4df32b1SMatthew Knepley   if (diag != 0.0) {
209408401ef6SPierre Jolivet     PetscCheck(A->rmap->n == A->cmap->n, PETSC_COMM_SELF, PETSC_ERR_SUP, "Only coded for square matrices");
20956f0a148fSBarry Smith     for (i = 0; i < N; i++) {
2096ca15aa20SStefano Zampini       slot  = v + (m + 1) * rows[i];
2097f4df32b1SMatthew Knepley       *slot = diag;
20986f0a148fSBarry Smith     }
20996f0a148fSBarry Smith   }
21009566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArray(A, &v));
21013ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
21026f0a148fSBarry Smith }
2103557bce09SLois Curfman McInnes 
2104d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatDenseGetLDA_SeqDense(Mat A, PetscInt *lda)
2105d71ae5a4SJacob Faibussowitsch {
210649a6ff4bSBarry Smith   Mat_SeqDense *mat = (Mat_SeqDense *)A->data;
210749a6ff4bSBarry Smith 
210849a6ff4bSBarry Smith   PetscFunctionBegin;
210949a6ff4bSBarry Smith   *lda = mat->lda;
21103ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
211149a6ff4bSBarry Smith }
211249a6ff4bSBarry Smith 
2113d71ae5a4SJacob Faibussowitsch PetscErrorCode MatDenseGetArray_SeqDense(Mat A, PetscScalar **array)
2114d71ae5a4SJacob Faibussowitsch {
2115c0bbcb79SLois Curfman McInnes   Mat_SeqDense *mat = (Mat_SeqDense *)A->data;
21163a40ed3dSBarry Smith 
21173a40ed3dSBarry Smith   PetscFunctionBegin;
211828b400f6SJacob Faibussowitsch   PetscCheck(!mat->matinuse, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Need to call MatDenseRestoreSubMatrix() first");
211964e87e97SBarry Smith   *array = mat->v;
21203ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
212164e87e97SBarry Smith }
21220754003eSLois Curfman McInnes 
2123d71ae5a4SJacob Faibussowitsch PetscErrorCode MatDenseRestoreArray_SeqDense(Mat A, PetscScalar **array)
2124d71ae5a4SJacob Faibussowitsch {
21253a40ed3dSBarry Smith   PetscFunctionBegin;
212675f6d85dSStefano Zampini   if (array) *array = NULL;
21273ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2128ff14e315SSatish Balay }
21290754003eSLois Curfman McInnes 
21300f74d2c1SSatish Balay /*@
213111a5261eSBarry Smith   MatDenseGetLDA - gets the leading dimension of the array returned from `MatDenseGetArray()`
213249a6ff4bSBarry Smith 
21332ef1f0ffSBarry Smith   Not Collective
213449a6ff4bSBarry Smith 
213549a6ff4bSBarry Smith   Input Parameter:
2136fe59aa6dSJacob Faibussowitsch . A - a `MATDENSE` or `MATDENSECUDA` matrix
213749a6ff4bSBarry Smith 
213849a6ff4bSBarry Smith   Output Parameter:
213949a6ff4bSBarry Smith . lda - the leading dimension
214049a6ff4bSBarry Smith 
214149a6ff4bSBarry Smith   Level: intermediate
214249a6ff4bSBarry Smith 
21431cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATDENSE`, `MATDENSECUDA`, `MatDenseGetArray()`, `MatDenseRestoreArray()`, `MatDenseGetArrayRead()`, `MatDenseRestoreArrayRead()`, `MatDenseSetLDA()`
214449a6ff4bSBarry Smith @*/
2145d71ae5a4SJacob Faibussowitsch PetscErrorCode MatDenseGetLDA(Mat A, PetscInt *lda)
2146d71ae5a4SJacob Faibussowitsch {
214749a6ff4bSBarry Smith   PetscFunctionBegin;
2148d5ea218eSStefano Zampini   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
21494f572ea9SToby Isaac   PetscAssertPointer(lda, 2);
215075f6d85dSStefano Zampini   MatCheckPreallocated(A, 1);
2151cac4c232SBarry Smith   PetscUseMethod(A, "MatDenseGetLDA_C", (Mat, PetscInt *), (A, lda));
21523ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
215349a6ff4bSBarry Smith }
215449a6ff4bSBarry Smith 
21550f74d2c1SSatish Balay /*@
215611a5261eSBarry Smith   MatDenseSetLDA - Sets the leading dimension of the array used by the `MATDENSE` matrix
2157ad16ce7aSStefano Zampini 
21582323109cSBarry Smith   Collective if the matrix layouts have not yet been setup
2159ad16ce7aSStefano Zampini 
2160d8d19677SJose E. Roman   Input Parameters:
2161fe59aa6dSJacob Faibussowitsch + A   - a `MATDENSE` or `MATDENSECUDA` matrix
2162ad16ce7aSStefano Zampini - lda - the leading dimension
2163ad16ce7aSStefano Zampini 
2164ad16ce7aSStefano Zampini   Level: intermediate
2165ad16ce7aSStefano Zampini 
21661cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATDENSE`, `MATDENSECUDA`, `MatDenseGetArray()`, `MatDenseRestoreArray()`, `MatDenseGetArrayRead()`, `MatDenseRestoreArrayRead()`, `MatDenseGetLDA()`
2167ad16ce7aSStefano Zampini @*/
2168d71ae5a4SJacob Faibussowitsch PetscErrorCode MatDenseSetLDA(Mat A, PetscInt lda)
2169d71ae5a4SJacob Faibussowitsch {
2170ad16ce7aSStefano Zampini   PetscFunctionBegin;
2171ad16ce7aSStefano Zampini   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
2172cac4c232SBarry Smith   PetscTryMethod(A, "MatDenseSetLDA_C", (Mat, PetscInt), (A, lda));
21733ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2174ad16ce7aSStefano Zampini }
2175ad16ce7aSStefano Zampini 
2176ad16ce7aSStefano Zampini /*@C
217711a5261eSBarry Smith   MatDenseGetArray - gives read-write access to the array where the data for a `MATDENSE` matrix is stored
217873a71a0fSBarry Smith 
2179c3339decSBarry Smith   Logically Collective
218073a71a0fSBarry Smith 
218173a71a0fSBarry Smith   Input Parameter:
2182fe59aa6dSJacob Faibussowitsch . A - a dense matrix
218373a71a0fSBarry Smith 
218473a71a0fSBarry Smith   Output Parameter:
218573a71a0fSBarry Smith . array - pointer to the data
218673a71a0fSBarry Smith 
218773a71a0fSBarry Smith   Level: intermediate
218873a71a0fSBarry Smith 
2189fe59aa6dSJacob Faibussowitsch   Fortran Notes:
21900ab4885dSBarry Smith   `MatDenseGetArray()` Fortran binding is deprecated (since PETSc 3.19), use `MatDenseGetArrayF90()`
21910ab4885dSBarry Smith 
21921cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATDENSE`, `MatDenseRestoreArray()`, `MatDenseGetArrayRead()`, `MatDenseRestoreArrayRead()`, `MatDenseGetArrayWrite()`, `MatDenseRestoreArrayWrite()`
219373a71a0fSBarry Smith @*/
2194d71ae5a4SJacob Faibussowitsch PetscErrorCode MatDenseGetArray(Mat A, PetscScalar **array)
2195d71ae5a4SJacob Faibussowitsch {
219673a71a0fSBarry Smith   PetscFunctionBegin;
2197d5ea218eSStefano Zampini   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
21984f572ea9SToby Isaac   PetscAssertPointer(array, 2);
2199cac4c232SBarry Smith   PetscUseMethod(A, "MatDenseGetArray_C", (Mat, PetscScalar **), (A, array));
22003ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
220173a71a0fSBarry Smith }
220273a71a0fSBarry Smith 
2203dec5eb66SMatthew G Knepley /*@C
220411a5261eSBarry Smith   MatDenseRestoreArray - returns access to the array where the data for a `MATDENSE` matrix is stored obtained by `MatDenseGetArray()`
220573a71a0fSBarry Smith 
2206c3339decSBarry Smith   Logically Collective
22078572280aSBarry Smith 
22088572280aSBarry Smith   Input Parameters:
2209fe59aa6dSJacob Faibussowitsch + A     - a dense matrix
22102ef1f0ffSBarry Smith - array - pointer to the data (may be `NULL`)
22118572280aSBarry Smith 
22128572280aSBarry Smith   Level: intermediate
22138572280aSBarry Smith 
2214fe59aa6dSJacob Faibussowitsch   Fortran Notes:
22150ab4885dSBarry Smith   `MatDenseRestoreArray()` Fortran binding is deprecated (since PETSc 3.19), use `MatDenseRestoreArrayF90()`
22160ab4885dSBarry Smith 
22171cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATDENSE`, `MatDenseGetArray()`, `MatDenseGetArrayRead()`, `MatDenseRestoreArrayRead()`, `MatDenseGetArrayWrite()`, `MatDenseRestoreArrayWrite()`
22188572280aSBarry Smith @*/
2219d71ae5a4SJacob Faibussowitsch PetscErrorCode MatDenseRestoreArray(Mat A, PetscScalar **array)
2220d71ae5a4SJacob Faibussowitsch {
22218572280aSBarry Smith   PetscFunctionBegin;
2222d5ea218eSStefano Zampini   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
22234f572ea9SToby Isaac   if (array) PetscAssertPointer(array, 2);
2224cac4c232SBarry Smith   PetscUseMethod(A, "MatDenseRestoreArray_C", (Mat, PetscScalar **), (A, array));
22259566063dSJacob Faibussowitsch   PetscCall(PetscObjectStateIncrease((PetscObject)A));
222647d993e7Ssuyashtn #if defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
2227637a0070SStefano Zampini   A->offloadmask = PETSC_OFFLOAD_CPU;
2228637a0070SStefano Zampini #endif
22293ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
22308572280aSBarry Smith }
22318572280aSBarry Smith 
22328572280aSBarry Smith /*@C
223311a5261eSBarry Smith   MatDenseGetArrayRead - gives read-only access to the array where the data for a `MATDENSE` matrix is stored
22348572280aSBarry Smith 
2235fb850c59SBarry Smith   Not Collective
22368572280aSBarry Smith 
22378572280aSBarry Smith   Input Parameter:
2238fe59aa6dSJacob Faibussowitsch . A - a dense matrix
22398572280aSBarry Smith 
22408572280aSBarry Smith   Output Parameter:
22418572280aSBarry Smith . array - pointer to the data
22428572280aSBarry Smith 
22438572280aSBarry Smith   Level: intermediate
22448572280aSBarry Smith 
22451cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATDENSE`, `MatDenseRestoreArrayRead()`, `MatDenseGetArray()`, `MatDenseRestoreArray()`, `MatDenseGetArrayWrite()`, `MatDenseRestoreArrayWrite()`
22468572280aSBarry Smith @*/
2247d71ae5a4SJacob Faibussowitsch PetscErrorCode MatDenseGetArrayRead(Mat A, const PetscScalar **array)
2248d71ae5a4SJacob Faibussowitsch {
22498572280aSBarry Smith   PetscFunctionBegin;
2250d5ea218eSStefano Zampini   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
22514f572ea9SToby Isaac   PetscAssertPointer(array, 2);
22525c0db29aSPierre Jolivet   PetscUseMethod(A, "MatDenseGetArrayRead_C", (Mat, PetscScalar **), (A, (PetscScalar **)array));
22533ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
22548572280aSBarry Smith }
22558572280aSBarry Smith 
22568572280aSBarry Smith /*@C
225711a5261eSBarry Smith   MatDenseRestoreArrayRead - returns access to the array where the data for a `MATDENSE` matrix is stored obtained by `MatDenseGetArrayRead()`
22588572280aSBarry Smith 
2259fb850c59SBarry Smith   Not Collective
226073a71a0fSBarry Smith 
226173a71a0fSBarry Smith   Input Parameters:
2262fe59aa6dSJacob Faibussowitsch + A     - a dense matrix
22632ef1f0ffSBarry Smith - array - pointer to the data (may be `NULL`)
226473a71a0fSBarry Smith 
226573a71a0fSBarry Smith   Level: intermediate
226673a71a0fSBarry Smith 
22671cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATDENSE`, `MatDenseGetArrayRead()`, `MatDenseGetArray()`, `MatDenseRestoreArray()`, `MatDenseGetArrayWrite()`, `MatDenseRestoreArrayWrite()`
226873a71a0fSBarry Smith @*/
2269d71ae5a4SJacob Faibussowitsch PetscErrorCode MatDenseRestoreArrayRead(Mat A, const PetscScalar **array)
2270d71ae5a4SJacob Faibussowitsch {
227173a71a0fSBarry Smith   PetscFunctionBegin;
2272d5ea218eSStefano Zampini   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
22734f572ea9SToby Isaac   if (array) PetscAssertPointer(array, 2);
22745c0db29aSPierre Jolivet   PetscUseMethod(A, "MatDenseRestoreArrayRead_C", (Mat, PetscScalar **), (A, (PetscScalar **)array));
22753ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
227673a71a0fSBarry Smith }
227773a71a0fSBarry Smith 
22786947451fSStefano Zampini /*@C
227911a5261eSBarry Smith   MatDenseGetArrayWrite - gives write-only access to the array where the data for a `MATDENSE` matrix is stored
22806947451fSStefano Zampini 
2281fb850c59SBarry Smith   Not Collective
22826947451fSStefano Zampini 
22836947451fSStefano Zampini   Input Parameter:
2284fe59aa6dSJacob Faibussowitsch . A - a dense matrix
22856947451fSStefano Zampini 
22866947451fSStefano Zampini   Output Parameter:
22876947451fSStefano Zampini . array - pointer to the data
22886947451fSStefano Zampini 
22896947451fSStefano Zampini   Level: intermediate
22906947451fSStefano Zampini 
22911cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATDENSE`, `MatDenseRestoreArrayWrite()`, `MatDenseGetArray()`, `MatDenseRestoreArray()`, `MatDenseGetArrayRead()`, `MatDenseRestoreArrayRead()`
22926947451fSStefano Zampini @*/
2293d71ae5a4SJacob Faibussowitsch PetscErrorCode MatDenseGetArrayWrite(Mat A, PetscScalar **array)
2294d71ae5a4SJacob Faibussowitsch {
22956947451fSStefano Zampini   PetscFunctionBegin;
2296d5ea218eSStefano Zampini   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
22974f572ea9SToby Isaac   PetscAssertPointer(array, 2);
2298cac4c232SBarry Smith   PetscUseMethod(A, "MatDenseGetArrayWrite_C", (Mat, PetscScalar **), (A, array));
22993ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
23006947451fSStefano Zampini }
23016947451fSStefano Zampini 
23026947451fSStefano Zampini /*@C
230311a5261eSBarry Smith   MatDenseRestoreArrayWrite - returns access to the array where the data for a `MATDENSE` matrix is stored obtained by `MatDenseGetArrayWrite()`
23046947451fSStefano Zampini 
2305fb850c59SBarry Smith   Not Collective
23066947451fSStefano Zampini 
23076947451fSStefano Zampini   Input Parameters:
2308fe59aa6dSJacob Faibussowitsch + A     - a dense matrix
23092ef1f0ffSBarry Smith - array - pointer to the data (may be `NULL`)
23106947451fSStefano Zampini 
23116947451fSStefano Zampini   Level: intermediate
23126947451fSStefano Zampini 
23131cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATDENSE`, `MatDenseGetArrayWrite()`, `MatDenseGetArray()`, `MatDenseRestoreArray()`, `MatDenseGetArrayRead()`, `MatDenseRestoreArrayRead()`
23146947451fSStefano Zampini @*/
2315d71ae5a4SJacob Faibussowitsch PetscErrorCode MatDenseRestoreArrayWrite(Mat A, PetscScalar **array)
2316d71ae5a4SJacob Faibussowitsch {
23176947451fSStefano Zampini   PetscFunctionBegin;
2318d5ea218eSStefano Zampini   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
23194f572ea9SToby Isaac   if (array) PetscAssertPointer(array, 2);
2320cac4c232SBarry Smith   PetscUseMethod(A, "MatDenseRestoreArrayWrite_C", (Mat, PetscScalar **), (A, array));
23219566063dSJacob Faibussowitsch   PetscCall(PetscObjectStateIncrease((PetscObject)A));
232247d993e7Ssuyashtn #if defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
23236947451fSStefano Zampini   A->offloadmask = PETSC_OFFLOAD_CPU;
23246947451fSStefano Zampini #endif
23253ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
23266947451fSStefano Zampini }
23276947451fSStefano Zampini 
2328cd3f9d89SJunchao Zhang /*@C
2329cd3f9d89SJunchao Zhang   MatDenseGetArrayAndMemType - gives read-write access to the array where the data for a `MATDENSE` matrix is stored
2330cd3f9d89SJunchao Zhang 
2331cd3f9d89SJunchao Zhang   Logically Collective
2332cd3f9d89SJunchao Zhang 
2333cd3f9d89SJunchao Zhang   Input Parameter:
2334fe59aa6dSJacob Faibussowitsch . A - a dense matrix
2335cd3f9d89SJunchao Zhang 
2336cd3f9d89SJunchao Zhang   Output Parameters:
2337cd3f9d89SJunchao Zhang + array - pointer to the data
2338cd3f9d89SJunchao Zhang - mtype - memory type of the returned pointer
2339cd3f9d89SJunchao Zhang 
2340cd3f9d89SJunchao Zhang   Level: intermediate
2341cd3f9d89SJunchao Zhang 
2342fb850c59SBarry Smith   Note:
23432ef1f0ffSBarry Smith   If the matrix is of a device type such as `MATDENSECUDA`, `MATDENSEHIP`, etc.,
23442ef1f0ffSBarry Smith   an array on device is always returned and is guaranteed to contain the matrix's latest data.
23452ef1f0ffSBarry Smith 
23461cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATDENSE`, `MatDenseRestoreArrayAndMemType()`, `MatDenseGetArrayReadAndMemType()`, `MatDenseGetArrayWriteAndMemType()`, `MatDenseGetArrayRead()`,
2347cd3f9d89SJunchao Zhang    `MatDenseRestoreArrayRead()`, `MatDenseGetArrayWrite()`, `MatDenseRestoreArrayWrite()`, `MatSeqAIJGetCSRAndMemType()`
2348cd3f9d89SJunchao Zhang @*/
2349cd3f9d89SJunchao Zhang PetscErrorCode MatDenseGetArrayAndMemType(Mat A, PetscScalar **array, PetscMemType *mtype)
2350cd3f9d89SJunchao Zhang {
2351cd3f9d89SJunchao Zhang   PetscBool isMPI;
2352cd3f9d89SJunchao Zhang 
2353cd3f9d89SJunchao Zhang   PetscFunctionBegin;
2354cd3f9d89SJunchao Zhang   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
23554f572ea9SToby Isaac   PetscAssertPointer(array, 2);
2356e865de01SJunchao 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 */
2357cd3f9d89SJunchao Zhang   PetscCall(PetscObjectBaseTypeCompare((PetscObject)A, MATMPIDENSE, &isMPI));
2358cd3f9d89SJunchao Zhang   if (isMPI) {
2359cd3f9d89SJunchao Zhang     /* Dispatch here so that the code can be reused for all subclasses of MATDENSE */
2360cd3f9d89SJunchao Zhang     PetscCall(MatDenseGetArrayAndMemType(((Mat_MPIDense *)A->data)->A, array, mtype));
2361cd3f9d89SJunchao Zhang   } else {
2362cd3f9d89SJunchao Zhang     PetscErrorCode (*fptr)(Mat, PetscScalar **, PetscMemType *);
23633ba16761SJacob Faibussowitsch 
23643ba16761SJacob Faibussowitsch     PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatDenseGetArrayAndMemType_C", &fptr));
2365cd3f9d89SJunchao Zhang     if (fptr) {
2366cd3f9d89SJunchao Zhang       PetscCall((*fptr)(A, array, mtype));
2367cd3f9d89SJunchao Zhang     } else {
2368cd3f9d89SJunchao Zhang       PetscUseMethod(A, "MatDenseGetArray_C", (Mat, PetscScalar **), (A, array));
2369cd3f9d89SJunchao Zhang       if (mtype) *mtype = PETSC_MEMTYPE_HOST;
2370cd3f9d89SJunchao Zhang     }
2371cd3f9d89SJunchao Zhang   }
23723ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2373cd3f9d89SJunchao Zhang }
2374cd3f9d89SJunchao Zhang 
2375cd3f9d89SJunchao Zhang /*@C
2376cd3f9d89SJunchao Zhang   MatDenseRestoreArrayAndMemType - returns access to the array that is obtained by `MatDenseGetArrayAndMemType()`
2377cd3f9d89SJunchao Zhang 
2378cd3f9d89SJunchao Zhang   Logically Collective
2379cd3f9d89SJunchao Zhang 
2380cd3f9d89SJunchao Zhang   Input Parameters:
2381fe59aa6dSJacob Faibussowitsch + A     - a dense matrix
2382cd3f9d89SJunchao Zhang - array - pointer to the data
2383cd3f9d89SJunchao Zhang 
2384cd3f9d89SJunchao Zhang   Level: intermediate
2385cd3f9d89SJunchao Zhang 
23861cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATDENSE`, `MatDenseGetArrayAndMemType()`, `MatDenseGetArray()`, `MatDenseGetArrayRead()`, `MatDenseRestoreArrayRead()`, `MatDenseGetArrayWrite()`, `MatDenseRestoreArrayWrite()`
2387cd3f9d89SJunchao Zhang @*/
2388cd3f9d89SJunchao Zhang PetscErrorCode MatDenseRestoreArrayAndMemType(Mat A, PetscScalar **array)
2389cd3f9d89SJunchao Zhang {
2390cd3f9d89SJunchao Zhang   PetscBool isMPI;
2391cd3f9d89SJunchao Zhang 
2392cd3f9d89SJunchao Zhang   PetscFunctionBegin;
2393cd3f9d89SJunchao Zhang   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
23944f572ea9SToby Isaac   PetscAssertPointer(array, 2);
2395cd3f9d89SJunchao Zhang   PetscCall(PetscObjectBaseTypeCompare((PetscObject)A, MATMPIDENSE, &isMPI));
2396cd3f9d89SJunchao Zhang   if (isMPI) {
2397cd3f9d89SJunchao Zhang     PetscCall(MatDenseRestoreArrayAndMemType(((Mat_MPIDense *)A->data)->A, array));
2398cd3f9d89SJunchao Zhang   } else {
2399cd3f9d89SJunchao Zhang     PetscErrorCode (*fptr)(Mat, PetscScalar **);
24003ba16761SJacob Faibussowitsch 
24013ba16761SJacob Faibussowitsch     PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatDenseRestoreArrayAndMemType_C", &fptr));
2402cd3f9d89SJunchao Zhang     if (fptr) {
2403cd3f9d89SJunchao Zhang       PetscCall((*fptr)(A, array));
2404cd3f9d89SJunchao Zhang     } else {
2405cd3f9d89SJunchao Zhang       PetscUseMethod(A, "MatDenseRestoreArray_C", (Mat, PetscScalar **), (A, array));
2406cd3f9d89SJunchao Zhang     }
2407cd3f9d89SJunchao Zhang     *array = NULL;
2408cd3f9d89SJunchao Zhang   }
2409cd3f9d89SJunchao Zhang   PetscCall(PetscObjectStateIncrease((PetscObject)A));
24103ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2411cd3f9d89SJunchao Zhang }
2412cd3f9d89SJunchao Zhang 
2413cd3f9d89SJunchao Zhang /*@C
2414cd3f9d89SJunchao Zhang   MatDenseGetArrayReadAndMemType - gives read-only access to the array where the data for a `MATDENSE` matrix is stored
2415cd3f9d89SJunchao Zhang 
2416cd3f9d89SJunchao Zhang   Logically Collective
2417cd3f9d89SJunchao Zhang 
2418cd3f9d89SJunchao Zhang   Input Parameter:
2419fe59aa6dSJacob Faibussowitsch . A - a dense matrix
2420cd3f9d89SJunchao Zhang 
2421cd3f9d89SJunchao Zhang   Output Parameters:
2422cd3f9d89SJunchao Zhang + array - pointer to the data
2423cd3f9d89SJunchao Zhang - mtype - memory type of the returned pointer
2424cd3f9d89SJunchao Zhang 
2425cd3f9d89SJunchao Zhang   Level: intermediate
2426cd3f9d89SJunchao Zhang 
2427fb850c59SBarry Smith   Note:
24282ef1f0ffSBarry Smith   If the matrix is of a device type such as `MATDENSECUDA`, `MATDENSEHIP`, etc.,
24292ef1f0ffSBarry Smith   an array on device is always returned and is guaranteed to contain the matrix's latest data.
24302ef1f0ffSBarry Smith 
24311cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATDENSE`, `MatDenseRestoreArrayReadAndMemType()`, `MatDenseGetArrayWriteAndMemType()`,
2432cd3f9d89SJunchao Zhang    `MatDenseGetArrayRead()`, `MatDenseRestoreArrayRead()`, `MatDenseGetArrayWrite()`, `MatDenseRestoreArrayWrite()`, `MatSeqAIJGetCSRAndMemType()`
2433cd3f9d89SJunchao Zhang @*/
2434cd3f9d89SJunchao Zhang PetscErrorCode MatDenseGetArrayReadAndMemType(Mat A, const PetscScalar **array, PetscMemType *mtype)
2435cd3f9d89SJunchao Zhang {
2436cd3f9d89SJunchao Zhang   PetscBool isMPI;
2437cd3f9d89SJunchao Zhang 
2438cd3f9d89SJunchao Zhang   PetscFunctionBegin;
2439cd3f9d89SJunchao Zhang   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
24404f572ea9SToby Isaac   PetscAssertPointer(array, 2);
2441e865de01SJunchao 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 */
2442cd3f9d89SJunchao Zhang   PetscCall(PetscObjectBaseTypeCompare((PetscObject)A, MATMPIDENSE, &isMPI));
2443cd3f9d89SJunchao Zhang   if (isMPI) { /* Dispatch here so that the code can be reused for all subclasses of MATDENSE */
2444cd3f9d89SJunchao Zhang     PetscCall(MatDenseGetArrayReadAndMemType(((Mat_MPIDense *)A->data)->A, array, mtype));
2445cd3f9d89SJunchao Zhang   } else {
2446cd3f9d89SJunchao Zhang     PetscErrorCode (*fptr)(Mat, const PetscScalar **, PetscMemType *);
24473ba16761SJacob Faibussowitsch 
24483ba16761SJacob Faibussowitsch     PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatDenseGetArrayReadAndMemType_C", &fptr));
2449cd3f9d89SJunchao Zhang     if (fptr) {
2450cd3f9d89SJunchao Zhang       PetscCall((*fptr)(A, array, mtype));
2451cd3f9d89SJunchao Zhang     } else {
24525c0db29aSPierre Jolivet       PetscUseMethod(A, "MatDenseGetArrayRead_C", (Mat, PetscScalar **), (A, (PetscScalar **)array));
2453cd3f9d89SJunchao Zhang       if (mtype) *mtype = PETSC_MEMTYPE_HOST;
2454cd3f9d89SJunchao Zhang     }
2455cd3f9d89SJunchao Zhang   }
24563ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2457cd3f9d89SJunchao Zhang }
2458cd3f9d89SJunchao Zhang 
2459cd3f9d89SJunchao Zhang /*@C
2460cd3f9d89SJunchao Zhang   MatDenseRestoreArrayReadAndMemType - returns access to the array that is obtained by `MatDenseGetArrayReadAndMemType()`
2461cd3f9d89SJunchao Zhang 
2462cd3f9d89SJunchao Zhang   Logically Collective
2463cd3f9d89SJunchao Zhang 
2464cd3f9d89SJunchao Zhang   Input Parameters:
2465fe59aa6dSJacob Faibussowitsch + A     - a dense matrix
2466cd3f9d89SJunchao Zhang - array - pointer to the data
2467cd3f9d89SJunchao Zhang 
2468cd3f9d89SJunchao Zhang   Level: intermediate
2469cd3f9d89SJunchao Zhang 
24701cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATDENSE`, `MatDenseGetArrayReadAndMemType()`, `MatDenseGetArray()`, `MatDenseGetArrayRead()`, `MatDenseRestoreArrayRead()`, `MatDenseGetArrayWrite()`, `MatDenseRestoreArrayWrite()`
2471cd3f9d89SJunchao Zhang @*/
2472cd3f9d89SJunchao Zhang PetscErrorCode MatDenseRestoreArrayReadAndMemType(Mat A, const PetscScalar **array)
2473cd3f9d89SJunchao Zhang {
2474cd3f9d89SJunchao Zhang   PetscBool isMPI;
2475cd3f9d89SJunchao Zhang 
2476cd3f9d89SJunchao Zhang   PetscFunctionBegin;
2477cd3f9d89SJunchao Zhang   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
24784f572ea9SToby Isaac   PetscAssertPointer(array, 2);
2479cd3f9d89SJunchao Zhang   PetscCall(PetscObjectBaseTypeCompare((PetscObject)A, MATMPIDENSE, &isMPI));
2480cd3f9d89SJunchao Zhang   if (isMPI) {
2481cd3f9d89SJunchao Zhang     PetscCall(MatDenseRestoreArrayReadAndMemType(((Mat_MPIDense *)A->data)->A, array));
2482cd3f9d89SJunchao Zhang   } else {
2483cd3f9d89SJunchao Zhang     PetscErrorCode (*fptr)(Mat, const PetscScalar **);
24843ba16761SJacob Faibussowitsch 
24853ba16761SJacob Faibussowitsch     PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatDenseRestoreArrayReadAndMemType_C", &fptr));
2486cd3f9d89SJunchao Zhang     if (fptr) {
2487cd3f9d89SJunchao Zhang       PetscCall((*fptr)(A, array));
2488cd3f9d89SJunchao Zhang     } else {
24895c0db29aSPierre Jolivet       PetscUseMethod(A, "MatDenseRestoreArrayRead_C", (Mat, PetscScalar **), (A, (PetscScalar **)array));
2490cd3f9d89SJunchao Zhang     }
2491cd3f9d89SJunchao Zhang     *array = NULL;
2492cd3f9d89SJunchao Zhang   }
24933ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2494cd3f9d89SJunchao Zhang }
2495cd3f9d89SJunchao Zhang 
2496cd3f9d89SJunchao Zhang /*@C
2497cd3f9d89SJunchao Zhang   MatDenseGetArrayWriteAndMemType - gives write-only access to the array where the data for a `MATDENSE` matrix is stored
2498cd3f9d89SJunchao Zhang 
2499cd3f9d89SJunchao Zhang   Logically Collective
2500cd3f9d89SJunchao Zhang 
2501cd3f9d89SJunchao Zhang   Input Parameter:
2502fe59aa6dSJacob Faibussowitsch . A - a dense matrix
2503cd3f9d89SJunchao Zhang 
2504cd3f9d89SJunchao Zhang   Output Parameters:
2505cd3f9d89SJunchao Zhang + array - pointer to the data
2506cd3f9d89SJunchao Zhang - mtype - memory type of the returned pointer
2507cd3f9d89SJunchao Zhang 
2508cd3f9d89SJunchao Zhang   Level: intermediate
2509cd3f9d89SJunchao Zhang 
2510fb850c59SBarry Smith   Note:
25112ef1f0ffSBarry Smith   If the matrix is of a device type such as `MATDENSECUDA`, `MATDENSEHIP`, etc.,
25122ef1f0ffSBarry Smith   an array on device is always returned and is guaranteed to contain the matrix's latest data.
25132ef1f0ffSBarry Smith 
25141cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATDENSE`, `MatDenseRestoreArrayWriteAndMemType()`, `MatDenseGetArrayReadAndMemType()`, `MatDenseGetArrayRead()`,
2515cd3f9d89SJunchao Zhang   `MatDenseRestoreArrayRead()`, `MatDenseGetArrayWrite()`, `MatDenseRestoreArrayWrite()`, `MatSeqAIJGetCSRAndMemType()`
2516cd3f9d89SJunchao Zhang @*/
2517cd3f9d89SJunchao Zhang PetscErrorCode MatDenseGetArrayWriteAndMemType(Mat A, PetscScalar **array, PetscMemType *mtype)
2518cd3f9d89SJunchao Zhang {
2519cd3f9d89SJunchao Zhang   PetscBool isMPI;
2520cd3f9d89SJunchao Zhang 
2521cd3f9d89SJunchao Zhang   PetscFunctionBegin;
2522cd3f9d89SJunchao Zhang   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
25234f572ea9SToby Isaac   PetscAssertPointer(array, 2);
2524e865de01SJunchao 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 */
2525cd3f9d89SJunchao Zhang   PetscCall(PetscObjectBaseTypeCompare((PetscObject)A, MATMPIDENSE, &isMPI));
2526cd3f9d89SJunchao Zhang   if (isMPI) {
2527cd3f9d89SJunchao Zhang     PetscCall(MatDenseGetArrayWriteAndMemType(((Mat_MPIDense *)A->data)->A, array, mtype));
2528cd3f9d89SJunchao Zhang   } else {
2529cd3f9d89SJunchao Zhang     PetscErrorCode (*fptr)(Mat, PetscScalar **, PetscMemType *);
25303ba16761SJacob Faibussowitsch 
25313ba16761SJacob Faibussowitsch     PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatDenseGetArrayWriteAndMemType_C", &fptr));
2532cd3f9d89SJunchao Zhang     if (fptr) {
2533cd3f9d89SJunchao Zhang       PetscCall((*fptr)(A, array, mtype));
2534cd3f9d89SJunchao Zhang     } else {
2535cd3f9d89SJunchao Zhang       PetscUseMethod(A, "MatDenseGetArrayWrite_C", (Mat, PetscScalar **), (A, array));
2536cd3f9d89SJunchao Zhang       if (mtype) *mtype = PETSC_MEMTYPE_HOST;
2537cd3f9d89SJunchao Zhang     }
2538cd3f9d89SJunchao Zhang   }
25393ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2540cd3f9d89SJunchao Zhang }
2541cd3f9d89SJunchao Zhang 
2542cd3f9d89SJunchao Zhang /*@C
2543cd3f9d89SJunchao Zhang   MatDenseRestoreArrayWriteAndMemType - returns access to the array that is obtained by `MatDenseGetArrayReadAndMemType()`
2544cd3f9d89SJunchao Zhang 
2545cd3f9d89SJunchao Zhang   Logically Collective
2546cd3f9d89SJunchao Zhang 
2547cd3f9d89SJunchao Zhang   Input Parameters:
2548fe59aa6dSJacob Faibussowitsch + A     - a dense matrix
2549cd3f9d89SJunchao Zhang - array - pointer to the data
2550cd3f9d89SJunchao Zhang 
2551cd3f9d89SJunchao Zhang   Level: intermediate
2552cd3f9d89SJunchao Zhang 
25531cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATDENSE`, `MatDenseGetArrayWriteAndMemType()`, `MatDenseGetArray()`, `MatDenseGetArrayRead()`, `MatDenseRestoreArrayRead()`, `MatDenseGetArrayWrite()`, `MatDenseRestoreArrayWrite()`
2554cd3f9d89SJunchao Zhang @*/
2555cd3f9d89SJunchao Zhang PetscErrorCode MatDenseRestoreArrayWriteAndMemType(Mat A, PetscScalar **array)
2556cd3f9d89SJunchao Zhang {
2557cd3f9d89SJunchao Zhang   PetscBool isMPI;
2558cd3f9d89SJunchao Zhang 
2559cd3f9d89SJunchao Zhang   PetscFunctionBegin;
2560cd3f9d89SJunchao Zhang   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
25614f572ea9SToby Isaac   PetscAssertPointer(array, 2);
2562cd3f9d89SJunchao Zhang   PetscCall(PetscObjectBaseTypeCompare((PetscObject)A, MATMPIDENSE, &isMPI));
2563cd3f9d89SJunchao Zhang   if (isMPI) {
2564cd3f9d89SJunchao Zhang     PetscCall(MatDenseRestoreArrayWriteAndMemType(((Mat_MPIDense *)A->data)->A, array));
2565cd3f9d89SJunchao Zhang   } else {
2566cd3f9d89SJunchao Zhang     PetscErrorCode (*fptr)(Mat, PetscScalar **);
25673ba16761SJacob Faibussowitsch 
25683ba16761SJacob Faibussowitsch     PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatDenseRestoreArrayWriteAndMemType_C", &fptr));
2569cd3f9d89SJunchao Zhang     if (fptr) {
2570cd3f9d89SJunchao Zhang       PetscCall((*fptr)(A, array));
2571cd3f9d89SJunchao Zhang     } else {
2572cd3f9d89SJunchao Zhang       PetscUseMethod(A, "MatDenseRestoreArrayWrite_C", (Mat, PetscScalar **), (A, array));
2573cd3f9d89SJunchao Zhang     }
2574cd3f9d89SJunchao Zhang     *array = NULL;
2575cd3f9d89SJunchao Zhang   }
2576cd3f9d89SJunchao Zhang   PetscCall(PetscObjectStateIncrease((PetscObject)A));
25773ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2578cd3f9d89SJunchao Zhang }
2579cd3f9d89SJunchao Zhang 
2580d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatCreateSubMatrix_SeqDense(Mat A, IS isrow, IS iscol, MatReuse scall, Mat *B)
2581d71ae5a4SJacob Faibussowitsch {
2582c0bbcb79SLois Curfman McInnes   Mat_SeqDense   *mat = (Mat_SeqDense *)A->data;
2583bf5a80bcSToby Isaac   PetscInt        i, j, nrows, ncols, ldb;
25845d0c19d7SBarry Smith   const PetscInt *irow, *icol;
258587828ca2SBarry Smith   PetscScalar    *av, *bv, *v = mat->v;
25860754003eSLois Curfman McInnes   Mat             newmat;
25870754003eSLois Curfman McInnes 
25883a40ed3dSBarry Smith   PetscFunctionBegin;
25899566063dSJacob Faibussowitsch   PetscCall(ISGetIndices(isrow, &irow));
25909566063dSJacob Faibussowitsch   PetscCall(ISGetIndices(iscol, &icol));
25919566063dSJacob Faibussowitsch   PetscCall(ISGetLocalSize(isrow, &nrows));
25929566063dSJacob Faibussowitsch   PetscCall(ISGetLocalSize(iscol, &ncols));
25930754003eSLois Curfman McInnes 
2594182d2002SSatish Balay   /* Check submatrixcall */
2595182d2002SSatish Balay   if (scall == MAT_REUSE_MATRIX) {
259613f74950SBarry Smith     PetscInt n_cols, n_rows;
25979566063dSJacob Faibussowitsch     PetscCall(MatGetSize(*B, &n_rows, &n_cols));
259821a2c019SBarry Smith     if (n_rows != nrows || n_cols != ncols) {
2599f746d493SDmitry Karpeev       /* resize the result matrix to match number of requested rows/columns */
26009566063dSJacob Faibussowitsch       PetscCall(MatSetSizes(*B, nrows, ncols, nrows, ncols));
260121a2c019SBarry Smith     }
2602182d2002SSatish Balay     newmat = *B;
2603182d2002SSatish Balay   } else {
26040754003eSLois Curfman McInnes     /* Create and fill new matrix */
26059566063dSJacob Faibussowitsch     PetscCall(MatCreate(PetscObjectComm((PetscObject)A), &newmat));
26069566063dSJacob Faibussowitsch     PetscCall(MatSetSizes(newmat, nrows, ncols, nrows, ncols));
26079566063dSJacob Faibussowitsch     PetscCall(MatSetType(newmat, ((PetscObject)A)->type_name));
26089566063dSJacob Faibussowitsch     PetscCall(MatSeqDenseSetPreallocation(newmat, NULL));
2609182d2002SSatish Balay   }
2610182d2002SSatish Balay 
2611182d2002SSatish Balay   /* Now extract the data pointers and do the copy,column at a time */
26129566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArray(newmat, &bv));
26139566063dSJacob Faibussowitsch   PetscCall(MatDenseGetLDA(newmat, &ldb));
2614182d2002SSatish Balay   for (i = 0; i < ncols; i++) {
26156de62eeeSBarry Smith     av = v + mat->lda * icol[i];
2616ca15aa20SStefano Zampini     for (j = 0; j < nrows; j++) bv[j] = av[irow[j]];
2617bf5a80bcSToby Isaac     bv += ldb;
26180754003eSLois Curfman McInnes   }
26199566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArray(newmat, &bv));
2620182d2002SSatish Balay 
2621182d2002SSatish Balay   /* Assemble the matrices so that the correct flags are set */
26229566063dSJacob Faibussowitsch   PetscCall(MatAssemblyBegin(newmat, MAT_FINAL_ASSEMBLY));
26239566063dSJacob Faibussowitsch   PetscCall(MatAssemblyEnd(newmat, MAT_FINAL_ASSEMBLY));
26240754003eSLois Curfman McInnes 
26250754003eSLois Curfman McInnes   /* Free work space */
26269566063dSJacob Faibussowitsch   PetscCall(ISRestoreIndices(isrow, &irow));
26279566063dSJacob Faibussowitsch   PetscCall(ISRestoreIndices(iscol, &icol));
2628182d2002SSatish Balay   *B = newmat;
26293ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
26300754003eSLois Curfman McInnes }
26310754003eSLois Curfman McInnes 
2632d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatCreateSubMatrices_SeqDense(Mat A, PetscInt n, const IS irow[], const IS icol[], MatReuse scall, Mat *B[])
2633d71ae5a4SJacob Faibussowitsch {
263413f74950SBarry Smith   PetscInt i;
2635905e6a2fSBarry Smith 
26363a40ed3dSBarry Smith   PetscFunctionBegin;
263748a46eb9SPierre Jolivet   if (scall == MAT_INITIAL_MATRIX) PetscCall(PetscCalloc1(n, B));
2638905e6a2fSBarry Smith 
263948a46eb9SPierre Jolivet   for (i = 0; i < n; i++) PetscCall(MatCreateSubMatrix_SeqDense(A, irow[i], icol[i], scall, &(*B)[i]));
26403ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2641905e6a2fSBarry Smith }
2642905e6a2fSBarry Smith 
2643d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatAssemblyBegin_SeqDense(Mat mat, MatAssemblyType mode)
2644d71ae5a4SJacob Faibussowitsch {
2645c0aa2d19SHong Zhang   PetscFunctionBegin;
26463ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2647c0aa2d19SHong Zhang }
2648c0aa2d19SHong Zhang 
2649d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatAssemblyEnd_SeqDense(Mat mat, MatAssemblyType mode)
2650d71ae5a4SJacob Faibussowitsch {
2651c0aa2d19SHong Zhang   PetscFunctionBegin;
26523ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2653c0aa2d19SHong Zhang }
2654c0aa2d19SHong Zhang 
2655d71ae5a4SJacob Faibussowitsch PetscErrorCode MatCopy_SeqDense(Mat A, Mat B, MatStructure str)
2656d71ae5a4SJacob Faibussowitsch {
26574b0e389bSBarry Smith   Mat_SeqDense      *a = (Mat_SeqDense *)A->data, *b = (Mat_SeqDense *)B->data;
2658ca15aa20SStefano Zampini   const PetscScalar *va;
2659ca15aa20SStefano Zampini   PetscScalar       *vb;
2660d0f46423SBarry Smith   PetscInt           lda1 = a->lda, lda2 = b->lda, m = A->rmap->n, n = A->cmap->n, j;
26613a40ed3dSBarry Smith 
26623a40ed3dSBarry Smith   PetscFunctionBegin;
266333f4a19fSKris Buschelman   /* If the two matrices don't have the same copy implementation, they aren't compatible for fast copy. */
266433f4a19fSKris Buschelman   if (A->ops->copy != B->ops->copy) {
26659566063dSJacob Faibussowitsch     PetscCall(MatCopy_Basic(A, B, str));
26663ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
26673a40ed3dSBarry Smith   }
2668aed4548fSBarry Smith   PetscCheck(m == B->rmap->n && n == B->cmap->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "size(B) != size(A)");
26699566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArrayRead(A, &va));
26709566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArray(B, &vb));
2671a5ce6ee0Svictorle   if (lda1 > m || lda2 > m) {
267248a46eb9SPierre Jolivet     for (j = 0; j < n; j++) PetscCall(PetscArraycpy(vb + j * lda2, va + j * lda1, m));
2673a5ce6ee0Svictorle   } else {
26749566063dSJacob Faibussowitsch     PetscCall(PetscArraycpy(vb, va, A->rmap->n * A->cmap->n));
2675a5ce6ee0Svictorle   }
26769566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArray(B, &vb));
26779566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArrayRead(A, &va));
26789566063dSJacob Faibussowitsch   PetscCall(MatAssemblyBegin(B, MAT_FINAL_ASSEMBLY));
26799566063dSJacob Faibussowitsch   PetscCall(MatAssemblyEnd(B, MAT_FINAL_ASSEMBLY));
26803ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2681273d9f13SBarry Smith }
2682273d9f13SBarry Smith 
2683d71ae5a4SJacob Faibussowitsch PetscErrorCode MatSetUp_SeqDense(Mat A)
2684d71ae5a4SJacob Faibussowitsch {
2685273d9f13SBarry Smith   PetscFunctionBegin;
26869566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetUp(A->rmap));
26879566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetUp(A->cmap));
268848a46eb9SPierre Jolivet   if (!A->preallocated) PetscCall(MatSeqDenseSetPreallocation(A, NULL));
26893ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
26904b0e389bSBarry Smith }
26914b0e389bSBarry Smith 
2692d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatConjugate_SeqDense(Mat A)
2693d71ae5a4SJacob Faibussowitsch {
26944396437dSToby Isaac   Mat_SeqDense *mat = (Mat_SeqDense *)A->data;
269506c5243aSJose E. Roman   PetscInt      i, j;
26964396437dSToby Isaac   PetscInt      min = PetscMin(A->rmap->n, A->cmap->n);
2697ca15aa20SStefano Zampini   PetscScalar  *aa;
2698ba337c44SJed Brown 
2699ba337c44SJed Brown   PetscFunctionBegin;
27009566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArray(A, &aa));
270106c5243aSJose E. Roman   for (j = 0; j < A->cmap->n; j++) {
270206c5243aSJose E. Roman     for (i = 0; i < A->rmap->n; i++) aa[i + j * mat->lda] = PetscConj(aa[i + j * mat->lda]);
270306c5243aSJose E. Roman   }
27049566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArray(A, &aa));
27059371c9d4SSatish Balay   if (mat->tau)
27069371c9d4SSatish Balay     for (i = 0; i < min; i++) mat->tau[i] = PetscConj(mat->tau[i]);
27073ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2708ba337c44SJed Brown }
2709ba337c44SJed Brown 
2710d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatRealPart_SeqDense(Mat A)
2711d71ae5a4SJacob Faibussowitsch {
271206c5243aSJose E. Roman   Mat_SeqDense *mat = (Mat_SeqDense *)A->data;
271306c5243aSJose E. Roman   PetscInt      i, j;
2714ca15aa20SStefano Zampini   PetscScalar  *aa;
2715ba337c44SJed Brown 
2716ba337c44SJed Brown   PetscFunctionBegin;
27179566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArray(A, &aa));
271806c5243aSJose E. Roman   for (j = 0; j < A->cmap->n; j++) {
271906c5243aSJose E. Roman     for (i = 0; i < A->rmap->n; i++) aa[i + j * mat->lda] = PetscRealPart(aa[i + j * mat->lda]);
272006c5243aSJose E. Roman   }
27219566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArray(A, &aa));
27223ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2723ba337c44SJed Brown }
2724ba337c44SJed Brown 
2725d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatImaginaryPart_SeqDense(Mat A)
2726d71ae5a4SJacob Faibussowitsch {
272706c5243aSJose E. Roman   Mat_SeqDense *mat = (Mat_SeqDense *)A->data;
272806c5243aSJose E. Roman   PetscInt      i, j;
2729ca15aa20SStefano Zampini   PetscScalar  *aa;
2730ba337c44SJed Brown 
2731ba337c44SJed Brown   PetscFunctionBegin;
27329566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArray(A, &aa));
273306c5243aSJose E. Roman   for (j = 0; j < A->cmap->n; j++) {
273406c5243aSJose E. Roman     for (i = 0; i < A->rmap->n; i++) aa[i + j * mat->lda] = PetscImaginaryPart(aa[i + j * mat->lda]);
273506c5243aSJose E. Roman   }
27369566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArray(A, &aa));
27373ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2738ba337c44SJed Brown }
2739284134d9SBarry Smith 
2740d71ae5a4SJacob Faibussowitsch PetscErrorCode MatMatMultSymbolic_SeqDense_SeqDense(Mat A, Mat B, PetscReal fill, Mat C)
2741d71ae5a4SJacob Faibussowitsch {
2742d0f46423SBarry Smith   PetscInt  m = A->rmap->n, n = B->cmap->n;
274347d993e7Ssuyashtn   PetscBool cisdense = PETSC_FALSE;
2744a9fe9ddaSSatish Balay 
2745ee16a9a1SHong Zhang   PetscFunctionBegin;
27469566063dSJacob Faibussowitsch   PetscCall(MatSetSizes(C, m, n, m, n));
274747d993e7Ssuyashtn #if defined(PETSC_HAVE_CUDA)
27489566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompareAny((PetscObject)C, &cisdense, MATSEQDENSE, MATSEQDENSECUDA, ""));
274947d993e7Ssuyashtn #endif
275047d993e7Ssuyashtn #if defined(PETSC_HAVE_HIP)
275147d993e7Ssuyashtn   PetscCall(PetscObjectTypeCompareAny((PetscObject)C, &cisdense, MATSEQDENSE, MATSEQDENSEHIP, ""));
275247d993e7Ssuyashtn #endif
27537a3c3d58SStefano Zampini   if (!cisdense) {
27547a3c3d58SStefano Zampini     PetscBool flg;
27557a3c3d58SStefano Zampini 
27569566063dSJacob Faibussowitsch     PetscCall(PetscObjectTypeCompare((PetscObject)B, ((PetscObject)A)->type_name, &flg));
27579566063dSJacob Faibussowitsch     PetscCall(MatSetType(C, flg ? ((PetscObject)A)->type_name : MATDENSE));
27587a3c3d58SStefano Zampini   }
27599566063dSJacob Faibussowitsch   PetscCall(MatSetUp(C));
27603ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2761ee16a9a1SHong Zhang }
2762a9fe9ddaSSatish Balay 
2763d71ae5a4SJacob Faibussowitsch PetscErrorCode MatMatMultNumeric_SeqDense_SeqDense(Mat A, Mat B, Mat C)
2764d71ae5a4SJacob Faibussowitsch {
27656718818eSStefano Zampini   Mat_SeqDense      *a = (Mat_SeqDense *)A->data, *b = (Mat_SeqDense *)B->data, *c = (Mat_SeqDense *)C->data;
27660805154bSBarry Smith   PetscBLASInt       m, n, k;
2767ca15aa20SStefano Zampini   const PetscScalar *av, *bv;
2768ca15aa20SStefano Zampini   PetscScalar       *cv;
2769a9fe9ddaSSatish Balay   PetscScalar        _DOne = 1.0, _DZero = 0.0;
2770a9fe9ddaSSatish Balay 
2771a9fe9ddaSSatish Balay   PetscFunctionBegin;
27729566063dSJacob Faibussowitsch   PetscCall(PetscBLASIntCast(C->rmap->n, &m));
27739566063dSJacob Faibussowitsch   PetscCall(PetscBLASIntCast(C->cmap->n, &n));
27749566063dSJacob Faibussowitsch   PetscCall(PetscBLASIntCast(A->cmap->n, &k));
27753ba16761SJacob Faibussowitsch   if (!m || !n || !k) PetscFunctionReturn(PETSC_SUCCESS);
27769566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArrayRead(A, &av));
27779566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArrayRead(B, &bv));
27789566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArrayWrite(C, &cv));
2779792fecdfSBarry Smith   PetscCallBLAS("BLASgemm", BLASgemm_("N", "N", &m, &n, &k, &_DOne, av, &a->lda, bv, &b->lda, &_DZero, cv, &c->lda));
27809566063dSJacob Faibussowitsch   PetscCall(PetscLogFlops(1.0 * m * n * k + 1.0 * m * n * (k - 1)));
27819566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArrayRead(A, &av));
27829566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArrayRead(B, &bv));
27839566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArrayWrite(C, &cv));
27843ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2785a9fe9ddaSSatish Balay }
2786a9fe9ddaSSatish Balay 
2787d71ae5a4SJacob Faibussowitsch PetscErrorCode MatMatTransposeMultSymbolic_SeqDense_SeqDense(Mat A, Mat B, PetscReal fill, Mat C)
2788d71ae5a4SJacob Faibussowitsch {
278969f65d41SStefano Zampini   PetscInt  m = A->rmap->n, n = B->rmap->n;
279047d993e7Ssuyashtn   PetscBool cisdense = PETSC_FALSE;
279169f65d41SStefano Zampini 
279269f65d41SStefano Zampini   PetscFunctionBegin;
27939566063dSJacob Faibussowitsch   PetscCall(MatSetSizes(C, m, n, m, n));
279447d993e7Ssuyashtn #if defined(PETSC_HAVE_CUDA)
27959566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompareAny((PetscObject)C, &cisdense, MATSEQDENSE, MATSEQDENSECUDA, ""));
279647d993e7Ssuyashtn #endif
279747d993e7Ssuyashtn #if defined(PETSC_HAVE_HIP)
279847d993e7Ssuyashtn   PetscCall(PetscObjectTypeCompareAny((PetscObject)C, &cisdense, MATSEQDENSE, MATSEQDENSEHIP, ""));
279947d993e7Ssuyashtn #endif
28007a3c3d58SStefano Zampini   if (!cisdense) {
28017a3c3d58SStefano Zampini     PetscBool flg;
28027a3c3d58SStefano Zampini 
28039566063dSJacob Faibussowitsch     PetscCall(PetscObjectTypeCompare((PetscObject)B, ((PetscObject)A)->type_name, &flg));
28049566063dSJacob Faibussowitsch     PetscCall(MatSetType(C, flg ? ((PetscObject)A)->type_name : MATDENSE));
28057a3c3d58SStefano Zampini   }
28069566063dSJacob Faibussowitsch   PetscCall(MatSetUp(C));
28073ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
280869f65d41SStefano Zampini }
280969f65d41SStefano Zampini 
2810d71ae5a4SJacob Faibussowitsch PetscErrorCode MatMatTransposeMultNumeric_SeqDense_SeqDense(Mat A, Mat B, Mat C)
2811d71ae5a4SJacob Faibussowitsch {
281269f65d41SStefano Zampini   Mat_SeqDense      *a = (Mat_SeqDense *)A->data;
281369f65d41SStefano Zampini   Mat_SeqDense      *b = (Mat_SeqDense *)B->data;
281469f65d41SStefano Zampini   Mat_SeqDense      *c = (Mat_SeqDense *)C->data;
28156718818eSStefano Zampini   const PetscScalar *av, *bv;
28166718818eSStefano Zampini   PetscScalar       *cv;
281769f65d41SStefano Zampini   PetscBLASInt       m, n, k;
281869f65d41SStefano Zampini   PetscScalar        _DOne = 1.0, _DZero = 0.0;
281969f65d41SStefano Zampini 
282069f65d41SStefano Zampini   PetscFunctionBegin;
28219566063dSJacob Faibussowitsch   PetscCall(PetscBLASIntCast(C->rmap->n, &m));
28229566063dSJacob Faibussowitsch   PetscCall(PetscBLASIntCast(C->cmap->n, &n));
28239566063dSJacob Faibussowitsch   PetscCall(PetscBLASIntCast(A->cmap->n, &k));
28243ba16761SJacob Faibussowitsch   if (!m || !n || !k) PetscFunctionReturn(PETSC_SUCCESS);
28259566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArrayRead(A, &av));
28269566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArrayRead(B, &bv));
28279566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArrayWrite(C, &cv));
2828792fecdfSBarry Smith   PetscCallBLAS("BLASgemm", BLASgemm_("N", "T", &m, &n, &k, &_DOne, av, &a->lda, bv, &b->lda, &_DZero, cv, &c->lda));
28299566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArrayRead(A, &av));
28309566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArrayRead(B, &bv));
28319566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArrayWrite(C, &cv));
28329566063dSJacob Faibussowitsch   PetscCall(PetscLogFlops(1.0 * m * n * k + 1.0 * m * n * (k - 1)));
28333ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
283469f65d41SStefano Zampini }
283569f65d41SStefano Zampini 
2836d71ae5a4SJacob Faibussowitsch PetscErrorCode MatTransposeMatMultSymbolic_SeqDense_SeqDense(Mat A, Mat B, PetscReal fill, Mat C)
2837d71ae5a4SJacob Faibussowitsch {
2838d0f46423SBarry Smith   PetscInt  m = A->cmap->n, n = B->cmap->n;
283947d993e7Ssuyashtn   PetscBool cisdense = PETSC_FALSE;
2840a9fe9ddaSSatish Balay 
2841ee16a9a1SHong Zhang   PetscFunctionBegin;
28429566063dSJacob Faibussowitsch   PetscCall(MatSetSizes(C, m, n, m, n));
284347d993e7Ssuyashtn #if defined(PETSC_HAVE_CUDA)
28449566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompareAny((PetscObject)C, &cisdense, MATSEQDENSE, MATSEQDENSECUDA, ""));
284547d993e7Ssuyashtn #endif
284647d993e7Ssuyashtn #if defined(PETSC_HAVE_HIP)
284747d993e7Ssuyashtn   PetscCall(PetscObjectTypeCompareAny((PetscObject)C, &cisdense, MATSEQDENSE, MATSEQDENSEHIP, ""));
284847d993e7Ssuyashtn #endif
28497a3c3d58SStefano Zampini   if (!cisdense) {
28507a3c3d58SStefano Zampini     PetscBool flg;
28517a3c3d58SStefano Zampini 
28529566063dSJacob Faibussowitsch     PetscCall(PetscObjectTypeCompare((PetscObject)B, ((PetscObject)A)->type_name, &flg));
28539566063dSJacob Faibussowitsch     PetscCall(MatSetType(C, flg ? ((PetscObject)A)->type_name : MATDENSE));
28547a3c3d58SStefano Zampini   }
28559566063dSJacob Faibussowitsch   PetscCall(MatSetUp(C));
28563ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2857ee16a9a1SHong Zhang }
2858a9fe9ddaSSatish Balay 
2859d71ae5a4SJacob Faibussowitsch PetscErrorCode MatTransposeMatMultNumeric_SeqDense_SeqDense(Mat A, Mat B, Mat C)
2860d71ae5a4SJacob Faibussowitsch {
2861a9fe9ddaSSatish Balay   Mat_SeqDense      *a = (Mat_SeqDense *)A->data;
2862a9fe9ddaSSatish Balay   Mat_SeqDense      *b = (Mat_SeqDense *)B->data;
2863a9fe9ddaSSatish Balay   Mat_SeqDense      *c = (Mat_SeqDense *)C->data;
28646718818eSStefano Zampini   const PetscScalar *av, *bv;
28656718818eSStefano Zampini   PetscScalar       *cv;
28660805154bSBarry Smith   PetscBLASInt       m, n, k;
2867a9fe9ddaSSatish Balay   PetscScalar        _DOne = 1.0, _DZero = 0.0;
2868a9fe9ddaSSatish Balay 
2869a9fe9ddaSSatish Balay   PetscFunctionBegin;
28709566063dSJacob Faibussowitsch   PetscCall(PetscBLASIntCast(C->rmap->n, &m));
28719566063dSJacob Faibussowitsch   PetscCall(PetscBLASIntCast(C->cmap->n, &n));
28729566063dSJacob Faibussowitsch   PetscCall(PetscBLASIntCast(A->rmap->n, &k));
28733ba16761SJacob Faibussowitsch   if (!m || !n || !k) PetscFunctionReturn(PETSC_SUCCESS);
28749566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArrayRead(A, &av));
28759566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArrayRead(B, &bv));
28769566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArrayWrite(C, &cv));
2877792fecdfSBarry Smith   PetscCallBLAS("BLASgemm", BLASgemm_("T", "N", &m, &n, &k, &_DOne, av, &a->lda, bv, &b->lda, &_DZero, cv, &c->lda));
28789566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArrayRead(A, &av));
28799566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArrayRead(B, &bv));
28809566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArrayWrite(C, &cv));
28819566063dSJacob Faibussowitsch   PetscCall(PetscLogFlops(1.0 * m * n * k + 1.0 * m * n * (k - 1)));
28823ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2883a9fe9ddaSSatish Balay }
2884985db425SBarry Smith 
2885d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatProductSetFromOptions_SeqDense_AB(Mat C)
2886d71ae5a4SJacob Faibussowitsch {
28874222ddf1SHong Zhang   PetscFunctionBegin;
28884222ddf1SHong Zhang   C->ops->matmultsymbolic = MatMatMultSymbolic_SeqDense_SeqDense;
28894222ddf1SHong Zhang   C->ops->productsymbolic = MatProductSymbolic_AB;
28903ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
28914222ddf1SHong Zhang }
28924222ddf1SHong Zhang 
2893d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatProductSetFromOptions_SeqDense_AtB(Mat C)
2894d71ae5a4SJacob Faibussowitsch {
28954222ddf1SHong Zhang   PetscFunctionBegin;
28964222ddf1SHong Zhang   C->ops->transposematmultsymbolic = MatTransposeMatMultSymbolic_SeqDense_SeqDense;
28974222ddf1SHong Zhang   C->ops->productsymbolic          = MatProductSymbolic_AtB;
28983ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
28994222ddf1SHong Zhang }
29004222ddf1SHong Zhang 
2901d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatProductSetFromOptions_SeqDense_ABt(Mat C)
2902d71ae5a4SJacob Faibussowitsch {
29034222ddf1SHong Zhang   PetscFunctionBegin;
29044222ddf1SHong Zhang   C->ops->mattransposemultsymbolic = MatMatTransposeMultSymbolic_SeqDense_SeqDense;
29054222ddf1SHong Zhang   C->ops->productsymbolic          = MatProductSymbolic_ABt;
29063ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
29074222ddf1SHong Zhang }
29084222ddf1SHong Zhang 
2909d71ae5a4SJacob Faibussowitsch PETSC_INTERN PetscErrorCode MatProductSetFromOptions_SeqDense(Mat C)
2910d71ae5a4SJacob Faibussowitsch {
29114222ddf1SHong Zhang   Mat_Product *product = C->product;
29124222ddf1SHong Zhang 
29134222ddf1SHong Zhang   PetscFunctionBegin;
29144222ddf1SHong Zhang   switch (product->type) {
2915d71ae5a4SJacob Faibussowitsch   case MATPRODUCT_AB:
2916d71ae5a4SJacob Faibussowitsch     PetscCall(MatProductSetFromOptions_SeqDense_AB(C));
2917d71ae5a4SJacob Faibussowitsch     break;
2918d71ae5a4SJacob Faibussowitsch   case MATPRODUCT_AtB:
2919d71ae5a4SJacob Faibussowitsch     PetscCall(MatProductSetFromOptions_SeqDense_AtB(C));
2920d71ae5a4SJacob Faibussowitsch     break;
2921d71ae5a4SJacob Faibussowitsch   case MATPRODUCT_ABt:
2922d71ae5a4SJacob Faibussowitsch     PetscCall(MatProductSetFromOptions_SeqDense_ABt(C));
2923d71ae5a4SJacob Faibussowitsch     break;
2924d71ae5a4SJacob Faibussowitsch   default:
2925d71ae5a4SJacob Faibussowitsch     break;
29264222ddf1SHong Zhang   }
29273ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
29284222ddf1SHong Zhang }
29294222ddf1SHong Zhang 
2930d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatGetRowMax_SeqDense(Mat A, Vec v, PetscInt idx[])
2931d71ae5a4SJacob Faibussowitsch {
2932985db425SBarry Smith   Mat_SeqDense      *a = (Mat_SeqDense *)A->data;
2933d0f46423SBarry Smith   PetscInt           i, j, m = A->rmap->n, n = A->cmap->n, p;
2934985db425SBarry Smith   PetscScalar       *x;
2935ca15aa20SStefano Zampini   const PetscScalar *aa;
2936985db425SBarry Smith 
2937985db425SBarry Smith   PetscFunctionBegin;
293828b400f6SJacob Faibussowitsch   PetscCheck(!A->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
29399566063dSJacob Faibussowitsch   PetscCall(VecGetArray(v, &x));
29409566063dSJacob Faibussowitsch   PetscCall(VecGetLocalSize(v, &p));
29419566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArrayRead(A, &aa));
294208401ef6SPierre Jolivet   PetscCheck(p == A->rmap->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Nonconforming matrix and vector");
2943985db425SBarry Smith   for (i = 0; i < m; i++) {
29449371c9d4SSatish Balay     x[i] = aa[i];
29459371c9d4SSatish Balay     if (idx) idx[i] = 0;
2946985db425SBarry Smith     for (j = 1; j < n; j++) {
29479371c9d4SSatish Balay       if (PetscRealPart(x[i]) < PetscRealPart(aa[i + a->lda * j])) {
29489371c9d4SSatish Balay         x[i] = aa[i + a->lda * j];
29499371c9d4SSatish Balay         if (idx) idx[i] = j;
29509371c9d4SSatish Balay       }
2951985db425SBarry Smith     }
2952985db425SBarry Smith   }
29539566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArrayRead(A, &aa));
29549566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(v, &x));
29553ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2956985db425SBarry Smith }
2957985db425SBarry Smith 
2958d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatGetRowMaxAbs_SeqDense(Mat A, Vec v, PetscInt idx[])
2959d71ae5a4SJacob Faibussowitsch {
2960985db425SBarry Smith   Mat_SeqDense      *a = (Mat_SeqDense *)A->data;
2961d0f46423SBarry Smith   PetscInt           i, j, m = A->rmap->n, n = A->cmap->n, p;
2962985db425SBarry Smith   PetscScalar       *x;
2963985db425SBarry Smith   PetscReal          atmp;
2964ca15aa20SStefano Zampini   const PetscScalar *aa;
2965985db425SBarry Smith 
2966985db425SBarry Smith   PetscFunctionBegin;
296728b400f6SJacob Faibussowitsch   PetscCheck(!A->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
29689566063dSJacob Faibussowitsch   PetscCall(VecGetArray(v, &x));
29699566063dSJacob Faibussowitsch   PetscCall(VecGetLocalSize(v, &p));
29709566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArrayRead(A, &aa));
297108401ef6SPierre Jolivet   PetscCheck(p == A->rmap->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Nonconforming matrix and vector");
2972985db425SBarry Smith   for (i = 0; i < m; i++) {
29739189402eSHong Zhang     x[i] = PetscAbsScalar(aa[i]);
2974985db425SBarry Smith     for (j = 1; j < n; j++) {
2975ca15aa20SStefano Zampini       atmp = PetscAbsScalar(aa[i + a->lda * j]);
29769371c9d4SSatish Balay       if (PetscAbsScalar(x[i]) < atmp) {
29779371c9d4SSatish Balay         x[i] = atmp;
29789371c9d4SSatish Balay         if (idx) idx[i] = j;
29799371c9d4SSatish Balay       }
2980985db425SBarry Smith     }
2981985db425SBarry Smith   }
29829566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArrayRead(A, &aa));
29839566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(v, &x));
29843ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2985985db425SBarry Smith }
2986985db425SBarry Smith 
2987d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatGetRowMin_SeqDense(Mat A, Vec v, PetscInt idx[])
2988d71ae5a4SJacob Faibussowitsch {
2989985db425SBarry Smith   Mat_SeqDense      *a = (Mat_SeqDense *)A->data;
2990d0f46423SBarry Smith   PetscInt           i, j, m = A->rmap->n, n = A->cmap->n, p;
2991985db425SBarry Smith   PetscScalar       *x;
2992ca15aa20SStefano Zampini   const PetscScalar *aa;
2993985db425SBarry Smith 
2994985db425SBarry Smith   PetscFunctionBegin;
299528b400f6SJacob Faibussowitsch   PetscCheck(!A->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
29969566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArrayRead(A, &aa));
29979566063dSJacob Faibussowitsch   PetscCall(VecGetArray(v, &x));
29989566063dSJacob Faibussowitsch   PetscCall(VecGetLocalSize(v, &p));
299908401ef6SPierre Jolivet   PetscCheck(p == A->rmap->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Nonconforming matrix and vector");
3000985db425SBarry Smith   for (i = 0; i < m; i++) {
30019371c9d4SSatish Balay     x[i] = aa[i];
30029371c9d4SSatish Balay     if (idx) idx[i] = 0;
3003985db425SBarry Smith     for (j = 1; j < n; j++) {
30049371c9d4SSatish Balay       if (PetscRealPart(x[i]) > PetscRealPart(aa[i + a->lda * j])) {
30059371c9d4SSatish Balay         x[i] = aa[i + a->lda * j];
30069371c9d4SSatish Balay         if (idx) idx[i] = j;
30079371c9d4SSatish Balay       }
3008985db425SBarry Smith     }
3009985db425SBarry Smith   }
30109566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(v, &x));
30119566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArrayRead(A, &aa));
30123ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3013985db425SBarry Smith }
3014985db425SBarry Smith 
3015d71ae5a4SJacob Faibussowitsch PetscErrorCode MatGetColumnVector_SeqDense(Mat A, Vec v, PetscInt col)
3016d71ae5a4SJacob Faibussowitsch {
30178d0534beSBarry Smith   Mat_SeqDense      *a = (Mat_SeqDense *)A->data;
30188d0534beSBarry Smith   PetscScalar       *x;
3019ca15aa20SStefano Zampini   const PetscScalar *aa;
30208d0534beSBarry Smith 
30218d0534beSBarry Smith   PetscFunctionBegin;
302228b400f6SJacob Faibussowitsch   PetscCheck(!A->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
30239566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArrayRead(A, &aa));
30249566063dSJacob Faibussowitsch   PetscCall(VecGetArray(v, &x));
30259566063dSJacob Faibussowitsch   PetscCall(PetscArraycpy(x, aa + col * a->lda, A->rmap->n));
30269566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(v, &x));
30279566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArrayRead(A, &aa));
30283ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
30298d0534beSBarry Smith }
30308d0534beSBarry Smith 
3031d71ae5a4SJacob Faibussowitsch PETSC_INTERN PetscErrorCode MatGetColumnReductions_SeqDense(Mat A, PetscInt type, PetscReal *reductions)
3032d71ae5a4SJacob Faibussowitsch {
30330716a85fSBarry Smith   PetscInt           i, j, m, n;
30341683a169SBarry Smith   const PetscScalar *a;
30350716a85fSBarry Smith 
30360716a85fSBarry Smith   PetscFunctionBegin;
30379566063dSJacob Faibussowitsch   PetscCall(MatGetSize(A, &m, &n));
30389566063dSJacob Faibussowitsch   PetscCall(PetscArrayzero(reductions, n));
30399566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArrayRead(A, &a));
3040857cbf51SRichard Tran Mills   if (type == NORM_2) {
30410716a85fSBarry Smith     for (i = 0; i < n; i++) {
3042ad540459SPierre Jolivet       for (j = 0; j < m; j++) reductions[i] += PetscAbsScalar(a[j] * a[j]);
304316cd844bSPierre Jolivet       a = PetscSafePointerPlusOffset(a, m);
30440716a85fSBarry Smith     }
3045857cbf51SRichard Tran Mills   } else if (type == NORM_1) {
30460716a85fSBarry Smith     for (i = 0; i < n; i++) {
3047ad540459SPierre Jolivet       for (j = 0; j < m; j++) reductions[i] += PetscAbsScalar(a[j]);
304816cd844bSPierre Jolivet       a = PetscSafePointerPlusOffset(a, m);
30490716a85fSBarry Smith     }
3050857cbf51SRichard Tran Mills   } else if (type == NORM_INFINITY) {
30510716a85fSBarry Smith     for (i = 0; i < n; i++) {
3052ad540459SPierre Jolivet       for (j = 0; j < m; j++) reductions[i] = PetscMax(PetscAbsScalar(a[j]), reductions[i]);
305316cd844bSPierre Jolivet       a = PetscSafePointerPlusOffset(a, m);
30540716a85fSBarry Smith     }
3055857cbf51SRichard Tran Mills   } else if (type == REDUCTION_SUM_REALPART || type == REDUCTION_MEAN_REALPART) {
3056a873a8cdSSam Reynolds     for (i = 0; i < n; i++) {
3057ad540459SPierre Jolivet       for (j = 0; j < m; j++) reductions[i] += PetscRealPart(a[j]);
305816cd844bSPierre Jolivet       a = PetscSafePointerPlusOffset(a, m);
3059a873a8cdSSam Reynolds     }
3060857cbf51SRichard Tran Mills   } else if (type == REDUCTION_SUM_IMAGINARYPART || type == REDUCTION_MEAN_IMAGINARYPART) {
3061857cbf51SRichard Tran Mills     for (i = 0; i < n; i++) {
3062ad540459SPierre Jolivet       for (j = 0; j < m; j++) reductions[i] += PetscImaginaryPart(a[j]);
306316cd844bSPierre Jolivet       a = PetscSafePointerPlusOffset(a, m);
3064857cbf51SRichard Tran Mills     }
3065857cbf51SRichard Tran Mills   } else SETERRQ(PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONG, "Unknown reduction type");
30669566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArrayRead(A, &a));
3067857cbf51SRichard Tran Mills   if (type == NORM_2) {
3068a873a8cdSSam Reynolds     for (i = 0; i < n; i++) reductions[i] = PetscSqrtReal(reductions[i]);
3069857cbf51SRichard Tran Mills   } else if (type == REDUCTION_MEAN_REALPART || type == REDUCTION_MEAN_IMAGINARYPART) {
3070a873a8cdSSam Reynolds     for (i = 0; i < n; i++) reductions[i] /= m;
30710716a85fSBarry Smith   }
30723ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
30730716a85fSBarry Smith }
30740716a85fSBarry Smith 
3075d71ae5a4SJacob Faibussowitsch PetscErrorCode MatSetRandom_SeqDense(Mat x, PetscRandom rctx)
3076d71ae5a4SJacob Faibussowitsch {
307773a71a0fSBarry Smith   PetscScalar *a;
3078637a0070SStefano Zampini   PetscInt     lda, m, n, i, j;
307973a71a0fSBarry Smith 
308073a71a0fSBarry Smith   PetscFunctionBegin;
30819566063dSJacob Faibussowitsch   PetscCall(MatGetSize(x, &m, &n));
30829566063dSJacob Faibussowitsch   PetscCall(MatDenseGetLDA(x, &lda));
30833faff063SStefano Zampini   PetscCall(MatDenseGetArrayWrite(x, &a));
3084637a0070SStefano Zampini   for (j = 0; j < n; j++) {
308548a46eb9SPierre Jolivet     for (i = 0; i < m; i++) PetscCall(PetscRandomGetValue(rctx, a + j * lda + i));
308673a71a0fSBarry Smith   }
30873faff063SStefano Zampini   PetscCall(MatDenseRestoreArrayWrite(x, &a));
30883ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
308973a71a0fSBarry Smith }
309073a71a0fSBarry Smith 
3091d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatMissingDiagonal_SeqDense(Mat A, PetscBool *missing, PetscInt *d)
3092d71ae5a4SJacob Faibussowitsch {
30933b49f96aSBarry Smith   PetscFunctionBegin;
30943b49f96aSBarry Smith   *missing = PETSC_FALSE;
30953ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
30963b49f96aSBarry Smith }
309773a71a0fSBarry Smith 
3098ca15aa20SStefano Zampini /* vals is not const */
3099d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatDenseGetColumn_SeqDense(Mat A, PetscInt col, PetscScalar **vals)
3100d71ae5a4SJacob Faibussowitsch {
310186aefd0dSHong Zhang   Mat_SeqDense *a = (Mat_SeqDense *)A->data;
3102ca15aa20SStefano Zampini   PetscScalar  *v;
310386aefd0dSHong Zhang 
310486aefd0dSHong Zhang   PetscFunctionBegin;
310528b400f6SJacob Faibussowitsch   PetscCheck(!A->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
31069566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArray(A, &v));
3107ca15aa20SStefano Zampini   *vals = v + col * a->lda;
31089566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArray(A, &v));
31093ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
311086aefd0dSHong Zhang }
311186aefd0dSHong Zhang 
3112d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatDenseRestoreColumn_SeqDense(Mat A, PetscScalar **vals)
3113d71ae5a4SJacob Faibussowitsch {
311486aefd0dSHong Zhang   PetscFunctionBegin;
3115742765d3SMatthew Knepley   if (vals) *vals = NULL; /* user cannot accidentally use the array later */
31163ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
311786aefd0dSHong Zhang }
3118abc3b08eSStefano Zampini 
3119a5ae1ecdSBarry Smith static struct _MatOps MatOps_Values = {MatSetValues_SeqDense,
3120905e6a2fSBarry Smith                                        MatGetRow_SeqDense,
3121905e6a2fSBarry Smith                                        MatRestoreRow_SeqDense,
3122905e6a2fSBarry Smith                                        MatMult_SeqDense,
312397304618SKris Buschelman                                        /*  4*/ MatMultAdd_SeqDense,
31247c922b88SBarry Smith                                        MatMultTranspose_SeqDense,
31257c922b88SBarry Smith                                        MatMultTransposeAdd_SeqDense,
3126f4259b30SLisandro Dalcin                                        NULL,
3127f4259b30SLisandro Dalcin                                        NULL,
3128f4259b30SLisandro Dalcin                                        NULL,
3129f4259b30SLisandro Dalcin                                        /* 10*/ NULL,
3130905e6a2fSBarry Smith                                        MatLUFactor_SeqDense,
3131905e6a2fSBarry Smith                                        MatCholeskyFactor_SeqDense,
313241f059aeSBarry Smith                                        MatSOR_SeqDense,
3133ec8511deSBarry Smith                                        MatTranspose_SeqDense,
313497304618SKris Buschelman                                        /* 15*/ MatGetInfo_SeqDense,
3135905e6a2fSBarry Smith                                        MatEqual_SeqDense,
3136905e6a2fSBarry Smith                                        MatGetDiagonal_SeqDense,
3137905e6a2fSBarry Smith                                        MatDiagonalScale_SeqDense,
3138905e6a2fSBarry Smith                                        MatNorm_SeqDense,
3139c0aa2d19SHong Zhang                                        /* 20*/ MatAssemblyBegin_SeqDense,
3140c0aa2d19SHong Zhang                                        MatAssemblyEnd_SeqDense,
3141905e6a2fSBarry Smith                                        MatSetOption_SeqDense,
3142905e6a2fSBarry Smith                                        MatZeroEntries_SeqDense,
3143d519adbfSMatthew Knepley                                        /* 24*/ MatZeroRows_SeqDense,
3144f4259b30SLisandro Dalcin                                        NULL,
3145f4259b30SLisandro Dalcin                                        NULL,
3146f4259b30SLisandro Dalcin                                        NULL,
3147f4259b30SLisandro Dalcin                                        NULL,
31484994cf47SJed Brown                                        /* 29*/ MatSetUp_SeqDense,
3149f4259b30SLisandro Dalcin                                        NULL,
3150f4259b30SLisandro Dalcin                                        NULL,
3151f4259b30SLisandro Dalcin                                        NULL,
3152f4259b30SLisandro Dalcin                                        NULL,
3153d519adbfSMatthew Knepley                                        /* 34*/ MatDuplicate_SeqDense,
3154f4259b30SLisandro Dalcin                                        NULL,
3155f4259b30SLisandro Dalcin                                        NULL,
3156f4259b30SLisandro Dalcin                                        NULL,
3157f4259b30SLisandro Dalcin                                        NULL,
3158d519adbfSMatthew Knepley                                        /* 39*/ MatAXPY_SeqDense,
31597dae84e0SHong Zhang                                        MatCreateSubMatrices_SeqDense,
3160f4259b30SLisandro Dalcin                                        NULL,
31614b0e389bSBarry Smith                                        MatGetValues_SeqDense,
3162a5ae1ecdSBarry Smith                                        MatCopy_SeqDense,
3163d519adbfSMatthew Knepley                                        /* 44*/ MatGetRowMax_SeqDense,
3164a5ae1ecdSBarry Smith                                        MatScale_SeqDense,
31652f605a99SJose E. Roman                                        MatShift_SeqDense,
3166f4259b30SLisandro Dalcin                                        NULL,
31673f49a652SStefano Zampini                                        MatZeroRowsColumns_SeqDense,
316873a71a0fSBarry Smith                                        /* 49*/ MatSetRandom_SeqDense,
3169f4259b30SLisandro Dalcin                                        NULL,
3170f4259b30SLisandro Dalcin                                        NULL,
3171f4259b30SLisandro Dalcin                                        NULL,
3172f4259b30SLisandro Dalcin                                        NULL,
3173f4259b30SLisandro Dalcin                                        /* 54*/ NULL,
3174f4259b30SLisandro Dalcin                                        NULL,
3175f4259b30SLisandro Dalcin                                        NULL,
3176f4259b30SLisandro Dalcin                                        NULL,
3177f4259b30SLisandro Dalcin                                        NULL,
3178023c16fcSToby Isaac                                        /* 59*/ MatCreateSubMatrix_SeqDense,
3179e03a110bSBarry Smith                                        MatDestroy_SeqDense,
3180e03a110bSBarry Smith                                        MatView_SeqDense,
3181f4259b30SLisandro Dalcin                                        NULL,
3182f4259b30SLisandro Dalcin                                        NULL,
3183f4259b30SLisandro Dalcin                                        /* 64*/ NULL,
3184f4259b30SLisandro Dalcin                                        NULL,
3185f4259b30SLisandro Dalcin                                        NULL,
3186f4259b30SLisandro Dalcin                                        NULL,
3187f4259b30SLisandro Dalcin                                        NULL,
3188d519adbfSMatthew Knepley                                        /* 69*/ MatGetRowMaxAbs_SeqDense,
3189f4259b30SLisandro Dalcin                                        NULL,
3190f4259b30SLisandro Dalcin                                        NULL,
3191f4259b30SLisandro Dalcin                                        NULL,
3192f4259b30SLisandro Dalcin                                        NULL,
3193f4259b30SLisandro Dalcin                                        /* 74*/ NULL,
3194f4259b30SLisandro Dalcin                                        NULL,
3195f4259b30SLisandro Dalcin                                        NULL,
3196f4259b30SLisandro Dalcin                                        NULL,
3197f4259b30SLisandro Dalcin                                        NULL,
3198f4259b30SLisandro Dalcin                                        /* 79*/ NULL,
3199f4259b30SLisandro Dalcin                                        NULL,
3200f4259b30SLisandro Dalcin                                        NULL,
3201f4259b30SLisandro Dalcin                                        NULL,
32025bba2384SShri Abhyankar                                        /* 83*/ MatLoad_SeqDense,
3203637a0070SStefano Zampini                                        MatIsSymmetric_SeqDense,
32041cbb95d3SBarry Smith                                        MatIsHermitian_SeqDense,
3205f4259b30SLisandro Dalcin                                        NULL,
3206f4259b30SLisandro Dalcin                                        NULL,
3207f4259b30SLisandro Dalcin                                        NULL,
3208f4259b30SLisandro Dalcin                                        /* 89*/ NULL,
3209f4259b30SLisandro Dalcin                                        NULL,
3210a9fe9ddaSSatish Balay                                        MatMatMultNumeric_SeqDense_SeqDense,
3211f4259b30SLisandro Dalcin                                        NULL,
3212f4259b30SLisandro Dalcin                                        NULL,
3213f4259b30SLisandro Dalcin                                        /* 94*/ NULL,
3214f4259b30SLisandro Dalcin                                        NULL,
3215f4259b30SLisandro Dalcin                                        NULL,
321669f65d41SStefano Zampini                                        MatMatTransposeMultNumeric_SeqDense_SeqDense,
3217f4259b30SLisandro Dalcin                                        NULL,
32184222ddf1SHong Zhang                                        /* 99*/ MatProductSetFromOptions_SeqDense,
3219f4259b30SLisandro Dalcin                                        NULL,
3220f4259b30SLisandro Dalcin                                        NULL,
3221ba337c44SJed Brown                                        MatConjugate_SeqDense,
3222f4259b30SLisandro Dalcin                                        NULL,
3223f4259b30SLisandro Dalcin                                        /*104*/ NULL,
3224ba337c44SJed Brown                                        MatRealPart_SeqDense,
3225ba337c44SJed Brown                                        MatImaginaryPart_SeqDense,
3226f4259b30SLisandro Dalcin                                        NULL,
3227f4259b30SLisandro Dalcin                                        NULL,
3228f4259b30SLisandro Dalcin                                        /*109*/ NULL,
3229f4259b30SLisandro Dalcin                                        NULL,
32308d0534beSBarry Smith                                        MatGetRowMin_SeqDense,
3231aabbc4fbSShri Abhyankar                                        MatGetColumnVector_SeqDense,
32323b49f96aSBarry Smith                                        MatMissingDiagonal_SeqDense,
3233f4259b30SLisandro Dalcin                                        /*114*/ NULL,
3234f4259b30SLisandro Dalcin                                        NULL,
3235f4259b30SLisandro Dalcin                                        NULL,
3236f4259b30SLisandro Dalcin                                        NULL,
3237f4259b30SLisandro Dalcin                                        NULL,
3238f4259b30SLisandro Dalcin                                        /*119*/ NULL,
3239f4259b30SLisandro Dalcin                                        NULL,
3240459e8d23SBlanca Mellado Pinto                                        MatMultHermitianTranspose_SeqDense,
3241459e8d23SBlanca Mellado Pinto                                        MatMultHermitianTransposeAdd_SeqDense,
3242f4259b30SLisandro Dalcin                                        NULL,
3243f4259b30SLisandro Dalcin                                        /*124*/ NULL,
3244a873a8cdSSam Reynolds                                        MatGetColumnReductions_SeqDense,
3245f4259b30SLisandro Dalcin                                        NULL,
3246f4259b30SLisandro Dalcin                                        NULL,
3247f4259b30SLisandro Dalcin                                        NULL,
3248f4259b30SLisandro Dalcin                                        /*129*/ NULL,
3249f4259b30SLisandro Dalcin                                        NULL,
3250f4259b30SLisandro Dalcin                                        NULL,
325175648e8dSHong Zhang                                        MatTransposeMatMultNumeric_SeqDense_SeqDense,
3252f4259b30SLisandro Dalcin                                        NULL,
3253f4259b30SLisandro Dalcin                                        /*134*/ NULL,
3254f4259b30SLisandro Dalcin                                        NULL,
3255f4259b30SLisandro Dalcin                                        NULL,
3256f4259b30SLisandro Dalcin                                        NULL,
3257f4259b30SLisandro Dalcin                                        NULL,
3258f4259b30SLisandro Dalcin                                        /*139*/ NULL,
3259f4259b30SLisandro Dalcin                                        NULL,
3260f4259b30SLisandro Dalcin                                        NULL,
3261f4259b30SLisandro Dalcin                                        NULL,
3262f4259b30SLisandro Dalcin                                        NULL,
32634222ddf1SHong Zhang                                        MatCreateMPIMatConcatenateSeqMat_SeqDense,
3264f4259b30SLisandro Dalcin                                        /*145*/ NULL,
3265f4259b30SLisandro Dalcin                                        NULL,
326699a7f59eSMark Adams                                        NULL,
326799a7f59eSMark Adams                                        NULL,
32687fb60732SBarry Smith                                        NULL,
3269dec0b466SHong Zhang                                        /*150*/ NULL,
3270eede4a3fSMark Adams                                        NULL,
3271dec0b466SHong Zhang                                        NULL};
327290ace30eSBarry Smith 
32734b828684SBarry Smith /*@C
327411a5261eSBarry Smith   MatCreateSeqDense - Creates a `MATSEQDENSE` that
3275fb850c59SBarry Smith   is stored in column major order (the usual Fortran format).
3276289bc588SBarry Smith 
3277d083f849SBarry Smith   Collective
3278db81eaa0SLois Curfman McInnes 
327920563c6bSBarry Smith   Input Parameters:
328011a5261eSBarry Smith + comm - MPI communicator, set to `PETSC_COMM_SELF`
32810c775827SLois Curfman McInnes . m    - number of rows
328218f449edSLois Curfman McInnes . n    - number of columns
32832ef1f0ffSBarry Smith - data - optional location of matrix data in column major order.  Use `NULL` for PETSc
3284dfc5480cSLois Curfman McInnes    to control all matrix memory allocation.
328520563c6bSBarry Smith 
328620563c6bSBarry Smith   Output Parameter:
328744cd7ae7SLois Curfman McInnes . A - the matrix
328820563c6bSBarry Smith 
32892ef1f0ffSBarry Smith   Level: intermediate
32902ef1f0ffSBarry Smith 
329111a5261eSBarry Smith   Note:
329218f449edSLois Curfman McInnes   The data input variable is intended primarily for Fortran programmers
329318f449edSLois Curfman McInnes   who wish to allocate their own matrix memory space.  Most users should
32942ef1f0ffSBarry Smith   set `data` = `NULL`.
329518f449edSLois Curfman McInnes 
3296fb850c59SBarry Smith   Developer Note:
3297fb850c59SBarry Smith   Many of the matrix operations for this variant use the BLAS and LAPACK routines.
3298fb850c59SBarry Smith 
32991cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATSEQDENSE`, `MatCreate()`, `MatCreateDense()`, `MatSetValues()`
330020563c6bSBarry Smith @*/
3301d71ae5a4SJacob Faibussowitsch PetscErrorCode MatCreateSeqDense(MPI_Comm comm, PetscInt m, PetscInt n, PetscScalar *data, Mat *A)
3302d71ae5a4SJacob Faibussowitsch {
33033a40ed3dSBarry Smith   PetscFunctionBegin;
33049566063dSJacob Faibussowitsch   PetscCall(MatCreate(comm, A));
33059566063dSJacob Faibussowitsch   PetscCall(MatSetSizes(*A, m, n, m, n));
33069566063dSJacob Faibussowitsch   PetscCall(MatSetType(*A, MATSEQDENSE));
33079566063dSJacob Faibussowitsch   PetscCall(MatSeqDenseSetPreallocation(*A, data));
33083ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3309273d9f13SBarry Smith }
3310273d9f13SBarry Smith 
3311273d9f13SBarry Smith /*@C
331211a5261eSBarry Smith   MatSeqDenseSetPreallocation - Sets the array used for storing the matrix elements of a `MATSEQDENSE` matrix
3313273d9f13SBarry Smith 
3314d083f849SBarry Smith   Collective
3315273d9f13SBarry Smith 
3316273d9f13SBarry Smith   Input Parameters:
33171c4f3114SJed Brown + B    - the matrix
33182ef1f0ffSBarry Smith - data - the array (or `NULL`)
33192ef1f0ffSBarry Smith 
33202ef1f0ffSBarry Smith   Level: intermediate
3321273d9f13SBarry Smith 
332211a5261eSBarry Smith   Note:
3323273d9f13SBarry Smith   The data input variable is intended primarily for Fortran programmers
3324273d9f13SBarry Smith   who wish to allocate their own matrix memory space.  Most users should
3325284134d9SBarry Smith   need not call this routine.
3326273d9f13SBarry Smith 
33271cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATSEQDENSE`, `MatCreate()`, `MatCreateDense()`, `MatSetValues()`, `MatDenseSetLDA()`
3328273d9f13SBarry Smith @*/
3329d71ae5a4SJacob Faibussowitsch PetscErrorCode MatSeqDenseSetPreallocation(Mat B, PetscScalar data[])
3330d71ae5a4SJacob Faibussowitsch {
3331a23d5eceSKris Buschelman   PetscFunctionBegin;
3332d5ea218eSStefano Zampini   PetscValidHeaderSpecific(B, MAT_CLASSID, 1);
3333cac4c232SBarry Smith   PetscTryMethod(B, "MatSeqDenseSetPreallocation_C", (Mat, PetscScalar[]), (B, data));
33343ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3335a23d5eceSKris Buschelman }
3336a23d5eceSKris Buschelman 
3337d71ae5a4SJacob Faibussowitsch PetscErrorCode MatSeqDenseSetPreallocation_SeqDense(Mat B, PetscScalar *data)
3338d71ae5a4SJacob Faibussowitsch {
3339ad16ce7aSStefano Zampini   Mat_SeqDense *b = (Mat_SeqDense *)B->data;
3340273d9f13SBarry Smith 
3341273d9f13SBarry Smith   PetscFunctionBegin;
334228b400f6SJacob Faibussowitsch   PetscCheck(!b->matinuse, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Need to call MatDenseRestoreSubMatrix() first");
3343273d9f13SBarry Smith   B->preallocated = PETSC_TRUE;
3344a868139aSShri Abhyankar 
33459566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetUp(B->rmap));
33469566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetUp(B->cmap));
334734ef9618SShri Abhyankar 
3348ad16ce7aSStefano Zampini   if (b->lda <= 0) b->lda = B->rmap->n;
334986d161a7SShri Abhyankar 
33509e8f95c4SLisandro Dalcin   if (!data) { /* petsc-allocated storage */
33519566063dSJacob Faibussowitsch     if (!b->user_alloc) PetscCall(PetscFree(b->v));
33529566063dSJacob Faibussowitsch     PetscCall(PetscCalloc1((size_t)b->lda * B->cmap->n, &b->v));
33532205254eSKarl Rupp 
33549e8f95c4SLisandro Dalcin     b->user_alloc = PETSC_FALSE;
3355273d9f13SBarry Smith   } else { /* user-allocated storage */
33569566063dSJacob Faibussowitsch     if (!b->user_alloc) PetscCall(PetscFree(b->v));
3357273d9f13SBarry Smith     b->v          = data;
3358273d9f13SBarry Smith     b->user_alloc = PETSC_TRUE;
3359273d9f13SBarry Smith   }
33600450473dSBarry Smith   B->assembled = PETSC_TRUE;
33613ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3362273d9f13SBarry Smith }
3363273d9f13SBarry Smith 
336465b80a83SHong Zhang #if defined(PETSC_HAVE_ELEMENTAL)
3365d71ae5a4SJacob Faibussowitsch PETSC_INTERN PetscErrorCode MatConvert_SeqDense_Elemental(Mat A, MatType newtype, MatReuse reuse, Mat *newmat)
3366d71ae5a4SJacob Faibussowitsch {
3367d77f618aSHong Zhang   Mat                mat_elemental;
33681683a169SBarry Smith   const PetscScalar *array;
33691683a169SBarry Smith   PetscScalar       *v_colwise;
3370d77f618aSHong Zhang   PetscInt           M = A->rmap->N, N = A->cmap->N, i, j, k, *rows, *cols;
3371d77f618aSHong Zhang 
33728baccfbdSHong Zhang   PetscFunctionBegin;
33739566063dSJacob Faibussowitsch   PetscCall(PetscMalloc3(M * N, &v_colwise, M, &rows, N, &cols));
33749566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArrayRead(A, &array));
3375d77f618aSHong Zhang   /* convert column-wise array into row-wise v_colwise, see MatSetValues_Elemental() */
3376d77f618aSHong Zhang   k = 0;
3377d77f618aSHong Zhang   for (j = 0; j < N; j++) {
3378d77f618aSHong Zhang     cols[j] = j;
3379ad540459SPierre Jolivet     for (i = 0; i < M; i++) v_colwise[j * M + i] = array[k++];
3380d77f618aSHong Zhang   }
3381ad540459SPierre Jolivet   for (i = 0; i < M; i++) rows[i] = i;
33829566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArrayRead(A, &array));
3383d77f618aSHong Zhang 
33849566063dSJacob Faibussowitsch   PetscCall(MatCreate(PetscObjectComm((PetscObject)A), &mat_elemental));
33859566063dSJacob Faibussowitsch   PetscCall(MatSetSizes(mat_elemental, PETSC_DECIDE, PETSC_DECIDE, M, N));
33869566063dSJacob Faibussowitsch   PetscCall(MatSetType(mat_elemental, MATELEMENTAL));
33879566063dSJacob Faibussowitsch   PetscCall(MatSetUp(mat_elemental));
3388d77f618aSHong Zhang 
3389d77f618aSHong Zhang   /* PETSc-Elemental interaface uses axpy for setting off-processor entries, only ADD_VALUES is allowed */
33909566063dSJacob Faibussowitsch   PetscCall(MatSetValues(mat_elemental, M, rows, N, cols, v_colwise, ADD_VALUES));
33919566063dSJacob Faibussowitsch   PetscCall(MatAssemblyBegin(mat_elemental, MAT_FINAL_ASSEMBLY));
33929566063dSJacob Faibussowitsch   PetscCall(MatAssemblyEnd(mat_elemental, MAT_FINAL_ASSEMBLY));
33939566063dSJacob Faibussowitsch   PetscCall(PetscFree3(v_colwise, rows, cols));
3394d77f618aSHong Zhang 
3395511c6705SHong Zhang   if (reuse == MAT_INPLACE_MATRIX) {
33969566063dSJacob Faibussowitsch     PetscCall(MatHeaderReplace(A, &mat_elemental));
3397d77f618aSHong Zhang   } else {
3398d77f618aSHong Zhang     *newmat = mat_elemental;
3399d77f618aSHong Zhang   }
34003ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
34018baccfbdSHong Zhang }
340265b80a83SHong Zhang #endif
34038baccfbdSHong Zhang 
3404d71ae5a4SJacob Faibussowitsch PetscErrorCode MatDenseSetLDA_SeqDense(Mat B, PetscInt lda)
3405d71ae5a4SJacob Faibussowitsch {
34061b807ce4Svictorle   Mat_SeqDense *b = (Mat_SeqDense *)B->data;
34077422da62SJose E. Roman   PetscBool     data;
340821a2c019SBarry Smith 
34091b807ce4Svictorle   PetscFunctionBegin;
34107422da62SJose E. Roman   data = (PetscBool)((B->rmap->n > 0 && B->cmap->n > 0) ? (b->v ? PETSC_TRUE : PETSC_FALSE) : PETSC_FALSE);
3411aed4548fSBarry Smith   PetscCheck(b->user_alloc || !data || b->lda == lda, PETSC_COMM_SELF, PETSC_ERR_ORDER, "LDA cannot be changed after allocation of internal storage");
341208401ef6SPierre 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);
34131b807ce4Svictorle   b->lda = lda;
34143ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
34151b807ce4Svictorle }
34161b807ce4Svictorle 
3417d71ae5a4SJacob Faibussowitsch PetscErrorCode MatCreateMPIMatConcatenateSeqMat_SeqDense(MPI_Comm comm, Mat inmat, PetscInt n, MatReuse scall, Mat *outmat)
3418d71ae5a4SJacob Faibussowitsch {
3419d528f656SJakub Kruzik   PetscFunctionBegin;
34209566063dSJacob Faibussowitsch   PetscCall(MatCreateMPIMatConcatenateSeqMat_MPIDense(comm, inmat, n, scall, outmat));
34213ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3422d528f656SJakub Kruzik }
3423d528f656SJakub Kruzik 
3424d16ceb75SStefano Zampini PetscErrorCode MatDenseCreateColumnVec_Private(Mat A, Vec *v)
3425d16ceb75SStefano Zampini {
3426d16ceb75SStefano Zampini   PetscBool   isstd, iskok, iscuda, iship;
3427d16ceb75SStefano Zampini   PetscMPIInt size;
3428d16ceb75SStefano Zampini #if PetscDefined(HAVE_CUDA) || PetscDefined(HAVE_HIP)
3429d16ceb75SStefano Zampini   /* we pass the data of A, to prevent allocating needless GPU memory the first time VecCUPMPlaceArray is called. */
3430d16ceb75SStefano Zampini   const PetscScalar *a;
3431d16ceb75SStefano Zampini #endif
3432d16ceb75SStefano Zampini 
3433d16ceb75SStefano Zampini   PetscFunctionBegin;
3434d16ceb75SStefano Zampini   *v = NULL;
3435d16ceb75SStefano Zampini   PetscCall(PetscStrcmpAny(A->defaultvectype, &isstd, VECSTANDARD, VECSEQ, VECMPI, ""));
3436d16ceb75SStefano Zampini   PetscCall(PetscStrcmpAny(A->defaultvectype, &iskok, VECKOKKOS, VECSEQKOKKOS, VECMPIKOKKOS, ""));
3437d16ceb75SStefano Zampini   PetscCall(PetscStrcmpAny(A->defaultvectype, &iscuda, VECCUDA, VECSEQCUDA, VECMPICUDA, ""));
3438d16ceb75SStefano Zampini   PetscCall(PetscStrcmpAny(A->defaultvectype, &iship, VECHIP, VECSEQHIP, VECMPIHIP, ""));
3439d16ceb75SStefano Zampini   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)A), &size));
3440d16ceb75SStefano Zampini   if (isstd) {
3441d16ceb75SStefano Zampini     if (size > 1) PetscCall(VecCreateMPIWithArray(PetscObjectComm((PetscObject)A), A->rmap->bs, A->rmap->n, A->rmap->N, NULL, v));
3442d16ceb75SStefano Zampini     else PetscCall(VecCreateSeqWithArray(PetscObjectComm((PetscObject)A), A->rmap->bs, A->rmap->n, NULL, v));
3443d16ceb75SStefano Zampini   } else if (iskok) {
3444d16ceb75SStefano Zampini     PetscCheck(PetscDefined(HAVE_KOKKOS_KERNELS), PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Reconfigure using KOKKOS kernels support");
3445d16ceb75SStefano Zampini #if PetscDefined(HAVE_KOKKOS_KERNELS)
3446d16ceb75SStefano Zampini     if (size > 1) PetscCall(VecCreateMPIKokkosWithArray(PetscObjectComm((PetscObject)A), A->rmap->bs, A->rmap->n, A->rmap->N, NULL, v));
3447d16ceb75SStefano Zampini     else PetscCall(VecCreateSeqKokkosWithArray(PetscObjectComm((PetscObject)A), A->rmap->bs, A->rmap->n, NULL, v));
3448d16ceb75SStefano Zampini #endif
3449d16ceb75SStefano Zampini   } else if (iscuda) {
3450d16ceb75SStefano Zampini     PetscCheck(PetscDefined(HAVE_CUDA), PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Reconfigure using CUDA support");
3451d16ceb75SStefano Zampini #if PetscDefined(HAVE_CUDA)
3452d16ceb75SStefano Zampini     PetscCall(MatDenseCUDAGetArrayRead(A, &a));
3453d16ceb75SStefano Zampini     if (size > 1) PetscCall(VecCreateMPICUDAWithArrays(PetscObjectComm((PetscObject)A), A->rmap->bs, A->rmap->n, A->rmap->N, NULL, a, v));
3454d16ceb75SStefano Zampini     else PetscCall(VecCreateSeqCUDAWithArrays(PetscObjectComm((PetscObject)A), A->rmap->bs, A->rmap->n, NULL, a, v));
3455d16ceb75SStefano Zampini #endif
3456d16ceb75SStefano Zampini   } else if (iship) {
3457d16ceb75SStefano Zampini     PetscCheck(PetscDefined(HAVE_HIP), PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Reconfigure using HIP support");
3458d16ceb75SStefano Zampini #if PetscDefined(HAVE_HIP)
3459d16ceb75SStefano Zampini     PetscCall(MatDenseHIPGetArrayRead(A, &a));
3460d16ceb75SStefano Zampini     if (size > 1) PetscCall(VecCreateMPIHIPWithArrays(PetscObjectComm((PetscObject)A), A->rmap->bs, A->rmap->n, A->rmap->N, NULL, a, v));
3461d16ceb75SStefano Zampini     else PetscCall(VecCreateSeqHIPWithArrays(PetscObjectComm((PetscObject)A), A->rmap->bs, A->rmap->n, NULL, a, v));
3462d16ceb75SStefano Zampini #endif
3463d16ceb75SStefano Zampini   }
3464d16ceb75SStefano Zampini   PetscCheck(*v, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Not coded for type %s", A->defaultvectype);
3465d16ceb75SStefano Zampini   PetscFunctionReturn(PETSC_SUCCESS);
3466d16ceb75SStefano Zampini }
3467d16ceb75SStefano Zampini 
3468d71ae5a4SJacob Faibussowitsch PetscErrorCode MatDenseGetColumnVec_SeqDense(Mat A, PetscInt col, Vec *v)
3469d71ae5a4SJacob Faibussowitsch {
34706947451fSStefano Zampini   Mat_SeqDense *a = (Mat_SeqDense *)A->data;
34716947451fSStefano Zampini 
34726947451fSStefano Zampini   PetscFunctionBegin;
347328b400f6SJacob Faibussowitsch   PetscCheck(!a->vecinuse, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Need to call MatDenseRestoreColumnVec() first");
347428b400f6SJacob Faibussowitsch   PetscCheck(!a->matinuse, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Need to call MatDenseRestoreSubMatrix() first");
3475d16ceb75SStefano Zampini   if (!a->cvec) PetscCall(MatDenseCreateColumnVec_Private(A, &a->cvec));
34766947451fSStefano Zampini   a->vecinuse = col + 1;
34779566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArray(A, (PetscScalar **)&a->ptrinuse));
34789566063dSJacob Faibussowitsch   PetscCall(VecPlaceArray(a->cvec, a->ptrinuse + (size_t)col * (size_t)a->lda));
34796947451fSStefano Zampini   *v = a->cvec;
34803ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
34816947451fSStefano Zampini }
34826947451fSStefano Zampini 
3483d71ae5a4SJacob Faibussowitsch PetscErrorCode MatDenseRestoreColumnVec_SeqDense(Mat A, PetscInt col, Vec *v)
3484d71ae5a4SJacob Faibussowitsch {
34856947451fSStefano Zampini   Mat_SeqDense *a = (Mat_SeqDense *)A->data;
34866947451fSStefano Zampini 
34876947451fSStefano Zampini   PetscFunctionBegin;
348828b400f6SJacob Faibussowitsch   PetscCheck(a->vecinuse, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Need to call MatDenseGetColumnVec() first");
348928b400f6SJacob Faibussowitsch   PetscCheck(a->cvec, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Missing internal column vector");
34906947451fSStefano Zampini   a->vecinuse = 0;
34919566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArray(A, (PetscScalar **)&a->ptrinuse));
34929566063dSJacob Faibussowitsch   PetscCall(VecResetArray(a->cvec));
349375f6d85dSStefano Zampini   if (v) *v = NULL;
34943ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
34956947451fSStefano Zampini }
34966947451fSStefano Zampini 
3497d71ae5a4SJacob Faibussowitsch PetscErrorCode MatDenseGetColumnVecRead_SeqDense(Mat A, PetscInt col, Vec *v)
3498d71ae5a4SJacob Faibussowitsch {
34996947451fSStefano Zampini   Mat_SeqDense *a = (Mat_SeqDense *)A->data;
35006947451fSStefano Zampini 
35016947451fSStefano Zampini   PetscFunctionBegin;
350228b400f6SJacob Faibussowitsch   PetscCheck(!a->vecinuse, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Need to call MatDenseRestoreColumnVec() first");
350328b400f6SJacob Faibussowitsch   PetscCheck(!a->matinuse, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Need to call MatDenseRestoreSubMatrix() first");
3504d16ceb75SStefano Zampini   if (!a->cvec) PetscCall(MatDenseCreateColumnVec_Private(A, &a->cvec));
35056947451fSStefano Zampini   a->vecinuse = col + 1;
35069566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArrayRead(A, &a->ptrinuse));
35078e3a54c0SPierre Jolivet   PetscCall(VecPlaceArray(a->cvec, PetscSafePointerPlusOffset(a->ptrinuse, (size_t)col * (size_t)a->lda)));
35089566063dSJacob Faibussowitsch   PetscCall(VecLockReadPush(a->cvec));
35096947451fSStefano Zampini   *v = a->cvec;
35103ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
35116947451fSStefano Zampini }
35126947451fSStefano Zampini 
3513d71ae5a4SJacob Faibussowitsch PetscErrorCode MatDenseRestoreColumnVecRead_SeqDense(Mat A, PetscInt col, Vec *v)
3514d71ae5a4SJacob Faibussowitsch {
35156947451fSStefano Zampini   Mat_SeqDense *a = (Mat_SeqDense *)A->data;
35166947451fSStefano Zampini 
35176947451fSStefano Zampini   PetscFunctionBegin;
351828b400f6SJacob Faibussowitsch   PetscCheck(a->vecinuse, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Need to call MatDenseGetColumnVec() first");
351928b400f6SJacob Faibussowitsch   PetscCheck(a->cvec, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Missing internal column vector");
35206947451fSStefano Zampini   a->vecinuse = 0;
35219566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArrayRead(A, &a->ptrinuse));
35229566063dSJacob Faibussowitsch   PetscCall(VecLockReadPop(a->cvec));
35239566063dSJacob Faibussowitsch   PetscCall(VecResetArray(a->cvec));
352475f6d85dSStefano Zampini   if (v) *v = NULL;
35253ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
35266947451fSStefano Zampini }
35276947451fSStefano Zampini 
3528d71ae5a4SJacob Faibussowitsch PetscErrorCode MatDenseGetColumnVecWrite_SeqDense(Mat A, PetscInt col, Vec *v)
3529d71ae5a4SJacob Faibussowitsch {
35306947451fSStefano Zampini   Mat_SeqDense *a = (Mat_SeqDense *)A->data;
35316947451fSStefano Zampini 
35326947451fSStefano Zampini   PetscFunctionBegin;
353328b400f6SJacob Faibussowitsch   PetscCheck(!a->vecinuse, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Need to call MatDenseRestoreColumnVec() first");
353428b400f6SJacob Faibussowitsch   PetscCheck(!a->matinuse, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Need to call MatDenseRestoreSubMatrix() first");
3535d16ceb75SStefano Zampini   if (!a->cvec) PetscCall(MatDenseCreateColumnVec_Private(A, &a->cvec));
35366947451fSStefano Zampini   a->vecinuse = col + 1;
35379566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArrayWrite(A, (PetscScalar **)&a->ptrinuse));
35388e3a54c0SPierre Jolivet   PetscCall(VecPlaceArray(a->cvec, PetscSafePointerPlusOffset(a->ptrinuse, (size_t)col * (size_t)a->lda)));
35396947451fSStefano Zampini   *v = a->cvec;
35403ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
35416947451fSStefano Zampini }
35426947451fSStefano Zampini 
3543d71ae5a4SJacob Faibussowitsch PetscErrorCode MatDenseRestoreColumnVecWrite_SeqDense(Mat A, PetscInt col, Vec *v)
3544d71ae5a4SJacob Faibussowitsch {
35456947451fSStefano Zampini   Mat_SeqDense *a = (Mat_SeqDense *)A->data;
35466947451fSStefano Zampini 
35476947451fSStefano Zampini   PetscFunctionBegin;
354828b400f6SJacob Faibussowitsch   PetscCheck(a->vecinuse, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Need to call MatDenseGetColumnVec() first");
354928b400f6SJacob Faibussowitsch   PetscCheck(a->cvec, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Missing internal column vector");
35506947451fSStefano Zampini   a->vecinuse = 0;
35519566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArrayWrite(A, (PetscScalar **)&a->ptrinuse));
35529566063dSJacob Faibussowitsch   PetscCall(VecResetArray(a->cvec));
355375f6d85dSStefano Zampini   if (v) *v = NULL;
35543ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
35556947451fSStefano Zampini }
35566947451fSStefano Zampini 
3557d71ae5a4SJacob Faibussowitsch PetscErrorCode MatDenseGetSubMatrix_SeqDense(Mat A, PetscInt rbegin, PetscInt rend, PetscInt cbegin, PetscInt cend, Mat *v)
3558d71ae5a4SJacob Faibussowitsch {
35595ea7661aSPierre Jolivet   Mat_SeqDense *a = (Mat_SeqDense *)A->data;
35605ea7661aSPierre Jolivet 
35615ea7661aSPierre Jolivet   PetscFunctionBegin;
356228b400f6SJacob Faibussowitsch   PetscCheck(!a->vecinuse, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Need to call MatDenseRestoreColumnVec() first");
356328b400f6SJacob Faibussowitsch   PetscCheck(!a->matinuse, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Need to call MatDenseRestoreSubMatrix() first");
3564a2748737SPierre Jolivet   if (a->cmat && (cend - cbegin != a->cmat->cmap->N || rend - rbegin != a->cmat->rmap->N)) PetscCall(MatDestroy(&a->cmat));
35655ea7661aSPierre Jolivet   if (!a->cmat) {
35668e3a54c0SPierre 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));
35675ea7661aSPierre Jolivet   } else {
35688e3a54c0SPierre Jolivet     PetscCall(MatDensePlaceArray(a->cmat, PetscSafePointerPlusOffset(a->v, rbegin + (size_t)cbegin * a->lda)));
35695ea7661aSPierre Jolivet   }
35709566063dSJacob Faibussowitsch   PetscCall(MatDenseSetLDA(a->cmat, a->lda));
35715ea7661aSPierre Jolivet   a->matinuse = cbegin + 1;
35725ea7661aSPierre Jolivet   *v          = a->cmat;
357347d993e7Ssuyashtn #if defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
357475f6d85dSStefano Zampini   A->offloadmask = PETSC_OFFLOAD_CPU;
357575f6d85dSStefano Zampini #endif
35763ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
35775ea7661aSPierre Jolivet }
35785ea7661aSPierre Jolivet 
3579d71ae5a4SJacob Faibussowitsch PetscErrorCode MatDenseRestoreSubMatrix_SeqDense(Mat A, Mat *v)
3580d71ae5a4SJacob Faibussowitsch {
35815ea7661aSPierre Jolivet   Mat_SeqDense *a = (Mat_SeqDense *)A->data;
35825ea7661aSPierre Jolivet 
35835ea7661aSPierre Jolivet   PetscFunctionBegin;
358428b400f6SJacob Faibussowitsch   PetscCheck(a->matinuse, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Need to call MatDenseGetSubMatrix() first");
358528b400f6SJacob Faibussowitsch   PetscCheck(a->cmat, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Missing internal column matrix");
358608401ef6SPierre Jolivet   PetscCheck(*v == a->cmat, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Not the matrix obtained from MatDenseGetSubMatrix()");
35875ea7661aSPierre Jolivet   a->matinuse = 0;
35889566063dSJacob Faibussowitsch   PetscCall(MatDenseResetArray(a->cmat));
3589742765d3SMatthew Knepley   if (v) *v = NULL;
359047d993e7Ssuyashtn #if defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
35913faff063SStefano Zampini   A->offloadmask = PETSC_OFFLOAD_CPU;
35923faff063SStefano Zampini #endif
35933ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
35945ea7661aSPierre Jolivet }
35955ea7661aSPierre Jolivet 
35960bad9183SKris Buschelman /*MC
3597fafad747SKris Buschelman    MATSEQDENSE - MATSEQDENSE = "seqdense" - A matrix type to be used for sequential dense matrices.
35980bad9183SKris Buschelman 
35992ef1f0ffSBarry Smith    Options Database Key:
360011a5261eSBarry Smith . -mat_type seqdense - sets the matrix type to `MATSEQDENSE` during a call to `MatSetFromOptions()`
36010bad9183SKris Buschelman 
36020bad9183SKris Buschelman   Level: beginner
36030bad9183SKris Buschelman 
36041cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATSEQDENSE`, `MatCreateSeqDense()`
36050bad9183SKris Buschelman M*/
3606d71ae5a4SJacob Faibussowitsch PetscErrorCode MatCreate_SeqDense(Mat B)
3607d71ae5a4SJacob Faibussowitsch {
3608273d9f13SBarry Smith   Mat_SeqDense *b;
36097c334f02SBarry Smith   PetscMPIInt   size;
3610273d9f13SBarry Smith 
3611273d9f13SBarry Smith   PetscFunctionBegin;
36129566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)B), &size));
361308401ef6SPierre Jolivet   PetscCheck(size <= 1, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Comm must be of size 1");
361455659b69SBarry Smith 
36154dfa11a4SJacob Faibussowitsch   PetscCall(PetscNew(&b));
361644cd7ae7SLois Curfman McInnes   B->data   = (void *)b;
3617aea10558SJacob Faibussowitsch   B->ops[0] = MatOps_Values;
361818f449edSLois Curfman McInnes 
3619273d9f13SBarry Smith   b->roworiented = PETSC_TRUE;
36204e220ebcSLois Curfman McInnes 
36219566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatQRFactor_C", MatQRFactor_SeqDense));
36229566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatDenseGetLDA_C", MatDenseGetLDA_SeqDense));
36239566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatDenseSetLDA_C", MatDenseSetLDA_SeqDense));
36249566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatDenseGetArray_C", MatDenseGetArray_SeqDense));
36259566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatDenseRestoreArray_C", MatDenseRestoreArray_SeqDense));
36269566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatDensePlaceArray_C", MatDensePlaceArray_SeqDense));
36279566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatDenseResetArray_C", MatDenseResetArray_SeqDense));
36289566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatDenseReplaceArray_C", MatDenseReplaceArray_SeqDense));
36299566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatDenseGetArrayRead_C", MatDenseGetArray_SeqDense));
36309566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatDenseRestoreArrayRead_C", MatDenseRestoreArray_SeqDense));
36319566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatDenseGetArrayWrite_C", MatDenseGetArray_SeqDense));
36329566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatDenseRestoreArrayWrite_C", MatDenseRestoreArray_SeqDense));
36339566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatConvert_seqdense_seqaij_C", MatConvert_SeqDense_SeqAIJ));
36348baccfbdSHong Zhang #if defined(PETSC_HAVE_ELEMENTAL)
36359566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatConvert_seqdense_elemental_C", MatConvert_SeqDense_Elemental));
36368baccfbdSHong Zhang #endif
3637d24d4204SJose E. Roman #if defined(PETSC_HAVE_SCALAPACK)
36389566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatConvert_seqdense_scalapack_C", MatConvert_Dense_ScaLAPACK));
3639d24d4204SJose E. Roman #endif
36402bf066beSStefano Zampini #if defined(PETSC_HAVE_CUDA)
36419566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatConvert_seqdense_seqdensecuda_C", MatConvert_SeqDense_SeqDenseCUDA));
36429566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatProductSetFromOptions_seqdensecuda_seqdensecuda_C", MatProductSetFromOptions_SeqDense));
36439566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatProductSetFromOptions_seqdensecuda_seqdense_C", MatProductSetFromOptions_SeqDense));
36449566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatProductSetFromOptions_seqdense_seqdensecuda_C", MatProductSetFromOptions_SeqDense));
36452bf066beSStefano Zampini #endif
364647d993e7Ssuyashtn #if defined(PETSC_HAVE_HIP)
364747d993e7Ssuyashtn   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatConvert_seqdense_seqdensehip_C", MatConvert_SeqDense_SeqDenseHIP));
364847d993e7Ssuyashtn   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatProductSetFromOptions_seqdensehip_seqdensehip_C", MatProductSetFromOptions_SeqDense));
364947d993e7Ssuyashtn   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatProductSetFromOptions_seqdensehip_seqdense_C", MatProductSetFromOptions_SeqDense));
365047d993e7Ssuyashtn   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatProductSetFromOptions_seqdense_seqdensehip_C", MatProductSetFromOptions_SeqDense));
365147d993e7Ssuyashtn #endif
36529566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatSeqDenseSetPreallocation_C", MatSeqDenseSetPreallocation_SeqDense));
36539566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatProductSetFromOptions_seqaij_seqdense_C", MatProductSetFromOptions_SeqAIJ_SeqDense));
36549566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatProductSetFromOptions_seqdense_seqdense_C", MatProductSetFromOptions_SeqDense));
36559566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatProductSetFromOptions_seqbaij_seqdense_C", MatProductSetFromOptions_SeqXBAIJ_SeqDense));
36569566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatProductSetFromOptions_seqsbaij_seqdense_C", MatProductSetFromOptions_SeqXBAIJ_SeqDense));
365796e6d5c4SRichard Tran Mills 
36589566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatDenseGetColumn_C", MatDenseGetColumn_SeqDense));
36599566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatDenseRestoreColumn_C", MatDenseRestoreColumn_SeqDense));
36609566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatDenseGetColumnVec_C", MatDenseGetColumnVec_SeqDense));
36619566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatDenseRestoreColumnVec_C", MatDenseRestoreColumnVec_SeqDense));
36629566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatDenseGetColumnVecRead_C", MatDenseGetColumnVecRead_SeqDense));
36639566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatDenseRestoreColumnVecRead_C", MatDenseRestoreColumnVecRead_SeqDense));
36649566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatDenseGetColumnVecWrite_C", MatDenseGetColumnVecWrite_SeqDense));
36659566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatDenseRestoreColumnVecWrite_C", MatDenseRestoreColumnVecWrite_SeqDense));
36669566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatDenseGetSubMatrix_C", MatDenseGetSubMatrix_SeqDense));
36679566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatDenseRestoreSubMatrix_C", MatDenseRestoreSubMatrix_SeqDense));
3668*0be0d8bdSHansol Suh   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatMultAddColumnRange_C", MatMultAddColumnRange_SeqDense));
3669*0be0d8bdSHansol Suh   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatMultHermitianTransposeColumnRange_C", MatMultHermitianTransposeColumnRange_SeqDense));
3670*0be0d8bdSHansol Suh   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatMultHermitianTransposeAddColumnRange_C", MatMultHermitianTransposeAddColumnRange_SeqDense));
36719566063dSJacob Faibussowitsch   PetscCall(PetscObjectChangeTypeName((PetscObject)B, MATSEQDENSE));
36723ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3673289bc588SBarry Smith }
367486aefd0dSHong Zhang 
367586aefd0dSHong Zhang /*@C
367611a5261eSBarry 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.
367786aefd0dSHong Zhang 
367886aefd0dSHong Zhang   Not Collective
367986aefd0dSHong Zhang 
36805ea7661aSPierre Jolivet   Input Parameters:
3681fe59aa6dSJacob Faibussowitsch + A   - a `MATSEQDENSE` or `MATMPIDENSE` matrix
368286aefd0dSHong Zhang - col - column index
368386aefd0dSHong Zhang 
368486aefd0dSHong Zhang   Output Parameter:
368586aefd0dSHong Zhang . vals - pointer to the data
368686aefd0dSHong Zhang 
368786aefd0dSHong Zhang   Level: intermediate
368886aefd0dSHong Zhang 
368911a5261eSBarry Smith   Note:
369011a5261eSBarry Smith   Use `MatDenseGetColumnVec()` to get access to a column of a `MATDENSE` treated as a `Vec`
369111a5261eSBarry Smith 
36921cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATDENSE`, `MatDenseRestoreColumn()`, `MatDenseGetColumnVec()`
369386aefd0dSHong Zhang @*/
3694d71ae5a4SJacob Faibussowitsch PetscErrorCode MatDenseGetColumn(Mat A, PetscInt col, PetscScalar **vals)
3695d71ae5a4SJacob Faibussowitsch {
369686aefd0dSHong Zhang   PetscFunctionBegin;
3697d5ea218eSStefano Zampini   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
3698d5ea218eSStefano Zampini   PetscValidLogicalCollectiveInt(A, col, 2);
36994f572ea9SToby Isaac   PetscAssertPointer(vals, 3);
3700cac4c232SBarry Smith   PetscUseMethod(A, "MatDenseGetColumn_C", (Mat, PetscInt, PetscScalar **), (A, col, vals));
37013ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
370286aefd0dSHong Zhang }
370386aefd0dSHong Zhang 
370486aefd0dSHong Zhang /*@C
370511a5261eSBarry Smith   MatDenseRestoreColumn - returns access to a column of a `MATDENSE` matrix which is returned by `MatDenseGetColumn()`.
370686aefd0dSHong Zhang 
370786aefd0dSHong Zhang   Not Collective
370886aefd0dSHong Zhang 
3709742765d3SMatthew Knepley   Input Parameters:
3710fe59aa6dSJacob Faibussowitsch + A    - a `MATSEQDENSE` or `MATMPIDENSE` matrix
37112ef1f0ffSBarry Smith - vals - pointer to the data (may be `NULL`)
371286aefd0dSHong Zhang 
371386aefd0dSHong Zhang   Level: intermediate
371486aefd0dSHong Zhang 
37151cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATDENSE`, `MatDenseGetColumn()`
371686aefd0dSHong Zhang @*/
3717d71ae5a4SJacob Faibussowitsch PetscErrorCode MatDenseRestoreColumn(Mat A, PetscScalar **vals)
3718d71ae5a4SJacob Faibussowitsch {
371986aefd0dSHong Zhang   PetscFunctionBegin;
3720d5ea218eSStefano Zampini   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
37214f572ea9SToby Isaac   PetscAssertPointer(vals, 2);
3722cac4c232SBarry Smith   PetscUseMethod(A, "MatDenseRestoreColumn_C", (Mat, PetscScalar **), (A, vals));
37233ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
372486aefd0dSHong Zhang }
37256947451fSStefano Zampini 
37260f74d2c1SSatish Balay /*@
372711a5261eSBarry Smith   MatDenseGetColumnVec - Gives read-write access to a column of a `MATDENSE` matrix, represented as a `Vec`.
37286947451fSStefano Zampini 
37296947451fSStefano Zampini   Collective
37306947451fSStefano Zampini 
37315ea7661aSPierre Jolivet   Input Parameters:
3732fe59aa6dSJacob Faibussowitsch + A   - the `Mat` object
37336947451fSStefano Zampini - col - the column index
37346947451fSStefano Zampini 
37356947451fSStefano Zampini   Output Parameter:
37366947451fSStefano Zampini . v - the vector
37376947451fSStefano Zampini 
37382ef1f0ffSBarry Smith   Level: intermediate
37392ef1f0ffSBarry Smith 
37406947451fSStefano Zampini   Notes:
374111a5261eSBarry Smith   The vector is owned by PETSc. Users need to call `MatDenseRestoreColumnVec()` when the vector is no longer needed.
374211a5261eSBarry Smith 
374311a5261eSBarry Smith   Use `MatDenseGetColumnVecRead()` to obtain read-only access or `MatDenseGetColumnVecWrite()` for write-only access.
37446947451fSStefano Zampini 
37451cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATDENSE`, `MATDENSECUDA`, `MATDENSEHIP`, `MatDenseGetColumnVecRead()`, `MatDenseGetColumnVecWrite()`, `MatDenseRestoreColumnVec()`, `MatDenseRestoreColumnVecRead()`, `MatDenseRestoreColumnVecWrite()`, `MatDenseGetColumn()`
37466947451fSStefano Zampini @*/
3747d71ae5a4SJacob Faibussowitsch PetscErrorCode MatDenseGetColumnVec(Mat A, PetscInt col, Vec *v)
3748d71ae5a4SJacob Faibussowitsch {
37496947451fSStefano Zampini   PetscFunctionBegin;
37506947451fSStefano Zampini   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
37516947451fSStefano Zampini   PetscValidType(A, 1);
37526947451fSStefano Zampini   PetscValidLogicalCollectiveInt(A, col, 2);
37534f572ea9SToby Isaac   PetscAssertPointer(v, 3);
375428b400f6SJacob Faibussowitsch   PetscCheck(A->preallocated, PetscObjectComm((PetscObject)A), PETSC_ERR_ORDER, "Matrix not preallocated");
37552cf15c64SPierre 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);
3756cac4c232SBarry Smith   PetscUseMethod(A, "MatDenseGetColumnVec_C", (Mat, PetscInt, Vec *), (A, col, v));
37573ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
37586947451fSStefano Zampini }
37596947451fSStefano Zampini 
37600f74d2c1SSatish Balay /*@
3761fb850c59SBarry Smith   MatDenseRestoreColumnVec - Returns access to a column of a dense matrix obtained from `MatDenseGetColumnVec()`.
37626947451fSStefano Zampini 
37636947451fSStefano Zampini   Collective
37646947451fSStefano Zampini 
37655ea7661aSPierre Jolivet   Input Parameters:
3766fb850c59SBarry Smith + A   - the `Mat` object
37676947451fSStefano Zampini . col - the column index
3768fb850c59SBarry Smith - v   - the `Vec` object (may be `NULL`)
37696947451fSStefano Zampini 
37706947451fSStefano Zampini   Level: intermediate
37716947451fSStefano Zampini 
37721cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATDENSE`, `MATDENSECUDA`, `MATDENSEHIP`, `MatDenseGetColumnVec()`, `MatDenseGetColumnVecRead()`, `MatDenseGetColumnVecWrite()`, `MatDenseRestoreColumnVecRead()`, `MatDenseRestoreColumnVecWrite()`
37736947451fSStefano Zampini @*/
3774d71ae5a4SJacob Faibussowitsch PetscErrorCode MatDenseRestoreColumnVec(Mat A, PetscInt col, Vec *v)
3775d71ae5a4SJacob Faibussowitsch {
37766947451fSStefano Zampini   PetscFunctionBegin;
37776947451fSStefano Zampini   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
37786947451fSStefano Zampini   PetscValidType(A, 1);
37796947451fSStefano Zampini   PetscValidLogicalCollectiveInt(A, col, 2);
378008401ef6SPierre Jolivet   PetscCheck(A->preallocated, PetscObjectComm((PetscObject)A), PETSC_ERR_ORDER, "Matrix not preallocated");
37812cf15c64SPierre 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);
3782cac4c232SBarry Smith   PetscUseMethod(A, "MatDenseRestoreColumnVec_C", (Mat, PetscInt, Vec *), (A, col, v));
37833ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
37846947451fSStefano Zampini }
37856947451fSStefano Zampini 
37860f74d2c1SSatish Balay /*@
3787fb850c59SBarry Smith   MatDenseGetColumnVecRead - Gives read-only access to a column of a dense matrix, represented as a `Vec`.
37886947451fSStefano Zampini 
37896947451fSStefano Zampini   Collective
37906947451fSStefano Zampini 
37915ea7661aSPierre Jolivet   Input Parameters:
3792fe59aa6dSJacob Faibussowitsch + A   - the `Mat` object
37936947451fSStefano Zampini - col - the column index
37946947451fSStefano Zampini 
37956947451fSStefano Zampini   Output Parameter:
37966947451fSStefano Zampini . v - the vector
37976947451fSStefano Zampini 
37982ef1f0ffSBarry Smith   Level: intermediate
37992ef1f0ffSBarry Smith 
38006947451fSStefano Zampini   Notes:
38016947451fSStefano Zampini   The vector is owned by PETSc and users cannot modify it.
380211a5261eSBarry Smith 
38032ef1f0ffSBarry Smith   Users need to call `MatDenseRestoreColumnVecRead()` when the vector is no longer needed.
380411a5261eSBarry Smith 
38052ef1f0ffSBarry Smith   Use `MatDenseGetColumnVec()` to obtain read-write access or `MatDenseGetColumnVecWrite()` for write-only access.
38066947451fSStefano Zampini 
38071cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATDENSE`, `MATDENSECUDA`, `MATDENSEHIP`, `MatDenseGetColumnVec()`, `MatDenseGetColumnVecWrite()`, `MatDenseRestoreColumnVec()`, `MatDenseRestoreColumnVecRead()`, `MatDenseRestoreColumnVecWrite()`
38086947451fSStefano Zampini @*/
3809d71ae5a4SJacob Faibussowitsch PetscErrorCode MatDenseGetColumnVecRead(Mat A, PetscInt col, Vec *v)
3810d71ae5a4SJacob Faibussowitsch {
38116947451fSStefano Zampini   PetscFunctionBegin;
38126947451fSStefano Zampini   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
38136947451fSStefano Zampini   PetscValidType(A, 1);
38146947451fSStefano Zampini   PetscValidLogicalCollectiveInt(A, col, 2);
38154f572ea9SToby Isaac   PetscAssertPointer(v, 3);
381628b400f6SJacob Faibussowitsch   PetscCheck(A->preallocated, PetscObjectComm((PetscObject)A), PETSC_ERR_ORDER, "Matrix not preallocated");
38172cf15c64SPierre 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);
3818cac4c232SBarry Smith   PetscUseMethod(A, "MatDenseGetColumnVecRead_C", (Mat, PetscInt, Vec *), (A, col, v));
38193ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
38206947451fSStefano Zampini }
38216947451fSStefano Zampini 
38220f74d2c1SSatish Balay /*@
3823fb850c59SBarry Smith   MatDenseRestoreColumnVecRead - Returns access to a column of a dense matrix obtained from `MatDenseGetColumnVecRead()`.
38246947451fSStefano Zampini 
38256947451fSStefano Zampini   Collective
38266947451fSStefano Zampini 
38275ea7661aSPierre Jolivet   Input Parameters:
3828fe59aa6dSJacob Faibussowitsch + A   - the `Mat` object
38296947451fSStefano Zampini . col - the column index
3830fb850c59SBarry Smith - v   - the `Vec` object (may be `NULL`)
38316947451fSStefano Zampini 
38326947451fSStefano Zampini   Level: intermediate
38336947451fSStefano Zampini 
38341cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATDENSE`, `MATDENSECUDA`, `MATDENSEHIP`, `MatDenseGetColumnVec()`, `MatDenseGetColumnVecRead()`, `MatDenseGetColumnVecWrite()`, `MatDenseRestoreColumnVec()`, `MatDenseRestoreColumnVecWrite()`
38356947451fSStefano Zampini @*/
3836d71ae5a4SJacob Faibussowitsch PetscErrorCode MatDenseRestoreColumnVecRead(Mat A, PetscInt col, Vec *v)
3837d71ae5a4SJacob Faibussowitsch {
38386947451fSStefano Zampini   PetscFunctionBegin;
38396947451fSStefano Zampini   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
38406947451fSStefano Zampini   PetscValidType(A, 1);
38416947451fSStefano Zampini   PetscValidLogicalCollectiveInt(A, col, 2);
384208401ef6SPierre Jolivet   PetscCheck(A->preallocated, PetscObjectComm((PetscObject)A), PETSC_ERR_ORDER, "Matrix not preallocated");
38432cf15c64SPierre 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);
3844cac4c232SBarry Smith   PetscUseMethod(A, "MatDenseRestoreColumnVecRead_C", (Mat, PetscInt, Vec *), (A, col, v));
38453ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
38466947451fSStefano Zampini }
38476947451fSStefano Zampini 
38480f74d2c1SSatish Balay /*@
3849fb850c59SBarry Smith   MatDenseGetColumnVecWrite - Gives write-only access to a column of a dense matrix, represented as a `Vec`.
38506947451fSStefano Zampini 
38516947451fSStefano Zampini   Collective
38526947451fSStefano Zampini 
38535ea7661aSPierre Jolivet   Input Parameters:
3854fe59aa6dSJacob Faibussowitsch + A   - the `Mat` object
38556947451fSStefano Zampini - col - the column index
38566947451fSStefano Zampini 
38576947451fSStefano Zampini   Output Parameter:
38586947451fSStefano Zampini . v - the vector
38596947451fSStefano Zampini 
38606947451fSStefano Zampini   Level: intermediate
38616947451fSStefano Zampini 
38622ef1f0ffSBarry Smith   Notes:
38632ef1f0ffSBarry Smith   The vector is owned by PETSc. Users need to call `MatDenseRestoreColumnVecWrite()` when the vector is no longer needed.
38642ef1f0ffSBarry Smith 
38652ef1f0ffSBarry Smith   Use `MatDenseGetColumnVec()` to obtain read-write access or `MatDenseGetColumnVecRead()` for read-only access.
38662ef1f0ffSBarry Smith 
38671cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATDENSE`, `MATDENSECUDA`, `MATDENSEHIP`, `MatDenseGetColumnVec()`, `MatDenseGetColumnVecRead()`, `MatDenseRestoreColumnVec()`, `MatDenseRestoreColumnVecRead()`, `MatDenseRestoreColumnVecWrite()`
38686947451fSStefano Zampini @*/
3869d71ae5a4SJacob Faibussowitsch PetscErrorCode MatDenseGetColumnVecWrite(Mat A, PetscInt col, Vec *v)
3870d71ae5a4SJacob Faibussowitsch {
38716947451fSStefano Zampini   PetscFunctionBegin;
38726947451fSStefano Zampini   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
38736947451fSStefano Zampini   PetscValidType(A, 1);
38746947451fSStefano Zampini   PetscValidLogicalCollectiveInt(A, col, 2);
38754f572ea9SToby Isaac   PetscAssertPointer(v, 3);
387628b400f6SJacob Faibussowitsch   PetscCheck(A->preallocated, PetscObjectComm((PetscObject)A), PETSC_ERR_ORDER, "Matrix not preallocated");
3877aed4548fSBarry 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);
3878cac4c232SBarry Smith   PetscUseMethod(A, "MatDenseGetColumnVecWrite_C", (Mat, PetscInt, Vec *), (A, col, v));
38793ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
38806947451fSStefano Zampini }
38816947451fSStefano Zampini 
38820f74d2c1SSatish Balay /*@
3883fb850c59SBarry Smith   MatDenseRestoreColumnVecWrite - Returns access to a column of a dense matrix obtained from `MatDenseGetColumnVecWrite()`.
38846947451fSStefano Zampini 
38856947451fSStefano Zampini   Collective
38866947451fSStefano Zampini 
38875ea7661aSPierre Jolivet   Input Parameters:
3888fe59aa6dSJacob Faibussowitsch + A   - the `Mat` object
38896947451fSStefano Zampini . col - the column index
38902ef1f0ffSBarry Smith - v   - the `Vec` object (may be `NULL`)
38916947451fSStefano Zampini 
38926947451fSStefano Zampini   Level: intermediate
38936947451fSStefano Zampini 
38941cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATDENSE`, `MATDENSECUDA`, `MATDENSEHIP`, `MatDenseGetColumnVec()`, `MatDenseGetColumnVecRead()`, `MatDenseGetColumnVecWrite()`, `MatDenseRestoreColumnVec()`, `MatDenseRestoreColumnVecRead()`
38956947451fSStefano Zampini @*/
3896d71ae5a4SJacob Faibussowitsch PetscErrorCode MatDenseRestoreColumnVecWrite(Mat A, PetscInt col, Vec *v)
3897d71ae5a4SJacob Faibussowitsch {
38986947451fSStefano Zampini   PetscFunctionBegin;
38996947451fSStefano Zampini   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
39006947451fSStefano Zampini   PetscValidType(A, 1);
39016947451fSStefano Zampini   PetscValidLogicalCollectiveInt(A, col, 2);
390208401ef6SPierre Jolivet   PetscCheck(A->preallocated, PetscObjectComm((PetscObject)A), PETSC_ERR_ORDER, "Matrix not preallocated");
3903aed4548fSBarry 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);
3904cac4c232SBarry Smith   PetscUseMethod(A, "MatDenseRestoreColumnVecWrite_C", (Mat, PetscInt, Vec *), (A, col, v));
39053ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
39066947451fSStefano Zampini }
39075ea7661aSPierre Jolivet 
39080f74d2c1SSatish Balay /*@
3909fb850c59SBarry Smith   MatDenseGetSubMatrix - Gives access to a block of rows and columns of a dense matrix, represented as a `Mat`.
39105ea7661aSPierre Jolivet 
39115ea7661aSPierre Jolivet   Collective
39125ea7661aSPierre Jolivet 
39135ea7661aSPierre Jolivet   Input Parameters:
3914fb850c59SBarry Smith + A      - the `Mat` object
39152ef1f0ffSBarry Smith . rbegin - the first global row index in the block (if `PETSC_DECIDE`, is 0)
39162ef1f0ffSBarry Smith . rend   - the global row index past the last one in the block (if `PETSC_DECIDE`, is `M`)
39172ef1f0ffSBarry Smith . cbegin - the first global column index in the block (if `PETSC_DECIDE`, is 0)
39182ef1f0ffSBarry Smith - cend   - the global column index past the last one in the block (if `PETSC_DECIDE`, is `N`)
39195ea7661aSPierre Jolivet 
39205ea7661aSPierre Jolivet   Output Parameter:
39215ea7661aSPierre Jolivet . v - the matrix
39225ea7661aSPierre Jolivet 
39235ea7661aSPierre Jolivet   Level: intermediate
39245ea7661aSPierre Jolivet 
39252ef1f0ffSBarry Smith   Notes:
39262ef1f0ffSBarry Smith   The matrix is owned by PETSc. Users need to call `MatDenseRestoreSubMatrix()` when the matrix is no longer needed.
39272ef1f0ffSBarry Smith 
39282ef1f0ffSBarry 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.
39292ef1f0ffSBarry Smith 
39301cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATDENSE`, `MATDENSECUDA`, `MATDENSEHIP`, `MatDenseGetColumnVec()`, `MatDenseRestoreColumnVec()`, `MatDenseRestoreSubMatrix()`
39315ea7661aSPierre Jolivet @*/
3932d71ae5a4SJacob Faibussowitsch PetscErrorCode MatDenseGetSubMatrix(Mat A, PetscInt rbegin, PetscInt rend, PetscInt cbegin, PetscInt cend, Mat *v)
3933d71ae5a4SJacob Faibussowitsch {
39345ea7661aSPierre Jolivet   PetscFunctionBegin;
39355ea7661aSPierre Jolivet   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
39365ea7661aSPierre Jolivet   PetscValidType(A, 1);
3937a2748737SPierre Jolivet   PetscValidLogicalCollectiveInt(A, rbegin, 2);
3938a2748737SPierre Jolivet   PetscValidLogicalCollectiveInt(A, rend, 3);
3939a2748737SPierre Jolivet   PetscValidLogicalCollectiveInt(A, cbegin, 4);
3940a2748737SPierre Jolivet   PetscValidLogicalCollectiveInt(A, cend, 5);
39414f572ea9SToby Isaac   PetscAssertPointer(v, 6);
3942a2748737SPierre Jolivet   if (rbegin == PETSC_DECIDE) rbegin = 0;
3943a2748737SPierre Jolivet   if (rend == PETSC_DECIDE) rend = A->rmap->N;
3944a2748737SPierre Jolivet   if (cbegin == PETSC_DECIDE) cbegin = 0;
3945a2748737SPierre Jolivet   if (cend == PETSC_DECIDE) cend = A->cmap->N;
394628b400f6SJacob Faibussowitsch   PetscCheck(A->preallocated, PetscObjectComm((PetscObject)A), PETSC_ERR_ORDER, "Matrix not preallocated");
3947a2748737SPierre 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);
3948a2748737SPierre 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);
3949a2748737SPierre 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);
3950a2748737SPierre 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);
3951a2748737SPierre Jolivet   PetscUseMethod(A, "MatDenseGetSubMatrix_C", (Mat, PetscInt, PetscInt, PetscInt, PetscInt, Mat *), (A, rbegin, rend, cbegin, cend, v));
39523ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
39535ea7661aSPierre Jolivet }
39545ea7661aSPierre Jolivet 
39550f74d2c1SSatish Balay /*@
3956fb850c59SBarry Smith   MatDenseRestoreSubMatrix - Returns access to a block of columns of a dense matrix obtained from `MatDenseGetSubMatrix()`.
39575ea7661aSPierre Jolivet 
39585ea7661aSPierre Jolivet   Collective
39595ea7661aSPierre Jolivet 
39605ea7661aSPierre Jolivet   Input Parameters:
3961fe59aa6dSJacob Faibussowitsch + A - the `Mat` object
39622ef1f0ffSBarry Smith - v - the `Mat` object (may be `NULL`)
39635ea7661aSPierre Jolivet 
39645ea7661aSPierre Jolivet   Level: intermediate
39655ea7661aSPierre Jolivet 
39661cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATDENSE`, `MATDENSECUDA`, `MATDENSEHIP`, `MatDenseGetColumnVec()`, `MatDenseRestoreColumnVec()`, `MatDenseGetSubMatrix()`
39675ea7661aSPierre Jolivet @*/
3968d71ae5a4SJacob Faibussowitsch PetscErrorCode MatDenseRestoreSubMatrix(Mat A, Mat *v)
3969d71ae5a4SJacob Faibussowitsch {
39705ea7661aSPierre Jolivet   PetscFunctionBegin;
39715ea7661aSPierre Jolivet   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
39725ea7661aSPierre Jolivet   PetscValidType(A, 1);
39734f572ea9SToby Isaac   PetscAssertPointer(v, 2);
3974cac4c232SBarry Smith   PetscUseMethod(A, "MatDenseRestoreSubMatrix_C", (Mat, Mat *), (A, v));
39753ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
39765ea7661aSPierre Jolivet }
39778a9c020eSBarry Smith 
39788a9c020eSBarry Smith #include <petscblaslapack.h>
39798a9c020eSBarry Smith #include <petsc/private/kernels/blockinvert.h>
39808a9c020eSBarry Smith 
3981d71ae5a4SJacob Faibussowitsch PetscErrorCode MatSeqDenseInvert(Mat A)
3982d71ae5a4SJacob Faibussowitsch {
3983d63b1753SJacob Faibussowitsch   PetscInt        m;
39848a9c020eSBarry Smith   const PetscReal shift = 0.0;
3985d63b1753SJacob Faibussowitsch   PetscBool       allowzeropivot, zeropivotdetected = PETSC_FALSE;
3986d63b1753SJacob Faibussowitsch   PetscScalar    *values;
39878a9c020eSBarry Smith 
39888a9c020eSBarry Smith   PetscFunctionBegin;
3989d63b1753SJacob Faibussowitsch   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
3990d63b1753SJacob Faibussowitsch   PetscCall(MatDenseGetArray(A, &values));
3991d63b1753SJacob Faibussowitsch   PetscCall(MatGetLocalSize(A, &m, NULL));
3992d63b1753SJacob Faibussowitsch   allowzeropivot = PetscNot(A->erroriffailure);
39938a9c020eSBarry Smith   /* factor and invert each block */
3994d63b1753SJacob Faibussowitsch   switch (m) {
3995d71ae5a4SJacob Faibussowitsch   case 1:
3996d71ae5a4SJacob Faibussowitsch     values[0] = (PetscScalar)1.0 / (values[0] + shift);
3997d71ae5a4SJacob Faibussowitsch     break;
39988a9c020eSBarry Smith   case 2:
39998a9c020eSBarry Smith     PetscCall(PetscKernel_A_gets_inverse_A_2(values, shift, allowzeropivot, &zeropivotdetected));
40008a9c020eSBarry Smith     if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
40018a9c020eSBarry Smith     break;
40028a9c020eSBarry Smith   case 3:
40038a9c020eSBarry Smith     PetscCall(PetscKernel_A_gets_inverse_A_3(values, shift, allowzeropivot, &zeropivotdetected));
40048a9c020eSBarry Smith     if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
40058a9c020eSBarry Smith     break;
40068a9c020eSBarry Smith   case 4:
40078a9c020eSBarry Smith     PetscCall(PetscKernel_A_gets_inverse_A_4(values, shift, allowzeropivot, &zeropivotdetected));
40088a9c020eSBarry Smith     if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
40098a9c020eSBarry Smith     break;
40109371c9d4SSatish Balay   case 5: {
40118a9c020eSBarry Smith     PetscScalar work[25];
40128a9c020eSBarry Smith     PetscInt    ipvt[5];
40138a9c020eSBarry Smith 
40148a9c020eSBarry Smith     PetscCall(PetscKernel_A_gets_inverse_A_5(values, ipvt, work, shift, allowzeropivot, &zeropivotdetected));
40158a9c020eSBarry Smith     if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
40169371c9d4SSatish Balay   } break;
40178a9c020eSBarry Smith   case 6:
40188a9c020eSBarry Smith     PetscCall(PetscKernel_A_gets_inverse_A_6(values, shift, allowzeropivot, &zeropivotdetected));
40198a9c020eSBarry Smith     if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
40208a9c020eSBarry Smith     break;
40218a9c020eSBarry Smith   case 7:
40228a9c020eSBarry Smith     PetscCall(PetscKernel_A_gets_inverse_A_7(values, shift, allowzeropivot, &zeropivotdetected));
40238a9c020eSBarry Smith     if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
40248a9c020eSBarry Smith     break;
40259371c9d4SSatish Balay   default: {
40268a9c020eSBarry Smith     PetscInt    *v_pivots, *IJ, j;
40278a9c020eSBarry Smith     PetscScalar *v_work;
40288a9c020eSBarry Smith 
4029d63b1753SJacob Faibussowitsch     PetscCall(PetscMalloc3(m, &v_work, m, &v_pivots, m, &IJ));
4030d63b1753SJacob Faibussowitsch     for (j = 0; j < m; j++) IJ[j] = j;
4031d63b1753SJacob Faibussowitsch     PetscCall(PetscKernel_A_gets_inverse_A(m, values, v_pivots, v_work, allowzeropivot, &zeropivotdetected));
40328a9c020eSBarry Smith     if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
40338a9c020eSBarry Smith     PetscCall(PetscFree3(v_work, v_pivots, IJ));
40348a9c020eSBarry Smith   }
40358a9c020eSBarry Smith   }
4036d63b1753SJacob Faibussowitsch   PetscCall(MatDenseRestoreArray(A, &values));
40373ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
40388a9c020eSBarry Smith }
4039