xref: /petsc/src/mat/impls/dense/seq/dense.c (revision 8e3a54c0662fee99ad69f33e814fb6a3f3eef16b)
167e560aaSBarry Smith /*
267e560aaSBarry Smith      Defines the basic matrix operations for sequential dense.
347d993e7Ssuyashtn      Portions of this code are under:
447d993e7Ssuyashtn      Copyright (c) 2022 Advanced Micro Devices, Inc. All rights reserved.
567e560aaSBarry Smith */
6289bc588SBarry Smith 
7dec5eb66SMatthew G Knepley #include <../src/mat/impls/dense/seq/dense.h> /*I "petscmat.h" I*/
8cd3f9d89SJunchao Zhang #include <../src/mat/impls/dense/mpi/mpidense.h>
9c6db04a5SJed Brown #include <petscblaslapack.h>
106a63e612SBarry Smith #include <../src/mat/impls/aij/seq/aij.h>
11b2573a8aSBarry Smith 
12d71ae5a4SJacob Faibussowitsch PetscErrorCode MatSeqDenseSymmetrize_Private(Mat A, PetscBool hermitian)
13d71ae5a4SJacob Faibussowitsch {
148c178816SStefano Zampini   Mat_SeqDense *mat = (Mat_SeqDense *)A->data;
158c178816SStefano Zampini   PetscInt      j, k, n = A->rmap->n;
16ca15aa20SStefano Zampini   PetscScalar  *v;
178c178816SStefano Zampini 
188c178816SStefano Zampini   PetscFunctionBegin;
1908401ef6SPierre Jolivet   PetscCheck(A->rmap->n == A->cmap->n, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Cannot symmetrize a rectangular matrix");
209566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArray(A, &v));
218c178816SStefano Zampini   if (!hermitian) {
228c178816SStefano Zampini     for (k = 0; k < n; k++) {
23ad540459SPierre Jolivet       for (j = k; j < n; j++) v[j * mat->lda + k] = v[k * mat->lda + j];
248c178816SStefano Zampini     }
258c178816SStefano Zampini   } else {
268c178816SStefano Zampini     for (k = 0; k < n; k++) {
27ad540459SPierre Jolivet       for (j = k; j < n; j++) v[j * mat->lda + k] = PetscConj(v[k * mat->lda + j]);
288c178816SStefano Zampini     }
298c178816SStefano Zampini   }
309566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArray(A, &v));
313ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
328c178816SStefano Zampini }
338c178816SStefano Zampini 
34ff6a9541SJacob Faibussowitsch PetscErrorCode MatSeqDenseInvertFactors_Private(Mat A)
35d71ae5a4SJacob Faibussowitsch {
368c178816SStefano Zampini   Mat_SeqDense *mat = (Mat_SeqDense *)A->data;
378c178816SStefano Zampini   PetscBLASInt  info, n;
388c178816SStefano Zampini 
398c178816SStefano Zampini   PetscFunctionBegin;
403ba16761SJacob Faibussowitsch   if (!A->rmap->n || !A->cmap->n) PetscFunctionReturn(PETSC_SUCCESS);
419566063dSJacob Faibussowitsch   PetscCall(PetscBLASIntCast(A->cmap->n, &n));
428c178816SStefano Zampini   if (A->factortype == MAT_FACTOR_LU) {
4328b400f6SJacob Faibussowitsch     PetscCheck(mat->pivots, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Pivots not present");
448c178816SStefano Zampini     if (!mat->fwork) {
458c178816SStefano Zampini       mat->lfwork = n;
469566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(mat->lfwork, &mat->fwork));
478c178816SStefano Zampini     }
489566063dSJacob Faibussowitsch     PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF));
49792fecdfSBarry Smith     PetscCallBLAS("LAPACKgetri", LAPACKgetri_(&n, mat->v, &mat->lda, mat->pivots, mat->fwork, &mat->lfwork, &info));
509566063dSJacob Faibussowitsch     PetscCall(PetscFPTrapPop());
519566063dSJacob Faibussowitsch     PetscCall(PetscLogFlops((1.0 * A->cmap->n * A->cmap->n * A->cmap->n) / 3.0));
528c178816SStefano Zampini   } else if (A->factortype == MAT_FACTOR_CHOLESKY) {
53b94d7dedSBarry Smith     if (A->spd == PETSC_BOOL3_TRUE) {
549566063dSJacob Faibussowitsch       PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF));
55792fecdfSBarry Smith       PetscCallBLAS("LAPACKpotri", LAPACKpotri_("L", &n, mat->v, &mat->lda, &info));
569566063dSJacob Faibussowitsch       PetscCall(PetscFPTrapPop());
579566063dSJacob Faibussowitsch       PetscCall(MatSeqDenseSymmetrize_Private(A, PETSC_TRUE));
588c178816SStefano Zampini #if defined(PETSC_USE_COMPLEX)
59b94d7dedSBarry Smith     } else if (A->hermitian == PETSC_BOOL3_TRUE) {
6028b400f6SJacob Faibussowitsch       PetscCheck(mat->pivots, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Pivots not present");
6128b400f6SJacob Faibussowitsch       PetscCheck(mat->fwork, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Fwork not present");
629566063dSJacob Faibussowitsch       PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF));
63792fecdfSBarry Smith       PetscCallBLAS("LAPACKhetri", LAPACKhetri_("L", &n, mat->v, &mat->lda, mat->pivots, mat->fwork, &info));
649566063dSJacob Faibussowitsch       PetscCall(PetscFPTrapPop());
659566063dSJacob Faibussowitsch       PetscCall(MatSeqDenseSymmetrize_Private(A, PETSC_TRUE));
668c178816SStefano Zampini #endif
678c178816SStefano Zampini     } else { /* symmetric case */
6828b400f6SJacob Faibussowitsch       PetscCheck(mat->pivots, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Pivots not present");
6928b400f6SJacob Faibussowitsch       PetscCheck(mat->fwork, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Fwork not present");
709566063dSJacob Faibussowitsch       PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF));
71792fecdfSBarry Smith       PetscCallBLAS("LAPACKsytri", LAPACKsytri_("L", &n, mat->v, &mat->lda, mat->pivots, mat->fwork, &info));
729566063dSJacob Faibussowitsch       PetscCall(PetscFPTrapPop());
739566063dSJacob Faibussowitsch       PetscCall(MatSeqDenseSymmetrize_Private(A, PETSC_FALSE));
748c178816SStefano Zampini     }
7528b400f6SJacob Faibussowitsch     PetscCheck(!info, PETSC_COMM_SELF, PETSC_ERR_MAT_CH_ZRPVT, "Bad Inversion: zero pivot in row %" PetscInt_FMT, (PetscInt)info - 1);
769566063dSJacob Faibussowitsch     PetscCall(PetscLogFlops((1.0 * A->cmap->n * A->cmap->n * A->cmap->n) / 3.0));
778c178816SStefano Zampini   } else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Matrix must be factored to solve");
788c178816SStefano Zampini 
798c178816SStefano Zampini   A->ops->solve             = NULL;
808c178816SStefano Zampini   A->ops->matsolve          = NULL;
818c178816SStefano Zampini   A->ops->solvetranspose    = NULL;
828c178816SStefano Zampini   A->ops->matsolvetranspose = NULL;
838c178816SStefano Zampini   A->ops->solveadd          = NULL;
848c178816SStefano Zampini   A->ops->solvetransposeadd = NULL;
858c178816SStefano Zampini   A->factortype             = MAT_FACTOR_NONE;
869566063dSJacob Faibussowitsch   PetscCall(PetscFree(A->solvertype));
873ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
888c178816SStefano Zampini }
898c178816SStefano Zampini 
9066976f2fSJacob Faibussowitsch static PetscErrorCode MatZeroRowsColumns_SeqDense(Mat A, PetscInt N, const PetscInt rows[], PetscScalar diag, Vec x, Vec b)
91d71ae5a4SJacob Faibussowitsch {
923f49a652SStefano Zampini   Mat_SeqDense      *l = (Mat_SeqDense *)A->data;
933f49a652SStefano Zampini   PetscInt           m = l->lda, n = A->cmap->n, r = A->rmap->n, i, j;
94ca15aa20SStefano Zampini   PetscScalar       *slot, *bb, *v;
953f49a652SStefano Zampini   const PetscScalar *xx;
963f49a652SStefano Zampini 
973f49a652SStefano Zampini   PetscFunctionBegin;
9876bd3646SJed Brown   if (PetscDefined(USE_DEBUG)) {
993f49a652SStefano Zampini     for (i = 0; i < N; i++) {
10008401ef6SPierre Jolivet       PetscCheck(rows[i] >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Negative row requested to be zeroed");
10108401ef6SPierre Jolivet       PetscCheck(rows[i] < A->rmap->n, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Row %" PetscInt_FMT " requested to be zeroed greater than or equal number of rows %" PetscInt_FMT, rows[i], A->rmap->n);
10208401ef6SPierre Jolivet       PetscCheck(rows[i] < A->cmap->n, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Col %" PetscInt_FMT " requested to be zeroed greater than or equal number of cols %" PetscInt_FMT, rows[i], A->cmap->n);
1033f49a652SStefano Zampini     }
10476bd3646SJed Brown   }
1053ba16761SJacob Faibussowitsch   if (!N) PetscFunctionReturn(PETSC_SUCCESS);
1063f49a652SStefano Zampini 
1073f49a652SStefano Zampini   /* fix right hand side if needed */
1083f49a652SStefano Zampini   if (x && b) {
1096c4d906cSStefano Zampini     Vec xt;
1106c4d906cSStefano Zampini 
11108401ef6SPierre Jolivet     PetscCheck(A->rmap->n == A->cmap->n, PETSC_COMM_SELF, PETSC_ERR_SUP, "Only coded for square matrices");
1129566063dSJacob Faibussowitsch     PetscCall(VecDuplicate(x, &xt));
1139566063dSJacob Faibussowitsch     PetscCall(VecCopy(x, xt));
1149566063dSJacob Faibussowitsch     PetscCall(VecScale(xt, -1.0));
1159566063dSJacob Faibussowitsch     PetscCall(MatMultAdd(A, xt, b, b));
1169566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&xt));
1179566063dSJacob Faibussowitsch     PetscCall(VecGetArrayRead(x, &xx));
1189566063dSJacob Faibussowitsch     PetscCall(VecGetArray(b, &bb));
1193f49a652SStefano Zampini     for (i = 0; i < N; i++) bb[rows[i]] = diag * xx[rows[i]];
1209566063dSJacob Faibussowitsch     PetscCall(VecRestoreArrayRead(x, &xx));
1219566063dSJacob Faibussowitsch     PetscCall(VecRestoreArray(b, &bb));
1223f49a652SStefano Zampini   }
1233f49a652SStefano Zampini 
1249566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArray(A, &v));
1253f49a652SStefano Zampini   for (i = 0; i < N; i++) {
126ca15aa20SStefano Zampini     slot = v + rows[i] * m;
1279566063dSJacob Faibussowitsch     PetscCall(PetscArrayzero(slot, r));
1283f49a652SStefano Zampini   }
1293f49a652SStefano Zampini   for (i = 0; i < N; i++) {
130ca15aa20SStefano Zampini     slot = v + rows[i];
1319371c9d4SSatish Balay     for (j = 0; j < n; j++) {
1329371c9d4SSatish Balay       *slot = 0.0;
1339371c9d4SSatish Balay       slot += m;
1349371c9d4SSatish Balay     }
1353f49a652SStefano Zampini   }
1363f49a652SStefano Zampini   if (diag != 0.0) {
13708401ef6SPierre Jolivet     PetscCheck(A->rmap->n == A->cmap->n, PETSC_COMM_SELF, PETSC_ERR_SUP, "Only coded for square matrices");
1383f49a652SStefano Zampini     for (i = 0; i < N; i++) {
139ca15aa20SStefano Zampini       slot  = v + (m + 1) * rows[i];
1403f49a652SStefano Zampini       *slot = diag;
1413f49a652SStefano Zampini     }
1423f49a652SStefano Zampini   }
1439566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArray(A, &v));
1443ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1453f49a652SStefano Zampini }
1463f49a652SStefano Zampini 
147d71ae5a4SJacob Faibussowitsch PETSC_INTERN PetscErrorCode MatConvert_SeqAIJ_SeqDense(Mat A, MatType newtype, MatReuse reuse, Mat *newmat)
148d71ae5a4SJacob Faibussowitsch {
149a13144ffSStefano Zampini   Mat              B = NULL;
150b49cda9fSStefano Zampini   Mat_SeqAIJ      *a = (Mat_SeqAIJ *)A->data;
151b49cda9fSStefano Zampini   Mat_SeqDense    *b;
152b49cda9fSStefano Zampini   PetscInt        *ai = a->i, *aj = a->j, m = A->rmap->N, n = A->cmap->N, i;
1532e5835c6SStefano Zampini   const MatScalar *av;
154a13144ffSStefano Zampini   PetscBool        isseqdense;
155b49cda9fSStefano Zampini 
156b49cda9fSStefano Zampini   PetscFunctionBegin;
157a13144ffSStefano Zampini   if (reuse == MAT_REUSE_MATRIX) {
1589566063dSJacob Faibussowitsch     PetscCall(PetscObjectTypeCompare((PetscObject)*newmat, MATSEQDENSE, &isseqdense));
15928b400f6SJacob Faibussowitsch     PetscCheck(isseqdense, PetscObjectComm((PetscObject)*newmat), PETSC_ERR_USER, "Cannot reuse matrix of type %s", ((PetscObject)(*newmat))->type_name);
160a13144ffSStefano Zampini   }
161a13144ffSStefano Zampini   if (reuse != MAT_REUSE_MATRIX) {
1629566063dSJacob Faibussowitsch     PetscCall(MatCreate(PetscObjectComm((PetscObject)A), &B));
1639566063dSJacob Faibussowitsch     PetscCall(MatSetSizes(B, m, n, m, n));
1649566063dSJacob Faibussowitsch     PetscCall(MatSetType(B, MATSEQDENSE));
1659566063dSJacob Faibussowitsch     PetscCall(MatSeqDenseSetPreallocation(B, NULL));
166b49cda9fSStefano Zampini     b = (Mat_SeqDense *)(B->data);
167a13144ffSStefano Zampini   } else {
168a13144ffSStefano Zampini     b = (Mat_SeqDense *)((*newmat)->data);
169e1ea5af7SJose E. Roman     for (i = 0; i < n; i++) PetscCall(PetscArrayzero(b->v + i * b->lda, m));
170a13144ffSStefano Zampini   }
1719566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJGetArrayRead(A, &av));
172b49cda9fSStefano Zampini   for (i = 0; i < m; i++) {
173b49cda9fSStefano Zampini     PetscInt j;
174b49cda9fSStefano Zampini     for (j = 0; j < ai[1] - ai[0]; j++) {
175e1ea5af7SJose E. Roman       b->v[*aj * b->lda + i] = *av;
176b49cda9fSStefano Zampini       aj++;
177b49cda9fSStefano Zampini       av++;
178b49cda9fSStefano Zampini     }
179b49cda9fSStefano Zampini     ai++;
180b49cda9fSStefano Zampini   }
1819566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJRestoreArrayRead(A, &av));
182b49cda9fSStefano Zampini 
183511c6705SHong Zhang   if (reuse == MAT_INPLACE_MATRIX) {
1849566063dSJacob Faibussowitsch     PetscCall(MatAssemblyBegin(B, MAT_FINAL_ASSEMBLY));
1859566063dSJacob Faibussowitsch     PetscCall(MatAssemblyEnd(B, MAT_FINAL_ASSEMBLY));
1869566063dSJacob Faibussowitsch     PetscCall(MatHeaderReplace(A, &B));
187b49cda9fSStefano Zampini   } else {
188a13144ffSStefano Zampini     if (B) *newmat = B;
1899566063dSJacob Faibussowitsch     PetscCall(MatAssemblyBegin(*newmat, MAT_FINAL_ASSEMBLY));
1909566063dSJacob Faibussowitsch     PetscCall(MatAssemblyEnd(*newmat, MAT_FINAL_ASSEMBLY));
191b49cda9fSStefano Zampini   }
1923ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
193b49cda9fSStefano Zampini }
194b49cda9fSStefano Zampini 
195d71ae5a4SJacob Faibussowitsch PETSC_INTERN PetscErrorCode MatConvert_SeqDense_SeqAIJ(Mat A, MatType newtype, MatReuse reuse, Mat *newmat)
196d71ae5a4SJacob Faibussowitsch {
1976d4ec7b0SPierre Jolivet   Mat           B = NULL;
1986a63e612SBarry Smith   Mat_SeqDense *a = (Mat_SeqDense *)A->data;
1999399e1b8SMatthew G. Knepley   PetscInt      i, j;
2009399e1b8SMatthew G. Knepley   PetscInt     *rows, *nnz;
2019399e1b8SMatthew G. Knepley   MatScalar    *aa = a->v, *vals;
2026a63e612SBarry Smith 
2036a63e612SBarry Smith   PetscFunctionBegin;
2049566063dSJacob Faibussowitsch   PetscCall(PetscCalloc3(A->rmap->n, &rows, A->rmap->n, &nnz, A->rmap->n, &vals));
2056d4ec7b0SPierre Jolivet   if (reuse != MAT_REUSE_MATRIX) {
2069566063dSJacob Faibussowitsch     PetscCall(MatCreate(PetscObjectComm((PetscObject)A), &B));
2079566063dSJacob Faibussowitsch     PetscCall(MatSetSizes(B, A->rmap->n, A->cmap->n, A->rmap->N, A->cmap->N));
2089566063dSJacob Faibussowitsch     PetscCall(MatSetType(B, MATSEQAIJ));
2099399e1b8SMatthew G. Knepley     for (j = 0; j < A->cmap->n; j++) {
2109371c9d4SSatish Balay       for (i = 0; i < A->rmap->n; i++)
2119371c9d4SSatish Balay         if (aa[i] != 0.0 || (i == j && A->cmap->n == A->rmap->n)) ++nnz[i];
2126a63e612SBarry Smith       aa += a->lda;
2136a63e612SBarry Smith     }
2149566063dSJacob Faibussowitsch     PetscCall(MatSeqAIJSetPreallocation(B, PETSC_DETERMINE, nnz));
2156d4ec7b0SPierre Jolivet   } else B = *newmat;
2169399e1b8SMatthew G. Knepley   aa = a->v;
2179399e1b8SMatthew G. Knepley   for (j = 0; j < A->cmap->n; j++) {
2189399e1b8SMatthew G. Knepley     PetscInt numRows = 0;
2199371c9d4SSatish Balay     for (i = 0; i < A->rmap->n; i++)
2209371c9d4SSatish Balay       if (aa[i] != 0.0 || (i == j && A->cmap->n == A->rmap->n)) {
2219371c9d4SSatish Balay         rows[numRows]   = i;
2229371c9d4SSatish Balay         vals[numRows++] = aa[i];
2239371c9d4SSatish Balay       }
2249566063dSJacob Faibussowitsch     PetscCall(MatSetValues(B, numRows, rows, 1, &j, vals, INSERT_VALUES));
2259399e1b8SMatthew G. Knepley     aa += a->lda;
2269399e1b8SMatthew G. Knepley   }
2279566063dSJacob Faibussowitsch   PetscCall(PetscFree3(rows, nnz, vals));
2289566063dSJacob Faibussowitsch   PetscCall(MatAssemblyBegin(B, MAT_FINAL_ASSEMBLY));
2299566063dSJacob Faibussowitsch   PetscCall(MatAssemblyEnd(B, MAT_FINAL_ASSEMBLY));
2306a63e612SBarry Smith 
231511c6705SHong Zhang   if (reuse == MAT_INPLACE_MATRIX) {
2329566063dSJacob Faibussowitsch     PetscCall(MatHeaderReplace(A, &B));
2336d4ec7b0SPierre Jolivet   } else if (reuse != MAT_REUSE_MATRIX) *newmat = B;
2343ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2356a63e612SBarry Smith }
2366a63e612SBarry Smith 
237d71ae5a4SJacob Faibussowitsch PetscErrorCode MatAXPY_SeqDense(Mat Y, PetscScalar alpha, Mat X, MatStructure str)
238d71ae5a4SJacob Faibussowitsch {
2391987afe7SBarry Smith   Mat_SeqDense      *x = (Mat_SeqDense *)X->data, *y = (Mat_SeqDense *)Y->data;
240ca15aa20SStefano Zampini   const PetscScalar *xv;
241ca15aa20SStefano Zampini   PetscScalar       *yv;
24223fff9afSBarry Smith   PetscBLASInt       N, m, ldax = 0, lday = 0, one = 1;
2433a40ed3dSBarry Smith 
2443a40ed3dSBarry Smith   PetscFunctionBegin;
2459566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArrayRead(X, &xv));
2469566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArray(Y, &yv));
2479566063dSJacob Faibussowitsch   PetscCall(PetscBLASIntCast(X->rmap->n * X->cmap->n, &N));
2489566063dSJacob Faibussowitsch   PetscCall(PetscBLASIntCast(X->rmap->n, &m));
2499566063dSJacob Faibussowitsch   PetscCall(PetscBLASIntCast(x->lda, &ldax));
2509566063dSJacob Faibussowitsch   PetscCall(PetscBLASIntCast(y->lda, &lday));
251a5ce6ee0Svictorle   if (ldax > m || lday > m) {
252*8e3a54c0SPierre Jolivet     for (PetscInt j = 0; j < X->cmap->n; j++) PetscCallBLAS("BLASaxpy", BLASaxpy_(&m, &alpha, PetscSafePointerPlusOffset(xv, j * ldax), &one, PetscSafePointerPlusOffset(yv, j * lday), &one));
253a5ce6ee0Svictorle   } else {
254792fecdfSBarry Smith     PetscCallBLAS("BLASaxpy", BLASaxpy_(&N, &alpha, xv, &one, yv, &one));
255a5ce6ee0Svictorle   }
2569566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArrayRead(X, &xv));
2579566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArray(Y, &yv));
2589566063dSJacob Faibussowitsch   PetscCall(PetscLogFlops(PetscMax(2.0 * N - 1, 0)));
2593ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2601987afe7SBarry Smith }
2611987afe7SBarry Smith 
262d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatGetInfo_SeqDense(Mat A, MatInfoType flag, MatInfo *info)
263d71ae5a4SJacob Faibussowitsch {
264ca15aa20SStefano Zampini   PetscLogDouble N = A->rmap->n * A->cmap->n;
2653a40ed3dSBarry Smith 
2663a40ed3dSBarry Smith   PetscFunctionBegin;
2674e220ebcSLois Curfman McInnes   info->block_size        = 1.0;
268ca15aa20SStefano Zampini   info->nz_allocated      = N;
269ca15aa20SStefano Zampini   info->nz_used           = N;
270ca15aa20SStefano Zampini   info->nz_unneeded       = 0;
271ca15aa20SStefano Zampini   info->assemblies        = A->num_ass;
2724e220ebcSLois Curfman McInnes   info->mallocs           = 0;
2734dfa11a4SJacob Faibussowitsch   info->memory            = 0; /* REVIEW ME */
2744e220ebcSLois Curfman McInnes   info->fill_ratio_given  = 0;
2754e220ebcSLois Curfman McInnes   info->fill_ratio_needed = 0;
2764e220ebcSLois Curfman McInnes   info->factor_mallocs    = 0;
2773ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
278289bc588SBarry Smith }
279289bc588SBarry Smith 
280d71ae5a4SJacob Faibussowitsch PetscErrorCode MatScale_SeqDense(Mat A, PetscScalar alpha)
281d71ae5a4SJacob Faibussowitsch {
282273d9f13SBarry Smith   Mat_SeqDense *a = (Mat_SeqDense *)A->data;
283ca15aa20SStefano Zampini   PetscScalar  *v;
28423fff9afSBarry Smith   PetscBLASInt  one = 1, j, nz, lda = 0;
28580cd9d93SLois Curfman McInnes 
2863a40ed3dSBarry Smith   PetscFunctionBegin;
2879566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArray(A, &v));
2889566063dSJacob Faibussowitsch   PetscCall(PetscBLASIntCast(a->lda, &lda));
289d0f46423SBarry Smith   if (lda > A->rmap->n) {
2909566063dSJacob Faibussowitsch     PetscCall(PetscBLASIntCast(A->rmap->n, &nz));
29148a46eb9SPierre Jolivet     for (j = 0; j < A->cmap->n; j++) PetscCallBLAS("BLASscal", BLASscal_(&nz, &alpha, v + j * lda, &one));
292a5ce6ee0Svictorle   } else {
2939566063dSJacob Faibussowitsch     PetscCall(PetscBLASIntCast(A->rmap->n * A->cmap->n, &nz));
294792fecdfSBarry Smith     PetscCallBLAS("BLASscal", BLASscal_(&nz, &alpha, v, &one));
295a5ce6ee0Svictorle   }
29604cbc005SJose E. Roman   PetscCall(PetscLogFlops(A->rmap->n * A->cmap->n));
2979566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArray(A, &v));
2983ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
29980cd9d93SLois Curfman McInnes }
30080cd9d93SLois Curfman McInnes 
301d71ae5a4SJacob Faibussowitsch PetscErrorCode MatShift_SeqDense(Mat A, PetscScalar alpha)
302d71ae5a4SJacob Faibussowitsch {
3032f605a99SJose E. Roman   Mat_SeqDense *a = (Mat_SeqDense *)A->data;
3042f605a99SJose E. Roman   PetscScalar  *v;
3052f605a99SJose E. Roman   PetscInt      j, k;
3062f605a99SJose E. Roman 
3072f605a99SJose E. Roman   PetscFunctionBegin;
3082f605a99SJose E. Roman   PetscCall(MatDenseGetArray(A, &v));
3092f605a99SJose E. Roman   k = PetscMin(A->rmap->n, A->cmap->n);
3102f605a99SJose E. Roman   for (j = 0; j < k; j++) v[j + j * a->lda] += alpha;
3112f605a99SJose E. Roman   PetscCall(PetscLogFlops(k));
3122f605a99SJose E. Roman   PetscCall(MatDenseRestoreArray(A, &v));
3133ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3142f605a99SJose E. Roman }
3152f605a99SJose E. Roman 
316d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatIsHermitian_SeqDense(Mat A, PetscReal rtol, PetscBool *fl)
317d71ae5a4SJacob Faibussowitsch {
3181cbb95d3SBarry Smith   Mat_SeqDense      *a = (Mat_SeqDense *)A->data;
319ca15aa20SStefano Zampini   PetscInt           i, j, m = A->rmap->n, N = a->lda;
320ca15aa20SStefano Zampini   const PetscScalar *v;
3211cbb95d3SBarry Smith 
3221cbb95d3SBarry Smith   PetscFunctionBegin;
3231cbb95d3SBarry Smith   *fl = PETSC_FALSE;
3243ba16761SJacob Faibussowitsch   if (A->rmap->n != A->cmap->n) PetscFunctionReturn(PETSC_SUCCESS);
3259566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArrayRead(A, &v));
3261cbb95d3SBarry Smith   for (i = 0; i < m; i++) {
327ca15aa20SStefano Zampini     for (j = i; j < m; j++) {
328ad540459SPierre Jolivet       if (PetscAbsScalar(v[i + j * N] - PetscConj(v[j + i * N])) > rtol) goto restore;
3291cbb95d3SBarry Smith     }
330637a0070SStefano Zampini   }
3311cbb95d3SBarry Smith   *fl = PETSC_TRUE;
332637a0070SStefano Zampini restore:
3339566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArrayRead(A, &v));
3343ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
335637a0070SStefano Zampini }
336637a0070SStefano Zampini 
337d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatIsSymmetric_SeqDense(Mat A, PetscReal rtol, PetscBool *fl)
338d71ae5a4SJacob Faibussowitsch {
339637a0070SStefano Zampini   Mat_SeqDense      *a = (Mat_SeqDense *)A->data;
340637a0070SStefano Zampini   PetscInt           i, j, m = A->rmap->n, N = a->lda;
341637a0070SStefano Zampini   const PetscScalar *v;
342637a0070SStefano Zampini 
343637a0070SStefano Zampini   PetscFunctionBegin;
344637a0070SStefano Zampini   *fl = PETSC_FALSE;
3453ba16761SJacob Faibussowitsch   if (A->rmap->n != A->cmap->n) PetscFunctionReturn(PETSC_SUCCESS);
3469566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArrayRead(A, &v));
347637a0070SStefano Zampini   for (i = 0; i < m; i++) {
348637a0070SStefano Zampini     for (j = i; j < m; j++) {
349ad540459SPierre Jolivet       if (PetscAbsScalar(v[i + j * N] - v[j + i * N]) > rtol) goto restore;
350637a0070SStefano Zampini     }
351637a0070SStefano Zampini   }
352637a0070SStefano Zampini   *fl = PETSC_TRUE;
353637a0070SStefano Zampini restore:
3549566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArrayRead(A, &v));
3553ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3561cbb95d3SBarry Smith }
3571cbb95d3SBarry Smith 
358d71ae5a4SJacob Faibussowitsch PetscErrorCode MatDuplicateNoCreate_SeqDense(Mat newi, Mat A, MatDuplicateOption cpvalues)
359d71ae5a4SJacob Faibussowitsch {
360ca15aa20SStefano Zampini   Mat_SeqDense *mat = (Mat_SeqDense *)A->data;
36123fc5dcaSStefano Zampini   PetscInt      lda = (PetscInt)mat->lda, j, m, nlda = lda;
36275f6d85dSStefano Zampini   PetscBool     isdensecpu;
363b24902e0SBarry Smith 
364b24902e0SBarry Smith   PetscFunctionBegin;
3659566063dSJacob Faibussowitsch   PetscCall(PetscLayoutReference(A->rmap, &newi->rmap));
3669566063dSJacob Faibussowitsch   PetscCall(PetscLayoutReference(A->cmap, &newi->cmap));
36723fc5dcaSStefano Zampini   if (cpvalues == MAT_SHARE_NONZERO_PATTERN) { /* propagate LDA */
3689566063dSJacob Faibussowitsch     PetscCall(MatDenseSetLDA(newi, lda));
36923fc5dcaSStefano Zampini   }
3709566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)newi, MATSEQDENSE, &isdensecpu));
3719566063dSJacob Faibussowitsch   if (isdensecpu) PetscCall(MatSeqDenseSetPreallocation(newi, NULL));
372b24902e0SBarry Smith   if (cpvalues == MAT_COPY_VALUES) {
373ca15aa20SStefano Zampini     const PetscScalar *av;
374ca15aa20SStefano Zampini     PetscScalar       *v;
375ca15aa20SStefano Zampini 
3769566063dSJacob Faibussowitsch     PetscCall(MatDenseGetArrayRead(A, &av));
3779566063dSJacob Faibussowitsch     PetscCall(MatDenseGetArrayWrite(newi, &v));
3789566063dSJacob Faibussowitsch     PetscCall(MatDenseGetLDA(newi, &nlda));
379d0f46423SBarry Smith     m = A->rmap->n;
38023fc5dcaSStefano Zampini     if (lda > m || nlda > m) {
381*8e3a54c0SPierre Jolivet       for (j = 0; j < A->cmap->n; j++) PetscCall(PetscArraycpy(PetscSafePointerPlusOffset(v, j * nlda), PetscSafePointerPlusOffset(av, j * lda), m));
382b24902e0SBarry Smith     } else {
3839566063dSJacob Faibussowitsch       PetscCall(PetscArraycpy(v, av, A->rmap->n * A->cmap->n));
384b24902e0SBarry Smith     }
3859566063dSJacob Faibussowitsch     PetscCall(MatDenseRestoreArrayWrite(newi, &v));
3869566063dSJacob Faibussowitsch     PetscCall(MatDenseRestoreArrayRead(A, &av));
387b24902e0SBarry Smith   }
3883ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
389b24902e0SBarry Smith }
390b24902e0SBarry Smith 
391d71ae5a4SJacob Faibussowitsch PetscErrorCode MatDuplicate_SeqDense(Mat A, MatDuplicateOption cpvalues, Mat *newmat)
392d71ae5a4SJacob Faibussowitsch {
3933a40ed3dSBarry Smith   PetscFunctionBegin;
3949566063dSJacob Faibussowitsch   PetscCall(MatCreate(PetscObjectComm((PetscObject)A), newmat));
3959566063dSJacob Faibussowitsch   PetscCall(MatSetSizes(*newmat, A->rmap->n, A->cmap->n, A->rmap->n, A->cmap->n));
3969566063dSJacob Faibussowitsch   PetscCall(MatSetType(*newmat, ((PetscObject)A)->type_name));
3979566063dSJacob Faibussowitsch   PetscCall(MatDuplicateNoCreate_SeqDense(*newmat, A, cpvalues));
3983ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
399b24902e0SBarry Smith }
400b24902e0SBarry Smith 
401d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatSolve_SeqDense_Internal_LU(Mat A, PetscScalar *x, PetscBLASInt ldx, PetscBLASInt m, PetscBLASInt nrhs, PetscBLASInt k, PetscBool T)
402d71ae5a4SJacob Faibussowitsch {
403c0bbcb79SLois Curfman McInnes   Mat_SeqDense *mat = (Mat_SeqDense *)A->data;
4044396437dSToby Isaac   PetscBLASInt  info;
40567e560aaSBarry Smith 
4063a40ed3dSBarry Smith   PetscFunctionBegin;
4079566063dSJacob Faibussowitsch   PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF));
408792fecdfSBarry Smith   PetscCallBLAS("LAPACKgetrs", LAPACKgetrs_(T ? "T" : "N", &m, &nrhs, mat->v, &mat->lda, mat->pivots, x, &m, &info));
4099566063dSJacob Faibussowitsch   PetscCall(PetscFPTrapPop());
41005fcb23eSStefano Zampini   PetscCheck(!info, PETSC_COMM_SELF, PETSC_ERR_LIB, "GETRS - Bad solve %d", (int)info);
4119566063dSJacob Faibussowitsch   PetscCall(PetscLogFlops(nrhs * (2.0 * m * m - m)));
4123ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4134396437dSToby Isaac }
4144396437dSToby Isaac 
4154396437dSToby Isaac static PetscErrorCode MatConjugate_SeqDense(Mat);
4164396437dSToby Isaac 
417d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatSolve_SeqDense_Internal_Cholesky(Mat A, PetscScalar *x, PetscBLASInt ldx, PetscBLASInt m, PetscBLASInt nrhs, PetscBLASInt k, PetscBool T)
418d71ae5a4SJacob Faibussowitsch {
4194396437dSToby Isaac   Mat_SeqDense *mat = (Mat_SeqDense *)A->data;
4204396437dSToby Isaac   PetscBLASInt  info;
4214396437dSToby Isaac 
4224396437dSToby Isaac   PetscFunctionBegin;
423b94d7dedSBarry Smith   if (A->spd == PETSC_BOOL3_TRUE) {
4249566063dSJacob Faibussowitsch     if (PetscDefined(USE_COMPLEX) && T) PetscCall(MatConjugate_SeqDense(A));
4259566063dSJacob Faibussowitsch     PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF));
426792fecdfSBarry Smith     PetscCallBLAS("LAPACKpotrs", LAPACKpotrs_("L", &m, &nrhs, mat->v, &mat->lda, x, &m, &info));
4279566063dSJacob Faibussowitsch     PetscCall(PetscFPTrapPop());
42805fcb23eSStefano Zampini     PetscCheck(!info, PETSC_COMM_SELF, PETSC_ERR_LIB, "POTRS Bad solve %d", (int)info);
4299566063dSJacob Faibussowitsch     if (PetscDefined(USE_COMPLEX) && T) PetscCall(MatConjugate_SeqDense(A));
430a49dc2a2SStefano Zampini #if defined(PETSC_USE_COMPLEX)
431b94d7dedSBarry Smith   } else if (A->hermitian == PETSC_BOOL3_TRUE) {
4329566063dSJacob Faibussowitsch     if (T) PetscCall(MatConjugate_SeqDense(A));
4339566063dSJacob Faibussowitsch     PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF));
434792fecdfSBarry Smith     PetscCallBLAS("LAPACKhetrs", LAPACKhetrs_("L", &m, &nrhs, mat->v, &mat->lda, mat->pivots, x, &m, &info));
4359566063dSJacob Faibussowitsch     PetscCall(PetscFPTrapPop());
43605fcb23eSStefano Zampini     PetscCheck(!info, PETSC_COMM_SELF, PETSC_ERR_LIB, "HETRS Bad solve %d", (int)info);
4379566063dSJacob Faibussowitsch     if (T) PetscCall(MatConjugate_SeqDense(A));
438a49dc2a2SStefano Zampini #endif
439a49dc2a2SStefano Zampini   } else { /* symmetric case */
4409566063dSJacob Faibussowitsch     PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF));
441792fecdfSBarry Smith     PetscCallBLAS("LAPACKsytrs", LAPACKsytrs_("L", &m, &nrhs, mat->v, &mat->lda, mat->pivots, x, &m, &info));
4429566063dSJacob Faibussowitsch     PetscCall(PetscFPTrapPop());
44305fcb23eSStefano Zampini     PetscCheck(!info, PETSC_COMM_SELF, PETSC_ERR_LIB, "SYTRS Bad solve %d", (int)info);
444a49dc2a2SStefano Zampini   }
4459566063dSJacob Faibussowitsch   PetscCall(PetscLogFlops(nrhs * (2.0 * m * m - m)));
4463ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4474396437dSToby Isaac }
44885e2c93fSHong Zhang 
449d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatSolve_SeqDense_Internal_QR(Mat A, PetscScalar *x, PetscBLASInt ldx, PetscBLASInt m, PetscBLASInt nrhs, PetscBLASInt k)
450d71ae5a4SJacob Faibussowitsch {
4514396437dSToby Isaac   Mat_SeqDense *mat = (Mat_SeqDense *)A->data;
4524396437dSToby Isaac   PetscBLASInt  info;
4534396437dSToby Isaac   char          trans;
4544396437dSToby Isaac 
4554396437dSToby Isaac   PetscFunctionBegin;
4564905a7bcSToby Isaac   if (PetscDefined(USE_COMPLEX)) {
4574905a7bcSToby Isaac     trans = 'C';
4584905a7bcSToby Isaac   } else {
4594905a7bcSToby Isaac     trans = 'T';
4604905a7bcSToby Isaac   }
4619566063dSJacob Faibussowitsch   PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF));
46205fcb23eSStefano Zampini   { /* lwork depends on the number of right-hand sides */
46305fcb23eSStefano Zampini     PetscBLASInt nlfwork, lfwork = -1;
46405fcb23eSStefano Zampini     PetscScalar  fwork;
46505fcb23eSStefano Zampini 
466792fecdfSBarry Smith     PetscCallBLAS("LAPACKormqr", LAPACKormqr_("L", &trans, &m, &nrhs, &mat->rank, mat->v, &mat->lda, mat->tau, x, &ldx, &fwork, &lfwork, &info));
46705fcb23eSStefano Zampini     nlfwork = (PetscBLASInt)PetscRealPart(fwork);
46805fcb23eSStefano Zampini     if (nlfwork > mat->lfwork) {
46905fcb23eSStefano Zampini       mat->lfwork = nlfwork;
47005fcb23eSStefano Zampini       PetscCall(PetscFree(mat->fwork));
47105fcb23eSStefano Zampini       PetscCall(PetscMalloc1(mat->lfwork, &mat->fwork));
47205fcb23eSStefano Zampini     }
47305fcb23eSStefano Zampini   }
474792fecdfSBarry Smith   PetscCallBLAS("LAPACKormqr", LAPACKormqr_("L", &trans, &m, &nrhs, &mat->rank, mat->v, &mat->lda, mat->tau, x, &ldx, mat->fwork, &mat->lfwork, &info));
4759566063dSJacob Faibussowitsch   PetscCall(PetscFPTrapPop());
47605fcb23eSStefano Zampini   PetscCheck(!info, PETSC_COMM_SELF, PETSC_ERR_LIB, "ORMQR - Bad orthogonal transform %d", (int)info);
4779566063dSJacob Faibussowitsch   PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF));
478792fecdfSBarry Smith   PetscCallBLAS("LAPACKtrtrs", LAPACKtrtrs_("U", "N", "N", &mat->rank, &nrhs, mat->v, &mat->lda, x, &ldx, &info));
4799566063dSJacob Faibussowitsch   PetscCall(PetscFPTrapPop());
48005fcb23eSStefano Zampini   PetscCheck(!info, PETSC_COMM_SELF, PETSC_ERR_LIB, "TRTRS - Bad triangular solve %d", (int)info);
4814905a7bcSToby Isaac   for (PetscInt j = 0; j < nrhs; j++) {
482ad540459SPierre Jolivet     for (PetscInt i = mat->rank; i < k; i++) x[j * ldx + i] = 0.;
4834905a7bcSToby Isaac   }
4849566063dSJacob Faibussowitsch   PetscCall(PetscLogFlops(nrhs * (4.0 * m * mat->rank - PetscSqr(mat->rank))));
4853ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4864905a7bcSToby Isaac }
4874905a7bcSToby Isaac 
488d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatSolveTranspose_SeqDense_Internal_QR(Mat A, PetscScalar *x, PetscBLASInt ldx, PetscBLASInt m, PetscBLASInt nrhs, PetscBLASInt k)
489d71ae5a4SJacob Faibussowitsch {
4904396437dSToby Isaac   Mat_SeqDense *mat = (Mat_SeqDense *)A->data;
4914396437dSToby Isaac   PetscBLASInt  info;
4924396437dSToby Isaac 
4934396437dSToby Isaac   PetscFunctionBegin;
4944396437dSToby Isaac   if (A->rmap->n == A->cmap->n && mat->rank == A->rmap->n) {
4959566063dSJacob Faibussowitsch     PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF));
496792fecdfSBarry Smith     PetscCallBLAS("LAPACKtrtrs", LAPACKtrtrs_("U", "T", "N", &m, &nrhs, mat->v, &mat->lda, x, &ldx, &info));
4979566063dSJacob Faibussowitsch     PetscCall(PetscFPTrapPop());
49805fcb23eSStefano Zampini     PetscCheck(!info, PETSC_COMM_SELF, PETSC_ERR_LIB, "TRTRS - Bad triangular solve %d", (int)info);
4999566063dSJacob Faibussowitsch     if (PetscDefined(USE_COMPLEX)) PetscCall(MatConjugate_SeqDense(A));
50005fcb23eSStefano Zampini     { /* lwork depends on the number of right-hand sides */
50105fcb23eSStefano Zampini       PetscBLASInt nlfwork, lfwork = -1;
50205fcb23eSStefano Zampini       PetscScalar  fwork;
50305fcb23eSStefano Zampini 
504792fecdfSBarry Smith       PetscCallBLAS("LAPACKormqr", LAPACKormqr_("L", "N", &m, &nrhs, &mat->rank, mat->v, &mat->lda, mat->tau, x, &ldx, &fwork, &lfwork, &info));
50505fcb23eSStefano Zampini       nlfwork = (PetscBLASInt)PetscRealPart(fwork);
50605fcb23eSStefano Zampini       if (nlfwork > mat->lfwork) {
50705fcb23eSStefano Zampini         mat->lfwork = nlfwork;
50805fcb23eSStefano Zampini         PetscCall(PetscFree(mat->fwork));
50905fcb23eSStefano Zampini         PetscCall(PetscMalloc1(mat->lfwork, &mat->fwork));
51005fcb23eSStefano Zampini       }
51105fcb23eSStefano Zampini     }
5129566063dSJacob Faibussowitsch     PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF));
513792fecdfSBarry Smith     PetscCallBLAS("LAPACKormqr", LAPACKormqr_("L", "N", &m, &nrhs, &mat->rank, mat->v, &mat->lda, mat->tau, x, &ldx, mat->fwork, &mat->lfwork, &info));
5149566063dSJacob Faibussowitsch     PetscCall(PetscFPTrapPop());
51505fcb23eSStefano Zampini     PetscCheck(!info, PETSC_COMM_SELF, PETSC_ERR_LIB, "ORMQR - Bad orthogonal transform %d", (int)info);
5169566063dSJacob Faibussowitsch     if (PetscDefined(USE_COMPLEX)) PetscCall(MatConjugate_SeqDense(A));
5174396437dSToby Isaac   } else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "QR factored matrix cannot be used for transpose solve");
5189566063dSJacob Faibussowitsch   PetscCall(PetscLogFlops(nrhs * (4.0 * m * mat->rank - PetscSqr(mat->rank))));
5193ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5204396437dSToby Isaac }
5214396437dSToby Isaac 
522d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatSolve_SeqDense_SetUp(Mat A, Vec xx, Vec yy, PetscScalar **_y, PetscBLASInt *_m, PetscBLASInt *_k)
523d71ae5a4SJacob Faibussowitsch {
5244396437dSToby Isaac   Mat_SeqDense *mat = (Mat_SeqDense *)A->data;
5254905a7bcSToby Isaac   PetscScalar  *y;
5264905a7bcSToby Isaac   PetscBLASInt  m = 0, k = 0;
5274905a7bcSToby Isaac 
5284905a7bcSToby Isaac   PetscFunctionBegin;
5299566063dSJacob Faibussowitsch   PetscCall(PetscBLASIntCast(A->rmap->n, &m));
5309566063dSJacob Faibussowitsch   PetscCall(PetscBLASIntCast(A->cmap->n, &k));
5314905a7bcSToby Isaac   if (k < m) {
5329566063dSJacob Faibussowitsch     PetscCall(VecCopy(xx, mat->qrrhs));
5339566063dSJacob Faibussowitsch     PetscCall(VecGetArray(mat->qrrhs, &y));
5344905a7bcSToby Isaac   } else {
5359566063dSJacob Faibussowitsch     PetscCall(VecCopy(xx, yy));
5369566063dSJacob Faibussowitsch     PetscCall(VecGetArray(yy, &y));
5374905a7bcSToby Isaac   }
5384396437dSToby Isaac   *_y = y;
5394396437dSToby Isaac   *_k = k;
5404396437dSToby Isaac   *_m = m;
5413ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5424396437dSToby Isaac }
5434396437dSToby Isaac 
544d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatSolve_SeqDense_TearDown(Mat A, Vec xx, Vec yy, PetscScalar **_y, PetscBLASInt *_m, PetscBLASInt *_k)
545d71ae5a4SJacob Faibussowitsch {
5464396437dSToby Isaac   Mat_SeqDense *mat = (Mat_SeqDense *)A->data;
54742e9364cSSatish Balay   PetscScalar  *y   = NULL;
5484396437dSToby Isaac   PetscBLASInt  m, k;
5494396437dSToby Isaac 
5504396437dSToby Isaac   PetscFunctionBegin;
5514396437dSToby Isaac   y   = *_y;
5524396437dSToby Isaac   *_y = NULL;
5534396437dSToby Isaac   k   = *_k;
5544396437dSToby Isaac   m   = *_m;
5554905a7bcSToby Isaac   if (k < m) {
5564905a7bcSToby Isaac     PetscScalar *yv;
5579566063dSJacob Faibussowitsch     PetscCall(VecGetArray(yy, &yv));
5589566063dSJacob Faibussowitsch     PetscCall(PetscArraycpy(yv, y, k));
5599566063dSJacob Faibussowitsch     PetscCall(VecRestoreArray(yy, &yv));
5609566063dSJacob Faibussowitsch     PetscCall(VecRestoreArray(mat->qrrhs, &y));
5614905a7bcSToby Isaac   } else {
5629566063dSJacob Faibussowitsch     PetscCall(VecRestoreArray(yy, &y));
5634905a7bcSToby Isaac   }
5643ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5654905a7bcSToby Isaac }
5664905a7bcSToby Isaac 
567d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatSolve_SeqDense_LU(Mat A, Vec xx, Vec yy)
568d71ae5a4SJacob Faibussowitsch {
56942e9364cSSatish Balay   PetscScalar *y = NULL;
57042e9364cSSatish Balay   PetscBLASInt m = 0, k = 0;
5714396437dSToby Isaac 
5724396437dSToby Isaac   PetscFunctionBegin;
5739566063dSJacob Faibussowitsch   PetscCall(MatSolve_SeqDense_SetUp(A, xx, yy, &y, &m, &k));
5749566063dSJacob Faibussowitsch   PetscCall(MatSolve_SeqDense_Internal_LU(A, y, m, m, 1, k, PETSC_FALSE));
5759566063dSJacob Faibussowitsch   PetscCall(MatSolve_SeqDense_TearDown(A, xx, yy, &y, &m, &k));
5763ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5774396437dSToby Isaac }
5784396437dSToby Isaac 
579d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatSolveTranspose_SeqDense_LU(Mat A, Vec xx, Vec yy)
580d71ae5a4SJacob Faibussowitsch {
58142e9364cSSatish Balay   PetscScalar *y = NULL;
58242e9364cSSatish Balay   PetscBLASInt m = 0, k = 0;
5834396437dSToby Isaac 
5844396437dSToby Isaac   PetscFunctionBegin;
5859566063dSJacob Faibussowitsch   PetscCall(MatSolve_SeqDense_SetUp(A, xx, yy, &y, &m, &k));
5869566063dSJacob Faibussowitsch   PetscCall(MatSolve_SeqDense_Internal_LU(A, y, m, m, 1, k, PETSC_TRUE));
5879566063dSJacob Faibussowitsch   PetscCall(MatSolve_SeqDense_TearDown(A, xx, yy, &y, &m, &k));
5883ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5894396437dSToby Isaac }
5904396437dSToby Isaac 
591d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatSolve_SeqDense_Cholesky(Mat A, Vec xx, Vec yy)
592d71ae5a4SJacob Faibussowitsch {
593e54beecaSStefano Zampini   PetscScalar *y = NULL;
594e54beecaSStefano Zampini   PetscBLASInt m = 0, k = 0;
5954396437dSToby Isaac 
5964396437dSToby Isaac   PetscFunctionBegin;
5979566063dSJacob Faibussowitsch   PetscCall(MatSolve_SeqDense_SetUp(A, xx, yy, &y, &m, &k));
5989566063dSJacob Faibussowitsch   PetscCall(MatSolve_SeqDense_Internal_Cholesky(A, y, m, m, 1, k, PETSC_FALSE));
5999566063dSJacob Faibussowitsch   PetscCall(MatSolve_SeqDense_TearDown(A, xx, yy, &y, &m, &k));
6003ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
6014396437dSToby Isaac }
6024396437dSToby Isaac 
603d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatSolveTranspose_SeqDense_Cholesky(Mat A, Vec xx, Vec yy)
604d71ae5a4SJacob Faibussowitsch {
605e54beecaSStefano Zampini   PetscScalar *y = NULL;
606e54beecaSStefano Zampini   PetscBLASInt m = 0, k = 0;
6074396437dSToby Isaac 
6084396437dSToby Isaac   PetscFunctionBegin;
6099566063dSJacob Faibussowitsch   PetscCall(MatSolve_SeqDense_SetUp(A, xx, yy, &y, &m, &k));
6109566063dSJacob Faibussowitsch   PetscCall(MatSolve_SeqDense_Internal_Cholesky(A, y, m, m, 1, k, PETSC_TRUE));
6119566063dSJacob Faibussowitsch   PetscCall(MatSolve_SeqDense_TearDown(A, xx, yy, &y, &m, &k));
6123ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
6134396437dSToby Isaac }
6144396437dSToby Isaac 
615d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatSolve_SeqDense_QR(Mat A, Vec xx, Vec yy)
616d71ae5a4SJacob Faibussowitsch {
617e54beecaSStefano Zampini   PetscScalar *y = NULL;
618e54beecaSStefano Zampini   PetscBLASInt m = 0, k = 0;
6194396437dSToby Isaac 
6204396437dSToby Isaac   PetscFunctionBegin;
6219566063dSJacob Faibussowitsch   PetscCall(MatSolve_SeqDense_SetUp(A, xx, yy, &y, &m, &k));
6229566063dSJacob Faibussowitsch   PetscCall(MatSolve_SeqDense_Internal_QR(A, y, PetscMax(m, k), m, 1, k));
6239566063dSJacob Faibussowitsch   PetscCall(MatSolve_SeqDense_TearDown(A, xx, yy, &y, &m, &k));
6243ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
6254396437dSToby Isaac }
6264396437dSToby Isaac 
627d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatSolveTranspose_SeqDense_QR(Mat A, Vec xx, Vec yy)
628d71ae5a4SJacob Faibussowitsch {
62942e9364cSSatish Balay   PetscScalar *y = NULL;
63042e9364cSSatish Balay   PetscBLASInt m = 0, k = 0;
6314396437dSToby Isaac 
6324396437dSToby Isaac   PetscFunctionBegin;
6339566063dSJacob Faibussowitsch   PetscCall(MatSolve_SeqDense_SetUp(A, xx, yy, &y, &m, &k));
6349566063dSJacob Faibussowitsch   PetscCall(MatSolveTranspose_SeqDense_Internal_QR(A, y, PetscMax(m, k), m, 1, k));
6359566063dSJacob Faibussowitsch   PetscCall(MatSolve_SeqDense_TearDown(A, xx, yy, &y, &m, &k));
6363ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
6374396437dSToby Isaac }
6384396437dSToby Isaac 
639d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatMatSolve_SeqDense_SetUp(Mat A, Mat B, Mat X, PetscScalar **_y, PetscBLASInt *_ldy, PetscBLASInt *_m, PetscBLASInt *_nrhs, PetscBLASInt *_k)
640d71ae5a4SJacob Faibussowitsch {
6414905a7bcSToby Isaac   const PetscScalar *b;
6424396437dSToby Isaac   PetscScalar       *y;
643bf5a80bcSToby Isaac   PetscInt           n, _ldb, _ldx;
644bf5a80bcSToby Isaac   PetscBLASInt       nrhs = 0, m = 0, k = 0, ldb = 0, ldx = 0, ldy = 0;
6454905a7bcSToby Isaac 
6464905a7bcSToby Isaac   PetscFunctionBegin;
6479371c9d4SSatish Balay   *_ldy  = 0;
6489371c9d4SSatish Balay   *_m    = 0;
6499371c9d4SSatish Balay   *_nrhs = 0;
6509371c9d4SSatish Balay   *_k    = 0;
6519371c9d4SSatish Balay   *_y    = NULL;
6529566063dSJacob Faibussowitsch   PetscCall(PetscBLASIntCast(A->rmap->n, &m));
6539566063dSJacob Faibussowitsch   PetscCall(PetscBLASIntCast(A->cmap->n, &k));
6549566063dSJacob Faibussowitsch   PetscCall(MatGetSize(B, NULL, &n));
6559566063dSJacob Faibussowitsch   PetscCall(PetscBLASIntCast(n, &nrhs));
6569566063dSJacob Faibussowitsch   PetscCall(MatDenseGetLDA(B, &_ldb));
6579566063dSJacob Faibussowitsch   PetscCall(PetscBLASIntCast(_ldb, &ldb));
6589566063dSJacob Faibussowitsch   PetscCall(MatDenseGetLDA(X, &_ldx));
6599566063dSJacob Faibussowitsch   PetscCall(PetscBLASIntCast(_ldx, &ldx));
660bf5a80bcSToby Isaac   if (ldx < m) {
6619566063dSJacob Faibussowitsch     PetscCall(MatDenseGetArrayRead(B, &b));
6629566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(nrhs * m, &y));
663bf5a80bcSToby Isaac     if (ldb == m) {
6649566063dSJacob Faibussowitsch       PetscCall(PetscArraycpy(y, b, ldb * nrhs));
6654905a7bcSToby Isaac     } else {
66648a46eb9SPierre Jolivet       for (PetscInt j = 0; j < nrhs; j++) PetscCall(PetscArraycpy(&y[j * m], &b[j * ldb], m));
6674905a7bcSToby Isaac     }
668bf5a80bcSToby Isaac     ldy = m;
6699566063dSJacob Faibussowitsch     PetscCall(MatDenseRestoreArrayRead(B, &b));
6704905a7bcSToby Isaac   } else {
671bf5a80bcSToby Isaac     if (ldb == ldx) {
6729566063dSJacob Faibussowitsch       PetscCall(MatCopy(B, X, SAME_NONZERO_PATTERN));
6739566063dSJacob Faibussowitsch       PetscCall(MatDenseGetArray(X, &y));
6744905a7bcSToby Isaac     } else {
6759566063dSJacob Faibussowitsch       PetscCall(MatDenseGetArray(X, &y));
6769566063dSJacob Faibussowitsch       PetscCall(MatDenseGetArrayRead(B, &b));
67748a46eb9SPierre Jolivet       for (PetscInt j = 0; j < nrhs; j++) PetscCall(PetscArraycpy(&y[j * ldx], &b[j * ldb], m));
6789566063dSJacob Faibussowitsch       PetscCall(MatDenseRestoreArrayRead(B, &b));
6794905a7bcSToby Isaac     }
680bf5a80bcSToby Isaac     ldy = ldx;
6814905a7bcSToby Isaac   }
6824396437dSToby Isaac   *_y    = y;
683bf5a80bcSToby Isaac   *_ldy  = ldy;
6844396437dSToby Isaac   *_k    = k;
6854396437dSToby Isaac   *_m    = m;
6864396437dSToby Isaac   *_nrhs = nrhs;
6873ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
6884396437dSToby Isaac }
6894396437dSToby Isaac 
690d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatMatSolve_SeqDense_TearDown(Mat A, Mat B, Mat X, PetscScalar **_y, PetscBLASInt *_ldy, PetscBLASInt *_m, PetscBLASInt *_nrhs, PetscBLASInt *_k)
691d71ae5a4SJacob Faibussowitsch {
6924396437dSToby Isaac   PetscScalar *y;
693bf5a80bcSToby Isaac   PetscInt     _ldx;
694bf5a80bcSToby Isaac   PetscBLASInt k, ldy, nrhs, ldx = 0;
6954396437dSToby Isaac 
6964396437dSToby Isaac   PetscFunctionBegin;
6974396437dSToby Isaac   y    = *_y;
6984396437dSToby Isaac   *_y  = NULL;
6994396437dSToby Isaac   k    = *_k;
700bf5a80bcSToby Isaac   ldy  = *_ldy;
7014396437dSToby Isaac   nrhs = *_nrhs;
7029566063dSJacob Faibussowitsch   PetscCall(MatDenseGetLDA(X, &_ldx));
7039566063dSJacob Faibussowitsch   PetscCall(PetscBLASIntCast(_ldx, &ldx));
704bf5a80bcSToby Isaac   if (ldx != ldy) {
7054905a7bcSToby Isaac     PetscScalar *xv;
7069566063dSJacob Faibussowitsch     PetscCall(MatDenseGetArray(X, &xv));
70748a46eb9SPierre Jolivet     for (PetscInt j = 0; j < nrhs; j++) PetscCall(PetscArraycpy(&xv[j * ldx], &y[j * ldy], k));
7089566063dSJacob Faibussowitsch     PetscCall(MatDenseRestoreArray(X, &xv));
7099566063dSJacob Faibussowitsch     PetscCall(PetscFree(y));
7104905a7bcSToby Isaac   } else {
7119566063dSJacob Faibussowitsch     PetscCall(MatDenseRestoreArray(X, &y));
7124905a7bcSToby Isaac   }
7133ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
71485e2c93fSHong Zhang }
71585e2c93fSHong Zhang 
716d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatMatSolve_SeqDense_LU(Mat A, Mat B, Mat X)
717d71ae5a4SJacob Faibussowitsch {
7184396437dSToby Isaac   PetscScalar *y;
719bf5a80bcSToby Isaac   PetscBLASInt m, k, ldy, nrhs;
7204396437dSToby Isaac 
7214396437dSToby Isaac   PetscFunctionBegin;
7229566063dSJacob Faibussowitsch   PetscCall(MatMatSolve_SeqDense_SetUp(A, B, X, &y, &ldy, &m, &nrhs, &k));
7239566063dSJacob Faibussowitsch   PetscCall(MatSolve_SeqDense_Internal_LU(A, y, ldy, m, nrhs, k, PETSC_FALSE));
7249566063dSJacob Faibussowitsch   PetscCall(MatMatSolve_SeqDense_TearDown(A, B, X, &y, &ldy, &m, &nrhs, &k));
7253ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
7264396437dSToby Isaac }
7274396437dSToby Isaac 
728d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatMatSolveTranspose_SeqDense_LU(Mat A, Mat B, Mat X)
729d71ae5a4SJacob Faibussowitsch {
7304396437dSToby Isaac   PetscScalar *y;
731bf5a80bcSToby Isaac   PetscBLASInt m, k, ldy, nrhs;
7324396437dSToby Isaac 
7334396437dSToby Isaac   PetscFunctionBegin;
7349566063dSJacob Faibussowitsch   PetscCall(MatMatSolve_SeqDense_SetUp(A, B, X, &y, &ldy, &m, &nrhs, &k));
7359566063dSJacob Faibussowitsch   PetscCall(MatSolve_SeqDense_Internal_LU(A, y, ldy, m, nrhs, k, PETSC_TRUE));
7369566063dSJacob Faibussowitsch   PetscCall(MatMatSolve_SeqDense_TearDown(A, B, X, &y, &ldy, &m, &nrhs, &k));
7373ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
7384396437dSToby Isaac }
7394396437dSToby Isaac 
740d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatMatSolve_SeqDense_Cholesky(Mat A, Mat B, Mat X)
741d71ae5a4SJacob Faibussowitsch {
7424396437dSToby Isaac   PetscScalar *y;
743bf5a80bcSToby Isaac   PetscBLASInt m, k, ldy, nrhs;
7444396437dSToby Isaac 
7454396437dSToby Isaac   PetscFunctionBegin;
7469566063dSJacob Faibussowitsch   PetscCall(MatMatSolve_SeqDense_SetUp(A, B, X, &y, &ldy, &m, &nrhs, &k));
7479566063dSJacob Faibussowitsch   PetscCall(MatSolve_SeqDense_Internal_Cholesky(A, y, ldy, m, nrhs, k, PETSC_FALSE));
7489566063dSJacob Faibussowitsch   PetscCall(MatMatSolve_SeqDense_TearDown(A, B, X, &y, &ldy, &m, &nrhs, &k));
7493ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
7504396437dSToby Isaac }
7514396437dSToby Isaac 
752d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatMatSolveTranspose_SeqDense_Cholesky(Mat A, Mat B, Mat X)
753d71ae5a4SJacob Faibussowitsch {
7544396437dSToby Isaac   PetscScalar *y;
755bf5a80bcSToby Isaac   PetscBLASInt m, k, ldy, nrhs;
7564396437dSToby Isaac 
7574396437dSToby Isaac   PetscFunctionBegin;
7589566063dSJacob Faibussowitsch   PetscCall(MatMatSolve_SeqDense_SetUp(A, B, X, &y, &ldy, &m, &nrhs, &k));
7599566063dSJacob Faibussowitsch   PetscCall(MatSolve_SeqDense_Internal_Cholesky(A, y, ldy, m, nrhs, k, PETSC_TRUE));
7609566063dSJacob Faibussowitsch   PetscCall(MatMatSolve_SeqDense_TearDown(A, B, X, &y, &ldy, &m, &nrhs, &k));
7613ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
7624396437dSToby Isaac }
7634396437dSToby Isaac 
764d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatMatSolve_SeqDense_QR(Mat A, Mat B, Mat X)
765d71ae5a4SJacob Faibussowitsch {
7664396437dSToby Isaac   PetscScalar *y;
767bf5a80bcSToby Isaac   PetscBLASInt m, k, ldy, nrhs;
7684396437dSToby Isaac 
7694396437dSToby Isaac   PetscFunctionBegin;
7709566063dSJacob Faibussowitsch   PetscCall(MatMatSolve_SeqDense_SetUp(A, B, X, &y, &ldy, &m, &nrhs, &k));
7719566063dSJacob Faibussowitsch   PetscCall(MatSolve_SeqDense_Internal_QR(A, y, ldy, m, nrhs, k));
7729566063dSJacob Faibussowitsch   PetscCall(MatMatSolve_SeqDense_TearDown(A, B, X, &y, &ldy, &m, &nrhs, &k));
7733ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
7744396437dSToby Isaac }
7754396437dSToby Isaac 
776d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatMatSolveTranspose_SeqDense_QR(Mat A, Mat B, Mat X)
777d71ae5a4SJacob Faibussowitsch {
7784396437dSToby Isaac   PetscScalar *y;
779bf5a80bcSToby Isaac   PetscBLASInt m, k, ldy, nrhs;
7804396437dSToby Isaac 
7814396437dSToby Isaac   PetscFunctionBegin;
7829566063dSJacob Faibussowitsch   PetscCall(MatMatSolve_SeqDense_SetUp(A, B, X, &y, &ldy, &m, &nrhs, &k));
7839566063dSJacob Faibussowitsch   PetscCall(MatSolveTranspose_SeqDense_Internal_QR(A, y, ldy, m, nrhs, k));
7849566063dSJacob Faibussowitsch   PetscCall(MatMatSolve_SeqDense_TearDown(A, B, X, &y, &ldy, &m, &nrhs, &k));
7853ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
7864396437dSToby Isaac }
7874396437dSToby Isaac 
788db4efbfdSBarry Smith /* COMMENT: I have chosen to hide row permutation in the pivots,
789db4efbfdSBarry Smith    rather than put it in the Mat->row slot.*/
790d71ae5a4SJacob Faibussowitsch PetscErrorCode MatLUFactor_SeqDense(Mat A, IS row, IS col, const MatFactorInfo *minfo)
791d71ae5a4SJacob Faibussowitsch {
792db4efbfdSBarry Smith   Mat_SeqDense *mat = (Mat_SeqDense *)A->data;
793db4efbfdSBarry Smith   PetscBLASInt  n, m, info;
794db4efbfdSBarry Smith 
795db4efbfdSBarry Smith   PetscFunctionBegin;
7969566063dSJacob Faibussowitsch   PetscCall(PetscBLASIntCast(A->cmap->n, &n));
7979566063dSJacob Faibussowitsch   PetscCall(PetscBLASIntCast(A->rmap->n, &m));
7984dfa11a4SJacob Faibussowitsch   if (!mat->pivots) { PetscCall(PetscMalloc1(A->rmap->n, &mat->pivots)); }
7993ba16761SJacob Faibussowitsch   if (!A->rmap->n || !A->cmap->n) PetscFunctionReturn(PETSC_SUCCESS);
8009566063dSJacob Faibussowitsch   PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF));
801792fecdfSBarry Smith   PetscCallBLAS("LAPACKgetrf", LAPACKgetrf_(&m, &n, mat->v, &mat->lda, mat->pivots, &info));
8029566063dSJacob Faibussowitsch   PetscCall(PetscFPTrapPop());
8038e57ea43SSatish Balay 
80405fcb23eSStefano Zampini   PetscCheck(info >= 0, PETSC_COMM_SELF, PETSC_ERR_LIB, "Bad argument to LU factorization %d", (int)info);
80505fcb23eSStefano Zampini   PetscCheck(info <= 0, PETSC_COMM_SELF, PETSC_ERR_MAT_LU_ZRPVT, "Bad LU factorization %d", (int)info);
8068208b9aeSStefano Zampini 
8074396437dSToby Isaac   A->ops->solve             = MatSolve_SeqDense_LU;
8084396437dSToby Isaac   A->ops->matsolve          = MatMatSolve_SeqDense_LU;
8094396437dSToby Isaac   A->ops->solvetranspose    = MatSolveTranspose_SeqDense_LU;
8104396437dSToby Isaac   A->ops->matsolvetranspose = MatMatSolveTranspose_SeqDense_LU;
811d5f3da31SBarry Smith   A->factortype             = MAT_FACTOR_LU;
812db4efbfdSBarry Smith 
8139566063dSJacob Faibussowitsch   PetscCall(PetscFree(A->solvertype));
8149566063dSJacob Faibussowitsch   PetscCall(PetscStrallocpy(MATSOLVERPETSC, &A->solvertype));
815f6224b95SHong Zhang 
8169566063dSJacob Faibussowitsch   PetscCall(PetscLogFlops((2.0 * A->cmap->n * A->cmap->n * A->cmap->n) / 3));
8173ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
818db4efbfdSBarry Smith }
819db4efbfdSBarry Smith 
820d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatLUFactorNumeric_SeqDense(Mat fact, Mat A, const MatFactorInfo *info_dummy)
821d71ae5a4SJacob Faibussowitsch {
8224396437dSToby Isaac   MatFactorInfo info;
8234396437dSToby Isaac 
8244396437dSToby Isaac   PetscFunctionBegin;
8259566063dSJacob Faibussowitsch   PetscCall(MatDuplicateNoCreate_SeqDense(fact, A, MAT_COPY_VALUES));
826dbbe0bcdSBarry Smith   PetscUseTypeMethod(fact, lufactor, NULL, NULL, &info);
8273ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
8284396437dSToby Isaac }
8294396437dSToby Isaac 
830d71ae5a4SJacob Faibussowitsch PetscErrorCode MatLUFactorSymbolic_SeqDense(Mat fact, Mat A, IS row, IS col, const MatFactorInfo *info)
831d71ae5a4SJacob Faibussowitsch {
8324396437dSToby Isaac   PetscFunctionBegin;
8334396437dSToby Isaac   fact->preallocated         = PETSC_TRUE;
8344396437dSToby Isaac   fact->assembled            = PETSC_TRUE;
8354396437dSToby Isaac   fact->ops->lufactornumeric = MatLUFactorNumeric_SeqDense;
8363ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
8374396437dSToby Isaac }
8384396437dSToby Isaac 
839a49dc2a2SStefano Zampini /* Cholesky as L*L^T or L*D*L^T and the symmetric/hermitian complex variants */
840d71ae5a4SJacob Faibussowitsch PetscErrorCode MatCholeskyFactor_SeqDense(Mat A, IS perm, const MatFactorInfo *factinfo)
841d71ae5a4SJacob Faibussowitsch {
842db4efbfdSBarry Smith   Mat_SeqDense *mat = (Mat_SeqDense *)A->data;
843c5df96a5SBarry Smith   PetscBLASInt  info, n;
844db4efbfdSBarry Smith 
845db4efbfdSBarry Smith   PetscFunctionBegin;
8469566063dSJacob Faibussowitsch   PetscCall(PetscBLASIntCast(A->cmap->n, &n));
8473ba16761SJacob Faibussowitsch   if (!A->rmap->n || !A->cmap->n) PetscFunctionReturn(PETSC_SUCCESS);
848b94d7dedSBarry Smith   if (A->spd == PETSC_BOOL3_TRUE) {
8499566063dSJacob Faibussowitsch     PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF));
850792fecdfSBarry Smith     PetscCallBLAS("LAPACKpotrf", LAPACKpotrf_("L", &n, mat->v, &mat->lda, &info));
8519566063dSJacob Faibussowitsch     PetscCall(PetscFPTrapPop());
852a49dc2a2SStefano Zampini #if defined(PETSC_USE_COMPLEX)
853b94d7dedSBarry Smith   } else if (A->hermitian == PETSC_BOOL3_TRUE) {
8544dfa11a4SJacob Faibussowitsch     if (!mat->pivots) { PetscCall(PetscMalloc1(A->rmap->n, &mat->pivots)); }
855a49dc2a2SStefano Zampini     if (!mat->fwork) {
856a49dc2a2SStefano Zampini       PetscScalar dummy;
857a49dc2a2SStefano Zampini 
858a49dc2a2SStefano Zampini       mat->lfwork = -1;
8599566063dSJacob Faibussowitsch       PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF));
860792fecdfSBarry Smith       PetscCallBLAS("LAPACKhetrf", LAPACKhetrf_("L", &n, mat->v, &mat->lda, mat->pivots, &dummy, &mat->lfwork, &info));
8619566063dSJacob Faibussowitsch       PetscCall(PetscFPTrapPop());
862a49dc2a2SStefano Zampini       mat->lfwork = (PetscInt)PetscRealPart(dummy);
8639566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(mat->lfwork, &mat->fwork));
864a49dc2a2SStefano Zampini     }
8659566063dSJacob Faibussowitsch     PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF));
866792fecdfSBarry Smith     PetscCallBLAS("LAPACKhetrf", LAPACKhetrf_("L", &n, mat->v, &mat->lda, mat->pivots, mat->fwork, &mat->lfwork, &info));
8679566063dSJacob Faibussowitsch     PetscCall(PetscFPTrapPop());
868a49dc2a2SStefano Zampini #endif
869a49dc2a2SStefano Zampini   } else { /* symmetric case */
8704dfa11a4SJacob Faibussowitsch     if (!mat->pivots) { PetscCall(PetscMalloc1(A->rmap->n, &mat->pivots)); }
871a49dc2a2SStefano Zampini     if (!mat->fwork) {
872a49dc2a2SStefano Zampini       PetscScalar dummy;
873a49dc2a2SStefano Zampini 
874a49dc2a2SStefano Zampini       mat->lfwork = -1;
8759566063dSJacob Faibussowitsch       PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF));
876792fecdfSBarry Smith       PetscCallBLAS("LAPACKsytrf", LAPACKsytrf_("L", &n, mat->v, &mat->lda, mat->pivots, &dummy, &mat->lfwork, &info));
8779566063dSJacob Faibussowitsch       PetscCall(PetscFPTrapPop());
878a49dc2a2SStefano Zampini       mat->lfwork = (PetscInt)PetscRealPart(dummy);
8799566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(mat->lfwork, &mat->fwork));
880a49dc2a2SStefano Zampini     }
8819566063dSJacob Faibussowitsch     PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF));
882792fecdfSBarry Smith     PetscCallBLAS("LAPACKsytrf", LAPACKsytrf_("L", &n, mat->v, &mat->lda, mat->pivots, mat->fwork, &mat->lfwork, &info));
8839566063dSJacob Faibussowitsch     PetscCall(PetscFPTrapPop());
884a49dc2a2SStefano Zampini   }
88528b400f6SJacob Faibussowitsch   PetscCheck(!info, PETSC_COMM_SELF, PETSC_ERR_MAT_CH_ZRPVT, "Bad factorization: zero pivot in row %" PetscInt_FMT, (PetscInt)info - 1);
8868208b9aeSStefano Zampini 
8874396437dSToby Isaac   A->ops->solve             = MatSolve_SeqDense_Cholesky;
8884396437dSToby Isaac   A->ops->matsolve          = MatMatSolve_SeqDense_Cholesky;
8894396437dSToby Isaac   A->ops->solvetranspose    = MatSolveTranspose_SeqDense_Cholesky;
8904396437dSToby Isaac   A->ops->matsolvetranspose = MatMatSolveTranspose_SeqDense_Cholesky;
891d5f3da31SBarry Smith   A->factortype             = MAT_FACTOR_CHOLESKY;
8922205254eSKarl Rupp 
8939566063dSJacob Faibussowitsch   PetscCall(PetscFree(A->solvertype));
8949566063dSJacob Faibussowitsch   PetscCall(PetscStrallocpy(MATSOLVERPETSC, &A->solvertype));
895f6224b95SHong Zhang 
8969566063dSJacob Faibussowitsch   PetscCall(PetscLogFlops((1.0 * A->cmap->n * A->cmap->n * A->cmap->n) / 3.0));
8973ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
898db4efbfdSBarry Smith }
899db4efbfdSBarry Smith 
900d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatCholeskyFactorNumeric_SeqDense(Mat fact, Mat A, const MatFactorInfo *info_dummy)
901d71ae5a4SJacob Faibussowitsch {
902db4efbfdSBarry Smith   MatFactorInfo info;
903db4efbfdSBarry Smith 
904db4efbfdSBarry Smith   PetscFunctionBegin;
905db4efbfdSBarry Smith   info.fill = 1.0;
9062205254eSKarl Rupp 
9079566063dSJacob Faibussowitsch   PetscCall(MatDuplicateNoCreate_SeqDense(fact, A, MAT_COPY_VALUES));
908dbbe0bcdSBarry Smith   PetscUseTypeMethod(fact, choleskyfactor, NULL, &info);
9093ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
910db4efbfdSBarry Smith }
911db4efbfdSBarry Smith 
912d71ae5a4SJacob Faibussowitsch PetscErrorCode MatCholeskyFactorSymbolic_SeqDense(Mat fact, Mat A, IS row, const MatFactorInfo *info)
913d71ae5a4SJacob Faibussowitsch {
914db4efbfdSBarry Smith   PetscFunctionBegin;
915c3ef05f6SHong Zhang   fact->assembled                  = PETSC_TRUE;
9161bbcc794SSatish Balay   fact->preallocated               = PETSC_TRUE;
917719d5645SBarry Smith   fact->ops->choleskyfactornumeric = MatCholeskyFactorNumeric_SeqDense;
9183ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
919db4efbfdSBarry Smith }
920db4efbfdSBarry Smith 
921d71ae5a4SJacob Faibussowitsch PetscErrorCode MatQRFactor_SeqDense(Mat A, IS col, const MatFactorInfo *minfo)
922d71ae5a4SJacob Faibussowitsch {
9234905a7bcSToby Isaac   Mat_SeqDense *mat = (Mat_SeqDense *)A->data;
9244905a7bcSToby Isaac   PetscBLASInt  n, m, info, min, max;
9254905a7bcSToby Isaac 
9264905a7bcSToby Isaac   PetscFunctionBegin;
9279566063dSJacob Faibussowitsch   PetscCall(PetscBLASIntCast(A->cmap->n, &n));
9289566063dSJacob Faibussowitsch   PetscCall(PetscBLASIntCast(A->rmap->n, &m));
9294396437dSToby Isaac   max = PetscMax(m, n);
9304396437dSToby Isaac   min = PetscMin(m, n);
9314dfa11a4SJacob Faibussowitsch   if (!mat->tau) { PetscCall(PetscMalloc1(min, &mat->tau)); }
9324dfa11a4SJacob Faibussowitsch   if (!mat->pivots) { PetscCall(PetscMalloc1(n, &mat->pivots)); }
93348a46eb9SPierre Jolivet   if (!mat->qrrhs) PetscCall(MatCreateVecs(A, NULL, &(mat->qrrhs)));
9343ba16761SJacob Faibussowitsch   if (!A->rmap->n || !A->cmap->n) PetscFunctionReturn(PETSC_SUCCESS);
9354905a7bcSToby Isaac   if (!mat->fwork) {
9364905a7bcSToby Isaac     PetscScalar dummy;
9374905a7bcSToby Isaac 
9384905a7bcSToby Isaac     mat->lfwork = -1;
9399566063dSJacob Faibussowitsch     PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF));
940792fecdfSBarry Smith     PetscCallBLAS("LAPACKgeqrf", LAPACKgeqrf_(&m, &n, mat->v, &mat->lda, mat->tau, &dummy, &mat->lfwork, &info));
9419566063dSJacob Faibussowitsch     PetscCall(PetscFPTrapPop());
9424905a7bcSToby Isaac     mat->lfwork = (PetscInt)PetscRealPart(dummy);
9439566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(mat->lfwork, &mat->fwork));
9444905a7bcSToby Isaac   }
9459566063dSJacob Faibussowitsch   PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF));
946792fecdfSBarry Smith   PetscCallBLAS("LAPACKgeqrf", LAPACKgeqrf_(&m, &n, mat->v, &mat->lda, mat->tau, mat->fwork, &mat->lfwork, &info));
9479566063dSJacob Faibussowitsch   PetscCall(PetscFPTrapPop());
94805fcb23eSStefano Zampini   PetscCheck(!info, PETSC_COMM_SELF, PETSC_ERR_LIB, "Bad argument to QR factorization %d", (int)info);
9494905a7bcSToby Isaac   // TODO: try to estimate rank or test for and use geqp3 for rank revealing QR.  For now just say rank is min of m and n
9504905a7bcSToby Isaac   mat->rank = min;
9514905a7bcSToby Isaac 
9524396437dSToby Isaac   A->ops->solve    = MatSolve_SeqDense_QR;
9534396437dSToby Isaac   A->ops->matsolve = MatMatSolve_SeqDense_QR;
9544905a7bcSToby Isaac   A->factortype    = MAT_FACTOR_QR;
9554905a7bcSToby Isaac   if (m == n) {
9564396437dSToby Isaac     A->ops->solvetranspose    = MatSolveTranspose_SeqDense_QR;
9574396437dSToby Isaac     A->ops->matsolvetranspose = MatMatSolveTranspose_SeqDense_QR;
9584905a7bcSToby Isaac   }
9594905a7bcSToby Isaac 
9609566063dSJacob Faibussowitsch   PetscCall(PetscFree(A->solvertype));
9619566063dSJacob Faibussowitsch   PetscCall(PetscStrallocpy(MATSOLVERPETSC, &A->solvertype));
9624905a7bcSToby Isaac 
9639566063dSJacob Faibussowitsch   PetscCall(PetscLogFlops(2.0 * min * min * (max - min / 3.0)));
9643ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
9654905a7bcSToby Isaac }
9664905a7bcSToby Isaac 
967d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatQRFactorNumeric_SeqDense(Mat fact, Mat A, const MatFactorInfo *info_dummy)
968d71ae5a4SJacob Faibussowitsch {
9694905a7bcSToby Isaac   MatFactorInfo info;
9704905a7bcSToby Isaac 
9714905a7bcSToby Isaac   PetscFunctionBegin;
9724905a7bcSToby Isaac   info.fill = 1.0;
9734905a7bcSToby Isaac 
9749566063dSJacob Faibussowitsch   PetscCall(MatDuplicateNoCreate_SeqDense(fact, A, MAT_COPY_VALUES));
975cac4c232SBarry Smith   PetscUseMethod(fact, "MatQRFactor_C", (Mat, IS, const MatFactorInfo *), (fact, NULL, &info));
9763ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
9774905a7bcSToby Isaac }
9784905a7bcSToby Isaac 
979d71ae5a4SJacob Faibussowitsch PetscErrorCode MatQRFactorSymbolic_SeqDense(Mat fact, Mat A, IS row, const MatFactorInfo *info)
980d71ae5a4SJacob Faibussowitsch {
9814905a7bcSToby Isaac   PetscFunctionBegin;
9824905a7bcSToby Isaac   fact->assembled    = PETSC_TRUE;
9834905a7bcSToby Isaac   fact->preallocated = PETSC_TRUE;
9849566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)fact, "MatQRFactorNumeric_C", MatQRFactorNumeric_SeqDense));
9853ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
9864905a7bcSToby Isaac }
9874905a7bcSToby Isaac 
988ca15aa20SStefano Zampini /* uses LAPACK */
989d71ae5a4SJacob Faibussowitsch PETSC_INTERN PetscErrorCode MatGetFactor_seqdense_petsc(Mat A, MatFactorType ftype, Mat *fact)
990d71ae5a4SJacob Faibussowitsch {
991db4efbfdSBarry Smith   PetscFunctionBegin;
9929566063dSJacob Faibussowitsch   PetscCall(MatCreate(PetscObjectComm((PetscObject)A), fact));
9939566063dSJacob Faibussowitsch   PetscCall(MatSetSizes(*fact, A->rmap->n, A->cmap->n, A->rmap->n, A->cmap->n));
9949566063dSJacob Faibussowitsch   PetscCall(MatSetType(*fact, MATDENSE));
99566e17bc3SBarry Smith   (*fact)->trivialsymbolic = PETSC_TRUE;
9962a350339SBarry Smith   if (ftype == MAT_FACTOR_LU || ftype == MAT_FACTOR_ILU) {
997db4efbfdSBarry Smith     (*fact)->ops->lufactorsymbolic  = MatLUFactorSymbolic_SeqDense;
9982a350339SBarry Smith     (*fact)->ops->ilufactorsymbolic = MatLUFactorSymbolic_SeqDense;
999bf5a80bcSToby Isaac   } else if (ftype == MAT_FACTOR_CHOLESKY || ftype == MAT_FACTOR_ICC) {
1000db4efbfdSBarry Smith     (*fact)->ops->choleskyfactorsymbolic = MatCholeskyFactorSymbolic_SeqDense;
1001bf5a80bcSToby Isaac   } else if (ftype == MAT_FACTOR_QR) {
10029566063dSJacob Faibussowitsch     PetscCall(PetscObjectComposeFunction((PetscObject)(*fact), "MatQRFactorSymbolic_C", MatQRFactorSymbolic_SeqDense));
1003db4efbfdSBarry Smith   }
1004d5f3da31SBarry Smith   (*fact)->factortype = ftype;
100500c67f3bSHong Zhang 
10069566063dSJacob Faibussowitsch   PetscCall(PetscFree((*fact)->solvertype));
10079566063dSJacob Faibussowitsch   PetscCall(PetscStrallocpy(MATSOLVERPETSC, &(*fact)->solvertype));
10089566063dSJacob Faibussowitsch   PetscCall(PetscStrallocpy(MATORDERINGEXTERNAL, (char **)&(*fact)->preferredordering[MAT_FACTOR_LU]));
10099566063dSJacob Faibussowitsch   PetscCall(PetscStrallocpy(MATORDERINGEXTERNAL, (char **)&(*fact)->preferredordering[MAT_FACTOR_ILU]));
10109566063dSJacob Faibussowitsch   PetscCall(PetscStrallocpy(MATORDERINGEXTERNAL, (char **)&(*fact)->preferredordering[MAT_FACTOR_CHOLESKY]));
10119566063dSJacob Faibussowitsch   PetscCall(PetscStrallocpy(MATORDERINGEXTERNAL, (char **)&(*fact)->preferredordering[MAT_FACTOR_ICC]));
10123ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1013db4efbfdSBarry Smith }
1014db4efbfdSBarry Smith 
1015d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatSOR_SeqDense(Mat A, Vec bb, PetscReal omega, MatSORType flag, PetscReal shift, PetscInt its, PetscInt lits, Vec xx)
1016d71ae5a4SJacob Faibussowitsch {
1017c0bbcb79SLois Curfman McInnes   Mat_SeqDense      *mat = (Mat_SeqDense *)A->data;
1018d9ca1df4SBarry Smith   PetscScalar       *x, *v = mat->v, zero = 0.0, xt;
1019d9ca1df4SBarry Smith   const PetscScalar *b;
1020d0f46423SBarry Smith   PetscInt           m = A->rmap->n, i;
102123fff9afSBarry Smith   PetscBLASInt       o = 1, bm = 0;
1022289bc588SBarry Smith 
10233a40ed3dSBarry Smith   PetscFunctionBegin;
102447d993e7Ssuyashtn #if defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
102508401ef6SPierre Jolivet   PetscCheck(A->offloadmask != PETSC_OFFLOAD_GPU, PETSC_COMM_SELF, PETSC_ERR_SUP, "Not implemented");
1026ca15aa20SStefano Zampini #endif
1027422a814eSBarry Smith   if (shift == -1) shift = 0.0; /* negative shift indicates do not error on zero diagonal; this code never zeros on zero diagonal */
10289566063dSJacob Faibussowitsch   PetscCall(PetscBLASIntCast(m, &bm));
1029289bc588SBarry Smith   if (flag & SOR_ZERO_INITIAL_GUESS) {
10303bffc371SBarry Smith     /* this is a hack fix, should have another version without the second BLASdotu */
10319566063dSJacob Faibussowitsch     PetscCall(VecSet(xx, zero));
1032289bc588SBarry Smith   }
10339566063dSJacob Faibussowitsch   PetscCall(VecGetArray(xx, &x));
10349566063dSJacob Faibussowitsch   PetscCall(VecGetArrayRead(bb, &b));
1035b965ef7fSBarry Smith   its = its * lits;
103608401ef6SPierre Jolivet   PetscCheck(its > 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Relaxation requires global its %" PetscInt_FMT " and local its %" PetscInt_FMT " both positive", its, lits);
1037289bc588SBarry Smith   while (its--) {
1038fccaa45eSBarry Smith     if (flag & SOR_FORWARD_SWEEP || flag & SOR_LOCAL_FORWARD_SWEEP) {
1039289bc588SBarry Smith       for (i = 0; i < m; i++) {
1040792fecdfSBarry Smith         PetscCallBLAS("BLASdotu", xt = b[i] - BLASdotu_(&bm, v + i, &bm, x, &o));
104155a1b374SBarry Smith         x[i] = (1. - omega) * x[i] + omega * (xt + v[i + i * m] * x[i]) / (v[i + i * m] + shift);
1042289bc588SBarry Smith       }
1043289bc588SBarry Smith     }
1044fccaa45eSBarry Smith     if (flag & SOR_BACKWARD_SWEEP || flag & SOR_LOCAL_BACKWARD_SWEEP) {
1045289bc588SBarry Smith       for (i = m - 1; i >= 0; i--) {
1046792fecdfSBarry Smith         PetscCallBLAS("BLASdotu", xt = b[i] - BLASdotu_(&bm, v + i, &bm, x, &o));
104755a1b374SBarry Smith         x[i] = (1. - omega) * x[i] + omega * (xt + v[i + i * m] * x[i]) / (v[i + i * m] + shift);
1048289bc588SBarry Smith       }
1049289bc588SBarry Smith     }
1050289bc588SBarry Smith   }
10519566063dSJacob Faibussowitsch   PetscCall(VecRestoreArrayRead(bb, &b));
10529566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(xx, &x));
10533ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1054289bc588SBarry Smith }
1055289bc588SBarry Smith 
1056d71ae5a4SJacob Faibussowitsch PetscErrorCode MatMultTranspose_SeqDense(Mat A, Vec xx, Vec yy)
1057d71ae5a4SJacob Faibussowitsch {
1058c0bbcb79SLois Curfman McInnes   Mat_SeqDense      *mat = (Mat_SeqDense *)A->data;
1059d9ca1df4SBarry Smith   const PetscScalar *v   = mat->v, *x;
1060d9ca1df4SBarry Smith   PetscScalar       *y;
10610805154bSBarry Smith   PetscBLASInt       m, n, _One = 1;
1062ea709b57SSatish Balay   PetscScalar        _DOne = 1.0, _DZero = 0.0;
10633a40ed3dSBarry Smith 
10643a40ed3dSBarry Smith   PetscFunctionBegin;
10659566063dSJacob Faibussowitsch   PetscCall(PetscBLASIntCast(A->rmap->n, &m));
10669566063dSJacob Faibussowitsch   PetscCall(PetscBLASIntCast(A->cmap->n, &n));
10679566063dSJacob Faibussowitsch   PetscCall(VecGetArrayRead(xx, &x));
10689566063dSJacob Faibussowitsch   PetscCall(VecGetArrayWrite(yy, &y));
10695ac36cfcSBarry Smith   if (!A->rmap->n || !A->cmap->n) {
10705ac36cfcSBarry Smith     PetscBLASInt i;
10715ac36cfcSBarry Smith     for (i = 0; i < n; i++) y[i] = 0.0;
10725ac36cfcSBarry Smith   } else {
1073792fecdfSBarry Smith     PetscCallBLAS("BLASgemv", BLASgemv_("T", &m, &n, &_DOne, v, &mat->lda, x, &_One, &_DZero, y, &_One));
10749566063dSJacob Faibussowitsch     PetscCall(PetscLogFlops(2.0 * A->rmap->n * A->cmap->n - A->cmap->n));
10755ac36cfcSBarry Smith   }
10769566063dSJacob Faibussowitsch   PetscCall(VecRestoreArrayRead(xx, &x));
10779566063dSJacob Faibussowitsch   PetscCall(VecRestoreArrayWrite(yy, &y));
10783ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1079289bc588SBarry Smith }
1080800995b7SMatthew Knepley 
1081d71ae5a4SJacob Faibussowitsch PetscErrorCode MatMult_SeqDense(Mat A, Vec xx, Vec yy)
1082d71ae5a4SJacob Faibussowitsch {
1083c0bbcb79SLois Curfman McInnes   Mat_SeqDense      *mat = (Mat_SeqDense *)A->data;
1084d9ca1df4SBarry Smith   PetscScalar       *y, _DOne = 1.0, _DZero = 0.0;
10850805154bSBarry Smith   PetscBLASInt       m, n, _One             = 1;
1086d9ca1df4SBarry Smith   const PetscScalar *v = mat->v, *x;
10873a40ed3dSBarry Smith 
10883a40ed3dSBarry Smith   PetscFunctionBegin;
10899566063dSJacob Faibussowitsch   PetscCall(PetscBLASIntCast(A->rmap->n, &m));
10909566063dSJacob Faibussowitsch   PetscCall(PetscBLASIntCast(A->cmap->n, &n));
10919566063dSJacob Faibussowitsch   PetscCall(VecGetArrayRead(xx, &x));
10929566063dSJacob Faibussowitsch   PetscCall(VecGetArrayWrite(yy, &y));
10935ac36cfcSBarry Smith   if (!A->rmap->n || !A->cmap->n) {
10945ac36cfcSBarry Smith     PetscBLASInt i;
10955ac36cfcSBarry Smith     for (i = 0; i < m; i++) y[i] = 0.0;
10965ac36cfcSBarry Smith   } else {
1097792fecdfSBarry Smith     PetscCallBLAS("BLASgemv", BLASgemv_("N", &m, &n, &_DOne, v, &(mat->lda), x, &_One, &_DZero, y, &_One));
10989566063dSJacob Faibussowitsch     PetscCall(PetscLogFlops(2.0 * A->rmap->n * A->cmap->n - A->rmap->n));
10995ac36cfcSBarry Smith   }
11009566063dSJacob Faibussowitsch   PetscCall(VecRestoreArrayRead(xx, &x));
11019566063dSJacob Faibussowitsch   PetscCall(VecRestoreArrayWrite(yy, &y));
11023ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1103289bc588SBarry Smith }
11046ee01492SSatish Balay 
1105d71ae5a4SJacob Faibussowitsch PetscErrorCode MatMultAdd_SeqDense(Mat A, Vec xx, Vec zz, Vec yy)
1106d71ae5a4SJacob Faibussowitsch {
1107c0bbcb79SLois Curfman McInnes   Mat_SeqDense      *mat = (Mat_SeqDense *)A->data;
1108d9ca1df4SBarry Smith   const PetscScalar *v   = mat->v, *x;
1109d9ca1df4SBarry Smith   PetscScalar       *y, _DOne = 1.0;
11100805154bSBarry Smith   PetscBLASInt       m, n, _One = 1;
11113a40ed3dSBarry Smith 
11123a40ed3dSBarry Smith   PetscFunctionBegin;
11139566063dSJacob Faibussowitsch   PetscCall(PetscBLASIntCast(A->rmap->n, &m));
11149566063dSJacob Faibussowitsch   PetscCall(PetscBLASIntCast(A->cmap->n, &n));
11159566063dSJacob Faibussowitsch   PetscCall(VecCopy(zz, yy));
11163ba16761SJacob Faibussowitsch   if (!A->rmap->n || !A->cmap->n) PetscFunctionReturn(PETSC_SUCCESS);
11179566063dSJacob Faibussowitsch   PetscCall(VecGetArrayRead(xx, &x));
11189566063dSJacob Faibussowitsch   PetscCall(VecGetArray(yy, &y));
1119792fecdfSBarry Smith   PetscCallBLAS("BLASgemv", BLASgemv_("N", &m, &n, &_DOne, v, &(mat->lda), x, &_One, &_DOne, y, &_One));
11209566063dSJacob Faibussowitsch   PetscCall(VecRestoreArrayRead(xx, &x));
11219566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(yy, &y));
11229566063dSJacob Faibussowitsch   PetscCall(PetscLogFlops(2.0 * A->rmap->n * A->cmap->n));
11233ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1124289bc588SBarry Smith }
11256ee01492SSatish Balay 
1126d71ae5a4SJacob Faibussowitsch PetscErrorCode MatMultTransposeAdd_SeqDense(Mat A, Vec xx, Vec zz, Vec yy)
1127d71ae5a4SJacob Faibussowitsch {
1128c0bbcb79SLois Curfman McInnes   Mat_SeqDense      *mat = (Mat_SeqDense *)A->data;
1129d9ca1df4SBarry Smith   const PetscScalar *v   = mat->v, *x;
1130d9ca1df4SBarry Smith   PetscScalar       *y;
11310805154bSBarry Smith   PetscBLASInt       m, n, _One = 1;
113287828ca2SBarry Smith   PetscScalar        _DOne = 1.0;
11333a40ed3dSBarry Smith 
11343a40ed3dSBarry Smith   PetscFunctionBegin;
11359566063dSJacob Faibussowitsch   PetscCall(PetscBLASIntCast(A->rmap->n, &m));
11369566063dSJacob Faibussowitsch   PetscCall(PetscBLASIntCast(A->cmap->n, &n));
11379566063dSJacob Faibussowitsch   PetscCall(VecCopy(zz, yy));
11383ba16761SJacob Faibussowitsch   if (!A->rmap->n || !A->cmap->n) PetscFunctionReturn(PETSC_SUCCESS);
11399566063dSJacob Faibussowitsch   PetscCall(VecGetArrayRead(xx, &x));
11409566063dSJacob Faibussowitsch   PetscCall(VecGetArray(yy, &y));
1141792fecdfSBarry Smith   PetscCallBLAS("BLASgemv", BLASgemv_("T", &m, &n, &_DOne, v, &(mat->lda), x, &_One, &_DOne, y, &_One));
11429566063dSJacob Faibussowitsch   PetscCall(VecRestoreArrayRead(xx, &x));
11439566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(yy, &y));
11449566063dSJacob Faibussowitsch   PetscCall(PetscLogFlops(2.0 * A->rmap->n * A->cmap->n));
11453ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1146289bc588SBarry Smith }
1147289bc588SBarry Smith 
1148d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatGetRow_SeqDense(Mat A, PetscInt row, PetscInt *ncols, PetscInt **cols, PetscScalar **vals)
1149d71ae5a4SJacob Faibussowitsch {
1150c0bbcb79SLois Curfman McInnes   Mat_SeqDense *mat = (Mat_SeqDense *)A->data;
115113f74950SBarry Smith   PetscInt      i;
115267e560aaSBarry Smith 
11533a40ed3dSBarry Smith   PetscFunctionBegin;
1154c3e1b152SPierre Jolivet   if (ncols) *ncols = A->cmap->n;
1155289bc588SBarry Smith   if (cols) {
11569566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(A->cmap->n, cols));
1157d0f46423SBarry Smith     for (i = 0; i < A->cmap->n; i++) (*cols)[i] = i;
1158289bc588SBarry Smith   }
1159289bc588SBarry Smith   if (vals) {
1160ca15aa20SStefano Zampini     const PetscScalar *v;
1161ca15aa20SStefano Zampini 
11629566063dSJacob Faibussowitsch     PetscCall(MatDenseGetArrayRead(A, &v));
11639566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(A->cmap->n, vals));
1164ca15aa20SStefano Zampini     v += row;
11659371c9d4SSatish Balay     for (i = 0; i < A->cmap->n; i++) {
11669371c9d4SSatish Balay       (*vals)[i] = *v;
11679371c9d4SSatish Balay       v += mat->lda;
11689371c9d4SSatish Balay     }
11699566063dSJacob Faibussowitsch     PetscCall(MatDenseRestoreArrayRead(A, &v));
1170289bc588SBarry Smith   }
11713ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1172289bc588SBarry Smith }
11736ee01492SSatish Balay 
1174d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatRestoreRow_SeqDense(Mat A, PetscInt row, PetscInt *ncols, PetscInt **cols, PetscScalar **vals)
1175d71ae5a4SJacob Faibussowitsch {
1176606d414cSSatish Balay   PetscFunctionBegin;
11779566063dSJacob Faibussowitsch   if (cols) PetscCall(PetscFree(*cols));
11789566063dSJacob Faibussowitsch   if (vals) PetscCall(PetscFree(*vals));
11793ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1180289bc588SBarry Smith }
11812ef1f0ffSBarry Smith 
1182d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatSetValues_SeqDense(Mat A, PetscInt m, const PetscInt indexm[], PetscInt n, const PetscInt indexn[], const PetscScalar v[], InsertMode addv)
1183d71ae5a4SJacob Faibussowitsch {
1184c0bbcb79SLois Curfman McInnes   Mat_SeqDense *mat = (Mat_SeqDense *)A->data;
1185ca15aa20SStefano Zampini   PetscScalar  *av;
118613f74950SBarry Smith   PetscInt      i, j, idx = 0;
118747d993e7Ssuyashtn #if defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
1188c70f7ee4SJunchao Zhang   PetscOffloadMask oldf;
1189ca15aa20SStefano Zampini #endif
1190d6dfbf8fSBarry Smith 
11913a40ed3dSBarry Smith   PetscFunctionBegin;
11929566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArray(A, &av));
1193289bc588SBarry Smith   if (!mat->roworiented) {
1194dbb450caSBarry Smith     if (addv == INSERT_VALUES) {
1195289bc588SBarry Smith       for (j = 0; j < n; j++) {
11969371c9d4SSatish Balay         if (indexn[j] < 0) {
11979371c9d4SSatish Balay           idx += m;
11989371c9d4SSatish Balay           continue;
11999371c9d4SSatish Balay         }
12006bdcaf15SBarry 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);
1201289bc588SBarry Smith         for (i = 0; i < m; i++) {
12029371c9d4SSatish Balay           if (indexm[i] < 0) {
12039371c9d4SSatish Balay             idx++;
12049371c9d4SSatish Balay             continue;
12059371c9d4SSatish Balay           }
12066bdcaf15SBarry 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);
1207ca15aa20SStefano Zampini           av[indexn[j] * mat->lda + indexm[i]] = v[idx++];
1208289bc588SBarry Smith         }
1209289bc588SBarry Smith       }
12103a40ed3dSBarry Smith     } else {
1211289bc588SBarry Smith       for (j = 0; j < n; j++) {
12129371c9d4SSatish Balay         if (indexn[j] < 0) {
12139371c9d4SSatish Balay           idx += m;
12149371c9d4SSatish Balay           continue;
12159371c9d4SSatish Balay         }
12166bdcaf15SBarry 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);
1217289bc588SBarry Smith         for (i = 0; i < m; i++) {
12189371c9d4SSatish Balay           if (indexm[i] < 0) {
12199371c9d4SSatish Balay             idx++;
12209371c9d4SSatish Balay             continue;
12219371c9d4SSatish Balay           }
12226bdcaf15SBarry 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);
1223ca15aa20SStefano Zampini           av[indexn[j] * mat->lda + indexm[i]] += v[idx++];
1224289bc588SBarry Smith         }
1225289bc588SBarry Smith       }
1226289bc588SBarry Smith     }
12273a40ed3dSBarry Smith   } else {
1228dbb450caSBarry Smith     if (addv == INSERT_VALUES) {
1229e8d4e0b9SBarry Smith       for (i = 0; i < m; i++) {
12309371c9d4SSatish Balay         if (indexm[i] < 0) {
12319371c9d4SSatish Balay           idx += n;
12329371c9d4SSatish Balay           continue;
12339371c9d4SSatish Balay         }
12346bdcaf15SBarry Smith         PetscCheck(indexm[i] < A->rmap->n, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Row too large: row %" PetscInt_FMT " max %" PetscInt_FMT, indexm[i], A->rmap->n - 1);
1235e8d4e0b9SBarry Smith         for (j = 0; j < n; j++) {
12369371c9d4SSatish Balay           if (indexn[j] < 0) {
12379371c9d4SSatish Balay             idx++;
12389371c9d4SSatish Balay             continue;
12399371c9d4SSatish Balay           }
12406bdcaf15SBarry 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);
1241ca15aa20SStefano Zampini           av[indexn[j] * mat->lda + indexm[i]] = v[idx++];
1242e8d4e0b9SBarry Smith         }
1243e8d4e0b9SBarry Smith       }
12443a40ed3dSBarry Smith     } else {
1245289bc588SBarry Smith       for (i = 0; i < m; i++) {
12469371c9d4SSatish Balay         if (indexm[i] < 0) {
12479371c9d4SSatish Balay           idx += n;
12489371c9d4SSatish Balay           continue;
12499371c9d4SSatish Balay         }
12506bdcaf15SBarry Smith         PetscCheck(indexm[i] < A->rmap->n, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Row too large: row %" PetscInt_FMT " max %" PetscInt_FMT, indexm[i], A->rmap->n - 1);
1251289bc588SBarry Smith         for (j = 0; j < n; j++) {
12529371c9d4SSatish Balay           if (indexn[j] < 0) {
12539371c9d4SSatish Balay             idx++;
12549371c9d4SSatish Balay             continue;
12559371c9d4SSatish Balay           }
12566bdcaf15SBarry 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);
1257ca15aa20SStefano Zampini           av[indexn[j] * mat->lda + indexm[i]] += v[idx++];
1258289bc588SBarry Smith         }
1259289bc588SBarry Smith       }
1260289bc588SBarry Smith     }
1261e8d4e0b9SBarry Smith   }
1262ca15aa20SStefano Zampini   /* hack to prevent unneeded copy to the GPU while returning the array */
126347d993e7Ssuyashtn #if defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
1264c70f7ee4SJunchao Zhang   oldf           = A->offloadmask;
1265c70f7ee4SJunchao Zhang   A->offloadmask = PETSC_OFFLOAD_GPU;
1266ca15aa20SStefano Zampini #endif
12679566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArray(A, &av));
126847d993e7Ssuyashtn #if defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
1269c70f7ee4SJunchao Zhang   A->offloadmask = (oldf == PETSC_OFFLOAD_UNALLOCATED ? PETSC_OFFLOAD_UNALLOCATED : PETSC_OFFLOAD_CPU);
1270ca15aa20SStefano Zampini #endif
12713ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1272289bc588SBarry Smith }
1273e8d4e0b9SBarry Smith 
1274d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatGetValues_SeqDense(Mat A, PetscInt m, const PetscInt indexm[], PetscInt n, const PetscInt indexn[], PetscScalar v[])
1275d71ae5a4SJacob Faibussowitsch {
1276ae80bb75SLois Curfman McInnes   Mat_SeqDense      *mat = (Mat_SeqDense *)A->data;
1277ca15aa20SStefano Zampini   const PetscScalar *vv;
127813f74950SBarry Smith   PetscInt           i, j;
1279ae80bb75SLois Curfman McInnes 
12803a40ed3dSBarry Smith   PetscFunctionBegin;
12819566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArrayRead(A, &vv));
1282ae80bb75SLois Curfman McInnes   /* row-oriented output */
1283ae80bb75SLois Curfman McInnes   for (i = 0; i < m; i++) {
12849371c9d4SSatish Balay     if (indexm[i] < 0) {
12859371c9d4SSatish Balay       v += n;
12869371c9d4SSatish Balay       continue;
12879371c9d4SSatish Balay     }
128808401ef6SPierre 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);
1289ae80bb75SLois Curfman McInnes     for (j = 0; j < n; j++) {
12909371c9d4SSatish Balay       if (indexn[j] < 0) {
12919371c9d4SSatish Balay         v++;
12929371c9d4SSatish Balay         continue;
12939371c9d4SSatish Balay       }
129408401ef6SPierre 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);
1295ca15aa20SStefano Zampini       *v++ = vv[indexn[j] * mat->lda + indexm[i]];
1296ae80bb75SLois Curfman McInnes     }
1297ae80bb75SLois Curfman McInnes   }
12989566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArrayRead(A, &vv));
12993ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1300ae80bb75SLois Curfman McInnes }
1301ae80bb75SLois Curfman McInnes 
1302d71ae5a4SJacob Faibussowitsch PetscErrorCode MatView_Dense_Binary(Mat mat, PetscViewer viewer)
1303d71ae5a4SJacob Faibussowitsch {
13048491ab44SLisandro Dalcin   PetscBool          skipHeader;
13058491ab44SLisandro Dalcin   PetscViewerFormat  format;
13068491ab44SLisandro Dalcin   PetscInt           header[4], M, N, m, lda, i, j, k;
13078491ab44SLisandro Dalcin   const PetscScalar *v;
13088491ab44SLisandro Dalcin   PetscScalar       *vwork;
1309aabbc4fbSShri Abhyankar 
1310aabbc4fbSShri Abhyankar   PetscFunctionBegin;
13119566063dSJacob Faibussowitsch   PetscCall(PetscViewerSetUp(viewer));
13129566063dSJacob Faibussowitsch   PetscCall(PetscViewerBinaryGetSkipHeader(viewer, &skipHeader));
13139566063dSJacob Faibussowitsch   PetscCall(PetscViewerGetFormat(viewer, &format));
13148491ab44SLisandro Dalcin   if (skipHeader) format = PETSC_VIEWER_NATIVE;
1315aabbc4fbSShri Abhyankar 
13169566063dSJacob Faibussowitsch   PetscCall(MatGetSize(mat, &M, &N));
13178491ab44SLisandro Dalcin 
13188491ab44SLisandro Dalcin   /* write matrix header */
13199371c9d4SSatish Balay   header[0] = MAT_FILE_CLASSID;
13209371c9d4SSatish Balay   header[1] = M;
13219371c9d4SSatish Balay   header[2] = N;
13228491ab44SLisandro Dalcin   header[3] = (format == PETSC_VIEWER_NATIVE) ? MATRIX_BINARY_FORMAT_DENSE : M * N;
13239566063dSJacob Faibussowitsch   if (!skipHeader) PetscCall(PetscViewerBinaryWrite(viewer, header, 4, PETSC_INT));
13248491ab44SLisandro Dalcin 
13259566063dSJacob Faibussowitsch   PetscCall(MatGetLocalSize(mat, &m, NULL));
13268491ab44SLisandro Dalcin   if (format != PETSC_VIEWER_NATIVE) {
13278491ab44SLisandro Dalcin     PetscInt nnz = m * N, *iwork;
13288491ab44SLisandro Dalcin     /* store row lengths for each row */
13299566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(nnz, &iwork));
13308491ab44SLisandro Dalcin     for (i = 0; i < m; i++) iwork[i] = N;
13319566063dSJacob Faibussowitsch     PetscCall(PetscViewerBinaryWriteAll(viewer, iwork, m, PETSC_DETERMINE, PETSC_DETERMINE, PETSC_INT));
13328491ab44SLisandro Dalcin     /* store column indices (zero start index) */
13338491ab44SLisandro Dalcin     for (k = 0, i = 0; i < m; i++)
13349371c9d4SSatish Balay       for (j = 0; j < N; j++, k++) iwork[k] = j;
13359566063dSJacob Faibussowitsch     PetscCall(PetscViewerBinaryWriteAll(viewer, iwork, nnz, PETSC_DETERMINE, PETSC_DETERMINE, PETSC_INT));
13369566063dSJacob Faibussowitsch     PetscCall(PetscFree(iwork));
13378491ab44SLisandro Dalcin   }
13388491ab44SLisandro Dalcin   /* store matrix values as a dense matrix in row major order */
13399566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(m * N, &vwork));
13409566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArrayRead(mat, &v));
13419566063dSJacob Faibussowitsch   PetscCall(MatDenseGetLDA(mat, &lda));
13428491ab44SLisandro Dalcin   for (k = 0, i = 0; i < m; i++)
13439371c9d4SSatish Balay     for (j = 0; j < N; j++, k++) vwork[k] = v[i + lda * j];
13449566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArrayRead(mat, &v));
13459566063dSJacob Faibussowitsch   PetscCall(PetscViewerBinaryWriteAll(viewer, vwork, m * N, PETSC_DETERMINE, PETSC_DETERMINE, PETSC_SCALAR));
13469566063dSJacob Faibussowitsch   PetscCall(PetscFree(vwork));
13473ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
13488491ab44SLisandro Dalcin }
13498491ab44SLisandro Dalcin 
1350d71ae5a4SJacob Faibussowitsch PetscErrorCode MatLoad_Dense_Binary(Mat mat, PetscViewer viewer)
1351d71ae5a4SJacob Faibussowitsch {
13528491ab44SLisandro Dalcin   PetscBool    skipHeader;
13538491ab44SLisandro Dalcin   PetscInt     header[4], M, N, m, nz, lda, i, j, k;
13548491ab44SLisandro Dalcin   PetscInt     rows, cols;
13558491ab44SLisandro Dalcin   PetscScalar *v, *vwork;
13568491ab44SLisandro Dalcin 
13578491ab44SLisandro Dalcin   PetscFunctionBegin;
13589566063dSJacob Faibussowitsch   PetscCall(PetscViewerSetUp(viewer));
13599566063dSJacob Faibussowitsch   PetscCall(PetscViewerBinaryGetSkipHeader(viewer, &skipHeader));
13608491ab44SLisandro Dalcin 
13618491ab44SLisandro Dalcin   if (!skipHeader) {
13629566063dSJacob Faibussowitsch     PetscCall(PetscViewerBinaryRead(viewer, header, 4, NULL, PETSC_INT));
136308401ef6SPierre Jolivet     PetscCheck(header[0] == MAT_FILE_CLASSID, PetscObjectComm((PetscObject)viewer), PETSC_ERR_FILE_UNEXPECTED, "Not a matrix object in file");
13649371c9d4SSatish Balay     M = header[1];
13659371c9d4SSatish Balay     N = header[2];
136608401ef6SPierre Jolivet     PetscCheck(M >= 0, PetscObjectComm((PetscObject)viewer), PETSC_ERR_FILE_UNEXPECTED, "Matrix row size (%" PetscInt_FMT ") in file is negative", M);
136708401ef6SPierre Jolivet     PetscCheck(N >= 0, PetscObjectComm((PetscObject)viewer), PETSC_ERR_FILE_UNEXPECTED, "Matrix column size (%" PetscInt_FMT ") in file is negative", N);
13688491ab44SLisandro Dalcin     nz = header[3];
1369aed4548fSBarry Smith     PetscCheck(nz == MATRIX_BINARY_FORMAT_DENSE || nz >= 0, PetscObjectComm((PetscObject)viewer), PETSC_ERR_FILE_UNEXPECTED, "Unknown matrix format %" PetscInt_FMT " in file", nz);
1370aabbc4fbSShri Abhyankar   } else {
13719566063dSJacob Faibussowitsch     PetscCall(MatGetSize(mat, &M, &N));
1372aed4548fSBarry 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");
13738491ab44SLisandro Dalcin     nz = MATRIX_BINARY_FORMAT_DENSE;
1374e6324fbbSBarry Smith   }
1375aabbc4fbSShri Abhyankar 
13768491ab44SLisandro Dalcin   /* setup global sizes if not set */
13778491ab44SLisandro Dalcin   if (mat->rmap->N < 0) mat->rmap->N = M;
13788491ab44SLisandro Dalcin   if (mat->cmap->N < 0) mat->cmap->N = N;
13799566063dSJacob Faibussowitsch   PetscCall(MatSetUp(mat));
13808491ab44SLisandro Dalcin   /* check if global sizes are correct */
13819566063dSJacob Faibussowitsch   PetscCall(MatGetSize(mat, &rows, &cols));
1382aed4548fSBarry 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);
1383aabbc4fbSShri Abhyankar 
13849566063dSJacob Faibussowitsch   PetscCall(MatGetSize(mat, NULL, &N));
13859566063dSJacob Faibussowitsch   PetscCall(MatGetLocalSize(mat, &m, NULL));
13869566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArray(mat, &v));
13879566063dSJacob Faibussowitsch   PetscCall(MatDenseGetLDA(mat, &lda));
13888491ab44SLisandro Dalcin   if (nz == MATRIX_BINARY_FORMAT_DENSE) { /* matrix in file is dense format */
13898491ab44SLisandro Dalcin     PetscInt nnz = m * N;
13908491ab44SLisandro Dalcin     /* read in matrix values */
13919566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(nnz, &vwork));
13929566063dSJacob Faibussowitsch     PetscCall(PetscViewerBinaryReadAll(viewer, vwork, nnz, PETSC_DETERMINE, PETSC_DETERMINE, PETSC_SCALAR));
13938491ab44SLisandro Dalcin     /* store values in column major order */
13948491ab44SLisandro Dalcin     for (j = 0; j < N; j++)
13959371c9d4SSatish Balay       for (i = 0; i < m; i++) v[i + lda * j] = vwork[i * N + j];
13969566063dSJacob Faibussowitsch     PetscCall(PetscFree(vwork));
13978491ab44SLisandro Dalcin   } else { /* matrix in file is sparse format */
13988491ab44SLisandro Dalcin     PetscInt nnz = 0, *rlens, *icols;
13998491ab44SLisandro Dalcin     /* read in row lengths */
14009566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(m, &rlens));
14019566063dSJacob Faibussowitsch     PetscCall(PetscViewerBinaryReadAll(viewer, rlens, m, PETSC_DETERMINE, PETSC_DETERMINE, PETSC_INT));
14028491ab44SLisandro Dalcin     for (i = 0; i < m; i++) nnz += rlens[i];
14038491ab44SLisandro Dalcin     /* read in column indices and values */
14049566063dSJacob Faibussowitsch     PetscCall(PetscMalloc2(nnz, &icols, nnz, &vwork));
14059566063dSJacob Faibussowitsch     PetscCall(PetscViewerBinaryReadAll(viewer, icols, nnz, PETSC_DETERMINE, PETSC_DETERMINE, PETSC_INT));
14069566063dSJacob Faibussowitsch     PetscCall(PetscViewerBinaryReadAll(viewer, vwork, nnz, PETSC_DETERMINE, PETSC_DETERMINE, PETSC_SCALAR));
14078491ab44SLisandro Dalcin     /* store values in column major order */
14088491ab44SLisandro Dalcin     for (k = 0, i = 0; i < m; i++)
14099371c9d4SSatish Balay       for (j = 0; j < rlens[i]; j++, k++) v[i + lda * icols[k]] = vwork[k];
14109566063dSJacob Faibussowitsch     PetscCall(PetscFree(rlens));
14119566063dSJacob Faibussowitsch     PetscCall(PetscFree2(icols, vwork));
1412aabbc4fbSShri Abhyankar   }
14139566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArray(mat, &v));
14149566063dSJacob Faibussowitsch   PetscCall(MatAssemblyBegin(mat, MAT_FINAL_ASSEMBLY));
14159566063dSJacob Faibussowitsch   PetscCall(MatAssemblyEnd(mat, MAT_FINAL_ASSEMBLY));
14163ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1417aabbc4fbSShri Abhyankar }
1418aabbc4fbSShri Abhyankar 
141966976f2fSJacob Faibussowitsch static PetscErrorCode MatLoad_SeqDense(Mat newMat, PetscViewer viewer)
1420d71ae5a4SJacob Faibussowitsch {
1421eb91f321SVaclav Hapla   PetscBool isbinary, ishdf5;
1422eb91f321SVaclav Hapla 
1423eb91f321SVaclav Hapla   PetscFunctionBegin;
1424eb91f321SVaclav Hapla   PetscValidHeaderSpecific(newMat, MAT_CLASSID, 1);
1425eb91f321SVaclav Hapla   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
1426eb91f321SVaclav Hapla   /* force binary viewer to load .info file if it has not yet done so */
14279566063dSJacob Faibussowitsch   PetscCall(PetscViewerSetUp(viewer));
14289566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERBINARY, &isbinary));
14299566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5));
1430eb91f321SVaclav Hapla   if (isbinary) {
14319566063dSJacob Faibussowitsch     PetscCall(MatLoad_Dense_Binary(newMat, viewer));
1432eb91f321SVaclav Hapla   } else if (ishdf5) {
1433eb91f321SVaclav Hapla #if defined(PETSC_HAVE_HDF5)
14349566063dSJacob Faibussowitsch     PetscCall(MatLoad_Dense_HDF5(newMat, viewer));
1435eb91f321SVaclav Hapla #else
1436eb91f321SVaclav Hapla     SETERRQ(PetscObjectComm((PetscObject)newMat), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5");
1437eb91f321SVaclav Hapla #endif
1438eb91f321SVaclav Hapla   } else {
143998921bdaSJacob 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);
1440eb91f321SVaclav Hapla   }
14413ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1442eb91f321SVaclav Hapla }
1443eb91f321SVaclav Hapla 
1444d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatView_SeqDense_ASCII(Mat A, PetscViewer viewer)
1445d71ae5a4SJacob Faibussowitsch {
1446932b0c3eSLois Curfman McInnes   Mat_SeqDense     *a = (Mat_SeqDense *)A->data;
144713f74950SBarry Smith   PetscInt          i, j;
14482dcb1b2aSMatthew Knepley   const char       *name;
1449ca15aa20SStefano Zampini   PetscScalar      *v, *av;
1450f3ef73ceSBarry Smith   PetscViewerFormat format;
14515f481a85SSatish Balay #if defined(PETSC_USE_COMPLEX)
1452ace3abfcSBarry Smith   PetscBool allreal = PETSC_TRUE;
14535f481a85SSatish Balay #endif
1454932b0c3eSLois Curfman McInnes 
14553a40ed3dSBarry Smith   PetscFunctionBegin;
14569566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArrayRead(A, (const PetscScalar **)&av));
14579566063dSJacob Faibussowitsch   PetscCall(PetscViewerGetFormat(viewer, &format));
1458456192e2SBarry Smith   if (format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL) {
14593ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS); /* do nothing for now */
1460fb9695e5SSatish Balay   } else if (format == PETSC_VIEWER_ASCII_COMMON) {
14619566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIUseTabs(viewer, PETSC_FALSE));
1462d0f46423SBarry Smith     for (i = 0; i < A->rmap->n; i++) {
1463ca15aa20SStefano Zampini       v = av + i;
14649566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "row %" PetscInt_FMT ":", i));
1465d0f46423SBarry Smith       for (j = 0; j < A->cmap->n; j++) {
1466aa482453SBarry Smith #if defined(PETSC_USE_COMPLEX)
1467329f5518SBarry Smith         if (PetscRealPart(*v) != 0.0 && PetscImaginaryPart(*v) != 0.0) {
14689566063dSJacob Faibussowitsch           PetscCall(PetscViewerASCIIPrintf(viewer, " (%" PetscInt_FMT ", %g + %g i) ", j, (double)PetscRealPart(*v), (double)PetscImaginaryPart(*v)));
1469329f5518SBarry Smith         } else if (PetscRealPart(*v)) {
14709566063dSJacob Faibussowitsch           PetscCall(PetscViewerASCIIPrintf(viewer, " (%" PetscInt_FMT ", %g) ", j, (double)PetscRealPart(*v)));
14716831982aSBarry Smith         }
147280cd9d93SLois Curfman McInnes #else
147348a46eb9SPierre Jolivet         if (*v) PetscCall(PetscViewerASCIIPrintf(viewer, " (%" PetscInt_FMT ", %g) ", j, (double)*v));
147480cd9d93SLois Curfman McInnes #endif
14751b807ce4Svictorle         v += a->lda;
147680cd9d93SLois Curfman McInnes       }
14779566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "\n"));
147880cd9d93SLois Curfman McInnes     }
14799566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIUseTabs(viewer, PETSC_TRUE));
14803a40ed3dSBarry Smith   } else {
14819566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIUseTabs(viewer, PETSC_FALSE));
1482aa482453SBarry Smith #if defined(PETSC_USE_COMPLEX)
148347989497SBarry Smith     /* determine if matrix has all real values */
1484bcd8d3a4SJose E. Roman     for (j = 0; j < A->cmap->n; j++) {
1485bcd8d3a4SJose E. Roman       v = av + j * a->lda;
1486bcd8d3a4SJose E. Roman       for (i = 0; i < A->rmap->n; i++) {
14879371c9d4SSatish Balay         if (PetscImaginaryPart(v[i])) {
14889371c9d4SSatish Balay           allreal = PETSC_FALSE;
14899371c9d4SSatish Balay           break;
14909371c9d4SSatish Balay         }
149147989497SBarry Smith       }
1492bcd8d3a4SJose E. Roman     }
149347989497SBarry Smith #endif
1494fb9695e5SSatish Balay     if (format == PETSC_VIEWER_ASCII_MATLAB) {
14959566063dSJacob Faibussowitsch       PetscCall(PetscObjectGetName((PetscObject)A, &name));
14969566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "%% Size = %" PetscInt_FMT " %" PetscInt_FMT " \n", A->rmap->n, A->cmap->n));
14979566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "%s = zeros(%" PetscInt_FMT ",%" PetscInt_FMT ");\n", name, A->rmap->n, A->cmap->n));
14989566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "%s = [\n", name));
1499ffac6cdbSBarry Smith     }
1500ffac6cdbSBarry Smith 
1501d0f46423SBarry Smith     for (i = 0; i < A->rmap->n; i++) {
1502ca15aa20SStefano Zampini       v = av + i;
1503d0f46423SBarry Smith       for (j = 0; j < A->cmap->n; j++) {
1504aa482453SBarry Smith #if defined(PETSC_USE_COMPLEX)
150547989497SBarry Smith         if (allreal) {
15069566063dSJacob Faibussowitsch           PetscCall(PetscViewerASCIIPrintf(viewer, "%18.16e ", (double)PetscRealPart(*v)));
150747989497SBarry Smith         } else {
15089566063dSJacob Faibussowitsch           PetscCall(PetscViewerASCIIPrintf(viewer, "%18.16e + %18.16ei ", (double)PetscRealPart(*v), (double)PetscImaginaryPart(*v)));
150947989497SBarry Smith         }
1510289bc588SBarry Smith #else
15119566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, "%18.16e ", (double)*v));
1512289bc588SBarry Smith #endif
15131b807ce4Svictorle         v += a->lda;
1514289bc588SBarry Smith       }
15159566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "\n"));
1516289bc588SBarry Smith     }
151748a46eb9SPierre Jolivet     if (format == PETSC_VIEWER_ASCII_MATLAB) PetscCall(PetscViewerASCIIPrintf(viewer, "];\n"));
15189566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIUseTabs(viewer, PETSC_TRUE));
1519da3a660dSBarry Smith   }
15209566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArrayRead(A, (const PetscScalar **)&av));
15219566063dSJacob Faibussowitsch   PetscCall(PetscViewerFlush(viewer));
15223ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1523289bc588SBarry Smith }
1524289bc588SBarry Smith 
15259804daf3SBarry Smith #include <petscdraw.h>
1526d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatView_SeqDense_Draw_Zoom(PetscDraw draw, void *Aa)
1527d71ae5a4SJacob Faibussowitsch {
1528f1af5d2fSBarry Smith   Mat                A = (Mat)Aa;
1529383922c3SLisandro Dalcin   PetscInt           m = A->rmap->n, n = A->cmap->n, i, j;
1530383922c3SLisandro Dalcin   int                color = PETSC_DRAW_WHITE;
1531ca15aa20SStefano Zampini   const PetscScalar *v;
1532b0a32e0cSBarry Smith   PetscViewer        viewer;
1533b05fc000SLisandro Dalcin   PetscReal          xl, yl, xr, yr, x_l, x_r, y_l, y_r;
1534f3ef73ceSBarry Smith   PetscViewerFormat  format;
1535f1af5d2fSBarry Smith 
1536f1af5d2fSBarry Smith   PetscFunctionBegin;
15379566063dSJacob Faibussowitsch   PetscCall(PetscObjectQuery((PetscObject)A, "Zoomviewer", (PetscObject *)&viewer));
15389566063dSJacob Faibussowitsch   PetscCall(PetscViewerGetFormat(viewer, &format));
15399566063dSJacob Faibussowitsch   PetscCall(PetscDrawGetCoordinates(draw, &xl, &yl, &xr, &yr));
1540f1af5d2fSBarry Smith 
1541f1af5d2fSBarry Smith   /* Loop over matrix elements drawing boxes */
15429566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArrayRead(A, &v));
1543fb9695e5SSatish Balay   if (format != PETSC_VIEWER_DRAW_CONTOUR) {
1544d0609cedSBarry Smith     PetscDrawCollectiveBegin(draw);
1545f1af5d2fSBarry Smith     /* Blue for negative and Red for positive */
1546f1af5d2fSBarry Smith     for (j = 0; j < n; j++) {
15479371c9d4SSatish Balay       x_l = j;
15489371c9d4SSatish Balay       x_r = x_l + 1.0;
1549f1af5d2fSBarry Smith       for (i = 0; i < m; i++) {
1550f1af5d2fSBarry Smith         y_l = m - i - 1.0;
1551f1af5d2fSBarry Smith         y_r = y_l + 1.0;
1552ca15aa20SStefano Zampini         if (PetscRealPart(v[j * m + i]) > 0.) color = PETSC_DRAW_RED;
1553ca15aa20SStefano Zampini         else if (PetscRealPart(v[j * m + i]) < 0.) color = PETSC_DRAW_BLUE;
1554ca15aa20SStefano Zampini         else continue;
15559566063dSJacob Faibussowitsch         PetscCall(PetscDrawRectangle(draw, x_l, y_l, x_r, y_r, color, color, color, color));
1556f1af5d2fSBarry Smith       }
1557f1af5d2fSBarry Smith     }
1558d0609cedSBarry Smith     PetscDrawCollectiveEnd(draw);
1559f1af5d2fSBarry Smith   } else {
1560f1af5d2fSBarry Smith     /* use contour shading to indicate magnitude of values */
1561f1af5d2fSBarry Smith     /* first determine max of all nonzero values */
1562b05fc000SLisandro Dalcin     PetscReal minv = 0.0, maxv = 0.0;
1563b05fc000SLisandro Dalcin     PetscDraw popup;
1564b05fc000SLisandro Dalcin 
1565f1af5d2fSBarry Smith     for (i = 0; i < m * n; i++) {
1566f1af5d2fSBarry Smith       if (PetscAbsScalar(v[i]) > maxv) maxv = PetscAbsScalar(v[i]);
1567f1af5d2fSBarry Smith     }
1568383922c3SLisandro Dalcin     if (minv >= maxv) maxv = minv + PETSC_SMALL;
15699566063dSJacob Faibussowitsch     PetscCall(PetscDrawGetPopup(draw, &popup));
15709566063dSJacob Faibussowitsch     PetscCall(PetscDrawScalePopup(popup, minv, maxv));
1571383922c3SLisandro Dalcin 
1572d0609cedSBarry Smith     PetscDrawCollectiveBegin(draw);
1573f1af5d2fSBarry Smith     for (j = 0; j < n; j++) {
1574f1af5d2fSBarry Smith       x_l = j;
1575f1af5d2fSBarry Smith       x_r = x_l + 1.0;
1576f1af5d2fSBarry Smith       for (i = 0; i < m; i++) {
1577f1af5d2fSBarry Smith         y_l   = m - i - 1.0;
1578f1af5d2fSBarry Smith         y_r   = y_l + 1.0;
1579b05fc000SLisandro Dalcin         color = PetscDrawRealToColor(PetscAbsScalar(v[j * m + i]), minv, maxv);
15809566063dSJacob Faibussowitsch         PetscCall(PetscDrawRectangle(draw, x_l, y_l, x_r, y_r, color, color, color, color));
1581f1af5d2fSBarry Smith       }
1582f1af5d2fSBarry Smith     }
1583d0609cedSBarry Smith     PetscDrawCollectiveEnd(draw);
1584f1af5d2fSBarry Smith   }
15859566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArrayRead(A, &v));
15863ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1587f1af5d2fSBarry Smith }
1588f1af5d2fSBarry Smith 
1589d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatView_SeqDense_Draw(Mat A, PetscViewer viewer)
1590d71ae5a4SJacob Faibussowitsch {
1591b0a32e0cSBarry Smith   PetscDraw draw;
1592ace3abfcSBarry Smith   PetscBool isnull;
1593329f5518SBarry Smith   PetscReal xr, yr, xl, yl, h, w;
1594f1af5d2fSBarry Smith 
1595f1af5d2fSBarry Smith   PetscFunctionBegin;
15969566063dSJacob Faibussowitsch   PetscCall(PetscViewerDrawGetDraw(viewer, 0, &draw));
15979566063dSJacob Faibussowitsch   PetscCall(PetscDrawIsNull(draw, &isnull));
15983ba16761SJacob Faibussowitsch   if (isnull) PetscFunctionReturn(PETSC_SUCCESS);
1599f1af5d2fSBarry Smith 
16009371c9d4SSatish Balay   xr = A->cmap->n;
16019371c9d4SSatish Balay   yr = A->rmap->n;
16029371c9d4SSatish Balay   h  = yr / 10.0;
16039371c9d4SSatish Balay   w  = xr / 10.0;
16049371c9d4SSatish Balay   xr += w;
16059371c9d4SSatish Balay   yr += h;
16069371c9d4SSatish Balay   xl = -w;
16079371c9d4SSatish Balay   yl = -h;
16089566063dSJacob Faibussowitsch   PetscCall(PetscDrawSetCoordinates(draw, xl, yl, xr, yr));
16099566063dSJacob Faibussowitsch   PetscCall(PetscObjectCompose((PetscObject)A, "Zoomviewer", (PetscObject)viewer));
16109566063dSJacob Faibussowitsch   PetscCall(PetscDrawZoom(draw, MatView_SeqDense_Draw_Zoom, A));
16119566063dSJacob Faibussowitsch   PetscCall(PetscObjectCompose((PetscObject)A, "Zoomviewer", NULL));
16129566063dSJacob Faibussowitsch   PetscCall(PetscDrawSave(draw));
16133ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1614f1af5d2fSBarry Smith }
1615f1af5d2fSBarry Smith 
1616d71ae5a4SJacob Faibussowitsch PetscErrorCode MatView_SeqDense(Mat A, PetscViewer viewer)
1617d71ae5a4SJacob Faibussowitsch {
1618ace3abfcSBarry Smith   PetscBool iascii, isbinary, isdraw;
1619932b0c3eSLois Curfman McInnes 
16203a40ed3dSBarry Smith   PetscFunctionBegin;
16219566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
16229566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERBINARY, &isbinary));
16239566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERDRAW, &isdraw));
16241baa6e33SBarry Smith   if (iascii) PetscCall(MatView_SeqDense_ASCII(A, viewer));
16251baa6e33SBarry Smith   else if (isbinary) PetscCall(MatView_Dense_Binary(A, viewer));
16261baa6e33SBarry Smith   else if (isdraw) PetscCall(MatView_SeqDense_Draw(A, viewer));
16273ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1628932b0c3eSLois Curfman McInnes }
1629289bc588SBarry Smith 
1630d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatDensePlaceArray_SeqDense(Mat A, const PetscScalar *array)
1631d71ae5a4SJacob Faibussowitsch {
1632d3042a70SBarry Smith   Mat_SeqDense *a = (Mat_SeqDense *)A->data;
1633d3042a70SBarry Smith 
1634d3042a70SBarry Smith   PetscFunctionBegin;
163528b400f6SJacob Faibussowitsch   PetscCheck(!a->vecinuse, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Need to call MatDenseRestoreColumnVec() first");
163628b400f6SJacob Faibussowitsch   PetscCheck(!a->matinuse, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Need to call MatDenseRestoreSubMatrix() first");
163728b400f6SJacob Faibussowitsch   PetscCheck(!a->unplacedarray, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Need to call MatDenseRestoreArray() first");
1638d3042a70SBarry Smith   a->unplacedarray       = a->v;
1639d3042a70SBarry Smith   a->unplaced_user_alloc = a->user_alloc;
1640d3042a70SBarry Smith   a->v                   = (PetscScalar *)array;
1641637a0070SStefano Zampini   a->user_alloc          = PETSC_TRUE;
164247d993e7Ssuyashtn #if defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
1643c70f7ee4SJunchao Zhang   A->offloadmask = PETSC_OFFLOAD_CPU;
1644ca15aa20SStefano Zampini #endif
16453ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1646d3042a70SBarry Smith }
1647d3042a70SBarry Smith 
1648d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatDenseResetArray_SeqDense(Mat A)
1649d71ae5a4SJacob Faibussowitsch {
1650d3042a70SBarry Smith   Mat_SeqDense *a = (Mat_SeqDense *)A->data;
1651d3042a70SBarry Smith 
1652d3042a70SBarry Smith   PetscFunctionBegin;
165328b400f6SJacob Faibussowitsch   PetscCheck(!a->vecinuse, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Need to call MatDenseRestoreColumnVec() first");
165428b400f6SJacob Faibussowitsch   PetscCheck(!a->matinuse, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Need to call MatDenseRestoreSubMatrix() first");
1655d3042a70SBarry Smith   a->v             = a->unplacedarray;
1656d3042a70SBarry Smith   a->user_alloc    = a->unplaced_user_alloc;
1657d3042a70SBarry Smith   a->unplacedarray = NULL;
165847d993e7Ssuyashtn #if defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
1659c70f7ee4SJunchao Zhang   A->offloadmask = PETSC_OFFLOAD_CPU;
1660ca15aa20SStefano Zampini #endif
16613ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1662d3042a70SBarry Smith }
1663d3042a70SBarry Smith 
1664d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatDenseReplaceArray_SeqDense(Mat A, const PetscScalar *array)
1665d71ae5a4SJacob Faibussowitsch {
1666d5ea218eSStefano Zampini   Mat_SeqDense *a = (Mat_SeqDense *)A->data;
1667d5ea218eSStefano Zampini 
1668d5ea218eSStefano Zampini   PetscFunctionBegin;
166928b400f6SJacob Faibussowitsch   PetscCheck(!a->vecinuse, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Need to call MatDenseRestoreColumnVec() first");
167028b400f6SJacob Faibussowitsch   PetscCheck(!a->matinuse, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Need to call MatDenseRestoreSubMatrix() first");
16719566063dSJacob Faibussowitsch   if (!a->user_alloc) PetscCall(PetscFree(a->v));
1672d5ea218eSStefano Zampini   a->v          = (PetscScalar *)array;
1673d5ea218eSStefano Zampini   a->user_alloc = PETSC_FALSE;
167447d993e7Ssuyashtn #if defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
1675d5ea218eSStefano Zampini   A->offloadmask = PETSC_OFFLOAD_CPU;
1676d5ea218eSStefano Zampini #endif
16773ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1678d5ea218eSStefano Zampini }
1679d5ea218eSStefano Zampini 
1680d71ae5a4SJacob Faibussowitsch PetscErrorCode MatDestroy_SeqDense(Mat mat)
1681d71ae5a4SJacob Faibussowitsch {
1682ec8511deSBarry Smith   Mat_SeqDense *l = (Mat_SeqDense *)mat->data;
168390f02eecSBarry Smith 
16843a40ed3dSBarry Smith   PetscFunctionBegin;
16853ba16761SJacob Faibussowitsch   PetscCall(PetscLogObjectState((PetscObject)mat, "Rows %" PetscInt_FMT " Cols %" PetscInt_FMT, mat->rmap->n, mat->cmap->n));
16869566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&(l->qrrhs)));
16879566063dSJacob Faibussowitsch   PetscCall(PetscFree(l->tau));
16889566063dSJacob Faibussowitsch   PetscCall(PetscFree(l->pivots));
16899566063dSJacob Faibussowitsch   PetscCall(PetscFree(l->fwork));
16909566063dSJacob Faibussowitsch   if (!l->user_alloc) PetscCall(PetscFree(l->v));
16919566063dSJacob Faibussowitsch   if (!l->unplaced_user_alloc) PetscCall(PetscFree(l->unplacedarray));
169228b400f6SJacob Faibussowitsch   PetscCheck(!l->vecinuse, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Need to call MatDenseRestoreColumnVec() first");
169328b400f6SJacob Faibussowitsch   PetscCheck(!l->matinuse, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Need to call MatDenseRestoreSubMatrix() first");
16949566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&l->cvec));
16959566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&l->cmat));
16969566063dSJacob Faibussowitsch   PetscCall(PetscFree(mat->data));
1697dbd8c25aSHong Zhang 
16989566063dSJacob Faibussowitsch   PetscCall(PetscObjectChangeTypeName((PetscObject)mat, NULL));
16999566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatQRFactor_C", NULL));
17002e956fe4SStefano Zampini   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatQRFactorSymbolic_C", NULL));
17012e956fe4SStefano Zampini   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatQRFactorNumeric_C", NULL));
17029566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatDenseGetLDA_C", NULL));
17039566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatDenseSetLDA_C", NULL));
17049566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatDenseGetArray_C", NULL));
17059566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatDenseRestoreArray_C", NULL));
17069566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatDensePlaceArray_C", NULL));
17079566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatDenseResetArray_C", NULL));
17089566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatDenseReplaceArray_C", NULL));
17099566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatDenseGetArrayRead_C", NULL));
17109566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatDenseRestoreArrayRead_C", NULL));
17119566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatDenseGetArrayWrite_C", NULL));
17129566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatDenseRestoreArrayWrite_C", NULL));
17139566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatConvert_seqdense_seqaij_C", NULL));
17148baccfbdSHong Zhang #if defined(PETSC_HAVE_ELEMENTAL)
17159566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatConvert_seqdense_elemental_C", NULL));
17168baccfbdSHong Zhang #endif
1717d24d4204SJose E. Roman #if defined(PETSC_HAVE_SCALAPACK)
17189566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatConvert_seqdense_scalapack_C", NULL));
1719d24d4204SJose E. Roman #endif
17202bf066beSStefano Zampini #if defined(PETSC_HAVE_CUDA)
17219566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatConvert_seqdense_seqdensecuda_C", NULL));
17229566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatProductSetFromOptions_seqdensecuda_seqdensecuda_C", NULL));
17239566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatProductSetFromOptions_seqdensecuda_seqdense_C", NULL));
17242e956fe4SStefano Zampini   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatProductSetFromOptions_seqdense_seqdensecuda_C", NULL));
17252bf066beSStefano Zampini #endif
172647d993e7Ssuyashtn #if defined(PETSC_HAVE_HIP)
172747d993e7Ssuyashtn   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatConvert_seqdense_seqdensehip_C", NULL));
172847d993e7Ssuyashtn   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatProductSetFromOptions_seqdensehip_seqdensehip_C", NULL));
172947d993e7Ssuyashtn   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatProductSetFromOptions_seqdensehip_seqdense_C", NULL));
173047d993e7Ssuyashtn   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatProductSetFromOptions_seqdense_seqdensehip_C", NULL));
173147d993e7Ssuyashtn #endif
17329566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatSeqDenseSetPreallocation_C", NULL));
17339566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatProductSetFromOptions_seqaij_seqdense_C", NULL));
17349566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatProductSetFromOptions_seqdense_seqdense_C", NULL));
17359566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatProductSetFromOptions_seqbaij_seqdense_C", NULL));
17369566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatProductSetFromOptions_seqsbaij_seqdense_C", NULL));
173752c5f739Sprj- 
17389566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatDenseGetColumn_C", NULL));
17399566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatDenseRestoreColumn_C", NULL));
17409566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatDenseGetColumnVec_C", NULL));
17419566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatDenseRestoreColumnVec_C", NULL));
17429566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatDenseGetColumnVecRead_C", NULL));
17439566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatDenseRestoreColumnVecRead_C", NULL));
17449566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatDenseGetColumnVecWrite_C", NULL));
17459566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatDenseRestoreColumnVecWrite_C", NULL));
17469566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatDenseGetSubMatrix_C", NULL));
17479566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatDenseRestoreSubMatrix_C", NULL));
17483ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1749289bc588SBarry Smith }
1750289bc588SBarry Smith 
1751d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatTranspose_SeqDense(Mat A, MatReuse reuse, Mat *matout)
1752d71ae5a4SJacob Faibussowitsch {
1753c0bbcb79SLois Curfman McInnes   Mat_SeqDense *mat = (Mat_SeqDense *)A->data;
17546536e3caSStefano Zampini   PetscInt      k, j, m = A->rmap->n, M = mat->lda, n = A->cmap->n;
175587828ca2SBarry Smith   PetscScalar  *v, tmp;
175648b35521SBarry Smith 
17573a40ed3dSBarry Smith   PetscFunctionBegin;
17587fb60732SBarry Smith   if (reuse == MAT_REUSE_MATRIX) PetscCall(MatTransposeCheckNonzeroState_Private(A, *matout));
17596536e3caSStefano Zampini   if (reuse == MAT_INPLACE_MATRIX) {
17606536e3caSStefano Zampini     if (m == n) { /* in place transpose */
17619566063dSJacob Faibussowitsch       PetscCall(MatDenseGetArray(A, &v));
1762d3e5ee88SLois Curfman McInnes       for (j = 0; j < m; j++) {
1763289bc588SBarry Smith         for (k = 0; k < j; k++) {
17641b807ce4Svictorle           tmp          = v[j + k * M];
17651b807ce4Svictorle           v[j + k * M] = v[k + j * M];
17661b807ce4Svictorle           v[k + j * M] = tmp;
1767289bc588SBarry Smith         }
1768289bc588SBarry Smith       }
17699566063dSJacob Faibussowitsch       PetscCall(MatDenseRestoreArray(A, &v));
17706536e3caSStefano Zampini     } else { /* reuse memory, temporary allocates new memory */
17716536e3caSStefano Zampini       PetscScalar *v2;
17726536e3caSStefano Zampini       PetscLayout  tmplayout;
17736536e3caSStefano Zampini 
17749566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1((size_t)m * n, &v2));
17759566063dSJacob Faibussowitsch       PetscCall(MatDenseGetArray(A, &v));
17766536e3caSStefano Zampini       for (j = 0; j < n; j++) {
17776536e3caSStefano Zampini         for (k = 0; k < m; k++) v2[j + (size_t)k * n] = v[k + (size_t)j * M];
17786536e3caSStefano Zampini       }
17799566063dSJacob Faibussowitsch       PetscCall(PetscArraycpy(v, v2, (size_t)m * n));
17809566063dSJacob Faibussowitsch       PetscCall(PetscFree(v2));
17819566063dSJacob Faibussowitsch       PetscCall(MatDenseRestoreArray(A, &v));
17826536e3caSStefano Zampini       /* cleanup size dependent quantities */
17839566063dSJacob Faibussowitsch       PetscCall(VecDestroy(&mat->cvec));
17849566063dSJacob Faibussowitsch       PetscCall(MatDestroy(&mat->cmat));
17859566063dSJacob Faibussowitsch       PetscCall(PetscFree(mat->pivots));
17869566063dSJacob Faibussowitsch       PetscCall(PetscFree(mat->fwork));
17876536e3caSStefano Zampini       /* swap row/col layouts */
17886536e3caSStefano Zampini       mat->lda  = n;
17896536e3caSStefano Zampini       tmplayout = A->rmap;
17906536e3caSStefano Zampini       A->rmap   = A->cmap;
17916536e3caSStefano Zampini       A->cmap   = tmplayout;
17926536e3caSStefano Zampini     }
17933a40ed3dSBarry Smith   } else { /* out-of-place transpose */
1794d3e5ee88SLois Curfman McInnes     Mat           tmat;
1795ec8511deSBarry Smith     Mat_SeqDense *tmatd;
179687828ca2SBarry Smith     PetscScalar  *v2;
1797af36a384SStefano Zampini     PetscInt      M2;
1798ea709b57SSatish Balay 
17996536e3caSStefano Zampini     if (reuse == MAT_INITIAL_MATRIX) {
18009566063dSJacob Faibussowitsch       PetscCall(MatCreate(PetscObjectComm((PetscObject)A), &tmat));
18019566063dSJacob Faibussowitsch       PetscCall(MatSetSizes(tmat, A->cmap->n, A->rmap->n, A->cmap->n, A->rmap->n));
18029566063dSJacob Faibussowitsch       PetscCall(MatSetType(tmat, ((PetscObject)A)->type_name));
18039566063dSJacob Faibussowitsch       PetscCall(MatSeqDenseSetPreallocation(tmat, NULL));
1804ca15aa20SStefano Zampini     } else tmat = *matout;
1805ca15aa20SStefano Zampini 
18069566063dSJacob Faibussowitsch     PetscCall(MatDenseGetArrayRead(A, (const PetscScalar **)&v));
18079566063dSJacob Faibussowitsch     PetscCall(MatDenseGetArray(tmat, &v2));
1808ec8511deSBarry Smith     tmatd = (Mat_SeqDense *)tmat->data;
1809ca15aa20SStefano Zampini     M2    = tmatd->lda;
1810d3e5ee88SLois Curfman McInnes     for (j = 0; j < n; j++) {
1811af36a384SStefano Zampini       for (k = 0; k < m; k++) v2[j + k * M2] = v[k + j * M];
1812d3e5ee88SLois Curfman McInnes     }
18139566063dSJacob Faibussowitsch     PetscCall(MatDenseRestoreArray(tmat, &v2));
18149566063dSJacob Faibussowitsch     PetscCall(MatDenseRestoreArrayRead(A, (const PetscScalar **)&v));
18159566063dSJacob Faibussowitsch     PetscCall(MatAssemblyBegin(tmat, MAT_FINAL_ASSEMBLY));
18169566063dSJacob Faibussowitsch     PetscCall(MatAssemblyEnd(tmat, MAT_FINAL_ASSEMBLY));
18176536e3caSStefano Zampini     *matout = tmat;
181848b35521SBarry Smith   }
18193ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1820289bc588SBarry Smith }
1821289bc588SBarry Smith 
1822d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatEqual_SeqDense(Mat A1, Mat A2, PetscBool *flg)
1823d71ae5a4SJacob Faibussowitsch {
1824c0bbcb79SLois Curfman McInnes   Mat_SeqDense      *mat1 = (Mat_SeqDense *)A1->data;
1825c0bbcb79SLois Curfman McInnes   Mat_SeqDense      *mat2 = (Mat_SeqDense *)A2->data;
1826ca15aa20SStefano Zampini   PetscInt           i;
1827ca15aa20SStefano Zampini   const PetscScalar *v1, *v2;
18289ea5d5aeSSatish Balay 
18293a40ed3dSBarry Smith   PetscFunctionBegin;
18309371c9d4SSatish Balay   if (A1->rmap->n != A2->rmap->n) {
18319371c9d4SSatish Balay     *flg = PETSC_FALSE;
18323ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
18339371c9d4SSatish Balay   }
18349371c9d4SSatish Balay   if (A1->cmap->n != A2->cmap->n) {
18359371c9d4SSatish Balay     *flg = PETSC_FALSE;
18363ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
18379371c9d4SSatish Balay   }
18389566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArrayRead(A1, &v1));
18399566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArrayRead(A2, &v2));
1840ca15aa20SStefano Zampini   for (i = 0; i < A1->cmap->n; i++) {
18419566063dSJacob Faibussowitsch     PetscCall(PetscArraycmp(v1, v2, A1->rmap->n, flg));
18423ba16761SJacob Faibussowitsch     if (*flg == PETSC_FALSE) PetscFunctionReturn(PETSC_SUCCESS);
1843ca15aa20SStefano Zampini     v1 += mat1->lda;
1844ca15aa20SStefano Zampini     v2 += mat2->lda;
18451b807ce4Svictorle   }
18469566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArrayRead(A1, &v1));
18479566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArrayRead(A2, &v2));
184877c4ece6SBarry Smith   *flg = PETSC_TRUE;
18493ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1850289bc588SBarry Smith }
1851289bc588SBarry Smith 
185214277c92SJacob Faibussowitsch PetscErrorCode MatGetDiagonal_SeqDense(Mat A, Vec v)
1853d71ae5a4SJacob Faibussowitsch {
1854c0bbcb79SLois Curfman McInnes   Mat_SeqDense      *mat = (Mat_SeqDense *)A->data;
185513f74950SBarry Smith   PetscInt           i, n, len;
1856ca15aa20SStefano Zampini   PetscScalar       *x;
1857ca15aa20SStefano Zampini   const PetscScalar *vv;
185844cd7ae7SLois Curfman McInnes 
18593a40ed3dSBarry Smith   PetscFunctionBegin;
18609566063dSJacob Faibussowitsch   PetscCall(VecGetSize(v, &n));
18619566063dSJacob Faibussowitsch   PetscCall(VecGetArray(v, &x));
1862d0f46423SBarry Smith   len = PetscMin(A->rmap->n, A->cmap->n);
18639566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArrayRead(A, &vv));
186408401ef6SPierre Jolivet   PetscCheck(n == A->rmap->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Nonconforming mat and vec");
1865ad540459SPierre Jolivet   for (i = 0; i < len; i++) x[i] = vv[i * mat->lda + i];
18669566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArrayRead(A, &vv));
18679566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(v, &x));
18683ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1869289bc588SBarry Smith }
1870289bc588SBarry Smith 
1871d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatDiagonalScale_SeqDense(Mat A, Vec ll, Vec rr)
1872d71ae5a4SJacob Faibussowitsch {
1873c0bbcb79SLois Curfman McInnes   Mat_SeqDense      *mat = (Mat_SeqDense *)A->data;
1874f1ceaac6SMatthew G. Knepley   const PetscScalar *l, *r;
1875ca15aa20SStefano Zampini   PetscScalar        x, *v, *vv;
1876d0f46423SBarry Smith   PetscInt           i, j, m = A->rmap->n, n = A->cmap->n;
187755659b69SBarry Smith 
18783a40ed3dSBarry Smith   PetscFunctionBegin;
18799566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArray(A, &vv));
188028988994SBarry Smith   if (ll) {
18819566063dSJacob Faibussowitsch     PetscCall(VecGetSize(ll, &m));
18829566063dSJacob Faibussowitsch     PetscCall(VecGetArrayRead(ll, &l));
188308401ef6SPierre Jolivet     PetscCheck(m == A->rmap->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Left scaling vec wrong size");
1884da3a660dSBarry Smith     for (i = 0; i < m; i++) {
1885da3a660dSBarry Smith       x = l[i];
1886ca15aa20SStefano Zampini       v = vv + i;
18879371c9d4SSatish Balay       for (j = 0; j < n; j++) {
18889371c9d4SSatish Balay         (*v) *= x;
18899371c9d4SSatish Balay         v += mat->lda;
18909371c9d4SSatish Balay       }
1891da3a660dSBarry Smith     }
18929566063dSJacob Faibussowitsch     PetscCall(VecRestoreArrayRead(ll, &l));
18939566063dSJacob Faibussowitsch     PetscCall(PetscLogFlops(1.0 * n * m));
1894da3a660dSBarry Smith   }
189528988994SBarry Smith   if (rr) {
18969566063dSJacob Faibussowitsch     PetscCall(VecGetSize(rr, &n));
18979566063dSJacob Faibussowitsch     PetscCall(VecGetArrayRead(rr, &r));
189808401ef6SPierre Jolivet     PetscCheck(n == A->cmap->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Right scaling vec wrong size");
1899da3a660dSBarry Smith     for (i = 0; i < n; i++) {
1900da3a660dSBarry Smith       x = r[i];
1901ca15aa20SStefano Zampini       v = vv + i * mat->lda;
19022205254eSKarl Rupp       for (j = 0; j < m; j++) (*v++) *= x;
1903da3a660dSBarry Smith     }
19049566063dSJacob Faibussowitsch     PetscCall(VecRestoreArrayRead(rr, &r));
19059566063dSJacob Faibussowitsch     PetscCall(PetscLogFlops(1.0 * n * m));
1906da3a660dSBarry Smith   }
19079566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArray(A, &vv));
19083ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1909289bc588SBarry Smith }
1910289bc588SBarry Smith 
1911d71ae5a4SJacob Faibussowitsch PetscErrorCode MatNorm_SeqDense(Mat A, NormType type, PetscReal *nrm)
1912d71ae5a4SJacob Faibussowitsch {
1913c0bbcb79SLois Curfman McInnes   Mat_SeqDense *mat = (Mat_SeqDense *)A->data;
1914ca15aa20SStefano Zampini   PetscScalar  *v, *vv;
1915329f5518SBarry Smith   PetscReal     sum = 0.0;
191675f6d85dSStefano Zampini   PetscInt      lda, m = A->rmap->n, i, j;
191755659b69SBarry Smith 
19183a40ed3dSBarry Smith   PetscFunctionBegin;
19199566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArrayRead(A, (const PetscScalar **)&vv));
19209566063dSJacob Faibussowitsch   PetscCall(MatDenseGetLDA(A, &lda));
1921ca15aa20SStefano Zampini   v = vv;
1922289bc588SBarry Smith   if (type == NORM_FROBENIUS) {
1923a5ce6ee0Svictorle     if (lda > m) {
1924d0f46423SBarry Smith       for (j = 0; j < A->cmap->n; j++) {
1925ca15aa20SStefano Zampini         v = vv + j * lda;
1926a5ce6ee0Svictorle         for (i = 0; i < m; i++) {
19279371c9d4SSatish Balay           sum += PetscRealPart(PetscConj(*v) * (*v));
19289371c9d4SSatish Balay           v++;
1929a5ce6ee0Svictorle         }
1930a5ce6ee0Svictorle       }
1931a5ce6ee0Svictorle     } else {
1932570b7f6dSBarry Smith #if defined(PETSC_USE_REAL___FP16)
1933570b7f6dSBarry Smith       PetscBLASInt one = 1, cnt = A->cmap->n * A->rmap->n;
1934792fecdfSBarry Smith       PetscCallBLAS("BLASnrm2", *nrm = BLASnrm2_(&cnt, v, &one));
1935570b7f6dSBarry Smith     }
1936570b7f6dSBarry Smith #else
1937d0f46423SBarry Smith       for (i = 0; i < A->cmap->n * A->rmap->n; i++) {
19389371c9d4SSatish Balay         sum += PetscRealPart(PetscConj(*v) * (*v));
19399371c9d4SSatish Balay         v++;
1940289bc588SBarry Smith       }
1941a5ce6ee0Svictorle     }
19428f1a2a5eSBarry Smith     *nrm = PetscSqrtReal(sum);
1943570b7f6dSBarry Smith #endif
19449566063dSJacob Faibussowitsch     PetscCall(PetscLogFlops(2.0 * A->cmap->n * A->rmap->n));
19453a40ed3dSBarry Smith   } else if (type == NORM_1) {
1946064f8208SBarry Smith     *nrm = 0.0;
1947d0f46423SBarry Smith     for (j = 0; j < A->cmap->n; j++) {
1948ca15aa20SStefano Zampini       v   = vv + j * mat->lda;
1949289bc588SBarry Smith       sum = 0.0;
1950d0f46423SBarry Smith       for (i = 0; i < A->rmap->n; i++) {
19519371c9d4SSatish Balay         sum += PetscAbsScalar(*v);
19529371c9d4SSatish Balay         v++;
1953289bc588SBarry Smith       }
1954064f8208SBarry Smith       if (sum > *nrm) *nrm = sum;
1955289bc588SBarry Smith     }
19569566063dSJacob Faibussowitsch     PetscCall(PetscLogFlops(1.0 * A->cmap->n * A->rmap->n));
19573a40ed3dSBarry Smith   } else if (type == NORM_INFINITY) {
1958064f8208SBarry Smith     *nrm = 0.0;
1959d0f46423SBarry Smith     for (j = 0; j < A->rmap->n; j++) {
1960ca15aa20SStefano Zampini       v   = vv + j;
1961289bc588SBarry Smith       sum = 0.0;
1962d0f46423SBarry Smith       for (i = 0; i < A->cmap->n; i++) {
19639371c9d4SSatish Balay         sum += PetscAbsScalar(*v);
19649371c9d4SSatish Balay         v += mat->lda;
1965289bc588SBarry Smith       }
1966064f8208SBarry Smith       if (sum > *nrm) *nrm = sum;
1967289bc588SBarry Smith     }
19689566063dSJacob Faibussowitsch     PetscCall(PetscLogFlops(1.0 * A->cmap->n * A->rmap->n));
1969e7e72b3dSBarry Smith   } else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "No two norm");
19709566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArrayRead(A, (const PetscScalar **)&vv));
19713ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1972289bc588SBarry Smith }
1973289bc588SBarry Smith 
1974d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatSetOption_SeqDense(Mat A, MatOption op, PetscBool flg)
1975d71ae5a4SJacob Faibussowitsch {
1976c0bbcb79SLois Curfman McInnes   Mat_SeqDense *aij = (Mat_SeqDense *)A->data;
197767e560aaSBarry Smith 
19783a40ed3dSBarry Smith   PetscFunctionBegin;
1979b5a2b587SKris Buschelman   switch (op) {
1980d71ae5a4SJacob Faibussowitsch   case MAT_ROW_ORIENTED:
1981d71ae5a4SJacob Faibussowitsch     aij->roworiented = flg;
1982d71ae5a4SJacob Faibussowitsch     break;
1983512a5fc5SBarry Smith   case MAT_NEW_NONZERO_LOCATIONS:
1984b5a2b587SKris Buschelman   case MAT_NEW_NONZERO_LOCATION_ERR:
19853971808eSMatthew Knepley   case MAT_NEW_NONZERO_ALLOCATION_ERR:
19868c78258cSHong Zhang   case MAT_FORCE_DIAGONAL_ENTRIES:
198713fa8e87SLisandro Dalcin   case MAT_KEEP_NONZERO_PATTERN:
1988b5a2b587SKris Buschelman   case MAT_IGNORE_OFF_PROC_ENTRIES:
1989b5a2b587SKris Buschelman   case MAT_USE_HASH_TABLE:
19900f8fb01aSBarry Smith   case MAT_IGNORE_ZERO_ENTRIES:
19915021d80fSJed Brown   case MAT_IGNORE_LOWER_TRIANGULAR:
1992d71ae5a4SJacob Faibussowitsch   case MAT_SORTED_FULL:
1993d71ae5a4SJacob Faibussowitsch     PetscCall(PetscInfo(A, "Option %s ignored\n", MatOptions[op]));
1994d71ae5a4SJacob Faibussowitsch     break;
19955021d80fSJed Brown   case MAT_SPD:
199677e54ba9SKris Buschelman   case MAT_SYMMETRIC:
199777e54ba9SKris Buschelman   case MAT_STRUCTURALLY_SYMMETRIC:
19989a4540c5SBarry Smith   case MAT_HERMITIAN:
19999a4540c5SBarry Smith   case MAT_SYMMETRY_ETERNAL:
2000b94d7dedSBarry Smith   case MAT_STRUCTURAL_SYMMETRY_ETERNAL:
2001d71ae5a4SJacob Faibussowitsch   case MAT_SPD_ETERNAL:
2002d71ae5a4SJacob Faibussowitsch     break;
2003d71ae5a4SJacob Faibussowitsch   default:
2004d71ae5a4SJacob Faibussowitsch     SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "unknown option %s", MatOptions[op]);
20053a40ed3dSBarry Smith   }
20063ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2007289bc588SBarry Smith }
2008289bc588SBarry Smith 
2009d71ae5a4SJacob Faibussowitsch PetscErrorCode MatZeroEntries_SeqDense(Mat A)
2010d71ae5a4SJacob Faibussowitsch {
2011ec8511deSBarry Smith   Mat_SeqDense *l   = (Mat_SeqDense *)A->data;
20123d8925e7SStefano Zampini   PetscInt      lda = l->lda, m = A->rmap->n, n = A->cmap->n, j;
2013ca15aa20SStefano Zampini   PetscScalar  *v;
20143a40ed3dSBarry Smith 
20153a40ed3dSBarry Smith   PetscFunctionBegin;
20169566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArrayWrite(A, &v));
2017a5ce6ee0Svictorle   if (lda > m) {
201848a46eb9SPierre Jolivet     for (j = 0; j < n; j++) PetscCall(PetscArrayzero(v + j * lda, m));
2019a5ce6ee0Svictorle   } else {
20209566063dSJacob Faibussowitsch     PetscCall(PetscArrayzero(v, PetscInt64Mult(m, n)));
2021a5ce6ee0Svictorle   }
20229566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArrayWrite(A, &v));
20233ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
20246f0a148fSBarry Smith }
20256f0a148fSBarry Smith 
2026d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatZeroRows_SeqDense(Mat A, PetscInt N, const PetscInt rows[], PetscScalar diag, Vec x, Vec b)
2027d71ae5a4SJacob Faibussowitsch {
2028ec8511deSBarry Smith   Mat_SeqDense      *l = (Mat_SeqDense *)A->data;
2029b9679d65SBarry Smith   PetscInt           m = l->lda, n = A->cmap->n, i, j;
2030ca15aa20SStefano Zampini   PetscScalar       *slot, *bb, *v;
203197b48c8fSBarry Smith   const PetscScalar *xx;
203255659b69SBarry Smith 
20333a40ed3dSBarry Smith   PetscFunctionBegin;
203476bd3646SJed Brown   if (PetscDefined(USE_DEBUG)) {
2035b9679d65SBarry Smith     for (i = 0; i < N; i++) {
203608401ef6SPierre Jolivet       PetscCheck(rows[i] >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Negative row requested to be zeroed");
203708401ef6SPierre 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);
2038b9679d65SBarry Smith     }
203976bd3646SJed Brown   }
20403ba16761SJacob Faibussowitsch   if (!N) PetscFunctionReturn(PETSC_SUCCESS);
2041b9679d65SBarry Smith 
204297b48c8fSBarry Smith   /* fix right hand side if needed */
204397b48c8fSBarry Smith   if (x && b) {
20449566063dSJacob Faibussowitsch     PetscCall(VecGetArrayRead(x, &xx));
20459566063dSJacob Faibussowitsch     PetscCall(VecGetArray(b, &bb));
20462205254eSKarl Rupp     for (i = 0; i < N; i++) bb[rows[i]] = diag * xx[rows[i]];
20479566063dSJacob Faibussowitsch     PetscCall(VecRestoreArrayRead(x, &xx));
20489566063dSJacob Faibussowitsch     PetscCall(VecRestoreArray(b, &bb));
204997b48c8fSBarry Smith   }
205097b48c8fSBarry Smith 
20519566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArray(A, &v));
20526f0a148fSBarry Smith   for (i = 0; i < N; i++) {
2053ca15aa20SStefano Zampini     slot = v + rows[i];
20549371c9d4SSatish Balay     for (j = 0; j < n; j++) {
20559371c9d4SSatish Balay       *slot = 0.0;
20569371c9d4SSatish Balay       slot += m;
20579371c9d4SSatish Balay     }
20586f0a148fSBarry Smith   }
2059f4df32b1SMatthew Knepley   if (diag != 0.0) {
206008401ef6SPierre Jolivet     PetscCheck(A->rmap->n == A->cmap->n, PETSC_COMM_SELF, PETSC_ERR_SUP, "Only coded for square matrices");
20616f0a148fSBarry Smith     for (i = 0; i < N; i++) {
2062ca15aa20SStefano Zampini       slot  = v + (m + 1) * rows[i];
2063f4df32b1SMatthew Knepley       *slot = diag;
20646f0a148fSBarry Smith     }
20656f0a148fSBarry Smith   }
20669566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArray(A, &v));
20673ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
20686f0a148fSBarry Smith }
2069557bce09SLois Curfman McInnes 
2070d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatDenseGetLDA_SeqDense(Mat A, PetscInt *lda)
2071d71ae5a4SJacob Faibussowitsch {
207249a6ff4bSBarry Smith   Mat_SeqDense *mat = (Mat_SeqDense *)A->data;
207349a6ff4bSBarry Smith 
207449a6ff4bSBarry Smith   PetscFunctionBegin;
207549a6ff4bSBarry Smith   *lda = mat->lda;
20763ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
207749a6ff4bSBarry Smith }
207849a6ff4bSBarry Smith 
2079d71ae5a4SJacob Faibussowitsch PetscErrorCode MatDenseGetArray_SeqDense(Mat A, PetscScalar **array)
2080d71ae5a4SJacob Faibussowitsch {
2081c0bbcb79SLois Curfman McInnes   Mat_SeqDense *mat = (Mat_SeqDense *)A->data;
20823a40ed3dSBarry Smith 
20833a40ed3dSBarry Smith   PetscFunctionBegin;
208428b400f6SJacob Faibussowitsch   PetscCheck(!mat->matinuse, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Need to call MatDenseRestoreSubMatrix() first");
208564e87e97SBarry Smith   *array = mat->v;
20863ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
208764e87e97SBarry Smith }
20880754003eSLois Curfman McInnes 
2089d71ae5a4SJacob Faibussowitsch PetscErrorCode MatDenseRestoreArray_SeqDense(Mat A, PetscScalar **array)
2090d71ae5a4SJacob Faibussowitsch {
20913a40ed3dSBarry Smith   PetscFunctionBegin;
209275f6d85dSStefano Zampini   if (array) *array = NULL;
20933ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2094ff14e315SSatish Balay }
20950754003eSLois Curfman McInnes 
20960f74d2c1SSatish Balay /*@
209711a5261eSBarry Smith   MatDenseGetLDA - gets the leading dimension of the array returned from `MatDenseGetArray()`
209849a6ff4bSBarry Smith 
20992ef1f0ffSBarry Smith   Not Collective
210049a6ff4bSBarry Smith 
210149a6ff4bSBarry Smith   Input Parameter:
2102fe59aa6dSJacob Faibussowitsch . A - a `MATDENSE` or `MATDENSECUDA` matrix
210349a6ff4bSBarry Smith 
210449a6ff4bSBarry Smith   Output Parameter:
210549a6ff4bSBarry Smith . lda - the leading dimension
210649a6ff4bSBarry Smith 
210749a6ff4bSBarry Smith   Level: intermediate
210849a6ff4bSBarry Smith 
21091cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATDENSE`, `MATDENSECUDA`, `MatDenseGetArray()`, `MatDenseRestoreArray()`, `MatDenseGetArrayRead()`, `MatDenseRestoreArrayRead()`, `MatDenseSetLDA()`
211049a6ff4bSBarry Smith @*/
2111d71ae5a4SJacob Faibussowitsch PetscErrorCode MatDenseGetLDA(Mat A, PetscInt *lda)
2112d71ae5a4SJacob Faibussowitsch {
211349a6ff4bSBarry Smith   PetscFunctionBegin;
2114d5ea218eSStefano Zampini   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
21154f572ea9SToby Isaac   PetscAssertPointer(lda, 2);
211675f6d85dSStefano Zampini   MatCheckPreallocated(A, 1);
2117cac4c232SBarry Smith   PetscUseMethod(A, "MatDenseGetLDA_C", (Mat, PetscInt *), (A, lda));
21183ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
211949a6ff4bSBarry Smith }
212049a6ff4bSBarry Smith 
21210f74d2c1SSatish Balay /*@
212211a5261eSBarry Smith   MatDenseSetLDA - Sets the leading dimension of the array used by the `MATDENSE` matrix
2123ad16ce7aSStefano Zampini 
21242323109cSBarry Smith   Collective if the matrix layouts have not yet been setup
2125ad16ce7aSStefano Zampini 
2126d8d19677SJose E. Roman   Input Parameters:
2127fe59aa6dSJacob Faibussowitsch + A   - a `MATDENSE` or `MATDENSECUDA` matrix
2128ad16ce7aSStefano Zampini - lda - the leading dimension
2129ad16ce7aSStefano Zampini 
2130ad16ce7aSStefano Zampini   Level: intermediate
2131ad16ce7aSStefano Zampini 
21321cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATDENSE`, `MATDENSECUDA`, `MatDenseGetArray()`, `MatDenseRestoreArray()`, `MatDenseGetArrayRead()`, `MatDenseRestoreArrayRead()`, `MatDenseGetLDA()`
2133ad16ce7aSStefano Zampini @*/
2134d71ae5a4SJacob Faibussowitsch PetscErrorCode MatDenseSetLDA(Mat A, PetscInt lda)
2135d71ae5a4SJacob Faibussowitsch {
2136ad16ce7aSStefano Zampini   PetscFunctionBegin;
2137ad16ce7aSStefano Zampini   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
2138cac4c232SBarry Smith   PetscTryMethod(A, "MatDenseSetLDA_C", (Mat, PetscInt), (A, lda));
21393ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2140ad16ce7aSStefano Zampini }
2141ad16ce7aSStefano Zampini 
2142ad16ce7aSStefano Zampini /*@C
214311a5261eSBarry Smith   MatDenseGetArray - gives read-write access to the array where the data for a `MATDENSE` matrix is stored
214473a71a0fSBarry Smith 
2145c3339decSBarry Smith   Logically Collective
214673a71a0fSBarry Smith 
214773a71a0fSBarry Smith   Input Parameter:
2148fe59aa6dSJacob Faibussowitsch . A - a dense matrix
214973a71a0fSBarry Smith 
215073a71a0fSBarry Smith   Output Parameter:
215173a71a0fSBarry Smith . array - pointer to the data
215273a71a0fSBarry Smith 
215373a71a0fSBarry Smith   Level: intermediate
215473a71a0fSBarry Smith 
2155fe59aa6dSJacob Faibussowitsch   Fortran Notes:
21560ab4885dSBarry Smith   `MatDenseGetArray()` Fortran binding is deprecated (since PETSc 3.19), use `MatDenseGetArrayF90()`
21570ab4885dSBarry Smith 
21581cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATDENSE`, `MatDenseRestoreArray()`, `MatDenseGetArrayRead()`, `MatDenseRestoreArrayRead()`, `MatDenseGetArrayWrite()`, `MatDenseRestoreArrayWrite()`
215973a71a0fSBarry Smith @*/
2160d71ae5a4SJacob Faibussowitsch PetscErrorCode MatDenseGetArray(Mat A, PetscScalar **array)
2161d71ae5a4SJacob Faibussowitsch {
216273a71a0fSBarry Smith   PetscFunctionBegin;
2163d5ea218eSStefano Zampini   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
21644f572ea9SToby Isaac   PetscAssertPointer(array, 2);
2165cac4c232SBarry Smith   PetscUseMethod(A, "MatDenseGetArray_C", (Mat, PetscScalar **), (A, array));
21663ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
216773a71a0fSBarry Smith }
216873a71a0fSBarry Smith 
2169dec5eb66SMatthew G Knepley /*@C
217011a5261eSBarry Smith   MatDenseRestoreArray - returns access to the array where the data for a `MATDENSE` matrix is stored obtained by `MatDenseGetArray()`
217173a71a0fSBarry Smith 
2172c3339decSBarry Smith   Logically Collective
21738572280aSBarry Smith 
21748572280aSBarry Smith   Input Parameters:
2175fe59aa6dSJacob Faibussowitsch + A     - a dense matrix
21762ef1f0ffSBarry Smith - array - pointer to the data (may be `NULL`)
21778572280aSBarry Smith 
21788572280aSBarry Smith   Level: intermediate
21798572280aSBarry Smith 
2180fe59aa6dSJacob Faibussowitsch   Fortran Notes:
21810ab4885dSBarry Smith   `MatDenseRestoreArray()` Fortran binding is deprecated (since PETSc 3.19), use `MatDenseRestoreArrayF90()`
21820ab4885dSBarry Smith 
21831cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATDENSE`, `MatDenseGetArray()`, `MatDenseGetArrayRead()`, `MatDenseRestoreArrayRead()`, `MatDenseGetArrayWrite()`, `MatDenseRestoreArrayWrite()`
21848572280aSBarry Smith @*/
2185d71ae5a4SJacob Faibussowitsch PetscErrorCode MatDenseRestoreArray(Mat A, PetscScalar **array)
2186d71ae5a4SJacob Faibussowitsch {
21878572280aSBarry Smith   PetscFunctionBegin;
2188d5ea218eSStefano Zampini   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
21894f572ea9SToby Isaac   if (array) PetscAssertPointer(array, 2);
2190cac4c232SBarry Smith   PetscUseMethod(A, "MatDenseRestoreArray_C", (Mat, PetscScalar **), (A, array));
21919566063dSJacob Faibussowitsch   PetscCall(PetscObjectStateIncrease((PetscObject)A));
219247d993e7Ssuyashtn #if defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
2193637a0070SStefano Zampini   A->offloadmask = PETSC_OFFLOAD_CPU;
2194637a0070SStefano Zampini #endif
21953ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
21968572280aSBarry Smith }
21978572280aSBarry Smith 
21988572280aSBarry Smith /*@C
219911a5261eSBarry Smith   MatDenseGetArrayRead - gives read-only access to the array where the data for a `MATDENSE` matrix is stored
22008572280aSBarry Smith 
2201fb850c59SBarry Smith   Not Collective
22028572280aSBarry Smith 
22038572280aSBarry Smith   Input Parameter:
2204fe59aa6dSJacob Faibussowitsch . A - a dense matrix
22058572280aSBarry Smith 
22068572280aSBarry Smith   Output Parameter:
22078572280aSBarry Smith . array - pointer to the data
22088572280aSBarry Smith 
22098572280aSBarry Smith   Level: intermediate
22108572280aSBarry Smith 
22111cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATDENSE`, `MatDenseRestoreArrayRead()`, `MatDenseGetArray()`, `MatDenseRestoreArray()`, `MatDenseGetArrayWrite()`, `MatDenseRestoreArrayWrite()`
22128572280aSBarry Smith @*/
2213d71ae5a4SJacob Faibussowitsch PetscErrorCode MatDenseGetArrayRead(Mat A, const PetscScalar **array)
2214d71ae5a4SJacob Faibussowitsch {
22158572280aSBarry Smith   PetscFunctionBegin;
2216d5ea218eSStefano Zampini   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
22174f572ea9SToby Isaac   PetscAssertPointer(array, 2);
22185c0db29aSPierre Jolivet   PetscUseMethod(A, "MatDenseGetArrayRead_C", (Mat, PetscScalar **), (A, (PetscScalar **)array));
22193ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
22208572280aSBarry Smith }
22218572280aSBarry Smith 
22228572280aSBarry Smith /*@C
222311a5261eSBarry Smith   MatDenseRestoreArrayRead - returns access to the array where the data for a `MATDENSE` matrix is stored obtained by `MatDenseGetArrayRead()`
22248572280aSBarry Smith 
2225fb850c59SBarry Smith   Not Collective
222673a71a0fSBarry Smith 
222773a71a0fSBarry Smith   Input Parameters:
2228fe59aa6dSJacob Faibussowitsch + A     - a dense matrix
22292ef1f0ffSBarry Smith - array - pointer to the data (may be `NULL`)
223073a71a0fSBarry Smith 
223173a71a0fSBarry Smith   Level: intermediate
223273a71a0fSBarry Smith 
22331cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATDENSE`, `MatDenseGetArrayRead()`, `MatDenseGetArray()`, `MatDenseRestoreArray()`, `MatDenseGetArrayWrite()`, `MatDenseRestoreArrayWrite()`
223473a71a0fSBarry Smith @*/
2235d71ae5a4SJacob Faibussowitsch PetscErrorCode MatDenseRestoreArrayRead(Mat A, const PetscScalar **array)
2236d71ae5a4SJacob Faibussowitsch {
223773a71a0fSBarry Smith   PetscFunctionBegin;
2238d5ea218eSStefano Zampini   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
22394f572ea9SToby Isaac   if (array) PetscAssertPointer(array, 2);
22405c0db29aSPierre Jolivet   PetscUseMethod(A, "MatDenseRestoreArrayRead_C", (Mat, PetscScalar **), (A, (PetscScalar **)array));
22413ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
224273a71a0fSBarry Smith }
224373a71a0fSBarry Smith 
22446947451fSStefano Zampini /*@C
224511a5261eSBarry Smith   MatDenseGetArrayWrite - gives write-only access to the array where the data for a `MATDENSE` matrix is stored
22466947451fSStefano Zampini 
2247fb850c59SBarry Smith   Not Collective
22486947451fSStefano Zampini 
22496947451fSStefano Zampini   Input Parameter:
2250fe59aa6dSJacob Faibussowitsch . A - a dense matrix
22516947451fSStefano Zampini 
22526947451fSStefano Zampini   Output Parameter:
22536947451fSStefano Zampini . array - pointer to the data
22546947451fSStefano Zampini 
22556947451fSStefano Zampini   Level: intermediate
22566947451fSStefano Zampini 
22571cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATDENSE`, `MatDenseRestoreArrayWrite()`, `MatDenseGetArray()`, `MatDenseRestoreArray()`, `MatDenseGetArrayRead()`, `MatDenseRestoreArrayRead()`
22586947451fSStefano Zampini @*/
2259d71ae5a4SJacob Faibussowitsch PetscErrorCode MatDenseGetArrayWrite(Mat A, PetscScalar **array)
2260d71ae5a4SJacob Faibussowitsch {
22616947451fSStefano Zampini   PetscFunctionBegin;
2262d5ea218eSStefano Zampini   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
22634f572ea9SToby Isaac   PetscAssertPointer(array, 2);
2264cac4c232SBarry Smith   PetscUseMethod(A, "MatDenseGetArrayWrite_C", (Mat, PetscScalar **), (A, array));
22653ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
22666947451fSStefano Zampini }
22676947451fSStefano Zampini 
22686947451fSStefano Zampini /*@C
226911a5261eSBarry Smith   MatDenseRestoreArrayWrite - returns access to the array where the data for a `MATDENSE` matrix is stored obtained by `MatDenseGetArrayWrite()`
22706947451fSStefano Zampini 
2271fb850c59SBarry Smith   Not Collective
22726947451fSStefano Zampini 
22736947451fSStefano Zampini   Input Parameters:
2274fe59aa6dSJacob Faibussowitsch + A     - a dense matrix
22752ef1f0ffSBarry Smith - array - pointer to the data (may be `NULL`)
22766947451fSStefano Zampini 
22776947451fSStefano Zampini   Level: intermediate
22786947451fSStefano Zampini 
22791cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATDENSE`, `MatDenseGetArrayWrite()`, `MatDenseGetArray()`, `MatDenseRestoreArray()`, `MatDenseGetArrayRead()`, `MatDenseRestoreArrayRead()`
22806947451fSStefano Zampini @*/
2281d71ae5a4SJacob Faibussowitsch PetscErrorCode MatDenseRestoreArrayWrite(Mat A, PetscScalar **array)
2282d71ae5a4SJacob Faibussowitsch {
22836947451fSStefano Zampini   PetscFunctionBegin;
2284d5ea218eSStefano Zampini   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
22854f572ea9SToby Isaac   if (array) PetscAssertPointer(array, 2);
2286cac4c232SBarry Smith   PetscUseMethod(A, "MatDenseRestoreArrayWrite_C", (Mat, PetscScalar **), (A, array));
22879566063dSJacob Faibussowitsch   PetscCall(PetscObjectStateIncrease((PetscObject)A));
228847d993e7Ssuyashtn #if defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
22896947451fSStefano Zampini   A->offloadmask = PETSC_OFFLOAD_CPU;
22906947451fSStefano Zampini #endif
22913ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
22926947451fSStefano Zampini }
22936947451fSStefano Zampini 
2294cd3f9d89SJunchao Zhang /*@C
2295cd3f9d89SJunchao Zhang   MatDenseGetArrayAndMemType - gives read-write access to the array where the data for a `MATDENSE` matrix is stored
2296cd3f9d89SJunchao Zhang 
2297cd3f9d89SJunchao Zhang   Logically Collective
2298cd3f9d89SJunchao Zhang 
2299cd3f9d89SJunchao Zhang   Input Parameter:
2300fe59aa6dSJacob Faibussowitsch . A - a dense matrix
2301cd3f9d89SJunchao Zhang 
2302cd3f9d89SJunchao Zhang   Output Parameters:
2303cd3f9d89SJunchao Zhang + array - pointer to the data
2304cd3f9d89SJunchao Zhang - mtype - memory type of the returned pointer
2305cd3f9d89SJunchao Zhang 
2306cd3f9d89SJunchao Zhang   Level: intermediate
2307cd3f9d89SJunchao Zhang 
2308fb850c59SBarry Smith   Note:
23092ef1f0ffSBarry Smith   If the matrix is of a device type such as `MATDENSECUDA`, `MATDENSEHIP`, etc.,
23102ef1f0ffSBarry Smith   an array on device is always returned and is guaranteed to contain the matrix's latest data.
23112ef1f0ffSBarry Smith 
23121cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATDENSE`, `MatDenseRestoreArrayAndMemType()`, `MatDenseGetArrayReadAndMemType()`, `MatDenseGetArrayWriteAndMemType()`, `MatDenseGetArrayRead()`,
2313cd3f9d89SJunchao Zhang    `MatDenseRestoreArrayRead()`, `MatDenseGetArrayWrite()`, `MatDenseRestoreArrayWrite()`, `MatSeqAIJGetCSRAndMemType()`
2314cd3f9d89SJunchao Zhang @*/
2315cd3f9d89SJunchao Zhang PetscErrorCode MatDenseGetArrayAndMemType(Mat A, PetscScalar **array, PetscMemType *mtype)
2316cd3f9d89SJunchao Zhang {
2317cd3f9d89SJunchao Zhang   PetscBool isMPI;
2318cd3f9d89SJunchao Zhang 
2319cd3f9d89SJunchao Zhang   PetscFunctionBegin;
2320cd3f9d89SJunchao Zhang   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
23214f572ea9SToby Isaac   PetscAssertPointer(array, 2);
2322e865de01SJunchao 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 */
2323cd3f9d89SJunchao Zhang   PetscCall(PetscObjectBaseTypeCompare((PetscObject)A, MATMPIDENSE, &isMPI));
2324cd3f9d89SJunchao Zhang   if (isMPI) {
2325cd3f9d89SJunchao Zhang     /* Dispatch here so that the code can be reused for all subclasses of MATDENSE */
2326cd3f9d89SJunchao Zhang     PetscCall(MatDenseGetArrayAndMemType(((Mat_MPIDense *)A->data)->A, array, mtype));
2327cd3f9d89SJunchao Zhang   } else {
2328cd3f9d89SJunchao Zhang     PetscErrorCode (*fptr)(Mat, PetscScalar **, PetscMemType *);
23293ba16761SJacob Faibussowitsch 
23303ba16761SJacob Faibussowitsch     PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatDenseGetArrayAndMemType_C", &fptr));
2331cd3f9d89SJunchao Zhang     if (fptr) {
2332cd3f9d89SJunchao Zhang       PetscCall((*fptr)(A, array, mtype));
2333cd3f9d89SJunchao Zhang     } else {
2334cd3f9d89SJunchao Zhang       PetscUseMethod(A, "MatDenseGetArray_C", (Mat, PetscScalar **), (A, array));
2335cd3f9d89SJunchao Zhang       if (mtype) *mtype = PETSC_MEMTYPE_HOST;
2336cd3f9d89SJunchao Zhang     }
2337cd3f9d89SJunchao Zhang   }
23383ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2339cd3f9d89SJunchao Zhang }
2340cd3f9d89SJunchao Zhang 
2341cd3f9d89SJunchao Zhang /*@C
2342cd3f9d89SJunchao Zhang   MatDenseRestoreArrayAndMemType - returns access to the array that is obtained by `MatDenseGetArrayAndMemType()`
2343cd3f9d89SJunchao Zhang 
2344cd3f9d89SJunchao Zhang   Logically Collective
2345cd3f9d89SJunchao Zhang 
2346cd3f9d89SJunchao Zhang   Input Parameters:
2347fe59aa6dSJacob Faibussowitsch + A     - a dense matrix
2348cd3f9d89SJunchao Zhang - array - pointer to the data
2349cd3f9d89SJunchao Zhang 
2350cd3f9d89SJunchao Zhang   Level: intermediate
2351cd3f9d89SJunchao Zhang 
23521cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATDENSE`, `MatDenseGetArrayAndMemType()`, `MatDenseGetArray()`, `MatDenseGetArrayRead()`, `MatDenseRestoreArrayRead()`, `MatDenseGetArrayWrite()`, `MatDenseRestoreArrayWrite()`
2353cd3f9d89SJunchao Zhang @*/
2354cd3f9d89SJunchao Zhang PetscErrorCode MatDenseRestoreArrayAndMemType(Mat A, PetscScalar **array)
2355cd3f9d89SJunchao Zhang {
2356cd3f9d89SJunchao Zhang   PetscBool isMPI;
2357cd3f9d89SJunchao Zhang 
2358cd3f9d89SJunchao Zhang   PetscFunctionBegin;
2359cd3f9d89SJunchao Zhang   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
23604f572ea9SToby Isaac   PetscAssertPointer(array, 2);
2361cd3f9d89SJunchao Zhang   PetscCall(PetscObjectBaseTypeCompare((PetscObject)A, MATMPIDENSE, &isMPI));
2362cd3f9d89SJunchao Zhang   if (isMPI) {
2363cd3f9d89SJunchao Zhang     PetscCall(MatDenseRestoreArrayAndMemType(((Mat_MPIDense *)A->data)->A, array));
2364cd3f9d89SJunchao Zhang   } else {
2365cd3f9d89SJunchao Zhang     PetscErrorCode (*fptr)(Mat, PetscScalar **);
23663ba16761SJacob Faibussowitsch 
23673ba16761SJacob Faibussowitsch     PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatDenseRestoreArrayAndMemType_C", &fptr));
2368cd3f9d89SJunchao Zhang     if (fptr) {
2369cd3f9d89SJunchao Zhang       PetscCall((*fptr)(A, array));
2370cd3f9d89SJunchao Zhang     } else {
2371cd3f9d89SJunchao Zhang       PetscUseMethod(A, "MatDenseRestoreArray_C", (Mat, PetscScalar **), (A, array));
2372cd3f9d89SJunchao Zhang     }
2373cd3f9d89SJunchao Zhang     *array = NULL;
2374cd3f9d89SJunchao Zhang   }
2375cd3f9d89SJunchao Zhang   PetscCall(PetscObjectStateIncrease((PetscObject)A));
23763ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2377cd3f9d89SJunchao Zhang }
2378cd3f9d89SJunchao Zhang 
2379cd3f9d89SJunchao Zhang /*@C
2380cd3f9d89SJunchao Zhang   MatDenseGetArrayReadAndMemType - gives read-only access to the array where the data for a `MATDENSE` matrix is stored
2381cd3f9d89SJunchao Zhang 
2382cd3f9d89SJunchao Zhang   Logically Collective
2383cd3f9d89SJunchao Zhang 
2384cd3f9d89SJunchao Zhang   Input Parameter:
2385fe59aa6dSJacob Faibussowitsch . A - a dense matrix
2386cd3f9d89SJunchao Zhang 
2387cd3f9d89SJunchao Zhang   Output Parameters:
2388cd3f9d89SJunchao Zhang + array - pointer to the data
2389cd3f9d89SJunchao Zhang - mtype - memory type of the returned pointer
2390cd3f9d89SJunchao Zhang 
2391cd3f9d89SJunchao Zhang   Level: intermediate
2392cd3f9d89SJunchao Zhang 
2393fb850c59SBarry Smith   Note:
23942ef1f0ffSBarry Smith   If the matrix is of a device type such as `MATDENSECUDA`, `MATDENSEHIP`, etc.,
23952ef1f0ffSBarry Smith   an array on device is always returned and is guaranteed to contain the matrix's latest data.
23962ef1f0ffSBarry Smith 
23971cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATDENSE`, `MatDenseRestoreArrayReadAndMemType()`, `MatDenseGetArrayWriteAndMemType()`,
2398cd3f9d89SJunchao Zhang    `MatDenseGetArrayRead()`, `MatDenseRestoreArrayRead()`, `MatDenseGetArrayWrite()`, `MatDenseRestoreArrayWrite()`, `MatSeqAIJGetCSRAndMemType()`
2399cd3f9d89SJunchao Zhang @*/
2400cd3f9d89SJunchao Zhang PetscErrorCode MatDenseGetArrayReadAndMemType(Mat A, const PetscScalar **array, PetscMemType *mtype)
2401cd3f9d89SJunchao Zhang {
2402cd3f9d89SJunchao Zhang   PetscBool isMPI;
2403cd3f9d89SJunchao Zhang 
2404cd3f9d89SJunchao Zhang   PetscFunctionBegin;
2405cd3f9d89SJunchao Zhang   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
24064f572ea9SToby Isaac   PetscAssertPointer(array, 2);
2407e865de01SJunchao 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 */
2408cd3f9d89SJunchao Zhang   PetscCall(PetscObjectBaseTypeCompare((PetscObject)A, MATMPIDENSE, &isMPI));
2409cd3f9d89SJunchao Zhang   if (isMPI) { /* Dispatch here so that the code can be reused for all subclasses of MATDENSE */
2410cd3f9d89SJunchao Zhang     PetscCall(MatDenseGetArrayReadAndMemType(((Mat_MPIDense *)A->data)->A, array, mtype));
2411cd3f9d89SJunchao Zhang   } else {
2412cd3f9d89SJunchao Zhang     PetscErrorCode (*fptr)(Mat, const PetscScalar **, PetscMemType *);
24133ba16761SJacob Faibussowitsch 
24143ba16761SJacob Faibussowitsch     PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatDenseGetArrayReadAndMemType_C", &fptr));
2415cd3f9d89SJunchao Zhang     if (fptr) {
2416cd3f9d89SJunchao Zhang       PetscCall((*fptr)(A, array, mtype));
2417cd3f9d89SJunchao Zhang     } else {
24185c0db29aSPierre Jolivet       PetscUseMethod(A, "MatDenseGetArrayRead_C", (Mat, PetscScalar **), (A, (PetscScalar **)array));
2419cd3f9d89SJunchao Zhang       if (mtype) *mtype = PETSC_MEMTYPE_HOST;
2420cd3f9d89SJunchao Zhang     }
2421cd3f9d89SJunchao Zhang   }
24223ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2423cd3f9d89SJunchao Zhang }
2424cd3f9d89SJunchao Zhang 
2425cd3f9d89SJunchao Zhang /*@C
2426cd3f9d89SJunchao Zhang   MatDenseRestoreArrayReadAndMemType - returns access to the array that is obtained by `MatDenseGetArrayReadAndMemType()`
2427cd3f9d89SJunchao Zhang 
2428cd3f9d89SJunchao Zhang   Logically Collective
2429cd3f9d89SJunchao Zhang 
2430cd3f9d89SJunchao Zhang   Input Parameters:
2431fe59aa6dSJacob Faibussowitsch + A     - a dense matrix
2432cd3f9d89SJunchao Zhang - array - pointer to the data
2433cd3f9d89SJunchao Zhang 
2434cd3f9d89SJunchao Zhang   Level: intermediate
2435cd3f9d89SJunchao Zhang 
24361cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATDENSE`, `MatDenseGetArrayReadAndMemType()`, `MatDenseGetArray()`, `MatDenseGetArrayRead()`, `MatDenseRestoreArrayRead()`, `MatDenseGetArrayWrite()`, `MatDenseRestoreArrayWrite()`
2437cd3f9d89SJunchao Zhang @*/
2438cd3f9d89SJunchao Zhang PetscErrorCode MatDenseRestoreArrayReadAndMemType(Mat A, const PetscScalar **array)
2439cd3f9d89SJunchao Zhang {
2440cd3f9d89SJunchao Zhang   PetscBool isMPI;
2441cd3f9d89SJunchao Zhang 
2442cd3f9d89SJunchao Zhang   PetscFunctionBegin;
2443cd3f9d89SJunchao Zhang   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
24444f572ea9SToby Isaac   PetscAssertPointer(array, 2);
2445cd3f9d89SJunchao Zhang   PetscCall(PetscObjectBaseTypeCompare((PetscObject)A, MATMPIDENSE, &isMPI));
2446cd3f9d89SJunchao Zhang   if (isMPI) {
2447cd3f9d89SJunchao Zhang     PetscCall(MatDenseRestoreArrayReadAndMemType(((Mat_MPIDense *)A->data)->A, array));
2448cd3f9d89SJunchao Zhang   } else {
2449cd3f9d89SJunchao Zhang     PetscErrorCode (*fptr)(Mat, const PetscScalar **);
24503ba16761SJacob Faibussowitsch 
24513ba16761SJacob Faibussowitsch     PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatDenseRestoreArrayReadAndMemType_C", &fptr));
2452cd3f9d89SJunchao Zhang     if (fptr) {
2453cd3f9d89SJunchao Zhang       PetscCall((*fptr)(A, array));
2454cd3f9d89SJunchao Zhang     } else {
24555c0db29aSPierre Jolivet       PetscUseMethod(A, "MatDenseRestoreArrayRead_C", (Mat, PetscScalar **), (A, (PetscScalar **)array));
2456cd3f9d89SJunchao Zhang     }
2457cd3f9d89SJunchao Zhang     *array = NULL;
2458cd3f9d89SJunchao Zhang   }
24593ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2460cd3f9d89SJunchao Zhang }
2461cd3f9d89SJunchao Zhang 
2462cd3f9d89SJunchao Zhang /*@C
2463cd3f9d89SJunchao Zhang   MatDenseGetArrayWriteAndMemType - gives write-only access to the array where the data for a `MATDENSE` matrix is stored
2464cd3f9d89SJunchao Zhang 
2465cd3f9d89SJunchao Zhang   Logically Collective
2466cd3f9d89SJunchao Zhang 
2467cd3f9d89SJunchao Zhang   Input Parameter:
2468fe59aa6dSJacob Faibussowitsch . A - a dense matrix
2469cd3f9d89SJunchao Zhang 
2470cd3f9d89SJunchao Zhang   Output Parameters:
2471cd3f9d89SJunchao Zhang + array - pointer to the data
2472cd3f9d89SJunchao Zhang - mtype - memory type of the returned pointer
2473cd3f9d89SJunchao Zhang 
2474cd3f9d89SJunchao Zhang   Level: intermediate
2475cd3f9d89SJunchao Zhang 
2476fb850c59SBarry Smith   Note:
24772ef1f0ffSBarry Smith   If the matrix is of a device type such as `MATDENSECUDA`, `MATDENSEHIP`, etc.,
24782ef1f0ffSBarry Smith   an array on device is always returned and is guaranteed to contain the matrix's latest data.
24792ef1f0ffSBarry Smith 
24801cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATDENSE`, `MatDenseRestoreArrayWriteAndMemType()`, `MatDenseGetArrayReadAndMemType()`, `MatDenseGetArrayRead()`,
2481cd3f9d89SJunchao Zhang   `MatDenseRestoreArrayRead()`, `MatDenseGetArrayWrite()`, `MatDenseRestoreArrayWrite()`, `MatSeqAIJGetCSRAndMemType()`
2482cd3f9d89SJunchao Zhang @*/
2483cd3f9d89SJunchao Zhang PetscErrorCode MatDenseGetArrayWriteAndMemType(Mat A, PetscScalar **array, PetscMemType *mtype)
2484cd3f9d89SJunchao Zhang {
2485cd3f9d89SJunchao Zhang   PetscBool isMPI;
2486cd3f9d89SJunchao Zhang 
2487cd3f9d89SJunchao Zhang   PetscFunctionBegin;
2488cd3f9d89SJunchao Zhang   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
24894f572ea9SToby Isaac   PetscAssertPointer(array, 2);
2490e865de01SJunchao 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 */
2491cd3f9d89SJunchao Zhang   PetscCall(PetscObjectBaseTypeCompare((PetscObject)A, MATMPIDENSE, &isMPI));
2492cd3f9d89SJunchao Zhang   if (isMPI) {
2493cd3f9d89SJunchao Zhang     PetscCall(MatDenseGetArrayWriteAndMemType(((Mat_MPIDense *)A->data)->A, array, mtype));
2494cd3f9d89SJunchao Zhang   } else {
2495cd3f9d89SJunchao Zhang     PetscErrorCode (*fptr)(Mat, PetscScalar **, PetscMemType *);
24963ba16761SJacob Faibussowitsch 
24973ba16761SJacob Faibussowitsch     PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatDenseGetArrayWriteAndMemType_C", &fptr));
2498cd3f9d89SJunchao Zhang     if (fptr) {
2499cd3f9d89SJunchao Zhang       PetscCall((*fptr)(A, array, mtype));
2500cd3f9d89SJunchao Zhang     } else {
2501cd3f9d89SJunchao Zhang       PetscUseMethod(A, "MatDenseGetArrayWrite_C", (Mat, PetscScalar **), (A, array));
2502cd3f9d89SJunchao Zhang       if (mtype) *mtype = PETSC_MEMTYPE_HOST;
2503cd3f9d89SJunchao Zhang     }
2504cd3f9d89SJunchao Zhang   }
25053ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2506cd3f9d89SJunchao Zhang }
2507cd3f9d89SJunchao Zhang 
2508cd3f9d89SJunchao Zhang /*@C
2509cd3f9d89SJunchao Zhang   MatDenseRestoreArrayWriteAndMemType - returns access to the array that is obtained by `MatDenseGetArrayReadAndMemType()`
2510cd3f9d89SJunchao Zhang 
2511cd3f9d89SJunchao Zhang   Logically Collective
2512cd3f9d89SJunchao Zhang 
2513cd3f9d89SJunchao Zhang   Input Parameters:
2514fe59aa6dSJacob Faibussowitsch + A     - a dense matrix
2515cd3f9d89SJunchao Zhang - array - pointer to the data
2516cd3f9d89SJunchao Zhang 
2517cd3f9d89SJunchao Zhang   Level: intermediate
2518cd3f9d89SJunchao Zhang 
25191cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATDENSE`, `MatDenseGetArrayWriteAndMemType()`, `MatDenseGetArray()`, `MatDenseGetArrayRead()`, `MatDenseRestoreArrayRead()`, `MatDenseGetArrayWrite()`, `MatDenseRestoreArrayWrite()`
2520cd3f9d89SJunchao Zhang @*/
2521cd3f9d89SJunchao Zhang PetscErrorCode MatDenseRestoreArrayWriteAndMemType(Mat A, PetscScalar **array)
2522cd3f9d89SJunchao Zhang {
2523cd3f9d89SJunchao Zhang   PetscBool isMPI;
2524cd3f9d89SJunchao Zhang 
2525cd3f9d89SJunchao Zhang   PetscFunctionBegin;
2526cd3f9d89SJunchao Zhang   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
25274f572ea9SToby Isaac   PetscAssertPointer(array, 2);
2528cd3f9d89SJunchao Zhang   PetscCall(PetscObjectBaseTypeCompare((PetscObject)A, MATMPIDENSE, &isMPI));
2529cd3f9d89SJunchao Zhang   if (isMPI) {
2530cd3f9d89SJunchao Zhang     PetscCall(MatDenseRestoreArrayWriteAndMemType(((Mat_MPIDense *)A->data)->A, array));
2531cd3f9d89SJunchao Zhang   } else {
2532cd3f9d89SJunchao Zhang     PetscErrorCode (*fptr)(Mat, PetscScalar **);
25333ba16761SJacob Faibussowitsch 
25343ba16761SJacob Faibussowitsch     PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatDenseRestoreArrayWriteAndMemType_C", &fptr));
2535cd3f9d89SJunchao Zhang     if (fptr) {
2536cd3f9d89SJunchao Zhang       PetscCall((*fptr)(A, array));
2537cd3f9d89SJunchao Zhang     } else {
2538cd3f9d89SJunchao Zhang       PetscUseMethod(A, "MatDenseRestoreArrayWrite_C", (Mat, PetscScalar **), (A, array));
2539cd3f9d89SJunchao Zhang     }
2540cd3f9d89SJunchao Zhang     *array = NULL;
2541cd3f9d89SJunchao Zhang   }
2542cd3f9d89SJunchao Zhang   PetscCall(PetscObjectStateIncrease((PetscObject)A));
25433ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2544cd3f9d89SJunchao Zhang }
2545cd3f9d89SJunchao Zhang 
2546d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatCreateSubMatrix_SeqDense(Mat A, IS isrow, IS iscol, MatReuse scall, Mat *B)
2547d71ae5a4SJacob Faibussowitsch {
2548c0bbcb79SLois Curfman McInnes   Mat_SeqDense   *mat = (Mat_SeqDense *)A->data;
2549bf5a80bcSToby Isaac   PetscInt        i, j, nrows, ncols, ldb;
25505d0c19d7SBarry Smith   const PetscInt *irow, *icol;
255187828ca2SBarry Smith   PetscScalar    *av, *bv, *v = mat->v;
25520754003eSLois Curfman McInnes   Mat             newmat;
25530754003eSLois Curfman McInnes 
25543a40ed3dSBarry Smith   PetscFunctionBegin;
25559566063dSJacob Faibussowitsch   PetscCall(ISGetIndices(isrow, &irow));
25569566063dSJacob Faibussowitsch   PetscCall(ISGetIndices(iscol, &icol));
25579566063dSJacob Faibussowitsch   PetscCall(ISGetLocalSize(isrow, &nrows));
25589566063dSJacob Faibussowitsch   PetscCall(ISGetLocalSize(iscol, &ncols));
25590754003eSLois Curfman McInnes 
2560182d2002SSatish Balay   /* Check submatrixcall */
2561182d2002SSatish Balay   if (scall == MAT_REUSE_MATRIX) {
256213f74950SBarry Smith     PetscInt n_cols, n_rows;
25639566063dSJacob Faibussowitsch     PetscCall(MatGetSize(*B, &n_rows, &n_cols));
256421a2c019SBarry Smith     if (n_rows != nrows || n_cols != ncols) {
2565f746d493SDmitry Karpeev       /* resize the result matrix to match number of requested rows/columns */
25669566063dSJacob Faibussowitsch       PetscCall(MatSetSizes(*B, nrows, ncols, nrows, ncols));
256721a2c019SBarry Smith     }
2568182d2002SSatish Balay     newmat = *B;
2569182d2002SSatish Balay   } else {
25700754003eSLois Curfman McInnes     /* Create and fill new matrix */
25719566063dSJacob Faibussowitsch     PetscCall(MatCreate(PetscObjectComm((PetscObject)A), &newmat));
25729566063dSJacob Faibussowitsch     PetscCall(MatSetSizes(newmat, nrows, ncols, nrows, ncols));
25739566063dSJacob Faibussowitsch     PetscCall(MatSetType(newmat, ((PetscObject)A)->type_name));
25749566063dSJacob Faibussowitsch     PetscCall(MatSeqDenseSetPreallocation(newmat, NULL));
2575182d2002SSatish Balay   }
2576182d2002SSatish Balay 
2577182d2002SSatish Balay   /* Now extract the data pointers and do the copy,column at a time */
25789566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArray(newmat, &bv));
25799566063dSJacob Faibussowitsch   PetscCall(MatDenseGetLDA(newmat, &ldb));
2580182d2002SSatish Balay   for (i = 0; i < ncols; i++) {
25816de62eeeSBarry Smith     av = v + mat->lda * icol[i];
2582ca15aa20SStefano Zampini     for (j = 0; j < nrows; j++) bv[j] = av[irow[j]];
2583bf5a80bcSToby Isaac     bv += ldb;
25840754003eSLois Curfman McInnes   }
25859566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArray(newmat, &bv));
2586182d2002SSatish Balay 
2587182d2002SSatish Balay   /* Assemble the matrices so that the correct flags are set */
25889566063dSJacob Faibussowitsch   PetscCall(MatAssemblyBegin(newmat, MAT_FINAL_ASSEMBLY));
25899566063dSJacob Faibussowitsch   PetscCall(MatAssemblyEnd(newmat, MAT_FINAL_ASSEMBLY));
25900754003eSLois Curfman McInnes 
25910754003eSLois Curfman McInnes   /* Free work space */
25929566063dSJacob Faibussowitsch   PetscCall(ISRestoreIndices(isrow, &irow));
25939566063dSJacob Faibussowitsch   PetscCall(ISRestoreIndices(iscol, &icol));
2594182d2002SSatish Balay   *B = newmat;
25953ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
25960754003eSLois Curfman McInnes }
25970754003eSLois Curfman McInnes 
2598d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatCreateSubMatrices_SeqDense(Mat A, PetscInt n, const IS irow[], const IS icol[], MatReuse scall, Mat *B[])
2599d71ae5a4SJacob Faibussowitsch {
260013f74950SBarry Smith   PetscInt i;
2601905e6a2fSBarry Smith 
26023a40ed3dSBarry Smith   PetscFunctionBegin;
260348a46eb9SPierre Jolivet   if (scall == MAT_INITIAL_MATRIX) PetscCall(PetscCalloc1(n, B));
2604905e6a2fSBarry Smith 
260548a46eb9SPierre Jolivet   for (i = 0; i < n; i++) PetscCall(MatCreateSubMatrix_SeqDense(A, irow[i], icol[i], scall, &(*B)[i]));
26063ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2607905e6a2fSBarry Smith }
2608905e6a2fSBarry Smith 
2609d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatAssemblyBegin_SeqDense(Mat mat, MatAssemblyType mode)
2610d71ae5a4SJacob Faibussowitsch {
2611c0aa2d19SHong Zhang   PetscFunctionBegin;
26123ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2613c0aa2d19SHong Zhang }
2614c0aa2d19SHong Zhang 
2615d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatAssemblyEnd_SeqDense(Mat mat, MatAssemblyType mode)
2616d71ae5a4SJacob Faibussowitsch {
2617c0aa2d19SHong Zhang   PetscFunctionBegin;
26183ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2619c0aa2d19SHong Zhang }
2620c0aa2d19SHong Zhang 
2621d71ae5a4SJacob Faibussowitsch PetscErrorCode MatCopy_SeqDense(Mat A, Mat B, MatStructure str)
2622d71ae5a4SJacob Faibussowitsch {
26234b0e389bSBarry Smith   Mat_SeqDense      *a = (Mat_SeqDense *)A->data, *b = (Mat_SeqDense *)B->data;
2624ca15aa20SStefano Zampini   const PetscScalar *va;
2625ca15aa20SStefano Zampini   PetscScalar       *vb;
2626d0f46423SBarry Smith   PetscInt           lda1 = a->lda, lda2 = b->lda, m = A->rmap->n, n = A->cmap->n, j;
26273a40ed3dSBarry Smith 
26283a40ed3dSBarry Smith   PetscFunctionBegin;
262933f4a19fSKris Buschelman   /* If the two matrices don't have the same copy implementation, they aren't compatible for fast copy. */
263033f4a19fSKris Buschelman   if (A->ops->copy != B->ops->copy) {
26319566063dSJacob Faibussowitsch     PetscCall(MatCopy_Basic(A, B, str));
26323ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
26333a40ed3dSBarry Smith   }
2634aed4548fSBarry Smith   PetscCheck(m == B->rmap->n && n == B->cmap->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "size(B) != size(A)");
26359566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArrayRead(A, &va));
26369566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArray(B, &vb));
2637a5ce6ee0Svictorle   if (lda1 > m || lda2 > m) {
263848a46eb9SPierre Jolivet     for (j = 0; j < n; j++) PetscCall(PetscArraycpy(vb + j * lda2, va + j * lda1, m));
2639a5ce6ee0Svictorle   } else {
26409566063dSJacob Faibussowitsch     PetscCall(PetscArraycpy(vb, va, A->rmap->n * A->cmap->n));
2641a5ce6ee0Svictorle   }
26429566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArray(B, &vb));
26439566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArrayRead(A, &va));
26449566063dSJacob Faibussowitsch   PetscCall(MatAssemblyBegin(B, MAT_FINAL_ASSEMBLY));
26459566063dSJacob Faibussowitsch   PetscCall(MatAssemblyEnd(B, MAT_FINAL_ASSEMBLY));
26463ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2647273d9f13SBarry Smith }
2648273d9f13SBarry Smith 
2649d71ae5a4SJacob Faibussowitsch PetscErrorCode MatSetUp_SeqDense(Mat A)
2650d71ae5a4SJacob Faibussowitsch {
2651273d9f13SBarry Smith   PetscFunctionBegin;
26529566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetUp(A->rmap));
26539566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetUp(A->cmap));
265448a46eb9SPierre Jolivet   if (!A->preallocated) PetscCall(MatSeqDenseSetPreallocation(A, NULL));
26553ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
26564b0e389bSBarry Smith }
26574b0e389bSBarry Smith 
2658d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatConjugate_SeqDense(Mat A)
2659d71ae5a4SJacob Faibussowitsch {
26604396437dSToby Isaac   Mat_SeqDense *mat = (Mat_SeqDense *)A->data;
266106c5243aSJose E. Roman   PetscInt      i, j;
26624396437dSToby Isaac   PetscInt      min = PetscMin(A->rmap->n, A->cmap->n);
2663ca15aa20SStefano Zampini   PetscScalar  *aa;
2664ba337c44SJed Brown 
2665ba337c44SJed Brown   PetscFunctionBegin;
26669566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArray(A, &aa));
266706c5243aSJose E. Roman   for (j = 0; j < A->cmap->n; j++) {
266806c5243aSJose E. Roman     for (i = 0; i < A->rmap->n; i++) aa[i + j * mat->lda] = PetscConj(aa[i + j * mat->lda]);
266906c5243aSJose E. Roman   }
26709566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArray(A, &aa));
26719371c9d4SSatish Balay   if (mat->tau)
26729371c9d4SSatish Balay     for (i = 0; i < min; i++) mat->tau[i] = PetscConj(mat->tau[i]);
26733ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2674ba337c44SJed Brown }
2675ba337c44SJed Brown 
2676d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatRealPart_SeqDense(Mat A)
2677d71ae5a4SJacob Faibussowitsch {
267806c5243aSJose E. Roman   Mat_SeqDense *mat = (Mat_SeqDense *)A->data;
267906c5243aSJose E. Roman   PetscInt      i, j;
2680ca15aa20SStefano Zampini   PetscScalar  *aa;
2681ba337c44SJed Brown 
2682ba337c44SJed Brown   PetscFunctionBegin;
26839566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArray(A, &aa));
268406c5243aSJose E. Roman   for (j = 0; j < A->cmap->n; j++) {
268506c5243aSJose E. Roman     for (i = 0; i < A->rmap->n; i++) aa[i + j * mat->lda] = PetscRealPart(aa[i + j * mat->lda]);
268606c5243aSJose E. Roman   }
26879566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArray(A, &aa));
26883ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2689ba337c44SJed Brown }
2690ba337c44SJed Brown 
2691d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatImaginaryPart_SeqDense(Mat A)
2692d71ae5a4SJacob Faibussowitsch {
269306c5243aSJose E. Roman   Mat_SeqDense *mat = (Mat_SeqDense *)A->data;
269406c5243aSJose E. Roman   PetscInt      i, j;
2695ca15aa20SStefano Zampini   PetscScalar  *aa;
2696ba337c44SJed Brown 
2697ba337c44SJed Brown   PetscFunctionBegin;
26989566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArray(A, &aa));
269906c5243aSJose E. Roman   for (j = 0; j < A->cmap->n; j++) {
270006c5243aSJose E. Roman     for (i = 0; i < A->rmap->n; i++) aa[i + j * mat->lda] = PetscImaginaryPart(aa[i + j * mat->lda]);
270106c5243aSJose E. Roman   }
27029566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArray(A, &aa));
27033ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2704ba337c44SJed Brown }
2705284134d9SBarry Smith 
2706d71ae5a4SJacob Faibussowitsch PetscErrorCode MatMatMultSymbolic_SeqDense_SeqDense(Mat A, Mat B, PetscReal fill, Mat C)
2707d71ae5a4SJacob Faibussowitsch {
2708d0f46423SBarry Smith   PetscInt  m = A->rmap->n, n = B->cmap->n;
270947d993e7Ssuyashtn   PetscBool cisdense = PETSC_FALSE;
2710a9fe9ddaSSatish Balay 
2711ee16a9a1SHong Zhang   PetscFunctionBegin;
27129566063dSJacob Faibussowitsch   PetscCall(MatSetSizes(C, m, n, m, n));
271347d993e7Ssuyashtn #if defined(PETSC_HAVE_CUDA)
27149566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompareAny((PetscObject)C, &cisdense, MATSEQDENSE, MATSEQDENSECUDA, ""));
271547d993e7Ssuyashtn #endif
271647d993e7Ssuyashtn #if defined(PETSC_HAVE_HIP)
271747d993e7Ssuyashtn   PetscCall(PetscObjectTypeCompareAny((PetscObject)C, &cisdense, MATSEQDENSE, MATSEQDENSEHIP, ""));
271847d993e7Ssuyashtn #endif
27197a3c3d58SStefano Zampini   if (!cisdense) {
27207a3c3d58SStefano Zampini     PetscBool flg;
27217a3c3d58SStefano Zampini 
27229566063dSJacob Faibussowitsch     PetscCall(PetscObjectTypeCompare((PetscObject)B, ((PetscObject)A)->type_name, &flg));
27239566063dSJacob Faibussowitsch     PetscCall(MatSetType(C, flg ? ((PetscObject)A)->type_name : MATDENSE));
27247a3c3d58SStefano Zampini   }
27259566063dSJacob Faibussowitsch   PetscCall(MatSetUp(C));
27263ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2727ee16a9a1SHong Zhang }
2728a9fe9ddaSSatish Balay 
2729d71ae5a4SJacob Faibussowitsch PetscErrorCode MatMatMultNumeric_SeqDense_SeqDense(Mat A, Mat B, Mat C)
2730d71ae5a4SJacob Faibussowitsch {
27316718818eSStefano Zampini   Mat_SeqDense      *a = (Mat_SeqDense *)A->data, *b = (Mat_SeqDense *)B->data, *c = (Mat_SeqDense *)C->data;
27320805154bSBarry Smith   PetscBLASInt       m, n, k;
2733ca15aa20SStefano Zampini   const PetscScalar *av, *bv;
2734ca15aa20SStefano Zampini   PetscScalar       *cv;
2735a9fe9ddaSSatish Balay   PetscScalar        _DOne = 1.0, _DZero = 0.0;
2736a9fe9ddaSSatish Balay 
2737a9fe9ddaSSatish Balay   PetscFunctionBegin;
27389566063dSJacob Faibussowitsch   PetscCall(PetscBLASIntCast(C->rmap->n, &m));
27399566063dSJacob Faibussowitsch   PetscCall(PetscBLASIntCast(C->cmap->n, &n));
27409566063dSJacob Faibussowitsch   PetscCall(PetscBLASIntCast(A->cmap->n, &k));
27413ba16761SJacob Faibussowitsch   if (!m || !n || !k) PetscFunctionReturn(PETSC_SUCCESS);
27429566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArrayRead(A, &av));
27439566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArrayRead(B, &bv));
27449566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArrayWrite(C, &cv));
2745792fecdfSBarry Smith   PetscCallBLAS("BLASgemm", BLASgemm_("N", "N", &m, &n, &k, &_DOne, av, &a->lda, bv, &b->lda, &_DZero, cv, &c->lda));
27469566063dSJacob Faibussowitsch   PetscCall(PetscLogFlops(1.0 * m * n * k + 1.0 * m * n * (k - 1)));
27479566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArrayRead(A, &av));
27489566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArrayRead(B, &bv));
27499566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArrayWrite(C, &cv));
27503ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2751a9fe9ddaSSatish Balay }
2752a9fe9ddaSSatish Balay 
2753d71ae5a4SJacob Faibussowitsch PetscErrorCode MatMatTransposeMultSymbolic_SeqDense_SeqDense(Mat A, Mat B, PetscReal fill, Mat C)
2754d71ae5a4SJacob Faibussowitsch {
275569f65d41SStefano Zampini   PetscInt  m = A->rmap->n, n = B->rmap->n;
275647d993e7Ssuyashtn   PetscBool cisdense = PETSC_FALSE;
275769f65d41SStefano Zampini 
275869f65d41SStefano Zampini   PetscFunctionBegin;
27599566063dSJacob Faibussowitsch   PetscCall(MatSetSizes(C, m, n, m, n));
276047d993e7Ssuyashtn #if defined(PETSC_HAVE_CUDA)
27619566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompareAny((PetscObject)C, &cisdense, MATSEQDENSE, MATSEQDENSECUDA, ""));
276247d993e7Ssuyashtn #endif
276347d993e7Ssuyashtn #if defined(PETSC_HAVE_HIP)
276447d993e7Ssuyashtn   PetscCall(PetscObjectTypeCompareAny((PetscObject)C, &cisdense, MATSEQDENSE, MATSEQDENSEHIP, ""));
276547d993e7Ssuyashtn #endif
27667a3c3d58SStefano Zampini   if (!cisdense) {
27677a3c3d58SStefano Zampini     PetscBool flg;
27687a3c3d58SStefano Zampini 
27699566063dSJacob Faibussowitsch     PetscCall(PetscObjectTypeCompare((PetscObject)B, ((PetscObject)A)->type_name, &flg));
27709566063dSJacob Faibussowitsch     PetscCall(MatSetType(C, flg ? ((PetscObject)A)->type_name : MATDENSE));
27717a3c3d58SStefano Zampini   }
27729566063dSJacob Faibussowitsch   PetscCall(MatSetUp(C));
27733ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
277469f65d41SStefano Zampini }
277569f65d41SStefano Zampini 
2776d71ae5a4SJacob Faibussowitsch PetscErrorCode MatMatTransposeMultNumeric_SeqDense_SeqDense(Mat A, Mat B, Mat C)
2777d71ae5a4SJacob Faibussowitsch {
277869f65d41SStefano Zampini   Mat_SeqDense      *a = (Mat_SeqDense *)A->data;
277969f65d41SStefano Zampini   Mat_SeqDense      *b = (Mat_SeqDense *)B->data;
278069f65d41SStefano Zampini   Mat_SeqDense      *c = (Mat_SeqDense *)C->data;
27816718818eSStefano Zampini   const PetscScalar *av, *bv;
27826718818eSStefano Zampini   PetscScalar       *cv;
278369f65d41SStefano Zampini   PetscBLASInt       m, n, k;
278469f65d41SStefano Zampini   PetscScalar        _DOne = 1.0, _DZero = 0.0;
278569f65d41SStefano Zampini 
278669f65d41SStefano Zampini   PetscFunctionBegin;
27879566063dSJacob Faibussowitsch   PetscCall(PetscBLASIntCast(C->rmap->n, &m));
27889566063dSJacob Faibussowitsch   PetscCall(PetscBLASIntCast(C->cmap->n, &n));
27899566063dSJacob Faibussowitsch   PetscCall(PetscBLASIntCast(A->cmap->n, &k));
27903ba16761SJacob Faibussowitsch   if (!m || !n || !k) PetscFunctionReturn(PETSC_SUCCESS);
27919566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArrayRead(A, &av));
27929566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArrayRead(B, &bv));
27939566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArrayWrite(C, &cv));
2794792fecdfSBarry Smith   PetscCallBLAS("BLASgemm", BLASgemm_("N", "T", &m, &n, &k, &_DOne, av, &a->lda, bv, &b->lda, &_DZero, cv, &c->lda));
27959566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArrayRead(A, &av));
27969566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArrayRead(B, &bv));
27979566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArrayWrite(C, &cv));
27989566063dSJacob Faibussowitsch   PetscCall(PetscLogFlops(1.0 * m * n * k + 1.0 * m * n * (k - 1)));
27993ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
280069f65d41SStefano Zampini }
280169f65d41SStefano Zampini 
2802d71ae5a4SJacob Faibussowitsch PetscErrorCode MatTransposeMatMultSymbolic_SeqDense_SeqDense(Mat A, Mat B, PetscReal fill, Mat C)
2803d71ae5a4SJacob Faibussowitsch {
2804d0f46423SBarry Smith   PetscInt  m = A->cmap->n, n = B->cmap->n;
280547d993e7Ssuyashtn   PetscBool cisdense = PETSC_FALSE;
2806a9fe9ddaSSatish Balay 
2807ee16a9a1SHong Zhang   PetscFunctionBegin;
28089566063dSJacob Faibussowitsch   PetscCall(MatSetSizes(C, m, n, m, n));
280947d993e7Ssuyashtn #if defined(PETSC_HAVE_CUDA)
28109566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompareAny((PetscObject)C, &cisdense, MATSEQDENSE, MATSEQDENSECUDA, ""));
281147d993e7Ssuyashtn #endif
281247d993e7Ssuyashtn #if defined(PETSC_HAVE_HIP)
281347d993e7Ssuyashtn   PetscCall(PetscObjectTypeCompareAny((PetscObject)C, &cisdense, MATSEQDENSE, MATSEQDENSEHIP, ""));
281447d993e7Ssuyashtn #endif
28157a3c3d58SStefano Zampini   if (!cisdense) {
28167a3c3d58SStefano Zampini     PetscBool flg;
28177a3c3d58SStefano Zampini 
28189566063dSJacob Faibussowitsch     PetscCall(PetscObjectTypeCompare((PetscObject)B, ((PetscObject)A)->type_name, &flg));
28199566063dSJacob Faibussowitsch     PetscCall(MatSetType(C, flg ? ((PetscObject)A)->type_name : MATDENSE));
28207a3c3d58SStefano Zampini   }
28219566063dSJacob Faibussowitsch   PetscCall(MatSetUp(C));
28223ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2823ee16a9a1SHong Zhang }
2824a9fe9ddaSSatish Balay 
2825d71ae5a4SJacob Faibussowitsch PetscErrorCode MatTransposeMatMultNumeric_SeqDense_SeqDense(Mat A, Mat B, Mat C)
2826d71ae5a4SJacob Faibussowitsch {
2827a9fe9ddaSSatish Balay   Mat_SeqDense      *a = (Mat_SeqDense *)A->data;
2828a9fe9ddaSSatish Balay   Mat_SeqDense      *b = (Mat_SeqDense *)B->data;
2829a9fe9ddaSSatish Balay   Mat_SeqDense      *c = (Mat_SeqDense *)C->data;
28306718818eSStefano Zampini   const PetscScalar *av, *bv;
28316718818eSStefano Zampini   PetscScalar       *cv;
28320805154bSBarry Smith   PetscBLASInt       m, n, k;
2833a9fe9ddaSSatish Balay   PetscScalar        _DOne = 1.0, _DZero = 0.0;
2834a9fe9ddaSSatish Balay 
2835a9fe9ddaSSatish Balay   PetscFunctionBegin;
28369566063dSJacob Faibussowitsch   PetscCall(PetscBLASIntCast(C->rmap->n, &m));
28379566063dSJacob Faibussowitsch   PetscCall(PetscBLASIntCast(C->cmap->n, &n));
28389566063dSJacob Faibussowitsch   PetscCall(PetscBLASIntCast(A->rmap->n, &k));
28393ba16761SJacob Faibussowitsch   if (!m || !n || !k) PetscFunctionReturn(PETSC_SUCCESS);
28409566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArrayRead(A, &av));
28419566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArrayRead(B, &bv));
28429566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArrayWrite(C, &cv));
2843792fecdfSBarry Smith   PetscCallBLAS("BLASgemm", BLASgemm_("T", "N", &m, &n, &k, &_DOne, av, &a->lda, bv, &b->lda, &_DZero, cv, &c->lda));
28449566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArrayRead(A, &av));
28459566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArrayRead(B, &bv));
28469566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArrayWrite(C, &cv));
28479566063dSJacob Faibussowitsch   PetscCall(PetscLogFlops(1.0 * m * n * k + 1.0 * m * n * (k - 1)));
28483ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2849a9fe9ddaSSatish Balay }
2850985db425SBarry Smith 
2851d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatProductSetFromOptions_SeqDense_AB(Mat C)
2852d71ae5a4SJacob Faibussowitsch {
28534222ddf1SHong Zhang   PetscFunctionBegin;
28544222ddf1SHong Zhang   C->ops->matmultsymbolic = MatMatMultSymbolic_SeqDense_SeqDense;
28554222ddf1SHong Zhang   C->ops->productsymbolic = MatProductSymbolic_AB;
28563ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
28574222ddf1SHong Zhang }
28584222ddf1SHong Zhang 
2859d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatProductSetFromOptions_SeqDense_AtB(Mat C)
2860d71ae5a4SJacob Faibussowitsch {
28614222ddf1SHong Zhang   PetscFunctionBegin;
28624222ddf1SHong Zhang   C->ops->transposematmultsymbolic = MatTransposeMatMultSymbolic_SeqDense_SeqDense;
28634222ddf1SHong Zhang   C->ops->productsymbolic          = MatProductSymbolic_AtB;
28643ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
28654222ddf1SHong Zhang }
28664222ddf1SHong Zhang 
2867d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatProductSetFromOptions_SeqDense_ABt(Mat C)
2868d71ae5a4SJacob Faibussowitsch {
28694222ddf1SHong Zhang   PetscFunctionBegin;
28704222ddf1SHong Zhang   C->ops->mattransposemultsymbolic = MatMatTransposeMultSymbolic_SeqDense_SeqDense;
28714222ddf1SHong Zhang   C->ops->productsymbolic          = MatProductSymbolic_ABt;
28723ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
28734222ddf1SHong Zhang }
28744222ddf1SHong Zhang 
2875d71ae5a4SJacob Faibussowitsch PETSC_INTERN PetscErrorCode MatProductSetFromOptions_SeqDense(Mat C)
2876d71ae5a4SJacob Faibussowitsch {
28774222ddf1SHong Zhang   Mat_Product *product = C->product;
28784222ddf1SHong Zhang 
28794222ddf1SHong Zhang   PetscFunctionBegin;
28804222ddf1SHong Zhang   switch (product->type) {
2881d71ae5a4SJacob Faibussowitsch   case MATPRODUCT_AB:
2882d71ae5a4SJacob Faibussowitsch     PetscCall(MatProductSetFromOptions_SeqDense_AB(C));
2883d71ae5a4SJacob Faibussowitsch     break;
2884d71ae5a4SJacob Faibussowitsch   case MATPRODUCT_AtB:
2885d71ae5a4SJacob Faibussowitsch     PetscCall(MatProductSetFromOptions_SeqDense_AtB(C));
2886d71ae5a4SJacob Faibussowitsch     break;
2887d71ae5a4SJacob Faibussowitsch   case MATPRODUCT_ABt:
2888d71ae5a4SJacob Faibussowitsch     PetscCall(MatProductSetFromOptions_SeqDense_ABt(C));
2889d71ae5a4SJacob Faibussowitsch     break;
2890d71ae5a4SJacob Faibussowitsch   default:
2891d71ae5a4SJacob Faibussowitsch     break;
28924222ddf1SHong Zhang   }
28933ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
28944222ddf1SHong Zhang }
28954222ddf1SHong Zhang 
2896d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatGetRowMax_SeqDense(Mat A, Vec v, PetscInt idx[])
2897d71ae5a4SJacob Faibussowitsch {
2898985db425SBarry Smith   Mat_SeqDense      *a = (Mat_SeqDense *)A->data;
2899d0f46423SBarry Smith   PetscInt           i, j, m = A->rmap->n, n = A->cmap->n, p;
2900985db425SBarry Smith   PetscScalar       *x;
2901ca15aa20SStefano Zampini   const PetscScalar *aa;
2902985db425SBarry Smith 
2903985db425SBarry Smith   PetscFunctionBegin;
290428b400f6SJacob Faibussowitsch   PetscCheck(!A->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
29059566063dSJacob Faibussowitsch   PetscCall(VecGetArray(v, &x));
29069566063dSJacob Faibussowitsch   PetscCall(VecGetLocalSize(v, &p));
29079566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArrayRead(A, &aa));
290808401ef6SPierre Jolivet   PetscCheck(p == A->rmap->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Nonconforming matrix and vector");
2909985db425SBarry Smith   for (i = 0; i < m; i++) {
29109371c9d4SSatish Balay     x[i] = aa[i];
29119371c9d4SSatish Balay     if (idx) idx[i] = 0;
2912985db425SBarry Smith     for (j = 1; j < n; j++) {
29139371c9d4SSatish Balay       if (PetscRealPart(x[i]) < PetscRealPart(aa[i + a->lda * j])) {
29149371c9d4SSatish Balay         x[i] = aa[i + a->lda * j];
29159371c9d4SSatish Balay         if (idx) idx[i] = j;
29169371c9d4SSatish Balay       }
2917985db425SBarry Smith     }
2918985db425SBarry Smith   }
29199566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArrayRead(A, &aa));
29209566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(v, &x));
29213ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2922985db425SBarry Smith }
2923985db425SBarry Smith 
2924d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatGetRowMaxAbs_SeqDense(Mat A, Vec v, PetscInt idx[])
2925d71ae5a4SJacob Faibussowitsch {
2926985db425SBarry Smith   Mat_SeqDense      *a = (Mat_SeqDense *)A->data;
2927d0f46423SBarry Smith   PetscInt           i, j, m = A->rmap->n, n = A->cmap->n, p;
2928985db425SBarry Smith   PetscScalar       *x;
2929985db425SBarry Smith   PetscReal          atmp;
2930ca15aa20SStefano Zampini   const PetscScalar *aa;
2931985db425SBarry Smith 
2932985db425SBarry Smith   PetscFunctionBegin;
293328b400f6SJacob Faibussowitsch   PetscCheck(!A->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
29349566063dSJacob Faibussowitsch   PetscCall(VecGetArray(v, &x));
29359566063dSJacob Faibussowitsch   PetscCall(VecGetLocalSize(v, &p));
29369566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArrayRead(A, &aa));
293708401ef6SPierre Jolivet   PetscCheck(p == A->rmap->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Nonconforming matrix and vector");
2938985db425SBarry Smith   for (i = 0; i < m; i++) {
29399189402eSHong Zhang     x[i] = PetscAbsScalar(aa[i]);
2940985db425SBarry Smith     for (j = 1; j < n; j++) {
2941ca15aa20SStefano Zampini       atmp = PetscAbsScalar(aa[i + a->lda * j]);
29429371c9d4SSatish Balay       if (PetscAbsScalar(x[i]) < atmp) {
29439371c9d4SSatish Balay         x[i] = atmp;
29449371c9d4SSatish Balay         if (idx) idx[i] = j;
29459371c9d4SSatish Balay       }
2946985db425SBarry Smith     }
2947985db425SBarry Smith   }
29489566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArrayRead(A, &aa));
29499566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(v, &x));
29503ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2951985db425SBarry Smith }
2952985db425SBarry Smith 
2953d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatGetRowMin_SeqDense(Mat A, Vec v, PetscInt idx[])
2954d71ae5a4SJacob Faibussowitsch {
2955985db425SBarry Smith   Mat_SeqDense      *a = (Mat_SeqDense *)A->data;
2956d0f46423SBarry Smith   PetscInt           i, j, m = A->rmap->n, n = A->cmap->n, p;
2957985db425SBarry Smith   PetscScalar       *x;
2958ca15aa20SStefano Zampini   const PetscScalar *aa;
2959985db425SBarry Smith 
2960985db425SBarry Smith   PetscFunctionBegin;
296128b400f6SJacob Faibussowitsch   PetscCheck(!A->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
29629566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArrayRead(A, &aa));
29639566063dSJacob Faibussowitsch   PetscCall(VecGetArray(v, &x));
29649566063dSJacob Faibussowitsch   PetscCall(VecGetLocalSize(v, &p));
296508401ef6SPierre Jolivet   PetscCheck(p == A->rmap->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Nonconforming matrix and vector");
2966985db425SBarry Smith   for (i = 0; i < m; i++) {
29679371c9d4SSatish Balay     x[i] = aa[i];
29689371c9d4SSatish Balay     if (idx) idx[i] = 0;
2969985db425SBarry Smith     for (j = 1; j < n; j++) {
29709371c9d4SSatish Balay       if (PetscRealPart(x[i]) > PetscRealPart(aa[i + a->lda * j])) {
29719371c9d4SSatish Balay         x[i] = aa[i + a->lda * j];
29729371c9d4SSatish Balay         if (idx) idx[i] = j;
29739371c9d4SSatish Balay       }
2974985db425SBarry Smith     }
2975985db425SBarry Smith   }
29769566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(v, &x));
29779566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArrayRead(A, &aa));
29783ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2979985db425SBarry Smith }
2980985db425SBarry Smith 
2981d71ae5a4SJacob Faibussowitsch PetscErrorCode MatGetColumnVector_SeqDense(Mat A, Vec v, PetscInt col)
2982d71ae5a4SJacob Faibussowitsch {
29838d0534beSBarry Smith   Mat_SeqDense      *a = (Mat_SeqDense *)A->data;
29848d0534beSBarry Smith   PetscScalar       *x;
2985ca15aa20SStefano Zampini   const PetscScalar *aa;
29868d0534beSBarry Smith 
29878d0534beSBarry Smith   PetscFunctionBegin;
298828b400f6SJacob Faibussowitsch   PetscCheck(!A->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
29899566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArrayRead(A, &aa));
29909566063dSJacob Faibussowitsch   PetscCall(VecGetArray(v, &x));
29919566063dSJacob Faibussowitsch   PetscCall(PetscArraycpy(x, aa + col * a->lda, A->rmap->n));
29929566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(v, &x));
29939566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArrayRead(A, &aa));
29943ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
29958d0534beSBarry Smith }
29968d0534beSBarry Smith 
2997d71ae5a4SJacob Faibussowitsch PETSC_INTERN PetscErrorCode MatGetColumnReductions_SeqDense(Mat A, PetscInt type, PetscReal *reductions)
2998d71ae5a4SJacob Faibussowitsch {
29990716a85fSBarry Smith   PetscInt           i, j, m, n;
30001683a169SBarry Smith   const PetscScalar *a;
30010716a85fSBarry Smith 
30020716a85fSBarry Smith   PetscFunctionBegin;
30039566063dSJacob Faibussowitsch   PetscCall(MatGetSize(A, &m, &n));
30049566063dSJacob Faibussowitsch   PetscCall(PetscArrayzero(reductions, n));
30059566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArrayRead(A, &a));
3006857cbf51SRichard Tran Mills   if (type == NORM_2) {
30070716a85fSBarry Smith     for (i = 0; i < n; i++) {
3008ad540459SPierre Jolivet       for (j = 0; j < m; j++) reductions[i] += PetscAbsScalar(a[j] * a[j]);
30090716a85fSBarry Smith       a += m;
30100716a85fSBarry Smith     }
3011857cbf51SRichard Tran Mills   } else if (type == NORM_1) {
30120716a85fSBarry Smith     for (i = 0; i < n; i++) {
3013ad540459SPierre Jolivet       for (j = 0; j < m; j++) reductions[i] += PetscAbsScalar(a[j]);
30140716a85fSBarry Smith       a += m;
30150716a85fSBarry Smith     }
3016857cbf51SRichard Tran Mills   } else if (type == NORM_INFINITY) {
30170716a85fSBarry Smith     for (i = 0; i < n; i++) {
3018ad540459SPierre Jolivet       for (j = 0; j < m; j++) reductions[i] = PetscMax(PetscAbsScalar(a[j]), reductions[i]);
30190716a85fSBarry Smith       a += m;
30200716a85fSBarry Smith     }
3021857cbf51SRichard Tran Mills   } else if (type == REDUCTION_SUM_REALPART || type == REDUCTION_MEAN_REALPART) {
3022a873a8cdSSam Reynolds     for (i = 0; i < n; i++) {
3023ad540459SPierre Jolivet       for (j = 0; j < m; j++) reductions[i] += PetscRealPart(a[j]);
3024a873a8cdSSam Reynolds       a += m;
3025a873a8cdSSam Reynolds     }
3026857cbf51SRichard Tran Mills   } else if (type == REDUCTION_SUM_IMAGINARYPART || type == REDUCTION_MEAN_IMAGINARYPART) {
3027857cbf51SRichard Tran Mills     for (i = 0; i < n; i++) {
3028ad540459SPierre Jolivet       for (j = 0; j < m; j++) reductions[i] += PetscImaginaryPart(a[j]);
3029857cbf51SRichard Tran Mills       a += m;
3030857cbf51SRichard Tran Mills     }
3031857cbf51SRichard Tran Mills   } else SETERRQ(PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONG, "Unknown reduction type");
30329566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArrayRead(A, &a));
3033857cbf51SRichard Tran Mills   if (type == NORM_2) {
3034a873a8cdSSam Reynolds     for (i = 0; i < n; i++) reductions[i] = PetscSqrtReal(reductions[i]);
3035857cbf51SRichard Tran Mills   } else if (type == REDUCTION_MEAN_REALPART || type == REDUCTION_MEAN_IMAGINARYPART) {
3036a873a8cdSSam Reynolds     for (i = 0; i < n; i++) reductions[i] /= m;
30370716a85fSBarry Smith   }
30383ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
30390716a85fSBarry Smith }
30400716a85fSBarry Smith 
3041d71ae5a4SJacob Faibussowitsch PetscErrorCode MatSetRandom_SeqDense(Mat x, PetscRandom rctx)
3042d71ae5a4SJacob Faibussowitsch {
304373a71a0fSBarry Smith   PetscScalar *a;
3044637a0070SStefano Zampini   PetscInt     lda, m, n, i, j;
304573a71a0fSBarry Smith 
304673a71a0fSBarry Smith   PetscFunctionBegin;
30479566063dSJacob Faibussowitsch   PetscCall(MatGetSize(x, &m, &n));
30489566063dSJacob Faibussowitsch   PetscCall(MatDenseGetLDA(x, &lda));
30493faff063SStefano Zampini   PetscCall(MatDenseGetArrayWrite(x, &a));
3050637a0070SStefano Zampini   for (j = 0; j < n; j++) {
305148a46eb9SPierre Jolivet     for (i = 0; i < m; i++) PetscCall(PetscRandomGetValue(rctx, a + j * lda + i));
305273a71a0fSBarry Smith   }
30533faff063SStefano Zampini   PetscCall(MatDenseRestoreArrayWrite(x, &a));
30543ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
305573a71a0fSBarry Smith }
305673a71a0fSBarry Smith 
3057d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatMissingDiagonal_SeqDense(Mat A, PetscBool *missing, PetscInt *d)
3058d71ae5a4SJacob Faibussowitsch {
30593b49f96aSBarry Smith   PetscFunctionBegin;
30603b49f96aSBarry Smith   *missing = PETSC_FALSE;
30613ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
30623b49f96aSBarry Smith }
306373a71a0fSBarry Smith 
3064ca15aa20SStefano Zampini /* vals is not const */
3065d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatDenseGetColumn_SeqDense(Mat A, PetscInt col, PetscScalar **vals)
3066d71ae5a4SJacob Faibussowitsch {
306786aefd0dSHong Zhang   Mat_SeqDense *a = (Mat_SeqDense *)A->data;
3068ca15aa20SStefano Zampini   PetscScalar  *v;
306986aefd0dSHong Zhang 
307086aefd0dSHong Zhang   PetscFunctionBegin;
307128b400f6SJacob Faibussowitsch   PetscCheck(!A->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
30729566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArray(A, &v));
3073ca15aa20SStefano Zampini   *vals = v + col * a->lda;
30749566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArray(A, &v));
30753ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
307686aefd0dSHong Zhang }
307786aefd0dSHong Zhang 
3078d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatDenseRestoreColumn_SeqDense(Mat A, PetscScalar **vals)
3079d71ae5a4SJacob Faibussowitsch {
308086aefd0dSHong Zhang   PetscFunctionBegin;
3081742765d3SMatthew Knepley   if (vals) *vals = NULL; /* user cannot accidentally use the array later */
30823ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
308386aefd0dSHong Zhang }
3084abc3b08eSStefano Zampini 
3085a5ae1ecdSBarry Smith static struct _MatOps MatOps_Values = {MatSetValues_SeqDense,
3086905e6a2fSBarry Smith                                        MatGetRow_SeqDense,
3087905e6a2fSBarry Smith                                        MatRestoreRow_SeqDense,
3088905e6a2fSBarry Smith                                        MatMult_SeqDense,
308997304618SKris Buschelman                                        /*  4*/ MatMultAdd_SeqDense,
30907c922b88SBarry Smith                                        MatMultTranspose_SeqDense,
30917c922b88SBarry Smith                                        MatMultTransposeAdd_SeqDense,
3092f4259b30SLisandro Dalcin                                        NULL,
3093f4259b30SLisandro Dalcin                                        NULL,
3094f4259b30SLisandro Dalcin                                        NULL,
3095f4259b30SLisandro Dalcin                                        /* 10*/ NULL,
3096905e6a2fSBarry Smith                                        MatLUFactor_SeqDense,
3097905e6a2fSBarry Smith                                        MatCholeskyFactor_SeqDense,
309841f059aeSBarry Smith                                        MatSOR_SeqDense,
3099ec8511deSBarry Smith                                        MatTranspose_SeqDense,
310097304618SKris Buschelman                                        /* 15*/ MatGetInfo_SeqDense,
3101905e6a2fSBarry Smith                                        MatEqual_SeqDense,
3102905e6a2fSBarry Smith                                        MatGetDiagonal_SeqDense,
3103905e6a2fSBarry Smith                                        MatDiagonalScale_SeqDense,
3104905e6a2fSBarry Smith                                        MatNorm_SeqDense,
3105c0aa2d19SHong Zhang                                        /* 20*/ MatAssemblyBegin_SeqDense,
3106c0aa2d19SHong Zhang                                        MatAssemblyEnd_SeqDense,
3107905e6a2fSBarry Smith                                        MatSetOption_SeqDense,
3108905e6a2fSBarry Smith                                        MatZeroEntries_SeqDense,
3109d519adbfSMatthew Knepley                                        /* 24*/ MatZeroRows_SeqDense,
3110f4259b30SLisandro Dalcin                                        NULL,
3111f4259b30SLisandro Dalcin                                        NULL,
3112f4259b30SLisandro Dalcin                                        NULL,
3113f4259b30SLisandro Dalcin                                        NULL,
31144994cf47SJed Brown                                        /* 29*/ MatSetUp_SeqDense,
3115f4259b30SLisandro Dalcin                                        NULL,
3116f4259b30SLisandro Dalcin                                        NULL,
3117f4259b30SLisandro Dalcin                                        NULL,
3118f4259b30SLisandro Dalcin                                        NULL,
3119d519adbfSMatthew Knepley                                        /* 34*/ MatDuplicate_SeqDense,
3120f4259b30SLisandro Dalcin                                        NULL,
3121f4259b30SLisandro Dalcin                                        NULL,
3122f4259b30SLisandro Dalcin                                        NULL,
3123f4259b30SLisandro Dalcin                                        NULL,
3124d519adbfSMatthew Knepley                                        /* 39*/ MatAXPY_SeqDense,
31257dae84e0SHong Zhang                                        MatCreateSubMatrices_SeqDense,
3126f4259b30SLisandro Dalcin                                        NULL,
31274b0e389bSBarry Smith                                        MatGetValues_SeqDense,
3128a5ae1ecdSBarry Smith                                        MatCopy_SeqDense,
3129d519adbfSMatthew Knepley                                        /* 44*/ MatGetRowMax_SeqDense,
3130a5ae1ecdSBarry Smith                                        MatScale_SeqDense,
31312f605a99SJose E. Roman                                        MatShift_SeqDense,
3132f4259b30SLisandro Dalcin                                        NULL,
31333f49a652SStefano Zampini                                        MatZeroRowsColumns_SeqDense,
313473a71a0fSBarry Smith                                        /* 49*/ MatSetRandom_SeqDense,
3135f4259b30SLisandro Dalcin                                        NULL,
3136f4259b30SLisandro Dalcin                                        NULL,
3137f4259b30SLisandro Dalcin                                        NULL,
3138f4259b30SLisandro Dalcin                                        NULL,
3139f4259b30SLisandro Dalcin                                        /* 54*/ NULL,
3140f4259b30SLisandro Dalcin                                        NULL,
3141f4259b30SLisandro Dalcin                                        NULL,
3142f4259b30SLisandro Dalcin                                        NULL,
3143f4259b30SLisandro Dalcin                                        NULL,
3144023c16fcSToby Isaac                                        /* 59*/ MatCreateSubMatrix_SeqDense,
3145e03a110bSBarry Smith                                        MatDestroy_SeqDense,
3146e03a110bSBarry Smith                                        MatView_SeqDense,
3147f4259b30SLisandro Dalcin                                        NULL,
3148f4259b30SLisandro Dalcin                                        NULL,
3149f4259b30SLisandro Dalcin                                        /* 64*/ NULL,
3150f4259b30SLisandro Dalcin                                        NULL,
3151f4259b30SLisandro Dalcin                                        NULL,
3152f4259b30SLisandro Dalcin                                        NULL,
3153f4259b30SLisandro Dalcin                                        NULL,
3154d519adbfSMatthew Knepley                                        /* 69*/ MatGetRowMaxAbs_SeqDense,
3155f4259b30SLisandro Dalcin                                        NULL,
3156f4259b30SLisandro Dalcin                                        NULL,
3157f4259b30SLisandro Dalcin                                        NULL,
3158f4259b30SLisandro Dalcin                                        NULL,
3159f4259b30SLisandro Dalcin                                        /* 74*/ NULL,
3160f4259b30SLisandro Dalcin                                        NULL,
3161f4259b30SLisandro Dalcin                                        NULL,
3162f4259b30SLisandro Dalcin                                        NULL,
3163f4259b30SLisandro Dalcin                                        NULL,
3164f4259b30SLisandro Dalcin                                        /* 79*/ NULL,
3165f4259b30SLisandro Dalcin                                        NULL,
3166f4259b30SLisandro Dalcin                                        NULL,
3167f4259b30SLisandro Dalcin                                        NULL,
31685bba2384SShri Abhyankar                                        /* 83*/ MatLoad_SeqDense,
3169637a0070SStefano Zampini                                        MatIsSymmetric_SeqDense,
31701cbb95d3SBarry Smith                                        MatIsHermitian_SeqDense,
3171f4259b30SLisandro Dalcin                                        NULL,
3172f4259b30SLisandro Dalcin                                        NULL,
3173f4259b30SLisandro Dalcin                                        NULL,
3174f4259b30SLisandro Dalcin                                        /* 89*/ NULL,
3175f4259b30SLisandro Dalcin                                        NULL,
3176a9fe9ddaSSatish Balay                                        MatMatMultNumeric_SeqDense_SeqDense,
3177f4259b30SLisandro Dalcin                                        NULL,
3178f4259b30SLisandro Dalcin                                        NULL,
3179f4259b30SLisandro Dalcin                                        /* 94*/ NULL,
3180f4259b30SLisandro Dalcin                                        NULL,
3181f4259b30SLisandro Dalcin                                        NULL,
318269f65d41SStefano Zampini                                        MatMatTransposeMultNumeric_SeqDense_SeqDense,
3183f4259b30SLisandro Dalcin                                        NULL,
31844222ddf1SHong Zhang                                        /* 99*/ MatProductSetFromOptions_SeqDense,
3185f4259b30SLisandro Dalcin                                        NULL,
3186f4259b30SLisandro Dalcin                                        NULL,
3187ba337c44SJed Brown                                        MatConjugate_SeqDense,
3188f4259b30SLisandro Dalcin                                        NULL,
3189f4259b30SLisandro Dalcin                                        /*104*/ NULL,
3190ba337c44SJed Brown                                        MatRealPart_SeqDense,
3191ba337c44SJed Brown                                        MatImaginaryPart_SeqDense,
3192f4259b30SLisandro Dalcin                                        NULL,
3193f4259b30SLisandro Dalcin                                        NULL,
3194f4259b30SLisandro Dalcin                                        /*109*/ NULL,
3195f4259b30SLisandro Dalcin                                        NULL,
31968d0534beSBarry Smith                                        MatGetRowMin_SeqDense,
3197aabbc4fbSShri Abhyankar                                        MatGetColumnVector_SeqDense,
31983b49f96aSBarry Smith                                        MatMissingDiagonal_SeqDense,
3199f4259b30SLisandro Dalcin                                        /*114*/ NULL,
3200f4259b30SLisandro Dalcin                                        NULL,
3201f4259b30SLisandro Dalcin                                        NULL,
3202f4259b30SLisandro Dalcin                                        NULL,
3203f4259b30SLisandro Dalcin                                        NULL,
3204f4259b30SLisandro Dalcin                                        /*119*/ NULL,
3205f4259b30SLisandro Dalcin                                        NULL,
3206f4259b30SLisandro Dalcin                                        NULL,
3207f4259b30SLisandro Dalcin                                        NULL,
3208f4259b30SLisandro Dalcin                                        NULL,
3209f4259b30SLisandro Dalcin                                        /*124*/ NULL,
3210a873a8cdSSam Reynolds                                        MatGetColumnReductions_SeqDense,
3211f4259b30SLisandro Dalcin                                        NULL,
3212f4259b30SLisandro Dalcin                                        NULL,
3213f4259b30SLisandro Dalcin                                        NULL,
3214f4259b30SLisandro Dalcin                                        /*129*/ NULL,
3215f4259b30SLisandro Dalcin                                        NULL,
3216f4259b30SLisandro Dalcin                                        NULL,
321775648e8dSHong Zhang                                        MatTransposeMatMultNumeric_SeqDense_SeqDense,
3218f4259b30SLisandro Dalcin                                        NULL,
3219f4259b30SLisandro Dalcin                                        /*134*/ NULL,
3220f4259b30SLisandro Dalcin                                        NULL,
3221f4259b30SLisandro Dalcin                                        NULL,
3222f4259b30SLisandro Dalcin                                        NULL,
3223f4259b30SLisandro Dalcin                                        NULL,
3224f4259b30SLisandro Dalcin                                        /*139*/ NULL,
3225f4259b30SLisandro Dalcin                                        NULL,
3226f4259b30SLisandro Dalcin                                        NULL,
3227f4259b30SLisandro Dalcin                                        NULL,
3228f4259b30SLisandro Dalcin                                        NULL,
32294222ddf1SHong Zhang                                        MatCreateMPIMatConcatenateSeqMat_SeqDense,
3230f4259b30SLisandro Dalcin                                        /*145*/ NULL,
3231f4259b30SLisandro Dalcin                                        NULL,
323299a7f59eSMark Adams                                        NULL,
323399a7f59eSMark Adams                                        NULL,
32347fb60732SBarry Smith                                        NULL,
3235dec0b466SHong Zhang                                        /*150*/ NULL,
3236dec0b466SHong Zhang                                        NULL};
323790ace30eSBarry Smith 
32384b828684SBarry Smith /*@C
323911a5261eSBarry Smith   MatCreateSeqDense - Creates a `MATSEQDENSE` that
3240fb850c59SBarry Smith   is stored in column major order (the usual Fortran format).
3241289bc588SBarry Smith 
3242d083f849SBarry Smith   Collective
3243db81eaa0SLois Curfman McInnes 
324420563c6bSBarry Smith   Input Parameters:
324511a5261eSBarry Smith + comm - MPI communicator, set to `PETSC_COMM_SELF`
32460c775827SLois Curfman McInnes . m    - number of rows
324718f449edSLois Curfman McInnes . n    - number of columns
32482ef1f0ffSBarry Smith - data - optional location of matrix data in column major order.  Use `NULL` for PETSc
3249dfc5480cSLois Curfman McInnes    to control all matrix memory allocation.
325020563c6bSBarry Smith 
325120563c6bSBarry Smith   Output Parameter:
325244cd7ae7SLois Curfman McInnes . A - the matrix
325320563c6bSBarry Smith 
32542ef1f0ffSBarry Smith   Level: intermediate
32552ef1f0ffSBarry Smith 
325611a5261eSBarry Smith   Note:
325718f449edSLois Curfman McInnes   The data input variable is intended primarily for Fortran programmers
325818f449edSLois Curfman McInnes   who wish to allocate their own matrix memory space.  Most users should
32592ef1f0ffSBarry Smith   set `data` = `NULL`.
326018f449edSLois Curfman McInnes 
3261fb850c59SBarry Smith   Developer Note:
3262fb850c59SBarry Smith   Many of the matrix operations for this variant use the BLAS and LAPACK routines.
3263fb850c59SBarry Smith 
32641cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATSEQDENSE`, `MatCreate()`, `MatCreateDense()`, `MatSetValues()`
326520563c6bSBarry Smith @*/
3266d71ae5a4SJacob Faibussowitsch PetscErrorCode MatCreateSeqDense(MPI_Comm comm, PetscInt m, PetscInt n, PetscScalar *data, Mat *A)
3267d71ae5a4SJacob Faibussowitsch {
32683a40ed3dSBarry Smith   PetscFunctionBegin;
32699566063dSJacob Faibussowitsch   PetscCall(MatCreate(comm, A));
32709566063dSJacob Faibussowitsch   PetscCall(MatSetSizes(*A, m, n, m, n));
32719566063dSJacob Faibussowitsch   PetscCall(MatSetType(*A, MATSEQDENSE));
32729566063dSJacob Faibussowitsch   PetscCall(MatSeqDenseSetPreallocation(*A, data));
32733ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3274273d9f13SBarry Smith }
3275273d9f13SBarry Smith 
3276273d9f13SBarry Smith /*@C
327711a5261eSBarry Smith   MatSeqDenseSetPreallocation - Sets the array used for storing the matrix elements of a `MATSEQDENSE` matrix
3278273d9f13SBarry Smith 
3279d083f849SBarry Smith   Collective
3280273d9f13SBarry Smith 
3281273d9f13SBarry Smith   Input Parameters:
32821c4f3114SJed Brown + B    - the matrix
32832ef1f0ffSBarry Smith - data - the array (or `NULL`)
32842ef1f0ffSBarry Smith 
32852ef1f0ffSBarry Smith   Level: intermediate
3286273d9f13SBarry Smith 
328711a5261eSBarry Smith   Note:
3288273d9f13SBarry Smith   The data input variable is intended primarily for Fortran programmers
3289273d9f13SBarry Smith   who wish to allocate their own matrix memory space.  Most users should
3290284134d9SBarry Smith   need not call this routine.
3291273d9f13SBarry Smith 
32921cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATSEQDENSE`, `MatCreate()`, `MatCreateDense()`, `MatSetValues()`, `MatDenseSetLDA()`
3293273d9f13SBarry Smith @*/
3294d71ae5a4SJacob Faibussowitsch PetscErrorCode MatSeqDenseSetPreallocation(Mat B, PetscScalar data[])
3295d71ae5a4SJacob Faibussowitsch {
3296a23d5eceSKris Buschelman   PetscFunctionBegin;
3297d5ea218eSStefano Zampini   PetscValidHeaderSpecific(B, MAT_CLASSID, 1);
3298cac4c232SBarry Smith   PetscTryMethod(B, "MatSeqDenseSetPreallocation_C", (Mat, PetscScalar[]), (B, data));
32993ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3300a23d5eceSKris Buschelman }
3301a23d5eceSKris Buschelman 
3302d71ae5a4SJacob Faibussowitsch PetscErrorCode MatSeqDenseSetPreallocation_SeqDense(Mat B, PetscScalar *data)
3303d71ae5a4SJacob Faibussowitsch {
3304ad16ce7aSStefano Zampini   Mat_SeqDense *b = (Mat_SeqDense *)B->data;
3305273d9f13SBarry Smith 
3306273d9f13SBarry Smith   PetscFunctionBegin;
330728b400f6SJacob Faibussowitsch   PetscCheck(!b->matinuse, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Need to call MatDenseRestoreSubMatrix() first");
3308273d9f13SBarry Smith   B->preallocated = PETSC_TRUE;
3309a868139aSShri Abhyankar 
33109566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetUp(B->rmap));
33119566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetUp(B->cmap));
331234ef9618SShri Abhyankar 
3313ad16ce7aSStefano Zampini   if (b->lda <= 0) b->lda = B->rmap->n;
331486d161a7SShri Abhyankar 
33159e8f95c4SLisandro Dalcin   if (!data) { /* petsc-allocated storage */
33169566063dSJacob Faibussowitsch     if (!b->user_alloc) PetscCall(PetscFree(b->v));
33179566063dSJacob Faibussowitsch     PetscCall(PetscCalloc1((size_t)b->lda * B->cmap->n, &b->v));
33182205254eSKarl Rupp 
33199e8f95c4SLisandro Dalcin     b->user_alloc = PETSC_FALSE;
3320273d9f13SBarry Smith   } else { /* user-allocated storage */
33219566063dSJacob Faibussowitsch     if (!b->user_alloc) PetscCall(PetscFree(b->v));
3322273d9f13SBarry Smith     b->v          = data;
3323273d9f13SBarry Smith     b->user_alloc = PETSC_TRUE;
3324273d9f13SBarry Smith   }
33250450473dSBarry Smith   B->assembled = PETSC_TRUE;
33263ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3327273d9f13SBarry Smith }
3328273d9f13SBarry Smith 
332965b80a83SHong Zhang #if defined(PETSC_HAVE_ELEMENTAL)
3330d71ae5a4SJacob Faibussowitsch PETSC_INTERN PetscErrorCode MatConvert_SeqDense_Elemental(Mat A, MatType newtype, MatReuse reuse, Mat *newmat)
3331d71ae5a4SJacob Faibussowitsch {
3332d77f618aSHong Zhang   Mat                mat_elemental;
33331683a169SBarry Smith   const PetscScalar *array;
33341683a169SBarry Smith   PetscScalar       *v_colwise;
3335d77f618aSHong Zhang   PetscInt           M = A->rmap->N, N = A->cmap->N, i, j, k, *rows, *cols;
3336d77f618aSHong Zhang 
33378baccfbdSHong Zhang   PetscFunctionBegin;
33389566063dSJacob Faibussowitsch   PetscCall(PetscMalloc3(M * N, &v_colwise, M, &rows, N, &cols));
33399566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArrayRead(A, &array));
3340d77f618aSHong Zhang   /* convert column-wise array into row-wise v_colwise, see MatSetValues_Elemental() */
3341d77f618aSHong Zhang   k = 0;
3342d77f618aSHong Zhang   for (j = 0; j < N; j++) {
3343d77f618aSHong Zhang     cols[j] = j;
3344ad540459SPierre Jolivet     for (i = 0; i < M; i++) v_colwise[j * M + i] = array[k++];
3345d77f618aSHong Zhang   }
3346ad540459SPierre Jolivet   for (i = 0; i < M; i++) rows[i] = i;
33479566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArrayRead(A, &array));
3348d77f618aSHong Zhang 
33499566063dSJacob Faibussowitsch   PetscCall(MatCreate(PetscObjectComm((PetscObject)A), &mat_elemental));
33509566063dSJacob Faibussowitsch   PetscCall(MatSetSizes(mat_elemental, PETSC_DECIDE, PETSC_DECIDE, M, N));
33519566063dSJacob Faibussowitsch   PetscCall(MatSetType(mat_elemental, MATELEMENTAL));
33529566063dSJacob Faibussowitsch   PetscCall(MatSetUp(mat_elemental));
3353d77f618aSHong Zhang 
3354d77f618aSHong Zhang   /* PETSc-Elemental interaface uses axpy for setting off-processor entries, only ADD_VALUES is allowed */
33559566063dSJacob Faibussowitsch   PetscCall(MatSetValues(mat_elemental, M, rows, N, cols, v_colwise, ADD_VALUES));
33569566063dSJacob Faibussowitsch   PetscCall(MatAssemblyBegin(mat_elemental, MAT_FINAL_ASSEMBLY));
33579566063dSJacob Faibussowitsch   PetscCall(MatAssemblyEnd(mat_elemental, MAT_FINAL_ASSEMBLY));
33589566063dSJacob Faibussowitsch   PetscCall(PetscFree3(v_colwise, rows, cols));
3359d77f618aSHong Zhang 
3360511c6705SHong Zhang   if (reuse == MAT_INPLACE_MATRIX) {
33619566063dSJacob Faibussowitsch     PetscCall(MatHeaderReplace(A, &mat_elemental));
3362d77f618aSHong Zhang   } else {
3363d77f618aSHong Zhang     *newmat = mat_elemental;
3364d77f618aSHong Zhang   }
33653ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
33668baccfbdSHong Zhang }
336765b80a83SHong Zhang #endif
33688baccfbdSHong Zhang 
3369d71ae5a4SJacob Faibussowitsch PetscErrorCode MatDenseSetLDA_SeqDense(Mat B, PetscInt lda)
3370d71ae5a4SJacob Faibussowitsch {
33711b807ce4Svictorle   Mat_SeqDense *b = (Mat_SeqDense *)B->data;
33727422da62SJose E. Roman   PetscBool     data;
337321a2c019SBarry Smith 
33741b807ce4Svictorle   PetscFunctionBegin;
33757422da62SJose E. Roman   data = (PetscBool)((B->rmap->n > 0 && B->cmap->n > 0) ? (b->v ? PETSC_TRUE : PETSC_FALSE) : PETSC_FALSE);
3376aed4548fSBarry Smith   PetscCheck(b->user_alloc || !data || b->lda == lda, PETSC_COMM_SELF, PETSC_ERR_ORDER, "LDA cannot be changed after allocation of internal storage");
337708401ef6SPierre 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);
33781b807ce4Svictorle   b->lda = lda;
33793ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
33801b807ce4Svictorle }
33811b807ce4Svictorle 
3382d71ae5a4SJacob Faibussowitsch PetscErrorCode MatCreateMPIMatConcatenateSeqMat_SeqDense(MPI_Comm comm, Mat inmat, PetscInt n, MatReuse scall, Mat *outmat)
3383d71ae5a4SJacob Faibussowitsch {
3384d528f656SJakub Kruzik   PetscFunctionBegin;
33859566063dSJacob Faibussowitsch   PetscCall(MatCreateMPIMatConcatenateSeqMat_MPIDense(comm, inmat, n, scall, outmat));
33863ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3387d528f656SJakub Kruzik }
3388d528f656SJakub Kruzik 
3389d16ceb75SStefano Zampini PetscErrorCode MatDenseCreateColumnVec_Private(Mat A, Vec *v)
3390d16ceb75SStefano Zampini {
3391d16ceb75SStefano Zampini   PetscBool   isstd, iskok, iscuda, iship;
3392d16ceb75SStefano Zampini   PetscMPIInt size;
3393d16ceb75SStefano Zampini #if PetscDefined(HAVE_CUDA) || PetscDefined(HAVE_HIP)
3394d16ceb75SStefano Zampini   /* we pass the data of A, to prevent allocating needless GPU memory the first time VecCUPMPlaceArray is called. */
3395d16ceb75SStefano Zampini   const PetscScalar *a;
3396d16ceb75SStefano Zampini #endif
3397d16ceb75SStefano Zampini 
3398d16ceb75SStefano Zampini   PetscFunctionBegin;
3399d16ceb75SStefano Zampini   *v = NULL;
3400d16ceb75SStefano Zampini   PetscCall(PetscStrcmpAny(A->defaultvectype, &isstd, VECSTANDARD, VECSEQ, VECMPI, ""));
3401d16ceb75SStefano Zampini   PetscCall(PetscStrcmpAny(A->defaultvectype, &iskok, VECKOKKOS, VECSEQKOKKOS, VECMPIKOKKOS, ""));
3402d16ceb75SStefano Zampini   PetscCall(PetscStrcmpAny(A->defaultvectype, &iscuda, VECCUDA, VECSEQCUDA, VECMPICUDA, ""));
3403d16ceb75SStefano Zampini   PetscCall(PetscStrcmpAny(A->defaultvectype, &iship, VECHIP, VECSEQHIP, VECMPIHIP, ""));
3404d16ceb75SStefano Zampini   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)A), &size));
3405d16ceb75SStefano Zampini   if (isstd) {
3406d16ceb75SStefano Zampini     if (size > 1) PetscCall(VecCreateMPIWithArray(PetscObjectComm((PetscObject)A), A->rmap->bs, A->rmap->n, A->rmap->N, NULL, v));
3407d16ceb75SStefano Zampini     else PetscCall(VecCreateSeqWithArray(PetscObjectComm((PetscObject)A), A->rmap->bs, A->rmap->n, NULL, v));
3408d16ceb75SStefano Zampini   } else if (iskok) {
3409d16ceb75SStefano Zampini     PetscCheck(PetscDefined(HAVE_KOKKOS_KERNELS), PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Reconfigure using KOKKOS kernels support");
3410d16ceb75SStefano Zampini #if PetscDefined(HAVE_KOKKOS_KERNELS)
3411d16ceb75SStefano Zampini     if (size > 1) PetscCall(VecCreateMPIKokkosWithArray(PetscObjectComm((PetscObject)A), A->rmap->bs, A->rmap->n, A->rmap->N, NULL, v));
3412d16ceb75SStefano Zampini     else PetscCall(VecCreateSeqKokkosWithArray(PetscObjectComm((PetscObject)A), A->rmap->bs, A->rmap->n, NULL, v));
3413d16ceb75SStefano Zampini #endif
3414d16ceb75SStefano Zampini   } else if (iscuda) {
3415d16ceb75SStefano Zampini     PetscCheck(PetscDefined(HAVE_CUDA), PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Reconfigure using CUDA support");
3416d16ceb75SStefano Zampini #if PetscDefined(HAVE_CUDA)
3417d16ceb75SStefano Zampini     PetscCall(MatDenseCUDAGetArrayRead(A, &a));
3418d16ceb75SStefano Zampini     if (size > 1) PetscCall(VecCreateMPICUDAWithArrays(PetscObjectComm((PetscObject)A), A->rmap->bs, A->rmap->n, A->rmap->N, NULL, a, v));
3419d16ceb75SStefano Zampini     else PetscCall(VecCreateSeqCUDAWithArrays(PetscObjectComm((PetscObject)A), A->rmap->bs, A->rmap->n, NULL, a, v));
3420d16ceb75SStefano Zampini #endif
3421d16ceb75SStefano Zampini   } else if (iship) {
3422d16ceb75SStefano Zampini     PetscCheck(PetscDefined(HAVE_HIP), PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Reconfigure using HIP support");
3423d16ceb75SStefano Zampini #if PetscDefined(HAVE_HIP)
3424d16ceb75SStefano Zampini     PetscCall(MatDenseHIPGetArrayRead(A, &a));
3425d16ceb75SStefano Zampini     if (size > 1) PetscCall(VecCreateMPIHIPWithArrays(PetscObjectComm((PetscObject)A), A->rmap->bs, A->rmap->n, A->rmap->N, NULL, a, v));
3426d16ceb75SStefano Zampini     else PetscCall(VecCreateSeqHIPWithArrays(PetscObjectComm((PetscObject)A), A->rmap->bs, A->rmap->n, NULL, a, v));
3427d16ceb75SStefano Zampini #endif
3428d16ceb75SStefano Zampini   }
3429d16ceb75SStefano Zampini   PetscCheck(*v, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Not coded for type %s", A->defaultvectype);
3430d16ceb75SStefano Zampini   PetscFunctionReturn(PETSC_SUCCESS);
3431d16ceb75SStefano Zampini }
3432d16ceb75SStefano Zampini 
3433d71ae5a4SJacob Faibussowitsch PetscErrorCode MatDenseGetColumnVec_SeqDense(Mat A, PetscInt col, Vec *v)
3434d71ae5a4SJacob Faibussowitsch {
34356947451fSStefano Zampini   Mat_SeqDense *a = (Mat_SeqDense *)A->data;
34366947451fSStefano Zampini 
34376947451fSStefano Zampini   PetscFunctionBegin;
343828b400f6SJacob Faibussowitsch   PetscCheck(!a->vecinuse, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Need to call MatDenseRestoreColumnVec() first");
343928b400f6SJacob Faibussowitsch   PetscCheck(!a->matinuse, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Need to call MatDenseRestoreSubMatrix() first");
3440d16ceb75SStefano Zampini   if (!a->cvec) PetscCall(MatDenseCreateColumnVec_Private(A, &a->cvec));
34416947451fSStefano Zampini   a->vecinuse = col + 1;
34429566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArray(A, (PetscScalar **)&a->ptrinuse));
34439566063dSJacob Faibussowitsch   PetscCall(VecPlaceArray(a->cvec, a->ptrinuse + (size_t)col * (size_t)a->lda));
34446947451fSStefano Zampini   *v = a->cvec;
34453ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
34466947451fSStefano Zampini }
34476947451fSStefano Zampini 
3448d71ae5a4SJacob Faibussowitsch PetscErrorCode MatDenseRestoreColumnVec_SeqDense(Mat A, PetscInt col, Vec *v)
3449d71ae5a4SJacob Faibussowitsch {
34506947451fSStefano Zampini   Mat_SeqDense *a = (Mat_SeqDense *)A->data;
34516947451fSStefano Zampini 
34526947451fSStefano Zampini   PetscFunctionBegin;
345328b400f6SJacob Faibussowitsch   PetscCheck(a->vecinuse, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Need to call MatDenseGetColumnVec() first");
345428b400f6SJacob Faibussowitsch   PetscCheck(a->cvec, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Missing internal column vector");
34556947451fSStefano Zampini   a->vecinuse = 0;
34569566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArray(A, (PetscScalar **)&a->ptrinuse));
34579566063dSJacob Faibussowitsch   PetscCall(VecResetArray(a->cvec));
345875f6d85dSStefano Zampini   if (v) *v = NULL;
34593ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
34606947451fSStefano Zampini }
34616947451fSStefano Zampini 
3462d71ae5a4SJacob Faibussowitsch PetscErrorCode MatDenseGetColumnVecRead_SeqDense(Mat A, PetscInt col, Vec *v)
3463d71ae5a4SJacob Faibussowitsch {
34646947451fSStefano Zampini   Mat_SeqDense *a = (Mat_SeqDense *)A->data;
34656947451fSStefano Zampini 
34666947451fSStefano Zampini   PetscFunctionBegin;
346728b400f6SJacob Faibussowitsch   PetscCheck(!a->vecinuse, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Need to call MatDenseRestoreColumnVec() first");
346828b400f6SJacob Faibussowitsch   PetscCheck(!a->matinuse, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Need to call MatDenseRestoreSubMatrix() first");
3469d16ceb75SStefano Zampini   if (!a->cvec) PetscCall(MatDenseCreateColumnVec_Private(A, &a->cvec));
34706947451fSStefano Zampini   a->vecinuse = col + 1;
34719566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArrayRead(A, &a->ptrinuse));
3472*8e3a54c0SPierre Jolivet   PetscCall(VecPlaceArray(a->cvec, PetscSafePointerPlusOffset(a->ptrinuse, (size_t)col * (size_t)a->lda)));
34739566063dSJacob Faibussowitsch   PetscCall(VecLockReadPush(a->cvec));
34746947451fSStefano Zampini   *v = a->cvec;
34753ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
34766947451fSStefano Zampini }
34776947451fSStefano Zampini 
3478d71ae5a4SJacob Faibussowitsch PetscErrorCode MatDenseRestoreColumnVecRead_SeqDense(Mat A, PetscInt col, Vec *v)
3479d71ae5a4SJacob Faibussowitsch {
34806947451fSStefano Zampini   Mat_SeqDense *a = (Mat_SeqDense *)A->data;
34816947451fSStefano Zampini 
34826947451fSStefano Zampini   PetscFunctionBegin;
348328b400f6SJacob Faibussowitsch   PetscCheck(a->vecinuse, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Need to call MatDenseGetColumnVec() first");
348428b400f6SJacob Faibussowitsch   PetscCheck(a->cvec, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Missing internal column vector");
34856947451fSStefano Zampini   a->vecinuse = 0;
34869566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArrayRead(A, &a->ptrinuse));
34879566063dSJacob Faibussowitsch   PetscCall(VecLockReadPop(a->cvec));
34889566063dSJacob Faibussowitsch   PetscCall(VecResetArray(a->cvec));
348975f6d85dSStefano Zampini   if (v) *v = NULL;
34903ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
34916947451fSStefano Zampini }
34926947451fSStefano Zampini 
3493d71ae5a4SJacob Faibussowitsch PetscErrorCode MatDenseGetColumnVecWrite_SeqDense(Mat A, PetscInt col, Vec *v)
3494d71ae5a4SJacob Faibussowitsch {
34956947451fSStefano Zampini   Mat_SeqDense *a = (Mat_SeqDense *)A->data;
34966947451fSStefano Zampini 
34976947451fSStefano Zampini   PetscFunctionBegin;
349828b400f6SJacob Faibussowitsch   PetscCheck(!a->vecinuse, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Need to call MatDenseRestoreColumnVec() first");
349928b400f6SJacob Faibussowitsch   PetscCheck(!a->matinuse, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Need to call MatDenseRestoreSubMatrix() first");
3500d16ceb75SStefano Zampini   if (!a->cvec) PetscCall(MatDenseCreateColumnVec_Private(A, &a->cvec));
35016947451fSStefano Zampini   a->vecinuse = col + 1;
35029566063dSJacob Faibussowitsch   PetscCall(MatDenseGetArrayWrite(A, (PetscScalar **)&a->ptrinuse));
3503*8e3a54c0SPierre Jolivet   PetscCall(VecPlaceArray(a->cvec, PetscSafePointerPlusOffset(a->ptrinuse, (size_t)col * (size_t)a->lda)));
35046947451fSStefano Zampini   *v = a->cvec;
35053ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
35066947451fSStefano Zampini }
35076947451fSStefano Zampini 
3508d71ae5a4SJacob Faibussowitsch PetscErrorCode MatDenseRestoreColumnVecWrite_SeqDense(Mat A, PetscInt col, Vec *v)
3509d71ae5a4SJacob Faibussowitsch {
35106947451fSStefano Zampini   Mat_SeqDense *a = (Mat_SeqDense *)A->data;
35116947451fSStefano Zampini 
35126947451fSStefano Zampini   PetscFunctionBegin;
351328b400f6SJacob Faibussowitsch   PetscCheck(a->vecinuse, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Need to call MatDenseGetColumnVec() first");
351428b400f6SJacob Faibussowitsch   PetscCheck(a->cvec, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Missing internal column vector");
35156947451fSStefano Zampini   a->vecinuse = 0;
35169566063dSJacob Faibussowitsch   PetscCall(MatDenseRestoreArrayWrite(A, (PetscScalar **)&a->ptrinuse));
35179566063dSJacob Faibussowitsch   PetscCall(VecResetArray(a->cvec));
351875f6d85dSStefano Zampini   if (v) *v = NULL;
35193ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
35206947451fSStefano Zampini }
35216947451fSStefano Zampini 
3522d71ae5a4SJacob Faibussowitsch PetscErrorCode MatDenseGetSubMatrix_SeqDense(Mat A, PetscInt rbegin, PetscInt rend, PetscInt cbegin, PetscInt cend, Mat *v)
3523d71ae5a4SJacob Faibussowitsch {
35245ea7661aSPierre Jolivet   Mat_SeqDense *a = (Mat_SeqDense *)A->data;
35255ea7661aSPierre Jolivet 
35265ea7661aSPierre Jolivet   PetscFunctionBegin;
352728b400f6SJacob Faibussowitsch   PetscCheck(!a->vecinuse, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Need to call MatDenseRestoreColumnVec() first");
352828b400f6SJacob Faibussowitsch   PetscCheck(!a->matinuse, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Need to call MatDenseRestoreSubMatrix() first");
3529a2748737SPierre Jolivet   if (a->cmat && (cend - cbegin != a->cmat->cmap->N || rend - rbegin != a->cmat->rmap->N)) PetscCall(MatDestroy(&a->cmat));
35305ea7661aSPierre Jolivet   if (!a->cmat) {
3531*8e3a54c0SPierre 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));
35325ea7661aSPierre Jolivet   } else {
3533*8e3a54c0SPierre Jolivet     PetscCall(MatDensePlaceArray(a->cmat, PetscSafePointerPlusOffset(a->v, rbegin + (size_t)cbegin * a->lda)));
35345ea7661aSPierre Jolivet   }
35359566063dSJacob Faibussowitsch   PetscCall(MatDenseSetLDA(a->cmat, a->lda));
35365ea7661aSPierre Jolivet   a->matinuse = cbegin + 1;
35375ea7661aSPierre Jolivet   *v          = a->cmat;
353847d993e7Ssuyashtn #if defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
353975f6d85dSStefano Zampini   A->offloadmask = PETSC_OFFLOAD_CPU;
354075f6d85dSStefano Zampini #endif
35413ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
35425ea7661aSPierre Jolivet }
35435ea7661aSPierre Jolivet 
3544d71ae5a4SJacob Faibussowitsch PetscErrorCode MatDenseRestoreSubMatrix_SeqDense(Mat A, Mat *v)
3545d71ae5a4SJacob Faibussowitsch {
35465ea7661aSPierre Jolivet   Mat_SeqDense *a = (Mat_SeqDense *)A->data;
35475ea7661aSPierre Jolivet 
35485ea7661aSPierre Jolivet   PetscFunctionBegin;
354928b400f6SJacob Faibussowitsch   PetscCheck(a->matinuse, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Need to call MatDenseGetSubMatrix() first");
355028b400f6SJacob Faibussowitsch   PetscCheck(a->cmat, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Missing internal column matrix");
355108401ef6SPierre Jolivet   PetscCheck(*v == a->cmat, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Not the matrix obtained from MatDenseGetSubMatrix()");
35525ea7661aSPierre Jolivet   a->matinuse = 0;
35539566063dSJacob Faibussowitsch   PetscCall(MatDenseResetArray(a->cmat));
3554742765d3SMatthew Knepley   if (v) *v = NULL;
355547d993e7Ssuyashtn #if defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
35563faff063SStefano Zampini   A->offloadmask = PETSC_OFFLOAD_CPU;
35573faff063SStefano Zampini #endif
35583ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
35595ea7661aSPierre Jolivet }
35605ea7661aSPierre Jolivet 
35610bad9183SKris Buschelman /*MC
3562fafad747SKris Buschelman    MATSEQDENSE - MATSEQDENSE = "seqdense" - A matrix type to be used for sequential dense matrices.
35630bad9183SKris Buschelman 
35642ef1f0ffSBarry Smith    Options Database Key:
356511a5261eSBarry Smith . -mat_type seqdense - sets the matrix type to `MATSEQDENSE` during a call to `MatSetFromOptions()`
35660bad9183SKris Buschelman 
35670bad9183SKris Buschelman   Level: beginner
35680bad9183SKris Buschelman 
35691cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATSEQDENSE`, `MatCreateSeqDense()`
35700bad9183SKris Buschelman M*/
3571d71ae5a4SJacob Faibussowitsch PetscErrorCode MatCreate_SeqDense(Mat B)
3572d71ae5a4SJacob Faibussowitsch {
3573273d9f13SBarry Smith   Mat_SeqDense *b;
35747c334f02SBarry Smith   PetscMPIInt   size;
3575273d9f13SBarry Smith 
3576273d9f13SBarry Smith   PetscFunctionBegin;
35779566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)B), &size));
357808401ef6SPierre Jolivet   PetscCheck(size <= 1, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Comm must be of size 1");
357955659b69SBarry Smith 
35804dfa11a4SJacob Faibussowitsch   PetscCall(PetscNew(&b));
358144cd7ae7SLois Curfman McInnes   B->data   = (void *)b;
3582aea10558SJacob Faibussowitsch   B->ops[0] = MatOps_Values;
358318f449edSLois Curfman McInnes 
3584273d9f13SBarry Smith   b->roworiented = PETSC_TRUE;
35854e220ebcSLois Curfman McInnes 
35869566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatQRFactor_C", MatQRFactor_SeqDense));
35879566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatDenseGetLDA_C", MatDenseGetLDA_SeqDense));
35889566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatDenseSetLDA_C", MatDenseSetLDA_SeqDense));
35899566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatDenseGetArray_C", MatDenseGetArray_SeqDense));
35909566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatDenseRestoreArray_C", MatDenseRestoreArray_SeqDense));
35919566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatDensePlaceArray_C", MatDensePlaceArray_SeqDense));
35929566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatDenseResetArray_C", MatDenseResetArray_SeqDense));
35939566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatDenseReplaceArray_C", MatDenseReplaceArray_SeqDense));
35949566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatDenseGetArrayRead_C", MatDenseGetArray_SeqDense));
35959566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatDenseRestoreArrayRead_C", MatDenseRestoreArray_SeqDense));
35969566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatDenseGetArrayWrite_C", MatDenseGetArray_SeqDense));
35979566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatDenseRestoreArrayWrite_C", MatDenseRestoreArray_SeqDense));
35989566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatConvert_seqdense_seqaij_C", MatConvert_SeqDense_SeqAIJ));
35998baccfbdSHong Zhang #if defined(PETSC_HAVE_ELEMENTAL)
36009566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatConvert_seqdense_elemental_C", MatConvert_SeqDense_Elemental));
36018baccfbdSHong Zhang #endif
3602d24d4204SJose E. Roman #if defined(PETSC_HAVE_SCALAPACK)
36039566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatConvert_seqdense_scalapack_C", MatConvert_Dense_ScaLAPACK));
3604d24d4204SJose E. Roman #endif
36052bf066beSStefano Zampini #if defined(PETSC_HAVE_CUDA)
36069566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatConvert_seqdense_seqdensecuda_C", MatConvert_SeqDense_SeqDenseCUDA));
36079566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatProductSetFromOptions_seqdensecuda_seqdensecuda_C", MatProductSetFromOptions_SeqDense));
36089566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatProductSetFromOptions_seqdensecuda_seqdense_C", MatProductSetFromOptions_SeqDense));
36099566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatProductSetFromOptions_seqdense_seqdensecuda_C", MatProductSetFromOptions_SeqDense));
36102bf066beSStefano Zampini #endif
361147d993e7Ssuyashtn #if defined(PETSC_HAVE_HIP)
361247d993e7Ssuyashtn   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatConvert_seqdense_seqdensehip_C", MatConvert_SeqDense_SeqDenseHIP));
361347d993e7Ssuyashtn   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatProductSetFromOptions_seqdensehip_seqdensehip_C", MatProductSetFromOptions_SeqDense));
361447d993e7Ssuyashtn   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatProductSetFromOptions_seqdensehip_seqdense_C", MatProductSetFromOptions_SeqDense));
361547d993e7Ssuyashtn   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatProductSetFromOptions_seqdense_seqdensehip_C", MatProductSetFromOptions_SeqDense));
361647d993e7Ssuyashtn #endif
36179566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatSeqDenseSetPreallocation_C", MatSeqDenseSetPreallocation_SeqDense));
36189566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatProductSetFromOptions_seqaij_seqdense_C", MatProductSetFromOptions_SeqAIJ_SeqDense));
36199566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatProductSetFromOptions_seqdense_seqdense_C", MatProductSetFromOptions_SeqDense));
36209566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatProductSetFromOptions_seqbaij_seqdense_C", MatProductSetFromOptions_SeqXBAIJ_SeqDense));
36219566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatProductSetFromOptions_seqsbaij_seqdense_C", MatProductSetFromOptions_SeqXBAIJ_SeqDense));
362296e6d5c4SRichard Tran Mills 
36239566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatDenseGetColumn_C", MatDenseGetColumn_SeqDense));
36249566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatDenseRestoreColumn_C", MatDenseRestoreColumn_SeqDense));
36259566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatDenseGetColumnVec_C", MatDenseGetColumnVec_SeqDense));
36269566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatDenseRestoreColumnVec_C", MatDenseRestoreColumnVec_SeqDense));
36279566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatDenseGetColumnVecRead_C", MatDenseGetColumnVecRead_SeqDense));
36289566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatDenseRestoreColumnVecRead_C", MatDenseRestoreColumnVecRead_SeqDense));
36299566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatDenseGetColumnVecWrite_C", MatDenseGetColumnVecWrite_SeqDense));
36309566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatDenseRestoreColumnVecWrite_C", MatDenseRestoreColumnVecWrite_SeqDense));
36319566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatDenseGetSubMatrix_C", MatDenseGetSubMatrix_SeqDense));
36329566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatDenseRestoreSubMatrix_C", MatDenseRestoreSubMatrix_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 @*/
3656d71ae5a4SJacob Faibussowitsch 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 @*/
3679d71ae5a4SJacob Faibussowitsch 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