xref: /petsc/src/mat/impls/dense/seq/dense.c (revision 9f196a0264fbaf0568fead3a30c861c7ae4cf663)
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.*/
79097b17b2cSPierre Jolivet PetscErrorCode MatLUFactor_SeqDense(Mat A, IS row, IS col, PETSC_UNUSED 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 
82097b17b2cSPierre Jolivet static PetscErrorCode MatLUFactorNumeric_SeqDense(Mat fact, Mat A, const MatFactorInfo *info)
821d71ae5a4SJacob Faibussowitsch {
8224396437dSToby Isaac   PetscFunctionBegin;
8239566063dSJacob Faibussowitsch   PetscCall(MatDuplicateNoCreate_SeqDense(fact, A, MAT_COPY_VALUES));
82497b17b2cSPierre Jolivet   PetscUseTypeMethod(fact, lufactor, NULL, NULL, info);
8253ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
8264396437dSToby Isaac }
8274396437dSToby Isaac 
82897b17b2cSPierre Jolivet PetscErrorCode MatLUFactorSymbolic_SeqDense(Mat fact, Mat A, IS row, IS col, PETSC_UNUSED const MatFactorInfo *info)
829d71ae5a4SJacob Faibussowitsch {
8304396437dSToby Isaac   PetscFunctionBegin;
8314396437dSToby Isaac   fact->preallocated         = PETSC_TRUE;
8324396437dSToby Isaac   fact->assembled            = PETSC_TRUE;
8334396437dSToby Isaac   fact->ops->lufactornumeric = MatLUFactorNumeric_SeqDense;
8343ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
8354396437dSToby Isaac }
8364396437dSToby Isaac 
837a49dc2a2SStefano Zampini /* Cholesky as L*L^T or L*D*L^T and the symmetric/hermitian complex variants */
83897b17b2cSPierre Jolivet PetscErrorCode MatCholeskyFactor_SeqDense(Mat A, IS perm, PETSC_UNUSED const MatFactorInfo *minfo)
839d71ae5a4SJacob Faibussowitsch {
840db4efbfdSBarry Smith   Mat_SeqDense *mat = (Mat_SeqDense *)A->data;
841c5df96a5SBarry Smith   PetscBLASInt  info, n;
842db4efbfdSBarry Smith 
843db4efbfdSBarry Smith   PetscFunctionBegin;
8449566063dSJacob Faibussowitsch   PetscCall(PetscBLASIntCast(A->cmap->n, &n));
8453ba16761SJacob Faibussowitsch   if (!A->rmap->n || !A->cmap->n) PetscFunctionReturn(PETSC_SUCCESS);
846b94d7dedSBarry Smith   if (A->spd == PETSC_BOOL3_TRUE) {
8479566063dSJacob Faibussowitsch     PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF));
848792fecdfSBarry Smith     PetscCallBLAS("LAPACKpotrf", LAPACKpotrf_("L", &n, mat->v, &mat->lda, &info));
8499566063dSJacob Faibussowitsch     PetscCall(PetscFPTrapPop());
850a49dc2a2SStefano Zampini #if defined(PETSC_USE_COMPLEX)
851b94d7dedSBarry Smith   } else if (A->hermitian == PETSC_BOOL3_TRUE) {
852789736e1SBarry Smith     if (!mat->pivots) PetscCall(PetscMalloc1(A->rmap->n, &mat->pivots));
853a49dc2a2SStefano Zampini     if (!mat->fwork) {
854a49dc2a2SStefano Zampini       PetscScalar dummy;
855a49dc2a2SStefano Zampini 
856a49dc2a2SStefano Zampini       mat->lfwork = -1;
8579566063dSJacob Faibussowitsch       PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF));
858792fecdfSBarry Smith       PetscCallBLAS("LAPACKhetrf", LAPACKhetrf_("L", &n, mat->v, &mat->lda, mat->pivots, &dummy, &mat->lfwork, &info));
8599566063dSJacob Faibussowitsch       PetscCall(PetscFPTrapPop());
86007c83e99SJose E. Roman       PetscCall(PetscBLASIntCast((PetscCount)(PetscRealPart(dummy)), &mat->lfwork));
8619566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(mat->lfwork, &mat->fwork));
862a49dc2a2SStefano Zampini     }
8639566063dSJacob Faibussowitsch     PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF));
864792fecdfSBarry Smith     PetscCallBLAS("LAPACKhetrf", LAPACKhetrf_("L", &n, mat->v, &mat->lda, mat->pivots, mat->fwork, &mat->lfwork, &info));
8659566063dSJacob Faibussowitsch     PetscCall(PetscFPTrapPop());
866a49dc2a2SStefano Zampini #endif
867a49dc2a2SStefano Zampini   } else { /* symmetric case */
868789736e1SBarry Smith     if (!mat->pivots) PetscCall(PetscMalloc1(A->rmap->n, &mat->pivots));
869a49dc2a2SStefano Zampini     if (!mat->fwork) {
870a49dc2a2SStefano Zampini       PetscScalar dummy;
871a49dc2a2SStefano Zampini 
872a49dc2a2SStefano Zampini       mat->lfwork = -1;
8739566063dSJacob Faibussowitsch       PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF));
874792fecdfSBarry Smith       PetscCallBLAS("LAPACKsytrf", LAPACKsytrf_("L", &n, mat->v, &mat->lda, mat->pivots, &dummy, &mat->lfwork, &info));
8759566063dSJacob Faibussowitsch       PetscCall(PetscFPTrapPop());
8766497c311SBarry Smith       PetscCall(PetscBLASIntCast((PetscCount)(PetscRealPart(dummy)), &mat->lfwork));
8779566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(mat->lfwork, &mat->fwork));
878a49dc2a2SStefano Zampini     }
8799566063dSJacob Faibussowitsch     PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF));
880792fecdfSBarry Smith     PetscCallBLAS("LAPACKsytrf", LAPACKsytrf_("L", &n, mat->v, &mat->lda, mat->pivots, mat->fwork, &mat->lfwork, &info));
8819566063dSJacob Faibussowitsch     PetscCall(PetscFPTrapPop());
882a49dc2a2SStefano Zampini   }
883835f2295SStefano Zampini   PetscCheck(!info, PETSC_COMM_SELF, PETSC_ERR_MAT_CH_ZRPVT, "Bad factorization: zero pivot in row %" PetscBLASInt_FMT, info - 1);
8848208b9aeSStefano Zampini 
8854396437dSToby Isaac   A->ops->solve             = MatSolve_SeqDense_Cholesky;
8864396437dSToby Isaac   A->ops->matsolve          = MatMatSolve_SeqDense_Cholesky;
8874396437dSToby Isaac   A->ops->solvetranspose    = MatSolveTranspose_SeqDense_Cholesky;
8884396437dSToby Isaac   A->ops->matsolvetranspose = MatMatSolveTranspose_SeqDense_Cholesky;
889d5f3da31SBarry Smith   A->factortype             = MAT_FACTOR_CHOLESKY;
8902205254eSKarl Rupp 
8919566063dSJacob Faibussowitsch   PetscCall(PetscFree(A->solvertype));
8929566063dSJacob Faibussowitsch   PetscCall(PetscStrallocpy(MATSOLVERPETSC, &A->solvertype));
893f6224b95SHong Zhang 
8949566063dSJacob Faibussowitsch   PetscCall(PetscLogFlops((1.0 * A->cmap->n * A->cmap->n * A->cmap->n) / 3.0));
8953ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
896db4efbfdSBarry Smith }
897db4efbfdSBarry Smith 
89897b17b2cSPierre Jolivet static PetscErrorCode MatCholeskyFactorNumeric_SeqDense(Mat fact, Mat A, const MatFactorInfo *info)
899d71ae5a4SJacob Faibussowitsch {
900db4efbfdSBarry Smith   PetscFunctionBegin;
9019566063dSJacob Faibussowitsch   PetscCall(MatDuplicateNoCreate_SeqDense(fact, A, MAT_COPY_VALUES));
90297b17b2cSPierre Jolivet   PetscUseTypeMethod(fact, choleskyfactor, NULL, info);
9033ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
904db4efbfdSBarry Smith }
905db4efbfdSBarry Smith 
906d71ae5a4SJacob Faibussowitsch PetscErrorCode MatCholeskyFactorSymbolic_SeqDense(Mat fact, Mat A, IS row, const MatFactorInfo *info)
907d71ae5a4SJacob Faibussowitsch {
908db4efbfdSBarry Smith   PetscFunctionBegin;
909c3ef05f6SHong Zhang   fact->assembled                  = PETSC_TRUE;
9101bbcc794SSatish Balay   fact->preallocated               = PETSC_TRUE;
911719d5645SBarry Smith   fact->ops->choleskyfactornumeric = MatCholeskyFactorNumeric_SeqDense;
9123ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
913db4efbfdSBarry Smith }
914db4efbfdSBarry Smith 
91597b17b2cSPierre Jolivet PetscErrorCode MatQRFactor_SeqDense(Mat A, IS col, PETSC_UNUSED const MatFactorInfo *minfo)
916d71ae5a4SJacob Faibussowitsch {
9174905a7bcSToby Isaac   Mat_SeqDense *mat = (Mat_SeqDense *)A->data;
9184905a7bcSToby Isaac   PetscBLASInt  n, m, info, min, max;
9194905a7bcSToby Isaac 
9204905a7bcSToby Isaac   PetscFunctionBegin;
9219566063dSJacob Faibussowitsch   PetscCall(PetscBLASIntCast(A->cmap->n, &n));
9229566063dSJacob Faibussowitsch   PetscCall(PetscBLASIntCast(A->rmap->n, &m));
9234396437dSToby Isaac   max = PetscMax(m, n);
9244396437dSToby Isaac   min = PetscMin(m, n);
925789736e1SBarry Smith   if (!mat->tau) PetscCall(PetscMalloc1(min, &mat->tau));
926789736e1SBarry Smith   if (!mat->pivots) PetscCall(PetscMalloc1(n, &mat->pivots));
927f4f49eeaSPierre Jolivet   if (!mat->qrrhs) PetscCall(MatCreateVecs(A, NULL, &mat->qrrhs));
9283ba16761SJacob Faibussowitsch   if (!A->rmap->n || !A->cmap->n) PetscFunctionReturn(PETSC_SUCCESS);
9294905a7bcSToby Isaac   if (!mat->fwork) {
9304905a7bcSToby Isaac     PetscScalar dummy;
9314905a7bcSToby Isaac 
9324905a7bcSToby Isaac     mat->lfwork = -1;
9339566063dSJacob Faibussowitsch     PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF));
934792fecdfSBarry Smith     PetscCallBLAS("LAPACKgeqrf", LAPACKgeqrf_(&m, &n, mat->v, &mat->lda, mat->tau, &dummy, &mat->lfwork, &info));
9359566063dSJacob Faibussowitsch     PetscCall(PetscFPTrapPop());
9366497c311SBarry Smith     PetscCall(PetscBLASIntCast((PetscCount)(PetscRealPart(dummy)), &mat->lfwork));
9379566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(mat->lfwork, &mat->fwork));
9384905a7bcSToby Isaac   }
9399566063dSJacob Faibussowitsch   PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF));
940792fecdfSBarry Smith   PetscCallBLAS("LAPACKgeqrf", LAPACKgeqrf_(&m, &n, mat->v, &mat->lda, mat->tau, mat->fwork, &mat->lfwork, &info));
9419566063dSJacob Faibussowitsch   PetscCall(PetscFPTrapPop());
942835f2295SStefano Zampini   PetscCheck(!info, PETSC_COMM_SELF, PETSC_ERR_LIB, "Bad argument to QR factorization %" PetscBLASInt_FMT, info);
9434905a7bcSToby 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
9444905a7bcSToby Isaac   mat->rank = min;
9454905a7bcSToby Isaac 
9464396437dSToby Isaac   A->ops->solve    = MatSolve_SeqDense_QR;
9474396437dSToby Isaac   A->ops->matsolve = MatMatSolve_SeqDense_QR;
9484905a7bcSToby Isaac   A->factortype    = MAT_FACTOR_QR;
9494905a7bcSToby Isaac   if (m == n) {
9504396437dSToby Isaac     A->ops->solvetranspose    = MatSolveTranspose_SeqDense_QR;
9514396437dSToby Isaac     A->ops->matsolvetranspose = MatMatSolveTranspose_SeqDense_QR;
9524905a7bcSToby Isaac   }
9534905a7bcSToby Isaac 
9549566063dSJacob Faibussowitsch   PetscCall(PetscFree(A->solvertype));
9559566063dSJacob Faibussowitsch   PetscCall(PetscStrallocpy(MATSOLVERPETSC, &A->solvertype));
9564905a7bcSToby Isaac 
9579566063dSJacob Faibussowitsch   PetscCall(PetscLogFlops(2.0 * min * min * (max - min / 3.0)));
9583ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
9594905a7bcSToby Isaac }
9604905a7bcSToby Isaac 
96197b17b2cSPierre Jolivet static PetscErrorCode MatQRFactorNumeric_SeqDense(Mat fact, Mat A, const MatFactorInfo *info)
962d71ae5a4SJacob Faibussowitsch {
9634905a7bcSToby Isaac   PetscFunctionBegin;
9649566063dSJacob Faibussowitsch   PetscCall(MatDuplicateNoCreate_SeqDense(fact, A, MAT_COPY_VALUES));
96597b17b2cSPierre Jolivet   PetscUseMethod(fact, "MatQRFactor_C", (Mat, IS, const MatFactorInfo *), (fact, NULL, info));
9663ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
9674905a7bcSToby Isaac }
9684905a7bcSToby Isaac 
969d71ae5a4SJacob Faibussowitsch PetscErrorCode MatQRFactorSymbolic_SeqDense(Mat fact, Mat A, IS row, const MatFactorInfo *info)
970d71ae5a4SJacob Faibussowitsch {
9714905a7bcSToby Isaac   PetscFunctionBegin;
9724905a7bcSToby Isaac   fact->assembled    = PETSC_TRUE;
9734905a7bcSToby Isaac   fact->preallocated = PETSC_TRUE;
9749566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)fact, "MatQRFactorNumeric_C", MatQRFactorNumeric_SeqDense));
9753ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
9764905a7bcSToby Isaac }
9774905a7bcSToby Isaac 
978ca15aa20SStefano Zampini /* uses LAPACK */
979d71ae5a4SJacob Faibussowitsch PETSC_INTERN PetscErrorCode MatGetFactor_seqdense_petsc(Mat A, MatFactorType ftype, Mat *fact)
980d71ae5a4SJacob Faibussowitsch {
981db4efbfdSBarry Smith   PetscFunctionBegin;
9829566063dSJacob Faibussowitsch   PetscCall(MatCreate(PetscObjectComm((PetscObject)A), fact));
9839566063dSJacob Faibussowitsch   PetscCall(MatSetSizes(*fact, A->rmap->n, A->cmap->n, A->rmap->n, A->cmap->n));
9849566063dSJacob Faibussowitsch   PetscCall(MatSetType(*fact, MATDENSE));
98566e17bc3SBarry Smith   (*fact)->trivialsymbolic = PETSC_TRUE;
9862a350339SBarry Smith   if (ftype == MAT_FACTOR_LU || ftype == MAT_FACTOR_ILU) {
987db4efbfdSBarry Smith     (*fact)->ops->lufactorsymbolic  = MatLUFactorSymbolic_SeqDense;
9882a350339SBarry Smith     (*fact)->ops->ilufactorsymbolic = MatLUFactorSymbolic_SeqDense;
989bf5a80bcSToby Isaac   } else if (ftype == MAT_FACTOR_CHOLESKY || ftype == MAT_FACTOR_ICC) {
990db4efbfdSBarry Smith     (*fact)->ops->choleskyfactorsymbolic = MatCholeskyFactorSymbolic_SeqDense;
991bf5a80bcSToby Isaac   } else if (ftype == MAT_FACTOR_QR) {
992f4f49eeaSPierre Jolivet     PetscCall(PetscObjectComposeFunction((PetscObject)*fact, "MatQRFactorSymbolic_C", MatQRFactorSymbolic_SeqDense));
993db4efbfdSBarry Smith   }
994d5f3da31SBarry Smith   (*fact)->factortype = ftype;
99500c67f3bSHong Zhang 
9969566063dSJacob Faibussowitsch   PetscCall(PetscFree((*fact)->solvertype));
9979566063dSJacob Faibussowitsch   PetscCall(PetscStrallocpy(MATSOLVERPETSC, &(*fact)->solvertype));
9989566063dSJacob Faibussowitsch   PetscCall(PetscStrallocpy(MATORDERINGEXTERNAL, (char **)&(*fact)->preferredordering[MAT_FACTOR_LU]));
9999566063dSJacob Faibussowitsch   PetscCall(PetscStrallocpy(MATORDERINGEXTERNAL, (char **)&(*fact)->preferredordering[MAT_FACTOR_ILU]));
10009566063dSJacob Faibussowitsch   PetscCall(PetscStrallocpy(MATORDERINGEXTERNAL, (char **)&(*fact)->preferredordering[MAT_FACTOR_CHOLESKY]));
10019566063dSJacob Faibussowitsch   PetscCall(PetscStrallocpy(MATORDERINGEXTERNAL, (char **)&(*fact)->preferredordering[MAT_FACTOR_ICC]));
10023ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1003db4efbfdSBarry Smith }
1004db4efbfdSBarry Smith 
1005d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatSOR_SeqDense(Mat A, Vec bb, PetscReal omega, MatSORType flag, PetscReal shift, PetscInt its, PetscInt lits, Vec xx)
1006d71ae5a4SJacob Faibussowitsch {
1007c0bbcb79SLois Curfman McInnes   Mat_SeqDense      *mat = (Mat_SeqDense *)A->data;
1008d9ca1df4SBarry Smith   PetscScalar       *x, *v = mat->v, zero = 0.0, xt;
1009d9ca1df4SBarry Smith   const PetscScalar *b;
1010d0f46423SBarry Smith   PetscInt           m = A->rmap->n, i;
101123fff9afSBarry Smith   PetscBLASInt       o = 1, bm = 0;
1012289bc588SBarry Smith 
10133a40ed3dSBarry Smith   PetscFunctionBegin;
101447d993e7Ssuyashtn #if defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
101508401ef6SPierre Jolivet   PetscCheck(A->offloadmask != PETSC_OFFLOAD_GPU, PETSC_COMM_SELF, PETSC_ERR_SUP, "Not implemented");
1016ca15aa20SStefano Zampini #endif
1017422a814eSBarry Smith   if (shift == -1) shift = 0.0; /* negative shift indicates do not error on zero diagonal; this code never zeros on zero diagonal */
10189566063dSJacob Faibussowitsch   PetscCall(PetscBLASIntCast(m, &bm));
1019289bc588SBarry Smith   if (flag & SOR_ZERO_INITIAL_GUESS) {
10203bffc371SBarry Smith     /* this is a hack fix, should have another version without the second BLASdotu */
10219566063dSJacob Faibussowitsch     PetscCall(VecSet(xx, zero));
1022289bc588SBarry Smith   }
10239566063dSJacob Faibussowitsch   PetscCall(VecGetArray(xx, &x));
10249566063dSJacob Faibussowitsch   PetscCall(VecGetArrayRead(bb, &b));
1025b965ef7fSBarry Smith   its = its * lits;
102608401ef6SPierre 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);
1027289bc588SBarry Smith   while (its--) {
1028fccaa45eSBarry Smith     if (flag & SOR_FORWARD_SWEEP || flag & SOR_LOCAL_FORWARD_SWEEP) {
1029289bc588SBarry Smith       for (i = 0; i < m; i++) {
1030792fecdfSBarry Smith         PetscCallBLAS("BLASdotu", xt = b[i] - BLASdotu_(&bm, v + i, &bm, x, &o));
1031883424caSPierre Jolivet         x[i] = (1. - omega) * x[i] + (xt + v[i + i * m] * x[i]) * omega / (v[i + i * m] + shift);
1032289bc588SBarry Smith       }
1033289bc588SBarry Smith     }
1034fccaa45eSBarry Smith     if (flag & SOR_BACKWARD_SWEEP || flag & SOR_LOCAL_BACKWARD_SWEEP) {
1035289bc588SBarry Smith       for (i = m - 1; i >= 0; i--) {
1036792fecdfSBarry Smith         PetscCallBLAS("BLASdotu", xt = b[i] - BLASdotu_(&bm, v + i, &bm, x, &o));
1037883424caSPierre Jolivet         x[i] = (1. - omega) * x[i] + (xt + v[i + i * m] * x[i]) * omega / (v[i + i * m] + shift);
1038289bc588SBarry Smith       }
1039289bc588SBarry Smith     }
1040289bc588SBarry Smith   }
10419566063dSJacob Faibussowitsch   PetscCall(VecRestoreArrayRead(bb, &b));
10429566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(xx, &x));
10433ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1044289bc588SBarry Smith }
1045289bc588SBarry Smith 
1046d016bddeSToby Isaac PETSC_INTERN PetscErrorCode MatMultColumnRangeKernel_SeqDense(Mat A, Vec xx, Vec yy, PetscInt c_start, PetscInt c_end, PetscBool trans, PetscBool herm)
1047d71ae5a4SJacob Faibussowitsch {
1048c0bbcb79SLois Curfman McInnes   Mat_SeqDense      *mat = (Mat_SeqDense *)A->data;
1049d9ca1df4SBarry Smith   PetscScalar       *y, _DOne = 1.0, _DZero = 0.0;
10500805154bSBarry Smith   PetscBLASInt       m, n, _One             = 1;
1051d9ca1df4SBarry Smith   const PetscScalar *v = mat->v, *x;
10523a40ed3dSBarry Smith 
10533a40ed3dSBarry Smith   PetscFunctionBegin;
10549566063dSJacob Faibussowitsch   PetscCall(PetscBLASIntCast(A->rmap->n, &m));
10550be0d8bdSHansol Suh   PetscCall(PetscBLASIntCast(c_end - c_start, &n));
10569566063dSJacob Faibussowitsch   PetscCall(VecGetArrayRead(xx, &x));
10579566063dSJacob Faibussowitsch   PetscCall(VecGetArrayWrite(yy, &y));
10580be0d8bdSHansol Suh   if (!m || !n) {
10595ac36cfcSBarry Smith     PetscBLASInt i;
1060459e8d23SBlanca Mellado Pinto     if (trans)
1061459e8d23SBlanca Mellado Pinto       for (i = 0; i < n; i++) y[i] = 0.0;
1062459e8d23SBlanca Mellado Pinto     else
10635ac36cfcSBarry Smith       for (i = 0; i < m; i++) y[i] = 0.0;
10645ac36cfcSBarry Smith   } else {
1065459e8d23SBlanca Mellado Pinto     if (trans) {
10660be0d8bdSHansol Suh       if (herm) PetscCallBLAS("BLASgemv", BLASgemv_("C", &m, &n, &_DOne, v + c_start * mat->lda, &mat->lda, x, &_One, &_DZero, y + c_start, &_One));
10670be0d8bdSHansol Suh       else PetscCallBLAS("BLASgemv", BLASgemv_("T", &m, &n, &_DOne, v + c_start * mat->lda, &mat->lda, x, &_One, &_DZero, y + c_start, &_One));
1068459e8d23SBlanca Mellado Pinto     } else {
10690be0d8bdSHansol Suh       PetscCallBLAS("BLASgemv", BLASgemv_("N", &m, &n, &_DOne, v + c_start * mat->lda, &mat->lda, x + c_start, &_One, &_DZero, y, &_One));
1070459e8d23SBlanca Mellado Pinto     }
10710be0d8bdSHansol Suh     PetscCall(PetscLogFlops(2.0 * m * n - n));
10725ac36cfcSBarry Smith   }
10739566063dSJacob Faibussowitsch   PetscCall(VecRestoreArrayRead(xx, &x));
10749566063dSJacob Faibussowitsch   PetscCall(VecRestoreArrayWrite(yy, &y));
10753ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1076289bc588SBarry Smith }
10776ee01492SSatish Balay 
10780be0d8bdSHansol Suh PetscErrorCode MatMultHermitianTransposeColumnRange_SeqDense(Mat A, Vec xx, Vec yy, PetscInt c_start, PetscInt c_end)
10790be0d8bdSHansol Suh {
10800be0d8bdSHansol Suh   PetscFunctionBegin;
10810be0d8bdSHansol Suh   PetscCall(MatMultColumnRangeKernel_SeqDense(A, xx, yy, c_start, c_end, PETSC_TRUE, PETSC_TRUE));
10820be0d8bdSHansol Suh   PetscFunctionReturn(PETSC_SUCCESS);
10830be0d8bdSHansol Suh }
10840be0d8bdSHansol Suh 
1085459e8d23SBlanca Mellado Pinto PetscErrorCode MatMult_SeqDense(Mat A, Vec xx, Vec yy)
1086459e8d23SBlanca Mellado Pinto {
1087459e8d23SBlanca Mellado Pinto   PetscFunctionBegin;
10880be0d8bdSHansol Suh   PetscCall(MatMultColumnRangeKernel_SeqDense(A, xx, yy, 0, A->cmap->n, PETSC_FALSE, PETSC_FALSE));
1089459e8d23SBlanca Mellado Pinto   PetscFunctionReturn(PETSC_SUCCESS);
1090459e8d23SBlanca Mellado Pinto }
1091459e8d23SBlanca Mellado Pinto 
1092459e8d23SBlanca Mellado Pinto PetscErrorCode MatMultTranspose_SeqDense(Mat A, Vec xx, Vec yy)
1093459e8d23SBlanca Mellado Pinto {
1094459e8d23SBlanca Mellado Pinto   PetscFunctionBegin;
10950be0d8bdSHansol Suh   PetscCall(MatMultColumnRangeKernel_SeqDense(A, xx, yy, 0, A->cmap->n, PETSC_TRUE, PETSC_FALSE));
1096459e8d23SBlanca Mellado Pinto   PetscFunctionReturn(PETSC_SUCCESS);
1097459e8d23SBlanca Mellado Pinto }
1098459e8d23SBlanca Mellado Pinto 
1099459e8d23SBlanca Mellado Pinto PetscErrorCode MatMultHermitianTranspose_SeqDense(Mat A, Vec xx, Vec yy)
1100459e8d23SBlanca Mellado Pinto {
1101459e8d23SBlanca Mellado Pinto   PetscFunctionBegin;
11020be0d8bdSHansol Suh   PetscCall(MatMultColumnRangeKernel_SeqDense(A, xx, yy, 0, A->cmap->n, PETSC_TRUE, PETSC_TRUE));
1103459e8d23SBlanca Mellado Pinto   PetscFunctionReturn(PETSC_SUCCESS);
1104459e8d23SBlanca Mellado Pinto }
1105459e8d23SBlanca Mellado Pinto 
1106d016bddeSToby Isaac PETSC_INTERN PetscErrorCode MatMultAddColumnRangeKernel_SeqDense(Mat A, Vec xx, Vec zz, Vec yy, PetscInt c_start, PetscInt c_end, PetscBool trans, PetscBool herm)
1107d71ae5a4SJacob Faibussowitsch {
1108c0bbcb79SLois Curfman McInnes   Mat_SeqDense      *mat = (Mat_SeqDense *)A->data;
1109d9ca1df4SBarry Smith   const PetscScalar *v   = mat->v, *x;
1110d9ca1df4SBarry Smith   PetscScalar       *y, _DOne = 1.0;
11110805154bSBarry Smith   PetscBLASInt       m, n, _One = 1;
11123a40ed3dSBarry Smith 
11133a40ed3dSBarry Smith   PetscFunctionBegin;
11149566063dSJacob Faibussowitsch   PetscCall(PetscBLASIntCast(A->rmap->n, &m));
11150be0d8bdSHansol Suh   PetscCall(PetscBLASIntCast(c_end - c_start, &n));
11169566063dSJacob Faibussowitsch   PetscCall(VecCopy(zz, yy));
11170be0d8bdSHansol Suh   if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS);
11189566063dSJacob Faibussowitsch   PetscCall(VecGetArray(yy, &y));
1119459e8d23SBlanca Mellado Pinto   PetscCall(VecGetArrayRead(xx, &x));
1120459e8d23SBlanca Mellado Pinto   if (trans) {
11210be0d8bdSHansol Suh     if (herm) PetscCallBLAS("BLASgemv", BLASgemv_("C", &m, &n, &_DOne, v + c_start * mat->lda, &mat->lda, x, &_One, &_DOne, y + c_start, &_One));
11220be0d8bdSHansol Suh     else PetscCallBLAS("BLASgemv", BLASgemv_("T", &m, &n, &_DOne, v + c_start * mat->lda, &mat->lda, x, &_One, &_DOne, y + c_start, &_One));
1123459e8d23SBlanca Mellado Pinto   } else {
11240be0d8bdSHansol Suh     PetscCallBLAS("BLASgemv", BLASgemv_("N", &m, &n, &_DOne, v + c_start * mat->lda, &mat->lda, x + c_start, &_One, &_DOne, y, &_One));
1125459e8d23SBlanca Mellado Pinto   }
11269566063dSJacob Faibussowitsch   PetscCall(VecRestoreArrayRead(xx, &x));
11279566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(yy, &y));
11280be0d8bdSHansol Suh   PetscCall(PetscLogFlops(2.0 * m * n));
11290be0d8bdSHansol Suh   PetscFunctionReturn(PETSC_SUCCESS);
11300be0d8bdSHansol Suh }
11310be0d8bdSHansol Suh 
1132d016bddeSToby Isaac PetscErrorCode MatMultColumnRange_SeqDense(Mat A, Vec xx, Vec yy, PetscInt c_start, PetscInt c_end)
1133d016bddeSToby Isaac {
1134d016bddeSToby Isaac   PetscFunctionBegin;
1135d016bddeSToby Isaac   PetscCall(MatMultColumnRangeKernel_SeqDense(A, xx, yy, c_start, c_end, PETSC_FALSE, PETSC_FALSE));
1136d016bddeSToby Isaac   PetscFunctionReturn(PETSC_SUCCESS);
1137d016bddeSToby Isaac }
1138d016bddeSToby Isaac 
11390be0d8bdSHansol Suh PetscErrorCode MatMultAddColumnRange_SeqDense(Mat A, Vec xx, Vec zz, Vec yy, PetscInt c_start, PetscInt c_end)
11400be0d8bdSHansol Suh {
11410be0d8bdSHansol Suh   PetscFunctionBegin;
11420be0d8bdSHansol Suh   PetscCall(MatMultAddColumnRangeKernel_SeqDense(A, xx, zz, yy, c_start, c_end, PETSC_FALSE, PETSC_FALSE));
11430be0d8bdSHansol Suh   PetscFunctionReturn(PETSC_SUCCESS);
11440be0d8bdSHansol Suh }
11450be0d8bdSHansol Suh 
11460be0d8bdSHansol Suh PetscErrorCode MatMultHermitianTransposeAddColumnRange_SeqDense(Mat A, Vec xx, Vec zz, Vec yy, PetscInt c_start, PetscInt c_end)
11470be0d8bdSHansol Suh {
11480be0d8bdSHansol Suh   PetscFunctionBegin;
11490be0d8bdSHansol Suh   PetscMPIInt rank;
11500be0d8bdSHansol Suh   PetscCallMPI(MPI_Comm_rank(MPI_COMM_WORLD, &rank));
11510be0d8bdSHansol Suh   PetscCall(MatMultAddColumnRangeKernel_SeqDense(A, xx, zz, yy, c_start, c_end, PETSC_TRUE, PETSC_TRUE));
11523ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1153289bc588SBarry Smith }
11546ee01492SSatish Balay 
1155459e8d23SBlanca Mellado Pinto PetscErrorCode MatMultAdd_SeqDense(Mat A, Vec xx, Vec zz, Vec yy)
1156459e8d23SBlanca Mellado Pinto {
1157459e8d23SBlanca Mellado Pinto   PetscFunctionBegin;
11580be0d8bdSHansol Suh   PetscCall(MatMultAddColumnRangeKernel_SeqDense(A, xx, zz, yy, 0, A->cmap->n, PETSC_FALSE, PETSC_FALSE));
1159459e8d23SBlanca Mellado Pinto   PetscFunctionReturn(PETSC_SUCCESS);
1160459e8d23SBlanca Mellado Pinto }
1161459e8d23SBlanca Mellado Pinto 
1162d71ae5a4SJacob Faibussowitsch PetscErrorCode MatMultTransposeAdd_SeqDense(Mat A, Vec xx, Vec zz, Vec yy)
1163d71ae5a4SJacob Faibussowitsch {
11643a40ed3dSBarry Smith   PetscFunctionBegin;
11650be0d8bdSHansol Suh   PetscCall(MatMultAddColumnRangeKernel_SeqDense(A, xx, zz, yy, 0, A->cmap->n, PETSC_TRUE, PETSC_FALSE));
1166459e8d23SBlanca Mellado Pinto   PetscFunctionReturn(PETSC_SUCCESS);
1167459e8d23SBlanca Mellado Pinto }
1168459e8d23SBlanca Mellado Pinto 
1169459e8d23SBlanca Mellado Pinto PetscErrorCode MatMultHermitianTransposeAdd_SeqDense(Mat A, Vec xx, Vec zz, Vec yy)
1170459e8d23SBlanca Mellado Pinto {
1171459e8d23SBlanca Mellado Pinto   PetscFunctionBegin;
11720be0d8bdSHansol Suh   PetscCall(MatMultAddColumnRangeKernel_SeqDense(A, xx, zz, yy, 0, A->cmap->n, PETSC_TRUE, PETSC_TRUE));
11733ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1174289bc588SBarry Smith }
1175289bc588SBarry Smith 
1176d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatGetRow_SeqDense(Mat A, PetscInt row, PetscInt *ncols, PetscInt **cols, PetscScalar **vals)
1177d71ae5a4SJacob Faibussowitsch {
1178c0bbcb79SLois Curfman McInnes   Mat_SeqDense *mat = (Mat_SeqDense *)A->data;
117913f74950SBarry Smith   PetscInt      i;
118067e560aaSBarry Smith 
11813a40ed3dSBarry Smith   PetscFunctionBegin;
1182c3e1b152SPierre Jolivet   if (ncols) *ncols = A->cmap->n;
1183289bc588SBarry Smith   if (cols) {
11849566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(A->cmap->n, cols));
1185d0f46423SBarry Smith     for (i = 0; i < A->cmap->n; i++) (*cols)[i] = i;
1186289bc588SBarry Smith   }
1187289bc588SBarry Smith   if (vals) {
1188ca15aa20SStefano Zampini     const PetscScalar *v;
1189ca15aa20SStefano Zampini 
11909566063dSJacob Faibussowitsch     PetscCall(MatDenseGetArrayRead(A, &v));
11919566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(A->cmap->n, vals));
1192ca15aa20SStefano Zampini     v += row;
11939371c9d4SSatish Balay     for (i = 0; i < A->cmap->n; i++) {
11949371c9d4SSatish Balay       (*vals)[i] = *v;
11959371c9d4SSatish Balay       v += mat->lda;
11969371c9d4SSatish Balay     }
11979566063dSJacob Faibussowitsch     PetscCall(MatDenseRestoreArrayRead(A, &v));
1198289bc588SBarry Smith   }
11993ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1200289bc588SBarry Smith }
12016ee01492SSatish Balay 
1202d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatRestoreRow_SeqDense(Mat A, PetscInt row, PetscInt *ncols, PetscInt **cols, PetscScalar **vals)
1203d71ae5a4SJacob Faibussowitsch {
1204606d414cSSatish Balay   PetscFunctionBegin;
12059566063dSJacob Faibussowitsch   if (cols) PetscCall(PetscFree(*cols));
12069566063dSJacob Faibussowitsch   if (vals) PetscCall(PetscFree(*vals));
12073ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1208289bc588SBarry Smith }
12092ef1f0ffSBarry Smith 
1210d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatSetValues_SeqDense(Mat A, PetscInt m, const PetscInt indexm[], PetscInt n, const PetscInt indexn[], const PetscScalar v[], InsertMode addv)
1211d71ae5a4SJacob Faibussowitsch {
1212c0bbcb79SLois Curfman McInnes   Mat_SeqDense *mat = (Mat_SeqDense *)A->data;
1213ca15aa20SStefano Zampini   PetscScalar  *av;
121413f74950SBarry Smith   PetscInt      i, j, idx = 0;
121547d993e7Ssuyashtn #if defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
1216c70f7ee4SJunchao Zhang   PetscOffloadMask oldf;
1217ca15aa20SStefano Zampini #endif
1218d6dfbf8fSBarry Smith 
12193a40ed3dSBarry Smith   PetscFunctionBegin;
12209566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArray(A, &av));
1221289bc588SBarry Smith   if (!mat->roworiented) {
1222dbb450caSBarry Smith     if (addv == INSERT_VALUES) {
1223289bc588SBarry Smith       for (j = 0; j < n; j++) {
12249371c9d4SSatish Balay         if (indexn[j] < 0) {
12259371c9d4SSatish Balay           idx += m;
12269371c9d4SSatish Balay           continue;
12279371c9d4SSatish Balay         }
12286bdcaf15SBarry 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);
1229289bc588SBarry Smith         for (i = 0; i < m; i++) {
12309371c9d4SSatish Balay           if (indexm[i] < 0) {
12319371c9d4SSatish Balay             idx++;
12329371c9d4SSatish Balay             continue;
12339371c9d4SSatish Balay           }
12346bdcaf15SBarry 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);
12358c4a67a0SStefano Zampini           av[indexn[j] * mat->lda + indexm[i]] = v ? v[idx++] : (idx++, 0.0);
1236289bc588SBarry Smith         }
1237289bc588SBarry Smith       }
12380be0d8bdSHansol Suh     } else {
1239289bc588SBarry Smith       for (j = 0; j < n; j++) {
12409371c9d4SSatish Balay         if (indexn[j] < 0) {
12419371c9d4SSatish Balay           idx += m;
12429371c9d4SSatish Balay           continue;
12439371c9d4SSatish Balay         }
12446bdcaf15SBarry 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);
1245289bc588SBarry Smith         for (i = 0; i < m; i++) {
12469371c9d4SSatish Balay           if (indexm[i] < 0) {
12479371c9d4SSatish Balay             idx++;
12489371c9d4SSatish Balay             continue;
12499371c9d4SSatish Balay           }
12506bdcaf15SBarry 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);
12518c4a67a0SStefano Zampini           av[indexn[j] * mat->lda + indexm[i]] += v ? v[idx++] : (idx++, 0.0);
1252289bc588SBarry Smith         }
1253289bc588SBarry Smith       }
1254289bc588SBarry Smith     }
12553a40ed3dSBarry Smith   } else {
1256dbb450caSBarry Smith     if (addv == INSERT_VALUES) {
1257e8d4e0b9SBarry Smith       for (i = 0; i < m; i++) {
12589371c9d4SSatish Balay         if (indexm[i] < 0) {
12599371c9d4SSatish Balay           idx += n;
12609371c9d4SSatish Balay           continue;
12619371c9d4SSatish Balay         }
12626bdcaf15SBarry 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);
1263e8d4e0b9SBarry Smith         for (j = 0; j < n; j++) {
12649371c9d4SSatish Balay           if (indexn[j] < 0) {
12659371c9d4SSatish Balay             idx++;
12669371c9d4SSatish Balay             continue;
12679371c9d4SSatish Balay           }
12686bdcaf15SBarry 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);
12698c4a67a0SStefano Zampini           av[indexn[j] * mat->lda + indexm[i]] = v ? v[idx++] : (idx++, 0.0);
1270e8d4e0b9SBarry Smith         }
1271e8d4e0b9SBarry Smith       }
12720be0d8bdSHansol Suh     } else {
1273289bc588SBarry Smith       for (i = 0; i < m; i++) {
12749371c9d4SSatish Balay         if (indexm[i] < 0) {
12759371c9d4SSatish Balay           idx += n;
12769371c9d4SSatish Balay           continue;
12779371c9d4SSatish Balay         }
12786bdcaf15SBarry 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);
1279289bc588SBarry Smith         for (j = 0; j < n; j++) {
12809371c9d4SSatish Balay           if (indexn[j] < 0) {
12819371c9d4SSatish Balay             idx++;
12829371c9d4SSatish Balay             continue;
12839371c9d4SSatish Balay           }
12846bdcaf15SBarry 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);
12858c4a67a0SStefano Zampini           av[indexn[j] * mat->lda + indexm[i]] += v ? v[idx++] : (idx++, 0.0);
1286289bc588SBarry Smith         }
1287289bc588SBarry Smith       }
1288289bc588SBarry Smith     }
1289e8d4e0b9SBarry Smith   }
1290ca15aa20SStefano Zampini   /* hack to prevent unneeded copy to the GPU while returning the array */
129147d993e7Ssuyashtn #if defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
1292c70f7ee4SJunchao Zhang   oldf           = A->offloadmask;
1293c70f7ee4SJunchao Zhang   A->offloadmask = PETSC_OFFLOAD_GPU;
1294ca15aa20SStefano Zampini #endif
12959566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArray(A, &av));
129647d993e7Ssuyashtn #if defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
1297c70f7ee4SJunchao Zhang   A->offloadmask = (oldf == PETSC_OFFLOAD_UNALLOCATED ? PETSC_OFFLOAD_UNALLOCATED : PETSC_OFFLOAD_CPU);
1298ca15aa20SStefano Zampini #endif
12993ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1300289bc588SBarry Smith }
1301e8d4e0b9SBarry Smith 
1302d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatGetValues_SeqDense(Mat A, PetscInt m, const PetscInt indexm[], PetscInt n, const PetscInt indexn[], PetscScalar v[])
1303d71ae5a4SJacob Faibussowitsch {
1304ae80bb75SLois Curfman McInnes   Mat_SeqDense      *mat = (Mat_SeqDense *)A->data;
1305ca15aa20SStefano Zampini   const PetscScalar *vv;
130613f74950SBarry Smith   PetscInt           i, j;
1307ae80bb75SLois Curfman McInnes 
13083a40ed3dSBarry Smith   PetscFunctionBegin;
13099566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArrayRead(A, &vv));
1310ae80bb75SLois Curfman McInnes   /* row-oriented output */
1311ae80bb75SLois Curfman McInnes   for (i = 0; i < m; i++) {
13129371c9d4SSatish Balay     if (indexm[i] < 0) {
13139371c9d4SSatish Balay       v += n;
13149371c9d4SSatish Balay       continue;
13159371c9d4SSatish Balay     }
131608401ef6SPierre 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);
1317ae80bb75SLois Curfman McInnes     for (j = 0; j < n; j++) {
13189371c9d4SSatish Balay       if (indexn[j] < 0) {
13199371c9d4SSatish Balay         v++;
13209371c9d4SSatish Balay         continue;
13219371c9d4SSatish Balay       }
132208401ef6SPierre 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);
1323ca15aa20SStefano Zampini       *v++ = vv[indexn[j] * mat->lda + indexm[i]];
1324ae80bb75SLois Curfman McInnes     }
1325ae80bb75SLois Curfman McInnes   }
13269566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArrayRead(A, &vv));
13273ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1328ae80bb75SLois Curfman McInnes }
1329ae80bb75SLois Curfman McInnes 
1330d71ae5a4SJacob Faibussowitsch PetscErrorCode MatView_Dense_Binary(Mat mat, PetscViewer viewer)
1331d71ae5a4SJacob Faibussowitsch {
13328491ab44SLisandro Dalcin   PetscBool          skipHeader;
13338491ab44SLisandro Dalcin   PetscViewerFormat  format;
13343e1d7bceSPierre Jolivet   PetscInt           header[4], M, N, m, lda, i, j;
13353e1d7bceSPierre Jolivet   PetscCount         k;
13368491ab44SLisandro Dalcin   const PetscScalar *v;
13378491ab44SLisandro Dalcin   PetscScalar       *vwork;
1338aabbc4fbSShri Abhyankar 
1339aabbc4fbSShri Abhyankar   PetscFunctionBegin;
13409566063dSJacob Faibussowitsch   PetscCall(PetscViewerSetUp(viewer));
13419566063dSJacob Faibussowitsch   PetscCall(PetscViewerBinaryGetSkipHeader(viewer, &skipHeader));
13429566063dSJacob Faibussowitsch   PetscCall(PetscViewerGetFormat(viewer, &format));
13438491ab44SLisandro Dalcin   if (skipHeader) format = PETSC_VIEWER_NATIVE;
1344aabbc4fbSShri Abhyankar 
13459566063dSJacob Faibussowitsch   PetscCall(MatGetSize(mat, &M, &N));
13468491ab44SLisandro Dalcin 
13478491ab44SLisandro Dalcin   /* write matrix header */
13489371c9d4SSatish Balay   header[0] = MAT_FILE_CLASSID;
13499371c9d4SSatish Balay   header[1] = M;
13509371c9d4SSatish Balay   header[2] = N;
13518491ab44SLisandro Dalcin   header[3] = (format == PETSC_VIEWER_NATIVE) ? MATRIX_BINARY_FORMAT_DENSE : M * N;
13529566063dSJacob Faibussowitsch   if (!skipHeader) PetscCall(PetscViewerBinaryWrite(viewer, header, 4, PETSC_INT));
13538491ab44SLisandro Dalcin 
13549566063dSJacob Faibussowitsch   PetscCall(MatGetLocalSize(mat, &m, NULL));
13558491ab44SLisandro Dalcin   if (format != PETSC_VIEWER_NATIVE) {
13568491ab44SLisandro Dalcin     PetscInt nnz = m * N, *iwork;
13578491ab44SLisandro Dalcin     /* store row lengths for each row */
13589566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(nnz, &iwork));
13598491ab44SLisandro Dalcin     for (i = 0; i < m; i++) iwork[i] = N;
13609566063dSJacob Faibussowitsch     PetscCall(PetscViewerBinaryWriteAll(viewer, iwork, m, PETSC_DETERMINE, PETSC_DETERMINE, PETSC_INT));
13618491ab44SLisandro Dalcin     /* store column indices (zero start index) */
13628491ab44SLisandro Dalcin     for (k = 0, i = 0; i < m; i++)
13639371c9d4SSatish Balay       for (j = 0; j < N; j++, k++) iwork[k] = j;
13649566063dSJacob Faibussowitsch     PetscCall(PetscViewerBinaryWriteAll(viewer, iwork, nnz, PETSC_DETERMINE, PETSC_DETERMINE, PETSC_INT));
13659566063dSJacob Faibussowitsch     PetscCall(PetscFree(iwork));
13668491ab44SLisandro Dalcin   }
13678491ab44SLisandro Dalcin   /* store matrix values as a dense matrix in row major order */
13689566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(m * N, &vwork));
13699566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArrayRead(mat, &v));
13709566063dSJacob Faibussowitsch   PetscCall(MatDenseGetLDA(mat, &lda));
13718491ab44SLisandro Dalcin   for (k = 0, i = 0; i < m; i++)
13723e1d7bceSPierre Jolivet     for (j = 0; j < N; j++, k++) vwork[k] = v[i + (size_t)lda * j];
13739566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArrayRead(mat, &v));
13749566063dSJacob Faibussowitsch   PetscCall(PetscViewerBinaryWriteAll(viewer, vwork, m * N, PETSC_DETERMINE, PETSC_DETERMINE, PETSC_SCALAR));
13759566063dSJacob Faibussowitsch   PetscCall(PetscFree(vwork));
13763ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
13778491ab44SLisandro Dalcin }
13788491ab44SLisandro Dalcin 
1379d71ae5a4SJacob Faibussowitsch PetscErrorCode MatLoad_Dense_Binary(Mat mat, PetscViewer viewer)
1380d71ae5a4SJacob Faibussowitsch {
13818491ab44SLisandro Dalcin   PetscBool    skipHeader;
13828491ab44SLisandro Dalcin   PetscInt     header[4], M, N, m, nz, lda, i, j, k;
13838491ab44SLisandro Dalcin   PetscInt     rows, cols;
13848491ab44SLisandro Dalcin   PetscScalar *v, *vwork;
13858491ab44SLisandro Dalcin 
13868491ab44SLisandro Dalcin   PetscFunctionBegin;
13879566063dSJacob Faibussowitsch   PetscCall(PetscViewerSetUp(viewer));
13889566063dSJacob Faibussowitsch   PetscCall(PetscViewerBinaryGetSkipHeader(viewer, &skipHeader));
13898491ab44SLisandro Dalcin 
13908491ab44SLisandro Dalcin   if (!skipHeader) {
13919566063dSJacob Faibussowitsch     PetscCall(PetscViewerBinaryRead(viewer, header, 4, NULL, PETSC_INT));
139208401ef6SPierre Jolivet     PetscCheck(header[0] == MAT_FILE_CLASSID, PetscObjectComm((PetscObject)viewer), PETSC_ERR_FILE_UNEXPECTED, "Not a matrix object in file");
13939371c9d4SSatish Balay     M = header[1];
13949371c9d4SSatish Balay     N = header[2];
139508401ef6SPierre Jolivet     PetscCheck(M >= 0, PetscObjectComm((PetscObject)viewer), PETSC_ERR_FILE_UNEXPECTED, "Matrix row size (%" PetscInt_FMT ") in file is negative", M);
139608401ef6SPierre Jolivet     PetscCheck(N >= 0, PetscObjectComm((PetscObject)viewer), PETSC_ERR_FILE_UNEXPECTED, "Matrix column size (%" PetscInt_FMT ") in file is negative", N);
13978491ab44SLisandro Dalcin     nz = header[3];
1398aed4548fSBarry Smith     PetscCheck(nz == MATRIX_BINARY_FORMAT_DENSE || nz >= 0, PetscObjectComm((PetscObject)viewer), PETSC_ERR_FILE_UNEXPECTED, "Unknown matrix format %" PetscInt_FMT " in file", nz);
1399aabbc4fbSShri Abhyankar   } else {
14009566063dSJacob Faibussowitsch     PetscCall(MatGetSize(mat, &M, &N));
1401aed4548fSBarry 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");
14028491ab44SLisandro Dalcin     nz = MATRIX_BINARY_FORMAT_DENSE;
1403e6324fbbSBarry Smith   }
1404aabbc4fbSShri Abhyankar 
14058491ab44SLisandro Dalcin   /* setup global sizes if not set */
14068491ab44SLisandro Dalcin   if (mat->rmap->N < 0) mat->rmap->N = M;
14078491ab44SLisandro Dalcin   if (mat->cmap->N < 0) mat->cmap->N = N;
14089566063dSJacob Faibussowitsch   PetscCall(MatSetUp(mat));
14098491ab44SLisandro Dalcin   /* check if global sizes are correct */
14109566063dSJacob Faibussowitsch   PetscCall(MatGetSize(mat, &rows, &cols));
1411aed4548fSBarry 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);
1412aabbc4fbSShri Abhyankar 
14139566063dSJacob Faibussowitsch   PetscCall(MatGetSize(mat, NULL, &N));
14149566063dSJacob Faibussowitsch   PetscCall(MatGetLocalSize(mat, &m, NULL));
14159566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArray(mat, &v));
14169566063dSJacob Faibussowitsch   PetscCall(MatDenseGetLDA(mat, &lda));
14178491ab44SLisandro Dalcin   if (nz == MATRIX_BINARY_FORMAT_DENSE) { /* matrix in file is dense format */
14183e1d7bceSPierre Jolivet     PetscCount nnz = (size_t)m * N;
14198491ab44SLisandro Dalcin     /* read in matrix values */
14209566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(nnz, &vwork));
14219566063dSJacob Faibussowitsch     PetscCall(PetscViewerBinaryReadAll(viewer, vwork, nnz, PETSC_DETERMINE, PETSC_DETERMINE, PETSC_SCALAR));
14228491ab44SLisandro Dalcin     /* store values in column major order */
14238491ab44SLisandro Dalcin     for (j = 0; j < N; j++)
14243e1d7bceSPierre Jolivet       for (i = 0; i < m; i++) v[i + (size_t)lda * j] = vwork[(size_t)i * N + j];
14259566063dSJacob Faibussowitsch     PetscCall(PetscFree(vwork));
14268491ab44SLisandro Dalcin   } else { /* matrix in file is sparse format */
14278491ab44SLisandro Dalcin     PetscInt nnz = 0, *rlens, *icols;
14288491ab44SLisandro Dalcin     /* read in row lengths */
14299566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(m, &rlens));
14309566063dSJacob Faibussowitsch     PetscCall(PetscViewerBinaryReadAll(viewer, rlens, m, PETSC_DETERMINE, PETSC_DETERMINE, PETSC_INT));
14318491ab44SLisandro Dalcin     for (i = 0; i < m; i++) nnz += rlens[i];
14328491ab44SLisandro Dalcin     /* read in column indices and values */
14339566063dSJacob Faibussowitsch     PetscCall(PetscMalloc2(nnz, &icols, nnz, &vwork));
14349566063dSJacob Faibussowitsch     PetscCall(PetscViewerBinaryReadAll(viewer, icols, nnz, PETSC_DETERMINE, PETSC_DETERMINE, PETSC_INT));
14359566063dSJacob Faibussowitsch     PetscCall(PetscViewerBinaryReadAll(viewer, vwork, nnz, PETSC_DETERMINE, PETSC_DETERMINE, PETSC_SCALAR));
14368491ab44SLisandro Dalcin     /* store values in column major order */
14378491ab44SLisandro Dalcin     for (k = 0, i = 0; i < m; i++)
14389371c9d4SSatish Balay       for (j = 0; j < rlens[i]; j++, k++) v[i + lda * icols[k]] = vwork[k];
14399566063dSJacob Faibussowitsch     PetscCall(PetscFree(rlens));
14409566063dSJacob Faibussowitsch     PetscCall(PetscFree2(icols, vwork));
1441aabbc4fbSShri Abhyankar   }
14429566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArray(mat, &v));
14439566063dSJacob Faibussowitsch   PetscCall(MatAssemblyBegin(mat, MAT_FINAL_ASSEMBLY));
14449566063dSJacob Faibussowitsch   PetscCall(MatAssemblyEnd(mat, MAT_FINAL_ASSEMBLY));
14453ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1446aabbc4fbSShri Abhyankar }
1447aabbc4fbSShri Abhyankar 
144866976f2fSJacob Faibussowitsch static PetscErrorCode MatLoad_SeqDense(Mat newMat, PetscViewer viewer)
1449d71ae5a4SJacob Faibussowitsch {
1450eb91f321SVaclav Hapla   PetscBool isbinary, ishdf5;
1451eb91f321SVaclav Hapla 
1452eb91f321SVaclav Hapla   PetscFunctionBegin;
1453eb91f321SVaclav Hapla   PetscValidHeaderSpecific(newMat, MAT_CLASSID, 1);
1454eb91f321SVaclav Hapla   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
1455eb91f321SVaclav Hapla   /* force binary viewer to load .info file if it has not yet done so */
14569566063dSJacob Faibussowitsch   PetscCall(PetscViewerSetUp(viewer));
14579566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERBINARY, &isbinary));
14589566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5));
1459eb91f321SVaclav Hapla   if (isbinary) {
14609566063dSJacob Faibussowitsch     PetscCall(MatLoad_Dense_Binary(newMat, viewer));
1461eb91f321SVaclav Hapla   } else if (ishdf5) {
1462eb91f321SVaclav Hapla #if defined(PETSC_HAVE_HDF5)
14639566063dSJacob Faibussowitsch     PetscCall(MatLoad_Dense_HDF5(newMat, viewer));
1464eb91f321SVaclav Hapla #else
1465eb91f321SVaclav Hapla     SETERRQ(PetscObjectComm((PetscObject)newMat), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5");
1466eb91f321SVaclav Hapla #endif
1467eb91f321SVaclav Hapla   } else {
146898921bdaSJacob 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);
1469eb91f321SVaclav Hapla   }
14703ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1471eb91f321SVaclav Hapla }
1472eb91f321SVaclav Hapla 
1473d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatView_SeqDense_ASCII(Mat A, PetscViewer viewer)
1474d71ae5a4SJacob Faibussowitsch {
1475932b0c3eSLois Curfman McInnes   Mat_SeqDense     *a = (Mat_SeqDense *)A->data;
147613f74950SBarry Smith   PetscInt          i, j;
14772dcb1b2aSMatthew Knepley   const char       *name;
1478ca15aa20SStefano Zampini   PetscScalar      *v, *av;
1479f3ef73ceSBarry Smith   PetscViewerFormat format;
14805f481a85SSatish Balay #if defined(PETSC_USE_COMPLEX)
1481ace3abfcSBarry Smith   PetscBool allreal = PETSC_TRUE;
14825f481a85SSatish Balay #endif
1483932b0c3eSLois Curfman McInnes 
14843a40ed3dSBarry Smith   PetscFunctionBegin;
14859566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArrayRead(A, (const PetscScalar **)&av));
14869566063dSJacob Faibussowitsch   PetscCall(PetscViewerGetFormat(viewer, &format));
1487456192e2SBarry Smith   if (format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL) {
14883ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS); /* do nothing for now */
1489fb9695e5SSatish Balay   } else if (format == PETSC_VIEWER_ASCII_COMMON) {
14909566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIUseTabs(viewer, PETSC_FALSE));
1491d0f46423SBarry Smith     for (i = 0; i < A->rmap->n; i++) {
1492ca15aa20SStefano Zampini       v = av + i;
14939566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "row %" PetscInt_FMT ":", i));
1494d0f46423SBarry Smith       for (j = 0; j < A->cmap->n; j++) {
1495aa482453SBarry Smith #if defined(PETSC_USE_COMPLEX)
1496329f5518SBarry Smith         if (PetscRealPart(*v) != 0.0 && PetscImaginaryPart(*v) != 0.0) {
14979566063dSJacob Faibussowitsch           PetscCall(PetscViewerASCIIPrintf(viewer, " (%" PetscInt_FMT ", %g + %g i) ", j, (double)PetscRealPart(*v), (double)PetscImaginaryPart(*v)));
1498329f5518SBarry Smith         } else if (PetscRealPart(*v)) {
14999566063dSJacob Faibussowitsch           PetscCall(PetscViewerASCIIPrintf(viewer, " (%" PetscInt_FMT ", %g) ", j, (double)PetscRealPart(*v)));
15006831982aSBarry Smith         }
150180cd9d93SLois Curfman McInnes #else
150248a46eb9SPierre Jolivet         if (*v) PetscCall(PetscViewerASCIIPrintf(viewer, " (%" PetscInt_FMT ", %g) ", j, (double)*v));
150380cd9d93SLois Curfman McInnes #endif
15041b807ce4Svictorle         v += a->lda;
150580cd9d93SLois Curfman McInnes       }
15069566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "\n"));
150780cd9d93SLois Curfman McInnes     }
15089566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIUseTabs(viewer, PETSC_TRUE));
15093a40ed3dSBarry Smith   } else {
15109566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIUseTabs(viewer, PETSC_FALSE));
1511aa482453SBarry Smith #if defined(PETSC_USE_COMPLEX)
151247989497SBarry Smith     /* determine if matrix has all real values */
1513bcd8d3a4SJose E. Roman     for (j = 0; j < A->cmap->n; j++) {
1514bcd8d3a4SJose E. Roman       v = av + j * a->lda;
1515bcd8d3a4SJose E. Roman       for (i = 0; i < A->rmap->n; i++) {
15169371c9d4SSatish Balay         if (PetscImaginaryPart(v[i])) {
15179371c9d4SSatish Balay           allreal = PETSC_FALSE;
15189371c9d4SSatish Balay           break;
15199371c9d4SSatish Balay         }
152047989497SBarry Smith       }
1521bcd8d3a4SJose E. Roman     }
152247989497SBarry Smith #endif
1523fb9695e5SSatish Balay     if (format == PETSC_VIEWER_ASCII_MATLAB) {
15249566063dSJacob Faibussowitsch       PetscCall(PetscObjectGetName((PetscObject)A, &name));
15259566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "%% Size = %" PetscInt_FMT " %" PetscInt_FMT " \n", A->rmap->n, A->cmap->n));
15269566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "%s = zeros(%" PetscInt_FMT ",%" PetscInt_FMT ");\n", name, A->rmap->n, A->cmap->n));
15279566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "%s = [\n", name));
1528ffac6cdbSBarry Smith     }
1529ffac6cdbSBarry Smith 
1530d0f46423SBarry Smith     for (i = 0; i < A->rmap->n; i++) {
1531ca15aa20SStefano Zampini       v = av + i;
1532d0f46423SBarry Smith       for (j = 0; j < A->cmap->n; j++) {
1533aa482453SBarry Smith #if defined(PETSC_USE_COMPLEX)
153447989497SBarry Smith         if (allreal) {
15359566063dSJacob Faibussowitsch           PetscCall(PetscViewerASCIIPrintf(viewer, "%18.16e ", (double)PetscRealPart(*v)));
153647989497SBarry Smith         } else {
15379566063dSJacob Faibussowitsch           PetscCall(PetscViewerASCIIPrintf(viewer, "%18.16e + %18.16ei ", (double)PetscRealPart(*v), (double)PetscImaginaryPart(*v)));
153847989497SBarry Smith         }
1539289bc588SBarry Smith #else
15409566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, "%18.16e ", (double)*v));
1541289bc588SBarry Smith #endif
15421b807ce4Svictorle         v += a->lda;
1543289bc588SBarry Smith       }
15449566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "\n"));
1545289bc588SBarry Smith     }
154648a46eb9SPierre Jolivet     if (format == PETSC_VIEWER_ASCII_MATLAB) PetscCall(PetscViewerASCIIPrintf(viewer, "];\n"));
15479566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIUseTabs(viewer, PETSC_TRUE));
1548da3a660dSBarry Smith   }
15499566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArrayRead(A, (const PetscScalar **)&av));
15509566063dSJacob Faibussowitsch   PetscCall(PetscViewerFlush(viewer));
15513ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1552289bc588SBarry Smith }
1553289bc588SBarry Smith 
15549804daf3SBarry Smith #include <petscdraw.h>
1555d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatView_SeqDense_Draw_Zoom(PetscDraw draw, void *Aa)
1556d71ae5a4SJacob Faibussowitsch {
1557f1af5d2fSBarry Smith   Mat                A = (Mat)Aa;
1558383922c3SLisandro Dalcin   PetscInt           m = A->rmap->n, n = A->cmap->n, i, j;
1559383922c3SLisandro Dalcin   int                color = PETSC_DRAW_WHITE;
1560ca15aa20SStefano Zampini   const PetscScalar *v;
1561b0a32e0cSBarry Smith   PetscViewer        viewer;
1562b05fc000SLisandro Dalcin   PetscReal          xl, yl, xr, yr, x_l, x_r, y_l, y_r;
1563f3ef73ceSBarry Smith   PetscViewerFormat  format;
1564f1af5d2fSBarry Smith 
1565f1af5d2fSBarry Smith   PetscFunctionBegin;
15669566063dSJacob Faibussowitsch   PetscCall(PetscObjectQuery((PetscObject)A, "Zoomviewer", (PetscObject *)&viewer));
15679566063dSJacob Faibussowitsch   PetscCall(PetscViewerGetFormat(viewer, &format));
15689566063dSJacob Faibussowitsch   PetscCall(PetscDrawGetCoordinates(draw, &xl, &yl, &xr, &yr));
1569f1af5d2fSBarry Smith 
1570f1af5d2fSBarry Smith   /* Loop over matrix elements drawing boxes */
15719566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArrayRead(A, &v));
1572fb9695e5SSatish Balay   if (format != PETSC_VIEWER_DRAW_CONTOUR) {
1573d0609cedSBarry Smith     PetscDrawCollectiveBegin(draw);
1574f1af5d2fSBarry Smith     /* Blue for negative and Red for positive */
1575f1af5d2fSBarry Smith     for (j = 0; j < n; j++) {
15769371c9d4SSatish Balay       x_l = j;
15779371c9d4SSatish Balay       x_r = x_l + 1.0;
1578f1af5d2fSBarry Smith       for (i = 0; i < m; i++) {
1579f1af5d2fSBarry Smith         y_l = m - i - 1.0;
1580f1af5d2fSBarry Smith         y_r = y_l + 1.0;
1581ca15aa20SStefano Zampini         if (PetscRealPart(v[j * m + i]) > 0.) color = PETSC_DRAW_RED;
1582ca15aa20SStefano Zampini         else if (PetscRealPart(v[j * m + i]) < 0.) color = PETSC_DRAW_BLUE;
1583ca15aa20SStefano Zampini         else continue;
15849566063dSJacob Faibussowitsch         PetscCall(PetscDrawRectangle(draw, x_l, y_l, x_r, y_r, color, color, color, color));
1585f1af5d2fSBarry Smith       }
1586f1af5d2fSBarry Smith     }
1587d0609cedSBarry Smith     PetscDrawCollectiveEnd(draw);
1588f1af5d2fSBarry Smith   } else {
1589f1af5d2fSBarry Smith     /* use contour shading to indicate magnitude of values */
1590f1af5d2fSBarry Smith     /* first determine max of all nonzero values */
1591b05fc000SLisandro Dalcin     PetscReal minv = 0.0, maxv = 0.0;
1592b05fc000SLisandro Dalcin     PetscDraw popup;
1593b05fc000SLisandro Dalcin 
1594f1af5d2fSBarry Smith     for (i = 0; i < m * n; i++) {
1595f1af5d2fSBarry Smith       if (PetscAbsScalar(v[i]) > maxv) maxv = PetscAbsScalar(v[i]);
1596f1af5d2fSBarry Smith     }
1597383922c3SLisandro Dalcin     if (minv >= maxv) maxv = minv + PETSC_SMALL;
15989566063dSJacob Faibussowitsch     PetscCall(PetscDrawGetPopup(draw, &popup));
15999566063dSJacob Faibussowitsch     PetscCall(PetscDrawScalePopup(popup, minv, maxv));
1600383922c3SLisandro Dalcin 
1601d0609cedSBarry Smith     PetscDrawCollectiveBegin(draw);
1602f1af5d2fSBarry Smith     for (j = 0; j < n; j++) {
1603f1af5d2fSBarry Smith       x_l = j;
1604f1af5d2fSBarry Smith       x_r = x_l + 1.0;
1605f1af5d2fSBarry Smith       for (i = 0; i < m; i++) {
1606f1af5d2fSBarry Smith         y_l   = m - i - 1.0;
1607f1af5d2fSBarry Smith         y_r   = y_l + 1.0;
1608b05fc000SLisandro Dalcin         color = PetscDrawRealToColor(PetscAbsScalar(v[j * m + i]), minv, maxv);
16099566063dSJacob Faibussowitsch         PetscCall(PetscDrawRectangle(draw, x_l, y_l, x_r, y_r, color, color, color, color));
1610f1af5d2fSBarry Smith       }
1611f1af5d2fSBarry Smith     }
1612d0609cedSBarry Smith     PetscDrawCollectiveEnd(draw);
1613f1af5d2fSBarry Smith   }
16149566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArrayRead(A, &v));
16153ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1616f1af5d2fSBarry Smith }
1617f1af5d2fSBarry Smith 
1618d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatView_SeqDense_Draw(Mat A, PetscViewer viewer)
1619d71ae5a4SJacob Faibussowitsch {
1620b0a32e0cSBarry Smith   PetscDraw draw;
1621ace3abfcSBarry Smith   PetscBool isnull;
1622329f5518SBarry Smith   PetscReal xr, yr, xl, yl, h, w;
1623f1af5d2fSBarry Smith 
1624f1af5d2fSBarry Smith   PetscFunctionBegin;
16259566063dSJacob Faibussowitsch   PetscCall(PetscViewerDrawGetDraw(viewer, 0, &draw));
16269566063dSJacob Faibussowitsch   PetscCall(PetscDrawIsNull(draw, &isnull));
16273ba16761SJacob Faibussowitsch   if (isnull) PetscFunctionReturn(PETSC_SUCCESS);
1628f1af5d2fSBarry Smith 
16299371c9d4SSatish Balay   xr = A->cmap->n;
16309371c9d4SSatish Balay   yr = A->rmap->n;
16319371c9d4SSatish Balay   h  = yr / 10.0;
16329371c9d4SSatish Balay   w  = xr / 10.0;
16339371c9d4SSatish Balay   xr += w;
16349371c9d4SSatish Balay   yr += h;
16359371c9d4SSatish Balay   xl = -w;
16369371c9d4SSatish Balay   yl = -h;
16379566063dSJacob Faibussowitsch   PetscCall(PetscDrawSetCoordinates(draw, xl, yl, xr, yr));
16389566063dSJacob Faibussowitsch   PetscCall(PetscObjectCompose((PetscObject)A, "Zoomviewer", (PetscObject)viewer));
16399566063dSJacob Faibussowitsch   PetscCall(PetscDrawZoom(draw, MatView_SeqDense_Draw_Zoom, A));
16409566063dSJacob Faibussowitsch   PetscCall(PetscObjectCompose((PetscObject)A, "Zoomviewer", NULL));
16419566063dSJacob Faibussowitsch   PetscCall(PetscDrawSave(draw));
16423ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1643f1af5d2fSBarry Smith }
1644f1af5d2fSBarry Smith 
1645d71ae5a4SJacob Faibussowitsch PetscErrorCode MatView_SeqDense(Mat A, PetscViewer viewer)
1646d71ae5a4SJacob Faibussowitsch {
1647*9f196a02SMartin Diehl   PetscBool isascii, isbinary, isdraw;
1648932b0c3eSLois Curfman McInnes 
16493a40ed3dSBarry Smith   PetscFunctionBegin;
1650*9f196a02SMartin Diehl   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii));
16519566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERBINARY, &isbinary));
16529566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERDRAW, &isdraw));
1653*9f196a02SMartin Diehl   if (isascii) PetscCall(MatView_SeqDense_ASCII(A, viewer));
16541baa6e33SBarry Smith   else if (isbinary) PetscCall(MatView_Dense_Binary(A, viewer));
16551baa6e33SBarry Smith   else if (isdraw) PetscCall(MatView_SeqDense_Draw(A, viewer));
16563ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1657932b0c3eSLois Curfman McInnes }
1658289bc588SBarry Smith 
1659d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatDensePlaceArray_SeqDense(Mat A, const PetscScalar *array)
1660d71ae5a4SJacob Faibussowitsch {
1661d3042a70SBarry Smith   Mat_SeqDense *a = (Mat_SeqDense *)A->data;
1662d3042a70SBarry Smith 
1663d3042a70SBarry Smith   PetscFunctionBegin;
166428b400f6SJacob Faibussowitsch   PetscCheck(!a->vecinuse, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Need to call MatDenseRestoreColumnVec() first");
166528b400f6SJacob Faibussowitsch   PetscCheck(!a->matinuse, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Need to call MatDenseRestoreSubMatrix() first");
16666635c364SPierre Jolivet   PetscCheck(!a->unplacedarray, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Need to call MatDenseResetArray() first");
1667d3042a70SBarry Smith   a->unplacedarray       = a->v;
1668d3042a70SBarry Smith   a->unplaced_user_alloc = a->user_alloc;
1669d3042a70SBarry Smith   a->v                   = (PetscScalar *)array;
1670637a0070SStefano Zampini   a->user_alloc          = PETSC_TRUE;
167147d993e7Ssuyashtn #if defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
1672c70f7ee4SJunchao Zhang   A->offloadmask = PETSC_OFFLOAD_CPU;
1673ca15aa20SStefano Zampini #endif
16743ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1675d3042a70SBarry Smith }
1676d3042a70SBarry Smith 
1677d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatDenseResetArray_SeqDense(Mat A)
1678d71ae5a4SJacob Faibussowitsch {
1679d3042a70SBarry Smith   Mat_SeqDense *a = (Mat_SeqDense *)A->data;
1680d3042a70SBarry Smith 
1681d3042a70SBarry Smith   PetscFunctionBegin;
168228b400f6SJacob Faibussowitsch   PetscCheck(!a->vecinuse, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Need to call MatDenseRestoreColumnVec() first");
168328b400f6SJacob Faibussowitsch   PetscCheck(!a->matinuse, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Need to call MatDenseRestoreSubMatrix() first");
1684d3042a70SBarry Smith   a->v             = a->unplacedarray;
1685d3042a70SBarry Smith   a->user_alloc    = a->unplaced_user_alloc;
1686d3042a70SBarry Smith   a->unplacedarray = NULL;
168747d993e7Ssuyashtn #if defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
1688c70f7ee4SJunchao Zhang   A->offloadmask = PETSC_OFFLOAD_CPU;
1689ca15aa20SStefano Zampini #endif
16903ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1691d3042a70SBarry Smith }
1692d3042a70SBarry Smith 
1693d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatDenseReplaceArray_SeqDense(Mat A, const PetscScalar *array)
1694d71ae5a4SJacob Faibussowitsch {
1695d5ea218eSStefano Zampini   Mat_SeqDense *a = (Mat_SeqDense *)A->data;
1696d5ea218eSStefano Zampini 
1697d5ea218eSStefano Zampini   PetscFunctionBegin;
169828b400f6SJacob Faibussowitsch   PetscCheck(!a->vecinuse, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Need to call MatDenseRestoreColumnVec() first");
169928b400f6SJacob Faibussowitsch   PetscCheck(!a->matinuse, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Need to call MatDenseRestoreSubMatrix() first");
17009566063dSJacob Faibussowitsch   if (!a->user_alloc) PetscCall(PetscFree(a->v));
1701d5ea218eSStefano Zampini   a->v          = (PetscScalar *)array;
1702d5ea218eSStefano Zampini   a->user_alloc = PETSC_FALSE;
170347d993e7Ssuyashtn #if defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
1704d5ea218eSStefano Zampini   A->offloadmask = PETSC_OFFLOAD_CPU;
1705d5ea218eSStefano Zampini #endif
17063ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1707d5ea218eSStefano Zampini }
1708d5ea218eSStefano Zampini 
1709d71ae5a4SJacob Faibussowitsch PetscErrorCode MatDestroy_SeqDense(Mat mat)
1710d71ae5a4SJacob Faibussowitsch {
1711ec8511deSBarry Smith   Mat_SeqDense *l = (Mat_SeqDense *)mat->data;
171290f02eecSBarry Smith 
17133a40ed3dSBarry Smith   PetscFunctionBegin;
17143ba16761SJacob Faibussowitsch   PetscCall(PetscLogObjectState((PetscObject)mat, "Rows %" PetscInt_FMT " Cols %" PetscInt_FMT, mat->rmap->n, mat->cmap->n));
1715f4f49eeaSPierre Jolivet   PetscCall(VecDestroy(&l->qrrhs));
17169566063dSJacob Faibussowitsch   PetscCall(PetscFree(l->tau));
17179566063dSJacob Faibussowitsch   PetscCall(PetscFree(l->pivots));
17189566063dSJacob Faibussowitsch   PetscCall(PetscFree(l->fwork));
17199566063dSJacob Faibussowitsch   if (!l->user_alloc) PetscCall(PetscFree(l->v));
17209566063dSJacob Faibussowitsch   if (!l->unplaced_user_alloc) PetscCall(PetscFree(l->unplacedarray));
172128b400f6SJacob Faibussowitsch   PetscCheck(!l->vecinuse, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Need to call MatDenseRestoreColumnVec() first");
172228b400f6SJacob Faibussowitsch   PetscCheck(!l->matinuse, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Need to call MatDenseRestoreSubMatrix() first");
17239566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&l->cvec));
17249566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&l->cmat));
17259566063dSJacob Faibussowitsch   PetscCall(PetscFree(mat->data));
1726dbd8c25aSHong Zhang 
17279566063dSJacob Faibussowitsch   PetscCall(PetscObjectChangeTypeName((PetscObject)mat, NULL));
17289566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatQRFactor_C", NULL));
17292e956fe4SStefano Zampini   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatQRFactorSymbolic_C", NULL));
17302e956fe4SStefano Zampini   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatQRFactorNumeric_C", NULL));
17319566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatDenseGetLDA_C", NULL));
17329566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatDenseSetLDA_C", NULL));
17339566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatDenseGetArray_C", NULL));
17349566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatDenseRestoreArray_C", NULL));
17359566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatDensePlaceArray_C", NULL));
17369566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatDenseResetArray_C", NULL));
17379566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatDenseReplaceArray_C", NULL));
17389566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatDenseGetArrayRead_C", NULL));
17399566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatDenseRestoreArrayRead_C", NULL));
17409566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatDenseGetArrayWrite_C", NULL));
17419566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatDenseRestoreArrayWrite_C", NULL));
17429566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatConvert_seqdense_seqaij_C", NULL));
17438baccfbdSHong Zhang #if defined(PETSC_HAVE_ELEMENTAL)
17449566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatConvert_seqdense_elemental_C", NULL));
17458baccfbdSHong Zhang #endif
1746d24d4204SJose E. Roman #if defined(PETSC_HAVE_SCALAPACK)
17479566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatConvert_seqdense_scalapack_C", NULL));
1748d24d4204SJose E. Roman #endif
17492bf066beSStefano Zampini #if defined(PETSC_HAVE_CUDA)
17509566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatConvert_seqdense_seqdensecuda_C", NULL));
17519566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatProductSetFromOptions_seqdensecuda_seqdensecuda_C", NULL));
17529566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatProductSetFromOptions_seqdensecuda_seqdense_C", NULL));
17532e956fe4SStefano Zampini   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatProductSetFromOptions_seqdense_seqdensecuda_C", NULL));
17542bf066beSStefano Zampini #endif
175547d993e7Ssuyashtn #if defined(PETSC_HAVE_HIP)
175647d993e7Ssuyashtn   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatConvert_seqdense_seqdensehip_C", NULL));
175747d993e7Ssuyashtn   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatProductSetFromOptions_seqdensehip_seqdensehip_C", NULL));
175847d993e7Ssuyashtn   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatProductSetFromOptions_seqdensehip_seqdense_C", NULL));
175947d993e7Ssuyashtn   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatProductSetFromOptions_seqdense_seqdensehip_C", NULL));
176047d993e7Ssuyashtn #endif
17619566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatSeqDenseSetPreallocation_C", NULL));
17629566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatProductSetFromOptions_seqaij_seqdense_C", NULL));
17639566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatProductSetFromOptions_seqdense_seqdense_C", NULL));
17649566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatProductSetFromOptions_seqbaij_seqdense_C", NULL));
17659566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatProductSetFromOptions_seqsbaij_seqdense_C", NULL));
176652c5f739Sprj- 
17679566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatDenseGetColumn_C", NULL));
17689566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatDenseRestoreColumn_C", NULL));
17699566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatDenseGetColumnVec_C", NULL));
17709566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatDenseRestoreColumnVec_C", NULL));
17719566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatDenseGetColumnVecRead_C", NULL));
17729566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatDenseRestoreColumnVecRead_C", NULL));
17739566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatDenseGetColumnVecWrite_C", NULL));
17749566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatDenseRestoreColumnVecWrite_C", NULL));
17759566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatDenseGetSubMatrix_C", NULL));
17769566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatDenseRestoreSubMatrix_C", NULL));
1777d016bddeSToby Isaac   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatMultColumnRange_C", NULL));
17780be0d8bdSHansol Suh   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatMultAddColumnRange_C", NULL));
17790be0d8bdSHansol Suh   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatMultHermitianTransposeColumnRange_C", NULL));
17800be0d8bdSHansol Suh   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatMultHermitianTransposeAddColumnRange_C", NULL));
17813ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1782289bc588SBarry Smith }
1783289bc588SBarry Smith 
1784d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatTranspose_SeqDense(Mat A, MatReuse reuse, Mat *matout)
1785d71ae5a4SJacob Faibussowitsch {
1786c0bbcb79SLois Curfman McInnes   Mat_SeqDense *mat = (Mat_SeqDense *)A->data;
17876536e3caSStefano Zampini   PetscInt      k, j, m = A->rmap->n, M = mat->lda, n = A->cmap->n;
178887828ca2SBarry Smith   PetscScalar  *v, tmp;
178948b35521SBarry Smith 
17903a40ed3dSBarry Smith   PetscFunctionBegin;
17917fb60732SBarry Smith   if (reuse == MAT_REUSE_MATRIX) PetscCall(MatTransposeCheckNonzeroState_Private(A, *matout));
17926536e3caSStefano Zampini   if (reuse == MAT_INPLACE_MATRIX) {
17936536e3caSStefano Zampini     if (m == n) { /* in place transpose */
17949566063dSJacob Faibussowitsch       PetscCall(MatDenseGetArray(A, &v));
1795d3e5ee88SLois Curfman McInnes       for (j = 0; j < m; j++) {
1796289bc588SBarry Smith         for (k = 0; k < j; k++) {
17971b807ce4Svictorle           tmp          = v[j + k * M];
17981b807ce4Svictorle           v[j + k * M] = v[k + j * M];
17991b807ce4Svictorle           v[k + j * M] = tmp;
1800289bc588SBarry Smith         }
1801289bc588SBarry Smith       }
18029566063dSJacob Faibussowitsch       PetscCall(MatDenseRestoreArray(A, &v));
18036536e3caSStefano Zampini     } else { /* reuse memory, temporary allocates new memory */
18046536e3caSStefano Zampini       PetscScalar *v2;
18056536e3caSStefano Zampini       PetscLayout  tmplayout;
18066536e3caSStefano Zampini 
18079566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1((size_t)m * n, &v2));
18089566063dSJacob Faibussowitsch       PetscCall(MatDenseGetArray(A, &v));
18096536e3caSStefano Zampini       for (j = 0; j < n; j++) {
18106536e3caSStefano Zampini         for (k = 0; k < m; k++) v2[j + (size_t)k * n] = v[k + (size_t)j * M];
18116536e3caSStefano Zampini       }
18129566063dSJacob Faibussowitsch       PetscCall(PetscArraycpy(v, v2, (size_t)m * n));
18139566063dSJacob Faibussowitsch       PetscCall(PetscFree(v2));
18149566063dSJacob Faibussowitsch       PetscCall(MatDenseRestoreArray(A, &v));
18156536e3caSStefano Zampini       /* cleanup size dependent quantities */
18169566063dSJacob Faibussowitsch       PetscCall(VecDestroy(&mat->cvec));
18179566063dSJacob Faibussowitsch       PetscCall(MatDestroy(&mat->cmat));
18189566063dSJacob Faibussowitsch       PetscCall(PetscFree(mat->pivots));
18199566063dSJacob Faibussowitsch       PetscCall(PetscFree(mat->fwork));
18206536e3caSStefano Zampini       /* swap row/col layouts */
18216497c311SBarry Smith       PetscCall(PetscBLASIntCast(n, &mat->lda));
18226536e3caSStefano Zampini       tmplayout = A->rmap;
18236536e3caSStefano Zampini       A->rmap   = A->cmap;
18246536e3caSStefano Zampini       A->cmap   = tmplayout;
18256536e3caSStefano Zampini     }
18263a40ed3dSBarry Smith   } else { /* out-of-place transpose */
1827d3e5ee88SLois Curfman McInnes     Mat           tmat;
1828ec8511deSBarry Smith     Mat_SeqDense *tmatd;
182987828ca2SBarry Smith     PetscScalar  *v2;
1830af36a384SStefano Zampini     PetscInt      M2;
1831ea709b57SSatish Balay 
18326536e3caSStefano Zampini     if (reuse == MAT_INITIAL_MATRIX) {
18339566063dSJacob Faibussowitsch       PetscCall(MatCreate(PetscObjectComm((PetscObject)A), &tmat));
18349566063dSJacob Faibussowitsch       PetscCall(MatSetSizes(tmat, A->cmap->n, A->rmap->n, A->cmap->n, A->rmap->n));
18359566063dSJacob Faibussowitsch       PetscCall(MatSetType(tmat, ((PetscObject)A)->type_name));
18369566063dSJacob Faibussowitsch       PetscCall(MatSeqDenseSetPreallocation(tmat, NULL));
1837ca15aa20SStefano Zampini     } else tmat = *matout;
1838ca15aa20SStefano Zampini 
18399566063dSJacob Faibussowitsch     PetscCall(MatDenseGetArrayRead(A, (const PetscScalar **)&v));
18409566063dSJacob Faibussowitsch     PetscCall(MatDenseGetArray(tmat, &v2));
1841ec8511deSBarry Smith     tmatd = (Mat_SeqDense *)tmat->data;
1842ca15aa20SStefano Zampini     M2    = tmatd->lda;
1843d3e5ee88SLois Curfman McInnes     for (j = 0; j < n; j++) {
1844af36a384SStefano Zampini       for (k = 0; k < m; k++) v2[j + k * M2] = v[k + j * M];
1845d3e5ee88SLois Curfman McInnes     }
18469566063dSJacob Faibussowitsch     PetscCall(MatDenseRestoreArray(tmat, &v2));
18479566063dSJacob Faibussowitsch     PetscCall(MatDenseRestoreArrayRead(A, (const PetscScalar **)&v));
18489566063dSJacob Faibussowitsch     PetscCall(MatAssemblyBegin(tmat, MAT_FINAL_ASSEMBLY));
18499566063dSJacob Faibussowitsch     PetscCall(MatAssemblyEnd(tmat, MAT_FINAL_ASSEMBLY));
18506536e3caSStefano Zampini     *matout = tmat;
185148b35521SBarry Smith   }
18523ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1853289bc588SBarry Smith }
1854289bc588SBarry Smith 
1855d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatEqual_SeqDense(Mat A1, Mat A2, PetscBool *flg)
1856d71ae5a4SJacob Faibussowitsch {
1857c0bbcb79SLois Curfman McInnes   Mat_SeqDense      *mat1 = (Mat_SeqDense *)A1->data;
1858c0bbcb79SLois Curfman McInnes   Mat_SeqDense      *mat2 = (Mat_SeqDense *)A2->data;
1859ca15aa20SStefano Zampini   PetscInt           i;
1860ca15aa20SStefano Zampini   const PetscScalar *v1, *v2;
18619ea5d5aeSSatish Balay 
18623a40ed3dSBarry Smith   PetscFunctionBegin;
18639371c9d4SSatish Balay   if (A1->rmap->n != A2->rmap->n) {
18649371c9d4SSatish Balay     *flg = PETSC_FALSE;
18653ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
18669371c9d4SSatish Balay   }
18679371c9d4SSatish Balay   if (A1->cmap->n != A2->cmap->n) {
18689371c9d4SSatish Balay     *flg = PETSC_FALSE;
18693ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
18709371c9d4SSatish Balay   }
18719566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArrayRead(A1, &v1));
18729566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArrayRead(A2, &v2));
1873ca15aa20SStefano Zampini   for (i = 0; i < A1->cmap->n; i++) {
18749566063dSJacob Faibussowitsch     PetscCall(PetscArraycmp(v1, v2, A1->rmap->n, flg));
18753ba16761SJacob Faibussowitsch     if (*flg == PETSC_FALSE) PetscFunctionReturn(PETSC_SUCCESS);
1876ca15aa20SStefano Zampini     v1 += mat1->lda;
1877ca15aa20SStefano Zampini     v2 += mat2->lda;
18781b807ce4Svictorle   }
18799566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArrayRead(A1, &v1));
18809566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArrayRead(A2, &v2));
188177c4ece6SBarry Smith   *flg = PETSC_TRUE;
18823ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1883289bc588SBarry Smith }
1884289bc588SBarry Smith 
188514277c92SJacob Faibussowitsch PetscErrorCode MatGetDiagonal_SeqDense(Mat A, Vec v)
1886d71ae5a4SJacob Faibussowitsch {
1887c0bbcb79SLois Curfman McInnes   Mat_SeqDense      *mat = (Mat_SeqDense *)A->data;
188813f74950SBarry Smith   PetscInt           i, n, len;
1889ca15aa20SStefano Zampini   PetscScalar       *x;
1890ca15aa20SStefano Zampini   const PetscScalar *vv;
189144cd7ae7SLois Curfman McInnes 
18923a40ed3dSBarry Smith   PetscFunctionBegin;
18939566063dSJacob Faibussowitsch   PetscCall(VecGetSize(v, &n));
18949566063dSJacob Faibussowitsch   PetscCall(VecGetArray(v, &x));
1895d0f46423SBarry Smith   len = PetscMin(A->rmap->n, A->cmap->n);
18969566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArrayRead(A, &vv));
189708401ef6SPierre Jolivet   PetscCheck(n == A->rmap->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Nonconforming mat and vec");
1898ad540459SPierre Jolivet   for (i = 0; i < len; i++) x[i] = vv[i * mat->lda + i];
18999566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArrayRead(A, &vv));
19009566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(v, &x));
19013ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1902289bc588SBarry Smith }
1903289bc588SBarry Smith 
1904d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatDiagonalScale_SeqDense(Mat A, Vec ll, Vec rr)
1905d71ae5a4SJacob Faibussowitsch {
1906c0bbcb79SLois Curfman McInnes   Mat_SeqDense      *mat = (Mat_SeqDense *)A->data;
1907f1ceaac6SMatthew G. Knepley   const PetscScalar *l, *r;
1908ca15aa20SStefano Zampini   PetscScalar        x, *v, *vv;
1909d0f46423SBarry Smith   PetscInt           i, j, m = A->rmap->n, n = A->cmap->n;
191055659b69SBarry Smith 
19113a40ed3dSBarry Smith   PetscFunctionBegin;
19129566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArray(A, &vv));
191328988994SBarry Smith   if (ll) {
19149566063dSJacob Faibussowitsch     PetscCall(VecGetSize(ll, &m));
19159566063dSJacob Faibussowitsch     PetscCall(VecGetArrayRead(ll, &l));
191608401ef6SPierre Jolivet     PetscCheck(m == A->rmap->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Left scaling vec wrong size");
1917da3a660dSBarry Smith     for (i = 0; i < m; i++) {
1918da3a660dSBarry Smith       x = l[i];
1919ca15aa20SStefano Zampini       v = vv + i;
19209371c9d4SSatish Balay       for (j = 0; j < n; j++) {
19219371c9d4SSatish Balay         (*v) *= x;
19229371c9d4SSatish Balay         v += mat->lda;
19239371c9d4SSatish Balay       }
1924da3a660dSBarry Smith     }
19259566063dSJacob Faibussowitsch     PetscCall(VecRestoreArrayRead(ll, &l));
19269566063dSJacob Faibussowitsch     PetscCall(PetscLogFlops(1.0 * n * m));
1927da3a660dSBarry Smith   }
192828988994SBarry Smith   if (rr) {
19299566063dSJacob Faibussowitsch     PetscCall(VecGetSize(rr, &n));
19309566063dSJacob Faibussowitsch     PetscCall(VecGetArrayRead(rr, &r));
193108401ef6SPierre Jolivet     PetscCheck(n == A->cmap->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Right scaling vec wrong size");
1932da3a660dSBarry Smith     for (i = 0; i < n; i++) {
1933da3a660dSBarry Smith       x = r[i];
1934ca15aa20SStefano Zampini       v = vv + i * mat->lda;
19352205254eSKarl Rupp       for (j = 0; j < m; j++) (*v++) *= x;
1936da3a660dSBarry Smith     }
19379566063dSJacob Faibussowitsch     PetscCall(VecRestoreArrayRead(rr, &r));
19389566063dSJacob Faibussowitsch     PetscCall(PetscLogFlops(1.0 * n * m));
1939da3a660dSBarry Smith   }
19409566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArray(A, &vv));
19413ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1942289bc588SBarry Smith }
1943289bc588SBarry Smith 
1944d71ae5a4SJacob Faibussowitsch PetscErrorCode MatNorm_SeqDense(Mat A, NormType type, PetscReal *nrm)
1945d71ae5a4SJacob Faibussowitsch {
1946c0bbcb79SLois Curfman McInnes   Mat_SeqDense *mat = (Mat_SeqDense *)A->data;
1947ca15aa20SStefano Zampini   PetscScalar  *v, *vv;
1948329f5518SBarry Smith   PetscReal     sum = 0.0;
194975f6d85dSStefano Zampini   PetscInt      lda, m = A->rmap->n, i, j;
195055659b69SBarry Smith 
19513a40ed3dSBarry Smith   PetscFunctionBegin;
19529566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArrayRead(A, (const PetscScalar **)&vv));
19539566063dSJacob Faibussowitsch   PetscCall(MatDenseGetLDA(A, &lda));
1954ca15aa20SStefano Zampini   v = vv;
1955289bc588SBarry Smith   if (type == NORM_FROBENIUS) {
1956a5ce6ee0Svictorle     if (lda > m) {
1957d0f46423SBarry Smith       for (j = 0; j < A->cmap->n; j++) {
1958ca15aa20SStefano Zampini         v = vv + j * lda;
1959a5ce6ee0Svictorle         for (i = 0; i < m; i++) {
19609371c9d4SSatish Balay           sum += PetscRealPart(PetscConj(*v) * (*v));
19619371c9d4SSatish Balay           v++;
1962a5ce6ee0Svictorle         }
1963a5ce6ee0Svictorle       }
1964a5ce6ee0Svictorle     } else {
1965570b7f6dSBarry Smith #if defined(PETSC_USE_REAL___FP16)
1966570b7f6dSBarry Smith       PetscBLASInt one = 1, cnt = A->cmap->n * A->rmap->n;
1967792fecdfSBarry Smith       PetscCallBLAS("BLASnrm2", *nrm = BLASnrm2_(&cnt, v, &one));
1968570b7f6dSBarry Smith     }
1969570b7f6dSBarry Smith #else
1970d0f46423SBarry Smith       for (i = 0; i < A->cmap->n * A->rmap->n; i++) {
19719371c9d4SSatish Balay         sum += PetscRealPart(PetscConj(*v) * (*v));
19729371c9d4SSatish Balay         v++;
1973289bc588SBarry Smith       }
1974a5ce6ee0Svictorle     }
19758f1a2a5eSBarry Smith     *nrm = PetscSqrtReal(sum);
1976570b7f6dSBarry Smith #endif
19779566063dSJacob Faibussowitsch     PetscCall(PetscLogFlops(2.0 * A->cmap->n * A->rmap->n));
19783a40ed3dSBarry Smith   } else if (type == NORM_1) {
1979064f8208SBarry Smith     *nrm = 0.0;
1980d0f46423SBarry Smith     for (j = 0; j < A->cmap->n; j++) {
1981ca15aa20SStefano Zampini       v   = vv + j * mat->lda;
1982289bc588SBarry Smith       sum = 0.0;
1983d0f46423SBarry Smith       for (i = 0; i < A->rmap->n; i++) {
19849371c9d4SSatish Balay         sum += PetscAbsScalar(*v);
19859371c9d4SSatish Balay         v++;
1986289bc588SBarry Smith       }
1987064f8208SBarry Smith       if (sum > *nrm) *nrm = sum;
1988289bc588SBarry Smith     }
19899566063dSJacob Faibussowitsch     PetscCall(PetscLogFlops(1.0 * A->cmap->n * A->rmap->n));
19903a40ed3dSBarry Smith   } else if (type == NORM_INFINITY) {
1991064f8208SBarry Smith     *nrm = 0.0;
1992d0f46423SBarry Smith     for (j = 0; j < A->rmap->n; j++) {
1993ca15aa20SStefano Zampini       v   = vv + j;
1994289bc588SBarry Smith       sum = 0.0;
1995d0f46423SBarry Smith       for (i = 0; i < A->cmap->n; i++) {
19969371c9d4SSatish Balay         sum += PetscAbsScalar(*v);
19979371c9d4SSatish Balay         v += mat->lda;
1998289bc588SBarry Smith       }
1999064f8208SBarry Smith       if (sum > *nrm) *nrm = sum;
2000289bc588SBarry Smith     }
20019566063dSJacob Faibussowitsch     PetscCall(PetscLogFlops(1.0 * A->cmap->n * A->rmap->n));
2002e7e72b3dSBarry Smith   } else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "No two norm");
20039566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArrayRead(A, (const PetscScalar **)&vv));
20043ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2005289bc588SBarry Smith }
2006289bc588SBarry Smith 
2007d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatSetOption_SeqDense(Mat A, MatOption op, PetscBool flg)
2008d71ae5a4SJacob Faibussowitsch {
2009c0bbcb79SLois Curfman McInnes   Mat_SeqDense *aij = (Mat_SeqDense *)A->data;
201067e560aaSBarry Smith 
20113a40ed3dSBarry Smith   PetscFunctionBegin;
2012b5a2b587SKris Buschelman   switch (op) {
2013d71ae5a4SJacob Faibussowitsch   case MAT_ROW_ORIENTED:
2014d71ae5a4SJacob Faibussowitsch     aij->roworiented = flg;
2015d71ae5a4SJacob Faibussowitsch     break;
2016d71ae5a4SJacob Faibussowitsch   default:
2017888c827cSStefano Zampini     break;
20183a40ed3dSBarry Smith   }
20193ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2020289bc588SBarry Smith }
2021289bc588SBarry Smith 
2022d71ae5a4SJacob Faibussowitsch PetscErrorCode MatZeroEntries_SeqDense(Mat A)
2023d71ae5a4SJacob Faibussowitsch {
2024ec8511deSBarry Smith   Mat_SeqDense *l   = (Mat_SeqDense *)A->data;
20253d8925e7SStefano Zampini   PetscInt      lda = l->lda, m = A->rmap->n, n = A->cmap->n, j;
2026ca15aa20SStefano Zampini   PetscScalar  *v;
20273a40ed3dSBarry Smith 
20283a40ed3dSBarry Smith   PetscFunctionBegin;
20299566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArrayWrite(A, &v));
2030a5ce6ee0Svictorle   if (lda > m) {
203148a46eb9SPierre Jolivet     for (j = 0; j < n; j++) PetscCall(PetscArrayzero(v + j * lda, m));
2032a5ce6ee0Svictorle   } else {
20339566063dSJacob Faibussowitsch     PetscCall(PetscArrayzero(v, PetscInt64Mult(m, n)));
2034a5ce6ee0Svictorle   }
20359566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArrayWrite(A, &v));
20363ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
20376f0a148fSBarry Smith }
20386f0a148fSBarry Smith 
2039d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatZeroRows_SeqDense(Mat A, PetscInt N, const PetscInt rows[], PetscScalar diag, Vec x, Vec b)
2040d71ae5a4SJacob Faibussowitsch {
2041ec8511deSBarry Smith   Mat_SeqDense      *l = (Mat_SeqDense *)A->data;
2042b9679d65SBarry Smith   PetscInt           m = l->lda, n = A->cmap->n, i, j;
2043ca15aa20SStefano Zampini   PetscScalar       *slot, *bb, *v;
204497b48c8fSBarry Smith   const PetscScalar *xx;
204555659b69SBarry Smith 
20463a40ed3dSBarry Smith   PetscFunctionBegin;
204776bd3646SJed Brown   if (PetscDefined(USE_DEBUG)) {
2048b9679d65SBarry Smith     for (i = 0; i < N; i++) {
204908401ef6SPierre Jolivet       PetscCheck(rows[i] >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Negative row requested to be zeroed");
205008401ef6SPierre 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);
2051b9679d65SBarry Smith     }
205276bd3646SJed Brown   }
20533ba16761SJacob Faibussowitsch   if (!N) PetscFunctionReturn(PETSC_SUCCESS);
2054b9679d65SBarry Smith 
2055dd8e379bSPierre Jolivet   /* fix right-hand side if needed */
205697b48c8fSBarry Smith   if (x && b) {
20579566063dSJacob Faibussowitsch     PetscCall(VecGetArrayRead(x, &xx));
20589566063dSJacob Faibussowitsch     PetscCall(VecGetArray(b, &bb));
20592205254eSKarl Rupp     for (i = 0; i < N; i++) bb[rows[i]] = diag * xx[rows[i]];
20609566063dSJacob Faibussowitsch     PetscCall(VecRestoreArrayRead(x, &xx));
20619566063dSJacob Faibussowitsch     PetscCall(VecRestoreArray(b, &bb));
206297b48c8fSBarry Smith   }
206397b48c8fSBarry Smith 
20649566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArray(A, &v));
20656f0a148fSBarry Smith   for (i = 0; i < N; i++) {
2066ca15aa20SStefano Zampini     slot = v + rows[i];
20679371c9d4SSatish Balay     for (j = 0; j < n; j++) {
20689371c9d4SSatish Balay       *slot = 0.0;
20699371c9d4SSatish Balay       slot += m;
20709371c9d4SSatish Balay     }
20716f0a148fSBarry Smith   }
2072f4df32b1SMatthew Knepley   if (diag != 0.0) {
207308401ef6SPierre Jolivet     PetscCheck(A->rmap->n == A->cmap->n, PETSC_COMM_SELF, PETSC_ERR_SUP, "Only coded for square matrices");
20746f0a148fSBarry Smith     for (i = 0; i < N; i++) {
2075ca15aa20SStefano Zampini       slot  = v + (m + 1) * rows[i];
2076f4df32b1SMatthew Knepley       *slot = diag;
20776f0a148fSBarry Smith     }
20786f0a148fSBarry Smith   }
20799566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArray(A, &v));
20803ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
20816f0a148fSBarry Smith }
2082557bce09SLois Curfman McInnes 
2083d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatDenseGetLDA_SeqDense(Mat A, PetscInt *lda)
2084d71ae5a4SJacob Faibussowitsch {
208549a6ff4bSBarry Smith   Mat_SeqDense *mat = (Mat_SeqDense *)A->data;
208649a6ff4bSBarry Smith 
208749a6ff4bSBarry Smith   PetscFunctionBegin;
208849a6ff4bSBarry Smith   *lda = mat->lda;
20893ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
209049a6ff4bSBarry Smith }
209149a6ff4bSBarry Smith 
2092d71ae5a4SJacob Faibussowitsch PetscErrorCode MatDenseGetArray_SeqDense(Mat A, PetscScalar **array)
2093d71ae5a4SJacob Faibussowitsch {
2094c0bbcb79SLois Curfman McInnes   Mat_SeqDense *mat = (Mat_SeqDense *)A->data;
20953a40ed3dSBarry Smith 
20963a40ed3dSBarry Smith   PetscFunctionBegin;
209728b400f6SJacob Faibussowitsch   PetscCheck(!mat->matinuse, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Need to call MatDenseRestoreSubMatrix() first");
209864e87e97SBarry Smith   *array = mat->v;
20993ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
210064e87e97SBarry Smith }
21010754003eSLois Curfman McInnes 
2102d71ae5a4SJacob Faibussowitsch PetscErrorCode MatDenseRestoreArray_SeqDense(Mat A, PetscScalar **array)
2103d71ae5a4SJacob Faibussowitsch {
21043a40ed3dSBarry Smith   PetscFunctionBegin;
210575f6d85dSStefano Zampini   if (array) *array = NULL;
21063ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2107ff14e315SSatish Balay }
21080754003eSLois Curfman McInnes 
21090f74d2c1SSatish Balay /*@
211011a5261eSBarry Smith   MatDenseGetLDA - gets the leading dimension of the array returned from `MatDenseGetArray()`
211149a6ff4bSBarry Smith 
21122ef1f0ffSBarry Smith   Not Collective
211349a6ff4bSBarry Smith 
211449a6ff4bSBarry Smith   Input Parameter:
2115fe59aa6dSJacob Faibussowitsch . A - a `MATDENSE` or `MATDENSECUDA` matrix
211649a6ff4bSBarry Smith 
211749a6ff4bSBarry Smith   Output Parameter:
211849a6ff4bSBarry Smith . lda - the leading dimension
211949a6ff4bSBarry Smith 
212049a6ff4bSBarry Smith   Level: intermediate
212149a6ff4bSBarry Smith 
21221cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATDENSE`, `MATDENSECUDA`, `MatDenseGetArray()`, `MatDenseRestoreArray()`, `MatDenseGetArrayRead()`, `MatDenseRestoreArrayRead()`, `MatDenseSetLDA()`
212349a6ff4bSBarry Smith @*/
2124d71ae5a4SJacob Faibussowitsch PetscErrorCode MatDenseGetLDA(Mat A, PetscInt *lda)
2125d71ae5a4SJacob Faibussowitsch {
212649a6ff4bSBarry Smith   PetscFunctionBegin;
2127d5ea218eSStefano Zampini   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
21284f572ea9SToby Isaac   PetscAssertPointer(lda, 2);
212975f6d85dSStefano Zampini   MatCheckPreallocated(A, 1);
2130cac4c232SBarry Smith   PetscUseMethod(A, "MatDenseGetLDA_C", (Mat, PetscInt *), (A, lda));
21313ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
213249a6ff4bSBarry Smith }
213349a6ff4bSBarry Smith 
21340f74d2c1SSatish Balay /*@
213511a5261eSBarry Smith   MatDenseSetLDA - Sets the leading dimension of the array used by the `MATDENSE` matrix
2136ad16ce7aSStefano Zampini 
21372323109cSBarry Smith   Collective if the matrix layouts have not yet been setup
2138ad16ce7aSStefano Zampini 
2139d8d19677SJose E. Roman   Input Parameters:
2140fe59aa6dSJacob Faibussowitsch + A   - a `MATDENSE` or `MATDENSECUDA` matrix
2141ad16ce7aSStefano Zampini - lda - the leading dimension
2142ad16ce7aSStefano Zampini 
2143ad16ce7aSStefano Zampini   Level: intermediate
2144ad16ce7aSStefano Zampini 
21451cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATDENSE`, `MATDENSECUDA`, `MatDenseGetArray()`, `MatDenseRestoreArray()`, `MatDenseGetArrayRead()`, `MatDenseRestoreArrayRead()`, `MatDenseGetLDA()`
2146ad16ce7aSStefano Zampini @*/
2147d71ae5a4SJacob Faibussowitsch PetscErrorCode MatDenseSetLDA(Mat A, PetscInt lda)
2148d71ae5a4SJacob Faibussowitsch {
2149ad16ce7aSStefano Zampini   PetscFunctionBegin;
2150ad16ce7aSStefano Zampini   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
2151cac4c232SBarry Smith   PetscTryMethod(A, "MatDenseSetLDA_C", (Mat, PetscInt), (A, lda));
21523ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2153ad16ce7aSStefano Zampini }
2154ad16ce7aSStefano Zampini 
2155ad16ce7aSStefano Zampini /*@C
215611a5261eSBarry Smith   MatDenseGetArray - gives read-write access to the array where the data for a `MATDENSE` matrix is stored
215773a71a0fSBarry Smith 
2158c3339decSBarry Smith   Logically Collective
215973a71a0fSBarry Smith 
216073a71a0fSBarry Smith   Input Parameter:
2161fe59aa6dSJacob Faibussowitsch . A - a dense matrix
216273a71a0fSBarry Smith 
216373a71a0fSBarry Smith   Output Parameter:
216473a71a0fSBarry Smith . array - pointer to the data
216573a71a0fSBarry Smith 
216673a71a0fSBarry Smith   Level: intermediate
216773a71a0fSBarry Smith 
21681cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATDENSE`, `MatDenseRestoreArray()`, `MatDenseGetArrayRead()`, `MatDenseRestoreArrayRead()`, `MatDenseGetArrayWrite()`, `MatDenseRestoreArrayWrite()`
216973a71a0fSBarry Smith @*/
2170ce78bad3SBarry Smith PetscErrorCode MatDenseGetArray(Mat A, PetscScalar *array[]) PeNS
2171d71ae5a4SJacob Faibussowitsch {
217273a71a0fSBarry Smith   PetscFunctionBegin;
2173d5ea218eSStefano Zampini   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
21744f572ea9SToby Isaac   PetscAssertPointer(array, 2);
2175cac4c232SBarry Smith   PetscUseMethod(A, "MatDenseGetArray_C", (Mat, PetscScalar **), (A, array));
21763ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
217773a71a0fSBarry Smith }
217873a71a0fSBarry Smith 
2179dec5eb66SMatthew G Knepley /*@C
218011a5261eSBarry Smith   MatDenseRestoreArray - returns access to the array where the data for a `MATDENSE` matrix is stored obtained by `MatDenseGetArray()`
218173a71a0fSBarry Smith 
2182c3339decSBarry Smith   Logically Collective
21838572280aSBarry Smith 
21848572280aSBarry Smith   Input Parameters:
2185fe59aa6dSJacob Faibussowitsch + A     - a dense matrix
21862ef1f0ffSBarry Smith - array - pointer to the data (may be `NULL`)
21878572280aSBarry Smith 
21888572280aSBarry Smith   Level: intermediate
21898572280aSBarry Smith 
21901cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATDENSE`, `MatDenseGetArray()`, `MatDenseGetArrayRead()`, `MatDenseRestoreArrayRead()`, `MatDenseGetArrayWrite()`, `MatDenseRestoreArrayWrite()`
21918572280aSBarry Smith @*/
2192ce78bad3SBarry Smith PetscErrorCode MatDenseRestoreArray(Mat A, PetscScalar *array[]) PeNS
2193d71ae5a4SJacob Faibussowitsch {
21948572280aSBarry Smith   PetscFunctionBegin;
2195d5ea218eSStefano Zampini   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
21964f572ea9SToby Isaac   if (array) PetscAssertPointer(array, 2);
2197cac4c232SBarry Smith   PetscUseMethod(A, "MatDenseRestoreArray_C", (Mat, PetscScalar **), (A, array));
21989566063dSJacob Faibussowitsch   PetscCall(PetscObjectStateIncrease((PetscObject)A));
219947d993e7Ssuyashtn #if defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
2200637a0070SStefano Zampini   A->offloadmask = PETSC_OFFLOAD_CPU;
2201637a0070SStefano Zampini #endif
22023ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
22038572280aSBarry Smith }
22048572280aSBarry Smith 
22058572280aSBarry Smith /*@C
220611a5261eSBarry Smith   MatDenseGetArrayRead - gives read-only access to the array where the data for a `MATDENSE` matrix is stored
22078572280aSBarry Smith 
2208fb850c59SBarry Smith   Not Collective
22098572280aSBarry Smith 
22108572280aSBarry Smith   Input Parameter:
2211fe59aa6dSJacob Faibussowitsch . A - a dense matrix
22128572280aSBarry Smith 
22138572280aSBarry Smith   Output Parameter:
22148572280aSBarry Smith . array - pointer to the data
22158572280aSBarry Smith 
22168572280aSBarry Smith   Level: intermediate
22178572280aSBarry Smith 
22181cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATDENSE`, `MatDenseRestoreArrayRead()`, `MatDenseGetArray()`, `MatDenseRestoreArray()`, `MatDenseGetArrayWrite()`, `MatDenseRestoreArrayWrite()`
22198572280aSBarry Smith @*/
2220ce78bad3SBarry Smith PetscErrorCode MatDenseGetArrayRead(Mat A, const PetscScalar *array[]) PeNS
2221d71ae5a4SJacob Faibussowitsch {
22228572280aSBarry Smith   PetscFunctionBegin;
2223d5ea218eSStefano Zampini   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
22244f572ea9SToby Isaac   PetscAssertPointer(array, 2);
22255c0db29aSPierre Jolivet   PetscUseMethod(A, "MatDenseGetArrayRead_C", (Mat, PetscScalar **), (A, (PetscScalar **)array));
22263ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
22278572280aSBarry Smith }
22288572280aSBarry Smith 
22298572280aSBarry Smith /*@C
223011a5261eSBarry Smith   MatDenseRestoreArrayRead - returns access to the array where the data for a `MATDENSE` matrix is stored obtained by `MatDenseGetArrayRead()`
22318572280aSBarry Smith 
2232fb850c59SBarry Smith   Not Collective
223373a71a0fSBarry Smith 
223473a71a0fSBarry Smith   Input Parameters:
2235fe59aa6dSJacob Faibussowitsch + A     - a dense matrix
22362ef1f0ffSBarry Smith - array - pointer to the data (may be `NULL`)
223773a71a0fSBarry Smith 
223873a71a0fSBarry Smith   Level: intermediate
223973a71a0fSBarry Smith 
22401cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATDENSE`, `MatDenseGetArrayRead()`, `MatDenseGetArray()`, `MatDenseRestoreArray()`, `MatDenseGetArrayWrite()`, `MatDenseRestoreArrayWrite()`
224173a71a0fSBarry Smith @*/
2242ce78bad3SBarry Smith PetscErrorCode MatDenseRestoreArrayRead(Mat A, const PetscScalar *array[]) PeNS
2243d71ae5a4SJacob Faibussowitsch {
224473a71a0fSBarry Smith   PetscFunctionBegin;
2245d5ea218eSStefano Zampini   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
22464f572ea9SToby Isaac   if (array) PetscAssertPointer(array, 2);
22475c0db29aSPierre Jolivet   PetscUseMethod(A, "MatDenseRestoreArrayRead_C", (Mat, PetscScalar **), (A, (PetscScalar **)array));
22483ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
224973a71a0fSBarry Smith }
225073a71a0fSBarry Smith 
22516947451fSStefano Zampini /*@C
225211a5261eSBarry Smith   MatDenseGetArrayWrite - gives write-only access to the array where the data for a `MATDENSE` matrix is stored
22536947451fSStefano Zampini 
2254fb850c59SBarry Smith   Not Collective
22556947451fSStefano Zampini 
22566947451fSStefano Zampini   Input Parameter:
2257fe59aa6dSJacob Faibussowitsch . A - a dense matrix
22586947451fSStefano Zampini 
22596947451fSStefano Zampini   Output Parameter:
22606947451fSStefano Zampini . array - pointer to the data
22616947451fSStefano Zampini 
22626947451fSStefano Zampini   Level: intermediate
22636947451fSStefano Zampini 
22641cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATDENSE`, `MatDenseRestoreArrayWrite()`, `MatDenseGetArray()`, `MatDenseRestoreArray()`, `MatDenseGetArrayRead()`, `MatDenseRestoreArrayRead()`
22656947451fSStefano Zampini @*/
2266ce78bad3SBarry Smith PetscErrorCode MatDenseGetArrayWrite(Mat A, PetscScalar *array[]) PeNS
2267d71ae5a4SJacob Faibussowitsch {
22686947451fSStefano Zampini   PetscFunctionBegin;
2269d5ea218eSStefano Zampini   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
22704f572ea9SToby Isaac   PetscAssertPointer(array, 2);
2271cac4c232SBarry Smith   PetscUseMethod(A, "MatDenseGetArrayWrite_C", (Mat, PetscScalar **), (A, array));
22723ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
22736947451fSStefano Zampini }
22746947451fSStefano Zampini 
22756947451fSStefano Zampini /*@C
227611a5261eSBarry Smith   MatDenseRestoreArrayWrite - returns access to the array where the data for a `MATDENSE` matrix is stored obtained by `MatDenseGetArrayWrite()`
22776947451fSStefano Zampini 
2278fb850c59SBarry Smith   Not Collective
22796947451fSStefano Zampini 
22806947451fSStefano Zampini   Input Parameters:
2281fe59aa6dSJacob Faibussowitsch + A     - a dense matrix
22822ef1f0ffSBarry Smith - array - pointer to the data (may be `NULL`)
22836947451fSStefano Zampini 
22846947451fSStefano Zampini   Level: intermediate
22856947451fSStefano Zampini 
22861cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATDENSE`, `MatDenseGetArrayWrite()`, `MatDenseGetArray()`, `MatDenseRestoreArray()`, `MatDenseGetArrayRead()`, `MatDenseRestoreArrayRead()`
22876947451fSStefano Zampini @*/
2288ce78bad3SBarry Smith PetscErrorCode MatDenseRestoreArrayWrite(Mat A, PetscScalar *array[]) PeNS
2289d71ae5a4SJacob Faibussowitsch {
22906947451fSStefano Zampini   PetscFunctionBegin;
2291d5ea218eSStefano Zampini   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
22924f572ea9SToby Isaac   if (array) PetscAssertPointer(array, 2);
2293cac4c232SBarry Smith   PetscUseMethod(A, "MatDenseRestoreArrayWrite_C", (Mat, PetscScalar **), (A, array));
22949566063dSJacob Faibussowitsch   PetscCall(PetscObjectStateIncrease((PetscObject)A));
229547d993e7Ssuyashtn #if defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
22966947451fSStefano Zampini   A->offloadmask = PETSC_OFFLOAD_CPU;
22976947451fSStefano Zampini #endif
22983ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
22996947451fSStefano Zampini }
23006947451fSStefano Zampini 
2301cd3f9d89SJunchao Zhang /*@C
2302cd3f9d89SJunchao Zhang   MatDenseGetArrayAndMemType - gives read-write access to the array where the data for a `MATDENSE` matrix is stored
2303cd3f9d89SJunchao Zhang 
2304cd3f9d89SJunchao Zhang   Logically Collective
2305cd3f9d89SJunchao Zhang 
2306cd3f9d89SJunchao Zhang   Input Parameter:
2307fe59aa6dSJacob Faibussowitsch . A - a dense matrix
2308cd3f9d89SJunchao Zhang 
2309cd3f9d89SJunchao Zhang   Output Parameters:
2310cd3f9d89SJunchao Zhang + array - pointer to the data
2311cd3f9d89SJunchao Zhang - mtype - memory type of the returned pointer
2312cd3f9d89SJunchao Zhang 
2313cd3f9d89SJunchao Zhang   Level: intermediate
2314cd3f9d89SJunchao Zhang 
2315fb850c59SBarry Smith   Note:
23162ef1f0ffSBarry Smith   If the matrix is of a device type such as `MATDENSECUDA`, `MATDENSEHIP`, etc.,
23172ef1f0ffSBarry Smith   an array on device is always returned and is guaranteed to contain the matrix's latest data.
23182ef1f0ffSBarry Smith 
23191cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATDENSE`, `MatDenseRestoreArrayAndMemType()`, `MatDenseGetArrayReadAndMemType()`, `MatDenseGetArrayWriteAndMemType()`, `MatDenseGetArrayRead()`,
2320cd3f9d89SJunchao Zhang    `MatDenseRestoreArrayRead()`, `MatDenseGetArrayWrite()`, `MatDenseRestoreArrayWrite()`, `MatSeqAIJGetCSRAndMemType()`
2321cd3f9d89SJunchao Zhang @*/
23225d83a8b1SBarry Smith PetscErrorCode MatDenseGetArrayAndMemType(Mat A, PetscScalar *array[], PetscMemType *mtype)
2323cd3f9d89SJunchao Zhang {
2324cd3f9d89SJunchao Zhang   PetscBool isMPI;
2325cd3f9d89SJunchao Zhang 
2326cd3f9d89SJunchao Zhang   PetscFunctionBegin;
2327cd3f9d89SJunchao Zhang   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
23284f572ea9SToby Isaac   PetscAssertPointer(array, 2);
2329e865de01SJunchao 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 */
2330cd3f9d89SJunchao Zhang   PetscCall(PetscObjectBaseTypeCompare((PetscObject)A, MATMPIDENSE, &isMPI));
2331cd3f9d89SJunchao Zhang   if (isMPI) {
2332cd3f9d89SJunchao Zhang     /* Dispatch here so that the code can be reused for all subclasses of MATDENSE */
2333cd3f9d89SJunchao Zhang     PetscCall(MatDenseGetArrayAndMemType(((Mat_MPIDense *)A->data)->A, array, mtype));
2334cd3f9d89SJunchao Zhang   } else {
2335cd3f9d89SJunchao Zhang     PetscErrorCode (*fptr)(Mat, PetscScalar **, PetscMemType *);
23363ba16761SJacob Faibussowitsch 
23373ba16761SJacob Faibussowitsch     PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatDenseGetArrayAndMemType_C", &fptr));
2338cd3f9d89SJunchao Zhang     if (fptr) {
2339cd3f9d89SJunchao Zhang       PetscCall((*fptr)(A, array, mtype));
2340cd3f9d89SJunchao Zhang     } else {
2341cd3f9d89SJunchao Zhang       PetscUseMethod(A, "MatDenseGetArray_C", (Mat, PetscScalar **), (A, array));
2342cd3f9d89SJunchao Zhang       if (mtype) *mtype = PETSC_MEMTYPE_HOST;
2343cd3f9d89SJunchao Zhang     }
2344cd3f9d89SJunchao Zhang   }
23453ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2346cd3f9d89SJunchao Zhang }
2347cd3f9d89SJunchao Zhang 
2348cd3f9d89SJunchao Zhang /*@C
2349cd3f9d89SJunchao Zhang   MatDenseRestoreArrayAndMemType - returns access to the array that is obtained by `MatDenseGetArrayAndMemType()`
2350cd3f9d89SJunchao Zhang 
2351cd3f9d89SJunchao Zhang   Logically Collective
2352cd3f9d89SJunchao Zhang 
2353cd3f9d89SJunchao Zhang   Input Parameters:
2354fe59aa6dSJacob Faibussowitsch + A     - a dense matrix
2355cd3f9d89SJunchao Zhang - array - pointer to the data
2356cd3f9d89SJunchao Zhang 
2357cd3f9d89SJunchao Zhang   Level: intermediate
2358cd3f9d89SJunchao Zhang 
23591cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATDENSE`, `MatDenseGetArrayAndMemType()`, `MatDenseGetArray()`, `MatDenseGetArrayRead()`, `MatDenseRestoreArrayRead()`, `MatDenseGetArrayWrite()`, `MatDenseRestoreArrayWrite()`
2360cd3f9d89SJunchao Zhang @*/
23615d83a8b1SBarry Smith PetscErrorCode MatDenseRestoreArrayAndMemType(Mat A, PetscScalar *array[])
2362cd3f9d89SJunchao Zhang {
2363cd3f9d89SJunchao Zhang   PetscBool isMPI;
2364cd3f9d89SJunchao Zhang 
2365cd3f9d89SJunchao Zhang   PetscFunctionBegin;
2366cd3f9d89SJunchao Zhang   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
2367fd5c2d83SStefano Zampini   if (array) PetscAssertPointer(array, 2);
2368cd3f9d89SJunchao Zhang   PetscCall(PetscObjectBaseTypeCompare((PetscObject)A, MATMPIDENSE, &isMPI));
2369cd3f9d89SJunchao Zhang   if (isMPI) {
2370cd3f9d89SJunchao Zhang     PetscCall(MatDenseRestoreArrayAndMemType(((Mat_MPIDense *)A->data)->A, array));
2371cd3f9d89SJunchao Zhang   } else {
2372cd3f9d89SJunchao Zhang     PetscErrorCode (*fptr)(Mat, PetscScalar **);
23733ba16761SJacob Faibussowitsch 
23743ba16761SJacob Faibussowitsch     PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatDenseRestoreArrayAndMemType_C", &fptr));
2375cd3f9d89SJunchao Zhang     if (fptr) {
2376cd3f9d89SJunchao Zhang       PetscCall((*fptr)(A, array));
2377cd3f9d89SJunchao Zhang     } else {
2378cd3f9d89SJunchao Zhang       PetscUseMethod(A, "MatDenseRestoreArray_C", (Mat, PetscScalar **), (A, array));
2379cd3f9d89SJunchao Zhang     }
2380fd5c2d83SStefano Zampini     if (array) *array = NULL;
2381cd3f9d89SJunchao Zhang   }
2382cd3f9d89SJunchao Zhang   PetscCall(PetscObjectStateIncrease((PetscObject)A));
23833ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2384cd3f9d89SJunchao Zhang }
2385cd3f9d89SJunchao Zhang 
2386cd3f9d89SJunchao Zhang /*@C
2387cd3f9d89SJunchao Zhang   MatDenseGetArrayReadAndMemType - gives read-only access to the array where the data for a `MATDENSE` matrix is stored
2388cd3f9d89SJunchao Zhang 
2389cd3f9d89SJunchao Zhang   Logically Collective
2390cd3f9d89SJunchao Zhang 
2391cd3f9d89SJunchao Zhang   Input Parameter:
2392fe59aa6dSJacob Faibussowitsch . A - a dense matrix
2393cd3f9d89SJunchao Zhang 
2394cd3f9d89SJunchao Zhang   Output Parameters:
2395cd3f9d89SJunchao Zhang + array - pointer to the data
2396cd3f9d89SJunchao Zhang - mtype - memory type of the returned pointer
2397cd3f9d89SJunchao Zhang 
2398cd3f9d89SJunchao Zhang   Level: intermediate
2399cd3f9d89SJunchao Zhang 
2400fb850c59SBarry Smith   Note:
24012ef1f0ffSBarry Smith   If the matrix is of a device type such as `MATDENSECUDA`, `MATDENSEHIP`, etc.,
24022ef1f0ffSBarry Smith   an array on device is always returned and is guaranteed to contain the matrix's latest data.
24032ef1f0ffSBarry Smith 
24041cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATDENSE`, `MatDenseRestoreArrayReadAndMemType()`, `MatDenseGetArrayWriteAndMemType()`,
2405cd3f9d89SJunchao Zhang    `MatDenseGetArrayRead()`, `MatDenseRestoreArrayRead()`, `MatDenseGetArrayWrite()`, `MatDenseRestoreArrayWrite()`, `MatSeqAIJGetCSRAndMemType()`
2406cd3f9d89SJunchao Zhang @*/
24075d83a8b1SBarry Smith PetscErrorCode MatDenseGetArrayReadAndMemType(Mat A, const PetscScalar *array[], PetscMemType *mtype)
2408cd3f9d89SJunchao Zhang {
2409cd3f9d89SJunchao Zhang   PetscBool isMPI;
2410cd3f9d89SJunchao Zhang 
2411cd3f9d89SJunchao Zhang   PetscFunctionBegin;
2412cd3f9d89SJunchao Zhang   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
24134f572ea9SToby Isaac   PetscAssertPointer(array, 2);
2414e865de01SJunchao 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 */
2415cd3f9d89SJunchao Zhang   PetscCall(PetscObjectBaseTypeCompare((PetscObject)A, MATMPIDENSE, &isMPI));
2416cd3f9d89SJunchao Zhang   if (isMPI) { /* Dispatch here so that the code can be reused for all subclasses of MATDENSE */
2417cd3f9d89SJunchao Zhang     PetscCall(MatDenseGetArrayReadAndMemType(((Mat_MPIDense *)A->data)->A, array, mtype));
2418cd3f9d89SJunchao Zhang   } else {
2419cd3f9d89SJunchao Zhang     PetscErrorCode (*fptr)(Mat, const PetscScalar **, PetscMemType *);
24203ba16761SJacob Faibussowitsch 
24213ba16761SJacob Faibussowitsch     PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatDenseGetArrayReadAndMemType_C", &fptr));
2422cd3f9d89SJunchao Zhang     if (fptr) {
2423cd3f9d89SJunchao Zhang       PetscCall((*fptr)(A, array, mtype));
2424cd3f9d89SJunchao Zhang     } else {
24255c0db29aSPierre Jolivet       PetscUseMethod(A, "MatDenseGetArrayRead_C", (Mat, PetscScalar **), (A, (PetscScalar **)array));
2426cd3f9d89SJunchao Zhang       if (mtype) *mtype = PETSC_MEMTYPE_HOST;
2427cd3f9d89SJunchao Zhang     }
2428cd3f9d89SJunchao Zhang   }
24293ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2430cd3f9d89SJunchao Zhang }
2431cd3f9d89SJunchao Zhang 
2432cd3f9d89SJunchao Zhang /*@C
2433cd3f9d89SJunchao Zhang   MatDenseRestoreArrayReadAndMemType - returns access to the array that is obtained by `MatDenseGetArrayReadAndMemType()`
2434cd3f9d89SJunchao Zhang 
2435cd3f9d89SJunchao Zhang   Logically Collective
2436cd3f9d89SJunchao Zhang 
2437cd3f9d89SJunchao Zhang   Input Parameters:
2438fe59aa6dSJacob Faibussowitsch + A     - a dense matrix
2439cd3f9d89SJunchao Zhang - array - pointer to the data
2440cd3f9d89SJunchao Zhang 
2441cd3f9d89SJunchao Zhang   Level: intermediate
2442cd3f9d89SJunchao Zhang 
24431cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATDENSE`, `MatDenseGetArrayReadAndMemType()`, `MatDenseGetArray()`, `MatDenseGetArrayRead()`, `MatDenseRestoreArrayRead()`, `MatDenseGetArrayWrite()`, `MatDenseRestoreArrayWrite()`
2444cd3f9d89SJunchao Zhang @*/
24455d83a8b1SBarry Smith PetscErrorCode MatDenseRestoreArrayReadAndMemType(Mat A, const PetscScalar *array[])
2446cd3f9d89SJunchao Zhang {
2447cd3f9d89SJunchao Zhang   PetscBool isMPI;
2448cd3f9d89SJunchao Zhang 
2449cd3f9d89SJunchao Zhang   PetscFunctionBegin;
2450cd3f9d89SJunchao Zhang   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
2451fd5c2d83SStefano Zampini   if (array) PetscAssertPointer(array, 2);
2452cd3f9d89SJunchao Zhang   PetscCall(PetscObjectBaseTypeCompare((PetscObject)A, MATMPIDENSE, &isMPI));
2453cd3f9d89SJunchao Zhang   if (isMPI) {
2454cd3f9d89SJunchao Zhang     PetscCall(MatDenseRestoreArrayReadAndMemType(((Mat_MPIDense *)A->data)->A, array));
2455cd3f9d89SJunchao Zhang   } else {
2456cd3f9d89SJunchao Zhang     PetscErrorCode (*fptr)(Mat, const PetscScalar **);
24573ba16761SJacob Faibussowitsch 
24583ba16761SJacob Faibussowitsch     PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatDenseRestoreArrayReadAndMemType_C", &fptr));
2459cd3f9d89SJunchao Zhang     if (fptr) {
2460cd3f9d89SJunchao Zhang       PetscCall((*fptr)(A, array));
2461cd3f9d89SJunchao Zhang     } else {
24625c0db29aSPierre Jolivet       PetscUseMethod(A, "MatDenseRestoreArrayRead_C", (Mat, PetscScalar **), (A, (PetscScalar **)array));
2463cd3f9d89SJunchao Zhang     }
2464fd5c2d83SStefano Zampini     if (array) *array = NULL;
2465cd3f9d89SJunchao Zhang   }
24663ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2467cd3f9d89SJunchao Zhang }
2468cd3f9d89SJunchao Zhang 
2469cd3f9d89SJunchao Zhang /*@C
2470cd3f9d89SJunchao Zhang   MatDenseGetArrayWriteAndMemType - gives write-only access to the array where the data for a `MATDENSE` matrix is stored
2471cd3f9d89SJunchao Zhang 
2472cd3f9d89SJunchao Zhang   Logically Collective
2473cd3f9d89SJunchao Zhang 
2474cd3f9d89SJunchao Zhang   Input Parameter:
2475fe59aa6dSJacob Faibussowitsch . A - a dense matrix
2476cd3f9d89SJunchao Zhang 
2477cd3f9d89SJunchao Zhang   Output Parameters:
2478cd3f9d89SJunchao Zhang + array - pointer to the data
2479cd3f9d89SJunchao Zhang - mtype - memory type of the returned pointer
2480cd3f9d89SJunchao Zhang 
2481cd3f9d89SJunchao Zhang   Level: intermediate
2482cd3f9d89SJunchao Zhang 
2483fb850c59SBarry Smith   Note:
24842ef1f0ffSBarry Smith   If the matrix is of a device type such as `MATDENSECUDA`, `MATDENSEHIP`, etc.,
24852ef1f0ffSBarry Smith   an array on device is always returned and is guaranteed to contain the matrix's latest data.
24862ef1f0ffSBarry Smith 
24871cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATDENSE`, `MatDenseRestoreArrayWriteAndMemType()`, `MatDenseGetArrayReadAndMemType()`, `MatDenseGetArrayRead()`,
2488cd3f9d89SJunchao Zhang   `MatDenseRestoreArrayRead()`, `MatDenseGetArrayWrite()`, `MatDenseRestoreArrayWrite()`, `MatSeqAIJGetCSRAndMemType()`
2489cd3f9d89SJunchao Zhang @*/
24905d83a8b1SBarry Smith PetscErrorCode MatDenseGetArrayWriteAndMemType(Mat A, PetscScalar *array[], PetscMemType *mtype)
2491cd3f9d89SJunchao Zhang {
2492cd3f9d89SJunchao Zhang   PetscBool isMPI;
2493cd3f9d89SJunchao Zhang 
2494cd3f9d89SJunchao Zhang   PetscFunctionBegin;
2495cd3f9d89SJunchao Zhang   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
24964f572ea9SToby Isaac   PetscAssertPointer(array, 2);
2497e865de01SJunchao 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 */
2498cd3f9d89SJunchao Zhang   PetscCall(PetscObjectBaseTypeCompare((PetscObject)A, MATMPIDENSE, &isMPI));
2499cd3f9d89SJunchao Zhang   if (isMPI) {
2500cd3f9d89SJunchao Zhang     PetscCall(MatDenseGetArrayWriteAndMemType(((Mat_MPIDense *)A->data)->A, array, mtype));
2501cd3f9d89SJunchao Zhang   } else {
2502cd3f9d89SJunchao Zhang     PetscErrorCode (*fptr)(Mat, PetscScalar **, PetscMemType *);
25033ba16761SJacob Faibussowitsch 
25043ba16761SJacob Faibussowitsch     PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatDenseGetArrayWriteAndMemType_C", &fptr));
2505cd3f9d89SJunchao Zhang     if (fptr) {
2506cd3f9d89SJunchao Zhang       PetscCall((*fptr)(A, array, mtype));
2507cd3f9d89SJunchao Zhang     } else {
2508cd3f9d89SJunchao Zhang       PetscUseMethod(A, "MatDenseGetArrayWrite_C", (Mat, PetscScalar **), (A, array));
2509cd3f9d89SJunchao Zhang       if (mtype) *mtype = PETSC_MEMTYPE_HOST;
2510cd3f9d89SJunchao Zhang     }
2511cd3f9d89SJunchao Zhang   }
25123ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2513cd3f9d89SJunchao Zhang }
2514cd3f9d89SJunchao Zhang 
2515cd3f9d89SJunchao Zhang /*@C
2516cd3f9d89SJunchao Zhang   MatDenseRestoreArrayWriteAndMemType - returns access to the array that is obtained by `MatDenseGetArrayReadAndMemType()`
2517cd3f9d89SJunchao Zhang 
2518cd3f9d89SJunchao Zhang   Logically Collective
2519cd3f9d89SJunchao Zhang 
2520cd3f9d89SJunchao Zhang   Input Parameters:
2521fe59aa6dSJacob Faibussowitsch + A     - a dense matrix
2522cd3f9d89SJunchao Zhang - array - pointer to the data
2523cd3f9d89SJunchao Zhang 
2524cd3f9d89SJunchao Zhang   Level: intermediate
2525cd3f9d89SJunchao Zhang 
25261cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATDENSE`, `MatDenseGetArrayWriteAndMemType()`, `MatDenseGetArray()`, `MatDenseGetArrayRead()`, `MatDenseRestoreArrayRead()`, `MatDenseGetArrayWrite()`, `MatDenseRestoreArrayWrite()`
2527cd3f9d89SJunchao Zhang @*/
25285d83a8b1SBarry Smith PetscErrorCode MatDenseRestoreArrayWriteAndMemType(Mat A, PetscScalar *array[])
2529cd3f9d89SJunchao Zhang {
2530cd3f9d89SJunchao Zhang   PetscBool isMPI;
2531cd3f9d89SJunchao Zhang 
2532cd3f9d89SJunchao Zhang   PetscFunctionBegin;
2533cd3f9d89SJunchao Zhang   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
2534fd5c2d83SStefano Zampini   if (array) PetscAssertPointer(array, 2);
2535cd3f9d89SJunchao Zhang   PetscCall(PetscObjectBaseTypeCompare((PetscObject)A, MATMPIDENSE, &isMPI));
2536cd3f9d89SJunchao Zhang   if (isMPI) {
2537cd3f9d89SJunchao Zhang     PetscCall(MatDenseRestoreArrayWriteAndMemType(((Mat_MPIDense *)A->data)->A, array));
2538cd3f9d89SJunchao Zhang   } else {
2539cd3f9d89SJunchao Zhang     PetscErrorCode (*fptr)(Mat, PetscScalar **);
25403ba16761SJacob Faibussowitsch 
25413ba16761SJacob Faibussowitsch     PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatDenseRestoreArrayWriteAndMemType_C", &fptr));
2542cd3f9d89SJunchao Zhang     if (fptr) {
2543cd3f9d89SJunchao Zhang       PetscCall((*fptr)(A, array));
2544cd3f9d89SJunchao Zhang     } else {
2545cd3f9d89SJunchao Zhang       PetscUseMethod(A, "MatDenseRestoreArrayWrite_C", (Mat, PetscScalar **), (A, array));
2546cd3f9d89SJunchao Zhang     }
2547fd5c2d83SStefano Zampini     if (array) *array = NULL;
2548cd3f9d89SJunchao Zhang   }
2549cd3f9d89SJunchao Zhang   PetscCall(PetscObjectStateIncrease((PetscObject)A));
25503ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2551cd3f9d89SJunchao Zhang }
2552cd3f9d89SJunchao Zhang 
2553d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatCreateSubMatrix_SeqDense(Mat A, IS isrow, IS iscol, MatReuse scall, Mat *B)
2554d71ae5a4SJacob Faibussowitsch {
2555c0bbcb79SLois Curfman McInnes   Mat_SeqDense   *mat = (Mat_SeqDense *)A->data;
2556bf5a80bcSToby Isaac   PetscInt        i, j, nrows, ncols, ldb;
25575d0c19d7SBarry Smith   const PetscInt *irow, *icol;
255887828ca2SBarry Smith   PetscScalar    *av, *bv, *v = mat->v;
25590754003eSLois Curfman McInnes   Mat             newmat;
25600754003eSLois Curfman McInnes 
25613a40ed3dSBarry Smith   PetscFunctionBegin;
25629566063dSJacob Faibussowitsch   PetscCall(ISGetIndices(isrow, &irow));
25639566063dSJacob Faibussowitsch   PetscCall(ISGetIndices(iscol, &icol));
25649566063dSJacob Faibussowitsch   PetscCall(ISGetLocalSize(isrow, &nrows));
25659566063dSJacob Faibussowitsch   PetscCall(ISGetLocalSize(iscol, &ncols));
25660754003eSLois Curfman McInnes 
2567182d2002SSatish Balay   /* Check submatrixcall */
2568182d2002SSatish Balay   if (scall == MAT_REUSE_MATRIX) {
256913f74950SBarry Smith     PetscInt n_cols, n_rows;
25709566063dSJacob Faibussowitsch     PetscCall(MatGetSize(*B, &n_rows, &n_cols));
257121a2c019SBarry Smith     if (n_rows != nrows || n_cols != ncols) {
2572f746d493SDmitry Karpeev       /* resize the result matrix to match number of requested rows/columns */
25739566063dSJacob Faibussowitsch       PetscCall(MatSetSizes(*B, nrows, ncols, nrows, ncols));
257421a2c019SBarry Smith     }
2575182d2002SSatish Balay     newmat = *B;
2576182d2002SSatish Balay   } else {
25770754003eSLois Curfman McInnes     /* Create and fill new matrix */
25789566063dSJacob Faibussowitsch     PetscCall(MatCreate(PetscObjectComm((PetscObject)A), &newmat));
25799566063dSJacob Faibussowitsch     PetscCall(MatSetSizes(newmat, nrows, ncols, nrows, ncols));
25809566063dSJacob Faibussowitsch     PetscCall(MatSetType(newmat, ((PetscObject)A)->type_name));
25819566063dSJacob Faibussowitsch     PetscCall(MatSeqDenseSetPreallocation(newmat, NULL));
2582182d2002SSatish Balay   }
2583182d2002SSatish Balay 
2584182d2002SSatish Balay   /* Now extract the data pointers and do the copy,column at a time */
25859566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArray(newmat, &bv));
25869566063dSJacob Faibussowitsch   PetscCall(MatDenseGetLDA(newmat, &ldb));
2587182d2002SSatish Balay   for (i = 0; i < ncols; i++) {
25886de62eeeSBarry Smith     av = v + mat->lda * icol[i];
2589ca15aa20SStefano Zampini     for (j = 0; j < nrows; j++) bv[j] = av[irow[j]];
2590bf5a80bcSToby Isaac     bv += ldb;
25910754003eSLois Curfman McInnes   }
25929566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArray(newmat, &bv));
2593182d2002SSatish Balay 
2594182d2002SSatish Balay   /* Assemble the matrices so that the correct flags are set */
25959566063dSJacob Faibussowitsch   PetscCall(MatAssemblyBegin(newmat, MAT_FINAL_ASSEMBLY));
25969566063dSJacob Faibussowitsch   PetscCall(MatAssemblyEnd(newmat, MAT_FINAL_ASSEMBLY));
25970754003eSLois Curfman McInnes 
25980754003eSLois Curfman McInnes   /* Free work space */
25999566063dSJacob Faibussowitsch   PetscCall(ISRestoreIndices(isrow, &irow));
26009566063dSJacob Faibussowitsch   PetscCall(ISRestoreIndices(iscol, &icol));
2601182d2002SSatish Balay   *B = newmat;
26023ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
26030754003eSLois Curfman McInnes }
26040754003eSLois Curfman McInnes 
2605d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatCreateSubMatrices_SeqDense(Mat A, PetscInt n, const IS irow[], const IS icol[], MatReuse scall, Mat *B[])
2606d71ae5a4SJacob Faibussowitsch {
260713f74950SBarry Smith   PetscInt i;
2608905e6a2fSBarry Smith 
26093a40ed3dSBarry Smith   PetscFunctionBegin;
261048a46eb9SPierre Jolivet   if (scall == MAT_INITIAL_MATRIX) PetscCall(PetscCalloc1(n, B));
2611905e6a2fSBarry Smith 
261248a46eb9SPierre Jolivet   for (i = 0; i < n; i++) PetscCall(MatCreateSubMatrix_SeqDense(A, irow[i], icol[i], scall, &(*B)[i]));
26133ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2614905e6a2fSBarry Smith }
2615905e6a2fSBarry Smith 
2616d71ae5a4SJacob Faibussowitsch PetscErrorCode MatCopy_SeqDense(Mat A, Mat B, MatStructure str)
2617d71ae5a4SJacob Faibussowitsch {
26184b0e389bSBarry Smith   Mat_SeqDense      *a = (Mat_SeqDense *)A->data, *b = (Mat_SeqDense *)B->data;
2619ca15aa20SStefano Zampini   const PetscScalar *va;
2620ca15aa20SStefano Zampini   PetscScalar       *vb;
2621d0f46423SBarry Smith   PetscInt           lda1 = a->lda, lda2 = b->lda, m = A->rmap->n, n = A->cmap->n, j;
26223a40ed3dSBarry Smith 
26233a40ed3dSBarry Smith   PetscFunctionBegin;
262433f4a19fSKris Buschelman   /* If the two matrices don't have the same copy implementation, they aren't compatible for fast copy. */
262533f4a19fSKris Buschelman   if (A->ops->copy != B->ops->copy) {
26269566063dSJacob Faibussowitsch     PetscCall(MatCopy_Basic(A, B, str));
26273ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
26283a40ed3dSBarry Smith   }
2629aed4548fSBarry Smith   PetscCheck(m == B->rmap->n && n == B->cmap->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "size(B) != size(A)");
26309566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArrayRead(A, &va));
26319566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArray(B, &vb));
2632a5ce6ee0Svictorle   if (lda1 > m || lda2 > m) {
263348a46eb9SPierre Jolivet     for (j = 0; j < n; j++) PetscCall(PetscArraycpy(vb + j * lda2, va + j * lda1, m));
2634a5ce6ee0Svictorle   } else {
26359566063dSJacob Faibussowitsch     PetscCall(PetscArraycpy(vb, va, A->rmap->n * A->cmap->n));
2636a5ce6ee0Svictorle   }
26379566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArray(B, &vb));
26389566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArrayRead(A, &va));
26399566063dSJacob Faibussowitsch   PetscCall(MatAssemblyBegin(B, MAT_FINAL_ASSEMBLY));
26409566063dSJacob Faibussowitsch   PetscCall(MatAssemblyEnd(B, MAT_FINAL_ASSEMBLY));
26413ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2642273d9f13SBarry Smith }
2643273d9f13SBarry Smith 
2644d71ae5a4SJacob Faibussowitsch PetscErrorCode MatSetUp_SeqDense(Mat A)
2645d71ae5a4SJacob Faibussowitsch {
2646273d9f13SBarry Smith   PetscFunctionBegin;
26479566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetUp(A->rmap));
26489566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetUp(A->cmap));
264948a46eb9SPierre Jolivet   if (!A->preallocated) PetscCall(MatSeqDenseSetPreallocation(A, NULL));
26503ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
26514b0e389bSBarry Smith }
26524b0e389bSBarry Smith 
26533853def2SToby Isaac PetscErrorCode MatConjugate_SeqDense(Mat A)
2654d71ae5a4SJacob Faibussowitsch {
26554396437dSToby Isaac   Mat_SeqDense *mat = (Mat_SeqDense *)A->data;
265606c5243aSJose E. Roman   PetscInt      i, j;
26574396437dSToby Isaac   PetscInt      min = PetscMin(A->rmap->n, A->cmap->n);
2658ca15aa20SStefano Zampini   PetscScalar  *aa;
2659ba337c44SJed Brown 
2660ba337c44SJed Brown   PetscFunctionBegin;
26619566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArray(A, &aa));
266206c5243aSJose E. Roman   for (j = 0; j < A->cmap->n; j++) {
266306c5243aSJose E. Roman     for (i = 0; i < A->rmap->n; i++) aa[i + j * mat->lda] = PetscConj(aa[i + j * mat->lda]);
266406c5243aSJose E. Roman   }
26659566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArray(A, &aa));
26669371c9d4SSatish Balay   if (mat->tau)
26679371c9d4SSatish Balay     for (i = 0; i < min; i++) mat->tau[i] = PetscConj(mat->tau[i]);
26683ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2669ba337c44SJed Brown }
2670ba337c44SJed Brown 
2671d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatRealPart_SeqDense(Mat A)
2672d71ae5a4SJacob Faibussowitsch {
267306c5243aSJose E. Roman   Mat_SeqDense *mat = (Mat_SeqDense *)A->data;
267406c5243aSJose E. Roman   PetscInt      i, j;
2675ca15aa20SStefano Zampini   PetscScalar  *aa;
2676ba337c44SJed Brown 
2677ba337c44SJed Brown   PetscFunctionBegin;
26789566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArray(A, &aa));
267906c5243aSJose E. Roman   for (j = 0; j < A->cmap->n; j++) {
268006c5243aSJose E. Roman     for (i = 0; i < A->rmap->n; i++) aa[i + j * mat->lda] = PetscRealPart(aa[i + j * mat->lda]);
268106c5243aSJose E. Roman   }
26829566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArray(A, &aa));
26833ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2684ba337c44SJed Brown }
2685ba337c44SJed Brown 
2686d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatImaginaryPart_SeqDense(Mat A)
2687d71ae5a4SJacob Faibussowitsch {
268806c5243aSJose E. Roman   Mat_SeqDense *mat = (Mat_SeqDense *)A->data;
268906c5243aSJose E. Roman   PetscInt      i, j;
2690ca15aa20SStefano Zampini   PetscScalar  *aa;
2691ba337c44SJed Brown 
2692ba337c44SJed Brown   PetscFunctionBegin;
26939566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArray(A, &aa));
269406c5243aSJose E. Roman   for (j = 0; j < A->cmap->n; j++) {
269506c5243aSJose E. Roman     for (i = 0; i < A->rmap->n; i++) aa[i + j * mat->lda] = PetscImaginaryPart(aa[i + j * mat->lda]);
269606c5243aSJose E. Roman   }
26979566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArray(A, &aa));
26983ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2699ba337c44SJed Brown }
2700284134d9SBarry Smith 
2701d71ae5a4SJacob Faibussowitsch PetscErrorCode MatMatMultSymbolic_SeqDense_SeqDense(Mat A, Mat B, PetscReal fill, Mat C)
2702d71ae5a4SJacob Faibussowitsch {
2703d0f46423SBarry Smith   PetscInt  m = A->rmap->n, n = B->cmap->n;
270447d993e7Ssuyashtn   PetscBool cisdense = PETSC_FALSE;
2705a9fe9ddaSSatish Balay 
2706ee16a9a1SHong Zhang   PetscFunctionBegin;
27079566063dSJacob Faibussowitsch   PetscCall(MatSetSizes(C, m, n, m, n));
270847d993e7Ssuyashtn #if defined(PETSC_HAVE_CUDA)
27099566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompareAny((PetscObject)C, &cisdense, MATSEQDENSE, MATSEQDENSECUDA, ""));
271047d993e7Ssuyashtn #endif
271147d993e7Ssuyashtn #if defined(PETSC_HAVE_HIP)
271247d993e7Ssuyashtn   PetscCall(PetscObjectTypeCompareAny((PetscObject)C, &cisdense, MATSEQDENSE, MATSEQDENSEHIP, ""));
271347d993e7Ssuyashtn #endif
27147a3c3d58SStefano Zampini   if (!cisdense) {
27157a3c3d58SStefano Zampini     PetscBool flg;
27167a3c3d58SStefano Zampini 
27179566063dSJacob Faibussowitsch     PetscCall(PetscObjectTypeCompare((PetscObject)B, ((PetscObject)A)->type_name, &flg));
27189566063dSJacob Faibussowitsch     PetscCall(MatSetType(C, flg ? ((PetscObject)A)->type_name : MATDENSE));
27197a3c3d58SStefano Zampini   }
27209566063dSJacob Faibussowitsch   PetscCall(MatSetUp(C));
27213ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2722ee16a9a1SHong Zhang }
2723a9fe9ddaSSatish Balay 
2724d71ae5a4SJacob Faibussowitsch PetscErrorCode MatMatMultNumeric_SeqDense_SeqDense(Mat A, Mat B, Mat C)
2725d71ae5a4SJacob Faibussowitsch {
27266718818eSStefano Zampini   Mat_SeqDense      *a = (Mat_SeqDense *)A->data, *b = (Mat_SeqDense *)B->data, *c = (Mat_SeqDense *)C->data;
27270805154bSBarry Smith   PetscBLASInt       m, n, k;
2728ca15aa20SStefano Zampini   const PetscScalar *av, *bv;
2729ca15aa20SStefano Zampini   PetscScalar       *cv;
2730a9fe9ddaSSatish Balay   PetscScalar        _DOne = 1.0, _DZero = 0.0;
2731a9fe9ddaSSatish Balay 
2732a9fe9ddaSSatish Balay   PetscFunctionBegin;
27339566063dSJacob Faibussowitsch   PetscCall(PetscBLASIntCast(C->rmap->n, &m));
27349566063dSJacob Faibussowitsch   PetscCall(PetscBLASIntCast(C->cmap->n, &n));
27359566063dSJacob Faibussowitsch   PetscCall(PetscBLASIntCast(A->cmap->n, &k));
27363ba16761SJacob Faibussowitsch   if (!m || !n || !k) PetscFunctionReturn(PETSC_SUCCESS);
27379566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArrayRead(A, &av));
27389566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArrayRead(B, &bv));
27399566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArrayWrite(C, &cv));
2740792fecdfSBarry Smith   PetscCallBLAS("BLASgemm", BLASgemm_("N", "N", &m, &n, &k, &_DOne, av, &a->lda, bv, &b->lda, &_DZero, cv, &c->lda));
27419566063dSJacob Faibussowitsch   PetscCall(PetscLogFlops(1.0 * m * n * k + 1.0 * m * n * (k - 1)));
27429566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArrayRead(A, &av));
27439566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArrayRead(B, &bv));
27449566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArrayWrite(C, &cv));
27453ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2746a9fe9ddaSSatish Balay }
2747a9fe9ddaSSatish Balay 
2748d71ae5a4SJacob Faibussowitsch PetscErrorCode MatMatTransposeMultSymbolic_SeqDense_SeqDense(Mat A, Mat B, PetscReal fill, Mat C)
2749d71ae5a4SJacob Faibussowitsch {
275069f65d41SStefano Zampini   PetscInt  m = A->rmap->n, n = B->rmap->n;
275147d993e7Ssuyashtn   PetscBool cisdense = PETSC_FALSE;
275269f65d41SStefano Zampini 
275369f65d41SStefano Zampini   PetscFunctionBegin;
27549566063dSJacob Faibussowitsch   PetscCall(MatSetSizes(C, m, n, m, n));
275547d993e7Ssuyashtn #if defined(PETSC_HAVE_CUDA)
27569566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompareAny((PetscObject)C, &cisdense, MATSEQDENSE, MATSEQDENSECUDA, ""));
275747d993e7Ssuyashtn #endif
275847d993e7Ssuyashtn #if defined(PETSC_HAVE_HIP)
275947d993e7Ssuyashtn   PetscCall(PetscObjectTypeCompareAny((PetscObject)C, &cisdense, MATSEQDENSE, MATSEQDENSEHIP, ""));
276047d993e7Ssuyashtn #endif
27617a3c3d58SStefano Zampini   if (!cisdense) {
27627a3c3d58SStefano Zampini     PetscBool flg;
27637a3c3d58SStefano Zampini 
27649566063dSJacob Faibussowitsch     PetscCall(PetscObjectTypeCompare((PetscObject)B, ((PetscObject)A)->type_name, &flg));
27659566063dSJacob Faibussowitsch     PetscCall(MatSetType(C, flg ? ((PetscObject)A)->type_name : MATDENSE));
27667a3c3d58SStefano Zampini   }
27679566063dSJacob Faibussowitsch   PetscCall(MatSetUp(C));
27683ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
276969f65d41SStefano Zampini }
277069f65d41SStefano Zampini 
2771d71ae5a4SJacob Faibussowitsch PetscErrorCode MatMatTransposeMultNumeric_SeqDense_SeqDense(Mat A, Mat B, Mat C)
2772d71ae5a4SJacob Faibussowitsch {
277369f65d41SStefano Zampini   Mat_SeqDense      *a = (Mat_SeqDense *)A->data;
277469f65d41SStefano Zampini   Mat_SeqDense      *b = (Mat_SeqDense *)B->data;
277569f65d41SStefano Zampini   Mat_SeqDense      *c = (Mat_SeqDense *)C->data;
27766718818eSStefano Zampini   const PetscScalar *av, *bv;
27776718818eSStefano Zampini   PetscScalar       *cv;
277869f65d41SStefano Zampini   PetscBLASInt       m, n, k;
277969f65d41SStefano Zampini   PetscScalar        _DOne = 1.0, _DZero = 0.0;
278069f65d41SStefano Zampini 
278169f65d41SStefano Zampini   PetscFunctionBegin;
27829566063dSJacob Faibussowitsch   PetscCall(PetscBLASIntCast(C->rmap->n, &m));
27839566063dSJacob Faibussowitsch   PetscCall(PetscBLASIntCast(C->cmap->n, &n));
27849566063dSJacob Faibussowitsch   PetscCall(PetscBLASIntCast(A->cmap->n, &k));
27853ba16761SJacob Faibussowitsch   if (!m || !n || !k) PetscFunctionReturn(PETSC_SUCCESS);
27869566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArrayRead(A, &av));
27879566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArrayRead(B, &bv));
27889566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArrayWrite(C, &cv));
2789792fecdfSBarry Smith   PetscCallBLAS("BLASgemm", BLASgemm_("N", "T", &m, &n, &k, &_DOne, av, &a->lda, bv, &b->lda, &_DZero, cv, &c->lda));
27909566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArrayRead(A, &av));
27919566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArrayRead(B, &bv));
27929566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArrayWrite(C, &cv));
27939566063dSJacob Faibussowitsch   PetscCall(PetscLogFlops(1.0 * m * n * k + 1.0 * m * n * (k - 1)));
27943ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
279569f65d41SStefano Zampini }
279669f65d41SStefano Zampini 
2797d71ae5a4SJacob Faibussowitsch PetscErrorCode MatTransposeMatMultSymbolic_SeqDense_SeqDense(Mat A, Mat B, PetscReal fill, Mat C)
2798d71ae5a4SJacob Faibussowitsch {
2799d0f46423SBarry Smith   PetscInt  m = A->cmap->n, n = B->cmap->n;
280047d993e7Ssuyashtn   PetscBool cisdense = PETSC_FALSE;
2801a9fe9ddaSSatish Balay 
2802ee16a9a1SHong Zhang   PetscFunctionBegin;
28039566063dSJacob Faibussowitsch   PetscCall(MatSetSizes(C, m, n, m, n));
280447d993e7Ssuyashtn #if defined(PETSC_HAVE_CUDA)
28059566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompareAny((PetscObject)C, &cisdense, MATSEQDENSE, MATSEQDENSECUDA, ""));
280647d993e7Ssuyashtn #endif
280747d993e7Ssuyashtn #if defined(PETSC_HAVE_HIP)
280847d993e7Ssuyashtn   PetscCall(PetscObjectTypeCompareAny((PetscObject)C, &cisdense, MATSEQDENSE, MATSEQDENSEHIP, ""));
280947d993e7Ssuyashtn #endif
28107a3c3d58SStefano Zampini   if (!cisdense) {
28117a3c3d58SStefano Zampini     PetscBool flg;
28127a3c3d58SStefano Zampini 
28139566063dSJacob Faibussowitsch     PetscCall(PetscObjectTypeCompare((PetscObject)B, ((PetscObject)A)->type_name, &flg));
28149566063dSJacob Faibussowitsch     PetscCall(MatSetType(C, flg ? ((PetscObject)A)->type_name : MATDENSE));
28157a3c3d58SStefano Zampini   }
28169566063dSJacob Faibussowitsch   PetscCall(MatSetUp(C));
28173ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2818ee16a9a1SHong Zhang }
2819a9fe9ddaSSatish Balay 
2820d71ae5a4SJacob Faibussowitsch PetscErrorCode MatTransposeMatMultNumeric_SeqDense_SeqDense(Mat A, Mat B, Mat C)
2821d71ae5a4SJacob Faibussowitsch {
2822a9fe9ddaSSatish Balay   Mat_SeqDense      *a = (Mat_SeqDense *)A->data;
2823a9fe9ddaSSatish Balay   Mat_SeqDense      *b = (Mat_SeqDense *)B->data;
2824a9fe9ddaSSatish Balay   Mat_SeqDense      *c = (Mat_SeqDense *)C->data;
28256718818eSStefano Zampini   const PetscScalar *av, *bv;
28266718818eSStefano Zampini   PetscScalar       *cv;
28270805154bSBarry Smith   PetscBLASInt       m, n, k;
2828a9fe9ddaSSatish Balay   PetscScalar        _DOne = 1.0, _DZero = 0.0;
2829a9fe9ddaSSatish Balay 
2830a9fe9ddaSSatish Balay   PetscFunctionBegin;
28319566063dSJacob Faibussowitsch   PetscCall(PetscBLASIntCast(C->rmap->n, &m));
28329566063dSJacob Faibussowitsch   PetscCall(PetscBLASIntCast(C->cmap->n, &n));
28339566063dSJacob Faibussowitsch   PetscCall(PetscBLASIntCast(A->rmap->n, &k));
28343ba16761SJacob Faibussowitsch   if (!m || !n || !k) PetscFunctionReturn(PETSC_SUCCESS);
28359566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArrayRead(A, &av));
28369566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArrayRead(B, &bv));
28379566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArrayWrite(C, &cv));
2838792fecdfSBarry Smith   PetscCallBLAS("BLASgemm", BLASgemm_("T", "N", &m, &n, &k, &_DOne, av, &a->lda, bv, &b->lda, &_DZero, cv, &c->lda));
28399566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArrayRead(A, &av));
28409566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArrayRead(B, &bv));
28419566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArrayWrite(C, &cv));
28429566063dSJacob Faibussowitsch   PetscCall(PetscLogFlops(1.0 * m * n * k + 1.0 * m * n * (k - 1)));
28433ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2844a9fe9ddaSSatish Balay }
2845985db425SBarry Smith 
2846d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatProductSetFromOptions_SeqDense_AB(Mat C)
2847d71ae5a4SJacob Faibussowitsch {
28484222ddf1SHong Zhang   PetscFunctionBegin;
28494222ddf1SHong Zhang   C->ops->matmultsymbolic = MatMatMultSymbolic_SeqDense_SeqDense;
28504222ddf1SHong Zhang   C->ops->productsymbolic = MatProductSymbolic_AB;
28513ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
28524222ddf1SHong Zhang }
28534222ddf1SHong Zhang 
2854d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatProductSetFromOptions_SeqDense_AtB(Mat C)
2855d71ae5a4SJacob Faibussowitsch {
28564222ddf1SHong Zhang   PetscFunctionBegin;
28574222ddf1SHong Zhang   C->ops->transposematmultsymbolic = MatTransposeMatMultSymbolic_SeqDense_SeqDense;
28584222ddf1SHong Zhang   C->ops->productsymbolic          = MatProductSymbolic_AtB;
28593ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
28604222ddf1SHong Zhang }
28614222ddf1SHong Zhang 
2862d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatProductSetFromOptions_SeqDense_ABt(Mat C)
2863d71ae5a4SJacob Faibussowitsch {
28644222ddf1SHong Zhang   PetscFunctionBegin;
28654222ddf1SHong Zhang   C->ops->mattransposemultsymbolic = MatMatTransposeMultSymbolic_SeqDense_SeqDense;
28664222ddf1SHong Zhang   C->ops->productsymbolic          = MatProductSymbolic_ABt;
28673ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
28684222ddf1SHong Zhang }
28694222ddf1SHong Zhang 
2870d71ae5a4SJacob Faibussowitsch PETSC_INTERN PetscErrorCode MatProductSetFromOptions_SeqDense(Mat C)
2871d71ae5a4SJacob Faibussowitsch {
28724222ddf1SHong Zhang   Mat_Product *product = C->product;
28734222ddf1SHong Zhang 
28744222ddf1SHong Zhang   PetscFunctionBegin;
28754222ddf1SHong Zhang   switch (product->type) {
2876d71ae5a4SJacob Faibussowitsch   case MATPRODUCT_AB:
2877d71ae5a4SJacob Faibussowitsch     PetscCall(MatProductSetFromOptions_SeqDense_AB(C));
2878d71ae5a4SJacob Faibussowitsch     break;
2879d71ae5a4SJacob Faibussowitsch   case MATPRODUCT_AtB:
2880d71ae5a4SJacob Faibussowitsch     PetscCall(MatProductSetFromOptions_SeqDense_AtB(C));
2881d71ae5a4SJacob Faibussowitsch     break;
2882d71ae5a4SJacob Faibussowitsch   case MATPRODUCT_ABt:
2883d71ae5a4SJacob Faibussowitsch     PetscCall(MatProductSetFromOptions_SeqDense_ABt(C));
2884d71ae5a4SJacob Faibussowitsch     break;
2885d71ae5a4SJacob Faibussowitsch   default:
2886d71ae5a4SJacob Faibussowitsch     break;
28874222ddf1SHong Zhang   }
28883ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
28894222ddf1SHong Zhang }
28904222ddf1SHong Zhang 
2891d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatGetRowMax_SeqDense(Mat A, Vec v, PetscInt idx[])
2892d71ae5a4SJacob Faibussowitsch {
2893985db425SBarry Smith   Mat_SeqDense      *a = (Mat_SeqDense *)A->data;
2894d0f46423SBarry Smith   PetscInt           i, j, m = A->rmap->n, n = A->cmap->n, p;
2895985db425SBarry Smith   PetscScalar       *x;
2896ca15aa20SStefano Zampini   const PetscScalar *aa;
2897985db425SBarry Smith 
2898985db425SBarry Smith   PetscFunctionBegin;
289928b400f6SJacob Faibussowitsch   PetscCheck(!A->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
29009566063dSJacob Faibussowitsch   PetscCall(VecGetArray(v, &x));
29019566063dSJacob Faibussowitsch   PetscCall(VecGetLocalSize(v, &p));
29029566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArrayRead(A, &aa));
290308401ef6SPierre Jolivet   PetscCheck(p == A->rmap->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Nonconforming matrix and vector");
2904985db425SBarry Smith   for (i = 0; i < m; i++) {
29059371c9d4SSatish Balay     x[i] = aa[i];
29069371c9d4SSatish Balay     if (idx) idx[i] = 0;
2907985db425SBarry Smith     for (j = 1; j < n; j++) {
29089371c9d4SSatish Balay       if (PetscRealPart(x[i]) < PetscRealPart(aa[i + a->lda * j])) {
29099371c9d4SSatish Balay         x[i] = aa[i + a->lda * j];
29109371c9d4SSatish Balay         if (idx) idx[i] = j;
29119371c9d4SSatish Balay       }
2912985db425SBarry Smith     }
2913985db425SBarry Smith   }
29149566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArrayRead(A, &aa));
29159566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(v, &x));
29163ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2917985db425SBarry Smith }
2918985db425SBarry Smith 
2919d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatGetRowMaxAbs_SeqDense(Mat A, Vec v, PetscInt idx[])
2920d71ae5a4SJacob Faibussowitsch {
2921985db425SBarry Smith   Mat_SeqDense      *a = (Mat_SeqDense *)A->data;
2922d0f46423SBarry Smith   PetscInt           i, j, m = A->rmap->n, n = A->cmap->n, p;
2923985db425SBarry Smith   PetscScalar       *x;
2924985db425SBarry Smith   PetscReal          atmp;
2925ca15aa20SStefano Zampini   const PetscScalar *aa;
2926985db425SBarry Smith 
2927985db425SBarry Smith   PetscFunctionBegin;
292828b400f6SJacob Faibussowitsch   PetscCheck(!A->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
29299566063dSJacob Faibussowitsch   PetscCall(VecGetArray(v, &x));
29309566063dSJacob Faibussowitsch   PetscCall(VecGetLocalSize(v, &p));
29319566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArrayRead(A, &aa));
293208401ef6SPierre Jolivet   PetscCheck(p == A->rmap->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Nonconforming matrix and vector");
2933985db425SBarry Smith   for (i = 0; i < m; i++) {
29349189402eSHong Zhang     x[i] = PetscAbsScalar(aa[i]);
2935985db425SBarry Smith     for (j = 1; j < n; j++) {
2936ca15aa20SStefano Zampini       atmp = PetscAbsScalar(aa[i + a->lda * j]);
29379371c9d4SSatish Balay       if (PetscAbsScalar(x[i]) < atmp) {
29389371c9d4SSatish Balay         x[i] = atmp;
29399371c9d4SSatish Balay         if (idx) idx[i] = j;
29409371c9d4SSatish Balay       }
2941985db425SBarry Smith     }
2942985db425SBarry Smith   }
29439566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArrayRead(A, &aa));
29449566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(v, &x));
29453ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2946985db425SBarry Smith }
2947985db425SBarry Smith 
2948d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatGetRowMin_SeqDense(Mat A, Vec v, PetscInt idx[])
2949d71ae5a4SJacob Faibussowitsch {
2950985db425SBarry Smith   Mat_SeqDense      *a = (Mat_SeqDense *)A->data;
2951d0f46423SBarry Smith   PetscInt           i, j, m = A->rmap->n, n = A->cmap->n, p;
2952985db425SBarry Smith   PetscScalar       *x;
2953ca15aa20SStefano Zampini   const PetscScalar *aa;
2954985db425SBarry Smith 
2955985db425SBarry Smith   PetscFunctionBegin;
295628b400f6SJacob Faibussowitsch   PetscCheck(!A->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
29579566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArrayRead(A, &aa));
29589566063dSJacob Faibussowitsch   PetscCall(VecGetArray(v, &x));
29599566063dSJacob Faibussowitsch   PetscCall(VecGetLocalSize(v, &p));
296008401ef6SPierre Jolivet   PetscCheck(p == A->rmap->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Nonconforming matrix and vector");
2961985db425SBarry Smith   for (i = 0; i < m; i++) {
29629371c9d4SSatish Balay     x[i] = aa[i];
29639371c9d4SSatish Balay     if (idx) idx[i] = 0;
2964985db425SBarry Smith     for (j = 1; j < n; j++) {
29659371c9d4SSatish Balay       if (PetscRealPart(x[i]) > PetscRealPart(aa[i + a->lda * j])) {
29669371c9d4SSatish Balay         x[i] = aa[i + a->lda * j];
29679371c9d4SSatish Balay         if (idx) idx[i] = j;
29689371c9d4SSatish Balay       }
2969985db425SBarry Smith     }
2970985db425SBarry Smith   }
29719566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(v, &x));
29729566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArrayRead(A, &aa));
29733ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2974985db425SBarry Smith }
2975985db425SBarry Smith 
2976d71ae5a4SJacob Faibussowitsch PetscErrorCode MatGetColumnVector_SeqDense(Mat A, Vec v, PetscInt col)
2977d71ae5a4SJacob Faibussowitsch {
29788d0534beSBarry Smith   Mat_SeqDense      *a = (Mat_SeqDense *)A->data;
29798d0534beSBarry Smith   PetscScalar       *x;
2980ca15aa20SStefano Zampini   const PetscScalar *aa;
29818d0534beSBarry Smith 
29828d0534beSBarry Smith   PetscFunctionBegin;
298328b400f6SJacob Faibussowitsch   PetscCheck(!A->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
29849566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArrayRead(A, &aa));
29859566063dSJacob Faibussowitsch   PetscCall(VecGetArray(v, &x));
29869566063dSJacob Faibussowitsch   PetscCall(PetscArraycpy(x, aa + col * a->lda, A->rmap->n));
29879566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(v, &x));
29889566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArrayRead(A, &aa));
29893ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
29908d0534beSBarry Smith }
29918d0534beSBarry Smith 
2992d71ae5a4SJacob Faibussowitsch PETSC_INTERN PetscErrorCode MatGetColumnReductions_SeqDense(Mat A, PetscInt type, PetscReal *reductions)
2993d71ae5a4SJacob Faibussowitsch {
29940716a85fSBarry Smith   PetscInt           i, j, m, n;
29951683a169SBarry Smith   const PetscScalar *a;
29960716a85fSBarry Smith 
29970716a85fSBarry Smith   PetscFunctionBegin;
29989566063dSJacob Faibussowitsch   PetscCall(MatGetSize(A, &m, &n));
29999566063dSJacob Faibussowitsch   PetscCall(PetscArrayzero(reductions, n));
30009566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArrayRead(A, &a));
3001857cbf51SRichard Tran Mills   if (type == NORM_2) {
30020716a85fSBarry Smith     for (i = 0; i < n; i++) {
3003ad540459SPierre Jolivet       for (j = 0; j < m; j++) reductions[i] += PetscAbsScalar(a[j] * a[j]);
300416cd844bSPierre Jolivet       a = PetscSafePointerPlusOffset(a, m);
30050716a85fSBarry Smith     }
3006857cbf51SRichard Tran Mills   } else if (type == NORM_1) {
30070716a85fSBarry Smith     for (i = 0; i < n; i++) {
3008ad540459SPierre Jolivet       for (j = 0; j < m; j++) reductions[i] += PetscAbsScalar(a[j]);
300916cd844bSPierre Jolivet       a = PetscSafePointerPlusOffset(a, m);
30100716a85fSBarry Smith     }
3011857cbf51SRichard Tran Mills   } else if (type == NORM_INFINITY) {
30120716a85fSBarry Smith     for (i = 0; i < n; i++) {
3013ad540459SPierre Jolivet       for (j = 0; j < m; j++) reductions[i] = PetscMax(PetscAbsScalar(a[j]), reductions[i]);
301416cd844bSPierre Jolivet       a = PetscSafePointerPlusOffset(a, m);
30150716a85fSBarry Smith     }
3016857cbf51SRichard Tran Mills   } else if (type == REDUCTION_SUM_REALPART || type == REDUCTION_MEAN_REALPART) {
3017a873a8cdSSam Reynolds     for (i = 0; i < n; i++) {
3018ad540459SPierre Jolivet       for (j = 0; j < m; j++) reductions[i] += PetscRealPart(a[j]);
301916cd844bSPierre Jolivet       a = PetscSafePointerPlusOffset(a, m);
3020a873a8cdSSam Reynolds     }
3021857cbf51SRichard Tran Mills   } else if (type == REDUCTION_SUM_IMAGINARYPART || type == REDUCTION_MEAN_IMAGINARYPART) {
3022857cbf51SRichard Tran Mills     for (i = 0; i < n; i++) {
3023ad540459SPierre Jolivet       for (j = 0; j < m; j++) reductions[i] += PetscImaginaryPart(a[j]);
302416cd844bSPierre Jolivet       a = PetscSafePointerPlusOffset(a, m);
3025857cbf51SRichard Tran Mills     }
3026857cbf51SRichard Tran Mills   } else SETERRQ(PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONG, "Unknown reduction type");
30279566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArrayRead(A, &a));
3028857cbf51SRichard Tran Mills   if (type == NORM_2) {
3029a873a8cdSSam Reynolds     for (i = 0; i < n; i++) reductions[i] = PetscSqrtReal(reductions[i]);
3030857cbf51SRichard Tran Mills   } else if (type == REDUCTION_MEAN_REALPART || type == REDUCTION_MEAN_IMAGINARYPART) {
3031a873a8cdSSam Reynolds     for (i = 0; i < n; i++) reductions[i] /= m;
30320716a85fSBarry Smith   }
30333ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
30340716a85fSBarry Smith }
30350716a85fSBarry Smith 
3036d71ae5a4SJacob Faibussowitsch PetscErrorCode MatSetRandom_SeqDense(Mat x, PetscRandom rctx)
3037d71ae5a4SJacob Faibussowitsch {
303873a71a0fSBarry Smith   PetscScalar *a;
3039637a0070SStefano Zampini   PetscInt     lda, m, n, i, j;
304073a71a0fSBarry Smith 
304173a71a0fSBarry Smith   PetscFunctionBegin;
30429566063dSJacob Faibussowitsch   PetscCall(MatGetSize(x, &m, &n));
30439566063dSJacob Faibussowitsch   PetscCall(MatDenseGetLDA(x, &lda));
30443faff063SStefano Zampini   PetscCall(MatDenseGetArrayWrite(x, &a));
3045637a0070SStefano Zampini   for (j = 0; j < n; j++) {
304648a46eb9SPierre Jolivet     for (i = 0; i < m; i++) PetscCall(PetscRandomGetValue(rctx, a + j * lda + i));
304773a71a0fSBarry Smith   }
30483faff063SStefano Zampini   PetscCall(MatDenseRestoreArrayWrite(x, &a));
30493ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
305073a71a0fSBarry Smith }
305173a71a0fSBarry Smith 
3052d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatMissingDiagonal_SeqDense(Mat A, PetscBool *missing, PetscInt *d)
3053d71ae5a4SJacob Faibussowitsch {
30543b49f96aSBarry Smith   PetscFunctionBegin;
30553b49f96aSBarry Smith   *missing = PETSC_FALSE;
30563ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
30573b49f96aSBarry Smith }
305873a71a0fSBarry Smith 
3059ca15aa20SStefano Zampini /* vals is not const */
3060d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatDenseGetColumn_SeqDense(Mat A, PetscInt col, PetscScalar **vals)
3061d71ae5a4SJacob Faibussowitsch {
306286aefd0dSHong Zhang   Mat_SeqDense *a = (Mat_SeqDense *)A->data;
3063ca15aa20SStefano Zampini   PetscScalar  *v;
306486aefd0dSHong Zhang 
306586aefd0dSHong Zhang   PetscFunctionBegin;
306628b400f6SJacob Faibussowitsch   PetscCheck(!A->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
30679566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArray(A, &v));
3068ca15aa20SStefano Zampini   *vals = v + col * a->lda;
30699566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArray(A, &v));
30703ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
307186aefd0dSHong Zhang }
307286aefd0dSHong Zhang 
3073d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatDenseRestoreColumn_SeqDense(Mat A, PetscScalar **vals)
3074d71ae5a4SJacob Faibussowitsch {
307586aefd0dSHong Zhang   PetscFunctionBegin;
3076742765d3SMatthew Knepley   if (vals) *vals = NULL; /* user cannot accidentally use the array later */
30773ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
307886aefd0dSHong Zhang }
3079abc3b08eSStefano Zampini 
3080a5ae1ecdSBarry Smith static struct _MatOps MatOps_Values = {MatSetValues_SeqDense,
3081905e6a2fSBarry Smith                                        MatGetRow_SeqDense,
3082905e6a2fSBarry Smith                                        MatRestoreRow_SeqDense,
3083905e6a2fSBarry Smith                                        MatMult_SeqDense,
308497304618SKris Buschelman                                        /*  4*/ MatMultAdd_SeqDense,
30857c922b88SBarry Smith                                        MatMultTranspose_SeqDense,
30867c922b88SBarry Smith                                        MatMultTransposeAdd_SeqDense,
3087f4259b30SLisandro Dalcin                                        NULL,
3088f4259b30SLisandro Dalcin                                        NULL,
3089f4259b30SLisandro Dalcin                                        NULL,
3090f4259b30SLisandro Dalcin                                        /* 10*/ NULL,
3091905e6a2fSBarry Smith                                        MatLUFactor_SeqDense,
3092905e6a2fSBarry Smith                                        MatCholeskyFactor_SeqDense,
309341f059aeSBarry Smith                                        MatSOR_SeqDense,
3094ec8511deSBarry Smith                                        MatTranspose_SeqDense,
309597304618SKris Buschelman                                        /* 15*/ MatGetInfo_SeqDense,
3096905e6a2fSBarry Smith                                        MatEqual_SeqDense,
3097905e6a2fSBarry Smith                                        MatGetDiagonal_SeqDense,
3098905e6a2fSBarry Smith                                        MatDiagonalScale_SeqDense,
3099905e6a2fSBarry Smith                                        MatNorm_SeqDense,
3100b7103cf4SPierre Jolivet                                        /* 20*/ NULL,
3101b7103cf4SPierre Jolivet                                        NULL,
3102905e6a2fSBarry Smith                                        MatSetOption_SeqDense,
3103905e6a2fSBarry Smith                                        MatZeroEntries_SeqDense,
3104d519adbfSMatthew Knepley                                        /* 24*/ MatZeroRows_SeqDense,
3105f4259b30SLisandro Dalcin                                        NULL,
3106f4259b30SLisandro Dalcin                                        NULL,
3107f4259b30SLisandro Dalcin                                        NULL,
3108f4259b30SLisandro Dalcin                                        NULL,
31094994cf47SJed Brown                                        /* 29*/ MatSetUp_SeqDense,
3110f4259b30SLisandro Dalcin                                        NULL,
3111f4259b30SLisandro Dalcin                                        NULL,
3112f4259b30SLisandro Dalcin                                        NULL,
3113f4259b30SLisandro Dalcin                                        NULL,
3114d519adbfSMatthew Knepley                                        /* 34*/ MatDuplicate_SeqDense,
3115f4259b30SLisandro Dalcin                                        NULL,
3116f4259b30SLisandro Dalcin                                        NULL,
3117f4259b30SLisandro Dalcin                                        NULL,
3118f4259b30SLisandro Dalcin                                        NULL,
3119d519adbfSMatthew Knepley                                        /* 39*/ MatAXPY_SeqDense,
31207dae84e0SHong Zhang                                        MatCreateSubMatrices_SeqDense,
3121f4259b30SLisandro Dalcin                                        NULL,
31224b0e389bSBarry Smith                                        MatGetValues_SeqDense,
3123a5ae1ecdSBarry Smith                                        MatCopy_SeqDense,
3124d519adbfSMatthew Knepley                                        /* 44*/ MatGetRowMax_SeqDense,
3125a5ae1ecdSBarry Smith                                        MatScale_SeqDense,
31262f605a99SJose E. Roman                                        MatShift_SeqDense,
3127f4259b30SLisandro Dalcin                                        NULL,
31283f49a652SStefano Zampini                                        MatZeroRowsColumns_SeqDense,
312973a71a0fSBarry Smith                                        /* 49*/ MatSetRandom_SeqDense,
3130f4259b30SLisandro Dalcin                                        NULL,
3131f4259b30SLisandro Dalcin                                        NULL,
3132f4259b30SLisandro Dalcin                                        NULL,
3133f4259b30SLisandro Dalcin                                        NULL,
3134f4259b30SLisandro Dalcin                                        /* 54*/ NULL,
3135f4259b30SLisandro Dalcin                                        NULL,
3136f4259b30SLisandro Dalcin                                        NULL,
3137f4259b30SLisandro Dalcin                                        NULL,
3138f4259b30SLisandro Dalcin                                        NULL,
3139023c16fcSToby Isaac                                        /* 59*/ MatCreateSubMatrix_SeqDense,
3140e03a110bSBarry Smith                                        MatDestroy_SeqDense,
3141e03a110bSBarry Smith                                        MatView_SeqDense,
3142f4259b30SLisandro Dalcin                                        NULL,
3143f4259b30SLisandro Dalcin                                        NULL,
3144f4259b30SLisandro Dalcin                                        /* 64*/ NULL,
3145f4259b30SLisandro Dalcin                                        NULL,
3146f4259b30SLisandro Dalcin                                        NULL,
3147f4259b30SLisandro Dalcin                                        NULL,
31488bb0f5c6SPierre Jolivet                                        MatGetRowMaxAbs_SeqDense,
31498bb0f5c6SPierre Jolivet                                        /* 69*/ NULL,
3150f4259b30SLisandro Dalcin                                        NULL,
3151f4259b30SLisandro Dalcin                                        NULL,
3152f4259b30SLisandro Dalcin                                        NULL,
3153f4259b30SLisandro Dalcin                                        NULL,
3154f4259b30SLisandro Dalcin                                        /* 74*/ NULL,
3155f4259b30SLisandro Dalcin                                        NULL,
3156f4259b30SLisandro Dalcin                                        NULL,
3157f4259b30SLisandro Dalcin                                        NULL,
31588bb0f5c6SPierre Jolivet                                        MatLoad_SeqDense,
31598bb0f5c6SPierre Jolivet                                        /* 79*/ MatIsSymmetric_SeqDense,
31601cbb95d3SBarry Smith                                        MatIsHermitian_SeqDense,
3161f4259b30SLisandro Dalcin                                        NULL,
3162f4259b30SLisandro Dalcin                                        NULL,
3163f4259b30SLisandro Dalcin                                        NULL,
31648bb0f5c6SPierre Jolivet                                        /* 84*/ NULL,
3165a9fe9ddaSSatish Balay                                        MatMatMultNumeric_SeqDense_SeqDense,
3166f4259b30SLisandro Dalcin                                        NULL,
3167f4259b30SLisandro Dalcin                                        NULL,
316869f65d41SStefano Zampini                                        MatMatTransposeMultNumeric_SeqDense_SeqDense,
31698bb0f5c6SPierre Jolivet                                        /* 89*/ NULL,
31708bb0f5c6SPierre Jolivet                                        MatProductSetFromOptions_SeqDense,
3171f4259b30SLisandro Dalcin                                        NULL,
3172f4259b30SLisandro Dalcin                                        NULL,
3173ba337c44SJed Brown                                        MatConjugate_SeqDense,
31748bb0f5c6SPierre Jolivet                                        /* 94*/ NULL,
3175f4259b30SLisandro Dalcin                                        NULL,
3176ba337c44SJed Brown                                        MatRealPart_SeqDense,
3177ba337c44SJed Brown                                        MatImaginaryPart_SeqDense,
3178f4259b30SLisandro Dalcin                                        NULL,
31798bb0f5c6SPierre Jolivet                                        /* 99*/ NULL,
31808bb0f5c6SPierre Jolivet                                        NULL,
31818bb0f5c6SPierre Jolivet                                        NULL,
31828bb0f5c6SPierre Jolivet                                        MatGetRowMin_SeqDense,
31838bb0f5c6SPierre Jolivet                                        MatGetColumnVector_SeqDense,
31848bb0f5c6SPierre Jolivet                                        /*104*/ MatMissingDiagonal_SeqDense,
31858bb0f5c6SPierre Jolivet                                        NULL,
31868bb0f5c6SPierre Jolivet                                        NULL,
31878bb0f5c6SPierre Jolivet                                        NULL,
3188f4259b30SLisandro Dalcin                                        NULL,
3189f4259b30SLisandro Dalcin                                        /*109*/ NULL,
3190f4259b30SLisandro Dalcin                                        NULL,
31918bb0f5c6SPierre Jolivet                                        NULL,
31928bb0f5c6SPierre Jolivet                                        MatMultHermitianTranspose_SeqDense,
31938bb0f5c6SPierre Jolivet                                        MatMultHermitianTransposeAdd_SeqDense,
3194f4259b30SLisandro Dalcin                                        /*114*/ NULL,
3195f4259b30SLisandro Dalcin                                        NULL,
31968bb0f5c6SPierre Jolivet                                        MatGetColumnReductions_SeqDense,
3197f4259b30SLisandro Dalcin                                        NULL,
3198f4259b30SLisandro Dalcin                                        NULL,
3199f4259b30SLisandro Dalcin                                        /*119*/ NULL,
3200f4259b30SLisandro Dalcin                                        NULL,
32018bb0f5c6SPierre Jolivet                                        NULL,
32028bb0f5c6SPierre Jolivet                                        MatTransposeMatMultNumeric_SeqDense_SeqDense,
3203f4259b30SLisandro Dalcin                                        NULL,
3204f4259b30SLisandro Dalcin                                        /*124*/ NULL,
32058bb0f5c6SPierre Jolivet                                        NULL,
3206f4259b30SLisandro Dalcin                                        NULL,
3207f4259b30SLisandro Dalcin                                        NULL,
3208f4259b30SLisandro Dalcin                                        NULL,
3209f4259b30SLisandro Dalcin                                        /*129*/ NULL,
3210f4259b30SLisandro Dalcin                                        NULL,
32118bb0f5c6SPierre Jolivet                                        MatCreateMPIMatConcatenateSeqMat_SeqDense,
3212f4259b30SLisandro Dalcin                                        NULL,
3213f4259b30SLisandro Dalcin                                        NULL,
3214f4259b30SLisandro Dalcin                                        /*134*/ NULL,
3215f4259b30SLisandro Dalcin                                        NULL,
3216f4259b30SLisandro Dalcin                                        NULL,
3217f4259b30SLisandro Dalcin                                        NULL,
3218f4259b30SLisandro Dalcin                                        NULL,
3219f4259b30SLisandro Dalcin                                        /*139*/ NULL,
3220f4259b30SLisandro Dalcin                                        NULL,
3221f4259b30SLisandro Dalcin                                        NULL,
322203db1824SAlex Lindsay                                        NULL,
3223dec0b466SHong Zhang                                        NULL};
322490ace30eSBarry Smith 
32255d83a8b1SBarry Smith /*@
322611a5261eSBarry Smith   MatCreateSeqDense - Creates a `MATSEQDENSE` that
3227fb850c59SBarry Smith   is stored in column major order (the usual Fortran format).
3228289bc588SBarry Smith 
3229d083f849SBarry Smith   Collective
3230db81eaa0SLois Curfman McInnes 
323120563c6bSBarry Smith   Input Parameters:
323211a5261eSBarry Smith + comm - MPI communicator, set to `PETSC_COMM_SELF`
32330c775827SLois Curfman McInnes . m    - number of rows
323418f449edSLois Curfman McInnes . n    - number of columns
32352ef1f0ffSBarry Smith - data - optional location of matrix data in column major order.  Use `NULL` for PETSc
3236dfc5480cSLois Curfman McInnes          to control all matrix memory allocation.
323720563c6bSBarry Smith 
323820563c6bSBarry Smith   Output Parameter:
323944cd7ae7SLois Curfman McInnes . A - the matrix
324020563c6bSBarry Smith 
32412ef1f0ffSBarry Smith   Level: intermediate
32422ef1f0ffSBarry Smith 
324311a5261eSBarry Smith   Note:
324418f449edSLois Curfman McInnes   The data input variable is intended primarily for Fortran programmers
324518f449edSLois Curfman McInnes   who wish to allocate their own matrix memory space.  Most users should
32462ef1f0ffSBarry Smith   set `data` = `NULL`.
324718f449edSLois Curfman McInnes 
3248fb850c59SBarry Smith   Developer Note:
3249fb850c59SBarry Smith   Many of the matrix operations for this variant use the BLAS and LAPACK routines.
3250fb850c59SBarry Smith 
32511cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATSEQDENSE`, `MatCreate()`, `MatCreateDense()`, `MatSetValues()`
325220563c6bSBarry Smith @*/
32535d83a8b1SBarry Smith PetscErrorCode MatCreateSeqDense(MPI_Comm comm, PetscInt m, PetscInt n, PetscScalar data[], Mat *A)
3254d71ae5a4SJacob Faibussowitsch {
32553a40ed3dSBarry Smith   PetscFunctionBegin;
32569566063dSJacob Faibussowitsch   PetscCall(MatCreate(comm, A));
32579566063dSJacob Faibussowitsch   PetscCall(MatSetSizes(*A, m, n, m, n));
32589566063dSJacob Faibussowitsch   PetscCall(MatSetType(*A, MATSEQDENSE));
32599566063dSJacob Faibussowitsch   PetscCall(MatSeqDenseSetPreallocation(*A, data));
32603ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3261273d9f13SBarry Smith }
3262273d9f13SBarry Smith 
32635d83a8b1SBarry Smith /*@
326411a5261eSBarry Smith   MatSeqDenseSetPreallocation - Sets the array used for storing the matrix elements of a `MATSEQDENSE` matrix
3265273d9f13SBarry Smith 
3266d083f849SBarry Smith   Collective
3267273d9f13SBarry Smith 
3268273d9f13SBarry Smith   Input Parameters:
32691c4f3114SJed Brown + B    - the matrix
32702ef1f0ffSBarry Smith - data - the array (or `NULL`)
32712ef1f0ffSBarry Smith 
32722ef1f0ffSBarry Smith   Level: intermediate
3273273d9f13SBarry Smith 
327411a5261eSBarry Smith   Note:
3275273d9f13SBarry Smith   The data input variable is intended primarily for Fortran programmers
3276273d9f13SBarry Smith   who wish to allocate their own matrix memory space.  Most users should
3277284134d9SBarry Smith   need not call this routine.
3278273d9f13SBarry Smith 
32791cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATSEQDENSE`, `MatCreate()`, `MatCreateDense()`, `MatSetValues()`, `MatDenseSetLDA()`
3280273d9f13SBarry Smith @*/
3281d71ae5a4SJacob Faibussowitsch PetscErrorCode MatSeqDenseSetPreallocation(Mat B, PetscScalar data[])
3282d71ae5a4SJacob Faibussowitsch {
3283a23d5eceSKris Buschelman   PetscFunctionBegin;
3284d5ea218eSStefano Zampini   PetscValidHeaderSpecific(B, MAT_CLASSID, 1);
3285cac4c232SBarry Smith   PetscTryMethod(B, "MatSeqDenseSetPreallocation_C", (Mat, PetscScalar[]), (B, data));
32863ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3287a23d5eceSKris Buschelman }
3288a23d5eceSKris Buschelman 
3289d71ae5a4SJacob Faibussowitsch PetscErrorCode MatSeqDenseSetPreallocation_SeqDense(Mat B, PetscScalar *data)
3290d71ae5a4SJacob Faibussowitsch {
3291ad16ce7aSStefano Zampini   Mat_SeqDense *b = (Mat_SeqDense *)B->data;
3292273d9f13SBarry Smith 
3293273d9f13SBarry Smith   PetscFunctionBegin;
329428b400f6SJacob Faibussowitsch   PetscCheck(!b->matinuse, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Need to call MatDenseRestoreSubMatrix() first");
3295273d9f13SBarry Smith   B->preallocated = PETSC_TRUE;
3296a868139aSShri Abhyankar 
32979566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetUp(B->rmap));
32989566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetUp(B->cmap));
329934ef9618SShri Abhyankar 
33006497c311SBarry Smith   if (b->lda <= 0) PetscCall(PetscBLASIntCast(B->rmap->n, &b->lda));
330186d161a7SShri Abhyankar 
33029e8f95c4SLisandro Dalcin   if (!data) { /* petsc-allocated storage */
33039566063dSJacob Faibussowitsch     if (!b->user_alloc) PetscCall(PetscFree(b->v));
33049566063dSJacob Faibussowitsch     PetscCall(PetscCalloc1((size_t)b->lda * B->cmap->n, &b->v));
33052205254eSKarl Rupp 
33069e8f95c4SLisandro Dalcin     b->user_alloc = PETSC_FALSE;
3307273d9f13SBarry Smith   } else { /* user-allocated storage */
33089566063dSJacob Faibussowitsch     if (!b->user_alloc) PetscCall(PetscFree(b->v));
3309273d9f13SBarry Smith     b->v          = data;
3310273d9f13SBarry Smith     b->user_alloc = PETSC_TRUE;
3311273d9f13SBarry Smith   }
33120450473dSBarry Smith   B->assembled = PETSC_TRUE;
33133ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3314273d9f13SBarry Smith }
3315273d9f13SBarry Smith 
331665b80a83SHong Zhang #if defined(PETSC_HAVE_ELEMENTAL)
3317d71ae5a4SJacob Faibussowitsch PETSC_INTERN PetscErrorCode MatConvert_SeqDense_Elemental(Mat A, MatType newtype, MatReuse reuse, Mat *newmat)
3318d71ae5a4SJacob Faibussowitsch {
3319d77f618aSHong Zhang   Mat                mat_elemental;
33201683a169SBarry Smith   const PetscScalar *array;
33211683a169SBarry Smith   PetscScalar       *v_colwise;
3322d77f618aSHong Zhang   PetscInt           M = A->rmap->N, N = A->cmap->N, i, j, k, *rows, *cols;
3323d77f618aSHong Zhang 
33248baccfbdSHong Zhang   PetscFunctionBegin;
33259566063dSJacob Faibussowitsch   PetscCall(PetscMalloc3(M * N, &v_colwise, M, &rows, N, &cols));
33269566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArrayRead(A, &array));
3327d77f618aSHong Zhang   /* convert column-wise array into row-wise v_colwise, see MatSetValues_Elemental() */
3328d77f618aSHong Zhang   k = 0;
3329d77f618aSHong Zhang   for (j = 0; j < N; j++) {
3330d77f618aSHong Zhang     cols[j] = j;
3331ad540459SPierre Jolivet     for (i = 0; i < M; i++) v_colwise[j * M + i] = array[k++];
3332d77f618aSHong Zhang   }
3333ad540459SPierre Jolivet   for (i = 0; i < M; i++) rows[i] = i;
33349566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArrayRead(A, &array));
3335d77f618aSHong Zhang 
33369566063dSJacob Faibussowitsch   PetscCall(MatCreate(PetscObjectComm((PetscObject)A), &mat_elemental));
33379566063dSJacob Faibussowitsch   PetscCall(MatSetSizes(mat_elemental, PETSC_DECIDE, PETSC_DECIDE, M, N));
33389566063dSJacob Faibussowitsch   PetscCall(MatSetType(mat_elemental, MATELEMENTAL));
33399566063dSJacob Faibussowitsch   PetscCall(MatSetUp(mat_elemental));
3340d77f618aSHong Zhang 
3341d77f618aSHong Zhang   /* PETSc-Elemental interaface uses axpy for setting off-processor entries, only ADD_VALUES is allowed */
33429566063dSJacob Faibussowitsch   PetscCall(MatSetValues(mat_elemental, M, rows, N, cols, v_colwise, ADD_VALUES));
33439566063dSJacob Faibussowitsch   PetscCall(MatAssemblyBegin(mat_elemental, MAT_FINAL_ASSEMBLY));
33449566063dSJacob Faibussowitsch   PetscCall(MatAssemblyEnd(mat_elemental, MAT_FINAL_ASSEMBLY));
33459566063dSJacob Faibussowitsch   PetscCall(PetscFree3(v_colwise, rows, cols));
3346d77f618aSHong Zhang 
3347511c6705SHong Zhang   if (reuse == MAT_INPLACE_MATRIX) {
33489566063dSJacob Faibussowitsch     PetscCall(MatHeaderReplace(A, &mat_elemental));
3349d77f618aSHong Zhang   } else {
3350d77f618aSHong Zhang     *newmat = mat_elemental;
3351d77f618aSHong Zhang   }
33523ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
33538baccfbdSHong Zhang }
335465b80a83SHong Zhang #endif
33558baccfbdSHong Zhang 
3356d71ae5a4SJacob Faibussowitsch PetscErrorCode MatDenseSetLDA_SeqDense(Mat B, PetscInt lda)
3357d71ae5a4SJacob Faibussowitsch {
33581b807ce4Svictorle   Mat_SeqDense *b = (Mat_SeqDense *)B->data;
33597422da62SJose E. Roman   PetscBool     data;
336021a2c019SBarry Smith 
33611b807ce4Svictorle   PetscFunctionBegin;
3362835f2295SStefano Zampini   data = (B->rmap->n > 0 && B->cmap->n > 0) ? (b->v ? PETSC_TRUE : PETSC_FALSE) : PETSC_FALSE;
3363aed4548fSBarry Smith   PetscCheck(b->user_alloc || !data || b->lda == lda, PETSC_COMM_SELF, PETSC_ERR_ORDER, "LDA cannot be changed after allocation of internal storage");
336408401ef6SPierre 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);
33656497c311SBarry Smith   PetscCall(PetscBLASIntCast(lda, &b->lda));
33663ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
33671b807ce4Svictorle }
33681b807ce4Svictorle 
3369d71ae5a4SJacob Faibussowitsch PetscErrorCode MatCreateMPIMatConcatenateSeqMat_SeqDense(MPI_Comm comm, Mat inmat, PetscInt n, MatReuse scall, Mat *outmat)
3370d71ae5a4SJacob Faibussowitsch {
3371d528f656SJakub Kruzik   PetscFunctionBegin;
33729566063dSJacob Faibussowitsch   PetscCall(MatCreateMPIMatConcatenateSeqMat_MPIDense(comm, inmat, n, scall, outmat));
33733ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3374d528f656SJakub Kruzik }
3375d528f656SJakub Kruzik 
3376d16ceb75SStefano Zampini PetscErrorCode MatDenseCreateColumnVec_Private(Mat A, Vec *v)
3377d16ceb75SStefano Zampini {
3378d16ceb75SStefano Zampini   PetscBool   isstd, iskok, iscuda, iship;
3379d16ceb75SStefano Zampini   PetscMPIInt size;
3380d16ceb75SStefano Zampini #if PetscDefined(HAVE_CUDA) || PetscDefined(HAVE_HIP)
3381d16ceb75SStefano Zampini   /* we pass the data of A, to prevent allocating needless GPU memory the first time VecCUPMPlaceArray is called. */
3382d16ceb75SStefano Zampini   const PetscScalar *a;
3383d16ceb75SStefano Zampini #endif
3384d16ceb75SStefano Zampini 
3385d16ceb75SStefano Zampini   PetscFunctionBegin;
3386d16ceb75SStefano Zampini   *v = NULL;
3387d16ceb75SStefano Zampini   PetscCall(PetscStrcmpAny(A->defaultvectype, &isstd, VECSTANDARD, VECSEQ, VECMPI, ""));
3388d16ceb75SStefano Zampini   PetscCall(PetscStrcmpAny(A->defaultvectype, &iskok, VECKOKKOS, VECSEQKOKKOS, VECMPIKOKKOS, ""));
3389d16ceb75SStefano Zampini   PetscCall(PetscStrcmpAny(A->defaultvectype, &iscuda, VECCUDA, VECSEQCUDA, VECMPICUDA, ""));
3390d16ceb75SStefano Zampini   PetscCall(PetscStrcmpAny(A->defaultvectype, &iship, VECHIP, VECSEQHIP, VECMPIHIP, ""));
3391d16ceb75SStefano Zampini   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)A), &size));
3392d16ceb75SStefano Zampini   if (isstd) {
3393d16ceb75SStefano Zampini     if (size > 1) PetscCall(VecCreateMPIWithArray(PetscObjectComm((PetscObject)A), A->rmap->bs, A->rmap->n, A->rmap->N, NULL, v));
3394d16ceb75SStefano Zampini     else PetscCall(VecCreateSeqWithArray(PetscObjectComm((PetscObject)A), A->rmap->bs, A->rmap->n, NULL, v));
3395d16ceb75SStefano Zampini   } else if (iskok) {
3396d16ceb75SStefano Zampini     PetscCheck(PetscDefined(HAVE_KOKKOS_KERNELS), PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Reconfigure using KOKKOS kernels support");
3397d16ceb75SStefano Zampini #if PetscDefined(HAVE_KOKKOS_KERNELS)
3398d16ceb75SStefano Zampini     if (size > 1) PetscCall(VecCreateMPIKokkosWithArray(PetscObjectComm((PetscObject)A), A->rmap->bs, A->rmap->n, A->rmap->N, NULL, v));
3399d16ceb75SStefano Zampini     else PetscCall(VecCreateSeqKokkosWithArray(PetscObjectComm((PetscObject)A), A->rmap->bs, A->rmap->n, NULL, v));
3400d16ceb75SStefano Zampini #endif
3401d16ceb75SStefano Zampini   } else if (iscuda) {
3402d16ceb75SStefano Zampini     PetscCheck(PetscDefined(HAVE_CUDA), PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Reconfigure using CUDA support");
3403d16ceb75SStefano Zampini #if PetscDefined(HAVE_CUDA)
3404d16ceb75SStefano Zampini     PetscCall(MatDenseCUDAGetArrayRead(A, &a));
3405d16ceb75SStefano Zampini     if (size > 1) PetscCall(VecCreateMPICUDAWithArrays(PetscObjectComm((PetscObject)A), A->rmap->bs, A->rmap->n, A->rmap->N, NULL, a, v));
3406d16ceb75SStefano Zampini     else PetscCall(VecCreateSeqCUDAWithArrays(PetscObjectComm((PetscObject)A), A->rmap->bs, A->rmap->n, NULL, a, v));
3407d16ceb75SStefano Zampini #endif
3408d16ceb75SStefano Zampini   } else if (iship) {
3409d16ceb75SStefano Zampini     PetscCheck(PetscDefined(HAVE_HIP), PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Reconfigure using HIP support");
3410d16ceb75SStefano Zampini #if PetscDefined(HAVE_HIP)
3411d16ceb75SStefano Zampini     PetscCall(MatDenseHIPGetArrayRead(A, &a));
3412d16ceb75SStefano Zampini     if (size > 1) PetscCall(VecCreateMPIHIPWithArrays(PetscObjectComm((PetscObject)A), A->rmap->bs, A->rmap->n, A->rmap->N, NULL, a, v));
3413d16ceb75SStefano Zampini     else PetscCall(VecCreateSeqHIPWithArrays(PetscObjectComm((PetscObject)A), A->rmap->bs, A->rmap->n, NULL, a, v));
3414d16ceb75SStefano Zampini #endif
3415d16ceb75SStefano Zampini   }
3416d16ceb75SStefano Zampini   PetscCheck(*v, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Not coded for type %s", A->defaultvectype);
3417d16ceb75SStefano Zampini   PetscFunctionReturn(PETSC_SUCCESS);
3418d16ceb75SStefano Zampini }
3419d16ceb75SStefano Zampini 
3420d71ae5a4SJacob Faibussowitsch PetscErrorCode MatDenseGetColumnVec_SeqDense(Mat A, PetscInt col, Vec *v)
3421d71ae5a4SJacob Faibussowitsch {
34226947451fSStefano Zampini   Mat_SeqDense *a = (Mat_SeqDense *)A->data;
34236947451fSStefano Zampini 
34246947451fSStefano Zampini   PetscFunctionBegin;
342528b400f6SJacob Faibussowitsch   PetscCheck(!a->vecinuse, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Need to call MatDenseRestoreColumnVec() first");
342628b400f6SJacob Faibussowitsch   PetscCheck(!a->matinuse, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Need to call MatDenseRestoreSubMatrix() first");
3427d16ceb75SStefano Zampini   if (!a->cvec) PetscCall(MatDenseCreateColumnVec_Private(A, &a->cvec));
34286947451fSStefano Zampini   a->vecinuse = col + 1;
34299566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArray(A, (PetscScalar **)&a->ptrinuse));
34309566063dSJacob Faibussowitsch   PetscCall(VecPlaceArray(a->cvec, a->ptrinuse + (size_t)col * (size_t)a->lda));
34316947451fSStefano Zampini   *v = a->cvec;
34323ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
34336947451fSStefano Zampini }
34346947451fSStefano Zampini 
3435d71ae5a4SJacob Faibussowitsch PetscErrorCode MatDenseRestoreColumnVec_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 MatDenseGetColumnVec() first");
344128b400f6SJacob Faibussowitsch   PetscCheck(a->cvec, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Missing internal column vector");
34424186a4bbSPierre Jolivet   VecCheckAssembled(a->cvec);
34436947451fSStefano Zampini   a->vecinuse = 0;
34449566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArray(A, (PetscScalar **)&a->ptrinuse));
34459566063dSJacob Faibussowitsch   PetscCall(VecResetArray(a->cvec));
344675f6d85dSStefano Zampini   if (v) *v = NULL;
34473ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
34486947451fSStefano Zampini }
34496947451fSStefano Zampini 
3450d71ae5a4SJacob Faibussowitsch PetscErrorCode MatDenseGetColumnVecRead_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 MatDenseRestoreColumnVec() first");
345628b400f6SJacob Faibussowitsch   PetscCheck(!a->matinuse, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Need to call MatDenseRestoreSubMatrix() first");
3457d16ceb75SStefano Zampini   if (!a->cvec) PetscCall(MatDenseCreateColumnVec_Private(A, &a->cvec));
34586947451fSStefano Zampini   a->vecinuse = col + 1;
34599566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArrayRead(A, &a->ptrinuse));
34608e3a54c0SPierre Jolivet   PetscCall(VecPlaceArray(a->cvec, PetscSafePointerPlusOffset(a->ptrinuse, (size_t)col * (size_t)a->lda)));
34619566063dSJacob Faibussowitsch   PetscCall(VecLockReadPush(a->cvec));
34626947451fSStefano Zampini   *v = a->cvec;
34633ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
34646947451fSStefano Zampini }
34656947451fSStefano Zampini 
3466d71ae5a4SJacob Faibussowitsch PetscErrorCode MatDenseRestoreColumnVecRead_SeqDense(Mat A, PetscInt col, Vec *v)
3467d71ae5a4SJacob Faibussowitsch {
34686947451fSStefano Zampini   Mat_SeqDense *a = (Mat_SeqDense *)A->data;
34696947451fSStefano Zampini 
34706947451fSStefano Zampini   PetscFunctionBegin;
347128b400f6SJacob Faibussowitsch   PetscCheck(a->vecinuse, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Need to call MatDenseGetColumnVec() first");
347228b400f6SJacob Faibussowitsch   PetscCheck(a->cvec, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Missing internal column vector");
34734186a4bbSPierre Jolivet   VecCheckAssembled(a->cvec);
34746947451fSStefano Zampini   a->vecinuse = 0;
34759566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArrayRead(A, &a->ptrinuse));
34769566063dSJacob Faibussowitsch   PetscCall(VecLockReadPop(a->cvec));
34779566063dSJacob Faibussowitsch   PetscCall(VecResetArray(a->cvec));
347875f6d85dSStefano Zampini   if (v) *v = NULL;
34793ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
34806947451fSStefano Zampini }
34816947451fSStefano Zampini 
3482d71ae5a4SJacob Faibussowitsch PetscErrorCode MatDenseGetColumnVecWrite_SeqDense(Mat A, PetscInt col, Vec *v)
3483d71ae5a4SJacob Faibussowitsch {
34846947451fSStefano Zampini   Mat_SeqDense *a = (Mat_SeqDense *)A->data;
34856947451fSStefano Zampini 
34866947451fSStefano Zampini   PetscFunctionBegin;
348728b400f6SJacob Faibussowitsch   PetscCheck(!a->vecinuse, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Need to call MatDenseRestoreColumnVec() first");
348828b400f6SJacob Faibussowitsch   PetscCheck(!a->matinuse, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Need to call MatDenseRestoreSubMatrix() first");
3489d16ceb75SStefano Zampini   if (!a->cvec) PetscCall(MatDenseCreateColumnVec_Private(A, &a->cvec));
34906947451fSStefano Zampini   a->vecinuse = col + 1;
34919566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArrayWrite(A, (PetscScalar **)&a->ptrinuse));
34928e3a54c0SPierre Jolivet   PetscCall(VecPlaceArray(a->cvec, PetscSafePointerPlusOffset(a->ptrinuse, (size_t)col * (size_t)a->lda)));
34936947451fSStefano Zampini   *v = a->cvec;
34943ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
34956947451fSStefano Zampini }
34966947451fSStefano Zampini 
3497d71ae5a4SJacob Faibussowitsch PetscErrorCode MatDenseRestoreColumnVecWrite_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 MatDenseGetColumnVec() first");
350328b400f6SJacob Faibussowitsch   PetscCheck(a->cvec, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Missing internal column vector");
35044186a4bbSPierre Jolivet   VecCheckAssembled(a->cvec);
35056947451fSStefano Zampini   a->vecinuse = 0;
35069566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArrayWrite(A, (PetscScalar **)&a->ptrinuse));
35079566063dSJacob Faibussowitsch   PetscCall(VecResetArray(a->cvec));
350875f6d85dSStefano Zampini   if (v) *v = NULL;
35093ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
35106947451fSStefano Zampini }
35116947451fSStefano Zampini 
3512d71ae5a4SJacob Faibussowitsch PetscErrorCode MatDenseGetSubMatrix_SeqDense(Mat A, PetscInt rbegin, PetscInt rend, PetscInt cbegin, PetscInt cend, Mat *v)
3513d71ae5a4SJacob Faibussowitsch {
35145ea7661aSPierre Jolivet   Mat_SeqDense *a = (Mat_SeqDense *)A->data;
35155ea7661aSPierre Jolivet 
35165ea7661aSPierre Jolivet   PetscFunctionBegin;
351728b400f6SJacob Faibussowitsch   PetscCheck(!a->vecinuse, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Need to call MatDenseRestoreColumnVec() first");
351828b400f6SJacob Faibussowitsch   PetscCheck(!a->matinuse, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Need to call MatDenseRestoreSubMatrix() first");
3519a2748737SPierre Jolivet   if (a->cmat && (cend - cbegin != a->cmat->cmap->N || rend - rbegin != a->cmat->rmap->N)) PetscCall(MatDestroy(&a->cmat));
35205ea7661aSPierre Jolivet   if (!a->cmat) {
35218e3a54c0SPierre 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));
35225ea7661aSPierre Jolivet   } else {
35238e3a54c0SPierre Jolivet     PetscCall(MatDensePlaceArray(a->cmat, PetscSafePointerPlusOffset(a->v, rbegin + (size_t)cbegin * a->lda)));
35245ea7661aSPierre Jolivet   }
35259566063dSJacob Faibussowitsch   PetscCall(MatDenseSetLDA(a->cmat, a->lda));
35265ea7661aSPierre Jolivet   a->matinuse = cbegin + 1;
35275ea7661aSPierre Jolivet   *v          = a->cmat;
352847d993e7Ssuyashtn #if defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
352975f6d85dSStefano Zampini   A->offloadmask = PETSC_OFFLOAD_CPU;
353075f6d85dSStefano Zampini #endif
35313ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
35325ea7661aSPierre Jolivet }
35335ea7661aSPierre Jolivet 
3534d71ae5a4SJacob Faibussowitsch PetscErrorCode MatDenseRestoreSubMatrix_SeqDense(Mat A, Mat *v)
3535d71ae5a4SJacob Faibussowitsch {
35365ea7661aSPierre Jolivet   Mat_SeqDense *a = (Mat_SeqDense *)A->data;
35375ea7661aSPierre Jolivet 
35385ea7661aSPierre Jolivet   PetscFunctionBegin;
353928b400f6SJacob Faibussowitsch   PetscCheck(a->matinuse, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Need to call MatDenseGetSubMatrix() first");
354028b400f6SJacob Faibussowitsch   PetscCheck(a->cmat, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Missing internal column matrix");
354108401ef6SPierre Jolivet   PetscCheck(*v == a->cmat, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Not the matrix obtained from MatDenseGetSubMatrix()");
35425ea7661aSPierre Jolivet   a->matinuse = 0;
35439566063dSJacob Faibussowitsch   PetscCall(MatDenseResetArray(a->cmat));
3544742765d3SMatthew Knepley   if (v) *v = NULL;
354547d993e7Ssuyashtn #if defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
35463faff063SStefano Zampini   A->offloadmask = PETSC_OFFLOAD_CPU;
35473faff063SStefano Zampini #endif
35483ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
35495ea7661aSPierre Jolivet }
35505ea7661aSPierre Jolivet 
35510bad9183SKris Buschelman /*MC
3552fafad747SKris Buschelman    MATSEQDENSE - MATSEQDENSE = "seqdense" - A matrix type to be used for sequential dense matrices.
35530bad9183SKris Buschelman 
35542ef1f0ffSBarry Smith    Options Database Key:
355511a5261eSBarry Smith . -mat_type seqdense - sets the matrix type to `MATSEQDENSE` during a call to `MatSetFromOptions()`
35560bad9183SKris Buschelman 
35570bad9183SKris Buschelman   Level: beginner
35580bad9183SKris Buschelman 
35591cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATSEQDENSE`, `MatCreateSeqDense()`
35600bad9183SKris Buschelman M*/
3561d71ae5a4SJacob Faibussowitsch PetscErrorCode MatCreate_SeqDense(Mat B)
3562d71ae5a4SJacob Faibussowitsch {
3563273d9f13SBarry Smith   Mat_SeqDense *b;
35647c334f02SBarry Smith   PetscMPIInt   size;
3565273d9f13SBarry Smith 
3566273d9f13SBarry Smith   PetscFunctionBegin;
35679566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)B), &size));
356808401ef6SPierre Jolivet   PetscCheck(size <= 1, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Comm must be of size 1");
356955659b69SBarry Smith 
35704dfa11a4SJacob Faibussowitsch   PetscCall(PetscNew(&b));
357144cd7ae7SLois Curfman McInnes   B->data   = (void *)b;
3572aea10558SJacob Faibussowitsch   B->ops[0] = MatOps_Values;
357318f449edSLois Curfman McInnes 
3574273d9f13SBarry Smith   b->roworiented = PETSC_TRUE;
35754e220ebcSLois Curfman McInnes 
35769566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatQRFactor_C", MatQRFactor_SeqDense));
35779566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatDenseGetLDA_C", MatDenseGetLDA_SeqDense));
35789566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatDenseSetLDA_C", MatDenseSetLDA_SeqDense));
35799566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatDenseGetArray_C", MatDenseGetArray_SeqDense));
35809566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatDenseRestoreArray_C", MatDenseRestoreArray_SeqDense));
35819566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatDensePlaceArray_C", MatDensePlaceArray_SeqDense));
35829566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatDenseResetArray_C", MatDenseResetArray_SeqDense));
35839566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatDenseReplaceArray_C", MatDenseReplaceArray_SeqDense));
35849566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatDenseGetArrayRead_C", MatDenseGetArray_SeqDense));
35859566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatDenseRestoreArrayRead_C", MatDenseRestoreArray_SeqDense));
35869566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatDenseGetArrayWrite_C", MatDenseGetArray_SeqDense));
35879566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatDenseRestoreArrayWrite_C", MatDenseRestoreArray_SeqDense));
35889566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatConvert_seqdense_seqaij_C", MatConvert_SeqDense_SeqAIJ));
35898baccfbdSHong Zhang #if defined(PETSC_HAVE_ELEMENTAL)
35909566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatConvert_seqdense_elemental_C", MatConvert_SeqDense_Elemental));
35918baccfbdSHong Zhang #endif
3592d24d4204SJose E. Roman #if defined(PETSC_HAVE_SCALAPACK)
35939566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatConvert_seqdense_scalapack_C", MatConvert_Dense_ScaLAPACK));
3594d24d4204SJose E. Roman #endif
35952bf066beSStefano Zampini #if defined(PETSC_HAVE_CUDA)
35969566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatConvert_seqdense_seqdensecuda_C", MatConvert_SeqDense_SeqDenseCUDA));
35979566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatProductSetFromOptions_seqdensecuda_seqdensecuda_C", MatProductSetFromOptions_SeqDense));
35989566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatProductSetFromOptions_seqdensecuda_seqdense_C", MatProductSetFromOptions_SeqDense));
35999566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatProductSetFromOptions_seqdense_seqdensecuda_C", MatProductSetFromOptions_SeqDense));
36002bf066beSStefano Zampini #endif
360147d993e7Ssuyashtn #if defined(PETSC_HAVE_HIP)
360247d993e7Ssuyashtn   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatConvert_seqdense_seqdensehip_C", MatConvert_SeqDense_SeqDenseHIP));
360347d993e7Ssuyashtn   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatProductSetFromOptions_seqdensehip_seqdensehip_C", MatProductSetFromOptions_SeqDense));
360447d993e7Ssuyashtn   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatProductSetFromOptions_seqdensehip_seqdense_C", MatProductSetFromOptions_SeqDense));
360547d993e7Ssuyashtn   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatProductSetFromOptions_seqdense_seqdensehip_C", MatProductSetFromOptions_SeqDense));
360647d993e7Ssuyashtn #endif
36079566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatSeqDenseSetPreallocation_C", MatSeqDenseSetPreallocation_SeqDense));
36089566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatProductSetFromOptions_seqaij_seqdense_C", MatProductSetFromOptions_SeqAIJ_SeqDense));
36099566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatProductSetFromOptions_seqdense_seqdense_C", MatProductSetFromOptions_SeqDense));
36109566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatProductSetFromOptions_seqbaij_seqdense_C", MatProductSetFromOptions_SeqXBAIJ_SeqDense));
36119566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatProductSetFromOptions_seqsbaij_seqdense_C", MatProductSetFromOptions_SeqXBAIJ_SeqDense));
361296e6d5c4SRichard Tran Mills 
36139566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatDenseGetColumn_C", MatDenseGetColumn_SeqDense));
36149566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatDenseRestoreColumn_C", MatDenseRestoreColumn_SeqDense));
36159566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatDenseGetColumnVec_C", MatDenseGetColumnVec_SeqDense));
36169566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatDenseRestoreColumnVec_C", MatDenseRestoreColumnVec_SeqDense));
36179566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatDenseGetColumnVecRead_C", MatDenseGetColumnVecRead_SeqDense));
36189566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatDenseRestoreColumnVecRead_C", MatDenseRestoreColumnVecRead_SeqDense));
36199566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatDenseGetColumnVecWrite_C", MatDenseGetColumnVecWrite_SeqDense));
36209566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatDenseRestoreColumnVecWrite_C", MatDenseRestoreColumnVecWrite_SeqDense));
36219566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatDenseGetSubMatrix_C", MatDenseGetSubMatrix_SeqDense));
36229566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatDenseRestoreSubMatrix_C", MatDenseRestoreSubMatrix_SeqDense));
3623d016bddeSToby Isaac   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatMultColumnRange_C", MatMultColumnRange_SeqDense));
36240be0d8bdSHansol Suh   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatMultAddColumnRange_C", MatMultAddColumnRange_SeqDense));
36250be0d8bdSHansol Suh   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatMultHermitianTransposeColumnRange_C", MatMultHermitianTransposeColumnRange_SeqDense));
36260be0d8bdSHansol Suh   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatMultHermitianTransposeAddColumnRange_C", MatMultHermitianTransposeAddColumnRange_SeqDense));
36279566063dSJacob Faibussowitsch   PetscCall(PetscObjectChangeTypeName((PetscObject)B, MATSEQDENSE));
36283ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3629289bc588SBarry Smith }
363086aefd0dSHong Zhang 
363186aefd0dSHong Zhang /*@C
363211a5261eSBarry 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.
363386aefd0dSHong Zhang 
363486aefd0dSHong Zhang   Not Collective
363586aefd0dSHong Zhang 
36365ea7661aSPierre Jolivet   Input Parameters:
3637fe59aa6dSJacob Faibussowitsch + A   - a `MATSEQDENSE` or `MATMPIDENSE` matrix
363886aefd0dSHong Zhang - col - column index
363986aefd0dSHong Zhang 
364086aefd0dSHong Zhang   Output Parameter:
364186aefd0dSHong Zhang . vals - pointer to the data
364286aefd0dSHong Zhang 
364386aefd0dSHong Zhang   Level: intermediate
364486aefd0dSHong Zhang 
364511a5261eSBarry Smith   Note:
364611a5261eSBarry Smith   Use `MatDenseGetColumnVec()` to get access to a column of a `MATDENSE` treated as a `Vec`
364711a5261eSBarry Smith 
36481cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATDENSE`, `MatDenseRestoreColumn()`, `MatDenseGetColumnVec()`
364986aefd0dSHong Zhang @*/
36505d83a8b1SBarry Smith PetscErrorCode MatDenseGetColumn(Mat A, PetscInt col, PetscScalar *vals[])
3651d71ae5a4SJacob Faibussowitsch {
365286aefd0dSHong Zhang   PetscFunctionBegin;
3653d5ea218eSStefano Zampini   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
3654d5ea218eSStefano Zampini   PetscValidLogicalCollectiveInt(A, col, 2);
36554f572ea9SToby Isaac   PetscAssertPointer(vals, 3);
3656cac4c232SBarry Smith   PetscUseMethod(A, "MatDenseGetColumn_C", (Mat, PetscInt, PetscScalar **), (A, col, vals));
36573ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
365886aefd0dSHong Zhang }
365986aefd0dSHong Zhang 
366086aefd0dSHong Zhang /*@C
366111a5261eSBarry Smith   MatDenseRestoreColumn - returns access to a column of a `MATDENSE` matrix which is returned by `MatDenseGetColumn()`.
366286aefd0dSHong Zhang 
366386aefd0dSHong Zhang   Not Collective
366486aefd0dSHong Zhang 
3665742765d3SMatthew Knepley   Input Parameters:
3666fe59aa6dSJacob Faibussowitsch + A    - a `MATSEQDENSE` or `MATMPIDENSE` matrix
36672ef1f0ffSBarry Smith - vals - pointer to the data (may be `NULL`)
366886aefd0dSHong Zhang 
366986aefd0dSHong Zhang   Level: intermediate
367086aefd0dSHong Zhang 
36711cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATDENSE`, `MatDenseGetColumn()`
367286aefd0dSHong Zhang @*/
36735d83a8b1SBarry Smith PetscErrorCode MatDenseRestoreColumn(Mat A, PetscScalar *vals[])
3674d71ae5a4SJacob Faibussowitsch {
367586aefd0dSHong Zhang   PetscFunctionBegin;
3676d5ea218eSStefano Zampini   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
36774f572ea9SToby Isaac   PetscAssertPointer(vals, 2);
3678cac4c232SBarry Smith   PetscUseMethod(A, "MatDenseRestoreColumn_C", (Mat, PetscScalar **), (A, vals));
36793ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
368086aefd0dSHong Zhang }
36816947451fSStefano Zampini 
36820f74d2c1SSatish Balay /*@
368311a5261eSBarry Smith   MatDenseGetColumnVec - Gives read-write access to a column of a `MATDENSE` matrix, represented as a `Vec`.
36846947451fSStefano Zampini 
36856947451fSStefano Zampini   Collective
36866947451fSStefano Zampini 
36875ea7661aSPierre Jolivet   Input Parameters:
3688fe59aa6dSJacob Faibussowitsch + A   - the `Mat` object
36896947451fSStefano Zampini - col - the column index
36906947451fSStefano Zampini 
36916947451fSStefano Zampini   Output Parameter:
36926947451fSStefano Zampini . v - the vector
36936947451fSStefano Zampini 
36942ef1f0ffSBarry Smith   Level: intermediate
36952ef1f0ffSBarry Smith 
36966947451fSStefano Zampini   Notes:
369711a5261eSBarry Smith   The vector is owned by PETSc. Users need to call `MatDenseRestoreColumnVec()` when the vector is no longer needed.
369811a5261eSBarry Smith 
369911a5261eSBarry Smith   Use `MatDenseGetColumnVecRead()` to obtain read-only access or `MatDenseGetColumnVecWrite()` for write-only access.
37006947451fSStefano Zampini 
37011cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATDENSE`, `MATDENSECUDA`, `MATDENSEHIP`, `MatDenseGetColumnVecRead()`, `MatDenseGetColumnVecWrite()`, `MatDenseRestoreColumnVec()`, `MatDenseRestoreColumnVecRead()`, `MatDenseRestoreColumnVecWrite()`, `MatDenseGetColumn()`
37026947451fSStefano Zampini @*/
3703d71ae5a4SJacob Faibussowitsch PetscErrorCode MatDenseGetColumnVec(Mat A, PetscInt col, Vec *v)
3704d71ae5a4SJacob Faibussowitsch {
37056947451fSStefano Zampini   PetscFunctionBegin;
37066947451fSStefano Zampini   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
37076947451fSStefano Zampini   PetscValidType(A, 1);
37086947451fSStefano Zampini   PetscValidLogicalCollectiveInt(A, col, 2);
37094f572ea9SToby Isaac   PetscAssertPointer(v, 3);
371028b400f6SJacob Faibussowitsch   PetscCheck(A->preallocated, PetscObjectComm((PetscObject)A), PETSC_ERR_ORDER, "Matrix not preallocated");
37112cf15c64SPierre 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);
3712cac4c232SBarry Smith   PetscUseMethod(A, "MatDenseGetColumnVec_C", (Mat, PetscInt, Vec *), (A, col, v));
37133ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
37146947451fSStefano Zampini }
37156947451fSStefano Zampini 
37160f74d2c1SSatish Balay /*@
3717fb850c59SBarry Smith   MatDenseRestoreColumnVec - Returns access to a column of a dense matrix obtained from `MatDenseGetColumnVec()`.
37186947451fSStefano Zampini 
37196947451fSStefano Zampini   Collective
37206947451fSStefano Zampini 
37215ea7661aSPierre Jolivet   Input Parameters:
3722fb850c59SBarry Smith + A   - the `Mat` object
37236947451fSStefano Zampini . col - the column index
3724fb850c59SBarry Smith - v   - the `Vec` object (may be `NULL`)
37256947451fSStefano Zampini 
37266947451fSStefano Zampini   Level: intermediate
37276947451fSStefano Zampini 
37281cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATDENSE`, `MATDENSECUDA`, `MATDENSEHIP`, `MatDenseGetColumnVec()`, `MatDenseGetColumnVecRead()`, `MatDenseGetColumnVecWrite()`, `MatDenseRestoreColumnVecRead()`, `MatDenseRestoreColumnVecWrite()`
37296947451fSStefano Zampini @*/
3730d71ae5a4SJacob Faibussowitsch PetscErrorCode MatDenseRestoreColumnVec(Mat A, PetscInt col, Vec *v)
3731d71ae5a4SJacob Faibussowitsch {
37326947451fSStefano Zampini   PetscFunctionBegin;
37336947451fSStefano Zampini   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
37346947451fSStefano Zampini   PetscValidType(A, 1);
37356947451fSStefano Zampini   PetscValidLogicalCollectiveInt(A, col, 2);
373608401ef6SPierre Jolivet   PetscCheck(A->preallocated, PetscObjectComm((PetscObject)A), PETSC_ERR_ORDER, "Matrix not preallocated");
37372cf15c64SPierre 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);
3738cac4c232SBarry Smith   PetscUseMethod(A, "MatDenseRestoreColumnVec_C", (Mat, PetscInt, Vec *), (A, col, v));
37393ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
37406947451fSStefano Zampini }
37416947451fSStefano Zampini 
37420f74d2c1SSatish Balay /*@
3743fb850c59SBarry Smith   MatDenseGetColumnVecRead - Gives read-only access to a column of a dense matrix, represented as a `Vec`.
37446947451fSStefano Zampini 
37456947451fSStefano Zampini   Collective
37466947451fSStefano Zampini 
37475ea7661aSPierre Jolivet   Input Parameters:
3748fe59aa6dSJacob Faibussowitsch + A   - the `Mat` object
37496947451fSStefano Zampini - col - the column index
37506947451fSStefano Zampini 
37516947451fSStefano Zampini   Output Parameter:
37526947451fSStefano Zampini . v - the vector
37536947451fSStefano Zampini 
37542ef1f0ffSBarry Smith   Level: intermediate
37552ef1f0ffSBarry Smith 
37566947451fSStefano Zampini   Notes:
37576947451fSStefano Zampini   The vector is owned by PETSc and users cannot modify it.
375811a5261eSBarry Smith 
37592ef1f0ffSBarry Smith   Users need to call `MatDenseRestoreColumnVecRead()` when the vector is no longer needed.
376011a5261eSBarry Smith 
37612ef1f0ffSBarry Smith   Use `MatDenseGetColumnVec()` to obtain read-write access or `MatDenseGetColumnVecWrite()` for write-only access.
37626947451fSStefano Zampini 
37631cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATDENSE`, `MATDENSECUDA`, `MATDENSEHIP`, `MatDenseGetColumnVec()`, `MatDenseGetColumnVecWrite()`, `MatDenseRestoreColumnVec()`, `MatDenseRestoreColumnVecRead()`, `MatDenseRestoreColumnVecWrite()`
37646947451fSStefano Zampini @*/
3765d71ae5a4SJacob Faibussowitsch PetscErrorCode MatDenseGetColumnVecRead(Mat A, PetscInt col, Vec *v)
3766d71ae5a4SJacob Faibussowitsch {
37676947451fSStefano Zampini   PetscFunctionBegin;
37686947451fSStefano Zampini   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
37696947451fSStefano Zampini   PetscValidType(A, 1);
37706947451fSStefano Zampini   PetscValidLogicalCollectiveInt(A, col, 2);
37714f572ea9SToby Isaac   PetscAssertPointer(v, 3);
377228b400f6SJacob Faibussowitsch   PetscCheck(A->preallocated, PetscObjectComm((PetscObject)A), PETSC_ERR_ORDER, "Matrix not preallocated");
37732cf15c64SPierre 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);
3774cac4c232SBarry Smith   PetscUseMethod(A, "MatDenseGetColumnVecRead_C", (Mat, PetscInt, Vec *), (A, col, v));
37753ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
37766947451fSStefano Zampini }
37776947451fSStefano Zampini 
37780f74d2c1SSatish Balay /*@
3779fb850c59SBarry Smith   MatDenseRestoreColumnVecRead - Returns access to a column of a dense matrix obtained from `MatDenseGetColumnVecRead()`.
37806947451fSStefano Zampini 
37816947451fSStefano Zampini   Collective
37826947451fSStefano Zampini 
37835ea7661aSPierre Jolivet   Input Parameters:
3784fe59aa6dSJacob Faibussowitsch + A   - the `Mat` object
37856947451fSStefano Zampini . col - the column index
3786fb850c59SBarry Smith - v   - the `Vec` object (may be `NULL`)
37876947451fSStefano Zampini 
37886947451fSStefano Zampini   Level: intermediate
37896947451fSStefano Zampini 
37901cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATDENSE`, `MATDENSECUDA`, `MATDENSEHIP`, `MatDenseGetColumnVec()`, `MatDenseGetColumnVecRead()`, `MatDenseGetColumnVecWrite()`, `MatDenseRestoreColumnVec()`, `MatDenseRestoreColumnVecWrite()`
37916947451fSStefano Zampini @*/
3792d71ae5a4SJacob Faibussowitsch PetscErrorCode MatDenseRestoreColumnVecRead(Mat A, PetscInt col, Vec *v)
3793d71ae5a4SJacob Faibussowitsch {
37946947451fSStefano Zampini   PetscFunctionBegin;
37956947451fSStefano Zampini   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
37966947451fSStefano Zampini   PetscValidType(A, 1);
37976947451fSStefano Zampini   PetscValidLogicalCollectiveInt(A, col, 2);
379808401ef6SPierre Jolivet   PetscCheck(A->preallocated, PetscObjectComm((PetscObject)A), PETSC_ERR_ORDER, "Matrix not preallocated");
37992cf15c64SPierre 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);
3800cac4c232SBarry Smith   PetscUseMethod(A, "MatDenseRestoreColumnVecRead_C", (Mat, PetscInt, Vec *), (A, col, v));
38013ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
38026947451fSStefano Zampini }
38036947451fSStefano Zampini 
38040f74d2c1SSatish Balay /*@
3805fb850c59SBarry Smith   MatDenseGetColumnVecWrite - Gives write-only access to a column of a dense matrix, represented as a `Vec`.
38066947451fSStefano Zampini 
38076947451fSStefano Zampini   Collective
38086947451fSStefano Zampini 
38095ea7661aSPierre Jolivet   Input Parameters:
3810fe59aa6dSJacob Faibussowitsch + A   - the `Mat` object
38116947451fSStefano Zampini - col - the column index
38126947451fSStefano Zampini 
38136947451fSStefano Zampini   Output Parameter:
38146947451fSStefano Zampini . v - the vector
38156947451fSStefano Zampini 
38166947451fSStefano Zampini   Level: intermediate
38176947451fSStefano Zampini 
38182ef1f0ffSBarry Smith   Notes:
38192ef1f0ffSBarry Smith   The vector is owned by PETSc. Users need to call `MatDenseRestoreColumnVecWrite()` when the vector is no longer needed.
38202ef1f0ffSBarry Smith 
38212ef1f0ffSBarry Smith   Use `MatDenseGetColumnVec()` to obtain read-write access or `MatDenseGetColumnVecRead()` for read-only access.
38222ef1f0ffSBarry Smith 
38231cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATDENSE`, `MATDENSECUDA`, `MATDENSEHIP`, `MatDenseGetColumnVec()`, `MatDenseGetColumnVecRead()`, `MatDenseRestoreColumnVec()`, `MatDenseRestoreColumnVecRead()`, `MatDenseRestoreColumnVecWrite()`
38246947451fSStefano Zampini @*/
3825d71ae5a4SJacob Faibussowitsch PetscErrorCode MatDenseGetColumnVecWrite(Mat A, PetscInt col, Vec *v)
3826d71ae5a4SJacob Faibussowitsch {
38276947451fSStefano Zampini   PetscFunctionBegin;
38286947451fSStefano Zampini   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
38296947451fSStefano Zampini   PetscValidType(A, 1);
38306947451fSStefano Zampini   PetscValidLogicalCollectiveInt(A, col, 2);
38314f572ea9SToby Isaac   PetscAssertPointer(v, 3);
383228b400f6SJacob Faibussowitsch   PetscCheck(A->preallocated, PetscObjectComm((PetscObject)A), PETSC_ERR_ORDER, "Matrix not preallocated");
3833aed4548fSBarry 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);
3834cac4c232SBarry Smith   PetscUseMethod(A, "MatDenseGetColumnVecWrite_C", (Mat, PetscInt, Vec *), (A, col, v));
38353ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
38366947451fSStefano Zampini }
38376947451fSStefano Zampini 
38380f74d2c1SSatish Balay /*@
3839fb850c59SBarry Smith   MatDenseRestoreColumnVecWrite - Returns access to a column of a dense matrix obtained from `MatDenseGetColumnVecWrite()`.
38406947451fSStefano Zampini 
38416947451fSStefano Zampini   Collective
38426947451fSStefano Zampini 
38435ea7661aSPierre Jolivet   Input Parameters:
3844fe59aa6dSJacob Faibussowitsch + A   - the `Mat` object
38456947451fSStefano Zampini . col - the column index
38462ef1f0ffSBarry Smith - v   - the `Vec` object (may be `NULL`)
38476947451fSStefano Zampini 
38486947451fSStefano Zampini   Level: intermediate
38496947451fSStefano Zampini 
38501cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATDENSE`, `MATDENSECUDA`, `MATDENSEHIP`, `MatDenseGetColumnVec()`, `MatDenseGetColumnVecRead()`, `MatDenseGetColumnVecWrite()`, `MatDenseRestoreColumnVec()`, `MatDenseRestoreColumnVecRead()`
38516947451fSStefano Zampini @*/
3852d71ae5a4SJacob Faibussowitsch PetscErrorCode MatDenseRestoreColumnVecWrite(Mat A, PetscInt col, Vec *v)
3853d71ae5a4SJacob Faibussowitsch {
38546947451fSStefano Zampini   PetscFunctionBegin;
38556947451fSStefano Zampini   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
38566947451fSStefano Zampini   PetscValidType(A, 1);
38576947451fSStefano Zampini   PetscValidLogicalCollectiveInt(A, col, 2);
385808401ef6SPierre Jolivet   PetscCheck(A->preallocated, PetscObjectComm((PetscObject)A), PETSC_ERR_ORDER, "Matrix not preallocated");
3859aed4548fSBarry 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);
3860cac4c232SBarry Smith   PetscUseMethod(A, "MatDenseRestoreColumnVecWrite_C", (Mat, PetscInt, Vec *), (A, col, v));
38613ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
38626947451fSStefano Zampini }
38635ea7661aSPierre Jolivet 
38640f74d2c1SSatish Balay /*@
3865fb850c59SBarry Smith   MatDenseGetSubMatrix - Gives access to a block of rows and columns of a dense matrix, represented as a `Mat`.
38665ea7661aSPierre Jolivet 
38675ea7661aSPierre Jolivet   Collective
38685ea7661aSPierre Jolivet 
38695ea7661aSPierre Jolivet   Input Parameters:
3870fb850c59SBarry Smith + A      - the `Mat` object
38712ef1f0ffSBarry Smith . rbegin - the first global row index in the block (if `PETSC_DECIDE`, is 0)
38722ef1f0ffSBarry Smith . rend   - the global row index past the last one in the block (if `PETSC_DECIDE`, is `M`)
38732ef1f0ffSBarry Smith . cbegin - the first global column index in the block (if `PETSC_DECIDE`, is 0)
38742ef1f0ffSBarry Smith - cend   - the global column index past the last one in the block (if `PETSC_DECIDE`, is `N`)
38755ea7661aSPierre Jolivet 
38765ea7661aSPierre Jolivet   Output Parameter:
38775ea7661aSPierre Jolivet . v - the matrix
38785ea7661aSPierre Jolivet 
38795ea7661aSPierre Jolivet   Level: intermediate
38805ea7661aSPierre Jolivet 
38812ef1f0ffSBarry Smith   Notes:
38822ef1f0ffSBarry Smith   The matrix is owned by PETSc. Users need to call `MatDenseRestoreSubMatrix()` when the matrix is no longer needed.
38832ef1f0ffSBarry Smith 
38842ef1f0ffSBarry 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.
38852ef1f0ffSBarry Smith 
38861cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATDENSE`, `MATDENSECUDA`, `MATDENSEHIP`, `MatDenseGetColumnVec()`, `MatDenseRestoreColumnVec()`, `MatDenseRestoreSubMatrix()`
38875ea7661aSPierre Jolivet @*/
3888d71ae5a4SJacob Faibussowitsch PetscErrorCode MatDenseGetSubMatrix(Mat A, PetscInt rbegin, PetscInt rend, PetscInt cbegin, PetscInt cend, Mat *v)
3889d71ae5a4SJacob Faibussowitsch {
38905ea7661aSPierre Jolivet   PetscFunctionBegin;
38915ea7661aSPierre Jolivet   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
38925ea7661aSPierre Jolivet   PetscValidType(A, 1);
3893a2748737SPierre Jolivet   PetscValidLogicalCollectiveInt(A, rbegin, 2);
3894a2748737SPierre Jolivet   PetscValidLogicalCollectiveInt(A, rend, 3);
3895a2748737SPierre Jolivet   PetscValidLogicalCollectiveInt(A, cbegin, 4);
3896a2748737SPierre Jolivet   PetscValidLogicalCollectiveInt(A, cend, 5);
38974f572ea9SToby Isaac   PetscAssertPointer(v, 6);
3898a2748737SPierre Jolivet   if (rbegin == PETSC_DECIDE) rbegin = 0;
3899a2748737SPierre Jolivet   if (rend == PETSC_DECIDE) rend = A->rmap->N;
3900a2748737SPierre Jolivet   if (cbegin == PETSC_DECIDE) cbegin = 0;
3901a2748737SPierre Jolivet   if (cend == PETSC_DECIDE) cend = A->cmap->N;
390228b400f6SJacob Faibussowitsch   PetscCheck(A->preallocated, PetscObjectComm((PetscObject)A), PETSC_ERR_ORDER, "Matrix not preallocated");
3903a2748737SPierre 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);
3904a2748737SPierre 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);
3905a2748737SPierre 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);
3906a2748737SPierre 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);
3907a2748737SPierre Jolivet   PetscUseMethod(A, "MatDenseGetSubMatrix_C", (Mat, PetscInt, PetscInt, PetscInt, PetscInt, Mat *), (A, rbegin, rend, cbegin, cend, v));
39083ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
39095ea7661aSPierre Jolivet }
39105ea7661aSPierre Jolivet 
39110f74d2c1SSatish Balay /*@
3912fb850c59SBarry Smith   MatDenseRestoreSubMatrix - Returns access to a block of columns of a dense matrix obtained from `MatDenseGetSubMatrix()`.
39135ea7661aSPierre Jolivet 
39145ea7661aSPierre Jolivet   Collective
39155ea7661aSPierre Jolivet 
39165ea7661aSPierre Jolivet   Input Parameters:
3917fe59aa6dSJacob Faibussowitsch + A - the `Mat` object
39182ef1f0ffSBarry Smith - v - the `Mat` object (may be `NULL`)
39195ea7661aSPierre Jolivet 
39205ea7661aSPierre Jolivet   Level: intermediate
39215ea7661aSPierre Jolivet 
39221cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATDENSE`, `MATDENSECUDA`, `MATDENSEHIP`, `MatDenseGetColumnVec()`, `MatDenseRestoreColumnVec()`, `MatDenseGetSubMatrix()`
39235ea7661aSPierre Jolivet @*/
3924d71ae5a4SJacob Faibussowitsch PetscErrorCode MatDenseRestoreSubMatrix(Mat A, Mat *v)
3925d71ae5a4SJacob Faibussowitsch {
39265ea7661aSPierre Jolivet   PetscFunctionBegin;
39275ea7661aSPierre Jolivet   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
39285ea7661aSPierre Jolivet   PetscValidType(A, 1);
39294f572ea9SToby Isaac   PetscAssertPointer(v, 2);
3930cac4c232SBarry Smith   PetscUseMethod(A, "MatDenseRestoreSubMatrix_C", (Mat, Mat *), (A, v));
39313ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
39325ea7661aSPierre Jolivet }
39338a9c020eSBarry Smith 
39348a9c020eSBarry Smith #include <petscblaslapack.h>
39358a9c020eSBarry Smith #include <petsc/private/kernels/blockinvert.h>
39368a9c020eSBarry Smith 
3937d71ae5a4SJacob Faibussowitsch PetscErrorCode MatSeqDenseInvert(Mat A)
3938d71ae5a4SJacob Faibussowitsch {
3939d63b1753SJacob Faibussowitsch   PetscInt        m;
39408a9c020eSBarry Smith   const PetscReal shift = 0.0;
3941d63b1753SJacob Faibussowitsch   PetscBool       allowzeropivot, zeropivotdetected = PETSC_FALSE;
3942d63b1753SJacob Faibussowitsch   PetscScalar    *values;
39438a9c020eSBarry Smith 
39448a9c020eSBarry Smith   PetscFunctionBegin;
3945d63b1753SJacob Faibussowitsch   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
3946d63b1753SJacob Faibussowitsch   PetscCall(MatDenseGetArray(A, &values));
3947d63b1753SJacob Faibussowitsch   PetscCall(MatGetLocalSize(A, &m, NULL));
3948d63b1753SJacob Faibussowitsch   allowzeropivot = PetscNot(A->erroriffailure);
39498a9c020eSBarry Smith   /* factor and invert each block */
3950d63b1753SJacob Faibussowitsch   switch (m) {
3951d71ae5a4SJacob Faibussowitsch   case 1:
3952d71ae5a4SJacob Faibussowitsch     values[0] = (PetscScalar)1.0 / (values[0] + shift);
3953d71ae5a4SJacob Faibussowitsch     break;
39548a9c020eSBarry Smith   case 2:
39558a9c020eSBarry Smith     PetscCall(PetscKernel_A_gets_inverse_A_2(values, shift, allowzeropivot, &zeropivotdetected));
39568a9c020eSBarry Smith     if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
39578a9c020eSBarry Smith     break;
39588a9c020eSBarry Smith   case 3:
39598a9c020eSBarry Smith     PetscCall(PetscKernel_A_gets_inverse_A_3(values, shift, allowzeropivot, &zeropivotdetected));
39608a9c020eSBarry Smith     if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
39618a9c020eSBarry Smith     break;
39628a9c020eSBarry Smith   case 4:
39638a9c020eSBarry Smith     PetscCall(PetscKernel_A_gets_inverse_A_4(values, shift, allowzeropivot, &zeropivotdetected));
39648a9c020eSBarry Smith     if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
39658a9c020eSBarry Smith     break;
39669371c9d4SSatish Balay   case 5: {
39678a9c020eSBarry Smith     PetscScalar work[25];
39688a9c020eSBarry Smith     PetscInt    ipvt[5];
39698a9c020eSBarry Smith 
39708a9c020eSBarry Smith     PetscCall(PetscKernel_A_gets_inverse_A_5(values, ipvt, work, shift, allowzeropivot, &zeropivotdetected));
39718a9c020eSBarry Smith     if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
39729371c9d4SSatish Balay   } break;
39738a9c020eSBarry Smith   case 6:
39748a9c020eSBarry Smith     PetscCall(PetscKernel_A_gets_inverse_A_6(values, shift, allowzeropivot, &zeropivotdetected));
39758a9c020eSBarry Smith     if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
39768a9c020eSBarry Smith     break;
39778a9c020eSBarry Smith   case 7:
39788a9c020eSBarry Smith     PetscCall(PetscKernel_A_gets_inverse_A_7(values, shift, allowzeropivot, &zeropivotdetected));
39798a9c020eSBarry Smith     if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
39808a9c020eSBarry Smith     break;
39819371c9d4SSatish Balay   default: {
39828a9c020eSBarry Smith     PetscInt    *v_pivots, *IJ, j;
39838a9c020eSBarry Smith     PetscScalar *v_work;
39848a9c020eSBarry Smith 
3985d63b1753SJacob Faibussowitsch     PetscCall(PetscMalloc3(m, &v_work, m, &v_pivots, m, &IJ));
3986d63b1753SJacob Faibussowitsch     for (j = 0; j < m; j++) IJ[j] = j;
3987d63b1753SJacob Faibussowitsch     PetscCall(PetscKernel_A_gets_inverse_A(m, values, v_pivots, v_work, allowzeropivot, &zeropivotdetected));
39888a9c020eSBarry Smith     if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
39898a9c020eSBarry Smith     PetscCall(PetscFree3(v_work, v_pivots, IJ));
39908a9c020eSBarry Smith   }
39918a9c020eSBarry Smith   }
3992d63b1753SJacob Faibussowitsch   PetscCall(MatDenseRestoreArray(A, &values));
39933ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
39948a9c020eSBarry Smith }
3995