00001
00002
00003
00004
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
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
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
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
00070
00071
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
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
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
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
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
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
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
00143
00144
00145
00146
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
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
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
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
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
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
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
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
00223 S0_m = 0.5 * lame * lnI3_m * invC + mu * (I - invC);
00224
00225
00226 sigma_m = (1.0 / J(cell, pt))
00227 * Intrepid::dot(F, Intrepid::dot(S0_m, Intrepid::transpose(F)));
00228
00229
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
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
00243 damage_deriv_m =
00244 max_damage_m_ / saturation_m_ * std::exp(-alpha_m / saturation_m_);
00245
00246
00247 Tangent_m = (1.0 - damage_m(cell, pt)) * Tangent_m
00248 - damage_deriv_m * Intrepid::tensor(S0_m, S0_m);
00249
00250
00251
00252
00253
00254
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
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
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
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
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
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
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
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
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
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
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
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
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 }
00359 }
00360 }
00361
00362 }
00363