///////////////////////////////////////////////////////////////////////////// //! simlib.h - SIMLIB/C++ main interface // // SIMLIB version: 2.18 // Date: 2004-11-07 // // ------------------------------------------------------------------------- // SIMLIB/C++ (SIMulation LIBrary for C++) // ------------------------------------------------------------------------- // Copyright (c) 1991-2004 Petr Peringer // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Library General Public // License as published by the Free Software Foundation; either // version 2 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Library General Public License for more details. // // You should have received a copy of the GNU Library General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 // USA. // ------------------------------------------------------------------------- // // This is main interface for SIMLIB/C++ // // Supported platforms: // Linux: GNU C++ compiler, arch i386+ // Portable to: // FreeBSD: GNU C++, i386+ // MSDOS: DJGPP v2.0 = GNU C++ compiler for MSDOS (DPMI) // WIN95: Borland C++ (v5.0, console application) // // WARNING: this is debugging version! // // Send bug reports to: peringer AT fit.vutbr.cz // // EXPERIMENTAL: #define NEW_WULIST #ifndef __SIMLIB_H #define __SIMLIB_H #define __SIMLIB__ 0x0218 // version of SIMLIB #define SIMLIB_VERSION "2.18" #ifndef __cplusplus # error Use C++ compiler, please. #endif // system and compiler dependent part #if defined(__MSDOS__) # define SIMLIB_SYSTEM "MSDOS" # if defined(__BCPLUSPLUS__) # error Borland C++ for DOS no longer supported (use DJGPP) # elif defined(__GNUG__) # define SIMLIB_COMPILER "GNU C++" # else # error This compiler is not supported (under MSDOS) # endif #elif defined(__linux__) # define SIMLIB_SYSTEM "Linux" # define SIMLIB_COMPILER "GNU C++" #elif defined(__WIN32__) && defined(__BCPLUSPLUS__) // check###!!! # define SIMLIB_SYSTEM "WIN32" # define SIMLIB_COMPILER "Borland C++" #elif defined(__FreeBSD__) # define SIMLIB_SYSTEM "FreeBSD" # define SIMLIB_COMPILER "GNU C++" #elif defined(__unix__) // ?????????????????######### # define SIMLIB_SYSTEM "Unixware?" # define SIMLIB_COMPILER "GNU C++" #else # error "SIMLIB is not implemented for this system/compiler" #endif //////////////////////////////////////////////////////////////////////////// // what we expect: // type bool, // standard ISO C++ containers and iterators (for implementation) // //////////////////////////////////////////////////////////////////////////// // DEBUGGING: print debug info ON/OFF/mode // void DebugON(); void DebugOFF(); unsigned long Debug(unsigned long mode=~0UL); // start/stop partial debugging // experimental code for start/stop debugging at global level #ifdef SIMLIB_DEBUG static unsigned long SIMLIB_old_debug_flags = Debug(SIMLIB_DEBUG); #endif //////////////////////////////////////////////////////////////////////////// // ATEXIT: special internal class for atexit, etc... // class SIMLIB_module { // internal class for SIMLIB cleanup (atexit) const char *string; // module identification string SIMLIB_module(const SIMLIB_module&); // disable copy-ctr SIMLIB_module &operator= (const SIMLIB_module&); // disable op= public: SIMLIB_module(); int Init(const char *s); ~SIMLIB_module(); }; // create single global registration object in each module static SIMLIB_module SIMLIB_module_id; //////////////////////////////////////////////////////////////////////////// // includes ... // // remove it !!! ### #include // will be removed // Leska: // try this instead the above if you have class list // and don't forget to link g++ library! #include #define dlist std::list //////////////////////////////////////////////////////////////////////////// // overwiew of basic SIMLIB classes (abstractions) // class SimObject; // base abstract class // discrete: class Link; // list item base class (Simula-like) class Entity; // discrete model entity class Process; // process base class Event; // event base class Sampler; // periodic calls of global function class List; // list of objects of class Link descendants class Queue; // priority queue class Stat; // statistics class TStat; // time dependent statistics class Histogram; // histogram class Facility; // SOL-like facility class Store; // SOL-like store class Barrier; // barrier class Semaphore; // semaphore // continuous: class aBlock; // abstract block class aContiBlock; // blocks with continuous output class Integrator; // integrator class Status; // status variables class Hyst; // hysteresis class Blash; // backlash class Relay; // general relay class Function; // general function class Constant; // constant class Variable; // variable class Parameter; // parameter (simulation run constant) //class aBoolBlock; // Boolean blocks // combined: class aCondition; // state condition base class class Condition; // state event detector (Boolean version) class ConditionUp; // action by FALSE-->TRUE change class ConditionDown; // action by TRUE-->FALSE //////////////////////////////////////////////////////////////////////////// // CATEGORY: global constants //////////////////////////////////////////////////////////////////////////// // simulation time limits // const double SIMLIB_MINTIME = 0.0; const double SIMLIB_MAXTIME = 1.0e30; //////////////////////////////////////////////////////////////////////////// // CATEGORY: global variables ... extern Entity *const &Current; // active (now running) entity // step limits of numerical integration method extern const double &MinStep; // minimal step size extern const double &StepSize; // actual step size extern const double &OptStep; // optimal step size extern const double &MaxStep; // max. step size // error params extern const double &AbsoluteError; // max. abs. error of num. integration extern const double &RelativeError; // max. rel. error ... // Phase type --- indicates current phase of experiment enum SIMLIB_Phase_t { START, INITIALIZATION, SIMULATION, TERMINATION, ERROREXIT }; // phase of experiment extern const SIMLIB_Phase_t &Phase; // for user checking ### remove? //////////////////////////////////////////////////////////////////////////// // CATEGORY: global functions ... inline void Init(double t0, double t1=SIMLIB_MAXTIME) // initialization { extern void SIMLIB_Init(double t0, double t1, unsigned version); SIMLIB_Init(t0,t1,__SIMLIB__); // consistency check... } void SetStep(double dtmin, double dtmax); // set integration step interval inline void SetStep(double dt) { SetStep(dt,dt); } // set fixed integration step void SetAccuracy(double abserr, double relerr); // max. error void SetAccuracy(double relerr); // rel. error void Run(); // simulation run (experiment) void Stop(); // stops the simulation run void Abort(); // end of program void Error(const char *fmt, ...); // print message & end of program int _Print(const char *fmt, ...);// non-fatal error messages (stdout) int Print(const char *fmt, ...); // for Output methods, can be redirected int Print(const double x); // output double int Print(const double x, const double y); int Print(const double x, const double y, const double x); void SetOutput(const char *name); // redirection of Output(), Print() void ContractStep(); // request for shorter step of num. integ. void ContractStep(double time); // request for step end at given time //////////////////////////////////////////////////////////////////////////// // CATEGORY: pseudorandom generators // void RandomSeed(long seed=1537L);// initialize random number seed double Random(); // base uniform generator 0-0.999999... // default Random can be replaced by user-defined base generator: void SetBaseRandomGenerator(double (*new_gen)()); // all following generators depend on Random() double Beta(double th, double fi, double min, double max); double Erlang(double alfa, int beta); double Exponential(double mv); double Gama(double alfa, double beta); int Geom(double q); int HyperGeom(double p, int n, int m); double Logar(double mi, double delta); int NegBinM(double p,int m); int NegBin(double q, int k); double Normal(double mi, double sigma); int Poisson(double lambda); double Rayle(double delta); double Triag(double mod, double min, double max); double Uniform(double l, double h); double Weibul(double lambda, double alfa); //////////////////////////////////////////////////////////////////////////// // CATEGORY: basics //////////////////////////////////////////////////////////////////////////// //! base of class hierarchy in SIMLIB // class SimObject { enum _Flags { _ALLOCATED = 1 }; // internal flags protected: const char * _name; unsigned _flags; public: SimObject(); virtual ~SimObject(); void *operator new(size_t size); // allocate object, set _flags void operator delete(void *ptr); // deallocate virtual void Output(); // print object to default output virtual const char *Name(); // object name bool HasName() const { return _name !=0; } void SetName(const char *name); // assign the name bool IsAllocated() const { return _flags & _ALLOCATED; } private: SimObject(SimObject&); // disable operation void operator= (SimObject&); // disable operation }; //////////////////////////////////////////////////////////////////////////// //! base class for all double-linked list items // class Link : public SimObject { Link(Link&); // disable operation void operator= (Link&); // disable operation Link *pred; // previous object in List Link *succ; // next object in List List *head; // pointer to List (if any) friend class List; // only list can access pred,succ,head protected: Link(Link *p, Link *s, List *h); public: Link(); virtual ~Link(); virtual void Into(List *l); // insert last virtual void Out(); // remove from list List *where() { return head; } // where is linked TODO: rename virtual bool isInQueue() { return where()!=NULL; } // in queue }; //////////////////////////////////////////////////////////////////////////// // CATEGORY: discrete blocks //! entity/process priority values enum { LOWEST_PRIORITY = 0, HIGHEST_PRIORITY = 255, DEFAULT_PRIORITY = LOWEST_PRIORITY }; typedef unsigned char EntityPriority_t; // process priority typedef unsigned char ServicePriority_t; // service priority (see Facility) //////////////////////////////////////////////////////////////////////////// //! abstract base class of all active entities // class Entity : public Link { Entity(const Entity&); //## disable Entity&operator=(const Entity&); //## disable protected: static unsigned long _Number; // current number of entities unsigned long _Ident; // unique identification of entity // next will be changed/removed: // Queue stores insertion time for statistics: friend class Queue; // ### remove double _MarkTime; // beginning of waiting in queue ###!!! // Facility and Store use these data friend class Facility; friend class Store; union { double _RestTime; // rest of time of interrupted service (Facility) ### unsigned long _ReqCapacity; // required store capacity of Store }; ServicePriority_t _SPrio; // priority of service (in Facility) ### public: typedef EntityPriority_t Priority_t; Priority_t Priority; // priority of the entity Entity(Priority_t p = DEFAULT_PRIORITY); virtual ~Entity(); operator Entity* () { return this; } virtual const char *Name(); virtual void Activate(); // activate now virtual void Activate(double t); // activate in time t (schedule) virtual void Passivate(); // deactivation // virtual void Wait(double dtime); // wait dtime time units virtual void Terminate(); // end of behavior and remove entity bool Idle() { return _Ev==0; } // is not scheduled void Cancel() { Terminate(); } // virtual void Into(Queue *q); // insert into queue virtual void Out(); // remove from queue private: void *_Ev; // points into calendar, if scheduled virtual void _Run() = 0; // run entity behavior // friends: friend class Calendar; // internal class friend class EventNotice; // internal calendar class friend void SIMLIB_DoActions(); // internal function - event dispatch }; // global functions: inline void Activate(Entity *e) { e->Activate(); } // activate entity e inline void Passivate(Entity *e) { e->Passivate(); } // passivate entity e //////////////////////////////////////////////////////////////////////////// #define WaitUntil(expr) while(_WaitUntil(expr)); //////////////////////////////////////////////////////////////////////////// //! abstract base class for processes // class Process : public Entity { Process(const Process&); //## disable Process&operator=(const Process&); //## disable char * volatile _p; // stack contents volatile unsigned int _size; // size of stack contents jmp_buf _ProcStatus; // stack status (for longjmp) enum ProcessStatus_t { _PREPARED=1, _RUNNING, _INTERRUPTED, _TERMINATED }; unsigned char _status; #ifdef NEW_WULIST bool _wait_until; void _WaitUntilRemove(); friend class WaitUntilList; #endif bool isCurrent() { return (_status==_RUNNING); } // called from _Run() bool Terminated() { return (_status==_TERMINATED); } // zombie... virtual void _Run(); // point of activation public: Process(Priority_t p=DEFAULT_PRIORITY); virtual ~Process(); virtual void Behavior() = 0; // behavior description virtual void Output(); // print object virtual const char *Name(); // name of object virtual void Activate(); // activate now virtual void Activate(double t); // activate in time t (schedule) virtual void Passivate(); // sleeping process (deactivation) virtual void Wait(double dtime); // wait dtime interval bool _WaitUntil(bool test); // wait for condition (slow!) void Interrupt(); // perform test of WaitUntil list ### virtual void Terminate(); // end of process // move to global level, use Current ???type check problem void Seize(Facility &f, ServicePriority_t sp=0); // void Release(Facility &f); // void Enter(Store &s, unsigned long ReqCap=1); // void Leave(Store &s, unsigned long ReqCap=1); // virtual void Into(Queue &q); // insert into queue }; //////////////////////////////////////////////////////////////////////////// //! abstract base class for events // class Event : public Entity { virtual void _Run(); public: Event(Priority_t p=DEFAULT_PRIORITY); virtual ~Event(); virtual void Output(); // print object virtual const char *Name(); virtual void Behavior() = 0; // behavior description // inherited: Activate, Passivate, Cancel==Terminate }; //////////////////////////////////////////////////////////////////////////// //! objects of this class call global function periodically // (typicaly used for output) // class Sampler: public Event { Sampler(const Sampler&); //## disable Sampler&operator=(const Sampler&); //## disable static Sampler *First; // list of objects Sampler *Next; // next object protected: void (*function)(); double last; // last sample -- prevents Stop() from sample duplication double step; // step of sampling bool on; // switch on/off virtual void Behavior(); // behavior description public: Sampler(void (*pf)(), double dt=0.0); virtual ~Sampler(); virtual void Output(); // print object void Start(); // start + sample void Stop(); // sample + stop void Sample(); // performs sample (function call) double SetStep(double dt=0.0); // change step double GetStep() const { return step; } private: static void InitAll(); // initialize all samplers (Init) static void ActivateAll(); // start all samplers (Run) }; //////////////////////////////////////////////////////////////////////////// // CATEGORY: discrete blocks - pasive #ifdef new_version //////////////////////////////////////////////////////////////////////////// //! abstract base class of all statistics // class aStat : public SimObject { protected: double t0; // time of initialization double min; // minimal recorded value double max; // maximal recorded value unsigned long n; // number of values recorded public: aStat(); aStat(const char *name); ~aStat(); virtual void Clear() = 0; // initialize virtual void Output(); // print statistic virtual void operator () (double x) = 0; // record value virtual double MeanValue() = 0; // compute mean value double Min() const { /* test n==0 */ return min; } double Max() const { /* test n==0 */ return max; } unsigned long Number() const { return n; } double StartTime() const { return t0; } }; #endif //////////////////////////////////////////////////////////////////////////// //! statistics // class Stat : public SimObject { protected: double sx; // sum of values double sx2; // sum of value square double min; // min value double max; // max value unsigned long n; // number of values recorded public: Stat(); Stat(const char *name); ~Stat(); virtual void Clear(); // initialize void operator () (double x); // record the value // Stat &operator = (Stat &x); // ??? semantics // Stat &operator += (Stat &x); virtual void Output(); // print statistic unsigned long Number() const { return n; } double Min() const { /* TODO: test n==0 */ return min; } double Max() const { /* test n==0 */ return max; } double Sum() const { return sx; } double SumSquare() const { return sx2; } double MeanValue() const; double StdDev() const; }; //////////////////////////////////////////////////////////////////////////// //! time dependent statistic // class TStat : public SimObject { protected: double sxt; // sum of x*time double sx2t; // sum of squares double min; // min value x double max; // max value x double t0; // time of initialization double tl; // last record time double xl; // last recorded value x unsigned long n; // number of records friend class Facility; // needs to correct n -- TODO: remove friend class Store; friend class Queue; public: TStat(double initval=0.0); TStat(const char *name, double initval=0.0); ~TStat(); virtual void Clear(double initval=0.0); // initialize virtual void Output(); // print virtual void operator () (double x); // record value unsigned long Number() const { return n; } double Min() const { /*TODO: only if(n>0)*/ return min; } double Max() const { return max; } double Sum() const { return sxt; } double SumSquare() const { return sx2t; } double StartTime() const { return t0; } double LastTime() const { return tl; } double LastValue() const { return xl; } double MeanValue() const; }; //////////////////////////////////////////////////////////////////////////// //! list of Link* items, uses data from Link // class List : public Link { // circular list of Link items List(List&); // disable void operator= (List&); // disable static Link *next(Link*p) { return p->succ; } static Link *previous(Link*p) { return p->pred; } unsigned n; // number of objects in list protected: //## repair class iterator { // next two lines can be removed ## Link *p; // position in List public: iterator(const iterator&x): p(x.p) {} iterator &operator=(const iterator&x) { p = x.p; return *this; } iterator(Link *pos) : p(pos) {} iterator &operator++() { p = List::next(p); return *this; } iterator &operator--() { p = List::previous(p); return *this; } iterator operator++(int) { Link *tmp = p; p = List::next(p); return tmp; } iterator operator--(int) { Link *tmp = p; p = List::previous(p); return tmp; } Link * operator*() const { return p; } bool operator != (iterator q) const { return p!=q.p; } bool operator == (iterator q) const { return p==q.p; } }; // iterator friend class iterator; public: List(); List(const char *_name); ~List(); virtual void Output(); // print // should be renamed: void InsFirst(Link *e); // insert operations void InsLast (Link *e); void PredIns(Link *e, iterator pos); // void PostIns(Link *e, iterator pos); // Link *GetFirst(); // removing operations Link *GetLast(); // virtual Link *Get(iterator pos); // remove at position // unsigned Length() { return size(); } // COMPATIBILITY // virtual void Clear() { clear(); } // remove all items // new-style: unsigned size() const { return n; } iterator begin() { return Link::succ; } iterator end() { return this; } Link *front() { return empty() ? 0 : Link::succ; } Link *back() { return empty() ? 0 : Link::pred; } bool empty() { return Link::succ == this; } void clear(); }; // List //////////////////////////////////////////////////////////////////////////// //! priority queue // class Queue : public List { // don't inherit interface for now //##repair friend class Facility; friend class Store; public: typedef List::iterator iterator; TStat StatN; Stat StatDT; // statistics Queue(); Queue(const char *_name); ~Queue(); virtual const char *Name(); virtual void Output(); // print operator Queue* () { return this; } // allows Queue instead Queue* iterator begin() { return List::begin(); } iterator end() { return List::end(); } Entity *front() { return (Entity*)List::front(); } Entity *back() { return (Entity*)List::back(); } void clear(); // size(), empty() inherited // backward COMPATIBILITY void Clear() { clear(); } bool Empty() { return empty(); } unsigned Length() { return size(); } // to rename: void Insert (Entity *e); // priority insert void InsFirst(Entity *e); void InsLast (Entity *e); void PredIns (Entity *e, iterator pos); // insert at position void PostIns (Entity *e, iterator pos); Entity *Get(iterator pos); // remove entity Entity *GetFirst(); Entity *GetLast(); }; //////////////////////////////////////////////////////////////////////////// //! histogram and statistics // class Histogram : public SimObject { Histogram(const Histogram&); // ## disable Histogram&operator=(const Histogram&); // ## disable protected: unsigned *dptr; // value array double low; // low bound double step; // interval width unsigned count; // number of intervals public: Stat stat; // statistics Histogram(); Histogram(double low, double step, unsigned count=10); Histogram(const char *_name, double low, double step, unsigned count=10); ~Histogram(); virtual void Output(); // print void Init(double low, double step, unsigned count); void operator () (double x); // record value x virtual void Clear(); // initialize (zero) value array double Low() const { return low; } double High() const { return low + step*count; } double Step() const { return step; } unsigned Count() const { return count; } unsigned operator [](unsigned i) const; // # of items in interval[i] }; //////////////////////////////////////////////////////////////////////////// //! (SOL-like) facility // class Facility : public SimObject { Facility(const Facility&); // ## disable Facility&operator=(const Facility&); // ## disable unsigned char _Qflag; public: Entity *in; // entity in service Queue *Q1; // input queue Queue *Q2; // interrupted requests queue TStat tstat; // stat Facility(); Facility(const char *_name); Facility(Queue *_queue1); Facility(const char *_name, Queue *_queue1); virtual ~Facility(); virtual void Output(); // print output operator Facility* () { return this; } void SetQueue(Queue *queue1); // change input queue bool OwnQueue() const; // test bool Busy() const { return in!=0; } unsigned QueueLen() const { return Q1->size(); } virtual void Seize(Entity *e, ServicePriority_t sp=DEFAULT_PRIORITY); virtual void Release(Entity *e); virtual void QueueIn(Entity *e, ServicePriority_t sp); // go into queue Q1 virtual void Clear(); // init protected: virtual void QueueIn2(Entity *e); // do into Q2 }; //////////////////////////////////////////////////////////////////////////// //! (SOL-like) store // class Store : public SimObject { Store(const Store&); // ## disable Store&operator=(const Store&); // ## disable unsigned char _Qflag; unsigned long capacity; // capacity of store unsigned long used; // used capacity public: Queue *Q; TStat tstat; // statistics Store(); Store(unsigned long _capacity); Store(const char *_name, unsigned long _capacity); Store(unsigned long _capacity, Queue *queue); Store(const char *_name, unsigned long _capacity, Queue *queue); virtual ~Store(); virtual void Output(); // print operator Store* () { return this; } void SetCapacity(unsigned long _capacity); void SetQueue(Queue *queue); unsigned long Free() const { return capacity - used; } // free capacity unsigned long Used() const { return used; } // used capacity unsigned long Capacity() const { return capacity; } // max capacity bool Full() const { return Free() == 0; } // store is full bool Empty() const { return Used() == 0; } // store is empty bool OwnQueue(); unsigned QueueLen() const { return Q->size(); } virtual void Enter(Entity *e, unsigned long rcap); // allocate virtual void Leave(unsigned long rcap); // deallocate virtual void QueueIn(Entity *e, unsigned long c); // go into queue virtual void Clear(); // init }; //////////////////////////////////////////////////////////////////////////// // CATEGORY: continuous blocks // //////////////////////////////////////////////////////////////////////////// //! abstract base class for all blocks // class aBlock : public SimObject { // base class }; //////////////////////////////////////////////////////////////////////////// //! abstract base for continuous blocks with single output // class aContiBlock : public aBlock { // abstract continuous block aContiBlock(const aContiBlock&); // disable copy ctr void operator= (aContiBlock&); // disable assignment virtual void Eval() {}; // evaluate without loop detection protected: bool isEvaluated; // flag for loop checking ###--- public: aContiBlock(): isEvaluated(false) {} virtual void _Eval(); // evaluate with loop detection virtual double Value() = 0; // output value }; //////////////////////////////////////////////////////////////////////////// //! constant block - value can't be changed // class Constant : public aContiBlock { const double value; public: Constant(double x) : value(x) {} virtual double Value () { return value; } }; //////////////////////////////////////////////////////////////////////////// //! block: variable (value can be changed) // class Variable : public aContiBlock { double value; public: Variable(double x=0) : value(x) {} Variable &operator= (double x) { value = x; return *this; } virtual double Value () { return value; } }; //////////////////////////////////////////////////////////////////////////// //! variable parameter (can't be changed at simulation time) // class Parameter : public aContiBlock { double value; public: Parameter(double x) : value(x) {} Parameter &operator= (double x) { value = x; return *this; } // add test ###!!! virtual double Value () { return value; } }; // time values: extern const double & StartTime; // time of simulation start extern const double & NextTime; // next-event time extern const double & EndTime; // time of simulation end //!WARNING: Time cannot be used in block expressions! extern const double & Time; // model time (is NOT the block) extern aContiBlock & T; // model time (continuous block) //////////////////////////////////////////////////////////////////////////// //! continuous block connection (transparent reference) // class Input { // small objects, without virtual methods aContiBlock *bp; public: Input(const Input &in): bp(in.bp) {} // copy reference Input(aContiBlock &cb): bp(&cb) {} // reference to block Input(aContiBlock *cb): bp(cb) {} // pointer to block Input(const double c): bp(new Constant(c)) {} // expression of type double // WARNING: using C++ variables in block expressions --> constant Input Set(Input i) { Input p=bp; bp=i.bp; /*LoopCheck();*/ return p; } double Value() const { return bp->Value(); } // get value bool operator ==(aContiBlock *p) const { return bp==p; } // for tests only! ### Input &operator= (const Input&x) { bp = x.bp; return *this; } }; //////////////////////////////////////////////////////////////////////////// //! base for continuous blocks with single input and algebraic loop check // class aContiBlock1 : public aContiBlock { Input input; public: aContiBlock1(Input i); double InputValue() { return input.Value(); } }; //////////////////////////////////////////////////////////////////////////// //! reference to block expression // struct Expression : public aContiBlock1 { Expression(Input i) : aContiBlock1(i) {} double Value() { return InputValue(); } }; //////////////////////////////////////////////////////////////////////////// //! base for continuous blocks with two inputs // class aContiBlock2 : public aContiBlock { Input input1; Input input2; public: aContiBlock2(Input i1, Input i2); double Input1Value() { return input1.Value(); } double Input2Value() { return input2.Value(); } }; //////////////////////////////////////////////////////////////////////////// //! base for continuous blocks vith three inputs and algebraic loop check // class aContiBlock3 : public aContiBlock { Input input1; Input input2; Input input3; public: aContiBlock3(Input i1, Input i2, Input i3); double Input1Value() { return input1.Value(); } double Input2Value() { return input2.Value(); } double Input3Value() { return input3.Value(); } }; //////////////////////////////////////////////////////////////////////////// //! internal // IntegratorContainer - container of integrators, // it is a singleton // class IntegratorContainer { private: static dlist * ListPtr; // list of integrators IntegratorContainer(); // forbid constructor static dlist * Instance(void); // return list (& create) public: typedef dlist::iterator iterator; // is there any integrator in the list? (e.g. list is not empty) static bool isAny(void) { return ListPtr!=0 && !(ListPtr->empty()); } // # of elements in the list static size_t Size(void) { return (ListPtr!=0) ? (ListPtr->size()) : 0; } // return iterator to the first element static iterator Begin(void) { return Instance()->begin(); } // return iterator to the end (not to the last element!) static iterator End(void) { return Instance()->end(); } static iterator Insert(Integrator* ptr); // insert element into container static void Erase(iterator it); // exclude element static void InitAll(); // initialize all static void EvaluateAll(); // evaluate all integrators static void LtoN(); // last -> now static void NtoL(); // now -> last }; // class IntegratorContainer //////////////////////////////////////////////////////////////////////////// //! internal // StatusContainer -- container of status variables, // it is a singleton // class StatusContainer { private: static dlist* ListPtr; // list of integrators StatusContainer(); // forbid constructor static dlist* Instance(void); // return list (& create) public: typedef dlist::iterator iterator; // is there any integrator in the list? (e.g. list is not empty) static bool isAny(void) { return ListPtr!=0 && !(ListPtr->empty()); } // # of elements in the list static size_t Size(void) { return (ListPtr!=0) ? (ListPtr->size()) : 0; } // return iterator to the first element static iterator Begin(void) { return Instance()->begin(); } // return iterator to the end (not to the last element!) static iterator End(void) { return Instance()->end(); } static iterator Insert(Status* ptr); // insert element into container static void Erase(iterator it); // exclude element static void InitAll(); // initialize all static void ClearAllValueOK(); // invalidate values of all items static void EvaluateAll(); // evaluate all integrators static void LtoN(); // last -> now static void NtoL(); // now -> last }; // class StatusContainer //////////////////////////////////////////////////////////////////////////// //! internal // IntegrationMethod // Abstract base class for integration methods // class IntegrationMethod { IntegrationMethod(const IntegrationMethod&); // ## disable IntegrationMethod&operator=(const IntegrationMethod&); // ## disable private: static IntegrationMethod* CurrentMethodPtr; // method used at present static dlist* MthLstPtr; // list of registrated methods dlist::iterator ItList; // position in the list char* Name; // the name of the method protected: //## repair class Memory; // forward declaration friend class Memory; private: //## repair size_t PrevINum; // # of integrators in previous step dlist MList; // list of auxiliary memories static dlist * PtrMList; // pointer to list being filled IntegrationMethod(); // forbid implicit constructor IntegrationMethod(IntegrationMethod&); // forbid implicit copy-constructor static bool Prepare(void); // prepare system for integration step static void Iterate(void); // compute new values of state blocks static void Summarize(void); // set up new state after integration protected: static bool IsEndStepEvent; // flag - will be event at the end of the step? typedef IntegratorContainer::iterator Iterator; // iterator of intg. list static Iterator FirstIntegrator(void) { // it. to first integrator in list return IntegratorContainer::Begin(); } static Iterator LastIntegrator(void) { // it. to last integrator in list return IntegratorContainer::End(); } static bool StateCond(void); // check on changes of state conditions static IntegrationMethod* SearchMethod(const char* name); // find method /* memory of auxiliary values */ class Memory { Memory(const Memory&); // ## disable Memory&operator=(const Memory&); // ## disable private: static const size_t page_size; // size of memory page double *arr; // array size_t mem_size; // allocated memory size Memory(Memory&); // forbid copy constructor void operator= (Memory&); // disable the operation dlist::iterator it_list; // position in list dlist * ListPtr; // which list is memory in public: Memory(dlist * PtrList=PtrMList); // create empty memory virtual ~Memory(); double& operator[](size_t ind) { // access the element of the array // dprintf(("IntegrationMethod::Memory::operator[](%lu) = %g", // (long unsigned)ind, arr[ind])); return arr[ind]; } virtual void Resize(size_t cs); // change size, content will be undefined! }; // class Memory public: IntegrationMethod(const char* name); // registrate method and name it virtual ~IntegrationMethod(); // destructor unregistrates method virtual bool IsSingleStep(void)=0; // is it a single-step method? virtual void TurnOff(void); // turn off integration method virtual void Integrate(void) = 0; // the method does integration virtual bool PrepareStep(void); // prepare object for integration step virtual void Resize(size_t size); // resize all memories to given size static void StepSim(void); // single step of numerical integration method static void IntegrationDone(void) { // terminate integration CurrentMethodPtr->TurnOff(); // suspend present method } static void SetMethod(const char* name); // set method which will be used static char* const GetMethod(void) { // get name of method which is used return CurrentMethodPtr->Name; } // auxiliary functions (interface) for user to add own method static void InitStep(double step_frag); // initialize step static void FunCall(double step_frag); // evaluate y'(t) = f(t, y(t)) static void SetOptStep(double opt_step) { // set optimal step size extern double SIMLIB_OptStep; // available without including internal.h SIMLIB_OptStep = opt_step; } static void SetStepSize(double step_size) { // set step size extern double SIMLIB_StepSize; // available without including internal.h SIMLIB_StepSize = step_size; } static bool IsConditionFlag(void) { // wer any changes of condition vector? extern bool SIMLIB_ConditionFlag; // available without ... blah, blah return SIMLIB_ConditionFlag; } static int GetErrNo(void) { // return # of errors extern int SIMLIB_ERRNO; return SIMLIB_ERRNO; } static void SetErrNo(int num) { // set # of errors extern int SIMLIB_ERRNO; SIMLIB_ERRNO = num; } }; // class IntegrationMethod //////////////////////////////////////////////////////////////////////////// //! internal // single-step integration method // class SingleStepMethod : public IntegrationMethod { private: // flag: single-step method is used to start multi-step method // (e. g. to restrict step increasing) bool StartMode; public: SingleStepMethod(const char* name) : // initialize method and registrate it IntegrationMethod(name), StartMode(false) { /* NOTHING */ } virtual void Integrate(void) = 0; // the method does integration virtual bool IsSingleStep(void) { // it's a single-step method return true; } void SetStartMode(bool start_mode) { // set flag on/off StartMode=start_mode; } bool IsStartMode(void) { // is method used to start multi-step method? return StartMode; } }; // class SingleStepMethod //////////////////////////////////////////////////////////////////////////// //! internal // multi-step integration method // class MultiStepMethod : public IntegrationMethod { MultiStepMethod(const MultiStepMethod&); // ## disable MultiStepMethod&operator=(const MultiStepMethod&); // ## disable private: char* SlaveName; // the name of the method used for starting SingleStepMethod* Slave_Ptr; // pointer to the method used for starting protected: SingleStepMethod* SlavePtr(void); // return pointer to the starting method public: // initialize method MultiStepMethod(const char* name, const char* slave_name); ~MultiStepMethod(); // destructor frees dynamic data virtual bool IsSingleStep(void) { // it's a multi-step method return false; } // set starting method for given method static void SetStarter(const char* name, const char* slave_name); // set starting method for the method virtual void SetStarter(const char* slave_name); // get the name of starting method of given method static char* const GetStarter(const char* name); virtual bool PrepareStep(void); // prepare the object for the step virtual void Integrate(void) = 0; // the method does integration virtual void TurnOff(void); // turn off method & its slave }; // class MultiStepMethod //////////////////////////////////////////////////////////////////////////// //! internal // Abstract base class for integration methods // with status auxiliary memories // class StatusMethod : public SingleStepMethod { private: StatusMethod(); // forbid implicit constructor StatusMethod(StatusMethod&); // forbid implicit copy-constructor size_t PrevStatusNum; // # of status variables in previous step dlist StatusMList; // list of auxiliary memories static dlist* PtrStatusMList; // pointer to list being filled protected: typedef StatusContainer::iterator StatusIterator; // iterator of intg. list static StatusIterator FirstStatus(void) { // it. to first status in list return StatusContainer::Begin(); } static StatusIterator LastStatus(void) { // it. to last status in list return StatusContainer::End(); } //## repair friend class EULER; friend class RKE; /* memory of auxiliary status values */ class StatusMemory : public Memory { private: StatusMemory(StatusMemory&); // forbid copy constructor void operator= (StatusMemory&); // disable the operation public: // create empty memory StatusMemory(dlist* PtrList=PtrStatusMList) : Memory(PtrList) { } // free dynamic data virtual ~StatusMemory() { } }; // class StatusMemory friend class StatusMemory; // store state of integrators and status variables static void StoreState(Memory& di, Memory& si, StatusMemory& xi); // restore state of integrators and status variables static void RestoreState(double dthlf, Memory& di, Memory& si, StatusMemory& xi); // move startpoint to given state static void GoToState(Memory& di, Memory& si, StatusMemory& xi); public: StatusMethod(const char* name); // initailization virtual ~StatusMethod() { } // free dynamic datas virtual void TurnOff(void); // turn off integration method virtual void Integrate(void) = 0; // the method does integration virtual bool PrepareStep(void); // prepare integration step virtual void StatusResize(size_t size); // resize status memories }; // StatusMethod //////////////////////////////////////////////////////////////////////////// // interface for class IntegrationMethod & its descendants // //! select the integration method //! Methods: "abm4", "euler", "fw", "rke"(default), "rkf3", "rkf5", "rkf8" inline void SetMethod(const char* name) { IntegrationMethod::SetMethod(name); } //! get the name of the method which is used inline char* const GetMethod(void) { return IntegrationMethod::GetMethod(); } //! set the method which will be used to start given multistep method inline void SetStarter(const char* name, const char* slave_name) { MultiStepMethod::SetStarter(name, slave_name); } //! set the method which will be used to start currently used multistep method inline void SetStarter(const char* slave_name) { MultiStepMethod::SetStarter(IntegrationMethod::GetMethod(), slave_name); } //! get the name of the method which is used to start given multistep method inline char* const GetStarter(const char* name) { return MultiStepMethod::GetStarter(name); } //! get the name of the method which is used //! to start currently used multistep method inline char* const GetStarter(void) { return MultiStepMethod::GetStarter(IntegrationMethod::GetMethod()); } //////////////////////////////////////////////////////////////////////////// //! block for numerical integration // class Integrator : public aContiBlock { // integrator private: Integrator &operator= (const Integrator &x); // disable assignment double dd; // input value: y'=f(t,y) double ddl; // the same from previous step double ss; // status: y = S f(t,y) dt double ssl; // the same from previous step protected: Input input; // input expression: f(t,y) double initval; // initial value: y(t0) void CtrInit(); IntegratorContainer::iterator it_list; // position in list of integrators public: Integrator(); // implicit CTR (input = 0) Integrator(Input i, double initvalue=0); Integrator(Integrator &i, double initvalue=0); // copy-ctr ~Integrator(); void Init(double initvalue); // set value void Init() { Init(initval); } // set initial value void Set(double value); // set value Integrator &operator= (double x) { Set(x); return *this; } Input SetInput(Input inp) { return input.Set(inp); } void Eval(); // input evaluation double Value(); // status double InputValue() { return input.Value(); } // interface void Save(void) { ddl=dd; ssl=ss; } // save status void Restore(void) { dd=ddl; ss=ssl; } // restore saved status void SetState(double s) { ss=s; } double GetState(void) { return ss; } void SetOldState(double s) { ssl=s; } double GetOldState(void) { return ssl; } void SetDiff(double d) { dd=d; } double GetDiff(void) { return dd; } void SetOldDiff(double d) { ddl=d; } double GetOldDiff(void) { return ddl; } }; //////////////////////////////////////////////////////////////////////////// //! status variables (memory) // class Status : public aContiBlock1 { // state-variables Status(Status&); // disable copy ctor void operator= (Status&); // disable assignment protected: double initval; // initial value bool ValueOK; // valid-flag ### void CtrInit(); StatusContainer::iterator it_list; // position in list of status variables public: double st; // status double stl; // status from previous step Status(Input i, double initvalue=0); ~Status(); void Init(double initvalue); // value initialization void Init() { Init(initval); } void Set(double value); // set status of block virtual void Eval(); // block evaluation virtual double Value(); // block status // interface void Save() { stl = st; } // save status void Restore(); // restore saved status void SetState(double s) { st=s; } double GetState(void) { return st; } void SetOldState(double s) { stl=s; } double GetOldState(void) { return stl; } void SetValid(bool flag) { ValueOK = flag; } // set valid flag }; //////////////////////////////////////////////////////////////////////////// //! nonlinear block - hysteresis // class Hyst : public Status { protected: double p1,p2; double y1,y2; double tga; virtual void Eval(); // block evaluation public: Hyst(Input i, double p1, double p2, double y1, double y2, double tga); }; typedef Hyst Hysteresis; // alias name //////////////////////////////////////////////////////////////////////////// //! nonlinear block - backlash // class Blash : public Status { // backlash protected: double p1,p2; double tga; public: Blash(Input i, double p1, double p2, double tga); virtual void Eval(); // block evaluation }; typedef Blash Backlash; //////////////////////////////////////////////////////////////////////////// //! relay detects exact time of switch // class Relay : public Status { // general relay block protected: double p1,p2,p3,p4; // points on x-axis double y1,y2; // points on y-axis public: Relay(Input i, double p1, double p2, double p3, double p4, double y1, double y2); virtual void Eval(); // block evaluation }; //////////////////////////////////////////////////////////////////////////// // Continuous block arithmetic operators // //! binary operators: Input operator + (Input a, Input b); Input operator - (Input a, Input b); Input operator * (Input a, Input b); Input operator / (Input a, Input b); //! unary operators: Input operator - (Input a); //! functions: Input Abs(Input x); // abs(x) absolute value Input Sin(Input x); // sin(x) Input Cos(Input x); // cos(x) Input Tan(Input x); // tan(x) Input ASin(Input x); // asin(x) Input ACos(Input x); // acos(x) Input ATan(Input x); // atan(x) Input ATan2(Input y, Input x); // atan2(y,x) Input Exp(Input x); // exp(x) e ** x Input Log10(Input x); // log10(x) Input Ln(Input x); // ln(x) natural logarithm Input Pow(Input x, Input y); // pow(x,y) x ** y Input Sqr(Input x); // square x * x Input Sqrt(Input x); // square root Input Min(Input x, Input y); // minimum Input Max(Input x, Input y); // maximum Input Sign(Input x); // signum ###warning-steps-not-detected //////////////////////////////////////////////////////////////////////////// //! block parametrized by function with single argument // class Function : public aContiBlock1 { Function(const Function&); // ## disable Function&operator=(const Function&); // ## disable double (*f)(double); // pointer to function public: Function(Input i, double (*pf)(double)); virtual double Value(); }; //////////////////////////////////////////////////////////////////////////// //! block parametrized by function with two arguments // class Function2 : public aContiBlock2 { Function2(const Function2&); // ## disable Function2&operator=(const Function2&); // ## disable double (*f)(double,double); // pointer to function public: Function2(Input i1, Input i2, double (*pf)(double,double)); virtual double Value(); }; //////////////////////////////////////////////////////////////////////////// // CATEGORY: state conditions //////////////////////////////////////////////////////////////////////////// //! abstract base class for all state-event blocks // class aCondition : public aBlock { static aCondition *First; // list of all conditions aCondition *Next; // next condition in list void operator= (aCondition&); // disable operation aCondition(aCondition&); // disable operation public: aCondition(); ~aCondition(); static void InitAll(); static void SetAll(); static void TestAll(); static void AllActions(); static bool isAny(); virtual bool Value()=0; // state of condition private: virtual void Init()=0; virtual void SetNewStatus()=0; virtual bool Test()=0; // test of condition virtual void Action()=0; // state event action }; //////////////////////////////////////////////////////////////////////////// //! change detector - Boolean version (int) // class Condition : public aCondition { // state condition Input in; // block input unsigned char cc; // state unsigned char ccl; // old state virtual void Init(); virtual void SetNewStatus(); protected: virtual bool Test(); // test function (input >= 0.0) bool Up() { return cclTRUE bool Down() { return ccl>cc; } // change: TRUE->FALSE bool Change() { return ccl!=cc; } // both changes public: Condition(Input i); ~Condition(); virtual bool Value() { return cc; } // status Input SetInput(Input inp) { return in.Set(inp); } // change input block virtual void Action()=0; // state event }; //////////////////////////////////////////////////////////////////////////// //! detector of FALSE-->TRUE // class ConditionUp : public Condition { // state event on FALSE-->TRUE change public: ConditionUp(Input i) : Condition(i) {} bool Test() { return Condition::Test() && Up(); } virtual void Action()=0; // state event }; //////////////////////////////////////////////////////////////////////////// //! detector of TRUE-->FALSE // class ConditionDown : public Condition { // state event on TRUE-->FALSE change public: ConditionDown(Input i) : Condition(i) {} bool Test() { return Condition::Test() && Down(); } virtual void Action()=0; // state event }; //////////////////////////////////////////////////////////////////////////// // CATEGORY: non-linear blocks //////////////////////////////////////////////////////////////////////////// //! limitation // class Lim : public aContiBlock1 { protected: double low, high; // limits double tgalpha; // public: Lim(Input in, double l, double h, double tga=1.0); virtual void _Eval(); // evaluation with loop check virtual double Value(); // returned value }; typedef Lim Limitation; //////////////////////////////////////////////////////////////////////////// //! dead zone // class Insv : public aContiBlock1 { protected: double low, high; // limits double tgalpha,tgbeta; // public: Insv(Input in, double l, double h, double tga=1.0, double tgb=1.0); virtual void _Eval(); // evaluation with loop check virtual double Value(); // returned value }; typedef Insv DeadZone; //////////////////////////////////////////////////////////////////////////// //! quantizer // class Qntzr : public aContiBlock1 { protected: double step; // quantum public: Qntzr(Input in, double qstep=1.0); virtual void _Eval(); // evaluation with loop check virtual double Value(); // returned value }; typedef Qntzr Quantizer; //////////////////////////////////////////////////////////////////////////// //! friction // class Frict : public aContiBlock1 { protected: double low, high; // limits double tgalpha; // public: Frict(Input in, double l, double h, double tga=1.0); virtual void _Eval(); // evaluation with loop check virtual double Value(); // returned value }; typedef Frict Friction; //////////////////////////////////////////////////////////////////////////// //! function defined by given table of values // //TODO: reimplement with std::vector class Rline : public aContiBlock1 { Rline(const Rline&); // ## disable Rline&operator=(const Rline&); // ## disable protected: int n; // table item number double *tableX; // tabulka X double *tableY; // tabulka Y public: Rline(Input in, int num, double *X, double *Y); ~Rline(); virtual void _Eval(); // evaluation with loop check virtual double Value(); // returned value }; //////////////////////////////////////////////////////////////////////////// // CATEGORY: algebraic loop solvers //////////////////////////////////////////////////////////////////////////// //! abstract base for algebraic loop solvers // class AlgLoop : public aContiBlock1 { protected: double Eps; // required accuracy unsigned long MaxIt; // max. number of iterations double TA; // boundary values of interval double TB; // (also used for convergency check) double T0; // initial value bool was_cycle; // flag for going through loop int phase; // phase of computation double root; // root of equation public: AlgLoop(Input i, double eps, unsigned long max_it, // constructor double t_min, double t_max, double t0); void Set(double eps, unsigned long max_it, // set parameters double t_min, double t_max, double t0); void Set(double eps, unsigned long max_it, // set parameters double t_min, double t_max); virtual double Value()=0; // returned value }; // AlgLoop //////////////////////////////////////////////////////////////////////////// //! solve using iterations // class Iterations : public AlgLoop { public: Iterations(Input i, double eps, unsigned long max_it, double t_min, double t_max, double t0): AlgLoop(i, eps, max_it, t_min, t_max, t0) {/*nothing*/} virtual double Value(); // returned value }; //////////////////////////////////////////////////////////////////////////// //! solve using halving interval method // class Halvint : public AlgLoop { public: Halvint(Input i, double eps, unsigned long max_it, double t_min, double t_max): AlgLoop(i, eps, max_it, t_min, t_max, t_min) {/*nothing*/} virtual double Value(); // returned value }; //////////////////////////////////////////////////////////////////////////// //! solve using regula falsi method // class RegulaFalsi : public AlgLoop { double eps_root; // root for force precision test public: RegulaFalsi(Input i, double eps, unsigned long max_it, double t_min, double t_max): AlgLoop(i, eps, max_it, t_min, t_max, t_min), eps_root(0) {/*nothing*/} virtual double Value(); // returned value }; //////////////////////////////////////////////////////////////////////////// //! solve using modified Newton's method // class Newton : public AlgLoop { double eps_root; // root for force precision test double prev_root; // root from previous iteration step public: Newton(Input i, double eps, unsigned long max_it, double t_min, double t_max, double t0): AlgLoop(i, eps, max_it, t_min, t_max, t0), eps_root(0), prev_root(0) {/*nothing*/} virtual double Value(); // returned value }; //////////////////////////////////////////////////////////////////////////// // CATEGORY: global functions //////////////////////////////////////////////////////////////////////////// // Naming Subsystem --- SimObject names (text identifiers) // this is system dictionary: relation: objectptr---textname // void SetName(SimObject &o, const char *name); void SetName(SimObject *o, const char *name); void RemoveName(SimObject &o); void RemoveName(SimObject *o); const char *GetName(SimObject &o); const char *GetName(SimObject *o); //////////////////////////////////////////////////////////////////////////// // InstallBreak --- set function for checking if user breaks simulation // // f is called at each step of simulation // void InstallBreak(void (*f)()); // f can call Stop() or Abort() //////////////////////////////////////////////////////////////////////////// //! basic synchronization tool for processes // class Semaphore : public SimObject { protected: int n; public: Queue Q; // internal quqeue Semaphore(); // constructor Semaphore(const char *_name); // with associated name virtual ~Semaphore(); virtual void Clear(); // initialization virtual void Output(); virtual void P(); // P operation virtual void V(); // V operation operator Semaphore* () { return this; } }; //////////////////////////////////////////////////////////////////////////// //! synchronization tool for processes // class Barrier : public SimObject { Barrier(const Barrier&); // ## disable Barrier&operator=(const Barrier&); // ## disable protected: Entity **waiting; // array of waiting entities (fixed size) unsigned n; // number of waiting entities (actual number) const unsigned maxn; // barrier capacity ### (size) void Init(); // initialization public: Barrier(unsigned N); Barrier(const char *_name, unsigned N); virtual ~Barrier(); // void ChangeCapacity(unsigned N); // change N unsigned Capacity() const { return maxn; } // barrier size virtual void Enter(Entity *e); // entity arrival virtual int Break(); // activate all waiting entities virtual void Clear(); // initialization virtual void Output(); // print operator Barrier* () { return this; } }; #endif // ifndef __SIMLIB_H // end of simlib.h