• Main Page
  • Related Pages
  • Namespaces
  • Classes
  • Files
  • File List
  • File Members

J2Model_Def.hpp

Go to the documentation of this file.
00001 //*****************************************************************//
00002 //    Albany 2.0:  Copyright 2012 Sandia Corporation               //
00003 //    This Software is released under the BSD license detailed     //
00004 //    in the file "license.txt" in the top-level Albany directory  //
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   // retrive appropriate field name strings
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   // define the dependent fields
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   // define the evaluated fields
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   // define the state variables
00052   //
00053   // stress
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   // Fp
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   // eqps
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   // mechanical source
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   // extract dependent MDFields
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   // extract evaluated MDFields
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   // get State Variables
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       // fill local tensors
00148       F.fill(&def_grad(cell, pt, 0, 0));
00149       //Fpn.fill( &Fpold(cell,pt,std::size_t(0),std::size_t(0)) );
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       // compute trial state
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       // check yield condition
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         // return mapping algorithm
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         // plastic direction
00216         N = (1 / smag) * s;
00217 
00218         // update s
00219         s -= 2 * mubar * dgam * N;
00220 
00221         // update eqps
00222         eqps(cell, pt) = alpha;
00223 
00224         // mechanical source
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         // exponential map to get Fpnew
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       // compute pressure
00250       p = 0.5 * kappa * (J(cell, pt) - 1. / (J(cell, pt)));
00251 
00252       // compute stress
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 

Generated on Wed Mar 26 2014 18:36:39 for Albany: a Trilinos-based PDE code by  doxygen 1.7.1