FOR_EACH_IN_PRODUCT¶
The FOR_EACH_IN_PRODUCT macro is a utility in SPECFEMPP for processing combinations of tags that represent different element dimensions, medium types, property types, boundary conditions, and connection types.
Description¶
This macro executes a specified operation for every combination in the Cartesian product of the provided tag sequences. It significantly reduces code duplication when implementing functionality across multiple specializations.
Syntax¶
FOR_EACH_IN_PRODUCT(
(DIMENSION_TAG(VALUES...), MEDIUM_TAG(VALUES...), ...),
OPERATION)
The first argument is a tuple of tag sequences, each defined by a macro that can be one of the following:
DIMENSION_TAG(VALUES...): Specifies the element dimensions (e.g.,DIM2,DIM3).MEDIUM_TAG(VALUES...): Specifies the medium types (e.g.,ACOUSTIC,ELASTIC_SH,ELASTIC_PSV).CONNECTION_TAG(VALUES...): Specifies the connection types (e.g.,WEAKLY_CONFORMING,NONCONFORMING).PROPERTY_TAG(VALUES...): Specifies the property types (e.g.,ISOTROPIC,ANISOTROPIC).BOUNDARY_TAG(VALUES...): Specifies the boundary conditions (e.g.,NONE,STACEY,COMPOSITE_STACEY_DIRICHLET).
The second argument OPERATION can be one of three types:
INSTANTIATE- For template instantiationDECLARE- For variable declarationA code block (with optional
CAPTURE)
Usage Patterns¶
Template Instantiation with INSTANTIATE¶
Used to explicitly instantiate templates for all combinations of the specified tags.
FOR_EACH_IN_PRODUCT(
(DIMENSION_TAG(DIM2),
MEDIUM_TAG(ELASTIC_PSV, ELASTIC_SH, ACOUSTIC, POROELASTIC, ELASTIC_PSV_T),
PROPERTY_TAG(ISOTROPIC, ANISOTROPIC, ISOTROPIC_COSSERAT),
BOUNDARY_TAG(NONE, ACOUSTIC_FREE_SURFACE, STACEY, COMPOSITE_STACEY_DIRICHLET)),
INSTANTIATE(
(template void specfem::compute::impl::compute_mass_matrix,
(_DIMENSION_TAG_, specfem::simulation::field_type::forward, 5,
_MEDIUM_TAG_, _PROPERTY_TAG_, _BOUNDARY_TAG_),
(const type_real &, const specfem::assembly::assembly &);)))
This expands to template instantiations for each combination of the specified tags. The placeholders _DIMENSION_TAG_, _MEDIUM_TAG_, etc. are substituted with the actual tags defined in the first argument.
Variable Declaration with DECLARE¶
Used to declare variables for each tag combination.
FOR_EACH_IN_PRODUCT(
(DIMENSION_TAG(DIM2),
MEDIUM_TAG(ACOUSTIC, ELASTIC_PSV)),
DECLARE((IndexViewType, elements),
(IndexViewType::HostMirror, h_elements)))
This generates declarations like
IndexViewType dim2_elements_acoustic;
IndexViewType::HostMirror dim2_h_elements_acoustic;
IndexViewType dim2_elements_elastic_psv;
IndexViewType::HostMirror dim2_h_elements_elastic_psv;
Code Execution with Code Blocks¶
The third usage pattern executes code blocks for each tag combination:
FOR_EACH_IN_PRODUCT(
(DIMENSION_TAG(DIM2),
MEDIUM_TAG(ELASTIC_PSV, ELASTIC_SH, ACOUSTIC, POROELASTIC, ELASTIC_PSV_T)),
{
if constexpr (dimension == _dimension_tag_ && medium == _medium_tag_) {
impl::divide_mass_matrix<dimension, wavefield, _medium_tag_>(assembly);
}
})
Inside the code, the current tags are accessible via references like _dimension_tag_ and _medium_tag_.
Optionally, you can capture existing variables using the CAPTURE macro:
FOR_EACH_IN_PRODUCT(
(DIMENSION_TAG(DIM2),
MEDIUM_TAG(ELASTIC_PSV, ELASTIC_SH, ACOUSTIC, POROELASTIC, ELASTIC_PSV_T)),
CAPTURE(elements, h_elements) {
// Code that uses elements and h_elements with type-specific logic
if (_medium_tag_ == medium_tag) {
return _elements_;
}
})
The variables inside the CAPTURE block are captured by reference as variables __elements__ and _h_elements_.
Tag Combinations¶
-
MEDIUM_TAGS_DIM2 ((DIMENSION_TAG_DIM2, MEDIUM_TAG_ELASTIC_PSV
))( \
(
DIMENSION_TAG_DIM2, MEDIUM_TAG_ELASTIC_SH))( \
(
DIMENSION_TAG_DIM2, MEDIUM_TAG_ELASTIC_PSV_T))( \
(
DIMENSION_TAG_DIM2, MEDIUM_TAG_ACOUSTIC))( \
(
DIMENSION_TAG_DIM2, MEDIUM_TAG_POROELASTIC))( \
(
DIMENSION_TAG_DIM2, MEDIUM_TAG_ELECTROMAGNETIC_TE))¶ Macro to generate a list of medium types.
-
MEDIUM_TAGS_DIM3 ((DIMENSION_TAG_DIM3, MEDIUM_TAG_ELASTIC
))( \
(
DIMENSION_TAG_DIM3, MEDIUM_TAG_ACOUSTIC))( \
(
DIMENSION_TAG_DIM3, MEDIUM_TAG_ELASTIC_SPIN))¶
-
MEDIUM_TAGS MEDIUM_TAGS_DIM2 MEDIUM_TAGS_DIM3¶
-
MATERIAL_SYSTEMS_DIM2 ((DIMENSION_TAG_DIM2, MEDIUM_TAG_ELASTIC_PSV, PROPERTY_TAG_ISOTROPIC, \
ATTENUATION_TAG_NONE))((DIMENSION_TAG_DIM2, MEDIUM_TAG_ELASTIC_PSV, \
PROPERTY_TAG_ANISOTROPIC, ATTENUATION_TAG_NONE
))( \
(
DIMENSION_TAG_DIM2, MEDIUM_TAG_ELASTIC_SH, PROPERTY_TAG_ISOTROPIC, \ ATTENUATION_TAG_NONE))( \
(
DIMENSION_TAG_DIM2, MEDIUM_TAG_ELASTIC_SH, PROPERTY_TAG_ANISOTROPIC, \ ATTENUATION_TAG_NONE))((DIMENSION_TAG_DIM2, MEDIUM_TAG_ELASTIC_PSV_T, \ PROPERTY_TAG_ISOTROPIC_COSSERAT, \ ATTENUATION_TAG_NONE))( \
(
DIMENSION_TAG_DIM2, MEDIUM_TAG_ACOUSTIC, PROPERTY_TAG_ISOTROPIC, \ ATTENUATION_TAG_NONE))((DIMENSION_TAG_DIM2, MEDIUM_TAG_POROELASTIC, \ PROPERTY_TAG_ISOTROPIC, ATTENUATION_TAG_NONE))( \
(
DIMENSION_TAG_DIM2, MEDIUM_TAG_ELECTROMAGNETIC_TE, \ PROPERTY_TAG_ISOTROPIC, ATTENUATION_TAG_NONE))( \
(
DIMENSION_TAG_DIM2, MEDIUM_TAG_ELASTIC_PSV, PROPERTY_TAG_ISOTROPIC, \ ATTENUATION_TAG_CONSTANT_ISOTROPIC))( \
(
DIMENSION_TAG_DIM2, MEDIUM_TAG_ELASTIC_PSV, PROPERTY_TAG_ANISOTROPIC, \ ATTENUATION_TAG_CONSTANT_ISOTROPIC))( \
(
DIMENSION_TAG_DIM2, MEDIUM_TAG_ELASTIC_SH, PROPERTY_TAG_ISOTROPIC, \ ATTENUATION_TAG_CONSTANT_ISOTROPIC))( \
(
DIMENSION_TAG_DIM2, MEDIUM_TAG_ELASTIC_SH, PROPERTY_TAG_ANISOTROPIC, \ ATTENUATION_TAG_CONSTANT_ISOTROPIC))( \
(
DIMENSION_TAG_DIM2, MEDIUM_TAG_ACOUSTIC, PROPERTY_TAG_ISOTROPIC, \ ATTENUATION_TAG_CONSTANT_ISOTROPIC))( \
(
DIMENSION_TAG_DIM2, MEDIUM_TAG_POROELASTIC, PROPERTY_TAG_ISOTROPIC, \ ATTENUATION_TAG_CONSTANT_ISOTROPIC))¶ Macro to generate a list of material systems.
-
MATERIAL_SYSTEMS_DIM3 ((DIMENSION_TAG_DIM3, MEDIUM_TAG_ELASTIC, PROPERTY_TAG_ISOTROPIC, \
ATTENUATION_TAG_NONE))((DIMENSION_TAG_DIM3, MEDIUM_TAG_ACOUSTIC, \
PROPERTY_TAG_ISOTROPIC, ATTENUATION_TAG_NONE
))( \
(
DIMENSION_TAG_DIM3, MEDIUM_TAG_ELASTIC, PROPERTY_TAG_ISOTROPIC, \ ATTENUATION_TAG_CONSTANT_ISOTROPIC))( \
(
DIMENSION_TAG_DIM3, MEDIUM_TAG_ACOUSTIC, PROPERTY_TAG_ISOTROPIC, \ ATTENUATION_TAG_CONSTANT_ISOTROPIC))( \
(
DIMENSION_TAG_DIM3, MEDIUM_TAG_ELASTIC_SPIN, \ PROPERTY_TAG_ISOTROPIC_COSSERAT, ATTENUATION_TAG_NONE))¶
-
MATERIAL_SYSTEMS MATERIAL_SYSTEMS_DIM2 MATERIAL_SYSTEMS_DIM3¶
-
MEDIUM_PROPERTY_SYSTEMS_DIM2 ((DIMENSION_TAG_DIM2, MEDIUM_TAG_ELASTIC_PSV, PROPERTY_TAG_ISOTROPIC
))( \
(
DIMENSION_TAG_DIM2, MEDIUM_TAG_ELASTIC_PSV, PROPERTY_TAG_ANISOTROPIC))( \
(
DIMENSION_TAG_DIM2, MEDIUM_TAG_ELASTIC_SH, PROPERTY_TAG_ISOTROPIC))( \
(
DIMENSION_TAG_DIM2, MEDIUM_TAG_ELASTIC_SH, PROPERTY_TAG_ANISOTROPIC))( \
(
DIMENSION_TAG_DIM2, MEDIUM_TAG_ELASTIC_PSV_T, \ PROPERTY_TAG_ISOTROPIC_COSSERAT))( \
(
DIMENSION_TAG_DIM2, MEDIUM_TAG_ACOUSTIC, PROPERTY_TAG_ISOTROPIC))( \
(
DIMENSION_TAG_DIM2, MEDIUM_TAG_POROELASTIC, PROPERTY_TAG_ISOTROPIC))( \
(
DIMENSION_TAG_DIM2, MEDIUM_TAG_ELECTROMAGNETIC_TE, \ PROPERTY_TAG_ISOTROPIC))¶ Macro to generate a list of medium-property systems (unique combinations of dimension, medium, and property tags, without attenuation). Derived from MATERIAL_SYSTEMS by removing the attenuation tag and deduplicating.
-
MEDIUM_PROPERTY_SYSTEMS_DIM3 ((DIMENSION_TAG_DIM3, MEDIUM_TAG_ELASTIC, PROPERTY_TAG_ISOTROPIC
))( \
(
DIMENSION_TAG_DIM3, MEDIUM_TAG_ACOUSTIC, PROPERTY_TAG_ISOTROPIC))( \
(
DIMENSION_TAG_DIM3, MEDIUM_TAG_ELASTIC_SPIN, \ PROPERTY_TAG_ISOTROPIC_COSSERAT))¶
-
MEDIUM_PROPERTY_SYSTEMS MEDIUM_PROPERTY_SYSTEMS_DIM2 MEDIUM_PROPERTY_SYSTEMS_DIM3¶
-
ELEMENT_TYPES_DIM2 ((DIMENSION_TAG_DIM2, MEDIUM_TAG_ELASTIC_PSV, PROPERTY_TAG_ISOTROPIC, \
BOUNDARY_TAG_NONE))((DIMENSION_TAG_DIM2, MEDIUM_TAG_ELASTIC_PSV, \
PROPERTY_TAG_ISOTROPIC, BOUNDARY_TAG_STACEY
))( \
(
DIMENSION_TAG_DIM2, MEDIUM_TAG_ELASTIC_SH, PROPERTY_TAG_ISOTROPIC, \ BOUNDARY_TAG_NONE))((DIMENSION_TAG_DIM2, MEDIUM_TAG_ELASTIC_SH, \ PROPERTY_TAG_ISOTROPIC, BOUNDARY_TAG_STACEY))( \
(
DIMENSION_TAG_DIM2, MEDIUM_TAG_ELASTIC_PSV_T, \ PROPERTY_TAG_ISOTROPIC_COSSERAT, BOUNDARY_TAG_NONE))( \
(
DIMENSION_TAG_DIM2, MEDIUM_TAG_ELASTIC_PSV_T, \ PROPERTY_TAG_ISOTROPIC_COSSERAT, \ BOUNDARY_TAG_STACEY))((DIMENSION_TAG_DIM2, MEDIUM_TAG_ACOUSTIC, \ PROPERTY_TAG_ISOTROPIC, BOUNDARY_TAG_NONE))( \
(
DIMENSION_TAG_DIM2, MEDIUM_TAG_ACOUSTIC, PROPERTY_TAG_ISOTROPIC, \ BOUNDARY_TAG_ACOUSTIC_FREE_SURFACE))( \
(
DIMENSION_TAG_DIM2, MEDIUM_TAG_ACOUSTIC, PROPERTY_TAG_ISOTROPIC, \ BOUNDARY_TAG_STACEY))((DIMENSION_TAG_DIM2, MEDIUM_TAG_ACOUSTIC, \ PROPERTY_TAG_ISOTROPIC, \ BOUNDARY_TAG_COMPOSITE_STACEY_DIRICHLET))( \
(
DIMENSION_TAG_DIM2, MEDIUM_TAG_ELASTIC_PSV, PROPERTY_TAG_ANISOTROPIC, \ BOUNDARY_TAG_NONE))((DIMENSION_TAG_DIM2, MEDIUM_TAG_ELASTIC_PSV, \ PROPERTY_TAG_ANISOTROPIC, BOUNDARY_TAG_STACEY))( \
(
DIMENSION_TAG_DIM2, MEDIUM_TAG_ELASTIC_SH, PROPERTY_TAG_ANISOTROPIC, \ BOUNDARY_TAG_NONE))((DIMENSION_TAG_DIM2, MEDIUM_TAG_ELASTIC_SH, \ PROPERTY_TAG_ANISOTROPIC, BOUNDARY_TAG_STACEY))( \
(
DIMENSION_TAG_DIM2, MEDIUM_TAG_POROELASTIC, PROPERTY_TAG_ISOTROPIC, \ BOUNDARY_TAG_NONE))((DIMENSION_TAG_DIM2, MEDIUM_TAG_POROELASTIC, \ PROPERTY_TAG_ISOTROPIC, BOUNDARY_TAG_STACEY))( \
(
DIMENSION_TAG_DIM2, MEDIUM_TAG_ELECTROMAGNETIC_TE, \ PROPERTY_TAG_ISOTROPIC, BOUNDARY_TAG_NONE))¶ Macro to generate a list of element types.
-
ELEMENT_TYPES_DIM3 ((DIMENSION_TAG_DIM3, MEDIUM_TAG_ELASTIC, PROPERTY_TAG_ISOTROPIC, \
BOUNDARY_TAG_NONE))((DIMENSION_TAG_DIM3, MEDIUM_TAG_ACOUSTIC, \
PROPERTY_TAG_ISOTROPIC, BOUNDARY_TAG_NONE
))( \
(
DIMENSION_TAG_DIM3, MEDIUM_TAG_ELASTIC_SPIN, \ PROPERTY_TAG_ISOTROPIC_COSSERAT, BOUNDARY_TAG_NONE))¶
-
ELEMENT_TYPES ELEMENT_TYPES_DIM2 ELEMENT_TYPES_DIM3¶