void ThermoMechanicalCoefficients<EvalT, Traits>:: evaluateFields(typename Traits::EvalData workset) { Intrepid2::Tensor<ScalarT> diffusivity(num_dims_); Intrepid2::Tensor<ScalarT> I(Intrepid2::eye<ScalarT>(num_dims_)); Intrepid2::Tensor<ScalarT> tensor; Intrepid2::Tensor<ScalarT> F(num_dims_); ScalarT dt = delta_time_(0); if (dt == 0.0) dt = 1.e-15; Albany::MDArray temperature_old = (*workset.stateArrayPtr)[temperature_name_]; for (int cell = 0; cell < workset.numCells; ++cell) { for (int pt = 0; pt < num_pts_; ++pt) { temperature_dot_(cell,pt) = (temperature_(cell,pt) - temperature_old(cell,pt)) / dt; } } if (have_mech_) { for (int cell = 0; cell < workset.numCells; ++cell) { for (int pt = 0; pt < num_pts_; ++pt) { F.fill(def_grad_,cell, pt,0,0); tensor = Intrepid2::inverse(Intrepid2::transpose(F) * F); thermal_transient_coeff_(cell, pt) = transient_coeff_; diffusivity = thermal_cond_(cell, pt) / (density_ * heat_capacity_) * tensor; for (int i = 0; i < num_dims_; ++i) { for (int j = 0; j < num_dims_; ++j) { thermal_diffusivity_(cell, pt, i, j) = diffusivity(i, j); } } } } } else { for (int cell = 0; cell < workset.numCells; ++cell) { for (int pt = 0; pt < num_pts_; ++pt) { thermal_transient_coeff_(cell, pt) = transient_coeff_; diffusivity = thermal_cond_(cell, pt) / (density_ * heat_capacity_) * I; for (int i = 0; i < num_dims_; ++i) { for (int j = 0; j < num_dims_; ++j) { thermal_diffusivity_(cell, pt, i, j) = diffusivity(i, j); } } } } } }
KOKKOS_INLINE_FUNCTION void J2MiniKernel<EvalT, Traits>::operator()(int cell, int pt) const { constexpr minitensor::Index MAX_DIM{3}; using Tensor = minitensor::Tensor<ScalarT, MAX_DIM>; Tensor F(num_dims_); Tensor const I(minitensor::eye<ScalarT, MAX_DIM>(num_dims_)); Tensor sigma(num_dims_); ScalarT const E = elastic_modulus_(cell, pt); ScalarT const nu = poissons_ratio_(cell, pt); ScalarT const kappa = E / (3.0 * (1.0 - 2.0 * nu)); ScalarT const mu = E / (2.0 * (1.0 + nu)); ScalarT const K = hardening_modulus_(cell, pt); ScalarT const Y = yield_strength_(cell, pt); ScalarT const J1 = J_(cell, pt); ScalarT const Jm23 = 1.0 / std::cbrt(J1 * J1); // fill local tensors F.fill(def_grad_, cell, pt, 0, 0); // Mechanical deformation gradient auto Fm = Tensor(F); if (have_temperature_) { // Compute the mechanical deformation gradient Fm based on the // multiplicative decomposition of the deformation gradient // // F = Fm.Ft => Fm = F.inv(Ft) // // where Ft is the thermal part of F, given as // // Ft = Le * I = exp(alpha * dtemp) * I // // Le = exp(alpha*dtemp) is the thermal stretch and alpha the // coefficient of thermal expansion. ScalarT dtemp = temperature_(cell, pt) - ref_temperature_; ScalarT thermal_stretch = std::exp(expansion_coeff_ * dtemp); Fm /= thermal_stretch; } Tensor Fpn(num_dims_); for (int i{0}; i < num_dims_; ++i) { for (int j{0}; j < num_dims_; ++j) { Fpn(i, j) = ScalarT(Fp_old_(cell, pt, i, j)); } } // compute trial state Tensor const Fpinv = minitensor::inverse(Fpn); Tensor const Cpinv = Fpinv * minitensor::transpose(Fpinv); Tensor const be = Jm23 * Fm * Cpinv * minitensor::transpose(Fm); Tensor s = mu * minitensor::dev(be); ScalarT const mubar = minitensor::trace(be) * mu / (num_dims_); // check yield condition ScalarT const smag = minitensor::norm(s); ScalarT const f = smag - SQ23 * (Y + K * eqps_old_(cell, pt) + sat_mod_ * (1.0 - std::exp(-sat_exp_ * eqps_old_(cell, pt)))); RealType constexpr yield_tolerance = 1.0e-12; if (f > yield_tolerance) { // Use minimization equivalent to return mapping using ValueT = typename Sacado::ValueType<ScalarT>::type; using NLS = J2NLS<EvalT>; constexpr minitensor::Index nls_dim{NLS::DIMENSION}; using MIN = minitensor::Minimizer<ValueT, nls_dim>; using STEP = minitensor::NewtonStep<NLS, ValueT, nls_dim>; MIN minimizer; STEP step; NLS j2nls(sat_mod_, sat_exp_, eqps_old_(cell, pt), K, smag, mubar, Y); minitensor::Vector<ScalarT, nls_dim> x; x(0) = 0.0; LCM::MiniSolver<MIN, STEP, NLS, EvalT, nls_dim> mini_solver( minimizer, step, j2nls, x); ScalarT const alpha = eqps_old_(cell, pt) + SQ23 * x(0); ScalarT const H = K * alpha + sat_mod_ * (1.0 - exp(-sat_exp_ * alpha)); ScalarT const dgam = x(0); // plastic direction Tensor const N = (1 / smag) * s; // update s s -= 2 * mubar * dgam * N; // update eqps eqps_(cell, pt) = alpha; // mechanical source if (have_temperature_ == true && delta_time_(0) > 0) { source_(cell, pt) = (SQ23 * dgam / delta_time_(0) * (Y + H + temperature_(cell, pt))) / (density_ * heat_capacity_); } // exponential map to get Fpnew Tensor const A = dgam * N; Tensor const expA = minitensor::exp(A); Tensor const Fpnew = expA * Fpn; for (int i{0}; i < num_dims_; ++i) { for (int j{0}; j < num_dims_; ++j) { Fp_(cell, pt, i, j) = Fpnew(i, j); } } } else { eqps_(cell, pt) = eqps_old_(cell, pt); if (have_temperature_ == true) source_(cell, pt) = 0.0; for (int i{0}; i < num_dims_; ++i) { for (int j{0}; j < num_dims_; ++j) { Fp_(cell, pt, i, j) = Fpn(i, j); } } } // update yield surface yield_surf_(cell, pt) = Y + K * eqps_(cell, pt) + sat_mod_ * (1. - std::exp(-sat_exp_ * eqps_(cell, pt))); // compute pressure ScalarT const p = 0.5 * kappa * (J_(cell, pt) - 1. / (J_(cell, pt))); // compute stress sigma = p * I + s / J_(cell, pt); for (int i(0); i < num_dims_; ++i) { for (int j(0); j < num_dims_; ++j) { stress_(cell, pt, i, j) = sigma(i, j); } } }
void ThermoMechanicalCoefficients<EvalT, Traits>::evaluateFields( typename Traits::EvalData workset) { if (SolutionType_ == "Continuation") { Albany::MDArray const temperature_old = (*workset.stateArrayPtr)[temperature_name_]; ScalarT dt = delta_time_(0); if (dt == 0.0) { // Initially, transfer the derivatives of temperature_ to the // derivatives of temperature_dot_ dt = 1.0; } for (int cell = 0; cell < workset.numCells; ++cell) { for (int pt = 0; pt < num_pts_; ++pt) { temperature_dot_(cell, pt) = (temperature_(cell, pt) - temperature_old(cell, pt)) / dt; } } } if (have_mech_) { for (int cell = 0; cell < workset.numCells; ++cell) { for (int pt = 0; pt < num_pts_; ++pt) { minitensor::Tensor<ScalarT> F(num_dims_); F.fill(def_grad_, cell, pt, 0, 0); minitensor::Tensor<ScalarT> tensor = minitensor::inverse(minitensor::transpose(F) * F); thermal_transient_coeff_(cell, pt) = transient_coeff_; minitensor::Tensor<ScalarT> diffusivity = thermal_cond_(cell, pt) / (density_ * heat_capacity_) * tensor; for (int i = 0; i < num_dims_; ++i) { for (int j = 0; j < num_dims_; ++j) { thermal_diffusivity_(cell, pt, i, j) = diffusivity(i, j); } } } } } else { for (int cell = 0; cell < workset.numCells; ++cell) { for (int pt = 0; pt < num_pts_; ++pt) { thermal_transient_coeff_(cell, pt) = transient_coeff_; minitensor::Tensor<RealType> I(minitensor::eye<RealType>(num_dims_)); minitensor::Tensor<ScalarT> diffusivity = thermal_cond_(cell, pt) / (density_ * heat_capacity_) * I; for (int i = 0; i < num_dims_; ++i) { for (int j = 0; j < num_dims_; ++j) { thermal_diffusivity_(cell, pt, i, j) = diffusivity(i, j); } } } } } }