1 # Copyright (C) 2009-2021 EDF R&D
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, or (at your option) any later version.
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.
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
17 # See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
27 from salome.gui.helper import sgPyQt
28 from salome.kernel import termcolor
29 from salome.kernel.logger import Logger
30 from salome.kernel.parametric.compo_utils import \
31 create_input_dict, create_normal_parametric_output, create_error_parametric_output
32 import GENERICSOLVER_ORB__POA
34 import SALOME_ComponentPy
35 import SALOME_DriverPy
36 import SALOME_Embedded_NamingService_ClientPy
41 logger = Logger("DEVIATION", color=termcolor.RED_FG)
42 logger.setLevel(logging.INFO)
48 # Retrieve data from selected case
50 def GetDataFromCase( studyId, caseEntry ):
52 study = salome.myStudyManager.GetStudyByID( studyId )
53 case = study.FindObjectID( caseEntry )
54 builder = study.NewBuilder()
55 # Get the values of the variables and make them a list
56 for name in ("E", "F", "L", "I"):
57 var = getSubSObjectByName( studyId, case, name )
59 raise Exception('No variable "%s" was found in case "%s" (entry %s). '
60 'It is probably not a case for the code DEVIATION.' %
61 (name, case.GetName(), caseEntry))
62 theCase[ name ] = getValueOfVariable( builder, var )
69 def getValueOfVariable( builder, varobj ):
70 attr = builder.FindOrCreateAttribute( varobj, "AttributeLocalID" )
72 if (objid == VARIABLE_ID):
73 attr = builder.FindOrCreateAttribute( varobj, "AttributeReal" )
76 attr = builder.FindOrCreateAttribute( varobj, "AttributeName" )
77 QMessageBox.information( sgPyQt.getDesktop(), 'Info', "Object '%s' isn't a variable. Can't set value." % attr.Value() )
80 def getSubSObjectByName( studyId, sobjFather, childName ):
81 logger.debug("GENERICSOLVER.getSubSObjectByName Looking for sobjet named " + childName)
82 study = salome.myStudyManager.GetStudyByID( studyId )
83 iterator = study.NewChildIterator(sobjFather)
84 #builder = study.NewBuilder()
85 while iterator.More():
86 sobj = iterator.Value()
87 logger.debug("GENERICSOLVER.getSubSObjectByName Got sobjet named " + sobj.GetName())
88 if sobj.GetName() == childName:
94 ################################################
96 class DEVIATION(GENERICSOLVER_ORB__POA.DEVIATION_Gen,
97 SALOME_ComponentPy.SALOME_ComponentPy_i,
98 SALOME_DriverPy.SALOME_DriverPy_i):
100 lock = threading.Lock()
103 Pour etre un composant SALOME cette classe Python
104 doit avoir le nom du composant et heriter de la
105 classe DEVIATION_Gen issue de la compilation de l'idl
106 par omniidl et de la classe SALOME_ComponentPy_i
107 qui porte les services generaux d'un composant SALOME
109 def __init__ ( self, orb, poa, contID, containerName, instanceName,
111 logger.info("__init__: " + containerName + ' ; ' + instanceName)
112 SALOME_ComponentPy.SALOME_ComponentPy_i.__init__(self, orb, poa,
113 contID, containerName, instanceName, interfaceName, False)
114 SALOME_DriverPy.SALOME_DriverPy_i.__init__(self, interfaceName)
115 # On stocke dans l'attribut _naming_service, une reference sur
116 # le Naming Service CORBA
117 #self._naming_service = SALOME_ComponentPy.SALOME_NamingServicePy_i( self._orb )
119 emb_ns = self._contId.get_embedded_NS_if_ssl()
121 if CORBA.is_nil(emb_ns):
122 self._naming_service = SALOME_ComponentPy.SALOME_NamingServicePy_i( self._orb )
124 self._naming_service = SALOME_Embedded_NamingService_ClientPy.SALOME_Embedded_NamingService_ClientPy(emb_ns)
126 self.deterministicValues = {}
128 ######################################################################
129 # This is the Wrapper part of the GENERICSOLVER module, ie
130 # the three following methods are used by generic controlling
131 # modules like OpenTURNS in order to launch a computation.
132 # The interface is declared in GENERICSOLVER_Gen.idl. The methods
133 # are free to call the legacy interface (see below).
134 ######################################################################
136 def _raiseSalomeError(self):
137 message = "Error in component %s running in container %s." % (self._instanceName, self._containerName)
138 logger.exception(message)
139 message += " " + traceback.format_exc()
140 exc = SALOME.ExceptionStruct(SALOME.INTERNAL_ERROR, message,
141 inspect.stack()[1][1], inspect.stack()[1][2])
142 raise SALOME.SALOME_Exception(exc)
144 def _getIdMessage(self):
145 return "%s in container %s running on %s, process %d, thread %d" % \
146 (self._instanceName, self._containerName,
147 platform.node(), os.getpid(), _thread.get_ident())
149 def Init(self, studyId, detCaseEntry):
151 This method is an example for the initialization of a computation component for
152 use with OpenTURNS in SALOME 5.1.5 and later (for YACS integration)
155 logger.info("Init: " + self._getIdMessage())
156 DEVIATION.lock.acquire()
158 DEVIATION.lock.release()
160 self.deterministicValues = GetDataFromCase(studyId, detCaseEntry)
161 logger.debug("deterministic values: %s" % self.deterministicValues)
163 self._raiseSalomeError()
165 def Exec(self, paramInput):
167 This method is an example for the execution of a computation component for
168 use with OpenTURNS in SALOME 5.1.5 and later (for YACS integration)
171 logger.info("Exec: " + self._getIdMessage())
172 logger.debug("inputVarList: %s" % paramInput.inputVarList)
173 logger.debug("outputVarList: %s" % paramInput.outputVarList)
174 logger.debug("inputValues: %s" % paramInput.inputValues)
176 # Get id and execution mode
179 for parameter in paramInput.specificParameters:
180 if parameter.name == "id":
182 if parameter.name == "executionMode":
183 exec_mode = parameter.value
184 logger.debug("ID: %s" % id)
185 logger.debug("Execution mode: %s" % exec_mode)
187 inputDict = create_input_dict(self.deterministicValues, paramInput)
188 logger.debug("inputDict = %s" % inputDict)
190 # Test for an invalid parameter and return an error in this case
191 if inputDict["L"] <= 0:
192 return create_error_parametric_output("Invalid value: L must be positive")
195 outputDict["dev"] = self.BeamModel(**inputDict)
197 paramOutput = create_normal_parametric_output(outputDict, paramInput)
198 logger.debug("outputValues: %s" % paramOutput.outputValues)
201 self._raiseSalomeError()
205 This method is an implementation for the DEVIATION interface.
206 It cleans everything set so far.
209 logger.info("Finalize: " + self._getIdMessage())
211 self._raiseSalomeError()
213 def GetFilesToTransfer(self, studyId, detCaseEntry):
215 This method can be used to specify files to transfer to the
216 computation resource. It is not useful for DEVIATION since it only
217 uses values from Salome study.
220 logger.info("GetFilesToTransfer: " + self._getIdMessage())
223 return (inputFiles, outputFiles)
225 self._raiseSalomeError()
227 ######################################################################
228 # This is the computation part of the GENERICSOLVER module, ie
229 # the following method realizes what the solver is intended to do.
230 # The interface of this method (and maybe other ones) is absolutely
231 # free and depends on the module (legacy interface).
232 ######################################################################
234 def BeamModel(self, E, F, L, I):
236 This method implements a beam bending model based on the following formula:
237 deviation = ( Force * Length^3 ) / ( 3 * YoungModulus * InertiaSection )
239 d = (F * L * L * L) / (3. * E * I)
240 logger.debug("BeamModel (E=%g, F=%g, L=%g, I=%g) = %g" % (E, F, L, I, d))