diff --git a/language_bindings/python/bind_py_material.cc b/language_bindings/python/bind_py_material.cc
index 667feda..0e09ef5 100644
--- a/language_bindings/python/bind_py_material.cc
+++ b/language_bindings/python/bind_py_material.cc
@@ -1,190 +1,252 @@
 /**
  * @file   bind_py_material.cc
  *
  * @author Till Junge <till.junge@epfl.ch>
  *
  * @date   09 Jan 2018
  *
  * @brief  python bindings for µSpectre's materials
  *
  * Copyright © 2018 Till Junge
  *
  * µSpectre is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License as
  * published by the Free Software Foundation, either version 3, or (at
  * your option) any later version.
  *
  * µSpectre 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
  * General Public License for more details.
  *
  * You should have received a copy of the GNU General Public License
  * along with GNU Emacs; see the file COPYING. If not, write to the
  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
  * Boston, MA 02111-1307, USA.
  */
 
 #include "common/common.hh"
 #include "materials/material_linear_elastic1.hh"
 #include "materials/material_linear_elastic2.hh"
 #include "materials/material_linear_elastic3.hh"
 #include "materials/material_linear_elastic4.hh"
+#include "materials/material_base.hh"
 #include "cell/cell_base.hh"
 
 #include <pybind11/pybind11.h>
 #include <pybind11/stl.h>
 #include <pybind11/eigen.h>
 
 #include <sstream>
 #include <string>
 
 using namespace muSpectre;
 namespace py = pybind11;
 using namespace pybind11::literals;
 
+
+
+template <Dim_t dim>
+void add_material_base_helper(py::module & mod) {
+  std::stringstream name_stream{};
+  name_stream << "MaterialBase" << dim << 'd';
+  const auto name {name_stream.str()};
+  using Mat_t = MaterialBase<dim, dim>;
+  py::class_<Mat_t>(mod, name.c_str());
+}
+
 /**
  * python binding for the optionally objective form of Hooke's law
  */
 template <Dim_t dim>
 void add_material_linear_elastic1_helper(py::module & mod) {
   std::stringstream name_stream{};
   name_stream << "MaterialLinearElastic1_" << dim << 'd';
   const auto name {name_stream.str()};
-
   using Mat_t = MaterialLinearElastic1<dim, dim>;
   using Sys_t = CellBase<dim, dim>;
-  py::class_<Mat_t>(mod, name.c_str())
+  using MatBase_t = MaterialBase<dim,dim>;
+  py::class_<Mat_t, MatBase_t>(mod, name.c_str())
      .def_static("make",
                 [](Sys_t & sys, std::string n, Real e, Real p) -> Mat_t & {
                   return Mat_t::make(sys, n, e, p);
                 },
                 "cell"_a, "name"_a, "Young"_a, "Poisson"_a,
                 py::return_value_policy::reference, py::keep_alive<1, 0>())
     .def("add_pixel",
          [] (Mat_t & mat, Ccoord_t<dim> pix) {
            mat.add_pixel(pix);},
          "pixel"_a)
     .def("add_pixel_split",
          [] (Mat_t & mat, Ccoord_t<dim> pix, Real ratio) {
            mat.add_pixel_split(pix, ratio);},
          "pixel"_a,
          "ratio"_a)
     .def("size", &Mat_t::size);
 }
 
 template <Dim_t dim>
 void add_material_linear_elastic2_helper(py::module & mod) {
   std::stringstream name_stream{};
   name_stream << "MaterialLinearElastic2_" << dim << 'd';
   const auto name {name_stream.str()};
 
   using Mat_t = MaterialLinearElastic2<dim, dim>;
   using Sys_t = CellBase<dim, dim>;
 
-  py::class_<Mat_t>(mod, name.c_str())
+  using MatBase_t = MaterialBase<dim,dim>;
+  py::class_<Mat_t, MatBase_t>(mod, name.c_str())
      .def_static("make",
                 [](Sys_t & sys, std::string n, Real e, Real p) -> Mat_t & {
                   return Mat_t::make(sys, n, e, p);
                 },
                 "cell"_a, "name"_a, "Young"_a, "Poisson"_a,
                 py::return_value_policy::reference, py::keep_alive<1, 0>())
     .def("add_pixel",
          [] (Mat_t & mat, Ccoord_t<dim> pix, py::EigenDRef<Eigen::ArrayXXd>& eig) {
            Eigen::Matrix<Real, dim, dim> eig_strain{eig};
            mat.add_pixel(pix, eig_strain);},
          "pixel"_a,
          "eigenstrain"_a)
     .def("add_pixel_split",
          [] (Mat_t & mat, Ccoord_t<dim> pix, Real ratio, py::EigenDRef<Eigen::ArrayXXd>& eig) {
            Eigen::Matrix<Real, dim, dim> eig_strain{eig};
            mat.add_pixel_split(pix, ratio, eig_strain);},
          "pixel"_a,
          "ratio"_a,
          "eigenstrain"_a)
     .def("size", &Mat_t::size);
 }
 
 
 template <Dim_t dim>
 void add_material_linear_elastic3_helper(py::module & mod) {
   std::stringstream name_stream{};
   name_stream << "MaterialLinearElastic3_" << dim << 'd';
   const auto name {name_stream.str()};
 
   using Mat_t = MaterialLinearElastic3<dim, dim>;
   using Sys_t = CellBase<dim, dim>;
 
-  py::class_<Mat_t>(mod, name.c_str())
+  using MatBase_t = MaterialBase<dim,dim>;
+  py::class_<Mat_t, MatBase_t>(mod, name.c_str())
     .def(py::init<std::string>(), "name"_a)
     .def_static("make",
                 [](Sys_t & sys, std::string n) -> Mat_t & {
                   return Mat_t::make(sys, n);
                 },
                 "cell"_a, "name"_a,
                 py::return_value_policy::reference, py::keep_alive<1, 0>())
     .def("add_pixel",
          [] (Mat_t & mat, Ccoord_t<dim> pix, Real Young, Real Poisson) {
 	   mat.add_pixel(pix, Young, Poisson);},
          "pixel"_a,
          "Young"_a,
          "Poisson"_a)
     .def("add_pixel_split",
          [] (Mat_t & mat, Ccoord_t<dim> pix, Real ratio, Real Young, Real Poisson) {
            mat.add_pixel_split(pix, ratio, Young, Poisson);},
          "pixel"_a,
          "ratio"_a,
          "Young"_a,
          "Poisson"_a)
 
     .def("size", &Mat_t::size);
 }
 
 template <Dim_t dim>
 void add_material_linear_elastic4_helper(py::module & mod) {
   std::stringstream name_stream{};
   name_stream << "MaterialLinearElastic4_" << dim << 'd';
   const auto name {name_stream.str()};
 
   using Mat_t = MaterialLinearElastic4<dim, dim>;
   using Sys_t = CellBase<dim, dim>;
 
   py::class_<Mat_t>(mod, name.c_str())
     .def(py::init<std::string>(), "name"_a)
     .def_static("make",
                 [](Sys_t & sys, std::string n) -> Mat_t & {
                   return Mat_t::make(sys, n);
                 },
                 "cell"_a, "name"_a,
                 py::return_value_policy::reference, py::keep_alive<1, 0>())
     .def("add_pixel",
          [] (Mat_t & mat, Ccoord_t<dim> pix, Real Young, Real Poisson) {
 	   mat.add_pixel(pix, Young, Poisson);},
          "pixel"_a,
          "Young"_a,
          "Poisson"_a)
     .def("add_pixel_split",
          [] (Mat_t & mat, Ccoord_t<dim> pix, Real ratio, Real Young, Real Poisson) {
            mat.add_pixel_split(pix, ratio, Young, Poisson);},
          "pixel"_a,
          "ratio"_a,
          "Young"_a,
          "Poisson"_a)
     .def("size", &Mat_t::size);
 }
-
+template <Dim_t Dim>
+class PyMaterialBase : public MaterialBase<Dim,  Dim>  {
+public:
+  /* Inherit the constructors */
+  using Parent = MaterialBase<Dim,  Dim>;
+  using Parent::Parent;
+
+  /* Trampoline (need one for each virtual function) */
+  void save_history_variables() override {
+    PYBIND11_OVERLOAD_PURE
+      (void, /* Return type */
+       Parent,      /* Parent class */
+       save_history_variables          /* Name of function in C++ (must match Python name) */
+       );
+  }
+
+  /* Trampoline (need one for each virtual function) */
+  void initialise() override {
+    PYBIND11_OVERLOAD_PURE
+      (void, /* Return type */
+       Parent,      /* Parent class */
+       initialise          /* Name of function in C++ (must match Python name) */
+       );
+  }
+  virtual void compute_stresses(const typename Parent::StrainField_t & F,
+                                typename Parent::StressField_t & P,
+                                Formulation form) override {
+    PYBIND11_OVERLOAD_PURE
+      (void, /* Return type */
+       Parent,      /* Parent class */
+       compute_stresses,          /* Name of function in C++ (must match Python name) */
+       F,P,form
+       );
+  }
+
+  virtual void compute_stresses_tangent(const typename Parent::StrainField_t & F,
+                                        typename Parent::StressField_t & P,
+                                        typename Parent::TangentField_t & K,
+                                        Formulation form) override {
+    PYBIND11_OVERLOAD_PURE
+      (void, /* Return type */
+       Parent,      /* Parent class */
+       compute_stresses_tangent,          /* Name of function in C++ (must match Python name) */
+       F,P,K, form
+       );
+  }
+
+};
 
 template <Dim_t dim>
 void add_material_helper(py::module & mod) {
+  add_material_base_helper<dim>(mod);
   add_material_linear_elastic1_helper<dim>(mod);
   add_material_linear_elastic2_helper<dim>(mod);
   add_material_linear_elastic3_helper<dim>(mod);
   add_material_linear_elastic4_helper<dim>(mod);
 }
 
 void add_material(py::module & mod) {
   auto material{mod.def_submodule("material")};
   material.doc() = "bindings for constitutive laws";
   add_material_helper<twoD  >(material);
   add_material_helper<threeD>(material);
 }
diff --git a/src/common/intersection_octree.hh b/src/common/intersection_octree.hh
index b9fac69..4465a54 100644
--- a/src/common/intersection_octree.hh
+++ b/src/common/intersection_octree.hh
@@ -1,145 +1,145 @@
 /**
  * @file   intersection_octree.hh
  *
  * @author Ali Falsafi <ali.falsafi@epfl.ch>
  *
  * @date   May 2018
  *
  * @brief  common operations on pixel addressing
  *
  * Copyright © 2018 Ali Falsafi
  *
  * µSpectre is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License as
  * published by the Free Software Foundation, either version 3, or (at
  * your option) any later version.
  *
  * µSpectre 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
  * General Public License for more details.
  *
  * You should have received a copy of the GNU General Public License
  * along with GNU Emacs; see the file COPYING. If not, write to the
  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
  * Boston, MA 02111-1307, USA.
  */
 
 
 #ifndef INTERSECTION_OCTREE_H
 #define INTERSECTION_OCTREE_H
 
 #include <vector>
 
 #include "common/ccoord_operations.hh"
 #include "common/common.hh"
 #include "cell/cell_base.hh"
 #include "materials/material_base.hh"
 #include "common/intersection_volume_calculator.hh"
 
 
 
 namespace muSpectre {
 
 
   template<Dim_t DimS>
   class RootNode;
 
   template<Dim_t DimS>
   class Node
   {
   public:
     using Rcoord = Rcoord_t<DimS>; //!< physical coordinates type
     using Ccoord = Ccoord_t<DimS>; //!< cell coordinates type
     using RootNode_t = RootNode<DimS>;
     //! Default constructor
     Node() = delete;
 
     // Construct by origin, lenghts, and depth
     Node(const Rcoord &new_origin, const Ccoord &new_lenghts,
          int depth, RootNode_t& root, bool is_root );
 
     // Construct by cell
     // Node(const CellBase<DimS, DimS>& cell, RootNode_t& root);
 
     //! Copy constructor
     Node(const Node &other) = delete;
 
   //! Move constructor
     Node(Node &&other) = default;
 
     //! Destructor
-    ~Node() = default;
+    virtual ~Node() = default;
 
     //This function checks the status of the node and orders its devision into
     //smaller nodes or asssign material to it
     virtual void check_node();
 
     //This function gives the ratio of the node which happens to be inside the precipitate
     //and assign materila to it if node is a pixel or divide it furhter if it is not
     void split_node(Real ratio);
 
     //this function constructs children of a node
     void divide_node();
 
   protected:
     ////////
     RootNode_t& root_node;
     Rcoord origin, Rlengths{};
     Ccoord Clengths{};
     int  depth;
     bool is_pixel;
     int  children_no;
     std::vector<Node> children{};
   };
 
 
 
   template<Dim_t DimS>
   class RootNode: public Node<DimS>
   {
     friend class Node<DimS>;
   public:
     using Rcoord = Rcoord_t<DimS>; //!< physical coordinates type
     using Ccoord = Ccoord_t<DimS>; //!< cell coordinates type
     using Parent = Node<DimS>; //!< base class
 
     //!Default Constructor
     RootNode() = delete ;
 
     //! Constructing a root node for a cell and a preticipate inside that cell
     RootNode(CellBase<DimS, DimS>& cell,
              std::vector<Rcoord> vert_precipitate);
 
     //! Copy constructor
     RootNode(const RootNode &other) = delete;
 
   //! Move constructor
     RootNode(RootNode &&other) = default;
 
     //! Destructor
     ~RootNode() = default;
 
     //returns the pixels which have intersection raio with the preipitate
     std::vector<Ccoord> get_intersected_pixels ();
 
     //return the intersection ratios of corresponding to the pixels returned by get_intersected_pixels()
     std::vector<Real> get_intersection_ratios ();
 
     //checking rootnode:
     void check_root_node();
 
   protected:
     CellBase<DimS, DimS>& cell;
     Rcoord cell_length, pixel_lengths;
     Ccoord cell_resolution;
     int max_resolution ;
     int max_depth;
     std::vector<Rcoord> precipitate_vertices{};
     std::vector<Ccoord> intersected_pixels{};
     std::vector<Real> intersection_ratios{};
   };
 
 } //muSpectre
 
 #endif /* INTERSECTION_OCTREE_H */
diff --git a/src/materials/material_muSpectre_base.hh b/src/materials/material_muSpectre_base.hh
index 932f2b8..2eb3036 100644
--- a/src/materials/material_muSpectre_base.hh
+++ b/src/materials/material_muSpectre_base.hh
@@ -1,911 +1,911 @@
 /**
  * @file   material_muSpectre_base.hh
  *
  * @author Till Junge <till.junge@epfl.ch>
  *
  * @date   25 Oct 2017
  *
  * @brief  Base class for materials written for µSpectre specifically. These
  *         can take full advantage of the configuration-change utilities of
  *         µSpectre. The user can inherit from them to define new constitutive
  *         laws and is merely required to provide the methods for computing the
  *         second Piola-Kirchhoff stress and Tangent. This class uses the
  *         "curiously recurring template parameter" to avoid virtual calls.
  *
  * Copyright © 2017 Till Junge
  *
  * µSpectre is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License as
  * published by the Free Software Foundation, either version 3, or (at
  * your option) any later version.
  *
  * µSpectre 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
  * General Public License for more details.
  *
  * You should have received a copy of the GNU General Public License
  * along with GNU Emacs; see the file COPYING. If not, write to the
  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
  * Boston, MA 02111-1307, USA.
  */
 
 #ifndef MATERIAL_MUSPECTRE_BASE_H
 #define MATERIAL_MUSPECTRE_BASE_H
 
 #include "common/common.hh"
 #include "materials/material_base.hh"
 #include "materials/materials_toolbox.hh"
 #include "common/field_collection.hh"
 #include "common/field.hh"
 #include "common//utilities.hh"
 
 #include <tuple>
 #include <type_traits>
 #include <iterator>
 #include <stdexcept>
 
 namespace muSpectre {
 
   // Forward declaration for factory function
   template <Dim_t DimS, Dim_t DimM>
   class CellBase;
 
   /**
    * material traits are used by `muSpectre::MaterialMuSpectre` to
    * break the circular dependence created by the curiously recurring
    * template parameter. These traits must define
    * - these `muSpectre::FieldMap`s:
    *   - `StrainMap_t`: typically a `muSpectre::MatrixFieldMap` for a
    *                    constant second-order `muSpectre::TensorField`
    *   - `StressMap_t`: typically a `muSpectre::MatrixFieldMap` for a
    *                    writable secord-order `muSpectre::TensorField`
    *   - `TangentMap_t`: typically a `muSpectre::T4MatrixFieldMap` for a
    *                     writable fourth-order `muSpectre::TensorField`
    * - `strain_measure`: the expected strain type (will be replaced by the
    *                     small-strain tensor ε
    *                     `muspectre::StrainMeasure::Infinitesimal` in small
    *                     strain computations)
    * - `stress_measure`: the measure of the returned stress. Is used by
    *                     `muspectre::MaterialMuSpectre` to transform it into
    *                     Cauchy stress (`muspectre::StressMeasure::Cauchy`) in
    *                     small-strain computations and into first
    *                     Piola-Kirchhoff stress `muspectre::StressMeasure::PK1`
    *                     in finite-strain computations
    * - `InternalVariables`: a tuple of `muSpectre::FieldMap`s containing
    *                        internal variables
    */
   template <class Material>
   struct MaterialMuSpectre_traits {
 
   };
 
   template <class Material, Dim_t DimS, Dim_t DimM>
   class MaterialMuSpectre;
 
   /**
    * Base class for most convenient implementation of materials
    */
   template <class Material, Dim_t DimS, Dim_t DimM>
   class MaterialMuSpectre: public MaterialBase<DimS, DimM>
   {
   public:
     /**
      * type used to determine whether the
      * `muSpectre::MaterialMuSpectre::iterable_proxy evaluate only
      * stresses or also tangent stiffnesses
      */
     using NeedTangent = MatTB::NeedTangent;
     using Parent = MaterialBase<DimS, DimM>; //!< base class
     //! global field collection
     using GFieldCollection_t = typename Parent::GFieldCollection_t;
     //! expected type for stress fields
     using StressField_t = typename Parent::StressField_t;
     //! expected type for strain fields
     using StrainField_t = typename Parent::StrainField_t;
     //! expected type for tangent stiffness fields
     using TangentField_t = typename Parent::TangentField_t;
     using Ccoord = Ccoord_t<DimS>; //!< cell coordinates type
     //! traits for the CRTP subclass
     using traits = MaterialMuSpectre_traits<Material>;
 
     //! Default constructor
     MaterialMuSpectre() = delete;
 
     //! Construct by name
     MaterialMuSpectre(std::string name);
 
     //! Copy constructor
     MaterialMuSpectre(const MaterialMuSpectre &other) = delete;
 
     //! Move constructor
     MaterialMuSpectre(MaterialMuSpectre &&other) = delete;
 
     //! Destructor
     virtual ~MaterialMuSpectre() = default;
 
     //! Factory
     template <class... ConstructorArgs>
     static Material & make(CellBase<DimS, DimM> & cell,
                            ConstructorArgs &&... args);
 
     //! Copy assignment operator
     MaterialMuSpectre& operator=(const MaterialMuSpectre &other) = delete;
 
     //! Move assignment operator
     MaterialMuSpectre& operator=(MaterialMuSpectre &&other) = delete;
 
 
     //! allocate memory, etc
     virtual void initialise() override;
 
     // this fucntion is speicalized to assign partial material to a pixel
     //void add_pixel_split(const Ccoord & local_ccoord, Real ratio = 1.0);
     template<class ...InternalArgs>
     inline void add_pixel_split(const Ccoord_t<DimS> & pixel,
                                 Real ratio,
                                 InternalArgs ... args);
 
     inline void add_pixel_split(const Ccoord_t<DimS> & pixel,
-                                Real ratio);
+                                Real ratio) override;
 
 
 
     void add_split_pixels_precipitate(std::vector<Ccoord_t<DimS>> intersected_precipitate,
                                       std::vector<Real> intersection_ratios);
     //! computes stress
     using Parent::compute_stresses;
     using Parent::compute_stresses_tangent;
     virtual void compute_stresses(const StrainField_t & F,
                                   StressField_t & P,
                                   Formulation form,
                                   SplittedCell is_cell_splitted) override;
     //! computes stress and tangent modulus
     virtual void compute_stresses_tangent(const StrainField_t & F,
                                           StressField_t & P,
                                           TangentField_t & K,
                                           Formulation form,
                                           SplittedCell is_cell_splitted)override;
 
   protected:
     //! computes stress with the formulation available at compile time
     //! __attribute__ required by g++-6 and g++-7 because of this bug:
     //! https://gcc.gnu.org/bugzilla/show_bug.cgi?id=80947
     template <Formulation Form, SplittedCell is_cell_splitted>
     inline void compute_stresses_worker(const StrainField_t & F,
                                         StressField_t & P)
       __attribute__ ((visibility ("default")));
 
     //! computes stress with the formulation available at compile time
     //! __attribute__ required by g++-6 and g++-7 because of this bug:
     //! https://gcc.gnu.org/bugzilla/show_bug.cgi?id=80947
     template <Formulation Form, SplittedCell is_cell_splitted>
     inline void compute_stresses_worker(const StrainField_t & F,
                                         StressField_t & P,
                                         TangentField_t & K)
       __attribute__ ((visibility ("default")));
     //! this iterable class is a default for simple laws that just take a strain
     //! the iterable is just a templated wrapper to provide a range to iterate over
     //! that does or does not include tangent moduli
     template<NeedTangent need_tgt = NeedTangent::no>
     class iterable_proxy;
 
     /**
      * inheriting classes with internal variables need to overload this function
      */
     typename traits::InternalVariables& get_internals() {
       return static_cast<Material&>(*this).get_internals();}
 
     bool is_initialised{false}; //!< to handle double initialisation right
 
   private:
   };
 
   /* ---------------------------------------------------------------------- */
   template <class Material, Dim_t DimS, Dim_t DimM>
   MaterialMuSpectre<Material, DimS, DimM>::
   MaterialMuSpectre(std::string name)
     :Parent(name){
     using stress_compatible = typename traits::StressMap_t::
       template is_compatible<StressField_t>;
     using strain_compatible = typename traits::StrainMap_t::
       template is_compatible<StrainField_t>;
     using tangent_compatible = typename traits::TangentMap_t::
       template is_compatible<TangentField_t>;
 
     static_assert((stress_compatible::value &&
                    stress_compatible::explain()),
                   "The material's declared stress map is not compatible "
                   "with the stress field. More info in previously shown "
                   "assert.");
 
     static_assert((strain_compatible::value &&
                    strain_compatible::explain()),
                   "The material's declared strain map is not compatible "
                   "with the strain field. More info in previously shown "
                   "assert.");
 
     static_assert((tangent_compatible::value &&
                    tangent_compatible::explain()),
                   "The material's declared tangent map is not compatible "
                   "with the tangent field. More info in previously shown "
                   "assert.");
   }
 
 
   /* ---------------------------------------------------------------------- */
   template <class Material, Dim_t DimS, Dim_t DimM>
   template <class... ConstructorArgs>
   Material & MaterialMuSpectre<Material, DimS, DimM>::
   make(CellBase<DimS, DimM> & cell,
                   ConstructorArgs && ... args) {
     auto mat = std::make_unique<Material>(args...);
     auto & mat_ref = *mat;
     cell.add_material(std::move(mat));
     return mat_ref;
   }
   /* ---------------------------------------------------------------------- */
   template <class Material, Dim_t DimS, Dim_t DimM>
   void MaterialMuSpectre<Material, DimS, DimM>::
   add_pixel_split(const Ccoord &local_ccoord, Real ratio) {
     auto & this_mat = static_cast<Material&>(*this);
     this_mat.add_pixel(local_ccoord);
     this->assigned_ratio.push_back(ratio);
   }
   /* ---------------------------------------------------------------------- */
   template <class Material, Dim_t DimS, Dim_t DimM>
   template<class ...InternalArgs>
   void MaterialMuSpectre<Material, DimS, DimM>::
   add_pixel_split(const Ccoord_t<DimS> & pixel,
                   Real ratio,
                   InternalArgs ... args){
     auto & this_mat = static_cast<Material&>(*this);
     this_mat.add_pixel(pixel, args...);
     this->assigned_ratio.push_back(ratio);
   }
   /* ---------------------------------------------------------------------- */
   template <class Material, Dim_t DimS, Dim_t DimM>
   void MaterialMuSpectre<Material, DimS, DimM>::
   add_split_pixels_precipitate(std::vector<Ccoord_t<DimS>> intersected_precipitate,
                                     std::vector<Real> intersection_ratios){
     //assign precipitate materials:
     for (auto && tup: akantu::zip(intersected_precipitate, intersection_ratios) ){
       auto pix = std::get<0> (tup);
       auto ratio = std::get<1> (tup);
       this->add_pixel_split(pix,ratio);
     }
   }
   /* ---------------------------------------------------------------------- */
   template <class Material, Dim_t DimS, Dim_t DimM>
   void MaterialMuSpectre<Material, DimS, DimM>::
   initialise() {
     if (!this->is_initialised) {
       this->internal_fields.initialise();
       this->is_initialised = true;
     }
   }
 
   /* ---------------------------------------------------------------------- */
   template <class Material, Dim_t DimS, Dim_t DimM>
   void MaterialMuSpectre<Material, DimS, DimM>::
   compute_stresses(const StrainField_t &F, StressField_t &P,
                    Formulation form, SplittedCell is_cell_splitted) {
     switch (form) {
     case Formulation::finite_strain: {
       switch (is_cell_splitted){
       case (SplittedCell::no): {
         this->compute_stresses_worker<Formulation::finite_strain, SplittedCell::no>(F, P);
         break;
       }
       case (SplittedCell::yes): {
         this->compute_stresses_worker<Formulation::finite_strain, SplittedCell::yes>(F, P);
         break;
       }
       }
       break;
     }
     case Formulation::small_strain: {
       switch (is_cell_splitted){
       case (SplittedCell::no): {
         this->compute_stresses_worker<Formulation::small_strain, SplittedCell::no>(F, P);
         break;
       }
       case (SplittedCell::yes): {
         this->compute_stresses_worker<Formulation::small_strain, SplittedCell::yes>(F, P);
         break;
       }
       }
       break;
     }
     default:
       throw std::runtime_error("Unknown formulation");
       break;
     }
   }
 
   /* ---------------------------------------------------------------------- */
   template <class Material, Dim_t DimS, Dim_t DimM>
   void MaterialMuSpectre<Material, DimS, DimM>::
   compute_stresses_tangent(const StrainField_t & F, StressField_t & P,
                            TangentField_t & K,
                            Formulation form, SplittedCell is_cell_splitted) {
     switch (form) {
     case Formulation::finite_strain: {
       switch (is_cell_splitted){
       case (SplittedCell::no): {
         this->compute_stresses_worker<Formulation::finite_strain, SplittedCell::no>(F, P, K);
         break;
       }
       case (SplittedCell::yes): {
         this->compute_stresses_worker<Formulation::finite_strain, SplittedCell::yes>(F, P, K);
         break;
       }
       }
       break;
     }
     case Formulation::small_strain: {
       switch (is_cell_splitted){
       case (SplittedCell::no): {
         this->compute_stresses_worker<Formulation::small_strain, SplittedCell::no>(F, P, K);
         break;
       }
       case (SplittedCell::yes): {
         this->compute_stresses_worker<Formulation::small_strain, SplittedCell::yes>(F, P, K);
         break;
       }
       }
       break;
     }
     default:
       throw std::runtime_error("Unknown formulation");
       break;
     }
   }
 
   /* ---------------------------------------------------------------------- */
   template <class Material, Dim_t DimS, Dim_t DimM>
   template <Formulation Form, SplittedCell is_cell_splitted>
   void MaterialMuSpectre<Material, DimS, DimM>::
   compute_stresses_worker(const StrainField_t & F,
                           StressField_t & P,
                           TangentField_t & K){
 
     /* These lambdas are executed for every integration point.
 
        F contains the transformation gradient for finite strain calculations and
        the infinitesimal strain tensor in small strain problems
 
        The internal_variables tuple contains whatever internal variables
        Material declared (e.g., eigenstrain, strain rate, etc.)
     */
     using Strains_t = std::tuple<typename traits::StrainMap_t::reference>;
     using Stresses_t = std::tuple<typename traits::StressMap_t::reference,
                                   typename traits::TangentMap_t::reference>;
     auto constitutive_law_small_strain = [this]
       (Strains_t Strains, Stresses_t Stresses, const Real & ratio, auto && internal_variables) {
       constexpr StrainMeasure stored_strain_m{get_stored_strain_type(Form)};
       constexpr StrainMeasure expected_strain_m{
         get_formulation_strain_type(Form, traits::strain_measure)};
       auto & this_mat = static_cast<Material&>(*this);
 
       // Transformation gradient is first in the strains tuple
       auto & grad = std::get<0>(Strains);
       auto && strain = MatTB::convert_strain<stored_strain_m, expected_strain_m>(grad);
       // return value contains a tuple of rvalue_refs to both stress and tangent moduli
 
       // for the case that cells do not contain any splitt cells
       auto non_split_pixel = [&strain, &this_mat, ratio, &Stresses, &internal_variables](){
         Stresses =
         apply([&strain, &this_mat] (auto && ... internals) {
             return
             this_mat.evaluate_stress_tangent(std::move(strain),
                                              internals...);},
           internal_variables);
       };
 
       // for the case that cells contain splitt cells
       auto split_pixel = [&strain, &this_mat, ratio, &Stresses, &internal_variables](){
         auto stress_tgt_contributions =
         apply([&strain, &this_mat] (auto && ... internals) {
             return
             this_mat.evaluate_stress_tangent(std::move(strain),
                                              internals...);},
           internal_variables);
         auto && stress   = std::get<0>(Stresses);
         auto && tangent  = std::get<1>(Stresses);
         stress  += ratio * std::get<0>(stress_tgt_contributions);
         tangent += ratio * std::get<1>(stress_tgt_contributions);
       };
 
       switch (is_cell_splitted){
       case  SplittedCell::no : {
         non_split_pixel();
         break;
       }
       case SplittedCell::yes : {
         split_pixel();
         break;
       }
       }
     };
 
     auto constitutive_law_finite_strain = [this]
       (Strains_t Strains, Stresses_t Stresses, const Real & ratio, auto && internal_variables) {
       constexpr StrainMeasure stored_strain_m{get_stored_strain_type(Form)};
       constexpr StrainMeasure expected_strain_m{
       get_formulation_strain_type(Form, traits::strain_measure)};
       auto & this_mat = static_cast<Material&>(*this);
 
       // Transformation gradient is first in the strains tuple
       auto & grad = std::get<0>(Strains);
       auto && strain = MatTB::convert_strain<stored_strain_m, expected_strain_m>(grad);
 
       // return value contains a tuple of rvalue_refs to both stress
       // and tangent moduli
 
       // for the case that cells do not contain splitt cells
       auto non_split_pixel = [&strain, &this_mat, ratio, &Stresses, &internal_variables, &grad](){
         auto stress_tgt =
         apply([&strain, &this_mat] (auto && ... internals) {
             return
             this_mat.evaluate_stress_tangent(std::move(strain),
                                              internals...);},
           internal_variables);
         Stresses = MatTB::PK1_stress<traits::stress_measure, traits::strain_measure>
         (std::move(grad),
          std::move(std::get<0>(stress_tgt)),
          std::move( std::get<1>(stress_tgt)));
       };
 
       // for the case that cells contain splitt cells
       auto split_pixel = [&strain, &this_mat, ratio, &Stresses, &internal_variables, &grad](){
         auto stress_tgt =
         apply([&strain, &this_mat] (auto && ... internals) {
             return
             this_mat.evaluate_stress_tangent(std::move(strain),
                                              internals...);},
           internal_variables);
         auto && stress_tgt_contributions = MatTB::PK1_stress<traits::stress_measure, traits::strain_measure>
         (std::move(grad),
          std::move(std::get<0>(stress_tgt)),
          std::move(std::get<1>(stress_tgt)));
         auto && stress   = std::get<0>(Stresses);
         auto && tangent  = std::get<1>(Stresses);
         stress  += ratio * std::get<0>(stress_tgt_contributions);
         tangent += ratio * std::get<1>(stress_tgt_contributions);
       };
 
       switch (is_cell_splitted){
       case  SplittedCell::no : {
         non_split_pixel();
         break;
       }
       case SplittedCell::yes : {
         split_pixel();
         break;
       }
       }
     };
 
     iterable_proxy<NeedTangent::yes> fields{*this, F, P, K};
     for (auto && arglist: fields) {
       /**
        * arglist is a tuple of three tuples containing only Lvalue
        * references (see value_tye in the class definition of
        * iterable_proxy::iterator). Tuples contain strains, stresses
        * and internal variables, respectively,
        */
 
       //auto && stress_tgt = std::get<0>(tuples);
       //auto && inputs = std::get<1>(tuples);TODO:clean this
       static_assert(std::is_same<typename traits::StrainMap_t::reference,
                     std::remove_reference_t<
                     decltype(std::get<0>(std::get<0>(arglist)))>>::value,
                     "Type mismatch for strain reference, check iterator "
                     "value_type");
       static_assert(std::is_same<typename traits::StressMap_t::reference,
                     std::remove_reference_t<
                     decltype(std::get<0>(std::get<1>(arglist)))>>::value,
                     "Type mismatch for stress reference, check iterator"
                     "value_type");
       static_assert(std::is_same<typename traits::TangentMap_t::reference,
                     std::remove_reference_t<
                     decltype(std::get<1>(std::get<1>(arglist)))>>::value,
                     "Type mismatch for tangent reference, check iterator"
                     "value_type");
       static_assert(std::is_same<Real,
                     std::remove_reference_t<
                     decltype(std::get<2>(arglist))>>::value,
                     "Type mismatch for ratio reference, expected a real number");
 
       switch (Form) {
       case Formulation::small_strain: {
         apply(constitutive_law_small_strain, std::move(arglist));
         break;
       }
       case Formulation::finite_strain: {
         apply(constitutive_law_finite_strain, std::move(arglist));
         break;
       }
       }
     }
   }
 
 
   /* ---------------------------------------------------------------------- */
   template <class Material, Dim_t DimS, Dim_t DimM>
   template <Formulation Form, SplittedCell is_cell_splitted>
   void MaterialMuSpectre<Material, DimS, DimM>::
   compute_stresses_worker(const StrainField_t & F,
                           StressField_t & P){
 
     /* These lambdas are executed for every integration point.
 
        F contains the transformation gradient for finite strain calculations and
        the infinitesimal strain tensor in small strain problems
 
        The internal_variables tuple contains whatever internal variables
        Material declared (e.g., eigenstrain, strain rate, etc.)
     */
 
     using Strains_t = std::tuple<typename traits::StrainMap_t::reference>;
     using Stresses_t = std::tuple<typename traits::StressMap_t::reference>;
     auto constitutive_law_small_strain = [this]
       (Strains_t Strains, Stresses_t Stresses,const  Real & ratio, auto && internal_variables) {
       constexpr StrainMeasure stored_strain_m{get_stored_strain_type(Form)};
       constexpr StrainMeasure expected_strain_m{
       get_formulation_strain_type(Form, traits::strain_measure)};
 
       auto & this_mat = static_cast<Material&>(*this);
 
       // Transformation gradient is first in the strains tuple
       auto & grad = std::get<0>(Strains);
       auto && strain = MatTB::convert_strain<stored_strain_m, expected_strain_m>(grad);
       // return value contains a tuple of rvalue_refs to both stress and tangent moduli
       auto & sigma = std::get<0>(Stresses);
 
       //for the case that cell does not contain any splitted pixel
       auto non_split_pixel = [&strain, &this_mat,ratio, &sigma, &internal_variables](){
       sigma =
       apply([&strain, &this_mat] (auto && ... internals) {
           return
           this_mat.evaluate_stress(std::move(strain),
                                            internals...);},
         internal_variables);
       };
 
       // for the case that cells contain splitt cells
       auto split_pixel = [&strain, &this_mat, &ratio, &sigma, &internal_variables](){
       sigma += ratio *
       apply([&strain, &this_mat] (auto && ... internals) {
           return
           this_mat.evaluate_stress(std::move(strain),
                                            internals...);},
         internal_variables);
       };
 
       switch (is_cell_splitted){
       case  SplittedCell::no : {
         non_split_pixel();
         break;
       }
       case SplittedCell::yes : {
         split_pixel();
         break;
       }
       }
     };
 
     auto constitutive_law_finite_strain = [this]
       (Strains_t Strains, Stresses_t && Stresses,const Real & ratio, auto && internal_variables) {
       constexpr StrainMeasure stored_strain_m{get_stored_strain_type(Form)};
       constexpr StrainMeasure expected_strain_m{
       get_formulation_strain_type(Form, traits::strain_measure)};
       auto & this_mat = static_cast<Material&>(*this);
 
       // Transformation gradient is first in the strains tuple
       auto & grad = std::get<0>(Strains);
       auto && strain = MatTB::convert_strain<stored_strain_m, expected_strain_m>(grad);
 
       // TODO: Figure this out: I can't std::move(internals...),
       // because if there are no internals, compilation fails with "no
       // matching function for call to ‘move()’'. These are tuples of
       // lvalue references, so it shouldn't be too bad, but still
       // irksome.
 
       //for the case that cell does not contain any splitted pixel
       auto non_split_pixel = [ &strain, &this_mat, &ratio, &Stresses, &internal_variables, &grad] (){
       auto stress =
       apply([&strain, &this_mat] (auto && ... internals) {
           return
           this_mat.evaluate_stress(std::move(strain),
                                            internals...);},
         internal_variables);
       auto & P = get<0>(Stresses);
       P = MatTB::PK1_stress<traits::stress_measure, traits::strain_measure>
       (grad, stress);
       };
 
       // for the case that cells contain splitted cells
       auto split_pixel = [&strain, &this_mat, ratio, &Stresses, internal_variables, &grad](){
       auto  stress =
       apply([&strain, &this_mat] (auto && ... internals) {
           return
           this_mat.evaluate_stress(std::move(strain),
                                            internals...);},
         internal_variables);
 
       auto && P = get<0>(Stresses);
       P += ratio * MatTB::PK1_stress<traits::stress_measure, traits::strain_measure>
       (grad, stress);
       };
 
       switch (is_cell_splitted){
       case  SplittedCell::no : {
         non_split_pixel();
         break;
       }
       case SplittedCell::yes : {
         split_pixel();
         break;
       }
       }
     };
 
     iterable_proxy<NeedTangent::no> fields{*this, F, P};
 
     for (auto && arglist: fields) {
       /**
        * arglist is a tuple of three tuples containing only Lvalue
        * references (see value_type in the class definition of
        * iterable_proxy::iterator). Tuples contain strains, stresses
        * and internal variables, respectively,
        */
 
       //auto && stress_tgt = std::get<0>(tuples);
       //auto && inputs = std::get<1>(tuples);TODO:clean this
       static_assert(std::is_same<typename traits::StrainMap_t::reference,
                     std::remove_reference_t<
                     decltype(std::get<0>(std::get<0>(arglist)))>>::value,
                     "Type mismatch for strain reference, check iterator "
                     "value_type");
       static_assert(std::is_same<typename traits::StressMap_t::reference,
                     std::remove_reference_t<
                     decltype(std::get<0>(std::get<1>(arglist)))>>::value,
                     "Type mismatch for stress reference, check iterator"
                     "value_type");
       static_assert(std::is_same<Real,
                     std::remove_reference_t<
                     decltype(std::get<2>(arglist))>>::value,
                     "Type mismatch for ratio reference, expected a real number");
 
       switch (Form) {
       case Formulation::small_strain: {
         apply(constitutive_law_small_strain, std::move(arglist));
         break;
       }
       case Formulation::finite_strain: {
         apply(constitutive_law_finite_strain, std::move(arglist));
         break;
       }
       }
     }
   }
 
 
   /* ---------------------------------------------------------------------- */
   //! this iterator class is a default for simple laws that just take a strain
   template <class Material, Dim_t DimS, Dim_t DimM>
   template <MatTB::NeedTangent NeedTgt>
   class MaterialMuSpectre<Material, DimS, DimM>::iterable_proxy {
   public:
     //! Default constructor
     iterable_proxy() = delete;
     /**
      * type used to determine whether the
      * `muSpectre::MaterialMuSpectre::iterable_proxy` evaluate only
      * stresses or also tangent stiffnesses
      */
     using NeedTangent =
       typename MaterialMuSpectre<Material, DimS, DimM>::NeedTangent;
     /** Iterator uses the material's internal variables field
         collection to iterate selectively over the global fields
         (such as the transformation gradient F and first
         Piola-Kirchhoff stress P.
     **/
     template<bool DoNeedTgt=(NeedTgt == NeedTangent::yes)>
     iterable_proxy(MaterialMuSpectre & mat,
                    const StrainField_t & F,
                    StressField_t & P,
                    std::enable_if_t<DoNeedTgt, TangentField_t> & K)
       :material{mat}, strain_field{F}, stress_tup{P,K},
        internals{material.get_internals()}{};
 
     /** Iterator uses the material's internal variables field
         collection to iterate selectively over the global fields
         (such as the transformation gradient F and first
         Piola-Kirchhoff stress P.
     **/
     template<bool DontNeedTgt=(NeedTgt == NeedTangent::no)>
     iterable_proxy(MaterialMuSpectre & mat,
                    const StrainField_t & F,
                    std::enable_if_t<DontNeedTgt, StressField_t> & P)
       :material{mat}, strain_field{F}, stress_tup{P},
        internals{material.get_internals()}{};
 
     //! Expected type for strain fields
     using StrainMap_t = typename traits::StrainMap_t;
     //! Expected type for stress fields
     using StressMap_t = typename traits::StressMap_t;
     //! Expected type for tangent stiffness fields
     using TangentMap_t = typename traits::TangentMap_t;
     //! expected type for strain values
     using Strain_t = typename traits::StrainMap_t::reference;
     //! expected type for stress values
     using Stress_t = typename traits::StressMap_t::reference;
     //! expected type for tangent stiffness values
     using Tangent_t = typename traits::TangentMap_t::reference;
 
     //! tuple of intervnal variables, depends on the material
     using InternalVariables = typename traits::InternalVariables;
     //! tuple containing a stress and possibly a tangent stiffness field
     using StressFieldTup = std::conditional_t
       <(NeedTgt == NeedTangent::yes),
        std::tuple<StressField_t&, TangentField_t&>,
        std::tuple<StressField_t&>>;
     //! tuple containing a stress and possibly a tangent stiffness field map
     using StressMapTup = std::conditional_t
       <(NeedTgt == NeedTangent::yes),
        std::tuple<StressMap_t, TangentMap_t>,
        std::tuple<StressMap_t>>;
     //! tuple containing a stress and possibly a tangent stiffness value ref
     using Stress_tTup = std::conditional_t<(NeedTgt == NeedTangent::yes),
                                            std::tuple<Stress_t, Tangent_t>,
                                            std::tuple<Stress_t>>;
 
 
     //! Copy constructor
     iterable_proxy(const iterable_proxy &other) = default;
 
     //! Move constructor
     iterable_proxy(iterable_proxy &&other) = default;
 
     //! Destructor
     virtual ~iterable_proxy() = default;
 
     //! Copy assignment operator
     iterable_proxy& operator=(const iterable_proxy &other) = default;
 
     //! Move assignment operator
     iterable_proxy& operator=(iterable_proxy &&other) = default;
 
     /**
      * dereferences into a tuple containing strains, and internal
      * variables, as well as maps to the stress and potentially
      * stiffness maps where to write the response of a pixel
      */
     class iterator
     {
     public:
       //! type to refer to internal variables owned by a CRTP material
       using InternalReferences = MatTB::ReferenceTuple_t<InternalVariables>;
       //! return type to be unpacked per pixel my the constitutive law
       using value_type =
         std::tuple<std::tuple<Strain_t>, Stress_tTup, Real, InternalReferences>;
       using iterator_category = std::forward_iterator_tag; //!< stl conformance
 
       //! Default constructor
       iterator() = delete;
 
       /** Iterator uses the material's internal variables field
           collection to iterate selectively over the global fields
           (such as the transformation gradient F and first
           Piola-Kirchhoff stress P.
       **/
       iterator(const iterable_proxy & it, bool begin = true)
         : it{it}, strain_map{it.strain_field},
           stress_map {it.stress_tup},
           index{begin ? 0:it.material.internal_fields.size()}{}
 
 
       //! Copy constructor
       iterator(const iterator &other) = default;
 
       //! Move constructor
       iterator(iterator &&other) = default;
 
       //! Destructor
       virtual ~iterator() = default;
 
       //! Copy assignment operator
       iterator& operator=(const iterator &other) = default;
 
       //! Move assignment operator
       iterator& operator=(iterator &&other) = default;
 
       //! pre-increment
       inline iterator & operator++();
       //! dereference
       inline value_type operator*();
       //! inequality
       inline bool operator!=(const iterator & other) const;
 
 
     protected:
       const iterable_proxy & it; //!< ref to the proxy
       StrainMap_t strain_map;    //!< map onto the global strain field
       //! map onto the global stress field and possibly tangent stiffness
       StressMapTup stress_map;
       size_t index; //!< index or pixel currently referred to
     private:
     };
 
     //! returns iterator to first pixel if this material
     iterator begin() {return std::move(iterator(*this));}
     //! returns iterator past the last pixel in this material
     iterator end() {return std::move(iterator(*this, false));}
 
   protected:
     MaterialMuSpectre & material; //!< reference to the proxied material
     const StrainField_t & strain_field; //!< cell's global strain field
     //! references to the global stress field and perhaps tangent stiffness
     StressFieldTup stress_tup;
     //! references to the internal variables
     InternalVariables & internals;
 
   private:
   };
 
   /* ---------------------------------------------------------------------- */
   template <class Material, Dim_t DimS, Dim_t DimM>
   template <MatTB::NeedTangent NeedTgt>
   bool
   MaterialMuSpectre<Material, DimS, DimM>::iterable_proxy<NeedTgt>::iterator::
   operator!=(const iterator & other) const {
     return (this->index != other.index);
   }
 
   /* ---------------------------------------------------------------------- */
   template <class Material, Dim_t DimS, Dim_t DimM>
   template <MatTB::NeedTangent NeedTgt>
   typename MaterialMuSpectre<Material, DimS, DimM>::
   template iterable_proxy<NeedTgt>::
   iterator &
   MaterialMuSpectre<Material, DimS, DimM>::iterable_proxy<NeedTgt>::iterator::
   operator++() {
     this->index++;
     return *this;
   }
 
   /* ---------------------------------------------------------------------- */
   template <class Material, Dim_t DimS, Dim_t DimM>
   template <MatTB::NeedTangent NeedTgT>
   typename MaterialMuSpectre<Material, DimS, DimM>::
   template iterable_proxy<NeedTgT>::iterator::
   value_type
   MaterialMuSpectre<Material, DimS, DimM>::iterable_proxy<NeedTgT>::iterator::
   operator*() {
 
     const Ccoord_t<DimS> pixel{
       this->it.material.internal_fields.get_ccoord(this->index)};
     auto && strain = std::make_tuple(this->strain_map[pixel]);
     auto && ratio  = this->it.material.get_assigned_ratio(pixel);
     auto && stresses =
       apply([&pixel] (auto && ... stress_tgt) {
           return std::make_tuple(stress_tgt[pixel]...);},
         this->stress_map);
     auto && internal = this->it.material.get_internals();
     const auto id{this->index};
     auto && internals =
       apply([id] (auto && ... internals_) {
           return InternalReferences{internals_[id]...};},
         internal);
     return std::make_tuple(std::move(strain),
                            std::move(stresses),
                            std::move(ratio),
                            std::move(internals));
   }
 }  // muSpectre
 
 
 #endif /* MATERIAL_MUSPECTRE_BASE_H */