SpECTRE Documentation Coverage Report
Current view: top level - PointwiseFunctions/AnalyticSolutions/Elasticity - BentBeam.hpp Hit Total Coverage
Commit: ecb8a275e1aebab77dcce48a5e098ed4e486ab4b Lines: 3 43 7.0 %
Date: 2026-08-22 01:05:40
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 <limits>
       7             : #include <pup.h>
       8             : 
       9             : #include "DataStructures/CachedTempBuffer.hpp"
      10             : #include "DataStructures/DataBox/Prefixes.hpp"
      11             : #include "DataStructures/DataVector.hpp"
      12             : #include "DataStructures/TaggedTuple.hpp"
      13             : #include "DataStructures/Tensor/Tensor.hpp"
      14             : #include "Elliptic/Systems/Elasticity/Tags.hpp"
      15             : #include "NumericalAlgorithms/LinearOperators/PartialDerivatives.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/Serialization/CharmPupable.hpp"
      22             : #include "Utilities/TMPL.hpp"
      23             : 
      24           0 : namespace Elasticity::Solutions {
      25             : 
      26             : namespace detail {
      27             : template <typename DataType>
      28             : struct BentBeamVariables {
      29             :   using Cache = CachedTempBuffer<
      30             :       Tags::Displacement<2>,
      31             :       ::Tags::deriv<Tags::Displacement<2>, tmpl::size_t<2>, Frame::Inertial>,
      32             :       Tags::Strain<2>, Tags::MinusStress<2>, Tags::PotentialEnergyDensity<2>,
      33             :       ::Tags::FixedSource<Tags::Displacement<2>>>;
      34             : 
      35             :   const tnsr::I<DataType, 2>& x;
      36             :   const double length;
      37             :   const double height;
      38             :   const double bending_moment;
      39             :   const ConstitutiveRelations::IsotropicHomogeneous<2>& constitutive_relation;
      40             : 
      41             :   void operator()(gsl::not_null<tnsr::I<DataType, 2>*> displacement,
      42             :                   gsl::not_null<Cache*> cache,
      43             :                   Tags::Displacement<2> /*meta*/) const;
      44             :   void operator()(gsl::not_null<tnsr::iJ<DataType, 2>*> deriv_displacement,
      45             :                   gsl::not_null<Cache*> cache,
      46             :                   ::Tags::deriv<Tags::Displacement<2>, tmpl::size_t<2>,
      47             :                                 Frame::Inertial> /*meta*/) const;
      48             :   void operator()(gsl::not_null<tnsr::ii<DataType, 2>*> strain,
      49             :                   gsl::not_null<Cache*> cache, Tags::Strain<2> /*meta*/) const;
      50             :   void operator()(gsl::not_null<tnsr::II<DataType, 2>*> minus_stress,
      51             :                   gsl::not_null<Cache*> cache,
      52             :                   Tags::MinusStress<2> /*meta*/) const;
      53             :   void operator()(gsl::not_null<Scalar<DataType>*> potential_energy_density,
      54             :                   gsl::not_null<Cache*> cache,
      55             :                   Tags::PotentialEnergyDensity<2> /*meta*/) const;
      56             :   void operator()(
      57             :       gsl::not_null<tnsr::I<DataType, 2>*> fixed_source_for_displacement,
      58             :       gsl::not_null<Cache*> cache,
      59             :       ::Tags::FixedSource<Tags::Displacement<2>> /*meta*/) const;
      60             : };
      61             : }  // namespace detail
      62             : 
      63             : /*!
      64             :  * \brief A state of pure bending of an elastic beam in 2D
      65             :  *
      66             :  * \details This solution describes a 2D slice through an elastic beam of length
      67             :  * \f$L\f$ and height \f$H\f$, centered around (0, 0), that is subject to a
      68             :  * bending moment \f$M=\int T^{xx}y\mathrm{d}y\f$ (see e.g.
      69             :  * \cite ThorneBlandford2017, Eq. 11.41c for a bending moment in 1D). The beam
      70             :  * material is characterized by an isotropic and homogeneous constitutive
      71             :  * relation \f$Y^{ijkl}\f$ in the plane-stress approximation (see
      72             :  * `Elasticity::ConstitutiveRelations::IsotropicHomogeneous`). In this scenario,
      73             :  * no body-forces \f$f_\mathrm{ext}^j\f$ act on the material, so the
      74             :  * \ref Elasticity equations reduce to \f$\nabla_i T^{ij}=0\f$, but the bending
      75             :  * moment \f$M\f$ generates the stress
      76             :  *
      77             :  * \f{align}
      78             :  * T^{xx} &= \frac{12 M}{H^3} y \\
      79             :  * T^{xy} &= 0 = T^{yy} \text{.}
      80             :  * \f}
      81             :  *
      82             :  * By fixing the rigid-body motions to
      83             :  *
      84             :  * \f[
      85             :  * \xi^x(0,y)=0 \quad \text{and} \quad \xi^y\left(\pm \frac{L}{2},0\right)=0
      86             :  * \f]
      87             :  *
      88             :  * we find that this stress is produced by the displacement field
      89             :  *
      90             :  * \f{align}
      91             :  * \xi^x&=-\frac{12 M}{EH^3}xy \\
      92             :  * \xi^y&=\frac{6 M}{EH^3}\left(x^2+\nu y^2-\frac{L^2}{4}\right)
      93             :  * \f}
      94             :  *
      95             :  * in terms of the Young's modulus \f$E\f$ and the Poisson ration \f$\nu\f$ of
      96             :  * the material. The corresponding strain \f$S_{ij}=\partial_{(i}\xi_{j)}\f$ is
      97             :  *
      98             :  * \f{align}
      99             :  * S_{xx} &= -\frac{12 M}{EH^3} y \\
     100             :  * S_{yy} &= \frac{12 M}{EH^3} \nu y \\
     101             :  * S_{xy} &= S_{yx} = 0
     102             :  * \f}
     103             :  *
     104             :  * and the potential energy stored in the entire infinitesimal slice is
     105             :  *
     106             :  * \f[
     107             :  * \int_{-L/2}^{L/2} \int_{-H/2}^{H/2} U dy\,dx = \frac{6M^2}{EH^3}L \text{.}
     108             :  * \f]
     109             :  */
     110           1 : class BentBeam : public elliptic::analytic_data::AnalyticSolution {
     111             :  public:
     112           0 :   using constitutive_relation_type =
     113             :       Elasticity::ConstitutiveRelations::IsotropicHomogeneous<2>;
     114             : 
     115           0 :   struct Length {
     116           0 :     using type = double;
     117           0 :     static constexpr Options::String help{"The beam length"};
     118           0 :     static type lower_bound() { return 0.0; }
     119             :   };
     120           0 :   struct Height {
     121           0 :     using type = double;
     122           0 :     static constexpr Options::String help{"The beam height"};
     123           0 :     static type lower_bound() { return 0.0; }
     124             :   };
     125           0 :   struct BendingMoment {
     126           0 :     using type = double;
     127           0 :     static constexpr Options::String help{
     128             :         "The bending moment applied to the beam"};
     129           0 :     static type lower_bound() { return 0.0; }
     130             :   };
     131           0 :   struct Material {
     132           0 :     using type = constitutive_relation_type;
     133           0 :     static constexpr Options::String help{
     134             :         "The material properties of the beam"};
     135             :   };
     136             : 
     137           0 :   using options = tmpl::list<Length, Height, BendingMoment, Material>;
     138           0 :   static constexpr Options::String help{
     139             :       "A 2D slice through an elastic beam which is subject to a bending "
     140             :       "moment. The bending moment is applied along the length of the beam, "
     141             :       "i.e. the x-axis, so that the beam's left and right ends are bent "
     142             :       "towards the positive y-axis. It is measured in units of force."};
     143             : 
     144           0 :   BentBeam() = default;
     145           0 :   BentBeam(const BentBeam&) = default;
     146           0 :   BentBeam& operator=(const BentBeam&) = default;
     147           0 :   BentBeam(BentBeam&&) = default;
     148           0 :   BentBeam& operator=(BentBeam&&) = default;
     149           0 :   ~BentBeam() override = default;
     150           0 :   std::unique_ptr<elliptic::analytic_data::AnalyticSolution> get_clone()
     151             :       const override {
     152             :     return std::make_unique<BentBeam>(*this);
     153             :   }
     154             : 
     155             :   /// \cond
     156             :   explicit BentBeam(CkMigrateMessage* m)
     157             :       : elliptic::analytic_data::AnalyticSolution(m) {}
     158             :   using PUP::able::register_constructor;
     159             :   WRAPPED_PUPable_decl_template(BentBeam);  // NOLINT
     160             :   /// \endcond
     161             : 
     162           0 :   BentBeam(double length, double height, double bending_moment,
     163             :            constitutive_relation_type constitutive_relation)
     164             :       : length_(length),
     165             :         height_(height),
     166             :         bending_moment_(bending_moment),
     167             :         constitutive_relation_(std::move(constitutive_relation)) {}
     168             : 
     169           0 :   double length() const { return length_; }
     170           0 :   double height() const { return height_; }
     171           0 :   double bending_moment() const { return bending_moment_; }
     172             : 
     173           0 :   const constitutive_relation_type& constitutive_relation() const {
     174             :     return constitutive_relation_;
     175             :   }
     176             : 
     177             :   /// Return potential energy integrated over the whole beam material
     178           1 :   double potential_energy() const {
     179             :     return 6. * length_ * square(bending_moment_) /
     180             :            (cube(height_) * constitutive_relation_.youngs_modulus());
     181             :   }
     182             : 
     183             :   template <typename DataType, typename... RequestedTags>
     184           0 :   tuples::TaggedTuple<RequestedTags...> variables(
     185             :       const tnsr::I<DataType, 2>& x,
     186             :       tmpl::list<RequestedTags...> /*meta*/) const {
     187             :     using VarsComputer = detail::BentBeamVariables<DataType>;
     188             :     typename VarsComputer::Cache cache{get_size(*x.begin())};
     189             :     const VarsComputer computer{x, length_, height_, bending_moment_,
     190             :                                 constitutive_relation_};
     191             :     return {cache.get_var(computer, RequestedTags{})...};
     192             :   }
     193             : 
     194             :   template <typename... RequestedTags>
     195           0 :   tuples::TaggedTuple<RequestedTags...> variables(
     196             :       const tnsr::I<DataVector, 2>& x, const Mesh<2>& /*mesh*/,
     197             :       const InverseJacobian<DataVector, 2, Frame::ElementLogical,
     198             :                             Frame::Inertial>& /*inv_jacobian*/,
     199             :       tmpl::list<RequestedTags...> meta) const {
     200             :     return variables(x, meta);
     201             :   }
     202             : 
     203             :   /// NOLINTNEXTLINE(google-runtime-references)
     204           1 :   void pup(PUP::er& p) override {
     205             :     elliptic::analytic_data::AnalyticSolution::pup(p);
     206             :     p | length_;
     207             :     p | height_;
     208             :     p | bending_moment_;
     209             :     p | constitutive_relation_;
     210             :   }
     211             : 
     212             :  private:
     213           0 :   double length_{std::numeric_limits<double>::signaling_NaN()};
     214           0 :   double height_{std::numeric_limits<double>::signaling_NaN()};
     215           0 :   double bending_moment_{std::numeric_limits<double>::signaling_NaN()};
     216           0 :   constitutive_relation_type constitutive_relation_{};
     217             : };
     218             : 
     219           0 : bool operator==(const BentBeam& lhs, const BentBeam& rhs);
     220           0 : bool operator!=(const BentBeam& lhs, const BentBeam& rhs);
     221             : 
     222             : }  // namespace Elasticity::Solutions

Generated by: LCOV version 1.14