HalfSpaceMirror.hpp
1 // Distributed under the MIT License.
2 // See LICENSE.txt for details.
3 
4 #pragma once
5 
6 #include <cstddef>
7 #include <limits>
8 
11 #include "Elliptic/Systems/Elasticity/Tags.hpp"
12 #include "ErrorHandling/Error.hpp"
13 #include "Options/Options.hpp"
14 #include "PointwiseFunctions/Elasticity/ConstitutiveRelations/IsotropicHomogeneous.hpp"
15 #include "Utilities/TMPL.hpp"
16 #include "Utilities/TaggedTuple.hpp"
17 
18 /// \cond
19 class DataVector;
20 namespace PUP {
21 class er;
22 } // namespace PUP
23 /// \endcond
24 
25 namespace Elasticity::Solutions {
26 /*!
27  * \brief The solution for a half-space mirror deformed by a laser beam.
28  *
29  * \details This solution is mapping (via the fluctuation dissipation theorem)
30  * thermal noise to an elasticity problem where a normally incident and
31  * axisymmetric laser beam with a Gaussian beam profile acts on the face of a
32  * semi-infinite mirror. Here we assume the face to be at \f$z = 0\f$ and the
33  * material to extend to \f$+\infty\f$ in the z-direction as well as for the
34  * mirror diameter to be comparatively large to the `beam width`. The mirror
35  * material is characterized by an isotropic homogeneous constitutive relation
36  * \f$Y^{ijkl}\f$ (see
37  * `Elasticity::ConstitutiveRelations::IsotropicHomogeneous`). In this scenario,
38  * the auxiliary elastic problem has an applied pressure distribution equal to
39  * the laser beam intensity profile \f$p(r)\f$ (see Eq. (11.94) and Eq. (11.95)
40  * in \cite ThorneBlandford2017 with F = 1 and the time dependency dropped)
41  *
42  * \f{align}
43  * T^{zr} &= T^{rz} = 0 \\
44  * T^{zz} &= p(r) = \frac{e^{-\frac{r^2}{r_0^2}}}{\pi r_0^2}\text{.}
45  * \f}
46  *
47  * in the form of a Neumann boundary condition to the face of the mirror. We
48  * find that this stress in cylinder coordinates is produced by the displacement
49  * field
50  *
51  * \f{align}
52  * \xi_{r} &= \frac{1}{2 \mu} \int_0^{\infty} dk J_1(kr)e^{(-kz)}\left(1 -
53  * \frac{\lambda + 2\mu}{\lambda + \mu} + kz \right) \tilde{p}(k) \\
54  * \xi_{\phi} &= 0 \\
55  * \xi_{z} &= \frac{1}{2 \mu} \int_0^{\infty} dk J_0(kr)e^{(-kz)}\left(1 +
56  * \frac{\mu}{\lambda + \mu} + kz \right) \tilde{p}(k)
57  * \f}
58  *
59  * and the strain
60  *
61  * \f{align}
62  * \Theta &= \frac{1}{2 \mu} \int_0^{\infty} dk
63  * J_0(kr) k e^{(-kz)}\left(\frac{-2\mu}{\lambda + \mu}\right) \tilde{p}(k) \\
64  * S_{rr} &= \Theta - S_{\phi\phi} - S_{zz} \\
65  * S_{\phi\phi} &= \frac{\xi_{r}}{r} \\
66  * S_{(rz)} &= -\frac{1}{2 \mu} \int_0^{\infty} dk J_1(kr) k e^{(-kz)}\left(kz
67  * \right) \tilde{p}(k) \\
68  * S_{zz} &= \frac{1}{2 \mu} \int_0^{\infty} dk
69  * J_0(kr) k e^{(-kz)}\left(-\frac{\mu}{\lambda + \mu} - kz \right) \tilde{p}(k)
70  * \f}
71  *
72  * (see Eqs. (11 a) - (11 c) and (13 a) - (13 e), with (13 c) swapped in favor
73  * of (12 c) in \cite Lovelace2007tn), where \f$\tilde{p}(k)= \frac{1}{2\pi}
74  * e^{-(\frac{kr_0}{2})^2}\f$ is the Hankel-Transform of the lasers intensity
75  * profile and \f$ \Theta = \mathrm{Tr}(S)\f$ the materials expansion.
76  *
77  */
79  public:
80  static constexpr size_t volume_dim = 3;
81 
84 
85  struct BeamWidth {
86  using type = double;
87  static constexpr Options::String help{
88  "The lasers beam width r_0 with FWHM = 2*sqrt(ln 2)*r_0"};
89  static type lower_bound() noexcept { return 0.0; }
90  };
91 
92  struct Material {
94  static constexpr Options::String help{
95  "The material properties of the beam"};
96  };
97 
99  using type = size_t;
100  static constexpr Options::String help{
101  "Workspace size for numerical integrals. Increase if integrals fail to "
102  "reach the prescribed tolerance at large distances relative to the "
103  "beam width. The default values for workspace size and tolerances "
104  "should accommodate distances of up to ~100 beam widths."};
105  static type lower_bound() noexcept { return 1; }
106  static type default_value() noexcept { return 350; }
107  };
108 
110  using type = double;
111  static constexpr Options::String help{
112  "Absolute tolerance for numerical integrals"};
113  static type lower_bound() noexcept { return 0.; }
114  static type default_value() noexcept { return 1e-12; }
115  };
116 
118  using type = double;
119  static constexpr Options::String help{
120  "Relative tolerance for numerical integrals"};
121  static type lower_bound() noexcept { return 0.; }
122  static type upper_bound() noexcept { return 1.; }
123  static type default_value() noexcept { return 1e-10; }
124  };
125 
126  using options = tmpl::list<BeamWidth, Material, IntegrationIntervals,
128  static constexpr Options::String help{
129  "A semi-infinite mirror on which a laser introduces stress perpendicular "
130  "to the mirrors surface."};
131 
132  HalfSpaceMirror() = default;
133  HalfSpaceMirror(const HalfSpaceMirror&) noexcept = default;
134  HalfSpaceMirror& operator=(const HalfSpaceMirror&) noexcept = default;
135  HalfSpaceMirror(HalfSpaceMirror&&) noexcept = default;
136  HalfSpaceMirror& operator=(HalfSpaceMirror&&) noexcept = default;
137  ~HalfSpaceMirror() noexcept = default;
138 
139  HalfSpaceMirror(double beam_width,
140  constitutive_relation_type constitutive_relation,
141  size_t integration_intervals = 350,
142  double absolute_tolerance = 1e-12,
143  double relative_tolerance = 1e-10) noexcept;
144 
145  const constitutive_relation_type& constitutive_relation() const noexcept {
146  return constitutive_relation_;
147  }
148 
149  // @{
150  /// Retrieve variable at coordinates `x`
151  auto variables(const tnsr::I<DataVector, 3>& x,
152  tmpl::list<Tags::Displacement<3>> /*meta*/) const noexcept
153  -> tuples::TaggedTuple<Tags::Displacement<3>>;
154 
155  auto variables(const tnsr::I<DataVector, 3>& x,
156  tmpl::list<Tags::Strain<3>> /*meta*/) const noexcept
157  -> tuples::TaggedTuple<Tags::Strain<3>>;
158 
159  // FixedSource in Elasticity equates to external forces
160  // (see Elasticity::FirstOrderSystem)
161  static auto variables(
162  const tnsr::I<DataVector, 3>& x,
163  tmpl::list<::Tags::FixedSource<Tags::Displacement<3>>> /*meta*/) noexcept
164  -> tuples::TaggedTuple<::Tags::FixedSource<Tags::Displacement<3>>>;
165  // @}
166 
167  /// Retrieve a collection of variables at coordinates `x`
168  template <typename... Tags>
169  tuples::TaggedTuple<Tags...> variables(const tnsr::I<DataVector, 3>& x,
170  tmpl::list<Tags...> /*meta*/) const
171  noexcept {
172  static_assert(sizeof...(Tags) > 1, "An unsupported Tag was requested.");
173  for (size_t i = 0; i < get<2>(x).size(); i++) {
174  if (UNLIKELY(get<2>(x)[i] < 0)) {
175  ERROR(
176  "The HalfSpaceMirror solution is not defined for negative values "
177  "of z.");
178  }
179  }
180  return {tuples::get<Tags>(variables(x, tmpl::list<Tags>{}))...};
181  }
182 
183  // clang-tidy: no pass by reference
184  void pup(PUP::er& p) noexcept; // NOLINT
185 
186  private:
187  friend bool operator==(const HalfSpaceMirror& lhs,
188  const HalfSpaceMirror& rhs) noexcept;
189 
190  double beam_width_{std::numeric_limits<double>::signaling_NaN()};
191  constitutive_relation_type constitutive_relation_{};
192  size_t integration_intervals_{std::numeric_limits<size_t>::max()};
193  double absolute_tolerance_{std::numeric_limits<double>::signaling_NaN()};
194  double relative_tolerance_{std::numeric_limits<double>::signaling_NaN()};
195 };
196 
197 bool operator!=(const HalfSpaceMirror& lhs,
198  const HalfSpaceMirror& rhs) noexcept;
199 
200 } // namespace Elasticity::Solutions
UNLIKELY
#define UNLIKELY(x)
Definition: Gsl.hpp:73
std::rel_ops::operator!=
T operator!=(T... args)
Options.hpp
Error.hpp
Elasticity::Solutions::HalfSpaceMirror::BeamWidth
Definition: HalfSpaceMirror.hpp:85
Elasticity::Solutions::HalfSpaceMirror::AbsoluteTolerance
Definition: HalfSpaceMirror.hpp:109
ERROR
#define ERROR(m)
prints an error message to the standard error stream and aborts the program.
Definition: Error.hpp:36
Elasticity::Tags::Displacement
The material displacement field .
Definition: Tags.hpp:47
Elasticity::Solutions::HalfSpaceMirror::RelativeTolerance
Definition: HalfSpaceMirror.hpp:117
cstddef
DataVector
Stores a collection of function values.
Definition: DataVector.hpp:42
Elasticity::Solutions::HalfSpaceMirror
The solution for a half-space mirror deformed by a laser beam.
Definition: HalfSpaceMirror.hpp:78
std::numeric_limits::signaling_NaN
T signaling_NaN(T... args)
Elasticity::Solutions
Analytic solutions to linear elasticity problems.
Definition: BentBeam.cpp:17
tnsr
Type aliases to construct common Tensors.
Definition: TypeAliases.hpp:31
Elasticity::Solutions::HalfSpaceMirror::Material
Definition: HalfSpaceMirror.hpp:92
Elasticity::ConstitutiveRelations::IsotropicHomogeneous< 3 >
limits
Elasticity::Solutions::HalfSpaceMirror::IntegrationIntervals
Definition: HalfSpaceMirror.hpp:98
Options::String
const char *const String
The string used in option structs.
Definition: Options.hpp:32
Tensor.hpp
std::numeric_limits::max
T max(T... args)
Prefixes.hpp
Elasticity::Solutions::HalfSpaceMirror::variables
auto variables(const tnsr::I< DataVector, 3 > &x, tmpl::list< Tags::Displacement< 3 >>) const noexcept -> tuples::TaggedTuple< Tags::Displacement< 3 >>
Retrieve variable at coordinates x
Definition: HalfSpaceMirror.cpp:43
TMPL.hpp