00001
00002
00003
00004
00005
00006
00007 #include <Intrepid_MiniTensor.h>
00008 #include "Teuchos_TestForException.hpp"
00009 #include "Phalanx_DataLayout.hpp"
00010
00011 namespace LCM
00012 {
00013
00014
00015 template<typename EvalT, typename Traits>
00016 NeohookeanModel<EvalT, Traits>::
00017 NeohookeanModel(Teuchos::ParameterList* p,
00018 const Teuchos::RCP<Albany::Layouts>& dl) :
00019 LCM::ConstitutiveModel<EvalT, Traits>(p, dl)
00020 {
00021 std::string F_string = (*field_name_map_)["F"];
00022 std::string J_string = (*field_name_map_)["J"];
00023 std::string cauchy = (*field_name_map_)["Cauchy_Stress"];
00024
00025
00026 this->dep_field_map_.insert(std::make_pair(F_string, dl->qp_tensor));
00027 this->dep_field_map_.insert(std::make_pair(J_string, 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
00031
00032 this->eval_field_map_.insert(std::make_pair(cauchy, dl->qp_tensor));
00033 this->eval_field_map_.insert(std::make_pair("Energy", dl->qp_scalar));
00034 this->eval_field_map_.insert(
00035 std::make_pair("Material Tangent", dl->qp_tensor4));
00036
00037
00038 this->num_state_variables_++;
00039 this->state_var_names_.push_back(cauchy);
00040 this->state_var_layouts_.push_back(dl->qp_tensor);
00041 this->state_var_init_types_.push_back("scalar");
00042 this->state_var_init_values_.push_back(0.0);
00043 this->state_var_old_state_flags_.push_back(false);
00044 this->state_var_output_flags_.push_back(p->get<bool>("Output Cauchy Stress", false));
00045 }
00046
00047 template<typename EvalT, typename Traits>
00048 void NeohookeanModel<EvalT, Traits>::
00049 computeState(typename Traits::EvalData workset,
00050 std::map<std::string, Teuchos::RCP<PHX::MDField<ScalarT> > > dep_fields,
00051 std::map<std::string, Teuchos::RCP<PHX::MDField<ScalarT> > > eval_fields)
00052 {
00053 std::string F_string = (*field_name_map_)["F"];
00054 std::string J_string = (*field_name_map_)["J"];
00055 std::string cauchy = (*field_name_map_)["Cauchy_Stress"];
00056
00057
00058 PHX::MDField<ScalarT> def_grad = *dep_fields[F_string];
00059 PHX::MDField<ScalarT> J = *dep_fields[J_string];
00060 PHX::MDField<ScalarT> poissons_ratio = *dep_fields["Poissons Ratio"];
00061 PHX::MDField<ScalarT> elastic_modulus = *dep_fields["Elastic Modulus"];
00062
00063 PHX::MDField<ScalarT> stress = *eval_fields[cauchy];
00064 PHX::MDField<ScalarT> energy = *eval_fields["Energy"];
00065 PHX::MDField<ScalarT> tangent = *eval_fields["Material Tangent"];
00066 ScalarT kappa;
00067 ScalarT mu, mubar;
00068 ScalarT Jm53, Jm23;
00069 ScalarT smag;
00070
00071 Intrepid::Tensor<ScalarT> F(num_dims_), b(num_dims_), sigma(num_dims_);
00072 Intrepid::Tensor<ScalarT> I(Intrepid::eye<ScalarT>(num_dims_));
00073 Intrepid::Tensor<ScalarT> s(num_dims_), n(num_dims_);
00074
00075 Intrepid::Tensor4<ScalarT> dsigmadb;
00076 Intrepid::Tensor4<ScalarT> I1(Intrepid::identity_1<ScalarT>(num_dims_));
00077 Intrepid::Tensor4<ScalarT> I3(Intrepid::identity_3<ScalarT>(num_dims_));
00078
00079 for (std::size_t cell(0); cell < workset.numCells; ++cell) {
00080 for (std::size_t pt(0); pt < num_pts_; ++pt) {
00081 kappa =
00082 elastic_modulus(cell, pt)
00083 / (3. * (1. - 2. * poissons_ratio(cell, pt)));
00084 mu =
00085 elastic_modulus(cell, pt) / (2. * (1. + poissons_ratio(cell, pt)));
00086 Jm53 = std::pow(J(cell, pt), -5. / 3.);
00087 Jm23 = Jm53 * J(cell, pt);
00088
00089 F.fill(&def_grad(cell, pt, 0, 0));
00090 b = F * transpose(F);
00091 mubar = (1.0 / 3.0) * mu * Jm23 * Intrepid::trace(b);
00092
00093 sigma = 0.5 * kappa * (J(cell, pt) - 1. / J(cell, pt)) * I
00094 + mu * Jm53 * Intrepid::dev(b);
00095
00096 for (std::size_t i = 0; i < num_dims_; ++i) {
00097 for (std::size_t j = 0; j < num_dims_; ++j) {
00098 stress(cell, pt, i, j) = sigma(i, j);
00099 }
00100 }
00101
00102 if (compute_energy_) {
00103 energy(cell, pt) =
00104 0.5 * kappa
00105 * (0.5 * (J(cell, pt) * J(cell, pt) - 1.0)
00106 - std::log(J(cell, pt)))
00107 + 0.5 * mu * (Jm23 * Intrepid::trace(b) - 3.0);
00108 }
00109
00110 if (compute_tangent_) {
00111
00112 s = Intrepid::dev(sigma);
00113 smag = Intrepid::norm(s);
00114 n = s / smag;
00115
00116 dsigmadb =
00117 kappa * J(cell, pt) * J(cell, pt) * I3
00118 - kappa * (J(cell, pt) * J(cell, pt) - 1.0) * I1
00119 + 2.0 * mubar * (I1 - (1.0 / 3.0) * I3)
00120 - 2.0 / 3.0 * smag
00121 * (Intrepid::tensor(n, I) + Intrepid::tensor(I, n));
00122
00123 for (std::size_t i = 0; i < num_dims_; ++i) {
00124 for (std::size_t j = 0; j < num_dims_; ++j) {
00125 for (std::size_t k = 0; k < num_dims_; ++k) {
00126 for (std::size_t l = 0; l < num_dims_; ++l) {
00127 tangent(cell, pt, i, j, k, l) = dsigmadb(i, j, k, l);
00128 }
00129 }
00130 }
00131 }
00132 }
00133 }
00134 }
00135
00136 if (have_temperature_) {
00137 for (std::size_t cell(0); cell < workset.numCells; ++cell) {
00138 for (std::size_t pt(0); pt < num_pts_; ++pt) {
00139 F.fill(&def_grad(cell,pt,0,0));
00140 ScalarT J = Intrepid::det(F);
00141 sigma.fill(&stress(cell,pt,0,0));
00142 sigma -= 3.0 * expansion_coeff_ * (1.0 + 1.0 / (J*J))
00143 * (temperature_(cell,pt) - ref_temperature_) * I;
00144
00145 for (std::size_t i = 0; i < num_dims_; ++i) {
00146 for (std::size_t j = 0; j < num_dims_; ++j) {
00147 stress(cell, pt, i, j) = sigma(i, j);
00148 }
00149 }
00150 }
00151 }
00152 }
00153 }
00154
00155 }
00156