Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
47 changes: 45 additions & 2 deletions cpp/dolfinx/fem/Form.h
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,8 @@
/// @param[in] entities Indices of entities to integrate over.
/// @param[in] coeffs Indices of the coefficients that are present
/// (active) in `kernel`.
/// @param[in] custom_data Optional custom user data pointer passed to
/// the kernel function.
template <typename K, typename V, typename W>
requires std::is_convertible_v<
std::remove_cvref_t<K>,
Expand All @@ -64,9 +66,10 @@
std::vector<std::int32_t>>
and std::is_convertible_v<std::remove_cvref_t<W>,
std::vector<int>>
integral_data(K&& kernel, V&& entities, W&& coeffs)
integral_data(K&& kernel, V&& entities, W&& coeffs,
std::optional<void*> custom_data = std::nullopt)

Check failure on line 70 in cpp/dolfinx/fem/Form.h

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Replace this use of "void *" with a more meaningful type.

See more on https://sonarcloud.io/project/issues?id=FEniCS_dolfinx&issues=AZraT3JQqA6mqPYJkcJp&open=AZraT3JQqA6mqPYJkcJp&pullRequest=4013
: kernel(std::forward<K>(kernel)), entities(std::forward<V>(entities)),
coeffs(std::forward<W>(coeffs))
coeffs(std::forward<W>(coeffs)), custom_data(custom_data)
{
}

Expand All @@ -82,6 +85,11 @@
/// @brief Indices of coefficients (from the form) that are in this
/// integral.
std::vector<int> coeffs;

/// @brief Custom user data pointer passed to the kernel function.
/// This can be used to pass runtime-computed data (e.g., per-cell
/// quadrature rules, material properties) to the kernel.
std::optional<void*> custom_data = std::nullopt;
};

/// @brief A representation of finite element variational forms.
Expand Down Expand Up @@ -391,6 +399,41 @@
return it->second.kernel;
}

/// @brief Get the custom data pointer for an integral.
///
/// The custom data pointer is passed to the kernel function during
/// assembly. This can be used to pass runtime-computed data to
/// kernels (e.g., per-cell quadrature rules, material properties).
///
/// @param[in] type Integral type.
/// @param[in] id Integral subdomain ID.
/// @param[in] kernel_idx Index of the kernel (we may have multiple
/// kernels for a given ID in mixed-topology meshes).
/// @return Custom data pointer for the integral, or std::nullopt if not set.
std::optional<void*> custom_data(IntegralType type, int id,

Check failure on line 413 in cpp/dolfinx/fem/Form.h

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Replace this use of "void *" with a more meaningful type.

See more on https://sonarcloud.io/project/issues?id=FEniCS_dolfinx&issues=AZraT3JQqA6mqPYJkcJq&open=AZraT3JQqA6mqPYJkcJq&pullRequest=4013
int kernel_idx) const
{
auto it = _integrals.find({type, id, kernel_idx});
if (it == _integrals.end())
throw std::runtime_error("Requested integral not found.");

Check warning on line 418 in cpp/dolfinx/fem/Form.h

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Define and throw a dedicated exception instead of using a generic one.

See more on https://sonarcloud.io/project/issues?id=FEniCS_dolfinx&issues=AZraT3JQqA6mqPYJkcJn&open=AZraT3JQqA6mqPYJkcJn&pullRequest=4013
return it->second.custom_data;
}

/// @brief Set the custom data pointer for an integral.
///
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would like to add a warning here:

"void-pointers are inherently unsafe and cannot be type or bounds checked. Incorrect usage of this feature can and will lead to undefined behaviour and crashes."

/// @param[in] type Integral type.
/// @param[in] id Integral subdomain ID.
/// @param[in] kernel_idx Index of the kernel.
/// @param[in] data Custom data pointer to set, or std::nullopt to clear.
void set_custom_data(IntegralType type, int id, int kernel_idx,
std::optional<void*> data)

Check failure on line 429 in cpp/dolfinx/fem/Form.h

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Replace this use of "void *" with a more meaningful type.

See more on https://sonarcloud.io/project/issues?id=FEniCS_dolfinx&issues=AZrb3q8zu-mtKnwcCd-e&open=AZrb3q8zu-mtKnwcCd-e&pullRequest=4013
{
auto it = _integrals.find({type, id, kernel_idx});
if (it == _integrals.end())
throw std::runtime_error("Requested integral not found.");

Check warning on line 433 in cpp/dolfinx/fem/Form.h

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Define and throw a dedicated exception instead of using a generic one.

See more on https://sonarcloud.io/project/issues?id=FEniCS_dolfinx&issues=AZraT3JQqA6mqPYJkcJo&open=AZraT3JQqA6mqPYJkcJo&pullRequest=4013
it->second.custom_data = data;
}

/// @brief Get types of integrals in the form.
/// @return Integrals types.
std::set<IntegralType> integral_types() const
Expand Down
29 changes: 20 additions & 9 deletions cpp/dolfinx/fem/assemble_matrix_impl.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
#include <dolfinx/mesh/Topology.h>
#include <functional>
#include <iterator>
#include <optional>
#include <span>
#include <tuple>
#include <vector>
Expand Down Expand Up @@ -60,6 +61,7 @@
/// function mesh.
/// @param cell_info1 Cell permutation information for the trial
/// function mesh.
/// @param custom_data Custom user data pointer passed to the kernel.
template <dolfinx::scalar T>
void assemble_cells_matrix(
la::MatSet<T> auto mat_set, mdspan2_t x_dofmap,
Expand All @@ -74,7 +76,8 @@
std::span<const std::int8_t> bc1, FEkernel<T> auto kernel,
md::mdspan<const T, md::dextents<std::size_t, 2>> coeffs,
std::span<const T> constants, std::span<const std::uint32_t> cell_info0,
std::span<const std::uint32_t> cell_info1)
std::span<const std::uint32_t> cell_info1,
std::optional<void*> custom_data = std::nullopt)

Check failure on line 80 in cpp/dolfinx/fem/assemble_matrix_impl.h

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Replace this use of "void *" with a more meaningful type.

See more on https://sonarcloud.io/project/issues?id=FEniCS_dolfinx&issues=AZrb3rAQu-mtKnwcCd-i&open=AZrb3rAQu-mtKnwcCd-i&pullRequest=4013
{
if (cells.empty())
return;
Expand Down Expand Up @@ -109,7 +112,7 @@
// Tabulate tensor
std::ranges::fill(Ae, 0);
kernel(Ae.data(), &coeffs(c, 0), constants.data(), cdofs.data(), nullptr,
nullptr, nullptr);
nullptr, custom_data.value_or(nullptr));

// Compute A = P_0 \tilde{A} P_1^T (dof transformation)
P0(Ae, cell_info0, cell0, ndim1); // B = P0 \tilde{A}
Expand Down Expand Up @@ -198,6 +201,7 @@
/// function mesh.
/// @param[in] perms Entity permutation integer. Empty if entity
/// permutations are not required.
/// @param custom_data Custom user data pointer passed to the kernel.
template <dolfinx::scalar T>
void assemble_entities(
la::MatSet<T> auto mat_set, mdspan2_t x_dofmap,
Expand All @@ -221,7 +225,8 @@
md::mdspan<const T, md::dextents<std::size_t, 2>> coeffs,
std::span<const T> constants, std::span<const std::uint32_t> cell_info0,
std::span<const std::uint32_t> cell_info1,
md::mdspan<const std::uint8_t, md::dextents<std::size_t, 2>> perms)
md::mdspan<const std::uint8_t, md::dextents<std::size_t, 2>> perms,
std::optional<void*> custom_data = std::nullopt)

Check failure on line 229 in cpp/dolfinx/fem/assemble_matrix_impl.h

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Replace this use of "void *" with a more meaningful type.

See more on https://sonarcloud.io/project/issues?id=FEniCS_dolfinx&issues=AZrb3rAQu-mtKnwcCd-j&open=AZrb3rAQu-mtKnwcCd-j&pullRequest=4013
{
if (entities.empty())
return;
Expand Down Expand Up @@ -259,7 +264,7 @@
// Tabulate tensor
std::ranges::fill(Ae, 0);
kernel(Ae.data(), &coeffs(f, 0), constants.data(), cdofs.data(),
&local_entity, &perm, nullptr);
&local_entity, &perm, custom_data.value_or(nullptr));
P0(Ae, cell_info0, cell0, ndim1);
P1T(Ae, cell_info1, cell1, ndim0);

Expand Down Expand Up @@ -363,7 +368,8 @@
coeffs,
std::span<const T> constants, std::span<const std::uint32_t> cell_info0,
std::span<const std::uint32_t> cell_info1,
md::mdspan<const std::uint8_t, md::dextents<std::size_t, 2>> perms)
md::mdspan<const std::uint8_t, md::dextents<std::size_t, 2>> perms,
std::optional<void*> custom_data = std::nullopt)

Check failure on line 372 in cpp/dolfinx/fem/assemble_matrix_impl.h

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Replace this use of "void *" with a more meaningful type.

See more on https://sonarcloud.io/project/issues?id=FEniCS_dolfinx&issues=AZrb3rAQu-mtKnwcCd-k&open=AZrb3rAQu-mtKnwcCd-k&pullRequest=4013
{
if (facets.empty())
return;
Expand Down Expand Up @@ -440,7 +446,7 @@
: 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(),
local_facet.data(), perm.data(), nullptr);
local_facet.data(), perm.data(), custom_data.value_or(nullptr));

// Local element layout is a 2x2 block matrix with structure
//
Expand Down Expand Up @@ -605,12 +611,14 @@
std::span cells0 = a.domain_arg(IntegralType::cell, 0, i, cell_type_idx);
std::span cells1 = a.domain_arg(IntegralType::cell, 1, i, cell_type_idx);
auto& [coeffs, cstride] = coefficients.at({IntegralType::cell, i});
std::optional<void*> custom_data
= a.custom_data(IntegralType::cell, i, cell_type_idx);
assert(cells.size() * cstride == coeffs.size());
impl::assemble_cells_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, custom_data);
}

md::mdspan<const std::uint8_t, md::dextents<std::size_t, 2>> facet_perms;
Expand Down Expand Up @@ -646,6 +654,8 @@
assert(fn);
auto& [coeffs, cstride]
= coefficients.at({IntegralType::interior_facet, i});
std::optional<void*> custom_data
= a.custom_data(IntegralType::interior_facet, i, 0);

std::span facets = a.domain(IntegralType::interior_facet, i, 0);
std::span facets0 = a.domain_arg(IntegralType::interior_facet, 0, i, 0);
Expand All @@ -661,7 +671,7 @@
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, facet_perms);
cell_info0, cell_info1, facet_perms, custom_data);
}

for (auto itg_type : {fem::IntegralType::exterior_facet,
Expand All @@ -688,6 +698,7 @@
auto fn = a.kernel(itg_type, i, 0);
assert(fn);
auto& [coeffs, cstride] = coefficients.at({itg_type, i});
std::optional<void*> custom_data = a.custom_data(itg_type, i, 0);

std::span e = a.domain(itg_type, i, 0);
mdspanx2_t entities(e.data(), e.size() / 2, 2);
Expand All @@ -700,7 +711,7 @@
mat_set, x_dofmap, x, entities, {dofs0, bs0, entities0}, P0,
{dofs1, bs1, entities1}, P1T, bc0, bc1, fn,
md::mdspan(coeffs.data(), entities.extent(0), cstride), constants,
cell_info0, cell_info1, perms);
cell_info0, cell_info1, perms, custom_data);
}
}
}
Expand Down
26 changes: 17 additions & 9 deletions cpp/dolfinx/fem/assemble_scalar_impl.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,20 +17,22 @@
#include <dolfinx/mesh/Mesh.h>
#include <dolfinx/mesh/Topology.h>
#include <memory>
#include <optional>
#include <vector>

namespace dolfinx::fem::impl
{
/// Assemble functional over cells
template <dolfinx::scalar T>
T assemble_cells(mdspan2_t x_dofmap,

Check warning on line 27 in cpp/dolfinx/fem/assemble_scalar_impl.h

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

This function has 8 parameters, which is greater than the 7 authorized.

See more on https://sonarcloud.io/project/issues?id=FEniCS_dolfinx&issues=AZraT3LpqA6mqPYJkcJs&open=AZraT3LpqA6mqPYJkcJs&pullRequest=4013
md::mdspan<const scalar_value_t<T>,
md::extents<std::size_t, md::dynamic_extent, 3>>
x,
std::span<const std::int32_t> cells, FEkernel<T> auto fn,
std::span<const T> constants,
md::mdspan<const T, md::dextents<std::size_t, 2>> coeffs,
std::span<scalar_value_t<T>> cdofs_b)
std::span<scalar_value_t<T>> cdofs_b,
std::optional<void*> custom_data = std::nullopt)

Check failure on line 35 in cpp/dolfinx/fem/assemble_scalar_impl.h

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Replace this use of "void *" with a more meaningful type.

See more on https://sonarcloud.io/project/issues?id=FEniCS_dolfinx&issues=AZrb3q_eu-mtKnwcCd-f&open=AZrb3q_eu-mtKnwcCd-f&pullRequest=4013
{
T value(0);
if (cells.empty())
Expand All @@ -49,7 +51,7 @@
std::copy_n(&x(x_dofs[i], 0), 3, std::next(cdofs_b.begin(), 3 * i));

fn(&value, &coeffs(index, 0), constants.data(), cdofs_b.data(), nullptr,
nullptr, nullptr);
nullptr, custom_data.value_or(nullptr));
}

return value;
Expand Down Expand Up @@ -77,7 +79,8 @@
FEkernel<T> auto fn, std::span<const T> constants,
md::mdspan<const T, md::dextents<std::size_t, 2>> coeffs,
md::mdspan<const std::uint8_t, md::dextents<std::size_t, 2>> perms,
std::span<scalar_value_t<T>> cdofs_b)
std::span<scalar_value_t<T>> cdofs_b,
std::optional<void*> custom_data = std::nullopt)

Check failure on line 83 in cpp/dolfinx/fem/assemble_scalar_impl.h

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Replace this use of "void *" with a more meaningful type.

See more on https://sonarcloud.io/project/issues?id=FEniCS_dolfinx&issues=AZrb4afWc6ZwUjXdSccy&open=AZrb4afWc6ZwUjXdSccy&pullRequest=4013
{
T value(0);
if (entities.empty())
Expand All @@ -99,7 +102,7 @@
// Permutations
std::uint8_t perm = perms.empty() ? 0 : perms(cell, local_entity);
fn(&value, &coeffs(f, 0), constants.data(), cdofs_b.data(), &local_entity,
&perm, nullptr);
&perm, custom_data.value_or(nullptr));
}

return value;
Expand All @@ -120,7 +123,8 @@
md::dynamic_extent>>
coeffs,
md::mdspan<const std::uint8_t, md::dextents<std::size_t, 2>> perms,
std::span<scalar_value_t<T>> cdofs_b)
std::span<scalar_value_t<T>> cdofs_b,
std::optional<void*> custom_data = std::nullopt)

Check failure on line 127 in cpp/dolfinx/fem/assemble_scalar_impl.h

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Replace this use of "void *" with a more meaningful type.

See more on https://sonarcloud.io/project/issues?id=FEniCS_dolfinx&issues=AZrb4afWc6ZwUjXdSccz&open=AZrb4afWc6ZwUjXdSccz&pullRequest=4013
{
T value(0);
if (facets.empty())
Expand Down Expand Up @@ -150,7 +154,7 @@
: std::array{perms(cells[0], local_facet[0]),
perms(cells[1], local_facet[1])};
fn(&value, &coeffs(f, 0, 0), constants.data(), cdofs_b.data(),
local_facet.data(), perm.data(), nullptr);
local_facet.data(), perm.data(), custom_data.value_or(nullptr));
}

return value;
Expand Down Expand Up @@ -178,11 +182,12 @@
auto fn = M.kernel(IntegralType::cell, i, 0);
assert(fn);
auto& [coeffs, cstride] = coefficients.at({IntegralType::cell, i});
std::optional<void*> custom_data = M.custom_data(IntegralType::cell, i, 0);
std::span<const std::int32_t> cells = M.domain(IntegralType::cell, i, 0);
assert(cells.size() * cstride == coeffs.size());
value += impl::assemble_cells(
x_dofmap, x, cells, fn, constants,
md::mdspan(coeffs.data(), cells.size(), cstride), cdofs_b);
md::mdspan(coeffs.data(), cells.size(), cstride), cdofs_b, custom_data);
}

mesh::CellType cell_type = mesh->topology()->cell_type();
Expand All @@ -204,6 +209,8 @@
assert(fn);
auto& [coeffs, cstride]
= coefficients.at({IntegralType::interior_facet, i});
std::optional<void*> custom_data
= M.custom_data(IntegralType::interior_facet, i, 0);
std::span facets = M.domain(IntegralType::interior_facet, i, 0);

constexpr std::size_t num_adjacent_cells = 2;
Expand All @@ -220,7 +227,7 @@
md::mdspan<const T, md::extents<std::size_t, md::dynamic_extent, 2,
md::dynamic_extent>>(
coeffs.data(), facets.size() / shape1, 2, cstride),
facet_perms, cdofs_b);
facet_perms, cdofs_b, custom_data);
}

for (auto itg_type : {fem::IntegralType::exterior_facet,
Expand All @@ -236,6 +243,7 @@
auto fn = M.kernel(itg_type, i, 0);
assert(fn);
auto& [coeffs, cstride] = coefficients.at({itg_type, i});
std::optional<void*> custom_data = M.custom_data(itg_type, i, 0);

std::span entities = M.domain(itg_type, i, 0);

Expand All @@ -248,7 +256,7 @@
entities.data(), entities.size() / 2, 2),
fn, constants,
md::mdspan(coeffs.data(), entities.size() / 2, cstride), perms,
cdofs_b);
cdofs_b, custom_data);
}
}

Expand Down
Loading
Loading