static char help[] = "Test ViennaCL Matrix Conversions"; #include int main(int argc, char **args) { PetscMPIInt rank, size; PetscFunctionBeginUser; PetscCall(PetscInitialize(&argc, &args, NULL, help)); PetscCallMPI(MPI_Comm_rank(PETSC_COMM_WORLD, &rank)); PetscCallMPI(MPI_Comm_size(PETSC_COMM_WORLD, &size)); /* Construct a sequential ViennaCL matrix and vector */ if (rank == 0) { Mat A_vcl; Vec v_vcl, r_vcl; PetscInt n = 17, m = 31, nz = 5, i, cnt, j; const PetscScalar val = 1.0; PetscCall(MatCreateSeqAIJViennaCL(PETSC_COMM_SELF, m, n, nz, NULL, &A_vcl)); /* Add nz arbitrary entries per row in arbitrary columns */ for (i = 0; i < m; ++i) { for (cnt = 0; cnt < nz; ++cnt) { j = (19 * cnt + (7 * i + 3)) % n; PetscCall(MatSetValue(A_vcl, i, j, (PetscScalar)(0.3 * i + j), INSERT_VALUES)); } } PetscCall(MatAssemblyBegin(A_vcl, MAT_FINAL_ASSEMBLY)); PetscCall(MatAssemblyEnd(A_vcl, MAT_FINAL_ASSEMBLY)); PetscCall(VecCreateSeqViennaCL(PETSC_COMM_SELF, n, &v_vcl)); PetscCall(VecCreateSeqViennaCL(PETSC_COMM_SELF, m, &r_vcl)); PetscCall(VecSet(v_vcl, val)); PetscCall(MatMult(A_vcl, v_vcl, r_vcl)); PetscCall(VecDestroy(&v_vcl)); PetscCall(VecDestroy(&r_vcl)); PetscCall(MatDestroy(&A_vcl)); } /* Create a sequential AIJ matrix on rank 0 convert it to a new ViennaCL matrix, and apply it to a ViennaCL vector */ if (rank == 0) { Mat A, A_vcl; Vec v, r, v_vcl, r_vcl, d_vcl; PetscInt n = 17, m = 31, nz = 5, i, cnt, j; const PetscScalar val = 1.0; PetscReal dnorm; const PetscReal tol = 1e-5; PetscCall(MatCreateSeqAIJ(PETSC_COMM_SELF, m, n, nz, NULL, &A)); /* Add nz arbitrary entries per row in arbitrary columns */ for (i = 0; i < m; ++i) { for (cnt = 0; cnt < nz; ++cnt) { j = (19 * cnt + (7 * i + 3)) % n; PetscCall(MatSetValue(A, i, j, (PetscScalar)(0.3 * i + j), INSERT_VALUES)); } } PetscCall(MatAssemblyBegin(A, MAT_FINAL_ASSEMBLY)); PetscCall(MatAssemblyEnd(A, MAT_FINAL_ASSEMBLY)); PetscCall(PetscObjectSetName((PetscObject)A, "Sequential CPU Matrix")); PetscCall(VecCreateSeq(PETSC_COMM_SELF, n, &v)); PetscCall(VecCreateSeq(PETSC_COMM_SELF, m, &r)); PetscCall(PetscObjectSetName((PetscObject)r, "CPU result vector")); PetscCall(VecSet(v, val)); PetscCall(MatMult(A, v, r)); PetscCall(MatConvert(A, MATSEQAIJVIENNACL, MAT_INITIAL_MATRIX, &A_vcl)); PetscCall(PetscObjectSetName((PetscObject)A_vcl, "New ViennaCL Matrix")); PetscCall(VecCreateSeqViennaCL(PETSC_COMM_SELF, n, &v_vcl)); PetscCall(VecCreateSeqViennaCL(PETSC_COMM_SELF, m, &r_vcl)); PetscCall(PetscObjectSetName((PetscObject)r_vcl, "ViennaCL result vector")); PetscCall(VecSet(v_vcl, val)); PetscCall(MatMult(A_vcl, v_vcl, r_vcl)); PetscCall(VecDuplicate(r_vcl, &d_vcl)); PetscCall(VecCopy(r_vcl, d_vcl)); PetscCall(VecAXPY(d_vcl, -1.0, r_vcl)); PetscCall(VecNorm(d_vcl, NORM_INFINITY, &dnorm)); PetscCheck(dnorm <= tol, PETSC_COMM_WORLD, PETSC_ERR_ARG_INCOMP, "Sequential CPU and MPI ViennaCL vector results incompatible with inf norm greater than tolerance of %g", tol); PetscCall(VecDestroy(&v)); PetscCall(VecDestroy(&r)); PetscCall(VecDestroy(&v_vcl)); PetscCall(VecDestroy(&r_vcl)); PetscCall(VecDestroy(&d_vcl)); PetscCall(MatDestroy(&A)); PetscCall(MatDestroy(&A_vcl)); } /* Create a sequential AIJ matrix on rank 0 convert it inplace to a new ViennaCL matrix, and apply it to a ViennaCL vector */ if (rank == 0) { Mat A; Vec v, r, v_vcl, r_vcl, d_vcl; PetscInt n = 17, m = 31, nz = 5, i, cnt, j; const PetscScalar val = 1.0; PetscReal dnorm; const PetscReal tol = 1e-5; PetscCall(MatCreateSeqAIJ(PETSC_COMM_SELF, m, n, nz, NULL, &A)); /* Add nz arbitrary entries per row in arbitrary columns */ for (i = 0; i < m; ++i) { for (cnt = 0; cnt < nz; ++cnt) { j = (19 * cnt + (7 * i + 3)) % n; PetscCall(MatSetValue(A, i, j, (PetscScalar)(0.3 * i + j), INSERT_VALUES)); } } PetscCall(MatAssemblyBegin(A, MAT_FINAL_ASSEMBLY)); PetscCall(MatAssemblyEnd(A, MAT_FINAL_ASSEMBLY)); PetscCall(PetscObjectSetName((PetscObject)A, "Sequential CPU Matrix")); PetscCall(VecCreateSeq(PETSC_COMM_SELF, n, &v)); PetscCall(VecCreateSeq(PETSC_COMM_SELF, m, &r)); PetscCall(PetscObjectSetName((PetscObject)r, "CPU result vector")); PetscCall(VecSet(v, val)); PetscCall(MatMult(A, v, r)); PetscCall(MatConvert(A, MATSEQAIJVIENNACL, MAT_INPLACE_MATRIX, &A)); PetscCall(PetscObjectSetName((PetscObject)A, "Converted ViennaCL Matrix")); PetscCall(VecCreateSeqViennaCL(PETSC_COMM_SELF, n, &v_vcl)); PetscCall(VecCreateSeqViennaCL(PETSC_COMM_SELF, m, &r_vcl)); PetscCall(PetscObjectSetName((PetscObject)r_vcl, "ViennaCL result vector")); PetscCall(VecSet(v_vcl, val)); PetscCall(MatMult(A, v_vcl, r_vcl)); PetscCall(VecDuplicate(r_vcl, &d_vcl)); PetscCall(VecCopy(r_vcl, d_vcl)); PetscCall(VecAXPY(d_vcl, -1.0, r_vcl)); PetscCall(VecNorm(d_vcl, NORM_INFINITY, &dnorm)); PetscCheck(dnorm <= tol, PETSC_COMM_WORLD, PETSC_ERR_ARG_INCOMP, "MPI CPU and MPI ViennaCL Vector results incompatible with inf norm greater than tolerance of %g", tol); PetscCall(VecDestroy(&v)); PetscCall(VecDestroy(&r)); PetscCall(VecDestroy(&v_vcl)); PetscCall(VecDestroy(&r_vcl)); PetscCall(VecDestroy(&d_vcl)); PetscCall(MatDestroy(&A)); } /* Create a parallel AIJ matrix, convert it to a new ViennaCL matrix, and apply it to a ViennaCL vector */ if (size > 1) { Mat A, A_vcl; Vec v, r, v_vcl, r_vcl, d_vcl; PetscInt N = 17, M = 31, nz = 5, i, cnt, j, rlow, rhigh; const PetscScalar val = 1.0; PetscReal dnorm; const PetscReal tol = 1e-5; PetscCall(MatCreateAIJ(PETSC_COMM_WORLD, PETSC_DETERMINE, PETSC_DETERMINE, M, N, nz, NULL, nz, NULL, &A)); /* Add nz arbitrary entries per row in arbitrary columns */ PetscCall(MatGetOwnershipRange(A, &rlow, &rhigh)); for (i = rlow; i < rhigh; ++i) { for (cnt = 0; cnt < nz; ++cnt) { j = (19 * cnt + (7 * i + 3)) % N; PetscCall(MatSetValue(A, i, j, (PetscScalar)(0.3 * i + j), INSERT_VALUES)); } } PetscCall(MatAssemblyBegin(A, MAT_FINAL_ASSEMBLY)); PetscCall(MatAssemblyEnd(A, MAT_FINAL_ASSEMBLY)); PetscCall(PetscObjectSetName((PetscObject)A, "MPI CPU Matrix")); PetscCall(MatCreateVecs(A, &v, &r)); PetscCall(PetscObjectSetName((PetscObject)r, "MPI CPU result vector")); PetscCall(VecSet(v, val)); PetscCall(MatMult(A, v, r)); PetscCall(MatConvert(A, MATMPIAIJVIENNACL, MAT_INITIAL_MATRIX, &A_vcl)); PetscCall(PetscObjectSetName((PetscObject)A_vcl, "New MPI ViennaCL Matrix")); PetscCall(MatCreateVecs(A_vcl, &v_vcl, &r_vcl)); PetscCall(PetscObjectSetName((PetscObject)r_vcl, "ViennaCL result vector")); PetscCall(VecSet(v_vcl, val)); PetscCall(MatMult(A_vcl, v_vcl, r_vcl)); PetscCall(VecDuplicate(r_vcl, &d_vcl)); PetscCall(VecCopy(r_vcl, d_vcl)); PetscCall(VecAXPY(d_vcl, -1.0, r_vcl)); PetscCall(VecNorm(d_vcl, NORM_INFINITY, &dnorm)); PetscCheck(dnorm <= tol, PETSC_COMM_WORLD, PETSC_ERR_ARG_INCOMP, "MPI CPU and MPI ViennaCL Vector results incompatible with inf norm greater than tolerance of %g", tol); PetscCall(VecDestroy(&v)); PetscCall(VecDestroy(&r)); PetscCall(VecDestroy(&v_vcl)); PetscCall(VecDestroy(&r_vcl)); PetscCall(VecDestroy(&d_vcl)); PetscCall(MatDestroy(&A)); PetscCall(MatDestroy(&A_vcl)); } /* Create a parallel AIJ matrix, convert it in-place to a ViennaCL matrix, and apply it to a ViennaCL vector */ if (size > 1) { Mat A; Vec v, r, v_vcl, r_vcl, d_vcl; PetscInt N = 17, M = 31, nz = 5, i, cnt, j, rlow, rhigh; const PetscScalar val = 1.0; PetscReal dnorm; const PetscReal tol = 1e-5; PetscCall(MatCreateAIJ(PETSC_COMM_WORLD, PETSC_DETERMINE, PETSC_DETERMINE, M, N, nz, NULL, nz, NULL, &A)); /* Add nz arbitrary entries per row in arbitrary columns */ PetscCall(MatGetOwnershipRange(A, &rlow, &rhigh)); for (i = rlow; i < rhigh; ++i) { for (cnt = 0; cnt < nz; ++cnt) { j = (19 * cnt + (7 * i + 3)) % N; PetscCall(MatSetValue(A, i, j, (PetscScalar)(0.3 * i + j), INSERT_VALUES)); } } PetscCall(MatAssemblyBegin(A, MAT_FINAL_ASSEMBLY)); PetscCall(MatAssemblyEnd(A, MAT_FINAL_ASSEMBLY)); PetscCall(PetscObjectSetName((PetscObject)A, "MPI CPU Matrix")); PetscCall(MatCreateVecs(A, &v, &r)); PetscCall(PetscObjectSetName((PetscObject)r, "MPI CPU result vector")); PetscCall(VecSet(v, val)); PetscCall(MatMult(A, v, r)); PetscCall(MatConvert(A, MATMPIAIJVIENNACL, MAT_INPLACE_MATRIX, &A)); PetscCall(PetscObjectSetName((PetscObject)A, "Converted MPI ViennaCL Matrix")); PetscCall(MatCreateVecs(A, &v_vcl, &r_vcl)); PetscCall(PetscObjectSetName((PetscObject)r_vcl, "ViennaCL result vector")); PetscCall(VecSet(v_vcl, val)); PetscCall(MatMult(A, v_vcl, r_vcl)); PetscCall(VecDuplicate(r_vcl, &d_vcl)); PetscCall(VecCopy(r_vcl, d_vcl)); PetscCall(VecAXPY(d_vcl, -1.0, r_vcl)); PetscCall(VecNorm(d_vcl, NORM_INFINITY, &dnorm)); PetscCheck(dnorm <= tol, PETSC_COMM_WORLD, PETSC_ERR_ARG_INCOMP, "MPI CPU and MPI ViennaCL Vector results incompatible with inf norm greater than tolerance of %g", tol); PetscCall(VecDestroy(&v)); PetscCall(VecDestroy(&r)); PetscCall(VecDestroy(&v_vcl)); PetscCall(VecDestroy(&r_vcl)); PetscCall(VecDestroy(&d_vcl)); PetscCall(MatDestroy(&A)); } PetscCall(PetscFinalize()); return 0; } /*TEST build: requires: viennacl test: output_file: output/empty.out test: suffix: 2 nsize: 2 output_file: output/empty.out TEST*/