MapInstantiationMacros.hpp
1 // Distributed under the MIT License.
2 // See LICENSE.txt for details.
3 
4 #pragma once
5 
6 #include <boost/optional.hpp>
7 #include <boost/preprocessor/punctuation/comma_if.hpp>
8 #include <boost/preprocessor/repetition/repeat.hpp>
9 #include <boost/preprocessor/tuple/elem.hpp>
10 #include <boost/preprocessor/tuple/enum.hpp>
11 #include <boost/preprocessor/tuple/size.hpp>
12 #include <memory>
13 #include <pup.h>
14 #include <string>
15 #include <tuple>
16 #include <unordered_map>
17 #include <utility>
18 
21 #include "Domain/CoordinateMaps/CoordinateMap.tpp"
22 #include "Domain/FunctionsOfTime/FunctionOfTime.hpp"
23 #include "Utilities/GenerateInstantiations.hpp"
24 
25 #define INSTANTIATE_COORD_MAP_DETAIL_GET_MAPS(data) \
26  BOOST_PP_TUPLE_ENUM(BOOST_PP_TUPLE_ELEM(0, data))
27 #define INSTANTIATE_COORD_MAP_DETAIL_GET_MAPS_DIM(data) \
28  BOOST_PP_TUPLE_ELEM(BOOST_PP_TUPLE_SIZE(BOOST_PP_TUPLE_ELEM(0, data)), 0, \
29  BOOST_PP_TUPLE_ELEM(0, data))::dim
30 #define INSTANTIATE_COORD_MAP_DETAILINSERT_SIZE(z, n, _) BOOST_PP_COMMA_IF(n) n
31 
32 #define INSTANTIATE_COORD_MAP_DETAIL_GET_FILLED_INDEX_SEQUENCE(data) \
33  BOOST_PP_REPEAT(BOOST_PP_TUPLE_SIZE(BOOST_PP_TUPLE_ELEM(0, data)), \
34  INSTANTIATE_COORD_MAP_DETAILINSERT_SIZE, _)
35 
36 #define INSTANTIATE_COORD_MAP_DETAIL_GET_SOURCE_FRAME(data) \
37  BOOST_PP_TUPLE_ELEM(1, data)
38 
39 #define INSTANTIATE_COORD_MAP_DETAIL_GET_TARGET_FRAME(data) \
40  BOOST_PP_TUPLE_ELEM(2, data)
41 
42 #define INSTANTIATE_COORD_MAP_DETAIL_DTYPE(data) BOOST_PP_TUPLE_ELEM(3, data)
43 
44 /*!
45  * \ingroup ComputationalDomainGroup
46  * \brief Generate instantiations of member functions of the `CoordinateMap`
47  * class template.
48  *
49  * Called as follows:
50  *
51  * \code
52  * using Affine2d =
53  * domain::CoordinateMaps::ProductOf2Maps<domain::CoordinateMaps::Affine,
54  * domain::CoordinateMaps::Affine>;
55  * using Affine3d =
56  * domain::CoordinateMaps::ProductOf3Maps<domain::CoordinateMaps::Affine,
57  * domain::CoordinateMaps::Affine,
58  * domain::CoordinateMaps::Affine>;
59  *
60  * GENERATE_INSTANTIATIONS(INSTANTIATE_MAPS_SIMPLE_FUNCTIONS,
61  * ((Affine2d), (Affine3d)), (Frame::Logical),
62  * (Frame::Grid, Frame::Inertial))
63  * \endcode
64  *
65  * The first tuple passed to `GENERATE_INSTANTIATIONS` has a bunch of tuples in
66  * it that is the list of maps being composed. The reason for defining the type
67  * aliases `Affine2d` and `Affine3d` is that otherwise the number of maps being
68  * composed is calculated incorrectly. The second tuple contains the source
69  * frames for the map. The third tuple passed to `GENERATE_INSTANTIATIONS`
70  * contains the target frames to instantiate for, typically `Frame::Grid` and
71  * `Frame::Inertial`.
72  *
73  * Instantiates:
74  * - `get_to_grid_frame_impl`
75  * - `inverse_impl`
76  * - `class CoordinateMap`
77  */
78 #define INSTANTIATE_MAPS_SIMPLE_FUNCTIONS(_, data) \
79  template std::unique_ptr<domain::CoordinateMapBase< \
80  INSTANTIATE_COORD_MAP_DETAIL_GET_SOURCE_FRAME(data), Frame::Grid, \
81  INSTANTIATE_COORD_MAP_DETAIL_GET_MAPS_DIM(data)>> \
82  domain::CoordinateMap< \
83  INSTANTIATE_COORD_MAP_DETAIL_GET_SOURCE_FRAME(data), \
84  INSTANTIATE_COORD_MAP_DETAIL_GET_TARGET_FRAME(data), \
85  INSTANTIATE_COORD_MAP_DETAIL_GET_MAPS(data)>:: \
86  get_to_grid_frame_impl( \
87  std::integer_sequence< \
88  unsigned long, \
89  INSTANTIATE_COORD_MAP_DETAIL_GET_FILLED_INDEX_SEQUENCE( \
90  data)>) const noexcept; \
91  template boost::optional< \
92  tnsr::I<double, INSTANTIATE_COORD_MAP_DETAIL_GET_MAPS_DIM(data), \
93  INSTANTIATE_COORD_MAP_DETAIL_GET_SOURCE_FRAME(data)>> \
94  domain::CoordinateMap<INSTANTIATE_COORD_MAP_DETAIL_GET_SOURCE_FRAME(data), \
95  INSTANTIATE_COORD_MAP_DETAIL_GET_TARGET_FRAME(data), \
96  INSTANTIATE_COORD_MAP_DETAIL_GET_MAPS(data)>:: \
97  inverse_impl( \
98  tnsr::I<double, INSTANTIATE_COORD_MAP_DETAIL_GET_MAPS_DIM(data), \
99  INSTANTIATE_COORD_MAP_DETAIL_GET_TARGET_FRAME(data)>&&, \
100  double, \
101  const std::unordered_map< \
102  std::string, \
103  std::unique_ptr<domain::FunctionsOfTime::FunctionOfTime>>&, \
104  std::index_sequence< \
105  INSTANTIATE_COORD_MAP_DETAIL_GET_FILLED_INDEX_SEQUENCE( \
106  data)> /*meta*/) const noexcept; \
107  template class domain::CoordinateMap< \
108  INSTANTIATE_COORD_MAP_DETAIL_GET_SOURCE_FRAME(data), \
109  INSTANTIATE_COORD_MAP_DETAIL_GET_TARGET_FRAME(data), \
110  INSTANTIATE_COORD_MAP_DETAIL_GET_MAPS(data)>;
111 
112 /*!
113  * \ingroup ComputationalDomainGroup
114  * \brief Generate instantiations of member functions of the `CoordinateMap`
115  * class template.
116  *
117  * Called as follows:
118  *
119  * \code
120  * using Affine2d =
121  * domain::CoordinateMaps::ProductOf2Maps<domain::CoordinateMaps::Affine,
122  * domain::CoordinateMaps::Affine>;
123  * using Affine3d =
124  * domain::CoordinateMaps::ProductOf3Maps<domain::CoordinateMaps::Affine,
125  * domain::CoordinateMaps::Affine,
126  * domain::CoordinateMaps::Affine>;
127  *
128  * GENERATE_INSTANTIATIONS(INSTANTIATE_MAPS_DATA_TYPE_FUNCTIONS,
129  * ((Affine2d), (Affine3d)), (Frame::Logical),
130  * (Frame::Grid, Frame::Inertial),
131  * (double, DataVector))
132  * \endcode
133  *
134  * The first tuple passed to `GENERATE_INSTANTIATIONS` has a bunch of tuples in
135  * it that is the list of maps being composed. The reason for defining the type
136  * aliases `Affine2d` and `Affine3d` is that otherwise the number of maps being
137  * composed is calculated incorrectly. The second tuple contains the source
138  * frames for the map. The third tuple passed to `GENERATE_INSTANTIATIONS`
139  * contains the target frames to instantiate for, typically `Frame::Grid` and
140  * `Frame::Inertial`. The last tuple is the data types for which to instantiate
141  * the functions, usually `double` and `DataVector`.
142  *
143  * Instantiates:
144  * - `call_impl`
145  * - `inv_jacobian_impl`
146  * - `jacobian_impl`
147  * - `coords_frame_velocity_jacobians_impl`
148  */
149 #define INSTANTIATE_MAPS_DATA_TYPE_FUNCTIONS(_, data) \
150  template tnsr::I<INSTANTIATE_COORD_MAP_DETAIL_DTYPE(data), \
151  INSTANTIATE_COORD_MAP_DETAIL_GET_MAPS_DIM(data), \
152  INSTANTIATE_COORD_MAP_DETAIL_GET_TARGET_FRAME(data)> \
153  domain::CoordinateMap<INSTANTIATE_COORD_MAP_DETAIL_GET_SOURCE_FRAME(data), \
154  INSTANTIATE_COORD_MAP_DETAIL_GET_TARGET_FRAME(data), \
155  INSTANTIATE_COORD_MAP_DETAIL_GET_MAPS(data)>:: \
156  call_impl( \
157  tnsr::I<INSTANTIATE_COORD_MAP_DETAIL_DTYPE(data), \
158  INSTANTIATE_COORD_MAP_DETAIL_GET_MAPS_DIM(data), \
159  INSTANTIATE_COORD_MAP_DETAIL_GET_SOURCE_FRAME(data)>&&, \
160  double, \
161  const std::unordered_map< \
162  std::string, \
163  std::unique_ptr<domain::FunctionsOfTime::FunctionOfTime>>&, \
164  std::integer_sequence< \
165  unsigned long, \
166  INSTANTIATE_COORD_MAP_DETAIL_GET_FILLED_INDEX_SEQUENCE(data)>) \
167  const; \
168  template InverseJacobian< \
169  INSTANTIATE_COORD_MAP_DETAIL_DTYPE(data), \
170  INSTANTIATE_COORD_MAP_DETAIL_GET_MAPS_DIM(data), \
171  INSTANTIATE_COORD_MAP_DETAIL_GET_SOURCE_FRAME(data), \
172  INSTANTIATE_COORD_MAP_DETAIL_GET_TARGET_FRAME(data)> \
173  domain::CoordinateMap<INSTANTIATE_COORD_MAP_DETAIL_GET_SOURCE_FRAME(data), \
174  INSTANTIATE_COORD_MAP_DETAIL_GET_TARGET_FRAME(data), \
175  INSTANTIATE_COORD_MAP_DETAIL_GET_MAPS(data)>:: \
176  inv_jacobian_impl( \
177  tnsr::I<INSTANTIATE_COORD_MAP_DETAIL_DTYPE(data), \
178  INSTANTIATE_COORD_MAP_DETAIL_GET_MAPS_DIM(data), \
179  INSTANTIATE_COORD_MAP_DETAIL_GET_SOURCE_FRAME(data)>&&, \
180  double, \
181  const std::unordered_map< \
182  std::string, \
183  std::unique_ptr<domain::FunctionsOfTime::FunctionOfTime>>&) \
184  const; \
185  template Jacobian<INSTANTIATE_COORD_MAP_DETAIL_DTYPE(data), \
186  INSTANTIATE_COORD_MAP_DETAIL_GET_MAPS_DIM(data), \
187  INSTANTIATE_COORD_MAP_DETAIL_GET_SOURCE_FRAME(data), \
188  INSTANTIATE_COORD_MAP_DETAIL_GET_TARGET_FRAME(data)> \
189  domain::CoordinateMap<INSTANTIATE_COORD_MAP_DETAIL_GET_SOURCE_FRAME(data), \
190  INSTANTIATE_COORD_MAP_DETAIL_GET_TARGET_FRAME(data), \
191  INSTANTIATE_COORD_MAP_DETAIL_GET_MAPS(data)>:: \
192  jacobian_impl( \
193  tnsr::I<INSTANTIATE_COORD_MAP_DETAIL_DTYPE(data), \
194  INSTANTIATE_COORD_MAP_DETAIL_GET_MAPS_DIM(data), \
195  INSTANTIATE_COORD_MAP_DETAIL_GET_SOURCE_FRAME(data)>&&, \
196  double, \
197  const std::unordered_map< \
198  std::string, \
199  std::unique_ptr<domain::FunctionsOfTime::FunctionOfTime>>&) \
200  const; \
201  template std::tuple< \
202  tnsr::I<INSTANTIATE_COORD_MAP_DETAIL_DTYPE(data), \
203  INSTANTIATE_COORD_MAP_DETAIL_GET_MAPS_DIM(data), \
204  INSTANTIATE_COORD_MAP_DETAIL_GET_TARGET_FRAME(data)>, \
205  InverseJacobian<INSTANTIATE_COORD_MAP_DETAIL_DTYPE(data), \
206  INSTANTIATE_COORD_MAP_DETAIL_GET_MAPS_DIM(data), \
207  INSTANTIATE_COORD_MAP_DETAIL_GET_SOURCE_FRAME(data), \
208  INSTANTIATE_COORD_MAP_DETAIL_GET_TARGET_FRAME(data)>, \
209  Jacobian<INSTANTIATE_COORD_MAP_DETAIL_DTYPE(data), \
210  INSTANTIATE_COORD_MAP_DETAIL_GET_MAPS_DIM(data), \
211  INSTANTIATE_COORD_MAP_DETAIL_GET_SOURCE_FRAME(data), \
212  INSTANTIATE_COORD_MAP_DETAIL_GET_TARGET_FRAME(data)>, \
213  tnsr::I<INSTANTIATE_COORD_MAP_DETAIL_DTYPE(data), \
214  INSTANTIATE_COORD_MAP_DETAIL_GET_MAPS_DIM(data), \
215  INSTANTIATE_COORD_MAP_DETAIL_GET_TARGET_FRAME(data)>> \
216  domain::CoordinateMap<INSTANTIATE_COORD_MAP_DETAIL_GET_SOURCE_FRAME(data), \
217  INSTANTIATE_COORD_MAP_DETAIL_GET_TARGET_FRAME(data), \
218  INSTANTIATE_COORD_MAP_DETAIL_GET_MAPS(data)>:: \
219  coords_frame_velocity_jacobians_impl( \
220  tnsr::I<INSTANTIATE_COORD_MAP_DETAIL_DTYPE(data), \
221  INSTANTIATE_COORD_MAP_DETAIL_GET_MAPS_DIM(data), \
222  INSTANTIATE_COORD_MAP_DETAIL_GET_SOURCE_FRAME(data)>, \
223  double, \
224  const std::unordered_map< \
225  std::string, \
226  std::unique_ptr<domain::FunctionsOfTime::FunctionOfTime>>&) \
227  const;
228 
229 /*!
230  * \ingroup ComputationalDomainGroup
231  * \brief Generate instantiations of member functions of the `CoordinateMap`
232  * class template.
233  *
234  * Called as follows:
235  *
236  * \code
237  * using Affine2d =
238  * domain::CoordinateMaps::ProductOf2Maps<domain::CoordinateMaps::Affine,
239  * domain::CoordinateMaps::Affine>;
240  * using Affine3d =
241  * domain::CoordinateMaps::ProductOf3Maps<domain::CoordinateMaps::Affine,
242  * domain::CoordinateMaps::Affine,
243  * domain::CoordinateMaps::Affine>;
244  *
245  * INSTANTIATE_MAPS_FUNCTIONS(((Affine2d), (Affine3d)), (Frame::Logical),
246  * (Frame::Grid, Frame::Inertial),
247  * (double, DataVector))
248  * \endcode
249  *
250  * The first tuple passed to `GENERATE_INSTANTIATIONS` has a bunch of tuples in
251  * it that is the list of maps being composed. The reason for defining the type
252  * aliases `Affine2d` and `Affine3d` is that otherwise the number of maps being
253  * composed is calculated incorrectly. The second tuple contains the source
254  * frames for the map. The third tuple passed to `GENERATE_INSTANTIATIONS`
255  * contains the frames to instantiate for, typically `Frame::Grid` and
256  * `Frame::Inertial`.
257  *
258  * Instantiates:
259  * - `get_to_grid_frame_impl`
260  * - `inverse_impl`
261  * - `class CoordinateMap`
262  * - `call_impl`
263  * - `inv_jacobian_impl`
264  * - `jacobian_impl`
265  * - `coords_frame_velocity_jacobians_impl`
266  */
267 #define INSTANTIATE_MAPS_FUNCTIONS(MAPS_TUPLE, SOURCE_FRAME, \
268  TARGET_FRAMES_TUPLE, TYPES_TUPLE) \
269  GENERATE_INSTANTIATIONS(INSTANTIATE_MAPS_SIMPLE_FUNCTIONS, MAPS_TUPLE, \
270  SOURCE_FRAME, TARGET_FRAMES_TUPLE) \
271  GENERATE_INSTANTIATIONS(INSTANTIATE_MAPS_DATA_TYPE_FUNCTIONS, MAPS_TUPLE, \
272  SOURCE_FRAME, TARGET_FRAMES_TUPLE, TYPES_TUPLE)
utility
tuple
CoordinateMap.hpp
memory
Tensor.hpp
unordered_map
string