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