/////////////////////////////////////////////////////////////////////////////
// simlib3D.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.
//
//
// 3D extension
//
// - Integrator3D
// - blocks for + - * / operations
//
////////////////////////////////////////////////////////////////////////////
// interface
//
#include "simlib.h"
#include "simlib3D.h"
#include "internal.h"
#include <cmath>
////////////////////////////////////////////////////////////////////////////
// implementation
//
SIMLIB_IMPLEMENTATION
////////////////////////////////////////////////////////////////////////////
// non-block operations
//
double abs(const Value3D &a)
{
return sqrt( a._x * a._x + a._y * a._y + a._z * a._z );
}
Value3D operator +(const Value3D& a, const Value3D &b)
{
return Value3D( a._x + b._x, a._y + b._y, a._z + b._z );
}
Value3D operator -(const Value3D& a, const Value3D &b)
{
return Value3D( a._x - b._x, a._y - b._y, a._z - b._z );
}
Value3D operator -(const Value3D& a)
{
return Value3D( -a._x, -a._y, -a._z);
}
Value3D operator *(const Value3D& a, const Value3D &b)
{
return Value3D( a._y * b._z - a._z * b._y,
a._z * b._x - a._x * b._z,
a._x * b._y - a._y * b._x
);
}
Value3D operator *(const Value3D& a, const double b)
{
return Value3D( a._x * b, a._y * b, a._z * b );
}
Value3D operator *(const double a, const Value3D& b)
{
return b * a;
}
double scalar_product(const Value3D& a, const Value3D &b)
{
return a._x * b._x + a._y * b._y + a._z * b._z;
}
Value3D operator /(const Value3D& a, const double b)
{
return Value3D( a._x / b, a._y / b, a._z / b );
}
////////////////////////////////////////////////////////////////////////////
// aContiBlock3D --- constructor & destructor
//
aContiBlock3D::aContiBlock3D():
isEvaluated(false)
{
dprintf(("3Dblock-ctr"));
}
aContiBlock3D::~aContiBlock3D() {
dprintf(("3Dblock-dtr"));
}
////////////////////////////////////////////////////////////////////////////
// aContiBlock3D::Print --- print of 3D block output value
//
void aContiBlock3D::Print() {
Value3D a = Value();
a.Print();
}
////////////////////////////////////////////////////////////////////////////
// aContiBlock::_Eval --- evaluation with algebraic loop detection ###
//
void aContiBlock3D::_Eval()
{
if(isEvaluated) // was evaluated
SIMLIB_error(AlgLoopDetected); // recursive call
isEvaluated = true; // eval-flag
Eval(); // evaluation of block
isEvaluated = false;
}
////////////////////////////////////////////////////////////////////////////
// Parameter3D --- parameter of model
//
Parameter3D &Parameter3D::operator= (const Value3D &x) {
if(SIMLIB_Phase==SIMULATION)
SIMLIB_error(ParameterChangeErr);
value = x;
return *this;
}
////////////////////////////////////////////////////////////////////////////
// aContiBlock1 --- base for blocks with one input
//
aContiBlock3D1::aContiBlock3D1(Input3D i) : input(i)
{
if(input==this)
SIMLIB_error(AlgLoopDetected);
// LoopCheck();
}
////////////////////////////////////////////////////////////////////////////
// Integrator3D::special_input::Value() --- expects 3 subsequent evaluations
//
// method returns scalar value for input of scalar integrator
// three evaluations are guaranteed by Integrator3D implementation
//
double Integrator3D::special_input::Value() { // interface class
if(count == 0)
a = in.Value(); // get vector input
switch(++count) {
case 1: return a.x(); // first call (x)
case 2: return a.y(); // second call (y)
case 3: count=0;
return a.z(); // third and last call (z)
} // switch
SIMLIB_internal_error(); // *** never reached ***
return 0; // compiler warning elimination
}
////////////////////////////////////////////////////////////////////////////
// Integrator3D --- constructors
//
Integrator3D::Integrator3D(Input3D i, Value3D initial_value):
_x(in, initial_value.x()), // linking of inputs to integrators
_y(in, initial_value.y()),
_z(in, initial_value.z()),
in(i) {}
Integrator3D::Integrator3D(Input3D i):
_x(in), _y(in), _z(in),
in(i) {}
// --- special copy constructor
Integrator3D::Integrator3D(Integrator3D &i, Value3D initial_value):
_x(in, initial_value.x()), // linking of inputs to integrators
_y(in, initial_value.y()),
_z(in, initial_value.z()),
in(i) {}
// zero input for default Integrator3D constructor
// we need it for creating arrays of integrators
static Constant3D Zero3D(0,0,0);
Integrator3D::Integrator3D():
_x(in), _y(in), _z(in),
in(Zero3D) {}
////////////////////////////////////////////////////////////////////////////
// Integrator3D output method
//
Value3D Integrator3D::Value()
{
return Value3D(_x.Value(), _y.Value(), _z.Value());
}
////////////////////////////////////////////////////////////////////////////
// operator =
//
Integrator3D &Integrator3D::operator = (const Value3D &a)
{
_x=a.x();
_y=a.y();
_z=a.z();
return *this;
}
Integrator3D &Integrator3D::operator = (Input3D i)
{
Value3D a = i.Value();
_x=a.x();
_y=a.y();
_z=a.z();
return *this;
}
////////////////////////////////////////////////////////////////////////////
// aContiBlock2 --- base for 2 input blocks
//
aContiBlock3D2::aContiBlock3D2(Input3D i1, Input3D i2)
: input1(i1), input2(i2)
{
if(input1==this || input2==this)
SIMLIB_error(AlgLoopDetected);
// LoopCheck();
}
aContiBlock3D3::aContiBlock3D3(Input3D i1, Input3D i2, Input3D i3)
: aContiBlock3D2(i1,i2), input3(i3)
{
if(input3==this )
SIMLIB_error(AlgLoopDetected);
}
////////////////////////////////////////////////////////////////////////////
// Add --- sum of two inputs
//
class _Add3D : public aContiBlock3D2 {
virtual void _Eval() {}
public:
_Add3D(Input3D a, Input3D b): aContiBlock3D2(a,b) {
dprintf(("ctr: _Add3D[%p](in1,in2)", this));
}
virtual Value3D Value() {
Value3D a = Input1Value();
Value3D b = Input2Value();
return a + b;
}
};
////////////////////////////////////////////////////////////////////////////
// Sub --- subtract two inputs
//
class _Sub3D : public aContiBlock3D2 {
virtual void _Eval() {}
public:
_Sub3D(Input3D a, Input3D b): aContiBlock3D2(a,b) {
dprintf(("ctr: _Sub3D[%p](in1,in2)", this));
}
virtual Value3D Value() {
Value3D a = Input1Value();
Value3D b = Input2Value();
return a - b;
}
};
////////////////////////////////////////////////////////////////////////////
// Mul --- vector multiplier
//
class _Mul3D : public aContiBlock3D2 {
virtual void _Eval() {}
public:
_Mul3D(Input3D a, Input3D b): aContiBlock3D2(a,b) {
dprintf(("ctr: _Mul3D[%p](in1,in2)", this));
}
virtual Value3D Value() {
Value3D a = Input1Value();
Value3D b = Input2Value();
return a * b;
}
};
////////////////////////////////////////////////////////////////////////////
// Mul --- multiplier vector * scalar
//
class _Mul3D1D : public aContiBlock3D1 {
Input _b;
virtual void _Eval() {}
public:
_Mul3D1D(Input3D a, Input b): aContiBlock3D1(a), _b(b) {
dprintf(("ctr: _Mul3D1D[%p](in1,in2)", this));
}
virtual Value3D Value() {
Value3D a = InputValue();
double b = _b.Value();
return a * b;
}
};
////////////////////////////////////////////////////////////////////////////
// Div --- divider vector / scalar
//
class _Div3D : public aContiBlock3D1 {
Input _b;
virtual void _Eval() {}
public:
_Div3D(Input3D a, Input b): aContiBlock3D1(a), _b(b) {
dprintf(("ctr: _Div3D[%p](in1_3D,in2)", this));
}
virtual Value3D Value() {
Value3D a = InputValue();
double b = _b.Value();
return a / b;
}
};
////////////////////////////////////////////////////////////////////////////
// binary operators ...
//
// wrapper operator functions for block expressions
//
Input3D operator + (Input3D a, Input3D b) { return new _Add3D(a,b); }
Input3D operator - (Input3D a, Input3D b) { return new _Sub3D(a,b); }
Input3D operator * (Input3D a, Input3D b) { return new _Mul3D(a,b); }
Input3D operator * (Input3D a, Input b) { return new _Mul3D1D(a,b); }
Input3D operator * (Input a, Input3D b) { return new _Mul3D1D(b,a); }
Input3D operator / (Input3D a, Input b) { return new _Div3D(a,b); }
////////////////////////////////////////////////////////////////////////////
// UMinus --- unary minus
//
class _UMinus3D: public aContiBlock3D1 {
virtual void _Eval() {}
public:
_UMinus3D(Input3D a): aContiBlock3D1(a) {
dprintf(("ctr: _UMinus3D[%p](in)", this));
}
virtual Value3D Value() {
Value3D a = InputValue();
return -a;
}
};
////////////////////////////////////////////////////////////////////////////
// unary operators ...
//
Input3D operator - (Input3D a) { return new _UMinus3D(a); }
////////////////////////////////////////////////////////////////////////////
// functions for block expressions
//
////////////////////////////////////////////////////////////////////////////
// _Abs3D --- absolute value of vector x
//
class _Abs3D: public aContiBlock {
virtual void _Eval() {}
Input3D in;
public:
_Abs3D(Input3D a): in(a) {}
virtual double Value() {
Value3D a = in.Value();
return abs(a);
}
};
////////////////////////////////////////////////////////////////////////////
// _Norm3D --- unit vector = vector x/Abs(x)
//
class _Norm3D: public aContiBlock3D1 {
virtual void _Eval() {}
public:
_Norm3D(Input3D a): aContiBlock3D1(a) {}
virtual Value3D Value() {
Value3D a = InputValue();
return a/abs(a);
}
};
////////////////////////////////////////////////////////////////////////////
// _ScalarMul3D --- scalar multiply
//
class _ScalarProduct3D: public aContiBlock {
virtual void _Eval() {}
Input3D input1;
Input3D input2;
public:
_ScalarProduct3D(Input3D a, Input3D b): input1(a), input2(b) {}
virtual double Value() {
Value3D a = input1.Value();
Value3D b = input2.Value();
return scalar_product(a,b);
}
};
////////////////////////////////////////////////////////////////////////////
// wrapper functions for block expressions
//
Input Abs(Input3D x) { return new _Abs3D(x); } // absolute value of vector x
Input3D UnitVector(Input3D x) { return new _Norm3D(x); }
Input ScalarProduct(Input3D x, Input3D y) { return new _ScalarProduct3D(x,y); }
////////////////////////////////////////////////////////////////////////////
// _XYZpart --- vector part
//
class _XYZpart: public aContiBlock {
virtual void _Eval() {}
Input3D input;
public:
enum WhichPart { x,y,z }; // part identification
_XYZpart(Input3D a, WhichPart w): input(a), which(w) {}
virtual double Value() {
Value3D a = input.Value();
switch(which) {
case x: return a.x();
case y: return a.y();
case z: return a.z();
}
SIMLIB_internal_error(); // never reached
return 0; // compiler warning elimination
}
private:
WhichPart which;
};
////////////////////////////////////////////////////////////////////////////
// get x,y,z part of vector block
//
// wrapper functions for block expressions
//
Input Xpart(Input3D a) { return new _XYZpart(a, _XYZpart::x); }
Input Ypart(Input3D a) { return new _XYZpart(a, _XYZpart::y); }
Input Zpart(Input3D a) { return new _XYZpart(a, _XYZpart::z); }
////////////////////////////////////////////////////////////////////////////
// end
////////////////////////////////////////////////////////////////////////////
syntax highlighted by Code2HTML, v. 0.9.1