///////////////////////////////////////////////////////////////////////////// // simlib2D.cc // // SIMLIB version: 2.18 // Date: 2004-01-25 // // Copyright (c) 1997-2004 Petr Peringer // // This library is licensed under GNU Library GPL. See the file COPYING. // // // 2D extension // // - Integrator2D // - blocks for + - * / operations // //////////////////////////////////////////////////////////////////////////// // interface // #include "simlib.h" #include "simlib2D.h" #include "internal.h" #include //////////////////////////////////////////////////////////////////////////// // implementation // SIMLIB_IMPLEMENTATION //////////////////////////////////////////////////////////////////////////// // non-block operations // double abs(const Value2D &a) { return sqrt( a._x * a._x + a._y * a._y ); } Value2D operator +(const Value2D& a, const Value2D &b) { return Value2D( a._x + b._x, a._y + b._y ); } Value2D operator -(const Value2D& a, const Value2D &b) { return Value2D( a._x - b._x, a._y - b._y ); } Value2D operator -(const Value2D& a) { return Value2D( -a._x, -a._y); } /* Value2D operator *(const Value2D& a, const Value2D &b) { return Value2D( a._y * b._z - a._z * b._y, a._z * b._x - a._x * b._z, a._x * b._y - a._y * b._x ); } */ Value2D operator *(const Value2D& a, const double b) { return Value2D( a._x * b, a._y * b ); } Value2D operator *(const double a, const Value2D& b) { return b * a; } double scalar_product(const Value2D& a, const Value2D &b) { return a._x * b._x + a._y * b._y ; } Value2D operator /(const Value2D& a, const double b) { return Value2D( a._x / b, a._y / b ); } //////////////////////////////////////////////////////////////////////////// // aContiBlock2D --- constructor & destructor // aContiBlock2D::aContiBlock2D(): isEvaluated(false) { dprintf(("2Dblock-ctr")); } aContiBlock2D::~aContiBlock2D() { dprintf(("2Dblock-dtr")); } //////////////////////////////////////////////////////////////////////////// // aContiBlock2D::Print --- print of 2D block output value // void aContiBlock2D::Print() { Value2D a = Value(); a.Print(); } //////////////////////////////////////////////////////////////////////////// // aContiBlock::_Eval --- evaluation with algebraic loop detection ### // void aContiBlock2D::_Eval() { if(isEvaluated) // was evaluated SIMLIB_error(AlgLoopDetected); // recursive call isEvaluated = true; // eval-flag Eval(); // evaluation of block isEvaluated = false; } //////////////////////////////////////////////////////////////////////////// // Parameter2D --- parameter of model // Parameter2D &Parameter2D::operator= (const Value2D &x) { if(SIMLIB_Phase==SIMULATION) SIMLIB_error(ParameterChangeErr); value = x; return *this; } //////////////////////////////////////////////////////////////////////////// // aContiBlock1 --- base for blocks with one input // aContiBlock2D1::aContiBlock2D1(Input2D i) : input(i) { if(input==this) SIMLIB_error(AlgLoopDetected); // LoopCheck(); } //////////////////////////////////////////////////////////////////////////// // Integrator2D::special_input::Value() --- expects 2 subsequent evaluations // // return scalar value for scalar integrator // two evaluations are guaranteed by Integrator2D // double Integrator2D::special_input::Value() { // interface class if(count == 0) a = in.Value(); // get vector input (x,y) switch(++count) { case 1: return a.x(); // first call (x) case 2: count=0; // second call (y) return a.y(); } // switch SIMLIB_internal_error(); // *** never reached *** return 0; // compiler warning elimination } //////////////////////////////////////////////////////////////////////////// // Integrator2D --- constructors // Integrator2D::Integrator2D(Input2D i, Value2D initial_value): _x(in, initial_value.x()), // linking of inputs to integrators _y(in, initial_value.y()), in(i) {} Integrator2D::Integrator2D(Input2D i): _x(in), _y(in), in(i) {} // --- special copy constructor Integrator2D::Integrator2D(Integrator2D &i, Value2D initial_value): _x(in, initial_value.x()), // linking of inputs to integrators _y(in, initial_value.y()), in(i) {} // zero input for default Integrator2D constructor // we need it for creating arrays of integrators static Constant2D Zero2D(0,0); Integrator2D::Integrator2D(): _x(in), _y(in), in(Zero2D) {} //////////////////////////////////////////////////////////////////////////// // operator = --- assign new value // Integrator2D &Integrator2D::operator = (const Value2D &a) { _x=a.x(); _y=a.y(); return *this; } Integrator2D &Integrator2D::operator = (Input2D i) { Value2D a = i.Value(); _x=a.x(); _y=a.y(); return *this; } //////////////////////////////////////////////////////////////////////////// // Integrator2D output method // Value2D Integrator2D::Value() { return Value2D(_x.Value(), _y.Value()); } //////////////////////////////////////////////////////////////////////////// // aContiBlock2 --- base for 2 input blocks // aContiBlock2D2::aContiBlock2D2(Input2D i1, Input2D i2) : input1(i1), input2(i2) { if(input1==this || input2==this) SIMLIB_error(AlgLoopDetected); // LoopCheck(); } aContiBlock2D3::aContiBlock2D3(Input2D i1, Input2D i2, Input2D i3) : aContiBlock2D2(i1,i2), input3(i3) { if(input3==this ) SIMLIB_error(AlgLoopDetected); } //////////////////////////////////////////////////////////////////////////// // Add --- sum of two inputs // class _Add2D : public aContiBlock2D2 { virtual void _Eval() {} public: _Add2D(Input2D a, Input2D b): aContiBlock2D2(a,b) { dprintf(("ctr: _Add2D[%p](in1,in2)", this)); } virtual Value2D Value() { Value2D a = Input1Value(); Value2D b = Input2Value(); return a + b; } }; //////////////////////////////////////////////////////////////////////////// // Sub --- subtract two inputs // class _Sub2D : public aContiBlock2D2 { virtual void _Eval() {} public: _Sub2D(Input2D a, Input2D b): aContiBlock2D2(a,b) { dprintf(("ctr: _Sub2D[%p](in1,in2)", this)); } virtual Value2D Value() { Value2D a = Input1Value(); Value2D b = Input2Value(); return a - b; } }; //////////////////////////////////////////////////////////////////////////// // Mul --- multiplier vector * scalar // class _Mul2D1D : public aContiBlock2D1 { Input _b; virtual void _Eval() {} public: _Mul2D1D(Input2D a, Input b): aContiBlock2D1(a), _b(b) { dprintf(("ctr: _Mul2D1D[%p](in1,in2)", this)); } virtual Value2D Value() { Value2D a = InputValue(); double b = _b.Value(); return a * b; } }; //////////////////////////////////////////////////////////////////////////// // Div --- divider vector / scalar // class _Div2D : public aContiBlock2D1 { Input _b; virtual void _Eval() {} public: _Div2D(Input2D a, Input b): aContiBlock2D1(a), _b(b) { dprintf(("ctr: _Div2D[%p](in1_2D,in2)", this)); } virtual Value2D Value() { Value2D a = InputValue(); double b = _b.Value(); return a / b; } }; //////////////////////////////////////////////////////////////////////////// // binary operators ... // // wrapper operator functions for block expressions // Input2D operator + (Input2D a, Input2D b) { return new _Add2D(a,b); } Input2D operator - (Input2D a, Input2D b) { return new _Sub2D(a,b); } Input2D operator * (Input2D a, Input b) { return new _Mul2D1D(a,b); } Input2D operator * (Input a, Input2D b) { return new _Mul2D1D(b,a); } Input2D operator / (Input2D a, Input b) { return new _Div2D(a,b); } //////////////////////////////////////////////////////////////////////////// // UMinus --- unary minus // class _UMinus2D: public aContiBlock2D1 { virtual void _Eval() {} public: _UMinus2D(Input2D a): aContiBlock2D1(a) { dprintf(("ctr: _UMinus2D[%p](in)", this)); } virtual Value2D Value() { Value2D a = InputValue(); return -a; } }; //////////////////////////////////////////////////////////////////////////// // unary operators ... // Input2D operator - (Input2D a) { return new _UMinus2D(a); } //////////////////////////////////////////////////////////////////////////// // functions for block expressions // //////////////////////////////////////////////////////////////////////////// // _Abs2D --- absolute value of vector x // class _Abs2D: public aContiBlock { virtual void _Eval() {} Input2D in; public: _Abs2D(Input2D a): in(a) {} virtual double Value() { Value2D a = in.Value(); return abs(a); } }; //////////////////////////////////////////////////////////////////////////// // _Norm2D --- unit vector = vector x/Abs(x) // class _Norm2D: public aContiBlock2D1 { virtual void _Eval() {} public: _Norm2D(Input2D a): aContiBlock2D1(a) {} virtual Value2D Value() { Value2D a = InputValue(); return a/abs(a); } }; //////////////////////////////////////////////////////////////////////////// // _ScalarProduct2D --- scalar multiply // class _ScalarProduct2D: public aContiBlock { virtual void _Eval() {} Input2D input1; Input2D input2; public: _ScalarProduct2D(Input2D a, Input2D b): input1(a), input2(b) {} virtual double Value() { Value2D a = input1.Value(); Value2D b = input2.Value(); return scalar_product(a,b); } }; //////////////////////////////////////////////////////////////////////////// // wrapper functions for block expressions // Input Abs(Input2D x) { return new _Abs2D(x); } // absolute value of vector x Input2D UnitVector(Input2D x) { return new _Norm2D(x); } Input ScalarProduct(Input2D x, Input2D y) { return new _ScalarProduct2D(x,y); } //////////////////////////////////////////////////////////////////////////// // _XYpart --- vector part // class _XYpart: public aContiBlock { virtual void _Eval() {} Input2D input; public: enum WhichPart { x,y }; // part identification _XYpart(Input2D a, WhichPart w): input(a), which(w) {} virtual double Value() { Value2D a = input.Value(); switch(which) { case x: return a.x(); case y: return a.y(); } SIMLIB_internal_error(); // *** never reached *** return 0; // compiler warning elimination } private: WhichPart which; }; //////////////////////////////////////////////////////////////////////////// // get x,y part of vector block // // wrapper functions for block expressions // Input Xpart(Input2D a) { return new _XYpart(a, _XYpart::x); } Input Ypart(Input2D a) { return new _XYpart(a, _XYpart::y); } //////////////////////////////////////////////////////////////////////////// // end ////////////////////////////////////////////////////////////////////////////