238 if ((
crack.driving_force_norm /
crack.driving_force_reference <
crack.tol_rel) ||
crack.crack_prop_iter >
crack.max_iter)
240 crack.crack_prop_iter = 0;
246 crack.crack_prop_iter = 0;
252 crack.crack_prop_iter = 0;
262 crack.crack_prop_iter++;
272 amrex::Box domain = geom[lev].Domain();
273 domain.convert(amrex::IntVect::TheNodeVector());
276 for (MFIter mfi(*
disp_mf[lev],
false); mfi.isValid(); ++mfi)
278 amrex::Box bx = mfi.grownnodaltilebox();
279 amrex::Array4<Set::Scalar>
const &eta =
material.eta_mf[lev]->array(mfi);
280 amrex::Array4<Set::Scalar>
const &c =
crack.c_mf[lev]->array(mfi);
281 amrex::Array4<Set::Matrix>
const &stress =
stress_mf[lev]->array(mfi);
282 amrex::Array4<Set::Matrix>
const &strain =
strain_mf[lev]->array(mfi);
283 amrex::Array4<Set::Scalar>
const &energy =
crack.energy_pristine_mf[lev]->array(mfi);
284 amrex::Array4<Set::Scalar>
const &history_var =
crack.history_var_mf[lev]->array(mfi);
286 amrex::ParallelFor(bx, [=] AMREX_GPU_DEVICE(
int i,
int j,
int k) {
323 energy(i, j, k, 0) = 0.0;
324 energy(i, j, k, 1) = 0.0;
325 energy(i, j, k, 2) = 0.0;
327 if (!
crack.cracktype[0].mixed_mode())
330 Eigen::SelfAdjointEigenSolver<Set::Matrix> eigensolver(eps);
338 for (
int n = 0; n < AMREX_SPACEDIM; n++)
340 if (eValues(n) > 0.0)
341 eps_p += eValues(n) * (eVectors.col(n) * eVectors.col(n).transpose());
343 eps_n += eValues(n) * (eVectors.col(n) * eVectors.col(n).transpose());
346 for (
int n = 0; n <
material.num_mat; n++)
347 energy(i, j, k, 0) += eta(i, j, k, n) *
material.models[n].W(eps_p);
349 if (energy(i, j, k, 0) > history_var(i, j, k, 0))
350 history_var(i, j, k, 0) = energy(i, j, k, 0);
356 if (crack_grad.lpNorm<2>() > 1.e-4)
360 Eigen::SelfAdjointEigenSolver<Set::Matrix> eigensolver(sig);
366 Set::Vector vec1 = Set::Vector::Zero(), vec2 = Set::Vector::Zero();
367 if (eValues(0) > eValues(1))
371 vec1 = eVectors.col(0);
372 vec2 = eVectors.col(1);
378 vec1 = eVectors.col(1);
379 vec2 = eVectors.col(0);
386 Set::Scalar mohr_radius = 0.5 * std::abs(sig1 - sig2);
403 beta = sig1 < 0 ? beta_bar : 1.0;
404 f_theta = (
beta * (
crack.el_mult *
crack.el_mult * sig1 * sig1 / (sig_t * sig_t))) - 1;
408 Set::Scalar theta_candidate1 = 0.0, f_candidate1 = 0.;
409 Set::Scalar temp = std::abs((mohr_center / mohr_radius) * (chi * chi / (1.0 - (chi * chi))));
410 if (temp >= 0.0 && temp <= 1.0)
412 theta_candidate1 = 0.5 * std::acos(temp);
415 sig_nn1 = mohr_center + (mohr_radius * std::cos(2.0 * theta_candidate1));
416 tau_nm1 = mohr_radius * std::sin(2.0 * theta_candidate1);
420 f_candidate1 = (
crack.el_mult *
crack.el_mult * sig_nn1 * sig_nn1 / (sig_t * sig_t)) + (
crack.el_mult *
crack.el_mult * tau_nm1 * tau_nm1 / (tau_f * tau_f)) - 1.0;
423 if (f_candidate1 > f_theta)
425 f_theta = f_candidate1;
433 Set::Scalar theta_candidate2 = 0.0, f_candidate2 = 0.;
434 temp = std::abs((mohr_center / mohr_radius) * (beta_bar * chi * chi / (1.0 - (beta_bar * chi * chi))));
435 if (temp >= 0.0 && temp <= 1.0)
437 theta_candidate2 = 0.5 * std::acos(temp);
440 sig_nn2 = mohr_center + (mohr_radius * std::cos(2.0 * theta_candidate2));
441 tau_nm2 = mohr_radius * std::sin(2.0 * theta_candidate2);
445 f_candidate2 = (beta_bar *
crack.el_mult *
crack.el_mult * sig_nn2 * sig_nn2 / (sig_t * sig_t)) + (
crack.el_mult *
crack.el_mult * tau_nm2 * tau_nm2 / (tau_f * tau_f)) - 1.0;
448 if (f_candidate2 > f_theta)
450 f_theta = f_candidate2;
463 Set::Scalar theta = std::atan(1) - std::atan(friction);
465 sig_nn =
crack.el_mult * (mohr_center + (mohr_radius * std::cos(2.0 * theta)));
466 tau_nm =
crack.el_mult * (mohr_radius * std::sin(2.0 * theta));
468 f_theta = (tau_nm + (friction * sig_nn)) * (tau_nm + (friction * sig_nn)) / (cohesion * cohesion);
469 f_theta = f_theta - 1.0;
474 energy(i,j,k,0) = (f_theta > 0) ? (c_alpha / (2.0 * irwing_length)) * ((f_theta)) : 0.0;
475 energy(i,j,k,1) = 0.0;
477 if (energy(i, j, k, 0) + energy(i, j, k, 1) > history_var(i, j, k, 0) + history_var(i, j, k, 1))
479 history_var(i, j, k, 0) = energy(i, j, k, 0);
480 history_var(i, j, k, 1) = energy(i, j, k, 1);
496 Advance(
int a_lev, amrex::Real a_time, amrex::Real a_dt)
override
500 crack.c_mf[a_lev]->FillBoundary();
502 std::swap(
crack.c_old_mf[a_lev],
crack.c_mf[a_lev]);
505 amrex::Box domain(geom[a_lev].Domain());
506 domain.convert(amrex::IntVect::TheNodeVector());
507 const amrex::Dim3 lo = amrex::lbound(domain), hi = amrex::ubound(domain);
513 for (amrex::MFIter mfi(*
crack.c_mf[a_lev],
true); mfi.isValid(); ++mfi)
515 amrex::Box bx = mfi.tilebox();
519 amrex::Array4<const Set::Scalar>
const &c_old =
crack.c_old_mf[a_lev]->array(mfi);
520 amrex::Array4<const Set::Scalar>
const &energy =
crack.history_var_mf[a_lev]->array(mfi);
521 amrex::Array4<const Set::Scalar>
const &eta =
material.eta_mf[a_lev]->array(mfi);
523 amrex::Array4<Set::Scalar>
const &c =
crack.c_mf[a_lev]->array(mfi);
524 amrex::Array4<Set::Scalar>
const &df =
crack.driving_force_mf[a_lev]->array(mfi);
526 amrex::ParallelFor(bx, [=] AMREX_GPU_DEVICE(
int i,
int j,
int k) {
527#if AMREX_SPACEDIM != 2
531 if (i == lo.x && j == lo.y)
532 c(i, j, k, 0) = c(i + 1, j + 1, k, 0);
533 else if (i == lo.x && j == hi.y)
534 c(i, j, k, 0) = c(i + 1, j - 1, k, 0);
535 else if (i == hi.x && j == lo.y)
536 c(i, j, k, 0) = c(i - 1, j + 1, k, 0);
537 else if (i == hi.x && j == hi.y)
538 c(i, j, k, 0) = c(i - 1, j - 1, k, 0);
540 c(i, j, k) = c(i + 1, j, k, 0);
542 c(i, j, k) = c(i, j + 1, k, 0);
544 c(i, j, k) = c(i - 1, j, k, 0);
546 c(i, j, k) = c(i, j - 1, k, 0);
553 if (
crack.beta > 0.0)
555 bilap =
Numeric::Stencil<Set::Scalar, 4, 0, 0>::D(c_old, i, j, k, 0, DX) +
Numeric::Stencil<Set::Scalar, 2, 2, 0>::D(c_old, i, j, k, 0, DX) * 2.0 +
Numeric::Stencil<Set::Scalar, 0, 4, 0>::D(c_old, i, j, k, 0, DX);
561 if (std::isnan(laplacian))
568 Set::Scalar _temp_product = 1.0, _temp_product2 = 1.0;
570 for (
int m = 0; m <
material.num_mat; m++)
572 Gc += eta(i, j, k, m) *
crack.cracktype[m].Gc(c_old(i, j, k, 0));
573 Zeta += eta(i, j, k, m) *
crack.cracktype[m].Zeta(c_old(i, j, k, 0));
574 Threshold += eta(i, j, k, m) *
crack.cracktype[m].DrivingForceThreshold(c_old(i, j, k, 0));
575 Mobility += eta(i, j, k, m) *
crack.cracktype[m].Mobility(c_old(i, j, k, 0));
576 _temp_product *= eta(i, j, k, m);
577 _temp_product2 *= 0.5;
580 Gc *= (1.0 - _temp_product * (1. -
crack.mult_Gc) / _temp_product2);
584 if (!
crack.cracktype[0].mixed_mode())
586 df(i, j, k, 0) =
crack.cracktype[0].Dg_phi(c_old(i, j, k)) * (energy(i, j, k, 0) + energy(i, j, k, 1)) *
crack.el_mult / Gc;
590 df(i, j, k, 0) =
crack.cracktype[0].Dg_phi(c_old(i, j, k)) * (energy(i, j, k, 0) + energy(i, j, k, 1));
592 rhs += df(i, j, k, 0);
594 df(i, j, k, 1) =
crack.cracktype[0].Dw_phi(c_old(i, j, k, 0), 0.0) / (Zeta);
595 rhs += df(i, j, k, 1);
597 df(i, j, k, 2) = 2.0 * Zeta * laplacian *
crack.mult_lap;
598 if (std::isnan(df(i, j, k, 2)))
600 rhs -= df(i, j, k, 2);
602 df(i, j, k, 3) =
crack.beta * (0.5 * Zeta * Zeta * Zeta) * bilap;
603 if (std::isnan(df(i, j, k, 3)))
605 rhs += df(i, j, k, 3);
607 df(i, j, k, 4) = std::max(0., rhs - Threshold);
608 c(i, j, k, 0) = c_old(i, j, k, 0) - a_dt * df(i, j, k, 4) * Mobility;
610 if (c(i, j, k, 0) < 0.0)
612 if (c(i, j, k, 0) > 1.0)
617 crack.c_mf[a_lev]->FillBoundary();
618 crack.driving_force_mf[a_lev]->FillBoundary();
631 for (amrex::MFIter mfi(*
crack.c_mf[lev], TilingIfNotGPU()); mfi.isValid(); ++mfi)
633 amrex::Box bx = mfi.tilebox();
634 bx.convert(amrex::IntVect::TheCellVector());
635 amrex::Array4<char>
const &tags = a_tags.array(mfi);
636 amrex::Array4<Set::Scalar>
const &c =
crack.c_mf[lev]->array(mfi);
637 amrex::ParallelFor(bx, [=] AMREX_GPU_DEVICE(
int i,
int j,
int k) {
639 if (grad.lpNorm<2>() * DXnorm >
crack.refinement_threshold)
640 tags(i, j, k) = amrex::TagBox::SET;
644 for (amrex::MFIter mfi(*
crack.driving_force_mf[lev], TilingIfNotGPU()); mfi.isValid(); ++mfi)
646 amrex::Box bx = mfi.tilebox();
647 bx.convert(amrex::IntVect::TheCellVector());
648 amrex::Array4<char>
const &tags = a_tags.array(mfi);
649 amrex::Array4<Set::Scalar>
const &df =
crack.driving_force_mf[lev]->array(mfi);
650 amrex::ParallelFor(bx, [=] AMREX_GPU_DEVICE(
int i,
int j,
int k) {
652 if (grad.lpNorm<2>() * DXnorm >
crack.driving_force_refinement_threshold)
653 tags(i, j, k) = amrex::TagBox::SET;
657 for (amrex::MFIter mfi(*
psi_mf[lev], TilingIfNotGPU()); mfi.isValid(); ++mfi)
659 amrex::Box bx = mfi.tilebox();
660 bx.convert(amrex::IntVect::TheCellVector());
661 amrex::Array4<char>
const &tags = a_tags.array(mfi);
662 amrex::Array4<Set::Scalar>
const &psi =
psi_mf[lev]->array(mfi);
663 amrex::ParallelFor(bx, [=] AMREX_GPU_DEVICE(
int i,
int j,
int k) {
665 if (grad.lpNorm<2>() * DXnorm >
crack.refinement_threshold)
666 tags(i, j, k) = amrex::TagBox::SET;
672 for (amrex::MFIter mfi(*
material.eta_mf[lev], TilingIfNotGPU()); mfi.isValid(); ++mfi)
674 amrex::Box bx = mfi.tilebox();
675 bx.convert(amrex::IntVect::TheCellVector());
676 amrex::Array4<char>
const &tags = a_tags.array(mfi);
677 amrex::Array4<Set::Scalar>
const &eta =
material.eta_mf[lev]->array(mfi);
678 amrex::ParallelFor(bx, [=] AMREX_GPU_DEVICE(
int i,
int j,
int k) {
680 if (grad.lpNorm<2>() * DXnorm >
material.m_eta_ref_threshold)
681 tags(i, j, k) = amrex::TagBox::SET;