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::I<DataVector, 3>& x, 106 : const tnsr::i<DataVector, 3>& face_normal) const; 107 : 108 0 : using argument_tags_linearized = tmpl::list<>; 109 0 : using volume_tags_linearized = tmpl::list<>; 110 : 111 0 : static void apply_linearized( 112 : gsl::not_null<tnsr::I<DataVector, 3>*> displacement, 113 : gsl::not_null<tnsr::I<DataVector, 3>*> n_dot_minus_stress); 114 : 115 : // NOLINTNEXTLINE(google-runtime-references) 116 0 : void pup(PUP::er& p) override { p | beam_width_; } 117 : 118 : private: 119 0 : double beam_width_{std::numeric_limits<double>::signaling_NaN()}; 120 : }; 121 : 122 0 : bool operator==(const LaserBeam& lhs, const LaserBeam& rhs); 123 : 124 0 : bool operator!=(const LaserBeam& lhs, const LaserBeam& rhs); 125 : 126 : } // namespace Elasticity::BoundaryConditions