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