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