]> SALOME platform Git repositories - modules/yacs.git/blob - src/evalyfx/YACSEvalYFXPattern.cxx
Salome HOME
b5cfd95ce93789e1aee061912d43c5fa048f759c
[modules/yacs.git] / src / evalyfx / YACSEvalYFXPattern.cxx
1 // Copyright (C) 2012-2015  CEA/DEN, 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, or (at your option) any later version.
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 // Author : Anthony Geay (EDF R&D)
20
21 #include "YACSEvalYFXPattern.hxx"
22 #include "YACSEvalResource.hxx"
23 #include "YACSEvalSeqAny.hxx"
24 #include "YACSEvalAutoPtr.hxx"
25
26 #include "ElementaryNode.hxx"
27 #include "RuntimeSALOME.hxx"
28 #include "InputPort.hxx"
29 #include "LinkInfo.hxx"
30 #include "TypeCode.hxx"
31 #include "Proc.hxx"
32
33 #include "PythonPorts.hxx"
34 #include "ForEachLoop.hxx"
35 #include "PythonNode.hxx"
36 #include "InlineNode.hxx"
37 #include "ServiceNode.hxx"
38
39 #include "ResourcesManager.hxx"
40
41 #include <map>
42 #include <numeric>
43 #include <sstream>
44
45 const char YACSEvalYFXPattern::DFT_PROC_NAME[]="YFX";
46
47 const char YACSEvalYFXRunOnlyPattern::GATHER_NODE_NAME[]="__gather__";
48
49 std::vector< YACSEvalInputPort *> YACSEvalYFXPattern::getFreeInputPorts() const
50 {
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)));
56   return ret;
57 }
58
59 std::vector< YACSEvalOutputPort *> YACSEvalYFXPattern::getFreeOutputPorts() const
60 {
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)));
66   return ret;
67 }
68
69 YACSEvalYFXPattern *YACSEvalYFXPattern::FindPatternFrom(YACS::ENGINE::Proc *scheme, bool ownScheme)
70 {
71   if(!scheme)
72     throw YACS::Exception("YACSEvalYFXPattern::FindPatternFrom : input scheme must be not null !");
73   {
74       YACS::ENGINE::ComposedNode *zeRunNode(0);
75       bool isMatchingRunOnlyPattern(YACSEvalYFXRunOnlyPattern::IsMatching(scheme,zeRunNode));
76       if(isMatchingRunOnlyPattern)
77         return new YACSEvalYFXRunOnlyPattern(scheme,ownScheme,zeRunNode);
78   }
79   throw YACS::Exception("YACSEvalYFXPattern::FindPatternFrom : no pattern found for the input scheme !");
80 }
81
82 bool YACSEvalYFXPattern::isAlreadyComputedResources() const
83 {
84   return _res!=0;
85 }
86
87 void YACSEvalYFXPattern::checkNonAlreadyComputedResources() const
88 {
89   if(isAlreadyComputedResources())
90     throw YACS::Exception("checkNonAlreadyComputedResources : instance of computed resources already computed !");
91 }
92
93 void YACSEvalYFXPattern::checkAlreadyComputedResources() const
94 {
95   if(!isAlreadyComputedResources())
96     throw YACS::Exception("checkAlreadyComputedResources : instance of computed resources not already computed !");
97 }
98
99 void YACSEvalYFXPattern::checkLocked() const
100 {
101   if(!isLocked())
102     throw YACS::Exception("YACSEvalYFXPattern::checkLocked : Pattern is not locked !");
103 }
104
105 void YACSEvalYFXPattern::checkNonLocked() const
106 {
107   if(isLocked())
108     throw YACS::Exception("YACSEvalYFXPattern::checkNonLocked : Pattern is locked !");
109 }
110
111 void YACSEvalYFXPattern::CheckNodeIsOK(YACS::ENGINE::ComposedNode *node)
112 {
113   /*YACS::ENGINE::LinkInfo info(YACS::ENGINE::LinkInfo::WARN_ONLY_DONT_STOP);
114   try
115   {
116       node->checkConsistency(info);
117   }
118   catch(YACS::Exception& e)
119   {
120   }
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++)
125     {
126       YACS::ENGINE::ServiceNode *node0(dynamic_cast<YACS::ENGINE::ServiceNode *>(*it));
127       YACS::ENGINE::InlineNode *node1(dynamic_cast<YACS::ENGINE::InlineNode *>(*it));
128       if(node0)
129         {
130           YACS::ENGINE::Container *cont(node0->getContainer());
131           YACS::ENGINE::ComponentInstance *comp(node0->getComponent());
132           if(!cont || !comp)
133             {
134               std::ostringstream oss; oss << "YACSEvalYFXPattern::CheckNodeIsOK : ServiceNode called \"" << node0->getName() << "\" is not correctly defined !";
135               throw YACS::Exception(oss.str());
136             }
137         }
138       if(node1)
139         {
140           YACS::ENGINE::Container *cont(node1->getContainer());
141           if(!cont && node1->getExecutionMode()==YACS::ENGINE::InlineNode::REMOTE_STR)
142             {
143               std::ostringstream oss; oss << "YACSEvalYFXPattern::CheckNodeIsOK : InlineNode called \"" << node1->getName() << "\" is not correctly defined !";
144               throw YACS::Exception(oss.str());
145             }
146         }
147     }*/
148 }
149
150 YACSEvalYFXPattern::YACSEvalYFXPattern(YACS::ENGINE::Proc *scheme, bool ownScheme):_scheme(scheme),_ownScheme(ownScheme),_rm(new ResourcesManager_cpp),_res(0)
151 {
152 }
153
154 YACS::ENGINE::TypeCode *YACSEvalYFXPattern::createSeqTypeCodeFrom(YACS::ENGINE::Proc *scheme, const std::string& zeType)
155 {
156   std::ostringstream oss; oss << "list[" << zeType << "]";
157   YACS::ENGINE::TypeCode *tc(scheme->getTypeCode(zeType));
158   return scheme->createSequenceTc(oss.str(),oss.str(),tc);
159 }
160
161 void YACSEvalYFXPattern::setResources(YACSEvalListOfResources *res)
162 {
163   checkNonAlreadyComputedResources();
164   if(res!=_res)
165     delete _res;
166   _res=res;
167 }
168
169 void YACSEvalYFXPattern::resetResources()
170 {
171   delete _res;
172   _res=0;
173 }
174
175 YACSEvalSeqAny *YACSEvalYFXPattern::BuildValueInPort(YACS::ENGINE::InputPyPort *port)
176 {
177   if(!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));
182   if(!tcc)
183     {
184       std::ostringstream oss; oss << "YACSEvalYFXPattern::GetValueInPort : internal error for tc of input \"" << port->getName() << "\"";
185       throw YACS::Exception(oss.str());
186     }
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)
192     {
193       std::vector<double> eltCpp(sz);
194       for(std::size_t i=0;i<sz;i++)
195         {
196           PyObject *elt(PyList_GetItem(obj,i));
197           eltCpp[i]=PyFloat_AsDouble(elt);
198         }
199       YACS::AutoCppPtr<YACSEvalSeqAnyDouble> elt(new YACSEvalSeqAnyDouble(eltCpp));
200       return elt.dettach();
201     }
202   else if(tcct->kind()==YACS::ENGINE::Int)
203     {
204       std::vector<int> eltCpp(sz);
205       for(std::size_t i=0;i<sz;i++)
206         {
207           PyObject *elt(PyList_GetItem(obj,i));
208           eltCpp[i]=PyInt_AsLong(elt);
209         }
210       YACS::AutoCppPtr<YACSEvalSeqAnyInt> elt(new YACSEvalSeqAnyInt(eltCpp));
211       return elt.dettach();
212     }
213   else
214     throw YACS::Exception("YACSEvalYFXPattern::GetValueInPort : not implemented yet for other than Double and Int !");
215 }
216
217 void YACSEvalYFXPattern::cleanScheme()
218 {
219   if(_ownScheme)
220     delete _scheme;
221   _scheme=0;
222 }
223
224 YACSEvalYFXPattern::~YACSEvalYFXPattern()
225 {
226   delete _rm;
227   delete _res;
228 }
229
230 YACSEvalYFXRunOnlyPattern::YACSEvalYFXRunOnlyPattern(YACS::ENGINE::Proc *scheme, bool ownScheme, YACS::ENGINE::ComposedNode *runNode):YACSEvalYFXPattern(scheme,ownScheme),_runNode(runNode),_commonSz(0),_generatedGraph(0)
231 {
232   if(!_runNode)
233     throw YACS::Exception("YACSEvalYFXRunOnlyPattern : internal run node must be not null !");
234   buildInputPorts();
235   buildOutputPorts();
236 }
237
238 void YACSEvalYFXRunOnlyPattern::setOutPortsOfInterestForEvaluation(std::size_t commonSize, const std::vector<YACSEvalOutputPort *>& outputsOfInterest)
239 {
240   checkNonLocked();
241   _commonSz=commonSize;
242   _outputsOfInterest=outputsOfInterest;
243 }
244
245 void YACSEvalYFXRunOnlyPattern::resetOutputsOfInterest()
246 {
247   checkLocked();
248   _commonSz=0;
249   _outputsOfInterest.clear();
250 }
251
252 void YACSEvalYFXRunOnlyPattern::generateGraph()
253 {
254   static const char LISTPYOBJ_STR[]="list[pyobj]";
255   if(_commonSz==0 || _outputsOfInterest.empty())
256     return ;
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");
264   //
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++)
271     {
272       std::size_t dummy;
273       if((*it).hasSequenceOfValuesToEval(dummy))
274         {
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));
279           if(!inpc)
280             throw YACS::Exception("YACSEvalYFXRunOnlyPattern::generateGraph : internal error 1 !");
281           (*it).initializeUndergroundWithSeq(inpc);
282         }
283     }
284   std::ostringstream n0Script; n0Script << "sender=zip(" << var0.str() << ")\n";
285   n0->setScript(n0Script.str());
286   //
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);
294   //
295   YACS::ENGINE::Bloc *n10(r->createBloc("Bloc"));
296   n1->edAddChild(n10);
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++)
306     {
307       std::size_t dummy;
308       if((*it).hasSequenceOfValuesToEval(dummy))
309         {
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);
315         }
316     }
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++)
320     {
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);
326     }
327   _generatedGraph->updateContainersAndComponents();
328 }
329
330 void YACSEvalYFXRunOnlyPattern::resetGeneratedGraph()
331 {
332   delete _generatedGraph;
333   _generatedGraph=0;
334   resetResources();
335 }
336
337 int YACSEvalYFXRunOnlyPattern::assignNbOfBranches()
338 {
339   checkAlreadyComputedResources();
340   if(!_generatedGraph)
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++)
345     {
346       YACS::ENGINE::ForEachLoop *isZeMainNode(dynamic_cast<YACS::ENGINE::ForEachLoop *>(*it));
347       if(isZeMainNode)
348         {
349           if(!zeMainNode)
350             zeMainNode=isZeMainNode;
351           else
352             throw YACS::Exception("YACSEvalYFXRunOnlyPattern::assignNbOfBranches : internal error 1 !");
353         }
354     }
355   if(!zeMainNode)
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));
363   if(!zeInputToSetC)
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();
368   a->decrRef();
369   return nbOfBranch;
370 }
371
372 bool YACSEvalYFXRunOnlyPattern::isLocked() const
373 {
374   return _generatedGraph!=0;
375 }
376
377 YACSEvalListOfResources *YACSEvalYFXRunOnlyPattern::giveResources()
378 {
379   checkLocked();
380   if(!isAlreadyComputedResources())
381     {
382       YACS::ENGINE::DeploymentTree dt(_runNode->getDeploymentTree());
383       YACSEvalListOfResources *res(new YACSEvalListOfResources(_runNode->getMaxLevelOfParallelism(),getCatalogInAppli(),dt));
384       setResources(res);
385     }
386   return getResourcesInternal();
387 }
388
389 YACS::ENGINE::Proc *YACSEvalYFXRunOnlyPattern::getUndergroundGeneratedGraph() const
390 {
391   return _generatedGraph;
392 }
393
394 std::vector<YACSEvalSeqAny *> YACSEvalYFXRunOnlyPattern::getResults() const
395 {
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));
401   if(!nodeC)
402     throw YACS::Exception("YACSEvalYFXRunOnlyPattern::getResults : internal error !");
403   std::size_t ii(0);
404   for(std::vector< YACSEvalOutputPort * >::const_iterator it=_outputsOfInterest.begin();it!=_outputsOfInterest.end();it++,ii++)
405     {
406       YACS::ENGINE::InPort *input(nodeC->getInPort((*it)->getName()));
407       YACS::ENGINE::InputPyPort *inputC(dynamic_cast<YACS::ENGINE::InputPyPort *>(input));
408       if(!inputC)
409         {
410           std::ostringstream oss; oss << "YACSEvalYFXRunOnlyPattern::getResults : internal error for input \"" << (*it)->getName() << "\"";
411           throw YACS::Exception(oss.str());
412         }
413       ret[ii]=BuildValueInPort(inputC);
414     }
415   return ret;
416 }
417
418 bool YACSEvalYFXRunOnlyPattern::IsMatching(YACS::ENGINE::Proc *scheme, YACS::ENGINE::ComposedNode *& runNode)
419 {
420   std::list<YACS::ENGINE::Node *> nodes(scheme->getChildren());
421   if(nodes.empty())
422     return false;
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;
427   if(areAllElementary)
428     {
429       if(scheme)
430         CheckNodeIsOK(scheme);
431       runNode=scheme;
432       return true;
433     }
434   if(nodes.size()!=1)
435     return false;
436   YACS::ENGINE::ComposedNode *candidate(dynamic_cast<YACS::ENGINE::ComposedNode *>(nodes.front()));
437   runNode=candidate;
438   if(candidate)
439     CheckNodeIsOK(candidate);
440   return candidate!=0;
441 }
442
443 void YACSEvalYFXRunOnlyPattern::buildInputPorts()
444 {
445   _inputs.clear();
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++)
449     {
450       YACS::ENGINE::InputPort *elt(*it);
451       if(!elt)
452         throw YACS::Exception("YACSEvalYFXRunOnlyPattern::buildInputPorts : presence of null input !");
453       std::set<YACS::ENGINE::OutPort *> bls(elt->edSetOutPort());
454       if(bls.empty())
455         {
456           std::string inpName(elt->getName());
457           if(inpName.empty())
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())
461             {
462               std::ostringstream oss; oss << "YACSEvalYFXRunOnlyPattern::buildInputPorts : input name \"" << inpName << "\" appears more than once !";
463               throw YACS::Exception(oss.str());
464             }
465           allNames.push_back(inpName);
466         }
467     }
468 }
469
470 void YACSEvalYFXRunOnlyPattern::buildOutputPorts()
471 {
472   _outputs.clear();
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++)
476     {
477       YACS::ENGINE::OutputPort *elt(*it);
478       if(!elt)
479         throw YACS::Exception("YACSEvalYFXRunOnlyPattern::buildOutputPorts : presence of null output !");
480       std::string outpName(elt->getName());
481       if(outpName.empty())
482         throw YACS::Exception("YACSEvalYFXRunOnlyPattern::buildOutputPorts : an output has empty name ! Should not !");
483       if(std::find(allNames.begin(),allNames.end(),outpName)!=allNames.end())
484         {
485           std::ostringstream oss; oss << "YACSEvalYFXRunOnlyPattern::buildOutputPorts : output name \"" << outpName << "\" appears more than once !";
486           throw YACS::Exception(oss.str());
487         }
488       _outputs.push_back(YACSEvalOutputPort(*it));
489     }
490 }
491