xref: /petsc/src/mat/impls/dense/seq/dense.c (revision 4186a4bb9c9e1da753bf42af334fff45208f4065)
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>
11*4186a4bbSPierre Jolivet #include <petsc/private/vecimpl.h>
12b2573a8aSBarry Smith 
13d71ae5a4SJacob Faibussowitsch PetscErrorCode MatSeqDenseSymmetrize_Private(Mat A, PetscBool hermitian)
14d71ae5a4SJacob Faibussowitsch {
158c178816SStefano Zampini   Mat_SeqDense *mat = (Mat_SeqDense *)A->data;
168c178816SStefano Zampini   PetscInt      j, k, n = A->rmap->n;
17ca15aa20SStefano Zampini   PetscScalar  *v;
188c178816SStefano Zampini 
198c178816SStefano Zampini   PetscFunctionBegin;
2008401ef6SPierre Jolivet   PetscCheck(A->rmap->n == A->cmap->n, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Cannot symmetrize a rectangular matrix");
219566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArray(A, &v));
228c178816SStefano Zampini   if (!hermitian) {
238c178816SStefano Zampini     for (k = 0; k < n; k++) {
24ad540459SPierre Jolivet       for (j = k; j < n; j++) v[j * mat->lda + k] = v[k * mat->lda + j];
258c178816SStefano Zampini     }
268c178816SStefano Zampini   } else {
278c178816SStefano Zampini     for (k = 0; k < n; k++) {
28ad540459SPierre Jolivet       for (j = k; j < n; j++) v[j * mat->lda + k] = PetscConj(v[k * mat->lda + j]);
298c178816SStefano Zampini     }
308c178816SStefano Zampini   }
319566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArray(A, &v));
323ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
338c178816SStefano Zampini }
348c178816SStefano Zampini 
35ff6a9541SJacob Faibussowitsch PetscErrorCode MatSeqDenseInvertFactors_Private(Mat A)
36d71ae5a4SJacob Faibussowitsch {
378c178816SStefano Zampini   Mat_SeqDense *mat = (Mat_SeqDense *)A->data;
388c178816SStefano Zampini   PetscBLASInt  info, n;
398c178816SStefano Zampini 
408c178816SStefano Zampini   PetscFunctionBegin;
413ba16761SJacob Faibussowitsch   if (!A->rmap->n || !A->cmap->n) PetscFunctionReturn(PETSC_SUCCESS);
429566063dSJacob Faibussowitsch   PetscCall(PetscBLASIntCast(A->cmap->n, &n));
438c178816SStefano Zampini   if (A->factortype == MAT_FACTOR_LU) {
4428b400f6SJacob Faibussowitsch     PetscCheck(mat->pivots, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Pivots not present");
458c178816SStefano Zampini     if (!mat->fwork) {
468c178816SStefano Zampini       mat->lfwork = n;
479566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(mat->lfwork, &mat->fwork));
488c178816SStefano Zampini     }
499566063dSJacob Faibussowitsch     PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF));
50792fecdfSBarry Smith     PetscCallBLAS("LAPACKgetri", LAPACKgetri_(&n, mat->v, &mat->lda, mat->pivots, mat->fwork, &mat->lfwork, &info));
519566063dSJacob Faibussowitsch     PetscCall(PetscFPTrapPop());
529566063dSJacob Faibussowitsch     PetscCall(PetscLogFlops((1.0 * A->cmap->n * A->cmap->n * A->cmap->n) / 3.0));
538c178816SStefano Zampini   } else if (A->factortype == MAT_FACTOR_CHOLESKY) {
54b94d7dedSBarry Smith     if (A->spd == PETSC_BOOL3_TRUE) {
559566063dSJacob Faibussowitsch       PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF));
56792fecdfSBarry Smith       PetscCallBLAS("LAPACKpotri", LAPACKpotri_("L", &n, mat->v, &mat->lda, &info));
579566063dSJacob Faibussowitsch       PetscCall(PetscFPTrapPop());
589566063dSJacob Faibussowitsch       PetscCall(MatSeqDenseSymmetrize_Private(A, PETSC_TRUE));
598c178816SStefano Zampini #if defined(PETSC_USE_COMPLEX)
60b94d7dedSBarry Smith     } else if (A->hermitian == PETSC_BOOL3_TRUE) {
6128b400f6SJacob Faibussowitsch       PetscCheck(mat->pivots, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Pivots not present");
6228b400f6SJacob Faibussowitsch       PetscCheck(mat->fwork, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Fwork not present");
639566063dSJacob Faibussowitsch       PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF));
64792fecdfSBarry Smith       PetscCallBLAS("LAPACKhetri", LAPACKhetri_("L", &n, mat->v, &mat->lda, mat->pivots, mat->fwork, &info));
659566063dSJacob Faibussowitsch       PetscCall(PetscFPTrapPop());
669566063dSJacob Faibussowitsch       PetscCall(MatSeqDenseSymmetrize_Private(A, PETSC_TRUE));
678c178816SStefano Zampini #endif
688c178816SStefano Zampini     } else { /* symmetric case */
6928b400f6SJacob Faibussowitsch       PetscCheck(mat->pivots, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Pivots not present");
7028b400f6SJacob Faibussowitsch       PetscCheck(mat->fwork, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Fwork not present");
719566063dSJacob Faibussowitsch       PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF));
72792fecdfSBarry Smith       PetscCallBLAS("LAPACKsytri", LAPACKsytri_("L", &n, mat->v, &mat->lda, mat->pivots, mat->fwork, &info));
739566063dSJacob Faibussowitsch       PetscCall(PetscFPTrapPop());
749566063dSJacob Faibussowitsch       PetscCall(MatSeqDenseSymmetrize_Private(A, PETSC_FALSE));
758c178816SStefano Zampini     }
7628b400f6SJacob Faibussowitsch     PetscCheck(!info, PETSC_COMM_SELF, PETSC_ERR_MAT_CH_ZRPVT, "Bad Inversion: zero pivot in row %" PetscInt_FMT, (PetscInt)info - 1);
779566063dSJacob Faibussowitsch     PetscCall(PetscLogFlops((1.0 * A->cmap->n * A->cmap->n * A->cmap->n) / 3.0));
788c178816SStefano Zampini   } else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Matrix must be factored to solve");
798c178816SStefano Zampini 
808c178816SStefano Zampini   A->ops->solve             = NULL;
818c178816SStefano Zampini   A->ops->matsolve          = NULL;
828c178816SStefano Zampini   A->ops->solvetranspose    = NULL;
838c178816SStefano Zampini   A->ops->matsolvetranspose = NULL;
848c178816SStefano Zampini   A->ops->solveadd          = NULL;
858c178816SStefano Zampini   A->ops->solvetransposeadd = NULL;
868c178816SStefano Zampini   A->factortype             = MAT_FACTOR_NONE;
879566063dSJacob Faibussowitsch   PetscCall(PetscFree(A->solvertype));
883ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
898c178816SStefano Zampini }
908c178816SStefano Zampini 
9166976f2fSJacob Faibussowitsch static PetscErrorCode MatZeroRowsColumns_SeqDense(Mat A, PetscInt N, const PetscInt rows[], PetscScalar diag, Vec x, Vec b)
92d71ae5a4SJacob Faibussowitsch {
933f49a652SStefano Zampini   Mat_SeqDense      *l = (Mat_SeqDense *)A->data;
943f49a652SStefano Zampini   PetscInt           m = l->lda, n = A->cmap->n, r = A->rmap->n, i, j;
95ca15aa20SStefano Zampini   PetscScalar       *slot, *bb, *v;
963f49a652SStefano Zampini   const PetscScalar *xx;
973f49a652SStefano Zampini 
983f49a652SStefano Zampini   PetscFunctionBegin;
9976bd3646SJed Brown   if (PetscDefined(USE_DEBUG)) {
1003f49a652SStefano Zampini     for (i = 0; i < N; i++) {
10108401ef6SPierre Jolivet       PetscCheck(rows[i] >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Negative row requested to be zeroed");
10208401ef6SPierre Jolivet       PetscCheck(rows[i] < A->rmap->n, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Row %" PetscInt_FMT " requested to be zeroed greater than or equal number of rows %" PetscInt_FMT, rows[i], A->rmap->n);
10308401ef6SPierre Jolivet       PetscCheck(rows[i] < A->cmap->n, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Col %" PetscInt_FMT " requested to be zeroed greater than or equal number of cols %" PetscInt_FMT, rows[i], A->cmap->n);
1043f49a652SStefano Zampini     }
10576bd3646SJed Brown   }
1063ba16761SJacob Faibussowitsch   if (!N) PetscFunctionReturn(PETSC_SUCCESS);
1073f49a652SStefano Zampini 
108dd8e379bSPierre Jolivet   /* fix right-hand side if needed */
1093f49a652SStefano Zampini   if (x && b) {
1106c4d906cSStefano Zampini     Vec xt;
1116c4d906cSStefano Zampini 
11208401ef6SPierre Jolivet     PetscCheck(A->rmap->n == A->cmap->n, PETSC_COMM_SELF, PETSC_ERR_SUP, "Only coded for square matrices");
1139566063dSJacob Faibussowitsch     PetscCall(VecDuplicate(x, &xt));
1149566063dSJacob Faibussowitsch     PetscCall(VecCopy(x, xt));
1159566063dSJacob Faibussowitsch     PetscCall(VecScale(xt, -1.0));
1169566063dSJacob Faibussowitsch     PetscCall(MatMultAdd(A, xt, b, b));
1179566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&xt));
1189566063dSJacob Faibussowitsch     PetscCall(VecGetArrayRead(x, &xx));
1199566063dSJacob Faibussowitsch     PetscCall(VecGetArray(b, &bb));
1203f49a652SStefano Zampini     for (i = 0; i < N; i++) bb[rows[i]] = diag * xx[rows[i]];
1219566063dSJacob Faibussowitsch     PetscCall(VecRestoreArrayRead(x, &xx));
1229566063dSJacob Faibussowitsch     PetscCall(VecRestoreArray(b, &bb));
1233f49a652SStefano Zampini   }
1243f49a652SStefano Zampini 
1259566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArray(A, &v));
1263f49a652SStefano Zampini   for (i = 0; i < N; i++) {
127ca15aa20SStefano Zampini     slot = v + rows[i] * m;
1289566063dSJacob Faibussowitsch     PetscCall(PetscArrayzero(slot, r));
1293f49a652SStefano Zampini   }
1303f49a652SStefano Zampini   for (i = 0; i < N; i++) {
131ca15aa20SStefano Zampini     slot = v + rows[i];
1329371c9d4SSatish Balay     for (j = 0; j < n; j++) {
1339371c9d4SSatish Balay       *slot = 0.0;
1349371c9d4SSatish Balay       slot += m;
1359371c9d4SSatish Balay     }
1363f49a652SStefano Zampini   }
1373f49a652SStefano Zampini   if (diag != 0.0) {
13808401ef6SPierre Jolivet     PetscCheck(A->rmap->n == A->cmap->n, PETSC_COMM_SELF, PETSC_ERR_SUP, "Only coded for square matrices");
1393f49a652SStefano Zampini     for (i = 0; i < N; i++) {
140ca15aa20SStefano Zampini       slot  = v + (m + 1) * rows[i];
1413f49a652SStefano Zampini       *slot = diag;
1423f49a652SStefano Zampini     }
1433f49a652SStefano Zampini   }
1449566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArray(A, &v));
1453ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1463f49a652SStefano Zampini }
1473f49a652SStefano Zampini 
148d71ae5a4SJacob Faibussowitsch PETSC_INTERN PetscErrorCode MatConvert_SeqAIJ_SeqDense(Mat A, MatType newtype, MatReuse reuse, Mat *newmat)
149d71ae5a4SJacob Faibussowitsch {
150a13144ffSStefano Zampini   Mat              B = NULL;
151b49cda9fSStefano Zampini   Mat_SeqAIJ      *a = (Mat_SeqAIJ *)A->data;
152b49cda9fSStefano Zampini   Mat_SeqDense    *b;
153b49cda9fSStefano Zampini   PetscInt        *ai = a->i, *aj = a->j, m = A->rmap->N, n = A->cmap->N, i;
1542e5835c6SStefano Zampini   const MatScalar *av;
155a13144ffSStefano Zampini   PetscBool        isseqdense;
156b49cda9fSStefano Zampini 
157b49cda9fSStefano Zampini   PetscFunctionBegin;
158a13144ffSStefano Zampini   if (reuse == MAT_REUSE_MATRIX) {
1599566063dSJacob Faibussowitsch     PetscCall(PetscObjectTypeCompare((PetscObject)*newmat, MATSEQDENSE, &isseqdense));
160f4f49eeaSPierre Jolivet     PetscCheck(isseqdense, PetscObjectComm((PetscObject)*newmat), PETSC_ERR_USER, "Cannot reuse matrix of type %s", ((PetscObject)*newmat)->type_name);
161a13144ffSStefano Zampini   }
162a13144ffSStefano Zampini   if (reuse != MAT_REUSE_MATRIX) {
1639566063dSJacob Faibussowitsch     PetscCall(MatCreate(PetscObjectComm((PetscObject)A), &B));
1649566063dSJacob Faibussowitsch     PetscCall(MatSetSizes(B, m, n, m, n));
1659566063dSJacob Faibussowitsch     PetscCall(MatSetType(B, MATSEQDENSE));
1669566063dSJacob Faibussowitsch     PetscCall(MatSeqDenseSetPreallocation(B, NULL));
167f4f49eeaSPierre Jolivet     b = (Mat_SeqDense *)B->data;
168a13144ffSStefano Zampini   } else {
169a13144ffSStefano Zampini     b = (Mat_SeqDense *)((*newmat)->data);
170e1ea5af7SJose E. Roman     for (i = 0; i < n; i++) PetscCall(PetscArrayzero(b->v + i * b->lda, m));
171a13144ffSStefano Zampini   }
1729566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJGetArrayRead(A, &av));
173b49cda9fSStefano Zampini   for (i = 0; i < m; i++) {
174b49cda9fSStefano Zampini     PetscInt j;
175b49cda9fSStefano Zampini     for (j = 0; j < ai[1] - ai[0]; j++) {
176e1ea5af7SJose E. Roman       b->v[*aj * b->lda + i] = *av;
177b49cda9fSStefano Zampini       aj++;
178b49cda9fSStefano Zampini       av++;
179b49cda9fSStefano Zampini     }
180b49cda9fSStefano Zampini     ai++;
181b49cda9fSStefano Zampini   }
1829566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJRestoreArrayRead(A, &av));
183b49cda9fSStefano Zampini 
184511c6705SHong Zhang   if (reuse == MAT_INPLACE_MATRIX) {
1859566063dSJacob Faibussowitsch     PetscCall(MatAssemblyBegin(B, MAT_FINAL_ASSEMBLY));
1869566063dSJacob Faibussowitsch     PetscCall(MatAssemblyEnd(B, MAT_FINAL_ASSEMBLY));
1879566063dSJacob Faibussowitsch     PetscCall(MatHeaderReplace(A, &B));
188b49cda9fSStefano Zampini   } else {
189a13144ffSStefano Zampini     if (B) *newmat = B;
1909566063dSJacob Faibussowitsch     PetscCall(MatAssemblyBegin(*newmat, MAT_FINAL_ASSEMBLY));
1919566063dSJacob Faibussowitsch     PetscCall(MatAssemblyEnd(*newmat, MAT_FINAL_ASSEMBLY));
192b49cda9fSStefano Zampini   }
1933ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
194b49cda9fSStefano Zampini }
195b49cda9fSStefano Zampini 
196d71ae5a4SJacob Faibussowitsch PETSC_INTERN PetscErrorCode MatConvert_SeqDense_SeqAIJ(Mat A, MatType newtype, MatReuse reuse, Mat *newmat)
197d71ae5a4SJacob Faibussowitsch {
1986d4ec7b0SPierre Jolivet   Mat           B = NULL;
1996a63e612SBarry Smith   Mat_SeqDense *a = (Mat_SeqDense *)A->data;
2009399e1b8SMatthew G. Knepley   PetscInt      i, j;
2019399e1b8SMatthew G. Knepley   PetscInt     *rows, *nnz;
2029399e1b8SMatthew G. Knepley   MatScalar    *aa = a->v, *vals;
2036a63e612SBarry Smith 
2046a63e612SBarry Smith   PetscFunctionBegin;
2059566063dSJacob Faibussowitsch   PetscCall(PetscCalloc3(A->rmap->n, &rows, A->rmap->n, &nnz, A->rmap->n, &vals));
2066d4ec7b0SPierre Jolivet   if (reuse != MAT_REUSE_MATRIX) {
2079566063dSJacob Faibussowitsch     PetscCall(MatCreate(PetscObjectComm((PetscObject)A), &B));
2089566063dSJacob Faibussowitsch     PetscCall(MatSetSizes(B, A->rmap->n, A->cmap->n, A->rmap->N, A->cmap->N));
2099566063dSJacob Faibussowitsch     PetscCall(MatSetType(B, MATSEQAIJ));
2109399e1b8SMatthew G. Knepley     for (j = 0; j < A->cmap->n; j++) {
2119371c9d4SSatish Balay       for (i = 0; i < A->rmap->n; i++)
2129371c9d4SSatish Balay         if (aa[i] != 0.0 || (i == j && A->cmap->n == A->rmap->n)) ++nnz[i];
2136a63e612SBarry Smith       aa += a->lda;
2146a63e612SBarry Smith     }
2159566063dSJacob Faibussowitsch     PetscCall(MatSeqAIJSetPreallocation(B, PETSC_DETERMINE, nnz));
2166d4ec7b0SPierre Jolivet   } else B = *newmat;
2179399e1b8SMatthew G. Knepley   aa = a->v;
2189399e1b8SMatthew G. Knepley   for (j = 0; j < A->cmap->n; j++) {
2199399e1b8SMatthew G. Knepley     PetscInt numRows = 0;
2209371c9d4SSatish Balay     for (i = 0; i < A->rmap->n; i++)
2219371c9d4SSatish Balay       if (aa[i] != 0.0 || (i == j && A->cmap->n == A->rmap->n)) {
2229371c9d4SSatish Balay         rows[numRows]   = i;
2239371c9d4SSatish Balay         vals[numRows++] = aa[i];
2249371c9d4SSatish Balay       }
2259566063dSJacob Faibussowitsch     PetscCall(MatSetValues(B, numRows, rows, 1, &j, vals, INSERT_VALUES));
2269399e1b8SMatthew G. Knepley     aa += a->lda;
2279399e1b8SMatthew G. Knepley   }
2289566063dSJacob Faibussowitsch   PetscCall(PetscFree3(rows, nnz, vals));
2299566063dSJacob Faibussowitsch   PetscCall(MatAssemblyBegin(B, MAT_FINAL_ASSEMBLY));
2309566063dSJacob Faibussowitsch   PetscCall(MatAssemblyEnd(B, MAT_FINAL_ASSEMBLY));
2316a63e612SBarry Smith 
232511c6705SHong Zhang   if (reuse == MAT_INPLACE_MATRIX) {
2339566063dSJacob Faibussowitsch     PetscCall(MatHeaderReplace(A, &B));
2346d4ec7b0SPierre Jolivet   } else if (reuse != MAT_REUSE_MATRIX) *newmat = B;
2353ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2366a63e612SBarry Smith }
2376a63e612SBarry Smith 
238d71ae5a4SJacob Faibussowitsch PetscErrorCode MatAXPY_SeqDense(Mat Y, PetscScalar alpha, Mat X, MatStructure str)
239d71ae5a4SJacob Faibussowitsch {
2401987afe7SBarry Smith   Mat_SeqDense      *x = (Mat_SeqDense *)X->data, *y = (Mat_SeqDense *)Y->data;
241ca15aa20SStefano Zampini   const PetscScalar *xv;
242ca15aa20SStefano Zampini   PetscScalar       *yv;
24323fff9afSBarry Smith   PetscBLASInt       N, m, ldax = 0, lday = 0, one = 1;
2443a40ed3dSBarry Smith 
2453a40ed3dSBarry Smith   PetscFunctionBegin;
2469566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArrayRead(X, &xv));
2479566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArray(Y, &yv));
2489566063dSJacob Faibussowitsch   PetscCall(PetscBLASIntCast(X->rmap->n * X->cmap->n, &N));
2499566063dSJacob Faibussowitsch   PetscCall(PetscBLASIntCast(X->rmap->n, &m));
2509566063dSJacob Faibussowitsch   PetscCall(PetscBLASIntCast(x->lda, &ldax));
2519566063dSJacob Faibussowitsch   PetscCall(PetscBLASIntCast(y->lda, &lday));
252a5ce6ee0Svictorle   if (ldax > m || lday > m) {
2538e3a54c0SPierre Jolivet     for (PetscInt j = 0; j < X->cmap->n; j++) PetscCallBLAS("BLASaxpy", BLASaxpy_(&m, &alpha, PetscSafePointerPlusOffset(xv, j * ldax), &one, PetscSafePointerPlusOffset(yv, j * lday), &one));
254a5ce6ee0Svictorle   } else {
255792fecdfSBarry Smith     PetscCallBLAS("BLASaxpy", BLASaxpy_(&N, &alpha, xv, &one, yv, &one));
256a5ce6ee0Svictorle   }
2579566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArrayRead(X, &xv));
2589566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArray(Y, &yv));
2599566063dSJacob Faibussowitsch   PetscCall(PetscLogFlops(PetscMax(2.0 * N - 1, 0)));
2603ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2611987afe7SBarry Smith }
2621987afe7SBarry Smith 
263d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatGetInfo_SeqDense(Mat A, MatInfoType flag, MatInfo *info)
264d71ae5a4SJacob Faibussowitsch {
265ca15aa20SStefano Zampini   PetscLogDouble N = A->rmap->n * A->cmap->n;
2663a40ed3dSBarry Smith 
2673a40ed3dSBarry Smith   PetscFunctionBegin;
2684e220ebcSLois Curfman McInnes   info->block_size        = 1.0;
269ca15aa20SStefano Zampini   info->nz_allocated      = N;
270ca15aa20SStefano Zampini   info->nz_used           = N;
271ca15aa20SStefano Zampini   info->nz_unneeded       = 0;
272ca15aa20SStefano Zampini   info->assemblies        = A->num_ass;
2734e220ebcSLois Curfman McInnes   info->mallocs           = 0;
2744dfa11a4SJacob Faibussowitsch   info->memory            = 0; /* REVIEW ME */
2754e220ebcSLois Curfman McInnes   info->fill_ratio_given  = 0;
2764e220ebcSLois Curfman McInnes   info->fill_ratio_needed = 0;
2774e220ebcSLois Curfman McInnes   info->factor_mallocs    = 0;
2783ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
279289bc588SBarry Smith }
280289bc588SBarry Smith 
281d71ae5a4SJacob Faibussowitsch PetscErrorCode MatScale_SeqDense(Mat A, PetscScalar alpha)
282d71ae5a4SJacob Faibussowitsch {
283273d9f13SBarry Smith   Mat_SeqDense *a = (Mat_SeqDense *)A->data;
284ca15aa20SStefano Zampini   PetscScalar  *v;
28523fff9afSBarry Smith   PetscBLASInt  one = 1, j, nz, lda = 0;
28680cd9d93SLois Curfman McInnes 
2873a40ed3dSBarry Smith   PetscFunctionBegin;
2889566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArray(A, &v));
2899566063dSJacob Faibussowitsch   PetscCall(PetscBLASIntCast(a->lda, &lda));
290d0f46423SBarry Smith   if (lda > A->rmap->n) {
2919566063dSJacob Faibussowitsch     PetscCall(PetscBLASIntCast(A->rmap->n, &nz));
29248a46eb9SPierre Jolivet     for (j = 0; j < A->cmap->n; j++) PetscCallBLAS("BLASscal", BLASscal_(&nz, &alpha, v + j * lda, &one));
293a5ce6ee0Svictorle   } else {
2949566063dSJacob Faibussowitsch     PetscCall(PetscBLASIntCast(A->rmap->n * A->cmap->n, &nz));
295792fecdfSBarry Smith     PetscCallBLAS("BLASscal", BLASscal_(&nz, &alpha, v, &one));
296a5ce6ee0Svictorle   }
29704cbc005SJose E. Roman   PetscCall(PetscLogFlops(A->rmap->n * A->cmap->n));
2989566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArray(A, &v));
2993ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
30080cd9d93SLois Curfman McInnes }
30180cd9d93SLois Curfman McInnes 
302d71ae5a4SJacob Faibussowitsch PetscErrorCode MatShift_SeqDense(Mat A, PetscScalar alpha)
303d71ae5a4SJacob Faibussowitsch {
3042f605a99SJose E. Roman   Mat_SeqDense *a = (Mat_SeqDense *)A->data;
3052f605a99SJose E. Roman   PetscScalar  *v;
3062f605a99SJose E. Roman   PetscInt      j, k;
3072f605a99SJose E. Roman 
3082f605a99SJose E. Roman   PetscFunctionBegin;
3092f605a99SJose E. Roman   PetscCall(MatDenseGetArray(A, &v));
3102f605a99SJose E. Roman   k = PetscMin(A->rmap->n, A->cmap->n);
3112f605a99SJose E. Roman   for (j = 0; j < k; j++) v[j + j * a->lda] += alpha;
3122f605a99SJose E. Roman   PetscCall(PetscLogFlops(k));
3132f605a99SJose E. Roman   PetscCall(MatDenseRestoreArray(A, &v));
3143ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3152f605a99SJose E. Roman }
3162f605a99SJose E. Roman 
317d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatIsHermitian_SeqDense(Mat A, PetscReal rtol, PetscBool *fl)
318d71ae5a4SJacob Faibussowitsch {
3191cbb95d3SBarry Smith   Mat_SeqDense      *a = (Mat_SeqDense *)A->data;
320ca15aa20SStefano Zampini   PetscInt           i, j, m = A->rmap->n, N = a->lda;
321ca15aa20SStefano Zampini   const PetscScalar *v;
3221cbb95d3SBarry Smith 
3231cbb95d3SBarry Smith   PetscFunctionBegin;
3241cbb95d3SBarry Smith   *fl = PETSC_FALSE;
3253ba16761SJacob Faibussowitsch   if (A->rmap->n != A->cmap->n) PetscFunctionReturn(PETSC_SUCCESS);
3269566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArrayRead(A, &v));
3271cbb95d3SBarry Smith   for (i = 0; i < m; i++) {
328ca15aa20SStefano Zampini     for (j = i; j < m; j++) {
329ad540459SPierre Jolivet       if (PetscAbsScalar(v[i + j * N] - PetscConj(v[j + i * N])) > rtol) goto restore;
3301cbb95d3SBarry Smith     }
331637a0070SStefano Zampini   }
3321cbb95d3SBarry Smith   *fl = PETSC_TRUE;
333637a0070SStefano Zampini restore:
3349566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArrayRead(A, &v));
3353ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
336637a0070SStefano Zampini }
337637a0070SStefano Zampini 
338d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatIsSymmetric_SeqDense(Mat A, PetscReal rtol, PetscBool *fl)
339d71ae5a4SJacob Faibussowitsch {
340637a0070SStefano Zampini   Mat_SeqDense      *a = (Mat_SeqDense *)A->data;
341637a0070SStefano Zampini   PetscInt           i, j, m = A->rmap->n, N = a->lda;
342637a0070SStefano Zampini   const PetscScalar *v;
343637a0070SStefano Zampini 
344637a0070SStefano Zampini   PetscFunctionBegin;
345637a0070SStefano Zampini   *fl = PETSC_FALSE;
3463ba16761SJacob Faibussowitsch   if (A->rmap->n != A->cmap->n) PetscFunctionReturn(PETSC_SUCCESS);
3479566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArrayRead(A, &v));
348637a0070SStefano Zampini   for (i = 0; i < m; i++) {
349637a0070SStefano Zampini     for (j = i; j < m; j++) {
350ad540459SPierre Jolivet       if (PetscAbsScalar(v[i + j * N] - v[j + i * N]) > rtol) goto restore;
351637a0070SStefano Zampini     }
352637a0070SStefano Zampini   }
353637a0070SStefano Zampini   *fl = PETSC_TRUE;
354637a0070SStefano Zampini restore:
3559566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArrayRead(A, &v));
3563ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3571cbb95d3SBarry Smith }
3581cbb95d3SBarry Smith 
359d71ae5a4SJacob Faibussowitsch PetscErrorCode MatDuplicateNoCreate_SeqDense(Mat newi, Mat A, MatDuplicateOption cpvalues)
360d71ae5a4SJacob Faibussowitsch {
361ca15aa20SStefano Zampini   Mat_SeqDense *mat = (Mat_SeqDense *)A->data;
36223fc5dcaSStefano Zampini   PetscInt      lda = (PetscInt)mat->lda, j, m, nlda = lda;
36375f6d85dSStefano Zampini   PetscBool     isdensecpu;
364b24902e0SBarry Smith 
365b24902e0SBarry Smith   PetscFunctionBegin;
3669566063dSJacob Faibussowitsch   PetscCall(PetscLayoutReference(A->rmap, &newi->rmap));
3679566063dSJacob Faibussowitsch   PetscCall(PetscLayoutReference(A->cmap, &newi->cmap));
36823fc5dcaSStefano Zampini   if (cpvalues == MAT_SHARE_NONZERO_PATTERN) { /* propagate LDA */
3699566063dSJacob Faibussowitsch     PetscCall(MatDenseSetLDA(newi, lda));
37023fc5dcaSStefano Zampini   }
3719566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)newi, MATSEQDENSE, &isdensecpu));
3729566063dSJacob Faibussowitsch   if (isdensecpu) PetscCall(MatSeqDenseSetPreallocation(newi, NULL));
373b24902e0SBarry Smith   if (cpvalues == MAT_COPY_VALUES) {
374ca15aa20SStefano Zampini     const PetscScalar *av;
375ca15aa20SStefano Zampini     PetscScalar       *v;
376ca15aa20SStefano Zampini 
3779566063dSJacob Faibussowitsch     PetscCall(MatDenseGetArrayRead(A, &av));
3789566063dSJacob Faibussowitsch     PetscCall(MatDenseGetArrayWrite(newi, &v));
3799566063dSJacob Faibussowitsch     PetscCall(MatDenseGetLDA(newi, &nlda));
380d0f46423SBarry Smith     m = A->rmap->n;
38123fc5dcaSStefano Zampini     if (lda > m || nlda > m) {
3828e3a54c0SPierre Jolivet       for (j = 0; j < A->cmap->n; j++) PetscCall(PetscArraycpy(PetscSafePointerPlusOffset(v, j * nlda), PetscSafePointerPlusOffset(av, j * lda), m));
383b24902e0SBarry Smith     } else {
3849566063dSJacob Faibussowitsch       PetscCall(PetscArraycpy(v, av, A->rmap->n * A->cmap->n));
385b24902e0SBarry Smith     }
3869566063dSJacob Faibussowitsch     PetscCall(MatDenseRestoreArrayWrite(newi, &v));
3879566063dSJacob Faibussowitsch     PetscCall(MatDenseRestoreArrayRead(A, &av));
388b24902e0SBarry Smith   }
3893ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
390b24902e0SBarry Smith }
391b24902e0SBarry Smith 
392d71ae5a4SJacob Faibussowitsch PetscErrorCode MatDuplicate_SeqDense(Mat A, MatDuplicateOption cpvalues, Mat *newmat)
393d71ae5a4SJacob Faibussowitsch {
3943a40ed3dSBarry Smith   PetscFunctionBegin;
3959566063dSJacob Faibussowitsch   PetscCall(MatCreate(PetscObjectComm((PetscObject)A), newmat));
3969566063dSJacob Faibussowitsch   PetscCall(MatSetSizes(*newmat, A->rmap->n, A->cmap->n, A->rmap->n, A->cmap->n));
3979566063dSJacob Faibussowitsch   PetscCall(MatSetType(*newmat, ((PetscObject)A)->type_name));
3989566063dSJacob Faibussowitsch   PetscCall(MatDuplicateNoCreate_SeqDense(*newmat, A, cpvalues));
3993ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
400b24902e0SBarry Smith }
401b24902e0SBarry Smith 
402d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatSolve_SeqDense_Internal_LU(Mat A, PetscScalar *x, PetscBLASInt ldx, PetscBLASInt m, PetscBLASInt nrhs, PetscBLASInt k, PetscBool T)
403d71ae5a4SJacob Faibussowitsch {
404c0bbcb79SLois Curfman McInnes   Mat_SeqDense *mat = (Mat_SeqDense *)A->data;
4054396437dSToby Isaac   PetscBLASInt  info;
40667e560aaSBarry Smith 
4073a40ed3dSBarry Smith   PetscFunctionBegin;
4089566063dSJacob Faibussowitsch   PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF));
409792fecdfSBarry Smith   PetscCallBLAS("LAPACKgetrs", LAPACKgetrs_(T ? "T" : "N", &m, &nrhs, mat->v, &mat->lda, mat->pivots, x, &m, &info));
4109566063dSJacob Faibussowitsch   PetscCall(PetscFPTrapPop());
41105fcb23eSStefano Zampini   PetscCheck(!info, PETSC_COMM_SELF, PETSC_ERR_LIB, "GETRS - Bad solve %d", (int)info);
4129566063dSJacob Faibussowitsch   PetscCall(PetscLogFlops(nrhs * (2.0 * m * m - m)));
4133ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4144396437dSToby Isaac }
4154396437dSToby Isaac 
4164396437dSToby Isaac static PetscErrorCode MatConjugate_SeqDense(Mat);
4174396437dSToby Isaac 
418d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatSolve_SeqDense_Internal_Cholesky(Mat A, PetscScalar *x, PetscBLASInt ldx, PetscBLASInt m, PetscBLASInt nrhs, PetscBLASInt k, PetscBool T)
419d71ae5a4SJacob Faibussowitsch {
4204396437dSToby Isaac   Mat_SeqDense *mat = (Mat_SeqDense *)A->data;
4214396437dSToby Isaac   PetscBLASInt  info;
4224396437dSToby Isaac 
4234396437dSToby Isaac   PetscFunctionBegin;
424b94d7dedSBarry Smith   if (A->spd == PETSC_BOOL3_TRUE) {
4259566063dSJacob Faibussowitsch     if (PetscDefined(USE_COMPLEX) && T) PetscCall(MatConjugate_SeqDense(A));
4269566063dSJacob Faibussowitsch     PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF));
427792fecdfSBarry Smith     PetscCallBLAS("LAPACKpotrs", LAPACKpotrs_("L", &m, &nrhs, mat->v, &mat->lda, x, &m, &info));
4289566063dSJacob Faibussowitsch     PetscCall(PetscFPTrapPop());
42905fcb23eSStefano Zampini     PetscCheck(!info, PETSC_COMM_SELF, PETSC_ERR_LIB, "POTRS Bad solve %d", (int)info);
4309566063dSJacob Faibussowitsch     if (PetscDefined(USE_COMPLEX) && T) PetscCall(MatConjugate_SeqDense(A));
431a49dc2a2SStefano Zampini #if defined(PETSC_USE_COMPLEX)
432b94d7dedSBarry Smith   } else if (A->hermitian == PETSC_BOOL3_TRUE) {
4339566063dSJacob Faibussowitsch     if (T) PetscCall(MatConjugate_SeqDense(A));
4349566063dSJacob Faibussowitsch     PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF));
435792fecdfSBarry Smith     PetscCallBLAS("LAPACKhetrs", LAPACKhetrs_("L", &m, &nrhs, mat->v, &mat->lda, mat->pivots, x, &m, &info));
4369566063dSJacob Faibussowitsch     PetscCall(PetscFPTrapPop());
43705fcb23eSStefano Zampini     PetscCheck(!info, PETSC_COMM_SELF, PETSC_ERR_LIB, "HETRS Bad solve %d", (int)info);
4389566063dSJacob Faibussowitsch     if (T) PetscCall(MatConjugate_SeqDense(A));
439a49dc2a2SStefano Zampini #endif
440a49dc2a2SStefano Zampini   } else { /* symmetric case */
4419566063dSJacob Faibussowitsch     PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF));
442792fecdfSBarry Smith     PetscCallBLAS("LAPACKsytrs", LAPACKsytrs_("L", &m, &nrhs, mat->v, &mat->lda, mat->pivots, x, &m, &info));
4439566063dSJacob Faibussowitsch     PetscCall(PetscFPTrapPop());
44405fcb23eSStefano Zampini     PetscCheck(!info, PETSC_COMM_SELF, PETSC_ERR_LIB, "SYTRS Bad solve %d", (int)info);
445a49dc2a2SStefano Zampini   }
4469566063dSJacob Faibussowitsch   PetscCall(PetscLogFlops(nrhs * (2.0 * m * m - m)));
4473ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4484396437dSToby Isaac }
44985e2c93fSHong Zhang 
450d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatSolve_SeqDense_Internal_QR(Mat A, PetscScalar *x, PetscBLASInt ldx, PetscBLASInt m, PetscBLASInt nrhs, PetscBLASInt k)
451d71ae5a4SJacob Faibussowitsch {
4524396437dSToby Isaac   Mat_SeqDense *mat = (Mat_SeqDense *)A->data;
4534396437dSToby Isaac   PetscBLASInt  info;
4544396437dSToby Isaac   char          trans;
4554396437dSToby Isaac 
4564396437dSToby Isaac   PetscFunctionBegin;
4574905a7bcSToby Isaac   if (PetscDefined(USE_COMPLEX)) {
4584905a7bcSToby Isaac     trans = 'C';
4594905a7bcSToby Isaac   } else {
4604905a7bcSToby Isaac     trans = 'T';
4614905a7bcSToby Isaac   }
4629566063dSJacob Faibussowitsch   PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF));
46305fcb23eSStefano Zampini   { /* lwork depends on the number of right-hand sides */
46405fcb23eSStefano Zampini     PetscBLASInt nlfwork, lfwork = -1;
46505fcb23eSStefano Zampini     PetscScalar  fwork;
46605fcb23eSStefano Zampini 
467792fecdfSBarry Smith     PetscCallBLAS("LAPACKormqr", LAPACKormqr_("L", &trans, &m, &nrhs, &mat->rank, mat->v, &mat->lda, mat->tau, x, &ldx, &fwork, &lfwork, &info));
46805fcb23eSStefano Zampini     nlfwork = (PetscBLASInt)PetscRealPart(fwork);
46905fcb23eSStefano Zampini     if (nlfwork > mat->lfwork) {
47005fcb23eSStefano Zampini       mat->lfwork = nlfwork;
47105fcb23eSStefano Zampini       PetscCall(PetscFree(mat->fwork));
47205fcb23eSStefano Zampini       PetscCall(PetscMalloc1(mat->lfwork, &mat->fwork));
47305fcb23eSStefano Zampini     }
47405fcb23eSStefano Zampini   }
475792fecdfSBarry Smith   PetscCallBLAS("LAPACKormqr", LAPACKormqr_("L", &trans, &m, &nrhs, &mat->rank, mat->v, &mat->lda, mat->tau, x, &ldx, mat->fwork, &mat->lfwork, &info));
4769566063dSJacob Faibussowitsch   PetscCall(PetscFPTrapPop());
47705fcb23eSStefano Zampini   PetscCheck(!info, PETSC_COMM_SELF, PETSC_ERR_LIB, "ORMQR - Bad orthogonal transform %d", (int)info);
4789566063dSJacob Faibussowitsch   PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF));
479792fecdfSBarry Smith   PetscCallBLAS("LAPACKtrtrs", LAPACKtrtrs_("U", "N", "N", &mat->rank, &nrhs, mat->v, &mat->lda, x, &ldx, &info));
4809566063dSJacob Faibussowitsch   PetscCall(PetscFPTrapPop());
48105fcb23eSStefano Zampini   PetscCheck(!info, PETSC_COMM_SELF, PETSC_ERR_LIB, "TRTRS - Bad triangular solve %d", (int)info);
4824905a7bcSToby Isaac   for (PetscInt j = 0; j < nrhs; j++) {
483ad540459SPierre Jolivet     for (PetscInt i = mat->rank; i < k; i++) x[j * ldx + i] = 0.;
4844905a7bcSToby Isaac   }
4859566063dSJacob Faibussowitsch   PetscCall(PetscLogFlops(nrhs * (4.0 * m * mat->rank - PetscSqr(mat->rank))));
4863ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4874905a7bcSToby Isaac }
4884905a7bcSToby Isaac 
489d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatSolveTranspose_SeqDense_Internal_QR(Mat A, PetscScalar *x, PetscBLASInt ldx, PetscBLASInt m, PetscBLASInt nrhs, PetscBLASInt k)
490d71ae5a4SJacob Faibussowitsch {
4914396437dSToby Isaac   Mat_SeqDense *mat = (Mat_SeqDense *)A->data;
4924396437dSToby Isaac   PetscBLASInt  info;
4934396437dSToby Isaac 
4944396437dSToby Isaac   PetscFunctionBegin;
4954396437dSToby Isaac   if (A->rmap->n == A->cmap->n && mat->rank == A->rmap->n) {
4969566063dSJacob Faibussowitsch     PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF));
497792fecdfSBarry Smith     PetscCallBLAS("LAPACKtrtrs", LAPACKtrtrs_("U", "T", "N", &m, &nrhs, mat->v, &mat->lda, x, &ldx, &info));
4989566063dSJacob Faibussowitsch     PetscCall(PetscFPTrapPop());
49905fcb23eSStefano Zampini     PetscCheck(!info, PETSC_COMM_SELF, PETSC_ERR_LIB, "TRTRS - Bad triangular solve %d", (int)info);
5009566063dSJacob Faibussowitsch     if (PetscDefined(USE_COMPLEX)) PetscCall(MatConjugate_SeqDense(A));
50105fcb23eSStefano Zampini     { /* lwork depends on the number of right-hand sides */
50205fcb23eSStefano Zampini       PetscBLASInt nlfwork, lfwork = -1;
50305fcb23eSStefano Zampini       PetscScalar  fwork;
50405fcb23eSStefano Zampini 
505792fecdfSBarry Smith       PetscCallBLAS("LAPACKormqr", LAPACKormqr_("L", "N", &m, &nrhs, &mat->rank, mat->v, &mat->lda, mat->tau, x, &ldx, &fwork, &lfwork, &info));
50605fcb23eSStefano Zampini       nlfwork = (PetscBLASInt)PetscRealPart(fwork);
50705fcb23eSStefano Zampini       if (nlfwork > mat->lfwork) {
50805fcb23eSStefano Zampini         mat->lfwork = nlfwork;
50905fcb23eSStefano Zampini         PetscCall(PetscFree(mat->fwork));
51005fcb23eSStefano Zampini         PetscCall(PetscMalloc1(mat->lfwork, &mat->fwork));
51105fcb23eSStefano Zampini       }
51205fcb23eSStefano Zampini     }
5139566063dSJacob Faibussowitsch     PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF));
514792fecdfSBarry Smith     PetscCallBLAS("LAPACKormqr", LAPACKormqr_("L", "N", &m, &nrhs, &mat->rank, mat->v, &mat->lda, mat->tau, x, &ldx, mat->fwork, &mat->lfwork, &info));
5159566063dSJacob Faibussowitsch     PetscCall(PetscFPTrapPop());
51605fcb23eSStefano Zampini     PetscCheck(!info, PETSC_COMM_SELF, PETSC_ERR_LIB, "ORMQR - Bad orthogonal transform %d", (int)info);
5179566063dSJacob Faibussowitsch     if (PetscDefined(USE_COMPLEX)) PetscCall(MatConjugate_SeqDense(A));
5184396437dSToby Isaac   } else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "QR factored matrix cannot be used for transpose solve");
5199566063dSJacob Faibussowitsch   PetscCall(PetscLogFlops(nrhs * (4.0 * m * mat->rank - PetscSqr(mat->rank))));
5203ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5214396437dSToby Isaac }
5224396437dSToby Isaac 
523d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatSolve_SeqDense_SetUp(Mat A, Vec xx, Vec yy, PetscScalar **_y, PetscBLASInt *_m, PetscBLASInt *_k)
524d71ae5a4SJacob Faibussowitsch {
5254396437dSToby Isaac   Mat_SeqDense *mat = (Mat_SeqDense *)A->data;
5264905a7bcSToby Isaac   PetscScalar  *y;
5274905a7bcSToby Isaac   PetscBLASInt  m = 0, k = 0;
5284905a7bcSToby Isaac 
5294905a7bcSToby Isaac   PetscFunctionBegin;
5309566063dSJacob Faibussowitsch   PetscCall(PetscBLASIntCast(A->rmap->n, &m));
5319566063dSJacob Faibussowitsch   PetscCall(PetscBLASIntCast(A->cmap->n, &k));
5324905a7bcSToby Isaac   if (k < m) {
5339566063dSJacob Faibussowitsch     PetscCall(VecCopy(xx, mat->qrrhs));
5349566063dSJacob Faibussowitsch     PetscCall(VecGetArray(mat->qrrhs, &y));
5354905a7bcSToby Isaac   } else {
5369566063dSJacob Faibussowitsch     PetscCall(VecCopy(xx, yy));
5379566063dSJacob Faibussowitsch     PetscCall(VecGetArray(yy, &y));
5384905a7bcSToby Isaac   }
5394396437dSToby Isaac   *_y = y;
5404396437dSToby Isaac   *_k = k;
5414396437dSToby Isaac   *_m = m;
5423ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5434396437dSToby Isaac }
5444396437dSToby Isaac 
545d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatSolve_SeqDense_TearDown(Mat A, Vec xx, Vec yy, PetscScalar **_y, PetscBLASInt *_m, PetscBLASInt *_k)
546d71ae5a4SJacob Faibussowitsch {
5474396437dSToby Isaac   Mat_SeqDense *mat = (Mat_SeqDense *)A->data;
54842e9364cSSatish Balay   PetscScalar  *y   = NULL;
5494396437dSToby Isaac   PetscBLASInt  m, k;
5504396437dSToby Isaac 
5514396437dSToby Isaac   PetscFunctionBegin;
5524396437dSToby Isaac   y   = *_y;
5534396437dSToby Isaac   *_y = NULL;
5544396437dSToby Isaac   k   = *_k;
5554396437dSToby Isaac   m   = *_m;
5564905a7bcSToby Isaac   if (k < m) {
5574905a7bcSToby Isaac     PetscScalar *yv;
5589566063dSJacob Faibussowitsch     PetscCall(VecGetArray(yy, &yv));
5599566063dSJacob Faibussowitsch     PetscCall(PetscArraycpy(yv, y, k));
5609566063dSJacob Faibussowitsch     PetscCall(VecRestoreArray(yy, &yv));
5619566063dSJacob Faibussowitsch     PetscCall(VecRestoreArray(mat->qrrhs, &y));
5624905a7bcSToby Isaac   } else {
5639566063dSJacob Faibussowitsch     PetscCall(VecRestoreArray(yy, &y));
5644905a7bcSToby Isaac   }
5653ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5664905a7bcSToby Isaac }
5674905a7bcSToby Isaac 
568d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatSolve_SeqDense_LU(Mat A, Vec xx, Vec yy)
569d71ae5a4SJacob Faibussowitsch {
57042e9364cSSatish Balay   PetscScalar *y = NULL;
57142e9364cSSatish Balay   PetscBLASInt m = 0, k = 0;
5724396437dSToby Isaac 
5734396437dSToby Isaac   PetscFunctionBegin;
5749566063dSJacob Faibussowitsch   PetscCall(MatSolve_SeqDense_SetUp(A, xx, yy, &y, &m, &k));
5759566063dSJacob Faibussowitsch   PetscCall(MatSolve_SeqDense_Internal_LU(A, y, m, m, 1, k, PETSC_FALSE));
5769566063dSJacob Faibussowitsch   PetscCall(MatSolve_SeqDense_TearDown(A, xx, yy, &y, &m, &k));
5773ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5784396437dSToby Isaac }
5794396437dSToby Isaac 
580d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatSolveTranspose_SeqDense_LU(Mat A, Vec xx, Vec yy)
581d71ae5a4SJacob Faibussowitsch {
58242e9364cSSatish Balay   PetscScalar *y = NULL;
58342e9364cSSatish Balay   PetscBLASInt m = 0, k = 0;
5844396437dSToby Isaac 
5854396437dSToby Isaac   PetscFunctionBegin;
5869566063dSJacob Faibussowitsch   PetscCall(MatSolve_SeqDense_SetUp(A, xx, yy, &y, &m, &k));
5879566063dSJacob Faibussowitsch   PetscCall(MatSolve_SeqDense_Internal_LU(A, y, m, m, 1, k, PETSC_TRUE));
5889566063dSJacob Faibussowitsch   PetscCall(MatSolve_SeqDense_TearDown(A, xx, yy, &y, &m, &k));
5893ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5904396437dSToby Isaac }
5914396437dSToby Isaac 
592d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatSolve_SeqDense_Cholesky(Mat A, Vec xx, Vec yy)
593d71ae5a4SJacob Faibussowitsch {
594e54beecaSStefano Zampini   PetscScalar *y = NULL;
595e54beecaSStefano Zampini   PetscBLASInt m = 0, k = 0;
5964396437dSToby Isaac 
5974396437dSToby Isaac   PetscFunctionBegin;
5989566063dSJacob Faibussowitsch   PetscCall(MatSolve_SeqDense_SetUp(A, xx, yy, &y, &m, &k));
5999566063dSJacob Faibussowitsch   PetscCall(MatSolve_SeqDense_Internal_Cholesky(A, y, m, m, 1, k, PETSC_FALSE));
6009566063dSJacob Faibussowitsch   PetscCall(MatSolve_SeqDense_TearDown(A, xx, yy, &y, &m, &k));
6013ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
6024396437dSToby Isaac }
6034396437dSToby Isaac 
604d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatSolveTranspose_SeqDense_Cholesky(Mat A, Vec xx, Vec yy)
605d71ae5a4SJacob Faibussowitsch {
606e54beecaSStefano Zampini   PetscScalar *y = NULL;
607e54beecaSStefano Zampini   PetscBLASInt m = 0, k = 0;
6084396437dSToby Isaac 
6094396437dSToby Isaac   PetscFunctionBegin;
6109566063dSJacob Faibussowitsch   PetscCall(MatSolve_SeqDense_SetUp(A, xx, yy, &y, &m, &k));
6119566063dSJacob Faibussowitsch   PetscCall(MatSolve_SeqDense_Internal_Cholesky(A, y, m, m, 1, k, PETSC_TRUE));
6129566063dSJacob Faibussowitsch   PetscCall(MatSolve_SeqDense_TearDown(A, xx, yy, &y, &m, &k));
6133ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
6144396437dSToby Isaac }
6154396437dSToby Isaac 
616d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatSolve_SeqDense_QR(Mat A, Vec xx, Vec yy)
617d71ae5a4SJacob Faibussowitsch {
618e54beecaSStefano Zampini   PetscScalar *y = NULL;
619e54beecaSStefano Zampini   PetscBLASInt m = 0, k = 0;
6204396437dSToby Isaac 
6214396437dSToby Isaac   PetscFunctionBegin;
6229566063dSJacob Faibussowitsch   PetscCall(MatSolve_SeqDense_SetUp(A, xx, yy, &y, &m, &k));
6239566063dSJacob Faibussowitsch   PetscCall(MatSolve_SeqDense_Internal_QR(A, y, PetscMax(m, k), m, 1, k));
6249566063dSJacob Faibussowitsch   PetscCall(MatSolve_SeqDense_TearDown(A, xx, yy, &y, &m, &k));
6253ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
6264396437dSToby Isaac }
6274396437dSToby Isaac 
628d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatSolveTranspose_SeqDense_QR(Mat A, Vec xx, Vec yy)
629d71ae5a4SJacob Faibussowitsch {
63042e9364cSSatish Balay   PetscScalar *y = NULL;
63142e9364cSSatish Balay   PetscBLASInt m = 0, k = 0;
6324396437dSToby Isaac 
6334396437dSToby Isaac   PetscFunctionBegin;
6349566063dSJacob Faibussowitsch   PetscCall(MatSolve_SeqDense_SetUp(A, xx, yy, &y, &m, &k));
6359566063dSJacob Faibussowitsch   PetscCall(MatSolveTranspose_SeqDense_Internal_QR(A, y, PetscMax(m, k), m, 1, k));
6369566063dSJacob Faibussowitsch   PetscCall(MatSolve_SeqDense_TearDown(A, xx, yy, &y, &m, &k));
6373ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
6384396437dSToby Isaac }
6394396437dSToby Isaac 
640d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatMatSolve_SeqDense_SetUp(Mat A, Mat B, Mat X, PetscScalar **_y, PetscBLASInt *_ldy, PetscBLASInt *_m, PetscBLASInt *_nrhs, PetscBLASInt *_k)
641d71ae5a4SJacob Faibussowitsch {
6424905a7bcSToby Isaac   const PetscScalar *b;
6434396437dSToby Isaac   PetscScalar       *y;
644bf5a80bcSToby Isaac   PetscInt           n, _ldb, _ldx;
645bf5a80bcSToby Isaac   PetscBLASInt       nrhs = 0, m = 0, k = 0, ldb = 0, ldx = 0, ldy = 0;
6464905a7bcSToby Isaac 
6474905a7bcSToby Isaac   PetscFunctionBegin;
6489371c9d4SSatish Balay   *_ldy  = 0;
6499371c9d4SSatish Balay   *_m    = 0;
6509371c9d4SSatish Balay   *_nrhs = 0;
6519371c9d4SSatish Balay   *_k    = 0;
6529371c9d4SSatish Balay   *_y    = NULL;
6539566063dSJacob Faibussowitsch   PetscCall(PetscBLASIntCast(A->rmap->n, &m));
6549566063dSJacob Faibussowitsch   PetscCall(PetscBLASIntCast(A->cmap->n, &k));
6559566063dSJacob Faibussowitsch   PetscCall(MatGetSize(B, NULL, &n));
6569566063dSJacob Faibussowitsch   PetscCall(PetscBLASIntCast(n, &nrhs));
6579566063dSJacob Faibussowitsch   PetscCall(MatDenseGetLDA(B, &_ldb));
6589566063dSJacob Faibussowitsch   PetscCall(PetscBLASIntCast(_ldb, &ldb));
6599566063dSJacob Faibussowitsch   PetscCall(MatDenseGetLDA(X, &_ldx));
6609566063dSJacob Faibussowitsch   PetscCall(PetscBLASIntCast(_ldx, &ldx));
661bf5a80bcSToby Isaac   if (ldx < m) {
6629566063dSJacob Faibussowitsch     PetscCall(MatDenseGetArrayRead(B, &b));
6639566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(nrhs * m, &y));
664bf5a80bcSToby Isaac     if (ldb == m) {
6659566063dSJacob Faibussowitsch       PetscCall(PetscArraycpy(y, b, ldb * nrhs));
6664905a7bcSToby Isaac     } else {
66748a46eb9SPierre Jolivet       for (PetscInt j = 0; j < nrhs; j++) PetscCall(PetscArraycpy(&y[j * m], &b[j * ldb], m));
6684905a7bcSToby Isaac     }
669bf5a80bcSToby Isaac     ldy = m;
6709566063dSJacob Faibussowitsch     PetscCall(MatDenseRestoreArrayRead(B, &b));
6714905a7bcSToby Isaac   } else {
672bf5a80bcSToby Isaac     if (ldb == ldx) {
6739566063dSJacob Faibussowitsch       PetscCall(MatCopy(B, X, SAME_NONZERO_PATTERN));
6749566063dSJacob Faibussowitsch       PetscCall(MatDenseGetArray(X, &y));
6754905a7bcSToby Isaac     } else {
6769566063dSJacob Faibussowitsch       PetscCall(MatDenseGetArray(X, &y));
6779566063dSJacob Faibussowitsch       PetscCall(MatDenseGetArrayRead(B, &b));
67848a46eb9SPierre Jolivet       for (PetscInt j = 0; j < nrhs; j++) PetscCall(PetscArraycpy(&y[j * ldx], &b[j * ldb], m));
6799566063dSJacob Faibussowitsch       PetscCall(MatDenseRestoreArrayRead(B, &b));
6804905a7bcSToby Isaac     }
681bf5a80bcSToby Isaac     ldy = ldx;
6824905a7bcSToby Isaac   }
6834396437dSToby Isaac   *_y    = y;
684bf5a80bcSToby Isaac   *_ldy  = ldy;
6854396437dSToby Isaac   *_k    = k;
6864396437dSToby Isaac   *_m    = m;
6874396437dSToby Isaac   *_nrhs = nrhs;
6883ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
6894396437dSToby Isaac }
6904396437dSToby Isaac 
691d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatMatSolve_SeqDense_TearDown(Mat A, Mat B, Mat X, PetscScalar **_y, PetscBLASInt *_ldy, PetscBLASInt *_m, PetscBLASInt *_nrhs, PetscBLASInt *_k)
692d71ae5a4SJacob Faibussowitsch {
6934396437dSToby Isaac   PetscScalar *y;
694bf5a80bcSToby Isaac   PetscInt     _ldx;
695bf5a80bcSToby Isaac   PetscBLASInt k, ldy, nrhs, ldx = 0;
6964396437dSToby Isaac 
6974396437dSToby Isaac   PetscFunctionBegin;
6984396437dSToby Isaac   y    = *_y;
6994396437dSToby Isaac   *_y  = NULL;
7004396437dSToby Isaac   k    = *_k;
701bf5a80bcSToby Isaac   ldy  = *_ldy;
7024396437dSToby Isaac   nrhs = *_nrhs;
7039566063dSJacob Faibussowitsch   PetscCall(MatDenseGetLDA(X, &_ldx));
7049566063dSJacob Faibussowitsch   PetscCall(PetscBLASIntCast(_ldx, &ldx));
705bf5a80bcSToby Isaac   if (ldx != ldy) {
7064905a7bcSToby Isaac     PetscScalar *xv;
7079566063dSJacob Faibussowitsch     PetscCall(MatDenseGetArray(X, &xv));
70848a46eb9SPierre Jolivet     for (PetscInt j = 0; j < nrhs; j++) PetscCall(PetscArraycpy(&xv[j * ldx], &y[j * ldy], k));
7099566063dSJacob Faibussowitsch     PetscCall(MatDenseRestoreArray(X, &xv));
7109566063dSJacob Faibussowitsch     PetscCall(PetscFree(y));
7114905a7bcSToby Isaac   } else {
7129566063dSJacob Faibussowitsch     PetscCall(MatDenseRestoreArray(X, &y));
7134905a7bcSToby Isaac   }
7143ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
71585e2c93fSHong Zhang }
71685e2c93fSHong Zhang 
717d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatMatSolve_SeqDense_LU(Mat A, Mat B, Mat X)
718d71ae5a4SJacob Faibussowitsch {
7194396437dSToby Isaac   PetscScalar *y;
720bf5a80bcSToby Isaac   PetscBLASInt m, k, ldy, nrhs;
7214396437dSToby Isaac 
7224396437dSToby Isaac   PetscFunctionBegin;
7239566063dSJacob Faibussowitsch   PetscCall(MatMatSolve_SeqDense_SetUp(A, B, X, &y, &ldy, &m, &nrhs, &k));
7249566063dSJacob Faibussowitsch   PetscCall(MatSolve_SeqDense_Internal_LU(A, y, ldy, m, nrhs, k, PETSC_FALSE));
7259566063dSJacob Faibussowitsch   PetscCall(MatMatSolve_SeqDense_TearDown(A, B, X, &y, &ldy, &m, &nrhs, &k));
7263ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
7274396437dSToby Isaac }
7284396437dSToby Isaac 
729d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatMatSolveTranspose_SeqDense_LU(Mat A, Mat B, Mat X)
730d71ae5a4SJacob Faibussowitsch {
7314396437dSToby Isaac   PetscScalar *y;
732bf5a80bcSToby Isaac   PetscBLASInt m, k, ldy, nrhs;
7334396437dSToby Isaac 
7344396437dSToby Isaac   PetscFunctionBegin;
7359566063dSJacob Faibussowitsch   PetscCall(MatMatSolve_SeqDense_SetUp(A, B, X, &y, &ldy, &m, &nrhs, &k));
7369566063dSJacob Faibussowitsch   PetscCall(MatSolve_SeqDense_Internal_LU(A, y, ldy, m, nrhs, k, PETSC_TRUE));
7379566063dSJacob Faibussowitsch   PetscCall(MatMatSolve_SeqDense_TearDown(A, B, X, &y, &ldy, &m, &nrhs, &k));
7383ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
7394396437dSToby Isaac }
7404396437dSToby Isaac 
741d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatMatSolve_SeqDense_Cholesky(Mat A, Mat B, Mat X)
742d71ae5a4SJacob Faibussowitsch {
7434396437dSToby Isaac   PetscScalar *y;
744bf5a80bcSToby Isaac   PetscBLASInt m, k, ldy, nrhs;
7454396437dSToby Isaac 
7464396437dSToby Isaac   PetscFunctionBegin;
7479566063dSJacob Faibussowitsch   PetscCall(MatMatSolve_SeqDense_SetUp(A, B, X, &y, &ldy, &m, &nrhs, &k));
7489566063dSJacob Faibussowitsch   PetscCall(MatSolve_SeqDense_Internal_Cholesky(A, y, ldy, m, nrhs, k, PETSC_FALSE));
7499566063dSJacob Faibussowitsch   PetscCall(MatMatSolve_SeqDense_TearDown(A, B, X, &y, &ldy, &m, &nrhs, &k));
7503ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
7514396437dSToby Isaac }
7524396437dSToby Isaac 
753d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatMatSolveTranspose_SeqDense_Cholesky(Mat A, Mat B, Mat X)
754d71ae5a4SJacob Faibussowitsch {
7554396437dSToby Isaac   PetscScalar *y;
756bf5a80bcSToby Isaac   PetscBLASInt m, k, ldy, nrhs;
7574396437dSToby Isaac 
7584396437dSToby Isaac   PetscFunctionBegin;
7599566063dSJacob Faibussowitsch   PetscCall(MatMatSolve_SeqDense_SetUp(A, B, X, &y, &ldy, &m, &nrhs, &k));
7609566063dSJacob Faibussowitsch   PetscCall(MatSolve_SeqDense_Internal_Cholesky(A, y, ldy, m, nrhs, k, PETSC_TRUE));
7619566063dSJacob Faibussowitsch   PetscCall(MatMatSolve_SeqDense_TearDown(A, B, X, &y, &ldy, &m, &nrhs, &k));
7623ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
7634396437dSToby Isaac }
7644396437dSToby Isaac 
765d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatMatSolve_SeqDense_QR(Mat A, Mat B, Mat X)
766d71ae5a4SJacob Faibussowitsch {
7674396437dSToby Isaac   PetscScalar *y;
768bf5a80bcSToby Isaac   PetscBLASInt m, k, ldy, nrhs;
7694396437dSToby Isaac 
7704396437dSToby Isaac   PetscFunctionBegin;
7719566063dSJacob Faibussowitsch   PetscCall(MatMatSolve_SeqDense_SetUp(A, B, X, &y, &ldy, &m, &nrhs, &k));
7729566063dSJacob Faibussowitsch   PetscCall(MatSolve_SeqDense_Internal_QR(A, y, ldy, m, nrhs, k));
7739566063dSJacob Faibussowitsch   PetscCall(MatMatSolve_SeqDense_TearDown(A, B, X, &y, &ldy, &m, &nrhs, &k));
7743ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
7754396437dSToby Isaac }
7764396437dSToby Isaac 
777d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatMatSolveTranspose_SeqDense_QR(Mat A, Mat B, Mat X)
778d71ae5a4SJacob Faibussowitsch {
7794396437dSToby Isaac   PetscScalar *y;
780bf5a80bcSToby Isaac   PetscBLASInt m, k, ldy, nrhs;
7814396437dSToby Isaac 
7824396437dSToby Isaac   PetscFunctionBegin;
7839566063dSJacob Faibussowitsch   PetscCall(MatMatSolve_SeqDense_SetUp(A, B, X, &y, &ldy, &m, &nrhs, &k));
7849566063dSJacob Faibussowitsch   PetscCall(MatSolveTranspose_SeqDense_Internal_QR(A, y, ldy, m, nrhs, k));
7859566063dSJacob Faibussowitsch   PetscCall(MatMatSolve_SeqDense_TearDown(A, B, X, &y, &ldy, &m, &nrhs, &k));
7863ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
7874396437dSToby Isaac }
7884396437dSToby Isaac 
789db4efbfdSBarry Smith /* COMMENT: I have chosen to hide row permutation in the pivots,
790db4efbfdSBarry Smith    rather than put it in the Mat->row slot.*/
791d71ae5a4SJacob Faibussowitsch PetscErrorCode MatLUFactor_SeqDense(Mat A, IS row, IS col, const MatFactorInfo *minfo)
792d71ae5a4SJacob Faibussowitsch {
793db4efbfdSBarry Smith   Mat_SeqDense *mat = (Mat_SeqDense *)A->data;
794db4efbfdSBarry Smith   PetscBLASInt  n, m, info;
795db4efbfdSBarry Smith 
796db4efbfdSBarry Smith   PetscFunctionBegin;
7979566063dSJacob Faibussowitsch   PetscCall(PetscBLASIntCast(A->cmap->n, &n));
7989566063dSJacob Faibussowitsch   PetscCall(PetscBLASIntCast(A->rmap->n, &m));
7994dfa11a4SJacob Faibussowitsch   if (!mat->pivots) { PetscCall(PetscMalloc1(A->rmap->n, &mat->pivots)); }
8003ba16761SJacob Faibussowitsch   if (!A->rmap->n || !A->cmap->n) PetscFunctionReturn(PETSC_SUCCESS);
8019566063dSJacob Faibussowitsch   PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF));
802792fecdfSBarry Smith   PetscCallBLAS("LAPACKgetrf", LAPACKgetrf_(&m, &n, mat->v, &mat->lda, mat->pivots, &info));
8039566063dSJacob Faibussowitsch   PetscCall(PetscFPTrapPop());
8048e57ea43SSatish Balay 
80505fcb23eSStefano Zampini   PetscCheck(info >= 0, PETSC_COMM_SELF, PETSC_ERR_LIB, "Bad argument to LU factorization %d", (int)info);
80605fcb23eSStefano Zampini   PetscCheck(info <= 0, PETSC_COMM_SELF, PETSC_ERR_MAT_LU_ZRPVT, "Bad LU factorization %d", (int)info);
8078208b9aeSStefano Zampini 
8084396437dSToby Isaac   A->ops->solve             = MatSolve_SeqDense_LU;
8094396437dSToby Isaac   A->ops->matsolve          = MatMatSolve_SeqDense_LU;
8104396437dSToby Isaac   A->ops->solvetranspose    = MatSolveTranspose_SeqDense_LU;
8114396437dSToby Isaac   A->ops->matsolvetranspose = MatMatSolveTranspose_SeqDense_LU;
812d5f3da31SBarry Smith   A->factortype             = MAT_FACTOR_LU;
813db4efbfdSBarry Smith 
8149566063dSJacob Faibussowitsch   PetscCall(PetscFree(A->solvertype));
8159566063dSJacob Faibussowitsch   PetscCall(PetscStrallocpy(MATSOLVERPETSC, &A->solvertype));
816f6224b95SHong Zhang 
8179566063dSJacob Faibussowitsch   PetscCall(PetscLogFlops((2.0 * A->cmap->n * A->cmap->n * A->cmap->n) / 3));
8183ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
819db4efbfdSBarry Smith }
820db4efbfdSBarry Smith 
821d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatLUFactorNumeric_SeqDense(Mat fact, Mat A, const MatFactorInfo *info_dummy)
822d71ae5a4SJacob Faibussowitsch {
8234396437dSToby Isaac   MatFactorInfo info;
8244396437dSToby Isaac 
8254396437dSToby Isaac   PetscFunctionBegin;
8269566063dSJacob Faibussowitsch   PetscCall(MatDuplicateNoCreate_SeqDense(fact, A, MAT_COPY_VALUES));
827dbbe0bcdSBarry Smith   PetscUseTypeMethod(fact, lufactor, NULL, NULL, &info);
8283ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
8294396437dSToby Isaac }
8304396437dSToby Isaac 
831d71ae5a4SJacob Faibussowitsch PetscErrorCode MatLUFactorSymbolic_SeqDense(Mat fact, Mat A, IS row, IS col, const MatFactorInfo *info)
832d71ae5a4SJacob Faibussowitsch {
8334396437dSToby Isaac   PetscFunctionBegin;
8344396437dSToby Isaac   fact->preallocated         = PETSC_TRUE;
8354396437dSToby Isaac   fact->assembled            = PETSC_TRUE;
8364396437dSToby Isaac   fact->ops->lufactornumeric = MatLUFactorNumeric_SeqDense;
8373ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
8384396437dSToby Isaac }
8394396437dSToby Isaac 
840a49dc2a2SStefano Zampini /* Cholesky as L*L^T or L*D*L^T and the symmetric/hermitian complex variants */
841d71ae5a4SJacob Faibussowitsch PetscErrorCode MatCholeskyFactor_SeqDense(Mat A, IS perm, const MatFactorInfo *factinfo)
842d71ae5a4SJacob Faibussowitsch {
843db4efbfdSBarry Smith   Mat_SeqDense *mat = (Mat_SeqDense *)A->data;
844c5df96a5SBarry Smith   PetscBLASInt  info, n;
845db4efbfdSBarry Smith 
846db4efbfdSBarry Smith   PetscFunctionBegin;
8479566063dSJacob Faibussowitsch   PetscCall(PetscBLASIntCast(A->cmap->n, &n));
8483ba16761SJacob Faibussowitsch   if (!A->rmap->n || !A->cmap->n) PetscFunctionReturn(PETSC_SUCCESS);
849b94d7dedSBarry Smith   if (A->spd == PETSC_BOOL3_TRUE) {
8509566063dSJacob Faibussowitsch     PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF));
851792fecdfSBarry Smith     PetscCallBLAS("LAPACKpotrf", LAPACKpotrf_("L", &n, mat->v, &mat->lda, &info));
8529566063dSJacob Faibussowitsch     PetscCall(PetscFPTrapPop());
853a49dc2a2SStefano Zampini #if defined(PETSC_USE_COMPLEX)
854b94d7dedSBarry Smith   } else if (A->hermitian == PETSC_BOOL3_TRUE) {
8554dfa11a4SJacob Faibussowitsch     if (!mat->pivots) { PetscCall(PetscMalloc1(A->rmap->n, &mat->pivots)); }
856a49dc2a2SStefano Zampini     if (!mat->fwork) {
857a49dc2a2SStefano Zampini       PetscScalar dummy;
858a49dc2a2SStefano Zampini 
859a49dc2a2SStefano Zampini       mat->lfwork = -1;
8609566063dSJacob Faibussowitsch       PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF));
861792fecdfSBarry Smith       PetscCallBLAS("LAPACKhetrf", LAPACKhetrf_("L", &n, mat->v, &mat->lda, mat->pivots, &dummy, &mat->lfwork, &info));
8629566063dSJacob Faibussowitsch       PetscCall(PetscFPTrapPop());
863a49dc2a2SStefano Zampini       mat->lfwork = (PetscInt)PetscRealPart(dummy);
8649566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(mat->lfwork, &mat->fwork));
865a49dc2a2SStefano Zampini     }
8669566063dSJacob Faibussowitsch     PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF));
867792fecdfSBarry Smith     PetscCallBLAS("LAPACKhetrf", LAPACKhetrf_("L", &n, mat->v, &mat->lda, mat->pivots, mat->fwork, &mat->lfwork, &info));
8689566063dSJacob Faibussowitsch     PetscCall(PetscFPTrapPop());
869a49dc2a2SStefano Zampini #endif
870a49dc2a2SStefano Zampini   } else { /* symmetric case */
8714dfa11a4SJacob Faibussowitsch     if (!mat->pivots) { PetscCall(PetscMalloc1(A->rmap->n, &mat->pivots)); }
872a49dc2a2SStefano Zampini     if (!mat->fwork) {
873a49dc2a2SStefano Zampini       PetscScalar dummy;
874a49dc2a2SStefano Zampini 
875a49dc2a2SStefano Zampini       mat->lfwork = -1;
8769566063dSJacob Faibussowitsch       PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF));
877792fecdfSBarry Smith       PetscCallBLAS("LAPACKsytrf", LAPACKsytrf_("L", &n, mat->v, &mat->lda, mat->pivots, &dummy, &mat->lfwork, &info));
8789566063dSJacob Faibussowitsch       PetscCall(PetscFPTrapPop());
879a49dc2a2SStefano Zampini       mat->lfwork = (PetscInt)PetscRealPart(dummy);
8809566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(mat->lfwork, &mat->fwork));
881a49dc2a2SStefano Zampini     }
8829566063dSJacob Faibussowitsch     PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF));
883792fecdfSBarry Smith     PetscCallBLAS("LAPACKsytrf", LAPACKsytrf_("L", &n, mat->v, &mat->lda, mat->pivots, mat->fwork, &mat->lfwork, &info));
8849566063dSJacob Faibussowitsch     PetscCall(PetscFPTrapPop());
885a49dc2a2SStefano Zampini   }
88628b400f6SJacob Faibussowitsch   PetscCheck(!info, PETSC_COMM_SELF, PETSC_ERR_MAT_CH_ZRPVT, "Bad factorization: zero pivot in row %" PetscInt_FMT, (PetscInt)info - 1);
8878208b9aeSStefano Zampini 
8884396437dSToby Isaac   A->ops->solve             = MatSolve_SeqDense_Cholesky;
8894396437dSToby Isaac   A->ops->matsolve          = MatMatSolve_SeqDense_Cholesky;
8904396437dSToby Isaac   A->ops->solvetranspose    = MatSolveTranspose_SeqDense_Cholesky;
8914396437dSToby Isaac   A->ops->matsolvetranspose = MatMatSolveTranspose_SeqDense_Cholesky;
892d5f3da31SBarry Smith   A->factortype             = MAT_FACTOR_CHOLESKY;
8932205254eSKarl Rupp 
8949566063dSJacob Faibussowitsch   PetscCall(PetscFree(A->solvertype));
8959566063dSJacob Faibussowitsch   PetscCall(PetscStrallocpy(MATSOLVERPETSC, &A->solvertype));
896f6224b95SHong Zhang 
8979566063dSJacob Faibussowitsch   PetscCall(PetscLogFlops((1.0 * A->cmap->n * A->cmap->n * A->cmap->n) / 3.0));
8983ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
899db4efbfdSBarry Smith }
900db4efbfdSBarry Smith 
901d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatCholeskyFactorNumeric_SeqDense(Mat fact, Mat A, const MatFactorInfo *info_dummy)
902d71ae5a4SJacob Faibussowitsch {
903db4efbfdSBarry Smith   MatFactorInfo info;
904db4efbfdSBarry Smith 
905db4efbfdSBarry Smith   PetscFunctionBegin;
906db4efbfdSBarry Smith   info.fill = 1.0;
9072205254eSKarl Rupp 
9089566063dSJacob Faibussowitsch   PetscCall(MatDuplicateNoCreate_SeqDense(fact, A, MAT_COPY_VALUES));
909dbbe0bcdSBarry Smith   PetscUseTypeMethod(fact, choleskyfactor, NULL, &info);
9103ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
911db4efbfdSBarry Smith }
912db4efbfdSBarry Smith 
913d71ae5a4SJacob Faibussowitsch PetscErrorCode MatCholeskyFactorSymbolic_SeqDense(Mat fact, Mat A, IS row, const MatFactorInfo *info)
914d71ae5a4SJacob Faibussowitsch {
915db4efbfdSBarry Smith   PetscFunctionBegin;
916c3ef05f6SHong Zhang   fact->assembled                  = PETSC_TRUE;
9171bbcc794SSatish Balay   fact->preallocated               = PETSC_TRUE;
918719d5645SBarry Smith   fact->ops->choleskyfactornumeric = MatCholeskyFactorNumeric_SeqDense;
9193ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
920db4efbfdSBarry Smith }
921db4efbfdSBarry Smith 
922d71ae5a4SJacob Faibussowitsch PetscErrorCode MatQRFactor_SeqDense(Mat A, IS col, const MatFactorInfo *minfo)
923d71ae5a4SJacob Faibussowitsch {
9244905a7bcSToby Isaac   Mat_SeqDense *mat = (Mat_SeqDense *)A->data;
9254905a7bcSToby Isaac   PetscBLASInt  n, m, info, min, max;
9264905a7bcSToby Isaac 
9274905a7bcSToby Isaac   PetscFunctionBegin;
9289566063dSJacob Faibussowitsch   PetscCall(PetscBLASIntCast(A->cmap->n, &n));
9299566063dSJacob Faibussowitsch   PetscCall(PetscBLASIntCast(A->rmap->n, &m));
9304396437dSToby Isaac   max = PetscMax(m, n);
9314396437dSToby Isaac   min = PetscMin(m, n);
9324dfa11a4SJacob Faibussowitsch   if (!mat->tau) { PetscCall(PetscMalloc1(min, &mat->tau)); }
9334dfa11a4SJacob Faibussowitsch   if (!mat->pivots) { PetscCall(PetscMalloc1(n, &mat->pivots)); }
934f4f49eeaSPierre Jolivet   if (!mat->qrrhs) PetscCall(MatCreateVecs(A, NULL, &mat->qrrhs));
9353ba16761SJacob Faibussowitsch   if (!A->rmap->n || !A->cmap->n) PetscFunctionReturn(PETSC_SUCCESS);
9364905a7bcSToby Isaac   if (!mat->fwork) {
9374905a7bcSToby Isaac     PetscScalar dummy;
9384905a7bcSToby Isaac 
9394905a7bcSToby Isaac     mat->lfwork = -1;
9409566063dSJacob Faibussowitsch     PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF));
941792fecdfSBarry Smith     PetscCallBLAS("LAPACKgeqrf", LAPACKgeqrf_(&m, &n, mat->v, &mat->lda, mat->tau, &dummy, &mat->lfwork, &info));
9429566063dSJacob Faibussowitsch     PetscCall(PetscFPTrapPop());
9434905a7bcSToby Isaac     mat->lfwork = (PetscInt)PetscRealPart(dummy);
9449566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(mat->lfwork, &mat->fwork));
9454905a7bcSToby Isaac   }
9469566063dSJacob Faibussowitsch   PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF));
947792fecdfSBarry Smith   PetscCallBLAS("LAPACKgeqrf", LAPACKgeqrf_(&m, &n, mat->v, &mat->lda, mat->tau, mat->fwork, &mat->lfwork, &info));
9489566063dSJacob Faibussowitsch   PetscCall(PetscFPTrapPop());
94905fcb23eSStefano Zampini   PetscCheck(!info, PETSC_COMM_SELF, PETSC_ERR_LIB, "Bad argument to QR factorization %d", (int)info);
9504905a7bcSToby 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
9514905a7bcSToby Isaac   mat->rank = min;
9524905a7bcSToby Isaac 
9534396437dSToby Isaac   A->ops->solve    = MatSolve_SeqDense_QR;
9544396437dSToby Isaac   A->ops->matsolve = MatMatSolve_SeqDense_QR;
9554905a7bcSToby Isaac   A->factortype    = MAT_FACTOR_QR;
9564905a7bcSToby Isaac   if (m == n) {
9574396437dSToby Isaac     A->ops->solvetranspose    = MatSolveTranspose_SeqDense_QR;
9584396437dSToby Isaac     A->ops->matsolvetranspose = MatMatSolveTranspose_SeqDense_QR;
9594905a7bcSToby Isaac   }
9604905a7bcSToby Isaac 
9619566063dSJacob Faibussowitsch   PetscCall(PetscFree(A->solvertype));
9629566063dSJacob Faibussowitsch   PetscCall(PetscStrallocpy(MATSOLVERPETSC, &A->solvertype));
9634905a7bcSToby Isaac 
9649566063dSJacob Faibussowitsch   PetscCall(PetscLogFlops(2.0 * min * min * (max - min / 3.0)));
9653ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
9664905a7bcSToby Isaac }
9674905a7bcSToby Isaac 
968d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatQRFactorNumeric_SeqDense(Mat fact, Mat A, const MatFactorInfo *info_dummy)
969d71ae5a4SJacob Faibussowitsch {
9704905a7bcSToby Isaac   MatFactorInfo info;
9714905a7bcSToby Isaac 
9724905a7bcSToby Isaac   PetscFunctionBegin;
9734905a7bcSToby Isaac   info.fill = 1.0;
9744905a7bcSToby Isaac 
9759566063dSJacob Faibussowitsch   PetscCall(MatDuplicateNoCreate_SeqDense(fact, A, MAT_COPY_VALUES));
976cac4c232SBarry Smith   PetscUseMethod(fact, "MatQRFactor_C", (Mat, IS, const MatFactorInfo *), (fact, NULL, &info));
9773ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
9784905a7bcSToby Isaac }
9794905a7bcSToby Isaac 
980d71ae5a4SJacob Faibussowitsch PetscErrorCode MatQRFactorSymbolic_SeqDense(Mat fact, Mat A, IS row, const MatFactorInfo *info)
981d71ae5a4SJacob Faibussowitsch {
9824905a7bcSToby Isaac   PetscFunctionBegin;
9834905a7bcSToby Isaac   fact->assembled    = PETSC_TRUE;
9844905a7bcSToby Isaac   fact->preallocated = PETSC_TRUE;
9859566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)fact, "MatQRFactorNumeric_C", MatQRFactorNumeric_SeqDense));
9863ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
9874905a7bcSToby Isaac }
9884905a7bcSToby Isaac 
989ca15aa20SStefano Zampini /* uses LAPACK */
990d71ae5a4SJacob Faibussowitsch PETSC_INTERN PetscErrorCode MatGetFactor_seqdense_petsc(Mat A, MatFactorType ftype, Mat *fact)
991d71ae5a4SJacob Faibussowitsch {
992db4efbfdSBarry Smith   PetscFunctionBegin;
9939566063dSJacob Faibussowitsch   PetscCall(MatCreate(PetscObjectComm((PetscObject)A), fact));
9949566063dSJacob Faibussowitsch   PetscCall(MatSetSizes(*fact, A->rmap->n, A->cmap->n, A->rmap->n, A->cmap->n));
9959566063dSJacob Faibussowitsch   PetscCall(MatSetType(*fact, MATDENSE));
99666e17bc3SBarry Smith   (*fact)->trivialsymbolic = PETSC_TRUE;
9972a350339SBarry Smith   if (ftype == MAT_FACTOR_LU || ftype == MAT_FACTOR_ILU) {
998db4efbfdSBarry Smith     (*fact)->ops->lufactorsymbolic  = MatLUFactorSymbolic_SeqDense;
9992a350339SBarry Smith     (*fact)->ops->ilufactorsymbolic = MatLUFactorSymbolic_SeqDense;
1000bf5a80bcSToby Isaac   } else if (ftype == MAT_FACTOR_CHOLESKY || ftype == MAT_FACTOR_ICC) {
1001db4efbfdSBarry Smith     (*fact)->ops->choleskyfactorsymbolic = MatCholeskyFactorSymbolic_SeqDense;
1002bf5a80bcSToby Isaac   } else if (ftype == MAT_FACTOR_QR) {
1003f4f49eeaSPierre Jolivet     PetscCall(PetscObjectComposeFunction((PetscObject)*fact, "MatQRFactorSymbolic_C", MatQRFactorSymbolic_SeqDense));
1004db4efbfdSBarry Smith   }
1005d5f3da31SBarry Smith   (*fact)->factortype = ftype;
100600c67f3bSHong Zhang 
10079566063dSJacob Faibussowitsch   PetscCall(PetscFree((*fact)->solvertype));
10089566063dSJacob Faibussowitsch   PetscCall(PetscStrallocpy(MATSOLVERPETSC, &(*fact)->solvertype));
10099566063dSJacob Faibussowitsch   PetscCall(PetscStrallocpy(MATORDERINGEXTERNAL, (char **)&(*fact)->preferredordering[MAT_FACTOR_LU]));
10109566063dSJacob Faibussowitsch   PetscCall(PetscStrallocpy(MATORDERINGEXTERNAL, (char **)&(*fact)->preferredordering[MAT_FACTOR_ILU]));
10119566063dSJacob Faibussowitsch   PetscCall(PetscStrallocpy(MATORDERINGEXTERNAL, (char **)&(*fact)->preferredordering[MAT_FACTOR_CHOLESKY]));
10129566063dSJacob Faibussowitsch   PetscCall(PetscStrallocpy(MATORDERINGEXTERNAL, (char **)&(*fact)->preferredordering[MAT_FACTOR_ICC]));
10133ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1014db4efbfdSBarry Smith }
1015db4efbfdSBarry Smith 
1016d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatSOR_SeqDense(Mat A, Vec bb, PetscReal omega, MatSORType flag, PetscReal shift, PetscInt its, PetscInt lits, Vec xx)
1017d71ae5a4SJacob Faibussowitsch {
1018c0bbcb79SLois Curfman McInnes   Mat_SeqDense      *mat = (Mat_SeqDense *)A->data;
1019d9ca1df4SBarry Smith   PetscScalar       *x, *v = mat->v, zero = 0.0, xt;
1020d9ca1df4SBarry Smith   const PetscScalar *b;
1021d0f46423SBarry Smith   PetscInt           m = A->rmap->n, i;
102223fff9afSBarry Smith   PetscBLASInt       o = 1, bm = 0;
1023289bc588SBarry Smith 
10243a40ed3dSBarry Smith   PetscFunctionBegin;
102547d993e7Ssuyashtn #if defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
102608401ef6SPierre Jolivet   PetscCheck(A->offloadmask != PETSC_OFFLOAD_GPU, PETSC_COMM_SELF, PETSC_ERR_SUP, "Not implemented");
1027ca15aa20SStefano Zampini #endif
1028422a814eSBarry Smith   if (shift == -1) shift = 0.0; /* negative shift indicates do not error on zero diagonal; this code never zeros on zero diagonal */
10299566063dSJacob Faibussowitsch   PetscCall(PetscBLASIntCast(m, &bm));
1030289bc588SBarry Smith   if (flag & SOR_ZERO_INITIAL_GUESS) {
10313bffc371SBarry Smith     /* this is a hack fix, should have another version without the second BLASdotu */
10329566063dSJacob Faibussowitsch     PetscCall(VecSet(xx, zero));
1033289bc588SBarry Smith   }
10349566063dSJacob Faibussowitsch   PetscCall(VecGetArray(xx, &x));
10359566063dSJacob Faibussowitsch   PetscCall(VecGetArrayRead(bb, &b));
1036b965ef7fSBarry Smith   its = its * lits;
103708401ef6SPierre 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);
1038289bc588SBarry Smith   while (its--) {
1039fccaa45eSBarry Smith     if (flag & SOR_FORWARD_SWEEP || flag & SOR_LOCAL_FORWARD_SWEEP) {
1040289bc588SBarry Smith       for (i = 0; i < m; i++) {
1041792fecdfSBarry Smith         PetscCallBLAS("BLASdotu", xt = b[i] - BLASdotu_(&bm, v + i, &bm, x, &o));
104255a1b374SBarry Smith         x[i] = (1. - omega) * x[i] + omega * (xt + v[i + i * m] * x[i]) / (v[i + i * m] + shift);
1043289bc588SBarry Smith       }
1044289bc588SBarry Smith     }
1045fccaa45eSBarry Smith     if (flag & SOR_BACKWARD_SWEEP || flag & SOR_LOCAL_BACKWARD_SWEEP) {
1046289bc588SBarry Smith       for (i = m - 1; i >= 0; i--) {
1047792fecdfSBarry Smith         PetscCallBLAS("BLASdotu", xt = b[i] - BLASdotu_(&bm, v + i, &bm, x, &o));
104855a1b374SBarry Smith         x[i] = (1. - omega) * x[i] + omega * (xt + v[i + i * m] * x[i]) / (v[i + i * m] + shift);
1049289bc588SBarry Smith       }
1050289bc588SBarry Smith     }
1051289bc588SBarry Smith   }
10529566063dSJacob Faibussowitsch   PetscCall(VecRestoreArrayRead(bb, &b));
10539566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(xx, &x));
10543ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1055289bc588SBarry Smith }
1056289bc588SBarry Smith 
10570be0d8bdSHansol Suh static PetscErrorCode MatMultColumnRangeKernel_SeqDense(Mat A, Vec xx, Vec yy, PetscInt c_start, PetscInt c_end, PetscBool trans, PetscBool herm)
1058d71ae5a4SJacob Faibussowitsch {
1059c0bbcb79SLois Curfman McInnes   Mat_SeqDense      *mat = (Mat_SeqDense *)A->data;
1060d9ca1df4SBarry Smith   PetscScalar       *y, _DOne = 1.0, _DZero = 0.0;
10610805154bSBarry Smith   PetscBLASInt       m, n, _One             = 1;
1062d9ca1df4SBarry Smith   const PetscScalar *v = mat->v, *x;
10633a40ed3dSBarry Smith 
10643a40ed3dSBarry Smith   PetscFunctionBegin;
10659566063dSJacob Faibussowitsch   PetscCall(PetscBLASIntCast(A->rmap->n, &m));
10660be0d8bdSHansol Suh   PetscCall(PetscBLASIntCast(c_end - c_start, &n));
10679566063dSJacob Faibussowitsch   PetscCall(VecGetArrayRead(xx, &x));
10689566063dSJacob Faibussowitsch   PetscCall(VecGetArrayWrite(yy, &y));
10690be0d8bdSHansol Suh   if (!m || !n) {
10705ac36cfcSBarry Smith     PetscBLASInt i;
1071459e8d23SBlanca Mellado Pinto     if (trans)
1072459e8d23SBlanca Mellado Pinto       for (i = 0; i < n; i++) y[i] = 0.0;
1073459e8d23SBlanca Mellado Pinto     else
10745ac36cfcSBarry Smith       for (i = 0; i < m; i++) y[i] = 0.0;
10755ac36cfcSBarry Smith   } else {
1076459e8d23SBlanca Mellado Pinto     if (trans) {
10770be0d8bdSHansol Suh       if (herm) PetscCallBLAS("BLASgemv", BLASgemv_("C", &m, &n, &_DOne, v + c_start * mat->lda, &mat->lda, x, &_One, &_DZero, y + c_start, &_One));
10780be0d8bdSHansol Suh       else PetscCallBLAS("BLASgemv", BLASgemv_("T", &m, &n, &_DOne, v + c_start * mat->lda, &mat->lda, x, &_One, &_DZero, y + c_start, &_One));
1079459e8d23SBlanca Mellado Pinto     } else {
10800be0d8bdSHansol Suh       PetscCallBLAS("BLASgemv", BLASgemv_("N", &m, &n, &_DOne, v + c_start * mat->lda, &mat->lda, x + c_start, &_One, &_DZero, y, &_One));
1081459e8d23SBlanca Mellado Pinto     }
10820be0d8bdSHansol Suh     PetscCall(PetscLogFlops(2.0 * m * n - n));
10835ac36cfcSBarry Smith   }
10849566063dSJacob Faibussowitsch   PetscCall(VecRestoreArrayRead(xx, &x));
10859566063dSJacob Faibussowitsch   PetscCall(VecRestoreArrayWrite(yy, &y));
10863ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1087289bc588SBarry Smith }
10886ee01492SSatish Balay 
10890be0d8bdSHansol Suh PetscErrorCode MatMultHermitianTransposeColumnRange_SeqDense(Mat A, Vec xx, Vec yy, PetscInt c_start, PetscInt c_end)
10900be0d8bdSHansol Suh {
10910be0d8bdSHansol Suh   PetscFunctionBegin;
10920be0d8bdSHansol Suh   PetscCall(MatMultColumnRangeKernel_SeqDense(A, xx, yy, c_start, c_end, PETSC_TRUE, PETSC_TRUE));
10930be0d8bdSHansol Suh   PetscFunctionReturn(PETSC_SUCCESS);
10940be0d8bdSHansol Suh }
10950be0d8bdSHansol Suh 
1096459e8d23SBlanca Mellado Pinto PetscErrorCode MatMult_SeqDense(Mat A, Vec xx, Vec yy)
1097459e8d23SBlanca Mellado Pinto {
1098459e8d23SBlanca Mellado Pinto   PetscFunctionBegin;
10990be0d8bdSHansol Suh   PetscCall(MatMultColumnRangeKernel_SeqDense(A, xx, yy, 0, A->cmap->n, PETSC_FALSE, PETSC_FALSE));
1100459e8d23SBlanca Mellado Pinto   PetscFunctionReturn(PETSC_SUCCESS);
1101459e8d23SBlanca Mellado Pinto }
1102459e8d23SBlanca Mellado Pinto 
1103459e8d23SBlanca Mellado Pinto PetscErrorCode MatMultTranspose_SeqDense(Mat A, Vec xx, Vec yy)
1104459e8d23SBlanca Mellado Pinto {
1105459e8d23SBlanca Mellado Pinto   PetscFunctionBegin;
11060be0d8bdSHansol Suh   PetscCall(MatMultColumnRangeKernel_SeqDense(A, xx, yy, 0, A->cmap->n, PETSC_TRUE, PETSC_FALSE));
1107459e8d23SBlanca Mellado Pinto   PetscFunctionReturn(PETSC_SUCCESS);
1108459e8d23SBlanca Mellado Pinto }
1109459e8d23SBlanca Mellado Pinto 
1110459e8d23SBlanca Mellado Pinto PetscErrorCode MatMultHermitianTranspose_SeqDense(Mat A, Vec xx, Vec yy)
1111459e8d23SBlanca Mellado Pinto {
1112459e8d23SBlanca Mellado Pinto   PetscFunctionBegin;
11130be0d8bdSHansol Suh   PetscCall(MatMultColumnRangeKernel_SeqDense(A, xx, yy, 0, A->cmap->n, PETSC_TRUE, PETSC_TRUE));
1114459e8d23SBlanca Mellado Pinto   PetscFunctionReturn(PETSC_SUCCESS);
1115459e8d23SBlanca Mellado Pinto }
1116459e8d23SBlanca Mellado Pinto 
11170be0d8bdSHansol Suh static PetscErrorCode MatMultAddColumnRangeKernel_SeqDense(Mat A, Vec xx, Vec zz, Vec yy, PetscInt c_start, PetscInt c_end, PetscBool trans, PetscBool herm)
1118d71ae5a4SJacob Faibussowitsch {
1119c0bbcb79SLois Curfman McInnes   Mat_SeqDense      *mat = (Mat_SeqDense *)A->data;
1120d9ca1df4SBarry Smith   const PetscScalar *v   = mat->v, *x;
1121d9ca1df4SBarry Smith   PetscScalar       *y, _DOne = 1.0;
11220805154bSBarry Smith   PetscBLASInt       m, n, _One = 1;
11233a40ed3dSBarry Smith 
11243a40ed3dSBarry Smith   PetscFunctionBegin;
11259566063dSJacob Faibussowitsch   PetscCall(PetscBLASIntCast(A->rmap->n, &m));
11260be0d8bdSHansol Suh   PetscCall(PetscBLASIntCast(c_end - c_start, &n));
11279566063dSJacob Faibussowitsch   PetscCall(VecCopy(zz, yy));
11280be0d8bdSHansol Suh   if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS);
11299566063dSJacob Faibussowitsch   PetscCall(VecGetArray(yy, &y));
1130459e8d23SBlanca Mellado Pinto   PetscCall(VecGetArrayRead(xx, &x));
1131459e8d23SBlanca Mellado Pinto   if (trans) {
11320be0d8bdSHansol Suh     if (herm) PetscCallBLAS("BLASgemv", BLASgemv_("C", &m, &n, &_DOne, v + c_start * mat->lda, &mat->lda, x, &_One, &_DOne, y + c_start, &_One));
11330be0d8bdSHansol Suh     else PetscCallBLAS("BLASgemv", BLASgemv_("T", &m, &n, &_DOne, v + c_start * mat->lda, &mat->lda, x, &_One, &_DOne, y + c_start, &_One));
1134459e8d23SBlanca Mellado Pinto   } else {
11350be0d8bdSHansol Suh     PetscCallBLAS("BLASgemv", BLASgemv_("N", &m, &n, &_DOne, v + c_start * mat->lda, &mat->lda, x + c_start, &_One, &_DOne, y, &_One));
1136459e8d23SBlanca Mellado Pinto   }
11379566063dSJacob Faibussowitsch   PetscCall(VecRestoreArrayRead(xx, &x));
11389566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(yy, &y));
11390be0d8bdSHansol Suh   PetscCall(PetscLogFlops(2.0 * m * n));
11400be0d8bdSHansol Suh   PetscFunctionReturn(PETSC_SUCCESS);
11410be0d8bdSHansol Suh }
11420be0d8bdSHansol Suh 
11430be0d8bdSHansol Suh PetscErrorCode MatMultAddColumnRange_SeqDense(Mat A, Vec xx, Vec zz, Vec yy, PetscInt c_start, PetscInt c_end)
11440be0d8bdSHansol Suh {
11450be0d8bdSHansol Suh   PetscFunctionBegin;
11460be0d8bdSHansol Suh   PetscCall(MatMultAddColumnRangeKernel_SeqDense(A, xx, zz, yy, c_start, c_end, PETSC_FALSE, PETSC_FALSE));
11470be0d8bdSHansol Suh   PetscFunctionReturn(PETSC_SUCCESS);
11480be0d8bdSHansol Suh }
11490be0d8bdSHansol Suh 
11500be0d8bdSHansol Suh PetscErrorCode MatMultHermitianTransposeAddColumnRange_SeqDense(Mat A, Vec xx, Vec zz, Vec yy, PetscInt c_start, PetscInt c_end)
11510be0d8bdSHansol Suh {
11520be0d8bdSHansol Suh   PetscFunctionBegin;
11530be0d8bdSHansol Suh   PetscMPIInt rank;
11540be0d8bdSHansol Suh   PetscCallMPI(MPI_Comm_rank(MPI_COMM_WORLD, &rank));
11550be0d8bdSHansol Suh   PetscCall(MatMultAddColumnRangeKernel_SeqDense(A, xx, zz, yy, c_start, c_end, PETSC_TRUE, PETSC_TRUE));
11563ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1157289bc588SBarry Smith }
11586ee01492SSatish Balay 
1159459e8d23SBlanca Mellado Pinto PetscErrorCode MatMultAdd_SeqDense(Mat A, Vec xx, Vec zz, Vec yy)
1160459e8d23SBlanca Mellado Pinto {
1161459e8d23SBlanca Mellado Pinto   PetscFunctionBegin;
11620be0d8bdSHansol Suh   PetscCall(MatMultAddColumnRangeKernel_SeqDense(A, xx, zz, yy, 0, A->cmap->n, PETSC_FALSE, PETSC_FALSE));
1163459e8d23SBlanca Mellado Pinto   PetscFunctionReturn(PETSC_SUCCESS);
1164459e8d23SBlanca Mellado Pinto }
1165459e8d23SBlanca Mellado Pinto 
1166d71ae5a4SJacob Faibussowitsch PetscErrorCode MatMultTransposeAdd_SeqDense(Mat A, Vec xx, Vec zz, Vec yy)
1167d71ae5a4SJacob Faibussowitsch {
11683a40ed3dSBarry Smith   PetscFunctionBegin;
11690be0d8bdSHansol Suh   PetscCall(MatMultAddColumnRangeKernel_SeqDense(A, xx, zz, yy, 0, A->cmap->n, PETSC_TRUE, PETSC_FALSE));
1170459e8d23SBlanca Mellado Pinto   PetscFunctionReturn(PETSC_SUCCESS);
1171459e8d23SBlanca Mellado Pinto }
1172459e8d23SBlanca Mellado Pinto 
1173459e8d23SBlanca Mellado Pinto PetscErrorCode MatMultHermitianTransposeAdd_SeqDense(Mat A, Vec xx, Vec zz, Vec yy)
1174459e8d23SBlanca Mellado Pinto {
1175459e8d23SBlanca Mellado Pinto   PetscFunctionBegin;
11760be0d8bdSHansol Suh   PetscCall(MatMultAddColumnRangeKernel_SeqDense(A, xx, zz, yy, 0, A->cmap->n, PETSC_TRUE, PETSC_TRUE));
11773ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1178289bc588SBarry Smith }
1179289bc588SBarry Smith 
1180d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatGetRow_SeqDense(Mat A, PetscInt row, PetscInt *ncols, PetscInt **cols, PetscScalar **vals)
1181d71ae5a4SJacob Faibussowitsch {
1182c0bbcb79SLois Curfman McInnes   Mat_SeqDense *mat = (Mat_SeqDense *)A->data;
118313f74950SBarry Smith   PetscInt      i;
118467e560aaSBarry Smith 
11853a40ed3dSBarry Smith   PetscFunctionBegin;
1186c3e1b152SPierre Jolivet   if (ncols) *ncols = A->cmap->n;
1187289bc588SBarry Smith   if (cols) {
11889566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(A->cmap->n, cols));
1189d0f46423SBarry Smith     for (i = 0; i < A->cmap->n; i++) (*cols)[i] = i;
1190289bc588SBarry Smith   }
1191289bc588SBarry Smith   if (vals) {
1192ca15aa20SStefano Zampini     const PetscScalar *v;
1193ca15aa20SStefano Zampini 
11949566063dSJacob Faibussowitsch     PetscCall(MatDenseGetArrayRead(A, &v));
11959566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(A->cmap->n, vals));
1196ca15aa20SStefano Zampini     v += row;
11979371c9d4SSatish Balay     for (i = 0; i < A->cmap->n; i++) {
11989371c9d4SSatish Balay       (*vals)[i] = *v;
11999371c9d4SSatish Balay       v += mat->lda;
12009371c9d4SSatish Balay     }
12019566063dSJacob Faibussowitsch     PetscCall(MatDenseRestoreArrayRead(A, &v));
1202289bc588SBarry Smith   }
12033ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1204289bc588SBarry Smith }
12056ee01492SSatish Balay 
1206d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatRestoreRow_SeqDense(Mat A, PetscInt row, PetscInt *ncols, PetscInt **cols, PetscScalar **vals)
1207d71ae5a4SJacob Faibussowitsch {
1208606d414cSSatish Balay   PetscFunctionBegin;
12099566063dSJacob Faibussowitsch   if (cols) PetscCall(PetscFree(*cols));
12109566063dSJacob Faibussowitsch   if (vals) PetscCall(PetscFree(*vals));
12113ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1212289bc588SBarry Smith }
12132ef1f0ffSBarry Smith 
1214d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatSetValues_SeqDense(Mat A, PetscInt m, const PetscInt indexm[], PetscInt n, const PetscInt indexn[], const PetscScalar v[], InsertMode addv)
1215d71ae5a4SJacob Faibussowitsch {
1216c0bbcb79SLois Curfman McInnes   Mat_SeqDense *mat = (Mat_SeqDense *)A->data;
1217ca15aa20SStefano Zampini   PetscScalar  *av;
121813f74950SBarry Smith   PetscInt      i, j, idx = 0;
121947d993e7Ssuyashtn #if defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
1220c70f7ee4SJunchao Zhang   PetscOffloadMask oldf;
1221ca15aa20SStefano Zampini #endif
1222d6dfbf8fSBarry Smith 
12233a40ed3dSBarry Smith   PetscFunctionBegin;
12249566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArray(A, &av));
1225289bc588SBarry Smith   if (!mat->roworiented) {
1226dbb450caSBarry Smith     if (addv == INSERT_VALUES) {
1227289bc588SBarry Smith       for (j = 0; j < n; j++) {
12289371c9d4SSatish Balay         if (indexn[j] < 0) {
12299371c9d4SSatish Balay           idx += m;
12309371c9d4SSatish Balay           continue;
12319371c9d4SSatish Balay         }
12326bdcaf15SBarry 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);
1233289bc588SBarry Smith         for (i = 0; i < m; i++) {
12349371c9d4SSatish Balay           if (indexm[i] < 0) {
12359371c9d4SSatish Balay             idx++;
12369371c9d4SSatish Balay             continue;
12379371c9d4SSatish Balay           }
12386bdcaf15SBarry 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);
12390be0d8bdSHansol Suh           av[indexn[j] * mat->lda + indexm[i]] = v[idx++];
1240289bc588SBarry Smith         }
1241289bc588SBarry Smith       }
12420be0d8bdSHansol Suh     } else {
1243289bc588SBarry Smith       for (j = 0; j < n; j++) {
12449371c9d4SSatish Balay         if (indexn[j] < 0) {
12459371c9d4SSatish Balay           idx += m;
12469371c9d4SSatish Balay           continue;
12479371c9d4SSatish Balay         }
12486bdcaf15SBarry 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);
1249289bc588SBarry Smith         for (i = 0; i < m; i++) {
12509371c9d4SSatish Balay           if (indexm[i] < 0) {
12519371c9d4SSatish Balay             idx++;
12529371c9d4SSatish Balay             continue;
12539371c9d4SSatish Balay           }
12546bdcaf15SBarry 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);
1255ca15aa20SStefano Zampini           av[indexn[j] * mat->lda + indexm[i]] += v[idx++];
1256289bc588SBarry Smith         }
1257289bc588SBarry Smith       }
1258289bc588SBarry Smith     }
12593a40ed3dSBarry Smith   } else {
1260dbb450caSBarry Smith     if (addv == INSERT_VALUES) {
1261e8d4e0b9SBarry Smith       for (i = 0; i < m; i++) {
12629371c9d4SSatish Balay         if (indexm[i] < 0) {
12639371c9d4SSatish Balay           idx += n;
12649371c9d4SSatish Balay           continue;
12659371c9d4SSatish Balay         }
12666bdcaf15SBarry 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);
1267e8d4e0b9SBarry Smith         for (j = 0; j < n; j++) {
12689371c9d4SSatish Balay           if (indexn[j] < 0) {
12699371c9d4SSatish Balay             idx++;
12709371c9d4SSatish Balay             continue;
12719371c9d4SSatish Balay           }
12726bdcaf15SBarry 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);
12730be0d8bdSHansol Suh           av[indexn[j] * mat->lda + indexm[i]] = v[idx++];
1274e8d4e0b9SBarry Smith         }
1275e8d4e0b9SBarry Smith       }
12760be0d8bdSHansol Suh     } else {
1277289bc588SBarry Smith       for (i = 0; i < m; i++) {
12789371c9d4SSatish Balay         if (indexm[i] < 0) {
12799371c9d4SSatish Balay           idx += n;
12809371c9d4SSatish Balay           continue;
12819371c9d4SSatish Balay         }
12826bdcaf15SBarry 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);
1283289bc588SBarry Smith         for (j = 0; j < n; j++) {
12849371c9d4SSatish Balay           if (indexn[j] < 0) {
12859371c9d4SSatish Balay             idx++;
12869371c9d4SSatish Balay             continue;
12879371c9d4SSatish Balay           }
12886bdcaf15SBarry 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);
1289ca15aa20SStefano Zampini           av[indexn[j] * mat->lda + indexm[i]] += v[idx++];
1290289bc588SBarry Smith         }
1291289bc588SBarry Smith       }
1292289bc588SBarry Smith     }
1293e8d4e0b9SBarry Smith   }
1294ca15aa20SStefano Zampini   /* hack to prevent unneeded copy to the GPU while returning the array */
129547d993e7Ssuyashtn #if defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
1296c70f7ee4SJunchao Zhang   oldf           = A->offloadmask;
1297c70f7ee4SJunchao Zhang   A->offloadmask = PETSC_OFFLOAD_GPU;
1298ca15aa20SStefano Zampini #endif
12999566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArray(A, &av));
130047d993e7Ssuyashtn #if defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
1301c70f7ee4SJunchao Zhang   A->offloadmask = (oldf == PETSC_OFFLOAD_UNALLOCATED ? PETSC_OFFLOAD_UNALLOCATED : PETSC_OFFLOAD_CPU);
1302ca15aa20SStefano Zampini #endif
13033ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1304289bc588SBarry Smith }
1305e8d4e0b9SBarry Smith 
1306d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatGetValues_SeqDense(Mat A, PetscInt m, const PetscInt indexm[], PetscInt n, const PetscInt indexn[], PetscScalar v[])
1307d71ae5a4SJacob Faibussowitsch {
1308ae80bb75SLois Curfman McInnes   Mat_SeqDense      *mat = (Mat_SeqDense *)A->data;
1309ca15aa20SStefano Zampini   const PetscScalar *vv;
131013f74950SBarry Smith   PetscInt           i, j;
1311ae80bb75SLois Curfman McInnes 
13123a40ed3dSBarry Smith   PetscFunctionBegin;
13139566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArrayRead(A, &vv));
1314ae80bb75SLois Curfman McInnes   /* row-oriented output */
1315ae80bb75SLois Curfman McInnes   for (i = 0; i < m; i++) {
13169371c9d4SSatish Balay     if (indexm[i] < 0) {
13179371c9d4SSatish Balay       v += n;
13189371c9d4SSatish Balay       continue;
13199371c9d4SSatish Balay     }
132008401ef6SPierre 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);
1321ae80bb75SLois Curfman McInnes     for (j = 0; j < n; j++) {
13229371c9d4SSatish Balay       if (indexn[j] < 0) {
13239371c9d4SSatish Balay         v++;
13249371c9d4SSatish Balay         continue;
13259371c9d4SSatish Balay       }
132608401ef6SPierre 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);
1327ca15aa20SStefano Zampini       *v++ = vv[indexn[j] * mat->lda + indexm[i]];
1328ae80bb75SLois Curfman McInnes     }
1329ae80bb75SLois Curfman McInnes   }
13309566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArrayRead(A, &vv));
13313ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1332ae80bb75SLois Curfman McInnes }
1333ae80bb75SLois Curfman McInnes 
1334d71ae5a4SJacob Faibussowitsch PetscErrorCode MatView_Dense_Binary(Mat mat, PetscViewer viewer)
1335d71ae5a4SJacob Faibussowitsch {
13368491ab44SLisandro Dalcin   PetscBool          skipHeader;
13378491ab44SLisandro Dalcin   PetscViewerFormat  format;
13388491ab44SLisandro Dalcin   PetscInt           header[4], M, N, m, lda, i, j, k;
13398491ab44SLisandro Dalcin   const PetscScalar *v;
13408491ab44SLisandro Dalcin   PetscScalar       *vwork;
1341aabbc4fbSShri Abhyankar 
1342aabbc4fbSShri Abhyankar   PetscFunctionBegin;
13439566063dSJacob Faibussowitsch   PetscCall(PetscViewerSetUp(viewer));
13449566063dSJacob Faibussowitsch   PetscCall(PetscViewerBinaryGetSkipHeader(viewer, &skipHeader));
13459566063dSJacob Faibussowitsch   PetscCall(PetscViewerGetFormat(viewer, &format));
13468491ab44SLisandro Dalcin   if (skipHeader) format = PETSC_VIEWER_NATIVE;
1347aabbc4fbSShri Abhyankar 
13489566063dSJacob Faibussowitsch   PetscCall(MatGetSize(mat, &M, &N));
13498491ab44SLisandro Dalcin 
13508491ab44SLisandro Dalcin   /* write matrix header */
13519371c9d4SSatish Balay   header[0] = MAT_FILE_CLASSID;
13529371c9d4SSatish Balay   header[1] = M;
13539371c9d4SSatish Balay   header[2] = N;
13548491ab44SLisandro Dalcin   header[3] = (format == PETSC_VIEWER_NATIVE) ? MATRIX_BINARY_FORMAT_DENSE : M * N;
13559566063dSJacob Faibussowitsch   if (!skipHeader) PetscCall(PetscViewerBinaryWrite(viewer, header, 4, PETSC_INT));
13568491ab44SLisandro Dalcin 
13579566063dSJacob Faibussowitsch   PetscCall(MatGetLocalSize(mat, &m, NULL));
13588491ab44SLisandro Dalcin   if (format != PETSC_VIEWER_NATIVE) {
13598491ab44SLisandro Dalcin     PetscInt nnz = m * N, *iwork;
13608491ab44SLisandro Dalcin     /* store row lengths for each row */
13619566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(nnz, &iwork));
13628491ab44SLisandro Dalcin     for (i = 0; i < m; i++) iwork[i] = N;
13639566063dSJacob Faibussowitsch     PetscCall(PetscViewerBinaryWriteAll(viewer, iwork, m, PETSC_DETERMINE, PETSC_DETERMINE, PETSC_INT));
13648491ab44SLisandro Dalcin     /* store column indices (zero start index) */
13658491ab44SLisandro Dalcin     for (k = 0, i = 0; i < m; i++)
13669371c9d4SSatish Balay       for (j = 0; j < N; j++, k++) iwork[k] = j;
13679566063dSJacob Faibussowitsch     PetscCall(PetscViewerBinaryWriteAll(viewer, iwork, nnz, PETSC_DETERMINE, PETSC_DETERMINE, PETSC_INT));
13689566063dSJacob Faibussowitsch     PetscCall(PetscFree(iwork));
13698491ab44SLisandro Dalcin   }
13708491ab44SLisandro Dalcin   /* store matrix values as a dense matrix in row major order */
13719566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(m * N, &vwork));
13729566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArrayRead(mat, &v));
13739566063dSJacob Faibussowitsch   PetscCall(MatDenseGetLDA(mat, &lda));
13748491ab44SLisandro Dalcin   for (k = 0, i = 0; i < m; i++)
13759371c9d4SSatish Balay     for (j = 0; j < N; j++, k++) vwork[k] = v[i + lda * j];
13769566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArrayRead(mat, &v));
13779566063dSJacob Faibussowitsch   PetscCall(PetscViewerBinaryWriteAll(viewer, vwork, m * N, PETSC_DETERMINE, PETSC_DETERMINE, PETSC_SCALAR));
13789566063dSJacob Faibussowitsch   PetscCall(PetscFree(vwork));
13793ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
13808491ab44SLisandro Dalcin }
13818491ab44SLisandro Dalcin 
1382d71ae5a4SJacob Faibussowitsch PetscErrorCode MatLoad_Dense_Binary(Mat mat, PetscViewer viewer)
1383d71ae5a4SJacob Faibussowitsch {
13848491ab44SLisandro Dalcin   PetscBool    skipHeader;
13858491ab44SLisandro Dalcin   PetscInt     header[4], M, N, m, nz, lda, i, j, k;
13868491ab44SLisandro Dalcin   PetscInt     rows, cols;
13878491ab44SLisandro Dalcin   PetscScalar *v, *vwork;
13888491ab44SLisandro Dalcin 
13898491ab44SLisandro Dalcin   PetscFunctionBegin;
13909566063dSJacob Faibussowitsch   PetscCall(PetscViewerSetUp(viewer));
13919566063dSJacob Faibussowitsch   PetscCall(PetscViewerBinaryGetSkipHeader(viewer, &skipHeader));
13928491ab44SLisandro Dalcin 
13938491ab44SLisandro Dalcin   if (!skipHeader) {
13949566063dSJacob Faibussowitsch     PetscCall(PetscViewerBinaryRead(viewer, header, 4, NULL, PETSC_INT));
139508401ef6SPierre Jolivet     PetscCheck(header[0] == MAT_FILE_CLASSID, PetscObjectComm((PetscObject)viewer), PETSC_ERR_FILE_UNEXPECTED, "Not a matrix object in file");
13969371c9d4SSatish Balay     M = header[1];
13979371c9d4SSatish Balay     N = header[2];
139808401ef6SPierre Jolivet     PetscCheck(M >= 0, PetscObjectComm((PetscObject)viewer), PETSC_ERR_FILE_UNEXPECTED, "Matrix row size (%" PetscInt_FMT ") in file is negative", M);
139908401ef6SPierre Jolivet     PetscCheck(N >= 0, PetscObjectComm((PetscObject)viewer), PETSC_ERR_FILE_UNEXPECTED, "Matrix column size (%" PetscInt_FMT ") in file is negative", N);
14008491ab44SLisandro Dalcin     nz = header[3];
1401aed4548fSBarry Smith     PetscCheck(nz == MATRIX_BINARY_FORMAT_DENSE || nz >= 0, PetscObjectComm((PetscObject)viewer), PETSC_ERR_FILE_UNEXPECTED, "Unknown matrix format %" PetscInt_FMT " in file", nz);
1402aabbc4fbSShri Abhyankar   } else {
14039566063dSJacob Faibussowitsch     PetscCall(MatGetSize(mat, &M, &N));
1404aed4548fSBarry 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");
14058491ab44SLisandro Dalcin     nz = MATRIX_BINARY_FORMAT_DENSE;
1406e6324fbbSBarry Smith   }
1407aabbc4fbSShri Abhyankar 
14088491ab44SLisandro Dalcin   /* setup global sizes if not set */
14098491ab44SLisandro Dalcin   if (mat->rmap->N < 0) mat->rmap->N = M;
14108491ab44SLisandro Dalcin   if (mat->cmap->N < 0) mat->cmap->N = N;
14119566063dSJacob Faibussowitsch   PetscCall(MatSetUp(mat));
14128491ab44SLisandro Dalcin   /* check if global sizes are correct */
14139566063dSJacob Faibussowitsch   PetscCall(MatGetSize(mat, &rows, &cols));
1414aed4548fSBarry 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);
1415aabbc4fbSShri Abhyankar 
14169566063dSJacob Faibussowitsch   PetscCall(MatGetSize(mat, NULL, &N));
14179566063dSJacob Faibussowitsch   PetscCall(MatGetLocalSize(mat, &m, NULL));
14189566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArray(mat, &v));
14199566063dSJacob Faibussowitsch   PetscCall(MatDenseGetLDA(mat, &lda));
14208491ab44SLisandro Dalcin   if (nz == MATRIX_BINARY_FORMAT_DENSE) { /* matrix in file is dense format */
14218491ab44SLisandro Dalcin     PetscInt nnz = m * N;
14228491ab44SLisandro Dalcin     /* read in matrix values */
14239566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(nnz, &vwork));
14249566063dSJacob Faibussowitsch     PetscCall(PetscViewerBinaryReadAll(viewer, vwork, nnz, PETSC_DETERMINE, PETSC_DETERMINE, PETSC_SCALAR));
14258491ab44SLisandro Dalcin     /* store values in column major order */
14268491ab44SLisandro Dalcin     for (j = 0; j < N; j++)
14279371c9d4SSatish Balay       for (i = 0; i < m; i++) v[i + lda * j] = vwork[i * N + j];
14289566063dSJacob Faibussowitsch     PetscCall(PetscFree(vwork));
14298491ab44SLisandro Dalcin   } else { /* matrix in file is sparse format */
14308491ab44SLisandro Dalcin     PetscInt nnz = 0, *rlens, *icols;
14318491ab44SLisandro Dalcin     /* read in row lengths */
14329566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(m, &rlens));
14339566063dSJacob Faibussowitsch     PetscCall(PetscViewerBinaryReadAll(viewer, rlens, m, PETSC_DETERMINE, PETSC_DETERMINE, PETSC_INT));
14348491ab44SLisandro Dalcin     for (i = 0; i < m; i++) nnz += rlens[i];
14358491ab44SLisandro Dalcin     /* read in column indices and values */
14369566063dSJacob Faibussowitsch     PetscCall(PetscMalloc2(nnz, &icols, nnz, &vwork));
14379566063dSJacob Faibussowitsch     PetscCall(PetscViewerBinaryReadAll(viewer, icols, nnz, PETSC_DETERMINE, PETSC_DETERMINE, PETSC_INT));
14389566063dSJacob Faibussowitsch     PetscCall(PetscViewerBinaryReadAll(viewer, vwork, nnz, PETSC_DETERMINE, PETSC_DETERMINE, PETSC_SCALAR));
14398491ab44SLisandro Dalcin     /* store values in column major order */
14408491ab44SLisandro Dalcin     for (k = 0, i = 0; i < m; i++)
14419371c9d4SSatish Balay       for (j = 0; j < rlens[i]; j++, k++) v[i + lda * icols[k]] = vwork[k];
14429566063dSJacob Faibussowitsch     PetscCall(PetscFree(rlens));
14439566063dSJacob Faibussowitsch     PetscCall(PetscFree2(icols, vwork));
1444aabbc4fbSShri Abhyankar   }
14459566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArray(mat, &v));
14469566063dSJacob Faibussowitsch   PetscCall(MatAssemblyBegin(mat, MAT_FINAL_ASSEMBLY));
14479566063dSJacob Faibussowitsch   PetscCall(MatAssemblyEnd(mat, MAT_FINAL_ASSEMBLY));
14483ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1449aabbc4fbSShri Abhyankar }
1450aabbc4fbSShri Abhyankar 
145166976f2fSJacob Faibussowitsch static PetscErrorCode MatLoad_SeqDense(Mat newMat, PetscViewer viewer)
1452d71ae5a4SJacob Faibussowitsch {
1453eb91f321SVaclav Hapla   PetscBool isbinary, ishdf5;
1454eb91f321SVaclav Hapla 
1455eb91f321SVaclav Hapla   PetscFunctionBegin;
1456eb91f321SVaclav Hapla   PetscValidHeaderSpecific(newMat, MAT_CLASSID, 1);
1457eb91f321SVaclav Hapla   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
1458eb91f321SVaclav Hapla   /* force binary viewer to load .info file if it has not yet done so */
14599566063dSJacob Faibussowitsch   PetscCall(PetscViewerSetUp(viewer));
14609566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERBINARY, &isbinary));
14619566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5));
1462eb91f321SVaclav Hapla   if (isbinary) {
14639566063dSJacob Faibussowitsch     PetscCall(MatLoad_Dense_Binary(newMat, viewer));
1464eb91f321SVaclav Hapla   } else if (ishdf5) {
1465eb91f321SVaclav Hapla #if defined(PETSC_HAVE_HDF5)
14669566063dSJacob Faibussowitsch     PetscCall(MatLoad_Dense_HDF5(newMat, viewer));
1467eb91f321SVaclav Hapla #else
1468eb91f321SVaclav Hapla     SETERRQ(PetscObjectComm((PetscObject)newMat), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5");
1469eb91f321SVaclav Hapla #endif
1470eb91f321SVaclav Hapla   } else {
147198921bdaSJacob 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);
1472eb91f321SVaclav Hapla   }
14733ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1474eb91f321SVaclav Hapla }
1475eb91f321SVaclav Hapla 
1476d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatView_SeqDense_ASCII(Mat A, PetscViewer viewer)
1477d71ae5a4SJacob Faibussowitsch {
1478932b0c3eSLois Curfman McInnes   Mat_SeqDense     *a = (Mat_SeqDense *)A->data;
147913f74950SBarry Smith   PetscInt          i, j;
14802dcb1b2aSMatthew Knepley   const char       *name;
1481ca15aa20SStefano Zampini   PetscScalar      *v, *av;
1482f3ef73ceSBarry Smith   PetscViewerFormat format;
14835f481a85SSatish Balay #if defined(PETSC_USE_COMPLEX)
1484ace3abfcSBarry Smith   PetscBool allreal = PETSC_TRUE;
14855f481a85SSatish Balay #endif
1486932b0c3eSLois Curfman McInnes 
14873a40ed3dSBarry Smith   PetscFunctionBegin;
14889566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArrayRead(A, (const PetscScalar **)&av));
14899566063dSJacob Faibussowitsch   PetscCall(PetscViewerGetFormat(viewer, &format));
1490456192e2SBarry Smith   if (format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL) {
14913ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS); /* do nothing for now */
1492fb9695e5SSatish Balay   } else if (format == PETSC_VIEWER_ASCII_COMMON) {
14939566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIUseTabs(viewer, PETSC_FALSE));
1494d0f46423SBarry Smith     for (i = 0; i < A->rmap->n; i++) {
1495ca15aa20SStefano Zampini       v = av + i;
14969566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "row %" PetscInt_FMT ":", i));
1497d0f46423SBarry Smith       for (j = 0; j < A->cmap->n; j++) {
1498aa482453SBarry Smith #if defined(PETSC_USE_COMPLEX)
1499329f5518SBarry Smith         if (PetscRealPart(*v) != 0.0 && PetscImaginaryPart(*v) != 0.0) {
15009566063dSJacob Faibussowitsch           PetscCall(PetscViewerASCIIPrintf(viewer, " (%" PetscInt_FMT ", %g + %g i) ", j, (double)PetscRealPart(*v), (double)PetscImaginaryPart(*v)));
1501329f5518SBarry Smith         } else if (PetscRealPart(*v)) {
15029566063dSJacob Faibussowitsch           PetscCall(PetscViewerASCIIPrintf(viewer, " (%" PetscInt_FMT ", %g) ", j, (double)PetscRealPart(*v)));
15036831982aSBarry Smith         }
150480cd9d93SLois Curfman McInnes #else
150548a46eb9SPierre Jolivet         if (*v) PetscCall(PetscViewerASCIIPrintf(viewer, " (%" PetscInt_FMT ", %g) ", j, (double)*v));
150680cd9d93SLois Curfman McInnes #endif
15071b807ce4Svictorle         v += a->lda;
150880cd9d93SLois Curfman McInnes       }
15099566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "\n"));
151080cd9d93SLois Curfman McInnes     }
15119566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIUseTabs(viewer, PETSC_TRUE));
15123a40ed3dSBarry Smith   } else {
15139566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIUseTabs(viewer, PETSC_FALSE));
1514aa482453SBarry Smith #if defined(PETSC_USE_COMPLEX)
151547989497SBarry Smith     /* determine if matrix has all real values */
1516bcd8d3a4SJose E. Roman     for (j = 0; j < A->cmap->n; j++) {
1517bcd8d3a4SJose E. Roman       v = av + j * a->lda;
1518bcd8d3a4SJose E. Roman       for (i = 0; i < A->rmap->n; i++) {
15199371c9d4SSatish Balay         if (PetscImaginaryPart(v[i])) {
15209371c9d4SSatish Balay           allreal = PETSC_FALSE;
15219371c9d4SSatish Balay           break;
15229371c9d4SSatish Balay         }
152347989497SBarry Smith       }
1524bcd8d3a4SJose E. Roman     }
152547989497SBarry Smith #endif
1526fb9695e5SSatish Balay     if (format == PETSC_VIEWER_ASCII_MATLAB) {
15279566063dSJacob Faibussowitsch       PetscCall(PetscObjectGetName((PetscObject)A, &name));
15289566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "%% Size = %" PetscInt_FMT " %" PetscInt_FMT " \n", A->rmap->n, A->cmap->n));
15299566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "%s = zeros(%" PetscInt_FMT ",%" PetscInt_FMT ");\n", name, A->rmap->n, A->cmap->n));
15309566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "%s = [\n", name));
1531ffac6cdbSBarry Smith     }
1532ffac6cdbSBarry Smith 
1533d0f46423SBarry Smith     for (i = 0; i < A->rmap->n; i++) {
1534ca15aa20SStefano Zampini       v = av + i;
1535d0f46423SBarry Smith       for (j = 0; j < A->cmap->n; j++) {
1536aa482453SBarry Smith #if defined(PETSC_USE_COMPLEX)
153747989497SBarry Smith         if (allreal) {
15389566063dSJacob Faibussowitsch           PetscCall(PetscViewerASCIIPrintf(viewer, "%18.16e ", (double)PetscRealPart(*v)));
153947989497SBarry Smith         } else {
15409566063dSJacob Faibussowitsch           PetscCall(PetscViewerASCIIPrintf(viewer, "%18.16e + %18.16ei ", (double)PetscRealPart(*v), (double)PetscImaginaryPart(*v)));
154147989497SBarry Smith         }
1542289bc588SBarry Smith #else
15439566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, "%18.16e ", (double)*v));
1544289bc588SBarry Smith #endif
15451b807ce4Svictorle         v += a->lda;
1546289bc588SBarry Smith       }
15479566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "\n"));
1548289bc588SBarry Smith     }
154948a46eb9SPierre Jolivet     if (format == PETSC_VIEWER_ASCII_MATLAB) PetscCall(PetscViewerASCIIPrintf(viewer, "];\n"));
15509566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIUseTabs(viewer, PETSC_TRUE));
1551da3a660dSBarry Smith   }
15529566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArrayRead(A, (const PetscScalar **)&av));
15539566063dSJacob Faibussowitsch   PetscCall(PetscViewerFlush(viewer));
15543ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1555289bc588SBarry Smith }
1556289bc588SBarry Smith 
15579804daf3SBarry Smith #include <petscdraw.h>
1558d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatView_SeqDense_Draw_Zoom(PetscDraw draw, void *Aa)
1559d71ae5a4SJacob Faibussowitsch {
1560f1af5d2fSBarry Smith   Mat                A = (Mat)Aa;
1561383922c3SLisandro Dalcin   PetscInt           m = A->rmap->n, n = A->cmap->n, i, j;
1562383922c3SLisandro Dalcin   int                color = PETSC_DRAW_WHITE;
1563ca15aa20SStefano Zampini   const PetscScalar *v;
1564b0a32e0cSBarry Smith   PetscViewer        viewer;
1565b05fc000SLisandro Dalcin   PetscReal          xl, yl, xr, yr, x_l, x_r, y_l, y_r;
1566f3ef73ceSBarry Smith   PetscViewerFormat  format;
1567f1af5d2fSBarry Smith 
1568f1af5d2fSBarry Smith   PetscFunctionBegin;
15699566063dSJacob Faibussowitsch   PetscCall(PetscObjectQuery((PetscObject)A, "Zoomviewer", (PetscObject *)&viewer));
15709566063dSJacob Faibussowitsch   PetscCall(PetscViewerGetFormat(viewer, &format));
15719566063dSJacob Faibussowitsch   PetscCall(PetscDrawGetCoordinates(draw, &xl, &yl, &xr, &yr));
1572f1af5d2fSBarry Smith 
1573f1af5d2fSBarry Smith   /* Loop over matrix elements drawing boxes */
15749566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArrayRead(A, &v));
1575fb9695e5SSatish Balay   if (format != PETSC_VIEWER_DRAW_CONTOUR) {
1576d0609cedSBarry Smith     PetscDrawCollectiveBegin(draw);
1577f1af5d2fSBarry Smith     /* Blue for negative and Red for positive */
1578f1af5d2fSBarry Smith     for (j = 0; j < n; j++) {
15799371c9d4SSatish Balay       x_l = j;
15809371c9d4SSatish Balay       x_r = x_l + 1.0;
1581f1af5d2fSBarry Smith       for (i = 0; i < m; i++) {
1582f1af5d2fSBarry Smith         y_l = m - i - 1.0;
1583f1af5d2fSBarry Smith         y_r = y_l + 1.0;
1584ca15aa20SStefano Zampini         if (PetscRealPart(v[j * m + i]) > 0.) color = PETSC_DRAW_RED;
1585ca15aa20SStefano Zampini         else if (PetscRealPart(v[j * m + i]) < 0.) color = PETSC_DRAW_BLUE;
1586ca15aa20SStefano Zampini         else continue;
15879566063dSJacob Faibussowitsch         PetscCall(PetscDrawRectangle(draw, x_l, y_l, x_r, y_r, color, color, color, color));
1588f1af5d2fSBarry Smith       }
1589f1af5d2fSBarry Smith     }
1590d0609cedSBarry Smith     PetscDrawCollectiveEnd(draw);
1591f1af5d2fSBarry Smith   } else {
1592f1af5d2fSBarry Smith     /* use contour shading to indicate magnitude of values */
1593f1af5d2fSBarry Smith     /* first determine max of all nonzero values */
1594b05fc000SLisandro Dalcin     PetscReal minv = 0.0, maxv = 0.0;
1595b05fc000SLisandro Dalcin     PetscDraw popup;
1596b05fc000SLisandro Dalcin 
1597f1af5d2fSBarry Smith     for (i = 0; i < m * n; i++) {
1598f1af5d2fSBarry Smith       if (PetscAbsScalar(v[i]) > maxv) maxv = PetscAbsScalar(v[i]);
1599f1af5d2fSBarry Smith     }
1600383922c3SLisandro Dalcin     if (minv >= maxv) maxv = minv + PETSC_SMALL;
16019566063dSJacob Faibussowitsch     PetscCall(PetscDrawGetPopup(draw, &popup));
16029566063dSJacob Faibussowitsch     PetscCall(PetscDrawScalePopup(popup, minv, maxv));
1603383922c3SLisandro Dalcin 
1604d0609cedSBarry Smith     PetscDrawCollectiveBegin(draw);
1605f1af5d2fSBarry Smith     for (j = 0; j < n; j++) {
1606f1af5d2fSBarry Smith       x_l = j;
1607f1af5d2fSBarry Smith       x_r = x_l + 1.0;
1608f1af5d2fSBarry Smith       for (i = 0; i < m; i++) {
1609f1af5d2fSBarry Smith         y_l   = m - i - 1.0;
1610f1af5d2fSBarry Smith         y_r   = y_l + 1.0;
1611b05fc000SLisandro Dalcin         color = PetscDrawRealToColor(PetscAbsScalar(v[j * m + i]), minv, maxv);
16129566063dSJacob Faibussowitsch         PetscCall(PetscDrawRectangle(draw, x_l, y_l, x_r, y_r, color, color, color, color));
1613f1af5d2fSBarry Smith       }
1614f1af5d2fSBarry Smith     }
1615d0609cedSBarry Smith     PetscDrawCollectiveEnd(draw);
1616f1af5d2fSBarry Smith   }
16179566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArrayRead(A, &v));
16183ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1619f1af5d2fSBarry Smith }
1620f1af5d2fSBarry Smith 
1621d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatView_SeqDense_Draw(Mat A, PetscViewer viewer)
1622d71ae5a4SJacob Faibussowitsch {
1623b0a32e0cSBarry Smith   PetscDraw draw;
1624ace3abfcSBarry Smith   PetscBool isnull;
1625329f5518SBarry Smith   PetscReal xr, yr, xl, yl, h, w;
1626f1af5d2fSBarry Smith 
1627f1af5d2fSBarry Smith   PetscFunctionBegin;
16289566063dSJacob Faibussowitsch   PetscCall(PetscViewerDrawGetDraw(viewer, 0, &draw));
16299566063dSJacob Faibussowitsch   PetscCall(PetscDrawIsNull(draw, &isnull));
16303ba16761SJacob Faibussowitsch   if (isnull) PetscFunctionReturn(PETSC_SUCCESS);
1631f1af5d2fSBarry Smith 
16329371c9d4SSatish Balay   xr = A->cmap->n;
16339371c9d4SSatish Balay   yr = A->rmap->n;
16349371c9d4SSatish Balay   h  = yr / 10.0;
16359371c9d4SSatish Balay   w  = xr / 10.0;
16369371c9d4SSatish Balay   xr += w;
16379371c9d4SSatish Balay   yr += h;
16389371c9d4SSatish Balay   xl = -w;
16399371c9d4SSatish Balay   yl = -h;
16409566063dSJacob Faibussowitsch   PetscCall(PetscDrawSetCoordinates(draw, xl, yl, xr, yr));
16419566063dSJacob Faibussowitsch   PetscCall(PetscObjectCompose((PetscObject)A, "Zoomviewer", (PetscObject)viewer));
16429566063dSJacob Faibussowitsch   PetscCall(PetscDrawZoom(draw, MatView_SeqDense_Draw_Zoom, A));
16439566063dSJacob Faibussowitsch   PetscCall(PetscObjectCompose((PetscObject)A, "Zoomviewer", NULL));
16449566063dSJacob Faibussowitsch   PetscCall(PetscDrawSave(draw));
16453ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1646f1af5d2fSBarry Smith }
1647f1af5d2fSBarry Smith 
1648d71ae5a4SJacob Faibussowitsch PetscErrorCode MatView_SeqDense(Mat A, PetscViewer viewer)
1649d71ae5a4SJacob Faibussowitsch {
1650ace3abfcSBarry Smith   PetscBool iascii, isbinary, isdraw;
1651932b0c3eSLois Curfman McInnes 
16523a40ed3dSBarry Smith   PetscFunctionBegin;
16539566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
16549566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERBINARY, &isbinary));
16559566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERDRAW, &isdraw));
16561baa6e33SBarry Smith   if (iascii) PetscCall(MatView_SeqDense_ASCII(A, viewer));
16571baa6e33SBarry Smith   else if (isbinary) PetscCall(MatView_Dense_Binary(A, viewer));
16581baa6e33SBarry Smith   else if (isdraw) PetscCall(MatView_SeqDense_Draw(A, viewer));
16593ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1660932b0c3eSLois Curfman McInnes }
1661289bc588SBarry Smith 
1662d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatDensePlaceArray_SeqDense(Mat A, const PetscScalar *array)
1663d71ae5a4SJacob Faibussowitsch {
1664d3042a70SBarry Smith   Mat_SeqDense *a = (Mat_SeqDense *)A->data;
1665d3042a70SBarry Smith 
1666d3042a70SBarry Smith   PetscFunctionBegin;
166728b400f6SJacob Faibussowitsch   PetscCheck(!a->vecinuse, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Need to call MatDenseRestoreColumnVec() first");
166828b400f6SJacob Faibussowitsch   PetscCheck(!a->matinuse, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Need to call MatDenseRestoreSubMatrix() first");
166928b400f6SJacob Faibussowitsch   PetscCheck(!a->unplacedarray, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Need to call MatDenseRestoreArray() first");
1670d3042a70SBarry Smith   a->unplacedarray       = a->v;
1671d3042a70SBarry Smith   a->unplaced_user_alloc = a->user_alloc;
1672d3042a70SBarry Smith   a->v                   = (PetscScalar *)array;
1673637a0070SStefano Zampini   a->user_alloc          = PETSC_TRUE;
167447d993e7Ssuyashtn #if defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
1675c70f7ee4SJunchao Zhang   A->offloadmask = PETSC_OFFLOAD_CPU;
1676ca15aa20SStefano Zampini #endif
16773ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1678d3042a70SBarry Smith }
1679d3042a70SBarry Smith 
1680d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatDenseResetArray_SeqDense(Mat A)
1681d71ae5a4SJacob Faibussowitsch {
1682d3042a70SBarry Smith   Mat_SeqDense *a = (Mat_SeqDense *)A->data;
1683d3042a70SBarry Smith 
1684d3042a70SBarry Smith   PetscFunctionBegin;
168528b400f6SJacob Faibussowitsch   PetscCheck(!a->vecinuse, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Need to call MatDenseRestoreColumnVec() first");
168628b400f6SJacob Faibussowitsch   PetscCheck(!a->matinuse, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Need to call MatDenseRestoreSubMatrix() first");
1687d3042a70SBarry Smith   a->v             = a->unplacedarray;
1688d3042a70SBarry Smith   a->user_alloc    = a->unplaced_user_alloc;
1689d3042a70SBarry Smith   a->unplacedarray = NULL;
169047d993e7Ssuyashtn #if defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
1691c70f7ee4SJunchao Zhang   A->offloadmask = PETSC_OFFLOAD_CPU;
1692ca15aa20SStefano Zampini #endif
16933ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1694d3042a70SBarry Smith }
1695d3042a70SBarry Smith 
1696d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatDenseReplaceArray_SeqDense(Mat A, const PetscScalar *array)
1697d71ae5a4SJacob Faibussowitsch {
1698d5ea218eSStefano Zampini   Mat_SeqDense *a = (Mat_SeqDense *)A->data;
1699d5ea218eSStefano Zampini 
1700d5ea218eSStefano Zampini   PetscFunctionBegin;
170128b400f6SJacob Faibussowitsch   PetscCheck(!a->vecinuse, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Need to call MatDenseRestoreColumnVec() first");
170228b400f6SJacob Faibussowitsch   PetscCheck(!a->matinuse, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Need to call MatDenseRestoreSubMatrix() first");
17039566063dSJacob Faibussowitsch   if (!a->user_alloc) PetscCall(PetscFree(a->v));
1704d5ea218eSStefano Zampini   a->v          = (PetscScalar *)array;
1705d5ea218eSStefano Zampini   a->user_alloc = PETSC_FALSE;
170647d993e7Ssuyashtn #if defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
1707d5ea218eSStefano Zampini   A->offloadmask = PETSC_OFFLOAD_CPU;
1708d5ea218eSStefano Zampini #endif
17093ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1710d5ea218eSStefano Zampini }
1711d5ea218eSStefano Zampini 
1712d71ae5a4SJacob Faibussowitsch PetscErrorCode MatDestroy_SeqDense(Mat mat)
1713d71ae5a4SJacob Faibussowitsch {
1714ec8511deSBarry Smith   Mat_SeqDense *l = (Mat_SeqDense *)mat->data;
171590f02eecSBarry Smith 
17163a40ed3dSBarry Smith   PetscFunctionBegin;
17173ba16761SJacob Faibussowitsch   PetscCall(PetscLogObjectState((PetscObject)mat, "Rows %" PetscInt_FMT " Cols %" PetscInt_FMT, mat->rmap->n, mat->cmap->n));
1718f4f49eeaSPierre Jolivet   PetscCall(VecDestroy(&l->qrrhs));
17199566063dSJacob Faibussowitsch   PetscCall(PetscFree(l->tau));
17209566063dSJacob Faibussowitsch   PetscCall(PetscFree(l->pivots));
17219566063dSJacob Faibussowitsch   PetscCall(PetscFree(l->fwork));
17229566063dSJacob Faibussowitsch   if (!l->user_alloc) PetscCall(PetscFree(l->v));
17239566063dSJacob Faibussowitsch   if (!l->unplaced_user_alloc) PetscCall(PetscFree(l->unplacedarray));
172428b400f6SJacob Faibussowitsch   PetscCheck(!l->vecinuse, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Need to call MatDenseRestoreColumnVec() first");
172528b400f6SJacob Faibussowitsch   PetscCheck(!l->matinuse, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Need to call MatDenseRestoreSubMatrix() first");
17269566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&l->cvec));
17279566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&l->cmat));
17289566063dSJacob Faibussowitsch   PetscCall(PetscFree(mat->data));
1729dbd8c25aSHong Zhang 
17309566063dSJacob Faibussowitsch   PetscCall(PetscObjectChangeTypeName((PetscObject)mat, NULL));
17319566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatQRFactor_C", NULL));
17322e956fe4SStefano Zampini   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatQRFactorSymbolic_C", NULL));
17332e956fe4SStefano Zampini   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatQRFactorNumeric_C", NULL));
17349566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatDenseGetLDA_C", NULL));
17359566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatDenseSetLDA_C", NULL));
17369566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatDenseGetArray_C", NULL));
17379566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatDenseRestoreArray_C", NULL));
17389566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatDensePlaceArray_C", NULL));
17399566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatDenseResetArray_C", NULL));
17409566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatDenseReplaceArray_C", NULL));
17419566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatDenseGetArrayRead_C", NULL));
17429566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatDenseRestoreArrayRead_C", NULL));
17439566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatDenseGetArrayWrite_C", NULL));
17449566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatDenseRestoreArrayWrite_C", NULL));
17459566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatConvert_seqdense_seqaij_C", NULL));
17468baccfbdSHong Zhang #if defined(PETSC_HAVE_ELEMENTAL)
17479566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatConvert_seqdense_elemental_C", NULL));
17488baccfbdSHong Zhang #endif
1749d24d4204SJose E. Roman #if defined(PETSC_HAVE_SCALAPACK)
17509566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatConvert_seqdense_scalapack_C", NULL));
1751d24d4204SJose E. Roman #endif
17522bf066beSStefano Zampini #if defined(PETSC_HAVE_CUDA)
17539566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatConvert_seqdense_seqdensecuda_C", NULL));
17549566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatProductSetFromOptions_seqdensecuda_seqdensecuda_C", NULL));
17559566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatProductSetFromOptions_seqdensecuda_seqdense_C", NULL));
17562e956fe4SStefano Zampini   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatProductSetFromOptions_seqdense_seqdensecuda_C", NULL));
17572bf066beSStefano Zampini #endif
175847d993e7Ssuyashtn #if defined(PETSC_HAVE_HIP)
175947d993e7Ssuyashtn   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatConvert_seqdense_seqdensehip_C", NULL));
176047d993e7Ssuyashtn   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatProductSetFromOptions_seqdensehip_seqdensehip_C", NULL));
176147d993e7Ssuyashtn   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatProductSetFromOptions_seqdensehip_seqdense_C", NULL));
176247d993e7Ssuyashtn   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatProductSetFromOptions_seqdense_seqdensehip_C", NULL));
176347d993e7Ssuyashtn #endif
17649566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatSeqDenseSetPreallocation_C", NULL));
17659566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatProductSetFromOptions_seqaij_seqdense_C", NULL));
17669566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatProductSetFromOptions_seqdense_seqdense_C", NULL));
17679566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatProductSetFromOptions_seqbaij_seqdense_C", NULL));
17689566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatProductSetFromOptions_seqsbaij_seqdense_C", NULL));
176952c5f739Sprj- 
17709566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatDenseGetColumn_C", NULL));
17719566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatDenseRestoreColumn_C", NULL));
17729566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatDenseGetColumnVec_C", NULL));
17739566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatDenseRestoreColumnVec_C", NULL));
17749566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatDenseGetColumnVecRead_C", NULL));
17759566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatDenseRestoreColumnVecRead_C", NULL));
17769566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatDenseGetColumnVecWrite_C", NULL));
17779566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatDenseRestoreColumnVecWrite_C", NULL));
17789566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatDenseGetSubMatrix_C", NULL));
17799566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatDenseRestoreSubMatrix_C", NULL));
17800be0d8bdSHansol Suh   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatMultAddColumnRange_C", NULL));
17810be0d8bdSHansol Suh   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatMultHermitianTransposeColumnRange_C", NULL));
17820be0d8bdSHansol Suh   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatMultHermitianTransposeAddColumnRange_C", NULL));
17833ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1784289bc588SBarry Smith }
1785289bc588SBarry Smith 
1786d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatTranspose_SeqDense(Mat A, MatReuse reuse, Mat *matout)
1787d71ae5a4SJacob Faibussowitsch {
1788c0bbcb79SLois Curfman McInnes   Mat_SeqDense *mat = (Mat_SeqDense *)A->data;
17896536e3caSStefano Zampini   PetscInt      k, j, m = A->rmap->n, M = mat->lda, n = A->cmap->n;
179087828ca2SBarry Smith   PetscScalar  *v, tmp;
179148b35521SBarry Smith 
17923a40ed3dSBarry Smith   PetscFunctionBegin;
17937fb60732SBarry Smith   if (reuse == MAT_REUSE_MATRIX) PetscCall(MatTransposeCheckNonzeroState_Private(A, *matout));
17946536e3caSStefano Zampini   if (reuse == MAT_INPLACE_MATRIX) {
17956536e3caSStefano Zampini     if (m == n) { /* in place transpose */
17969566063dSJacob Faibussowitsch       PetscCall(MatDenseGetArray(A, &v));
1797d3e5ee88SLois Curfman McInnes       for (j = 0; j < m; j++) {
1798289bc588SBarry Smith         for (k = 0; k < j; k++) {
17991b807ce4Svictorle           tmp          = v[j + k * M];
18001b807ce4Svictorle           v[j + k * M] = v[k + j * M];
18011b807ce4Svictorle           v[k + j * M] = tmp;
1802289bc588SBarry Smith         }
1803289bc588SBarry Smith       }
18049566063dSJacob Faibussowitsch       PetscCall(MatDenseRestoreArray(A, &v));
18056536e3caSStefano Zampini     } else { /* reuse memory, temporary allocates new memory */
18066536e3caSStefano Zampini       PetscScalar *v2;
18076536e3caSStefano Zampini       PetscLayout  tmplayout;
18086536e3caSStefano Zampini 
18099566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1((size_t)m * n, &v2));
18109566063dSJacob Faibussowitsch       PetscCall(MatDenseGetArray(A, &v));
18116536e3caSStefano Zampini       for (j = 0; j < n; j++) {
18126536e3caSStefano Zampini         for (k = 0; k < m; k++) v2[j + (size_t)k * n] = v[k + (size_t)j * M];
18136536e3caSStefano Zampini       }
18149566063dSJacob Faibussowitsch       PetscCall(PetscArraycpy(v, v2, (size_t)m * n));
18159566063dSJacob Faibussowitsch       PetscCall(PetscFree(v2));
18169566063dSJacob Faibussowitsch       PetscCall(MatDenseRestoreArray(A, &v));
18176536e3caSStefano Zampini       /* cleanup size dependent quantities */
18189566063dSJacob Faibussowitsch       PetscCall(VecDestroy(&mat->cvec));
18199566063dSJacob Faibussowitsch       PetscCall(MatDestroy(&mat->cmat));
18209566063dSJacob Faibussowitsch       PetscCall(PetscFree(mat->pivots));
18219566063dSJacob Faibussowitsch       PetscCall(PetscFree(mat->fwork));
18226536e3caSStefano Zampini       /* swap row/col layouts */
18236536e3caSStefano Zampini       mat->lda  = n;
18246536e3caSStefano Zampini       tmplayout = A->rmap;
18256536e3caSStefano Zampini       A->rmap   = A->cmap;
18266536e3caSStefano Zampini       A->cmap   = tmplayout;
18276536e3caSStefano Zampini     }
18283a40ed3dSBarry Smith   } else { /* out-of-place transpose */
1829d3e5ee88SLois Curfman McInnes     Mat           tmat;
1830ec8511deSBarry Smith     Mat_SeqDense *tmatd;
183187828ca2SBarry Smith     PetscScalar  *v2;
1832af36a384SStefano Zampini     PetscInt      M2;
1833ea709b57SSatish Balay 
18346536e3caSStefano Zampini     if (reuse == MAT_INITIAL_MATRIX) {
18359566063dSJacob Faibussowitsch       PetscCall(MatCreate(PetscObjectComm((PetscObject)A), &tmat));
18369566063dSJacob Faibussowitsch       PetscCall(MatSetSizes(tmat, A->cmap->n, A->rmap->n, A->cmap->n, A->rmap->n));
18379566063dSJacob Faibussowitsch       PetscCall(MatSetType(tmat, ((PetscObject)A)->type_name));
18389566063dSJacob Faibussowitsch       PetscCall(MatSeqDenseSetPreallocation(tmat, NULL));
1839ca15aa20SStefano Zampini     } else tmat = *matout;
1840ca15aa20SStefano Zampini 
18419566063dSJacob Faibussowitsch     PetscCall(MatDenseGetArrayRead(A, (const PetscScalar **)&v));
18429566063dSJacob Faibussowitsch     PetscCall(MatDenseGetArray(tmat, &v2));
1843ec8511deSBarry Smith     tmatd = (Mat_SeqDense *)tmat->data;
1844ca15aa20SStefano Zampini     M2    = tmatd->lda;
1845d3e5ee88SLois Curfman McInnes     for (j = 0; j < n; j++) {
1846af36a384SStefano Zampini       for (k = 0; k < m; k++) v2[j + k * M2] = v[k + j * M];
1847d3e5ee88SLois Curfman McInnes     }
18489566063dSJacob Faibussowitsch     PetscCall(MatDenseRestoreArray(tmat, &v2));
18499566063dSJacob Faibussowitsch     PetscCall(MatDenseRestoreArrayRead(A, (const PetscScalar **)&v));
18509566063dSJacob Faibussowitsch     PetscCall(MatAssemblyBegin(tmat, MAT_FINAL_ASSEMBLY));
18519566063dSJacob Faibussowitsch     PetscCall(MatAssemblyEnd(tmat, MAT_FINAL_ASSEMBLY));
18526536e3caSStefano Zampini     *matout = tmat;
185348b35521SBarry Smith   }
18543ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1855289bc588SBarry Smith }
1856289bc588SBarry Smith 
1857d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatEqual_SeqDense(Mat A1, Mat A2, PetscBool *flg)
1858d71ae5a4SJacob Faibussowitsch {
1859c0bbcb79SLois Curfman McInnes   Mat_SeqDense      *mat1 = (Mat_SeqDense *)A1->data;
1860c0bbcb79SLois Curfman McInnes   Mat_SeqDense      *mat2 = (Mat_SeqDense *)A2->data;
1861ca15aa20SStefano Zampini   PetscInt           i;
1862ca15aa20SStefano Zampini   const PetscScalar *v1, *v2;
18639ea5d5aeSSatish Balay 
18643a40ed3dSBarry Smith   PetscFunctionBegin;
18659371c9d4SSatish Balay   if (A1->rmap->n != A2->rmap->n) {
18669371c9d4SSatish Balay     *flg = PETSC_FALSE;
18673ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
18689371c9d4SSatish Balay   }
18699371c9d4SSatish Balay   if (A1->cmap->n != A2->cmap->n) {
18709371c9d4SSatish Balay     *flg = PETSC_FALSE;
18713ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
18729371c9d4SSatish Balay   }
18739566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArrayRead(A1, &v1));
18749566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArrayRead(A2, &v2));
1875ca15aa20SStefano Zampini   for (i = 0; i < A1->cmap->n; i++) {
18769566063dSJacob Faibussowitsch     PetscCall(PetscArraycmp(v1, v2, A1->rmap->n, flg));
18773ba16761SJacob Faibussowitsch     if (*flg == PETSC_FALSE) PetscFunctionReturn(PETSC_SUCCESS);
1878ca15aa20SStefano Zampini     v1 += mat1->lda;
1879ca15aa20SStefano Zampini     v2 += mat2->lda;
18801b807ce4Svictorle   }
18819566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArrayRead(A1, &v1));
18829566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArrayRead(A2, &v2));
188377c4ece6SBarry Smith   *flg = PETSC_TRUE;
18843ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1885289bc588SBarry Smith }
1886289bc588SBarry Smith 
188714277c92SJacob Faibussowitsch PetscErrorCode MatGetDiagonal_SeqDense(Mat A, Vec v)
1888d71ae5a4SJacob Faibussowitsch {
1889c0bbcb79SLois Curfman McInnes   Mat_SeqDense      *mat = (Mat_SeqDense *)A->data;
189013f74950SBarry Smith   PetscInt           i, n, len;
1891ca15aa20SStefano Zampini   PetscScalar       *x;
1892ca15aa20SStefano Zampini   const PetscScalar *vv;
189344cd7ae7SLois Curfman McInnes 
18943a40ed3dSBarry Smith   PetscFunctionBegin;
18959566063dSJacob Faibussowitsch   PetscCall(VecGetSize(v, &n));
18969566063dSJacob Faibussowitsch   PetscCall(VecGetArray(v, &x));
1897d0f46423SBarry Smith   len = PetscMin(A->rmap->n, A->cmap->n);
18989566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArrayRead(A, &vv));
189908401ef6SPierre Jolivet   PetscCheck(n == A->rmap->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Nonconforming mat and vec");
1900ad540459SPierre Jolivet   for (i = 0; i < len; i++) x[i] = vv[i * mat->lda + i];
19019566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArrayRead(A, &vv));
19029566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(v, &x));
19033ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1904289bc588SBarry Smith }
1905289bc588SBarry Smith 
1906d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatDiagonalScale_SeqDense(Mat A, Vec ll, Vec rr)
1907d71ae5a4SJacob Faibussowitsch {
1908c0bbcb79SLois Curfman McInnes   Mat_SeqDense      *mat = (Mat_SeqDense *)A->data;
1909f1ceaac6SMatthew G. Knepley   const PetscScalar *l, *r;
1910ca15aa20SStefano Zampini   PetscScalar        x, *v, *vv;
1911d0f46423SBarry Smith   PetscInt           i, j, m = A->rmap->n, n = A->cmap->n;
191255659b69SBarry Smith 
19133a40ed3dSBarry Smith   PetscFunctionBegin;
19149566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArray(A, &vv));
191528988994SBarry Smith   if (ll) {
19169566063dSJacob Faibussowitsch     PetscCall(VecGetSize(ll, &m));
19179566063dSJacob Faibussowitsch     PetscCall(VecGetArrayRead(ll, &l));
191808401ef6SPierre Jolivet     PetscCheck(m == A->rmap->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Left scaling vec wrong size");
1919da3a660dSBarry Smith     for (i = 0; i < m; i++) {
1920da3a660dSBarry Smith       x = l[i];
1921ca15aa20SStefano Zampini       v = vv + i;
19229371c9d4SSatish Balay       for (j = 0; j < n; j++) {
19239371c9d4SSatish Balay         (*v) *= x;
19249371c9d4SSatish Balay         v += mat->lda;
19259371c9d4SSatish Balay       }
1926da3a660dSBarry Smith     }
19279566063dSJacob Faibussowitsch     PetscCall(VecRestoreArrayRead(ll, &l));
19289566063dSJacob Faibussowitsch     PetscCall(PetscLogFlops(1.0 * n * m));
1929da3a660dSBarry Smith   }
193028988994SBarry Smith   if (rr) {
19319566063dSJacob Faibussowitsch     PetscCall(VecGetSize(rr, &n));
19329566063dSJacob Faibussowitsch     PetscCall(VecGetArrayRead(rr, &r));
193308401ef6SPierre Jolivet     PetscCheck(n == A->cmap->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Right scaling vec wrong size");
1934da3a660dSBarry Smith     for (i = 0; i < n; i++) {
1935da3a660dSBarry Smith       x = r[i];
1936ca15aa20SStefano Zampini       v = vv + i * mat->lda;
19372205254eSKarl Rupp       for (j = 0; j < m; j++) (*v++) *= x;
1938da3a660dSBarry Smith     }
19399566063dSJacob Faibussowitsch     PetscCall(VecRestoreArrayRead(rr, &r));
19409566063dSJacob Faibussowitsch     PetscCall(PetscLogFlops(1.0 * n * m));
1941da3a660dSBarry Smith   }
19429566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArray(A, &vv));
19433ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1944289bc588SBarry Smith }
1945289bc588SBarry Smith 
1946d71ae5a4SJacob Faibussowitsch PetscErrorCode MatNorm_SeqDense(Mat A, NormType type, PetscReal *nrm)
1947d71ae5a4SJacob Faibussowitsch {
1948c0bbcb79SLois Curfman McInnes   Mat_SeqDense *mat = (Mat_SeqDense *)A->data;
1949ca15aa20SStefano Zampini   PetscScalar  *v, *vv;
1950329f5518SBarry Smith   PetscReal     sum = 0.0;
195175f6d85dSStefano Zampini   PetscInt      lda, m = A->rmap->n, i, j;
195255659b69SBarry Smith 
19533a40ed3dSBarry Smith   PetscFunctionBegin;
19549566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArrayRead(A, (const PetscScalar **)&vv));
19559566063dSJacob Faibussowitsch   PetscCall(MatDenseGetLDA(A, &lda));
1956ca15aa20SStefano Zampini   v = vv;
1957289bc588SBarry Smith   if (type == NORM_FROBENIUS) {
1958a5ce6ee0Svictorle     if (lda > m) {
1959d0f46423SBarry Smith       for (j = 0; j < A->cmap->n; j++) {
1960ca15aa20SStefano Zampini         v = vv + j * lda;
1961a5ce6ee0Svictorle         for (i = 0; i < m; i++) {
19629371c9d4SSatish Balay           sum += PetscRealPart(PetscConj(*v) * (*v));
19639371c9d4SSatish Balay           v++;
1964a5ce6ee0Svictorle         }
1965a5ce6ee0Svictorle       }
1966a5ce6ee0Svictorle     } else {
1967570b7f6dSBarry Smith #if defined(PETSC_USE_REAL___FP16)
1968570b7f6dSBarry Smith       PetscBLASInt one = 1, cnt = A->cmap->n * A->rmap->n;
1969792fecdfSBarry Smith       PetscCallBLAS("BLASnrm2", *nrm = BLASnrm2_(&cnt, v, &one));
1970570b7f6dSBarry Smith     }
1971570b7f6dSBarry Smith #else
1972d0f46423SBarry Smith       for (i = 0; i < A->cmap->n * A->rmap->n; i++) {
19739371c9d4SSatish Balay         sum += PetscRealPart(PetscConj(*v) * (*v));
19749371c9d4SSatish Balay         v++;
1975289bc588SBarry Smith       }
1976a5ce6ee0Svictorle     }
19778f1a2a5eSBarry Smith     *nrm = PetscSqrtReal(sum);
1978570b7f6dSBarry Smith #endif
19799566063dSJacob Faibussowitsch     PetscCall(PetscLogFlops(2.0 * A->cmap->n * A->rmap->n));
19803a40ed3dSBarry Smith   } else if (type == NORM_1) {
1981064f8208SBarry Smith     *nrm = 0.0;
1982d0f46423SBarry Smith     for (j = 0; j < A->cmap->n; j++) {
1983ca15aa20SStefano Zampini       v   = vv + j * mat->lda;
1984289bc588SBarry Smith       sum = 0.0;
1985d0f46423SBarry Smith       for (i = 0; i < A->rmap->n; i++) {
19869371c9d4SSatish Balay         sum += PetscAbsScalar(*v);
19879371c9d4SSatish Balay         v++;
1988289bc588SBarry Smith       }
1989064f8208SBarry Smith       if (sum > *nrm) *nrm = sum;
1990289bc588SBarry Smith     }
19919566063dSJacob Faibussowitsch     PetscCall(PetscLogFlops(1.0 * A->cmap->n * A->rmap->n));
19923a40ed3dSBarry Smith   } else if (type == NORM_INFINITY) {
1993064f8208SBarry Smith     *nrm = 0.0;
1994d0f46423SBarry Smith     for (j = 0; j < A->rmap->n; j++) {
1995ca15aa20SStefano Zampini       v   = vv + j;
1996289bc588SBarry Smith       sum = 0.0;
1997d0f46423SBarry Smith       for (i = 0; i < A->cmap->n; i++) {
19989371c9d4SSatish Balay         sum += PetscAbsScalar(*v);
19999371c9d4SSatish Balay         v += mat->lda;
2000289bc588SBarry Smith       }
2001064f8208SBarry Smith       if (sum > *nrm) *nrm = sum;
2002289bc588SBarry Smith     }
20039566063dSJacob Faibussowitsch     PetscCall(PetscLogFlops(1.0 * A->cmap->n * A->rmap->n));
2004e7e72b3dSBarry Smith   } else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "No two norm");
20059566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArrayRead(A, (const PetscScalar **)&vv));
20063ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2007289bc588SBarry Smith }
2008289bc588SBarry Smith 
2009d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatSetOption_SeqDense(Mat A, MatOption op, PetscBool flg)
2010d71ae5a4SJacob Faibussowitsch {
2011c0bbcb79SLois Curfman McInnes   Mat_SeqDense *aij = (Mat_SeqDense *)A->data;
201267e560aaSBarry Smith 
20133a40ed3dSBarry Smith   PetscFunctionBegin;
2014b5a2b587SKris Buschelman   switch (op) {
2015d71ae5a4SJacob Faibussowitsch   case MAT_ROW_ORIENTED:
2016d71ae5a4SJacob Faibussowitsch     aij->roworiented = flg;
2017d71ae5a4SJacob Faibussowitsch     break;
2018512a5fc5SBarry Smith   case MAT_NEW_NONZERO_LOCATIONS:
2019b5a2b587SKris Buschelman   case MAT_NEW_NONZERO_LOCATION_ERR:
20203971808eSMatthew Knepley   case MAT_NEW_NONZERO_ALLOCATION_ERR:
20218c78258cSHong Zhang   case MAT_FORCE_DIAGONAL_ENTRIES:
202213fa8e87SLisandro Dalcin   case MAT_KEEP_NONZERO_PATTERN:
2023b5a2b587SKris Buschelman   case MAT_IGNORE_OFF_PROC_ENTRIES:
2024b5a2b587SKris Buschelman   case MAT_USE_HASH_TABLE:
20250f8fb01aSBarry Smith   case MAT_IGNORE_ZERO_ENTRIES:
20265021d80fSJed Brown   case MAT_IGNORE_LOWER_TRIANGULAR:
2027d71ae5a4SJacob Faibussowitsch   case MAT_SORTED_FULL:
2028d71ae5a4SJacob Faibussowitsch     PetscCall(PetscInfo(A, "Option %s ignored\n", MatOptions[op]));
2029d71ae5a4SJacob Faibussowitsch     break;
20305021d80fSJed Brown   case MAT_SPD:
203177e54ba9SKris Buschelman   case MAT_SYMMETRIC:
203277e54ba9SKris Buschelman   case MAT_STRUCTURALLY_SYMMETRIC:
20339a4540c5SBarry Smith   case MAT_HERMITIAN:
20349a4540c5SBarry Smith   case MAT_SYMMETRY_ETERNAL:
2035b94d7dedSBarry Smith   case MAT_STRUCTURAL_SYMMETRY_ETERNAL:
2036d71ae5a4SJacob Faibussowitsch   case MAT_SPD_ETERNAL:
2037d71ae5a4SJacob Faibussowitsch     break;
2038d71ae5a4SJacob Faibussowitsch   default:
2039d71ae5a4SJacob Faibussowitsch     SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "unknown option %s", MatOptions[op]);
20403a40ed3dSBarry Smith   }
20413ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2042289bc588SBarry Smith }
2043289bc588SBarry Smith 
2044d71ae5a4SJacob Faibussowitsch PetscErrorCode MatZeroEntries_SeqDense(Mat A)
2045d71ae5a4SJacob Faibussowitsch {
2046ec8511deSBarry Smith   Mat_SeqDense *l   = (Mat_SeqDense *)A->data;
20473d8925e7SStefano Zampini   PetscInt      lda = l->lda, m = A->rmap->n, n = A->cmap->n, j;
2048ca15aa20SStefano Zampini   PetscScalar  *v;
20493a40ed3dSBarry Smith 
20503a40ed3dSBarry Smith   PetscFunctionBegin;
20519566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArrayWrite(A, &v));
2052a5ce6ee0Svictorle   if (lda > m) {
205348a46eb9SPierre Jolivet     for (j = 0; j < n; j++) PetscCall(PetscArrayzero(v + j * lda, m));
2054a5ce6ee0Svictorle   } else {
20559566063dSJacob Faibussowitsch     PetscCall(PetscArrayzero(v, PetscInt64Mult(m, n)));
2056a5ce6ee0Svictorle   }
20579566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArrayWrite(A, &v));
20583ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
20596f0a148fSBarry Smith }
20606f0a148fSBarry Smith 
2061d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatZeroRows_SeqDense(Mat A, PetscInt N, const PetscInt rows[], PetscScalar diag, Vec x, Vec b)
2062d71ae5a4SJacob Faibussowitsch {
2063ec8511deSBarry Smith   Mat_SeqDense      *l = (Mat_SeqDense *)A->data;
2064b9679d65SBarry Smith   PetscInt           m = l->lda, n = A->cmap->n, i, j;
2065ca15aa20SStefano Zampini   PetscScalar       *slot, *bb, *v;
206697b48c8fSBarry Smith   const PetscScalar *xx;
206755659b69SBarry Smith 
20683a40ed3dSBarry Smith   PetscFunctionBegin;
206976bd3646SJed Brown   if (PetscDefined(USE_DEBUG)) {
2070b9679d65SBarry Smith     for (i = 0; i < N; i++) {
207108401ef6SPierre Jolivet       PetscCheck(rows[i] >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Negative row requested to be zeroed");
207208401ef6SPierre 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);
2073b9679d65SBarry Smith     }
207476bd3646SJed Brown   }
20753ba16761SJacob Faibussowitsch   if (!N) PetscFunctionReturn(PETSC_SUCCESS);
2076b9679d65SBarry Smith 
2077dd8e379bSPierre Jolivet   /* fix right-hand side if needed */
207897b48c8fSBarry Smith   if (x && b) {
20799566063dSJacob Faibussowitsch     PetscCall(VecGetArrayRead(x, &xx));
20809566063dSJacob Faibussowitsch     PetscCall(VecGetArray(b, &bb));
20812205254eSKarl Rupp     for (i = 0; i < N; i++) bb[rows[i]] = diag * xx[rows[i]];
20829566063dSJacob Faibussowitsch     PetscCall(VecRestoreArrayRead(x, &xx));
20839566063dSJacob Faibussowitsch     PetscCall(VecRestoreArray(b, &bb));
208497b48c8fSBarry Smith   }
208597b48c8fSBarry Smith 
20869566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArray(A, &v));
20876f0a148fSBarry Smith   for (i = 0; i < N; i++) {
2088ca15aa20SStefano Zampini     slot = v + rows[i];
20899371c9d4SSatish Balay     for (j = 0; j < n; j++) {
20909371c9d4SSatish Balay       *slot = 0.0;
20919371c9d4SSatish Balay       slot += m;
20929371c9d4SSatish Balay     }
20936f0a148fSBarry Smith   }
2094f4df32b1SMatthew Knepley   if (diag != 0.0) {
209508401ef6SPierre Jolivet     PetscCheck(A->rmap->n == A->cmap->n, PETSC_COMM_SELF, PETSC_ERR_SUP, "Only coded for square matrices");
20966f0a148fSBarry Smith     for (i = 0; i < N; i++) {
2097ca15aa20SStefano Zampini       slot  = v + (m + 1) * rows[i];
2098f4df32b1SMatthew Knepley       *slot = diag;
20996f0a148fSBarry Smith     }
21006f0a148fSBarry Smith   }
21019566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArray(A, &v));
21023ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
21036f0a148fSBarry Smith }
2104557bce09SLois Curfman McInnes 
2105d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatDenseGetLDA_SeqDense(Mat A, PetscInt *lda)
2106d71ae5a4SJacob Faibussowitsch {
210749a6ff4bSBarry Smith   Mat_SeqDense *mat = (Mat_SeqDense *)A->data;
210849a6ff4bSBarry Smith 
210949a6ff4bSBarry Smith   PetscFunctionBegin;
211049a6ff4bSBarry Smith   *lda = mat->lda;
21113ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
211249a6ff4bSBarry Smith }
211349a6ff4bSBarry Smith 
2114d71ae5a4SJacob Faibussowitsch PetscErrorCode MatDenseGetArray_SeqDense(Mat A, PetscScalar **array)
2115d71ae5a4SJacob Faibussowitsch {
2116c0bbcb79SLois Curfman McInnes   Mat_SeqDense *mat = (Mat_SeqDense *)A->data;
21173a40ed3dSBarry Smith 
21183a40ed3dSBarry Smith   PetscFunctionBegin;
211928b400f6SJacob Faibussowitsch   PetscCheck(!mat->matinuse, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Need to call MatDenseRestoreSubMatrix() first");
212064e87e97SBarry Smith   *array = mat->v;
21213ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
212264e87e97SBarry Smith }
21230754003eSLois Curfman McInnes 
2124d71ae5a4SJacob Faibussowitsch PetscErrorCode MatDenseRestoreArray_SeqDense(Mat A, PetscScalar **array)
2125d71ae5a4SJacob Faibussowitsch {
21263a40ed3dSBarry Smith   PetscFunctionBegin;
212775f6d85dSStefano Zampini   if (array) *array = NULL;
21283ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2129ff14e315SSatish Balay }
21300754003eSLois Curfman McInnes 
21310f74d2c1SSatish Balay /*@
213211a5261eSBarry Smith   MatDenseGetLDA - gets the leading dimension of the array returned from `MatDenseGetArray()`
213349a6ff4bSBarry Smith 
21342ef1f0ffSBarry Smith   Not Collective
213549a6ff4bSBarry Smith 
213649a6ff4bSBarry Smith   Input Parameter:
2137fe59aa6dSJacob Faibussowitsch . A - a `MATDENSE` or `MATDENSECUDA` matrix
213849a6ff4bSBarry Smith 
213949a6ff4bSBarry Smith   Output Parameter:
214049a6ff4bSBarry Smith . lda - the leading dimension
214149a6ff4bSBarry Smith 
214249a6ff4bSBarry Smith   Level: intermediate
214349a6ff4bSBarry Smith 
21441cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATDENSE`, `MATDENSECUDA`, `MatDenseGetArray()`, `MatDenseRestoreArray()`, `MatDenseGetArrayRead()`, `MatDenseRestoreArrayRead()`, `MatDenseSetLDA()`
214549a6ff4bSBarry Smith @*/
2146d71ae5a4SJacob Faibussowitsch PetscErrorCode MatDenseGetLDA(Mat A, PetscInt *lda)
2147d71ae5a4SJacob Faibussowitsch {
214849a6ff4bSBarry Smith   PetscFunctionBegin;
2149d5ea218eSStefano Zampini   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
21504f572ea9SToby Isaac   PetscAssertPointer(lda, 2);
215175f6d85dSStefano Zampini   MatCheckPreallocated(A, 1);
2152cac4c232SBarry Smith   PetscUseMethod(A, "MatDenseGetLDA_C", (Mat, PetscInt *), (A, lda));
21533ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
215449a6ff4bSBarry Smith }
215549a6ff4bSBarry Smith 
21560f74d2c1SSatish Balay /*@
215711a5261eSBarry Smith   MatDenseSetLDA - Sets the leading dimension of the array used by the `MATDENSE` matrix
2158ad16ce7aSStefano Zampini 
21592323109cSBarry Smith   Collective if the matrix layouts have not yet been setup
2160ad16ce7aSStefano Zampini 
2161d8d19677SJose E. Roman   Input Parameters:
2162fe59aa6dSJacob Faibussowitsch + A   - a `MATDENSE` or `MATDENSECUDA` matrix
2163ad16ce7aSStefano Zampini - lda - the leading dimension
2164ad16ce7aSStefano Zampini 
2165ad16ce7aSStefano Zampini   Level: intermediate
2166ad16ce7aSStefano Zampini 
21671cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATDENSE`, `MATDENSECUDA`, `MatDenseGetArray()`, `MatDenseRestoreArray()`, `MatDenseGetArrayRead()`, `MatDenseRestoreArrayRead()`, `MatDenseGetLDA()`
2168ad16ce7aSStefano Zampini @*/
2169d71ae5a4SJacob Faibussowitsch PetscErrorCode MatDenseSetLDA(Mat A, PetscInt lda)
2170d71ae5a4SJacob Faibussowitsch {
2171ad16ce7aSStefano Zampini   PetscFunctionBegin;
2172ad16ce7aSStefano Zampini   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
2173cac4c232SBarry Smith   PetscTryMethod(A, "MatDenseSetLDA_C", (Mat, PetscInt), (A, lda));
21743ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2175ad16ce7aSStefano Zampini }
2176ad16ce7aSStefano Zampini 
2177ad16ce7aSStefano Zampini /*@C
217811a5261eSBarry Smith   MatDenseGetArray - gives read-write access to the array where the data for a `MATDENSE` matrix is stored
217973a71a0fSBarry Smith 
2180c3339decSBarry Smith   Logically Collective
218173a71a0fSBarry Smith 
218273a71a0fSBarry Smith   Input Parameter:
2183fe59aa6dSJacob Faibussowitsch . A - a dense matrix
218473a71a0fSBarry Smith 
218573a71a0fSBarry Smith   Output Parameter:
218673a71a0fSBarry Smith . array - pointer to the data
218773a71a0fSBarry Smith 
218873a71a0fSBarry Smith   Level: intermediate
218973a71a0fSBarry Smith 
2190fe59aa6dSJacob Faibussowitsch   Fortran Notes:
21910ab4885dSBarry Smith   `MatDenseGetArray()` Fortran binding is deprecated (since PETSc 3.19), use `MatDenseGetArrayF90()`
21920ab4885dSBarry Smith 
21931cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATDENSE`, `MatDenseRestoreArray()`, `MatDenseGetArrayRead()`, `MatDenseRestoreArrayRead()`, `MatDenseGetArrayWrite()`, `MatDenseRestoreArrayWrite()`
219473a71a0fSBarry Smith @*/
2195d71ae5a4SJacob Faibussowitsch PetscErrorCode MatDenseGetArray(Mat A, PetscScalar **array)
2196d71ae5a4SJacob Faibussowitsch {
219773a71a0fSBarry Smith   PetscFunctionBegin;
2198d5ea218eSStefano Zampini   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
21994f572ea9SToby Isaac   PetscAssertPointer(array, 2);
2200cac4c232SBarry Smith   PetscUseMethod(A, "MatDenseGetArray_C", (Mat, PetscScalar **), (A, array));
22013ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
220273a71a0fSBarry Smith }
220373a71a0fSBarry Smith 
2204dec5eb66SMatthew G Knepley /*@C
220511a5261eSBarry Smith   MatDenseRestoreArray - returns access to the array where the data for a `MATDENSE` matrix is stored obtained by `MatDenseGetArray()`
220673a71a0fSBarry Smith 
2207c3339decSBarry Smith   Logically Collective
22088572280aSBarry Smith 
22098572280aSBarry Smith   Input Parameters:
2210fe59aa6dSJacob Faibussowitsch + A     - a dense matrix
22112ef1f0ffSBarry Smith - array - pointer to the data (may be `NULL`)
22128572280aSBarry Smith 
22138572280aSBarry Smith   Level: intermediate
22148572280aSBarry Smith 
2215fe59aa6dSJacob Faibussowitsch   Fortran Notes:
22160ab4885dSBarry Smith   `MatDenseRestoreArray()` Fortran binding is deprecated (since PETSc 3.19), use `MatDenseRestoreArrayF90()`
22170ab4885dSBarry Smith 
22181cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATDENSE`, `MatDenseGetArray()`, `MatDenseGetArrayRead()`, `MatDenseRestoreArrayRead()`, `MatDenseGetArrayWrite()`, `MatDenseRestoreArrayWrite()`
22198572280aSBarry Smith @*/
2220d71ae5a4SJacob Faibussowitsch PetscErrorCode MatDenseRestoreArray(Mat A, PetscScalar **array)
2221d71ae5a4SJacob Faibussowitsch {
22228572280aSBarry Smith   PetscFunctionBegin;
2223d5ea218eSStefano Zampini   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
22244f572ea9SToby Isaac   if (array) PetscAssertPointer(array, 2);
2225cac4c232SBarry Smith   PetscUseMethod(A, "MatDenseRestoreArray_C", (Mat, PetscScalar **), (A, array));
22269566063dSJacob Faibussowitsch   PetscCall(PetscObjectStateIncrease((PetscObject)A));
222747d993e7Ssuyashtn #if defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
2228637a0070SStefano Zampini   A->offloadmask = PETSC_OFFLOAD_CPU;
2229637a0070SStefano Zampini #endif
22303ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
22318572280aSBarry Smith }
22328572280aSBarry Smith 
22338572280aSBarry Smith /*@C
223411a5261eSBarry Smith   MatDenseGetArrayRead - gives read-only access to the array where the data for a `MATDENSE` matrix is stored
22358572280aSBarry Smith 
2236fb850c59SBarry Smith   Not Collective
22378572280aSBarry Smith 
22388572280aSBarry Smith   Input Parameter:
2239fe59aa6dSJacob Faibussowitsch . A - a dense matrix
22408572280aSBarry Smith 
22418572280aSBarry Smith   Output Parameter:
22428572280aSBarry Smith . array - pointer to the data
22438572280aSBarry Smith 
22448572280aSBarry Smith   Level: intermediate
22458572280aSBarry Smith 
22461cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATDENSE`, `MatDenseRestoreArrayRead()`, `MatDenseGetArray()`, `MatDenseRestoreArray()`, `MatDenseGetArrayWrite()`, `MatDenseRestoreArrayWrite()`
22478572280aSBarry Smith @*/
2248d71ae5a4SJacob Faibussowitsch PetscErrorCode MatDenseGetArrayRead(Mat A, const PetscScalar **array)
2249d71ae5a4SJacob Faibussowitsch {
22508572280aSBarry Smith   PetscFunctionBegin;
2251d5ea218eSStefano Zampini   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
22524f572ea9SToby Isaac   PetscAssertPointer(array, 2);
22535c0db29aSPierre Jolivet   PetscUseMethod(A, "MatDenseGetArrayRead_C", (Mat, PetscScalar **), (A, (PetscScalar **)array));
22543ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
22558572280aSBarry Smith }
22568572280aSBarry Smith 
22578572280aSBarry Smith /*@C
225811a5261eSBarry Smith   MatDenseRestoreArrayRead - returns access to the array where the data for a `MATDENSE` matrix is stored obtained by `MatDenseGetArrayRead()`
22598572280aSBarry Smith 
2260fb850c59SBarry Smith   Not Collective
226173a71a0fSBarry Smith 
226273a71a0fSBarry Smith   Input Parameters:
2263fe59aa6dSJacob Faibussowitsch + A     - a dense matrix
22642ef1f0ffSBarry Smith - array - pointer to the data (may be `NULL`)
226573a71a0fSBarry Smith 
226673a71a0fSBarry Smith   Level: intermediate
226773a71a0fSBarry Smith 
22681cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATDENSE`, `MatDenseGetArrayRead()`, `MatDenseGetArray()`, `MatDenseRestoreArray()`, `MatDenseGetArrayWrite()`, `MatDenseRestoreArrayWrite()`
226973a71a0fSBarry Smith @*/
2270d71ae5a4SJacob Faibussowitsch PetscErrorCode MatDenseRestoreArrayRead(Mat A, const PetscScalar **array)
2271d71ae5a4SJacob Faibussowitsch {
227273a71a0fSBarry Smith   PetscFunctionBegin;
2273d5ea218eSStefano Zampini   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
22744f572ea9SToby Isaac   if (array) PetscAssertPointer(array, 2);
22755c0db29aSPierre Jolivet   PetscUseMethod(A, "MatDenseRestoreArrayRead_C", (Mat, PetscScalar **), (A, (PetscScalar **)array));
22763ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
227773a71a0fSBarry Smith }
227873a71a0fSBarry Smith 
22796947451fSStefano Zampini /*@C
228011a5261eSBarry Smith   MatDenseGetArrayWrite - gives write-only access to the array where the data for a `MATDENSE` matrix is stored
22816947451fSStefano Zampini 
2282fb850c59SBarry Smith   Not Collective
22836947451fSStefano Zampini 
22846947451fSStefano Zampini   Input Parameter:
2285fe59aa6dSJacob Faibussowitsch . A - a dense matrix
22866947451fSStefano Zampini 
22876947451fSStefano Zampini   Output Parameter:
22886947451fSStefano Zampini . array - pointer to the data
22896947451fSStefano Zampini 
22906947451fSStefano Zampini   Level: intermediate
22916947451fSStefano Zampini 
22921cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATDENSE`, `MatDenseRestoreArrayWrite()`, `MatDenseGetArray()`, `MatDenseRestoreArray()`, `MatDenseGetArrayRead()`, `MatDenseRestoreArrayRead()`
22936947451fSStefano Zampini @*/
2294d71ae5a4SJacob Faibussowitsch PetscErrorCode MatDenseGetArrayWrite(Mat A, PetscScalar **array)
2295d71ae5a4SJacob Faibussowitsch {
22966947451fSStefano Zampini   PetscFunctionBegin;
2297d5ea218eSStefano Zampini   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
22984f572ea9SToby Isaac   PetscAssertPointer(array, 2);
2299cac4c232SBarry Smith   PetscUseMethod(A, "MatDenseGetArrayWrite_C", (Mat, PetscScalar **), (A, array));
23003ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
23016947451fSStefano Zampini }
23026947451fSStefano Zampini 
23036947451fSStefano Zampini /*@C
230411a5261eSBarry Smith   MatDenseRestoreArrayWrite - returns access to the array where the data for a `MATDENSE` matrix is stored obtained by `MatDenseGetArrayWrite()`
23056947451fSStefano Zampini 
2306fb850c59SBarry Smith   Not Collective
23076947451fSStefano Zampini 
23086947451fSStefano Zampini   Input Parameters:
2309fe59aa6dSJacob Faibussowitsch + A     - a dense matrix
23102ef1f0ffSBarry Smith - array - pointer to the data (may be `NULL`)
23116947451fSStefano Zampini 
23126947451fSStefano Zampini   Level: intermediate
23136947451fSStefano Zampini 
23141cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATDENSE`, `MatDenseGetArrayWrite()`, `MatDenseGetArray()`, `MatDenseRestoreArray()`, `MatDenseGetArrayRead()`, `MatDenseRestoreArrayRead()`
23156947451fSStefano Zampini @*/
2316d71ae5a4SJacob Faibussowitsch PetscErrorCode MatDenseRestoreArrayWrite(Mat A, PetscScalar **array)
2317d71ae5a4SJacob Faibussowitsch {
23186947451fSStefano Zampini   PetscFunctionBegin;
2319d5ea218eSStefano Zampini   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
23204f572ea9SToby Isaac   if (array) PetscAssertPointer(array, 2);
2321cac4c232SBarry Smith   PetscUseMethod(A, "MatDenseRestoreArrayWrite_C", (Mat, PetscScalar **), (A, array));
23229566063dSJacob Faibussowitsch   PetscCall(PetscObjectStateIncrease((PetscObject)A));
232347d993e7Ssuyashtn #if defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
23246947451fSStefano Zampini   A->offloadmask = PETSC_OFFLOAD_CPU;
23256947451fSStefano Zampini #endif
23263ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
23276947451fSStefano Zampini }
23286947451fSStefano Zampini 
2329cd3f9d89SJunchao Zhang /*@C
2330cd3f9d89SJunchao Zhang   MatDenseGetArrayAndMemType - gives read-write access to the array where the data for a `MATDENSE` matrix is stored
2331cd3f9d89SJunchao Zhang 
2332cd3f9d89SJunchao Zhang   Logically Collective
2333cd3f9d89SJunchao Zhang 
2334cd3f9d89SJunchao Zhang   Input Parameter:
2335fe59aa6dSJacob Faibussowitsch . A - a dense matrix
2336cd3f9d89SJunchao Zhang 
2337cd3f9d89SJunchao Zhang   Output Parameters:
2338cd3f9d89SJunchao Zhang + array - pointer to the data
2339cd3f9d89SJunchao Zhang - mtype - memory type of the returned pointer
2340cd3f9d89SJunchao Zhang 
2341cd3f9d89SJunchao Zhang   Level: intermediate
2342cd3f9d89SJunchao Zhang 
2343fb850c59SBarry Smith   Note:
23442ef1f0ffSBarry Smith   If the matrix is of a device type such as `MATDENSECUDA`, `MATDENSEHIP`, etc.,
23452ef1f0ffSBarry Smith   an array on device is always returned and is guaranteed to contain the matrix's latest data.
23462ef1f0ffSBarry Smith 
23471cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATDENSE`, `MatDenseRestoreArrayAndMemType()`, `MatDenseGetArrayReadAndMemType()`, `MatDenseGetArrayWriteAndMemType()`, `MatDenseGetArrayRead()`,
2348cd3f9d89SJunchao Zhang    `MatDenseRestoreArrayRead()`, `MatDenseGetArrayWrite()`, `MatDenseRestoreArrayWrite()`, `MatSeqAIJGetCSRAndMemType()`
2349cd3f9d89SJunchao Zhang @*/
2350cd3f9d89SJunchao Zhang PetscErrorCode MatDenseGetArrayAndMemType(Mat A, PetscScalar **array, PetscMemType *mtype)
2351cd3f9d89SJunchao Zhang {
2352cd3f9d89SJunchao Zhang   PetscBool isMPI;
2353cd3f9d89SJunchao Zhang 
2354cd3f9d89SJunchao Zhang   PetscFunctionBegin;
2355cd3f9d89SJunchao Zhang   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
23564f572ea9SToby Isaac   PetscAssertPointer(array, 2);
2357e865de01SJunchao 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 */
2358cd3f9d89SJunchao Zhang   PetscCall(PetscObjectBaseTypeCompare((PetscObject)A, MATMPIDENSE, &isMPI));
2359cd3f9d89SJunchao Zhang   if (isMPI) {
2360cd3f9d89SJunchao Zhang     /* Dispatch here so that the code can be reused for all subclasses of MATDENSE */
2361cd3f9d89SJunchao Zhang     PetscCall(MatDenseGetArrayAndMemType(((Mat_MPIDense *)A->data)->A, array, mtype));
2362cd3f9d89SJunchao Zhang   } else {
2363cd3f9d89SJunchao Zhang     PetscErrorCode (*fptr)(Mat, PetscScalar **, PetscMemType *);
23643ba16761SJacob Faibussowitsch 
23653ba16761SJacob Faibussowitsch     PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatDenseGetArrayAndMemType_C", &fptr));
2366cd3f9d89SJunchao Zhang     if (fptr) {
2367cd3f9d89SJunchao Zhang       PetscCall((*fptr)(A, array, mtype));
2368cd3f9d89SJunchao Zhang     } else {
2369cd3f9d89SJunchao Zhang       PetscUseMethod(A, "MatDenseGetArray_C", (Mat, PetscScalar **), (A, array));
2370cd3f9d89SJunchao Zhang       if (mtype) *mtype = PETSC_MEMTYPE_HOST;
2371cd3f9d89SJunchao Zhang     }
2372cd3f9d89SJunchao Zhang   }
23733ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2374cd3f9d89SJunchao Zhang }
2375cd3f9d89SJunchao Zhang 
2376cd3f9d89SJunchao Zhang /*@C
2377cd3f9d89SJunchao Zhang   MatDenseRestoreArrayAndMemType - returns access to the array that is obtained by `MatDenseGetArrayAndMemType()`
2378cd3f9d89SJunchao Zhang 
2379cd3f9d89SJunchao Zhang   Logically Collective
2380cd3f9d89SJunchao Zhang 
2381cd3f9d89SJunchao Zhang   Input Parameters:
2382fe59aa6dSJacob Faibussowitsch + A     - a dense matrix
2383cd3f9d89SJunchao Zhang - array - pointer to the data
2384cd3f9d89SJunchao Zhang 
2385cd3f9d89SJunchao Zhang   Level: intermediate
2386cd3f9d89SJunchao Zhang 
23871cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATDENSE`, `MatDenseGetArrayAndMemType()`, `MatDenseGetArray()`, `MatDenseGetArrayRead()`, `MatDenseRestoreArrayRead()`, `MatDenseGetArrayWrite()`, `MatDenseRestoreArrayWrite()`
2388cd3f9d89SJunchao Zhang @*/
2389cd3f9d89SJunchao Zhang PetscErrorCode MatDenseRestoreArrayAndMemType(Mat A, PetscScalar **array)
2390cd3f9d89SJunchao Zhang {
2391cd3f9d89SJunchao Zhang   PetscBool isMPI;
2392cd3f9d89SJunchao Zhang 
2393cd3f9d89SJunchao Zhang   PetscFunctionBegin;
2394cd3f9d89SJunchao Zhang   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
23954f572ea9SToby Isaac   PetscAssertPointer(array, 2);
2396cd3f9d89SJunchao Zhang   PetscCall(PetscObjectBaseTypeCompare((PetscObject)A, MATMPIDENSE, &isMPI));
2397cd3f9d89SJunchao Zhang   if (isMPI) {
2398cd3f9d89SJunchao Zhang     PetscCall(MatDenseRestoreArrayAndMemType(((Mat_MPIDense *)A->data)->A, array));
2399cd3f9d89SJunchao Zhang   } else {
2400cd3f9d89SJunchao Zhang     PetscErrorCode (*fptr)(Mat, PetscScalar **);
24013ba16761SJacob Faibussowitsch 
24023ba16761SJacob Faibussowitsch     PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatDenseRestoreArrayAndMemType_C", &fptr));
2403cd3f9d89SJunchao Zhang     if (fptr) {
2404cd3f9d89SJunchao Zhang       PetscCall((*fptr)(A, array));
2405cd3f9d89SJunchao Zhang     } else {
2406cd3f9d89SJunchao Zhang       PetscUseMethod(A, "MatDenseRestoreArray_C", (Mat, PetscScalar **), (A, array));
2407cd3f9d89SJunchao Zhang     }
2408cd3f9d89SJunchao Zhang     *array = NULL;
2409cd3f9d89SJunchao Zhang   }
2410cd3f9d89SJunchao Zhang   PetscCall(PetscObjectStateIncrease((PetscObject)A));
24113ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2412cd3f9d89SJunchao Zhang }
2413cd3f9d89SJunchao Zhang 
2414cd3f9d89SJunchao Zhang /*@C
2415cd3f9d89SJunchao Zhang   MatDenseGetArrayReadAndMemType - gives read-only access to the array where the data for a `MATDENSE` matrix is stored
2416cd3f9d89SJunchao Zhang 
2417cd3f9d89SJunchao Zhang   Logically Collective
2418cd3f9d89SJunchao Zhang 
2419cd3f9d89SJunchao Zhang   Input Parameter:
2420fe59aa6dSJacob Faibussowitsch . A - a dense matrix
2421cd3f9d89SJunchao Zhang 
2422cd3f9d89SJunchao Zhang   Output Parameters:
2423cd3f9d89SJunchao Zhang + array - pointer to the data
2424cd3f9d89SJunchao Zhang - mtype - memory type of the returned pointer
2425cd3f9d89SJunchao Zhang 
2426cd3f9d89SJunchao Zhang   Level: intermediate
2427cd3f9d89SJunchao Zhang 
2428fb850c59SBarry Smith   Note:
24292ef1f0ffSBarry Smith   If the matrix is of a device type such as `MATDENSECUDA`, `MATDENSEHIP`, etc.,
24302ef1f0ffSBarry Smith   an array on device is always returned and is guaranteed to contain the matrix's latest data.
24312ef1f0ffSBarry Smith 
24321cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATDENSE`, `MatDenseRestoreArrayReadAndMemType()`, `MatDenseGetArrayWriteAndMemType()`,
2433cd3f9d89SJunchao Zhang    `MatDenseGetArrayRead()`, `MatDenseRestoreArrayRead()`, `MatDenseGetArrayWrite()`, `MatDenseRestoreArrayWrite()`, `MatSeqAIJGetCSRAndMemType()`
2434cd3f9d89SJunchao Zhang @*/
2435cd3f9d89SJunchao Zhang PetscErrorCode MatDenseGetArrayReadAndMemType(Mat A, const PetscScalar **array, PetscMemType *mtype)
2436cd3f9d89SJunchao Zhang {
2437cd3f9d89SJunchao Zhang   PetscBool isMPI;
2438cd3f9d89SJunchao Zhang 
2439cd3f9d89SJunchao Zhang   PetscFunctionBegin;
2440cd3f9d89SJunchao Zhang   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
24414f572ea9SToby Isaac   PetscAssertPointer(array, 2);
2442e865de01SJunchao 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 */
2443cd3f9d89SJunchao Zhang   PetscCall(PetscObjectBaseTypeCompare((PetscObject)A, MATMPIDENSE, &isMPI));
2444cd3f9d89SJunchao Zhang   if (isMPI) { /* Dispatch here so that the code can be reused for all subclasses of MATDENSE */
2445cd3f9d89SJunchao Zhang     PetscCall(MatDenseGetArrayReadAndMemType(((Mat_MPIDense *)A->data)->A, array, mtype));
2446cd3f9d89SJunchao Zhang   } else {
2447cd3f9d89SJunchao Zhang     PetscErrorCode (*fptr)(Mat, const PetscScalar **, PetscMemType *);
24483ba16761SJacob Faibussowitsch 
24493ba16761SJacob Faibussowitsch     PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatDenseGetArrayReadAndMemType_C", &fptr));
2450cd3f9d89SJunchao Zhang     if (fptr) {
2451cd3f9d89SJunchao Zhang       PetscCall((*fptr)(A, array, mtype));
2452cd3f9d89SJunchao Zhang     } else {
24535c0db29aSPierre Jolivet       PetscUseMethod(A, "MatDenseGetArrayRead_C", (Mat, PetscScalar **), (A, (PetscScalar **)array));
2454cd3f9d89SJunchao Zhang       if (mtype) *mtype = PETSC_MEMTYPE_HOST;
2455cd3f9d89SJunchao Zhang     }
2456cd3f9d89SJunchao Zhang   }
24573ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2458cd3f9d89SJunchao Zhang }
2459cd3f9d89SJunchao Zhang 
2460cd3f9d89SJunchao Zhang /*@C
2461cd3f9d89SJunchao Zhang   MatDenseRestoreArrayReadAndMemType - returns access to the array that is obtained by `MatDenseGetArrayReadAndMemType()`
2462cd3f9d89SJunchao Zhang 
2463cd3f9d89SJunchao Zhang   Logically Collective
2464cd3f9d89SJunchao Zhang 
2465cd3f9d89SJunchao Zhang   Input Parameters:
2466fe59aa6dSJacob Faibussowitsch + A     - a dense matrix
2467cd3f9d89SJunchao Zhang - array - pointer to the data
2468cd3f9d89SJunchao Zhang 
2469cd3f9d89SJunchao Zhang   Level: intermediate
2470cd3f9d89SJunchao Zhang 
24711cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATDENSE`, `MatDenseGetArrayReadAndMemType()`, `MatDenseGetArray()`, `MatDenseGetArrayRead()`, `MatDenseRestoreArrayRead()`, `MatDenseGetArrayWrite()`, `MatDenseRestoreArrayWrite()`
2472cd3f9d89SJunchao Zhang @*/
2473cd3f9d89SJunchao Zhang PetscErrorCode MatDenseRestoreArrayReadAndMemType(Mat A, const PetscScalar **array)
2474cd3f9d89SJunchao Zhang {
2475cd3f9d89SJunchao Zhang   PetscBool isMPI;
2476cd3f9d89SJunchao Zhang 
2477cd3f9d89SJunchao Zhang   PetscFunctionBegin;
2478cd3f9d89SJunchao Zhang   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
24794f572ea9SToby Isaac   PetscAssertPointer(array, 2);
2480cd3f9d89SJunchao Zhang   PetscCall(PetscObjectBaseTypeCompare((PetscObject)A, MATMPIDENSE, &isMPI));
2481cd3f9d89SJunchao Zhang   if (isMPI) {
2482cd3f9d89SJunchao Zhang     PetscCall(MatDenseRestoreArrayReadAndMemType(((Mat_MPIDense *)A->data)->A, array));
2483cd3f9d89SJunchao Zhang   } else {
2484cd3f9d89SJunchao Zhang     PetscErrorCode (*fptr)(Mat, const PetscScalar **);
24853ba16761SJacob Faibussowitsch 
24863ba16761SJacob Faibussowitsch     PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatDenseRestoreArrayReadAndMemType_C", &fptr));
2487cd3f9d89SJunchao Zhang     if (fptr) {
2488cd3f9d89SJunchao Zhang       PetscCall((*fptr)(A, array));
2489cd3f9d89SJunchao Zhang     } else {
24905c0db29aSPierre Jolivet       PetscUseMethod(A, "MatDenseRestoreArrayRead_C", (Mat, PetscScalar **), (A, (PetscScalar **)array));
2491cd3f9d89SJunchao Zhang     }
2492cd3f9d89SJunchao Zhang     *array = NULL;
2493cd3f9d89SJunchao Zhang   }
24943ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2495cd3f9d89SJunchao Zhang }
2496cd3f9d89SJunchao Zhang 
2497cd3f9d89SJunchao Zhang /*@C
2498cd3f9d89SJunchao Zhang   MatDenseGetArrayWriteAndMemType - gives write-only access to the array where the data for a `MATDENSE` matrix is stored
2499cd3f9d89SJunchao Zhang 
2500cd3f9d89SJunchao Zhang   Logically Collective
2501cd3f9d89SJunchao Zhang 
2502cd3f9d89SJunchao Zhang   Input Parameter:
2503fe59aa6dSJacob Faibussowitsch . A - a dense matrix
2504cd3f9d89SJunchao Zhang 
2505cd3f9d89SJunchao Zhang   Output Parameters:
2506cd3f9d89SJunchao Zhang + array - pointer to the data
2507cd3f9d89SJunchao Zhang - mtype - memory type of the returned pointer
2508cd3f9d89SJunchao Zhang 
2509cd3f9d89SJunchao Zhang   Level: intermediate
2510cd3f9d89SJunchao Zhang 
2511fb850c59SBarry Smith   Note:
25122ef1f0ffSBarry Smith   If the matrix is of a device type such as `MATDENSECUDA`, `MATDENSEHIP`, etc.,
25132ef1f0ffSBarry Smith   an array on device is always returned and is guaranteed to contain the matrix's latest data.
25142ef1f0ffSBarry Smith 
25151cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATDENSE`, `MatDenseRestoreArrayWriteAndMemType()`, `MatDenseGetArrayReadAndMemType()`, `MatDenseGetArrayRead()`,
2516cd3f9d89SJunchao Zhang   `MatDenseRestoreArrayRead()`, `MatDenseGetArrayWrite()`, `MatDenseRestoreArrayWrite()`, `MatSeqAIJGetCSRAndMemType()`
2517cd3f9d89SJunchao Zhang @*/
2518cd3f9d89SJunchao Zhang PetscErrorCode MatDenseGetArrayWriteAndMemType(Mat A, PetscScalar **array, PetscMemType *mtype)
2519cd3f9d89SJunchao Zhang {
2520cd3f9d89SJunchao Zhang   PetscBool isMPI;
2521cd3f9d89SJunchao Zhang 
2522cd3f9d89SJunchao Zhang   PetscFunctionBegin;
2523cd3f9d89SJunchao Zhang   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
25244f572ea9SToby Isaac   PetscAssertPointer(array, 2);
2525e865de01SJunchao 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 */
2526cd3f9d89SJunchao Zhang   PetscCall(PetscObjectBaseTypeCompare((PetscObject)A, MATMPIDENSE, &isMPI));
2527cd3f9d89SJunchao Zhang   if (isMPI) {
2528cd3f9d89SJunchao Zhang     PetscCall(MatDenseGetArrayWriteAndMemType(((Mat_MPIDense *)A->data)->A, array, mtype));
2529cd3f9d89SJunchao Zhang   } else {
2530cd3f9d89SJunchao Zhang     PetscErrorCode (*fptr)(Mat, PetscScalar **, PetscMemType *);
25313ba16761SJacob Faibussowitsch 
25323ba16761SJacob Faibussowitsch     PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatDenseGetArrayWriteAndMemType_C", &fptr));
2533cd3f9d89SJunchao Zhang     if (fptr) {
2534cd3f9d89SJunchao Zhang       PetscCall((*fptr)(A, array, mtype));
2535cd3f9d89SJunchao Zhang     } else {
2536cd3f9d89SJunchao Zhang       PetscUseMethod(A, "MatDenseGetArrayWrite_C", (Mat, PetscScalar **), (A, array));
2537cd3f9d89SJunchao Zhang       if (mtype) *mtype = PETSC_MEMTYPE_HOST;
2538cd3f9d89SJunchao Zhang     }
2539cd3f9d89SJunchao Zhang   }
25403ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2541cd3f9d89SJunchao Zhang }
2542cd3f9d89SJunchao Zhang 
2543cd3f9d89SJunchao Zhang /*@C
2544cd3f9d89SJunchao Zhang   MatDenseRestoreArrayWriteAndMemType - returns access to the array that is obtained by `MatDenseGetArrayReadAndMemType()`
2545cd3f9d89SJunchao Zhang 
2546cd3f9d89SJunchao Zhang   Logically Collective
2547cd3f9d89SJunchao Zhang 
2548cd3f9d89SJunchao Zhang   Input Parameters:
2549fe59aa6dSJacob Faibussowitsch + A     - a dense matrix
2550cd3f9d89SJunchao Zhang - array - pointer to the data
2551cd3f9d89SJunchao Zhang 
2552cd3f9d89SJunchao Zhang   Level: intermediate
2553cd3f9d89SJunchao Zhang 
25541cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATDENSE`, `MatDenseGetArrayWriteAndMemType()`, `MatDenseGetArray()`, `MatDenseGetArrayRead()`, `MatDenseRestoreArrayRead()`, `MatDenseGetArrayWrite()`, `MatDenseRestoreArrayWrite()`
2555cd3f9d89SJunchao Zhang @*/
2556cd3f9d89SJunchao Zhang PetscErrorCode MatDenseRestoreArrayWriteAndMemType(Mat A, PetscScalar **array)
2557cd3f9d89SJunchao Zhang {
2558cd3f9d89SJunchao Zhang   PetscBool isMPI;
2559cd3f9d89SJunchao Zhang 
2560cd3f9d89SJunchao Zhang   PetscFunctionBegin;
2561cd3f9d89SJunchao Zhang   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
25624f572ea9SToby Isaac   PetscAssertPointer(array, 2);
2563cd3f9d89SJunchao Zhang   PetscCall(PetscObjectBaseTypeCompare((PetscObject)A, MATMPIDENSE, &isMPI));
2564cd3f9d89SJunchao Zhang   if (isMPI) {
2565cd3f9d89SJunchao Zhang     PetscCall(MatDenseRestoreArrayWriteAndMemType(((Mat_MPIDense *)A->data)->A, array));
2566cd3f9d89SJunchao Zhang   } else {
2567cd3f9d89SJunchao Zhang     PetscErrorCode (*fptr)(Mat, PetscScalar **);
25683ba16761SJacob Faibussowitsch 
25693ba16761SJacob Faibussowitsch     PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatDenseRestoreArrayWriteAndMemType_C", &fptr));
2570cd3f9d89SJunchao Zhang     if (fptr) {
2571cd3f9d89SJunchao Zhang       PetscCall((*fptr)(A, array));
2572cd3f9d89SJunchao Zhang     } else {
2573cd3f9d89SJunchao Zhang       PetscUseMethod(A, "MatDenseRestoreArrayWrite_C", (Mat, PetscScalar **), (A, array));
2574cd3f9d89SJunchao Zhang     }
2575cd3f9d89SJunchao Zhang     *array = NULL;
2576cd3f9d89SJunchao Zhang   }
2577cd3f9d89SJunchao Zhang   PetscCall(PetscObjectStateIncrease((PetscObject)A));
25783ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2579cd3f9d89SJunchao Zhang }
2580cd3f9d89SJunchao Zhang 
2581d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatCreateSubMatrix_SeqDense(Mat A, IS isrow, IS iscol, MatReuse scall, Mat *B)
2582d71ae5a4SJacob Faibussowitsch {
2583c0bbcb79SLois Curfman McInnes   Mat_SeqDense   *mat = (Mat_SeqDense *)A->data;
2584bf5a80bcSToby Isaac   PetscInt        i, j, nrows, ncols, ldb;
25855d0c19d7SBarry Smith   const PetscInt *irow, *icol;
258687828ca2SBarry Smith   PetscScalar    *av, *bv, *v = mat->v;
25870754003eSLois Curfman McInnes   Mat             newmat;
25880754003eSLois Curfman McInnes 
25893a40ed3dSBarry Smith   PetscFunctionBegin;
25909566063dSJacob Faibussowitsch   PetscCall(ISGetIndices(isrow, &irow));
25919566063dSJacob Faibussowitsch   PetscCall(ISGetIndices(iscol, &icol));
25929566063dSJacob Faibussowitsch   PetscCall(ISGetLocalSize(isrow, &nrows));
25939566063dSJacob Faibussowitsch   PetscCall(ISGetLocalSize(iscol, &ncols));
25940754003eSLois Curfman McInnes 
2595182d2002SSatish Balay   /* Check submatrixcall */
2596182d2002SSatish Balay   if (scall == MAT_REUSE_MATRIX) {
259713f74950SBarry Smith     PetscInt n_cols, n_rows;
25989566063dSJacob Faibussowitsch     PetscCall(MatGetSize(*B, &n_rows, &n_cols));
259921a2c019SBarry Smith     if (n_rows != nrows || n_cols != ncols) {
2600f746d493SDmitry Karpeev       /* resize the result matrix to match number of requested rows/columns */
26019566063dSJacob Faibussowitsch       PetscCall(MatSetSizes(*B, nrows, ncols, nrows, ncols));
260221a2c019SBarry Smith     }
2603182d2002SSatish Balay     newmat = *B;
2604182d2002SSatish Balay   } else {
26050754003eSLois Curfman McInnes     /* Create and fill new matrix */
26069566063dSJacob Faibussowitsch     PetscCall(MatCreate(PetscObjectComm((PetscObject)A), &newmat));
26079566063dSJacob Faibussowitsch     PetscCall(MatSetSizes(newmat, nrows, ncols, nrows, ncols));
26089566063dSJacob Faibussowitsch     PetscCall(MatSetType(newmat, ((PetscObject)A)->type_name));
26099566063dSJacob Faibussowitsch     PetscCall(MatSeqDenseSetPreallocation(newmat, NULL));
2610182d2002SSatish Balay   }
2611182d2002SSatish Balay 
2612182d2002SSatish Balay   /* Now extract the data pointers and do the copy,column at a time */
26139566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArray(newmat, &bv));
26149566063dSJacob Faibussowitsch   PetscCall(MatDenseGetLDA(newmat, &ldb));
2615182d2002SSatish Balay   for (i = 0; i < ncols; i++) {
26166de62eeeSBarry Smith     av = v + mat->lda * icol[i];
2617ca15aa20SStefano Zampini     for (j = 0; j < nrows; j++) bv[j] = av[irow[j]];
2618bf5a80bcSToby Isaac     bv += ldb;
26190754003eSLois Curfman McInnes   }
26209566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArray(newmat, &bv));
2621182d2002SSatish Balay 
2622182d2002SSatish Balay   /* Assemble the matrices so that the correct flags are set */
26239566063dSJacob Faibussowitsch   PetscCall(MatAssemblyBegin(newmat, MAT_FINAL_ASSEMBLY));
26249566063dSJacob Faibussowitsch   PetscCall(MatAssemblyEnd(newmat, MAT_FINAL_ASSEMBLY));
26250754003eSLois Curfman McInnes 
26260754003eSLois Curfman McInnes   /* Free work space */
26279566063dSJacob Faibussowitsch   PetscCall(ISRestoreIndices(isrow, &irow));
26289566063dSJacob Faibussowitsch   PetscCall(ISRestoreIndices(iscol, &icol));
2629182d2002SSatish Balay   *B = newmat;
26303ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
26310754003eSLois Curfman McInnes }
26320754003eSLois Curfman McInnes 
2633d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatCreateSubMatrices_SeqDense(Mat A, PetscInt n, const IS irow[], const IS icol[], MatReuse scall, Mat *B[])
2634d71ae5a4SJacob Faibussowitsch {
263513f74950SBarry Smith   PetscInt i;
2636905e6a2fSBarry Smith 
26373a40ed3dSBarry Smith   PetscFunctionBegin;
263848a46eb9SPierre Jolivet   if (scall == MAT_INITIAL_MATRIX) PetscCall(PetscCalloc1(n, B));
2639905e6a2fSBarry Smith 
264048a46eb9SPierre Jolivet   for (i = 0; i < n; i++) PetscCall(MatCreateSubMatrix_SeqDense(A, irow[i], icol[i], scall, &(*B)[i]));
26413ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2642905e6a2fSBarry Smith }
2643905e6a2fSBarry Smith 
2644d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatAssemblyBegin_SeqDense(Mat mat, MatAssemblyType mode)
2645d71ae5a4SJacob Faibussowitsch {
2646c0aa2d19SHong Zhang   PetscFunctionBegin;
26473ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2648c0aa2d19SHong Zhang }
2649c0aa2d19SHong Zhang 
2650d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatAssemblyEnd_SeqDense(Mat mat, MatAssemblyType mode)
2651d71ae5a4SJacob Faibussowitsch {
2652c0aa2d19SHong Zhang   PetscFunctionBegin;
26533ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2654c0aa2d19SHong Zhang }
2655c0aa2d19SHong Zhang 
2656d71ae5a4SJacob Faibussowitsch PetscErrorCode MatCopy_SeqDense(Mat A, Mat B, MatStructure str)
2657d71ae5a4SJacob Faibussowitsch {
26584b0e389bSBarry Smith   Mat_SeqDense      *a = (Mat_SeqDense *)A->data, *b = (Mat_SeqDense *)B->data;
2659ca15aa20SStefano Zampini   const PetscScalar *va;
2660ca15aa20SStefano Zampini   PetscScalar       *vb;
2661d0f46423SBarry Smith   PetscInt           lda1 = a->lda, lda2 = b->lda, m = A->rmap->n, n = A->cmap->n, j;
26623a40ed3dSBarry Smith 
26633a40ed3dSBarry Smith   PetscFunctionBegin;
266433f4a19fSKris Buschelman   /* If the two matrices don't have the same copy implementation, they aren't compatible for fast copy. */
266533f4a19fSKris Buschelman   if (A->ops->copy != B->ops->copy) {
26669566063dSJacob Faibussowitsch     PetscCall(MatCopy_Basic(A, B, str));
26673ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
26683a40ed3dSBarry Smith   }
2669aed4548fSBarry Smith   PetscCheck(m == B->rmap->n && n == B->cmap->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "size(B) != size(A)");
26709566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArrayRead(A, &va));
26719566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArray(B, &vb));
2672a5ce6ee0Svictorle   if (lda1 > m || lda2 > m) {
267348a46eb9SPierre Jolivet     for (j = 0; j < n; j++) PetscCall(PetscArraycpy(vb + j * lda2, va + j * lda1, m));
2674a5ce6ee0Svictorle   } else {
26759566063dSJacob Faibussowitsch     PetscCall(PetscArraycpy(vb, va, A->rmap->n * A->cmap->n));
2676a5ce6ee0Svictorle   }
26779566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArray(B, &vb));
26789566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArrayRead(A, &va));
26799566063dSJacob Faibussowitsch   PetscCall(MatAssemblyBegin(B, MAT_FINAL_ASSEMBLY));
26809566063dSJacob Faibussowitsch   PetscCall(MatAssemblyEnd(B, MAT_FINAL_ASSEMBLY));
26813ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2682273d9f13SBarry Smith }
2683273d9f13SBarry Smith 
2684d71ae5a4SJacob Faibussowitsch PetscErrorCode MatSetUp_SeqDense(Mat A)
2685d71ae5a4SJacob Faibussowitsch {
2686273d9f13SBarry Smith   PetscFunctionBegin;
26879566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetUp(A->rmap));
26889566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetUp(A->cmap));
268948a46eb9SPierre Jolivet   if (!A->preallocated) PetscCall(MatSeqDenseSetPreallocation(A, NULL));
26903ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
26914b0e389bSBarry Smith }
26924b0e389bSBarry Smith 
2693d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatConjugate_SeqDense(Mat A)
2694d71ae5a4SJacob Faibussowitsch {
26954396437dSToby Isaac   Mat_SeqDense *mat = (Mat_SeqDense *)A->data;
269606c5243aSJose E. Roman   PetscInt      i, j;
26974396437dSToby Isaac   PetscInt      min = PetscMin(A->rmap->n, A->cmap->n);
2698ca15aa20SStefano Zampini   PetscScalar  *aa;
2699ba337c44SJed Brown 
2700ba337c44SJed Brown   PetscFunctionBegin;
27019566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArray(A, &aa));
270206c5243aSJose E. Roman   for (j = 0; j < A->cmap->n; j++) {
270306c5243aSJose E. Roman     for (i = 0; i < A->rmap->n; i++) aa[i + j * mat->lda] = PetscConj(aa[i + j * mat->lda]);
270406c5243aSJose E. Roman   }
27059566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArray(A, &aa));
27069371c9d4SSatish Balay   if (mat->tau)
27079371c9d4SSatish Balay     for (i = 0; i < min; i++) mat->tau[i] = PetscConj(mat->tau[i]);
27083ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2709ba337c44SJed Brown }
2710ba337c44SJed Brown 
2711d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatRealPart_SeqDense(Mat A)
2712d71ae5a4SJacob Faibussowitsch {
271306c5243aSJose E. Roman   Mat_SeqDense *mat = (Mat_SeqDense *)A->data;
271406c5243aSJose E. Roman   PetscInt      i, j;
2715ca15aa20SStefano Zampini   PetscScalar  *aa;
2716ba337c44SJed Brown 
2717ba337c44SJed Brown   PetscFunctionBegin;
27189566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArray(A, &aa));
271906c5243aSJose E. Roman   for (j = 0; j < A->cmap->n; j++) {
272006c5243aSJose E. Roman     for (i = 0; i < A->rmap->n; i++) aa[i + j * mat->lda] = PetscRealPart(aa[i + j * mat->lda]);
272106c5243aSJose E. Roman   }
27229566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArray(A, &aa));
27233ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2724ba337c44SJed Brown }
2725ba337c44SJed Brown 
2726d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatImaginaryPart_SeqDense(Mat A)
2727d71ae5a4SJacob Faibussowitsch {
272806c5243aSJose E. Roman   Mat_SeqDense *mat = (Mat_SeqDense *)A->data;
272906c5243aSJose E. Roman   PetscInt      i, j;
2730ca15aa20SStefano Zampini   PetscScalar  *aa;
2731ba337c44SJed Brown 
2732ba337c44SJed Brown   PetscFunctionBegin;
27339566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArray(A, &aa));
273406c5243aSJose E. Roman   for (j = 0; j < A->cmap->n; j++) {
273506c5243aSJose E. Roman     for (i = 0; i < A->rmap->n; i++) aa[i + j * mat->lda] = PetscImaginaryPart(aa[i + j * mat->lda]);
273606c5243aSJose E. Roman   }
27379566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArray(A, &aa));
27383ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2739ba337c44SJed Brown }
2740284134d9SBarry Smith 
2741d71ae5a4SJacob Faibussowitsch PetscErrorCode MatMatMultSymbolic_SeqDense_SeqDense(Mat A, Mat B, PetscReal fill, Mat C)
2742d71ae5a4SJacob Faibussowitsch {
2743d0f46423SBarry Smith   PetscInt  m = A->rmap->n, n = B->cmap->n;
274447d993e7Ssuyashtn   PetscBool cisdense = PETSC_FALSE;
2745a9fe9ddaSSatish Balay 
2746ee16a9a1SHong Zhang   PetscFunctionBegin;
27479566063dSJacob Faibussowitsch   PetscCall(MatSetSizes(C, m, n, m, n));
274847d993e7Ssuyashtn #if defined(PETSC_HAVE_CUDA)
27499566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompareAny((PetscObject)C, &cisdense, MATSEQDENSE, MATSEQDENSECUDA, ""));
275047d993e7Ssuyashtn #endif
275147d993e7Ssuyashtn #if defined(PETSC_HAVE_HIP)
275247d993e7Ssuyashtn   PetscCall(PetscObjectTypeCompareAny((PetscObject)C, &cisdense, MATSEQDENSE, MATSEQDENSEHIP, ""));
275347d993e7Ssuyashtn #endif
27547a3c3d58SStefano Zampini   if (!cisdense) {
27557a3c3d58SStefano Zampini     PetscBool flg;
27567a3c3d58SStefano Zampini 
27579566063dSJacob Faibussowitsch     PetscCall(PetscObjectTypeCompare((PetscObject)B, ((PetscObject)A)->type_name, &flg));
27589566063dSJacob Faibussowitsch     PetscCall(MatSetType(C, flg ? ((PetscObject)A)->type_name : MATDENSE));
27597a3c3d58SStefano Zampini   }
27609566063dSJacob Faibussowitsch   PetscCall(MatSetUp(C));
27613ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2762ee16a9a1SHong Zhang }
2763a9fe9ddaSSatish Balay 
2764d71ae5a4SJacob Faibussowitsch PetscErrorCode MatMatMultNumeric_SeqDense_SeqDense(Mat A, Mat B, Mat C)
2765d71ae5a4SJacob Faibussowitsch {
27666718818eSStefano Zampini   Mat_SeqDense      *a = (Mat_SeqDense *)A->data, *b = (Mat_SeqDense *)B->data, *c = (Mat_SeqDense *)C->data;
27670805154bSBarry Smith   PetscBLASInt       m, n, k;
2768ca15aa20SStefano Zampini   const PetscScalar *av, *bv;
2769ca15aa20SStefano Zampini   PetscScalar       *cv;
2770a9fe9ddaSSatish Balay   PetscScalar        _DOne = 1.0, _DZero = 0.0;
2771a9fe9ddaSSatish Balay 
2772a9fe9ddaSSatish Balay   PetscFunctionBegin;
27739566063dSJacob Faibussowitsch   PetscCall(PetscBLASIntCast(C->rmap->n, &m));
27749566063dSJacob Faibussowitsch   PetscCall(PetscBLASIntCast(C->cmap->n, &n));
27759566063dSJacob Faibussowitsch   PetscCall(PetscBLASIntCast(A->cmap->n, &k));
27763ba16761SJacob Faibussowitsch   if (!m || !n || !k) PetscFunctionReturn(PETSC_SUCCESS);
27779566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArrayRead(A, &av));
27789566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArrayRead(B, &bv));
27799566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArrayWrite(C, &cv));
2780792fecdfSBarry Smith   PetscCallBLAS("BLASgemm", BLASgemm_("N", "N", &m, &n, &k, &_DOne, av, &a->lda, bv, &b->lda, &_DZero, cv, &c->lda));
27819566063dSJacob Faibussowitsch   PetscCall(PetscLogFlops(1.0 * m * n * k + 1.0 * m * n * (k - 1)));
27829566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArrayRead(A, &av));
27839566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArrayRead(B, &bv));
27849566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArrayWrite(C, &cv));
27853ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2786a9fe9ddaSSatish Balay }
2787a9fe9ddaSSatish Balay 
2788d71ae5a4SJacob Faibussowitsch PetscErrorCode MatMatTransposeMultSymbolic_SeqDense_SeqDense(Mat A, Mat B, PetscReal fill, Mat C)
2789d71ae5a4SJacob Faibussowitsch {
279069f65d41SStefano Zampini   PetscInt  m = A->rmap->n, n = B->rmap->n;
279147d993e7Ssuyashtn   PetscBool cisdense = PETSC_FALSE;
279269f65d41SStefano Zampini 
279369f65d41SStefano Zampini   PetscFunctionBegin;
27949566063dSJacob Faibussowitsch   PetscCall(MatSetSizes(C, m, n, m, n));
279547d993e7Ssuyashtn #if defined(PETSC_HAVE_CUDA)
27969566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompareAny((PetscObject)C, &cisdense, MATSEQDENSE, MATSEQDENSECUDA, ""));
279747d993e7Ssuyashtn #endif
279847d993e7Ssuyashtn #if defined(PETSC_HAVE_HIP)
279947d993e7Ssuyashtn   PetscCall(PetscObjectTypeCompareAny((PetscObject)C, &cisdense, MATSEQDENSE, MATSEQDENSEHIP, ""));
280047d993e7Ssuyashtn #endif
28017a3c3d58SStefano Zampini   if (!cisdense) {
28027a3c3d58SStefano Zampini     PetscBool flg;
28037a3c3d58SStefano Zampini 
28049566063dSJacob Faibussowitsch     PetscCall(PetscObjectTypeCompare((PetscObject)B, ((PetscObject)A)->type_name, &flg));
28059566063dSJacob Faibussowitsch     PetscCall(MatSetType(C, flg ? ((PetscObject)A)->type_name : MATDENSE));
28067a3c3d58SStefano Zampini   }
28079566063dSJacob Faibussowitsch   PetscCall(MatSetUp(C));
28083ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
280969f65d41SStefano Zampini }
281069f65d41SStefano Zampini 
2811d71ae5a4SJacob Faibussowitsch PetscErrorCode MatMatTransposeMultNumeric_SeqDense_SeqDense(Mat A, Mat B, Mat C)
2812d71ae5a4SJacob Faibussowitsch {
281369f65d41SStefano Zampini   Mat_SeqDense      *a = (Mat_SeqDense *)A->data;
281469f65d41SStefano Zampini   Mat_SeqDense      *b = (Mat_SeqDense *)B->data;
281569f65d41SStefano Zampini   Mat_SeqDense      *c = (Mat_SeqDense *)C->data;
28166718818eSStefano Zampini   const PetscScalar *av, *bv;
28176718818eSStefano Zampini   PetscScalar       *cv;
281869f65d41SStefano Zampini   PetscBLASInt       m, n, k;
281969f65d41SStefano Zampini   PetscScalar        _DOne = 1.0, _DZero = 0.0;
282069f65d41SStefano Zampini 
282169f65d41SStefano Zampini   PetscFunctionBegin;
28229566063dSJacob Faibussowitsch   PetscCall(PetscBLASIntCast(C->rmap->n, &m));
28239566063dSJacob Faibussowitsch   PetscCall(PetscBLASIntCast(C->cmap->n, &n));
28249566063dSJacob Faibussowitsch   PetscCall(PetscBLASIntCast(A->cmap->n, &k));
28253ba16761SJacob Faibussowitsch   if (!m || !n || !k) PetscFunctionReturn(PETSC_SUCCESS);
28269566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArrayRead(A, &av));
28279566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArrayRead(B, &bv));
28289566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArrayWrite(C, &cv));
2829792fecdfSBarry Smith   PetscCallBLAS("BLASgemm", BLASgemm_("N", "T", &m, &n, &k, &_DOne, av, &a->lda, bv, &b->lda, &_DZero, cv, &c->lda));
28309566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArrayRead(A, &av));
28319566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArrayRead(B, &bv));
28329566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArrayWrite(C, &cv));
28339566063dSJacob Faibussowitsch   PetscCall(PetscLogFlops(1.0 * m * n * k + 1.0 * m * n * (k - 1)));
28343ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
283569f65d41SStefano Zampini }
283669f65d41SStefano Zampini 
2837d71ae5a4SJacob Faibussowitsch PetscErrorCode MatTransposeMatMultSymbolic_SeqDense_SeqDense(Mat A, Mat B, PetscReal fill, Mat C)
2838d71ae5a4SJacob Faibussowitsch {
2839d0f46423SBarry Smith   PetscInt  m = A->cmap->n, n = B->cmap->n;
284047d993e7Ssuyashtn   PetscBool cisdense = PETSC_FALSE;
2841a9fe9ddaSSatish Balay 
2842ee16a9a1SHong Zhang   PetscFunctionBegin;
28439566063dSJacob Faibussowitsch   PetscCall(MatSetSizes(C, m, n, m, n));
284447d993e7Ssuyashtn #if defined(PETSC_HAVE_CUDA)
28459566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompareAny((PetscObject)C, &cisdense, MATSEQDENSE, MATSEQDENSECUDA, ""));
284647d993e7Ssuyashtn #endif
284747d993e7Ssuyashtn #if defined(PETSC_HAVE_HIP)
284847d993e7Ssuyashtn   PetscCall(PetscObjectTypeCompareAny((PetscObject)C, &cisdense, MATSEQDENSE, MATSEQDENSEHIP, ""));
284947d993e7Ssuyashtn #endif
28507a3c3d58SStefano Zampini   if (!cisdense) {
28517a3c3d58SStefano Zampini     PetscBool flg;
28527a3c3d58SStefano Zampini 
28539566063dSJacob Faibussowitsch     PetscCall(PetscObjectTypeCompare((PetscObject)B, ((PetscObject)A)->type_name, &flg));
28549566063dSJacob Faibussowitsch     PetscCall(MatSetType(C, flg ? ((PetscObject)A)->type_name : MATDENSE));
28557a3c3d58SStefano Zampini   }
28569566063dSJacob Faibussowitsch   PetscCall(MatSetUp(C));
28573ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2858ee16a9a1SHong Zhang }
2859a9fe9ddaSSatish Balay 
2860d71ae5a4SJacob Faibussowitsch PetscErrorCode MatTransposeMatMultNumeric_SeqDense_SeqDense(Mat A, Mat B, Mat C)
2861d71ae5a4SJacob Faibussowitsch {
2862a9fe9ddaSSatish Balay   Mat_SeqDense      *a = (Mat_SeqDense *)A->data;
2863a9fe9ddaSSatish Balay   Mat_SeqDense      *b = (Mat_SeqDense *)B->data;
2864a9fe9ddaSSatish Balay   Mat_SeqDense      *c = (Mat_SeqDense *)C->data;
28656718818eSStefano Zampini   const PetscScalar *av, *bv;
28666718818eSStefano Zampini   PetscScalar       *cv;
28670805154bSBarry Smith   PetscBLASInt       m, n, k;
2868a9fe9ddaSSatish Balay   PetscScalar        _DOne = 1.0, _DZero = 0.0;
2869a9fe9ddaSSatish Balay 
2870a9fe9ddaSSatish Balay   PetscFunctionBegin;
28719566063dSJacob Faibussowitsch   PetscCall(PetscBLASIntCast(C->rmap->n, &m));
28729566063dSJacob Faibussowitsch   PetscCall(PetscBLASIntCast(C->cmap->n, &n));
28739566063dSJacob Faibussowitsch   PetscCall(PetscBLASIntCast(A->rmap->n, &k));
28743ba16761SJacob Faibussowitsch   if (!m || !n || !k) PetscFunctionReturn(PETSC_SUCCESS);
28759566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArrayRead(A, &av));
28769566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArrayRead(B, &bv));
28779566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArrayWrite(C, &cv));
2878792fecdfSBarry Smith   PetscCallBLAS("BLASgemm", BLASgemm_("T", "N", &m, &n, &k, &_DOne, av, &a->lda, bv, &b->lda, &_DZero, cv, &c->lda));
28799566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArrayRead(A, &av));
28809566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArrayRead(B, &bv));
28819566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArrayWrite(C, &cv));
28829566063dSJacob Faibussowitsch   PetscCall(PetscLogFlops(1.0 * m * n * k + 1.0 * m * n * (k - 1)));
28833ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2884a9fe9ddaSSatish Balay }
2885985db425SBarry Smith 
2886d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatProductSetFromOptions_SeqDense_AB(Mat C)
2887d71ae5a4SJacob Faibussowitsch {
28884222ddf1SHong Zhang   PetscFunctionBegin;
28894222ddf1SHong Zhang   C->ops->matmultsymbolic = MatMatMultSymbolic_SeqDense_SeqDense;
28904222ddf1SHong Zhang   C->ops->productsymbolic = MatProductSymbolic_AB;
28913ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
28924222ddf1SHong Zhang }
28934222ddf1SHong Zhang 
2894d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatProductSetFromOptions_SeqDense_AtB(Mat C)
2895d71ae5a4SJacob Faibussowitsch {
28964222ddf1SHong Zhang   PetscFunctionBegin;
28974222ddf1SHong Zhang   C->ops->transposematmultsymbolic = MatTransposeMatMultSymbolic_SeqDense_SeqDense;
28984222ddf1SHong Zhang   C->ops->productsymbolic          = MatProductSymbolic_AtB;
28993ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
29004222ddf1SHong Zhang }
29014222ddf1SHong Zhang 
2902d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatProductSetFromOptions_SeqDense_ABt(Mat C)
2903d71ae5a4SJacob Faibussowitsch {
29044222ddf1SHong Zhang   PetscFunctionBegin;
29054222ddf1SHong Zhang   C->ops->mattransposemultsymbolic = MatMatTransposeMultSymbolic_SeqDense_SeqDense;
29064222ddf1SHong Zhang   C->ops->productsymbolic          = MatProductSymbolic_ABt;
29073ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
29084222ddf1SHong Zhang }
29094222ddf1SHong Zhang 
2910d71ae5a4SJacob Faibussowitsch PETSC_INTERN PetscErrorCode MatProductSetFromOptions_SeqDense(Mat C)
2911d71ae5a4SJacob Faibussowitsch {
29124222ddf1SHong Zhang   Mat_Product *product = C->product;
29134222ddf1SHong Zhang 
29144222ddf1SHong Zhang   PetscFunctionBegin;
29154222ddf1SHong Zhang   switch (product->type) {
2916d71ae5a4SJacob Faibussowitsch   case MATPRODUCT_AB:
2917d71ae5a4SJacob Faibussowitsch     PetscCall(MatProductSetFromOptions_SeqDense_AB(C));
2918d71ae5a4SJacob Faibussowitsch     break;
2919d71ae5a4SJacob Faibussowitsch   case MATPRODUCT_AtB:
2920d71ae5a4SJacob Faibussowitsch     PetscCall(MatProductSetFromOptions_SeqDense_AtB(C));
2921d71ae5a4SJacob Faibussowitsch     break;
2922d71ae5a4SJacob Faibussowitsch   case MATPRODUCT_ABt:
2923d71ae5a4SJacob Faibussowitsch     PetscCall(MatProductSetFromOptions_SeqDense_ABt(C));
2924d71ae5a4SJacob Faibussowitsch     break;
2925d71ae5a4SJacob Faibussowitsch   default:
2926d71ae5a4SJacob Faibussowitsch     break;
29274222ddf1SHong Zhang   }
29283ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
29294222ddf1SHong Zhang }
29304222ddf1SHong Zhang 
2931d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatGetRowMax_SeqDense(Mat A, Vec v, PetscInt idx[])
2932d71ae5a4SJacob Faibussowitsch {
2933985db425SBarry Smith   Mat_SeqDense      *a = (Mat_SeqDense *)A->data;
2934d0f46423SBarry Smith   PetscInt           i, j, m = A->rmap->n, n = A->cmap->n, p;
2935985db425SBarry Smith   PetscScalar       *x;
2936ca15aa20SStefano Zampini   const PetscScalar *aa;
2937985db425SBarry Smith 
2938985db425SBarry Smith   PetscFunctionBegin;
293928b400f6SJacob Faibussowitsch   PetscCheck(!A->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
29409566063dSJacob Faibussowitsch   PetscCall(VecGetArray(v, &x));
29419566063dSJacob Faibussowitsch   PetscCall(VecGetLocalSize(v, &p));
29429566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArrayRead(A, &aa));
294308401ef6SPierre Jolivet   PetscCheck(p == A->rmap->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Nonconforming matrix and vector");
2944985db425SBarry Smith   for (i = 0; i < m; i++) {
29459371c9d4SSatish Balay     x[i] = aa[i];
29469371c9d4SSatish Balay     if (idx) idx[i] = 0;
2947985db425SBarry Smith     for (j = 1; j < n; j++) {
29489371c9d4SSatish Balay       if (PetscRealPart(x[i]) < PetscRealPart(aa[i + a->lda * j])) {
29499371c9d4SSatish Balay         x[i] = aa[i + a->lda * j];
29509371c9d4SSatish Balay         if (idx) idx[i] = j;
29519371c9d4SSatish Balay       }
2952985db425SBarry Smith     }
2953985db425SBarry Smith   }
29549566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArrayRead(A, &aa));
29559566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(v, &x));
29563ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2957985db425SBarry Smith }
2958985db425SBarry Smith 
2959d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatGetRowMaxAbs_SeqDense(Mat A, Vec v, PetscInt idx[])
2960d71ae5a4SJacob Faibussowitsch {
2961985db425SBarry Smith   Mat_SeqDense      *a = (Mat_SeqDense *)A->data;
2962d0f46423SBarry Smith   PetscInt           i, j, m = A->rmap->n, n = A->cmap->n, p;
2963985db425SBarry Smith   PetscScalar       *x;
2964985db425SBarry Smith   PetscReal          atmp;
2965ca15aa20SStefano Zampini   const PetscScalar *aa;
2966985db425SBarry Smith 
2967985db425SBarry Smith   PetscFunctionBegin;
296828b400f6SJacob Faibussowitsch   PetscCheck(!A->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
29699566063dSJacob Faibussowitsch   PetscCall(VecGetArray(v, &x));
29709566063dSJacob Faibussowitsch   PetscCall(VecGetLocalSize(v, &p));
29719566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArrayRead(A, &aa));
297208401ef6SPierre Jolivet   PetscCheck(p == A->rmap->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Nonconforming matrix and vector");
2973985db425SBarry Smith   for (i = 0; i < m; i++) {
29749189402eSHong Zhang     x[i] = PetscAbsScalar(aa[i]);
2975985db425SBarry Smith     for (j = 1; j < n; j++) {
2976ca15aa20SStefano Zampini       atmp = PetscAbsScalar(aa[i + a->lda * j]);
29779371c9d4SSatish Balay       if (PetscAbsScalar(x[i]) < atmp) {
29789371c9d4SSatish Balay         x[i] = atmp;
29799371c9d4SSatish Balay         if (idx) idx[i] = j;
29809371c9d4SSatish Balay       }
2981985db425SBarry Smith     }
2982985db425SBarry Smith   }
29839566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArrayRead(A, &aa));
29849566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(v, &x));
29853ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2986985db425SBarry Smith }
2987985db425SBarry Smith 
2988d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatGetRowMin_SeqDense(Mat A, Vec v, PetscInt idx[])
2989d71ae5a4SJacob Faibussowitsch {
2990985db425SBarry Smith   Mat_SeqDense      *a = (Mat_SeqDense *)A->data;
2991d0f46423SBarry Smith   PetscInt           i, j, m = A->rmap->n, n = A->cmap->n, p;
2992985db425SBarry Smith   PetscScalar       *x;
2993ca15aa20SStefano Zampini   const PetscScalar *aa;
2994985db425SBarry Smith 
2995985db425SBarry Smith   PetscFunctionBegin;
299628b400f6SJacob Faibussowitsch   PetscCheck(!A->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
29979566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArrayRead(A, &aa));
29989566063dSJacob Faibussowitsch   PetscCall(VecGetArray(v, &x));
29999566063dSJacob Faibussowitsch   PetscCall(VecGetLocalSize(v, &p));
300008401ef6SPierre Jolivet   PetscCheck(p == A->rmap->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Nonconforming matrix and vector");
3001985db425SBarry Smith   for (i = 0; i < m; i++) {
30029371c9d4SSatish Balay     x[i] = aa[i];
30039371c9d4SSatish Balay     if (idx) idx[i] = 0;
3004985db425SBarry Smith     for (j = 1; j < n; j++) {
30059371c9d4SSatish Balay       if (PetscRealPart(x[i]) > PetscRealPart(aa[i + a->lda * j])) {
30069371c9d4SSatish Balay         x[i] = aa[i + a->lda * j];
30079371c9d4SSatish Balay         if (idx) idx[i] = j;
30089371c9d4SSatish Balay       }
3009985db425SBarry Smith     }
3010985db425SBarry Smith   }
30119566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(v, &x));
30129566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArrayRead(A, &aa));
30133ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3014985db425SBarry Smith }
3015985db425SBarry Smith 
3016d71ae5a4SJacob Faibussowitsch PetscErrorCode MatGetColumnVector_SeqDense(Mat A, Vec v, PetscInt col)
3017d71ae5a4SJacob Faibussowitsch {
30188d0534beSBarry Smith   Mat_SeqDense      *a = (Mat_SeqDense *)A->data;
30198d0534beSBarry Smith   PetscScalar       *x;
3020ca15aa20SStefano Zampini   const PetscScalar *aa;
30218d0534beSBarry Smith 
30228d0534beSBarry Smith   PetscFunctionBegin;
302328b400f6SJacob Faibussowitsch   PetscCheck(!A->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
30249566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArrayRead(A, &aa));
30259566063dSJacob Faibussowitsch   PetscCall(VecGetArray(v, &x));
30269566063dSJacob Faibussowitsch   PetscCall(PetscArraycpy(x, aa + col * a->lda, A->rmap->n));
30279566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(v, &x));
30289566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArrayRead(A, &aa));
30293ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
30308d0534beSBarry Smith }
30318d0534beSBarry Smith 
3032d71ae5a4SJacob Faibussowitsch PETSC_INTERN PetscErrorCode MatGetColumnReductions_SeqDense(Mat A, PetscInt type, PetscReal *reductions)
3033d71ae5a4SJacob Faibussowitsch {
30340716a85fSBarry Smith   PetscInt           i, j, m, n;
30351683a169SBarry Smith   const PetscScalar *a;
30360716a85fSBarry Smith 
30370716a85fSBarry Smith   PetscFunctionBegin;
30389566063dSJacob Faibussowitsch   PetscCall(MatGetSize(A, &m, &n));
30399566063dSJacob Faibussowitsch   PetscCall(PetscArrayzero(reductions, n));
30409566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArrayRead(A, &a));
3041857cbf51SRichard Tran Mills   if (type == NORM_2) {
30420716a85fSBarry Smith     for (i = 0; i < n; i++) {
3043ad540459SPierre Jolivet       for (j = 0; j < m; j++) reductions[i] += PetscAbsScalar(a[j] * a[j]);
304416cd844bSPierre Jolivet       a = PetscSafePointerPlusOffset(a, m);
30450716a85fSBarry Smith     }
3046857cbf51SRichard Tran Mills   } else if (type == NORM_1) {
30470716a85fSBarry Smith     for (i = 0; i < n; i++) {
3048ad540459SPierre Jolivet       for (j = 0; j < m; j++) reductions[i] += PetscAbsScalar(a[j]);
304916cd844bSPierre Jolivet       a = PetscSafePointerPlusOffset(a, m);
30500716a85fSBarry Smith     }
3051857cbf51SRichard Tran Mills   } else if (type == NORM_INFINITY) {
30520716a85fSBarry Smith     for (i = 0; i < n; i++) {
3053ad540459SPierre Jolivet       for (j = 0; j < m; j++) reductions[i] = PetscMax(PetscAbsScalar(a[j]), reductions[i]);
305416cd844bSPierre Jolivet       a = PetscSafePointerPlusOffset(a, m);
30550716a85fSBarry Smith     }
3056857cbf51SRichard Tran Mills   } else if (type == REDUCTION_SUM_REALPART || type == REDUCTION_MEAN_REALPART) {
3057a873a8cdSSam Reynolds     for (i = 0; i < n; i++) {
3058ad540459SPierre Jolivet       for (j = 0; j < m; j++) reductions[i] += PetscRealPart(a[j]);
305916cd844bSPierre Jolivet       a = PetscSafePointerPlusOffset(a, m);
3060a873a8cdSSam Reynolds     }
3061857cbf51SRichard Tran Mills   } else if (type == REDUCTION_SUM_IMAGINARYPART || type == REDUCTION_MEAN_IMAGINARYPART) {
3062857cbf51SRichard Tran Mills     for (i = 0; i < n; i++) {
3063ad540459SPierre Jolivet       for (j = 0; j < m; j++) reductions[i] += PetscImaginaryPart(a[j]);
306416cd844bSPierre Jolivet       a = PetscSafePointerPlusOffset(a, m);
3065857cbf51SRichard Tran Mills     }
3066857cbf51SRichard Tran Mills   } else SETERRQ(PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONG, "Unknown reduction type");
30679566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArrayRead(A, &a));
3068857cbf51SRichard Tran Mills   if (type == NORM_2) {
3069a873a8cdSSam Reynolds     for (i = 0; i < n; i++) reductions[i] = PetscSqrtReal(reductions[i]);
3070857cbf51SRichard Tran Mills   } else if (type == REDUCTION_MEAN_REALPART || type == REDUCTION_MEAN_IMAGINARYPART) {
3071a873a8cdSSam Reynolds     for (i = 0; i < n; i++) reductions[i] /= m;
30720716a85fSBarry Smith   }
30733ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
30740716a85fSBarry Smith }
30750716a85fSBarry Smith 
3076d71ae5a4SJacob Faibussowitsch PetscErrorCode MatSetRandom_SeqDense(Mat x, PetscRandom rctx)
3077d71ae5a4SJacob Faibussowitsch {
307873a71a0fSBarry Smith   PetscScalar *a;
3079637a0070SStefano Zampini   PetscInt     lda, m, n, i, j;
308073a71a0fSBarry Smith 
308173a71a0fSBarry Smith   PetscFunctionBegin;
30829566063dSJacob Faibussowitsch   PetscCall(MatGetSize(x, &m, &n));
30839566063dSJacob Faibussowitsch   PetscCall(MatDenseGetLDA(x, &lda));
30843faff063SStefano Zampini   PetscCall(MatDenseGetArrayWrite(x, &a));
3085637a0070SStefano Zampini   for (j = 0; j < n; j++) {
308648a46eb9SPierre Jolivet     for (i = 0; i < m; i++) PetscCall(PetscRandomGetValue(rctx, a + j * lda + i));
308773a71a0fSBarry Smith   }
30883faff063SStefano Zampini   PetscCall(MatDenseRestoreArrayWrite(x, &a));
30893ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
309073a71a0fSBarry Smith }
309173a71a0fSBarry Smith 
3092d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatMissingDiagonal_SeqDense(Mat A, PetscBool *missing, PetscInt *d)
3093d71ae5a4SJacob Faibussowitsch {
30943b49f96aSBarry Smith   PetscFunctionBegin;
30953b49f96aSBarry Smith   *missing = PETSC_FALSE;
30963ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
30973b49f96aSBarry Smith }
309873a71a0fSBarry Smith 
3099ca15aa20SStefano Zampini /* vals is not const */
3100d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatDenseGetColumn_SeqDense(Mat A, PetscInt col, PetscScalar **vals)
3101d71ae5a4SJacob Faibussowitsch {
310286aefd0dSHong Zhang   Mat_SeqDense *a = (Mat_SeqDense *)A->data;
3103ca15aa20SStefano Zampini   PetscScalar  *v;
310486aefd0dSHong Zhang 
310586aefd0dSHong Zhang   PetscFunctionBegin;
310628b400f6SJacob Faibussowitsch   PetscCheck(!A->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
31079566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArray(A, &v));
3108ca15aa20SStefano Zampini   *vals = v + col * a->lda;
31099566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArray(A, &v));
31103ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
311186aefd0dSHong Zhang }
311286aefd0dSHong Zhang 
3113d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatDenseRestoreColumn_SeqDense(Mat A, PetscScalar **vals)
3114d71ae5a4SJacob Faibussowitsch {
311586aefd0dSHong Zhang   PetscFunctionBegin;
3116742765d3SMatthew Knepley   if (vals) *vals = NULL; /* user cannot accidentally use the array later */
31173ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
311886aefd0dSHong Zhang }
3119abc3b08eSStefano Zampini 
3120a5ae1ecdSBarry Smith static struct _MatOps MatOps_Values = {MatSetValues_SeqDense,
3121905e6a2fSBarry Smith                                        MatGetRow_SeqDense,
3122905e6a2fSBarry Smith                                        MatRestoreRow_SeqDense,
3123905e6a2fSBarry Smith                                        MatMult_SeqDense,
312497304618SKris Buschelman                                        /*  4*/ MatMultAdd_SeqDense,
31257c922b88SBarry Smith                                        MatMultTranspose_SeqDense,
31267c922b88SBarry Smith                                        MatMultTransposeAdd_SeqDense,
3127f4259b30SLisandro Dalcin                                        NULL,
3128f4259b30SLisandro Dalcin                                        NULL,
3129f4259b30SLisandro Dalcin                                        NULL,
3130f4259b30SLisandro Dalcin                                        /* 10*/ NULL,
3131905e6a2fSBarry Smith                                        MatLUFactor_SeqDense,
3132905e6a2fSBarry Smith                                        MatCholeskyFactor_SeqDense,
313341f059aeSBarry Smith                                        MatSOR_SeqDense,
3134ec8511deSBarry Smith                                        MatTranspose_SeqDense,
313597304618SKris Buschelman                                        /* 15*/ MatGetInfo_SeqDense,
3136905e6a2fSBarry Smith                                        MatEqual_SeqDense,
3137905e6a2fSBarry Smith                                        MatGetDiagonal_SeqDense,
3138905e6a2fSBarry Smith                                        MatDiagonalScale_SeqDense,
3139905e6a2fSBarry Smith                                        MatNorm_SeqDense,
3140c0aa2d19SHong Zhang                                        /* 20*/ MatAssemblyBegin_SeqDense,
3141c0aa2d19SHong Zhang                                        MatAssemblyEnd_SeqDense,
3142905e6a2fSBarry Smith                                        MatSetOption_SeqDense,
3143905e6a2fSBarry Smith                                        MatZeroEntries_SeqDense,
3144d519adbfSMatthew Knepley                                        /* 24*/ MatZeroRows_SeqDense,
3145f4259b30SLisandro Dalcin                                        NULL,
3146f4259b30SLisandro Dalcin                                        NULL,
3147f4259b30SLisandro Dalcin                                        NULL,
3148f4259b30SLisandro Dalcin                                        NULL,
31494994cf47SJed Brown                                        /* 29*/ MatSetUp_SeqDense,
3150f4259b30SLisandro Dalcin                                        NULL,
3151f4259b30SLisandro Dalcin                                        NULL,
3152f4259b30SLisandro Dalcin                                        NULL,
3153f4259b30SLisandro Dalcin                                        NULL,
3154d519adbfSMatthew Knepley                                        /* 34*/ MatDuplicate_SeqDense,
3155f4259b30SLisandro Dalcin                                        NULL,
3156f4259b30SLisandro Dalcin                                        NULL,
3157f4259b30SLisandro Dalcin                                        NULL,
3158f4259b30SLisandro Dalcin                                        NULL,
3159d519adbfSMatthew Knepley                                        /* 39*/ MatAXPY_SeqDense,
31607dae84e0SHong Zhang                                        MatCreateSubMatrices_SeqDense,
3161f4259b30SLisandro Dalcin                                        NULL,
31624b0e389bSBarry Smith                                        MatGetValues_SeqDense,
3163a5ae1ecdSBarry Smith                                        MatCopy_SeqDense,
3164d519adbfSMatthew Knepley                                        /* 44*/ MatGetRowMax_SeqDense,
3165a5ae1ecdSBarry Smith                                        MatScale_SeqDense,
31662f605a99SJose E. Roman                                        MatShift_SeqDense,
3167f4259b30SLisandro Dalcin                                        NULL,
31683f49a652SStefano Zampini                                        MatZeroRowsColumns_SeqDense,
316973a71a0fSBarry Smith                                        /* 49*/ MatSetRandom_SeqDense,
3170f4259b30SLisandro Dalcin                                        NULL,
3171f4259b30SLisandro Dalcin                                        NULL,
3172f4259b30SLisandro Dalcin                                        NULL,
3173f4259b30SLisandro Dalcin                                        NULL,
3174f4259b30SLisandro Dalcin                                        /* 54*/ NULL,
3175f4259b30SLisandro Dalcin                                        NULL,
3176f4259b30SLisandro Dalcin                                        NULL,
3177f4259b30SLisandro Dalcin                                        NULL,
3178f4259b30SLisandro Dalcin                                        NULL,
3179023c16fcSToby Isaac                                        /* 59*/ MatCreateSubMatrix_SeqDense,
3180e03a110bSBarry Smith                                        MatDestroy_SeqDense,
3181e03a110bSBarry Smith                                        MatView_SeqDense,
3182f4259b30SLisandro Dalcin                                        NULL,
3183f4259b30SLisandro Dalcin                                        NULL,
3184f4259b30SLisandro Dalcin                                        /* 64*/ NULL,
3185f4259b30SLisandro Dalcin                                        NULL,
3186f4259b30SLisandro Dalcin                                        NULL,
3187f4259b30SLisandro Dalcin                                        NULL,
3188f4259b30SLisandro Dalcin                                        NULL,
3189d519adbfSMatthew Knepley                                        /* 69*/ MatGetRowMaxAbs_SeqDense,
3190f4259b30SLisandro Dalcin                                        NULL,
3191f4259b30SLisandro Dalcin                                        NULL,
3192f4259b30SLisandro Dalcin                                        NULL,
3193f4259b30SLisandro Dalcin                                        NULL,
3194f4259b30SLisandro Dalcin                                        /* 74*/ NULL,
3195f4259b30SLisandro Dalcin                                        NULL,
3196f4259b30SLisandro Dalcin                                        NULL,
3197f4259b30SLisandro Dalcin                                        NULL,
3198f4259b30SLisandro Dalcin                                        NULL,
3199f4259b30SLisandro Dalcin                                        /* 79*/ NULL,
3200f4259b30SLisandro Dalcin                                        NULL,
3201f4259b30SLisandro Dalcin                                        NULL,
3202f4259b30SLisandro Dalcin                                        NULL,
32035bba2384SShri Abhyankar                                        /* 83*/ MatLoad_SeqDense,
3204637a0070SStefano Zampini                                        MatIsSymmetric_SeqDense,
32051cbb95d3SBarry Smith                                        MatIsHermitian_SeqDense,
3206f4259b30SLisandro Dalcin                                        NULL,
3207f4259b30SLisandro Dalcin                                        NULL,
3208f4259b30SLisandro Dalcin                                        NULL,
3209f4259b30SLisandro Dalcin                                        /* 89*/ NULL,
3210f4259b30SLisandro Dalcin                                        NULL,
3211a9fe9ddaSSatish Balay                                        MatMatMultNumeric_SeqDense_SeqDense,
3212f4259b30SLisandro Dalcin                                        NULL,
3213f4259b30SLisandro Dalcin                                        NULL,
3214f4259b30SLisandro Dalcin                                        /* 94*/ NULL,
3215f4259b30SLisandro Dalcin                                        NULL,
3216f4259b30SLisandro Dalcin                                        NULL,
321769f65d41SStefano Zampini                                        MatMatTransposeMultNumeric_SeqDense_SeqDense,
3218f4259b30SLisandro Dalcin                                        NULL,
32194222ddf1SHong Zhang                                        /* 99*/ MatProductSetFromOptions_SeqDense,
3220f4259b30SLisandro Dalcin                                        NULL,
3221f4259b30SLisandro Dalcin                                        NULL,
3222ba337c44SJed Brown                                        MatConjugate_SeqDense,
3223f4259b30SLisandro Dalcin                                        NULL,
3224f4259b30SLisandro Dalcin                                        /*104*/ NULL,
3225ba337c44SJed Brown                                        MatRealPart_SeqDense,
3226ba337c44SJed Brown                                        MatImaginaryPart_SeqDense,
3227f4259b30SLisandro Dalcin                                        NULL,
3228f4259b30SLisandro Dalcin                                        NULL,
3229f4259b30SLisandro Dalcin                                        /*109*/ NULL,
3230f4259b30SLisandro Dalcin                                        NULL,
32318d0534beSBarry Smith                                        MatGetRowMin_SeqDense,
3232aabbc4fbSShri Abhyankar                                        MatGetColumnVector_SeqDense,
32333b49f96aSBarry Smith                                        MatMissingDiagonal_SeqDense,
3234f4259b30SLisandro Dalcin                                        /*114*/ NULL,
3235f4259b30SLisandro Dalcin                                        NULL,
3236f4259b30SLisandro Dalcin                                        NULL,
3237f4259b30SLisandro Dalcin                                        NULL,
3238f4259b30SLisandro Dalcin                                        NULL,
3239f4259b30SLisandro Dalcin                                        /*119*/ NULL,
3240f4259b30SLisandro Dalcin                                        NULL,
3241459e8d23SBlanca Mellado Pinto                                        MatMultHermitianTranspose_SeqDense,
3242459e8d23SBlanca Mellado Pinto                                        MatMultHermitianTransposeAdd_SeqDense,
3243f4259b30SLisandro Dalcin                                        NULL,
3244f4259b30SLisandro Dalcin                                        /*124*/ NULL,
3245a873a8cdSSam Reynolds                                        MatGetColumnReductions_SeqDense,
3246f4259b30SLisandro Dalcin                                        NULL,
3247f4259b30SLisandro Dalcin                                        NULL,
3248f4259b30SLisandro Dalcin                                        NULL,
3249f4259b30SLisandro Dalcin                                        /*129*/ NULL,
3250f4259b30SLisandro Dalcin                                        NULL,
3251f4259b30SLisandro Dalcin                                        NULL,
325275648e8dSHong Zhang                                        MatTransposeMatMultNumeric_SeqDense_SeqDense,
3253f4259b30SLisandro Dalcin                                        NULL,
3254f4259b30SLisandro Dalcin                                        /*134*/ NULL,
3255f4259b30SLisandro Dalcin                                        NULL,
3256f4259b30SLisandro Dalcin                                        NULL,
3257f4259b30SLisandro Dalcin                                        NULL,
3258f4259b30SLisandro Dalcin                                        NULL,
3259f4259b30SLisandro Dalcin                                        /*139*/ NULL,
3260f4259b30SLisandro Dalcin                                        NULL,
3261f4259b30SLisandro Dalcin                                        NULL,
3262f4259b30SLisandro Dalcin                                        NULL,
3263f4259b30SLisandro Dalcin                                        NULL,
32644222ddf1SHong Zhang                                        MatCreateMPIMatConcatenateSeqMat_SeqDense,
3265f4259b30SLisandro Dalcin                                        /*145*/ NULL,
3266f4259b30SLisandro Dalcin                                        NULL,
326799a7f59eSMark Adams                                        NULL,
326899a7f59eSMark Adams                                        NULL,
32697fb60732SBarry Smith                                        NULL,
3270dec0b466SHong Zhang                                        /*150*/ NULL,
3271eede4a3fSMark Adams                                        NULL,
3272dec0b466SHong Zhang                                        NULL};
327390ace30eSBarry Smith 
32744b828684SBarry Smith /*@C
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 @*/
3302d71ae5a4SJacob Faibussowitsch 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 
3312273d9f13SBarry Smith /*@C
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");
3491*4186a4bbSPierre Jolivet   VecCheckAssembled(a->cvec);
34926947451fSStefano Zampini   a->vecinuse = 0;
34939566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArray(A, (PetscScalar **)&a->ptrinuse));
34949566063dSJacob Faibussowitsch   PetscCall(VecResetArray(a->cvec));
349575f6d85dSStefano Zampini   if (v) *v = NULL;
34963ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
34976947451fSStefano Zampini }
34986947451fSStefano Zampini 
3499d71ae5a4SJacob Faibussowitsch PetscErrorCode MatDenseGetColumnVecRead_SeqDense(Mat A, PetscInt col, Vec *v)
3500d71ae5a4SJacob Faibussowitsch {
35016947451fSStefano Zampini   Mat_SeqDense *a = (Mat_SeqDense *)A->data;
35026947451fSStefano Zampini 
35036947451fSStefano Zampini   PetscFunctionBegin;
350428b400f6SJacob Faibussowitsch   PetscCheck(!a->vecinuse, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Need to call MatDenseRestoreColumnVec() first");
350528b400f6SJacob Faibussowitsch   PetscCheck(!a->matinuse, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Need to call MatDenseRestoreSubMatrix() first");
3506d16ceb75SStefano Zampini   if (!a->cvec) PetscCall(MatDenseCreateColumnVec_Private(A, &a->cvec));
35076947451fSStefano Zampini   a->vecinuse = col + 1;
35089566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArrayRead(A, &a->ptrinuse));
35098e3a54c0SPierre Jolivet   PetscCall(VecPlaceArray(a->cvec, PetscSafePointerPlusOffset(a->ptrinuse, (size_t)col * (size_t)a->lda)));
35109566063dSJacob Faibussowitsch   PetscCall(VecLockReadPush(a->cvec));
35116947451fSStefano Zampini   *v = a->cvec;
35123ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
35136947451fSStefano Zampini }
35146947451fSStefano Zampini 
3515d71ae5a4SJacob Faibussowitsch PetscErrorCode MatDenseRestoreColumnVecRead_SeqDense(Mat A, PetscInt col, Vec *v)
3516d71ae5a4SJacob Faibussowitsch {
35176947451fSStefano Zampini   Mat_SeqDense *a = (Mat_SeqDense *)A->data;
35186947451fSStefano Zampini 
35196947451fSStefano Zampini   PetscFunctionBegin;
352028b400f6SJacob Faibussowitsch   PetscCheck(a->vecinuse, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Need to call MatDenseGetColumnVec() first");
352128b400f6SJacob Faibussowitsch   PetscCheck(a->cvec, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Missing internal column vector");
3522*4186a4bbSPierre Jolivet   VecCheckAssembled(a->cvec);
35236947451fSStefano Zampini   a->vecinuse = 0;
35249566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArrayRead(A, &a->ptrinuse));
35259566063dSJacob Faibussowitsch   PetscCall(VecLockReadPop(a->cvec));
35269566063dSJacob Faibussowitsch   PetscCall(VecResetArray(a->cvec));
352775f6d85dSStefano Zampini   if (v) *v = NULL;
35283ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
35296947451fSStefano Zampini }
35306947451fSStefano Zampini 
3531d71ae5a4SJacob Faibussowitsch PetscErrorCode MatDenseGetColumnVecWrite_SeqDense(Mat A, PetscInt col, Vec *v)
3532d71ae5a4SJacob Faibussowitsch {
35336947451fSStefano Zampini   Mat_SeqDense *a = (Mat_SeqDense *)A->data;
35346947451fSStefano Zampini 
35356947451fSStefano Zampini   PetscFunctionBegin;
353628b400f6SJacob Faibussowitsch   PetscCheck(!a->vecinuse, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Need to call MatDenseRestoreColumnVec() first");
353728b400f6SJacob Faibussowitsch   PetscCheck(!a->matinuse, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Need to call MatDenseRestoreSubMatrix() first");
3538d16ceb75SStefano Zampini   if (!a->cvec) PetscCall(MatDenseCreateColumnVec_Private(A, &a->cvec));
35396947451fSStefano Zampini   a->vecinuse = col + 1;
35409566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArrayWrite(A, (PetscScalar **)&a->ptrinuse));
35418e3a54c0SPierre Jolivet   PetscCall(VecPlaceArray(a->cvec, PetscSafePointerPlusOffset(a->ptrinuse, (size_t)col * (size_t)a->lda)));
35426947451fSStefano Zampini   *v = a->cvec;
35433ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
35446947451fSStefano Zampini }
35456947451fSStefano Zampini 
3546d71ae5a4SJacob Faibussowitsch PetscErrorCode MatDenseRestoreColumnVecWrite_SeqDense(Mat A, PetscInt col, Vec *v)
3547d71ae5a4SJacob Faibussowitsch {
35486947451fSStefano Zampini   Mat_SeqDense *a = (Mat_SeqDense *)A->data;
35496947451fSStefano Zampini 
35506947451fSStefano Zampini   PetscFunctionBegin;
355128b400f6SJacob Faibussowitsch   PetscCheck(a->vecinuse, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Need to call MatDenseGetColumnVec() first");
355228b400f6SJacob Faibussowitsch   PetscCheck(a->cvec, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Missing internal column vector");
3553*4186a4bbSPierre Jolivet   VecCheckAssembled(a->cvec);
35546947451fSStefano Zampini   a->vecinuse = 0;
35559566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArrayWrite(A, (PetscScalar **)&a->ptrinuse));
35569566063dSJacob Faibussowitsch   PetscCall(VecResetArray(a->cvec));
355775f6d85dSStefano Zampini   if (v) *v = NULL;
35583ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
35596947451fSStefano Zampini }
35606947451fSStefano Zampini 
3561d71ae5a4SJacob Faibussowitsch PetscErrorCode MatDenseGetSubMatrix_SeqDense(Mat A, PetscInt rbegin, PetscInt rend, PetscInt cbegin, PetscInt cend, Mat *v)
3562d71ae5a4SJacob Faibussowitsch {
35635ea7661aSPierre Jolivet   Mat_SeqDense *a = (Mat_SeqDense *)A->data;
35645ea7661aSPierre Jolivet 
35655ea7661aSPierre Jolivet   PetscFunctionBegin;
356628b400f6SJacob Faibussowitsch   PetscCheck(!a->vecinuse, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Need to call MatDenseRestoreColumnVec() first");
356728b400f6SJacob Faibussowitsch   PetscCheck(!a->matinuse, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Need to call MatDenseRestoreSubMatrix() first");
3568a2748737SPierre Jolivet   if (a->cmat && (cend - cbegin != a->cmat->cmap->N || rend - rbegin != a->cmat->rmap->N)) PetscCall(MatDestroy(&a->cmat));
35695ea7661aSPierre Jolivet   if (!a->cmat) {
35708e3a54c0SPierre 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));
35715ea7661aSPierre Jolivet   } else {
35728e3a54c0SPierre Jolivet     PetscCall(MatDensePlaceArray(a->cmat, PetscSafePointerPlusOffset(a->v, rbegin + (size_t)cbegin * a->lda)));
35735ea7661aSPierre Jolivet   }
35749566063dSJacob Faibussowitsch   PetscCall(MatDenseSetLDA(a->cmat, a->lda));
35755ea7661aSPierre Jolivet   a->matinuse = cbegin + 1;
35765ea7661aSPierre Jolivet   *v          = a->cmat;
357747d993e7Ssuyashtn #if defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
357875f6d85dSStefano Zampini   A->offloadmask = PETSC_OFFLOAD_CPU;
357975f6d85dSStefano Zampini #endif
35803ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
35815ea7661aSPierre Jolivet }
35825ea7661aSPierre Jolivet 
3583d71ae5a4SJacob Faibussowitsch PetscErrorCode MatDenseRestoreSubMatrix_SeqDense(Mat A, Mat *v)
3584d71ae5a4SJacob Faibussowitsch {
35855ea7661aSPierre Jolivet   Mat_SeqDense *a = (Mat_SeqDense *)A->data;
35865ea7661aSPierre Jolivet 
35875ea7661aSPierre Jolivet   PetscFunctionBegin;
358828b400f6SJacob Faibussowitsch   PetscCheck(a->matinuse, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Need to call MatDenseGetSubMatrix() first");
358928b400f6SJacob Faibussowitsch   PetscCheck(a->cmat, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Missing internal column matrix");
359008401ef6SPierre Jolivet   PetscCheck(*v == a->cmat, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Not the matrix obtained from MatDenseGetSubMatrix()");
35915ea7661aSPierre Jolivet   a->matinuse = 0;
35929566063dSJacob Faibussowitsch   PetscCall(MatDenseResetArray(a->cmat));
3593742765d3SMatthew Knepley   if (v) *v = NULL;
359447d993e7Ssuyashtn #if defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
35953faff063SStefano Zampini   A->offloadmask = PETSC_OFFLOAD_CPU;
35963faff063SStefano Zampini #endif
35973ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
35985ea7661aSPierre Jolivet }
35995ea7661aSPierre Jolivet 
36000bad9183SKris Buschelman /*MC
3601fafad747SKris Buschelman    MATSEQDENSE - MATSEQDENSE = "seqdense" - A matrix type to be used for sequential dense matrices.
36020bad9183SKris Buschelman 
36032ef1f0ffSBarry Smith    Options Database Key:
360411a5261eSBarry Smith . -mat_type seqdense - sets the matrix type to `MATSEQDENSE` during a call to `MatSetFromOptions()`
36050bad9183SKris Buschelman 
36060bad9183SKris Buschelman   Level: beginner
36070bad9183SKris Buschelman 
36081cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATSEQDENSE`, `MatCreateSeqDense()`
36090bad9183SKris Buschelman M*/
3610d71ae5a4SJacob Faibussowitsch PetscErrorCode MatCreate_SeqDense(Mat B)
3611d71ae5a4SJacob Faibussowitsch {
3612273d9f13SBarry Smith   Mat_SeqDense *b;
36137c334f02SBarry Smith   PetscMPIInt   size;
3614273d9f13SBarry Smith 
3615273d9f13SBarry Smith   PetscFunctionBegin;
36169566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)B), &size));
361708401ef6SPierre Jolivet   PetscCheck(size <= 1, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Comm must be of size 1");
361855659b69SBarry Smith 
36194dfa11a4SJacob Faibussowitsch   PetscCall(PetscNew(&b));
362044cd7ae7SLois Curfman McInnes   B->data   = (void *)b;
3621aea10558SJacob Faibussowitsch   B->ops[0] = MatOps_Values;
362218f449edSLois Curfman McInnes 
3623273d9f13SBarry Smith   b->roworiented = PETSC_TRUE;
36244e220ebcSLois Curfman McInnes 
36259566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatQRFactor_C", MatQRFactor_SeqDense));
36269566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatDenseGetLDA_C", MatDenseGetLDA_SeqDense));
36279566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatDenseSetLDA_C", MatDenseSetLDA_SeqDense));
36289566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatDenseGetArray_C", MatDenseGetArray_SeqDense));
36299566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatDenseRestoreArray_C", MatDenseRestoreArray_SeqDense));
36309566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatDensePlaceArray_C", MatDensePlaceArray_SeqDense));
36319566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatDenseResetArray_C", MatDenseResetArray_SeqDense));
36329566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatDenseReplaceArray_C", MatDenseReplaceArray_SeqDense));
36339566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatDenseGetArrayRead_C", MatDenseGetArray_SeqDense));
36349566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatDenseRestoreArrayRead_C", MatDenseRestoreArray_SeqDense));
36359566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatDenseGetArrayWrite_C", MatDenseGetArray_SeqDense));
36369566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatDenseRestoreArrayWrite_C", MatDenseRestoreArray_SeqDense));
36379566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatConvert_seqdense_seqaij_C", MatConvert_SeqDense_SeqAIJ));
36388baccfbdSHong Zhang #if defined(PETSC_HAVE_ELEMENTAL)
36399566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatConvert_seqdense_elemental_C", MatConvert_SeqDense_Elemental));
36408baccfbdSHong Zhang #endif
3641d24d4204SJose E. Roman #if defined(PETSC_HAVE_SCALAPACK)
36429566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatConvert_seqdense_scalapack_C", MatConvert_Dense_ScaLAPACK));
3643d24d4204SJose E. Roman #endif
36442bf066beSStefano Zampini #if defined(PETSC_HAVE_CUDA)
36459566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatConvert_seqdense_seqdensecuda_C", MatConvert_SeqDense_SeqDenseCUDA));
36469566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatProductSetFromOptions_seqdensecuda_seqdensecuda_C", MatProductSetFromOptions_SeqDense));
36479566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatProductSetFromOptions_seqdensecuda_seqdense_C", MatProductSetFromOptions_SeqDense));
36489566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatProductSetFromOptions_seqdense_seqdensecuda_C", MatProductSetFromOptions_SeqDense));
36492bf066beSStefano Zampini #endif
365047d993e7Ssuyashtn #if defined(PETSC_HAVE_HIP)
365147d993e7Ssuyashtn   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatConvert_seqdense_seqdensehip_C", MatConvert_SeqDense_SeqDenseHIP));
365247d993e7Ssuyashtn   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatProductSetFromOptions_seqdensehip_seqdensehip_C", MatProductSetFromOptions_SeqDense));
365347d993e7Ssuyashtn   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatProductSetFromOptions_seqdensehip_seqdense_C", MatProductSetFromOptions_SeqDense));
365447d993e7Ssuyashtn   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatProductSetFromOptions_seqdense_seqdensehip_C", MatProductSetFromOptions_SeqDense));
365547d993e7Ssuyashtn #endif
36569566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatSeqDenseSetPreallocation_C", MatSeqDenseSetPreallocation_SeqDense));
36579566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatProductSetFromOptions_seqaij_seqdense_C", MatProductSetFromOptions_SeqAIJ_SeqDense));
36589566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatProductSetFromOptions_seqdense_seqdense_C", MatProductSetFromOptions_SeqDense));
36599566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatProductSetFromOptions_seqbaij_seqdense_C", MatProductSetFromOptions_SeqXBAIJ_SeqDense));
36609566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatProductSetFromOptions_seqsbaij_seqdense_C", MatProductSetFromOptions_SeqXBAIJ_SeqDense));
366196e6d5c4SRichard Tran Mills 
36629566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatDenseGetColumn_C", MatDenseGetColumn_SeqDense));
36639566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatDenseRestoreColumn_C", MatDenseRestoreColumn_SeqDense));
36649566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatDenseGetColumnVec_C", MatDenseGetColumnVec_SeqDense));
36659566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatDenseRestoreColumnVec_C", MatDenseRestoreColumnVec_SeqDense));
36669566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatDenseGetColumnVecRead_C", MatDenseGetColumnVecRead_SeqDense));
36679566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatDenseRestoreColumnVecRead_C", MatDenseRestoreColumnVecRead_SeqDense));
36689566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatDenseGetColumnVecWrite_C", MatDenseGetColumnVecWrite_SeqDense));
36699566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatDenseRestoreColumnVecWrite_C", MatDenseRestoreColumnVecWrite_SeqDense));
36709566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatDenseGetSubMatrix_C", MatDenseGetSubMatrix_SeqDense));
36719566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatDenseRestoreSubMatrix_C", MatDenseRestoreSubMatrix_SeqDense));
36720be0d8bdSHansol Suh   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatMultAddColumnRange_C", MatMultAddColumnRange_SeqDense));
36730be0d8bdSHansol Suh   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatMultHermitianTransposeColumnRange_C", MatMultHermitianTransposeColumnRange_SeqDense));
36740be0d8bdSHansol Suh   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatMultHermitianTransposeAddColumnRange_C", MatMultHermitianTransposeAddColumnRange_SeqDense));
36759566063dSJacob Faibussowitsch   PetscCall(PetscObjectChangeTypeName((PetscObject)B, MATSEQDENSE));
36763ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3677289bc588SBarry Smith }
367886aefd0dSHong Zhang 
367986aefd0dSHong Zhang /*@C
368011a5261eSBarry 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.
368186aefd0dSHong Zhang 
368286aefd0dSHong Zhang   Not Collective
368386aefd0dSHong Zhang 
36845ea7661aSPierre Jolivet   Input Parameters:
3685fe59aa6dSJacob Faibussowitsch + A   - a `MATSEQDENSE` or `MATMPIDENSE` matrix
368686aefd0dSHong Zhang - col - column index
368786aefd0dSHong Zhang 
368886aefd0dSHong Zhang   Output Parameter:
368986aefd0dSHong Zhang . vals - pointer to the data
369086aefd0dSHong Zhang 
369186aefd0dSHong Zhang   Level: intermediate
369286aefd0dSHong Zhang 
369311a5261eSBarry Smith   Note:
369411a5261eSBarry Smith   Use `MatDenseGetColumnVec()` to get access to a column of a `MATDENSE` treated as a `Vec`
369511a5261eSBarry Smith 
36961cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATDENSE`, `MatDenseRestoreColumn()`, `MatDenseGetColumnVec()`
369786aefd0dSHong Zhang @*/
3698d71ae5a4SJacob Faibussowitsch PetscErrorCode MatDenseGetColumn(Mat A, PetscInt col, PetscScalar **vals)
3699d71ae5a4SJacob Faibussowitsch {
370086aefd0dSHong Zhang   PetscFunctionBegin;
3701d5ea218eSStefano Zampini   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
3702d5ea218eSStefano Zampini   PetscValidLogicalCollectiveInt(A, col, 2);
37034f572ea9SToby Isaac   PetscAssertPointer(vals, 3);
3704cac4c232SBarry Smith   PetscUseMethod(A, "MatDenseGetColumn_C", (Mat, PetscInt, PetscScalar **), (A, col, vals));
37053ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
370686aefd0dSHong Zhang }
370786aefd0dSHong Zhang 
370886aefd0dSHong Zhang /*@C
370911a5261eSBarry Smith   MatDenseRestoreColumn - returns access to a column of a `MATDENSE` matrix which is returned by `MatDenseGetColumn()`.
371086aefd0dSHong Zhang 
371186aefd0dSHong Zhang   Not Collective
371286aefd0dSHong Zhang 
3713742765d3SMatthew Knepley   Input Parameters:
3714fe59aa6dSJacob Faibussowitsch + A    - a `MATSEQDENSE` or `MATMPIDENSE` matrix
37152ef1f0ffSBarry Smith - vals - pointer to the data (may be `NULL`)
371686aefd0dSHong Zhang 
371786aefd0dSHong Zhang   Level: intermediate
371886aefd0dSHong Zhang 
37191cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATDENSE`, `MatDenseGetColumn()`
372086aefd0dSHong Zhang @*/
3721d71ae5a4SJacob Faibussowitsch PetscErrorCode MatDenseRestoreColumn(Mat A, PetscScalar **vals)
3722d71ae5a4SJacob Faibussowitsch {
372386aefd0dSHong Zhang   PetscFunctionBegin;
3724d5ea218eSStefano Zampini   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
37254f572ea9SToby Isaac   PetscAssertPointer(vals, 2);
3726cac4c232SBarry Smith   PetscUseMethod(A, "MatDenseRestoreColumn_C", (Mat, PetscScalar **), (A, vals));
37273ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
372886aefd0dSHong Zhang }
37296947451fSStefano Zampini 
37300f74d2c1SSatish Balay /*@
373111a5261eSBarry Smith   MatDenseGetColumnVec - Gives read-write access to a column of a `MATDENSE` matrix, represented as a `Vec`.
37326947451fSStefano Zampini 
37336947451fSStefano Zampini   Collective
37346947451fSStefano Zampini 
37355ea7661aSPierre Jolivet   Input Parameters:
3736fe59aa6dSJacob Faibussowitsch + A   - the `Mat` object
37376947451fSStefano Zampini - col - the column index
37386947451fSStefano Zampini 
37396947451fSStefano Zampini   Output Parameter:
37406947451fSStefano Zampini . v - the vector
37416947451fSStefano Zampini 
37422ef1f0ffSBarry Smith   Level: intermediate
37432ef1f0ffSBarry Smith 
37446947451fSStefano Zampini   Notes:
374511a5261eSBarry Smith   The vector is owned by PETSc. Users need to call `MatDenseRestoreColumnVec()` when the vector is no longer needed.
374611a5261eSBarry Smith 
374711a5261eSBarry Smith   Use `MatDenseGetColumnVecRead()` to obtain read-only access or `MatDenseGetColumnVecWrite()` for write-only access.
37486947451fSStefano Zampini 
37491cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATDENSE`, `MATDENSECUDA`, `MATDENSEHIP`, `MatDenseGetColumnVecRead()`, `MatDenseGetColumnVecWrite()`, `MatDenseRestoreColumnVec()`, `MatDenseRestoreColumnVecRead()`, `MatDenseRestoreColumnVecWrite()`, `MatDenseGetColumn()`
37506947451fSStefano Zampini @*/
3751d71ae5a4SJacob Faibussowitsch PetscErrorCode MatDenseGetColumnVec(Mat A, PetscInt col, Vec *v)
3752d71ae5a4SJacob Faibussowitsch {
37536947451fSStefano Zampini   PetscFunctionBegin;
37546947451fSStefano Zampini   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
37556947451fSStefano Zampini   PetscValidType(A, 1);
37566947451fSStefano Zampini   PetscValidLogicalCollectiveInt(A, col, 2);
37574f572ea9SToby Isaac   PetscAssertPointer(v, 3);
375828b400f6SJacob Faibussowitsch   PetscCheck(A->preallocated, PetscObjectComm((PetscObject)A), PETSC_ERR_ORDER, "Matrix not preallocated");
37592cf15c64SPierre 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);
3760cac4c232SBarry Smith   PetscUseMethod(A, "MatDenseGetColumnVec_C", (Mat, PetscInt, Vec *), (A, col, v));
37613ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
37626947451fSStefano Zampini }
37636947451fSStefano Zampini 
37640f74d2c1SSatish Balay /*@
3765fb850c59SBarry Smith   MatDenseRestoreColumnVec - Returns access to a column of a dense matrix obtained from `MatDenseGetColumnVec()`.
37666947451fSStefano Zampini 
37676947451fSStefano Zampini   Collective
37686947451fSStefano Zampini 
37695ea7661aSPierre Jolivet   Input Parameters:
3770fb850c59SBarry Smith + A   - the `Mat` object
37716947451fSStefano Zampini . col - the column index
3772fb850c59SBarry Smith - v   - the `Vec` object (may be `NULL`)
37736947451fSStefano Zampini 
37746947451fSStefano Zampini   Level: intermediate
37756947451fSStefano Zampini 
37761cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATDENSE`, `MATDENSECUDA`, `MATDENSEHIP`, `MatDenseGetColumnVec()`, `MatDenseGetColumnVecRead()`, `MatDenseGetColumnVecWrite()`, `MatDenseRestoreColumnVecRead()`, `MatDenseRestoreColumnVecWrite()`
37776947451fSStefano Zampini @*/
3778d71ae5a4SJacob Faibussowitsch PetscErrorCode MatDenseRestoreColumnVec(Mat A, PetscInt col, Vec *v)
3779d71ae5a4SJacob Faibussowitsch {
37806947451fSStefano Zampini   PetscFunctionBegin;
37816947451fSStefano Zampini   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
37826947451fSStefano Zampini   PetscValidType(A, 1);
37836947451fSStefano Zampini   PetscValidLogicalCollectiveInt(A, col, 2);
378408401ef6SPierre Jolivet   PetscCheck(A->preallocated, PetscObjectComm((PetscObject)A), PETSC_ERR_ORDER, "Matrix not preallocated");
37852cf15c64SPierre 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);
3786cac4c232SBarry Smith   PetscUseMethod(A, "MatDenseRestoreColumnVec_C", (Mat, PetscInt, Vec *), (A, col, v));
37873ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
37886947451fSStefano Zampini }
37896947451fSStefano Zampini 
37900f74d2c1SSatish Balay /*@
3791fb850c59SBarry Smith   MatDenseGetColumnVecRead - Gives read-only access to a column of a dense matrix, represented as a `Vec`.
37926947451fSStefano Zampini 
37936947451fSStefano Zampini   Collective
37946947451fSStefano Zampini 
37955ea7661aSPierre Jolivet   Input Parameters:
3796fe59aa6dSJacob Faibussowitsch + A   - the `Mat` object
37976947451fSStefano Zampini - col - the column index
37986947451fSStefano Zampini 
37996947451fSStefano Zampini   Output Parameter:
38006947451fSStefano Zampini . v - the vector
38016947451fSStefano Zampini 
38022ef1f0ffSBarry Smith   Level: intermediate
38032ef1f0ffSBarry Smith 
38046947451fSStefano Zampini   Notes:
38056947451fSStefano Zampini   The vector is owned by PETSc and users cannot modify it.
380611a5261eSBarry Smith 
38072ef1f0ffSBarry Smith   Users need to call `MatDenseRestoreColumnVecRead()` when the vector is no longer needed.
380811a5261eSBarry Smith 
38092ef1f0ffSBarry Smith   Use `MatDenseGetColumnVec()` to obtain read-write access or `MatDenseGetColumnVecWrite()` for write-only access.
38106947451fSStefano Zampini 
38111cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATDENSE`, `MATDENSECUDA`, `MATDENSEHIP`, `MatDenseGetColumnVec()`, `MatDenseGetColumnVecWrite()`, `MatDenseRestoreColumnVec()`, `MatDenseRestoreColumnVecRead()`, `MatDenseRestoreColumnVecWrite()`
38126947451fSStefano Zampini @*/
3813d71ae5a4SJacob Faibussowitsch PetscErrorCode MatDenseGetColumnVecRead(Mat A, PetscInt col, Vec *v)
3814d71ae5a4SJacob Faibussowitsch {
38156947451fSStefano Zampini   PetscFunctionBegin;
38166947451fSStefano Zampini   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
38176947451fSStefano Zampini   PetscValidType(A, 1);
38186947451fSStefano Zampini   PetscValidLogicalCollectiveInt(A, col, 2);
38194f572ea9SToby Isaac   PetscAssertPointer(v, 3);
382028b400f6SJacob Faibussowitsch   PetscCheck(A->preallocated, PetscObjectComm((PetscObject)A), PETSC_ERR_ORDER, "Matrix not preallocated");
38212cf15c64SPierre 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);
3822cac4c232SBarry Smith   PetscUseMethod(A, "MatDenseGetColumnVecRead_C", (Mat, PetscInt, Vec *), (A, col, v));
38233ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
38246947451fSStefano Zampini }
38256947451fSStefano Zampini 
38260f74d2c1SSatish Balay /*@
3827fb850c59SBarry Smith   MatDenseRestoreColumnVecRead - Returns access to a column of a dense matrix obtained from `MatDenseGetColumnVecRead()`.
38286947451fSStefano Zampini 
38296947451fSStefano Zampini   Collective
38306947451fSStefano Zampini 
38315ea7661aSPierre Jolivet   Input Parameters:
3832fe59aa6dSJacob Faibussowitsch + A   - the `Mat` object
38336947451fSStefano Zampini . col - the column index
3834fb850c59SBarry Smith - v   - the `Vec` object (may be `NULL`)
38356947451fSStefano Zampini 
38366947451fSStefano Zampini   Level: intermediate
38376947451fSStefano Zampini 
38381cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATDENSE`, `MATDENSECUDA`, `MATDENSEHIP`, `MatDenseGetColumnVec()`, `MatDenseGetColumnVecRead()`, `MatDenseGetColumnVecWrite()`, `MatDenseRestoreColumnVec()`, `MatDenseRestoreColumnVecWrite()`
38396947451fSStefano Zampini @*/
3840d71ae5a4SJacob Faibussowitsch PetscErrorCode MatDenseRestoreColumnVecRead(Mat A, PetscInt col, Vec *v)
3841d71ae5a4SJacob Faibussowitsch {
38426947451fSStefano Zampini   PetscFunctionBegin;
38436947451fSStefano Zampini   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
38446947451fSStefano Zampini   PetscValidType(A, 1);
38456947451fSStefano Zampini   PetscValidLogicalCollectiveInt(A, col, 2);
384608401ef6SPierre Jolivet   PetscCheck(A->preallocated, PetscObjectComm((PetscObject)A), PETSC_ERR_ORDER, "Matrix not preallocated");
38472cf15c64SPierre 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);
3848cac4c232SBarry Smith   PetscUseMethod(A, "MatDenseRestoreColumnVecRead_C", (Mat, PetscInt, Vec *), (A, col, v));
38493ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
38506947451fSStefano Zampini }
38516947451fSStefano Zampini 
38520f74d2c1SSatish Balay /*@
3853fb850c59SBarry Smith   MatDenseGetColumnVecWrite - Gives write-only access to a column of a dense matrix, represented as a `Vec`.
38546947451fSStefano Zampini 
38556947451fSStefano Zampini   Collective
38566947451fSStefano Zampini 
38575ea7661aSPierre Jolivet   Input Parameters:
3858fe59aa6dSJacob Faibussowitsch + A   - the `Mat` object
38596947451fSStefano Zampini - col - the column index
38606947451fSStefano Zampini 
38616947451fSStefano Zampini   Output Parameter:
38626947451fSStefano Zampini . v - the vector
38636947451fSStefano Zampini 
38646947451fSStefano Zampini   Level: intermediate
38656947451fSStefano Zampini 
38662ef1f0ffSBarry Smith   Notes:
38672ef1f0ffSBarry Smith   The vector is owned by PETSc. Users need to call `MatDenseRestoreColumnVecWrite()` when the vector is no longer needed.
38682ef1f0ffSBarry Smith 
38692ef1f0ffSBarry Smith   Use `MatDenseGetColumnVec()` to obtain read-write access or `MatDenseGetColumnVecRead()` for read-only access.
38702ef1f0ffSBarry Smith 
38711cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATDENSE`, `MATDENSECUDA`, `MATDENSEHIP`, `MatDenseGetColumnVec()`, `MatDenseGetColumnVecRead()`, `MatDenseRestoreColumnVec()`, `MatDenseRestoreColumnVecRead()`, `MatDenseRestoreColumnVecWrite()`
38726947451fSStefano Zampini @*/
3873d71ae5a4SJacob Faibussowitsch PetscErrorCode MatDenseGetColumnVecWrite(Mat A, PetscInt col, Vec *v)
3874d71ae5a4SJacob Faibussowitsch {
38756947451fSStefano Zampini   PetscFunctionBegin;
38766947451fSStefano Zampini   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
38776947451fSStefano Zampini   PetscValidType(A, 1);
38786947451fSStefano Zampini   PetscValidLogicalCollectiveInt(A, col, 2);
38794f572ea9SToby Isaac   PetscAssertPointer(v, 3);
388028b400f6SJacob Faibussowitsch   PetscCheck(A->preallocated, PetscObjectComm((PetscObject)A), PETSC_ERR_ORDER, "Matrix not preallocated");
3881aed4548fSBarry 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);
3882cac4c232SBarry Smith   PetscUseMethod(A, "MatDenseGetColumnVecWrite_C", (Mat, PetscInt, Vec *), (A, col, v));
38833ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
38846947451fSStefano Zampini }
38856947451fSStefano Zampini 
38860f74d2c1SSatish Balay /*@
3887fb850c59SBarry Smith   MatDenseRestoreColumnVecWrite - Returns access to a column of a dense matrix obtained from `MatDenseGetColumnVecWrite()`.
38886947451fSStefano Zampini 
38896947451fSStefano Zampini   Collective
38906947451fSStefano Zampini 
38915ea7661aSPierre Jolivet   Input Parameters:
3892fe59aa6dSJacob Faibussowitsch + A   - the `Mat` object
38936947451fSStefano Zampini . col - the column index
38942ef1f0ffSBarry Smith - v   - the `Vec` object (may be `NULL`)
38956947451fSStefano Zampini 
38966947451fSStefano Zampini   Level: intermediate
38976947451fSStefano Zampini 
38981cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATDENSE`, `MATDENSECUDA`, `MATDENSEHIP`, `MatDenseGetColumnVec()`, `MatDenseGetColumnVecRead()`, `MatDenseGetColumnVecWrite()`, `MatDenseRestoreColumnVec()`, `MatDenseRestoreColumnVecRead()`
38996947451fSStefano Zampini @*/
3900d71ae5a4SJacob Faibussowitsch PetscErrorCode MatDenseRestoreColumnVecWrite(Mat A, PetscInt col, Vec *v)
3901d71ae5a4SJacob Faibussowitsch {
39026947451fSStefano Zampini   PetscFunctionBegin;
39036947451fSStefano Zampini   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
39046947451fSStefano Zampini   PetscValidType(A, 1);
39056947451fSStefano Zampini   PetscValidLogicalCollectiveInt(A, col, 2);
390608401ef6SPierre Jolivet   PetscCheck(A->preallocated, PetscObjectComm((PetscObject)A), PETSC_ERR_ORDER, "Matrix not preallocated");
3907aed4548fSBarry 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);
3908cac4c232SBarry Smith   PetscUseMethod(A, "MatDenseRestoreColumnVecWrite_C", (Mat, PetscInt, Vec *), (A, col, v));
39093ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
39106947451fSStefano Zampini }
39115ea7661aSPierre Jolivet 
39120f74d2c1SSatish Balay /*@
3913fb850c59SBarry Smith   MatDenseGetSubMatrix - Gives access to a block of rows and columns of a dense matrix, represented as a `Mat`.
39145ea7661aSPierre Jolivet 
39155ea7661aSPierre Jolivet   Collective
39165ea7661aSPierre Jolivet 
39175ea7661aSPierre Jolivet   Input Parameters:
3918fb850c59SBarry Smith + A      - the `Mat` object
39192ef1f0ffSBarry Smith . rbegin - the first global row index in the block (if `PETSC_DECIDE`, is 0)
39202ef1f0ffSBarry Smith . rend   - the global row index past the last one in the block (if `PETSC_DECIDE`, is `M`)
39212ef1f0ffSBarry Smith . cbegin - the first global column index in the block (if `PETSC_DECIDE`, is 0)
39222ef1f0ffSBarry Smith - cend   - the global column index past the last one in the block (if `PETSC_DECIDE`, is `N`)
39235ea7661aSPierre Jolivet 
39245ea7661aSPierre Jolivet   Output Parameter:
39255ea7661aSPierre Jolivet . v - the matrix
39265ea7661aSPierre Jolivet 
39275ea7661aSPierre Jolivet   Level: intermediate
39285ea7661aSPierre Jolivet 
39292ef1f0ffSBarry Smith   Notes:
39302ef1f0ffSBarry Smith   The matrix is owned by PETSc. Users need to call `MatDenseRestoreSubMatrix()` when the matrix is no longer needed.
39312ef1f0ffSBarry Smith 
39322ef1f0ffSBarry 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.
39332ef1f0ffSBarry Smith 
39341cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATDENSE`, `MATDENSECUDA`, `MATDENSEHIP`, `MatDenseGetColumnVec()`, `MatDenseRestoreColumnVec()`, `MatDenseRestoreSubMatrix()`
39355ea7661aSPierre Jolivet @*/
3936d71ae5a4SJacob Faibussowitsch PetscErrorCode MatDenseGetSubMatrix(Mat A, PetscInt rbegin, PetscInt rend, PetscInt cbegin, PetscInt cend, Mat *v)
3937d71ae5a4SJacob Faibussowitsch {
39385ea7661aSPierre Jolivet   PetscFunctionBegin;
39395ea7661aSPierre Jolivet   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
39405ea7661aSPierre Jolivet   PetscValidType(A, 1);
3941a2748737SPierre Jolivet   PetscValidLogicalCollectiveInt(A, rbegin, 2);
3942a2748737SPierre Jolivet   PetscValidLogicalCollectiveInt(A, rend, 3);
3943a2748737SPierre Jolivet   PetscValidLogicalCollectiveInt(A, cbegin, 4);
3944a2748737SPierre Jolivet   PetscValidLogicalCollectiveInt(A, cend, 5);
39454f572ea9SToby Isaac   PetscAssertPointer(v, 6);
3946a2748737SPierre Jolivet   if (rbegin == PETSC_DECIDE) rbegin = 0;
3947a2748737SPierre Jolivet   if (rend == PETSC_DECIDE) rend = A->rmap->N;
3948a2748737SPierre Jolivet   if (cbegin == PETSC_DECIDE) cbegin = 0;
3949a2748737SPierre Jolivet   if (cend == PETSC_DECIDE) cend = A->cmap->N;
395028b400f6SJacob Faibussowitsch   PetscCheck(A->preallocated, PetscObjectComm((PetscObject)A), PETSC_ERR_ORDER, "Matrix not preallocated");
3951a2748737SPierre 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);
3952a2748737SPierre 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);
3953a2748737SPierre 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);
3954a2748737SPierre 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);
3955a2748737SPierre Jolivet   PetscUseMethod(A, "MatDenseGetSubMatrix_C", (Mat, PetscInt, PetscInt, PetscInt, PetscInt, Mat *), (A, rbegin, rend, cbegin, cend, v));
39563ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
39575ea7661aSPierre Jolivet }
39585ea7661aSPierre Jolivet 
39590f74d2c1SSatish Balay /*@
3960fb850c59SBarry Smith   MatDenseRestoreSubMatrix - Returns access to a block of columns of a dense matrix obtained from `MatDenseGetSubMatrix()`.
39615ea7661aSPierre Jolivet 
39625ea7661aSPierre Jolivet   Collective
39635ea7661aSPierre Jolivet 
39645ea7661aSPierre Jolivet   Input Parameters:
3965fe59aa6dSJacob Faibussowitsch + A - the `Mat` object
39662ef1f0ffSBarry Smith - v - the `Mat` object (may be `NULL`)
39675ea7661aSPierre Jolivet 
39685ea7661aSPierre Jolivet   Level: intermediate
39695ea7661aSPierre Jolivet 
39701cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATDENSE`, `MATDENSECUDA`, `MATDENSEHIP`, `MatDenseGetColumnVec()`, `MatDenseRestoreColumnVec()`, `MatDenseGetSubMatrix()`
39715ea7661aSPierre Jolivet @*/
3972d71ae5a4SJacob Faibussowitsch PetscErrorCode MatDenseRestoreSubMatrix(Mat A, Mat *v)
3973d71ae5a4SJacob Faibussowitsch {
39745ea7661aSPierre Jolivet   PetscFunctionBegin;
39755ea7661aSPierre Jolivet   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
39765ea7661aSPierre Jolivet   PetscValidType(A, 1);
39774f572ea9SToby Isaac   PetscAssertPointer(v, 2);
3978cac4c232SBarry Smith   PetscUseMethod(A, "MatDenseRestoreSubMatrix_C", (Mat, Mat *), (A, v));
39793ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
39805ea7661aSPierre Jolivet }
39818a9c020eSBarry Smith 
39828a9c020eSBarry Smith #include <petscblaslapack.h>
39838a9c020eSBarry Smith #include <petsc/private/kernels/blockinvert.h>
39848a9c020eSBarry Smith 
3985d71ae5a4SJacob Faibussowitsch PetscErrorCode MatSeqDenseInvert(Mat A)
3986d71ae5a4SJacob Faibussowitsch {
3987d63b1753SJacob Faibussowitsch   PetscInt        m;
39888a9c020eSBarry Smith   const PetscReal shift = 0.0;
3989d63b1753SJacob Faibussowitsch   PetscBool       allowzeropivot, zeropivotdetected = PETSC_FALSE;
3990d63b1753SJacob Faibussowitsch   PetscScalar    *values;
39918a9c020eSBarry Smith 
39928a9c020eSBarry Smith   PetscFunctionBegin;
3993d63b1753SJacob Faibussowitsch   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
3994d63b1753SJacob Faibussowitsch   PetscCall(MatDenseGetArray(A, &values));
3995d63b1753SJacob Faibussowitsch   PetscCall(MatGetLocalSize(A, &m, NULL));
3996d63b1753SJacob Faibussowitsch   allowzeropivot = PetscNot(A->erroriffailure);
39978a9c020eSBarry Smith   /* factor and invert each block */
3998d63b1753SJacob Faibussowitsch   switch (m) {
3999d71ae5a4SJacob Faibussowitsch   case 1:
4000d71ae5a4SJacob Faibussowitsch     values[0] = (PetscScalar)1.0 / (values[0] + shift);
4001d71ae5a4SJacob Faibussowitsch     break;
40028a9c020eSBarry Smith   case 2:
40038a9c020eSBarry Smith     PetscCall(PetscKernel_A_gets_inverse_A_2(values, shift, allowzeropivot, &zeropivotdetected));
40048a9c020eSBarry Smith     if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
40058a9c020eSBarry Smith     break;
40068a9c020eSBarry Smith   case 3:
40078a9c020eSBarry Smith     PetscCall(PetscKernel_A_gets_inverse_A_3(values, shift, allowzeropivot, &zeropivotdetected));
40088a9c020eSBarry Smith     if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
40098a9c020eSBarry Smith     break;
40108a9c020eSBarry Smith   case 4:
40118a9c020eSBarry Smith     PetscCall(PetscKernel_A_gets_inverse_A_4(values, shift, allowzeropivot, &zeropivotdetected));
40128a9c020eSBarry Smith     if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
40138a9c020eSBarry Smith     break;
40149371c9d4SSatish Balay   case 5: {
40158a9c020eSBarry Smith     PetscScalar work[25];
40168a9c020eSBarry Smith     PetscInt    ipvt[5];
40178a9c020eSBarry Smith 
40188a9c020eSBarry Smith     PetscCall(PetscKernel_A_gets_inverse_A_5(values, ipvt, work, shift, allowzeropivot, &zeropivotdetected));
40198a9c020eSBarry Smith     if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
40209371c9d4SSatish Balay   } break;
40218a9c020eSBarry Smith   case 6:
40228a9c020eSBarry Smith     PetscCall(PetscKernel_A_gets_inverse_A_6(values, shift, allowzeropivot, &zeropivotdetected));
40238a9c020eSBarry Smith     if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
40248a9c020eSBarry Smith     break;
40258a9c020eSBarry Smith   case 7:
40268a9c020eSBarry Smith     PetscCall(PetscKernel_A_gets_inverse_A_7(values, shift, allowzeropivot, &zeropivotdetected));
40278a9c020eSBarry Smith     if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
40288a9c020eSBarry Smith     break;
40299371c9d4SSatish Balay   default: {
40308a9c020eSBarry Smith     PetscInt    *v_pivots, *IJ, j;
40318a9c020eSBarry Smith     PetscScalar *v_work;
40328a9c020eSBarry Smith 
4033d63b1753SJacob Faibussowitsch     PetscCall(PetscMalloc3(m, &v_work, m, &v_pivots, m, &IJ));
4034d63b1753SJacob Faibussowitsch     for (j = 0; j < m; j++) IJ[j] = j;
4035d63b1753SJacob Faibussowitsch     PetscCall(PetscKernel_A_gets_inverse_A(m, values, v_pivots, v_work, allowzeropivot, &zeropivotdetected));
40368a9c020eSBarry Smith     if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
40378a9c020eSBarry Smith     PetscCall(PetscFree3(v_work, v_pivots, IJ));
40388a9c020eSBarry Smith   }
40398a9c020eSBarry Smith   }
4040d63b1753SJacob Faibussowitsch   PetscCall(MatDenseRestoreArray(A, &values));
40413ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
40428a9c020eSBarry Smith }
4043