15 #include "smith/numerics/functional/geometric_factors.hpp"
16 #include "smith/numerics/functional/function_signature.hpp"
17 #include "smith/numerics/functional/domain_integral_kernels.hpp"
18 #include "smith/numerics/functional/boundary_integral_kernels.hpp"
19 #include "smith/numerics/functional/interior_face_integral_kernels.hpp"
20 #include "smith/numerics/functional/differentiate_wrt.hpp"
41 std::size_t num_trial_spaces = trial_space_indices.size();
43 jvp_.resize(num_trial_spaces);
46 for (uint32_t i = 0; i < num_trial_spaces; i++) {
66 void Mult(
double t,
const std::vector<mfem::BlockVector>& input_E, mfem::BlockVector& output_E,
67 uint32_t differentiation_index,
bool update_state)
const
75 for (
auto& [geometry, func] : kernels) {
80 func(t, inputs, output_E.GetBlock(geometry).ReadWrite(), update_state);
94 void GradientMult(
const mfem::BlockVector& dinput_E, mfem::BlockVector& doutput_E,
95 uint32_t differentiation_index)
const
102 func(dinput_E.GetBlock(geometry).Read(), doutput_E.GetBlock(geometry).ReadWrite());
115 uint32_t differentiation_index)
const
120 func(
view(K_e[geometry]));
134 if (which == i)
return true;
143 using eval_func = std::function<void(
double,
const std::vector<const double*>&,
double*,
bool)>;
155 std::vector<std::map<mfem::Geometry::Type, jacobian_vector_product_func> >
jvp_;
200 template <mfem::Geometry::Type geom,
int Q,
typename test,
typename... trials,
typename lambda_type,
201 typename qpt_data_type>
209 const double* positions = gf.
X.Read();
210 const double* jacobians = gf.
J.Read();
211 const uint32_t num_elements = uint32_t(gf.
num_elements);
214 std::shared_ptr<zero> dummy_derivatives;
215 integral.
evaluation_[geom] = domain_integral::evaluation_kernel<NO_DIFFERENTIATION, Q, geom>(
216 s, qf, positions, jacobians, qdata, dummy_derivatives, num_elements);
218 constexpr std::size_t num_args = s.num_args;
219 [[maybe_unused]]
static constexpr
int dim =
dimension_of(geom);
220 for_constexpr<num_args>([&](
auto index) {
226 using derivative_type = decltype(domain_integral::get_derivative_type<index, dim, trials...>(qf, qpt_data_type{}));
227 auto ptr = accelerator::make_shared_array<ExecutionSpace::CPU, derivative_type>(num_elements * qpts_per_element);
230 domain_integral::evaluation_kernel<index, Q, geom>(s, qf, positions, jacobians, qdata, ptr, num_elements);
232 integral.
jvp_[index][geom] = domain_integral::jacobian_vector_product_kernel<index, Q, geom>(s, ptr, num_elements);
234 domain_integral::element_gradient_kernel<index, Q, geom>(s, ptr, num_elements);
252 template <
typename s,
int Q,
int dim,
typename lambda_type,
typename qpt_data_type>
255 std::vector<uint32_t> argument_indices)
259 SLIC_ERROR_IF(domain.
type_ != Domain::Type::Elements,
"Error: trying to evaluate a domain integral over a boundary");
261 Integral integral(domain, argument_indices);
263 if constexpr (dim == 2) {
264 generate_kernels<mfem::Geometry::TRIANGLE, Q>(signature, integral, qf, qdata);
265 generate_kernels<mfem::Geometry::SQUARE, Q>(signature, integral, qf, qdata);
268 if constexpr (dim == 3) {
269 generate_kernels<mfem::Geometry::TETRAHEDRON, Q>(signature, integral, qf, qdata);
270 generate_kernels<mfem::Geometry::CUBE, Q>(signature, integral, qf, qdata);
289 template <mfem::Geometry::Type geom,
int Q,
typename test,
typename... trials,
typename lambda_type>
296 const double* positions = gf.
X.Read();
297 const double* jacobians = gf.
J.Read();
298 const uint32_t num_elements = uint32_t(gf.
num_elements);
301 std::shared_ptr<zero> dummy_derivatives;
302 integral.
evaluation_[geom] = boundary_integral::evaluation_kernel<NO_DIFFERENTIATION, Q, geom>(
303 s, qf, positions, jacobians, dummy_derivatives, num_elements);
305 constexpr std::size_t num_args = s.num_args;
306 [[maybe_unused]]
static constexpr
int dim =
dimension_of(geom);
307 for_constexpr<num_args>([&](
auto index) {
313 using derivative_type = decltype(boundary_integral::get_derivative_type<index, dim, trials...>(qf));
314 auto ptr = accelerator::make_shared_array<ExecutionSpace::CPU, derivative_type>(num_elements * qpts_per_element);
317 boundary_integral::evaluation_kernel<index, Q, geom>(s, qf, positions, jacobians, ptr, num_elements);
319 integral.
jvp_[index][geom] =
320 boundary_integral::jacobian_vector_product_kernel<index, Q, geom>(s, ptr, num_elements);
322 boundary_integral::element_gradient_kernel<index, Q, geom>(s, ptr, num_elements);
340 template <
typename s,
int Q,
int dim,
typename lambda_type>
345 SLIC_ERROR_IF(domain.
type_ != Domain::Type::BoundaryElements,
346 "Error: trying to evaluate a boundary integral over a non-boundary domain of integration");
348 Integral integral(domain, argument_indices);
350 if constexpr (dim == 1) {
351 generate_bdr_kernels<mfem::Geometry::SEGMENT, Q>(signature, integral, qf);
354 if constexpr (dim == 2) {
355 generate_bdr_kernels<mfem::Geometry::TRIANGLE, Q>(signature, integral, qf);
356 generate_bdr_kernels<mfem::Geometry::SQUARE, Q>(signature, integral, qf);
375 template <mfem::Geometry::Type geom,
int Q,
typename test,
typename... trials,
typename lambda_type>
382 const double* positions = gf.
X.Read();
383 const double* jacobians = gf.
J.Read();
384 const uint32_t num_elements = uint32_t(gf.
num_elements);
387 std::shared_ptr<zero> dummy_derivatives;
388 integral.
evaluation_[geom] = interior_face_integral::evaluation_kernel<NO_DIFFERENTIATION, Q, geom>(
389 s, qf, positions, jacobians, dummy_derivatives, num_elements);
391 constexpr std::size_t num_args = s.num_args;
392 [[maybe_unused]]
static constexpr
int dim =
dimension_of(geom);
393 for_constexpr<num_args>([&](
auto index) {
399 using derivative_type = decltype(interior_face_integral::get_derivative_type<index, dim, trials...>(qf));
400 auto ptr = accelerator::make_shared_array<ExecutionSpace::CPU, derivative_type>(num_elements * qpts_per_element);
403 interior_face_integral::evaluation_kernel<index, Q, geom>(s, qf, positions, jacobians, ptr, num_elements);
405 integral.
jvp_[index][geom] =
406 interior_face_integral::jacobian_vector_product_kernel<index, Q, geom>(s, ptr, num_elements);
408 interior_face_integral::element_gradient_kernel<index, Q, geom>(s, ptr, num_elements);
426 template <
typename s,
int Q,
int dim,
typename lambda_type>
431 SLIC_ERROR_IF(domain.
type_ != Domain::Type::InteriorFaces,
432 "Error: trying to evaluate a boundary integral over a non-boundary domain of integration");
434 Integral integral(domain, argument_indices);
436 if constexpr (dim == 1) {
437 generate_interior_face_kernels<mfem::Geometry::SEGMENT, Q>(signature, integral, qf);
440 if constexpr (dim == 2) {
441 generate_interior_face_kernels<mfem::Geometry::TRIANGLE, Q>(signature, integral, qf);
442 generate_interior_face_kernels<mfem::Geometry::SQUARE, Q>(signature, integral, qf);
This file contains the interface used for initializing/terminating any hardware accelerator-related f...
Accelerator functionality.
auto view(axom::Array< T, dim, space > &arr)
convenience function for creating a view of an axom::Array type
constexpr int num_quadrature_points(mfem::Geometry::Type g, int Q)
return the number of quadrature points in a Gauss-Legendre rule with parameter "Q"
void generate_kernels(FunctionSignature< test(trials...)> s, Integral &integral, const lambda_type &qf, std::shared_ptr< QuadratureData< qpt_data_type > > qdata)
function to generate kernels held by an Integral object of type "Domain", with a specific element typ...
constexpr int dimension_of(mfem::Geometry::Type g)
Returns the dimension of an element geometry.
axom::Array< T, dim, detail::execution_to_memory_v< space > > ExecArray
Alias for an Array corresponding to a particular ExecutionSpace.
void generate_bdr_kernels(FunctionSignature< test(trials...)> s, Integral &integral, const lambda_type &qf)
function to generate kernels held by an Integral object of type "BoundaryDomain", with a specific ele...
Integral MakeInteriorFaceIntegral(const Domain &domain, const lambda_type &qf, std::vector< uint32_t > argument_indices)
function to generate kernels held by an Integral object of type "Boundary", for all element types
Integral MakeBoundaryIntegral(const Domain &domain, const lambda_type &qf, std::vector< uint32_t > argument_indices)
function to generate kernels held by an Integral object of type "Boundary", for all element types
void generate_interior_face_kernels(FunctionSignature< test(trials...)> s, Integral &integral, const lambda_type &qf)
function to generate kernels held by an Integral object of type "InteriorFaceDomain",...
Integral MakeDomainIntegral(const Domain &domain, const lambda_type &qf, std::shared_ptr< QuadratureData< qpt_data_type > > qdata, std::vector< uint32_t > argument_indices)
function to generate kernels held by an Integral object of type "Domain", for all element types
axom::ArrayView< T, dim, detail::execution_to_memory_v< space > > ExecArrayView
Alias for an ArrayView corresponding to a particular ExecutionSpace.
a class for representing a geometric region that can be used for integration
Type type_
whether the elements in this domain are on the boundary or not
a class that computes and stores positions and jacobians at each quadrature point
std::size_t num_elements
the number of elements in the domain
mfem::Vector J
Jacobians of the element transformations at all quadrature points.
mfem::Vector X
Mapped (physical) coordinates of all quadrature points.
a class for representing a Integral calculations and their derivatives
std::map< mfem::Geometry::Type, GeometricFactors > geometric_factors_
the spatial positions and jacobians (dx_dxi) for each element type and quadrature point
std::function< void(double, const std::vector< const double * > &, double *, bool)> eval_func
signature of integral evaluation kernel
void GradientMult(const mfem::BlockVector &dinput_E, mfem::BlockVector &doutput_E, uint32_t differentiation_index) const
evaluate the jacobian(with respect to some trial space)-vector product of this integral
Integral(const Domain &d, std::vector< uint32_t > trial_space_indices)
Construct an "empty" Integral object, whose kernels are to be initialized later in one of the Make***...
std::map< mfem::Geometry::Type, eval_func > evaluation_
kernels for integral evaluation over each type of element
std::function< void(ExecArrayView< double, 3, ExecutionSpace::CPU >)> grad_func
signature of element gradient kernel
std::vector< std::map< mfem::Geometry::Type, eval_func > > evaluation_with_AD_
kernels for integral evaluation + derivative w.r.t. specified argument over each type of element
std::map< uint32_t, uint32_t > functional_to_integral_index_
a way of translating between the indices used by Functional and Integral to refer to the same trial s...
std::vector< std::map< mfem::Geometry::Type, jacobian_vector_product_func > > jvp_
kernels for jacobian-vector product of integral calculation
std::function< void(const double *, double *)> jacobian_vector_product_func
signature of element jvp kernel
bool DependsOn(uint32_t which) const
returns whether or not this integral depends on argument which
std::vector< std::map< mfem::Geometry::Type, grad_func > > element_gradient_
kernels for calculation of element jacobians
void ComputeElementGradients(std::map< mfem::Geometry::Type, ExecArray< double, 3, ExecutionSpace::CPU > > &K_e, uint32_t differentiation_index) const
evaluate the jacobian (with respect to some trial space) of this integral
std::vector< uint32_t > active_trial_spaces_
a list of the trial spaces that take part in this integrand
static constexpr std::size_t num_types
the number of different kinds of integration domains
Domain domain_
information about which elements to integrate over
void Mult(double t, const std::vector< mfem::BlockVector > &input_E, mfem::BlockVector &output_E, uint32_t differentiation_index, bool update_state) const
evaluate the integral, optionally storing q-function derivatives with respect to a specific trial spa...
A class for storing and access user-defined types at quadrature points.