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;