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