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
40 logger = Logger("DEVIATION", color=termcolor.RED_FG)
41 logger.setLevel(logging.INFO)
47 # Retrieve data from selected case
49 def GetDataFromCase( studyId, caseEntry ):
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 )
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 )
68 def getValueOfVariable( builder, varobj ):
69 attr = builder.FindOrCreateAttribute( varobj, "AttributeLocalID" )
71 if (objid == VARIABLE_ID):
72 attr = builder.FindOrCreateAttribute( varobj, "AttributeReal" )
75 attr = builder.FindOrCreateAttribute( varobj, "AttributeName" )
76 QMessageBox.information( sgPyQt.getDesktop(), 'Info', "Object '%s' isn't a variable. Can't set value." % attr.Value() )
79 def getSubSObjectByName( studyId, sobjFather, childName ):
80 logger.debug("GENERICSOLVER.getSubSObjectByName Looking for sobjet named " + childName)
81 study = salome.myStudyManager.GetStudyByID( studyId )
82 iterator = study.NewChildIterator(sobjFather)
83 #builder = study.NewBuilder()
84 while iterator.More():
85 sobj = iterator.Value()
86 logger.debug("GENERICSOLVER.getSubSObjectByName Got sobjet named " + sobj.GetName())
87 if sobj.GetName() == childName:
93 ################################################
95 class DEVIATION(GENERICSOLVER_ORB__POA.DEVIATION_Gen,
96 SALOME_ComponentPy.SALOME_ComponentPy_i,
97 SALOME_DriverPy.SALOME_DriverPy_i):
99 lock = threading.Lock()
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
108 def __init__ ( self, orb, poa, contID, containerName, instanceName,
110 logger.info("__init__: " + containerName + ' ; ' + instanceName)
111 SALOME_ComponentPy.SALOME_ComponentPy_i.__init__(self, orb, poa,
112 contID, containerName, instanceName, interfaceName, False)
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 = {}
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 ######################################################################
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)
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())
140 def Init(self, studyId, detCaseEntry):
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)
146 logger.info("Init: " + self._getIdMessage())
147 DEVIATION.lock.acquire()
149 DEVIATION.lock.release()
151 self.deterministicValues = GetDataFromCase(studyId, detCaseEntry)
152 logger.debug("deterministic values: %s" % self.deterministicValues)
154 self._raiseSalomeError()
156 def Exec(self, paramInput):
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)
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)
167 # Get id and execution mode
170 for parameter in paramInput.specificParameters:
171 if parameter.name == "id":
173 if parameter.name == "executionMode":
174 exec_mode = parameter.value
175 logger.debug("ID: %s" % id)
176 logger.debug("Execution mode: %s" % exec_mode)
178 inputDict = create_input_dict(self.deterministicValues, paramInput)
179 logger.debug("inputDict = %s" % inputDict)
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")
186 outputDict["dev"] = self.BeamModel(**inputDict)
188 paramOutput = create_normal_parametric_output(outputDict, paramInput)
189 logger.debug("outputValues: %s" % paramOutput.outputValues)
192 self._raiseSalomeError()
196 This method is an implementation for the DEVIATION interface.
197 It cleans everything set so far.
200 logger.info("Finalize: " + self._getIdMessage())
202 self._raiseSalomeError()
204 def GetFilesToTransfer(self, studyId, detCaseEntry):
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.
211 logger.info("GetFilesToTransfer: " + self._getIdMessage())
214 return (inputFiles, outputFiles)
216 self._raiseSalomeError()
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 ######################################################################
225 def BeamModel(self, E, F, L, I):
227 This method implements a beam bending model based on the following formula:
228 deviation = ( Force * Length^3 ) / ( 3 * YoungModulus * InertiaSection )
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))