POINT_CONTAINER¶
Description¶
The POINT_CONTAINER macro is used to define data containers for physical properties and kernels at quadrature points. It reduces code duplication by automatically generating accessor methods, constructors, operators, and printing functionality for point data.
Syntax¶
POINT_CONTAINER(field1, field2, ..., fieldN)
The macro accepts a variable number of field names that will be used to generate the data container’s member functions.
Generated Functions¶
For each field provided to the macro, the following functions are generated:
Accessor Methods: For each field, the macro generates both const and non-const accessors:
KOKKOS_INLINE_FUNCTION const value_type field1() const; KOKKOS_INLINE_FUNCTION value_type& field1();
Index Operators: Allow array-like access to the internal data:
KOKKOS_INLINE_FUNCTION const value_type operator[](const int i) const; KOKKOS_INLINE_FUNCTION value_type& operator[](const int i);
Constructors:
Default constructor
Variadic template constructor accepting individual values
Constructor accepting a pointer to values
Constructor accepting a single value to initialize all fields
Equality Operators:
Implementation of == and != operators for comparing containers
Print Functions:
Regular printing for scalar values
SIMD-aware printing for vectorized data
Behind the Scenes¶
The POINT_CONTAINER macro is a high-level interface that expands to several other macros:
#define POINT_CONTAINER(...) POINT_DATA_CONTAINER_SEQ(POINT_ARGS(__VA_ARGS__))
It uses Boost Preprocessor library to process the arguments and generate the appropriate code. The macro chain includes:
POINT_ARGS: Converts variadic arguments to a Boost PP sequencePOINT_DATA_CONTAINER_SEQ: Processes the sequence to create numbered fieldsPOINT_VALUE_ACCESSORS: Generates accessor methodsPOINT_CONSTRUCTOR: Creates constructorsPOINT_BOOLEAN_OPERATOR_DEFINITION: Implements comparison operatorsPOINT_OPERATOR_DEFINITION: Implements array-like accessPOINT_PRINTandPOINT_PRINT_SIMD: Implement printing functionality
Example Usage¶
Here’s an example from the elastic media implementation (core/specfem/point/properties.hpp):
template <specfem::dimension::type DimensionTag,
specfem::element::medium_tag MediumTag, bool UseSIMD>
struct data_container<
DimensionTag, MediumTag, specfem::element::property_tag::isotropic, UseSIMD,
std::enable_if_t<specfem::element::is_elastic<MediumTag>::value> >
: public PropertyAccessor<DimensionTag, MediumTag,
specfem::element::property_tag::isotropic, UseSIMD> {
using base_type = PropertyAccessor<DimensionTag, MediumTag,
specfem::element::property_tag::isotropic, UseSIMD>;
using value_type = typename base_type::value_type;
using simd = typename base_type::simd;
POINT_CONTAINER(rho, kappa, mu)
KOKKOS_INLINE_FUNCTION
const value_type lambdaplus2mu() const {
return kappa() + static_cast<value_type>(4.0 / 3.0) * mu();
}
KOKKOS_INLINE_FUNCTION
const value_type rho_vp() const { return rho() * lambdaplus2mu(); }
KOKKOS_INLINE_FUNCTION
const value_type rho_vs() const { return rho() * mu(); }
KOKKOS_INLINE_FUNCTION
const value_type lambda() const {
return kappa() - static_cast<value_type>(2.0 / 3.0) * mu();
}
};
In this example, the POINT_CONTAINER(rho, kappa, mu) macro generates all the necessary accessor methods and functions for the density (rho), bulk modulus (kappa), and shear modulus (mu) properties. The class then adds custom methods that build upon these basic properties to compute derived quantities like lambdaplus2mu, rho_vp, rho_vs, and lambda.