Skip to content
Snippets Groups Projects
Select Git revision
  • ec5baf0e268089f2cc1e7f1f088214b5ceb7685f
  • master default protected
  • github/fork/hrani/master
  • github/fork/dilawar/master
  • chamcham
  • chhennapoda
  • wheel
  • 3.2.0-pre0
  • v3.1.3
  • 3.1.2
  • 3.1.1
  • chamcham-3.1.1
  • 3.1.0
  • ghevar_3.0.2_pre2
  • ghevar_3.0.2
15 results

Shell.h

Blame
  • user avatar
    Dilawar Singh authored
    git-subtree-dir: moose-core
    git-subtree-split: fe77059f98c5a6cab2e106f78b7eb505f4f62850
    e6e83b76
    History
    Shell.h 20.64 KiB
    /**********************************************************************
    ** 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();
    
    #ifdef  CYMOOSE
    
        /**
         * @brief Initialize shell.
         *
         * @return Pointer to shell.
         *
         * This function initialize shell and returns a pointer to it.
         * This function must create a fully functional shell which can
         * be used by cython interface.
         */
        Shell* initShell();
    
    
        /**
         * @brief A thin wrapper around doCreate function. Used in
         * cython interface.
         *
         * @param type Type of Moose-element to be created e.g. Table,
         * Compartment, etc.
         * @param parent Parent element under which this element is
         * being created.
         * @param name Name of the element. String.
         * @param numData
         * @param nodePolicy
         * @param preferredNode
         *
         * @return Id of the element.
         */
        Id create( string type, string name, unsigned int numData,
                   NodePolicy nodePolicy = MooseBlockBalance,
                   unsigned int preferredNode = 1 );
    
    
    #endif     /* -----  CYMOOSE  ----- */
        ///////////////////////////////////////////////////////////
        // 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;
    
        ///////////////////////////////////////////////////////////
        // 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 );
    
        /**
         * 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 );
    
        // static void wildcard( const string& path, vector< Id >& list );
    
        /**
         * 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