Salome HOME
Added a test for invalid parameters
[samples/genericsolver.git] / src / GENERICSOLVER / DEVIATION.py
1 #  Copyright (C) 2009-2010 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 #  $Id$
20 #
21
22 import logging
23 import threading
24 import inspect
25 import traceback
26
27 import salome
28 import GENERICSOLVER_ORB__POA
29 import SALOME_ComponentPy
30 import SALOME_DriverPy
31 import SALOME
32 import SALOME_TYPES
33
34 from salome.kernel.logger import Logger
35 from salome.kernel import termcolor
36 logger = Logger("DEVIATION", color = termcolor.RED_FG)
37 logger.setLevel(logging.INFO)
38
39 VARIABLE_ID = 1030
40
41 ###
42 # Retrieve data from selected case
43 ###
44 def GetDataFromCase( studyId, caseEntry ):
45     theCase = {}
46     study = salome.myStudyManager.GetStudyByID( studyId )
47     case = study.FindObjectID( caseEntry )
48     builder = study.NewBuilder()
49     # Get the values of the variables and make them a list
50     for name in ("E", "F", "L", "I"):
51         var = getSubSObjectByName( studyId, case, name )
52         if var is None:
53             raise Exception('No variable "%s" was found in case "%s" (entry %s). '
54                             'It is probably not a case for the code DEVIATION.' %
55                             (name, case.GetName(), caseEntry))
56         theCase[ name ] = getValueOfVariable( builder, var )
57     return theCase
58
59 ###
60 # Plays with study
61 ###
62
63 def getValueOfVariable( builder, varobj ):
64     attr = builder.FindOrCreateAttribute( varobj, "AttributeLocalID" )
65     objid = attr.Value()
66     if (objid == VARIABLE_ID):
67         attr = builder.FindOrCreateAttribute( varobj, "AttributeReal" )
68         return attr.Value()
69     else:
70         attr = builder.FindOrCreateAttribute( varobj, "AttributeName" )
71         QMessageBox.information( sgPyQt.getDesktop(), 'Info', "Object '%s' isn't a variable. Can't set value." % attr.Value() )
72     return 0.
73
74 def getSubSObjectByName( studyId, sobjFather, childName ):
75     logger.debug("GENERICSOLVER.getSubSObjectByName Looking for sobjet named " + childName)
76     study = salome.myStudyManager.GetStudyByID( studyId )
77     iter = study.NewChildIterator( sobjFather )
78     #builder = study.NewBuilder()
79     while iter.More():
80         sobj = iter.Value()
81         logger.debug("GENERICSOLVER.getSubSObjectByName Got sobjet named " + sobj.GetName())
82         if sobj.GetName() == childName:
83             return sobj
84         iter.Next()
85         pass
86     return None
87
88 ################################################
89
90 class DEVIATION(GENERICSOLVER_ORB__POA.DEVIATION_Gen,
91                 SALOME_ComponentPy.SALOME_ComponentPy_i,
92                 SALOME_DriverPy.SALOME_DriverPy_i):
93     
94     lock = threading.Lock()
95     
96     """
97         Pour etre un composant SALOME cette classe Python
98         doit avoir le nom du composant et heriter de la
99         classe DEVIATION_Gen issue de la compilation de l'idl
100         par omniidl et de la classe SALOME_ComponentPy_i
101         qui porte les services generaux d'un composant SALOME
102     """
103     def __init__ ( self, orb, poa, contID, containerName, instanceName, 
104                    interfaceName ):
105         logger.info("__init__: " + containerName + ' ; ' + instanceName)
106         SALOME_ComponentPy.SALOME_ComponentPy_i.__init__(self, orb, poa,
107                     contID, containerName, instanceName, interfaceName, 0)
108         SALOME_DriverPy.SALOME_DriverPy_i.__init__(self, interfaceName)
109         # On stocke dans l'attribut _naming_service, une reference sur
110         # le Naming Service CORBA
111         self._naming_service = SALOME_ComponentPy.SALOME_NamingServicePy_i( self._orb )
112         self.deterministicValues = {}
113
114 ######################################################################
115 # This is the Wrapper part of the GENERICSOLVER module, ie
116 # the three following methods are used by generic controlling
117 # modules like OpenTURNS in order to launch a computation.
118 # The interface is declared in GENERICSOLVER_Gen.idl. The methods
119 # are free to call the legacy interface (see below).
120 ######################################################################
121
122     def _raiseSalomeError(self):
123         message = "Error in component %s running in container %s." % (self._instanceName, self._containerName)
124         logger.exception(message)
125         message += " " + traceback.format_exc()
126         exc = SALOME.ExceptionStruct(SALOME.INTERNAL_ERROR, message,
127                                      inspect.stack()[1][1], inspect.stack()[1][2])
128         raise SALOME.SALOME_Exception(exc)
129
130     def Init(self, studyId, detCaseEntry):
131         """
132         This method is an example for the initialization of a computation component for
133         use with OpenTURNS in SALOME 5.1.5 and later (for YACS integration)
134         """
135         try:
136             logger.info("Init: " + self._containerName + ' ; ' + self._instanceName)
137             DEVIATION.lock.acquire()
138             salome.salome_init()
139             DEVIATION.lock.release()
140
141             self.deterministicValues = GetDataFromCase(studyId, detCaseEntry)
142             logger.debug("deterministic values: %s" % self.deterministicValues)
143         except:
144             self._raiseSalomeError()
145
146     def Exec(self, paramInput):
147         """
148         This method is an example for the execution of a computation component for
149         use with OpenTURNS in SALOME 5.1.5 and later (for YACS integration)
150         """
151         try:
152             logger.info("Exec: " + self._containerName + ' ; ' + self._instanceName)
153             logger.debug("inputVarList: %s" % paramInput.inputVarList)
154             logger.debug("outputVarList: %s" % paramInput.outputVarList)
155             logger.debug("inputValues: %s" % paramInput.inputValues)
156             if len(paramInput.inputValues) != len(paramInput.inputVarList):
157                 raise Exception("Size mismatch between inputVarList and point to evaluate")
158
159             evalPoint = self.deterministicValues
160             for i in range(len(paramInput.inputVarList)):
161                 evalPoint[paramInput.inputVarList[i]] = paramInput.inputValues[i][0][0]
162             logger.debug("evalPoint = %s" % evalPoint)
163             
164             # Test for an invalid parameter and return an error in this case
165             if evalPoint["L"] <= 0:
166                 return SALOME_TYPES.ParametricOutput(
167                         outputValues = [],
168                         specificOutputInfos = [],
169                         returnCode = 1,
170                         errorMessage = "Invalid value: L must be positive")
171
172             resDict = {}
173             resDict["dev"] = self.BeamModel(**evalPoint)
174
175             outputValues = []
176             for outputVar in paramInput.outputVarList:
177                 outputValues.append([[resDict[outputVar]]])
178             logger.debug("paramOutput: %s" % outputValues)
179             return SALOME_TYPES.ParametricOutput(outputValues,
180                                                  specificOutputInfos = [],
181                                                  returnCode = 0,
182                                                  errorMessage = "")
183         except:
184             self._raiseSalomeError()
185
186     def Finalize(self):
187         """
188         This method is an implementation for the DEVIATION interface.
189         It cleans everything set so far.
190         """
191         try:
192             logger.info("Finalize: " + self._containerName + ' ; ' + self._instanceName)
193         except:
194             self._raiseSalomeError()
195         
196 ######################################################################
197 # This is the computation part of the GENERICSOLVER module, ie
198 # the following method realizes what the solver is intended to do.
199 # The interface of this method (and maybe other ones) is absolutely
200 # free and depends on the module (legacy interface).
201 ######################################################################
202
203     def BeamModel(self, E, F, L, I):
204        """
205        This method implements a beam bending model based on the following formula:
206        deviation = ( Force * Length^3 ) / ( 3 * YoungModulus * InertiaSection )
207        """
208        d = (F * L * L * L) / (3. * E * I)
209        logger.debug("BeamModel (E=%g, F=%g, L=%g, I=%g) = %g" % (E, F, L, I, d))
210        return d