| 185 | /// @param comm MPI communicator to assembler over. |
| 186 | template <std::floating_point T> |
| 187 | void assemble(MPI_Comm comm) |
| 188 | { |
| 189 | // Create mesh |
| 190 | auto mesh = std::make_shared<mesh::Mesh<T>>(mesh::create_rectangle<T>( |
| 191 | comm, {{{0, 0}, {1, 1}}}, {516, 116}, mesh::CellType::triangle)); |
| 192 | |
| 193 | // Create Basix P1 Lagrange element. This will be used to construct |
| 194 | // basis functions inside the custom cell kernel. |
| 195 | constexpr int order = 1; |
| 196 | basix::FiniteElement e = basix::create_element<T>( |
| 197 | basix::element::family::P, |
| 198 | mesh::cell_type_to_basix_type(mesh::CellType::triangle), order, |
| 199 | basix::element::lagrange_variant::unset, |
| 200 | basix::element::dpc_variant::unset, false); |
| 201 | |
| 202 | // Construct quadrature rule |
| 203 | constexpr int max_degree = 2 * order; |
| 204 | auto quadrature_type = basix::quadrature::get_default_rule( |
| 205 | basix::cell::type::triangle, max_degree); |
| 206 | auto [X_b, weights] = basix::quadrature::make_quadrature<T>( |
| 207 | quadrature_type, basix::cell::type::triangle, |
| 208 | basix::polyset::type::standard, max_degree); |
| 209 | mdspand_t<const T, 2> X(X_b.data(), weights.size(), 2); |
| 210 | |
| 211 | // Create a scalar function space |
| 212 | auto V = std::make_shared<fem::FunctionSpace<T>>(fem::create_functionspace<T>( |
| 213 | mesh, std::make_shared<fem::FiniteElement<T>>(e))); |
| 214 | |
| 215 | // Build list of cells to assembler over (all cells owned by this |
| 216 | // rank) |
| 217 | std::int32_t size_local |
| 218 | = mesh->topology()->index_map(mesh->topology()->dim())->size_local(); |
| 219 | std::vector<std::int32_t> cells(size_local); |
| 220 | std::iota(cells.begin(), cells.end(), 0); |
| 221 | |
| 222 | // Tabulate basis functions at quadrature points |
| 223 | auto e_shape = e.tabulate_shape(0, weights.size()); |
| 224 | std::size_t length |
| 225 | = std::accumulate(e_shape.begin(), e_shape.end(), 1, std::multiplies<>{}); |
| 226 | std::vector<T> phi_b(length); |
| 227 | mdspand_t<T, 4> phi(phi_b.data(), e_shape); |
| 228 | e.tabulate(0, X, phi); |
| 229 | |
| 230 | // Utility function to compute det(J) for an affine triangle cell |
| 231 | // (geometry is 3D) |
| 232 | auto detJ = [](mdspan2_t<const T, 3, 3> x) |
| 233 | { |
| 234 | return std::abs((x(0, 0) - x(1, 0)) * (x(2, 1) - x(1, 1)) |
| 235 | - (x(0, 1) - x(1, 1)) * (x(2, 0) - x(1, 0))); |
| 236 | }; |
| 237 | |
| 238 | // Finite element mass matrix kernel function |
| 239 | std::array<T, 9> A_hat_b = A_ref<T>(phi, weights); |
| 240 | auto kernel_a = [A_hat = mdspan2_t<T, 3, 3>(A_hat_b.data()), |
| 241 | detJ](T* A, const T*, const T*, const T* x, const int*, |
| 242 | const uint8_t*, void*) |
| 243 | { |
| 244 | T scale = detJ(mdspan2_t<const T, 3, 3>(x)); |
nothing calls this directly
no test coverage detected