From 57e7cb5e8951319806000f343af8067c5823d3a4 Mon Sep 17 00:00:00 2001
From: Francois Henrotte <francois.henrotte@ulg.ac.be>
Date: Wed, 23 Apr 2014 14:40:06 +0000
Subject: [PATCH] communication to the metamoodel of the Gmsh batch and loop
 status; OL preprocessors returns the /changed/ status of the client;
 /changed/ flag of all parameters set to false after a /compute/; param
 attributes updated (not replaced) by a parameter redefinition; + some clean
 up

---
 Common/CommandLine.cpp                        |  9 ---
 Common/OpenFile.cpp                           |  7 +-
 Fltk/onelabGroup.cpp                          | 10 ++-
 Mesh/cross3D.h                                |  5 +-
 Mesh/directions3D.cpp                         | 10 +--
 contrib/onelab/OLMakefile                     | 61 -----------------
 contrib/onelab/OnelabParser.cpp               |  6 +-
 contrib/onelab/python/onelab.py               | 66 ++++++++++++-------
 contrib/onelab/python/test.py                 |  2 +-
 contrib/onelab/python/wrappers/Makefile       | 11 ----
 .../onelab/python/wrappers/OnelabClient.py    | 59 -----------------
 contrib/onelab/python/wrappers/onelab.i       | 15 -----
 contrib/onelab/python/wrappers/test.ol        |  2 -
 contrib/onelab/python/wrappers/test.py        | 20 ------
 14 files changed, 65 insertions(+), 218 deletions(-)
 delete mode 100644 contrib/onelab/OLMakefile
 delete mode 100644 contrib/onelab/python/wrappers/Makefile
 delete mode 100755 contrib/onelab/python/wrappers/OnelabClient.py
 delete mode 100644 contrib/onelab/python/wrappers/onelab.i
 delete mode 100755 contrib/onelab/python/wrappers/test.ol
 delete mode 100755 contrib/onelab/python/wrappers/test.py

diff --git a/Common/CommandLine.cpp b/Common/CommandLine.cpp
index 028c7fcd40..7702350407 100644
--- a/Common/CommandLine.cpp
+++ b/Common/CommandLine.cpp
@@ -305,15 +305,6 @@ void GetOptions(int argc, char *argv[])
         else
           Msg::Fatal("Missing client name and/or address of ONELAB server");
       }
-      else if(!strcmp(argv[i] + 1, "lol")) {
-        i++;
-        if(argv[i] && argv[i + 1] && argv[i + 1][0] != '-'){
-          Msg::LoadOnelabClient(argv[i], argv[i + 1]);
-          i += 2;
-        }
-        else
-          Msg::Fatal("Missing client name and/or address of ONELAB server");
-      }
       else if(!strcmp(argv[i] + 1, "socket")) {
         i++;
         if(argv[i])
diff --git a/Common/OpenFile.cpp b/Common/OpenFile.cpp
index 1a95effcf3..a111b0b5a8 100644
--- a/Common/OpenFile.cpp
+++ b/Common/OpenFile.cpp
@@ -439,14 +439,9 @@ int MergeFile(const std::string &fileName, bool warnIfMissing, bool setWindowTit
     int num = defineSolver(split[1]);
     opt_solver_executable(num, GMSH_SET, fileName);
     CTX::instance()->launchSolverAtStartup = num;
+    Msg::SetOnelabNumber("0Metamodel/Batch", CTX::instance()->batch, false);
     return 1;
   }
-#endif
-#if defined(HAVE_ONELAB_METAMODEL) && defined(HAVE_FLTK)
-  else if(ext == ".ol"){
-    // FIXME: this is a hack -- think about a better way
-    status = metamodel_cb(fileName);
-  }
 #endif
   else {
     CTX::instance()->geom.draw = 1;
diff --git a/Fltk/onelabGroup.cpp b/Fltk/onelabGroup.cpp
index 36483de0ac..4fc4db0709 100644
--- a/Fltk/onelabGroup.cpp
+++ b/Fltk/onelabGroup.cpp
@@ -394,17 +394,17 @@ bool gmshLocalNetworkClient::receiveMessage(gmshLocalNetworkClient *master)
   case GmshSocket::GMSH_OLPARSE:
     {
 #if defined(HAVE_ONELAB_METAMODEL)
-      localSolverClient *c = new InterfacedClient("OLParser","","");
       std::vector<std::string> split = SplitOLFileName(message);
       std::string ofileName = split[0] + split[1] ;
       std::ofstream outfile(ofileName.c_str());
+      localSolverClient *c = new InterfacedClient(split[1],"","");
       if (outfile.is_open())
         c->convert_onefile(message, outfile);
       else
         Msg::Error("The file <%s> cannot be opened",ofileName.c_str());
       outfile.close();
 
-      std::string reply = "done"; // reply is dummy
+      std::string reply = onelab::server::instance()->getChanged(c->getName()) ? "changed" : "unchanged";
       getGmshServer()->SendMessage
         (GmshSocket::GMSH_OLPARSE, reply.size(), &reply[0]);
 
@@ -576,7 +576,7 @@ static bool incrementLoops()
   else if(onelabUtils::incrementLoop("2")) ret = true;
   else if(onelabUtils::incrementLoop("1")) ret = true;
 
-  //Update Onelab db flag indicating whether or not in a loop
+  //Update Onelab db parameter indicating whether or not in a loop
   std::vector<onelab::number> pn;
   onelab::server::instance()->get(pn,"0Metamodel/Loop");
   if(pn.size()){
@@ -894,6 +894,10 @@ void onelab_cb(Fl_Widget *w, void *data)
         }
         if(FlGui::instance()->onelab->stop()) break;
       }
+      // After computing, all parameters are set unchanged
+      if(action == "compute"){
+          onelab::server::instance()->setChanged(false);
+      }
     }
 
     if(action != "initialize"){
diff --git a/Mesh/cross3D.h b/Mesh/cross3D.h
index a553159375..d270090865 100644
--- a/Mesh/cross3D.h
+++ b/Mesh/cross3D.h
@@ -285,8 +285,9 @@ Qtn cross3D::rotationToOnSurf(const cross3D &y) const{
 
   Qtn R1 = Qtn(axis, th1);
   xx.rotate(R1);
-  if(fabs(angle(xx.getFrst(), yy.getFrst())) > 1e-8){
-    std::cout << "This should not happen: not aligned "<< std::endl; 
+  double temp = fabs(angle(xx.getFrst(), yy.getFrst()));
+  if( (temp > 1e-8) && (temp < M_PI - 1e-8)){
+    std::cout << "This should not happen: not aligned= " << temp << std::endl; 
     exit(1);
   }
   
diff --git a/Mesh/directions3D.cpp b/Mesh/directions3D.cpp
index 67103d82b4..dcc1b3f4b7 100644
--- a/Mesh/directions3D.cpp
+++ b/Mesh/directions3D.cpp
@@ -455,7 +455,7 @@ int Frame_field::findAnnIndex(SPoint3 p){
 }
 
 void Frame_field::initFace(GFace* gf){
-  // align crosses of gf with the normal (average on neighbour elements)
+  // align crosses of "gf" with the normal (average on neighbour elements)
   // at all vertices of the GFace gf
   build_vertex_to_elements(gf);
   for(std::map<MVertex*, std::set<MElement*> >::const_iterator it
@@ -489,7 +489,7 @@ void Frame_field::initFace(GFace* gf){
 
   std::cout << "Nodes in face = " << vertex_to_elements.size() << std::endl;
 
-  // compute cumulative cross-data vertices x elements for the whole contour of gf
+  // compute cumulative cross-data "vertices x elements" for the whole contour of gf
   std::list<GEdge*> edges = gf->edges();
   vertex_to_elements.clear();
   //Replace edges by their compounds
@@ -768,6 +768,8 @@ void Frame_field::save(const std::vector<std::pair<SPoint3, STensor3> > data,
   file.close();
 }
 
+// BARYCENTRIC End
+
 void Frame_field::recur_connect_vert(FILE *fi, int count,
 				     MVertex *v,
 				     STensor3 &cross,
@@ -1629,8 +1631,8 @@ void Nearest_point::clear(){
   field.clear();
   vicinity.clear();
 #if defined(HAVE_ANN)
-  delete kd_tree->thePoints();
-  delete kd_tree;
+   delete kd_tree->thePoints();
+   delete kd_tree;
   annClose();
 #endif
 }
diff --git a/contrib/onelab/OLMakefile b/contrib/onelab/OLMakefile
deleted file mode 100644
index 0079571bdf..0000000000
--- a/contrib/onelab/OLMakefile
+++ /dev/null
@@ -1,61 +0,0 @@
-SOLVERS=loader
-SOURCES=myOS StringUtils mathex OnelabClients OnelabMessage OnelabParser metamodel
-
-COMMON_DIR=$(GMSH_DIR)/Common
-ONELAB_DIR=$(GMSH_DIR)/contrib/onelab
-MATHEX_DIR=$(GMSH_DIR)/contrib/MathEx
-CPPFLAGS+= $(shell python-config --includes) -fPIC
-
-OBJDIR=objects
-
-ifeq ($(STATICLINUX), 32)
-	LDFLAGS+=-static-libgcc -static-libstdc++ -static -m32
-	CPPFLAGS+= -m32
-	OBJDIR=objects-static-linux32
-	EXESUFFIX=32
-endif
-ifeq ($(STATICLINUX), 64)
-	LDFLAGS+=-static-libgcc -static-libstdc++ -static
-	OBJDIR=objects-static-linux64
-	EXESUFFIX=64
-endif
-ifeq ($(MINGW), 32)
-	CXX=i686-w64-mingw32-g++
-	LDFLAGS+=-static-libgcc -static-libstdc++ -static -lws2_32
-	OBJDIR=objects-mingw32
-	EXESUFFIX=32.exe
-endif
-ifeq ($(MINGW), 64)
-	CXX=x86_64-w64-mingw32-g++
-	LDFLAGS+=-static-libgcc -static-libstdc++ -static -lws2_32
-	OBJDIR=objects-mingw64
-	EXESUFFIX=64.exe
-endif
-
-TARGETS=$(SOLVERS:=_onelab$(EXESUFFIX))
-all : $(TARGETS)
-ifndef GMSH_DIR
-	@echo '"The environment variable GMSH_DIR is not set."'
-	@exit
-endif
-
-CPPFLAGS+=-g -DONELAB_LOADER -I$(COMMON_DIR) -I$(ONELAB_DIR) -I$(MATHEX_DIR)
-VPATH=$(ONELAB_DIR):$(COMMON_DIR):$(MATHEX_DIR)
-
-OBJECTS=$(foreach OBJ, $(SOURCES), $(OBJDIR)/$(OBJ).o)
-$(OBJDIR)/%.o : %.cpp $(ONELAB_DIR)/*.h
-	@mkdir -p $(OBJDIR) 
-	$(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $< -o $@
-
-%_onelab$(EXESUFFIX) : $(OBJDIR)/%.o $(OBJECTS)
-	$(CXX) $< $(OBJECTS) $(LDFLAGS) -o $@
-
-clean :
-	$(RM) $(TARGETS) $(OBJDIR)/*.o
-
-onelab_wrap.cpp : onelab.i
-	swig -python -c++ -o $@ $<
-
-_onelab.so : $(OBJECTS) $(OBJDIR)/onelab_wrap.o
-	$(CXX) -bundle -flat_namespace -undefined suppress $(OBJECTS) $(OBJDIR)/onelab_wrap.o -o _onelab.so
-.PRECIOUS: $(OBJDIR)/%.o
diff --git a/contrib/onelab/OnelabParser.cpp b/contrib/onelab/OnelabParser.cpp
index bd42b12f08..6baf07118c 100644
--- a/contrib/onelab/OnelabParser.cpp
+++ b/contrib/onelab/OnelabParser.cpp
@@ -1,7 +1,10 @@
-#include "OnelabClients.h"
+
 #include <algorithm>
 #include "mathex.h"
 
+#include "OnelabClients.h"
+
+
 // reserved keywords for the onelab parser
 
 namespace olkey{
@@ -126,6 +129,7 @@ void MetaModel::saveCommandLines(){
   outfile.close();
 }
 
+
 int enclosed(const std::string &in, std::vector<std::string> &arguments,
 	     size_t &end){
   // syntax: (arguments[Ø], arguments[1], ... , arguments[n])
diff --git a/contrib/onelab/python/onelab.py b/contrib/onelab/python/onelab.py
index e8ae67824f..508b346b4a 100755
--- a/contrib/onelab/python/onelab.py
+++ b/contrib/onelab/python/onelab.py
@@ -114,9 +114,13 @@ class _parameter() :
     return self
 
   def modify(self, **param) :
+    ## updates the parameter with the content of param, attributes are merged
     for i in _parameter._members[self.type] :
       if i[0] in param :
-        setattr(self, i[0], param[i[0]]) #NB: no else statement => update
+        if i[0] == 'attributes' :
+          self.attributes.update(param['attributes'])
+        else :
+          setattr(self, i[0], param[i[0]])
 
 
 class client :
@@ -164,41 +168,30 @@ class client :
       self._createSocket()
       self.socket.send(struct.pack('ii%is' %len(m), t, len(m), m))
 
-  def _defineParameter(self, param) :
+  def _defineParameter(self, p) :
     if not self.socket :
-      return param.value
-    self._send(self._GMSH_PARAMETER_QUERY, param.tochar())
+      return p.value
+    self._send(self._GMSH_PARAMETER_QUERY, p.tochar())
     (t, msg) = self._receive() 
     if t == self._GMSH_PARAMETER :
-      self._send(self._GMSH_PARAMETER_UPDATE, param.tochar()) #enrich a previous decl.
-      return param.fromchar(msg).value # use value from server
+      self._send(self._GMSH_PARAMETER_UPDATE, p.tochar())
+      return p.fromchar(msg).value
     elif t == self._GMSH_PARAMETER_NOT_FOUND :
-      self._send(self._GMSH_PARAMETER, param.tochar()) #declaration
-      return param.value
-    
+      self._send(self._GMSH_PARAMETER, p.tochar())
+      return p.value
+        
   def defineNumber(self, name, **param):
     if 'labels' in param :
       param["choices"] = param["labels"].keys()
     p = _parameter('number', name=name, **param)
-    if 'value' not in param : #make the parameter readOnly
-      p.readOnly = 1
-      p.attributes={'Highlight':'AliceBlue'}
     value = self._defineParameter(p)
     return value
 
   def defineString(self, name, **param):
     p = _parameter('string', name=name, **param)
-    if 'value' not in param : #make the parameter readOnly
-      p.readOnly = 1
-      p.attributes={'Highlight':'AliceBlue'}
     value = self._defineParameter(p)
     return value
   
-  def clear(self, name) :
-    if not self.socket :
-      return
-    self._send(self._GMSH_PARAMETER_CLEAR, str(name))
-
   def setNumber(self, name, **param):
     if not self.socket :
       return
@@ -223,6 +216,11 @@ class client :
       p.modify(**param)
     self._send(self._GMSH_PARAMETER, p.tochar())
 
+  def clear(self, name) :
+    if not self.socket :
+      return
+    self._send(self._GMSH_PARAMETER_CLEAR, str(name))
+    
   def addNumberChoice(self, name, value):
     if not self.socket :
       return
@@ -230,7 +228,11 @@ class client :
     self._send(self._GMSH_PARAMETER_QUERY, p.tochar())
     (t, msg) = self._receive() 
     if t == self._GMSH_PARAMETER :
-      p.fromchar(msg).choices.append(value)
+      p.fromchar(msg).value = value
+      if self.loop :
+        p.choices.append(value)
+      else :
+        p.choices = ()
     elif t == self._GMSH_PARAMETER_NOT_FOUND :
       print ('Unknown parameter %s' %(param.name))
     self._send(self._GMSH_PARAMETER, p.tochar())
@@ -323,7 +325,10 @@ class client :
     self._send(self._GMSH_OLPARSE, filename)
     (t, msg) = self._receive() 
     if t == self._GMSH_OLPARSE :
-      print (msg)
+      print(msg)
+      if msg == "changed" :
+          return True
+    return False
 
   def _createSocket(self) :
     addr = self.addr
@@ -373,10 +378,12 @@ class client :
         self.addr = sys.argv[i + 2]
         self._createSocket()
         self._send(self._GMSH_START, str(os.getpid()))
-    self.action = self.getString(self.name + '/Action')
+    self.action = "compute" # default (subclients have no client.Action defined)
+    self.action = self.getString(self.name + '/Action', False)
     self.setNumber('IsPyMetamodel',value=1,visible=0)
     self.defineNumber('0Metamodel/Loop',value=0,visible=0)
-    self.loop = bool(self.getNumber('0Metamodel/Loop'))
+    self.loop = self.getNumber('0Metamodel/Loop')
+    self.batch = self.getNumber('0Metamodel/Batch')
     self.sendInfo("Performing OneLab '" + self.action + "'")
     if self.action == "initialize": 
       self.finalize()
@@ -469,3 +476,14 @@ class client :
     if list :
       self.setString(self.name+'/9Output files', value=list[0],
                      choices=list, visible=0)
+
+# tool to extract the (i, j)th element in an array file
+from rlcompleter import readline
+def extract(filename,i,j):
+    input = open(filename,'r')
+    all_lines = input.readlines()
+    input.close()
+    if i == -1:
+        i = len(all_lines) # last line
+    items = all_lines[i-1].split()
+    return float(items[j-1])
diff --git a/contrib/onelab/python/test.py b/contrib/onelab/python/test.py
index e551aceae0..04bcf7d72b 100755
--- a/contrib/onelab/python/test.py
+++ b/contrib/onelab/python/test.py
@@ -14,7 +14,7 @@ B = OL.defineNumber('Group/B', value=0, min = -10, max = 10, step = 1)
 C = OL.defineNumber('Group/C', value=2, choices = [0, 1, 2, 3], attributes={'Highlight':'Pink'})
 D = OL.defineNumber('Group/D', value=3, labels = {0:'zero', 1:'un', 2:'deux', 3:'trois'}, attributes={'Highlight':'Blue'})
 
-OL.openGeometry(modelName + '.geo')
+OL.reloadGeometry(modelName + '.geo')
 OL.preProcess(modelName + '.txt.ol')
 
 if OL.action == 'compute' :
diff --git a/contrib/onelab/python/wrappers/Makefile b/contrib/onelab/python/wrappers/Makefile
deleted file mode 100644
index e3978894fe..0000000000
--- a/contrib/onelab/python/wrappers/Makefile
+++ /dev/null
@@ -1,11 +0,0 @@
-all: _onelab.so
-GMSH_DIR=../../../../
-COMMON_DIR=$(GMSH_DIR)/Common
-CPPFLAGS+= $(shell python-config --includes) -I$(COMMON_DIR) -DONELAB_LOADER
-
-onelab_wrap.cpp : onelab.i
-	swig -python -c++ ${CPPFLAGS} -o $@ $<
-
-_onelab.so : onelab_wrap.cpp
-	$(CXX) -shared onelab_wrap.cpp -o $@ $(CPPFLAGS) -fPIC -DSWIG
-.PRECIOUS: $(OBJDIR)/%.o
diff --git a/contrib/onelab/python/wrappers/OnelabClient.py b/contrib/onelab/python/wrappers/OnelabClient.py
deleted file mode 100755
index 3677a6a1d9..0000000000
--- a/contrib/onelab/python/wrappers/OnelabClient.py
+++ /dev/null
@@ -1,59 +0,0 @@
-import onelab
-import sys
-
-class client :
-
-  def get_number(self, name, default, label = '', min = -sys.float_info.max, max = sys.float_info.max, step = 0, choices = [], labels = [], attributes = {}, help = "", visible = 1, read_only = 0) :
-    if not self.client :
-      return default
-    n = onelab.number(name, default)
-    n.setLabel(label)
-    n.setVisible(visible)
-    n.setReadOnly(read_only)
-    n.setMin(min)
-    n.setMax(max)
-    n.setStep(step)
-    n.setHelp(help)
-    n.setChoices(choices)
-    if labels :
-      n.setChoices([k for k in labels.keys()])
-      n.setChoiceLabels([v for v in labels.values()])
-    for k,v in attributes.items() :
-      n.setAttribute(k, v)
-    r = onelab.OnelabNumberVector()
-    self.client.get(r, n.getName())
-    if r :
-      return r[0].getValue()
-    else :
-      self.client.set(n)
-      return default
-
-  def get_string(self, name, default, choices = [], help ="", label = "", visible = 1, read_only = 0, kind = "generic", attributes = {}) :
-    if not self.client :
-      return default
-    n = onelab.string(name, default)
-    n.setChoices(choices)
-    n.setReadOnly(read_only)
-    n.setVisible(visible)
-    n.setLabel(label)
-    n.setHelp(help)
-    n.setKind(kind)
-    r = onelab.OnelabStringVector()
-    for k,v in attributes.items() :
-      n.setAttribute(k, v)
-    self.client.get(r, n.getName())
-    if r :
-      return r[0].getValue()
-    else :
-      self.client.set(n)
-      return default
-
-  def __init__(self):
-    self.client = None
-    self.name = ""
-    for i, v in enumerate(sys.argv) :
-      if v == '-onelab':
-        self.name = sys.argv[i + 1]
-        self.client = onelab.remoteNetworkClient(self.name, sys.argv[i+2])
-    self.action = self.get_string(self.name + '/Action', 'compute')
-    if self.action == "initialize": exit(0)
diff --git a/contrib/onelab/python/wrappers/onelab.i b/contrib/onelab/python/wrappers/onelab.i
deleted file mode 100644
index 21c18c2875..0000000000
--- a/contrib/onelab/python/wrappers/onelab.i
+++ /dev/null
@@ -1,15 +0,0 @@
-%module onelab
-%{
-#include "onelab.h"
-onelab::server *onelab::server::_server = 0;
-%}
- 
-%include std_string.i
-%include std_vector.i
-%include std_map.i
-%template(OnelabNumberVector) std::vector<onelab::number>;
-%template(OnelabStringVector) std::vector<onelab::string>;
-%template(DoubleVector) std::vector<double>;
-%template(StringVector) std::vector<std::string>;
-%template(DoubleStringMap) std::map<double, std::string>;
-%include "onelab.h"
diff --git a/contrib/onelab/python/wrappers/test.ol b/contrib/onelab/python/wrappers/test.ol
deleted file mode 100755
index 79463f51e7..0000000000
--- a/contrib/onelab/python/wrappers/test.ol
+++ /dev/null
@@ -1,2 +0,0 @@
-Native.register(native, ./test.py);
-Native.run();
diff --git a/contrib/onelab/python/wrappers/test.py b/contrib/onelab/python/wrappers/test.py
deleted file mode 100755
index 631bb7070f..0000000000
--- a/contrib/onelab/python/wrappers/test.py
+++ /dev/null
@@ -1,20 +0,0 @@
-#!/usr/bin/env python
-#coding=utf-8
-import OnelabClient
-
-oc = OnelabClient.client()
-
-#name and default value are required
-A = oc.get_number('A', 10)
-#other attributes are optionals
-B = oc.get_number('Group/B', 0, min = -10, max = 10, step = 1)
-C = oc.get_number('Group/C', 2, choices = [0, 1, 2, 3], attributes={'Highlight':'Pink'})
-D = oc.get_number('Group/D', 2, labels = {0:'zero', 1:'un', 2:'deux', 3:'trois'}, attributes={'Highlight':'Blue'})
-#utf-8 are allowed everywhere (should be prefixed by 'u' in python 2, not required in python 3)
-Omega = oc.get_string(u'Ω', u'∫(∂φ/∂α)³dx', help=u'ask someone@universe.org', choices = ['oui', 'non', u'peut-être'])
-
-if oc.action != 'compute' :
-  exit(0)
-
-#this is the solver code
-print (A, B, C, str(Omega))
-- 
GitLab