SpECTRE Documentation Coverage Report
Current view: top level - PointwiseFunctions/AnalyticSolutions/Elasticity - HalfSpaceMirror.hpp Coverage Total Hit
Commit: 0d1d717af84a81fb1284a20c4013708fe85cc2f0 Lines: 3.9 % 51 2
Test Date: 2026-10-22 17:29:42
Legend: Lines:     hit not hit

            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 <limits>
       8              : 
       9              : #include "DataStructures/CachedTempBuffer.hpp"
      10              : #include "DataStructures/DataBox/Prefixes.hpp"
      11              : #include "DataStructures/DataBox/Tag.hpp"
      12              : #include "DataStructures/DataVector.hpp"
      13              : #include "DataStructures/TaggedTuple.hpp"
      14              : #include "DataStructures/Tensor/Tensor.hpp"
      15              : #include "Elliptic/Systems/Elasticity/Tags.hpp"
      16              : #include "NumericalAlgorithms/Spectral/Mesh.hpp"
      17              : #include "Options/String.hpp"
      18              : #include "PointwiseFunctions/Elasticity/ConstitutiveRelations/IsotropicHomogeneous.hpp"
      19              : #include "PointwiseFunctions/InitialDataUtilities/AnalyticSolution.hpp"
      20              : #include "Utilities/ContainerHelpers.hpp"
      21              : #include "Utilities/ErrorHandling/Error.hpp"
      22              : #include "Utilities/Serialization/CharmPupable.hpp"
      23              : #include "Utilities/TMPL.hpp"
      24              : 
      25              : namespace Elasticity::Solutions {
      26              : 
      27              : namespace detail {
      28              : template <typename DataType>
      29              : struct HalfSpaceMirrorVariables {
      30              :   struct DisplacementR : db::SimpleTag {
      31              :     using type = Scalar<DataType>;
      32              :   };
      33              :   using Cache =
      34              :       CachedTempBuffer<DisplacementR, Tags::Displacement<3>, Tags::Strain<3>,
      35              :                        Tags::MinusStress<3>, Tags::PotentialEnergyDensity<3>,
      36              :                        ::Tags::FixedSource<Tags::Displacement<3>>>;
      37              : 
      38              :   const tnsr::I<DataType, 3>& x;
      39              :   const double beam_width;
      40              :   const ConstitutiveRelations::IsotropicHomogeneous<3>& constitutive_relation;
      41              :   const size_t integration_intervals;
      42              :   const double absolute_tolerance;
      43              :   const double relative_tolerance;
      44              : 
      45              :   void operator()(gsl::not_null<Scalar<DataType>*> displacement_r,
      46              :                   gsl::not_null<Cache*> cache, DisplacementR /*meta*/) const;
      47              :   void operator()(gsl::not_null<tnsr::I<DataType, 3>*> displacement,
      48              :                   gsl::not_null<Cache*> cache,
      49              :                   Tags::Displacement<3> /*meta*/) const;
      50              :   void operator()(gsl::not_null<tnsr::ii<DataType, 3>*> strain,
      51              :                   gsl::not_null<Cache*> cache, Tags::Strain<3> /*meta*/) const;
      52              :   void operator()(gsl::not_null<tnsr::II<DataType, 3>*> minus_stress,
      53              :                   gsl::not_null<Cache*> cache,
      54              :                   Tags::MinusStress<3> /*meta*/) const;
      55              :   void operator()(gsl::not_null<Scalar<DataType>*> potential_energy_density,
      56              :                   gsl::not_null<Cache*> cache,
      57              :                   Tags::PotentialEnergyDensity<3> /*meta*/) const;
      58              :   void operator()(
      59              :       gsl::not_null<tnsr::I<DataType, 3>*> fixed_source_for_displacement,
      60              :       gsl::not_null<Cache*> cache,
      61              :       ::Tags::FixedSource<Tags::Displacement<3>> /*meta*/) const;
      62              : };
      63              : }  // namespace detail
      64              : 
      65              : /*!
      66              :  * \brief The solution for a half-space mirror deformed by a laser beam.
      67              :  *
      68              :  * \details This solution is mapping (via the fluctuation dissipation theorem)
      69              :  * thermal noise to an elasticity problem where a normally incident and
      70              :  * axisymmetric laser beam with a Gaussian beam profile acts on the face of a
      71              :  * semi-infinite mirror. Here we assume the face to be at \f$z = 0\f$ and the
      72              :  * material to extend to \f$+\infty\f$ in the z-direction as well as for the
      73              :  * mirror diameter to be comparatively large to the `beam width`. The mirror
      74              :  * material is characterized by an isotropic homogeneous constitutive relation
      75              :  * \f$Y^{ijkl}\f$ (see
      76              :  * `Elasticity::ConstitutiveRelations::IsotropicHomogeneous`). In this scenario,
      77              :  * the auxiliary elastic problem has an applied pressure distribution equal to
      78              :  * the laser beam intensity profile \f$p(r)\f$ (see Eq. (11.94) and Eq. (11.95)
      79              :  * in \cite ThorneBlandford2017 with F = 1 and the time dependency dropped)
      80              :  *
      81              :  * \f{align}
      82              :  * T^{zr} &= T^{rz} = 0 \\
      83              :  * T^{zz} &= p(r) = \frac{e^{-\frac{r^2}{r_0^2}}}{\pi r_0^2}\text{.}
      84              :  * \f}
      85              :  *
      86              :  * in the form of a Neumann boundary condition to the face of the mirror. We
      87              :  * find that this stress in cylinder coordinates is produced by the displacement
      88              :  * field
      89              :  *
      90              :  * \f{align}
      91              :  * \xi_{r} &= \frac{1}{2 \mu} \int_0^{\infty} dk J_1(kr)e^{(-kz)}\left(1 -
      92              :  * \frac{\lambda + 2\mu}{\lambda + \mu} + kz \right) \tilde{p}(k) \\
      93              :  * \xi_{\phi} &= 0 \\
      94              :  * \xi_{z} &=  \frac{1}{2 \mu} \int_0^{\infty} dk J_0(kr)e^{(-kz)}\left(1 +
      95              :  * \frac{\mu}{\lambda + \mu} + kz \right) \tilde{p}(k)
      96              :  * \f}
      97              :  *
      98              :  * and the strain
      99              :  *
     100              :  * \f{align}
     101              :  * \Theta &= \frac{1}{2 \mu} \int_0^{\infty} dk
     102              :  * J_0(kr) k e^{(-kz)}\left(\frac{-2\mu}{\lambda + \mu}\right) \tilde{p}(k) \\
     103              :  * S_{rr} &= \Theta - S_{\phi\phi} - S_{zz} \\
     104              :  * S_{\phi\phi} &= \frac{\xi_{r}}{r} \\
     105              :  * S_{(rz)} &= -\frac{1}{2 \mu} \int_0^{\infty} dk J_1(kr) k e^{(-kz)}\left(kz
     106              :  * \right) \tilde{p}(k) \\
     107              :  * S_{zz} &= \frac{1}{2 \mu} \int_0^{\infty} dk
     108              :  * J_0(kr) k e^{(-kz)}\left(-\frac{\mu}{\lambda + \mu} - kz \right) \tilde{p}(k)
     109              :  * \f}
     110              :  *
     111              :  * (see Eqs. (11 a) - (11 c) and (13 a) - (13 e), with (13 c) swapped in favor
     112              :  * of (12 c) in \cite Lovelace2007tn), where \f$\tilde{p}(k)= \frac{1}{2\pi}
     113              :  * e^{-(\frac{kr_0}{2})^2}\f$ is the Hankel-Transform of the lasers intensity
     114              :  * profile and \f$ \Theta = \mathrm{Tr}(S)\f$ the materials expansion.
     115              :  *
     116              :  */
     117            1 : class HalfSpaceMirror : public elliptic::analytic_data::AnalyticSolution {
     118              :  public:
     119            0 :   using constitutive_relation_type =
     120              :       Elasticity::ConstitutiveRelations::IsotropicHomogeneous<3>;
     121              : 
     122            0 :   struct BeamWidth {
     123            0 :     using type = double;
     124            0 :     static constexpr Options::String help{
     125              :         "The lasers beam width r_0 with FWHM = 2*sqrt(ln 2)*r_0"};
     126            0 :     static type lower_bound() { return 0.0; }
     127              :   };
     128              : 
     129            0 :   struct Material {
     130            0 :     using type = constitutive_relation_type;
     131            0 :     static constexpr Options::String help{
     132              :         "The material properties of the beam"};
     133              :   };
     134              : 
     135            0 :   struct IntegrationIntervals {
     136            0 :     using type = size_t;
     137            0 :     static constexpr Options::String help{
     138              :         "Workspace size for numerical integrals. Increase if integrals fail to "
     139              :         "reach the prescribed tolerance at large distances relative to the "
     140              :         "beam width. The suggested values for workspace size and tolerances "
     141              :         "should accommodate distances of up to ~100 beam widths."};
     142            0 :     static type lower_bound() { return 1; }
     143            0 :     static type suggested_value() { return 350; }
     144              :   };
     145              : 
     146            0 :   struct AbsoluteTolerance {
     147            0 :     using type = double;
     148            0 :     static constexpr Options::String help{
     149              :         "Absolute tolerance for numerical integrals"};
     150            0 :     static type lower_bound() { return 0.; }
     151            0 :     static type suggested_value() { return 1e-12; }
     152              :   };
     153              : 
     154            0 :   struct RelativeTolerance {
     155            0 :     using type = double;
     156            0 :     static constexpr Options::String help{
     157              :         "Relative tolerance for numerical integrals"};
     158            0 :     static type lower_bound() { return 0.; }
     159            0 :     static type upper_bound() { return 1.; }
     160            0 :     static type suggested_value() { return 1e-10; }
     161              :   };
     162              : 
     163            0 :   using options = tmpl::list<BeamWidth, Material, IntegrationIntervals,
     164              :                              AbsoluteTolerance, RelativeTolerance>;
     165            0 :   static constexpr Options::String help{
     166              :       "A semi-infinite mirror on which a laser introduces stress perpendicular "
     167              :       "to the mirrors surface."};
     168              : 
     169            0 :   HalfSpaceMirror() = default;
     170            0 :   HalfSpaceMirror(const HalfSpaceMirror&) = default;
     171            0 :   HalfSpaceMirror& operator=(const HalfSpaceMirror&) = default;
     172            0 :   HalfSpaceMirror(HalfSpaceMirror&&) = default;
     173            0 :   HalfSpaceMirror& operator=(HalfSpaceMirror&&) = default;
     174            0 :   ~HalfSpaceMirror() override = default;
     175            0 :   std::unique_ptr<elliptic::analytic_data::AnalyticSolution> get_clone()
     176              :       const override {
     177              :     return std::make_unique<HalfSpaceMirror>(*this);
     178              :   }
     179              : 
     180              :   /// \cond
     181              :   explicit HalfSpaceMirror(CkMigrateMessage* m)
     182              :       : elliptic::analytic_data::AnalyticSolution(m) {}
     183              :   using PUP::able::register_constructor;
     184              :   WRAPPED_PUPable_decl_template(HalfSpaceMirror);  // NOLINT
     185              :   /// \endcond
     186              : 
     187            0 :   HalfSpaceMirror(double beam_width,
     188              :                   constitutive_relation_type constitutive_relation,
     189              :                   size_t integration_intervals = 350,
     190              :                   double absolute_tolerance = 1e-12,
     191              :                   double relative_tolerance = 1e-10)
     192              :       : beam_width_(beam_width),
     193              :         constitutive_relation_(std::move(constitutive_relation)),
     194              :         integration_intervals_(integration_intervals),
     195              :         absolute_tolerance_(absolute_tolerance),
     196              :         relative_tolerance_(relative_tolerance) {}
     197              : 
     198            0 :   double beam_width() const { return beam_width_; }
     199            0 :   size_t integration_intervals() const { return integration_intervals_; }
     200            0 :   double absolute_tolerance() const { return absolute_tolerance_; }
     201            0 :   double relative_tolerance() const { return relative_tolerance_; }
     202              : 
     203            0 :   const constitutive_relation_type& constitutive_relation() const {
     204              :     return constitutive_relation_;
     205              :   }
     206              : 
     207              :   template <typename DataType, typename... RequestedTags>
     208            0 :   tuples::TaggedTuple<RequestedTags...> variables(
     209              :       const tnsr::I<DataType, 3>& x,
     210              :       tmpl::list<RequestedTags...> /*meta*/) const {
     211              :     for (size_t i = 0; i < get_size(get<2>(x)); i++) {
     212              :       if (UNLIKELY(get_element(get<2>(x), i) < 0)) {
     213              :         ERROR(
     214              :             "The HalfSpaceMirror solution is not defined for negative values "
     215              :             "of z.");
     216              :       }
     217              :     }
     218              :     using VarsComputer = detail::HalfSpaceMirrorVariables<DataType>;
     219              :     typename VarsComputer::Cache cache{get_size(*x.begin())};
     220              :     const VarsComputer computer{x,
     221              :                                 beam_width_,
     222              :                                 constitutive_relation_,
     223              :                                 integration_intervals_,
     224              :                                 absolute_tolerance_,
     225              :                                 relative_tolerance_};
     226              :     return {cache.get_var(computer, RequestedTags{})...};
     227              :   }
     228              : 
     229              :   template <typename... RequestedTags>
     230            0 :   tuples::TaggedTuple<RequestedTags...> variables(
     231              :       const tnsr::I<DataVector, 3>& x, const Mesh<3>& /*mesh*/,
     232              :       const InverseJacobian<DataVector, 3, Frame::ElementLogical,
     233              :                             Frame::Inertial>& /*inv_jacobian*/,
     234              :       tmpl::list<RequestedTags...> meta) const {
     235              :     return variables(x, meta);
     236              :   }
     237              : 
     238              :   /// NOLINTNEXTLINE(google-runtime-references)
     239            1 :   void pup(PUP::er& p) override {
     240              :     elliptic::analytic_data::AnalyticSolution::pup(p);
     241              :     p | beam_width_;
     242              :     p | constitutive_relation_;
     243              :     p | integration_intervals_;
     244              :     p | absolute_tolerance_;
     245              :     p | relative_tolerance_;
     246              :   }
     247              : 
     248              :  private:
     249            0 :   double beam_width_{std::numeric_limits<double>::signaling_NaN()};
     250            0 :   constitutive_relation_type constitutive_relation_{};
     251            0 :   size_t integration_intervals_{std::numeric_limits<size_t>::max()};
     252            0 :   double absolute_tolerance_{std::numeric_limits<double>::signaling_NaN()};
     253            0 :   double relative_tolerance_{std::numeric_limits<double>::signaling_NaN()};
     254              : };
     255              : 
     256            0 : bool operator==(const HalfSpaceMirror& lhs, const HalfSpaceMirror& rhs);
     257            0 : bool operator!=(const HalfSpaceMirror& lhs, const HalfSpaceMirror& rhs);
     258              : 
     259              : }  // namespace Elasticity::Solutions
        

Generated by: LCOV version 2.0-1