MOOSE - Multiscale Object Oriented Simulation Environment
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
Shell.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 <string>
11 #include <algorithm>
12 
13 using namespace std;
14 
15 
16 #include "header.h"
17 #include "global.h"
18 #include "SingleMsg.h"
19 #include "DiagonalMsg.h"
20 #include "OneToOneMsg.h"
21 #include "OneToAllMsg.h"
22 #include "SparseMatrix.h"
23 #include "SparseMsg.h"
24 #include "Shell.h"
25 #include "Dinfo.h"
26 #include "Wildcard.h"
27 
28 // Want to separate out this search path into the Makefile options
29 #include "../scheduling/Clock.h"
30 
31 const unsigned int Shell::OkStatus = ~0;
32 const unsigned int Shell::ErrorStatus = ~1;
33 
35 bool Shell::keepLooping_ = 1;
36 unsigned int Shell::numCores_;
37 unsigned int Shell::numNodes_;
38 unsigned int Shell::myNode_;
40 unsigned int Shell::numAcks_ = 0;
41 vector< unsigned int > Shell::acked_( 1, 0 );
42 bool Shell::doReinit_( 0 );
43 bool Shell::isParserIdle_( 0 );
44 double Shell::runtime_( 0.0 );
45 
47 {
48 
50 // Value Finfos
52  static ReadOnlyValueFinfo< Shell, bool > isRunning(
53  "isRunning",
54  "Flag: Checks if simulation is in progress",
56 
57  static ValueFinfo< Shell, ObjId > cwe(
58  "cwe",
59  "Current working Element",
61  &Shell::getCwe );
62 
64 // Dest Finfos: Functions handled by Shell
66  static DestFinfo handleUseClock( "useClock",
67  "Deals with assignment of path to a given clock."
68  " Arguments: path, field, tick number. ",
71  );
72  static DestFinfo handleCreate( "create",
73  "create( class, parent, newElm, name, numData, isGlobal )",
75 
76  static DestFinfo handleDelete( "delete",
77  "When applied to a regular object, this function operates "
78  "on the Id (element) specified by the ObjId argument. "
79  "The function deletes the entire object "
80  "array on this Id, including all dataEntries on it,"
81  "all its messages, and all its children. The DataIndex here "
82  "is ignored, and all dataEntries are destroyed. \n"
83  "When applied to a message: Destroys only that one specific "
84  "message identified by the full ObjId. \n"
85  "Args: ObjId\n",
87 
88  static DestFinfo handleAddMsg( "addMsg",
89  "Makes a msg. Arguments are:"
90  " msgtype, src object, src field, dest object, dest field",
92  ( & Shell::handleAddMsg ) );
93  static DestFinfo handleQuit( "quit",
94  "Stops simulation running and quits the simulator",
96  static DestFinfo handleMove( "move",
97  "handleMove( Id orig, Id newParent ): "
98  "moves an Element to a new parent",
100  static DestFinfo handleCopy( "copy",
101  "handleCopy( vector< Id > args, string newName, unsigned int nCopies, bool toGlobal, bool copyExtMsgs ): "
102  " The vector< Id > has Id orig, Id newParent, Id newElm. "
103  "This function copies an Element and all its children to a new parent."
104  " May also expand out the original into nCopies copies."
105  " Normally all messages within the copy tree are also copied. "
106  " If the flag copyExtMsgs is true, then all msgs going out are also copied.",
107  new EpFunc5< Shell, vector< ObjId >, string, unsigned int, bool, bool >(
108  & Shell::handleCopy ) );
109 
110  static DestFinfo setclock( "setclock",
111  "Assigns clock ticks. Args: tick#, dt",
113 
114  static Finfo* shellFinfos[] =
115  {
116  &setclock,
118 // Shared msg
120  // &master,
121  // &worker,
122  &handleCreate,
123  &handleDelete,
124  &handleCopy,
125  &handleMove,
126  &handleAddMsg,
127  &handleQuit,
128  &handleUseClock,
129  };
130 
131  static Dinfo< Shell > d;
132  static Cinfo shellCinfo (
133  "Shell",
135  shellFinfos,
136  sizeof( shellFinfos ) / sizeof( Finfo* ),
137  &d
138  //new Dinfo< Shell >()
139  );
140 
141 #ifdef ENABLE_LOGGER
142  float time = (float(clock() - t)/CLOCKS_PER_SEC);
143  logger.initializationTime.push_back( time );
144 #endif
145 
146  return &shellCinfo;
147 }
148 
150 
151 
153  :
154  gettingVector_( 0 ),
155  numGetVecReturns_( 0 ),
156  cwe_( ObjId() )
157 {
158  getBuf_.resize( 1, 0 );
159 }
160 
162 {
163  ;
164 }
165 
167 {
168  shelle_ = shelle;
169 }
170 
171 
181 Id Shell::doCreate( string type, ObjId parent, string name,
182  unsigned int numData,
183  NodePolicy nodePolicy,
184  unsigned int preferredNode )
185 {
186 
187  const Cinfo* c = Cinfo::find( type );
188  if ( !isNameValid( name ) )
189  {
190  stringstream ss;
191  ss << "Shell::doCreate: bad character in name'" << name <<
192  "'. No Element created";
193  warning( ss.str() );
194  return Id();
195  }
196 
197  if ( c )
198  {
199  if ( c->banCreation() )
200  {
201  stringstream ss;
202  ss << "Shell::doCreate: Cannot create an object of class '" <<
203  type << "' because it is an abstract base class or a FieldElement.\n";
204  warning( ss.str() );
205  return Id();
206  }
207  Element* pa = parent.element();
208  if ( !pa )
209  {
210  stringstream ss;
211  ss << "Shell::doCreate: Parent Element'" << parent << "' not found. No Element created";
212  warning( ss.str() );
213  return Id();
214  }
215 
216  // TODO: This should be an error in future.
217  // This logic of handling already existing path is now handled in
218  // melements.cpp . Calling this section should become an error in
219  // future.
220  if ( Neutral::child( parent.eref(), name ) != Id() )
221  {
222  stringstream ss;
223  ss << "Object with same path already present : " << parent.path()
224  << "/" << name;
225  moose::showWarn( ss.str() );
226  return Id();
227  }
228  // Get the new Id ahead of time and pass to all nodes.
229  Id ret = Id::nextId();
230  NodeBalance nb( numData, nodePolicy, preferredNode );
231  // Get the parent MsgIndex ahead of time and pass to all nodes.
232  unsigned int parentMsgIndex = OneToAllMsg::numMsg();
233 
235  ObjId(), // Apply command to Shell
236  "create", // Function to call.
237  type, // class of new object
238  parent, // Parent
239  ret, // id of new object
240  name, // name of new object
241  nb, // Node balance configuration
242  parentMsgIndex // Message index of child-parent msg.
243  );
244 
245  // innerCreate( type, parent, ret, name, numData, isGlobal );
246 
247  return ret;
248  }
249  else
250  {
251  stringstream ss;
252  ss << "Shell::doCreate: Class '" << type << "' not known. No Element created";
253  warning( ss.str() );
254  }
255 
256  return Id();
257 }
258 
260 {
261  SetGet1< ObjId >::set( ObjId(), "delete", oid );
262  /*
263  Neutral n;
264  n.destroy( i.eref(), 0 );
265  */
266  return true;
267 }
268 
269 ObjId Shell::doAddMsg( const string& msgType,
270  ObjId src, const string& srcField,
271  ObjId dest, const string& destField )
272 {
273 
274  if ( !src.id.element() )
275  {
276  cout << myNode_ << ": Error: Shell::doAddMsg: src not found" << endl;
277  return ObjId();
278  }
279  if ( !dest.id.element() )
280  {
281  cout << myNode_ << ": Error: Shell::doAddMsg: dest not found" << endl;
282  return ObjId(0, BADINDEX );
283  }
284  const Finfo* f1 = src.id.element()->cinfo()->findFinfo( srcField );
285  if ( !f1 )
286  {
287  cout << myNode_ << ": Shell::doAddMsg: Error: Failed to find field " << srcField <<
288  " on src: " << src.id.element()->getName() << endl;
289  return ObjId(0, BADINDEX );
290  }
291  const Finfo* f2 = dest.id.element()->cinfo()->findFinfo( destField );
292  if ( !f2 )
293  {
294  cout << myNode_ << ": Shell::doAddMsg: Error: Failed to find field " << destField <<
295  " on dest: " << dest.id.element()->getName() << endl;
296  cout << "Available fields are : " << endl
297  << moose::mapToString<string, Finfo*>(dest.id.element()->cinfo()->finfoMap());
298 
299  return ObjId( 0, BADINDEX );
300  }
301  if ( ! f1->checkTarget( f2 ) )
302  {
303  cout << myNode_ << ": Shell::doAddMsg: Error: Src/Dest Msg type mismatch: " << srcField << "/" << destField << endl;
304  return ObjId( 0, BADINDEX );
305  }
306 
307  const Msg* m = innerAddMsg( msgType, src, srcField, dest, destField, 0 );
308 
310  ObjId(), // Apply command to Shell
311  "addMsg", // Function to call.
312  msgType,
313  src,
314  srcField,
315  dest,
316  destField,
317  m->mid().dataIndex
318  );
319 
320  return m->mid();
321 
322  // const Msg* m = innerAddMsg( msgType, src, srcField, dest, destField );
323  // return m->mid();
324  // return Msg::lastMsg()->mid();
325 }
326 
328 {
329  SetGet0::set( ObjId(), "quit" );
330 }
331 
332 void Shell::doStart( double runtime, bool notify )
333 {
334  Id clockId( 1 );
335  SetGet2< double, bool >::set( clockId, "start", runtime, notify );
336 
337  /*-----------------------------------------------------------------------------
338  * Now that simulation is over, call cleanUp function of Streamer class
339  * objects. The purpose of this is to write whatever is left in tables to
340  * the output file.
341  *-----------------------------------------------------------------------------*/
342  vector< ObjId > streamers;
343  wildcardFind( "/##[TYPE=Streamer]", streamers );
344  // LOG( moose::debug, "total streamers " << streamers.size( ) );
345  for( vector<ObjId>::const_iterator itr = streamers.begin()
346  ; itr != streamers.end(); itr++ )
347  {
348  Streamer* pStreamer = reinterpret_cast<Streamer*>( itr->data( ) );
349  pStreamer->cleanUp( );
350  }
351 }
352 
354 {
355  static Id clockId( 1 );
356  assert( clockId.element() != 0 );
357 
358  return ( reinterpret_cast< const Clock* >(
359  clockId.eref().data() ) )->isDoingReinit();
360 }
361 
363 {
364 
365  Id clockId( 1 );
366  SetGet0::set( clockId, "reinit" );
367 
368 }
369 
371 {
372  Id clockId( 1 );
373  SetGet0::set( clockId, "stop" );
374 }
376 
377 void Shell::doSetClock( unsigned int tickNum, double dt )
378 {
379  LookupField< unsigned int, double >::set( ObjId( 1 ), "tickDt", tickNum, dt );
380 }
381 
382 void Shell::doUseClock( string path, string field, unsigned int tick )
383 {
384  unsigned int msgIndex = OneToAllMsg::numMsg();
386  "useClock", path, field, tick, msgIndex );
387  // innerUseClock( path, field, tick);
388 }
389 
390 void Shell::doMove( Id orig, ObjId newParent )
391 {
392  if ( orig == Id() )
393  {
394  cout << "Error: Shell::doMove: Cannot move root Element\n";
395  return;
396  }
397 
398  if ( newParent.element() == 0 )
399  {
400  cout << "Error: Shell::doMove: Cannot move object to null parent \n";
401  return;
402  }
403  if ( Neutral::isDescendant( newParent, orig ) )
404  {
405  cout << "Error: Shell::doMove: Cannot move object to descendant in tree\n";
406  return;
407 
408  }
409  const string& name = orig.element()->getName();
410  if ( Neutral::child( newParent.eref(), name ) != Id() )
411  {
412  stringstream ss;
413  ss << "Shell::doMove: Object with same name already present: '"
414  << newParent.path() << "/" << name << "'. Move failed.";
415  warning( ss.str() );
416  return;
417  }
418 
419  SetGet2< Id, ObjId >::set( ObjId(), "move", orig, newParent );
420  // innerMove( orig, newParent );
421 }
422 
423 bool extractIndex( const string& s, unsigned int& index )
424 {
425  vector< unsigned int > open;
426  vector< unsigned int > close;
427 
428  index = 0;
429  if ( s.length() == 0 ) // a plain slash is OK
430  return true;
431 
432  if ( s[0] == '[' ) // Cannot open with a brace
433  return false;
434 
435  for ( unsigned int i = 0; i < s.length(); ++i )
436  {
437  if ( s[i] == '[' )
438  open.push_back( i+1 );
439  else if ( s[i] == ']' )
440  close.push_back( i );
441  }
442 
443  if ( open.size() != close.size() )
444  return false;
445  if ( open.size() == 0 )
446  return true; // the index was set already to zero.
447  int j = atoi( s.c_str() + open[0] );
448  if ( j >= 0 )
449  {
450  index = j;
451  return true;
452  }
453  return false;
454 }
455 
459 bool Shell::chopString( const string& path, vector< string >& ret,
460  char separator )
461 {
462  // /foo/bar/zod
463  // foo/bar/zod
464  // ./foo/bar/zod
465  // ../foo/bar/zod
466  // .
467  // /
468  // ..
469  ret.resize( 0 );
470  if ( path.length() == 0 )
471  return 1; // Treat it as an absolute path
472 
473  bool isAbsolute = 0;
474  string temp = path;
475  if ( path[0] == separator )
476  {
477  isAbsolute = 1;
478  if ( path.length() == 1 )
479  return 1;
480  temp = temp.substr( 1 );
481  }
482 
483  string::size_type pos = temp.find_first_of( separator );
484  ret.push_back( temp.substr( 0, pos ) );
485  while ( pos != string::npos )
486  {
487  temp = temp.substr( pos + 1 );
488  if ( temp.length() == 0 )
489  break;
490  pos = temp.find_first_of( separator );
491  ret.push_back( temp.substr( 0, pos ) );
492  }
493  return isAbsolute;
494 }
495 
499 bool Shell::isNameValid( const string& name )
500 {
501  return ( name.length() > 0 &&
502  name.find_first_of( "[] #?\"/\\" ) == string::npos );
503 }
504 
512 bool Shell::chopPath( const string& path, vector< string >& ret,
513  vector< unsigned int >& index )
514 {
515  bool isAbsolute = chopString( path, ret, '/' );
516  if ( isAbsolute )
517  {
518  index.clear();
519  }
520  else
521  {
522  index.clear();
523  }
524  for ( unsigned int i = 0; i < ret.size(); ++i )
525  {
526  index.push_back( 0 );
527  if ( ret[i] == "." )
528  continue;
529  if ( ret[i] == ".." )
530  {
531  continue;
532  }
533  if ( !extractIndex( ret[i], index[i] ) )
534  {
535  cout << "Error: Shell::chopPath: Failed to parse indices in path '" <<
536  path << "'\n";
537  ret.resize( 0 );
538  index.resize( 0 );
539  return isAbsolute;
540  }
541  size_t pos = ret[i].find_first_of( '[' );
542  if ( ret[i].find_first_of( '[' ) != string::npos )
543  ret[i] = ret[i].substr( 0, pos );
544  }
545 
546  return isAbsolute;
547 }
548 
549 ObjId Shell::doFind( const string& path ) const
550 {
551  if ( path == "/" || path == "/root" )
552  return ObjId();
553 
554  ObjId curr;
555  vector< string > names;
556  vector< unsigned int > indices;
557  bool isAbsolute = chopPath( path, names, indices );
558  assert( names.size() == indices.size() );
559 
560  if ( !isAbsolute )
561  curr = cwe_;
562 
563  for ( unsigned int i = 0; i < names.size(); ++i )
564  {
565  if ( names[i] == "." )
566  {
567  }
568  else if ( names[i] == ".." )
569  {
570  curr = Neutral::parent( curr.eref() );
571  }
572  else
573  {
574  ObjId pa = curr;
575  curr = Neutral::child( curr.eref(), names[i] );
576  if ( curr == ObjId() ) // Neutral::child returned Id(), ie, bad.
577  return ObjId( 0, BADINDEX );
578  if ( curr.element()->hasFields() )
579  {
580  curr.dataIndex = pa.dataIndex;
581  curr.fieldIndex = indices[i];
582  }
583  else
584  {
585  curr.dataIndex = indices[i];
586  if ( curr.element()->numData() <= curr.dataIndex )
587  return ObjId( 0, BADINDEX );
588  }
589  }
590  }
591 
592  assert( curr.element() );
593  if ( curr.element()->numData() <= curr.dataIndex )
594  return ObjId( 0, BADINDEX );
595  if ( curr.fieldIndex > 0 && !curr.element()->hasFields() )
596  return ObjId( 0, BADINDEX );
597 
598  return curr;
599 }
600 
602 // DestFuncs
604 
606 {
607  return MOOSE_VERSION;
608 }
609 
610 void Shell::setCwe( ObjId val )
611 {
612  cwe_ = val;
613 }
614 
616 {
617  return cwe_;
618 }
619 
620 bool Shell::isRunning() const
621 {
622  static Id clockId( 1 );
623  assert( clockId.element() != 0 );
624 
625  return ( reinterpret_cast< const Clock* >( clockId.eref().data() ) )->isRunning();
626 }
627 
628 
638 void Shell::handleCreate( const Eref& e,
639  string type, ObjId parent, Id newElm, string name,
640  NodeBalance nb, unsigned int parentMsgIndex )
641 {
642  innerCreate( type, parent, newElm, name, nb, parentMsgIndex );
643 }
644 
645 
646 
654 bool Shell::adopt( ObjId parent, Id child, unsigned int msgIndex )
655 {
656  static const Finfo* pf = Neutral::initCinfo()->findFinfo( "parentMsg" );
657  // static const DestFinfo* pf2 = dynamic_cast< const DestFinfo* >( pf );
658  // static const FuncId pafid = pf2->getFid();
659  static const Finfo* f1 = Neutral::initCinfo()->findFinfo( "childOut" );
660 
661  assert( !( child.element() == 0 ) );
662  assert( !( child == Id() ) );
663  assert( !( parent.element() == 0 ) );
664 
665  Msg* m = new OneToAllMsg( parent.eref(), child.element(), msgIndex );
666  assert( m );
667 
668  // cout << myNode_ << ", Shell::adopt: mid = " << m->mid() << ", pa =" << parent << "." << parent()->getName() << ", kid=" << child << "." << child()->getName() << "\n";
669 
670  if ( !f1->addMsg( pf, m->mid(), parent.element() ) )
671  {
672  cout << "move: Error: unable to add parent->child msg from " <<
673  parent.element()->getName() << " to " <<
674  child.element()->getName() << "\n";
675  return 0;
676  }
677  return 1;
678 }
679 
681 bool Shell::adopt( Id parent, Id child, unsigned int msgIndex )
682 {
683  return adopt( ObjId( parent ), child, msgIndex );
684 }
685 
690 void Shell::innerCreate( string type, ObjId parent, Id newElm, string name,
691  const NodeBalance& nb, unsigned int msgIndex )
692 // unsigned int numData, bool isGlobal
693 {
694  const Cinfo* c = Cinfo::find( type );
695  if ( c )
696  {
697  Element* ret = 0;
698  switch ( nb.policy )
699  {
700  case MooseGlobal:
701  ret = new GlobalDataElement( newElm, c, name, nb.numData );
702  break;
703  case MooseBlockBalance:
704  ret = new LocalDataElement( newElm, c, name, nb.numData );
705  break;
706  case MooseSingleNode:
707  cout << "Error: Shell::innerCreate: Yet to implement SingleNodeDataElement. Making BlockBalance.\n";
708  ret = new LocalDataElement( newElm, c, name, nb.numData );
709  // ret = new SingleNodeDataElement( newElm, c, name, numData, nb.preferredNode );
710  break;
711  };
712  assert( ret );
713  adopt( parent, newElm, msgIndex );
714  ret->setTick( Clock::lookupDefaultTick( c->name() ) );
715  }
716  else
717  {
718  assert( 0 );
719  }
720 }
721 
722 void Shell::destroy( const Eref& e, ObjId oid)
723 {
724  Neutral *n = reinterpret_cast< Neutral* >( e.data() );
725  assert( n );
726  // cout << myNode_ << ": Shell::destroy done for element id: " << eid << ", name = " << eid.element()->getName() << endl;
727  n->destroy( oid.eref(), 0 );
728  if ( cwe_.id == oid.id )
729  cwe_ = ObjId();
730 }
731 
732 
738 void Shell::handleAddMsg( const Eref& e,
739  string msgType, ObjId src, string srcField,
740  ObjId dest, string destField, unsigned int msgIndex )
741 {
742  // Node 0 will have already called innerAddMsg to get the msgIndex
743  if ( myNode() != 0 )
744  innerAddMsg( msgType, src, srcField, dest, destField, msgIndex );
745  /*
746  if ( innerAddMsg( msgType, src, srcField, dest, destField ) )
747  ack()->send( Eref( shelle_, 0 ), Shell::myNode(), OkStatus );
748  else
749  ack()->send( Eref( shelle_, 0), Shell::myNode(), ErrorStatus );
750  */
751 }
752 
759 const Msg* Shell::innerAddMsg( string msgType,
760  ObjId src, string srcField,
761  ObjId dest, string destField, unsigned int msgIndex )
762 {
763  /*
764  cout << myNode_ << ", Shell::handleAddMsg: " <<
765  msgType << ", " << mid <<
766  ", src =" << src << "." << srcField <<
767  ", dest =" << dest << "." << destField << "\n";
768  */
769  const Finfo* f1 = src.id.element()->cinfo()->findFinfo( srcField );
770  if ( f1 == 0 ) return 0;
771  const Finfo* f2 = dest.id.element()->cinfo()->findFinfo( destField );
772  if ( f2 == 0 ) return 0;
773 
774  // Should have been done before msgs request went out.
775  assert( f1->checkTarget( f2 ) );
776 
777  Msg *m = 0;
778  if ( msgType == "diagonal" || msgType == "Diagonal" )
779  {
780  m = new DiagonalMsg( src.id.element(), dest.id.element(),
781  msgIndex );
782  }
783  else if ( msgType == "sparse" || msgType == "Sparse" )
784  {
785  m = new SparseMsg( src.id.element(), dest.id.element(), msgIndex );
786  }
787  else if ( msgType == "Single" || msgType == "single" )
788  {
789  m = new SingleMsg( src.eref(), dest.eref(), msgIndex );
790  }
791  else if ( msgType == "OneToAll" || msgType == "oneToAll" )
792  {
793  m = new OneToAllMsg( src.eref(), dest.id.element(), msgIndex );
794  }
795  else if ( msgType == "AllToOne" || msgType == "allToOne" )
796  {
797  m = new OneToAllMsg( dest.eref(), src.id.element(), msgIndex ); // Little hack.
798  }
799  else if ( msgType == "OneToOne" || msgType == "oneToOne" )
800  {
801  m = new OneToOneMsg( src.eref(), dest.eref(), msgIndex );
802  }
803  else
804  {
805  cout << myNode_ <<
806  ": Error: Shell::handleAddMsg: msgType not known: "
807  << msgType << endl;
808  return m;
809  }
810  if ( m )
811  {
812  if ( f1->addMsg( f2, m->mid(), src.id.element() ) )
813  {
814  return m;
815  }
816  delete m;
817  m = 0;
818  }
819  cout << myNode_ <<
820  ": Error: Shell::handleAddMsg: Unable to make/connect Msg: "
821  << msgType << " from " << src.id.element()->getName() <<
822  " to " << dest.id.element()->getName() << endl;
823  return m;
824 }
825 
826 bool Shell::innerMove( Id orig, ObjId newParent )
827 {
828  static const Finfo* pf = Neutral::initCinfo()->findFinfo( "parentMsg" );
829  static const DestFinfo* pf2 = dynamic_cast< const DestFinfo* >( pf );
830  static const FuncId pafid = pf2->getFid();
831  static const Finfo* f1 = Neutral::initCinfo()->findFinfo( "childOut" );
832 
833  assert( !( orig == Id() ) );
834  assert( !( newParent.element() == 0 ) );
835 
836  ObjId mid = orig.element()->findCaller( pafid );
837  Msg::deleteMsg( mid );
838 
839  Msg* m = new OneToAllMsg( newParent.eref(), orig.element(), 0 );
840  assert( m );
841  if ( !f1->addMsg( pf, m->mid(), newParent.element() ) )
842  {
843  cout << "move: Error: unable to add parent->child msg from " <<
844  newParent.element()->getName() << " to " <<
845  orig.element()->getName() << "\n";
846  return 0;
847  }
848  return 1;
849 }
850 
851 void Shell::handleMove( const Eref& e, Id orig, ObjId newParent )
852 {
853 
854  innerMove( orig, newParent );
855  /*
856  if ( innerMove( orig, newParent ) )
857  ack()->send( Eref( shelle_, 0 ), Shell::myNode(), OkStatus );
858  else
859  ack()->send( Eref( shelle_, 0 ), Shell::myNode(), ErrorStatus );
860  */
861 }
862 
863 void insertSharedMsgs( const Finfo* f, const Element* e,
864  vector< ObjId >& msgs )
865 {
866  const SharedFinfo* sf = dynamic_cast< const SharedFinfo *>( f );
867  if ( sf )
868  {
869  for ( vector< Finfo* >::const_iterator j =
870  sf->dest().begin(); j != sf->dest().end(); ++j )
871  {
872  DestFinfo* df = dynamic_cast< DestFinfo* >( *j );
873  assert( df );
874  FuncId fid = df->getFid();
875  // These are the messages to be zapped
876  vector< ObjId > caller;
877  if ( e->getInputMsgs( caller, fid ) > 0 )
878  {
879  msgs.insert( msgs.end(), caller.begin(), caller.end() );
880  }
881  }
882  }
883 }
884 
885 // Static function
887  const vector< ObjId >& list, const string& field )
888 {
889  vector< ObjId > msgs; // These are the messages to delete.
890  for ( vector< ObjId >::const_iterator
891  i = list.begin(); i != list.end(); ++i )
892  {
893  // Sanity check: shouldn't try to operate on already deleted objects
894  if ( i->element() )
895  {
896  const Finfo* f = i->element()->cinfo()->findFinfo( field );
897  const DestFinfo* df = dynamic_cast< const DestFinfo *>( f );
898  if ( df )
899  {
900  FuncId fid = df->getFid();
901 
902  // These are the messages to be zapped
903  vector< ObjId > caller;
904  if ( i->element()->getInputMsgs( caller, fid ) > 0 )
905  {
906  msgs.insert( msgs.end(), caller.begin(), caller.end() );
907  }
908  }
909  else
910  {
911  insertSharedMsgs( f, i->element(), msgs );
912  }
913  }
914  }
915  // Do the unique/erase bit. My favourite example of C++ hideousity.
916  sort( msgs.begin(), msgs.end() );
917  msgs.erase( unique( msgs.begin(), msgs.end() ), msgs.end() );
918  // Delete them.
919  for( vector< ObjId >::iterator i = msgs.begin(); i != msgs.end(); ++i )
920  Msg::deleteMsg( *i );
921 }
922 
923 // Non-static function. The innerAddMsg needs the shell.
925  const vector< ObjId >& list, const string& field, unsigned int tick,
926  unsigned int msgIndex )
927 {
928  if ( !Id( 1 ).element() )
929  return;
930  ObjId clockId( 1 );
931  dropClockMsgs( list, field ); // Forbid duplicate PROCESS actions.
932  for ( vector< ObjId >::const_iterator i = list.begin();
933  i != list.end(); ++i )
934  {
935  if ( i->element() )
936  {
937  stringstream ss;
938  ss << "proc" << tick;
939  const Msg* m = innerAddMsg( "OneToAll",
940  clockId, ss.str(),
941  *i, field, msgIndex++ );
942  if ( m )
943  i->element()->innerSetTick( tick );
944  }
945  }
946 }
947 
948 bool Shell::innerUseClock( string path, string field, unsigned int tick,
949  unsigned int msgIndex )
950 {
951  vector< ObjId > list;
952  wildcardFind( path, list ); // By default scans only Elements.
953  if ( list.size() == 0 )
954  {
955  // cout << "Warning: Shell::innerUseClock: no Elements found on path " << path << endl;
956  return 0;
957  }
958  // string tickField = "proc";
959  // Hack to get around a common error.
960  if ( field.substr( 0, 4 ) == "proc" || field.substr( 0, 4 ) == "Proc" )
961  field = "proc";
962  if ( field.substr( 0, 4 ) == "init" || field.substr( 0, 4 ) == "Init" )
963  field = "init";
964 
965  addClockMsgs( list, field, tick, msgIndex );
966  for ( vector< ObjId >::iterator
967  i = list.begin(); i != list.end(); ++i )
968  i->id.element()->innerSetTick( tick );
969  return 1;
970 }
971 
973  string path, string field, unsigned int tick, unsigned int msgIndex )
974 {
975  // cout << q->getProcInfo()->threadIndexInGroup << ": in Shell::handleUseClock with path " << path << endl << flush;
976  innerUseClock( path, field, tick, msgIndex );
977  /*
978  if ( innerUseClock( path, field, tick ) )
979  ack()->send( Eref( shelle_, 0 ),
980  Shell::myNode(), OkStatus );
981  else
982  ack()->send( Eref( shelle_, 0 ),
983  Shell::myNode(), ErrorStatus );
984  */
985 }
986 
991 {
993 }
994 
995 // Static function
997 {
998  return keepLooping_;
999 }
1000 
1001 void Shell::warning( const string& text )
1002 {
1003  moose::showWarn( text );
1004 }
1005 
1006 void Shell::error( const string& text )
1007 {
1008  cout << "Error: Shell:: " << text << endl;
1009 }
1010 
1016 {
1017  Eref sheller = Id().eref();
1018  Shell* s = reinterpret_cast< Shell* >( sheller.data() );
1019  vector< Id > kids;
1020  Neutral::children( sheller, kids );
1021  for ( vector< Id >::iterator i = kids.begin(); i != kids.end(); ++i )
1022  {
1023  if ( i->value() > 4 ) /* These are created by users */
1024  {
1025  LOG( moose::debug
1026  , "Shell::cleanSimulation: deleted cruft at " <<
1027  i->value() << ": " << i->path());
1028  s->doDelete( *i );
1029  }
1030  }
1031  LOG( moose::info, "Cleaned up!");
1032 }
int wildcardFind(const string &path, vector< ObjId > &ret)
Definition: Wildcard.cpp:169
NodePolicy policy
Definition: Shell.h:39
void doStart(double runtime, bool notify=false)
Definition: Shell.cpp:332
static ProcInfo p_
Definition: Shell.h:613
static double runtime_
Definition: Shell.h:634
ObjId mid() const
Definition: Msg.h:106
static unsigned int myNode_
Definition: Shell.h:606
char * data() const
Definition: Eref.cpp:41
void handleCreate(const Eref &e, string type, ObjId parent, Id newElm, string name, NodeBalance nb, unsigned int parentMsgIndex)
Definition: Shell.cpp:638
void cleanUp(void)
This function is called from Shell when simulation is called to write the left-over data to streamer ...
Definition: Streamer.cpp:249
#define MOOSE_VERSION
Definition: header.h:35
static ObjId parent(const Eref &e)
Definition: Neutral.cpp:701
static bool chopString(const string &path, vector< string > &ret, char separator= '/')
Definition: Shell.cpp:459
static bool set(const ObjId &dest, const string &field, L index, A arg)
Definition: SetGet.h:467
void addClockMsgs(const vector< ObjId > &list, const string &field, unsigned int tick, unsigned int msgIndex)
Definition: Shell.cpp:924
static bool keepLooping_
Definition: Shell.h:583
unsigned int fieldIndex
Definition: ObjId.h:100
Element * element() const
Synonym for Id::operator()()
Definition: Id.cpp:113
void warning(const string &text)
Definition: Shell.cpp:1001
const Msg * innerAddMsg(string msgType, ObjId src, string srcField, ObjId dest, string destField, unsigned int msgIndex)
Definition: Shell.cpp:759
static bool isParserIdle_
Definition: Shell.h:636
void doSetClock(unsigned int tickNum, double dt)
Definition: Shell.cpp:377
static void cleanSimulation()
Clean-up MOOSE before shutting down. This function is called whenever keyboard interrupt terminates t...
Definition: Shell.cpp:1015
Definition: Dinfo.h:60
void handleUseClock(const Eref &e, string path, string field, unsigned int tick, unsigned int msgIndex)
Definition: Shell.cpp:972
static unsigned int numAcks_
Definition: Shell.h:621
void handleMove(const Eref &e, Id orig, ObjId newParent)
Definition: Shell.cpp:851
Definition: EpFunc.h:64
static const Cinfo * shellCinfo
Definition: Shell.cpp:149
const vector< Finfo * > & dest() const
Id id
Definition: ObjId.h:98
static bool set(const ObjId &dest, const string &field, A1 arg1, A2 arg2, A3 arg3, A4 arg4, A5 arg5, A6 arg6)
Definition: SetGet.h:818
static const Cinfo * find(const std::string &name)
Definition: Cinfo.cpp:200
string doVersion()
Definition: Shell.cpp:605
bool innerUseClock(string path, string field, unsigned int tick, unsigned int msgIndex)
Definition: Shell.cpp:948
static Id child(const Eref &e, const string &name)
Definition: Neutral.cpp:665
static const unsigned int OkStatus
Definition: Shell.h:492
Definition: ObjId.h:20
const map< string, Finfo * > & finfoMap() const
Definition: Cinfo.cpp:270
ObjId cwe_
Current working Element.
Definition: Shell.h:639
Eref eref() const
Definition: Id.cpp:125
static void children(const Eref &e, vector< Id > &ret)
Definition: Neutral.cpp:342
ObjId doFind(const string &path) const
Definition: Shell.cpp:549
NodePolicy
Definition: Shell.h:28
Id doCreate(string type, ObjId parent, string name, unsigned int numData, NodePolicy nodePolicy=MooseBlockBalance, unsigned int preferredNode=1)
Definition: Shell.cpp:181
ObjId getCwe() const
Definition: Shell.cpp:615
static unsigned int numNodes_
Definition: Shell.h:601
void handleCopy(const Eref &e, vector< ObjId > args, string newName, unsigned int n, bool toGlobal, bool copyExtMsgs)
Definition: ShellCopy.cpp:162
static bool isBlockedOnParser_
Definition: Shell.h:577
static const Cinfo * initCinfo()
Definition: Shell.cpp:46
Definition: OpFunc.h:40
void setShellElement(Element *shelle)
Definition: Shell.cpp:166
vector< double * > getBuf_
Definition: Shell.h:558
const std::string & name() const
Definition: Cinfo.cpp:260
static Id nextId()
Definition: Id.cpp:132
bool innerMove(Id orig, ObjId newParent)
Definition: Shell.cpp:826
static bool isDescendant(Id me, Id ancestor)
Definition: Neutral.cpp:647
virtual bool checkTarget(const Finfo *target) const
Definition: Finfo.h:81
static void deleteMsg(ObjId mid)
Definition: Msg.cpp:52
unsigned int numData
Definition: Shell.h:38
string path() const
Definition: ObjId.cpp:119
ObjId findCaller(FuncId fid) const
Definition: Element.cpp:350
Shell()
Definition: Shell.cpp:152
virtual bool addMsg(const Finfo *target, ObjId mid, Element *src) const
Definition: Finfo.h:92
FuncId getFid() const
Definition: DestFinfo.cpp:45
static bool set(const ObjId &dest, const string &field, A1 arg1, A2 arg2, A3 arg3, A4 arg4)
Definition: SetGet.h:687
static bool keepLooping()
Definition: Shell.cpp:996
virtual bool hasFields() const =0
static unsigned int numCores_
Definition: Shell.h:588
Definition: Eref.h:26
static unsigned int lookupDefaultTick(const string &className)
Definition: Clock.cpp:1035
const Cinfo * cinfo() const
Definition: Element.cpp:66
virtual unsigned int numData() const =0
Returns number of data entries across all nodes.
void destroy(const Eref &e, ObjId oid)
Definition: Shell.cpp:722
void doQuit()
Definition: Shell.cpp:327
bool banCreation() const
Definition: Cinfo.cpp:232
Definition: Msg.h:18
static bool set(const ObjId &dest, const string &field)
Definition: SetGet.h:103
SimpleLogger logger
void insertSharedMsgs(const Finfo *f, const Element *e, vector< ObjId > &msgs)
Definition: Shell.cpp:863
unsigned int getInputMsgs(vector< ObjId > &caller, FuncId fid) const
Definition: Element.cpp:984
Element * element() const
Definition: ObjId.cpp:124
bool extractIndex(const string &s, unsigned int &index)
Definition: Shell.cpp:423
void destroy(const Eref &e, int stage)
Definition: Neutral.cpp:605
void doReinit()
Definition: Shell.cpp:362
static char name[]
Definition: mfield.cpp:401
static bool chopPath(const string &path, vector< string > &ret, vector< unsigned int > &index)
Definition: Shell.cpp:512
void setCwe(ObjId cwe)
Definition: Shell.cpp:610
Eref eref() const
Definition: ObjId.cpp:66
static void dropClockMsgs(const vector< ObjId > &list, const string &field)
Definition: Shell.cpp:886
bool isDoingReinit()
Definition: Shell.cpp:353
ObjId doAddMsg(const string &msgType, ObjId src, const string &srcField, ObjId dest, const string &destField)
Definition: Shell.cpp:269
void error(const string &text)
Definition: Shell.cpp:1006
static bool set(const ObjId &dest, const string &field, A arg)
Definition: SetGet.h:153
static bool adopt(ObjId parent, Id child, unsigned int msgIndex)
Definition: Shell.cpp:654
bool isRunning() const
Definition: Shell.cpp:620
bool doDelete(ObjId oid)
Definition: Shell.cpp:259
static const unsigned int ErrorStatus
Definition: Shell.h:493
Definition: Id.h:17
void setTick(int t)
Definition: Element.cpp:251
vector< float > initializationTime
Definition: OpFunc.h:13
static unsigned int myNode()
void doUseClock(string path, string field, unsigned int tick)
Definition: Shell.cpp:382
static vector< unsigned int > acked_
Definition: Shell.h:622
void innerCreate(string type, ObjId parent, Id newElm, string name, const NodeBalance &nb, unsigned int parentMsgIndex)
Definition: Shell.cpp:690
static const Cinfo * initCinfo()
Definition: Neutral.cpp:16
void showWarn(string msg)
void doStop()
Definition: Shell.cpp:370
Element * shelle_
Definition: Shell.h:551
unsigned int FuncId
Definition: header.h:42
const string & getName() const
Definition: Element.cpp:56
const unsigned int BADINDEX
Used by ObjId and Eref.
Definition: consts.cpp:25
Definition: Cinfo.h:18
static char path[]
Definition: mfield.cpp:403
static bool doReinit_
Definition: Shell.h:629
void handleQuit()
This function is NOT called when simulation ends normally.
Definition: Shell.cpp:990
~Shell()
Definition: Shell.cpp:161
Definition: EpFunc.h:79
static unsigned int numMsg()
Assign the first DataId.
Definition: Shell.h:43
static bool isNameValid(const string &name)
Definition: Shell.cpp:499
const Finfo * findFinfo(const string &name) const
Definition: Cinfo.cpp:224
unsigned int dataIndex
Definition: ObjId.h:99
void handleAddMsg(const Eref &e, string msgType, ObjId src, string srcField, ObjId dest, string destField, unsigned int msgIndex)
Definition: Shell.cpp:738
Definition: Finfo.h:12
static bool set(const ObjId &dest, const string &field, A1 arg1, A2 arg2)
Definition: SetGet.h:365
void doMove(Id orig, ObjId newParent)
Definition: Shell.cpp:390