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

AnisotropicDamageModel_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 #include <typeinfo>
00011 
00012 namespace LCM
00013 {
00014 
00015 //------------------------------------------------------------------------------
00016 template<typename EvalT, typename Traits>
00017 AnisotropicDamageModel<EvalT, Traits>::
00018 AnisotropicDamageModel(Teuchos::ParameterList* p,
00019     const Teuchos::RCP<Albany::Layouts>& dl) :
00020         LCM::ConstitutiveModel<EvalT, Traits>(p, dl),
00021         k_f1_(p->get<RealType>("Fiber 1 k", 1.0)),
00022         q_f1_(p->get<RealType>("Fiber 1 q", 1.0)),
00023         volume_fraction_f1_(p->get<RealType>("Fiber 1 volume fraction", 0.0)),
00024         max_damage_f1_(p->get<RealType>("Fiber 1 maximum damage", 1.0)),
00025         saturation_f1_(p->get<RealType>("Fiber 1 damage saturation", 0.0)),
00026         k_f2_(p->get<RealType>("Fiber 2 k", 1.0)),
00027         q_f2_(p->get<RealType>("Fiber 2 q", 1.0)),
00028         volume_fraction_f2_(p->get<RealType>("Fiber 2 volume fraction", 0.0)),
00029         max_damage_f2_(p->get<RealType>("Fiber 2 maximum damage", 1.0)),
00030         saturation_f2_(p->get<RealType>("Fiber 2 damage saturation", 0.0)),
00031         volume_fraction_m_(p->get<RealType>("Matrix volume fraction", 1.0)),
00032         max_damage_m_(p->get<RealType>("Matrix maximum damage", 1.0)),
00033         saturation_m_(p->get<RealType>("Matrix damage saturation", 0.0)),
00034         direction_f1_(
00035             p->get<Teuchos::Array<RealType> >("Fiber 1 Orientation Vector")
00036                 .toVector()),
00037         direction_f2_(
00038             p->get<Teuchos::Array<RealType> >("Fiber 2 Orientation Vector")
00039                 .toVector())
00040 {
00041   // define the dependent fields
00042   this->dep_field_map_.insert(std::make_pair("F", dl->qp_tensor));
00043   this->dep_field_map_.insert(std::make_pair("J", dl->qp_scalar));
00044   this->dep_field_map_.insert(std::make_pair("Poissons Ratio", dl->qp_scalar));
00045   this->dep_field_map_.insert(std::make_pair("Elastic Modulus", dl->qp_scalar));
00046 
00047   // retrieve appropriate field name strings
00048   std::string cauchy_string = (*field_name_map_)["Cauchy_Stress"];
00049   std::string matrix_energy_string = (*field_name_map_)["Matrix_Energy"];
00050   std::string f1_energy_string = (*field_name_map_)["F1_Energy"];
00051   std::string f2_energy_string = (*field_name_map_)["F2_Energy"];
00052   std::string matrix_damage_string = (*field_name_map_)["Matrix_Damage"];
00053   std::string f1_damage_string = (*field_name_map_)["F1_Damage"];
00054   std::string f2_damage_string = (*field_name_map_)["F2_Damage"];
00055 
00056   // define the evaluated fields
00057   this->eval_field_map_.insert(std::make_pair(cauchy_string, dl->qp_tensor));
00058   this->eval_field_map_.insert(
00059       std::make_pair(matrix_energy_string, dl->qp_scalar));
00060   this->eval_field_map_.insert(std::make_pair(f1_energy_string, dl->qp_scalar));
00061   this->eval_field_map_.insert(std::make_pair(f2_energy_string, dl->qp_scalar));
00062   this->eval_field_map_.insert(
00063       std::make_pair(matrix_damage_string, dl->qp_scalar));
00064   this->eval_field_map_.insert(std::make_pair(f1_damage_string, dl->qp_scalar));
00065   this->eval_field_map_.insert(std::make_pair(f2_damage_string, dl->qp_scalar));
00066   this->eval_field_map_.insert(
00067       std::make_pair("Material Tangent", dl->qp_tensor4));
00068 
00069   // define the state variables
00070   //
00071   // stress
00072   this->num_state_variables_++;
00073   this->state_var_names_.push_back(cauchy_string);
00074   this->state_var_layouts_.push_back(dl->qp_tensor);
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(false);
00078   this->state_var_output_flags_.push_back(true);
00079   //
00080   // matrix energy
00081   this->num_state_variables_++;
00082   this->state_var_names_.push_back(matrix_energy_string);
00083   this->state_var_layouts_.push_back(dl->qp_scalar);
00084   this->state_var_init_types_.push_back("scalar");
00085   this->state_var_init_values_.push_back(0.0);
00086   this->state_var_old_state_flags_.push_back(true);
00087   this->state_var_output_flags_.push_back(true);
00088   //
00089   // fiber 1 energy
00090   this->num_state_variables_++;
00091   this->state_var_names_.push_back(f1_energy_string);
00092   this->state_var_layouts_.push_back(dl->qp_scalar);
00093   this->state_var_init_types_.push_back("scalar");
00094   this->state_var_init_values_.push_back(0.0);
00095   this->state_var_old_state_flags_.push_back(true);
00096   this->state_var_output_flags_.push_back(true);
00097   //
00098   // fiber 2 energy
00099   this->num_state_variables_++;
00100   this->state_var_names_.push_back(f2_energy_string);
00101   this->state_var_layouts_.push_back(dl->qp_scalar);
00102   this->state_var_init_types_.push_back("scalar");
00103   this->state_var_init_values_.push_back(0.0);
00104   this->state_var_old_state_flags_.push_back(true);
00105   this->state_var_output_flags_.push_back(true);
00106   //
00107   // matrix damage
00108   this->num_state_variables_++;
00109   this->state_var_names_.push_back(matrix_damage_string);
00110   this->state_var_layouts_.push_back(dl->qp_scalar);
00111   this->state_var_init_types_.push_back("scalar");
00112   this->state_var_init_values_.push_back(0.0);
00113   this->state_var_old_state_flags_.push_back(true);
00114   this->state_var_output_flags_.push_back(true);
00115   //
00116   // fiber 1 damage
00117   this->num_state_variables_++;
00118   this->state_var_names_.push_back(f1_damage_string);
00119   this->state_var_layouts_.push_back(dl->qp_scalar);
00120   this->state_var_init_types_.push_back("scalar");
00121   this->state_var_init_values_.push_back(0.0);
00122   this->state_var_old_state_flags_.push_back(true);
00123   this->state_var_output_flags_.push_back(true);
00124   //
00125   // fiber 2 damage
00126   this->num_state_variables_++;
00127   this->state_var_names_.push_back(f2_damage_string);
00128   this->state_var_layouts_.push_back(dl->qp_scalar);
00129   this->state_var_init_types_.push_back("scalar");
00130   this->state_var_init_values_.push_back(0.0);
00131   this->state_var_old_state_flags_.push_back(true);
00132   this->state_var_output_flags_.push_back(true);
00133 
00134 }
00135 //----------------------------------------------------------------------------
00136 template<typename EvalT, typename Traits>
00137 void AnisotropicDamageModel<EvalT, Traits>::
00138 computeState(typename Traits::EvalData workset,
00139     std::map<std::string, Teuchos::RCP<PHX::MDField<ScalarT> > > dep_fields,
00140     std::map<std::string, Teuchos::RCP<PHX::MDField<ScalarT> > > eval_fields)
00141 {
00142   //bool print = false;
00143   //if (typeid(ScalarT) == typeid(RealType)) print = true;
00144   //cout.precision(15);
00145 
00146   // extract dependent MDFields
00147   PHX::MDField<ScalarT> def_grad = *dep_fields["F"];
00148   PHX::MDField<ScalarT> J = *dep_fields["J"];
00149   PHX::MDField<ScalarT> poissons_ratio = *dep_fields["Poissons Ratio"];
00150   PHX::MDField<ScalarT> elastic_modulus = *dep_fields["Elastic Modulus"];
00151 
00152   // retrieve appropriate field name strings
00153   std::string cauchy_string = (*field_name_map_)["Cauchy_Stress"];
00154   std::string matrix_energy_string = (*field_name_map_)["Matrix_Energy"];
00155   std::string f1_energy_string = (*field_name_map_)["F1_Energy"];
00156   std::string f2_energy_string = (*field_name_map_)["F2_Energy"];
00157   std::string matrix_damage_string = (*field_name_map_)["Matrix_Damage"];
00158   std::string f1_damage_string = (*field_name_map_)["F1_Damage"];
00159   std::string f2_damage_string = (*field_name_map_)["F2_Damage"];
00160 
00161   // extract evaluated MDFields
00162   PHX::MDField<ScalarT> stress = *eval_fields[cauchy_string];
00163   PHX::MDField<ScalarT> energy_m = *eval_fields[matrix_energy_string];
00164   PHX::MDField<ScalarT> energy_f1 = *eval_fields[f1_energy_string];
00165   PHX::MDField<ScalarT> energy_f2 = *eval_fields[f2_energy_string];
00166   PHX::MDField<ScalarT> damage_m = *eval_fields[matrix_damage_string];
00167   PHX::MDField<ScalarT> damage_f1 = *eval_fields[f1_damage_string];
00168   PHX::MDField<ScalarT> damage_f2 = *eval_fields[f2_damage_string];
00169   PHX::MDField<ScalarT> tangent = *eval_fields["Material Tangent"];
00170 
00171   // previous state
00172   Albany::MDArray energy_m_old =
00173       (*workset.stateArrayPtr)[matrix_energy_string + "_old"];
00174   Albany::MDArray energy_f1_old =
00175       (*workset.stateArrayPtr)[f1_energy_string + "_old"];
00176   Albany::MDArray energy_f2_old =
00177       (*workset.stateArrayPtr)[f2_energy_string + "_old"];
00178 
00179   ScalarT mu, lame, mu_tilde, I1_m, I3_m, lnI3_m;
00180   ScalarT I4_f1, I4_f2;
00181   ScalarT alpha_f1, alpha_f2, alpha_m;
00182   ScalarT coefficient_f1, coefficient_f2;
00183   ScalarT damage_deriv_m, damage_deriv_f1, damage_deriv_f2;
00184 
00185   // Define some tensors for use
00186   Intrepid::Tensor<ScalarT> I(Intrepid::eye<ScalarT>(num_dims_));
00187   Intrepid::Tensor<ScalarT> F(num_dims_), C(num_dims_), invC(num_dims_);
00188   Intrepid::Tensor<ScalarT> sigma_m(num_dims_), sigma_f1(num_dims_), sigma_f2(
00189       num_dims_);
00190   Intrepid::Tensor<ScalarT> M1dyadM1(num_dims_), M2dyadM2(num_dims_);
00191   Intrepid::Tensor<ScalarT> S0_m(num_dims_), S0_f1(num_dims_), S0_f2(num_dims_);
00192 
00193   Intrepid::Tensor4<ScalarT> Tangent_m(num_dims_);
00194   Intrepid::Tensor4<ScalarT> Tangent_f1(num_dims_), Tangent_f2(num_dims_);
00195 
00196   Intrepid::Vector<ScalarT> M1(num_dims_), M2(num_dims_);
00197 
00198   volume_fraction_m_ = 1.0 - volume_fraction_f1_ - volume_fraction_f2_;
00199 
00200   for (std::size_t cell = 0; cell < workset.numCells; ++cell) {
00201     for (std::size_t pt = 0; pt < num_pts_; ++pt) {
00202       // local parameters
00203       mu = elastic_modulus(cell, pt)
00204           / (2.0 * (1.0 + poissons_ratio(cell, pt)));
00205       lame = elastic_modulus(cell, pt) * poissons_ratio(cell, pt)
00206           / (1.0 + poissons_ratio(cell, pt))
00207           / (1.0 - 2.0 * poissons_ratio(cell, pt));
00208 
00209       F.fill(&def_grad(cell, pt, 0, 0));
00210       // Right Cauchy-Green Tensor C = F^{T} * F
00211 
00212       C = Intrepid::transpose(F) * F;
00213       invC = Intrepid::inverse(C);
00214       I1_m = Intrepid::trace(C);
00215       I3_m = Intrepid::det(C);
00216       lnI3_m = std::log(I3_m);
00217 
00218       // energy for M
00219       energy_m(cell, pt) = volume_fraction_m_ * (0.125 * lame * lnI3_m * lnI3_m
00220           - 0.5 * mu * lnI3_m + 0.5 * mu * (I1_m - 3.0));
00221 
00222       // 2nd PK stress (undamaged) for M
00223       S0_m = 0.5 * lame * lnI3_m * invC + mu * (I - invC);
00224 
00225       // undamaged Cauchy stress for M
00226       sigma_m = (1.0 / J(cell, pt))
00227           * Intrepid::dot(F, Intrepid::dot(S0_m, Intrepid::transpose(F)));
00228 
00229       // elasticity tensor (undamaged) for M
00230       mu_tilde = mu - 0.5 * lame * lnI3_m;
00231       Tangent_m = lame * Intrepid::tensor(invC, invC)
00232           + mu_tilde * (Intrepid::tensor2(invC, invC)
00233               + Intrepid::tensor3(invC, invC));
00234 
00235       // damage term in M
00236       alpha_m = energy_m_old(cell, pt);
00237       if (energy_m(cell, pt) > alpha_m) alpha_m = energy_m(cell, pt);
00238 
00239       damage_m(cell, pt) = max_damage_m_
00240           * (1 - std::exp(-alpha_m / saturation_m_));
00241 
00242       // derivative of damage w.r.t alpha
00243       damage_deriv_m =
00244           max_damage_m_ / saturation_m_ * std::exp(-alpha_m / saturation_m_);
00245 
00246       // tangent for matrix considering damage
00247       Tangent_m = (1.0 - damage_m(cell, pt)) * Tangent_m
00248           - damage_deriv_m * Intrepid::tensor(S0_m, S0_m);
00249 
00250       //-----------compute quantities in Fibers------------
00251 
00252       // Fiber orientation vectors
00253       //
00254       // fiber 1
00255       for (std::size_t i = 0; i < num_dims_; ++i) {
00256         M1(i) = direction_f1_[i];
00257       }
00258       M1 = M1 / norm(M1);
00259 
00260       // fiber 2
00261       for (std::size_t i = 0; i < num_dims_; ++i) {
00262         M2(i) = direction_f2_[i];
00263       }
00264       M2 = M2 / norm(M2);
00265 
00266       // Anisotropic invariants I4 = M_{i} * C * M_{i}
00267       I4_f1 = Intrepid::dot(M1, Intrepid::dot(C, M1));
00268       I4_f2 = Intrepid::dot(M2, Intrepid::dot(C, M2));
00269       M1dyadM1 = Intrepid::dyad(M1, M1);
00270       M2dyadM2 = Intrepid::dyad(M2, M2);
00271 
00272       // compute energy for fibers
00273       energy_f1(cell, pt) = volume_fraction_f1_ * (k_f1_
00274           * (std::exp(q_f1_ * (I4_f1 - 1) * (I4_f1 - 1)) - 1) / q_f1_);
00275       energy_f2(cell, pt) = volume_fraction_f2_ * (k_f2_
00276           * (std::exp(q_f2_ * (I4_f2 - 1) * (I4_f2 - 1)) - 1) / q_f2_);
00277 
00278       // undamaged stress (2nd PK stress)
00279       S0_f1 = (4.0 * k_f1_ * (I4_f1 - 1.0)
00280           * std::exp(q_f1_ * (I4_f1 - 1) * (I4_f1 - 1))) * M1dyadM1;
00281       S0_f2 = (4.0 * k_f2_ * (I4_f2 - 1.0)
00282           * std::exp(q_f2_ * (I4_f2 - 1) * (I4_f2 - 1))) * M2dyadM2;
00283 
00284       // Fiber undamaged Cauchy stress
00285       sigma_f1 = (1.0 / J(cell, pt))
00286           * Intrepid::dot(F, Intrepid::dot(S0_f1, Intrepid::transpose(F)));
00287       sigma_f2 = (1.0 / J(cell, pt))
00288           * Intrepid::dot(F, Intrepid::dot(S0_f2, Intrepid::transpose(F)));
00289 
00290       // undamaged tangent for fibers
00291       coefficient_f1 = 8.0 * k_f1_
00292           * (1.0 + 2.0 * q_f1_ * (I4_f1 - 1.0) * (I4_f1 - 1.0))
00293           * exp(q_f1_ * (I4_f1 - 1.0) * (I4_f1 - 1.0));
00294 
00295       coefficient_f2 = 8.0 * k_f2_
00296           * (1.0 + 2.0 * q_f2_ * (I4_f2 - 1.0) * (I4_f2 - 1.0))
00297           * exp(q_f2_ * (I4_f2 - 1.0) * (I4_f2 - 1.0));
00298 
00299       Tangent_f1 = coefficient_f1 * Intrepid::tensor(M1dyadM1, M1dyadM1);
00300       Tangent_f2 = coefficient_f2 * Intrepid::tensor(M2dyadM2, M2dyadM2);
00301 
00302       // maximum thermodynamic forces
00303       alpha_f1 = energy_f1_old(cell, pt);
00304       alpha_f2 = energy_f2_old(cell, pt);
00305 
00306       if (energy_f1(cell, pt) > alpha_f1) alpha_f1 = energy_f1(cell, pt);
00307 
00308       if (energy_f2(cell, pt) > alpha_f2) alpha_f2 = energy_f2(cell, pt);
00309 
00310       // damage term in fibers
00311       damage_f1(cell, pt) = max_damage_f1_
00312           * (1 - std::exp(-alpha_f1 / saturation_f1_));
00313       damage_f2(cell, pt) = max_damage_f2_
00314           * (1 - std::exp(-alpha_f2 / saturation_f2_));
00315 
00316       // derivative of damage w.r.t alpha
00317       damage_deriv_f1 =
00318           max_damage_f1_ / saturation_f1_
00319               * std::exp(-alpha_f1 / saturation_f1_);
00320 
00321       damage_deriv_f2 =
00322           max_damage_f2_ / saturation_f2_
00323               * std::exp(-alpha_f2 / saturation_f2_);
00324 
00325       // tangent for fibers including damage
00326       Tangent_f1 = (1.0 - damage_f1(cell, pt)) * Tangent_f1
00327           - damage_deriv_f1 * Intrepid::tensor(S0_f1, S0_f1);
00328       Tangent_f2 = (1.0 - damage_f2(cell, pt)) * Tangent_f2
00329           - damage_deriv_f2 * Intrepid::tensor(S0_f2, S0_f2);
00330 
00331       // total Cauchy stress (M, Fibers)
00332       for (std::size_t i(0); i < num_dims_; ++i) {
00333         for (std::size_t j(0); j < num_dims_; ++j) {
00334           stress(cell, pt, i, j) =
00335               volume_fraction_m_ * (1.0 - damage_m(cell, pt)) * sigma_m(i, j)
00336                   + volume_fraction_f1_ * (1. - damage_f1(cell, pt))
00337                       * sigma_f1(i, j)
00338                   + volume_fraction_f2_ * (1. - damage_f2(cell, pt))
00339                       * sigma_f2(i, j);
00340         }
00341       }
00342 
00343       // total tangent (M, Fibers)
00344       for (std::size_t i(0); i < num_dims_; ++i) {
00345         for (std::size_t j(0); j < num_dims_; ++j) {
00346           for (std::size_t k(0); k < num_dims_; ++k) {
00347             for (std::size_t l(0); l < num_dims_; ++l) {
00348 
00349               tangent(cell, pt, i, j, k, l) =
00350                   volume_fraction_m_ * Tangent_m(i, j, k, l)
00351                       + volume_fraction_f1_ * Tangent_f1(i, j, k, l)
00352                       + volume_fraction_f2_ * Tangent_f2(i, j, k, l);
00353 
00354             }
00355           }
00356         }
00357       }
00358     } // pt
00359   } // cell
00360 }
00361 //----------------------------------------------------------------------------
00362 }
00363 

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