Actual source code: ex318.c

  1: static const char help[] = "Tests MatDenseGetColumnVec() and friends on dense matrices created from a VecType, including device dense matrices whose vectors are VECKOKKOS\n\n";

  3: #include <petscmat.h>

  5: int main(int argc, char **argv)
  6: {
  7:   Mat                A;
  8:   Vec                v;
  9:   char               vtype[64] = VECSTANDARD;
 10:   PetscInt           M = 9, N = 3, lda, rstart, rend, i, j;
 11:   PetscReal          norm;
 12:   PetscScalar        sum;
 13:   const PetscScalar *array;

 15:   PetscFunctionBeginUser;
 16:   PetscCall(PetscInitialize(&argc, &argv, NULL, help));
 17:   PetscCall(PetscOptionsGetString(NULL, NULL, "-vec_type", vtype, sizeof(vtype), NULL));
 18:   /* A VECKOKKOS type gives a MATDENSECUDA/MATDENSEHIP with VECKOKKOS vectors when the Kokkos backend runs on that device */
 19:   PetscCall(MatCreateDenseFromVecType(PETSC_COMM_WORLD, vtype, PETSC_DECIDE, PETSC_DECIDE, M, N, PETSC_DECIDE, NULL, &A));
 20:   PetscCall(MatGetOwnershipRange(A, &rstart, &rend));

 22:   /* Write column j through its column vector, then scale it through a read/write column vector: A(:, j) = 2 (j + 1) */
 23:   for (j = 0; j < N; j++) {
 24:     PetscCall(MatDenseGetColumnVecWrite(A, j, &v));
 25:     PetscCall(VecSet(v, (PetscScalar)(j + 1)));
 26:     PetscCall(MatDenseRestoreColumnVecWrite(A, j, &v));
 27:   }
 28:   for (j = 0; j < N; j++) {
 29:     PetscCall(MatDenseGetColumnVec(A, j, &v));
 30:     PetscCall(VecScale(v, 2.0));
 31:     PetscCall(MatDenseRestoreColumnVec(A, j, &v));
 32:   }

 34:   /* Check through read-only column vectors, and independently through the matrix itself */
 35:   for (j = 0; j < N; j++) {
 36:     PetscCall(MatDenseGetColumnVecRead(A, j, &v));
 37:     PetscCall(VecSum(v, &sum));
 38:     PetscCheck(PetscAbsScalar(sum - 2.0 * (j + 1) * M) < PETSC_SMALL, PETSC_COMM_WORLD, PETSC_ERR_PLIB, "Column %" PetscInt_FMT " read back through MatDenseGetColumnVecRead() sums to %g, expected %g", j, (double)PetscRealPart(sum), 2.0 * (j + 1) * M);
 39:     PetscCall(MatDenseRestoreColumnVecRead(A, j, &v));
 40:   }
 41:   PetscCall(MatNorm(A, NORM_INFINITY, &norm));
 42:   PetscCheck(PetscAbsReal(norm - N * (N + 1)) < PETSC_SMALL, PETSC_COMM_WORLD, PETSC_ERR_PLIB, "MatNorm() gives %g, expected %g", (double)norm, (double)(N * (N + 1)));
 43:   PetscCall(MatDenseGetLDA(A, &lda));
 44:   PetscCall(MatDenseGetArrayRead(A, &array));
 45:   for (j = 0; j < N; j++) {
 46:     for (i = 0; i < rend - rstart; i++)
 47:       PetscCheck(array[i + j * lda] == 2.0 * (j + 1), PETSC_COMM_WORLD, PETSC_ERR_PLIB, "Entry (%" PetscInt_FMT ", %" PetscInt_FMT ") is %g, expected %g", rstart + i, j, (double)PetscRealPart(array[i + j * lda]), 2.0 * (j + 1));
 48:   }
 49:   PetscCall(MatDenseRestoreArrayRead(A, &array));

 51:   PetscCall(MatDestroy(&A));
 52:   PetscCall(PetscFinalize());
 53:   return 0;
 54: }

 56: /*TEST

 58:   testset:
 59:     output_file: output/empty.out
 60:     nsize: {{1 2}}
 61:     test:
 62:       suffix: standard
 63:       args: -vec_type standard
 64:     test:
 65:       suffix: cuda
 66:       requires: cuda
 67:       args: -vec_type cuda
 68:     test:
 69:       suffix: hip
 70:       requires: hip
 71:       args: -vec_type hip
 72:     # On a CUDA or HIP build this is a MATDENSECUDA or MATDENSEHIP with VECKOKKOS column vectors
 73:     test:
 74:       suffix: kokkos
 75:       requires: kokkos_kernels !sycl
 76:       args: -vec_type kokkos

 78: TEST*/