Alamo
Mechanics.H
Go to the documentation of this file.
1 //
2 // This is a general purpose integrator that focuses on solving
3 // elasticity/mechanics equations in the absence of other multiphysics
4 // simulations.
5 // It is enabled by :code:`alamo.program=mechanics` if used on its own, in
6 // which case there is no prefix.
7 // If it is being used by another integrator, see that integrator to determine
8 // the value of :code:`[prefix]` (often equal to :code:`elastic`).
9 //
10 // This integrator inherits from :ref:`Integrator::Base::Mechanics`; see
11 // documentation for that integrator for additional parameters.
12 //
13 // :bdg-primary-line:`Model setup`
14 // There are two basic tools for setting up a mechanics problem in this
15 // integrator.
16 //
17 // 1. The :code:`eta` field: this is used to mix models of different types.
18 // Use :code:`nmodels` to specify how many material models to use, and then
19 // specify each model as :code:`model1`, :code:`model2`, etc.
20 // The type of moel is specified using the :code:`alamo.program.mechanics.model`
21 // input.
22 //
23 // Once you have done this, you must determine the spatial distribution of each
24 // model. This is done by choosing an IC for the eta field with :code:`ic.type`.
25 // The :code:`IC::Expression` is the most general and recommended.
26 // The models are then mixed linearly, i.e.
27 //
28 // .. math::
29 //
30 // W_{\textrm{eff}} = \sum_{i=1}^N W_i\,\eta_i(\mathbf{x})
31 //
32 // See the :ref:`Eshelby` test for an example of model mixing.
33 //
34 // 2. The :code:`psi` field: this is used specifically for cases where a "void" region
35 // is desired. Its usage is similar to the :code:`eta` case, and is conceptually
36 // similar in that it scales the model field to near-zero in order to mimic the
37 // (lack of) mechanical behavior in an empty region.
38 // It is important to use :code:`psi` here, for reasons that are discussed in detail
39 // in
40 // `this paper <https://doi.org/10.1007/s00466-023-02325-8>`_.
41 // The initialization of :code:`psi` is similar to that for :code:`eta`.
42 //
43 // See the :ref:`PlateHole` and :ref:`RubberPlateHole` for canonical exmaples.
44 // The :ref:`Integrator::Fracture` and :ref:`Integrator::TopOp` integrators are examples
45 // of integrators that leverage the psi property.
46 //
47 // :bdg-primary-line:`Body forces`
48 // currently have limited support due to the relatively low number of
49 // times they are needed. See the :ref:`Integrator::Base::Mechanics` documentation for
50 // detail.
51 // See the :ref:`TrigTest` test for examples of current body force implementation.
52 //
53 // :bdg-primary-line:`Boundary conditions`
54 // are implemented using the :ref:`BC::Operator::Elastic` classes.
55 // See the documentation on these classes for more detail.
56 // See any of the mechanics-based tests for examples of boundary condition application.
57 //
58 
59 #ifndef INTEGRATOR_MECHANICS_H
60 #define INTEGRATOR_MECHANICS_H
61 #include <iostream>
62 #include <fstream>
63 #include <iomanip>
64 #include <numeric>
65 
66 #include "AMReX.H"
67 #include "AMReX_ParallelDescriptor.H"
68 #include "AMReX_ParmParse.H"
69 
70 #include "IO/ParmParse.H"
72 
73 
74 #include "IC/IC.H"
75 #include "BC/BC.H"
79 
80 #include "IC/Ellipse.H"
81 #include "IC/Voronoi.H"
82 #include "IC/Constant.H"
83 #include "IC/Expression.H"
84 #include "IC/BMP.H"
85 #include "IC/PNG.H"
86 #include "IC/PSRead.H"
87 #include "IC/Constant.H"
88 #include "BC/Constant.H"
89 #include "Numeric/Stencil.H"
90 
91 #include "Model/Solid/Solid.H"
92 #include "Solver/Nonlocal/Linear.H"
93 #include "Solver/Nonlocal/Newton.H"
94 
95 #include "Operator/Operator.H"
96 
97 
98 namespace Integrator
99 {
100 template<class MODEL>
101 class Mechanics : virtual public Base::Mechanics<MODEL>
102 {
103 public:
104 
105  Mechanics() : Base::Mechanics<MODEL>() { }
106  Mechanics(IO::ParmParse& pp) : Base::Mechanics<MODEL>()
107  {
108  Parse(*this, pp);
109  }
110 
111  // Mechanics inputs. See also :ref:`Integrator::Base::Mechanics`
112  static void Parse(Mechanics& value, IO::ParmParse& pp)
113  {
115 
116  int nmodels;
117  pp_query_default("nmodels", nmodels, 1); // Number of elastic model varieties
118  for (int i = 0; i < nmodels; i++)
119  {
120  bool init = false;
121  MODEL tmp_model;
122  if (pp.contains("model"))
123  {
124  pp_queryclass("model", tmp_model);
125  init = true;
126  }
127  std::string name = "model" + std::to_string(i + 1);
128  if (pp.contains(name.c_str()))
129  {
130  pp_queryclass(std::string(name.data()), tmp_model);
131  init = true;
132  }
133 
134  if (!init) Util::Exception(INFO,"No way to initialize ",pp.full(name));
135 
136  value.models.push_back(tmp_model);
137  }
138  Util::Assert(INFO, TEST(value.models.size() > 0));
139  value.RegisterNodalFab(value.eta_mf, value.models.size(), 2, "eta", true);
140  // Refinement threshold for eta field
141  pp_query_default("eta_ref_threshold", value.m_eta_ref_threshold, 0.01);
142  // Refinement threshold for strain gradient
143  pp_query_default("ref_threshold", value.m_elastic_ref_threshold, 0.01);
144  // Explicity impose neumann condition on model at domain boundaries (2d only)
145  pp_query_default("model_neumann_boundary",value.model_neumann_boundary,false);
146 
147  // Read in IC for eta
148  if (nmodels > 1 && pp.contains("ic.type"))
149  {
150  // Select the initial condition for eta
152 
153  value.eta_reset_on_regrid = true;
154  // Whether to re-initialize eta when re-gridding occurs.
155  // Default is false unless eta ic is set, then default is.
156  // true.
157  pp_query_default("eta.reset_on_regrid", value.eta_reset_on_regrid, true);
158  }
159 
160  // Read in IC for psi
161  if (pp.contains("psi.ic.type"))
162  {
163  // Select initial condition for psi field
164  pp.select<IC::Ellipse,IC::Constant,IC::Expression,IC::PSRead,IC::PNG>("psi.ic",value.ic_psi,value.geom);
165 
166  value.bc_psi = new BC::Nothing();
167  value.RegisterNewFab(value.psi_mf, value.bc_psi, 1, 2, "psi", value.plot_psi);
168  value.psi_on = true;
169 
170  value.psi_reset_on_regrid = true;
171  // Whether to re-initialize psi when re-gridding occurs.
172  // Default is false unless a psi ic is set, then default is
173  // true.
174  pp_query_default("psi.reset_on_regrid", value.psi_reset_on_regrid, true);
175  }
176 
177  if (pp.contains("trac_normal.ic.type"))
178  {
179  // Read in IC for the "normal traction" field (applied at diffuse boundaries)
180  pp.select<IC::Ellipse,IC::Constant,IC::Expression,IC::PSRead>("trac_normal.ic",value.ic_trac_normal,value.geom);
181 
182  if (value.ic_trac_normal)
183  {
184  value.bc_trac_normal = new BC::Nothing();
185  value.RegisterNewFab(value.trac_normal_mf, value.bc_trac_normal, 1, 2, "trac_normal", true);
186  }
187  }
189 
190  }
191 
192  void Initialize(int lev) override
193  {
195  eta_mf[lev]->setVal(0.0);
196  if (models.size() > 1 && ic_eta) ic_eta->Initialize(lev, eta_mf);
197  else eta_mf[lev]->setVal(1.0);
198 
199  if (psi_on) ic_psi->Initialize(lev, psi_mf);
201  }
202 
203  virtual void UpdateModel(int a_step, Set::Scalar time) override
204  {
206 
207  if (ic_trac_normal)
208  {
209  for (int lev = 0; lev <= finest_level; ++lev)
210  {
212  psi_mf[lev]->FillBoundary();
213  amrex::Box domain = this->geom[lev].Domain();
214  domain.convert(amrex::IntVect::TheNodeVector());
215  Set::Vector DX(geom[lev].CellSize());
216 
217  for (MFIter mfi(*model_mf[lev], false); mfi.isValid(); ++mfi)
218  {
219  amrex::Box bx = mfi.grownnodaltilebox();
220  bx = bx & domain;
221 
222  amrex::Array4<Set::Vector> const& rhs = rhs_mf[lev]->array(mfi);
223  amrex::Array4<const Set::Scalar> const& psi = psi_mf[lev]->array(mfi);
224  amrex::Array4<const Set::Scalar> const& trac_normal = trac_normal_mf[lev]->array(mfi);
225 
226  amrex::ParallelFor(bx, [=] AMREX_GPU_DEVICE(int i, int j, int k) {
227  Set::Vector grad = Numeric::CellGradientOnNode(psi, i, j, k, 0, DX.data());
228  rhs(i,j,k) = trac_normal(i,j,k) * grad;
229  });
230  }
231  Util::RealFillBoundary(*rhs_mf[lev], geom[lev]);
232  }
233  }
234 
235  if (a_step > 0) return;
236 
237  for (int lev = 0; lev <= finest_level; ++lev)
238  {
239  eta_mf[lev]->FillBoundary();
240 
241  amrex::Box domain = this->geom[lev].Domain();
242  domain.convert(amrex::IntVect::TheNodeVector());
243 
244  Set::Vector DX(geom[lev].CellSize());
245 
246  for (MFIter mfi(*model_mf[lev], false); mfi.isValid(); ++mfi)
247  {
248  amrex::Box bx = mfi.grownnodaltilebox();
249  bx = bx & domain;
250 
251  amrex::Array4<MODEL> const& model = model_mf[lev]->array(mfi);
252  amrex::Array4<const Set::Scalar> const& eta = eta_mf[lev]->array(mfi);
253 
254  amrex::ParallelFor(bx, [=] AMREX_GPU_DEVICE(int i, int j, int k) {
255  model(i, j, k) = MODEL::Zero();
256  for (unsigned int n = 0; n < models.size(); n++)
257  model(i, j, k) += eta(i, j, k, n) * models[n];
258  });
259  }
260 
261 
263  {
264  Util::AssertException(INFO,TEST(AMREX_SPACEDIM==2),"neumann boundary works in 2d only");
265  for (MFIter mfi(*model_mf[lev], false); mfi.isValid(); ++mfi)
266  {
267  amrex::Box bx = mfi.grownnodaltilebox() & domain;
268  amrex::Array4<MODEL> const& model = this->model_mf[lev]->array(mfi);
269  const Dim3 lo = amrex::lbound(domain), hi = amrex::ubound(domain);
270 
271  amrex::ParallelFor(bx, [=] AMREX_GPU_DEVICE(int i, int j, int k)
272  {
273  if (i==lo.x && j==lo.y)
274  model(i,j,k) = 0.5*(model(i+1,j,k)+model(i,j+1,k));
275  else if (i==lo.x && j==hi.y)
276  model(i,j,k) = 0.5*(model(i+1,j,k)+model(i,j-1,k));
277  else if (i==hi.x && j==lo.y)
278  model(i,j,k) = 0.5*(model(i-1,j,k)+model(i,j+1,k));
279  else if (i==hi.x && j==hi.y)
280  model(i,j,k) = 0.5*(model(i-1,j,k)+model(i,j-1,k));
281 
282  else if (i==lo.x)
283  model(i,j,k) = model(i+1,j,k);
284  else if (i==hi.x)
285  model(i,j,k) = model(i-1,j,k);
286  else if (j==lo.y)
287  model(i,j,k) = model(i,j+1,k);
288  else if (j==hi.y)
289  model(i,j,k) = model(i,j-1,k);
290  });
291  }
292  }
293 
294  Util::RealFillBoundary(*model_mf[lev], geom[lev]);
295  }
296  }
297 
298  void TagCellsForRefinement(int lev, amrex::TagBoxArray& a_tags, Set::Scalar a_time, int a_ngrow) override
299  {
301  Base::Mechanics<MODEL>::TagCellsForRefinement(lev, a_tags, a_time, a_ngrow);
302 
303  Set::Vector DX(geom[lev].CellSize());
304  Set::Scalar DXnorm = DX.lpNorm<2>();
305  for (amrex::MFIter mfi(*eta_mf[lev], TilingIfNotGPU()); mfi.isValid(); ++mfi)
306  {
307  amrex::Box bx = mfi.nodaltilebox();
308  amrex::Array4<char> const& tags = a_tags.array(mfi);
309  amrex::Array4<Set::Scalar> const& eta = eta_mf[lev]->array(mfi);
310  amrex::ParallelFor(bx, [=] AMREX_GPU_DEVICE(int i, int j, int k)
311  {
312  auto sten = Numeric::GetStencil(i, j, k, bx);
313  for (int n = 0; n < eta_mf[lev]->nComp(); n++)
314  {
315  Set::Vector grad = Numeric::Gradient(eta, i, j, k, n, DX.data(), sten);
316  if (grad.lpNorm<2>() * DXnorm > m_eta_ref_threshold)
317  tags(i, j, k) = amrex::TagBox::SET;
318  }
319  });
320  if (psi_on)
321  {
322  amrex::Array4<Set::Scalar> const& psi = psi_mf[lev]->array(mfi);
323  amrex::ParallelFor(bx, [=] AMREX_GPU_DEVICE(int i, int j, int k)
324  {
325  auto sten = Numeric::GetStencil(i, j, k, bx);
326  {
327  Set::Vector gradpsi = Numeric::Gradient(psi, i, j, k, 0, DX.data(), sten);
328  if (gradpsi.lpNorm<2>() * DXnorm > m_eta_ref_threshold)
329  tags(i, j, k) = amrex::TagBox::SET;
330  }
331  });
332  }
333  }
334  }
335 
336  void Regrid(int lev, Set::Scalar time) override
337  {
338  if (eta_reset_on_regrid && models.size() > 1 && ic_eta) ic_eta->Initialize(lev, eta_mf, time);
339  if (psi_reset_on_regrid) ic_psi->Initialize(lev, psi_mf, time);
340  }
341 
342 protected:
345  std::vector<MODEL> models;
346  IC::IC* ic_eta = nullptr;
347  IC::IC* ic_psi = nullptr;
348  IC::IC* ic_trac_normal = nullptr;
351  bool psi_reset_on_regrid = false;
352  bool eta_reset_on_regrid = false;
353 
355 
357 
365 };
366 
367 
368 
369 
370 
371 
372 
373 
374 
375 
376 } // namespace Integrator
377 #endif
Numeric::CellGradientOnNode
AMREX_FORCE_INLINE Set::Vector CellGradientOnNode(const amrex::Array4< const Set::Scalar > &f, const int &i, const int &j, const int &k, const int &m, const Set::Scalar dx[AMREX_SPACEDIM])
Definition: Stencil.H:674
IC::BMP
Definition: BMP.H:20
TensionTest.H
IC::IC::Initialize
void Initialize(const int &a_lev, Set::Field< Set::Scalar > &a_field, Set::Scalar a_time=0.0)
Definition: IC.H:35
Util::RealFillBoundary
AMREX_FORCE_INLINE void RealFillBoundary(amrex::FabArray< amrex::BaseFab< T >> &a_mf, const amrex::Geometry &)
Definition: Util.H:319
BC::BC< Set::Scalar >
IC::IC
Pure abstract IC object from which all other IC objects inherit.
Definition: IC.H:21
Integrator::Mechanics::ic_psi
IC::IC * ic_psi
Definition: Mechanics.H:347
Integrator::Mechanics::eta_reset_on_regrid
bool eta_reset_on_regrid
Definition: Mechanics.H:352
Integrator::Mechanics
Definition: Mechanics.H:101
Integrator::Integrator::RegisterNewFab
void RegisterNewFab(Set::Field< Set::Scalar > &new_fab, BC::BC< Set::Scalar > *new_bc, int ncomp, int nghost, std::string name, bool writeout, std::vector< std::string > suffix={})
Definition: Integrator.cpp:314
IC::Ellipse
Definition: Ellipse.H:15
Integrator::Base::Mechanics
Definition: Mechanics.H:23
Integrator::Mechanics::psi_reset_on_regrid
bool psi_reset_on_regrid
Definition: Mechanics.H:351
TEST
#define TEST(x)
Definition: Util.H:21
Integrator::Base::Mechanics::m_elastic_ref_threshold
Set::Scalar m_elastic_ref_threshold
Definition: Mechanics.H:489
Integrator::Mechanics::eta_mf
Set::Field< Set::Scalar > eta_mf
Definition: Mechanics.H:343
IO::ParmParse::full
std::string full(std::string name)
Definition: ParmParse.H:445
Expression.H
PSRead.H
Integrator::Mechanics::Mechanics
Mechanics(IO::ParmParse &pp)
Definition: Mechanics.H:106
IC::PSRead
Definition: PSRead.H:21
Integrator::Mechanics::ic_eta
IC::IC * ic_eta
Definition: Mechanics.H:346
Integrator::Mechanics::Regrid
void Regrid(int lev, Set::Scalar time) override
Definition: Mechanics.H:336
Integrator::Base::Mechanics::psi_mf
Set::Field< Set::Scalar > psi_mf
Definition: Mechanics.H:455
Set::Field< Set::Scalar >
Definition: Set.H:236
Integrator::Mechanics::Mechanics
Mechanics()
Definition: Mechanics.H:105
Integrator::Base::Mechanics::model_mf
Set::Field< MODEL > model_mf
Definition: Mechanics.H:453
Expression.H
Integrator::Mechanics::m_eta_ref_threshold
Set::Scalar m_eta_ref_threshold
Definition: Mechanics.H:344
Util::AssertException
AMREX_FORCE_INLINE void AssertException(std::string file, std::string func, int line, std::string smt, bool pass, Args const &... args)
Definition: Util.H:230
Integrator::Base::Mechanics::m_type
Type m_type
Definition: Mechanics.H:459
Set::Vector
Eigen::Matrix< amrex::Real, AMREX_SPACEDIM, 1 > Vector
Definition: Base.H:20
Constant.H
ParmParse.H
Numeric::Gradient
AMREX_FORCE_INLINE Set::Vector Gradient(const amrex::Array4< const Set::Scalar > &f, const int &i, const int &j, const int &k, const int &m, const Set::Scalar dx[AMREX_SPACEDIM], std::array< StencilType, AMREX_SPACEDIM > stencil=DefaultType)
Definition: Stencil.H:656
Constant.H
Integrator::Base::Mechanics::Initialize
void Initialize(int lev) override
Use the #ic object to initialize::Temp.
Definition: Mechanics.H:134
Integrator::Mechanics::model_neumann_boundary
bool model_neumann_boundary
Definition: Mechanics.H:354
Integrator::Mechanics::bc_trac_normal
BC::BC< Set::Scalar > * bc_trac_normal
Definition: Mechanics.H:350
Set::Scalar
amrex::Real Scalar
Definition: Base.H:19
PNG.H
Integrator::Mechanics::bc_psi
BC::BC< Set::Scalar > * bc_psi
Definition: Mechanics.H:349
pp_queryclass
#define pp_queryclass(...)
Definition: ParmParse.H:106
Solid.H
Integrator::Mechanics::ic_trac_normal
IC::IC * ic_trac_normal
Definition: Mechanics.H:348
IC::Voronoi
Definition: Voronoi.H:10
Integrator::Mechanics::models
std::vector< MODEL > models
Definition: Mechanics.H:345
IC::PNG
Definition: PNG.H:24
Mechanics.H
Constant.H
Integrator::Mechanics::TagCellsForRefinement
void TagCellsForRefinement(int lev, amrex::TagBoxArray &a_tags, Set::Scalar a_time, int a_ngrow) override
Definition: Mechanics.H:298
BC::Nothing
Definition: Nothing.H:11
Integrator::Mechanics::trac_normal_mf
Set::Field< Set::Scalar > trac_normal_mf
Definition: Mechanics.H:356
Util::Exception
void Exception(std::string file, std::string func, int line, Args const &... args)
Definition: Util.H:202
IO::ParmParse::contains
bool contains(std::string name)
Definition: ParmParse.H:153
Util::Assert
AMREX_FORCE_INLINE void Assert(std::string file, std::string func, int line, std::string smt, bool pass, Args const &... args)
Definition: Util.H:67
Integrator::Mechanics::UpdateModel
virtual void UpdateModel(int a_step, Set::Scalar time) override
Definition: Mechanics.H:203
pp_query_default
#define pp_query_default(...)
Definition: ParmParse.H:100
Integrator
Collection of numerical integrator objects.
Definition: AllenCahn.H:40
IC::Constant
Definition: Constant.H:18
Newton.H
BMP.H
Integrator::Integrator::RegisterNodalFab
void RegisterNodalFab(Set::Field< Set::Scalar > &new_fab, int ncomp, int nghost, std::string name, bool writeout, std::vector< std::string > suffix={})
Definition: Integrator.cpp:332
IC::Expression
Definition: Expression.H:44
Voronoi.H
Integrator::Base::Mechanics::TagCellsForRefinement
void TagCellsForRefinement(int lev, amrex::TagBoxArray &a_tags, Set::Scalar, int) override
Definition: Mechanics.H:429
BC.H
IO::ParmParse
Definition: ParmParse.H:112
Integrator::Base::Mechanics::plot_psi
bool plot_psi
Definition: Mechanics.H:500
Integrator::Mechanics::Parse
static void Parse(Mechanics &value, IO::ParmParse &pp)
Definition: Mechanics.H:112
IO::ParmParse::queryclass
void queryclass(std::string name, T *value, std::string file="", std::string func="", int line=-1)
Definition: ParmParse.H:455
Integrator::Mechanics::Initialize
void Initialize(int lev) override
Definition: Mechanics.H:192
INFO
#define INFO
Definition: Util.H:20
IC.H
Numeric::GetStencil
static AMREX_FORCE_INLINE std::array< StencilType, AMREX_SPACEDIM > GetStencil(const int i, const int j, const int k, const amrex::Box domain)
Definition: Stencil.H:20
Integrator::Base::Mechanics::rhs_mf
Set::Field< Set::Vector > rhs_mf
Definition: Mechanics.H:462
Integrator::Base::Mechanics::psi_on
bool psi_on
Definition: Mechanics.H:456
Linear.H
Util::Message
void Message(std::string file, std::string func, int line, Args const &... args)
Definition: Util.H:138
IO::ParmParse::select
void select(std::string name, PTRTYPE *&ic_eta, Args &&... args)
Definition: ParmParse.H:541
Ellipse.H