1#ifndef INTEGRATOR_BASE_MECHANICS_H
2#define INTEGRATOR_BASE_MECHANICS_H
10#include "Numeric/Stencil.H"
14#include "Operator/Operator.H"
44 BL_PROFILE(
"Integrator::Base::Mechanics::Parse");
87 pp_forbid(
"viscous.mu",
"replaced with viscous.mu_dashpot");
89 pp_forbid(
"viscous.mu2",
"replaced with viscous.mu_newton");
92 std::string velocity_ic_str;
145 BL_PROFILE(
"Integrator::Base::Mechanics::Initialize");
148 disp_mf[lev]->setVal(Set::Vector::Zero());
158 else rhs_mf[lev]->setVal(Set::Vector::Zero());
165 BL_PROFILE(
"Integrator::Base::Mechanics::TimeStepBegin");
168 for (
int lev = 0; lev <= finest_level; ++lev)
171 rhs_mf[lev]->setVal(Set::Vector::Zero());
181 if (a_time <
tstart)
return;
204 amrex::Box domain = geom[lev].Domain();
205 domain.convert(amrex::IntVect::TheNodeVector());
207 const amrex::Real* DX = geom[lev].CellSize();
208 for (MFIter mfi(*
disp_mf[lev],
false); mfi.isValid(); ++mfi)
210 amrex::Box bx = mfi.nodaltilebox();
213 amrex::Array4<MODEL>
const& model =
model_mf[lev]->array(mfi);
214 amrex::Array4<Set::Matrix>
const& stress =
stress_mf[lev]->array(mfi);
215 amrex::Array4<Set::Matrix>
const& strain =
strain_mf[lev]->array(mfi);
216 amrex::Array4<const Set::Vector>
const& disp =
disp_mf[lev]->array(mfi);
219 amrex::ParallelFor(bx, [=] AMREX_GPU_DEVICE(
int i,
int j,
int k)
225 stress(i, j, k) = model(i, j, k).DW(F);
231 stress(i, j, k) = model(i, j, k).DW(gradu);
232 strain(i, j, k) = 0.5 * (gradu + gradu.transpose());
243 BL_PROFILE(
"Integrator::Base::Mechanics::Advance");
245 const amrex::Real* DX = geom[lev].CellSize();
247 amrex::Box domain = geom[lev].Domain();
248 domain.convert(amrex::IntVect::TheNodeVector());
249 const amrex::Dim3 lo = amrex::lbound(domain), hi = amrex::ubound(domain);
258 for (amrex::MFIter mfi(*
disp_mf[lev], amrex::TilingIfNotGPU()); mfi.isValid(); ++mfi)
271 amrex::Box bx = mfi.grownnodaltilebox() & domain;
272 amrex::ParallelFor(bx, [=] AMREX_GPU_DEVICE(
int i,
int j,
int k)
276 sig(i, j, k) = model(i, j, k).DW(eps(i, j, k));
280 bx = mfi.nodaltilebox() & domain;
281 amrex::ParallelFor(bx, [=] AMREX_GPU_DEVICE(
int i,
int j,
int k)
284 bool AMREX_D_DECL(xmin = (i == lo.x), ymin = (j == lo.y), zmin = (k == lo.z));
285 bool AMREX_D_DECL(xmax = (i == hi.x), ymax = (j == hi.y), zmax = (k == hi.z));
287 if (AMREX_D_TERM(xmax || xmin, || ymax || ymin, || zmax || zmin))
293 for (
int d = 0; d < AMREX_SPACEDIM; d++)
297 unew(i,j,k)(d) = b(i,j,k)(d);
303 AMREX_D_DECL(xmax,ymax,zmax));
309 Set::Matrix DW_F0 = model(i,j,k).DW(Set::Matrix::Zero());
310 MATRIX4 ddw = model(i,j,k).DDW(eps(i,j,k));
313 for (
int p = 0; p < AMREX_SPACEDIM; p++)
314 for (
int q = 0; q < AMREX_SPACEDIM; q++)
316 for (
int r = 0; r < AMREX_SPACEDIM; r++)
317 for (
int s = 0; s < AMREX_SPACEDIM; s++)
319 A(p,r) += ddw(p,q,r,s) * phi(s) * N(q);
321 rhs(p) -= ddw(p,q,r,s) * eps(i,j,k)(r,s) * N(q);
324 rhs(p) -= DW_F0(p,q)*N(q);
328 unew(i,j,k)(d) = u(i,j,k)(d) + delta_u(d);
329 vnew(i,j,k)(d) = (unew(i,j,k)(d) - u(i,j,k)(d))/
dt;
358 vnew(i, j, k) = v(i, j, k) +
dt * udotdot;
359 unew(i, j, k) = u(i, j, k) +
dt * v(i, j, k);
365 for (amrex::MFIter mfi(*
disp_mf[lev],
false); mfi.isValid(); ++mfi)
367 amrex::Box bx = mfi.grownnodaltilebox() & domain;
368 amrex::Array4<Set::Matrix>
const& eps = (*
strain_mf[lev]).array(mfi);
369 amrex::Array4<Set::Matrix>
const& sig = (*
stress_mf[lev]).array(mfi);
370 amrex::Array4<MODEL>
const& model = (*
model_mf[lev]).array(mfi);
371 amrex::ParallelFor(bx, [=] AMREX_GPU_DEVICE(
int i,
int j,
int k)
373 model(i, j, k).Advance(
dt, eps(i, j, k), sig(i, j, k),time);
381 const amrex::MFIter& mfi,
const amrex::Box& a_box)
override
383 BL_PROFILE(
"Integrator::Base::Mechanics::Integrate");
386 if (amrex::ParallelDescriptor::NProcs() > 1 && a_box.contains(amrex::IntVect::TheZeroVector()) &&
389 Util::Warning(
INFO,
"There is a known bug when calculating trac/disp in Base::Mechanics in parallel.");
390 Util::Warning(
INFO,
"The thermo.dat values likely will not be correct; use the boxlib output instead.");
393 const amrex::Real* DX = geom[amrlev].CellSize();
394 amrex::Box domain = geom[amrlev].Domain();
395 domain.convert(amrex::IntVect::TheNodeVector());
397 amrex::Box
box = a_box;
398 box.convert(amrex::IntVect::TheNodeVector());
402#if AMREX_SPACEDIM == 2
405#elif AMREX_SPACEDIM == 3
409 const Dim3 hi = amrex::ubound(domain);
410 const Dim3 boxhi = amrex::ubound(
box);
412 amrex::Array4<const Set::Matrix>
const& stress = (*
stress_mf[amrlev]).array(mfi);
413 amrex::Array4<const Set::Vector>
const& disp = (*
disp_mf[amrlev]).array(mfi);
414 amrex::ParallelFor(
box, [=] AMREX_GPU_DEVICE(
int i,
int j,
int k)
416#if AMREX_SPACEDIM == 2
417 if (i == hi.x && j < boxhi.y)
419 trac_hi[0] += (0.5 * (stress(i, j, k) + stress(i, j + 1, k)) * da0);
420 disp_hi[0] = disp(i, j, k);
422 if (j == hi.y && i < boxhi.x)
424 trac_hi[1] += (0.5 * (stress(i, j, k) + stress(i + 1, j, k)) * da1);
425 disp_hi[1] = disp(i, j, k);
427#elif AMREX_SPACEDIM == 3
428 if (i == hi.x && (j < boxhi.y && k < boxhi.z))
430 trac_hi[0] += (0.25 * (stress(i, j, k) + stress(i, j + 1, k)
431 + stress(i, j, k + 1) + stress(i, j + 1, k + 1)) * da);
432 disp_hi[0] = disp(i, j, k);
441 BL_PROFILE(
"Integrator::Base::Mechanics::TagCellsForRefinement");
446 for (amrex::MFIter mfi(*
strain_mf[lev], TilingIfNotGPU()); mfi.isValid(); ++mfi)
448 amrex::Box bx = mfi.tilebox();
449 bx.convert(amrex::IntVect::TheCellVector());
450 amrex::Array4<char>
const& tags = a_tags.array(mfi);
451 amrex::Array4<Set::Matrix>
const& eps =
strain_mf[lev]->array(mfi);
452 amrex::ParallelFor(bx, [=] AMREX_GPU_DEVICE(
int i,
int j,
int k)
456 tags(i, j, k) = amrex::TagBox::SET;
#define pp_query_validate(...)
#define pp_query_default(...)
#define pp_queryclass(...)
void SetTime(const Set::Scalar a_time)
virtual void Init(amrex::MultiFab *a_rhs, const amrex::Geometry &a_geom, bool a_homogeneous=false) const =0
virtual std::array< Type, AMREX_SPACEDIM > getType(const int &i, const int &j, const int &k, const amrex::Box &domain)=0
Pure abstract IC object from which all other IC objects inherit.
void Initialize(const int &a_lev, Set::Field< T > &a_field, Set::Scalar a_time=0.0)
Initialize using a trigonometric series.
bool contains(std::string name)
void select(std::string name, PTRTYPE *&ic_eta, Args &&... args)
Set::Field< Set::Vector > disp_mf
virtual void TimeStepBegin(Set::Scalar a_time, int a_step) override
Set::Field< Set::Matrix > strain_mf
Set::Field< MATRIX4 > ddw_mf
bool m_zero_out_displacement
IC::IC< Set::Vector > * ic_rhs
void Integrate(int amrlev, Set::Scalar, int, const amrex::MFIter &mfi, const amrex::Box &a_box) override
Set::Field< Set::Vector > vel_old_mf
Set::Field< Set::Vector > vel_mf
int m_max_coarsening_level
static void Parse(Mechanics &value, IO::ParmParse &pp)
Set::Scalar m_elastic_ref_threshold
IC::IC< Set::Vector > * velocity_ic
Set::Vector disp_hi[AMREX_SPACEDIM]
void Initialize(int lev) override
Use the #ic object to initialize::Temp.
Set::Matrix4< AMREX_SPACEDIM, MODEL::sym > MATRIX4
void Advance(int lev, Set::Scalar time, Set::Scalar dt) override
Set::Field< Set::Vector > disp_old_mf
Solver::Nonlocal::Newton< MODEL > solver
void TagCellsForRefinement(int lev, amrex::TagBoxArray &a_tags, Set::Scalar, int) override
Set::Field< Set::Matrix > stress_mf
Set::Field< Set::Vector > res_mf
Set::Field< Set::Vector > rhs_mf
BC::Operator::Elastic::Elastic * bc
Set::Field< Set::Scalar > psi_mf
virtual void UpdateModel(int a_step, Set::Scalar a_time)=0
Set::Field< MODEL > model_mf
Set::Vector trac_hi[AMREX_SPACEDIM]
std::vector< amrex::Box > box
amrex::Vector< amrex::Real > dt
Timesteps for each level of refinement.
void RegisterGeneralFab(Set::Field< T > &new_fab, int ncomp, int nghost, bool evolving=true)
Add a templated nodal field.
void RegisterIntegratedVariable(Set::Scalar *integrated_variable, std::string name, bool extensive=true)
Register a variable to be integrated over the spatial domain using the Integrate function.
void SetBC(::BC::Operator::Elastic::Elastic *a_bc)
The different types of Boundary Condtiions are listed in the BC::Operator::Elastic documentation.
void SetUniform(bool a_uniform)
virtual void SetHomogeneous(bool a_homogeneous) override
amrex::Array4< T > Patch(int lev, amrex::MFIter &mfi) const &
AMREX_FORCE_INLINE Set::Scalar norm()
void setPsi(Set::Field< Set::Scalar > &a_psi)
void Define(Operator::Elastic< T::sym > &a_op)
void compLinearSolverResidual(Set::Field< Set::Vector > &a_res_mf, Set::Field< Set::Vector > &a_u_mf, Set::Field< Set::Vector > &a_b_mf)
Set::Scalar solve(const Set::Field< Set::Vector > &a_u_mf, const Set::Field< Set::Vector > &a_b_mf, Set::Field< T > &a_model_mf, Real a_tol_rel, Real a_tol_abs, const char *checkpoint_file=nullptr)
Collection of numerical integrator objects.
AMREX_FORCE_INLINE Set::Scalar Laplacian(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)
static AMREX_FORCE_INLINE std::array< StencilType, AMREX_SPACEDIM > GetStencil(const int i, const int j, const int k, const amrex::Box domain)
AMREX_FORCE_INLINE Set::Vector NodeGradientOnCell(const amrex::Array4< const Set::Scalar > &f, const int &i, const int &j, const int &k, const Set::Scalar dx[AMREX_SPACEDIM])
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)
AMREX_FORCE_INLINE Set::Vector Divergence(const amrex::Array4< const Set::Matrix > &dw, const int &i, const int &j, const int &k, const Set::Scalar DX[AMREX_SPACEDIM], std::array< StencilType, AMREX_SPACEDIM > &stencil=DefaultType)
AMREX_FORCE_INLINE std::pair< Set::Vector, Set::Matrix > GradientSplit(const amrex::Array4< const Set::Vector > &f, const int &i, const int &j, const int &k, const Set::Scalar dx[AMREX_SPACEDIM], std::array< StencilType, AMREX_SPACEDIM > stencil=DefaultType)
Eigen::Matrix< amrex::Real, AMREX_SPACEDIM, 1 > Vector
AMREX_FORCE_INLINE Vector Normal(AMREX_D_DECL(bool xmin, bool ymin, bool zmin), AMREX_D_DECL(bool xmax, bool ymax, bool zmax))
Eigen::Matrix< amrex::Real, AMREX_SPACEDIM, AMREX_SPACEDIM > Matrix
AMREX_FORCE_INLINE void RealFillBoundary(amrex::FabArray< amrex::BaseFab< T > > &a_mf, const amrex::Geometry &)
void Abort(const char *msg)
void Warning(std::string file, std::string func, int line, Args const &... args)