diff --git a/src/model/solid_mechanics/materials/material_thermal.cc b/src/model/solid_mechanics/materials/material_thermal.cc index 8c5dc0ed4..ebd887e52 100644 --- a/src/model/solid_mechanics/materials/material_thermal.cc +++ b/src/model/solid_mechanics/materials/material_thermal.cc @@ -1,77 +1,79 @@ /** * Copyright (©) 2010-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne) * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) * * This file is part of Akantu * * Akantu is free software: you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License as published by the Free * Software Foundation, either version 3 of the License, or (at your option) any * later version. * * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. * * You should have received a copy of the GNU Lesser General Public License * along with Akantu. If not, see <http://www.gnu.org/licenses/>. */ /* -------------------------------------------------------------------------- */ #include "material_thermal.hh" /* -------------------------------------------------------------------------- */ namespace akantu { /* -------------------------------------------------------------------------- */ template <Int dim> MaterialThermal<dim>::MaterialThermal(SolidMechanicsModel & model, const ID & id, const ID & fe_engine_id) : Parent(model, id, fe_engine_id), delta_T(this->registerInternal("delta_T", 1)), - sigma_th(this->registerInternal("sigma_th", 1)) { + sigma_th(this->registerInternal("sigma_th", 1)), + epsilon_th(this->registerInternal("epsilon_th", 1)) { sigma_th.initializeHistory(); + epsilon_th.initializeHistory(); this->registerParam("E", E, Real(0.), _pat_parsable | _pat_modifiable, "Young's modulus"); this->registerParam("nu", nu, Real(0.5), _pat_parsable | _pat_modifiable, "Poisson's ratio"); this->registerParam("alpha", alpha, Real(0.), _pat_parsable | _pat_modifiable, "Thermal expansion coefficient"); this->registerParam("delta_T", delta_T, _pat_parsable | _pat_modifiable, "Uniform temperature field"); } /* -------------------------------------------------------------------------- */ template <Int dim> void MaterialThermal<dim>::computeStress(ElementType el_type, GhostType ghost_type) { auto && arguments = getArguments(el_type, ghost_type); for (auto && args : arguments) { computeStressOnQuad(args); } } /* -------------------------------------------------------------------------- */ template <> void MaterialThermal<2>::computeStress(ElementType el_type, GhostType ghost_type) { auto && arguments = getArguments(el_type, ghost_type); if (this->plane_stress) { for (auto && args : arguments) { computeStressOnQuadPlaneStress(args); } } else { for (auto && args : arguments) { computeStressOnQuad(args); } } } /* -------------------------------------------------------------------------- */ template class MaterialThermal<1>; template class MaterialThermal<2>; template class MaterialThermal<3>; } // namespace akantu diff --git a/src/model/solid_mechanics/materials/material_thermal.hh b/src/model/solid_mechanics/materials/material_thermal.hh index 578177599..610adb130 100644 --- a/src/model/solid_mechanics/materials/material_thermal.hh +++ b/src/model/solid_mechanics/materials/material_thermal.hh @@ -1,123 +1,132 @@ /** * Copyright (©) 2010-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne) * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) * * This file is part of Akantu * * Akantu is free software: you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License as published by the Free * Software Foundation, either version 3 of the License, or (at your option) any * later version. * * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. * * You should have received a copy of the GNU Lesser General Public License * along with Akantu. If not, see <http://www.gnu.org/licenses/>. */ /* -------------------------------------------------------------------------- */ #include "material.hh" #include "plane_stress_toolbox.hh" /* -------------------------------------------------------------------------- */ #ifndef AKANTU_MATERIAL_THERMAL_HH_ #define AKANTU_MATERIAL_THERMAL_HH_ namespace akantu { template <Int dim> class MaterialThermal : public PlaneStressToolbox<dim, Material> { private: using Parent = PlaneStressToolbox<dim, Material>; /* ------------------------------------------------------------------------ */ /* Constructors/Destructors */ /* ------------------------------------------------------------------------ */ public: MaterialThermal(SolidMechanicsModel & model, const ID & id = "", const ID & fe_engine_id = ""); /* ------------------------------------------------------------------------ */ /* Methods */ /* ------------------------------------------------------------------------ */ public: /// constitutive law for all element of a type void computeStress(ElementType el_type, GhostType ghost_type) override; /// local computation of thermal stress template <class Args> inline void computeStressOnQuad(Args && args); template <class Args> inline void computeStressOnQuadPlaneStress(Args && args); /* ------------------------------------------------------------------------ */ template <Int dim_ = dim> decltype(auto) getArguments(ElementType el_type, GhostType ghost_type) { - return zip_append(Material::getArguments<dim_>(el_type, ghost_type), - "delta_T"_n = delta_T(el_type, ghost_type), - "sigma_th"_n = sigma_th(el_type, ghost_type), - "previous_sigma_th"_n = - sigma_th.previous(el_type, ghost_type)); + return zip_append( + Material::getArguments<dim_>(el_type, ghost_type), + "delta_T"_n = delta_T(el_type, ghost_type), + "epsilon_th"_n = epsilon_th(el_type, ghost_type), + "previous_epsilon_th"_n = epsilon_th.previous(el_type, ghost_type), + "sigma_th"_n = sigma_th(el_type, ghost_type), + "previous_sigma_th"_n = sigma_th.previous(el_type, ghost_type)); } template <Int dim_ = dim> decltype(auto) getArgumentsTangent(Array<Real> & tangent_matrices, ElementType el_type, GhostType ghost_type) { return Material::getArgumentsTangent<dim_>(tangent_matrices, el_type, ghost_type); } /* ------------------------------------------------------------------------ */ /* Class Members */ /* ------------------------------------------------------------------------ */ protected: /// Young modulus Real E{0.}; /// Poisson ratio Real nu{1. / 2.}; /// Thermal expansion coefficient /// TODO : implement alpha as a matrix Real alpha{0.}; /// Temperature field InternalField<Real> & delta_T; /// Current thermal stress InternalField<Real> & sigma_th; + + /// Thermal strain + InternalField<Real> & epsilon_th; }; /* ------------------------------------------------------------------------ */ /* Inline impl */ /* ------------------------------------------------------------------------ */ template <Int dim> template <class Args> inline void MaterialThermal<dim>::computeStressOnQuad(Args && args) { + auto && epsilon = args["epsilon_th"_n]; auto && sigma = args["sigma_th"_n]; auto && deltaT = args["delta_T"_n]; - sigma = -this->E / (1. - 2. * this->nu) * this->alpha * deltaT; + epsilon = deltaT * this->alpha; + sigma = -this->E / (1. - 2. * this->nu) * epsilon; } template <> template <class Args> inline void MaterialThermal<2>::computeStressOnQuadPlaneStress(Args && args) { auto && epsilon = args["epsilon_th"_n]; auto && sigma = args["sigma_th"_n]; auto && deltaT = args["delta_T"_n]; epsilon = deltaT * this->alpha; sigma = -this->E / (1. - this->nu) * epsilon; } template <> template <class Args> inline void MaterialThermal<1>::computeStressOnQuad(Args && args) { + auto && epsilon = args["epsilon_th"_n]; auto && sigma = args["sigma_th"_n]; auto && deltaT = args["delta_T"_n]; - sigma = -this->E * this->alpha * deltaT; + epsilon = deltaT * this->alpha; + sigma = -this->E * epsilon; } } // namespace akantu #endif /* AKANTU_MATERIAL_THERMAL_HH_ */ diff --git a/test/test_model/test_solid_mechanics_model/test_materials/test_material_thermal.cc b/test/test_model/test_solid_mechanics_model/test_materials/test_material_thermal.cc index 24c284c22..0fe960b0d 100644 --- a/test/test_model/test_solid_mechanics_model/test_materials/test_material_thermal.cc +++ b/test/test_model/test_solid_mechanics_model/test_materials/test_material_thermal.cc @@ -1,98 +1,106 @@ /** * Copyright (©) 2010-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne) * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) * * This file is part of Akantu * * Akantu is free software: you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License as published by the Free * Software Foundation, either version 3 of the License, or (at your option) any * later version. * * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. * * You should have received a copy of the GNU Lesser General Public License * along with Akantu. If not, see <http://www.gnu.org/licenses/>. */ /* -------------------------------------------------------------------------- */ #include "material_thermal.hh" #include "solid_mechanics_model.hh" #include "test_material_fixtures.hh" /* -------------------------------------------------------------------------- */ #include <gtest/gtest.h> #include <type_traits> /* -------------------------------------------------------------------------- */ using namespace akantu; using mat_types = ::testing::Types<Traits<MaterialThermal, 1>, Traits<MaterialThermal, 2>, Traits<MaterialThermal, 3>>; /* -------------------------------------------------------------------------- */ template <> void FriendMaterial<MaterialThermal<3>>::testComputeStress() { Real E = 1.; Real nu = .3; Real alpha = 2; setParam("E", E); setParam("nu", nu); setParam("alpha", alpha); Real deltaT = 1; Real sigma = 0; - this->computeStressOnQuad( - make_named_tuple("sigma_th"_n = sigma, "delta_T"_n = deltaT)); + Real epsilon = 0; + this->computeStressOnQuad(make_named_tuple( + "sigma_th"_n = sigma, "delta_T"_n = deltaT, "epsilon_th"_n = epsilon)); Real solution = -E / (1 - 2 * nu) * alpha * deltaT; auto error = std::abs(sigma - solution); ASSERT_NEAR(error, 0, 1e-14); } template <> void FriendMaterial<MaterialThermal<2>>::testComputeStress() { Real E = 1.; Real nu = .3; Real alpha = 2; setParam("E", E); setParam("nu", nu); setParam("alpha", alpha); Real deltaT = 1; Real sigma = 0; - this->computeStressOnQuad( - make_named_tuple("sigma_th"_n = sigma, "delta_T"_n = deltaT)); + Real epsilon = 0; + this->computeStressOnQuad(make_named_tuple( + "sigma_th"_n = sigma, "delta_T"_n = deltaT, "epsilon_th"_n = epsilon)); Real solution = -E / (1 - 2 * nu) * alpha * deltaT; auto error = std::abs(sigma - solution); ASSERT_NEAR(error, 0, 1e-14); + this->computeStressOnQuadPlaneStress(make_named_tuple( + "sigma_th"_n = sigma, "delta_T"_n = deltaT, "epsilon_th"_n = epsilon)); + solution = -E / (1 - nu) * alpha * deltaT; + error = std::abs(sigma - solution); + ASSERT_NEAR(error, 0, 1e-14); } template <> void FriendMaterial<MaterialThermal<1>>::testComputeStress() { Real E = 1.; Real nu = .3; Real alpha = 2; setParam("E", E); setParam("nu", nu); setParam("alpha", alpha); Real deltaT = 1; Real sigma = 0; - this->computeStressOnQuad( - make_named_tuple("sigma_th"_n = sigma, "delta_T"_n = deltaT)); + Real epsilon = 0; + this->computeStressOnQuad(make_named_tuple( + "sigma_th"_n = sigma, "delta_T"_n = deltaT, "epsilon_th"_n = epsilon)); Real solution = -E * alpha * deltaT; auto error = std::abs(sigma - solution); ASSERT_NEAR(error, 0, 1e-14); } namespace { template <typename T> class TestMaterialThermalFixture : public ::TestMaterialFixture<T> {}; TYPED_TEST_SUITE(TestMaterialThermalFixture, mat_types, ); TYPED_TEST(TestMaterialThermalFixture, ThermalComputeStress) { this->material->testComputeStress(); } } // namespace