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