| 64 | } |
| 65 | |
| 66 | void test_matrix_apply() |
| 67 | { |
| 68 | MPI_Comm comm = MPI_COMM_WORLD; |
| 69 | auto part = mesh::create_cell_partitioner(mesh::GhostMode::none, 2); |
| 70 | auto mesh = std::make_shared<mesh::Mesh<double>>( |
| 71 | mesh::create_box(comm, {{{0.0, 0.0, 0.0}, {1.0, 1.0, 1.0}}}, {12, 12, 12}, |
| 72 | mesh::CellType::tetrahedron, part)); |
| 73 | |
| 74 | auto element = basix::create_element<double>( |
| 75 | basix::element::family::P, basix::cell::type::tetrahedron, 2, |
| 76 | basix::element::lagrange_variant::unset, |
| 77 | basix::element::dpc_variant::unset, false); |
| 78 | |
| 79 | auto V = std::make_shared<fem::FunctionSpace<double>>( |
| 80 | fem::create_functionspace<double>( |
| 81 | mesh, std::make_shared<fem::FiniteElement<double>>(element))); |
| 82 | |
| 83 | // Prepare and set Constants for the bilinear form |
| 84 | auto kappa = std::make_shared<fem::Constant<double>>(2.0); |
| 85 | auto ui = std::make_shared<fem::Function<double, double>>(V); |
| 86 | |
| 87 | // Define variational forms |
| 88 | auto a = std::make_shared<fem::Form<double, double>>( |
| 89 | fem::create_form<double, double>(*form_poisson_a, {V, V}, {}, |
| 90 | {{"kappa", kappa}}, {}, {})); |
| 91 | |
| 92 | // Create sparsity pattern |
| 93 | la::SparsityPattern sp = fem::create_sparsity_pattern(*a); |
| 94 | sp.finalize(); |
| 95 | |
| 96 | // Assemble matrix |
| 97 | la::MatrixCSR<double> A(sp); |
| 98 | fem::assemble_matrix(A.mat_add_values(), *a, {}); |
| 99 | A.scatter_rev(); |
| 100 | CHECK((V->dofmap()->index_map->size_local() == A.num_owned_rows())); |
| 101 | |
| 102 | // Get compatible vectors |
| 103 | auto col_map = A.index_map(1); |
| 104 | |
| 105 | la::Vector<double> x(col_map, 1); |
| 106 | la::Vector<double> y(col_map, 1); |
| 107 | |
| 108 | std::size_t col_size = col_map->size_local() + col_map->num_ghosts(); |
| 109 | CHECK(x.array().size() == col_size); |
| 110 | |
| 111 | // Fill x vector with 1 (Constant) |
| 112 | std::ranges::fill(x.array(), 1); |
| 113 | |
| 114 | // Matrix A represents the action of the Laplace operator, so when |
| 115 | // applied to a constant vector the result should be zero |
| 116 | A.mult(x, y); |
| 117 | |
| 118 | std::ranges::for_each(y.array(), |
| 119 | [](auto a) { REQUIRE(std::abs(a) < 1e-13); }); |
| 120 | } |
| 121 | |
| 122 | void test_matrix_cast() |
| 123 | { |
no test coverage detected