From 4120bea697590667deebf200359d92e85c6f4e11 Mon Sep 17 00:00:00 2001 From: "Garth N. Wells" Date: Tue, 9 Sep 2025 11:00:27 +0100 Subject: [PATCH 1/8] Starr removing dynamic mempory allocation from low-level matrix assemble --- cpp/dolfinx/fem/assemble_matrix_impl.h | 58 +++++++++++++++----------- 1 file changed, 34 insertions(+), 24 deletions(-) diff --git a/cpp/dolfinx/fem/assemble_matrix_impl.h b/cpp/dolfinx/fem/assemble_matrix_impl.h index 90351a05b7a..0e4b66ac1f0 100644 --- a/cpp/dolfinx/fem/assemble_matrix_impl.h +++ b/cpp/dolfinx/fem/assemble_matrix_impl.h @@ -74,7 +74,8 @@ void assemble_cells_matrix( std::span bc1, FEkernel auto kernel, md::mdspan> coeffs, std::span constants, std::span cell_info0, - std::span cell_info1) + std::span cell_info1, std::span Ab, + std::span> cdofs_b) { if (cells.empty()) return; @@ -87,8 +88,10 @@ void assemble_cells_matrix( const int num_dofs1 = dmap1.extent(1); const int ndim0 = bs0 * num_dofs0; const int ndim1 = bs1 * num_dofs1; - std::vector Ae(ndim0 * ndim1); - std::vector> cdofs(3 * x_dofmap.extent(1)); + + assert(Ab.size() >= ndim0 * ndim1); + assert(cdofs_b.size() >= 3 * x_dofmap.extent(1)); + auto Ae = Ab.first(ndim0 * ndim1); // Iterate over active cells assert(cells0.size() == cells.size()); @@ -104,11 +107,11 @@ void assemble_cells_matrix( // Get cell coordinates/geometry auto x_dofs = md::submdspan(x_dofmap, cell, md::full_extent); for (std::size_t i = 0; i < x_dofs.size(); ++i) - std::copy_n(&x(x_dofs[i], 0), 3, std::next(cdofs.begin(), 3 * i)); + std::copy_n(&x(x_dofs[i], 0), 3, std::next(cdofs_b.begin(), 3 * i)); // Tabulate tensor std::ranges::fill(Ae, 0); - kernel(Ae.data(), &coeffs(c, 0), constants.data(), cdofs.data(), nullptr, + kernel(Ae.data(), &coeffs(c, 0), constants.data(), cdofs_b.data(), nullptr, nullptr, nullptr); // Compute A = P_0 \tilde{A} P_1^T (dof transformation) @@ -213,7 +216,8 @@ void assemble_exterior_facets( md::mdspan> coeffs, std::span constants, std::span cell_info0, std::span cell_info1, - md::mdspan> perms) + md::mdspan> perms, + std::span Ab, std::span> cdofs_b) { if (facets.empty()) return; @@ -221,15 +225,15 @@ void assemble_exterior_facets( const auto [dmap0, bs0, facets0] = dofmap0; const auto [dmap1, bs1, facets1] = dofmap1; - // Data structures used in assembly - std::vector> cdofs(3 * x_dofmap.extent(1)); const int num_dofs0 = dmap0.extent(1); const int num_dofs1 = dmap1.extent(1); const int ndim0 = bs0 * num_dofs0; const int ndim1 = bs1 * num_dofs1; - std::vector Ae(ndim0 * ndim1); assert(facets0.size() == facets.size()); assert(facets1.size() == facets.size()); + assert(Ab.size() >= ndim0 * ndim1); + assert(cdofs_b.size() >= 3 * x_dofmap.extent(1)); + auto Ae = Ab.first(ndim0 * ndim1); for (std::size_t f = 0; f < facets.extent(0); ++f) { // Cell in the integration domain, local facet index relative to the @@ -243,14 +247,14 @@ void assemble_exterior_facets( // Get cell coordinates/geometry auto x_dofs = md::submdspan(x_dofmap, cell, md::full_extent); for (std::size_t i = 0; i < x_dofs.size(); ++i) - std::copy_n(&x(x_dofs[i], 0), 3, std::next(cdofs.begin(), 3 * i)); + std::copy_n(&x(x_dofs[i], 0), 3, std::next(cdofs_b.begin(), 3 * i)); // Permutations std::uint8_t perm = perms.empty() ? 0 : perms(cell, local_facet); // Tabulate tensor std::ranges::fill(Ae, 0); - kernel(Ae.data(), &coeffs(f, 0), constants.data(), cdofs.data(), + kernel(Ae.data(), &coeffs(f, 0), constants.data(), cdofs_b.data(), &local_facet, &perm, nullptr); P0(Ae, cell_info0, cell0, ndim1); P1T(Ae, cell_info1, cell1, ndim0); @@ -355,7 +359,8 @@ void assemble_interior_facets( coeffs, std::span constants, std::span cell_info0, std::span cell_info1, - md::mdspan> perms) + md::mdspan> perms, + std::span Ab, std::span> cdofs_b) { if (facets.empty()) return; @@ -364,11 +369,9 @@ void assemble_interior_facets( const auto [dmap1, bs1, facets1] = dofmap1; // Data structures used in assembly - using X = scalar_value_t; - std::vector cdofs(2 * x_dofmap.extent(1) * 3); - std::span cdofs0(cdofs.data(), x_dofmap.extent(1) * 3); - std::span cdofs1(cdofs.data() + x_dofmap.extent(1) * 3, - x_dofmap.extent(1) * 3); + assert(cdofs_b.size() >= 2 * 3 * x_dofmap.extent(1)); + auto cdofs0 = cdofs_b.first(3 * x_dofmap.extent(1)); + auto cdofs1 = cdofs_b.last(3 * x_dofmap.extent(1)); const std::size_t dmap0_size = dmap0.map().extent(1); const std::size_t dmap1_size = dmap1.map().extent(1); @@ -376,11 +379,12 @@ void assemble_interior_facets( const int num_cols = bs1 * 2 * dmap1_size; // Temporaries for joint dofmaps - std::vector Ae(num_rows * num_cols), be(num_rows); std::vector dmapjoint0(2 * dmap0_size); std::vector dmapjoint1(2 * dmap1_size); assert(facets0.size() == facets.size()); assert(facets1.size() == facets.size()); + assert(Ab.size() >= num_rows * num_cols); + auto Ae = Ab.first(num_rows * num_cols); for (std::size_t f = 0; f < facets.extent(0); ++f) { // Cells in integration domain, test function domain and trial @@ -431,7 +435,7 @@ void assemble_interior_facets( ? std::array{0, 0} : std::array{perms(cells[0], local_facet[0]), perms(cells[1], local_facet[1])}; - kernel(Ae.data(), &coeffs(f, 0, 0), constants.data(), cdofs.data(), + kernel(Ae.data(), &coeffs(f, 0, 0), constants.data(), cdofs_b.data(), local_facet.data(), perm.data(), nullptr); // Local element layout is a 2x2 block matrix with structure @@ -562,11 +566,17 @@ void assemble_matrix( = a.function_spaces().at(1)->dofmaps(cell_type_idx); assert(dofmap0); assert(dofmap1); - auto dofs0 = dofmap0->map(); + md::mdspan> dofs0 + = dofmap0->map(); const int bs0 = dofmap0->bs(); - auto dofs1 = dofmap1->map(); + md::mdspan> dofs1 + = dofmap1->map(); const int bs1 = dofmap1->bs(); + std::vector Ab((2 * bs0 * dofs0.extent(1)) + * (2 * bs1 * dofs1.extent(1))); + std::vector> cdofs_b(2 * 3 * x_dofmap.extent(1)); + auto element0 = a.function_spaces().at(0)->elements(cell_type_idx); assert(element0); auto element1 = a.function_spaces().at(1)->elements(cell_type_idx); @@ -602,7 +612,7 @@ void assemble_matrix( mat_set, x_dofmap, x, cells, {dofs0, bs0, cells0}, P0, {dofs1, bs1, cells1}, P1T, bc0, bc1, fn, md::mdspan(coeffs.data(), cells.size(), cstride), constants, - cell_info0, cell_info1); + cell_info0, cell_info1, Ab, cdofs_b); } md::mdspan> perms; @@ -647,7 +657,7 @@ void assemble_matrix( mat_set, x_dofmap, x, facets, {dofs0, bs0, facets0}, P0, {dofs1, bs1, facets1}, P1T, bc0, bc1, fn, md::mdspan(coeffs.data(), facets.extent(0), cstride), constants, - cell_info0, cell_info1, perms); + cell_info0, cell_info1, perms, Ab, cdofs_b); } for (int i = 0; @@ -685,7 +695,7 @@ void assemble_matrix( mdspanx22_t(facets1.data(), facets1.size() / 4, 2, 2)}, P1T, bc0, bc1, fn, mdspanx2x_t(coeffs.data(), facets.size() / 4, 2, cstride), constants, - cell_info0, cell_info1, perms); + cell_info0, cell_info1, perms, Ab, cdofs_b); } } } From a67f0f8645b4afd82ad704300e44c06c1207b0cb Mon Sep 17 00:00:00 2001 From: "Garth N. Wells" Date: Tue, 9 Sep 2025 11:17:14 +0100 Subject: [PATCH 2/8] Update --- cpp/dolfinx/fem/assemble_matrix_impl.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/cpp/dolfinx/fem/assemble_matrix_impl.h b/cpp/dolfinx/fem/assemble_matrix_impl.h index 0e4b66ac1f0..7f056a3b8b2 100644 --- a/cpp/dolfinx/fem/assemble_matrix_impl.h +++ b/cpp/dolfinx/fem/assemble_matrix_impl.h @@ -612,7 +612,7 @@ void assemble_matrix( mat_set, x_dofmap, x, cells, {dofs0, bs0, cells0}, P0, {dofs1, bs1, cells1}, P1T, bc0, bc1, fn, md::mdspan(coeffs.data(), cells.size(), cstride), constants, - cell_info0, cell_info1, Ab, cdofs_b); + cell_info0, cell_info1, std::span(Ab), std::span(cdofs_b)); } md::mdspan> perms; @@ -657,7 +657,7 @@ void assemble_matrix( mat_set, x_dofmap, x, facets, {dofs0, bs0, facets0}, P0, {dofs1, bs1, facets1}, P1T, bc0, bc1, fn, md::mdspan(coeffs.data(), facets.extent(0), cstride), constants, - cell_info0, cell_info1, perms, Ab, cdofs_b); + cell_info0, cell_info1, perms, std::span(Ab), std::span(cdofs_b)); } for (int i = 0; @@ -695,7 +695,7 @@ void assemble_matrix( mdspanx22_t(facets1.data(), facets1.size() / 4, 2, 2)}, P1T, bc0, bc1, fn, mdspanx2x_t(coeffs.data(), facets.size() / 4, 2, cstride), constants, - cell_info0, cell_info1, perms, Ab, cdofs_b); + cell_info0, cell_info1, perms, std::span(Ab), std::span(cdofs_b)); } } } From 5640f9b652f02f18dfc8b0f8a115c6abc5794617 Mon Sep 17 00:00:00 2001 From: "Garth N. Wells" Date: Tue, 9 Sep 2025 12:21:31 +0100 Subject: [PATCH 3/8] Doc update --- cpp/dolfinx/fem/assemble_matrix_impl.h | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/cpp/dolfinx/fem/assemble_matrix_impl.h b/cpp/dolfinx/fem/assemble_matrix_impl.h index 7f056a3b8b2..d31f5b1d638 100644 --- a/cpp/dolfinx/fem/assemble_matrix_impl.h +++ b/cpp/dolfinx/fem/assemble_matrix_impl.h @@ -60,6 +60,12 @@ using mdspan2_t = md::mdspan>; /// function mesh. /// @param cell_info1 Cell permutation information for the trial /// function mesh. +/// @param Ab Buffer for local element matrix. Size must be at least +/// `(bs0 * num_dofs0) * (bs1 * num_dofs1)`, where `bs0 * num_dofs0` is +/// the number of rows and `bs1 * num_dofs1` is the number of columns in +/// local element matrix. +/// @param cdofs_b Buffer for local element geometry. Size must be at +/// least `3 * x_dofmap.extent(1))`. template void assemble_cells_matrix( la::MatSet auto mat_set, mdspan2_t x_dofmap, @@ -193,6 +199,12 @@ void assemble_cells_matrix( /// function mesh. /// @param[in] perms Facet permutation integer. Empty if facet /// permutations are not required. +/// @param Ab Buffer for local element matrix. Size must be at least +/// `(bs0 * num_dofs0) * (bs1 * num_dofs1)`, where `bs0 * num_dofs0` is +/// the number of rows and `bs1 * num_dofs1` is the number of columns in +/// local element matrix. +/// @param cdofs_b Buffer for local element geometry. Size must be at +/// least `3 * x_dofmap.extent(1))`. template void assemble_exterior_facets( la::MatSet auto mat_set, mdspan2_t x_dofmap, @@ -334,6 +346,12 @@ void assemble_exterior_facets( /// function mesh. /// @param[in] perms Facet permutation integer. Empty if facet /// permutations are not required. +/// @param Ab Buffer for local element matrix. Size must be at least `4 +/// * (bs0 * num_dofs0) * (bs1 * num_dofs1)`, where `bs0 * num_dofs0` is +/// the number of rows and `bs1 * num_dofs1` is the number of columns in +/// local element matrix. +/// @param cdofs_b Buffer for local element geometry. Size must be at +/// least `2 * 3 * x_dofmap.extent(1))`. template void assemble_interior_facets( la::MatSet auto mat_set, mdspan2_t x_dofmap, From bc35f00ea420a4194e1e6e7670966ac566c1453e Mon Sep 17 00:00:00 2001 From: "Garth N. Wells" Date: Tue, 9 Sep 2025 14:20:18 +0100 Subject: [PATCH 4/8] Integer type updates --- cpp/dolfinx/fem/assemble_matrix_impl.h | 44 +++++++++++++------------- 1 file changed, 22 insertions(+), 22 deletions(-) diff --git a/cpp/dolfinx/fem/assemble_matrix_impl.h b/cpp/dolfinx/fem/assemble_matrix_impl.h index d31f5b1d638..fa10bba56dc 100644 --- a/cpp/dolfinx/fem/assemble_matrix_impl.h +++ b/cpp/dolfinx/fem/assemble_matrix_impl.h @@ -90,10 +90,10 @@ void assemble_cells_matrix( const auto [dmap1, bs1, cells1] = dofmap1; // Iterate over active cells - const int num_dofs0 = dmap0.extent(1); - const int num_dofs1 = dmap1.extent(1); - const int ndim0 = bs0 * num_dofs0; - const int ndim1 = bs1 * num_dofs1; + std::size_t num_dofs0 = dmap0.extent(1); + std::size_t num_dofs1 = dmap1.extent(1); + std::size_t ndim0 = bs0 * num_dofs0; + std::size_t ndim1 = bs1 * num_dofs1; assert(Ab.size() >= ndim0 * ndim1); assert(cdofs_b.size() >= 3 * x_dofmap.extent(1)); @@ -130,7 +130,7 @@ void assemble_cells_matrix( if (!bc0.empty()) { - for (int i = 0; i < num_dofs0; ++i) + for (std::size_t i = 0; i < num_dofs0; ++i) { for (int k = 0; k < bs0; ++k) { @@ -146,15 +146,15 @@ void assemble_cells_matrix( if (!bc1.empty()) { - for (int j = 0; j < num_dofs1; ++j) + for (std::size_t j = 0; j < num_dofs1; ++j) { for (int k = 0; k < bs1; ++k) { if (bc1[bs1 * dofs1[j] + k]) { // Zero column bs1 * j + k - const int col = bs1 * j + k; - for (int row = 0; row < ndim0; ++row) + int col = bs1 * j + k; + for (std::size_t row = 0; row < ndim0; ++row) Ae[row * ndim1 + col] = 0; } } @@ -237,10 +237,10 @@ void assemble_exterior_facets( const auto [dmap0, bs0, facets0] = dofmap0; const auto [dmap1, bs1, facets1] = dofmap1; - const int num_dofs0 = dmap0.extent(1); - const int num_dofs1 = dmap1.extent(1); - const int ndim0 = bs0 * num_dofs0; - const int ndim1 = bs1 * num_dofs1; + std::size_t num_dofs0 = dmap0.extent(1); + std::size_t num_dofs1 = dmap1.extent(1); + std::size_t ndim0 = bs0 * num_dofs0; + std::size_t ndim1 = bs1 * num_dofs1; assert(facets0.size() == facets.size()); assert(facets1.size() == facets.size()); assert(Ab.size() >= ndim0 * ndim1); @@ -276,7 +276,7 @@ void assemble_exterior_facets( std::span dofs1(dmap1.data_handle() + cell1 * num_dofs1, num_dofs1); if (!bc0.empty()) { - for (int i = 0; i < num_dofs0; ++i) + for (std::size_t i = 0; i < num_dofs0; ++i) { for (int k = 0; k < bs0; ++k) { @@ -291,15 +291,15 @@ void assemble_exterior_facets( } if (!bc1.empty()) { - for (int j = 0; j < num_dofs1; ++j) + for (std::size_t j = 0; j < num_dofs1; ++j) { for (int k = 0; k < bs1; ++k) { if (bc1[bs1 * dofs1[j] + k]) { // Zero column bs1 * j + k - const int col = bs1 * j + k; - for (int row = 0; row < ndim0; ++row) + int col = bs1 * j + k; + for (std::size_t row = 0; row < ndim0; ++row) Ae[row * ndim1 + col] = 0; } } @@ -391,10 +391,10 @@ void assemble_interior_facets( auto cdofs0 = cdofs_b.first(3 * x_dofmap.extent(1)); auto cdofs1 = cdofs_b.last(3 * x_dofmap.extent(1)); - const std::size_t dmap0_size = dmap0.map().extent(1); - const std::size_t dmap1_size = dmap1.map().extent(1); - const int num_rows = bs0 * 2 * dmap0_size; - const int num_cols = bs1 * 2 * dmap1_size; + std::size_t dmap0_size = dmap0.map().extent(1); + std::size_t dmap1_size = dmap1.map().extent(1); + std::size_t num_rows = bs0 * 2 * dmap0_size; + std::size_t num_cols = bs1 * 2 * dmap1_size; // Temporaries for joint dofmaps std::vector dmapjoint0(2 * dmap0_size); @@ -478,7 +478,7 @@ void assemble_interior_facets( if (cells1[1] >= 0) { - for (int row = 0; row < num_rows; ++row) + for (std::size_t row = 0; row < num_rows; ++row) { // DOFs for dmap1 and cell1 are not stored contiguously in the // block matrix, so each row needs a separate span access @@ -513,7 +513,7 @@ void assemble_interior_facets( if (bc1[bs1 * dmapjoint1[j] + k]) { // Zero column bs1 * j + k - for (int m = 0; m < num_rows; ++m) + for (std::size_t m = 0; m < num_rows; ++m) Ae[m * num_cols + bs1 * j + k] = 0; } } From b5c20f49a742507d6c16ed0f0257760659893850 Mon Sep 17 00:00:00 2001 From: "Garth N. Wells" Date: Tue, 9 Sep 2025 14:36:20 +0100 Subject: [PATCH 5/8] Update demo --- cpp/demo/custom_kernel/main.cpp | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/cpp/demo/custom_kernel/main.cpp b/cpp/demo/custom_kernel/main.cpp index 6ddcfacabfb..7f701fd4c21 100644 --- a/cpp/demo/custom_kernel/main.cpp +++ b/cpp/demo/custom_kernel/main.cpp @@ -141,9 +141,13 @@ double assemble_matrix1(const mesh::Geometry& g, const fem::DofMap& dofmap, common::Timer timer("Assembler1 lambda (matrix)"); md::mdspan> x( g.x().data(), g.x().size() / 3, 3); - fem::impl::assemble_cells_matrix( - A.mat_add_values(), g.dofmap(), x, cells, {dofmap.map(), 1, cells}, ident, - {dofmap.map(), 1, cells}, ident, {}, {}, kernel, {}, {}, {}, {}); + + std::vector cdofs_b(3 * g.dofmap().extent(1)); + std::vector Ab(dofmap.map().extent(1) * dofmap.map().extent(1)); + fem::impl::assemble_cells_matrix(A.mat_add_values(), g.dofmap(), x, cells, + {dofmap.map(), 1, cells}, ident, + {dofmap.map(), 1, cells}, ident, {}, {}, + kernel, {}, {}, {}, {}, Ab, cdofs_b); A.scatter_rev(); return A.squared_norm(); } From a69ed26cbda6625bb41bd22ae6e95784bd5c3d58 Mon Sep 17 00:00:00 2001 From: "Garth N. Wells" Date: Fri, 12 Sep 2025 12:04:17 +0100 Subject: [PATCH 6/8] Remove allocation --- cpp/dolfinx/fem/assemble_matrix_impl.h | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/cpp/dolfinx/fem/assemble_matrix_impl.h b/cpp/dolfinx/fem/assemble_matrix_impl.h index fa10bba56dc..45ca9e046d7 100644 --- a/cpp/dolfinx/fem/assemble_matrix_impl.h +++ b/cpp/dolfinx/fem/assemble_matrix_impl.h @@ -378,7 +378,8 @@ void assemble_interior_facets( std::span constants, std::span cell_info0, std::span cell_info1, md::mdspan> perms, - std::span Ab, std::span> cdofs_b) + std::span Ab, std::span> cdofs_b, + std::span dofs_b) { if (facets.empty()) return; @@ -397,8 +398,10 @@ void assemble_interior_facets( std::size_t num_cols = bs1 * 2 * dmap1_size; // Temporaries for joint dofmaps - std::vector dmapjoint0(2 * dmap0_size); - std::vector dmapjoint1(2 * dmap1_size); + assert(dofs_b.size() >= (2 * dmap0_size) + (2 * dmap1_size)); + auto dmapjoint0 = dofs_b.first(2 * dmap0_size); + auto dmapjoint1 = dofs_b.last(2 * dmap1_size); + assert(facets0.size() == facets.size()); assert(facets1.size() == facets.size()); assert(Ab.size() >= num_rows * num_cols); @@ -594,6 +597,11 @@ void assemble_matrix( std::vector Ab((2 * bs0 * dofs0.extent(1)) * (2 * bs1 * dofs1.extent(1))); std::vector> cdofs_b(2 * 3 * x_dofmap.extent(1)); + std::size_t dmap0_size = dofmap0->map().extent(1); + std::size_t dmap1_size = dofmap1->map().extent(1); + // std::size_t num_rows = bs0 * 2 * dmap0_size; + // std::size_t num_cols = bs1 * 2 * dmap1_size; + std::vector dmap_b((2 * dmap0_size) + (2 * dmap1_size)); auto element0 = a.function_spaces().at(0)->elements(cell_type_idx); assert(element0); @@ -713,7 +721,8 @@ void assemble_matrix( mdspanx22_t(facets1.data(), facets1.size() / 4, 2, 2)}, P1T, bc0, bc1, fn, mdspanx2x_t(coeffs.data(), facets.size() / 4, 2, cstride), constants, - cell_info0, cell_info1, perms, std::span(Ab), std::span(cdofs_b)); + cell_info0, cell_info1, perms, std::span(Ab), std::span(cdofs_b), + dmap_b); } } } From a6df69eea51794bc5e2c2b30b4ad3e0aafe47912 Mon Sep 17 00:00:00 2001 From: "Garth N. Wells" Date: Fri, 12 Sep 2025 12:05:19 +0100 Subject: [PATCH 7/8] Remove some code --- cpp/dolfinx/fem/assemble_matrix_impl.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/cpp/dolfinx/fem/assemble_matrix_impl.h b/cpp/dolfinx/fem/assemble_matrix_impl.h index 45ca9e046d7..229a529682b 100644 --- a/cpp/dolfinx/fem/assemble_matrix_impl.h +++ b/cpp/dolfinx/fem/assemble_matrix_impl.h @@ -599,8 +599,6 @@ void assemble_matrix( std::vector> cdofs_b(2 * 3 * x_dofmap.extent(1)); std::size_t dmap0_size = dofmap0->map().extent(1); std::size_t dmap1_size = dofmap1->map().extent(1); - // std::size_t num_rows = bs0 * 2 * dmap0_size; - // std::size_t num_cols = bs1 * 2 * dmap1_size; std::vector dmap_b((2 * dmap0_size) + (2 * dmap1_size)); auto element0 = a.function_spaces().at(0)->elements(cell_type_idx); From d96c020dffdaf8a61f4b1656100f68ea0efd8a4e Mon Sep 17 00:00:00 2001 From: "Garth N. Wells" Date: Fri, 12 Sep 2025 12:07:47 +0100 Subject: [PATCH 8/8] Doc fix --- cpp/dolfinx/fem/assemble_matrix_impl.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/cpp/dolfinx/fem/assemble_matrix_impl.h b/cpp/dolfinx/fem/assemble_matrix_impl.h index 229a529682b..165526a563d 100644 --- a/cpp/dolfinx/fem/assemble_matrix_impl.h +++ b/cpp/dolfinx/fem/assemble_matrix_impl.h @@ -352,6 +352,8 @@ void assemble_exterior_facets( /// local element matrix. /// @param cdofs_b Buffer for local element geometry. Size must be at /// least `2 * 3 * x_dofmap.extent(1))`. +/// @param dofs_b Buffer for degrees-of-freedom. Size must be at least +/// `2 * dmap0.map().extent(1) + 2 * dmap1.map().extent(1)`. template void assemble_interior_facets( la::MatSet auto mat_set, mdspan2_t x_dofmap, @@ -397,7 +399,7 @@ void assemble_interior_facets( std::size_t num_rows = bs0 * 2 * dmap0_size; std::size_t num_cols = bs1 * 2 * dmap1_size; - // Temporaries for joint dofmaps + // Dofmap data structures assert(dofs_b.size() >= (2 * dmap0_size) + (2 * dmap1_size)); auto dmapjoint0 = dofs_b.first(2 * dmap0_size); auto dmapjoint1 = dofs_b.last(2 * dmap1_size);