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>
51 pp_crack.query(
"modulus_scaling_max",
crack.scaleModulusMax);
52 pp_crack.query(
"refinement_threshold",
crack.refinement_threshold);
58 pp_crack_df.query(
"mult_Gc",
crack.mult_df_Gc);
59 pp_crack_df.query(
"mult_Lap",
crack.mult_df_lap);
60 pp_crack_df.query(
"beta",
crack.beta);
61 pp_crack_df.query(
"tol_rel",
crack.driving_force_tolerance_rel);
62 pp_crack_df.query(
"tol_abs",
crack.driving_force_tolerance_abs);
68 if (
crack.ic_type.size() == 0)
crack.is_ic =
false;
72 for (
int i = 0; i <
crack.ic_type.size(); i++)
74 if(
crack.ic_type[i] ==
"notch")
81 else if (
crack.ic_type[i] ==
"ellipsoid")
102 pp_material.query(
"refinement_threshold",
material.refinement_threshold);
105 pp_material_ic.query(
"type",
material.ic_type);
118 else if (
material.ic_type ==
"ellipse")
127 else if (
material.ic_type ==
"perturbed_interface")
130 pp_material_ic.
queryclass(
"perturbed_interface", *tmpic);
141 std::string pp_string =
"material.model"+std::to_string(p+1);
147 std::string model_type_str;
148 pp_model.query(
"type", model_type_str);
149 if(model_type_str ==
"isotropic")
153 material.brittlemodeltype.push_back(*tmpmodel);
158 if (p == 0)
Util::Abort(
INFO,
"Need material information for at least one material");
164 if (pp_load.countval(
"body_force")) pp_load.
queryarr(
"body_force",
loading.body_force);
165 pp_load.query(
"val",
loading.val);
168 pp_elastic.query(
"df_mult",
elastic.df_mult);
170 pp_elastic.query(
"int",
elastic.interval);
171 pp_elastic.query(
"omega",
elastic.omega);
191 elastic.disp_mf[ilev]->setVal(0.0);
192 elastic.strain_mf[ilev]->setVal(0.0);
193 elastic.stress_mf[ilev]->setVal(0.0);
194 elastic.rhs_mf[ilev]->setVal(0.0);
195 elastic.energy_mf[ilev]->setVal(0.0);
196 elastic.residual_mf[ilev]->setVal(0.0);
197 elastic.energy_pristine_mf[ilev] -> setVal(0.);
198 elastic.energy_pristine_old_mf[ilev] -> setVal(0.);
202 crack.c_mf[ilev]->setVal(1.0);
203 crack.c_old_mf[ilev]->setVal(1.0);
205 for (
int i = 0; i <
crack.ic.size(); i++)
213 crack.c_mf[ilev]->setVal(1.0);
214 crack.c_old_mf[ilev]->setVal(1.0);
218 else material.material_mf[ilev]->setVal(1.0);
224 if (
crack.driving_force_norm /
crack.driving_force_reference <
crack.driving_force_tolerance_rel)
226 if (
crack.driving_force_norm <
crack.driving_force_tolerance_abs)
229 if (!
elastic.do_solve_now)
return;
237 for (
int ilev = 0; ilev <
nlevels; ++ilev)
241 std::swap(
elastic.energy_pristine_old_mf[ilev],
elastic.energy_pristine_mf[ilev]);
243 for (MFIter mfi(*
material.material_mf[ilev],
false); mfi.isValid(); ++mfi)
245 amrex::Box bx = mfi.grownnodaltilebox();
246 amrex::Array4<brittle_fracture_model_type_test>
const &model =
material.model_mf[ilev]->array(mfi);
247 amrex::Array4<const Set::Scalar>
const &mat =
material.material_mf[ilev]->array(mfi);
249 amrex::ParallelFor(bx, [=] AMREX_GPU_DEVICE(
int i,
int j,
int k) {
253 modelsum += mat(i,j,k,p)*
material.brittlemodeltype[p];
255 model(i,j,k) = modelsum ;
262 for (
int ilev = 0; ilev <
nlevels; ++ilev)
267 for (amrex::MFIter mfi(*
elastic.disp_mf[ilev],
true); mfi.isValid(); ++mfi)
269 amrex::Box
box = mfi.grownnodaltilebox();
270 amrex::Array4<const Set::Scalar>
const& c = (*
crack.c_mf[ilev]).array(mfi);
274 amrex::ParallelFor (
box,[=] AMREX_GPU_DEVICE(
int i,
int j,
int k){
277 _temp =
crack.cracktype.g_phi(c(i,j,k,0),0) +
crack.scaleModulusMax;
280 if(_temp < 0.0) _temp = 0.;
281 if(_temp > 1.0) _temp = 1.0;
296 for (
int ilev = 0; ilev <
nlevels; ++ilev)
298 const Real* DX = geom[ilev].CellSize();
299 Set::Scalar volume = AMREX_D_TERM(DX[0],*DX[1],*DX[2]);
301 AMREX_D_TERM(
elastic.rhs_mf[ilev]->setVal(
loading.body_force(0)*volume,0,1);,
315 op_b.
define(geom, grids, dmap, info);
336 for (
int ilev = 0; ilev <
nlevels; ilev++)
345 elastic.energy_pristine_mf[ilev]->setVal(0.0);
347 for (amrex::MFIter mfi(*
elastic.strain_mf[ilev],
true); mfi.isValid(); ++mfi)
349 const amrex::Box&
box = mfi.grownnodaltilebox();
350 amrex::Array4<const Set::Scalar>
const& strain = (*
elastic.strain_mf[ilev]).array(mfi);
351 amrex::Array4<const Set::Scalar>
const& mat = (*
material.material_mf[ilev]).array(mfi);
352 amrex::Array4<Set::Scalar>
const& energy = (*
elastic.energy_pristine_mf[ilev]).array(mfi);
353 amrex::Array4<Set::Scalar>
const& energy_old = (*
elastic.energy_pristine_old_mf[ilev]).array(mfi);
355 amrex::ParallelFor (
box,[=] AMREX_GPU_DEVICE(
int i,
int j,
int k){
358 Eigen::SelfAdjointEigenSolver<Set::Matrix> eigensolver(eps);
365 for (
int n = 0; n < AMREX_SPACEDIM; n++)
367 if(eValues(n) > 0.0) epsp += eValues(n)*(eVectors.col(n)*eVectors.col(n).transpose());
368 else epsn += eValues(n)*(eVectors.col(n)*eVectors.col(n).transpose());
376 energy(i,j,k) += mat(i,j,k,p)*
material.brittlemodeltype[p].W(epsp);
378 if (energy(i,j,k) < energy_old(i,j,k)) energy(i,j,k) = energy_old(i,j,k);
390 std::swap(
crack.c_old_mf[lev],
crack.c_mf[lev]);
398 amrex::Box domain(geom[lev].Domain());
399 domain.convert(amrex::IntVect::TheNodeVector());
400 const amrex::Dim3 lo= amrex::lbound(domain), hi = amrex::ubound(domain);
402 for ( amrex::MFIter mfi(*
crack.c_mf[lev],
true); mfi.isValid(); ++mfi )
404 const amrex::Box& bx = mfi.nodaltilebox();
405 amrex::Array4<const Set::Scalar>
const& c_old = (*
crack.c_old_mf[lev]).array(mfi);
406 amrex::Array4<Set::Scalar>
const& df = (*
crack.driving_force_mf[lev]).array(mfi);
407 amrex::Array4<Set::Scalar>
const& c = (*
crack.c_mf[lev]).array(mfi);
408 amrex::Array4<const Set::Scalar>
const& energy = (*
elastic.energy_pristine_mf[lev]).array(mfi);
409 amrex::Array4<const Set::Scalar>
const& mat = (*
material.material_mf[lev]).array(mfi);
411 amrex::ParallelFor (bx,[=] AMREX_GPU_DEVICE(
int i,
int j,
int k){
413 #if AMREX_SPACEDIM !=2
416 if (i == lo.x && j == lo.y) c(i,j,k,0) = c(i+1,j+1,k,0);
417 else if (i == lo.x && j == hi.y) c(i,j,k,0) = c(i+1,j-1,k,0);
418 else if (i == hi.x && j == lo.y) c(i,j,k,0) = c(i-1,j+1,k,0);
419 else if (i == hi.x && j == hi.y) c(i,j,k,0) = c(i-1,j-1,k,0);
420 else if (i == lo.x) c(i,j,k,0) = c(i+1,j,k,0);
421 else if (j == lo.y) c(i,j,k,0) = c(i,j+1,k,0);
422 else if (i == hi.x) c(i,j,k,0) = c(i-1,j,k,0);
423 else if (j == hi.y) c(i,j,k,0) = c(i,j-1,k,0);
440 df(i,j,k,0) =
crack.cracktype.Dg_phi(c_old(i,j,k,0),0.0)*en_cell*
elastic.df_mult;
441 rhs +=
crack.cracktype.Dg_phi(c_old(i,j,k,0),0.0)*en_cell*
elastic.df_mult;
452 _temp_product *= mat(i,j,k,m);
458 df(i,j,k,1) = Gc*
crack.cracktype.Dw_phi(c_old(i,j,k,0),0.0)/(4.0*Zeta);
459 rhs += Gc*
crack.cracktype.Dw_phi(c_old(i,j,k,0),0.)/(4.0*Zeta);
461 df(i,j,k,2) = 2.0*Zeta*Gc*laplacian*
crack.mult_df_lap;
462 rhs -= 2.0*Zeta*Gc*laplacian*
crack.mult_df_lap;
464 df(i,j,k,3) =
crack.beta*bilap;
465 rhs +=
crack.beta * bilap;
471 df(i,j,k,4) = std::max(0.,rhs -
crack.cracktype.DrivingForceThreshold(c_old(i,j,k,0)));
472 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));
474 if (c (i,j,k,0) < 0.0) c(i,j,k,0) = 0.0;
475 if (c (i,j,k,0) > 1.0) c(i,j,k,0) = 1.0;
484 const amrex::Real *DX = geom[lev].CellSize();
487 amrex::Box domain(geom[lev].Domain());
488 domain.convert(amrex::IntVect::TheNodeVector());
490 for (amrex::MFIter mfi(*
crack.c_mf[lev], TilingIfNotGPU()); mfi.isValid(); ++mfi)
492 const amrex::Box bx = mfi.tilebox() & domain.grow(-1);
493 amrex::Array4<char>
const &tags = a_tags.array(mfi);
494 amrex::Array4<const Set::Scalar>
const &c = (*
crack.c_mf[lev]).array(mfi);
495 amrex::Array4<const Set::Scalar>
const &mat = (*
material.material_mf[lev]).array(mfi);
497 amrex::ParallelFor(bx, [=] AMREX_GPU_DEVICE(
int i,
int j,
int k) {
500 if (dxnorm * grad.lpNorm<2>() >=
crack.refinement_threshold || dxnorm * grad2.lpNorm<2>() >=
material.refinement_threshold)
501 tags(i, j, k) = amrex::TagBox::SET;
508 const amrex::Real* DX = geom[amrlev].CellSize();
509 const Set::Scalar DV = AMREX_D_TERM(DX[0],*DX[1],*DX[2]);
511 amrex::Array4<const Set::Scalar>
const &df = (*
crack.driving_force_mf[amrlev]).array(mfi);
512 amrex::Array4<const Set::Scalar>
const &c_new = (*
crack.c_mf[amrlev]).array(mfi);
513 amrex::Array4<const Set::Scalar>
const &energy = (*
elastic.energy_mf[amrlev]).array(mfi);
515 amrex::ParallelFor(
box, [=] AMREX_GPU_DEVICE(
int i,
int j,
int k)
517 crack.driving_force_norm += df(i,j,k,4) * DV;
518 crack.int_crack += c_new(i,j,k) * DV;
519 elastic.int_energy += energy(i,j,k) * DV;
526 crack.driving_force_reference =
crack.driving_force_norm;
571 amrex::Vector<IC::IC*>
ic;