diff --git a/src/model/hooke.cpp b/src/model/hooke.cpp index 45eb0d2e..9cd04e1b 100644 --- a/src/model/hooke.cpp +++ b/src/model/hooke.cpp @@ -1,190 +1,198 @@ /* * SPDX-License-Indentifier: AGPL-3.0-or-later * * Copyright (©) 2016-2024 EPFL (École Polytechnique Fédérale de Lausanne), * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) * Copyright (©) 2020-2024 Lucas Frérot * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as published * by the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program 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 Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see <https://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #include "hooke.hh" #include "influence.hh" #include "loop.hh" #include "model.hh" #include "static_types.hh" #include <boost/preprocessor/seq.hpp> /* -------------------------------------------------------------------------- */ namespace tamaas { template <model_type type> void Hooke<type>::apply(GridBase<Real>& strain, GridBase<Real>& stress) const { constexpr auto dim = model_type_traits<type>::dimension; const influence::ElasticHelper<dim> elasticity( this->model->getShearModulus(), this->model->getPoissonRatio()); // Checking incompressibility if (elasticity.nu == 0.5) throw std::range_error{TAMAAS_MSG("Incompressibility error, nu = 0.5")}; // Checking number of components if (strain.getNbComponents() == dim * dim) { Loop::loop( [elasticity] CUDA_LAMBDA(MatrixProxy<Real, dim, dim> sigma, MatrixProxy<const Real, dim, dim> epsilon) { sigma = elasticity(epsilon); }, range<MatrixProxy<Real, dim, dim>>(stress), range<MatrixProxy<const Real, dim, dim>>(strain)); } // in case we have voigt notation else if (strain.getNbComponents() == voigt_size<dim>::value) { Loop::loop( [elasticity] CUDA_LAMBDA(SymMatrixProxy<Real, dim> sigma, SymMatrixProxy<const Real, dim> epsilon) { sigma = elasticity(epsilon); }, range<SymMatrixProxy<Real, dim>>(stress), range<SymMatrixProxy<const Real, dim>>(strain)); } else throw std::invalid_argument{TAMAAS_MSG("Strain components (", strain.getNbComponents(), ") do not match model type ", type)}; } /* -------------------------------------------------------------------------- */ template <model_type type> std::pair<UInt, UInt> Hooke<type>::matvecShape() const { auto shape = this->model->getDiscretization(); auto N = std::accumulate(shape.begin(), shape.end(), 6, std::multiplies<UInt>()); return std::make_pair(N, N); } template <model_type type> GridBase<Real> Hooke<type>::matvec(GridBase<Real>& X) const { constexpr auto dim = model_type_traits<type>::dimension; X.setNbComponents(voigt_size<dim>::value); GridBase<Real> x(X.getGlobalNbPoints(), X.getNbComponents()); apply(X, x); return x; } /* -------------------------------------------------------------------------- */ template <model_type type> HookeField<type>::HookeField(Model* model) : Hooke<type>(model) { this->template request<false, Real>("mu", model->getType(), model->getDiscretization(), 1); this->template request<false, Real>("nu", model->getType(), model->getDiscretization(), 1); this->template field<Real>("mu") = model->getShearModulus(); this->template field<Real>("nu") = model->getPoissonRatio(); } template <UInt dim> struct HookeFieldHelper { void operator()(MatrixProxy<Real, dim, dim> sigma, MatrixProxy<const Real, dim, dim> epsilon, const Real& mu, const Real& nu) { elasticity.mu = mu; elasticity.nu = nu; sigma = elasticity(epsilon); } influence::ElasticHelper<dim> elasticity{0, 0}; }; template <UInt dim> struct SymHookeFieldHelper { void operator()(SymMatrixProxy<Real, dim> sigma, SymMatrixProxy<const Real, dim> epsilon, const Real& mu, const Real& nu) { elasticity.mu = mu; elasticity.nu = nu; sigma = elasticity(epsilon); } influence::ElasticHelper<dim> elasticity{0, 0}; }; template <model_type type> void HookeField<type>::apply(GridBase<Real>& strain, GridBase<Real>& stress) const { constexpr auto dim = model_type_traits<type>::dimension; // Checking incompressibility auto incompressible = Loop::reduce<operation::plus>([](Real nu) -> UInt { return nu >= 0.5; }, this->template field<Real>("nu")); + auto valid_elasticity = + Loop::reduce<operation::plus>([](Real mu) -> UInt { return mu <= 0; }, + this->template field<Real>("mu")); + if (incompressible > 0) throw std::range_error{ TAMAAS_MSG("Incompressibility error, nu = 0.5 somewhere")}; + if (valid_elasticity > 0) + throw std::range_error{ + TAMAAS_MSG("Invalid elastic constants, mu <= 0 somewhere")}; + std::vector<influence::ElasticHelper<dim>> hookes; const auto& mu = this->template field<Real>("mu"); const auto& nu = this->template field<Real>("nu"); hookes.reserve(mu.getNbPoints()); std::transform(mu.begin(), mu.end(), nu.begin(), std::back_inserter(hookes), [](const Real& mu, const Real& nu) { return influence::ElasticHelper<dim>{mu, nu}; }); // Checking number of components if (strain.getNbComponents() == dim * dim) { Loop::loop( [](MatrixProxy<Real, dim, dim> stress, MatrixProxy<const Real, dim, dim> strain, const influence::ElasticHelper<dim>& elasticity) { stress = elasticity(strain); }, range<MatrixProxy<Real, dim, dim>>(stress), range<MatrixProxy<const Real, dim, dim>>(strain), hookes); } // in case we have voigt notation else if (strain.getNbComponents() == voigt_size<dim>::value) { Loop::loop( [](SymMatrixProxy<Real, dim> stress, SymMatrixProxy<const Real, dim> strain, const influence::ElasticHelper<dim>& elasticity) { stress = elasticity(strain); }, range<SymMatrixProxy<Real, dim>>(stress), range<SymMatrixProxy<const Real, dim>>(strain), hookes); } else throw std::invalid_argument{TAMAAS_MSG("Strain components (", strain.getNbComponents(), ") do not match model type ", type)}; } /* -------------------------------------------------------------------------- */ #define INSTANTIATE_HOOKE(r, _, type) \ template class Hooke<type>; \ template class HookeField<type>; BOOST_PP_SEQ_FOR_EACH(INSTANTIATE_HOOKE, ~, TAMAAS_MODEL_TYPES) #undef INSTANTIATE_HOOKE } // namespace tamaas