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 ElasticDamageModel<EvalT, Traits>::
00018 ElasticDamageModel(Teuchos::ParameterList* p,
00019 const Teuchos::RCP<Albany::Layouts>& dl) :
00020 LCM::ConstitutiveModel<EvalT, Traits>(p, dl),
00021 max_damage_(p->get<RealType>("Maximum damage", 1.0)),
00022 saturation_(p->get<RealType>("Damage saturation", 0.0))
00023 {
00024
00025 this->dep_field_map_.insert(std::make_pair("Strain", dl->qp_tensor));
00026 this->dep_field_map_.insert(std::make_pair("Poissons Ratio", dl->qp_scalar));
00027 this->dep_field_map_.insert(std::make_pair("Elastic Modulus", dl->qp_scalar));
00028
00029
00030 std::string cauchy_string = (*field_name_map_)["Cauchy_Stress"];
00031 std::string energy_string = (*field_name_map_)["Matrix_Energy"];
00032 std::string damage_string = (*field_name_map_)["Matrix_Damage"];
00033
00034
00035 this->eval_field_map_.insert(std::make_pair(cauchy_string, dl->qp_tensor));
00036 this->eval_field_map_.insert(std::make_pair(energy_string, dl->qp_scalar));
00037 this->eval_field_map_.insert(std::make_pair(damage_string, dl->qp_scalar));
00038 this->eval_field_map_.insert(
00039 std::make_pair("Material Tangent", dl->qp_tensor4));
00040
00041
00042
00043
00044 this->num_state_variables_++;
00045 this->state_var_names_.push_back(cauchy_string);
00046 this->state_var_layouts_.push_back(dl->qp_tensor);
00047 this->state_var_init_types_.push_back("scalar");
00048 this->state_var_init_values_.push_back(0.0);
00049 this->state_var_old_state_flags_.push_back(false);
00050 this->state_var_output_flags_.push_back(true);
00051
00052
00053 this->num_state_variables_++;
00054 this->state_var_names_.push_back(energy_string);
00055 this->state_var_layouts_.push_back(dl->qp_scalar);
00056 this->state_var_init_types_.push_back("scalar");
00057 this->state_var_init_values_.push_back(0.0);
00058 this->state_var_old_state_flags_.push_back(true);
00059 this->state_var_output_flags_.push_back(true);
00060
00061
00062 this->num_state_variables_++;
00063 this->state_var_names_.push_back(damage_string);
00064 this->state_var_layouts_.push_back(dl->qp_scalar);
00065 this->state_var_init_types_.push_back("scalar");
00066 this->state_var_init_values_.push_back(0.0);
00067 this->state_var_old_state_flags_.push_back(true);
00068 this->state_var_output_flags_.push_back(true);
00069
00070 }
00071
00072 template<typename EvalT, typename Traits>
00073 void ElasticDamageModel<EvalT, Traits>::
00074 computeState(typename Traits::EvalData workset,
00075 std::map<std::string, Teuchos::RCP<PHX::MDField<ScalarT> > > dep_fields,
00076 std::map<std::string, Teuchos::RCP<PHX::MDField<ScalarT> > > eval_fields)
00077 {
00078
00079
00080
00081
00082
00083 PHX::MDField<ScalarT> strain = *dep_fields["Strain"];
00084 PHX::MDField<ScalarT> poissons_ratio = *dep_fields["Poissons Ratio"];
00085 PHX::MDField<ScalarT> elastic_modulus = *dep_fields["Elastic Modulus"];
00086
00087
00088 std::string cauchy_string = (*field_name_map_)["Cauchy_Stress"];
00089 std::string energy_string = (*field_name_map_)["Matrix_Energy"];
00090 std::string damage_string = (*field_name_map_)["Matrix_Damage"];
00091
00092
00093 PHX::MDField<ScalarT> stress = *eval_fields[cauchy_string];
00094 PHX::MDField<ScalarT> energy = *eval_fields[energy_string];
00095 PHX::MDField<ScalarT> damage = *eval_fields[damage_string];
00096 PHX::MDField<ScalarT> tangent = *eval_fields["Material Tangent"];
00097
00098
00099 Albany::MDArray energy_old =
00100 (*workset.stateArrayPtr)[energy_string + "_old"];
00101
00102 ScalarT mu, lame;
00103 ScalarT alpha, damage_deriv;
00104
00105
00106 Intrepid::Tensor<ScalarT> I(Intrepid::eye<ScalarT>(num_dims_));
00107 Intrepid::Tensor<ScalarT> epsilon(num_dims_), sigma(num_dims_);
00108
00109 Intrepid::Tensor4<ScalarT> Ce(num_dims_);
00110 Intrepid::Tensor4<ScalarT> id4(num_dims_);
00111 Intrepid::Tensor4<ScalarT> id3(Intrepid::identity_3<ScalarT>(num_dims_));
00112
00113 id4 = 0.5 * (Intrepid::identity_1<ScalarT>(num_dims_)
00114 + Intrepid::identity_2<ScalarT>(num_dims_));
00115
00116 for (std::size_t cell = 0; cell < workset.numCells; ++cell) {
00117 for (std::size_t pt = 0; pt < num_pts_; ++pt) {
00118
00119 mu = elastic_modulus(cell, pt)
00120 / (2.0 * (1.0 + poissons_ratio(cell, pt)));
00121 lame = elastic_modulus(cell, pt) * poissons_ratio(cell, pt)
00122 / (1.0 + poissons_ratio(cell, pt))
00123 / (1.0 - 2.0 * poissons_ratio(cell, pt));
00124
00125
00126 epsilon.fill(&strain(cell, pt, 0, 0));
00127
00128
00129 Ce = lame * id3 + 2.0 * mu * id4;
00130
00131
00132 energy(cell, pt) =
00133 0.5 * Intrepid::dotdot(Intrepid::dotdot(epsilon, Ce), epsilon);
00134
00135
00136 sigma = Intrepid::dotdot(Ce, epsilon);
00137
00138
00139 alpha = energy_old(cell, pt);
00140 if (energy(cell, pt) > alpha) alpha = energy(cell, pt);
00141
00142
00143 damage(cell, pt) = max_damage_
00144 * (1 - std::exp(-alpha / saturation_));
00145
00146
00147 damage_deriv =
00148 max_damage_ / saturation_ * std::exp(-alpha / saturation_);
00149
00150
00151 Ce = (1.0 - damage(cell, pt)) * Ce
00152 - damage_deriv * Intrepid::tensor(sigma, sigma);
00153
00154
00155 for (std::size_t i(0); i < num_dims_; ++i) {
00156 for (std::size_t j(0); j < num_dims_; ++j) {
00157 stress(cell, pt, i, j) =
00158 (1.0 - damage(cell, pt)) * sigma(i, j);
00159 }
00160 }
00161
00162
00163 for (std::size_t i(0); i < num_dims_; ++i) {
00164 for (std::size_t j(0); j < num_dims_; ++j) {
00165 for (std::size_t k(0); k < num_dims_; ++k) {
00166 for (std::size_t l(0); l < num_dims_; ++l) {
00167
00168 tangent(cell, pt, i, j, k, l) = Ce(i, j, k, l);
00169
00170 }
00171 }
00172 }
00173 }
00174 }
00175 }
00176 }
00177
00178 }