00001
00002
00003
00004
00005
00006
00007 #include <Intrepid_MiniTensor.h>
00008 #include "Teuchos_TestForException.hpp"
00009 #include "Phalanx_DataLayout.hpp"
00010
00011 #include "LocalNonlinearSolver.hpp"
00012
00013 namespace LCM
00014 {
00015
00016
00017 template<typename EvalT, typename Traits>
00018 J2Model<EvalT, Traits>::
00019 J2Model(Teuchos::ParameterList* p,
00020 const Teuchos::RCP<Albany::Layouts>& dl) :
00021 LCM::ConstitutiveModel<EvalT, Traits>(p, dl),
00022 sat_mod_(p->get<RealType>("Saturation Modulus", 0.0)),
00023 sat_exp_(p->get<RealType>("Saturation Exponent", 0.0))
00024 {
00025
00026 std::string cauchy_string = (*field_name_map_)["Cauchy_Stress"];
00027 std::string Fp_string = (*field_name_map_)["Fp"];
00028 std::string eqps_string = (*field_name_map_)["eqps"];
00029 std::string source_string = (*field_name_map_)["Mechanical_Source"];
00030 std::string F_string = (*field_name_map_)["F"];
00031 std::string J_string = (*field_name_map_)["J"];
00032
00033
00034 this->dep_field_map_.insert(std::make_pair(F_string, dl->qp_tensor));
00035 this->dep_field_map_.insert(std::make_pair(J_string, dl->qp_scalar));
00036 this->dep_field_map_.insert(std::make_pair("Poissons Ratio", dl->qp_scalar));
00037 this->dep_field_map_.insert(std::make_pair("Elastic Modulus", dl->qp_scalar));
00038 this->dep_field_map_.insert(std::make_pair("Yield Strength", dl->qp_scalar));
00039 this->dep_field_map_.insert(
00040 std::make_pair("Hardening Modulus", dl->qp_scalar));
00041 this->dep_field_map_.insert(std::make_pair("Delta Time", dl->workset_scalar));
00042
00043
00044 this->eval_field_map_.insert(std::make_pair(cauchy_string, dl->qp_tensor));
00045 this->eval_field_map_.insert(std::make_pair(Fp_string, dl->qp_tensor));
00046 this->eval_field_map_.insert(std::make_pair(eqps_string, dl->qp_scalar));
00047 if (have_temperature_) {
00048 this->eval_field_map_.insert(std::make_pair(source_string, dl->qp_scalar));
00049 }
00050
00051
00052
00053
00054 this->num_state_variables_++;
00055 this->state_var_names_.push_back(cauchy_string);
00056 this->state_var_layouts_.push_back(dl->qp_tensor);
00057 this->state_var_init_types_.push_back("scalar");
00058 this->state_var_init_values_.push_back(0.0);
00059 this->state_var_old_state_flags_.push_back(false);
00060 this->state_var_output_flags_.push_back(p->get<bool>("Output Cauchy Stress", false));
00061
00062
00063 this->num_state_variables_++;
00064 this->state_var_names_.push_back(Fp_string);
00065 this->state_var_layouts_.push_back(dl->qp_tensor);
00066 this->state_var_init_types_.push_back("identity");
00067 this->state_var_init_values_.push_back(0.0);
00068 this->state_var_old_state_flags_.push_back(true);
00069 this->state_var_output_flags_.push_back(p->get<bool>("Output Fp", false));
00070
00071
00072 this->num_state_variables_++;
00073 this->state_var_names_.push_back(eqps_string);
00074 this->state_var_layouts_.push_back(dl->qp_scalar);
00075 this->state_var_init_types_.push_back("scalar");
00076 this->state_var_init_values_.push_back(0.0);
00077 this->state_var_old_state_flags_.push_back(true);
00078 this->state_var_output_flags_.push_back(p->get<bool>("Output eqps", false));
00079
00080
00081 if (have_temperature_) {
00082 this->num_state_variables_++;
00083 this->state_var_names_.push_back(source_string);
00084 this->state_var_layouts_.push_back(dl->qp_scalar);
00085 this->state_var_init_types_.push_back("scalar");
00086 this->state_var_init_values_.push_back(0.0);
00087 this->state_var_old_state_flags_.push_back(false);
00088 this->state_var_output_flags_.push_back(p->get<bool>("Output Mechanical Source", false));
00089 }
00090 }
00091
00092 template<typename EvalT, typename Traits>
00093 void J2Model<EvalT, Traits>::
00094 computeState(typename Traits::EvalData workset,
00095 std::map<std::string, Teuchos::RCP<PHX::MDField<ScalarT> > > dep_fields,
00096 std::map<std::string, Teuchos::RCP<PHX::MDField<ScalarT> > > eval_fields)
00097 {
00098 std::string cauchy_string = (*field_name_map_)["Cauchy_Stress"];
00099 std::string Fp_string = (*field_name_map_)["Fp"];
00100 std::string eqps_string = (*field_name_map_)["eqps"];
00101 std::string source_string = (*field_name_map_)["Mechanical_Source"];
00102 std::string F_string = (*field_name_map_)["F"];
00103 std::string J_string = (*field_name_map_)["J"];
00104
00105
00106 PHX::MDField<ScalarT> def_grad = *dep_fields[F_string];
00107 PHX::MDField<ScalarT> J = *dep_fields[J_string];
00108 PHX::MDField<ScalarT> poissons_ratio = *dep_fields["Poissons Ratio"];
00109 PHX::MDField<ScalarT> elastic_modulus = *dep_fields["Elastic Modulus"];
00110 PHX::MDField<ScalarT> yieldStrength = *dep_fields["Yield Strength"];
00111 PHX::MDField<ScalarT> hardeningModulus = *dep_fields["Hardening Modulus"];
00112 PHX::MDField<ScalarT> delta_time = *dep_fields["Delta Time"];
00113
00114
00115 PHX::MDField<ScalarT> stress = *eval_fields[cauchy_string];
00116 PHX::MDField<ScalarT> Fp = *eval_fields[Fp_string];
00117 PHX::MDField<ScalarT> eqps = *eval_fields[eqps_string];
00118 PHX::MDField<ScalarT> source;
00119 if (have_temperature_) {
00120 source = *eval_fields[source_string];
00121 }
00122
00123
00124 Albany::MDArray Fpold = (*workset.stateArrayPtr)[Fp_string + "_old"];
00125 Albany::MDArray eqpsold = (*workset.stateArrayPtr)[eqps_string + "_old"];
00126
00127 ScalarT kappa, mu, mubar, K, Y;
00128 ScalarT Jm23, trace, smag2, smag, f, p, dgam;
00129 ScalarT sq23(std::sqrt(2. / 3.));
00130
00131 Intrepid::Tensor<ScalarT> F(num_dims_), be(num_dims_), s(num_dims_), sigma(
00132 num_dims_);
00133 Intrepid::Tensor<ScalarT> N(num_dims_), A(num_dims_), expA(num_dims_), Fpnew(
00134 num_dims_);
00135 Intrepid::Tensor<ScalarT> I(Intrepid::eye<ScalarT>(num_dims_));
00136 Intrepid::Tensor<ScalarT> Fpn(num_dims_), Fpinv(num_dims_), Cpinv(num_dims_);
00137
00138 for (std::size_t cell(0); cell < workset.numCells; ++cell) {
00139 for (std::size_t pt(0); pt < num_pts_; ++pt) {
00140 kappa = elastic_modulus(cell, pt)
00141 / (3. * (1. - 2. * poissons_ratio(cell, pt)));
00142 mu = elastic_modulus(cell, pt) / (2. * (1. + poissons_ratio(cell, pt)));
00143 K = hardeningModulus(cell, pt);
00144 Y = yieldStrength(cell, pt);
00145 Jm23 = std::pow(J(cell, pt), -2. / 3.);
00146
00147
00148 F.fill(&def_grad(cell, pt, 0, 0));
00149
00150 for (std::size_t i(0); i < num_dims_; ++i) {
00151 for (std::size_t j(0); j < num_dims_; ++j) {
00152 Fpn(i, j) = ScalarT(Fpold(cell, pt, i, j));
00153 }
00154 }
00155
00156
00157 Fpinv = Intrepid::inverse(Fpn);
00158 Cpinv = Fpinv * Intrepid::transpose(Fpinv);
00159 be = Jm23 * F * Cpinv * Intrepid::transpose(F);
00160 s = mu * Intrepid::dev(be);
00161 mubar = Intrepid::trace(be) * mu / (num_dims_);
00162
00163
00164 smag = Intrepid::norm(s);
00165 f = smag - sq23 * (Y + K * eqpsold(cell, pt)
00166 + sat_mod_ * (1. - std::exp(-sat_exp_ * eqpsold(cell, pt))));
00167
00168 if (f > 1E-12) {
00169
00170 bool converged = false;
00171 ScalarT g = f;
00172 ScalarT H = 0.0;
00173 ScalarT dH = 0.0;
00174 ScalarT alpha = 0.0;
00175 ScalarT res = 0.0;
00176 int count = 0;
00177 dgam = 0.0;
00178
00179 LocalNonlinearSolver<EvalT, Traits> solver;
00180
00181 std::vector<ScalarT> F(1);
00182 std::vector<ScalarT> dFdX(1);
00183 std::vector<ScalarT> X(1);
00184
00185 F[0] = f;
00186 X[0] = 0.0;
00187 dFdX[0] = (-2. * mubar) * (1. + H / (3. * mubar));
00188 while (!converged && count < 30)
00189 {
00190 count++;
00191 solver.solve(dFdX, X, F);
00192 alpha = eqpsold(cell, pt) + sq23 * X[0];
00193 H = K * alpha + sat_mod_ * (1. - exp(-sat_exp_ * alpha));
00194 dH = K + sat_exp_ * sat_mod_ * exp(-sat_exp_ * alpha);
00195 F[0] = smag - (2. * mubar * X[0] + sq23 * (Y + H));
00196 dFdX[0] = -2. * mubar * (1. + dH / (3. * mubar));
00197
00198 res = std::abs(F[0]);
00199 if (res < 1.e-11 || res / f < 1.E-11)
00200 converged = true;
00201
00202 TEUCHOS_TEST_FOR_EXCEPTION(count > 30, std::runtime_error,
00203 std::endl <<
00204 "Error in return mapping, count = " <<
00205 count <<
00206 "\nres = " << res <<
00207 "\nrelres = " << res/f <<
00208 "\ng = " << F[0] <<
00209 "\ndg = " << dFdX[0] <<
00210 "\nalpha = " << alpha << std::endl);
00211 }
00212 solver.computeFadInfo(dFdX, X, F);
00213 dgam = X[0];
00214
00215
00216 N = (1 / smag) * s;
00217
00218
00219 s -= 2 * mubar * dgam * N;
00220
00221
00222 eqps(cell, pt) = alpha;
00223
00224
00225 if (have_temperature_ && delta_time(0) > 0) {
00226 source(cell, pt) = (sq23 * dgam / delta_time(0)
00227 * (Y + H + temperature_(cell,pt))) / (density_ * heat_capacity_);
00228 }
00229
00230
00231 A = dgam * N;
00232 expA = Intrepid::exp(A);
00233 Fpnew = expA * Fpn;
00234 for (std::size_t i(0); i < num_dims_; ++i) {
00235 for (std::size_t j(0); j < num_dims_; ++j) {
00236 Fp(cell, pt, i, j) = Fpnew(i, j);
00237 }
00238 }
00239 } else {
00240 eqps(cell, pt) = eqpsold(cell, pt);
00241 if (have_temperature_) source(cell, pt) = 0.0;
00242 for (std::size_t i(0); i < num_dims_; ++i) {
00243 for (std::size_t j(0); j < num_dims_; ++j) {
00244 Fp(cell, pt, i, j) = Fpn(i, j);
00245 }
00246 }
00247 }
00248
00249
00250 p = 0.5 * kappa * (J(cell, pt) - 1. / (J(cell, pt)));
00251
00252
00253 sigma = p * I + s / J(cell, pt);
00254 for (std::size_t i(0); i < num_dims_; ++i) {
00255 for (std::size_t j(0); j < num_dims_; ++j) {
00256 stress(cell, pt, i, j) = sigma(i, j);
00257 }
00258 }
00259 }
00260 }
00261
00262 if (have_temperature_) {
00263 for (std::size_t cell(0); cell < workset.numCells; ++cell) {
00264 for (std::size_t pt(0); pt < num_pts_; ++pt) {
00265 F.fill(&def_grad(cell,pt,0,0));
00266 ScalarT J = Intrepid::det(F);
00267 sigma.fill(&stress(cell,pt,0,0));
00268 sigma -= 3.0 * expansion_coeff_ * (1.0 + 1.0 / (J*J))
00269 * (temperature_(cell,pt) - ref_temperature_) * I;
00270 for (std::size_t i = 0; i < num_dims_; ++i) {
00271 for (std::size_t j = 0; j < num_dims_; ++j) {
00272 stress(cell, pt, i, j) = sigma(i, j);
00273 }
00274 }
00275 }
00276 }
00277 }
00278
00279 }
00280
00281 }
00282