Smith  0.1
Smith is an implicit thermal structural mechanics simulation code.
dirichlet_boundary_conditions.cpp
1 // Copyright (c) Lawrence Livermore National Security, LLC and
2 // other Smith Project Developers. See the top-level LICENSE file for
3 // details.
4 //
5 // SPDX-License-Identifier: (BSD-3-Clause)
6 
7 #include "smith/physics/mesh.hpp"
11 
12 #include <algorithm>
13 #include <cmath>
14 
15 namespace smith {
16 
17 namespace {
18 
19 constexpr double bc_time_fd_step = 1.0e-4;
20 
21 class SecondTimeDerivativeScalarCoefficient : public mfem::Coefficient {
22  public:
23  explicit SecondTimeDerivativeScalarCoefficient(std::shared_ptr<mfem::Coefficient> source) : source_(std::move(source))
24  {
25  }
26 
27  double Eval(mfem::ElementTransformation& T, const mfem::IntegrationPoint& ip) override
28  {
29  const double t0 = GetTime();
30  const double h = bc_time_fd_step * std::max(1.0, std::abs(t0));
31  source_->SetTime(t0);
32  const double f0 = source_->Eval(T, ip);
33  source_->SetTime(t0 + h);
34  const double f1 = source_->Eval(T, ip);
35  source_->SetTime(t0 + 2.0 * h);
36  const double f2 = source_->Eval(T, ip);
37  source_->SetTime(t0);
38  return (f2 - 2.0 * f1 + f0) / (h * h);
39  }
40 
41  private:
42  std::shared_ptr<mfem::Coefficient> source_;
43 };
44 
45 class SecondTimeDerivativeVectorCoefficient : public mfem::VectorCoefficient {
46  public:
47  explicit SecondTimeDerivativeVectorCoefficient(std::shared_ptr<mfem::VectorCoefficient> source)
48  : mfem::VectorCoefficient(source->GetVDim()), source_(std::move(source))
49  {
50  }
51 
52  void Eval(mfem::Vector& V, mfem::ElementTransformation& T, const mfem::IntegrationPoint& ip) override
53  {
54  const double t0 = GetTime();
55  const double h = bc_time_fd_step * std::max(1.0, std::abs(t0));
56  mfem::Vector v0(vdim), v1(vdim), v2(vdim);
57  source_->SetTime(t0);
58  source_->Eval(v0, T, ip);
59  source_->SetTime(t0 + h);
60  source_->Eval(v1, T, ip);
61  source_->SetTime(t0 + 2.0 * h);
62  source_->Eval(v2, T, ip);
63  source_->SetTime(t0);
64  V = v2;
65  V.Add(-2.0, v1);
66  V += v0;
67  V /= (h * h);
68  }
69 
70  private:
71  std::shared_ptr<mfem::VectorCoefficient> source_;
72 };
73 
74 } // namespace
75 
77  mfem::ParFiniteElementSpace& space)
78  : mfem_mesh_(mfem_mesh), bcs_(mfem_mesh), space_(space)
79 {
80 }
81 
82 DirichletBoundaryConditions::DirichletBoundaryConditions(const Mesh& mesh, mfem::ParFiniteElementSpace& space)
83  : DirichletBoundaryConditions(mesh.mfemParMesh(), space)
84 {
85 }
86 
88 {
89  second_derivative_manager_.emplace(mfem_mesh_);
90  rebuildSecondDerivativeManager(*second_derivative_manager_);
91  return *second_derivative_manager_;
92 }
93 
94 void DirichletBoundaryConditions::rebuildSecondDerivativeManager(BoundaryConditionManager& target) const
95 {
96  for (const auto& bc : bcs_.essentials()) {
97  if (is_vector_valued(bc.coefficient())) {
98  auto deriv_coef = std::make_shared<SecondTimeDerivativeVectorCoefficient>(
99  get<std::shared_ptr<mfem::VectorCoefficient>>(bc.coefficient()));
100  target.addEssentialByTrueDofs(bc.getTrueDofList(), deriv_coef, space_);
101  } else {
102  auto deriv_coef = std::make_shared<SecondTimeDerivativeScalarCoefficient>(
103  get<std::shared_ptr<mfem::Coefficient>>(bc.coefficient()));
104  target.addEssential(bc.getLocalDofList(), deriv_coef, space_, bc.component());
105  }
106  }
107 }
108 
109 } // namespace smith
This file contains the declaration of the boundary condition class.
This file contains the declaration of the boundary condition manager class.
A container for the boundary condition information relating to a specific physics module.
void addEssentialByTrueDofs(const mfem::Array< int > &true_dofs, std::shared_ptr< mfem::VectorCoefficient > ess_bdr_coef, mfem::ParFiniteElementSpace &space)
std::vector< BoundaryCondition > & essentials()
Accessor for the essential BC objects.
void addEssential(const std::set< int > &ess_bdr, smith::GeneralCoefficient ess_bdr_coef, mfem::ParFiniteElementSpace &space, const std::optional< int > component={})
Set the essential boundary conditions from a list of boundary markers and a coefficient.
A generic class for setting Dirichlet boundary conditions on arbitrary physics.
const smith::BoundaryConditionManager & getSecondDerivativeManager() const
Return the BC manager whose prescribed values are the second time derivative of the value-level BC,...
DirichletBoundaryConditions(const mfem::ParMesh &mfem_mesh, mfem::ParFiniteElementSpace &space)
Construct from mfem::ParMesh.
Helper class for constructing a mesh consistent with Smith.
Definition: mesh.hpp:37
Contains DirichletBoundaryConditions class for interaction with the differentiable solve interfaces.
Smith mesh class which assists in constructing the appropriate parallel mfem meshes and registering a...
Accelerator functionality.
Definition: smith.cpp:36
constexpr T & get(variant< T0, T1 > &v)
Returns the variant member of specified type.
Definition: variant.hpp:338
SMITH_HOST_DEVICE auto max(dual< gradient_type > a, double b)
Implementation of max for dual numbers.
Definition: dual.hpp:229
bool is_vector_valued(const GeneralCoefficient &coef)
convenience function for querying the type stored in a GeneralCoefficient
SMITH_HOST_DEVICE auto abs(dual< gradient_type > x)
Implementation of absolute value function for dual numbers.
Definition: dual.hpp:219
mfem::ParFiniteElementSpace & space(FieldState field)
Get the space from the primal field of a field states.