Line data Source code
1 0 : // Distributed under the MIT License.
2 : // See LICENSE.txt for details.
3 :
4 : #pragma once
5 :
6 : #include <type_traits>
7 :
8 : #include "DataStructures/DataBox/DataBox.hpp"
9 : #include "DataStructures/DataVector.hpp"
10 : #include "DataStructures/Tensor/TypeAliases.hpp"
11 : #include "DataStructures/Variables.hpp"
12 : #include "Utilities/Gsl.hpp"
13 : #include "Utilities/TMPL.hpp"
14 :
15 : /// \cond
16 : namespace Frame {
17 : struct ElementLogical;
18 : struct Grid;
19 : struct Inertial;
20 : } // namespace Frame
21 : template <size_t Dim>
22 : struct Mesh;
23 : struct DataVector;
24 : /// \endcond
25 :
26 : namespace intrp::protocols {
27 : /*!
28 : * \brief A protocol for the type alias `compute_vars_to_interpolate` that can
29 : * potentially be found in an InterpolationTargetTag (potentially because an
30 : * InterpolationTargetTag does not require this type alias).
31 : *
32 : * \details A struct conforming to the `ComputeVarsToInterpolate` protocol must
33 : * have
34 : *
35 : * - a type alias `allowed_src_tags` which is a `tmpl::list` of tags from the
36 : * volume that can be used to compute quantities that will be interpolated
37 : * onto the target.
38 : *
39 : * - a type alias `required_src_tags` which is a `tmpl::list` of tags from the
40 : * volume that are necessary to compute quantities that will be interpolated
41 : * onto the target. This list must be a subset of `allowed_src_tags`.
42 : *
43 : * - a type alias `allowed_dest_tags<Frame>` which is a `tmpl::list` of tags on
44 : * the target that can be computed from the source tags.
45 : *
46 : * - a type alias `required_dest_tags<Frame>` which is a `tmpl::list` of tags on
47 : * the target that must be computed from the source tags. This list must be a
48 : * subset of `allowed_dest_tags<Frame>`
49 : *
50 : * - an `apply` function with at least one of the signatures in the example.
51 : * This apply function fills the `vars_to_interpolate_to_target` type alias
52 : * from the InterpolationTargetTag. Here `Dim` is `Metavariables::volume_dim`,
53 : * SrcFrame is typically `Frame::Inertial` and
54 : * TargetFrame is the frame of `vars_to_interpolate_to_target` from the
55 : * InterpolationTargetTag. The overload without Jacobians treats the case in
56 : * which TargetFrame is the same as SrcFrame.
57 : *
58 : * Here is an example of a class that conforms to this protocols:
59 : *
60 : * \snippet Helpers/ParallelAlgorithms/Interpolation/Examples.hpp ComputeVarsToInterpolate
61 : */
62 1 : struct ComputeVarsToInterpolate {
63 : template <typename ConformingType>
64 0 : struct test {
65 : template <size_t Dim>
66 0 : struct DummyTag : db::SimpleTag {
67 0 : using type = tnsr::a<DataVector, Dim, Frame::Grid>;
68 : };
69 : template <size_t Dim>
70 0 : using example_list = tmpl::list<DummyTag<Dim>>;
71 :
72 : template <typename T, size_t Dim, typename = std::void_t<>>
73 0 : struct has_signature_1 : std::false_type {};
74 :
75 : template <typename T, size_t Dim>
76 : struct has_signature_1<
77 : T, Dim,
78 : std::void_t<decltype(T::apply(
79 : std::declval<const gsl::not_null<Variables<example_list<Dim>>*>>(),
80 : std::declval<const Variables<example_list<Dim>>&>(),
81 : std::declval<const Mesh<Dim>&>()))>> : std::true_type {};
82 :
83 : template <typename T, size_t Dim, typename = std::void_t<>>
84 0 : struct has_signature_2 : std::false_type {};
85 :
86 : template <typename T, size_t Dim>
87 : struct has_signature_2<
88 : T, Dim,
89 : std::void_t<decltype(T::apply(
90 : std::declval<const gsl::not_null<Variables<example_list<Dim>>*>>(),
91 : std::declval<const Variables<example_list<Dim>>&>(),
92 : std::declval<const Mesh<Dim>&>(),
93 : std::declval<const Jacobian<DataVector, Dim, Frame::Grid,
94 : Frame::Inertial>&>(),
95 : std::declval<const InverseJacobian<DataVector, Dim, Frame::Grid,
96 : Frame::Inertial>&>(),
97 : std::declval<const Jacobian<DataVector, Dim, Frame::ElementLogical,
98 : Frame::Grid>&>(),
99 : std::declval<const InverseJacobian<
100 : DataVector, Dim, Frame::ElementLogical, Frame::Grid>&>(),
101 : std::declval<const tnsr::I<DataVector, Dim, Frame::Inertial>&>(),
102 : std::declval<const tnsr::I<DataVector, Dim, Frame::Grid>&>()))>>
103 : : std::true_type {};
104 :
105 : static_assert(has_signature_1<ConformingType, 1>::value or
106 : has_signature_2<ConformingType, 1>::value or
107 : has_signature_1<ConformingType, 2>::value or
108 : has_signature_2<ConformingType, 2>::value or
109 : has_signature_1<ConformingType, 3>::value or
110 : has_signature_2<ConformingType, 3>::value);
111 :
112 0 : using allowed_src_tags = typename ConformingType::allowed_src_tags;
113 0 : using required_src_tags = typename ConformingType::required_src_tags;
114 : static_assert(
115 : tmpl::size<tmpl::list_difference<required_src_tags,
116 : allowed_src_tags>>::value == 0,
117 : "Some of the required source tags are not in the allowed source tags.");
118 :
119 : // Checking this in the grid frame is just a choice, but it suffices to
120 : // check conformance.
121 0 : using allowed_dest_tags =
122 : typename ConformingType::template allowed_dest_tags<Frame::Grid>;
123 0 : using required_dest_tags =
124 : typename ConformingType::template required_dest_tags<Frame::Grid>;
125 : static_assert(tmpl::size<tmpl::list_difference<required_dest_tags,
126 : allowed_dest_tags>>::value ==
127 : 0,
128 : "Some of the required destination tags are not in the "
129 : "allowed destination tags.");
130 : };
131 : };
132 : } // namespace intrp::protocols
|