00001
00002
00003
00004
00005
00006
00007 #include <Intrepid_FunctionSpaceTools.hpp>
00008 #include <Intrepid_MiniTensor.h>
00009 #include "Teuchos_TestForException.hpp"
00010 #include "Phalanx_DataLayout.hpp"
00011 #include <typeinfo>
00012
00013 #include "LocalNonlinearSolver.hpp"
00014
00015 namespace LCM
00016 {
00017
00018
00019 template<typename EvalT, typename Traits>
00020 DruckerPragerModel<EvalT, Traits>::
00021 DruckerPragerModel(Teuchos::ParameterList* p,
00022 const Teuchos::RCP<Albany::Layouts>& dl) :
00023 LCM::ConstitutiveModel<EvalT, Traits>(p, dl),
00024 a0_(p->get<RealType>("Initial Friction Parameter a0", 0.0)),
00025 a1_(p->get<RealType>("Hardening Parameter a1", 0.0)),
00026 a2_(p->get<RealType>("Hardening Parameter a2", 1.0)),
00027 a3_(p->get<RealType>("Hardening Parameter a3", 1.0)),
00028 b0_(p->get<RealType>("Critical Friction Coefficient b0", 0.0)),
00029 Cf_(p->get<RealType>("Cohesion Parameter Cf", 0.0)),
00030 Cg_(p->get<RealType>("Plastic Potential Parameter Cg", 0.0))
00031 {
00032
00033 this->dep_field_map_.insert(std::make_pair("Strain", dl->qp_tensor));
00034 this->dep_field_map_.insert(std::make_pair("Poissons Ratio", dl->qp_scalar));
00035 this->dep_field_map_.insert(std::make_pair("Elastic Modulus", dl->qp_scalar));
00036
00037
00038 std::string cauchy_string = (*field_name_map_)["Cauchy_Stress"];
00039 std::string strain_string = (*field_name_map_)["Strain"];
00040 std::string eqps_string = (*field_name_map_)["eqps"];
00041 std::string friction_string = (*field_name_map_)["Friction_Parameter"];
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(eqps_string, dl->qp_scalar));
00046 this->eval_field_map_.insert(std::make_pair(friction_string, dl->qp_scalar));
00047 this->eval_field_map_.insert(
00048 std::make_pair("Material Tangent", dl->qp_tensor4));
00049
00050
00051
00052 this->num_state_variables_++;
00053 this->state_var_names_.push_back(strain_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(true);
00058 this->state_var_output_flags_.push_back(true);
00059
00060
00061 this->num_state_variables_++;
00062 this->state_var_names_.push_back(cauchy_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(true);
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(friction_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(a0_);
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 DruckerPragerModel<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> strain = *dep_fields["Strain"];
00096 PHX::MDField<ScalarT> poissons_ratio = *dep_fields["Poissons Ratio"];
00097 PHX::MDField<ScalarT> elastic_modulus = *dep_fields["Elastic Modulus"];
00098
00099
00100 std::string cauchy_string = (*field_name_map_)["Cauchy_Stress"];
00101 std::string strain_string = (*field_name_map_)["Strain"];
00102 std::string eqps_string = (*field_name_map_)["eqps"];
00103 std::string friction_string = (*field_name_map_)["Friction_Parameter"];
00104
00105
00106 PHX::MDField<ScalarT> stress = *eval_fields[cauchy_string];
00107 PHX::MDField<ScalarT> eqps = *eval_fields[eqps_string];
00108 PHX::MDField<ScalarT> friction = *eval_fields[friction_string];
00109 PHX::MDField<ScalarT> tangent = *eval_fields["Material Tangent"];
00110
00111
00112 Albany::MDArray strainold = (*workset.stateArrayPtr)[strain_string + "_old"];
00113 Albany::MDArray stressold = (*workset.stateArrayPtr)[cauchy_string + "_old"];
00114 Albany::MDArray eqpsold = (*workset.stateArrayPtr)[eqps_string + "_old"];
00115 Albany::MDArray frictionold = (*workset.stateArrayPtr)[friction_string + "_old"];
00116
00117 Intrepid::Tensor<ScalarT> id(Intrepid::eye<ScalarT>(num_dims_));
00118 Intrepid::Tensor4<ScalarT> id1(Intrepid::identity_1<ScalarT>(num_dims_));
00119 Intrepid::Tensor4<ScalarT> id2(Intrepid::identity_2<ScalarT>(num_dims_));
00120 Intrepid::Tensor4<ScalarT> id3(Intrepid::identity_3<ScalarT>(num_dims_));
00121
00122 Intrepid::Tensor4<ScalarT> Celastic (num_dims_);
00123 Intrepid::Tensor<ScalarT> sigma(num_dims_), sigmaN(num_dims_), s(num_dims_);
00124 Intrepid::Tensor<ScalarT> epsilon(num_dims_), epsilonN(num_dims_);
00125 Intrepid::Tensor<ScalarT> depsilon(num_dims_);
00126 Intrepid::Tensor<ScalarT> nhat(num_dims_);
00127
00128 ScalarT lambda, mu, kappa;
00129 ScalarT alpha, alphaN;
00130 ScalarT p, q, ptr, qtr;
00131 ScalarT eq, eqN, deq;
00132 ScalarT snorm;
00133 ScalarT Phi;
00134
00135
00136 std::vector<ScalarT> X(4);
00137 std::vector<ScalarT> R(4);
00138 std::vector<ScalarT> dRdX(16);
00139
00140 for (std::size_t cell(0); cell < workset.numCells; ++cell) {
00141 for (std::size_t pt(0); pt < num_pts_; ++pt) {
00142 lambda = ( elastic_modulus(cell,pt) * poissons_ratio(cell,pt) )
00143 / ( ( 1 + poissons_ratio(cell,pt) ) * ( 1 - 2 * poissons_ratio(cell,pt) ) );
00144 mu = elastic_modulus(cell,pt) / ( 2 * ( 1 + poissons_ratio(cell,pt) ) );
00145 kappa = lambda + 2.0 * mu / 3.0;
00146
00147
00148 Celastic = lambda * id3 + mu * (id1 + id2);
00149
00150
00151
00152
00153
00154 for (std::size_t i(0); i < num_dims_; ++i) {
00155 for (std::size_t j(0); j < num_dims_; ++j) {
00156 sigmaN(i, j) = stressold(cell, pt, i, j);
00157 epsilonN(i, j) = strainold(cell, pt, i, j);
00158
00159 }
00160 }
00161
00162 epsilon.fill( &strain(cell,pt,0,0) );
00163 depsilon = epsilon - epsilonN;
00164
00165 alphaN = frictionold(cell,pt);
00166 eqN = eqpsold(cell,pt);
00167
00168
00169 sigma = sigmaN + Intrepid::dotdot(Celastic,depsilon);
00170 ptr = Intrepid::trace(sigma) / 3.0;
00171 s = sigma - ptr * id;
00172 snorm = Intrepid::dotdot(s,s);
00173 if(snorm > 0) snorm = std::sqrt(snorm);
00174 qtr = sqrt(3.0/2.0) * snorm;
00175
00176
00177 if (snorm > 0){
00178 nhat = s / snorm;
00179 } else{
00180 nhat = id;
00181 }
00182
00183
00184 Phi = qtr + alphaN * ptr - Cf_;
00185
00186 alpha = alphaN;
00187 p = ptr;
00188 q = qtr;
00189 deq = 0.0;
00190 if(Phi > 1.0e-12) {
00191
00192
00193 X[0] = ptr;
00194 X[1] = qtr;
00195 X[2] = alpha;
00196 X[3] = deq;
00197
00198 LocalNonlinearSolver<EvalT, Traits> solver;
00199 int iter = 0;
00200 ScalarT norm_residual0(0.0), norm_residual(0.0), relative_residual(0.0);
00201
00202
00203 while (true) {
00204
00205 ResidualJacobian(X, R, dRdX, ptr, qtr, eqN, mu, kappa);
00206
00207 norm_residual = 0.0;
00208 for (int i = 0; i < 4; i++)
00209 norm_residual += R[i] * R[i];
00210 norm_residual = std::sqrt(norm_residual);
00211
00212 if (iter == 0)
00213 norm_residual0 = norm_residual;
00214
00215 if (norm_residual0 != 0)
00216 relative_residual = norm_residual / norm_residual0;
00217 else
00218 relative_residual = norm_residual0;
00219
00220
00221
00222
00223
00224
00225 if (relative_residual < 1.0e-11 || norm_residual < 1.0e-11)
00226 break;
00227
00228 if (iter > 20)
00229 break;
00230
00231
00232 solver.solve(dRdX, X, R);
00233
00234 iter++;
00235
00236 }
00237
00238
00239
00240 solver.computeFadInfo(dRdX, X, R);
00241
00242
00243 p = X[0];
00244 q = X[1];
00245 alpha = X[2];
00246 deq = X[3];
00247
00248 }
00249
00250 eq = eqN + deq;
00251
00252 s = sqrt(2.0/3.0) * q * nhat;
00253 sigma = s + p * id;
00254
00255 eqps(cell, pt) = eq;
00256 friction(cell,pt) = alpha;
00257
00258 for (std::size_t i(0); i < num_dims_; ++i) {
00259 for (std::size_t j(0); j < num_dims_; ++j) {
00260 stress(cell,pt,i,j) = sigma(i, j);
00261 }
00262 }
00263
00264 }
00265 }
00266 }
00267
00268
00269 template<typename EvalT, typename Traits>
00270 void
00271 DruckerPragerModel<EvalT, Traits>::ResidualJacobian(std::vector<ScalarT> & X,
00272 std::vector<ScalarT> & R, std::vector<ScalarT> & dRdX,
00273 const ScalarT ptr, const ScalarT qtr, const ScalarT eqN,
00274 const ScalarT mu, const ScalarT kappa)
00275 {
00276 std::vector<DFadType> Rfad(4);
00277 std::vector<DFadType> Xfad(4);
00278
00279
00280
00281
00282
00283 std::vector<ScalarT> Xval(4);
00284 for (std::size_t i = 0; i < 4; ++i) {
00285 Xval[i] = Sacado::ScalarValue<ScalarT>::eval(X[i]);
00286 Xfad[i] = DFadType(4, i, Xval[i]);
00287 }
00288
00289 DFadType pFad = Xfad[0];
00290 DFadType qFad = Xfad[1];
00291 DFadType alphaFad = Xfad[2];
00292 DFadType deqFad = Xfad[3];
00293
00294 DFadType betaFad = alphaFad - b0_;
00295
00296
00297 DFadType eqFad = eqN + deqFad;
00298
00299
00300
00301 DFadType dq = deqFad;
00302 dq = mu * dq;
00303 dq = 3.0 * dq;
00304
00305
00306 Rfad[0] = pFad - ptr + kappa * betaFad * deqFad;
00307 Rfad[1] = qFad - qtr + dq;
00308 Rfad[2] = alphaFad
00309 - (a0_ + a1_ * eqFad * std::exp(a2_ * pFad - a3_ * eqFad));
00310 Rfad[3] = qFad + alphaFad * pFad - Cf_;
00311
00312
00313 for (int i = 0; i < 4; i++)
00314 R[i] = Rfad[i].val();
00315
00316
00317 for (int i = 0; i < 4; i++)
00318 for (int j = 0; j < 4; j++)
00319 dRdX[i + 4 * j] = Rfad[i].dx(j);
00320
00321 }
00322
00323 }
00324