xref: /petsc/src/mat/impls/dense/seq/dense.c (revision 4cc2b5b5fe4ffd09e5956b56d7cdc4f43e324103)
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 
10560be0d8bdSHansol 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));
10650be0d8bdSHansol Suh   PetscCall(PetscBLASIntCast(c_end - c_start, &n));
10669566063dSJacob Faibussowitsch   PetscCall(VecGetArrayRead(xx, &x));
10679566063dSJacob Faibussowitsch   PetscCall(VecGetArrayWrite(yy, &y));
10680be0d8bdSHansol Suh   if (!m || !n) {
10695ac36cfcSBarry Smith     PetscBLASInt i;
1070459e8d23SBlanca Mellado Pinto     if (trans)
1071459e8d23SBlanca Mellado Pinto       for (i = 0; i < n; i++) y[i] = 0.0;
1072459e8d23SBlanca Mellado Pinto     else
10735ac36cfcSBarry Smith       for (i = 0; i < m; i++) y[i] = 0.0;
10745ac36cfcSBarry Smith   } else {
1075459e8d23SBlanca Mellado Pinto     if (trans) {
10760be0d8bdSHansol Suh       if (herm) PetscCallBLAS("BLASgemv", BLASgemv_("C", &m, &n, &_DOne, v + c_start * mat->lda, &mat->lda, x, &_One, &_DZero, y + c_start, &_One));
10770be0d8bdSHansol Suh       else PetscCallBLAS("BLASgemv", BLASgemv_("T", &m, &n, &_DOne, v + c_start * mat->lda, &mat->lda, x, &_One, &_DZero, y + c_start, &_One));
1078459e8d23SBlanca Mellado Pinto     } else {
10790be0d8bdSHansol Suh       PetscCallBLAS("BLASgemv", BLASgemv_("N", &m, &n, &_DOne, v + c_start * mat->lda, &mat->lda, x + c_start, &_One, &_DZero, y, &_One));
1080459e8d23SBlanca Mellado Pinto     }
10810be0d8bdSHansol Suh     PetscCall(PetscLogFlops(2.0 * m * n - n));
10825ac36cfcSBarry Smith   }
10839566063dSJacob Faibussowitsch   PetscCall(VecRestoreArrayRead(xx, &x));
10849566063dSJacob Faibussowitsch   PetscCall(VecRestoreArrayWrite(yy, &y));
10853ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1086289bc588SBarry Smith }
10876ee01492SSatish Balay 
10880be0d8bdSHansol Suh PetscErrorCode MatMultHermitianTransposeColumnRange_SeqDense(Mat A, Vec xx, Vec yy, PetscInt c_start, PetscInt c_end)
10890be0d8bdSHansol Suh {
10900be0d8bdSHansol Suh   PetscFunctionBegin;
10910be0d8bdSHansol Suh   PetscCall(MatMultColumnRangeKernel_SeqDense(A, xx, yy, c_start, c_end, PETSC_TRUE, PETSC_TRUE));
10920be0d8bdSHansol Suh   PetscFunctionReturn(PETSC_SUCCESS);
10930be0d8bdSHansol Suh }
10940be0d8bdSHansol Suh 
1095459e8d23SBlanca Mellado Pinto PetscErrorCode MatMult_SeqDense(Mat A, Vec xx, Vec yy)
1096459e8d23SBlanca Mellado Pinto {
1097459e8d23SBlanca Mellado Pinto   PetscFunctionBegin;
10980be0d8bdSHansol Suh   PetscCall(MatMultColumnRangeKernel_SeqDense(A, xx, yy, 0, A->cmap->n, PETSC_FALSE, PETSC_FALSE));
1099459e8d23SBlanca Mellado Pinto   PetscFunctionReturn(PETSC_SUCCESS);
1100459e8d23SBlanca Mellado Pinto }
1101459e8d23SBlanca Mellado Pinto 
1102459e8d23SBlanca Mellado Pinto PetscErrorCode MatMultTranspose_SeqDense(Mat A, Vec xx, Vec yy)
1103459e8d23SBlanca Mellado Pinto {
1104459e8d23SBlanca Mellado Pinto   PetscFunctionBegin;
11050be0d8bdSHansol Suh   PetscCall(MatMultColumnRangeKernel_SeqDense(A, xx, yy, 0, A->cmap->n, PETSC_TRUE, PETSC_FALSE));
1106459e8d23SBlanca Mellado Pinto   PetscFunctionReturn(PETSC_SUCCESS);
1107459e8d23SBlanca Mellado Pinto }
1108459e8d23SBlanca Mellado Pinto 
1109459e8d23SBlanca Mellado Pinto PetscErrorCode MatMultHermitianTranspose_SeqDense(Mat A, Vec xx, Vec yy)
1110459e8d23SBlanca Mellado Pinto {
1111459e8d23SBlanca Mellado Pinto   PetscFunctionBegin;
11120be0d8bdSHansol Suh   PetscCall(MatMultColumnRangeKernel_SeqDense(A, xx, yy, 0, A->cmap->n, PETSC_TRUE, PETSC_TRUE));
1113459e8d23SBlanca Mellado Pinto   PetscFunctionReturn(PETSC_SUCCESS);
1114459e8d23SBlanca Mellado Pinto }
1115459e8d23SBlanca Mellado Pinto 
11160be0d8bdSHansol 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));
11250be0d8bdSHansol Suh   PetscCall(PetscBLASIntCast(c_end - c_start, &n));
11269566063dSJacob Faibussowitsch   PetscCall(VecCopy(zz, yy));
11270be0d8bdSHansol Suh   if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS);
11289566063dSJacob Faibussowitsch   PetscCall(VecGetArray(yy, &y));
1129459e8d23SBlanca Mellado Pinto   PetscCall(VecGetArrayRead(xx, &x));
1130459e8d23SBlanca Mellado Pinto   if (trans) {
11310be0d8bdSHansol Suh     if (herm) PetscCallBLAS("BLASgemv", BLASgemv_("C", &m, &n, &_DOne, v + c_start * mat->lda, &mat->lda, x, &_One, &_DOne, y + c_start, &_One));
11320be0d8bdSHansol Suh     else PetscCallBLAS("BLASgemv", BLASgemv_("T", &m, &n, &_DOne, v + c_start * mat->lda, &mat->lda, x, &_One, &_DOne, y + c_start, &_One));
1133459e8d23SBlanca Mellado Pinto   } else {
11340be0d8bdSHansol Suh     PetscCallBLAS("BLASgemv", BLASgemv_("N", &m, &n, &_DOne, v + c_start * mat->lda, &mat->lda, x + c_start, &_One, &_DOne, y, &_One));
1135459e8d23SBlanca Mellado Pinto   }
11369566063dSJacob Faibussowitsch   PetscCall(VecRestoreArrayRead(xx, &x));
11379566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(yy, &y));
11380be0d8bdSHansol Suh   PetscCall(PetscLogFlops(2.0 * m * n));
11390be0d8bdSHansol Suh   PetscFunctionReturn(PETSC_SUCCESS);
11400be0d8bdSHansol Suh }
11410be0d8bdSHansol Suh 
11420be0d8bdSHansol Suh PetscErrorCode MatMultAddColumnRange_SeqDense(Mat A, Vec xx, Vec zz, Vec yy, PetscInt c_start, PetscInt c_end)
11430be0d8bdSHansol Suh {
11440be0d8bdSHansol Suh   PetscFunctionBegin;
11450be0d8bdSHansol Suh   PetscCall(MatMultAddColumnRangeKernel_SeqDense(A, xx, zz, yy, c_start, c_end, PETSC_FALSE, PETSC_FALSE));
11460be0d8bdSHansol Suh   PetscFunctionReturn(PETSC_SUCCESS);
11470be0d8bdSHansol Suh }
11480be0d8bdSHansol Suh 
11490be0d8bdSHansol Suh PetscErrorCode MatMultHermitianTransposeAddColumnRange_SeqDense(Mat A, Vec xx, Vec zz, Vec yy, PetscInt c_start, PetscInt c_end)
11500be0d8bdSHansol Suh {
11510be0d8bdSHansol Suh   PetscFunctionBegin;
11520be0d8bdSHansol Suh   PetscMPIInt rank;
11530be0d8bdSHansol Suh   PetscCallMPI(MPI_Comm_rank(MPI_COMM_WORLD, &rank));
11540be0d8bdSHansol 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;
11610be0d8bdSHansol 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;
11680be0d8bdSHansol 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;
11750be0d8bdSHansol 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);
12388c4a67a0SStefano Zampini           av[indexn[j] * mat->lda + indexm[i]] = v ? v[idx++] : (idx++, 0.0);
1239289bc588SBarry Smith         }
1240289bc588SBarry Smith       }
12410be0d8bdSHansol 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);
12548c4a67a0SStefano Zampini           av[indexn[j] * mat->lda + indexm[i]] += v ? v[idx++] : (idx++, 0.0);
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);
12728c4a67a0SStefano Zampini           av[indexn[j] * mat->lda + indexm[i]] = v ? v[idx++] : (idx++, 0.0);
1273e8d4e0b9SBarry Smith         }
1274e8d4e0b9SBarry Smith       }
12750be0d8bdSHansol 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);
12888c4a67a0SStefano Zampini           av[indexn[j] * mat->lda + indexm[i]] += v ? v[idx++] : (idx++, 0.0);
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));
17790be0d8bdSHansol Suh   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatMultAddColumnRange_C", NULL));
17800be0d8bdSHansol Suh   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatMultHermitianTransposeColumnRange_C", NULL));
17810be0d8bdSHansol 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 @*/
21945d83a8b1SBarry Smith 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 @*/
22195d83a8b1SBarry Smith 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 @*/
22475d83a8b1SBarry Smith 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 @*/
22695d83a8b1SBarry Smith 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 @*/
22935d83a8b1SBarry Smith 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 @*/
23155d83a8b1SBarry Smith 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 @*/
23495d83a8b1SBarry Smith 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 @*/
23885d83a8b1SBarry Smith 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 @*/
24345d83a8b1SBarry Smith 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 @*/
24725d83a8b1SBarry Smith 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 @*/
25175d83a8b1SBarry Smith 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 @*/
25555d83a8b1SBarry Smith 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,
3271*4cc2b5b5SPierre Jolivet                                        NULL,
3272dec0b466SHong Zhang                                        NULL};
327390ace30eSBarry Smith 
32745d83a8b1SBarry Smith /*@
327511a5261eSBarry Smith   MatCreateSeqDense - Creates a `MATSEQDENSE` that
3276fb850c59SBarry Smith   is stored in column major order (the usual Fortran format).
3277289bc588SBarry Smith 
3278d083f849SBarry Smith   Collective
3279db81eaa0SLois Curfman McInnes 
328020563c6bSBarry Smith   Input Parameters:
328111a5261eSBarry Smith + comm - MPI communicator, set to `PETSC_COMM_SELF`
32820c775827SLois Curfman McInnes . m    - number of rows
328318f449edSLois Curfman McInnes . n    - number of columns
32842ef1f0ffSBarry Smith - data - optional location of matrix data in column major order.  Use `NULL` for PETSc
3285dfc5480cSLois Curfman McInnes          to control all matrix memory allocation.
328620563c6bSBarry Smith 
328720563c6bSBarry Smith   Output Parameter:
328844cd7ae7SLois Curfman McInnes . A - the matrix
328920563c6bSBarry Smith 
32902ef1f0ffSBarry Smith   Level: intermediate
32912ef1f0ffSBarry Smith 
329211a5261eSBarry Smith   Note:
329318f449edSLois Curfman McInnes   The data input variable is intended primarily for Fortran programmers
329418f449edSLois Curfman McInnes   who wish to allocate their own matrix memory space.  Most users should
32952ef1f0ffSBarry Smith   set `data` = `NULL`.
329618f449edSLois Curfman McInnes 
3297fb850c59SBarry Smith   Developer Note:
3298fb850c59SBarry Smith   Many of the matrix operations for this variant use the BLAS and LAPACK routines.
3299fb850c59SBarry Smith 
33001cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATSEQDENSE`, `MatCreate()`, `MatCreateDense()`, `MatSetValues()`
330120563c6bSBarry Smith @*/
33025d83a8b1SBarry Smith PetscErrorCode MatCreateSeqDense(MPI_Comm comm, PetscInt m, PetscInt n, PetscScalar data[], Mat *A)
3303d71ae5a4SJacob Faibussowitsch {
33043a40ed3dSBarry Smith   PetscFunctionBegin;
33059566063dSJacob Faibussowitsch   PetscCall(MatCreate(comm, A));
33069566063dSJacob Faibussowitsch   PetscCall(MatSetSizes(*A, m, n, m, n));
33079566063dSJacob Faibussowitsch   PetscCall(MatSetType(*A, MATSEQDENSE));
33089566063dSJacob Faibussowitsch   PetscCall(MatSeqDenseSetPreallocation(*A, data));
33093ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3310273d9f13SBarry Smith }
3311273d9f13SBarry Smith 
33125d83a8b1SBarry Smith /*@
331311a5261eSBarry Smith   MatSeqDenseSetPreallocation - Sets the array used for storing the matrix elements of a `MATSEQDENSE` matrix
3314273d9f13SBarry Smith 
3315d083f849SBarry Smith   Collective
3316273d9f13SBarry Smith 
3317273d9f13SBarry Smith   Input Parameters:
33181c4f3114SJed Brown + B    - the matrix
33192ef1f0ffSBarry Smith - data - the array (or `NULL`)
33202ef1f0ffSBarry Smith 
33212ef1f0ffSBarry Smith   Level: intermediate
3322273d9f13SBarry Smith 
332311a5261eSBarry Smith   Note:
3324273d9f13SBarry Smith   The data input variable is intended primarily for Fortran programmers
3325273d9f13SBarry Smith   who wish to allocate their own matrix memory space.  Most users should
3326284134d9SBarry Smith   need not call this routine.
3327273d9f13SBarry Smith 
33281cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATSEQDENSE`, `MatCreate()`, `MatCreateDense()`, `MatSetValues()`, `MatDenseSetLDA()`
3329273d9f13SBarry Smith @*/
3330d71ae5a4SJacob Faibussowitsch PetscErrorCode MatSeqDenseSetPreallocation(Mat B, PetscScalar data[])
3331d71ae5a4SJacob Faibussowitsch {
3332a23d5eceSKris Buschelman   PetscFunctionBegin;
3333d5ea218eSStefano Zampini   PetscValidHeaderSpecific(B, MAT_CLASSID, 1);
3334cac4c232SBarry Smith   PetscTryMethod(B, "MatSeqDenseSetPreallocation_C", (Mat, PetscScalar[]), (B, data));
33353ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3336a23d5eceSKris Buschelman }
3337a23d5eceSKris Buschelman 
3338d71ae5a4SJacob Faibussowitsch PetscErrorCode MatSeqDenseSetPreallocation_SeqDense(Mat B, PetscScalar *data)
3339d71ae5a4SJacob Faibussowitsch {
3340ad16ce7aSStefano Zampini   Mat_SeqDense *b = (Mat_SeqDense *)B->data;
3341273d9f13SBarry Smith 
3342273d9f13SBarry Smith   PetscFunctionBegin;
334328b400f6SJacob Faibussowitsch   PetscCheck(!b->matinuse, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Need to call MatDenseRestoreSubMatrix() first");
3344273d9f13SBarry Smith   B->preallocated = PETSC_TRUE;
3345a868139aSShri Abhyankar 
33469566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetUp(B->rmap));
33479566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetUp(B->cmap));
334834ef9618SShri Abhyankar 
3349ad16ce7aSStefano Zampini   if (b->lda <= 0) b->lda = B->rmap->n;
335086d161a7SShri Abhyankar 
33519e8f95c4SLisandro Dalcin   if (!data) { /* petsc-allocated storage */
33529566063dSJacob Faibussowitsch     if (!b->user_alloc) PetscCall(PetscFree(b->v));
33539566063dSJacob Faibussowitsch     PetscCall(PetscCalloc1((size_t)b->lda * B->cmap->n, &b->v));
33542205254eSKarl Rupp 
33559e8f95c4SLisandro Dalcin     b->user_alloc = PETSC_FALSE;
3356273d9f13SBarry Smith   } else { /* user-allocated storage */
33579566063dSJacob Faibussowitsch     if (!b->user_alloc) PetscCall(PetscFree(b->v));
3358273d9f13SBarry Smith     b->v          = data;
3359273d9f13SBarry Smith     b->user_alloc = PETSC_TRUE;
3360273d9f13SBarry Smith   }
33610450473dSBarry Smith   B->assembled = PETSC_TRUE;
33623ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3363273d9f13SBarry Smith }
3364273d9f13SBarry Smith 
336565b80a83SHong Zhang #if defined(PETSC_HAVE_ELEMENTAL)
3366d71ae5a4SJacob Faibussowitsch PETSC_INTERN PetscErrorCode MatConvert_SeqDense_Elemental(Mat A, MatType newtype, MatReuse reuse, Mat *newmat)
3367d71ae5a4SJacob Faibussowitsch {
3368d77f618aSHong Zhang   Mat                mat_elemental;
33691683a169SBarry Smith   const PetscScalar *array;
33701683a169SBarry Smith   PetscScalar       *v_colwise;
3371d77f618aSHong Zhang   PetscInt           M = A->rmap->N, N = A->cmap->N, i, j, k, *rows, *cols;
3372d77f618aSHong Zhang 
33738baccfbdSHong Zhang   PetscFunctionBegin;
33749566063dSJacob Faibussowitsch   PetscCall(PetscMalloc3(M * N, &v_colwise, M, &rows, N, &cols));
33759566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArrayRead(A, &array));
3376d77f618aSHong Zhang   /* convert column-wise array into row-wise v_colwise, see MatSetValues_Elemental() */
3377d77f618aSHong Zhang   k = 0;
3378d77f618aSHong Zhang   for (j = 0; j < N; j++) {
3379d77f618aSHong Zhang     cols[j] = j;
3380ad540459SPierre Jolivet     for (i = 0; i < M; i++) v_colwise[j * M + i] = array[k++];
3381d77f618aSHong Zhang   }
3382ad540459SPierre Jolivet   for (i = 0; i < M; i++) rows[i] = i;
33839566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArrayRead(A, &array));
3384d77f618aSHong Zhang 
33859566063dSJacob Faibussowitsch   PetscCall(MatCreate(PetscObjectComm((PetscObject)A), &mat_elemental));
33869566063dSJacob Faibussowitsch   PetscCall(MatSetSizes(mat_elemental, PETSC_DECIDE, PETSC_DECIDE, M, N));
33879566063dSJacob Faibussowitsch   PetscCall(MatSetType(mat_elemental, MATELEMENTAL));
33889566063dSJacob Faibussowitsch   PetscCall(MatSetUp(mat_elemental));
3389d77f618aSHong Zhang 
3390d77f618aSHong Zhang   /* PETSc-Elemental interaface uses axpy for setting off-processor entries, only ADD_VALUES is allowed */
33919566063dSJacob Faibussowitsch   PetscCall(MatSetValues(mat_elemental, M, rows, N, cols, v_colwise, ADD_VALUES));
33929566063dSJacob Faibussowitsch   PetscCall(MatAssemblyBegin(mat_elemental, MAT_FINAL_ASSEMBLY));
33939566063dSJacob Faibussowitsch   PetscCall(MatAssemblyEnd(mat_elemental, MAT_FINAL_ASSEMBLY));
33949566063dSJacob Faibussowitsch   PetscCall(PetscFree3(v_colwise, rows, cols));
3395d77f618aSHong Zhang 
3396511c6705SHong Zhang   if (reuse == MAT_INPLACE_MATRIX) {
33979566063dSJacob Faibussowitsch     PetscCall(MatHeaderReplace(A, &mat_elemental));
3398d77f618aSHong Zhang   } else {
3399d77f618aSHong Zhang     *newmat = mat_elemental;
3400d77f618aSHong Zhang   }
34013ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
34028baccfbdSHong Zhang }
340365b80a83SHong Zhang #endif
34048baccfbdSHong Zhang 
3405d71ae5a4SJacob Faibussowitsch PetscErrorCode MatDenseSetLDA_SeqDense(Mat B, PetscInt lda)
3406d71ae5a4SJacob Faibussowitsch {
34071b807ce4Svictorle   Mat_SeqDense *b = (Mat_SeqDense *)B->data;
34087422da62SJose E. Roman   PetscBool     data;
340921a2c019SBarry Smith 
34101b807ce4Svictorle   PetscFunctionBegin;
34117422da62SJose E. Roman   data = (PetscBool)((B->rmap->n > 0 && B->cmap->n > 0) ? (b->v ? PETSC_TRUE : PETSC_FALSE) : PETSC_FALSE);
3412aed4548fSBarry Smith   PetscCheck(b->user_alloc || !data || b->lda == lda, PETSC_COMM_SELF, PETSC_ERR_ORDER, "LDA cannot be changed after allocation of internal storage");
341308401ef6SPierre 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);
34141b807ce4Svictorle   b->lda = lda;
34153ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
34161b807ce4Svictorle }
34171b807ce4Svictorle 
3418d71ae5a4SJacob Faibussowitsch PetscErrorCode MatCreateMPIMatConcatenateSeqMat_SeqDense(MPI_Comm comm, Mat inmat, PetscInt n, MatReuse scall, Mat *outmat)
3419d71ae5a4SJacob Faibussowitsch {
3420d528f656SJakub Kruzik   PetscFunctionBegin;
34219566063dSJacob Faibussowitsch   PetscCall(MatCreateMPIMatConcatenateSeqMat_MPIDense(comm, inmat, n, scall, outmat));
34223ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3423d528f656SJakub Kruzik }
3424d528f656SJakub Kruzik 
3425d16ceb75SStefano Zampini PetscErrorCode MatDenseCreateColumnVec_Private(Mat A, Vec *v)
3426d16ceb75SStefano Zampini {
3427d16ceb75SStefano Zampini   PetscBool   isstd, iskok, iscuda, iship;
3428d16ceb75SStefano Zampini   PetscMPIInt size;
3429d16ceb75SStefano Zampini #if PetscDefined(HAVE_CUDA) || PetscDefined(HAVE_HIP)
3430d16ceb75SStefano Zampini   /* we pass the data of A, to prevent allocating needless GPU memory the first time VecCUPMPlaceArray is called. */
3431d16ceb75SStefano Zampini   const PetscScalar *a;
3432d16ceb75SStefano Zampini #endif
3433d16ceb75SStefano Zampini 
3434d16ceb75SStefano Zampini   PetscFunctionBegin;
3435d16ceb75SStefano Zampini   *v = NULL;
3436d16ceb75SStefano Zampini   PetscCall(PetscStrcmpAny(A->defaultvectype, &isstd, VECSTANDARD, VECSEQ, VECMPI, ""));
3437d16ceb75SStefano Zampini   PetscCall(PetscStrcmpAny(A->defaultvectype, &iskok, VECKOKKOS, VECSEQKOKKOS, VECMPIKOKKOS, ""));
3438d16ceb75SStefano Zampini   PetscCall(PetscStrcmpAny(A->defaultvectype, &iscuda, VECCUDA, VECSEQCUDA, VECMPICUDA, ""));
3439d16ceb75SStefano Zampini   PetscCall(PetscStrcmpAny(A->defaultvectype, &iship, VECHIP, VECSEQHIP, VECMPIHIP, ""));
3440d16ceb75SStefano Zampini   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)A), &size));
3441d16ceb75SStefano Zampini   if (isstd) {
3442d16ceb75SStefano Zampini     if (size > 1) PetscCall(VecCreateMPIWithArray(PetscObjectComm((PetscObject)A), A->rmap->bs, A->rmap->n, A->rmap->N, NULL, v));
3443d16ceb75SStefano Zampini     else PetscCall(VecCreateSeqWithArray(PetscObjectComm((PetscObject)A), A->rmap->bs, A->rmap->n, NULL, v));
3444d16ceb75SStefano Zampini   } else if (iskok) {
3445d16ceb75SStefano Zampini     PetscCheck(PetscDefined(HAVE_KOKKOS_KERNELS), PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Reconfigure using KOKKOS kernels support");
3446d16ceb75SStefano Zampini #if PetscDefined(HAVE_KOKKOS_KERNELS)
3447d16ceb75SStefano Zampini     if (size > 1) PetscCall(VecCreateMPIKokkosWithArray(PetscObjectComm((PetscObject)A), A->rmap->bs, A->rmap->n, A->rmap->N, NULL, v));
3448d16ceb75SStefano Zampini     else PetscCall(VecCreateSeqKokkosWithArray(PetscObjectComm((PetscObject)A), A->rmap->bs, A->rmap->n, NULL, v));
3449d16ceb75SStefano Zampini #endif
3450d16ceb75SStefano Zampini   } else if (iscuda) {
3451d16ceb75SStefano Zampini     PetscCheck(PetscDefined(HAVE_CUDA), PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Reconfigure using CUDA support");
3452d16ceb75SStefano Zampini #if PetscDefined(HAVE_CUDA)
3453d16ceb75SStefano Zampini     PetscCall(MatDenseCUDAGetArrayRead(A, &a));
3454d16ceb75SStefano Zampini     if (size > 1) PetscCall(VecCreateMPICUDAWithArrays(PetscObjectComm((PetscObject)A), A->rmap->bs, A->rmap->n, A->rmap->N, NULL, a, v));
3455d16ceb75SStefano Zampini     else PetscCall(VecCreateSeqCUDAWithArrays(PetscObjectComm((PetscObject)A), A->rmap->bs, A->rmap->n, NULL, a, v));
3456d16ceb75SStefano Zampini #endif
3457d16ceb75SStefano Zampini   } else if (iship) {
3458d16ceb75SStefano Zampini     PetscCheck(PetscDefined(HAVE_HIP), PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Reconfigure using HIP support");
3459d16ceb75SStefano Zampini #if PetscDefined(HAVE_HIP)
3460d16ceb75SStefano Zampini     PetscCall(MatDenseHIPGetArrayRead(A, &a));
3461d16ceb75SStefano Zampini     if (size > 1) PetscCall(VecCreateMPIHIPWithArrays(PetscObjectComm((PetscObject)A), A->rmap->bs, A->rmap->n, A->rmap->N, NULL, a, v));
3462d16ceb75SStefano Zampini     else PetscCall(VecCreateSeqHIPWithArrays(PetscObjectComm((PetscObject)A), A->rmap->bs, A->rmap->n, NULL, a, v));
3463d16ceb75SStefano Zampini #endif
3464d16ceb75SStefano Zampini   }
3465d16ceb75SStefano Zampini   PetscCheck(*v, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Not coded for type %s", A->defaultvectype);
3466d16ceb75SStefano Zampini   PetscFunctionReturn(PETSC_SUCCESS);
3467d16ceb75SStefano Zampini }
3468d16ceb75SStefano Zampini 
3469d71ae5a4SJacob Faibussowitsch PetscErrorCode MatDenseGetColumnVec_SeqDense(Mat A, PetscInt col, Vec *v)
3470d71ae5a4SJacob Faibussowitsch {
34716947451fSStefano Zampini   Mat_SeqDense *a = (Mat_SeqDense *)A->data;
34726947451fSStefano Zampini 
34736947451fSStefano Zampini   PetscFunctionBegin;
347428b400f6SJacob Faibussowitsch   PetscCheck(!a->vecinuse, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Need to call MatDenseRestoreColumnVec() first");
347528b400f6SJacob Faibussowitsch   PetscCheck(!a->matinuse, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Need to call MatDenseRestoreSubMatrix() first");
3476d16ceb75SStefano Zampini   if (!a->cvec) PetscCall(MatDenseCreateColumnVec_Private(A, &a->cvec));
34776947451fSStefano Zampini   a->vecinuse = col + 1;
34789566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArray(A, (PetscScalar **)&a->ptrinuse));
34799566063dSJacob Faibussowitsch   PetscCall(VecPlaceArray(a->cvec, a->ptrinuse + (size_t)col * (size_t)a->lda));
34806947451fSStefano Zampini   *v = a->cvec;
34813ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
34826947451fSStefano Zampini }
34836947451fSStefano Zampini 
3484d71ae5a4SJacob Faibussowitsch PetscErrorCode MatDenseRestoreColumnVec_SeqDense(Mat A, PetscInt col, Vec *v)
3485d71ae5a4SJacob Faibussowitsch {
34866947451fSStefano Zampini   Mat_SeqDense *a = (Mat_SeqDense *)A->data;
34876947451fSStefano Zampini 
34886947451fSStefano Zampini   PetscFunctionBegin;
348928b400f6SJacob Faibussowitsch   PetscCheck(a->vecinuse, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Need to call MatDenseGetColumnVec() first");
349028b400f6SJacob Faibussowitsch   PetscCheck(a->cvec, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Missing internal column vector");
34916947451fSStefano Zampini   a->vecinuse = 0;
34929566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArray(A, (PetscScalar **)&a->ptrinuse));
34939566063dSJacob Faibussowitsch   PetscCall(VecResetArray(a->cvec));
349475f6d85dSStefano Zampini   if (v) *v = NULL;
34953ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
34966947451fSStefano Zampini }
34976947451fSStefano Zampini 
3498d71ae5a4SJacob Faibussowitsch PetscErrorCode MatDenseGetColumnVecRead_SeqDense(Mat A, PetscInt col, Vec *v)
3499d71ae5a4SJacob Faibussowitsch {
35006947451fSStefano Zampini   Mat_SeqDense *a = (Mat_SeqDense *)A->data;
35016947451fSStefano Zampini 
35026947451fSStefano Zampini   PetscFunctionBegin;
350328b400f6SJacob Faibussowitsch   PetscCheck(!a->vecinuse, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Need to call MatDenseRestoreColumnVec() first");
350428b400f6SJacob Faibussowitsch   PetscCheck(!a->matinuse, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Need to call MatDenseRestoreSubMatrix() first");
3505d16ceb75SStefano Zampini   if (!a->cvec) PetscCall(MatDenseCreateColumnVec_Private(A, &a->cvec));
35066947451fSStefano Zampini   a->vecinuse = col + 1;
35079566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArrayRead(A, &a->ptrinuse));
35088e3a54c0SPierre Jolivet   PetscCall(VecPlaceArray(a->cvec, PetscSafePointerPlusOffset(a->ptrinuse, (size_t)col * (size_t)a->lda)));
35099566063dSJacob Faibussowitsch   PetscCall(VecLockReadPush(a->cvec));
35106947451fSStefano Zampini   *v = a->cvec;
35113ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
35126947451fSStefano Zampini }
35136947451fSStefano Zampini 
3514d71ae5a4SJacob Faibussowitsch PetscErrorCode MatDenseRestoreColumnVecRead_SeqDense(Mat A, PetscInt col, Vec *v)
3515d71ae5a4SJacob Faibussowitsch {
35166947451fSStefano Zampini   Mat_SeqDense *a = (Mat_SeqDense *)A->data;
35176947451fSStefano Zampini 
35186947451fSStefano Zampini   PetscFunctionBegin;
351928b400f6SJacob Faibussowitsch   PetscCheck(a->vecinuse, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Need to call MatDenseGetColumnVec() first");
352028b400f6SJacob Faibussowitsch   PetscCheck(a->cvec, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Missing internal column vector");
35216947451fSStefano Zampini   a->vecinuse = 0;
35229566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArrayRead(A, &a->ptrinuse));
35239566063dSJacob Faibussowitsch   PetscCall(VecLockReadPop(a->cvec));
35249566063dSJacob Faibussowitsch   PetscCall(VecResetArray(a->cvec));
352575f6d85dSStefano Zampini   if (v) *v = NULL;
35263ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
35276947451fSStefano Zampini }
35286947451fSStefano Zampini 
3529d71ae5a4SJacob Faibussowitsch PetscErrorCode MatDenseGetColumnVecWrite_SeqDense(Mat A, PetscInt col, Vec *v)
3530d71ae5a4SJacob Faibussowitsch {
35316947451fSStefano Zampini   Mat_SeqDense *a = (Mat_SeqDense *)A->data;
35326947451fSStefano Zampini 
35336947451fSStefano Zampini   PetscFunctionBegin;
353428b400f6SJacob Faibussowitsch   PetscCheck(!a->vecinuse, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Need to call MatDenseRestoreColumnVec() first");
353528b400f6SJacob Faibussowitsch   PetscCheck(!a->matinuse, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Need to call MatDenseRestoreSubMatrix() first");
3536d16ceb75SStefano Zampini   if (!a->cvec) PetscCall(MatDenseCreateColumnVec_Private(A, &a->cvec));
35376947451fSStefano Zampini   a->vecinuse = col + 1;
35389566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArrayWrite(A, (PetscScalar **)&a->ptrinuse));
35398e3a54c0SPierre Jolivet   PetscCall(VecPlaceArray(a->cvec, PetscSafePointerPlusOffset(a->ptrinuse, (size_t)col * (size_t)a->lda)));
35406947451fSStefano Zampini   *v = a->cvec;
35413ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
35426947451fSStefano Zampini }
35436947451fSStefano Zampini 
3544d71ae5a4SJacob Faibussowitsch PetscErrorCode MatDenseRestoreColumnVecWrite_SeqDense(Mat A, PetscInt col, Vec *v)
3545d71ae5a4SJacob Faibussowitsch {
35466947451fSStefano Zampini   Mat_SeqDense *a = (Mat_SeqDense *)A->data;
35476947451fSStefano Zampini 
35486947451fSStefano Zampini   PetscFunctionBegin;
354928b400f6SJacob Faibussowitsch   PetscCheck(a->vecinuse, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Need to call MatDenseGetColumnVec() first");
355028b400f6SJacob Faibussowitsch   PetscCheck(a->cvec, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Missing internal column vector");
35516947451fSStefano Zampini   a->vecinuse = 0;
35529566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArrayWrite(A, (PetscScalar **)&a->ptrinuse));
35539566063dSJacob Faibussowitsch   PetscCall(VecResetArray(a->cvec));
355475f6d85dSStefano Zampini   if (v) *v = NULL;
35553ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
35566947451fSStefano Zampini }
35576947451fSStefano Zampini 
3558d71ae5a4SJacob Faibussowitsch PetscErrorCode MatDenseGetSubMatrix_SeqDense(Mat A, PetscInt rbegin, PetscInt rend, PetscInt cbegin, PetscInt cend, Mat *v)
3559d71ae5a4SJacob Faibussowitsch {
35605ea7661aSPierre Jolivet   Mat_SeqDense *a = (Mat_SeqDense *)A->data;
35615ea7661aSPierre Jolivet 
35625ea7661aSPierre Jolivet   PetscFunctionBegin;
356328b400f6SJacob Faibussowitsch   PetscCheck(!a->vecinuse, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Need to call MatDenseRestoreColumnVec() first");
356428b400f6SJacob Faibussowitsch   PetscCheck(!a->matinuse, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Need to call MatDenseRestoreSubMatrix() first");
3565a2748737SPierre Jolivet   if (a->cmat && (cend - cbegin != a->cmat->cmap->N || rend - rbegin != a->cmat->rmap->N)) PetscCall(MatDestroy(&a->cmat));
35665ea7661aSPierre Jolivet   if (!a->cmat) {
35678e3a54c0SPierre 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));
35685ea7661aSPierre Jolivet   } else {
35698e3a54c0SPierre Jolivet     PetscCall(MatDensePlaceArray(a->cmat, PetscSafePointerPlusOffset(a->v, rbegin + (size_t)cbegin * a->lda)));
35705ea7661aSPierre Jolivet   }
35719566063dSJacob Faibussowitsch   PetscCall(MatDenseSetLDA(a->cmat, a->lda));
35725ea7661aSPierre Jolivet   a->matinuse = cbegin + 1;
35735ea7661aSPierre Jolivet   *v          = a->cmat;
357447d993e7Ssuyashtn #if defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
357575f6d85dSStefano Zampini   A->offloadmask = PETSC_OFFLOAD_CPU;
357675f6d85dSStefano Zampini #endif
35773ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
35785ea7661aSPierre Jolivet }
35795ea7661aSPierre Jolivet 
3580d71ae5a4SJacob Faibussowitsch PetscErrorCode MatDenseRestoreSubMatrix_SeqDense(Mat A, Mat *v)
3581d71ae5a4SJacob Faibussowitsch {
35825ea7661aSPierre Jolivet   Mat_SeqDense *a = (Mat_SeqDense *)A->data;
35835ea7661aSPierre Jolivet 
35845ea7661aSPierre Jolivet   PetscFunctionBegin;
358528b400f6SJacob Faibussowitsch   PetscCheck(a->matinuse, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Need to call MatDenseGetSubMatrix() first");
358628b400f6SJacob Faibussowitsch   PetscCheck(a->cmat, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Missing internal column matrix");
358708401ef6SPierre Jolivet   PetscCheck(*v == a->cmat, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Not the matrix obtained from MatDenseGetSubMatrix()");
35885ea7661aSPierre Jolivet   a->matinuse = 0;
35899566063dSJacob Faibussowitsch   PetscCall(MatDenseResetArray(a->cmat));
3590742765d3SMatthew Knepley   if (v) *v = NULL;
359147d993e7Ssuyashtn #if defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
35923faff063SStefano Zampini   A->offloadmask = PETSC_OFFLOAD_CPU;
35933faff063SStefano Zampini #endif
35943ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
35955ea7661aSPierre Jolivet }
35965ea7661aSPierre Jolivet 
35970bad9183SKris Buschelman /*MC
3598fafad747SKris Buschelman    MATSEQDENSE - MATSEQDENSE = "seqdense" - A matrix type to be used for sequential dense matrices.
35990bad9183SKris Buschelman 
36002ef1f0ffSBarry Smith    Options Database Key:
360111a5261eSBarry Smith . -mat_type seqdense - sets the matrix type to `MATSEQDENSE` during a call to `MatSetFromOptions()`
36020bad9183SKris Buschelman 
36030bad9183SKris Buschelman   Level: beginner
36040bad9183SKris Buschelman 
36051cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATSEQDENSE`, `MatCreateSeqDense()`
36060bad9183SKris Buschelman M*/
3607d71ae5a4SJacob Faibussowitsch PetscErrorCode MatCreate_SeqDense(Mat B)
3608d71ae5a4SJacob Faibussowitsch {
3609273d9f13SBarry Smith   Mat_SeqDense *b;
36107c334f02SBarry Smith   PetscMPIInt   size;
3611273d9f13SBarry Smith 
3612273d9f13SBarry Smith   PetscFunctionBegin;
36139566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)B), &size));
361408401ef6SPierre Jolivet   PetscCheck(size <= 1, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Comm must be of size 1");
361555659b69SBarry Smith 
36164dfa11a4SJacob Faibussowitsch   PetscCall(PetscNew(&b));
361744cd7ae7SLois Curfman McInnes   B->data   = (void *)b;
3618aea10558SJacob Faibussowitsch   B->ops[0] = MatOps_Values;
361918f449edSLois Curfman McInnes 
3620273d9f13SBarry Smith   b->roworiented = PETSC_TRUE;
36214e220ebcSLois Curfman McInnes 
36229566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatQRFactor_C", MatQRFactor_SeqDense));
36239566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatDenseGetLDA_C", MatDenseGetLDA_SeqDense));
36249566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatDenseSetLDA_C", MatDenseSetLDA_SeqDense));
36259566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatDenseGetArray_C", MatDenseGetArray_SeqDense));
36269566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatDenseRestoreArray_C", MatDenseRestoreArray_SeqDense));
36279566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatDensePlaceArray_C", MatDensePlaceArray_SeqDense));
36289566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatDenseResetArray_C", MatDenseResetArray_SeqDense));
36299566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatDenseReplaceArray_C", MatDenseReplaceArray_SeqDense));
36309566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatDenseGetArrayRead_C", MatDenseGetArray_SeqDense));
36319566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatDenseRestoreArrayRead_C", MatDenseRestoreArray_SeqDense));
36329566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatDenseGetArrayWrite_C", MatDenseGetArray_SeqDense));
36339566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatDenseRestoreArrayWrite_C", MatDenseRestoreArray_SeqDense));
36349566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatConvert_seqdense_seqaij_C", MatConvert_SeqDense_SeqAIJ));
36358baccfbdSHong Zhang #if defined(PETSC_HAVE_ELEMENTAL)
36369566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatConvert_seqdense_elemental_C", MatConvert_SeqDense_Elemental));
36378baccfbdSHong Zhang #endif
3638d24d4204SJose E. Roman #if defined(PETSC_HAVE_SCALAPACK)
36399566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatConvert_seqdense_scalapack_C", MatConvert_Dense_ScaLAPACK));
3640d24d4204SJose E. Roman #endif
36412bf066beSStefano Zampini #if defined(PETSC_HAVE_CUDA)
36429566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatConvert_seqdense_seqdensecuda_C", MatConvert_SeqDense_SeqDenseCUDA));
36439566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatProductSetFromOptions_seqdensecuda_seqdensecuda_C", MatProductSetFromOptions_SeqDense));
36449566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatProductSetFromOptions_seqdensecuda_seqdense_C", MatProductSetFromOptions_SeqDense));
36459566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatProductSetFromOptions_seqdense_seqdensecuda_C", MatProductSetFromOptions_SeqDense));
36462bf066beSStefano Zampini #endif
364747d993e7Ssuyashtn #if defined(PETSC_HAVE_HIP)
364847d993e7Ssuyashtn   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatConvert_seqdense_seqdensehip_C", MatConvert_SeqDense_SeqDenseHIP));
364947d993e7Ssuyashtn   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatProductSetFromOptions_seqdensehip_seqdensehip_C", MatProductSetFromOptions_SeqDense));
365047d993e7Ssuyashtn   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatProductSetFromOptions_seqdensehip_seqdense_C", MatProductSetFromOptions_SeqDense));
365147d993e7Ssuyashtn   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatProductSetFromOptions_seqdense_seqdensehip_C", MatProductSetFromOptions_SeqDense));
365247d993e7Ssuyashtn #endif
36539566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatSeqDenseSetPreallocation_C", MatSeqDenseSetPreallocation_SeqDense));
36549566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatProductSetFromOptions_seqaij_seqdense_C", MatProductSetFromOptions_SeqAIJ_SeqDense));
36559566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatProductSetFromOptions_seqdense_seqdense_C", MatProductSetFromOptions_SeqDense));
36569566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatProductSetFromOptions_seqbaij_seqdense_C", MatProductSetFromOptions_SeqXBAIJ_SeqDense));
36579566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatProductSetFromOptions_seqsbaij_seqdense_C", MatProductSetFromOptions_SeqXBAIJ_SeqDense));
365896e6d5c4SRichard Tran Mills 
36599566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatDenseGetColumn_C", MatDenseGetColumn_SeqDense));
36609566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatDenseRestoreColumn_C", MatDenseRestoreColumn_SeqDense));
36619566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatDenseGetColumnVec_C", MatDenseGetColumnVec_SeqDense));
36629566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatDenseRestoreColumnVec_C", MatDenseRestoreColumnVec_SeqDense));
36639566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatDenseGetColumnVecRead_C", MatDenseGetColumnVecRead_SeqDense));
36649566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatDenseRestoreColumnVecRead_C", MatDenseRestoreColumnVecRead_SeqDense));
36659566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatDenseGetColumnVecWrite_C", MatDenseGetColumnVecWrite_SeqDense));
36669566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatDenseRestoreColumnVecWrite_C", MatDenseRestoreColumnVecWrite_SeqDense));
36679566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatDenseGetSubMatrix_C", MatDenseGetSubMatrix_SeqDense));
36689566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatDenseRestoreSubMatrix_C", MatDenseRestoreSubMatrix_SeqDense));
36690be0d8bdSHansol Suh   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatMultAddColumnRange_C", MatMultAddColumnRange_SeqDense));
36700be0d8bdSHansol Suh   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatMultHermitianTransposeColumnRange_C", MatMultHermitianTransposeColumnRange_SeqDense));
36710be0d8bdSHansol Suh   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatMultHermitianTransposeAddColumnRange_C", MatMultHermitianTransposeAddColumnRange_SeqDense));
36729566063dSJacob Faibussowitsch   PetscCall(PetscObjectChangeTypeName((PetscObject)B, MATSEQDENSE));
36733ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3674289bc588SBarry Smith }
367586aefd0dSHong Zhang 
367686aefd0dSHong Zhang /*@C
367711a5261eSBarry 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.
367886aefd0dSHong Zhang 
367986aefd0dSHong Zhang   Not Collective
368086aefd0dSHong Zhang 
36815ea7661aSPierre Jolivet   Input Parameters:
3682fe59aa6dSJacob Faibussowitsch + A   - a `MATSEQDENSE` or `MATMPIDENSE` matrix
368386aefd0dSHong Zhang - col - column index
368486aefd0dSHong Zhang 
368586aefd0dSHong Zhang   Output Parameter:
368686aefd0dSHong Zhang . vals - pointer to the data
368786aefd0dSHong Zhang 
368886aefd0dSHong Zhang   Level: intermediate
368986aefd0dSHong Zhang 
369011a5261eSBarry Smith   Note:
369111a5261eSBarry Smith   Use `MatDenseGetColumnVec()` to get access to a column of a `MATDENSE` treated as a `Vec`
369211a5261eSBarry Smith 
36931cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATDENSE`, `MatDenseRestoreColumn()`, `MatDenseGetColumnVec()`
369486aefd0dSHong Zhang @*/
36955d83a8b1SBarry Smith PetscErrorCode MatDenseGetColumn(Mat A, PetscInt col, PetscScalar *vals[])
3696d71ae5a4SJacob Faibussowitsch {
369786aefd0dSHong Zhang   PetscFunctionBegin;
3698d5ea218eSStefano Zampini   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
3699d5ea218eSStefano Zampini   PetscValidLogicalCollectiveInt(A, col, 2);
37004f572ea9SToby Isaac   PetscAssertPointer(vals, 3);
3701cac4c232SBarry Smith   PetscUseMethod(A, "MatDenseGetColumn_C", (Mat, PetscInt, PetscScalar **), (A, col, vals));
37023ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
370386aefd0dSHong Zhang }
370486aefd0dSHong Zhang 
370586aefd0dSHong Zhang /*@C
370611a5261eSBarry Smith   MatDenseRestoreColumn - returns access to a column of a `MATDENSE` matrix which is returned by `MatDenseGetColumn()`.
370786aefd0dSHong Zhang 
370886aefd0dSHong Zhang   Not Collective
370986aefd0dSHong Zhang 
3710742765d3SMatthew Knepley   Input Parameters:
3711fe59aa6dSJacob Faibussowitsch + A    - a `MATSEQDENSE` or `MATMPIDENSE` matrix
37122ef1f0ffSBarry Smith - vals - pointer to the data (may be `NULL`)
371386aefd0dSHong Zhang 
371486aefd0dSHong Zhang   Level: intermediate
371586aefd0dSHong Zhang 
37161cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATDENSE`, `MatDenseGetColumn()`
371786aefd0dSHong Zhang @*/
37185d83a8b1SBarry Smith PetscErrorCode MatDenseRestoreColumn(Mat A, PetscScalar *vals[])
3719d71ae5a4SJacob Faibussowitsch {
372086aefd0dSHong Zhang   PetscFunctionBegin;
3721d5ea218eSStefano Zampini   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
37224f572ea9SToby Isaac   PetscAssertPointer(vals, 2);
3723cac4c232SBarry Smith   PetscUseMethod(A, "MatDenseRestoreColumn_C", (Mat, PetscScalar **), (A, vals));
37243ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
372586aefd0dSHong Zhang }
37266947451fSStefano Zampini 
37270f74d2c1SSatish Balay /*@
372811a5261eSBarry Smith   MatDenseGetColumnVec - Gives read-write access to a column of a `MATDENSE` matrix, represented as a `Vec`.
37296947451fSStefano Zampini 
37306947451fSStefano Zampini   Collective
37316947451fSStefano Zampini 
37325ea7661aSPierre Jolivet   Input Parameters:
3733fe59aa6dSJacob Faibussowitsch + A   - the `Mat` object
37346947451fSStefano Zampini - col - the column index
37356947451fSStefano Zampini 
37366947451fSStefano Zampini   Output Parameter:
37376947451fSStefano Zampini . v - the vector
37386947451fSStefano Zampini 
37392ef1f0ffSBarry Smith   Level: intermediate
37402ef1f0ffSBarry Smith 
37416947451fSStefano Zampini   Notes:
374211a5261eSBarry Smith   The vector is owned by PETSc. Users need to call `MatDenseRestoreColumnVec()` when the vector is no longer needed.
374311a5261eSBarry Smith 
374411a5261eSBarry Smith   Use `MatDenseGetColumnVecRead()` to obtain read-only access or `MatDenseGetColumnVecWrite()` for write-only access.
37456947451fSStefano Zampini 
37461cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATDENSE`, `MATDENSECUDA`, `MATDENSEHIP`, `MatDenseGetColumnVecRead()`, `MatDenseGetColumnVecWrite()`, `MatDenseRestoreColumnVec()`, `MatDenseRestoreColumnVecRead()`, `MatDenseRestoreColumnVecWrite()`, `MatDenseGetColumn()`
37476947451fSStefano Zampini @*/
3748d71ae5a4SJacob Faibussowitsch PetscErrorCode MatDenseGetColumnVec(Mat A, PetscInt col, Vec *v)
3749d71ae5a4SJacob Faibussowitsch {
37506947451fSStefano Zampini   PetscFunctionBegin;
37516947451fSStefano Zampini   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
37526947451fSStefano Zampini   PetscValidType(A, 1);
37536947451fSStefano Zampini   PetscValidLogicalCollectiveInt(A, col, 2);
37544f572ea9SToby Isaac   PetscAssertPointer(v, 3);
375528b400f6SJacob Faibussowitsch   PetscCheck(A->preallocated, PetscObjectComm((PetscObject)A), PETSC_ERR_ORDER, "Matrix not preallocated");
37562cf15c64SPierre 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);
3757cac4c232SBarry Smith   PetscUseMethod(A, "MatDenseGetColumnVec_C", (Mat, PetscInt, Vec *), (A, col, v));
37583ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
37596947451fSStefano Zampini }
37606947451fSStefano Zampini 
37610f74d2c1SSatish Balay /*@
3762fb850c59SBarry Smith   MatDenseRestoreColumnVec - Returns access to a column of a dense matrix obtained from `MatDenseGetColumnVec()`.
37636947451fSStefano Zampini 
37646947451fSStefano Zampini   Collective
37656947451fSStefano Zampini 
37665ea7661aSPierre Jolivet   Input Parameters:
3767fb850c59SBarry Smith + A   - the `Mat` object
37686947451fSStefano Zampini . col - the column index
3769fb850c59SBarry Smith - v   - the `Vec` object (may be `NULL`)
37706947451fSStefano Zampini 
37716947451fSStefano Zampini   Level: intermediate
37726947451fSStefano Zampini 
37731cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATDENSE`, `MATDENSECUDA`, `MATDENSEHIP`, `MatDenseGetColumnVec()`, `MatDenseGetColumnVecRead()`, `MatDenseGetColumnVecWrite()`, `MatDenseRestoreColumnVecRead()`, `MatDenseRestoreColumnVecWrite()`
37746947451fSStefano Zampini @*/
3775d71ae5a4SJacob Faibussowitsch PetscErrorCode MatDenseRestoreColumnVec(Mat A, PetscInt col, Vec *v)
3776d71ae5a4SJacob Faibussowitsch {
37776947451fSStefano Zampini   PetscFunctionBegin;
37786947451fSStefano Zampini   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
37796947451fSStefano Zampini   PetscValidType(A, 1);
37806947451fSStefano Zampini   PetscValidLogicalCollectiveInt(A, col, 2);
378108401ef6SPierre Jolivet   PetscCheck(A->preallocated, PetscObjectComm((PetscObject)A), PETSC_ERR_ORDER, "Matrix not preallocated");
37822cf15c64SPierre 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);
3783cac4c232SBarry Smith   PetscUseMethod(A, "MatDenseRestoreColumnVec_C", (Mat, PetscInt, Vec *), (A, col, v));
37843ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
37856947451fSStefano Zampini }
37866947451fSStefano Zampini 
37870f74d2c1SSatish Balay /*@
3788fb850c59SBarry Smith   MatDenseGetColumnVecRead - Gives read-only access to a column of a dense matrix, represented as a `Vec`.
37896947451fSStefano Zampini 
37906947451fSStefano Zampini   Collective
37916947451fSStefano Zampini 
37925ea7661aSPierre Jolivet   Input Parameters:
3793fe59aa6dSJacob Faibussowitsch + A   - the `Mat` object
37946947451fSStefano Zampini - col - the column index
37956947451fSStefano Zampini 
37966947451fSStefano Zampini   Output Parameter:
37976947451fSStefano Zampini . v - the vector
37986947451fSStefano Zampini 
37992ef1f0ffSBarry Smith   Level: intermediate
38002ef1f0ffSBarry Smith 
38016947451fSStefano Zampini   Notes:
38026947451fSStefano Zampini   The vector is owned by PETSc and users cannot modify it.
380311a5261eSBarry Smith 
38042ef1f0ffSBarry Smith   Users need to call `MatDenseRestoreColumnVecRead()` when the vector is no longer needed.
380511a5261eSBarry Smith 
38062ef1f0ffSBarry Smith   Use `MatDenseGetColumnVec()` to obtain read-write access or `MatDenseGetColumnVecWrite()` for write-only access.
38076947451fSStefano Zampini 
38081cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATDENSE`, `MATDENSECUDA`, `MATDENSEHIP`, `MatDenseGetColumnVec()`, `MatDenseGetColumnVecWrite()`, `MatDenseRestoreColumnVec()`, `MatDenseRestoreColumnVecRead()`, `MatDenseRestoreColumnVecWrite()`
38096947451fSStefano Zampini @*/
3810d71ae5a4SJacob Faibussowitsch PetscErrorCode MatDenseGetColumnVecRead(Mat A, PetscInt col, Vec *v)
3811d71ae5a4SJacob Faibussowitsch {
38126947451fSStefano Zampini   PetscFunctionBegin;
38136947451fSStefano Zampini   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
38146947451fSStefano Zampini   PetscValidType(A, 1);
38156947451fSStefano Zampini   PetscValidLogicalCollectiveInt(A, col, 2);
38164f572ea9SToby Isaac   PetscAssertPointer(v, 3);
381728b400f6SJacob Faibussowitsch   PetscCheck(A->preallocated, PetscObjectComm((PetscObject)A), PETSC_ERR_ORDER, "Matrix not preallocated");
38182cf15c64SPierre 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);
3819cac4c232SBarry Smith   PetscUseMethod(A, "MatDenseGetColumnVecRead_C", (Mat, PetscInt, Vec *), (A, col, v));
38203ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
38216947451fSStefano Zampini }
38226947451fSStefano Zampini 
38230f74d2c1SSatish Balay /*@
3824fb850c59SBarry Smith   MatDenseRestoreColumnVecRead - Returns access to a column of a dense matrix obtained from `MatDenseGetColumnVecRead()`.
38256947451fSStefano Zampini 
38266947451fSStefano Zampini   Collective
38276947451fSStefano Zampini 
38285ea7661aSPierre Jolivet   Input Parameters:
3829fe59aa6dSJacob Faibussowitsch + A   - the `Mat` object
38306947451fSStefano Zampini . col - the column index
3831fb850c59SBarry Smith - v   - the `Vec` object (may be `NULL`)
38326947451fSStefano Zampini 
38336947451fSStefano Zampini   Level: intermediate
38346947451fSStefano Zampini 
38351cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATDENSE`, `MATDENSECUDA`, `MATDENSEHIP`, `MatDenseGetColumnVec()`, `MatDenseGetColumnVecRead()`, `MatDenseGetColumnVecWrite()`, `MatDenseRestoreColumnVec()`, `MatDenseRestoreColumnVecWrite()`
38366947451fSStefano Zampini @*/
3837d71ae5a4SJacob Faibussowitsch PetscErrorCode MatDenseRestoreColumnVecRead(Mat A, PetscInt col, Vec *v)
3838d71ae5a4SJacob Faibussowitsch {
38396947451fSStefano Zampini   PetscFunctionBegin;
38406947451fSStefano Zampini   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
38416947451fSStefano Zampini   PetscValidType(A, 1);
38426947451fSStefano Zampini   PetscValidLogicalCollectiveInt(A, col, 2);
384308401ef6SPierre Jolivet   PetscCheck(A->preallocated, PetscObjectComm((PetscObject)A), PETSC_ERR_ORDER, "Matrix not preallocated");
38442cf15c64SPierre 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);
3845cac4c232SBarry Smith   PetscUseMethod(A, "MatDenseRestoreColumnVecRead_C", (Mat, PetscInt, Vec *), (A, col, v));
38463ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
38476947451fSStefano Zampini }
38486947451fSStefano Zampini 
38490f74d2c1SSatish Balay /*@
3850fb850c59SBarry Smith   MatDenseGetColumnVecWrite - Gives write-only access to a column of a dense matrix, represented as a `Vec`.
38516947451fSStefano Zampini 
38526947451fSStefano Zampini   Collective
38536947451fSStefano Zampini 
38545ea7661aSPierre Jolivet   Input Parameters:
3855fe59aa6dSJacob Faibussowitsch + A   - the `Mat` object
38566947451fSStefano Zampini - col - the column index
38576947451fSStefano Zampini 
38586947451fSStefano Zampini   Output Parameter:
38596947451fSStefano Zampini . v - the vector
38606947451fSStefano Zampini 
38616947451fSStefano Zampini   Level: intermediate
38626947451fSStefano Zampini 
38632ef1f0ffSBarry Smith   Notes:
38642ef1f0ffSBarry Smith   The vector is owned by PETSc. Users need to call `MatDenseRestoreColumnVecWrite()` when the vector is no longer needed.
38652ef1f0ffSBarry Smith 
38662ef1f0ffSBarry Smith   Use `MatDenseGetColumnVec()` to obtain read-write access or `MatDenseGetColumnVecRead()` for read-only access.
38672ef1f0ffSBarry Smith 
38681cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATDENSE`, `MATDENSECUDA`, `MATDENSEHIP`, `MatDenseGetColumnVec()`, `MatDenseGetColumnVecRead()`, `MatDenseRestoreColumnVec()`, `MatDenseRestoreColumnVecRead()`, `MatDenseRestoreColumnVecWrite()`
38696947451fSStefano Zampini @*/
3870d71ae5a4SJacob Faibussowitsch PetscErrorCode MatDenseGetColumnVecWrite(Mat A, PetscInt col, Vec *v)
3871d71ae5a4SJacob Faibussowitsch {
38726947451fSStefano Zampini   PetscFunctionBegin;
38736947451fSStefano Zampini   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
38746947451fSStefano Zampini   PetscValidType(A, 1);
38756947451fSStefano Zampini   PetscValidLogicalCollectiveInt(A, col, 2);
38764f572ea9SToby Isaac   PetscAssertPointer(v, 3);
387728b400f6SJacob Faibussowitsch   PetscCheck(A->preallocated, PetscObjectComm((PetscObject)A), PETSC_ERR_ORDER, "Matrix not preallocated");
3878aed4548fSBarry 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);
3879cac4c232SBarry Smith   PetscUseMethod(A, "MatDenseGetColumnVecWrite_C", (Mat, PetscInt, Vec *), (A, col, v));
38803ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
38816947451fSStefano Zampini }
38826947451fSStefano Zampini 
38830f74d2c1SSatish Balay /*@
3884fb850c59SBarry Smith   MatDenseRestoreColumnVecWrite - Returns access to a column of a dense matrix obtained from `MatDenseGetColumnVecWrite()`.
38856947451fSStefano Zampini 
38866947451fSStefano Zampini   Collective
38876947451fSStefano Zampini 
38885ea7661aSPierre Jolivet   Input Parameters:
3889fe59aa6dSJacob Faibussowitsch + A   - the `Mat` object
38906947451fSStefano Zampini . col - the column index
38912ef1f0ffSBarry Smith - v   - the `Vec` object (may be `NULL`)
38926947451fSStefano Zampini 
38936947451fSStefano Zampini   Level: intermediate
38946947451fSStefano Zampini 
38951cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATDENSE`, `MATDENSECUDA`, `MATDENSEHIP`, `MatDenseGetColumnVec()`, `MatDenseGetColumnVecRead()`, `MatDenseGetColumnVecWrite()`, `MatDenseRestoreColumnVec()`, `MatDenseRestoreColumnVecRead()`
38966947451fSStefano Zampini @*/
3897d71ae5a4SJacob Faibussowitsch PetscErrorCode MatDenseRestoreColumnVecWrite(Mat A, PetscInt col, Vec *v)
3898d71ae5a4SJacob Faibussowitsch {
38996947451fSStefano Zampini   PetscFunctionBegin;
39006947451fSStefano Zampini   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
39016947451fSStefano Zampini   PetscValidType(A, 1);
39026947451fSStefano Zampini   PetscValidLogicalCollectiveInt(A, col, 2);
390308401ef6SPierre Jolivet   PetscCheck(A->preallocated, PetscObjectComm((PetscObject)A), PETSC_ERR_ORDER, "Matrix not preallocated");
3904aed4548fSBarry 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);
3905cac4c232SBarry Smith   PetscUseMethod(A, "MatDenseRestoreColumnVecWrite_C", (Mat, PetscInt, Vec *), (A, col, v));
39063ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
39076947451fSStefano Zampini }
39085ea7661aSPierre Jolivet 
39090f74d2c1SSatish Balay /*@
3910fb850c59SBarry Smith   MatDenseGetSubMatrix - Gives access to a block of rows and columns of a dense matrix, represented as a `Mat`.
39115ea7661aSPierre Jolivet 
39125ea7661aSPierre Jolivet   Collective
39135ea7661aSPierre Jolivet 
39145ea7661aSPierre Jolivet   Input Parameters:
3915fb850c59SBarry Smith + A      - the `Mat` object
39162ef1f0ffSBarry Smith . rbegin - the first global row index in the block (if `PETSC_DECIDE`, is 0)
39172ef1f0ffSBarry Smith . rend   - the global row index past the last one in the block (if `PETSC_DECIDE`, is `M`)
39182ef1f0ffSBarry Smith . cbegin - the first global column index in the block (if `PETSC_DECIDE`, is 0)
39192ef1f0ffSBarry Smith - cend   - the global column index past the last one in the block (if `PETSC_DECIDE`, is `N`)
39205ea7661aSPierre Jolivet 
39215ea7661aSPierre Jolivet   Output Parameter:
39225ea7661aSPierre Jolivet . v - the matrix
39235ea7661aSPierre Jolivet 
39245ea7661aSPierre Jolivet   Level: intermediate
39255ea7661aSPierre Jolivet 
39262ef1f0ffSBarry Smith   Notes:
39272ef1f0ffSBarry Smith   The matrix is owned by PETSc. Users need to call `MatDenseRestoreSubMatrix()` when the matrix is no longer needed.
39282ef1f0ffSBarry Smith 
39292ef1f0ffSBarry 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.
39302ef1f0ffSBarry Smith 
39311cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATDENSE`, `MATDENSECUDA`, `MATDENSEHIP`, `MatDenseGetColumnVec()`, `MatDenseRestoreColumnVec()`, `MatDenseRestoreSubMatrix()`
39325ea7661aSPierre Jolivet @*/
3933d71ae5a4SJacob Faibussowitsch PetscErrorCode MatDenseGetSubMatrix(Mat A, PetscInt rbegin, PetscInt rend, PetscInt cbegin, PetscInt cend, Mat *v)
3934d71ae5a4SJacob Faibussowitsch {
39355ea7661aSPierre Jolivet   PetscFunctionBegin;
39365ea7661aSPierre Jolivet   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
39375ea7661aSPierre Jolivet   PetscValidType(A, 1);
3938a2748737SPierre Jolivet   PetscValidLogicalCollectiveInt(A, rbegin, 2);
3939a2748737SPierre Jolivet   PetscValidLogicalCollectiveInt(A, rend, 3);
3940a2748737SPierre Jolivet   PetscValidLogicalCollectiveInt(A, cbegin, 4);
3941a2748737SPierre Jolivet   PetscValidLogicalCollectiveInt(A, cend, 5);
39424f572ea9SToby Isaac   PetscAssertPointer(v, 6);
3943a2748737SPierre Jolivet   if (rbegin == PETSC_DECIDE) rbegin = 0;
3944a2748737SPierre Jolivet   if (rend == PETSC_DECIDE) rend = A->rmap->N;
3945a2748737SPierre Jolivet   if (cbegin == PETSC_DECIDE) cbegin = 0;
3946a2748737SPierre Jolivet   if (cend == PETSC_DECIDE) cend = A->cmap->N;
394728b400f6SJacob Faibussowitsch   PetscCheck(A->preallocated, PetscObjectComm((PetscObject)A), PETSC_ERR_ORDER, "Matrix not preallocated");
3948a2748737SPierre 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);
3949a2748737SPierre 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);
3950a2748737SPierre 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);
3951a2748737SPierre 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);
3952a2748737SPierre Jolivet   PetscUseMethod(A, "MatDenseGetSubMatrix_C", (Mat, PetscInt, PetscInt, PetscInt, PetscInt, Mat *), (A, rbegin, rend, cbegin, cend, v));
39533ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
39545ea7661aSPierre Jolivet }
39555ea7661aSPierre Jolivet 
39560f74d2c1SSatish Balay /*@
3957fb850c59SBarry Smith   MatDenseRestoreSubMatrix - Returns access to a block of columns of a dense matrix obtained from `MatDenseGetSubMatrix()`.
39585ea7661aSPierre Jolivet 
39595ea7661aSPierre Jolivet   Collective
39605ea7661aSPierre Jolivet 
39615ea7661aSPierre Jolivet   Input Parameters:
3962fe59aa6dSJacob Faibussowitsch + A - the `Mat` object
39632ef1f0ffSBarry Smith - v - the `Mat` object (may be `NULL`)
39645ea7661aSPierre Jolivet 
39655ea7661aSPierre Jolivet   Level: intermediate
39665ea7661aSPierre Jolivet 
39671cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATDENSE`, `MATDENSECUDA`, `MATDENSEHIP`, `MatDenseGetColumnVec()`, `MatDenseRestoreColumnVec()`, `MatDenseGetSubMatrix()`
39685ea7661aSPierre Jolivet @*/
3969d71ae5a4SJacob Faibussowitsch PetscErrorCode MatDenseRestoreSubMatrix(Mat A, Mat *v)
3970d71ae5a4SJacob Faibussowitsch {
39715ea7661aSPierre Jolivet   PetscFunctionBegin;
39725ea7661aSPierre Jolivet   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
39735ea7661aSPierre Jolivet   PetscValidType(A, 1);
39744f572ea9SToby Isaac   PetscAssertPointer(v, 2);
3975cac4c232SBarry Smith   PetscUseMethod(A, "MatDenseRestoreSubMatrix_C", (Mat, Mat *), (A, v));
39763ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
39775ea7661aSPierre Jolivet }
39788a9c020eSBarry Smith 
39798a9c020eSBarry Smith #include <petscblaslapack.h>
39808a9c020eSBarry Smith #include <petsc/private/kernels/blockinvert.h>
39818a9c020eSBarry Smith 
3982d71ae5a4SJacob Faibussowitsch PetscErrorCode MatSeqDenseInvert(Mat A)
3983d71ae5a4SJacob Faibussowitsch {
3984d63b1753SJacob Faibussowitsch   PetscInt        m;
39858a9c020eSBarry Smith   const PetscReal shift = 0.0;
3986d63b1753SJacob Faibussowitsch   PetscBool       allowzeropivot, zeropivotdetected = PETSC_FALSE;
3987d63b1753SJacob Faibussowitsch   PetscScalar    *values;
39888a9c020eSBarry Smith 
39898a9c020eSBarry Smith   PetscFunctionBegin;
3990d63b1753SJacob Faibussowitsch   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
3991d63b1753SJacob Faibussowitsch   PetscCall(MatDenseGetArray(A, &values));
3992d63b1753SJacob Faibussowitsch   PetscCall(MatGetLocalSize(A, &m, NULL));
3993d63b1753SJacob Faibussowitsch   allowzeropivot = PetscNot(A->erroriffailure);
39948a9c020eSBarry Smith   /* factor and invert each block */
3995d63b1753SJacob Faibussowitsch   switch (m) {
3996d71ae5a4SJacob Faibussowitsch   case 1:
3997d71ae5a4SJacob Faibussowitsch     values[0] = (PetscScalar)1.0 / (values[0] + shift);
3998d71ae5a4SJacob Faibussowitsch     break;
39998a9c020eSBarry Smith   case 2:
40008a9c020eSBarry Smith     PetscCall(PetscKernel_A_gets_inverse_A_2(values, shift, allowzeropivot, &zeropivotdetected));
40018a9c020eSBarry Smith     if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
40028a9c020eSBarry Smith     break;
40038a9c020eSBarry Smith   case 3:
40048a9c020eSBarry Smith     PetscCall(PetscKernel_A_gets_inverse_A_3(values, shift, allowzeropivot, &zeropivotdetected));
40058a9c020eSBarry Smith     if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
40068a9c020eSBarry Smith     break;
40078a9c020eSBarry Smith   case 4:
40088a9c020eSBarry Smith     PetscCall(PetscKernel_A_gets_inverse_A_4(values, shift, allowzeropivot, &zeropivotdetected));
40098a9c020eSBarry Smith     if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
40108a9c020eSBarry Smith     break;
40119371c9d4SSatish Balay   case 5: {
40128a9c020eSBarry Smith     PetscScalar work[25];
40138a9c020eSBarry Smith     PetscInt    ipvt[5];
40148a9c020eSBarry Smith 
40158a9c020eSBarry Smith     PetscCall(PetscKernel_A_gets_inverse_A_5(values, ipvt, work, shift, allowzeropivot, &zeropivotdetected));
40168a9c020eSBarry Smith     if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
40179371c9d4SSatish Balay   } break;
40188a9c020eSBarry Smith   case 6:
40198a9c020eSBarry Smith     PetscCall(PetscKernel_A_gets_inverse_A_6(values, shift, allowzeropivot, &zeropivotdetected));
40208a9c020eSBarry Smith     if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
40218a9c020eSBarry Smith     break;
40228a9c020eSBarry Smith   case 7:
40238a9c020eSBarry Smith     PetscCall(PetscKernel_A_gets_inverse_A_7(values, shift, allowzeropivot, &zeropivotdetected));
40248a9c020eSBarry Smith     if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
40258a9c020eSBarry Smith     break;
40269371c9d4SSatish Balay   default: {
40278a9c020eSBarry Smith     PetscInt    *v_pivots, *IJ, j;
40288a9c020eSBarry Smith     PetscScalar *v_work;
40298a9c020eSBarry Smith 
4030d63b1753SJacob Faibussowitsch     PetscCall(PetscMalloc3(m, &v_work, m, &v_pivots, m, &IJ));
4031d63b1753SJacob Faibussowitsch     for (j = 0; j < m; j++) IJ[j] = j;
4032d63b1753SJacob Faibussowitsch     PetscCall(PetscKernel_A_gets_inverse_A(m, values, v_pivots, v_work, allowzeropivot, &zeropivotdetected));
40338a9c020eSBarry Smith     if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
40348a9c020eSBarry Smith     PetscCall(PetscFree3(v_work, v_pivots, IJ));
40358a9c020eSBarry Smith   }
40368a9c020eSBarry Smith   }
4037d63b1753SJacob Faibussowitsch   PetscCall(MatDenseRestoreArray(A, &values));
40383ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
40398a9c020eSBarry Smith }
4040