diff --git a/src/common.hpp b/src/common.hpp
index b264956..7f3ad39 100644
--- a/src/common.hpp
+++ b/src/common.hpp
@@ -1,65 +1,94 @@
+/*-------------------------------------------------------
+
+Copyright (c) 2014,2015 Fabien Georget <fabieng@princeton.edu>, Princeton University
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+    * Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+    * Redistributions in binary form must reproduce the above copyright
+      notice, this list of conditions and the following disclaimer in the
+      documentation and/or other materials provided with the distribution.
+    * Neither the name of the Princeton University nor the
+      names of its contributors may be used to endorse or promote products
+      derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+---------------------------------------------------------*/
+
 #ifndef SPECMICP_COMMON_HPP
 #define SPECMICP_COMMON_HPP
 
 #include "boost/range/irange.hpp"
 
 namespace specmicp {
 
 //! type of an index
 using index_t = std::ptrdiff_t;
 using uindex_t = std::size_t;
 }
 #define EIGEN_DEFAULT_DENSE_INDEX_TYPE specmicp::index_t
 
 #include <Eigen/Core>
 
 namespace specmicp {
 //! type of a scalar
 using scalar_t = double;
 
 // linear algebra
 //! A vector
 using Vector = Eigen::Matrix<scalar_t, Eigen::Dynamic, 1>;
 //! A matrix
 using Matrix = Eigen::Matrix<scalar_t, Eigen::Dynamic, Eigen::Dynamic>;
 
 //! \brief Range
 //!
 //! used to access all species of a certain types
 using range_t = boost::iterator_range<boost::range_detail::integer_iterator<index_t>>;
 
 
 // constants
 
 //! Id of an equation that is not an equation
 const index_t no_equation = -1;
 //! Id of a non-existant species
 const index_t no_species = -1;
 
 //! Precision used to compute jacobian
 const scalar_t eps_jacobian = 1e-8;
 
 } // namespace specmicp
 
 
 // macros
 // ------
 
 #ifdef NDEBUG
 constexpr bool ndebug { false };
 #else
 constexpr bool ndebug { true };
 #endif
 
 #define NOEXCEPT noexcept(ndebug)
 
 #ifdef SPECMICP_NO_DEBUG
 #define specmicp_assert
 #else
 #define specmicp_assert(x) assert(x)
 #endif // SPECMICP_NO_DEBUG
 
 
 
 #endif // SPECMICP_COMMON_HPP
 
diff --git a/src/database.hpp b/src/database.hpp
index 0b7a0cb..1b0f991 100644
--- a/src/database.hpp
+++ b/src/database.hpp
@@ -1,13 +1,42 @@
+/*-------------------------------------------------------
+
+Copyright (c) 2014,2015 Fabien Georget <fabieng@princeton.edu>, Princeton University
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+    * Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+    * Redistributions in binary form must reproduce the above copyright
+      notice, this list of conditions and the following disclaimer in the
+      documentation and/or other materials provided with the distribution.
+    * Neither the name of the Princeton University nor the
+      names of its contributors may be used to endorse or promote products
+      derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+---------------------------------------------------------*/
+
 #ifndef SPECMICP_DATABASE_HPP
 #define SPECMICP_DATABASE_HPP
 
 #ifndef SPECMICP_DATABASE_DATACONTAINER_HPP
 #include "database/data_container.hpp"
 #endif
 
 namespace specmicp
 {
     using RawDatabasePtr = database::RawDatabasePtr;
 }
 
 #endif // SPECMICP_DATABASE_HPP
diff --git a/src/dfpm/1dtransport/diffusion.cpp b/src/dfpm/1dtransport/diffusion.cpp
index aedac2f..0f0bd11 100644
--- a/src/dfpm/1dtransport/diffusion.cpp
+++ b/src/dfpm/1dtransport/diffusion.cpp
@@ -1,194 +1,223 @@
+/*-------------------------------------------------------
+
+Copyright (c) 2014,2015 Fabien Georget <fabieng@princeton.edu>, Princeton University
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+    * Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+    * Redistributions in binary form must reproduce the above copyright
+      notice, this list of conditions and the following disclaimer in the
+      documentation and/or other materials provided with the distribution.
+    * Neither the name of the Princeton University nor the
+      names of its contributors may be used to endorse or promote products
+      derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+---------------------------------------------------------*/
+
 #include "diffusion.hpp"
 #include "diffusion_parameters.hpp"
 #include "dfpm/meshes/mesh1d.hpp"
 
 namespace specmicp {
 namespace dfpm {
 
 // SaturatedDiffusion1D::
 
 SaturatedDiffusion1D::SaturatedDiffusion1D(
         mesh::Mesh1DPtr the_mesh,
         std::shared_ptr<SaturatedDiffusion1DParameters> parameters,
         std::vector<index_t> list_bcs
         ):
     m_tot_ndf(the_mesh->nb_nodes()),
     m_mesh(the_mesh),
     m_param(parameters),
     m_internal_flow(Vector::Zero(m_tot_ndf)),
     m_external_flow(Vector::Zero(m_tot_ndf))
 {
     number_equations(list_bcs);
 }
 
 void SaturatedDiffusion1D::number_equations(std::vector<index_t> list_bcs)
 {
     m_id_equations = Eigen::VectorXi::Zero(m_tot_ndf);
     for (auto it=list_bcs.begin(); it!=list_bcs.end(); ++it)
     {
         m_id_equations(*it) = no_equation;
     }
     index_t neq = 0;
     for (index_t node: m_mesh->range_nodes())
     {
         if (m_id_equations(node) == no_equation) continue;
         m_id_equations(node) = neq;
         ++ neq;
     }
     m_neq = neq;
 }
 
 void SaturatedDiffusion1D::compute_residuals(
         const Vector& displacement,
         const Vector& velocity,
         Vector& residual
         )
 {
     m_internal_flow.setZero();
     residual.resize(get_neq());
     residual.setZero();
     for (index_t element: m_mesh->range_elements())
     {
         Vector elem_residuals(2);
         elem_residuals.setZero();
         element_residuals(element, displacement, velocity, elem_residuals);
         for (index_t enode: m_mesh->range_nen())
         {
             if (id_equation(m_mesh->get_node(element, enode)) == no_equation) continue;
             residual(id_equation(m_mesh->get_node(element, enode))) += elem_residuals(enode);
         }
     }
 }
 
 void SaturatedDiffusion1D::element_residuals(
         index_t element,
         const Vector& displacement,
         const Vector& velocity,
         Vector& elem_residuals
         )
 {
     Eigen::Matrix<scalar_t, 2, 2> jacob;
     Eigen::Matrix<scalar_t, 2, 1> evelocity, edisplacement;
     scalar_t mass_coeff = -(m_mesh->get_volume_element(element)/2.0);
 
     const index_t node_0 = m_mesh->get_node(element, 0);
     const index_t node_1 = m_mesh->get_node(element, 1);
 
     const scalar_t porosity = (m_param->porosity(node_0) +
                                m_param->porosity(node_1) )/2.0;
     const scalar_t diff_coeff = 1.0/(0.5/m_param->diffusion_coefficient(node_0) +
                                      0.5/m_param->diffusion_coefficient(node_1));
 
     const index_t dof_0 = node_0;
     const index_t dof_1 = node_1;
 
     scalar_t flux_coeff = -( m_mesh->get_face_area(element) / m_mesh->get_dx(element)
                             // * porosity
                              * diff_coeff
                              );
     jacob << 1.0, -1.0, -1.0, 1.0;
     jacob *= flux_coeff;
     evelocity << velocity(dof_0)*
                  mass_coeff*m_param->porosity(node_0),
             velocity(dof_1)*
             mass_coeff*m_param->porosity(node_1);
 
     edisplacement << displacement(dof_0),
             displacement(dof_1);
 
     elem_residuals = jacob*edisplacement;
 
     m_internal_flow(dof_0) += elem_residuals(0);
     m_internal_flow(dof_1) += elem_residuals(1);
 
     for (index_t en: m_mesh->range_nen())
     {
         elem_residuals(en) += evelocity(en);
         elem_residuals(en) += (m_mesh->get_volume_element(element)/2.0
                                  *external_flow(m_mesh->get_node(element, en)));
     }
 }
 
 void SaturatedDiffusion1D::compute_jacobian(
         Vector& displacement,
         Vector& velocity,
         Eigen::SparseMatrix<scalar_t>& jacobian,
         scalar_t alphadt
         )
 {
 
     list_triplet_t jacob;
     const index_t estimation = m_mesh->nb_nodes()*(m_mesh->nen);
     jacob.reserve(estimation);
     for (index_t element: m_mesh->range_elements())
     {
         element_jacobian(element, displacement, velocity, jacob, alphadt);
     }
     jacobian = Eigen::SparseMatrix<scalar_t>(get_neq(), get_neq());
     jacobian.setFromTriplets(jacob.begin(), jacob.end());
 }
 
 void SaturatedDiffusion1D::element_jacobian(
         index_t element,
         Vector& displacement,
         Vector& velocity,
         list_triplet_t& jacobian,
         scalar_t alphadt)
 {
     Eigen::VectorXd element_residual_orig(Eigen::VectorXd::Zero(2));
     element_residuals(element, displacement, velocity, element_residual_orig);
 
     for (index_t en: m_mesh->range_nen())
     {
         Eigen::VectorXd element_residual(Eigen::VectorXd::Zero(2));
 
         const index_t node = m_mesh->get_node(element, en);
         const index_t dof = node;
         const index_t idc = id_equation(dof);
 
         if (idc == no_equation) continue;
 
         const scalar_t tmp_v = velocity(dof);
         const scalar_t tmp_d = displacement(dof);
 
         scalar_t h = eps_jacobian*std::abs(tmp_v);
         if (h < 1e-4*eps_jacobian) h = eps_jacobian;
         velocity(dof) = tmp_v + h;
         h = velocity(dof) - tmp_v;
 
         displacement(dof) = tmp_d + alphadt*h;
 
         element_residuals(element, displacement, velocity, element_residual);
         velocity(dof) = tmp_v;
         displacement(dof) = tmp_d;
 
         for (index_t enr: m_mesh->range_nen())
         {
             const index_t noder = m_mesh->get_node(element, enr);
             const index_t idr = id_equation(noder);
 
             if (idr == no_equation) continue;
             jacobian.push_back(triplet_t(idr, idc, (element_residual(enr) - element_residual_orig(enr))/h));
         }
     }
 }
 
 void SaturatedDiffusion1D::update_solution(const Vector &update,
         scalar_t lambda,
         scalar_t alpha_dt,
         Vector &predictor,
         Vector &displacement,
         Vector &velocity
         )
 {
     for (index_t node: m_mesh->range_nodes())
     {
         const index_t id = id_equation(node);
         if (id == no_equation) continue;
         velocity(node) += lambda*update(id);
     }
     displacement = predictor + alpha_dt*velocity;
 }
 
 } // end namespace dfpm
 } // end namespace specmicp
diff --git a/src/dfpm/1dtransport/diffusion.hpp b/src/dfpm/1dtransport/diffusion.hpp
index 6871df4..637ee4f 100644
--- a/src/dfpm/1dtransport/diffusion.hpp
+++ b/src/dfpm/1dtransport/diffusion.hpp
@@ -1,108 +1,137 @@
+/*-------------------------------------------------------
+
+Copyright (c) 2014,2015 Fabien Georget <fabieng@princeton.edu>, Princeton University
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+    * Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+    * Redistributions in binary form must reproduce the above copyright
+      notice, this list of conditions and the following disclaimer in the
+      documentation and/or other materials provided with the distribution.
+    * Neither the name of the Princeton University nor the
+      names of its contributors may be used to endorse or promote products
+      derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+---------------------------------------------------------*/
+
 #ifndef SPECMICP_DFPM_1DTRANSPORT_DIFFUSION_HPP
 #define SPECMICP_DFPM_1DTRANSPORT_DIFFUSION_HPP
 
 #include <memory>
 
 #include "common.hpp"
 
 #include "dfpm/types.hpp"
 #include "dfpmsolver/parabolic_program.hpp"
 #include "dfpm/meshes/mesh1dfwd.hpp"
 
 namespace specmicp {
 
 namespace dfpm {
 
 class SaturatedDiffusion1DParameters;
 
 class SaturatedDiffusion1D: public dfpmsolver::ParabolicProgram<SaturatedDiffusion1D>
 {
 public:
     SaturatedDiffusion1D(
             mesh::Mesh1DPtr the_mesh,
             std::shared_ptr<SaturatedDiffusion1DParameters>  parameters,
             std::vector<index_t> list_bcs
             );
 
     //! \brief Return the number of equations
     index_t get_neq() const {return m_neq;}
 
     //! \brief Return the number of degrees of freedom per node
     index_t get_ndf() const {return 1;}
 
     //! \brief Return the total number of degrees of freedom
     index_t get_tot_ndf() const {return m_tot_ndf;}
 
     //! \brief Return the id of the equation corresponding to the degree of freedom 'id_dof'
     //!
     //! Return 'no_equation' if no equation exist
     index_t id_equation(index_t id_dof) const {return m_id_equations(id_dof);}
 
     void element_residuals(index_t element,
                            const Vector& displacement,
                            const Vector& velocity,
                            Vector& element_residual
                            );
 
     //! \brief Compute the residuals
     void compute_residuals(const Vector& displacement,
                            const Vector& velocity,
                            Vector& residual
                            );
 
     //! \brief Compute the jacobian
     void compute_jacobian(Vector& displacement,
                           Vector& velocity,
                           Eigen::SparseMatrix<scalar_t>& jacobian,
                           scalar_t alphadt
                           );
     void element_jacobian(
             index_t element,
             Vector& displacement,
             Vector& velocity,
             list_triplet_t& jacobian,
             scalar_t alphadt);
 
     //! \brief Update the solutions
     void update_solution(const Vector& update,
                          scalar_t lambda,
                          scalar_t alpha_dt,
                          Vector& predictor,
                          Vector& displacement,
                          Vector& velocity);
 
     //! \brief Apply boundary conditions to the velocity vector
     //!
     //! by default do nothing.
     void apply_bc(scalar_t dt,
                   const Vector& displacement,
                   Vector& velocity)
     {}
 
     //! \brief Return the value of the external flow for dof 'id_dof'
     scalar_t external_flow(index_t id_dof) const {return m_external_flow(id_dof);}
     //! \brief Return a reference to the value of the external flow for dof 'id_dof'
     scalar_t& external_flow(index_t id_dof) {return m_external_flow(id_dof);}
     //! \brief Return a reference to the vector of external flow
     Vector& external_flow() {return m_external_flow;}
 
 private:
     void number_equations(std::vector<index_t> list_bcs);
 
     index_t m_tot_ndf;
     index_t m_neq;
     Eigen::VectorXi m_id_equations;
 
     mesh::Mesh1DPtr m_mesh;
     std::shared_ptr<SaturatedDiffusion1DParameters> m_param;
 
     Vector m_internal_flow;
     Vector m_external_flow;
 };
 
 
 } // end namespace dfpm
 
 } // end namespace specmicp
 
 #endif // SPECMICP_DFPM_1DTRANSPORT_DIFFUSION_HPP
diff --git a/src/dfpm/1dtransport/diffusion_parameters.hpp b/src/dfpm/1dtransport/diffusion_parameters.hpp
index 5d81787..d01c2a3 100644
--- a/src/dfpm/1dtransport/diffusion_parameters.hpp
+++ b/src/dfpm/1dtransport/diffusion_parameters.hpp
@@ -1,25 +1,54 @@
+/*-------------------------------------------------------
+
+Copyright (c) 2014,2015 Fabien Georget <fabieng@princeton.edu>, Princeton University
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+    * Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+    * Redistributions in binary form must reproduce the above copyright
+      notice, this list of conditions and the following disclaimer in the
+      documentation and/or other materials provided with the distribution.
+    * Neither the name of the Princeton University nor the
+      names of its contributors may be used to endorse or promote products
+      derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+---------------------------------------------------------*/
+
 #ifndef SPECMICP_DFPM_1DTRANSPORT_DIFFUSIONPARAMETERS_HPP
 #define SPECMICP_DFPM_1DTRANSPORT_DIFFUSIONPARAMETERS_HPP
 
 #include "common.hpp"
 
 namespace specmicp {
 namespace dfpm {
 
 struct SaturatedDiffusion1DParameters
 {
     Vector porosity;
     Vector diffusion_coefficient;
 
     SaturatedDiffusion1DParameters(index_t nb_nodes):
         porosity(nb_nodes),
         diffusion_coefficient(nb_nodes)
     {}
 
 
 };
 
 } // end namespace dfpm
 } // end namespace specmicp
 
 #endif // SPECMICP_DFPM_1DTRANSPORT_DIFFUSIONPARAMETERS_HPP
diff --git a/src/dfpm/mesh.hpp b/src/dfpm/mesh.hpp
index 6a61c3c..421af96 100644
--- a/src/dfpm/mesh.hpp
+++ b/src/dfpm/mesh.hpp
@@ -1,14 +1,32 @@
 /*-------------------------------------------------------
 
- - Module : reactmicp
- - File : mesh.hpp
- - Author : Fabien Georget
+Copyright (c) 2014,2015 Fabien Georget <fabieng@princeton.edu>, Princeton University
+All rights reserved.
 
- Copyright (c) 2014, Fabien Georget, Princeton University
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+    * Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+    * Redistributions in binary form must reproduce the above copyright
+      notice, this list of conditions and the following disclaimer in the
+      documentation and/or other materials provided with the distribution.
+    * Neither the name of the Princeton University nor the
+      names of its contributors may be used to endorse or promote products
+      derived from this software without specific prior written permission.
 
----------------------------------------------------------*/
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
+---------------------------------------------------------*/
 #include "meshes/uniform_mesh1d.hpp"
 #include "meshes/axisymmetric_uniform_mesh1d.hpp"
 #include "meshes/axisymmetric_mesh1d.hpp"
 #include "meshes/generic_mesh1d.hpp"
diff --git a/src/dfpm/meshes/axisymmetric_mesh1d.hpp b/src/dfpm/meshes/axisymmetric_mesh1d.hpp
index e4541bc..4edea05 100644
--- a/src/dfpm/meshes/axisymmetric_mesh1d.hpp
+++ b/src/dfpm/meshes/axisymmetric_mesh1d.hpp
@@ -1,126 +1,155 @@
+/*-------------------------------------------------------
+
+Copyright (c) 2014,2015 Fabien Georget <fabieng@princeton.edu>, Princeton University
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+    * Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+    * Redistributions in binary form must reproduce the above copyright
+      notice, this list of conditions and the following disclaimer in the
+      documentation and/or other materials provided with the distribution.
+    * Neither the name of the Princeton University nor the
+      names of its contributors may be used to endorse or promote products
+      derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+---------------------------------------------------------*/
+
 #ifndef SPECMICP_DFPM_MESHES_AXISYMMETRICMESH1D_HPP
 #define SPECMICP_DFPM_MESHES_AXISYMMETRICMESH1D_HPP
 
 #include "mesh1d.hpp"
 
 namespace specmicp {
 namespace mesh {
 
 
 //! \brief A generic Axisymmetric 1D mesh
 class AxisymmetricMesh1D: public Mesh1D
 {
 public:
     const index_t radius = 0;
     const index_t cell_vol_0 = 1;
     const index_t cell_vol_1 = 2;
 
     //! \brief Build an axisymmetric 1D mesh
     //!
     //! \param radius is a vector of the position of the nodes
     //! \param height is the height of the sample (or depth)
     AxisymmetricMesh1D(Vector radius, scalar_t height):
         Mesh1D(radius.rows()),
         m_height(height),
         m_data(radius.rows(), 3),
         m_face_radius(radius.rows()-1)
     {
         // radius
         m_data.col(0) = radius;
         // Radius of the faces
         for (index_t element=0; element<nb_elements(); ++element)
         {
             m_face_radius(element) = (radius(element+1)+radius(element))/2.0;
         }
 
         // Volume at the left of the cell
         m_data(0, cell_vol_0) = 0.0;
         for (index_t node=1; node<nb_nodes(); ++node)
         {
            m_data(node, cell_vol_0) =  M_PI*height*(std::pow(m_face_radius(node-1), 2)
                                               - std::pow(radius(node), 2));
         }
         // Volume of the cell at the right of the node
         for (index_t node=0; node<nb_nodes()-1; ++node)
         {
             m_data(node, cell_vol_1) =  M_PI*height*(std::pow(radius(node), 2)
                                               - std::pow(m_face_radius(node), 2));
         }
         m_data(nb_nodes()-1, cell_vol_1) = 0.0;
 
     }
 
     //!  \brief Return the radius of an element
     scalar_t get_radius(index_t element, index_t enode) {
         return m_data(get_node(element, enode), radius);
     }
     //! \brief Return the radius of the face
     scalar_t get_radius_face(index_t element) {
         return m_face_radius(element);
     }
     //! \brief Return the position (meaning may vary with the mesh) of the node
     scalar_t get_position(index_t node) {return m_data(node, radius);}
     //! \brief Return the length of an element
     scalar_t get_dx(index_t element) {
         return get_radius(element, 0) - get_radius(element, 1);}
     //! \brief Return the area of the face at the middle of an element
     scalar_t get_face_area(index_t element) {
         return 2*M_PI*m_face_radius(element)*m_height;}
     //! \brief Return the volume of an element
     scalar_t get_volume_element(index_t element) {
         return (m_data(get_node(element, 0), cell_vol_1)
                 + m_data(get_node(element, 1), cell_vol_0));}
     //! \brief Return the volume of a cell (element of the dual mesh)
     scalar_t get_volume_cell(index_t node) {
         return (m_data(node, cell_vol_0) + m_data(node, cell_vol_1));}
     //! \brief Return the volume of a cell inside an element
     virtual scalar_t get_volume_cell_element(index_t element, index_t enode) {
         if (enode == 0)
             return m_data(get_node(element, enode), cell_vol_1);
         else
             return m_data(get_node(element, enode), cell_vol_0);
     }
 
 private:
     scalar_t m_height;
     Matrix m_data;
     Vector m_face_radius;
 };
 
 //! \brief Return a shared_ptr to an axisymmetric mesh
 //!
 //! \param radius is a vector of the position of the nodes
 //! \param height is the height of the sample (or depth)
 inline Mesh1DPtr axisymmetric_mesh1d(Vector radius, scalar_t height)
 {
     return std::static_pointer_cast<Mesh1D>(
                 std::make_shared<AxisymmetricMesh1D>(radius, height));
 
 }
 
 //! \brief Factory method to build a pointer to a uniform axisymmetric 1D mesh
 //!
 //! \param nb_nodes number of nodes in the mesh
 //! \param radius of the first node (biggest radius in the mesh)
 //! \param dx length of an element
 //! \param height is the height of the sample (or depth)
 //!
 //! Note: this method buil an AxisymmetricMesh1D instance while
 //! the specmicp::mesh::axisymmetric_uniform_mesh1d method build a
 //! specmicp::mesh::AxisymmetricUniformMesh1D instance.
 inline Mesh1DPtr uniform_axisymmetric_mesh1d(index_t nb_nodes, scalar_t radius, scalar_t dx, scalar_t height)
 {
     Vector radius_s(nb_nodes);
     for (index_t node=0; node<nb_nodes; ++node)
     {
         radius_s(node) = radius - node*dx;
     }
     return std::static_pointer_cast<Mesh1D>(
                 std::make_shared<AxisymmetricMesh1D>(radius_s, height));
 
 }
 
 } // end namespace mesh
 } // end namespace specmicp
 
 #endif // SPECMICP_DFPM_MESHES_AXISYMMETRICMESH1D_HPP
diff --git a/src/dfpm/meshes/axisymmetric_uniform_mesh1d.hpp b/src/dfpm/meshes/axisymmetric_uniform_mesh1d.hpp
index 09d91f5..e510941 100644
--- a/src/dfpm/meshes/axisymmetric_uniform_mesh1d.hpp
+++ b/src/dfpm/meshes/axisymmetric_uniform_mesh1d.hpp
@@ -1,105 +1,124 @@
 /*-------------------------------------------------------
 
- - Module : reactmicp/meshes
- - File : axisymmetric_uniform_mesh1d.hpp
- - Author : Fabien Georget
-
- Copyright (c) 2014, Fabien Georget, Princeton University
+Copyright (c) 2014,2015 Fabien Georget <fabieng@princeton.edu>, Princeton University
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+    * Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+    * Redistributions in binary form must reproduce the above copyright
+      notice, this list of conditions and the following disclaimer in the
+      documentation and/or other materials provided with the distribution.
+    * Neither the name of the Princeton University nor the
+      names of its contributors may be used to endorse or promote products
+      derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 ---------------------------------------------------------*/
 
 #ifndef SPECMICP_REACTMICP_MESHES_AXISYMMETRICMESH1D_HPP
 #define SPECMICP_REACTMICP_MESHES_AXISYMMETRICMESH1D_HPP
 
 #include "mesh1d.hpp"
 
 // \file axisymmetric_uniform_mesh1d.hpp Uniform axisymmetric 1D mesh
 
 namespace specmicp {
 namespace mesh {
 
 //! \brief A uniform 1D mesh
 class AxisymmetricUniformMesh1D: public Mesh1D
 {
 public:
     AxisymmetricUniformMesh1D(index_t nb_nodes, scalar_t radius, scalar_t height):
         Mesh1D(nb_nodes),
         m_radius(radius),
 	m_radius_int(0.0),
         m_dx(radius/(nb_nodes-1)),
         m_height(height)
     {}
 
     AxisymmetricUniformMesh1D(index_t nb_nodes, scalar_t radius, scalar_t dx, scalar_t height):
         Mesh1D(nb_nodes),
         m_radius(radius),
 	m_radius_int(radius-(nb_nodes-1)*dx),
         m_dx(dx),
         m_height(height)
     {}
 
     scalar_t get_radius_node(index_t node) {
         return m_radius-m_dx*node;
     }
     //! Return the radius of a face of an element
     scalar_t get_radius_face(index_t element) {
         return get_radius_node(get_node(element, 1))+m_dx/2;
     }
 
     scalar_t get_position(index_t node) {return get_radius_node(node);}
     scalar_t get_dx(index_t _) {return m_dx;}
     scalar_t get_face_area(index_t element) {
         return 2*M_PI*get_radius_face(element)*m_height;}
     scalar_t get_volume_element(index_t element) {return M_PI*m_height*(
                      std::pow(get_radius_node(get_node(element, 0)),2)
                    - std::pow(get_radius_node(get_node(element, 1)),2))
                 ;}
     scalar_t get_volume_cell(index_t node) {
         if (node ==0)
             return M_PI*m_height*(std::pow(m_radius,2)-std::pow(get_radius_face(0),2));
         else if (node == nb_nodes()-1)
             if (m_radius_int == 0.0)
                 return M_PI*m_height*std::pow(m_dx/2.0,2);
             else
 	        return M_PI*m_height*(std::pow(get_radius_face(node-1),2) - std::pow(m_radius_int,2));
 
         else
             return M_PI*m_height*(std::pow(get_radius_face(node-1),2) - std::pow(get_radius_face(node),2));
     }
     scalar_t get_volume_cell_element(index_t element, index_t enode) {
        if (enode == 0)
        {
            return M_PI*m_height*(std::pow(get_radius_node(get_node(element,enode)),2)
                                  - std::pow(get_radius_face(element),2));
        }
        else
        {
            return M_PI*m_height*(std::pow(get_radius_face(element),2)
                                  - std::pow(get_radius_node(get_node(element,enode)),2));
        }
     }
 private:
     scalar_t m_radius;
     scalar_t m_radius_int;
     scalar_t m_dx;
     scalar_t m_height;
 };
 
 //! \brief Factory method to build a pointer to a uniform 1D mesh
 inline Mesh1DPtr axisymmetric_uniform_mesh1d(index_t nb_nodes, scalar_t radius, scalar_t height)
 {
     return std::static_pointer_cast<Mesh1D>(
                 std::make_shared<AxisymmetricUniformMesh1D>(nb_nodes, radius, height));
 }
 
 
 //! \brief Factory method to build a pointer to a uniform 1D mesh
 inline Mesh1DPtr axisymmetric_uniform_mesh1d(index_t nb_nodes, scalar_t radius, scalar_t dx, scalar_t height)
 {
     return std::static_pointer_cast<Mesh1D>(
                 std::make_shared<AxisymmetricUniformMesh1D>(nb_nodes, radius, dx, height));
 }
 } // end namespace mesh
 } // end namespace specmicp
 
 #endif // SPECMICP_REACTMICP_MESHES_AXISYMMETRICMESH1D_HPP
diff --git a/src/dfpm/meshes/generic_mesh1d.hpp b/src/dfpm/meshes/generic_mesh1d.hpp
index b4c6549..5de7b33 100644
--- a/src/dfpm/meshes/generic_mesh1d.hpp
+++ b/src/dfpm/meshes/generic_mesh1d.hpp
@@ -1,95 +1,124 @@
+/*-------------------------------------------------------
+
+Copyright (c) 2014,2015 Fabien Georget <fabieng@princeton.edu>, Princeton University
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+    * Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+    * Redistributions in binary form must reproduce the above copyright
+      notice, this list of conditions and the following disclaimer in the
+      documentation and/or other materials provided with the distribution.
+    * Neither the name of the Princeton University nor the
+      names of its contributors may be used to endorse or promote products
+      derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+---------------------------------------------------------*/
+
 #ifndef SPECMICP_DFPM_MESHES_GENERICMESH1D_HPP
 #define SPECMICP_DFPM_MESHES_GENERICMESH1D_HPP
 
 #include "mesh1d.hpp"
 
 namespace specmicp {
 namespace mesh {
 
 
 //! \brief A generic 1D mesh
 class GenericMesh1D: public Mesh1D
 {
 public:
     const index_t coord = 0;
     const index_t cell_vol_0 = 1;
     const index_t cell_vol_1 = 2;
 
     //! \brief Build an axisymmetric 1D mesh
     //!
     //! \param radius is a vector of the position of the nodes
     //! \param height is the height of the sample (or depth)
     GenericMesh1D(Vector coords, scalar_t section):
         Mesh1D(coords.rows()),
         m_section(section),
         m_data(coords.rows(), 4),
         m_face_coord(coords.rows()-1)
     {
         // radius
         m_data.col(coord) = coords;
         // Radius of the faces
         for (index_t element=0; element<nb_elements(); ++element)
         {
             m_face_coord(element) = (coords(element+1)+coords(element))/2.0;
         }
 
         // Volume at the left of the cell
         m_data(0, cell_vol_0) = 0.0;
         for (index_t node=1; node<nb_nodes(); ++node)
         {
            m_data(node, cell_vol_0) =  m_section*(coords(node)-m_face_coord(node-1));
         }
         // Volume of the cell at the right of the node
         for (index_t node=0; node<nb_nodes()-1; ++node)
         {
             m_data(node, cell_vol_1) =  m_section*(m_face_coord(node)-coords(node));
         }
         m_data(nb_nodes()-1, cell_vol_1) = 0.0;
 
     }
 
     scalar_t get_coord(index_t element, index_t enode) {return m_data(get_node(element, enode), coord);}
     //! \brief Return the position (meaning may vary with the mesh) of the node
     scalar_t get_position(index_t node) {return m_data(node, coord);}
     //! \brief Return the length of an element
     scalar_t get_dx(index_t element) {
         return get_coord(element, 1) - get_coord(element, 0);}
     //! \brief Return the area of the face at the middle of an element
     scalar_t get_face_area(index_t element) {
         return m_section;}
     //! \brief Return the volume of an element
     scalar_t get_volume_element(index_t element) {
         return (m_data(get_node(element, 0), cell_vol_1)
                 + m_data(get_node(element, 1), cell_vol_0));}
     //! \brief Return the volume of a cell (element of the dual mesh)
     scalar_t get_volume_cell(index_t node) {
         return (m_data(node, cell_vol_0) + m_data(node, cell_vol_1));}
     //! \brief Return the volume of a cell inside an element
     virtual scalar_t get_volume_cell_element(index_t element, index_t enode) {
         if (enode == 0)
             return m_data(get_node(element, enode), cell_vol_1);
         else
             return m_data(get_node(element, enode), cell_vol_0);
     }
 
 private:
     scalar_t m_section;
     Matrix m_data;
     Vector m_face_coord;
 };
 
 //! \brief Return a shared_ptr to an axisymmetric mesh
 //!
 //! \param coords is a vector of the position of the nodes
 //! \param section is the section of the sample (or depth)
 inline Mesh1DPtr generic_mesh1d(Vector coords, scalar_t section)
 {
     return std::static_pointer_cast<Mesh1D>(
                 std::make_shared<GenericMesh1D>(coords, section));
 
 }
 
 } // end namespace mesh
 } // end namespace specmicp
 
 #endif // SPECMICP_DFPM_MESHES_GENERICMESH1D_HPP
diff --git a/src/dfpm/meshes/mesh1d.hpp b/src/dfpm/meshes/mesh1d.hpp
index f896e54..da2e4af 100644
--- a/src/dfpm/meshes/mesh1d.hpp
+++ b/src/dfpm/meshes/mesh1d.hpp
@@ -1,96 +1,92 @@
 /*-------------------------------------------------------
 
- - Module : reactmicp/meshes
- - File : mesh1d.hpp
- - Author : Fabien Georget
-
-Copyright (c) 2014, Fabien Georget <fabieng@princeton.edu>, Princeton University
+Copyright (c) 2014,2015 Fabien Georget <fabieng@princeton.edu>, Princeton University
 All rights reserved.
 
 Redistribution and use in source and binary forms, with or without
 modification, are permitted provided that the following conditions are met:
     * Redistributions of source code must retain the above copyright
       notice, this list of conditions and the following disclaimer.
     * Redistributions in binary form must reproduce the above copyright
       notice, this list of conditions and the following disclaimer in the
       documentation and/or other materials provided with the distribution.
     * Neither the name of the Princeton University nor the
       names of its contributors may be used to endorse or promote products
       derived from this software without specific prior written permission.
 
 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
 ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 ---------------------------------------------------------*/
 
 #ifndef SPECMICP_REACTMICP_MESH_MESH1D_HPP
 #define SPECMICP_REACTMICP_MESH_MESH1D_HPP
 
 #include "common.hpp"
 #include <memory>
 
 namespace specmicp {
 namespace mesh {
 
 //! AbstractBase class for a 1D mesh
 class Mesh1D
 {
 public:
     const index_t nen = 2; //!< Number of elemental nodes
 
     Mesh1D(index_t nb_nodes): m_nb_nodes(nb_nodes) {}
     virtual ~Mesh1D() {}
 
     //! \brief Return the number of elements
     index_t nb_elements() {return m_nb_nodes-1;}
     //! \brief Return the number of nodes
     index_t nb_nodes() {return m_nb_nodes;}
 
     //! \brief Return the node from local nod enumber and element
     index_t get_node(index_t element, index_t index)
     {
         specmicp_assert(index < nen);
         return element+index;
     }
     //! \brief Return the position (meaning may vary with the mesh) of the node
     virtual scalar_t get_position(index_t node) = 0;
     //! \brief Return the length of an element
     virtual scalar_t get_dx(index_t element) = 0;
     //! \brief Return the area of the face at the middle of an element
     virtual scalar_t get_face_area(index_t element) = 0;
     //! \brief Return the volume of an element
     virtual scalar_t get_volume_element(index_t element) = 0;
     //! \brief Return the volume of a cell (element of the dual mesh)
     virtual scalar_t get_volume_cell(index_t node) = 0;
     //!
     virtual scalar_t get_volume_cell_element(index_t element, index_t node) = 0;
 
     //! \brief Range over the elements
     range_t range_elements() {return boost::irange((index_t) 0, nb_elements());}
     //! \brief Range over the nodes
     range_t range_nodes() {return boost::irange((index_t) 0, nb_nodes());}
     //! \brief Range over the elemental nodes
     range_t range_nen() {return boost::irange((index_t) 0, nen);}
 
 private:
     index_t m_nb_nodes; //!< Number of elements
 };
 
 //! \brief type of a pointer to a mesh
 //!
 //! This is a smart pointer allowing the mesh to be shared freely
 using Mesh1DPtr = std::shared_ptr<Mesh1D>;
 
 
 } // end namespace mesh
 } // end namespace specmicp
 
 #endif // SPECMICP_REACTMICP_MESH_MESH1D_HPP
diff --git a/src/dfpm/meshes/mesh1dfwd.hpp b/src/dfpm/meshes/mesh1dfwd.hpp
index a1daa2d..9a96ee1 100644
--- a/src/dfpm/meshes/mesh1dfwd.hpp
+++ b/src/dfpm/meshes/mesh1dfwd.hpp
@@ -1,27 +1,46 @@
 /*-------------------------------------------------------
 
- - Module : reactmicp/meshes
- - File : mesh1dfwd.hpp
- - Author : Fabien Georget
-
- Copyright (c) 2014, Fabien Georget, Princeton University
+Copyright (c) 2014,2015 Fabien Georget <fabieng@princeton.edu>, Princeton University
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+    * Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+    * Redistributions in binary form must reproduce the above copyright
+      notice, this list of conditions and the following disclaimer in the
+      documentation and/or other materials provided with the distribution.
+    * Neither the name of the Princeton University nor the
+      names of its contributors may be used to endorse or promote products
+      derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 ---------------------------------------------------------*/
 
 #ifndef SPECMICP_REACTMICP_MESH_MESH1DFWD
 #define SPECMICP_REACTMICP_MESH_MESH1DFWD
 
 #include <memory>
 
 // define the forward declaration of a 1D mesh
 
 namespace specmicp {
 namespace mesh {
 
 class Mesh1D;
 using Mesh1DPtr = std::shared_ptr<Mesh1D>;
 
 } // end namespace mesh
 } // end namespace specmicp
 
 #endif // SPECMICP_REACTMICP_MESH_MESH1DFWD
diff --git a/src/dfpm/meshes/uniform_mesh1d.hpp b/src/dfpm/meshes/uniform_mesh1d.hpp
index 653b0ca..01de348 100644
--- a/src/dfpm/meshes/uniform_mesh1d.hpp
+++ b/src/dfpm/meshes/uniform_mesh1d.hpp
@@ -1,54 +1,72 @@
 /*-------------------------------------------------------
 
- - Module : reactmicp/meshes
- - File : uniform_mesh1d
- - Author : Fabien Georget
+Copyright (c) 2014,2015 Fabien Georget <fabieng@princeton.edu>, Princeton University
+All rights reserved.
 
- Copyright (c) 2014, Fabien Georget, Princeton University
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+    * Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+    * Redistributions in binary form must reproduce the above copyright
+      notice, this list of conditions and the following disclaimer in the
+      documentation and/or other materials provided with the distribution.
+    * Neither the name of the Princeton University nor the
+      names of its contributors may be used to endorse or promote products
+      derived from this software without specific prior written permission.
 
----------------------------------------------------------*/
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
+---------------------------------------------------------*/
 #ifndef SPECMICP_REACTMICP_MESH_UNIFORMMESH1D_HPP
 #define SPECMICP_REACTMICP_MESH_UNIFORMMESH1D_HPP
 
 #include "mesh1d.hpp"
 
 // \file uniform_mesh1d.hpp Uniform 1D mesh
 
 namespace specmicp {
 namespace mesh {
 
 //! \brief A uniform 1D mesh
 class UniformMesh1D: public Mesh1D
 {
 public:
     UniformMesh1D(index_t nb_nodes, scalar_t dx, scalar_t cross_section):
         Mesh1D(nb_nodes), m_dx(dx), m_crosssection(cross_section)
     {}
     scalar_t get_position(index_t node) {return m_dx*node;}
     scalar_t get_dx(index_t _) {return m_dx;}
     scalar_t get_face_area(index_t _) { return m_crosssection;}
     scalar_t get_volume_element(index_t _) {return m_dx*m_crosssection;}
     scalar_t get_volume_cell(index_t node) {
         if (node ==0 or node == nb_nodes()-1) return m_dx*m_crosssection/2;
         else return m_dx*m_crosssection;
 
     }
     scalar_t get_volume_cell_element(index_t element, index_t enode) {
         return m_dx*m_crosssection/2;
     }
 private:
     scalar_t m_dx;
     scalar_t m_crosssection;
 };
 
 //! \brief Factory method to build a pointer to a uniform 1D mesh
 inline Mesh1DPtr uniform_mesh1d(index_t nb_nodes, scalar_t dx, scalar_t cross_section)
 {
     return std::static_pointer_cast<Mesh1D>(std::make_shared<UniformMesh1D>(nb_nodes, dx, cross_section));
 }
 
 } // end namespace mesh
 } // end namespace specmicp
 
 #endif // SPECMICP_REACTMICP_MESH_UNIFORMMESH1D_HPP
diff --git a/src/dfpm/types.hpp b/src/dfpm/types.hpp
index 8d5cb9c..7f0b895 100644
--- a/src/dfpm/types.hpp
+++ b/src/dfpm/types.hpp
@@ -1,17 +1,46 @@
+/*-------------------------------------------------------
+
+Copyright (c) 2014,2015 Fabien Georget <fabieng@princeton.edu>, Princeton University
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+    * Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+    * Redistributions in binary form must reproduce the above copyright
+      notice, this list of conditions and the following disclaimer in the
+      documentation and/or other materials provided with the distribution.
+    * Neither the name of the Princeton University nor the
+      names of its contributors may be used to endorse or promote products
+      derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+---------------------------------------------------------*/
+
 #ifndef SPECMICP_DFPM_TYPES_HPP
 #define SPECMICP_DFPM_TYPES_HPP
 
 #include "common.hpp"
 #include "Eigen/SparseCore"
 #include <vector>
 
 namespace specmicp {
 namespace dfpm {
 
 using triplet_t = Eigen::Triplet<scalar_t>;
 using list_triplet_t = std::vector<triplet_t>;
 
 } // end namespace dfpm
 } // end namespace specmicp
 
 #endif // SPECMICP_DFPM_TYPES_HPP
diff --git a/src/dfpmsolver/dfpm_program.hpp b/src/dfpmsolver/dfpm_program.hpp
index 5d21b89..ec9ad59 100644
--- a/src/dfpmsolver/dfpm_program.hpp
+++ b/src/dfpmsolver/dfpm_program.hpp
@@ -1,36 +1,65 @@
+/*-------------------------------------------------------
+
+Copyright (c) 2014,2015 Fabien Georget <fabieng@princeton.edu>, Princeton University
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+    * Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+    * Redistributions in binary form must reproduce the above copyright
+      notice, this list of conditions and the following disclaimer in the
+      documentation and/or other materials provided with the distribution.
+    * Neither the name of the Princeton University nor the
+      names of its contributors may be used to endorse or promote products
+      derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+---------------------------------------------------------*/
+
 #ifndef SPECMICP_DFPMSOLVER_DFPMPROGRAM_HPP
 #define SPECMICP_DFPMSOLVER_DFPMPROGRAM_HPP
 
 #include "common.hpp"
 
 namespace specmicp {
 namespace dfpmsolver {
 
 //! \brief Base class for a program
 template <class Derived>
 class DFPMProgram
 {
 public:
     //! \brief Return a pointer to the true object
     Derived* derived() {static_cast<Derived*>(this);}
 
     //! \brief Return the number of equations
     index_t get_neq() const {return derived()->get_neq();}
 
     //! \brief Return the number of degrees of freedom per node
     index_t get_ndf() const {return derived()->get_ndf();}
 
     //! \brief Return the total number of degrees of freedom
     index_t get_tot_ndf() const {return derived()->get_tot_ndf();}
 
     //! \brief Return the id of the equation corresponding to the degree of freedom 'id_dof'
     //!
     //! Return 'no_equation' if no equation exist
     index_t id_equation(index_t id_dof) const {return derived()->id_equation(id_dof);}
 
 };
 
 } // end namespace dfpmsolver
 } // end namespace specmicp
 
 #endif // SPECMICP_DFPMSOLVER_DFPMPROGRAM_HPP
diff --git a/src/dfpmsolver/driver.hpp b/src/dfpmsolver/driver.hpp
index 7eaddc7..7551049 100644
--- a/src/dfpmsolver/driver.hpp
+++ b/src/dfpmsolver/driver.hpp
@@ -1,106 +1,135 @@
+/*-------------------------------------------------------
+
+Copyright (c) 2014,2015 Fabien Georget <fabieng@princeton.edu>, Princeton University
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+    * Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+    * Redistributions in binary form must reproduce the above copyright
+      notice, this list of conditions and the following disclaimer in the
+      documentation and/or other materials provided with the distribution.
+    * Neither the name of the Princeton University nor the
+      names of its contributors may be used to endorse or promote products
+      derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+---------------------------------------------------------*/
+
 #ifndef SPECMICP_DFPMSOLVER_DRIVER_HPP
 #define SPECMICP_DFPMSOLVER_DRIVER_HPP
 
 #include "common.hpp"
 
 namespace specmicp {
 namespace dfpmsolver {
 
 //! \brief Base class for a driver
 //!
 //! Options should be a subclass of DriverOptions
 //! Performance should be a subclass of DriverPerformance
 //!
 template <class Program, class Options, class Performance>
 class Driver
 {
 public:
     Driver(Program& the_program):
         m_program(the_program),
         m_options(),
         m_scaling_is_initialized(false)
     {
     }
 
     Driver(Program& the_program,
             Options some_options):
         m_program(the_program),
         m_options(some_options),
         m_scaling_is_initialized(false)
     {
     }
 
     // basic program management
     // ------------------------
 
     //! Return the program
     Program& program() {return m_program;}
 
     //! Return the number of equations
     index_t get_neq() {return m_program.get_neq();}
 
     // common process
     // --------------
     //! \brief rescale the update if needed
     //!
     //! Return the step length
     scalar_t is_step_too_long(Vector& update);
 
 
     // options
     // -------
 
     //! \brief Return a read/write reference to the options
     Options& get_options() {return m_options;}
     //! \brief Return a read-only reference to the options
     const Options& get_options() const {return m_options;}
 
     // performance
     // -----------
 
     //! \brief Return a const reference to the performance
     const Performance& get_perfs() const {return m_performance;}
 
     // Scaling
     // -------
 
     void initialize_scaling() {
         if (not m_scaling_is_initialized)
         {
             m_scaling.resize(get_neq());
             m_scaling.setOnes();
         }
     }
 
     void set_scaling(const Vector& scale) {
         specmicp_assert(scale.rows() == get_neq());
         m_scaling = scale;
         m_scaling_is_initialized = true;
     }
 
     const Vector& scaling() const {return m_scaling;}
     scalar_t scaling(index_t id_eq) const {return m_scaling(id_eq);}
 
 
 protected:
     //! \brief Read/write access to the performance
     Performance& get_perfs() {return m_performance;}
 
 private:
     Program& m_program;        //!< The program
     Performance m_performance; //!< The performance
     Options m_options;         //!< The options
 
     Vector m_scaling;            //!< Scaling factor
     bool m_scaling_is_initialized;
 };
 
 } // end namespace dfpmsolver
 } // end namespace specmicp
 
 // implementation
 // ==============
 
 #include "driver.inl"
 
 #endif // SPECMICP_DFPMSOLVER_DRIVER_HPP
diff --git a/src/dfpmsolver/driver.inl b/src/dfpmsolver/driver.inl
index cf3736e..90f7f88 100644
--- a/src/dfpmsolver/driver.inl
+++ b/src/dfpmsolver/driver.inl
@@ -1,22 +1,51 @@
+/*-------------------------------------------------------
+
+Copyright (c) 2014,2015 Fabien Georget <fabieng@princeton.edu>, Princeton University
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+    * Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+    * Redistributions in binary form must reproduce the above copyright
+      notice, this list of conditions and the following disclaimer in the
+      documentation and/or other materials provided with the distribution.
+    * Neither the name of the Princeton University nor the
+      names of its contributors may be used to endorse or promote products
+      derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+---------------------------------------------------------*/
+
 #include "driver.hpp" // syntaxic coloration only
 
 namespace specmicp {
 namespace dfpmsolver {
 
 
 template <class Program, class Options, class Performance>
 scalar_t Driver<Program, Options, Performance>::is_step_too_long(Vector& update)
 {
     double steplength = (scaling().asDiagonal()*update).norm();
     if (steplength > get_options().maximum_step_length)
     {
         get_perfs().maximum_step_taken = true;
         update  = (get_options().maximum_step_length / steplength) * update;
         steplength = get_options().maximum_step_length;
     }
     return steplength;
 }
 
 
 } // end namespace dfpmsolver
 } // end namespace specmicp
diff --git a/src/dfpmsolver/driver_structs.hpp b/src/dfpmsolver/driver_structs.hpp
index 0c369f3..38653c9 100644
--- a/src/dfpmsolver/driver_structs.hpp
+++ b/src/dfpmsolver/driver_structs.hpp
@@ -1,67 +1,96 @@
+/*-------------------------------------------------------
+
+Copyright (c) 2014,2015 Fabien Georget <fabieng@princeton.edu>, Princeton University
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+    * Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+    * Redistributions in binary form must reproduce the above copyright
+      notice, this list of conditions and the following disclaimer in the
+      documentation and/or other materials provided with the distribution.
+    * Neither the name of the Princeton University nor the
+      names of its contributors may be used to endorse or promote products
+      derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+---------------------------------------------------------*/
+
 #ifndef SPECMICP_DFPMSOLVER_DRIVERSTRUCTS_HPP
 #define SPECMICP_DFPMSOLVER_DRIVERSTRUCTS_HPP
 
 #include "common.hpp"
 #include "utils/sparse_solvers/sparse_solver_structs.hpp"
 
 namespace specmicp {
 namespace dfpmsolver {
 
 
 //! \brief Options of a driver
 //!
 struct DriverOptions
 {
     scalar_t residuals_tolerance;    //!< Tolerance for the residual
     scalar_t absolute_tolerance;    //!< Absolute tolerance for the residual
     scalar_t step_tolerance;        //!< Tolerance for the minimum step length
     scalar_t threshold_stationary_point; //!< if ||R||>threshold, the point is classified as stationary
     int maximum_iterations;       //!< Maximum iterations allowed
     scalar_t maximum_step_length;   //!< Maximum step length allowed
     int max_iterations_at_max_length;   //!< Maximum number of iterations at maximum step length
     scalar_t coeff_accept_newton_step; //!< Accept Newton step if enough progress is made
     sparse_solvers::SparseSolver sparse_solver;   //!< The sparse solver to use
 
     DriverOptions():
         residuals_tolerance(5e-5),
         absolute_tolerance(1e-12),
         step_tolerance(1e-10),
         threshold_stationary_point(1e-4),
         maximum_iterations(200),
         maximum_step_length(1e3),
         max_iterations_at_max_length(50),
         coeff_accept_newton_step(0.9),
         sparse_solver(sparse_solvers::SparseSolver::SparseQR)
     {}
 };
 
 //! \brief Performance of a driver
 struct DriverPerformance
 {
     int nb_call_residuals;
     int nb_call_jacobian;
     int nb_iterations;
     int nb_consecutive_max_step_taken;
     int nb_max_step_taken;
     bool maximum_step_taken;
     scalar_t current_residual;
     scalar_t absolute_residual;
     scalar_t current_update;
 
     DriverPerformance():
         nb_call_residuals(0),
         nb_call_jacobian(0),
         nb_iterations(0),
         nb_consecutive_max_step_taken(0),
         nb_max_step_taken(0),
         maximum_step_taken(0),
         current_residual(0.0),
         absolute_residual(0.0),
         current_update(0.0)
     {}
 };
 
 } // end namespace dfpmsolver
 } // end namespace specmicp
 
 #endif // SPECMICP_DFPMSOLVER_DRIVERSTRUCTS_HPP
diff --git a/src/dfpmsolver/parabolic_driver.hpp b/src/dfpmsolver/parabolic_driver.hpp
index 1f56b40..9e64070 100644
--- a/src/dfpmsolver/parabolic_driver.hpp
+++ b/src/dfpmsolver/parabolic_driver.hpp
@@ -1,153 +1,182 @@
+/*-------------------------------------------------------
+
+Copyright (c) 2014,2015 Fabien Georget <fabieng@princeton.edu>, Princeton University
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+    * Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+    * Redistributions in binary form must reproduce the above copyright
+      notice, this list of conditions and the following disclaimer in the
+      documentation and/or other materials provided with the distribution.
+    * Neither the name of the Princeton University nor the
+      names of its contributors may be used to endorse or promote products
+      derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+---------------------------------------------------------*/
+
 #ifndef SPECMICP_DFPMSOLVER_PARABOLICDRIVER_HPP
 #define SPECMICP_DFPMSOLVER_PARABOLICDRIVER_HPP
 
 #include "common.hpp"
 #include "utils/sparse_solvers/sparse_solver.hpp"
 
 #include "driver.hpp"
 #include "parabolic_structs.hpp"
 
 namespace specmicp {
 namespace dfpmsolver {
 
 //! \brief The parabolic driver
 //!
 //!  Parabolic driver for finite element programs
 template <class Program>
 class ParabolicDriver: public Driver<Program, ParabolicDriverOptions, ParabolicDriverPerformance>
 {
 public:
     using base=Driver<Program, ParabolicDriverOptions, ParabolicDriverPerformance>;
     using base::program;
     using base::get_neq;
     using base::get_options;
     using base::get_perfs;
     using base::scaling;
     using base::initialize_scaling;
 
 
     ParabolicDriver(Program& the_program):
         Driver<Program, ParabolicDriverOptions, ParabolicDriverPerformance>(the_program),
         m_velocity(Vector::Zero(the_program.get_tot_ndf())),
         m_solver(nullptr)
     {}
 
     //! \brief Solve a timestep of length dt
     ParabolicDriverReturnCode  solve_timestep(scalar_t dt, Vector& displacement);
     //! \brief Restart the current timestep
     ParabolicDriverReturnCode  restart_timestep(Vector& displacement);
     //! \brief Check if the solution has been found
     ParabolicDriverReturnCode check_convergence();
     //! \brief Compute the residuals
     void compute_residuals(const Vector& displacement,
                            Vector& residual)
     {
         compute_residuals(displacement, m_velocity, residual);
     }
 
     //! \brief Compute the residuals
     void compute_residuals(const Vector& displacement,
                            const Vector& velocity,
                            Vector& residual)
     {
         program().compute_residuals(displacement, velocity, residual);
         get_perfs().nb_call_residuals += 1;
     }
     //! \brief Compute the jacobian
     void compute_jacobian(Vector& displacement,
                           Vector& velocity,
                           Eigen::SparseMatrix<scalar_t>& jacobian
                           );
     //! \brief Return the norm of the current residuals
     double norm_residuals() {return m_residuals.norm();}
     //! \brief Read/Write reference to the velocity vector
     const Vector& get_velocity() const {return m_velocity;}
     Vector& velocity() {return m_velocity;}
     void set_velocity(Vector& velocity_vector);
 
     //! \brief Reset the Sparse solver
     //! This function should be called when a new solver need to be used
     void reset_solver() {return m_solver.reset(nullptr);}
 
     //! \brief Call this function if the pattern of the jacobian has changed
     void jacobian_pattern_has_changed() {reset_solver();}
 
     //! \brief Initialize the computation
     void initialize_timestep(scalar_t dt, Eigen::VectorXd& displacement);
 
     //! \brief Strang Linesearch
     //!
     //! ref :
     //!     -  Matthies et al. (1979)
     //!     -  JHP course notes
     ParabolicLinesearchReturnCode strang_linesearch(
             Vector& update,
             Vector& displacements,
             scalar_t& lambda
             );
 
     scalar_t residuals_0() {return m_norm_0;}
 private:
 
     void reset_velocity();
 
     //! \brief Backtracking Linesearch
     //!
     //! ref :
     //!    - Algo A6.3.1 : Dennis and Schnabel (1983)
     //!    - Nocedal & Wrigth (2006)
     ParabolicLinesearchReturnCode backtracking_linesearch(
             Vector& update,
             Vector& displacements,
             scalar_t& lambda_out
             );
     //! Update the variables in displacement
     void update_variable(
             const Vector& update,
             scalar_t lambda,
             Vector& displacement
             );
     //! \brief Set the predictor
     void set_predictor(Vector& displacement);
     //! \brief perform the linesearch
     ParabolicDriverReturnCode linesearch(
             Vector &update,
             Vector &displacements
             );
     //! Compute the residuals for the linesearch
     double compute_residuals_linesearch(
             Vector& update,
             scalar_t lambda,
             Vector& displacement
             );
     double compute_residuals_strang_linesearch(
             Vector &update,
             scalar_t lambda,
             Vector &displacement
             );
 
     scalar_t update_norm(const Vector& update);
 
 
     double m_norm_0;
     double m_current_dt;
     Eigen::VectorXd m_gradient;
     Eigen::VectorXd m_velocity;
     Eigen::VectorXd m_residuals;
     Eigen::VectorXd m_predictor;
     Eigen::SparseMatrix<double> m_jacobian;
 
     sparse_solvers::SparseSolverPtr<Eigen::SparseMatrix<double>, Vector, Vector> m_solver;
     bool m_velocity_is_initialized;
 
 };
 
 } // end namespace dfpmsolver
 } // end namespace specmicp
 
 
 // implementation
 // ==============
 #include "parabolic_driver.inl"
 
 #endif // SPECMICP_DFPMSOLVER_PARABOLICDRIVER_HPP
diff --git a/src/dfpmsolver/parabolic_driver.inl b/src/dfpmsolver/parabolic_driver.inl
index 6440f61..0025ee7 100644
--- a/src/dfpmsolver/parabolic_driver.inl
+++ b/src/dfpmsolver/parabolic_driver.inl
@@ -1,481 +1,510 @@
+/*-------------------------------------------------------
+
+Copyright (c) 2014,2015 Fabien Georget <fabieng@princeton.edu>, Princeton University
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+    * Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+    * Redistributions in binary form must reproduce the above copyright
+      notice, this list of conditions and the following disclaimer in the
+      documentation and/or other materials provided with the distribution.
+    * Neither the name of the Princeton University nor the
+      names of its contributors may be used to endorse or promote products
+      derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+---------------------------------------------------------*/
+
 #include "parabolic_driver.hpp" // for syntaxic coloration only
 #include "utils/log.hpp"
 //#include "utils/sparse_solver.hpp"
 
 namespace specmicp {
 namespace dfpmsolver {
 
 template <class Program>
 void ParabolicDriver<Program>::compute_jacobian(Vector& displacement,
                       Vector& velocity,
                       Eigen::SparseMatrix<scalar_t>& jacobian
                       )
 {
     program().compute_jacobian(displacement, velocity, jacobian, get_options().alpha*m_current_dt);
     jacobian = jacobian*scaling().asDiagonal();
     jacobian.makeCompressed();
 
     get_perfs().nb_call_jacobian += 1;
 }
 
 template <class Program>
 ParabolicDriverReturnCode  ParabolicDriver<Program>::solve_timestep(scalar_t dt, Eigen::VectorXd& displacement)
 {
     initialize_timestep(dt, displacement);
     return restart_timestep(displacement);
 }
 
 template <class Program>
 void  ParabolicDriver<Program>::initialize_timestep(scalar_t dt, Eigen::VectorXd& displacement)
 {
     initialize_scaling();
     m_residuals = Eigen::VectorXd::Zero(get_neq());
     m_current_dt = dt;
     set_predictor(displacement);
     reset_velocity();
     program().apply_bc(dt, displacement, m_velocity);
 
     compute_residuals(displacement, m_velocity, m_residuals);
     m_norm_0 = norm_residuals();
     get_perfs().nb_iterations = 0;
 }
 
 template <class Program>
 void  ParabolicDriver<Program>::set_predictor(Vector& displacement)
 {
     if (get_options().alpha < 1)
         m_predictor = displacement + (1-get_options().alpha)*m_current_dt*m_velocity;
     else
         m_predictor = displacement;
 }
 
 template <class Program>
 scalar_t ParabolicDriver<Program>::update_norm(const Vector& update)
 {
     // l-∞ scaled norm
     scalar_t norm = 0.0;
     for (index_t dof=0; dof<program().get_tot_ndf(); ++dof)
     {
         const index_t id_eq = program().id_equation(dof);
         if (id_eq == no_species or update(id_eq) == 0.0) continue;
         norm = std::max(norm, std::abs(update(id_eq))/(std::max(std::abs(m_velocity(dof)), 1.0/scaling(id_eq))));
     }
     return norm;
 }
 
 template <class Program>
 ParabolicDriverReturnCode  ParabolicDriver<Program>::restart_timestep(Vector& displacement)
 {
     ParabolicDriverReturnCode return_code = ParabolicDriverReturnCode::NotConvergedYet;
 
     //m_solver.reset(nullptr);
 
     Eigen::VectorXd update(get_neq());
     update.setZero();
     get_perfs().current_update = 0;
     bool force_recompute_jacobian = true;
     while (return_code == ParabolicDriverReturnCode::NotConvergedYet)
     {
         compute_residuals(displacement, m_velocity, m_residuals);
         get_perfs().absolute_residual = m_residuals.norm();
         get_perfs().current_residual = m_residuals.norm()/m_norm_0;
         get_perfs().current_update = update_norm(update);
         DEBUG << " NB iterations : " << get_perfs().nb_iterations
                   << " - res : " << get_perfs().current_residual
                   << " - update : " << get_perfs().current_update;
         return_code = check_convergence();
 
         if (return_code != ParabolicDriverReturnCode::NotConvergedYet) break;
         if (m_solver == nullptr)
         {
             m_solver = sparse_solvers::get_sparse_solver<
                     Eigen::SparseMatrix<scalar_t>, Vector, Vector>(get_options().sparse_solver);
             compute_jacobian(displacement, m_velocity, m_jacobian);
             m_solver->analyse_pattern(m_jacobian);
             m_solver->decompose(m_jacobian);
             force_recompute_jacobian =false;
         }
         else if (force_recompute_jacobian
                 or get_perfs().nb_iterations % get_options().quasi_newton == 0)
         {
             compute_jacobian(displacement, m_velocity, m_jacobian);
             m_solver->decompose(m_jacobian);
         }
         get_perfs().nb_iterations += 1;
         m_gradient = m_jacobian.transpose()*m_residuals;
         sparse_solvers::SparseSolverReturnCode retcode = m_solver->solve_scaling(m_residuals, scaling(), update);
         if (retcode != sparse_solvers::SparseSolverReturnCode::Success)
         {
             ERROR << "Error when solving linear system : " << (int) retcode << std::endl;
             return ParabolicDriverReturnCode::ErrorLinearSystem;
         }
         //if (update.norm() < get_options().step_tolerance) return_code = ParabolicDriverReturnCode::ErrorMinimized;
         //else
             return_code = linesearch(update, displacement);
     }
     return return_code;
 
 }
 
 template <class Program>
 ParabolicDriverReturnCode  ParabolicDriver<Program>::check_convergence()
 {
     ParabolicDriverReturnCode termcode = ParabolicDriverReturnCode::NotConvergedYet;
     const int nb_iterations = get_perfs().nb_iterations;
     const scalar_t norm_residuals = get_perfs().current_residual;
     const scalar_t norm_update = get_perfs().current_update;
     //std::cout << "Residuals : " << nb_iterations << " - " << norm_residuals/m_norm_0 << std::endl;
     DEBUG << "Residuals : " << nb_iterations << " - " << norm_residuals/m_norm_0;
     if (norm_residuals < get_options().residuals_tolerance)
     {
         termcode = ParabolicDriverReturnCode::ResidualMinimized;
     }
     else if (get_perfs().absolute_residual < get_options().absolute_tolerance)
     {
         termcode = ParabolicDriverReturnCode::ResidualMinimized;
     }
     else if (nb_iterations > 0 and norm_update > 0.0 and norm_update < 1.01*get_options().step_tolerance)
     {
         if (norm_residuals  > get_options().threshold_stationary_point)
         {
             ERROR << "Stationary point detected !";
             termcode = ParabolicDriverReturnCode::StationaryPoint;
         }
         WARNING << "Error is minimized - may indicate a stationnary point";
         termcode = ParabolicDriverReturnCode::ErrorMinimized;
 
     }
     else if (nb_iterations >  get_options().maximum_iterations)
     {
         ERROR << "Maximum number of iteration reached (" << get_options().maximum_iterations << ")";
         termcode = ParabolicDriverReturnCode::MaxIterations;
     }
     else if (get_perfs().maximum_step_taken)
     {
         get_perfs().nb_consecutive_max_step_taken += 1;
         get_perfs().nb_max_step_taken += 1;
         if (get_perfs().nb_consecutive_max_step_taken == get_options().max_iterations_at_max_length) {
             ERROR << "Divergence detected - Maximum step length taken two many times";
             termcode = ParabolicDriverReturnCode::MaxStepTakenTooManyTimes;
         }
     }
     else
     {
         get_perfs().nb_consecutive_max_step_taken = 0;
     }
     get_perfs().return_code = termcode;
     return termcode;
 }
 
 template <class Program>
 double ParabolicDriver<Program>::compute_residuals_linesearch(
         Vector &update,
         scalar_t lambda,
         Vector &displacement
         )
 {
     Eigen::VectorXd velocity(m_velocity);
     Eigen::VectorXd residual = Eigen::VectorXd::Zero(get_neq());
     program().update_solution(update, lambda, get_options().alpha*m_current_dt, m_predictor, displacement, velocity);
     compute_residuals(displacement, velocity, residual);
     return 0.5*residual.squaredNorm();
 }
 
 template <class Program>
 double ParabolicDriver<Program>::compute_residuals_strang_linesearch(
         Vector &update,
         scalar_t lambda,
         Vector &displacement
         )
 {
     Eigen::VectorXd velocity(m_velocity);
     Eigen::VectorXd residual = Eigen::VectorXd::Zero(get_neq());
     program().update_solution(update, lambda, get_options().alpha*m_current_dt, m_predictor, displacement, velocity);
     compute_residuals(displacement, velocity, residual);
     return update.dot(residual);
 }
 
 
 template <class Program>
 void ParabolicDriver<Program>::update_variable(
         const Vector& update,
         scalar_t lambda,
         Vector& displacement
         )
 {
     program().update_solution(update, lambda, get_options().alpha*m_current_dt,
                               m_predictor, displacement, m_velocity);
 }
 
 template <class Program>
 ParabolicDriverReturnCode ParabolicDriver<Program>::linesearch(
         Vector &update,
         Vector &displacements
         )
 {
     base::is_step_too_long(update);
     get_perfs().maximum_step_taken = false;
 
     scalar_t lambda;
     ParabolicLinesearchReturnCode retcode;
     switch (get_options().linesearch) {
     case ParabolicLinesearch::Bactracking:
         retcode = backtracking_linesearch(update, displacements, lambda);
         break;
     case ParabolicLinesearch::Strang:
         retcode = strang_linesearch(update, displacements, lambda);
         break;
     default:
         throw std::runtime_error("Linesearch type for Parabolic driver is not recognized");
         break;
     }
     if (retcode != ParabolicLinesearchReturnCode::Success)
     {
         return ParabolicDriverReturnCode::LinesearchFailed;
     }
 
     update_variable(update, lambda, displacements);
     update *= lambda;
 
     return ParabolicDriverReturnCode::NotConvergedYet;
 }
 
 namespace internal
 {
 //! \brief Return true if a and b have the same sign
 inline bool have_same_sign(double a, double b)
 {
     return (std::copysign(1., a) * std::copysign(1., b) > 0);
 }
 } // end namespace internal
 
 template <class Program>
 ParabolicLinesearchReturnCode ParabolicDriver<Program>::strang_linesearch(
         Vector& update,
         Vector& displacements,
         scalar_t& lambda
         )
 {
     DEBUG << "Strang linesearch";
     Eigen::VectorXd xp(displacements);
 
     const scalar_t s_tol = 0.5;
     const scalar_t s_max = 2.0;
     const int lin_max = 10;
 
     scalar_t s_b = 0.0;
     scalar_t g_b = 0.5*m_residuals.squaredNorm();
     scalar_t s_a = 1.0;
     scalar_t g_a = compute_residuals_strang_linesearch(update, 1.0, xp);
     scalar_t newtlen = (scaling().asDiagonal()*update).norm();
 
    // const scalar_t s_r = s_a;
     const scalar_t g_r = g_a;
 
     if (std::abs(g_a) <= s_tol*std::abs(g_b))
     {
         DEBUG << "Skip linesearch ";
         lambda = 1.0;
         if (lambda == 1.0 and (newtlen > 0.99 * get_options().maximum_step_length)) {
             get_perfs().maximum_step_taken = true;
         }
         return ParabolicLinesearchReturnCode::Success;
     }
 
     while (internal::have_same_sign(g_a, g_b) and s_a < s_max)
     {
         s_b = s_a;
         s_a = 2*s_a;
         g_b = g_a;
         g_a = compute_residuals_strang_linesearch(update, s_a, xp);
     }
 
     scalar_t g_ = g_a;
     scalar_t g_0 = g_a;
     scalar_t s = s_a;
 
     int l;
     for (l=0; l<lin_max; ++l)
     {
         if (internal::have_same_sign(g_a, g_b) or
                     std::abs(g_) < s_tol*std::abs(g_0)
                     or std::abs(s_a - s_b) < s_tol*(s_a + s_b)/2 )
             break;
 
         s = s_a - g_a * ( s_a - s_b)/(g_a - g_b);
         g_ = compute_residuals_strang_linesearch(update, s, xp);
         if (internal::have_same_sign(g_, g_a))
             g_b = g_b/2.;
         else
         {
             s_b = s_a;
             g_b = g_a;
         }
         s_a = s;
         g_a = g_;
 
     }
     if (l == lin_max) return ParabolicLinesearchReturnCode::MaximumIterations;
     if (g_a >= g_r) {
         WARNING << "Failed to find better update in Strang linesearch";
         //lambda = 0.1*s_r;
         return backtracking_linesearch(update, displacements, lambda);
     }
     lambda = s_a;
     if (lambda == 1.0 and (newtlen > 0.99 * get_options().maximum_step_length)) {
         get_perfs().maximum_step_taken = true;
     }
     return ParabolicLinesearchReturnCode::Success;
 }
 
 template <class Program>
 ParabolicLinesearchReturnCode ParabolicDriver<Program>::backtracking_linesearch(
         Vector& update,
         Vector& displacements,
         scalar_t& lambda_out
         )
 {
     // References
     // ----------
     //    - Algo A6.3.1 : Dennis and Schnabel (1983)
     //    - Nocedal & Wrigth (2006)
     DEBUG << "Linesearch";
     Eigen::VectorXd xp(displacements);
     double fcp;
 
     int retcode = 2; // 2 not converged, 1 problem, 0 success
     const scalar_t alpha = 1e-4;
     scalar_t newtlen = (scaling().asDiagonal()*update).norm();
     scalar_t init_slope = m_gradient.dot(update);
     const scalar_t rellength = update_norm(update);
     const scalar_t minlambda = get_options().step_tolerance / rellength;
     scalar_t lambda = 1.0;
     scalar_t lambda_prev = lambda;
 
     scalar_t merit_value = 0.5*m_residuals.squaredNorm();
     // new residual
     fcp = compute_residuals_linesearch(update, lambda, xp);
     // Skip linesearch if enough progress is done
     // ------------------------------------------
     if (fcp < get_options().coeff_accept_newton_step *merit_value)
     {
         DEBUG << "Skip linesearch ";
         lambda_out = 1.0;
         return ParabolicLinesearchReturnCode::Success;
     }
     // The linesearch
     // --------------
     scalar_t fc = merit_value;
     scalar_t fcp_prev;
     int cnt = 0;
     do
     {
         SPAM << "cnt : " <<cnt << " - lambda : " << lambda << " # " << fc << " # " << fcp << " # " << init_slope;
         if (fcp <= fc + alpha*lambda*init_slope) //pg760 Fachinei2003
         {
             retcode = 0;
             if (lambda == 1.0 and (newtlen > 0.99 * get_options().maximum_step_length)) {
                 get_perfs().maximum_step_taken = true;
             }
             break;
         }
         else if (lambda < minlambda)
         {
             retcode = 0;
             lambda = minlambda;
             //retcode = 1;
             break;
         }
         else
         {
             //WARNING << "denom : " << fcp - fc -init_slope;
             // Select a new step length
             // - - - - - - - - - - - -
             double lambdatmp;
             if (cnt == 0) { // only a quadratic at the first
                 lambdatmp = - init_slope / (2*(fcp - fc -init_slope));
             }
             else
             {
                 const scalar_t factor = 1.0 /(lambda - lambda_prev);
                 const scalar_t x1 = fcp - fc - lambda*init_slope;
                 const scalar_t x2 = fcp_prev - fc - lambda_prev*init_slope;
 
                 const scalar_t a = factor * ( x1/(lambda*lambda) - x2/(lambda_prev*lambda_prev));
                 const scalar_t b = factor * ( -x1*lambda_prev/(lambda*lambda) + x2*lambda/(lambda_prev*lambda_prev));
 
                 if (a == 0)
                 { // cubic interpolation is in fact a quadratic interpolation
                     lambdatmp = - init_slope/(2*b);
                 }
                 else
                 {
                     const scalar_t disc = b*b-3*a*init_slope;
                     lambdatmp = (-b+std::sqrt(disc))/(3*a);
                 }
                 if (lambdatmp > 0.5*lambda ) lambdatmp = 0.5*lambda;
             }
             //WARNING << "lambdatmp : " << lambdatmp;
             lambda_prev = lambda;
             fcp_prev = fcp;
             if (lambdatmp < 0.1*lambda) {
                 lambda = 0.1 * lambda;
             } else {
                 lambda = lambdatmp;
             }
         }
         if (not std::isfinite(lambda))
         {
             ERROR << "Lambda is non finite - we stop";
             return ParabolicLinesearchReturnCode::Divergence;
         }
         fcp = compute_residuals_linesearch(update, lambda, xp);
         //xp.velocity = x.velocity;
         ++cnt;
     } while(retcode == 2 and cnt < 50);
     //WARNING << "Lambda : " << lambda << " - iterations : " << cnt;
     if (cnt == 50)
     {
         ERROR << "Too much linesearch iterations ! We stop";
         return ParabolicLinesearchReturnCode::MaximumIterations;
     }
     lambda_out = lambda;
     switch (retcode) {
     case 0:
         return ParabolicLinesearchReturnCode::Success;
         break;
     case 1:
         return ParabolicLinesearchReturnCode::LambdaTooSmall;
     default:
         return ParabolicLinesearchReturnCode::NotSupposedToHappen;
         break;
     }
 }
 
 template <class Program>
 void ParabolicDriver<Program>::set_velocity(Vector& velocity_vector)
 {
     m_velocity.resize(program().get_tot_ndf());
     m_velocity.setZero();
     for (index_t dof=0; dof<program().get_tot_ndf(); ++dof)
     {
         if (program().id_equation(dof) == no_equation)
         {
             m_velocity(dof) = velocity_vector(dof);
         }
     }
 }
 
 template <class Program>
 void ParabolicDriver<Program>::reset_velocity()
 {
     for (index_t dof=0; dof<program().get_tot_ndf(); ++dof)
     {
         if (program().id_equation(dof) == no_equation) continue;
         m_velocity(dof) = 0.0;
 
     }
 }
 
 } // end namespace dfpmsolver
 } // end namespace specmicp
diff --git a/src/dfpmsolver/parabolic_program.hpp b/src/dfpmsolver/parabolic_program.hpp
index 3ce7e18..8fcf9b6 100644
--- a/src/dfpmsolver/parabolic_program.hpp
+++ b/src/dfpmsolver/parabolic_program.hpp
@@ -1,58 +1,87 @@
+/*-------------------------------------------------------
+
+Copyright (c) 2014,2015 Fabien Georget <fabieng@princeton.edu>, Princeton University
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+    * Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+    * Redistributions in binary form must reproduce the above copyright
+      notice, this list of conditions and the following disclaimer in the
+      documentation and/or other materials provided with the distribution.
+    * Neither the name of the Princeton University nor the
+      names of its contributors may be used to endorse or promote products
+      derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+---------------------------------------------------------*/
+
 #ifndef SPECMICP_DFPMSOLVER_PARABOLICPROGRAM_HPP
 #define SPECMICP_DFPMSOLVER_PARABOLICPROGRAM_HPP
 
 #include "common.hpp"
 #include <Eigen/Sparse>
 #include "dfpm_program.hpp"
 
 namespace specmicp {
 namespace dfpmsolver {
 
 //! Concept class for a program
 template <class Derived>
 class ParabolicProgram: DFPMProgram<ParabolicProgram<Derived>>
 {
 public:
     Derived* derived() {static_cast<Derived*>(this);}
 
     //! \brief Compute the residuals
     void compute_residuals(const Vector& displacement,
                            const Vector& velocity,
                            Vector& residual
                            )
     {
         derived()->compute_residuals(displacement, velocity, residual);
     }
     //! \brief Compute the jacobian
     void compute_jacobian(Vector& displacement,
                           Vector& velocity,
                           Eigen::SparseMatrix<scalar_t>& jacobian,
                           scalar_t alphadt
                           )
     {
         derived()->compute_jacobian(displacement, velocity, jacobian, alphadt);
     }
     //! \brief Update the solutions
     void update_solution(const Vector& update,
                          scalar_t lambda,
                          scalar_t alpha_dt,
                          Vector& predictor,
                          Vector& displacement,
                          Vector& velocity)
     {
         derived()->update_solution(update, lambda, alpha_dt, predictor, displacement, velocity);
     }
     //! \brief Apply boundary conditions to the velocity vector
     //!
     //! by default do nothing.
     void apply_bc(scalar_t dt,
                   const Vector& displacement,
                   Vector& velocity)
     {}
 
 };
 
 } // end namespace dfpmsolver
 } // end namespace specmicp
 
 #endif // SPECMICP_DFPMSOLVER_PARABOLICPROGRAM_HPP
diff --git a/src/dfpmsolver/parabolic_structs.hpp b/src/dfpmsolver/parabolic_structs.hpp
index ad05aa3..544a82a 100644
--- a/src/dfpmsolver/parabolic_structs.hpp
+++ b/src/dfpmsolver/parabolic_structs.hpp
@@ -1,68 +1,97 @@
+/*-------------------------------------------------------
+
+Copyright (c) 2014,2015 Fabien Georget <fabieng@princeton.edu>, Princeton University
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+    * Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+    * Redistributions in binary form must reproduce the above copyright
+      notice, this list of conditions and the following disclaimer in the
+      documentation and/or other materials provided with the distribution.
+    * Neither the name of the Princeton University nor the
+      names of its contributors may be used to endorse or promote products
+      derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+---------------------------------------------------------*/
+
 #ifndef SPECMICP_DFPMSOLVER_PARABOLICSTRUCTS_HPP
 #define SPECMICP_DFPMSOLVER_PARABOLICSTRUCTS_HPP
 
 #include "driver_structs.hpp"
 
 namespace specmicp {
 namespace dfpmsolver {
 
 enum class ParabolicLinesearch
 {
     Bactracking, // Bactracking linesearch
     Strang       // Strang Linesearch
 };
 
 enum class ParabolicLinesearchReturnCode
 {
     NotSupposedToHappen,
     MaximumIterations,
     LambdaTooSmall,
     Divergence,
     Success
 
 };
 
 //! \brief Options of a parabolic driver
 //!
 struct ParabolicDriverOptions: public DriverOptions
 {
     scalar_t alpha;                 //!< Implicit/Cranck-Nicholson parameter
     ParabolicLinesearch linesearch; //!< The linesearch to use
     int quasi_newton;            //!< Number of iterations without reforming the jacobian
 
     ParabolicDriverOptions():
         DriverOptions(),
         alpha(1.0),
         linesearch(ParabolicLinesearch::Bactracking),
         quasi_newton(1)
     {}
 };
 
 //! \brief Return codes
 enum class ParabolicDriverReturnCode
 {
     LinesearchFailed = -5,         //!< Linesearch has failed (usually indicates a bad system)
     MaxIterations = -4,            //!< Maximum number of iterations reached
     MaxStepTakenTooManyTimes = -3, //!< Maximum step taken too many times (divergence)
     ErrorLinearSystem = -2,        //!< Error when solving the linear system
     StationaryPoint = -1,          //!< Stationnary points are detected
     NotConvergedYet = 0,           //!< Problem is not converged
     ResidualMinimized = 1,         //!< The residual is minimized (Success)
     ErrorMinimized = 2             //!< Error is minimized (may be good)
 };
 
 //! \brief Performance of the parabolic driver
 struct ParabolicDriverPerformance: public DriverPerformance
 {
     ParabolicDriverReturnCode return_code;
 
     ParabolicDriverPerformance():
         DriverPerformance(),
         return_code(ParabolicDriverReturnCode::NotConvergedYet)
     {}
 };
 
 } // end namespace dfpmsolver
 } // end namespace specmicp
 
 #endif // SPECMICP_DFPMSOLVER_PARABOLICSTRUCTS_HPP
diff --git a/src/micpsolver/estimate_cond_number.hpp b/src/micpsolver/estimate_cond_number.hpp
index 22e43fe..00356be 100644
--- a/src/micpsolver/estimate_cond_number.hpp
+++ b/src/micpsolver/estimate_cond_number.hpp
@@ -1,118 +1,114 @@
 /*-------------------------------------------------------
 
- - Module : micpsolver
- - File : estimate_cond_number.hpp
- - Author : Fabien Georget
-
-Copyright (c) 2014, Fabien Georget <fabieng@princeton.edu>, Princeton University
+Copyright (c) 2014,2015 Fabien Georget <fabieng@princeton.edu>, Princeton University
 All rights reserved.
 
 Redistribution and use in source and binary forms, with or without
 modification, are permitted provided that the following conditions are met:
     * Redistributions of source code must retain the above copyright
       notice, this list of conditions and the following disclaimer.
     * Redistributions in binary form must reproduce the above copyright
       notice, this list of conditions and the following disclaimer in the
       documentation and/or other materials provided with the distribution.
     * Neither the name of the Princeton University nor the
       names of its contributors may be used to endorse or promote products
       derived from this software without specific prior written permission.
 
 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
 ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 ---------------------------------------------------------*/
 
 #ifndef SPECMICP_MICPSOLVER_ESTIMATECONDNUMBER_HPP
 #define SPECMICP_MICPSOLVER_ESTIMATECONDNUMBER_HPP
 
 #include <Eigen/Core>
 
 //! \file estimate_cond_number.hpp Estimate the condition number of a matrix
 
 
 namespace specmicp {
 
 //! \namespace micpsolver Namespace for the MiCP Solver
 namespace micpsolver {
 
 //! \brief Estimate the condition number of a dense square triangular matrix
 //!
 //! References :
 //!     - \cite Cline1979
 //!     - \cite Hager1984
 //!
 //! @param tmatrix  a triangular view of a dense matrix
 //! @param maxit    maximum number of iterations done by the algorithm (2 triangular solve by iteration)
 //!
 template <class MatrixType, unsigned int mode>
 double estimate_condition_number(Eigen::TriangularView<MatrixType, mode> tmatrix, int maxit=10)
 {
     const int n = tmatrix.cols();
     Eigen::VectorXd x = 1/n*Eigen::VectorXd::Ones(n);
     Eigen::VectorXd y(n);
     int cnt  = 0;
     y = tmatrix.solve(x);
     while (cnt < maxit)
     {
         for (int i=0; i<n; ++i)
         {
             if (y(i) >= 0) y(i) = 1;
             else y(i) = -1;
         }
         tmatrix.solveInPlace(y);
         y.reverseInPlace(); // transpose
         int j;
         const double maxi = y.array().abs().maxCoeff(&j);
         const double gamma = y.dot(x);
         if (maxi <= gamma) break; // This is a local maximum
         x= Eigen::VectorXd::Zero(n);
         x(j) = 1;
         y = tmatrix.solve(x);
         ++cnt;
     }
     // norm tmatrix
     // ------------
     double nnorm;
     if (mode == Eigen::Lower)
     {
         nnorm = std::abs(tmatrix(0, 0));
         for (int i=1; i<n; ++i)
         {
             double normrow = 0;
             for (int j=0; j<i+1; ++j)
             {
                 normrow += std::abs(tmatrix(i, j));
             }
             nnorm = std::max(nnorm, normrow);
         }
     }
     else if (mode == Eigen::Upper)
     {
         nnorm = std::abs(tmatrix(n-1, n-1));
         for (int i=n-2; i>-1; --i)
         {
             double normrow = 0;
             for (int j=i; j<n; ++j)
             {
                 normrow += std::abs(tmatrix(i, j));
             }
             nnorm = std::max(nnorm, normrow);
         }
     }
     // Return ||A||*||A^-1||
     return nnorm*x.lpNorm<1>();
 }
 
 } // end namespace micpsolver
 } // end namespace specmicp
 
 #endif // SPECMICP_MICPSOLVER_ESTIMATECONDNUMBER_HPP
diff --git a/src/micpsolver/micpprog.hpp b/src/micpsolver/micpprog.hpp
index 339f7d4..adb5033 100644
--- a/src/micpsolver/micpprog.hpp
+++ b/src/micpsolver/micpprog.hpp
@@ -1,113 +1,109 @@
 /*-------------------------------------------------------
 
- - Module : micpsolver
- - File : micpprog.hpp
- - Author : Fabien Georget
-
-Copyright (c) 2014, Fabien Georget <fabieng@princeton.edu>, Princeton University
+Copyright (c) 2014,2015 Fabien Georget <fabieng@princeton.edu>, Princeton University
 All rights reserved.
 
 Redistribution and use in source and binary forms, with or without
 modification, are permitted provided that the following conditions are met:
     * Redistributions of source code must retain the above copyright
       notice, this list of conditions and the following disclaimer.
     * Redistributions in binary form must reproduce the above copyright
       notice, this list of conditions and the following disclaimer in the
       documentation and/or other materials provided with the distribution.
     * Neither the name of the Princeton University nor the
       names of its contributors may be used to endorse or promote products
       derived from this software without specific prior written permission.
 
 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
 ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 ---------------------------------------------------------*/
 
 #ifndef SPECMICP_MICPSOLVER_MICPPROG_HPP
 #define SPECMICP_MICPSOLVER_MICPPROG_HPP
 
 #include "common.hpp"
 
 //! \file micpprog.hpp The static interface of a MiCP solver
 
 namespace specmicp {
 namespace micpsolver {
 
 //! \class MiCPProg
 //! \brief A base clase for a MiCP program
 //!
 //! This class described a static interface.
 //! Any MiCP program should derived from this class and implement its methods
 template <class Derived>
 class MiCPProg
 {
 public:
     //! \brief Return the derived class
     Derived& derived() {return static_cast<Derived*>(*this);}
 
 
     //! \brief Return the number of variables
     //!
     //! Sould be implemented by the program
     index_t total_variables() {return derived->total_variables();}
     //! \brief Return the number of free variables
     //!
     //! Sould be implemented by the variables
     //!
     //! The free variables are the variables not subjected to the complementarity condition.
     index_t nb_free_variables() {return derived->total_variables();}
     //! \brief Return the number of constrained variables
     //!
     //! Not need to implemented this method by the program.
     index_t nb_complementarity_variables() {return total_variables() - nb_free_variables();}
 
     //! \brief Return the residuals
     //!
     //! \param[in] x the variables
     //! \param[out] residual the residuals
     void get_residuals(const Vector& x,
                        Vector& residual);
 
     //! \brief Return the jacobian
     //!
     //! \param[in] x the variables
     //! \param[out] jacobian the jacobian
     void get_jacobian(Vector& x,
                       Matrix& jacobian);
 
     //! \brief Called at the beginning of an iteration
     //!
     //! \param x the variables
     //! \param norm_residual norm of the residuals of the previous iteration
     //! \return A boolean indicating if the system can have converged
     //!
     //! Return true by default
     bool hook_start_iteration(const Vector& x, scalar_t norm_residual) {return true;}
     //! \brief Return the maximum update length that the algorithm can take
     //!
     //! This is usually used to impose nonnegativity conditions
     //!
     //! \param x the variables
     //! \param update solution of the linear system
     //! \return multiplicating factor to scale the update
     scalar_t max_lambda(const Vector& x, const Vector& update) {return 1.0;}
 
 
     //! \brief Return the value used for infinity
     static double infinity() {return HUGE_VAL;}
 
 
 };
 
 } // end namespace micpsolver
 } // end namespace specmicp
 
 #endif // SPECMICP_MICPSOLVER_MICPPROG_HPP
diff --git a/src/micpsolver/micpsolver.hpp b/src/micpsolver/micpsolver.hpp
index a8bf2f7..a7a3e53 100644
--- a/src/micpsolver/micpsolver.hpp
+++ b/src/micpsolver/micpsolver.hpp
@@ -1,215 +1,210 @@
 /*-------------------------------------------------------
 
- - Module : micpsolver
- - File : micpsolver.hpp
- - Author : Fabien Georget
-
 Copyright (c) 2014,2015 Fabien Georget <fabieng@princeton.edu>, Princeton University
 All rights reserved.
 
 Redistribution and use in source and binary forms, with or without
 modification, are permitted provided that the following conditions are met:
     * Redistributions of source code must retain the above copyright
       notice, this list of conditions and the following disclaimer.
     * Redistributions in binary form must reproduce the above copyright
       notice, this list of conditions and the following disclaimer in the
       documentation and/or other materials provided with the distribution.
     * Neither the name of the Princeton University nor the
       names of its contributors may be used to endorse or promote products
       derived from this software without specific prior written permission.
 
 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
 ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 ---------------------------------------------------------*/
-
 #ifndef SPECMIC_MICPSOLVER_MICPSOLVER_HPP
 #define SPECMIC_MICPSOLVER_MICPSOLVER_HPP
 
 #include "common.hpp"
 #include "micpsolver_base.hpp"
 #include "ncp_function.hpp"
 
 //! \file micpsolver.hpp The MiCP solver
 
 namespace specmicp {
 namespace micpsolver {
 
 //! \class MiCPSolver
 //! \brief The MiCP Solver
 //!
 //! Solve
 //!     - \f$ G(u, v) = 0\f$
 //!     - \f$ 0 \leq v \perp H(u,v) \geq 0 \f$
 //!
 //! \tparam program_t a subclass of MiCPProg
 //!
 //! References :
 //!     - \cite Munson2001
 //!     - \cite Facchinei2003
 //!
 template <class program_t>
 class MiCPSolver: public MiCPSolverBaseProgram<program_t>
 {
 public:
     using base = MiCPSolverBaseProgram<program_t>;
     using base::get_options;
     using base::get_program;
     using base::get_perfs;
     using base::get_neq;
     using base::get_neq_free;
 
     //! \brief Constructor
     //!
     //! \param prog smart pointer toward an instance of a program_t to solve
     MiCPSolver(std::shared_ptr<program_t> prog):
         MiCPSolverBaseProgram<program_t>(prog),
         m_residuals(prog->total_variables()),
         m_phi_residuals(Vector::Zero(prog->total_variables())),
         m_jacobian(prog->total_variables(),prog ->total_variables())
     {}
 
     // Merit function
     // ##############
 
     // Residuals and jacobian
     // ----------------------
 
     //! \brief Compute the residuals, use internal storage
     //!
     //! \param[in] x the variables
     void compute_residuals(const Vector& x)
     {
         base::compute_residuals(x, m_residuals);
     }
     //! \brief Compute the jacobian
     //!
     //! Assumes that the residual have been computed before
     //!
     //! \param[in] x the variables
     void compute_jacobian(Vector& x)
     {
         base::compute_jacobian(x, m_jacobian);
     }
     //! \brief Reformulation of the residuals
     //!
     //! Reformulate the problem - assumes that r, the residual, has been computed before
     //!
     //! \param[in] x the variables
     //! \param[in] r the residuals
     //! \param[out] r_phi a vector of size neq, which will contain the reformulated residuals
     void reformulate_residuals(const Vector& x,
                                const Vector& r,
                                Vector& r_phi);
     //! \brief Reformulation of the residuals *inplace*
     //!
     //! \param[in] x the variables
     //! \param[in,out] r the residual, will contain the reformulated residuals
     void reformulate_residuals_inplace(const Vector &x,
                                        Vector &r);
     //! \brief Reformulation of the jacobian
     //!
     //! r is the original vector of residuals (not reformulated)
     void reformulate_jacobian(const Vector& x) {
         base::reformulate_jacobian_cck(x, m_residuals, m_jacobian);
     }
 
     // Algorithm
     // #########
 
     //! \brief Solver the program using x as initial guess
     //!
     //! \param[in,out] x the initial guess, as output contains the solution (from the last iteration)
     MiCPSolverReturnCode solve(Vector& x);
 
     //! \brief Setup the residuals
     //!
     //! \param[in] x the current solution
     void setup_residuals(const Eigen::VectorXd& x) {
         compute_residuals(x);
         reformulate_residuals(x, m_residuals, m_phi_residuals);
     }
     //! \brief Setup the jacobian
     //!
     //! \param[in] x the current solution
     void setup_jacobian(Eigen::VectorXd& x) {
         compute_jacobian(x);
         reformulate_jacobian(x);
         m_grad_phi = m_jacobian.transpose() * m_phi_residuals;
     }
     //! \brief Solve the Newton system
     //!
     //! The system will be scaled before being solved, may be expensive and not necessary.
     //! Do disable the scaling, disable the corresponding options in #MiCPSolverOptions.
     //! It assumes that the Newton system has been formed
     //!
     //! \param[out] update the update to apply to the solution
     //!
     //! \sa search_direction_calculation_no_scaling.
     MiCPSolverReturnCode search_direction_calculation(Vector& update);
 
     //! \brief Solve the Newton system - does not scale the jacobian
     //!
     //! The system will not be scaled.
     //! It assumes that the Newton system has been formed
     //!
     //! \param[out] update the update to apply to the solution
     //!
     //! \sa search_direction_scaling
     MiCPSolverReturnCode search_direction_calculation_no_scaling(Vector &update);
 
     //! \brief Linesearch
     //!
     //! It is a backtracking linesearch.
     //! If the correct option is set, this is a nonmonotone linesearch.
     //!
     //! \param[in] x the current solution
     //!
     //! References :
     //!     - \cite Dennis1983
     //!     - \cite Munson2001
     //!
     //! \sa #MiCPSolverOptions
     int linesearch(Eigen::VectorXd& update, Eigen::VectorXd& x);
 
     //! \brief Crashing
     //!
     //! This function improves, if possible, the initial guess
     //!
     //! \param[in] x the current solution
     //!
     //! Reference :
     //!     - \cite Munson2001
     void crashing(Vector &x);
 
 private:
 
     // Residuals and jacobian
     Eigen::VectorXd m_residuals;        //!< The residuals
     Eigen::VectorXd m_phi_residuals;    //!< The reformulated residuals
     Eigen::VectorXd m_grad_phi;         //!< The gradient of the reformulated residuals
     Eigen::MatrixXd m_jacobian;         //!< The jacobian
 
     std::vector<scalar_t> m_max_merits;   //!< Contains the m best value of the merit function
 
     bool m_gradient_step_taken; //!< True if the update was computed using the gradient
 
 };
 
 } // end namespace micpsolver
 } // end namespace specmicp
 
 // ###############//
 // Implementation //
 // ###############//
 #include "micpsolver.inl"
 
 #endif // SPECMIC_MICPSOLVER_MICPSOLVER_HPP
diff --git a/src/micpsolver/micpsolver.inl b/src/micpsolver/micpsolver.inl
index d03b2b4..fc671b7 100644
--- a/src/micpsolver/micpsolver.inl
+++ b/src/micpsolver/micpsolver.inl
@@ -1,449 +1,445 @@
 /*-------------------------------------------------------
 
- - Module : micpsolver
- - File : micpsolver.inl
- - Author : Fabien Georget
-
 Copyright (c) 2014,2015 Fabien Georget <fabieng@princeton.edu>, Princeton University
 All rights reserved.
 
 Redistribution and use in source and binary forms, with or without
 modification, are permitted provided that the following conditions are met:
     * Redistributions of source code must retain the above copyright
       notice, this list of conditions and the following disclaimer.
     * Redistributions in binary form must reproduce the above copyright
       notice, this list of conditions and the following disclaimer in the
       documentation and/or other materials provided with the distribution.
     * Neither the name of the Princeton University nor the
       names of its contributors may be used to endorse or promote products
       derived from this software without specific prior written permission.
 
 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
 ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 ---------------------------------------------------------*/
 
 #ifndef SPECMIC_MICPSOLVER_MICPSOLVER_HPP
 #include "micpsolver.hpp" // for syntaxic coloration...
 #endif // SPECMIC_MICPSOLVER_MICPSOLVER_HPP
 
 #include <Eigen/QR>
 #include "estimate_cond_number.hpp"
 #include "utils/log.hpp"
 
 
 //! \file micpsolver.inl implementation of the MiCP solver
 
 namespace specmicp {
 namespace micpsolver {
 
 // Main algorithm
 // ##############
 
 template <class program_t>
 MiCPSolverReturnCode MiCPSolver<program_t>::solve(Vector &x)
 {
     int cnt = 0;
     if (get_options().use_crashing) crashing(x);
     else setup_residuals(x);
     MiCPSolverReturnCode retcode = MiCPSolverReturnCode::NotConvergedYet;
     Eigen::VectorXd update(get_neq());
     while (retcode == MiCPSolverReturnCode::NotConvergedYet)
     {
         DEBUG << "Iteration : " << cnt;
         // (S.0) Initialization of the iteration
         // this is a hook for simultaneous fixed-point iterations
         // implemented to solve the non-ideality model
         bool may_have_converged = get_program()->hook_start_iteration(x, m_phi_residuals.norm());
         // (S.1) Check the convergence
         setup_residuals(x);
         get_perfs().current_residual = m_phi_residuals.norm();
         DEBUG << "Norm residuals : " << get_perfs().current_residual;
         retcode = base::check_convergence(cnt, update, x, m_phi_residuals, may_have_converged);
         get_perfs().return_code = retcode;
         if (retcode != MiCPSolverReturnCode::NotConvergedYet) break;
         ++cnt;
         // (S.2) Compute the jacobian and solve the linear problem
         setup_jacobian(x);
         if(get_options().use_scaling)
             search_direction_calculation(update);
         else
             search_direction_calculation_no_scaling(update);
         // (S.3) Linesearch
         int termcode = linesearch(update, x);
         if (termcode != 0) retcode = MiCPSolverReturnCode::LinesearchFailure;
         get_perfs().return_code = retcode;
         get_perfs().current_update = update.norm();
         DEBUG << "Return LineSearch : " << termcode;
         base::projection(x); // project x to the positive quadrant
         get_perfs().nb_iterations = cnt;
     }
     return retcode;
 }
 
 template <class program_t>
 MiCPSolverReturnCode MiCPSolver<program_t>::search_direction_calculation(Eigen::VectorXd& update)
 {
     Vector rscaler(Vector::Ones(m_jacobian.cols()));
     Vector cscaler(Vector::Ones(m_jacobian.rows()));
     base::scaling_jacobian(m_jacobian, m_phi_residuals, rscaler, cscaler);
     m_jacobian = rscaler.asDiagonal() * (m_jacobian) * cscaler.asDiagonal();
     Eigen::ColPivHouseholderQR<Matrix> solver(m_jacobian.rows(), m_jacobian.cols()); // it needs to be correctly initialized
     m_gradient_step_taken = false;
     int m;
     for (m=0; m<get_options().max_factorization_step; ++m)
     {
         const scalar_t lambda = get_options().factor_gradient_search_direction;
         solver.compute(m_jacobian);
         get_perfs().nb_factorization += 1;
         if (solver.info() != Eigen::Success or not solver.isInvertible())
         {
             DEBUG << "Solver.info : " << solver.info() << " - is invertible : " << solver.isInvertible();
             ERROR << "System cannot be solved, we try a perturbation";
             m_gradient_step_taken = true;
             m_jacobian.diagonal() += lambda*rscaler.cwiseProduct(cscaler);
             continue;
         }
         if (get_options().condition_limit > 0)
         {
             scalar_t cond = estimate_condition_number(solver.matrixR().triangularView<Eigen::Upper>());
             if (cond > get_options().condition_limit)
             {
                 m_gradient_step_taken = true;
                 m_jacobian.diagonal() += lambda*rscaler.cwiseProduct(cscaler);
                 continue;
             }
         }
         update = solver.solve(-rscaler.cwiseProduct(m_phi_residuals + m*lambda*m_grad_phi));
         update  = cscaler.cwiseProduct(update);
         if (get_options().factor_descent_condition < 0 ) break; // we have a solution
         // else we compute the descent condition
         scalar_t descent_cond = m_grad_phi.dot(update);
         scalar_t norm_grad = m_grad_phi.norm();
         scalar_t norm_update = update.norm();
 
         if ((descent_cond <= -get_options().factor_descent_condition*std::min(
                      std::pow(norm_update,2),std::pow(norm_update,3)))
                and (descent_cond <= -get_options().factor_descent_condition*std::min(
                         std::pow(norm_grad,2),std::pow(norm_grad,3)))
              )
             break; // we have a solution !
         m_gradient_step_taken = true;
 
         m_jacobian.diagonal() += lambda*rscaler.cwiseProduct(cscaler);
     }
     DEBUG << "Gradient step : m = " << m;
     if (m == get_options().max_factorization_step) {
         INFO << "Full gradient step taken !";
         update = -m_grad_phi;
     }
     return MiCPSolverReturnCode::NotConvergedYet;
 }
 
 template <class program_t>
 MiCPSolverReturnCode MiCPSolver<program_t>::search_direction_calculation_no_scaling(
         Vector& update
         )
 {
     Eigen::ColPivHouseholderQR<Eigen::MatrixXd> solver(m_jacobian.rows(), m_jacobian.cols()); // it needs to be correctly initialized
     // if everything is ok, this is the only decomposition
     m_gradient_step_taken = false;
     int m; // this is an index that increase the contribution of the gradient in the solution
     // the pure Newton solution is when m=0
     for (m=0; m<get_options().max_factorization_step; ++m)
     {
         const scalar_t lambda = get_options().factor_gradient_search_direction;
         solver.compute(m_jacobian); // we need to recompute it (?)
         get_perfs().nb_factorization += 1;
         // Check that the decomposition was ok
         if (solver.info() != Eigen::Success or not solver.isInvertible())
         {
             DEBUG << "Solver.info : " << solver.info() << " (should be " << Eigen::Success
                   << ") - is invertible : " << solver.isInvertible() << " (sould be " << true << ")";
             ERROR << "System cannot be solved, we try a perturbation";
             m_gradient_step_taken = true;
             m_jacobian.diagonal() += Eigen::VectorXd::Constant(m_jacobian.rows(), lambda);
             continue;
         }
         // Estimate the condition number
         if (get_options().condition_limit > 0)
         {
             scalar_t cond = estimate_condition_number(solver.matrixR().triangularView<Eigen::Upper>());
 
             if (cond > get_options().condition_limit)
             {
                 // add the perturbation
                 m_gradient_step_taken = true;
                 m_jacobian.diagonal() += Eigen::VectorXd::Constant(m_jacobian.rows(), lambda);
             }
         }
         update = solver.solve(-(m_phi_residuals + m*lambda*m_grad_phi));
 
         if (get_options().factor_descent_condition < 0 ) break; // we have a solution
 
         scalar_t descent_cond = m_grad_phi.dot(update);
         scalar_t norm_grad = m_grad_phi.norm();
         scalar_t norm_update = update.norm();
 
         if ( (descent_cond <= -get_options().factor_descent_condition*std::min(
                          std::pow(norm_update,2),std::pow(norm_update,3)))
              and (descent_cond <= -get_options().factor_descent_condition*std::min(
                              std::pow(norm_grad,2),std::pow(norm_grad,3)))
             )
             break; // we have a solution !
 
         // add the perturbation
         m_gradient_step_taken = true;
         m_jacobian.diagonal() += Eigen::VectorXd::Constant(m_jacobian.rows(), lambda);
     }
     DEBUG << "Gradient step : m = " << m;
     if (m_gradient_step_taken && m == get_options().max_factorization_step) {
         INFO << "Full gradient step taken !";
         update = -m_grad_phi;
     }
     return MiCPSolverReturnCode::NotConvergedYet;
 }
 
 template <class program_t>
 void MiCPSolver<program_t>::crashing(Vector& x)
 {
     // steepest descent direction algorithm
     DEBUG << "Crashing ";
     const scalar_t beta = 0.5;
     const scalar_t sigma = 1e-5;
     int cnt = 0;
     while (cnt < 10)
     {
         setup_residuals(x);
         setup_jacobian(x);
         m_grad_phi = m_jacobian.transpose()*m_phi_residuals;
         Vector xp(get_neq());
         int l=0;
         const int maxl = 10;
         while (l<maxl)
         {
             xp = x - std::pow(beta, l)*m_grad_phi;
             for (int i=get_neq_free(); i<get_neq(); ++i)
             {
                 if (xp(i) < 0) xp(i) = 0;
             }
             Vector new_res(get_neq());
             base::compute_residuals(x, new_res);
             reformulate_residuals_inplace(x, new_res);
             scalar_t test = 0.5*(new_res.squaredNorm() - m_phi_residuals.squaredNorm())  + sigma*m_grad_phi.dot(x - xp);
             if (test <= 0) break;
             ++l;
         }
         if (l == maxl) break;
         x = xp;
 
         ++cnt;
     }
     get_perfs().nb_crashing_iterations = cnt;
     DEBUG << "Crashing iterations : " << cnt;
     m_max_merits.reserve(4);
     SPAM << "Solution after crashing \n ------ \n " << x << "\n ----- \n";
 }
 
 // Others
 // ######
 
 template <class program_t>
 void MiCPSolver<program_t>::reformulate_residuals(
         const Vector &x,
         const Vector &r,
         Vector &r_phi
         )
 {
     // reformulation with copy from r to r_phi
     r_phi.resizeLike(r);
     r_phi.block(0, 0, get_neq_free(), 1) = r.block(0, 0, get_neq_free(), 1);
     for (index_t i =  get_neq_free(); i<get_neq(); ++i)
     {
         r_phi(i) = penalized_fisher_burmeister(x(i), r(i), get_options().penalization_factor);
     }
 }
 
 template <class program_t>
 void MiCPSolver<program_t>::reformulate_residuals_inplace(
         const Vector& x,
         Vector& r
         )
 {
     for (index_t i =  get_neq_free(); i<get_neq(); ++i)
     {
         r(i) = penalized_fisher_burmeister(x(i), r(i), get_options().penalization_factor);
     }
 }
 
 template <class program_t>
 int MiCPSolver<program_t>::linesearch(Eigen::VectorXd& p, Eigen::VectorXd& x)
 {
     // References
     // ----------
     //    - Algo A6.3.1 : Dennis and Schnabel (1983)
     //    - Munson et al. (2001)
     //    - Facchinei (2003)
     //    - Nocedal & Wrigth (2006)
     DEBUG << "Linesearch";
     Eigen::VectorXd xp(get_neq());
     Eigen::VectorXd new_res(get_neq());
     double fcp;
 
     get_perfs().max_taken = false;
     int retcode = 2;
     const double alpha = 1e-4;
     double newtlen = base::is_step_too_long(p);
     double init_slope = m_grad_phi.dot(p);
     double rellength = std::abs(p(0));
     for (int i=1; i<get_neq(); ++i)
     {
         rellength = std::max(rellength, std::abs(p(i)));
     }
     double minlambda = get_options().steptol / rellength;
     double lambda = get_program()->max_lambda(x, p);
     double lambda_prev = lambda;
 
     // non monotone linesearch
     // =======================
 
     double merit_value = 0.5*m_phi_residuals.squaredNorm();
     // new residual
     xp = x + lambda*p;
     base::compute_residuals(xp, new_res);
     reformulate_residuals_inplace(xp, new_res);
     fcp = 0.5*new_res.squaredNorm();
 
     // Skip linesearch if enough progress is done
     // ------------------------------------------
     if (fcp < get_options().coeff_accept_newton_step *merit_value)
     {
         if (m_max_merits.size() > 0) m_max_merits[m_max_merits.size()-1] = merit_value;
         else m_max_merits.push_back(merit_value);
         x = xp;
         return 0;
     }
     // Select the merit value of reference
     // -----------------------------------
     if (get_options().non_monotone_linesearch)
     {
         double mmax = merit_value;
         if (m_max_merits.size() > 0)
         {
             mmax = m_max_merits[m_max_merits.size()-1];
             // check for cycling
             // - - - - - - - - -
             if (    m_max_merits.size() ==4
                     &&  std::fabs(mmax - merit_value) < get_options().threshold_cycling_linesearch*get_options().fvectol)
             {
                 //std::cout << merit_value << std::endl;
                 WARNING << "Cycling has been detected by the linesearch - Taking the full Newton step";
                 x = xp;
                 p = lambda*p;
                 return 3;
             }
         }
         if (m_max_merits.size() < 4)
         {
             m_max_merits.push_back(merit_value);
             if (merit_value < mmax) merit_value = (3*merit_value + mmax)/4;
         }
         else if (merit_value < mmax)
         {
             m_max_merits[3] = merit_value;
             merit_value = mmax;
         }
         if (m_gradient_step_taken)
         {
             merit_value *= 100;
         }
     }
     // The linesearch
     // --------------
     double fc = merit_value;
     double fcp_prev;
     int cnt = 0;
     do
     {
         fcp = 0.5*new_res.squaredNorm();
         if (fcp <= fc - std::min(-alpha*lambda*init_slope,(1-alpha)*fc)) //pg760 Fachinei2003
         {
             retcode = 0;
             if (lambda ==1 and (newtlen > 0.99 * get_options().maxstep)) {
                 get_perfs().max_taken = true;
             }
             break;
         }
         else if (lambda < minlambda)
         {
             ERROR << "Linesearch cannot find a solution bigger than the minimal step";
             retcode = 1;
             break;
         }
         else
         {
             // Select a new step length
             // - - - - - - - - - - - -
             double lambdatmp;
             if (cnt == 0) { // only a quadratic at the first
                 lambdatmp = - init_slope / (2*(fcp - fc -init_slope));
             }
             else
             {
                 const double factor = 1 /(lambda - lambda_prev);
                 const double x1 = fcp - fc - lambda*init_slope;
                 const double x2 = fcp_prev - fc - lambda_prev*init_slope;
 
                 const double a = factor * ( x1/(lambda*lambda) - x2/(lambda_prev*lambda_prev));
                 const double b = factor * ( -x1*lambda_prev/(lambda*lambda) + x2*lambda/(lambda_prev*lambda_prev));
 
                 if (a == 0)
                 { // cubic interpolation is in fact a quadratic interpolation
                     lambdatmp = - init_slope/(2*b);
                 }
                 else
                 {
                     const double disc = b*b-3*a*init_slope;
                     lambdatmp = (-b+std::sqrt(disc))/(3*a);
                 }
                 if (lambdatmp > 0.5*lambda ) lambdatmp = 0.5*lambda;
             }
             lambda_prev = lambda;
             fcp_prev = fcp;
             if (lambdatmp < 0.1*lambda) {
                 lambda = 0.1 * lambda;
             } else {
                 lambda = lambdatmp;
             }
             if (not std::isfinite(lambda))
             {
                 ERROR << "Lambda is non finite in micpsolver linesearch - we stop";
                 return 3;
             }
         }
         xp = x + lambda*p;
         base::compute_residuals(xp, new_res);
         reformulate_residuals_inplace(xp, new_res);
         ++cnt;
     } while(retcode == 2 and cnt < 100);
     DEBUG << "Lambda : " << lambda;
     if (cnt == 100)
     {
         ERROR << "Too much linesearch iterations ! We stop";
     }
     x = xp;
     p = lambda*p;
     return retcode;
 }
 
 
 } // end namespace micpsolver
 } // end namespace specmicp
diff --git a/src/micpsolver/micpsolver_base.hpp b/src/micpsolver/micpsolver_base.hpp
index 12873f5..27c1bc8 100644
--- a/src/micpsolver/micpsolver_base.hpp
+++ b/src/micpsolver/micpsolver_base.hpp
@@ -1,190 +1,185 @@
 /*-------------------------------------------------------
 
- - Module : micpsolver
- - File : micpsolver_base.hpp
- - Author : Fabien Georget
-
-Copyright (c) 2014, Fabien Georget <fabieng@princeton.edu>, Princeton University
+Copyright (c) 2014,2015 Fabien Georget <fabieng@princeton.edu>, Princeton University
 All rights reserved.
 
 Redistribution and use in source and binary forms, with or without
 modification, are permitted provided that the following conditions are met:
     * Redistributions of source code must retain the above copyright
       notice, this list of conditions and the following disclaimer.
     * Redistributions in binary form must reproduce the above copyright
       notice, this list of conditions and the following disclaimer in the
       documentation and/or other materials provided with the distribution.
     * Neither the name of the Princeton University nor the
       names of its contributors may be used to endorse or promote products
       derived from this software without specific prior written permission.
 
 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
 ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 ---------------------------------------------------------*/
-
 #ifndef SPECMICP_MICPSOLVER_MICPSOLVERBASE_HPP
 #define SPECMICP_MICPSOLVER_MICPSOLVERBASE_HPP
 
 //! \file micpsolver_base.hpp Base class for micpsolver
 
 #include <memory>
 #include "common.hpp"
 #include "micpsolver_structs.hpp"
 #include "utils/log.hpp"
 
 #include "utils/options_handler.hpp"
 #include "utils/perfs_handler.hpp"
 
 namespace specmicp {
 namespace micpsolver {
 
 
 //! \brief Base class for an MiCP solver
 //!
 //!  Handle the program, options and performance
 //!
 template <class program_t>
 class MiCPSolverBaseProgram:
         public OptionsHandler<MiCPSolverOptions>,
         public PerformanceHandler<MiCPPerformance>
 {
 public:
     using program_ptr = std::shared_ptr<program_t>;
     using OptionsHandler<MiCPSolverOptions>::get_options;
     using PerformanceHandler<MiCPPerformance>::get_perfs;
 
     MiCPSolverBaseProgram():
         OptionsHandler<MiCPSolverOptions>(),
         PerformanceHandler<MiCPPerformance>()
     {}
     //! \brief Constructor
     //!
     //! \param prog shared_ptr to the program
     MiCPSolverBaseProgram(program_ptr prog):
         OptionsHandler<MiCPSolverOptions>(),
         PerformanceHandler<MiCPPerformance>(),
         m_program(prog)
     {}
 
     //! \brief Return the program
     //!
     //! This is due to the templating, allow to do get_program()->whatever();
     program_ptr& get_program() {return m_program;}
 
 
     //! \brief Return the number of equations
     index_t get_neq() const {return m_program->total_variables();}
     //! \brief Return the number of equations corresponding to the free variables (size of G)
     index_t get_neq_free() const {return m_program->nb_free_variables();}
 
     //! \brief Compute the residuals, store it in r
     //!
     //! \param[in] x the variables
     //! \param[out] r vector to store the residuals (must be of the same size as x)
     void compute_residuals(const Vector& x, Vector& r)
     {
         m_program->get_residuals(x, r);
         get_perfs().nb_call_residuals += 1;
     }
 
     //! \brief Compute the jacobian
     //!
     //! Assumes that the residual have been computed before
     //!
     //! \param[in] x the variables
     //! \param[out] jacobian the jacobian
     void compute_jacobian(Vector& x, Matrix& jacobian)
     {
         m_program->get_jacobian(x, jacobian);
         get_perfs().nb_call_jacobian += 1;
     }
     //! \brief Compute the factors to scale the jacobian
     //!
     //! \param[in] jacobian the jacobian to scale (from the reformulated problem)
     //! \param[in] residuals the residuals corresponding to the jacobian
     //! \param[out] rscaler scaling factors of the rows
     //! \param[out] cscaler scaling factors of the columns
     void scaling_jacobian(
             const Matrix& jacobian,
             const Vector& residuals,
             Vector& rscaler,
             Vector& cscaler);
 
 
     //! \brief Check for convergence
     //!
     //! \param nb_iterations the number of iterations
     //! \param update the update taken at the previous iteration
     //! \param solution the current solution
     //! \param residuals current residuals
     //! \param may_have_converged a boolean given by the user to indicates if the problem has converged yet
     //! \return a MiCPSolverReturnCode describing the state of the algorithm
     MiCPSolverReturnCode check_convergence(int nb_iterations,
                                            const Vector& update,
                                            const Vector& solution,
                                            const Vector &residuals,
                                            bool may_have_converged = true);
 
     //! \brief Reformulate the jacobian using the cck function
     //!
     //! \param x the variables
     //! \param r the residuals
     //! \param jacobian the jacobian
     void reformulate_jacobian_cck(
             const Vector& x,
             const Vector& r,
             Matrix& jacobian
             );
 
     //! \brief Compute the norm of the update
     //!
     //! \tparam p order of the norm (1, 2, ..., Eigen::Infinity)
     //! \param update the solution of the linear system
     //! \param solution the solution (variables)
     template <int p>
     double norm_update(const Vector& update,
                         const Vector& solution) const {
         return (update.array().abs()/(solution.array().max(1))
                 ).matrix().template lpNorm<p>();
     }
 
     //! \brief Project variables on the feasible set
     //!
     //! \param x the variables
     void projection(Vector& x);
 
     //! \brief Return the step corrected step length if it is too long
     //!
     //! \param update the solution of the linear system
     scalar_t is_step_too_long(Vector& update);
 
 protected:
     //! \brief Set the program
     //!
     //! \param program_ptr shared_ptr to the program
     program_ptr& set_program(program_ptr theprogram) {
         m_program = theprogram;
     }
 private:
     program_ptr m_program;
 };
 
 } // end namespace micpsolver
 } // end namespace specmicp
 
 // ----------------------------------- //
 //         Implementation              //
 // ----------------------------------- //
 #include "micpsolver_base.inl"
 
 
 #endif // SPECMICP_MICPSOLVER_MICPSOLVERBASE_HPP
diff --git a/src/micpsolver/micpsolver_base.inl b/src/micpsolver/micpsolver_base.inl
index 6d50a7c..055b7e9 100644
--- a/src/micpsolver/micpsolver_base.inl
+++ b/src/micpsolver/micpsolver_base.inl
@@ -1,189 +1,184 @@
 /*-------------------------------------------------------
 
- - Module : micpsolver
- - File : micpsolver_base.inl
- - Author : Fabien Georget
-
-Copyright (c) 2014, Fabien Georget <fabieng@princeton.edu>, Princeton University
+Copyright (c) 2014,2015 Fabien Georget <fabieng@princeton.edu>, Princeton University
 All rights reserved.
 
 Redistribution and use in source and binary forms, with or without
 modification, are permitted provided that the following conditions are met:
     * Redistributions of source code must retain the above copyright
       notice, this list of conditions and the following disclaimer.
     * Redistributions in binary form must reproduce the above copyright
       notice, this list of conditions and the following disclaimer in the
       documentation and/or other materials provided with the distribution.
     * Neither the name of the Princeton University nor the
       names of its contributors may be used to endorse or promote products
       derived from this software without specific prior written permission.
 
 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
 ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 ---------------------------------------------------------*/
-
 #include "micpsolver_base.hpp" // syntaxic coloration
 
 namespace specmicp {
 namespace micpsolver {
 
 
 // ref : Munson et al. (2001)
 template <class program_t>
 void MiCPSolverBaseProgram<program_t>::scaling_jacobian(
         const Matrix& jacobian,
         const Vector& residuals,
         Vector& rscaler,
         Vector& cscaler)
 {
     for (int i=0; i<jacobian.cols(); ++i)
     {
         const double sumhsq = jacobian.row(i).array().square().sum();
         double s = std::sqrt(residuals(i)*residuals(i) + sumhsq);
         rscaler(i) = 1.0/std::max(s, 1e-10);
     }
     for (int i=0; i<jacobian.cols(); ++i)
     {
         const double sumhsq = (rscaler.asDiagonal()*jacobian).col(i).array().square().sum();
         double s = std::sqrt(sumhsq);
         cscaler(i) = 1.0/std::max(s, 1e-10);
     }
 }
 
 template <class program_t>
 MiCPSolverReturnCode MiCPSolverBaseProgram<program_t>::check_convergence(
         int nb_iterations,
         const Vector& update,
         const Vector& solution,
         const Vector& residuals,
         bool may_have_converged
         )
 {
     MiCPSolverReturnCode termcode = MiCPSolverReturnCode::NotConvergedYet;
     const scalar_t norm_residuals = residuals.lpNorm<Eigen::Infinity>();
     if (norm_residuals < get_options().fvectol)
     {
         if (may_have_converged == true)
             termcode = MiCPSolverReturnCode::ResidualMinimized;
     }
     else if (nb_iterations >0 and norm_update<Eigen::Infinity>(update, solution) < get_options().steptol)
     {
         if (norm_residuals > get_options().threshold_stationary_point)
         {
             ERROR << "Stationary point detected !";
             termcode = MiCPSolverReturnCode::StationaryPoint;
         }
         if (may_have_converged == true)
         {
             WARNING << "MiCP solver : Error is minimized - may indicate a stationnary point";
             termcode = MiCPSolverReturnCode::ErrorMinimized;
         }
     }
     else if (nb_iterations >  get_options().max_iter)
     {
         ERROR << "Maximum number of iteration reached (" << get_options().max_iter << ")";
         termcode = MiCPSolverReturnCode::MaxIterations;
     }
     else if (get_perfs().max_taken)
     {
         ++get_perfs().nb_consecutive_max_taken;
         ++get_perfs().nb_max_taken;
         if (get_perfs().nb_consecutive_max_taken == get_options().maxiter_maxstep) {
             ERROR << "Divergence detected - Maximum step length taken two many times";
             termcode = MiCPSolverReturnCode::MaxStepTakenTooManyTimes;
         }
     }
     else
     {
         get_perfs().nb_consecutive_max_taken = 0;
     }
     return termcode;
 }
 
 template <class program_t>
 void MiCPSolverBaseProgram<program_t>::reformulate_jacobian_cck(
         const Vector& x,
         const Vector& r,
         Matrix& jacobian
         )
 {
     // set the z vector : contains 1 for degenerate points
     Eigen::VectorXd z(Eigen::VectorXd::Zero(get_neq()));
     for (index_t i=get_neq_free(); i<get_neq(); ++i)
     {
         if (x(i) == 0 and r(i) == 0)
             z(i) = 1.0;
     }
     // modify the jacobian
     const scalar_t lambda = get_options().penalization_factor;
     for (index_t i=get_neq_free(); i<get_neq(); ++i)
     {
         if (z(i) != 0)
         {
             const scalar_t gpdotz = jacobian.row(i).dot(z);
             scalar_t s = std::abs(z(i)) + std::abs(gpdotz);
             const scalar_t ssquare = s*s;
             s = s * std::sqrt((z(i)*z(i))/ssquare + (gpdotz*gpdotz)/ssquare);
             const scalar_t c = lambda*(z(i)/s - 1);
             const scalar_t d = lambda*(gpdotz/s -1);
             jacobian.row(i) *= d;
             jacobian(i, i) += c;
         }
         else
         {
             scalar_t s = std::abs(x(i)) + std::abs(r(i));
             const scalar_t ssquare = s*s;
             s = s * std::sqrt((x(i)*x(i))/ssquare + (r(i)*r(i))/ssquare);
             scalar_t c = lambda*(x(i)/s - 1);
             scalar_t d = lambda*(r(i)/s - 1);
             if ((lambda <1) and (r(i) > 0)  and (x(i) >0))
             {
                 c -= (1-lambda)*r(i);
                 d -= (1-lambda)*x(i);
             }
             jacobian.row(i) *= d;
             jacobian(i, i) += c;
         }
     }
 }
 
 // Projection of the variables onto the feasible set
 template <class program_t>
 void MiCPSolverBaseProgram<program_t>::projection(Vector& x)
 {
     for (index_t i=0; i<get_program()->nb_complementarity_variables(); ++i)
     {
         if (x(i+get_program()->nb_free_variables()) < get_options().projection_min_variable)
         {
             x(i+get_program()->nb_free_variables()) = 0;
         }
     }
 }
 
 
 
 template <class program_t>
 scalar_t MiCPSolverBaseProgram<program_t>::is_step_too_long(Vector& update)
 {
     scalar_t steplength = update.norm();
     if (steplength > get_options().maxstep)
     {
         get_perfs().max_taken = true;
         update  = get_options().maxstep / steplength * update;
         steplength = get_options().maxstep;
     }
     return steplength;
 }
 
 
 } // end namespace micpsolver
 } // end namespace specmicp
diff --git a/src/micpsolver/micpsolver_min.hpp b/src/micpsolver/micpsolver_min.hpp
index 7db0d1f..c41659d 100644
--- a/src/micpsolver/micpsolver_min.hpp
+++ b/src/micpsolver/micpsolver_min.hpp
@@ -1,125 +1,121 @@
 /*-------------------------------------------------------
 
- - Module : micpsolver
- - File : micpsolver_min
- - Author : Fabien Georget
-
-Copyright (c) 2014, Fabien Georget <fabieng@princeton.edu>, Princeton University
+Copyright (c) 2014,2015 Fabien Georget <fabieng@princeton.edu>, Princeton University
 All rights reserved.
 
 Redistribution and use in source and binary forms, with or without
 modification, are permitted provided that the following conditions are met:
     * Redistributions of source code must retain the above copyright
       notice, this list of conditions and the following disclaimer.
     * Redistributions in binary form must reproduce the above copyright
       notice, this list of conditions and the following disclaimer in the
       documentation and/or other materials provided with the distribution.
     * Neither the name of the Princeton University nor the
       names of its contributors may be used to endorse or promote products
       derived from this software without specific prior written permission.
 
 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
 ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 ---------------------------------------------------------*/
 
 #ifndef SPECMICP_MICPSOLVER_MICPSOLVERMIN_HPP
 #define SPECMICP_MICPSOLVER_MICPSOLVERMIN_HPP
 
 //! \file micpsolver_min.hpp micpsolver based on the min function
 
 #include "micpsolver_base.hpp"
 
 namespace specmicp {
 namespace micpsolver {
 
 //! \brief MiCP solver using the min function
 template <class program_t>
 class MiCPSolverMin: public MiCPSolverBaseProgram<program_t>
 {
 public:
 
     using base = MiCPSolverBaseProgram<program_t>;
     using MiCPSolverBaseProgram<program_t>::get_options;
     using MiCPSolverBaseProgram<program_t>::get_program;
     using MiCPSolverBaseProgram<program_t>::get_perf;
     using MiCPSolverBaseProgram<program_t>::get_neq;
     using MiCPSolverBaseProgram<program_t>::get_neq_free;
 
     //! \brief Constructor
     //!
     //! @param prog smart pointer toward an instance of a Program to solve
     MiCPSolverMin(std::shared_ptr<program_t> prog):
         MiCPSolverBaseProgram<program_t>(prog),
         m_residuals(prog->total_variables()),
         m_grad_phicck(prog->total_variables()),
         m_jacobian(prog->total_variables(),prog ->total_variables())
     {
 
         m_max_merits.reserve(4);
     }
 
     //! \brief Solve the program
     //!
     //! @param[in,out] x (in) initial guess, (out) solution
     MiCPSolverReturnCode solve(Eigen::VectorXd& x);
 
     MiCPSolverReturnCode search_direction_calculation(Eigen::VectorXd& x,
                                       Eigen::VectorXd& update);
 
     int linesearch(Eigen::VectorXd& p, Eigen::VectorXd& x);
 
     //! \brief Setup the residuals
     //!
     //! @param[in] x the current solution
     void setup_residuals(const Eigen::VectorXd& x) {
         base::compute_residuals(x, m_residuals);
     }
 
     void setup_jacobian(Eigen::VectorXd& x) {
         base::compute_jacobian(x, m_jacobian);
     }
 
 
     //! Reduce the system
     //!
     //! @return reduced number of freedom
     int reduce_system(const Eigen::VectorXd& x,
                        Eigen::MatrixXd& reduced_jacobian,
                        Eigen::VectorXd& reduced_residual);
 
     void reformulate_residuals_cck_inplace(const Eigen::VectorXd& x,
                                            Eigen::VectorXd& residuals);
 
     void reformulate_result(const Eigen::VectorXd &x,
                        Eigen::VectorXd &update);
 private:
     void sanitize(Eigen::VectorXd &x);
     Eigen::VectorXd m_residuals;
     Eigen::VectorXd m_grad_phicck;
     Eigen::MatrixXd m_jacobian;
 
     bool m_gradient_step_taken;
 
     std::vector<double> m_max_merits;   //!< Contains the m best value of the merit function
 
     double m_newton_length;
 };
 
 
 } // end namespace micpsolver
 } // end namespace specm
 
 // implementation
 // --------------
 #include "micpsolver_min.inl"
 
 #endif // SPECMICP_MICPSOLVER_MICPSOLVERMIN_HPP
diff --git a/src/micpsolver/micpsolver_min.inl b/src/micpsolver/micpsolver_min.inl
index efeed67..185d8f4 100644
--- a/src/micpsolver/micpsolver_min.inl
+++ b/src/micpsolver/micpsolver_min.inl
@@ -1,384 +1,379 @@
 /*-------------------------------------------------------
 
- - Module : micpsolver
- - File : micpsolver_min.inl
- - Author : Fabien Georget
-
-Copyright (c) 2014, Fabien Georget <fabieng@princeton.edu>, Princeton University
+Copyright (c) 2014,2015 Fabien Georget <fabieng@princeton.edu>, Princeton University
 All rights reserved.
 
 Redistribution and use in source and binary forms, with or without
 modification, are permitted provided that the following conditions are met:
     * Redistributions of source code must retain the above copyright
       notice, this list of conditions and the following disclaimer.
     * Redistributions in binary form must reproduce the above copyright
       notice, this list of conditions and the following disclaimer in the
       documentation and/or other materials provided with the distribution.
     * Neither the name of the Princeton University nor the
       names of its contributors may be used to endorse or promote products
       derived from this software without specific prior written permission.
 
 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
 ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 ---------------------------------------------------------*/
-
 #include "micpsolver_min.hpp" // for syntaxic coloration
 
 #include "utils/log.hpp"
 #include "ncp_function.hpp"
 #include "estimate_cond_number.hpp"
 
 namespace specmicp {
 namespace micpsolver {
 
 template <class program_t>
 MiCPSolverReturnCode MiCPSolverMin<program_t>::solve(Eigen::VectorXd& x)
 {
     int cnt = 0;
     MiCPSolverReturnCode retcode = MiCPSolverReturnCode::NotConvergedYet;
     Eigen::VectorXd update(Eigen::VectorXd::Zero(get_neq()));
     setup_residuals(x);
     while (retcode == MiCPSolverReturnCode::NotConvergedYet)
     {
         DEBUG << "Iteration : " << cnt;
         DEBUG << "Solution : \n" << x;
         get_program()->hook_start_iteration(x, m_residuals.norm());
         setup_residuals(x);
         get_perf().current_residual = m_residuals.norm();
         SPAM << "Residuals : \n ----- \n" << m_residuals << "\n ----- \n";
         retcode = base::check_convergence(cnt, update, x, m_residuals);
         get_perf().return_code = retcode;
         if (retcode != MiCPSolverReturnCode::NotConvergedYet) break;
         ++cnt;
         get_perf().max_taken = false;
         setup_jacobian(x);
         search_direction_calculation(x, update);
         sanitize(x);
         int termcode = linesearch(update, x);
         get_perf().current_update = update.norm();
         DEBUG << "Return LineSearch : " << termcode;
         base::projection(x);
         get_perf().nb_iterations = cnt;
     }
     return retcode;
 }
 
 
 template <class program_t>
 MiCPSolverReturnCode MiCPSolverMin<program_t>::search_direction_calculation(
                                                  Eigen::VectorXd& x,
                                                  Eigen::VectorXd& update)
 {
     Eigen::MatrixXd reduced_jacobian;
     Eigen::VectorXd reduced_residual;
 
     reduce_system(x, reduced_jacobian, reduced_residual);
     DEBUG << reduced_jacobian;
 
     Eigen::ColPivHouseholderQR<Eigen::MatrixXd> solver;
     m_gradient_step_taken = false;
     solver.compute(reduced_jacobian);
     get_perf().nb_factorization += 1;
     { // first condition : is the factorization ok ?
         if (solver.info() != Eigen::Success or not solver.isInvertible())
         {
             DEBUG << "Solver.info : " << solver.info() << " - is invertible : " << solver.isInvertible();
             m_gradient_step_taken = true;
             goto after_second_cond; // jump directly to the gradient step
         }
     }
     { // second condition : is the condition number ok ?
         const double cond = estimate_condition_number(solver.matrixR().triangularView<Eigen::Upper>());
         DEBUG << "Condition number : " << cond;
         if (cond > get_options().condition_limit)
         {
             m_gradient_step_taken = true;
         }
     }
 after_second_cond:
     //  third condition : is the descent condition respected
     update = solver.solve(-reduced_residual);
     m_grad_phicck = reduced_jacobian.transpose()*reduced_residual;
     const double descent_cond = m_grad_phicck.dot(update);
     reformulate_result(x, update);
     base::reformulate_jacobian_cck(x, m_residuals, m_jacobian);
     reformulate_residuals_cck_inplace(x, m_residuals);
     m_grad_phicck = m_jacobian.transpose()*m_residuals;
     m_grad_phicck(0) = 0;
 
 
     if (not m_gradient_step_taken)
     {
         m_newton_length = base::is_step_too_long(update);
         // we compute the descent condition
         //const double descent_cond = m_grad_phicck.dot(update);
         const double norm_update = update.norm();
         DEBUG << "grad(phi).dot(update) = " << descent_cond << " compared to : " << (
                      - get_options().factor_descent_condition * std::pow(norm_update, get_options().power_descent_condition));
         if (descent_cond > - get_options().factor_descent_condition * std::pow(norm_update, get_options().power_descent_condition))
         {
             m_gradient_step_taken = true;
         }
     }
 
     if (m_gradient_step_taken)
     {
         INFO << "Full gradient step taken !";
         update = - m_grad_phicck;
         m_newton_length = base::is_step_too_long(update);
     }
     return MiCPSolverReturnCode::NotConvergedYet;
 
 }
 
 template <class program_t>
 int MiCPSolverMin<program_t>::reduce_system(const Eigen::VectorXd& x,
                                              Eigen::MatrixXd& reduced_jacobian,
                                              Eigen::VectorXd& reduced_residual)
 {
     reduced_jacobian.resizeLike(m_jacobian); // memory is cheap, we will resize at the end
     reduced_jacobian.setZero();
     reduced_residual.resizeLike(m_residuals);
     // copy identical information
     int ideq_reduced = get_neq_free();
     reduced_jacobian.block(0, 0, get_neq_free(), get_neq_free()) = m_jacobian.block(0, 0, get_neq_free(), get_neq_free());
     // select active degree of freedom
     Eigen::VectorXd to_remove(get_neq()-get_neq_free());
     for (int dof=get_neq_free(); dof<get_neq(); ++dof)
     {
         if (x(dof) >= m_residuals(dof))
         {
             DEBUG << "Mineral to precipitate : " << dof;
             reduced_residual(ideq_reduced) = m_residuals(dof);
             reduced_jacobian.block(ideq_reduced, 0, 1, get_neq_free()) = m_jacobian.block(dof, 0, 1, get_neq_free());
             reduced_jacobian.block(0, ideq_reduced, get_neq_free(), 1) = m_jacobian.block(0, dof, get_neq_free(), 1);
             to_remove(dof-get_neq_free()) = 0;
             ++ideq_reduced;
         }
         else
         {
             to_remove(dof-get_neq_free()) = x(dof);
         }
     }
     reduced_residual.block(0, 0, get_neq_free(), 1) -=
            m_jacobian.block(0, get_neq_free(), get_neq_free(), get_neq()-get_neq_free())*to_remove;
 
     reduced_jacobian.conservativeResize(ideq_reduced, ideq_reduced);
     reduced_residual.conservativeResize(ideq_reduced);
     DEBUG << "ideq reduced : " << ideq_reduced;
     return ideq_reduced;
 }
 
 template <class program_t>
 void MiCPSolverMin<program_t>::reformulate_result(const Eigen::VectorXd& x,
                                                   Eigen::VectorXd& update)
 {
     update.conservativeResizeLike(x);
     int tot_to_keep = 0;
     for (int dof=get_neq_free(); dof<get_neq(); ++dof)
     {
         if (x(dof) >= m_residuals(dof))
             ++tot_to_keep;
     }
     int kept_dof = 1;
     for (int dof=get_neq()-1; dof>=get_neq_free(); --dof)
     {   // we go backwards to avoid extra copies
         if (x(dof) >= m_residuals(dof))
         {
             update(dof) = update(get_neq_free()+(tot_to_keep-kept_dof));
             ++kept_dof;
         }
         else
         {
             update(dof) = -x(dof);
         }
     }
 }
 
 template <class program_t>
 void MiCPSolverMin<program_t>::sanitize(Eigen::VectorXd& x)
 {
     if (x(0) <=0) x(0) = 1;
     for (int dof=get_neq_free(); dof<get_neq(); ++dof)
     {
         if (x(dof) <=0) {x(dof) =0; DEBUG<< "sanitize dof : " << dof;}
     }
 }
 
 template <class program_t>
 void MiCPSolverMin<program_t>::reformulate_residuals_cck_inplace(const Eigen::VectorXd& x,
                                                                  Eigen::VectorXd& residuals)
 {
     for (int i =  get_neq_free(); i<get_neq(); ++i)
     {
         residuals(i) = penalized_fisher_burmeister(x(i), residuals(i), get_options().penalization_factor);
     }
 }
 
 
 template <class program_t>
 int MiCPSolverMin<program_t>::linesearch(Eigen::VectorXd& p, Eigen::VectorXd& x)
 {
      // Reference Algo A6.3.1 : Dennis and Schnabel (1983)
 
     DEBUG << "Linesearch";
     Eigen::VectorXd xp(get_neq());
     Eigen::VectorXd new_res(get_neq());
     double fcp;
 
     get_perf().max_taken = false;
     int retcode = 2;
     const double alpha = get_options().factor_descent_condition;
     double newtlen = m_newton_length;
     //double newtlen = p.norm();
     double init_slope = m_grad_phicck.dot(p);
     double rellength = std::abs(p(0));
     for (int i=1; i<p.rows(); ++i)
     {
         rellength = std::max(rellength, std::abs(p(i)));
     }
     double minlambda = get_options().steptol / rellength;
     double lambda = get_program()->max_lambda(x, p);
     DEBUG << "Initial lambda : " << lambda;
     double lambda_prev = lambda;
 
     // non monotone linesearch
     //
     //  - reference : Munson et al. (2001)
     // ------------------------------------
 
     double merit_value = 0.5*m_residuals.squaredNorm();
 //    // new residual
     //reformulate_result(x, p);
     xp = x + lambda*p;
     DEBUG << "update \n" << p <<std::endl;
     base::compute_residuals(xp, new_res);
     reformulate_residuals_cck_inplace(xp, new_res);
     fcp = 0.5*new_res.squaredNorm();
 
     // Skip linesearch if enough progress is done
     if (fcp < get_options().coeff_accept_newton_step *merit_value)
     {
         if (m_max_merits.size() > 0) m_max_merits[m_max_merits.size()-1] = merit_value;
         else m_max_merits.push_back(merit_value);
         x = xp;
         return 0;
     }
 
     DEBUG << "Merit value : " << merit_value;
     double mmax = merit_value;
     if (m_max_merits.size() > 0)
     {
         mmax = m_max_merits[m_max_merits.size()-1];
     }
     if (m_max_merits.size() < 4)
     {
         m_max_merits.push_back(merit_value);
         if (merit_value < mmax) merit_value = (3*merit_value + mmax)/4;
     }
     else if (merit_value < mmax)
     {
         m_max_merits[3] = merit_value;
         merit_value = mmax;
     }
     if (m_gradient_step_taken)
     {
         merit_value *= 100;
     }
     DEBUG << "Merit value used : " << merit_value;
     double fc = merit_value;
     double fcp_prev;
     int cnt = 0;
     do
     {
         DEBUG << "cnt : " << cnt << " - lambda : " << lambda;
         DEBUG << "fcp : " << fcp << "\n fc+alin : " << fc+alpha*lambda*init_slope << " # fc : " << fc << std::endl;
         if (fcp <= fc + alpha*lambda*init_slope)
         {
             retcode = 0;
             if (lambda ==1 and (newtlen > 0.99 * get_options().maxstep)) {
                 get_perf().max_taken = true;
             }
             break;
         }
         else if (lambda < minlambda)
         {
             lambda = get_program()->max_lambda(x, p);
             xp = x + lambda*p;
             retcode = 1;
             break;
         }
         else
         {
             double lambdatmp;
             if (cnt == 0) { // only a quadratic at the first
                 lambdatmp = - init_slope / (2*(fcp - fc -init_slope));
             }
             else
             {
                 const double factor = 1 /(lambda - lambda_prev);
                 const double x1 = fcp - fc - lambda*init_slope;
                 const double x2 = fcp_prev - fc - lambda_prev*init_slope;
 
                 const double a = factor * ( x1/(lambda*lambda) - x2/(lambda_prev*lambda_prev));
                 const double b = factor * ( -x1*lambda_prev/(lambda*lambda) + x2*lambda/(lambda_prev*lambda_prev));
 
                 if (a == 0)
                 { // cubic interpolation is in fact a quadratic interpolation
                     DEBUG << "not disc : " << - init_slope/(2*b);
                     lambdatmp = - init_slope/(2*b);
                 }
                 else
                 {
                     const double disc = b*b-3*a*init_slope;
                     lambdatmp = (-b+std::sqrt(disc))/(3*a);
                 }
                 if (lambdatmp > 0.5*lambda ) lambdatmp = 0.5*lambda;
             }
             DEBUG << "lambdatmp : " << lambdatmp;
             lambda_prev = lambda;
             fcp_prev = fcp;
             if (not std::isfinite(lambdatmp))
             {
                 lambda = get_program()->max_lambda(x, p);
                 xp = x + lambda*p;
                 retcode = 1;
                 break;
             } else if ((lambdatmp < 0.1*lambda)) {
                 lambda = 0.1 * lambda;
             } else {
                 lambda = lambdatmp;
             }
 
             DEBUG << "lambda end : " << lambda;
         }
         xp = x + lambda*p;
         //sanitize(xp);
         DEBUG << "xp : " << std::endl << xp;
         base::compute_residuals(xp, new_res);
         reformulate_residuals_cck_inplace(xp, new_res);
         fcp = 0.5*new_res.squaredNorm();
         ++cnt;
     } while(retcode == 2 and cnt < 100);
     DEBUG << "Lambda : " << lambda;
     if (cnt == 100)
     {
         ERROR << "Too much linesearch iterations ! We stop";
     }
     x = xp;
     p = lambda*p;
     return retcode;
 
 }
 
 } // end namespace micpsolver
 } // end namespace specmicp
diff --git a/src/micpsolver/micpsolver_structs.hpp b/src/micpsolver/micpsolver_structs.hpp
index 5e0cb3c..2998ed5 100644
--- a/src/micpsolver/micpsolver_structs.hpp
+++ b/src/micpsolver/micpsolver_structs.hpp
@@ -1,219 +1,215 @@
 /*-------------------------------------------------------
 
- - Module : micpsolver
- - File : micpsolver_structs.hpp
- - Author : Fabien Georget
-
-Copyright (c) 2014, Fabien Georget <fabieng@princeton.edu>, Princeton University
+Copyright (c) 2014,2015 Fabien Georget <fabieng@princeton.edu>, Princeton University
 All rights reserved.
 
 Redistribution and use in source and binary forms, with or without
 modification, are permitted provided that the following conditions are met:
     * Redistributions of source code must retain the above copyright
       notice, this list of conditions and the following disclaimer.
     * Redistributions in binary form must reproduce the above copyright
       notice, this list of conditions and the following disclaimer in the
       documentation and/or other materials provided with the distribution.
     * Neither the name of the Princeton University nor the
       names of its contributors may be used to endorse or promote products
       derived from this software without specific prior written permission.
 
 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
 ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 ---------------------------------------------------------*/
 
 #ifndef SPECMICP_MICPSOLVER_MICPSOLVERSTRUCTS_HPP
 #define SPECMICP_MICPSOLVER_MICPSOLVERSTRUCTS_HPP
 
 //! \file micpsolver_structs.hpp structures and enum used by the micpsolver
 
 // this file exists to reduce the header dependancy
 
 #include <float.h>
 
 namespace specmicp {
 namespace micpsolver {
 
 //! \brief Options for the MiCPSolver
 struct MiCPSolverOptions
 {
     int max_iter;    //!< Maximum number of iterations allowed
     // tolerances
     double fvectol;  //!< Tolerance for minimization of residuals
     double steptol;  //!< Tolerance for minimization of error
     // misc ...
     double condition_limit; //!< Condition number limit, -1 to disable it
     double penalization_factor; //!< Penalization factor for the penalized Fisher-Burmeister function
     double maxstep;        //!< the maximum step allowed
     int maxiter_maxstep;   //!< the maximum number of step of length maxstep allowed
     double factor_descent_condition; //!< factor in front of the descent condition > 0
     double power_descent_condition; //!<  power used in the traditional format of the descent condition > 2
     bool use_crashing;          //! Use a crashing step to improve the starting guess
     double coeff_accept_newton_step; //! Accept the newton step without line search if merit(x+d)<coeff*merit(x^k)
     bool use_scaling;           //! Use scaling to improve convergence
     double factor_gradient_search_direction;    //! factor which multiply the gradient in the search direction system
     double projection_min_variable;    //! threshold under which a mineral is considered to be 0
     double threshold_stationary_point; //! If norm(residual)>threshold_stationary_point and ErrorMinimized -> stationary point
     double threshold_cycling_linesearch; //! factor to detect cycling in linesearch
     int max_factorization_step;        //! Max number of factorization in an iteration
     bool non_monotone_linesearch;      //! Use non monotone linesearch
 
     //! \brief Constructor - also defines the default value used by the algorithm
     MiCPSolverOptions():
         max_iter(100),
         fvectol(1e-8),
         steptol(1e-10),
         condition_limit(1e6),
         penalization_factor(0.8),
         maxstep(100), // this is quite restrictif
         maxiter_maxstep(20),
         factor_descent_condition(1e-4),
         power_descent_condition(2),
         use_crashing(false),
         coeff_accept_newton_step(0.95),
         use_scaling(true),
         factor_gradient_search_direction(5.0),
         projection_min_variable(DBL_EPSILON),
         threshold_stationary_point(1e-6),
         threshold_cycling_linesearch(1e-5),
         max_factorization_step(4),
         non_monotone_linesearch(true)
     {}
 
     //! \brief Disable the descent condition
     void disable_descent_direction() {
         factor_descent_condition = -1.0;
     }
     //! \brief Enable the descent condition
     void enable_descent_condition(double  factor, double power) {
         factor_descent_condition = factor;
         power_descent_condition = power;
     }
     //! \brief Disable the condition check
     void disable_condition_check() {
         condition_limit = -1;
     }
     //! \brief Enable the condition check
     void enable_condition_check(double threshold) {
         condition_limit = threshold;
     }
     //! \brief Disable the non-monotone linesearch
     void disable_non_monotone_linesearch() {
         non_monotone_linesearch = false;
     }
     //! \brief Enable the scaling
     void enable_scaling() {
         use_scaling = true;
     }
     //! \brief Disable the scaling
     void disable_scaling() {
         use_scaling = false;
     }
     //! \brief Enable the crashing
     void enable_crashing() {
         use_crashing = true;
     }
     //! \brief Disable the scaling
     void disable_crashing() {
         use_crashing = false;
     }
     //! \brief Enable the non-monotone linesearch
     void enable_non_monotone_linesearch() {
         non_monotone_linesearch = true;
     }
     //! \brief Set tolerance
     void set_tolerance(double residuals_tolerance) {
         fvectol = residuals_tolerance;
     }
     //! \brief Set tolerances
     void set_tolerance(double residuals_tolerance, double step_tolerance) {
         fvectol = residuals_tolerance;
         steptol = step_tolerance;
     }
 };
 
 //! \brief Return code of the MiCP solver
 //!
 //! A positive return code means that the algorithm converged (but maybe to a stationnary points)
 //! A negative return code means that something wrong happened and was detected
 enum class MiCPSolverReturnCode
 {
     LolItsNotSupposedToHappen = -10,    //!< bummer...
     LinesearchFailure = -5,             //!< Failure in linesearch
     MaxStepTakenTooManyTimes = -4,      //!< Probably detect a divergence
     FailedToSolveLinearSystem = -3,     //!< Problem in the decomposition... shouldn't be raised, use of the gradient step
     MaxIterations = -2,                 //!< Algorithm has reached the maximum number of iterations
     StationaryPoint = -1,               //!< Algorithm is stuck in a stationnary point of the merit function
     NotConvergedYet = 0,                //!< Keep going...
     Success = 1,                        //!< Test success (well be careful of stationnary points)
     ResidualMinimized = 2,              //!< The residual is minimized (i.e. close to zero)
     ErrorMinimized = 3                  //!< The error is minimized, may indicate a stationary point
 };
 
 //! \brief This structure contains counter to check/query the performance of the algorithm
 //!
 //! It should be updated after each operations, not at the end
 struct MiCPPerformance
 {
     int nb_call_residuals;            //! Number of calls of the residual
     int nb_call_jacobian;             //! Number of calls of the jacobian
     int nb_factorization;             //! Number of factorization performed (may be > number of iterations)
     int nb_gradient_step;             //! Number of gradient steps (too many gradient steps indicate a bad starting guess)
     int nb_crashing_iterations;       //! Number of crashing iterations
     int nb_iterations;                //! Number of iterations
     bool max_taken;                   //! Maximum step has been taken
     int nb_max_taken;                 //! Number of time the maximum has been taken
     int nb_consecutive_max_taken;     //! Number of consecutive step at max length
     double current_residual;          //! Current residual
     double current_update;            //! Current update
     MiCPSolverReturnCode return_code; //! Return code
 
     MiCPPerformance():
         nb_call_residuals(0),
         nb_call_jacobian(0),
         nb_factorization(0),
         nb_gradient_step(0),
         nb_crashing_iterations(0),
         nb_iterations(0),
         max_taken(false),
         nb_max_taken(0),
         nb_consecutive_max_taken(0),
         current_residual(INFINITY),
         current_update(INFINITY),
         return_code(MiCPSolverReturnCode::NotConvergedYet)
     {}
 
     //! \brief add two performance instances - useful when restarting a computation in case of failure
     MiCPPerformance& operator+=(const MiCPPerformance& other)
     {
         nb_call_residuals += other.nb_call_residuals;
         nb_call_jacobian += other.nb_call_jacobian;
         nb_factorization += other.nb_factorization;
         nb_gradient_step += other.nb_gradient_step;
         nb_crashing_iterations += other.nb_crashing_iterations;
         nb_iterations += other.nb_iterations;
         return_code = other.return_code; // we take the last one
         return *this;
     }
 };
 
 //! The NCP function that are implemented
 enum class NCPfunction
 {
     penalizedFB, // Penalized Fischer-Burmeister function
     min          // The minimum function
 };
 
 } // end namespace micpsolver
 } // end namespace specmicp
 
 #endif //SPECMICP_MICPSOLVER_MICPSOLVERSTRUCTS_HPP
diff --git a/src/micpsolver/micpsolverold.hpp b/src/micpsolver/micpsolverold.hpp
index 176ec07..a89d7f8 100644
--- a/src/micpsolver/micpsolverold.hpp
+++ b/src/micpsolver/micpsolverold.hpp
@@ -1,302 +1,321 @@
 /*-------------------------------------------------------
 
- - Module : micpsolver
- - File : micpsolver.hpp
- - Author : Fabien Georget
-
- Copyright (c) 2014, Fabien Georget, Princeton University
+Copyright (c) 2014,2015 Fabien Georget <fabieng@princeton.edu>, Princeton University
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+    * Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+    * Redistributions in binary form must reproduce the above copyright
+      notice, this list of conditions and the following disclaimer in the
+      documentation and/or other materials provided with the distribution.
+    * Neither the name of the Princeton University nor the
+      names of its contributors may be used to endorse or promote products
+      derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 ---------------------------------------------------------*/
 
 #ifndef SPECMIC_MICPSOLVER_MICPSOLVEROLD_HPP
 #define SPECMIC_MICPSOLVER_MICPSOLVEROLD_HPP
 
 #include <memory>
 #include <Eigen/Dense>
 #include "micpsolver_structs.hpp"
 #include "ncp_function.hpp"
 
 //! \file micpsolver.hpp The MiCP solver
 
 namespace specmicp {
 namespace micpsolver {
 
 //! \brief Call a NCP-function
 //!
 //! @tparam ncp_t the NCP function to use
 //! @param a first argument
 //! @param b second argument
 //! @param t parameter of the NCP function
 //!
 template <NCPfunction ncp_t>
 inline double ncp_function(double a, double b, double t);
 
 //! \brief Reformulate the jacobian using the NCP-function ncp_t
 //!
 //! @tparam ncp_t the NCP-function to use
 //! @param[in] neq number of equation
 //! @param[in] neq_free number of free variables
 //! @param[in] x the variables
 //! @param[in] r the residuals
 //! @param[in,out] jacobian the jacobian to reformulate
 //! @param[in,out] r_reformulated the reformulated residuals
 //! @param[in] t parameter of the NCP function
 template <NCPfunction ncp_t>
 inline void reformulate_jacobian_helper(
         int neq,
         int neq_free,
         const Eigen::VectorXd& x,
         const Eigen::VectorXd& r,
         Eigen::MatrixXd& jacobian,
         Eigen::VectorXd& r_reformulated,
         double t
         );
 
 //! \brief reformulate the result of the Newton system
 template <NCPfunction ncp_t>
 inline void reformulate_result(
         int neq,
         int neq_free,
         Eigen::VectorXd& x,
         const Eigen::VectorXd& orig_r,
         Eigen::VectorXd& grad_phi,
         Eigen::VectorXd& update
         );
 
 //! \brief The MiCP Solver
 //!
 //! Solve
 //!     - \f$ G(u, v) = 0\f$
 //!     - \f$ 0 \leq v \perp H(u,v) \geq 0 \f$
 //!
 //! \tparam Program a subclass of MiCPProg
 //!
 //! References :
 //!     - \cite Munson2001
 //!     - \cite Facchinei2003
 //!
 template <class Program, NCPfunction ncp_t>
 class MiCPSolverOLD {
 
 public:
     //! \brief Constructor
     //!
     //! @param prog smart pointer toward an instance of a Program to solve
     MiCPSolverOLD(std::shared_ptr<Program> prog):
         m_program(prog),
         m_residuals(prog->total_variables()),
         m_phi_residuals(Eigen::VectorXd::Zero(prog->total_variables())),
         m_jacobian(prog->total_variables(),prog ->total_variables()),
         m_max_taken(false),
         m_consec_max(0)
     {
     }
 
     //! \brief Return a const reference to the options used by the algorithm
     const MiCPSolverOptions& get_options() const {return m_options;}
     //! \brief Return a reference to the options used by the algorithm
     MiCPSolverOptions& get_options() {return m_options;}
     //! \brief Set the options
     void set_options(const MiCPSolverOptions& options) {m_options = options;}
 
     //! \brief Return the number of equations
     int get_neq() const {return m_program->total_variables();}
     //! \brief Return the number of equations corresponding to the free variables (size of G)
     int get_neq_free() const {return m_program->nb_free_variables();}
 
     // Merit function
     // ##############
 
     //! \brief Reformulation for lower bounded variable
     double phi_lower_bounded(const double& x, const double& r, const double& l) const {
         return ncp_function<ncp_t>(x-l, r, get_options().penalization_factor);}
     //! \brief Reformulation for a free variable
     double phi_free(const double& r) const {
         return r;
     }
 
     //! \brief Compute the norm of the update
     template <int p>
     double norm_update(const Eigen::VectorXd& update,
                         const Eigen::VectorXd& solution) const {
         return (update.array().abs()/(solution.array().max(1))
                 ).matrix().template lpNorm<p>();
     }
     // Residuals and jacobian
     // ----------------------
 
     //! \brief Compute the residuals, store it in r
     //!
     //! @param[in] x the variables
     //! @param[out] r vector to store the residuals (must be of the same size as x)
     void compute_residuals(const Eigen::VectorXd& x, Eigen::VectorXd& r)
     {
         m_program->get_residuals(x, r);
         get_perf().nb_call_residuals += 1;
     }
     //! \brief Compute the residuals, use internal storage
     //!
     //! @param[in] x the variables
     void compute_residuals(const Eigen::VectorXd& x)
     {
         return compute_residuals(x, m_residuals);
         get_perf().nb_call_jacobian += 1;
     }
     //! \brief Compute the jacobian
     //!
     //! Assumes that the residual have been computed before
     //!
     //! @param[in] x the variables
     void compute_jacobian(Eigen::VectorXd& x)
     {
         m_program->get_jacobian(x, m_jacobian);
     }
     //! \brief Reformulation of the residuals
     //!
     //! Reformulate the problem - assumes that r, the residual, has been computed before
     //!
     //! @param[in] x the variables
     //! @param[in] r the residuals
     //! @param[out] r_phi a vector of size neq, which will contain the reformulated residuals
     void reformulate_residuals(const Eigen::VectorXd& x,
                                const Eigen::VectorXd& r,
                                Eigen::VectorXd& r_phi);
     //! \brief Reformulation of the residuals *inplace*
     //!
     //! @param[in] x the variables
     //! @param[in,out] r the residual, will contain the reformulated residuals
     void reformulate_residuals_inplace(const Eigen::VectorXd& x,
                                        Eigen::VectorXd &r);
     //! \brief Reformulation of the jacobian
     //!
     //! r is the original vector of residuals (not reformulated)
     void reformulate_jacobian(const Eigen::VectorXd& x
                               )
     {
         reformulate_jacobian_helper<ncp_t>(get_neq(), get_neq_free(),
                                            x, m_residuals,
                                            m_jacobian,
                                            m_phi_residuals,
                                            get_options().penalization_factor);
     }
 
     //! \brief Compute the factors to scale the jacobian
     //!
     //! @param[in] jacobian the jacobian to scale (from the reformulated problem)
     //! @param[in] residual the residuals corresponding to the jacobian
     //! @param[out] rscaler scaling factors of the rows
     //! @param[out] cscaler scaling factors of the columns
     void scaling_jacobian(const Eigen::MatrixXd& jacobian,
                           const Eigen::VectorXd& residual,
                           Eigen::VectorXd& rscaler,
                           Eigen::VectorXd& cscaler);
 
     // Algorithm
     // #########
 
     //! \brief Solver the program using x as initial guess
     //!
     //! @param[in,out] x the initial guess, as output contains the solution (from the last iteration)
     MiCPSolverReturnCode solve(Eigen::VectorXd& x);
 
     //! \brief Setup the residuals
     //!
     //! @param[in] x the current solution
     void setup_residuals(const Eigen::VectorXd& x) {
         compute_residuals(x);
         reformulate_residuals(x, m_residuals, m_phi_residuals);
     }
 
     //! \brief Setup the jacobian
     //!
     //! @param[in] x the current solution
     void setup_jacobian(Eigen::VectorXd& x) {
         compute_jacobian(x);
         reformulate_jacobian(x);
         m_grad_phi = m_jacobian.transpose() * m_phi_residuals;
     }
 
     //! \brief Check for convergence
     //!
     //! @param nb_iterations the number of iterations
     //! @param update the update taken at the previous iteration
     //! @param solution the current solution
     //! @return a MiCPSolverReturnCode describing the state of the algorithm
     MiCPSolverReturnCode check_convergence(int nb_iterations,
                                            Eigen::VectorXd& update,
                                            Eigen::VectorXd& solution);
 
     //! \brief Solve the Newton system
     //!
     //! Assume that the Newton system has been formed
     //!
     //! \param[out] update the update to apply to the solution
     MiCPSolverReturnCode search_direction_calculation(Eigen::VectorXd& update);
 
     //! \brief Solve the Newton system - does not scale the jacobian
     //!
     //! Assume that the Newton system has been formed
     //!
     //! \param[out] update the update to apply to the solution
     MiCPSolverReturnCode search_direction_calculation_no_scaling(Eigen::VectorXd& update);
     //! \brief Linesearch
     //!
     //! Nonmonotone linesearch
     //!
     //! References :
     //!     - \cite Dennis1983
     //!     - \cite Munson2001
     //!
     int linesearch(Eigen::VectorXd& update, Eigen::VectorXd& x);
 
     //! \brief Crashing
     //!
     //! This function improves, if possible, the initial guess
     //! Reference :
     //!     - \cite Munson2001
     void crashing(Eigen::VectorXd& x);
 
     //! \brief Project variables on the feasible set
     void projection(Eigen::VectorXd& x);
 
     //! \brief Return a const reference to an instance of MiCPPerformance
     const MiCPPerformance& get_performance() {return m_perf;}
 
 protected:
     //! \brief Return a reference to an instance of MiCPPerformance
     MiCPPerformance& get_perf() {return m_perf;}
 
 private:
 
     //! \brief Return the step corrected step length if it is too long
     double is_step_too_long(Eigen::VectorXd& update);
 
     std::shared_ptr<Program> m_program; //!< Smart pointer of a program
 
     MiCPSolverOptions m_options;    //!< The options
     MiCPPerformance m_perf;         //!< The performance
 
     // Residuals and jacobian
     Eigen::VectorXd m_residuals;        //!< The residuals
     Eigen::VectorXd m_phi_residuals;    //!< The reformulated residuals
     Eigen::VectorXd m_grad_phi;         //!< The gradient of the reformulated residuals
     Eigen::MatrixXd m_jacobian;         //!< The jacobian
 
     std::vector<double> m_max_merits;   //!< Contains the m best value of the merit function
 
     bool m_max_taken;  //!< True if the 'length' of the step was equal or bigger than the maximum step length
     int m_consec_max;  //!< The number of consecutive step were the step length was equal or bigger than the maximum step length
 
     bool m_gradient_step_taken; //!< True if the update was computed using the gradient
 
 };
 
 } // end namespace micpsolver
 } // end namespace specmicp
 
 // ###############//
 // Implementation //
 // ###############//
 #include "micpsolverold.inl"
 
 #endif // SPECMIC_MICPSOLVER_MICPSOLVER_HPP
diff --git a/src/micpsolver/micpsolverold.inl b/src/micpsolver/micpsolverold.inl
index 2ca4d49..b051241 100644
--- a/src/micpsolver/micpsolverold.inl
+++ b/src/micpsolver/micpsolverold.inl
@@ -1,615 +1,634 @@
 /*-------------------------------------------------------
 
- - Module : micpsolver
- - File : micpsolver.inl
- - Author : Fabien Georget
-
- Copyright (c) 2014, Fabien Georget, Princeton University
+Copyright (c) 2014,2015 Fabien Georget <fabieng@princeton.edu>, Princeton University
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+    * Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+    * Redistributions in binary form must reproduce the above copyright
+      notice, this list of conditions and the following disclaimer in the
+      documentation and/or other materials provided with the distribution.
+    * Neither the name of the Princeton University nor the
+      names of its contributors may be used to endorse or promote products
+      derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 ---------------------------------------------------------*/
 
 #include "micpsolverold.hpp" // for syntaxic coloration...
 
 #include "estimate_cond_number.hpp"
 #include "utils/log.hpp"
 
 #include <iostream>
 
 //! \file micpsolver.inl implementation of the MiCP solver
 
 namespace specmicp {
 namespace micpsolver {
 
 // Main algorithm
 // ##############
 
 template <class Program, NCPfunction ncp_t>
 MiCPSolverReturnCode MiCPSolverOLD<Program, ncp_t>::solve(Eigen::VectorXd &x)
 {
     int cnt = 0;
     if (get_options().use_crashing) crashing(x);
     else setup_residuals(x);
     MiCPSolverReturnCode retcode = MiCPSolverReturnCode::NotConvergedYet;
     Eigen::VectorXd update(get_neq());
     while (retcode == MiCPSolverReturnCode::NotConvergedYet)
     {
         DEBUG << "Iteration : " << cnt;
         SPAM << "Solution : \n" << x;
         m_program->hook_start_iteration(x, m_phi_residuals.norm());
         setup_residuals(x);
         get_perf().current_residual = m_phi_residuals.norm();
         SPAM << "Residuals : \n ----- \n" << m_phi_residuals << "\n ----- \n";
         retcode = check_convergence(cnt, update, x);
         get_perf().return_code = retcode;
         if (retcode != MiCPSolverReturnCode::NotConvergedYet) break;
         ++cnt;
         m_max_taken = false;
         setup_jacobian(x);
         if(get_options().use_scaling)
             search_direction_calculation(update);
         else
             search_direction_calculation_no_scaling(update);
         reformulate_result<ncp_t>(get_neq(), get_neq_free(),
                 x, m_residuals,
                 m_grad_phi, update);
         int termcode = linesearch(update, x);
         get_perf().current_update = update.norm();
         DEBUG << "Return LineSearch : " << termcode;
         projection(x);
         get_perf().nb_iterations = cnt;
     }
     return retcode;
 }
 
 template <class Program, NCPfunction ncp_t>
 MiCPSolverReturnCode MiCPSolverOLD<Program, ncp_t>::check_convergence(int nb_iterations,
                                             Eigen::VectorXd& update,
                                             Eigen::VectorXd& solution)
 {
     MiCPSolverReturnCode termcode = MiCPSolverReturnCode::NotConvergedYet;
     const double norm_residuals = m_phi_residuals.lpNorm<Eigen::Infinity>();
     if (norm_residuals < get_options().fvectol)
     {
         termcode = MiCPSolverReturnCode::ResidualMinimized;
     }
     else if (nb_iterations >0 and norm_update<Eigen::Infinity>(update, solution) < get_options().steptol)
     {
         if (norm_residuals > get_options().threshold_stationary_point)
         {
             ERROR << "Stationary point detected !";
             termcode = MiCPSolverReturnCode::StationaryPoint;
         }
         WARNING << "Error is minimized - may indicate a stationnary point";
         termcode = MiCPSolverReturnCode::ErrorMinimized;
     }
     else if (nb_iterations >  get_options().max_iter)
     {
         ERROR << "Maximum number of iteration reached (" << get_options().max_iter << ")";
         termcode = MiCPSolverReturnCode::MaxIterations;
     }
     else if (m_max_taken)
     {
         ++m_consec_max;
         if (m_consec_max == get_options().maxiter_maxstep) {
             ERROR << "Divergence detected - Maximum step length taken two many times";
             termcode = MiCPSolverReturnCode::MaxStepTakenTooManyTimes;
         }
     }
     else
     {
         m_consec_max = 0;
     }
     return termcode;
 }
 
 
 template <class Program, NCPfunction ncp_t>
 MiCPSolverReturnCode MiCPSolverOLD<Program, ncp_t>::search_direction_calculation(Eigen::VectorXd& update)
 {
     Eigen::VectorXd rscaler(Eigen::VectorXd::Ones(m_jacobian.cols()));
     Eigen::VectorXd cscaler(Eigen::VectorXd::Ones(m_jacobian.rows()));
     scaling_jacobian(m_jacobian, m_phi_residuals, rscaler, cscaler);
     m_jacobian = rscaler.asDiagonal() * (m_jacobian) * cscaler.asDiagonal();
     Eigen::ColPivHouseholderQR<Eigen::MatrixXd> solver;
     m_gradient_step_taken = false;
     int m;
     for (m=0; m<get_options().max_factorization_step; ++m)
     {
         const double lambda = get_options().factor_gradient_search_direction;
         solver.compute(m_jacobian);
         get_perf().nb_factorization += 1;
         if (solver.info() != Eigen::Success or not solver.isInvertible())
         {
             DEBUG << "Solver.info : " << solver.info() << " - is invertible : " << solver.isInvertible();
             ERROR << "System cannot be solved, we try a perturbation";
             m_gradient_step_taken = true;
             m_jacobian +=  rscaler.asDiagonal() * (
                         lambda*Eigen::MatrixXd::Identity(m_jacobian.rows(),m_jacobian.cols())) * cscaler.asDiagonal();
             continue;
         }
         double cond = estimate_condition_number(solver.matrixR().triangularView<Eigen::Upper>());
         if (cond > get_options().condition_limit)
         {
             m_gradient_step_taken = true;
             m_jacobian +=  rscaler.asDiagonal() * (
                         lambda*Eigen::MatrixXd::Identity(m_jacobian.rows(),m_jacobian.cols())) * cscaler.asDiagonal();
             continue;
         }
         update = solver.solve(-rscaler.cwiseProduct(m_phi_residuals + m*lambda*m_grad_phi));
         update  = cscaler.cwiseProduct(update);
         double descent_cond = m_grad_phi.dot(update);
         double norm_grad = m_grad_phi.norm();
         double norm_update = update.norm();
 
         if (   (descent_cond <= -get_options().factor_descent_condition*std::min(std::pow(norm_update,2),std::pow(norm_update,3)))
                and (descent_cond <= -get_options().factor_descent_condition*std::min(std::pow(norm_grad,2),std::pow(norm_grad,3)))
              )
             break; // we have a solution !
         m_gradient_step_taken = true;
         m_jacobian +=  rscaler.asDiagonal() * ( lambda*
                                                 Eigen::MatrixXd::Identity(m_jacobian.rows(),m_jacobian.cols())
                                                ) * cscaler.asDiagonal();
     }
     DEBUG << "Gradient step : m = " << m;
     if (m == get_options().max_factorization_step) {
         INFO << "Full gradient step taken !";
         update = -m_grad_phi;
     }
     return MiCPSolverReturnCode::NotConvergedYet;
 }
 
 template <class Program, NCPfunction ncp_t>
 MiCPSolverReturnCode MiCPSolverOLD<Program, ncp_t>::search_direction_calculation_no_scaling(Eigen::VectorXd& update)
 {
     DEBUG << "Solving linear system";
     Eigen::ColPivHouseholderQR<Eigen::MatrixXd> solver;
     m_gradient_step_taken = false;
     int m;
     for (m=0; m<get_options().max_factorization_step; ++m)
     {
         const double lambda = get_options().factor_gradient_search_direction;
         solver.compute(m_jacobian);
         get_perf().nb_factorization += 1;
 
         if (solver.info() != Eigen::Success or not solver.isInvertible()) continue;
         double cond = estimate_condition_number(solver.matrixR().triangularView<Eigen::Upper>());
         if (cond > get_options().condition_limit)
         {
             continue;
         }
         update = solver.solve(-(m_phi_residuals + m*lambda*m_grad_phi));
         double descent_cond = m_grad_phi.dot(update);
         double norm_grad = m_grad_phi.norm();
         double norm_update = update.norm();
 
         if (   (descent_cond <= -get_options().factor_descent_condition*std::min(std::pow(norm_update,2),std::pow(norm_update,3)))
                and (descent_cond <= -get_options().factor_descent_condition*std::min(std::pow(norm_grad,2),std::pow(norm_grad,3)))
              )
             break; // we have a solution !
         m_gradient_step_taken = true;
         m_jacobian +=  lambda*Eigen::MatrixXd::Identity(m_jacobian.rows(),m_jacobian.cols());
     }
     DEBUG << "Gradient step : m = " << m;
     if (m ==4) {
         INFO << "Full gradient step taken !";
         update = -m_grad_phi;
     }
     return MiCPSolverReturnCode::NotConvergedYet;
 }
 
 template <class Program, NCPfunction ncp_t>
 void MiCPSolverOLD<Program, ncp_t>::crashing(Eigen::VectorXd &x)
 {
     DEBUG << "Crashing ";
     const double beta = 0.5;
     const double sigma = 1e-5;
     int cnt = 0;
     while (cnt < 10)
     {
         setup_residuals(x);
         setup_jacobian(x);
         m_grad_phi = m_jacobian.transpose()*m_phi_residuals;
         Eigen::VectorXd xp(get_neq());
         int l=0;
         const int maxl = 10;
         while (l<maxl)
         {
             xp = x - std::pow(beta, l)*m_grad_phi;
             for (int i=get_neq_free(); i<get_neq(); ++i)
             {
                 if (xp(i) < 0) xp(i) = 0;
             }
             Eigen::VectorXd new_res(get_neq());
             compute_residuals(x, new_res);
             reformulate_residuals_inplace(x, new_res);
             double test = 0.5*(new_res.squaredNorm() - m_phi_residuals.squaredNorm())  + sigma*m_grad_phi.dot(x - xp);
             if (test <= 0) break;
             ++l;
         }
         if (l == maxl) break;
         x = xp;
 
         ++cnt;
     }
     get_perf().nb_crashing_iterations = cnt;
     DEBUG << "Crashing iterations : " << cnt;
     m_max_merits.reserve(4);
     SPAM << "Solution after crashing \n ------ \n " << x << "\n ----- \n";
 }
 
 // Others
 // ######
 
 template <class Program, NCPfunction ncp_t>
 void MiCPSolverOLD<Program, ncp_t>::reformulate_residuals(const Eigen::VectorXd& x,
                                                 const Eigen::VectorXd& r,
                                                 Eigen::VectorXd& r_phi)
 {
     r_phi.resizeLike(r);
     r_phi.block(0, 0, get_neq_free(), 1) = r.block(0, 0, get_neq_free(), 1);
     for (int i =  get_neq_free(); i<get_neq(); ++i)
     {
         r_phi(i) = phi_lower_bounded(x(i), r(i), 0);
     }
 }
 
 template <class Program, NCPfunction ncp_t>
 void MiCPSolverOLD<Program, ncp_t>::reformulate_residuals_inplace(const Eigen::VectorXd& x,
                                                 Eigen::VectorXd& r)
 {
     for (int i =  get_neq_free(); i<get_neq(); ++i)
     {
         r(i) = phi_lower_bounded(x(i), r(i), 0);
     }
 }
 
 
 // ref : Munson et al. (2001)
 template <class Program, NCPfunction ncp_t>
 void MiCPSolverOLD<Program, ncp_t>:: scaling_jacobian(
         const Eigen::MatrixXd& jacobian,
         const Eigen::VectorXd& r_phi,
         Eigen::VectorXd& rscaler,
         Eigen::VectorXd& cscaler)
 {
     for (int i=0; i<jacobian.cols(); ++i)
     {
         const double sumhsq = jacobian.row(i).array().square().sum();
         double s = std::sqrt(r_phi(i)*r_phi(i) + sumhsq);
         rscaler(i) = 1.0/std::max(s, 1e-10);
     }
     for (int i=0; i<jacobian.cols(); ++i)
     {
         const double sumhsq = (rscaler.asDiagonal()*jacobian).col(i).array().square().sum();
         double s = std::sqrt(sumhsq);
         cscaler(i) = 1.0/std::max(s, 1e-10);
     }
 }
 
 
 template <class Program, NCPfunction ncp_t>
 int MiCPSolverOLD<Program, ncp_t>::linesearch(Eigen::VectorXd& p, Eigen::VectorXd& x)
 {
      // Reference Algo A6.3.1 : Dennis and Schnabel (1983)
     DEBUG << "Linesearch";
     Eigen::VectorXd xp(get_neq());
     Eigen::VectorXd new_res(get_neq());
     double fcp;
 
     m_max_taken = false;
     int retcode = 2;
     const double alpha = 1e-6;
     double newtlen = is_step_too_long(p);
     double init_slope = m_grad_phi.dot(p);
     double rellength = std::abs(p(0));
     for (int i=1; i<get_neq(); ++i)
     {
         rellength = std::max(rellength, std::abs(p(i)));
     }
     double minlambda = get_options().steptol / rellength;
     double lambda = m_program->max_lambda(x, p);
     double lambda_prev = lambda;
 
     // non monotone linesearch
     // -----------------------
 
     double merit_value = 0.5*m_phi_residuals.squaredNorm();
     // new residual
     xp = x + lambda*p;
     compute_residuals(xp, new_res);
     reformulate_residuals_inplace(xp, new_res);
     fcp = 0.5*new_res.squaredNorm();
 
     // Skip linesearch if enough progress is done
     if (fcp < get_options().coeff_accept_newton_step *merit_value)
     {
         if (m_max_merits.size() > 0) m_max_merits[m_max_merits.size()-1] = merit_value;
         else m_max_merits.push_back(merit_value);
         x = xp;
         return 0;
     }
 
     //std::cout << "Merit value : " << merit_value << std::endl;
     double mmax = merit_value;
     if (m_max_merits.size() > 0)
     {
         mmax = m_max_merits[m_max_merits.size()-1];
     }
     if (m_max_merits.size() < 4)
     {
         m_max_merits.push_back(merit_value);
         if (merit_value < mmax) merit_value = (3*merit_value + mmax)/4;
     }
     else if (merit_value < mmax)
     {
         m_max_merits[3] = merit_value;
         merit_value = mmax;
     }
     if (m_gradient_step_taken)
     {
         merit_value *= 100;
     }
     //std::cout << "Merit value used : " << merit_value << std::endl;
     double fc = merit_value;
     double fcp_prev;
     int cnt = 0;
     do
     {
         fcp = 0.5*new_res.squaredNorm();
         //std::cout << "fcp : " << fcp << "\n fc+alin : " << fc+alpha*lambda*init_slope << " # fc : " << fc << std::endl;
         if (fcp <= fc - std::min(-alpha*lambda*init_slope,(1-alpha)*fc)) //pg760 Fachinei2003
         {
             retcode = 0;
             if (lambda ==1 and (newtlen > 0.99 * get_options().maxstep)) {
                 m_max_taken = true;
             }
             break;
         }
         else if (lambda < minlambda)
         {
             retcode = 1;
             break;
         }
         else
         {
             double lambdatmp;
             if (cnt == 0) { // only a quadratic at the first
                 lambdatmp = - init_slope / (2*(fcp - fc -init_slope));
             }
             else
             {
                 const double factor = 1 /(lambda - lambda_prev);
                 const double x1 = fcp - fc - lambda*init_slope;
                 const double x2 = fcp_prev - fc - lambda_prev*init_slope;
 
                 const double a = factor * ( x1/(lambda*lambda) - x2/(lambda_prev*lambda_prev));
                 const double b = factor * ( -x1*lambda_prev/(lambda*lambda) + x2*lambda/(lambda_prev*lambda_prev));
 
                 if (a == 0)
                 { // cubic interpolation is in fact a quadratic interpolation
                     lambdatmp = - init_slope/(2*b);
                 }
                 else
                 {
                     const double disc = b*b-3*a*init_slope;
                     lambdatmp = (-b+std::sqrt(disc))/(3*a);
                 }
                 if (lambdatmp > 0.5*lambda ) lambdatmp = 0.5*lambda;
             }
             lambda_prev = lambda;
             fcp_prev = fcp;
             if (lambdatmp < 0.1*lambda) {
                 lambda = 0.1 * lambda;
             } else {
                 lambda = lambdatmp;
             }
         }
         xp = x + lambda*p;
         compute_residuals(xp, new_res);
         reformulate_residuals_inplace(xp, new_res);
         ++cnt;
     } while(retcode == 2 and cnt < 100);
     DEBUG << "Lambda : " << lambda;
     if (cnt == 100)
     {
         ERROR << "Too much linesearch iterations ! We stop";
     }
     x = xp;
     p = lambda*p;
     return retcode;
 
 }
 
 // Projection of the variables onto the feasible set
 template <class Program, NCPfunction ncp_t>
 void MiCPSolverOLD<Program, ncp_t>::projection(Eigen::VectorXd &x)
 {
     for (int i=0; i<m_program->nb_complementarity_variables(); ++i)
     {
         if (x(i+m_program->nb_free_variables()) < get_options().projection_min_variable)
         {
             x(i+m_program->nb_free_variables()) = 0;
         }
     }
 }
 
 template <class Program, NCPfunction ncp_t>
 double MiCPSolverOLD<Program, ncp_t>::is_step_too_long(Eigen::VectorXd& update)
 {
     double steplength = update.norm();
     if (steplength > get_options().maxstep)
     {
         m_max_taken = true;
         update  = get_options().maxstep / steplength * update;
         steplength = get_options().maxstep;
     }
     return steplength;
 }
 
 
 // ================================================= //
 //                                                   //
 //         NCP functions and reformulation           //
 //                                                   //
 // ================================================= //
 
 template <>
 inline double ncp_function<NCPfunction::penalizedFB>(double a, double b, double t)
 {
     return penalized_fisher_burmeister(a, b, t);
 }
 
 template <>
 inline double ncp_function<NCPfunction::min>(double a, double b, double _)
 {
     return std::min(a, b);
 }
 
 template <>
 inline void reformulate_jacobian_helper<NCPfunction::penalizedFB>(
         int neq,
         int neq_free,
         const Eigen::VectorXd& x,
         const Eigen::VectorXd& r,
         Eigen::MatrixXd& jacobian,
         Eigen::VectorXd& _,
         double t
         )
 {
     // set the z vector : contains 1 for degenerate points
     Eigen::VectorXd z(Eigen::VectorXd::Zero(neq));
     for (int i=neq_free; i<neq; ++i)
     {
         if (x(i) == 0 and r(i) == 0)
             z(i) = 1.0;
     }
     // modify the jacobian
     const double lambda = t;
     for (int i=neq_free; i<neq; ++i)
     {
         Eigen::VectorXd grad_fi = jacobian.block(i, 0, 1, neq).transpose();
         if (z(i) != 0)
         {
             double gpdotz = grad_fi.dot(z);
             double s = std::abs(z(i)) + std::abs(gpdotz);
             s = s * std::sqrt(z(i)*z(i)/(s*s) + gpdotz*gpdotz/(s*s));
             const double c = lambda*(z(i)/s - 1);
             const double d = lambda*(gpdotz/s -1);
             grad_fi = d*grad_fi;
             grad_fi(i) += c;
         }
         else
         {
             double s = std::abs(x(i)) + std::abs(r(i));
             s = s * std::sqrt(x(i)*x(i)/(s*s) + r(i)*r(i)/(s*s));
             double c = lambda*(x(i)/s - 1);
             double d = lambda*(r(i)/s - 1);
             if ((lambda <1) and (r(i) > 0)  and (x(i) >0))
             {
                 c -= (1-lambda)*r(i);
                 d -= (1-lambda)*x(i);
             }
 
             grad_fi = d*grad_fi;
             grad_fi(i) += c;
         }
         jacobian.block(i, 0, 1, neq) = grad_fi.transpose();
     }
 }
 
 template <>
 inline void reformulate_jacobian_helper<NCPfunction::min>(
         int neq,
         int neq_free,
         const Eigen::VectorXd& x,
         const Eigen::VectorXd& r,
         Eigen::MatrixXd& jacobian,
         Eigen::VectorXd& r_phi,
         double _
         )
 {
     std::vector<int> to_keep;
     to_keep.reserve(10);
     Eigen::VectorXd to_remove(neq-neq_free);
     for (int i=neq_free; i<neq; ++i)
     {
         if (x(i) >= r(i))
         {
             to_remove(i-neq_free) = 0;
             to_keep.push_back(i);
         }
         else
             to_remove(i-neq_free) = x(i);
     }
     r_phi.block(0, 0, neq_free, 1) -= jacobian.block(0, neq_free, neq_free, neq-neq_free)*to_remove;
     int new_i = neq_free;
     for (auto it=to_keep.begin(); it!=to_keep.end(); ++it)
     {
         //r_phi.block(0, 0, neq_free, 1) += x(*it)*jacobian.block(0, *it, neq_free, 1);
         jacobian.block(new_i, 0, 1, neq_free) = jacobian.block(*it, 0, 1, neq_free); // the bottom right corner is 0
         jacobian.block(0, new_i, neq_free, 1) = jacobian.block(0, *it, neq_free, 1);
         r_phi(new_i) = r_phi(*it);
         ++new_i;
 
     }
     r_phi.conservativeResize(new_i);
     jacobian.conservativeResize(new_i, new_i);
     DEBUG << jacobian;
 }
 
 
 template <>
 inline void reformulate_result<NCPfunction::penalizedFB>(
         int neq,
         int neq_free,
         Eigen::VectorXd& x,
         const Eigen::VectorXd& orig_r,
         Eigen::VectorXd& grad_phi,
         Eigen::VectorXd& update
         )
 {}
 
 template <>
 inline void reformulate_result<NCPfunction::min>(
         int neq,
         int neq_free,
         Eigen::VectorXd& x,
         const Eigen::VectorXd& orig_r,
         Eigen::VectorXd& grad_phi,
         Eigen::VectorXd& update
         )
 {
     //std::cout << " Update \n ------- \n " << update << std::endl;
     int tot_to_keep = 0;
     for (int i=neq_free; i<neq; ++i)
     {
         if (x(i) >= orig_r(i))
             ++tot_to_keep;
     }
     //std::cout << " update \n ------ \n" << update.block(neq_free, 0, tot_to_keep, 1) << std::endl;
     update.conservativeResize(neq);
     grad_phi.conservativeResize(neq);
     int kept_i = 1;
     for (int i=neq-1; i>=neq_free; --i)
     {   // we go backwards to avoid extra copies
         //std::cout << i << " # " << x(i) << " - " << orig_r(i) << std::endl;
         if (x(i) >= orig_r(i))
         {
             //std::cout << i << std::endl;
             update(i) = update(neq_free+(tot_to_keep-kept_i));
             //std::cout << update(i) << std::endl;
             grad_phi(i) = grad_phi(neq_free+(tot_to_keep-kept_i));
             ++kept_i;
         }
         else
         {
             //x(i) = 0.0;
             //update(i) = 0.0;
             update(i) = -x(i);
             grad_phi(i) = x(i);
         }
     }
 }
 
 } // end namespace micpsolver
 } // end namespace specmicp
diff --git a/src/micpsolver/ncp_function.hpp b/src/micpsolver/ncp_function.hpp
index 7273f2b..e04ef06 100644
--- a/src/micpsolver/ncp_function.hpp
+++ b/src/micpsolver/ncp_function.hpp
@@ -1,92 +1,88 @@
 /*-------------------------------------------------------
 
- - Module : micpsolver
- - File : ncp_function.hpp
- - Author : Fabien Georget
-
-Copyright (c) 2014, Fabien Georget <fabieng@princeton.edu>, Princeton University
+Copyright (c) 2014,2015 Fabien Georget <fabieng@princeton.edu>, Princeton University
 All rights reserved.
 
 Redistribution and use in source and binary forms, with or without
 modification, are permitted provided that the following conditions are met:
     * Redistributions of source code must retain the above copyright
       notice, this list of conditions and the following disclaimer.
     * Redistributions in binary form must reproduce the above copyright
       notice, this list of conditions and the following disclaimer in the
       documentation and/or other materials provided with the distribution.
     * Neither the name of the Princeton University nor the
       names of its contributors may be used to endorse or promote products
       derived from this software without specific prior written permission.
 
 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
 ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 ---------------------------------------------------------*/
 
 #ifndef SPECMICP_MICPSOLVE_NCPFUNCTION_HPP
 #define SPECMICP_MICPSOLVE_NCPFUNCTION_HPP
 
 #include <cassert>
 
 //! \file ncp_function.hpp implements the ncp function
 
 namespace specmicp {
 namespace micpsolver {
 
 //! \brief The Fisher-Burmeister NCP-function
 //!
 //! @param a a scalar, first argument of the NCP-function
 //! @param b a scalar, second argument of the NCP-function
 //!
 //!  References:
 //!     - \cite Munson2001
 //!     - \cite Facchinei2003
 template <typename ScalarT>
 ScalarT fisher_burmeister(ScalarT a, ScalarT b)
 {
     ScalarT s = std::abs(a) + std::abs(b);
     if (s != 0)
     {
         s = s*std::sqrt((a*a)/(s*s) + (b*b)/(s*s));
     }
     if ( a + b <= 0)
     {
         return s - (a + b);
     }
     else
     {
         return -2*a*b/(s + (a+b));
     }
 }
 
 //! \brief The penalized Fisher-Burmeister NCP-function
 //!
 //! @param t in (0, 1), penalization factor
 //! @param a a scalar, first argument of the NCP-function
 //! @param b a scalar, second argument of the NCP-function
 //!
 //! References:
 //!     - \cite Chen1997a
 //!     - \cite Chen2000
 //!     - \cite Munson2001
 template <typename ScalarT>
 inline ScalarT penalized_fisher_burmeister(ScalarT a, ScalarT b, ScalarT t)
 {
     assert(t >= 0);
     assert(t <= 1);
     return t*fisher_burmeister(a,b)-(1-t)*std::max(0.0, a)*std::max(0.0, b);
 }
 
 
 } // end namespace micpsolver
 } // end namespace specmicp
 
 #endif // SPECMICP_MICPSOLVE_NCPFUNCTION_HPP
diff --git a/src/odeint/butcher_tableau.hpp b/src/odeint/butcher_tableau.hpp
index 109ebc0..bf2057a 100644
--- a/src/odeint/butcher_tableau.hpp
+++ b/src/odeint/butcher_tableau.hpp
@@ -1,108 +1,103 @@
 /*-------------------------------------------------------
 
- - Module : odeint
- - File : butcher_tableau.hpp
- - Author : Fabien Georget
-
-Copyright (c) 2014, Fabien Georget <fabieng@princeton.edu>, Princeton University
+Copyright (c) 2014,2015 Fabien Georget <fabieng@princeton.edu>, Princeton University
 All rights reserved.
 
 Redistribution and use in source and binary forms, with or without
 modification, are permitted provided that the following conditions are met:
     * Redistributions of source code must retain the above copyright
       notice, this list of conditions and the following disclaimer.
     * Redistributions in binary form must reproduce the above copyright
       notice, this list of conditions and the following disclaimer in the
       documentation and/or other materials provided with the distribution.
     * Neither the name of the Princeton University nor the
       names of its contributors may be used to endorse or promote products
       derived from this software without specific prior written permission.
 
 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
 ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 ---------------------------------------------------------*/
-
 #ifndef SPECMICP_ODEINT_BUTCHERTABLEAU_HPP
 #define SPECMICP_ODEINT_BUTCHERTABLEAU_HPP
 
 //! \file butcher_tableau.hpp Butcher tableau for embedded runge kutta method
 
 #include <array>
 #include "common.hpp"
 
 namespace specmicp {
 namespace odeint {
 
 template <int order, int s>
 class ButcherTableau {
 public:
     static const int RK_order = order;
     static const int RK_evaluations = s+1;
 
     ButcherTableau(const std::array<scalar_t, s>& aa,
                    const std::array<std::array<scalar_t, s>, s>& ba,
                    const std::array<scalar_t, s+1>& ca,
                    const std::array<scalar_t, s+1>& csa
                    ):
         m_a(aa), m_b(ba), m_c(ca), m_cs(csa)
     {}
     ButcherTableau(std::array<scalar_t, s>&& aa,
                    std::array<std::array<scalar_t, s>, s>&& ba,
                    std::array<scalar_t, s+1>&& ca,
                    std::array<scalar_t, s+1>&& csa
                    ):
         m_a(aa), m_b(ba), m_c(ca), m_cs(csa)
     {}
     double a(int i) const {return m_a[i-2];}
     double b(int i, int j) const {return m_b[i-2][j-1];}
     double c(int i) const {return m_c[i-1];}
     double cs(int i) const {return m_cs[i-1];}
 
 
 private:
     std::array<scalar_t, s> m_a;
     std::array<std::array<scalar_t, s>, s> m_b;
     std::array<scalar_t, s+1> m_c;
     std::array<scalar_t, s+1> m_cs;
 };
 
 const ButcherTableau<5, 5> butcher_cash_karp45({1.0/5.0, 3.0/10.0, 3.0/5.0, 1.0, 7.0/8.0},
                                    {{{1.0/5.0, 0, 0, 0, 0},
                                      {3.0/40.0, 9.0/40.0, 0, 0, 0},
                                      {3.0/10.0, -9.0/10.0, 6.0/5.0, 0, 0},
                                      {-11.0/54.0, 5.0/2.0, -70.0/27.0, 35.0/27.0, 0},
                                      {1631.0/55296.0, 175.0/512.0, 575.0/13824.0, 44275.0/110592.0, 253.0/4096.0}
                                    }},
                                    {37.0/378.0, 0.0, 250.0/621.0, 125.0/594.0, 0.0, 512.0/1771.0},
                                    {2825.0/27648.0, 0.0, 18575.0/48384.0, 13525.0/55296.0, 277.0/14336.0, 1.0/4.0}
                                    );
 using ButcherTableauCashKarp_t = ButcherTableau<5, 5>;
 
 const ButcherTableau<5, 6> butcher_dormand_prince45(
                                 {1.0/5.0, 3.0/10.0, 4.0/5.0, 8.0/9.0, 1.0, 1.0},
                                    { {{1.0/5.0, 0, 0, 0, 0, 0},
                                      {3.0/40.0, 9.0/40.0, 0, 0, 0, 0},
                                      {44.0/45.0, -56.0/15.0, 32.0/9.0, 0, 0, 0},
                                      {19372.0/6561.0, -25360.0/2187.0, 64448.0/6561.0, -212.0/729.0, 0, 0},
                                      {9017.0/3168.0, -355.0/33.0, 46732.0/5247.0, 49.0/176.0, -5103.0/18656.0, 0},
                                      {35.0/384.0, 0.0, 500.0/1113.0, 125.0/192.0, -2187.0/6784.0, 11.0/84.0}
                                    }},
                                     {35.0/384.0, 0.0, 500.0/1113.0, 125.0/192.0, -2187.0/6784.0, 11.0/84.0, 0.0},
                                    {5179.0/57600.0, 0.0, 7571.0/16695.0, 393.0/640.0, -92097.0/339200.0, 187.0/2100.0, 1.0/40.0}
                                    );
 using ButcherTableauDormandPrince_t = ButcherTableau<5, 6>;
 
 } // end namespace odeint
 } // end namespace specmicp
 
 
 #endif // SPECMICP_ODEINT_BUTCHERTABLEAU_HPP
diff --git a/src/odeint/odeint_types.hpp b/src/odeint/odeint_types.hpp
index 741e79b..8e9af14 100644
--- a/src/odeint/odeint_types.hpp
+++ b/src/odeint/odeint_types.hpp
@@ -1,123 +1,119 @@
 /*-------------------------------------------------------
 
- - Module : odeint
- - File : odeint_types.hpp
- - Author : Fabien Georget
-
-Copyright (c) 2014, Fabien Georget <fabieng@princeton.edu>, Princeton University
+Copyright (c) 2014,2015 Fabien Georget <fabieng@princeton.edu>, Princeton University
 All rights reserved.
 
 Redistribution and use in source and binary forms, with or without
 modification, are permitted provided that the following conditions are met:
     * Redistributions of source code must retain the above copyright
       notice, this list of conditions and the following disclaimer.
     * Redistributions in binary form must reproduce the above copyright
       notice, this list of conditions and the following disclaimer in the
       documentation and/or other materials provided with the distribution.
     * Neither the name of the Princeton University nor the
       names of its contributors may be used to endorse or promote products
       derived from this software without specific prior written permission.
 
 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
 ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 ---------------------------------------------------------*/
 
 #ifndef SPECMICP_ODEINT_ODEINTTYPES_HPP
 #define SPECMICP_ODEINT_ODEINTTYPES_HPP
 
 //! \file odeint_types.hpp common types for odeint
 
 #include "common.hpp"
 #include <functional>
 #include <Eigen/Core>
 
 namespace specmicp {
 namespace odeint {
 
 namespace internal {
 
 //! \brief implementation for the vector type (which may not be a vector for dim=1)
 template <int dim>
 struct vector_trait
 {
     using type = Eigen::Matrix<scalar_t, Eigen::Dynamic, 1>;
 };
 
 //! Specialisation for dimension 1 (scalar)
 template <>
 struct vector_trait<1>
 {
     using type = scalar_t;
 };
 
 //! Specialization for dimension 2 (fixed-size vector)
 template <>
 struct vector_trait<2>
 {
     using type = Eigen::Matrix<scalar_t, 2, 1>;
 };
 
 //! Specialization for dimension 3 (fixed-size vector)
 template <>
 struct vector_trait<3>
 {
     using type = Eigen::Matrix<scalar_t, 3, 1>;
 };
 
 
 } // end namespace internal
 
 //! The vector type
 template <int dim>
 using vector_t = typename internal::vector_trait<dim>::type;
 
 //! Return the maximum coefficient of the vector
 template <int dim>
 inline scalar_t max_coeff(const vector_t<dim>& vec) {return vec.maxCoeff();}
 
 template <>
 inline scalar_t max_coeff<1>(const vector_t<1>& vec) {return vec;}
 
 //! \brief Type of the function f in dy/dx=f(x,y)
 template <int dim>
 using rhs_f = std::function<void (scalar_t, const vector_t<dim>&, vector_t<dim>&)>;
 
 //! \brief Return true of all members of 'vec' are non-negative
 template <int dim>
 inline bool is_nonnegative(vector_t<dim>& vec)
 {
     return (vec.array() >= Eigen::VectorXd::Zero(vec.rows()).array()).all();
 }
 
 template <>
 inline bool is_nonnegative<1>(vector_t<1>& vec)
 {
     return vec >= 0.0;
 }
 
 //! \brief Project to the positive quadrant
 template <int dim>
 inline void set_non_negative(vector_t<dim>& vec)
 {
     vec = vec.cwiseMax(Eigen::VectorXd::Zero(vec.rows()));
 }
 
 template <>
 inline void set_non_negative<1>(vector_t<1>& vec)
 {
     vec = std::max(0.0, vec);
 }
 
 } // end namespace odeint
 } // end namespace specmicp
 
 #endif // SPECMICP_ODEINT_ODEINTTYPES_HPP
diff --git a/src/odeint/runge_kutta_step.inl b/src/odeint/runge_kutta_step.inl
index c43cfc5..fdae2a2 100644
--- a/src/odeint/runge_kutta_step.inl
+++ b/src/odeint/runge_kutta_step.inl
@@ -1,124 +1,120 @@
 /*-------------------------------------------------------
 
- - Module : odeint
- - File : runge_kutta_step.cpp
- - Author : Fabien Georget
-
-Copyright (c) 2014, Fabien Georget <fabieng@princeton.edu>, Princeton University
+Copyright (c) 2014,2015 Fabien Georget <fabieng@princeton.edu>, Princeton University
 All rights reserved.
 
 Redistribution and use in source and binary forms, with or without
 modification, are permitted provided that the following conditions are met:
     * Redistributions of source code must retain the above copyright
       notice, this list of conditions and the following disclaimer.
     * Redistributions in binary form must reproduce the above copyright
       notice, this list of conditions and the following disclaimer in the
       documentation and/or other materials provided with the distribution.
     * Neither the name of the Princeton University nor the
       names of its contributors may be used to endorse or promote products
       derived from this software without specific prior written permission.
 
 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
 ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 ---------------------------------------------------------*/
 
 #include "runge_kutta_step.hpp" // syntaxic coloration only
 
 namespace specmicp {
 namespace odeint {
 
 template <int dim, class butcher_tableau_t>
 void EmbeddedRungeKuttaStep45<dim, butcher_tableau_t>::run_step(const vec_t& y,
                                            const vec_t& dydx,
                                            scalar_t x,
                                            scalar_t timestep,
                                            vec_t& y_out,
                                            vec_t& y_err)
 {
     vec_t ak2, ak3, ak4, ak5, ak6;
     vec_t ytemp;
 
     ytemp = y + butcher().b(2, 1)*timestep*dydx;
     get_rhs(x + butcher().a(2)*timestep, ytemp, ak2);
     ytemp = y + timestep*(butcher().b(3,1)*dydx + butcher().b(3, 2)*ak2);
     get_rhs(x + butcher().a(3)*timestep, ytemp, ak3);
     ytemp = y + timestep*(butcher().b(4,1)*dydx + butcher().b(4, 2)*ak2 + butcher().b(4, 3)*ak3);
     get_rhs(x + butcher().a(4)*timestep, ytemp, ak4);
     ytemp = y + timestep*(butcher().b(5,1)*dydx + butcher().b(5, 2)*ak2
                             + butcher().b(5, 3)*ak3 + butcher().b(5, 4)*ak4);
     get_rhs(x + butcher().a(5)*timestep, ytemp, ak5);
     ytemp = y + timestep*(butcher().b(6,1)*dydx + butcher().b(6, 2)*ak2
                           + butcher().b(6, 3)*ak3 + butcher().b(6, 4)*ak4
                           + butcher().b(6, 5)*ak5);
     get_rhs(x + butcher().a(6)*timestep, ytemp, ak6);
 
     if (butcher_tableau_t::RK_evaluations == 6)
     {
     y_out = y + timestep*(butcher().c(1)*dydx + butcher().c(2)*ak2 + butcher().c(3)*ak3
                           + butcher().c(4)*ak4 + butcher().c(5)*ak5 + butcher().c(6)*ak6);
     y_err = timestep * ( (butcher().c(1) - butcher().cs(1))*dydx +  (butcher().c(2) - butcher().cs(2))*ak2 +
                          (butcher().c(3) - butcher().cs(3))*ak3 +  (butcher().c(4) - butcher().cs(4))*ak4 +
                          (butcher().c(5) - butcher().cs(5))*ak5 +  (butcher().c(6) - butcher().cs(6))*ak6
                          );
     }
     else
     {
         vec_t ak7;
         ytemp = y + timestep*(butcher().b(7,1)*dydx + butcher().b(7, 2)*ak2
                               + butcher().b(7, 3)*ak3 + butcher().b(7, 4)*ak4
                               + butcher().b(7, 5)*ak5 + butcher().b(7, 6)*ak6);
         get_rhs(x + butcher().a(7)*timestep, ytemp, ak7);
         y_out = y + timestep*(butcher().c(1)*dydx + butcher().c(2)*ak2 + butcher().c(3)*ak3
                               + butcher().c(4)*ak4 + butcher().c(5)*ak5 + butcher().c(6)*ak6
                               + butcher().c(7)*ak7);
         y_err = timestep * ( (butcher().c(1) - butcher().cs(1))*dydx +  (butcher().c(2) - butcher().cs(2))*ak2 +
                              (butcher().c(3) - butcher().cs(3))*ak3 +  (butcher().c(4) - butcher().cs(4))*ak4 +
                              (butcher().c(5) - butcher().cs(5))*ak5 +  (butcher().c(6) - butcher().cs(6))*ak6 +
                              (butcher().c(7) - butcher().cs(7))*ak7
                              );
     }
     if (get_options().non_negativity)
         set_non_negative<dim>(y_out);
 }
 
 
 template <int dim, class butcher_tableau_t>
 void EmbeddedRungeKuttaStep45<dim, butcher_tableau_t>::rk_step(vector_t<dim>& y,
             const vector_t<dim>& dydx,
             double& x,
             StepLength& stepl)
 {
     vector_t<dim> y_err;
     vector_t<dim> y_temp;
     double h = stepl.test;
     double xnew;
     scalar_t errmax;
     for (int i=0; i<get_options().max_try; ++i)
     {
         run_step(y, dydx, x, h, y_temp, y_err);
         errmax = max_coeff<dim>(y_err) / get_options().eps;
         if (errmax < 1) break;
         double htemp = get_options().safety*h*std::pow(errmax, get_options().p_shrink);
         h = (h >= 0.0 ? std::max(htemp, 0.1*h) : std::min(htemp, 0.1*h));
         xnew = x+h;
         if (xnew == x) {throw std::runtime_error("stepsize underflow");}
     }
     stepl.did = h;
     x += h;
     if (errmax > get_options().errcon) {stepl.next = get_options().safety*h*std::pow(errmax, get_options().p_grow);}
     else {stepl.next = 5.0*h;}
     y = y_temp;
 }
 
 
 } // end namespace odeint
 } // end namespace specmicp
diff --git a/src/odeint/runge_kutta_step_structs.hpp b/src/odeint/runge_kutta_step_structs.hpp
index 319f2c7..a0ea1a5 100644
--- a/src/odeint/runge_kutta_step_structs.hpp
+++ b/src/odeint/runge_kutta_step_structs.hpp
@@ -1,35 +1,64 @@
+/*-------------------------------------------------------
+
+Copyright (c) 2014,2015 Fabien Georget <fabieng@princeton.edu>, Princeton University
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+    * Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+    * Redistributions in binary form must reproduce the above copyright
+      notice, this list of conditions and the following disclaimer in the
+      documentation and/or other materials provided with the distribution.
+    * Neither the name of the Princeton University nor the
+      names of its contributors may be used to endorse or promote products
+      derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+---------------------------------------------------------*/
+
 #ifndef SPECMICP_ODEINT_RUNGEKUTTASTEPSTRUCTS_HPP
 #define SPECMICP_ODEINT_RUNGEKUTTASTEPSTRUCTS_HPP
 
 #include "common.hpp"
 
 namespace specmicp {
 namespace odeint {
 
 struct EmbeddedRungeKuttaStepOptions
 {
     scalar_t safety;
     scalar_t p_grow;
     scalar_t p_shrink;
     scalar_t errcon;
     scalar_t max_try;
     scalar_t eps;
     bool non_negativity;
 
     EmbeddedRungeKuttaStepOptions():
         safety(0.9),
         p_grow(-0.2),
         p_shrink(-0.25),
         errcon(1.89e-4),
         max_try(20),
         eps(1e-5),
         non_negativity(false)
     {}
 };
 
 
 } // end namespace odeint
 } // end namespace specmicp
 
 
 #endif// SPECMICP_ODEINT_RUNGEKUTTASTEPSTRUCTS_HPP
diff --git a/src/physics/constants.hpp b/src/physics/constants.hpp
index 16196ba..5ce0b59 100644
--- a/src/physics/constants.hpp
+++ b/src/physics/constants.hpp
@@ -1,56 +1,52 @@
 /*-------------------------------------------------------
 
- - Module : Physics
- - File : constants
- - Author : Fabien Georget
-
-Copyright (c) 2014, Fabien Georget <fabieng@princeton.edu>, Princeton University
+Copyright (c) 2014,2015 Fabien Georget <fabieng@princeton.edu>, Princeton University
 All rights reserved.
 
 Redistribution and use in source and binary forms, with or without
 modification, are permitted provided that the following conditions are met:
     * Redistributions of source code must retain the above copyright
       notice, this list of conditions and the following disclaimer.
     * Redistributions in binary form must reproduce the above copyright
       notice, this list of conditions and the following disclaimer in the
       documentation and/or other materials provided with the distribution.
     * Neither the name of the Princeton University nor the
       names of its contributors may be used to endorse or promote products
       derived from this software without specific prior written permission.
 
 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
 ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 ---------------------------------------------------------*/
 
 #ifndef SPECMICP_CONSTANTS_CONSTANTS_HPP
 #define SPECMICP_CONSTANTS_CONSTANTS_HPP
 
 //! \file constants Contains physical constants
 
 namespace specmicp {
 namespace constants {
 
 const double gas_constant = 8.3144621; // J / K mol
 
 const double water_density_25 = 997.05; // kg / m^3
 const double water_density_25_kgl = 0.99705; // kg / L
 
 
 const double Adebye = 0.5092; //!< constant 'A' for Debye-Huckel activity coefficient
 const double Bdebye = 0.3283; //!< constant 'B' for Debye-Huckel activity coefficient
 
 const double faraday_constant = 9.6485339924e4 ; //! the Faraday constant
 
 } // end namespace constants
 } // end namespace specmicp
 
 #endif // SPECMICP_CONSTANTS_CONSTANTS_HPP
diff --git a/src/physics/laws.hpp b/src/physics/laws.hpp
index fac056c..dd78093 100644
--- a/src/physics/laws.hpp
+++ b/src/physics/laws.hpp
@@ -1,92 +1,88 @@
 /*-------------------------------------------------------
 
- - Module : physics
- - File : laws
- - Author : Fabien Georget
-
-Copyright (c) 2014, Fabien Georget <fabieng@princeton.edu>, Princeton University
+Copyright (c) 2014,2015 Fabien Georget <fabieng@princeton.edu>, Princeton University
 All rights reserved.
 
 Redistribution and use in source and binary forms, with or without
 modification, are permitted provided that the following conditions are met:
     * Redistributions of source code must retain the above copyright
       notice, this list of conditions and the following disclaimer.
     * Redistributions in binary form must reproduce the above copyright
       notice, this list of conditions and the following disclaimer in the
       documentation and/or other materials provided with the distribution.
     * Neither the name of the Princeton University nor the
       names of its contributors may be used to endorse or promote products
       derived from this software without specific prior written permission.
 
 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
 ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 ---------------------------------------------------------*/
 
 #ifndef SPECMICP_LAWS_LAWS_HPP
 #define SPECMICP_LAWS_LAWS_HPP
 
 //! \file laws Simple physical laws
 
 #include "common.hpp"
 #include "constants.hpp"
 #include "units.hpp"
 #include <cmath>
 
 namespace specmicp {
 namespace laws {
 
 inline constexpr scalar_t pressure_perfect_gas(scalar_t n, scalar_t V, scalar_t T=298.15)
 {
     return n*constants::gas_constant*T/V;
 }
 
 inline constexpr scalar_t mole_perfect_gas(scalar_t P, scalar_t V, scalar_t T=298.15)
 {
     return P*V/(constants::gas_constant*T);
 }
 
 inline scalar_t debye_huckel(scalar_t sqrtI, scalar_t zi, scalar_t ao)
 {
     if (zi != 0)
     {
         scalar_t tmp = - constants::Adebye*std::pow(2, zi)*sqrtI;
         tmp /= (1 + ao*constants::Bdebye*sqrtI);
         return tmp;
     }
     else return 0;
 }
 
 inline scalar_t extended_debye_huckel(scalar_t I, scalar_t sqrtI, scalar_t zi, scalar_t ao, scalar_t bdot)
 {
     scalar_t tmp = debye_huckel(sqrtI, zi, ao);
     return tmp + bdot*I;
 }
 
 inline scalar_t extended_debye_huckel(scalar_t I, scalar_t zi, scalar_t ao, scalar_t bdot)
 {
     scalar_t tmp = debye_huckel(std::sqrt(I), zi, ao);
     return tmp + bdot*I;
 }
 
 inline scalar_t density_water(scalar_t temperature, units::LengthUnit length_unit, units::MassUnit mass_unit)
 {
     scalar_t scaling = 1.0;
     if (mass_unit == units::MassUnit::gram) scaling *= 1e-3;
     if (length_unit == units::LengthUnit::centimeter) scaling *= 1e-6;
     else if (length_unit == units::LengthUnit::decimeter) scaling = 1e-3;
     return scaling*constants::water_density_25;
 }
 
 } // end namespace laws
 } // end namespace specmicp
 
 #endif // SPECMICP_LAWS_LAWS_HPP
diff --git a/src/physics/units.hpp b/src/physics/units.hpp
index f5c9a20..c6ce065 100644
--- a/src/physics/units.hpp
+++ b/src/physics/units.hpp
@@ -1,140 +1,136 @@
 /*-------------------------------------------------------
 
- - Module : Physics
- - File : units.hpp
- - Author : Fabien Georget
-
-Copyright (c) 2014, Fabien Georget <fabieng@princeton.edu>, Princeton University
+Copyright (c) 2014,2015 Fabien Georget <fabieng@princeton.edu>, Princeton University
 All rights reserved.
 
 Redistribution and use in source and binary forms, with or without
 modification, are permitted provided that the following conditions are met:
     * Redistributions of source code must retain the above copyright
       notice, this list of conditions and the following disclaimer.
     * Redistributions in binary form must reproduce the above copyright
       notice, this list of conditions and the following disclaimer in the
       documentation and/or other materials provided with the distribution.
     * Neither the name of the Princeton University nor the
       names of its contributors may be used to endorse or promote products
       derived from this software without specific prior written permission.
 
 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
 ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 ---------------------------------------------------------*/
 
 #ifndef SPECMICP_UNITS_UNITS
 #define SPECMICP_UNITS_UNITS
 
 #include "common.hpp"
 
 //! \file units.hpp units conversion
 
 namespace specmicp {
 namespace units {
 
 //! units used for length
 enum class LengthUnit {
     meter,
     decimeter,
     centimeter
 };
 
 //! units used for mass
 enum class MassUnit {
     kilogram,
     gram
 };
 
 
 //! \brief Simple struct which contains the unit information
 struct UnitsSet
 {
     MassUnit mass; //!< The unit to use for mass
     LengthUnit length; //!< The unit to use for length (also area and volume)
 
     //! \brief Defaults are the SI unit system
     UnitsSet():
         mass(MassUnit::kilogram),
         length(LengthUnit::meter)
     {}
 };
 
 //! \brief Base class that handles the units
 //!
 //!  To be inherited by other classes that need units
 class UnitBaseClass
 {
 public:
     UnitBaseClass() {}
     UnitBaseClass(UnitsSet units):
         m_units(units)
     {}
     //! \brief Return the units
     UnitsSet get_units() {return m_units;}
 
     //! \brief Set the units
     void set_units(UnitsSet units) {m_units = units;}
 
     //! \brief Return the Mass unit
     MassUnit mass_unit() const {return m_units.mass;}
     //! \brief Return the Length unit
     LengthUnit length_unit() const {return m_units.length;}
 
     //! \brief Return the mass unit
     MassUnit& mass_unit() {return m_units.mass;}
     //! \brief Return the length unit
     LengthUnit& length_unit() {return m_units.length;}
 
 private:
     UnitsSet m_units;
 };
 
 // Temperature
 // -----------
 
 //! Convert a temperature from Celsius to Kelvin
 inline constexpr scalar_t celsius(scalar_t tc) {return tc + 273.15;}
 //! Convert a temperature from Kelvin to Celsius
 inline constexpr scalar_t to_celsius(scalar_t tk) { return tk - 273.15;}
 
 // Volume
 // ------
 
 //! Convert liter to cubic meter
 inline constexpr scalar_t liter(scalar_t vl) {return 1e-3*vl;}
 //! convert cubic meter to liter
 inline constexpr scalar_t to_liter(scalar_t vcm) {return 1e3*vcm;}
 
 // Pressure
 // --------
 
 
 inline scalar_t convert_pressure(scalar_t pressure_si, LengthUnit length_unit)
 {
     scalar_t pressure;
     switch (length_unit) {
     case LengthUnit::meter:
         pressure = pressure_si;
         break;
     case LengthUnit::decimeter:
         pressure = 1e-2*pressure_si;
         break;
     case LengthUnit::centimeter:
         pressure = 1e-4*pressure_si;
     }
     return pressure;
 }
 
 } // end namespace units
 } // end namespace specmicp
 
 #endif // SPECMICP_UNITS_UNITS
diff --git a/src/reactmicp/equilibrium_curve/chemistry.cpp b/src/reactmicp/equilibrium_curve/chemistry.cpp
index e7692b6..0e68645 100644
--- a/src/reactmicp/equilibrium_curve/chemistry.cpp
+++ b/src/reactmicp/equilibrium_curve/chemistry.cpp
@@ -1,105 +1,134 @@
+/*-------------------------------------------------------
+
+Copyright (c) 2014,2015 Fabien Georget <fabieng@princeton.edu>, Princeton University
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+    * Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+    * Redistributions in binary form must reproduce the above copyright
+      notice, this list of conditions and the following disclaimer in the
+      documentation and/or other materials provided with the distribution.
+    * Neither the name of the Princeton University nor the
+      names of its contributors may be used to endorse or promote products
+      derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+---------------------------------------------------------*/
+
 #include "chemistry.hpp"
 #include "specmicp/adimensional/adimensional_system_solution_extractor.hpp"
 #include "specmicp/adimensional/adimensional_system_solver.hpp"
 #include "utils/log.hpp"
 #include <iostream>
 
 namespace specmicp {
 namespace reactmicp {
 namespace eqcurve {
 
 // EquilibriumCurveSpeciation::
 
 void EquilibriumCurveSpeciation::output()
 {
     index_t size = m_eqcurve.rows();
     if (m_cnt == size) m_eqcurve.conservativeResize(size+500, 4);
     m_eqcurve.block(size, 0, m_eqcurve.rows()-size, 4).setZero();
 
     AdimensionalSystemSolutionExtractor sol(current_solution(), m_data, get_units());
     m_eqcurve(m_cnt, 0) = sol.total_solid_concentration(m_idc);
     m_eqcurve(m_cnt, 1) = sol.total_aqueous_concentration(m_idc);
     m_eqcurve(m_cnt, 2) = sol.porosity();
     m_eqcurve(m_cnt, 3) = m_eqcurve(m_cnt, 2)>0.92?2.219e-5:1e4*std::exp(9.95*m_eqcurve(m_cnt, 2)-29.08);
 
     std::cout <<  m_eqcurve(m_cnt, 0) << " \t " << m_eqcurve(m_cnt, 1)  << std::endl;
 }
 
 Matrix EquilibriumCurveSpeciation::get_equilibrium_curve(scalar_t end_total_concentration, scalar_t delta)
 {
     m_cnt = 0;
     solve_first_problem();
     output();
 
     AdimensionalSystemSolutionExtractor sol(current_solution(), m_data, get_units());
     index_t nb_steps = std::abs(end_total_concentration - constraints().total_concentrations(m_idc))/(
                 std::abs(delta)*sol.total_aqueous_concentration(m_idc));
     std::cout << nb_steps << std::endl;
     m_eqcurve = Matrix::Zero(nb_steps, 4);
     m_delta = delta; ///(nb_steps-1);
 
     while (constraints().total_concentrations(m_idc) > end_total_concentration)
     {
         //std::cout << m_cnt << " - " << conditions().total_concentrations(m_idc) << std::endl;
         run_step();
         ++m_cnt;
     }
 
     m_eqcurve.conservativeResize(m_cnt, 4);
 
     return m_eqcurve;
 }
 
 void EquilibriumCurveSpeciation::update_problem()
 {
     Vector diff_conc = get_perturbation();
     scalar_t coeff = m_delta;
     for (index_t component: m_data->range_component())
     {
         if (std::abs(constraints().total_concentrations(component)) < 1e-4) {
             constraints().total_concentrations(component) = 0.0;
             diff_conc(component) = 0.0;
         }
         if (constraints().total_concentrations(component) != 0 and
                std::copysign(1.0, constraints().total_concentrations(component) + coeff*diff_conc(component))
             != std::copysign(1.0, constraints().total_concentrations(component))
            )
         {
 
             //std::cout << "Component : " << component << std::endl;
             coeff = std::copysign(0.9*constraints().total_concentrations(component), m_delta);
             coeff /= diff_conc(component);
         }
     }
     //std::cout << "Update : " << std::endl << coeff*diff_conc << std::endl;
 
     constraints().total_concentrations += coeff*diff_conc;
 
 //    std::cout << "total concentrations : " << std::endl <<  conditions().total_concentrations << std::endl;
 }
 
 Vector EquilibriumCurveSpeciation::get_perturbation()
 {
     AdimensionalSystemSolutionExtractor sol(current_solution(), m_data, get_units());
 
     Vector tot_aq_conc(m_data->nb_component());
     tot_aq_conc.setZero();
     for (index_t component: m_data->range_aqueous_component())
     {
         tot_aq_conc(component) = sol.total_aqueous_concentration(component);
     }
     //tot_aq_conc *= m_delta/tot_aq_conc.norm();
     return tot_aq_conc;
 }
 
 void EquilibriumCurveSpeciation::error_handling(std::string msg) const
 {
 
     ERROR << msg;
     ERROR << " Total concentration " << std::endl << constraints().total_concentrations << std::endl;
     throw std::runtime_error(msg);
 }
 
 } // end namespace eqcurve
 } // end namespace reactmicp
 } // end namespace specmicp
diff --git a/src/reactmicp/equilibrium_curve/chemistry.hpp b/src/reactmicp/equilibrium_curve/chemistry.hpp
index 3cd7f03..5c3a9dc 100644
--- a/src/reactmicp/equilibrium_curve/chemistry.hpp
+++ b/src/reactmicp/equilibrium_curve/chemistry.hpp
@@ -1,57 +1,86 @@
+/*-------------------------------------------------------
+
+Copyright (c) 2014,2015 Fabien Georget <fabieng@princeton.edu>, Princeton University
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+    * Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+    * Redistributions in binary form must reproduce the above copyright
+      notice, this list of conditions and the following disclaimer in the
+      documentation and/or other materials provided with the distribution.
+    * Neither the name of the Princeton University nor the
+      names of its contributors may be used to endorse or promote products
+      derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+---------------------------------------------------------*/
+
 #ifndef SPECMICP_REACTMICP_EQUILIBRIUMCURVE_CHEMISTRY_HPP
 #define SPECMICP_REACTMICP_EQUILIBRIUMCURVE_CHEMISTRY_HPP
 
 #include "specmicp/adimensional/equilibrium_curve.hpp"
 #include "physics/units.hpp"
 
 namespace specmicp {
 namespace reactmicp {
 
 //! \namespace eqcurve Equilibrium approach to reactive transport
 namespace eqcurve {
 
 class EquilibriumCurveSpeciation:
         public EquilibriumCurve,
         public units::UnitBaseClass
 {
 public:
     EquilibriumCurveSpeciation(
             RawDatabasePtr thedatabase,
             AdimensionalSystemConstraints constraints,
             index_t id_component,
             AdimensionalSystemSolverOptions options
             ):
         EquilibriumCurve(thedatabase, constraints),
         UnitBaseClass(options.units_set),
         m_data(thedatabase),
         m_idc(id_component)
     {
         solver_options() = options;
     }
 
     void output();
 
     void update_problem();
 
     Matrix get_equilibrium_curve(scalar_t end_total_concentration, scalar_t delta);
 
     Vector get_perturbation();
 
     void error_handling(std::string msg) const;
 
 private:
     RawDatabasePtr m_data;
 
     index_t m_idc;
 
     Matrix m_eqcurve;
 
     index_t m_cnt;
     scalar_t m_delta;
 };
 
 } // end namespace eqcurve
 } // end namespace reactmicp
 } // end namespace specmicp
 
 #endif // SPECMICP_REACTMICP_EQUILIBRIUMCURVE_CHEMISTRY_HPP
diff --git a/src/reactmicp/equilibrium_curve/eqcurve_coupler.cpp b/src/reactmicp/equilibrium_curve/eqcurve_coupler.cpp
index 940f1f0..207d63a 100644
--- a/src/reactmicp/equilibrium_curve/eqcurve_coupler.cpp
+++ b/src/reactmicp/equilibrium_curve/eqcurve_coupler.cpp
@@ -1,77 +1,106 @@
+/*-------------------------------------------------------
+
+Copyright (c) 2014,2015 Fabien Georget <fabieng@princeton.edu>, Princeton University
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+    * Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+    * Redistributions in binary form must reproduce the above copyright
+      notice, this list of conditions and the following disclaimer in the
+      documentation and/or other materials provided with the distribution.
+    * Neither the name of the Princeton University nor the
+      names of its contributors may be used to endorse or promote products
+      derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+---------------------------------------------------------*/
+
 #include "eqcurve_coupler.hpp"
 
 #include "dfpm/meshes/mesh1d.hpp"
 #include "dfpm/1dtransport/diffusion_parameters.hpp"
 
 #include "dfpmsolver/parabolic_driver.hpp"
 
 namespace specmicp {
 namespace reactmicp {
 namespace eqcurve {
 
 EquilibriumCurveCoupler::EquilibriumCurveCoupler(Matrix& eq_curve,
                         mesh::Mesh1DPtr the_mesh
                         , dfpmsolver::ParabolicDriverOptions options):
     m_eqcurve(eq_curve),
     m_mesh(the_mesh),
     m_param(std::make_shared<dfpm::SaturatedDiffusion1DParameters>(m_mesh->nb_nodes())),
     m_aqueous_concentrations(the_mesh->nb_nodes()),
     m_solid_concentrations(the_mesh->nb_nodes()),
     m_transport_program(the_mesh, m_param, {0,}),
     m_transport_solver(m_transport_program)
 {
 
     m_transport_solver.get_options() = options;
 
     index_t last = m_eqcurve.last();
     m_aqueous_concentrations(0) = m_eqcurve.totaq_concentration(last);
     m_solid_concentrations(0) = m_eqcurve.totsolid_concentration(last);
     m_param->porosity(0) = m_eqcurve.porosity(last);
     m_param->diffusion_coefficient(0) = m_eqcurve.diffusion_coefficient(last);
 
     index_t first = m_eqcurve.first();
     for (index_t node=1; node<the_mesh->nb_nodes(); ++node)
     {
         m_aqueous_concentrations(node) = m_eqcurve.totaq_concentration(first);
         m_solid_concentrations(node) = m_eqcurve.totsolid_concentration(first);
         m_param->porosity(node) = m_eqcurve.porosity(first);
         m_param->diffusion_coefficient(node) = m_eqcurve.diffusion_coefficient(first);
     }
 }
 
 void EquilibriumCurveCoupler::run_step(scalar_t timestep)
 {
     dfpmsolver::ParabolicDriverReturnCode retcode = m_transport_solver.solve_timestep(timestep, m_aqueous_concentrations);
     if (retcode <= dfpmsolver::ParabolicDriverReturnCode::NotConvergedYet)
     {
         throw std::runtime_error("Cannot solve the transport problem, retcode : "+std::to_string((int) retcode));
     }
 
     chemistry_step();
 }
 
 void EquilibriumCurveCoupler::chemistry_step()
 {
     for (index_t node=1; node<m_mesh->nb_nodes(); ++node)
     {
         index_t index = m_eqcurve.find_point(m_solid_concentrations(node));
         //std::cout << index << std::endl;
         scalar_t ceq = m_eqcurve.totaq_concentration(index);
         //std::cout << m_solid_concentrations(node) << " - diff : " << m_eqcurve.porosity(index)*(ceq-m_aqueous_concentrations(node)) << std::endl;
         m_solid_concentrations(node) -= std::min( m_solid_concentrations(node),
                                                   m_eqcurve.porosity(index)*(ceq-m_aqueous_concentrations(node)));
         m_aqueous_concentrations(node) = ceq;
 
 
         // ###FIXME -> locate node using previous guess
         index = m_eqcurve.find_point(m_solid_concentrations(node));
         m_param->porosity(node) = m_eqcurve.porosity(index);
         m_param->diffusion_coefficient(node)= m_eqcurve.diffusion_coefficient(index);
 
     }
 }
 
 
 } // end namespace eqcurve
 } // end namespace reactmicp
 } // end namespace specmicp
diff --git a/src/reactmicp/equilibrium_curve/eqcurve_coupler.hpp b/src/reactmicp/equilibrium_curve/eqcurve_coupler.hpp
index 576cf59..a1be80a 100644
--- a/src/reactmicp/equilibrium_curve/eqcurve_coupler.hpp
+++ b/src/reactmicp/equilibrium_curve/eqcurve_coupler.hpp
@@ -1,52 +1,81 @@
+/*-------------------------------------------------------
+
+Copyright (c) 2014,2015 Fabien Georget <fabieng@princeton.edu>, Princeton University
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+    * Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+    * Redistributions in binary form must reproduce the above copyright
+      notice, this list of conditions and the following disclaimer in the
+      documentation and/or other materials provided with the distribution.
+    * Neither the name of the Princeton University nor the
+      names of its contributors may be used to endorse or promote products
+      derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+---------------------------------------------------------*/
+
 #ifndef SPECMICP_REACTMICP_EQCURVECOUPLER_HPP
 #define SPECMICP_REACTMICP_EQCURVECOUPLER_HPP
 
 #include "eqcurve_extractor.hpp"
 #include "dfpm/meshes/mesh1dfwd.hpp"
 
 #include "dfpm/1dtransport/diffusion.hpp"
 #include "dfpmsolver/parabolic_driver.hpp"
 
 namespace specmicp {
 
 namespace dfpm {
 class SaturatedDiffusion1DParameters;
 } // end namespace dfpm
 
 namespace reactmicp {
 namespace eqcurve {
 
 class EquilibriumCurveCoupler
 {
 public:
     EquilibriumCurveCoupler(Matrix& eq_curve,
                             mesh::Mesh1DPtr the_mesh,
                             dfpmsolver::ParabolicDriverOptions options
                             );
 
     void run_step(scalar_t timestep);
 
     Vector& solid_concentrations() {return m_solid_concentrations;}
     Vector& aqueous_concentrations() {return m_aqueous_concentrations;}
 
     void chemistry_step();
 
 private:
     EquilibriumCurveExtractor m_eqcurve;
 
     mesh::Mesh1DPtr m_mesh;
 
     std::shared_ptr<dfpm::SaturatedDiffusion1DParameters> m_param;
 
     Vector m_aqueous_concentrations;
     Vector m_solid_concentrations;
 
     dfpm::SaturatedDiffusion1D m_transport_program;
     dfpmsolver::ParabolicDriver<dfpm::SaturatedDiffusion1D> m_transport_solver;
 };
 
 } // end namespace eqcurve
 } // end namespace reactmicp
 } // end namespace specmicp
 
 #endif // SPECMICP_REACTMICP_EQCURVECOUPLER_HPP
diff --git a/src/reactmicp/equilibrium_curve/eqcurve_extractor.cpp b/src/reactmicp/equilibrium_curve/eqcurve_extractor.cpp
index 32257a7..92d4a8d 100644
--- a/src/reactmicp/equilibrium_curve/eqcurve_extractor.cpp
+++ b/src/reactmicp/equilibrium_curve/eqcurve_extractor.cpp
@@ -1,66 +1,95 @@
+/*-------------------------------------------------------
+
+Copyright (c) 2014,2015 Fabien Georget <fabieng@princeton.edu>, Princeton University
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+    * Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+    * Redistributions in binary form must reproduce the above copyright
+      notice, this list of conditions and the following disclaimer in the
+      documentation and/or other materials provided with the distribution.
+    * Neither the name of the Princeton University nor the
+      names of its contributors may be used to endorse or promote products
+      derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+---------------------------------------------------------*/
+
 #include "eqcurve_extractor.hpp"
 
 #include <iostream>
 
 namespace specmicp {
 namespace reactmicp {
 namespace eqcurve {
 
 
 index_t  EquilibriumCurveExtractor::find_point(scalar_t x)
 {
     index_t index;
     const index_t size = m_eqcurve.rows();
     index_t lower_index = 0;
     index_t upper_index = size+1;
 
     while (upper_index - lower_index > 1)
     {
         index = (upper_index + lower_index) /2;
         if ((x >= xs_offset(index)) == is_increasing())
             lower_index = index;
         else
             upper_index = index;
     }
     if (x == xs_offset(1)) index = 0;
     else if (x == xs_offset(size)) index = size-1;
     else index = std::max((specmicp::index_t) 0, lower_index-1);
 
     return index;
 }
 
 
 scalar_t EquilibriumCurveExtractor::interpolate(index_t index, scalar_t x, index_t col)
 {
     // limit
     if (is_increasing())
     {
         if (x <= m_eqcurve(first(), 0))
             return m_eqcurve(first(), col);
         else if (x >= m_eqcurve(last(), 0))
             return m_eqcurve(last(), col);
     }
     else
     {
         if (x >= m_eqcurve(first(), 0))
             return m_eqcurve(first(), col);
         else if (x <= m_eqcurve(last(), 0))
             return m_eqcurve(last(), col);
     }
     scalar_t y;
 
     const scalar_t diff = slope(index, col);
     y = m_eqcurve(index, col) + diff*(m_eqcurve(index+1,0)-x);
 
     return y;
 }
 
 scalar_t EquilibriumCurveExtractor::slope(index_t index, index_t col)
 {
     if (index == last()) return (m_eqcurve(index-1,col)-m_eqcurve(index,col))/(m_eqcurve(index-1,0)-m_eqcurve(index,0));
     return (m_eqcurve(index+1,col)-m_eqcurve(index,col))/(m_eqcurve(index+1,0)-m_eqcurve(index,0));
 }
 
 } // end namespace eqcurve
 } // end namespace reactmicp
 } // end namespace specmicp
diff --git a/src/reactmicp/equilibrium_curve/eqcurve_extractor.hpp b/src/reactmicp/equilibrium_curve/eqcurve_extractor.hpp
index 47886c3..6134a69 100644
--- a/src/reactmicp/equilibrium_curve/eqcurve_extractor.hpp
+++ b/src/reactmicp/equilibrium_curve/eqcurve_extractor.hpp
@@ -1,67 +1,96 @@
+/*-------------------------------------------------------
+
+Copyright (c) 2014,2015 Fabien Georget <fabieng@princeton.edu>, Princeton University
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+    * Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+    * Redistributions in binary form must reproduce the above copyright
+      notice, this list of conditions and the following disclaimer in the
+      documentation and/or other materials provided with the distribution.
+    * Neither the name of the Princeton University nor the
+      names of its contributors may be used to endorse or promote products
+      derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+---------------------------------------------------------*/
+
 #ifndef SPECMICP_REACTMICP_EQCURVEEXTRACTOR_HPP
 #define SPECMICP_REACTMICP_EQCURVEEXTRACTOR_HPP
 
 #include "common.hpp"
 
 namespace specmicp {
 namespace reactmicp {
 namespace eqcurve {
 
 
 class EquilibriumCurveExtractor
 {
 public:
     EquilibriumCurveExtractor(const Matrix& eq_curve):
         m_eqcurve(eq_curve)
     {
         m_is_increasing = (xs_offset(m_eqcurve.rows()) >= xs_offset(1));
     }
 
     EquilibriumCurveExtractor(Matrix&& eq_curve):
         m_eqcurve(eq_curve)
     {
         m_is_increasing = (xs_offset(m_eqcurve.rows()) >= xs_offset(1));
     }
 
     index_t find_point(scalar_t x);
 
     index_t first() {return 0;}
     index_t last() {return m_eqcurve.rows()-1;}
 
     bool is_increasing() {return m_is_increasing;}
 
     scalar_t totsolid_concentration(index_t index) {
         return m_eqcurve(index, 0);
     }
 
     scalar_t totaq_concentration(index_t index) {
         return m_eqcurve(index, 1);
     }
 
     scalar_t porosity(index_t index) {
         return m_eqcurve(index, 2);
     }
 
     scalar_t diffusion_coefficient(index_t index) {
         return m_eqcurve(index, 3);
     }
 
     scalar_t interpolate(index_t index, scalar_t x, index_t col);
 
     scalar_t slope(index_t index, index_t col);
 
 private:
     scalar_t xs_offset(index_t offset_index) {
         return m_eqcurve(offset_index-1, 0);
     }
 
     Matrix m_eqcurve;
 
     bool m_is_increasing;
 };
 
 } // end namespace eqcurve
 } // end namespace reactmicp
 } // end namespace specmicp
 
 #endif // SPECMICP_REACTMICP_EQCURVEEXTRACTOR_HPP
diff --git a/src/reactmicp/equilibrium_curve/eqcurve_solid_transport.cpp b/src/reactmicp/equilibrium_curve/eqcurve_solid_transport.cpp
index 58a4169..aa97bf4 100644
--- a/src/reactmicp/equilibrium_curve/eqcurve_solid_transport.cpp
+++ b/src/reactmicp/equilibrium_curve/eqcurve_solid_transport.cpp
@@ -1,233 +1,262 @@
+/*-------------------------------------------------------
+
+Copyright (c) 2014,2015 Fabien Georget <fabieng@princeton.edu>, Princeton University
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+    * Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+    * Redistributions in binary form must reproduce the above copyright
+      notice, this list of conditions and the following disclaimer in the
+      documentation and/or other materials provided with the distribution.
+    * Neither the name of the Princeton University nor the
+      names of its contributors may be used to endorse or promote products
+      derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+---------------------------------------------------------*/
+
 #include "eqcurve_solid_transport.hpp"
 #include "dfpm/meshes/mesh1d.hpp"
 
 #include <iostream>
 
 namespace specmicp {
 namespace reactmicp {
 namespace eqcurve {
 
 // SolidDiffusion::
 
 SolidDiffusion::SolidDiffusion(
         mesh::Mesh1DPtr the_mesh,
         const Matrix& eq_curve,
         std::vector<index_t> list_bcs
         ):
     m_tot_ndf(the_mesh->nb_nodes()),
     m_mesh(the_mesh),
     m_eqcurve(eq_curve),
     m_internal_flow(Vector::Zero(m_tot_ndf)),
     m_external_flow(Vector::Zero(m_tot_ndf)),
     m_in_jac(false)
 {
     number_equations(list_bcs);
 }
 
 void SolidDiffusion::number_equations(std::vector<index_t> list_bcs)
 {
     m_id_equations = Eigen::VectorXi::Zero(m_tot_ndf);
     for (auto it=list_bcs.begin(); it!=list_bcs.end(); ++it)
     {
         m_id_equations(*it) = no_equation;
     }
     index_t neq = 0;
     for (index_t node: m_mesh->range_nodes())
     {
         if (m_id_equations(node) == no_equation) continue;
         m_id_equations(node) = neq;
         ++ neq;
     }
     m_neq = neq;
 }
 
 void SolidDiffusion::compute_residuals(
         const Vector& displacement,
         const Vector& velocity,
         Vector& residual
         )
 {
     m_internal_flow.setZero();
     residual.resize(get_neq());
     residual.setZero();
     for (index_t element: m_mesh->range_elements())
     {
         Vector elem_residuals(2);
         elem_residuals.setZero();
         element_residuals(element, displacement, velocity, elem_residuals);
         for (index_t enode: m_mesh->range_nen())
         {
             const index_t id_eq = id_equation(m_mesh->get_node(element, enode));
             if (id_eq == no_equation) continue;
             residual(id_eq) += elem_residuals(enode);
         }
     }
     //std::cout << "residual : " << std::endl << residual << std::endl;
     //std::cout << "flow : " << std::endl << m_internal_flow << std::endl;
 }
 
 void SolidDiffusion::element_residuals(
         index_t element,
         const Vector& displacement,
         const Vector& velocity,
         Vector& elem_residuals
         )
 {
     Eigen::Matrix<scalar_t, 2, 2> jacob;
     Eigen::Matrix<scalar_t, 2, 1> evelocity, econc;
     //scalar_t mass_coeff = -(m_mesh->get_volume_element(element)/2.0);
 
     const index_t node_0 = m_mesh->get_node(element, 0);
     const index_t node_1 = m_mesh->get_node(element, 1);
 
     const scalar_t mass_coeff_0 = m_mesh->get_volume_cell_element(element, 0);
     const scalar_t mass_coeff_1 = m_mesh->get_volume_cell_element(element, 1);
 
     const scalar_t sc_0 = displacement(node_0);
     const scalar_t sc_1 = displacement(node_1);
 
     const index_t index_0 = m_eqcurve.find_point(sc_0);
     const index_t index_1 = m_eqcurve.find_point(sc_1);
 
     //std::cout << element << " # " << index_0 << " - " << index_1 << std::endl;
     const scalar_t cc_0 = m_eqcurve.interpolate(index_0, sc_0, 1);
             //std::max(m_eqcurve.totaq_concentration(m_eqcurve.last()), m_eqcurve.interpolate(index_0, sc_0, 1));
     const scalar_t cc_1 = m_eqcurve.interpolate(index_1, sc_1, 1);
             //std::max(m_eqcurve.totaq_concentration(m_eqcurve.last()), m_eqcurve.interpolate(index_1, sc_1, 1));
 
     const scalar_t porosity_0 = m_eqcurve.interpolate(index_0, sc_0, 2);
     const scalar_t porosity_1 = m_eqcurve.interpolate(index_1, sc_1, 2);
 
     //const scalar_t diffcoeff_0 = m_eqcurve.interpolate(index_0, sc_0, 3);
     //const scalar_t diffcoeff_1 = m_eqcurve.interpolate(index_1, sc_1, 3);
 
     const scalar_t porosity = (  porosity_0
                                + porosity_1
                               )/2.0;
     const scalar_t diff_coeff =  porosity>0.92?2.219e-5:1e4*std::exp(9.95*porosity-29.08);
 //    const scalar_t diff_coeff = 1.0/(0.5/diffcoeff_0 +
 //                                     0.5/diffcoeff_1);
 
     scalar_t flux_coeff = ( m_mesh->get_face_area(element) / m_mesh->get_dx(element)
                              //* porosity
                              * diff_coeff
                              );
 //    if (m_eqcurve.slope(index_1, 1) != 0)
 //    {
 //        std::cout << element << " # " <<  m_eqcurve.slope(index_0, 1) << " - " <<  m_eqcurve.slope(index_0, 2)
  //             <<  " # " <<  m_eqcurve.slope(index_1, 1) << " - " <<  m_eqcurve.slope(index_1, 2) << std::endl;
 //    }
     evelocity << (+ m_eqcurve.slope(index_0, 1)*porosity_0
                       + m_eqcurve.slope(index_0, 2)*cc_0
                       + 1.0)*mass_coeff_0*velocity(node_0),
                      (+ m_eqcurve.slope(index_1, 1)*porosity_1
                       + m_eqcurve.slope(index_1, 2)*cc_1
                       + 1.0)*mass_coeff_1*velocity(node_1);
 
 
     jacob << 1.0, -1.0, -1.0, 1.0;
     jacob *= flux_coeff;
     econc << cc_0,
              cc_1;
 //    if (element == 0)
 //        std::cout << econc << std::endl;
     elem_residuals += jacob*econc;
 
     m_internal_flow(node_0) += elem_residuals(0);
     m_internal_flow(node_1) += elem_residuals(1);
 
     elem_residuals += evelocity;
 
 //    for (index_t en: m_mesh->range_nen())
 //    {
 //        elem_residuals(en) += evelocity(en);
 //        elem_residuals(en) += (m_mesh->get_volume_element(element)/2.0
 //                                 *external_flow(m_mesh->get_node(element, en)));
 //    }
 }
 
 void SolidDiffusion::compute_jacobian(
         Vector& displacement,
         Vector& velocity,
         Eigen::SparseMatrix<scalar_t>& jacobian,
         scalar_t alphadt
         )
 {
     m_in_jac = true;
     dfpm::list_triplet_t jacob;
     const index_t estimation = m_mesh->nb_nodes()*(m_mesh->nen);
     jacob.reserve(estimation);
     for (index_t element: m_mesh->range_elements())
     {
         element_jacobian(element, displacement, velocity, jacob, alphadt);
     }
     jacobian = Eigen::SparseMatrix<scalar_t>(get_neq(), get_neq());
     jacobian.setFromTriplets(jacob.begin(), jacob.end());
     m_in_jac = false;
 }
 
 void SolidDiffusion::element_jacobian(
         index_t element,
         Vector& displacement,
         Vector& velocity,
         dfpm::list_triplet_t& jacobian,
         scalar_t alphadt)
 {
     Eigen::VectorXd element_residual_orig(Eigen::VectorXd::Zero(2));
     element_residuals(element, displacement, velocity, element_residual_orig);
 
     for (index_t en: m_mesh->range_nen())
     {
         Eigen::VectorXd element_residual(Eigen::VectorXd::Zero(2));
 
         const index_t node = m_mesh->get_node(element, en);
         const index_t dof = node;
         const index_t idc = id_equation(dof);
 
         if (idc == no_equation) continue;
 
         const scalar_t tmp_v = velocity(dof);
         const scalar_t tmp_d = displacement(dof);
 
         scalar_t h = eps_jacobian*std::abs(tmp_v);
         if (h < 1e-6) h = eps_jacobian;
         velocity(dof) = tmp_v + h;
         h = velocity(dof) - tmp_v;
 
         displacement(dof) = tmp_d + alphadt*h;
 
         element_residuals(element, displacement, velocity, element_residual);
         velocity(dof) = tmp_v;
         displacement(dof) = tmp_d;
 
         for (index_t enr: m_mesh->range_nen())
         {
             const index_t noder = m_mesh->get_node(element, enr);
             const index_t idr = id_equation(noder);
 
             if (idr == no_equation) continue;
             jacobian.push_back(dfpm::triplet_t(idr, idc, (element_residual(enr) - element_residual_orig(enr))/h));
         }
     }
 }
 
 void SolidDiffusion::update_solution(const Vector &update,
         scalar_t lambda,
         scalar_t alpha_dt,
         Vector &predictor,
         Vector &displacement,
         Vector &velocity
         )
 {
     for (index_t node: m_mesh->range_nodes())
     {
         const index_t id = id_equation(node);
         if (id == no_equation) continue;
         velocity(node) += lambda*update(id);
     }
     displacement = predictor + alpha_dt*velocity;
 }
 
 } // end namespace eqcurve
 } // end namespace reactmicp
 } // end namespace specmicp
diff --git a/src/reactmicp/equilibrium_curve/eqcurve_solid_transport.hpp b/src/reactmicp/equilibrium_curve/eqcurve_solid_transport.hpp
index b920453..23234fa 100644
--- a/src/reactmicp/equilibrium_curve/eqcurve_solid_transport.hpp
+++ b/src/reactmicp/equilibrium_curve/eqcurve_solid_transport.hpp
@@ -1,111 +1,140 @@
+/*-------------------------------------------------------
+
+Copyright (c) 2014,2015 Fabien Georget <fabieng@princeton.edu>, Princeton University
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+    * Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+    * Redistributions in binary form must reproduce the above copyright
+      notice, this list of conditions and the following disclaimer in the
+      documentation and/or other materials provided with the distribution.
+    * Neither the name of the Princeton University nor the
+      names of its contributors may be used to endorse or promote products
+      derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+---------------------------------------------------------*/
+
 #ifndef SPECMICP_REACTMICP_EQCURVE_SOLIDTRANSPORT_HPP
 #define SPECMICP_REACTMICP_EQCURVE_SOLIDTRANSPORT_HPP
 
 #include <memory>
 
 #include "common.hpp"
 
 #include "dfpm/types.hpp"
 #include "dfpmsolver/parabolic_program.hpp"
 #include "dfpm/meshes/mesh1dfwd.hpp"
 
 #include "eqcurve_extractor.hpp"
 
 namespace specmicp {
 namespace reactmicp {
 namespace eqcurve {
 
 class SolidDiffusion: public dfpmsolver::ParabolicProgram<SolidDiffusion>
 {
 public:
     SolidDiffusion(
             mesh::Mesh1DPtr the_mesh,
             const Matrix& eqcurve,
             std::vector<index_t> list_bcs
             );
 
     //! \brief Return the number of equations
     index_t get_neq() const {return m_neq;}
 
     //! \brief Return the number of degrees of freedom per node
     index_t get_ndf() const {return 1;}
 
     //! \brief Return the total number of degrees of freedom
     index_t get_tot_ndf() const {return m_tot_ndf;}
 
     //! \brief Return the id of the equation corresponding to the degree of freedom 'id_dof'
     //!
     //! Return 'no_equation' if no equation exist
     index_t id_equation(index_t id_dof) const {return m_id_equations(id_dof);}
 
     void element_residuals(index_t element,
                            const Vector& displacement,
                            const Vector& velocity,
                            Vector& element_residual
                            );
 
     //! \brief Compute the residuals
     void compute_residuals(const Vector& displacement,
                            const Vector& velocity,
                            Vector& residual
                            );
 
     //! \brief Compute the jacobian
     void compute_jacobian(Vector& displacement,
                           Vector& velocity,
                           Eigen::SparseMatrix<scalar_t>& jacobian,
                           scalar_t alphadt
                           );
     void element_jacobian(
             index_t element,
             Vector& displacement,
             Vector& velocity,
             dfpm::list_triplet_t& jacobian,
             scalar_t alphadt);
 
     //! \brief Update the solutions
     void update_solution(const Vector& update,
                          scalar_t lambda,
                          scalar_t alpha_dt,
                          Vector& predictor,
                          Vector& displacement,
                          Vector& velocity);
 
     //! \brief Apply boundary conditions to the velocity vector
     //!
     //! by default do nothing.
     void apply_bc(scalar_t dt,
                   const Vector& displacement,
                   Vector& velocity)
     {}
 
     //! \brief Return the value of the external flow for dof 'id_dof'
     scalar_t external_flow(index_t id_dof) const {return m_external_flow(id_dof);}
     //! \brief Return a reference to the value of the external flow for dof 'id_dof'
     scalar_t& external_flow(index_t id_dof) {return m_external_flow(id_dof);}
     //! \brief Return a reference to the vector of external flow
     Vector& external_flow() {return m_external_flow;}
 
 private:
     void number_equations(std::vector<index_t> list_bcs);
 
     index_t m_tot_ndf;
     index_t m_neq;
     Eigen::VectorXi m_id_equations;
 
     mesh::Mesh1DPtr m_mesh;
 
     EquilibriumCurveExtractor m_eqcurve;
 
     Vector m_internal_flow;
     Vector m_external_flow;
 
     bool m_in_jac;
 };
 
 
 } // end namespace eqcurve
 } // end namespace reactmicp
 } // end namespace specmicp
 
 #endif // SPECMICP_REACTMICP_EQCURVE_SOLIDTRANSPORT_HPP
diff --git a/src/reactmicp/solver/reactive_transport_solver.cpp b/src/reactmicp/solver/reactive_transport_solver.cpp
index d8aa966..4a7258f 100644
--- a/src/reactmicp/solver/reactive_transport_solver.cpp
+++ b/src/reactmicp/solver/reactive_transport_solver.cpp
@@ -1,221 +1,250 @@
+/*-------------------------------------------------------
+
+Copyright (c) 2014,2015 Fabien Georget <fabieng@princeton.edu>, Princeton University
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+    * Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+    * Redistributions in binary form must reproduce the above copyright
+      notice, this list of conditions and the following disclaimer in the
+      documentation and/or other materials provided with the distribution.
+    * Neither the name of the Princeton University nor the
+      names of its contributors may be used to endorse or promote products
+      derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+---------------------------------------------------------*/
+
 #include "reactive_transport_solver.hpp"
 
 #include "staggers_base/staggers_base.hpp"
 
 #include "utils/log.hpp"
 
 #include "utils/timer.hpp"
 
 namespace specmicp {
 namespace reactmicp {
 namespace solver {
 
 namespace internal {
 
 // This contains internal information for the reactive transport solver
 // It is used to check the convergence
 struct ReactiveTransportResiduals
 {
     index_t nb_iterations;
     scalar_t transport_residual_0;
     scalar_t transport_residuals;
     scalar_t update;
 
     ReactiveTransportResiduals():
         nb_iterations(0),
         transport_residual_0(-1),
         transport_residuals(-1),
         update(-1)
     {}
 };
 
 } // end namespace internal
 
 // ReactiveTransportSolver::
 
 // Solve a timestep
 //
 // Attention : This function uses goto to handle return code and performance
 ReactiveTransportReturnCode ReactiveTransportSolver::solve_timestep(
         scalar_t timestep,
         VariablesBasePtr variables
         )
 {
     // start the timer
     Timer tot_timer;
     tot_timer.start();
     // initialization
     internal::ReactiveTransportResiduals residuals;
     reset_perfs();
     get_perfs().timestep = timestep;
 
     // copy of variables // ?
     m_transport_stagger->initialize_timestep(timestep, variables);
     m_chemistry_stagger->initialize_timestep(timestep, variables);
     m_upscaling_stagger->initialize_timestep(timestep, variables);
 
     //
     residuals.transport_residual_0 = m_transport_stagger->get_residual_0(variables);
 
     ReactiveTransportReturnCode retcode = one_iteration(variables, residuals);
     // check for failure
     if (retcode < ReactiveTransportReturnCode::StaggerFailure)
     {
         ERROR << "Failed to solve the iteration, return code : " << (int) retcode;
         goto set_return;
     }
 
     retcode = check_convergence(variables, residuals, false);
 
     ++residuals.nb_iterations;
     // if sequential non-iterative algorithm
     if (get_options().is_snia())
     {
         goto end;
     }
     // else
     while (retcode == ReactiveTransportReturnCode::NotConvergedYet)
     {
         retcode = one_iteration(variables, residuals);
         // check for failure
         if (retcode < ReactiveTransportReturnCode::StaggerFailure)
         {
             ERROR << "Failed to solve the iteration, return code : " << (int) retcode;
             goto set_return;
         }
         if (retcode != ReactiveTransportReturnCode::TransportBypass)
             retcode = check_convergence(variables, residuals, true);
         retcode = check_convergence(variables, residuals, false);
         ++residuals.nb_iterations;
 
     }
     // wrapup
     end:
 
     // upscaling, if needed
     if (not get_options().implicit_upscaling)
     {
         Timer timer;
 
         timer.start();
         m_upscaling_stagger->restart_timestep(variables);
         timer.stop();
         m_timer.upscaling_time += timer.elapsed_time();
     }
     // record performance and return code
     set_return:
 
     tot_timer.stop();
 
     get_perfs().total_time = tot_timer.elapsed_time();
     get_perfs().nb_iterations = residuals.nb_iterations;
     get_perfs().return_code = retcode;
     get_perfs().residuals = residuals.transport_residuals/residuals.transport_residual_0;
 
     return retcode;
 }
 
 ReactiveTransportReturnCode ReactiveTransportSolver::one_iteration(
         VariablesBasePtr variables,
         internal::ReactiveTransportResiduals& residuals
         )
 {
     Timer timer;
     bool bypass = false;
 
     // Transport
     // ---------
     timer.start();
     StaggerReturnCode transport_ret_code = m_transport_stagger->restart_timestep(variables);
     if (transport_ret_code <= StaggerReturnCode::NotConvergedYet)
     {
         return ReactiveTransportReturnCode::TransportFailure;
     }
     if (transport_ret_code == StaggerReturnCode::ErrorMinimized)
     {
         bypass = true;
     }
     timer.stop();
     const scalar_t ttime = timer.elapsed_time();
     m_timer.transport_time += ttime;
     get_perfs().transport_time += ttime;
 
     // Chemistry
     // ---------
 
     timer.start();
     StaggerReturnCode chemistry_ret_code = m_chemistry_stagger->restart_timestep(variables);
     if (chemistry_ret_code <= StaggerReturnCode::NotConvergedYet)
     {
         return ReactiveTransportReturnCode::ChemistryFailure;
     }
     timer.stop();
     const scalar_t ctime = timer.elapsed_time();
     m_timer.chemistry_time += ctime;
     get_perfs().chemistry_time += ctime;
 
     // Upscaling0
     // ---------
     if (get_options().implicit_upscaling)
     {
         timer.start();
         StaggerReturnCode upscaling_ret_code = m_upscaling_stagger->restart_timestep(variables);
         if (upscaling_ret_code <= StaggerReturnCode::NotConvergedYet)
         {
             return ReactiveTransportReturnCode::UpscalingFailure;
         }
         timer.stop();
         m_timer.upscaling_time += timer.elapsed_time();
     }
     // Final residuals
     // ---------------
     residuals.transport_residuals = m_transport_stagger->get_residual(variables);
     residuals.update = m_transport_stagger->get_update(variables);
     if (bypass)
         return ReactiveTransportReturnCode::TransportBypass;
     return ReactiveTransportReturnCode::NotConvergedYet;
 }
 
 // Check the convergence
 ReactiveTransportReturnCode ReactiveTransportSolver::check_convergence(
         VariablesBasePtr _,
         const internal::ReactiveTransportResiduals& residuals,
         bool bypass
         )
 {
     const scalar_t relative_residual = residuals.transport_residuals/residuals.transport_residual_0;
     // Residual
     if (relative_residual < get_options().residuals_tolerance
             or residuals.transport_residuals < get_options().absolute_residuals_tolerance)
     {
         return ReactiveTransportReturnCode::ResidualMinimized;
     }
     // Step
     else if (residuals.update < get_options().step_tolerance)
     {
         if (relative_residual < get_options().good_enough_tolerance)
         {
             return ReactiveTransportReturnCode::ErrorMinimized;
         }
         else
             return ReactiveTransportReturnCode::StationaryPoint;
     }
     else if (bypass)
     {
         return ReactiveTransportReturnCode::TransportBypass;
     }
     // Number of iterations
     else if (residuals.nb_iterations >= get_options().maximum_iterations)
     {
         if (relative_residual < get_options().good_enough_tolerance)
         {
             return ReactiveTransportReturnCode::GoodEnough;
         }
         return ReactiveTransportReturnCode::MaximumIterationsReached;
     }
     return ReactiveTransportReturnCode::NotConvergedYet;
 }
 
 } // end namespace solver
 } // end namespace reactmicp
 } // end namespace specmicp
diff --git a/src/reactmicp/solver/reactive_transport_solver.hpp b/src/reactmicp/solver/reactive_transport_solver.hpp
index 7af18ab..24136aa 100644
--- a/src/reactmicp/solver/reactive_transport_solver.hpp
+++ b/src/reactmicp/solver/reactive_transport_solver.hpp
@@ -1,126 +1,155 @@
+/*-------------------------------------------------------
+
+Copyright (c) 2014,2015 Fabien Georget <fabieng@princeton.edu>, Princeton University
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+    * Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+    * Redistributions in binary form must reproduce the above copyright
+      notice, this list of conditions and the following disclaimer in the
+      documentation and/or other materials provided with the distribution.
+    * Neither the name of the Princeton University nor the
+      names of its contributors may be used to endorse or promote products
+      derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+---------------------------------------------------------*/
+
 #ifndef SPECMICP_REACTMICP_SOLVER_REACTIVETRANSPORTSOLVER_HPP
 #define SPECMICP_REACTMICP_SOLVER_REACTIVETRANSPORTSOLVER_HPP
 
 //! \file reactive_transport_solver.hpp The reactive transport solver
 
 //! \namespace specmicp::reactmicp::solver Namespace containing the algorithms for the reactive transport solver
 
 #include "common.hpp"
 #include <memory>
 #include "reactive_transport_solver_structs.hpp"
 
 #include "utils/options_handler.hpp"
 #include "utils/perfs_handler.hpp"
 
 // forward declarations
 // ====================
 namespace specmicp {
 namespace reactmicp {
 namespace solver {
 
 class VariablesBase;
 using VariablesBasePtr = std::shared_ptr<VariablesBase>;
 
 class TransportStaggerBase;
 class ChemistryStaggerBase;
 class UpscalingStaggerBase;
 using TransportStaggerPtr = std::shared_ptr<TransportStaggerBase>;
 using ChemistryStaggerPtr = std::shared_ptr<ChemistryStaggerBase>;
 using UpscalingStaggerPtr = std::shared_ptr<UpscalingStaggerBase>;
 
 namespace internal {
 struct ReactiveTransportResiduals;
 } // end namespace internal
 
 } // end namespace solver
 } // end namespace reactmicp
 } // end namespace specmicp
 
 
 // Reactive Transport Solver
 // =========================
 
 namespace specmicp {
 namespace reactmicp {
 namespace solver {
 
 //! \brief The reactive transport solver
 //!
 //! This class solves a reactive transport problem.
 //! The details of the problem are implemented in the staggers.
 //!
 //! There is three staggers :
 //!     - The transport stagger
 //!     - The chemistry stagger
 //!     - The upscaling stagger
 //!
 //! The transport stagger also implements the residuals used to checked the convergence.
 //!
 //! This algorithm do not update, modify the variables.
 //! The details must be implemented in the staggers.
 //! The variables shared by the algorithm is a shared_ptr to the abstract base class specmicp::reactmicp::solver::VariablesBase
 //! To be useful, this variable must be casted to the true class in the staggers.
 class ReactiveTransportSolver:
         public OptionsHandler<ReactiveTransportOptions>,
         public PerformanceHandler<ReactiveTransportPerformance>
 {
 public:
     //! \brief Build a reactive transport
     //!
     //! \param transport_stagger shared_ptr to a transport stagger
     //! \param chemistry_stagger shared_ptr to a chemistry stagger
     //! \param upscaling_stagger shared_ptr to an upscaling stagger
     ReactiveTransportSolver(
             TransportStaggerPtr transport_stagger,
             ChemistryStaggerPtr chemistry_stagger,
             UpscalingStaggerPtr upscaling_stagger
             ):
         m_transport_stagger(transport_stagger),
         m_chemistry_stagger(chemistry_stagger),
         m_upscaling_stagger(upscaling_stagger)
     {}
 
     //! \brief Solve a timestep
     //!
     //! \param timestep The duration of the timestep
     //! \param variables shared_ptr to the variables
     ReactiveTransportReturnCode solve_timestep(
             scalar_t timestep,
             VariablesBasePtr variables
             );
 
     //! \brief Return the timer
     ReactiveTransportTimer& get_timer() {return m_timer;}
 
 private: // members
     //! \brief One iteration inside the timestep
     //!
     //! \param variables shared_ptr to the variables
     //! \param residuals struct containing the residuals information
     ReactiveTransportReturnCode one_iteration(
             VariablesBasePtr variables,
             internal::ReactiveTransportResiduals& residuals
             );
     //! \brief Check the convergence
     //!
     //! \param variables shared_ptr to the variables
     //! \param residuals struct containing the residuals information
     ReactiveTransportReturnCode check_convergence(
             VariablesBasePtr variables,
             const internal::ReactiveTransportResiduals& residuals,
             bool bypass
             );
 
 private: // attributes
     TransportStaggerPtr m_transport_stagger; //!< The transport stagger
     ChemistryStaggerPtr m_chemistry_stagger; //!< The chemistry stagger
     UpscalingStaggerPtr m_upscaling_stagger; //!< The upscaling stagger
 
     ReactiveTransportTimer m_timer;
 };
 
 } // end namespace solver
 } // end namespace reactmicp
 } // end namespace specmicp
 
 #endif // SPECMICP_REACTMICP_SOLVER_REACTIVETRANSPORTSOLVER_HPP
diff --git a/src/reactmicp/solver/reactive_transport_solver_structs.hpp b/src/reactmicp/solver/reactive_transport_solver_structs.hpp
index 3a45fef..0c36772 100644
--- a/src/reactmicp/solver/reactive_transport_solver_structs.hpp
+++ b/src/reactmicp/solver/reactive_transport_solver_structs.hpp
@@ -1,90 +1,119 @@
+/*-------------------------------------------------------
+
+Copyright (c) 2014,2015 Fabien Georget <fabieng@princeton.edu>, Princeton University
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+    * Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+    * Redistributions in binary form must reproduce the above copyright
+      notice, this list of conditions and the following disclaimer in the
+      documentation and/or other materials provided with the distribution.
+    * Neither the name of the Princeton University nor the
+      names of its contributors may be used to endorse or promote products
+      derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+---------------------------------------------------------*/
+
 #ifndef SPECMICP_REACTMICP_SOLVER_REACTIVETRANSPORTSOLVERSTRUCTS_HPP
 #define SPECMICP_REACTMICP_SOLVER_REACTIVETRANSPORTSOLVERSTRUCTS_HPP
 
 #include "common.hpp"
 
 //! \file reactive_transport_solver_structs.hpp Structs used by the reactive transport solver
 
 namespace specmicp {
 namespace reactmicp {
 namespace solver {
 
 
 //! \brief Return codes used by the reactive transport solver
 enum class ReactiveTransportReturnCode
 {
     UpscalingFailure         = -13, //!< Upscaling stagger has failed
     ChemistryFailure         = -12, //!< Chemistry stagger has failed
     TransportFailure         = -11, //!< Transport stagger has failed
     StaggerFailure           = -10, //!< A stagger has failed
     MaximumIterationsReached = - 2, //!< Maximum number of fixed-point iterations is reached
     StationaryPoint          = - 1, //!< The solver has reached a stationnary points
     NotConvergedYet          =   0, //!< The solver has not converged yet
     ResidualMinimized        =   1, //!< The residuals are minimized
     ErrorMinimized           =   2, //!< The error is minimized (may indicate a stationnary point)
     GoodEnough               =   3, //!< Good enough
     TransportBypass          =   5, //!< Transport is minimized, no need to do iterations
 };
 
 //! \brief Options used by the reactive transport solver
 struct ReactiveTransportOptions
 {
     scalar_t residuals_tolerance;          //!< Relative tolerance for the residuals
     scalar_t absolute_residuals_tolerance; //!< Absolute tolerance for the residuals
     scalar_t step_tolerance;               //!< Absolute tolerance for the step
     scalar_t good_enough_tolerance;        //!< Relative tolerance to detect a stationnary point
     index_t  maximum_iterations;           //!< Maximum number of iterations allowed
     bool     implicit_upscaling;           //!< When true, the upscaling problem is solved at each iteration
 
     //! \brief Use a Sequential Non-iterative Algorithm
     void set_snia() {maximum_iterations = 1;}
     //! \brief Return true if the problem is solved using a SNIA
     bool is_snia() {return maximum_iterations <= 1;}
 
     ReactiveTransportOptions():
         residuals_tolerance(1e-4),
         absolute_residuals_tolerance(1e-16),
         step_tolerance(1e-10),
         good_enough_tolerance(1e-2),
         maximum_iterations(100),
         implicit_upscaling(false)
     {}
 };
 
 //! \brief Struct containing performance information
 //!
 //! This is valid for one timestep.
 struct ReactiveTransportPerformance
 {
     scalar_t timestep;     //!< Timestep used
     index_t nb_iterations; //!< The number of fixed-point iterations for this timestep
     ReactiveTransportReturnCode return_code; //!< The return code of the timestep
     scalar_t residuals;      //!< The norm of the residuals at the end of the timestep
     scalar_t total_time;     //!< Time spent solving one timestep
     scalar_t transport_time; //!< Time spent solving the transport problem
     scalar_t chemistry_time; //!< Time spent solving the chemistry problem
 
     ReactiveTransportPerformance():
         nb_iterations(0),
         return_code(ReactiveTransportReturnCode::NotConvergedYet),
         residuals(HUGE_VAL),
         total_time(0.0),
         transport_time(0.0),
         chemistry_time(0.0)
     {}
 };
 
 //! \brief Struct containing the execution time of the staggers
 struct ReactiveTransportTimer
 {
     scalar_t transport_time;
     scalar_t chemistry_time;
     scalar_t upscaling_time;
 };
 
 
 } // end namespace solver
 } // end namespace reactmicp
 } // end namespace specmicp
 
 #endif // SPECMICP_REACTMICP_SOLVER_REACTIVETRANSPORTSOLVERSTRUCTS_HPP
diff --git a/src/reactmicp/solver/runner.cpp b/src/reactmicp/solver/runner.cpp
index 5d70bf5..d23f583 100644
--- a/src/reactmicp/solver/runner.cpp
+++ b/src/reactmicp/solver/runner.cpp
@@ -1,76 +1,105 @@
+/*-------------------------------------------------------
+
+Copyright (c) 2014,2015 Fabien Georget <fabieng@princeton.edu>, Princeton University
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+    * Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+    * Redistributions in binary form must reproduce the above copyright
+      notice, this list of conditions and the following disclaimer in the
+      documentation and/or other materials provided with the distribution.
+    * Neither the name of the Princeton University nor the
+      names of its contributors may be used to endorse or promote products
+      derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+---------------------------------------------------------*/
+
 #include "runner.hpp"
 
 #include "utils/io/reactive_transport.hpp"
 #include "utils/timer.hpp"
 #include <fstream>
 #include  "staggers_base/variables_base.hpp"
 
 namespace specmicp {
 namespace reactmicp {
 namespace solver {
 
 void ReactiveTransportRunner::run_until(scalar_t target, VariablesBasePtr variables)
 {
 
     Timer total_time;
     total_time.start();
 
     m_timestepper.set_total_target(target);
     m_output_target = m_timestepper.get_total()+m_simulinfo.output_step;
 
     std::ofstream out_iter;
 
     if (m_simulinfo.print_iter_info)
     {
         out_iter.open(m_simulinfo.complete_filepath("iter", "dat"));
         io::print_reactmicp_header(&out_iter);
     }
 
     scalar_t dt = m_timestepper.get_options().restart_timestep;
     ReactiveTransportReturnCode retcode = ReactiveTransportReturnCode::NotConvergedYet;
 
     while(retcode >= ReactiveTransportReturnCode::NotConvergedYet
           and m_timestepper.get_total() < m_timestepper.get_total_target())
     {
         Timer step_timer;
         step_timer.start();
         reactmicp::solver::ReactiveTransportReturnCode retcode = m_solver.solve_timestep(dt, variables);
         step_timer.stop();
 
         if (m_simulinfo.print_iter_info)
             io::print_reactmicp_performance_long(&out_iter, m_cnt, m_timestepper.get_total()+dt, m_solver.get_perfs());
 
         dt = m_timestepper.next_timestep(dt, retcode, m_solver.get_perfs().nb_iterations);
         if (retcode <= reactmicp::solver::ReactiveTransportReturnCode::NotConvergedYet)
         {
             dt = m_timestepper.get_options().restart_timestep;
             variables->reset_main_variables();
             retcode = m_solver.solve_timestep(dt, variables);
             if (m_simulinfo.print_iter_info)
                 io::print_reactmicp_performance_long(&out_iter, m_cnt, m_timestepper.get_total()+dt, m_solver.get_perfs());
             dt = m_timestepper.next_timestep(dt, retcode, m_solver.get_perfs().nb_iterations);
         }
         ++m_cnt;
 
         // output
         if (m_timestepper.get_total() > m_output_target)
         {
             m_output_function(m_timestepper.get_total(), variables);
             m_output_target += m_simulinfo.output_step;
         }
     }
 
     total_time.stop();
 
     if (m_simulinfo.print_iter_info)
     {
 
         io::print_reactmicp_end(&out_iter, total_time, get_timer());
         out_iter.close();
 
     }
 }
 
 } // end namespace solver
 } // end namespace reactmicp
 } // end namespace specmicp
diff --git a/src/reactmicp/solver/runner.hpp b/src/reactmicp/solver/runner.hpp
index 0137cae..d75802b 100644
--- a/src/reactmicp/solver/runner.hpp
+++ b/src/reactmicp/solver/runner.hpp
@@ -1,96 +1,125 @@
+/*-------------------------------------------------------
+
+Copyright (c) 2014,2015 Fabien Georget <fabieng@princeton.edu>, Princeton University
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+    * Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+    * Redistributions in binary form must reproduce the above copyright
+      notice, this list of conditions and the following disclaimer in the
+      documentation and/or other materials provided with the distribution.
+    * Neither the name of the Princeton University nor the
+      names of its contributors may be used to endorse or promote products
+      derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+---------------------------------------------------------*/
+
 #ifndef SPECMICP_REACTMICP_SOLVER_RUNNER_HPP
 #define SPECMICP_REACTMICP_SOLVER_RUNNER_HPP
 
 #include "reactive_transport_solver.hpp"
 #include "timestepper.hpp"
 #include <string>
 #include <functional>
 
 namespace specmicp {
 namespace reactmicp {
 namespace solver {
 
 
 //! \struct SimulationInformation
 //! \brief Information about the simulation
 struct SimulationInformation
 {
     std::string name;             //!< Name of the simulation
     std::string output_prefix;    //!< prefix for the output files
 
     bool print_iter_info{true}; //!< If true, print the iteration informations
     scalar_t output_step; //!< output step
 
     SimulationInformation(std::string name_simul, scalar_t outputstep):
         name(name_simul),
         output_prefix(name_simul+"_"),
         output_step(outputstep)
 
     {}
 
     std::string complete_filepath(std::string name, std::string suffix) const {
         return output_prefix+name+"."+suffix;
     }
 
 };
 
 
 using output_f = std::function<void (scalar_t time, VariablesBasePtr variables)>;
 
 inline void dummy_output(scalar_t _, VariablesBasePtr __) {}
 
 class ReactiveTransportRunner
 {
 public:
     ReactiveTransportRunner(ReactiveTransportSolver& solver,
                             scalar_t lower_dt_bound,
                             scalar_t upper_dt_bound,
                             const SimulationInformation info):
         m_solver(solver),
         m_timestepper(lower_dt_bound, upper_dt_bound, 0, 2.0),
         m_simulinfo(info)
     {
 
     }
 
 
     void run_until(scalar_t target, VariablesBasePtr variables);
 
     void set_output_policy(output_f output_policy) {
         m_output_function = output_policy;
     }
 
     ReactiveTransportOptions& get_options() {
         return m_solver.get_options();
     }
 
     TimestepperOptions& get_timestepper_options() {
         return m_timestepper.get_options();
     }
 
     ReactiveTransportPerformance& get_perfs() {
         return m_solver.get_perfs();
     }
 
     ReactiveTransportTimer& get_timer() {
         return m_solver.get_timer();
     }
 
 private:
     index_t m_cnt{0};
     ReactiveTransportSolver& m_solver;
     Timestepper m_timestepper;
     const SimulationInformation& m_simulinfo;
 
     output_f m_output_function{dummy_output};
 
     scalar_t m_output_target;
 
 
 };
 
 } // end namespace solver
 } // end namespace reactmicp
 } // end namespace specmicp
 
 #endif // SPECMICP_REACTMICP_SOLVER_RUNNER_HPP
diff --git a/src/reactmicp/solver/staggers_base/chemistry_stagger_base.hpp b/src/reactmicp/solver/staggers_base/chemistry_stagger_base.hpp
index 355f365..e16444e 100644
--- a/src/reactmicp/solver/staggers_base/chemistry_stagger_base.hpp
+++ b/src/reactmicp/solver/staggers_base/chemistry_stagger_base.hpp
@@ -1,46 +1,75 @@
+/*-------------------------------------------------------
+
+Copyright (c) 2014,2015 Fabien Georget <fabieng@princeton.edu>, Princeton University
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+    * Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+    * Redistributions in binary form must reproduce the above copyright
+      notice, this list of conditions and the following disclaimer in the
+      documentation and/or other materials provided with the distribution.
+    * Neither the name of the Princeton University nor the
+      names of its contributors may be used to endorse or promote products
+      derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+---------------------------------------------------------*/
+
 #ifndef SPECMICP_REACTMICP_SOLVER_CHEMISTRYSTAGGERBASE_HPP
 #define SPECMICP_REACTMICP_SOLVER_CHEMISTRYSTAGGERBASE_HPP
 
 //! \file chemistry_stagger_base.hpp The base class for a chemistry stagger
 
 // following file include main data types and forward declaration needed for a stagger
 #include "decl.inl"
 
 namespace specmicp {
 namespace reactmicp {
 namespace solver {
 
 
 //! \brief The base class for a transport stagger
 //!
 //! Implement the chemistry (equilibrium, kinetics, ...) in a derived class
 class ChemistryStaggerBase
 {
 public:
     virtual ~ChemistryStaggerBase() {}
 
     //! \brief Initialize the stagger at the beginning of the computation
     //!
     //! \param var a shared_ptr to the variables
     virtual void initialize(VariablesBasePtr var) {}
 
     //! \brief Initialize the stagger at the beginning of an iteration
     //!
     //! This is where the predictor can be saved, the first trivial iteration done, ...
     //!
     //! \param dt the duration of the timestep
     //! \param var a shared_ptr to the variables
     virtual void initialize_timestep(scalar_t dt, VariablesBasePtr var) = 0;
 
     //! \brief Solve the equation for the timestep
     //!
     //! \param var a shared_ptr to the variables
     virtual StaggerReturnCode restart_timestep(VariablesBasePtr var) = 0;
 };
 
 } // end namespace solver
 } // end namespace reactmicp
 } // end namespace specmicp
 
 
 #endif // SPECMICP_REACTMICP_SOLVER_CHEMISTRYSTAGGERBASE_HPP
diff --git a/src/reactmicp/solver/staggers_base/decl.inl b/src/reactmicp/solver/staggers_base/decl.inl
index 338db31..f893bb2 100644
--- a/src/reactmicp/solver/staggers_base/decl.inl
+++ b/src/reactmicp/solver/staggers_base/decl.inl
@@ -1,23 +1,52 @@
+/*-------------------------------------------------------
+
+Copyright (c) 2014,2015 Fabien Georget <fabieng@princeton.edu>, Princeton University
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+    * Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+    * Redistributions in binary form must reproduce the above copyright
+      notice, this list of conditions and the following disclaimer in the
+      documentation and/or other materials provided with the distribution.
+    * Neither the name of the Princeton University nor the
+      names of its contributors may be used to endorse or promote products
+      derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+---------------------------------------------------------*/
+
 #ifndef SPECMICP_REACTMICP_SOLVER_DECL_INL
 #define SPECMICP_REACTMICP_SOLVER_DECL_INL
 
 //! \file decl.inl common declaration needed for the *stagger_base headers
 
 #include "common.hpp"
 #include <memory>
 
 namespace specmicp {
 namespace reactmicp {
 namespace solver {
 
 // forward declaration
 class VariablesBase;
 using VariablesBasePtr = std::shared_ptr<VariablesBase>;
 
 enum class StaggerReturnCode;
 
 } // end namespace solver
 } // end namespace reactmicp
 } // end namespace specmicp
 
 #endif // SPECMICP_REACTMICP_SOLVER_DECL_INL
diff --git a/src/reactmicp/solver/staggers_base/stagger_structs.hpp b/src/reactmicp/solver/staggers_base/stagger_structs.hpp
index 6e4b9d3..a655096 100644
--- a/src/reactmicp/solver/staggers_base/stagger_structs.hpp
+++ b/src/reactmicp/solver/staggers_base/stagger_structs.hpp
@@ -1,29 +1,58 @@
+/*-------------------------------------------------------
+
+Copyright (c) 2014,2015 Fabien Georget <fabieng@princeton.edu>, Princeton University
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+    * Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+    * Redistributions in binary form must reproduce the above copyright
+      notice, this list of conditions and the following disclaimer in the
+      documentation and/or other materials provided with the distribution.
+    * Neither the name of the Princeton University nor the
+      names of its contributors may be used to endorse or promote products
+      derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+---------------------------------------------------------*/
+
 #ifndef SPECMICP_REACTMICP_SOLVER_STAGGERSTRUCTS_HPP
 #define SPECMICP_REACTMICP_SOLVER_STAGGERSTRUCTS_HPP
 
 //! \file stagger_structs.hpp common structs for the staggers
 
 namespace specmicp {
 namespace reactmicp {
 namespace solver {
 
 //! \brief Return code error used by a stagger
 //!
 //! Success of the stagger should be tested as :
 //!     return code > NotConvergedYet
 enum class StaggerReturnCode
 {
     LolThatsNotSupposedToHappen, //!< Mainly for debugging purposes
     UnknownError,                //!< Generic error, when used, an entry in the log is necessary
     MaximumIterationsReached,    //!< Maximum number of iterations reached in the code
     StationaryPoint,             //!< Stagger is stuck in a Stationary point
     NotConvergedYet,             //!< The stagger has not converged yet
     ResidualMinimized,           //!< The residuals are minimized
     ErrorMinimized               //!< The error is minimized
 };
 
 } // end namespace solver
 } // end namespace reactmicp
 } // end namespace specmicp
 
 #endif // SPECMICP_REACTMICP_SOLVER_STAGGERSTRUCTS_HPP
diff --git a/src/reactmicp/solver/staggers_base/staggers_base.hpp b/src/reactmicp/solver/staggers_base/staggers_base.hpp
index 4c81c25..6e26ff0 100644
--- a/src/reactmicp/solver/staggers_base/staggers_base.hpp
+++ b/src/reactmicp/solver/staggers_base/staggers_base.hpp
@@ -1,7 +1,36 @@
+/*-------------------------------------------------------
+
+Copyright (c) 2014,2015 Fabien Georget <fabieng@princeton.edu>, Princeton University
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+    * Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+    * Redistributions in binary form must reproduce the above copyright
+      notice, this list of conditions and the following disclaimer in the
+      documentation and/or other materials provided with the distribution.
+    * Neither the name of the Princeton University nor the
+      names of its contributors may be used to endorse or promote products
+      derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+---------------------------------------------------------*/
+
 //! \file staggers_base.hpp Include headers of the staggers base directory
 
 #include "variables_base.hpp"
 #include "transport_stagger_base.hpp"
 #include "chemistry_stagger_base.hpp"
 #include "upscaling_stagger_base.hpp"
 #include "stagger_structs.hpp"
diff --git a/src/reactmicp/solver/staggers_base/transport_stagger_base.hpp b/src/reactmicp/solver/staggers_base/transport_stagger_base.hpp
index 7bdcc43..0ed203d 100644
--- a/src/reactmicp/solver/staggers_base/transport_stagger_base.hpp
+++ b/src/reactmicp/solver/staggers_base/transport_stagger_base.hpp
@@ -1,59 +1,88 @@
+/*-------------------------------------------------------
+
+Copyright (c) 2014,2015 Fabien Georget <fabieng@princeton.edu>, Princeton University
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+    * Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+    * Redistributions in binary form must reproduce the above copyright
+      notice, this list of conditions and the following disclaimer in the
+      documentation and/or other materials provided with the distribution.
+    * Neither the name of the Princeton University nor the
+      names of its contributors may be used to endorse or promote products
+      derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+---------------------------------------------------------*/
+
 #ifndef SPECMICP_REACTMICP_SOLVER_TRANSPORTSTAGGERBASE_HPP
 #define SPECMICP_REACTMICP_SOLVER_TRANSPORTSTAGGERBASE_HPP
 
 //! \file transport_stagger_base.hpp The base class for the transport stagger
 
 // following file include main data types and forward declaration needed for a stagger
 #include "decl.inl"
 
 namespace specmicp {
 namespace reactmicp {
 namespace solver {
 
 //! \brief The base class for a transport stagger
 //!
 class TransportStaggerBase
 {
 public:
     virtual ~TransportStaggerBase() {}
 
     //! \brief Initialize the stagger at the beginning of the computation
     //!
     //! \param var shared_ptr to the variables
     virtual void initialize(VariablesBasePtr var) {}
 
     //! \brief Initialize the stagger at the beginning of an iteration
     //!
     //! This is where the first residual may be computed, the predictor saved, ...
     //! \param dt the duration of the timestep
     //! \param var shared_ptr to the variables
     virtual void initialize_timestep(scalar_t dt, VariablesBasePtr var) = 0;
 
     //! \brief Solve the equation for the timetep
     //!
     //! \param var shared_ptr to the variables
     virtual StaggerReturnCode restart_timestep(VariablesBasePtr var) = 0;
 
     //! \brief Compute the residuals norm
     //!
     //! \param var shared_ptr to the variables
     virtual scalar_t get_residual(VariablesBasePtr var) = 0;
     //! \brief Compute the residuals norm
     //!
     //! \param var shared_ptr to the variables
     virtual scalar_t get_residual_0(VariablesBasePtr var) = 0;
 
     //! \brief Obtain the norm of the step size
     //!
     //! This is used to check if the algorithm has reach a stationary points.
     //! It should look like : return main_variables.norm()
     //!
     //! \param var shared_ptr to the variables
     virtual scalar_t get_update(VariablesBasePtr var) = 0;
 };
 
 } // end namespace solver
 } // end namespace reactmicp
 } // end namespace specmicp
 
 #endif // SPECMICP_REACTMICP_SOLVER_TRANSPORTSTAGGERBASE_HPP
diff --git a/src/reactmicp/solver/staggers_base/upscaling_stagger_base.hpp b/src/reactmicp/solver/staggers_base/upscaling_stagger_base.hpp
index ef5702b..435d194 100644
--- a/src/reactmicp/solver/staggers_base/upscaling_stagger_base.hpp
+++ b/src/reactmicp/solver/staggers_base/upscaling_stagger_base.hpp
@@ -1,44 +1,73 @@
+/*-------------------------------------------------------
+
+Copyright (c) 2014,2015 Fabien Georget <fabieng@princeton.edu>, Princeton University
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+    * Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+    * Redistributions in binary form must reproduce the above copyright
+      notice, this list of conditions and the following disclaimer in the
+      documentation and/or other materials provided with the distribution.
+    * Neither the name of the Princeton University nor the
+      names of its contributors may be used to endorse or promote products
+      derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+---------------------------------------------------------*/
+
 #ifndef SPECMICP_REACTMICP_SOLVER_UPSCALINGSTAGGERBASE_HPP
 #define SPECMICP_REACTMICP_SOLVER_UPSCALINGSTAGGERBASE_HPP
 
 //! \file upscaling_stagger_base.hpp The base class for the upscaling stagger
 
 // following file include main data types and forward declaration needed for a stagger
 #include "decl.inl"
 
 namespace specmicp {
 namespace reactmicp {
 namespace solver {
 
 //! \brief The base class for an upscaling stagger
 //!
 class UpscalingStaggerBase
 {
 public:
 
     virtual ~UpscalingStaggerBase() {}
 
     //! \brief Initialize the stagger at the beginning of the computation
     //!
     //! \param var a shared_ptr to the variables
     virtual void initialize(VariablesBasePtr var) {}
 
     //! \brief Initialize the stagger at the beginning of an iteration
     //!
     //! This is where the predictor can be saved, the first trivial iteration done, ...
     //!
     //! \param dt the duration of the timestep
     //! \param var a shared_ptr to the variables
     virtual void initialize_timestep(scalar_t dt, VariablesBasePtr var) = 0;
 
     //! \brief Solve the equation for the timestep
     //!
     //! \param var a shared_ptr to the variables
     virtual StaggerReturnCode restart_timestep(VariablesBasePtr var) = 0;
 };
 
 } // end namespace solver
 } // end namespace reactmicp
 } // end namespace specmicp
 
 #endif // SPECMICP_REACTMICP_SOLVER_UPSCALINGSTAGGERBASE_HPP
diff --git a/src/reactmicp/solver/staggers_base/variables_base.hpp b/src/reactmicp/solver/staggers_base/variables_base.hpp
index 2e9dbd6..13eec40 100644
--- a/src/reactmicp/solver/staggers_base/variables_base.hpp
+++ b/src/reactmicp/solver/staggers_base/variables_base.hpp
@@ -1,26 +1,55 @@
+/*-------------------------------------------------------
+
+Copyright (c) 2014,2015 Fabien Georget <fabieng@princeton.edu>, Princeton University
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+    * Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+    * Redistributions in binary form must reproduce the above copyright
+      notice, this list of conditions and the following disclaimer in the
+      documentation and/or other materials provided with the distribution.
+    * Neither the name of the Princeton University nor the
+      names of its contributors may be used to endorse or promote products
+      derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+---------------------------------------------------------*/
+
 #ifndef SPECMICP_REACTMICP_SOLVER_VARIABLESBASE_HPP
 #define SPECMICP_REACTMICP_SOLVER_VARIABLESBASE_HPP
 
 //! \file variables_base.hpp Base class for a reactive transport variables
 
 namespace specmicp {
 namespace reactmicp {
 namespace solver {
 
 //! \brief Variables base class
 //!
 //! This is just for polymorphism, implementations is left to the user.
 class VariablesBase
 {
 public:
     virtual ~VariablesBase() {}
 
     //! \brief Reset the variables to restart a computation in case of failure
     virtual void reset_main_variables() = 0;
 };
 
 } // end namespace solver
 } // end namespace reactmicp
 } // end namespace specmicp
 
 #endif // SPECMICP_REACTMICP_SOLVER_VARIABLESBASE_HPP
diff --git a/src/reactmicp/solver/timestepper.cpp b/src/reactmicp/solver/timestepper.cpp
index 3912ce6..8151c51 100644
--- a/src/reactmicp/solver/timestepper.cpp
+++ b/src/reactmicp/solver/timestepper.cpp
@@ -1,65 +1,94 @@
+/*-------------------------------------------------------
+
+Copyright (c) 2014,2015 Fabien Georget <fabieng@princeton.edu>, Princeton University
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+    * Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+    * Redistributions in binary form must reproduce the above copyright
+      notice, this list of conditions and the following disclaimer in the
+      documentation and/or other materials provided with the distribution.
+    * Neither the name of the Princeton University nor the
+      names of its contributors may be used to endorse or promote products
+      derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+---------------------------------------------------------*/
+
 #include "timestepper.hpp"
 
 #include "reactive_transport_solver_structs.hpp"
 
 namespace specmicp {
 namespace reactmicp {
 namespace solver {
 
 scalar_t Timestepper::next_timestep(
         scalar_t dt_done,
         ReactiveTransportReturnCode return_code,
         index_t nb_iterations
         )
 {
     if (return_code <= ReactiveTransportReturnCode::NotConvergedYet)
     {
         return get_options().decrease_failure*dt_done;
     }
 
     // previous timestep is correct
     m_total += dt_done;
     m_average.add_point(nb_iterations);
 
     scalar_t proposed_dt = dt_done;
 
     // If the error is minimized we increase the timestep
     if (return_code == ReactiveTransportReturnCode::ErrorMinimized)
     {
         proposed_dt *= get_options().increase_error_minimization;
     }
     else
     // Increase or decrease the timestep to reach the number of iteration target range
     {
         if (m_average.current_value() <= get_options().iteration_lower_target)
         {
             proposed_dt *= get_options().increase_factor;
         }
         else if (m_average.current_value() > get_options().iteration_upper_target)
         {
             proposed_dt *= get_options().decrease_factor;
         }
     }
     // Check that the total target is not exceeded
     if (m_total + proposed_dt > m_total_target)
     {
         proposed_dt = m_total_target - m_total;
     }
 
     // Check that the timestep is inside the bounds
     if (proposed_dt < get_options().lower_bound)
     {
         proposed_dt = get_options().lower_bound;
     }
     else if (proposed_dt > get_options().upper_bound)
     {
         proposed_dt = get_options().upper_bound;
     }
 
     return proposed_dt;
 
 }
 
 } // end namespace solver
 } // end namespace reactmicp
 } // end namespace specmicp
diff --git a/src/reactmicp/solver/timestepper.hpp b/src/reactmicp/solver/timestepper.hpp
index 511196f..a3ab2bb 100644
--- a/src/reactmicp/solver/timestepper.hpp
+++ b/src/reactmicp/solver/timestepper.hpp
@@ -1,87 +1,116 @@
+/*-------------------------------------------------------
+
+Copyright (c) 2014,2015 Fabien Georget <fabieng@princeton.edu>, Princeton University
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+    * Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+    * Redistributions in binary form must reproduce the above copyright
+      notice, this list of conditions and the following disclaimer in the
+      documentation and/or other materials provided with the distribution.
+    * Neither the name of the Princeton University nor the
+      names of its contributors may be used to endorse or promote products
+      derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+---------------------------------------------------------*/
+
 #ifndef SPECMICP_REACTMICP_SOLVER_TIMESTEPPER_HPP
 #define SPECMICP_REACTMICP_SOLVER_TIMESTEPPER_HPP
 
 #include "utils/moving_average.hpp"
 #include "utils/options_handler.hpp"
 
 namespace specmicp {
 namespace reactmicp {
 namespace solver {
 
 // forward declaration
 enum class ReactiveTransportReturnCode;
 
 //! \brief Options for the timestepper
 struct TimestepperOptions
 {
     scalar_t lower_bound; //!< Lower bound for the timestep
     scalar_t upper_bound; //!< Upper bound for the timestep
     scalar_t restart_timestep; //!< Value used when restarting the problem
 
     scalar_t iteration_lower_target{1.01}; //!< Lower target for the number of iterations
     scalar_t iteration_upper_target{15.0}; //!< Upper target for the number of iterations
 
     scalar_t alpha_average{0.5}; //!< Parameter for the exponential moving average
 
     scalar_t decrease_failure{0.5}; //!< Reduction factor in case of failure
     scalar_t increase_error_minimization{1.3}; //!< Increase factor in case of error minimization
     scalar_t decrease_factor{0.75};  //!< Reduction factor to get the number of iterations inside the target
     scalar_t increase_factor{1.25};  //!< Increase factor to get the number of iterations inside the target
 
     TimestepperOptions(scalar_t dt_lower_bound, scalar_t dt_upper_bound):
         lower_bound(dt_lower_bound),
         upper_bound(dt_upper_bound),
         restart_timestep(dt_lower_bound)
     {}
 };
 
 //! \brief Adaptative timestepper for the reactive transport solver
 class Timestepper: public OptionsHandler<TimestepperOptions>
 {
 public:
     //! \brief Constructor
     //!
     //! \param dt_lower_bound lower_bound for the timestep
     //! \param dt_upper_bound upper_bound for the timestep
     //! \param total_target total target time
     //! \param init_iterations initial iterations
     Timestepper(scalar_t dt_lower_bound,
                 scalar_t dt_upper_bound,
                 scalar_t total_target,
                 scalar_t init_iterations
                 ):
         OptionsHandler(dt_lower_bound, dt_upper_bound),
         m_total(0),
         m_total_target(total_target),
         m_average(0.5, init_iterations)
     {
         m_average.set_alpha(get_options().alpha_average);
     }
 
     //! \brief Return the total time
     scalar_t get_total() const {return m_total;}
     //! \brief Return the total target time
     scalar_t get_total_target() const {return m_total_target;}
     //! \brief Set the total target time
     void set_total_target(scalar_t total_target) {m_total_target = total_target;}
 
     void set_average_parameter(scalar_t alpha) {
         get_options().alpha_average = alpha;
         m_average.set_alpha(alpha);
     }
 
     //! obtain the next timestep
     scalar_t next_timestep(scalar_t dt_done, ReactiveTransportReturnCode return_code, index_t nb_iterations);
 
 private:
     scalar_t m_total;
     scalar_t m_total_target;
 
     utils::ExponentialMovingAverage m_average;
 };
 
 } // end namespace solver
 } // end namespace reactmicp
 } // end namespace specmicp
 
 #endif // SPECMICP_REACTMICP_SOLVER_TIMESTEPPER_HPP
diff --git a/src/reactmicp/systems/saturated_react/equilibrium_stagger.cpp b/src/reactmicp/systems/saturated_react/equilibrium_stagger.cpp
index 66adc7d..e39e2a4 100644
--- a/src/reactmicp/systems/saturated_react/equilibrium_stagger.cpp
+++ b/src/reactmicp/systems/saturated_react/equilibrium_stagger.cpp
@@ -1,142 +1,171 @@
+/*-------------------------------------------------------
+
+Copyright (c) 2014,2015 Fabien Georget <fabieng@princeton.edu>, Princeton University
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+    * Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+    * Redistributions in binary form must reproduce the above copyright
+      notice, this list of conditions and the following disclaimer in the
+      documentation and/or other materials provided with the distribution.
+    * Neither the name of the Princeton University nor the
+      names of its contributors may be used to endorse or promote products
+      derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+---------------------------------------------------------*/
+
 #include "equilibrium_stagger.hpp"
 #include "variables.hpp"
 
 #include "specmicp/adimensional/adimensional_system_solver.hpp"
 #include "specmicp/adimensional/adimensional_system_solution_extractor.hpp"
 #include "utils/log.hpp"
 #include "reactmicp/solver/staggers_base/stagger_structs.hpp"
 
 #ifdef SPECMICP_USE_OPENMP
 #include <omp.h>
 #endif // SPECMICP_USE_OPENMP
 
 namespace specmicp {
 namespace reactmicp {
 namespace systems {
 namespace satdiff {
 
 // EquilibriumStagger::
 
 //! \brief Initialize the stagger at the beginning of an iteration
 void EquilibriumStagger::initialize_timestep(scalar_t dt, VariablesBasePtr var)
 {
     m_dt = dt;
 
     SaturatedVariablesPtr true_var = cast_var_from_base(var);
 
     // Initialize velocity using values from previous timestep
     for (index_t node=0; node<true_var->nb_nodes(); ++node)
     {
         if (true_var->is_fixed_composition(node)) continue;
         scalar_t alpha = 1.0;
         for (index_t component: true_var->get_database()->range_aqueous_component())
         {
             alpha = std::max(alpha,
                              0.9*dt*true_var->solid_concentration(node, component, true_var->chemistry_rate())
                                /(true_var->solid_concentration(node, component, true_var->displacement()))
                              );
         }
         auto solid_velocity = true_var->velocity().segment(
                     true_var->offset_node(node)+true_var->offset_solid_concentration(),
                     true_var->nb_component());
         auto solid_chemistry_rate = true_var->chemistry_rate().segment(
                     true_var->offset_node(node)+true_var->offset_solid_concentration(),
                     true_var->nb_component());
         solid_velocity = 1/alpha * solid_chemistry_rate;
     }
 }
 
 //! \brief Solve the equation for the timestep
 solver::StaggerReturnCode EquilibriumStagger::restart_timestep(VariablesBasePtr var)
 {
     SaturatedVariablesPtr true_var = cast_var_from_base(var);
     int failed_chemistry = 0;
 #ifdef SPECMICP_USE_OPENMP
 #pragma omp parallel  default(none) shared(true_var, failed_chemistry)
     {
 #pragma omp for schedule(dynamic, 5)
         for (index_t node=0; node<true_var->nb_nodes(); ++node)
         {
             // only solve if necessary
             if (true_var->is_fixed_composition(node) or failed_chemistry > 0) continue;
             const auto retcode = solve_one_node(node, true_var);
             if (retcode > 0)
             {
                 ++failed_chemistry;
             }
         }
     }
 #else
     {
         for (index_t node=0; node<true_var->nb_nodes(); ++node)
         {
             if (true_var->is_fixed_composition(node)) continue;
             const auto retcode = solve_one_node(node, true_var);
             if (retcode > 0)
             {
                 ++failed_chemistry;
                 break;
             }
         }
     }
 #endif // SPECMICP_USE_OPENMP
     if (failed_chemistry > 0)
         return solver::StaggerReturnCode::UnknownError;
     return solver::StaggerReturnCode::ResidualMinimized;
 }
 
 //!
 int EquilibriumStagger::solve_one_node(index_t node, SaturatedVariablesPtr true_var)
 {
     AdimensionalSystemConstraints constraints(get_constraints(node));
 
     constraints.total_concentrations = true_var->total_concentrations(node);
 
     AdimensionalSystemSolver adim_solver(true_var->get_database(),
                                          constraints,
                                          true_var->equilibrium_solution(node),
                                          m_options);
     Vector variables(true_var->equilibrium_solution(node).main_variables);
     micpsolver::MiCPPerformance perf =  adim_solver.solve(variables);
 
     micpsolver::MiCPSolverReturnCode retcode = perf.return_code;
     if (retcode <= micpsolver::MiCPSolverReturnCode::NotConvergedYet)
     {
 
         ERROR << "Failed to solve chemistry problem at node " << node
               << ", return code = " << static_cast<int>(retcode)
               << ", residual = " << perf.current_residual;
         ERROR << "Total concentration : \n" << constraints.total_concentrations;
         return  1;
     }
 
     true_var->equilibrium_solution(node) = adim_solver.get_raw_solution(variables);
     AdimensionalSystemSolutionExtractor extractor(true_var->equilibrium_solution(node),
                                                   true_var->get_database(),
                                                   m_options.units_set);
 
     for (index_t component=0; component<true_var->nb_component(); ++component)
     {
         const scalar_t c_aq = extractor.density_water()*extractor.total_aqueous_concentration(component);
         true_var->aqueous_concentration(node, component, true_var->displacement()) = c_aq;
 
         const scalar_t c_aq_0 = true_var->aqueous_concentration(node, component, true_var->predictor());
         const scalar_t vel_aq = (c_aq - c_aq_0)/m_dt;
         true_var->aqueous_concentration(node, component, true_var->velocity()) = vel_aq;
 
         const scalar_t c_sol = extractor.total_immobile_concentration(component);
         true_var->solid_concentration(node, component, true_var->displacement()) = c_sol;
 
         const scalar_t c_sol_0 = true_var->solid_concentration(node, component, true_var->predictor());
         const scalar_t vel_sol = (c_sol - c_sol_0)/m_dt;
         true_var->solid_concentration(node, component, true_var->velocity()) = vel_sol;
         true_var->solid_concentration(node, component, true_var->chemistry_rate()) =  vel_sol;
     }
 
     return 0;
 }
 
 } // end namespace satdiff
 } // end namespace systems
 } // end namespace reactmicp
 } // end namespace specmicp
diff --git a/src/reactmicp/systems/saturated_react/equilibrium_stagger.hpp b/src/reactmicp/systems/saturated_react/equilibrium_stagger.hpp
index 083a7a7..fc4df2f 100644
--- a/src/reactmicp/systems/saturated_react/equilibrium_stagger.hpp
+++ b/src/reactmicp/systems/saturated_react/equilibrium_stagger.hpp
@@ -1,70 +1,99 @@
+/*-------------------------------------------------------
+
+Copyright (c) 2014,2015 Fabien Georget <fabieng@princeton.edu>, Princeton University
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+    * Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+    * Redistributions in binary form must reproduce the above copyright
+      notice, this list of conditions and the following disclaimer in the
+      documentation and/or other materials provided with the distribution.
+    * Neither the name of the Princeton University nor the
+      names of its contributors may be used to endorse or promote products
+      derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+---------------------------------------------------------*/
+
 #ifndef SPECMICP_REACTMICP_SYSTEMS_SATURATED_EQUILIBRIUMSTAGGER_HPP
 #define SPECMICP_REACTMICP_SYSTEMS_SATURATED_EQUILIBRIUMSTAGGER_HPP
 
 #include "reactmicp/solver/staggers_base/chemistry_stagger_base.hpp"
 #include "variablesfwd.hpp"
 
 #include "specmicp/adimensional/adimensional_system_solver_structs.hpp"
 
 namespace specmicp {
 namespace reactmicp {
 namespace systems {
 namespace satdiff {
 
 using VariablesBasePtr = solver::VariablesBasePtr;
 
 
 //! \brief Solve the equilibrium problem
 class EquilibriumStagger: public solver::ChemistryStaggerBase
 {
 public:
     EquilibriumStagger(index_t nb_nodes,
                        AdimensionalSystemConstraints constraints,
                        AdimensionalSystemSolverOptions options):
         m_id_constraints(nb_nodes, 0),
         m_list_constraints({constraints,}),
         m_options(options)
     {}
     EquilibriumStagger(
             std::vector<AdimensionalSystemConstraints> list_constraints,
             std::vector<int> index_constraints,
             AdimensionalSystemSolverOptions options):
         m_id_constraints(index_constraints),
         m_list_constraints(list_constraints),
         m_options(options)
     {}
     //! \brief Initialize the stagger at the beginning of the computation
     void initialize(VariablesBasePtr var) {}
 
     //! \brief Initialize the stagger at the beginning of an iteration
     void initialize_timestep(scalar_t dt, VariablesBasePtr var) override;
 
     //! \brief Solve the equation for the timestep
     solver::StaggerReturnCode restart_timestep(VariablesBasePtr var) override;
 
     //! \brief Solve the speciation problem at one node
     int solve_one_node(index_t node, SaturatedVariablesPtr var);
 
     //! \brief Return the constraints for 'node'
     //!
     //! \param node Index of the node
     AdimensionalSystemConstraints& get_constraints(index_t node) {
         return m_list_constraints[m_id_constraints[node]];
     }
 
 private:
 
 
     scalar_t m_dt;
 
     std::vector<int> m_id_constraints;
     std::vector<AdimensionalSystemConstraints> m_list_constraints;
     AdimensionalSystemSolverOptions m_options;
 };
 
 } // end namespace satdiff
 } // end namespace systems
 } // end namespace reactmicp
 } // end namespace specmicp
 
 #endif // SPECMICP_REACTMICP_SYSTEMS_SATURATED_EQUILIBRIUMSTAGGER_HPP
diff --git a/src/reactmicp/systems/saturated_react/init_variables.cpp b/src/reactmicp/systems/saturated_react/init_variables.cpp
index 6287191..8f69269 100644
--- a/src/reactmicp/systems/saturated_react/init_variables.cpp
+++ b/src/reactmicp/systems/saturated_react/init_variables.cpp
@@ -1,86 +1,115 @@
+/*-------------------------------------------------------
+
+Copyright (c) 2014,2015 Fabien Georget <fabieng@princeton.edu>, Princeton University
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+    * Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+    * Redistributions in binary form must reproduce the above copyright
+      notice, this list of conditions and the following disclaimer in the
+      documentation and/or other materials provided with the distribution.
+    * Neither the name of the Princeton University nor the
+      names of its contributors may be used to endorse or promote products
+      derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+---------------------------------------------------------*/
+
 #include "init_variables.hpp"
 
 #include "variables.hpp"
 #include "dfpm/meshes/mesh1d.hpp"
 
 #include "specmicp/adimensional/adimensional_system_solution_extractor.hpp"
 
 namespace specmicp {
 namespace reactmicp {
 namespace systems {
 namespace satdiff {
 
 // SaturatedVariablesFactory::
 
 SaturatedVariablesFactory::SaturatedVariablesFactory(
         mesh::Mesh1DPtr the_mesh,
         RawDatabasePtr the_database,
         units::UnitsSet the_units,
         const std::vector<index_t>& list_fixed_nodes,
         const std::vector<AdimensionalSystemSolution>& list_initial_states,
         const std::vector<int>& index_initial_state
         ):
     m_variable(std::make_shared<SaturatedVariables>(the_mesh, the_database)),
     m_database(the_database),
     nb_component(the_database->nb_component()),
     nb_nodes(the_mesh->nb_nodes())
 {
     init_size();
     set_fixed_nodes(list_fixed_nodes);
     init_chemistry(the_units, index_initial_state, list_initial_states);
 }
 
 void SaturatedVariablesFactory::init_size()
 {
     index_t main_ndf = nb_nodes*2*nb_component;
 
     m_variable->displacement() = Vector::Zero(main_ndf);
     m_variable->chemistry_rate() = Vector::Zero(main_ndf);
     m_variable->transport_rate() = Vector::Zero(main_ndf);
     m_variable->predictor() = Vector::Zero(main_ndf);
     m_variable->velocity() = Vector::Zero(main_ndf);
 
     m_variable->m_upscaling = Vector::Zero(m_variable->ndf_upscaling()*nb_nodes);
 }
 
 void SaturatedVariablesFactory::set_fixed_nodes(const std::vector<index_t>& list_fixed_nodes)
 {
     m_variable->m_is_fixed_composition = std::vector<bool>(nb_nodes, false);
     for (index_t node: list_fixed_nodes)
     {
         m_variable->m_is_fixed_composition[node] = true;
     }
 }
 
 void SaturatedVariablesFactory::init_chemistry(
         units::UnitsSet  the_units,
         const std::vector<int>& index_initial_state,
         const std::vector<AdimensionalSystemSolution>& list_initial_states)
 {
     m_variable->m_equilibrium_solutions.reserve(nb_nodes);
 
 
     for (index_t node=0; node<nb_nodes; ++node)
     {
         m_variable->m_equilibrium_solutions.push_back(list_initial_states[index_initial_state[node]]);
 
         AdimensionalSystemSolutionExtractor extractor(m_variable->m_equilibrium_solutions[node],
                                                       m_database, the_units);
 
         scalar_t rho_w = extractor.density_water();
 
         for (index_t component: m_database->range_component())
         {
             m_variable->aqueous_concentration(node, component, m_variable->displacement())
                     = rho_w*extractor.total_aqueous_concentration(component);
             m_variable->solid_concentration(node, component, m_variable->displacement())
                     = extractor.total_immobile_concentration(component);
         }
     }
 
 }
 
 } // end namespace satdiff
 } // end namespace systems
 } // end namespace reactmicp
 } // end namespace specmicp
diff --git a/src/reactmicp/systems/saturated_react/init_variables.hpp b/src/reactmicp/systems/saturated_react/init_variables.hpp
index a6f76dc..6fad376 100644
--- a/src/reactmicp/systems/saturated_react/init_variables.hpp
+++ b/src/reactmicp/systems/saturated_react/init_variables.hpp
@@ -1,68 +1,97 @@
+/*-------------------------------------------------------
+
+Copyright (c) 2014,2015 Fabien Georget <fabieng@princeton.edu>, Princeton University
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+    * Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+    * Redistributions in binary form must reproduce the above copyright
+      notice, this list of conditions and the following disclaimer in the
+      documentation and/or other materials provided with the distribution.
+    * Neither the name of the Princeton University nor the
+      names of its contributors may be used to endorse or promote products
+      derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+---------------------------------------------------------*/
+
 #ifndef SPECMICP_REACTMICP_SYSTEMS_SATURATED_INITVARIABLES_HPP
 #define SPECMICP_REACTMICP_SYSTEMS_SATURATED_INITVARIABLES_HPP
 
 #include "variablesfwd.hpp"
 #include "dfpm/meshes/mesh1dfwd.hpp"
 #include "database.hpp"
 
 #include "specmicp/adimensional/adimensional_system_solution.hpp"
 
 namespace specmicp {
 namespace reactmicp {
 namespace systems {
 namespace satdiff {
 
 //! \brief Initialize an instance of Saturated Variables
 class SaturatedVariablesFactory
 {
 public:
     SaturatedVariablesFactory(
             mesh::Mesh1DPtr the_mesh,
             RawDatabasePtr the_database,
             units::UnitsSet the_units,
             const std::vector<index_t>& list_fixed_nodes,
             const std::vector<AdimensionalSystemSolution>& list_initial_states,
             const std::vector<int>& index_initial_state
             );
     //! \brief Initialize the main vectors
     void init_size();
     //! \brief Initialize the BC
     void set_fixed_nodes(const std::vector<index_t>& list_fixed_nodes);
     //! \brief Initialize the chemistry informations
     void init_chemistry(
             units::UnitsSet the_units,
             const std::vector<int>& index_initial_state,
             const std::vector<AdimensionalSystemSolution>& list_initial_states);
     //! \brief Return the variables
     SaturatedVariablesPtr get_variable() {return m_variable;}
 
 private:
     SaturatedVariablesPtr m_variable;
     RawDatabasePtr m_database;
     index_t nb_component;
     index_t nb_nodes;
 };
 
 //! \brief Initialise an instance of SaturatedVariables
 inline SaturatedVariablesPtr init_variables(
         mesh::Mesh1DPtr the_mesh,
         RawDatabasePtr the_database,
         units::UnitsSet the_units,
         const std::vector<index_t>& list_fixed_nodes,
         const std::vector<AdimensionalSystemSolution>& list_initial_states,
         const std::vector<int>& index_initial_state
         )
 {
     SaturatedVariablesFactory factory(the_mesh, the_database, the_units,
                                      list_fixed_nodes,
                                      list_initial_states, index_initial_state);
     return factory.get_variable();
 }
 
 } // end namespace satdiff
 } // end namespace systems
 } // end namespace reactmicp
 } // end namespace specmicp
 
 #endif // SPECMICP_REACTMICP_SYSTEMS_SATURATED_INITVARIABLES_HPP
 
diff --git a/src/reactmicp/systems/saturated_react/react_solver.cpp b/src/reactmicp/systems/saturated_react/react_solver.cpp
index 8668cb2..e8751fd 100644
--- a/src/reactmicp/systems/saturated_react/react_solver.cpp
+++ b/src/reactmicp/systems/saturated_react/react_solver.cpp
@@ -1,11 +1,40 @@
+/*-------------------------------------------------------
+
+Copyright (c) 2014,2015 Fabien Georget <fabieng@princeton.edu>, Princeton University
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+    * Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+    * Redistributions in binary form must reproduce the above copyright
+      notice, this list of conditions and the following disclaimer in the
+      documentation and/or other materials provided with the distribution.
+    * Neither the name of the Princeton University nor the
+      names of its contributors may be used to endorse or promote products
+      derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+---------------------------------------------------------*/
+
 #include "react_solver.hpp"
 
 namespace specmicp {
 namespace reactmicp {
 namespace systems {
 namespace satdiff {
 
 } // end namespace satdiff
 } // end namespace systems
 } // end namespace reactmicp
 } // end namespace specmicp
diff --git a/src/reactmicp/systems/saturated_react/react_solver.hpp b/src/reactmicp/systems/saturated_react/react_solver.hpp
index 342c1f6..f5a653b 100644
--- a/src/reactmicp/systems/saturated_react/react_solver.hpp
+++ b/src/reactmicp/systems/saturated_react/react_solver.hpp
@@ -1,18 +1,47 @@
+/*-------------------------------------------------------
+
+Copyright (c) 2014,2015 Fabien Georget <fabieng@princeton.edu>, Princeton University
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+    * Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+    * Redistributions in binary form must reproduce the above copyright
+      notice, this list of conditions and the following disclaimer in the
+      documentation and/or other materials provided with the distribution.
+    * Neither the name of the Princeton University nor the
+      names of its contributors may be used to endorse or promote products
+      derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+---------------------------------------------------------*/
+
 #ifndef SPECMICP_REACTMICP_SYSTEMS_SATURATED_REACTSOLVER_HPP
 #define SPECMICP_REACTMICP_SYSTEMS_SATURATED_REACTSOLVER_HPP
 
 
 namespace specmicp {
 namespace reactmicp {
 namespace systems {
 namespace satdiff {
 
 
 
 } // end namespace satdiff
 } // end namespace systems
 } // end namespace reactmicp
 } // end namespace specmicp
 
 
 #endif // SPECMICP_REACTMICP_SYSTEMS_SATURATED_REACTSOLVER_HPP
diff --git a/src/reactmicp/systems/saturated_react/transport_program.cpp b/src/reactmicp/systems/saturated_react/transport_program.cpp
index 6158a65..e219487 100644
--- a/src/reactmicp/systems/saturated_react/transport_program.cpp
+++ b/src/reactmicp/systems/saturated_react/transport_program.cpp
@@ -1,285 +1,314 @@
+/*-------------------------------------------------------
+
+Copyright (c) 2014,2015 Fabien Georget <fabieng@princeton.edu>, Princeton University
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+    * Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+    * Redistributions in binary form must reproduce the above copyright
+      notice, this list of conditions and the following disclaimer in the
+      documentation and/or other materials provided with the distribution.
+    * Neither the name of the Princeton University nor the
+      names of its contributors may be used to endorse or promote products
+      derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+---------------------------------------------------------*/
+
 #include "transport_program.hpp"
 #include "dfpm/meshes/mesh1d.hpp"
 #include "variables.hpp"
 
 namespace specmicp {
 namespace reactmicp {
 namespace systems {
 namespace satdiff {
 
 //class SaturatedDiffusion::
 
 
 SaturatedDiffusion::SaturatedDiffusion(SaturatedVariablesPtr variables,
                    std::vector<index_t> list_fixed_nodes):
     m_ndf(2*variables->nb_component()),
     m_tot_ndf(2*variables->nb_component()*variables->get_mesh()->nb_nodes()),
     m_mesh(variables->get_mesh()),
     m_variables(variables),
     m_is_in_residual_computation(false)
 {
     number_equations(list_fixed_nodes, {}, {0, 1});
 }
 
 
 SaturatedDiffusion::SaturatedDiffusion(SaturatedVariablesPtr variables,
                    std::vector<index_t> list_fixed_nodes,
                    std::map<index_t, index_t>  list_slave_nodes,
                    std::vector<index_t> list_immobile_components):
     m_ndf(2*variables->nb_component()),
     m_tot_ndf(2*variables->nb_component()*variables->get_mesh()->nb_nodes()),
     m_mesh(variables->get_mesh()),
     m_variables(variables),
     m_is_in_residual_computation(false)
 {
     number_equations(list_fixed_nodes, list_slave_nodes, list_immobile_components);
 }
 
 void SaturatedDiffusion::number_equations(std::vector<index_t> list_fixed_nodes,
                                           std::map<index_t, index_t>  list_slave_nodes,
                                           std::vector<index_t> list_immobile_components)
 {
     m_ideq.resizeLike(m_variables->displacement());
     m_ideq.setZero();
     // flag fixed nodes
     for (index_t node: list_fixed_nodes)
     {
         for (index_t component=2; component<m_variables->nb_component(); ++component)
         {
             m_ideq(m_variables->dof_aqueous_concentration(node, component)) = no_equation;
         }
     }
     // flag slaves nodes
     // we flag them by making their ideq more negative than no_equation
     for (auto slave_pair: list_slave_nodes)
     {
         for (index_t component=2; component<m_variables->nb_component(); ++component)
         {
             m_ideq(m_variables->dof_aqueous_concentration(slave_pair.first, component)) = no_equation-1;
         }
     }
     // set equation numbers
     index_t neq = 0;
     for (index_t node=0; node<m_mesh->nb_nodes(); ++node)
     {
         for (index_t component: list_immobile_components)
         {
             m_ideq(m_variables->dof_aqueous_concentration(node, component)) = no_equation;
             m_ideq(m_variables->dof_aqueous_concentration(node, component)) = no_equation;
         }
         for (index_t component=0; component<m_variables->nb_component(); ++component)
         {
             index_t dof = m_variables->dof_aqueous_concentration(node, component);
             if (m_ideq(dof) > no_equation) // attribute an equation number if it is NOT a slave nor a fixed node
             {
                 m_ideq(dof) = neq;
                 ++neq;
             }
             dof = m_variables->dof_solid_concentration(node, component);
             m_ideq(dof) = no_equation;
         }
     }
     // slave nodes
     // attribute the correct equation number
     for (auto slave_pair: list_slave_nodes)
     {
         for (index_t component=1; component<m_variables->nb_component(); ++component)
         {
             m_ideq(m_variables->dof_aqueous_concentration(slave_pair.first, component)) =
                     m_ideq(m_variables->dof_aqueous_concentration(slave_pair.second, component));
         }
     }
     m_neq = neq;
 }
 
 void SaturatedDiffusion::compute_residuals(
         const Vector& displacement,
         const Vector& velocity,
         Vector& residual)
 {
     residual = Vector::Zero(get_neq());
     m_is_in_residual_computation = true;
     for (index_t element: m_mesh->range_elements())
     {
         for (index_t component=2; component<m_variables->nb_component(); ++component)
         {
             Eigen::Vector2d element_residual;
             element_residual.setZero();
             residuals_element_component(element, component, displacement, velocity, element_residual);
             for (index_t en=0; en<2; ++en)
             {
                 const index_t node = m_mesh->get_node(element, en);
                 const index_t id = m_ideq(m_variables->dof_aqueous_concentration(node, component));
                 if (id != no_equation) {residual(id) += element_residual(en);}
             }
         }
     }
     m_is_in_residual_computation = false;
 }
 
 void SaturatedDiffusion::residuals_element_component(
         index_t element,
         index_t component,
         const Vector& displacement,
         const Vector& velocity,
         Eigen::Vector2d& element_residual
         )
 {
     const scalar_t mass_coeff_0 = -m_mesh->get_volume_cell_element(element, 0);
     const scalar_t mass_coeff_1 = -m_mesh->get_volume_cell_element(element, 1);
 
     const index_t node_0 = m_mesh->get_node(element, 0);
     const index_t node_1 = m_mesh->get_node(element, 1);
 
     const scalar_t diff_coeff = 1.0/(0.5/m_variables->diffusion_coefficient(node_0) +
                                      0.5/m_variables->diffusion_coefficient(node_1));
 
 
     scalar_t flux_coeff = -( m_mesh->get_face_area(element) / m_mesh->get_dx(element)
                            * diff_coeff
                            ) ;
 
     const index_t dof_0 = m_variables->dof_aqueous_concentration(node_0, component);
     const index_t dof_1 = m_variables->dof_aqueous_concentration(node_1, component);
 
     // diffusion
     scalar_t flux_diffusion = flux_coeff*(displacement(dof_0) - displacement(dof_1));
 
     element_residual(0) = flux_diffusion;
     element_residual(1) = - flux_diffusion;
 
     // advection
 
     if (m_variables->fluid_velocity(element) != 0.0)
     {
         scalar_t flux_advection = (m_mesh->get_face_area(element))
                 *m_variables->fluid_velocity(element);
         if (m_variables->fluid_velocity(element) > 0)
         {
             flux_advection *= (displacement(dof_0) - displacement(dof_1));
             element_residual(1) += flux_advection;
         }
         else
         {
             flux_advection *= (displacement(dof_1) - displacement(dof_0));
             element_residual(0) -= flux_advection;
         }
     }
 
     if (m_is_in_residual_computation)
     {
         m_variables->aqueous_concentration(node_0, component,
                            m_variables->transport_rate()) += element_residual(0);
         m_variables->aqueous_concentration(node_1, component,
                            m_variables->transport_rate()) += element_residual(1);
     }
     // velocity
     element_residual(0) += mass_coeff_0*(velocity(dof_0)*m_variables->porosity(node_0)
                                          +m_variables->vel_porosity(node_0)*displacement(dof_0));
     element_residual(1) += mass_coeff_1*(velocity(dof_1)*m_variables->porosity(node_1)
                                          + m_variables->vel_porosity(node_1)*displacement(dof_1));
     // external rate
     element_residual(0) +=  mass_coeff_0*m_variables->solid_concentration(node_0, component,
                 m_variables->chemistry_rate());
     element_residual(1) +=  mass_coeff_1*m_variables->solid_concentration(node_1, component,
                 m_variables->chemistry_rate());
 }
 
 
 void SaturatedDiffusion::compute_jacobian(
         Vector& displacement,
         Vector& velocity,
         Eigen::SparseMatrix<scalar_t>& jacobian,
         scalar_t alphadt
         )
 {
     dfpm::list_triplet_t jacob;
     const index_t ncomp = m_variables->nb_component();
     const index_t estimation = m_mesh->nb_nodes()*(ncomp*m_mesh->nen);
     jacob.reserve(estimation);
     for (index_t element: m_mesh->range_elements())
     {
         jacobian_element(element, displacement, velocity, jacob, alphadt);
     }
     jacobian = Eigen::SparseMatrix<scalar_t>(get_neq(), get_neq());
     jacobian.setFromTriplets(jacob.begin(), jacob.end());
 }
 
 void SaturatedDiffusion::jacobian_element(
         index_t element,
         Vector& displacement,
         Vector& velocity,
         dfpm::list_triplet_t& jacobian,
         scalar_t alphadt)
 {
     for (index_t component=1; component<m_variables->nb_component(); ++component)
     {
         Eigen::Vector2d element_residual_orig(Eigen::Vector2d::Zero());
         residuals_element_component(element, component, displacement, velocity, element_residual_orig);
 
         for (index_t en=0; en<2; ++en)
         {
             Eigen::Vector2d element_residual(Eigen::Vector2d::Zero());
 
             const index_t node = m_mesh->get_node(element, en);
             const index_t dof = m_variables->dof_aqueous_concentration(node, component);
             const index_t idc = m_ideq(dof);
 
             if (idc == no_equation) continue;
 
             const scalar_t tmp_v = velocity(dof);
             const scalar_t tmp_d = displacement(dof);
 
             scalar_t h = eps_jacobian*std::abs(tmp_v);
             if (h < 1e-4*eps_jacobian) h = eps_jacobian;
             velocity(dof) = tmp_v + h;
             h = velocity(dof) - tmp_v;
 
             displacement(dof) = tmp_d + alphadt*h;
 
             residuals_element_component(element, component, displacement, velocity, element_residual);
             velocity(dof) = tmp_v;
             displacement(dof) = tmp_d;
 
             for (index_t enr=0; enr<2; ++enr)
             {
                 const index_t noder = m_mesh->get_node(element, enr);
                 const index_t idr = m_ideq(m_variables->dof_aqueous_concentration(noder, component));
 
                 if (idr == no_equation) continue;
                 jacobian.push_back(dfpm::triplet_t(
                               idr,
                               idc,
                               (element_residual(enr) - element_residual_orig(enr))/h
                               ));
             }
         }
     }
 }
 
 //! \brief Update the solutions
 void SaturatedDiffusion::update_solution(const Vector& update,
                      scalar_t lambda,
                      scalar_t alpha_dt,
                      Vector& predictor,
                      Vector& displacement,
                      Vector& velocity)
 {
     for (index_t node: m_mesh->range_nodes())
     {
         for (index_t component=1; component< m_variables->nb_component(); ++component)
         {
             const index_t dof = m_variables->dof_aqueous_concentration(node, component);
             const index_t id = m_ideq(dof);
             if (id == no_equation) continue;
             velocity(dof) += lambda*update(id);
         }
     }
     //displacement = m_variables->predictor() + alpha_dt*velocity;
     displacement = predictor + alpha_dt*velocity;
 }
 
 } // end namespace satdiff
 } // end namespace systems
 } // end namespace reactmicp
 } // end namespace specmicp
diff --git a/src/reactmicp/systems/saturated_react/transport_program.hpp b/src/reactmicp/systems/saturated_react/transport_program.hpp
index c3c1b58..a0dcadd 100644
--- a/src/reactmicp/systems/saturated_react/transport_program.hpp
+++ b/src/reactmicp/systems/saturated_react/transport_program.hpp
@@ -1,111 +1,140 @@
+/*-------------------------------------------------------
+
+Copyright (c) 2014,2015 Fabien Georget <fabieng@princeton.edu>, Princeton University
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+    * Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+    * Redistributions in binary form must reproduce the above copyright
+      notice, this list of conditions and the following disclaimer in the
+      documentation and/or other materials provided with the distribution.
+    * Neither the name of the Princeton University nor the
+      names of its contributors may be used to endorse or promote products
+      derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+---------------------------------------------------------*/
+
 #ifndef SPECMICP_REACTMICP_SYSTEMS_SATURATED_TRANSPORTPROGRAM_HPP
 #define SPECMICP_REACTMICP_SYSTEMS_SATURATED_TRANSPORTPROGRAM_HPP
 
 #include "dfpmsolver/parabolic_program.hpp"
 
 #include "variablesfwd.hpp"
 #include "dfpm/meshes/mesh1dfwd.hpp"
 #include "dfpm/types.hpp"
 
 namespace specmicp {
 namespace reactmicp {
 namespace systems {
 namespace satdiff {
 
 class SaturatedDiffusion:  public dfpmsolver::ParabolicProgram<SaturatedDiffusion>
 {
 public:
 
     SaturatedDiffusion(SaturatedVariablesPtr variables,
                        std::vector<index_t> list_fixed_nodes,
                        std::map<index_t, index_t>  list_slave_nodes,
                        std::vector<index_t> list_immobile_components);
 
     SaturatedDiffusion(SaturatedVariablesPtr variables,
                        std::vector<index_t> list_fixed_nodes);
 
     //! \brief Return the number of equations
     index_t get_neq() const {return m_neq;}
     //! \brief Return the number of degrees of freedom per node
     index_t get_ndf() const {return m_ndf;}
     //! \brief Return the total number of degrees of freedom
     index_t get_tot_ndf() const  {return m_tot_ndf;}
 
     //! \brief Method to update the variables
     void set_variables(SaturatedVariablesPtr variables) {m_variables = variables;}
 
     //! \brief Return the id of the equation corresponding to the degree of freedom 'id_dof'
     //!
     //! Return 'no_equation' if no equation exist
     index_t id_equation(index_t id_dof) const {return m_ideq(id_dof);}
 
     //! \brief Compute the residuals
     void compute_residuals(const Vector& displacement,
                            const Vector& velocity,
                            Vector& residual
                            );
     //! Compute the residuals inside 'element' for 'component'
     void residuals_element_component(
             index_t element,
             index_t component,
             const Vector& displacement,
             const Vector& velocity,
             Eigen::Vector2d& element_residual
             );
 
     //! \brief Compute the jacobian
     void compute_jacobian(Vector& displacement,
                           Vector& velocity,
                           Eigen::SparseMatrix<scalar_t>& jacobian,
                           scalar_t alphadt
                           );
     //! \brief Compute the contribution of 'element' in the jacobian
     void jacobian_element(
             index_t element,
             Vector& displacement,
             Vector& velocity,
             dfpm::list_triplet_t& jacobian,
             scalar_t alphadt);
 
     //! \brief Update the solutions
     void update_solution(const Vector& update,
                          scalar_t lambda,
                          scalar_t alpha_dt,
                          Vector& predictor,
                          Vector& displacement,
                          Vector& velocity);
 
     //! \brief Apply boundary conditions to the velocity vector
     //!
     //! by default do nothing.
     void apply_bc(scalar_t dt,
                   const Vector& displacement,
                   Vector& velocity)
     {}
 
 
 private:
     // number the equations
     void number_equations(std::vector<index_t> list_fixed_nodes,
                           std::map<index_t, index_t>  list_slave_nodes, std::vector<index_t> list_immobile_components);
 
 
     index_t m_neq;
     index_t m_ndf;
     index_t m_tot_ndf;
 
     Eigen::Matrix<index_t, Eigen::Dynamic, 1> m_ideq;
 
     mesh::Mesh1DPtr m_mesh;
     SaturatedVariablesPtr m_variables;
 
     bool m_is_in_residual_computation;
 
 };
 
 } // end namespace satdiff
 } // end namespace systems
 } // end namespace reactmicp
 } // end namespace specmicp
 
 #endif // SPECMICP_REACTMICP_SYSTEMS_SATURATED_TRANSPORTPROGRAM_HPP
diff --git a/src/reactmicp/systems/saturated_react/transport_stagger.cpp b/src/reactmicp/systems/saturated_react/transport_stagger.cpp
index 1569d67..4020f30 100644
--- a/src/reactmicp/systems/saturated_react/transport_stagger.cpp
+++ b/src/reactmicp/systems/saturated_react/transport_stagger.cpp
@@ -1,125 +1,154 @@
+/*-------------------------------------------------------
+
+Copyright (c) 2014,2015 Fabien Georget <fabieng@princeton.edu>, Princeton University
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+    * Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+    * Redistributions in binary form must reproduce the above copyright
+      notice, this list of conditions and the following disclaimer in the
+      documentation and/or other materials provided with the distribution.
+    * Neither the name of the Princeton University nor the
+      names of its contributors may be used to endorse or promote products
+      derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+---------------------------------------------------------*/
+
 #include "transport_stagger.hpp"
 #include "variables.hpp"
 #include "reactmicp/solver/staggers_base/stagger_structs.hpp"
 
 namespace specmicp {
 namespace reactmicp {
 namespace systems {
 namespace satdiff {
 
 // class SaturatedTransportStagger::
 
 namespace internal {
 
 //! \brief Translate a ParabolicDriverReturnCode to a StaggerReturnCode
 solver::StaggerReturnCode Parabolic2StaggerReturnCode(dfpmsolver::ParabolicDriverReturnCode retcode)
 {
     using ParRC = dfpmsolver::ParabolicDriverReturnCode;
     using StaRC = solver::StaggerReturnCode;
 
     switch (retcode)
     {
     case ParRC::ResidualMinimized:
             return StaRC::ResidualMinimized;
             break;
     case ParRC::ErrorMinimized:
             return StaRC::ErrorMinimized;
             break;
     default: // error
         switch(retcode)
         {
         case ParRC::MaxIterations:
             return StaRC::MaximumIterationsReached;
             break;
         case ParRC::StationaryPoint:
             return StaRC::StationaryPoint;
             break;
         case ParRC::NotConvergedYet:
             return StaRC::NotConvergedYet;
             break;
         default:
             return StaRC::UnknownError;
         }
     }
 }
 
 } // end namespace internal
 
 SaturatedTransportStagger::SaturatedTransportStagger(SaturatedVariablesPtr variables,
                                                      std::vector<index_t> list_fixed_nodes):
     m_program(variables, list_fixed_nodes),
     m_solver(m_program)
 {
 
 }
 
 SaturatedTransportStagger::SaturatedTransportStagger(
         SaturatedVariablesPtr variables,
         std::vector<index_t> list_fixed_nodes,
         std::map<index_t, index_t>  list_slave_nodes,
         std::vector<index_t> list_immobile_components):
     m_program(variables, list_fixed_nodes, list_slave_nodes, list_immobile_components),
     m_solver(m_program)
 {
 
 }
 
 //! \brief Initialize the stagger at the beginning of an iteration
 void SaturatedTransportStagger::initialize_timestep(scalar_t dt, VariablesBasePtr var)
 {
     m_dt = dt;
 
     SaturatedVariablesPtr true_var = cast_var_from_base(var);
     true_var->predictor() = true_var->displacement();
 
     true_var->velocity().setZero();
     true_var->transport_rate().setZero();
     m_solver.initialize_timestep(dt, true_var->displacement());
 
     Vector tmp = true_var->chemistry_rate();
     true_var->chemistry_rate().setZero();
     Eigen::VectorXd residuals;
     m_program.compute_residuals(true_var->displacement(), true_var->velocity(), residuals);
     m_residual_0 = residuals.norm();
 
     true_var->chemistry_rate() = tmp;
 
     m_program.set_variables(true_var);
 }
 
 
 //! \brief Solve the equation for the timestep
 solver::StaggerReturnCode SaturatedTransportStagger::restart_timestep(VariablesBasePtr var)
 {
     SaturatedVariablesPtr true_var = cast_var_from_base(var);
     m_solver.velocity() = true_var->velocity();
     dfpmsolver::ParabolicDriverReturnCode retcode = m_solver.restart_timestep(true_var->displacement());
     // copy variables if successful
     if (retcode > dfpmsolver::ParabolicDriverReturnCode::NotConvergedYet)
     {
         true_var->velocity() = m_solver.velocity();
     }
 
     return internal::Parabolic2StaggerReturnCode(retcode);
 }
 
 scalar_t SaturatedTransportStagger::get_update(VariablesBasePtr var)
 {
     return cast_var_from_base(var)->velocity().norm();
 }
 
 
 //! \brief Compute the residuals norm
 scalar_t SaturatedTransportStagger::get_residual(VariablesBasePtr var)
 {
     SaturatedVariablesPtr true_var = cast_var_from_base(var);
 
     Eigen::VectorXd residuals;
     m_program.compute_residuals(true_var->displacement(), true_var->velocity(), residuals);
     return residuals.norm();
 }
 
 } // end namespace satdiff
 } // end namespace systems
 } // end namespace reactmicp
 } // end namespace specmicp
diff --git a/src/reactmicp/systems/saturated_react/transport_stagger.hpp b/src/reactmicp/systems/saturated_react/transport_stagger.hpp
index 52219ad..52171ea 100644
--- a/src/reactmicp/systems/saturated_react/transport_stagger.hpp
+++ b/src/reactmicp/systems/saturated_react/transport_stagger.hpp
@@ -1,62 +1,91 @@
+/*-------------------------------------------------------
+
+Copyright (c) 2014,2015 Fabien Georget <fabieng@princeton.edu>, Princeton University
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+    * Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+    * Redistributions in binary form must reproduce the above copyright
+      notice, this list of conditions and the following disclaimer in the
+      documentation and/or other materials provided with the distribution.
+    * Neither the name of the Princeton University nor the
+      names of its contributors may be used to endorse or promote products
+      derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+---------------------------------------------------------*/
+
 #ifndef SPECMICP_REACTMICP_SYSTEMS_SATURATED_TRANSPORTSTAGGER_HPP
 #define SPECMICP_REACTMICP_SYSTEMS_SATURATED_TRANSPORTSTAGGER_HPP
 
 #include "variablesfwd.hpp"
 #include "reactmicp/solver/staggers_base/transport_stagger_base.hpp"
 
 #include "transport_program.hpp"
 #include "dfpmsolver/parabolic_driver.hpp"
 
 namespace specmicp {
 namespace reactmicp {
 namespace systems {
 namespace satdiff {
 
 using VariablesBasePtr = solver::VariablesBasePtr;
 
 class SaturatedTransportStagger: public solver::TransportStaggerBase
 {
 public:
 
     SaturatedTransportStagger(SaturatedVariablesPtr variables,
                               std::vector<index_t> list_fixed_nodes);
 
     SaturatedTransportStagger(SaturatedVariablesPtr variables,
                               std::vector<index_t> list_fixed_nodes,
                               std::map<index_t, index_t>  list_slave_nodes,
                               std::vector<index_t> list_immobile_components);
 
     //! \brief Return the options of the solver
     dfpmsolver::ParabolicDriverOptions& options_solver() {return m_solver.get_options();}
 
     //! \brief Initialize the stagger at the beginning of an iteration
     void initialize_timestep(scalar_t dt, VariablesBasePtr var) override;
 
     //! \brief Solve the equation for the timestep
     solver::StaggerReturnCode restart_timestep(VariablesBasePtr var) override;
 
     //! \brief Compute the residuals norm
     scalar_t get_residual(VariablesBasePtr var) override;
     //! \brief Compute the residuals norm
     scalar_t get_residual_0(VariablesBasePtr var) override {
         // TODO : a slightly more optimized version would use the value from the solver
         return m_residual_0;
     }
 
     //! \brief Obtain the update
     scalar_t get_update(VariablesBasePtr var) override;
 
 private:
     scalar_t m_dt;
     scalar_t m_residual_0;
     SaturatedDiffusion m_program;
     dfpmsolver::ParabolicDriver<SaturatedDiffusion> m_solver;
 
 };
 
 } // end namespace satdiff
 } // end namespace systems
 } // end namespace reactmicp
 } // end namespace specmicp
 
 #endif // SPECMICP_REACTMICP_SYSTEMS_SATURATED_TRANSPORTSTAGGER_HPP
diff --git a/src/reactmicp/systems/saturated_react/variables.cpp b/src/reactmicp/systems/saturated_react/variables.cpp
index 3a738e1..4aa0385 100644
--- a/src/reactmicp/systems/saturated_react/variables.cpp
+++ b/src/reactmicp/systems/saturated_react/variables.cpp
@@ -1,33 +1,62 @@
+/*-------------------------------------------------------
+
+Copyright (c) 2014,2015 Fabien Georget <fabieng@princeton.edu>, Princeton University
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+    * Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+    * Redistributions in binary form must reproduce the above copyright
+      notice, this list of conditions and the following disclaimer in the
+      documentation and/or other materials provided with the distribution.
+    * Neither the name of the Princeton University nor the
+      names of its contributors may be used to endorse or promote products
+      derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+---------------------------------------------------------*/
+
 #include "variables.hpp"
 
 #include "dfpm/meshes/mesh1d.hpp"
 
 namespace specmicp {
 namespace reactmicp {
 namespace systems {
 namespace satdiff {
 
 SaturatedVariables::SaturatedVariables(mesh::Mesh1DPtr the_mesh,
                    RawDatabasePtr the_database):
     m_mesh(the_mesh),
     m_database(the_database)
 {}
 
 Vector SaturatedVariables::total_concentrations(index_t node) {
 
     Vector total_conc =  porosity(node)*displacement().segment(offset_aqueous_concentration(node), nb_component())
             + displacement().segment(offset_solid_concentration(node), nb_component());
     return total_conc;
 }
 
 void SaturatedVariables::reset_main_variables() {
     displacement() = predictor();
     velocity().setZero();
     transport_rate().setZero();
     chemistry_rate().setZero();
 }
 
 } // end namespace satdiff
 } // end namespace systems
 } // end namespace reactmicp
 } // end namespace specmicp
diff --git a/src/reactmicp/systems/saturated_react/variables.hpp b/src/reactmicp/systems/saturated_react/variables.hpp
index 6d670dd..13830ab 100644
--- a/src/reactmicp/systems/saturated_react/variables.hpp
+++ b/src/reactmicp/systems/saturated_react/variables.hpp
@@ -1,224 +1,253 @@
+/*-------------------------------------------------------
+
+Copyright (c) 2014,2015 Fabien Georget <fabieng@princeton.edu>, Princeton University
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+    * Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+    * Redistributions in binary form must reproduce the above copyright
+      notice, this list of conditions and the following disclaimer in the
+      documentation and/or other materials provided with the distribution.
+    * Neither the name of the Princeton University nor the
+      names of its contributors may be used to endorse or promote products
+      derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+---------------------------------------------------------*/
+
 #ifndef SPECMICP_REACTMICP_SYSTEMS_SATURATED_VARIABLES_HPP
 #define SPECMICP_REACTMICP_SYSTEMS_SATURATED_VARIABLES_HPP
 
 #include "database.hpp"
 #include "reactmicp/solver/staggers_base/variables_base.hpp"
 #include "specmicp/adimensional/adimensional_system_solution.hpp"
 #include <vector>
 
 // forward declaration
 // ===================
 
 #include "dfpm/meshes/mesh1dfwd.hpp"
 namespace specmicp {
 namespace reactmicp {
 namespace solver {
     using VariablesBasePtr = std::shared_ptr<VariablesBase>;
 }
 namespace systems {
 namespace satdiff {
 class SaturatedVariablesFactory;
 } // end namespace satdiff
 } // end namespace systems
 } // end namespace reactmicp
 } // end namespace specmicp
 
 
 // Class declaration
 // =================
 
 namespace specmicp {
 namespace reactmicp {
 namespace systems {
 namespace satdiff {
 
 //! \brief Variables for the saturated reactive transport system
 //!
 //! Contain all the variables that need to be shared between the staggers
 class SaturatedVariables: public solver::VariablesBase
 {
     // SaturatedVariablesFactory should be the class to use to inialize
     // the variables correctly
     friend class SaturatedVariablesFactory;
 
 public:
     SaturatedVariables(mesh::Mesh1DPtr the_mesh,
                        RawDatabasePtr the_database);
 
     //! \brief Return the mesh
     mesh::Mesh1DPtr get_mesh() {return m_mesh;}
     //! \brief Return the database
     RawDatabasePtr get_database() {return m_database;}
 
     //! \brief Return the number of components
     index_t nb_component() {return m_database->nb_component();}
     //! \brief Return the number of nodes
     index_t nb_nodes() {return m_is_fixed_composition.size();}
     //! \brief Return true if 'node' has a fixed composition
     index_t is_fixed_composition(index_t node) {return m_is_fixed_composition[node];}
 
     // Main variables
     // ==============
 
     //! \brief Return the main variable vector
     Vector& displacement() {return m_displacement;}
     //! \brief Return the main variable vector at the beginning of the timestep
     Vector& predictor() {return m_predictor;}
     //! \brief Return the velocity of the main variables
     Vector& velocity() {return m_velocity;}
     //! \brief Return the rate of change of the main variables due to the transport operator
     Vector& transport_rate() {return m_transport_rate;}
     //! \brief Return the rate of change of the main variables due to the chemistry operator
     Vector& chemistry_rate() {return m_chemistry_rate;}
 
     // Access to main variables
     // ========================
 
     //! \brief Return the number of degree of freedom (per node) in the main variables vector
     index_t ndf() {return 2*m_database->nb_component();}
     //! \brief Return the offset of 'node' in the main variables vector
     index_t offset_node(index_t node) {return node*ndf();}
     //! \brief Return the offset of the aqueous concentration variables in the main variables vector
     index_t offset_aqueous_concentration() {return 0;}
     //! \brief Return the offset of the aqueous concentrations variables in the main variables vector
     index_t offset_aqueous_concentration(index_t node) {
         return offset_aqueous_concentration()+offset_node(node);}
     //! \brief Return the offset of the solid concentration variables in the main variables vector
     index_t offset_solid_concentration() {return m_database->nb_component();}
     //! \brief Return the offset of the solid concentrations variables in the main variables vector
     index_t offset_solid_concentration(index_t node) {
         return offset_solid_concentration()+offset_node(node);}
 
     //! \brief Return the degree of freedom number for the aqueous concentration of 'component' at 'node'
     index_t dof_aqueous_concentration(index_t node, index_t component) {
         return (component + offset_aqueous_concentration(node));
     }
     //! \brief Return the degree of freedom number for the solid concentration of 'component' at 'node'
     index_t dof_solid_concentration(index_t node, index_t component) {
         return (component + offset_solid_concentration(node));
     }
     //! \brief Return the aqueous concentration of 'component' at 'node' in 'var'
     //!
     //! 'var' is any of the main variables vector, it may be a velocity vector
     scalar_t& aqueous_concentration(index_t node, index_t component, Vector& var) {
         return var(dof_aqueous_concentration(node, component));
     }
     //! \brief Return the aqueous concentration of 'component' at 'node' in main variables
     //!
     //! 'var' is any of the main variables vector, it may be a velocity vector
     scalar_t& aqueous_concentration(index_t node, index_t component) {
         return m_displacement(dof_aqueous_concentration(node, component));
     }
     //! \brief Return the solid concentration of 'component' at 'node' in 'var'
     //!
     //! 'var' is any of the main variables vector, it may be a velocity vector
     scalar_t& solid_concentration(index_t node, index_t component, Vector& var){
         return var(dof_solid_concentration(node, component));
     }
     //! \brief Return the solid concentration of 'component' at 'node' in main variables
     //!
     //! 'var' is any of the main variables vector, it may be a velocity vector
     scalar_t& solid_concentration(index_t node, index_t component){
         return m_displacement(dof_solid_concentration(node, component));
     }
     //! \brief Return a vector containing the total concentrations computed from the main variables
     //!
     //! This is to be used to restart the chemistry computation
     Vector total_concentrations(index_t node);
 
     // Equilibrium
     // ===========
 
     //! \brief Returh the solution of the speciation solver at 'node'
     AdimensionalSystemSolution& equilibrium_solution(index_t node) {
         return m_equilibrium_solutions[node];
     }
 
     // Upscaling
     // =========
     //! \brief Return the offset for 'node' in the upscaling variables vector
     index_t offset_node_upscaling(index_t node) {return ndf_upscaling()*node;}
 
     //! \brief Return the number fo degree of freedom (per node) for the upscaling vector
     index_t ndf_upscaling() {return 5;}
     //! \brief Return the degree of freedom for the porosity at 'node'
     index_t dof_porosity(index_t node) {return 0 + offset_node_upscaling(node);}
     //! \brief Return the degree of freedom of the porosity velocity at 'node'
     index_t dof_vel_porosity(index_t node) {return 1 + offset_node_upscaling(node);}
     //! \brief Return the degree of freedom of the diffusion coefficient at 'node'
     index_t dof_diffusion_coefficient(index_t node) {return 2 + offset_node_upscaling(node);}
     //! \brief Return the degree of freedom of the permeability at 'node'
     index_t dof_permeability(index_t node) {return 3 + offset_node_upscaling(node);}
     //! \brief Return the fluid velocity
     index_t dof_fluid_velocity(index_t node) {return 4 + offset_node_upscaling(node);}
 
     //! \brief Return the porosity at 'node'
     scalar_t& porosity(index_t node) {return m_upscaling(dof_porosity(node));}
     //! \brief Return the rate of change of the porosity at 'node'
     scalar_t& vel_porosity(index_t node) {return m_upscaling(dof_vel_porosity(node));}
     //! \brief Return the diffusion coefficient at 'node'
     scalar_t& diffusion_coefficient(index_t node) {return m_upscaling(dof_diffusion_coefficient(node));}
     //! \brief Return the permeability at 'node'
     scalar_t& permeability(index_t node) {return m_upscaling(dof_permeability(node));}
     //! \brief Return the fluid velocity at 'node'
     scalar_t& fluid_velocity(index_t node) {return m_upscaling(dof_fluid_velocity(node));}
 
     //! \brief Return the vector of upscaling variables
     Vector& upscaling_variables() {return m_upscaling;}
 
     //! \brief Reset the main variables
     void reset_main_variables() override;
 
 private:
 
     // ############ //
     //  Attributes  //
     // ############ //
 
     mesh::Mesh1DPtr m_mesh;
     RawDatabasePtr m_database;
 
     std::vector<bool> m_is_fixed_composition;
 
     // Main variables
     // ==============
 
     Vector m_displacement;
     Vector m_predictor;
     Vector m_velocity;
     Vector m_transport_rate;
     Vector m_chemistry_rate;
 
     // Equilibrium
     // ===========
     std::vector<AdimensionalSystemSolution> m_equilibrium_solutions;
 
     // Upscaling
     // =========
 
     Vector m_upscaling;
 };
 
 //! \brief typedef of a shared pointer of a SaturatedVariables
 using SaturatedVariablesPtr = std::shared_ptr<SaturatedVariables>;
 
 // Casting function
 // =================
 
 //! \brief Static cast to a SaturatedVariablesPtr
 inline SaturatedVariablesPtr cast_var_from_base(solver::VariablesBasePtr var)
 {
     return std::static_pointer_cast<SaturatedVariables>(var);
 }
 //! \brief Static cast from a SaturatedVariablesPtr
 inline solver::VariablesBasePtr cast_var_to_base(SaturatedVariablesPtr var)
 {
     return std::static_pointer_cast<solver::VariablesBase>(var);
 }
 
 } // end namespace satdiff
 } // end namespace systems
 } // end namespace reactmicp
 } // end namespace specmicp
 
 #endif // SPECMICP_REACTMICP_SYSTEMS_SATURATED_VARIABLES_HPP
diff --git a/src/reactmicp/systems/saturated_react/variablesfwd.hpp b/src/reactmicp/systems/saturated_react/variablesfwd.hpp
index c5479f1..cef30e9 100644
--- a/src/reactmicp/systems/saturated_react/variablesfwd.hpp
+++ b/src/reactmicp/systems/saturated_react/variablesfwd.hpp
@@ -1,19 +1,48 @@
+/*-------------------------------------------------------
+
+Copyright (c) 2014,2015 Fabien Georget <fabieng@princeton.edu>, Princeton University
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+    * Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+    * Redistributions in binary form must reproduce the above copyright
+      notice, this list of conditions and the following disclaimer in the
+      documentation and/or other materials provided with the distribution.
+    * Neither the name of the Princeton University nor the
+      names of its contributors may be used to endorse or promote products
+      derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+---------------------------------------------------------*/
+
 #ifndef SPECMICP_REACTMICP_SYSTEMS_SATURATED_VARIABLESFWD_HPP
 #define SPECMICP_REACTMICP_SYSTEMS_SATURATED_VARIABLESFWD_HPP
 
 #include <memory>
 
 namespace specmicp {
 namespace reactmicp {
 namespace systems {
 namespace satdiff {
 
 class SaturatedVariables;
 using SaturatedVariablesPtr = std::shared_ptr<SaturatedVariables>;
 
 } // end namespace satdiff
 } // end namespace systems
 } // end namespace reactmicp
 } // end namespace specmicp
 
 #endif // SPECMICP_REACTMICP_SYSTEMS_SATURATED_VARIABLESFWD_HPP
diff --git a/src/specmicp/adimensional_kinetics/kinetic_model.hpp b/src/specmicp/adimensional_kinetics/kinetic_model.hpp
index ad428eb..90d6edd 100644
--- a/src/specmicp/adimensional_kinetics/kinetic_model.hpp
+++ b/src/specmicp/adimensional_kinetics/kinetic_model.hpp
@@ -1,53 +1,82 @@
+/*-------------------------------------------------------
+
+Copyright (c) 2014,2015 Fabien Georget <fabieng@princeton.edu>, Princeton University
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+    * Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+    * Redistributions in binary form must reproduce the above copyright
+      notice, this list of conditions and the following disclaimer in the
+      documentation and/or other materials provided with the distribution.
+    * Neither the name of the Princeton University nor the
+      names of its contributors may be used to endorse or promote products
+      derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+---------------------------------------------------------*/
+
 #ifndef SPECMICP_SPECMICP_ADIMKINETICS_KINETICMODEL_HPP
 #define SPECMICP_SPECMICP_ADIMKINETICS_KINETICMODEL_HPP
 
 #include "common.hpp"
 #include "kinetic_variables.hpp"
 
 namespace specmicp {
 namespace kinetics {
 
 // \brief Base class for a kinetic model
 class AdimKineticModel
 {
 public:
 
     AdimKineticModel()
     {}
 
     AdimKineticModel(const std::vector<index_t>& list_species):
         m_list_species(list_species)
     {}
 
     virtual ~AdimKineticModel() {}
 
     //! \brief Return the number of kinetic minerals included in the problem
     index_t get_neq() {return m_list_species.size();}
 
     //! \brief Compute the kinetic rates and store them in dydt
     virtual void compute_rate(
             scalar_t t,
             const Vector& y,
             AdimKineticVariables& variables,
             Vector& dydt
             ) = 0;
 
 
     void add_equation(index_t species) {m_list_species.push_back(species);}
 
     //! \brief Index of species corresponding to equation 'id_equation'
     index_t index_species(index_t id_equation) {return m_list_species[id_equation];}
 
     //! \brief Iterator over the species vector
     std::vector<index_t>::iterator species_begin() {return m_list_species.begin();}
     std::vector<index_t>::iterator species_end() {return m_list_species.end();}
 
 private:
     std::vector<index_t> m_list_species;
 };
 
 } // end namespace kinetics
 } // end namespace specmicp
 
 
 #endif //SPECMICP_SPECMICP_ADIMKINETICS_KINETICMODEL_HPP
diff --git a/src/specmicp/adimensional_kinetics/kinetic_system.cpp b/src/specmicp/adimensional_kinetics/kinetic_system.cpp
index e6e86a9..a933a78 100644
--- a/src/specmicp/adimensional_kinetics/kinetic_system.cpp
+++ b/src/specmicp/adimensional_kinetics/kinetic_system.cpp
@@ -1,78 +1,107 @@
+/*-------------------------------------------------------
+
+Copyright (c) 2014,2015 Fabien Georget <fabieng@princeton.edu>, Princeton University
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+    * Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+    * Redistributions in binary form must reproduce the above copyright
+      notice, this list of conditions and the following disclaimer in the
+      documentation and/or other materials provided with the distribution.
+    * Neither the name of the Princeton University nor the
+      names of its contributors may be used to endorse or promote products
+      derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+---------------------------------------------------------*/
+
 #include "kinetic_system.hpp"
 
 #include "kinetic_model.hpp"
 #include "specmicp/adimensional/adimensional_system_solver.hpp"
 
 #include "utils/log.hpp"
 
 
 namespace specmicp {
 namespace kinetics {
 
 void AdimKineticSystem::update_total_concentrations(const Vector& y)
 {
     //Vector y_temp = y.cwiseMax(Vector::Zero(y.rows()));
     Vector update_minerals = (y - m_variables.concentration_minerals());
     m_variables.total_concentrations() = m_variables.total_concentrations_initial();
     for (auto it=m_model->species_begin(); it!=m_model->species_end(); ++it)
     {
         for (index_t component: m_data->range_component())
         {
             if (m_data->nu_mineral_kinetic(*it, component) == 0.0) continue;
             m_variables.total_concentration(component) -=
                     m_data->nu_mineral_kinetic(*it, component)*update_minerals(it-m_model->species_begin());
         }
     }
 }
 
 void AdimKineticSystem::update_to_new_initial_condition(const Vector& y, scalar_t dt)
 {
     update_total_concentrations(y);
     m_variables.rate_components() += (
                   m_variables.total_concentrations()
                 - m_variables.total_concentrations_initial()
                 )/dt;
     m_variables.concentration_minerals() = y;
     m_variables.total_concentrations_initial() = m_variables.total_concentrations();
 }
 
 void AdimKineticSystem::compute_rates(scalar_t t, const Vector& y, Vector& dydt)
 {
     m_model->compute_rate(t, y, m_variables, dydt);
 }
 
 
 void AdimKineticSystem::compute_equilibrium(
         AdimensionalSystemConstraints& constraints,
         AdimensionalSystemSolverOptions& options)
 {
     AdimensionalSystemSolver solver;
     Vector variables;
     specmicp::micpsolver::MiCPPerformance perf;
     constraints.total_concentrations = m_variables.total_concentrations();
     if (m_variables.equilibrium_solution().is_valid)
     {
         solver = AdimensionalSystemSolver(m_data,
                                      constraints,
                                      m_variables.equilibrium_solution(),
                                      options);
         variables = m_variables.equilibrium_solution().main_variables;
         perf = solver.solve(variables);
     }
     else
     {
         solver = AdimensionalSystemSolver(m_data,
                                      constraints,
                                      options);
         perf = solver.solve(variables, true);
     }
     //std::cout << variables << std::endl;
     if ((int) perf.return_code < 0)
     {
         ERROR << "Failed to solve the system ! Error code " << (int) perf.return_code;
     }
     m_variables.update_equilibrium_solution(solver.get_raw_solution(variables));
 }
 
 } // end namespace kinetics
 } // end namespace specmicp
diff --git a/src/specmicp/adimensional_kinetics/kinetic_system.hpp b/src/specmicp/adimensional_kinetics/kinetic_system.hpp
index 7aa22b1..d872f03 100644
--- a/src/specmicp/adimensional_kinetics/kinetic_system.hpp
+++ b/src/specmicp/adimensional_kinetics/kinetic_system.hpp
@@ -1,90 +1,119 @@
+/*-------------------------------------------------------
+
+Copyright (c) 2014,2015 Fabien Georget <fabieng@princeton.edu>, Princeton University
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+    * Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+    * Redistributions in binary form must reproduce the above copyright
+      notice, this list of conditions and the following disclaimer in the
+      documentation and/or other materials provided with the distribution.
+    * Neither the name of the Princeton University nor the
+      names of its contributors may be used to endorse or promote products
+      derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+---------------------------------------------------------*/
+
 #ifndef SPECMICP_SPECMICP_ADIMKINETICS_KINETICSYSTEM_HPP
 #define SPECMICP_SPECMICP_ADIMKINETICS_KINETICSYSTEM_HPP
 
 #include <memory>
 #include "common.hpp"
 #include "database.hpp"
 #include "kinetic_variables.hpp"
 #include "specmicp/adimensional/adimensional_system_solver_structs.hpp"
 
 namespace specmicp {
 
 namespace kinetics {
 
 class AdimKineticModel;
 
 //! \brief Kinetics System,
 //!
 //! Wrapper for a kinetic model
 class AdimKineticSystem
 {
 public:
 
     AdimKineticSystem(
             std::shared_ptr<AdimKineticModel> model,
             const Vector& total_concentrations,
             const Vector& mineral_concentrations,
             AdimensionalSystemConstraints& constraints,
             RawDatabasePtr database
             ):
         m_data(database),
         m_model(model),
         m_constraints(constraints),
         m_variables(total_concentrations, mineral_concentrations)
     {}
 
     AdimKineticSystem(
             std::shared_ptr<AdimKineticModel> model,
             const Vector& total_concentrations,
             const Vector& mineral_concentrations,
             AdimensionalSystemConstraints& constraints,
             const AdimensionalSystemSolution& equilibrium_solution,
             RawDatabasePtr database
             ):
         m_data(database),
         m_model(model),
         m_constraints(constraints),
         m_variables(total_concentrations, mineral_concentrations, equilibrium_solution)
     {}
 
     //! \brief Compute the kinetics rates to be solved
     //!
     //! Use the kinetic model provided by the user
     void compute_rates(scalar_t x, const Vector& y, Vector& dydt);
 
     //! \brief Compute the equilibrium state of the solution
     void compute_equilibrium(
             AdimensionalSystemConstraints& constraints,
             AdimensionalSystemSolverOptions& options
             );
 
     //! \brief Update the total concentrations
     //!
     //! \param y vector of variables (mols of minerals)
     void update_total_concentrations(const Vector& y);
 
     void update_to_new_initial_condition(const Vector& y, scalar_t dt);
 
     //! \brief Right Hand side function for the integrator
     void rhs(scalar_t x, const Vector& y, Vector& dydt, AdimensionalSystemSolverOptions& options)
     {
         update_total_concentrations(y);
         compute_equilibrium(m_constraints, options);
         compute_rates(x, y, dydt);
     }
 
     AdimKineticVariables& variables() {return m_variables;}
 
     AdimensionalSystemConstraints& constraints() {return m_constraints;}
 private:
     RawDatabasePtr m_data;
     std::shared_ptr<AdimKineticModel> m_model;
     AdimensionalSystemConstraints m_constraints;
     AdimKineticVariables m_variables;
 };
 
 } // end namespace kinetics
 } // end namespace specmicp
 
 
 #endif //SPECMICP_SPECMICP_ADIMKINETICS_KINETICSYSTEM_HPP
diff --git a/src/specmicp/adimensional_kinetics/kinetic_system_euler_solver.cpp b/src/specmicp/adimensional_kinetics/kinetic_system_euler_solver.cpp
index 292caad..28081cf 100644
--- a/src/specmicp/adimensional_kinetics/kinetic_system_euler_solver.cpp
+++ b/src/specmicp/adimensional_kinetics/kinetic_system_euler_solver.cpp
@@ -1,34 +1,63 @@
+/*-------------------------------------------------------
+
+Copyright (c) 2014,2015 Fabien Georget <fabieng@princeton.edu>, Princeton University
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+    * Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+    * Redistributions in binary form must reproduce the above copyright
+      notice, this list of conditions and the following disclaimer in the
+      documentation and/or other materials provided with the distribution.
+    * Neither the name of the Princeton University nor the
+      names of its contributors may be used to endorse or promote products
+      derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+---------------------------------------------------------*/
+
 #include "kinetic_system_euler_solver.hpp"
 
 #include "kinetic_model.hpp"
 #include "odeint/runge_kutta_step.hpp"
 
 #include <functional>
 
 namespace specmicp {
 namespace kinetics {
 
 
 void AdimKineticSystemEulerSolver::solve(scalar_t dt, scalar_t total)
 {
     double t = 0.0;
     Vector y = m_system.variables().concentration_minerals();
     Vector dydx(y.rows());
     dydx.setZero();
 
     while (t < total)
     {
         m_system.rhs(t, y, dydx, get_options().speciation_options);
         y += dt*dydx;
 
         m_system.update_to_new_initial_condition(y, dt);
         t += dt;
         if (t+dt > total) dt =(total - t);
     }
     m_system.update_total_concentrations(y);
     m_system.compute_equilibrium(m_system.constraints(), get_options().speciation_options);
 
 }
 
 } // end namespace kinetics
 } // end namespace specmicp
diff --git a/src/specmicp/adimensional_kinetics/kinetic_system_euler_solver.hpp b/src/specmicp/adimensional_kinetics/kinetic_system_euler_solver.hpp
index f606bb5..147f0d2 100644
--- a/src/specmicp/adimensional_kinetics/kinetic_system_euler_solver.hpp
+++ b/src/specmicp/adimensional_kinetics/kinetic_system_euler_solver.hpp
@@ -1,54 +1,83 @@
+/*-------------------------------------------------------
+
+Copyright (c) 2014,2015 Fabien Georget <fabieng@princeton.edu>, Princeton University
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+    * Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+    * Redistributions in binary form must reproduce the above copyright
+      notice, this list of conditions and the following disclaimer in the
+      documentation and/or other materials provided with the distribution.
+    * Neither the name of the Princeton University nor the
+      names of its contributors may be used to endorse or promote products
+      derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+---------------------------------------------------------*/
+
 #ifndef SPECMICP_SPECMICP_ADIMKINETICS_KINETICSYSTEMEULERSOLVER_HPP
 #define SPECMICP_SPECMICP_ADIMKINETICS_KINETICSYSTEMEULERSOLVER_HPP
 
 #include "kinetic_system.hpp"
 #include "kinetic_system_solver_structs.hpp"
 
 #include "utils/options_handler.hpp"
 
 namespace specmicp {
 namespace kinetics {
 
 class AdimKineticModel;
 
 class AdimKineticSystemEulerSolver: public OptionsHandler<AdimKineticSystemSolverOptions>
 {
 public:
     AdimKineticSystemEulerSolver(
             std::shared_ptr<AdimKineticModel> model,
             const Vector& total_concentrations,
             const Vector& mineral_concentration,
             AdimensionalSystemConstraints& constraints,
             RawDatabasePtr database
             ):
         m_current_dt(-1),
         m_system(model, total_concentrations, mineral_concentration, constraints, database)
     {}
 
     AdimKineticSystemEulerSolver(
             std::shared_ptr<AdimKineticModel> model,
             const Vector& total_concentrations,
             const Vector& mineral_concentration,
             AdimensionalSystemConstraints& constraints,
             const AdimensionalSystemSolution& equilibrium_solution,
             RawDatabasePtr database
             ):
         m_current_dt(-1),
         m_system(model, total_concentrations, mineral_concentration, constraints, equilibrium_solution, database)
     {}
 
     void solve(scalar_t dt, scalar_t total);
 
     scalar_t current_dt() {return m_current_dt;}
 
     AdimKineticVariables& variables() {return m_system.variables();}
 
 private:
     scalar_t m_current_dt;
     AdimKineticSystem m_system;
 };
 
 } // end namespace kinetics
 } // end namespace specmicp
 
 #endif //SPECMICP_SPECMICP_ADIMKINETICS_KINETICSYSTEMEULERSOLVER_HPP
diff --git a/src/specmicp/adimensional_kinetics/kinetic_system_solver.cpp b/src/specmicp/adimensional_kinetics/kinetic_system_solver.cpp
index 10ff090..36fc4bd 100644
--- a/src/specmicp/adimensional_kinetics/kinetic_system_solver.cpp
+++ b/src/specmicp/adimensional_kinetics/kinetic_system_solver.cpp
@@ -1,50 +1,79 @@
+/*-------------------------------------------------------
+
+Copyright (c) 2014,2015 Fabien Georget <fabieng@princeton.edu>, Princeton University
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+    * Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+    * Redistributions in binary form must reproduce the above copyright
+      notice, this list of conditions and the following disclaimer in the
+      documentation and/or other materials provided with the distribution.
+    * Neither the name of the Princeton University nor the
+      names of its contributors may be used to endorse or promote products
+      derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+---------------------------------------------------------*/
+
 #include "kinetic_system_solver.hpp"
 
 #include "kinetic_model.hpp"
 #include "odeint/runge_kutta_step.hpp"
 
 #include <functional>
 
 namespace specmicp {
 namespace kinetics {
 
 
 void AdimKineticSystemSolver::solve(scalar_t dt, scalar_t total)
 {
     double t = 0.0;
     Vector y = m_system.variables().concentration_minerals();
     Vector dydx(y.rows());
     dydx.setZero();
     m_system.rhs(t, y, dydx, get_options().speciation_options);
 
 
     odeint::rhs_f<Eigen::Dynamic> rhs =  std::bind(std::mem_fn(&AdimKineticSystem::rhs),
                                              m_system,
                                              std::placeholders::_1,
                                              std::placeholders::_2,
                                              std::placeholders::_3,
                                              get_options().speciation_options);
     //odeint::CashKarpStep<Eigen::Dynamic> driver = odeint::get_cash_karp_step<Eigen::Dynamic>(rhs);
     odeint::DormandPrinceStep<Eigen::Dynamic> driver = odeint::get_dormand_prince_step<Eigen::Dynamic>(rhs);
 
     odeint::StepLength stepl(dt, total);
     int cnt = 0;
     while (t < total)
     {
         driver.rk_step(y, dydx, t, stepl);
         m_system.update_to_new_initial_condition(y, stepl.did);
         cnt +=1;
         scalar_t remaining = stepl.remaining(t);
         if (remaining == 0.0)  break;
         if (stepl.next > remaining) stepl.next = remaining;
         stepl.get_next();
         m_current_dt = stepl.test;
 
     }
     m_system.update_total_concentrations(y);
     m_system.compute_equilibrium(m_system.constraints(), get_options().speciation_options);
 
 }
 
 } // end namespace kinetics
 } // end namespace specmicp
diff --git a/src/specmicp/adimensional_kinetics/kinetic_system_solver.hpp b/src/specmicp/adimensional_kinetics/kinetic_system_solver.hpp
index c7206f3..a8d8cea 100644
--- a/src/specmicp/adimensional_kinetics/kinetic_system_solver.hpp
+++ b/src/specmicp/adimensional_kinetics/kinetic_system_solver.hpp
@@ -1,54 +1,83 @@
+/*-------------------------------------------------------
+
+Copyright (c) 2014,2015 Fabien Georget <fabieng@princeton.edu>, Princeton University
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+    * Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+    * Redistributions in binary form must reproduce the above copyright
+      notice, this list of conditions and the following disclaimer in the
+      documentation and/or other materials provided with the distribution.
+    * Neither the name of the Princeton University nor the
+      names of its contributors may be used to endorse or promote products
+      derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+---------------------------------------------------------*/
+
 #ifndef SPECMICP_SPECMICP_ADIMKINETICS_KINETICSYSTEMSOLVER_HPP
 #define SPECMICP_SPECMICP_ADIMKINETICS_KINETICSYSTEMSOLVER_HPP
 
 #include "kinetic_system.hpp"
 #include "kinetic_system_solver_structs.hpp"
 
 #include "utils/options_handler.hpp"
 
 namespace specmicp {
 namespace kinetics {
 
 class AdimKineticModel;
 
 class AdimKineticSystemSolver: public OptionsHandler<AdimKineticSystemSolverOptions>
 {
 public:
     AdimKineticSystemSolver(
             std::shared_ptr<AdimKineticModel> model,
             const Vector& total_concentrations,
             const Vector& mineral_moles,
             AdimensionalSystemConstraints& constraints,
             RawDatabasePtr database
             ):
         m_current_dt(-1),
         m_system(model, total_concentrations, mineral_moles, constraints, database)
     {}
 
     AdimKineticSystemSolver(
             std::shared_ptr<AdimKineticModel> model,
             const Vector& total_concentrations,
             const Vector& mineral_moles,
             AdimensionalSystemConstraints& constraints,
             const AdimensionalSystemSolution& equilibrium_solution,
             RawDatabasePtr database
             ):
         m_current_dt(-1),
         m_system(model, total_concentrations, mineral_moles, constraints, equilibrium_solution, database)
     {}
 
     void solve(scalar_t dt, scalar_t total);
 
     scalar_t current_dt() {return m_current_dt;}
 
     AdimKineticVariables& variables() {return m_system.variables();}
 
 private:
     scalar_t m_current_dt;
     AdimKineticSystem m_system;
 };
 
 } // end namespace kinetics
 } // end namespace specmicp
 
 #endif //SPECMICP_SPECMICP_ADIMKINETICS_KINETICSYSTEMSOLVER_HPP
diff --git a/src/specmicp/adimensional_kinetics/kinetic_system_solver_structs.hpp b/src/specmicp/adimensional_kinetics/kinetic_system_solver_structs.hpp
index 95402ca..8d0c604 100644
--- a/src/specmicp/adimensional_kinetics/kinetic_system_solver_structs.hpp
+++ b/src/specmicp/adimensional_kinetics/kinetic_system_solver_structs.hpp
@@ -1,20 +1,49 @@
+/*-------------------------------------------------------
+
+Copyright (c) 2014,2015 Fabien Georget <fabieng@princeton.edu>, Princeton University
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+    * Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+    * Redistributions in binary form must reproduce the above copyright
+      notice, this list of conditions and the following disclaimer in the
+      documentation and/or other materials provided with the distribution.
+    * Neither the name of the Princeton University nor the
+      names of its contributors may be used to endorse or promote products
+      derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+---------------------------------------------------------*/
+
 #ifndef SPECMICP_SPECMICP_ADIMKINETICS_KINETICSYSTEMSOLVERSTRUCTS
 #define SPECMICP_SPECMICP_ADIMKINETICS_KINETICSYSTEMSOLVERSTRUCTS
 
 #include "specmicp/adimensional/adimensional_system_solver_structs.hpp"
 #include "odeint/runge_kutta_step_structs.hpp"
 
 namespace specmicp {
 namespace kinetics {
 
 struct AdimKineticSystemSolverOptions
 {
     odeint::EmbeddedRungeKuttaStepOptions rk_options;
     AdimensionalSystemSolverOptions speciation_options;
 };
 
 
 } // end namespace kinetics
 } // end namespace specmicp
 
 #endif //  SPECMICP_SPECMICP_ADIMKINETICS_KINETICSYSTEMSOLVERSTRUCTS
diff --git a/src/specmicp/adimensional_kinetics/kinetic_variables.hpp b/src/specmicp/adimensional_kinetics/kinetic_variables.hpp
index c8a9d1d..4861058 100644
--- a/src/specmicp/adimensional_kinetics/kinetic_variables.hpp
+++ b/src/specmicp/adimensional_kinetics/kinetic_variables.hpp
@@ -1,107 +1,136 @@
+/*-------------------------------------------------------
+
+Copyright (c) 2014,2015 Fabien Georget <fabieng@princeton.edu>, Princeton University
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+    * Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+    * Redistributions in binary form must reproduce the above copyright
+      notice, this list of conditions and the following disclaimer in the
+      documentation and/or other materials provided with the distribution.
+    * Neither the name of the Princeton University nor the
+      names of its contributors may be used to endorse or promote products
+      derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+---------------------------------------------------------*/
+
 #ifndef SPECMICP_SPECMICP_ADIMKINETICS_KINETICVARIABLES_HPP
 #define SPECMICP_SPECMICP_ADIMKINETICS_KINETICVARIABLES_HPP
 
 #include "common.hpp"
 #include "database.hpp"
 #include "specmicp/adimensional/adimensional_system_solution.hpp"
 
 namespace specmicp {
 namespace kinetics {
 
 //! \brief Variables used in a kinetic computation
 class AdimKineticVariables
 {
 public:
     AdimKineticVariables(
             const Vector& total_concentrations,
             const Vector& mineral_concentration
             ):
         m_mineral_kinetics(mineral_concentration),
         m_total_concentrations_initial(total_concentrations),
         m_total_concentrations(total_concentrations),
         m_rate(Vector::Zero(total_concentrations.rows()))
     {}
 
     AdimKineticVariables(
             const Vector& total_concentrations,
             const Vector& mineral_concentration,
             const AdimensionalSystemSolution& equilibrium_solution
             ):
         m_mineral_kinetics(mineral_concentration),
         m_total_concentrations_initial(total_concentrations),
         m_total_concentrations(total_concentrations),
         m_rate(Vector::Zero(total_concentrations.rows())),
         m_equilibrium_solution(equilibrium_solution)
     {}
 
     //! \brief Return the number of species considered in the kinetics computation
     index_t get_neq() {return m_mineral_kinetics.rows();}
 
     // Concentration of minerals
     // ---------------------------
 
     //! \brief Return mole number of mineral "mineral kinetic"
     scalar_t concentration_mineral(index_t mineral_kinetic) const {return m_mineral_kinetics(mineral_kinetic);}
     //! \brief Return a const reference to the vector of moles number
     const Vector& concentration_minerals() const {return m_mineral_kinetics;}
     //! \brief Return a reference to the vector of moles number
     Vector& concentration_minerals() {return m_mineral_kinetics;}
 
     // Total concentrations
     // --------------------
 
     //! \brief Return the total concentration (at equilibrium) of 'component'
     scalar_t total_concentration(index_t component) const {return m_total_concentrations(component);}
     //! \brief Return the total concentration (at equilibrium) of 'component'
     scalar_t& total_concentration(index_t component) {return m_total_concentrations(component);}
     //! \brief Return a const reference to the total concentration (at equilibrium) vector
     const Vector& total_concentrations() const {return m_total_concentrations;}
     //! \brief Return a reference to the total concentration at equilibrium vector
     Vector& total_concentrations() {return m_total_concentrations; }
 
     // Initial total concentrations
     // ----------------------------
 
     //! \brief Return the total concentration (at equilibrium) of 'component'
     scalar_t total_concentration_initial(index_t component) const {
         return m_total_concentrations_initial(component);}
     //! \brief Return a const reference to the total concentration (at equilibrium) vector
     const Vector& total_concentrations_initial() const {return m_total_concentrations_initial;}
     //! \brief Return a reference to the total concentration at equilibrium vector
     Vector& total_concentrations_initial() {return m_total_concentrations_initial; }
 
     // Rates
     // -----
 
     //! \brief Return the value of the flux for 'component'
     scalar_t rate_component(index_t component) const {
         return m_rate(component);
     }
     //! \brief Return a const reference to the flux vector
     const Vector& rate_components() const {return m_rate;}
     //! \brief Return a reference to the flux vector
     Vector& rate_components() {return m_rate;}
     //! \brief reset the rates
     void reset_rate() {m_rate.setZero();}
 
     // Equilibrium
     // ------------
 
     //! \brief Const Reference to the equilibrium state
     const AdimensionalSystemSolution& equilibrium_solution() const {return m_equilibrium_solution;}
     //! \brief Reference to the equilibrium State
     AdimensionalSystemSolution& equilibrium_solution() {return m_equilibrium_solution;}
     //! \brief Update the equilibrium state
     void update_equilibrium_solution(const AdimensionalSystemSolution& other) {m_equilibrium_solution = other;}
 private:
     Vector m_mineral_kinetics;             //!< Number of moles of minerals at equilibrium
     Vector m_total_concentrations_initial; //!< Initial total concentrations at equilibrium
     Vector m_total_concentrations;         //!< total concentration at equilibrium,
     Vector m_rate;
     AdimensionalSystemSolution m_equilibrium_solution;        //!< Current equilibrium state
 };
 
 } // end namespace kinetics
 } // end namespace specmicp
 
 #endif //  SPECMICP_SPECMICP_KINETICS_KINETICVARIABLES_HPP
diff --git a/src/specmicp/problem_solver/dissolver.cpp b/src/specmicp/problem_solver/dissolver.cpp
index fe12b8d..36ad73b 100644
--- a/src/specmicp/problem_solver/dissolver.cpp
+++ b/src/specmicp/problem_solver/dissolver.cpp
@@ -1,142 +1,171 @@
+/*-------------------------------------------------------
+
+Copyright (c) 2014,2015 Fabien Georget <fabieng@princeton.edu>, Princeton University
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+    * Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+    * Redistributions in binary form must reproduce the above copyright
+      notice, this list of conditions and the following disclaimer in the
+      documentation and/or other materials provided with the distribution.
+    * Neither the name of the Princeton University nor the
+      names of its contributors may be used to endorse or promote products
+      derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+---------------------------------------------------------*/
+
 #include "dissolver.hpp"
 
 #include "formulation.hpp"
 #include "database/database.hpp"
 
 namespace specmicp {
 
 Vector Dissolver::dissolve(const Formulation& the_problem)
 {
     m_components_to_keep[0] = true;
     m_components_to_keep[1] = true;
     for (index_t component: m_database->range_aqueous_component())
     {
         m_components_to_keep[component] = false;
     }
     m_total_concentration.setZero();
 
     set_solvent(the_problem.mass_solution);
     for (auto it=the_problem.concentration_aqueous.begin(); it!=the_problem.concentration_aqueous.end(); ++it)
     {
         dissolve_aqueous(it->first, it->second, the_problem.mass_solution);
     }
     for (auto it=the_problem.amount_minerals.begin(); it!=the_problem.amount_minerals.end(); ++it)
     {
         dissolve_mineral(it->first, it->second);
     }
     keep_extra_components(the_problem.extra_components_to_keep);
     reduce_problem();
 
     // Remove minerals if needed
     if (the_problem.minerals_to_keep.size() > 0)
     {
         database::Database(m_database).minerals_keep_only(the_problem.minerals_to_keep);
     }
 
     return m_total_concentration;
 }
 
 
 void Dissolver::set_solvent(scalar_t amount)
 {
     index_t idw = m_database->water_index();
     specmicp_assert(idw != no_species and idw == 0);
     m_total_concentration(0) += amount/m_database->molar_mass_basis(idw, mass_unit());
     m_components_to_keep[0] = true;
 }
 
 void Dissolver::dissolve_aqueous(std::string label, scalar_t concentration, scalar_t mass_solution)
 {
     index_t idaq = m_database->get_id_component(label);
     if (idaq != no_species)
     {
         m_total_concentration(idaq) += mass_solution*concentration;
         m_components_to_keep[idaq] = true;
     }
     else
     {
         index_t idsaq = m_database->get_id_aqueous(label);
         if (idsaq == no_species)
         {
             throw std::invalid_argument("Unknown species : " + label + ".");
         }
         for (index_t component: m_database->range_component())
         {
             if (m_database->nu_aqueous(idsaq, component) == 0.0) continue;
             m_total_concentration(component) +=
                     m_database->nu_aqueous(idsaq, component)*mass_solution*concentration;
             m_components_to_keep[component] = true;
         }
     }
 }
 
 void Dissolver::dissolve_mineral(std::string label, scalar_t amount)
 {
     index_t id_mineral = m_database->get_id_mineral(label);
     if (id_mineral != no_species)
     {
         for (index_t component: m_database->range_component())
         {
             if (m_database->nu_mineral(id_mineral, component) == 0.0) continue;
             m_total_concentration(component) +=
                     m_database->nu_mineral(id_mineral, component)*amount;
             m_components_to_keep[component] = true;
         }
     }
     else
     {
         index_t id_minkin = m_database->get_id_mineral_kinetic(label);
         if (id_minkin == no_species)
         {
             throw std::invalid_argument("Unknown mineral : " + label + ".");
         }
         for (index_t component: m_database->range_component())
         {
             if (m_database->nu_mineral_kinetic(id_minkin, component) == 0.0) continue;
             m_total_concentration(component) +=
                     m_database->nu_mineral_kinetic(id_minkin, component)*amount;
             m_components_to_keep[component] = true;
         }
     }
 }
 
 void Dissolver::keep_extra_components(const std::vector<std::string>& list_component_to_keep)
 {
     for (auto it:list_component_to_keep)
     {
         index_t idc = m_database->get_id_component(it);
         if (idc == no_species)
         {
             throw std::invalid_argument("Species '" + it + "' is not a component");
         }
         m_components_to_keep[idc] = true;
     }
 }
 
 void Dissolver::reduce_problem()
 {
     std::vector<index_t> to_remove;
     to_remove.reserve(m_database->nb_component());
     index_t new_id = 0;
     Vector reduced_tot_conc(m_database->nb_component());
     // Copy information
     for (index_t component: m_database->range_component())
     {
         if (m_components_to_keep[component])
         {
             reduced_tot_conc(new_id) = m_total_concentration(component);
             ++new_id;
         }
         else
         {
             to_remove.push_back(component);
         }
     }
     // Remove components from database
     database::Database(m_database).remove_components(to_remove);
     // Resize total concentrations
     reduced_tot_conc.conservativeResize(m_database->nb_component());
     m_total_concentration = reduced_tot_conc;
 }
 
 } // end namespace specmicp
diff --git a/src/specmicp/problem_solver/dissolver.hpp b/src/specmicp/problem_solver/dissolver.hpp
index 94c98d5..94c06ec 100644
--- a/src/specmicp/problem_solver/dissolver.hpp
+++ b/src/specmicp/problem_solver/dissolver.hpp
@@ -1,52 +1,81 @@
+/*-------------------------------------------------------
+
+Copyright (c) 2014,2015 Fabien Georget <fabieng@princeton.edu>, Princeton University
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+    * Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+    * Redistributions in binary form must reproduce the above copyright
+      notice, this list of conditions and the following disclaimer in the
+      documentation and/or other materials provided with the distribution.
+    * Neither the name of the Princeton University nor the
+      names of its contributors may be used to endorse or promote products
+      derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+---------------------------------------------------------*/
+
 #ifndef SPECMICP_SPECMICP_PROBLEMSOLVER_DISSOLVER_HPP
 #define SPECMICP_SPECMICP_PROBLEMSOLVER_DISSOLVER_HPP
 
 #include "common.hpp"
 #include "database.hpp"
 #include "physics/units.hpp"
 
 namespace specmicp {
 
 class Formulation;
 
 //! \brief Return the total concentration of a given formulation
 class Dissolver: public units::UnitBaseClass
 {
 public:
 
     Dissolver(RawDatabasePtr the_database):
       m_database(the_database),
       m_total_concentration(the_database->nb_component()),
       m_components_to_keep(the_database->nb_component())
     {
         m_total_concentration.setZero();
     }
 
     //! \brief Dissolve the problem into the components
     //!
     //! Also simplify the database
     Vector dissolve(const Formulation& the_problem);
 
     //! \brief Return the total concentration vector
     Vector get_total_concentration() {return m_total_concentration;}
 
 private:
 
     void set_solvent(scalar_t amount);
     void dissolve_aqueous(std::string label, scalar_t concentration, scalar_t mass_solution);
     void dissolve_mineral(std::string label, scalar_t amount);
     void keep_extra_components(const std::vector<std::string>& list_component_to_keep);
     void reduce_problem();
 
 
 private:
 
     RawDatabasePtr m_database;
     Vector m_total_concentration;
     std::vector<bool> m_components_to_keep;
 
 };
 
 } // end namespace specmicp
 
 #endif //SPECMICP_SPECMICP_PROBLEMSOLVER_DISSOLVER_HPP
diff --git a/src/specmicp/problem_solver/formulation.hpp b/src/specmicp/problem_solver/formulation.hpp
index b2c2d04..9b260d2 100644
--- a/src/specmicp/problem_solver/formulation.hpp
+++ b/src/specmicp/problem_solver/formulation.hpp
@@ -1,34 +1,63 @@
+/*-------------------------------------------------------
+
+Copyright (c) 2014,2015 Fabien Georget <fabieng@princeton.edu>, Princeton University
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+    * Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+    * Redistributions in binary form must reproduce the above copyright
+      notice, this list of conditions and the following disclaimer in the
+      documentation and/or other materials provided with the distribution.
+    * Neither the name of the Princeton University nor the
+      names of its contributors may be used to endorse or promote products
+      derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+---------------------------------------------------------*/
+
 #ifndef SPECMICP_SPECMICP_PROBLEMSOLVER_FORMULATION_HPP
 #define SPECMICP_SPECMICP_PROBLEMSOLVER_FORMULATION_HPP
 
 #include "common.hpp"
 #include <map>
 #include <vector>
 #include <string>
 
 namespace specmicp {
 
 struct Formulation
 {
     //! \brief Mass of the solvent
     scalar_t mass_solution;
     //! \brief Contains the amount of each solid phase
     std::map<std::string, scalar_t> concentration_aqueous;
     //! \brief Contains the amount of each solid phase
     //!  included in the problem
     std::map<std::string, scalar_t> amount_minerals;
 
     //! \brief Extra component to leave in the database
     //!
     //! All components not present in this list and with
     //! a total concentration of zero will be removed.
     std::vector<std::string> extra_components_to_keep;
     //! \brief List of solid phase at equilibrium to keep in the computation
     //!
     //! Leave empty to keep all solid phases present in the database
     std::vector<std::string> minerals_to_keep;
 };
 
 } // end namespace specmicp
 
 #endif // SPECMICP_SPECMICP_PROBLEMSOLVER_FORMULATION_HPP
diff --git a/src/utils/io/meshes.hpp b/src/utils/io/meshes.hpp
index 4791c4a..0f71668 100644
--- a/src/utils/io/meshes.hpp
+++ b/src/utils/io/meshes.hpp
@@ -1,34 +1,63 @@
+/*-------------------------------------------------------
+
+Copyright (c) 2014,2015 Fabien Georget <fabieng@princeton.edu>, Princeton University
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+    * Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+    * Redistributions in binary form must reproduce the above copyright
+      notice, this list of conditions and the following disclaimer in the
+      documentation and/or other materials provided with the distribution.
+    * Neither the name of the Princeton University nor the
+      names of its contributors may be used to endorse or promote products
+      derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+---------------------------------------------------------*/
+
 #ifndef SPECMICP_IO_MESHES_HPP
 #define SPECMICP_IO_MESHES_HPP
 
 #include <iostream>
 #include <fstream>
 #include "dfpm/meshes/mesh1d.hpp"
 #include "physics/units.hpp"
 #include "utils/io/units.hpp"
 
 namespace specmicp {
 namespace io {
 
 inline void print_mesh(std::ostream* output, mesh::Mesh1DPtr the_mesh, units::LengthUnit lenght_unit)
 {
     (*output) << "# dfpm mesh \n";
     (*output) << "# units : " << length_unit_to_string(lenght_unit) << "\n";
     (*output) << "Node\tDistance\tCell_volume" << std::endl;
     for (index_t node: the_mesh->range_nodes())
     {
         (*output) << node << "\t" << the_mesh->get_position(node) << "\t" << the_mesh->get_volume_cell(node) << "\n";
     }
 }
 
 inline void print_mesh(std::string filepath, mesh::Mesh1DPtr the_mesh, units::LengthUnit lenght_unit)
 {
     std::ofstream outfile(filepath);
     print_mesh(&outfile, the_mesh, lenght_unit);
     outfile.close();
 }
 
 } // end namespace io
 } // end namespace specmicp
 
 #endif // SPECMICP_IO_MESHES_HPP
diff --git a/src/utils/io/reactive_transport.hpp b/src/utils/io/reactive_transport.hpp
index 236856e..f9441e9 100644
--- a/src/utils/io/reactive_transport.hpp
+++ b/src/utils/io/reactive_transport.hpp
@@ -1,161 +1,190 @@
+/*-------------------------------------------------------
+
+Copyright (c) 2014,2015 Fabien Georget <fabieng@princeton.edu>, Princeton University
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+    * Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+    * Redistributions in binary form must reproduce the above copyright
+      notice, this list of conditions and the following disclaimer in the
+      documentation and/or other materials provided with the distribution.
+    * Neither the name of the Princeton University nor the
+      names of its contributors may be used to endorse or promote products
+      derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+---------------------------------------------------------*/
+
 #ifndef SPECMICP_IO_REACTMICP_HPP
 #define SPECMICP_IO_REACTMICP_HPP
 
 #include <iostream>
 
 #include "reactmicp/solver/reactive_transport_solver_structs.hpp"
 #include "utils/timer.hpp"
 
 
 namespace specmicp {
 namespace io {
 
 //! \brief Print the header
 inline void print_reactmicp_header(
         std::ostream* output
         );
 
 //! \brief Print the performance information of the reactive transport solver
 inline void print_reactmicp_performance_short(
         std::ostream* output,
         const reactmicp::solver::ReactiveTransportPerformance& perf
         );
 
 //! \brief Print the timing information of the reactive transport solver
 inline void print_reactmicp_timer(
         std::ostream* output,
         const reactmicp::solver::ReactiveTransportTimer& timer
         );
 
 //! \brief Return a literal version of a ReactiveTransportReturnCode
 inline std::string reactmicp_return_code_to_string(
         reactmicp::solver::ReactiveTransportReturnCode retcode);
 
 
 
 inline void print_reactmicp_header(
         std::ostream* output
         )
 {
     (*output) << "//  ================================== //\n"
               << "//                                     //\n"
               << "//           ReactMiCP                 //\n"
               << "//                                     //\n"
               << "// ==================================  //\n\n"
               << "A reactive transport solver based on SpecMiCP.\n"
               << "------------------------------------------- \n"
               << std::endl;
 }
 
 inline void print_reactmicp_performance_short(
         std::ostream* output,
         const reactmicp::solver::ReactiveTransportPerformance& perf
         )
 {
     (*output) << "------------------------------------------- \n"
               << " Performance \n "
               << "------------------------------------------- \n\t"
               << " - Return code : " << reactmicp_return_code_to_string(perf.return_code) << "\n\t"
               << " - Residuals : " << perf.residuals << "\n\t"
               << " - Number of iterations : " << perf.nb_iterations << "\n"
               << "------------------------------------------- " << std::endl;
 }
 
 inline void print_reactmicp_timer(
         std::ostream* output,
         const reactmicp::solver::ReactiveTransportTimer& timer
         )
 {
     (*output) << "------------------------------------------- \n"
               << "Time spent in each stagger \n"
               << "------------------------------------------- \n\t"
               << "- Transport : " << timer.transport_time << " s\n\t"
               << "- Chemistry : " << timer.chemistry_time << " s\n\t"
               << "- Upscaling : " << timer.upscaling_time << " s\n"
               << "-----------------------------------------" << std::endl;
 }
 
 inline void print_reactmicp_end(
         std::ostream* output,
         const Timer& total_timer,
         const reactmicp::solver::ReactiveTransportTimer& timer
         )
 {
     scalar_t elapsed_s = total_timer.elapsed_time();
     index_t hours =  static_cast<index_t>(elapsed_s) / 3600;
     index_t elapsed_minutes = elapsed_s - hours*3600;
     index_t minute = elapsed_minutes / 60;
     index_t seconds = elapsed_minutes - 60*minute;
 
     (*output) << " ====================================================== \n";
     (*output) << "computation finished at "
               << total_timer.get_ctime_stop();
     (*output) << " Duration of the computation : " << total_timer.elapsed_time() << " s"
               << "( " << hours << "h " << minute << "min " << seconds << "s )\n";
     print_reactmicp_timer(output, timer);
 }
 
 inline void print_reactmicp_performance_long_header(
         std::ostream* output
         )
 {
     (*output) << "Id\t T\t dt\t Return_code\t Iterations \t Residuals\t Time\t Transport_time\t Chemistry_time"
               << std::endl;
 
 }
 
 inline void print_reactmicp_performance_long(
         std::ostream* output,
         index_t cnt,
         scalar_t total,
         const reactmicp::solver::ReactiveTransportPerformance& perfs
         )
 {
     (*output) << cnt << "\t "
               << total << "\t "
               << perfs.timestep << "\t "
               << (int) perfs.return_code << "\t "
               << perfs.nb_iterations << "\t "
               << perfs.residuals << "\t "
               << perfs.total_time << "\t"
               << perfs.transport_time << "\t"
               << perfs.chemistry_time
               << std::endl;
 }
 
 inline std::string reactmicp_return_code_to_string(
         reactmicp::solver::ReactiveTransportReturnCode retcode)
 {
     using RetCode = reactmicp::solver::ReactiveTransportReturnCode;
     switch (retcode) {
     case RetCode::ResidualMinimized:
         return "ResidualMinimized";
     case RetCode::ErrorMinimized:
         return "ErrorMinimized";
     default:
         switch (retcode) {
         case RetCode::StationaryPoint:
             return "StationaryPoint";
         case RetCode::MaximumIterationsReached:
             return "MaximumIterationsReached";
         case RetCode::GoodEnough:
             return "Good enough...";
         case RetCode::TransportBypass:
             return "Transport Bypass";
         case RetCode::TransportFailure:
             return "TransportFailure";
         case RetCode::ChemistryFailure:
             return "ChemistryFailure";
         case RetCode::UpscalingFailure:
             return "UpscalingFailure";
         default:
             return "Unknow error code !";
         }
     }
 }
 
 } // end namespace io
 } // end namespace specmicp
 
 
 #endif // SPECMICP_IO_REACTMICP_HPP
diff --git a/src/utils/io/saturated_react.hpp b/src/utils/io/saturated_react.hpp
index a9b93e5..4c0020d 100644
--- a/src/utils/io/saturated_react.hpp
+++ b/src/utils/io/saturated_react.hpp
@@ -1,168 +1,197 @@
+/*-------------------------------------------------------
+
+Copyright (c) 2014,2015 Fabien Georget <fabieng@princeton.edu>, Princeton University
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+    * Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+    * Redistributions in binary form must reproduce the above copyright
+      notice, this list of conditions and the following disclaimer in the
+      documentation and/or other materials provided with the distribution.
+    * Neither the name of the Princeton University nor the
+      names of its contributors may be used to endorse or promote products
+      derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+---------------------------------------------------------*/
+
 #ifndef SPECMICP_IO_SATURATEDREACT_HPP
 #define SPECMICP_IO_SATURATEDREACT_HPP
 
 #include <iostream>
 #include <fstream>
 
 #include "utils/io/units.hpp"
 
 //#include "reactmicp/systems/saturated_react/variablesfwd.hpp"
 #include "reactmicp/systems/saturated_react/variables.hpp"
 #include <chrono>
 #include <ctime>
 
 using namespace specmicp::reactmicp::systems::satdiff;
 
 namespace specmicp {
 namespace io {
 
 static constexpr char field_sep = '\t';
 static constexpr char comment = '#';
 
 void print_csv_header(std::ostream* ofile)
 {
     std::time_t time = std::chrono::system_clock::to_time_t(std::chrono::system_clock::now());
     (*ofile) << comment << " - ReactMiCP - " << std::ctime(&time);
 }
 
 void print_components_total_aqueous_concentration(
         RawDatabasePtr the_database,
         SaturatedVariablesPtr variables,
         mesh::Mesh1DPtr the_mesh,
         const units::UnitsSet& units_set,
         std::ostream* ofile
         )
 {
     print_csv_header(ofile);
     (*ofile) << comment << "units : mol/"  << io::volume_unit_to_string(units_set.length) << std::endl;
     (*ofile) << "Position";
     for (index_t component: the_database->range_aqueous_component())
     {
         (*ofile) << field_sep << the_database->get_label_component(component);
     }
     (*ofile) << std::endl;
 
     for (index_t node: the_mesh->range_nodes())
     {
         (*ofile) << the_mesh->get_position(node);
 
         for (index_t component: the_database->range_aqueous_component())
         {
             (*ofile) << field_sep << variables->aqueous_concentration(node, component);
         }
         (*ofile) << std::endl;
     }
 }
 
 void print_components_total_aqueous_concentration(
         RawDatabasePtr the_database,
         SaturatedVariablesPtr variables,
         mesh::Mesh1DPtr the_mesh,
         const units::UnitsSet& units_set,
         const std::string& filepath
         )
 {
     std::ofstream ofile(filepath);
     print_components_total_aqueous_concentration(the_database, variables, the_mesh, units_set, &ofile);
     ofile.close();
 }
 
 void print_components_total_solid_concentration(
         RawDatabasePtr the_database,
         SaturatedVariablesPtr variables,
         mesh::Mesh1DPtr the_mesh,
         const units::UnitsSet& units_set,
         std::ostream* ofile
         )
 {
     print_csv_header(ofile);
     (*ofile) << comment << "units : mol/"  << io::volume_unit_to_string(units_set.length) << std::endl;
     (*ofile) << "Position";
     for (index_t component: the_database->range_aqueous_component())
     {
         (*ofile) << field_sep << the_database->get_label_component(component);
     }
     (*ofile) << std::endl;
 
     for (index_t node: the_mesh->range_nodes())
     {
         (*ofile) << the_mesh->get_position(node);
 
         for (index_t component: the_database->range_aqueous_component())
         {
             (*ofile) << field_sep << variables->solid_concentration(node, component);
         }
         (*ofile) << std::endl;
     }
 }
 
 void print_components_total_solid_concentration(
         RawDatabasePtr the_database,
         SaturatedVariablesPtr variables,
         mesh::Mesh1DPtr the_mesh,
         const units::UnitsSet& units_set,
         const std::string& filepath
         )
 {
     std::ofstream ofile(filepath);
     print_components_total_solid_concentration(the_database, variables, the_mesh, units_set, &ofile);
     ofile.close();
 }
 
 void print_minerals_profile(
         RawDatabasePtr the_database,
         SaturatedVariablesPtr variables,
         mesh::Mesh1DPtr the_mesh,
         std::ostream* ofile
         )
 {
     print_csv_header(ofile);
     (*ofile) << "Position";
     for (index_t mineral: the_database->range_mineral())
     {
         (*ofile) << field_sep << the_database->get_label_mineral(mineral);
     }
     (*ofile) << field_sep << "Porosity";
     (*ofile) << field_sep << "pH";
     (*ofile) << std::endl;
 
     for (index_t node: the_mesh->range_nodes())
     {
         (*ofile) << the_mesh->get_position(node);
         AdimensionalSystemSolutionExtractor extractor(variables->equilibrium_solution(node), the_database, units::UnitsSet());
 
         for (index_t mineral: the_database->range_mineral())
         {
             (*ofile) << field_sep << extractor.volume_fraction_mineral(mineral);
         }
         (*ofile) << field_sep << variables->porosity(node);
         (*ofile) << field_sep << extractor.pH();
         (*ofile) << std::endl;
 
     }
 
 }
 
 void print_minerals_profile(
         RawDatabasePtr the_database,
         SaturatedVariablesPtr variables,
         mesh::Mesh1DPtr the_mesh,
         const std::string& filepath
         )
 {
     std::ofstream ofile(filepath);
     print_minerals_profile(
             the_database,
             variables,
             the_mesh,
             &ofile
             );
     ofile.close();
 }
 
 
 
 } // end namespace io
 } // end namespace specmicp
 
 #endif // SPECMICP_IO_SATURATEDREACT_HPP
diff --git a/src/utils/io/units.hpp b/src/utils/io/units.hpp
index d691b3d..3c98580 100644
--- a/src/utils/io/units.hpp
+++ b/src/utils/io/units.hpp
@@ -1,34 +1,63 @@
 #ifndef SPECMICP_IO_UNITS_HPP
 #define SPECMICP_IO_UNITS_HPP
 
 #include <string>
+/*-------------------------------------------------------
+
+Copyright (c) 2014,2015 Fabien Georget <fabieng@princeton.edu>, Princeton University
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+    * Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+    * Redistributions in binary form must reproduce the above copyright
+      notice, this list of conditions and the following disclaimer in the
+      documentation and/or other materials provided with the distribution.
+    * Neither the name of the Princeton University nor the
+      names of its contributors may be used to endorse or promote products
+      derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+---------------------------------------------------------*/
+
 #include "physics/units.hpp"
 
 namespace specmicp {
 namespace io {
 
 std::string length_unit_to_string(units::LengthUnit length_u)
 {
     switch (length_u) {
     case units::LengthUnit::meter:
         return "m";
         break;
     case units::LengthUnit::decimeter:
         return "dm";
         break;
     case units::LengthUnit::centimeter:
         return "cm";
         break;
     }
 }
 
 std::string volume_unit_to_string(units::LengthUnit length_u)
 {
     return length_unit_to_string(length_u) + "^3";
 }
 
 
 } // end namespace io
 } // end namespace specmicp
 
 #endif // SPECMICP_IO_UNITS_HPP
diff --git a/src/utils/log.hpp b/src/utils/log.hpp
index b6bef3d..24acfec 100644
--- a/src/utils/log.hpp
+++ b/src/utils/log.hpp
@@ -1,164 +1,160 @@
 /*-------------------------------------------------------
 
- - Module : utils
- - File : log.hpp
- - Author : Fabien Georget
-
-Copyright (c) 2014, Fabien Georget <fabieng@princeton.edu>, Princeton University
+Copyright (c) 2014,2015 Fabien Georget <fabieng@princeton.edu>, Princeton University
 All rights reserved.
 
 Redistribution and use in source and binary forms, with or without
 modification, are permitted provided that the following conditions are met:
     * Redistributions of source code must retain the above copyright
       notice, this list of conditions and the following disclaimer.
     * Redistributions in binary form must reproduce the above copyright
       notice, this list of conditions and the following disclaimer in the
       documentation and/or other materials provided with the distribution.
     * Neither the name of the Princeton University nor the
       names of its contributors may be used to endorse or promote products
       derived from this software without specific prior written permission.
 
 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
 ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 ---------------------------------------------------------*/
 
 #ifndef SPECMICP_UTILS_LOG_HPP
 #define SPECMICP_UTILS_LOG_HPP
 
 #include <sstream>
 
 //! \file log.hpp logger
 
 namespace specmicp {
 namespace logger {
 //! \enum LogLevel the different log level
 //!
 //!  If changed, the function to_string must also be changed
 enum LogLevel {Critical, //!< Error that should lead to abortion
                Error,    //!< Error
                Warning,  //!< Warnings
                Info,     //!< May be worth mentionning, not worth listening...
                Debug,    //!< (Relevant) Debugging information
                Spam      //!< How is your life ? ususally contains large debugging information such as the variables vector
               };
 
 //!  \brief Format the log level into a string
 inline std::string to_string(LogLevel);
 
 /*! \brief A log message
  *
  *  The message is written during the destruction of the Log object.
  *  The stream which contain the message is accessed with the member get(Level)
  */
 template <typename outputPolicy>
 class Log
 {
 public:
     //! Constructor
     Log() {}
     //! Destructor - Output the message
     ~Log();
 
     //! \brief Return the steam so we can write the message
     std::ostringstream& get(LogLevel level);
 
     //! \brief Return the report level
     static LogLevel& ReportLevel(){
         static LogLevel report_level = Debug;
         return report_level;
     }
 protected:
     std::ostringstream msg; //!< the actual message
 private:
     // this are hidden on purpose, no need
     Log(Log&);
     Log& operator=(Log&);
 };
 
 template <typename outputPolicy>
 std::ostringstream& Log<outputPolicy>::get(LogLevel level)
 {
     msg << to_string(level) << " : ";
     return msg;
 }
 
 template <typename outputPolicy>
 Log<outputPolicy>::~Log()
 {
     outputPolicy::output(msg.str());
 }
 
 //! \brief Output Policy to use for logging
 class ErrFile
 {
 public:
     //! \brief Return a pointer to the stream we want to write in
     static std::ostream*& stream();
     //! \brief Output the message to the stream
     static void output(const std::string& msg);
 };
 
 inline std::ostream*& ErrFile::stream()
 {
     static std::ostream* stream = nullptr;
     return stream;
 }
 
 inline void ErrFile::output(const std::string &msg)
 {
     std::ostream* out = stream();
     (*out) << msg << std::endl;
     out->flush();
 }
 
 
 inline std::string to_string(LogLevel level)
 {
     static const char* list_level[] = {"CRITICAL", "ERROR", "Warning", "info", "debug", "spam"};
     return list_level[static_cast<int>(level)];
 }
 
 
 } // end namespace logger
 
 //! \brief Standard logger type
 using stdlog = logger::Log<logger::ErrFile>;
 
 //! \brief Filter logs to stdlog
 #define FILTER(level) \
     if (level >  stdlog::ReportLevel() || logger::ErrFile::stream() == nullptr) ;\
     else stdlog().get(level)
 
 //! \brief Spam log to stdlog
 #define SPAM FILTER(logger::Spam)
 
 //! \brief Debug log to stdlog
 #define DEBUG FILTER(logger::Debug)
 
 //! \brief Info log to stdlog
 #ifdef INFO
 #undef INFO
 #endif
 #define INFO FILTER(logger::Info)
 
 //! \brief Warning log to stdlog
 #define WARNING FILTER(logger::Warning)
 
 //! \brief Error log to stdlog
 #define ERROR FILTER(logger::Error)
 
 //! \brief Critical log to stdlog
 #define CRITICAL FILTER(logger::Critical)
 
 } // end namespace specmicp
 
 #endif // SPECMICP_UTILS_LOG_HPP
diff --git a/src/utils/moving_average.hpp b/src/utils/moving_average.hpp
index fe4d337..8c4fbdd 100644
--- a/src/utils/moving_average.hpp
+++ b/src/utils/moving_average.hpp
@@ -1,51 +1,80 @@
+/*-------------------------------------------------------
+
+Copyright (c) 2014,2015 Fabien Georget <fabieng@princeton.edu>, Princeton University
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+    * Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+    * Redistributions in binary form must reproduce the above copyright
+      notice, this list of conditions and the following disclaimer in the
+      documentation and/or other materials provided with the distribution.
+    * Neither the name of the Princeton University nor the
+      names of its contributors may be used to endorse or promote products
+      derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+---------------------------------------------------------*/
+
 #ifndef SPECMICP_UTILS_MOVINGAVERAGE_HPP
 #define SPECMICP_UTILS_MOVINGAVERAGE_HPP
 
 #include "common.hpp"
 
 namespace specmicp {
 namespace utils {
 
 //! \brief Exponential moving average
 //!
 //! https://en.wikipedia.org/wiki/Moving_average#Exponential_moving_average
 //!
 //! @param alpha coefficient between 0 and 1
 //! @param init initial value of the average
 class ExponentialMovingAverage
 {
 public:
     ExponentialMovingAverage(scalar_t alpha, scalar_t init):
         m_alpha(alpha),
         m_current_value(init)
     {
     }
     //! \brief Add a point in the series, return current average value
     scalar_t add_point(scalar_t value){
         m_current_value = m_alpha*value + (1-m_alpha)*m_current_value;
         return m_current_value;
     }
 
     //! \brief Return the current average value
     scalar_t current_value() {
         return m_current_value;
     }
     //! \brief Reset the average to 'value'
     void reset(scalar_t value) {
         m_current_value = value;
     }
 
     //! \brief Set the parameter value
     void set_alpha(scalar_t alpha) {m_alpha = alpha;}
 
 
 private:
     scalar_t m_alpha;
     scalar_t m_current_value;
 };
 
 
 } // end namespace utils
 } // end namespace specmicp
 
 #endif // SPECMICP_UTILS_MOVINGAVERAGE_HPP
diff --git a/src/utils/options_handler.hpp b/src/utils/options_handler.hpp
index bc50046..89e5ce7 100644
--- a/src/utils/options_handler.hpp
+++ b/src/utils/options_handler.hpp
@@ -1,47 +1,76 @@
+/*-------------------------------------------------------
+
+Copyright (c) 2014,2015 Fabien Georget <fabieng@princeton.edu>, Princeton University
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+    * Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+    * Redistributions in binary form must reproduce the above copyright
+      notice, this list of conditions and the following disclaimer in the
+      documentation and/or other materials provided with the distribution.
+    * Neither the name of the Princeton University nor the
+      names of its contributors may be used to endorse or promote products
+      derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+---------------------------------------------------------*/
+
 #ifndef SPECMICP_UTILS_OPTIONSHANDLER_HPP
 #define SPECMICP_UTILS_OPTIONSHANDLER_HPP
 
 namespace specmicp {
 
 //! \brief Class that handles the options
 template <class OptionsClass>
 class OptionsHandler
 {
 public:
     //! \brief Initializa with the default options
     OptionsHandler() {}
 
     //! \brief Initialise the options class using the arguments provided
     template <typename... Args>
     OptionsHandler(Args... args):
         m_options(args...)
     {}
 
     //! \brief Initialize with given options
     OptionsHandler(const OptionsClass& options):
         m_options(options)
     {}
 
     //! \brief Return a reference to the options
     OptionsClass& get_options() {return m_options;}
     //! \brief Return a const reference to the options
     const OptionsClass& get_options() const {return m_options;}
 
     //! \brief Set the options
     void set_options(const OptionsClass& options) {m_options = options;}
 
     //! \brief Swap the options with another set
     //!
     //! May be useful for temporary change
     void swap(OptionsClass& options) {std::swap(m_options, options);}
 
     //! \brief Reset to default options
     void reset_to_default() {m_options = OptionsClass();}
 
 private:
     OptionsClass m_options; //!< The options
 };
 
 } // end namespace specmicp
 
 #endif // SPECMICP_UTILS_OPTIONSHANDLER_HPP
diff --git a/src/utils/perfs_handler.hpp b/src/utils/perfs_handler.hpp
index 846ce81..0abb4f3 100644
--- a/src/utils/perfs_handler.hpp
+++ b/src/utils/perfs_handler.hpp
@@ -1,41 +1,60 @@
 /*-------------------------------------------------------
 
- - Module : utils
- - File : perfs_handler.hpp
- - Author : Fabien Georget
-
- Copyright (c) 2014, Fabien Georget, Princeton University
+Copyright (c) 2014,2015 Fabien Georget <fabieng@princeton.edu>, Princeton University
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+    * Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+    * Redistributions in binary form must reproduce the above copyright
+      notice, this list of conditions and the following disclaimer in the
+      documentation and/or other materials provided with the distribution.
+    * Neither the name of the Princeton University nor the
+      names of its contributors may be used to endorse or promote products
+      derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 ---------------------------------------------------------*/
 
 #ifndef SPECMICP_UTILS_PERFSHANDLER_HPP
 #define SPECMICP_UTILS_PERFSHANDLER_HPP
 
 namespace specmicp {
 
 //! \brief Handle a performance struct for the algorithms
 //!
 //! Like options handler but for the performance
 template <class PerformanceStruct>
 class PerformanceHandler
 {
 public:
     //! \brief Return the performance (read-only)
     const PerformanceStruct& get_perfs() const {return m_perfs;}
 
     //! \brief Reset the performance
     void reset_perfs() {m_perfs = PerformanceStruct();}
 
     //! \brief Return a reference to the performance
     PerformanceStruct& get_perfs() {return m_perfs;}
 
 protected:
     //! \brief Swap the performance with another
     void swap(PerformanceStruct& other) {std::swap(m_perfs, other);}
 private:
     PerformanceStruct m_perfs;
 };
 
 } // end namespace specmicp
 
 #endif // SPECMICP_UTILS_PERFSHANDLER_HPP
diff --git a/src/utils/sparse_solvers/sparse_bicgstab.hpp b/src/utils/sparse_solvers/sparse_bicgstab.hpp
index 993ff64..0e6689c 100644
--- a/src/utils/sparse_solvers/sparse_bicgstab.hpp
+++ b/src/utils/sparse_solvers/sparse_bicgstab.hpp
@@ -1,69 +1,98 @@
+/*-------------------------------------------------------
+
+Copyright (c) 2014,2015 Fabien Georget <fabieng@princeton.edu>, Princeton University
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+    * Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+    * Redistributions in binary form must reproduce the above copyright
+      notice, this list of conditions and the following disclaimer in the
+      documentation and/or other materials provided with the distribution.
+    * Neither the name of the Princeton University nor the
+      names of its contributors may be used to endorse or promote products
+      derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+---------------------------------------------------------*/
+
 #ifndef SPECMICP_SPARSESOLVERS_SPARSEBICGSTAB_HPP
 #define SPECMICP_SPARSESOLVERS_SPARSEBICGSTAB_HPP
 
 #include "sparse_solver_structs.hpp"
 #include "sparse_solver_base.hpp"
 
 #include <Eigen/IterativeLinearSolvers>
 
 namespace specmicp {
 namespace sparse_solvers {
 
 template <class MatrixT, class DerivedR, class DerivedS>
 class SparseSolverBiCGSTAB: public SparseSolverBase<MatrixT, DerivedR, DerivedS>
 {
     using SolverT = Eigen::BiCGSTAB<MatrixT, Eigen::IncompleteLUT<typename MatrixT::Scalar>>;
 
 public:
     void analyse_pattern(MatrixT& jacobian)
     {
         m_solver.analyzePattern(jacobian);
     }
 
     //! \brief Decompose the jacboian
     SparseSolverReturnCode decompose(MatrixT& jacobian)
     {
         m_solver.compute(jacobian);
         if (m_solver.info() != Eigen::Success)
         {
             return SparseSolverReturnCode::FailedDecomposition;
         }
         return SparseSolverReturnCode::Success;
     }
 
     //! \brief Solve the problem
     SparseSolverReturnCode solve(
             const DerivedR& residuals,
             DerivedS& solution
             )
     {
         solution = m_solver.solve(-residuals);
         if (m_solver.info() != Eigen::Success)
         {
             return SparseSolverReturnCode::FailedSystemSolving;
         }
         return SparseSolverReturnCode::Success;
     }
 
     SparseSolverReturnCode solve_scaling(
             const DerivedR& residuals,
             const DerivedR& scaling,
             DerivedS& solution
             )
     {
         solution = m_solver.solve(scaling.asDiagonal()*(-residuals));
         if (m_solver.info() != Eigen::Success)
         {
             return SparseSolverReturnCode::FailedSystemSolving;
         }
         return SparseSolverReturnCode::Success;
     }
 
 private:
      SolverT m_solver;
 };
 
 } // end namespace sparse_solvers
 } // end namespace specmicp
 
 #endif //SPECMICP_SPARSESOLVERS_SPARSEBICGSTAB_HPP
diff --git a/src/utils/sparse_solvers/sparse_gmres.hpp b/src/utils/sparse_solvers/sparse_gmres.hpp
index d2a7853..41ed97c 100644
--- a/src/utils/sparse_solvers/sparse_gmres.hpp
+++ b/src/utils/sparse_solvers/sparse_gmres.hpp
@@ -1,71 +1,100 @@
+/*-------------------------------------------------------
+
+Copyright (c) 2014,2015 Fabien Georget <fabieng@princeton.edu>, Princeton University
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+    * Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+    * Redistributions in binary form must reproduce the above copyright
+      notice, this list of conditions and the following disclaimer in the
+      documentation and/or other materials provided with the distribution.
+    * Neither the name of the Princeton University nor the
+      names of its contributors may be used to endorse or promote products
+      derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+---------------------------------------------------------*/
+
 #ifndef SPECMICP_SPARSESOLVERS_SPARSEGMRES_HPP
 #define SPECMICP_SPARSESOLVERS_SPARSEGMRES_HPP
 
 #include "sparse_solver_structs.hpp"
 #include "sparse_solver_base.hpp"
 
 // needed for eigen 3.2.2
 #include <iostream>
 
 #include <Eigen/IterativeSolvers>
 
 namespace specmicp {
 namespace sparse_solvers {
 
 template <class MatrixT, class DerivedR, class DerivedS>
 class SparseSolverGMRES: public SparseSolverBase<MatrixT, DerivedR, DerivedS>
 {
     using SolverT = Eigen::GMRES<MatrixT, Eigen::IncompleteLUT<typename MatrixT::Scalar>> ;
 
 public:
     void analyse_pattern(MatrixT& jacobian)
     {
     }
 
     //! \brief Decompose the jacboian
     SparseSolverReturnCode decompose(MatrixT& jacobian)
     {
         m_solver.compute(jacobian);
         if (m_solver.info() != Eigen::Success)
         {
             return SparseSolverReturnCode::FailedDecomposition;
         }
         return SparseSolverReturnCode::Success;
     }
 
     //! \brief Solve the problem
     SparseSolverReturnCode solve(
             const DerivedR& residuals,
             DerivedS& solution
             )
     {
         solution = m_solver.solve(-residuals);
         if (m_solver.info() != Eigen::Success)
         {
             return SparseSolverReturnCode::FailedSystemSolving;
         }
         return SparseSolverReturnCode::Success;
     }
 
     SparseSolverReturnCode solve_scaling(
             const DerivedR& residuals,
             const DerivedR& scaling,
             DerivedS& solution
             )
     {
         solution = m_solver.solve(scaling.asDiagonal()*(-residuals));
         if (m_solver.info() != Eigen::Success)
         {
             return SparseSolverReturnCode::FailedSystemSolving;
         }
         return SparseSolverReturnCode::Success;
     }
 
 private:
      SolverT m_solver;
 };
 
 } // end namespace sparse_solvers
 } // end namespace specmicp
 
 #endif //SPECMICP_SPARSESOLVERS_SPARSEGMRES_HPP
diff --git a/src/utils/sparse_solvers/sparse_lu.hpp b/src/utils/sparse_solvers/sparse_lu.hpp
index 0d5fb76..b79dba4 100644
--- a/src/utils/sparse_solvers/sparse_lu.hpp
+++ b/src/utils/sparse_solvers/sparse_lu.hpp
@@ -1,69 +1,98 @@
+/*-------------------------------------------------------
+
+Copyright (c) 2014,2015 Fabien Georget <fabieng@princeton.edu>, Princeton University
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+    * Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+    * Redistributions in binary form must reproduce the above copyright
+      notice, this list of conditions and the following disclaimer in the
+      documentation and/or other materials provided with the distribution.
+    * Neither the name of the Princeton University nor the
+      names of its contributors may be used to endorse or promote products
+      derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+---------------------------------------------------------*/
+
 #ifndef SPECMICP_SPARSESOLVERS_SPARSELU_HPP
 #define SPECMICP_SPARSESOLVERS_SPARSELU_HPP
 
 #include "sparse_solver_structs.hpp"
 #include "sparse_solver_base.hpp"
 
 #include <Eigen/SparseLU>
 
 namespace specmicp {
 namespace sparse_solvers {
 
 template <class MatrixT, class DerivedR, class DerivedS>
 class SparseSolverLU: public SparseSolverBase<MatrixT, DerivedR, DerivedS>
 {
     using SolverT = Eigen::SparseLU<MatrixT, Eigen::COLAMDOrdering<typename MatrixT::Index>>;
 
 public:
     void analyse_pattern(MatrixT& jacobian)
     {
         m_solver.analyzePattern(jacobian);
     }
 
     //! \brief Decompose the jacboian
     SparseSolverReturnCode decompose(MatrixT& jacobian)
     {
         m_solver.factorize(jacobian);
         if (m_solver.info() != Eigen::Success)
         {
             return SparseSolverReturnCode::FailedDecomposition;
         }
         return SparseSolverReturnCode::Success;
     }
 
     //! \brief Solve the problem
     SparseSolverReturnCode solve(
             const DerivedR& residuals,
             DerivedS& solution
             )
     {
         solution = m_solver.solve(-residuals);
         if (m_solver.info() != Eigen::Success)
         {
             return SparseSolverReturnCode::FailedSystemSolving;
         }
         return SparseSolverReturnCode::Success;
     }
 
     SparseSolverReturnCode solve_scaling(
             const DerivedR& residuals,
             const DerivedR& scaling,
             DerivedS& solution
             )
     {
         solution = m_solver.solve(scaling.asDiagonal()*(-residuals));
         if (m_solver.info() != Eigen::Success)
         {
             return SparseSolverReturnCode::FailedSystemSolving;
         }
         return SparseSolverReturnCode::Success;
     }
 
 private:
      SolverT m_solver;
 };
 
 } // end namespace sparse_solvers
 } // end namespace specmicp
 
 #endif //SPECMICP_SPARSESOLVERS_SPARSELU_HPP
diff --git a/src/utils/sparse_solvers/sparse_qr.hpp b/src/utils/sparse_solvers/sparse_qr.hpp
index 0945bf4..822c5ee 100644
--- a/src/utils/sparse_solvers/sparse_qr.hpp
+++ b/src/utils/sparse_solvers/sparse_qr.hpp
@@ -1,69 +1,98 @@
+/*-------------------------------------------------------
+
+Copyright (c) 2014,2015 Fabien Georget <fabieng@princeton.edu>, Princeton University
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+    * Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+    * Redistributions in binary form must reproduce the above copyright
+      notice, this list of conditions and the following disclaimer in the
+      documentation and/or other materials provided with the distribution.
+    * Neither the name of the Princeton University nor the
+      names of its contributors may be used to endorse or promote products
+      derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+---------------------------------------------------------*/
+
 #ifndef SPECMICP_SPARSESOLVERS_SPARSEQR_HPP
 #define SPECMICP_SPARSESOLVERS_SPARSEQR_HPP
 
 #include "sparse_solver_structs.hpp"
 #include "sparse_solver_base.hpp"
 
 #include <Eigen/SparseQR>
 
 namespace specmicp {
 namespace sparse_solvers {
 
 template <class MatrixT, class DerivedR, class DerivedS>
 class SparseSolverQR: public SparseSolverBase<MatrixT, DerivedR, DerivedS>
 {
     using SolverT = Eigen::SparseQR<MatrixT, Eigen::COLAMDOrdering<int>>;
 
 public:
     void analyse_pattern(MatrixT& jacobian)
     {
         m_solver.analyzePattern(jacobian);
     }
 
     //! \brief Decompose the jacboian
     SparseSolverReturnCode decompose(MatrixT& jacobian)
     {
         m_solver.factorize(jacobian);
         if (m_solver.info() != Eigen::Success)
         {
             return SparseSolverReturnCode::FailedDecomposition;
         }
         return SparseSolverReturnCode::Success;
     }
 
     //! \brief Solve the problem
     SparseSolverReturnCode solve(
             const DerivedR& residuals,
             DerivedS& solution
             )
     {
         solution = m_solver.solve(-residuals);
         if (m_solver.info() != Eigen::Success)
         {
             return SparseSolverReturnCode::FailedSystemSolving;
         }
         return SparseSolverReturnCode::Success;
     }
 
     SparseSolverReturnCode solve_scaling(
             const DerivedR& residuals,
             const DerivedR& scaling,
             DerivedS& solution
             )
     {
         solution = m_solver.solve(scaling.asDiagonal()*(-residuals));
         if (m_solver.info() != Eigen::Success)
         {
             return SparseSolverReturnCode::FailedSystemSolving;
         }
         return SparseSolverReturnCode::Success;
     }
 
 private:
      SolverT m_solver;
 };
 
 } // end namespace sparse_solvers
 } // end namespace specmicp
 
 #endif //SPECMICP_SPARSESOLVERS_SPARSEQR_HPP
diff --git a/src/utils/sparse_solvers/sparse_solver.hpp b/src/utils/sparse_solvers/sparse_solver.hpp
index d9e0580..95aa9f6 100644
--- a/src/utils/sparse_solvers/sparse_solver.hpp
+++ b/src/utils/sparse_solvers/sparse_solver.hpp
@@ -1,49 +1,78 @@
+/*-------------------------------------------------------
+
+Copyright (c) 2014,2015 Fabien Georget <fabieng@princeton.edu>, Princeton University
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+    * Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+    * Redistributions in binary form must reproduce the above copyright
+      notice, this list of conditions and the following disclaimer in the
+      documentation and/or other materials provided with the distribution.
+    * Neither the name of the Princeton University nor the
+      names of its contributors may be used to endorse or promote products
+      derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+---------------------------------------------------------*/
+
 #ifndef SPECMICP_SPARSESOLVERS_SPARSESOLVERS_HPP
 #define SPECMICP_SPARSESOLVERS_SPARSESOLVERS_HPP
 
 #include <memory>
 #include "sparse_qr.hpp"
 #include "sparse_lu.hpp"
 #include "sparse_bicgstab.hpp"
 #ifdef EIGEN_UNSUPPORTED_FOUND
 #include "sparse_gmres.hpp"
 #endif
 
 namespace specmicp {
 namespace sparse_solvers {
 
 template <class MatrixT, class DerivedR, class DerivedS>
 using SparseSolverPtr = std::unique_ptr<SparseSolverBase<MatrixT, DerivedR, DerivedS>>;
 
 template <class MatrixT, class DerivedR, class DerivedS>
 SparseSolverPtr<MatrixT, DerivedR, DerivedS> get_sparse_solver(SparseSolver solver_type)
 {
     SparseSolverPtr<MatrixT, DerivedR, DerivedS> sparse_solver;
     switch (solver_type) {
     case SparseSolver::SparseQR:
         sparse_solver = SparseSolverPtr<MatrixT, DerivedR, DerivedS>(
                     new SparseSolverQR<MatrixT, DerivedR, DerivedS>);
         break;
 #ifdef EIGEN_UNSUPPORTED_FOUND
     case SparseSolver::GMRES:
         sparse_solver = SparseSolverPtr<MatrixT, DerivedR, DerivedS>(
                         new SparseSolverGMRES<MatrixT, DerivedR, DerivedS>);
         break;
 #endif
     case SparseSolver::SparseLU:
         sparse_solver = SparseSolverPtr<MatrixT, DerivedR, DerivedS>(
                         new SparseSolverLU<MatrixT, DerivedR, DerivedS>);
         break;
     case SparseSolver::BiCGSTAB:
         sparse_solver = SparseSolverPtr<MatrixT, DerivedR, DerivedS>(
                         new SparseSolverBiCGSTAB<MatrixT, DerivedR, DerivedS>);
         break;
     }
     return sparse_solver;
 }
 
 } // end namespace sparse_solvers
 } // end namespace specmicp
 
 
 #endif //SPECMICP_SPARSESOLVERS_SPARSESOLVERS_HPP
diff --git a/src/utils/sparse_solvers/sparse_solver_base.hpp b/src/utils/sparse_solvers/sparse_solver_base.hpp
index 338e451..059a335 100644
--- a/src/utils/sparse_solvers/sparse_solver_base.hpp
+++ b/src/utils/sparse_solvers/sparse_solver_base.hpp
@@ -1,28 +1,57 @@
+/*-------------------------------------------------------
+
+Copyright (c) 2014,2015 Fabien Georget <fabieng@princeton.edu>, Princeton University
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+    * Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+    * Redistributions in binary form must reproduce the above copyright
+      notice, this list of conditions and the following disclaimer in the
+      documentation and/or other materials provided with the distribution.
+    * Neither the name of the Princeton University nor the
+      names of its contributors may be used to endorse or promote products
+      derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+---------------------------------------------------------*/
+
 #ifndef SPECMICP_SPARSESOLVERS_SPARSESOLVERSBASE_HPP
 #define SPECMICP_SPARSESOLVERS_SPARSESOLVERSBASE_HPP
 
 namespace specmicp {
 namespace sparse_solvers {
 
 enum class SparseSolverReturnCode;
 
 //! \brief Abstract Base Class for a sparse solver
 template <class MatrixT, class DerivedR, class DerivedS>
 class SparseSolverBase
 {
 public:
     virtual ~SparseSolverBase() {}
     virtual void analyse_pattern(MatrixT& jacobian) = 0;
     //! \brief Decompose the jacboian
     virtual SparseSolverReturnCode decompose(MatrixT& jacobian) = 0;
     //! \brief Solve the problem
     virtual SparseSolverReturnCode solve(const DerivedR& residuals, DerivedS& solution) = 0;
     //! \brief Solve the problem
     virtual SparseSolverReturnCode solve_scaling(const DerivedR& residuals, const DerivedR& scaling, DerivedS& solution) = 0;
 };
 
 } // end namespace sparse_solvers
 } // end namespace specmicp
 
 
 #endif //SPECMICP_SPARSESOLVERS_SPARSESOLVERSBASE_HPP
diff --git a/src/utils/sparse_solvers/sparse_solver_structs.hpp b/src/utils/sparse_solvers/sparse_solver_structs.hpp
index e04142f..56b7090 100644
--- a/src/utils/sparse_solvers/sparse_solver_structs.hpp
+++ b/src/utils/sparse_solvers/sparse_solver_structs.hpp
@@ -1,34 +1,63 @@
+/*-------------------------------------------------------
+
+Copyright (c) 2014,2015 Fabien Georget <fabieng@princeton.edu>, Princeton University
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+    * Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+    * Redistributions in binary form must reproduce the above copyright
+      notice, this list of conditions and the following disclaimer in the
+      documentation and/or other materials provided with the distribution.
+    * Neither the name of the Princeton University nor the
+      names of its contributors may be used to endorse or promote products
+      derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+---------------------------------------------------------*/
+
 #ifndef SPECMICP_UTILS_SPARSESOLVERSTRUCT_HPP
 #define SPECMICP_UTILS_SPARSESOLVERSTRUCT_HPP
 
 
 namespace specmicp {
 namespace sparse_solvers {
 
 //! \brief Available sparse solver
 enum class SparseSolver
 {
     SparseLU, //!< Eigen Sparse LU solver
     SparseQR, //!< Eigen Sparse QR solver
     BiCGSTAB  //!< Eigen BiCGSTAB solver
 #ifdef EIGEN_UNSUPPORTED_FOUND
     ,
     GMRES     //!< Eigen unsupported GMRES solver
 #endif
 };
 
 enum class SparseSolverReturnCode
 {
     FailedDecomposition =-2, //!< Decomposition has failed
     FailedSystemSolving =-1, //!< Solving linear system has failed
     Success = 0              //!< Success
 };
 
 
 } // end namespace sparse_solvers
 
 using SparseSolver = sparse_solvers::SparseSolver;
 
 } // end namespace specmicp
 
 #endif //SPECMICP_DFPMSOLVER_SPARSESOLVERSTRUCT_HPP
diff --git a/src/utils/timer.hpp b/src/utils/timer.hpp
index 8f73af0..b9604fd 100644
--- a/src/utils/timer.hpp
+++ b/src/utils/timer.hpp
@@ -1,63 +1,92 @@
+/*-------------------------------------------------------
+
+Copyright (c) 2014,2015 Fabien Georget <fabieng@princeton.edu>, Princeton University
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+    * Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+    * Redistributions in binary form must reproduce the above copyright
+      notice, this list of conditions and the following disclaimer in the
+      documentation and/or other materials provided with the distribution.
+    * Neither the name of the Princeton University nor the
+      names of its contributors may be used to endorse or promote products
+      derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+---------------------------------------------------------*/
+
 #ifndef SPECMICP_UTILS_TIMER_HPP
 #define SPECMICP_UTILS_TIMER_HPP
 
 #include <chrono>
 #include <ctime>
 
 namespace specmicp {
 
 //! \brief A simple timer
 class Timer
 {
 public:
     //! \brief Initialize the timer and start it
     Timer()
     {
         start();
     }
 
     //! \brief Start the timer
     void start() {
         m_start = std::chrono::system_clock::now();
     }
     //! \brief Stop the timer
     void stop() {
         m_end = std::chrono::system_clock::now();
     }
 
     //! \brief Return the time of the starting point
     std::time_t get_start() const {
         return std::chrono::system_clock::to_time_t(m_start);
     }
 
     //! \brief Return the time of the ending point
     std::time_t get_stop() const {
         return std::chrono::system_clock::to_time_t(m_end);
     }
 
     //! \brief Return a textual representation (ctime) of the starting point
     char* get_ctime_start() const {
         std::time_t start_time = get_start();
         return std::ctime(&start_time);
     }
 
     //! \brief Return a textual representation (ctime) of the ending point
     char* get_ctime_stop() const {
         std::time_t stop_time = get_stop();
         return std::ctime(&stop_time);
     }
 
     //! \brief Return the elapsed time (in seconds)
     double elapsed_time() const {
         std::chrono::duration<double> elapsed_seconds = m_end-m_start;
         return elapsed_seconds.count();
     }
 
 private:
     std::chrono::time_point<std::chrono::system_clock> m_start;
     std::chrono::time_point<std::chrono::system_clock> m_end;
 };
 
 } // end namespace specmicp
 
 #endif // SPECMICP_UTILS_TIMER_HPP