1 # Copyright (C) 2012 EDF
3 # This file is part of SALOME PARAMETRIC module.
5 # SALOME PARAMETRIC module is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Lesser General Public License as published by
7 # the Free Software Foundation, either version 3 of the License, or
8 # (at your option) any later version.
10 # SALOME PARAMETRIC module is distributed in the hope that it will be useful,
11 # but WITHOUT ANY WARRANTY; without even the implied warranty of
12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 # GNU Lesser General Public License for more details.
15 # You should have received a copy of the GNU Lesser General Public License
16 # along with SALOME PARAMETRIC module. If not, see <http://www.gnu.org/licenses/>.
27 import SALOME_ModuleCatalog
28 import PARAMETRIC_ORB__POA
29 from SALOME_ComponentPy import SALOME_ComponentPy_i
30 from SALOME_DriverPy import SALOME_DriverPy_i
35 from salome.kernel.logger import Logger
36 from salome.kernel import termcolor
37 logger = Logger("PARAMETRIC", color = termcolor.BLUE)
38 logger.setLevel(logging.DEBUG)
40 from salome.parametric.study import ParametricStudyEditor
42 class PARAMETRIC(PARAMETRIC_ORB__POA.PARAMETRIC_Gen, SALOME_ComponentPy_i, SALOME_DriverPy_i):
44 lock = threading.Lock()
46 def __init__(self, orb, poa, contID, containerName, instanceName, interfaceName):
47 SALOME_ComponentPy_i.__init__(self, orb, poa, contID, containerName, instanceName, interfaceName, 0)
48 SALOME_DriverPy_i.__init__(self, interfaceName)
49 self.salome_runtime = None
50 self.session_catalog = None
52 def _raiseSalomeError(self):
53 message = "Error in component %s running in container %s." % (self._instanceName, self._containerName)
54 logger.exception(message)
55 message += " " + traceback.format_exc()
56 exc = SALOME.ExceptionStruct(SALOME.INTERNAL_ERROR, message,
57 inspect.stack()[1][1], inspect.stack()[1][2])
58 raise SALOME.SALOME_Exception(exc)
60 def _get_salome_runtime(self):
61 if self.salome_runtime is None:
62 # Initialize runtime for YACS
63 SALOMERuntime.RuntimeSALOME.setRuntime()
64 self.salome_runtime = SALOMERuntime.getSALOMERuntime()
65 mc = salome.naming_service.Resolve('/Kernel/ModulCatalog')
67 raise Exception ("Internal error: Cannot find SALOME Module Catalog")
68 ior = salome.orb.object_to_string(mc)
69 self.session_catalog = self.salome_runtime.loadCatalog("session", ior)
70 self.salome_runtime.addCatalog(self.session_catalog)
71 return self.salome_runtime
73 def _parse_entry(self, selected_value):
75 Find entry if selected_value is something like "name (entry)"
77 entry = selected_value
78 match = re.search("\((.*)\)$", entry)
80 entry = match.group(1)
83 def RunStudy(self, studyId, caseEntry):
85 self.beginService("PARAMETRIC.RunStudy")
87 PARAMETRIC.lock.acquire()
89 PARAMETRIC.lock.release()
91 # Get parametric study from the case in Salome study
92 ed = ParametricStudyEditor(studyId)
93 param_study = ed.get_parametric_study(caseEntry)
95 # Generate YACS schema
96 runtime = self._get_salome_runtime()
97 proc = pilot.Proc("ParametricSchema")
98 param_input_tc = runtime.getTypeCode("SALOME_TYPES/ParametricInput")
99 if param_input_tc is None:
100 raise Exception ("Internal error: No typecode found for type 'SALOME_TYPES/ParametricInput'")
101 foreach = pilot.ForEachLoop("ForEach", param_input_tc)
102 foreach.edGetNbOfBranchesPort().edInit(param_study.nb_parallel_computations)
103 proc.edAddChild(foreach)
105 solver_code = param_study.salome_component_name
106 solver_compo_inst = proc.createComponentInstance(solver_code)
107 solver_compo_def = self.session_catalog._componentMap[solver_code]
109 distrib_container = proc.createContainer("DistribContainer")
110 distrib_container.setProperty("hostname", "localhost")
111 solver_compo_inst.setContainer(distrib_container)
113 init_solver = solver_compo_def._serviceMap["Init"].clone(None)
114 init_solver.setComponent(solver_compo_inst)
115 init_solver.getInputPort("studyID").edInit(studyId)
116 entry = self._parse_entry(param_study.solver_case_entry)
117 init_solver.getInputPort("detCaseEntry").edInit(entry)
118 foreach.edSetInitNode(init_solver)
120 exec_solver = solver_compo_def._serviceMap["Exec"].clone(None)
121 exec_solver.setComponent(solver_compo_inst)
122 foreach.edSetNode(exec_solver)
124 finalize_solver = solver_compo_def._serviceMap["Finalize"].clone(None)
125 finalize_solver.setComponent(solver_compo_inst)
126 foreach.edSetFinalizeNode(finalize_solver)
128 param_output_tc = runtime.getTypeCode("SALOME_TYPES/ParametricOutput")
129 if param_output_tc is None:
130 raise Exception ("Internal error: No typecode found for type 'SALOME_TYPES/ParametricOutput'")
131 seq_param_output_tc = proc.createSequenceTc("", "seq_param_output", param_output_tc)
132 aggregator = runtime.createScriptNode(SALOMERuntime.PythonNode.KIND, "Aggregator")
133 aggregator_input_port = aggregator.edAddInputPort("results", seq_param_output_tc)
134 proc.edAddChild(aggregator)
136 #proc.edAddLink(init_data_output_port, foreach.edGetSeqOfSamplesPort())
137 proc.edAddLink(foreach.edGetSamplePort(), exec_solver.getInputPort("paramInput"))
138 proc.edAddCFLink(foreach, aggregator)
139 proc.edAddLink(exec_solver.getOutputPort("paramOutput"), aggregator_input_port)
142 if param_study.data is None:
143 param_study.generate_data()
146 refsample = {"inputVarList": [],
148 "inputValues": [[[]]],
149 "specificParameters": [],
151 for varname in param_study.output_vars:
152 refsample["outputVarList"].append(varname)
154 for i in range(param_study.datasize):
155 sample = copy.deepcopy(refsample)
156 for var in param_study.input_vars:
157 sample["inputVarList"].append(var.name)
158 sample["inputValues"][0][0].append([param_study.data[var.name][i]])
159 seqsamples.append(sample)
160 foreach.edGetSeqOfSamplesPort().edInitPy(seqsamples)
162 logger.debug("Checking validity...")
163 if not proc.isValid():
164 raise Exception("The schema is not valid and can not be executed.")
166 logger.debug("Checking consistency...")
167 info = pilot.LinkInfo(pilot.LinkInfo.ALL_DONT_STOP)
168 proc.checkConsistency(info)
169 if info.areWarningsOrErrors():
170 logger.error(info.getGlobalRepr())
171 raise Exception("The schema is not consistent and can not be executed.")
172 logger.debug("Schema validated")
175 executor = pilot.ExecutorSwig()
177 if proc.getEffectiveState() != pilot.DONE:
178 msg = proc.getErrorReport()
180 raise Exception("YACS schema execution ended with errors:\n%s" % msg)
182 raise Exception("YACS schema execution failed. No error report available.")
185 seqresults = aggregator.getInputPort("results").getPyObj()
186 for varname in param_study.output_vars:
187 param_study.data[varname] = []
188 param_study.data["__ERROR_MESSAGE__"] = []
190 for result in seqresults:
191 if result["returnCode"] == 0:
192 valuelist = result["outputValues"][0][0]
193 if len(valuelist) != len(param_study.output_vars):
194 raise Exception("Incoherent number of result variables")
195 for i in range(len(valuelist)):
196 param_study.data[param_study.output_vars[i]].append(valuelist[i][0])
197 param_study.data["__ERROR_MESSAGE__"].append(None)
199 for varname in param_study.output_vars:
200 param_study.data[varname].append(None)
201 param_study.data["__ERROR_MESSAGE__"].append(result["errorMessage"])
203 # Save results in Salome study
204 ed.set_parametric_study_at_entry(param_study, caseEntry)
206 self.endService("PARAMETRIC.RunStudy")
208 self._raiseSalomeError()