Salome HOME
Added examples of services using variable lists
[samples/genericsolver.git] / src / GENERICSOLVER / GENERICSOLVER.py
1 #  Copyright (C) 2007-2010  CEA/DEN, EDF R&D, OPEN CASCADE
2 #
3 #  Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 #  CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
5 #
6 #  This library is free software; you can redistribute it and/or
7 #  modify it under the terms of the GNU Lesser General Public
8 #  License as published by the Free Software Foundation; either
9 #  version 2.1 of the License.
10 #
11 #  This library is distributed in the hope that it will be useful,
12 #  but WITHOUT ANY WARRANTY; without even the implied warranty of
13 #  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 #  Lesser General Public License for more details.
15 #
16 #  You should have received a copy of the GNU Lesser General Public
17 #  License along with this library; if not, write to the Free Software
18 #  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
19 #
20 #  See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
21 #
22 #  $Id$
23 #
24
25 import logging
26 import threading
27 import inspect
28
29 import salome
30 import GENERICSOLVER_ORB__POA
31 import SALOME_ComponentPy
32 import SALOME_DriverPy
33 import SALOME
34
35 from pal.logger import Logger
36 from pal import termcolor
37 logger = Logger("GENERICSOLVER", color = termcolor.BLUE_FG)
38 logger.setLevel(logging.INFO)
39
40 VARIABLE_ID = 1030
41
42 ###
43 # Retrieve data from selected case
44 ###
45 def GetDataFromCase( studyId, caseEntry ):
46     theCase = {}
47     study = salome.myStudyManager.GetStudyByID( studyId )
48     case = study.FindObjectID( caseEntry )
49     builder = study.NewBuilder()
50     # Get the values of the variables and make them a list
51     for name in ("E", "F", "L", "I"):
52         var = getSubSObjectByName( studyId, case, name )
53         if var == None:
54             logger.error("GENERICSOLVER.GetDataFromCase : ERROR! no variable '%s'" % name)
55             break
56         theCase[ name ] = getValueOfVariable( builder, var )
57     return theCase
58
59 ###
60 # Add some variable to the case
61 ###
62 def AddDataToCase( studyId, caseEntry, varName, varValue ):
63     study = salome.myStudyManager.GetStudyByID( studyId )
64     case = study.FindObjectID( caseEntry )
65     builder = study.NewBuilder()
66     var = addObjectInStudy( builder, case, varName, VARIABLE_ID )
67     setValueToVariable( builder, var, varValue )
68     sg.updateObjBrowser( True )
69     pass
70
71 ###
72 # Plays with study
73 ###
74 def addObjectInStudy( builder, father, objname, objid ):
75     obj = getSubSObjectByName( father, objname )
76     if obj is None:
77         obj  = builder.NewObject( father )
78         attr = builder.FindOrCreateAttribute( obj, "AttributeName" )
79         attr.SetValue( objname )
80         attr = builder.FindOrCreateAttribute( obj, "AttributeLocalID" )
81         attr.SetValue( objid )
82     return obj
83
84 def setValueToVariable( builder, varobj, value ):
85     attr = builder.FindOrCreateAttribute( varobj, "AttributeLocalID" )
86     objid = attr.Value()
87     if (objid == VARIABLE_ID):
88         attr = builder.FindOrCreateAttribute( varobj, "AttributeReal" )
89         attr.SetValue( value )
90     else:
91         attr = builder.FindOrCreateAttribute( varobj, "AttributeName" )
92         QMessageBox.information( sgPyQt.getDesktop(), 'Info', "Object '%s' isn't a variable. Can't set value." % attr.Value() )
93     pass
94
95 def getValueOfVariable( builder, varobj ):
96     attr = builder.FindOrCreateAttribute( varobj, "AttributeLocalID" )
97     objid = attr.Value()
98     if (objid == VARIABLE_ID):
99         attr = builder.FindOrCreateAttribute( varobj, "AttributeReal" )
100         return attr.Value()
101     else:
102         attr = builder.FindOrCreateAttribute( varobj, "AttributeName" )
103         QMessageBox.information( sgPyQt.getDesktop(), 'Info', "Object '%s' isn't a variable. Can't set value." % attr.Value() )
104     return 0.
105
106 def getSubSObjectByName( studyId, sobjFather, childName ):
107     logger.debug("GENERICSOLVER.getSubSObjectByName Looking for sobjet named " + childName)
108     study = salome.myStudyManager.GetStudyByID( studyId )
109     iter = study.NewChildIterator( sobjFather )
110     #builder = study.NewBuilder()
111     while iter.More():
112         sobj = iter.Value()
113         logger.debug("GENERICSOLVER.getSubSObjectByName Got sobjet named " + sobj.GetName())
114         if sobj.GetName() == childName:
115             return sobj
116         iter.Next()
117         pass
118     return None
119
120 ################################################
121
122 class GENERICSOLVER(GENERICSOLVER_ORB__POA.GENERICSOLVER_Gen,
123                     SALOME_ComponentPy.SALOME_ComponentPy_i,
124                     SALOME_DriverPy.SALOME_DriverPy_i):
125     
126     lock = threading.Lock()
127     
128     """
129         Pour etre un composant SALOME cette classe Python
130         doit avoir le nom du composant et heriter de la
131         classe GENERICSOLVER_Gen issue de la compilation de l'idl
132         par omniidl et de la classe SALOME_ComponentPy_i
133         qui porte les services generaux d'un composant SALOME
134     """
135     def __init__ ( self, orb, poa, contID, containerName, instanceName, 
136                    interfaceName ):
137         logger.info("GENERICSOLVER.__init__: " + containerName + ' ; ' + instanceName)
138         SALOME_ComponentPy.SALOME_ComponentPy_i.__init__(self, orb, poa,
139                     contID, containerName, instanceName, interfaceName, 0)
140         SALOME_DriverPy.SALOME_DriverPy_i.__init__(self, interfaceName)
141         # On stocke dans l'attribut _naming_service, une reference sur
142         # le Naming Service CORBA
143         self._naming_service = SALOME_ComponentPy.SALOME_NamingServicePy_i( self._orb )
144         self.case = None
145         self.wrapperDescription = ""
146
147 ######################################################################
148 # This is the Wrapper part of the GENERICSOLVER module, ie
149 # the three following methods are used by generic controlling
150 # modules like OpenTURNS in order to launch a computation.
151 # The interface is declared in GENERICSOLVER_Gen.idl. The methods
152 # are free to call the legacy interface (see below).
153 ######################################################################
154
155     def _raiseSalomeError(self):
156         message = "Error in %s.%s" % (self.__class__.__name__, inspect.stack()[1][3])
157         logger.exception(message)
158         message += ". See logs of container %s for more details." % self._containerName
159         exc = SALOME.ExceptionStruct(SALOME.INTERNAL_ERROR, message,
160                                      inspect.stack()[1][1], inspect.stack()[1][2])
161         raise SALOME.SALOME_Exception(exc)
162
163     def Init ( self, studyId, caseEntry, wrapperDescription ):
164         """
165         This method is an implementation for the GENERICSOLVER interface.
166         It sets the component with some deterministic parametrization.
167         """
168         try:
169             logger.info("GENERICSOLVER.Init: " + self._containerName + ' ; ' + self._instanceName)
170             logger.debug("GENERICSOLVER.Init : enter")
171             logger.debug("GENERICSOLVER.Init : studyId = %d - caseEntry = %s - wrapperDescription = %s" % ( studyId, caseEntry, wrapperDescription ))
172             self.wrapperDescription = wrapperDescription
173             GENERICSOLVER.lock.acquire()
174             salome.salome_init()
175             GENERICSOLVER.lock.release()
176         
177             self.case = GetDataFromCase( studyId, caseEntry )
178             if self.case is None:
179                 return 1
180             logger.debug("GENERICSOLVER.Init : exit")
181             return 0
182         except:
183             self._raiseSalomeError()
184
185     def Exec ( self , inPoint ):
186         """
187         This method is an implementation for the GENERICSOLVER interface.
188         It runs the component with some new parameters compared with the deterministic ones.
189         """
190         try:
191             logger.info("GENERICSOLVER.Exec: " + self._containerName + ' ; ' + self._instanceName)
192             if self.case is None :
193                 logger.error("GENERICSOLVER.Exec : Init not run")
194                 return 1, None
195         
196             logger.debug("GENERICSOLVER.Exec (1): inPoint  = %s" % inPoint)
197             case = dict( self.case )
198             if self.wrapperDescription != "":
199                 import sys
200                 logger.debug("sys.path = %s" % sys.path)
201                 import openturns.wrapper
202                 wrapper = openturns.wrapper.WrapperFile.BuildWrapperFromStream( self.wrapperDescription )
203                 data = wrapper.getWrapperData()
204                 variableList = data.getVariableList()
205                 i = 0
206                 for idx in range( variableList.getSize() ):
207                     variable = variableList[ idx ]
208                     if variable.type_ == 0:
209                         logger.debug("variable %s <-> index %d" % ( variable.id_, i ))
210                         case[ variable.id_ ] = inPoint[ i ]
211                         i += 1
212
213             logger.debug("Case = %s" % case)
214             logger.info("Evaluating case by component %s in container %s" %
215                         (self._instanceName, self._containerName))
216             outPoint = self.BeamModel( **case )
217
218             logger.debug("GENERICSOLVER.Exec (2): inPoint  = %s" % inPoint)
219             logger.debug("GENERICSOLVER.Exec (2): outPoint = %s" % outPoint)
220             return 0, outPoint
221
222         except:
223             self._raiseSalomeError()
224
225     def Finalize ( self ):
226         """
227         This method is an implementation for the GENERICSOLVER interface.
228         It cleans everything set so far.
229         """
230         try:
231             logger.info("GENERICSOLVER.Finalize: " + self._containerName + ' ; ' + self._instanceName)
232             logger.debug("GENERICSOLVER.Finalize : enter")
233             logger.debug("GENERICSOLVER.Finalize : exit")
234             return 0
235         except:
236             self._raiseSalomeError()
237         
238 ######################################################################
239 # This is the computation part of the GENERICSOLVER module, ie
240 # the following method realizes what the solver is intended to do.
241 # The interface of this method (and maybe other ones) is absolutely
242 # free and depends on the module (legacy interface).
243 ######################################################################
244
245     def BeamModel ( self , E=1., F=0., L=0., I=1. ):
246        """
247        This method implements a beam bending model based on the following formula:
248        deviation = ( Force * Length^3 ) / ( 3 * YoungModulus * InertiaSection )
249        """
250        d = ( F * L*L*L ) / ( 3. * E * I )
251        logger.debug("GENERICSOLVER.BeamModel (E=%g, F=%g, L=%g, I=%g) = %g" % (E,F,L,I,d))
252
253        return (d,)
254
255
256
257     def InitWithVarList(self, inputVarList, outputVarList, deterministicVars):
258         """
259         This method is an example for the initialization of a computation component for
260         use with OpenTURNS in SALOME 5.1.5 and later (for YACS integration)
261         """
262         try:
263             logger.info("GENERICSOLVER.InitWithVarList: " + self._containerName +
264                         ' ; ' + self._instanceName)
265             import cPickle
266             self.inputVarList = inputVarList
267             self.outputVarList = outputVarList
268             self.evalPoint = cPickle.loads(deterministicVars)
269             logger.debug("inputVarList: %s" % self.inputVarList)
270             logger.debug("outputVarList: %s" % self.outputVarList)
271             logger.debug("evalPoint: %s" % self.evalPoint)
272         except:
273             self._raiseSalomeError()
274
275     def ExecWithVarList(self, inPoint):
276         """
277         This method is an example for the execution of a computation component for
278         use with OpenTURNS in SALOME 5.1.5 and later (for YACS integration)
279         """
280         try:
281             logger.info("GENERICSOLVER.ExecWithVarList: " + self._containerName +
282                         ' ; ' + self._instanceName)
283             if self.inputVarList is None:
284                 raise Exception("InitWithVarList not run")
285             if len(inPoint) != len(self.inputVarList):
286                 raise Exception("Size mismatch between inputVarList and point to evaluate")
287
288             logger.debug("GENERICSOLVER.ExecWithVarList (1): inPoint  = %s" % inPoint)
289             for i in range(len(self.inputVarList)):
290                 self.evalPoint[self.inputVarList[i]] = inPoint[i]
291             logger.debug("evalPoint = %s" % self.evalPoint)
292
293             (dev,) = self.BeamModel(**self.evalPoint)
294
295             outPoint = []
296             for outputVar in self.outputVarList:
297                 outPoint.append(eval(outputVar))
298             logger.debug("GENERICSOLVER.ExecWithVarList (2): outPoint = %s" % outPoint)
299             return outPoint
300         except:
301             self._raiseSalomeError()