Salome HOME
Merge from V6_main 01/04/2013
[modules/yacs.git] / src / runtime / SalomeOptimizerLoop.cxx
1 // Copyright (C) 2006-2013  CEA/DEN, EDF R&D
2 //
3 // This library is free software; you can redistribute it and/or
4 // modify it under the terms of the GNU Lesser General Public
5 // License as published by the Free Software Foundation; either
6 // version 2.1 of the License.
7 //
8 // This library is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11 // Lesser General Public License for more details.
12 //
13 // You should have received a copy of the GNU Lesser General Public
14 // License along with this library; if not, write to the Free Software
15 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
16 //
17 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
18 //
19
20 #include "SalomeOptimizerLoop.hxx"
21
22 // rnv: avoid compilation warning on Linux : "_POSIX_C_SOURCE" and "_XOPEN_SOURCE" are redefined
23 #ifdef _POSIX_C_SOURCE
24 #undef _POSIX_C_SOURCE
25 #endif
26
27 #ifdef _XOPEN_SOURCE
28 #undef _XOPEN_SOURCE
29 #endif
30 #include <Python.h>
31 #include "TypeCode.hxx"
32 #include "PyStdout.hxx"
33
34 //#define _DEVDEBUG_
35 #include "YacsTrace.hxx"
36
37 using namespace YACS::ENGINE;
38 using namespace std;
39
40
41 /*! \class YACS::ENGINE::SalomeOptimizerLoop
42  *  \brief class to build optimization loops
43  *
44  * \ingroup Nodes
45  */
46
47 SalomeOptimizerLoop::SalomeOptimizerLoop(const std::string& name, const std::string& algLibWthOutExt,
48                                          const std::string& symbolNameToOptimizerAlgBaseInstanceFactory,
49                                          bool algInitOnFile,bool initAlgo, Proc * procForTypes):
50                      OptimizerLoop(name,algLibWthOutExt,symbolNameToOptimizerAlgBaseInstanceFactory,algInitOnFile,false)
51 {
52   if(initAlgo)
53     {
54       //try
55       //  {
56           setAlgorithm(algLibWthOutExt, symbolNameToOptimizerAlgBaseInstanceFactory, true, procForTypes);
57       //  }
58       //catch(YACS::Exception& e)
59       //  {
60           //ignore it
61       //  }
62     }
63 }
64
65 SalomeOptimizerLoop::SalomeOptimizerLoop(const SalomeOptimizerLoop& other, ComposedNode *father, bool editionOnly): 
66                      OptimizerLoop(other,father,editionOnly)
67 {
68 }
69
70 SalomeOptimizerLoop::~SalomeOptimizerLoop()
71 {
72 }
73
74 Node *SalomeOptimizerLoop::simpleClone(ComposedNode *father, bool editionOnly) const
75 {
76   SalomeOptimizerLoop* sol=new SalomeOptimizerLoop(*this,father,editionOnly);
77   // TODO: Remove this const_cast (find a better design to get the type codes from the original node)
78   Proc * procForTypes = sol->getProc();
79   if (procForTypes == NULL) {
80     const Proc * origProc = getProc();
81     procForTypes = const_cast<Proc *>(origProc);
82   }
83   sol->setAlgorithm(_alglib, _symbol, false, procForTypes);
84   return sol;
85 }
86
87 //! Load the algorithm object from a Python module or a dynamic library
88 /*!
89  *  Member _alglib is the library name (shared library WITHOUT extension .so or python
90  *  module WITH extension .py). Member _symbol is a symbol name in the library to use as
91  *  an algorithm factory.
92  */
93 void SalomeOptimizerLoop::loadAlgorithm()
94 {
95   YASSERT(_alg == NULL)
96
97   if(_alglib.size() > 3 && _alglib.substr(_alglib.size()-3,3)==".py")
98     {
99       //if alglib extension is .py try to import the corresponding python module
100       PyGILState_STATE gstate=PyGILState_Ensure();
101
102       PyObject* mainmod = PyImport_AddModule("__main__");
103       PyObject* globals = PyModule_GetDict(mainmod);
104
105       std::string pyscript;
106       pyscript="import sys\n"
107                "import SALOMERuntime\n"
108                "filename='";
109       pyscript=pyscript+_alglib+"'\nentry='"+_symbol+"'\n";
110       pyscript=pyscript+"import os\n"
111                         "import pilot\n"
112                         "rep,mod=os.path.split(os.path.splitext(filename)[0])\n"
113                         "if rep != '':\n"
114                         "  sys.path.insert(0,rep)\n"
115                         "algomodule=__import__(mod)\n"
116                         "if rep != '':\n"
117                         "  del sys.path[0]\n"
118                         "algoclass= getattr(algomodule,entry)\n"
119                         "algo= algoclass()\n"
120                         "swigalgo= algo.this\n"
121                         "\n";
122
123       PyObject* res=PyRun_String(pyscript.c_str(), Py_file_input, globals, globals );
124
125       if(res == NULL)
126         {
127           //error during import
128           _errorDetails="";
129           PyObject* new_stderr = newPyStdOut(_errorDetails);
130           PySys_SetObject((char*)"stderr", new_stderr);
131           PyErr_Print();
132           PySys_SetObject((char*)"stderr", PySys_GetObject((char*)"__stderr__"));
133           Py_DECREF(new_stderr);
134           modified();
135           PyGILState_Release(gstate);
136           throw YACS::Exception(_errorDetails);
137         }
138       else
139         {
140           Py_DECREF(res);
141
142           typedef struct {
143               PyObject_HEAD
144               void *ptr;
145               void *ty;
146               int own;
147               PyObject *next;
148           } SwigPyObject;
149
150           SwigPyObject* pyalgo = (SwigPyObject*)PyDict_GetItemString(globals, "swigalgo");
151           _alg=(OptimizerAlgBase*)pyalgo->ptr;
152           _alg->setPool(&_myPool);
153           _alg->incrRef();
154         }
155       PyGILState_Release(gstate);
156     }
157   else
158     {
159       //else try to load a dynamic library
160       OptimizerLoop::loadAlgorithm();
161     }
162 }