Line data Source code
1 0 : // Distributed under the MIT License.
2 : // See LICENSE.txt for details.
3 :
4 : #pragma once
5 :
6 : #include <cstddef>
7 : #include <memory>
8 : #include <pup.h>
9 : #include <tuple>
10 : #include <type_traits>
11 : #include <utility>
12 :
13 : #include "DataStructures/TaggedTuple.hpp"
14 : #include "DataStructures/Tensor/Tensor.hpp"
15 : #include "Options/String.hpp"
16 : #include "ParallelAlgorithms/RayTracer/BackgroundSpacetimes/BackgroundSpacetime.hpp"
17 : #include "PointwiseFunctions/GeneralRelativity/DerivativeSpatialMetric.hpp"
18 : #include "PointwiseFunctions/GeneralRelativity/Tags.hpp"
19 : #include "Utilities/PrettyType.hpp"
20 : #include "Utilities/Serialization/CharmPupable.hpp"
21 : #include "Utilities/TMPL.hpp"
22 : #include "Utilities/TupleSlice.hpp"
23 :
24 : namespace ray_tracing {
25 :
26 : /// Analytic background spacetime from a GR or GRMHD solution.
27 : template <typename SolutionType>
28 1 : class WrappedGr : public BackgroundSpacetime {
29 : public:
30 0 : using options = typename SolutionType::options;
31 0 : static constexpr Options::String help = SolutionType::help;
32 0 : static std::string name() { return pretty_type::name<SolutionType>(); }
33 :
34 0 : WrappedGr() = default;
35 0 : WrappedGr(const WrappedGr& /*rhs*/) = default;
36 0 : WrappedGr& operator=(const WrappedGr& /*rhs*/) = default;
37 0 : WrappedGr(WrappedGr&& /*rhs*/) = default;
38 0 : WrappedGr& operator=(WrappedGr&& /*rhs*/) = default;
39 0 : ~WrappedGr() override = default;
40 :
41 : template <typename Arg1, typename Arg2, typename... Args>
42 : requires(tmpl::size<options>::value > 0)
43 0 : WrappedGr(Arg1&& /*arg1*/, Arg2&& arg2, Args&&... args)
44 : : wrapped_solution_(
45 : // Some gymnastics so this works with option parsing: skip the first
46 : // argument (ParseOptions) and last two arguments (context,
47 : // Metavars), then forward the rest to construct the SolutionType.
48 : std::apply(
49 : [](auto&&... forwarded_args) {
50 : return SolutionType(std::forward<decltype(forwarded_args)>(
51 : forwarded_args)...);
52 : },
53 : tuple_slice<0, sizeof...(Args) - 1>(std::forward_as_tuple(
54 : std::forward<Arg2>(arg2), std::forward<Args>(args)...)))) {}
55 :
56 0 : explicit WrappedGr(SolutionType wrapped_solution)
57 : : wrapped_solution_(std::move(wrapped_solution)) {}
58 :
59 0 : const auto& wrapped_solution() const { return wrapped_solution_; }
60 :
61 1 : auto get_clone() const -> std::unique_ptr<BackgroundSpacetime> override {
62 : return std::make_unique<WrappedGr<SolutionType>>(*this);
63 : }
64 :
65 : /// \cond
66 : explicit WrappedGr(CkMigrateMessage* msg) : BackgroundSpacetime(msg) {}
67 : using PUP::able::register_constructor;
68 : WRAPPED_PUPable_decl_template(WrappedGr);
69 : /// \endcond
70 :
71 0 : tuples::tagged_tuple_from_typelist<tags> variables(
72 : const tnsr::I<DataType, Dim, Frame>& x, double t,
73 : const std::optional<gsl::not_null<std::vector<size_t>*>> /*block_order*/ =
74 : std::nullopt) const override {
75 : // Tags that we retrieve from the solution. Gets the deriv(SpatialMetric)
76 : // instead of deriv(InvSpatialMetric) because the latter isn't available.
77 : using retrieve_tags =
78 : tmpl::replace<tags, DerivInvSpatialMetric, DerivSpatialMetric>;
79 : auto intermediate_vars = wrapped_solution_.variables(x, t, retrieve_tags{});
80 : tuples::tagged_tuple_from_typelist<tags> result{};
81 : // Compute the deriv(InvSpatialMetric) from the deriv(SpatialMetric)
82 : gr::deriv_inverse_spatial_metric(
83 : make_not_null(&get<DerivInvSpatialMetric>(result)),
84 : get<gr::Tags::InverseSpatialMetric<DataType, Dim, Frame>>(
85 : intermediate_vars),
86 : get<DerivSpatialMetric>(intermediate_vars));
87 : tmpl::for_each<tmpl::remove<retrieve_tags, DerivSpatialMetric>>(
88 : [&result, &intermediate_vars](auto tag_v) {
89 : using tag = tmpl::type_from<decltype(tag_v)>;
90 : get<tag>(result) = std::move(get<tag>(intermediate_vars));
91 : });
92 : return result;
93 : }
94 :
95 : // NOLINTNEXTLINE(google-runtime-references)
96 0 : void pup(PUP::er& p) override {
97 : BackgroundSpacetime::pup(p);
98 : p | wrapped_solution_;
99 : }
100 :
101 0 : friend bool operator==(const WrappedGr& lhs, const WrappedGr& rhs) {
102 : return lhs.wrapped_solution_ == rhs.wrapped_solution_;
103 : }
104 :
105 : private:
106 0 : SolutionType wrapped_solution_;
107 : };
108 :
109 : template <typename SolutionType>
110 0 : bool operator!=(const WrappedGr<SolutionType>& lhs,
111 : const WrappedGr<SolutionType>& rhs) {
112 : return not(lhs == rhs);
113 : }
114 :
115 : /// \cond
116 : template <typename SolutionType>
117 : PUP::able::PUP_ID WrappedGr<SolutionType>::my_PUP_ID = 0; // NOLINT
118 : /// \endcond
119 :
120 : } // namespace ray_tracing
|