MOOSE - Multiscale Object Oriented Simulation Environment
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
Element.cpp
Go to the documentation of this file.
1 /**********************************************************************
2 ** This program is part of 'MOOSE', the
3 ** Messaging Object Oriented Simulation Environment.
4 ** Copyright (C) 2003-2009 Upinder S. Bhalla. and NCBS
5 ** It is made available under the terms of the
6 ** GNU Lesser General Public License version 2.1
7 ** See the file COPYING.LIB for the full notice.
8 **********************************************************************/
9 
10 #include "header.h"
11 #include "FuncOrder.h"
12 #include "HopFunc.h"
13 #include "../msg/OneToAllMsg.h"
14 #include "../shell/Shell.h"
15 #include "../scheduling/Clock.h"
16 
17 Element::Element( Id id, const Cinfo* c, const string& name )
18  : name_( name ),
19  id_( id ),
20  cinfo_( c ),
21  msgBinding_( c->numBindIndex() ),
22  msgDigest_( c->numBindIndex() ),
23  tick_( -1 ),
24  isRewired_( false ),
25  isDoomed_( false )
26 {
27  id.bindIdToElement( this );
28 }
29 
30 
32 {
33  // A flag that the Element is doomed, used to avoid lookups
34  // when deleting Msgs.
35  id_.zeroOut();
36  markAsDoomed();
37  for ( vector< vector< MsgFuncBinding > >::iterator
38  i = msgBinding_.begin(); i != msgBinding_.end(); ++i )
39  {
40  for ( vector< MsgFuncBinding >::iterator
41  j = i->begin(); j != i->end(); ++j )
42  {
43  // This call internally protects against double deletion.
44  Msg::deleteMsg( j->mid );
45  }
46  }
47 
48  for ( vector< ObjId >::iterator i = m_.begin(); i != m_.end(); ++i )
49  Msg::deleteMsg( *i );
50 }
51 
53 // Element info functions
55 
56 const string& Element::getName() const
57 {
58  return name_;
59 }
60 
61 void Element::setName( const string& val )
62 {
63  name_ = val;
64 }
65 
66 const Cinfo* Element::cinfo() const
67 {
68  return cinfo_;
69 }
70 
71 Id Element::id() const
72 {
73  return id_;
74 }
75 
77 // Msg Management
80 {
81  while ( m_.size() > 0 )
82  {
83  if ( m_.back().bad() )
84  m_.pop_back();
85  else
86  break;
87  }
88  m_.push_back( m );
89  markRewired();
90 }
91 
92 class matchMid
93 {
94 public:
95  matchMid( ObjId mid )
96  : mid_( mid )
97  {
98  ;
99  }
100 
101  bool operator()( const MsgFuncBinding& m ) const
102  {
103  return m.mid == mid_;
104  }
105 private:
107 };
108 
114 {
115  if ( isDoomed() ) // This is a flag that the Element is doomed.
116  return;
117  // Here we have the spectacularly ugly C++ erase-remove idiot.
118  m_.erase( remove( m_.begin(), m_.end(), mid ), m_.end() );
119 
120  for ( vector< vector< MsgFuncBinding > >::iterator i = msgBinding_.begin(); i != msgBinding_.end(); ++i )
121  {
122  matchMid match( mid );
123  i->erase( remove_if( i->begin(), i->end(), match ), i->end() );
124  }
125  markRewired();
126 }
127 
128 void Element::addMsgAndFunc( ObjId mid, FuncId fid, BindIndex bindIndex )
129 {
130  if ( msgBinding_.size() < bindIndex + 1U )
131  msgBinding_.resize( bindIndex + 1 );
132  msgBinding_[ bindIndex ].push_back( MsgFuncBinding( mid, fid ) );
133  markRewired();
134 }
135 
137 {
138  assert( b < msgBinding_.size() );
139  vector< MsgFuncBinding > temp = msgBinding_[ b ];
140  msgBinding_[ b ].resize( 0 );
141  for( vector< MsgFuncBinding >::iterator i = temp.begin();
142  i != temp.end(); ++i )
143  {
144  Msg::deleteMsg( i->mid );
145  }
146  markRewired();
147 }
148 
151 {
152  markAsDoomed();
153  m_.clear();
154  msgBinding_.clear();
155  msgDigest_.clear();
156 }
157 
159 void Element::zombieSwap( const Cinfo* c )
160 {
161  // cout << name_ << ", cname=" << c->name() << ", t0 = " << this->tick_ << ", t1 = " << Clock::lookupDefaultTick( c->name() ) << endl;
162  if ( tick_ == -1 ) // Object is already disabled, let it be.
163  {
164  return;
165  }
166  bool zombieInName = ( c->name().substr(0, 6) == "Zombie" );
167  if ( tick_ == -2 && !zombieInName ) // Object was a zombie and wants to come home.
168  {
169  int t = Clock::lookupDefaultTick( c->name() );
170  setTick( t );
171  }
172  else if ( tick_ >= 0 ) // disable clock, with option to return
173  {
174  if ( zombieInName )
175  {
176  setTick( -2 );
177  }
178  else
179  {
180  int t = Clock::lookupDefaultTick( c->name() );
181  setTick( t );
182  }
183  }
184 }
185 
186 int Element::getTick() const
187 {
188  return tick_;
189 }
190 
191 void Element::innerSetTick( unsigned int tick )
192 {
193  if ( tick < 32 )
194  tick_ = tick;
195 }
196 
198 {
199  static Id clockId( 1 );
200  const Element* clock = clockId.element();
201  vector< ObjId > msgs;
202  for ( vector< ObjId >::const_iterator i = m_.begin();
203  i != m_.end(); ++i )
204  {
205  const Msg* m = Msg::getMsg( *i );
206  const Element* src;
207  if ( m->e1() == this )
208  {
209  src = m->e2();
210  }
211  else
212  {
213  src = m->e1();
214  }
215  if ( src == clock )
216  {
217  msgs.push_back( *i );
218  }
219  }
220  sort( msgs.begin(), msgs.end() );
221  // C++ detritus.
222  msgs.erase( unique( msgs.begin(), msgs.end() ), msgs.end() );
223  for( vector< ObjId >::iterator
224  i = msgs.begin(); i != msgs.end(); ++i )
225  Msg::deleteMsg( *i );
226 }
227 
228 static bool addClockMsg( unsigned int tick, Id tgt, const Finfo* f2 )
229 {
230  Id clockId( 1 );
231  stringstream ss;
232  ss << "proc" << tick;
233 
234  const Finfo* f1 = clockId.element()->cinfo()->findFinfo( ss.str() );
235  assert( f1 );
236  assert( f2 );
237  Msg* m = new OneToAllMsg( clockId.eref(), tgt.element(), 0 );
238  if ( m )
239  {
240  if ( f1->addMsg( f2, m->mid(), clockId.element() ) )
241  {
242  return true;
243  }
244  delete m;
245  }
246  cout << "Error: Element::setTick: failed to connect " << tgt <<
247  " to clock\n";
248  return false;
249 }
250 
251 void Element::setTick( int t )
252 {
253  Id clockId( 1 );
254  if ( t == tick_ )
255  return;
256  if ( tick_ >= 0 ) // Drop all messages coming here from clock.
257  {
258  dropAllMsgsFromSrc( clockId );
259  }
260  tick_ = t;
261  if ( t < 0 || t > 31 ) // Only 32 ticks available.
262  {
263  // Don't need to add new ticks.
264  return;
265  }
266  const Finfo* f2 = cinfo()->findFinfo( "init" );
267  if ( f2 && dynamic_cast< const SharedFinfo* >( f2 ) )
268  {
269  // Must build init msg too. This comes on the previous tick.
270  assert( t > 0 );
271  addClockMsg( t-1, id(), f2 );
272  }
273  f2 = cinfo()->findFinfo( "proc" );
274  if ( f2 )
275  {
276  addClockMsg( t, id(), f2 );
277  }
278  else
279  {
280  cout << "Element::setTick:Warning: Attempt to assign a tick to a '"
281  << cinfo_->name() << "'.\nThis does not support process actions.\n";
282  tick_ = -1;
283  }
284 }
286 // Msg Information
288 
289 const vector< MsgDigest >& Element::msgDigest( unsigned int index )
290 {
291  if ( isRewired_ )
292  {
293  digestMessages();
294  isRewired_ = false;
295  }
296  assert( index < msgDigest_.size() );
297  return msgDigest_[ index ];
298 }
299 
300 const vector< MsgFuncBinding >* Element::getMsgAndFunc( BindIndex b ) const
301 {
302  if ( b < msgBinding_.size() )
303  return &( msgBinding_[ b ] );
304  return 0;
305 }
306 
308 {
309  return ( b < msgBinding_.size() && msgBinding_[b].size() > 0 );
310 }
311 
312 
313 void Element::showMsg() const
314 {
315  cout << "Outgoing: \n";
316  for ( map< string, Finfo* >::const_iterator i =
317  cinfo_->finfoMap().begin();
318  i != cinfo_->finfoMap().end(); ++i )
319  {
320  const SrcFinfo* sf = dynamic_cast< const SrcFinfo* >( i->second );
321  if ( sf && msgBinding_.size() > sf->getBindIndex() )
322  {
323  const vector< MsgFuncBinding >& mb = msgBinding_[ sf->getBindIndex()];
324  unsigned int numTgt = mb.size();
325  if ( numTgt > 0 )
326  {
327  for ( unsigned int j = 0; j < numTgt; ++j )
328  {
329  cout << sf->name() << " bindId=" << sf->getBindIndex() << ": ";
330  cout << j << ": MessageId=" << mb[j].mid <<
331  ", FuncId=" << mb[j].fid <<
332  ", " << Msg::getMsg( mb[j].mid )->e1()->getName() <<
333  " -> " <<
334  Msg::getMsg( mb[j].mid )->e2()->getName() << endl;
335  }
336  }
337  }
338  }
339  cout << "Dest and Src: \n";
340  for ( unsigned int i = 0; i < m_.size(); ++i )
341  {
342  const Msg* m = Msg::getMsg( m_[i] );
343  cout << i << ": MessageId= " << m_[i] <<
344  ", e1= " << m->e1()->name_ <<
345  ", e2= " << m->e2()->name_ << endl;
346  }
347 }
348 
349 
351 {
352  for ( vector< ObjId >::const_iterator i = m_.begin();
353  i != m_.end(); ++i )
354  {
355  const Msg* m = Msg::getMsg( *i );
356  const Element* src;
357  if ( m->e1() == this )
358  {
359  src = m->e2();
360  }
361  else
362  {
363  src = m->e1();
364  }
365  unsigned int ret = src->findBinding( MsgFuncBinding( *i, fid ) );
366  if ( ret != ~0U )
367  {
368  return *i;
369  }
370  }
371  return ObjId( 0, BADINDEX );
372 }
373 
374 unsigned int Element::findBinding( MsgFuncBinding b ) const
375 {
376  for ( unsigned int i = 0; i < msgBinding_.size(); ++i )
377  {
378  const vector< MsgFuncBinding >& mb = msgBinding_[i];
379  vector< MsgFuncBinding>::const_iterator bi =
380  find( mb.begin(), mb.end(), b );
381  if ( bi != mb.end() )
382  return i;
383  }
384  return ~0;
385 }
386 
387 const vector< ObjId >& Element::msgIn() const
388 {
389  return m_;
390 }
391 
392 vector< FuncOrder> putFuncsInOrder(
393  const Element* elm, const vector< MsgFuncBinding >& vec )
394 {
395  vector< FuncOrder > fo( vec.size() );
396  for ( unsigned int j = 0; j < vec.size(); ++j )
397  {
398  const MsgFuncBinding& mfb = vec[j];
399  const Msg* msg = Msg::getMsg( mfb.mid );
400  if ( msg->e1() == elm )
401  {
402  fo[j].set( msg->e2()->cinfo()->getOpFunc( mfb.fid ), j );
403  }
404  else
405  {
406  fo[j].set( msg->e1()->cinfo()->getOpFunc( mfb.fid ), j );
407  }
408  }
409  sort( fo.begin(), fo.end() );
410  return fo;
411 }
412 
422 // Filter out the messages going off-node. Eliminate from erefs and
423 // flip flags in targetNodes.
424 // Do not set any flags for messages originating from off-node, though.
425 // We're not interested in setting up targets that are the responsibility
426 // of other nodes.
427 // Retain Erefs sourced from off-node that go to current node, but eliminate
428 // those sourced and going off-node.
430  unsigned int start, // This specifies the range of dataIndex of parent
431  unsigned int end, // Element that are present on current node.
432  bool isSrcGlobal,
433  unsigned int myNode, // I pass this in to help with debugging.
434  vector< vector < Eref > >& erefs,
435  vector< vector< bool > >& targetNodes ) // targetNodes[srcDataId][node]
436 {
437  // i is index of src dataid
438  for ( unsigned int i = 0; i < erefs.size(); ++i )
439  {
440  vector< Eref > temp;
441  vector< Eref >& vec = erefs[i];
442  for ( unsigned int j = 0; j < vec.size(); ++j ) // list of tgts.
443  {
444  const Eref& er = vec[j];
445  unsigned int node = er.getNode();
446  if ( !isSrcGlobal && // Don't send any msgs
447  // off-node, as it will be dealt with by the off-node src.
448  i >= start && i < end ) // Sourced from current node.
449  {
450  if ( node != myNode ) // Target is off-node
451  targetNodes[i][node] = true;
452  if ( er.dataIndex() == ALLDATA || er.element()->isGlobal())
453  {
454  for ( unsigned int k = 0; k < Shell::numNodes(); ++k )
455  if ( k != myNode )
456  targetNodes[i][k] = true;
457  }
458  }
459  if ( node == myNode ) // Regardless of source, target is onNode.
460  temp.push_back( er );
461  }
462  erefs[i] = temp; // Swap out the original set with the new one.
463  }
464 }
465 
467  unsigned int srcNum, const MsgFuncBinding& mfb,
468  const FuncOrder& fo,
469  vector< vector< bool > >& targetNodes )
470 // targetNodes[srcDataId][node]
471 {
472  const Msg* msg = Msg::getMsg( mfb.mid );
473  vector< vector < Eref > > erefs;
474  if ( msg->e1() == this )
475  msg->targets( erefs );
476  else if ( msg->e2() == this )
477  msg->sources( erefs );
478  else
479  assert( 0 );
480 
481  if ( Shell::numNodes() > 1 )
483  localDataStart(),
485  isGlobal(), Shell::myNode(),
486  erefs, targetNodes );
487 
488  for ( unsigned int j = 0; j < erefs.size(); ++j )
489  {
490  vector< MsgDigest >& md =
491  msgDigest_[ msgBinding_.size() * j + srcNum ];
492  // k->func(); erefs[ j ];
493  if ( md.size() == 0 || md.back().func != fo.func() )
494  {
495  md.push_back( MsgDigest( fo.func(), erefs[j] ) );
496  /*
497  if ( md.back().targets.size() > 0 )
498  cout << "putTargetsInDigest: " << md.back().targets[0] <<
499  ", eref = " << erefs[j][0] << endl;
500  else
501  cout << "putTargetsInDigest: empty\n";
502  */
503  }
504  else
505  {
506  md.back().targets.insert( md.back().targets.end(),
507  erefs[ j ].begin(),
508  erefs[ j ].end() );
509  }
510  }
511 }
512 
513 // This puts the special HopFuncs into the MsgDigest. Furthermore, the
514 // Erefs to which they point are the originating Eref instance on the
515 // remote node. This Eref will then invoke its own send call to complete
516 // the message transfer.
518  unsigned int srcNum, vector< vector< bool > >& targetNodes )
519 // targetNodes[srcDataId][node]
520 {
521  if ( msgBinding_[ srcNum ].size() == 0 )
522  return;
523  const MsgFuncBinding& mfb = msgBinding_[ srcNum ][0];
524  const Msg* msg = Msg::getMsg( mfb.mid );
525  const OpFunc* func;
526  if ( msg->e1() == this )
527  {
528  func = msg->e2()->cinfo()->getOpFunc( mfb.fid );
529  }
530  else
531  {
532  func = msg->e1()->cinfo()->getOpFunc( mfb.fid );
533  }
534  assert( func );
535  // How do I eventually destroy these?
536  const OpFunc* hop = func->makeHopFunc( srcNum );
537  for ( unsigned int i = 0; i < numData(); ++i )
538  {
539  vector< Eref > tgts;
540  for ( unsigned int j = 0; j < Shell::numNodes(); ++j )
541  {
542  if ( targetNodes[i][j] )
543  tgts.push_back( Eref( this, i, j ) );
544  // This is a hack. I encode the target node # in the FieldIndex
545  // and the originating Eref in the remainder of the Eref.
546  // The HopFunc has to extract both these things to push into
547  // the correct SendBuffer.
548  }
549  if ( tgts.size() > 0 )
550  {
551  vector< MsgDigest >& md =
552  msgDigest_[ msgBinding_.size() * i + srcNum ];
553  md.push_back( MsgDigest( hop, tgts ) );
554  }
555  }
556 }
557 
558 unsigned int findNumDigest( const vector< vector< MsgDigest > > & md,
559  unsigned int totFunc, unsigned int numData, unsigned int funcNum )
560 {
561  unsigned int ret = 0;
562  for ( unsigned int i = 0; i < numData; ++i )
563  {
564  ret += md[ totFunc * i + funcNum ].size();
565  }
566  return ret;
567 }
568 
570 {
571  bool report = 0; // for debugging
572  msgDigest_.clear();
573  msgDigest_.resize( msgBinding_.size() * numData() );
574  vector< bool > temp( Shell::numNodes(), false );
575  vector< vector< bool > > targetNodes( numData(), temp );
576  // targetNodes[srcDataId][node]. The idea is that if any dataEntry has
577  // a target off-node, it should flag the entry here so that it can
578  // send the message request to the proxy on that node.
579  for ( unsigned int i = 0; i < msgBinding_.size(); ++i )
580  {
581  // Go through and identify functions with the same ptr.
582  vector< FuncOrder > fo = putFuncsInOrder( this, msgBinding_[i] );
583  for ( vector< FuncOrder >::const_iterator
584  k = fo.begin(); k != fo.end(); ++k )
585  {
586  const MsgFuncBinding& mfb = msgBinding_[i][ k->index() ];
587  putTargetsInDigest( i, mfb, *k, targetNodes );
588  }
589  if ( Shell::numNodes() > 1 )
590  {
591  if ( report )
592  {
593  unsigned int numPre = findNumDigest( msgDigest_,
594  msgBinding_.size(), numData(), i );
595  putOffNodeTargetsInDigest( i, targetNodes );
596  unsigned int numPost = findNumDigest( msgDigest_,
597  msgBinding_.size(), numData(), i );
598  cout << "\nfor Element " << name_;
599  cout << ", Func: " << i << ", numFunc = " << fo.size() <<
600  ", numPre= " << numPre <<
601  ", numPost= " << numPost << endl;
602  for ( unsigned int j = 0; j < numData(); ++j )
603  {
604  cout << endl << j << " ";
605  for ( unsigned int node = 0; node < Shell::numNodes(); ++node)
606  {
607  cout << (int)targetNodes[j][node];
608  }
609  }
610  cout << endl;
611  }
612  else
613  {
614  putOffNodeTargetsInDigest( i, targetNodes );
615  }
616  }
617  }
618 }
619 
621 // Field Information
624 {
625  vector< const SrcFinfo* > srcVec;
626  vector< const DestFinfo* > destVec;
627  vector< const SharedFinfo* > sharedVec;
628  vector< const Finfo* > valueVec; // ValueFinfos are what is left.
629  for ( map< string, Finfo* >::const_iterator i =
630  cinfo_->finfoMap().begin();
631  i != cinfo_->finfoMap().end(); ++i )
632  {
633  const SrcFinfo* sf = dynamic_cast< const SrcFinfo* >( i->second);
634  const DestFinfo* df = dynamic_cast< const DestFinfo* >( i->second);
635  const SharedFinfo* shf = dynamic_cast< const SharedFinfo* >( i->second);
636  if ( sf )
637  srcVec.push_back( sf );
638  else if ( df )
639  destVec.push_back( df );
640  else if ( shf )
641  sharedVec.push_back( shf );
642  else
643  valueVec.push_back( i->second );
644  }
645 
646  cout << "Showing SrcFinfos: \n";
647  for ( unsigned int i = 0; i < srcVec.size(); ++i )
648  cout << i << ": " << srcVec[i]->name() << " Bind=" << srcVec[i]->getBindIndex() << endl;
649  cout << "Showing " << destVec.size() << " DestFinfos: \n";
650  /*
651  for ( unsigned int i = 0; i < destVec.size(); ++i )
652  cout << i << ": " << destVec[i]->name() << " FuncId=" << destVec[i]->getFid() << endl;
653  */
654  cout << "Showing SharedFinfos: \n";
655  for ( unsigned int i = 0; i < sharedVec.size(); ++i )
656  {
657  cout << i << ": " << sharedVec[i]->name() << " Src=[ ";
658  for ( unsigned int j = 0; j < sharedVec[i]->src().size(); ++j )
659  cout << " " << sharedVec[i]->src()[j]->name();
660  cout << " ] Dest=[ ";
661  for ( unsigned int j = 0; j < sharedVec[i]->dest().size(); ++j )
662  cout << " " << sharedVec[i]->dest()[j]->name();
663  cout << " ]\n";
664  }
665  cout << "Listing ValueFinfos: \n";
666  Eref er = this->id().eref();
667  string val;
668  for ( unsigned int i = 0; i < valueVec.size(); ++i )
669  {
670  valueVec[i]->strGet( er, valueVec[i]->name(), val );
671  cout << i << ": " << valueVec[i]->name() << " " <<
672  val << endl;
673  }
674 }
675 
676 void Element::destroyElementTree( const vector< Id >& tree )
677 {
678  for( vector< Id >::const_iterator i = tree.begin();
679  i != tree.end(); i++ )
680  i->element()->markAsDoomed(); // Indicate that Element is doomed
681  bool killShell = false;
682 
683  // Do not destroy the shell till the very end.
684  for( vector< Id >::const_iterator i = tree.begin();
685  i != tree.end(); i++ )
686  {
687  if ( *i == Id() )
688  killShell = true;
689  else
690  i->destroy();
691  }
692  if ( killShell )
693  Id().destroy();
694 }
695 
697 {
698  isDoomed_ = true;
699 }
700 
701 bool Element::isDoomed() const
702 {
703  return isDoomed_;
704 }
705 
707 {
708  isRewired_ = true;
709 }
710 
711 void Element::printMsgDigest( unsigned int srcIndex, unsigned int dataId ) const
712 {
713  unsigned int numSrcMsgs = msgBinding_.size();
714  unsigned int start = 0;
715  unsigned int end = numData();
716  if ( dataId < numData() )
717  {
718  start = dataId;
719  end = dataId + 1;
720  }
721  for (unsigned int i = start; i < end; ++i )
722  {
723  cout << i << ": ";
724  const vector< MsgDigest> & md =
725  msgDigest_[numSrcMsgs * i + srcIndex];
726  for ( unsigned int j = 0; j < md.size(); ++j )
727  {
728  cout << j << ": ";
729  for ( unsigned int k = 0; k < md[j].targets.size(); ++k )
730  {
731  cout << " " <<
732  md[j].targets[k].dataIndex() << "," <<
733  md[j].targets[k].fieldIndex();
734  }
735  }
736  cout << endl;
737  }
738 }
739 
740 void Element::replaceCinfo( const Cinfo* newCinfo )
741 {
742  cinfo_ = newCinfo;
743  // Stuff to be done for data is handled by derived classes in ZombeSwap.
744 }
745 
747 // Message traversal
749 unsigned int Element::getOutputs( vector< Id >& ret, const SrcFinfo* finfo )
750 const
751 {
752  assert( finfo ); // would like to check that finfo is on this.
753  unsigned int oldSize = ret.size();
754 
755  const vector< MsgFuncBinding >* msgVec =
756  getMsgAndFunc( finfo->getBindIndex() );
757  if ( !msgVec )
758  return 0;
759  for ( unsigned int i = 0; i < msgVec->size(); ++i )
760  {
761  const Msg* m = Msg::getMsg( (*msgVec)[i].mid );
762  assert( m );
763  Id id = m->e2()->id();
764  if ( m->e2() == this )
765  id = m->e1()->id();
766  ret.push_back( id );
767  }
768 
769  return ret.size() - oldSize;
770 }
771 
773  const SrcFinfo* finfo ,
774  vector< ObjId >& tgt,
775  vector< string >& func
776  ) const
777 {
778  assert( finfo ); // would like to check that finfo is on this.
779  assert( srcDataId < this->numData() );
780 
781  tgt.resize( 0 );
782  func.resize( 0 );
783 
784  const vector< MsgFuncBinding >* msgVec =
785  getMsgAndFunc( finfo->getBindIndex() );
786  for ( unsigned int i = 0; i < msgVec->size(); ++i )
787  {
788  const Msg* m = Msg::getMsg( (*msgVec)[i].mid );
789  assert( m );
790  FuncId fid = (*msgVec)[i].fid;
791  if ( m->e1() == this ) // regular direction message.
792  {
793  string name = m->e2()->cinfo()->destFinfoName( fid );
794  vector< vector< Eref > > t;
795  m->targets( t );
796  assert( t.size() == this->numData() );
797  vector< Eref >& row = t[srcDataId];
798  for ( vector< Eref >::const_iterator
799  e = row.begin(); e != row.end(); ++e )
800  {
801  tgt.push_back( e->objId() );
802  func.push_back( name );
803  }
804  }
805  else if ( m->e2() == this )
806  {
807  string name = m->e1()->cinfo()->destFinfoName( fid );
808  vector< vector< Eref > > t;
809  m->sources( t );
810  assert( t.size() == this->numData() );
811  vector< Eref >& row = t[srcDataId];
812  for ( vector< Eref >::const_iterator
813  e = row.begin(); e != row.end(); ++e )
814  {
815  tgt.push_back( e->objId() );
816  func.push_back( name );
817  }
818  }
819  else
820  {
821  assert( 0 );
822  }
823  }
824  return tgt.size();
825 }
826 
827 // Returns multiple Obj sources and their srcFinfo names.
829  vector< ObjId >& srcObj,
830  vector< string >& sender ) const
831 {
832  for ( vector< ObjId >::const_iterator i = m_.begin();
833  i != m_.end(); ++i )
834  {
835  const Msg* m = Msg::getMsg( *i );
836  const Element* src;
837  if ( m->e1() == this )
838  {
839  src = m->e2();
840  }
841  else
842  {
843  src = m->e1();
844  }
845  unsigned int ret = src->findBinding( MsgFuncBinding( *i, fid ) );
846  if ( ret != ~0U )
847  {
848  // problem here, to get dataId
849  srcObj.push_back( ObjId( src->id(), 0 ) );
850  sender.push_back( src->cinfo()->srcFinfoName( ret ) );
851  }
852  }
853  return srcObj.size();
854 }
855 
856 vector< ObjId > Element::getMsgTargets( DataId srcDataId,
857  const SrcFinfo* finfo ) const
858 {
859  assert( finfo ); // would like to check that finfo is on this.
860  assert( srcDataId < this->numData() );
861 
862  vector< ObjId > ret;
863  Eref er( const_cast< Element* >( this ), srcDataId );
864 
865  const vector< MsgDigest >&md = er.msgDigest( finfo->getBindIndex() );
866  for ( vector< MsgDigest >::const_iterator
867  i = md.begin(); i != md.end(); ++i )
868  {
869  for ( vector< Eref >::const_iterator
870  j = i->targets.begin(); j != i->targets.end(); ++j )
871  {
872  if ( j->dataIndex() == ALLDATA )
873  {
874  for ( unsigned int k = 0;
875  k < j->element()->numData(); ++k )
876  ret.push_back( ObjId( j->id(), k ) );
877  }
878  else
879  {
880  ret.push_back( j->objId() );
881  }
882  }
883  }
884  return ret;
885 }
886 
887 unsigned int Element::getInputs( vector< Id >& ret, const DestFinfo* finfo )
888 const
889 {
890  assert( finfo ); // would like to check that finfo is on src.
891  unsigned int oldSize = ret.size();
892 
893  FuncId fid = finfo->getFid();
894  vector< ObjId > caller;
895  getInputMsgs( caller, fid );
896  for ( vector< ObjId >::iterator i = caller.begin();
897  i != caller.end(); ++i )
898  {
899  const Msg* m = Msg::getMsg( *i );
900  assert( m );
901 
902  Id id = m->e1()->id();
903  if ( m->e1() == this )
904  id = m->e2()->id();
905  ret.push_back( id );
906  }
907  return ret.size() - oldSize;
908 }
909 
918 unsigned int Element::getInputsWithTgtIndex( vector< pair< Id, unsigned int> >& ret, const DestFinfo* finfo )
919 const
920 {
921  assert( finfo ); // would like to check that finfo is on src.
922  ret.clear();
923 
924  FuncId fid = finfo->getFid();
925  vector< ObjId > caller;
926  getInputMsgs( caller, fid );
927  for ( vector< ObjId >::iterator i = caller.begin();
928  i != caller.end(); ++i )
929  {
930  const Msg* m = Msg::getMsg( *i );
931  assert( m );
932 
933  if ( m->e1() == this )
934  {
935  Eref tgt = m->firstTgt( Eref( m->e2(), 0 ) );
936  unsigned int idx = this->hasFields() ? tgt.fieldIndex(): tgt.dataIndex();
937  ret.push_back( pair< Id, unsigned int >( m->e2()->id(), idx ) );
938  }
939  else if ( m->e2() == this )
940  {
941  Eref tgt = m->firstTgt( Eref( m->e1(), 0 ) );
942  unsigned int idx = this->hasFields() ? tgt.fieldIndex(): tgt.dataIndex();
943  ret.push_back( pair< Id, unsigned int >( m->e1()->id(), idx ) );
944  }
945  }
946  return ret.size();
947 }
948 
949 unsigned int Element::getNeighbors( vector< Id >& ret, const Finfo* finfo )
950 const
951 {
952  ret.resize( 0 );
953  if ( !finfo )
954  return 0;
955 
956  const SrcFinfo* srcF = dynamic_cast< const SrcFinfo* >( finfo );
957  const DestFinfo* destF = dynamic_cast< const DestFinfo* >( finfo );
958  const SharedFinfo* sharedF = dynamic_cast< const SharedFinfo* >( finfo );
959  assert( srcF || destF || sharedF );
960 
961 
962  if ( srcF )
963  return getOutputs( ret, srcF );
964  else if ( destF )
965  return getInputs( ret, destF );
966  else if ( ! sharedF->src().empty() )
967  return getOutputs( ret, sharedF->src().front() );
968  else if ( ! sharedF->dest().empty() )
969  {
970  Finfo* subFinfo = sharedF->dest().front();
971  const DestFinfo* subDestFinfo =
972  dynamic_cast< const DestFinfo* >( subFinfo );
973  assert( subDestFinfo );
974  return getInputs( ret, subDestFinfo );
975  }
976  else
977  {
978  assert( 0 );
979  }
980  return 0;
981 }
982 
983 // May return multiple Msgs.
984 unsigned int Element::getInputMsgs( vector< ObjId >& caller, FuncId fid)
985 const
986 {
987  for ( vector< ObjId >::const_iterator i = m_.begin();
988  i != m_.end(); ++i )
989  {
990  const Msg* m = Msg::getMsg( *i );
991  const Element* src;
992  if ( m->e1() == this )
993  {
994  src = m->e2();
995  }
996  else
997  {
998  src = m->e1();
999  }
1000  unsigned int ret = src->findBinding( MsgFuncBinding( *i, fid ) );
1001  if ( ret != ~0U )
1002  {
1003  caller.push_back( *i );
1004  }
1005  }
1006  return caller.size();
1007 }
1008 
1010  vector< pair< BindIndex, FuncId > >& ret ) const
1011 {
1012  ret.resize( 0 );
1013  for ( unsigned int i = 0; i < msgBinding_.size(); ++i )
1014  {
1015  const vector< MsgFuncBinding >& mb = msgBinding_[i];
1016  for ( vector< MsgFuncBinding >::const_iterator j = mb.begin();
1017  j != mb.end(); ++j )
1018  {
1019  if ( j->mid == mid )
1020  {
1021  ret.push_back( pair< BindIndex, FuncId >( i, j->fid ));
1022  }
1023  }
1024  }
1025  return ret.size();
1026 }
void markRewired()
Definition: Element.cpp:706
const vector< ObjId > & msgIn() const
Definition: Element.cpp:387
Element * e2() const
Definition: Msg.h:68
ObjId mid() const
Definition: Msg.h:106
const OpFunc * getOpFunc(FuncId fid) const
Definition: Cinfo.cpp:240
void putOffNodeTargetsInDigest(unsigned int srcNum, vector< vector< bool > > &targetNodes)
Definition: Element.cpp:517
void setName(const string &val)
Definition: Element.cpp:61
vector< ObjId > getMsgTargets(DataId srcDataId, const SrcFinfo *finfo) const
Definition: Element.cpp:856
unsigned int getOutputs(vector< Id > &ret, const SrcFinfo *finfo) const
Definition: Element.cpp:749
Element * element() const
Synonym for Id::operator()()
Definition: Id.cpp:113
virtual Eref firstTgt(const Eref &src) const =0
unsigned short BindIndex
Definition: header.h:62
void clearBinding(BindIndex b)
Definition: Element.cpp:136
BindIndex getBindIndex() const
Definition: SrcFinfo.cpp:28
unsigned int getNode() const
Definition: Eref.cpp:52
void markAsDoomed()
Definition: Element.cpp:696
const vector< Finfo * > & dest() const
unsigned int dataIndex() const
Definition: Eref.h:50
unsigned int getMsgTargetAndFunctions(DataId srcDataId, const SrcFinfo *finfo, vector< ObjId > &tgt, vector< string > &func) const
Definition: Element.cpp:772
unsigned int getInputsWithTgtIndex(vector< pair< Id, unsigned int > > &ret, const DestFinfo *finfo) const
Definition: Element.cpp:918
void printMsgDigest(unsigned int srcIndex, unsigned int dataIndex) const
Definition: Element.cpp:711
const vector< SrcFinfo * > & src() const
virtual void zombieSwap(const Cinfo *zCinfo)
virtual func, this base version must be called by all derived classes
Definition: Element.cpp:159
void addMsgAndFunc(ObjId mid, FuncId fid, BindIndex bindIndex)
Definition: Element.cpp:128
Definition: ObjId.h:20
const map< string, Finfo * > & finfoMap() const
Definition: Cinfo.cpp:270
Eref eref() const
Definition: Id.cpp:125
const string & name() const
Definition: Finfo.cpp:80
Element * element() const
Definition: Eref.h:42
unsigned int getMsgSourceAndSender(FuncId fid, vector< ObjId > &src, vector< string > &sender) const
Definition: Element.cpp:828
unsigned int fieldIndex() const
Definition: Eref.h:61
virtual void sources(vector< vector< Eref > > &v) const =0
virtual void targets(vector< vector< Eref > > &v) const =0
void zeroOut() const
Definition: Id.cpp:191
void dropMsg(ObjId mid)
Definition: Element.cpp:113
void innerSetTick(unsigned int tick)
Definition: Element.cpp:191
void destroy() const
Definition: Id.cpp:176
Id id() const
Definition: Element.cpp:71
bool isRewired_
True if messages have been changed and need to digestMessages.
Definition: Element.h:443
unsigned int getInputs(vector< Id > &ret, const DestFinfo *finfo) const
Definition: Element.cpp:887
int getTick() const
Definition: Element.cpp:186
unsigned int getFieldsOfOutgoingMsg(ObjId mid, vector< pair< BindIndex, FuncId > > &ret) const
Definition: Element.cpp:1009
const unsigned int ALLDATA
Used by ObjId and Eref.
Definition: consts.cpp:22
const vector< MsgDigest > & msgDigest(unsigned int bindIndex) const
Definition: Eref.cpp:67
const std::string & name() const
Definition: Cinfo.cpp:260
void showFields() const
Definition: Element.cpp:623
vector< FuncOrder > putFuncsInOrder(const Element *elm, const vector< MsgFuncBinding > &vec)
Definition: Element.cpp:392
static unsigned int myNode
bool hasMsgs(BindIndex b) const
Definition: Element.cpp:307
Id id_
Name of the Element.
Definition: Element.h:401
const vector< MsgDigest > & msgDigest(unsigned int index)
Definition: Element.cpp:289
virtual ~Element()
Definition: Element.cpp:31
static void deleteMsg(ObjId mid)
Definition: Msg.cpp:52
matchMid(ObjId mid)
Definition: Element.cpp:95
vector< ObjId > m_
Definition: Element.h:412
ObjId findCaller(FuncId fid) const
Definition: Element.cpp:350
virtual bool addMsg(const Finfo *target, ObjId mid, Element *src) const
Definition: Finfo.h:92
FuncId getFid() const
Definition: DestFinfo.cpp:45
string name_
Definition: Element.h:399
virtual const OpFunc * makeHopFunc(HopIndex hopIndex) const =0
void digestMessages()
Definition: Element.cpp:569
virtual bool hasFields() const =0
Definition: Eref.h:26
const string & destFinfoName(FuncId fid) const
Definition: Cinfo.cpp:569
ObjId mid_
Definition: Element.cpp:106
static unsigned int lookupDefaultTick(const string &className)
Definition: Clock.cpp:1035
const vector< MsgFuncBinding > * getMsgAndFunc(BindIndex b) const
Definition: Element.cpp:300
const Cinfo * cinfo() const
Definition: Element.cpp:66
virtual unsigned int numData() const =0
Returns number of data entries across all nodes.
void addMsg(ObjId mid)
Definition: Element.cpp:79
virtual bool isGlobal() const =0
True if there is a copy of every dataEntry on all nodes.
const OpFunc * func() const
Definition: FuncOrder.h:21
Definition: Msg.h:18
virtual unsigned int localDataStart() const =0
Returns index of first data entry on this node.
const Cinfo * cinfo_
Stores the unique identifier for Element.
Definition: Element.h:406
virtual unsigned int numLocalData() const =0
Returns number of local data entries on this node.
vector< vector< MsgDigest > > msgDigest_
Definition: Element.h:437
Element * e1() const
Definition: Msg.h:61
unsigned int getInputMsgs(vector< ObjId > &caller, FuncId fid) const
Definition: Element.cpp:984
void showMsg() const
Definition: Element.cpp:313
Element(Id id, const Cinfo *c, const string &name)
Definition: Element.cpp:17
void putTargetsInDigest(unsigned int srcNum, const MsgFuncBinding &mfb, const FuncOrder &fo, vector< vector< bool > > &targetNodes)
Definition: Element.cpp:466
static char name[]
Definition: mfield.cpp:401
static void destroyElementTree(const vector< Id > &tree)
Definition: Element.cpp:676
bool operator()(const MsgFuncBinding &m) const
Definition: Element.cpp:101
void dropAllMsgsFromSrc(Id src)
Definition: Element.cpp:197
Definition: Id.h:17
void setTick(int t)
Definition: Element.cpp:251
unsigned int getNeighbors(vector< Id > &ret, const Finfo *finfo) const
Definition: Element.cpp:949
static unsigned int myNode()
static const Msg * getMsg(ObjId m)
Definition: Msg.cpp:59
const string & srcFinfoName(BindIndex bid) const
Definition: Cinfo.cpp:552
static unsigned int numNodes()
vector< vector< MsgFuncBinding > > msgBinding_
Definition: Element.h:423
unsigned int findNumDigest(const vector< vector< MsgDigest > > &md, unsigned int totFunc, unsigned int numData, unsigned int funcNum)
Definition: Element.cpp:558
unsigned int FuncId
Definition: header.h:42
static bool addClockMsg(unsigned int tick, Id tgt, const Finfo *f2)
Definition: Element.cpp:228
bool isDoomed() const
Definition: Element.cpp:701
void clearAllMsgs()
Used upon ending of MOOSE session, to rapidly clear out messages.
Definition: Element.cpp:150
int tick_
Returns tick on which element is scheduled. -1 for disabled.
Definition: Element.h:440
const string & getName() const
Definition: Element.cpp:56
void replaceCinfo(const Cinfo *newCinfo)
Support function for zombieSwap, replaces Cinfo.
Definition: Element.cpp:740
const unsigned int BADINDEX
Used by ObjId and Eref.
Definition: consts.cpp:25
unsigned int DataId
Definition: header.h:47
unsigned int findBinding(MsgFuncBinding b) const
Definition: Element.cpp:374
Definition: Cinfo.h:18
const Finfo * findFinfo(const string &name) const
Definition: Cinfo.cpp:224
bool isDoomed_
True if the element is marked for destruction.
Definition: Element.h:446
Definition: Finfo.h:12
void filterOffNodeTargets(unsigned int start, unsigned int end, bool isSrcGlobal, unsigned int myNode, vector< vector< Eref > > &erefs, vector< vector< bool > > &targetNodes)
Definition: Element.cpp:429