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

DruckerPragerModel_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_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   // define the dependent fields
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   // retrieve appropriate field name strings
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   // 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(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   // define the state variables
00051     // strain
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     // stress
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     // 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     // alpha (friction parameter)
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   // extract dependent MDFields
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   // retrieve appropriate field name strings
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   // extract evaluated MDFields
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   // get State Variables
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   //local unknowns and residual vectors
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       // 4-th order elasticity tensor
00148       Celastic = lambda * id3 + mu * (id1 + id2);
00149         
00150       // previous state (the fill doesn't work for state virable)
00151       //sigmaN.fill( &stressold(cell,pt,0,0) );
00152       //epsilonN.fill( &strainold(cell,pt,0,0) );
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           //epsilon(i,j) = strain(cell,pt,i,j);
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       // trial state
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       // unit deviatoric tensor      
00177       if (snorm > 0){
00178         nhat = s / snorm;
00179        } else{
00180         nhat = id;
00181        }
00182       
00183       // check yielding
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) {// plastic yielding  
00191         
00192         // initialize local unknown vector
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         // local N-R loop
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           //std::cout << iter << " "
00221           //<< Sacado::ScalarValue<ScalarT>::eval(norm_residual)
00222             //<< " " << Sacado::ScalarValue<ScalarT>::eval(relative_residual)
00223             //<< std::endl;
00224             
00225           if (relative_residual < 1.0e-11 || norm_residual < 1.0e-11)
00226               break;
00227             
00228           if (iter > 20)
00229               break;
00230             
00231           // call local nonlinear solver
00232           solver.solve(dRdX, X, R);
00233             
00234           iter++;           
00235               
00236         } // end of local N-R loop        
00237 
00238       // compute sensitivity information w.r.t. system parameters
00239       // and pack the sensitivity back to X
00240       solver.computeFadInfo(dRdX, X, R);        
00241       
00242       // update
00243       p = X[0];
00244       q = X[1];
00245       alpha = X[2];
00246       deq = X[3];
00247     
00248       }//end plastic yielding      
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     }// end loop over pt
00265   } //  end loop over cell
00266 }
00267 //----------------------------------------------------------------------------
00268 // all local functions for compute state
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   // initialize DFadType local unknown vector Xfad
00279   // Note that since Xfad is a temporary variable
00280   // that gets changed within local iterations
00281   // when we initialize Xfad, we only pass in the values of X,
00282   // NOT the system sensitivity information
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   // check this
00297   DFadType eqFad = eqN + deqFad; // (eqFad + deqFad??)
00298   
00299   // have to break down 3.0 * mu * deqFad;
00300   // other wise there wil be compiling error
00301   DFadType dq = deqFad;
00302   dq = mu * dq;
00303   dq = 3.0 * dq;
00304   
00305   // local system of equations
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   // get ScalarT Residual
00313   for (int i = 0; i < 4; i++)
00314     R[i] = Rfad[i].val();
00315 
00316   // get local Jacobian
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 }// end of ResidualJacobian
00322 //------------------------------------------------------------------------------
00323 }
00324 

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