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/Tensor/Tensor.hpp" 14 : #include "Options/String.hpp" 15 : #include "ParallelAlgorithms/RayTracer/BackgroundSpacetimes/BackgroundSpacetime.hpp" 16 : #include "PointwiseFunctions/GeneralRelativity/DerivativeSpatialMetric.hpp" 17 : #include "PointwiseFunctions/GeneralRelativity/Tags.hpp" 18 : #include "Utilities/PrettyType.hpp" 19 : #include "Utilities/Serialization/CharmPupable.hpp" 20 : #include "Utilities/TMPL.hpp" 21 : #include "Utilities/TaggedTuple.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