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 <pup.h> 8 : 9 : #include "DataStructures/CachedTempBuffer.hpp" 10 : #include "DataStructures/DataBox/Prefixes.hpp" 11 : #include "DataStructures/Tensor/Tensor.hpp" 12 : #include "Elliptic/Systems/Poisson/Tags.hpp" 13 : #include "NumericalAlgorithms/LinearOperators/PartialDerivatives.hpp" 14 : #include "Options/String.hpp" 15 : #include "PointwiseFunctions/InitialDataUtilities/AnalyticSolution.hpp" 16 : #include "Utilities/ContainerHelpers.hpp" 17 : #include "Utilities/Gsl.hpp" 18 : #include "Utilities/TMPL.hpp" 19 : #include "Utilities/TaggedTuple.hpp" 20 : 21 : namespace Poisson::Solutions { 22 : 23 : namespace detail { 24 : template <typename DataType, size_t Dim> 25 : struct MoustacheVariables { 26 : using Cache = CachedTempBuffer< 27 : Tags::Field, 28 : ::Tags::deriv<Tags::Field, tmpl::size_t<Dim>, Frame::Inertial>, 29 : ::Tags::Flux<Tags::Field, tmpl::size_t<Dim>, Frame::Inertial>, 30 : ::Tags::FixedSource<Tags::Field>>; 31 : 32 : const tnsr::I<DataType, Dim>& x; 33 : 34 : void operator()(gsl::not_null<Scalar<DataType>*> field, 35 : gsl::not_null<Cache*> cache, Tags::Field /*meta*/) const; 36 : void operator()(gsl::not_null<tnsr::i<DataType, Dim>*> field_gradient, 37 : gsl::not_null<Cache*> cache, 38 : ::Tags::deriv<Tags::Field, tmpl::size_t<Dim>, 39 : Frame::Inertial> /*meta*/) const; 40 : void operator()(gsl::not_null<tnsr::I<DataType, Dim>*> flux_for_field, 41 : gsl::not_null<Cache*> cache, 42 : ::Tags::Flux<Tags::Field, tmpl::size_t<Dim>, 43 : Frame::Inertial> /*meta*/) const; 44 : void operator()(gsl::not_null<Scalar<DataType>*> fixed_source_for_field, 45 : gsl::not_null<Cache*> cache, 46 : ::Tags::FixedSource<Tags::Field> /*meta*/) const; 47 : }; 48 : } // namespace detail 49 : 50 : /*! 51 : * \brief A solution to the Poisson equation with a discontinuous first 52 : * derivative. 53 : * 54 : * \details This implements the solution \f$u(x,y)=x\left(1-x\right) 55 : * y\left(1-y\right)\left(\left(x-\frac{1}{2}\right)^2+\left(y- 56 : * \frac{1}{2}\right)^2\right)^\frac{3}{2}\f$ to the Poisson equation 57 : * in two dimensions, and 58 : * \f$u(x)=x\left(1-x\right)\left|x-\frac{1}{2}\right|^3\f$ in one dimension. 59 : * Their boundary conditions vanish on the square \f$[0,1]^2\f$ or interval 60 : * \f$[0,1]\f$, respectively. 61 : * 62 : * The corresponding source \f$f=-\Delta u\f$ has a discontinuous first 63 : * derivative at \f$\frac{1}{2}\f$. This accomplishes two things: 64 : * 65 : * - It makes it useful to test the convergence behaviour of our elliptic DG 66 : * solver. 67 : * - It makes it look like a moustache (at least in 1D). 68 : * 69 : * This solution is taken from \cite Stamm2010. 70 : */ 71 : template <size_t Dim> 72 1 : class Moustache : public elliptic::analytic_data::AnalyticSolution { 73 : public: 74 0 : using options = tmpl::list<>; 75 0 : static constexpr Options::String help{ 76 : "A solution with a discontinuous first derivative of its source at 1/2 " 77 : "that also happens to look like a moustache. It vanishes at zero and one " 78 : "in each dimension"}; 79 : 80 0 : Moustache() = default; 81 0 : Moustache(const Moustache&) = default; 82 0 : Moustache& operator=(const Moustache&) = default; 83 0 : Moustache(Moustache&&) = default; 84 0 : Moustache& operator=(Moustache&&) = default; 85 0 : ~Moustache() override = default; 86 0 : std::unique_ptr<elliptic::analytic_data::AnalyticSolution> get_clone() 87 : const override { 88 : return std::make_unique<Moustache>(*this); 89 : } 90 : 91 : /// \cond 92 : explicit Moustache(CkMigrateMessage* m) 93 : : elliptic::analytic_data::AnalyticSolution(m) {} 94 : using PUP::able::register_constructor; 95 : WRAPPED_PUPable_decl_template(Moustache); // NOLINT 96 : /// \endcond 97 : 98 : template <typename DataType, typename... RequestedTags> 99 0 : tuples::TaggedTuple<RequestedTags...> variables( 100 : const tnsr::I<DataType, Dim>& x, 101 : tmpl::list<RequestedTags...> /*meta*/) const { 102 : using VarsComputer = detail::MoustacheVariables<DataType, Dim>; 103 : typename VarsComputer::Cache cache{get_size(*x.begin())}; 104 : const VarsComputer computer{x}; 105 : return {cache.get_var(computer, RequestedTags{})...}; 106 : } 107 : }; 108 : 109 : /// \cond 110 : template <size_t Dim> 111 : PUP::able::PUP_ID Moustache<Dim>::my_PUP_ID = 0; // NOLINT 112 : /// \endcond 113 : 114 : template <size_t Dim> 115 0 : constexpr bool operator==(const Moustache<Dim>& /*lhs*/, 116 : const Moustache<Dim>& /*rhs*/) { 117 : return true; 118 : } 119 : 120 : template <size_t Dim> 121 0 : constexpr bool operator!=(const Moustache<Dim>& lhs, 122 : const Moustache<Dim>& rhs) { 123 : return not(lhs == rhs); 124 : } 125 : 126 : } // namespace Poisson::Solutions