diff --git a/src/filter/compute_interface.hh b/src/filter/compute_interface.hh
index 083f407..f0a4176 100644
--- a/src/filter/compute_interface.hh
+++ b/src/filter/compute_interface.hh
@@ -1,130 +1,130 @@
 /**
  * @file   compute_interface.hh
  *
  * @author Guillaume Anciaux <guillaume.anciaux@epfl.ch>
  *
  * @date   Mon Oct 28 19:23:14 2013
  *
  * @brief  This is the interface of all computes
  *
  * @section LICENSE
  *
  * Copyright (©) 2010-2011 EPFL (Ecole Polytechnique Fédérale de Lausanne)
  * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
  *
  * LibMultiScale 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.
  *
  * LibMultiScale 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 LibMultiScale. If not, see <http://www.gnu.org/licenses/>.
  *
  */
 
 #ifndef __LIBMULTISCALE_COMPUTE_INTERFACE_HH__
 #define __LIBMULTISCALE_COMPUTE_INTERFACE_HH__
 /* -------------------------------------------------------------------------- */
 #include "container_array.hh"
 #include "filter_interface.hh"
 /* -------------------------------------------------------------------------- */
 
 __BEGIN_LIBMULTISCALE__
 /* -------------------------------------------------------------------------- */
 
 class ComputeInterface : public FilterInterface // , public ContainerArray<Real>
 {
 
 public:
   ComputeInterface();
 
   virtual ~ComputeInterface();
 
   //! gather result routine
   std::vector<Real> &gatherData(UInt source_rank, UInt root_rank = 0);
   //! gather all other processor result routine
   std::vector<Real> &gatherAllData(UInt root_rank = 0);
   //! all gather result routine
   std::vector<Real> &allGatherAllData();
   //! return the total number of elements (parallel safe)
   UInt getTotalNbData(UInt root_rank = 0);
 
   //! get an item from its computed name
   virtual Real &operator()(const std::string &name, UInt index = 0) {
     std::vector<std::string>::iterator it;
     it = find(name_computed.begin(), name_computed.end(), name);
     if (it == name_computed.end()) {
       LM_FATAL("Name computed '" << name << "' not found");
     } else {
       UInt position = it - name_computed.begin();
       LM_FATAL("temp " << position);
     }
   }
 
   virtual UInt getDim() { return name_computed.size(); };
   inline virtual void compute_make_call() override { LM_TOIMPLEMENT; };
 
   //-------------------------------------
   // compatibility with array
   //-------------------------------------
 
   ContainerArray<Real> &getArray() {
-    return this->getCastedOutput<ContainerArray<Real>>();
+    return this->getCastedOutput<ContainerArray<Real>>(false);
   }
 
 #define forward_method(name)                                                   \
   template <typename... Args> inline decltype(auto) name(Args &&... args) {    \
     return this->getArray().name(args...);                                     \
   };
 
   inline Real &operator[](UInt index) { return getArray()[index]; };
   inline ContainerArray<Real> &operator[](const std::string &id);
 
   inline operator ContainerArray<Real> &() { return getArray(); };
   inline operator std::vector<Real> &() { return getArray(); };
 
   forward_method(begin);
   forward_method(end);
   forward_method(assign);
   forward_method(size);
   forward_method(resize);
   forward_method(setCommGroup);
   forward_method(getCommGroup);
   forward_method(push_back);
   forward_method(clear);
   forward_method(copyContainerInfo);
   forward_method(get);
 
 public:
   std::vector<std::string> name_computed;
 
 protected:
   //! vector for gather routine usage
   std::vector<Real> data_gather;
   //! vector for receive counts on allGatherAllData.
   std::vector<int> rcnts;
   //!  flag specifying that input data was gathered(for python)
   bool gather_flag;
   //!  processor number compute_python use to gather data
   UInt gather_root_proc;
 
   //! number of columns of the produced compute
 };
 
 __END_LIBMULTISCALE__
 
 #define DECLARE_COMPUTE(class_name)                                            \
   class_name(const std::string &name);                                         \
   virtual ~class_name();                                                       \
                                                                                \
   void declareParams() override;                                               \
   void compute_make_call() override
 
 #endif /* __LIBMULTISCALE_COMPUTE_INTERFACE_HH__ */
diff --git a/src/filter/compute_python.cc b/src/filter/compute_python.cc
index df700a0..3d7183f 100644
--- a/src/filter/compute_python.cc
+++ b/src/filter/compute_python.cc
@@ -1,393 +1,394 @@
 /**
  * @file   compute_python.cc
  *
  * @author Guillaume Anciaux <guillaume.anciaux@epfl.ch>
  *
  * @date   Tue Jul 22 14:47:56 2014
  *
  * @brief  This compute allows to use Python to produce computed values as input
  * to LM
  *
  * @section LICENSE
  *
  * Copyright (©) 2010-2011 EPFL (Ecole Polytechnique Fédérale de Lausanne)
  * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
  *
  * LibMultiScale 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.
  *
  * LibMultiScale 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 LibMultiScale. If not, see <http://www.gnu.org/licenses/>.
  *
  */
 
 /* -------------------------------------------------------------------------- */
 #define TIMER
 #include "compute_python.hh"
 #include "communicator.hh"
 #include "compute_compatibility.hh"
 #include "factory_multiscale.hh"
 #include "lib_dd.hh"
 #include "lib_md.hh"
 #include "lm_common.hh"
 #include "lm_parser.hh"
 #include "units.hh"
 #include <Eigen/Dense>
 #include <pybind11/eigen.h>
 #include <pybind11/pybind11.h>
 #include <pybind11/stl.h>
 /* -------------------------------------------------------------------------- */
 
 __BEGIN_LIBMULTISCALE__
 
 namespace py = pybind11;
 
 template <typename T>
 void appendGeneralVariables(py::object &kwargs, const std::string &name,
                             T &value) {
   py::object pyvalue = py::cast(value);
   kwargs.attr("__setitem__")(name, pyvalue);
 }
 
 /* -------------------------------------------------------------------------- */
 
 template <>
 void appendGeneralVariables<IntegrationSchemeStage>(
     py::object &kwargs, const std::string &name,
     IntegrationSchemeStage &value) {
   std::stringstream sstr;
   sstr << value;
   std::string str = sstr.str();
   appendGeneralVariables<std::string>(kwargs, name, str);
 }
 
 /* -------------------------------------------------------------------------- */
 template <typename Cont>
 void appendGeneralArray(py::object &kwargs, Cont &cont, bool gather_flag,
                         CommGroup &group, bool gather_root_proc) {
 
   const UInt Dim = cont.getDim();
 
   std::vector<Real> *vdata_ptr = nullptr;
 
   if (gather_flag) {
     vdata_ptr = &cont.gatherAllData(gather_root_proc);
   } else {
     std::vector<Real> &tmp = dynamic_cast<ComputeInterface &>(cont);
     vdata_ptr = &tmp;
   }
 
   if (gather_flag) {
     UInt my_rank = group.getMyRank();
 
     if (my_rank != gather_root_proc) {
       // this->setDim(0);
       return;
     }
   }
 
   LM_ASSERT(vdata_ptr, "null pointer detected: abort");
   std::vector<Real> &vdata = *vdata_ptr;
   UInt sz = vdata.size() / Dim;
 
   Eigen::Map<
       Eigen::Array<Real, Eigen::Dynamic, Eigen::Dynamic, Eigen::RowMajor>>
       python_input(&vdata[0], sz, Dim);
   py::object pyvalue = py::cast(python_input);
 
   DUMP("adding the compute " << cont.getID(), DBG_INFO);
   kwargs.attr("__setitem__")(cont.getID(), pyvalue);
 
   py::object pyNameComputed;
   try {
     pyNameComputed = kwargs.attr("__getitem__")("name_computed");
   } catch (py::error_already_set &e) {
     pyNameComputed = py::dict();
   }
 
   py::object pyThisNameComputed = py::dict();
   for (UInt i = 0; i < cont.name_computed.size(); ++i) {
     py::object index = py::cast(i);
     pyThisNameComputed.attr("__setitem__")(cont.name_computed[i], index);
   }
   pyNameComputed.attr("__setitem__")(cont.getID(), pyThisNameComputed);
   kwargs.attr("__setitem__")("name_computed", pyNameComputed);
 }
 
 /* -------------------------------------------------------------------------- */
 
 ComputePython::ComputePython(const std::string &name) : LMObject(name) {
   gather_root_proc = 0;
   gather_flag = false;
 
   pModule = std::make_unique<py::object>();
   pCompute = std::make_unique<py::object>();
   kwargs = std::make_unique<py::dict>();
 };
 
 /* -------------------------------------------------------------------------- */
 
 ComputePython::~ComputePython() {}
 
 /* -------------------------------------------------------------------------- */
 
 void ComputePython::init() {
 
   if (!this->isConnected("input1"))
     this->removeInput("input1");
 
   try {
     *pModule = py::module::import(filename.c_str());
   } catch (py::error_already_set &e) {
     DUMP(std::endl
              << "Python error while loading " << filename << ":" << std::endl
              << e.what() << std::endl
              << std::endl,
          DBG_MESSAGE);
     LM_FATAL("Failed to load " << filename);
   }
 
   std::map<std::string, decltype(code_unit_system.mvv2e)> units_dict{
       {"mvv2e", code_unit_system.mvv2e},
       {"f_m2v_t", code_unit_system.f_m2v_t},
       {"ft_m2v", code_unit_system.ft_m2v},
       {"mv_t2f", code_unit_system.mv_t2f},
       {"kT2e", code_unit_system.kT2e},
       {"kT2fd", code_unit_system.kT2fd},
       {"m_tt2f_d", code_unit_system.m_tt2f_d},
       {"e_dd2m_tt", code_unit_system.e_dd2m_tt},
       {"e2fd", code_unit_system.e2fd},
       {"e_m2dd_tt", code_unit_system.e_m2dd_tt},
       {"fd2e", code_unit_system.fd2e}};
 
   pModule->attr("__dict__").attr("update")(units_dict);
 
   try {
     *pCompute = pModule->attr("compute");
   } catch (py::error_already_set &e) {
     DUMP(std::endl
              << "Python error in " << filename << ":" << std::endl
              << e.what() << std::endl
              << std::endl,
          DBG_MESSAGE);
     PyErr_Print();
     LM_FATAL("Cannot find entry point: compute()");
   }
 
   // try {
   //   pSetNameComputed = pModule.attr("setNameComputed");
   // } catch (py::error_already_set &e) {
   //   pSetNameComputed = py::none();
   //   DUMP(this->getID() << ": no setNameComputed routine", DBG_WARNING);
   // }
 
   kwargs->attr("update")(Parser::getAlgebraicVariables());
 }
 
 /* -------------------------------------------------------------------------- */
 void ComputePython::appendGeneralInfo(CommGroup &group) {
 
   UInt my_rank = group.getMyRank();
 
   for (UInt comp = 0; comp < compute_list.size(); ++comp) {
     LMID id = compute_list[comp];
     auto &my_compute =
         FilterManager::getManager().getCastedObject<ComputeInterface>(id);
     my_compute.build();
 
     appendGeneralArray(*kwargs, my_compute, this->gather_flag, group,
                        this->gather_root_proc);
   }
 
   if (this->gather_flag && (my_rank != gather_root_proc))
     return;
 
   appendGeneralVariables(*kwargs, "step", current_step);
   appendGeneralVariables(*kwargs, "current_stage", current_stage);
   appendGeneralVariables(*kwargs, "compute_name", this->getID());
   appendGeneralVariables(*kwargs, "rank", lm_my_proc_id);
 }
 
 /* -------------------------------------------------------------------------- */
 
 template <typename T> void treat_dict(T &dict) {}
 
 void ComputePython::callPythonRoutine() {
   STARTTIMER(this->getID());
-  LM_TOIMPLEMENT;
 
-  // //  py::array_t<Real> pValue = (*pCompute)(***kwargs);
-  // py::object pValue = (*pCompute)(***kwargs);
+  //  py::array_t<Real> pValue = (*pCompute)(***kwargs);
+  py::object pValue = (*pCompute)(***kwargs);
 
-  // std::map<std::string, py::object> results;
-  // try{
-  //   results = pValue.cast<std::map<std::string, py::object>>();
-  // }catch(...){
-  //   py::object res = pValue;
-  //   results["result"] = res;
-  // }
+  std::map<std::string, py::object> results;
+  try {
+    results = pValue.cast<std::map<std::string, py::object>>();
+  } catch (...) {
+    py::object res = pValue;
+    results["output"] = res;
+  }
 
-  // using eigen_array = Eigen::Array<double, Eigen::Dynamic, Eigen::Dynamic>;
-  // std::map<std::string, eigen_array> results_vec;
-  // for (auto && pair: results){
-  //   auto & key = pair.first;
-  //   auto & vec = pair.second;
-  //   results_vec[key] = vec.cast<eigen_array>();
-  // }
+  using eigen_array = Eigen::Array<double, Eigen::Dynamic, Eigen::Dynamic>;
+  std::map<std::string, eigen_array> results_vec;
+  for (auto &&pair : results) {
+    auto &key = pair.first;
+    auto &vec = pair.second;
+    results_vec[key] = vec.cast<eigen_array>();
+  }
   // UInt dim = result_vec.cols();
   // // setNameComputed(pArgs, dim);
 
   // this->name_computed.clear();
 
   // for (UInt i = 0; i < dim; ++i) {
   //   std::stringstream title;
   //   title << "python" << i;
   //   this->name_computed.push_back(title.str());
   // }
 
   // for (UInt i = 0; i < result_vec.rows(); ++i) {
   //   for (UInt j = 0; j < dim; ++j) {
   //     this->add(result_vec(i, j));
   //   }
   // }
   // DUMP("compute python " << this->getID() << " computed " << this->size()
   //                        << " values",
   //      DBG_INFO);
 
+  LM_TOIMPLEMENT;
+
   STOPTIMER(this->getID());
 }
 
 /* --------------------------------------------------------------------------
  */
 
 void ComputePython::compute_no_arg() {
 
   this->clear();
   // import_array();
 
   this->setCommGroup(Communicator::getCommunicator().getObject("all"));
   CommGroup &group = this->getCommGroup();
   this->appendGeneralInfo(group);
   this->callPythonRoutine();
 }
 
 /* ----------------------------------------------------------------------- */
 
 void ComputePython::compute_with_arg(ComputeInterface &cont) {
 
   this->clear();
   this->copyContainerInfo(cont);
   // import_array();
 
   CommGroup &group = this->getCommGroup();
   appendGeneralArray(*kwargs, cont, this->gather_flag, group,
                      this->gather_root_proc);
 
   this->appendGeneralInfo(group);
   this->callPythonRoutine();
 }
 /* ----------------------------------------------------------------------- */
 
 // void ComputePython::setNameComputed(py::object &pArgs, UInt dim) {
 
 //   this->name_computed.clear();
 
 //   if (!pSetNameComputed.is_none()) {
 
 //     std::list<py::object> pValue =
 //         pSetNameComputed(pArgs, kwargs).cast<std::list<py::object>>();
 
 //     if (pValue.size() != dim)
 //       LM_FATAL("The number of names provided is not correct " <<
 //       pValue.size()
 //                                                               << " != " <<
 //                                                               dim);
 
 //     for (auto &&entry : pValue) {
 
 //       std::string name = entry.cast<std::string>();
 //       DUMP("adding name_computed " << name, DBG_INFO);
 //       this->name_computed.push_back(std::string(name));
 //     }
 //   } else {
 //     for (UInt i = 0; i < dim; ++i) {
 //       std::stringstream title;
 //       title << "python" << i;
 //       this->name_computed.push_back(title.str());
 //     }
 //   }
 // }
 
 /* --------------------------------------------------------------------------
  */
 
 /* LMDESC PYTHON
    This computes an array of reals based on a python script
 */
 
 /* LMEXAMPLE
    COMPUTE disp EXTRACT INPUT md FIELD displacement \\\\
    COMPUTE disp2 PYTHON INPUT disp FILENAME script \\\\
 
    with a python script stored in a file script.py with the content such
    as:\\\\
 
    import numpy as np\\ \\
 
    def compute(**kwargs):\\
    ~~vec = np.copy(kwargs["disp"])\\
    ~~vec *= 2. \\
    ~~return vec
 */
 
 void ComputePython::declareParams() {
 
   ComputeInterface::declareParams();
 
   /* LMKEYWORD FILENAME
        Specify the name of the python script to use
     */
   this->parseKeyword("FILENAME", filename);
 
   /* LMKEYWORD GATHER_ROOT
      Specify the processor where to gather data before inputing to python
      script
   */
   this->parseKeyword("GATHER_ROOT", gather_root_proc, 0u);
 
   /* LMKEYWORD GATHER
      Specify the processor where to gather data before inputing to python
      script
   */
   this->parseTag("GATHER", gather_flag, false);
 
   /* LMKEYWORD ADD_COMPUTE
      Add computes to input to the kwargs of the python script
   */
   this->parseKeyword("ADD_COMPUTE", compute_list, std::vector<std::string>{});
 }
 
 /* --------------------------------------------------------------------------
  */
 
 void ComputePython::compute_make_call() {
 
   DUMP(this->getID() << ": Compute", DBG_INFO);
   if (this->isConnected("input1"))
     call_compute(*this,
                  [&](auto &... args) { this->compute_with_arg(args...); },
                  this->getInput("input1"));
   else
     call_compute(*this, [&]() { this->compute_no_arg(); });
 }
 
 __END_LIBMULTISCALE__