diff --git a/src/model/common/non_linear_solver/non_linear_solver_petsc.cc b/src/model/common/non_linear_solver/non_linear_solver_petsc.cc
index 29a63530d..7a956190c 100644
--- a/src/model/common/non_linear_solver/non_linear_solver_petsc.cc
+++ b/src/model/common/non_linear_solver/non_linear_solver_petsc.cc
@@ -1,301 +1,213 @@
 /**
  * Copyright (©) 2018-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne)
  * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
  *
  * This file is part of Akantu
  *
  * Akantu is free software: you can redistribute it and/or modify it under the
  * terms of the GNU Lesser General Public License as published by the Free
  * Software Foundation, either version 3 of the License, or (at your option) any
  * later version.
  *
  * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
  * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
  * details.
  *
  * You should have received a copy of the GNU Lesser General Public License
  * along with Akantu. If not, see <http://www.gnu.org/licenses/>.
  */
 
 /* -------------------------------------------------------------------------- */
 #include "non_linear_solver_petsc.hh"
 #include "dof_manager_petsc.hh"
 #include "mpi_communicator_data.hh"
 #include "solver_callback.hh"
 #include "solver_vector_petsc.hh"
 #include "sparse_matrix_petsc.hh"
 /* -------------------------------------------------------------------------- */
 #include "petscsnes.h"
 /* -------------------------------------------------------------------------- */
 
 namespace akantu {
 
 NonLinearSolverPETSc::NonLinearSolverPETSc(
     DOFManagerPETSc & dof_manager, const ModelSolverOptions & solver_options,
     const ID & id)
     : NonLinearSolver(dof_manager, solver_options, id) {
 
   if (solver_options.sparse_solver_type != SparseSolverType::_petsc)
     AKANTU_EXCEPTION(
         "petsc non linear solver works only with petsc sparse solver");
 
-  // std::unordered_map<NonLinearSolverType, SNESType>
-  //     petsc_non_linear_solver_types{
-  //         {NonLinearSolverType::_newton_raphson, SNESNEWTONLS},
-  //         {NonLinearSolverType::_linear, SNESKSPONLY},
-  //         {NonLinearSolverType::_gmres, SNESNGMRES},
-  //         {NonLinearSolverType::_bfgs, SNESQN},
-  //         {NonLinearSolverType::_cg, SNESNCG}};
-
   this->has_internal_set_param = true;
 
-  // for (const auto & pair : petsc_non_linear_solver_types) {
-  //   supported_type.insert(pair.first);
-  // }
   supported_type.insert(NonLinearSolverType::_petsc_snes);
 
   this->checkIfTypeIsSupported();
 
   auto && mpi_comm = dof_manager.getMPIComm();
 
   SNESCreate(mpi_comm, &snes);
 
-  // auto it = petsc_non_linear_solver_types.find(non_linear_solver_type);
-  // if (it != petsc_non_linear_solver_types.end()) {
-  //   SNESSetType(snes, it->second);
-  // }
   SNESSetType(snes, SNESNEWTONLS);
-
   SNESSetFromOptions(snes);
 
   this->registerParam("max_iterations", max_iterations, 10, _pat_parsmod,
                       "Max number of iterations");
 
   this->registerParam("threshold", convergence_criteria, 1e-10, _pat_parsmod,
                       "Threshold to consider results as converged");
 
   this->registerParam("convergence_type", convergence_criteria_type,
                       SolveConvergenceCriteria::_solution, _pat_parsmod,
                       "Type of convergence criteria");
 }
 
 /* -------------------------------------------------------------------------- */
 NonLinearSolverPETSc::~NonLinearSolverPETSc() { SNESDestroy(&snes); }
 
 /* -------------------------------------------------------------------------- */
 
 void NonLinearSolverPETSc::saveSolution() { AKANTU_TO_IMPLEMENT(); }
 
 /* -------------------------------------------------------------------------- */
 
 void NonLinearSolverPETSc::restoreSolution() { AKANTU_TO_IMPLEMENT(); }
 
 /* -------------------------------------------------------------------------- */
 
-void NonLinearSolverPETSc::corrector(Vec & x) {
-  PetscInt iteration;
-  SNESGetIterationNumber(snes, &iteration);
-
-  // if (prev_iteration == iteration) {
-  //   return;
-  // }
-
-  prev_iteration = iteration;
-
-  // SolverVectorPETSc dx(*this->x, "dx");
-  // VecWAXPY(dx, -1., *solution_prev, x); // w = alpha x + y.
-
-  // std::cout << "x= ";
-  // PetscPrint(x);
-  // std::cout << std::endl;
-  // std::cout << "solution_prev= " << *solution_prev << std::endl;
-  // std::cout << "dx= " << dx << std::endl;
+void NonLinearSolverPETSc::corrector(Vec x) {
 
   auto & solution = aka::as_type<SolverVectorPETSc>(dof_manager.getSolution());
-
-  // VecCopy(solution, *solution_prev);
-  // VecCopy(dx, solution);
   if (x != solution.getVec())
     VecCopy(x, solution);
 
   dof_manager.splitSolutionPerDOFs();
-  auto & model_x = this->dof_manager.getDOFs("displacement");
-
   callback->restoreLastConvergedStep();
   callback->corrector();
-  //  VecCopy(*solution_prev, solution);
 }
 
+/* -------------------------------------------------------------------------- */
+
 void NonLinearSolverPETSc::assembleResidual(Vec x, Vec f) {
-  //  saveSolution();
   corrector(x);
   auto & residual =
       dynamic_cast<SolverVectorPETSc &>(dof_manager.getResidual());
 
-  // if (residual.getVec() != f) {
-  //   VecCopy(residual, *residual_prev);
-  // }
   callback->assembleResidual();
 
   const auto & blocked_dofs = this->dof_manager.getGlobalBlockedDOFsIndexes();
-
   std::vector<Real> zeros_to_set(blocked_dofs.size());
-
   VecSetValuesLocal(residual, blocked_dofs.size(), blocked_dofs.data(),
                     zeros_to_set.data(), INSERT_VALUES);
 
   // for PETSc F is -akantu::residual
   VecScale(residual, -1);
 
   if (residual.getVec() != f) {
     VecCopy(residual, f);
-    //    VecCopy(*residual_prev, residual);
   }
-  std::cout << "x= ";
-  PetscPrint(x);
-  std::cout << " f = ";
-  PetscPrint(f);
-  std::cout << std::endl;
-
-  //  restoreSolution();
 }
 
-void NonLinearSolverPETSc::assembleJacobian(Vec x) {
-  // corrector(x);
+/* -------------------------------------------------------------------------- */
+
+void NonLinearSolverPETSc::assembleJacobian(Vec x, Mat J) {
+  corrector(x);
   callback->assembleMatrix("J");
-  PetscPrint(aka::as_type<SparseMatrixPETSc>(this->dof_manager.getMatrix("J")));
+  auto & _J = aka::as_type<SparseMatrixPETSc>(dof_manager.getMatrix("J"));
+  if (_J.getMat() != J) {
+    MatCopy(_J, J, SAME_NONZERO_PATTERN);
+  }
 }
 
-// void NonLinearSolverPETSc::reset() { prev_iteration = -1; }
-
-// void NonLinearSolverPETSc::setInitialSolution(SolverVectorPETSc & x) {
-//   VecCopy(x, x_prev);
-// }
-
-// void NonLinearSolverPETSc::setCallback(SolverCallback & callback) {
-//   this->callback = &callback;
-// }
-
 /* -------------------------------------------------------------------------- */
+
 PetscErrorCode NonLinearSolverPETSc::FormFunction(SNES /*snes*/, Vec x, Vec f,
                                                   void * ctx) {
-  auto * _this = reinterpret_cast<NonLinearSolverPETSc *>(ctx);
-  _this->assembleResidual(x, f);
-
+  reinterpret_cast<NonLinearSolverPETSc *>(ctx)->assembleResidual(x, f);
   return 0;
 }
 
 /* -------------------------------------------------------------------------- */
 PetscErrorCode NonLinearSolverPETSc::FormJacobian(SNES /*snes*/, Vec x, Mat J,
-                                                  Mat P, void * ctx) {
-  std::cout << "J= ";
-  PetscPrint(J);
-  std::cout << std::endl;
-  std::cout << "P= ";
-  PetscPrint(P);
-  std::cout << std::endl;
-  auto * _this = reinterpret_cast<NonLinearSolverPETSc *>(ctx);
-  _this->assembleJacobian(x);
-  std::cout << "Jafter= ";
-  PetscPrint(J);
-  std::cout << std::endl;
-  std::cout << "Pafter= ";
-  PetscPrint(P);
-  std::cout << std::endl;
+                                                  Mat /*P*/, void * ctx) {
+  reinterpret_cast<NonLinearSolverPETSc *>(ctx)->assembleJacobian(x, J);
   return 0;
 }
 
 /* -------------------------------------------------------------------------- */
 void NonLinearSolverPETSc::solve(SolverCallback & callback) {
   callback.beforeSolveStep();
   this->dof_manager.updateGlobalBlockedDofs();
 
   callback.assembleMatrix("J");
-  auto & global_x =
-      dynamic_cast<SolverVectorPETSc &>(dof_manager.getSolution());
-  global_x.zero();
-
-  if (not x) {
-    x = std::make_unique<SolverVectorPETSc>(global_x, "temporary_solution");
-    solution_prev =
-        std::make_unique<SolverVectorPETSc>(global_x, "previous_solution");
-    residual_prev =
-        std::make_unique<SolverVectorPETSc>(global_x, "previous_residual");
-  }
+  auto & x = dynamic_cast<SolverVectorPETSc &>(dof_manager.getSolution());
+  x.zero();
 
-  *x = global_x;
-
-  // this->reset();
-  prev_iteration = -1;
-
-  // this->setCallback(callback);
   this->callback = &callback;
 
-  // this->setInitialSolution(global_x);
-  VecCopy(*x, *solution_prev);
-
   auto & rhs = aka::as_type<SolverVectorPETSc>(dof_manager.getResidual());
+  rhs.zero();
+
   auto & J = aka::as_type<SparseMatrixPETSc>(dof_manager.getMatrix("J"));
 
   SNESSetFunction(snes, rhs, NonLinearSolverPETSc::FormFunction, this);
   SNESSetJacobian(snes, J, J, NonLinearSolverPETSc::FormJacobian, this);
 
-  rhs.zero();
-
   callback.predictor();
-  //  callback.assembleResidual();
-  SNESView(snes, PETSC_VIEWER_STDOUT_WORLD);
 
-  SNESSolve(snes, nullptr, *x);
+  // SNESView(snes, PETSC_VIEWER_STDOUT_WORLD);
+  SNESSolve(snes, nullptr, x);
   SNESGetConvergedReason(snes, &reason);
   SNESGetIterationNumber(snes, &n_iter);
 
-  auto & model_x = this->dof_manager.getDOFs("displacement");
+  // access the model solution counter part: only for debug
+  // auto & model_x = this->dof_manager.getDOFs("displacement");
   dof_manager.splitSolutionPerDOFs();
   callback.restoreLastConvergedStep();
   callback.corrector();
 
   bool converged = reason >= 0;
   callback.afterSolveStep(converged);
 
   if (not converged) {
     PetscReal atol;
     PetscReal rtol;
     PetscReal stol;
     PetscInt maxit;
     PetscInt maxf;
 
     SNESGetTolerances(snes, &atol, &rtol, &stol, &maxit, &maxf);
     AKANTU_CUSTOM_EXCEPTION(debug::SNESNotConvergedException(
         this->reason, this->n_iter, stol, atol, rtol, maxit));
   }
 }
 
 /* -------------------------------------------------------------------------- */
 void NonLinearSolverPETSc::updateInternalParameters() {
 
   std::map<ID, ID> akantu_to_petsc_option = {{"max_iterations", "snes_max_it"},
                                              {"threshold", "snes_stol"}};
 
   for (auto && [param, param_akantu] : akantu_to_petsc_option) {
     auto & value = this->get(param);
     PetscOptionsSetValue(nullptr, ("-" + param_akantu).c_str(),
                          value.to_string().c_str());
   }
   SNESSetFromOptions(snes);
   PetscOptionsClear(nullptr);
 }
 /* -------------------------------------------------------------------------- */
 void NonLinearSolverPETSc::parseSection(const ParserSection & section) {
   auto parameters = section.getParameters();
   for (auto && param : range(parameters.first, parameters.second)) {
     PetscOptionsSetValue(nullptr, param.getName().c_str(),
                          param.getValue().c_str());
   }
   SNESSetFromOptions(snes);
   PetscOptionsClear(nullptr);
 }
 /* -------------------------------------------------------------------------- */
 
 } // namespace akantu
diff --git a/src/model/common/non_linear_solver/non_linear_solver_petsc.hh b/src/model/common/non_linear_solver/non_linear_solver_petsc.hh
index ec9cddc45..0cf10f655 100644
--- a/src/model/common/non_linear_solver/non_linear_solver_petsc.hh
+++ b/src/model/common/non_linear_solver/non_linear_solver_petsc.hh
@@ -1,112 +1,108 @@
 /**
  * Copyright (©) 2018-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne)
  * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
  *
  * This file is part of Akantu
  *
  * Akantu is free software: you can redistribute it and/or modify it under the
  * terms of the GNU Lesser General Public License as published by the Free
  * Software Foundation, either version 3 of the License, or (at your option) any
  * later version.
  *
  * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
  * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
  * details.
  *
  * You should have received a copy of the GNU Lesser General Public License
  * along with Akantu. If not, see <http://www.gnu.org/licenses/>.
  */
 
 /* -------------------------------------------------------------------------- */
 #include "non_linear_solver.hh"
 #include "solver_vector_petsc.hh"
 /* -------------------------------------------------------------------------- */
 #include <petscsnes.h>
 /* -------------------------------------------------------------------------- */
 
 #ifndef AKANTU_NON_LINEAR_SOLVER_PETSC_HH_
 #define AKANTU_NON_LINEAR_SOLVER_PETSC_HH_
 
 namespace akantu {
 class DOFManagerPETSc;
 class SolverVectorPETSc;
 } // namespace akantu
 
 namespace akantu {
 
 class NonLinearSolverPETSc : public NonLinearSolver {
   /* ------------------------------------------------------------------------ */
   /* Constructors/Destructors                                                 */
   /* ------------------------------------------------------------------------ */
 public:
   NonLinearSolverPETSc(DOFManagerPETSc & dof_manager,
                        const ModelSolverOptions & solver_options,
                        const ID & id = "non_linear_solver_petsc");
 
   ~NonLinearSolverPETSc() override;
 
   /* ------------------------------------------------------------------------ */
   /* Methods                                                                  */
   /* ------------------------------------------------------------------------ */
 public:
   /// solve the system described by the jacobian matrix, and rhs contained in
   /// the dof manager
   void solve(SolverCallback & callback) override;
 
   /// parse the arguments from the input file
   void parseSection(const ParserSection & section) override;
   /* ------------------------------------------------------------------------ */
   /* Class Members                                                            */
   /* ------------------------------------------------------------------------ */
 protected:
   static PetscErrorCode FormFunction(SNES snes, Vec dx, Vec f, void * ctx);
   static PetscErrorCode FormJacobian(SNES snes, Vec dx, Mat J, Mat P,
                                      void * ctx);
 
-  void corrector(Vec & x);
+  void corrector(Vec x);
   void assembleResidual(Vec x, Vec f);
-  void assembleJacobian(Vec x);
+  void assembleJacobian(Vec x, Mat J);
   void updateInternalParameters() override;
 
   void saveSolution();
   void restoreSolution();
 
   /// PETSc non linear solver
   SNES snes;
   SNESConvergedReason reason;
 
   SolverCallback * callback{nullptr};
 
   std::unique_ptr<SolverVectorPETSc> x;
-  std::unique_ptr<SolverVectorPETSc> solution_prev;
-  std::unique_ptr<SolverVectorPETSc> residual_prev;
 
   Int n_iter{0};
   Int max_iterations;
   /// Type of convergence criteria
   SolveConvergenceCriteria convergence_criteria_type;
   /// convergence threshold
   Real convergence_criteria;
-  // save previous iteration
-  PetscInt prev_iteration{-1};
 };
 
 namespace debug {
   class SNESNotConvergedException : public NLSNotConvergedException {
   public:
     SNESNotConvergedException(SNESConvergedReason reason, Int niter, Real error,
                               Real absolute_tolerance, Real relative_tolerance,
                               Int max_iterations)
         : NLSNotConvergedException(relative_tolerance, niter, error),
           reason(reason), absolute_tolerance(absolute_tolerance),
           max_iterations(max_iterations) {}
     SNESConvergedReason reason;
     Real absolute_tolerance;
     Int max_iterations;
   };
 } // namespace debug
 
 } // namespace akantu
 
 #endif /* AKANTU_NON_LINEAR_SOLVER_PETSC_HH_ */