xref: /petsc/src/mat/impls/dense/seq/dense.c (revision 97b17b2c96638fa82656d19f821c0b2bb95580e1)
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 
4174396437dSToby Isaac static PetscErrorCode MatConjugate_SeqDense(Mat);
4184396437dSToby Isaac 
419d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatSolve_SeqDense_Internal_Cholesky(Mat A, PetscScalar *x, PetscBLASInt ldx, PetscBLASInt m, PetscBLASInt nrhs, PetscBLASInt k, PetscBool T)
420d71ae5a4SJacob Faibussowitsch {
4214396437dSToby Isaac   Mat_SeqDense *mat = (Mat_SeqDense *)A->data;
4224396437dSToby Isaac   PetscBLASInt  info;
4234396437dSToby Isaac 
4244396437dSToby Isaac   PetscFunctionBegin;
425b94d7dedSBarry Smith   if (A->spd == PETSC_BOOL3_TRUE) {
4269566063dSJacob Faibussowitsch     if (PetscDefined(USE_COMPLEX) && T) PetscCall(MatConjugate_SeqDense(A));
4279566063dSJacob Faibussowitsch     PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF));
428792fecdfSBarry Smith     PetscCallBLAS("LAPACKpotrs", LAPACKpotrs_("L", &m, &nrhs, mat->v, &mat->lda, x, &m, &info));
4299566063dSJacob Faibussowitsch     PetscCall(PetscFPTrapPop());
430835f2295SStefano Zampini     PetscCheck(!info, PETSC_COMM_SELF, PETSC_ERR_LIB, "POTRS Bad solve %" PetscBLASInt_FMT, info);
4319566063dSJacob Faibussowitsch     if (PetscDefined(USE_COMPLEX) && T) PetscCall(MatConjugate_SeqDense(A));
432a49dc2a2SStefano Zampini #if defined(PETSC_USE_COMPLEX)
433b94d7dedSBarry Smith   } else if (A->hermitian == PETSC_BOOL3_TRUE) {
4349566063dSJacob Faibussowitsch     if (T) PetscCall(MatConjugate_SeqDense(A));
4359566063dSJacob Faibussowitsch     PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF));
436792fecdfSBarry Smith     PetscCallBLAS("LAPACKhetrs", LAPACKhetrs_("L", &m, &nrhs, mat->v, &mat->lda, mat->pivots, x, &m, &info));
4379566063dSJacob Faibussowitsch     PetscCall(PetscFPTrapPop());
438835f2295SStefano Zampini     PetscCheck(!info, PETSC_COMM_SELF, PETSC_ERR_LIB, "HETRS Bad solve %" PetscBLASInt_FMT, info);
4399566063dSJacob Faibussowitsch     if (T) PetscCall(MatConjugate_SeqDense(A));
440a49dc2a2SStefano Zampini #endif
441a49dc2a2SStefano Zampini   } else { /* symmetric case */
4429566063dSJacob Faibussowitsch     PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF));
443792fecdfSBarry Smith     PetscCallBLAS("LAPACKsytrs", LAPACKsytrs_("L", &m, &nrhs, mat->v, &mat->lda, mat->pivots, x, &m, &info));
4449566063dSJacob Faibussowitsch     PetscCall(PetscFPTrapPop());
445835f2295SStefano Zampini     PetscCheck(!info, PETSC_COMM_SELF, PETSC_ERR_LIB, "SYTRS Bad solve %" PetscBLASInt_FMT, info);
446a49dc2a2SStefano Zampini   }
4479566063dSJacob Faibussowitsch   PetscCall(PetscLogFlops(nrhs * (2.0 * m * m - m)));
4483ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4494396437dSToby Isaac }
45085e2c93fSHong Zhang 
451d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatSolve_SeqDense_Internal_QR(Mat A, PetscScalar *x, PetscBLASInt ldx, PetscBLASInt m, PetscBLASInt nrhs, PetscBLASInt k)
452d71ae5a4SJacob Faibussowitsch {
4534396437dSToby Isaac   Mat_SeqDense *mat = (Mat_SeqDense *)A->data;
4544396437dSToby Isaac   PetscBLASInt  info;
4554396437dSToby Isaac   char          trans;
4564396437dSToby Isaac 
4574396437dSToby Isaac   PetscFunctionBegin;
4584905a7bcSToby Isaac   if (PetscDefined(USE_COMPLEX)) {
4594905a7bcSToby Isaac     trans = 'C';
4604905a7bcSToby Isaac   } else {
4614905a7bcSToby Isaac     trans = 'T';
4624905a7bcSToby Isaac   }
4639566063dSJacob Faibussowitsch   PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF));
46405fcb23eSStefano Zampini   { /* lwork depends on the number of right-hand sides */
46505fcb23eSStefano Zampini     PetscBLASInt nlfwork, lfwork = -1;
46605fcb23eSStefano Zampini     PetscScalar  fwork;
46705fcb23eSStefano Zampini 
468792fecdfSBarry Smith     PetscCallBLAS("LAPACKormqr", LAPACKormqr_("L", &trans, &m, &nrhs, &mat->rank, mat->v, &mat->lda, mat->tau, x, &ldx, &fwork, &lfwork, &info));
46905fcb23eSStefano Zampini     nlfwork = (PetscBLASInt)PetscRealPart(fwork);
47005fcb23eSStefano Zampini     if (nlfwork > mat->lfwork) {
47105fcb23eSStefano Zampini       mat->lfwork = nlfwork;
47205fcb23eSStefano Zampini       PetscCall(PetscFree(mat->fwork));
47305fcb23eSStefano Zampini       PetscCall(PetscMalloc1(mat->lfwork, &mat->fwork));
47405fcb23eSStefano Zampini     }
47505fcb23eSStefano Zampini   }
476792fecdfSBarry Smith   PetscCallBLAS("LAPACKormqr", LAPACKormqr_("L", &trans, &m, &nrhs, &mat->rank, mat->v, &mat->lda, mat->tau, x, &ldx, mat->fwork, &mat->lfwork, &info));
4779566063dSJacob Faibussowitsch   PetscCall(PetscFPTrapPop());
478835f2295SStefano Zampini   PetscCheck(!info, PETSC_COMM_SELF, PETSC_ERR_LIB, "ORMQR - Bad orthogonal transform %" PetscBLASInt_FMT, info);
4799566063dSJacob Faibussowitsch   PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF));
480792fecdfSBarry Smith   PetscCallBLAS("LAPACKtrtrs", LAPACKtrtrs_("U", "N", "N", &mat->rank, &nrhs, mat->v, &mat->lda, x, &ldx, &info));
4819566063dSJacob Faibussowitsch   PetscCall(PetscFPTrapPop());
482835f2295SStefano Zampini   PetscCheck(!info, PETSC_COMM_SELF, PETSC_ERR_LIB, "TRTRS - Bad triangular solve %" PetscBLASInt_FMT, info);
4834905a7bcSToby Isaac   for (PetscInt j = 0; j < nrhs; j++) {
484ad540459SPierre Jolivet     for (PetscInt i = mat->rank; i < k; i++) x[j * ldx + i] = 0.;
4854905a7bcSToby Isaac   }
4869566063dSJacob Faibussowitsch   PetscCall(PetscLogFlops(nrhs * (4.0 * m * mat->rank - PetscSqr(mat->rank))));
4873ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4884905a7bcSToby Isaac }
4894905a7bcSToby Isaac 
490d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatSolveTranspose_SeqDense_Internal_QR(Mat A, PetscScalar *x, PetscBLASInt ldx, PetscBLASInt m, PetscBLASInt nrhs, PetscBLASInt k)
491d71ae5a4SJacob Faibussowitsch {
4924396437dSToby Isaac   Mat_SeqDense *mat = (Mat_SeqDense *)A->data;
4934396437dSToby Isaac   PetscBLASInt  info;
4944396437dSToby Isaac 
4954396437dSToby Isaac   PetscFunctionBegin;
4964396437dSToby Isaac   if (A->rmap->n == A->cmap->n && mat->rank == A->rmap->n) {
4979566063dSJacob Faibussowitsch     PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF));
498792fecdfSBarry Smith     PetscCallBLAS("LAPACKtrtrs", LAPACKtrtrs_("U", "T", "N", &m, &nrhs, mat->v, &mat->lda, x, &ldx, &info));
4999566063dSJacob Faibussowitsch     PetscCall(PetscFPTrapPop());
500835f2295SStefano Zampini     PetscCheck(!info, PETSC_COMM_SELF, PETSC_ERR_LIB, "TRTRS - Bad triangular solve %" PetscBLASInt_FMT, info);
5019566063dSJacob Faibussowitsch     if (PetscDefined(USE_COMPLEX)) PetscCall(MatConjugate_SeqDense(A));
50205fcb23eSStefano Zampini     { /* lwork depends on the number of right-hand sides */
50305fcb23eSStefano Zampini       PetscBLASInt nlfwork, lfwork = -1;
50405fcb23eSStefano Zampini       PetscScalar  fwork;
50505fcb23eSStefano Zampini 
506792fecdfSBarry Smith       PetscCallBLAS("LAPACKormqr", LAPACKormqr_("L", "N", &m, &nrhs, &mat->rank, mat->v, &mat->lda, mat->tau, x, &ldx, &fwork, &lfwork, &info));
50705fcb23eSStefano Zampini       nlfwork = (PetscBLASInt)PetscRealPart(fwork);
50805fcb23eSStefano Zampini       if (nlfwork > mat->lfwork) {
50905fcb23eSStefano Zampini         mat->lfwork = nlfwork;
51005fcb23eSStefano Zampini         PetscCall(PetscFree(mat->fwork));
51105fcb23eSStefano Zampini         PetscCall(PetscMalloc1(mat->lfwork, &mat->fwork));
51205fcb23eSStefano Zampini       }
51305fcb23eSStefano Zampini     }
5149566063dSJacob Faibussowitsch     PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF));
515792fecdfSBarry Smith     PetscCallBLAS("LAPACKormqr", LAPACKormqr_("L", "N", &m, &nrhs, &mat->rank, mat->v, &mat->lda, mat->tau, x, &ldx, mat->fwork, &mat->lfwork, &info));
5169566063dSJacob Faibussowitsch     PetscCall(PetscFPTrapPop());
517835f2295SStefano Zampini     PetscCheck(!info, PETSC_COMM_SELF, PETSC_ERR_LIB, "ORMQR - Bad orthogonal transform %" PetscBLASInt_FMT, info);
5189566063dSJacob Faibussowitsch     if (PetscDefined(USE_COMPLEX)) PetscCall(MatConjugate_SeqDense(A));
5194396437dSToby Isaac   } else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "QR factored matrix cannot be used for transpose solve");
5209566063dSJacob Faibussowitsch   PetscCall(PetscLogFlops(nrhs * (4.0 * m * mat->rank - PetscSqr(mat->rank))));
5213ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5224396437dSToby Isaac }
5234396437dSToby Isaac 
524d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatSolve_SeqDense_SetUp(Mat A, Vec xx, Vec yy, PetscScalar **_y, PetscBLASInt *_m, PetscBLASInt *_k)
525d71ae5a4SJacob Faibussowitsch {
5264396437dSToby Isaac   Mat_SeqDense *mat = (Mat_SeqDense *)A->data;
5274905a7bcSToby Isaac   PetscScalar  *y;
5284905a7bcSToby Isaac   PetscBLASInt  m = 0, k = 0;
5294905a7bcSToby Isaac 
5304905a7bcSToby Isaac   PetscFunctionBegin;
5319566063dSJacob Faibussowitsch   PetscCall(PetscBLASIntCast(A->rmap->n, &m));
5329566063dSJacob Faibussowitsch   PetscCall(PetscBLASIntCast(A->cmap->n, &k));
5334905a7bcSToby Isaac   if (k < m) {
5349566063dSJacob Faibussowitsch     PetscCall(VecCopy(xx, mat->qrrhs));
5359566063dSJacob Faibussowitsch     PetscCall(VecGetArray(mat->qrrhs, &y));
5364905a7bcSToby Isaac   } else {
5379566063dSJacob Faibussowitsch     PetscCall(VecCopy(xx, yy));
5389566063dSJacob Faibussowitsch     PetscCall(VecGetArray(yy, &y));
5394905a7bcSToby Isaac   }
5404396437dSToby Isaac   *_y = y;
5414396437dSToby Isaac   *_k = k;
5424396437dSToby Isaac   *_m = m;
5433ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5444396437dSToby Isaac }
5454396437dSToby Isaac 
546d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatSolve_SeqDense_TearDown(Mat A, Vec xx, Vec yy, PetscScalar **_y, PetscBLASInt *_m, PetscBLASInt *_k)
547d71ae5a4SJacob Faibussowitsch {
5484396437dSToby Isaac   Mat_SeqDense *mat = (Mat_SeqDense *)A->data;
54942e9364cSSatish Balay   PetscScalar  *y   = NULL;
5504396437dSToby Isaac   PetscBLASInt  m, k;
5514396437dSToby Isaac 
5524396437dSToby Isaac   PetscFunctionBegin;
5534396437dSToby Isaac   y   = *_y;
5544396437dSToby Isaac   *_y = NULL;
5554396437dSToby Isaac   k   = *_k;
5564396437dSToby Isaac   m   = *_m;
5574905a7bcSToby Isaac   if (k < m) {
5584905a7bcSToby Isaac     PetscScalar *yv;
5599566063dSJacob Faibussowitsch     PetscCall(VecGetArray(yy, &yv));
5609566063dSJacob Faibussowitsch     PetscCall(PetscArraycpy(yv, y, k));
5619566063dSJacob Faibussowitsch     PetscCall(VecRestoreArray(yy, &yv));
5629566063dSJacob Faibussowitsch     PetscCall(VecRestoreArray(mat->qrrhs, &y));
5634905a7bcSToby Isaac   } else {
5649566063dSJacob Faibussowitsch     PetscCall(VecRestoreArray(yy, &y));
5654905a7bcSToby Isaac   }
5663ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5674905a7bcSToby Isaac }
5684905a7bcSToby Isaac 
569d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatSolve_SeqDense_LU(Mat A, Vec xx, Vec yy)
570d71ae5a4SJacob Faibussowitsch {
57142e9364cSSatish Balay   PetscScalar *y = NULL;
57242e9364cSSatish Balay   PetscBLASInt m = 0, k = 0;
5734396437dSToby Isaac 
5744396437dSToby Isaac   PetscFunctionBegin;
5759566063dSJacob Faibussowitsch   PetscCall(MatSolve_SeqDense_SetUp(A, xx, yy, &y, &m, &k));
5769566063dSJacob Faibussowitsch   PetscCall(MatSolve_SeqDense_Internal_LU(A, y, m, m, 1, k, PETSC_FALSE));
5779566063dSJacob Faibussowitsch   PetscCall(MatSolve_SeqDense_TearDown(A, xx, yy, &y, &m, &k));
5783ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5794396437dSToby Isaac }
5804396437dSToby Isaac 
581d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatSolveTranspose_SeqDense_LU(Mat A, Vec xx, Vec yy)
582d71ae5a4SJacob Faibussowitsch {
58342e9364cSSatish Balay   PetscScalar *y = NULL;
58442e9364cSSatish Balay   PetscBLASInt m = 0, k = 0;
5854396437dSToby Isaac 
5864396437dSToby Isaac   PetscFunctionBegin;
5879566063dSJacob Faibussowitsch   PetscCall(MatSolve_SeqDense_SetUp(A, xx, yy, &y, &m, &k));
5889566063dSJacob Faibussowitsch   PetscCall(MatSolve_SeqDense_Internal_LU(A, y, m, m, 1, k, PETSC_TRUE));
5899566063dSJacob Faibussowitsch   PetscCall(MatSolve_SeqDense_TearDown(A, xx, yy, &y, &m, &k));
5903ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5914396437dSToby Isaac }
5924396437dSToby Isaac 
593d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatSolve_SeqDense_Cholesky(Mat A, Vec xx, Vec yy)
594d71ae5a4SJacob Faibussowitsch {
595e54beecaSStefano Zampini   PetscScalar *y = NULL;
596e54beecaSStefano Zampini   PetscBLASInt m = 0, k = 0;
5974396437dSToby Isaac 
5984396437dSToby Isaac   PetscFunctionBegin;
5999566063dSJacob Faibussowitsch   PetscCall(MatSolve_SeqDense_SetUp(A, xx, yy, &y, &m, &k));
6009566063dSJacob Faibussowitsch   PetscCall(MatSolve_SeqDense_Internal_Cholesky(A, y, m, m, 1, k, PETSC_FALSE));
6019566063dSJacob Faibussowitsch   PetscCall(MatSolve_SeqDense_TearDown(A, xx, yy, &y, &m, &k));
6023ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
6034396437dSToby Isaac }
6044396437dSToby Isaac 
605d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatSolveTranspose_SeqDense_Cholesky(Mat A, Vec xx, Vec yy)
606d71ae5a4SJacob Faibussowitsch {
607e54beecaSStefano Zampini   PetscScalar *y = NULL;
608e54beecaSStefano Zampini   PetscBLASInt m = 0, k = 0;
6094396437dSToby Isaac 
6104396437dSToby Isaac   PetscFunctionBegin;
6119566063dSJacob Faibussowitsch   PetscCall(MatSolve_SeqDense_SetUp(A, xx, yy, &y, &m, &k));
6129566063dSJacob Faibussowitsch   PetscCall(MatSolve_SeqDense_Internal_Cholesky(A, y, m, m, 1, k, PETSC_TRUE));
6139566063dSJacob Faibussowitsch   PetscCall(MatSolve_SeqDense_TearDown(A, xx, yy, &y, &m, &k));
6143ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
6154396437dSToby Isaac }
6164396437dSToby Isaac 
617d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatSolve_SeqDense_QR(Mat A, Vec xx, Vec yy)
618d71ae5a4SJacob Faibussowitsch {
619e54beecaSStefano Zampini   PetscScalar *y = NULL;
620e54beecaSStefano Zampini   PetscBLASInt m = 0, k = 0;
6214396437dSToby Isaac 
6224396437dSToby Isaac   PetscFunctionBegin;
6239566063dSJacob Faibussowitsch   PetscCall(MatSolve_SeqDense_SetUp(A, xx, yy, &y, &m, &k));
6249566063dSJacob Faibussowitsch   PetscCall(MatSolve_SeqDense_Internal_QR(A, y, PetscMax(m, k), m, 1, k));
6259566063dSJacob Faibussowitsch   PetscCall(MatSolve_SeqDense_TearDown(A, xx, yy, &y, &m, &k));
6263ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
6274396437dSToby Isaac }
6284396437dSToby Isaac 
629d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatSolveTranspose_SeqDense_QR(Mat A, Vec xx, Vec yy)
630d71ae5a4SJacob Faibussowitsch {
63142e9364cSSatish Balay   PetscScalar *y = NULL;
63242e9364cSSatish Balay   PetscBLASInt m = 0, k = 0;
6334396437dSToby Isaac 
6344396437dSToby Isaac   PetscFunctionBegin;
6359566063dSJacob Faibussowitsch   PetscCall(MatSolve_SeqDense_SetUp(A, xx, yy, &y, &m, &k));
6369566063dSJacob Faibussowitsch   PetscCall(MatSolveTranspose_SeqDense_Internal_QR(A, y, PetscMax(m, k), m, 1, k));
6379566063dSJacob Faibussowitsch   PetscCall(MatSolve_SeqDense_TearDown(A, xx, yy, &y, &m, &k));
6383ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
6394396437dSToby Isaac }
6404396437dSToby Isaac 
641d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatMatSolve_SeqDense_SetUp(Mat A, Mat B, Mat X, PetscScalar **_y, PetscBLASInt *_ldy, PetscBLASInt *_m, PetscBLASInt *_nrhs, PetscBLASInt *_k)
642d71ae5a4SJacob Faibussowitsch {
6434905a7bcSToby Isaac   const PetscScalar *b;
6444396437dSToby Isaac   PetscScalar       *y;
645bf5a80bcSToby Isaac   PetscInt           n, _ldb, _ldx;
646bf5a80bcSToby Isaac   PetscBLASInt       nrhs = 0, m = 0, k = 0, ldb = 0, ldx = 0, ldy = 0;
6474905a7bcSToby Isaac 
6484905a7bcSToby Isaac   PetscFunctionBegin;
6499371c9d4SSatish Balay   *_ldy  = 0;
6509371c9d4SSatish Balay   *_m    = 0;
6519371c9d4SSatish Balay   *_nrhs = 0;
6529371c9d4SSatish Balay   *_k    = 0;
6539371c9d4SSatish Balay   *_y    = NULL;
6549566063dSJacob Faibussowitsch   PetscCall(PetscBLASIntCast(A->rmap->n, &m));
6559566063dSJacob Faibussowitsch   PetscCall(PetscBLASIntCast(A->cmap->n, &k));
6569566063dSJacob Faibussowitsch   PetscCall(MatGetSize(B, NULL, &n));
6579566063dSJacob Faibussowitsch   PetscCall(PetscBLASIntCast(n, &nrhs));
6589566063dSJacob Faibussowitsch   PetscCall(MatDenseGetLDA(B, &_ldb));
6599566063dSJacob Faibussowitsch   PetscCall(PetscBLASIntCast(_ldb, &ldb));
6609566063dSJacob Faibussowitsch   PetscCall(MatDenseGetLDA(X, &_ldx));
6619566063dSJacob Faibussowitsch   PetscCall(PetscBLASIntCast(_ldx, &ldx));
662bf5a80bcSToby Isaac   if (ldx < m) {
6639566063dSJacob Faibussowitsch     PetscCall(MatDenseGetArrayRead(B, &b));
6649566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(nrhs * m, &y));
665bf5a80bcSToby Isaac     if (ldb == m) {
6669566063dSJacob Faibussowitsch       PetscCall(PetscArraycpy(y, b, ldb * nrhs));
6674905a7bcSToby Isaac     } else {
66848a46eb9SPierre Jolivet       for (PetscInt j = 0; j < nrhs; j++) PetscCall(PetscArraycpy(&y[j * m], &b[j * ldb], m));
6694905a7bcSToby Isaac     }
670bf5a80bcSToby Isaac     ldy = m;
6719566063dSJacob Faibussowitsch     PetscCall(MatDenseRestoreArrayRead(B, &b));
6724905a7bcSToby Isaac   } else {
673bf5a80bcSToby Isaac     if (ldb == ldx) {
6749566063dSJacob Faibussowitsch       PetscCall(MatCopy(B, X, SAME_NONZERO_PATTERN));
6759566063dSJacob Faibussowitsch       PetscCall(MatDenseGetArray(X, &y));
6764905a7bcSToby Isaac     } else {
6779566063dSJacob Faibussowitsch       PetscCall(MatDenseGetArray(X, &y));
6789566063dSJacob Faibussowitsch       PetscCall(MatDenseGetArrayRead(B, &b));
67948a46eb9SPierre Jolivet       for (PetscInt j = 0; j < nrhs; j++) PetscCall(PetscArraycpy(&y[j * ldx], &b[j * ldb], m));
6809566063dSJacob Faibussowitsch       PetscCall(MatDenseRestoreArrayRead(B, &b));
6814905a7bcSToby Isaac     }
682bf5a80bcSToby Isaac     ldy = ldx;
6834905a7bcSToby Isaac   }
6844396437dSToby Isaac   *_y    = y;
685bf5a80bcSToby Isaac   *_ldy  = ldy;
6864396437dSToby Isaac   *_k    = k;
6874396437dSToby Isaac   *_m    = m;
6884396437dSToby Isaac   *_nrhs = nrhs;
6893ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
6904396437dSToby Isaac }
6914396437dSToby Isaac 
692d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatMatSolve_SeqDense_TearDown(Mat A, Mat B, Mat X, PetscScalar **_y, PetscBLASInt *_ldy, PetscBLASInt *_m, PetscBLASInt *_nrhs, PetscBLASInt *_k)
693d71ae5a4SJacob Faibussowitsch {
6944396437dSToby Isaac   PetscScalar *y;
695bf5a80bcSToby Isaac   PetscInt     _ldx;
696bf5a80bcSToby Isaac   PetscBLASInt k, ldy, nrhs, ldx = 0;
6974396437dSToby Isaac 
6984396437dSToby Isaac   PetscFunctionBegin;
6994396437dSToby Isaac   y    = *_y;
7004396437dSToby Isaac   *_y  = NULL;
7014396437dSToby Isaac   k    = *_k;
702bf5a80bcSToby Isaac   ldy  = *_ldy;
7034396437dSToby Isaac   nrhs = *_nrhs;
7049566063dSJacob Faibussowitsch   PetscCall(MatDenseGetLDA(X, &_ldx));
7059566063dSJacob Faibussowitsch   PetscCall(PetscBLASIntCast(_ldx, &ldx));
706bf5a80bcSToby Isaac   if (ldx != ldy) {
7074905a7bcSToby Isaac     PetscScalar *xv;
7089566063dSJacob Faibussowitsch     PetscCall(MatDenseGetArray(X, &xv));
70948a46eb9SPierre Jolivet     for (PetscInt j = 0; j < nrhs; j++) PetscCall(PetscArraycpy(&xv[j * ldx], &y[j * ldy], k));
7109566063dSJacob Faibussowitsch     PetscCall(MatDenseRestoreArray(X, &xv));
7119566063dSJacob Faibussowitsch     PetscCall(PetscFree(y));
7124905a7bcSToby Isaac   } else {
7139566063dSJacob Faibussowitsch     PetscCall(MatDenseRestoreArray(X, &y));
7144905a7bcSToby Isaac   }
7153ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
71685e2c93fSHong Zhang }
71785e2c93fSHong Zhang 
718d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatMatSolve_SeqDense_LU(Mat A, Mat B, Mat X)
719d71ae5a4SJacob Faibussowitsch {
7204396437dSToby Isaac   PetscScalar *y;
721bf5a80bcSToby Isaac   PetscBLASInt m, k, ldy, nrhs;
7224396437dSToby Isaac 
7234396437dSToby Isaac   PetscFunctionBegin;
7249566063dSJacob Faibussowitsch   PetscCall(MatMatSolve_SeqDense_SetUp(A, B, X, &y, &ldy, &m, &nrhs, &k));
7259566063dSJacob Faibussowitsch   PetscCall(MatSolve_SeqDense_Internal_LU(A, y, ldy, m, nrhs, k, PETSC_FALSE));
7269566063dSJacob Faibussowitsch   PetscCall(MatMatSolve_SeqDense_TearDown(A, B, X, &y, &ldy, &m, &nrhs, &k));
7273ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
7284396437dSToby Isaac }
7294396437dSToby Isaac 
730d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatMatSolveTranspose_SeqDense_LU(Mat A, Mat B, Mat X)
731d71ae5a4SJacob Faibussowitsch {
7324396437dSToby Isaac   PetscScalar *y;
733bf5a80bcSToby Isaac   PetscBLASInt m, k, ldy, nrhs;
7344396437dSToby Isaac 
7354396437dSToby Isaac   PetscFunctionBegin;
7369566063dSJacob Faibussowitsch   PetscCall(MatMatSolve_SeqDense_SetUp(A, B, X, &y, &ldy, &m, &nrhs, &k));
7379566063dSJacob Faibussowitsch   PetscCall(MatSolve_SeqDense_Internal_LU(A, y, ldy, m, nrhs, k, PETSC_TRUE));
7389566063dSJacob Faibussowitsch   PetscCall(MatMatSolve_SeqDense_TearDown(A, B, X, &y, &ldy, &m, &nrhs, &k));
7393ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
7404396437dSToby Isaac }
7414396437dSToby Isaac 
742d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatMatSolve_SeqDense_Cholesky(Mat A, Mat B, Mat X)
743d71ae5a4SJacob Faibussowitsch {
7444396437dSToby Isaac   PetscScalar *y;
745bf5a80bcSToby Isaac   PetscBLASInt m, k, ldy, nrhs;
7464396437dSToby Isaac 
7474396437dSToby Isaac   PetscFunctionBegin;
7489566063dSJacob Faibussowitsch   PetscCall(MatMatSolve_SeqDense_SetUp(A, B, X, &y, &ldy, &m, &nrhs, &k));
7499566063dSJacob Faibussowitsch   PetscCall(MatSolve_SeqDense_Internal_Cholesky(A, y, ldy, m, nrhs, k, PETSC_FALSE));
7509566063dSJacob Faibussowitsch   PetscCall(MatMatSolve_SeqDense_TearDown(A, B, X, &y, &ldy, &m, &nrhs, &k));
7513ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
7524396437dSToby Isaac }
7534396437dSToby Isaac 
754d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatMatSolveTranspose_SeqDense_Cholesky(Mat A, Mat B, Mat X)
755d71ae5a4SJacob Faibussowitsch {
7564396437dSToby Isaac   PetscScalar *y;
757bf5a80bcSToby Isaac   PetscBLASInt m, k, ldy, nrhs;
7584396437dSToby Isaac 
7594396437dSToby Isaac   PetscFunctionBegin;
7609566063dSJacob Faibussowitsch   PetscCall(MatMatSolve_SeqDense_SetUp(A, B, X, &y, &ldy, &m, &nrhs, &k));
7619566063dSJacob Faibussowitsch   PetscCall(MatSolve_SeqDense_Internal_Cholesky(A, y, ldy, m, nrhs, k, PETSC_TRUE));
7629566063dSJacob Faibussowitsch   PetscCall(MatMatSolve_SeqDense_TearDown(A, B, X, &y, &ldy, &m, &nrhs, &k));
7633ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
7644396437dSToby Isaac }
7654396437dSToby Isaac 
766d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatMatSolve_SeqDense_QR(Mat A, Mat B, Mat X)
767d71ae5a4SJacob Faibussowitsch {
7684396437dSToby Isaac   PetscScalar *y;
769bf5a80bcSToby Isaac   PetscBLASInt m, k, ldy, nrhs;
7704396437dSToby Isaac 
7714396437dSToby Isaac   PetscFunctionBegin;
7729566063dSJacob Faibussowitsch   PetscCall(MatMatSolve_SeqDense_SetUp(A, B, X, &y, &ldy, &m, &nrhs, &k));
7739566063dSJacob Faibussowitsch   PetscCall(MatSolve_SeqDense_Internal_QR(A, y, ldy, m, nrhs, k));
7749566063dSJacob Faibussowitsch   PetscCall(MatMatSolve_SeqDense_TearDown(A, B, X, &y, &ldy, &m, &nrhs, &k));
7753ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
7764396437dSToby Isaac }
7774396437dSToby Isaac 
778d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatMatSolveTranspose_SeqDense_QR(Mat A, Mat B, Mat X)
779d71ae5a4SJacob Faibussowitsch {
7804396437dSToby Isaac   PetscScalar *y;
781bf5a80bcSToby Isaac   PetscBLASInt m, k, ldy, nrhs;
7824396437dSToby Isaac 
7834396437dSToby Isaac   PetscFunctionBegin;
7849566063dSJacob Faibussowitsch   PetscCall(MatMatSolve_SeqDense_SetUp(A, B, X, &y, &ldy, &m, &nrhs, &k));
7859566063dSJacob Faibussowitsch   PetscCall(MatSolveTranspose_SeqDense_Internal_QR(A, y, ldy, m, nrhs, k));
7869566063dSJacob Faibussowitsch   PetscCall(MatMatSolve_SeqDense_TearDown(A, B, X, &y, &ldy, &m, &nrhs, &k));
7873ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
7884396437dSToby Isaac }
7894396437dSToby Isaac 
790db4efbfdSBarry Smith /* COMMENT: I have chosen to hide row permutation in the pivots,
791db4efbfdSBarry Smith    rather than put it in the Mat->row slot.*/
792*97b17b2cSPierre Jolivet PetscErrorCode MatLUFactor_SeqDense(Mat A, IS row, IS col, PETSC_UNUSED const MatFactorInfo *minfo)
793d71ae5a4SJacob Faibussowitsch {
794db4efbfdSBarry Smith   Mat_SeqDense *mat = (Mat_SeqDense *)A->data;
795db4efbfdSBarry Smith   PetscBLASInt  n, m, info;
796db4efbfdSBarry Smith 
797db4efbfdSBarry Smith   PetscFunctionBegin;
7989566063dSJacob Faibussowitsch   PetscCall(PetscBLASIntCast(A->cmap->n, &n));
7999566063dSJacob Faibussowitsch   PetscCall(PetscBLASIntCast(A->rmap->n, &m));
8004dfa11a4SJacob Faibussowitsch   if (!mat->pivots) { PetscCall(PetscMalloc1(A->rmap->n, &mat->pivots)); }
8013ba16761SJacob Faibussowitsch   if (!A->rmap->n || !A->cmap->n) PetscFunctionReturn(PETSC_SUCCESS);
8029566063dSJacob Faibussowitsch   PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF));
803792fecdfSBarry Smith   PetscCallBLAS("LAPACKgetrf", LAPACKgetrf_(&m, &n, mat->v, &mat->lda, mat->pivots, &info));
8049566063dSJacob Faibussowitsch   PetscCall(PetscFPTrapPop());
8058e57ea43SSatish Balay 
806835f2295SStefano Zampini   PetscCheck(info >= 0, PETSC_COMM_SELF, PETSC_ERR_LIB, "Bad argument to LU factorization %" PetscBLASInt_FMT, info);
807835f2295SStefano Zampini   PetscCheck(info <= 0, PETSC_COMM_SELF, PETSC_ERR_MAT_LU_ZRPVT, "Bad LU factorization %" PetscBLASInt_FMT, info);
8088208b9aeSStefano Zampini 
8094396437dSToby Isaac   A->ops->solve             = MatSolve_SeqDense_LU;
8104396437dSToby Isaac   A->ops->matsolve          = MatMatSolve_SeqDense_LU;
8114396437dSToby Isaac   A->ops->solvetranspose    = MatSolveTranspose_SeqDense_LU;
8124396437dSToby Isaac   A->ops->matsolvetranspose = MatMatSolveTranspose_SeqDense_LU;
813d5f3da31SBarry Smith   A->factortype             = MAT_FACTOR_LU;
814db4efbfdSBarry Smith 
8159566063dSJacob Faibussowitsch   PetscCall(PetscFree(A->solvertype));
8169566063dSJacob Faibussowitsch   PetscCall(PetscStrallocpy(MATSOLVERPETSC, &A->solvertype));
817f6224b95SHong Zhang 
8189566063dSJacob Faibussowitsch   PetscCall(PetscLogFlops((2.0 * A->cmap->n * A->cmap->n * A->cmap->n) / 3));
8193ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
820db4efbfdSBarry Smith }
821db4efbfdSBarry Smith 
822*97b17b2cSPierre Jolivet static PetscErrorCode MatLUFactorNumeric_SeqDense(Mat fact, Mat A, const MatFactorInfo *info)
823d71ae5a4SJacob Faibussowitsch {
8244396437dSToby Isaac   PetscFunctionBegin;
8259566063dSJacob Faibussowitsch   PetscCall(MatDuplicateNoCreate_SeqDense(fact, A, MAT_COPY_VALUES));
826*97b17b2cSPierre Jolivet   PetscUseTypeMethod(fact, lufactor, NULL, NULL, info);
8273ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
8284396437dSToby Isaac }
8294396437dSToby Isaac 
830*97b17b2cSPierre Jolivet PetscErrorCode MatLUFactorSymbolic_SeqDense(Mat fact, Mat A, IS row, IS col, PETSC_UNUSED const MatFactorInfo *info)
831d71ae5a4SJacob Faibussowitsch {
8324396437dSToby Isaac   PetscFunctionBegin;
8334396437dSToby Isaac   fact->preallocated         = PETSC_TRUE;
8344396437dSToby Isaac   fact->assembled            = PETSC_TRUE;
8354396437dSToby Isaac   fact->ops->lufactornumeric = MatLUFactorNumeric_SeqDense;
8363ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
8374396437dSToby Isaac }
8384396437dSToby Isaac 
839a49dc2a2SStefano Zampini /* Cholesky as L*L^T or L*D*L^T and the symmetric/hermitian complex variants */
840*97b17b2cSPierre Jolivet PetscErrorCode MatCholeskyFactor_SeqDense(Mat A, IS perm, PETSC_UNUSED const MatFactorInfo *minfo)
841d71ae5a4SJacob Faibussowitsch {
842db4efbfdSBarry Smith   Mat_SeqDense *mat = (Mat_SeqDense *)A->data;
843c5df96a5SBarry Smith   PetscBLASInt  info, n;
844db4efbfdSBarry Smith 
845db4efbfdSBarry Smith   PetscFunctionBegin;
8469566063dSJacob Faibussowitsch   PetscCall(PetscBLASIntCast(A->cmap->n, &n));
8473ba16761SJacob Faibussowitsch   if (!A->rmap->n || !A->cmap->n) PetscFunctionReturn(PETSC_SUCCESS);
848b94d7dedSBarry Smith   if (A->spd == PETSC_BOOL3_TRUE) {
8499566063dSJacob Faibussowitsch     PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF));
850792fecdfSBarry Smith     PetscCallBLAS("LAPACKpotrf", LAPACKpotrf_("L", &n, mat->v, &mat->lda, &info));
8519566063dSJacob Faibussowitsch     PetscCall(PetscFPTrapPop());
852a49dc2a2SStefano Zampini #if defined(PETSC_USE_COMPLEX)
853b94d7dedSBarry Smith   } else if (A->hermitian == PETSC_BOOL3_TRUE) {
8544dfa11a4SJacob Faibussowitsch     if (!mat->pivots) { PetscCall(PetscMalloc1(A->rmap->n, &mat->pivots)); }
855a49dc2a2SStefano Zampini     if (!mat->fwork) {
856a49dc2a2SStefano Zampini       PetscScalar dummy;
857a49dc2a2SStefano Zampini 
858a49dc2a2SStefano Zampini       mat->lfwork = -1;
8599566063dSJacob Faibussowitsch       PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF));
860792fecdfSBarry Smith       PetscCallBLAS("LAPACKhetrf", LAPACKhetrf_("L", &n, mat->v, &mat->lda, mat->pivots, &dummy, &mat->lfwork, &info));
8619566063dSJacob Faibussowitsch       PetscCall(PetscFPTrapPop());
86207c83e99SJose E. Roman       PetscCall(PetscBLASIntCast((PetscCount)(PetscRealPart(dummy)), &mat->lfwork));
8639566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(mat->lfwork, &mat->fwork));
864a49dc2a2SStefano Zampini     }
8659566063dSJacob Faibussowitsch     PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF));
866792fecdfSBarry Smith     PetscCallBLAS("LAPACKhetrf", LAPACKhetrf_("L", &n, mat->v, &mat->lda, mat->pivots, mat->fwork, &mat->lfwork, &info));
8679566063dSJacob Faibussowitsch     PetscCall(PetscFPTrapPop());
868a49dc2a2SStefano Zampini #endif
869a49dc2a2SStefano Zampini   } else { /* symmetric case */
8704dfa11a4SJacob Faibussowitsch     if (!mat->pivots) { PetscCall(PetscMalloc1(A->rmap->n, &mat->pivots)); }
871a49dc2a2SStefano Zampini     if (!mat->fwork) {
872a49dc2a2SStefano Zampini       PetscScalar dummy;
873a49dc2a2SStefano Zampini 
874a49dc2a2SStefano Zampini       mat->lfwork = -1;
8759566063dSJacob Faibussowitsch       PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF));
876792fecdfSBarry Smith       PetscCallBLAS("LAPACKsytrf", LAPACKsytrf_("L", &n, mat->v, &mat->lda, mat->pivots, &dummy, &mat->lfwork, &info));
8779566063dSJacob Faibussowitsch       PetscCall(PetscFPTrapPop());
8786497c311SBarry Smith       PetscCall(PetscBLASIntCast((PetscCount)(PetscRealPart(dummy)), &mat->lfwork));
8799566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(mat->lfwork, &mat->fwork));
880a49dc2a2SStefano Zampini     }
8819566063dSJacob Faibussowitsch     PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF));
882792fecdfSBarry Smith     PetscCallBLAS("LAPACKsytrf", LAPACKsytrf_("L", &n, mat->v, &mat->lda, mat->pivots, mat->fwork, &mat->lfwork, &info));
8839566063dSJacob Faibussowitsch     PetscCall(PetscFPTrapPop());
884a49dc2a2SStefano Zampini   }
885835f2295SStefano Zampini   PetscCheck(!info, PETSC_COMM_SELF, PETSC_ERR_MAT_CH_ZRPVT, "Bad factorization: zero pivot in row %" PetscBLASInt_FMT, info - 1);
8868208b9aeSStefano Zampini 
8874396437dSToby Isaac   A->ops->solve             = MatSolve_SeqDense_Cholesky;
8884396437dSToby Isaac   A->ops->matsolve          = MatMatSolve_SeqDense_Cholesky;
8894396437dSToby Isaac   A->ops->solvetranspose    = MatSolveTranspose_SeqDense_Cholesky;
8904396437dSToby Isaac   A->ops->matsolvetranspose = MatMatSolveTranspose_SeqDense_Cholesky;
891d5f3da31SBarry Smith   A->factortype             = MAT_FACTOR_CHOLESKY;
8922205254eSKarl Rupp 
8939566063dSJacob Faibussowitsch   PetscCall(PetscFree(A->solvertype));
8949566063dSJacob Faibussowitsch   PetscCall(PetscStrallocpy(MATSOLVERPETSC, &A->solvertype));
895f6224b95SHong Zhang 
8969566063dSJacob Faibussowitsch   PetscCall(PetscLogFlops((1.0 * A->cmap->n * A->cmap->n * A->cmap->n) / 3.0));
8973ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
898db4efbfdSBarry Smith }
899db4efbfdSBarry Smith 
900*97b17b2cSPierre Jolivet static PetscErrorCode MatCholeskyFactorNumeric_SeqDense(Mat fact, Mat A, const MatFactorInfo *info)
901d71ae5a4SJacob Faibussowitsch {
902db4efbfdSBarry Smith   PetscFunctionBegin;
9039566063dSJacob Faibussowitsch   PetscCall(MatDuplicateNoCreate_SeqDense(fact, A, MAT_COPY_VALUES));
904*97b17b2cSPierre Jolivet   PetscUseTypeMethod(fact, choleskyfactor, NULL, info);
9053ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
906db4efbfdSBarry Smith }
907db4efbfdSBarry Smith 
908d71ae5a4SJacob Faibussowitsch PetscErrorCode MatCholeskyFactorSymbolic_SeqDense(Mat fact, Mat A, IS row, const MatFactorInfo *info)
909d71ae5a4SJacob Faibussowitsch {
910db4efbfdSBarry Smith   PetscFunctionBegin;
911c3ef05f6SHong Zhang   fact->assembled                  = PETSC_TRUE;
9121bbcc794SSatish Balay   fact->preallocated               = PETSC_TRUE;
913719d5645SBarry Smith   fact->ops->choleskyfactornumeric = MatCholeskyFactorNumeric_SeqDense;
9143ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
915db4efbfdSBarry Smith }
916db4efbfdSBarry Smith 
917*97b17b2cSPierre Jolivet PetscErrorCode MatQRFactor_SeqDense(Mat A, IS col, PETSC_UNUSED const MatFactorInfo *minfo)
918d71ae5a4SJacob Faibussowitsch {
9194905a7bcSToby Isaac   Mat_SeqDense *mat = (Mat_SeqDense *)A->data;
9204905a7bcSToby Isaac   PetscBLASInt  n, m, info, min, max;
9214905a7bcSToby Isaac 
9224905a7bcSToby Isaac   PetscFunctionBegin;
9239566063dSJacob Faibussowitsch   PetscCall(PetscBLASIntCast(A->cmap->n, &n));
9249566063dSJacob Faibussowitsch   PetscCall(PetscBLASIntCast(A->rmap->n, &m));
9254396437dSToby Isaac   max = PetscMax(m, n);
9264396437dSToby Isaac   min = PetscMin(m, n);
9274dfa11a4SJacob Faibussowitsch   if (!mat->tau) { PetscCall(PetscMalloc1(min, &mat->tau)); }
9284dfa11a4SJacob Faibussowitsch   if (!mat->pivots) { PetscCall(PetscMalloc1(n, &mat->pivots)); }
929f4f49eeaSPierre Jolivet   if (!mat->qrrhs) PetscCall(MatCreateVecs(A, NULL, &mat->qrrhs));
9303ba16761SJacob Faibussowitsch   if (!A->rmap->n || !A->cmap->n) PetscFunctionReturn(PETSC_SUCCESS);
9314905a7bcSToby Isaac   if (!mat->fwork) {
9324905a7bcSToby Isaac     PetscScalar dummy;
9334905a7bcSToby Isaac 
9344905a7bcSToby Isaac     mat->lfwork = -1;
9359566063dSJacob Faibussowitsch     PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF));
936792fecdfSBarry Smith     PetscCallBLAS("LAPACKgeqrf", LAPACKgeqrf_(&m, &n, mat->v, &mat->lda, mat->tau, &dummy, &mat->lfwork, &info));
9379566063dSJacob Faibussowitsch     PetscCall(PetscFPTrapPop());
9386497c311SBarry Smith     PetscCall(PetscBLASIntCast((PetscCount)(PetscRealPart(dummy)), &mat->lfwork));
9399566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(mat->lfwork, &mat->fwork));
9404905a7bcSToby Isaac   }
9419566063dSJacob Faibussowitsch   PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF));
942792fecdfSBarry Smith   PetscCallBLAS("LAPACKgeqrf", LAPACKgeqrf_(&m, &n, mat->v, &mat->lda, mat->tau, mat->fwork, &mat->lfwork, &info));
9439566063dSJacob Faibussowitsch   PetscCall(PetscFPTrapPop());
944835f2295SStefano Zampini   PetscCheck(!info, PETSC_COMM_SELF, PETSC_ERR_LIB, "Bad argument to QR factorization %" PetscBLASInt_FMT, info);
9454905a7bcSToby 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
9464905a7bcSToby Isaac   mat->rank = min;
9474905a7bcSToby Isaac 
9484396437dSToby Isaac   A->ops->solve    = MatSolve_SeqDense_QR;
9494396437dSToby Isaac   A->ops->matsolve = MatMatSolve_SeqDense_QR;
9504905a7bcSToby Isaac   A->factortype    = MAT_FACTOR_QR;
9514905a7bcSToby Isaac   if (m == n) {
9524396437dSToby Isaac     A->ops->solvetranspose    = MatSolveTranspose_SeqDense_QR;
9534396437dSToby Isaac     A->ops->matsolvetranspose = MatMatSolveTranspose_SeqDense_QR;
9544905a7bcSToby Isaac   }
9554905a7bcSToby Isaac 
9569566063dSJacob Faibussowitsch   PetscCall(PetscFree(A->solvertype));
9579566063dSJacob Faibussowitsch   PetscCall(PetscStrallocpy(MATSOLVERPETSC, &A->solvertype));
9584905a7bcSToby Isaac 
9599566063dSJacob Faibussowitsch   PetscCall(PetscLogFlops(2.0 * min * min * (max - min / 3.0)));
9603ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
9614905a7bcSToby Isaac }
9624905a7bcSToby Isaac 
963*97b17b2cSPierre Jolivet static PetscErrorCode MatQRFactorNumeric_SeqDense(Mat fact, Mat A, const MatFactorInfo *info)
964d71ae5a4SJacob Faibussowitsch {
9654905a7bcSToby Isaac   PetscFunctionBegin;
9669566063dSJacob Faibussowitsch   PetscCall(MatDuplicateNoCreate_SeqDense(fact, A, MAT_COPY_VALUES));
967*97b17b2cSPierre Jolivet   PetscUseMethod(fact, "MatQRFactor_C", (Mat, IS, const MatFactorInfo *), (fact, NULL, info));
9683ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
9694905a7bcSToby Isaac }
9704905a7bcSToby Isaac 
971d71ae5a4SJacob Faibussowitsch PetscErrorCode MatQRFactorSymbolic_SeqDense(Mat fact, Mat A, IS row, const MatFactorInfo *info)
972d71ae5a4SJacob Faibussowitsch {
9734905a7bcSToby Isaac   PetscFunctionBegin;
9744905a7bcSToby Isaac   fact->assembled    = PETSC_TRUE;
9754905a7bcSToby Isaac   fact->preallocated = PETSC_TRUE;
9769566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)fact, "MatQRFactorNumeric_C", MatQRFactorNumeric_SeqDense));
9773ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
9784905a7bcSToby Isaac }
9794905a7bcSToby Isaac 
980ca15aa20SStefano Zampini /* uses LAPACK */
981d71ae5a4SJacob Faibussowitsch PETSC_INTERN PetscErrorCode MatGetFactor_seqdense_petsc(Mat A, MatFactorType ftype, Mat *fact)
982d71ae5a4SJacob Faibussowitsch {
983db4efbfdSBarry Smith   PetscFunctionBegin;
9849566063dSJacob Faibussowitsch   PetscCall(MatCreate(PetscObjectComm((PetscObject)A), fact));
9859566063dSJacob Faibussowitsch   PetscCall(MatSetSizes(*fact, A->rmap->n, A->cmap->n, A->rmap->n, A->cmap->n));
9869566063dSJacob Faibussowitsch   PetscCall(MatSetType(*fact, MATDENSE));
98766e17bc3SBarry Smith   (*fact)->trivialsymbolic = PETSC_TRUE;
9882a350339SBarry Smith   if (ftype == MAT_FACTOR_LU || ftype == MAT_FACTOR_ILU) {
989db4efbfdSBarry Smith     (*fact)->ops->lufactorsymbolic  = MatLUFactorSymbolic_SeqDense;
9902a350339SBarry Smith     (*fact)->ops->ilufactorsymbolic = MatLUFactorSymbolic_SeqDense;
991bf5a80bcSToby Isaac   } else if (ftype == MAT_FACTOR_CHOLESKY || ftype == MAT_FACTOR_ICC) {
992db4efbfdSBarry Smith     (*fact)->ops->choleskyfactorsymbolic = MatCholeskyFactorSymbolic_SeqDense;
993bf5a80bcSToby Isaac   } else if (ftype == MAT_FACTOR_QR) {
994f4f49eeaSPierre Jolivet     PetscCall(PetscObjectComposeFunction((PetscObject)*fact, "MatQRFactorSymbolic_C", MatQRFactorSymbolic_SeqDense));
995db4efbfdSBarry Smith   }
996d5f3da31SBarry Smith   (*fact)->factortype = ftype;
99700c67f3bSHong Zhang 
9989566063dSJacob Faibussowitsch   PetscCall(PetscFree((*fact)->solvertype));
9999566063dSJacob Faibussowitsch   PetscCall(PetscStrallocpy(MATSOLVERPETSC, &(*fact)->solvertype));
10009566063dSJacob Faibussowitsch   PetscCall(PetscStrallocpy(MATORDERINGEXTERNAL, (char **)&(*fact)->preferredordering[MAT_FACTOR_LU]));
10019566063dSJacob Faibussowitsch   PetscCall(PetscStrallocpy(MATORDERINGEXTERNAL, (char **)&(*fact)->preferredordering[MAT_FACTOR_ILU]));
10029566063dSJacob Faibussowitsch   PetscCall(PetscStrallocpy(MATORDERINGEXTERNAL, (char **)&(*fact)->preferredordering[MAT_FACTOR_CHOLESKY]));
10039566063dSJacob Faibussowitsch   PetscCall(PetscStrallocpy(MATORDERINGEXTERNAL, (char **)&(*fact)->preferredordering[MAT_FACTOR_ICC]));
10043ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1005db4efbfdSBarry Smith }
1006db4efbfdSBarry Smith 
1007d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatSOR_SeqDense(Mat A, Vec bb, PetscReal omega, MatSORType flag, PetscReal shift, PetscInt its, PetscInt lits, Vec xx)
1008d71ae5a4SJacob Faibussowitsch {
1009c0bbcb79SLois Curfman McInnes   Mat_SeqDense      *mat = (Mat_SeqDense *)A->data;
1010d9ca1df4SBarry Smith   PetscScalar       *x, *v = mat->v, zero = 0.0, xt;
1011d9ca1df4SBarry Smith   const PetscScalar *b;
1012d0f46423SBarry Smith   PetscInt           m = A->rmap->n, i;
101323fff9afSBarry Smith   PetscBLASInt       o = 1, bm = 0;
1014289bc588SBarry Smith 
10153a40ed3dSBarry Smith   PetscFunctionBegin;
101647d993e7Ssuyashtn #if defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
101708401ef6SPierre Jolivet   PetscCheck(A->offloadmask != PETSC_OFFLOAD_GPU, PETSC_COMM_SELF, PETSC_ERR_SUP, "Not implemented");
1018ca15aa20SStefano Zampini #endif
1019422a814eSBarry Smith   if (shift == -1) shift = 0.0; /* negative shift indicates do not error on zero diagonal; this code never zeros on zero diagonal */
10209566063dSJacob Faibussowitsch   PetscCall(PetscBLASIntCast(m, &bm));
1021289bc588SBarry Smith   if (flag & SOR_ZERO_INITIAL_GUESS) {
10223bffc371SBarry Smith     /* this is a hack fix, should have another version without the second BLASdotu */
10239566063dSJacob Faibussowitsch     PetscCall(VecSet(xx, zero));
1024289bc588SBarry Smith   }
10259566063dSJacob Faibussowitsch   PetscCall(VecGetArray(xx, &x));
10269566063dSJacob Faibussowitsch   PetscCall(VecGetArrayRead(bb, &b));
1027b965ef7fSBarry Smith   its = its * lits;
102808401ef6SPierre 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);
1029289bc588SBarry Smith   while (its--) {
1030fccaa45eSBarry Smith     if (flag & SOR_FORWARD_SWEEP || flag & SOR_LOCAL_FORWARD_SWEEP) {
1031289bc588SBarry Smith       for (i = 0; i < m; i++) {
1032792fecdfSBarry Smith         PetscCallBLAS("BLASdotu", xt = b[i] - BLASdotu_(&bm, v + i, &bm, x, &o));
1033883424caSPierre Jolivet         x[i] = (1. - omega) * x[i] + (xt + v[i + i * m] * x[i]) * omega / (v[i + i * m] + shift);
1034289bc588SBarry Smith       }
1035289bc588SBarry Smith     }
1036fccaa45eSBarry Smith     if (flag & SOR_BACKWARD_SWEEP || flag & SOR_LOCAL_BACKWARD_SWEEP) {
1037289bc588SBarry Smith       for (i = m - 1; i >= 0; i--) {
1038792fecdfSBarry Smith         PetscCallBLAS("BLASdotu", xt = b[i] - BLASdotu_(&bm, v + i, &bm, x, &o));
1039883424caSPierre Jolivet         x[i] = (1. - omega) * x[i] + (xt + v[i + i * m] * x[i]) * omega / (v[i + i * m] + shift);
1040289bc588SBarry Smith       }
1041289bc588SBarry Smith     }
1042289bc588SBarry Smith   }
10439566063dSJacob Faibussowitsch   PetscCall(VecRestoreArrayRead(bb, &b));
10449566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(xx, &x));
10453ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1046289bc588SBarry Smith }
1047289bc588SBarry Smith 
10480be0d8bdSHansol Suh static PetscErrorCode MatMultColumnRangeKernel_SeqDense(Mat A, Vec xx, Vec yy, PetscInt c_start, PetscInt c_end, PetscBool trans, PetscBool herm)
1049d71ae5a4SJacob Faibussowitsch {
1050c0bbcb79SLois Curfman McInnes   Mat_SeqDense      *mat = (Mat_SeqDense *)A->data;
1051d9ca1df4SBarry Smith   PetscScalar       *y, _DOne = 1.0, _DZero = 0.0;
10520805154bSBarry Smith   PetscBLASInt       m, n, _One             = 1;
1053d9ca1df4SBarry Smith   const PetscScalar *v = mat->v, *x;
10543a40ed3dSBarry Smith 
10553a40ed3dSBarry Smith   PetscFunctionBegin;
10569566063dSJacob Faibussowitsch   PetscCall(PetscBLASIntCast(A->rmap->n, &m));
10570be0d8bdSHansol Suh   PetscCall(PetscBLASIntCast(c_end - c_start, &n));
10589566063dSJacob Faibussowitsch   PetscCall(VecGetArrayRead(xx, &x));
10599566063dSJacob Faibussowitsch   PetscCall(VecGetArrayWrite(yy, &y));
10600be0d8bdSHansol Suh   if (!m || !n) {
10615ac36cfcSBarry Smith     PetscBLASInt i;
1062459e8d23SBlanca Mellado Pinto     if (trans)
1063459e8d23SBlanca Mellado Pinto       for (i = 0; i < n; i++) y[i] = 0.0;
1064459e8d23SBlanca Mellado Pinto     else
10655ac36cfcSBarry Smith       for (i = 0; i < m; i++) y[i] = 0.0;
10665ac36cfcSBarry Smith   } else {
1067459e8d23SBlanca Mellado Pinto     if (trans) {
10680be0d8bdSHansol Suh       if (herm) PetscCallBLAS("BLASgemv", BLASgemv_("C", &m, &n, &_DOne, v + c_start * mat->lda, &mat->lda, x, &_One, &_DZero, y + c_start, &_One));
10690be0d8bdSHansol Suh       else PetscCallBLAS("BLASgemv", BLASgemv_("T", &m, &n, &_DOne, v + c_start * mat->lda, &mat->lda, x, &_One, &_DZero, y + c_start, &_One));
1070459e8d23SBlanca Mellado Pinto     } else {
10710be0d8bdSHansol Suh       PetscCallBLAS("BLASgemv", BLASgemv_("N", &m, &n, &_DOne, v + c_start * mat->lda, &mat->lda, x + c_start, &_One, &_DZero, y, &_One));
1072459e8d23SBlanca Mellado Pinto     }
10730be0d8bdSHansol Suh     PetscCall(PetscLogFlops(2.0 * m * n - n));
10745ac36cfcSBarry Smith   }
10759566063dSJacob Faibussowitsch   PetscCall(VecRestoreArrayRead(xx, &x));
10769566063dSJacob Faibussowitsch   PetscCall(VecRestoreArrayWrite(yy, &y));
10773ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1078289bc588SBarry Smith }
10796ee01492SSatish Balay 
10800be0d8bdSHansol Suh PetscErrorCode MatMultHermitianTransposeColumnRange_SeqDense(Mat A, Vec xx, Vec yy, PetscInt c_start, PetscInt c_end)
10810be0d8bdSHansol Suh {
10820be0d8bdSHansol Suh   PetscFunctionBegin;
10830be0d8bdSHansol Suh   PetscCall(MatMultColumnRangeKernel_SeqDense(A, xx, yy, c_start, c_end, PETSC_TRUE, PETSC_TRUE));
10840be0d8bdSHansol Suh   PetscFunctionReturn(PETSC_SUCCESS);
10850be0d8bdSHansol Suh }
10860be0d8bdSHansol Suh 
1087459e8d23SBlanca Mellado Pinto PetscErrorCode MatMult_SeqDense(Mat A, Vec xx, Vec yy)
1088459e8d23SBlanca Mellado Pinto {
1089459e8d23SBlanca Mellado Pinto   PetscFunctionBegin;
10900be0d8bdSHansol Suh   PetscCall(MatMultColumnRangeKernel_SeqDense(A, xx, yy, 0, A->cmap->n, PETSC_FALSE, PETSC_FALSE));
1091459e8d23SBlanca Mellado Pinto   PetscFunctionReturn(PETSC_SUCCESS);
1092459e8d23SBlanca Mellado Pinto }
1093459e8d23SBlanca Mellado Pinto 
1094459e8d23SBlanca Mellado Pinto PetscErrorCode MatMultTranspose_SeqDense(Mat A, Vec xx, Vec yy)
1095459e8d23SBlanca Mellado Pinto {
1096459e8d23SBlanca Mellado Pinto   PetscFunctionBegin;
10970be0d8bdSHansol Suh   PetscCall(MatMultColumnRangeKernel_SeqDense(A, xx, yy, 0, A->cmap->n, PETSC_TRUE, PETSC_FALSE));
1098459e8d23SBlanca Mellado Pinto   PetscFunctionReturn(PETSC_SUCCESS);
1099459e8d23SBlanca Mellado Pinto }
1100459e8d23SBlanca Mellado Pinto 
1101459e8d23SBlanca Mellado Pinto PetscErrorCode MatMultHermitianTranspose_SeqDense(Mat A, Vec xx, Vec yy)
1102459e8d23SBlanca Mellado Pinto {
1103459e8d23SBlanca Mellado Pinto   PetscFunctionBegin;
11040be0d8bdSHansol Suh   PetscCall(MatMultColumnRangeKernel_SeqDense(A, xx, yy, 0, A->cmap->n, PETSC_TRUE, PETSC_TRUE));
1105459e8d23SBlanca Mellado Pinto   PetscFunctionReturn(PETSC_SUCCESS);
1106459e8d23SBlanca Mellado Pinto }
1107459e8d23SBlanca Mellado Pinto 
11080be0d8bdSHansol Suh static PetscErrorCode MatMultAddColumnRangeKernel_SeqDense(Mat A, Vec xx, Vec zz, Vec yy, PetscInt c_start, PetscInt c_end, PetscBool trans, PetscBool herm)
1109d71ae5a4SJacob Faibussowitsch {
1110c0bbcb79SLois Curfman McInnes   Mat_SeqDense      *mat = (Mat_SeqDense *)A->data;
1111d9ca1df4SBarry Smith   const PetscScalar *v   = mat->v, *x;
1112d9ca1df4SBarry Smith   PetscScalar       *y, _DOne = 1.0;
11130805154bSBarry Smith   PetscBLASInt       m, n, _One = 1;
11143a40ed3dSBarry Smith 
11153a40ed3dSBarry Smith   PetscFunctionBegin;
11169566063dSJacob Faibussowitsch   PetscCall(PetscBLASIntCast(A->rmap->n, &m));
11170be0d8bdSHansol Suh   PetscCall(PetscBLASIntCast(c_end - c_start, &n));
11189566063dSJacob Faibussowitsch   PetscCall(VecCopy(zz, yy));
11190be0d8bdSHansol Suh   if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS);
11209566063dSJacob Faibussowitsch   PetscCall(VecGetArray(yy, &y));
1121459e8d23SBlanca Mellado Pinto   PetscCall(VecGetArrayRead(xx, &x));
1122459e8d23SBlanca Mellado Pinto   if (trans) {
11230be0d8bdSHansol Suh     if (herm) PetscCallBLAS("BLASgemv", BLASgemv_("C", &m, &n, &_DOne, v + c_start * mat->lda, &mat->lda, x, &_One, &_DOne, y + c_start, &_One));
11240be0d8bdSHansol Suh     else PetscCallBLAS("BLASgemv", BLASgemv_("T", &m, &n, &_DOne, v + c_start * mat->lda, &mat->lda, x, &_One, &_DOne, y + c_start, &_One));
1125459e8d23SBlanca Mellado Pinto   } else {
11260be0d8bdSHansol Suh     PetscCallBLAS("BLASgemv", BLASgemv_("N", &m, &n, &_DOne, v + c_start * mat->lda, &mat->lda, x + c_start, &_One, &_DOne, y, &_One));
1127459e8d23SBlanca Mellado Pinto   }
11289566063dSJacob Faibussowitsch   PetscCall(VecRestoreArrayRead(xx, &x));
11299566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(yy, &y));
11300be0d8bdSHansol Suh   PetscCall(PetscLogFlops(2.0 * m * n));
11310be0d8bdSHansol Suh   PetscFunctionReturn(PETSC_SUCCESS);
11320be0d8bdSHansol Suh }
11330be0d8bdSHansol Suh 
11340be0d8bdSHansol Suh PetscErrorCode MatMultAddColumnRange_SeqDense(Mat A, Vec xx, Vec zz, Vec yy, PetscInt c_start, PetscInt c_end)
11350be0d8bdSHansol Suh {
11360be0d8bdSHansol Suh   PetscFunctionBegin;
11370be0d8bdSHansol Suh   PetscCall(MatMultAddColumnRangeKernel_SeqDense(A, xx, zz, yy, c_start, c_end, PETSC_FALSE, PETSC_FALSE));
11380be0d8bdSHansol Suh   PetscFunctionReturn(PETSC_SUCCESS);
11390be0d8bdSHansol Suh }
11400be0d8bdSHansol Suh 
11410be0d8bdSHansol Suh PetscErrorCode MatMultHermitianTransposeAddColumnRange_SeqDense(Mat A, Vec xx, Vec zz, Vec yy, PetscInt c_start, PetscInt c_end)
11420be0d8bdSHansol Suh {
11430be0d8bdSHansol Suh   PetscFunctionBegin;
11440be0d8bdSHansol Suh   PetscMPIInt rank;
11450be0d8bdSHansol Suh   PetscCallMPI(MPI_Comm_rank(MPI_COMM_WORLD, &rank));
11460be0d8bdSHansol Suh   PetscCall(MatMultAddColumnRangeKernel_SeqDense(A, xx, zz, yy, c_start, c_end, PETSC_TRUE, PETSC_TRUE));
11473ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1148289bc588SBarry Smith }
11496ee01492SSatish Balay 
1150459e8d23SBlanca Mellado Pinto PetscErrorCode MatMultAdd_SeqDense(Mat A, Vec xx, Vec zz, Vec yy)
1151459e8d23SBlanca Mellado Pinto {
1152459e8d23SBlanca Mellado Pinto   PetscFunctionBegin;
11530be0d8bdSHansol Suh   PetscCall(MatMultAddColumnRangeKernel_SeqDense(A, xx, zz, yy, 0, A->cmap->n, PETSC_FALSE, PETSC_FALSE));
1154459e8d23SBlanca Mellado Pinto   PetscFunctionReturn(PETSC_SUCCESS);
1155459e8d23SBlanca Mellado Pinto }
1156459e8d23SBlanca Mellado Pinto 
1157d71ae5a4SJacob Faibussowitsch PetscErrorCode MatMultTransposeAdd_SeqDense(Mat A, Vec xx, Vec zz, Vec yy)
1158d71ae5a4SJacob Faibussowitsch {
11593a40ed3dSBarry Smith   PetscFunctionBegin;
11600be0d8bdSHansol Suh   PetscCall(MatMultAddColumnRangeKernel_SeqDense(A, xx, zz, yy, 0, A->cmap->n, PETSC_TRUE, PETSC_FALSE));
1161459e8d23SBlanca Mellado Pinto   PetscFunctionReturn(PETSC_SUCCESS);
1162459e8d23SBlanca Mellado Pinto }
1163459e8d23SBlanca Mellado Pinto 
1164459e8d23SBlanca Mellado Pinto PetscErrorCode MatMultHermitianTransposeAdd_SeqDense(Mat A, Vec xx, Vec zz, Vec yy)
1165459e8d23SBlanca Mellado Pinto {
1166459e8d23SBlanca Mellado Pinto   PetscFunctionBegin;
11670be0d8bdSHansol Suh   PetscCall(MatMultAddColumnRangeKernel_SeqDense(A, xx, zz, yy, 0, A->cmap->n, PETSC_TRUE, PETSC_TRUE));
11683ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1169289bc588SBarry Smith }
1170289bc588SBarry Smith 
1171d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatGetRow_SeqDense(Mat A, PetscInt row, PetscInt *ncols, PetscInt **cols, PetscScalar **vals)
1172d71ae5a4SJacob Faibussowitsch {
1173c0bbcb79SLois Curfman McInnes   Mat_SeqDense *mat = (Mat_SeqDense *)A->data;
117413f74950SBarry Smith   PetscInt      i;
117567e560aaSBarry Smith 
11763a40ed3dSBarry Smith   PetscFunctionBegin;
1177c3e1b152SPierre Jolivet   if (ncols) *ncols = A->cmap->n;
1178289bc588SBarry Smith   if (cols) {
11799566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(A->cmap->n, cols));
1180d0f46423SBarry Smith     for (i = 0; i < A->cmap->n; i++) (*cols)[i] = i;
1181289bc588SBarry Smith   }
1182289bc588SBarry Smith   if (vals) {
1183ca15aa20SStefano Zampini     const PetscScalar *v;
1184ca15aa20SStefano Zampini 
11859566063dSJacob Faibussowitsch     PetscCall(MatDenseGetArrayRead(A, &v));
11869566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(A->cmap->n, vals));
1187ca15aa20SStefano Zampini     v += row;
11889371c9d4SSatish Balay     for (i = 0; i < A->cmap->n; i++) {
11899371c9d4SSatish Balay       (*vals)[i] = *v;
11909371c9d4SSatish Balay       v += mat->lda;
11919371c9d4SSatish Balay     }
11929566063dSJacob Faibussowitsch     PetscCall(MatDenseRestoreArrayRead(A, &v));
1193289bc588SBarry Smith   }
11943ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1195289bc588SBarry Smith }
11966ee01492SSatish Balay 
1197d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatRestoreRow_SeqDense(Mat A, PetscInt row, PetscInt *ncols, PetscInt **cols, PetscScalar **vals)
1198d71ae5a4SJacob Faibussowitsch {
1199606d414cSSatish Balay   PetscFunctionBegin;
12009566063dSJacob Faibussowitsch   if (cols) PetscCall(PetscFree(*cols));
12019566063dSJacob Faibussowitsch   if (vals) PetscCall(PetscFree(*vals));
12023ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1203289bc588SBarry Smith }
12042ef1f0ffSBarry Smith 
1205d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatSetValues_SeqDense(Mat A, PetscInt m, const PetscInt indexm[], PetscInt n, const PetscInt indexn[], const PetscScalar v[], InsertMode addv)
1206d71ae5a4SJacob Faibussowitsch {
1207c0bbcb79SLois Curfman McInnes   Mat_SeqDense *mat = (Mat_SeqDense *)A->data;
1208ca15aa20SStefano Zampini   PetscScalar  *av;
120913f74950SBarry Smith   PetscInt      i, j, idx = 0;
121047d993e7Ssuyashtn #if defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
1211c70f7ee4SJunchao Zhang   PetscOffloadMask oldf;
1212ca15aa20SStefano Zampini #endif
1213d6dfbf8fSBarry Smith 
12143a40ed3dSBarry Smith   PetscFunctionBegin;
12159566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArray(A, &av));
1216289bc588SBarry Smith   if (!mat->roworiented) {
1217dbb450caSBarry Smith     if (addv == INSERT_VALUES) {
1218289bc588SBarry Smith       for (j = 0; j < n; j++) {
12199371c9d4SSatish Balay         if (indexn[j] < 0) {
12209371c9d4SSatish Balay           idx += m;
12219371c9d4SSatish Balay           continue;
12229371c9d4SSatish Balay         }
12236bdcaf15SBarry 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);
1224289bc588SBarry Smith         for (i = 0; i < m; i++) {
12259371c9d4SSatish Balay           if (indexm[i] < 0) {
12269371c9d4SSatish Balay             idx++;
12279371c9d4SSatish Balay             continue;
12289371c9d4SSatish Balay           }
12296bdcaf15SBarry 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);
12308c4a67a0SStefano Zampini           av[indexn[j] * mat->lda + indexm[i]] = v ? v[idx++] : (idx++, 0.0);
1231289bc588SBarry Smith         }
1232289bc588SBarry Smith       }
12330be0d8bdSHansol Suh     } else {
1234289bc588SBarry Smith       for (j = 0; j < n; j++) {
12359371c9d4SSatish Balay         if (indexn[j] < 0) {
12369371c9d4SSatish Balay           idx += m;
12379371c9d4SSatish Balay           continue;
12389371c9d4SSatish Balay         }
12396bdcaf15SBarry 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);
1240289bc588SBarry Smith         for (i = 0; i < m; i++) {
12419371c9d4SSatish Balay           if (indexm[i] < 0) {
12429371c9d4SSatish Balay             idx++;
12439371c9d4SSatish Balay             continue;
12449371c9d4SSatish Balay           }
12456bdcaf15SBarry 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);
12468c4a67a0SStefano Zampini           av[indexn[j] * mat->lda + indexm[i]] += v ? v[idx++] : (idx++, 0.0);
1247289bc588SBarry Smith         }
1248289bc588SBarry Smith       }
1249289bc588SBarry Smith     }
12503a40ed3dSBarry Smith   } else {
1251dbb450caSBarry Smith     if (addv == INSERT_VALUES) {
1252e8d4e0b9SBarry Smith       for (i = 0; i < m; i++) {
12539371c9d4SSatish Balay         if (indexm[i] < 0) {
12549371c9d4SSatish Balay           idx += n;
12559371c9d4SSatish Balay           continue;
12569371c9d4SSatish Balay         }
12576bdcaf15SBarry 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);
1258e8d4e0b9SBarry Smith         for (j = 0; j < n; j++) {
12599371c9d4SSatish Balay           if (indexn[j] < 0) {
12609371c9d4SSatish Balay             idx++;
12619371c9d4SSatish Balay             continue;
12629371c9d4SSatish Balay           }
12636bdcaf15SBarry 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);
12648c4a67a0SStefano Zampini           av[indexn[j] * mat->lda + indexm[i]] = v ? v[idx++] : (idx++, 0.0);
1265e8d4e0b9SBarry Smith         }
1266e8d4e0b9SBarry Smith       }
12670be0d8bdSHansol Suh     } else {
1268289bc588SBarry Smith       for (i = 0; i < m; i++) {
12699371c9d4SSatish Balay         if (indexm[i] < 0) {
12709371c9d4SSatish Balay           idx += n;
12719371c9d4SSatish Balay           continue;
12729371c9d4SSatish Balay         }
12736bdcaf15SBarry 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);
1274289bc588SBarry Smith         for (j = 0; j < n; j++) {
12759371c9d4SSatish Balay           if (indexn[j] < 0) {
12769371c9d4SSatish Balay             idx++;
12779371c9d4SSatish Balay             continue;
12789371c9d4SSatish Balay           }
12796bdcaf15SBarry 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);
12808c4a67a0SStefano Zampini           av[indexn[j] * mat->lda + indexm[i]] += v ? v[idx++] : (idx++, 0.0);
1281289bc588SBarry Smith         }
1282289bc588SBarry Smith       }
1283289bc588SBarry Smith     }
1284e8d4e0b9SBarry Smith   }
1285ca15aa20SStefano Zampini   /* hack to prevent unneeded copy to the GPU while returning the array */
128647d993e7Ssuyashtn #if defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
1287c70f7ee4SJunchao Zhang   oldf           = A->offloadmask;
1288c70f7ee4SJunchao Zhang   A->offloadmask = PETSC_OFFLOAD_GPU;
1289ca15aa20SStefano Zampini #endif
12909566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArray(A, &av));
129147d993e7Ssuyashtn #if defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
1292c70f7ee4SJunchao Zhang   A->offloadmask = (oldf == PETSC_OFFLOAD_UNALLOCATED ? PETSC_OFFLOAD_UNALLOCATED : PETSC_OFFLOAD_CPU);
1293ca15aa20SStefano Zampini #endif
12943ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1295289bc588SBarry Smith }
1296e8d4e0b9SBarry Smith 
1297d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatGetValues_SeqDense(Mat A, PetscInt m, const PetscInt indexm[], PetscInt n, const PetscInt indexn[], PetscScalar v[])
1298d71ae5a4SJacob Faibussowitsch {
1299ae80bb75SLois Curfman McInnes   Mat_SeqDense      *mat = (Mat_SeqDense *)A->data;
1300ca15aa20SStefano Zampini   const PetscScalar *vv;
130113f74950SBarry Smith   PetscInt           i, j;
1302ae80bb75SLois Curfman McInnes 
13033a40ed3dSBarry Smith   PetscFunctionBegin;
13049566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArrayRead(A, &vv));
1305ae80bb75SLois Curfman McInnes   /* row-oriented output */
1306ae80bb75SLois Curfman McInnes   for (i = 0; i < m; i++) {
13079371c9d4SSatish Balay     if (indexm[i] < 0) {
13089371c9d4SSatish Balay       v += n;
13099371c9d4SSatish Balay       continue;
13109371c9d4SSatish Balay     }
131108401ef6SPierre 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);
1312ae80bb75SLois Curfman McInnes     for (j = 0; j < n; j++) {
13139371c9d4SSatish Balay       if (indexn[j] < 0) {
13149371c9d4SSatish Balay         v++;
13159371c9d4SSatish Balay         continue;
13169371c9d4SSatish Balay       }
131708401ef6SPierre 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);
1318ca15aa20SStefano Zampini       *v++ = vv[indexn[j] * mat->lda + indexm[i]];
1319ae80bb75SLois Curfman McInnes     }
1320ae80bb75SLois Curfman McInnes   }
13219566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArrayRead(A, &vv));
13223ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1323ae80bb75SLois Curfman McInnes }
1324ae80bb75SLois Curfman McInnes 
1325d71ae5a4SJacob Faibussowitsch PetscErrorCode MatView_Dense_Binary(Mat mat, PetscViewer viewer)
1326d71ae5a4SJacob Faibussowitsch {
13278491ab44SLisandro Dalcin   PetscBool          skipHeader;
13288491ab44SLisandro Dalcin   PetscViewerFormat  format;
13293e1d7bceSPierre Jolivet   PetscInt           header[4], M, N, m, lda, i, j;
13303e1d7bceSPierre Jolivet   PetscCount         k;
13318491ab44SLisandro Dalcin   const PetscScalar *v;
13328491ab44SLisandro Dalcin   PetscScalar       *vwork;
1333aabbc4fbSShri Abhyankar 
1334aabbc4fbSShri Abhyankar   PetscFunctionBegin;
13359566063dSJacob Faibussowitsch   PetscCall(PetscViewerSetUp(viewer));
13369566063dSJacob Faibussowitsch   PetscCall(PetscViewerBinaryGetSkipHeader(viewer, &skipHeader));
13379566063dSJacob Faibussowitsch   PetscCall(PetscViewerGetFormat(viewer, &format));
13388491ab44SLisandro Dalcin   if (skipHeader) format = PETSC_VIEWER_NATIVE;
1339aabbc4fbSShri Abhyankar 
13409566063dSJacob Faibussowitsch   PetscCall(MatGetSize(mat, &M, &N));
13418491ab44SLisandro Dalcin 
13428491ab44SLisandro Dalcin   /* write matrix header */
13439371c9d4SSatish Balay   header[0] = MAT_FILE_CLASSID;
13449371c9d4SSatish Balay   header[1] = M;
13459371c9d4SSatish Balay   header[2] = N;
13468491ab44SLisandro Dalcin   header[3] = (format == PETSC_VIEWER_NATIVE) ? MATRIX_BINARY_FORMAT_DENSE : M * N;
13479566063dSJacob Faibussowitsch   if (!skipHeader) PetscCall(PetscViewerBinaryWrite(viewer, header, 4, PETSC_INT));
13488491ab44SLisandro Dalcin 
13499566063dSJacob Faibussowitsch   PetscCall(MatGetLocalSize(mat, &m, NULL));
13508491ab44SLisandro Dalcin   if (format != PETSC_VIEWER_NATIVE) {
13518491ab44SLisandro Dalcin     PetscInt nnz = m * N, *iwork;
13528491ab44SLisandro Dalcin     /* store row lengths for each row */
13539566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(nnz, &iwork));
13548491ab44SLisandro Dalcin     for (i = 0; i < m; i++) iwork[i] = N;
13559566063dSJacob Faibussowitsch     PetscCall(PetscViewerBinaryWriteAll(viewer, iwork, m, PETSC_DETERMINE, PETSC_DETERMINE, PETSC_INT));
13568491ab44SLisandro Dalcin     /* store column indices (zero start index) */
13578491ab44SLisandro Dalcin     for (k = 0, i = 0; i < m; i++)
13589371c9d4SSatish Balay       for (j = 0; j < N; j++, k++) iwork[k] = j;
13599566063dSJacob Faibussowitsch     PetscCall(PetscViewerBinaryWriteAll(viewer, iwork, nnz, PETSC_DETERMINE, PETSC_DETERMINE, PETSC_INT));
13609566063dSJacob Faibussowitsch     PetscCall(PetscFree(iwork));
13618491ab44SLisandro Dalcin   }
13628491ab44SLisandro Dalcin   /* store matrix values as a dense matrix in row major order */
13639566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(m * N, &vwork));
13649566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArrayRead(mat, &v));
13659566063dSJacob Faibussowitsch   PetscCall(MatDenseGetLDA(mat, &lda));
13668491ab44SLisandro Dalcin   for (k = 0, i = 0; i < m; i++)
13673e1d7bceSPierre Jolivet     for (j = 0; j < N; j++, k++) vwork[k] = v[i + (size_t)lda * j];
13689566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArrayRead(mat, &v));
13699566063dSJacob Faibussowitsch   PetscCall(PetscViewerBinaryWriteAll(viewer, vwork, m * N, PETSC_DETERMINE, PETSC_DETERMINE, PETSC_SCALAR));
13709566063dSJacob Faibussowitsch   PetscCall(PetscFree(vwork));
13713ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
13728491ab44SLisandro Dalcin }
13738491ab44SLisandro Dalcin 
1374d71ae5a4SJacob Faibussowitsch PetscErrorCode MatLoad_Dense_Binary(Mat mat, PetscViewer viewer)
1375d71ae5a4SJacob Faibussowitsch {
13768491ab44SLisandro Dalcin   PetscBool    skipHeader;
13778491ab44SLisandro Dalcin   PetscInt     header[4], M, N, m, nz, lda, i, j, k;
13788491ab44SLisandro Dalcin   PetscInt     rows, cols;
13798491ab44SLisandro Dalcin   PetscScalar *v, *vwork;
13808491ab44SLisandro Dalcin 
13818491ab44SLisandro Dalcin   PetscFunctionBegin;
13829566063dSJacob Faibussowitsch   PetscCall(PetscViewerSetUp(viewer));
13839566063dSJacob Faibussowitsch   PetscCall(PetscViewerBinaryGetSkipHeader(viewer, &skipHeader));
13848491ab44SLisandro Dalcin 
13858491ab44SLisandro Dalcin   if (!skipHeader) {
13869566063dSJacob Faibussowitsch     PetscCall(PetscViewerBinaryRead(viewer, header, 4, NULL, PETSC_INT));
138708401ef6SPierre Jolivet     PetscCheck(header[0] == MAT_FILE_CLASSID, PetscObjectComm((PetscObject)viewer), PETSC_ERR_FILE_UNEXPECTED, "Not a matrix object in file");
13889371c9d4SSatish Balay     M = header[1];
13899371c9d4SSatish Balay     N = header[2];
139008401ef6SPierre Jolivet     PetscCheck(M >= 0, PetscObjectComm((PetscObject)viewer), PETSC_ERR_FILE_UNEXPECTED, "Matrix row size (%" PetscInt_FMT ") in file is negative", M);
139108401ef6SPierre Jolivet     PetscCheck(N >= 0, PetscObjectComm((PetscObject)viewer), PETSC_ERR_FILE_UNEXPECTED, "Matrix column size (%" PetscInt_FMT ") in file is negative", N);
13928491ab44SLisandro Dalcin     nz = header[3];
1393aed4548fSBarry Smith     PetscCheck(nz == MATRIX_BINARY_FORMAT_DENSE || nz >= 0, PetscObjectComm((PetscObject)viewer), PETSC_ERR_FILE_UNEXPECTED, "Unknown matrix format %" PetscInt_FMT " in file", nz);
1394aabbc4fbSShri Abhyankar   } else {
13959566063dSJacob Faibussowitsch     PetscCall(MatGetSize(mat, &M, &N));
1396aed4548fSBarry 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");
13978491ab44SLisandro Dalcin     nz = MATRIX_BINARY_FORMAT_DENSE;
1398e6324fbbSBarry Smith   }
1399aabbc4fbSShri Abhyankar 
14008491ab44SLisandro Dalcin   /* setup global sizes if not set */
14018491ab44SLisandro Dalcin   if (mat->rmap->N < 0) mat->rmap->N = M;
14028491ab44SLisandro Dalcin   if (mat->cmap->N < 0) mat->cmap->N = N;
14039566063dSJacob Faibussowitsch   PetscCall(MatSetUp(mat));
14048491ab44SLisandro Dalcin   /* check if global sizes are correct */
14059566063dSJacob Faibussowitsch   PetscCall(MatGetSize(mat, &rows, &cols));
1406aed4548fSBarry 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);
1407aabbc4fbSShri Abhyankar 
14089566063dSJacob Faibussowitsch   PetscCall(MatGetSize(mat, NULL, &N));
14099566063dSJacob Faibussowitsch   PetscCall(MatGetLocalSize(mat, &m, NULL));
14109566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArray(mat, &v));
14119566063dSJacob Faibussowitsch   PetscCall(MatDenseGetLDA(mat, &lda));
14128491ab44SLisandro Dalcin   if (nz == MATRIX_BINARY_FORMAT_DENSE) { /* matrix in file is dense format */
14133e1d7bceSPierre Jolivet     PetscCount nnz = (size_t)m * N;
14148491ab44SLisandro Dalcin     /* read in matrix values */
14159566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(nnz, &vwork));
14169566063dSJacob Faibussowitsch     PetscCall(PetscViewerBinaryReadAll(viewer, vwork, nnz, PETSC_DETERMINE, PETSC_DETERMINE, PETSC_SCALAR));
14178491ab44SLisandro Dalcin     /* store values in column major order */
14188491ab44SLisandro Dalcin     for (j = 0; j < N; j++)
14193e1d7bceSPierre Jolivet       for (i = 0; i < m; i++) v[i + (size_t)lda * j] = vwork[(size_t)i * N + j];
14209566063dSJacob Faibussowitsch     PetscCall(PetscFree(vwork));
14218491ab44SLisandro Dalcin   } else { /* matrix in file is sparse format */
14228491ab44SLisandro Dalcin     PetscInt nnz = 0, *rlens, *icols;
14238491ab44SLisandro Dalcin     /* read in row lengths */
14249566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(m, &rlens));
14259566063dSJacob Faibussowitsch     PetscCall(PetscViewerBinaryReadAll(viewer, rlens, m, PETSC_DETERMINE, PETSC_DETERMINE, PETSC_INT));
14268491ab44SLisandro Dalcin     for (i = 0; i < m; i++) nnz += rlens[i];
14278491ab44SLisandro Dalcin     /* read in column indices and values */
14289566063dSJacob Faibussowitsch     PetscCall(PetscMalloc2(nnz, &icols, nnz, &vwork));
14299566063dSJacob Faibussowitsch     PetscCall(PetscViewerBinaryReadAll(viewer, icols, nnz, PETSC_DETERMINE, PETSC_DETERMINE, PETSC_INT));
14309566063dSJacob Faibussowitsch     PetscCall(PetscViewerBinaryReadAll(viewer, vwork, nnz, PETSC_DETERMINE, PETSC_DETERMINE, PETSC_SCALAR));
14318491ab44SLisandro Dalcin     /* store values in column major order */
14328491ab44SLisandro Dalcin     for (k = 0, i = 0; i < m; i++)
14339371c9d4SSatish Balay       for (j = 0; j < rlens[i]; j++, k++) v[i + lda * icols[k]] = vwork[k];
14349566063dSJacob Faibussowitsch     PetscCall(PetscFree(rlens));
14359566063dSJacob Faibussowitsch     PetscCall(PetscFree2(icols, vwork));
1436aabbc4fbSShri Abhyankar   }
14379566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArray(mat, &v));
14389566063dSJacob Faibussowitsch   PetscCall(MatAssemblyBegin(mat, MAT_FINAL_ASSEMBLY));
14399566063dSJacob Faibussowitsch   PetscCall(MatAssemblyEnd(mat, MAT_FINAL_ASSEMBLY));
14403ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1441aabbc4fbSShri Abhyankar }
1442aabbc4fbSShri Abhyankar 
144366976f2fSJacob Faibussowitsch static PetscErrorCode MatLoad_SeqDense(Mat newMat, PetscViewer viewer)
1444d71ae5a4SJacob Faibussowitsch {
1445eb91f321SVaclav Hapla   PetscBool isbinary, ishdf5;
1446eb91f321SVaclav Hapla 
1447eb91f321SVaclav Hapla   PetscFunctionBegin;
1448eb91f321SVaclav Hapla   PetscValidHeaderSpecific(newMat, MAT_CLASSID, 1);
1449eb91f321SVaclav Hapla   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
1450eb91f321SVaclav Hapla   /* force binary viewer to load .info file if it has not yet done so */
14519566063dSJacob Faibussowitsch   PetscCall(PetscViewerSetUp(viewer));
14529566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERBINARY, &isbinary));
14539566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5));
1454eb91f321SVaclav Hapla   if (isbinary) {
14559566063dSJacob Faibussowitsch     PetscCall(MatLoad_Dense_Binary(newMat, viewer));
1456eb91f321SVaclav Hapla   } else if (ishdf5) {
1457eb91f321SVaclav Hapla #if defined(PETSC_HAVE_HDF5)
14589566063dSJacob Faibussowitsch     PetscCall(MatLoad_Dense_HDF5(newMat, viewer));
1459eb91f321SVaclav Hapla #else
1460eb91f321SVaclav Hapla     SETERRQ(PetscObjectComm((PetscObject)newMat), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5");
1461eb91f321SVaclav Hapla #endif
1462eb91f321SVaclav Hapla   } else {
146398921bdaSJacob 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);
1464eb91f321SVaclav Hapla   }
14653ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1466eb91f321SVaclav Hapla }
1467eb91f321SVaclav Hapla 
1468d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatView_SeqDense_ASCII(Mat A, PetscViewer viewer)
1469d71ae5a4SJacob Faibussowitsch {
1470932b0c3eSLois Curfman McInnes   Mat_SeqDense     *a = (Mat_SeqDense *)A->data;
147113f74950SBarry Smith   PetscInt          i, j;
14722dcb1b2aSMatthew Knepley   const char       *name;
1473ca15aa20SStefano Zampini   PetscScalar      *v, *av;
1474f3ef73ceSBarry Smith   PetscViewerFormat format;
14755f481a85SSatish Balay #if defined(PETSC_USE_COMPLEX)
1476ace3abfcSBarry Smith   PetscBool allreal = PETSC_TRUE;
14775f481a85SSatish Balay #endif
1478932b0c3eSLois Curfman McInnes 
14793a40ed3dSBarry Smith   PetscFunctionBegin;
14809566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArrayRead(A, (const PetscScalar **)&av));
14819566063dSJacob Faibussowitsch   PetscCall(PetscViewerGetFormat(viewer, &format));
1482456192e2SBarry Smith   if (format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL) {
14833ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS); /* do nothing for now */
1484fb9695e5SSatish Balay   } else if (format == PETSC_VIEWER_ASCII_COMMON) {
14859566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIUseTabs(viewer, PETSC_FALSE));
1486d0f46423SBarry Smith     for (i = 0; i < A->rmap->n; i++) {
1487ca15aa20SStefano Zampini       v = av + i;
14889566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "row %" PetscInt_FMT ":", i));
1489d0f46423SBarry Smith       for (j = 0; j < A->cmap->n; j++) {
1490aa482453SBarry Smith #if defined(PETSC_USE_COMPLEX)
1491329f5518SBarry Smith         if (PetscRealPart(*v) != 0.0 && PetscImaginaryPart(*v) != 0.0) {
14929566063dSJacob Faibussowitsch           PetscCall(PetscViewerASCIIPrintf(viewer, " (%" PetscInt_FMT ", %g + %g i) ", j, (double)PetscRealPart(*v), (double)PetscImaginaryPart(*v)));
1493329f5518SBarry Smith         } else if (PetscRealPart(*v)) {
14949566063dSJacob Faibussowitsch           PetscCall(PetscViewerASCIIPrintf(viewer, " (%" PetscInt_FMT ", %g) ", j, (double)PetscRealPart(*v)));
14956831982aSBarry Smith         }
149680cd9d93SLois Curfman McInnes #else
149748a46eb9SPierre Jolivet         if (*v) PetscCall(PetscViewerASCIIPrintf(viewer, " (%" PetscInt_FMT ", %g) ", j, (double)*v));
149880cd9d93SLois Curfman McInnes #endif
14991b807ce4Svictorle         v += a->lda;
150080cd9d93SLois Curfman McInnes       }
15019566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "\n"));
150280cd9d93SLois Curfman McInnes     }
15039566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIUseTabs(viewer, PETSC_TRUE));
15043a40ed3dSBarry Smith   } else {
15059566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIUseTabs(viewer, PETSC_FALSE));
1506aa482453SBarry Smith #if defined(PETSC_USE_COMPLEX)
150747989497SBarry Smith     /* determine if matrix has all real values */
1508bcd8d3a4SJose E. Roman     for (j = 0; j < A->cmap->n; j++) {
1509bcd8d3a4SJose E. Roman       v = av + j * a->lda;
1510bcd8d3a4SJose E. Roman       for (i = 0; i < A->rmap->n; i++) {
15119371c9d4SSatish Balay         if (PetscImaginaryPart(v[i])) {
15129371c9d4SSatish Balay           allreal = PETSC_FALSE;
15139371c9d4SSatish Balay           break;
15149371c9d4SSatish Balay         }
151547989497SBarry Smith       }
1516bcd8d3a4SJose E. Roman     }
151747989497SBarry Smith #endif
1518fb9695e5SSatish Balay     if (format == PETSC_VIEWER_ASCII_MATLAB) {
15199566063dSJacob Faibussowitsch       PetscCall(PetscObjectGetName((PetscObject)A, &name));
15209566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "%% Size = %" PetscInt_FMT " %" PetscInt_FMT " \n", A->rmap->n, A->cmap->n));
15219566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "%s = zeros(%" PetscInt_FMT ",%" PetscInt_FMT ");\n", name, A->rmap->n, A->cmap->n));
15229566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "%s = [\n", name));
1523ffac6cdbSBarry Smith     }
1524ffac6cdbSBarry Smith 
1525d0f46423SBarry Smith     for (i = 0; i < A->rmap->n; i++) {
1526ca15aa20SStefano Zampini       v = av + i;
1527d0f46423SBarry Smith       for (j = 0; j < A->cmap->n; j++) {
1528aa482453SBarry Smith #if defined(PETSC_USE_COMPLEX)
152947989497SBarry Smith         if (allreal) {
15309566063dSJacob Faibussowitsch           PetscCall(PetscViewerASCIIPrintf(viewer, "%18.16e ", (double)PetscRealPart(*v)));
153147989497SBarry Smith         } else {
15329566063dSJacob Faibussowitsch           PetscCall(PetscViewerASCIIPrintf(viewer, "%18.16e + %18.16ei ", (double)PetscRealPart(*v), (double)PetscImaginaryPart(*v)));
153347989497SBarry Smith         }
1534289bc588SBarry Smith #else
15359566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, "%18.16e ", (double)*v));
1536289bc588SBarry Smith #endif
15371b807ce4Svictorle         v += a->lda;
1538289bc588SBarry Smith       }
15399566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "\n"));
1540289bc588SBarry Smith     }
154148a46eb9SPierre Jolivet     if (format == PETSC_VIEWER_ASCII_MATLAB) PetscCall(PetscViewerASCIIPrintf(viewer, "];\n"));
15429566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIUseTabs(viewer, PETSC_TRUE));
1543da3a660dSBarry Smith   }
15449566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArrayRead(A, (const PetscScalar **)&av));
15459566063dSJacob Faibussowitsch   PetscCall(PetscViewerFlush(viewer));
15463ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1547289bc588SBarry Smith }
1548289bc588SBarry Smith 
15499804daf3SBarry Smith #include <petscdraw.h>
1550d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatView_SeqDense_Draw_Zoom(PetscDraw draw, void *Aa)
1551d71ae5a4SJacob Faibussowitsch {
1552f1af5d2fSBarry Smith   Mat                A = (Mat)Aa;
1553383922c3SLisandro Dalcin   PetscInt           m = A->rmap->n, n = A->cmap->n, i, j;
1554383922c3SLisandro Dalcin   int                color = PETSC_DRAW_WHITE;
1555ca15aa20SStefano Zampini   const PetscScalar *v;
1556b0a32e0cSBarry Smith   PetscViewer        viewer;
1557b05fc000SLisandro Dalcin   PetscReal          xl, yl, xr, yr, x_l, x_r, y_l, y_r;
1558f3ef73ceSBarry Smith   PetscViewerFormat  format;
1559f1af5d2fSBarry Smith 
1560f1af5d2fSBarry Smith   PetscFunctionBegin;
15619566063dSJacob Faibussowitsch   PetscCall(PetscObjectQuery((PetscObject)A, "Zoomviewer", (PetscObject *)&viewer));
15629566063dSJacob Faibussowitsch   PetscCall(PetscViewerGetFormat(viewer, &format));
15639566063dSJacob Faibussowitsch   PetscCall(PetscDrawGetCoordinates(draw, &xl, &yl, &xr, &yr));
1564f1af5d2fSBarry Smith 
1565f1af5d2fSBarry Smith   /* Loop over matrix elements drawing boxes */
15669566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArrayRead(A, &v));
1567fb9695e5SSatish Balay   if (format != PETSC_VIEWER_DRAW_CONTOUR) {
1568d0609cedSBarry Smith     PetscDrawCollectiveBegin(draw);
1569f1af5d2fSBarry Smith     /* Blue for negative and Red for positive */
1570f1af5d2fSBarry Smith     for (j = 0; j < n; j++) {
15719371c9d4SSatish Balay       x_l = j;
15729371c9d4SSatish Balay       x_r = x_l + 1.0;
1573f1af5d2fSBarry Smith       for (i = 0; i < m; i++) {
1574f1af5d2fSBarry Smith         y_l = m - i - 1.0;
1575f1af5d2fSBarry Smith         y_r = y_l + 1.0;
1576ca15aa20SStefano Zampini         if (PetscRealPart(v[j * m + i]) > 0.) color = PETSC_DRAW_RED;
1577ca15aa20SStefano Zampini         else if (PetscRealPart(v[j * m + i]) < 0.) color = PETSC_DRAW_BLUE;
1578ca15aa20SStefano Zampini         else continue;
15799566063dSJacob Faibussowitsch         PetscCall(PetscDrawRectangle(draw, x_l, y_l, x_r, y_r, color, color, color, color));
1580f1af5d2fSBarry Smith       }
1581f1af5d2fSBarry Smith     }
1582d0609cedSBarry Smith     PetscDrawCollectiveEnd(draw);
1583f1af5d2fSBarry Smith   } else {
1584f1af5d2fSBarry Smith     /* use contour shading to indicate magnitude of values */
1585f1af5d2fSBarry Smith     /* first determine max of all nonzero values */
1586b05fc000SLisandro Dalcin     PetscReal minv = 0.0, maxv = 0.0;
1587b05fc000SLisandro Dalcin     PetscDraw popup;
1588b05fc000SLisandro Dalcin 
1589f1af5d2fSBarry Smith     for (i = 0; i < m * n; i++) {
1590f1af5d2fSBarry Smith       if (PetscAbsScalar(v[i]) > maxv) maxv = PetscAbsScalar(v[i]);
1591f1af5d2fSBarry Smith     }
1592383922c3SLisandro Dalcin     if (minv >= maxv) maxv = minv + PETSC_SMALL;
15939566063dSJacob Faibussowitsch     PetscCall(PetscDrawGetPopup(draw, &popup));
15949566063dSJacob Faibussowitsch     PetscCall(PetscDrawScalePopup(popup, minv, maxv));
1595383922c3SLisandro Dalcin 
1596d0609cedSBarry Smith     PetscDrawCollectiveBegin(draw);
1597f1af5d2fSBarry Smith     for (j = 0; j < n; j++) {
1598f1af5d2fSBarry Smith       x_l = j;
1599f1af5d2fSBarry Smith       x_r = x_l + 1.0;
1600f1af5d2fSBarry Smith       for (i = 0; i < m; i++) {
1601f1af5d2fSBarry Smith         y_l   = m - i - 1.0;
1602f1af5d2fSBarry Smith         y_r   = y_l + 1.0;
1603b05fc000SLisandro Dalcin         color = PetscDrawRealToColor(PetscAbsScalar(v[j * m + i]), minv, maxv);
16049566063dSJacob Faibussowitsch         PetscCall(PetscDrawRectangle(draw, x_l, y_l, x_r, y_r, color, color, color, color));
1605f1af5d2fSBarry Smith       }
1606f1af5d2fSBarry Smith     }
1607d0609cedSBarry Smith     PetscDrawCollectiveEnd(draw);
1608f1af5d2fSBarry Smith   }
16099566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArrayRead(A, &v));
16103ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1611f1af5d2fSBarry Smith }
1612f1af5d2fSBarry Smith 
1613d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatView_SeqDense_Draw(Mat A, PetscViewer viewer)
1614d71ae5a4SJacob Faibussowitsch {
1615b0a32e0cSBarry Smith   PetscDraw draw;
1616ace3abfcSBarry Smith   PetscBool isnull;
1617329f5518SBarry Smith   PetscReal xr, yr, xl, yl, h, w;
1618f1af5d2fSBarry Smith 
1619f1af5d2fSBarry Smith   PetscFunctionBegin;
16209566063dSJacob Faibussowitsch   PetscCall(PetscViewerDrawGetDraw(viewer, 0, &draw));
16219566063dSJacob Faibussowitsch   PetscCall(PetscDrawIsNull(draw, &isnull));
16223ba16761SJacob Faibussowitsch   if (isnull) PetscFunctionReturn(PETSC_SUCCESS);
1623f1af5d2fSBarry Smith 
16249371c9d4SSatish Balay   xr = A->cmap->n;
16259371c9d4SSatish Balay   yr = A->rmap->n;
16269371c9d4SSatish Balay   h  = yr / 10.0;
16279371c9d4SSatish Balay   w  = xr / 10.0;
16289371c9d4SSatish Balay   xr += w;
16299371c9d4SSatish Balay   yr += h;
16309371c9d4SSatish Balay   xl = -w;
16319371c9d4SSatish Balay   yl = -h;
16329566063dSJacob Faibussowitsch   PetscCall(PetscDrawSetCoordinates(draw, xl, yl, xr, yr));
16339566063dSJacob Faibussowitsch   PetscCall(PetscObjectCompose((PetscObject)A, "Zoomviewer", (PetscObject)viewer));
16349566063dSJacob Faibussowitsch   PetscCall(PetscDrawZoom(draw, MatView_SeqDense_Draw_Zoom, A));
16359566063dSJacob Faibussowitsch   PetscCall(PetscObjectCompose((PetscObject)A, "Zoomviewer", NULL));
16369566063dSJacob Faibussowitsch   PetscCall(PetscDrawSave(draw));
16373ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1638f1af5d2fSBarry Smith }
1639f1af5d2fSBarry Smith 
1640d71ae5a4SJacob Faibussowitsch PetscErrorCode MatView_SeqDense(Mat A, PetscViewer viewer)
1641d71ae5a4SJacob Faibussowitsch {
1642ace3abfcSBarry Smith   PetscBool iascii, isbinary, isdraw;
1643932b0c3eSLois Curfman McInnes 
16443a40ed3dSBarry Smith   PetscFunctionBegin;
16459566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
16469566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERBINARY, &isbinary));
16479566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERDRAW, &isdraw));
16481baa6e33SBarry Smith   if (iascii) PetscCall(MatView_SeqDense_ASCII(A, viewer));
16491baa6e33SBarry Smith   else if (isbinary) PetscCall(MatView_Dense_Binary(A, viewer));
16501baa6e33SBarry Smith   else if (isdraw) PetscCall(MatView_SeqDense_Draw(A, viewer));
16513ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1652932b0c3eSLois Curfman McInnes }
1653289bc588SBarry Smith 
1654d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatDensePlaceArray_SeqDense(Mat A, const PetscScalar *array)
1655d71ae5a4SJacob Faibussowitsch {
1656d3042a70SBarry Smith   Mat_SeqDense *a = (Mat_SeqDense *)A->data;
1657d3042a70SBarry Smith 
1658d3042a70SBarry Smith   PetscFunctionBegin;
165928b400f6SJacob Faibussowitsch   PetscCheck(!a->vecinuse, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Need to call MatDenseRestoreColumnVec() first");
166028b400f6SJacob Faibussowitsch   PetscCheck(!a->matinuse, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Need to call MatDenseRestoreSubMatrix() first");
16616635c364SPierre Jolivet   PetscCheck(!a->unplacedarray, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Need to call MatDenseResetArray() first");
1662d3042a70SBarry Smith   a->unplacedarray       = a->v;
1663d3042a70SBarry Smith   a->unplaced_user_alloc = a->user_alloc;
1664d3042a70SBarry Smith   a->v                   = (PetscScalar *)array;
1665637a0070SStefano Zampini   a->user_alloc          = PETSC_TRUE;
166647d993e7Ssuyashtn #if defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
1667c70f7ee4SJunchao Zhang   A->offloadmask = PETSC_OFFLOAD_CPU;
1668ca15aa20SStefano Zampini #endif
16693ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1670d3042a70SBarry Smith }
1671d3042a70SBarry Smith 
1672d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatDenseResetArray_SeqDense(Mat A)
1673d71ae5a4SJacob Faibussowitsch {
1674d3042a70SBarry Smith   Mat_SeqDense *a = (Mat_SeqDense *)A->data;
1675d3042a70SBarry Smith 
1676d3042a70SBarry Smith   PetscFunctionBegin;
167728b400f6SJacob Faibussowitsch   PetscCheck(!a->vecinuse, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Need to call MatDenseRestoreColumnVec() first");
167828b400f6SJacob Faibussowitsch   PetscCheck(!a->matinuse, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Need to call MatDenseRestoreSubMatrix() first");
1679d3042a70SBarry Smith   a->v             = a->unplacedarray;
1680d3042a70SBarry Smith   a->user_alloc    = a->unplaced_user_alloc;
1681d3042a70SBarry Smith   a->unplacedarray = NULL;
168247d993e7Ssuyashtn #if defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
1683c70f7ee4SJunchao Zhang   A->offloadmask = PETSC_OFFLOAD_CPU;
1684ca15aa20SStefano Zampini #endif
16853ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1686d3042a70SBarry Smith }
1687d3042a70SBarry Smith 
1688d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatDenseReplaceArray_SeqDense(Mat A, const PetscScalar *array)
1689d71ae5a4SJacob Faibussowitsch {
1690d5ea218eSStefano Zampini   Mat_SeqDense *a = (Mat_SeqDense *)A->data;
1691d5ea218eSStefano Zampini 
1692d5ea218eSStefano Zampini   PetscFunctionBegin;
169328b400f6SJacob Faibussowitsch   PetscCheck(!a->vecinuse, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Need to call MatDenseRestoreColumnVec() first");
169428b400f6SJacob Faibussowitsch   PetscCheck(!a->matinuse, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Need to call MatDenseRestoreSubMatrix() first");
16959566063dSJacob Faibussowitsch   if (!a->user_alloc) PetscCall(PetscFree(a->v));
1696d5ea218eSStefano Zampini   a->v          = (PetscScalar *)array;
1697d5ea218eSStefano Zampini   a->user_alloc = PETSC_FALSE;
169847d993e7Ssuyashtn #if defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
1699d5ea218eSStefano Zampini   A->offloadmask = PETSC_OFFLOAD_CPU;
1700d5ea218eSStefano Zampini #endif
17013ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1702d5ea218eSStefano Zampini }
1703d5ea218eSStefano Zampini 
1704d71ae5a4SJacob Faibussowitsch PetscErrorCode MatDestroy_SeqDense(Mat mat)
1705d71ae5a4SJacob Faibussowitsch {
1706ec8511deSBarry Smith   Mat_SeqDense *l = (Mat_SeqDense *)mat->data;
170790f02eecSBarry Smith 
17083a40ed3dSBarry Smith   PetscFunctionBegin;
17093ba16761SJacob Faibussowitsch   PetscCall(PetscLogObjectState((PetscObject)mat, "Rows %" PetscInt_FMT " Cols %" PetscInt_FMT, mat->rmap->n, mat->cmap->n));
1710f4f49eeaSPierre Jolivet   PetscCall(VecDestroy(&l->qrrhs));
17119566063dSJacob Faibussowitsch   PetscCall(PetscFree(l->tau));
17129566063dSJacob Faibussowitsch   PetscCall(PetscFree(l->pivots));
17139566063dSJacob Faibussowitsch   PetscCall(PetscFree(l->fwork));
17149566063dSJacob Faibussowitsch   if (!l->user_alloc) PetscCall(PetscFree(l->v));
17159566063dSJacob Faibussowitsch   if (!l->unplaced_user_alloc) PetscCall(PetscFree(l->unplacedarray));
171628b400f6SJacob Faibussowitsch   PetscCheck(!l->vecinuse, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Need to call MatDenseRestoreColumnVec() first");
171728b400f6SJacob Faibussowitsch   PetscCheck(!l->matinuse, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Need to call MatDenseRestoreSubMatrix() first");
17189566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&l->cvec));
17199566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&l->cmat));
17209566063dSJacob Faibussowitsch   PetscCall(PetscFree(mat->data));
1721dbd8c25aSHong Zhang 
17229566063dSJacob Faibussowitsch   PetscCall(PetscObjectChangeTypeName((PetscObject)mat, NULL));
17239566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatQRFactor_C", NULL));
17242e956fe4SStefano Zampini   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatQRFactorSymbolic_C", NULL));
17252e956fe4SStefano Zampini   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatQRFactorNumeric_C", NULL));
17269566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatDenseGetLDA_C", NULL));
17279566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatDenseSetLDA_C", NULL));
17289566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatDenseGetArray_C", NULL));
17299566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatDenseRestoreArray_C", NULL));
17309566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatDensePlaceArray_C", NULL));
17319566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatDenseResetArray_C", NULL));
17329566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatDenseReplaceArray_C", NULL));
17339566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatDenseGetArrayRead_C", NULL));
17349566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatDenseRestoreArrayRead_C", NULL));
17359566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatDenseGetArrayWrite_C", NULL));
17369566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatDenseRestoreArrayWrite_C", NULL));
17379566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatConvert_seqdense_seqaij_C", NULL));
17388baccfbdSHong Zhang #if defined(PETSC_HAVE_ELEMENTAL)
17399566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatConvert_seqdense_elemental_C", NULL));
17408baccfbdSHong Zhang #endif
1741d24d4204SJose E. Roman #if defined(PETSC_HAVE_SCALAPACK)
17429566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatConvert_seqdense_scalapack_C", NULL));
1743d24d4204SJose E. Roman #endif
17442bf066beSStefano Zampini #if defined(PETSC_HAVE_CUDA)
17459566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatConvert_seqdense_seqdensecuda_C", NULL));
17469566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatProductSetFromOptions_seqdensecuda_seqdensecuda_C", NULL));
17479566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatProductSetFromOptions_seqdensecuda_seqdense_C", NULL));
17482e956fe4SStefano Zampini   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatProductSetFromOptions_seqdense_seqdensecuda_C", NULL));
17492bf066beSStefano Zampini #endif
175047d993e7Ssuyashtn #if defined(PETSC_HAVE_HIP)
175147d993e7Ssuyashtn   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatConvert_seqdense_seqdensehip_C", NULL));
175247d993e7Ssuyashtn   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatProductSetFromOptions_seqdensehip_seqdensehip_C", NULL));
175347d993e7Ssuyashtn   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatProductSetFromOptions_seqdensehip_seqdense_C", NULL));
175447d993e7Ssuyashtn   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatProductSetFromOptions_seqdense_seqdensehip_C", NULL));
175547d993e7Ssuyashtn #endif
17569566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatSeqDenseSetPreallocation_C", NULL));
17579566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatProductSetFromOptions_seqaij_seqdense_C", NULL));
17589566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatProductSetFromOptions_seqdense_seqdense_C", NULL));
17599566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatProductSetFromOptions_seqbaij_seqdense_C", NULL));
17609566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatProductSetFromOptions_seqsbaij_seqdense_C", NULL));
176152c5f739Sprj- 
17629566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatDenseGetColumn_C", NULL));
17639566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatDenseRestoreColumn_C", NULL));
17649566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatDenseGetColumnVec_C", NULL));
17659566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatDenseRestoreColumnVec_C", NULL));
17669566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatDenseGetColumnVecRead_C", NULL));
17679566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatDenseRestoreColumnVecRead_C", NULL));
17689566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatDenseGetColumnVecWrite_C", NULL));
17699566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatDenseRestoreColumnVecWrite_C", NULL));
17709566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatDenseGetSubMatrix_C", NULL));
17719566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatDenseRestoreSubMatrix_C", NULL));
17720be0d8bdSHansol Suh   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatMultAddColumnRange_C", NULL));
17730be0d8bdSHansol Suh   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatMultHermitianTransposeColumnRange_C", NULL));
17740be0d8bdSHansol Suh   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatMultHermitianTransposeAddColumnRange_C", NULL));
17753ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1776289bc588SBarry Smith }
1777289bc588SBarry Smith 
1778d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatTranspose_SeqDense(Mat A, MatReuse reuse, Mat *matout)
1779d71ae5a4SJacob Faibussowitsch {
1780c0bbcb79SLois Curfman McInnes   Mat_SeqDense *mat = (Mat_SeqDense *)A->data;
17816536e3caSStefano Zampini   PetscInt      k, j, m = A->rmap->n, M = mat->lda, n = A->cmap->n;
178287828ca2SBarry Smith   PetscScalar  *v, tmp;
178348b35521SBarry Smith 
17843a40ed3dSBarry Smith   PetscFunctionBegin;
17857fb60732SBarry Smith   if (reuse == MAT_REUSE_MATRIX) PetscCall(MatTransposeCheckNonzeroState_Private(A, *matout));
17866536e3caSStefano Zampini   if (reuse == MAT_INPLACE_MATRIX) {
17876536e3caSStefano Zampini     if (m == n) { /* in place transpose */
17889566063dSJacob Faibussowitsch       PetscCall(MatDenseGetArray(A, &v));
1789d3e5ee88SLois Curfman McInnes       for (j = 0; j < m; j++) {
1790289bc588SBarry Smith         for (k = 0; k < j; k++) {
17911b807ce4Svictorle           tmp          = v[j + k * M];
17921b807ce4Svictorle           v[j + k * M] = v[k + j * M];
17931b807ce4Svictorle           v[k + j * M] = tmp;
1794289bc588SBarry Smith         }
1795289bc588SBarry Smith       }
17969566063dSJacob Faibussowitsch       PetscCall(MatDenseRestoreArray(A, &v));
17976536e3caSStefano Zampini     } else { /* reuse memory, temporary allocates new memory */
17986536e3caSStefano Zampini       PetscScalar *v2;
17996536e3caSStefano Zampini       PetscLayout  tmplayout;
18006536e3caSStefano Zampini 
18019566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1((size_t)m * n, &v2));
18029566063dSJacob Faibussowitsch       PetscCall(MatDenseGetArray(A, &v));
18036536e3caSStefano Zampini       for (j = 0; j < n; j++) {
18046536e3caSStefano Zampini         for (k = 0; k < m; k++) v2[j + (size_t)k * n] = v[k + (size_t)j * M];
18056536e3caSStefano Zampini       }
18069566063dSJacob Faibussowitsch       PetscCall(PetscArraycpy(v, v2, (size_t)m * n));
18079566063dSJacob Faibussowitsch       PetscCall(PetscFree(v2));
18089566063dSJacob Faibussowitsch       PetscCall(MatDenseRestoreArray(A, &v));
18096536e3caSStefano Zampini       /* cleanup size dependent quantities */
18109566063dSJacob Faibussowitsch       PetscCall(VecDestroy(&mat->cvec));
18119566063dSJacob Faibussowitsch       PetscCall(MatDestroy(&mat->cmat));
18129566063dSJacob Faibussowitsch       PetscCall(PetscFree(mat->pivots));
18139566063dSJacob Faibussowitsch       PetscCall(PetscFree(mat->fwork));
18146536e3caSStefano Zampini       /* swap row/col layouts */
18156497c311SBarry Smith       PetscCall(PetscBLASIntCast(n, &mat->lda));
18166536e3caSStefano Zampini       tmplayout = A->rmap;
18176536e3caSStefano Zampini       A->rmap   = A->cmap;
18186536e3caSStefano Zampini       A->cmap   = tmplayout;
18196536e3caSStefano Zampini     }
18203a40ed3dSBarry Smith   } else { /* out-of-place transpose */
1821d3e5ee88SLois Curfman McInnes     Mat           tmat;
1822ec8511deSBarry Smith     Mat_SeqDense *tmatd;
182387828ca2SBarry Smith     PetscScalar  *v2;
1824af36a384SStefano Zampini     PetscInt      M2;
1825ea709b57SSatish Balay 
18266536e3caSStefano Zampini     if (reuse == MAT_INITIAL_MATRIX) {
18279566063dSJacob Faibussowitsch       PetscCall(MatCreate(PetscObjectComm((PetscObject)A), &tmat));
18289566063dSJacob Faibussowitsch       PetscCall(MatSetSizes(tmat, A->cmap->n, A->rmap->n, A->cmap->n, A->rmap->n));
18299566063dSJacob Faibussowitsch       PetscCall(MatSetType(tmat, ((PetscObject)A)->type_name));
18309566063dSJacob Faibussowitsch       PetscCall(MatSeqDenseSetPreallocation(tmat, NULL));
1831ca15aa20SStefano Zampini     } else tmat = *matout;
1832ca15aa20SStefano Zampini 
18339566063dSJacob Faibussowitsch     PetscCall(MatDenseGetArrayRead(A, (const PetscScalar **)&v));
18349566063dSJacob Faibussowitsch     PetscCall(MatDenseGetArray(tmat, &v2));
1835ec8511deSBarry Smith     tmatd = (Mat_SeqDense *)tmat->data;
1836ca15aa20SStefano Zampini     M2    = tmatd->lda;
1837d3e5ee88SLois Curfman McInnes     for (j = 0; j < n; j++) {
1838af36a384SStefano Zampini       for (k = 0; k < m; k++) v2[j + k * M2] = v[k + j * M];
1839d3e5ee88SLois Curfman McInnes     }
18409566063dSJacob Faibussowitsch     PetscCall(MatDenseRestoreArray(tmat, &v2));
18419566063dSJacob Faibussowitsch     PetscCall(MatDenseRestoreArrayRead(A, (const PetscScalar **)&v));
18429566063dSJacob Faibussowitsch     PetscCall(MatAssemblyBegin(tmat, MAT_FINAL_ASSEMBLY));
18439566063dSJacob Faibussowitsch     PetscCall(MatAssemblyEnd(tmat, MAT_FINAL_ASSEMBLY));
18446536e3caSStefano Zampini     *matout = tmat;
184548b35521SBarry Smith   }
18463ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1847289bc588SBarry Smith }
1848289bc588SBarry Smith 
1849d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatEqual_SeqDense(Mat A1, Mat A2, PetscBool *flg)
1850d71ae5a4SJacob Faibussowitsch {
1851c0bbcb79SLois Curfman McInnes   Mat_SeqDense      *mat1 = (Mat_SeqDense *)A1->data;
1852c0bbcb79SLois Curfman McInnes   Mat_SeqDense      *mat2 = (Mat_SeqDense *)A2->data;
1853ca15aa20SStefano Zampini   PetscInt           i;
1854ca15aa20SStefano Zampini   const PetscScalar *v1, *v2;
18559ea5d5aeSSatish Balay 
18563a40ed3dSBarry Smith   PetscFunctionBegin;
18579371c9d4SSatish Balay   if (A1->rmap->n != A2->rmap->n) {
18589371c9d4SSatish Balay     *flg = PETSC_FALSE;
18593ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
18609371c9d4SSatish Balay   }
18619371c9d4SSatish Balay   if (A1->cmap->n != A2->cmap->n) {
18629371c9d4SSatish Balay     *flg = PETSC_FALSE;
18633ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
18649371c9d4SSatish Balay   }
18659566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArrayRead(A1, &v1));
18669566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArrayRead(A2, &v2));
1867ca15aa20SStefano Zampini   for (i = 0; i < A1->cmap->n; i++) {
18689566063dSJacob Faibussowitsch     PetscCall(PetscArraycmp(v1, v2, A1->rmap->n, flg));
18693ba16761SJacob Faibussowitsch     if (*flg == PETSC_FALSE) PetscFunctionReturn(PETSC_SUCCESS);
1870ca15aa20SStefano Zampini     v1 += mat1->lda;
1871ca15aa20SStefano Zampini     v2 += mat2->lda;
18721b807ce4Svictorle   }
18739566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArrayRead(A1, &v1));
18749566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArrayRead(A2, &v2));
187577c4ece6SBarry Smith   *flg = PETSC_TRUE;
18763ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1877289bc588SBarry Smith }
1878289bc588SBarry Smith 
187914277c92SJacob Faibussowitsch PetscErrorCode MatGetDiagonal_SeqDense(Mat A, Vec v)
1880d71ae5a4SJacob Faibussowitsch {
1881c0bbcb79SLois Curfman McInnes   Mat_SeqDense      *mat = (Mat_SeqDense *)A->data;
188213f74950SBarry Smith   PetscInt           i, n, len;
1883ca15aa20SStefano Zampini   PetscScalar       *x;
1884ca15aa20SStefano Zampini   const PetscScalar *vv;
188544cd7ae7SLois Curfman McInnes 
18863a40ed3dSBarry Smith   PetscFunctionBegin;
18879566063dSJacob Faibussowitsch   PetscCall(VecGetSize(v, &n));
18889566063dSJacob Faibussowitsch   PetscCall(VecGetArray(v, &x));
1889d0f46423SBarry Smith   len = PetscMin(A->rmap->n, A->cmap->n);
18909566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArrayRead(A, &vv));
189108401ef6SPierre Jolivet   PetscCheck(n == A->rmap->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Nonconforming mat and vec");
1892ad540459SPierre Jolivet   for (i = 0; i < len; i++) x[i] = vv[i * mat->lda + i];
18939566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArrayRead(A, &vv));
18949566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(v, &x));
18953ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1896289bc588SBarry Smith }
1897289bc588SBarry Smith 
1898d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatDiagonalScale_SeqDense(Mat A, Vec ll, Vec rr)
1899d71ae5a4SJacob Faibussowitsch {
1900c0bbcb79SLois Curfman McInnes   Mat_SeqDense      *mat = (Mat_SeqDense *)A->data;
1901f1ceaac6SMatthew G. Knepley   const PetscScalar *l, *r;
1902ca15aa20SStefano Zampini   PetscScalar        x, *v, *vv;
1903d0f46423SBarry Smith   PetscInt           i, j, m = A->rmap->n, n = A->cmap->n;
190455659b69SBarry Smith 
19053a40ed3dSBarry Smith   PetscFunctionBegin;
19069566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArray(A, &vv));
190728988994SBarry Smith   if (ll) {
19089566063dSJacob Faibussowitsch     PetscCall(VecGetSize(ll, &m));
19099566063dSJacob Faibussowitsch     PetscCall(VecGetArrayRead(ll, &l));
191008401ef6SPierre Jolivet     PetscCheck(m == A->rmap->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Left scaling vec wrong size");
1911da3a660dSBarry Smith     for (i = 0; i < m; i++) {
1912da3a660dSBarry Smith       x = l[i];
1913ca15aa20SStefano Zampini       v = vv + i;
19149371c9d4SSatish Balay       for (j = 0; j < n; j++) {
19159371c9d4SSatish Balay         (*v) *= x;
19169371c9d4SSatish Balay         v += mat->lda;
19179371c9d4SSatish Balay       }
1918da3a660dSBarry Smith     }
19199566063dSJacob Faibussowitsch     PetscCall(VecRestoreArrayRead(ll, &l));
19209566063dSJacob Faibussowitsch     PetscCall(PetscLogFlops(1.0 * n * m));
1921da3a660dSBarry Smith   }
192228988994SBarry Smith   if (rr) {
19239566063dSJacob Faibussowitsch     PetscCall(VecGetSize(rr, &n));
19249566063dSJacob Faibussowitsch     PetscCall(VecGetArrayRead(rr, &r));
192508401ef6SPierre Jolivet     PetscCheck(n == A->cmap->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Right scaling vec wrong size");
1926da3a660dSBarry Smith     for (i = 0; i < n; i++) {
1927da3a660dSBarry Smith       x = r[i];
1928ca15aa20SStefano Zampini       v = vv + i * mat->lda;
19292205254eSKarl Rupp       for (j = 0; j < m; j++) (*v++) *= x;
1930da3a660dSBarry Smith     }
19319566063dSJacob Faibussowitsch     PetscCall(VecRestoreArrayRead(rr, &r));
19329566063dSJacob Faibussowitsch     PetscCall(PetscLogFlops(1.0 * n * m));
1933da3a660dSBarry Smith   }
19349566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArray(A, &vv));
19353ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1936289bc588SBarry Smith }
1937289bc588SBarry Smith 
1938d71ae5a4SJacob Faibussowitsch PetscErrorCode MatNorm_SeqDense(Mat A, NormType type, PetscReal *nrm)
1939d71ae5a4SJacob Faibussowitsch {
1940c0bbcb79SLois Curfman McInnes   Mat_SeqDense *mat = (Mat_SeqDense *)A->data;
1941ca15aa20SStefano Zampini   PetscScalar  *v, *vv;
1942329f5518SBarry Smith   PetscReal     sum = 0.0;
194375f6d85dSStefano Zampini   PetscInt      lda, m = A->rmap->n, i, j;
194455659b69SBarry Smith 
19453a40ed3dSBarry Smith   PetscFunctionBegin;
19469566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArrayRead(A, (const PetscScalar **)&vv));
19479566063dSJacob Faibussowitsch   PetscCall(MatDenseGetLDA(A, &lda));
1948ca15aa20SStefano Zampini   v = vv;
1949289bc588SBarry Smith   if (type == NORM_FROBENIUS) {
1950a5ce6ee0Svictorle     if (lda > m) {
1951d0f46423SBarry Smith       for (j = 0; j < A->cmap->n; j++) {
1952ca15aa20SStefano Zampini         v = vv + j * lda;
1953a5ce6ee0Svictorle         for (i = 0; i < m; i++) {
19549371c9d4SSatish Balay           sum += PetscRealPart(PetscConj(*v) * (*v));
19559371c9d4SSatish Balay           v++;
1956a5ce6ee0Svictorle         }
1957a5ce6ee0Svictorle       }
1958a5ce6ee0Svictorle     } else {
1959570b7f6dSBarry Smith #if defined(PETSC_USE_REAL___FP16)
1960570b7f6dSBarry Smith       PetscBLASInt one = 1, cnt = A->cmap->n * A->rmap->n;
1961792fecdfSBarry Smith       PetscCallBLAS("BLASnrm2", *nrm = BLASnrm2_(&cnt, v, &one));
1962570b7f6dSBarry Smith     }
1963570b7f6dSBarry Smith #else
1964d0f46423SBarry Smith       for (i = 0; i < A->cmap->n * A->rmap->n; i++) {
19659371c9d4SSatish Balay         sum += PetscRealPart(PetscConj(*v) * (*v));
19669371c9d4SSatish Balay         v++;
1967289bc588SBarry Smith       }
1968a5ce6ee0Svictorle     }
19698f1a2a5eSBarry Smith     *nrm = PetscSqrtReal(sum);
1970570b7f6dSBarry Smith #endif
19719566063dSJacob Faibussowitsch     PetscCall(PetscLogFlops(2.0 * A->cmap->n * A->rmap->n));
19723a40ed3dSBarry Smith   } else if (type == NORM_1) {
1973064f8208SBarry Smith     *nrm = 0.0;
1974d0f46423SBarry Smith     for (j = 0; j < A->cmap->n; j++) {
1975ca15aa20SStefano Zampini       v   = vv + j * mat->lda;
1976289bc588SBarry Smith       sum = 0.0;
1977d0f46423SBarry Smith       for (i = 0; i < A->rmap->n; i++) {
19789371c9d4SSatish Balay         sum += PetscAbsScalar(*v);
19799371c9d4SSatish Balay         v++;
1980289bc588SBarry Smith       }
1981064f8208SBarry Smith       if (sum > *nrm) *nrm = sum;
1982289bc588SBarry Smith     }
19839566063dSJacob Faibussowitsch     PetscCall(PetscLogFlops(1.0 * A->cmap->n * A->rmap->n));
19843a40ed3dSBarry Smith   } else if (type == NORM_INFINITY) {
1985064f8208SBarry Smith     *nrm = 0.0;
1986d0f46423SBarry Smith     for (j = 0; j < A->rmap->n; j++) {
1987ca15aa20SStefano Zampini       v   = vv + j;
1988289bc588SBarry Smith       sum = 0.0;
1989d0f46423SBarry Smith       for (i = 0; i < A->cmap->n; i++) {
19909371c9d4SSatish Balay         sum += PetscAbsScalar(*v);
19919371c9d4SSatish Balay         v += mat->lda;
1992289bc588SBarry Smith       }
1993064f8208SBarry Smith       if (sum > *nrm) *nrm = sum;
1994289bc588SBarry Smith     }
19959566063dSJacob Faibussowitsch     PetscCall(PetscLogFlops(1.0 * A->cmap->n * A->rmap->n));
1996e7e72b3dSBarry Smith   } else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "No two norm");
19979566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArrayRead(A, (const PetscScalar **)&vv));
19983ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1999289bc588SBarry Smith }
2000289bc588SBarry Smith 
2001d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatSetOption_SeqDense(Mat A, MatOption op, PetscBool flg)
2002d71ae5a4SJacob Faibussowitsch {
2003c0bbcb79SLois Curfman McInnes   Mat_SeqDense *aij = (Mat_SeqDense *)A->data;
200467e560aaSBarry Smith 
20053a40ed3dSBarry Smith   PetscFunctionBegin;
2006b5a2b587SKris Buschelman   switch (op) {
2007d71ae5a4SJacob Faibussowitsch   case MAT_ROW_ORIENTED:
2008d71ae5a4SJacob Faibussowitsch     aij->roworiented = flg;
2009d71ae5a4SJacob Faibussowitsch     break;
2010d71ae5a4SJacob Faibussowitsch   default:
2011888c827cSStefano Zampini     break;
20123a40ed3dSBarry Smith   }
20133ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2014289bc588SBarry Smith }
2015289bc588SBarry Smith 
2016d71ae5a4SJacob Faibussowitsch PetscErrorCode MatZeroEntries_SeqDense(Mat A)
2017d71ae5a4SJacob Faibussowitsch {
2018ec8511deSBarry Smith   Mat_SeqDense *l   = (Mat_SeqDense *)A->data;
20193d8925e7SStefano Zampini   PetscInt      lda = l->lda, m = A->rmap->n, n = A->cmap->n, j;
2020ca15aa20SStefano Zampini   PetscScalar  *v;
20213a40ed3dSBarry Smith 
20223a40ed3dSBarry Smith   PetscFunctionBegin;
20239566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArrayWrite(A, &v));
2024a5ce6ee0Svictorle   if (lda > m) {
202548a46eb9SPierre Jolivet     for (j = 0; j < n; j++) PetscCall(PetscArrayzero(v + j * lda, m));
2026a5ce6ee0Svictorle   } else {
20279566063dSJacob Faibussowitsch     PetscCall(PetscArrayzero(v, PetscInt64Mult(m, n)));
2028a5ce6ee0Svictorle   }
20299566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArrayWrite(A, &v));
20303ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
20316f0a148fSBarry Smith }
20326f0a148fSBarry Smith 
2033d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatZeroRows_SeqDense(Mat A, PetscInt N, const PetscInt rows[], PetscScalar diag, Vec x, Vec b)
2034d71ae5a4SJacob Faibussowitsch {
2035ec8511deSBarry Smith   Mat_SeqDense      *l = (Mat_SeqDense *)A->data;
2036b9679d65SBarry Smith   PetscInt           m = l->lda, n = A->cmap->n, i, j;
2037ca15aa20SStefano Zampini   PetscScalar       *slot, *bb, *v;
203897b48c8fSBarry Smith   const PetscScalar *xx;
203955659b69SBarry Smith 
20403a40ed3dSBarry Smith   PetscFunctionBegin;
204176bd3646SJed Brown   if (PetscDefined(USE_DEBUG)) {
2042b9679d65SBarry Smith     for (i = 0; i < N; i++) {
204308401ef6SPierre Jolivet       PetscCheck(rows[i] >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Negative row requested to be zeroed");
204408401ef6SPierre 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);
2045b9679d65SBarry Smith     }
204676bd3646SJed Brown   }
20473ba16761SJacob Faibussowitsch   if (!N) PetscFunctionReturn(PETSC_SUCCESS);
2048b9679d65SBarry Smith 
2049dd8e379bSPierre Jolivet   /* fix right-hand side if needed */
205097b48c8fSBarry Smith   if (x && b) {
20519566063dSJacob Faibussowitsch     PetscCall(VecGetArrayRead(x, &xx));
20529566063dSJacob Faibussowitsch     PetscCall(VecGetArray(b, &bb));
20532205254eSKarl Rupp     for (i = 0; i < N; i++) bb[rows[i]] = diag * xx[rows[i]];
20549566063dSJacob Faibussowitsch     PetscCall(VecRestoreArrayRead(x, &xx));
20559566063dSJacob Faibussowitsch     PetscCall(VecRestoreArray(b, &bb));
205697b48c8fSBarry Smith   }
205797b48c8fSBarry Smith 
20589566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArray(A, &v));
20596f0a148fSBarry Smith   for (i = 0; i < N; i++) {
2060ca15aa20SStefano Zampini     slot = v + rows[i];
20619371c9d4SSatish Balay     for (j = 0; j < n; j++) {
20629371c9d4SSatish Balay       *slot = 0.0;
20639371c9d4SSatish Balay       slot += m;
20649371c9d4SSatish Balay     }
20656f0a148fSBarry Smith   }
2066f4df32b1SMatthew Knepley   if (diag != 0.0) {
206708401ef6SPierre Jolivet     PetscCheck(A->rmap->n == A->cmap->n, PETSC_COMM_SELF, PETSC_ERR_SUP, "Only coded for square matrices");
20686f0a148fSBarry Smith     for (i = 0; i < N; i++) {
2069ca15aa20SStefano Zampini       slot  = v + (m + 1) * rows[i];
2070f4df32b1SMatthew Knepley       *slot = diag;
20716f0a148fSBarry Smith     }
20726f0a148fSBarry Smith   }
20739566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArray(A, &v));
20743ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
20756f0a148fSBarry Smith }
2076557bce09SLois Curfman McInnes 
2077d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatDenseGetLDA_SeqDense(Mat A, PetscInt *lda)
2078d71ae5a4SJacob Faibussowitsch {
207949a6ff4bSBarry Smith   Mat_SeqDense *mat = (Mat_SeqDense *)A->data;
208049a6ff4bSBarry Smith 
208149a6ff4bSBarry Smith   PetscFunctionBegin;
208249a6ff4bSBarry Smith   *lda = mat->lda;
20833ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
208449a6ff4bSBarry Smith }
208549a6ff4bSBarry Smith 
2086d71ae5a4SJacob Faibussowitsch PetscErrorCode MatDenseGetArray_SeqDense(Mat A, PetscScalar **array)
2087d71ae5a4SJacob Faibussowitsch {
2088c0bbcb79SLois Curfman McInnes   Mat_SeqDense *mat = (Mat_SeqDense *)A->data;
20893a40ed3dSBarry Smith 
20903a40ed3dSBarry Smith   PetscFunctionBegin;
209128b400f6SJacob Faibussowitsch   PetscCheck(!mat->matinuse, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Need to call MatDenseRestoreSubMatrix() first");
209264e87e97SBarry Smith   *array = mat->v;
20933ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
209464e87e97SBarry Smith }
20950754003eSLois Curfman McInnes 
2096d71ae5a4SJacob Faibussowitsch PetscErrorCode MatDenseRestoreArray_SeqDense(Mat A, PetscScalar **array)
2097d71ae5a4SJacob Faibussowitsch {
20983a40ed3dSBarry Smith   PetscFunctionBegin;
209975f6d85dSStefano Zampini   if (array) *array = NULL;
21003ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2101ff14e315SSatish Balay }
21020754003eSLois Curfman McInnes 
21030f74d2c1SSatish Balay /*@
210411a5261eSBarry Smith   MatDenseGetLDA - gets the leading dimension of the array returned from `MatDenseGetArray()`
210549a6ff4bSBarry Smith 
21062ef1f0ffSBarry Smith   Not Collective
210749a6ff4bSBarry Smith 
210849a6ff4bSBarry Smith   Input Parameter:
2109fe59aa6dSJacob Faibussowitsch . A - a `MATDENSE` or `MATDENSECUDA` matrix
211049a6ff4bSBarry Smith 
211149a6ff4bSBarry Smith   Output Parameter:
211249a6ff4bSBarry Smith . lda - the leading dimension
211349a6ff4bSBarry Smith 
211449a6ff4bSBarry Smith   Level: intermediate
211549a6ff4bSBarry Smith 
21161cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATDENSE`, `MATDENSECUDA`, `MatDenseGetArray()`, `MatDenseRestoreArray()`, `MatDenseGetArrayRead()`, `MatDenseRestoreArrayRead()`, `MatDenseSetLDA()`
211749a6ff4bSBarry Smith @*/
2118d71ae5a4SJacob Faibussowitsch PetscErrorCode MatDenseGetLDA(Mat A, PetscInt *lda)
2119d71ae5a4SJacob Faibussowitsch {
212049a6ff4bSBarry Smith   PetscFunctionBegin;
2121d5ea218eSStefano Zampini   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
21224f572ea9SToby Isaac   PetscAssertPointer(lda, 2);
212375f6d85dSStefano Zampini   MatCheckPreallocated(A, 1);
2124cac4c232SBarry Smith   PetscUseMethod(A, "MatDenseGetLDA_C", (Mat, PetscInt *), (A, lda));
21253ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
212649a6ff4bSBarry Smith }
212749a6ff4bSBarry Smith 
21280f74d2c1SSatish Balay /*@
212911a5261eSBarry Smith   MatDenseSetLDA - Sets the leading dimension of the array used by the `MATDENSE` matrix
2130ad16ce7aSStefano Zampini 
21312323109cSBarry Smith   Collective if the matrix layouts have not yet been setup
2132ad16ce7aSStefano Zampini 
2133d8d19677SJose E. Roman   Input Parameters:
2134fe59aa6dSJacob Faibussowitsch + A   - a `MATDENSE` or `MATDENSECUDA` matrix
2135ad16ce7aSStefano Zampini - lda - the leading dimension
2136ad16ce7aSStefano Zampini 
2137ad16ce7aSStefano Zampini   Level: intermediate
2138ad16ce7aSStefano Zampini 
21391cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATDENSE`, `MATDENSECUDA`, `MatDenseGetArray()`, `MatDenseRestoreArray()`, `MatDenseGetArrayRead()`, `MatDenseRestoreArrayRead()`, `MatDenseGetLDA()`
2140ad16ce7aSStefano Zampini @*/
2141d71ae5a4SJacob Faibussowitsch PetscErrorCode MatDenseSetLDA(Mat A, PetscInt lda)
2142d71ae5a4SJacob Faibussowitsch {
2143ad16ce7aSStefano Zampini   PetscFunctionBegin;
2144ad16ce7aSStefano Zampini   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
2145cac4c232SBarry Smith   PetscTryMethod(A, "MatDenseSetLDA_C", (Mat, PetscInt), (A, lda));
21463ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2147ad16ce7aSStefano Zampini }
2148ad16ce7aSStefano Zampini 
2149ad16ce7aSStefano Zampini /*@C
215011a5261eSBarry Smith   MatDenseGetArray - gives read-write access to the array where the data for a `MATDENSE` matrix is stored
215173a71a0fSBarry Smith 
2152c3339decSBarry Smith   Logically Collective
215373a71a0fSBarry Smith 
215473a71a0fSBarry Smith   Input Parameter:
2155fe59aa6dSJacob Faibussowitsch . A - a dense matrix
215673a71a0fSBarry Smith 
215773a71a0fSBarry Smith   Output Parameter:
215873a71a0fSBarry Smith . array - pointer to the data
215973a71a0fSBarry Smith 
216073a71a0fSBarry Smith   Level: intermediate
216173a71a0fSBarry Smith 
21621cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATDENSE`, `MatDenseRestoreArray()`, `MatDenseGetArrayRead()`, `MatDenseRestoreArrayRead()`, `MatDenseGetArrayWrite()`, `MatDenseRestoreArrayWrite()`
216373a71a0fSBarry Smith @*/
2164ce78bad3SBarry Smith PetscErrorCode MatDenseGetArray(Mat A, PetscScalar *array[]) PeNS
2165d71ae5a4SJacob Faibussowitsch {
216673a71a0fSBarry Smith   PetscFunctionBegin;
2167d5ea218eSStefano Zampini   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
21684f572ea9SToby Isaac   PetscAssertPointer(array, 2);
2169cac4c232SBarry Smith   PetscUseMethod(A, "MatDenseGetArray_C", (Mat, PetscScalar **), (A, array));
21703ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
217173a71a0fSBarry Smith }
217273a71a0fSBarry Smith 
2173dec5eb66SMatthew G Knepley /*@C
217411a5261eSBarry Smith   MatDenseRestoreArray - returns access to the array where the data for a `MATDENSE` matrix is stored obtained by `MatDenseGetArray()`
217573a71a0fSBarry Smith 
2176c3339decSBarry Smith   Logically Collective
21778572280aSBarry Smith 
21788572280aSBarry Smith   Input Parameters:
2179fe59aa6dSJacob Faibussowitsch + A     - a dense matrix
21802ef1f0ffSBarry Smith - array - pointer to the data (may be `NULL`)
21818572280aSBarry Smith 
21828572280aSBarry Smith   Level: intermediate
21838572280aSBarry Smith 
21841cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATDENSE`, `MatDenseGetArray()`, `MatDenseGetArrayRead()`, `MatDenseRestoreArrayRead()`, `MatDenseGetArrayWrite()`, `MatDenseRestoreArrayWrite()`
21858572280aSBarry Smith @*/
2186ce78bad3SBarry Smith PetscErrorCode MatDenseRestoreArray(Mat A, PetscScalar *array[]) PeNS
2187d71ae5a4SJacob Faibussowitsch {
21888572280aSBarry Smith   PetscFunctionBegin;
2189d5ea218eSStefano Zampini   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
21904f572ea9SToby Isaac   if (array) PetscAssertPointer(array, 2);
2191cac4c232SBarry Smith   PetscUseMethod(A, "MatDenseRestoreArray_C", (Mat, PetscScalar **), (A, array));
21929566063dSJacob Faibussowitsch   PetscCall(PetscObjectStateIncrease((PetscObject)A));
219347d993e7Ssuyashtn #if defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
2194637a0070SStefano Zampini   A->offloadmask = PETSC_OFFLOAD_CPU;
2195637a0070SStefano Zampini #endif
21963ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
21978572280aSBarry Smith }
21988572280aSBarry Smith 
21998572280aSBarry Smith /*@C
220011a5261eSBarry Smith   MatDenseGetArrayRead - gives read-only access to the array where the data for a `MATDENSE` matrix is stored
22018572280aSBarry Smith 
2202fb850c59SBarry Smith   Not Collective
22038572280aSBarry Smith 
22048572280aSBarry Smith   Input Parameter:
2205fe59aa6dSJacob Faibussowitsch . A - a dense matrix
22068572280aSBarry Smith 
22078572280aSBarry Smith   Output Parameter:
22088572280aSBarry Smith . array - pointer to the data
22098572280aSBarry Smith 
22108572280aSBarry Smith   Level: intermediate
22118572280aSBarry Smith 
22121cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATDENSE`, `MatDenseRestoreArrayRead()`, `MatDenseGetArray()`, `MatDenseRestoreArray()`, `MatDenseGetArrayWrite()`, `MatDenseRestoreArrayWrite()`
22138572280aSBarry Smith @*/
2214ce78bad3SBarry Smith PetscErrorCode MatDenseGetArrayRead(Mat A, const PetscScalar *array[]) PeNS
2215d71ae5a4SJacob Faibussowitsch {
22168572280aSBarry Smith   PetscFunctionBegin;
2217d5ea218eSStefano Zampini   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
22184f572ea9SToby Isaac   PetscAssertPointer(array, 2);
22195c0db29aSPierre Jolivet   PetscUseMethod(A, "MatDenseGetArrayRead_C", (Mat, PetscScalar **), (A, (PetscScalar **)array));
22203ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
22218572280aSBarry Smith }
22228572280aSBarry Smith 
22238572280aSBarry Smith /*@C
222411a5261eSBarry Smith   MatDenseRestoreArrayRead - returns access to the array where the data for a `MATDENSE` matrix is stored obtained by `MatDenseGetArrayRead()`
22258572280aSBarry Smith 
2226fb850c59SBarry Smith   Not Collective
222773a71a0fSBarry Smith 
222873a71a0fSBarry Smith   Input Parameters:
2229fe59aa6dSJacob Faibussowitsch + A     - a dense matrix
22302ef1f0ffSBarry Smith - array - pointer to the data (may be `NULL`)
223173a71a0fSBarry Smith 
223273a71a0fSBarry Smith   Level: intermediate
223373a71a0fSBarry Smith 
22341cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATDENSE`, `MatDenseGetArrayRead()`, `MatDenseGetArray()`, `MatDenseRestoreArray()`, `MatDenseGetArrayWrite()`, `MatDenseRestoreArrayWrite()`
223573a71a0fSBarry Smith @*/
2236ce78bad3SBarry Smith PetscErrorCode MatDenseRestoreArrayRead(Mat A, const PetscScalar *array[]) PeNS
2237d71ae5a4SJacob Faibussowitsch {
223873a71a0fSBarry Smith   PetscFunctionBegin;
2239d5ea218eSStefano Zampini   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
22404f572ea9SToby Isaac   if (array) PetscAssertPointer(array, 2);
22415c0db29aSPierre Jolivet   PetscUseMethod(A, "MatDenseRestoreArrayRead_C", (Mat, PetscScalar **), (A, (PetscScalar **)array));
22423ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
224373a71a0fSBarry Smith }
224473a71a0fSBarry Smith 
22456947451fSStefano Zampini /*@C
224611a5261eSBarry Smith   MatDenseGetArrayWrite - gives write-only access to the array where the data for a `MATDENSE` matrix is stored
22476947451fSStefano Zampini 
2248fb850c59SBarry Smith   Not Collective
22496947451fSStefano Zampini 
22506947451fSStefano Zampini   Input Parameter:
2251fe59aa6dSJacob Faibussowitsch . A - a dense matrix
22526947451fSStefano Zampini 
22536947451fSStefano Zampini   Output Parameter:
22546947451fSStefano Zampini . array - pointer to the data
22556947451fSStefano Zampini 
22566947451fSStefano Zampini   Level: intermediate
22576947451fSStefano Zampini 
22581cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATDENSE`, `MatDenseRestoreArrayWrite()`, `MatDenseGetArray()`, `MatDenseRestoreArray()`, `MatDenseGetArrayRead()`, `MatDenseRestoreArrayRead()`
22596947451fSStefano Zampini @*/
2260ce78bad3SBarry Smith PetscErrorCode MatDenseGetArrayWrite(Mat A, PetscScalar *array[]) PeNS
2261d71ae5a4SJacob Faibussowitsch {
22626947451fSStefano Zampini   PetscFunctionBegin;
2263d5ea218eSStefano Zampini   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
22644f572ea9SToby Isaac   PetscAssertPointer(array, 2);
2265cac4c232SBarry Smith   PetscUseMethod(A, "MatDenseGetArrayWrite_C", (Mat, PetscScalar **), (A, array));
22663ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
22676947451fSStefano Zampini }
22686947451fSStefano Zampini 
22696947451fSStefano Zampini /*@C
227011a5261eSBarry Smith   MatDenseRestoreArrayWrite - returns access to the array where the data for a `MATDENSE` matrix is stored obtained by `MatDenseGetArrayWrite()`
22716947451fSStefano Zampini 
2272fb850c59SBarry Smith   Not Collective
22736947451fSStefano Zampini 
22746947451fSStefano Zampini   Input Parameters:
2275fe59aa6dSJacob Faibussowitsch + A     - a dense matrix
22762ef1f0ffSBarry Smith - array - pointer to the data (may be `NULL`)
22776947451fSStefano Zampini 
22786947451fSStefano Zampini   Level: intermediate
22796947451fSStefano Zampini 
22801cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATDENSE`, `MatDenseGetArrayWrite()`, `MatDenseGetArray()`, `MatDenseRestoreArray()`, `MatDenseGetArrayRead()`, `MatDenseRestoreArrayRead()`
22816947451fSStefano Zampini @*/
2282ce78bad3SBarry Smith PetscErrorCode MatDenseRestoreArrayWrite(Mat A, PetscScalar *array[]) PeNS
2283d71ae5a4SJacob Faibussowitsch {
22846947451fSStefano Zampini   PetscFunctionBegin;
2285d5ea218eSStefano Zampini   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
22864f572ea9SToby Isaac   if (array) PetscAssertPointer(array, 2);
2287cac4c232SBarry Smith   PetscUseMethod(A, "MatDenseRestoreArrayWrite_C", (Mat, PetscScalar **), (A, array));
22889566063dSJacob Faibussowitsch   PetscCall(PetscObjectStateIncrease((PetscObject)A));
228947d993e7Ssuyashtn #if defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
22906947451fSStefano Zampini   A->offloadmask = PETSC_OFFLOAD_CPU;
22916947451fSStefano Zampini #endif
22923ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
22936947451fSStefano Zampini }
22946947451fSStefano Zampini 
2295cd3f9d89SJunchao Zhang /*@C
2296cd3f9d89SJunchao Zhang   MatDenseGetArrayAndMemType - gives read-write access to the array where the data for a `MATDENSE` matrix is stored
2297cd3f9d89SJunchao Zhang 
2298cd3f9d89SJunchao Zhang   Logically Collective
2299cd3f9d89SJunchao Zhang 
2300cd3f9d89SJunchao Zhang   Input Parameter:
2301fe59aa6dSJacob Faibussowitsch . A - a dense matrix
2302cd3f9d89SJunchao Zhang 
2303cd3f9d89SJunchao Zhang   Output Parameters:
2304cd3f9d89SJunchao Zhang + array - pointer to the data
2305cd3f9d89SJunchao Zhang - mtype - memory type of the returned pointer
2306cd3f9d89SJunchao Zhang 
2307cd3f9d89SJunchao Zhang   Level: intermediate
2308cd3f9d89SJunchao Zhang 
2309fb850c59SBarry Smith   Note:
23102ef1f0ffSBarry Smith   If the matrix is of a device type such as `MATDENSECUDA`, `MATDENSEHIP`, etc.,
23112ef1f0ffSBarry Smith   an array on device is always returned and is guaranteed to contain the matrix's latest data.
23122ef1f0ffSBarry Smith 
23131cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATDENSE`, `MatDenseRestoreArrayAndMemType()`, `MatDenseGetArrayReadAndMemType()`, `MatDenseGetArrayWriteAndMemType()`, `MatDenseGetArrayRead()`,
2314cd3f9d89SJunchao Zhang    `MatDenseRestoreArrayRead()`, `MatDenseGetArrayWrite()`, `MatDenseRestoreArrayWrite()`, `MatSeqAIJGetCSRAndMemType()`
2315cd3f9d89SJunchao Zhang @*/
23165d83a8b1SBarry Smith PetscErrorCode MatDenseGetArrayAndMemType(Mat A, PetscScalar *array[], PetscMemType *mtype)
2317cd3f9d89SJunchao Zhang {
2318cd3f9d89SJunchao Zhang   PetscBool isMPI;
2319cd3f9d89SJunchao Zhang 
2320cd3f9d89SJunchao Zhang   PetscFunctionBegin;
2321cd3f9d89SJunchao Zhang   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
23224f572ea9SToby Isaac   PetscAssertPointer(array, 2);
2323e865de01SJunchao 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 */
2324cd3f9d89SJunchao Zhang   PetscCall(PetscObjectBaseTypeCompare((PetscObject)A, MATMPIDENSE, &isMPI));
2325cd3f9d89SJunchao Zhang   if (isMPI) {
2326cd3f9d89SJunchao Zhang     /* Dispatch here so that the code can be reused for all subclasses of MATDENSE */
2327cd3f9d89SJunchao Zhang     PetscCall(MatDenseGetArrayAndMemType(((Mat_MPIDense *)A->data)->A, array, mtype));
2328cd3f9d89SJunchao Zhang   } else {
2329cd3f9d89SJunchao Zhang     PetscErrorCode (*fptr)(Mat, PetscScalar **, PetscMemType *);
23303ba16761SJacob Faibussowitsch 
23313ba16761SJacob Faibussowitsch     PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatDenseGetArrayAndMemType_C", &fptr));
2332cd3f9d89SJunchao Zhang     if (fptr) {
2333cd3f9d89SJunchao Zhang       PetscCall((*fptr)(A, array, mtype));
2334cd3f9d89SJunchao Zhang     } else {
2335cd3f9d89SJunchao Zhang       PetscUseMethod(A, "MatDenseGetArray_C", (Mat, PetscScalar **), (A, array));
2336cd3f9d89SJunchao Zhang       if (mtype) *mtype = PETSC_MEMTYPE_HOST;
2337cd3f9d89SJunchao Zhang     }
2338cd3f9d89SJunchao Zhang   }
23393ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2340cd3f9d89SJunchao Zhang }
2341cd3f9d89SJunchao Zhang 
2342cd3f9d89SJunchao Zhang /*@C
2343cd3f9d89SJunchao Zhang   MatDenseRestoreArrayAndMemType - returns access to the array that is obtained by `MatDenseGetArrayAndMemType()`
2344cd3f9d89SJunchao Zhang 
2345cd3f9d89SJunchao Zhang   Logically Collective
2346cd3f9d89SJunchao Zhang 
2347cd3f9d89SJunchao Zhang   Input Parameters:
2348fe59aa6dSJacob Faibussowitsch + A     - a dense matrix
2349cd3f9d89SJunchao Zhang - array - pointer to the data
2350cd3f9d89SJunchao Zhang 
2351cd3f9d89SJunchao Zhang   Level: intermediate
2352cd3f9d89SJunchao Zhang 
23531cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATDENSE`, `MatDenseGetArrayAndMemType()`, `MatDenseGetArray()`, `MatDenseGetArrayRead()`, `MatDenseRestoreArrayRead()`, `MatDenseGetArrayWrite()`, `MatDenseRestoreArrayWrite()`
2354cd3f9d89SJunchao Zhang @*/
23555d83a8b1SBarry Smith PetscErrorCode MatDenseRestoreArrayAndMemType(Mat A, PetscScalar *array[])
2356cd3f9d89SJunchao Zhang {
2357cd3f9d89SJunchao Zhang   PetscBool isMPI;
2358cd3f9d89SJunchao Zhang 
2359cd3f9d89SJunchao Zhang   PetscFunctionBegin;
2360cd3f9d89SJunchao Zhang   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
2361fd5c2d83SStefano Zampini   if (array) PetscAssertPointer(array, 2);
2362cd3f9d89SJunchao Zhang   PetscCall(PetscObjectBaseTypeCompare((PetscObject)A, MATMPIDENSE, &isMPI));
2363cd3f9d89SJunchao Zhang   if (isMPI) {
2364cd3f9d89SJunchao Zhang     PetscCall(MatDenseRestoreArrayAndMemType(((Mat_MPIDense *)A->data)->A, array));
2365cd3f9d89SJunchao Zhang   } else {
2366cd3f9d89SJunchao Zhang     PetscErrorCode (*fptr)(Mat, PetscScalar **);
23673ba16761SJacob Faibussowitsch 
23683ba16761SJacob Faibussowitsch     PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatDenseRestoreArrayAndMemType_C", &fptr));
2369cd3f9d89SJunchao Zhang     if (fptr) {
2370cd3f9d89SJunchao Zhang       PetscCall((*fptr)(A, array));
2371cd3f9d89SJunchao Zhang     } else {
2372cd3f9d89SJunchao Zhang       PetscUseMethod(A, "MatDenseRestoreArray_C", (Mat, PetscScalar **), (A, array));
2373cd3f9d89SJunchao Zhang     }
2374fd5c2d83SStefano Zampini     if (array) *array = NULL;
2375cd3f9d89SJunchao Zhang   }
2376cd3f9d89SJunchao Zhang   PetscCall(PetscObjectStateIncrease((PetscObject)A));
23773ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2378cd3f9d89SJunchao Zhang }
2379cd3f9d89SJunchao Zhang 
2380cd3f9d89SJunchao Zhang /*@C
2381cd3f9d89SJunchao Zhang   MatDenseGetArrayReadAndMemType - gives read-only access to the array where the data for a `MATDENSE` matrix is stored
2382cd3f9d89SJunchao Zhang 
2383cd3f9d89SJunchao Zhang   Logically Collective
2384cd3f9d89SJunchao Zhang 
2385cd3f9d89SJunchao Zhang   Input Parameter:
2386fe59aa6dSJacob Faibussowitsch . A - a dense matrix
2387cd3f9d89SJunchao Zhang 
2388cd3f9d89SJunchao Zhang   Output Parameters:
2389cd3f9d89SJunchao Zhang + array - pointer to the data
2390cd3f9d89SJunchao Zhang - mtype - memory type of the returned pointer
2391cd3f9d89SJunchao Zhang 
2392cd3f9d89SJunchao Zhang   Level: intermediate
2393cd3f9d89SJunchao Zhang 
2394fb850c59SBarry Smith   Note:
23952ef1f0ffSBarry Smith   If the matrix is of a device type such as `MATDENSECUDA`, `MATDENSEHIP`, etc.,
23962ef1f0ffSBarry Smith   an array on device is always returned and is guaranteed to contain the matrix's latest data.
23972ef1f0ffSBarry Smith 
23981cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATDENSE`, `MatDenseRestoreArrayReadAndMemType()`, `MatDenseGetArrayWriteAndMemType()`,
2399cd3f9d89SJunchao Zhang    `MatDenseGetArrayRead()`, `MatDenseRestoreArrayRead()`, `MatDenseGetArrayWrite()`, `MatDenseRestoreArrayWrite()`, `MatSeqAIJGetCSRAndMemType()`
2400cd3f9d89SJunchao Zhang @*/
24015d83a8b1SBarry Smith PetscErrorCode MatDenseGetArrayReadAndMemType(Mat A, const PetscScalar *array[], PetscMemType *mtype)
2402cd3f9d89SJunchao Zhang {
2403cd3f9d89SJunchao Zhang   PetscBool isMPI;
2404cd3f9d89SJunchao Zhang 
2405cd3f9d89SJunchao Zhang   PetscFunctionBegin;
2406cd3f9d89SJunchao Zhang   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
24074f572ea9SToby Isaac   PetscAssertPointer(array, 2);
2408e865de01SJunchao 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 */
2409cd3f9d89SJunchao Zhang   PetscCall(PetscObjectBaseTypeCompare((PetscObject)A, MATMPIDENSE, &isMPI));
2410cd3f9d89SJunchao Zhang   if (isMPI) { /* Dispatch here so that the code can be reused for all subclasses of MATDENSE */
2411cd3f9d89SJunchao Zhang     PetscCall(MatDenseGetArrayReadAndMemType(((Mat_MPIDense *)A->data)->A, array, mtype));
2412cd3f9d89SJunchao Zhang   } else {
2413cd3f9d89SJunchao Zhang     PetscErrorCode (*fptr)(Mat, const PetscScalar **, PetscMemType *);
24143ba16761SJacob Faibussowitsch 
24153ba16761SJacob Faibussowitsch     PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatDenseGetArrayReadAndMemType_C", &fptr));
2416cd3f9d89SJunchao Zhang     if (fptr) {
2417cd3f9d89SJunchao Zhang       PetscCall((*fptr)(A, array, mtype));
2418cd3f9d89SJunchao Zhang     } else {
24195c0db29aSPierre Jolivet       PetscUseMethod(A, "MatDenseGetArrayRead_C", (Mat, PetscScalar **), (A, (PetscScalar **)array));
2420cd3f9d89SJunchao Zhang       if (mtype) *mtype = PETSC_MEMTYPE_HOST;
2421cd3f9d89SJunchao Zhang     }
2422cd3f9d89SJunchao Zhang   }
24233ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2424cd3f9d89SJunchao Zhang }
2425cd3f9d89SJunchao Zhang 
2426cd3f9d89SJunchao Zhang /*@C
2427cd3f9d89SJunchao Zhang   MatDenseRestoreArrayReadAndMemType - returns access to the array that is obtained by `MatDenseGetArrayReadAndMemType()`
2428cd3f9d89SJunchao Zhang 
2429cd3f9d89SJunchao Zhang   Logically Collective
2430cd3f9d89SJunchao Zhang 
2431cd3f9d89SJunchao Zhang   Input Parameters:
2432fe59aa6dSJacob Faibussowitsch + A     - a dense matrix
2433cd3f9d89SJunchao Zhang - array - pointer to the data
2434cd3f9d89SJunchao Zhang 
2435cd3f9d89SJunchao Zhang   Level: intermediate
2436cd3f9d89SJunchao Zhang 
24371cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATDENSE`, `MatDenseGetArrayReadAndMemType()`, `MatDenseGetArray()`, `MatDenseGetArrayRead()`, `MatDenseRestoreArrayRead()`, `MatDenseGetArrayWrite()`, `MatDenseRestoreArrayWrite()`
2438cd3f9d89SJunchao Zhang @*/
24395d83a8b1SBarry Smith PetscErrorCode MatDenseRestoreArrayReadAndMemType(Mat A, const PetscScalar *array[])
2440cd3f9d89SJunchao Zhang {
2441cd3f9d89SJunchao Zhang   PetscBool isMPI;
2442cd3f9d89SJunchao Zhang 
2443cd3f9d89SJunchao Zhang   PetscFunctionBegin;
2444cd3f9d89SJunchao Zhang   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
2445fd5c2d83SStefano Zampini   if (array) PetscAssertPointer(array, 2);
2446cd3f9d89SJunchao Zhang   PetscCall(PetscObjectBaseTypeCompare((PetscObject)A, MATMPIDENSE, &isMPI));
2447cd3f9d89SJunchao Zhang   if (isMPI) {
2448cd3f9d89SJunchao Zhang     PetscCall(MatDenseRestoreArrayReadAndMemType(((Mat_MPIDense *)A->data)->A, array));
2449cd3f9d89SJunchao Zhang   } else {
2450cd3f9d89SJunchao Zhang     PetscErrorCode (*fptr)(Mat, const PetscScalar **);
24513ba16761SJacob Faibussowitsch 
24523ba16761SJacob Faibussowitsch     PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatDenseRestoreArrayReadAndMemType_C", &fptr));
2453cd3f9d89SJunchao Zhang     if (fptr) {
2454cd3f9d89SJunchao Zhang       PetscCall((*fptr)(A, array));
2455cd3f9d89SJunchao Zhang     } else {
24565c0db29aSPierre Jolivet       PetscUseMethod(A, "MatDenseRestoreArrayRead_C", (Mat, PetscScalar **), (A, (PetscScalar **)array));
2457cd3f9d89SJunchao Zhang     }
2458fd5c2d83SStefano Zampini     if (array) *array = NULL;
2459cd3f9d89SJunchao Zhang   }
24603ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2461cd3f9d89SJunchao Zhang }
2462cd3f9d89SJunchao Zhang 
2463cd3f9d89SJunchao Zhang /*@C
2464cd3f9d89SJunchao Zhang   MatDenseGetArrayWriteAndMemType - gives write-only access to the array where the data for a `MATDENSE` matrix is stored
2465cd3f9d89SJunchao Zhang 
2466cd3f9d89SJunchao Zhang   Logically Collective
2467cd3f9d89SJunchao Zhang 
2468cd3f9d89SJunchao Zhang   Input Parameter:
2469fe59aa6dSJacob Faibussowitsch . A - a dense matrix
2470cd3f9d89SJunchao Zhang 
2471cd3f9d89SJunchao Zhang   Output Parameters:
2472cd3f9d89SJunchao Zhang + array - pointer to the data
2473cd3f9d89SJunchao Zhang - mtype - memory type of the returned pointer
2474cd3f9d89SJunchao Zhang 
2475cd3f9d89SJunchao Zhang   Level: intermediate
2476cd3f9d89SJunchao Zhang 
2477fb850c59SBarry Smith   Note:
24782ef1f0ffSBarry Smith   If the matrix is of a device type such as `MATDENSECUDA`, `MATDENSEHIP`, etc.,
24792ef1f0ffSBarry Smith   an array on device is always returned and is guaranteed to contain the matrix's latest data.
24802ef1f0ffSBarry Smith 
24811cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATDENSE`, `MatDenseRestoreArrayWriteAndMemType()`, `MatDenseGetArrayReadAndMemType()`, `MatDenseGetArrayRead()`,
2482cd3f9d89SJunchao Zhang   `MatDenseRestoreArrayRead()`, `MatDenseGetArrayWrite()`, `MatDenseRestoreArrayWrite()`, `MatSeqAIJGetCSRAndMemType()`
2483cd3f9d89SJunchao Zhang @*/
24845d83a8b1SBarry Smith PetscErrorCode MatDenseGetArrayWriteAndMemType(Mat A, PetscScalar *array[], PetscMemType *mtype)
2485cd3f9d89SJunchao Zhang {
2486cd3f9d89SJunchao Zhang   PetscBool isMPI;
2487cd3f9d89SJunchao Zhang 
2488cd3f9d89SJunchao Zhang   PetscFunctionBegin;
2489cd3f9d89SJunchao Zhang   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
24904f572ea9SToby Isaac   PetscAssertPointer(array, 2);
2491e865de01SJunchao 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 */
2492cd3f9d89SJunchao Zhang   PetscCall(PetscObjectBaseTypeCompare((PetscObject)A, MATMPIDENSE, &isMPI));
2493cd3f9d89SJunchao Zhang   if (isMPI) {
2494cd3f9d89SJunchao Zhang     PetscCall(MatDenseGetArrayWriteAndMemType(((Mat_MPIDense *)A->data)->A, array, mtype));
2495cd3f9d89SJunchao Zhang   } else {
2496cd3f9d89SJunchao Zhang     PetscErrorCode (*fptr)(Mat, PetscScalar **, PetscMemType *);
24973ba16761SJacob Faibussowitsch 
24983ba16761SJacob Faibussowitsch     PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatDenseGetArrayWriteAndMemType_C", &fptr));
2499cd3f9d89SJunchao Zhang     if (fptr) {
2500cd3f9d89SJunchao Zhang       PetscCall((*fptr)(A, array, mtype));
2501cd3f9d89SJunchao Zhang     } else {
2502cd3f9d89SJunchao Zhang       PetscUseMethod(A, "MatDenseGetArrayWrite_C", (Mat, PetscScalar **), (A, array));
2503cd3f9d89SJunchao Zhang       if (mtype) *mtype = PETSC_MEMTYPE_HOST;
2504cd3f9d89SJunchao Zhang     }
2505cd3f9d89SJunchao Zhang   }
25063ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2507cd3f9d89SJunchao Zhang }
2508cd3f9d89SJunchao Zhang 
2509cd3f9d89SJunchao Zhang /*@C
2510cd3f9d89SJunchao Zhang   MatDenseRestoreArrayWriteAndMemType - returns access to the array that is obtained by `MatDenseGetArrayReadAndMemType()`
2511cd3f9d89SJunchao Zhang 
2512cd3f9d89SJunchao Zhang   Logically Collective
2513cd3f9d89SJunchao Zhang 
2514cd3f9d89SJunchao Zhang   Input Parameters:
2515fe59aa6dSJacob Faibussowitsch + A     - a dense matrix
2516cd3f9d89SJunchao Zhang - array - pointer to the data
2517cd3f9d89SJunchao Zhang 
2518cd3f9d89SJunchao Zhang   Level: intermediate
2519cd3f9d89SJunchao Zhang 
25201cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATDENSE`, `MatDenseGetArrayWriteAndMemType()`, `MatDenseGetArray()`, `MatDenseGetArrayRead()`, `MatDenseRestoreArrayRead()`, `MatDenseGetArrayWrite()`, `MatDenseRestoreArrayWrite()`
2521cd3f9d89SJunchao Zhang @*/
25225d83a8b1SBarry Smith PetscErrorCode MatDenseRestoreArrayWriteAndMemType(Mat A, PetscScalar *array[])
2523cd3f9d89SJunchao Zhang {
2524cd3f9d89SJunchao Zhang   PetscBool isMPI;
2525cd3f9d89SJunchao Zhang 
2526cd3f9d89SJunchao Zhang   PetscFunctionBegin;
2527cd3f9d89SJunchao Zhang   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
2528fd5c2d83SStefano Zampini   if (array) PetscAssertPointer(array, 2);
2529cd3f9d89SJunchao Zhang   PetscCall(PetscObjectBaseTypeCompare((PetscObject)A, MATMPIDENSE, &isMPI));
2530cd3f9d89SJunchao Zhang   if (isMPI) {
2531cd3f9d89SJunchao Zhang     PetscCall(MatDenseRestoreArrayWriteAndMemType(((Mat_MPIDense *)A->data)->A, array));
2532cd3f9d89SJunchao Zhang   } else {
2533cd3f9d89SJunchao Zhang     PetscErrorCode (*fptr)(Mat, PetscScalar **);
25343ba16761SJacob Faibussowitsch 
25353ba16761SJacob Faibussowitsch     PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatDenseRestoreArrayWriteAndMemType_C", &fptr));
2536cd3f9d89SJunchao Zhang     if (fptr) {
2537cd3f9d89SJunchao Zhang       PetscCall((*fptr)(A, array));
2538cd3f9d89SJunchao Zhang     } else {
2539cd3f9d89SJunchao Zhang       PetscUseMethod(A, "MatDenseRestoreArrayWrite_C", (Mat, PetscScalar **), (A, array));
2540cd3f9d89SJunchao Zhang     }
2541fd5c2d83SStefano Zampini     if (array) *array = NULL;
2542cd3f9d89SJunchao Zhang   }
2543cd3f9d89SJunchao Zhang   PetscCall(PetscObjectStateIncrease((PetscObject)A));
25443ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2545cd3f9d89SJunchao Zhang }
2546cd3f9d89SJunchao Zhang 
2547d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatCreateSubMatrix_SeqDense(Mat A, IS isrow, IS iscol, MatReuse scall, Mat *B)
2548d71ae5a4SJacob Faibussowitsch {
2549c0bbcb79SLois Curfman McInnes   Mat_SeqDense   *mat = (Mat_SeqDense *)A->data;
2550bf5a80bcSToby Isaac   PetscInt        i, j, nrows, ncols, ldb;
25515d0c19d7SBarry Smith   const PetscInt *irow, *icol;
255287828ca2SBarry Smith   PetscScalar    *av, *bv, *v = mat->v;
25530754003eSLois Curfman McInnes   Mat             newmat;
25540754003eSLois Curfman McInnes 
25553a40ed3dSBarry Smith   PetscFunctionBegin;
25569566063dSJacob Faibussowitsch   PetscCall(ISGetIndices(isrow, &irow));
25579566063dSJacob Faibussowitsch   PetscCall(ISGetIndices(iscol, &icol));
25589566063dSJacob Faibussowitsch   PetscCall(ISGetLocalSize(isrow, &nrows));
25599566063dSJacob Faibussowitsch   PetscCall(ISGetLocalSize(iscol, &ncols));
25600754003eSLois Curfman McInnes 
2561182d2002SSatish Balay   /* Check submatrixcall */
2562182d2002SSatish Balay   if (scall == MAT_REUSE_MATRIX) {
256313f74950SBarry Smith     PetscInt n_cols, n_rows;
25649566063dSJacob Faibussowitsch     PetscCall(MatGetSize(*B, &n_rows, &n_cols));
256521a2c019SBarry Smith     if (n_rows != nrows || n_cols != ncols) {
2566f746d493SDmitry Karpeev       /* resize the result matrix to match number of requested rows/columns */
25679566063dSJacob Faibussowitsch       PetscCall(MatSetSizes(*B, nrows, ncols, nrows, ncols));
256821a2c019SBarry Smith     }
2569182d2002SSatish Balay     newmat = *B;
2570182d2002SSatish Balay   } else {
25710754003eSLois Curfman McInnes     /* Create and fill new matrix */
25729566063dSJacob Faibussowitsch     PetscCall(MatCreate(PetscObjectComm((PetscObject)A), &newmat));
25739566063dSJacob Faibussowitsch     PetscCall(MatSetSizes(newmat, nrows, ncols, nrows, ncols));
25749566063dSJacob Faibussowitsch     PetscCall(MatSetType(newmat, ((PetscObject)A)->type_name));
25759566063dSJacob Faibussowitsch     PetscCall(MatSeqDenseSetPreallocation(newmat, NULL));
2576182d2002SSatish Balay   }
2577182d2002SSatish Balay 
2578182d2002SSatish Balay   /* Now extract the data pointers and do the copy,column at a time */
25799566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArray(newmat, &bv));
25809566063dSJacob Faibussowitsch   PetscCall(MatDenseGetLDA(newmat, &ldb));
2581182d2002SSatish Balay   for (i = 0; i < ncols; i++) {
25826de62eeeSBarry Smith     av = v + mat->lda * icol[i];
2583ca15aa20SStefano Zampini     for (j = 0; j < nrows; j++) bv[j] = av[irow[j]];
2584bf5a80bcSToby Isaac     bv += ldb;
25850754003eSLois Curfman McInnes   }
25869566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArray(newmat, &bv));
2587182d2002SSatish Balay 
2588182d2002SSatish Balay   /* Assemble the matrices so that the correct flags are set */
25899566063dSJacob Faibussowitsch   PetscCall(MatAssemblyBegin(newmat, MAT_FINAL_ASSEMBLY));
25909566063dSJacob Faibussowitsch   PetscCall(MatAssemblyEnd(newmat, MAT_FINAL_ASSEMBLY));
25910754003eSLois Curfman McInnes 
25920754003eSLois Curfman McInnes   /* Free work space */
25939566063dSJacob Faibussowitsch   PetscCall(ISRestoreIndices(isrow, &irow));
25949566063dSJacob Faibussowitsch   PetscCall(ISRestoreIndices(iscol, &icol));
2595182d2002SSatish Balay   *B = newmat;
25963ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
25970754003eSLois Curfman McInnes }
25980754003eSLois Curfman McInnes 
2599d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatCreateSubMatrices_SeqDense(Mat A, PetscInt n, const IS irow[], const IS icol[], MatReuse scall, Mat *B[])
2600d71ae5a4SJacob Faibussowitsch {
260113f74950SBarry Smith   PetscInt i;
2602905e6a2fSBarry Smith 
26033a40ed3dSBarry Smith   PetscFunctionBegin;
260448a46eb9SPierre Jolivet   if (scall == MAT_INITIAL_MATRIX) PetscCall(PetscCalloc1(n, B));
2605905e6a2fSBarry Smith 
260648a46eb9SPierre Jolivet   for (i = 0; i < n; i++) PetscCall(MatCreateSubMatrix_SeqDense(A, irow[i], icol[i], scall, &(*B)[i]));
26073ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2608905e6a2fSBarry Smith }
2609905e6a2fSBarry Smith 
2610d71ae5a4SJacob Faibussowitsch PetscErrorCode MatCopy_SeqDense(Mat A, Mat B, MatStructure str)
2611d71ae5a4SJacob Faibussowitsch {
26124b0e389bSBarry Smith   Mat_SeqDense      *a = (Mat_SeqDense *)A->data, *b = (Mat_SeqDense *)B->data;
2613ca15aa20SStefano Zampini   const PetscScalar *va;
2614ca15aa20SStefano Zampini   PetscScalar       *vb;
2615d0f46423SBarry Smith   PetscInt           lda1 = a->lda, lda2 = b->lda, m = A->rmap->n, n = A->cmap->n, j;
26163a40ed3dSBarry Smith 
26173a40ed3dSBarry Smith   PetscFunctionBegin;
261833f4a19fSKris Buschelman   /* If the two matrices don't have the same copy implementation, they aren't compatible for fast copy. */
261933f4a19fSKris Buschelman   if (A->ops->copy != B->ops->copy) {
26209566063dSJacob Faibussowitsch     PetscCall(MatCopy_Basic(A, B, str));
26213ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
26223a40ed3dSBarry Smith   }
2623aed4548fSBarry Smith   PetscCheck(m == B->rmap->n && n == B->cmap->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "size(B) != size(A)");
26249566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArrayRead(A, &va));
26259566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArray(B, &vb));
2626a5ce6ee0Svictorle   if (lda1 > m || lda2 > m) {
262748a46eb9SPierre Jolivet     for (j = 0; j < n; j++) PetscCall(PetscArraycpy(vb + j * lda2, va + j * lda1, m));
2628a5ce6ee0Svictorle   } else {
26299566063dSJacob Faibussowitsch     PetscCall(PetscArraycpy(vb, va, A->rmap->n * A->cmap->n));
2630a5ce6ee0Svictorle   }
26319566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArray(B, &vb));
26329566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArrayRead(A, &va));
26339566063dSJacob Faibussowitsch   PetscCall(MatAssemblyBegin(B, MAT_FINAL_ASSEMBLY));
26349566063dSJacob Faibussowitsch   PetscCall(MatAssemblyEnd(B, MAT_FINAL_ASSEMBLY));
26353ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2636273d9f13SBarry Smith }
2637273d9f13SBarry Smith 
2638d71ae5a4SJacob Faibussowitsch PetscErrorCode MatSetUp_SeqDense(Mat A)
2639d71ae5a4SJacob Faibussowitsch {
2640273d9f13SBarry Smith   PetscFunctionBegin;
26419566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetUp(A->rmap));
26429566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetUp(A->cmap));
264348a46eb9SPierre Jolivet   if (!A->preallocated) PetscCall(MatSeqDenseSetPreallocation(A, NULL));
26443ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
26454b0e389bSBarry Smith }
26464b0e389bSBarry Smith 
2647d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatConjugate_SeqDense(Mat A)
2648d71ae5a4SJacob Faibussowitsch {
26494396437dSToby Isaac   Mat_SeqDense *mat = (Mat_SeqDense *)A->data;
265006c5243aSJose E. Roman   PetscInt      i, j;
26514396437dSToby Isaac   PetscInt      min = PetscMin(A->rmap->n, A->cmap->n);
2652ca15aa20SStefano Zampini   PetscScalar  *aa;
2653ba337c44SJed Brown 
2654ba337c44SJed Brown   PetscFunctionBegin;
26559566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArray(A, &aa));
265606c5243aSJose E. Roman   for (j = 0; j < A->cmap->n; j++) {
265706c5243aSJose E. Roman     for (i = 0; i < A->rmap->n; i++) aa[i + j * mat->lda] = PetscConj(aa[i + j * mat->lda]);
265806c5243aSJose E. Roman   }
26599566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArray(A, &aa));
26609371c9d4SSatish Balay   if (mat->tau)
26619371c9d4SSatish Balay     for (i = 0; i < min; i++) mat->tau[i] = PetscConj(mat->tau[i]);
26623ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2663ba337c44SJed Brown }
2664ba337c44SJed Brown 
2665d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatRealPart_SeqDense(Mat A)
2666d71ae5a4SJacob Faibussowitsch {
266706c5243aSJose E. Roman   Mat_SeqDense *mat = (Mat_SeqDense *)A->data;
266806c5243aSJose E. Roman   PetscInt      i, j;
2669ca15aa20SStefano Zampini   PetscScalar  *aa;
2670ba337c44SJed Brown 
2671ba337c44SJed Brown   PetscFunctionBegin;
26729566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArray(A, &aa));
267306c5243aSJose E. Roman   for (j = 0; j < A->cmap->n; j++) {
267406c5243aSJose E. Roman     for (i = 0; i < A->rmap->n; i++) aa[i + j * mat->lda] = PetscRealPart(aa[i + j * mat->lda]);
267506c5243aSJose E. Roman   }
26769566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArray(A, &aa));
26773ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2678ba337c44SJed Brown }
2679ba337c44SJed Brown 
2680d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatImaginaryPart_SeqDense(Mat A)
2681d71ae5a4SJacob Faibussowitsch {
268206c5243aSJose E. Roman   Mat_SeqDense *mat = (Mat_SeqDense *)A->data;
268306c5243aSJose E. Roman   PetscInt      i, j;
2684ca15aa20SStefano Zampini   PetscScalar  *aa;
2685ba337c44SJed Brown 
2686ba337c44SJed Brown   PetscFunctionBegin;
26879566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArray(A, &aa));
268806c5243aSJose E. Roman   for (j = 0; j < A->cmap->n; j++) {
268906c5243aSJose E. Roman     for (i = 0; i < A->rmap->n; i++) aa[i + j * mat->lda] = PetscImaginaryPart(aa[i + j * mat->lda]);
269006c5243aSJose E. Roman   }
26919566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArray(A, &aa));
26923ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2693ba337c44SJed Brown }
2694284134d9SBarry Smith 
2695d71ae5a4SJacob Faibussowitsch PetscErrorCode MatMatMultSymbolic_SeqDense_SeqDense(Mat A, Mat B, PetscReal fill, Mat C)
2696d71ae5a4SJacob Faibussowitsch {
2697d0f46423SBarry Smith   PetscInt  m = A->rmap->n, n = B->cmap->n;
269847d993e7Ssuyashtn   PetscBool cisdense = PETSC_FALSE;
2699a9fe9ddaSSatish Balay 
2700ee16a9a1SHong Zhang   PetscFunctionBegin;
27019566063dSJacob Faibussowitsch   PetscCall(MatSetSizes(C, m, n, m, n));
270247d993e7Ssuyashtn #if defined(PETSC_HAVE_CUDA)
27039566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompareAny((PetscObject)C, &cisdense, MATSEQDENSE, MATSEQDENSECUDA, ""));
270447d993e7Ssuyashtn #endif
270547d993e7Ssuyashtn #if defined(PETSC_HAVE_HIP)
270647d993e7Ssuyashtn   PetscCall(PetscObjectTypeCompareAny((PetscObject)C, &cisdense, MATSEQDENSE, MATSEQDENSEHIP, ""));
270747d993e7Ssuyashtn #endif
27087a3c3d58SStefano Zampini   if (!cisdense) {
27097a3c3d58SStefano Zampini     PetscBool flg;
27107a3c3d58SStefano Zampini 
27119566063dSJacob Faibussowitsch     PetscCall(PetscObjectTypeCompare((PetscObject)B, ((PetscObject)A)->type_name, &flg));
27129566063dSJacob Faibussowitsch     PetscCall(MatSetType(C, flg ? ((PetscObject)A)->type_name : MATDENSE));
27137a3c3d58SStefano Zampini   }
27149566063dSJacob Faibussowitsch   PetscCall(MatSetUp(C));
27153ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2716ee16a9a1SHong Zhang }
2717a9fe9ddaSSatish Balay 
2718d71ae5a4SJacob Faibussowitsch PetscErrorCode MatMatMultNumeric_SeqDense_SeqDense(Mat A, Mat B, Mat C)
2719d71ae5a4SJacob Faibussowitsch {
27206718818eSStefano Zampini   Mat_SeqDense      *a = (Mat_SeqDense *)A->data, *b = (Mat_SeqDense *)B->data, *c = (Mat_SeqDense *)C->data;
27210805154bSBarry Smith   PetscBLASInt       m, n, k;
2722ca15aa20SStefano Zampini   const PetscScalar *av, *bv;
2723ca15aa20SStefano Zampini   PetscScalar       *cv;
2724a9fe9ddaSSatish Balay   PetscScalar        _DOne = 1.0, _DZero = 0.0;
2725a9fe9ddaSSatish Balay 
2726a9fe9ddaSSatish Balay   PetscFunctionBegin;
27279566063dSJacob Faibussowitsch   PetscCall(PetscBLASIntCast(C->rmap->n, &m));
27289566063dSJacob Faibussowitsch   PetscCall(PetscBLASIntCast(C->cmap->n, &n));
27299566063dSJacob Faibussowitsch   PetscCall(PetscBLASIntCast(A->cmap->n, &k));
27303ba16761SJacob Faibussowitsch   if (!m || !n || !k) PetscFunctionReturn(PETSC_SUCCESS);
27319566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArrayRead(A, &av));
27329566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArrayRead(B, &bv));
27339566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArrayWrite(C, &cv));
2734792fecdfSBarry Smith   PetscCallBLAS("BLASgemm", BLASgemm_("N", "N", &m, &n, &k, &_DOne, av, &a->lda, bv, &b->lda, &_DZero, cv, &c->lda));
27359566063dSJacob Faibussowitsch   PetscCall(PetscLogFlops(1.0 * m * n * k + 1.0 * m * n * (k - 1)));
27369566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArrayRead(A, &av));
27379566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArrayRead(B, &bv));
27389566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArrayWrite(C, &cv));
27393ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2740a9fe9ddaSSatish Balay }
2741a9fe9ddaSSatish Balay 
2742d71ae5a4SJacob Faibussowitsch PetscErrorCode MatMatTransposeMultSymbolic_SeqDense_SeqDense(Mat A, Mat B, PetscReal fill, Mat C)
2743d71ae5a4SJacob Faibussowitsch {
274469f65d41SStefano Zampini   PetscInt  m = A->rmap->n, n = B->rmap->n;
274547d993e7Ssuyashtn   PetscBool cisdense = PETSC_FALSE;
274669f65d41SStefano Zampini 
274769f65d41SStefano Zampini   PetscFunctionBegin;
27489566063dSJacob Faibussowitsch   PetscCall(MatSetSizes(C, m, n, m, n));
274947d993e7Ssuyashtn #if defined(PETSC_HAVE_CUDA)
27509566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompareAny((PetscObject)C, &cisdense, MATSEQDENSE, MATSEQDENSECUDA, ""));
275147d993e7Ssuyashtn #endif
275247d993e7Ssuyashtn #if defined(PETSC_HAVE_HIP)
275347d993e7Ssuyashtn   PetscCall(PetscObjectTypeCompareAny((PetscObject)C, &cisdense, MATSEQDENSE, MATSEQDENSEHIP, ""));
275447d993e7Ssuyashtn #endif
27557a3c3d58SStefano Zampini   if (!cisdense) {
27567a3c3d58SStefano Zampini     PetscBool flg;
27577a3c3d58SStefano Zampini 
27589566063dSJacob Faibussowitsch     PetscCall(PetscObjectTypeCompare((PetscObject)B, ((PetscObject)A)->type_name, &flg));
27599566063dSJacob Faibussowitsch     PetscCall(MatSetType(C, flg ? ((PetscObject)A)->type_name : MATDENSE));
27607a3c3d58SStefano Zampini   }
27619566063dSJacob Faibussowitsch   PetscCall(MatSetUp(C));
27623ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
276369f65d41SStefano Zampini }
276469f65d41SStefano Zampini 
2765d71ae5a4SJacob Faibussowitsch PetscErrorCode MatMatTransposeMultNumeric_SeqDense_SeqDense(Mat A, Mat B, Mat C)
2766d71ae5a4SJacob Faibussowitsch {
276769f65d41SStefano Zampini   Mat_SeqDense      *a = (Mat_SeqDense *)A->data;
276869f65d41SStefano Zampini   Mat_SeqDense      *b = (Mat_SeqDense *)B->data;
276969f65d41SStefano Zampini   Mat_SeqDense      *c = (Mat_SeqDense *)C->data;
27706718818eSStefano Zampini   const PetscScalar *av, *bv;
27716718818eSStefano Zampini   PetscScalar       *cv;
277269f65d41SStefano Zampini   PetscBLASInt       m, n, k;
277369f65d41SStefano Zampini   PetscScalar        _DOne = 1.0, _DZero = 0.0;
277469f65d41SStefano Zampini 
277569f65d41SStefano Zampini   PetscFunctionBegin;
27769566063dSJacob Faibussowitsch   PetscCall(PetscBLASIntCast(C->rmap->n, &m));
27779566063dSJacob Faibussowitsch   PetscCall(PetscBLASIntCast(C->cmap->n, &n));
27789566063dSJacob Faibussowitsch   PetscCall(PetscBLASIntCast(A->cmap->n, &k));
27793ba16761SJacob Faibussowitsch   if (!m || !n || !k) PetscFunctionReturn(PETSC_SUCCESS);
27809566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArrayRead(A, &av));
27819566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArrayRead(B, &bv));
27829566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArrayWrite(C, &cv));
2783792fecdfSBarry Smith   PetscCallBLAS("BLASgemm", BLASgemm_("N", "T", &m, &n, &k, &_DOne, av, &a->lda, bv, &b->lda, &_DZero, cv, &c->lda));
27849566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArrayRead(A, &av));
27859566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArrayRead(B, &bv));
27869566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArrayWrite(C, &cv));
27879566063dSJacob Faibussowitsch   PetscCall(PetscLogFlops(1.0 * m * n * k + 1.0 * m * n * (k - 1)));
27883ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
278969f65d41SStefano Zampini }
279069f65d41SStefano Zampini 
2791d71ae5a4SJacob Faibussowitsch PetscErrorCode MatTransposeMatMultSymbolic_SeqDense_SeqDense(Mat A, Mat B, PetscReal fill, Mat C)
2792d71ae5a4SJacob Faibussowitsch {
2793d0f46423SBarry Smith   PetscInt  m = A->cmap->n, n = B->cmap->n;
279447d993e7Ssuyashtn   PetscBool cisdense = PETSC_FALSE;
2795a9fe9ddaSSatish Balay 
2796ee16a9a1SHong Zhang   PetscFunctionBegin;
27979566063dSJacob Faibussowitsch   PetscCall(MatSetSizes(C, m, n, m, n));
279847d993e7Ssuyashtn #if defined(PETSC_HAVE_CUDA)
27999566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompareAny((PetscObject)C, &cisdense, MATSEQDENSE, MATSEQDENSECUDA, ""));
280047d993e7Ssuyashtn #endif
280147d993e7Ssuyashtn #if defined(PETSC_HAVE_HIP)
280247d993e7Ssuyashtn   PetscCall(PetscObjectTypeCompareAny((PetscObject)C, &cisdense, MATSEQDENSE, MATSEQDENSEHIP, ""));
280347d993e7Ssuyashtn #endif
28047a3c3d58SStefano Zampini   if (!cisdense) {
28057a3c3d58SStefano Zampini     PetscBool flg;
28067a3c3d58SStefano Zampini 
28079566063dSJacob Faibussowitsch     PetscCall(PetscObjectTypeCompare((PetscObject)B, ((PetscObject)A)->type_name, &flg));
28089566063dSJacob Faibussowitsch     PetscCall(MatSetType(C, flg ? ((PetscObject)A)->type_name : MATDENSE));
28097a3c3d58SStefano Zampini   }
28109566063dSJacob Faibussowitsch   PetscCall(MatSetUp(C));
28113ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2812ee16a9a1SHong Zhang }
2813a9fe9ddaSSatish Balay 
2814d71ae5a4SJacob Faibussowitsch PetscErrorCode MatTransposeMatMultNumeric_SeqDense_SeqDense(Mat A, Mat B, Mat C)
2815d71ae5a4SJacob Faibussowitsch {
2816a9fe9ddaSSatish Balay   Mat_SeqDense      *a = (Mat_SeqDense *)A->data;
2817a9fe9ddaSSatish Balay   Mat_SeqDense      *b = (Mat_SeqDense *)B->data;
2818a9fe9ddaSSatish Balay   Mat_SeqDense      *c = (Mat_SeqDense *)C->data;
28196718818eSStefano Zampini   const PetscScalar *av, *bv;
28206718818eSStefano Zampini   PetscScalar       *cv;
28210805154bSBarry Smith   PetscBLASInt       m, n, k;
2822a9fe9ddaSSatish Balay   PetscScalar        _DOne = 1.0, _DZero = 0.0;
2823a9fe9ddaSSatish Balay 
2824a9fe9ddaSSatish Balay   PetscFunctionBegin;
28259566063dSJacob Faibussowitsch   PetscCall(PetscBLASIntCast(C->rmap->n, &m));
28269566063dSJacob Faibussowitsch   PetscCall(PetscBLASIntCast(C->cmap->n, &n));
28279566063dSJacob Faibussowitsch   PetscCall(PetscBLASIntCast(A->rmap->n, &k));
28283ba16761SJacob Faibussowitsch   if (!m || !n || !k) PetscFunctionReturn(PETSC_SUCCESS);
28299566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArrayRead(A, &av));
28309566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArrayRead(B, &bv));
28319566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArrayWrite(C, &cv));
2832792fecdfSBarry Smith   PetscCallBLAS("BLASgemm", BLASgemm_("T", "N", &m, &n, &k, &_DOne, av, &a->lda, bv, &b->lda, &_DZero, cv, &c->lda));
28339566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArrayRead(A, &av));
28349566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArrayRead(B, &bv));
28359566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArrayWrite(C, &cv));
28369566063dSJacob Faibussowitsch   PetscCall(PetscLogFlops(1.0 * m * n * k + 1.0 * m * n * (k - 1)));
28373ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2838a9fe9ddaSSatish Balay }
2839985db425SBarry Smith 
2840d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatProductSetFromOptions_SeqDense_AB(Mat C)
2841d71ae5a4SJacob Faibussowitsch {
28424222ddf1SHong Zhang   PetscFunctionBegin;
28434222ddf1SHong Zhang   C->ops->matmultsymbolic = MatMatMultSymbolic_SeqDense_SeqDense;
28444222ddf1SHong Zhang   C->ops->productsymbolic = MatProductSymbolic_AB;
28453ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
28464222ddf1SHong Zhang }
28474222ddf1SHong Zhang 
2848d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatProductSetFromOptions_SeqDense_AtB(Mat C)
2849d71ae5a4SJacob Faibussowitsch {
28504222ddf1SHong Zhang   PetscFunctionBegin;
28514222ddf1SHong Zhang   C->ops->transposematmultsymbolic = MatTransposeMatMultSymbolic_SeqDense_SeqDense;
28524222ddf1SHong Zhang   C->ops->productsymbolic          = MatProductSymbolic_AtB;
28533ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
28544222ddf1SHong Zhang }
28554222ddf1SHong Zhang 
2856d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatProductSetFromOptions_SeqDense_ABt(Mat C)
2857d71ae5a4SJacob Faibussowitsch {
28584222ddf1SHong Zhang   PetscFunctionBegin;
28594222ddf1SHong Zhang   C->ops->mattransposemultsymbolic = MatMatTransposeMultSymbolic_SeqDense_SeqDense;
28604222ddf1SHong Zhang   C->ops->productsymbolic          = MatProductSymbolic_ABt;
28613ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
28624222ddf1SHong Zhang }
28634222ddf1SHong Zhang 
2864d71ae5a4SJacob Faibussowitsch PETSC_INTERN PetscErrorCode MatProductSetFromOptions_SeqDense(Mat C)
2865d71ae5a4SJacob Faibussowitsch {
28664222ddf1SHong Zhang   Mat_Product *product = C->product;
28674222ddf1SHong Zhang 
28684222ddf1SHong Zhang   PetscFunctionBegin;
28694222ddf1SHong Zhang   switch (product->type) {
2870d71ae5a4SJacob Faibussowitsch   case MATPRODUCT_AB:
2871d71ae5a4SJacob Faibussowitsch     PetscCall(MatProductSetFromOptions_SeqDense_AB(C));
2872d71ae5a4SJacob Faibussowitsch     break;
2873d71ae5a4SJacob Faibussowitsch   case MATPRODUCT_AtB:
2874d71ae5a4SJacob Faibussowitsch     PetscCall(MatProductSetFromOptions_SeqDense_AtB(C));
2875d71ae5a4SJacob Faibussowitsch     break;
2876d71ae5a4SJacob Faibussowitsch   case MATPRODUCT_ABt:
2877d71ae5a4SJacob Faibussowitsch     PetscCall(MatProductSetFromOptions_SeqDense_ABt(C));
2878d71ae5a4SJacob Faibussowitsch     break;
2879d71ae5a4SJacob Faibussowitsch   default:
2880d71ae5a4SJacob Faibussowitsch     break;
28814222ddf1SHong Zhang   }
28823ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
28834222ddf1SHong Zhang }
28844222ddf1SHong Zhang 
2885d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatGetRowMax_SeqDense(Mat A, Vec v, PetscInt idx[])
2886d71ae5a4SJacob Faibussowitsch {
2887985db425SBarry Smith   Mat_SeqDense      *a = (Mat_SeqDense *)A->data;
2888d0f46423SBarry Smith   PetscInt           i, j, m = A->rmap->n, n = A->cmap->n, p;
2889985db425SBarry Smith   PetscScalar       *x;
2890ca15aa20SStefano Zampini   const PetscScalar *aa;
2891985db425SBarry Smith 
2892985db425SBarry Smith   PetscFunctionBegin;
289328b400f6SJacob Faibussowitsch   PetscCheck(!A->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
28949566063dSJacob Faibussowitsch   PetscCall(VecGetArray(v, &x));
28959566063dSJacob Faibussowitsch   PetscCall(VecGetLocalSize(v, &p));
28969566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArrayRead(A, &aa));
289708401ef6SPierre Jolivet   PetscCheck(p == A->rmap->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Nonconforming matrix and vector");
2898985db425SBarry Smith   for (i = 0; i < m; i++) {
28999371c9d4SSatish Balay     x[i] = aa[i];
29009371c9d4SSatish Balay     if (idx) idx[i] = 0;
2901985db425SBarry Smith     for (j = 1; j < n; j++) {
29029371c9d4SSatish Balay       if (PetscRealPart(x[i]) < PetscRealPart(aa[i + a->lda * j])) {
29039371c9d4SSatish Balay         x[i] = aa[i + a->lda * j];
29049371c9d4SSatish Balay         if (idx) idx[i] = j;
29059371c9d4SSatish Balay       }
2906985db425SBarry Smith     }
2907985db425SBarry Smith   }
29089566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArrayRead(A, &aa));
29099566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(v, &x));
29103ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2911985db425SBarry Smith }
2912985db425SBarry Smith 
2913d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatGetRowMaxAbs_SeqDense(Mat A, Vec v, PetscInt idx[])
2914d71ae5a4SJacob Faibussowitsch {
2915985db425SBarry Smith   Mat_SeqDense      *a = (Mat_SeqDense *)A->data;
2916d0f46423SBarry Smith   PetscInt           i, j, m = A->rmap->n, n = A->cmap->n, p;
2917985db425SBarry Smith   PetscScalar       *x;
2918985db425SBarry Smith   PetscReal          atmp;
2919ca15aa20SStefano Zampini   const PetscScalar *aa;
2920985db425SBarry Smith 
2921985db425SBarry Smith   PetscFunctionBegin;
292228b400f6SJacob Faibussowitsch   PetscCheck(!A->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
29239566063dSJacob Faibussowitsch   PetscCall(VecGetArray(v, &x));
29249566063dSJacob Faibussowitsch   PetscCall(VecGetLocalSize(v, &p));
29259566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArrayRead(A, &aa));
292608401ef6SPierre Jolivet   PetscCheck(p == A->rmap->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Nonconforming matrix and vector");
2927985db425SBarry Smith   for (i = 0; i < m; i++) {
29289189402eSHong Zhang     x[i] = PetscAbsScalar(aa[i]);
2929985db425SBarry Smith     for (j = 1; j < n; j++) {
2930ca15aa20SStefano Zampini       atmp = PetscAbsScalar(aa[i + a->lda * j]);
29319371c9d4SSatish Balay       if (PetscAbsScalar(x[i]) < atmp) {
29329371c9d4SSatish Balay         x[i] = atmp;
29339371c9d4SSatish Balay         if (idx) idx[i] = j;
29349371c9d4SSatish Balay       }
2935985db425SBarry Smith     }
2936985db425SBarry Smith   }
29379566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArrayRead(A, &aa));
29389566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(v, &x));
29393ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2940985db425SBarry Smith }
2941985db425SBarry Smith 
2942d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatGetRowMin_SeqDense(Mat A, Vec v, PetscInt idx[])
2943d71ae5a4SJacob Faibussowitsch {
2944985db425SBarry Smith   Mat_SeqDense      *a = (Mat_SeqDense *)A->data;
2945d0f46423SBarry Smith   PetscInt           i, j, m = A->rmap->n, n = A->cmap->n, p;
2946985db425SBarry Smith   PetscScalar       *x;
2947ca15aa20SStefano Zampini   const PetscScalar *aa;
2948985db425SBarry Smith 
2949985db425SBarry Smith   PetscFunctionBegin;
295028b400f6SJacob Faibussowitsch   PetscCheck(!A->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
29519566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArrayRead(A, &aa));
29529566063dSJacob Faibussowitsch   PetscCall(VecGetArray(v, &x));
29539566063dSJacob Faibussowitsch   PetscCall(VecGetLocalSize(v, &p));
295408401ef6SPierre Jolivet   PetscCheck(p == A->rmap->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Nonconforming matrix and vector");
2955985db425SBarry Smith   for (i = 0; i < m; i++) {
29569371c9d4SSatish Balay     x[i] = aa[i];
29579371c9d4SSatish Balay     if (idx) idx[i] = 0;
2958985db425SBarry Smith     for (j = 1; j < n; j++) {
29599371c9d4SSatish Balay       if (PetscRealPart(x[i]) > PetscRealPart(aa[i + a->lda * j])) {
29609371c9d4SSatish Balay         x[i] = aa[i + a->lda * j];
29619371c9d4SSatish Balay         if (idx) idx[i] = j;
29629371c9d4SSatish Balay       }
2963985db425SBarry Smith     }
2964985db425SBarry Smith   }
29659566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(v, &x));
29669566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArrayRead(A, &aa));
29673ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2968985db425SBarry Smith }
2969985db425SBarry Smith 
2970d71ae5a4SJacob Faibussowitsch PetscErrorCode MatGetColumnVector_SeqDense(Mat A, Vec v, PetscInt col)
2971d71ae5a4SJacob Faibussowitsch {
29728d0534beSBarry Smith   Mat_SeqDense      *a = (Mat_SeqDense *)A->data;
29738d0534beSBarry Smith   PetscScalar       *x;
2974ca15aa20SStefano Zampini   const PetscScalar *aa;
29758d0534beSBarry Smith 
29768d0534beSBarry Smith   PetscFunctionBegin;
297728b400f6SJacob Faibussowitsch   PetscCheck(!A->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
29789566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArrayRead(A, &aa));
29799566063dSJacob Faibussowitsch   PetscCall(VecGetArray(v, &x));
29809566063dSJacob Faibussowitsch   PetscCall(PetscArraycpy(x, aa + col * a->lda, A->rmap->n));
29819566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(v, &x));
29829566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArrayRead(A, &aa));
29833ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
29848d0534beSBarry Smith }
29858d0534beSBarry Smith 
2986d71ae5a4SJacob Faibussowitsch PETSC_INTERN PetscErrorCode MatGetColumnReductions_SeqDense(Mat A, PetscInt type, PetscReal *reductions)
2987d71ae5a4SJacob Faibussowitsch {
29880716a85fSBarry Smith   PetscInt           i, j, m, n;
29891683a169SBarry Smith   const PetscScalar *a;
29900716a85fSBarry Smith 
29910716a85fSBarry Smith   PetscFunctionBegin;
29929566063dSJacob Faibussowitsch   PetscCall(MatGetSize(A, &m, &n));
29939566063dSJacob Faibussowitsch   PetscCall(PetscArrayzero(reductions, n));
29949566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArrayRead(A, &a));
2995857cbf51SRichard Tran Mills   if (type == NORM_2) {
29960716a85fSBarry Smith     for (i = 0; i < n; i++) {
2997ad540459SPierre Jolivet       for (j = 0; j < m; j++) reductions[i] += PetscAbsScalar(a[j] * a[j]);
299816cd844bSPierre Jolivet       a = PetscSafePointerPlusOffset(a, m);
29990716a85fSBarry Smith     }
3000857cbf51SRichard Tran Mills   } else if (type == NORM_1) {
30010716a85fSBarry Smith     for (i = 0; i < n; i++) {
3002ad540459SPierre Jolivet       for (j = 0; j < m; j++) reductions[i] += PetscAbsScalar(a[j]);
300316cd844bSPierre Jolivet       a = PetscSafePointerPlusOffset(a, m);
30040716a85fSBarry Smith     }
3005857cbf51SRichard Tran Mills   } else if (type == NORM_INFINITY) {
30060716a85fSBarry Smith     for (i = 0; i < n; i++) {
3007ad540459SPierre Jolivet       for (j = 0; j < m; j++) reductions[i] = PetscMax(PetscAbsScalar(a[j]), reductions[i]);
300816cd844bSPierre Jolivet       a = PetscSafePointerPlusOffset(a, m);
30090716a85fSBarry Smith     }
3010857cbf51SRichard Tran Mills   } else if (type == REDUCTION_SUM_REALPART || type == REDUCTION_MEAN_REALPART) {
3011a873a8cdSSam Reynolds     for (i = 0; i < n; i++) {
3012ad540459SPierre Jolivet       for (j = 0; j < m; j++) reductions[i] += PetscRealPart(a[j]);
301316cd844bSPierre Jolivet       a = PetscSafePointerPlusOffset(a, m);
3014a873a8cdSSam Reynolds     }
3015857cbf51SRichard Tran Mills   } else if (type == REDUCTION_SUM_IMAGINARYPART || type == REDUCTION_MEAN_IMAGINARYPART) {
3016857cbf51SRichard Tran Mills     for (i = 0; i < n; i++) {
3017ad540459SPierre Jolivet       for (j = 0; j < m; j++) reductions[i] += PetscImaginaryPart(a[j]);
301816cd844bSPierre Jolivet       a = PetscSafePointerPlusOffset(a, m);
3019857cbf51SRichard Tran Mills     }
3020857cbf51SRichard Tran Mills   } else SETERRQ(PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONG, "Unknown reduction type");
30219566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArrayRead(A, &a));
3022857cbf51SRichard Tran Mills   if (type == NORM_2) {
3023a873a8cdSSam Reynolds     for (i = 0; i < n; i++) reductions[i] = PetscSqrtReal(reductions[i]);
3024857cbf51SRichard Tran Mills   } else if (type == REDUCTION_MEAN_REALPART || type == REDUCTION_MEAN_IMAGINARYPART) {
3025a873a8cdSSam Reynolds     for (i = 0; i < n; i++) reductions[i] /= m;
30260716a85fSBarry Smith   }
30273ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
30280716a85fSBarry Smith }
30290716a85fSBarry Smith 
3030d71ae5a4SJacob Faibussowitsch PetscErrorCode MatSetRandom_SeqDense(Mat x, PetscRandom rctx)
3031d71ae5a4SJacob Faibussowitsch {
303273a71a0fSBarry Smith   PetscScalar *a;
3033637a0070SStefano Zampini   PetscInt     lda, m, n, i, j;
303473a71a0fSBarry Smith 
303573a71a0fSBarry Smith   PetscFunctionBegin;
30369566063dSJacob Faibussowitsch   PetscCall(MatGetSize(x, &m, &n));
30379566063dSJacob Faibussowitsch   PetscCall(MatDenseGetLDA(x, &lda));
30383faff063SStefano Zampini   PetscCall(MatDenseGetArrayWrite(x, &a));
3039637a0070SStefano Zampini   for (j = 0; j < n; j++) {
304048a46eb9SPierre Jolivet     for (i = 0; i < m; i++) PetscCall(PetscRandomGetValue(rctx, a + j * lda + i));
304173a71a0fSBarry Smith   }
30423faff063SStefano Zampini   PetscCall(MatDenseRestoreArrayWrite(x, &a));
30433ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
304473a71a0fSBarry Smith }
304573a71a0fSBarry Smith 
3046d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatMissingDiagonal_SeqDense(Mat A, PetscBool *missing, PetscInt *d)
3047d71ae5a4SJacob Faibussowitsch {
30483b49f96aSBarry Smith   PetscFunctionBegin;
30493b49f96aSBarry Smith   *missing = PETSC_FALSE;
30503ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
30513b49f96aSBarry Smith }
305273a71a0fSBarry Smith 
3053ca15aa20SStefano Zampini /* vals is not const */
3054d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatDenseGetColumn_SeqDense(Mat A, PetscInt col, PetscScalar **vals)
3055d71ae5a4SJacob Faibussowitsch {
305686aefd0dSHong Zhang   Mat_SeqDense *a = (Mat_SeqDense *)A->data;
3057ca15aa20SStefano Zampini   PetscScalar  *v;
305886aefd0dSHong Zhang 
305986aefd0dSHong Zhang   PetscFunctionBegin;
306028b400f6SJacob Faibussowitsch   PetscCheck(!A->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
30619566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArray(A, &v));
3062ca15aa20SStefano Zampini   *vals = v + col * a->lda;
30639566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArray(A, &v));
30643ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
306586aefd0dSHong Zhang }
306686aefd0dSHong Zhang 
3067d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatDenseRestoreColumn_SeqDense(Mat A, PetscScalar **vals)
3068d71ae5a4SJacob Faibussowitsch {
306986aefd0dSHong Zhang   PetscFunctionBegin;
3070742765d3SMatthew Knepley   if (vals) *vals = NULL; /* user cannot accidentally use the array later */
30713ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
307286aefd0dSHong Zhang }
3073abc3b08eSStefano Zampini 
3074a5ae1ecdSBarry Smith static struct _MatOps MatOps_Values = {MatSetValues_SeqDense,
3075905e6a2fSBarry Smith                                        MatGetRow_SeqDense,
3076905e6a2fSBarry Smith                                        MatRestoreRow_SeqDense,
3077905e6a2fSBarry Smith                                        MatMult_SeqDense,
307897304618SKris Buschelman                                        /*  4*/ MatMultAdd_SeqDense,
30797c922b88SBarry Smith                                        MatMultTranspose_SeqDense,
30807c922b88SBarry Smith                                        MatMultTransposeAdd_SeqDense,
3081f4259b30SLisandro Dalcin                                        NULL,
3082f4259b30SLisandro Dalcin                                        NULL,
3083f4259b30SLisandro Dalcin                                        NULL,
3084f4259b30SLisandro Dalcin                                        /* 10*/ NULL,
3085905e6a2fSBarry Smith                                        MatLUFactor_SeqDense,
3086905e6a2fSBarry Smith                                        MatCholeskyFactor_SeqDense,
308741f059aeSBarry Smith                                        MatSOR_SeqDense,
3088ec8511deSBarry Smith                                        MatTranspose_SeqDense,
308997304618SKris Buschelman                                        /* 15*/ MatGetInfo_SeqDense,
3090905e6a2fSBarry Smith                                        MatEqual_SeqDense,
3091905e6a2fSBarry Smith                                        MatGetDiagonal_SeqDense,
3092905e6a2fSBarry Smith                                        MatDiagonalScale_SeqDense,
3093905e6a2fSBarry Smith                                        MatNorm_SeqDense,
3094b7103cf4SPierre Jolivet                                        /* 20*/ NULL,
3095b7103cf4SPierre Jolivet                                        NULL,
3096905e6a2fSBarry Smith                                        MatSetOption_SeqDense,
3097905e6a2fSBarry Smith                                        MatZeroEntries_SeqDense,
3098d519adbfSMatthew Knepley                                        /* 24*/ MatZeroRows_SeqDense,
3099f4259b30SLisandro Dalcin                                        NULL,
3100f4259b30SLisandro Dalcin                                        NULL,
3101f4259b30SLisandro Dalcin                                        NULL,
3102f4259b30SLisandro Dalcin                                        NULL,
31034994cf47SJed Brown                                        /* 29*/ MatSetUp_SeqDense,
3104f4259b30SLisandro Dalcin                                        NULL,
3105f4259b30SLisandro Dalcin                                        NULL,
3106f4259b30SLisandro Dalcin                                        NULL,
3107f4259b30SLisandro Dalcin                                        NULL,
3108d519adbfSMatthew Knepley                                        /* 34*/ MatDuplicate_SeqDense,
3109f4259b30SLisandro Dalcin                                        NULL,
3110f4259b30SLisandro Dalcin                                        NULL,
3111f4259b30SLisandro Dalcin                                        NULL,
3112f4259b30SLisandro Dalcin                                        NULL,
3113d519adbfSMatthew Knepley                                        /* 39*/ MatAXPY_SeqDense,
31147dae84e0SHong Zhang                                        MatCreateSubMatrices_SeqDense,
3115f4259b30SLisandro Dalcin                                        NULL,
31164b0e389bSBarry Smith                                        MatGetValues_SeqDense,
3117a5ae1ecdSBarry Smith                                        MatCopy_SeqDense,
3118d519adbfSMatthew Knepley                                        /* 44*/ MatGetRowMax_SeqDense,
3119a5ae1ecdSBarry Smith                                        MatScale_SeqDense,
31202f605a99SJose E. Roman                                        MatShift_SeqDense,
3121f4259b30SLisandro Dalcin                                        NULL,
31223f49a652SStefano Zampini                                        MatZeroRowsColumns_SeqDense,
312373a71a0fSBarry Smith                                        /* 49*/ MatSetRandom_SeqDense,
3124f4259b30SLisandro Dalcin                                        NULL,
3125f4259b30SLisandro Dalcin                                        NULL,
3126f4259b30SLisandro Dalcin                                        NULL,
3127f4259b30SLisandro Dalcin                                        NULL,
3128f4259b30SLisandro Dalcin                                        /* 54*/ NULL,
3129f4259b30SLisandro Dalcin                                        NULL,
3130f4259b30SLisandro Dalcin                                        NULL,
3131f4259b30SLisandro Dalcin                                        NULL,
3132f4259b30SLisandro Dalcin                                        NULL,
3133023c16fcSToby Isaac                                        /* 59*/ MatCreateSubMatrix_SeqDense,
3134e03a110bSBarry Smith                                        MatDestroy_SeqDense,
3135e03a110bSBarry Smith                                        MatView_SeqDense,
3136f4259b30SLisandro Dalcin                                        NULL,
3137f4259b30SLisandro Dalcin                                        NULL,
3138f4259b30SLisandro Dalcin                                        /* 64*/ NULL,
3139f4259b30SLisandro Dalcin                                        NULL,
3140f4259b30SLisandro Dalcin                                        NULL,
3141f4259b30SLisandro Dalcin                                        NULL,
3142f4259b30SLisandro Dalcin                                        NULL,
3143d519adbfSMatthew Knepley                                        /* 69*/ MatGetRowMaxAbs_SeqDense,
3144f4259b30SLisandro Dalcin                                        NULL,
3145f4259b30SLisandro Dalcin                                        NULL,
3146f4259b30SLisandro Dalcin                                        NULL,
3147f4259b30SLisandro Dalcin                                        NULL,
3148f4259b30SLisandro Dalcin                                        /* 74*/ NULL,
3149f4259b30SLisandro Dalcin                                        NULL,
3150f4259b30SLisandro Dalcin                                        NULL,
3151f4259b30SLisandro Dalcin                                        NULL,
3152f4259b30SLisandro Dalcin                                        NULL,
3153f4259b30SLisandro Dalcin                                        /* 79*/ NULL,
3154f4259b30SLisandro Dalcin                                        NULL,
3155f4259b30SLisandro Dalcin                                        NULL,
3156f4259b30SLisandro Dalcin                                        NULL,
31575bba2384SShri Abhyankar                                        /* 83*/ MatLoad_SeqDense,
3158637a0070SStefano Zampini                                        MatIsSymmetric_SeqDense,
31591cbb95d3SBarry Smith                                        MatIsHermitian_SeqDense,
3160f4259b30SLisandro Dalcin                                        NULL,
3161f4259b30SLisandro Dalcin                                        NULL,
3162f4259b30SLisandro Dalcin                                        NULL,
3163f4259b30SLisandro Dalcin                                        /* 89*/ NULL,
3164f4259b30SLisandro Dalcin                                        NULL,
3165a9fe9ddaSSatish Balay                                        MatMatMultNumeric_SeqDense_SeqDense,
3166f4259b30SLisandro Dalcin                                        NULL,
3167f4259b30SLisandro Dalcin                                        NULL,
3168f4259b30SLisandro Dalcin                                        /* 94*/ NULL,
3169f4259b30SLisandro Dalcin                                        NULL,
3170f4259b30SLisandro Dalcin                                        NULL,
317169f65d41SStefano Zampini                                        MatMatTransposeMultNumeric_SeqDense_SeqDense,
3172f4259b30SLisandro Dalcin                                        NULL,
31734222ddf1SHong Zhang                                        /* 99*/ MatProductSetFromOptions_SeqDense,
3174f4259b30SLisandro Dalcin                                        NULL,
3175f4259b30SLisandro Dalcin                                        NULL,
3176ba337c44SJed Brown                                        MatConjugate_SeqDense,
3177f4259b30SLisandro Dalcin                                        NULL,
3178f4259b30SLisandro Dalcin                                        /*104*/ NULL,
3179ba337c44SJed Brown                                        MatRealPart_SeqDense,
3180ba337c44SJed Brown                                        MatImaginaryPart_SeqDense,
3181f4259b30SLisandro Dalcin                                        NULL,
3182f4259b30SLisandro Dalcin                                        NULL,
3183f4259b30SLisandro Dalcin                                        /*109*/ NULL,
3184f4259b30SLisandro Dalcin                                        NULL,
31858d0534beSBarry Smith                                        MatGetRowMin_SeqDense,
3186aabbc4fbSShri Abhyankar                                        MatGetColumnVector_SeqDense,
31873b49f96aSBarry Smith                                        MatMissingDiagonal_SeqDense,
3188f4259b30SLisandro Dalcin                                        /*114*/ NULL,
3189f4259b30SLisandro Dalcin                                        NULL,
3190f4259b30SLisandro Dalcin                                        NULL,
3191f4259b30SLisandro Dalcin                                        NULL,
3192f4259b30SLisandro Dalcin                                        NULL,
3193f4259b30SLisandro Dalcin                                        /*119*/ NULL,
3194f4259b30SLisandro Dalcin                                        NULL,
3195459e8d23SBlanca Mellado Pinto                                        MatMultHermitianTranspose_SeqDense,
3196459e8d23SBlanca Mellado Pinto                                        MatMultHermitianTransposeAdd_SeqDense,
3197f4259b30SLisandro Dalcin                                        NULL,
3198f4259b30SLisandro Dalcin                                        /*124*/ NULL,
3199a873a8cdSSam Reynolds                                        MatGetColumnReductions_SeqDense,
3200f4259b30SLisandro Dalcin                                        NULL,
3201f4259b30SLisandro Dalcin                                        NULL,
3202f4259b30SLisandro Dalcin                                        NULL,
3203f4259b30SLisandro Dalcin                                        /*129*/ NULL,
3204f4259b30SLisandro Dalcin                                        NULL,
3205f4259b30SLisandro Dalcin                                        NULL,
320675648e8dSHong Zhang                                        MatTransposeMatMultNumeric_SeqDense_SeqDense,
3207f4259b30SLisandro Dalcin                                        NULL,
3208f4259b30SLisandro Dalcin                                        /*134*/ NULL,
3209f4259b30SLisandro Dalcin                                        NULL,
3210f4259b30SLisandro Dalcin                                        NULL,
3211f4259b30SLisandro Dalcin                                        NULL,
3212f4259b30SLisandro Dalcin                                        NULL,
3213f4259b30SLisandro Dalcin                                        /*139*/ NULL,
3214f4259b30SLisandro Dalcin                                        NULL,
3215f4259b30SLisandro Dalcin                                        NULL,
3216f4259b30SLisandro Dalcin                                        NULL,
3217f4259b30SLisandro Dalcin                                        NULL,
32184222ddf1SHong Zhang                                        MatCreateMPIMatConcatenateSeqMat_SeqDense,
3219f4259b30SLisandro Dalcin                                        /*145*/ NULL,
3220f4259b30SLisandro Dalcin                                        NULL,
322199a7f59eSMark Adams                                        NULL,
322299a7f59eSMark Adams                                        NULL,
32237fb60732SBarry Smith                                        NULL,
3224dec0b466SHong Zhang                                        /*150*/ NULL,
3225eede4a3fSMark Adams                                        NULL,
32264cc2b5b5SPierre Jolivet                                        NULL,
322742ce410bSJunchao Zhang                                        NULL,
322842ce410bSJunchao Zhang                                        NULL,
3229fe1fc275SAlexander                                        /*155*/ NULL,
3230dec0b466SHong Zhang                                        NULL};
323190ace30eSBarry Smith 
32325d83a8b1SBarry Smith /*@
323311a5261eSBarry Smith   MatCreateSeqDense - Creates a `MATSEQDENSE` that
3234fb850c59SBarry Smith   is stored in column major order (the usual Fortran format).
3235289bc588SBarry Smith 
3236d083f849SBarry Smith   Collective
3237db81eaa0SLois Curfman McInnes 
323820563c6bSBarry Smith   Input Parameters:
323911a5261eSBarry Smith + comm - MPI communicator, set to `PETSC_COMM_SELF`
32400c775827SLois Curfman McInnes . m    - number of rows
324118f449edSLois Curfman McInnes . n    - number of columns
32422ef1f0ffSBarry Smith - data - optional location of matrix data in column major order.  Use `NULL` for PETSc
3243dfc5480cSLois Curfman McInnes          to control all matrix memory allocation.
324420563c6bSBarry Smith 
324520563c6bSBarry Smith   Output Parameter:
324644cd7ae7SLois Curfman McInnes . A - the matrix
324720563c6bSBarry Smith 
32482ef1f0ffSBarry Smith   Level: intermediate
32492ef1f0ffSBarry Smith 
325011a5261eSBarry Smith   Note:
325118f449edSLois Curfman McInnes   The data input variable is intended primarily for Fortran programmers
325218f449edSLois Curfman McInnes   who wish to allocate their own matrix memory space.  Most users should
32532ef1f0ffSBarry Smith   set `data` = `NULL`.
325418f449edSLois Curfman McInnes 
3255fb850c59SBarry Smith   Developer Note:
3256fb850c59SBarry Smith   Many of the matrix operations for this variant use the BLAS and LAPACK routines.
3257fb850c59SBarry Smith 
32581cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATSEQDENSE`, `MatCreate()`, `MatCreateDense()`, `MatSetValues()`
325920563c6bSBarry Smith @*/
32605d83a8b1SBarry Smith PetscErrorCode MatCreateSeqDense(MPI_Comm comm, PetscInt m, PetscInt n, PetscScalar data[], Mat *A)
3261d71ae5a4SJacob Faibussowitsch {
32623a40ed3dSBarry Smith   PetscFunctionBegin;
32639566063dSJacob Faibussowitsch   PetscCall(MatCreate(comm, A));
32649566063dSJacob Faibussowitsch   PetscCall(MatSetSizes(*A, m, n, m, n));
32659566063dSJacob Faibussowitsch   PetscCall(MatSetType(*A, MATSEQDENSE));
32669566063dSJacob Faibussowitsch   PetscCall(MatSeqDenseSetPreallocation(*A, data));
32673ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3268273d9f13SBarry Smith }
3269273d9f13SBarry Smith 
32705d83a8b1SBarry Smith /*@
327111a5261eSBarry Smith   MatSeqDenseSetPreallocation - Sets the array used for storing the matrix elements of a `MATSEQDENSE` matrix
3272273d9f13SBarry Smith 
3273d083f849SBarry Smith   Collective
3274273d9f13SBarry Smith 
3275273d9f13SBarry Smith   Input Parameters:
32761c4f3114SJed Brown + B    - the matrix
32772ef1f0ffSBarry Smith - data - the array (or `NULL`)
32782ef1f0ffSBarry Smith 
32792ef1f0ffSBarry Smith   Level: intermediate
3280273d9f13SBarry Smith 
328111a5261eSBarry Smith   Note:
3282273d9f13SBarry Smith   The data input variable is intended primarily for Fortran programmers
3283273d9f13SBarry Smith   who wish to allocate their own matrix memory space.  Most users should
3284284134d9SBarry Smith   need not call this routine.
3285273d9f13SBarry Smith 
32861cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATSEQDENSE`, `MatCreate()`, `MatCreateDense()`, `MatSetValues()`, `MatDenseSetLDA()`
3287273d9f13SBarry Smith @*/
3288d71ae5a4SJacob Faibussowitsch PetscErrorCode MatSeqDenseSetPreallocation(Mat B, PetscScalar data[])
3289d71ae5a4SJacob Faibussowitsch {
3290a23d5eceSKris Buschelman   PetscFunctionBegin;
3291d5ea218eSStefano Zampini   PetscValidHeaderSpecific(B, MAT_CLASSID, 1);
3292cac4c232SBarry Smith   PetscTryMethod(B, "MatSeqDenseSetPreallocation_C", (Mat, PetscScalar[]), (B, data));
32933ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3294a23d5eceSKris Buschelman }
3295a23d5eceSKris Buschelman 
3296d71ae5a4SJacob Faibussowitsch PetscErrorCode MatSeqDenseSetPreallocation_SeqDense(Mat B, PetscScalar *data)
3297d71ae5a4SJacob Faibussowitsch {
3298ad16ce7aSStefano Zampini   Mat_SeqDense *b = (Mat_SeqDense *)B->data;
3299273d9f13SBarry Smith 
3300273d9f13SBarry Smith   PetscFunctionBegin;
330128b400f6SJacob Faibussowitsch   PetscCheck(!b->matinuse, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Need to call MatDenseRestoreSubMatrix() first");
3302273d9f13SBarry Smith   B->preallocated = PETSC_TRUE;
3303a868139aSShri Abhyankar 
33049566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetUp(B->rmap));
33059566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetUp(B->cmap));
330634ef9618SShri Abhyankar 
33076497c311SBarry Smith   if (b->lda <= 0) PetscCall(PetscBLASIntCast(B->rmap->n, &b->lda));
330886d161a7SShri Abhyankar 
33099e8f95c4SLisandro Dalcin   if (!data) { /* petsc-allocated storage */
33109566063dSJacob Faibussowitsch     if (!b->user_alloc) PetscCall(PetscFree(b->v));
33119566063dSJacob Faibussowitsch     PetscCall(PetscCalloc1((size_t)b->lda * B->cmap->n, &b->v));
33122205254eSKarl Rupp 
33139e8f95c4SLisandro Dalcin     b->user_alloc = PETSC_FALSE;
3314273d9f13SBarry Smith   } else { /* user-allocated storage */
33159566063dSJacob Faibussowitsch     if (!b->user_alloc) PetscCall(PetscFree(b->v));
3316273d9f13SBarry Smith     b->v          = data;
3317273d9f13SBarry Smith     b->user_alloc = PETSC_TRUE;
3318273d9f13SBarry Smith   }
33190450473dSBarry Smith   B->assembled = PETSC_TRUE;
33203ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3321273d9f13SBarry Smith }
3322273d9f13SBarry Smith 
332365b80a83SHong Zhang #if defined(PETSC_HAVE_ELEMENTAL)
3324d71ae5a4SJacob Faibussowitsch PETSC_INTERN PetscErrorCode MatConvert_SeqDense_Elemental(Mat A, MatType newtype, MatReuse reuse, Mat *newmat)
3325d71ae5a4SJacob Faibussowitsch {
3326d77f618aSHong Zhang   Mat                mat_elemental;
33271683a169SBarry Smith   const PetscScalar *array;
33281683a169SBarry Smith   PetscScalar       *v_colwise;
3329d77f618aSHong Zhang   PetscInt           M = A->rmap->N, N = A->cmap->N, i, j, k, *rows, *cols;
3330d77f618aSHong Zhang 
33318baccfbdSHong Zhang   PetscFunctionBegin;
33329566063dSJacob Faibussowitsch   PetscCall(PetscMalloc3(M * N, &v_colwise, M, &rows, N, &cols));
33339566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArrayRead(A, &array));
3334d77f618aSHong Zhang   /* convert column-wise array into row-wise v_colwise, see MatSetValues_Elemental() */
3335d77f618aSHong Zhang   k = 0;
3336d77f618aSHong Zhang   for (j = 0; j < N; j++) {
3337d77f618aSHong Zhang     cols[j] = j;
3338ad540459SPierre Jolivet     for (i = 0; i < M; i++) v_colwise[j * M + i] = array[k++];
3339d77f618aSHong Zhang   }
3340ad540459SPierre Jolivet   for (i = 0; i < M; i++) rows[i] = i;
33419566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArrayRead(A, &array));
3342d77f618aSHong Zhang 
33439566063dSJacob Faibussowitsch   PetscCall(MatCreate(PetscObjectComm((PetscObject)A), &mat_elemental));
33449566063dSJacob Faibussowitsch   PetscCall(MatSetSizes(mat_elemental, PETSC_DECIDE, PETSC_DECIDE, M, N));
33459566063dSJacob Faibussowitsch   PetscCall(MatSetType(mat_elemental, MATELEMENTAL));
33469566063dSJacob Faibussowitsch   PetscCall(MatSetUp(mat_elemental));
3347d77f618aSHong Zhang 
3348d77f618aSHong Zhang   /* PETSc-Elemental interaface uses axpy for setting off-processor entries, only ADD_VALUES is allowed */
33499566063dSJacob Faibussowitsch   PetscCall(MatSetValues(mat_elemental, M, rows, N, cols, v_colwise, ADD_VALUES));
33509566063dSJacob Faibussowitsch   PetscCall(MatAssemblyBegin(mat_elemental, MAT_FINAL_ASSEMBLY));
33519566063dSJacob Faibussowitsch   PetscCall(MatAssemblyEnd(mat_elemental, MAT_FINAL_ASSEMBLY));
33529566063dSJacob Faibussowitsch   PetscCall(PetscFree3(v_colwise, rows, cols));
3353d77f618aSHong Zhang 
3354511c6705SHong Zhang   if (reuse == MAT_INPLACE_MATRIX) {
33559566063dSJacob Faibussowitsch     PetscCall(MatHeaderReplace(A, &mat_elemental));
3356d77f618aSHong Zhang   } else {
3357d77f618aSHong Zhang     *newmat = mat_elemental;
3358d77f618aSHong Zhang   }
33593ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
33608baccfbdSHong Zhang }
336165b80a83SHong Zhang #endif
33628baccfbdSHong Zhang 
3363d71ae5a4SJacob Faibussowitsch PetscErrorCode MatDenseSetLDA_SeqDense(Mat B, PetscInt lda)
3364d71ae5a4SJacob Faibussowitsch {
33651b807ce4Svictorle   Mat_SeqDense *b = (Mat_SeqDense *)B->data;
33667422da62SJose E. Roman   PetscBool     data;
336721a2c019SBarry Smith 
33681b807ce4Svictorle   PetscFunctionBegin;
3369835f2295SStefano Zampini   data = (B->rmap->n > 0 && B->cmap->n > 0) ? (b->v ? PETSC_TRUE : PETSC_FALSE) : PETSC_FALSE;
3370aed4548fSBarry Smith   PetscCheck(b->user_alloc || !data || b->lda == lda, PETSC_COMM_SELF, PETSC_ERR_ORDER, "LDA cannot be changed after allocation of internal storage");
337108401ef6SPierre 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);
33726497c311SBarry Smith   PetscCall(PetscBLASIntCast(lda, &b->lda));
33733ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
33741b807ce4Svictorle }
33751b807ce4Svictorle 
3376d71ae5a4SJacob Faibussowitsch PetscErrorCode MatCreateMPIMatConcatenateSeqMat_SeqDense(MPI_Comm comm, Mat inmat, PetscInt n, MatReuse scall, Mat *outmat)
3377d71ae5a4SJacob Faibussowitsch {
3378d528f656SJakub Kruzik   PetscFunctionBegin;
33799566063dSJacob Faibussowitsch   PetscCall(MatCreateMPIMatConcatenateSeqMat_MPIDense(comm, inmat, n, scall, outmat));
33803ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3381d528f656SJakub Kruzik }
3382d528f656SJakub Kruzik 
3383d16ceb75SStefano Zampini PetscErrorCode MatDenseCreateColumnVec_Private(Mat A, Vec *v)
3384d16ceb75SStefano Zampini {
3385d16ceb75SStefano Zampini   PetscBool   isstd, iskok, iscuda, iship;
3386d16ceb75SStefano Zampini   PetscMPIInt size;
3387d16ceb75SStefano Zampini #if PetscDefined(HAVE_CUDA) || PetscDefined(HAVE_HIP)
3388d16ceb75SStefano Zampini   /* we pass the data of A, to prevent allocating needless GPU memory the first time VecCUPMPlaceArray is called. */
3389d16ceb75SStefano Zampini   const PetscScalar *a;
3390d16ceb75SStefano Zampini #endif
3391d16ceb75SStefano Zampini 
3392d16ceb75SStefano Zampini   PetscFunctionBegin;
3393d16ceb75SStefano Zampini   *v = NULL;
3394d16ceb75SStefano Zampini   PetscCall(PetscStrcmpAny(A->defaultvectype, &isstd, VECSTANDARD, VECSEQ, VECMPI, ""));
3395d16ceb75SStefano Zampini   PetscCall(PetscStrcmpAny(A->defaultvectype, &iskok, VECKOKKOS, VECSEQKOKKOS, VECMPIKOKKOS, ""));
3396d16ceb75SStefano Zampini   PetscCall(PetscStrcmpAny(A->defaultvectype, &iscuda, VECCUDA, VECSEQCUDA, VECMPICUDA, ""));
3397d16ceb75SStefano Zampini   PetscCall(PetscStrcmpAny(A->defaultvectype, &iship, VECHIP, VECSEQHIP, VECMPIHIP, ""));
3398d16ceb75SStefano Zampini   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)A), &size));
3399d16ceb75SStefano Zampini   if (isstd) {
3400d16ceb75SStefano Zampini     if (size > 1) PetscCall(VecCreateMPIWithArray(PetscObjectComm((PetscObject)A), A->rmap->bs, A->rmap->n, A->rmap->N, NULL, v));
3401d16ceb75SStefano Zampini     else PetscCall(VecCreateSeqWithArray(PetscObjectComm((PetscObject)A), A->rmap->bs, A->rmap->n, NULL, v));
3402d16ceb75SStefano Zampini   } else if (iskok) {
3403d16ceb75SStefano Zampini     PetscCheck(PetscDefined(HAVE_KOKKOS_KERNELS), PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Reconfigure using KOKKOS kernels support");
3404d16ceb75SStefano Zampini #if PetscDefined(HAVE_KOKKOS_KERNELS)
3405d16ceb75SStefano Zampini     if (size > 1) PetscCall(VecCreateMPIKokkosWithArray(PetscObjectComm((PetscObject)A), A->rmap->bs, A->rmap->n, A->rmap->N, NULL, v));
3406d16ceb75SStefano Zampini     else PetscCall(VecCreateSeqKokkosWithArray(PetscObjectComm((PetscObject)A), A->rmap->bs, A->rmap->n, NULL, v));
3407d16ceb75SStefano Zampini #endif
3408d16ceb75SStefano Zampini   } else if (iscuda) {
3409d16ceb75SStefano Zampini     PetscCheck(PetscDefined(HAVE_CUDA), PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Reconfigure using CUDA support");
3410d16ceb75SStefano Zampini #if PetscDefined(HAVE_CUDA)
3411d16ceb75SStefano Zampini     PetscCall(MatDenseCUDAGetArrayRead(A, &a));
3412d16ceb75SStefano Zampini     if (size > 1) PetscCall(VecCreateMPICUDAWithArrays(PetscObjectComm((PetscObject)A), A->rmap->bs, A->rmap->n, A->rmap->N, NULL, a, v));
3413d16ceb75SStefano Zampini     else PetscCall(VecCreateSeqCUDAWithArrays(PetscObjectComm((PetscObject)A), A->rmap->bs, A->rmap->n, NULL, a, v));
3414d16ceb75SStefano Zampini #endif
3415d16ceb75SStefano Zampini   } else if (iship) {
3416d16ceb75SStefano Zampini     PetscCheck(PetscDefined(HAVE_HIP), PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Reconfigure using HIP support");
3417d16ceb75SStefano Zampini #if PetscDefined(HAVE_HIP)
3418d16ceb75SStefano Zampini     PetscCall(MatDenseHIPGetArrayRead(A, &a));
3419d16ceb75SStefano Zampini     if (size > 1) PetscCall(VecCreateMPIHIPWithArrays(PetscObjectComm((PetscObject)A), A->rmap->bs, A->rmap->n, A->rmap->N, NULL, a, v));
3420d16ceb75SStefano Zampini     else PetscCall(VecCreateSeqHIPWithArrays(PetscObjectComm((PetscObject)A), A->rmap->bs, A->rmap->n, NULL, a, v));
3421d16ceb75SStefano Zampini #endif
3422d16ceb75SStefano Zampini   }
3423d16ceb75SStefano Zampini   PetscCheck(*v, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Not coded for type %s", A->defaultvectype);
3424d16ceb75SStefano Zampini   PetscFunctionReturn(PETSC_SUCCESS);
3425d16ceb75SStefano Zampini }
3426d16ceb75SStefano Zampini 
3427d71ae5a4SJacob Faibussowitsch PetscErrorCode MatDenseGetColumnVec_SeqDense(Mat A, PetscInt col, Vec *v)
3428d71ae5a4SJacob Faibussowitsch {
34296947451fSStefano Zampini   Mat_SeqDense *a = (Mat_SeqDense *)A->data;
34306947451fSStefano Zampini 
34316947451fSStefano Zampini   PetscFunctionBegin;
343228b400f6SJacob Faibussowitsch   PetscCheck(!a->vecinuse, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Need to call MatDenseRestoreColumnVec() first");
343328b400f6SJacob Faibussowitsch   PetscCheck(!a->matinuse, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Need to call MatDenseRestoreSubMatrix() first");
3434d16ceb75SStefano Zampini   if (!a->cvec) PetscCall(MatDenseCreateColumnVec_Private(A, &a->cvec));
34356947451fSStefano Zampini   a->vecinuse = col + 1;
34369566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArray(A, (PetscScalar **)&a->ptrinuse));
34379566063dSJacob Faibussowitsch   PetscCall(VecPlaceArray(a->cvec, a->ptrinuse + (size_t)col * (size_t)a->lda));
34386947451fSStefano Zampini   *v = a->cvec;
34393ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
34406947451fSStefano Zampini }
34416947451fSStefano Zampini 
3442d71ae5a4SJacob Faibussowitsch PetscErrorCode MatDenseRestoreColumnVec_SeqDense(Mat A, PetscInt col, Vec *v)
3443d71ae5a4SJacob Faibussowitsch {
34446947451fSStefano Zampini   Mat_SeqDense *a = (Mat_SeqDense *)A->data;
34456947451fSStefano Zampini 
34466947451fSStefano Zampini   PetscFunctionBegin;
344728b400f6SJacob Faibussowitsch   PetscCheck(a->vecinuse, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Need to call MatDenseGetColumnVec() first");
344828b400f6SJacob Faibussowitsch   PetscCheck(a->cvec, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Missing internal column vector");
34494186a4bbSPierre Jolivet   VecCheckAssembled(a->cvec);
34506947451fSStefano Zampini   a->vecinuse = 0;
34519566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArray(A, (PetscScalar **)&a->ptrinuse));
34529566063dSJacob Faibussowitsch   PetscCall(VecResetArray(a->cvec));
345375f6d85dSStefano Zampini   if (v) *v = NULL;
34543ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
34556947451fSStefano Zampini }
34566947451fSStefano Zampini 
3457d71ae5a4SJacob Faibussowitsch PetscErrorCode MatDenseGetColumnVecRead_SeqDense(Mat A, PetscInt col, Vec *v)
3458d71ae5a4SJacob Faibussowitsch {
34596947451fSStefano Zampini   Mat_SeqDense *a = (Mat_SeqDense *)A->data;
34606947451fSStefano Zampini 
34616947451fSStefano Zampini   PetscFunctionBegin;
346228b400f6SJacob Faibussowitsch   PetscCheck(!a->vecinuse, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Need to call MatDenseRestoreColumnVec() first");
346328b400f6SJacob Faibussowitsch   PetscCheck(!a->matinuse, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Need to call MatDenseRestoreSubMatrix() first");
3464d16ceb75SStefano Zampini   if (!a->cvec) PetscCall(MatDenseCreateColumnVec_Private(A, &a->cvec));
34656947451fSStefano Zampini   a->vecinuse = col + 1;
34669566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArrayRead(A, &a->ptrinuse));
34678e3a54c0SPierre Jolivet   PetscCall(VecPlaceArray(a->cvec, PetscSafePointerPlusOffset(a->ptrinuse, (size_t)col * (size_t)a->lda)));
34689566063dSJacob Faibussowitsch   PetscCall(VecLockReadPush(a->cvec));
34696947451fSStefano Zampini   *v = a->cvec;
34703ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
34716947451fSStefano Zampini }
34726947451fSStefano Zampini 
3473d71ae5a4SJacob Faibussowitsch PetscErrorCode MatDenseRestoreColumnVecRead_SeqDense(Mat A, PetscInt col, Vec *v)
3474d71ae5a4SJacob Faibussowitsch {
34756947451fSStefano Zampini   Mat_SeqDense *a = (Mat_SeqDense *)A->data;
34766947451fSStefano Zampini 
34776947451fSStefano Zampini   PetscFunctionBegin;
347828b400f6SJacob Faibussowitsch   PetscCheck(a->vecinuse, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Need to call MatDenseGetColumnVec() first");
347928b400f6SJacob Faibussowitsch   PetscCheck(a->cvec, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Missing internal column vector");
34804186a4bbSPierre Jolivet   VecCheckAssembled(a->cvec);
34816947451fSStefano Zampini   a->vecinuse = 0;
34829566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArrayRead(A, &a->ptrinuse));
34839566063dSJacob Faibussowitsch   PetscCall(VecLockReadPop(a->cvec));
34849566063dSJacob Faibussowitsch   PetscCall(VecResetArray(a->cvec));
348575f6d85dSStefano Zampini   if (v) *v = NULL;
34863ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
34876947451fSStefano Zampini }
34886947451fSStefano Zampini 
3489d71ae5a4SJacob Faibussowitsch PetscErrorCode MatDenseGetColumnVecWrite_SeqDense(Mat A, PetscInt col, Vec *v)
3490d71ae5a4SJacob Faibussowitsch {
34916947451fSStefano Zampini   Mat_SeqDense *a = (Mat_SeqDense *)A->data;
34926947451fSStefano Zampini 
34936947451fSStefano Zampini   PetscFunctionBegin;
349428b400f6SJacob Faibussowitsch   PetscCheck(!a->vecinuse, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Need to call MatDenseRestoreColumnVec() first");
349528b400f6SJacob Faibussowitsch   PetscCheck(!a->matinuse, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Need to call MatDenseRestoreSubMatrix() first");
3496d16ceb75SStefano Zampini   if (!a->cvec) PetscCall(MatDenseCreateColumnVec_Private(A, &a->cvec));
34976947451fSStefano Zampini   a->vecinuse = col + 1;
34989566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArrayWrite(A, (PetscScalar **)&a->ptrinuse));
34998e3a54c0SPierre Jolivet   PetscCall(VecPlaceArray(a->cvec, PetscSafePointerPlusOffset(a->ptrinuse, (size_t)col * (size_t)a->lda)));
35006947451fSStefano Zampini   *v = a->cvec;
35013ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
35026947451fSStefano Zampini }
35036947451fSStefano Zampini 
3504d71ae5a4SJacob Faibussowitsch PetscErrorCode MatDenseRestoreColumnVecWrite_SeqDense(Mat A, PetscInt col, Vec *v)
3505d71ae5a4SJacob Faibussowitsch {
35066947451fSStefano Zampini   Mat_SeqDense *a = (Mat_SeqDense *)A->data;
35076947451fSStefano Zampini 
35086947451fSStefano Zampini   PetscFunctionBegin;
350928b400f6SJacob Faibussowitsch   PetscCheck(a->vecinuse, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Need to call MatDenseGetColumnVec() first");
351028b400f6SJacob Faibussowitsch   PetscCheck(a->cvec, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Missing internal column vector");
35114186a4bbSPierre Jolivet   VecCheckAssembled(a->cvec);
35126947451fSStefano Zampini   a->vecinuse = 0;
35139566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArrayWrite(A, (PetscScalar **)&a->ptrinuse));
35149566063dSJacob Faibussowitsch   PetscCall(VecResetArray(a->cvec));
351575f6d85dSStefano Zampini   if (v) *v = NULL;
35163ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
35176947451fSStefano Zampini }
35186947451fSStefano Zampini 
3519d71ae5a4SJacob Faibussowitsch PetscErrorCode MatDenseGetSubMatrix_SeqDense(Mat A, PetscInt rbegin, PetscInt rend, PetscInt cbegin, PetscInt cend, Mat *v)
3520d71ae5a4SJacob Faibussowitsch {
35215ea7661aSPierre Jolivet   Mat_SeqDense *a = (Mat_SeqDense *)A->data;
35225ea7661aSPierre Jolivet 
35235ea7661aSPierre Jolivet   PetscFunctionBegin;
352428b400f6SJacob Faibussowitsch   PetscCheck(!a->vecinuse, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Need to call MatDenseRestoreColumnVec() first");
352528b400f6SJacob Faibussowitsch   PetscCheck(!a->matinuse, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Need to call MatDenseRestoreSubMatrix() first");
3526a2748737SPierre Jolivet   if (a->cmat && (cend - cbegin != a->cmat->cmap->N || rend - rbegin != a->cmat->rmap->N)) PetscCall(MatDestroy(&a->cmat));
35275ea7661aSPierre Jolivet   if (!a->cmat) {
35288e3a54c0SPierre 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));
35295ea7661aSPierre Jolivet   } else {
35308e3a54c0SPierre Jolivet     PetscCall(MatDensePlaceArray(a->cmat, PetscSafePointerPlusOffset(a->v, rbegin + (size_t)cbegin * a->lda)));
35315ea7661aSPierre Jolivet   }
35329566063dSJacob Faibussowitsch   PetscCall(MatDenseSetLDA(a->cmat, a->lda));
35335ea7661aSPierre Jolivet   a->matinuse = cbegin + 1;
35345ea7661aSPierre Jolivet   *v          = a->cmat;
353547d993e7Ssuyashtn #if defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
353675f6d85dSStefano Zampini   A->offloadmask = PETSC_OFFLOAD_CPU;
353775f6d85dSStefano Zampini #endif
35383ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
35395ea7661aSPierre Jolivet }
35405ea7661aSPierre Jolivet 
3541d71ae5a4SJacob Faibussowitsch PetscErrorCode MatDenseRestoreSubMatrix_SeqDense(Mat A, Mat *v)
3542d71ae5a4SJacob Faibussowitsch {
35435ea7661aSPierre Jolivet   Mat_SeqDense *a = (Mat_SeqDense *)A->data;
35445ea7661aSPierre Jolivet 
35455ea7661aSPierre Jolivet   PetscFunctionBegin;
354628b400f6SJacob Faibussowitsch   PetscCheck(a->matinuse, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Need to call MatDenseGetSubMatrix() first");
354728b400f6SJacob Faibussowitsch   PetscCheck(a->cmat, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Missing internal column matrix");
354808401ef6SPierre Jolivet   PetscCheck(*v == a->cmat, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Not the matrix obtained from MatDenseGetSubMatrix()");
35495ea7661aSPierre Jolivet   a->matinuse = 0;
35509566063dSJacob Faibussowitsch   PetscCall(MatDenseResetArray(a->cmat));
3551742765d3SMatthew Knepley   if (v) *v = NULL;
355247d993e7Ssuyashtn #if defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
35533faff063SStefano Zampini   A->offloadmask = PETSC_OFFLOAD_CPU;
35543faff063SStefano Zampini #endif
35553ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
35565ea7661aSPierre Jolivet }
35575ea7661aSPierre Jolivet 
35580bad9183SKris Buschelman /*MC
3559fafad747SKris Buschelman    MATSEQDENSE - MATSEQDENSE = "seqdense" - A matrix type to be used for sequential dense matrices.
35600bad9183SKris Buschelman 
35612ef1f0ffSBarry Smith    Options Database Key:
356211a5261eSBarry Smith . -mat_type seqdense - sets the matrix type to `MATSEQDENSE` during a call to `MatSetFromOptions()`
35630bad9183SKris Buschelman 
35640bad9183SKris Buschelman   Level: beginner
35650bad9183SKris Buschelman 
35661cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATSEQDENSE`, `MatCreateSeqDense()`
35670bad9183SKris Buschelman M*/
3568d71ae5a4SJacob Faibussowitsch PetscErrorCode MatCreate_SeqDense(Mat B)
3569d71ae5a4SJacob Faibussowitsch {
3570273d9f13SBarry Smith   Mat_SeqDense *b;
35717c334f02SBarry Smith   PetscMPIInt   size;
3572273d9f13SBarry Smith 
3573273d9f13SBarry Smith   PetscFunctionBegin;
35749566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)B), &size));
357508401ef6SPierre Jolivet   PetscCheck(size <= 1, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Comm must be of size 1");
357655659b69SBarry Smith 
35774dfa11a4SJacob Faibussowitsch   PetscCall(PetscNew(&b));
357844cd7ae7SLois Curfman McInnes   B->data   = (void *)b;
3579aea10558SJacob Faibussowitsch   B->ops[0] = MatOps_Values;
358018f449edSLois Curfman McInnes 
3581273d9f13SBarry Smith   b->roworiented = PETSC_TRUE;
35824e220ebcSLois Curfman McInnes 
35839566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatQRFactor_C", MatQRFactor_SeqDense));
35849566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatDenseGetLDA_C", MatDenseGetLDA_SeqDense));
35859566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatDenseSetLDA_C", MatDenseSetLDA_SeqDense));
35869566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatDenseGetArray_C", MatDenseGetArray_SeqDense));
35879566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatDenseRestoreArray_C", MatDenseRestoreArray_SeqDense));
35889566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatDensePlaceArray_C", MatDensePlaceArray_SeqDense));
35899566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatDenseResetArray_C", MatDenseResetArray_SeqDense));
35909566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatDenseReplaceArray_C", MatDenseReplaceArray_SeqDense));
35919566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatDenseGetArrayRead_C", MatDenseGetArray_SeqDense));
35929566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatDenseRestoreArrayRead_C", MatDenseRestoreArray_SeqDense));
35939566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatDenseGetArrayWrite_C", MatDenseGetArray_SeqDense));
35949566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatDenseRestoreArrayWrite_C", MatDenseRestoreArray_SeqDense));
35959566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatConvert_seqdense_seqaij_C", MatConvert_SeqDense_SeqAIJ));
35968baccfbdSHong Zhang #if defined(PETSC_HAVE_ELEMENTAL)
35979566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatConvert_seqdense_elemental_C", MatConvert_SeqDense_Elemental));
35988baccfbdSHong Zhang #endif
3599d24d4204SJose E. Roman #if defined(PETSC_HAVE_SCALAPACK)
36009566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatConvert_seqdense_scalapack_C", MatConvert_Dense_ScaLAPACK));
3601d24d4204SJose E. Roman #endif
36022bf066beSStefano Zampini #if defined(PETSC_HAVE_CUDA)
36039566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatConvert_seqdense_seqdensecuda_C", MatConvert_SeqDense_SeqDenseCUDA));
36049566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatProductSetFromOptions_seqdensecuda_seqdensecuda_C", MatProductSetFromOptions_SeqDense));
36059566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatProductSetFromOptions_seqdensecuda_seqdense_C", MatProductSetFromOptions_SeqDense));
36069566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatProductSetFromOptions_seqdense_seqdensecuda_C", MatProductSetFromOptions_SeqDense));
36072bf066beSStefano Zampini #endif
360847d993e7Ssuyashtn #if defined(PETSC_HAVE_HIP)
360947d993e7Ssuyashtn   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatConvert_seqdense_seqdensehip_C", MatConvert_SeqDense_SeqDenseHIP));
361047d993e7Ssuyashtn   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatProductSetFromOptions_seqdensehip_seqdensehip_C", MatProductSetFromOptions_SeqDense));
361147d993e7Ssuyashtn   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatProductSetFromOptions_seqdensehip_seqdense_C", MatProductSetFromOptions_SeqDense));
361247d993e7Ssuyashtn   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatProductSetFromOptions_seqdense_seqdensehip_C", MatProductSetFromOptions_SeqDense));
361347d993e7Ssuyashtn #endif
36149566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatSeqDenseSetPreallocation_C", MatSeqDenseSetPreallocation_SeqDense));
36159566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatProductSetFromOptions_seqaij_seqdense_C", MatProductSetFromOptions_SeqAIJ_SeqDense));
36169566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatProductSetFromOptions_seqdense_seqdense_C", MatProductSetFromOptions_SeqDense));
36179566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatProductSetFromOptions_seqbaij_seqdense_C", MatProductSetFromOptions_SeqXBAIJ_SeqDense));
36189566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatProductSetFromOptions_seqsbaij_seqdense_C", MatProductSetFromOptions_SeqXBAIJ_SeqDense));
361996e6d5c4SRichard Tran Mills 
36209566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatDenseGetColumn_C", MatDenseGetColumn_SeqDense));
36219566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatDenseRestoreColumn_C", MatDenseRestoreColumn_SeqDense));
36229566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatDenseGetColumnVec_C", MatDenseGetColumnVec_SeqDense));
36239566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatDenseRestoreColumnVec_C", MatDenseRestoreColumnVec_SeqDense));
36249566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatDenseGetColumnVecRead_C", MatDenseGetColumnVecRead_SeqDense));
36259566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatDenseRestoreColumnVecRead_C", MatDenseRestoreColumnVecRead_SeqDense));
36269566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatDenseGetColumnVecWrite_C", MatDenseGetColumnVecWrite_SeqDense));
36279566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatDenseRestoreColumnVecWrite_C", MatDenseRestoreColumnVecWrite_SeqDense));
36289566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatDenseGetSubMatrix_C", MatDenseGetSubMatrix_SeqDense));
36299566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatDenseRestoreSubMatrix_C", MatDenseRestoreSubMatrix_SeqDense));
36300be0d8bdSHansol Suh   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatMultAddColumnRange_C", MatMultAddColumnRange_SeqDense));
36310be0d8bdSHansol Suh   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatMultHermitianTransposeColumnRange_C", MatMultHermitianTransposeColumnRange_SeqDense));
36320be0d8bdSHansol Suh   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatMultHermitianTransposeAddColumnRange_C", MatMultHermitianTransposeAddColumnRange_SeqDense));
36339566063dSJacob Faibussowitsch   PetscCall(PetscObjectChangeTypeName((PetscObject)B, MATSEQDENSE));
36343ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3635289bc588SBarry Smith }
363686aefd0dSHong Zhang 
363786aefd0dSHong Zhang /*@C
363811a5261eSBarry 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.
363986aefd0dSHong Zhang 
364086aefd0dSHong Zhang   Not Collective
364186aefd0dSHong Zhang 
36425ea7661aSPierre Jolivet   Input Parameters:
3643fe59aa6dSJacob Faibussowitsch + A   - a `MATSEQDENSE` or `MATMPIDENSE` matrix
364486aefd0dSHong Zhang - col - column index
364586aefd0dSHong Zhang 
364686aefd0dSHong Zhang   Output Parameter:
364786aefd0dSHong Zhang . vals - pointer to the data
364886aefd0dSHong Zhang 
364986aefd0dSHong Zhang   Level: intermediate
365086aefd0dSHong Zhang 
365111a5261eSBarry Smith   Note:
365211a5261eSBarry Smith   Use `MatDenseGetColumnVec()` to get access to a column of a `MATDENSE` treated as a `Vec`
365311a5261eSBarry Smith 
36541cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATDENSE`, `MatDenseRestoreColumn()`, `MatDenseGetColumnVec()`
365586aefd0dSHong Zhang @*/
36565d83a8b1SBarry Smith PetscErrorCode MatDenseGetColumn(Mat A, PetscInt col, PetscScalar *vals[])
3657d71ae5a4SJacob Faibussowitsch {
365886aefd0dSHong Zhang   PetscFunctionBegin;
3659d5ea218eSStefano Zampini   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
3660d5ea218eSStefano Zampini   PetscValidLogicalCollectiveInt(A, col, 2);
36614f572ea9SToby Isaac   PetscAssertPointer(vals, 3);
3662cac4c232SBarry Smith   PetscUseMethod(A, "MatDenseGetColumn_C", (Mat, PetscInt, PetscScalar **), (A, col, vals));
36633ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
366486aefd0dSHong Zhang }
366586aefd0dSHong Zhang 
366686aefd0dSHong Zhang /*@C
366711a5261eSBarry Smith   MatDenseRestoreColumn - returns access to a column of a `MATDENSE` matrix which is returned by `MatDenseGetColumn()`.
366886aefd0dSHong Zhang 
366986aefd0dSHong Zhang   Not Collective
367086aefd0dSHong Zhang 
3671742765d3SMatthew Knepley   Input Parameters:
3672fe59aa6dSJacob Faibussowitsch + A    - a `MATSEQDENSE` or `MATMPIDENSE` matrix
36732ef1f0ffSBarry Smith - vals - pointer to the data (may be `NULL`)
367486aefd0dSHong Zhang 
367586aefd0dSHong Zhang   Level: intermediate
367686aefd0dSHong Zhang 
36771cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATDENSE`, `MatDenseGetColumn()`
367886aefd0dSHong Zhang @*/
36795d83a8b1SBarry Smith PetscErrorCode MatDenseRestoreColumn(Mat A, PetscScalar *vals[])
3680d71ae5a4SJacob Faibussowitsch {
368186aefd0dSHong Zhang   PetscFunctionBegin;
3682d5ea218eSStefano Zampini   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
36834f572ea9SToby Isaac   PetscAssertPointer(vals, 2);
3684cac4c232SBarry Smith   PetscUseMethod(A, "MatDenseRestoreColumn_C", (Mat, PetscScalar **), (A, vals));
36853ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
368686aefd0dSHong Zhang }
36876947451fSStefano Zampini 
36880f74d2c1SSatish Balay /*@
368911a5261eSBarry Smith   MatDenseGetColumnVec - Gives read-write access to a column of a `MATDENSE` matrix, represented as a `Vec`.
36906947451fSStefano Zampini 
36916947451fSStefano Zampini   Collective
36926947451fSStefano Zampini 
36935ea7661aSPierre Jolivet   Input Parameters:
3694fe59aa6dSJacob Faibussowitsch + A   - the `Mat` object
36956947451fSStefano Zampini - col - the column index
36966947451fSStefano Zampini 
36976947451fSStefano Zampini   Output Parameter:
36986947451fSStefano Zampini . v - the vector
36996947451fSStefano Zampini 
37002ef1f0ffSBarry Smith   Level: intermediate
37012ef1f0ffSBarry Smith 
37026947451fSStefano Zampini   Notes:
370311a5261eSBarry Smith   The vector is owned by PETSc. Users need to call `MatDenseRestoreColumnVec()` when the vector is no longer needed.
370411a5261eSBarry Smith 
370511a5261eSBarry Smith   Use `MatDenseGetColumnVecRead()` to obtain read-only access or `MatDenseGetColumnVecWrite()` for write-only access.
37066947451fSStefano Zampini 
37071cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATDENSE`, `MATDENSECUDA`, `MATDENSEHIP`, `MatDenseGetColumnVecRead()`, `MatDenseGetColumnVecWrite()`, `MatDenseRestoreColumnVec()`, `MatDenseRestoreColumnVecRead()`, `MatDenseRestoreColumnVecWrite()`, `MatDenseGetColumn()`
37086947451fSStefano Zampini @*/
3709d71ae5a4SJacob Faibussowitsch PetscErrorCode MatDenseGetColumnVec(Mat A, PetscInt col, Vec *v)
3710d71ae5a4SJacob Faibussowitsch {
37116947451fSStefano Zampini   PetscFunctionBegin;
37126947451fSStefano Zampini   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
37136947451fSStefano Zampini   PetscValidType(A, 1);
37146947451fSStefano Zampini   PetscValidLogicalCollectiveInt(A, col, 2);
37154f572ea9SToby Isaac   PetscAssertPointer(v, 3);
371628b400f6SJacob Faibussowitsch   PetscCheck(A->preallocated, PetscObjectComm((PetscObject)A), PETSC_ERR_ORDER, "Matrix not preallocated");
37172cf15c64SPierre 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);
3718cac4c232SBarry Smith   PetscUseMethod(A, "MatDenseGetColumnVec_C", (Mat, PetscInt, Vec *), (A, col, v));
37193ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
37206947451fSStefano Zampini }
37216947451fSStefano Zampini 
37220f74d2c1SSatish Balay /*@
3723fb850c59SBarry Smith   MatDenseRestoreColumnVec - Returns access to a column of a dense matrix obtained from `MatDenseGetColumnVec()`.
37246947451fSStefano Zampini 
37256947451fSStefano Zampini   Collective
37266947451fSStefano Zampini 
37275ea7661aSPierre Jolivet   Input Parameters:
3728fb850c59SBarry Smith + A   - the `Mat` object
37296947451fSStefano Zampini . col - the column index
3730fb850c59SBarry Smith - v   - the `Vec` object (may be `NULL`)
37316947451fSStefano Zampini 
37326947451fSStefano Zampini   Level: intermediate
37336947451fSStefano Zampini 
37341cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATDENSE`, `MATDENSECUDA`, `MATDENSEHIP`, `MatDenseGetColumnVec()`, `MatDenseGetColumnVecRead()`, `MatDenseGetColumnVecWrite()`, `MatDenseRestoreColumnVecRead()`, `MatDenseRestoreColumnVecWrite()`
37356947451fSStefano Zampini @*/
3736d71ae5a4SJacob Faibussowitsch PetscErrorCode MatDenseRestoreColumnVec(Mat A, PetscInt col, Vec *v)
3737d71ae5a4SJacob Faibussowitsch {
37386947451fSStefano Zampini   PetscFunctionBegin;
37396947451fSStefano Zampini   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
37406947451fSStefano Zampini   PetscValidType(A, 1);
37416947451fSStefano Zampini   PetscValidLogicalCollectiveInt(A, col, 2);
374208401ef6SPierre Jolivet   PetscCheck(A->preallocated, PetscObjectComm((PetscObject)A), PETSC_ERR_ORDER, "Matrix not preallocated");
37432cf15c64SPierre 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);
3744cac4c232SBarry Smith   PetscUseMethod(A, "MatDenseRestoreColumnVec_C", (Mat, PetscInt, Vec *), (A, col, v));
37453ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
37466947451fSStefano Zampini }
37476947451fSStefano Zampini 
37480f74d2c1SSatish Balay /*@
3749fb850c59SBarry Smith   MatDenseGetColumnVecRead - Gives read-only access to a column of a dense matrix, represented as a `Vec`.
37506947451fSStefano Zampini 
37516947451fSStefano Zampini   Collective
37526947451fSStefano Zampini 
37535ea7661aSPierre Jolivet   Input Parameters:
3754fe59aa6dSJacob Faibussowitsch + A   - the `Mat` object
37556947451fSStefano Zampini - col - the column index
37566947451fSStefano Zampini 
37576947451fSStefano Zampini   Output Parameter:
37586947451fSStefano Zampini . v - the vector
37596947451fSStefano Zampini 
37602ef1f0ffSBarry Smith   Level: intermediate
37612ef1f0ffSBarry Smith 
37626947451fSStefano Zampini   Notes:
37636947451fSStefano Zampini   The vector is owned by PETSc and users cannot modify it.
376411a5261eSBarry Smith 
37652ef1f0ffSBarry Smith   Users need to call `MatDenseRestoreColumnVecRead()` when the vector is no longer needed.
376611a5261eSBarry Smith 
37672ef1f0ffSBarry Smith   Use `MatDenseGetColumnVec()` to obtain read-write access or `MatDenseGetColumnVecWrite()` for write-only access.
37686947451fSStefano Zampini 
37691cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATDENSE`, `MATDENSECUDA`, `MATDENSEHIP`, `MatDenseGetColumnVec()`, `MatDenseGetColumnVecWrite()`, `MatDenseRestoreColumnVec()`, `MatDenseRestoreColumnVecRead()`, `MatDenseRestoreColumnVecWrite()`
37706947451fSStefano Zampini @*/
3771d71ae5a4SJacob Faibussowitsch PetscErrorCode MatDenseGetColumnVecRead(Mat A, PetscInt col, Vec *v)
3772d71ae5a4SJacob Faibussowitsch {
37736947451fSStefano Zampini   PetscFunctionBegin;
37746947451fSStefano Zampini   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
37756947451fSStefano Zampini   PetscValidType(A, 1);
37766947451fSStefano Zampini   PetscValidLogicalCollectiveInt(A, col, 2);
37774f572ea9SToby Isaac   PetscAssertPointer(v, 3);
377828b400f6SJacob Faibussowitsch   PetscCheck(A->preallocated, PetscObjectComm((PetscObject)A), PETSC_ERR_ORDER, "Matrix not preallocated");
37792cf15c64SPierre 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);
3780cac4c232SBarry Smith   PetscUseMethod(A, "MatDenseGetColumnVecRead_C", (Mat, PetscInt, Vec *), (A, col, v));
37813ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
37826947451fSStefano Zampini }
37836947451fSStefano Zampini 
37840f74d2c1SSatish Balay /*@
3785fb850c59SBarry Smith   MatDenseRestoreColumnVecRead - Returns access to a column of a dense matrix obtained from `MatDenseGetColumnVecRead()`.
37866947451fSStefano Zampini 
37876947451fSStefano Zampini   Collective
37886947451fSStefano Zampini 
37895ea7661aSPierre Jolivet   Input Parameters:
3790fe59aa6dSJacob Faibussowitsch + A   - the `Mat` object
37916947451fSStefano Zampini . col - the column index
3792fb850c59SBarry Smith - v   - the `Vec` object (may be `NULL`)
37936947451fSStefano Zampini 
37946947451fSStefano Zampini   Level: intermediate
37956947451fSStefano Zampini 
37961cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATDENSE`, `MATDENSECUDA`, `MATDENSEHIP`, `MatDenseGetColumnVec()`, `MatDenseGetColumnVecRead()`, `MatDenseGetColumnVecWrite()`, `MatDenseRestoreColumnVec()`, `MatDenseRestoreColumnVecWrite()`
37976947451fSStefano Zampini @*/
3798d71ae5a4SJacob Faibussowitsch PetscErrorCode MatDenseRestoreColumnVecRead(Mat A, PetscInt col, Vec *v)
3799d71ae5a4SJacob Faibussowitsch {
38006947451fSStefano Zampini   PetscFunctionBegin;
38016947451fSStefano Zampini   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
38026947451fSStefano Zampini   PetscValidType(A, 1);
38036947451fSStefano Zampini   PetscValidLogicalCollectiveInt(A, col, 2);
380408401ef6SPierre Jolivet   PetscCheck(A->preallocated, PetscObjectComm((PetscObject)A), PETSC_ERR_ORDER, "Matrix not preallocated");
38052cf15c64SPierre 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);
3806cac4c232SBarry Smith   PetscUseMethod(A, "MatDenseRestoreColumnVecRead_C", (Mat, PetscInt, Vec *), (A, col, v));
38073ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
38086947451fSStefano Zampini }
38096947451fSStefano Zampini 
38100f74d2c1SSatish Balay /*@
3811fb850c59SBarry Smith   MatDenseGetColumnVecWrite - Gives write-only access to a column of a dense matrix, represented as a `Vec`.
38126947451fSStefano Zampini 
38136947451fSStefano Zampini   Collective
38146947451fSStefano Zampini 
38155ea7661aSPierre Jolivet   Input Parameters:
3816fe59aa6dSJacob Faibussowitsch + A   - the `Mat` object
38176947451fSStefano Zampini - col - the column index
38186947451fSStefano Zampini 
38196947451fSStefano Zampini   Output Parameter:
38206947451fSStefano Zampini . v - the vector
38216947451fSStefano Zampini 
38226947451fSStefano Zampini   Level: intermediate
38236947451fSStefano Zampini 
38242ef1f0ffSBarry Smith   Notes:
38252ef1f0ffSBarry Smith   The vector is owned by PETSc. Users need to call `MatDenseRestoreColumnVecWrite()` when the vector is no longer needed.
38262ef1f0ffSBarry Smith 
38272ef1f0ffSBarry Smith   Use `MatDenseGetColumnVec()` to obtain read-write access or `MatDenseGetColumnVecRead()` for read-only access.
38282ef1f0ffSBarry Smith 
38291cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATDENSE`, `MATDENSECUDA`, `MATDENSEHIP`, `MatDenseGetColumnVec()`, `MatDenseGetColumnVecRead()`, `MatDenseRestoreColumnVec()`, `MatDenseRestoreColumnVecRead()`, `MatDenseRestoreColumnVecWrite()`
38306947451fSStefano Zampini @*/
3831d71ae5a4SJacob Faibussowitsch PetscErrorCode MatDenseGetColumnVecWrite(Mat A, PetscInt col, Vec *v)
3832d71ae5a4SJacob Faibussowitsch {
38336947451fSStefano Zampini   PetscFunctionBegin;
38346947451fSStefano Zampini   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
38356947451fSStefano Zampini   PetscValidType(A, 1);
38366947451fSStefano Zampini   PetscValidLogicalCollectiveInt(A, col, 2);
38374f572ea9SToby Isaac   PetscAssertPointer(v, 3);
383828b400f6SJacob Faibussowitsch   PetscCheck(A->preallocated, PetscObjectComm((PetscObject)A), PETSC_ERR_ORDER, "Matrix not preallocated");
3839aed4548fSBarry 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);
3840cac4c232SBarry Smith   PetscUseMethod(A, "MatDenseGetColumnVecWrite_C", (Mat, PetscInt, Vec *), (A, col, v));
38413ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
38426947451fSStefano Zampini }
38436947451fSStefano Zampini 
38440f74d2c1SSatish Balay /*@
3845fb850c59SBarry Smith   MatDenseRestoreColumnVecWrite - Returns access to a column of a dense matrix obtained from `MatDenseGetColumnVecWrite()`.
38466947451fSStefano Zampini 
38476947451fSStefano Zampini   Collective
38486947451fSStefano Zampini 
38495ea7661aSPierre Jolivet   Input Parameters:
3850fe59aa6dSJacob Faibussowitsch + A   - the `Mat` object
38516947451fSStefano Zampini . col - the column index
38522ef1f0ffSBarry Smith - v   - the `Vec` object (may be `NULL`)
38536947451fSStefano Zampini 
38546947451fSStefano Zampini   Level: intermediate
38556947451fSStefano Zampini 
38561cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATDENSE`, `MATDENSECUDA`, `MATDENSEHIP`, `MatDenseGetColumnVec()`, `MatDenseGetColumnVecRead()`, `MatDenseGetColumnVecWrite()`, `MatDenseRestoreColumnVec()`, `MatDenseRestoreColumnVecRead()`
38576947451fSStefano Zampini @*/
3858d71ae5a4SJacob Faibussowitsch PetscErrorCode MatDenseRestoreColumnVecWrite(Mat A, PetscInt col, Vec *v)
3859d71ae5a4SJacob Faibussowitsch {
38606947451fSStefano Zampini   PetscFunctionBegin;
38616947451fSStefano Zampini   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
38626947451fSStefano Zampini   PetscValidType(A, 1);
38636947451fSStefano Zampini   PetscValidLogicalCollectiveInt(A, col, 2);
386408401ef6SPierre Jolivet   PetscCheck(A->preallocated, PetscObjectComm((PetscObject)A), PETSC_ERR_ORDER, "Matrix not preallocated");
3865aed4548fSBarry 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);
3866cac4c232SBarry Smith   PetscUseMethod(A, "MatDenseRestoreColumnVecWrite_C", (Mat, PetscInt, Vec *), (A, col, v));
38673ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
38686947451fSStefano Zampini }
38695ea7661aSPierre Jolivet 
38700f74d2c1SSatish Balay /*@
3871fb850c59SBarry Smith   MatDenseGetSubMatrix - Gives access to a block of rows and columns of a dense matrix, represented as a `Mat`.
38725ea7661aSPierre Jolivet 
38735ea7661aSPierre Jolivet   Collective
38745ea7661aSPierre Jolivet 
38755ea7661aSPierre Jolivet   Input Parameters:
3876fb850c59SBarry Smith + A      - the `Mat` object
38772ef1f0ffSBarry Smith . rbegin - the first global row index in the block (if `PETSC_DECIDE`, is 0)
38782ef1f0ffSBarry Smith . rend   - the global row index past the last one in the block (if `PETSC_DECIDE`, is `M`)
38792ef1f0ffSBarry Smith . cbegin - the first global column index in the block (if `PETSC_DECIDE`, is 0)
38802ef1f0ffSBarry Smith - cend   - the global column index past the last one in the block (if `PETSC_DECIDE`, is `N`)
38815ea7661aSPierre Jolivet 
38825ea7661aSPierre Jolivet   Output Parameter:
38835ea7661aSPierre Jolivet . v - the matrix
38845ea7661aSPierre Jolivet 
38855ea7661aSPierre Jolivet   Level: intermediate
38865ea7661aSPierre Jolivet 
38872ef1f0ffSBarry Smith   Notes:
38882ef1f0ffSBarry Smith   The matrix is owned by PETSc. Users need to call `MatDenseRestoreSubMatrix()` when the matrix is no longer needed.
38892ef1f0ffSBarry Smith 
38902ef1f0ffSBarry 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.
38912ef1f0ffSBarry Smith 
38921cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATDENSE`, `MATDENSECUDA`, `MATDENSEHIP`, `MatDenseGetColumnVec()`, `MatDenseRestoreColumnVec()`, `MatDenseRestoreSubMatrix()`
38935ea7661aSPierre Jolivet @*/
3894d71ae5a4SJacob Faibussowitsch PetscErrorCode MatDenseGetSubMatrix(Mat A, PetscInt rbegin, PetscInt rend, PetscInt cbegin, PetscInt cend, Mat *v)
3895d71ae5a4SJacob Faibussowitsch {
38965ea7661aSPierre Jolivet   PetscFunctionBegin;
38975ea7661aSPierre Jolivet   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
38985ea7661aSPierre Jolivet   PetscValidType(A, 1);
3899a2748737SPierre Jolivet   PetscValidLogicalCollectiveInt(A, rbegin, 2);
3900a2748737SPierre Jolivet   PetscValidLogicalCollectiveInt(A, rend, 3);
3901a2748737SPierre Jolivet   PetscValidLogicalCollectiveInt(A, cbegin, 4);
3902a2748737SPierre Jolivet   PetscValidLogicalCollectiveInt(A, cend, 5);
39034f572ea9SToby Isaac   PetscAssertPointer(v, 6);
3904a2748737SPierre Jolivet   if (rbegin == PETSC_DECIDE) rbegin = 0;
3905a2748737SPierre Jolivet   if (rend == PETSC_DECIDE) rend = A->rmap->N;
3906a2748737SPierre Jolivet   if (cbegin == PETSC_DECIDE) cbegin = 0;
3907a2748737SPierre Jolivet   if (cend == PETSC_DECIDE) cend = A->cmap->N;
390828b400f6SJacob Faibussowitsch   PetscCheck(A->preallocated, PetscObjectComm((PetscObject)A), PETSC_ERR_ORDER, "Matrix not preallocated");
3909a2748737SPierre 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);
3910a2748737SPierre 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);
3911a2748737SPierre 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);
3912a2748737SPierre 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);
3913a2748737SPierre Jolivet   PetscUseMethod(A, "MatDenseGetSubMatrix_C", (Mat, PetscInt, PetscInt, PetscInt, PetscInt, Mat *), (A, rbegin, rend, cbegin, cend, v));
39143ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
39155ea7661aSPierre Jolivet }
39165ea7661aSPierre Jolivet 
39170f74d2c1SSatish Balay /*@
3918fb850c59SBarry Smith   MatDenseRestoreSubMatrix - Returns access to a block of columns of a dense matrix obtained from `MatDenseGetSubMatrix()`.
39195ea7661aSPierre Jolivet 
39205ea7661aSPierre Jolivet   Collective
39215ea7661aSPierre Jolivet 
39225ea7661aSPierre Jolivet   Input Parameters:
3923fe59aa6dSJacob Faibussowitsch + A - the `Mat` object
39242ef1f0ffSBarry Smith - v - the `Mat` object (may be `NULL`)
39255ea7661aSPierre Jolivet 
39265ea7661aSPierre Jolivet   Level: intermediate
39275ea7661aSPierre Jolivet 
39281cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATDENSE`, `MATDENSECUDA`, `MATDENSEHIP`, `MatDenseGetColumnVec()`, `MatDenseRestoreColumnVec()`, `MatDenseGetSubMatrix()`
39295ea7661aSPierre Jolivet @*/
3930d71ae5a4SJacob Faibussowitsch PetscErrorCode MatDenseRestoreSubMatrix(Mat A, Mat *v)
3931d71ae5a4SJacob Faibussowitsch {
39325ea7661aSPierre Jolivet   PetscFunctionBegin;
39335ea7661aSPierre Jolivet   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
39345ea7661aSPierre Jolivet   PetscValidType(A, 1);
39354f572ea9SToby Isaac   PetscAssertPointer(v, 2);
3936cac4c232SBarry Smith   PetscUseMethod(A, "MatDenseRestoreSubMatrix_C", (Mat, Mat *), (A, v));
39373ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
39385ea7661aSPierre Jolivet }
39398a9c020eSBarry Smith 
39408a9c020eSBarry Smith #include <petscblaslapack.h>
39418a9c020eSBarry Smith #include <petsc/private/kernels/blockinvert.h>
39428a9c020eSBarry Smith 
3943d71ae5a4SJacob Faibussowitsch PetscErrorCode MatSeqDenseInvert(Mat A)
3944d71ae5a4SJacob Faibussowitsch {
3945d63b1753SJacob Faibussowitsch   PetscInt        m;
39468a9c020eSBarry Smith   const PetscReal shift = 0.0;
3947d63b1753SJacob Faibussowitsch   PetscBool       allowzeropivot, zeropivotdetected = PETSC_FALSE;
3948d63b1753SJacob Faibussowitsch   PetscScalar    *values;
39498a9c020eSBarry Smith 
39508a9c020eSBarry Smith   PetscFunctionBegin;
3951d63b1753SJacob Faibussowitsch   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
3952d63b1753SJacob Faibussowitsch   PetscCall(MatDenseGetArray(A, &values));
3953d63b1753SJacob Faibussowitsch   PetscCall(MatGetLocalSize(A, &m, NULL));
3954d63b1753SJacob Faibussowitsch   allowzeropivot = PetscNot(A->erroriffailure);
39558a9c020eSBarry Smith   /* factor and invert each block */
3956d63b1753SJacob Faibussowitsch   switch (m) {
3957d71ae5a4SJacob Faibussowitsch   case 1:
3958d71ae5a4SJacob Faibussowitsch     values[0] = (PetscScalar)1.0 / (values[0] + shift);
3959d71ae5a4SJacob Faibussowitsch     break;
39608a9c020eSBarry Smith   case 2:
39618a9c020eSBarry Smith     PetscCall(PetscKernel_A_gets_inverse_A_2(values, shift, allowzeropivot, &zeropivotdetected));
39628a9c020eSBarry Smith     if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
39638a9c020eSBarry Smith     break;
39648a9c020eSBarry Smith   case 3:
39658a9c020eSBarry Smith     PetscCall(PetscKernel_A_gets_inverse_A_3(values, shift, allowzeropivot, &zeropivotdetected));
39668a9c020eSBarry Smith     if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
39678a9c020eSBarry Smith     break;
39688a9c020eSBarry Smith   case 4:
39698a9c020eSBarry Smith     PetscCall(PetscKernel_A_gets_inverse_A_4(values, shift, allowzeropivot, &zeropivotdetected));
39708a9c020eSBarry Smith     if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
39718a9c020eSBarry Smith     break;
39729371c9d4SSatish Balay   case 5: {
39738a9c020eSBarry Smith     PetscScalar work[25];
39748a9c020eSBarry Smith     PetscInt    ipvt[5];
39758a9c020eSBarry Smith 
39768a9c020eSBarry Smith     PetscCall(PetscKernel_A_gets_inverse_A_5(values, ipvt, work, shift, allowzeropivot, &zeropivotdetected));
39778a9c020eSBarry Smith     if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
39789371c9d4SSatish Balay   } break;
39798a9c020eSBarry Smith   case 6:
39808a9c020eSBarry Smith     PetscCall(PetscKernel_A_gets_inverse_A_6(values, shift, allowzeropivot, &zeropivotdetected));
39818a9c020eSBarry Smith     if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
39828a9c020eSBarry Smith     break;
39838a9c020eSBarry Smith   case 7:
39848a9c020eSBarry Smith     PetscCall(PetscKernel_A_gets_inverse_A_7(values, shift, allowzeropivot, &zeropivotdetected));
39858a9c020eSBarry Smith     if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
39868a9c020eSBarry Smith     break;
39879371c9d4SSatish Balay   default: {
39888a9c020eSBarry Smith     PetscInt    *v_pivots, *IJ, j;
39898a9c020eSBarry Smith     PetscScalar *v_work;
39908a9c020eSBarry Smith 
3991d63b1753SJacob Faibussowitsch     PetscCall(PetscMalloc3(m, &v_work, m, &v_pivots, m, &IJ));
3992d63b1753SJacob Faibussowitsch     for (j = 0; j < m; j++) IJ[j] = j;
3993d63b1753SJacob Faibussowitsch     PetscCall(PetscKernel_A_gets_inverse_A(m, values, v_pivots, v_work, allowzeropivot, &zeropivotdetected));
39948a9c020eSBarry Smith     if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
39958a9c020eSBarry Smith     PetscCall(PetscFree3(v_work, v_pivots, IJ));
39968a9c020eSBarry Smith   }
39978a9c020eSBarry Smith   }
3998d63b1753SJacob Faibussowitsch   PetscCall(MatDenseRestoreArray(A, &values));
39993ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
40008a9c020eSBarry Smith }
4001