Skip to content

Refactor dolfinx::fem::Form to use local indexing of forms, rather than integral ids #3740

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 10 commits into
base: main
Choose a base branch
from
Open
4 changes: 2 additions & 2 deletions cpp/demo/custom_kernel/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ double assemble_matrix0(std::shared_ptr<const fem::FunctionSpace<T>> V,
{
// Kernel data (ID, kernel function, cell indices to execute over)
std::map integrals{
std::pair{std::tuple{fem::IntegralType::cell, -1, 0},
std::pair{std::tuple{fem::IntegralType::cell, 0, 0},
fem::integral_data<T>(kernel, cells, std::vector<int>{})}};

fem::Form<T, T> a({V, V}, integrals, V->mesh(), {}, {}, false, {});
Expand Down Expand Up @@ -105,7 +105,7 @@ double assemble_vector0(std::shared_ptr<const fem::FunctionSpace<T>> V,
{
auto mesh = V->mesh();
std::map integrals{
std::pair{std::tuple{fem::IntegralType::cell, -1, 0},
std::pair{std::tuple{fem::IntegralType::cell, 0, 0},
fem::integral_data<T>(kernel, cells, std::vector<int>{})}};
fem::Form<T> L({V}, integrals, mesh, {}, {}, false, {});
auto dofmap = V->dofmap();
Expand Down
72 changes: 31 additions & 41 deletions cpp/dolfinx/fem/Form.h
Original file line number Diff line number Diff line change
Expand Up @@ -188,9 +188,8 @@ class Form
/// @param[in] V Function spaces for the form arguments, e.g. test and
/// trial function spaces.
/// @param[in] integrals Integrals in the form, where
/// `integrals[IntegralType, domain ID, kernel index]` returns the
/// integral (`integral_data`) of type `IntegralType` over domain `ID`
/// with kernel index `kernel index`.
/// `integrals[IntegralType, i, kernel index]` returns the `i`th integral
// (`integral_data`) of type `IntegralType` with kernel index `kernel index`.
/// @param[in] coefficients Coefficients in the form.
/// @param[in] constants Constants in the form.
/// @param[in] mesh Mesh of the domain to integrate over (the
Expand Down Expand Up @@ -257,7 +256,7 @@ class Form

for (auto& space : _function_spaces)
{
// Working map: [integral type, domain ID, kernel_idx]->entities
// Working map: [integral type, integral_idx, kernel_idx]->entities
std::map<std::tuple<IntegralType, int, int>,
std::variant<std::vector<std::int32_t>,
std::span<const std::int32_t>>>
Expand All @@ -275,7 +274,7 @@ class Form
std::span<const std::int32_t> entity_map = it->second;
for (auto& [key, itg] : _integrals)
{
auto [type, id, kernel_idx] = key;
auto [type, idx, kernel_idx] = key;
std::vector<std::int32_t> e;
if (type == IntegralType::cell)
{
Expand Down Expand Up @@ -309,13 +308,13 @@ class Form

for (auto& [key, integral] : _integrals)
{
auto [type, id, kernel_idx] = key;
auto [type, idx, kernel_idx] = key;
for (int c : integral.coeffs)
{
if (auto mesh0 = coefficients.at(c)->function_space()->mesh();
mesh0 == _mesh)
{
_cdata.insert({{type, id, c}, std::span(integral.entities)});
_cdata.insert({{type, idx, c}, std::span(integral.entities)});
}
else
{
Expand Down Expand Up @@ -346,7 +345,7 @@ class Form
}
else
throw std::runtime_error("Integral type not supported.");
_cdata.insert({{type, id, c}, std::move(e)});
_cdata.insert({{type, idx, c}, std::move(e)});
}
}
}
Expand Down Expand Up @@ -432,31 +431,22 @@ class Form
return it->second.coeffs;
}

/// @brief Get the IDs for integrals (kernels) for given integral
/// domain type.
///
/// The IDs correspond to the domain IDs which the integrals are
/// defined for in the form. `ID=-1` is the default integral over the
/// whole domain.
/// @brief Get number of integrals (kernels) for a given integral type and
/// kernel index.
///
/// @param[in] type Integral type.
/// @return List of IDs for given integral type.
std::vector<int> integral_ids(IntegralType type) const
/// @param[in] kernel_idx Index of the kernel (we may have multiple
/// kernels for a integral type in mixed-topology meshes).
int num_integrals(IntegralType type, int kernel_idx) const
{
std::vector<int> ids;
int count = 0;
for (auto& [key, integral] : _integrals)
{
auto [t, id, kernel_idx] = key;
if (t == type)
ids.push_back(id);
auto [t, id, k_idx] = key;
if (t == type and k_idx == kernel_idx)
count++;
}

// IDs may be repeated in mixed-topology meshes, so remove
// duplicates
std::sort(ids.begin(), ids.end());
auto it = std::unique(ids.begin(), ids.end());
ids.erase(it, ids.end());
return ids;
return count;
}

/// @brief Mesh entity indices to integrate over for a given integral
Expand All @@ -477,16 +467,16 @@ class Form
/// is row-major.
///
/// @param[in] type Integral type.
/// @param[in] id Integral domain identifier.
/// @param[in] idx Integral identifier.
/// @param[in] kernel_idx Index of the kernel with in the domain (we
/// may have multiple kernels for a given ID in mixed-topology
/// meshes).
/// @return Entity indices in the mesh::Mesh returned by mesh() to
/// integrate over.
std::span<const std::int32_t> domain(IntegralType type, int id,
std::span<const std::int32_t> domain(IntegralType type, int idx,
int kernel_idx) const
{
auto it = _integrals.find({type, id, kernel_idx});
auto it = _integrals.find({type, idx, kernel_idx});
if (it == _integrals.end())
throw std::runtime_error("Requested domain not found.");
return it->second.entities;
Expand All @@ -512,21 +502,21 @@ class Form
/// `entities0[i]` point to the same mesh entity, but with respect to
/// different mesh views.
///
/// @param type Integral type.
/// @param rank Argument index, e.g. `0` for the test function space, `1`
/// @param[in] type Integral type.
/// @param[in] rank Argument index, e.g. `0` for the test function space, `1`
/// for the trial function space.
/// @param id Integral domain identifier.
/// @param kernel_idx Kernel index (cell type).
/// @param[in] idx Integral identifier.
/// @param[in] kernel_idx Kernel index (cell type).
/// @return Entity indices in the argument function space mesh that is
/// integrated over.
/// - For cell integrals it has shape `(num_cells,)`.
/// - For exterior/interior facet integrals, it has shape `(num_facts, 2)`
/// (row-major storage), where `[i, 0]` is the index of a cell and
/// `[i, 1]` is the local index of the facet relative to the cell.
std::span<const std::int32_t> domain_arg(IntegralType type, int rank, int id,
std::span<const std::int32_t> domain_arg(IntegralType type, int rank, int idx,
int kernel_idx) const
{
auto it = _edata.at(rank).find({type, id, kernel_idx});
auto it = _edata.at(rank).find({type, idx, kernel_idx});
if (it == _edata.at(rank).end())
throw std::runtime_error("Requested domain for argument not found.");
try
Expand All @@ -544,19 +534,19 @@ class Form
/// This method is equivalent to ::domain_arg, but returns mesh entity
/// indices for coefficient \link Function Functions. \endlink
///
/// @param type Integral type.
/// @param id Integral identifier index.
/// @param c Coefficient index.
/// @param[in] type Integral type.
/// @param[in] idx Integral identifier.
/// @param[in] c Coefficient index.
/// @return Entity indices in the coefficient function space mesh that
/// is integrated over.
/// - For cell integrals it has shape `(num_cells,)`.
/// - For exterior/interior facet integrals, it has shape `(num_facts, 2)`
/// (row-major storage), where `[i, 0]` is the index of a cell and
/// `[i, 1]` is the local index of the facet relative to the cell.
std::span<const std::int32_t> domain_coeff(IntegralType type, int id,
std::span<const std::int32_t> domain_coeff(IntegralType type, int idx,
int c) const
{
auto it = _cdata.find({type, id, c});
auto it = _cdata.find({type, idx, c});
if (it == _cdata.end())
throw std::runtime_error("No domain for requested integral.");
try
Expand Down
8 changes: 5 additions & 3 deletions cpp/dolfinx/fem/assemble_matrix_impl.h
Original file line number Diff line number Diff line change
Expand Up @@ -578,7 +578,7 @@ void assemble_matrix(
cell_info1 = std::span(mesh1->topology()->get_cell_permutation_info());
}

for (int i : a.integral_ids(IntegralType::cell))
for (int i = 0; i < a.num_integrals(IntegralType::cell, cell_type_idx); ++i)
{
auto fn = a.kernel(IntegralType::cell, i, cell_type_idx);
assert(fn);
Expand Down Expand Up @@ -606,7 +606,8 @@ void assemble_matrix(
num_facets_per_cell);
}

for (int i : a.integral_ids(IntegralType::exterior_facet))
for (int i = 0;
i < a.num_integrals(IntegralType::exterior_facet, cell_type_idx); ++i)
{
if (num_cell_types > 1)
{
Expand Down Expand Up @@ -637,7 +638,8 @@ void assemble_matrix(
cell_info0, cell_info1, perms);
}

for (int i : a.integral_ids(IntegralType::interior_facet))
for (int i = 0;
i < a.num_integrals(IntegralType::interior_facet, cell_type_idx); ++i)
{
if (num_cell_types > 1)
{
Expand Down
6 changes: 3 additions & 3 deletions cpp/dolfinx/fem/assemble_scalar_impl.h
Original file line number Diff line number Diff line change
Expand Up @@ -165,7 +165,7 @@ T assemble_scalar(
assert(mesh);

T value = 0;
for (int i : M.integral_ids(IntegralType::cell))
for (int i = 0; i < M.num_integrals(IntegralType::cell, 0); ++i)
{
auto fn = M.kernel(IntegralType::cell, i, 0);
assert(fn);
Expand All @@ -190,7 +190,7 @@ T assemble_scalar(
num_facets_per_cell);
}

for (int i : M.integral_ids(IntegralType::exterior_facet))
for (int i = 0; i < M.num_integrals(IntegralType::exterior_facet, 0); ++i)
{
auto fn = M.kernel(IntegralType::exterior_facet, i, 0);
assert(fn);
Expand All @@ -208,7 +208,7 @@ T assemble_scalar(
perms);
}

for (int i : M.integral_ids(IntegralType::interior_facet))
for (int i = 0; i < M.num_integrals(IntegralType::interior_facet, 0); ++i)
{
auto fn = M.kernel(IntegralType::interior_facet, i, 0);
assert(fn);
Expand Down
12 changes: 6 additions & 6 deletions cpp/dolfinx/fem/assemble_vector_impl.h
Original file line number Diff line number Diff line change
Expand Up @@ -976,7 +976,7 @@ void lift_bc(std::span<T> b, const Form<T, U>& a, mdspan2_t x_dofmap,
= element1->template dof_transformation_right_fn<T>(
doftransform::transpose);

for (int i : a.integral_ids(IntegralType::cell))
for (int i = 0; i < a.num_integrals(IntegralType::cell, 0); ++i)
{
auto kernel = a.kernel(IntegralType::cell, i, 0);
assert(kernel);
Expand Down Expand Up @@ -1021,7 +1021,7 @@ void lift_bc(std::span<T> b, const Form<T, U>& a, mdspan2_t x_dofmap,
num_facets_per_cell);
}

for (int i : a.integral_ids(IntegralType::exterior_facet))
for (int i = 0; i < a.num_integrals(IntegralType::exterior_facet, 0); ++i)
{
auto kernel = a.kernel(IntegralType::exterior_facet, i, 0);
assert(kernel);
Expand All @@ -1045,7 +1045,7 @@ void lift_bc(std::span<T> b, const Form<T, U>& a, mdspan2_t x_dofmap,
cell_info1, bc_values1, bc_markers1, x0, alpha, perms);
}

for (int i : a.integral_ids(IntegralType::interior_facet))
for (int i = 0; i < a.num_integrals(IntegralType::interior_facet, 0); ++i)
{
auto kernel = a.kernel(IntegralType::interior_facet, i, 0);
assert(kernel);
Expand Down Expand Up @@ -1211,7 +1211,7 @@ void assemble_vector(
cell_info0 = std::span(mesh0->topology()->get_cell_permutation_info());
}

for (int i : L.integral_ids(IntegralType::cell))
for (int i = 0; i < L.num_integrals(IntegralType::cell, 0); ++i)
{
auto fn = L.kernel(IntegralType::cell, i, cell_type_idx);
assert(fn);
Expand Down Expand Up @@ -1256,7 +1256,7 @@ void assemble_vector(
= md::mdspan<const std::int32_t,
md::extents<std::size_t, md::dynamic_extent, 2>>;

for (int i : L.integral_ids(IntegralType::exterior_facet))
for (int i = 0; i < L.num_integrals(IntegralType::exterior_facet, 0); ++i)
{
auto fn = L.kernel(IntegralType::exterior_facet, i, 0);
assert(fn);
Expand Down Expand Up @@ -1290,7 +1290,7 @@ void assemble_vector(
}
}

for (int i : L.integral_ids(IntegralType::interior_facet))
for (int i = 0; i < L.num_integrals(IntegralType::interior_facet, 0); ++i)
{
using mdspanx22_t
= md::mdspan<const std::int32_t,
Expand Down
6 changes: 3 additions & 3 deletions cpp/dolfinx/fem/pack.h
Original file line number Diff line number Diff line change
Expand Up @@ -200,10 +200,10 @@ allocate_coefficient_storage(const Form<T, U>& form)
std::map<std::pair<IntegralType, int>, std::pair<std::vector<T>, int>> coeffs;
for (fem::IntegralType type : form.integral_types())
{
for (int id : form.integral_ids(type))
for (int i = 0; i < form.num_integrals(type, 0); ++i)
{
coeffs.emplace_hint(coeffs.end(), std::pair{type, id},
allocate_coefficient_storage(form, type, id));
coeffs.emplace_hint(coeffs.end(), std::pair{type, i},
allocate_coefficient_storage(form, type, i));
}
}

Expand Down
Loading
Loading