diff --git a/Common/onelab.h b/Common/onelab.h
index d37b23b4ce9c8afca55f990f4af22e74e38407a1..615b4da960f4f404d6e48efdd441fd346b1d21bf 100644
--- a/Common/onelab.h
+++ b/Common/onelab.h
@@ -53,13 +53,11 @@ namespace onelab{
     std::string _label;
     // a help string
     std::string _help;
-    // clients that use this parameter
-    std::set<std::string> _clients;
-    // flag to check if the value of the parameter has been changed since the
-    // last computation (normally this is reset after all the clients have been
-    // run)
-    bool _changed;
-    // flag indicating that the _changed flag of this parameter will always be
+    // map of clients that use this parameter, associated with a "changed" flag
+    // (set to false if the client has already been run with the current value of
+    // the parameter)
+    std::map<std::string, bool> _clients;
+    // flag indicating that the "changed" flags of this parameter will always be
     // reset to false when the parameter is updated
     bool _neverChanged;
     // should the parameter be visible in the interface?
@@ -72,13 +70,24 @@ namespace onelab{
   public:
     parameter(const std::string &name="", const std::string &label="",
               const std::string &help="")
-      : _name(name), _label(label), _help(help), _changed(true),
-        _neverChanged(false), _visible(true), _readOnly(false) {}
+      : _name(name), _label(label), _help(help), _neverChanged(false),
+        _visible(true), _readOnly(false) {}
     virtual ~parameter(){}
     void setName(const std::string &name){ _name = name; }
     void setLabel(const std::string &label){ _label = label; }
     void setHelp(const std::string &help){ _help = help; }
-    void setChanged(bool changed){ _changed = changed; }
+    void setChanged(bool changed, const std::string &client="")
+    {
+      if(client.size()){
+        std::map<std::string, bool>::iterator it = _clients.find(client);
+        if(it != _clients.end()) it->second = changed;
+      }
+      else{
+        for(std::map<std::string, bool>::iterator it = _clients.begin();
+            it != _clients.end(); it++)
+          it->second = changed;
+      }
+    }
     void setNeverChanged(bool never){ _neverChanged = never; }
     void setVisible(bool visible){ _visible = visible; }
     void setReadOnly(bool readOnly){ _readOnly = readOnly; }
@@ -90,9 +99,13 @@ namespace onelab{
     {
       _attributes = attributes;
     }
-    void setClients(const std::set<std::string> &clients){ _clients = clients; }
-    void addClient(const std::string &client){ _clients.insert(client); }
-    void addClients(const std::set<std::string> &clients)
+    void setClients(const std::map<std::string, bool> &clients){ _clients = clients; }
+    void addClient(const std::string &client, bool changed)
+    {
+      if(_clients.find(client) == _clients.end())
+        _clients[client] = changed;
+    }
+    void addClients(const std::map<std::string, bool> &clients)
     {
       _clients.insert(clients.begin(), clients.end());
     }
@@ -123,7 +136,21 @@ namespace onelab{
         s = s.substr(1);
       return s;
     }
-    bool getChanged() const { return _changed; }
+    bool getChanged(const std::string &client="") const
+    {
+      if(client.size()){
+        std::map<std::string, bool>::const_iterator it = _clients.find(client);
+        if(it != _clients.end()) return it->second;
+        else return false;
+      }
+      else{
+        for(std::map<std::string, bool>::const_iterator it = _clients.begin();
+            it != _clients.end(); it++){
+          if(it->second) return true;
+        }
+        return false;
+      }
+    }
     bool getNeverChanged() const { return _neverChanged; }
     bool getVisible() const { return _visible; }
     bool getReadOnly() const { return _readOnly; }
@@ -137,10 +164,10 @@ namespace onelab{
     {
       return _attributes;
     }
-    const std::set<std::string> &getClients() const { return _clients; }
+    const std::map<std::string, bool> &getClients() const { return _clients; }
     static char charSep() { return '\0'; }
     static double maxNumber() { return 1e200; }
-    static std::string version() { return "1.05"; }
+    static std::string version() { return "1.1"; }
     static std::string getNextToken(const std::string &msg,
                                     std::string::size_type &first,
                                     char separator=charSep())
@@ -186,7 +213,6 @@ namespace onelab{
               << sanitize(getLabel()) << charSep()
               << sanitize(getHelp()) << charSep()
               << (getNeverChanged() ? 1 : 0) << charSep()
-              << (getChanged() ? 1 : 0) << charSep()
               << (getVisible() ? 1 : 0) << charSep()
               << (getReadOnly() ? 1 : 0) << charSep()
               << _attributes.size() << charSep();
@@ -195,9 +221,10 @@ namespace onelab{
         sstream << sanitize(it->first) << charSep()
                 << sanitize(it->second) << charSep();
       sstream << getClients().size() << charSep();
-      for(std::set<std::string>::const_iterator it = getClients().begin();
+      for(std::map<std::string, bool>::const_iterator it = getClients().begin();
           it != getClients().end(); it++)
-        sstream << sanitize(*it) << charSep();
+        sstream << sanitize(it->first) << charSep()
+                << (it->second ? 1 : 0) << charSep();
       return sstream.str();
     }
     virtual std::string::size_type fromChar(const std::string &msg)
@@ -209,7 +236,6 @@ namespace onelab{
       setLabel(getNextToken(msg, pos));
       setHelp(getNextToken(msg, pos));
       setNeverChanged(atoi(getNextToken(msg, pos).c_str()));
-      setChanged(atoi(getNextToken(msg, pos).c_str()));
       setVisible(atoi(getNextToken(msg, pos).c_str()));
       setReadOnly(atoi(getNextToken(msg, pos).c_str()));
       int numAttributes = atoi(getNextToken(msg, pos).c_str());
@@ -220,7 +246,8 @@ namespace onelab{
       int numClients = atoi(getNextToken(msg, pos).c_str());
       for(int i = 0; i < numClients; i++){
         std::string client(getNextToken(msg, pos));
-        addClient(client);
+        int changed = atoi(getNextToken(msg, pos).c_str());
+        addClient(client, changed ? true : false);
       }
       return pos;
     }
@@ -330,7 +357,7 @@ namespace onelab{
     }
     void update(const number &p)
     {
-      addClients(p.getClients()); // complete the list of clients
+      addClients(p.getClients());
       setLabel(p.getLabel());
       setHelp(p.getHelp());
       setVisible(p.getVisible());
@@ -655,19 +682,20 @@ namespace onelab{
       return false;
     }
     // set a parameter in the parameter space; if it already exists, update it
-    // (adding new clients if necessary). This needs to be locked to avoid race
-    // conditions when several clients try to set a parameter at the same time.
+    // (adding new clients if necessary). This would need to be locked to avoid
+    // race conditions when several clients try to set a parameter at the same
+    // time.
     template <class T> bool _set(const T &p, const std::string &client,
                                  std::set<T*, parameterLessThan> &ps)
     {
       typename std::set<T*, parameterLessThan>::iterator it = ps.find((T*)&p);
       if(it != ps.end()){
         (*it)->update(p);
-        if(client.size()) (*it)->addClient(client);
+        if(client.size()) (*it)->addClient(client, true);
       }
       else{
         T* newp = new T(p);
-        if(client.size()) newp->addClient(client);
+        if(client.size()) newp->addClient(client, true);
         ps.insert(newp);
       }
       return true;
@@ -675,7 +703,7 @@ namespace onelab{
     // get the parameter matching the given name, or all the parameters in the
     // category if no name is given. If we find a given parameter by name, we
     // add the client requesting the parameter to the list of clients for this
-    // parameter. This also needs to be locked.
+    // parameter. This would also need to be locked.
     template <class T> bool _get(std::vector<T> &p, const std::string &name,
                                  const std::string &client,
                                  std::set<T*, parameterLessThan> &ps)
@@ -690,7 +718,7 @@ namespace onelab{
         T tmp(name);
         typename std::set<T*, parameterLessThan>::iterator it = ps.find(&tmp);
         if(it != ps.end()){
-          if(client.size()) (*it)->addClient(client);
+          if(client.size()) (*it)->addClient(client, true);
           p.push_back(**it);
         }
       }
@@ -764,25 +792,21 @@ namespace onelab{
       _getAllParameters(ps);
       for(std::set<parameter*, parameterLessThan>::iterator it = ps.begin();
           it != ps.end(); it++){
-        if((client.empty() || (*it)->hasClient(client)) && (*it)->getChanged()){
+        if((*it)->getChanged(client)){
           return true;
         }
       }
       return false;
     }
-    // if no client name is given, set the changed flag for all the parameters;
-    // if a client name is given, affect parameters that are (exclusively if
-    // "exclusive" is set) owned by the client
-    bool setChanged(bool changed, const std::string &client="", bool exclusive=false)
+    // set the changed flag for all the parameters that depend on the give
+    // client (or for all parameters if no client name is provided)
+    void setChanged(bool changed, const std::string &client="")
     {
       std::set<parameter*, parameterLessThan> ps;
       _getAllParameters(ps);
       for(std::set<parameter*, parameterLessThan>::iterator it = ps.begin();
           it != ps.end(); it++)
-        if(client.empty() || ((*it)->hasClient(client) &&
-                              (!exclusive || (*it)->getNumClients() == 1)))
-          (*it)->setChanged(changed);
-      return true;
+        (*it)->setChanged(changed, client);
     }
     // serialize the parameter space (optionally only serialize those parameters
     // that depend on the given client)
@@ -957,9 +981,9 @@ namespace onelab{
       c->setId(_clients.size());
     }
     void unregisterClient(client *c){ _clients.erase(c->getName()); }
-    void setChanged(bool changed, const std::string &client="", bool exclusive=false)
+    void setChanged(bool changed, const std::string &client="")
     {
-      _parameterSpace.setChanged(changed, client, exclusive);
+      _parameterSpace.setChanged(changed, client);
     }
     bool getChanged(const std::string &client="")
     {
diff --git a/Common/onelabUtils.cpp b/Common/onelabUtils.cpp
index 41ccc1f27ca87ea922fa75e7a48d80ee92a929f4..b152f8df5b7ad2c5eb742215bcc83fab61b36869 100644
--- a/Common/onelabUtils.cpp
+++ b/Common/onelabUtils.cpp
@@ -349,11 +349,6 @@ namespace onelabUtils {
         }
       }
       setFirstComputationFlag(false);
-      // don't set the "exclusive" flag here: otherwise Gmsh will re-run in a
-      // loop as soon as a shared parameter exists; this is OK because
-      // metamodels don't call runGmshClient, and the solver (e.g. GetDP) will
-      // always run anyway. The correct fix will of course to keep track of
-      // the "changed" status for each client
       onelab::server::instance()->setChanged(false, "Gmsh");
     }
 
diff --git a/Fltk/onelabGroup.cpp b/Fltk/onelabGroup.cpp
index 597b77f11e491c4fe0ee909a3086fc97ce146113..0068e79ea6bae634eb688e7dd547b3affbb73031 100644
--- a/Fltk/onelabGroup.cpp
+++ b/Fltk/onelabGroup.cpp
@@ -421,7 +421,8 @@ bool gmshLocalNetworkClient::receiveMessage(gmshLocalNetworkClient *master)
     break;
   case GmshSocket::GMSH_CLIENT_CHANGED:
     {
-      std::string reply = onelab::server::instance()->getChanged(message) ? "changed" : "unchanged";
+      std::string reply = onelab::server::instance()->getChanged(message) ?
+        "changed" : "unchanged";
       getGmshServer()->SendMessage
         (GmshSocket::GMSH_CLIENT_CHANGED, reply.size(), &reply[0]);
     }
@@ -909,9 +910,9 @@ void onelab_cb(Fl_Widget *w, void *data)
       onelab::server::instance()->set(o);
       c->run();
       if(action == "compute"){
-        // after computing with this solver, mark the parameters exclusively
-        // owned by this solver as unchanged
-        onelab::server::instance()->setChanged(false, c->getName(), true);
+        // after computing with this solver, mark the parameters as unchanged
+        // for this solver
+        onelab::server::instance()->setChanged(false, c->getName());
 	FlGui::instance()->onelab->checkForErrors(c->getName());
       }
       if(FlGui::instance()->onelab->stop()) break;
@@ -925,11 +926,6 @@ void onelab_cb(Fl_Widget *w, void *data)
   } while(action == "compute" && !FlGui::instance()->onelab->stop() &&
           incrementLoops());
 
-  if(action == "compute"){
-    // the computation is done; mark all parameters as unchanged
-    onelab::server::instance()->setChanged(false);
-  }
-
   if(action == "compute" && (CTX::instance()->solver.autoSaveDatabase ||
                              CTX::instance()->solver.autoArchiveOutputFiles)){
     std::string db = SplitFileName(GModel::current()->getFileName())[0] + "onelab.db";
@@ -2134,7 +2130,7 @@ void solver_batch_cb(Fl_Widget *w, void *data)
     o.setValue("compute");
     onelab::server::instance()->set(o);
     c->run();
-    onelab::server::instance()->setChanged(false, c->getName(), true);
+    onelab::server::instance()->setChanged(false, c->getName());
   } while(incrementLoops());
 
   if(CTX::instance()->solver.autoSaveDatabase ||
diff --git a/contrib/onelab/python/onelab.py b/contrib/onelab/python/onelab.py
index bebf94661849007e64b8c7e9dd0ce84c9ea7f9de..62207b4c1eddfbd8ed06b005f0fb8baf3587bb29 100755
--- a/contrib/onelab/python/onelab.py
+++ b/contrib/onelab/python/onelab.py
@@ -1,5 +1,5 @@
 """
-OneLab - Copyright (C) 2011-2013 ULg-UCL
+OneLab - Copyright (C) 2011-2014 ULg-UCL
 
 Permission is hereby granted, free of charge, to any person
 obtaining a copy of this software and associated documentation
@@ -28,7 +28,7 @@ Please report all bugs and problems to the public mailing list
 """
 
 import socket, struct, os, sys, subprocess
-_VERSION = '1.05'
+_VERSION = '1.1'
 
 def file_exist(filename):
   try:
@@ -56,9 +56,9 @@ def path(ref,inp=''):
 class _parameter() :
   _membersbase = [
     ('name', 'string'), ('label', 'string', ''), ('help', 'string', ''),
-    ('neverChanged', 'int', 0), ('changed', 'int', 1), ('visible', 'int', 1),
-    ('readOnly', 'int', 0), ('attributes', ('dict', 'string', 'string'), {}),
-    ('clients', ('list', 'string'), [])
+    ('neverChanged', 'int', 0), ('visible', 'int', 1), ('readOnly', 'int', 0), 
+    ('attributes', ('dict', 'string', 'string'), {}),
+    ('clients', ('dict', 'string', 'int'), {})
   ]
   _members = {
     'string' : _membersbase + [
@@ -368,7 +368,6 @@ class client :
           return True
     return False
 
-    
   def waitOnSubClients(self):
     if not self.socket :
       return
diff --git a/utils/solvers/c++/onelab.h b/utils/solvers/c++/onelab.h
index c7a3d8a7c55f9e86c60076ec69c4ee846df4d00e..615b4da960f4f404d6e48efdd441fd346b1d21bf 100644
--- a/utils/solvers/c++/onelab.h
+++ b/utils/solvers/c++/onelab.h
@@ -1,4 +1,4 @@
-// OneLab - Copyright (C) 2011-2013 ULg-UCL
+// ONELAB - Copyright (C) 2011-2014 ULg-UCL
 //
 // Permission is hereby granted, free of charge, to any person
 // obtaining a copy of this software and associated documentation
@@ -53,13 +53,11 @@ namespace onelab{
     std::string _label;
     // a help string
     std::string _help;
-    // clients that use this parameter
-    std::set<std::string> _clients;
-    // flag to check if the value of the parameter has been changed since the
-    // last computation (normally this is reset after all the clients have been
-    // run)
-    bool _changed;
-    // flag indicating that the _changed flag of this parameter will always be
+    // map of clients that use this parameter, associated with a "changed" flag
+    // (set to false if the client has already been run with the current value of
+    // the parameter)
+    std::map<std::string, bool> _clients;
+    // flag indicating that the "changed" flags of this parameter will always be
     // reset to false when the parameter is updated
     bool _neverChanged;
     // should the parameter be visible in the interface?
@@ -72,13 +70,24 @@ namespace onelab{
   public:
     parameter(const std::string &name="", const std::string &label="",
               const std::string &help="")
-      : _name(name), _label(label), _help(help), _changed(true),
-        _neverChanged(false), _visible(true), _readOnly(false) {}
+      : _name(name), _label(label), _help(help), _neverChanged(false),
+        _visible(true), _readOnly(false) {}
     virtual ~parameter(){}
     void setName(const std::string &name){ _name = name; }
     void setLabel(const std::string &label){ _label = label; }
     void setHelp(const std::string &help){ _help = help; }
-    void setChanged(bool changed){ _changed = changed; }
+    void setChanged(bool changed, const std::string &client="")
+    {
+      if(client.size()){
+        std::map<std::string, bool>::iterator it = _clients.find(client);
+        if(it != _clients.end()) it->second = changed;
+      }
+      else{
+        for(std::map<std::string, bool>::iterator it = _clients.begin();
+            it != _clients.end(); it++)
+          it->second = changed;
+      }
+    }
     void setNeverChanged(bool never){ _neverChanged = never; }
     void setVisible(bool visible){ _visible = visible; }
     void setReadOnly(bool readOnly){ _readOnly = readOnly; }
@@ -90,9 +99,13 @@ namespace onelab{
     {
       _attributes = attributes;
     }
-    void setClients(const std::set<std::string> &clients){ _clients = clients; }
-    void addClient(const std::string &client){ _clients.insert(client); }
-    void addClients(const std::set<std::string> &clients)
+    void setClients(const std::map<std::string, bool> &clients){ _clients = clients; }
+    void addClient(const std::string &client, bool changed)
+    {
+      if(_clients.find(client) == _clients.end())
+        _clients[client] = changed;
+    }
+    void addClients(const std::map<std::string, bool> &clients)
     {
       _clients.insert(clients.begin(), clients.end());
     }
@@ -100,6 +113,7 @@ namespace onelab{
     {
       return (_clients.find(client) != _clients.end());
     }
+    int getNumClients() { return (int)_clients.size(); };
     virtual std::string getType() const = 0;
     const std::string &getName() const { return _name; }
     const std::string &getLabel() const { return _label; }
@@ -122,7 +136,21 @@ namespace onelab{
         s = s.substr(1);
       return s;
     }
-    bool getChanged() const { return _changed; }
+    bool getChanged(const std::string &client="") const
+    {
+      if(client.size()){
+        std::map<std::string, bool>::const_iterator it = _clients.find(client);
+        if(it != _clients.end()) return it->second;
+        else return false;
+      }
+      else{
+        for(std::map<std::string, bool>::const_iterator it = _clients.begin();
+            it != _clients.end(); it++){
+          if(it->second) return true;
+        }
+        return false;
+      }
+    }
     bool getNeverChanged() const { return _neverChanged; }
     bool getVisible() const { return _visible; }
     bool getReadOnly() const { return _readOnly; }
@@ -136,10 +164,10 @@ namespace onelab{
     {
       return _attributes;
     }
-    const std::set<std::string> &getClients() const { return _clients; }
+    const std::map<std::string, bool> &getClients() const { return _clients; }
     static char charSep() { return '\0'; }
     static double maxNumber() { return 1e200; }
-    static std::string version() { return "1.05"; }
+    static std::string version() { return "1.1"; }
     static std::string getNextToken(const std::string &msg,
                                     std::string::size_type &first,
                                     char separator=charSep())
@@ -185,7 +213,6 @@ namespace onelab{
               << sanitize(getLabel()) << charSep()
               << sanitize(getHelp()) << charSep()
               << (getNeverChanged() ? 1 : 0) << charSep()
-              << (getChanged() ? 1 : 0) << charSep()
               << (getVisible() ? 1 : 0) << charSep()
               << (getReadOnly() ? 1 : 0) << charSep()
               << _attributes.size() << charSep();
@@ -194,9 +221,10 @@ namespace onelab{
         sstream << sanitize(it->first) << charSep()
                 << sanitize(it->second) << charSep();
       sstream << getClients().size() << charSep();
-      for(std::set<std::string>::const_iterator it = getClients().begin();
+      for(std::map<std::string, bool>::const_iterator it = getClients().begin();
           it != getClients().end(); it++)
-        sstream << sanitize(*it) << charSep();
+        sstream << sanitize(it->first) << charSep()
+                << (it->second ? 1 : 0) << charSep();
       return sstream.str();
     }
     virtual std::string::size_type fromChar(const std::string &msg)
@@ -208,7 +236,6 @@ namespace onelab{
       setLabel(getNextToken(msg, pos));
       setHelp(getNextToken(msg, pos));
       setNeverChanged(atoi(getNextToken(msg, pos).c_str()));
-      setChanged(atoi(getNextToken(msg, pos).c_str()));
       setVisible(atoi(getNextToken(msg, pos).c_str()));
       setReadOnly(atoi(getNextToken(msg, pos).c_str()));
       int numAttributes = atoi(getNextToken(msg, pos).c_str());
@@ -219,7 +246,8 @@ namespace onelab{
       int numClients = atoi(getNextToken(msg, pos).c_str());
       for(int i = 0; i < numClients; i++){
         std::string client(getNextToken(msg, pos));
-        addClient(client);
+        int changed = atoi(getNextToken(msg, pos).c_str());
+        addClient(client, changed ? true : false);
       }
       return pos;
     }
@@ -254,7 +282,7 @@ namespace onelab{
     {
       time_t now;
       time(&now);
-      fprintf(fp, "OneLab database created by %s on %s",
+      fprintf(fp, "ONELAB database created by %s on %s",
               creator.c_str(), ctime(&now));
       for(unsigned int i = 0; i < msg.size(); i++){
         fprintf(fp, "%d ", (int)msg[i].size());
@@ -329,7 +357,7 @@ namespace onelab{
     }
     void update(const number &p)
     {
-      addClients(p.getClients()); // complete the list of clients
+      addClients(p.getClients());
       setLabel(p.getLabel());
       setHelp(p.getHelp());
       setVisible(p.getVisible());
@@ -654,19 +682,20 @@ namespace onelab{
       return false;
     }
     // set a parameter in the parameter space; if it already exists, update it
-    // (adding new clients if necessary). This needs to be locked to avoid race
-    // conditions when several clients try to set a parameter at the same time.
+    // (adding new clients if necessary). This would need to be locked to avoid
+    // race conditions when several clients try to set a parameter at the same
+    // time.
     template <class T> bool _set(const T &p, const std::string &client,
                                  std::set<T*, parameterLessThan> &ps)
     {
       typename std::set<T*, parameterLessThan>::iterator it = ps.find((T*)&p);
       if(it != ps.end()){
         (*it)->update(p);
-        if(client.size()) (*it)->addClient(client);
+        if(client.size()) (*it)->addClient(client, true);
       }
       else{
         T* newp = new T(p);
-        if(client.size()) newp->addClient(client);
+        if(client.size()) newp->addClient(client, true);
         ps.insert(newp);
       }
       return true;
@@ -674,7 +703,7 @@ namespace onelab{
     // get the parameter matching the given name, or all the parameters in the
     // category if no name is given. If we find a given parameter by name, we
     // add the client requesting the parameter to the list of clients for this
-    // parameter. This also needs to be locked.
+    // parameter. This would also need to be locked.
     template <class T> bool _get(std::vector<T> &p, const std::string &name,
                                  const std::string &client,
                                  std::set<T*, parameterLessThan> &ps)
@@ -689,7 +718,7 @@ namespace onelab{
         T tmp(name);
         typename std::set<T*, parameterLessThan>::iterator it = ps.find(&tmp);
         if(it != ps.end()){
-          if(client.size()) (*it)->addClient(client);
+          if(client.size()) (*it)->addClient(client, true);
           p.push_back(**it);
         }
       }
@@ -763,23 +792,21 @@ namespace onelab{
       _getAllParameters(ps);
       for(std::set<parameter*, parameterLessThan>::iterator it = ps.begin();
           it != ps.end(); it++){
-        if((client.empty() || (*it)->hasClient(client)) && (*it)->getChanged()){
+        if((*it)->getChanged(client)){
           return true;
         }
       }
       return false;
     }
-    // set the changed flag for all parameters (optionnally only affect those
-    // parameters that depend on a given client)
-    bool setChanged(bool changed, const std::string &client="")
+    // set the changed flag for all the parameters that depend on the give
+    // client (or for all parameters if no client name is provided)
+    void setChanged(bool changed, const std::string &client="")
     {
       std::set<parameter*, parameterLessThan> ps;
       _getAllParameters(ps);
       for(std::set<parameter*, parameterLessThan>::iterator it = ps.begin();
           it != ps.end(); it++)
-        if(client.empty() || (*it)->hasClient(client))
-          (*it)->setChanged(changed);
-      return true;
+        (*it)->setChanged(changed, client);
     }
     // serialize the parameter space (optionally only serialize those parameters
     // that depend on the given client)
@@ -849,6 +876,7 @@ namespace onelab{
     virtual void sendError(const std::string &msg){ std::cerr << msg << std::endl; }
     virtual void sendProgress(const std::string &msg){ std::cout << msg << std::endl; }
     virtual void sendMergeFileRequest(const std::string &msg){}
+    virtual void sendOpenProjectRequest(const std::string &msg){}
     virtual void sendParseStringRequest(const std::string &msg){}
     virtual void sendVertexArray(const std::string &msg){}
     virtual bool clear(const std::string &name) = 0;
@@ -1137,7 +1165,8 @@ namespace onelab{
       }
       return true;
     }
-    void _waitOnSubClients()
+  public:
+    void waitOnSubClients()
     {
       if(!_gmshClient) return;
       while(_numSubClients > 0){
@@ -1180,7 +1209,7 @@ namespace onelab{
     virtual ~remoteNetworkClient()
     {
       if(_gmshClient){
-        _waitOnSubClients();
+        waitOnSubClients();
         _gmshClient->Stop();
         _gmshClient->Disconnect();
         delete _gmshClient;
@@ -1229,11 +1258,15 @@ namespace onelab{
     {
       if(_gmshClient) _gmshClient->MergeFile(msg.c_str());
     }
+    void sendOpenProjectRequest(const std::string &msg)
+    {
+      if(_gmshClient) _gmshClient->OpenProject(msg.c_str());
+    }
     void sendParseStringRequest(const std::string &msg)
     {
       if(_gmshClient) _gmshClient->ParseString(msg.c_str());
     }
-    void runSubClient(const std::string &name, const std::string &command)
+    void runNonBlockingSubClient(const std::string &name, const std::string &command)
     {
       if(!_gmshClient){
         system(command.c_str());
@@ -1242,7 +1275,11 @@ namespace onelab{
       std::string msg = name + parameter::charSep() + command;
       _gmshClient->SendMessage(GmshSocket::GMSH_CONNECT, msg.size(), &msg[0]);
       _numSubClients += 1;
-      _waitOnSubClients();
+    }
+    void runSubClient(const std::string &name, const std::string &command)
+    {
+      runNonBlockingSubClient(name, command);
+      waitOnSubClients();
     }
   };