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

RIHMRModel_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 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   // define the dependent fields
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   // retrieve appropriate field name strings
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   // define evaluated fields
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   // define the state variables
00050   //
00051   // stress
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   // logFp
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   // eqps
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   // isoHardening
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   // extract dependent MDFields
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   // retrieve appropriate field name strings
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   // extract evaluated MDFields
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   // get State Variables
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   // scratch space FCs
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   //local unknowns and residual vectors
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       //logFp_n.fill(&logFp_old(cell, pt, std::size_t(0), std::size_t(0)) );
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 // std::cout << "logFp_n(" << cell << ", " << pt << ", " << i << ", " << j << " ) = " << logFp_n(i, j) << std::endl;
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       // Compute Trial State
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       // check for yielding
00192       smag = Intrepid::norm(s);
00193       Phi = smag - sq23 * (Y + isoH);
00194 
00195       if (Phi > 1e-11) { // plastic yielding
00196 
00197         // return mapping algorithm
00198         bool converged = false;
00199         int iter = 0;
00200         dgam = 0.0;
00201 
00202         // initialize local unknown vector
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           //              std::cout << iter << " " << normR << " " << conv << std::endl;
00221           if (conv < 1.e-11 || normR < 1.e-11) break;
00222           if (iter > 20) break;
00223 
00224           //            TEUCHOS_TEST_FOR_EXCEPTION( iter > 20, std::runtime_error,
00225           //                std::endl << "Error in return mapping, iter = " << iter << "\nres = " << normR << "\nrelres = " << conv << std::endl);
00226 
00227           solver.solve(dRdX, X, R);
00228           iter++;
00229         }
00230 
00231         // compute sensitivity information w.r.t system parameters, and pack back to X
00232         solver.computeFadInfo(dRdX, X, R);
00233 
00234         // update
00235         dgam = X[0];
00236         isoH = X[1];
00237 
00238         // plastic direction
00239         n = ScalarT(1. / smag) * s;
00240 
00241         // updated deviatoric stress
00242         s -= ScalarT(2. * mubar * dgam) * n;
00243 
00244         // update isoHardening
00245         isoHardening(cell, pt) = isoH;
00246 
00247         // update eqps
00248         eqps(cell, pt) = eqps_old(cell, pt) + sq23 * dgam;
00249 
00250         // exponential map to get Fp
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         // set state variables to old values
00265         isoHardening(cell, pt) = isoHardening_old(cell, pt);
00266 
00267         eqps(cell, pt) = eqps_old(cell, pt);
00268         Fp = Fpold;
00269       }
00270 
00271       // store logFp as the state variable
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       // compute pressure
00278       p = 0.5 * kappa * (J(cell, pt) - 1 / (J(cell, pt)));
00279 
00280       // compute stress
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 } // end of compute state
00291 //----------------------------------------------------------------------------
00292 // all local functions for compute state
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   // initialize DFadType local unknown vector Xfad
00306   // Note that since Xfad is a temporary variable
00307   // that gets changed within local iterations.
00308   // Therefore, when we initialize Xfad, we only pass in the values of X
00309   // NOT the system sensitivity information
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   //I have to break down these equations, to avoid compile error
00321   //Q.Chen.
00322   // smagfad = smag - 2.0 * mubar * dgam;
00323   smagfad = mubar * dgam;
00324   smagfad = 2.0 * smagfad;
00325   smagfad = smag - smagfad;
00326 
00327   // Yfad = sq23 * (Y + isoHfad);
00328   Yfad = Y + isoHfad;
00329   Yfad = sq23 * Yfad;
00330 
00331   //d_isoH = (K - Rd * isoHfad) * sq23 * dgam;
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   // local nonlinear sys of equations
00338   Rfad[0] = smagfad - Yfad; // Phi = smag - 2.* mubar * dgam - sq23 * (Y + isoHfad);
00339   Rfad[1] = isoHfad - isoH - d_isoH;
00340 
00341   // get ScalarT residual
00342   R[0] = Rfad[0].val();
00343   R[1] = Rfad[1].val();
00344 
00345   // get local Jacobian
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 }

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