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 : #include <string>
9 : #include <vector>
10 :
11 : #include "DataStructures/Tensor/EagerMath/Magnitude.hpp"
12 : #include "DataStructures/Tensor/TypeAliases.hpp"
13 : #include "Domain/FaceNormal.hpp"
14 : #include "Domain/Tags.hpp"
15 : #include "Elliptic/BoundaryConditions/BoundaryCondition.hpp"
16 : #include "Elliptic/BoundaryConditions/BoundaryConditionType.hpp"
17 : #include "Options/String.hpp"
18 : #include "Utilities/Gsl.hpp"
19 : #include "Utilities/Serialization/CharmPupable.hpp"
20 : #include "Utilities/TMPL.hpp"
21 :
22 : /// \cond
23 : class DataVector;
24 : /// \endcond
25 :
26 : namespace Elasticity::BoundaryConditions {
27 :
28 : /*!
29 : * \brief A laser beam with Gaussian profile normally incident to the surface
30 : *
31 : * This boundary condition represents a laser beam with Gaussian profile that
32 : * exerts pressure normal to the surface of a reflecting material. The pressure
33 : * we are considering here is
34 : *
35 : * \f{align}
36 : * n_i T^{ij} = -n^j \frac{e^{-\frac{r^2}{r_0^2}}}{\pi r_0^2}
37 : * \f}
38 : *
39 : * where \f$n_i\f$ is the unit normal pointing _out_ of the surface, \f$r\f$ is
40 : * the coordinate distance from the origin in the plane perpendicular to
41 : * \f$n_i\f$ and \f$r_0\f$ is the "beam width" parameter. The pressure profile
42 : * and the angle of incidence can be generalized in future work. Note that we
43 : * follow the convention of \cite Lovelace2007tn, \cite Lovelace2017xyf, and
44 : * \cite Vu2023thn in defining the beam width, and other publications may
45 : * include a factor of \f$\sqrt{2}\f$ in its definition.
46 : *
47 : * This boundary condition is used to simulate thermal noise induced in a mirror
48 : * by the laser, as detailed for instance in \cite Lovelace2007tn,
49 : * \cite Lovelace2017xyf, and \cite Vu2023thn.
50 : * See also `Elasticity::Solutions::HalfSpaceMirror` for
51 : * an analytic solution that involves this boundary condition.
52 : */
53 1 : class LaserBeam : public elliptic::BoundaryConditions::BoundaryCondition<3> {
54 : private:
55 0 : using Base = elliptic::BoundaryConditions::BoundaryCondition<3>;
56 :
57 : public:
58 0 : struct BeamWidth {
59 0 : using type = double;
60 0 : static constexpr Options::String help =
61 : "The width r_0 of the Gaussian beam profile, such that FWHM = 2 * "
62 : "sqrt(ln 2) * r_0";
63 0 : static type lower_bound() { return 0.0; }
64 : };
65 :
66 0 : static constexpr Options::String help =
67 : "A laser beam with Gaussian profile normally incident to the surface.";
68 0 : using options = tmpl::list<BeamWidth>;
69 :
70 0 : LaserBeam() = default;
71 0 : LaserBeam(const LaserBeam&) = default;
72 0 : LaserBeam& operator=(const LaserBeam&) = default;
73 0 : LaserBeam(LaserBeam&&) = default;
74 0 : LaserBeam& operator=(LaserBeam&&) = default;
75 0 : ~LaserBeam() = default;
76 :
77 : /// \cond
78 : explicit LaserBeam(CkMigrateMessage* m) : Base(m) {}
79 : using PUP::able::register_constructor;
80 : WRAPPED_PUPable_decl_template(LaserBeam);
81 : /// \endcond
82 :
83 0 : std::unique_ptr<domain::BoundaryConditions::BoundaryCondition> get_clone()
84 : const override {
85 : return std::make_unique<LaserBeam>(*this);
86 : }
87 :
88 0 : LaserBeam(double beam_width) : beam_width_(beam_width) {}
89 :
90 0 : double beam_width() const { return beam_width_; }
91 :
92 0 : std::vector<elliptic::BoundaryConditionType> boundary_condition_types()
93 : const override {
94 : return {3, elliptic::BoundaryConditionType::Neumann};
95 : }
96 :
97 0 : using argument_tags =
98 : tmpl::list<domain::Tags::Coordinates<3, Frame::Inertial>,
99 : ::Tags::Normalized<
100 : domain::Tags::UnnormalizedFaceNormal<3, Frame::Inertial>>>;
101 0 : using volume_tags = tmpl::list<>;
102 :
103 0 : void apply(gsl::not_null<tnsr::I<DataVector, 3>*> displacement,
104 : gsl::not_null<tnsr::I<DataVector, 3>*> n_dot_minus_stress,
105 : const tnsr::iJ<DataVector, 3>& deriv_displacement,
106 : const tnsr::I<DataVector, 3>& x,
107 : const tnsr::i<DataVector, 3>& face_normal) const;
108 :
109 0 : using argument_tags_linearized = tmpl::list<>;
110 0 : using volume_tags_linearized = tmpl::list<>;
111 :
112 0 : static void apply_linearized(
113 : gsl::not_null<tnsr::I<DataVector, 3>*> displacement,
114 : gsl::not_null<tnsr::I<DataVector, 3>*> n_dot_minus_stress,
115 : const tnsr::iJ<DataVector, 3>& deriv_displacement);
116 :
117 : // NOLINTNEXTLINE(google-runtime-references)
118 0 : void pup(PUP::er& p) override { p | beam_width_; }
119 :
120 : private:
121 0 : double beam_width_{std::numeric_limits<double>::signaling_NaN()};
122 : };
123 :
124 0 : bool operator==(const LaserBeam& lhs, const LaserBeam& rhs);
125 :
126 0 : bool operator!=(const LaserBeam& lhs, const LaserBeam& rhs);
127 :
128 : } // namespace Elasticity::BoundaryConditions
|