Line data Source code
1 0 : // Distributed under the MIT License. 2 : // See LICENSE.txt for details. 3 : 4 : #pragma once 5 : 6 : #include <array> 7 : #include <cstddef> 8 : #include <limits> 9 : #include <pup.h> 10 : 11 : #include "DataStructures/CachedTempBuffer.hpp" 12 : #include "DataStructures/DataBox/Prefixes.hpp" 13 : #include "DataStructures/Tensor/Tensor.hpp" 14 : #include "Elliptic/Systems/Poisson/Tags.hpp" 15 : #include "NumericalAlgorithms/LinearOperators/PartialDerivatives.hpp" 16 : #include "Options/String.hpp" 17 : #include "PointwiseFunctions/InitialDataUtilities/AnalyticSolution.hpp" 18 : #include "Utilities/ContainerHelpers.hpp" 19 : #include "Utilities/Gsl.hpp" 20 : #include "Utilities/TMPL.hpp" 21 : #include "Utilities/TaggedTuple.hpp" 22 : 23 : namespace Poisson::Solutions { 24 : 25 : namespace detail { 26 : template <typename DataType, size_t Dim> 27 : struct ProductOfSinusoidsVariables { 28 : using Cache = CachedTempBuffer< 29 : Tags::Field, 30 : ::Tags::deriv<Tags::Field, tmpl::size_t<Dim>, Frame::Inertial>, 31 : ::Tags::Flux<Tags::Field, tmpl::size_t<Dim>, Frame::Inertial>, 32 : ::Tags::FixedSource<Tags::Field>>; 33 : 34 : const tnsr::I<DataType, Dim>& x; 35 : const std::array<double, Dim>& wave_numbers; 36 : 37 : void operator()(gsl::not_null<Scalar<DataType>*> field, 38 : gsl::not_null<Cache*> cache, Tags::Field /*meta*/) const; 39 : void operator()(gsl::not_null<tnsr::i<DataType, Dim>*> field_gradient, 40 : gsl::not_null<Cache*> cache, 41 : ::Tags::deriv<Tags::Field, tmpl::size_t<Dim>, 42 : Frame::Inertial> /*meta*/) const; 43 : void operator()(gsl::not_null<tnsr::I<DataType, Dim>*> flux_for_field, 44 : gsl::not_null<Cache*> cache, 45 : ::Tags::Flux<Tags::Field, tmpl::size_t<Dim>, 46 : Frame::Inertial> /*meta*/) const; 47 : void operator()(gsl::not_null<Scalar<DataType>*> fixed_source_for_field, 48 : gsl::not_null<Cache*> cache, 49 : ::Tags::FixedSource<Tags::Field> /*meta*/) const; 50 : }; 51 : } // namespace detail 52 : 53 : /*! 54 : * \brief A product of sinusoids \f$u(\boldsymbol{x}) = \prod_i \sin(k_i x_i)\f$ 55 : * 56 : * \details Solves the Poisson equation \f$-\Delta u(x)=f(x)\f$ for a source 57 : * \f$f(x)=\boldsymbol{k}^2\prod_i \sin(k_i x_i)\f$. 58 : */ 59 : template <size_t Dim> 60 1 : class ProductOfSinusoids : public elliptic::analytic_data::AnalyticSolution { 61 : public: 62 0 : struct WaveNumbers { 63 0 : using type = std::array<double, Dim>; 64 0 : static constexpr Options::String help{"The wave numbers of the sinusoids"}; 65 : }; 66 : 67 0 : using options = tmpl::list<WaveNumbers>; 68 0 : static constexpr Options::String help{ 69 : "A product of sinusoids that are taken of a wave number times the " 70 : "coordinate in each dimension."}; 71 : 72 0 : ProductOfSinusoids() = default; 73 0 : ProductOfSinusoids(const ProductOfSinusoids&) = default; 74 0 : ProductOfSinusoids& operator=(const ProductOfSinusoids&) = default; 75 0 : ProductOfSinusoids(ProductOfSinusoids&&) = default; 76 0 : ProductOfSinusoids& operator=(ProductOfSinusoids&&) = default; 77 0 : ~ProductOfSinusoids() override = default; 78 0 : std::unique_ptr<elliptic::analytic_data::AnalyticSolution> get_clone() 79 : const override { 80 : return std::make_unique<ProductOfSinusoids>(*this); 81 : } 82 : 83 : /// \cond 84 : explicit ProductOfSinusoids(CkMigrateMessage* m) 85 : : elliptic::analytic_data::AnalyticSolution(m) {} 86 : using PUP::able::register_constructor; 87 : WRAPPED_PUPable_decl_template(ProductOfSinusoids); // NOLINT 88 : /// \endcond 89 : 90 0 : explicit ProductOfSinusoids(const std::array<double, Dim>& wave_numbers) 91 : : wave_numbers_(wave_numbers) {} 92 : 93 : template <typename DataType, typename... RequestedTags> 94 0 : tuples::TaggedTuple<RequestedTags...> variables( 95 : const tnsr::I<DataType, Dim>& x, 96 : tmpl::list<RequestedTags...> /*meta*/) const { 97 : using VarsComputer = detail::ProductOfSinusoidsVariables<DataType, Dim>; 98 : typename VarsComputer::Cache cache{get_size(*x.begin())}; 99 : const VarsComputer computer{x, wave_numbers_}; 100 : return {cache.get_var(computer, RequestedTags{})...}; 101 : } 102 : 103 : // NOLINTNEXTLINE(google-runtime-references) 104 0 : void pup(PUP::er& p) override { 105 : elliptic::analytic_data::AnalyticSolution::pup(p); 106 : p | wave_numbers_; 107 : } 108 : 109 0 : const std::array<double, Dim>& wave_numbers() const { return wave_numbers_; } 110 : 111 : private: 112 0 : std::array<double, Dim> wave_numbers_{ 113 : {std::numeric_limits<double>::signaling_NaN()}}; 114 : }; 115 : 116 : /// \cond 117 : template <size_t Dim> 118 : PUP::able::PUP_ID ProductOfSinusoids<Dim>::my_PUP_ID = 0; // NOLINT 119 : /// \endcond 120 : 121 : template <size_t Dim> 122 0 : bool operator==(const ProductOfSinusoids<Dim>& lhs, 123 : const ProductOfSinusoids<Dim>& rhs) { 124 : return lhs.wave_numbers() == rhs.wave_numbers(); 125 : } 126 : 127 : template <size_t Dim> 128 0 : bool operator!=(const ProductOfSinusoids<Dim>& lhs, 129 : const ProductOfSinusoids<Dim>& rhs) { 130 : return not(lhs == rhs); 131 : } 132 : 133 : } // namespace Poisson::Solutions