diff --git a/utils/solvers/c++/GmshSocket.h b/utils/solvers/c++/GmshSocket.h index 462933f4a816817e803e67a34131ba5f00013117..ed57e35d43691356b59d354cd067e9fc2595e9a9 100644 --- a/utils/solvers/c++/GmshSocket.h +++ b/utils/solvers/c++/GmshSocket.h @@ -21,7 +21,7 @@ // WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS // ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE // OF THIS SOFTWARE. -// +// // Please report all bugs and problems to <gmsh@geuz.org>. #ifndef _GMSH_SOCKET_H_ @@ -61,7 +61,7 @@ class GmshSocket{ // that 65535: if we receive a type > 65535 we assume that we // receive data from a machine with a different byte ordering, and // we swap the bytes in the payload) - enum MessageType{ + enum MessageType{ GMSH_START = 1, GMSH_STOP = 2, GMSH_INFO = 10, @@ -73,6 +73,8 @@ class GmshSocket{ GMSH_VERTEX_ARRAY = 22, GMSH_PARAMETER = 23, GMSH_PARAMETER_QUERY = 24, + GMSH_PARAM_QUERY_ALL = 25, + GMSH_PARAM_QUERY_END = 26, GMSH_SPEED_TEST = 30, GMSH_OPTION_1 = 100, GMSH_OPTION_2 = 101, @@ -91,7 +93,7 @@ class GmshSocket{ int sofar = 0; int remaining = bytes; do { - int len = send(_sock, buf + sofar, remaining, 0); + int len = send(_sock, buf + sofar, remaining, 0); sofar += len; remaining -= len; } while(remaining > 0); @@ -193,7 +195,7 @@ class GmshSocket{ *swap = 0; if(_ReceiveData(type, sizeof(int))){ if(*type < 0) return 0; - if(*type > 65535){ + if(*type > 65535){ // the data comes from a machine with different endianness and // we must swap the bytes *swap = 1; @@ -403,7 +405,7 @@ class GmshServer : public GmshSocket{ CloseSocket(tmpsock); throw "Socket listen failed"; } - + // wait until we get data int ret = NonBlockingWait(tmpsock, 0.5, timeout); if(ret){ @@ -445,6 +447,6 @@ class GmshServer : public GmshSocket{ CloseSocket(_sock); return 0; } -}; +}; #endif diff --git a/utils/solvers/c++/onelab.h b/utils/solvers/c++/onelab.h index 32ed1533606dcb71cbd144f5a5a22a87849fcb4f..17511aad9298f2f2045c55f708e7c2353fd9276d 100644 --- a/utils/solvers/c++/onelab.h +++ b/utils/solvers/c++/onelab.h @@ -91,6 +91,19 @@ namespace onelab{ const std::string &getName() const { return _name; } const std::string &getShortHelp() const { return _shortHelp; } const std::string &getHelp() const { return _help; } + std::string getShortName() const + { + if(_shortHelp.size()) return _shortHelp; + std::string s = _name; + // remove path + std::string::size_type last = _name.find_last_of('/'); + if(last != std::string::npos) + s = _name.substr(last + 1); + // remove starting numbers + while(s.size() && s[0] >= '0' && s[0] <= '9') + s = s.substr(1); + return s; + } bool getChanged() const { return _changed; } bool getVisible() const { return _visible; } std::string getAttribute(const std::string &key) const @@ -110,6 +123,7 @@ namespace onelab{ static std::string getNextToken(const std::string &msg, std::string::size_type &first) { + if(first == std::string::npos) return ""; std::string::size_type last = msg.find_first_of(charSep(), first); std::string next = msg.substr(first, last - first); first = (last == std::string::npos) ? last : last + 1; @@ -311,15 +325,18 @@ namespace onelab{ // regions will include union, intersection, etc. class region : public parameter{ private: - std::string _value; // TODO: change this into std::set<std::string> - std::vector<std::string> _choices; + std::set<std::string> _value; + std::vector<std::set<std::string> > _choices; + // optional geometrical dimension + int _dimension; public: - region(const std::string &name="", const std::string &value="", + region(const std::string &name="", + const std::set<std::string> &value = std::set<std::string>(), const std::string &shortHelp="", const std::string &help="") : parameter(name, shortHelp, help), _value(value) {} - void setValue(const std::string &value){ _value = value; } + void setValue(const std::set<std::string> &value){ _value = value; } std::string getType() const { return "region"; } - const std::string &getValue() const { return _value; } + const std::set<std::string> &getValue() const { return _value; } void update(const region &p) { addClients(p.getClients()); @@ -333,12 +350,15 @@ namespace onelab{ } std::string toChar() const { + /* std::ostringstream sstream; sstream << parameter::toChar() << _value << charSep() << _choices.size() << charSep(); for(unsigned int i = 0; i < _choices.size(); i++) sstream << sanitize(_choices[i]) << charSep(); return sstream.str(); + */ + return ""; } }; @@ -493,6 +513,10 @@ namespace onelab{ const std::string &client=""){ return _get(ps, name, client, _regions); } bool get(std::vector<function> &ps, const std::string &name="", const std::string &client=""){ return _get(ps, name, client, _functions); } + unsigned int getNumParameters() + { + return _numbers.size() + _strings.size() + _regions.size() + _functions.size(); + } // check if at least one parameter depends on the given client bool hasClient(const std::string &client) const { @@ -556,7 +580,7 @@ namespace onelab{ int getId(){ return _id; } void setIndex(int index){ _index = index; } int getIndex(){ return _index; } - virtual bool run(const std::string &what){ return false; } + virtual bool run(){ return false; } virtual bool isNetworkClient(){ return false; } virtual bool kill(){ return false; } virtual void sendInfo(const std::string &msg){ std::cout << msg << std::endl; } @@ -580,7 +604,7 @@ namespace onelab{ // and interacts with onelab clients. class server{ private: - // the unique server + // the unique server (singleton behaviour due to the "static" specifier) static server *_server; // the address of the server std::string _address; @@ -609,6 +633,7 @@ namespace onelab{ typedef std::map<std::string, client*>::iterator citer; citer firstClient(){ return _clients.begin(); } citer lastClient(){ return _clients.end(); } + int getNumClients() { return _clients.size(); }; citer findClient(const std::string &name){ return _clients.find(name); } void registerClient(client *c) { @@ -627,7 +652,8 @@ namespace onelab{ std::string toChar(const std::string &client="") { return _parameterSpace.toChar(client); - } + } + unsigned int getNumParameters(){ return _parameterSpace.getNumParameters(); } }; class localClient : public client{ @@ -687,7 +713,7 @@ namespace onelab{ void setPid(int pid){ _pid = pid; } GmshServer *getGmshServer(){ return _gmshServer; } void setGmshServer(GmshServer *server){ _gmshServer = server; } - virtual bool run(const std::string &what); + virtual bool run(); virtual bool kill(); }; @@ -711,7 +737,11 @@ namespace onelab{ if(!_gmshClient) return false; T p(name); std::string msg = p.toChar(); - _gmshClient->SendMessage(GmshSocket::GMSH_PARAMETER_QUERY, msg.size(), &msg[0]); + if (name.size()) + _gmshClient->SendMessage(GmshSocket::GMSH_PARAMETER_QUERY, msg.size(), &msg[0]); + else //get all parameters + _gmshClient->SendMessage(GmshSocket::GMSH_PARAM_QUERY_ALL, msg.size(), &msg[0]); + while(1){ // stop if we have no communications for 10 secs int ret = _gmshClient->Select(10, 0); @@ -739,8 +769,17 @@ namespace onelab{ ps.push_back(p); return true; } + if(type == GmshSocket::GMSH_PARAM_QUERY_ALL){ + T p; + p.fromChar(msg); + ps.push_back(p); + // do NOT return until all parameters have been downloaded + } + else if(type == GmshSocket::GMSH_PARAM_QUERY_END){ + return true; + } else if(type == GmshSocket::GMSH_INFO){ - // parameter not found + // parameter not found or all aparameters have been sent return true; } else{ diff --git a/utils/solvers/c++/solver.cpp b/utils/solvers/c++/solver.cpp index f5c1f41bf3edf0eceb7b75110852fd032f682ac0..446915eeedbdf6c8689c32579fea83e0af03a7b2 100644 --- a/utils/solvers/c++/solver.cpp +++ b/utils/solvers/c++/solver.cpp @@ -6,34 +6,36 @@ // 1) Compile this solver: g++ solver.cpp // // 2) Add it to Gmsh: -// - launch Gmsh and open Tools->OneLab +// - launch Gmsh and open Tools->OneLab // - In the gear menu, select "Add new client" // - Enter "My Solver" as client name, then choose the exe in the dialog -int main(int argc, char **argv) +int main(int argc, char **argv) { onelab::remoteNetworkClient *client = 0; for(int i = 0; i < argc; i++){ - if(std::string(argv[i]) == "-onelab" && i < argc - 1) - client = new onelab::remoteNetworkClient("My solver", argv[i + 1]); + if(std::string(argv[i]) == "-onelab" && i + 2 < argc){ + client = new onelab::remoteNetworkClient(argv[i + 1], argv[i + 2]); + break; + } } if(!client){ - printf("usage: %s -onelab socket\n", argv[0]); + printf("usage: %s -onelab name socket\n", argv[0]); exit(1); } std::vector<onelab::string> strings; // try to get the string variable "My solver/My string" from the server - client->get(strings, "My solver/My string"); + client->get(strings, "My string"); if(strings.size()){ std::cout << "Got string from server: '" << strings[0].getValue() << "'\n"; } else{ // send a value to the server - onelab::string s("My solver/My string", "Hello!"); + onelab::string s("My string", "Hello!"); client->set(s); }