Actual source code: dense.c
1: /*
2: Defines the basic matrix operations for sequential dense.
3: Portions of this code are under:
4: Copyright (c) 2022 Advanced Micro Devices, Inc. All rights reserved.
5: */
7: #include <../src/mat/impls/dense/seq/dense.h>
8: #include <../src/mat/impls/dense/mpi/mpidense.h>
9: #include <petscblaslapack.h>
10: #include <../src/mat/impls/aij/seq/aij.h>
11: #include <petsc/private/vecimpl.h>
13: PetscErrorCode MatSeqDenseSymmetrize_Private(Mat A, PetscBool hermitian)
14: {
15: Mat_SeqDense *mat = (Mat_SeqDense *)A->data;
16: PetscInt j, k, n = A->rmap->n;
17: PetscScalar *v;
19: PetscFunctionBegin;
20: PetscCheck(A->rmap->n == A->cmap->n, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Cannot symmetrize a rectangular matrix");
21: PetscCall(MatDenseGetArray(A, &v));
22: if (!hermitian) {
23: for (k = 0; k < n; k++) {
24: for (j = k; j < n; j++) v[j * mat->lda + k] = v[k * mat->lda + j];
25: }
26: } else {
27: for (k = 0; k < n; k++) {
28: for (j = k; j < n; j++) v[j * mat->lda + k] = PetscConj(v[k * mat->lda + j]);
29: }
30: }
31: PetscCall(MatDenseRestoreArray(A, &v));
32: PetscFunctionReturn(PETSC_SUCCESS);
33: }
35: PetscErrorCode MatSeqDenseInvertFactors_Private(Mat A)
36: {
37: Mat_SeqDense *mat = (Mat_SeqDense *)A->data;
38: PetscBLASInt info, n;
40: PetscFunctionBegin;
41: if (!A->rmap->n || !A->cmap->n) PetscFunctionReturn(PETSC_SUCCESS);
42: PetscCall(PetscBLASIntCast(A->cmap->n, &n));
43: if (A->factortype == MAT_FACTOR_LU) {
44: PetscCheck(mat->pivots, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Pivots not present");
45: if (!mat->fwork) {
46: mat->lfwork = n;
47: PetscCall(PetscMalloc1(mat->lfwork, &mat->fwork));
48: }
49: PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF));
50: PetscCallBLAS("LAPACKgetri", LAPACKgetri_(&n, mat->v, &mat->lda, mat->pivots, mat->fwork, &mat->lfwork, &info));
51: PetscCall(PetscFPTrapPop());
52: PetscCall(PetscLogFlops((1.0 * A->cmap->n * A->cmap->n * A->cmap->n) / 3.0));
53: } else if (A->factortype == MAT_FACTOR_CHOLESKY) {
54: if (A->spd == PETSC_BOOL3_TRUE) {
55: PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF));
56: PetscCallBLAS("LAPACKpotri", LAPACKpotri_("L", &n, mat->v, &mat->lda, &info));
57: PetscCall(PetscFPTrapPop());
58: PetscCall(MatSeqDenseSymmetrize_Private(A, PETSC_TRUE));
59: #if defined(PETSC_USE_COMPLEX)
60: } else if (A->hermitian == PETSC_BOOL3_TRUE) {
61: PetscCheck(mat->pivots, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Pivots not present");
62: PetscCheck(mat->fwork, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Fwork not present");
63: PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF));
64: PetscCallBLAS("LAPACKhetri", LAPACKhetri_("L", &n, mat->v, &mat->lda, mat->pivots, mat->fwork, &info));
65: PetscCall(PetscFPTrapPop());
66: PetscCall(MatSeqDenseSymmetrize_Private(A, PETSC_TRUE));
67: #endif
68: } else { /* symmetric case */
69: PetscCheck(mat->pivots, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Pivots not present");
70: PetscCheck(mat->fwork, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Fwork not present");
71: PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF));
72: PetscCallBLAS("LAPACKsytri", LAPACKsytri_("L", &n, mat->v, &mat->lda, mat->pivots, mat->fwork, &info));
73: PetscCall(PetscFPTrapPop());
74: PetscCall(MatSeqDenseSymmetrize_Private(A, PETSC_FALSE));
75: }
76: PetscCheck(!info, PETSC_COMM_SELF, PETSC_ERR_MAT_CH_ZRPVT, "Bad Inversion: zero pivot in row %" PetscInt_FMT, (PetscInt)info - 1);
77: PetscCall(PetscLogFlops((1.0 * A->cmap->n * A->cmap->n * A->cmap->n) / 3.0));
78: } else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Matrix must be factored to solve");
80: A->ops->solve = NULL;
81: A->ops->matsolve = NULL;
82: A->ops->solvetranspose = NULL;
83: A->ops->matsolvetranspose = NULL;
84: A->ops->solveadd = NULL;
85: A->ops->solvetransposeadd = NULL;
86: A->factortype = MAT_FACTOR_NONE;
87: PetscCall(PetscFree(A->solvertype));
88: PetscFunctionReturn(PETSC_SUCCESS);
89: }
91: static PetscErrorCode MatZeroRowsColumns_SeqDense(Mat A, PetscInt N, const PetscInt rows[], PetscScalar diag, Vec x, Vec b)
92: {
93: Mat_SeqDense *l = (Mat_SeqDense *)A->data;
94: PetscInt m = l->lda, n = A->cmap->n, r = A->rmap->n, i, j;
95: PetscScalar *slot, *bb, *v;
96: const PetscScalar *xx;
98: PetscFunctionBegin;
99: if (PetscDefined(USE_DEBUG)) {
100: for (i = 0; i < N; i++) {
101: PetscCheck(rows[i] >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Negative row requested to be zeroed");
102: 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);
103: 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);
104: }
105: }
106: if (!N) PetscFunctionReturn(PETSC_SUCCESS);
108: /* fix right-hand side if needed */
109: if (x && b) {
110: Vec xt;
112: PetscCheck(A->rmap->n == A->cmap->n, PETSC_COMM_SELF, PETSC_ERR_SUP, "Only coded for square matrices");
113: PetscCall(VecDuplicate(x, &xt));
114: PetscCall(VecCopy(x, xt));
115: PetscCall(VecScale(xt, -1.0));
116: PetscCall(MatMultAdd(A, xt, b, b));
117: PetscCall(VecDestroy(&xt));
118: PetscCall(VecGetArrayRead(x, &xx));
119: PetscCall(VecGetArray(b, &bb));
120: for (i = 0; i < N; i++) bb[rows[i]] = diag * xx[rows[i]];
121: PetscCall(VecRestoreArrayRead(x, &xx));
122: PetscCall(VecRestoreArray(b, &bb));
123: }
125: PetscCall(MatDenseGetArray(A, &v));
126: for (i = 0; i < N; i++) {
127: slot = v + rows[i] * m;
128: PetscCall(PetscArrayzero(slot, r));
129: }
130: for (i = 0; i < N; i++) {
131: slot = v + rows[i];
132: for (j = 0; j < n; j++) {
133: *slot = 0.0;
134: slot += m;
135: }
136: }
137: if (diag != 0.0) {
138: PetscCheck(A->rmap->n == A->cmap->n, PETSC_COMM_SELF, PETSC_ERR_SUP, "Only coded for square matrices");
139: for (i = 0; i < N; i++) {
140: slot = v + (m + 1) * rows[i];
141: *slot = diag;
142: }
143: }
144: PetscCall(MatDenseRestoreArray(A, &v));
145: PetscFunctionReturn(PETSC_SUCCESS);
146: }
148: PETSC_INTERN PetscErrorCode MatConvert_SeqAIJ_SeqDense(Mat A, MatType newtype, MatReuse reuse, Mat *newmat)
149: {
150: Mat B = NULL;
151: Mat_SeqAIJ *a = (Mat_SeqAIJ *)A->data;
152: Mat_SeqDense *b;
153: PetscInt *ai = a->i, *aj = a->j, m = A->rmap->N, n = A->cmap->N, i;
154: const MatScalar *av;
155: PetscBool isseqdense;
157: PetscFunctionBegin;
158: if (reuse == MAT_REUSE_MATRIX) {
159: PetscCall(PetscObjectTypeCompare((PetscObject)*newmat, MATSEQDENSE, &isseqdense));
160: PetscCheck(isseqdense, PetscObjectComm((PetscObject)*newmat), PETSC_ERR_USER, "Cannot reuse matrix of type %s", ((PetscObject)*newmat)->type_name);
161: }
162: if (reuse != MAT_REUSE_MATRIX) {
163: PetscCall(MatCreate(PetscObjectComm((PetscObject)A), &B));
164: PetscCall(MatSetSizes(B, m, n, m, n));
165: PetscCall(MatSetType(B, MATSEQDENSE));
166: PetscCall(MatSeqDenseSetPreallocation(B, NULL));
167: b = (Mat_SeqDense *)B->data;
168: } else {
169: b = (Mat_SeqDense *)((*newmat)->data);
170: for (i = 0; i < n; i++) PetscCall(PetscArrayzero(b->v + i * b->lda, m));
171: }
172: PetscCall(MatSeqAIJGetArrayRead(A, &av));
173: for (i = 0; i < m; i++) {
174: PetscInt j;
175: for (j = 0; j < ai[1] - ai[0]; j++) {
176: b->v[*aj * b->lda + i] = *av;
177: aj++;
178: av++;
179: }
180: ai++;
181: }
182: PetscCall(MatSeqAIJRestoreArrayRead(A, &av));
184: if (reuse == MAT_INPLACE_MATRIX) {
185: PetscCall(MatAssemblyBegin(B, MAT_FINAL_ASSEMBLY));
186: PetscCall(MatAssemblyEnd(B, MAT_FINAL_ASSEMBLY));
187: PetscCall(MatHeaderReplace(A, &B));
188: } else {
189: if (B) *newmat = B;
190: PetscCall(MatAssemblyBegin(*newmat, MAT_FINAL_ASSEMBLY));
191: PetscCall(MatAssemblyEnd(*newmat, MAT_FINAL_ASSEMBLY));
192: }
193: PetscFunctionReturn(PETSC_SUCCESS);
194: }
196: PETSC_INTERN PetscErrorCode MatConvert_SeqDense_SeqAIJ(Mat A, MatType newtype, MatReuse reuse, Mat *newmat)
197: {
198: Mat B = NULL;
199: Mat_SeqDense *a = (Mat_SeqDense *)A->data;
200: PetscInt i, j;
201: PetscInt *rows, *nnz;
202: MatScalar *aa = a->v, *vals;
204: PetscFunctionBegin;
205: PetscCall(PetscCalloc3(A->rmap->n, &rows, A->rmap->n, &nnz, A->rmap->n, &vals));
206: if (reuse != MAT_REUSE_MATRIX) {
207: PetscCall(MatCreate(PetscObjectComm((PetscObject)A), &B));
208: PetscCall(MatSetSizes(B, A->rmap->n, A->cmap->n, A->rmap->N, A->cmap->N));
209: PetscCall(MatSetType(B, MATSEQAIJ));
210: for (j = 0; j < A->cmap->n; j++) {
211: for (i = 0; i < A->rmap->n; i++)
212: if (aa[i] != 0.0 || (i == j && A->cmap->n == A->rmap->n)) ++nnz[i];
213: aa += a->lda;
214: }
215: PetscCall(MatSeqAIJSetPreallocation(B, PETSC_DETERMINE, nnz));
216: } else B = *newmat;
217: aa = a->v;
218: for (j = 0; j < A->cmap->n; j++) {
219: PetscInt numRows = 0;
220: for (i = 0; i < A->rmap->n; i++)
221: if (aa[i] != 0.0 || (i == j && A->cmap->n == A->rmap->n)) {
222: rows[numRows] = i;
223: vals[numRows++] = aa[i];
224: }
225: PetscCall(MatSetValues(B, numRows, rows, 1, &j, vals, INSERT_VALUES));
226: aa += a->lda;
227: }
228: PetscCall(PetscFree3(rows, nnz, vals));
229: PetscCall(MatAssemblyBegin(B, MAT_FINAL_ASSEMBLY));
230: PetscCall(MatAssemblyEnd(B, MAT_FINAL_ASSEMBLY));
232: if (reuse == MAT_INPLACE_MATRIX) {
233: PetscCall(MatHeaderReplace(A, &B));
234: } else if (reuse != MAT_REUSE_MATRIX) *newmat = B;
235: PetscFunctionReturn(PETSC_SUCCESS);
236: }
238: PetscErrorCode MatAXPY_SeqDense(Mat Y, PetscScalar alpha, Mat X, MatStructure str)
239: {
240: Mat_SeqDense *x = (Mat_SeqDense *)X->data, *y = (Mat_SeqDense *)Y->data;
241: const PetscScalar *xv;
242: PetscScalar *yv;
243: PetscBLASInt N, m, ldax = 0, lday = 0, one = 1;
245: PetscFunctionBegin;
246: PetscCall(MatDenseGetArrayRead(X, &xv));
247: PetscCall(MatDenseGetArray(Y, &yv));
248: PetscCall(PetscBLASIntCast(X->rmap->n * X->cmap->n, &N));
249: PetscCall(PetscBLASIntCast(X->rmap->n, &m));
250: PetscCall(PetscBLASIntCast(x->lda, &ldax));
251: PetscCall(PetscBLASIntCast(y->lda, &lday));
252: if (ldax > m || lday > m) {
253: for (PetscInt j = 0; j < X->cmap->n; j++) PetscCallBLAS("BLASaxpy", BLASaxpy_(&m, &alpha, PetscSafePointerPlusOffset(xv, j * ldax), &one, PetscSafePointerPlusOffset(yv, j * lday), &one));
254: } else {
255: PetscCallBLAS("BLASaxpy", BLASaxpy_(&N, &alpha, xv, &one, yv, &one));
256: }
257: PetscCall(MatDenseRestoreArrayRead(X, &xv));
258: PetscCall(MatDenseRestoreArray(Y, &yv));
259: PetscCall(PetscLogFlops(PetscMax(2.0 * N - 1, 0)));
260: PetscFunctionReturn(PETSC_SUCCESS);
261: }
263: static PetscErrorCode MatGetInfo_SeqDense(Mat A, MatInfoType flag, MatInfo *info)
264: {
265: PetscLogDouble N = A->rmap->n * A->cmap->n;
267: PetscFunctionBegin;
268: info->block_size = 1.0;
269: info->nz_allocated = N;
270: info->nz_used = N;
271: info->nz_unneeded = 0;
272: info->assemblies = A->num_ass;
273: info->mallocs = 0;
274: info->memory = 0; /* REVIEW ME */
275: info->fill_ratio_given = 0;
276: info->fill_ratio_needed = 0;
277: info->factor_mallocs = 0;
278: PetscFunctionReturn(PETSC_SUCCESS);
279: }
281: PetscErrorCode MatScale_SeqDense(Mat A, PetscScalar alpha)
282: {
283: Mat_SeqDense *a = (Mat_SeqDense *)A->data;
284: PetscScalar *v;
285: PetscBLASInt one = 1, j, nz, lda = 0;
287: PetscFunctionBegin;
288: PetscCall(MatDenseGetArray(A, &v));
289: PetscCall(PetscBLASIntCast(a->lda, &lda));
290: if (lda > A->rmap->n) {
291: PetscCall(PetscBLASIntCast(A->rmap->n, &nz));
292: for (j = 0; j < A->cmap->n; j++) PetscCallBLAS("BLASscal", BLASscal_(&nz, &alpha, v + j * lda, &one));
293: } else {
294: PetscCall(PetscBLASIntCast(A->rmap->n * A->cmap->n, &nz));
295: PetscCallBLAS("BLASscal", BLASscal_(&nz, &alpha, v, &one));
296: }
297: PetscCall(PetscLogFlops(A->rmap->n * A->cmap->n));
298: PetscCall(MatDenseRestoreArray(A, &v));
299: PetscFunctionReturn(PETSC_SUCCESS);
300: }
302: PetscErrorCode MatShift_SeqDense(Mat A, PetscScalar alpha)
303: {
304: Mat_SeqDense *a = (Mat_SeqDense *)A->data;
305: PetscScalar *v;
306: PetscInt j, k;
308: PetscFunctionBegin;
309: PetscCall(MatDenseGetArray(A, &v));
310: k = PetscMin(A->rmap->n, A->cmap->n);
311: for (j = 0; j < k; j++) v[j + j * a->lda] += alpha;
312: PetscCall(PetscLogFlops(k));
313: PetscCall(MatDenseRestoreArray(A, &v));
314: PetscFunctionReturn(PETSC_SUCCESS);
315: }
317: static PetscErrorCode MatIsHermitian_SeqDense(Mat A, PetscReal rtol, PetscBool *fl)
318: {
319: Mat_SeqDense *a = (Mat_SeqDense *)A->data;
320: PetscInt i, j, m = A->rmap->n, N = a->lda;
321: const PetscScalar *v;
323: PetscFunctionBegin;
324: *fl = PETSC_FALSE;
325: if (A->rmap->n != A->cmap->n) PetscFunctionReturn(PETSC_SUCCESS);
326: PetscCall(MatDenseGetArrayRead(A, &v));
327: for (i = 0; i < m; i++) {
328: for (j = i; j < m; j++) {
329: if (PetscAbsScalar(v[i + j * N] - PetscConj(v[j + i * N])) > rtol) goto restore;
330: }
331: }
332: *fl = PETSC_TRUE;
333: restore:
334: PetscCall(MatDenseRestoreArrayRead(A, &v));
335: PetscFunctionReturn(PETSC_SUCCESS);
336: }
338: static PetscErrorCode MatIsSymmetric_SeqDense(Mat A, PetscReal rtol, PetscBool *fl)
339: {
340: Mat_SeqDense *a = (Mat_SeqDense *)A->data;
341: PetscInt i, j, m = A->rmap->n, N = a->lda;
342: const PetscScalar *v;
344: PetscFunctionBegin;
345: *fl = PETSC_FALSE;
346: if (A->rmap->n != A->cmap->n) PetscFunctionReturn(PETSC_SUCCESS);
347: PetscCall(MatDenseGetArrayRead(A, &v));
348: for (i = 0; i < m; i++) {
349: for (j = i; j < m; j++) {
350: if (PetscAbsScalar(v[i + j * N] - v[j + i * N]) > rtol) goto restore;
351: }
352: }
353: *fl = PETSC_TRUE;
354: restore:
355: PetscCall(MatDenseRestoreArrayRead(A, &v));
356: PetscFunctionReturn(PETSC_SUCCESS);
357: }
359: PetscErrorCode MatDuplicateNoCreate_SeqDense(Mat newi, Mat A, MatDuplicateOption cpvalues)
360: {
361: Mat_SeqDense *mat = (Mat_SeqDense *)A->data;
362: PetscInt lda = (PetscInt)mat->lda, j, m, nlda = lda;
363: PetscBool isdensecpu;
365: PetscFunctionBegin;
366: PetscCall(PetscLayoutReference(A->rmap, &newi->rmap));
367: PetscCall(PetscLayoutReference(A->cmap, &newi->cmap));
368: if (cpvalues == MAT_SHARE_NONZERO_PATTERN) { /* propagate LDA */
369: PetscCall(MatDenseSetLDA(newi, lda));
370: }
371: PetscCall(PetscObjectTypeCompare((PetscObject)newi, MATSEQDENSE, &isdensecpu));
372: if (isdensecpu) PetscCall(MatSeqDenseSetPreallocation(newi, NULL));
373: if (cpvalues == MAT_COPY_VALUES) {
374: const PetscScalar *av;
375: PetscScalar *v;
377: PetscCall(MatDenseGetArrayRead(A, &av));
378: PetscCall(MatDenseGetArrayWrite(newi, &v));
379: PetscCall(MatDenseGetLDA(newi, &nlda));
380: m = A->rmap->n;
381: if (lda > m || nlda > m) {
382: for (j = 0; j < A->cmap->n; j++) PetscCall(PetscArraycpy(PetscSafePointerPlusOffset(v, j * nlda), PetscSafePointerPlusOffset(av, j * lda), m));
383: } else {
384: PetscCall(PetscArraycpy(v, av, A->rmap->n * A->cmap->n));
385: }
386: PetscCall(MatDenseRestoreArrayWrite(newi, &v));
387: PetscCall(MatDenseRestoreArrayRead(A, &av));
388: }
389: PetscFunctionReturn(PETSC_SUCCESS);
390: }
392: PetscErrorCode MatDuplicate_SeqDense(Mat A, MatDuplicateOption cpvalues, Mat *newmat)
393: {
394: PetscFunctionBegin;
395: PetscCall(MatCreate(PetscObjectComm((PetscObject)A), newmat));
396: PetscCall(MatSetSizes(*newmat, A->rmap->n, A->cmap->n, A->rmap->n, A->cmap->n));
397: PetscCall(MatSetType(*newmat, ((PetscObject)A)->type_name));
398: PetscCall(MatDuplicateNoCreate_SeqDense(*newmat, A, cpvalues));
399: PetscFunctionReturn(PETSC_SUCCESS);
400: }
402: static PetscErrorCode MatSolve_SeqDense_Internal_LU(Mat A, PetscScalar *x, PetscBLASInt ldx, PetscBLASInt m, PetscBLASInt nrhs, PetscBLASInt k, PetscBool T)
403: {
404: Mat_SeqDense *mat = (Mat_SeqDense *)A->data;
405: PetscBLASInt info;
407: PetscFunctionBegin;
408: PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF));
409: PetscCallBLAS("LAPACKgetrs", LAPACKgetrs_(T ? "T" : "N", &m, &nrhs, mat->v, &mat->lda, mat->pivots, x, &m, &info));
410: PetscCall(PetscFPTrapPop());
411: PetscCheck(!info, PETSC_COMM_SELF, PETSC_ERR_LIB, "GETRS - Bad solve %d", (int)info);
412: PetscCall(PetscLogFlops(nrhs * (2.0 * m * m - m)));
413: PetscFunctionReturn(PETSC_SUCCESS);
414: }
416: static PetscErrorCode MatConjugate_SeqDense(Mat);
418: static PetscErrorCode MatSolve_SeqDense_Internal_Cholesky(Mat A, PetscScalar *x, PetscBLASInt ldx, PetscBLASInt m, PetscBLASInt nrhs, PetscBLASInt k, PetscBool T)
419: {
420: Mat_SeqDense *mat = (Mat_SeqDense *)A->data;
421: PetscBLASInt info;
423: PetscFunctionBegin;
424: if (A->spd == PETSC_BOOL3_TRUE) {
425: if (PetscDefined(USE_COMPLEX) && T) PetscCall(MatConjugate_SeqDense(A));
426: PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF));
427: PetscCallBLAS("LAPACKpotrs", LAPACKpotrs_("L", &m, &nrhs, mat->v, &mat->lda, x, &m, &info));
428: PetscCall(PetscFPTrapPop());
429: PetscCheck(!info, PETSC_COMM_SELF, PETSC_ERR_LIB, "POTRS Bad solve %d", (int)info);
430: if (PetscDefined(USE_COMPLEX) && T) PetscCall(MatConjugate_SeqDense(A));
431: #if defined(PETSC_USE_COMPLEX)
432: } else if (A->hermitian == PETSC_BOOL3_TRUE) {
433: if (T) PetscCall(MatConjugate_SeqDense(A));
434: PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF));
435: PetscCallBLAS("LAPACKhetrs", LAPACKhetrs_("L", &m, &nrhs, mat->v, &mat->lda, mat->pivots, x, &m, &info));
436: PetscCall(PetscFPTrapPop());
437: PetscCheck(!info, PETSC_COMM_SELF, PETSC_ERR_LIB, "HETRS Bad solve %d", (int)info);
438: if (T) PetscCall(MatConjugate_SeqDense(A));
439: #endif
440: } else { /* symmetric case */
441: PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF));
442: PetscCallBLAS("LAPACKsytrs", LAPACKsytrs_("L", &m, &nrhs, mat->v, &mat->lda, mat->pivots, x, &m, &info));
443: PetscCall(PetscFPTrapPop());
444: PetscCheck(!info, PETSC_COMM_SELF, PETSC_ERR_LIB, "SYTRS Bad solve %d", (int)info);
445: }
446: PetscCall(PetscLogFlops(nrhs * (2.0 * m * m - m)));
447: PetscFunctionReturn(PETSC_SUCCESS);
448: }
450: static PetscErrorCode MatSolve_SeqDense_Internal_QR(Mat A, PetscScalar *x, PetscBLASInt ldx, PetscBLASInt m, PetscBLASInt nrhs, PetscBLASInt k)
451: {
452: Mat_SeqDense *mat = (Mat_SeqDense *)A->data;
453: PetscBLASInt info;
454: char trans;
456: PetscFunctionBegin;
457: if (PetscDefined(USE_COMPLEX)) {
458: trans = 'C';
459: } else {
460: trans = 'T';
461: }
462: PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF));
463: { /* lwork depends on the number of right-hand sides */
464: PetscBLASInt nlfwork, lfwork = -1;
465: PetscScalar fwork;
467: PetscCallBLAS("LAPACKormqr", LAPACKormqr_("L", &trans, &m, &nrhs, &mat->rank, mat->v, &mat->lda, mat->tau, x, &ldx, &fwork, &lfwork, &info));
468: nlfwork = (PetscBLASInt)PetscRealPart(fwork);
469: if (nlfwork > mat->lfwork) {
470: mat->lfwork = nlfwork;
471: PetscCall(PetscFree(mat->fwork));
472: PetscCall(PetscMalloc1(mat->lfwork, &mat->fwork));
473: }
474: }
475: PetscCallBLAS("LAPACKormqr", LAPACKormqr_("L", &trans, &m, &nrhs, &mat->rank, mat->v, &mat->lda, mat->tau, x, &ldx, mat->fwork, &mat->lfwork, &info));
476: PetscCall(PetscFPTrapPop());
477: PetscCheck(!info, PETSC_COMM_SELF, PETSC_ERR_LIB, "ORMQR - Bad orthogonal transform %d", (int)info);
478: PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF));
479: PetscCallBLAS("LAPACKtrtrs", LAPACKtrtrs_("U", "N", "N", &mat->rank, &nrhs, mat->v, &mat->lda, x, &ldx, &info));
480: PetscCall(PetscFPTrapPop());
481: PetscCheck(!info, PETSC_COMM_SELF, PETSC_ERR_LIB, "TRTRS - Bad triangular solve %d", (int)info);
482: for (PetscInt j = 0; j < nrhs; j++) {
483: for (PetscInt i = mat->rank; i < k; i++) x[j * ldx + i] = 0.;
484: }
485: PetscCall(PetscLogFlops(nrhs * (4.0 * m * mat->rank - PetscSqr(mat->rank))));
486: PetscFunctionReturn(PETSC_SUCCESS);
487: }
489: static PetscErrorCode MatSolveTranspose_SeqDense_Internal_QR(Mat A, PetscScalar *x, PetscBLASInt ldx, PetscBLASInt m, PetscBLASInt nrhs, PetscBLASInt k)
490: {
491: Mat_SeqDense *mat = (Mat_SeqDense *)A->data;
492: PetscBLASInt info;
494: PetscFunctionBegin;
495: if (A->rmap->n == A->cmap->n && mat->rank == A->rmap->n) {
496: PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF));
497: PetscCallBLAS("LAPACKtrtrs", LAPACKtrtrs_("U", "T", "N", &m, &nrhs, mat->v, &mat->lda, x, &ldx, &info));
498: PetscCall(PetscFPTrapPop());
499: PetscCheck(!info, PETSC_COMM_SELF, PETSC_ERR_LIB, "TRTRS - Bad triangular solve %d", (int)info);
500: if (PetscDefined(USE_COMPLEX)) PetscCall(MatConjugate_SeqDense(A));
501: { /* lwork depends on the number of right-hand sides */
502: PetscBLASInt nlfwork, lfwork = -1;
503: PetscScalar fwork;
505: PetscCallBLAS("LAPACKormqr", LAPACKormqr_("L", "N", &m, &nrhs, &mat->rank, mat->v, &mat->lda, mat->tau, x, &ldx, &fwork, &lfwork, &info));
506: nlfwork = (PetscBLASInt)PetscRealPart(fwork);
507: if (nlfwork > mat->lfwork) {
508: mat->lfwork = nlfwork;
509: PetscCall(PetscFree(mat->fwork));
510: PetscCall(PetscMalloc1(mat->lfwork, &mat->fwork));
511: }
512: }
513: PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF));
514: PetscCallBLAS("LAPACKormqr", LAPACKormqr_("L", "N", &m, &nrhs, &mat->rank, mat->v, &mat->lda, mat->tau, x, &ldx, mat->fwork, &mat->lfwork, &info));
515: PetscCall(PetscFPTrapPop());
516: PetscCheck(!info, PETSC_COMM_SELF, PETSC_ERR_LIB, "ORMQR - Bad orthogonal transform %d", (int)info);
517: if (PetscDefined(USE_COMPLEX)) PetscCall(MatConjugate_SeqDense(A));
518: } else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "QR factored matrix cannot be used for transpose solve");
519: PetscCall(PetscLogFlops(nrhs * (4.0 * m * mat->rank - PetscSqr(mat->rank))));
520: PetscFunctionReturn(PETSC_SUCCESS);
521: }
523: static PetscErrorCode MatSolve_SeqDense_SetUp(Mat A, Vec xx, Vec yy, PetscScalar **_y, PetscBLASInt *_m, PetscBLASInt *_k)
524: {
525: Mat_SeqDense *mat = (Mat_SeqDense *)A->data;
526: PetscScalar *y;
527: PetscBLASInt m = 0, k = 0;
529: PetscFunctionBegin;
530: PetscCall(PetscBLASIntCast(A->rmap->n, &m));
531: PetscCall(PetscBLASIntCast(A->cmap->n, &k));
532: if (k < m) {
533: PetscCall(VecCopy(xx, mat->qrrhs));
534: PetscCall(VecGetArray(mat->qrrhs, &y));
535: } else {
536: PetscCall(VecCopy(xx, yy));
537: PetscCall(VecGetArray(yy, &y));
538: }
539: *_y = y;
540: *_k = k;
541: *_m = m;
542: PetscFunctionReturn(PETSC_SUCCESS);
543: }
545: static PetscErrorCode MatSolve_SeqDense_TearDown(Mat A, Vec xx, Vec yy, PetscScalar **_y, PetscBLASInt *_m, PetscBLASInt *_k)
546: {
547: Mat_SeqDense *mat = (Mat_SeqDense *)A->data;
548: PetscScalar *y = NULL;
549: PetscBLASInt m, k;
551: PetscFunctionBegin;
552: y = *_y;
553: *_y = NULL;
554: k = *_k;
555: m = *_m;
556: if (k < m) {
557: PetscScalar *yv;
558: PetscCall(VecGetArray(yy, &yv));
559: PetscCall(PetscArraycpy(yv, y, k));
560: PetscCall(VecRestoreArray(yy, &yv));
561: PetscCall(VecRestoreArray(mat->qrrhs, &y));
562: } else {
563: PetscCall(VecRestoreArray(yy, &y));
564: }
565: PetscFunctionReturn(PETSC_SUCCESS);
566: }
568: static PetscErrorCode MatSolve_SeqDense_LU(Mat A, Vec xx, Vec yy)
569: {
570: PetscScalar *y = NULL;
571: PetscBLASInt m = 0, k = 0;
573: PetscFunctionBegin;
574: PetscCall(MatSolve_SeqDense_SetUp(A, xx, yy, &y, &m, &k));
575: PetscCall(MatSolve_SeqDense_Internal_LU(A, y, m, m, 1, k, PETSC_FALSE));
576: PetscCall(MatSolve_SeqDense_TearDown(A, xx, yy, &y, &m, &k));
577: PetscFunctionReturn(PETSC_SUCCESS);
578: }
580: static PetscErrorCode MatSolveTranspose_SeqDense_LU(Mat A, Vec xx, Vec yy)
581: {
582: PetscScalar *y = NULL;
583: PetscBLASInt m = 0, k = 0;
585: PetscFunctionBegin;
586: PetscCall(MatSolve_SeqDense_SetUp(A, xx, yy, &y, &m, &k));
587: PetscCall(MatSolve_SeqDense_Internal_LU(A, y, m, m, 1, k, PETSC_TRUE));
588: PetscCall(MatSolve_SeqDense_TearDown(A, xx, yy, &y, &m, &k));
589: PetscFunctionReturn(PETSC_SUCCESS);
590: }
592: static PetscErrorCode MatSolve_SeqDense_Cholesky(Mat A, Vec xx, Vec yy)
593: {
594: PetscScalar *y = NULL;
595: PetscBLASInt m = 0, k = 0;
597: PetscFunctionBegin;
598: PetscCall(MatSolve_SeqDense_SetUp(A, xx, yy, &y, &m, &k));
599: PetscCall(MatSolve_SeqDense_Internal_Cholesky(A, y, m, m, 1, k, PETSC_FALSE));
600: PetscCall(MatSolve_SeqDense_TearDown(A, xx, yy, &y, &m, &k));
601: PetscFunctionReturn(PETSC_SUCCESS);
602: }
604: static PetscErrorCode MatSolveTranspose_SeqDense_Cholesky(Mat A, Vec xx, Vec yy)
605: {
606: PetscScalar *y = NULL;
607: PetscBLASInt m = 0, k = 0;
609: PetscFunctionBegin;
610: PetscCall(MatSolve_SeqDense_SetUp(A, xx, yy, &y, &m, &k));
611: PetscCall(MatSolve_SeqDense_Internal_Cholesky(A, y, m, m, 1, k, PETSC_TRUE));
612: PetscCall(MatSolve_SeqDense_TearDown(A, xx, yy, &y, &m, &k));
613: PetscFunctionReturn(PETSC_SUCCESS);
614: }
616: static PetscErrorCode MatSolve_SeqDense_QR(Mat A, Vec xx, Vec yy)
617: {
618: PetscScalar *y = NULL;
619: PetscBLASInt m = 0, k = 0;
621: PetscFunctionBegin;
622: PetscCall(MatSolve_SeqDense_SetUp(A, xx, yy, &y, &m, &k));
623: PetscCall(MatSolve_SeqDense_Internal_QR(A, y, PetscMax(m, k), m, 1, k));
624: PetscCall(MatSolve_SeqDense_TearDown(A, xx, yy, &y, &m, &k));
625: PetscFunctionReturn(PETSC_SUCCESS);
626: }
628: static PetscErrorCode MatSolveTranspose_SeqDense_QR(Mat A, Vec xx, Vec yy)
629: {
630: PetscScalar *y = NULL;
631: PetscBLASInt m = 0, k = 0;
633: PetscFunctionBegin;
634: PetscCall(MatSolve_SeqDense_SetUp(A, xx, yy, &y, &m, &k));
635: PetscCall(MatSolveTranspose_SeqDense_Internal_QR(A, y, PetscMax(m, k), m, 1, k));
636: PetscCall(MatSolve_SeqDense_TearDown(A, xx, yy, &y, &m, &k));
637: PetscFunctionReturn(PETSC_SUCCESS);
638: }
640: static PetscErrorCode MatMatSolve_SeqDense_SetUp(Mat A, Mat B, Mat X, PetscScalar **_y, PetscBLASInt *_ldy, PetscBLASInt *_m, PetscBLASInt *_nrhs, PetscBLASInt *_k)
641: {
642: const PetscScalar *b;
643: PetscScalar *y;
644: PetscInt n, _ldb, _ldx;
645: PetscBLASInt nrhs = 0, m = 0, k = 0, ldb = 0, ldx = 0, ldy = 0;
647: PetscFunctionBegin;
648: *_ldy = 0;
649: *_m = 0;
650: *_nrhs = 0;
651: *_k = 0;
652: *_y = NULL;
653: PetscCall(PetscBLASIntCast(A->rmap->n, &m));
654: PetscCall(PetscBLASIntCast(A->cmap->n, &k));
655: PetscCall(MatGetSize(B, NULL, &n));
656: PetscCall(PetscBLASIntCast(n, &nrhs));
657: PetscCall(MatDenseGetLDA(B, &_ldb));
658: PetscCall(PetscBLASIntCast(_ldb, &ldb));
659: PetscCall(MatDenseGetLDA(X, &_ldx));
660: PetscCall(PetscBLASIntCast(_ldx, &ldx));
661: if (ldx < m) {
662: PetscCall(MatDenseGetArrayRead(B, &b));
663: PetscCall(PetscMalloc1(nrhs * m, &y));
664: if (ldb == m) {
665: PetscCall(PetscArraycpy(y, b, ldb * nrhs));
666: } else {
667: for (PetscInt j = 0; j < nrhs; j++) PetscCall(PetscArraycpy(&y[j * m], &b[j * ldb], m));
668: }
669: ldy = m;
670: PetscCall(MatDenseRestoreArrayRead(B, &b));
671: } else {
672: if (ldb == ldx) {
673: PetscCall(MatCopy(B, X, SAME_NONZERO_PATTERN));
674: PetscCall(MatDenseGetArray(X, &y));
675: } else {
676: PetscCall(MatDenseGetArray(X, &y));
677: PetscCall(MatDenseGetArrayRead(B, &b));
678: for (PetscInt j = 0; j < nrhs; j++) PetscCall(PetscArraycpy(&y[j * ldx], &b[j * ldb], m));
679: PetscCall(MatDenseRestoreArrayRead(B, &b));
680: }
681: ldy = ldx;
682: }
683: *_y = y;
684: *_ldy = ldy;
685: *_k = k;
686: *_m = m;
687: *_nrhs = nrhs;
688: PetscFunctionReturn(PETSC_SUCCESS);
689: }
691: static PetscErrorCode MatMatSolve_SeqDense_TearDown(Mat A, Mat B, Mat X, PetscScalar **_y, PetscBLASInt *_ldy, PetscBLASInt *_m, PetscBLASInt *_nrhs, PetscBLASInt *_k)
692: {
693: PetscScalar *y;
694: PetscInt _ldx;
695: PetscBLASInt k, ldy, nrhs, ldx = 0;
697: PetscFunctionBegin;
698: y = *_y;
699: *_y = NULL;
700: k = *_k;
701: ldy = *_ldy;
702: nrhs = *_nrhs;
703: PetscCall(MatDenseGetLDA(X, &_ldx));
704: PetscCall(PetscBLASIntCast(_ldx, &ldx));
705: if (ldx != ldy) {
706: PetscScalar *xv;
707: PetscCall(MatDenseGetArray(X, &xv));
708: for (PetscInt j = 0; j < nrhs; j++) PetscCall(PetscArraycpy(&xv[j * ldx], &y[j * ldy], k));
709: PetscCall(MatDenseRestoreArray(X, &xv));
710: PetscCall(PetscFree(y));
711: } else {
712: PetscCall(MatDenseRestoreArray(X, &y));
713: }
714: PetscFunctionReturn(PETSC_SUCCESS);
715: }
717: static PetscErrorCode MatMatSolve_SeqDense_LU(Mat A, Mat B, Mat X)
718: {
719: PetscScalar *y;
720: PetscBLASInt m, k, ldy, nrhs;
722: PetscFunctionBegin;
723: PetscCall(MatMatSolve_SeqDense_SetUp(A, B, X, &y, &ldy, &m, &nrhs, &k));
724: PetscCall(MatSolve_SeqDense_Internal_LU(A, y, ldy, m, nrhs, k, PETSC_FALSE));
725: PetscCall(MatMatSolve_SeqDense_TearDown(A, B, X, &y, &ldy, &m, &nrhs, &k));
726: PetscFunctionReturn(PETSC_SUCCESS);
727: }
729: static PetscErrorCode MatMatSolveTranspose_SeqDense_LU(Mat A, Mat B, Mat X)
730: {
731: PetscScalar *y;
732: PetscBLASInt m, k, ldy, nrhs;
734: PetscFunctionBegin;
735: PetscCall(MatMatSolve_SeqDense_SetUp(A, B, X, &y, &ldy, &m, &nrhs, &k));
736: PetscCall(MatSolve_SeqDense_Internal_LU(A, y, ldy, m, nrhs, k, PETSC_TRUE));
737: PetscCall(MatMatSolve_SeqDense_TearDown(A, B, X, &y, &ldy, &m, &nrhs, &k));
738: PetscFunctionReturn(PETSC_SUCCESS);
739: }
741: static PetscErrorCode MatMatSolve_SeqDense_Cholesky(Mat A, Mat B, Mat X)
742: {
743: PetscScalar *y;
744: PetscBLASInt m, k, ldy, nrhs;
746: PetscFunctionBegin;
747: PetscCall(MatMatSolve_SeqDense_SetUp(A, B, X, &y, &ldy, &m, &nrhs, &k));
748: PetscCall(MatSolve_SeqDense_Internal_Cholesky(A, y, ldy, m, nrhs, k, PETSC_FALSE));
749: PetscCall(MatMatSolve_SeqDense_TearDown(A, B, X, &y, &ldy, &m, &nrhs, &k));
750: PetscFunctionReturn(PETSC_SUCCESS);
751: }
753: static PetscErrorCode MatMatSolveTranspose_SeqDense_Cholesky(Mat A, Mat B, Mat X)
754: {
755: PetscScalar *y;
756: PetscBLASInt m, k, ldy, nrhs;
758: PetscFunctionBegin;
759: PetscCall(MatMatSolve_SeqDense_SetUp(A, B, X, &y, &ldy, &m, &nrhs, &k));
760: PetscCall(MatSolve_SeqDense_Internal_Cholesky(A, y, ldy, m, nrhs, k, PETSC_TRUE));
761: PetscCall(MatMatSolve_SeqDense_TearDown(A, B, X, &y, &ldy, &m, &nrhs, &k));
762: PetscFunctionReturn(PETSC_SUCCESS);
763: }
765: static PetscErrorCode MatMatSolve_SeqDense_QR(Mat A, Mat B, Mat X)
766: {
767: PetscScalar *y;
768: PetscBLASInt m, k, ldy, nrhs;
770: PetscFunctionBegin;
771: PetscCall(MatMatSolve_SeqDense_SetUp(A, B, X, &y, &ldy, &m, &nrhs, &k));
772: PetscCall(MatSolve_SeqDense_Internal_QR(A, y, ldy, m, nrhs, k));
773: PetscCall(MatMatSolve_SeqDense_TearDown(A, B, X, &y, &ldy, &m, &nrhs, &k));
774: PetscFunctionReturn(PETSC_SUCCESS);
775: }
777: static PetscErrorCode MatMatSolveTranspose_SeqDense_QR(Mat A, Mat B, Mat X)
778: {
779: PetscScalar *y;
780: PetscBLASInt m, k, ldy, nrhs;
782: PetscFunctionBegin;
783: PetscCall(MatMatSolve_SeqDense_SetUp(A, B, X, &y, &ldy, &m, &nrhs, &k));
784: PetscCall(MatSolveTranspose_SeqDense_Internal_QR(A, y, ldy, m, nrhs, k));
785: PetscCall(MatMatSolve_SeqDense_TearDown(A, B, X, &y, &ldy, &m, &nrhs, &k));
786: PetscFunctionReturn(PETSC_SUCCESS);
787: }
789: /* COMMENT: I have chosen to hide row permutation in the pivots,
790: rather than put it in the Mat->row slot.*/
791: PetscErrorCode MatLUFactor_SeqDense(Mat A, IS row, IS col, const MatFactorInfo *minfo)
792: {
793: Mat_SeqDense *mat = (Mat_SeqDense *)A->data;
794: PetscBLASInt n, m, info;
796: PetscFunctionBegin;
797: PetscCall(PetscBLASIntCast(A->cmap->n, &n));
798: PetscCall(PetscBLASIntCast(A->rmap->n, &m));
799: if (!mat->pivots) { PetscCall(PetscMalloc1(A->rmap->n, &mat->pivots)); }
800: if (!A->rmap->n || !A->cmap->n) PetscFunctionReturn(PETSC_SUCCESS);
801: PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF));
802: PetscCallBLAS("LAPACKgetrf", LAPACKgetrf_(&m, &n, mat->v, &mat->lda, mat->pivots, &info));
803: PetscCall(PetscFPTrapPop());
805: PetscCheck(info >= 0, PETSC_COMM_SELF, PETSC_ERR_LIB, "Bad argument to LU factorization %d", (int)info);
806: PetscCheck(info <= 0, PETSC_COMM_SELF, PETSC_ERR_MAT_LU_ZRPVT, "Bad LU factorization %d", (int)info);
808: A->ops->solve = MatSolve_SeqDense_LU;
809: A->ops->matsolve = MatMatSolve_SeqDense_LU;
810: A->ops->solvetranspose = MatSolveTranspose_SeqDense_LU;
811: A->ops->matsolvetranspose = MatMatSolveTranspose_SeqDense_LU;
812: A->factortype = MAT_FACTOR_LU;
814: PetscCall(PetscFree(A->solvertype));
815: PetscCall(PetscStrallocpy(MATSOLVERPETSC, &A->solvertype));
817: PetscCall(PetscLogFlops((2.0 * A->cmap->n * A->cmap->n * A->cmap->n) / 3));
818: PetscFunctionReturn(PETSC_SUCCESS);
819: }
821: static PetscErrorCode MatLUFactorNumeric_SeqDense(Mat fact, Mat A, const MatFactorInfo *info_dummy)
822: {
823: MatFactorInfo info;
825: PetscFunctionBegin;
826: PetscCall(MatDuplicateNoCreate_SeqDense(fact, A, MAT_COPY_VALUES));
827: PetscUseTypeMethod(fact, lufactor, NULL, NULL, &info);
828: PetscFunctionReturn(PETSC_SUCCESS);
829: }
831: PetscErrorCode MatLUFactorSymbolic_SeqDense(Mat fact, Mat A, IS row, IS col, const MatFactorInfo *info)
832: {
833: PetscFunctionBegin;
834: fact->preallocated = PETSC_TRUE;
835: fact->assembled = PETSC_TRUE;
836: fact->ops->lufactornumeric = MatLUFactorNumeric_SeqDense;
837: PetscFunctionReturn(PETSC_SUCCESS);
838: }
840: /* Cholesky as L*L^T or L*D*L^T and the symmetric/hermitian complex variants */
841: PetscErrorCode MatCholeskyFactor_SeqDense(Mat A, IS perm, const MatFactorInfo *factinfo)
842: {
843: Mat_SeqDense *mat = (Mat_SeqDense *)A->data;
844: PetscBLASInt info, n;
846: PetscFunctionBegin;
847: PetscCall(PetscBLASIntCast(A->cmap->n, &n));
848: if (!A->rmap->n || !A->cmap->n) PetscFunctionReturn(PETSC_SUCCESS);
849: if (A->spd == PETSC_BOOL3_TRUE) {
850: PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF));
851: PetscCallBLAS("LAPACKpotrf", LAPACKpotrf_("L", &n, mat->v, &mat->lda, &info));
852: PetscCall(PetscFPTrapPop());
853: #if defined(PETSC_USE_COMPLEX)
854: } else if (A->hermitian == PETSC_BOOL3_TRUE) {
855: if (!mat->pivots) { PetscCall(PetscMalloc1(A->rmap->n, &mat->pivots)); }
856: if (!mat->fwork) {
857: PetscScalar dummy;
859: mat->lfwork = -1;
860: PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF));
861: PetscCallBLAS("LAPACKhetrf", LAPACKhetrf_("L", &n, mat->v, &mat->lda, mat->pivots, &dummy, &mat->lfwork, &info));
862: PetscCall(PetscFPTrapPop());
863: mat->lfwork = (PetscInt)PetscRealPart(dummy);
864: PetscCall(PetscMalloc1(mat->lfwork, &mat->fwork));
865: }
866: PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF));
867: PetscCallBLAS("LAPACKhetrf", LAPACKhetrf_("L", &n, mat->v, &mat->lda, mat->pivots, mat->fwork, &mat->lfwork, &info));
868: PetscCall(PetscFPTrapPop());
869: #endif
870: } else { /* symmetric case */
871: if (!mat->pivots) { PetscCall(PetscMalloc1(A->rmap->n, &mat->pivots)); }
872: if (!mat->fwork) {
873: PetscScalar dummy;
875: mat->lfwork = -1;
876: PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF));
877: PetscCallBLAS("LAPACKsytrf", LAPACKsytrf_("L", &n, mat->v, &mat->lda, mat->pivots, &dummy, &mat->lfwork, &info));
878: PetscCall(PetscFPTrapPop());
879: mat->lfwork = (PetscInt)PetscRealPart(dummy);
880: PetscCall(PetscMalloc1(mat->lfwork, &mat->fwork));
881: }
882: PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF));
883: PetscCallBLAS("LAPACKsytrf", LAPACKsytrf_("L", &n, mat->v, &mat->lda, mat->pivots, mat->fwork, &mat->lfwork, &info));
884: PetscCall(PetscFPTrapPop());
885: }
886: PetscCheck(!info, PETSC_COMM_SELF, PETSC_ERR_MAT_CH_ZRPVT, "Bad factorization: zero pivot in row %" PetscInt_FMT, (PetscInt)info - 1);
888: A->ops->solve = MatSolve_SeqDense_Cholesky;
889: A->ops->matsolve = MatMatSolve_SeqDense_Cholesky;
890: A->ops->solvetranspose = MatSolveTranspose_SeqDense_Cholesky;
891: A->ops->matsolvetranspose = MatMatSolveTranspose_SeqDense_Cholesky;
892: A->factortype = MAT_FACTOR_CHOLESKY;
894: PetscCall(PetscFree(A->solvertype));
895: PetscCall(PetscStrallocpy(MATSOLVERPETSC, &A->solvertype));
897: PetscCall(PetscLogFlops((1.0 * A->cmap->n * A->cmap->n * A->cmap->n) / 3.0));
898: PetscFunctionReturn(PETSC_SUCCESS);
899: }
901: static PetscErrorCode MatCholeskyFactorNumeric_SeqDense(Mat fact, Mat A, const MatFactorInfo *info_dummy)
902: {
903: MatFactorInfo info;
905: PetscFunctionBegin;
906: info.fill = 1.0;
908: PetscCall(MatDuplicateNoCreate_SeqDense(fact, A, MAT_COPY_VALUES));
909: PetscUseTypeMethod(fact, choleskyfactor, NULL, &info);
910: PetscFunctionReturn(PETSC_SUCCESS);
911: }
913: PetscErrorCode MatCholeskyFactorSymbolic_SeqDense(Mat fact, Mat A, IS row, const MatFactorInfo *info)
914: {
915: PetscFunctionBegin;
916: fact->assembled = PETSC_TRUE;
917: fact->preallocated = PETSC_TRUE;
918: fact->ops->choleskyfactornumeric = MatCholeskyFactorNumeric_SeqDense;
919: PetscFunctionReturn(PETSC_SUCCESS);
920: }
922: PetscErrorCode MatQRFactor_SeqDense(Mat A, IS col, const MatFactorInfo *minfo)
923: {
924: Mat_SeqDense *mat = (Mat_SeqDense *)A->data;
925: PetscBLASInt n, m, info, min, max;
927: PetscFunctionBegin;
928: PetscCall(PetscBLASIntCast(A->cmap->n, &n));
929: PetscCall(PetscBLASIntCast(A->rmap->n, &m));
930: max = PetscMax(m, n);
931: min = PetscMin(m, n);
932: if (!mat->tau) { PetscCall(PetscMalloc1(min, &mat->tau)); }
933: if (!mat->pivots) { PetscCall(PetscMalloc1(n, &mat->pivots)); }
934: if (!mat->qrrhs) PetscCall(MatCreateVecs(A, NULL, &mat->qrrhs));
935: if (!A->rmap->n || !A->cmap->n) PetscFunctionReturn(PETSC_SUCCESS);
936: if (!mat->fwork) {
937: PetscScalar dummy;
939: mat->lfwork = -1;
940: PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF));
941: PetscCallBLAS("LAPACKgeqrf", LAPACKgeqrf_(&m, &n, mat->v, &mat->lda, mat->tau, &dummy, &mat->lfwork, &info));
942: PetscCall(PetscFPTrapPop());
943: mat->lfwork = (PetscInt)PetscRealPart(dummy);
944: PetscCall(PetscMalloc1(mat->lfwork, &mat->fwork));
945: }
946: PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF));
947: PetscCallBLAS("LAPACKgeqrf", LAPACKgeqrf_(&m, &n, mat->v, &mat->lda, mat->tau, mat->fwork, &mat->lfwork, &info));
948: PetscCall(PetscFPTrapPop());
949: PetscCheck(!info, PETSC_COMM_SELF, PETSC_ERR_LIB, "Bad argument to QR factorization %d", (int)info);
950: // 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
951: mat->rank = min;
953: A->ops->solve = MatSolve_SeqDense_QR;
954: A->ops->matsolve = MatMatSolve_SeqDense_QR;
955: A->factortype = MAT_FACTOR_QR;
956: if (m == n) {
957: A->ops->solvetranspose = MatSolveTranspose_SeqDense_QR;
958: A->ops->matsolvetranspose = MatMatSolveTranspose_SeqDense_QR;
959: }
961: PetscCall(PetscFree(A->solvertype));
962: PetscCall(PetscStrallocpy(MATSOLVERPETSC, &A->solvertype));
964: PetscCall(PetscLogFlops(2.0 * min * min * (max - min / 3.0)));
965: PetscFunctionReturn(PETSC_SUCCESS);
966: }
968: static PetscErrorCode MatQRFactorNumeric_SeqDense(Mat fact, Mat A, const MatFactorInfo *info_dummy)
969: {
970: MatFactorInfo info;
972: PetscFunctionBegin;
973: info.fill = 1.0;
975: PetscCall(MatDuplicateNoCreate_SeqDense(fact, A, MAT_COPY_VALUES));
976: PetscUseMethod(fact, "MatQRFactor_C", (Mat, IS, const MatFactorInfo *), (fact, NULL, &info));
977: PetscFunctionReturn(PETSC_SUCCESS);
978: }
980: PetscErrorCode MatQRFactorSymbolic_SeqDense(Mat fact, Mat A, IS row, const MatFactorInfo *info)
981: {
982: PetscFunctionBegin;
983: fact->assembled = PETSC_TRUE;
984: fact->preallocated = PETSC_TRUE;
985: PetscCall(PetscObjectComposeFunction((PetscObject)fact, "MatQRFactorNumeric_C", MatQRFactorNumeric_SeqDense));
986: PetscFunctionReturn(PETSC_SUCCESS);
987: }
989: /* uses LAPACK */
990: PETSC_INTERN PetscErrorCode MatGetFactor_seqdense_petsc(Mat A, MatFactorType ftype, Mat *fact)
991: {
992: PetscFunctionBegin;
993: PetscCall(MatCreate(PetscObjectComm((PetscObject)A), fact));
994: PetscCall(MatSetSizes(*fact, A->rmap->n, A->cmap->n, A->rmap->n, A->cmap->n));
995: PetscCall(MatSetType(*fact, MATDENSE));
996: (*fact)->trivialsymbolic = PETSC_TRUE;
997: if (ftype == MAT_FACTOR_LU || ftype == MAT_FACTOR_ILU) {
998: (*fact)->ops->lufactorsymbolic = MatLUFactorSymbolic_SeqDense;
999: (*fact)->ops->ilufactorsymbolic = MatLUFactorSymbolic_SeqDense;
1000: } else if (ftype == MAT_FACTOR_CHOLESKY || ftype == MAT_FACTOR_ICC) {
1001: (*fact)->ops->choleskyfactorsymbolic = MatCholeskyFactorSymbolic_SeqDense;
1002: } else if (ftype == MAT_FACTOR_QR) {
1003: PetscCall(PetscObjectComposeFunction((PetscObject)*fact, "MatQRFactorSymbolic_C", MatQRFactorSymbolic_SeqDense));
1004: }
1005: (*fact)->factortype = ftype;
1007: PetscCall(PetscFree((*fact)->solvertype));
1008: PetscCall(PetscStrallocpy(MATSOLVERPETSC, &(*fact)->solvertype));
1009: PetscCall(PetscStrallocpy(MATORDERINGEXTERNAL, (char **)&(*fact)->preferredordering[MAT_FACTOR_LU]));
1010: PetscCall(PetscStrallocpy(MATORDERINGEXTERNAL, (char **)&(*fact)->preferredordering[MAT_FACTOR_ILU]));
1011: PetscCall(PetscStrallocpy(MATORDERINGEXTERNAL, (char **)&(*fact)->preferredordering[MAT_FACTOR_CHOLESKY]));
1012: PetscCall(PetscStrallocpy(MATORDERINGEXTERNAL, (char **)&(*fact)->preferredordering[MAT_FACTOR_ICC]));
1013: PetscFunctionReturn(PETSC_SUCCESS);
1014: }
1016: static PetscErrorCode MatSOR_SeqDense(Mat A, Vec bb, PetscReal omega, MatSORType flag, PetscReal shift, PetscInt its, PetscInt lits, Vec xx)
1017: {
1018: Mat_SeqDense *mat = (Mat_SeqDense *)A->data;
1019: PetscScalar *x, *v = mat->v, zero = 0.0, xt;
1020: const PetscScalar *b;
1021: PetscInt m = A->rmap->n, i;
1022: PetscBLASInt o = 1, bm = 0;
1024: PetscFunctionBegin;
1025: #if defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
1026: PetscCheck(A->offloadmask != PETSC_OFFLOAD_GPU, PETSC_COMM_SELF, PETSC_ERR_SUP, "Not implemented");
1027: #endif
1028: if (shift == -1) shift = 0.0; /* negative shift indicates do not error on zero diagonal; this code never zeros on zero diagonal */
1029: PetscCall(PetscBLASIntCast(m, &bm));
1030: if (flag & SOR_ZERO_INITIAL_GUESS) {
1031: /* this is a hack fix, should have another version without the second BLASdotu */
1032: PetscCall(VecSet(xx, zero));
1033: }
1034: PetscCall(VecGetArray(xx, &x));
1035: PetscCall(VecGetArrayRead(bb, &b));
1036: its = its * lits;
1037: 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);
1038: while (its--) {
1039: if (flag & SOR_FORWARD_SWEEP || flag & SOR_LOCAL_FORWARD_SWEEP) {
1040: for (i = 0; i < m; i++) {
1041: PetscCallBLAS("BLASdotu", xt = b[i] - BLASdotu_(&bm, v + i, &bm, x, &o));
1042: x[i] = (1. - omega) * x[i] + omega * (xt + v[i + i * m] * x[i]) / (v[i + i * m] + shift);
1043: }
1044: }
1045: if (flag & SOR_BACKWARD_SWEEP || flag & SOR_LOCAL_BACKWARD_SWEEP) {
1046: for (i = m - 1; i >= 0; i--) {
1047: PetscCallBLAS("BLASdotu", xt = b[i] - BLASdotu_(&bm, v + i, &bm, x, &o));
1048: x[i] = (1. - omega) * x[i] + omega * (xt + v[i + i * m] * x[i]) / (v[i + i * m] + shift);
1049: }
1050: }
1051: }
1052: PetscCall(VecRestoreArrayRead(bb, &b));
1053: PetscCall(VecRestoreArray(xx, &x));
1054: PetscFunctionReturn(PETSC_SUCCESS);
1055: }
1057: static PetscErrorCode MatMultColumnRangeKernel_SeqDense(Mat A, Vec xx, Vec yy, PetscInt c_start, PetscInt c_end, PetscBool trans, PetscBool herm)
1058: {
1059: Mat_SeqDense *mat = (Mat_SeqDense *)A->data;
1060: PetscScalar *y, _DOne = 1.0, _DZero = 0.0;
1061: PetscBLASInt m, n, _One = 1;
1062: const PetscScalar *v = mat->v, *x;
1064: PetscFunctionBegin;
1065: PetscCall(PetscBLASIntCast(A->rmap->n, &m));
1066: PetscCall(PetscBLASIntCast(c_end - c_start, &n));
1067: PetscCall(VecGetArrayRead(xx, &x));
1068: PetscCall(VecGetArrayWrite(yy, &y));
1069: if (!m || !n) {
1070: PetscBLASInt i;
1071: if (trans)
1072: for (i = 0; i < n; i++) y[i] = 0.0;
1073: else
1074: for (i = 0; i < m; i++) y[i] = 0.0;
1075: } else {
1076: if (trans) {
1077: if (herm) PetscCallBLAS("BLASgemv", BLASgemv_("C", &m, &n, &_DOne, v + c_start * mat->lda, &mat->lda, x, &_One, &_DZero, y + c_start, &_One));
1078: else PetscCallBLAS("BLASgemv", BLASgemv_("T", &m, &n, &_DOne, v + c_start * mat->lda, &mat->lda, x, &_One, &_DZero, y + c_start, &_One));
1079: } else {
1080: PetscCallBLAS("BLASgemv", BLASgemv_("N", &m, &n, &_DOne, v + c_start * mat->lda, &mat->lda, x + c_start, &_One, &_DZero, y, &_One));
1081: }
1082: PetscCall(PetscLogFlops(2.0 * m * n - n));
1083: }
1084: PetscCall(VecRestoreArrayRead(xx, &x));
1085: PetscCall(VecRestoreArrayWrite(yy, &y));
1086: PetscFunctionReturn(PETSC_SUCCESS);
1087: }
1089: PetscErrorCode MatMultHermitianTransposeColumnRange_SeqDense(Mat A, Vec xx, Vec yy, PetscInt c_start, PetscInt c_end)
1090: {
1091: PetscFunctionBegin;
1092: PetscCall(MatMultColumnRangeKernel_SeqDense(A, xx, yy, c_start, c_end, PETSC_TRUE, PETSC_TRUE));
1093: PetscFunctionReturn(PETSC_SUCCESS);
1094: }
1096: PetscErrorCode MatMult_SeqDense(Mat A, Vec xx, Vec yy)
1097: {
1098: PetscFunctionBegin;
1099: PetscCall(MatMultColumnRangeKernel_SeqDense(A, xx, yy, 0, A->cmap->n, PETSC_FALSE, PETSC_FALSE));
1100: PetscFunctionReturn(PETSC_SUCCESS);
1101: }
1103: PetscErrorCode MatMultTranspose_SeqDense(Mat A, Vec xx, Vec yy)
1104: {
1105: PetscFunctionBegin;
1106: PetscCall(MatMultColumnRangeKernel_SeqDense(A, xx, yy, 0, A->cmap->n, PETSC_TRUE, PETSC_FALSE));
1107: PetscFunctionReturn(PETSC_SUCCESS);
1108: }
1110: PetscErrorCode MatMultHermitianTranspose_SeqDense(Mat A, Vec xx, Vec yy)
1111: {
1112: PetscFunctionBegin;
1113: PetscCall(MatMultColumnRangeKernel_SeqDense(A, xx, yy, 0, A->cmap->n, PETSC_TRUE, PETSC_TRUE));
1114: PetscFunctionReturn(PETSC_SUCCESS);
1115: }
1117: static PetscErrorCode MatMultAddColumnRangeKernel_SeqDense(Mat A, Vec xx, Vec zz, Vec yy, PetscInt c_start, PetscInt c_end, PetscBool trans, PetscBool herm)
1118: {
1119: Mat_SeqDense *mat = (Mat_SeqDense *)A->data;
1120: const PetscScalar *v = mat->v, *x;
1121: PetscScalar *y, _DOne = 1.0;
1122: PetscBLASInt m, n, _One = 1;
1124: PetscFunctionBegin;
1125: PetscCall(PetscBLASIntCast(A->rmap->n, &m));
1126: PetscCall(PetscBLASIntCast(c_end - c_start, &n));
1127: PetscCall(VecCopy(zz, yy));
1128: if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS);
1129: PetscCall(VecGetArray(yy, &y));
1130: PetscCall(VecGetArrayRead(xx, &x));
1131: if (trans) {
1132: if (herm) PetscCallBLAS("BLASgemv", BLASgemv_("C", &m, &n, &_DOne, v + c_start * mat->lda, &mat->lda, x, &_One, &_DOne, y + c_start, &_One));
1133: else PetscCallBLAS("BLASgemv", BLASgemv_("T", &m, &n, &_DOne, v + c_start * mat->lda, &mat->lda, x, &_One, &_DOne, y + c_start, &_One));
1134: } else {
1135: PetscCallBLAS("BLASgemv", BLASgemv_("N", &m, &n, &_DOne, v + c_start * mat->lda, &mat->lda, x + c_start, &_One, &_DOne, y, &_One));
1136: }
1137: PetscCall(VecRestoreArrayRead(xx, &x));
1138: PetscCall(VecRestoreArray(yy, &y));
1139: PetscCall(PetscLogFlops(2.0 * m * n));
1140: PetscFunctionReturn(PETSC_SUCCESS);
1141: }
1143: PetscErrorCode MatMultAddColumnRange_SeqDense(Mat A, Vec xx, Vec zz, Vec yy, PetscInt c_start, PetscInt c_end)
1144: {
1145: PetscFunctionBegin;
1146: PetscCall(MatMultAddColumnRangeKernel_SeqDense(A, xx, zz, yy, c_start, c_end, PETSC_FALSE, PETSC_FALSE));
1147: PetscFunctionReturn(PETSC_SUCCESS);
1148: }
1150: PetscErrorCode MatMultHermitianTransposeAddColumnRange_SeqDense(Mat A, Vec xx, Vec zz, Vec yy, PetscInt c_start, PetscInt c_end)
1151: {
1152: PetscFunctionBegin;
1153: PetscMPIInt rank;
1154: PetscCallMPI(MPI_Comm_rank(MPI_COMM_WORLD, &rank));
1155: PetscCall(MatMultAddColumnRangeKernel_SeqDense(A, xx, zz, yy, c_start, c_end, PETSC_TRUE, PETSC_TRUE));
1156: PetscFunctionReturn(PETSC_SUCCESS);
1157: }
1159: PetscErrorCode MatMultAdd_SeqDense(Mat A, Vec xx, Vec zz, Vec yy)
1160: {
1161: PetscFunctionBegin;
1162: PetscCall(MatMultAddColumnRangeKernel_SeqDense(A, xx, zz, yy, 0, A->cmap->n, PETSC_FALSE, PETSC_FALSE));
1163: PetscFunctionReturn(PETSC_SUCCESS);
1164: }
1166: PetscErrorCode MatMultTransposeAdd_SeqDense(Mat A, Vec xx, Vec zz, Vec yy)
1167: {
1168: PetscFunctionBegin;
1169: PetscCall(MatMultAddColumnRangeKernel_SeqDense(A, xx, zz, yy, 0, A->cmap->n, PETSC_TRUE, PETSC_FALSE));
1170: PetscFunctionReturn(PETSC_SUCCESS);
1171: }
1173: PetscErrorCode MatMultHermitianTransposeAdd_SeqDense(Mat A, Vec xx, Vec zz, Vec yy)
1174: {
1175: PetscFunctionBegin;
1176: PetscCall(MatMultAddColumnRangeKernel_SeqDense(A, xx, zz, yy, 0, A->cmap->n, PETSC_TRUE, PETSC_TRUE));
1177: PetscFunctionReturn(PETSC_SUCCESS);
1178: }
1180: static PetscErrorCode MatGetRow_SeqDense(Mat A, PetscInt row, PetscInt *ncols, PetscInt **cols, PetscScalar **vals)
1181: {
1182: Mat_SeqDense *mat = (Mat_SeqDense *)A->data;
1183: PetscInt i;
1185: PetscFunctionBegin;
1186: if (ncols) *ncols = A->cmap->n;
1187: if (cols) {
1188: PetscCall(PetscMalloc1(A->cmap->n, cols));
1189: for (i = 0; i < A->cmap->n; i++) (*cols)[i] = i;
1190: }
1191: if (vals) {
1192: const PetscScalar *v;
1194: PetscCall(MatDenseGetArrayRead(A, &v));
1195: PetscCall(PetscMalloc1(A->cmap->n, vals));
1196: v += row;
1197: for (i = 0; i < A->cmap->n; i++) {
1198: (*vals)[i] = *v;
1199: v += mat->lda;
1200: }
1201: PetscCall(MatDenseRestoreArrayRead(A, &v));
1202: }
1203: PetscFunctionReturn(PETSC_SUCCESS);
1204: }
1206: static PetscErrorCode MatRestoreRow_SeqDense(Mat A, PetscInt row, PetscInt *ncols, PetscInt **cols, PetscScalar **vals)
1207: {
1208: PetscFunctionBegin;
1209: if (cols) PetscCall(PetscFree(*cols));
1210: if (vals) PetscCall(PetscFree(*vals));
1211: PetscFunctionReturn(PETSC_SUCCESS);
1212: }
1214: static PetscErrorCode MatSetValues_SeqDense(Mat A, PetscInt m, const PetscInt indexm[], PetscInt n, const PetscInt indexn[], const PetscScalar v[], InsertMode addv)
1215: {
1216: Mat_SeqDense *mat = (Mat_SeqDense *)A->data;
1217: PetscScalar *av;
1218: PetscInt i, j, idx = 0;
1219: #if defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
1220: PetscOffloadMask oldf;
1221: #endif
1223: PetscFunctionBegin;
1224: PetscCall(MatDenseGetArray(A, &av));
1225: if (!mat->roworiented) {
1226: if (addv == INSERT_VALUES) {
1227: for (j = 0; j < n; j++) {
1228: if (indexn[j] < 0) {
1229: idx += m;
1230: continue;
1231: }
1232: 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);
1233: for (i = 0; i < m; i++) {
1234: if (indexm[i] < 0) {
1235: idx++;
1236: continue;
1237: }
1238: 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);
1239: av[indexn[j] * mat->lda + indexm[i]] = v[idx++];
1240: }
1241: }
1242: } else {
1243: for (j = 0; j < n; j++) {
1244: if (indexn[j] < 0) {
1245: idx += m;
1246: continue;
1247: }
1248: 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);
1249: for (i = 0; i < m; i++) {
1250: if (indexm[i] < 0) {
1251: idx++;
1252: continue;
1253: }
1254: 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);
1255: av[indexn[j] * mat->lda + indexm[i]] += v[idx++];
1256: }
1257: }
1258: }
1259: } else {
1260: if (addv == INSERT_VALUES) {
1261: for (i = 0; i < m; i++) {
1262: if (indexm[i] < 0) {
1263: idx += n;
1264: continue;
1265: }
1266: 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);
1267: for (j = 0; j < n; j++) {
1268: if (indexn[j] < 0) {
1269: idx++;
1270: continue;
1271: }
1272: 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);
1273: av[indexn[j] * mat->lda + indexm[i]] = v[idx++];
1274: }
1275: }
1276: } else {
1277: for (i = 0; i < m; i++) {
1278: if (indexm[i] < 0) {
1279: idx += n;
1280: continue;
1281: }
1282: 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);
1283: for (j = 0; j < n; j++) {
1284: if (indexn[j] < 0) {
1285: idx++;
1286: continue;
1287: }
1288: 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);
1289: av[indexn[j] * mat->lda + indexm[i]] += v[idx++];
1290: }
1291: }
1292: }
1293: }
1294: /* hack to prevent unneeded copy to the GPU while returning the array */
1295: #if defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
1296: oldf = A->offloadmask;
1297: A->offloadmask = PETSC_OFFLOAD_GPU;
1298: #endif
1299: PetscCall(MatDenseRestoreArray(A, &av));
1300: #if defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
1301: A->offloadmask = (oldf == PETSC_OFFLOAD_UNALLOCATED ? PETSC_OFFLOAD_UNALLOCATED : PETSC_OFFLOAD_CPU);
1302: #endif
1303: PetscFunctionReturn(PETSC_SUCCESS);
1304: }
1306: static PetscErrorCode MatGetValues_SeqDense(Mat A, PetscInt m, const PetscInt indexm[], PetscInt n, const PetscInt indexn[], PetscScalar v[])
1307: {
1308: Mat_SeqDense *mat = (Mat_SeqDense *)A->data;
1309: const PetscScalar *vv;
1310: PetscInt i, j;
1312: PetscFunctionBegin;
1313: PetscCall(MatDenseGetArrayRead(A, &vv));
1314: /* row-oriented output */
1315: for (i = 0; i < m; i++) {
1316: if (indexm[i] < 0) {
1317: v += n;
1318: continue;
1319: }
1320: 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);
1321: for (j = 0; j < n; j++) {
1322: if (indexn[j] < 0) {
1323: v++;
1324: continue;
1325: }
1326: 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);
1327: *v++ = vv[indexn[j] * mat->lda + indexm[i]];
1328: }
1329: }
1330: PetscCall(MatDenseRestoreArrayRead(A, &vv));
1331: PetscFunctionReturn(PETSC_SUCCESS);
1332: }
1334: PetscErrorCode MatView_Dense_Binary(Mat mat, PetscViewer viewer)
1335: {
1336: PetscBool skipHeader;
1337: PetscViewerFormat format;
1338: PetscInt header[4], M, N, m, lda, i, j, k;
1339: const PetscScalar *v;
1340: PetscScalar *vwork;
1342: PetscFunctionBegin;
1343: PetscCall(PetscViewerSetUp(viewer));
1344: PetscCall(PetscViewerBinaryGetSkipHeader(viewer, &skipHeader));
1345: PetscCall(PetscViewerGetFormat(viewer, &format));
1346: if (skipHeader) format = PETSC_VIEWER_NATIVE;
1348: PetscCall(MatGetSize(mat, &M, &N));
1350: /* write matrix header */
1351: header[0] = MAT_FILE_CLASSID;
1352: header[1] = M;
1353: header[2] = N;
1354: header[3] = (format == PETSC_VIEWER_NATIVE) ? MATRIX_BINARY_FORMAT_DENSE : M * N;
1355: if (!skipHeader) PetscCall(PetscViewerBinaryWrite(viewer, header, 4, PETSC_INT));
1357: PetscCall(MatGetLocalSize(mat, &m, NULL));
1358: if (format != PETSC_VIEWER_NATIVE) {
1359: PetscInt nnz = m * N, *iwork;
1360: /* store row lengths for each row */
1361: PetscCall(PetscMalloc1(nnz, &iwork));
1362: for (i = 0; i < m; i++) iwork[i] = N;
1363: PetscCall(PetscViewerBinaryWriteAll(viewer, iwork, m, PETSC_DETERMINE, PETSC_DETERMINE, PETSC_INT));
1364: /* store column indices (zero start index) */
1365: for (k = 0, i = 0; i < m; i++)
1366: for (j = 0; j < N; j++, k++) iwork[k] = j;
1367: PetscCall(PetscViewerBinaryWriteAll(viewer, iwork, nnz, PETSC_DETERMINE, PETSC_DETERMINE, PETSC_INT));
1368: PetscCall(PetscFree(iwork));
1369: }
1370: /* store matrix values as a dense matrix in row major order */
1371: PetscCall(PetscMalloc1(m * N, &vwork));
1372: PetscCall(MatDenseGetArrayRead(mat, &v));
1373: PetscCall(MatDenseGetLDA(mat, &lda));
1374: for (k = 0, i = 0; i < m; i++)
1375: for (j = 0; j < N; j++, k++) vwork[k] = v[i + lda * j];
1376: PetscCall(MatDenseRestoreArrayRead(mat, &v));
1377: PetscCall(PetscViewerBinaryWriteAll(viewer, vwork, m * N, PETSC_DETERMINE, PETSC_DETERMINE, PETSC_SCALAR));
1378: PetscCall(PetscFree(vwork));
1379: PetscFunctionReturn(PETSC_SUCCESS);
1380: }
1382: PetscErrorCode MatLoad_Dense_Binary(Mat mat, PetscViewer viewer)
1383: {
1384: PetscBool skipHeader;
1385: PetscInt header[4], M, N, m, nz, lda, i, j, k;
1386: PetscInt rows, cols;
1387: PetscScalar *v, *vwork;
1389: PetscFunctionBegin;
1390: PetscCall(PetscViewerSetUp(viewer));
1391: PetscCall(PetscViewerBinaryGetSkipHeader(viewer, &skipHeader));
1393: if (!skipHeader) {
1394: PetscCall(PetscViewerBinaryRead(viewer, header, 4, NULL, PETSC_INT));
1395: PetscCheck(header[0] == MAT_FILE_CLASSID, PetscObjectComm((PetscObject)viewer), PETSC_ERR_FILE_UNEXPECTED, "Not a matrix object in file");
1396: M = header[1];
1397: N = header[2];
1398: PetscCheck(M >= 0, PetscObjectComm((PetscObject)viewer), PETSC_ERR_FILE_UNEXPECTED, "Matrix row size (%" PetscInt_FMT ") in file is negative", M);
1399: PetscCheck(N >= 0, PetscObjectComm((PetscObject)viewer), PETSC_ERR_FILE_UNEXPECTED, "Matrix column size (%" PetscInt_FMT ") in file is negative", N);
1400: nz = header[3];
1401: PetscCheck(nz == MATRIX_BINARY_FORMAT_DENSE || nz >= 0, PetscObjectComm((PetscObject)viewer), PETSC_ERR_FILE_UNEXPECTED, "Unknown matrix format %" PetscInt_FMT " in file", nz);
1402: } else {
1403: PetscCall(MatGetSize(mat, &M, &N));
1404: 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");
1405: nz = MATRIX_BINARY_FORMAT_DENSE;
1406: }
1408: /* setup global sizes if not set */
1409: if (mat->rmap->N < 0) mat->rmap->N = M;
1410: if (mat->cmap->N < 0) mat->cmap->N = N;
1411: PetscCall(MatSetUp(mat));
1412: /* check if global sizes are correct */
1413: PetscCall(MatGetSize(mat, &rows, &cols));
1414: 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);
1416: PetscCall(MatGetSize(mat, NULL, &N));
1417: PetscCall(MatGetLocalSize(mat, &m, NULL));
1418: PetscCall(MatDenseGetArray(mat, &v));
1419: PetscCall(MatDenseGetLDA(mat, &lda));
1420: if (nz == MATRIX_BINARY_FORMAT_DENSE) { /* matrix in file is dense format */
1421: PetscInt nnz = m * N;
1422: /* read in matrix values */
1423: PetscCall(PetscMalloc1(nnz, &vwork));
1424: PetscCall(PetscViewerBinaryReadAll(viewer, vwork, nnz, PETSC_DETERMINE, PETSC_DETERMINE, PETSC_SCALAR));
1425: /* store values in column major order */
1426: for (j = 0; j < N; j++)
1427: for (i = 0; i < m; i++) v[i + lda * j] = vwork[i * N + j];
1428: PetscCall(PetscFree(vwork));
1429: } else { /* matrix in file is sparse format */
1430: PetscInt nnz = 0, *rlens, *icols;
1431: /* read in row lengths */
1432: PetscCall(PetscMalloc1(m, &rlens));
1433: PetscCall(PetscViewerBinaryReadAll(viewer, rlens, m, PETSC_DETERMINE, PETSC_DETERMINE, PETSC_INT));
1434: for (i = 0; i < m; i++) nnz += rlens[i];
1435: /* read in column indices and values */
1436: PetscCall(PetscMalloc2(nnz, &icols, nnz, &vwork));
1437: PetscCall(PetscViewerBinaryReadAll(viewer, icols, nnz, PETSC_DETERMINE, PETSC_DETERMINE, PETSC_INT));
1438: PetscCall(PetscViewerBinaryReadAll(viewer, vwork, nnz, PETSC_DETERMINE, PETSC_DETERMINE, PETSC_SCALAR));
1439: /* store values in column major order */
1440: for (k = 0, i = 0; i < m; i++)
1441: for (j = 0; j < rlens[i]; j++, k++) v[i + lda * icols[k]] = vwork[k];
1442: PetscCall(PetscFree(rlens));
1443: PetscCall(PetscFree2(icols, vwork));
1444: }
1445: PetscCall(MatDenseRestoreArray(mat, &v));
1446: PetscCall(MatAssemblyBegin(mat, MAT_FINAL_ASSEMBLY));
1447: PetscCall(MatAssemblyEnd(mat, MAT_FINAL_ASSEMBLY));
1448: PetscFunctionReturn(PETSC_SUCCESS);
1449: }
1451: static PetscErrorCode MatLoad_SeqDense(Mat newMat, PetscViewer viewer)
1452: {
1453: PetscBool isbinary, ishdf5;
1455: PetscFunctionBegin;
1458: /* force binary viewer to load .info file if it has not yet done so */
1459: PetscCall(PetscViewerSetUp(viewer));
1460: PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERBINARY, &isbinary));
1461: PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5));
1462: if (isbinary) {
1463: PetscCall(MatLoad_Dense_Binary(newMat, viewer));
1464: } else if (ishdf5) {
1465: #if defined(PETSC_HAVE_HDF5)
1466: PetscCall(MatLoad_Dense_HDF5(newMat, viewer));
1467: #else
1468: SETERRQ(PetscObjectComm((PetscObject)newMat), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5");
1469: #endif
1470: } else {
1471: 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);
1472: }
1473: PetscFunctionReturn(PETSC_SUCCESS);
1474: }
1476: static PetscErrorCode MatView_SeqDense_ASCII(Mat A, PetscViewer viewer)
1477: {
1478: Mat_SeqDense *a = (Mat_SeqDense *)A->data;
1479: PetscInt i, j;
1480: const char *name;
1481: PetscScalar *v, *av;
1482: PetscViewerFormat format;
1483: #if defined(PETSC_USE_COMPLEX)
1484: PetscBool allreal = PETSC_TRUE;
1485: #endif
1487: PetscFunctionBegin;
1488: PetscCall(MatDenseGetArrayRead(A, (const PetscScalar **)&av));
1489: PetscCall(PetscViewerGetFormat(viewer, &format));
1490: if (format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL) {
1491: PetscFunctionReturn(PETSC_SUCCESS); /* do nothing for now */
1492: } else if (format == PETSC_VIEWER_ASCII_COMMON) {
1493: PetscCall(PetscViewerASCIIUseTabs(viewer, PETSC_FALSE));
1494: for (i = 0; i < A->rmap->n; i++) {
1495: v = av + i;
1496: PetscCall(PetscViewerASCIIPrintf(viewer, "row %" PetscInt_FMT ":", i));
1497: for (j = 0; j < A->cmap->n; j++) {
1498: #if defined(PETSC_USE_COMPLEX)
1499: if (PetscRealPart(*v) != 0.0 && PetscImaginaryPart(*v) != 0.0) {
1500: PetscCall(PetscViewerASCIIPrintf(viewer, " (%" PetscInt_FMT ", %g + %g i) ", j, (double)PetscRealPart(*v), (double)PetscImaginaryPart(*v)));
1501: } else if (PetscRealPart(*v)) {
1502: PetscCall(PetscViewerASCIIPrintf(viewer, " (%" PetscInt_FMT ", %g) ", j, (double)PetscRealPart(*v)));
1503: }
1504: #else
1505: if (*v) PetscCall(PetscViewerASCIIPrintf(viewer, " (%" PetscInt_FMT ", %g) ", j, (double)*v));
1506: #endif
1507: v += a->lda;
1508: }
1509: PetscCall(PetscViewerASCIIPrintf(viewer, "\n"));
1510: }
1511: PetscCall(PetscViewerASCIIUseTabs(viewer, PETSC_TRUE));
1512: } else {
1513: PetscCall(PetscViewerASCIIUseTabs(viewer, PETSC_FALSE));
1514: #if defined(PETSC_USE_COMPLEX)
1515: /* determine if matrix has all real values */
1516: for (j = 0; j < A->cmap->n; j++) {
1517: v = av + j * a->lda;
1518: for (i = 0; i < A->rmap->n; i++) {
1519: if (PetscImaginaryPart(v[i])) {
1520: allreal = PETSC_FALSE;
1521: break;
1522: }
1523: }
1524: }
1525: #endif
1526: if (format == PETSC_VIEWER_ASCII_MATLAB) {
1527: PetscCall(PetscObjectGetName((PetscObject)A, &name));
1528: PetscCall(PetscViewerASCIIPrintf(viewer, "%% Size = %" PetscInt_FMT " %" PetscInt_FMT " \n", A->rmap->n, A->cmap->n));
1529: PetscCall(PetscViewerASCIIPrintf(viewer, "%s = zeros(%" PetscInt_FMT ",%" PetscInt_FMT ");\n", name, A->rmap->n, A->cmap->n));
1530: PetscCall(PetscViewerASCIIPrintf(viewer, "%s = [\n", name));
1531: }
1533: for (i = 0; i < A->rmap->n; i++) {
1534: v = av + i;
1535: for (j = 0; j < A->cmap->n; j++) {
1536: #if defined(PETSC_USE_COMPLEX)
1537: if (allreal) {
1538: PetscCall(PetscViewerASCIIPrintf(viewer, "%18.16e ", (double)PetscRealPart(*v)));
1539: } else {
1540: PetscCall(PetscViewerASCIIPrintf(viewer, "%18.16e + %18.16ei ", (double)PetscRealPart(*v), (double)PetscImaginaryPart(*v)));
1541: }
1542: #else
1543: PetscCall(PetscViewerASCIIPrintf(viewer, "%18.16e ", (double)*v));
1544: #endif
1545: v += a->lda;
1546: }
1547: PetscCall(PetscViewerASCIIPrintf(viewer, "\n"));
1548: }
1549: if (format == PETSC_VIEWER_ASCII_MATLAB) PetscCall(PetscViewerASCIIPrintf(viewer, "];\n"));
1550: PetscCall(PetscViewerASCIIUseTabs(viewer, PETSC_TRUE));
1551: }
1552: PetscCall(MatDenseRestoreArrayRead(A, (const PetscScalar **)&av));
1553: PetscCall(PetscViewerFlush(viewer));
1554: PetscFunctionReturn(PETSC_SUCCESS);
1555: }
1557: #include <petscdraw.h>
1558: static PetscErrorCode MatView_SeqDense_Draw_Zoom(PetscDraw draw, void *Aa)
1559: {
1560: Mat A = (Mat)Aa;
1561: PetscInt m = A->rmap->n, n = A->cmap->n, i, j;
1562: int color = PETSC_DRAW_WHITE;
1563: const PetscScalar *v;
1564: PetscViewer viewer;
1565: PetscReal xl, yl, xr, yr, x_l, x_r, y_l, y_r;
1566: PetscViewerFormat format;
1568: PetscFunctionBegin;
1569: PetscCall(PetscObjectQuery((PetscObject)A, "Zoomviewer", (PetscObject *)&viewer));
1570: PetscCall(PetscViewerGetFormat(viewer, &format));
1571: PetscCall(PetscDrawGetCoordinates(draw, &xl, &yl, &xr, &yr));
1573: /* Loop over matrix elements drawing boxes */
1574: PetscCall(MatDenseGetArrayRead(A, &v));
1575: if (format != PETSC_VIEWER_DRAW_CONTOUR) {
1576: PetscDrawCollectiveBegin(draw);
1577: /* Blue for negative and Red for positive */
1578: for (j = 0; j < n; j++) {
1579: x_l = j;
1580: x_r = x_l + 1.0;
1581: for (i = 0; i < m; i++) {
1582: y_l = m - i - 1.0;
1583: y_r = y_l + 1.0;
1584: if (PetscRealPart(v[j * m + i]) > 0.) color = PETSC_DRAW_RED;
1585: else if (PetscRealPart(v[j * m + i]) < 0.) color = PETSC_DRAW_BLUE;
1586: else continue;
1587: PetscCall(PetscDrawRectangle(draw, x_l, y_l, x_r, y_r, color, color, color, color));
1588: }
1589: }
1590: PetscDrawCollectiveEnd(draw);
1591: } else {
1592: /* use contour shading to indicate magnitude of values */
1593: /* first determine max of all nonzero values */
1594: PetscReal minv = 0.0, maxv = 0.0;
1595: PetscDraw popup;
1597: for (i = 0; i < m * n; i++) {
1598: if (PetscAbsScalar(v[i]) > maxv) maxv = PetscAbsScalar(v[i]);
1599: }
1600: if (minv >= maxv) maxv = minv + PETSC_SMALL;
1601: PetscCall(PetscDrawGetPopup(draw, &popup));
1602: PetscCall(PetscDrawScalePopup(popup, minv, maxv));
1604: PetscDrawCollectiveBegin(draw);
1605: for (j = 0; j < n; j++) {
1606: x_l = j;
1607: x_r = x_l + 1.0;
1608: for (i = 0; i < m; i++) {
1609: y_l = m - i - 1.0;
1610: y_r = y_l + 1.0;
1611: color = PetscDrawRealToColor(PetscAbsScalar(v[j * m + i]), minv, maxv);
1612: PetscCall(PetscDrawRectangle(draw, x_l, y_l, x_r, y_r, color, color, color, color));
1613: }
1614: }
1615: PetscDrawCollectiveEnd(draw);
1616: }
1617: PetscCall(MatDenseRestoreArrayRead(A, &v));
1618: PetscFunctionReturn(PETSC_SUCCESS);
1619: }
1621: static PetscErrorCode MatView_SeqDense_Draw(Mat A, PetscViewer viewer)
1622: {
1623: PetscDraw draw;
1624: PetscBool isnull;
1625: PetscReal xr, yr, xl, yl, h, w;
1627: PetscFunctionBegin;
1628: PetscCall(PetscViewerDrawGetDraw(viewer, 0, &draw));
1629: PetscCall(PetscDrawIsNull(draw, &isnull));
1630: if (isnull) PetscFunctionReturn(PETSC_SUCCESS);
1632: xr = A->cmap->n;
1633: yr = A->rmap->n;
1634: h = yr / 10.0;
1635: w = xr / 10.0;
1636: xr += w;
1637: yr += h;
1638: xl = -w;
1639: yl = -h;
1640: PetscCall(PetscDrawSetCoordinates(draw, xl, yl, xr, yr));
1641: PetscCall(PetscObjectCompose((PetscObject)A, "Zoomviewer", (PetscObject)viewer));
1642: PetscCall(PetscDrawZoom(draw, MatView_SeqDense_Draw_Zoom, A));
1643: PetscCall(PetscObjectCompose((PetscObject)A, "Zoomviewer", NULL));
1644: PetscCall(PetscDrawSave(draw));
1645: PetscFunctionReturn(PETSC_SUCCESS);
1646: }
1648: PetscErrorCode MatView_SeqDense(Mat A, PetscViewer viewer)
1649: {
1650: PetscBool iascii, isbinary, isdraw;
1652: PetscFunctionBegin;
1653: PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
1654: PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERBINARY, &isbinary));
1655: PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERDRAW, &isdraw));
1656: if (iascii) PetscCall(MatView_SeqDense_ASCII(A, viewer));
1657: else if (isbinary) PetscCall(MatView_Dense_Binary(A, viewer));
1658: else if (isdraw) PetscCall(MatView_SeqDense_Draw(A, viewer));
1659: PetscFunctionReturn(PETSC_SUCCESS);
1660: }
1662: static PetscErrorCode MatDensePlaceArray_SeqDense(Mat A, const PetscScalar *array)
1663: {
1664: Mat_SeqDense *a = (Mat_SeqDense *)A->data;
1666: PetscFunctionBegin;
1667: PetscCheck(!a->vecinuse, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Need to call MatDenseRestoreColumnVec() first");
1668: PetscCheck(!a->matinuse, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Need to call MatDenseRestoreSubMatrix() first");
1669: PetscCheck(!a->unplacedarray, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Need to call MatDenseResetArray() first");
1670: a->unplacedarray = a->v;
1671: a->unplaced_user_alloc = a->user_alloc;
1672: a->v = (PetscScalar *)array;
1673: a->user_alloc = PETSC_TRUE;
1674: #if defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
1675: A->offloadmask = PETSC_OFFLOAD_CPU;
1676: #endif
1677: PetscFunctionReturn(PETSC_SUCCESS);
1678: }
1680: static PetscErrorCode MatDenseResetArray_SeqDense(Mat A)
1681: {
1682: Mat_SeqDense *a = (Mat_SeqDense *)A->data;
1684: PetscFunctionBegin;
1685: PetscCheck(!a->vecinuse, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Need to call MatDenseRestoreColumnVec() first");
1686: PetscCheck(!a->matinuse, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Need to call MatDenseRestoreSubMatrix() first");
1687: a->v = a->unplacedarray;
1688: a->user_alloc = a->unplaced_user_alloc;
1689: a->unplacedarray = NULL;
1690: #if defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
1691: A->offloadmask = PETSC_OFFLOAD_CPU;
1692: #endif
1693: PetscFunctionReturn(PETSC_SUCCESS);
1694: }
1696: static PetscErrorCode MatDenseReplaceArray_SeqDense(Mat A, const PetscScalar *array)
1697: {
1698: Mat_SeqDense *a = (Mat_SeqDense *)A->data;
1700: PetscFunctionBegin;
1701: PetscCheck(!a->vecinuse, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Need to call MatDenseRestoreColumnVec() first");
1702: PetscCheck(!a->matinuse, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Need to call MatDenseRestoreSubMatrix() first");
1703: if (!a->user_alloc) PetscCall(PetscFree(a->v));
1704: a->v = (PetscScalar *)array;
1705: a->user_alloc = PETSC_FALSE;
1706: #if defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
1707: A->offloadmask = PETSC_OFFLOAD_CPU;
1708: #endif
1709: PetscFunctionReturn(PETSC_SUCCESS);
1710: }
1712: PetscErrorCode MatDestroy_SeqDense(Mat mat)
1713: {
1714: Mat_SeqDense *l = (Mat_SeqDense *)mat->data;
1716: PetscFunctionBegin;
1717: PetscCall(PetscLogObjectState((PetscObject)mat, "Rows %" PetscInt_FMT " Cols %" PetscInt_FMT, mat->rmap->n, mat->cmap->n));
1718: PetscCall(VecDestroy(&l->qrrhs));
1719: PetscCall(PetscFree(l->tau));
1720: PetscCall(PetscFree(l->pivots));
1721: PetscCall(PetscFree(l->fwork));
1722: if (!l->user_alloc) PetscCall(PetscFree(l->v));
1723: if (!l->unplaced_user_alloc) PetscCall(PetscFree(l->unplacedarray));
1724: PetscCheck(!l->vecinuse, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Need to call MatDenseRestoreColumnVec() first");
1725: PetscCheck(!l->matinuse, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Need to call MatDenseRestoreSubMatrix() first");
1726: PetscCall(VecDestroy(&l->cvec));
1727: PetscCall(MatDestroy(&l->cmat));
1728: PetscCall(PetscFree(mat->data));
1730: PetscCall(PetscObjectChangeTypeName((PetscObject)mat, NULL));
1731: PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatQRFactor_C", NULL));
1732: PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatQRFactorSymbolic_C", NULL));
1733: PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatQRFactorNumeric_C", NULL));
1734: PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatDenseGetLDA_C", NULL));
1735: PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatDenseSetLDA_C", NULL));
1736: PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatDenseGetArray_C", NULL));
1737: PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatDenseRestoreArray_C", NULL));
1738: PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatDensePlaceArray_C", NULL));
1739: PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatDenseResetArray_C", NULL));
1740: PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatDenseReplaceArray_C", NULL));
1741: PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatDenseGetArrayRead_C", NULL));
1742: PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatDenseRestoreArrayRead_C", NULL));
1743: PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatDenseGetArrayWrite_C", NULL));
1744: PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatDenseRestoreArrayWrite_C", NULL));
1745: PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatConvert_seqdense_seqaij_C", NULL));
1746: #if defined(PETSC_HAVE_ELEMENTAL)
1747: PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatConvert_seqdense_elemental_C", NULL));
1748: #endif
1749: #if defined(PETSC_HAVE_SCALAPACK)
1750: PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatConvert_seqdense_scalapack_C", NULL));
1751: #endif
1752: #if defined(PETSC_HAVE_CUDA)
1753: PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatConvert_seqdense_seqdensecuda_C", NULL));
1754: PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatProductSetFromOptions_seqdensecuda_seqdensecuda_C", NULL));
1755: PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatProductSetFromOptions_seqdensecuda_seqdense_C", NULL));
1756: PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatProductSetFromOptions_seqdense_seqdensecuda_C", NULL));
1757: #endif
1758: #if defined(PETSC_HAVE_HIP)
1759: PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatConvert_seqdense_seqdensehip_C", NULL));
1760: PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatProductSetFromOptions_seqdensehip_seqdensehip_C", NULL));
1761: PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatProductSetFromOptions_seqdensehip_seqdense_C", NULL));
1762: PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatProductSetFromOptions_seqdense_seqdensehip_C", NULL));
1763: #endif
1764: PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatSeqDenseSetPreallocation_C", NULL));
1765: PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatProductSetFromOptions_seqaij_seqdense_C", NULL));
1766: PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatProductSetFromOptions_seqdense_seqdense_C", NULL));
1767: PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatProductSetFromOptions_seqbaij_seqdense_C", NULL));
1768: PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatProductSetFromOptions_seqsbaij_seqdense_C", NULL));
1770: PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatDenseGetColumn_C", NULL));
1771: PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatDenseRestoreColumn_C", NULL));
1772: PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatDenseGetColumnVec_C", NULL));
1773: PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatDenseRestoreColumnVec_C", NULL));
1774: PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatDenseGetColumnVecRead_C", NULL));
1775: PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatDenseRestoreColumnVecRead_C", NULL));
1776: PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatDenseGetColumnVecWrite_C", NULL));
1777: PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatDenseRestoreColumnVecWrite_C", NULL));
1778: PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatDenseGetSubMatrix_C", NULL));
1779: PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatDenseRestoreSubMatrix_C", NULL));
1780: PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatMultAddColumnRange_C", NULL));
1781: PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatMultHermitianTransposeColumnRange_C", NULL));
1782: PetscCall(PetscObjectComposeFunction((PetscObject)mat, "MatMultHermitianTransposeAddColumnRange_C", NULL));
1783: PetscFunctionReturn(PETSC_SUCCESS);
1784: }
1786: static PetscErrorCode MatTranspose_SeqDense(Mat A, MatReuse reuse, Mat *matout)
1787: {
1788: Mat_SeqDense *mat = (Mat_SeqDense *)A->data;
1789: PetscInt k, j, m = A->rmap->n, M = mat->lda, n = A->cmap->n;
1790: PetscScalar *v, tmp;
1792: PetscFunctionBegin;
1793: if (reuse == MAT_REUSE_MATRIX) PetscCall(MatTransposeCheckNonzeroState_Private(A, *matout));
1794: if (reuse == MAT_INPLACE_MATRIX) {
1795: if (m == n) { /* in place transpose */
1796: PetscCall(MatDenseGetArray(A, &v));
1797: for (j = 0; j < m; j++) {
1798: for (k = 0; k < j; k++) {
1799: tmp = v[j + k * M];
1800: v[j + k * M] = v[k + j * M];
1801: v[k + j * M] = tmp;
1802: }
1803: }
1804: PetscCall(MatDenseRestoreArray(A, &v));
1805: } else { /* reuse memory, temporary allocates new memory */
1806: PetscScalar *v2;
1807: PetscLayout tmplayout;
1809: PetscCall(PetscMalloc1((size_t)m * n, &v2));
1810: PetscCall(MatDenseGetArray(A, &v));
1811: for (j = 0; j < n; j++) {
1812: for (k = 0; k < m; k++) v2[j + (size_t)k * n] = v[k + (size_t)j * M];
1813: }
1814: PetscCall(PetscArraycpy(v, v2, (size_t)m * n));
1815: PetscCall(PetscFree(v2));
1816: PetscCall(MatDenseRestoreArray(A, &v));
1817: /* cleanup size dependent quantities */
1818: PetscCall(VecDestroy(&mat->cvec));
1819: PetscCall(MatDestroy(&mat->cmat));
1820: PetscCall(PetscFree(mat->pivots));
1821: PetscCall(PetscFree(mat->fwork));
1822: /* swap row/col layouts */
1823: mat->lda = n;
1824: tmplayout = A->rmap;
1825: A->rmap = A->cmap;
1826: A->cmap = tmplayout;
1827: }
1828: } else { /* out-of-place transpose */
1829: Mat tmat;
1830: Mat_SeqDense *tmatd;
1831: PetscScalar *v2;
1832: PetscInt M2;
1834: if (reuse == MAT_INITIAL_MATRIX) {
1835: PetscCall(MatCreate(PetscObjectComm((PetscObject)A), &tmat));
1836: PetscCall(MatSetSizes(tmat, A->cmap->n, A->rmap->n, A->cmap->n, A->rmap->n));
1837: PetscCall(MatSetType(tmat, ((PetscObject)A)->type_name));
1838: PetscCall(MatSeqDenseSetPreallocation(tmat, NULL));
1839: } else tmat = *matout;
1841: PetscCall(MatDenseGetArrayRead(A, (const PetscScalar **)&v));
1842: PetscCall(MatDenseGetArray(tmat, &v2));
1843: tmatd = (Mat_SeqDense *)tmat->data;
1844: M2 = tmatd->lda;
1845: for (j = 0; j < n; j++) {
1846: for (k = 0; k < m; k++) v2[j + k * M2] = v[k + j * M];
1847: }
1848: PetscCall(MatDenseRestoreArray(tmat, &v2));
1849: PetscCall(MatDenseRestoreArrayRead(A, (const PetscScalar **)&v));
1850: PetscCall(MatAssemblyBegin(tmat, MAT_FINAL_ASSEMBLY));
1851: PetscCall(MatAssemblyEnd(tmat, MAT_FINAL_ASSEMBLY));
1852: *matout = tmat;
1853: }
1854: PetscFunctionReturn(PETSC_SUCCESS);
1855: }
1857: static PetscErrorCode MatEqual_SeqDense(Mat A1, Mat A2, PetscBool *flg)
1858: {
1859: Mat_SeqDense *mat1 = (Mat_SeqDense *)A1->data;
1860: Mat_SeqDense *mat2 = (Mat_SeqDense *)A2->data;
1861: PetscInt i;
1862: const PetscScalar *v1, *v2;
1864: PetscFunctionBegin;
1865: if (A1->rmap->n != A2->rmap->n) {
1866: *flg = PETSC_FALSE;
1867: PetscFunctionReturn(PETSC_SUCCESS);
1868: }
1869: if (A1->cmap->n != A2->cmap->n) {
1870: *flg = PETSC_FALSE;
1871: PetscFunctionReturn(PETSC_SUCCESS);
1872: }
1873: PetscCall(MatDenseGetArrayRead(A1, &v1));
1874: PetscCall(MatDenseGetArrayRead(A2, &v2));
1875: for (i = 0; i < A1->cmap->n; i++) {
1876: PetscCall(PetscArraycmp(v1, v2, A1->rmap->n, flg));
1877: if (*flg == PETSC_FALSE) PetscFunctionReturn(PETSC_SUCCESS);
1878: v1 += mat1->lda;
1879: v2 += mat2->lda;
1880: }
1881: PetscCall(MatDenseRestoreArrayRead(A1, &v1));
1882: PetscCall(MatDenseRestoreArrayRead(A2, &v2));
1883: *flg = PETSC_TRUE;
1884: PetscFunctionReturn(PETSC_SUCCESS);
1885: }
1887: PetscErrorCode MatGetDiagonal_SeqDense(Mat A, Vec v)
1888: {
1889: Mat_SeqDense *mat = (Mat_SeqDense *)A->data;
1890: PetscInt i, n, len;
1891: PetscScalar *x;
1892: const PetscScalar *vv;
1894: PetscFunctionBegin;
1895: PetscCall(VecGetSize(v, &n));
1896: PetscCall(VecGetArray(v, &x));
1897: len = PetscMin(A->rmap->n, A->cmap->n);
1898: PetscCall(MatDenseGetArrayRead(A, &vv));
1899: PetscCheck(n == A->rmap->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Nonconforming mat and vec");
1900: for (i = 0; i < len; i++) x[i] = vv[i * mat->lda + i];
1901: PetscCall(MatDenseRestoreArrayRead(A, &vv));
1902: PetscCall(VecRestoreArray(v, &x));
1903: PetscFunctionReturn(PETSC_SUCCESS);
1904: }
1906: static PetscErrorCode MatDiagonalScale_SeqDense(Mat A, Vec ll, Vec rr)
1907: {
1908: Mat_SeqDense *mat = (Mat_SeqDense *)A->data;
1909: const PetscScalar *l, *r;
1910: PetscScalar x, *v, *vv;
1911: PetscInt i, j, m = A->rmap->n, n = A->cmap->n;
1913: PetscFunctionBegin;
1914: PetscCall(MatDenseGetArray(A, &vv));
1915: if (ll) {
1916: PetscCall(VecGetSize(ll, &m));
1917: PetscCall(VecGetArrayRead(ll, &l));
1918: PetscCheck(m == A->rmap->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Left scaling vec wrong size");
1919: for (i = 0; i < m; i++) {
1920: x = l[i];
1921: v = vv + i;
1922: for (j = 0; j < n; j++) {
1923: (*v) *= x;
1924: v += mat->lda;
1925: }
1926: }
1927: PetscCall(VecRestoreArrayRead(ll, &l));
1928: PetscCall(PetscLogFlops(1.0 * n * m));
1929: }
1930: if (rr) {
1931: PetscCall(VecGetSize(rr, &n));
1932: PetscCall(VecGetArrayRead(rr, &r));
1933: PetscCheck(n == A->cmap->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Right scaling vec wrong size");
1934: for (i = 0; i < n; i++) {
1935: x = r[i];
1936: v = vv + i * mat->lda;
1937: for (j = 0; j < m; j++) (*v++) *= x;
1938: }
1939: PetscCall(VecRestoreArrayRead(rr, &r));
1940: PetscCall(PetscLogFlops(1.0 * n * m));
1941: }
1942: PetscCall(MatDenseRestoreArray(A, &vv));
1943: PetscFunctionReturn(PETSC_SUCCESS);
1944: }
1946: PetscErrorCode MatNorm_SeqDense(Mat A, NormType type, PetscReal *nrm)
1947: {
1948: Mat_SeqDense *mat = (Mat_SeqDense *)A->data;
1949: PetscScalar *v, *vv;
1950: PetscReal sum = 0.0;
1951: PetscInt lda, m = A->rmap->n, i, j;
1953: PetscFunctionBegin;
1954: PetscCall(MatDenseGetArrayRead(A, (const PetscScalar **)&vv));
1955: PetscCall(MatDenseGetLDA(A, &lda));
1956: v = vv;
1957: if (type == NORM_FROBENIUS) {
1958: if (lda > m) {
1959: for (j = 0; j < A->cmap->n; j++) {
1960: v = vv + j * lda;
1961: for (i = 0; i < m; i++) {
1962: sum += PetscRealPart(PetscConj(*v) * (*v));
1963: v++;
1964: }
1965: }
1966: } else {
1967: #if defined(PETSC_USE_REAL___FP16)
1968: PetscBLASInt one = 1, cnt = A->cmap->n * A->rmap->n;
1969: PetscCallBLAS("BLASnrm2", *nrm = BLASnrm2_(&cnt, v, &one));
1970: }
1971: #else
1972: for (i = 0; i < A->cmap->n * A->rmap->n; i++) {
1973: sum += PetscRealPart(PetscConj(*v) * (*v));
1974: v++;
1975: }
1976: }
1977: *nrm = PetscSqrtReal(sum);
1978: #endif
1979: PetscCall(PetscLogFlops(2.0 * A->cmap->n * A->rmap->n));
1980: } else if (type == NORM_1) {
1981: *nrm = 0.0;
1982: for (j = 0; j < A->cmap->n; j++) {
1983: v = vv + j * mat->lda;
1984: sum = 0.0;
1985: for (i = 0; i < A->rmap->n; i++) {
1986: sum += PetscAbsScalar(*v);
1987: v++;
1988: }
1989: if (sum > *nrm) *nrm = sum;
1990: }
1991: PetscCall(PetscLogFlops(1.0 * A->cmap->n * A->rmap->n));
1992: } else if (type == NORM_INFINITY) {
1993: *nrm = 0.0;
1994: for (j = 0; j < A->rmap->n; j++) {
1995: v = vv + j;
1996: sum = 0.0;
1997: for (i = 0; i < A->cmap->n; i++) {
1998: sum += PetscAbsScalar(*v);
1999: v += mat->lda;
2000: }
2001: if (sum > *nrm) *nrm = sum;
2002: }
2003: PetscCall(PetscLogFlops(1.0 * A->cmap->n * A->rmap->n));
2004: } else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "No two norm");
2005: PetscCall(MatDenseRestoreArrayRead(A, (const PetscScalar **)&vv));
2006: PetscFunctionReturn(PETSC_SUCCESS);
2007: }
2009: static PetscErrorCode MatSetOption_SeqDense(Mat A, MatOption op, PetscBool flg)
2010: {
2011: Mat_SeqDense *aij = (Mat_SeqDense *)A->data;
2013: PetscFunctionBegin;
2014: switch (op) {
2015: case MAT_ROW_ORIENTED:
2016: aij->roworiented = flg;
2017: break;
2018: case MAT_NEW_NONZERO_LOCATIONS:
2019: case MAT_NEW_NONZERO_LOCATION_ERR:
2020: case MAT_NEW_NONZERO_ALLOCATION_ERR:
2021: case MAT_FORCE_DIAGONAL_ENTRIES:
2022: case MAT_KEEP_NONZERO_PATTERN:
2023: case MAT_IGNORE_OFF_PROC_ENTRIES:
2024: case MAT_USE_HASH_TABLE:
2025: case MAT_IGNORE_ZERO_ENTRIES:
2026: case MAT_IGNORE_LOWER_TRIANGULAR:
2027: case MAT_SORTED_FULL:
2028: PetscCall(PetscInfo(A, "Option %s ignored\n", MatOptions[op]));
2029: break;
2030: case MAT_SPD:
2031: case MAT_SYMMETRIC:
2032: case MAT_STRUCTURALLY_SYMMETRIC:
2033: case MAT_HERMITIAN:
2034: case MAT_SYMMETRY_ETERNAL:
2035: case MAT_STRUCTURAL_SYMMETRY_ETERNAL:
2036: case MAT_SPD_ETERNAL:
2037: break;
2038: default:
2039: SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "unknown option %s", MatOptions[op]);
2040: }
2041: PetscFunctionReturn(PETSC_SUCCESS);
2042: }
2044: PetscErrorCode MatZeroEntries_SeqDense(Mat A)
2045: {
2046: Mat_SeqDense *l = (Mat_SeqDense *)A->data;
2047: PetscInt lda = l->lda, m = A->rmap->n, n = A->cmap->n, j;
2048: PetscScalar *v;
2050: PetscFunctionBegin;
2051: PetscCall(MatDenseGetArrayWrite(A, &v));
2052: if (lda > m) {
2053: for (j = 0; j < n; j++) PetscCall(PetscArrayzero(v + j * lda, m));
2054: } else {
2055: PetscCall(PetscArrayzero(v, PetscInt64Mult(m, n)));
2056: }
2057: PetscCall(MatDenseRestoreArrayWrite(A, &v));
2058: PetscFunctionReturn(PETSC_SUCCESS);
2059: }
2061: static PetscErrorCode MatZeroRows_SeqDense(Mat A, PetscInt N, const PetscInt rows[], PetscScalar diag, Vec x, Vec b)
2062: {
2063: Mat_SeqDense *l = (Mat_SeqDense *)A->data;
2064: PetscInt m = l->lda, n = A->cmap->n, i, j;
2065: PetscScalar *slot, *bb, *v;
2066: const PetscScalar *xx;
2068: PetscFunctionBegin;
2069: if (PetscDefined(USE_DEBUG)) {
2070: for (i = 0; i < N; i++) {
2071: PetscCheck(rows[i] >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Negative row requested to be zeroed");
2072: 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);
2073: }
2074: }
2075: if (!N) PetscFunctionReturn(PETSC_SUCCESS);
2077: /* fix right-hand side if needed */
2078: if (x && b) {
2079: PetscCall(VecGetArrayRead(x, &xx));
2080: PetscCall(VecGetArray(b, &bb));
2081: for (i = 0; i < N; i++) bb[rows[i]] = diag * xx[rows[i]];
2082: PetscCall(VecRestoreArrayRead(x, &xx));
2083: PetscCall(VecRestoreArray(b, &bb));
2084: }
2086: PetscCall(MatDenseGetArray(A, &v));
2087: for (i = 0; i < N; i++) {
2088: slot = v + rows[i];
2089: for (j = 0; j < n; j++) {
2090: *slot = 0.0;
2091: slot += m;
2092: }
2093: }
2094: if (diag != 0.0) {
2095: PetscCheck(A->rmap->n == A->cmap->n, PETSC_COMM_SELF, PETSC_ERR_SUP, "Only coded for square matrices");
2096: for (i = 0; i < N; i++) {
2097: slot = v + (m + 1) * rows[i];
2098: *slot = diag;
2099: }
2100: }
2101: PetscCall(MatDenseRestoreArray(A, &v));
2102: PetscFunctionReturn(PETSC_SUCCESS);
2103: }
2105: static PetscErrorCode MatDenseGetLDA_SeqDense(Mat A, PetscInt *lda)
2106: {
2107: Mat_SeqDense *mat = (Mat_SeqDense *)A->data;
2109: PetscFunctionBegin;
2110: *lda = mat->lda;
2111: PetscFunctionReturn(PETSC_SUCCESS);
2112: }
2114: PetscErrorCode MatDenseGetArray_SeqDense(Mat A, PetscScalar **array)
2115: {
2116: Mat_SeqDense *mat = (Mat_SeqDense *)A->data;
2118: PetscFunctionBegin;
2119: PetscCheck(!mat->matinuse, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Need to call MatDenseRestoreSubMatrix() first");
2120: *array = mat->v;
2121: PetscFunctionReturn(PETSC_SUCCESS);
2122: }
2124: PetscErrorCode MatDenseRestoreArray_SeqDense(Mat A, PetscScalar **array)
2125: {
2126: PetscFunctionBegin;
2127: if (array) *array = NULL;
2128: PetscFunctionReturn(PETSC_SUCCESS);
2129: }
2131: /*@
2132: MatDenseGetLDA - gets the leading dimension of the array returned from `MatDenseGetArray()`
2134: Not Collective
2136: Input Parameter:
2137: . A - a `MATDENSE` or `MATDENSECUDA` matrix
2139: Output Parameter:
2140: . lda - the leading dimension
2142: Level: intermediate
2144: .seealso: [](ch_matrices), `Mat`, `MATDENSE`, `MATDENSECUDA`, `MatDenseGetArray()`, `MatDenseRestoreArray()`, `MatDenseGetArrayRead()`, `MatDenseRestoreArrayRead()`, `MatDenseSetLDA()`
2145: @*/
2146: PetscErrorCode MatDenseGetLDA(Mat A, PetscInt *lda)
2147: {
2148: PetscFunctionBegin;
2150: PetscAssertPointer(lda, 2);
2151: MatCheckPreallocated(A, 1);
2152: PetscUseMethod(A, "MatDenseGetLDA_C", (Mat, PetscInt *), (A, lda));
2153: PetscFunctionReturn(PETSC_SUCCESS);
2154: }
2156: /*@
2157: MatDenseSetLDA - Sets the leading dimension of the array used by the `MATDENSE` matrix
2159: Collective if the matrix layouts have not yet been setup
2161: Input Parameters:
2162: + A - a `MATDENSE` or `MATDENSECUDA` matrix
2163: - lda - the leading dimension
2165: Level: intermediate
2167: .seealso: [](ch_matrices), `Mat`, `MATDENSE`, `MATDENSECUDA`, `MatDenseGetArray()`, `MatDenseRestoreArray()`, `MatDenseGetArrayRead()`, `MatDenseRestoreArrayRead()`, `MatDenseGetLDA()`
2168: @*/
2169: PetscErrorCode MatDenseSetLDA(Mat A, PetscInt lda)
2170: {
2171: PetscFunctionBegin;
2173: PetscTryMethod(A, "MatDenseSetLDA_C", (Mat, PetscInt), (A, lda));
2174: PetscFunctionReturn(PETSC_SUCCESS);
2175: }
2177: /*@C
2178: MatDenseGetArray - gives read-write access to the array where the data for a `MATDENSE` matrix is stored
2180: Logically Collective
2182: Input Parameter:
2183: . A - a dense matrix
2185: Output Parameter:
2186: . array - pointer to the data
2188: Level: intermediate
2190: Fortran Notes:
2191: `MatDenseGetArray()` Fortran binding is deprecated (since PETSc 3.19), use `MatDenseGetArrayF90()`
2193: .seealso: [](ch_matrices), `Mat`, `MATDENSE`, `MatDenseRestoreArray()`, `MatDenseGetArrayRead()`, `MatDenseRestoreArrayRead()`, `MatDenseGetArrayWrite()`, `MatDenseRestoreArrayWrite()`
2194: @*/
2195: PetscErrorCode MatDenseGetArray(Mat A, PetscScalar **array)
2196: {
2197: PetscFunctionBegin;
2199: PetscAssertPointer(array, 2);
2200: PetscUseMethod(A, "MatDenseGetArray_C", (Mat, PetscScalar **), (A, array));
2201: PetscFunctionReturn(PETSC_SUCCESS);
2202: }
2204: /*@C
2205: MatDenseRestoreArray - returns access to the array where the data for a `MATDENSE` matrix is stored obtained by `MatDenseGetArray()`
2207: Logically Collective
2209: Input Parameters:
2210: + A - a dense matrix
2211: - array - pointer to the data (may be `NULL`)
2213: Level: intermediate
2215: Fortran Notes:
2216: `MatDenseRestoreArray()` Fortran binding is deprecated (since PETSc 3.19), use `MatDenseRestoreArrayF90()`
2218: .seealso: [](ch_matrices), `Mat`, `MATDENSE`, `MatDenseGetArray()`, `MatDenseGetArrayRead()`, `MatDenseRestoreArrayRead()`, `MatDenseGetArrayWrite()`, `MatDenseRestoreArrayWrite()`
2219: @*/
2220: PetscErrorCode MatDenseRestoreArray(Mat A, PetscScalar **array)
2221: {
2222: PetscFunctionBegin;
2224: if (array) PetscAssertPointer(array, 2);
2225: PetscUseMethod(A, "MatDenseRestoreArray_C", (Mat, PetscScalar **), (A, array));
2226: PetscCall(PetscObjectStateIncrease((PetscObject)A));
2227: #if defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
2228: A->offloadmask = PETSC_OFFLOAD_CPU;
2229: #endif
2230: PetscFunctionReturn(PETSC_SUCCESS);
2231: }
2233: /*@C
2234: MatDenseGetArrayRead - gives read-only access to the array where the data for a `MATDENSE` matrix is stored
2236: Not Collective
2238: Input Parameter:
2239: . A - a dense matrix
2241: Output Parameter:
2242: . array - pointer to the data
2244: Level: intermediate
2246: .seealso: [](ch_matrices), `Mat`, `MATDENSE`, `MatDenseRestoreArrayRead()`, `MatDenseGetArray()`, `MatDenseRestoreArray()`, `MatDenseGetArrayWrite()`, `MatDenseRestoreArrayWrite()`
2247: @*/
2248: PetscErrorCode MatDenseGetArrayRead(Mat A, const PetscScalar **array)
2249: {
2250: PetscFunctionBegin;
2252: PetscAssertPointer(array, 2);
2253: PetscUseMethod(A, "MatDenseGetArrayRead_C", (Mat, PetscScalar **), (A, (PetscScalar **)array));
2254: PetscFunctionReturn(PETSC_SUCCESS);
2255: }
2257: /*@C
2258: MatDenseRestoreArrayRead - returns access to the array where the data for a `MATDENSE` matrix is stored obtained by `MatDenseGetArrayRead()`
2260: Not Collective
2262: Input Parameters:
2263: + A - a dense matrix
2264: - array - pointer to the data (may be `NULL`)
2266: Level: intermediate
2268: .seealso: [](ch_matrices), `Mat`, `MATDENSE`, `MatDenseGetArrayRead()`, `MatDenseGetArray()`, `MatDenseRestoreArray()`, `MatDenseGetArrayWrite()`, `MatDenseRestoreArrayWrite()`
2269: @*/
2270: PetscErrorCode MatDenseRestoreArrayRead(Mat A, const PetscScalar **array)
2271: {
2272: PetscFunctionBegin;
2274: if (array) PetscAssertPointer(array, 2);
2275: PetscUseMethod(A, "MatDenseRestoreArrayRead_C", (Mat, PetscScalar **), (A, (PetscScalar **)array));
2276: PetscFunctionReturn(PETSC_SUCCESS);
2277: }
2279: /*@C
2280: MatDenseGetArrayWrite - gives write-only access to the array where the data for a `MATDENSE` matrix is stored
2282: Not Collective
2284: Input Parameter:
2285: . A - a dense matrix
2287: Output Parameter:
2288: . array - pointer to the data
2290: Level: intermediate
2292: .seealso: [](ch_matrices), `Mat`, `MATDENSE`, `MatDenseRestoreArrayWrite()`, `MatDenseGetArray()`, `MatDenseRestoreArray()`, `MatDenseGetArrayRead()`, `MatDenseRestoreArrayRead()`
2293: @*/
2294: PetscErrorCode MatDenseGetArrayWrite(Mat A, PetscScalar **array)
2295: {
2296: PetscFunctionBegin;
2298: PetscAssertPointer(array, 2);
2299: PetscUseMethod(A, "MatDenseGetArrayWrite_C", (Mat, PetscScalar **), (A, array));
2300: PetscFunctionReturn(PETSC_SUCCESS);
2301: }
2303: /*@C
2304: MatDenseRestoreArrayWrite - returns access to the array where the data for a `MATDENSE` matrix is stored obtained by `MatDenseGetArrayWrite()`
2306: Not Collective
2308: Input Parameters:
2309: + A - a dense matrix
2310: - array - pointer to the data (may be `NULL`)
2312: Level: intermediate
2314: .seealso: [](ch_matrices), `Mat`, `MATDENSE`, `MatDenseGetArrayWrite()`, `MatDenseGetArray()`, `MatDenseRestoreArray()`, `MatDenseGetArrayRead()`, `MatDenseRestoreArrayRead()`
2315: @*/
2316: PetscErrorCode MatDenseRestoreArrayWrite(Mat A, PetscScalar **array)
2317: {
2318: PetscFunctionBegin;
2320: if (array) PetscAssertPointer(array, 2);
2321: PetscUseMethod(A, "MatDenseRestoreArrayWrite_C", (Mat, PetscScalar **), (A, array));
2322: PetscCall(PetscObjectStateIncrease((PetscObject)A));
2323: #if defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
2324: A->offloadmask = PETSC_OFFLOAD_CPU;
2325: #endif
2326: PetscFunctionReturn(PETSC_SUCCESS);
2327: }
2329: /*@C
2330: MatDenseGetArrayAndMemType - gives read-write access to the array where the data for a `MATDENSE` matrix is stored
2332: Logically Collective
2334: Input Parameter:
2335: . A - a dense matrix
2337: Output Parameters:
2338: + array - pointer to the data
2339: - mtype - memory type of the returned pointer
2341: Level: intermediate
2343: Note:
2344: If the matrix is of a device type such as `MATDENSECUDA`, `MATDENSEHIP`, etc.,
2345: an array on device is always returned and is guaranteed to contain the matrix's latest data.
2347: .seealso: [](ch_matrices), `Mat`, `MATDENSE`, `MatDenseRestoreArrayAndMemType()`, `MatDenseGetArrayReadAndMemType()`, `MatDenseGetArrayWriteAndMemType()`, `MatDenseGetArrayRead()`,
2348: `MatDenseRestoreArrayRead()`, `MatDenseGetArrayWrite()`, `MatDenseRestoreArrayWrite()`, `MatSeqAIJGetCSRAndMemType()`
2349: @*/
2350: PetscErrorCode MatDenseGetArrayAndMemType(Mat A, PetscScalar **array, PetscMemType *mtype)
2351: {
2352: PetscBool isMPI;
2354: PetscFunctionBegin;
2356: PetscAssertPointer(array, 2);
2357: 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 */
2358: PetscCall(PetscObjectBaseTypeCompare((PetscObject)A, MATMPIDENSE, &isMPI));
2359: if (isMPI) {
2360: /* Dispatch here so that the code can be reused for all subclasses of MATDENSE */
2361: PetscCall(MatDenseGetArrayAndMemType(((Mat_MPIDense *)A->data)->A, array, mtype));
2362: } else {
2363: PetscErrorCode (*fptr)(Mat, PetscScalar **, PetscMemType *);
2365: PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatDenseGetArrayAndMemType_C", &fptr));
2366: if (fptr) {
2367: PetscCall((*fptr)(A, array, mtype));
2368: } else {
2369: PetscUseMethod(A, "MatDenseGetArray_C", (Mat, PetscScalar **), (A, array));
2370: if (mtype) *mtype = PETSC_MEMTYPE_HOST;
2371: }
2372: }
2373: PetscFunctionReturn(PETSC_SUCCESS);
2374: }
2376: /*@C
2377: MatDenseRestoreArrayAndMemType - returns access to the array that is obtained by `MatDenseGetArrayAndMemType()`
2379: Logically Collective
2381: Input Parameters:
2382: + A - a dense matrix
2383: - array - pointer to the data
2385: Level: intermediate
2387: .seealso: [](ch_matrices), `Mat`, `MATDENSE`, `MatDenseGetArrayAndMemType()`, `MatDenseGetArray()`, `MatDenseGetArrayRead()`, `MatDenseRestoreArrayRead()`, `MatDenseGetArrayWrite()`, `MatDenseRestoreArrayWrite()`
2388: @*/
2389: PetscErrorCode MatDenseRestoreArrayAndMemType(Mat A, PetscScalar **array)
2390: {
2391: PetscBool isMPI;
2393: PetscFunctionBegin;
2395: PetscAssertPointer(array, 2);
2396: PetscCall(PetscObjectBaseTypeCompare((PetscObject)A, MATMPIDENSE, &isMPI));
2397: if (isMPI) {
2398: PetscCall(MatDenseRestoreArrayAndMemType(((Mat_MPIDense *)A->data)->A, array));
2399: } else {
2400: PetscErrorCode (*fptr)(Mat, PetscScalar **);
2402: PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatDenseRestoreArrayAndMemType_C", &fptr));
2403: if (fptr) {
2404: PetscCall((*fptr)(A, array));
2405: } else {
2406: PetscUseMethod(A, "MatDenseRestoreArray_C", (Mat, PetscScalar **), (A, array));
2407: }
2408: *array = NULL;
2409: }
2410: PetscCall(PetscObjectStateIncrease((PetscObject)A));
2411: PetscFunctionReturn(PETSC_SUCCESS);
2412: }
2414: /*@C
2415: MatDenseGetArrayReadAndMemType - gives read-only access to the array where the data for a `MATDENSE` matrix is stored
2417: Logically Collective
2419: Input Parameter:
2420: . A - a dense matrix
2422: Output Parameters:
2423: + array - pointer to the data
2424: - mtype - memory type of the returned pointer
2426: Level: intermediate
2428: Note:
2429: If the matrix is of a device type such as `MATDENSECUDA`, `MATDENSEHIP`, etc.,
2430: an array on device is always returned and is guaranteed to contain the matrix's latest data.
2432: .seealso: [](ch_matrices), `Mat`, `MATDENSE`, `MatDenseRestoreArrayReadAndMemType()`, `MatDenseGetArrayWriteAndMemType()`,
2433: `MatDenseGetArrayRead()`, `MatDenseRestoreArrayRead()`, `MatDenseGetArrayWrite()`, `MatDenseRestoreArrayWrite()`, `MatSeqAIJGetCSRAndMemType()`
2434: @*/
2435: PetscErrorCode MatDenseGetArrayReadAndMemType(Mat A, const PetscScalar **array, PetscMemType *mtype)
2436: {
2437: PetscBool isMPI;
2439: PetscFunctionBegin;
2441: PetscAssertPointer(array, 2);
2442: 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 */
2443: PetscCall(PetscObjectBaseTypeCompare((PetscObject)A, MATMPIDENSE, &isMPI));
2444: if (isMPI) { /* Dispatch here so that the code can be reused for all subclasses of MATDENSE */
2445: PetscCall(MatDenseGetArrayReadAndMemType(((Mat_MPIDense *)A->data)->A, array, mtype));
2446: } else {
2447: PetscErrorCode (*fptr)(Mat, const PetscScalar **, PetscMemType *);
2449: PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatDenseGetArrayReadAndMemType_C", &fptr));
2450: if (fptr) {
2451: PetscCall((*fptr)(A, array, mtype));
2452: } else {
2453: PetscUseMethod(A, "MatDenseGetArrayRead_C", (Mat, PetscScalar **), (A, (PetscScalar **)array));
2454: if (mtype) *mtype = PETSC_MEMTYPE_HOST;
2455: }
2456: }
2457: PetscFunctionReturn(PETSC_SUCCESS);
2458: }
2460: /*@C
2461: MatDenseRestoreArrayReadAndMemType - returns access to the array that is obtained by `MatDenseGetArrayReadAndMemType()`
2463: Logically Collective
2465: Input Parameters:
2466: + A - a dense matrix
2467: - array - pointer to the data
2469: Level: intermediate
2471: .seealso: [](ch_matrices), `Mat`, `MATDENSE`, `MatDenseGetArrayReadAndMemType()`, `MatDenseGetArray()`, `MatDenseGetArrayRead()`, `MatDenseRestoreArrayRead()`, `MatDenseGetArrayWrite()`, `MatDenseRestoreArrayWrite()`
2472: @*/
2473: PetscErrorCode MatDenseRestoreArrayReadAndMemType(Mat A, const PetscScalar **array)
2474: {
2475: PetscBool isMPI;
2477: PetscFunctionBegin;
2479: PetscAssertPointer(array, 2);
2480: PetscCall(PetscObjectBaseTypeCompare((PetscObject)A, MATMPIDENSE, &isMPI));
2481: if (isMPI) {
2482: PetscCall(MatDenseRestoreArrayReadAndMemType(((Mat_MPIDense *)A->data)->A, array));
2483: } else {
2484: PetscErrorCode (*fptr)(Mat, const PetscScalar **);
2486: PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatDenseRestoreArrayReadAndMemType_C", &fptr));
2487: if (fptr) {
2488: PetscCall((*fptr)(A, array));
2489: } else {
2490: PetscUseMethod(A, "MatDenseRestoreArrayRead_C", (Mat, PetscScalar **), (A, (PetscScalar **)array));
2491: }
2492: *array = NULL;
2493: }
2494: PetscFunctionReturn(PETSC_SUCCESS);
2495: }
2497: /*@C
2498: MatDenseGetArrayWriteAndMemType - gives write-only access to the array where the data for a `MATDENSE` matrix is stored
2500: Logically Collective
2502: Input Parameter:
2503: . A - a dense matrix
2505: Output Parameters:
2506: + array - pointer to the data
2507: - mtype - memory type of the returned pointer
2509: Level: intermediate
2511: Note:
2512: If the matrix is of a device type such as `MATDENSECUDA`, `MATDENSEHIP`, etc.,
2513: an array on device is always returned and is guaranteed to contain the matrix's latest data.
2515: .seealso: [](ch_matrices), `Mat`, `MATDENSE`, `MatDenseRestoreArrayWriteAndMemType()`, `MatDenseGetArrayReadAndMemType()`, `MatDenseGetArrayRead()`,
2516: `MatDenseRestoreArrayRead()`, `MatDenseGetArrayWrite()`, `MatDenseRestoreArrayWrite()`, `MatSeqAIJGetCSRAndMemType()`
2517: @*/
2518: PetscErrorCode MatDenseGetArrayWriteAndMemType(Mat A, PetscScalar **array, PetscMemType *mtype)
2519: {
2520: PetscBool isMPI;
2522: PetscFunctionBegin;
2524: PetscAssertPointer(array, 2);
2525: 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 */
2526: PetscCall(PetscObjectBaseTypeCompare((PetscObject)A, MATMPIDENSE, &isMPI));
2527: if (isMPI) {
2528: PetscCall(MatDenseGetArrayWriteAndMemType(((Mat_MPIDense *)A->data)->A, array, mtype));
2529: } else {
2530: PetscErrorCode (*fptr)(Mat, PetscScalar **, PetscMemType *);
2532: PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatDenseGetArrayWriteAndMemType_C", &fptr));
2533: if (fptr) {
2534: PetscCall((*fptr)(A, array, mtype));
2535: } else {
2536: PetscUseMethod(A, "MatDenseGetArrayWrite_C", (Mat, PetscScalar **), (A, array));
2537: if (mtype) *mtype = PETSC_MEMTYPE_HOST;
2538: }
2539: }
2540: PetscFunctionReturn(PETSC_SUCCESS);
2541: }
2543: /*@C
2544: MatDenseRestoreArrayWriteAndMemType - returns access to the array that is obtained by `MatDenseGetArrayReadAndMemType()`
2546: Logically Collective
2548: Input Parameters:
2549: + A - a dense matrix
2550: - array - pointer to the data
2552: Level: intermediate
2554: .seealso: [](ch_matrices), `Mat`, `MATDENSE`, `MatDenseGetArrayWriteAndMemType()`, `MatDenseGetArray()`, `MatDenseGetArrayRead()`, `MatDenseRestoreArrayRead()`, `MatDenseGetArrayWrite()`, `MatDenseRestoreArrayWrite()`
2555: @*/
2556: PetscErrorCode MatDenseRestoreArrayWriteAndMemType(Mat A, PetscScalar **array)
2557: {
2558: PetscBool isMPI;
2560: PetscFunctionBegin;
2562: PetscAssertPointer(array, 2);
2563: PetscCall(PetscObjectBaseTypeCompare((PetscObject)A, MATMPIDENSE, &isMPI));
2564: if (isMPI) {
2565: PetscCall(MatDenseRestoreArrayWriteAndMemType(((Mat_MPIDense *)A->data)->A, array));
2566: } else {
2567: PetscErrorCode (*fptr)(Mat, PetscScalar **);
2569: PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatDenseRestoreArrayWriteAndMemType_C", &fptr));
2570: if (fptr) {
2571: PetscCall((*fptr)(A, array));
2572: } else {
2573: PetscUseMethod(A, "MatDenseRestoreArrayWrite_C", (Mat, PetscScalar **), (A, array));
2574: }
2575: *array = NULL;
2576: }
2577: PetscCall(PetscObjectStateIncrease((PetscObject)A));
2578: PetscFunctionReturn(PETSC_SUCCESS);
2579: }
2581: static PetscErrorCode MatCreateSubMatrix_SeqDense(Mat A, IS isrow, IS iscol, MatReuse scall, Mat *B)
2582: {
2583: Mat_SeqDense *mat = (Mat_SeqDense *)A->data;
2584: PetscInt i, j, nrows, ncols, ldb;
2585: const PetscInt *irow, *icol;
2586: PetscScalar *av, *bv, *v = mat->v;
2587: Mat newmat;
2589: PetscFunctionBegin;
2590: PetscCall(ISGetIndices(isrow, &irow));
2591: PetscCall(ISGetIndices(iscol, &icol));
2592: PetscCall(ISGetLocalSize(isrow, &nrows));
2593: PetscCall(ISGetLocalSize(iscol, &ncols));
2595: /* Check submatrixcall */
2596: if (scall == MAT_REUSE_MATRIX) {
2597: PetscInt n_cols, n_rows;
2598: PetscCall(MatGetSize(*B, &n_rows, &n_cols));
2599: if (n_rows != nrows || n_cols != ncols) {
2600: /* resize the result matrix to match number of requested rows/columns */
2601: PetscCall(MatSetSizes(*B, nrows, ncols, nrows, ncols));
2602: }
2603: newmat = *B;
2604: } else {
2605: /* Create and fill new matrix */
2606: PetscCall(MatCreate(PetscObjectComm((PetscObject)A), &newmat));
2607: PetscCall(MatSetSizes(newmat, nrows, ncols, nrows, ncols));
2608: PetscCall(MatSetType(newmat, ((PetscObject)A)->type_name));
2609: PetscCall(MatSeqDenseSetPreallocation(newmat, NULL));
2610: }
2612: /* Now extract the data pointers and do the copy,column at a time */
2613: PetscCall(MatDenseGetArray(newmat, &bv));
2614: PetscCall(MatDenseGetLDA(newmat, &ldb));
2615: for (i = 0; i < ncols; i++) {
2616: av = v + mat->lda * icol[i];
2617: for (j = 0; j < nrows; j++) bv[j] = av[irow[j]];
2618: bv += ldb;
2619: }
2620: PetscCall(MatDenseRestoreArray(newmat, &bv));
2622: /* Assemble the matrices so that the correct flags are set */
2623: PetscCall(MatAssemblyBegin(newmat, MAT_FINAL_ASSEMBLY));
2624: PetscCall(MatAssemblyEnd(newmat, MAT_FINAL_ASSEMBLY));
2626: /* Free work space */
2627: PetscCall(ISRestoreIndices(isrow, &irow));
2628: PetscCall(ISRestoreIndices(iscol, &icol));
2629: *B = newmat;
2630: PetscFunctionReturn(PETSC_SUCCESS);
2631: }
2633: static PetscErrorCode MatCreateSubMatrices_SeqDense(Mat A, PetscInt n, const IS irow[], const IS icol[], MatReuse scall, Mat *B[])
2634: {
2635: PetscInt i;
2637: PetscFunctionBegin;
2638: if (scall == MAT_INITIAL_MATRIX) PetscCall(PetscCalloc1(n, B));
2640: for (i = 0; i < n; i++) PetscCall(MatCreateSubMatrix_SeqDense(A, irow[i], icol[i], scall, &(*B)[i]));
2641: PetscFunctionReturn(PETSC_SUCCESS);
2642: }
2644: static PetscErrorCode MatAssemblyBegin_SeqDense(Mat mat, MatAssemblyType mode)
2645: {
2646: PetscFunctionBegin;
2647: PetscFunctionReturn(PETSC_SUCCESS);
2648: }
2650: static PetscErrorCode MatAssemblyEnd_SeqDense(Mat mat, MatAssemblyType mode)
2651: {
2652: PetscFunctionBegin;
2653: PetscFunctionReturn(PETSC_SUCCESS);
2654: }
2656: PetscErrorCode MatCopy_SeqDense(Mat A, Mat B, MatStructure str)
2657: {
2658: Mat_SeqDense *a = (Mat_SeqDense *)A->data, *b = (Mat_SeqDense *)B->data;
2659: const PetscScalar *va;
2660: PetscScalar *vb;
2661: PetscInt lda1 = a->lda, lda2 = b->lda, m = A->rmap->n, n = A->cmap->n, j;
2663: PetscFunctionBegin;
2664: /* If the two matrices don't have the same copy implementation, they aren't compatible for fast copy. */
2665: if (A->ops->copy != B->ops->copy) {
2666: PetscCall(MatCopy_Basic(A, B, str));
2667: PetscFunctionReturn(PETSC_SUCCESS);
2668: }
2669: PetscCheck(m == B->rmap->n && n == B->cmap->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "size(B) != size(A)");
2670: PetscCall(MatDenseGetArrayRead(A, &va));
2671: PetscCall(MatDenseGetArray(B, &vb));
2672: if (lda1 > m || lda2 > m) {
2673: for (j = 0; j < n; j++) PetscCall(PetscArraycpy(vb + j * lda2, va + j * lda1, m));
2674: } else {
2675: PetscCall(PetscArraycpy(vb, va, A->rmap->n * A->cmap->n));
2676: }
2677: PetscCall(MatDenseRestoreArray(B, &vb));
2678: PetscCall(MatDenseRestoreArrayRead(A, &va));
2679: PetscCall(MatAssemblyBegin(B, MAT_FINAL_ASSEMBLY));
2680: PetscCall(MatAssemblyEnd(B, MAT_FINAL_ASSEMBLY));
2681: PetscFunctionReturn(PETSC_SUCCESS);
2682: }
2684: PetscErrorCode MatSetUp_SeqDense(Mat A)
2685: {
2686: PetscFunctionBegin;
2687: PetscCall(PetscLayoutSetUp(A->rmap));
2688: PetscCall(PetscLayoutSetUp(A->cmap));
2689: if (!A->preallocated) PetscCall(MatSeqDenseSetPreallocation(A, NULL));
2690: PetscFunctionReturn(PETSC_SUCCESS);
2691: }
2693: static PetscErrorCode MatConjugate_SeqDense(Mat A)
2694: {
2695: Mat_SeqDense *mat = (Mat_SeqDense *)A->data;
2696: PetscInt i, j;
2697: PetscInt min = PetscMin(A->rmap->n, A->cmap->n);
2698: PetscScalar *aa;
2700: PetscFunctionBegin;
2701: PetscCall(MatDenseGetArray(A, &aa));
2702: for (j = 0; j < A->cmap->n; j++) {
2703: for (i = 0; i < A->rmap->n; i++) aa[i + j * mat->lda] = PetscConj(aa[i + j * mat->lda]);
2704: }
2705: PetscCall(MatDenseRestoreArray(A, &aa));
2706: if (mat->tau)
2707: for (i = 0; i < min; i++) mat->tau[i] = PetscConj(mat->tau[i]);
2708: PetscFunctionReturn(PETSC_SUCCESS);
2709: }
2711: static PetscErrorCode MatRealPart_SeqDense(Mat A)
2712: {
2713: Mat_SeqDense *mat = (Mat_SeqDense *)A->data;
2714: PetscInt i, j;
2715: PetscScalar *aa;
2717: PetscFunctionBegin;
2718: PetscCall(MatDenseGetArray(A, &aa));
2719: for (j = 0; j < A->cmap->n; j++) {
2720: for (i = 0; i < A->rmap->n; i++) aa[i + j * mat->lda] = PetscRealPart(aa[i + j * mat->lda]);
2721: }
2722: PetscCall(MatDenseRestoreArray(A, &aa));
2723: PetscFunctionReturn(PETSC_SUCCESS);
2724: }
2726: static PetscErrorCode MatImaginaryPart_SeqDense(Mat A)
2727: {
2728: Mat_SeqDense *mat = (Mat_SeqDense *)A->data;
2729: PetscInt i, j;
2730: PetscScalar *aa;
2732: PetscFunctionBegin;
2733: PetscCall(MatDenseGetArray(A, &aa));
2734: for (j = 0; j < A->cmap->n; j++) {
2735: for (i = 0; i < A->rmap->n; i++) aa[i + j * mat->lda] = PetscImaginaryPart(aa[i + j * mat->lda]);
2736: }
2737: PetscCall(MatDenseRestoreArray(A, &aa));
2738: PetscFunctionReturn(PETSC_SUCCESS);
2739: }
2741: PetscErrorCode MatMatMultSymbolic_SeqDense_SeqDense(Mat A, Mat B, PetscReal fill, Mat C)
2742: {
2743: PetscInt m = A->rmap->n, n = B->cmap->n;
2744: PetscBool cisdense = PETSC_FALSE;
2746: PetscFunctionBegin;
2747: PetscCall(MatSetSizes(C, m, n, m, n));
2748: #if defined(PETSC_HAVE_CUDA)
2749: PetscCall(PetscObjectTypeCompareAny((PetscObject)C, &cisdense, MATSEQDENSE, MATSEQDENSECUDA, ""));
2750: #endif
2751: #if defined(PETSC_HAVE_HIP)
2752: PetscCall(PetscObjectTypeCompareAny((PetscObject)C, &cisdense, MATSEQDENSE, MATSEQDENSEHIP, ""));
2753: #endif
2754: if (!cisdense) {
2755: PetscBool flg;
2757: PetscCall(PetscObjectTypeCompare((PetscObject)B, ((PetscObject)A)->type_name, &flg));
2758: PetscCall(MatSetType(C, flg ? ((PetscObject)A)->type_name : MATDENSE));
2759: }
2760: PetscCall(MatSetUp(C));
2761: PetscFunctionReturn(PETSC_SUCCESS);
2762: }
2764: PetscErrorCode MatMatMultNumeric_SeqDense_SeqDense(Mat A, Mat B, Mat C)
2765: {
2766: Mat_SeqDense *a = (Mat_SeqDense *)A->data, *b = (Mat_SeqDense *)B->data, *c = (Mat_SeqDense *)C->data;
2767: PetscBLASInt m, n, k;
2768: const PetscScalar *av, *bv;
2769: PetscScalar *cv;
2770: PetscScalar _DOne = 1.0, _DZero = 0.0;
2772: PetscFunctionBegin;
2773: PetscCall(PetscBLASIntCast(C->rmap->n, &m));
2774: PetscCall(PetscBLASIntCast(C->cmap->n, &n));
2775: PetscCall(PetscBLASIntCast(A->cmap->n, &k));
2776: if (!m || !n || !k) PetscFunctionReturn(PETSC_SUCCESS);
2777: PetscCall(MatDenseGetArrayRead(A, &av));
2778: PetscCall(MatDenseGetArrayRead(B, &bv));
2779: PetscCall(MatDenseGetArrayWrite(C, &cv));
2780: PetscCallBLAS("BLASgemm", BLASgemm_("N", "N", &m, &n, &k, &_DOne, av, &a->lda, bv, &b->lda, &_DZero, cv, &c->lda));
2781: PetscCall(PetscLogFlops(1.0 * m * n * k + 1.0 * m * n * (k - 1)));
2782: PetscCall(MatDenseRestoreArrayRead(A, &av));
2783: PetscCall(MatDenseRestoreArrayRead(B, &bv));
2784: PetscCall(MatDenseRestoreArrayWrite(C, &cv));
2785: PetscFunctionReturn(PETSC_SUCCESS);
2786: }
2788: PetscErrorCode MatMatTransposeMultSymbolic_SeqDense_SeqDense(Mat A, Mat B, PetscReal fill, Mat C)
2789: {
2790: PetscInt m = A->rmap->n, n = B->rmap->n;
2791: PetscBool cisdense = PETSC_FALSE;
2793: PetscFunctionBegin;
2794: PetscCall(MatSetSizes(C, m, n, m, n));
2795: #if defined(PETSC_HAVE_CUDA)
2796: PetscCall(PetscObjectTypeCompareAny((PetscObject)C, &cisdense, MATSEQDENSE, MATSEQDENSECUDA, ""));
2797: #endif
2798: #if defined(PETSC_HAVE_HIP)
2799: PetscCall(PetscObjectTypeCompareAny((PetscObject)C, &cisdense, MATSEQDENSE, MATSEQDENSEHIP, ""));
2800: #endif
2801: if (!cisdense) {
2802: PetscBool flg;
2804: PetscCall(PetscObjectTypeCompare((PetscObject)B, ((PetscObject)A)->type_name, &flg));
2805: PetscCall(MatSetType(C, flg ? ((PetscObject)A)->type_name : MATDENSE));
2806: }
2807: PetscCall(MatSetUp(C));
2808: PetscFunctionReturn(PETSC_SUCCESS);
2809: }
2811: PetscErrorCode MatMatTransposeMultNumeric_SeqDense_SeqDense(Mat A, Mat B, Mat C)
2812: {
2813: Mat_SeqDense *a = (Mat_SeqDense *)A->data;
2814: Mat_SeqDense *b = (Mat_SeqDense *)B->data;
2815: Mat_SeqDense *c = (Mat_SeqDense *)C->data;
2816: const PetscScalar *av, *bv;
2817: PetscScalar *cv;
2818: PetscBLASInt m, n, k;
2819: PetscScalar _DOne = 1.0, _DZero = 0.0;
2821: PetscFunctionBegin;
2822: PetscCall(PetscBLASIntCast(C->rmap->n, &m));
2823: PetscCall(PetscBLASIntCast(C->cmap->n, &n));
2824: PetscCall(PetscBLASIntCast(A->cmap->n, &k));
2825: if (!m || !n || !k) PetscFunctionReturn(PETSC_SUCCESS);
2826: PetscCall(MatDenseGetArrayRead(A, &av));
2827: PetscCall(MatDenseGetArrayRead(B, &bv));
2828: PetscCall(MatDenseGetArrayWrite(C, &cv));
2829: PetscCallBLAS("BLASgemm", BLASgemm_("N", "T", &m, &n, &k, &_DOne, av, &a->lda, bv, &b->lda, &_DZero, cv, &c->lda));
2830: PetscCall(MatDenseRestoreArrayRead(A, &av));
2831: PetscCall(MatDenseRestoreArrayRead(B, &bv));
2832: PetscCall(MatDenseRestoreArrayWrite(C, &cv));
2833: PetscCall(PetscLogFlops(1.0 * m * n * k + 1.0 * m * n * (k - 1)));
2834: PetscFunctionReturn(PETSC_SUCCESS);
2835: }
2837: PetscErrorCode MatTransposeMatMultSymbolic_SeqDense_SeqDense(Mat A, Mat B, PetscReal fill, Mat C)
2838: {
2839: PetscInt m = A->cmap->n, n = B->cmap->n;
2840: PetscBool cisdense = PETSC_FALSE;
2842: PetscFunctionBegin;
2843: PetscCall(MatSetSizes(C, m, n, m, n));
2844: #if defined(PETSC_HAVE_CUDA)
2845: PetscCall(PetscObjectTypeCompareAny((PetscObject)C, &cisdense, MATSEQDENSE, MATSEQDENSECUDA, ""));
2846: #endif
2847: #if defined(PETSC_HAVE_HIP)
2848: PetscCall(PetscObjectTypeCompareAny((PetscObject)C, &cisdense, MATSEQDENSE, MATSEQDENSEHIP, ""));
2849: #endif
2850: if (!cisdense) {
2851: PetscBool flg;
2853: PetscCall(PetscObjectTypeCompare((PetscObject)B, ((PetscObject)A)->type_name, &flg));
2854: PetscCall(MatSetType(C, flg ? ((PetscObject)A)->type_name : MATDENSE));
2855: }
2856: PetscCall(MatSetUp(C));
2857: PetscFunctionReturn(PETSC_SUCCESS);
2858: }
2860: PetscErrorCode MatTransposeMatMultNumeric_SeqDense_SeqDense(Mat A, Mat B, Mat C)
2861: {
2862: Mat_SeqDense *a = (Mat_SeqDense *)A->data;
2863: Mat_SeqDense *b = (Mat_SeqDense *)B->data;
2864: Mat_SeqDense *c = (Mat_SeqDense *)C->data;
2865: const PetscScalar *av, *bv;
2866: PetscScalar *cv;
2867: PetscBLASInt m, n, k;
2868: PetscScalar _DOne = 1.0, _DZero = 0.0;
2870: PetscFunctionBegin;
2871: PetscCall(PetscBLASIntCast(C->rmap->n, &m));
2872: PetscCall(PetscBLASIntCast(C->cmap->n, &n));
2873: PetscCall(PetscBLASIntCast(A->rmap->n, &k));
2874: if (!m || !n || !k) PetscFunctionReturn(PETSC_SUCCESS);
2875: PetscCall(MatDenseGetArrayRead(A, &av));
2876: PetscCall(MatDenseGetArrayRead(B, &bv));
2877: PetscCall(MatDenseGetArrayWrite(C, &cv));
2878: PetscCallBLAS("BLASgemm", BLASgemm_("T", "N", &m, &n, &k, &_DOne, av, &a->lda, bv, &b->lda, &_DZero, cv, &c->lda));
2879: PetscCall(MatDenseRestoreArrayRead(A, &av));
2880: PetscCall(MatDenseRestoreArrayRead(B, &bv));
2881: PetscCall(MatDenseRestoreArrayWrite(C, &cv));
2882: PetscCall(PetscLogFlops(1.0 * m * n * k + 1.0 * m * n * (k - 1)));
2883: PetscFunctionReturn(PETSC_SUCCESS);
2884: }
2886: static PetscErrorCode MatProductSetFromOptions_SeqDense_AB(Mat C)
2887: {
2888: PetscFunctionBegin;
2889: C->ops->matmultsymbolic = MatMatMultSymbolic_SeqDense_SeqDense;
2890: C->ops->productsymbolic = MatProductSymbolic_AB;
2891: PetscFunctionReturn(PETSC_SUCCESS);
2892: }
2894: static PetscErrorCode MatProductSetFromOptions_SeqDense_AtB(Mat C)
2895: {
2896: PetscFunctionBegin;
2897: C->ops->transposematmultsymbolic = MatTransposeMatMultSymbolic_SeqDense_SeqDense;
2898: C->ops->productsymbolic = MatProductSymbolic_AtB;
2899: PetscFunctionReturn(PETSC_SUCCESS);
2900: }
2902: static PetscErrorCode MatProductSetFromOptions_SeqDense_ABt(Mat C)
2903: {
2904: PetscFunctionBegin;
2905: C->ops->mattransposemultsymbolic = MatMatTransposeMultSymbolic_SeqDense_SeqDense;
2906: C->ops->productsymbolic = MatProductSymbolic_ABt;
2907: PetscFunctionReturn(PETSC_SUCCESS);
2908: }
2910: PETSC_INTERN PetscErrorCode MatProductSetFromOptions_SeqDense(Mat C)
2911: {
2912: Mat_Product *product = C->product;
2914: PetscFunctionBegin;
2915: switch (product->type) {
2916: case MATPRODUCT_AB:
2917: PetscCall(MatProductSetFromOptions_SeqDense_AB(C));
2918: break;
2919: case MATPRODUCT_AtB:
2920: PetscCall(MatProductSetFromOptions_SeqDense_AtB(C));
2921: break;
2922: case MATPRODUCT_ABt:
2923: PetscCall(MatProductSetFromOptions_SeqDense_ABt(C));
2924: break;
2925: default:
2926: break;
2927: }
2928: PetscFunctionReturn(PETSC_SUCCESS);
2929: }
2931: static PetscErrorCode MatGetRowMax_SeqDense(Mat A, Vec v, PetscInt idx[])
2932: {
2933: Mat_SeqDense *a = (Mat_SeqDense *)A->data;
2934: PetscInt i, j, m = A->rmap->n, n = A->cmap->n, p;
2935: PetscScalar *x;
2936: const PetscScalar *aa;
2938: PetscFunctionBegin;
2939: PetscCheck(!A->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2940: PetscCall(VecGetArray(v, &x));
2941: PetscCall(VecGetLocalSize(v, &p));
2942: PetscCall(MatDenseGetArrayRead(A, &aa));
2943: PetscCheck(p == A->rmap->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Nonconforming matrix and vector");
2944: for (i = 0; i < m; i++) {
2945: x[i] = aa[i];
2946: if (idx) idx[i] = 0;
2947: for (j = 1; j < n; j++) {
2948: if (PetscRealPart(x[i]) < PetscRealPart(aa[i + a->lda * j])) {
2949: x[i] = aa[i + a->lda * j];
2950: if (idx) idx[i] = j;
2951: }
2952: }
2953: }
2954: PetscCall(MatDenseRestoreArrayRead(A, &aa));
2955: PetscCall(VecRestoreArray(v, &x));
2956: PetscFunctionReturn(PETSC_SUCCESS);
2957: }
2959: static PetscErrorCode MatGetRowMaxAbs_SeqDense(Mat A, Vec v, PetscInt idx[])
2960: {
2961: Mat_SeqDense *a = (Mat_SeqDense *)A->data;
2962: PetscInt i, j, m = A->rmap->n, n = A->cmap->n, p;
2963: PetscScalar *x;
2964: PetscReal atmp;
2965: const PetscScalar *aa;
2967: PetscFunctionBegin;
2968: PetscCheck(!A->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2969: PetscCall(VecGetArray(v, &x));
2970: PetscCall(VecGetLocalSize(v, &p));
2971: PetscCall(MatDenseGetArrayRead(A, &aa));
2972: PetscCheck(p == A->rmap->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Nonconforming matrix and vector");
2973: for (i = 0; i < m; i++) {
2974: x[i] = PetscAbsScalar(aa[i]);
2975: for (j = 1; j < n; j++) {
2976: atmp = PetscAbsScalar(aa[i + a->lda * j]);
2977: if (PetscAbsScalar(x[i]) < atmp) {
2978: x[i] = atmp;
2979: if (idx) idx[i] = j;
2980: }
2981: }
2982: }
2983: PetscCall(MatDenseRestoreArrayRead(A, &aa));
2984: PetscCall(VecRestoreArray(v, &x));
2985: PetscFunctionReturn(PETSC_SUCCESS);
2986: }
2988: static PetscErrorCode MatGetRowMin_SeqDense(Mat A, Vec v, PetscInt idx[])
2989: {
2990: Mat_SeqDense *a = (Mat_SeqDense *)A->data;
2991: PetscInt i, j, m = A->rmap->n, n = A->cmap->n, p;
2992: PetscScalar *x;
2993: const PetscScalar *aa;
2995: PetscFunctionBegin;
2996: PetscCheck(!A->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2997: PetscCall(MatDenseGetArrayRead(A, &aa));
2998: PetscCall(VecGetArray(v, &x));
2999: PetscCall(VecGetLocalSize(v, &p));
3000: PetscCheck(p == A->rmap->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Nonconforming matrix and vector");
3001: for (i = 0; i < m; i++) {
3002: x[i] = aa[i];
3003: if (idx) idx[i] = 0;
3004: for (j = 1; j < n; j++) {
3005: if (PetscRealPart(x[i]) > PetscRealPart(aa[i + a->lda * j])) {
3006: x[i] = aa[i + a->lda * j];
3007: if (idx) idx[i] = j;
3008: }
3009: }
3010: }
3011: PetscCall(VecRestoreArray(v, &x));
3012: PetscCall(MatDenseRestoreArrayRead(A, &aa));
3013: PetscFunctionReturn(PETSC_SUCCESS);
3014: }
3016: PetscErrorCode MatGetColumnVector_SeqDense(Mat A, Vec v, PetscInt col)
3017: {
3018: Mat_SeqDense *a = (Mat_SeqDense *)A->data;
3019: PetscScalar *x;
3020: const PetscScalar *aa;
3022: PetscFunctionBegin;
3023: PetscCheck(!A->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3024: PetscCall(MatDenseGetArrayRead(A, &aa));
3025: PetscCall(VecGetArray(v, &x));
3026: PetscCall(PetscArraycpy(x, aa + col * a->lda, A->rmap->n));
3027: PetscCall(VecRestoreArray(v, &x));
3028: PetscCall(MatDenseRestoreArrayRead(A, &aa));
3029: PetscFunctionReturn(PETSC_SUCCESS);
3030: }
3032: PETSC_INTERN PetscErrorCode MatGetColumnReductions_SeqDense(Mat A, PetscInt type, PetscReal *reductions)
3033: {
3034: PetscInt i, j, m, n;
3035: const PetscScalar *a;
3037: PetscFunctionBegin;
3038: PetscCall(MatGetSize(A, &m, &n));
3039: PetscCall(PetscArrayzero(reductions, n));
3040: PetscCall(MatDenseGetArrayRead(A, &a));
3041: if (type == NORM_2) {
3042: for (i = 0; i < n; i++) {
3043: for (j = 0; j < m; j++) reductions[i] += PetscAbsScalar(a[j] * a[j]);
3044: a = PetscSafePointerPlusOffset(a, m);
3045: }
3046: } else if (type == NORM_1) {
3047: for (i = 0; i < n; i++) {
3048: for (j = 0; j < m; j++) reductions[i] += PetscAbsScalar(a[j]);
3049: a = PetscSafePointerPlusOffset(a, m);
3050: }
3051: } else if (type == NORM_INFINITY) {
3052: for (i = 0; i < n; i++) {
3053: for (j = 0; j < m; j++) reductions[i] = PetscMax(PetscAbsScalar(a[j]), reductions[i]);
3054: a = PetscSafePointerPlusOffset(a, m);
3055: }
3056: } else if (type == REDUCTION_SUM_REALPART || type == REDUCTION_MEAN_REALPART) {
3057: for (i = 0; i < n; i++) {
3058: for (j = 0; j < m; j++) reductions[i] += PetscRealPart(a[j]);
3059: a = PetscSafePointerPlusOffset(a, m);
3060: }
3061: } else if (type == REDUCTION_SUM_IMAGINARYPART || type == REDUCTION_MEAN_IMAGINARYPART) {
3062: for (i = 0; i < n; i++) {
3063: for (j = 0; j < m; j++) reductions[i] += PetscImaginaryPart(a[j]);
3064: a = PetscSafePointerPlusOffset(a, m);
3065: }
3066: } else SETERRQ(PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONG, "Unknown reduction type");
3067: PetscCall(MatDenseRestoreArrayRead(A, &a));
3068: if (type == NORM_2) {
3069: for (i = 0; i < n; i++) reductions[i] = PetscSqrtReal(reductions[i]);
3070: } else if (type == REDUCTION_MEAN_REALPART || type == REDUCTION_MEAN_IMAGINARYPART) {
3071: for (i = 0; i < n; i++) reductions[i] /= m;
3072: }
3073: PetscFunctionReturn(PETSC_SUCCESS);
3074: }
3076: PetscErrorCode MatSetRandom_SeqDense(Mat x, PetscRandom rctx)
3077: {
3078: PetscScalar *a;
3079: PetscInt lda, m, n, i, j;
3081: PetscFunctionBegin;
3082: PetscCall(MatGetSize(x, &m, &n));
3083: PetscCall(MatDenseGetLDA(x, &lda));
3084: PetscCall(MatDenseGetArrayWrite(x, &a));
3085: for (j = 0; j < n; j++) {
3086: for (i = 0; i < m; i++) PetscCall(PetscRandomGetValue(rctx, a + j * lda + i));
3087: }
3088: PetscCall(MatDenseRestoreArrayWrite(x, &a));
3089: PetscFunctionReturn(PETSC_SUCCESS);
3090: }
3092: static PetscErrorCode MatMissingDiagonal_SeqDense(Mat A, PetscBool *missing, PetscInt *d)
3093: {
3094: PetscFunctionBegin;
3095: *missing = PETSC_FALSE;
3096: PetscFunctionReturn(PETSC_SUCCESS);
3097: }
3099: /* vals is not const */
3100: static PetscErrorCode MatDenseGetColumn_SeqDense(Mat A, PetscInt col, PetscScalar **vals)
3101: {
3102: Mat_SeqDense *a = (Mat_SeqDense *)A->data;
3103: PetscScalar *v;
3105: PetscFunctionBegin;
3106: PetscCheck(!A->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3107: PetscCall(MatDenseGetArray(A, &v));
3108: *vals = v + col * a->lda;
3109: PetscCall(MatDenseRestoreArray(A, &v));
3110: PetscFunctionReturn(PETSC_SUCCESS);
3111: }
3113: static PetscErrorCode MatDenseRestoreColumn_SeqDense(Mat A, PetscScalar **vals)
3114: {
3115: PetscFunctionBegin;
3116: if (vals) *vals = NULL; /* user cannot accidentally use the array later */
3117: PetscFunctionReturn(PETSC_SUCCESS);
3118: }
3120: static struct _MatOps MatOps_Values = {MatSetValues_SeqDense,
3121: MatGetRow_SeqDense,
3122: MatRestoreRow_SeqDense,
3123: MatMult_SeqDense,
3124: /* 4*/ MatMultAdd_SeqDense,
3125: MatMultTranspose_SeqDense,
3126: MatMultTransposeAdd_SeqDense,
3127: NULL,
3128: NULL,
3129: NULL,
3130: /* 10*/ NULL,
3131: MatLUFactor_SeqDense,
3132: MatCholeskyFactor_SeqDense,
3133: MatSOR_SeqDense,
3134: MatTranspose_SeqDense,
3135: /* 15*/ MatGetInfo_SeqDense,
3136: MatEqual_SeqDense,
3137: MatGetDiagonal_SeqDense,
3138: MatDiagonalScale_SeqDense,
3139: MatNorm_SeqDense,
3140: /* 20*/ MatAssemblyBegin_SeqDense,
3141: MatAssemblyEnd_SeqDense,
3142: MatSetOption_SeqDense,
3143: MatZeroEntries_SeqDense,
3144: /* 24*/ MatZeroRows_SeqDense,
3145: NULL,
3146: NULL,
3147: NULL,
3148: NULL,
3149: /* 29*/ MatSetUp_SeqDense,
3150: NULL,
3151: NULL,
3152: NULL,
3153: NULL,
3154: /* 34*/ MatDuplicate_SeqDense,
3155: NULL,
3156: NULL,
3157: NULL,
3158: NULL,
3159: /* 39*/ MatAXPY_SeqDense,
3160: MatCreateSubMatrices_SeqDense,
3161: NULL,
3162: MatGetValues_SeqDense,
3163: MatCopy_SeqDense,
3164: /* 44*/ MatGetRowMax_SeqDense,
3165: MatScale_SeqDense,
3166: MatShift_SeqDense,
3167: NULL,
3168: MatZeroRowsColumns_SeqDense,
3169: /* 49*/ MatSetRandom_SeqDense,
3170: NULL,
3171: NULL,
3172: NULL,
3173: NULL,
3174: /* 54*/ NULL,
3175: NULL,
3176: NULL,
3177: NULL,
3178: NULL,
3179: /* 59*/ MatCreateSubMatrix_SeqDense,
3180: MatDestroy_SeqDense,
3181: MatView_SeqDense,
3182: NULL,
3183: NULL,
3184: /* 64*/ NULL,
3185: NULL,
3186: NULL,
3187: NULL,
3188: NULL,
3189: /* 69*/ MatGetRowMaxAbs_SeqDense,
3190: NULL,
3191: NULL,
3192: NULL,
3193: NULL,
3194: /* 74*/ NULL,
3195: NULL,
3196: NULL,
3197: NULL,
3198: NULL,
3199: /* 79*/ NULL,
3200: NULL,
3201: NULL,
3202: NULL,
3203: /* 83*/ MatLoad_SeqDense,
3204: MatIsSymmetric_SeqDense,
3205: MatIsHermitian_SeqDense,
3206: NULL,
3207: NULL,
3208: NULL,
3209: /* 89*/ NULL,
3210: NULL,
3211: MatMatMultNumeric_SeqDense_SeqDense,
3212: NULL,
3213: NULL,
3214: /* 94*/ NULL,
3215: NULL,
3216: NULL,
3217: MatMatTransposeMultNumeric_SeqDense_SeqDense,
3218: NULL,
3219: /* 99*/ MatProductSetFromOptions_SeqDense,
3220: NULL,
3221: NULL,
3222: MatConjugate_SeqDense,
3223: NULL,
3224: /*104*/ NULL,
3225: MatRealPart_SeqDense,
3226: MatImaginaryPart_SeqDense,
3227: NULL,
3228: NULL,
3229: /*109*/ NULL,
3230: NULL,
3231: MatGetRowMin_SeqDense,
3232: MatGetColumnVector_SeqDense,
3233: MatMissingDiagonal_SeqDense,
3234: /*114*/ NULL,
3235: NULL,
3236: NULL,
3237: NULL,
3238: NULL,
3239: /*119*/ NULL,
3240: NULL,
3241: MatMultHermitianTranspose_SeqDense,
3242: MatMultHermitianTransposeAdd_SeqDense,
3243: NULL,
3244: /*124*/ NULL,
3245: MatGetColumnReductions_SeqDense,
3246: NULL,
3247: NULL,
3248: NULL,
3249: /*129*/ NULL,
3250: NULL,
3251: NULL,
3252: MatTransposeMatMultNumeric_SeqDense_SeqDense,
3253: NULL,
3254: /*134*/ NULL,
3255: NULL,
3256: NULL,
3257: NULL,
3258: NULL,
3259: /*139*/ NULL,
3260: NULL,
3261: NULL,
3262: NULL,
3263: NULL,
3264: MatCreateMPIMatConcatenateSeqMat_SeqDense,
3265: /*145*/ NULL,
3266: NULL,
3267: NULL,
3268: NULL,
3269: NULL,
3270: /*150*/ NULL,
3271: NULL,
3272: NULL};
3274: /*@C
3275: MatCreateSeqDense - Creates a `MATSEQDENSE` that
3276: is stored in column major order (the usual Fortran format).
3278: Collective
3280: Input Parameters:
3281: + comm - MPI communicator, set to `PETSC_COMM_SELF`
3282: . m - number of rows
3283: . n - number of columns
3284: - data - optional location of matrix data in column major order. Use `NULL` for PETSc
3285: to control all matrix memory allocation.
3287: Output Parameter:
3288: . A - the matrix
3290: Level: intermediate
3292: Note:
3293: The data input variable is intended primarily for Fortran programmers
3294: who wish to allocate their own matrix memory space. Most users should
3295: set `data` = `NULL`.
3297: Developer Note:
3298: Many of the matrix operations for this variant use the BLAS and LAPACK routines.
3300: .seealso: [](ch_matrices), `Mat`, `MATSEQDENSE`, `MatCreate()`, `MatCreateDense()`, `MatSetValues()`
3301: @*/
3302: PetscErrorCode MatCreateSeqDense(MPI_Comm comm, PetscInt m, PetscInt n, PetscScalar *data, Mat *A)
3303: {
3304: PetscFunctionBegin;
3305: PetscCall(MatCreate(comm, A));
3306: PetscCall(MatSetSizes(*A, m, n, m, n));
3307: PetscCall(MatSetType(*A, MATSEQDENSE));
3308: PetscCall(MatSeqDenseSetPreallocation(*A, data));
3309: PetscFunctionReturn(PETSC_SUCCESS);
3310: }
3312: /*@C
3313: MatSeqDenseSetPreallocation - Sets the array used for storing the matrix elements of a `MATSEQDENSE` matrix
3315: Collective
3317: Input Parameters:
3318: + B - the matrix
3319: - data - the array (or `NULL`)
3321: Level: intermediate
3323: Note:
3324: The data input variable is intended primarily for Fortran programmers
3325: who wish to allocate their own matrix memory space. Most users should
3326: need not call this routine.
3328: .seealso: [](ch_matrices), `Mat`, `MATSEQDENSE`, `MatCreate()`, `MatCreateDense()`, `MatSetValues()`, `MatDenseSetLDA()`
3329: @*/
3330: PetscErrorCode MatSeqDenseSetPreallocation(Mat B, PetscScalar data[])
3331: {
3332: PetscFunctionBegin;
3334: PetscTryMethod(B, "MatSeqDenseSetPreallocation_C", (Mat, PetscScalar[]), (B, data));
3335: PetscFunctionReturn(PETSC_SUCCESS);
3336: }
3338: PetscErrorCode MatSeqDenseSetPreallocation_SeqDense(Mat B, PetscScalar *data)
3339: {
3340: Mat_SeqDense *b = (Mat_SeqDense *)B->data;
3342: PetscFunctionBegin;
3343: PetscCheck(!b->matinuse, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Need to call MatDenseRestoreSubMatrix() first");
3344: B->preallocated = PETSC_TRUE;
3346: PetscCall(PetscLayoutSetUp(B->rmap));
3347: PetscCall(PetscLayoutSetUp(B->cmap));
3349: if (b->lda <= 0) b->lda = B->rmap->n;
3351: if (!data) { /* petsc-allocated storage */
3352: if (!b->user_alloc) PetscCall(PetscFree(b->v));
3353: PetscCall(PetscCalloc1((size_t)b->lda * B->cmap->n, &b->v));
3355: b->user_alloc = PETSC_FALSE;
3356: } else { /* user-allocated storage */
3357: if (!b->user_alloc) PetscCall(PetscFree(b->v));
3358: b->v = data;
3359: b->user_alloc = PETSC_TRUE;
3360: }
3361: B->assembled = PETSC_TRUE;
3362: PetscFunctionReturn(PETSC_SUCCESS);
3363: }
3365: #if defined(PETSC_HAVE_ELEMENTAL)
3366: PETSC_INTERN PetscErrorCode MatConvert_SeqDense_Elemental(Mat A, MatType newtype, MatReuse reuse, Mat *newmat)
3367: {
3368: Mat mat_elemental;
3369: const PetscScalar *array;
3370: PetscScalar *v_colwise;
3371: PetscInt M = A->rmap->N, N = A->cmap->N, i, j, k, *rows, *cols;
3373: PetscFunctionBegin;
3374: PetscCall(PetscMalloc3(M * N, &v_colwise, M, &rows, N, &cols));
3375: PetscCall(MatDenseGetArrayRead(A, &array));
3376: /* convert column-wise array into row-wise v_colwise, see MatSetValues_Elemental() */
3377: k = 0;
3378: for (j = 0; j < N; j++) {
3379: cols[j] = j;
3380: for (i = 0; i < M; i++) v_colwise[j * M + i] = array[k++];
3381: }
3382: for (i = 0; i < M; i++) rows[i] = i;
3383: PetscCall(MatDenseRestoreArrayRead(A, &array));
3385: PetscCall(MatCreate(PetscObjectComm((PetscObject)A), &mat_elemental));
3386: PetscCall(MatSetSizes(mat_elemental, PETSC_DECIDE, PETSC_DECIDE, M, N));
3387: PetscCall(MatSetType(mat_elemental, MATELEMENTAL));
3388: PetscCall(MatSetUp(mat_elemental));
3390: /* PETSc-Elemental interaface uses axpy for setting off-processor entries, only ADD_VALUES is allowed */
3391: PetscCall(MatSetValues(mat_elemental, M, rows, N, cols, v_colwise, ADD_VALUES));
3392: PetscCall(MatAssemblyBegin(mat_elemental, MAT_FINAL_ASSEMBLY));
3393: PetscCall(MatAssemblyEnd(mat_elemental, MAT_FINAL_ASSEMBLY));
3394: PetscCall(PetscFree3(v_colwise, rows, cols));
3396: if (reuse == MAT_INPLACE_MATRIX) {
3397: PetscCall(MatHeaderReplace(A, &mat_elemental));
3398: } else {
3399: *newmat = mat_elemental;
3400: }
3401: PetscFunctionReturn(PETSC_SUCCESS);
3402: }
3403: #endif
3405: PetscErrorCode MatDenseSetLDA_SeqDense(Mat B, PetscInt lda)
3406: {
3407: Mat_SeqDense *b = (Mat_SeqDense *)B->data;
3408: PetscBool data;
3410: PetscFunctionBegin;
3411: data = (PetscBool)((B->rmap->n > 0 && B->cmap->n > 0) ? (b->v ? PETSC_TRUE : PETSC_FALSE) : PETSC_FALSE);
3412: PetscCheck(b->user_alloc || !data || b->lda == lda, PETSC_COMM_SELF, PETSC_ERR_ORDER, "LDA cannot be changed after allocation of internal storage");
3413: 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);
3414: b->lda = lda;
3415: PetscFunctionReturn(PETSC_SUCCESS);
3416: }
3418: PetscErrorCode MatCreateMPIMatConcatenateSeqMat_SeqDense(MPI_Comm comm, Mat inmat, PetscInt n, MatReuse scall, Mat *outmat)
3419: {
3420: PetscFunctionBegin;
3421: PetscCall(MatCreateMPIMatConcatenateSeqMat_MPIDense(comm, inmat, n, scall, outmat));
3422: PetscFunctionReturn(PETSC_SUCCESS);
3423: }
3425: PetscErrorCode MatDenseCreateColumnVec_Private(Mat A, Vec *v)
3426: {
3427: PetscBool isstd, iskok, iscuda, iship;
3428: PetscMPIInt size;
3429: #if PetscDefined(HAVE_CUDA) || PetscDefined(HAVE_HIP)
3430: /* we pass the data of A, to prevent allocating needless GPU memory the first time VecCUPMPlaceArray is called. */
3431: const PetscScalar *a;
3432: #endif
3434: PetscFunctionBegin;
3435: *v = NULL;
3436: PetscCall(PetscStrcmpAny(A->defaultvectype, &isstd, VECSTANDARD, VECSEQ, VECMPI, ""));
3437: PetscCall(PetscStrcmpAny(A->defaultvectype, &iskok, VECKOKKOS, VECSEQKOKKOS, VECMPIKOKKOS, ""));
3438: PetscCall(PetscStrcmpAny(A->defaultvectype, &iscuda, VECCUDA, VECSEQCUDA, VECMPICUDA, ""));
3439: PetscCall(PetscStrcmpAny(A->defaultvectype, &iship, VECHIP, VECSEQHIP, VECMPIHIP, ""));
3440: PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)A), &size));
3441: if (isstd) {
3442: if (size > 1) PetscCall(VecCreateMPIWithArray(PetscObjectComm((PetscObject)A), A->rmap->bs, A->rmap->n, A->rmap->N, NULL, v));
3443: else PetscCall(VecCreateSeqWithArray(PetscObjectComm((PetscObject)A), A->rmap->bs, A->rmap->n, NULL, v));
3444: } else if (iskok) {
3445: PetscCheck(PetscDefined(HAVE_KOKKOS_KERNELS), PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Reconfigure using KOKKOS kernels support");
3446: #if PetscDefined(HAVE_KOKKOS_KERNELS)
3447: if (size > 1) PetscCall(VecCreateMPIKokkosWithArray(PetscObjectComm((PetscObject)A), A->rmap->bs, A->rmap->n, A->rmap->N, NULL, v));
3448: else PetscCall(VecCreateSeqKokkosWithArray(PetscObjectComm((PetscObject)A), A->rmap->bs, A->rmap->n, NULL, v));
3449: #endif
3450: } else if (iscuda) {
3451: PetscCheck(PetscDefined(HAVE_CUDA), PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Reconfigure using CUDA support");
3452: #if PetscDefined(HAVE_CUDA)
3453: PetscCall(MatDenseCUDAGetArrayRead(A, &a));
3454: if (size > 1) PetscCall(VecCreateMPICUDAWithArrays(PetscObjectComm((PetscObject)A), A->rmap->bs, A->rmap->n, A->rmap->N, NULL, a, v));
3455: else PetscCall(VecCreateSeqCUDAWithArrays(PetscObjectComm((PetscObject)A), A->rmap->bs, A->rmap->n, NULL, a, v));
3456: #endif
3457: } else if (iship) {
3458: PetscCheck(PetscDefined(HAVE_HIP), PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Reconfigure using HIP support");
3459: #if PetscDefined(HAVE_HIP)
3460: PetscCall(MatDenseHIPGetArrayRead(A, &a));
3461: if (size > 1) PetscCall(VecCreateMPIHIPWithArrays(PetscObjectComm((PetscObject)A), A->rmap->bs, A->rmap->n, A->rmap->N, NULL, a, v));
3462: else PetscCall(VecCreateSeqHIPWithArrays(PetscObjectComm((PetscObject)A), A->rmap->bs, A->rmap->n, NULL, a, v));
3463: #endif
3464: }
3465: PetscCheck(*v, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Not coded for type %s", A->defaultvectype);
3466: PetscFunctionReturn(PETSC_SUCCESS);
3467: }
3469: PetscErrorCode MatDenseGetColumnVec_SeqDense(Mat A, PetscInt col, Vec *v)
3470: {
3471: Mat_SeqDense *a = (Mat_SeqDense *)A->data;
3473: PetscFunctionBegin;
3474: PetscCheck(!a->vecinuse, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Need to call MatDenseRestoreColumnVec() first");
3475: PetscCheck(!a->matinuse, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Need to call MatDenseRestoreSubMatrix() first");
3476: if (!a->cvec) PetscCall(MatDenseCreateColumnVec_Private(A, &a->cvec));
3477: a->vecinuse = col + 1;
3478: PetscCall(MatDenseGetArray(A, (PetscScalar **)&a->ptrinuse));
3479: PetscCall(VecPlaceArray(a->cvec, a->ptrinuse + (size_t)col * (size_t)a->lda));
3480: *v = a->cvec;
3481: PetscFunctionReturn(PETSC_SUCCESS);
3482: }
3484: PetscErrorCode MatDenseRestoreColumnVec_SeqDense(Mat A, PetscInt col, Vec *v)
3485: {
3486: Mat_SeqDense *a = (Mat_SeqDense *)A->data;
3488: PetscFunctionBegin;
3489: PetscCheck(a->vecinuse, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Need to call MatDenseGetColumnVec() first");
3490: PetscCheck(a->cvec, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Missing internal column vector");
3491: VecCheckAssembled(a->cvec);
3492: a->vecinuse = 0;
3493: PetscCall(MatDenseRestoreArray(A, (PetscScalar **)&a->ptrinuse));
3494: PetscCall(VecResetArray(a->cvec));
3495: if (v) *v = NULL;
3496: PetscFunctionReturn(PETSC_SUCCESS);
3497: }
3499: PetscErrorCode MatDenseGetColumnVecRead_SeqDense(Mat A, PetscInt col, Vec *v)
3500: {
3501: Mat_SeqDense *a = (Mat_SeqDense *)A->data;
3503: PetscFunctionBegin;
3504: PetscCheck(!a->vecinuse, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Need to call MatDenseRestoreColumnVec() first");
3505: PetscCheck(!a->matinuse, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Need to call MatDenseRestoreSubMatrix() first");
3506: if (!a->cvec) PetscCall(MatDenseCreateColumnVec_Private(A, &a->cvec));
3507: a->vecinuse = col + 1;
3508: PetscCall(MatDenseGetArrayRead(A, &a->ptrinuse));
3509: PetscCall(VecPlaceArray(a->cvec, PetscSafePointerPlusOffset(a->ptrinuse, (size_t)col * (size_t)a->lda)));
3510: PetscCall(VecLockReadPush(a->cvec));
3511: *v = a->cvec;
3512: PetscFunctionReturn(PETSC_SUCCESS);
3513: }
3515: PetscErrorCode MatDenseRestoreColumnVecRead_SeqDense(Mat A, PetscInt col, Vec *v)
3516: {
3517: Mat_SeqDense *a = (Mat_SeqDense *)A->data;
3519: PetscFunctionBegin;
3520: PetscCheck(a->vecinuse, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Need to call MatDenseGetColumnVec() first");
3521: PetscCheck(a->cvec, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Missing internal column vector");
3522: VecCheckAssembled(a->cvec);
3523: a->vecinuse = 0;
3524: PetscCall(MatDenseRestoreArrayRead(A, &a->ptrinuse));
3525: PetscCall(VecLockReadPop(a->cvec));
3526: PetscCall(VecResetArray(a->cvec));
3527: if (v) *v = NULL;
3528: PetscFunctionReturn(PETSC_SUCCESS);
3529: }
3531: PetscErrorCode MatDenseGetColumnVecWrite_SeqDense(Mat A, PetscInt col, Vec *v)
3532: {
3533: Mat_SeqDense *a = (Mat_SeqDense *)A->data;
3535: PetscFunctionBegin;
3536: PetscCheck(!a->vecinuse, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Need to call MatDenseRestoreColumnVec() first");
3537: PetscCheck(!a->matinuse, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Need to call MatDenseRestoreSubMatrix() first");
3538: if (!a->cvec) PetscCall(MatDenseCreateColumnVec_Private(A, &a->cvec));
3539: a->vecinuse = col + 1;
3540: PetscCall(MatDenseGetArrayWrite(A, (PetscScalar **)&a->ptrinuse));
3541: PetscCall(VecPlaceArray(a->cvec, PetscSafePointerPlusOffset(a->ptrinuse, (size_t)col * (size_t)a->lda)));
3542: *v = a->cvec;
3543: PetscFunctionReturn(PETSC_SUCCESS);
3544: }
3546: PetscErrorCode MatDenseRestoreColumnVecWrite_SeqDense(Mat A, PetscInt col, Vec *v)
3547: {
3548: Mat_SeqDense *a = (Mat_SeqDense *)A->data;
3550: PetscFunctionBegin;
3551: PetscCheck(a->vecinuse, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Need to call MatDenseGetColumnVec() first");
3552: PetscCheck(a->cvec, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Missing internal column vector");
3553: VecCheckAssembled(a->cvec);
3554: a->vecinuse = 0;
3555: PetscCall(MatDenseRestoreArrayWrite(A, (PetscScalar **)&a->ptrinuse));
3556: PetscCall(VecResetArray(a->cvec));
3557: if (v) *v = NULL;
3558: PetscFunctionReturn(PETSC_SUCCESS);
3559: }
3561: PetscErrorCode MatDenseGetSubMatrix_SeqDense(Mat A, PetscInt rbegin, PetscInt rend, PetscInt cbegin, PetscInt cend, Mat *v)
3562: {
3563: Mat_SeqDense *a = (Mat_SeqDense *)A->data;
3565: PetscFunctionBegin;
3566: PetscCheck(!a->vecinuse, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Need to call MatDenseRestoreColumnVec() first");
3567: PetscCheck(!a->matinuse, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Need to call MatDenseRestoreSubMatrix() first");
3568: if (a->cmat && (cend - cbegin != a->cmat->cmap->N || rend - rbegin != a->cmat->rmap->N)) PetscCall(MatDestroy(&a->cmat));
3569: if (!a->cmat) {
3570: PetscCall(MatCreateDense(PetscObjectComm((PetscObject)A), rend - rbegin, PETSC_DECIDE, rend - rbegin, cend - cbegin, PetscSafePointerPlusOffset(a->v, rbegin + (size_t)cbegin * a->lda), &a->cmat));
3571: } else {
3572: PetscCall(MatDensePlaceArray(a->cmat, PetscSafePointerPlusOffset(a->v, rbegin + (size_t)cbegin * a->lda)));
3573: }
3574: PetscCall(MatDenseSetLDA(a->cmat, a->lda));
3575: a->matinuse = cbegin + 1;
3576: *v = a->cmat;
3577: #if defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
3578: A->offloadmask = PETSC_OFFLOAD_CPU;
3579: #endif
3580: PetscFunctionReturn(PETSC_SUCCESS);
3581: }
3583: PetscErrorCode MatDenseRestoreSubMatrix_SeqDense(Mat A, Mat *v)
3584: {
3585: Mat_SeqDense *a = (Mat_SeqDense *)A->data;
3587: PetscFunctionBegin;
3588: PetscCheck(a->matinuse, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Need to call MatDenseGetSubMatrix() first");
3589: PetscCheck(a->cmat, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Missing internal column matrix");
3590: PetscCheck(*v == a->cmat, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Not the matrix obtained from MatDenseGetSubMatrix()");
3591: a->matinuse = 0;
3592: PetscCall(MatDenseResetArray(a->cmat));
3593: if (v) *v = NULL;
3594: #if defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
3595: A->offloadmask = PETSC_OFFLOAD_CPU;
3596: #endif
3597: PetscFunctionReturn(PETSC_SUCCESS);
3598: }
3600: /*MC
3601: MATSEQDENSE - MATSEQDENSE = "seqdense" - A matrix type to be used for sequential dense matrices.
3603: Options Database Key:
3604: . -mat_type seqdense - sets the matrix type to `MATSEQDENSE` during a call to `MatSetFromOptions()`
3606: Level: beginner
3608: .seealso: [](ch_matrices), `Mat`, `MATSEQDENSE`, `MatCreateSeqDense()`
3609: M*/
3610: PetscErrorCode MatCreate_SeqDense(Mat B)
3611: {
3612: Mat_SeqDense *b;
3613: PetscMPIInt size;
3615: PetscFunctionBegin;
3616: PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)B), &size));
3617: PetscCheck(size <= 1, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Comm must be of size 1");
3619: PetscCall(PetscNew(&b));
3620: B->data = (void *)b;
3621: B->ops[0] = MatOps_Values;
3623: b->roworiented = PETSC_TRUE;
3625: PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatQRFactor_C", MatQRFactor_SeqDense));
3626: PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatDenseGetLDA_C", MatDenseGetLDA_SeqDense));
3627: PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatDenseSetLDA_C", MatDenseSetLDA_SeqDense));
3628: PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatDenseGetArray_C", MatDenseGetArray_SeqDense));
3629: PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatDenseRestoreArray_C", MatDenseRestoreArray_SeqDense));
3630: PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatDensePlaceArray_C", MatDensePlaceArray_SeqDense));
3631: PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatDenseResetArray_C", MatDenseResetArray_SeqDense));
3632: PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatDenseReplaceArray_C", MatDenseReplaceArray_SeqDense));
3633: PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatDenseGetArrayRead_C", MatDenseGetArray_SeqDense));
3634: PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatDenseRestoreArrayRead_C", MatDenseRestoreArray_SeqDense));
3635: PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatDenseGetArrayWrite_C", MatDenseGetArray_SeqDense));
3636: PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatDenseRestoreArrayWrite_C", MatDenseRestoreArray_SeqDense));
3637: PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatConvert_seqdense_seqaij_C", MatConvert_SeqDense_SeqAIJ));
3638: #if defined(PETSC_HAVE_ELEMENTAL)
3639: PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatConvert_seqdense_elemental_C", MatConvert_SeqDense_Elemental));
3640: #endif
3641: #if defined(PETSC_HAVE_SCALAPACK)
3642: PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatConvert_seqdense_scalapack_C", MatConvert_Dense_ScaLAPACK));
3643: #endif
3644: #if defined(PETSC_HAVE_CUDA)
3645: PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatConvert_seqdense_seqdensecuda_C", MatConvert_SeqDense_SeqDenseCUDA));
3646: PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatProductSetFromOptions_seqdensecuda_seqdensecuda_C", MatProductSetFromOptions_SeqDense));
3647: PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatProductSetFromOptions_seqdensecuda_seqdense_C", MatProductSetFromOptions_SeqDense));
3648: PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatProductSetFromOptions_seqdense_seqdensecuda_C", MatProductSetFromOptions_SeqDense));
3649: #endif
3650: #if defined(PETSC_HAVE_HIP)
3651: PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatConvert_seqdense_seqdensehip_C", MatConvert_SeqDense_SeqDenseHIP));
3652: PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatProductSetFromOptions_seqdensehip_seqdensehip_C", MatProductSetFromOptions_SeqDense));
3653: PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatProductSetFromOptions_seqdensehip_seqdense_C", MatProductSetFromOptions_SeqDense));
3654: PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatProductSetFromOptions_seqdense_seqdensehip_C", MatProductSetFromOptions_SeqDense));
3655: #endif
3656: PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatSeqDenseSetPreallocation_C", MatSeqDenseSetPreallocation_SeqDense));
3657: PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatProductSetFromOptions_seqaij_seqdense_C", MatProductSetFromOptions_SeqAIJ_SeqDense));
3658: PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatProductSetFromOptions_seqdense_seqdense_C", MatProductSetFromOptions_SeqDense));
3659: PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatProductSetFromOptions_seqbaij_seqdense_C", MatProductSetFromOptions_SeqXBAIJ_SeqDense));
3660: PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatProductSetFromOptions_seqsbaij_seqdense_C", MatProductSetFromOptions_SeqXBAIJ_SeqDense));
3662: PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatDenseGetColumn_C", MatDenseGetColumn_SeqDense));
3663: PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatDenseRestoreColumn_C", MatDenseRestoreColumn_SeqDense));
3664: PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatDenseGetColumnVec_C", MatDenseGetColumnVec_SeqDense));
3665: PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatDenseRestoreColumnVec_C", MatDenseRestoreColumnVec_SeqDense));
3666: PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatDenseGetColumnVecRead_C", MatDenseGetColumnVecRead_SeqDense));
3667: PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatDenseRestoreColumnVecRead_C", MatDenseRestoreColumnVecRead_SeqDense));
3668: PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatDenseGetColumnVecWrite_C", MatDenseGetColumnVecWrite_SeqDense));
3669: PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatDenseRestoreColumnVecWrite_C", MatDenseRestoreColumnVecWrite_SeqDense));
3670: PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatDenseGetSubMatrix_C", MatDenseGetSubMatrix_SeqDense));
3671: PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatDenseRestoreSubMatrix_C", MatDenseRestoreSubMatrix_SeqDense));
3672: PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatMultAddColumnRange_C", MatMultAddColumnRange_SeqDense));
3673: PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatMultHermitianTransposeColumnRange_C", MatMultHermitianTransposeColumnRange_SeqDense));
3674: PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatMultHermitianTransposeAddColumnRange_C", MatMultHermitianTransposeAddColumnRange_SeqDense));
3675: PetscCall(PetscObjectChangeTypeName((PetscObject)B, MATSEQDENSE));
3676: PetscFunctionReturn(PETSC_SUCCESS);
3677: }
3679: /*@C
3680: 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.
3682: Not Collective
3684: Input Parameters:
3685: + A - a `MATSEQDENSE` or `MATMPIDENSE` matrix
3686: - col - column index
3688: Output Parameter:
3689: . vals - pointer to the data
3691: Level: intermediate
3693: Note:
3694: Use `MatDenseGetColumnVec()` to get access to a column of a `MATDENSE` treated as a `Vec`
3696: .seealso: [](ch_matrices), `Mat`, `MATDENSE`, `MatDenseRestoreColumn()`, `MatDenseGetColumnVec()`
3697: @*/
3698: PetscErrorCode MatDenseGetColumn(Mat A, PetscInt col, PetscScalar **vals)
3699: {
3700: PetscFunctionBegin;
3703: PetscAssertPointer(vals, 3);
3704: PetscUseMethod(A, "MatDenseGetColumn_C", (Mat, PetscInt, PetscScalar **), (A, col, vals));
3705: PetscFunctionReturn(PETSC_SUCCESS);
3706: }
3708: /*@C
3709: MatDenseRestoreColumn - returns access to a column of a `MATDENSE` matrix which is returned by `MatDenseGetColumn()`.
3711: Not Collective
3713: Input Parameters:
3714: + A - a `MATSEQDENSE` or `MATMPIDENSE` matrix
3715: - vals - pointer to the data (may be `NULL`)
3717: Level: intermediate
3719: .seealso: [](ch_matrices), `Mat`, `MATDENSE`, `MatDenseGetColumn()`
3720: @*/
3721: PetscErrorCode MatDenseRestoreColumn(Mat A, PetscScalar **vals)
3722: {
3723: PetscFunctionBegin;
3725: PetscAssertPointer(vals, 2);
3726: PetscUseMethod(A, "MatDenseRestoreColumn_C", (Mat, PetscScalar **), (A, vals));
3727: PetscFunctionReturn(PETSC_SUCCESS);
3728: }
3730: /*@
3731: MatDenseGetColumnVec - Gives read-write access to a column of a `MATDENSE` matrix, represented as a `Vec`.
3733: Collective
3735: Input Parameters:
3736: + A - the `Mat` object
3737: - col - the column index
3739: Output Parameter:
3740: . v - the vector
3742: Level: intermediate
3744: Notes:
3745: The vector is owned by PETSc. Users need to call `MatDenseRestoreColumnVec()` when the vector is no longer needed.
3747: Use `MatDenseGetColumnVecRead()` to obtain read-only access or `MatDenseGetColumnVecWrite()` for write-only access.
3749: .seealso: [](ch_matrices), `Mat`, `MATDENSE`, `MATDENSECUDA`, `MATDENSEHIP`, `MatDenseGetColumnVecRead()`, `MatDenseGetColumnVecWrite()`, `MatDenseRestoreColumnVec()`, `MatDenseRestoreColumnVecRead()`, `MatDenseRestoreColumnVecWrite()`, `MatDenseGetColumn()`
3750: @*/
3751: PetscErrorCode MatDenseGetColumnVec(Mat A, PetscInt col, Vec *v)
3752: {
3753: PetscFunctionBegin;
3757: PetscAssertPointer(v, 3);
3758: PetscCheck(A->preallocated, PetscObjectComm((PetscObject)A), PETSC_ERR_ORDER, "Matrix not preallocated");
3759: 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);
3760: PetscUseMethod(A, "MatDenseGetColumnVec_C", (Mat, PetscInt, Vec *), (A, col, v));
3761: PetscFunctionReturn(PETSC_SUCCESS);
3762: }
3764: /*@
3765: MatDenseRestoreColumnVec - Returns access to a column of a dense matrix obtained from `MatDenseGetColumnVec()`.
3767: Collective
3769: Input Parameters:
3770: + A - the `Mat` object
3771: . col - the column index
3772: - v - the `Vec` object (may be `NULL`)
3774: Level: intermediate
3776: .seealso: [](ch_matrices), `Mat`, `MATDENSE`, `MATDENSECUDA`, `MATDENSEHIP`, `MatDenseGetColumnVec()`, `MatDenseGetColumnVecRead()`, `MatDenseGetColumnVecWrite()`, `MatDenseRestoreColumnVecRead()`, `MatDenseRestoreColumnVecWrite()`
3777: @*/
3778: PetscErrorCode MatDenseRestoreColumnVec(Mat A, PetscInt col, Vec *v)
3779: {
3780: PetscFunctionBegin;
3784: PetscCheck(A->preallocated, PetscObjectComm((PetscObject)A), PETSC_ERR_ORDER, "Matrix not preallocated");
3785: 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);
3786: PetscUseMethod(A, "MatDenseRestoreColumnVec_C", (Mat, PetscInt, Vec *), (A, col, v));
3787: PetscFunctionReturn(PETSC_SUCCESS);
3788: }
3790: /*@
3791: MatDenseGetColumnVecRead - Gives read-only access to a column of a dense matrix, represented as a `Vec`.
3793: Collective
3795: Input Parameters:
3796: + A - the `Mat` object
3797: - col - the column index
3799: Output Parameter:
3800: . v - the vector
3802: Level: intermediate
3804: Notes:
3805: The vector is owned by PETSc and users cannot modify it.
3807: Users need to call `MatDenseRestoreColumnVecRead()` when the vector is no longer needed.
3809: Use `MatDenseGetColumnVec()` to obtain read-write access or `MatDenseGetColumnVecWrite()` for write-only access.
3811: .seealso: [](ch_matrices), `Mat`, `MATDENSE`, `MATDENSECUDA`, `MATDENSEHIP`, `MatDenseGetColumnVec()`, `MatDenseGetColumnVecWrite()`, `MatDenseRestoreColumnVec()`, `MatDenseRestoreColumnVecRead()`, `MatDenseRestoreColumnVecWrite()`
3812: @*/
3813: PetscErrorCode MatDenseGetColumnVecRead(Mat A, PetscInt col, Vec *v)
3814: {
3815: PetscFunctionBegin;
3819: PetscAssertPointer(v, 3);
3820: PetscCheck(A->preallocated, PetscObjectComm((PetscObject)A), PETSC_ERR_ORDER, "Matrix not preallocated");
3821: 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);
3822: PetscUseMethod(A, "MatDenseGetColumnVecRead_C", (Mat, PetscInt, Vec *), (A, col, v));
3823: PetscFunctionReturn(PETSC_SUCCESS);
3824: }
3826: /*@
3827: MatDenseRestoreColumnVecRead - Returns access to a column of a dense matrix obtained from `MatDenseGetColumnVecRead()`.
3829: Collective
3831: Input Parameters:
3832: + A - the `Mat` object
3833: . col - the column index
3834: - v - the `Vec` object (may be `NULL`)
3836: Level: intermediate
3838: .seealso: [](ch_matrices), `Mat`, `MATDENSE`, `MATDENSECUDA`, `MATDENSEHIP`, `MatDenseGetColumnVec()`, `MatDenseGetColumnVecRead()`, `MatDenseGetColumnVecWrite()`, `MatDenseRestoreColumnVec()`, `MatDenseRestoreColumnVecWrite()`
3839: @*/
3840: PetscErrorCode MatDenseRestoreColumnVecRead(Mat A, PetscInt col, Vec *v)
3841: {
3842: PetscFunctionBegin;
3846: PetscCheck(A->preallocated, PetscObjectComm((PetscObject)A), PETSC_ERR_ORDER, "Matrix not preallocated");
3847: 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);
3848: PetscUseMethod(A, "MatDenseRestoreColumnVecRead_C", (Mat, PetscInt, Vec *), (A, col, v));
3849: PetscFunctionReturn(PETSC_SUCCESS);
3850: }
3852: /*@
3853: MatDenseGetColumnVecWrite - Gives write-only access to a column of a dense matrix, represented as a `Vec`.
3855: Collective
3857: Input Parameters:
3858: + A - the `Mat` object
3859: - col - the column index
3861: Output Parameter:
3862: . v - the vector
3864: Level: intermediate
3866: Notes:
3867: The vector is owned by PETSc. Users need to call `MatDenseRestoreColumnVecWrite()` when the vector is no longer needed.
3869: Use `MatDenseGetColumnVec()` to obtain read-write access or `MatDenseGetColumnVecRead()` for read-only access.
3871: .seealso: [](ch_matrices), `Mat`, `MATDENSE`, `MATDENSECUDA`, `MATDENSEHIP`, `MatDenseGetColumnVec()`, `MatDenseGetColumnVecRead()`, `MatDenseRestoreColumnVec()`, `MatDenseRestoreColumnVecRead()`, `MatDenseRestoreColumnVecWrite()`
3872: @*/
3873: PetscErrorCode MatDenseGetColumnVecWrite(Mat A, PetscInt col, Vec *v)
3874: {
3875: PetscFunctionBegin;
3879: PetscAssertPointer(v, 3);
3880: PetscCheck(A->preallocated, PetscObjectComm((PetscObject)A), PETSC_ERR_ORDER, "Matrix not preallocated");
3881: 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);
3882: PetscUseMethod(A, "MatDenseGetColumnVecWrite_C", (Mat, PetscInt, Vec *), (A, col, v));
3883: PetscFunctionReturn(PETSC_SUCCESS);
3884: }
3886: /*@
3887: MatDenseRestoreColumnVecWrite - Returns access to a column of a dense matrix obtained from `MatDenseGetColumnVecWrite()`.
3889: Collective
3891: Input Parameters:
3892: + A - the `Mat` object
3893: . col - the column index
3894: - v - the `Vec` object (may be `NULL`)
3896: Level: intermediate
3898: .seealso: [](ch_matrices), `Mat`, `MATDENSE`, `MATDENSECUDA`, `MATDENSEHIP`, `MatDenseGetColumnVec()`, `MatDenseGetColumnVecRead()`, `MatDenseGetColumnVecWrite()`, `MatDenseRestoreColumnVec()`, `MatDenseRestoreColumnVecRead()`
3899: @*/
3900: PetscErrorCode MatDenseRestoreColumnVecWrite(Mat A, PetscInt col, Vec *v)
3901: {
3902: PetscFunctionBegin;
3906: PetscCheck(A->preallocated, PetscObjectComm((PetscObject)A), PETSC_ERR_ORDER, "Matrix not preallocated");
3907: 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);
3908: PetscUseMethod(A, "MatDenseRestoreColumnVecWrite_C", (Mat, PetscInt, Vec *), (A, col, v));
3909: PetscFunctionReturn(PETSC_SUCCESS);
3910: }
3912: /*@
3913: MatDenseGetSubMatrix - Gives access to a block of rows and columns of a dense matrix, represented as a `Mat`.
3915: Collective
3917: Input Parameters:
3918: + A - the `Mat` object
3919: . rbegin - the first global row index in the block (if `PETSC_DECIDE`, is 0)
3920: . rend - the global row index past the last one in the block (if `PETSC_DECIDE`, is `M`)
3921: . cbegin - the first global column index in the block (if `PETSC_DECIDE`, is 0)
3922: - cend - the global column index past the last one in the block (if `PETSC_DECIDE`, is `N`)
3924: Output Parameter:
3925: . v - the matrix
3927: Level: intermediate
3929: Notes:
3930: The matrix is owned by PETSc. Users need to call `MatDenseRestoreSubMatrix()` when the matrix is no longer needed.
3932: The output matrix is not redistributed by PETSc, so depending on the values of `rbegin` and `rend`, some processes may have no local rows.
3934: .seealso: [](ch_matrices), `Mat`, `MATDENSE`, `MATDENSECUDA`, `MATDENSEHIP`, `MatDenseGetColumnVec()`, `MatDenseRestoreColumnVec()`, `MatDenseRestoreSubMatrix()`
3935: @*/
3936: PetscErrorCode MatDenseGetSubMatrix(Mat A, PetscInt rbegin, PetscInt rend, PetscInt cbegin, PetscInt cend, Mat *v)
3937: {
3938: PetscFunctionBegin;
3945: PetscAssertPointer(v, 6);
3946: if (rbegin == PETSC_DECIDE) rbegin = 0;
3947: if (rend == PETSC_DECIDE) rend = A->rmap->N;
3948: if (cbegin == PETSC_DECIDE) cbegin = 0;
3949: if (cend == PETSC_DECIDE) cend = A->cmap->N;
3950: PetscCheck(A->preallocated, PetscObjectComm((PetscObject)A), PETSC_ERR_ORDER, "Matrix not preallocated");
3951: 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);
3952: 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);
3953: 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);
3954: 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);
3955: PetscUseMethod(A, "MatDenseGetSubMatrix_C", (Mat, PetscInt, PetscInt, PetscInt, PetscInt, Mat *), (A, rbegin, rend, cbegin, cend, v));
3956: PetscFunctionReturn(PETSC_SUCCESS);
3957: }
3959: /*@
3960: MatDenseRestoreSubMatrix - Returns access to a block of columns of a dense matrix obtained from `MatDenseGetSubMatrix()`.
3962: Collective
3964: Input Parameters:
3965: + A - the `Mat` object
3966: - v - the `Mat` object (may be `NULL`)
3968: Level: intermediate
3970: .seealso: [](ch_matrices), `Mat`, `MATDENSE`, `MATDENSECUDA`, `MATDENSEHIP`, `MatDenseGetColumnVec()`, `MatDenseRestoreColumnVec()`, `MatDenseGetSubMatrix()`
3971: @*/
3972: PetscErrorCode MatDenseRestoreSubMatrix(Mat A, Mat *v)
3973: {
3974: PetscFunctionBegin;
3977: PetscAssertPointer(v, 2);
3978: PetscUseMethod(A, "MatDenseRestoreSubMatrix_C", (Mat, Mat *), (A, v));
3979: PetscFunctionReturn(PETSC_SUCCESS);
3980: }
3982: #include <petscblaslapack.h>
3983: #include <petsc/private/kernels/blockinvert.h>
3985: PetscErrorCode MatSeqDenseInvert(Mat A)
3986: {
3987: PetscInt m;
3988: const PetscReal shift = 0.0;
3989: PetscBool allowzeropivot, zeropivotdetected = PETSC_FALSE;
3990: PetscScalar *values;
3992: PetscFunctionBegin;
3994: PetscCall(MatDenseGetArray(A, &values));
3995: PetscCall(MatGetLocalSize(A, &m, NULL));
3996: allowzeropivot = PetscNot(A->erroriffailure);
3997: /* factor and invert each block */
3998: switch (m) {
3999: case 1:
4000: values[0] = (PetscScalar)1.0 / (values[0] + shift);
4001: break;
4002: case 2:
4003: PetscCall(PetscKernel_A_gets_inverse_A_2(values, shift, allowzeropivot, &zeropivotdetected));
4004: if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
4005: break;
4006: case 3:
4007: PetscCall(PetscKernel_A_gets_inverse_A_3(values, shift, allowzeropivot, &zeropivotdetected));
4008: if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
4009: break;
4010: case 4:
4011: PetscCall(PetscKernel_A_gets_inverse_A_4(values, shift, allowzeropivot, &zeropivotdetected));
4012: if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
4013: break;
4014: case 5: {
4015: PetscScalar work[25];
4016: PetscInt ipvt[5];
4018: PetscCall(PetscKernel_A_gets_inverse_A_5(values, ipvt, work, shift, allowzeropivot, &zeropivotdetected));
4019: if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
4020: } break;
4021: case 6:
4022: PetscCall(PetscKernel_A_gets_inverse_A_6(values, shift, allowzeropivot, &zeropivotdetected));
4023: if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
4024: break;
4025: case 7:
4026: PetscCall(PetscKernel_A_gets_inverse_A_7(values, shift, allowzeropivot, &zeropivotdetected));
4027: if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
4028: break;
4029: default: {
4030: PetscInt *v_pivots, *IJ, j;
4031: PetscScalar *v_work;
4033: PetscCall(PetscMalloc3(m, &v_work, m, &v_pivots, m, &IJ));
4034: for (j = 0; j < m; j++) IJ[j] = j;
4035: PetscCall(PetscKernel_A_gets_inverse_A(m, values, v_pivots, v_work, allowzeropivot, &zeropivotdetected));
4036: if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
4037: PetscCall(PetscFree3(v_work, v_pivots, IJ));
4038: }
4039: }
4040: PetscCall(MatDenseRestoreArray(A, &values));
4041: PetscFunctionReturn(PETSC_SUCCESS);
4042: }