1 // Copyright (C) 2012-2015 CEA/DEN, 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
19 // Author : Anthony Geay (EDF R&D)
21 #include "YACSEvalYFXPattern.hxx"
22 #include "YACSEvalResource.hxx"
23 #include "YACSEvalSeqAny.hxx"
24 #include "YACSEvalAutoPtr.hxx"
26 #include "ElementaryNode.hxx"
27 #include "RuntimeSALOME.hxx"
28 #include "InputPort.hxx"
29 #include "LinkInfo.hxx"
30 #include "TypeCode.hxx"
33 #include "PythonPorts.hxx"
34 #include "ForEachLoop.hxx"
35 #include "PythonNode.hxx"
36 #include "InlineNode.hxx"
37 #include "ServiceNode.hxx"
39 #include "ResourcesManager.hxx"
45 const char YACSEvalYFXPattern::DFT_PROC_NAME[]="YFX";
47 const char YACSEvalYFXRunOnlyPattern::GATHER_NODE_NAME[]="__gather__";
49 std::vector< YACSEvalInputPort *> YACSEvalYFXPattern::getFreeInputPorts() const
51 std::size_t sz(_inputs.size());
52 std::vector< YACSEvalInputPort *> ret;
53 std::vector< YACSEvalInputPort >::const_iterator it(_inputs.begin());
54 for(std::size_t i=0;i<sz;i++,it++)
55 ret.push_back(const_cast<YACSEvalInputPort *>(&(*it)));
59 std::vector< YACSEvalOutputPort *> YACSEvalYFXPattern::getFreeOutputPorts() const
61 std::size_t sz(_outputs.size());
62 std::vector< YACSEvalOutputPort *> ret;
63 std::vector< YACSEvalOutputPort >::const_iterator it(_outputs.begin());
64 for(std::size_t i=0;i<sz;i++,it++)
65 ret.push_back(const_cast<YACSEvalOutputPort *>(&(*it)));
69 YACSEvalYFXPattern *YACSEvalYFXPattern::FindPatternFrom(YACS::ENGINE::Proc *scheme, bool ownScheme)
72 throw YACS::Exception("YACSEvalYFXPattern::FindPatternFrom : input scheme must be not null !");
74 YACS::ENGINE::ComposedNode *zeRunNode(0);
75 bool isMatchingRunOnlyPattern(YACSEvalYFXRunOnlyPattern::IsMatching(scheme,zeRunNode));
76 if(isMatchingRunOnlyPattern)
77 return new YACSEvalYFXRunOnlyPattern(scheme,ownScheme,zeRunNode);
79 throw YACS::Exception("YACSEvalYFXPattern::FindPatternFrom : no pattern found for the input scheme !");
82 bool YACSEvalYFXPattern::isAlreadyComputedResources() const
87 void YACSEvalYFXPattern::checkNonAlreadyComputedResources() const
89 if(isAlreadyComputedResources())
90 throw YACS::Exception("checkNonAlreadyComputedResources : instance of computed resources already computed !");
93 void YACSEvalYFXPattern::checkAlreadyComputedResources() const
95 if(!isAlreadyComputedResources())
96 throw YACS::Exception("checkAlreadyComputedResources : instance of computed resources not already computed !");
99 void YACSEvalYFXPattern::checkLocked() const
102 throw YACS::Exception("YACSEvalYFXPattern::checkLocked : Pattern is not locked !");
105 void YACSEvalYFXPattern::checkNonLocked() const
108 throw YACS::Exception("YACSEvalYFXPattern::checkNonLocked : Pattern is locked !");
111 void YACSEvalYFXPattern::CheckNodeIsOK(YACS::ENGINE::ComposedNode *node)
113 /*YACS::ENGINE::LinkInfo info(YACS::ENGINE::LinkInfo::WARN_ONLY_DONT_STOP);
116 node->checkConsistency(info);
118 catch(YACS::Exception& e)
121 if(info.getNumberOfErrLinks(YACS::ENGINE::E_ALL)!=0)
122 throw YACS::Exception("YACSEvalYFXPattern::CheckNodeIsOK : found node is not OK !");
123 std::list<YACS::ENGINE::ElementaryNode *> allNodes(node->getRecursiveConstituents());
124 for(std::list<YACS::ENGINE::ElementaryNode *>::const_iterator it=allNodes.begin();it!=allNodes.end();it++)
126 YACS::ENGINE::ServiceNode *node0(dynamic_cast<YACS::ENGINE::ServiceNode *>(*it));
127 YACS::ENGINE::InlineNode *node1(dynamic_cast<YACS::ENGINE::InlineNode *>(*it));
130 YACS::ENGINE::Container *cont(node0->getContainer());
131 YACS::ENGINE::ComponentInstance *comp(node0->getComponent());
134 std::ostringstream oss; oss << "YACSEvalYFXPattern::CheckNodeIsOK : ServiceNode called \"" << node0->getName() << "\" is not correctly defined !";
135 throw YACS::Exception(oss.str());
140 YACS::ENGINE::Container *cont(node1->getContainer());
141 if(!cont && node1->getExecutionMode()==YACS::ENGINE::InlineNode::REMOTE_STR)
143 std::ostringstream oss; oss << "YACSEvalYFXPattern::CheckNodeIsOK : InlineNode called \"" << node1->getName() << "\" is not correctly defined !";
144 throw YACS::Exception(oss.str());
150 YACSEvalYFXPattern::YACSEvalYFXPattern(YACS::ENGINE::Proc *scheme, bool ownScheme):_scheme(scheme),_ownScheme(ownScheme),_rm(new ResourcesManager_cpp),_res(0)
154 YACS::ENGINE::TypeCode *YACSEvalYFXPattern::createSeqTypeCodeFrom(YACS::ENGINE::Proc *scheme, const std::string& zeType)
156 std::ostringstream oss; oss << "list[" << zeType << "]";
157 YACS::ENGINE::TypeCode *tc(scheme->getTypeCode(zeType));
158 return scheme->createSequenceTc(oss.str(),oss.str(),tc);
161 void YACSEvalYFXPattern::setResources(YACSEvalListOfResources *res)
163 checkNonAlreadyComputedResources();
169 void YACSEvalYFXPattern::resetResources()
175 YACSEvalSeqAny *YACSEvalYFXPattern::BuildValueInPort(YACS::ENGINE::InputPyPort *port)
178 throw YACS::Exception("YACSEvalYFXPattern::GetValueInPort : null input port !");
179 PyObject *obj(port->getPyObj());
180 YACS::ENGINE::TypeCode *tc(port->edGetType());
181 YACS::ENGINE::TypeCodeSeq *tcc(dynamic_cast<YACS::ENGINE::TypeCodeSeq *>(tc));
184 std::ostringstream oss; oss << "YACSEvalYFXPattern::GetValueInPort : internal error for tc of input \"" << port->getName() << "\"";
185 throw YACS::Exception(oss.str());
187 const YACS::ENGINE::TypeCode *tcct(tcc->contentType());
188 if(!PyList_Check(obj))
189 throw YACS::Exception("YACSEvalYFXPattern::GetValueInPort : internal error 2 !");
190 std::size_t sz(PyList_Size(obj));
191 if(tcct->kind()==YACS::ENGINE::Double)
193 std::vector<double> eltCpp(sz);
194 for(std::size_t i=0;i<sz;i++)
196 PyObject *elt(PyList_GetItem(obj,i));
197 eltCpp[i]=PyFloat_AsDouble(elt);
199 YACS::AutoCppPtr<YACSEvalSeqAnyDouble> elt(new YACSEvalSeqAnyDouble(eltCpp));
200 return elt.dettach();
202 else if(tcct->kind()==YACS::ENGINE::Int)
204 std::vector<int> eltCpp(sz);
205 for(std::size_t i=0;i<sz;i++)
207 PyObject *elt(PyList_GetItem(obj,i));
208 eltCpp[i]=PyInt_AsLong(elt);
210 YACS::AutoCppPtr<YACSEvalSeqAnyInt> elt(new YACSEvalSeqAnyInt(eltCpp));
211 return elt.dettach();
214 throw YACS::Exception("YACSEvalYFXPattern::GetValueInPort : not implemented yet for other than Double and Int !");
217 void YACSEvalYFXPattern::cleanScheme()
224 YACSEvalYFXPattern::~YACSEvalYFXPattern()
230 YACSEvalYFXRunOnlyPattern::YACSEvalYFXRunOnlyPattern(YACS::ENGINE::Proc *scheme, bool ownScheme, YACS::ENGINE::ComposedNode *runNode):YACSEvalYFXPattern(scheme,ownScheme),_runNode(runNode),_commonSz(0),_generatedGraph(0)
233 throw YACS::Exception("YACSEvalYFXRunOnlyPattern : internal run node must be not null !");
238 void YACSEvalYFXRunOnlyPattern::setOutPortsOfInterestForEvaluation(std::size_t commonSize, const std::vector<YACSEvalOutputPort *>& outputsOfInterest)
241 _commonSz=commonSize;
242 _outputsOfInterest=outputsOfInterest;
245 void YACSEvalYFXRunOnlyPattern::resetOutputsOfInterest()
249 _outputsOfInterest.clear();
252 void YACSEvalYFXRunOnlyPattern::generateGraph()
254 static const char LISTPYOBJ_STR[]="list[pyobj]";
255 if(_commonSz==0 || _outputsOfInterest.empty())
257 YACS::ENGINE::RuntimeSALOME::setRuntime();
258 YACS::ENGINE::RuntimeSALOME *r(YACS::ENGINE::getSALOMERuntime());
259 _generatedGraph=r->createProc(DFT_PROC_NAME);
260 YACS::ENGINE::TypeCode *pyobjTC(_generatedGraph->createInterfaceTc("python:obj:1.0","pyobj",std::list<YACS::ENGINE::TypeCodeObjref *>()));
261 std::ostringstream oss; oss << "Loop_" << _runNode->getName();
262 _generatedGraph->createType(YACSEvalAnyDouble::TYPE_REPR,"double");
263 _generatedGraph->createType(YACSEvalAnyInt::TYPE_REPR,"int");
265 YACS::ENGINE::InlineNode *n0(r->createScriptNode(YACS::ENGINE::PythonNode::KIND,"__initializer__"));
266 _generatedGraph->edAddChild(n0);
267 YACS::ENGINE::TypeCode *listPyobjTC(_generatedGraph->createSequenceTc(LISTPYOBJ_STR,LISTPYOBJ_STR,pyobjTC));
268 YACS::ENGINE::OutputPort *sender(n0->edAddOutputPort("sender",listPyobjTC));
269 std::ostringstream var0;
270 for(std::vector< YACSEvalInputPort >::const_iterator it=_inputs.begin();it!=_inputs.end();it++)
273 if((*it).hasSequenceOfValuesToEval(dummy))
275 var0 << (*it).getName() << ",";
276 YACS::ENGINE::TypeCode *tc(createSeqTypeCodeFrom(_generatedGraph,(*it).getTypeOfData()));
277 YACS::ENGINE::InputPort *inp(n0->edAddInputPort((*it).getName(),tc));
278 YACS::ENGINE::InputPyPort *inpc(dynamic_cast<YACS::ENGINE::InputPyPort *>(inp));
280 throw YACS::Exception("YACSEvalYFXRunOnlyPattern::generateGraph : internal error 1 !");
281 (*it).initializeUndergroundWithSeq(inpc);
284 std::ostringstream n0Script; n0Script << "sender=zip(" << var0.str() << ")\n";
285 n0->setScript(n0Script.str());
287 YACS::ENGINE::ForEachLoop *n1(r->createForEachLoop(oss.str(),pyobjTC));
288 _generatedGraph->edAddChild(n1);
289 _generatedGraph->edAddCFLink(n0,n1);
290 _generatedGraph->edAddDFLink(sender,n1->edGetSeqOfSamplesPort());
291 YACS::ENGINE::InlineNode *n2(r->createScriptNode(YACS::ENGINE::PythonNode::KIND,GATHER_NODE_NAME));
292 _generatedGraph->edAddChild(n2);
293 _generatedGraph->edAddCFLink(n1,n2);
295 YACS::ENGINE::Bloc *n10(r->createBloc("Bloc"));
297 YACS::ENGINE::InlineNode *n100(r->createScriptNode(YACS::ENGINE::PythonNode::KIND,"__dispatch__"));
298 YACS::ENGINE::Node *n101(_runNode->cloneWithoutCompAndContDeepCpy(0,true));
299 n10->edAddChild(n100);
300 n10->edAddChild(n101);
301 YACS::ENGINE::InputPort *dispatchIn(n100->edAddInputPort("i0",pyobjTC));
302 n10->edAddCFLink(n100,n101);
303 n1->edAddDFLink(n1->edGetSamplePort(),dispatchIn);
304 std::ostringstream var1;
305 for(std::vector< YACSEvalInputPort >::const_iterator it=_inputs.begin();it!=_inputs.end();it++)
308 if((*it).hasSequenceOfValuesToEval(dummy))
310 var1 << (*it).getName() << ",";
311 YACS::ENGINE::OutputPort *myOut(n100->edAddOutputPort((*it).getName(),_generatedGraph->getTypeCode((*it).getTypeOfData())));
312 std::string tmpPortName(_runNode->getInPortName((*it).getUndergroundPtr()));
313 YACS::ENGINE::InputPort *myIn(n101->getInputPort(tmpPortName));
314 n10->edAddDFLink(myOut,myIn);
317 std::ostringstream n100Script; n100Script << var1.str() << "=i0\n";
318 n100->setScript(n100Script.str());
319 for(std::vector< YACSEvalOutputPort * >::const_iterator it=_outputsOfInterest.begin();it!=_outputsOfInterest.end();it++)
321 YACS::ENGINE::TypeCode *tc(createSeqTypeCodeFrom(_generatedGraph,(*it)->getTypeOfData()));
322 YACS::ENGINE::InputPort *myIn(n2->edAddInputPort((*it)->getName(),tc));
323 std::string tmpPortName(_runNode->getOutPortName((*it)->getUndergroundPtr()));
324 YACS::ENGINE::OutputPort *myOut(n101->getOutputPort(tmpPortName));
325 _generatedGraph->edAddDFLink(myOut,myIn);
327 _generatedGraph->updateContainersAndComponents();
330 void YACSEvalYFXRunOnlyPattern::resetGeneratedGraph()
332 delete _generatedGraph;
337 int YACSEvalYFXRunOnlyPattern::assignNbOfBranches()
339 checkAlreadyComputedResources();
341 throw YACS::Exception("YACSEvalYFXRunOnlyPattern::assignNbOfBranches : the generated graph has not been created !");
342 std::list<YACS::ENGINE::Node *> nodes(_generatedGraph->getChildren());
343 YACS::ENGINE::ForEachLoop *zeMainNode(0);
344 for(std::list<YACS::ENGINE::Node *>::const_iterator it=nodes.begin();it!=nodes.end();it++)
346 YACS::ENGINE::ForEachLoop *isZeMainNode(dynamic_cast<YACS::ENGINE::ForEachLoop *>(*it));
350 zeMainNode=isZeMainNode;
352 throw YACS::Exception("YACSEvalYFXRunOnlyPattern::assignNbOfBranches : internal error 1 !");
356 throw YACS::Exception("YACSEvalYFXRunOnlyPattern::assignNbOfBranches : internal error 2 !");
357 unsigned int nbProcsDeclared(getResourcesInternal()->getNumberOfProcsDeclared());
358 nbProcsDeclared=std::max(nbProcsDeclared,4u);
359 int nbOfBranch(nbProcsDeclared/getResourcesInternal()->getMaxLevelOfParallelism());
360 nbOfBranch=std::max(nbOfBranch,1);
361 YACS::ENGINE::InputPort *zeInputToSet(zeMainNode->edGetNbOfBranchesPort());
362 YACS::ENGINE::AnyInputPort *zeInputToSetC(dynamic_cast<YACS::ENGINE::AnyInputPort *>(zeInputToSet));
364 throw YACS::Exception("YACSEvalYFXRunOnlyPattern::assignNbOfBranches : internal error 3 !");
365 YACS::ENGINE::Any *a(YACS::ENGINE::AtomAny::New(nbOfBranch));
366 zeInputToSetC->put(a);
367 zeInputToSetC->exSaveInit();
372 bool YACSEvalYFXRunOnlyPattern::isLocked() const
374 return _generatedGraph!=0;
377 YACSEvalListOfResources *YACSEvalYFXRunOnlyPattern::giveResources()
380 if(!isAlreadyComputedResources())
382 YACS::ENGINE::DeploymentTree dt(_runNode->getDeploymentTree());
383 YACSEvalListOfResources *res(new YACSEvalListOfResources(_runNode->getMaxLevelOfParallelism(),getCatalogInAppli(),dt));
386 return getResourcesInternal();
389 YACS::ENGINE::Proc *YACSEvalYFXRunOnlyPattern::getUndergroundGeneratedGraph() const
391 return _generatedGraph;
394 std::vector<YACSEvalSeqAny *> YACSEvalYFXRunOnlyPattern::getResults() const
396 if(_generatedGraph->getState()!=YACS::DONE)
397 throw YACS::Exception("YACSEvalYFXRunOnlyPattern::getResults : the execution did not finished correctly ! getResults should not be called !");
398 std::vector<YACSEvalSeqAny *> ret(_outputsOfInterest.size());
399 YACS::ENGINE::Node *node(_generatedGraph->getChildByName(GATHER_NODE_NAME));
400 YACS::ENGINE::PythonNode *nodeC(dynamic_cast<YACS::ENGINE::PythonNode *>(node));
402 throw YACS::Exception("YACSEvalYFXRunOnlyPattern::getResults : internal error !");
404 for(std::vector< YACSEvalOutputPort * >::const_iterator it=_outputsOfInterest.begin();it!=_outputsOfInterest.end();it++,ii++)
406 YACS::ENGINE::InPort *input(nodeC->getInPort((*it)->getName()));
407 YACS::ENGINE::InputPyPort *inputC(dynamic_cast<YACS::ENGINE::InputPyPort *>(input));
410 std::ostringstream oss; oss << "YACSEvalYFXRunOnlyPattern::getResults : internal error for input \"" << (*it)->getName() << "\"";
411 throw YACS::Exception(oss.str());
413 ret[ii]=BuildValueInPort(inputC);
418 bool YACSEvalYFXRunOnlyPattern::IsMatching(YACS::ENGINE::Proc *scheme, YACS::ENGINE::ComposedNode *& runNode)
420 std::list<YACS::ENGINE::Node *> nodes(scheme->getChildren());
423 bool areAllElementary(true);
424 for(std::list<YACS::ENGINE::Node *>::const_iterator it=nodes.begin();it!=nodes.end() && areAllElementary;it++)
425 if(!dynamic_cast<YACS::ENGINE::ElementaryNode *>(*it))
426 areAllElementary=false;
430 CheckNodeIsOK(scheme);
436 YACS::ENGINE::ComposedNode *candidate(dynamic_cast<YACS::ENGINE::ComposedNode *>(nodes.front()));
439 CheckNodeIsOK(candidate);
443 void YACSEvalYFXRunOnlyPattern::buildInputPorts()
446 std::list< YACS::ENGINE::InputPort *> allInputPorts(_runNode->getSetOfInputPort());
447 std::vector<std::string> allNames;
448 for(std::list< YACS::ENGINE::InputPort *>::const_iterator it=allInputPorts.begin();it!=allInputPorts.end();it++)
450 YACS::ENGINE::InputPort *elt(*it);
452 throw YACS::Exception("YACSEvalYFXRunOnlyPattern::buildInputPorts : presence of null input !");
453 std::set<YACS::ENGINE::OutPort *> bls(elt->edSetOutPort());
456 std::string inpName(elt->getName());
458 throw YACS::Exception("YACSEvalYFXRunOnlyPattern::buildInputPorts : an input has empty name ! Should not !");
459 _inputs.push_back(YACSEvalInputPort(elt));
460 if(std::find(allNames.begin(),allNames.end(),inpName)!=allNames.end())
462 std::ostringstream oss; oss << "YACSEvalYFXRunOnlyPattern::buildInputPorts : input name \"" << inpName << "\" appears more than once !";
463 throw YACS::Exception(oss.str());
465 allNames.push_back(inpName);
470 void YACSEvalYFXRunOnlyPattern::buildOutputPorts()
473 std::list< YACS::ENGINE::OutputPort *> allOutputPorts(_runNode->getSetOfOutputPort());
474 std::vector<std::string> allNames;
475 for(std::list< YACS::ENGINE::OutputPort *>::const_iterator it=allOutputPorts.begin();it!=allOutputPorts.end();it++)
477 YACS::ENGINE::OutputPort *elt(*it);
479 throw YACS::Exception("YACSEvalYFXRunOnlyPattern::buildOutputPorts : presence of null output !");
480 std::string outpName(elt->getName());
482 throw YACS::Exception("YACSEvalYFXRunOnlyPattern::buildOutputPorts : an output has empty name ! Should not !");
483 if(std::find(allNames.begin(),allNames.end(),outpName)!=allNames.end())
485 std::ostringstream oss; oss << "YACSEvalYFXRunOnlyPattern::buildOutputPorts : output name \"" << outpName << "\" appears more than once !";
486 throw YACS::Exception(oss.str());
488 _outputs.push_back(YACSEvalOutputPort(*it));