243 if ((
crack.driving_force_norm /
crack.driving_force_reference <
crack.tol_rel) ||
crack.crack_prop_iter >
crack.max_iter)
245 crack.crack_prop_iter = 0;
251 crack.crack_prop_iter = 0;
257 crack.crack_prop_iter = 0;
267 crack.crack_prop_iter++;
277 amrex::Box domain = geom[lev].Domain();
278 domain.convert(amrex::IntVect::TheNodeVector());
281 for (MFIter mfi(*
disp_mf[lev],
false); mfi.isValid(); ++mfi)
283 amrex::Box bx = mfi.grownnodaltilebox();
284 amrex::Array4<Set::Scalar>
const &eta =
material.eta_mf[lev]->array(mfi);
285 amrex::Array4<Set::Scalar>
const &c =
crack.c_mf[lev]->array(mfi);
286 amrex::Array4<Set::Matrix>
const &stress =
stress_mf[lev]->array(mfi);
287 amrex::Array4<Set::Matrix>
const &strain =
strain_mf[lev]->array(mfi);
288 amrex::Array4<Set::Scalar>
const &energy =
crack.energy_pristine_mf[lev]->array(mfi);
289 amrex::Array4<Set::Scalar>
const &history_var =
crack.history_var_mf[lev]->array(mfi);
291 amrex::ParallelFor(bx, [=] AMREX_GPU_DEVICE(
int i,
int j,
int k) {
328 energy(i, j, k, 0) = 0.0;
329 energy(i, j, k, 1) = 0.0;
330 energy(i, j, k, 2) = 0.0;
332 if (!
crack.cracktype[0].mixed_mode())
335 Eigen::SelfAdjointEigenSolver<Set::Matrix> eigensolver(eps);
343 for (
int n = 0; n < AMREX_SPACEDIM; n++)
345 if (eValues(n) > 0.0)
346 eps_p += eValues(n) * (eVectors.col(n) * eVectors.col(n).transpose());
348 eps_n += eValues(n) * (eVectors.col(n) * eVectors.col(n).transpose());
351 for (
int n = 0; n <
material.num_mat; n++)
352 energy(i, j, k, 0) += eta(i, j, k, n) *
material.models[n].W(eps_p);
354 if (energy(i, j, k, 0) > history_var(i, j, k, 0))
355 history_var(i, j, k, 0) = energy(i, j, k, 0);
361 if (crack_grad.lpNorm<2>() > 1.e-4)
365 Eigen::SelfAdjointEigenSolver<Set::Matrix> eigensolver(sig);
371 Set::Vector vec1 = Set::Vector::Zero(), vec2 = Set::Vector::Zero();
372 if (eValues(0) > eValues(1))
376 vec1 = eVectors.col(0);
377 vec2 = eVectors.col(1);
383 vec1 = eVectors.col(1);
384 vec2 = eVectors.col(0);
391 Set::Scalar mohr_radius = 0.5 * std::abs(sig1 - sig2);
408 beta = sig1 < 0 ? beta_bar : 1.0;
409 f_theta = (
beta * (
crack.el_mult *
crack.el_mult * sig1 * sig1 / (sig_t * sig_t))) - 1;
413 Set::Scalar theta_candidate1 = 0.0, f_candidate1 = 0.;
414 Set::Scalar temp = std::abs((mohr_center / mohr_radius) * (chi * chi / (1.0 - (chi * chi))));
415 if (temp >= 0.0 && temp <= 1.0)
417 theta_candidate1 = 0.5 * std::acos(temp);
420 sig_nn1 = mohr_center + (mohr_radius * std::cos(2.0 * theta_candidate1));
421 tau_nm1 = mohr_radius * std::sin(2.0 * theta_candidate1);
425 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;
428 if (f_candidate1 > f_theta)
430 f_theta = f_candidate1;
438 Set::Scalar theta_candidate2 = 0.0, f_candidate2 = 0.;
439 temp = std::abs((mohr_center / mohr_radius) * (beta_bar * chi * chi / (1.0 - (beta_bar * chi * chi))));
440 if (temp >= 0.0 && temp <= 1.0)
442 theta_candidate2 = 0.5 * std::acos(temp);
445 sig_nn2 = mohr_center + (mohr_radius * std::cos(2.0 * theta_candidate2));
446 tau_nm2 = mohr_radius * std::sin(2.0 * theta_candidate2);
450 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;
453 if (f_candidate2 > f_theta)
455 f_theta = f_candidate2;
468 Set::Scalar theta = std::atan(1) - std::atan(friction);
470 sig_nn =
crack.el_mult * (mohr_center + (mohr_radius * std::cos(2.0 * theta)));
471 tau_nm =
crack.el_mult * (mohr_radius * std::sin(2.0 * theta));
473 f_theta = (tau_nm + (friction * sig_nn)) * (tau_nm + (friction * sig_nn)) / (cohesion * cohesion);
474 f_theta = f_theta - 1.0;
479 energy(i,j,k,0) = (f_theta > 0) ? (c_alpha / (2.0 * irwing_length)) * ((f_theta)) : 0.0;
480 energy(i,j,k,1) = 0.0;
482 if (energy(i, j, k, 0) + energy(i, j, k, 1) > history_var(i, j, k, 0) + history_var(i, j, k, 1))
484 history_var(i, j, k, 0) = energy(i, j, k, 0);
485 history_var(i, j, k, 1) = energy(i, j, k, 1);
501 Advance(
int a_lev, amrex::Real a_time, amrex::Real a_dt)
override
505 crack.c_mf[a_lev]->FillBoundary();
507 std::swap(
crack.c_old_mf[a_lev],
crack.c_mf[a_lev]);
510 amrex::Box domain(geom[a_lev].Domain());
511 domain.convert(amrex::IntVect::TheNodeVector());
512 const amrex::Dim3 lo = amrex::lbound(domain), hi = amrex::ubound(domain);
518 for (amrex::MFIter mfi(*
crack.c_mf[a_lev],
true); mfi.isValid(); ++mfi)
520 amrex::Box bx = mfi.tilebox();
524 amrex::Array4<const Set::Scalar>
const &c_old =
crack.c_old_mf[a_lev]->array(mfi);
525 amrex::Array4<const Set::Scalar>
const &energy =
crack.history_var_mf[a_lev]->array(mfi);
526 amrex::Array4<const Set::Scalar>
const &eta =
material.eta_mf[a_lev]->array(mfi);
528 amrex::Array4<Set::Scalar>
const &c =
crack.c_mf[a_lev]->array(mfi);
529 amrex::Array4<Set::Scalar>
const &df =
crack.driving_force_mf[a_lev]->array(mfi);
531 amrex::ParallelFor(bx, [=] AMREX_GPU_DEVICE(
int i,
int j,
int k) {
532#if AMREX_SPACEDIM != 2
536 if (i == lo.x && j == lo.y)
537 c(i, j, k, 0) = c(i + 1, j + 1, k, 0);
538 else if (i == lo.x && j == hi.y)
539 c(i, j, k, 0) = c(i + 1, j - 1, k, 0);
540 else if (i == hi.x && j == lo.y)
541 c(i, j, k, 0) = c(i - 1, j + 1, k, 0);
542 else if (i == hi.x && j == hi.y)
543 c(i, j, k, 0) = c(i - 1, j - 1, k, 0);
545 c(i, j, k) = c(i + 1, j, k, 0);
547 c(i, j, k) = c(i, j + 1, k, 0);
549 c(i, j, k) = c(i - 1, j, k, 0);
551 c(i, j, k) = c(i, j - 1, k, 0);
558 if (
crack.beta > 0.0)
560 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);
566 if (std::isnan(laplacian))
573 Set::Scalar _temp_product = 1.0, _temp_product2 = 1.0;
575 for (
int m = 0; m <
material.num_mat; m++)
577 Gc += eta(i, j, k, m) *
crack.cracktype[m].Gc(c_old(i, j, k, 0));
578 Zeta += eta(i, j, k, m) *
crack.cracktype[m].Zeta(c_old(i, j, k, 0));
579 Threshold += eta(i, j, k, m) *
crack.cracktype[m].DrivingForceThreshold(c_old(i, j, k, 0));
580 Mobility += eta(i, j, k, m) *
crack.cracktype[m].Mobility(c_old(i, j, k, 0));
581 _temp_product *= eta(i, j, k, m);
582 _temp_product2 *= 0.5;
585 Gc *= (1.0 - _temp_product * (1. -
crack.mult_Gc) / _temp_product2);
589 if (!
crack.cracktype[0].mixed_mode())
591 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;
595 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));
597 rhs += df(i, j, k, 0);
599 df(i, j, k, 1) =
crack.cracktype[0].Dw_phi(c_old(i, j, k, 0), 0.0) / (Zeta);
600 rhs += df(i, j, k, 1);
602 df(i, j, k, 2) = 2.0 * Zeta * laplacian *
crack.mult_lap;
603 if (std::isnan(df(i, j, k, 2)))
605 rhs -= df(i, j, k, 2);
607 df(i, j, k, 3) =
crack.beta * (0.5 * Zeta * Zeta * Zeta) * bilap;
608 if (std::isnan(df(i, j, k, 3)))
610 rhs += df(i, j, k, 3);
612 df(i, j, k, 4) = std::max(0., rhs - Threshold);
613 c(i, j, k, 0) = c_old(i, j, k, 0) - a_dt * df(i, j, k, 4) * Mobility;
615 if (c(i, j, k, 0) < 0.0)
617 if (c(i, j, k, 0) > 1.0)
622 crack.c_mf[a_lev]->FillBoundary();
623 crack.driving_force_mf[a_lev]->FillBoundary();
636 for (amrex::MFIter mfi(*
crack.c_mf[lev], TilingIfNotGPU()); mfi.isValid(); ++mfi)
638 amrex::Box bx = mfi.tilebox();
639 bx.convert(amrex::IntVect::TheCellVector());
640 amrex::Array4<char>
const &tags = a_tags.array(mfi);
641 amrex::Array4<Set::Scalar>
const &c =
crack.c_mf[lev]->array(mfi);
642 amrex::ParallelFor(bx, [=] AMREX_GPU_DEVICE(
int i,
int j,
int k) {
644 if (grad.lpNorm<2>() * DXnorm >
crack.refinement_threshold)
645 tags(i, j, k) = amrex::TagBox::SET;
649 for (amrex::MFIter mfi(*
crack.driving_force_mf[lev], TilingIfNotGPU()); mfi.isValid(); ++mfi)
651 amrex::Box bx = mfi.tilebox();
652 bx.convert(amrex::IntVect::TheCellVector());
653 amrex::Array4<char>
const &tags = a_tags.array(mfi);
654 amrex::Array4<Set::Scalar>
const &df =
crack.driving_force_mf[lev]->array(mfi);
655 amrex::ParallelFor(bx, [=] AMREX_GPU_DEVICE(
int i,
int j,
int k) {
657 if (grad.lpNorm<2>() * DXnorm >
crack.driving_force_refinement_threshold)
658 tags(i, j, k) = amrex::TagBox::SET;
662 for (amrex::MFIter mfi(*
psi_mf[lev], TilingIfNotGPU()); mfi.isValid(); ++mfi)
664 amrex::Box bx = mfi.tilebox();
665 bx.convert(amrex::IntVect::TheCellVector());
666 amrex::Array4<char>
const &tags = a_tags.array(mfi);
667 amrex::Array4<Set::Scalar>
const &psi =
psi_mf[lev]->array(mfi);
668 amrex::ParallelFor(bx, [=] AMREX_GPU_DEVICE(
int i,
int j,
int k) {
670 if (grad.lpNorm<2>() * DXnorm >
crack.refinement_threshold)
671 tags(i, j, k) = amrex::TagBox::SET;
677 for (amrex::MFIter mfi(*
material.eta_mf[lev], TilingIfNotGPU()); mfi.isValid(); ++mfi)
679 amrex::Box bx = mfi.tilebox();
680 bx.convert(amrex::IntVect::TheCellVector());
681 amrex::Array4<char>
const &tags = a_tags.array(mfi);
682 amrex::Array4<Set::Scalar>
const &eta =
material.eta_mf[lev]->array(mfi);
683 amrex::ParallelFor(bx, [=] AMREX_GPU_DEVICE(
int i,
int j,
int k) {
685 if (grad.lpNorm<2>() * DXnorm >
material.m_eta_ref_threshold)
686 tags(i, j, k) = amrex::TagBox::SET;