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 RIHMRModel<EvalT, Traits>::
00019 RIHMRModel(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 this->dep_field_map_.insert(std::make_pair("F", dl->qp_tensor));
00027 this->dep_field_map_.insert(std::make_pair("J", dl->qp_scalar));
00028 this->dep_field_map_.insert(std::make_pair("Poissons Ratio", dl->qp_scalar));
00029 this->dep_field_map_.insert(std::make_pair("Elastic Modulus", dl->qp_scalar));
00030 this->dep_field_map_.insert(std::make_pair("Yield Strength", dl->qp_scalar));
00031 this->dep_field_map_.insert(
00032 std::make_pair("Hardening Modulus", dl->qp_scalar));
00033 this->dep_field_map_.insert(
00034 std::make_pair("Recovery Modulus", dl->qp_scalar));
00035
00036
00037 std::string cauchy_string = (*field_name_map_)["Cauchy_Stress"];
00038 std::string logFp_string = (*field_name_map_)["logFp"];
00039 std::string eqps_string = (*field_name_map_)["eqps"];
00040 std::string isoHardening_string = (*field_name_map_)["isoHardening"];
00041
00042
00043 this->eval_field_map_.insert(std::make_pair(cauchy_string, dl->qp_tensor));
00044 this->eval_field_map_.insert(std::make_pair(logFp_string, dl->qp_tensor));
00045 this->eval_field_map_.insert(std::make_pair(eqps_string, dl->qp_scalar));
00046 this->eval_field_map_.insert(
00047 std::make_pair(isoHardening_string, dl->qp_scalar));
00048
00049
00050
00051
00052 this->num_state_variables_++;
00053 this->state_var_names_.push_back(cauchy_string);
00054 this->state_var_layouts_.push_back(dl->qp_tensor);
00055 this->state_var_init_types_.push_back("scalar");
00056 this->state_var_init_values_.push_back(0.0);
00057 this->state_var_old_state_flags_.push_back(false);
00058 this->state_var_output_flags_.push_back(true);
00059
00060
00061 this->num_state_variables_++;
00062 this->state_var_names_.push_back(logFp_string);
00063 this->state_var_layouts_.push_back(dl->qp_tensor);
00064 this->state_var_init_types_.push_back("scalar");
00065 this->state_var_init_values_.push_back(0.0);
00066 this->state_var_old_state_flags_.push_back(true);
00067 this->state_var_output_flags_.push_back(false);
00068
00069
00070 this->num_state_variables_++;
00071 this->state_var_names_.push_back(eqps_string);
00072 this->state_var_layouts_.push_back(dl->qp_scalar);
00073 this->state_var_init_types_.push_back("scalar");
00074 this->state_var_init_values_.push_back(0.0);
00075 this->state_var_old_state_flags_.push_back(true);
00076 this->state_var_output_flags_.push_back(true);
00077
00078
00079 this->num_state_variables_++;
00080 this->state_var_names_.push_back(isoHardening_string);
00081 this->state_var_layouts_.push_back(dl->qp_scalar);
00082 this->state_var_init_types_.push_back("scalar");
00083 this->state_var_init_values_.push_back(0.0);
00084 this->state_var_old_state_flags_.push_back(true);
00085 this->state_var_output_flags_.push_back(true);
00086 }
00087
00088 template<typename EvalT, typename Traits>
00089 void RIHMRModel<EvalT, Traits>::
00090 computeState(typename Traits::EvalData workset,
00091 std::map<std::string, Teuchos::RCP<PHX::MDField<ScalarT> > > dep_fields,
00092 std::map<std::string, Teuchos::RCP<PHX::MDField<ScalarT> > > eval_fields)
00093 {
00094
00095 PHX::MDField<ScalarT> def_grad = *dep_fields["F"];
00096 PHX::MDField<ScalarT> J = *dep_fields["J"];
00097 PHX::MDField<ScalarT> poissons_ratio = *dep_fields["Poissons Ratio"];
00098 PHX::MDField<ScalarT> elastic_modulus = *dep_fields["Elastic Modulus"];
00099 PHX::MDField<ScalarT> yield_strength = *dep_fields["Yield Strength"];
00100 PHX::MDField<ScalarT> hardening_modulus = *dep_fields["Hardening Modulus"];
00101 PHX::MDField<ScalarT> recovery_modulus = *dep_fields["Recovery Modulus"];
00102
00103
00104 std::string cauchy_string = (*field_name_map_)["Cauchy_Stress"];
00105 std::string logFp_string = (*field_name_map_)["logFp"];
00106 std::string eqps_string = (*field_name_map_)["eqps"];
00107 std::string isoHardening_string = (*field_name_map_)["isoHardening"];
00108
00109
00110 PHX::MDField<ScalarT> stress = *eval_fields[cauchy_string];
00111 PHX::MDField<ScalarT> logFp = *eval_fields[logFp_string];
00112 PHX::MDField<ScalarT> eqps = *eval_fields[eqps_string];
00113 PHX::MDField<ScalarT> isoHardening = *eval_fields[isoHardening_string];
00114
00115
00116 Albany::MDArray logFp_old =
00117 (*workset.stateArrayPtr)[logFp_string + "_old"];
00118 Albany::MDArray eqps_old =
00119 (*workset.stateArrayPtr)[eqps_string + "_old"];
00120 Albany::MDArray isoHardening_old =
00121 (*workset.stateArrayPtr)[isoHardening_string + "_old"];
00122
00123
00124 Intrepid::Tensor<ScalarT> be(num_dims_);
00125 Intrepid::Tensor<ScalarT> s(num_dims_);
00126 Intrepid::Tensor<ScalarT> n(num_dims_);
00127 Intrepid::Tensor<ScalarT> A(num_dims_);
00128 Intrepid::Tensor<ScalarT> expA(num_dims_);
00129
00130 Intrepid::Tensor<ScalarT> logFp_n(num_dims_);
00131 Intrepid::Tensor<ScalarT> Fp(num_dims_);
00132 Intrepid::Tensor<ScalarT> Fpold(num_dims_);
00133 Intrepid::Tensor<ScalarT> Cpinv(num_dims_);
00134 Intrepid::Tensor<ScalarT> I(Intrepid::eye<ScalarT>(num_dims_));
00135
00136 ScalarT kappa, Rd;
00137 ScalarT mu, mubar;
00138 ScalarT K, Y;
00139 ScalarT Jm23;
00140 ScalarT trd3, smag;
00141 ScalarT Phi, p, dgam, isoH;
00142 ScalarT sq23 = std::sqrt(2.0 / 3.0);
00143
00144
00145 std::vector<ScalarT> R(2);
00146 std::vector<ScalarT> X(2);
00147 std::vector<ScalarT> dRdX(4);
00148 ScalarT normR0(0.0), normR(0.0), conv(0.0);
00149 LocalNonlinearSolver<EvalT, Traits> solver;
00150
00151 for (std::size_t cell = 0; cell < workset.numCells; ++cell) {
00152 for (std::size_t pt = 0; pt < num_pts_; ++pt) {
00153
00154
00155 for (std::size_t i(0); i < num_dims_; ++i) {
00156 for (std::size_t j(0); j < num_dims_; ++j) {
00157 logFp_n(i, j) = static_cast<ScalarT>(logFp_old(cell, pt, i, j));
00158
00159 }
00160 }
00161
00162 Fp = Intrepid::exp(logFp_n);
00163 Fpold = Fp;
00164 Cpinv = Intrepid::dot(Intrepid::inverse(Fp),
00165 Intrepid::transpose(Intrepid::inverse(Fp)));
00166
00167 kappa = elastic_modulus(cell, pt)
00168 / (3.0 * (1.0 - 2.0 * poissons_ratio(cell, pt)));
00169 mu = elastic_modulus(cell, pt)
00170 / (2.0 * (1.0 + poissons_ratio(cell, pt)));
00171 K = hardening_modulus(cell, pt);
00172 Y = yield_strength(cell, pt);
00173 Rd = recovery_modulus(cell, pt);
00174 Jm23 = std::pow(J(cell, pt), -2.0 / 3.0);
00175
00176
00177 be.clear();
00178 for (std::size_t i = 0; i < num_dims_; ++i)
00179 for (std::size_t j = 0; j < num_dims_; ++j)
00180 for (std::size_t p = 0; p < num_dims_; ++p)
00181 for (std::size_t q = 0; q < num_dims_; ++q)
00182 be(i, j) += Jm23 * def_grad(cell, pt, i, p) * Cpinv(p, q)
00183 * def_grad(cell, pt, j, q);
00184
00185 trd3 = Intrepid::trace(be) / 3.;
00186 mubar = trd3 * mu;
00187 s = mu * (be - trd3 * I);
00188
00189 isoH = isoHardening_old(cell, pt);
00190
00191
00192 smag = Intrepid::norm(s);
00193 Phi = smag - sq23 * (Y + isoH);
00194
00195 if (Phi > 1e-11) {
00196
00197
00198 bool converged = false;
00199 int iter = 0;
00200 dgam = 0.0;
00201
00202
00203 X[0] = dgam;
00204 X[1] = isoH;
00205
00206 while (!converged) {
00207
00208 ResidualJacobian(X, R, dRdX, isoH, smag, mubar, mu, kappa, K,
00209 Y, Rd);
00210
00211 normR = R[0] * R[0] + R[1] * R[1];
00212 normR = std::sqrt(normR);
00213
00214 if (iter == 0) normR0 = normR;
00215 if (normR0 != 0)
00216 conv = normR / normR0;
00217 else
00218 conv = normR0;
00219
00220
00221 if (conv < 1.e-11 || normR < 1.e-11) break;
00222 if (iter > 20) break;
00223
00224
00225
00226
00227 solver.solve(dRdX, X, R);
00228 iter++;
00229 }
00230
00231
00232 solver.computeFadInfo(dRdX, X, R);
00233
00234
00235 dgam = X[0];
00236 isoH = X[1];
00237
00238
00239 n = ScalarT(1. / smag) * s;
00240
00241
00242 s -= ScalarT(2. * mubar * dgam) * n;
00243
00244
00245 isoHardening(cell, pt) = isoH;
00246
00247
00248 eqps(cell, pt) = eqps_old(cell, pt) + sq23 * dgam;
00249
00250
00251 A = dgam * n;
00252 expA = Intrepid::exp<ScalarT>(A);
00253
00254 for (std::size_t i = 0; i < num_dims_; ++i) {
00255 for (std::size_t j = 0; j < num_dims_; ++j) {
00256 Fp(i, j) = 0.0;
00257 for (std::size_t p = 0; p < num_dims_; ++p) {
00258 Fp(i, j) += expA(i, p) * Fpold(p, j);
00259 }
00260 }
00261 }
00262
00263 } else {
00264
00265 isoHardening(cell, pt) = isoHardening_old(cell, pt);
00266
00267 eqps(cell, pt) = eqps_old(cell, pt);
00268 Fp = Fpold;
00269 }
00270
00271
00272 logFp_n = Intrepid::log(Fp);
00273 for (std::size_t i = 0; i < num_dims_; ++i)
00274 for (std::size_t j = 0; j < num_dims_; ++j)
00275 logFp(cell, pt, i, j) = logFp_n(i, j);
00276
00277
00278 p = 0.5 * kappa * (J(cell, pt) - 1 / (J(cell, pt)));
00279
00280
00281 for (std::size_t i = 0; i < num_dims_; ++i) {
00282 for (std::size_t j = 0; j < num_dims_; ++j) {
00283 stress(cell, pt, i, j) = s(i, j) / J(cell, pt);
00284 }
00285 stress(cell, pt, i, i) += p;
00286 }
00287 }
00288 }
00289
00290 }
00291
00292
00293 template<typename EvalT, typename Traits>
00294 void
00295 RIHMRModel<EvalT, Traits>::ResidualJacobian(std::vector<ScalarT> & X,
00296 std::vector<ScalarT> & R, std::vector<ScalarT> & dRdX,
00297 const ScalarT & isoH, const ScalarT & smag, const ScalarT & mubar,
00298 ScalarT & mu, ScalarT & kappa, ScalarT & K, ScalarT & Y, ScalarT & Rd)
00299 {
00300 ScalarT sq23 = std::sqrt(2.0 / 3.0);
00301 std::vector<DFadType> Rfad(2);
00302 std::vector<DFadType> Xfad(2);
00303 std::vector<ScalarT> Xval(2);
00304
00305
00306
00307
00308
00309
00310 Xval[0] = Sacado::ScalarValue<ScalarT>::eval(X[0]);
00311 Xval[1] = Sacado::ScalarValue<ScalarT>::eval(X[1]);
00312
00313 Xfad[0] = DFadType(2, 0, Xval[0]);
00314 Xfad[1] = DFadType(2, 1, Xval[1]);
00315
00316 DFadType smagfad, Yfad, d_isoH;
00317
00318 DFadType dgam = Xfad[0], isoHfad = Xfad[1];
00319
00320
00321
00322
00323 smagfad = mubar * dgam;
00324 smagfad = 2.0 * smagfad;
00325 smagfad = smag - smagfad;
00326
00327
00328 Yfad = Y + isoHfad;
00329 Yfad = sq23 * Yfad;
00330
00331
00332 d_isoH = Rd * isoHfad;
00333 d_isoH = K - d_isoH;
00334 d_isoH = d_isoH * dgam;
00335 d_isoH = d_isoH * sq23;
00336
00337
00338 Rfad[0] = smagfad - Yfad;
00339 Rfad[1] = isoHfad - isoH - d_isoH;
00340
00341
00342 R[0] = Rfad[0].val();
00343 R[1] = Rfad[1].val();
00344
00345
00346 dRdX[0 + 2 * 0] = Rfad[0].dx(0);
00347 dRdX[0 + 2 * 1] = Rfad[0].dx(1);
00348 dRdX[1 + 2 * 0] = Rfad[1].dx(0);
00349 dRdX[1 + 2 * 1] = Rfad[1].dx(1);
00350 }
00351
00352 }