xref: /petsc/src/mat/impls/dense/seq/dense.c (revision 3853def2c757d2edd67eca368879a1c0942aa1f7)
167e560aaSBarry Smith /*
267e560aaSBarry Smith      Defines the basic matrix operations for sequential dense.
347d993e7Ssuyashtn      Portions of this code are under:
447d993e7Ssuyashtn      Copyright (c) 2022 Advanced Micro Devices, Inc. All rights reserved.
567e560aaSBarry Smith */
6289bc588SBarry Smith 
7dec5eb66SMatthew G Knepley #include <../src/mat/impls/dense/seq/dense.h> /*I "petscmat.h" I*/
8cd3f9d89SJunchao Zhang #include <../src/mat/impls/dense/mpi/mpidense.h>
9c6db04a5SJed Brown #include <petscblaslapack.h>
106a63e612SBarry Smith #include <../src/mat/impls/aij/seq/aij.h>
114186a4bbSPierre Jolivet #include <petsc/private/vecimpl.h>
12b2573a8aSBarry Smith 
13d71ae5a4SJacob Faibussowitsch PetscErrorCode MatSeqDenseSymmetrize_Private(Mat A, PetscBool hermitian)
14d71ae5a4SJacob Faibussowitsch {
158c178816SStefano Zampini   Mat_SeqDense *mat = (Mat_SeqDense *)A->data;
168c178816SStefano Zampini   PetscInt      j, k, n = A->rmap->n;
17ca15aa20SStefano Zampini   PetscScalar  *v;
188c178816SStefano Zampini 
198c178816SStefano Zampini   PetscFunctionBegin;
2008401ef6SPierre Jolivet   PetscCheck(A->rmap->n == A->cmap->n, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Cannot symmetrize a rectangular matrix");
219566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArray(A, &v));
228c178816SStefano Zampini   if (!hermitian) {
238c178816SStefano Zampini     for (k = 0; k < n; k++) {
24ad540459SPierre Jolivet       for (j = k; j < n; j++) v[j * mat->lda + k] = v[k * mat->lda + j];
258c178816SStefano Zampini     }
268c178816SStefano Zampini   } else {
278c178816SStefano Zampini     for (k = 0; k < n; k++) {
28ad540459SPierre Jolivet       for (j = k; j < n; j++) v[j * mat->lda + k] = PetscConj(v[k * mat->lda + j]);
298c178816SStefano Zampini     }
308c178816SStefano Zampini   }
319566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArray(A, &v));
323ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
338c178816SStefano Zampini }
348c178816SStefano Zampini 
35ff6a9541SJacob Faibussowitsch PetscErrorCode MatSeqDenseInvertFactors_Private(Mat A)
36d71ae5a4SJacob Faibussowitsch {
378c178816SStefano Zampini   Mat_SeqDense *mat = (Mat_SeqDense *)A->data;
388c178816SStefano Zampini   PetscBLASInt  info, n;
398c178816SStefano Zampini 
408c178816SStefano Zampini   PetscFunctionBegin;
413ba16761SJacob Faibussowitsch   if (!A->rmap->n || !A->cmap->n) PetscFunctionReturn(PETSC_SUCCESS);
429566063dSJacob Faibussowitsch   PetscCall(PetscBLASIntCast(A->cmap->n, &n));
438c178816SStefano Zampini   if (A->factortype == MAT_FACTOR_LU) {
4428b400f6SJacob Faibussowitsch     PetscCheck(mat->pivots, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Pivots not present");
458c178816SStefano Zampini     if (!mat->fwork) {
468c178816SStefano Zampini       mat->lfwork = n;
479566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(mat->lfwork, &mat->fwork));
488c178816SStefano Zampini     }
499566063dSJacob Faibussowitsch     PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF));
50792fecdfSBarry Smith     PetscCallBLAS("LAPACKgetri", LAPACKgetri_(&n, mat->v, &mat->lda, mat->pivots, mat->fwork, &mat->lfwork, &info));
519566063dSJacob Faibussowitsch     PetscCall(PetscFPTrapPop());
529566063dSJacob Faibussowitsch     PetscCall(PetscLogFlops((1.0 * A->cmap->n * A->cmap->n * A->cmap->n) / 3.0));
538c178816SStefano Zampini   } else if (A->factortype == MAT_FACTOR_CHOLESKY) {
54b94d7dedSBarry Smith     if (A->spd == PETSC_BOOL3_TRUE) {
559566063dSJacob Faibussowitsch       PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF));
56792fecdfSBarry Smith       PetscCallBLAS("LAPACKpotri", LAPACKpotri_("L", &n, mat->v, &mat->lda, &info));
579566063dSJacob Faibussowitsch       PetscCall(PetscFPTrapPop());
589566063dSJacob Faibussowitsch       PetscCall(MatSeqDenseSymmetrize_Private(A, PETSC_TRUE));
598c178816SStefano Zampini #if defined(PETSC_USE_COMPLEX)
60b94d7dedSBarry Smith     } else if (A->hermitian == PETSC_BOOL3_TRUE) {
6128b400f6SJacob Faibussowitsch       PetscCheck(mat->pivots, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Pivots not present");
6228b400f6SJacob Faibussowitsch       PetscCheck(mat->fwork, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Fwork not present");
639566063dSJacob Faibussowitsch       PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF));
64792fecdfSBarry Smith       PetscCallBLAS("LAPACKhetri", LAPACKhetri_("L", &n, mat->v, &mat->lda, mat->pivots, mat->fwork, &info));
659566063dSJacob Faibussowitsch       PetscCall(PetscFPTrapPop());
669566063dSJacob Faibussowitsch       PetscCall(MatSeqDenseSymmetrize_Private(A, PETSC_TRUE));
678c178816SStefano Zampini #endif
688c178816SStefano Zampini     } else { /* symmetric case */
6928b400f6SJacob Faibussowitsch       PetscCheck(mat->pivots, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Pivots not present");
7028b400f6SJacob Faibussowitsch       PetscCheck(mat->fwork, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Fwork not present");
719566063dSJacob Faibussowitsch       PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF));
72792fecdfSBarry Smith       PetscCallBLAS("LAPACKsytri", LAPACKsytri_("L", &n, mat->v, &mat->lda, mat->pivots, mat->fwork, &info));
739566063dSJacob Faibussowitsch       PetscCall(PetscFPTrapPop());
749566063dSJacob Faibussowitsch       PetscCall(MatSeqDenseSymmetrize_Private(A, PETSC_FALSE));
758c178816SStefano Zampini     }
76835f2295SStefano Zampini     PetscCheck(!info, PETSC_COMM_SELF, PETSC_ERR_MAT_CH_ZRPVT, "Bad Inversion: zero pivot in row %" PetscBLASInt_FMT, info - 1);
779566063dSJacob Faibussowitsch     PetscCall(PetscLogFlops((1.0 * A->cmap->n * A->cmap->n * A->cmap->n) / 3.0));
788c178816SStefano Zampini   } else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Matrix must be factored to solve");
798c178816SStefano Zampini 
808c178816SStefano Zampini   A->ops->solve             = NULL;
818c178816SStefano Zampini   A->ops->matsolve          = NULL;
828c178816SStefano Zampini   A->ops->solvetranspose    = NULL;
838c178816SStefano Zampini   A->ops->matsolvetranspose = NULL;
848c178816SStefano Zampini   A->ops->solveadd          = NULL;
858c178816SStefano Zampini   A->ops->solvetransposeadd = NULL;
868c178816SStefano Zampini   A->factortype             = MAT_FACTOR_NONE;
879566063dSJacob Faibussowitsch   PetscCall(PetscFree(A->solvertype));
883ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
898c178816SStefano Zampini }
908c178816SStefano Zampini 
9166976f2fSJacob Faibussowitsch static PetscErrorCode MatZeroRowsColumns_SeqDense(Mat A, PetscInt N, const PetscInt rows[], PetscScalar diag, Vec x, Vec b)
92d71ae5a4SJacob Faibussowitsch {
933f49a652SStefano Zampini   Mat_SeqDense      *l = (Mat_SeqDense *)A->data;
943f49a652SStefano Zampini   PetscInt           m = l->lda, n = A->cmap->n, r = A->rmap->n, i, j;
95ca15aa20SStefano Zampini   PetscScalar       *slot, *bb, *v;
963f49a652SStefano Zampini   const PetscScalar *xx;
973f49a652SStefano Zampini 
983f49a652SStefano Zampini   PetscFunctionBegin;
9976bd3646SJed Brown   if (PetscDefined(USE_DEBUG)) {
1003f49a652SStefano Zampini     for (i = 0; i < N; i++) {
10108401ef6SPierre Jolivet       PetscCheck(rows[i] >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Negative row requested to be zeroed");
10208401ef6SPierre Jolivet       PetscCheck(rows[i] < A->rmap->n, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Row %" PetscInt_FMT " requested to be zeroed greater than or equal number of rows %" PetscInt_FMT, rows[i], A->rmap->n);
10308401ef6SPierre Jolivet       PetscCheck(rows[i] < A->cmap->n, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Col %" PetscInt_FMT " requested to be zeroed greater than or equal number of cols %" PetscInt_FMT, rows[i], A->cmap->n);
1043f49a652SStefano Zampini     }
10576bd3646SJed Brown   }
1063ba16761SJacob Faibussowitsch   if (!N) PetscFunctionReturn(PETSC_SUCCESS);
1073f49a652SStefano Zampini 
108dd8e379bSPierre Jolivet   /* fix right-hand side if needed */
1093f49a652SStefano Zampini   if (x && b) {
1106c4d906cSStefano Zampini     Vec xt;
1116c4d906cSStefano Zampini 
11208401ef6SPierre Jolivet     PetscCheck(A->rmap->n == A->cmap->n, PETSC_COMM_SELF, PETSC_ERR_SUP, "Only coded for square matrices");
1139566063dSJacob Faibussowitsch     PetscCall(VecDuplicate(x, &xt));
1149566063dSJacob Faibussowitsch     PetscCall(VecCopy(x, xt));
1159566063dSJacob Faibussowitsch     PetscCall(VecScale(xt, -1.0));
1169566063dSJacob Faibussowitsch     PetscCall(MatMultAdd(A, xt, b, b));
1179566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&xt));
1189566063dSJacob Faibussowitsch     PetscCall(VecGetArrayRead(x, &xx));
1199566063dSJacob Faibussowitsch     PetscCall(VecGetArray(b, &bb));
1203f49a652SStefano Zampini     for (i = 0; i < N; i++) bb[rows[i]] = diag * xx[rows[i]];
1219566063dSJacob Faibussowitsch     PetscCall(VecRestoreArrayRead(x, &xx));
1229566063dSJacob Faibussowitsch     PetscCall(VecRestoreArray(b, &bb));
1233f49a652SStefano Zampini   }
1243f49a652SStefano Zampini 
1259566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArray(A, &v));
1263f49a652SStefano Zampini   for (i = 0; i < N; i++) {
127ca15aa20SStefano Zampini     slot = v + rows[i] * m;
1289566063dSJacob Faibussowitsch     PetscCall(PetscArrayzero(slot, r));
1293f49a652SStefano Zampini   }
1303f49a652SStefano Zampini   for (i = 0; i < N; i++) {
131ca15aa20SStefano Zampini     slot = v + rows[i];
1329371c9d4SSatish Balay     for (j = 0; j < n; j++) {
1339371c9d4SSatish Balay       *slot = 0.0;
1349371c9d4SSatish Balay       slot += m;
1359371c9d4SSatish Balay     }
1363f49a652SStefano Zampini   }
1373f49a652SStefano Zampini   if (diag != 0.0) {
13808401ef6SPierre Jolivet     PetscCheck(A->rmap->n == A->cmap->n, PETSC_COMM_SELF, PETSC_ERR_SUP, "Only coded for square matrices");
1393f49a652SStefano Zampini     for (i = 0; i < N; i++) {
140ca15aa20SStefano Zampini       slot  = v + (m + 1) * rows[i];
1413f49a652SStefano Zampini       *slot = diag;
1423f49a652SStefano Zampini     }
1433f49a652SStefano Zampini   }
1449566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArray(A, &v));
1453ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1463f49a652SStefano Zampini }
1473f49a652SStefano Zampini 
148d71ae5a4SJacob Faibussowitsch PETSC_INTERN PetscErrorCode MatConvert_SeqAIJ_SeqDense(Mat A, MatType newtype, MatReuse reuse, Mat *newmat)
149d71ae5a4SJacob Faibussowitsch {
150a13144ffSStefano Zampini   Mat              B = NULL;
151b49cda9fSStefano Zampini   Mat_SeqAIJ      *a = (Mat_SeqAIJ *)A->data;
152b49cda9fSStefano Zampini   Mat_SeqDense    *b;
153b49cda9fSStefano Zampini   PetscInt        *ai = a->i, *aj = a->j, m = A->rmap->N, n = A->cmap->N, i;
1542e5835c6SStefano Zampini   const MatScalar *av;
155a13144ffSStefano Zampini   PetscBool        isseqdense;
156b49cda9fSStefano Zampini 
157b49cda9fSStefano Zampini   PetscFunctionBegin;
158a13144ffSStefano Zampini   if (reuse == MAT_REUSE_MATRIX) {
1599566063dSJacob Faibussowitsch     PetscCall(PetscObjectTypeCompare((PetscObject)*newmat, MATSEQDENSE, &isseqdense));
160f4f49eeaSPierre Jolivet     PetscCheck(isseqdense, PetscObjectComm((PetscObject)*newmat), PETSC_ERR_USER, "Cannot reuse matrix of type %s", ((PetscObject)*newmat)->type_name);
161a13144ffSStefano Zampini   }
162a13144ffSStefano Zampini   if (reuse != MAT_REUSE_MATRIX) {
1639566063dSJacob Faibussowitsch     PetscCall(MatCreate(PetscObjectComm((PetscObject)A), &B));
1649566063dSJacob Faibussowitsch     PetscCall(MatSetSizes(B, m, n, m, n));
1659566063dSJacob Faibussowitsch     PetscCall(MatSetType(B, MATSEQDENSE));
1669566063dSJacob Faibussowitsch     PetscCall(MatSeqDenseSetPreallocation(B, NULL));
167f4f49eeaSPierre Jolivet     b = (Mat_SeqDense *)B->data;
168a13144ffSStefano Zampini   } else {
169a13144ffSStefano Zampini     b = (Mat_SeqDense *)((*newmat)->data);
170e1ea5af7SJose E. Roman     for (i = 0; i < n; i++) PetscCall(PetscArrayzero(b->v + i * b->lda, m));
171a13144ffSStefano Zampini   }
1729566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJGetArrayRead(A, &av));
173b49cda9fSStefano Zampini   for (i = 0; i < m; i++) {
174b49cda9fSStefano Zampini     PetscInt j;
175b49cda9fSStefano Zampini     for (j = 0; j < ai[1] - ai[0]; j++) {
176e1ea5af7SJose E. Roman       b->v[*aj * b->lda + i] = *av;
177b49cda9fSStefano Zampini       aj++;
178b49cda9fSStefano Zampini       av++;
179b49cda9fSStefano Zampini     }
180b49cda9fSStefano Zampini     ai++;
181b49cda9fSStefano Zampini   }
1829566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJRestoreArrayRead(A, &av));
183b49cda9fSStefano Zampini 
184511c6705SHong Zhang   if (reuse == MAT_INPLACE_MATRIX) {
1859566063dSJacob Faibussowitsch     PetscCall(MatAssemblyBegin(B, MAT_FINAL_ASSEMBLY));
1869566063dSJacob Faibussowitsch     PetscCall(MatAssemblyEnd(B, MAT_FINAL_ASSEMBLY));
1879566063dSJacob Faibussowitsch     PetscCall(MatHeaderReplace(A, &B));
188b49cda9fSStefano Zampini   } else {
189a13144ffSStefano Zampini     if (B) *newmat = B;
1909566063dSJacob Faibussowitsch     PetscCall(MatAssemblyBegin(*newmat, MAT_FINAL_ASSEMBLY));
1919566063dSJacob Faibussowitsch     PetscCall(MatAssemblyEnd(*newmat, MAT_FINAL_ASSEMBLY));
192b49cda9fSStefano Zampini   }
1933ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
194b49cda9fSStefano Zampini }
195b49cda9fSStefano Zampini 
196d71ae5a4SJacob Faibussowitsch PETSC_INTERN PetscErrorCode MatConvert_SeqDense_SeqAIJ(Mat A, MatType newtype, MatReuse reuse, Mat *newmat)
197d71ae5a4SJacob Faibussowitsch {
1986d4ec7b0SPierre Jolivet   Mat           B = NULL;
1996a63e612SBarry Smith   Mat_SeqDense *a = (Mat_SeqDense *)A->data;
2009399e1b8SMatthew G. Knepley   PetscInt      i, j;
2019399e1b8SMatthew G. Knepley   PetscInt     *rows, *nnz;
2029399e1b8SMatthew G. Knepley   MatScalar    *aa = a->v, *vals;
2036a63e612SBarry Smith 
2046a63e612SBarry Smith   PetscFunctionBegin;
2059566063dSJacob Faibussowitsch   PetscCall(PetscCalloc3(A->rmap->n, &rows, A->rmap->n, &nnz, A->rmap->n, &vals));
2066d4ec7b0SPierre Jolivet   if (reuse != MAT_REUSE_MATRIX) {
2079566063dSJacob Faibussowitsch     PetscCall(MatCreate(PetscObjectComm((PetscObject)A), &B));
2089566063dSJacob Faibussowitsch     PetscCall(MatSetSizes(B, A->rmap->n, A->cmap->n, A->rmap->N, A->cmap->N));
2099566063dSJacob Faibussowitsch     PetscCall(MatSetType(B, MATSEQAIJ));
2109399e1b8SMatthew G. Knepley     for (j = 0; j < A->cmap->n; j++) {
2119371c9d4SSatish Balay       for (i = 0; i < A->rmap->n; i++)
2129371c9d4SSatish Balay         if (aa[i] != 0.0 || (i == j && A->cmap->n == A->rmap->n)) ++nnz[i];
2136a63e612SBarry Smith       aa += a->lda;
2146a63e612SBarry Smith     }
2159566063dSJacob Faibussowitsch     PetscCall(MatSeqAIJSetPreallocation(B, PETSC_DETERMINE, nnz));
2166d4ec7b0SPierre Jolivet   } else B = *newmat;
2179399e1b8SMatthew G. Knepley   aa = a->v;
2189399e1b8SMatthew G. Knepley   for (j = 0; j < A->cmap->n; j++) {
2199399e1b8SMatthew G. Knepley     PetscInt numRows = 0;
2209371c9d4SSatish Balay     for (i = 0; i < A->rmap->n; i++)
2219371c9d4SSatish Balay       if (aa[i] != 0.0 || (i == j && A->cmap->n == A->rmap->n)) {
2229371c9d4SSatish Balay         rows[numRows]   = i;
2239371c9d4SSatish Balay         vals[numRows++] = aa[i];
2249371c9d4SSatish Balay       }
2259566063dSJacob Faibussowitsch     PetscCall(MatSetValues(B, numRows, rows, 1, &j, vals, INSERT_VALUES));
2269399e1b8SMatthew G. Knepley     aa += a->lda;
2279399e1b8SMatthew G. Knepley   }
2289566063dSJacob Faibussowitsch   PetscCall(PetscFree3(rows, nnz, vals));
2299566063dSJacob Faibussowitsch   PetscCall(MatAssemblyBegin(B, MAT_FINAL_ASSEMBLY));
2309566063dSJacob Faibussowitsch   PetscCall(MatAssemblyEnd(B, MAT_FINAL_ASSEMBLY));
2316a63e612SBarry Smith 
232511c6705SHong Zhang   if (reuse == MAT_INPLACE_MATRIX) {
2339566063dSJacob Faibussowitsch     PetscCall(MatHeaderReplace(A, &B));
2346d4ec7b0SPierre Jolivet   } else if (reuse != MAT_REUSE_MATRIX) *newmat = B;
2353ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2366a63e612SBarry Smith }
2376a63e612SBarry Smith 
238d71ae5a4SJacob Faibussowitsch PetscErrorCode MatAXPY_SeqDense(Mat Y, PetscScalar alpha, Mat X, MatStructure str)
239d71ae5a4SJacob Faibussowitsch {
2401987afe7SBarry Smith   Mat_SeqDense      *x = (Mat_SeqDense *)X->data, *y = (Mat_SeqDense *)Y->data;
241ca15aa20SStefano Zampini   const PetscScalar *xv;
242ca15aa20SStefano Zampini   PetscScalar       *yv;
24323fff9afSBarry Smith   PetscBLASInt       N, m, ldax = 0, lday = 0, one = 1;
2443a40ed3dSBarry Smith 
2453a40ed3dSBarry Smith   PetscFunctionBegin;
2469566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArrayRead(X, &xv));
2479566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArray(Y, &yv));
2489566063dSJacob Faibussowitsch   PetscCall(PetscBLASIntCast(X->rmap->n * X->cmap->n, &N));
2499566063dSJacob Faibussowitsch   PetscCall(PetscBLASIntCast(X->rmap->n, &m));
2509566063dSJacob Faibussowitsch   PetscCall(PetscBLASIntCast(x->lda, &ldax));
2519566063dSJacob Faibussowitsch   PetscCall(PetscBLASIntCast(y->lda, &lday));
252a5ce6ee0Svictorle   if (ldax > m || lday > m) {
2538e3a54c0SPierre Jolivet     for (PetscInt j = 0; j < X->cmap->n; j++) PetscCallBLAS("BLASaxpy", BLASaxpy_(&m, &alpha, PetscSafePointerPlusOffset(xv, j * ldax), &one, PetscSafePointerPlusOffset(yv, j * lday), &one));
254a5ce6ee0Svictorle   } else {
255792fecdfSBarry Smith     PetscCallBLAS("BLASaxpy", BLASaxpy_(&N, &alpha, xv, &one, yv, &one));
256a5ce6ee0Svictorle   }
2579566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArrayRead(X, &xv));
2589566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArray(Y, &yv));
2599566063dSJacob Faibussowitsch   PetscCall(PetscLogFlops(PetscMax(2.0 * N - 1, 0)));
2603ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2611987afe7SBarry Smith }
2621987afe7SBarry Smith 
263d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatGetInfo_SeqDense(Mat A, MatInfoType flag, MatInfo *info)
264d71ae5a4SJacob Faibussowitsch {
265ca15aa20SStefano Zampini   PetscLogDouble N = A->rmap->n * A->cmap->n;
2663a40ed3dSBarry Smith 
2673a40ed3dSBarry Smith   PetscFunctionBegin;
2684e220ebcSLois Curfman McInnes   info->block_size        = 1.0;
269ca15aa20SStefano Zampini   info->nz_allocated      = N;
270ca15aa20SStefano Zampini   info->nz_used           = N;
271ca15aa20SStefano Zampini   info->nz_unneeded       = 0;
272ca15aa20SStefano Zampini   info->assemblies        = A->num_ass;
2734e220ebcSLois Curfman McInnes   info->mallocs           = 0;
2744dfa11a4SJacob Faibussowitsch   info->memory            = 0; /* REVIEW ME */
2754e220ebcSLois Curfman McInnes   info->fill_ratio_given  = 0;
2764e220ebcSLois Curfman McInnes   info->fill_ratio_needed = 0;
2774e220ebcSLois Curfman McInnes   info->factor_mallocs    = 0;
2783ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
279289bc588SBarry Smith }
280289bc588SBarry Smith 
281d71ae5a4SJacob Faibussowitsch PetscErrorCode MatScale_SeqDense(Mat A, PetscScalar alpha)
282d71ae5a4SJacob Faibussowitsch {
283273d9f13SBarry Smith   Mat_SeqDense *a = (Mat_SeqDense *)A->data;
284ca15aa20SStefano Zampini   PetscScalar  *v;
28523fff9afSBarry Smith   PetscBLASInt  one = 1, j, nz, lda = 0;
28680cd9d93SLois Curfman McInnes 
2873a40ed3dSBarry Smith   PetscFunctionBegin;
2889566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArray(A, &v));
2899566063dSJacob Faibussowitsch   PetscCall(PetscBLASIntCast(a->lda, &lda));
290d0f46423SBarry Smith   if (lda > A->rmap->n) {
2919566063dSJacob Faibussowitsch     PetscCall(PetscBLASIntCast(A->rmap->n, &nz));
29248a46eb9SPierre Jolivet     for (j = 0; j < A->cmap->n; j++) PetscCallBLAS("BLASscal", BLASscal_(&nz, &alpha, v + j * lda, &one));
293a5ce6ee0Svictorle   } else {
2949566063dSJacob Faibussowitsch     PetscCall(PetscBLASIntCast(A->rmap->n * A->cmap->n, &nz));
295792fecdfSBarry Smith     PetscCallBLAS("BLASscal", BLASscal_(&nz, &alpha, v, &one));
296a5ce6ee0Svictorle   }
29704cbc005SJose E. Roman   PetscCall(PetscLogFlops(A->rmap->n * A->cmap->n));
2989566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArray(A, &v));
2993ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
30080cd9d93SLois Curfman McInnes }
30180cd9d93SLois Curfman McInnes 
302d71ae5a4SJacob Faibussowitsch PetscErrorCode MatShift_SeqDense(Mat A, PetscScalar alpha)
303d71ae5a4SJacob Faibussowitsch {
3042f605a99SJose E. Roman   Mat_SeqDense *a = (Mat_SeqDense *)A->data;
3052f605a99SJose E. Roman   PetscScalar  *v;
3062f605a99SJose E. Roman   PetscInt      j, k;
3072f605a99SJose E. Roman 
3082f605a99SJose E. Roman   PetscFunctionBegin;
3092f605a99SJose E. Roman   PetscCall(MatDenseGetArray(A, &v));
3102f605a99SJose E. Roman   k = PetscMin(A->rmap->n, A->cmap->n);
3112f605a99SJose E. Roman   for (j = 0; j < k; j++) v[j + j * a->lda] += alpha;
3122f605a99SJose E. Roman   PetscCall(PetscLogFlops(k));
3132f605a99SJose E. Roman   PetscCall(MatDenseRestoreArray(A, &v));
3143ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3152f605a99SJose E. Roman }
3162f605a99SJose E. Roman 
317d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatIsHermitian_SeqDense(Mat A, PetscReal rtol, PetscBool *fl)
318d71ae5a4SJacob Faibussowitsch {
3191cbb95d3SBarry Smith   Mat_SeqDense      *a = (Mat_SeqDense *)A->data;
320ca15aa20SStefano Zampini   PetscInt           i, j, m = A->rmap->n, N = a->lda;
321ca15aa20SStefano Zampini   const PetscScalar *v;
3221cbb95d3SBarry Smith 
3231cbb95d3SBarry Smith   PetscFunctionBegin;
3241cbb95d3SBarry Smith   *fl = PETSC_FALSE;
3253ba16761SJacob Faibussowitsch   if (A->rmap->n != A->cmap->n) PetscFunctionReturn(PETSC_SUCCESS);
3269566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArrayRead(A, &v));
3271cbb95d3SBarry Smith   for (i = 0; i < m; i++) {
328ca15aa20SStefano Zampini     for (j = i; j < m; j++) {
329ad540459SPierre Jolivet       if (PetscAbsScalar(v[i + j * N] - PetscConj(v[j + i * N])) > rtol) goto restore;
3301cbb95d3SBarry Smith     }
331637a0070SStefano Zampini   }
3321cbb95d3SBarry Smith   *fl = PETSC_TRUE;
333637a0070SStefano Zampini restore:
3349566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArrayRead(A, &v));
3353ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
336637a0070SStefano Zampini }
337637a0070SStefano Zampini 
338d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatIsSymmetric_SeqDense(Mat A, PetscReal rtol, PetscBool *fl)
339d71ae5a4SJacob Faibussowitsch {
340637a0070SStefano Zampini   Mat_SeqDense      *a = (Mat_SeqDense *)A->data;
341637a0070SStefano Zampini   PetscInt           i, j, m = A->rmap->n, N = a->lda;
342637a0070SStefano Zampini   const PetscScalar *v;
343637a0070SStefano Zampini 
344637a0070SStefano Zampini   PetscFunctionBegin;
345637a0070SStefano Zampini   *fl = PETSC_FALSE;
3463ba16761SJacob Faibussowitsch   if (A->rmap->n != A->cmap->n) PetscFunctionReturn(PETSC_SUCCESS);
3479566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArrayRead(A, &v));
348637a0070SStefano Zampini   for (i = 0; i < m; i++) {
349637a0070SStefano Zampini     for (j = i; j < m; j++) {
350ad540459SPierre Jolivet       if (PetscAbsScalar(v[i + j * N] - v[j + i * N]) > rtol) goto restore;
351637a0070SStefano Zampini     }
352637a0070SStefano Zampini   }
353637a0070SStefano Zampini   *fl = PETSC_TRUE;
354637a0070SStefano Zampini restore:
3559566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArrayRead(A, &v));
3563ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3571cbb95d3SBarry Smith }
3581cbb95d3SBarry Smith 
359d71ae5a4SJacob Faibussowitsch PetscErrorCode MatDuplicateNoCreate_SeqDense(Mat newi, Mat A, MatDuplicateOption cpvalues)
360d71ae5a4SJacob Faibussowitsch {
361ca15aa20SStefano Zampini   Mat_SeqDense *mat = (Mat_SeqDense *)A->data;
362835f2295SStefano Zampini   PetscInt      lda = mat->lda, j, m, nlda = lda;
36375f6d85dSStefano Zampini   PetscBool     isdensecpu;
364b24902e0SBarry Smith 
365b24902e0SBarry Smith   PetscFunctionBegin;
3669566063dSJacob Faibussowitsch   PetscCall(PetscLayoutReference(A->rmap, &newi->rmap));
3679566063dSJacob Faibussowitsch   PetscCall(PetscLayoutReference(A->cmap, &newi->cmap));
36823fc5dcaSStefano Zampini   if (cpvalues == MAT_SHARE_NONZERO_PATTERN) { /* propagate LDA */
3699566063dSJacob Faibussowitsch     PetscCall(MatDenseSetLDA(newi, lda));
37023fc5dcaSStefano Zampini   }
3719566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)newi, MATSEQDENSE, &isdensecpu));
3729566063dSJacob Faibussowitsch   if (isdensecpu) PetscCall(MatSeqDenseSetPreallocation(newi, NULL));
373b24902e0SBarry Smith   if (cpvalues == MAT_COPY_VALUES) {
374ca15aa20SStefano Zampini     const PetscScalar *av;
375ca15aa20SStefano Zampini     PetscScalar       *v;
376ca15aa20SStefano Zampini 
3779566063dSJacob Faibussowitsch     PetscCall(MatDenseGetArrayRead(A, &av));
3789566063dSJacob Faibussowitsch     PetscCall(MatDenseGetArrayWrite(newi, &v));
3799566063dSJacob Faibussowitsch     PetscCall(MatDenseGetLDA(newi, &nlda));
380d0f46423SBarry Smith     m = A->rmap->n;
38123fc5dcaSStefano Zampini     if (lda > m || nlda > m) {
3828e3a54c0SPierre Jolivet       for (j = 0; j < A->cmap->n; j++) PetscCall(PetscArraycpy(PetscSafePointerPlusOffset(v, j * nlda), PetscSafePointerPlusOffset(av, j * lda), m));
383b24902e0SBarry Smith     } else {
3849566063dSJacob Faibussowitsch       PetscCall(PetscArraycpy(v, av, A->rmap->n * A->cmap->n));
385b24902e0SBarry Smith     }
3869566063dSJacob Faibussowitsch     PetscCall(MatDenseRestoreArrayWrite(newi, &v));
3879566063dSJacob Faibussowitsch     PetscCall(MatDenseRestoreArrayRead(A, &av));
388c956ced0SPierre Jolivet     PetscCall(MatPropagateSymmetryOptions(A, newi));
389b24902e0SBarry Smith   }
3903ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
391b24902e0SBarry Smith }
392b24902e0SBarry Smith 
393d71ae5a4SJacob Faibussowitsch PetscErrorCode MatDuplicate_SeqDense(Mat A, MatDuplicateOption cpvalues, Mat *newmat)
394d71ae5a4SJacob Faibussowitsch {
3953a40ed3dSBarry Smith   PetscFunctionBegin;
3969566063dSJacob Faibussowitsch   PetscCall(MatCreate(PetscObjectComm((PetscObject)A), newmat));
3979566063dSJacob Faibussowitsch   PetscCall(MatSetSizes(*newmat, A->rmap->n, A->cmap->n, A->rmap->n, A->cmap->n));
3989566063dSJacob Faibussowitsch   PetscCall(MatSetType(*newmat, ((PetscObject)A)->type_name));
3999566063dSJacob Faibussowitsch   PetscCall(MatDuplicateNoCreate_SeqDense(*newmat, A, cpvalues));
4003ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
401b24902e0SBarry Smith }
402b24902e0SBarry Smith 
403d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatSolve_SeqDense_Internal_LU(Mat A, PetscScalar *x, PetscBLASInt ldx, PetscBLASInt m, PetscBLASInt nrhs, PetscBLASInt k, PetscBool T)
404d71ae5a4SJacob Faibussowitsch {
405c0bbcb79SLois Curfman McInnes   Mat_SeqDense *mat = (Mat_SeqDense *)A->data;
4064396437dSToby Isaac   PetscBLASInt  info;
40767e560aaSBarry Smith 
4083a40ed3dSBarry Smith   PetscFunctionBegin;
4099566063dSJacob Faibussowitsch   PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF));
410792fecdfSBarry Smith   PetscCallBLAS("LAPACKgetrs", LAPACKgetrs_(T ? "T" : "N", &m, &nrhs, mat->v, &mat->lda, mat->pivots, x, &m, &info));
4119566063dSJacob Faibussowitsch   PetscCall(PetscFPTrapPop());
412835f2295SStefano Zampini   PetscCheck(!info, PETSC_COMM_SELF, PETSC_ERR_LIB, "GETRS - Bad solve %" PetscBLASInt_FMT, info);
4139566063dSJacob Faibussowitsch   PetscCall(PetscLogFlops(nrhs * (2.0 * m * m - m)));
4143ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4154396437dSToby Isaac }
4164396437dSToby Isaac 
417d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatSolve_SeqDense_Internal_Cholesky(Mat A, PetscScalar *x, PetscBLASInt ldx, PetscBLASInt m, PetscBLASInt nrhs, PetscBLASInt k, PetscBool T)
418d71ae5a4SJacob Faibussowitsch {
4194396437dSToby Isaac   Mat_SeqDense *mat = (Mat_SeqDense *)A->data;
4204396437dSToby Isaac   PetscBLASInt  info;
4214396437dSToby Isaac 
4224396437dSToby Isaac   PetscFunctionBegin;
423b94d7dedSBarry Smith   if (A->spd == PETSC_BOOL3_TRUE) {
4249566063dSJacob Faibussowitsch     if (PetscDefined(USE_COMPLEX) && T) PetscCall(MatConjugate_SeqDense(A));
4259566063dSJacob Faibussowitsch     PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF));
426792fecdfSBarry Smith     PetscCallBLAS("LAPACKpotrs", LAPACKpotrs_("L", &m, &nrhs, mat->v, &mat->lda, x, &m, &info));
4279566063dSJacob Faibussowitsch     PetscCall(PetscFPTrapPop());
428835f2295SStefano Zampini     PetscCheck(!info, PETSC_COMM_SELF, PETSC_ERR_LIB, "POTRS Bad solve %" PetscBLASInt_FMT, info);
4299566063dSJacob Faibussowitsch     if (PetscDefined(USE_COMPLEX) && T) PetscCall(MatConjugate_SeqDense(A));
430a49dc2a2SStefano Zampini #if defined(PETSC_USE_COMPLEX)
431b94d7dedSBarry Smith   } else if (A->hermitian == PETSC_BOOL3_TRUE) {
4329566063dSJacob Faibussowitsch     if (T) PetscCall(MatConjugate_SeqDense(A));
4339566063dSJacob Faibussowitsch     PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF));
434792fecdfSBarry Smith     PetscCallBLAS("LAPACKhetrs", LAPACKhetrs_("L", &m, &nrhs, mat->v, &mat->lda, mat->pivots, x, &m, &info));
4359566063dSJacob Faibussowitsch     PetscCall(PetscFPTrapPop());
436835f2295SStefano Zampini     PetscCheck(!info, PETSC_COMM_SELF, PETSC_ERR_LIB, "HETRS Bad solve %" PetscBLASInt_FMT, info);
4379566063dSJacob Faibussowitsch     if (T) PetscCall(MatConjugate_SeqDense(A));
438a49dc2a2SStefano Zampini #endif
439a49dc2a2SStefano Zampini   } else { /* symmetric case */
4409566063dSJacob Faibussowitsch     PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF));
441792fecdfSBarry Smith     PetscCallBLAS("LAPACKsytrs", LAPACKsytrs_("L", &m, &nrhs, mat->v, &mat->lda, mat->pivots, x, &m, &info));
4429566063dSJacob Faibussowitsch     PetscCall(PetscFPTrapPop());
443835f2295SStefano Zampini     PetscCheck(!info, PETSC_COMM_SELF, PETSC_ERR_LIB, "SYTRS Bad solve %" PetscBLASInt_FMT, info);
444a49dc2a2SStefano Zampini   }
4459566063dSJacob Faibussowitsch   PetscCall(PetscLogFlops(nrhs * (2.0 * m * m - m)));
4463ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4474396437dSToby Isaac }
44885e2c93fSHong Zhang 
449d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatSolve_SeqDense_Internal_QR(Mat A, PetscScalar *x, PetscBLASInt ldx, PetscBLASInt m, PetscBLASInt nrhs, PetscBLASInt k)
450d71ae5a4SJacob Faibussowitsch {
4514396437dSToby Isaac   Mat_SeqDense *mat = (Mat_SeqDense *)A->data;
4524396437dSToby Isaac   PetscBLASInt  info;
4534396437dSToby Isaac   char          trans;
4544396437dSToby Isaac 
4554396437dSToby Isaac   PetscFunctionBegin;
4564905a7bcSToby Isaac   if (PetscDefined(USE_COMPLEX)) {
4574905a7bcSToby Isaac     trans = 'C';
4584905a7bcSToby Isaac   } else {
4594905a7bcSToby Isaac     trans = 'T';
4604905a7bcSToby Isaac   }
4619566063dSJacob Faibussowitsch   PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF));
46205fcb23eSStefano Zampini   { /* lwork depends on the number of right-hand sides */
46305fcb23eSStefano Zampini     PetscBLASInt nlfwork, lfwork = -1;
46405fcb23eSStefano Zampini     PetscScalar  fwork;
46505fcb23eSStefano Zampini 
466792fecdfSBarry Smith     PetscCallBLAS("LAPACKormqr", LAPACKormqr_("L", &trans, &m, &nrhs, &mat->rank, mat->v, &mat->lda, mat->tau, x, &ldx, &fwork, &lfwork, &info));
46705fcb23eSStefano Zampini     nlfwork = (PetscBLASInt)PetscRealPart(fwork);
46805fcb23eSStefano Zampini     if (nlfwork > mat->lfwork) {
46905fcb23eSStefano Zampini       mat->lfwork = nlfwork;
47005fcb23eSStefano Zampini       PetscCall(PetscFree(mat->fwork));
47105fcb23eSStefano Zampini       PetscCall(PetscMalloc1(mat->lfwork, &mat->fwork));
47205fcb23eSStefano Zampini     }
47305fcb23eSStefano Zampini   }
474792fecdfSBarry Smith   PetscCallBLAS("LAPACKormqr", LAPACKormqr_("L", &trans, &m, &nrhs, &mat->rank, mat->v, &mat->lda, mat->tau, x, &ldx, mat->fwork, &mat->lfwork, &info));
4759566063dSJacob Faibussowitsch   PetscCall(PetscFPTrapPop());
476835f2295SStefano Zampini   PetscCheck(!info, PETSC_COMM_SELF, PETSC_ERR_LIB, "ORMQR - Bad orthogonal transform %" PetscBLASInt_FMT, info);
4779566063dSJacob Faibussowitsch   PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF));
478792fecdfSBarry Smith   PetscCallBLAS("LAPACKtrtrs", LAPACKtrtrs_("U", "N", "N", &mat->rank, &nrhs, mat->v, &mat->lda, x, &ldx, &info));
4799566063dSJacob Faibussowitsch   PetscCall(PetscFPTrapPop());
480835f2295SStefano Zampini   PetscCheck(!info, PETSC_COMM_SELF, PETSC_ERR_LIB, "TRTRS - Bad triangular solve %" PetscBLASInt_FMT, info);
4814905a7bcSToby Isaac   for (PetscInt j = 0; j < nrhs; j++) {
482ad540459SPierre Jolivet     for (PetscInt i = mat->rank; i < k; i++) x[j * ldx + i] = 0.;
4834905a7bcSToby Isaac   }
4849566063dSJacob Faibussowitsch   PetscCall(PetscLogFlops(nrhs * (4.0 * m * mat->rank - PetscSqr(mat->rank))));
4853ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4864905a7bcSToby Isaac }
4874905a7bcSToby Isaac 
488d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatSolveTranspose_SeqDense_Internal_QR(Mat A, PetscScalar *x, PetscBLASInt ldx, PetscBLASInt m, PetscBLASInt nrhs, PetscBLASInt k)
489d71ae5a4SJacob Faibussowitsch {
4904396437dSToby Isaac   Mat_SeqDense *mat = (Mat_SeqDense *)A->data;
4914396437dSToby Isaac   PetscBLASInt  info;
4924396437dSToby Isaac 
4934396437dSToby Isaac   PetscFunctionBegin;
4944396437dSToby Isaac   if (A->rmap->n == A->cmap->n && mat->rank == A->rmap->n) {
4959566063dSJacob Faibussowitsch     PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF));
496792fecdfSBarry Smith     PetscCallBLAS("LAPACKtrtrs", LAPACKtrtrs_("U", "T", "N", &m, &nrhs, mat->v, &mat->lda, x, &ldx, &info));
4979566063dSJacob Faibussowitsch     PetscCall(PetscFPTrapPop());
498835f2295SStefano Zampini     PetscCheck(!info, PETSC_COMM_SELF, PETSC_ERR_LIB, "TRTRS - Bad triangular solve %" PetscBLASInt_FMT, info);
4999566063dSJacob Faibussowitsch     if (PetscDefined(USE_COMPLEX)) PetscCall(MatConjugate_SeqDense(A));
50005fcb23eSStefano Zampini     { /* lwork depends on the number of right-hand sides */
50105fcb23eSStefano Zampini       PetscBLASInt nlfwork, lfwork = -1;
50205fcb23eSStefano Zampini       PetscScalar  fwork;
50305fcb23eSStefano Zampini 
504792fecdfSBarry Smith       PetscCallBLAS("LAPACKormqr", LAPACKormqr_("L", "N", &m, &nrhs, &mat->rank, mat->v, &mat->lda, mat->tau, x, &ldx, &fwork, &lfwork, &info));
50505fcb23eSStefano Zampini       nlfwork = (PetscBLASInt)PetscRealPart(fwork);
50605fcb23eSStefano Zampini       if (nlfwork > mat->lfwork) {
50705fcb23eSStefano Zampini         mat->lfwork = nlfwork;
50805fcb23eSStefano Zampini         PetscCall(PetscFree(mat->fwork));
50905fcb23eSStefano Zampini         PetscCall(PetscMalloc1(mat->lfwork, &mat->fwork));
51005fcb23eSStefano Zampini       }
51105fcb23eSStefano Zampini     }
5129566063dSJacob Faibussowitsch     PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF));
513792fecdfSBarry Smith     PetscCallBLAS("LAPACKormqr", LAPACKormqr_("L", "N", &m, &nrhs, &mat->rank, mat->v, &mat->lda, mat->tau, x, &ldx, mat->fwork, &mat->lfwork, &info));
5149566063dSJacob Faibussowitsch     PetscCall(PetscFPTrapPop());
515835f2295SStefano Zampini     PetscCheck(!info, PETSC_COMM_SELF, PETSC_ERR_LIB, "ORMQR - Bad orthogonal transform %" PetscBLASInt_FMT, info);
5169566063dSJacob Faibussowitsch     if (PetscDefined(USE_COMPLEX)) PetscCall(MatConjugate_SeqDense(A));
5174396437dSToby Isaac   } else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "QR factored matrix cannot be used for transpose solve");
5189566063dSJacob Faibussowitsch   PetscCall(PetscLogFlops(nrhs * (4.0 * m * mat->rank - PetscSqr(mat->rank))));
5193ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5204396437dSToby Isaac }
5214396437dSToby Isaac 
522d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatSolve_SeqDense_SetUp(Mat A, Vec xx, Vec yy, PetscScalar **_y, PetscBLASInt *_m, PetscBLASInt *_k)
523d71ae5a4SJacob Faibussowitsch {
5244396437dSToby Isaac   Mat_SeqDense *mat = (Mat_SeqDense *)A->data;
5254905a7bcSToby Isaac   PetscScalar  *y;
5264905a7bcSToby Isaac   PetscBLASInt  m = 0, k = 0;
5274905a7bcSToby Isaac 
5284905a7bcSToby Isaac   PetscFunctionBegin;
5299566063dSJacob Faibussowitsch   PetscCall(PetscBLASIntCast(A->rmap->n, &m));
5309566063dSJacob Faibussowitsch   PetscCall(PetscBLASIntCast(A->cmap->n, &k));
5314905a7bcSToby Isaac   if (k < m) {
5329566063dSJacob Faibussowitsch     PetscCall(VecCopy(xx, mat->qrrhs));
5339566063dSJacob Faibussowitsch     PetscCall(VecGetArray(mat->qrrhs, &y));
5344905a7bcSToby Isaac   } else {
5359566063dSJacob Faibussowitsch     PetscCall(VecCopy(xx, yy));
5369566063dSJacob Faibussowitsch     PetscCall(VecGetArray(yy, &y));
5374905a7bcSToby Isaac   }
5384396437dSToby Isaac   *_y = y;
5394396437dSToby Isaac   *_k = k;
5404396437dSToby Isaac   *_m = m;
5413ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5424396437dSToby Isaac }
5434396437dSToby Isaac 
544d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatSolve_SeqDense_TearDown(Mat A, Vec xx, Vec yy, PetscScalar **_y, PetscBLASInt *_m, PetscBLASInt *_k)
545d71ae5a4SJacob Faibussowitsch {
5464396437dSToby Isaac   Mat_SeqDense *mat = (Mat_SeqDense *)A->data;
54742e9364cSSatish Balay   PetscScalar  *y   = NULL;
5484396437dSToby Isaac   PetscBLASInt  m, k;
5494396437dSToby Isaac 
5504396437dSToby Isaac   PetscFunctionBegin;
5514396437dSToby Isaac   y   = *_y;
5524396437dSToby Isaac   *_y = NULL;
5534396437dSToby Isaac   k   = *_k;
5544396437dSToby Isaac   m   = *_m;
5554905a7bcSToby Isaac   if (k < m) {
5564905a7bcSToby Isaac     PetscScalar *yv;
5579566063dSJacob Faibussowitsch     PetscCall(VecGetArray(yy, &yv));
5589566063dSJacob Faibussowitsch     PetscCall(PetscArraycpy(yv, y, k));
5599566063dSJacob Faibussowitsch     PetscCall(VecRestoreArray(yy, &yv));
5609566063dSJacob Faibussowitsch     PetscCall(VecRestoreArray(mat->qrrhs, &y));
5614905a7bcSToby Isaac   } else {
5629566063dSJacob Faibussowitsch     PetscCall(VecRestoreArray(yy, &y));
5634905a7bcSToby Isaac   }
5643ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5654905a7bcSToby Isaac }
5664905a7bcSToby Isaac 
567d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatSolve_SeqDense_LU(Mat A, Vec xx, Vec yy)
568d71ae5a4SJacob Faibussowitsch {
56942e9364cSSatish Balay   PetscScalar *y = NULL;
57042e9364cSSatish Balay   PetscBLASInt m = 0, k = 0;
5714396437dSToby Isaac 
5724396437dSToby Isaac   PetscFunctionBegin;
5739566063dSJacob Faibussowitsch   PetscCall(MatSolve_SeqDense_SetUp(A, xx, yy, &y, &m, &k));
5749566063dSJacob Faibussowitsch   PetscCall(MatSolve_SeqDense_Internal_LU(A, y, m, m, 1, k, PETSC_FALSE));
5759566063dSJacob Faibussowitsch   PetscCall(MatSolve_SeqDense_TearDown(A, xx, yy, &y, &m, &k));
5763ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5774396437dSToby Isaac }
5784396437dSToby Isaac 
579d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatSolveTranspose_SeqDense_LU(Mat A, Vec xx, Vec yy)
580d71ae5a4SJacob Faibussowitsch {
58142e9364cSSatish Balay   PetscScalar *y = NULL;
58242e9364cSSatish Balay   PetscBLASInt m = 0, k = 0;
5834396437dSToby Isaac 
5844396437dSToby Isaac   PetscFunctionBegin;
5859566063dSJacob Faibussowitsch   PetscCall(MatSolve_SeqDense_SetUp(A, xx, yy, &y, &m, &k));
5869566063dSJacob Faibussowitsch   PetscCall(MatSolve_SeqDense_Internal_LU(A, y, m, m, 1, k, PETSC_TRUE));
5879566063dSJacob Faibussowitsch   PetscCall(MatSolve_SeqDense_TearDown(A, xx, yy, &y, &m, &k));
5883ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5894396437dSToby Isaac }
5904396437dSToby Isaac 
591d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatSolve_SeqDense_Cholesky(Mat A, Vec xx, Vec yy)
592d71ae5a4SJacob Faibussowitsch {
593e54beecaSStefano Zampini   PetscScalar *y = NULL;
594e54beecaSStefano Zampini   PetscBLASInt m = 0, k = 0;
5954396437dSToby Isaac 
5964396437dSToby Isaac   PetscFunctionBegin;
5979566063dSJacob Faibussowitsch   PetscCall(MatSolve_SeqDense_SetUp(A, xx, yy, &y, &m, &k));
5989566063dSJacob Faibussowitsch   PetscCall(MatSolve_SeqDense_Internal_Cholesky(A, y, m, m, 1, k, PETSC_FALSE));
5999566063dSJacob Faibussowitsch   PetscCall(MatSolve_SeqDense_TearDown(A, xx, yy, &y, &m, &k));
6003ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
6014396437dSToby Isaac }
6024396437dSToby Isaac 
603d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatSolveTranspose_SeqDense_Cholesky(Mat A, Vec xx, Vec yy)
604d71ae5a4SJacob Faibussowitsch {
605e54beecaSStefano Zampini   PetscScalar *y = NULL;
606e54beecaSStefano Zampini   PetscBLASInt m = 0, k = 0;
6074396437dSToby Isaac 
6084396437dSToby Isaac   PetscFunctionBegin;
6099566063dSJacob Faibussowitsch   PetscCall(MatSolve_SeqDense_SetUp(A, xx, yy, &y, &m, &k));
6109566063dSJacob Faibussowitsch   PetscCall(MatSolve_SeqDense_Internal_Cholesky(A, y, m, m, 1, k, PETSC_TRUE));
6119566063dSJacob Faibussowitsch   PetscCall(MatSolve_SeqDense_TearDown(A, xx, yy, &y, &m, &k));
6123ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
6134396437dSToby Isaac }
6144396437dSToby Isaac 
615d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatSolve_SeqDense_QR(Mat A, Vec xx, Vec yy)
616d71ae5a4SJacob Faibussowitsch {
617e54beecaSStefano Zampini   PetscScalar *y = NULL;
618e54beecaSStefano Zampini   PetscBLASInt m = 0, k = 0;
6194396437dSToby Isaac 
6204396437dSToby Isaac   PetscFunctionBegin;
6219566063dSJacob Faibussowitsch   PetscCall(MatSolve_SeqDense_SetUp(A, xx, yy, &y, &m, &k));
6229566063dSJacob Faibussowitsch   PetscCall(MatSolve_SeqDense_Internal_QR(A, y, PetscMax(m, k), m, 1, k));
6239566063dSJacob Faibussowitsch   PetscCall(MatSolve_SeqDense_TearDown(A, xx, yy, &y, &m, &k));
6243ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
6254396437dSToby Isaac }
6264396437dSToby Isaac 
627d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatSolveTranspose_SeqDense_QR(Mat A, Vec xx, Vec yy)
628d71ae5a4SJacob Faibussowitsch {
62942e9364cSSatish Balay   PetscScalar *y = NULL;
63042e9364cSSatish Balay   PetscBLASInt m = 0, k = 0;
6314396437dSToby Isaac 
6324396437dSToby Isaac   PetscFunctionBegin;
6339566063dSJacob Faibussowitsch   PetscCall(MatSolve_SeqDense_SetUp(A, xx, yy, &y, &m, &k));
6349566063dSJacob Faibussowitsch   PetscCall(MatSolveTranspose_SeqDense_Internal_QR(A, y, PetscMax(m, k), m, 1, k));
6359566063dSJacob Faibussowitsch   PetscCall(MatSolve_SeqDense_TearDown(A, xx, yy, &y, &m, &k));
6363ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
6374396437dSToby Isaac }
6384396437dSToby Isaac 
639d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatMatSolve_SeqDense_SetUp(Mat A, Mat B, Mat X, PetscScalar **_y, PetscBLASInt *_ldy, PetscBLASInt *_m, PetscBLASInt *_nrhs, PetscBLASInt *_k)
640d71ae5a4SJacob Faibussowitsch {
6414905a7bcSToby Isaac   const PetscScalar *b;
6424396437dSToby Isaac   PetscScalar       *y;
643bf5a80bcSToby Isaac   PetscInt           n, _ldb, _ldx;
644bf5a80bcSToby Isaac   PetscBLASInt       nrhs = 0, m = 0, k = 0, ldb = 0, ldx = 0, ldy = 0;
6454905a7bcSToby Isaac 
6464905a7bcSToby Isaac   PetscFunctionBegin;
6479371c9d4SSatish Balay   *_ldy  = 0;
6489371c9d4SSatish Balay   *_m    = 0;
6499371c9d4SSatish Balay   *_nrhs = 0;
6509371c9d4SSatish Balay   *_k    = 0;
6519371c9d4SSatish Balay   *_y    = NULL;
6529566063dSJacob Faibussowitsch   PetscCall(PetscBLASIntCast(A->rmap->n, &m));
6539566063dSJacob Faibussowitsch   PetscCall(PetscBLASIntCast(A->cmap->n, &k));
6549566063dSJacob Faibussowitsch   PetscCall(MatGetSize(B, NULL, &n));
6559566063dSJacob Faibussowitsch   PetscCall(PetscBLASIntCast(n, &nrhs));
6569566063dSJacob Faibussowitsch   PetscCall(MatDenseGetLDA(B, &_ldb));
6579566063dSJacob Faibussowitsch   PetscCall(PetscBLASIntCast(_ldb, &ldb));
6589566063dSJacob Faibussowitsch   PetscCall(MatDenseGetLDA(X, &_ldx));
6599566063dSJacob Faibussowitsch   PetscCall(PetscBLASIntCast(_ldx, &ldx));
660bf5a80bcSToby Isaac   if (ldx < m) {
6619566063dSJacob Faibussowitsch     PetscCall(MatDenseGetArrayRead(B, &b));
6629566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(nrhs * m, &y));
663bf5a80bcSToby Isaac     if (ldb == m) {
6649566063dSJacob Faibussowitsch       PetscCall(PetscArraycpy(y, b, ldb * nrhs));
6654905a7bcSToby Isaac     } else {
66648a46eb9SPierre Jolivet       for (PetscInt j = 0; j < nrhs; j++) PetscCall(PetscArraycpy(&y[j * m], &b[j * ldb], m));
6674905a7bcSToby Isaac     }
668bf5a80bcSToby Isaac     ldy = m;
6699566063dSJacob Faibussowitsch     PetscCall(MatDenseRestoreArrayRead(B, &b));
6704905a7bcSToby Isaac   } else {
671bf5a80bcSToby Isaac     if (ldb == ldx) {
6729566063dSJacob Faibussowitsch       PetscCall(MatCopy(B, X, SAME_NONZERO_PATTERN));
6739566063dSJacob Faibussowitsch       PetscCall(MatDenseGetArray(X, &y));
6744905a7bcSToby Isaac     } else {
6759566063dSJacob Faibussowitsch       PetscCall(MatDenseGetArray(X, &y));
6769566063dSJacob Faibussowitsch       PetscCall(MatDenseGetArrayRead(B, &b));
67748a46eb9SPierre Jolivet       for (PetscInt j = 0; j < nrhs; j++) PetscCall(PetscArraycpy(&y[j * ldx], &b[j * ldb], m));
6789566063dSJacob Faibussowitsch       PetscCall(MatDenseRestoreArrayRead(B, &b));
6794905a7bcSToby Isaac     }
680bf5a80bcSToby Isaac     ldy = ldx;
6814905a7bcSToby Isaac   }
6824396437dSToby Isaac   *_y    = y;
683bf5a80bcSToby Isaac   *_ldy  = ldy;
6844396437dSToby Isaac   *_k    = k;
6854396437dSToby Isaac   *_m    = m;
6864396437dSToby Isaac   *_nrhs = nrhs;
6873ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
6884396437dSToby Isaac }
6894396437dSToby Isaac 
690d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatMatSolve_SeqDense_TearDown(Mat A, Mat B, Mat X, PetscScalar **_y, PetscBLASInt *_ldy, PetscBLASInt *_m, PetscBLASInt *_nrhs, PetscBLASInt *_k)
691d71ae5a4SJacob Faibussowitsch {
6924396437dSToby Isaac   PetscScalar *y;
693bf5a80bcSToby Isaac   PetscInt     _ldx;
694bf5a80bcSToby Isaac   PetscBLASInt k, ldy, nrhs, ldx = 0;
6954396437dSToby Isaac 
6964396437dSToby Isaac   PetscFunctionBegin;
6974396437dSToby Isaac   y    = *_y;
6984396437dSToby Isaac   *_y  = NULL;
6994396437dSToby Isaac   k    = *_k;
700bf5a80bcSToby Isaac   ldy  = *_ldy;
7014396437dSToby Isaac   nrhs = *_nrhs;
7029566063dSJacob Faibussowitsch   PetscCall(MatDenseGetLDA(X, &_ldx));
7039566063dSJacob Faibussowitsch   PetscCall(PetscBLASIntCast(_ldx, &ldx));
704bf5a80bcSToby Isaac   if (ldx != ldy) {
7054905a7bcSToby Isaac     PetscScalar *xv;
7069566063dSJacob Faibussowitsch     PetscCall(MatDenseGetArray(X, &xv));
70748a46eb9SPierre Jolivet     for (PetscInt j = 0; j < nrhs; j++) PetscCall(PetscArraycpy(&xv[j * ldx], &y[j * ldy], k));
7089566063dSJacob Faibussowitsch     PetscCall(MatDenseRestoreArray(X, &xv));
7099566063dSJacob Faibussowitsch     PetscCall(PetscFree(y));
7104905a7bcSToby Isaac   } else {
7119566063dSJacob Faibussowitsch     PetscCall(MatDenseRestoreArray(X, &y));
7124905a7bcSToby Isaac   }
7133ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
71485e2c93fSHong Zhang }
71585e2c93fSHong Zhang 
716d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatMatSolve_SeqDense_LU(Mat A, Mat B, Mat X)
717d71ae5a4SJacob Faibussowitsch {
7184396437dSToby Isaac   PetscScalar *y;
719bf5a80bcSToby Isaac   PetscBLASInt m, k, ldy, nrhs;
7204396437dSToby Isaac 
7214396437dSToby Isaac   PetscFunctionBegin;
7229566063dSJacob Faibussowitsch   PetscCall(MatMatSolve_SeqDense_SetUp(A, B, X, &y, &ldy, &m, &nrhs, &k));
7239566063dSJacob Faibussowitsch   PetscCall(MatSolve_SeqDense_Internal_LU(A, y, ldy, m, nrhs, k, PETSC_FALSE));
7249566063dSJacob Faibussowitsch   PetscCall(MatMatSolve_SeqDense_TearDown(A, B, X, &y, &ldy, &m, &nrhs, &k));
7253ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
7264396437dSToby Isaac }
7274396437dSToby Isaac 
728d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatMatSolveTranspose_SeqDense_LU(Mat A, Mat B, Mat X)
729d71ae5a4SJacob Faibussowitsch {
7304396437dSToby Isaac   PetscScalar *y;
731bf5a80bcSToby Isaac   PetscBLASInt m, k, ldy, nrhs;
7324396437dSToby Isaac 
7334396437dSToby Isaac   PetscFunctionBegin;
7349566063dSJacob Faibussowitsch   PetscCall(MatMatSolve_SeqDense_SetUp(A, B, X, &y, &ldy, &m, &nrhs, &k));
7359566063dSJacob Faibussowitsch   PetscCall(MatSolve_SeqDense_Internal_LU(A, y, ldy, m, nrhs, k, PETSC_TRUE));
7369566063dSJacob Faibussowitsch   PetscCall(MatMatSolve_SeqDense_TearDown(A, B, X, &y, &ldy, &m, &nrhs, &k));
7373ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
7384396437dSToby Isaac }
7394396437dSToby Isaac 
740d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatMatSolve_SeqDense_Cholesky(Mat A, Mat B, Mat X)
741d71ae5a4SJacob Faibussowitsch {
7424396437dSToby Isaac   PetscScalar *y;
743bf5a80bcSToby Isaac   PetscBLASInt m, k, ldy, nrhs;
7444396437dSToby Isaac 
7454396437dSToby Isaac   PetscFunctionBegin;
7469566063dSJacob Faibussowitsch   PetscCall(MatMatSolve_SeqDense_SetUp(A, B, X, &y, &ldy, &m, &nrhs, &k));
7479566063dSJacob Faibussowitsch   PetscCall(MatSolve_SeqDense_Internal_Cholesky(A, y, ldy, m, nrhs, k, PETSC_FALSE));
7489566063dSJacob Faibussowitsch   PetscCall(MatMatSolve_SeqDense_TearDown(A, B, X, &y, &ldy, &m, &nrhs, &k));
7493ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
7504396437dSToby Isaac }
7514396437dSToby Isaac 
752d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatMatSolveTranspose_SeqDense_Cholesky(Mat A, Mat B, Mat X)
753d71ae5a4SJacob Faibussowitsch {
7544396437dSToby Isaac   PetscScalar *y;
755bf5a80bcSToby Isaac   PetscBLASInt m, k, ldy, nrhs;
7564396437dSToby Isaac 
7574396437dSToby Isaac   PetscFunctionBegin;
7589566063dSJacob Faibussowitsch   PetscCall(MatMatSolve_SeqDense_SetUp(A, B, X, &y, &ldy, &m, &nrhs, &k));
7599566063dSJacob Faibussowitsch   PetscCall(MatSolve_SeqDense_Internal_Cholesky(A, y, ldy, m, nrhs, k, PETSC_TRUE));
7609566063dSJacob Faibussowitsch   PetscCall(MatMatSolve_SeqDense_TearDown(A, B, X, &y, &ldy, &m, &nrhs, &k));
7613ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
7624396437dSToby Isaac }
7634396437dSToby Isaac 
764d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatMatSolve_SeqDense_QR(Mat A, Mat B, Mat X)
765d71ae5a4SJacob Faibussowitsch {
7664396437dSToby Isaac   PetscScalar *y;
767bf5a80bcSToby Isaac   PetscBLASInt m, k, ldy, nrhs;
7684396437dSToby Isaac 
7694396437dSToby Isaac   PetscFunctionBegin;
7709566063dSJacob Faibussowitsch   PetscCall(MatMatSolve_SeqDense_SetUp(A, B, X, &y, &ldy, &m, &nrhs, &k));
7719566063dSJacob Faibussowitsch   PetscCall(MatSolve_SeqDense_Internal_QR(A, y, ldy, m, nrhs, k));
7729566063dSJacob Faibussowitsch   PetscCall(MatMatSolve_SeqDense_TearDown(A, B, X, &y, &ldy, &m, &nrhs, &k));
7733ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
7744396437dSToby Isaac }
7754396437dSToby Isaac 
776d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatMatSolveTranspose_SeqDense_QR(Mat A, Mat B, Mat X)
777d71ae5a4SJacob Faibussowitsch {
7784396437dSToby Isaac   PetscScalar *y;
779bf5a80bcSToby Isaac   PetscBLASInt m, k, ldy, nrhs;
7804396437dSToby Isaac 
7814396437dSToby Isaac   PetscFunctionBegin;
7829566063dSJacob Faibussowitsch   PetscCall(MatMatSolve_SeqDense_SetUp(A, B, X, &y, &ldy, &m, &nrhs, &k));
7839566063dSJacob Faibussowitsch   PetscCall(MatSolveTranspose_SeqDense_Internal_QR(A, y, ldy, m, nrhs, k));
7849566063dSJacob Faibussowitsch   PetscCall(MatMatSolve_SeqDense_TearDown(A, B, X, &y, &ldy, &m, &nrhs, &k));
7853ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
7864396437dSToby Isaac }
7874396437dSToby Isaac 
788db4efbfdSBarry Smith /* COMMENT: I have chosen to hide row permutation in the pivots,
789db4efbfdSBarry Smith    rather than put it in the Mat->row slot.*/
790d71ae5a4SJacob Faibussowitsch PetscErrorCode MatLUFactor_SeqDense(Mat A, IS row, IS col, const MatFactorInfo *minfo)
791d71ae5a4SJacob Faibussowitsch {
792db4efbfdSBarry Smith   Mat_SeqDense *mat = (Mat_SeqDense *)A->data;
793db4efbfdSBarry Smith   PetscBLASInt  n, m, info;
794db4efbfdSBarry Smith 
795db4efbfdSBarry Smith   PetscFunctionBegin;
7969566063dSJacob Faibussowitsch   PetscCall(PetscBLASIntCast(A->cmap->n, &n));
7979566063dSJacob Faibussowitsch   PetscCall(PetscBLASIntCast(A->rmap->n, &m));
7984dfa11a4SJacob Faibussowitsch   if (!mat->pivots) { PetscCall(PetscMalloc1(A->rmap->n, &mat->pivots)); }
7993ba16761SJacob Faibussowitsch   if (!A->rmap->n || !A->cmap->n) PetscFunctionReturn(PETSC_SUCCESS);
8009566063dSJacob Faibussowitsch   PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF));
801792fecdfSBarry Smith   PetscCallBLAS("LAPACKgetrf", LAPACKgetrf_(&m, &n, mat->v, &mat->lda, mat->pivots, &info));
8029566063dSJacob Faibussowitsch   PetscCall(PetscFPTrapPop());
8038e57ea43SSatish Balay 
804835f2295SStefano Zampini   PetscCheck(info >= 0, PETSC_COMM_SELF, PETSC_ERR_LIB, "Bad argument to LU factorization %" PetscBLASInt_FMT, info);
805835f2295SStefano Zampini   PetscCheck(info <= 0, PETSC_COMM_SELF, PETSC_ERR_MAT_LU_ZRPVT, "Bad LU factorization %" PetscBLASInt_FMT, info);
8068208b9aeSStefano Zampini 
8074396437dSToby Isaac   A->ops->solve             = MatSolve_SeqDense_LU;
8084396437dSToby Isaac   A->ops->matsolve          = MatMatSolve_SeqDense_LU;
8094396437dSToby Isaac   A->ops->solvetranspose    = MatSolveTranspose_SeqDense_LU;
8104396437dSToby Isaac   A->ops->matsolvetranspose = MatMatSolveTranspose_SeqDense_LU;
811d5f3da31SBarry Smith   A->factortype             = MAT_FACTOR_LU;
812db4efbfdSBarry Smith 
8139566063dSJacob Faibussowitsch   PetscCall(PetscFree(A->solvertype));
8149566063dSJacob Faibussowitsch   PetscCall(PetscStrallocpy(MATSOLVERPETSC, &A->solvertype));
815f6224b95SHong Zhang 
8169566063dSJacob Faibussowitsch   PetscCall(PetscLogFlops((2.0 * A->cmap->n * A->cmap->n * A->cmap->n) / 3));
8173ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
818db4efbfdSBarry Smith }
819db4efbfdSBarry Smith 
820d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatLUFactorNumeric_SeqDense(Mat fact, Mat A, const MatFactorInfo *info_dummy)
821d71ae5a4SJacob Faibussowitsch {
8224396437dSToby Isaac   MatFactorInfo info;
8234396437dSToby Isaac 
8244396437dSToby Isaac   PetscFunctionBegin;
8259566063dSJacob Faibussowitsch   PetscCall(MatDuplicateNoCreate_SeqDense(fact, A, MAT_COPY_VALUES));
826dbbe0bcdSBarry Smith   PetscUseTypeMethod(fact, lufactor, NULL, NULL, &info);
8273ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
8284396437dSToby Isaac }
8294396437dSToby Isaac 
830d71ae5a4SJacob Faibussowitsch PetscErrorCode MatLUFactorSymbolic_SeqDense(Mat fact, Mat A, IS row, IS col, const MatFactorInfo *info)
831d71ae5a4SJacob Faibussowitsch {
8324396437dSToby Isaac   PetscFunctionBegin;
8334396437dSToby Isaac   fact->preallocated         = PETSC_TRUE;
8344396437dSToby Isaac   fact->assembled            = PETSC_TRUE;
8354396437dSToby Isaac   fact->ops->lufactornumeric = MatLUFactorNumeric_SeqDense;
8363ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
8374396437dSToby Isaac }
8384396437dSToby Isaac 
839a49dc2a2SStefano Zampini /* Cholesky as L*L^T or L*D*L^T and the symmetric/hermitian complex variants */
840d71ae5a4SJacob Faibussowitsch PetscErrorCode MatCholeskyFactor_SeqDense(Mat A, IS perm, const MatFactorInfo *factinfo)
841d71ae5a4SJacob Faibussowitsch {
842db4efbfdSBarry Smith   Mat_SeqDense *mat = (Mat_SeqDense *)A->data;
843c5df96a5SBarry Smith   PetscBLASInt  info, n;
844db4efbfdSBarry Smith 
845db4efbfdSBarry Smith   PetscFunctionBegin;
8469566063dSJacob Faibussowitsch   PetscCall(PetscBLASIntCast(A->cmap->n, &n));
8473ba16761SJacob Faibussowitsch   if (!A->rmap->n || !A->cmap->n) PetscFunctionReturn(PETSC_SUCCESS);
848b94d7dedSBarry Smith   if (A->spd == PETSC_BOOL3_TRUE) {
8499566063dSJacob Faibussowitsch     PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF));
850792fecdfSBarry Smith     PetscCallBLAS("LAPACKpotrf", LAPACKpotrf_("L", &n, mat->v, &mat->lda, &info));
8519566063dSJacob Faibussowitsch     PetscCall(PetscFPTrapPop());
852a49dc2a2SStefano Zampini #if defined(PETSC_USE_COMPLEX)
853b94d7dedSBarry Smith   } else if (A->hermitian == PETSC_BOOL3_TRUE) {
8544dfa11a4SJacob Faibussowitsch     if (!mat->pivots) { PetscCall(PetscMalloc1(A->rmap->n, &mat->pivots)); }
855a49dc2a2SStefano Zampini     if (!mat->fwork) {
856a49dc2a2SStefano Zampini       PetscScalar dummy;
857a49dc2a2SStefano Zampini 
858a49dc2a2SStefano Zampini       mat->lfwork = -1;
8599566063dSJacob Faibussowitsch       PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF));
860792fecdfSBarry Smith       PetscCallBLAS("LAPACKhetrf", LAPACKhetrf_("L", &n, mat->v, &mat->lda, mat->pivots, &dummy, &mat->lfwork, &info));
8619566063dSJacob Faibussowitsch       PetscCall(PetscFPTrapPop());
86207c83e99SJose E. Roman       PetscCall(PetscBLASIntCast((PetscCount)(PetscRealPart(dummy)), &mat->lfwork));
8639566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(mat->lfwork, &mat->fwork));
864a49dc2a2SStefano Zampini     }
8659566063dSJacob Faibussowitsch     PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF));
866792fecdfSBarry Smith     PetscCallBLAS("LAPACKhetrf", LAPACKhetrf_("L", &n, mat->v, &mat->lda, mat->pivots, mat->fwork, &mat->lfwork, &info));
8679566063dSJacob Faibussowitsch     PetscCall(PetscFPTrapPop());
868a49dc2a2SStefano Zampini #endif
869a49dc2a2SStefano Zampini   } else { /* symmetric case */
8704dfa11a4SJacob Faibussowitsch     if (!mat->pivots) { PetscCall(PetscMalloc1(A->rmap->n, &mat->pivots)); }
871a49dc2a2SStefano Zampini     if (!mat->fwork) {
872a49dc2a2SStefano Zampini       PetscScalar dummy;
873a49dc2a2SStefano Zampini 
874a49dc2a2SStefano Zampini       mat->lfwork = -1;
8759566063dSJacob Faibussowitsch       PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF));
876792fecdfSBarry Smith       PetscCallBLAS("LAPACKsytrf", LAPACKsytrf_("L", &n, mat->v, &mat->lda, mat->pivots, &dummy, &mat->lfwork, &info));
8779566063dSJacob Faibussowitsch       PetscCall(PetscFPTrapPop());
8786497c311SBarry Smith       PetscCall(PetscBLASIntCast((PetscCount)(PetscRealPart(dummy)), &mat->lfwork));
8799566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(mat->lfwork, &mat->fwork));
880a49dc2a2SStefano Zampini     }
8819566063dSJacob Faibussowitsch     PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF));
882792fecdfSBarry Smith     PetscCallBLAS("LAPACKsytrf", LAPACKsytrf_("L", &n, mat->v, &mat->lda, mat->pivots, mat->fwork, &mat->lfwork, &info));
8839566063dSJacob Faibussowitsch     PetscCall(PetscFPTrapPop());
884a49dc2a2SStefano Zampini   }
885835f2295SStefano Zampini   PetscCheck(!info, PETSC_COMM_SELF, PETSC_ERR_MAT_CH_ZRPVT, "Bad factorization: zero pivot in row %" PetscBLASInt_FMT, info - 1);
8868208b9aeSStefano Zampini 
8874396437dSToby Isaac   A->ops->solve             = MatSolve_SeqDense_Cholesky;
8884396437dSToby Isaac   A->ops->matsolve          = MatMatSolve_SeqDense_Cholesky;
8894396437dSToby Isaac   A->ops->solvetranspose    = MatSolveTranspose_SeqDense_Cholesky;
8904396437dSToby Isaac   A->ops->matsolvetranspose = MatMatSolveTranspose_SeqDense_Cholesky;
891d5f3da31SBarry Smith   A->factortype             = MAT_FACTOR_CHOLESKY;
8922205254eSKarl Rupp 
8939566063dSJacob Faibussowitsch   PetscCall(PetscFree(A->solvertype));
8949566063dSJacob Faibussowitsch   PetscCall(PetscStrallocpy(MATSOLVERPETSC, &A->solvertype));
895f6224b95SHong Zhang 
8969566063dSJacob Faibussowitsch   PetscCall(PetscLogFlops((1.0 * A->cmap->n * A->cmap->n * A->cmap->n) / 3.0));
8973ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
898db4efbfdSBarry Smith }
899db4efbfdSBarry Smith 
900d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatCholeskyFactorNumeric_SeqDense(Mat fact, Mat A, const MatFactorInfo *info_dummy)
901d71ae5a4SJacob Faibussowitsch {
902db4efbfdSBarry Smith   MatFactorInfo info;
903db4efbfdSBarry Smith 
904db4efbfdSBarry Smith   PetscFunctionBegin;
905db4efbfdSBarry Smith   info.fill = 1.0;
9062205254eSKarl Rupp 
9079566063dSJacob Faibussowitsch   PetscCall(MatDuplicateNoCreate_SeqDense(fact, A, MAT_COPY_VALUES));
908dbbe0bcdSBarry Smith   PetscUseTypeMethod(fact, choleskyfactor, NULL, &info);
9093ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
910db4efbfdSBarry Smith }
911db4efbfdSBarry Smith 
912d71ae5a4SJacob Faibussowitsch PetscErrorCode MatCholeskyFactorSymbolic_SeqDense(Mat fact, Mat A, IS row, const MatFactorInfo *info)
913d71ae5a4SJacob Faibussowitsch {
914db4efbfdSBarry Smith   PetscFunctionBegin;
915c3ef05f6SHong Zhang   fact->assembled                  = PETSC_TRUE;
9161bbcc794SSatish Balay   fact->preallocated               = PETSC_TRUE;
917719d5645SBarry Smith   fact->ops->choleskyfactornumeric = MatCholeskyFactorNumeric_SeqDense;
9183ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
919db4efbfdSBarry Smith }
920db4efbfdSBarry Smith 
921d71ae5a4SJacob Faibussowitsch PetscErrorCode MatQRFactor_SeqDense(Mat A, IS col, const MatFactorInfo *minfo)
922d71ae5a4SJacob Faibussowitsch {
9234905a7bcSToby Isaac   Mat_SeqDense *mat = (Mat_SeqDense *)A->data;
9244905a7bcSToby Isaac   PetscBLASInt  n, m, info, min, max;
9254905a7bcSToby Isaac 
9264905a7bcSToby Isaac   PetscFunctionBegin;
9279566063dSJacob Faibussowitsch   PetscCall(PetscBLASIntCast(A->cmap->n, &n));
9289566063dSJacob Faibussowitsch   PetscCall(PetscBLASIntCast(A->rmap->n, &m));
9294396437dSToby Isaac   max = PetscMax(m, n);
9304396437dSToby Isaac   min = PetscMin(m, n);
9314dfa11a4SJacob Faibussowitsch   if (!mat->tau) { PetscCall(PetscMalloc1(min, &mat->tau)); }
9324dfa11a4SJacob Faibussowitsch   if (!mat->pivots) { PetscCall(PetscMalloc1(n, &mat->pivots)); }
933f4f49eeaSPierre Jolivet   if (!mat->qrrhs) PetscCall(MatCreateVecs(A, NULL, &mat->qrrhs));
9343ba16761SJacob Faibussowitsch   if (!A->rmap->n || !A->cmap->n) PetscFunctionReturn(PETSC_SUCCESS);
9354905a7bcSToby Isaac   if (!mat->fwork) {
9364905a7bcSToby Isaac     PetscScalar dummy;
9374905a7bcSToby Isaac 
9384905a7bcSToby Isaac     mat->lfwork = -1;
9399566063dSJacob Faibussowitsch     PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF));
940792fecdfSBarry Smith     PetscCallBLAS("LAPACKgeqrf", LAPACKgeqrf_(&m, &n, mat->v, &mat->lda, mat->tau, &dummy, &mat->lfwork, &info));
9419566063dSJacob Faibussowitsch     PetscCall(PetscFPTrapPop());
9426497c311SBarry Smith     PetscCall(PetscBLASIntCast((PetscCount)(PetscRealPart(dummy)), &mat->lfwork));
9439566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(mat->lfwork, &mat->fwork));
9444905a7bcSToby Isaac   }
9459566063dSJacob Faibussowitsch   PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF));
946792fecdfSBarry Smith   PetscCallBLAS("LAPACKgeqrf", LAPACKgeqrf_(&m, &n, mat->v, &mat->lda, mat->tau, mat->fwork, &mat->lfwork, &info));
9479566063dSJacob Faibussowitsch   PetscCall(PetscFPTrapPop());
948835f2295SStefano Zampini   PetscCheck(!info, PETSC_COMM_SELF, PETSC_ERR_LIB, "Bad argument to QR factorization %" PetscBLASInt_FMT, info);
9494905a7bcSToby Isaac   // TODO: try to estimate rank or test for and use geqp3 for rank revealing QR.  For now just say rank is min of m and n
9504905a7bcSToby Isaac   mat->rank = min;
9514905a7bcSToby Isaac 
9524396437dSToby Isaac   A->ops->solve    = MatSolve_SeqDense_QR;
9534396437dSToby Isaac   A->ops->matsolve = MatMatSolve_SeqDense_QR;
9544905a7bcSToby Isaac   A->factortype    = MAT_FACTOR_QR;
9554905a7bcSToby Isaac   if (m == n) {
9564396437dSToby Isaac     A->ops->solvetranspose    = MatSolveTranspose_SeqDense_QR;
9574396437dSToby Isaac     A->ops->matsolvetranspose = MatMatSolveTranspose_SeqDense_QR;
9584905a7bcSToby Isaac   }
9594905a7bcSToby Isaac 
9609566063dSJacob Faibussowitsch   PetscCall(PetscFree(A->solvertype));
9619566063dSJacob Faibussowitsch   PetscCall(PetscStrallocpy(MATSOLVERPETSC, &A->solvertype));
9624905a7bcSToby Isaac 
9639566063dSJacob Faibussowitsch   PetscCall(PetscLogFlops(2.0 * min * min * (max - min / 3.0)));
9643ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
9654905a7bcSToby Isaac }
9664905a7bcSToby Isaac 
967d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatQRFactorNumeric_SeqDense(Mat fact, Mat A, const MatFactorInfo *info_dummy)
968d71ae5a4SJacob Faibussowitsch {
9694905a7bcSToby Isaac   MatFactorInfo info;
9704905a7bcSToby Isaac 
9714905a7bcSToby Isaac   PetscFunctionBegin;
9724905a7bcSToby Isaac   info.fill = 1.0;
9734905a7bcSToby Isaac 
9749566063dSJacob Faibussowitsch   PetscCall(MatDuplicateNoCreate_SeqDense(fact, A, MAT_COPY_VALUES));
975cac4c232SBarry Smith   PetscUseMethod(fact, "MatQRFactor_C", (Mat, IS, const MatFactorInfo *), (fact, NULL, &info));
9763ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
9774905a7bcSToby Isaac }
9784905a7bcSToby Isaac 
979d71ae5a4SJacob Faibussowitsch PetscErrorCode MatQRFactorSymbolic_SeqDense(Mat fact, Mat A, IS row, const MatFactorInfo *info)
980d71ae5a4SJacob Faibussowitsch {
9814905a7bcSToby Isaac   PetscFunctionBegin;
9824905a7bcSToby Isaac   fact->assembled    = PETSC_TRUE;
9834905a7bcSToby Isaac   fact->preallocated = PETSC_TRUE;
9849566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)fact, "MatQRFactorNumeric_C", MatQRFactorNumeric_SeqDense));
9853ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
9864905a7bcSToby Isaac }
9874905a7bcSToby Isaac 
988ca15aa20SStefano Zampini /* uses LAPACK */
989d71ae5a4SJacob Faibussowitsch PETSC_INTERN PetscErrorCode MatGetFactor_seqdense_petsc(Mat A, MatFactorType ftype, Mat *fact)
990d71ae5a4SJacob Faibussowitsch {
991db4efbfdSBarry Smith   PetscFunctionBegin;
9929566063dSJacob Faibussowitsch   PetscCall(MatCreate(PetscObjectComm((PetscObject)A), fact));
9939566063dSJacob Faibussowitsch   PetscCall(MatSetSizes(*fact, A->rmap->n, A->cmap->n, A->rmap->n, A->cmap->n));
9949566063dSJacob Faibussowitsch   PetscCall(MatSetType(*fact, MATDENSE));
99566e17bc3SBarry Smith   (*fact)->trivialsymbolic = PETSC_TRUE;
9962a350339SBarry Smith   if (ftype == MAT_FACTOR_LU || ftype == MAT_FACTOR_ILU) {
997db4efbfdSBarry Smith     (*fact)->ops->lufactorsymbolic  = MatLUFactorSymbolic_SeqDense;
9982a350339SBarry Smith     (*fact)->ops->ilufactorsymbolic = MatLUFactorSymbolic_SeqDense;
999bf5a80bcSToby Isaac   } else if (ftype == MAT_FACTOR_CHOLESKY || ftype == MAT_FACTOR_ICC) {
1000db4efbfdSBarry Smith     (*fact)->ops->choleskyfactorsymbolic = MatCholeskyFactorSymbolic_SeqDense;
1001bf5a80bcSToby Isaac   } else if (ftype == MAT_FACTOR_QR) {
1002f4f49eeaSPierre Jolivet     PetscCall(PetscObjectComposeFunction((PetscObject)*fact, "MatQRFactorSymbolic_C", MatQRFactorSymbolic_SeqDense));
1003db4efbfdSBarry Smith   }
1004d5f3da31SBarry Smith   (*fact)->factortype = ftype;
100500c67f3bSHong Zhang 
10069566063dSJacob Faibussowitsch   PetscCall(PetscFree((*fact)->solvertype));
10079566063dSJacob Faibussowitsch   PetscCall(PetscStrallocpy(MATSOLVERPETSC, &(*fact)->solvertype));
10089566063dSJacob Faibussowitsch   PetscCall(PetscStrallocpy(MATORDERINGEXTERNAL, (char **)&(*fact)->preferredordering[MAT_FACTOR_LU]));
10099566063dSJacob Faibussowitsch   PetscCall(PetscStrallocpy(MATORDERINGEXTERNAL, (char **)&(*fact)->preferredordering[MAT_FACTOR_ILU]));
10109566063dSJacob Faibussowitsch   PetscCall(PetscStrallocpy(MATORDERINGEXTERNAL, (char **)&(*fact)->preferredordering[MAT_FACTOR_CHOLESKY]));
10119566063dSJacob Faibussowitsch   PetscCall(PetscStrallocpy(MATORDERINGEXTERNAL, (char **)&(*fact)->preferredordering[MAT_FACTOR_ICC]));
10123ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1013db4efbfdSBarry Smith }
1014db4efbfdSBarry Smith 
1015d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatSOR_SeqDense(Mat A, Vec bb, PetscReal omega, MatSORType flag, PetscReal shift, PetscInt its, PetscInt lits, Vec xx)
1016d71ae5a4SJacob Faibussowitsch {
1017c0bbcb79SLois Curfman McInnes   Mat_SeqDense      *mat = (Mat_SeqDense *)A->data;
1018d9ca1df4SBarry Smith   PetscScalar       *x, *v = mat->v, zero = 0.0, xt;
1019d9ca1df4SBarry Smith   const PetscScalar *b;
1020d0f46423SBarry Smith   PetscInt           m = A->rmap->n, i;
102123fff9afSBarry Smith   PetscBLASInt       o = 1, bm = 0;
1022289bc588SBarry Smith 
10233a40ed3dSBarry Smith   PetscFunctionBegin;
102447d993e7Ssuyashtn #if defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
102508401ef6SPierre Jolivet   PetscCheck(A->offloadmask != PETSC_OFFLOAD_GPU, PETSC_COMM_SELF, PETSC_ERR_SUP, "Not implemented");
1026ca15aa20SStefano Zampini #endif
1027422a814eSBarry Smith   if (shift == -1) shift = 0.0; /* negative shift indicates do not error on zero diagonal; this code never zeros on zero diagonal */
10289566063dSJacob Faibussowitsch   PetscCall(PetscBLASIntCast(m, &bm));
1029289bc588SBarry Smith   if (flag & SOR_ZERO_INITIAL_GUESS) {
10303bffc371SBarry Smith     /* this is a hack fix, should have another version without the second BLASdotu */
10319566063dSJacob Faibussowitsch     PetscCall(VecSet(xx, zero));
1032289bc588SBarry Smith   }
10339566063dSJacob Faibussowitsch   PetscCall(VecGetArray(xx, &x));
10349566063dSJacob Faibussowitsch   PetscCall(VecGetArrayRead(bb, &b));
1035b965ef7fSBarry Smith   its = its * lits;
103608401ef6SPierre Jolivet   PetscCheck(its > 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Relaxation requires global its %" PetscInt_FMT " and local its %" PetscInt_FMT " both positive", its, lits);
1037289bc588SBarry Smith   while (its--) {
1038fccaa45eSBarry Smith     if (flag & SOR_FORWARD_SWEEP || flag & SOR_LOCAL_FORWARD_SWEEP) {
1039289bc588SBarry Smith       for (i = 0; i < m; i++) {
1040792fecdfSBarry Smith         PetscCallBLAS("BLASdotu", xt = b[i] - BLASdotu_(&bm, v + i, &bm, x, &o));
1041883424caSPierre Jolivet         x[i] = (1. - omega) * x[i] + (xt + v[i + i * m] * x[i]) * omega / (v[i + i * m] + shift);
1042289bc588SBarry Smith       }
1043289bc588SBarry Smith     }
1044fccaa45eSBarry Smith     if (flag & SOR_BACKWARD_SWEEP || flag & SOR_LOCAL_BACKWARD_SWEEP) {
1045289bc588SBarry Smith       for (i = m - 1; i >= 0; i--) {
1046792fecdfSBarry Smith         PetscCallBLAS("BLASdotu", xt = b[i] - BLASdotu_(&bm, v + i, &bm, x, &o));
1047883424caSPierre Jolivet         x[i] = (1. - omega) * x[i] + (xt + v[i + i * m] * x[i]) * omega / (v[i + i * m] + shift);
1048289bc588SBarry Smith       }
1049289bc588SBarry Smith     }
1050289bc588SBarry Smith   }
10519566063dSJacob Faibussowitsch   PetscCall(VecRestoreArrayRead(bb, &b));
10529566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(xx, &x));
10533ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1054289bc588SBarry Smith }
1055289bc588SBarry Smith 
10560be0d8bdSHansol Suh static PetscErrorCode MatMultColumnRangeKernel_SeqDense(Mat A, Vec xx, Vec yy, PetscInt c_start, PetscInt c_end, PetscBool trans, PetscBool herm)
1057d71ae5a4SJacob Faibussowitsch {
1058c0bbcb79SLois Curfman McInnes   Mat_SeqDense      *mat = (Mat_SeqDense *)A->data;
1059d9ca1df4SBarry Smith   PetscScalar       *y, _DOne = 1.0, _DZero = 0.0;
10600805154bSBarry Smith   PetscBLASInt       m, n, _One             = 1;
1061d9ca1df4SBarry Smith   const PetscScalar *v = mat->v, *x;
10623a40ed3dSBarry Smith 
10633a40ed3dSBarry Smith   PetscFunctionBegin;
10649566063dSJacob Faibussowitsch   PetscCall(PetscBLASIntCast(A->rmap->n, &m));
10650be0d8bdSHansol Suh   PetscCall(PetscBLASIntCast(c_end - c_start, &n));
10669566063dSJacob Faibussowitsch   PetscCall(VecGetArrayRead(xx, &x));
10679566063dSJacob Faibussowitsch   PetscCall(VecGetArrayWrite(yy, &y));
10680be0d8bdSHansol Suh   if (!m || !n) {
10695ac36cfcSBarry Smith     PetscBLASInt i;
1070459e8d23SBlanca Mellado Pinto     if (trans)
1071459e8d23SBlanca Mellado Pinto       for (i = 0; i < n; i++) y[i] = 0.0;
1072459e8d23SBlanca Mellado Pinto     else
10735ac36cfcSBarry Smith       for (i = 0; i < m; i++) y[i] = 0.0;
10745ac36cfcSBarry Smith   } else {
1075459e8d23SBlanca Mellado Pinto     if (trans) {
10760be0d8bdSHansol Suh       if (herm) PetscCallBLAS("BLASgemv", BLASgemv_("C", &m, &n, &_DOne, v + c_start * mat->lda, &mat->lda, x, &_One, &_DZero, y + c_start, &_One));
10770be0d8bdSHansol Suh       else PetscCallBLAS("BLASgemv", BLASgemv_("T", &m, &n, &_DOne, v + c_start * mat->lda, &mat->lda, x, &_One, &_DZero, y + c_start, &_One));
1078459e8d23SBlanca Mellado Pinto     } else {
10790be0d8bdSHansol Suh       PetscCallBLAS("BLASgemv", BLASgemv_("N", &m, &n, &_DOne, v + c_start * mat->lda, &mat->lda, x + c_start, &_One, &_DZero, y, &_One));
1080459e8d23SBlanca Mellado Pinto     }
10810be0d8bdSHansol Suh     PetscCall(PetscLogFlops(2.0 * m * n - n));
10825ac36cfcSBarry Smith   }
10839566063dSJacob Faibussowitsch   PetscCall(VecRestoreArrayRead(xx, &x));
10849566063dSJacob Faibussowitsch   PetscCall(VecRestoreArrayWrite(yy, &y));
10853ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1086289bc588SBarry Smith }
10876ee01492SSatish Balay 
10880be0d8bdSHansol Suh PetscErrorCode MatMultHermitianTransposeColumnRange_SeqDense(Mat A, Vec xx, Vec yy, PetscInt c_start, PetscInt c_end)
10890be0d8bdSHansol Suh {
10900be0d8bdSHansol Suh   PetscFunctionBegin;
10910be0d8bdSHansol Suh   PetscCall(MatMultColumnRangeKernel_SeqDense(A, xx, yy, c_start, c_end, PETSC_TRUE, PETSC_TRUE));
10920be0d8bdSHansol Suh   PetscFunctionReturn(PETSC_SUCCESS);
10930be0d8bdSHansol Suh }
10940be0d8bdSHansol Suh 
1095459e8d23SBlanca Mellado Pinto PetscErrorCode MatMult_SeqDense(Mat A, Vec xx, Vec yy)
1096459e8d23SBlanca Mellado Pinto {
1097459e8d23SBlanca Mellado Pinto   PetscFunctionBegin;
10980be0d8bdSHansol Suh   PetscCall(MatMultColumnRangeKernel_SeqDense(A, xx, yy, 0, A->cmap->n, PETSC_FALSE, PETSC_FALSE));
1099459e8d23SBlanca Mellado Pinto   PetscFunctionReturn(PETSC_SUCCESS);
1100459e8d23SBlanca Mellado Pinto }
1101459e8d23SBlanca Mellado Pinto 
1102459e8d23SBlanca Mellado Pinto PetscErrorCode MatMultTranspose_SeqDense(Mat A, Vec xx, Vec yy)
1103459e8d23SBlanca Mellado Pinto {
1104459e8d23SBlanca Mellado Pinto   PetscFunctionBegin;
11050be0d8bdSHansol Suh   PetscCall(MatMultColumnRangeKernel_SeqDense(A, xx, yy, 0, A->cmap->n, PETSC_TRUE, PETSC_FALSE));
1106459e8d23SBlanca Mellado Pinto   PetscFunctionReturn(PETSC_SUCCESS);
1107459e8d23SBlanca Mellado Pinto }
1108459e8d23SBlanca Mellado Pinto 
1109459e8d23SBlanca Mellado Pinto PetscErrorCode MatMultHermitianTranspose_SeqDense(Mat A, Vec xx, Vec yy)
1110459e8d23SBlanca Mellado Pinto {
1111459e8d23SBlanca Mellado Pinto   PetscFunctionBegin;
11120be0d8bdSHansol Suh   PetscCall(MatMultColumnRangeKernel_SeqDense(A, xx, yy, 0, A->cmap->n, PETSC_TRUE, PETSC_TRUE));
1113459e8d23SBlanca Mellado Pinto   PetscFunctionReturn(PETSC_SUCCESS);
1114459e8d23SBlanca Mellado Pinto }
1115459e8d23SBlanca Mellado Pinto 
11160be0d8bdSHansol Suh static PetscErrorCode MatMultAddColumnRangeKernel_SeqDense(Mat A, Vec xx, Vec zz, Vec yy, PetscInt c_start, PetscInt c_end, PetscBool trans, PetscBool herm)
1117d71ae5a4SJacob Faibussowitsch {
1118c0bbcb79SLois Curfman McInnes   Mat_SeqDense      *mat = (Mat_SeqDense *)A->data;
1119d9ca1df4SBarry Smith   const PetscScalar *v   = mat->v, *x;
1120d9ca1df4SBarry Smith   PetscScalar       *y, _DOne = 1.0;
11210805154bSBarry Smith   PetscBLASInt       m, n, _One = 1;
11223a40ed3dSBarry Smith 
11233a40ed3dSBarry Smith   PetscFunctionBegin;
11249566063dSJacob Faibussowitsch   PetscCall(PetscBLASIntCast(A->rmap->n, &m));
11250be0d8bdSHansol Suh   PetscCall(PetscBLASIntCast(c_end - c_start, &n));
11269566063dSJacob Faibussowitsch   PetscCall(VecCopy(zz, yy));
11270be0d8bdSHansol Suh   if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS);
11289566063dSJacob Faibussowitsch   PetscCall(VecGetArray(yy, &y));
1129459e8d23SBlanca Mellado Pinto   PetscCall(VecGetArrayRead(xx, &x));
1130459e8d23SBlanca Mellado Pinto   if (trans) {
11310be0d8bdSHansol Suh     if (herm) PetscCallBLAS("BLASgemv", BLASgemv_("C", &m, &n, &_DOne, v + c_start * mat->lda, &mat->lda, x, &_One, &_DOne, y + c_start, &_One));
11320be0d8bdSHansol Suh     else PetscCallBLAS("BLASgemv", BLASgemv_("T", &m, &n, &_DOne, v + c_start * mat->lda, &mat->lda, x, &_One, &_DOne, y + c_start, &_One));
1133459e8d23SBlanca Mellado Pinto   } else {
11340be0d8bdSHansol Suh     PetscCallBLAS("BLASgemv", BLASgemv_("N", &m, &n, &_DOne, v + c_start * mat->lda, &mat->lda, x + c_start, &_One, &_DOne, y, &_One));
1135459e8d23SBlanca Mellado Pinto   }
11369566063dSJacob Faibussowitsch   PetscCall(VecRestoreArrayRead(xx, &x));
11379566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(yy, &y));
11380be0d8bdSHansol Suh   PetscCall(PetscLogFlops(2.0 * m * n));
11390be0d8bdSHansol Suh   PetscFunctionReturn(PETSC_SUCCESS);
11400be0d8bdSHansol Suh }
11410be0d8bdSHansol Suh 
11420be0d8bdSHansol Suh PetscErrorCode MatMultAddColumnRange_SeqDense(Mat A, Vec xx, Vec zz, Vec yy, PetscInt c_start, PetscInt c_end)
11430be0d8bdSHansol Suh {
11440be0d8bdSHansol Suh   PetscFunctionBegin;
11450be0d8bdSHansol Suh   PetscCall(MatMultAddColumnRangeKernel_SeqDense(A, xx, zz, yy, c_start, c_end, PETSC_FALSE, PETSC_FALSE));
11460be0d8bdSHansol Suh   PetscFunctionReturn(PETSC_SUCCESS);
11470be0d8bdSHansol Suh }
11480be0d8bdSHansol Suh 
11490be0d8bdSHansol Suh PetscErrorCode MatMultHermitianTransposeAddColumnRange_SeqDense(Mat A, Vec xx, Vec zz, Vec yy, PetscInt c_start, PetscInt c_end)
11500be0d8bdSHansol Suh {
11510be0d8bdSHansol Suh   PetscFunctionBegin;
11520be0d8bdSHansol Suh   PetscMPIInt rank;
11530be0d8bdSHansol Suh   PetscCallMPI(MPI_Comm_rank(MPI_COMM_WORLD, &rank));
11540be0d8bdSHansol Suh   PetscCall(MatMultAddColumnRangeKernel_SeqDense(A, xx, zz, yy, c_start, c_end, PETSC_TRUE, PETSC_TRUE));
11553ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1156289bc588SBarry Smith }
11576ee01492SSatish Balay 
1158459e8d23SBlanca Mellado Pinto PetscErrorCode MatMultAdd_SeqDense(Mat A, Vec xx, Vec zz, Vec yy)
1159459e8d23SBlanca Mellado Pinto {
1160459e8d23SBlanca Mellado Pinto   PetscFunctionBegin;
11610be0d8bdSHansol Suh   PetscCall(MatMultAddColumnRangeKernel_SeqDense(A, xx, zz, yy, 0, A->cmap->n, PETSC_FALSE, PETSC_FALSE));
1162459e8d23SBlanca Mellado Pinto   PetscFunctionReturn(PETSC_SUCCESS);
1163459e8d23SBlanca Mellado Pinto }
1164459e8d23SBlanca Mellado Pinto 
1165d71ae5a4SJacob Faibussowitsch PetscErrorCode MatMultTransposeAdd_SeqDense(Mat A, Vec xx, Vec zz, Vec yy)
1166d71ae5a4SJacob Faibussowitsch {
11673a40ed3dSBarry Smith   PetscFunctionBegin;
11680be0d8bdSHansol Suh   PetscCall(MatMultAddColumnRangeKernel_SeqDense(A, xx, zz, yy, 0, A->cmap->n, PETSC_TRUE, PETSC_FALSE));
1169459e8d23SBlanca Mellado Pinto   PetscFunctionReturn(PETSC_SUCCESS);
1170459e8d23SBlanca Mellado Pinto }
1171459e8d23SBlanca Mellado Pinto 
1172459e8d23SBlanca Mellado Pinto PetscErrorCode MatMultHermitianTransposeAdd_SeqDense(Mat A, Vec xx, Vec zz, Vec yy)
1173459e8d23SBlanca Mellado Pinto {
1174459e8d23SBlanca Mellado Pinto   PetscFunctionBegin;
11750be0d8bdSHansol Suh   PetscCall(MatMultAddColumnRangeKernel_SeqDense(A, xx, zz, yy, 0, A->cmap->n, PETSC_TRUE, PETSC_TRUE));
11763ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1177289bc588SBarry Smith }
1178289bc588SBarry Smith 
1179d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatGetRow_SeqDense(Mat A, PetscInt row, PetscInt *ncols, PetscInt **cols, PetscScalar **vals)
1180d71ae5a4SJacob Faibussowitsch {
1181c0bbcb79SLois Curfman McInnes   Mat_SeqDense *mat = (Mat_SeqDense *)A->data;
118213f74950SBarry Smith   PetscInt      i;
118367e560aaSBarry Smith 
11843a40ed3dSBarry Smith   PetscFunctionBegin;
1185c3e1b152SPierre Jolivet   if (ncols) *ncols = A->cmap->n;
1186289bc588SBarry Smith   if (cols) {
11879566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(A->cmap->n, cols));
1188d0f46423SBarry Smith     for (i = 0; i < A->cmap->n; i++) (*cols)[i] = i;
1189289bc588SBarry Smith   }
1190289bc588SBarry Smith   if (vals) {
1191ca15aa20SStefano Zampini     const PetscScalar *v;
1192ca15aa20SStefano Zampini 
11939566063dSJacob Faibussowitsch     PetscCall(MatDenseGetArrayRead(A, &v));
11949566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(A->cmap->n, vals));
1195ca15aa20SStefano Zampini     v += row;
11969371c9d4SSatish Balay     for (i = 0; i < A->cmap->n; i++) {
11979371c9d4SSatish Balay       (*vals)[i] = *v;
11989371c9d4SSatish Balay       v += mat->lda;
11999371c9d4SSatish Balay     }
12009566063dSJacob Faibussowitsch     PetscCall(MatDenseRestoreArrayRead(A, &v));
1201289bc588SBarry Smith   }
12023ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1203289bc588SBarry Smith }
12046ee01492SSatish Balay 
1205d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatRestoreRow_SeqDense(Mat A, PetscInt row, PetscInt *ncols, PetscInt **cols, PetscScalar **vals)
1206d71ae5a4SJacob Faibussowitsch {
1207606d414cSSatish Balay   PetscFunctionBegin;
12089566063dSJacob Faibussowitsch   if (cols) PetscCall(PetscFree(*cols));
12099566063dSJacob Faibussowitsch   if (vals) PetscCall(PetscFree(*vals));
12103ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1211289bc588SBarry Smith }
12122ef1f0ffSBarry Smith 
1213d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatSetValues_SeqDense(Mat A, PetscInt m, const PetscInt indexm[], PetscInt n, const PetscInt indexn[], const PetscScalar v[], InsertMode addv)
1214d71ae5a4SJacob Faibussowitsch {
1215c0bbcb79SLois Curfman McInnes   Mat_SeqDense *mat = (Mat_SeqDense *)A->data;
1216ca15aa20SStefano Zampini   PetscScalar  *av;
121713f74950SBarry Smith   PetscInt      i, j, idx = 0;
121847d993e7Ssuyashtn #if defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
1219c70f7ee4SJunchao Zhang   PetscOffloadMask oldf;
1220ca15aa20SStefano Zampini #endif
1221d6dfbf8fSBarry Smith 
12223a40ed3dSBarry Smith   PetscFunctionBegin;
12239566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArray(A, &av));
1224289bc588SBarry Smith   if (!mat->roworiented) {
1225dbb450caSBarry Smith     if (addv == INSERT_VALUES) {
1226289bc588SBarry Smith       for (j = 0; j < n; j++) {
12279371c9d4SSatish Balay         if (indexn[j] < 0) {
12289371c9d4SSatish Balay           idx += m;
12299371c9d4SSatish Balay           continue;
12309371c9d4SSatish Balay         }
12316bdcaf15SBarry Smith         PetscCheck(indexn[j] < A->cmap->n, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Column too large: col %" PetscInt_FMT " max %" PetscInt_FMT, indexn[j], A->cmap->n - 1);
1232289bc588SBarry Smith         for (i = 0; i < m; i++) {
12339371c9d4SSatish Balay           if (indexm[i] < 0) {
12349371c9d4SSatish Balay             idx++;
12359371c9d4SSatish Balay             continue;
12369371c9d4SSatish Balay           }
12376bdcaf15SBarry Smith           PetscCheck(indexm[i] < A->rmap->n, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Row too large: row %" PetscInt_FMT " max %" PetscInt_FMT, indexm[i], A->rmap->n - 1);
12388c4a67a0SStefano Zampini           av[indexn[j] * mat->lda + indexm[i]] = v ? v[idx++] : (idx++, 0.0);
1239289bc588SBarry Smith         }
1240289bc588SBarry Smith       }
12410be0d8bdSHansol Suh     } else {
1242289bc588SBarry Smith       for (j = 0; j < n; j++) {
12439371c9d4SSatish Balay         if (indexn[j] < 0) {
12449371c9d4SSatish Balay           idx += m;
12459371c9d4SSatish Balay           continue;
12469371c9d4SSatish Balay         }
12476bdcaf15SBarry Smith         PetscCheck(indexn[j] < A->cmap->n, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Column too large: col %" PetscInt_FMT " max %" PetscInt_FMT, indexn[j], A->cmap->n - 1);
1248289bc588SBarry Smith         for (i = 0; i < m; i++) {
12499371c9d4SSatish Balay           if (indexm[i] < 0) {
12509371c9d4SSatish Balay             idx++;
12519371c9d4SSatish Balay             continue;
12529371c9d4SSatish Balay           }
12536bdcaf15SBarry Smith           PetscCheck(indexm[i] < A->rmap->n, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Row too large: row %" PetscInt_FMT " max %" PetscInt_FMT, indexm[i], A->rmap->n - 1);
12548c4a67a0SStefano Zampini           av[indexn[j] * mat->lda + indexm[i]] += v ? v[idx++] : (idx++, 0.0);
1255289bc588SBarry Smith         }
1256289bc588SBarry Smith       }
1257289bc588SBarry Smith     }
12583a40ed3dSBarry Smith   } else {
1259dbb450caSBarry Smith     if (addv == INSERT_VALUES) {
1260e8d4e0b9SBarry Smith       for (i = 0; i < m; i++) {
12619371c9d4SSatish Balay         if (indexm[i] < 0) {
12629371c9d4SSatish Balay           idx += n;
12639371c9d4SSatish Balay           continue;
12649371c9d4SSatish Balay         }
12656bdcaf15SBarry Smith         PetscCheck(indexm[i] < A->rmap->n, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Row too large: row %" PetscInt_FMT " max %" PetscInt_FMT, indexm[i], A->rmap->n - 1);
1266e8d4e0b9SBarry Smith         for (j = 0; j < n; j++) {
12679371c9d4SSatish Balay           if (indexn[j] < 0) {
12689371c9d4SSatish Balay             idx++;
12699371c9d4SSatish Balay             continue;
12709371c9d4SSatish Balay           }
12716bdcaf15SBarry Smith           PetscCheck(indexn[j] < A->cmap->n, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Column too large: col %" PetscInt_FMT " max %" PetscInt_FMT, indexn[j], A->cmap->n - 1);
12728c4a67a0SStefano Zampini           av[indexn[j] * mat->lda + indexm[i]] = v ? v[idx++] : (idx++, 0.0);
1273e8d4e0b9SBarry Smith         }
1274e8d4e0b9SBarry Smith       }
12750be0d8bdSHansol Suh     } else {
1276289bc588SBarry Smith       for (i = 0; i < m; i++) {
12779371c9d4SSatish Balay         if (indexm[i] < 0) {
12789371c9d4SSatish Balay           idx += n;
12799371c9d4SSatish Balay           continue;
12809371c9d4SSatish Balay         }
12816bdcaf15SBarry Smith         PetscCheck(indexm[i] < A->rmap->n, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Row too large: row %" PetscInt_FMT " max %" PetscInt_FMT, indexm[i], A->rmap->n - 1);
1282289bc588SBarry Smith         for (j = 0; j < n; j++) {
12839371c9d4SSatish Balay           if (indexn[j] < 0) {
12849371c9d4SSatish Balay             idx++;
12859371c9d4SSatish Balay             continue;
12869371c9d4SSatish Balay           }
12876bdcaf15SBarry Smith           PetscCheck(indexn[j] < A->cmap->n, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Column too large: col %" PetscInt_FMT " max %" PetscInt_FMT, indexn[j], A->cmap->n - 1);
12888c4a67a0SStefano Zampini           av[indexn[j] * mat->lda + indexm[i]] += v ? v[idx++] : (idx++, 0.0);
1289289bc588SBarry Smith         }
1290289bc588SBarry Smith       }
1291289bc588SBarry Smith     }
1292e8d4e0b9SBarry Smith   }
1293ca15aa20SStefano Zampini   /* hack to prevent unneeded copy to the GPU while returning the array */
129447d993e7Ssuyashtn #if defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
1295c70f7ee4SJunchao Zhang   oldf           = A->offloadmask;
1296c70f7ee4SJunchao Zhang   A->offloadmask = PETSC_OFFLOAD_GPU;
1297ca15aa20SStefano Zampini #endif
12989566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArray(A, &av));
129947d993e7Ssuyashtn #if defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
1300c70f7ee4SJunchao Zhang   A->offloadmask = (oldf == PETSC_OFFLOAD_UNALLOCATED ? PETSC_OFFLOAD_UNALLOCATED : PETSC_OFFLOAD_CPU);
1301ca15aa20SStefano Zampini #endif
13023ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1303289bc588SBarry Smith }
1304e8d4e0b9SBarry Smith 
1305d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatGetValues_SeqDense(Mat A, PetscInt m, const PetscInt indexm[], PetscInt n, const PetscInt indexn[], PetscScalar v[])
1306d71ae5a4SJacob Faibussowitsch {
1307ae80bb75SLois Curfman McInnes   Mat_SeqDense      *mat = (Mat_SeqDense *)A->data;
1308ca15aa20SStefano Zampini   const PetscScalar *vv;
130913f74950SBarry Smith   PetscInt           i, j;
1310ae80bb75SLois Curfman McInnes 
13113a40ed3dSBarry Smith   PetscFunctionBegin;
13129566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArrayRead(A, &vv));
1313ae80bb75SLois Curfman McInnes   /* row-oriented output */
1314ae80bb75SLois Curfman McInnes   for (i = 0; i < m; i++) {
13159371c9d4SSatish Balay     if (indexm[i] < 0) {
13169371c9d4SSatish Balay       v += n;
13179371c9d4SSatish Balay       continue;
13189371c9d4SSatish Balay     }
131908401ef6SPierre Jolivet     PetscCheck(indexm[i] < A->rmap->n, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Row %" PetscInt_FMT " requested larger than number rows %" PetscInt_FMT, indexm[i], A->rmap->n);
1320ae80bb75SLois Curfman McInnes     for (j = 0; j < n; j++) {
13219371c9d4SSatish Balay       if (indexn[j] < 0) {
13229371c9d4SSatish Balay         v++;
13239371c9d4SSatish Balay         continue;
13249371c9d4SSatish Balay       }
132508401ef6SPierre Jolivet       PetscCheck(indexn[j] < A->cmap->n, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Column %" PetscInt_FMT " requested larger than number columns %" PetscInt_FMT, indexn[j], A->cmap->n);
1326ca15aa20SStefano Zampini       *v++ = vv[indexn[j] * mat->lda + indexm[i]];
1327ae80bb75SLois Curfman McInnes     }
1328ae80bb75SLois Curfman McInnes   }
13299566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArrayRead(A, &vv));
13303ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1331ae80bb75SLois Curfman McInnes }
1332ae80bb75SLois Curfman McInnes 
1333d71ae5a4SJacob Faibussowitsch PetscErrorCode MatView_Dense_Binary(Mat mat, PetscViewer viewer)
1334d71ae5a4SJacob Faibussowitsch {
13358491ab44SLisandro Dalcin   PetscBool          skipHeader;
13368491ab44SLisandro Dalcin   PetscViewerFormat  format;
13373e1d7bceSPierre Jolivet   PetscInt           header[4], M, N, m, lda, i, j;
13383e1d7bceSPierre Jolivet   PetscCount         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++)
13753e1d7bceSPierre Jolivet     for (j = 0; j < N; j++, k++) vwork[k] = v[i + (size_t)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 */
14213e1d7bceSPierre Jolivet     PetscCount nnz = (size_t)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++)
14273e1d7bceSPierre Jolivet       for (i = 0; i < m; i++) v[i + (size_t)lda * j] = vwork[(size_t)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");
16696635c364SPierre Jolivet   PetscCheck(!a->unplacedarray, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Need to call MatDenseResetArray() 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 */
18236497c311SBarry Smith       PetscCall(PetscBLASIntCast(n, &mat->lda));
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;
2018d71ae5a4SJacob Faibussowitsch   default:
2019888c827cSStefano Zampini     break;
20203a40ed3dSBarry Smith   }
20213ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2022289bc588SBarry Smith }
2023289bc588SBarry Smith 
2024d71ae5a4SJacob Faibussowitsch PetscErrorCode MatZeroEntries_SeqDense(Mat A)
2025d71ae5a4SJacob Faibussowitsch {
2026ec8511deSBarry Smith   Mat_SeqDense *l   = (Mat_SeqDense *)A->data;
20273d8925e7SStefano Zampini   PetscInt      lda = l->lda, m = A->rmap->n, n = A->cmap->n, j;
2028ca15aa20SStefano Zampini   PetscScalar  *v;
20293a40ed3dSBarry Smith 
20303a40ed3dSBarry Smith   PetscFunctionBegin;
20319566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArrayWrite(A, &v));
2032a5ce6ee0Svictorle   if (lda > m) {
203348a46eb9SPierre Jolivet     for (j = 0; j < n; j++) PetscCall(PetscArrayzero(v + j * lda, m));
2034a5ce6ee0Svictorle   } else {
20359566063dSJacob Faibussowitsch     PetscCall(PetscArrayzero(v, PetscInt64Mult(m, n)));
2036a5ce6ee0Svictorle   }
20379566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArrayWrite(A, &v));
20383ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
20396f0a148fSBarry Smith }
20406f0a148fSBarry Smith 
2041d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatZeroRows_SeqDense(Mat A, PetscInt N, const PetscInt rows[], PetscScalar diag, Vec x, Vec b)
2042d71ae5a4SJacob Faibussowitsch {
2043ec8511deSBarry Smith   Mat_SeqDense      *l = (Mat_SeqDense *)A->data;
2044b9679d65SBarry Smith   PetscInt           m = l->lda, n = A->cmap->n, i, j;
2045ca15aa20SStefano Zampini   PetscScalar       *slot, *bb, *v;
204697b48c8fSBarry Smith   const PetscScalar *xx;
204755659b69SBarry Smith 
20483a40ed3dSBarry Smith   PetscFunctionBegin;
204976bd3646SJed Brown   if (PetscDefined(USE_DEBUG)) {
2050b9679d65SBarry Smith     for (i = 0; i < N; i++) {
205108401ef6SPierre Jolivet       PetscCheck(rows[i] >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Negative row requested to be zeroed");
205208401ef6SPierre 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);
2053b9679d65SBarry Smith     }
205476bd3646SJed Brown   }
20553ba16761SJacob Faibussowitsch   if (!N) PetscFunctionReturn(PETSC_SUCCESS);
2056b9679d65SBarry Smith 
2057dd8e379bSPierre Jolivet   /* fix right-hand side if needed */
205897b48c8fSBarry Smith   if (x && b) {
20599566063dSJacob Faibussowitsch     PetscCall(VecGetArrayRead(x, &xx));
20609566063dSJacob Faibussowitsch     PetscCall(VecGetArray(b, &bb));
20612205254eSKarl Rupp     for (i = 0; i < N; i++) bb[rows[i]] = diag * xx[rows[i]];
20629566063dSJacob Faibussowitsch     PetscCall(VecRestoreArrayRead(x, &xx));
20639566063dSJacob Faibussowitsch     PetscCall(VecRestoreArray(b, &bb));
206497b48c8fSBarry Smith   }
206597b48c8fSBarry Smith 
20669566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArray(A, &v));
20676f0a148fSBarry Smith   for (i = 0; i < N; i++) {
2068ca15aa20SStefano Zampini     slot = v + rows[i];
20699371c9d4SSatish Balay     for (j = 0; j < n; j++) {
20709371c9d4SSatish Balay       *slot = 0.0;
20719371c9d4SSatish Balay       slot += m;
20729371c9d4SSatish Balay     }
20736f0a148fSBarry Smith   }
2074f4df32b1SMatthew Knepley   if (diag != 0.0) {
207508401ef6SPierre Jolivet     PetscCheck(A->rmap->n == A->cmap->n, PETSC_COMM_SELF, PETSC_ERR_SUP, "Only coded for square matrices");
20766f0a148fSBarry Smith     for (i = 0; i < N; i++) {
2077ca15aa20SStefano Zampini       slot  = v + (m + 1) * rows[i];
2078f4df32b1SMatthew Knepley       *slot = diag;
20796f0a148fSBarry Smith     }
20806f0a148fSBarry Smith   }
20819566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArray(A, &v));
20823ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
20836f0a148fSBarry Smith }
2084557bce09SLois Curfman McInnes 
2085d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatDenseGetLDA_SeqDense(Mat A, PetscInt *lda)
2086d71ae5a4SJacob Faibussowitsch {
208749a6ff4bSBarry Smith   Mat_SeqDense *mat = (Mat_SeqDense *)A->data;
208849a6ff4bSBarry Smith 
208949a6ff4bSBarry Smith   PetscFunctionBegin;
209049a6ff4bSBarry Smith   *lda = mat->lda;
20913ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
209249a6ff4bSBarry Smith }
209349a6ff4bSBarry Smith 
2094d71ae5a4SJacob Faibussowitsch PetscErrorCode MatDenseGetArray_SeqDense(Mat A, PetscScalar **array)
2095d71ae5a4SJacob Faibussowitsch {
2096c0bbcb79SLois Curfman McInnes   Mat_SeqDense *mat = (Mat_SeqDense *)A->data;
20973a40ed3dSBarry Smith 
20983a40ed3dSBarry Smith   PetscFunctionBegin;
209928b400f6SJacob Faibussowitsch   PetscCheck(!mat->matinuse, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Need to call MatDenseRestoreSubMatrix() first");
210064e87e97SBarry Smith   *array = mat->v;
21013ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
210264e87e97SBarry Smith }
21030754003eSLois Curfman McInnes 
2104d71ae5a4SJacob Faibussowitsch PetscErrorCode MatDenseRestoreArray_SeqDense(Mat A, PetscScalar **array)
2105d71ae5a4SJacob Faibussowitsch {
21063a40ed3dSBarry Smith   PetscFunctionBegin;
210775f6d85dSStefano Zampini   if (array) *array = NULL;
21083ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2109ff14e315SSatish Balay }
21100754003eSLois Curfman McInnes 
21110f74d2c1SSatish Balay /*@
211211a5261eSBarry Smith   MatDenseGetLDA - gets the leading dimension of the array returned from `MatDenseGetArray()`
211349a6ff4bSBarry Smith 
21142ef1f0ffSBarry Smith   Not Collective
211549a6ff4bSBarry Smith 
211649a6ff4bSBarry Smith   Input Parameter:
2117fe59aa6dSJacob Faibussowitsch . A - a `MATDENSE` or `MATDENSECUDA` matrix
211849a6ff4bSBarry Smith 
211949a6ff4bSBarry Smith   Output Parameter:
212049a6ff4bSBarry Smith . lda - the leading dimension
212149a6ff4bSBarry Smith 
212249a6ff4bSBarry Smith   Level: intermediate
212349a6ff4bSBarry Smith 
21241cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATDENSE`, `MATDENSECUDA`, `MatDenseGetArray()`, `MatDenseRestoreArray()`, `MatDenseGetArrayRead()`, `MatDenseRestoreArrayRead()`, `MatDenseSetLDA()`
212549a6ff4bSBarry Smith @*/
2126d71ae5a4SJacob Faibussowitsch PetscErrorCode MatDenseGetLDA(Mat A, PetscInt *lda)
2127d71ae5a4SJacob Faibussowitsch {
212849a6ff4bSBarry Smith   PetscFunctionBegin;
2129d5ea218eSStefano Zampini   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
21304f572ea9SToby Isaac   PetscAssertPointer(lda, 2);
213175f6d85dSStefano Zampini   MatCheckPreallocated(A, 1);
2132cac4c232SBarry Smith   PetscUseMethod(A, "MatDenseGetLDA_C", (Mat, PetscInt *), (A, lda));
21333ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
213449a6ff4bSBarry Smith }
213549a6ff4bSBarry Smith 
21360f74d2c1SSatish Balay /*@
213711a5261eSBarry Smith   MatDenseSetLDA - Sets the leading dimension of the array used by the `MATDENSE` matrix
2138ad16ce7aSStefano Zampini 
21392323109cSBarry Smith   Collective if the matrix layouts have not yet been setup
2140ad16ce7aSStefano Zampini 
2141d8d19677SJose E. Roman   Input Parameters:
2142fe59aa6dSJacob Faibussowitsch + A   - a `MATDENSE` or `MATDENSECUDA` matrix
2143ad16ce7aSStefano Zampini - lda - the leading dimension
2144ad16ce7aSStefano Zampini 
2145ad16ce7aSStefano Zampini   Level: intermediate
2146ad16ce7aSStefano Zampini 
21471cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATDENSE`, `MATDENSECUDA`, `MatDenseGetArray()`, `MatDenseRestoreArray()`, `MatDenseGetArrayRead()`, `MatDenseRestoreArrayRead()`, `MatDenseGetLDA()`
2148ad16ce7aSStefano Zampini @*/
2149d71ae5a4SJacob Faibussowitsch PetscErrorCode MatDenseSetLDA(Mat A, PetscInt lda)
2150d71ae5a4SJacob Faibussowitsch {
2151ad16ce7aSStefano Zampini   PetscFunctionBegin;
2152ad16ce7aSStefano Zampini   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
2153cac4c232SBarry Smith   PetscTryMethod(A, "MatDenseSetLDA_C", (Mat, PetscInt), (A, lda));
21543ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2155ad16ce7aSStefano Zampini }
2156ad16ce7aSStefano Zampini 
2157ad16ce7aSStefano Zampini /*@C
215811a5261eSBarry Smith   MatDenseGetArray - gives read-write access to the array where the data for a `MATDENSE` matrix is stored
215973a71a0fSBarry Smith 
2160c3339decSBarry Smith   Logically Collective
216173a71a0fSBarry Smith 
216273a71a0fSBarry Smith   Input Parameter:
2163fe59aa6dSJacob Faibussowitsch . A - a dense matrix
216473a71a0fSBarry Smith 
216573a71a0fSBarry Smith   Output Parameter:
216673a71a0fSBarry Smith . array - pointer to the data
216773a71a0fSBarry Smith 
216873a71a0fSBarry Smith   Level: intermediate
216973a71a0fSBarry Smith 
21701cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATDENSE`, `MatDenseRestoreArray()`, `MatDenseGetArrayRead()`, `MatDenseRestoreArrayRead()`, `MatDenseGetArrayWrite()`, `MatDenseRestoreArrayWrite()`
217173a71a0fSBarry Smith @*/
2172ce78bad3SBarry Smith PetscErrorCode MatDenseGetArray(Mat A, PetscScalar *array[]) PeNS
2173d71ae5a4SJacob Faibussowitsch {
217473a71a0fSBarry Smith   PetscFunctionBegin;
2175d5ea218eSStefano Zampini   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
21764f572ea9SToby Isaac   PetscAssertPointer(array, 2);
2177cac4c232SBarry Smith   PetscUseMethod(A, "MatDenseGetArray_C", (Mat, PetscScalar **), (A, array));
21783ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
217973a71a0fSBarry Smith }
218073a71a0fSBarry Smith 
2181dec5eb66SMatthew G Knepley /*@C
218211a5261eSBarry Smith   MatDenseRestoreArray - returns access to the array where the data for a `MATDENSE` matrix is stored obtained by `MatDenseGetArray()`
218373a71a0fSBarry Smith 
2184c3339decSBarry Smith   Logically Collective
21858572280aSBarry Smith 
21868572280aSBarry Smith   Input Parameters:
2187fe59aa6dSJacob Faibussowitsch + A     - a dense matrix
21882ef1f0ffSBarry Smith - array - pointer to the data (may be `NULL`)
21898572280aSBarry Smith 
21908572280aSBarry Smith   Level: intermediate
21918572280aSBarry Smith 
21921cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATDENSE`, `MatDenseGetArray()`, `MatDenseGetArrayRead()`, `MatDenseRestoreArrayRead()`, `MatDenseGetArrayWrite()`, `MatDenseRestoreArrayWrite()`
21938572280aSBarry Smith @*/
2194ce78bad3SBarry Smith PetscErrorCode MatDenseRestoreArray(Mat A, PetscScalar *array[]) PeNS
2195d71ae5a4SJacob Faibussowitsch {
21968572280aSBarry Smith   PetscFunctionBegin;
2197d5ea218eSStefano Zampini   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
21984f572ea9SToby Isaac   if (array) PetscAssertPointer(array, 2);
2199cac4c232SBarry Smith   PetscUseMethod(A, "MatDenseRestoreArray_C", (Mat, PetscScalar **), (A, array));
22009566063dSJacob Faibussowitsch   PetscCall(PetscObjectStateIncrease((PetscObject)A));
220147d993e7Ssuyashtn #if defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
2202637a0070SStefano Zampini   A->offloadmask = PETSC_OFFLOAD_CPU;
2203637a0070SStefano Zampini #endif
22043ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
22058572280aSBarry Smith }
22068572280aSBarry Smith 
22078572280aSBarry Smith /*@C
220811a5261eSBarry Smith   MatDenseGetArrayRead - gives read-only access to the array where the data for a `MATDENSE` matrix is stored
22098572280aSBarry Smith 
2210fb850c59SBarry Smith   Not Collective
22118572280aSBarry Smith 
22128572280aSBarry Smith   Input Parameter:
2213fe59aa6dSJacob Faibussowitsch . A - a dense matrix
22148572280aSBarry Smith 
22158572280aSBarry Smith   Output Parameter:
22168572280aSBarry Smith . array - pointer to the data
22178572280aSBarry Smith 
22188572280aSBarry Smith   Level: intermediate
22198572280aSBarry Smith 
22201cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATDENSE`, `MatDenseRestoreArrayRead()`, `MatDenseGetArray()`, `MatDenseRestoreArray()`, `MatDenseGetArrayWrite()`, `MatDenseRestoreArrayWrite()`
22218572280aSBarry Smith @*/
2222ce78bad3SBarry Smith PetscErrorCode MatDenseGetArrayRead(Mat A, const PetscScalar *array[]) PeNS
2223d71ae5a4SJacob Faibussowitsch {
22248572280aSBarry Smith   PetscFunctionBegin;
2225d5ea218eSStefano Zampini   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
22264f572ea9SToby Isaac   PetscAssertPointer(array, 2);
22275c0db29aSPierre Jolivet   PetscUseMethod(A, "MatDenseGetArrayRead_C", (Mat, PetscScalar **), (A, (PetscScalar **)array));
22283ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
22298572280aSBarry Smith }
22308572280aSBarry Smith 
22318572280aSBarry Smith /*@C
223211a5261eSBarry Smith   MatDenseRestoreArrayRead - returns access to the array where the data for a `MATDENSE` matrix is stored obtained by `MatDenseGetArrayRead()`
22338572280aSBarry Smith 
2234fb850c59SBarry Smith   Not Collective
223573a71a0fSBarry Smith 
223673a71a0fSBarry Smith   Input Parameters:
2237fe59aa6dSJacob Faibussowitsch + A     - a dense matrix
22382ef1f0ffSBarry Smith - array - pointer to the data (may be `NULL`)
223973a71a0fSBarry Smith 
224073a71a0fSBarry Smith   Level: intermediate
224173a71a0fSBarry Smith 
22421cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATDENSE`, `MatDenseGetArrayRead()`, `MatDenseGetArray()`, `MatDenseRestoreArray()`, `MatDenseGetArrayWrite()`, `MatDenseRestoreArrayWrite()`
224373a71a0fSBarry Smith @*/
2244ce78bad3SBarry Smith PetscErrorCode MatDenseRestoreArrayRead(Mat A, const PetscScalar *array[]) PeNS
2245d71ae5a4SJacob Faibussowitsch {
224673a71a0fSBarry Smith   PetscFunctionBegin;
2247d5ea218eSStefano Zampini   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
22484f572ea9SToby Isaac   if (array) PetscAssertPointer(array, 2);
22495c0db29aSPierre Jolivet   PetscUseMethod(A, "MatDenseRestoreArrayRead_C", (Mat, PetscScalar **), (A, (PetscScalar **)array));
22503ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
225173a71a0fSBarry Smith }
225273a71a0fSBarry Smith 
22536947451fSStefano Zampini /*@C
225411a5261eSBarry Smith   MatDenseGetArrayWrite - gives write-only access to the array where the data for a `MATDENSE` matrix is stored
22556947451fSStefano Zampini 
2256fb850c59SBarry Smith   Not Collective
22576947451fSStefano Zampini 
22586947451fSStefano Zampini   Input Parameter:
2259fe59aa6dSJacob Faibussowitsch . A - a dense matrix
22606947451fSStefano Zampini 
22616947451fSStefano Zampini   Output Parameter:
22626947451fSStefano Zampini . array - pointer to the data
22636947451fSStefano Zampini 
22646947451fSStefano Zampini   Level: intermediate
22656947451fSStefano Zampini 
22661cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATDENSE`, `MatDenseRestoreArrayWrite()`, `MatDenseGetArray()`, `MatDenseRestoreArray()`, `MatDenseGetArrayRead()`, `MatDenseRestoreArrayRead()`
22676947451fSStefano Zampini @*/
2268ce78bad3SBarry Smith PetscErrorCode MatDenseGetArrayWrite(Mat A, PetscScalar *array[]) PeNS
2269d71ae5a4SJacob Faibussowitsch {
22706947451fSStefano Zampini   PetscFunctionBegin;
2271d5ea218eSStefano Zampini   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
22724f572ea9SToby Isaac   PetscAssertPointer(array, 2);
2273cac4c232SBarry Smith   PetscUseMethod(A, "MatDenseGetArrayWrite_C", (Mat, PetscScalar **), (A, array));
22743ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
22756947451fSStefano Zampini }
22766947451fSStefano Zampini 
22776947451fSStefano Zampini /*@C
227811a5261eSBarry Smith   MatDenseRestoreArrayWrite - returns access to the array where the data for a `MATDENSE` matrix is stored obtained by `MatDenseGetArrayWrite()`
22796947451fSStefano Zampini 
2280fb850c59SBarry Smith   Not Collective
22816947451fSStefano Zampini 
22826947451fSStefano Zampini   Input Parameters:
2283fe59aa6dSJacob Faibussowitsch + A     - a dense matrix
22842ef1f0ffSBarry Smith - array - pointer to the data (may be `NULL`)
22856947451fSStefano Zampini 
22866947451fSStefano Zampini   Level: intermediate
22876947451fSStefano Zampini 
22881cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATDENSE`, `MatDenseGetArrayWrite()`, `MatDenseGetArray()`, `MatDenseRestoreArray()`, `MatDenseGetArrayRead()`, `MatDenseRestoreArrayRead()`
22896947451fSStefano Zampini @*/
2290ce78bad3SBarry Smith PetscErrorCode MatDenseRestoreArrayWrite(Mat A, PetscScalar *array[]) PeNS
2291d71ae5a4SJacob Faibussowitsch {
22926947451fSStefano Zampini   PetscFunctionBegin;
2293d5ea218eSStefano Zampini   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
22944f572ea9SToby Isaac   if (array) PetscAssertPointer(array, 2);
2295cac4c232SBarry Smith   PetscUseMethod(A, "MatDenseRestoreArrayWrite_C", (Mat, PetscScalar **), (A, array));
22969566063dSJacob Faibussowitsch   PetscCall(PetscObjectStateIncrease((PetscObject)A));
229747d993e7Ssuyashtn #if defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
22986947451fSStefano Zampini   A->offloadmask = PETSC_OFFLOAD_CPU;
22996947451fSStefano Zampini #endif
23003ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
23016947451fSStefano Zampini }
23026947451fSStefano Zampini 
2303cd3f9d89SJunchao Zhang /*@C
2304cd3f9d89SJunchao Zhang   MatDenseGetArrayAndMemType - gives read-write access to the array where the data for a `MATDENSE` matrix is stored
2305cd3f9d89SJunchao Zhang 
2306cd3f9d89SJunchao Zhang   Logically Collective
2307cd3f9d89SJunchao Zhang 
2308cd3f9d89SJunchao Zhang   Input Parameter:
2309fe59aa6dSJacob Faibussowitsch . A - a dense matrix
2310cd3f9d89SJunchao Zhang 
2311cd3f9d89SJunchao Zhang   Output Parameters:
2312cd3f9d89SJunchao Zhang + array - pointer to the data
2313cd3f9d89SJunchao Zhang - mtype - memory type of the returned pointer
2314cd3f9d89SJunchao Zhang 
2315cd3f9d89SJunchao Zhang   Level: intermediate
2316cd3f9d89SJunchao Zhang 
2317fb850c59SBarry Smith   Note:
23182ef1f0ffSBarry Smith   If the matrix is of a device type such as `MATDENSECUDA`, `MATDENSEHIP`, etc.,
23192ef1f0ffSBarry Smith   an array on device is always returned and is guaranteed to contain the matrix's latest data.
23202ef1f0ffSBarry Smith 
23211cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATDENSE`, `MatDenseRestoreArrayAndMemType()`, `MatDenseGetArrayReadAndMemType()`, `MatDenseGetArrayWriteAndMemType()`, `MatDenseGetArrayRead()`,
2322cd3f9d89SJunchao Zhang    `MatDenseRestoreArrayRead()`, `MatDenseGetArrayWrite()`, `MatDenseRestoreArrayWrite()`, `MatSeqAIJGetCSRAndMemType()`
2323cd3f9d89SJunchao Zhang @*/
23245d83a8b1SBarry Smith PetscErrorCode MatDenseGetArrayAndMemType(Mat A, PetscScalar *array[], PetscMemType *mtype)
2325cd3f9d89SJunchao Zhang {
2326cd3f9d89SJunchao Zhang   PetscBool isMPI;
2327cd3f9d89SJunchao Zhang 
2328cd3f9d89SJunchao Zhang   PetscFunctionBegin;
2329cd3f9d89SJunchao Zhang   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
23304f572ea9SToby Isaac   PetscAssertPointer(array, 2);
2331e865de01SJunchao 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 */
2332cd3f9d89SJunchao Zhang   PetscCall(PetscObjectBaseTypeCompare((PetscObject)A, MATMPIDENSE, &isMPI));
2333cd3f9d89SJunchao Zhang   if (isMPI) {
2334cd3f9d89SJunchao Zhang     /* Dispatch here so that the code can be reused for all subclasses of MATDENSE */
2335cd3f9d89SJunchao Zhang     PetscCall(MatDenseGetArrayAndMemType(((Mat_MPIDense *)A->data)->A, array, mtype));
2336cd3f9d89SJunchao Zhang   } else {
2337cd3f9d89SJunchao Zhang     PetscErrorCode (*fptr)(Mat, PetscScalar **, PetscMemType *);
23383ba16761SJacob Faibussowitsch 
23393ba16761SJacob Faibussowitsch     PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatDenseGetArrayAndMemType_C", &fptr));
2340cd3f9d89SJunchao Zhang     if (fptr) {
2341cd3f9d89SJunchao Zhang       PetscCall((*fptr)(A, array, mtype));
2342cd3f9d89SJunchao Zhang     } else {
2343cd3f9d89SJunchao Zhang       PetscUseMethod(A, "MatDenseGetArray_C", (Mat, PetscScalar **), (A, array));
2344cd3f9d89SJunchao Zhang       if (mtype) *mtype = PETSC_MEMTYPE_HOST;
2345cd3f9d89SJunchao Zhang     }
2346cd3f9d89SJunchao Zhang   }
23473ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2348cd3f9d89SJunchao Zhang }
2349cd3f9d89SJunchao Zhang 
2350cd3f9d89SJunchao Zhang /*@C
2351cd3f9d89SJunchao Zhang   MatDenseRestoreArrayAndMemType - returns access to the array that is obtained by `MatDenseGetArrayAndMemType()`
2352cd3f9d89SJunchao Zhang 
2353cd3f9d89SJunchao Zhang   Logically Collective
2354cd3f9d89SJunchao Zhang 
2355cd3f9d89SJunchao Zhang   Input Parameters:
2356fe59aa6dSJacob Faibussowitsch + A     - a dense matrix
2357cd3f9d89SJunchao Zhang - array - pointer to the data
2358cd3f9d89SJunchao Zhang 
2359cd3f9d89SJunchao Zhang   Level: intermediate
2360cd3f9d89SJunchao Zhang 
23611cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATDENSE`, `MatDenseGetArrayAndMemType()`, `MatDenseGetArray()`, `MatDenseGetArrayRead()`, `MatDenseRestoreArrayRead()`, `MatDenseGetArrayWrite()`, `MatDenseRestoreArrayWrite()`
2362cd3f9d89SJunchao Zhang @*/
23635d83a8b1SBarry Smith PetscErrorCode MatDenseRestoreArrayAndMemType(Mat A, PetscScalar *array[])
2364cd3f9d89SJunchao Zhang {
2365cd3f9d89SJunchao Zhang   PetscBool isMPI;
2366cd3f9d89SJunchao Zhang 
2367cd3f9d89SJunchao Zhang   PetscFunctionBegin;
2368cd3f9d89SJunchao Zhang   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
23694f572ea9SToby Isaac   PetscAssertPointer(array, 2);
2370cd3f9d89SJunchao Zhang   PetscCall(PetscObjectBaseTypeCompare((PetscObject)A, MATMPIDENSE, &isMPI));
2371cd3f9d89SJunchao Zhang   if (isMPI) {
2372cd3f9d89SJunchao Zhang     PetscCall(MatDenseRestoreArrayAndMemType(((Mat_MPIDense *)A->data)->A, array));
2373cd3f9d89SJunchao Zhang   } else {
2374cd3f9d89SJunchao Zhang     PetscErrorCode (*fptr)(Mat, PetscScalar **);
23753ba16761SJacob Faibussowitsch 
23763ba16761SJacob Faibussowitsch     PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatDenseRestoreArrayAndMemType_C", &fptr));
2377cd3f9d89SJunchao Zhang     if (fptr) {
2378cd3f9d89SJunchao Zhang       PetscCall((*fptr)(A, array));
2379cd3f9d89SJunchao Zhang     } else {
2380cd3f9d89SJunchao Zhang       PetscUseMethod(A, "MatDenseRestoreArray_C", (Mat, PetscScalar **), (A, array));
2381cd3f9d89SJunchao Zhang     }
2382cd3f9d89SJunchao Zhang     *array = NULL;
2383cd3f9d89SJunchao Zhang   }
2384cd3f9d89SJunchao Zhang   PetscCall(PetscObjectStateIncrease((PetscObject)A));
23853ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2386cd3f9d89SJunchao Zhang }
2387cd3f9d89SJunchao Zhang 
2388cd3f9d89SJunchao Zhang /*@C
2389cd3f9d89SJunchao Zhang   MatDenseGetArrayReadAndMemType - gives read-only access to the array where the data for a `MATDENSE` matrix is stored
2390cd3f9d89SJunchao Zhang 
2391cd3f9d89SJunchao Zhang   Logically Collective
2392cd3f9d89SJunchao Zhang 
2393cd3f9d89SJunchao Zhang   Input Parameter:
2394fe59aa6dSJacob Faibussowitsch . A - a dense matrix
2395cd3f9d89SJunchao Zhang 
2396cd3f9d89SJunchao Zhang   Output Parameters:
2397cd3f9d89SJunchao Zhang + array - pointer to the data
2398cd3f9d89SJunchao Zhang - mtype - memory type of the returned pointer
2399cd3f9d89SJunchao Zhang 
2400cd3f9d89SJunchao Zhang   Level: intermediate
2401cd3f9d89SJunchao Zhang 
2402fb850c59SBarry Smith   Note:
24032ef1f0ffSBarry Smith   If the matrix is of a device type such as `MATDENSECUDA`, `MATDENSEHIP`, etc.,
24042ef1f0ffSBarry Smith   an array on device is always returned and is guaranteed to contain the matrix's latest data.
24052ef1f0ffSBarry Smith 
24061cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATDENSE`, `MatDenseRestoreArrayReadAndMemType()`, `MatDenseGetArrayWriteAndMemType()`,
2407cd3f9d89SJunchao Zhang    `MatDenseGetArrayRead()`, `MatDenseRestoreArrayRead()`, `MatDenseGetArrayWrite()`, `MatDenseRestoreArrayWrite()`, `MatSeqAIJGetCSRAndMemType()`
2408cd3f9d89SJunchao Zhang @*/
24095d83a8b1SBarry Smith PetscErrorCode MatDenseGetArrayReadAndMemType(Mat A, const PetscScalar *array[], PetscMemType *mtype)
2410cd3f9d89SJunchao Zhang {
2411cd3f9d89SJunchao Zhang   PetscBool isMPI;
2412cd3f9d89SJunchao Zhang 
2413cd3f9d89SJunchao Zhang   PetscFunctionBegin;
2414cd3f9d89SJunchao Zhang   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
24154f572ea9SToby Isaac   PetscAssertPointer(array, 2);
2416e865de01SJunchao 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 */
2417cd3f9d89SJunchao Zhang   PetscCall(PetscObjectBaseTypeCompare((PetscObject)A, MATMPIDENSE, &isMPI));
2418cd3f9d89SJunchao Zhang   if (isMPI) { /* Dispatch here so that the code can be reused for all subclasses of MATDENSE */
2419cd3f9d89SJunchao Zhang     PetscCall(MatDenseGetArrayReadAndMemType(((Mat_MPIDense *)A->data)->A, array, mtype));
2420cd3f9d89SJunchao Zhang   } else {
2421cd3f9d89SJunchao Zhang     PetscErrorCode (*fptr)(Mat, const PetscScalar **, PetscMemType *);
24223ba16761SJacob Faibussowitsch 
24233ba16761SJacob Faibussowitsch     PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatDenseGetArrayReadAndMemType_C", &fptr));
2424cd3f9d89SJunchao Zhang     if (fptr) {
2425cd3f9d89SJunchao Zhang       PetscCall((*fptr)(A, array, mtype));
2426cd3f9d89SJunchao Zhang     } else {
24275c0db29aSPierre Jolivet       PetscUseMethod(A, "MatDenseGetArrayRead_C", (Mat, PetscScalar **), (A, (PetscScalar **)array));
2428cd3f9d89SJunchao Zhang       if (mtype) *mtype = PETSC_MEMTYPE_HOST;
2429cd3f9d89SJunchao Zhang     }
2430cd3f9d89SJunchao Zhang   }
24313ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2432cd3f9d89SJunchao Zhang }
2433cd3f9d89SJunchao Zhang 
2434cd3f9d89SJunchao Zhang /*@C
2435cd3f9d89SJunchao Zhang   MatDenseRestoreArrayReadAndMemType - returns access to the array that is obtained by `MatDenseGetArrayReadAndMemType()`
2436cd3f9d89SJunchao Zhang 
2437cd3f9d89SJunchao Zhang   Logically Collective
2438cd3f9d89SJunchao Zhang 
2439cd3f9d89SJunchao Zhang   Input Parameters:
2440fe59aa6dSJacob Faibussowitsch + A     - a dense matrix
2441cd3f9d89SJunchao Zhang - array - pointer to the data
2442cd3f9d89SJunchao Zhang 
2443cd3f9d89SJunchao Zhang   Level: intermediate
2444cd3f9d89SJunchao Zhang 
24451cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATDENSE`, `MatDenseGetArrayReadAndMemType()`, `MatDenseGetArray()`, `MatDenseGetArrayRead()`, `MatDenseRestoreArrayRead()`, `MatDenseGetArrayWrite()`, `MatDenseRestoreArrayWrite()`
2446cd3f9d89SJunchao Zhang @*/
24475d83a8b1SBarry Smith PetscErrorCode MatDenseRestoreArrayReadAndMemType(Mat A, const PetscScalar *array[])
2448cd3f9d89SJunchao Zhang {
2449cd3f9d89SJunchao Zhang   PetscBool isMPI;
2450cd3f9d89SJunchao Zhang 
2451cd3f9d89SJunchao Zhang   PetscFunctionBegin;
2452cd3f9d89SJunchao Zhang   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
24534f572ea9SToby Isaac   PetscAssertPointer(array, 2);
2454cd3f9d89SJunchao Zhang   PetscCall(PetscObjectBaseTypeCompare((PetscObject)A, MATMPIDENSE, &isMPI));
2455cd3f9d89SJunchao Zhang   if (isMPI) {
2456cd3f9d89SJunchao Zhang     PetscCall(MatDenseRestoreArrayReadAndMemType(((Mat_MPIDense *)A->data)->A, array));
2457cd3f9d89SJunchao Zhang   } else {
2458cd3f9d89SJunchao Zhang     PetscErrorCode (*fptr)(Mat, const PetscScalar **);
24593ba16761SJacob Faibussowitsch 
24603ba16761SJacob Faibussowitsch     PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatDenseRestoreArrayReadAndMemType_C", &fptr));
2461cd3f9d89SJunchao Zhang     if (fptr) {
2462cd3f9d89SJunchao Zhang       PetscCall((*fptr)(A, array));
2463cd3f9d89SJunchao Zhang     } else {
24645c0db29aSPierre Jolivet       PetscUseMethod(A, "MatDenseRestoreArrayRead_C", (Mat, PetscScalar **), (A, (PetscScalar **)array));
2465cd3f9d89SJunchao Zhang     }
2466cd3f9d89SJunchao Zhang     *array = NULL;
2467cd3f9d89SJunchao Zhang   }
24683ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2469cd3f9d89SJunchao Zhang }
2470cd3f9d89SJunchao Zhang 
2471cd3f9d89SJunchao Zhang /*@C
2472cd3f9d89SJunchao Zhang   MatDenseGetArrayWriteAndMemType - gives write-only access to the array where the data for a `MATDENSE` matrix is stored
2473cd3f9d89SJunchao Zhang 
2474cd3f9d89SJunchao Zhang   Logically Collective
2475cd3f9d89SJunchao Zhang 
2476cd3f9d89SJunchao Zhang   Input Parameter:
2477fe59aa6dSJacob Faibussowitsch . A - a dense matrix
2478cd3f9d89SJunchao Zhang 
2479cd3f9d89SJunchao Zhang   Output Parameters:
2480cd3f9d89SJunchao Zhang + array - pointer to the data
2481cd3f9d89SJunchao Zhang - mtype - memory type of the returned pointer
2482cd3f9d89SJunchao Zhang 
2483cd3f9d89SJunchao Zhang   Level: intermediate
2484cd3f9d89SJunchao Zhang 
2485fb850c59SBarry Smith   Note:
24862ef1f0ffSBarry Smith   If the matrix is of a device type such as `MATDENSECUDA`, `MATDENSEHIP`, etc.,
24872ef1f0ffSBarry Smith   an array on device is always returned and is guaranteed to contain the matrix's latest data.
24882ef1f0ffSBarry Smith 
24891cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATDENSE`, `MatDenseRestoreArrayWriteAndMemType()`, `MatDenseGetArrayReadAndMemType()`, `MatDenseGetArrayRead()`,
2490cd3f9d89SJunchao Zhang   `MatDenseRestoreArrayRead()`, `MatDenseGetArrayWrite()`, `MatDenseRestoreArrayWrite()`, `MatSeqAIJGetCSRAndMemType()`
2491cd3f9d89SJunchao Zhang @*/
24925d83a8b1SBarry Smith PetscErrorCode MatDenseGetArrayWriteAndMemType(Mat A, PetscScalar *array[], PetscMemType *mtype)
2493cd3f9d89SJunchao Zhang {
2494cd3f9d89SJunchao Zhang   PetscBool isMPI;
2495cd3f9d89SJunchao Zhang 
2496cd3f9d89SJunchao Zhang   PetscFunctionBegin;
2497cd3f9d89SJunchao Zhang   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
24984f572ea9SToby Isaac   PetscAssertPointer(array, 2);
2499e865de01SJunchao 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 */
2500cd3f9d89SJunchao Zhang   PetscCall(PetscObjectBaseTypeCompare((PetscObject)A, MATMPIDENSE, &isMPI));
2501cd3f9d89SJunchao Zhang   if (isMPI) {
2502cd3f9d89SJunchao Zhang     PetscCall(MatDenseGetArrayWriteAndMemType(((Mat_MPIDense *)A->data)->A, array, mtype));
2503cd3f9d89SJunchao Zhang   } else {
2504cd3f9d89SJunchao Zhang     PetscErrorCode (*fptr)(Mat, PetscScalar **, PetscMemType *);
25053ba16761SJacob Faibussowitsch 
25063ba16761SJacob Faibussowitsch     PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatDenseGetArrayWriteAndMemType_C", &fptr));
2507cd3f9d89SJunchao Zhang     if (fptr) {
2508cd3f9d89SJunchao Zhang       PetscCall((*fptr)(A, array, mtype));
2509cd3f9d89SJunchao Zhang     } else {
2510cd3f9d89SJunchao Zhang       PetscUseMethod(A, "MatDenseGetArrayWrite_C", (Mat, PetscScalar **), (A, array));
2511cd3f9d89SJunchao Zhang       if (mtype) *mtype = PETSC_MEMTYPE_HOST;
2512cd3f9d89SJunchao Zhang     }
2513cd3f9d89SJunchao Zhang   }
25143ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2515cd3f9d89SJunchao Zhang }
2516cd3f9d89SJunchao Zhang 
2517cd3f9d89SJunchao Zhang /*@C
2518cd3f9d89SJunchao Zhang   MatDenseRestoreArrayWriteAndMemType - returns access to the array that is obtained by `MatDenseGetArrayReadAndMemType()`
2519cd3f9d89SJunchao Zhang 
2520cd3f9d89SJunchao Zhang   Logically Collective
2521cd3f9d89SJunchao Zhang 
2522cd3f9d89SJunchao Zhang   Input Parameters:
2523fe59aa6dSJacob Faibussowitsch + A     - a dense matrix
2524cd3f9d89SJunchao Zhang - array - pointer to the data
2525cd3f9d89SJunchao Zhang 
2526cd3f9d89SJunchao Zhang   Level: intermediate
2527cd3f9d89SJunchao Zhang 
25281cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATDENSE`, `MatDenseGetArrayWriteAndMemType()`, `MatDenseGetArray()`, `MatDenseGetArrayRead()`, `MatDenseRestoreArrayRead()`, `MatDenseGetArrayWrite()`, `MatDenseRestoreArrayWrite()`
2529cd3f9d89SJunchao Zhang @*/
25305d83a8b1SBarry Smith PetscErrorCode MatDenseRestoreArrayWriteAndMemType(Mat A, PetscScalar *array[])
2531cd3f9d89SJunchao Zhang {
2532cd3f9d89SJunchao Zhang   PetscBool isMPI;
2533cd3f9d89SJunchao Zhang 
2534cd3f9d89SJunchao Zhang   PetscFunctionBegin;
2535cd3f9d89SJunchao Zhang   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
25364f572ea9SToby Isaac   PetscAssertPointer(array, 2);
2537cd3f9d89SJunchao Zhang   PetscCall(PetscObjectBaseTypeCompare((PetscObject)A, MATMPIDENSE, &isMPI));
2538cd3f9d89SJunchao Zhang   if (isMPI) {
2539cd3f9d89SJunchao Zhang     PetscCall(MatDenseRestoreArrayWriteAndMemType(((Mat_MPIDense *)A->data)->A, array));
2540cd3f9d89SJunchao Zhang   } else {
2541cd3f9d89SJunchao Zhang     PetscErrorCode (*fptr)(Mat, PetscScalar **);
25423ba16761SJacob Faibussowitsch 
25433ba16761SJacob Faibussowitsch     PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatDenseRestoreArrayWriteAndMemType_C", &fptr));
2544cd3f9d89SJunchao Zhang     if (fptr) {
2545cd3f9d89SJunchao Zhang       PetscCall((*fptr)(A, array));
2546cd3f9d89SJunchao Zhang     } else {
2547cd3f9d89SJunchao Zhang       PetscUseMethod(A, "MatDenseRestoreArrayWrite_C", (Mat, PetscScalar **), (A, array));
2548cd3f9d89SJunchao Zhang     }
2549cd3f9d89SJunchao Zhang     *array = NULL;
2550cd3f9d89SJunchao Zhang   }
2551cd3f9d89SJunchao Zhang   PetscCall(PetscObjectStateIncrease((PetscObject)A));
25523ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2553cd3f9d89SJunchao Zhang }
2554cd3f9d89SJunchao Zhang 
2555d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatCreateSubMatrix_SeqDense(Mat A, IS isrow, IS iscol, MatReuse scall, Mat *B)
2556d71ae5a4SJacob Faibussowitsch {
2557c0bbcb79SLois Curfman McInnes   Mat_SeqDense   *mat = (Mat_SeqDense *)A->data;
2558bf5a80bcSToby Isaac   PetscInt        i, j, nrows, ncols, ldb;
25595d0c19d7SBarry Smith   const PetscInt *irow, *icol;
256087828ca2SBarry Smith   PetscScalar    *av, *bv, *v = mat->v;
25610754003eSLois Curfman McInnes   Mat             newmat;
25620754003eSLois Curfman McInnes 
25633a40ed3dSBarry Smith   PetscFunctionBegin;
25649566063dSJacob Faibussowitsch   PetscCall(ISGetIndices(isrow, &irow));
25659566063dSJacob Faibussowitsch   PetscCall(ISGetIndices(iscol, &icol));
25669566063dSJacob Faibussowitsch   PetscCall(ISGetLocalSize(isrow, &nrows));
25679566063dSJacob Faibussowitsch   PetscCall(ISGetLocalSize(iscol, &ncols));
25680754003eSLois Curfman McInnes 
2569182d2002SSatish Balay   /* Check submatrixcall */
2570182d2002SSatish Balay   if (scall == MAT_REUSE_MATRIX) {
257113f74950SBarry Smith     PetscInt n_cols, n_rows;
25729566063dSJacob Faibussowitsch     PetscCall(MatGetSize(*B, &n_rows, &n_cols));
257321a2c019SBarry Smith     if (n_rows != nrows || n_cols != ncols) {
2574f746d493SDmitry Karpeev       /* resize the result matrix to match number of requested rows/columns */
25759566063dSJacob Faibussowitsch       PetscCall(MatSetSizes(*B, nrows, ncols, nrows, ncols));
257621a2c019SBarry Smith     }
2577182d2002SSatish Balay     newmat = *B;
2578182d2002SSatish Balay   } else {
25790754003eSLois Curfman McInnes     /* Create and fill new matrix */
25809566063dSJacob Faibussowitsch     PetscCall(MatCreate(PetscObjectComm((PetscObject)A), &newmat));
25819566063dSJacob Faibussowitsch     PetscCall(MatSetSizes(newmat, nrows, ncols, nrows, ncols));
25829566063dSJacob Faibussowitsch     PetscCall(MatSetType(newmat, ((PetscObject)A)->type_name));
25839566063dSJacob Faibussowitsch     PetscCall(MatSeqDenseSetPreallocation(newmat, NULL));
2584182d2002SSatish Balay   }
2585182d2002SSatish Balay 
2586182d2002SSatish Balay   /* Now extract the data pointers and do the copy,column at a time */
25879566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArray(newmat, &bv));
25889566063dSJacob Faibussowitsch   PetscCall(MatDenseGetLDA(newmat, &ldb));
2589182d2002SSatish Balay   for (i = 0; i < ncols; i++) {
25906de62eeeSBarry Smith     av = v + mat->lda * icol[i];
2591ca15aa20SStefano Zampini     for (j = 0; j < nrows; j++) bv[j] = av[irow[j]];
2592bf5a80bcSToby Isaac     bv += ldb;
25930754003eSLois Curfman McInnes   }
25949566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArray(newmat, &bv));
2595182d2002SSatish Balay 
2596182d2002SSatish Balay   /* Assemble the matrices so that the correct flags are set */
25979566063dSJacob Faibussowitsch   PetscCall(MatAssemblyBegin(newmat, MAT_FINAL_ASSEMBLY));
25989566063dSJacob Faibussowitsch   PetscCall(MatAssemblyEnd(newmat, MAT_FINAL_ASSEMBLY));
25990754003eSLois Curfman McInnes 
26000754003eSLois Curfman McInnes   /* Free work space */
26019566063dSJacob Faibussowitsch   PetscCall(ISRestoreIndices(isrow, &irow));
26029566063dSJacob Faibussowitsch   PetscCall(ISRestoreIndices(iscol, &icol));
2603182d2002SSatish Balay   *B = newmat;
26043ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
26050754003eSLois Curfman McInnes }
26060754003eSLois Curfman McInnes 
2607d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatCreateSubMatrices_SeqDense(Mat A, PetscInt n, const IS irow[], const IS icol[], MatReuse scall, Mat *B[])
2608d71ae5a4SJacob Faibussowitsch {
260913f74950SBarry Smith   PetscInt i;
2610905e6a2fSBarry Smith 
26113a40ed3dSBarry Smith   PetscFunctionBegin;
261248a46eb9SPierre Jolivet   if (scall == MAT_INITIAL_MATRIX) PetscCall(PetscCalloc1(n, B));
2613905e6a2fSBarry Smith 
261448a46eb9SPierre Jolivet   for (i = 0; i < n; i++) PetscCall(MatCreateSubMatrix_SeqDense(A, irow[i], icol[i], scall, &(*B)[i]));
26153ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2616905e6a2fSBarry Smith }
2617905e6a2fSBarry Smith 
2618d71ae5a4SJacob Faibussowitsch PetscErrorCode MatCopy_SeqDense(Mat A, Mat B, MatStructure str)
2619d71ae5a4SJacob Faibussowitsch {
26204b0e389bSBarry Smith   Mat_SeqDense      *a = (Mat_SeqDense *)A->data, *b = (Mat_SeqDense *)B->data;
2621ca15aa20SStefano Zampini   const PetscScalar *va;
2622ca15aa20SStefano Zampini   PetscScalar       *vb;
2623d0f46423SBarry Smith   PetscInt           lda1 = a->lda, lda2 = b->lda, m = A->rmap->n, n = A->cmap->n, j;
26243a40ed3dSBarry Smith 
26253a40ed3dSBarry Smith   PetscFunctionBegin;
262633f4a19fSKris Buschelman   /* If the two matrices don't have the same copy implementation, they aren't compatible for fast copy. */
262733f4a19fSKris Buschelman   if (A->ops->copy != B->ops->copy) {
26289566063dSJacob Faibussowitsch     PetscCall(MatCopy_Basic(A, B, str));
26293ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
26303a40ed3dSBarry Smith   }
2631aed4548fSBarry Smith   PetscCheck(m == B->rmap->n && n == B->cmap->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "size(B) != size(A)");
26329566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArrayRead(A, &va));
26339566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArray(B, &vb));
2634a5ce6ee0Svictorle   if (lda1 > m || lda2 > m) {
263548a46eb9SPierre Jolivet     for (j = 0; j < n; j++) PetscCall(PetscArraycpy(vb + j * lda2, va + j * lda1, m));
2636a5ce6ee0Svictorle   } else {
26379566063dSJacob Faibussowitsch     PetscCall(PetscArraycpy(vb, va, A->rmap->n * A->cmap->n));
2638a5ce6ee0Svictorle   }
26399566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArray(B, &vb));
26409566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArrayRead(A, &va));
26419566063dSJacob Faibussowitsch   PetscCall(MatAssemblyBegin(B, MAT_FINAL_ASSEMBLY));
26429566063dSJacob Faibussowitsch   PetscCall(MatAssemblyEnd(B, MAT_FINAL_ASSEMBLY));
26433ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2644273d9f13SBarry Smith }
2645273d9f13SBarry Smith 
2646d71ae5a4SJacob Faibussowitsch PetscErrorCode MatSetUp_SeqDense(Mat A)
2647d71ae5a4SJacob Faibussowitsch {
2648273d9f13SBarry Smith   PetscFunctionBegin;
26499566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetUp(A->rmap));
26509566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetUp(A->cmap));
265148a46eb9SPierre Jolivet   if (!A->preallocated) PetscCall(MatSeqDenseSetPreallocation(A, NULL));
26523ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
26534b0e389bSBarry Smith }
26544b0e389bSBarry Smith 
2655*3853def2SToby Isaac PetscErrorCode MatConjugate_SeqDense(Mat A)
2656d71ae5a4SJacob Faibussowitsch {
26574396437dSToby Isaac   Mat_SeqDense *mat = (Mat_SeqDense *)A->data;
265806c5243aSJose E. Roman   PetscInt      i, j;
26594396437dSToby Isaac   PetscInt      min = PetscMin(A->rmap->n, A->cmap->n);
2660ca15aa20SStefano Zampini   PetscScalar  *aa;
2661ba337c44SJed Brown 
2662ba337c44SJed Brown   PetscFunctionBegin;
26639566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArray(A, &aa));
266406c5243aSJose E. Roman   for (j = 0; j < A->cmap->n; j++) {
266506c5243aSJose E. Roman     for (i = 0; i < A->rmap->n; i++) aa[i + j * mat->lda] = PetscConj(aa[i + j * mat->lda]);
266606c5243aSJose E. Roman   }
26679566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArray(A, &aa));
26689371c9d4SSatish Balay   if (mat->tau)
26699371c9d4SSatish Balay     for (i = 0; i < min; i++) mat->tau[i] = PetscConj(mat->tau[i]);
26703ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2671ba337c44SJed Brown }
2672ba337c44SJed Brown 
2673d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatRealPart_SeqDense(Mat A)
2674d71ae5a4SJacob Faibussowitsch {
267506c5243aSJose E. Roman   Mat_SeqDense *mat = (Mat_SeqDense *)A->data;
267606c5243aSJose E. Roman   PetscInt      i, j;
2677ca15aa20SStefano Zampini   PetscScalar  *aa;
2678ba337c44SJed Brown 
2679ba337c44SJed Brown   PetscFunctionBegin;
26809566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArray(A, &aa));
268106c5243aSJose E. Roman   for (j = 0; j < A->cmap->n; j++) {
268206c5243aSJose E. Roman     for (i = 0; i < A->rmap->n; i++) aa[i + j * mat->lda] = PetscRealPart(aa[i + j * mat->lda]);
268306c5243aSJose E. Roman   }
26849566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArray(A, &aa));
26853ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2686ba337c44SJed Brown }
2687ba337c44SJed Brown 
2688d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatImaginaryPart_SeqDense(Mat A)
2689d71ae5a4SJacob Faibussowitsch {
269006c5243aSJose E. Roman   Mat_SeqDense *mat = (Mat_SeqDense *)A->data;
269106c5243aSJose E. Roman   PetscInt      i, j;
2692ca15aa20SStefano Zampini   PetscScalar  *aa;
2693ba337c44SJed Brown 
2694ba337c44SJed Brown   PetscFunctionBegin;
26959566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArray(A, &aa));
269606c5243aSJose E. Roman   for (j = 0; j < A->cmap->n; j++) {
269706c5243aSJose E. Roman     for (i = 0; i < A->rmap->n; i++) aa[i + j * mat->lda] = PetscImaginaryPart(aa[i + j * mat->lda]);
269806c5243aSJose E. Roman   }
26999566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArray(A, &aa));
27003ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2701ba337c44SJed Brown }
2702284134d9SBarry Smith 
2703d71ae5a4SJacob Faibussowitsch PetscErrorCode MatMatMultSymbolic_SeqDense_SeqDense(Mat A, Mat B, PetscReal fill, Mat C)
2704d71ae5a4SJacob Faibussowitsch {
2705d0f46423SBarry Smith   PetscInt  m = A->rmap->n, n = B->cmap->n;
270647d993e7Ssuyashtn   PetscBool cisdense = PETSC_FALSE;
2707a9fe9ddaSSatish Balay 
2708ee16a9a1SHong Zhang   PetscFunctionBegin;
27099566063dSJacob Faibussowitsch   PetscCall(MatSetSizes(C, m, n, m, n));
271047d993e7Ssuyashtn #if defined(PETSC_HAVE_CUDA)
27119566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompareAny((PetscObject)C, &cisdense, MATSEQDENSE, MATSEQDENSECUDA, ""));
271247d993e7Ssuyashtn #endif
271347d993e7Ssuyashtn #if defined(PETSC_HAVE_HIP)
271447d993e7Ssuyashtn   PetscCall(PetscObjectTypeCompareAny((PetscObject)C, &cisdense, MATSEQDENSE, MATSEQDENSEHIP, ""));
271547d993e7Ssuyashtn #endif
27167a3c3d58SStefano Zampini   if (!cisdense) {
27177a3c3d58SStefano Zampini     PetscBool flg;
27187a3c3d58SStefano Zampini 
27199566063dSJacob Faibussowitsch     PetscCall(PetscObjectTypeCompare((PetscObject)B, ((PetscObject)A)->type_name, &flg));
27209566063dSJacob Faibussowitsch     PetscCall(MatSetType(C, flg ? ((PetscObject)A)->type_name : MATDENSE));
27217a3c3d58SStefano Zampini   }
27229566063dSJacob Faibussowitsch   PetscCall(MatSetUp(C));
27233ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2724ee16a9a1SHong Zhang }
2725a9fe9ddaSSatish Balay 
2726d71ae5a4SJacob Faibussowitsch PetscErrorCode MatMatMultNumeric_SeqDense_SeqDense(Mat A, Mat B, Mat C)
2727d71ae5a4SJacob Faibussowitsch {
27286718818eSStefano Zampini   Mat_SeqDense      *a = (Mat_SeqDense *)A->data, *b = (Mat_SeqDense *)B->data, *c = (Mat_SeqDense *)C->data;
27290805154bSBarry Smith   PetscBLASInt       m, n, k;
2730ca15aa20SStefano Zampini   const PetscScalar *av, *bv;
2731ca15aa20SStefano Zampini   PetscScalar       *cv;
2732a9fe9ddaSSatish Balay   PetscScalar        _DOne = 1.0, _DZero = 0.0;
2733a9fe9ddaSSatish Balay 
2734a9fe9ddaSSatish Balay   PetscFunctionBegin;
27359566063dSJacob Faibussowitsch   PetscCall(PetscBLASIntCast(C->rmap->n, &m));
27369566063dSJacob Faibussowitsch   PetscCall(PetscBLASIntCast(C->cmap->n, &n));
27379566063dSJacob Faibussowitsch   PetscCall(PetscBLASIntCast(A->cmap->n, &k));
27383ba16761SJacob Faibussowitsch   if (!m || !n || !k) PetscFunctionReturn(PETSC_SUCCESS);
27399566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArrayRead(A, &av));
27409566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArrayRead(B, &bv));
27419566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArrayWrite(C, &cv));
2742792fecdfSBarry Smith   PetscCallBLAS("BLASgemm", BLASgemm_("N", "N", &m, &n, &k, &_DOne, av, &a->lda, bv, &b->lda, &_DZero, cv, &c->lda));
27439566063dSJacob Faibussowitsch   PetscCall(PetscLogFlops(1.0 * m * n * k + 1.0 * m * n * (k - 1)));
27449566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArrayRead(A, &av));
27459566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArrayRead(B, &bv));
27469566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArrayWrite(C, &cv));
27473ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2748a9fe9ddaSSatish Balay }
2749a9fe9ddaSSatish Balay 
2750d71ae5a4SJacob Faibussowitsch PetscErrorCode MatMatTransposeMultSymbolic_SeqDense_SeqDense(Mat A, Mat B, PetscReal fill, Mat C)
2751d71ae5a4SJacob Faibussowitsch {
275269f65d41SStefano Zampini   PetscInt  m = A->rmap->n, n = B->rmap->n;
275347d993e7Ssuyashtn   PetscBool cisdense = PETSC_FALSE;
275469f65d41SStefano Zampini 
275569f65d41SStefano Zampini   PetscFunctionBegin;
27569566063dSJacob Faibussowitsch   PetscCall(MatSetSizes(C, m, n, m, n));
275747d993e7Ssuyashtn #if defined(PETSC_HAVE_CUDA)
27589566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompareAny((PetscObject)C, &cisdense, MATSEQDENSE, MATSEQDENSECUDA, ""));
275947d993e7Ssuyashtn #endif
276047d993e7Ssuyashtn #if defined(PETSC_HAVE_HIP)
276147d993e7Ssuyashtn   PetscCall(PetscObjectTypeCompareAny((PetscObject)C, &cisdense, MATSEQDENSE, MATSEQDENSEHIP, ""));
276247d993e7Ssuyashtn #endif
27637a3c3d58SStefano Zampini   if (!cisdense) {
27647a3c3d58SStefano Zampini     PetscBool flg;
27657a3c3d58SStefano Zampini 
27669566063dSJacob Faibussowitsch     PetscCall(PetscObjectTypeCompare((PetscObject)B, ((PetscObject)A)->type_name, &flg));
27679566063dSJacob Faibussowitsch     PetscCall(MatSetType(C, flg ? ((PetscObject)A)->type_name : MATDENSE));
27687a3c3d58SStefano Zampini   }
27699566063dSJacob Faibussowitsch   PetscCall(MatSetUp(C));
27703ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
277169f65d41SStefano Zampini }
277269f65d41SStefano Zampini 
2773d71ae5a4SJacob Faibussowitsch PetscErrorCode MatMatTransposeMultNumeric_SeqDense_SeqDense(Mat A, Mat B, Mat C)
2774d71ae5a4SJacob Faibussowitsch {
277569f65d41SStefano Zampini   Mat_SeqDense      *a = (Mat_SeqDense *)A->data;
277669f65d41SStefano Zampini   Mat_SeqDense      *b = (Mat_SeqDense *)B->data;
277769f65d41SStefano Zampini   Mat_SeqDense      *c = (Mat_SeqDense *)C->data;
27786718818eSStefano Zampini   const PetscScalar *av, *bv;
27796718818eSStefano Zampini   PetscScalar       *cv;
278069f65d41SStefano Zampini   PetscBLASInt       m, n, k;
278169f65d41SStefano Zampini   PetscScalar        _DOne = 1.0, _DZero = 0.0;
278269f65d41SStefano Zampini 
278369f65d41SStefano Zampini   PetscFunctionBegin;
27849566063dSJacob Faibussowitsch   PetscCall(PetscBLASIntCast(C->rmap->n, &m));
27859566063dSJacob Faibussowitsch   PetscCall(PetscBLASIntCast(C->cmap->n, &n));
27869566063dSJacob Faibussowitsch   PetscCall(PetscBLASIntCast(A->cmap->n, &k));
27873ba16761SJacob Faibussowitsch   if (!m || !n || !k) PetscFunctionReturn(PETSC_SUCCESS);
27889566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArrayRead(A, &av));
27899566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArrayRead(B, &bv));
27909566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArrayWrite(C, &cv));
2791792fecdfSBarry Smith   PetscCallBLAS("BLASgemm", BLASgemm_("N", "T", &m, &n, &k, &_DOne, av, &a->lda, bv, &b->lda, &_DZero, cv, &c->lda));
27929566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArrayRead(A, &av));
27939566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArrayRead(B, &bv));
27949566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArrayWrite(C, &cv));
27959566063dSJacob Faibussowitsch   PetscCall(PetscLogFlops(1.0 * m * n * k + 1.0 * m * n * (k - 1)));
27963ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
279769f65d41SStefano Zampini }
279869f65d41SStefano Zampini 
2799d71ae5a4SJacob Faibussowitsch PetscErrorCode MatTransposeMatMultSymbolic_SeqDense_SeqDense(Mat A, Mat B, PetscReal fill, Mat C)
2800d71ae5a4SJacob Faibussowitsch {
2801d0f46423SBarry Smith   PetscInt  m = A->cmap->n, n = B->cmap->n;
280247d993e7Ssuyashtn   PetscBool cisdense = PETSC_FALSE;
2803a9fe9ddaSSatish Balay 
2804ee16a9a1SHong Zhang   PetscFunctionBegin;
28059566063dSJacob Faibussowitsch   PetscCall(MatSetSizes(C, m, n, m, n));
280647d993e7Ssuyashtn #if defined(PETSC_HAVE_CUDA)
28079566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompareAny((PetscObject)C, &cisdense, MATSEQDENSE, MATSEQDENSECUDA, ""));
280847d993e7Ssuyashtn #endif
280947d993e7Ssuyashtn #if defined(PETSC_HAVE_HIP)
281047d993e7Ssuyashtn   PetscCall(PetscObjectTypeCompareAny((PetscObject)C, &cisdense, MATSEQDENSE, MATSEQDENSEHIP, ""));
281147d993e7Ssuyashtn #endif
28127a3c3d58SStefano Zampini   if (!cisdense) {
28137a3c3d58SStefano Zampini     PetscBool flg;
28147a3c3d58SStefano Zampini 
28159566063dSJacob Faibussowitsch     PetscCall(PetscObjectTypeCompare((PetscObject)B, ((PetscObject)A)->type_name, &flg));
28169566063dSJacob Faibussowitsch     PetscCall(MatSetType(C, flg ? ((PetscObject)A)->type_name : MATDENSE));
28177a3c3d58SStefano Zampini   }
28189566063dSJacob Faibussowitsch   PetscCall(MatSetUp(C));
28193ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2820ee16a9a1SHong Zhang }
2821a9fe9ddaSSatish Balay 
2822d71ae5a4SJacob Faibussowitsch PetscErrorCode MatTransposeMatMultNumeric_SeqDense_SeqDense(Mat A, Mat B, Mat C)
2823d71ae5a4SJacob Faibussowitsch {
2824a9fe9ddaSSatish Balay   Mat_SeqDense      *a = (Mat_SeqDense *)A->data;
2825a9fe9ddaSSatish Balay   Mat_SeqDense      *b = (Mat_SeqDense *)B->data;
2826a9fe9ddaSSatish Balay   Mat_SeqDense      *c = (Mat_SeqDense *)C->data;
28276718818eSStefano Zampini   const PetscScalar *av, *bv;
28286718818eSStefano Zampini   PetscScalar       *cv;
28290805154bSBarry Smith   PetscBLASInt       m, n, k;
2830a9fe9ddaSSatish Balay   PetscScalar        _DOne = 1.0, _DZero = 0.0;
2831a9fe9ddaSSatish Balay 
2832a9fe9ddaSSatish Balay   PetscFunctionBegin;
28339566063dSJacob Faibussowitsch   PetscCall(PetscBLASIntCast(C->rmap->n, &m));
28349566063dSJacob Faibussowitsch   PetscCall(PetscBLASIntCast(C->cmap->n, &n));
28359566063dSJacob Faibussowitsch   PetscCall(PetscBLASIntCast(A->rmap->n, &k));
28363ba16761SJacob Faibussowitsch   if (!m || !n || !k) PetscFunctionReturn(PETSC_SUCCESS);
28379566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArrayRead(A, &av));
28389566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArrayRead(B, &bv));
28399566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArrayWrite(C, &cv));
2840792fecdfSBarry Smith   PetscCallBLAS("BLASgemm", BLASgemm_("T", "N", &m, &n, &k, &_DOne, av, &a->lda, bv, &b->lda, &_DZero, cv, &c->lda));
28419566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArrayRead(A, &av));
28429566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArrayRead(B, &bv));
28439566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArrayWrite(C, &cv));
28449566063dSJacob Faibussowitsch   PetscCall(PetscLogFlops(1.0 * m * n * k + 1.0 * m * n * (k - 1)));
28453ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2846a9fe9ddaSSatish Balay }
2847985db425SBarry Smith 
2848d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatProductSetFromOptions_SeqDense_AB(Mat C)
2849d71ae5a4SJacob Faibussowitsch {
28504222ddf1SHong Zhang   PetscFunctionBegin;
28514222ddf1SHong Zhang   C->ops->matmultsymbolic = MatMatMultSymbolic_SeqDense_SeqDense;
28524222ddf1SHong Zhang   C->ops->productsymbolic = MatProductSymbolic_AB;
28533ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
28544222ddf1SHong Zhang }
28554222ddf1SHong Zhang 
2856d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatProductSetFromOptions_SeqDense_AtB(Mat C)
2857d71ae5a4SJacob Faibussowitsch {
28584222ddf1SHong Zhang   PetscFunctionBegin;
28594222ddf1SHong Zhang   C->ops->transposematmultsymbolic = MatTransposeMatMultSymbolic_SeqDense_SeqDense;
28604222ddf1SHong Zhang   C->ops->productsymbolic          = MatProductSymbolic_AtB;
28613ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
28624222ddf1SHong Zhang }
28634222ddf1SHong Zhang 
2864d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatProductSetFromOptions_SeqDense_ABt(Mat C)
2865d71ae5a4SJacob Faibussowitsch {
28664222ddf1SHong Zhang   PetscFunctionBegin;
28674222ddf1SHong Zhang   C->ops->mattransposemultsymbolic = MatMatTransposeMultSymbolic_SeqDense_SeqDense;
28684222ddf1SHong Zhang   C->ops->productsymbolic          = MatProductSymbolic_ABt;
28693ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
28704222ddf1SHong Zhang }
28714222ddf1SHong Zhang 
2872d71ae5a4SJacob Faibussowitsch PETSC_INTERN PetscErrorCode MatProductSetFromOptions_SeqDense(Mat C)
2873d71ae5a4SJacob Faibussowitsch {
28744222ddf1SHong Zhang   Mat_Product *product = C->product;
28754222ddf1SHong Zhang 
28764222ddf1SHong Zhang   PetscFunctionBegin;
28774222ddf1SHong Zhang   switch (product->type) {
2878d71ae5a4SJacob Faibussowitsch   case MATPRODUCT_AB:
2879d71ae5a4SJacob Faibussowitsch     PetscCall(MatProductSetFromOptions_SeqDense_AB(C));
2880d71ae5a4SJacob Faibussowitsch     break;
2881d71ae5a4SJacob Faibussowitsch   case MATPRODUCT_AtB:
2882d71ae5a4SJacob Faibussowitsch     PetscCall(MatProductSetFromOptions_SeqDense_AtB(C));
2883d71ae5a4SJacob Faibussowitsch     break;
2884d71ae5a4SJacob Faibussowitsch   case MATPRODUCT_ABt:
2885d71ae5a4SJacob Faibussowitsch     PetscCall(MatProductSetFromOptions_SeqDense_ABt(C));
2886d71ae5a4SJacob Faibussowitsch     break;
2887d71ae5a4SJacob Faibussowitsch   default:
2888d71ae5a4SJacob Faibussowitsch     break;
28894222ddf1SHong Zhang   }
28903ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
28914222ddf1SHong Zhang }
28924222ddf1SHong Zhang 
2893d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatGetRowMax_SeqDense(Mat A, Vec v, PetscInt idx[])
2894d71ae5a4SJacob Faibussowitsch {
2895985db425SBarry Smith   Mat_SeqDense      *a = (Mat_SeqDense *)A->data;
2896d0f46423SBarry Smith   PetscInt           i, j, m = A->rmap->n, n = A->cmap->n, p;
2897985db425SBarry Smith   PetscScalar       *x;
2898ca15aa20SStefano Zampini   const PetscScalar *aa;
2899985db425SBarry Smith 
2900985db425SBarry Smith   PetscFunctionBegin;
290128b400f6SJacob Faibussowitsch   PetscCheck(!A->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
29029566063dSJacob Faibussowitsch   PetscCall(VecGetArray(v, &x));
29039566063dSJacob Faibussowitsch   PetscCall(VecGetLocalSize(v, &p));
29049566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArrayRead(A, &aa));
290508401ef6SPierre Jolivet   PetscCheck(p == A->rmap->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Nonconforming matrix and vector");
2906985db425SBarry Smith   for (i = 0; i < m; i++) {
29079371c9d4SSatish Balay     x[i] = aa[i];
29089371c9d4SSatish Balay     if (idx) idx[i] = 0;
2909985db425SBarry Smith     for (j = 1; j < n; j++) {
29109371c9d4SSatish Balay       if (PetscRealPart(x[i]) < PetscRealPart(aa[i + a->lda * j])) {
29119371c9d4SSatish Balay         x[i] = aa[i + a->lda * j];
29129371c9d4SSatish Balay         if (idx) idx[i] = j;
29139371c9d4SSatish Balay       }
2914985db425SBarry Smith     }
2915985db425SBarry Smith   }
29169566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArrayRead(A, &aa));
29179566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(v, &x));
29183ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2919985db425SBarry Smith }
2920985db425SBarry Smith 
2921d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatGetRowMaxAbs_SeqDense(Mat A, Vec v, PetscInt idx[])
2922d71ae5a4SJacob Faibussowitsch {
2923985db425SBarry Smith   Mat_SeqDense      *a = (Mat_SeqDense *)A->data;
2924d0f46423SBarry Smith   PetscInt           i, j, m = A->rmap->n, n = A->cmap->n, p;
2925985db425SBarry Smith   PetscScalar       *x;
2926985db425SBarry Smith   PetscReal          atmp;
2927ca15aa20SStefano Zampini   const PetscScalar *aa;
2928985db425SBarry Smith 
2929985db425SBarry Smith   PetscFunctionBegin;
293028b400f6SJacob Faibussowitsch   PetscCheck(!A->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
29319566063dSJacob Faibussowitsch   PetscCall(VecGetArray(v, &x));
29329566063dSJacob Faibussowitsch   PetscCall(VecGetLocalSize(v, &p));
29339566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArrayRead(A, &aa));
293408401ef6SPierre Jolivet   PetscCheck(p == A->rmap->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Nonconforming matrix and vector");
2935985db425SBarry Smith   for (i = 0; i < m; i++) {
29369189402eSHong Zhang     x[i] = PetscAbsScalar(aa[i]);
2937985db425SBarry Smith     for (j = 1; j < n; j++) {
2938ca15aa20SStefano Zampini       atmp = PetscAbsScalar(aa[i + a->lda * j]);
29399371c9d4SSatish Balay       if (PetscAbsScalar(x[i]) < atmp) {
29409371c9d4SSatish Balay         x[i] = atmp;
29419371c9d4SSatish Balay         if (idx) idx[i] = j;
29429371c9d4SSatish Balay       }
2943985db425SBarry Smith     }
2944985db425SBarry Smith   }
29459566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArrayRead(A, &aa));
29469566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(v, &x));
29473ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2948985db425SBarry Smith }
2949985db425SBarry Smith 
2950d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatGetRowMin_SeqDense(Mat A, Vec v, PetscInt idx[])
2951d71ae5a4SJacob Faibussowitsch {
2952985db425SBarry Smith   Mat_SeqDense      *a = (Mat_SeqDense *)A->data;
2953d0f46423SBarry Smith   PetscInt           i, j, m = A->rmap->n, n = A->cmap->n, p;
2954985db425SBarry Smith   PetscScalar       *x;
2955ca15aa20SStefano Zampini   const PetscScalar *aa;
2956985db425SBarry Smith 
2957985db425SBarry Smith   PetscFunctionBegin;
295828b400f6SJacob Faibussowitsch   PetscCheck(!A->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
29599566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArrayRead(A, &aa));
29609566063dSJacob Faibussowitsch   PetscCall(VecGetArray(v, &x));
29619566063dSJacob Faibussowitsch   PetscCall(VecGetLocalSize(v, &p));
296208401ef6SPierre Jolivet   PetscCheck(p == A->rmap->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Nonconforming matrix and vector");
2963985db425SBarry Smith   for (i = 0; i < m; i++) {
29649371c9d4SSatish Balay     x[i] = aa[i];
29659371c9d4SSatish Balay     if (idx) idx[i] = 0;
2966985db425SBarry Smith     for (j = 1; j < n; j++) {
29679371c9d4SSatish Balay       if (PetscRealPart(x[i]) > PetscRealPart(aa[i + a->lda * j])) {
29689371c9d4SSatish Balay         x[i] = aa[i + a->lda * j];
29699371c9d4SSatish Balay         if (idx) idx[i] = j;
29709371c9d4SSatish Balay       }
2971985db425SBarry Smith     }
2972985db425SBarry Smith   }
29739566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(v, &x));
29749566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArrayRead(A, &aa));
29753ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2976985db425SBarry Smith }
2977985db425SBarry Smith 
2978d71ae5a4SJacob Faibussowitsch PetscErrorCode MatGetColumnVector_SeqDense(Mat A, Vec v, PetscInt col)
2979d71ae5a4SJacob Faibussowitsch {
29808d0534beSBarry Smith   Mat_SeqDense      *a = (Mat_SeqDense *)A->data;
29818d0534beSBarry Smith   PetscScalar       *x;
2982ca15aa20SStefano Zampini   const PetscScalar *aa;
29838d0534beSBarry Smith 
29848d0534beSBarry Smith   PetscFunctionBegin;
298528b400f6SJacob Faibussowitsch   PetscCheck(!A->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
29869566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArrayRead(A, &aa));
29879566063dSJacob Faibussowitsch   PetscCall(VecGetArray(v, &x));
29889566063dSJacob Faibussowitsch   PetscCall(PetscArraycpy(x, aa + col * a->lda, A->rmap->n));
29899566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(v, &x));
29909566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArrayRead(A, &aa));
29913ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
29928d0534beSBarry Smith }
29938d0534beSBarry Smith 
2994d71ae5a4SJacob Faibussowitsch PETSC_INTERN PetscErrorCode MatGetColumnReductions_SeqDense(Mat A, PetscInt type, PetscReal *reductions)
2995d71ae5a4SJacob Faibussowitsch {
29960716a85fSBarry Smith   PetscInt           i, j, m, n;
29971683a169SBarry Smith   const PetscScalar *a;
29980716a85fSBarry Smith 
29990716a85fSBarry Smith   PetscFunctionBegin;
30009566063dSJacob Faibussowitsch   PetscCall(MatGetSize(A, &m, &n));
30019566063dSJacob Faibussowitsch   PetscCall(PetscArrayzero(reductions, n));
30029566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArrayRead(A, &a));
3003857cbf51SRichard Tran Mills   if (type == NORM_2) {
30040716a85fSBarry Smith     for (i = 0; i < n; i++) {
3005ad540459SPierre Jolivet       for (j = 0; j < m; j++) reductions[i] += PetscAbsScalar(a[j] * a[j]);
300616cd844bSPierre Jolivet       a = PetscSafePointerPlusOffset(a, m);
30070716a85fSBarry Smith     }
3008857cbf51SRichard Tran Mills   } else if (type == NORM_1) {
30090716a85fSBarry Smith     for (i = 0; i < n; i++) {
3010ad540459SPierre Jolivet       for (j = 0; j < m; j++) reductions[i] += PetscAbsScalar(a[j]);
301116cd844bSPierre Jolivet       a = PetscSafePointerPlusOffset(a, m);
30120716a85fSBarry Smith     }
3013857cbf51SRichard Tran Mills   } else if (type == NORM_INFINITY) {
30140716a85fSBarry Smith     for (i = 0; i < n; i++) {
3015ad540459SPierre Jolivet       for (j = 0; j < m; j++) reductions[i] = PetscMax(PetscAbsScalar(a[j]), reductions[i]);
301616cd844bSPierre Jolivet       a = PetscSafePointerPlusOffset(a, m);
30170716a85fSBarry Smith     }
3018857cbf51SRichard Tran Mills   } else if (type == REDUCTION_SUM_REALPART || type == REDUCTION_MEAN_REALPART) {
3019a873a8cdSSam Reynolds     for (i = 0; i < n; i++) {
3020ad540459SPierre Jolivet       for (j = 0; j < m; j++) reductions[i] += PetscRealPart(a[j]);
302116cd844bSPierre Jolivet       a = PetscSafePointerPlusOffset(a, m);
3022a873a8cdSSam Reynolds     }
3023857cbf51SRichard Tran Mills   } else if (type == REDUCTION_SUM_IMAGINARYPART || type == REDUCTION_MEAN_IMAGINARYPART) {
3024857cbf51SRichard Tran Mills     for (i = 0; i < n; i++) {
3025ad540459SPierre Jolivet       for (j = 0; j < m; j++) reductions[i] += PetscImaginaryPart(a[j]);
302616cd844bSPierre Jolivet       a = PetscSafePointerPlusOffset(a, m);
3027857cbf51SRichard Tran Mills     }
3028857cbf51SRichard Tran Mills   } else SETERRQ(PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONG, "Unknown reduction type");
30299566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArrayRead(A, &a));
3030857cbf51SRichard Tran Mills   if (type == NORM_2) {
3031a873a8cdSSam Reynolds     for (i = 0; i < n; i++) reductions[i] = PetscSqrtReal(reductions[i]);
3032857cbf51SRichard Tran Mills   } else if (type == REDUCTION_MEAN_REALPART || type == REDUCTION_MEAN_IMAGINARYPART) {
3033a873a8cdSSam Reynolds     for (i = 0; i < n; i++) reductions[i] /= m;
30340716a85fSBarry Smith   }
30353ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
30360716a85fSBarry Smith }
30370716a85fSBarry Smith 
3038d71ae5a4SJacob Faibussowitsch PetscErrorCode MatSetRandom_SeqDense(Mat x, PetscRandom rctx)
3039d71ae5a4SJacob Faibussowitsch {
304073a71a0fSBarry Smith   PetscScalar *a;
3041637a0070SStefano Zampini   PetscInt     lda, m, n, i, j;
304273a71a0fSBarry Smith 
304373a71a0fSBarry Smith   PetscFunctionBegin;
30449566063dSJacob Faibussowitsch   PetscCall(MatGetSize(x, &m, &n));
30459566063dSJacob Faibussowitsch   PetscCall(MatDenseGetLDA(x, &lda));
30463faff063SStefano Zampini   PetscCall(MatDenseGetArrayWrite(x, &a));
3047637a0070SStefano Zampini   for (j = 0; j < n; j++) {
304848a46eb9SPierre Jolivet     for (i = 0; i < m; i++) PetscCall(PetscRandomGetValue(rctx, a + j * lda + i));
304973a71a0fSBarry Smith   }
30503faff063SStefano Zampini   PetscCall(MatDenseRestoreArrayWrite(x, &a));
30513ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
305273a71a0fSBarry Smith }
305373a71a0fSBarry Smith 
3054d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatMissingDiagonal_SeqDense(Mat A, PetscBool *missing, PetscInt *d)
3055d71ae5a4SJacob Faibussowitsch {
30563b49f96aSBarry Smith   PetscFunctionBegin;
30573b49f96aSBarry Smith   *missing = PETSC_FALSE;
30583ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
30593b49f96aSBarry Smith }
306073a71a0fSBarry Smith 
3061ca15aa20SStefano Zampini /* vals is not const */
3062d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatDenseGetColumn_SeqDense(Mat A, PetscInt col, PetscScalar **vals)
3063d71ae5a4SJacob Faibussowitsch {
306486aefd0dSHong Zhang   Mat_SeqDense *a = (Mat_SeqDense *)A->data;
3065ca15aa20SStefano Zampini   PetscScalar  *v;
306686aefd0dSHong Zhang 
306786aefd0dSHong Zhang   PetscFunctionBegin;
306828b400f6SJacob Faibussowitsch   PetscCheck(!A->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
30699566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArray(A, &v));
3070ca15aa20SStefano Zampini   *vals = v + col * a->lda;
30719566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArray(A, &v));
30723ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
307386aefd0dSHong Zhang }
307486aefd0dSHong Zhang 
3075d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatDenseRestoreColumn_SeqDense(Mat A, PetscScalar **vals)
3076d71ae5a4SJacob Faibussowitsch {
307786aefd0dSHong Zhang   PetscFunctionBegin;
3078742765d3SMatthew Knepley   if (vals) *vals = NULL; /* user cannot accidentally use the array later */
30793ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
308086aefd0dSHong Zhang }
3081abc3b08eSStefano Zampini 
3082a5ae1ecdSBarry Smith static struct _MatOps MatOps_Values = {MatSetValues_SeqDense,
3083905e6a2fSBarry Smith                                        MatGetRow_SeqDense,
3084905e6a2fSBarry Smith                                        MatRestoreRow_SeqDense,
3085905e6a2fSBarry Smith                                        MatMult_SeqDense,
308697304618SKris Buschelman                                        /*  4*/ MatMultAdd_SeqDense,
30877c922b88SBarry Smith                                        MatMultTranspose_SeqDense,
30887c922b88SBarry Smith                                        MatMultTransposeAdd_SeqDense,
3089f4259b30SLisandro Dalcin                                        NULL,
3090f4259b30SLisandro Dalcin                                        NULL,
3091f4259b30SLisandro Dalcin                                        NULL,
3092f4259b30SLisandro Dalcin                                        /* 10*/ NULL,
3093905e6a2fSBarry Smith                                        MatLUFactor_SeqDense,
3094905e6a2fSBarry Smith                                        MatCholeskyFactor_SeqDense,
309541f059aeSBarry Smith                                        MatSOR_SeqDense,
3096ec8511deSBarry Smith                                        MatTranspose_SeqDense,
309797304618SKris Buschelman                                        /* 15*/ MatGetInfo_SeqDense,
3098905e6a2fSBarry Smith                                        MatEqual_SeqDense,
3099905e6a2fSBarry Smith                                        MatGetDiagonal_SeqDense,
3100905e6a2fSBarry Smith                                        MatDiagonalScale_SeqDense,
3101905e6a2fSBarry Smith                                        MatNorm_SeqDense,
3102b7103cf4SPierre Jolivet                                        /* 20*/ NULL,
3103b7103cf4SPierre Jolivet                                        NULL,
3104905e6a2fSBarry Smith                                        MatSetOption_SeqDense,
3105905e6a2fSBarry Smith                                        MatZeroEntries_SeqDense,
3106d519adbfSMatthew Knepley                                        /* 24*/ MatZeroRows_SeqDense,
3107f4259b30SLisandro Dalcin                                        NULL,
3108f4259b30SLisandro Dalcin                                        NULL,
3109f4259b30SLisandro Dalcin                                        NULL,
3110f4259b30SLisandro Dalcin                                        NULL,
31114994cf47SJed Brown                                        /* 29*/ MatSetUp_SeqDense,
3112f4259b30SLisandro Dalcin                                        NULL,
3113f4259b30SLisandro Dalcin                                        NULL,
3114f4259b30SLisandro Dalcin                                        NULL,
3115f4259b30SLisandro Dalcin                                        NULL,
3116d519adbfSMatthew Knepley                                        /* 34*/ MatDuplicate_SeqDense,
3117f4259b30SLisandro Dalcin                                        NULL,
3118f4259b30SLisandro Dalcin                                        NULL,
3119f4259b30SLisandro Dalcin                                        NULL,
3120f4259b30SLisandro Dalcin                                        NULL,
3121d519adbfSMatthew Knepley                                        /* 39*/ MatAXPY_SeqDense,
31227dae84e0SHong Zhang                                        MatCreateSubMatrices_SeqDense,
3123f4259b30SLisandro Dalcin                                        NULL,
31244b0e389bSBarry Smith                                        MatGetValues_SeqDense,
3125a5ae1ecdSBarry Smith                                        MatCopy_SeqDense,
3126d519adbfSMatthew Knepley                                        /* 44*/ MatGetRowMax_SeqDense,
3127a5ae1ecdSBarry Smith                                        MatScale_SeqDense,
31282f605a99SJose E. Roman                                        MatShift_SeqDense,
3129f4259b30SLisandro Dalcin                                        NULL,
31303f49a652SStefano Zampini                                        MatZeroRowsColumns_SeqDense,
313173a71a0fSBarry Smith                                        /* 49*/ MatSetRandom_SeqDense,
3132f4259b30SLisandro Dalcin                                        NULL,
3133f4259b30SLisandro Dalcin                                        NULL,
3134f4259b30SLisandro Dalcin                                        NULL,
3135f4259b30SLisandro Dalcin                                        NULL,
3136f4259b30SLisandro Dalcin                                        /* 54*/ NULL,
3137f4259b30SLisandro Dalcin                                        NULL,
3138f4259b30SLisandro Dalcin                                        NULL,
3139f4259b30SLisandro Dalcin                                        NULL,
3140f4259b30SLisandro Dalcin                                        NULL,
3141023c16fcSToby Isaac                                        /* 59*/ MatCreateSubMatrix_SeqDense,
3142e03a110bSBarry Smith                                        MatDestroy_SeqDense,
3143e03a110bSBarry Smith                                        MatView_SeqDense,
3144f4259b30SLisandro Dalcin                                        NULL,
3145f4259b30SLisandro Dalcin                                        NULL,
3146f4259b30SLisandro Dalcin                                        /* 64*/ NULL,
3147f4259b30SLisandro Dalcin                                        NULL,
3148f4259b30SLisandro Dalcin                                        NULL,
3149f4259b30SLisandro Dalcin                                        NULL,
3150f4259b30SLisandro Dalcin                                        NULL,
3151d519adbfSMatthew Knepley                                        /* 69*/ MatGetRowMaxAbs_SeqDense,
3152f4259b30SLisandro Dalcin                                        NULL,
3153f4259b30SLisandro Dalcin                                        NULL,
3154f4259b30SLisandro Dalcin                                        NULL,
3155f4259b30SLisandro Dalcin                                        NULL,
3156f4259b30SLisandro Dalcin                                        /* 74*/ NULL,
3157f4259b30SLisandro Dalcin                                        NULL,
3158f4259b30SLisandro Dalcin                                        NULL,
3159f4259b30SLisandro Dalcin                                        NULL,
3160f4259b30SLisandro Dalcin                                        NULL,
3161f4259b30SLisandro Dalcin                                        /* 79*/ NULL,
3162f4259b30SLisandro Dalcin                                        NULL,
3163f4259b30SLisandro Dalcin                                        NULL,
3164f4259b30SLisandro Dalcin                                        NULL,
31655bba2384SShri Abhyankar                                        /* 83*/ MatLoad_SeqDense,
3166637a0070SStefano Zampini                                        MatIsSymmetric_SeqDense,
31671cbb95d3SBarry Smith                                        MatIsHermitian_SeqDense,
3168f4259b30SLisandro Dalcin                                        NULL,
3169f4259b30SLisandro Dalcin                                        NULL,
3170f4259b30SLisandro Dalcin                                        NULL,
3171f4259b30SLisandro Dalcin                                        /* 89*/ NULL,
3172f4259b30SLisandro Dalcin                                        NULL,
3173a9fe9ddaSSatish Balay                                        MatMatMultNumeric_SeqDense_SeqDense,
3174f4259b30SLisandro Dalcin                                        NULL,
3175f4259b30SLisandro Dalcin                                        NULL,
3176f4259b30SLisandro Dalcin                                        /* 94*/ NULL,
3177f4259b30SLisandro Dalcin                                        NULL,
3178f4259b30SLisandro Dalcin                                        NULL,
317969f65d41SStefano Zampini                                        MatMatTransposeMultNumeric_SeqDense_SeqDense,
3180f4259b30SLisandro Dalcin                                        NULL,
31814222ddf1SHong Zhang                                        /* 99*/ MatProductSetFromOptions_SeqDense,
3182f4259b30SLisandro Dalcin                                        NULL,
3183f4259b30SLisandro Dalcin                                        NULL,
3184ba337c44SJed Brown                                        MatConjugate_SeqDense,
3185f4259b30SLisandro Dalcin                                        NULL,
3186f4259b30SLisandro Dalcin                                        /*104*/ NULL,
3187ba337c44SJed Brown                                        MatRealPart_SeqDense,
3188ba337c44SJed Brown                                        MatImaginaryPart_SeqDense,
3189f4259b30SLisandro Dalcin                                        NULL,
3190f4259b30SLisandro Dalcin                                        NULL,
3191f4259b30SLisandro Dalcin                                        /*109*/ NULL,
3192f4259b30SLisandro Dalcin                                        NULL,
31938d0534beSBarry Smith                                        MatGetRowMin_SeqDense,
3194aabbc4fbSShri Abhyankar                                        MatGetColumnVector_SeqDense,
31953b49f96aSBarry Smith                                        MatMissingDiagonal_SeqDense,
3196f4259b30SLisandro Dalcin                                        /*114*/ NULL,
3197f4259b30SLisandro Dalcin                                        NULL,
3198f4259b30SLisandro Dalcin                                        NULL,
3199f4259b30SLisandro Dalcin                                        NULL,
3200f4259b30SLisandro Dalcin                                        NULL,
3201f4259b30SLisandro Dalcin                                        /*119*/ NULL,
3202f4259b30SLisandro Dalcin                                        NULL,
3203459e8d23SBlanca Mellado Pinto                                        MatMultHermitianTranspose_SeqDense,
3204459e8d23SBlanca Mellado Pinto                                        MatMultHermitianTransposeAdd_SeqDense,
3205f4259b30SLisandro Dalcin                                        NULL,
3206f4259b30SLisandro Dalcin                                        /*124*/ NULL,
3207a873a8cdSSam Reynolds                                        MatGetColumnReductions_SeqDense,
3208f4259b30SLisandro Dalcin                                        NULL,
3209f4259b30SLisandro Dalcin                                        NULL,
3210f4259b30SLisandro Dalcin                                        NULL,
3211f4259b30SLisandro Dalcin                                        /*129*/ NULL,
3212f4259b30SLisandro Dalcin                                        NULL,
3213f4259b30SLisandro Dalcin                                        NULL,
321475648e8dSHong Zhang                                        MatTransposeMatMultNumeric_SeqDense_SeqDense,
3215f4259b30SLisandro Dalcin                                        NULL,
3216f4259b30SLisandro Dalcin                                        /*134*/ NULL,
3217f4259b30SLisandro Dalcin                                        NULL,
3218f4259b30SLisandro Dalcin                                        NULL,
3219f4259b30SLisandro Dalcin                                        NULL,
3220f4259b30SLisandro Dalcin                                        NULL,
3221f4259b30SLisandro Dalcin                                        /*139*/ NULL,
3222f4259b30SLisandro Dalcin                                        NULL,
3223f4259b30SLisandro Dalcin                                        NULL,
3224f4259b30SLisandro Dalcin                                        NULL,
3225f4259b30SLisandro Dalcin                                        NULL,
32264222ddf1SHong Zhang                                        MatCreateMPIMatConcatenateSeqMat_SeqDense,
3227f4259b30SLisandro Dalcin                                        /*145*/ NULL,
3228f4259b30SLisandro Dalcin                                        NULL,
322999a7f59eSMark Adams                                        NULL,
323099a7f59eSMark Adams                                        NULL,
32317fb60732SBarry Smith                                        NULL,
3232dec0b466SHong Zhang                                        /*150*/ NULL,
3233eede4a3fSMark Adams                                        NULL,
32344cc2b5b5SPierre Jolivet                                        NULL,
323542ce410bSJunchao Zhang                                        NULL,
323642ce410bSJunchao Zhang                                        NULL,
3237fe1fc275SAlexander                                        /*155*/ NULL,
3238dec0b466SHong Zhang                                        NULL};
323990ace30eSBarry Smith 
32405d83a8b1SBarry Smith /*@
324111a5261eSBarry Smith   MatCreateSeqDense - Creates a `MATSEQDENSE` that
3242fb850c59SBarry Smith   is stored in column major order (the usual Fortran format).
3243289bc588SBarry Smith 
3244d083f849SBarry Smith   Collective
3245db81eaa0SLois Curfman McInnes 
324620563c6bSBarry Smith   Input Parameters:
324711a5261eSBarry Smith + comm - MPI communicator, set to `PETSC_COMM_SELF`
32480c775827SLois Curfman McInnes . m    - number of rows
324918f449edSLois Curfman McInnes . n    - number of columns
32502ef1f0ffSBarry Smith - data - optional location of matrix data in column major order.  Use `NULL` for PETSc
3251dfc5480cSLois Curfman McInnes          to control all matrix memory allocation.
325220563c6bSBarry Smith 
325320563c6bSBarry Smith   Output Parameter:
325444cd7ae7SLois Curfman McInnes . A - the matrix
325520563c6bSBarry Smith 
32562ef1f0ffSBarry Smith   Level: intermediate
32572ef1f0ffSBarry Smith 
325811a5261eSBarry Smith   Note:
325918f449edSLois Curfman McInnes   The data input variable is intended primarily for Fortran programmers
326018f449edSLois Curfman McInnes   who wish to allocate their own matrix memory space.  Most users should
32612ef1f0ffSBarry Smith   set `data` = `NULL`.
326218f449edSLois Curfman McInnes 
3263fb850c59SBarry Smith   Developer Note:
3264fb850c59SBarry Smith   Many of the matrix operations for this variant use the BLAS and LAPACK routines.
3265fb850c59SBarry Smith 
32661cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATSEQDENSE`, `MatCreate()`, `MatCreateDense()`, `MatSetValues()`
326720563c6bSBarry Smith @*/
32685d83a8b1SBarry Smith PetscErrorCode MatCreateSeqDense(MPI_Comm comm, PetscInt m, PetscInt n, PetscScalar data[], Mat *A)
3269d71ae5a4SJacob Faibussowitsch {
32703a40ed3dSBarry Smith   PetscFunctionBegin;
32719566063dSJacob Faibussowitsch   PetscCall(MatCreate(comm, A));
32729566063dSJacob Faibussowitsch   PetscCall(MatSetSizes(*A, m, n, m, n));
32739566063dSJacob Faibussowitsch   PetscCall(MatSetType(*A, MATSEQDENSE));
32749566063dSJacob Faibussowitsch   PetscCall(MatSeqDenseSetPreallocation(*A, data));
32753ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3276273d9f13SBarry Smith }
3277273d9f13SBarry Smith 
32785d83a8b1SBarry Smith /*@
327911a5261eSBarry Smith   MatSeqDenseSetPreallocation - Sets the array used for storing the matrix elements of a `MATSEQDENSE` matrix
3280273d9f13SBarry Smith 
3281d083f849SBarry Smith   Collective
3282273d9f13SBarry Smith 
3283273d9f13SBarry Smith   Input Parameters:
32841c4f3114SJed Brown + B    - the matrix
32852ef1f0ffSBarry Smith - data - the array (or `NULL`)
32862ef1f0ffSBarry Smith 
32872ef1f0ffSBarry Smith   Level: intermediate
3288273d9f13SBarry Smith 
328911a5261eSBarry Smith   Note:
3290273d9f13SBarry Smith   The data input variable is intended primarily for Fortran programmers
3291273d9f13SBarry Smith   who wish to allocate their own matrix memory space.  Most users should
3292284134d9SBarry Smith   need not call this routine.
3293273d9f13SBarry Smith 
32941cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATSEQDENSE`, `MatCreate()`, `MatCreateDense()`, `MatSetValues()`, `MatDenseSetLDA()`
3295273d9f13SBarry Smith @*/
3296d71ae5a4SJacob Faibussowitsch PetscErrorCode MatSeqDenseSetPreallocation(Mat B, PetscScalar data[])
3297d71ae5a4SJacob Faibussowitsch {
3298a23d5eceSKris Buschelman   PetscFunctionBegin;
3299d5ea218eSStefano Zampini   PetscValidHeaderSpecific(B, MAT_CLASSID, 1);
3300cac4c232SBarry Smith   PetscTryMethod(B, "MatSeqDenseSetPreallocation_C", (Mat, PetscScalar[]), (B, data));
33013ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3302a23d5eceSKris Buschelman }
3303a23d5eceSKris Buschelman 
3304d71ae5a4SJacob Faibussowitsch PetscErrorCode MatSeqDenseSetPreallocation_SeqDense(Mat B, PetscScalar *data)
3305d71ae5a4SJacob Faibussowitsch {
3306ad16ce7aSStefano Zampini   Mat_SeqDense *b = (Mat_SeqDense *)B->data;
3307273d9f13SBarry Smith 
3308273d9f13SBarry Smith   PetscFunctionBegin;
330928b400f6SJacob Faibussowitsch   PetscCheck(!b->matinuse, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Need to call MatDenseRestoreSubMatrix() first");
3310273d9f13SBarry Smith   B->preallocated = PETSC_TRUE;
3311a868139aSShri Abhyankar 
33129566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetUp(B->rmap));
33139566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetUp(B->cmap));
331434ef9618SShri Abhyankar 
33156497c311SBarry Smith   if (b->lda <= 0) PetscCall(PetscBLASIntCast(B->rmap->n, &b->lda));
331686d161a7SShri Abhyankar 
33179e8f95c4SLisandro Dalcin   if (!data) { /* petsc-allocated storage */
33189566063dSJacob Faibussowitsch     if (!b->user_alloc) PetscCall(PetscFree(b->v));
33199566063dSJacob Faibussowitsch     PetscCall(PetscCalloc1((size_t)b->lda * B->cmap->n, &b->v));
33202205254eSKarl Rupp 
33219e8f95c4SLisandro Dalcin     b->user_alloc = PETSC_FALSE;
3322273d9f13SBarry Smith   } else { /* user-allocated storage */
33239566063dSJacob Faibussowitsch     if (!b->user_alloc) PetscCall(PetscFree(b->v));
3324273d9f13SBarry Smith     b->v          = data;
3325273d9f13SBarry Smith     b->user_alloc = PETSC_TRUE;
3326273d9f13SBarry Smith   }
33270450473dSBarry Smith   B->assembled = PETSC_TRUE;
33283ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3329273d9f13SBarry Smith }
3330273d9f13SBarry Smith 
333165b80a83SHong Zhang #if defined(PETSC_HAVE_ELEMENTAL)
3332d71ae5a4SJacob Faibussowitsch PETSC_INTERN PetscErrorCode MatConvert_SeqDense_Elemental(Mat A, MatType newtype, MatReuse reuse, Mat *newmat)
3333d71ae5a4SJacob Faibussowitsch {
3334d77f618aSHong Zhang   Mat                mat_elemental;
33351683a169SBarry Smith   const PetscScalar *array;
33361683a169SBarry Smith   PetscScalar       *v_colwise;
3337d77f618aSHong Zhang   PetscInt           M = A->rmap->N, N = A->cmap->N, i, j, k, *rows, *cols;
3338d77f618aSHong Zhang 
33398baccfbdSHong Zhang   PetscFunctionBegin;
33409566063dSJacob Faibussowitsch   PetscCall(PetscMalloc3(M * N, &v_colwise, M, &rows, N, &cols));
33419566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArrayRead(A, &array));
3342d77f618aSHong Zhang   /* convert column-wise array into row-wise v_colwise, see MatSetValues_Elemental() */
3343d77f618aSHong Zhang   k = 0;
3344d77f618aSHong Zhang   for (j = 0; j < N; j++) {
3345d77f618aSHong Zhang     cols[j] = j;
3346ad540459SPierre Jolivet     for (i = 0; i < M; i++) v_colwise[j * M + i] = array[k++];
3347d77f618aSHong Zhang   }
3348ad540459SPierre Jolivet   for (i = 0; i < M; i++) rows[i] = i;
33499566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArrayRead(A, &array));
3350d77f618aSHong Zhang 
33519566063dSJacob Faibussowitsch   PetscCall(MatCreate(PetscObjectComm((PetscObject)A), &mat_elemental));
33529566063dSJacob Faibussowitsch   PetscCall(MatSetSizes(mat_elemental, PETSC_DECIDE, PETSC_DECIDE, M, N));
33539566063dSJacob Faibussowitsch   PetscCall(MatSetType(mat_elemental, MATELEMENTAL));
33549566063dSJacob Faibussowitsch   PetscCall(MatSetUp(mat_elemental));
3355d77f618aSHong Zhang 
3356d77f618aSHong Zhang   /* PETSc-Elemental interaface uses axpy for setting off-processor entries, only ADD_VALUES is allowed */
33579566063dSJacob Faibussowitsch   PetscCall(MatSetValues(mat_elemental, M, rows, N, cols, v_colwise, ADD_VALUES));
33589566063dSJacob Faibussowitsch   PetscCall(MatAssemblyBegin(mat_elemental, MAT_FINAL_ASSEMBLY));
33599566063dSJacob Faibussowitsch   PetscCall(MatAssemblyEnd(mat_elemental, MAT_FINAL_ASSEMBLY));
33609566063dSJacob Faibussowitsch   PetscCall(PetscFree3(v_colwise, rows, cols));
3361d77f618aSHong Zhang 
3362511c6705SHong Zhang   if (reuse == MAT_INPLACE_MATRIX) {
33639566063dSJacob Faibussowitsch     PetscCall(MatHeaderReplace(A, &mat_elemental));
3364d77f618aSHong Zhang   } else {
3365d77f618aSHong Zhang     *newmat = mat_elemental;
3366d77f618aSHong Zhang   }
33673ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
33688baccfbdSHong Zhang }
336965b80a83SHong Zhang #endif
33708baccfbdSHong Zhang 
3371d71ae5a4SJacob Faibussowitsch PetscErrorCode MatDenseSetLDA_SeqDense(Mat B, PetscInt lda)
3372d71ae5a4SJacob Faibussowitsch {
33731b807ce4Svictorle   Mat_SeqDense *b = (Mat_SeqDense *)B->data;
33747422da62SJose E. Roman   PetscBool     data;
337521a2c019SBarry Smith 
33761b807ce4Svictorle   PetscFunctionBegin;
3377835f2295SStefano Zampini   data = (B->rmap->n > 0 && B->cmap->n > 0) ? (b->v ? PETSC_TRUE : PETSC_FALSE) : PETSC_FALSE;
3378aed4548fSBarry Smith   PetscCheck(b->user_alloc || !data || b->lda == lda, PETSC_COMM_SELF, PETSC_ERR_ORDER, "LDA cannot be changed after allocation of internal storage");
337908401ef6SPierre 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);
33806497c311SBarry Smith   PetscCall(PetscBLASIntCast(lda, &b->lda));
33813ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
33821b807ce4Svictorle }
33831b807ce4Svictorle 
3384d71ae5a4SJacob Faibussowitsch PetscErrorCode MatCreateMPIMatConcatenateSeqMat_SeqDense(MPI_Comm comm, Mat inmat, PetscInt n, MatReuse scall, Mat *outmat)
3385d71ae5a4SJacob Faibussowitsch {
3386d528f656SJakub Kruzik   PetscFunctionBegin;
33879566063dSJacob Faibussowitsch   PetscCall(MatCreateMPIMatConcatenateSeqMat_MPIDense(comm, inmat, n, scall, outmat));
33883ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3389d528f656SJakub Kruzik }
3390d528f656SJakub Kruzik 
3391d16ceb75SStefano Zampini PetscErrorCode MatDenseCreateColumnVec_Private(Mat A, Vec *v)
3392d16ceb75SStefano Zampini {
3393d16ceb75SStefano Zampini   PetscBool   isstd, iskok, iscuda, iship;
3394d16ceb75SStefano Zampini   PetscMPIInt size;
3395d16ceb75SStefano Zampini #if PetscDefined(HAVE_CUDA) || PetscDefined(HAVE_HIP)
3396d16ceb75SStefano Zampini   /* we pass the data of A, to prevent allocating needless GPU memory the first time VecCUPMPlaceArray is called. */
3397d16ceb75SStefano Zampini   const PetscScalar *a;
3398d16ceb75SStefano Zampini #endif
3399d16ceb75SStefano Zampini 
3400d16ceb75SStefano Zampini   PetscFunctionBegin;
3401d16ceb75SStefano Zampini   *v = NULL;
3402d16ceb75SStefano Zampini   PetscCall(PetscStrcmpAny(A->defaultvectype, &isstd, VECSTANDARD, VECSEQ, VECMPI, ""));
3403d16ceb75SStefano Zampini   PetscCall(PetscStrcmpAny(A->defaultvectype, &iskok, VECKOKKOS, VECSEQKOKKOS, VECMPIKOKKOS, ""));
3404d16ceb75SStefano Zampini   PetscCall(PetscStrcmpAny(A->defaultvectype, &iscuda, VECCUDA, VECSEQCUDA, VECMPICUDA, ""));
3405d16ceb75SStefano Zampini   PetscCall(PetscStrcmpAny(A->defaultvectype, &iship, VECHIP, VECSEQHIP, VECMPIHIP, ""));
3406d16ceb75SStefano Zampini   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)A), &size));
3407d16ceb75SStefano Zampini   if (isstd) {
3408d16ceb75SStefano Zampini     if (size > 1) PetscCall(VecCreateMPIWithArray(PetscObjectComm((PetscObject)A), A->rmap->bs, A->rmap->n, A->rmap->N, NULL, v));
3409d16ceb75SStefano Zampini     else PetscCall(VecCreateSeqWithArray(PetscObjectComm((PetscObject)A), A->rmap->bs, A->rmap->n, NULL, v));
3410d16ceb75SStefano Zampini   } else if (iskok) {
3411d16ceb75SStefano Zampini     PetscCheck(PetscDefined(HAVE_KOKKOS_KERNELS), PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Reconfigure using KOKKOS kernels support");
3412d16ceb75SStefano Zampini #if PetscDefined(HAVE_KOKKOS_KERNELS)
3413d16ceb75SStefano Zampini     if (size > 1) PetscCall(VecCreateMPIKokkosWithArray(PetscObjectComm((PetscObject)A), A->rmap->bs, A->rmap->n, A->rmap->N, NULL, v));
3414d16ceb75SStefano Zampini     else PetscCall(VecCreateSeqKokkosWithArray(PetscObjectComm((PetscObject)A), A->rmap->bs, A->rmap->n, NULL, v));
3415d16ceb75SStefano Zampini #endif
3416d16ceb75SStefano Zampini   } else if (iscuda) {
3417d16ceb75SStefano Zampini     PetscCheck(PetscDefined(HAVE_CUDA), PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Reconfigure using CUDA support");
3418d16ceb75SStefano Zampini #if PetscDefined(HAVE_CUDA)
3419d16ceb75SStefano Zampini     PetscCall(MatDenseCUDAGetArrayRead(A, &a));
3420d16ceb75SStefano Zampini     if (size > 1) PetscCall(VecCreateMPICUDAWithArrays(PetscObjectComm((PetscObject)A), A->rmap->bs, A->rmap->n, A->rmap->N, NULL, a, v));
3421d16ceb75SStefano Zampini     else PetscCall(VecCreateSeqCUDAWithArrays(PetscObjectComm((PetscObject)A), A->rmap->bs, A->rmap->n, NULL, a, v));
3422d16ceb75SStefano Zampini #endif
3423d16ceb75SStefano Zampini   } else if (iship) {
3424d16ceb75SStefano Zampini     PetscCheck(PetscDefined(HAVE_HIP), PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Reconfigure using HIP support");
3425d16ceb75SStefano Zampini #if PetscDefined(HAVE_HIP)
3426d16ceb75SStefano Zampini     PetscCall(MatDenseHIPGetArrayRead(A, &a));
3427d16ceb75SStefano Zampini     if (size > 1) PetscCall(VecCreateMPIHIPWithArrays(PetscObjectComm((PetscObject)A), A->rmap->bs, A->rmap->n, A->rmap->N, NULL, a, v));
3428d16ceb75SStefano Zampini     else PetscCall(VecCreateSeqHIPWithArrays(PetscObjectComm((PetscObject)A), A->rmap->bs, A->rmap->n, NULL, a, v));
3429d16ceb75SStefano Zampini #endif
3430d16ceb75SStefano Zampini   }
3431d16ceb75SStefano Zampini   PetscCheck(*v, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Not coded for type %s", A->defaultvectype);
3432d16ceb75SStefano Zampini   PetscFunctionReturn(PETSC_SUCCESS);
3433d16ceb75SStefano Zampini }
3434d16ceb75SStefano Zampini 
3435d71ae5a4SJacob Faibussowitsch PetscErrorCode MatDenseGetColumnVec_SeqDense(Mat A, PetscInt col, Vec *v)
3436d71ae5a4SJacob Faibussowitsch {
34376947451fSStefano Zampini   Mat_SeqDense *a = (Mat_SeqDense *)A->data;
34386947451fSStefano Zampini 
34396947451fSStefano Zampini   PetscFunctionBegin;
344028b400f6SJacob Faibussowitsch   PetscCheck(!a->vecinuse, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Need to call MatDenseRestoreColumnVec() first");
344128b400f6SJacob Faibussowitsch   PetscCheck(!a->matinuse, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Need to call MatDenseRestoreSubMatrix() first");
3442d16ceb75SStefano Zampini   if (!a->cvec) PetscCall(MatDenseCreateColumnVec_Private(A, &a->cvec));
34436947451fSStefano Zampini   a->vecinuse = col + 1;
34449566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArray(A, (PetscScalar **)&a->ptrinuse));
34459566063dSJacob Faibussowitsch   PetscCall(VecPlaceArray(a->cvec, a->ptrinuse + (size_t)col * (size_t)a->lda));
34466947451fSStefano Zampini   *v = a->cvec;
34473ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
34486947451fSStefano Zampini }
34496947451fSStefano Zampini 
3450d71ae5a4SJacob Faibussowitsch PetscErrorCode MatDenseRestoreColumnVec_SeqDense(Mat A, PetscInt col, Vec *v)
3451d71ae5a4SJacob Faibussowitsch {
34526947451fSStefano Zampini   Mat_SeqDense *a = (Mat_SeqDense *)A->data;
34536947451fSStefano Zampini 
34546947451fSStefano Zampini   PetscFunctionBegin;
345528b400f6SJacob Faibussowitsch   PetscCheck(a->vecinuse, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Need to call MatDenseGetColumnVec() first");
345628b400f6SJacob Faibussowitsch   PetscCheck(a->cvec, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Missing internal column vector");
34574186a4bbSPierre Jolivet   VecCheckAssembled(a->cvec);
34586947451fSStefano Zampini   a->vecinuse = 0;
34599566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArray(A, (PetscScalar **)&a->ptrinuse));
34609566063dSJacob Faibussowitsch   PetscCall(VecResetArray(a->cvec));
346175f6d85dSStefano Zampini   if (v) *v = NULL;
34623ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
34636947451fSStefano Zampini }
34646947451fSStefano Zampini 
3465d71ae5a4SJacob Faibussowitsch PetscErrorCode MatDenseGetColumnVecRead_SeqDense(Mat A, PetscInt col, Vec *v)
3466d71ae5a4SJacob Faibussowitsch {
34676947451fSStefano Zampini   Mat_SeqDense *a = (Mat_SeqDense *)A->data;
34686947451fSStefano Zampini 
34696947451fSStefano Zampini   PetscFunctionBegin;
347028b400f6SJacob Faibussowitsch   PetscCheck(!a->vecinuse, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Need to call MatDenseRestoreColumnVec() first");
347128b400f6SJacob Faibussowitsch   PetscCheck(!a->matinuse, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Need to call MatDenseRestoreSubMatrix() first");
3472d16ceb75SStefano Zampini   if (!a->cvec) PetscCall(MatDenseCreateColumnVec_Private(A, &a->cvec));
34736947451fSStefano Zampini   a->vecinuse = col + 1;
34749566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArrayRead(A, &a->ptrinuse));
34758e3a54c0SPierre Jolivet   PetscCall(VecPlaceArray(a->cvec, PetscSafePointerPlusOffset(a->ptrinuse, (size_t)col * (size_t)a->lda)));
34769566063dSJacob Faibussowitsch   PetscCall(VecLockReadPush(a->cvec));
34776947451fSStefano Zampini   *v = a->cvec;
34783ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
34796947451fSStefano Zampini }
34806947451fSStefano Zampini 
3481d71ae5a4SJacob Faibussowitsch PetscErrorCode MatDenseRestoreColumnVecRead_SeqDense(Mat A, PetscInt col, Vec *v)
3482d71ae5a4SJacob Faibussowitsch {
34836947451fSStefano Zampini   Mat_SeqDense *a = (Mat_SeqDense *)A->data;
34846947451fSStefano Zampini 
34856947451fSStefano Zampini   PetscFunctionBegin;
348628b400f6SJacob Faibussowitsch   PetscCheck(a->vecinuse, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Need to call MatDenseGetColumnVec() first");
348728b400f6SJacob Faibussowitsch   PetscCheck(a->cvec, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Missing internal column vector");
34884186a4bbSPierre Jolivet   VecCheckAssembled(a->cvec);
34896947451fSStefano Zampini   a->vecinuse = 0;
34909566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArrayRead(A, &a->ptrinuse));
34919566063dSJacob Faibussowitsch   PetscCall(VecLockReadPop(a->cvec));
34929566063dSJacob Faibussowitsch   PetscCall(VecResetArray(a->cvec));
349375f6d85dSStefano Zampini   if (v) *v = NULL;
34943ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
34956947451fSStefano Zampini }
34966947451fSStefano Zampini 
3497d71ae5a4SJacob Faibussowitsch PetscErrorCode MatDenseGetColumnVecWrite_SeqDense(Mat A, PetscInt col, Vec *v)
3498d71ae5a4SJacob Faibussowitsch {
34996947451fSStefano Zampini   Mat_SeqDense *a = (Mat_SeqDense *)A->data;
35006947451fSStefano Zampini 
35016947451fSStefano Zampini   PetscFunctionBegin;
350228b400f6SJacob Faibussowitsch   PetscCheck(!a->vecinuse, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Need to call MatDenseRestoreColumnVec() first");
350328b400f6SJacob Faibussowitsch   PetscCheck(!a->matinuse, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Need to call MatDenseRestoreSubMatrix() first");
3504d16ceb75SStefano Zampini   if (!a->cvec) PetscCall(MatDenseCreateColumnVec_Private(A, &a->cvec));
35056947451fSStefano Zampini   a->vecinuse = col + 1;
35069566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArrayWrite(A, (PetscScalar **)&a->ptrinuse));
35078e3a54c0SPierre Jolivet   PetscCall(VecPlaceArray(a->cvec, PetscSafePointerPlusOffset(a->ptrinuse, (size_t)col * (size_t)a->lda)));
35086947451fSStefano Zampini   *v = a->cvec;
35093ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
35106947451fSStefano Zampini }
35116947451fSStefano Zampini 
3512d71ae5a4SJacob Faibussowitsch PetscErrorCode MatDenseRestoreColumnVecWrite_SeqDense(Mat A, PetscInt col, Vec *v)
3513d71ae5a4SJacob Faibussowitsch {
35146947451fSStefano Zampini   Mat_SeqDense *a = (Mat_SeqDense *)A->data;
35156947451fSStefano Zampini 
35166947451fSStefano Zampini   PetscFunctionBegin;
351728b400f6SJacob Faibussowitsch   PetscCheck(a->vecinuse, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Need to call MatDenseGetColumnVec() first");
351828b400f6SJacob Faibussowitsch   PetscCheck(a->cvec, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Missing internal column vector");
35194186a4bbSPierre Jolivet   VecCheckAssembled(a->cvec);
35206947451fSStefano Zampini   a->vecinuse = 0;
35219566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArrayWrite(A, (PetscScalar **)&a->ptrinuse));
35229566063dSJacob Faibussowitsch   PetscCall(VecResetArray(a->cvec));
352375f6d85dSStefano Zampini   if (v) *v = NULL;
35243ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
35256947451fSStefano Zampini }
35266947451fSStefano Zampini 
3527d71ae5a4SJacob Faibussowitsch PetscErrorCode MatDenseGetSubMatrix_SeqDense(Mat A, PetscInt rbegin, PetscInt rend, PetscInt cbegin, PetscInt cend, Mat *v)
3528d71ae5a4SJacob Faibussowitsch {
35295ea7661aSPierre Jolivet   Mat_SeqDense *a = (Mat_SeqDense *)A->data;
35305ea7661aSPierre Jolivet 
35315ea7661aSPierre Jolivet   PetscFunctionBegin;
353228b400f6SJacob Faibussowitsch   PetscCheck(!a->vecinuse, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Need to call MatDenseRestoreColumnVec() first");
353328b400f6SJacob Faibussowitsch   PetscCheck(!a->matinuse, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Need to call MatDenseRestoreSubMatrix() first");
3534a2748737SPierre Jolivet   if (a->cmat && (cend - cbegin != a->cmat->cmap->N || rend - rbegin != a->cmat->rmap->N)) PetscCall(MatDestroy(&a->cmat));
35355ea7661aSPierre Jolivet   if (!a->cmat) {
35368e3a54c0SPierre 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));
35375ea7661aSPierre Jolivet   } else {
35388e3a54c0SPierre Jolivet     PetscCall(MatDensePlaceArray(a->cmat, PetscSafePointerPlusOffset(a->v, rbegin + (size_t)cbegin * a->lda)));
35395ea7661aSPierre Jolivet   }
35409566063dSJacob Faibussowitsch   PetscCall(MatDenseSetLDA(a->cmat, a->lda));
35415ea7661aSPierre Jolivet   a->matinuse = cbegin + 1;
35425ea7661aSPierre Jolivet   *v          = a->cmat;
354347d993e7Ssuyashtn #if defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
354475f6d85dSStefano Zampini   A->offloadmask = PETSC_OFFLOAD_CPU;
354575f6d85dSStefano Zampini #endif
35463ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
35475ea7661aSPierre Jolivet }
35485ea7661aSPierre Jolivet 
3549d71ae5a4SJacob Faibussowitsch PetscErrorCode MatDenseRestoreSubMatrix_SeqDense(Mat A, Mat *v)
3550d71ae5a4SJacob Faibussowitsch {
35515ea7661aSPierre Jolivet   Mat_SeqDense *a = (Mat_SeqDense *)A->data;
35525ea7661aSPierre Jolivet 
35535ea7661aSPierre Jolivet   PetscFunctionBegin;
355428b400f6SJacob Faibussowitsch   PetscCheck(a->matinuse, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Need to call MatDenseGetSubMatrix() first");
355528b400f6SJacob Faibussowitsch   PetscCheck(a->cmat, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Missing internal column matrix");
355608401ef6SPierre Jolivet   PetscCheck(*v == a->cmat, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Not the matrix obtained from MatDenseGetSubMatrix()");
35575ea7661aSPierre Jolivet   a->matinuse = 0;
35589566063dSJacob Faibussowitsch   PetscCall(MatDenseResetArray(a->cmat));
3559742765d3SMatthew Knepley   if (v) *v = NULL;
356047d993e7Ssuyashtn #if defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
35613faff063SStefano Zampini   A->offloadmask = PETSC_OFFLOAD_CPU;
35623faff063SStefano Zampini #endif
35633ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
35645ea7661aSPierre Jolivet }
35655ea7661aSPierre Jolivet 
35660bad9183SKris Buschelman /*MC
3567fafad747SKris Buschelman    MATSEQDENSE - MATSEQDENSE = "seqdense" - A matrix type to be used for sequential dense matrices.
35680bad9183SKris Buschelman 
35692ef1f0ffSBarry Smith    Options Database Key:
357011a5261eSBarry Smith . -mat_type seqdense - sets the matrix type to `MATSEQDENSE` during a call to `MatSetFromOptions()`
35710bad9183SKris Buschelman 
35720bad9183SKris Buschelman   Level: beginner
35730bad9183SKris Buschelman 
35741cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATSEQDENSE`, `MatCreateSeqDense()`
35750bad9183SKris Buschelman M*/
3576d71ae5a4SJacob Faibussowitsch PetscErrorCode MatCreate_SeqDense(Mat B)
3577d71ae5a4SJacob Faibussowitsch {
3578273d9f13SBarry Smith   Mat_SeqDense *b;
35797c334f02SBarry Smith   PetscMPIInt   size;
3580273d9f13SBarry Smith 
3581273d9f13SBarry Smith   PetscFunctionBegin;
35829566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)B), &size));
358308401ef6SPierre Jolivet   PetscCheck(size <= 1, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Comm must be of size 1");
358455659b69SBarry Smith 
35854dfa11a4SJacob Faibussowitsch   PetscCall(PetscNew(&b));
358644cd7ae7SLois Curfman McInnes   B->data   = (void *)b;
3587aea10558SJacob Faibussowitsch   B->ops[0] = MatOps_Values;
358818f449edSLois Curfman McInnes 
3589273d9f13SBarry Smith   b->roworiented = PETSC_TRUE;
35904e220ebcSLois Curfman McInnes 
35919566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatQRFactor_C", MatQRFactor_SeqDense));
35929566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatDenseGetLDA_C", MatDenseGetLDA_SeqDense));
35939566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatDenseSetLDA_C", MatDenseSetLDA_SeqDense));
35949566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatDenseGetArray_C", MatDenseGetArray_SeqDense));
35959566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatDenseRestoreArray_C", MatDenseRestoreArray_SeqDense));
35969566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatDensePlaceArray_C", MatDensePlaceArray_SeqDense));
35979566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatDenseResetArray_C", MatDenseResetArray_SeqDense));
35989566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatDenseReplaceArray_C", MatDenseReplaceArray_SeqDense));
35999566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatDenseGetArrayRead_C", MatDenseGetArray_SeqDense));
36009566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatDenseRestoreArrayRead_C", MatDenseRestoreArray_SeqDense));
36019566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatDenseGetArrayWrite_C", MatDenseGetArray_SeqDense));
36029566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatDenseRestoreArrayWrite_C", MatDenseRestoreArray_SeqDense));
36039566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatConvert_seqdense_seqaij_C", MatConvert_SeqDense_SeqAIJ));
36048baccfbdSHong Zhang #if defined(PETSC_HAVE_ELEMENTAL)
36059566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatConvert_seqdense_elemental_C", MatConvert_SeqDense_Elemental));
36068baccfbdSHong Zhang #endif
3607d24d4204SJose E. Roman #if defined(PETSC_HAVE_SCALAPACK)
36089566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatConvert_seqdense_scalapack_C", MatConvert_Dense_ScaLAPACK));
3609d24d4204SJose E. Roman #endif
36102bf066beSStefano Zampini #if defined(PETSC_HAVE_CUDA)
36119566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatConvert_seqdense_seqdensecuda_C", MatConvert_SeqDense_SeqDenseCUDA));
36129566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatProductSetFromOptions_seqdensecuda_seqdensecuda_C", MatProductSetFromOptions_SeqDense));
36139566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatProductSetFromOptions_seqdensecuda_seqdense_C", MatProductSetFromOptions_SeqDense));
36149566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatProductSetFromOptions_seqdense_seqdensecuda_C", MatProductSetFromOptions_SeqDense));
36152bf066beSStefano Zampini #endif
361647d993e7Ssuyashtn #if defined(PETSC_HAVE_HIP)
361747d993e7Ssuyashtn   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatConvert_seqdense_seqdensehip_C", MatConvert_SeqDense_SeqDenseHIP));
361847d993e7Ssuyashtn   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatProductSetFromOptions_seqdensehip_seqdensehip_C", MatProductSetFromOptions_SeqDense));
361947d993e7Ssuyashtn   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatProductSetFromOptions_seqdensehip_seqdense_C", MatProductSetFromOptions_SeqDense));
362047d993e7Ssuyashtn   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatProductSetFromOptions_seqdense_seqdensehip_C", MatProductSetFromOptions_SeqDense));
362147d993e7Ssuyashtn #endif
36229566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatSeqDenseSetPreallocation_C", MatSeqDenseSetPreallocation_SeqDense));
36239566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatProductSetFromOptions_seqaij_seqdense_C", MatProductSetFromOptions_SeqAIJ_SeqDense));
36249566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatProductSetFromOptions_seqdense_seqdense_C", MatProductSetFromOptions_SeqDense));
36259566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatProductSetFromOptions_seqbaij_seqdense_C", MatProductSetFromOptions_SeqXBAIJ_SeqDense));
36269566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatProductSetFromOptions_seqsbaij_seqdense_C", MatProductSetFromOptions_SeqXBAIJ_SeqDense));
362796e6d5c4SRichard Tran Mills 
36289566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatDenseGetColumn_C", MatDenseGetColumn_SeqDense));
36299566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatDenseRestoreColumn_C", MatDenseRestoreColumn_SeqDense));
36309566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatDenseGetColumnVec_C", MatDenseGetColumnVec_SeqDense));
36319566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatDenseRestoreColumnVec_C", MatDenseRestoreColumnVec_SeqDense));
36329566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatDenseGetColumnVecRead_C", MatDenseGetColumnVecRead_SeqDense));
36339566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatDenseRestoreColumnVecRead_C", MatDenseRestoreColumnVecRead_SeqDense));
36349566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatDenseGetColumnVecWrite_C", MatDenseGetColumnVecWrite_SeqDense));
36359566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatDenseRestoreColumnVecWrite_C", MatDenseRestoreColumnVecWrite_SeqDense));
36369566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatDenseGetSubMatrix_C", MatDenseGetSubMatrix_SeqDense));
36379566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatDenseRestoreSubMatrix_C", MatDenseRestoreSubMatrix_SeqDense));
36380be0d8bdSHansol Suh   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatMultAddColumnRange_C", MatMultAddColumnRange_SeqDense));
36390be0d8bdSHansol Suh   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatMultHermitianTransposeColumnRange_C", MatMultHermitianTransposeColumnRange_SeqDense));
36400be0d8bdSHansol Suh   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatMultHermitianTransposeAddColumnRange_C", MatMultHermitianTransposeAddColumnRange_SeqDense));
36419566063dSJacob Faibussowitsch   PetscCall(PetscObjectChangeTypeName((PetscObject)B, MATSEQDENSE));
36423ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3643289bc588SBarry Smith }
364486aefd0dSHong Zhang 
364586aefd0dSHong Zhang /*@C
364611a5261eSBarry 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.
364786aefd0dSHong Zhang 
364886aefd0dSHong Zhang   Not Collective
364986aefd0dSHong Zhang 
36505ea7661aSPierre Jolivet   Input Parameters:
3651fe59aa6dSJacob Faibussowitsch + A   - a `MATSEQDENSE` or `MATMPIDENSE` matrix
365286aefd0dSHong Zhang - col - column index
365386aefd0dSHong Zhang 
365486aefd0dSHong Zhang   Output Parameter:
365586aefd0dSHong Zhang . vals - pointer to the data
365686aefd0dSHong Zhang 
365786aefd0dSHong Zhang   Level: intermediate
365886aefd0dSHong Zhang 
365911a5261eSBarry Smith   Note:
366011a5261eSBarry Smith   Use `MatDenseGetColumnVec()` to get access to a column of a `MATDENSE` treated as a `Vec`
366111a5261eSBarry Smith 
36621cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATDENSE`, `MatDenseRestoreColumn()`, `MatDenseGetColumnVec()`
366386aefd0dSHong Zhang @*/
36645d83a8b1SBarry Smith PetscErrorCode MatDenseGetColumn(Mat A, PetscInt col, PetscScalar *vals[])
3665d71ae5a4SJacob Faibussowitsch {
366686aefd0dSHong Zhang   PetscFunctionBegin;
3667d5ea218eSStefano Zampini   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
3668d5ea218eSStefano Zampini   PetscValidLogicalCollectiveInt(A, col, 2);
36694f572ea9SToby Isaac   PetscAssertPointer(vals, 3);
3670cac4c232SBarry Smith   PetscUseMethod(A, "MatDenseGetColumn_C", (Mat, PetscInt, PetscScalar **), (A, col, vals));
36713ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
367286aefd0dSHong Zhang }
367386aefd0dSHong Zhang 
367486aefd0dSHong Zhang /*@C
367511a5261eSBarry Smith   MatDenseRestoreColumn - returns access to a column of a `MATDENSE` matrix which is returned by `MatDenseGetColumn()`.
367686aefd0dSHong Zhang 
367786aefd0dSHong Zhang   Not Collective
367886aefd0dSHong Zhang 
3679742765d3SMatthew Knepley   Input Parameters:
3680fe59aa6dSJacob Faibussowitsch + A    - a `MATSEQDENSE` or `MATMPIDENSE` matrix
36812ef1f0ffSBarry Smith - vals - pointer to the data (may be `NULL`)
368286aefd0dSHong Zhang 
368386aefd0dSHong Zhang   Level: intermediate
368486aefd0dSHong Zhang 
36851cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATDENSE`, `MatDenseGetColumn()`
368686aefd0dSHong Zhang @*/
36875d83a8b1SBarry Smith PetscErrorCode MatDenseRestoreColumn(Mat A, PetscScalar *vals[])
3688d71ae5a4SJacob Faibussowitsch {
368986aefd0dSHong Zhang   PetscFunctionBegin;
3690d5ea218eSStefano Zampini   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
36914f572ea9SToby Isaac   PetscAssertPointer(vals, 2);
3692cac4c232SBarry Smith   PetscUseMethod(A, "MatDenseRestoreColumn_C", (Mat, PetscScalar **), (A, vals));
36933ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
369486aefd0dSHong Zhang }
36956947451fSStefano Zampini 
36960f74d2c1SSatish Balay /*@
369711a5261eSBarry Smith   MatDenseGetColumnVec - Gives read-write access to a column of a `MATDENSE` matrix, represented as a `Vec`.
36986947451fSStefano Zampini 
36996947451fSStefano Zampini   Collective
37006947451fSStefano Zampini 
37015ea7661aSPierre Jolivet   Input Parameters:
3702fe59aa6dSJacob Faibussowitsch + A   - the `Mat` object
37036947451fSStefano Zampini - col - the column index
37046947451fSStefano Zampini 
37056947451fSStefano Zampini   Output Parameter:
37066947451fSStefano Zampini . v - the vector
37076947451fSStefano Zampini 
37082ef1f0ffSBarry Smith   Level: intermediate
37092ef1f0ffSBarry Smith 
37106947451fSStefano Zampini   Notes:
371111a5261eSBarry Smith   The vector is owned by PETSc. Users need to call `MatDenseRestoreColumnVec()` when the vector is no longer needed.
371211a5261eSBarry Smith 
371311a5261eSBarry Smith   Use `MatDenseGetColumnVecRead()` to obtain read-only access or `MatDenseGetColumnVecWrite()` for write-only access.
37146947451fSStefano Zampini 
37151cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATDENSE`, `MATDENSECUDA`, `MATDENSEHIP`, `MatDenseGetColumnVecRead()`, `MatDenseGetColumnVecWrite()`, `MatDenseRestoreColumnVec()`, `MatDenseRestoreColumnVecRead()`, `MatDenseRestoreColumnVecWrite()`, `MatDenseGetColumn()`
37166947451fSStefano Zampini @*/
3717d71ae5a4SJacob Faibussowitsch PetscErrorCode MatDenseGetColumnVec(Mat A, PetscInt col, Vec *v)
3718d71ae5a4SJacob Faibussowitsch {
37196947451fSStefano Zampini   PetscFunctionBegin;
37206947451fSStefano Zampini   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
37216947451fSStefano Zampini   PetscValidType(A, 1);
37226947451fSStefano Zampini   PetscValidLogicalCollectiveInt(A, col, 2);
37234f572ea9SToby Isaac   PetscAssertPointer(v, 3);
372428b400f6SJacob Faibussowitsch   PetscCheck(A->preallocated, PetscObjectComm((PetscObject)A), PETSC_ERR_ORDER, "Matrix not preallocated");
37252cf15c64SPierre 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);
3726cac4c232SBarry Smith   PetscUseMethod(A, "MatDenseGetColumnVec_C", (Mat, PetscInt, Vec *), (A, col, v));
37273ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
37286947451fSStefano Zampini }
37296947451fSStefano Zampini 
37300f74d2c1SSatish Balay /*@
3731fb850c59SBarry Smith   MatDenseRestoreColumnVec - Returns access to a column of a dense matrix obtained from `MatDenseGetColumnVec()`.
37326947451fSStefano Zampini 
37336947451fSStefano Zampini   Collective
37346947451fSStefano Zampini 
37355ea7661aSPierre Jolivet   Input Parameters:
3736fb850c59SBarry Smith + A   - the `Mat` object
37376947451fSStefano Zampini . col - the column index
3738fb850c59SBarry Smith - v   - the `Vec` object (may be `NULL`)
37396947451fSStefano Zampini 
37406947451fSStefano Zampini   Level: intermediate
37416947451fSStefano Zampini 
37421cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATDENSE`, `MATDENSECUDA`, `MATDENSEHIP`, `MatDenseGetColumnVec()`, `MatDenseGetColumnVecRead()`, `MatDenseGetColumnVecWrite()`, `MatDenseRestoreColumnVecRead()`, `MatDenseRestoreColumnVecWrite()`
37436947451fSStefano Zampini @*/
3744d71ae5a4SJacob Faibussowitsch PetscErrorCode MatDenseRestoreColumnVec(Mat A, PetscInt col, Vec *v)
3745d71ae5a4SJacob Faibussowitsch {
37466947451fSStefano Zampini   PetscFunctionBegin;
37476947451fSStefano Zampini   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
37486947451fSStefano Zampini   PetscValidType(A, 1);
37496947451fSStefano Zampini   PetscValidLogicalCollectiveInt(A, col, 2);
375008401ef6SPierre Jolivet   PetscCheck(A->preallocated, PetscObjectComm((PetscObject)A), PETSC_ERR_ORDER, "Matrix not preallocated");
37512cf15c64SPierre 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);
3752cac4c232SBarry Smith   PetscUseMethod(A, "MatDenseRestoreColumnVec_C", (Mat, PetscInt, Vec *), (A, col, v));
37533ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
37546947451fSStefano Zampini }
37556947451fSStefano Zampini 
37560f74d2c1SSatish Balay /*@
3757fb850c59SBarry Smith   MatDenseGetColumnVecRead - Gives read-only access to a column of a dense matrix, represented as a `Vec`.
37586947451fSStefano Zampini 
37596947451fSStefano Zampini   Collective
37606947451fSStefano Zampini 
37615ea7661aSPierre Jolivet   Input Parameters:
3762fe59aa6dSJacob Faibussowitsch + A   - the `Mat` object
37636947451fSStefano Zampini - col - the column index
37646947451fSStefano Zampini 
37656947451fSStefano Zampini   Output Parameter:
37666947451fSStefano Zampini . v - the vector
37676947451fSStefano Zampini 
37682ef1f0ffSBarry Smith   Level: intermediate
37692ef1f0ffSBarry Smith 
37706947451fSStefano Zampini   Notes:
37716947451fSStefano Zampini   The vector is owned by PETSc and users cannot modify it.
377211a5261eSBarry Smith 
37732ef1f0ffSBarry Smith   Users need to call `MatDenseRestoreColumnVecRead()` when the vector is no longer needed.
377411a5261eSBarry Smith 
37752ef1f0ffSBarry Smith   Use `MatDenseGetColumnVec()` to obtain read-write access or `MatDenseGetColumnVecWrite()` for write-only access.
37766947451fSStefano Zampini 
37771cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATDENSE`, `MATDENSECUDA`, `MATDENSEHIP`, `MatDenseGetColumnVec()`, `MatDenseGetColumnVecWrite()`, `MatDenseRestoreColumnVec()`, `MatDenseRestoreColumnVecRead()`, `MatDenseRestoreColumnVecWrite()`
37786947451fSStefano Zampini @*/
3779d71ae5a4SJacob Faibussowitsch PetscErrorCode MatDenseGetColumnVecRead(Mat A, PetscInt col, Vec *v)
3780d71ae5a4SJacob Faibussowitsch {
37816947451fSStefano Zampini   PetscFunctionBegin;
37826947451fSStefano Zampini   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
37836947451fSStefano Zampini   PetscValidType(A, 1);
37846947451fSStefano Zampini   PetscValidLogicalCollectiveInt(A, col, 2);
37854f572ea9SToby Isaac   PetscAssertPointer(v, 3);
378628b400f6SJacob Faibussowitsch   PetscCheck(A->preallocated, PetscObjectComm((PetscObject)A), PETSC_ERR_ORDER, "Matrix not preallocated");
37872cf15c64SPierre 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);
3788cac4c232SBarry Smith   PetscUseMethod(A, "MatDenseGetColumnVecRead_C", (Mat, PetscInt, Vec *), (A, col, v));
37893ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
37906947451fSStefano Zampini }
37916947451fSStefano Zampini 
37920f74d2c1SSatish Balay /*@
3793fb850c59SBarry Smith   MatDenseRestoreColumnVecRead - Returns access to a column of a dense matrix obtained from `MatDenseGetColumnVecRead()`.
37946947451fSStefano Zampini 
37956947451fSStefano Zampini   Collective
37966947451fSStefano Zampini 
37975ea7661aSPierre Jolivet   Input Parameters:
3798fe59aa6dSJacob Faibussowitsch + A   - the `Mat` object
37996947451fSStefano Zampini . col - the column index
3800fb850c59SBarry Smith - v   - the `Vec` object (may be `NULL`)
38016947451fSStefano Zampini 
38026947451fSStefano Zampini   Level: intermediate
38036947451fSStefano Zampini 
38041cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATDENSE`, `MATDENSECUDA`, `MATDENSEHIP`, `MatDenseGetColumnVec()`, `MatDenseGetColumnVecRead()`, `MatDenseGetColumnVecWrite()`, `MatDenseRestoreColumnVec()`, `MatDenseRestoreColumnVecWrite()`
38056947451fSStefano Zampini @*/
3806d71ae5a4SJacob Faibussowitsch PetscErrorCode MatDenseRestoreColumnVecRead(Mat A, PetscInt col, Vec *v)
3807d71ae5a4SJacob Faibussowitsch {
38086947451fSStefano Zampini   PetscFunctionBegin;
38096947451fSStefano Zampini   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
38106947451fSStefano Zampini   PetscValidType(A, 1);
38116947451fSStefano Zampini   PetscValidLogicalCollectiveInt(A, col, 2);
381208401ef6SPierre Jolivet   PetscCheck(A->preallocated, PetscObjectComm((PetscObject)A), PETSC_ERR_ORDER, "Matrix not preallocated");
38132cf15c64SPierre 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);
3814cac4c232SBarry Smith   PetscUseMethod(A, "MatDenseRestoreColumnVecRead_C", (Mat, PetscInt, Vec *), (A, col, v));
38153ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
38166947451fSStefano Zampini }
38176947451fSStefano Zampini 
38180f74d2c1SSatish Balay /*@
3819fb850c59SBarry Smith   MatDenseGetColumnVecWrite - Gives write-only access to a column of a dense matrix, represented as a `Vec`.
38206947451fSStefano Zampini 
38216947451fSStefano Zampini   Collective
38226947451fSStefano Zampini 
38235ea7661aSPierre Jolivet   Input Parameters:
3824fe59aa6dSJacob Faibussowitsch + A   - the `Mat` object
38256947451fSStefano Zampini - col - the column index
38266947451fSStefano Zampini 
38276947451fSStefano Zampini   Output Parameter:
38286947451fSStefano Zampini . v - the vector
38296947451fSStefano Zampini 
38306947451fSStefano Zampini   Level: intermediate
38316947451fSStefano Zampini 
38322ef1f0ffSBarry Smith   Notes:
38332ef1f0ffSBarry Smith   The vector is owned by PETSc. Users need to call `MatDenseRestoreColumnVecWrite()` when the vector is no longer needed.
38342ef1f0ffSBarry Smith 
38352ef1f0ffSBarry Smith   Use `MatDenseGetColumnVec()` to obtain read-write access or `MatDenseGetColumnVecRead()` for read-only access.
38362ef1f0ffSBarry Smith 
38371cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATDENSE`, `MATDENSECUDA`, `MATDENSEHIP`, `MatDenseGetColumnVec()`, `MatDenseGetColumnVecRead()`, `MatDenseRestoreColumnVec()`, `MatDenseRestoreColumnVecRead()`, `MatDenseRestoreColumnVecWrite()`
38386947451fSStefano Zampini @*/
3839d71ae5a4SJacob Faibussowitsch PetscErrorCode MatDenseGetColumnVecWrite(Mat A, PetscInt col, Vec *v)
3840d71ae5a4SJacob Faibussowitsch {
38416947451fSStefano Zampini   PetscFunctionBegin;
38426947451fSStefano Zampini   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
38436947451fSStefano Zampini   PetscValidType(A, 1);
38446947451fSStefano Zampini   PetscValidLogicalCollectiveInt(A, col, 2);
38454f572ea9SToby Isaac   PetscAssertPointer(v, 3);
384628b400f6SJacob Faibussowitsch   PetscCheck(A->preallocated, PetscObjectComm((PetscObject)A), PETSC_ERR_ORDER, "Matrix not preallocated");
3847aed4548fSBarry 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);
3848cac4c232SBarry Smith   PetscUseMethod(A, "MatDenseGetColumnVecWrite_C", (Mat, PetscInt, Vec *), (A, col, v));
38493ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
38506947451fSStefano Zampini }
38516947451fSStefano Zampini 
38520f74d2c1SSatish Balay /*@
3853fb850c59SBarry Smith   MatDenseRestoreColumnVecWrite - Returns access to a column of a dense matrix obtained from `MatDenseGetColumnVecWrite()`.
38546947451fSStefano Zampini 
38556947451fSStefano Zampini   Collective
38566947451fSStefano Zampini 
38575ea7661aSPierre Jolivet   Input Parameters:
3858fe59aa6dSJacob Faibussowitsch + A   - the `Mat` object
38596947451fSStefano Zampini . col - the column index
38602ef1f0ffSBarry Smith - v   - the `Vec` object (may be `NULL`)
38616947451fSStefano Zampini 
38626947451fSStefano Zampini   Level: intermediate
38636947451fSStefano Zampini 
38641cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATDENSE`, `MATDENSECUDA`, `MATDENSEHIP`, `MatDenseGetColumnVec()`, `MatDenseGetColumnVecRead()`, `MatDenseGetColumnVecWrite()`, `MatDenseRestoreColumnVec()`, `MatDenseRestoreColumnVecRead()`
38656947451fSStefano Zampini @*/
3866d71ae5a4SJacob Faibussowitsch PetscErrorCode MatDenseRestoreColumnVecWrite(Mat A, PetscInt col, Vec *v)
3867d71ae5a4SJacob Faibussowitsch {
38686947451fSStefano Zampini   PetscFunctionBegin;
38696947451fSStefano Zampini   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
38706947451fSStefano Zampini   PetscValidType(A, 1);
38716947451fSStefano Zampini   PetscValidLogicalCollectiveInt(A, col, 2);
387208401ef6SPierre Jolivet   PetscCheck(A->preallocated, PetscObjectComm((PetscObject)A), PETSC_ERR_ORDER, "Matrix not preallocated");
3873aed4548fSBarry 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);
3874cac4c232SBarry Smith   PetscUseMethod(A, "MatDenseRestoreColumnVecWrite_C", (Mat, PetscInt, Vec *), (A, col, v));
38753ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
38766947451fSStefano Zampini }
38775ea7661aSPierre Jolivet 
38780f74d2c1SSatish Balay /*@
3879fb850c59SBarry Smith   MatDenseGetSubMatrix - Gives access to a block of rows and columns of a dense matrix, represented as a `Mat`.
38805ea7661aSPierre Jolivet 
38815ea7661aSPierre Jolivet   Collective
38825ea7661aSPierre Jolivet 
38835ea7661aSPierre Jolivet   Input Parameters:
3884fb850c59SBarry Smith + A      - the `Mat` object
38852ef1f0ffSBarry Smith . rbegin - the first global row index in the block (if `PETSC_DECIDE`, is 0)
38862ef1f0ffSBarry Smith . rend   - the global row index past the last one in the block (if `PETSC_DECIDE`, is `M`)
38872ef1f0ffSBarry Smith . cbegin - the first global column index in the block (if `PETSC_DECIDE`, is 0)
38882ef1f0ffSBarry Smith - cend   - the global column index past the last one in the block (if `PETSC_DECIDE`, is `N`)
38895ea7661aSPierre Jolivet 
38905ea7661aSPierre Jolivet   Output Parameter:
38915ea7661aSPierre Jolivet . v - the matrix
38925ea7661aSPierre Jolivet 
38935ea7661aSPierre Jolivet   Level: intermediate
38945ea7661aSPierre Jolivet 
38952ef1f0ffSBarry Smith   Notes:
38962ef1f0ffSBarry Smith   The matrix is owned by PETSc. Users need to call `MatDenseRestoreSubMatrix()` when the matrix is no longer needed.
38972ef1f0ffSBarry Smith 
38982ef1f0ffSBarry 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.
38992ef1f0ffSBarry Smith 
39001cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATDENSE`, `MATDENSECUDA`, `MATDENSEHIP`, `MatDenseGetColumnVec()`, `MatDenseRestoreColumnVec()`, `MatDenseRestoreSubMatrix()`
39015ea7661aSPierre Jolivet @*/
3902d71ae5a4SJacob Faibussowitsch PetscErrorCode MatDenseGetSubMatrix(Mat A, PetscInt rbegin, PetscInt rend, PetscInt cbegin, PetscInt cend, Mat *v)
3903d71ae5a4SJacob Faibussowitsch {
39045ea7661aSPierre Jolivet   PetscFunctionBegin;
39055ea7661aSPierre Jolivet   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
39065ea7661aSPierre Jolivet   PetscValidType(A, 1);
3907a2748737SPierre Jolivet   PetscValidLogicalCollectiveInt(A, rbegin, 2);
3908a2748737SPierre Jolivet   PetscValidLogicalCollectiveInt(A, rend, 3);
3909a2748737SPierre Jolivet   PetscValidLogicalCollectiveInt(A, cbegin, 4);
3910a2748737SPierre Jolivet   PetscValidLogicalCollectiveInt(A, cend, 5);
39114f572ea9SToby Isaac   PetscAssertPointer(v, 6);
3912a2748737SPierre Jolivet   if (rbegin == PETSC_DECIDE) rbegin = 0;
3913a2748737SPierre Jolivet   if (rend == PETSC_DECIDE) rend = A->rmap->N;
3914a2748737SPierre Jolivet   if (cbegin == PETSC_DECIDE) cbegin = 0;
3915a2748737SPierre Jolivet   if (cend == PETSC_DECIDE) cend = A->cmap->N;
391628b400f6SJacob Faibussowitsch   PetscCheck(A->preallocated, PetscObjectComm((PetscObject)A), PETSC_ERR_ORDER, "Matrix not preallocated");
3917a2748737SPierre 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);
3918a2748737SPierre 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);
3919a2748737SPierre 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);
3920a2748737SPierre 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);
3921a2748737SPierre Jolivet   PetscUseMethod(A, "MatDenseGetSubMatrix_C", (Mat, PetscInt, PetscInt, PetscInt, PetscInt, Mat *), (A, rbegin, rend, cbegin, cend, v));
39223ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
39235ea7661aSPierre Jolivet }
39245ea7661aSPierre Jolivet 
39250f74d2c1SSatish Balay /*@
3926fb850c59SBarry Smith   MatDenseRestoreSubMatrix - Returns access to a block of columns of a dense matrix obtained from `MatDenseGetSubMatrix()`.
39275ea7661aSPierre Jolivet 
39285ea7661aSPierre Jolivet   Collective
39295ea7661aSPierre Jolivet 
39305ea7661aSPierre Jolivet   Input Parameters:
3931fe59aa6dSJacob Faibussowitsch + A - the `Mat` object
39322ef1f0ffSBarry Smith - v - the `Mat` object (may be `NULL`)
39335ea7661aSPierre Jolivet 
39345ea7661aSPierre Jolivet   Level: intermediate
39355ea7661aSPierre Jolivet 
39361cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATDENSE`, `MATDENSECUDA`, `MATDENSEHIP`, `MatDenseGetColumnVec()`, `MatDenseRestoreColumnVec()`, `MatDenseGetSubMatrix()`
39375ea7661aSPierre Jolivet @*/
3938d71ae5a4SJacob Faibussowitsch PetscErrorCode MatDenseRestoreSubMatrix(Mat A, Mat *v)
3939d71ae5a4SJacob Faibussowitsch {
39405ea7661aSPierre Jolivet   PetscFunctionBegin;
39415ea7661aSPierre Jolivet   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
39425ea7661aSPierre Jolivet   PetscValidType(A, 1);
39434f572ea9SToby Isaac   PetscAssertPointer(v, 2);
3944cac4c232SBarry Smith   PetscUseMethod(A, "MatDenseRestoreSubMatrix_C", (Mat, Mat *), (A, v));
39453ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
39465ea7661aSPierre Jolivet }
39478a9c020eSBarry Smith 
39488a9c020eSBarry Smith #include <petscblaslapack.h>
39498a9c020eSBarry Smith #include <petsc/private/kernels/blockinvert.h>
39508a9c020eSBarry Smith 
3951d71ae5a4SJacob Faibussowitsch PetscErrorCode MatSeqDenseInvert(Mat A)
3952d71ae5a4SJacob Faibussowitsch {
3953d63b1753SJacob Faibussowitsch   PetscInt        m;
39548a9c020eSBarry Smith   const PetscReal shift = 0.0;
3955d63b1753SJacob Faibussowitsch   PetscBool       allowzeropivot, zeropivotdetected = PETSC_FALSE;
3956d63b1753SJacob Faibussowitsch   PetscScalar    *values;
39578a9c020eSBarry Smith 
39588a9c020eSBarry Smith   PetscFunctionBegin;
3959d63b1753SJacob Faibussowitsch   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
3960d63b1753SJacob Faibussowitsch   PetscCall(MatDenseGetArray(A, &values));
3961d63b1753SJacob Faibussowitsch   PetscCall(MatGetLocalSize(A, &m, NULL));
3962d63b1753SJacob Faibussowitsch   allowzeropivot = PetscNot(A->erroriffailure);
39638a9c020eSBarry Smith   /* factor and invert each block */
3964d63b1753SJacob Faibussowitsch   switch (m) {
3965d71ae5a4SJacob Faibussowitsch   case 1:
3966d71ae5a4SJacob Faibussowitsch     values[0] = (PetscScalar)1.0 / (values[0] + shift);
3967d71ae5a4SJacob Faibussowitsch     break;
39688a9c020eSBarry Smith   case 2:
39698a9c020eSBarry Smith     PetscCall(PetscKernel_A_gets_inverse_A_2(values, shift, allowzeropivot, &zeropivotdetected));
39708a9c020eSBarry Smith     if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
39718a9c020eSBarry Smith     break;
39728a9c020eSBarry Smith   case 3:
39738a9c020eSBarry Smith     PetscCall(PetscKernel_A_gets_inverse_A_3(values, shift, allowzeropivot, &zeropivotdetected));
39748a9c020eSBarry Smith     if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
39758a9c020eSBarry Smith     break;
39768a9c020eSBarry Smith   case 4:
39778a9c020eSBarry Smith     PetscCall(PetscKernel_A_gets_inverse_A_4(values, shift, allowzeropivot, &zeropivotdetected));
39788a9c020eSBarry Smith     if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
39798a9c020eSBarry Smith     break;
39809371c9d4SSatish Balay   case 5: {
39818a9c020eSBarry Smith     PetscScalar work[25];
39828a9c020eSBarry Smith     PetscInt    ipvt[5];
39838a9c020eSBarry Smith 
39848a9c020eSBarry Smith     PetscCall(PetscKernel_A_gets_inverse_A_5(values, ipvt, work, shift, allowzeropivot, &zeropivotdetected));
39858a9c020eSBarry Smith     if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
39869371c9d4SSatish Balay   } break;
39878a9c020eSBarry Smith   case 6:
39888a9c020eSBarry Smith     PetscCall(PetscKernel_A_gets_inverse_A_6(values, shift, allowzeropivot, &zeropivotdetected));
39898a9c020eSBarry Smith     if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
39908a9c020eSBarry Smith     break;
39918a9c020eSBarry Smith   case 7:
39928a9c020eSBarry Smith     PetscCall(PetscKernel_A_gets_inverse_A_7(values, shift, allowzeropivot, &zeropivotdetected));
39938a9c020eSBarry Smith     if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
39948a9c020eSBarry Smith     break;
39959371c9d4SSatish Balay   default: {
39968a9c020eSBarry Smith     PetscInt    *v_pivots, *IJ, j;
39978a9c020eSBarry Smith     PetscScalar *v_work;
39988a9c020eSBarry Smith 
3999d63b1753SJacob Faibussowitsch     PetscCall(PetscMalloc3(m, &v_work, m, &v_pivots, m, &IJ));
4000d63b1753SJacob Faibussowitsch     for (j = 0; j < m; j++) IJ[j] = j;
4001d63b1753SJacob Faibussowitsch     PetscCall(PetscKernel_A_gets_inverse_A(m, values, v_pivots, v_work, allowzeropivot, &zeropivotdetected));
40028a9c020eSBarry Smith     if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
40038a9c020eSBarry Smith     PetscCall(PetscFree3(v_work, v_pivots, IJ));
40048a9c020eSBarry Smith   }
40058a9c020eSBarry Smith   }
4006d63b1753SJacob Faibussowitsch   PetscCall(MatDenseRestoreArray(A, &values));
40073ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
40088a9c020eSBarry Smith }
4009