1#ifndef INTEGRATOR_SUTURECRACK_H
2#define INTEGRATOR_SUTURECRACK_H
9#include "AMReX_ParallelDescriptor.H"
10#include "AMReX_ParmParse.H"
21#include "Operator/Operator.H"
28#include "Model/Solid/Linear/IsotropicDegradable.H"
36#include "Numeric/Stencil.H"
37#include <eigen3/Eigen/Dense>
51 pp_crack.query(
"modulus_scaling_max",
crack.scaleModulusMax);
52 pp_crack.query(
"refinement_threshold",
crack.refinement_threshold);
53 pp_crack.query(
"df_tol_rel",
crack.driving_force_tolerance_rel);
54 pp_crack.query(
"df_tol_abs",
crack.driving_force_tolerance_abs);
58 crack.cracktype = tmpbdy;
63 if (
crack.ic_type ==
"notch")
65 IC::Notch *tmpic =
new IC::Notch(geom);
80 pp_material.query(
"refinement_threshold",
material.refinement_threshold);
83 pp_material_ic.query(
"type",
material.ic_type);
100 if (pp_load.countval(
"body_force")) pp_load.
queryarr(
"body_force",
loading.body_force);
101 pp_load.query(
"val",
loading.val);
104 pp_elastic.query(
"df_mult",
elastic.df_mult);
108 pp_solver.query(
"int",
sol.interval);
109 pp_solver.query(
"type",
sol.type);
110 pp_solver.query(
"max_iter",
sol.max_iter);
111 pp_solver.query(
"max_fmg_iter",
sol.max_fmg_iter);
112 pp_solver.query(
"verbose",
sol.verbose);
113 pp_solver.query(
"cgverbose",
sol.cgverbose);
114 pp_solver.query(
"tol_rel",
sol.tol_rel);
115 pp_solver.query(
"tol_abs",
sol.tol_abs);
116 pp_solver.query(
"cg_tol_rel",
sol.cg_tol_rel);
117 pp_solver.query(
"cg_tol_abs",
sol.cg_tol_abs);
118 pp_solver.query(
"use_fsmooth",
sol.use_fsmooth);
119 pp_solver.query(
"agglomeration",
sol.agglomeration);
120 pp_solver.query(
"consolidation",
sol.consolidation);
121 pp_solver.query(
"bottom_solver",
sol.bottom_solver);
122 pp_solver.query(
"linop_maxorder",
sol.linop_maxorder);
123 pp_solver.query(
"max_coarsening_level",
sol.max_coarsening_level);
124 pp_solver.query(
"verbose",
sol.verbose);
125 pp_solver.query(
"cg_verbose",
sol.cgverbose);
126 pp_solver.query(
"bottom_max_iter",
sol.bottom_max_iter);
127 pp_solver.query(
"max_fixed_iter",
sol.max_fixed_iter);
128 pp_solver.query(
"bottom_tol",
sol.bottom_tol);
129 pp_solver.query(
"pre_smooth",
sol.pre_smooth);
130 pp_solver.query(
"post_smooth",
sol.post_smooth);
151 elastic.disp[ilev]->setVal(0.0);
152 elastic.strain[ilev]->setVal(0.0);
153 elastic.stress[ilev]->setVal(0.0);
154 elastic.rhs[ilev]->setVal(0.0);
155 elastic.energy[ilev]->setVal(0.0);
156 elastic.residual[ilev]->setVal(0.0);
157 elastic.energy_pristine[ilev] -> setVal(0.);
158 elastic.energy_pristine_old[ilev] -> setVal(0.);
162 else material.modulus_field[ilev]->setVal(1.0);
171 crack.field[ilev]->setVal(1.0);
172 crack.field_old[ilev]->setVal(1.0);
181 if (
crack.driving_force_norm /
crack.driving_force_reference <
crack.driving_force_tolerance_rel)
183 if (
crack.driving_force_norm <
crack.driving_force_tolerance_abs)
186 if (!
elastic.do_solve_now)
return;
188 material.brittlemodeltype.DegradeModulus(0.0);
190 for (
int ilev = 0; ilev <
nlevels; ++ilev)
192 std::swap(
elastic.energy_pristine_old[ilev],
elastic.energy_pristine[ilev]);
198 for (
int ilev = 0; ilev <
nlevels; ++ilev)
204 for (amrex::MFIter mfi(*
elastic.disp[ilev],
true); mfi.isValid(); ++mfi)
206 amrex::Box
box = mfi.grownnodaltilebox();
207 amrex::Array4<const Set::Scalar>
const& c_new = (*
crack.field[ilev]).array(mfi);
208 amrex::Array4<const Set::Scalar>
const& modbox = (*
material.modulus_field[ilev]).array(mfi);
209 amrex::Array4<brittle_fracture_model_type_test> modelfab = (
material.brittlemodel)[ilev]->array(mfi);
211 amrex::ParallelFor (
box,[=] AMREX_GPU_DEVICE(
int i,
int j,
int k){
217 _temp =
crack.cracktype->g_phi(c_new(i,j,k,0),0);
223 _temp =
crack.scaleModulusMax + _temp * (1. -
crack.scaleModulusMax);
225 modelfab(i,j,k,0).DegradeModulus(1-_temp);
232 for (
int ilev = 0; ilev <
nlevels; ++ilev)
234 const Real* DX = geom[ilev].CellSize();
235 Set::Scalar volume = AMREX_D_TERM(DX[0],*DX[1],*DX[2]);
237 AMREX_D_TERM(
elastic.rhs[ilev]->setVal(
loading.body_force(0)*volume,0,1);,
246 info.setAgglomeration(
sol.agglomeration);
247 info.setConsolidation(
sol.consolidation);
248 info.setMaxCoarseningLevel(
sol.max_coarsening_level);
252 op_b.
define(geom, grids, dmap, info);
253 op_b.setMaxOrder(
sol.linop_maxorder);
264 solver.setBottomTolerance(
sol.cg_tol_rel) ;
265 solver.setBottomToleranceAbs(
sol.cg_tol_abs) ;
268 if (
sol.bottom_solver ==
"cg") solver.setBottomSolver(MLMG::BottomSolver::cg);
269 else if (
sol.bottom_solver ==
"bicgstab") solver.setBottomSolver(MLMG::BottomSolver::bicgstab);
280 for (
int ilev = 0; ilev <
nlevels; ilev++)
289 elastic.energy_pristine[ilev]->setVal(0.0);
291 for (amrex::MFIter mfi(*
elastic.strain[ilev],
true); mfi.isValid(); ++mfi)
293 const amrex::Box&
box = mfi.grownnodaltilebox();
294 amrex::Array4<const Set::Scalar>
const& strain_box = (*
elastic.strain[ilev]).array(mfi);
296 amrex::Array4<Set::Scalar>
const& energy_box = (*
elastic.energy_pristine[ilev]).array(mfi);
297 amrex::Array4<Set::Scalar>
const& energy_box_old = (*
elastic.energy_pristine_old[ilev]).array(mfi);
299 amrex::ParallelFor (
box,[=] AMREX_GPU_DEVICE(
int i,
int j,
int k){
301 Eigen::SelfAdjointEigenSolver<Set::Matrix> eigensolver(eps);
308 for (
int n = 0; n < AMREX_SPACEDIM; n++)
310 if(eValues(n) > 0.0) epsp += eValues(n)*(eVectors.col(n)*eVectors.col(n).transpose());
311 else epsn += eValues(n)*(eVectors.col(n)*eVectors.col(n).transpose());
319 energy_box(i,j,k,0) =
material.brittlemodeltype.W(epsp);
320 energy_box(i,j,k,0) = energy_box(i,j,k,0) > energy_box_old(i,j,k,0) ? energy_box(i,j,k,0) : energy_box_old(i,j,k,0);
332 std::swap(
crack.field_old[lev],
crack.field[lev]);
342 amrex::Box domain(geom[lev].Domain());
344 domain.convert(amrex::IntVect::TheNodeVector());
345 const amrex::Dim3 lo= amrex::lbound(domain), hi = amrex::ubound(domain);
347 for ( amrex::MFIter mfi(*
crack.field[lev],
true); mfi.isValid(); ++mfi )
349 const amrex::Box& bx = mfi.validbox();
350 amrex::Array4<const Set::Scalar>
const& c_old = (*
crack.field_old[lev]).array(mfi);
351 amrex::Array4<Set::Scalar>
const& df = (*
crack.driving_force[lev]).array(mfi);
352 amrex::Array4<Set::Scalar>
const& c_new = (*
crack.field[lev]).array(mfi);
353 amrex::Array4<const Set::Scalar>
const& energy_box = (*
elastic.energy_pristine[lev]).array(mfi);
354 amrex::Array4<const Set::Scalar>
const& modbox = (*
material.modulus_field[lev]).array(mfi);
356 amrex::ParallelFor (bx,[=] AMREX_GPU_DEVICE(
int i,
int j,
int k){
358#if AMREX_SPACEDIM !=2
361 if (i == lo.x && j == lo.y) c_new(i,j,k,0) = c_new(i+1,j+1,k,0);
362 else if (i == lo.x && j == hi.y) c_new(i,j,k,0) = c_new(i+1,j-1,k,0);
363 else if (i == hi.x && j == lo.y) c_new(i,j,k,0) = c_new(i-1,j+1,k,0);
364 else if (i == hi.x && j == hi.y) c_new(i,j,k,0) = c_new(i-1,j-1,k,0);
365 else if (i == lo.x) c_new(i,j,k,0) = c_new(i+1,j,k,0);
366 else if (j == lo.y) c_new(i,j,k,0) = c_new(i,j+1,k,0);
367 else if (i == hi.x) c_new(i,j,k,0) = c_new(i-1,j,k,0);
368 else if (j == hi.y) c_new(i,j,k,0) = c_new(i,j-1,k,0);
376 if (std::isnan(en_cell))
Util::Abort(
INFO,
"Nans detected in en_cell. energy_box(i,j,k,0) = ", energy_box(i,j,k,0));
377 if (std::isinf(c_old(i,j,k,0)))
Util::Abort(
INFO,
"Infs detected in c_old");
380 df(i,j,k,0) =
crack.cracktype->Dg_phi(c_old(i,j,k,0),0.0)*en_cell*
elastic.df_mult;
381 rhs +=
crack.cracktype->Dg_phi(c_old(i,j,k,0),0.0)*en_cell*
elastic.df_mult;
390 _temp *= modbox(i,j,k,m);
394 df(i,j,k,1) = Gc*
crack.cracktype->Dw_phi(c_old(i,j,k,0),0.0)/(4.0*
crack.cracktype->Zeta(0.0))*
crack.mult_df_Gc;
395 df(i,j,k,2) = 2.0*
crack.cracktype->Zeta(0.0)*Gc*laplacian*
crack.mult_df_lap;
397 rhs += Gc*
crack.cracktype->Dw_phi(c_old(i,j,k,0),0.)/(4.0*
crack.cracktype->Zeta(0.0))*
crack.mult_df_Gc;
400 rhs -= 2.0*
crack.cracktype->Zeta(0.0)*Gc*laplacian*
crack.mult_df_lap;
407 df(i,j,k,3) = std::max(0.,
rhs -
crack.cracktype->DrivingForceThreshold(c_old(i,j,k,0)));
408 if(std::isnan(
rhs))
Util::Abort(
INFO,
"Dwphi = ",
crack.cracktype->Dw_phi(c_old(i,j,k,0),0.0),
". c_old(i,j,k,0) = ",c_old(i,j,k,0));
409 c_new(i,j,k,0) = c_old(i,j,k,0) -
dt*std::max(0.,
rhs -
crack.cracktype->DrivingForceThreshold(c_old(i,j,k,0)))*
crack.cracktype->Mobility(c_old(i,j,k,0));
411 if (c_new (i,j,k,0) < 0.0) c_new(i,j,k,0) = 0.0;
412 if (c_new (i,j,k,0) > 1.0) c_new(i,j,k,0) = 1.0;
422 const amrex::Real *DX = geom[lev].CellSize();
425 amrex::Box domain(geom[lev].Domain());
426 domain.convert(amrex::IntVect::TheNodeVector());
428 for (amrex::MFIter mfi(*
crack.field[lev], TilingIfNotGPU()); mfi.isValid(); ++mfi)
430 const amrex::Box bx = mfi.tilebox() & domain.grow(-1);
431 amrex::Array4<char>
const &tags = a_tags.array(mfi);
432 amrex::Array4<const Set::Scalar>
const &c_new = (*
crack.field[lev]).array(mfi);
433 amrex::Array4<const Set::Scalar>
const &modbox = (*
material.modulus_field[lev]).array(mfi);
435 amrex::ParallelFor(bx, [=] AMREX_GPU_DEVICE(
int i,
int j,
int k) {
438 if (dxnorm * grad.lpNorm<2>() >=
crack.refinement_threshold || dxnorm * grad2.lpNorm<2>() >=
material.refinement_threshold)
439 tags(i, j, k) = amrex::TagBox::SET;
446 const amrex::Real* DX = geom[amrlev].CellSize();
447 const Set::Scalar DV = AMREX_D_TERM(DX[0],*DX[1],*DX[2]);
449 amrex::Array4<const Set::Scalar>
const &df = (*
crack.driving_force[amrlev]).array(mfi);
451 amrex::ParallelFor(
box, [=] AMREX_GPU_DEVICE(
int i,
int j,
int k)
453 crack.driving_force_norm += df(i,j,k,3) * DV;
460 crack.driving_force_reference =
crack.driving_force_norm;
#define pp_queryclass(...)
Pure abstract IC object from which all other IC objects inherit.
Initialize Laminates in a matrix.
void queryclass(std::string name, T *value, std::string file="", std::string func="", int line=-1)
int queryarr(std::string name, std::vector< T > &value, std::string, std::string, int)
std::vector< amrex::Box > box
void RegisterNodalFab(Set::Field< Set::Scalar > &new_fab, int ncomp, int nghost, std::string name, bool writeout, std::vector< std::string > suffix={})
Add a new node-based scalar field.
amrex::Vector< amrex::Real > dt
Timesteps for each level of refinement.
bool integrate_variables_before_advance
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.
bool integrate_variables_after_advance
void TimeStepComplete(amrex::Real, int)
suture_fracture_model_type brittlemodeltype
Set::Field< Set::Scalar > field
crack field at current time step
IC::IC * ic
crack IC. See IC/Notch and IC/Ellipsoid
struct Integrator::SutureCrack::@26 elastic
Set::Field< Set::Scalar > field_old
crack field at previous time step
Set::Scalar driving_force_norm
Set::Field< suture_fracture_model_type > brittlemodel
Set::Field< Set::Scalar > rhs
rhs fab for elastic solution
Set::Scalar driving_force_tolerance_rel
Set::Scalar driving_force_reference
Set::Field< Set::Scalar > modulus_field
struct Integrator::SutureCrack::@27 crack
Set::Scalar scaleModulusMax
material modulus ratio inside crack (default = 0.02).
Set::Scalar mult_df_Gc
Multiplier for Gc/zeta term.
struct Integrator::SutureCrack::@28 material
void TimeStepBegin(Set::Scalar, int iter) override
void TagCellsForRefinement(int lev, amrex::TagBoxArray &a_tags, amrex::Real, int) override
Set::Field< Set::Scalar > energy
total elastic energy
Set::Scalar mult_df_lap
Multiplier for the laplacian term.
struct Integrator::SutureCrack::@29 sol
Set::Field< Set::Scalar > residual
residual field for solver
BC::Operator::Elastic::Constant brittlebc
elastic BC if using brittle fracture
Set::Field< Set::Scalar > energy_pristine
energy of the prisitne material as if no crack is present
void Integrate(int amrlev, Set::Scalar, int, const amrex::MFIter &mfi, const amrex::Box &box)
Set::Scalar refinement_threshold
Model::Interface::Crack::Crack * cracktype
type of crack. See Crack/Constant or Crack/Sin
std::string bottom_solver
Set::Field< Set::Scalar > driving_force
crack driving forces.
void Initialize(int ilev) override
std::string input_material
Set::Scalar driving_force_tolerance_abs
int number_of_ghost_nodes
Number of ghost nodes.
Set::Field< Set::Scalar > stress
stress field
struct Integrator::SutureCrack::@30 loading
Set::Field< Set::Scalar > strain
total strain field (gradient of displacement)
Set::Field< Set::Scalar > disp
displacement field
void Advance(int lev, Set::Scalar, Set::Scalar dt) override
Set::Field< Set::Scalar > energy_pristine_old
energy of the pristine material for previous time step.
std::string ic_type
crack IC type. See IC/Notch and IC/Ellipsoid
Set::Scalar df_mult
mulitplier for elastic driving force.
void define(const Vector< Geometry > &a_geom, const Vector< BoxArray > &a_grids, const Vector< DistributionMapping > &a_dmap, const LPInfo &a_info=LPInfo(), const Vector< FabFactory< FArrayBox > const * > &a_factory={})
void SetBC(::BC::Operator::Elastic::Elastic *a_bc)
The different types of Boundary Condtiions are listed in the BC::Operator::Elastic documentation.
void Stress(int amrlev, amrex::MultiFab &sigmafab, const amrex::MultiFab &ufab, bool voigt=false, bool a_homogeneous=false)
Compute stress given the displacement field by.
void Strain(int amrlev, amrex::MultiFab &epsfab, const amrex::MultiFab &ufab, bool voigt=false) const
Compute strain given the displacement field by.
void Energy(int amrlev, amrex::MultiFab &energy, const amrex::MultiFab &u, bool a_homogeneous=false)
Compute energy density given the displacement field by.
void setPostSmooth(const int a_post_smooth)
void setBottomMaxIter(const int a_bottom_max_iter)
void setVerbose(const int a_verbose)
void setMaxFmgIter(const int a_max_fmg_iter)
void setFixedIter(const int a_fixed_iter)
void setPreSmooth(const int a_pre_smooth)
void setMaxIter(const int a_max_iter)
void compResidual(Set::Field< Set::Scalar > &a_res_mf, Set::Field< Set::Scalar > &a_u_mf, Set::Field< Set::Scalar > &a_b_mf, Set::Field< T > &a_model_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.
Model::Solid::Linear::IsotropicDegradable suture_fracture_model_type
AMREX_FORCE_INLINE Set::Matrix FieldToMatrix(const amrex::Array4< const Set::Scalar > &f, const int &i, const int &j, const int &k)
AMREX_FORCE_INLINE Set::Matrix Hessian(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 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)
Eigen::Matrix< amrex::Real, AMREX_SPACEDIM, 1 > Vector
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)
void Message(std::string file, std::string func, int line, Args const &... args)