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