// // Test the LCM mini minimizer. // TEST(AlbanyResidual, NewtonBanana) { bool const print_output = ::testing::GTEST_FLAG(print_time); // outputs nothing Teuchos::oblackholestream bhs; std::ostream& os = (print_output == true) ? std::cout : bhs; using EvalT = PHAL::AlbanyTraits::Residual; using ScalarT = typename EvalT::ScalarT; using ValueT = typename Sacado::ValueType<ScalarT>::type; constexpr minitensor::Index DIM{2}; using MIN = minitensor::Minimizer<ValueT, DIM>; using FN = LCM::Banana<ValueT>; using STEP = minitensor::StepBase<FN, ValueT, DIM>; MIN minimizer; std::unique_ptr<STEP> pstep = minitensor::stepFactory<FN, ValueT, DIM>(minitensor::StepType::NEWTON); assert(pstep->name() != nullptr); STEP& step = *pstep; FN banana; minitensor::Vector<ScalarT, DIM> x; x(0) = 0.0; x(1) = 3.0; LCM::MiniSolver<MIN, STEP, FN, EvalT, DIM> mini_solver( minimizer, step, banana, x); minimizer.printReport(os); ASSERT_EQ(minimizer.converged, true); }
// // Test the LCM mini minimizer. // TEST(AlbanyJacobian, NewtonBanana) { bool const print_output = ::testing::GTEST_FLAG(print_time); // outputs nothing Teuchos::oblackholestream bhs; std::ostream& os = (print_output == true) ? std::cout : bhs; using EvalT = PHAL::AlbanyTraits::Jacobian; using ScalarT = typename EvalT::ScalarT; using ValueT = typename Sacado::ValueType<ScalarT>::type; constexpr minitensor::Index DIM{2}; using MIN = minitensor::Minimizer<ValueT, DIM>; using FN = LCM::Banana<ValueT>; using STEP = minitensor::NewtonStep<FN, ValueT, DIM>; MIN minimizer; STEP step; FN banana; minitensor::Vector<ScalarT, DIM> x; x(0) = 0.0; x(1) = 3.0; LCM::MiniSolver<MIN, STEP, FN, EvalT, DIM> mini_solver( minimizer, step, banana, x); minimizer.printReport(os); ASSERT_EQ(minimizer.converged, true); }
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 FerroicModel<EvalT>:: computeState( const Intrepid2::Tensor<ScalarT, FM::THREE_D>& x, const Intrepid2::Vector<ScalarT, FM::THREE_D>& E, const Teuchos::Array<RealType>& oldfractions, Intrepid2::Tensor<ScalarT, FM::THREE_D>& X, Intrepid2::Vector<ScalarT, FM::THREE_D>& D, Teuchos::Array<ScalarT>& newfractions) /******************************************************************************/ { // create non-linear system // using NLS = FM::DomainSwitching<EvalT>; NLS domainSwitching(crystalVariants, transitions, tBarriers, oldfractions, aMatrix, x, E, /* dt= */ 1.0); // solution variable // Intrepid2::Vector<ScalarT,FM::MAX_TRNS> xi; // solve for xi // switch (m_integrationType){ default: break; case FM::IntegrationType::EXPLICIT: { switch (m_explicitMethod){ default: break; case FM::ExplicitMethod::SCALED_DESCENT: { FM::ScaledDescent(domainSwitching, xi); } case FM::ExplicitMethod::DESCENT_NORM: { FM::DescentNorm(domainSwitching, xi); } } } case FM::IntegrationType::IMPLICIT: { // create minimizer using ValueT = typename Sacado::ValueType<ScalarT>::type; using MIN = Intrepid2::Minimizer<ValueT, MAX_TRNS>; MIN minimizer; // create stepper using STEP = Intrepid2::StepBase<NLS, ValueT, MAX_TRNS>; std::unique_ptr<STEP> pstep = Intrepid2::stepFactory<NLS, ValueT, MAX_TRNS>(m_step_type); STEP &step = *pstep; // create solution vector with initial guess int ntrans = domainSwitching.getNumStates(); xi.set_dimension(ntrans); for(int itrans=0; itrans<ntrans; itrans++) xi(itrans) = Sacado::ScalarValue<ScalarT>::eval(0.0); // solve LCM::MiniSolver<MIN, STEP, NLS, EvalT, MAX_TRNS> mini_solver(minimizer, step, domainSwitching, xi); } } // update based on new xi values // }