1#ifndef INTEGRATOR_FRACTURE_H
2#define INTEGRATOR_FRACTURE_H
9#include "AMReX_ParallelDescriptor.H"
10#include "AMReX_ParmParse.H"
21#include "Operator/Operator.H"
36#include "Numeric/Stencil.H"
37#include <eigen3/Eigen/Dense>
48 static constexpr const char*
name =
"fracture";
53 pp_crack.query(
"modulus_scaling_max",
crack.scaleModulusMax);
54 pp_crack.query(
"refinement_threshold",
crack.refinement_threshold);
60 pp_crack_df.query(
"mult_Gc",
crack.mult_df_Gc);
61 pp_crack_df.query(
"mult_Lap",
crack.mult_df_lap);
62 pp_crack_df.query(
"beta",
crack.beta);
63 pp_crack_df.query(
"tol_rel",
crack.driving_force_tolerance_rel);
64 pp_crack_df.query(
"tol_abs",
crack.driving_force_tolerance_abs);
70 if (
crack.ic_type.size() == 0)
crack.is_ic =
false;
74 for (
int i = 0; i <
crack.ic_type.size(); i++)
76 if(
crack.ic_type[i] ==
"notch")
83 else if (
crack.ic_type[i] ==
"ellipsoid")
104 pp_material.query(
"refinement_threshold",
material.refinement_threshold);
107 pp_material_ic.query(
"type",
material.ic_type);
120 else if (
material.ic_type ==
"ellipse")
129 else if (
material.ic_type ==
"perturbed_interface")
132 pp_material_ic.
queryclass(
"perturbed_interface", *tmpic);
143 std::string pp_string =
"material.model"+std::to_string(p+1);
149 std::string model_type_str;
150 pp_model.query(
"type", model_type_str);
151 if(model_type_str ==
"isotropic")
155 material.brittlemodeltype.push_back(*tmpmodel);
160 if (p == 0)
Util::Abort(
INFO,
"Need material information for at least one material");
166 if (pp_load.countval(
"body_force")) pp_load.
queryarr(
"body_force",
loading.body_force);
167 pp_load.query(
"val",
loading.val);
170 pp_elastic.query(
"df_mult",
elastic.df_mult);
172 pp_elastic.query(
"int",
elastic.interval);
173 pp_elastic.query(
"omega",
elastic.omega);
193 elastic.disp_mf[ilev]->setVal(0.0);
194 elastic.strain_mf[ilev]->setVal(0.0);
195 elastic.stress_mf[ilev]->setVal(0.0);
196 elastic.rhs_mf[ilev]->setVal(0.0);
197 elastic.energy_mf[ilev]->setVal(0.0);
198 elastic.residual_mf[ilev]->setVal(0.0);
199 elastic.energy_pristine_mf[ilev] -> setVal(0.);
200 elastic.energy_pristine_old_mf[ilev] -> setVal(0.);
204 crack.c_mf[ilev]->setVal(1.0);
205 crack.c_old_mf[ilev]->setVal(1.0);
207 for (
int i = 0; i <
crack.ic.size(); i++)
215 crack.c_mf[ilev]->setVal(1.0);
216 crack.c_old_mf[ilev]->setVal(1.0);
220 else material.material_mf[ilev]->setVal(1.0);
226 if (
crack.driving_force_norm /
crack.driving_force_reference <
crack.driving_force_tolerance_rel)
228 if (
crack.driving_force_norm <
crack.driving_force_tolerance_abs)
231 if (!
elastic.do_solve_now)
return;
239 for (
int ilev = 0; ilev <
nlevels; ++ilev)
243 std::swap(
elastic.energy_pristine_old_mf[ilev],
elastic.energy_pristine_mf[ilev]);
245 for (MFIter mfi(*
material.material_mf[ilev],
false); mfi.isValid(); ++mfi)
247 amrex::Box bx = mfi.grownnodaltilebox();
248 amrex::Array4<brittle_fracture_model_type_test>
const &model =
material.model_mf[ilev]->array(mfi);
249 amrex::Array4<const Set::Scalar>
const &mat =
material.material_mf[ilev]->array(mfi);
251 amrex::ParallelFor(bx, [=] AMREX_GPU_DEVICE(
int i,
int j,
int k) {
255 modelsum += mat(i,j,k,p)*
material.brittlemodeltype[p];
257 model(i,j,k) = modelsum ;
264 for (
int ilev = 0; ilev <
nlevels; ++ilev)
269 for (amrex::MFIter mfi(*
elastic.disp_mf[ilev],
true); mfi.isValid(); ++mfi)
271 amrex::Box
box = mfi.grownnodaltilebox();
272 amrex::Array4<const Set::Scalar>
const& c = (*
crack.c_mf[ilev]).array(mfi);
276 amrex::ParallelFor (
box,[=] AMREX_GPU_DEVICE(
int i,
int j,
int k){
279 _temp =
crack.cracktype.g_phi(c(i,j,k,0),0) +
crack.scaleModulusMax;
282 if(_temp < 0.0) _temp = 0.;
283 if(_temp > 1.0) _temp = 1.0;
298 for (
int ilev = 0; ilev <
nlevels; ++ilev)
300 const Real* DX = geom[ilev].CellSize();
301 Set::Scalar volume = AMREX_D_TERM(DX[0],*DX[1],*DX[2]);
303 AMREX_D_TERM(
elastic.rhs_mf[ilev]->setVal(
loading.body_force(0)*volume,0,1);,
317 op_b.
define(geom, grids, dmap, info);
338 for (
int ilev = 0; ilev <
nlevels; ilev++)
347 elastic.energy_pristine_mf[ilev]->setVal(0.0);
349 for (amrex::MFIter mfi(*
elastic.strain_mf[ilev],
true); mfi.isValid(); ++mfi)
351 const amrex::Box&
box = mfi.grownnodaltilebox();
352 amrex::Array4<const Set::Scalar>
const& strain = (*
elastic.strain_mf[ilev]).array(mfi);
353 amrex::Array4<const Set::Scalar>
const& mat = (*
material.material_mf[ilev]).array(mfi);
354 amrex::Array4<Set::Scalar>
const& energy = (*
elastic.energy_pristine_mf[ilev]).array(mfi);
355 amrex::Array4<Set::Scalar>
const& energy_old = (*
elastic.energy_pristine_old_mf[ilev]).array(mfi);
357 amrex::ParallelFor (
box,[=] AMREX_GPU_DEVICE(
int i,
int j,
int k){
360 Eigen::SelfAdjointEigenSolver<Set::Matrix> eigensolver(eps);
367 for (
int n = 0; n < AMREX_SPACEDIM; n++)
369 if(eValues(n) > 0.0) epsp += eValues(n)*(eVectors.col(n)*eVectors.col(n).transpose());
370 else epsn += eValues(n)*(eVectors.col(n)*eVectors.col(n).transpose());
378 energy(i,j,k) += mat(i,j,k,p)*
material.brittlemodeltype[p].W(epsp);
380 if (energy(i,j,k) < energy_old(i,j,k)) energy(i,j,k) = energy_old(i,j,k);
392 std::swap(
crack.c_old_mf[lev],
crack.c_mf[lev]);
400 amrex::Box domain(geom[lev].Domain());
401 domain.convert(amrex::IntVect::TheNodeVector());
402 const amrex::Dim3 lo= amrex::lbound(domain), hi = amrex::ubound(domain);
404 for ( amrex::MFIter mfi(*
crack.c_mf[lev],
true); mfi.isValid(); ++mfi )
406 const amrex::Box& bx = mfi.nodaltilebox();
407 amrex::Array4<const Set::Scalar>
const& c_old = (*
crack.c_old_mf[lev]).array(mfi);
408 amrex::Array4<Set::Scalar>
const& df = (*
crack.driving_force_mf[lev]).array(mfi);
409 amrex::Array4<Set::Scalar>
const& c = (*
crack.c_mf[lev]).array(mfi);
410 amrex::Array4<const Set::Scalar>
const& energy = (*
elastic.energy_pristine_mf[lev]).array(mfi);
411 amrex::Array4<const Set::Scalar>
const& mat = (*
material.material_mf[lev]).array(mfi);
413 amrex::ParallelFor (bx,[=] AMREX_GPU_DEVICE(
int i,
int j,
int k){
415#if AMREX_SPACEDIM !=2
418 if (i == lo.x && j == lo.y) c(i,j,k,0) = c(i+1,j+1,k,0);
419 else if (i == lo.x && j == hi.y) c(i,j,k,0) = c(i+1,j-1,k,0);
420 else if (i == hi.x && j == lo.y) c(i,j,k,0) = c(i-1,j+1,k,0);
421 else if (i == hi.x && j == hi.y) c(i,j,k,0) = c(i-1,j-1,k,0);
422 else if (i == lo.x) c(i,j,k,0) = c(i+1,j,k,0);
423 else if (j == lo.y) c(i,j,k,0) = c(i,j+1,k,0);
424 else if (i == hi.x) c(i,j,k,0) = c(i-1,j,k,0);
425 else if (j == hi.y) c(i,j,k,0) = c(i,j-1,k,0);
442 df(i,j,k,0) =
crack.cracktype.Dg_phi(c_old(i,j,k,0),0.0)*en_cell*
elastic.df_mult;
443 rhs +=
crack.cracktype.Dg_phi(c_old(i,j,k,0),0.0)*en_cell*
elastic.df_mult;
454 _temp_product *= mat(i,j,k,m);
460 df(i,j,k,1) = Gc*
crack.cracktype.Dw_phi(c_old(i,j,k,0),0.0)/(4.0*Zeta);
461 rhs += Gc*
crack.cracktype.Dw_phi(c_old(i,j,k,0),0.)/(4.0*Zeta);
463 df(i,j,k,2) = 2.0*Zeta*Gc*laplacian*
crack.mult_df_lap;
464 rhs -= 2.0*Zeta*Gc*laplacian*
crack.mult_df_lap;
466 df(i,j,k,3) =
crack.beta*bilap;
467 rhs +=
crack.beta * bilap;
473 df(i,j,k,4) = std::max(0.,rhs -
crack.cracktype.DrivingForceThreshold(c_old(i,j,k,0)));
474 c(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));
476 if (c (i,j,k,0) < 0.0) c(i,j,k,0) = 0.0;
477 if (c (i,j,k,0) > 1.0) c(i,j,k,0) = 1.0;
486 const amrex::Real *DX = geom[lev].CellSize();
489 amrex::Box domain(geom[lev].Domain());
490 domain.convert(amrex::IntVect::TheNodeVector());
492 for (amrex::MFIter mfi(*
crack.c_mf[lev], TilingIfNotGPU()); mfi.isValid(); ++mfi)
494 const amrex::Box bx = mfi.tilebox() & domain.grow(-1);
495 amrex::Array4<char>
const &tags = a_tags.array(mfi);
496 amrex::Array4<const Set::Scalar>
const &c = (*
crack.c_mf[lev]).array(mfi);
497 amrex::Array4<const Set::Scalar>
const &mat = (*
material.material_mf[lev]).array(mfi);
499 amrex::ParallelFor(bx, [=] AMREX_GPU_DEVICE(
int i,
int j,
int k) {
502 if (dxnorm * grad.lpNorm<2>() >=
crack.refinement_threshold || dxnorm * grad2.lpNorm<2>() >=
material.refinement_threshold)
503 tags(i, j, k) = amrex::TagBox::SET;
510 const amrex::Real* DX = geom[amrlev].CellSize();
511 const Set::Scalar DV = AMREX_D_TERM(DX[0],*DX[1],*DX[2]);
513 amrex::Array4<const Set::Scalar>
const &df = (*
crack.driving_force_mf[amrlev]).array(mfi);
514 amrex::Array4<const Set::Scalar>
const &c_new = (*
crack.c_mf[amrlev]).array(mfi);
515 amrex::Array4<const Set::Scalar>
const &energy = (*
elastic.energy_mf[amrlev]).array(mfi);
517 amrex::ParallelFor(
box, [=] AMREX_GPU_DEVICE(
int i,
int j,
int k)
519 crack.driving_force_norm += df(i,j,k,4) * DV;
520 crack.int_crack += c_new(i,j,k) * DV;
521 elastic.int_energy += energy(i,j,k) * DV;
528 crack.driving_force_reference =
crack.driving_force_norm;
573 amrex::Vector<IC::IC<Set::Scalar>*>
ic;
#define pp_queryclass(...)
Pure abstract IC object from which all other IC objects inherit.
Initialize Laminates in a matrix.
bool contains(std::string name)
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)
struct Integrator::Fracture::@9 material
Set::Scalar scaleModulusMax
material modulus ratio inside crack (default = 0.02).
Set::Field< Set::Scalar > stress_mf
stress field
amrex::Vector< IC::IC< Set::Scalar > * > ic
crack IC. See IC/Notch and IC/Ellipsoid
struct Integrator::Fracture::@8 crack
amrex::Vector< std::string > ic_type
crack IC type. See IC/Notch and IC/Ellipsoid
IC::IC< Set::Scalar > * ic
struct Integrator::Fracture::@7 elastic
Set::Field< Set::Scalar > rhs_mf
rhs fab for elastic solution
Set::Scalar driving_force_tolerance_abs
Set::Scalar int_crack
integrated crack field over the entire domain.
void Initialize(int ilev) override
void Integrate(int amrlev, Set::Scalar, int, const amrex::MFIter &mfi, const amrex::Box &box) override
Set::Field< Set::Scalar > c_old_mf
crack field at previous time step
struct Integrator::Fracture::@10 loading
Set::Field< Set::Scalar > energy_pristine_old_mf
energy of the pristine material for previous time step.
void Advance(int lev, Set::Scalar, Set::Scalar dt) override
void TimeStepBegin(Set::Scalar, int) override
Set::Field< Set::Scalar > energy_pristine_mf
energy of the prisitne material as if no crack is present
Set::Field< Set::Scalar > disp_mf
displacement field
BC::Operator::Elastic::Constant brittlebc
elastic BC if using brittle fracture
void TagCellsForRefinement(int lev, amrex::TagBoxArray &a_tags, amrex::Real, int) override
int number_of_ghost_nodes
Number of ghost nodes.
Model::Interface::Crack::Constant cracktype
type of crack. See Crack/Constant or Crack/Sin
Set::Scalar mult_df_Gc
Multiplier for Gc/zeta term.
Set::Field< Set::Scalar > residual_mf
residual field for solver
static constexpr const char * name
std::string input_material
Set::Scalar driving_force_norminf
Set::Scalar mult_df_lap
Multiplier for the laplacian term.
Set::Scalar driving_force_tolerance_rel
Set::Field< Set::Scalar > energy_mf
total elastic energy
Set::Field< brittle_fracture_model_type_test > model_mf
void TimeStepComplete(amrex::Real, int) override
Set::Scalar df_mult
mulitplier for elastic driving force.
Set::Scalar refinement_threshold
amrex::Vector< brittle_fracture_model_type_test > brittlemodeltype
Set::Field< Set::Scalar > material_mf
Set::Scalar driving_force_reference
Set::Field< Set::Scalar > driving_force_mf
crack driving forces.
Set::Scalar int_energy
integrated energy over the entire domain.
Set::Field< Set::Scalar > strain_mf
total strain field (gradient of displacement)
Set::Field< Set::Scalar > c_mf
crack field at current time step
Set::Scalar driving_force_norm
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 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.
virtual void SetAverageDownCoeffs(bool a_average_down_coeffs) override
void Energy(int amrlev, amrex::MultiFab &energy, const amrex::MultiFab &u, bool a_homogeneous=false)
Compute energy density given the displacement field by.
void SetOmega(Set::Scalar a_omega)
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::Isotropic brittle_fracture_model_type_test
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::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)
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)