-
Notifications
You must be signed in to change notification settings - Fork 29
/
Copy pathShell.h
616 lines (516 loc) · 19.9 KB
/
Shell.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
/**********************************************************************
** This program is part of 'MOOSE', the
** Messaging Object Oriented Simulation Environment.
** Copyright (C) 2003-2009 Upinder S. Bhalla. and NCBS
** It is made available under the terms of the
** GNU Lesser General Public License version 2.1
** See the file COPYING.LIB for the full notice.
**********************************************************************/
#ifndef _SHELL_H
#define _SHELL_H
#include <string>
using namespace std;
class DestFinfo;
enum AssignmentType { SINGLE, VECTOR, REPEAT };
// These Finfo objects are exposed to other classes for convenience in test cases and other functions.
// NOTE: These should never be re-registered in an initCinfo of another class.
//extern SrcFinfo4< Id, DataId, FuncId, unsigned int >* requestGet(); // Not available
extern DestFinfo* receiveGet();
//extern SrcFinfo2< unsigned int, unsigned int >* ack(); // Not currently used.
enum NodePolicy { MooseGlobal, MooseBlockBalance, MooseSingleNode };
class NodeBalance
{
public:
NodeBalance( unsigned int nd, NodePolicy np, unsigned int node )
: numData( nd ), policy( np ), preferredNode( node )
{
;
}
unsigned int numData;
NodePolicy policy;
unsigned int preferredNode;
};
class Shell
{
public:
Shell();
~Shell();
///////////////////////////////////////////////////////////
// Field functions
///////////////////////////////////////////////////////////
/**
* Returns version number of the software.
*/
string doVersion();
/**
* Assigns the current working Element of the Shell
*/
void setCwe( ObjId cwe );
/**
* Returns the current working Element of the Shell
*/
ObjId getCwe() const;
/**
* Returns flag to indicate whether simulation is still running
*/
bool isRunning() const;
void setupSocketStreamer(const string host, const int port );
///////////////////////////////////////////////////////////
// Parser functions
///////////////////////////////////////////////////////////
/**
* Create an Element. Returns its id.
* type: Specifies classname of Objects in Element.
* parent: Id of parent element
* name: Name to be used for identifying Element.
* numData: Size of array.
*/
Id doCreate( string type, ObjId parent, string name,
unsigned int numData,
NodePolicy nodePolicy = MooseBlockBalance,
unsigned int preferredNode = 1 );
// Same as before but with default nodePolicy and preferredNode. We are
// hidning them away from the python bindings.
Id doCreate2( string type, ObjId parent, string name, unsigned int numData);
/**
* Delete specified Element and all its children and all
* Msgs connected to it. This also works for Msgs, which are
* also identified by an ObjId. Unlike regular objects, only
* the one Msg entry specified by the DataIndex part of the ObjId
* argument is deleted.
*/
bool doDelete( ObjId oid );
/**
* Sets up a Message of specified type.
* Later need to consider doing this through MsgSpecs only.
* Here the 'args' vector handles whatever arguments we may need
* to pass to the specified msgType.
*/
ObjId doAddMsg( const string& msgType,
ObjId src, const string& srcField,
ObjId dest, const string& destField );
/**
* Cleanly quits simulation, wrapping up all nodes and threads.
*/
void doQuit( );
/**
* Starts off simulation, to run for 'runtime' more than current
* time. This version is blocking, and returns only when the
* simulation is done. If `nofity = true' then also notify user
* whenever 10\% of simulation is over.
*/
void doStart( double runtime, bool notify = false );
/**
* Starts off simulation, to run for 'runtime' more than current
* time. This version returns at once, and the parser can go
* on to do other things. It has to check with the
* Shell::isRunning function (accessible as a MOOSE field)
* to find out if it is finished. Can call 'doStop', 'doTerminate'
* or 'doReinit' at any time to stop the run with increasing
* levels of prejudice.
*/
void doNonBlockingStart( double runtime );
/**
* Reinitializes simulation: time goes to zero, all scheduled
* objects are set to initial conditions. If simulation is
* already running, first stops it.
*/
void doReinit();
/**
* Cleanly stops simulation, ready to take up again from where
* the stop occurred. Waits till current operations are done.
*/
void doStop();
/**
* Terminate ongoing simulation, with prejudice.
* Uncleanly stops simulation. Things may be in a mess with
* different objects at different times, but it stops at once.
*/
void doTerminate();
/**
* shifts orig Element (including offspring) to newParent. All old
* hierarchy, data, Msgs etc are preserved below the orig.
*/
void doMove( Id orig, ObjId newParent );
/**
* Copies orig Element to newParent. n specifies how many copies
* are made.
* copyExtMsgs specifies whether to also copy messages from orig
* to objects outside the copy tree. Usually we don't do this.
*/
Id doCopy( Id orig, ObjId newParent, string newName,
unsigned int n, bool toGlobal, bool copyExtMsgs );
/**
* Looks up the Id specified by the given path. May include
* relative references and the internal cwe
* (current working Element) on the shell
*/
ObjId doFind( const string& path ) const;
/**
* Connects up process messages from the specified Tick to the
* targets on the path. Does so for whole Elements, not individual
* entries in the Element array.
* The target on the path usually has the 'process' field but
* other options are allowed, like 'init'
*/
void doUseClock( string path, string field, unsigned int tick );
/**
* Loads in a model to a specified path.
* Tries to figure out model type from fname or contents of file.
* Currently knows about kkit, cspace.
* Soon to learn .p, SBML, NeuroML.
* Later to learn NineML
*/
Id doLoadModel( const string& fname, const string& modelpath,
const string& solverClass = "" );
/**
* Saves specified model to specified file, using filetype
* identified by filename extension. Currently known filetypes are:
* .g: Kkit model
*
* Still to come:
* .p: GENESIS neuron morphology and channel spec file
* .sbml: SBML file
* .nml: NeuroML file
* .9ml: NineML file
* .snml: SigNeurML
*/
void doSaveModel( Id model, const string& fileName, bool qflag = 0 ) const;
/**
* This function synchronizes fieldDimension on the DataHandler
* across nodes. Used after function calls that might alter the
* number of Field entries in the table..
* The tgt is the FieldElement whose fieldDimension needs updating.
*/
void doSyncDataHandler( Id tgt );
/**
* This function builds a reac-diffusion mesh starting at the
* specified ChemCompt, which houses MeshEntry FieldElements.
* Assumes that the dimensions of the baseCompartment have just been
* redefined, and we now need to go through and update the child
* reaction system.
*/
void doReacDiffMesh( Id baseCompartment );
/**
* This function is called by the parser to tell the ProcessLoop
* to wait a bit between cycles. Used when we are waiting for user
* input and there is no point in having the ProcessLoop go at
* full speed. When flag is true, then the ProcessLoop will sleep
* a bit, when false it will work at full speed.
*/
void doSetParserIdleFlag( bool isParserIdle );
/**
* Works through internal queue of operations that modify the
* structure of the simulation. These operations have to be
* carefully separated from any other functions or messaging,
* so this happens while all other threads are blocked.
*/
static void clearRestructuringQ();
///////////////////////////////////////////////////////////
// DestFinfo functions
///////////////////////////////////////////////////////////
/**
* Sets of a simulation for duration runTime. Handles
* cases including single-thread, multithread, and multinode
*/
void start( double runTime );
/**
* Initialize acks. This call should be done before the 'send' goes
* out, because with the wonders of threading we might get a
* response to the 'send' before this call is executed.
* This MUST be followed by a waitForAck call.
*/
void initAck();
/**
* test for completion of request. This MUST be preceded by an
* initAck call.
*/
void waitForAck();
/**
* Generic handler for ack msgs from various nodes. Keeps track of
* which nodes have responded.
*/
void handleAck( unsigned int ackNode, unsigned int status );
/**
* Test for receipt of acks from all nodes
*/
bool isAckPending() const;
/**
* Wraps up operations. Doesn't quit instantly, completes the
* current process cycle first.
*/
void handleQuit();
void handleCreate( const Eref& e,
string type, ObjId parent, Id newElm, string name,
NodeBalance nb, unsigned int parentMsgIndex );
void destroy( const Eref& e, ObjId oid);
/**
* Function that does the actual work of creating a new Element.
* The Class of the Moose objects formed is specified by type.
* The NodeBalance specifies how many entries and how they are
* distributed across nodes.
* The parentMsgIndex specifies the index for the
* parent-child message.
*/
void innerCreate( string type, ObjId parent, Id newElm, string name,
const NodeBalance& nb, unsigned int parentMsgIndex );
/// Does actual work of copying. Returns true on success.
bool innerCopy( const vector< ObjId >& args, const string& newName,
unsigned int n, bool toGlobal, bool copyExtMsgs );
/**
* Connects src to dest on appropriate fields, with specified
* msgType.
* This inner function does NOT send an ack. Returns true on
* success
*/
const Msg* innerAddMsg( string msgType, ObjId src, string srcField,
ObjId dest, string destField, unsigned int msgIndex );
/**
* Connects src to dest on appropriate fields, with specified
* msgType.
* This wrapper function sends the ack back to the master node.
*/
void handleAddMsg( const Eref& e,
string msgType,
ObjId src, string srcField,
ObjId dest, string destField,
unsigned int msgIndex );
/**
* Moves Element orig onto the newParent.
*/
bool innerMove( Id orig, ObjId newParent );
/**
* Handler to move Element orig onto the newParent.
*/
void handleMove( const Eref& e,
Id orig, ObjId newParent );
/**
* Handles sync of DataHandler indexing across nodes
*/
void handleSync( const Eref& e, Id elm, FuncId fid);
/**
* Deep copy of source element to target, renaming it to newName.
* The Args are orig, newParent, newElm
* where the newElm is the Id passed in for the root of the copy.
* All subsequent created Elements should have successive Ids.
* The copy may generate an array with n entries.
* Normally only copies msgs within the tree, but if the flag
* copyExtMsgs is true then it copies external Msgs too.
*/
void handleCopy( const Eref& e,
vector< ObjId > args, string newName, unsigned int n,
bool toGlobal, bool copyExtMsgs );
/**
* Sets up scheduling for elements on the path.
*/
bool innerUseClock( string path, string field,
unsigned int tick, unsigned int msgIndex);
void handleUseClock( const Eref& e,
string path, string field, unsigned int tick,
unsigned int msgIndex );
/**
* Utility function to set up messages to schedule a list of Ids
* using the specified field and tick
*/
void addClockMsgs( const vector< ObjId >& list,
const string& field, unsigned int tick, unsigned int msgIndex );
/**
* Utility function to unschedule the specified elist operating
* on the specified field, typically 'process'
*/
static void dropClockMsgs(
const vector< ObjId >& list, const string& field );
////////////////////////////////////////////////////////////////
// Thread and MPI handling functions
////////////////////////////////////////////////////////////////
/**
* Assigns the hardware availability. Assumes that each node will
* have the same number of cores available.
*/
static void setHardware(
unsigned int numCores, unsigned int numNodes,
unsigned int myNode );
static unsigned int myNode();
static unsigned int numNodes();
static unsigned int numCores();
static unsigned int numProcessThreads();
/**
* Stub for eventual function to handle load balancing. This must
* be called to set up default groups.
*/
static void loadBalance();
static void launchParser();
/**
* True when the parser is in a call which is being blocked because
* it requires the event loop to complete some actions.
*/
static bool inBlockingParserCall();
/**
* True in single-threaded mode. This is a special mode of
* the system in which it does not start up the event loop
* at all, and the whole thing operates on one thread, which
* is ultimately under the control of the parser.
* Note that this is distinct from running on one core. It is
* possible, and even recommended, to run in multithread mode
* even when the system has just one core to run it on.
*/
static bool isSingleThreaded();
/**
* True as long as the main process loop is looping
*/
static bool keepLooping();
/**
* Flag to indicate if the parser is idle. If so, the main
* ProcessLoop should also slow down to avoid pounding on the CPUs
*/
static bool isParserIdle();
/**
* This function sets up the threading for the entire system.
* It creates all the worker threads and the threads for
* handling MPI and handling shell requests.
*/
static void launchThreads();
/**
* Checks for highest 'val' on all nodes
*/
static unsigned int reduceInt( unsigned int val );
////////////////////////////////////////////////////////////////
// Sets up clock ticks. Essentially is a call into the
// Clock::setupTick function, but may be needed to be called from
// the parser so it is a Shell function too.
void doSetClock( unsigned int tickNum, double dt );
// Should set these up as streams so that we can build error
// messages similar to cout.
void warning( const string& text );
void error( const string& text );
static const Cinfo* initCinfo();
////////////////////////////////////////////////////////////////
// Utility functions
////////////////////////////////////////////////////////////////
static bool adopt( ObjId parent, Id child, unsigned int msgIndex );
static bool adopt( Id parent, Id child, unsigned int msgIndex );
static const unsigned int OkStatus;
static const unsigned int ErrorStatus;
// Initialization function, used only in main.cpp:init()
void setShellElement( Element* shelle );
/// Static func for returning the ProcInfo of the shell.
static const ProcInfo* procInfo();
const ProcInfo* getProcInfo( unsigned int index ) const;
/**
* Chops up the names in the string into the vector of strings,
* using the specified separator.
* Returns true if it is an absolute path, that is, starts with the
* separator.
*/
static bool chopString( const string& path, vector< string >& ret,
char separator = '/' );
/**
* Checks that the provided name is valid for an object.
* This returns false if it finds the reserved path chars /#[]
*/
static bool isNameValid( const string& name );
/**
* Chop up the path into a vector of Element names, and
* also fills out a matching vector of indices. If at any level of
* the path there are no indices or the index is zero, the
* index entry * remains empty. Otherwise the entry contains a
* vector with index values for this level of the path.
* The zeroth position of this index vector is the slowest
* varying, i.e., most significant.
* Returns true if it starts at '/'.
*
* Example: /foo/bar[10]/zod[3][4][5] would return:
* ret: {"foo", "bar", "zod" }
* index: { {}, {10}, {3,4,5} }
*/
static bool chopPath( const string& path, vector< string >& ret,
vector< unsigned int >& index );
/**
* Cleans up all Elements except /root itself, /clock, /classes,
* and /Msgs.
* In due course will also do suitable reinitialization of
* tick and other values.
*/
static void cleanSimulation();
/**
* set the gettingVector_ flag
*/
void expectVector( bool flag );
private:
Element* shelle_; // It is useful for the Shell to have this.
/**
* Buffer into which return values from the 'get' command are placed
* Only index 0 is used for any single-value 'get' call.
* If it was the 'getVec' command then the array is filled up
*/
vector< double* > getBuf_;
/**
* Flag, used by the 'get' subsystem which maintains a buffer for
* returned value. True when the returned value is a vector.
*/
bool gettingVector_;
/**
* Counter, used by the 'get' subsystem in order to keep track of
* number of returned values, especially for getVec.
*/
unsigned int numGetVecReturns_;
/**
* Flag: True when the parser thread is blocked waiting for
* some system call to be handled by the threading and the
* MPI connected nodes.
*/
static bool isBlockedOnParser_;
/**
* Flag: Tells the ProcessLoop to keep on going.
* Should only be altered during a barrier.
*/
static bool keepLooping_;
/**
* Number of CPU cores in system.
*/
static unsigned int numCores_;
/**
* Number of threads dedicated to the ProcessLoop.
* The parser thread is the master thread.
* Additional threads may be created for graphics, but not now.
*/
static unsigned int numProcessThreads_;
/**
* Number of nodes in MPI-based system. Each node may have many
* threads.
*/
static unsigned int numNodes_;
/**
* Identifier for current node
*/
static unsigned int myNode_;
/**
* Shell owns its own ProcInfo, has global thread/node info.
* Used to talk to parser and for thread specification in
* setup operations.
*/
static ProcInfo p_;
static vector< ProcInfo > threadProcs_;
/**
* Array of threads, initialized in launchThreads.
*/
static unsigned int numAcks_;
static vector< unsigned int > acked_;
/**
* Flag to tell system to reinitialize. We use this to defer the
* actual operation to the 'process' call for a clean reinit.
*/
static bool doReinit_;
/**
* Simulation run time
*/
static double runtime_;
static bool isParserIdle_;
/// Current working Element
ObjId cwe_;
};
/*
extern bool set( Eref& dest, const string& destField, const string& val );
extern bool get( const Eref& dest, const string& destField );
*/
#endif // _SHELL_H