MOOSE - Multiscale Object Oriented Simulation Environment
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
main.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 "SparseMatrix.h"
12 
13 #ifndef WIN32
14 #include <sys/time.h>
15 #else
16 #include <time.h>
17 #endif
18 #include <math.h>
19 #include <queue>
20 #ifdef WIN32
21 #include "../external/xgetopt/XGetopt.h"
22 #else
23 #include <unistd.h> // for getopt
24 #endif
25 #include "../scheduling/Clock.h"
26 #include "../msg/DiagonalMsg.h"
27 #include "../msg/SparseMsg.h"
28 #include "../mpi/PostMaster.h"
29 #ifdef USE_MPI
30 #include <mpi.h>
31 #endif
32 #include "../shell/Shell.h"
33 #ifdef MACOSX
34 #include <sys/sysctl.h>
35 #endif // MACOSX
36 
37 #ifdef DO_UNIT_TESTS
38 #include <iomanip>
39 int testIndex = 0;
40 #define MOOSE_TEST(name, f ) \
41  cout << "[TEST " << setw(2) << testIndex << "] " << name; \
42  testIndex += 1; \
43  f; \
44  cout << std::right << " [DONE]" << endl; \
45 
46 extern void testSync();
47 extern void testAsync();
48 extern void testSyncArray( unsigned int size, unsigned int method );
49 extern void testShell();
50 extern void testScheduling();
51 extern void testSchedulingProcess();
52 extern void testBuiltins();
53 extern void testSynapse();
54 extern void testBuiltinsProcess();
55 
56 extern void testMpiScheduling();
57 extern void testMpiBuiltins();
58 extern void testMpiShell();
59 extern void testMsg();
60 extern void testMpiMsg();
61 // extern void testKinetics();
62 extern void testKsolve();
63 extern void testKsolveProcess();
64 extern void testBiophysics();
65 extern void testBiophysicsProcess();
66 extern void testDiffusion();
67 extern void testHSolve();
68 // extern void testKineticsProcess();
69 // extern void testGeom();
70 extern void testMesh();
71 // extern void testSimManager();
72 extern void testSigNeur();
73 extern void testSigNeurProcess();
74 
75 extern unsigned int initMsgManagers();
76 extern void destroyMsgManagers();
77 // void regressionTests();
78 #endif
80  unsigned int size, unsigned int runsteps );
81 
82 #ifdef USE_SMOLDYN
83 extern void testSmoldyn();
84 #endif
85 // bool benchmarkTests( int argc, char** argv );
86 
87 extern void mooseBenchmarks( unsigned int option );
88 
90 // System-dependent function here
92 
93 unsigned int getNumCores()
94 {
95  unsigned int numCPU = 0;
96 #ifdef WIN_32
97  SYSTEM_INFO sysinfo;
98  GetSystemInfo( &sysinfo );
99 
100  numCPU = sysinfo.dwNumberOfProcessors;
101 #endif
102 
103 #ifdef LINUX
104  numCPU = sysconf( _SC_NPROCESSORS_ONLN );
105 #endif
106 
107 #ifdef MACOSX
108  int mib[4];
109  size_t len = sizeof(numCPU);
110 
111  /* set the mib for hw.ncpu */
112  mib[0] = CTL_HW;
113  mib[1] = HW_AVAILCPU; // alternatively, try HW_NCPU;
114 
115  /* get the number of CPUs from the system */
116  sysctl(mib, 2, &numCPU, &len, NULL, 0);
117 
118  if( numCPU < 1 )
119  {
120  mib[1] = HW_NCPU;
121  sysctl( mib, 2, &numCPU, &len, NULL, 0 );
122  }
123 #endif
124  if ( numCPU < 1 )
125  {
126  cout << "No CPU information available. Assuming single core." << endl;
127  numCPU = 1;
128  }
129  return numCPU;
130 }
131 
132 bool quitFlag = 0;
135 
136 void checkChildren( Id parent, const string& info )
137 {
138  vector< Id > ret;
139  Neutral::children( parent.eref(), ret );
140  cout << info << " checkChildren of " <<
141  parent.element()->getName() << ": " <<
142  ret.size() << " children\n";
143  for ( vector< Id >::iterator i = ret.begin(); i != ret.end(); ++i )
144  {
145  cout << i->element()->getName() << endl;
146  }
147 }
148 
149 
150 Id init( int argc, char** argv, bool& doUnitTests, bool& doRegressionTests,
151  unsigned int& benchmark )
152 {
153  unsigned int numCores = getNumCores();
154  int numNodes = 1;
155  int myNode = 0;
156  bool isInfinite = 0;
157  int opt;
158  benchmark = 0; // Default, means don't do any benchmarks.
160 #ifdef USE_MPI
161  /*
162  // OpenMPI does not use argc or argv.
163  // unsigned int temp_argc = 1;
164  int provided;
165  MPI_Init_thread( &argc, &argv, MPI_THREAD_SERIALIZED, &provided );
166  */
167  MPI_Init( &argc, &argv );
168 
169  MPI_Comm_size( MPI_COMM_WORLD, &numNodes );
170  MPI_Comm_rank( MPI_COMM_WORLD, &myNode );
171  /*
172  if ( provided < MPI_THREAD_SERIALIZED && myNode == 0 ) {
173  cout << "Warning: This MPI implementation does not like multithreading: " << provided << "\n";
174  }
175  */
176  // myNode = MPI::COMM_WORLD.Get_rank();
177 #endif
178 
182  while ( ( opt = getopt( argc, argv, "hiqurn:b:B:" ) ) != -1 )
183  {
184  switch ( opt )
185  {
186  case 'i' : // infinite loop, used for multinode debugging, to give gdb something to attach to.
187  isInfinite = 1;
188  break;
189  case 'n': // Multiple nodes
190  numNodes = (unsigned int)atoi( optarg );
191  break;
192  case 'b': // Benchmark:
193  {
194  string s(optarg);
195  if ( s == "ee" )
196  benchmark = 1;
197  else if ( s == "gsl" )
198  benchmark = 2;
199  else if ( s == "gssa" )
200  benchmark = 3;
201  else if ( s[0] == 'i' )
202  benchmark = 4;
203  else if ( s[0] == 'h' )
204  benchmark = 5;
205  else if ( s[0] == 'm' )
206  benchmark = 6;
207  else
208  cout << "Unknown benchmark, " << optarg << ", skipping\n";
209  }
210  break;
211  case 'B': // Benchmark plus dump data: handle later.
212  break;
213  case 'u': // Do unit tests, pass back.
214  doUnitTests = 1;
215  break;
216  case 'r': // Do regression tests: pass back
217  doRegressionTests = 1;
218  break;
219  case 'q': // quit immediately after completion.
220  quitFlag = 1;
221  break;
222  case 'h': // help
223  default:
224  cout << "Usage: moose -help -infiniteLoop -unit_tests -regression_tests -quit -n numNodes -benchmark [ee gsl gssa intFire hhNet msg_<msgType>_<size>]\n";
225 
226  exit( 1 );
227  }
228  }
229  if ( myNode == 0 )
230  {
231 #ifndef QUIET_MODE
232  cout << "on node " << myNode << ", numNodes = "
233  << numNodes << ", numCores = " << numCores << endl;
234 #endif
235  }
236 
237  Id shellId;
238  Element* shelle =
239  new GlobalDataElement( shellId, Shell::initCinfo(), "root", 1 );
240 
241  Id clockId = Id::nextId();
242  assert( clockId.value() == 1 );
243  Id classMasterId = Id::nextId();
244  Id postMasterId = Id::nextId();
245 
246  Shell* s = reinterpret_cast< Shell* >( shellId.eref().data() );
247  s->setShellElement( shelle );
248  s->setHardware( numCores, numNodes, myNode );
249  s->loadBalance();
250 
252  unsigned int numMsg = Msg::initMsgManagers();
253 
254  new GlobalDataElement( clockId, Clock::initCinfo(), "clock", 1 );
255  new GlobalDataElement( classMasterId, Neutral::initCinfo(), "classes", 1);
256  new GlobalDataElement( postMasterId, PostMaster::initCinfo(), "postmaster", 1 );
257 
258  assert ( shellId == Id() );
259  assert( clockId == Id( 1 ) );
260  assert( classMasterId == Id( 2 ) );
261  assert( postMasterId == Id( 3 ) );
262 
263 
264 
265  // s->connectMasterMsg();
266 
267  Shell::adopt( shellId, clockId, numMsg++ );
268  Shell::adopt( shellId, classMasterId, numMsg++ );
269  Shell::adopt( shellId, postMasterId, numMsg++ );
270 
271  assert( numMsg == 10 ); // Must be the same on all nodes.
272 
273  Cinfo::makeCinfoElements( classMasterId );
274 
275 
276  // This will be initialized within the Process loop, and better there
277  // as it flags attempts to call the Reduce operations before ProcessLoop
278  // Qinfo::clearReduceQ( numCores ); // Initialize the ReduceQ entry.
279 
280 
281  // SetGet::setShell();
282  // Msg* m = new OneToOneMsg( shelle, shelle );
283  // assert ( m != 0 );
284 
285  while ( isInfinite ) // busy loop for debugging under gdb and MPI.
286  ;
287 
288  return shellId;
289 }
290 
297 void nonMpiTests( Shell* s )
298 {
299 #ifdef DO_UNIT_TESTS
300  if ( Shell::myNode() == 0 )
301  {
302  unsigned int numNodes = s->numNodes();
303  unsigned int numCores = s->numCores();
304  if ( numCores > 0 )
305  s->setHardware( 1, 1, 0 );
306  MOOSE_TEST("testAsync", testAsync());
307  MOOSE_TEST("testMsg", testMsg());
308  MOOSE_TEST("testShell", testShell());
309  MOOSE_TEST("testScheduling", testScheduling());
310  MOOSE_TEST("testBuiltints", testBuiltins());
311  //MOOSE_TEST("testKinetics", testKinetics());
312  MOOSE_TEST("testKsolve", testKsolve());
313  //MOOSE_TEST("testKsolveProcess", testKsolveProcess());
314  MOOSE_TEST("testBiophysics", testBiophysics());
315  MOOSE_TEST("testDiffusion", testDiffusion());
316  MOOSE_TEST("testHsolve", testHSolve());
317  //MOOSE_TEST("testGeom", testGeom());
318  MOOSE_TEST("testMesh", testMesh());
319  MOOSE_TEST("testSynapse", testSynapse());
320  MOOSE_TEST( "testSigneur", testSigNeur());
321 #ifdef USE_SMOLDYN
322  //MOOSE_TEST(testSmoldyn());
323 #endif
324  s->setHardware( numCores, numNodes, 0 );
325  }
326 #endif
327 }
328 
333 void processTests( Shell* s )
334 {
335 #ifdef DO_UNIT_TESTS
336  MOOSE_TEST( "testSchedulingProcess", testSchedulingProcess());
337  MOOSE_TEST( "testBuiltinsProcess", testBuiltinsProcess());
338  // MOOSE_TEST( "testKineticsProcess", testKineticsProcess());
339  MOOSE_TEST( "testBiophysicsProcess", testBiophysicsProcess());
340  // MOOSE_TEST( "testKineticSolversProcess", testKineticSolversProcess());
341  // MOOSE_TEST( "testSimManager", testSimManager());
342  MOOSE_TEST( "testSigNeurProcess", testSigNeurProcess());
343 #endif
344 }
345 
350 void mpiTests()
351 {
352 #ifdef DO_UNIT_TESTS
353  MOOSE_TEST( "testMpiMsg", testMpiMsg());
354  MOOSE_TEST( "testMpiShell", testMpiShell());
355  MOOSE_TEST( "testMpiBuiltins", testMpiBuiltins());
356  MOOSE_TEST( "testMpiScheduling", testMpiScheduling());
357 #endif
358 }
359 #if ! defined(PYMOOSE) && ! defined(MOOSE_LIB)
360 int main( int argc, char** argv )
361 {
362  bool doUnitTests = 0;
363  bool doRegressionTests = 0;
364  unsigned int benchmark = 0;
365  // This reorders the OpFunc to Fid mapping to ensure it is node and
366  // compiler independent.
367  Id shellId = init( argc, argv, doUnitTests, doRegressionTests, benchmark );
368  // Note that the main loop remains the parser loop, though it may
369  // spawn a lot of other stuff.
370  Element* shelle = shellId.element();
371  Shell* s = reinterpret_cast< Shell* >( shelle->data( 0 ) );
372  if ( doUnitTests )
373  nonMpiTests( s ); // These tests do not need the process loop.
374 
375  if ( Shell::myNode() == 0 )
376  {
377  if ( Shell::numNodes() > 1 )
378  {
379  // Use the last clock for the postmaster, so that it is called
380  // after everything else has been processed and all messages
381  // are ready to send out.
382  s->doUseClock( "/postmaster", "process", 9 );
383  s->doSetClock( 9, 1.0 ); // Use a sensible default.
384  }
385 #ifdef DO_UNIT_TESTS
386  if ( doUnitTests )
387  {
388  mpiTests();
389  processTests( s );
390  }
391  // if ( doRegressionTests ) regressionTests();
392 #endif
393  // These are outside unit tests because they happen in optimized
394  // mode, using a command-line argument. As soon as they are done
395  // the system quits, in order to estimate timing.
396  if ( benchmark != 0 )
397  {
398  mooseBenchmarks( benchmark );
399  s->doQuit();
400  }
401  else
402  {
403  // Here we set off a little event loop to poll user input.
404  // It deals with the doQuit call too.
405  if(! quitFlag)
407  }
408  }
409  else
410  {
411  PostMaster* p = reinterpret_cast< PostMaster* >( ObjId( 3 ).data());
412  while ( Shell::keepLooping() )
413  {
414  p->clearPending();
415  }
416  }
419 #ifdef USE_MPI
420  MPI_Finalize();
421 #endif
422  return 0;
423 }
424 #endif
425 
static unsigned int numCores
static void makeCinfoElements(Id parent)
Definition: Cinfo.cpp:164
Id init(int argc, char **argv, bool &doUnitTests, bool &doRegressionTests, unsigned int &benchmark)
Definition: main.cpp:150
char * data() const
Definition: Eref.cpp:41
void testAsync()
Definition: testAsync.cpp:1813
static void clearAllElements()
Definition: Id.cpp:202
void initMsgManagers()
char * data() const
Definition: ObjId.cpp:113
static unsigned int numCores()
Element * element() const
Synonym for Id::operator()()
Definition: Id.cpp:113
void doSetClock(unsigned int tickNum, double dt)
Definition: Shell.cpp:377
unsigned int value() const
Definition: Id.cpp:197
int main(int argc, char **argv)
Definition: main.cpp:360
static const Cinfo * initCinfo()
Definition: Clock.cpp:133
void testKsolveProcess()
Definition: testKsolve.cpp:338
void testDiffusion()
void testSigNeurProcess()
void testKsolve()
Definition: testKsolve.cpp:329
void testMpiShell()
Definition: testShell.cpp:1833
Definition: ObjId.h:20
static int isInfinite
static void setHardware(unsigned int numCores, unsigned int numNodes, unsigned int myNode)
static void launchParser()
Eref eref() const
Definition: Id.cpp:125
static void children(const Eref &e, vector< Id > &ret)
Definition: Neutral.cpp:342
void testBuiltinsProcess()
void testShell()
Definition: testShell.cpp:1818
static const Cinfo * initCinfo()
Definition: Shell.cpp:46
void testMsg()
Definition: testMsg.cpp:370
void processTests(Shell *s)
Definition: main.cpp:333
void mooseBenchmarks(unsigned int option)
void setShellElement(Element *shelle)
Definition: Shell.cpp:166
void testMpiBuiltins()
static int doRegressionTests
static Id nextId()
Definition: Id.cpp:132
static unsigned int myNode
void testSchedulingProcess()
void testMpiMsg()
Definition: testMsg.cpp:376
void testSigNeur()
void testMpiScheduling()
void nonMpiTests(Shell *s)
Definition: main.cpp:297
static bool keepLooping()
Definition: Shell.cpp:996
void doQuit()
Definition: Shell.cpp:327
static void loadBalance()
void testScheduling()
void testMesh()
Definition: testMesh.cpp:2138
void checkChildren(Id parent, const string &info)
Definition: main.cpp:136
void testBiophysicsProcess()
void clearPending()
All arrived messages and set calls are handled and cleared.
Definition: PostMaster.cpp:215
static unsigned int numNodes
virtual char * data(unsigned int rawIndex, unsigned int fieldIndex=0) const =0
unsigned int getNumCores()
Definition: main.cpp:93
static unsigned int initMsgManagers()
Definition: Msg.cpp:236
static void rebuildOpIndex()
Definition: Cinfo.cpp:589
static bool adopt(ObjId parent, Id child, unsigned int msgIndex)
Definition: Shell.cpp:654
Definition: Id.h:17
void testBiophysics()
void testBuiltins()
void destroyMsgManagers()
static unsigned int myNode()
void doUseClock(string path, string field, unsigned int tick)
Definition: Shell.cpp:382
static const Cinfo * initCinfo()
Definition: PostMaster.cpp:82
static const Cinfo * initCinfo()
Definition: Neutral.cpp:16
static int doUnitTests
static unsigned int numNodes()
bool quitFlag
Definition: main.cpp:132
void testSynapse()
const string & getName() const
Definition: Element.cpp:56
void mpiTests()
Definition: main.cpp:350
void speedTestMultiNodeIntFireNetwork(unsigned int size, unsigned int runsteps)
void testHSolve()
Definition: testHSolve.cpp:11
static void clearAllMsgs()
Definition: Msg.cpp:286
Definition: Shell.h:43