/////////////////////////////////////////////////////////////////////////////
// stdblock.cc
//
// SIMLIB version: 2.18
// Date: 2004-01-25
//
// Copyright (c) 1991-2004 Petr Peringer
//
// This library is licensed under GNU Library GPL. See the file COPYING.
//
//
// standard continuous blocks
//
// class Lim -- limitation
// class Insv -- dead space
// class Qntzr -- quantizer
// class Frict -- friction
// class Hyst -- hysteresis
// class Relay -- relay
// class Blash -- backlash
// class Rline -- table-defined function (lin. interpolation)
//
// modification history:
// 930825 added Rline
////////////////////////////////////////////////////////////////////////////
// interface
//
#include "simlib.h"
#include "internal.h"
#include <cmath>
#include <cstring>
////////////////////////////////////////////////////////////////////////////
// implementation
//
SIMLIB_IMPLEMENTATION
////////////////////////////////////////////////////////////////////////////
// class Lim -- limitation
//
Lim::Lim(Input in, double l, double h, double tga) :
aContiBlock1(in),
low(l),
high(h),
tgalpha(tga)
{
if(l>=h) SIMLIB_error(LowGreaterHigh);
dprintf(("Lim::Lim(in,l=%g,h=%g,tga=%g)", l,h,tga));
}
void Lim::_Eval() {};
double Lim::Value()
{
double x = InputValue();
if(x > high) return high*tgalpha;
if(x < low) return low*tgalpha;
return x*tgalpha;
}
////////////////////////////////////////////////////////////////////////////
// class Insv -- dead space
//
Insv::Insv(Input in, double l, double h, double tga, double tgb) :
aContiBlock1(in),
low(l),
high(h),
tgalpha(tga),
tgbeta(tgb)
{
if(l>=h) SIMLIB_error(LowGreaterHigh);
dprintf(("Insv::Insv(in,l=%g,h=%g,tga=%g,tgb=%g)", l,h,tga,tgb));
}
void Insv::_Eval() {};
double Insv::Value()
{
double x = InputValue();
if(x > high) return ((x-high)*tgalpha);
if(x < low) return ((x-low)*tgbeta);
return(0);
}
////////////////////////////////////////////////////////////////////////////
// class Qntzr --
//
Qntzr::Qntzr(Input in, double p) : // p = quantiz. step
aContiBlock1(in),
step(p)
{
if(p<=0) SIMLIB_error(BadQntzrStep);
dprintf(("Qntzr::Qntzr(in,step=%g)", p));
}
void Qntzr::_Eval() {};
double Qntzr::Value()
{
double x = InputValue();
double zn = (x>0)? 1:((x<0)? -1:0);
double k = zn*floor((fabs(x)-step/2)/step+1);
return(k*step);
}
////////////////////////////////////////////////////////////////////////////
// class Frict --
//
Frict::Frict(Input in, double l, double h, double tga) :
aContiBlock1(in),
low(l),
high(h),
tgalpha(tga)
{
if(l>=h) SIMLIB_error(LowGreaterHigh);
dprintf(("Frict::Frict(in,l=%g,h=%g,tga=%g)", l,h,tga));
}
void Frict::_Eval() {};
double Frict::Value()
{
double x = InputValue();
if(x<0) return(low + x*tgalpha);
if(x>0) return(high + x*tgalpha);
return(0);
}
////////////////////////////////////////////////////////////////////////////
// class Hyst --
//
Hyst::Hyst(Input i, double _p1, double _p2,
double _y1, double _y2,
double _tga) :
Status(i),
p1(_p1), p2(_p2),
y1(_y1), y2(_y2),
tga(_tga)
{
dprintf(("Hyst::Hyst(in,%g,%g,%g,%g,tga=%g)", p1,p2,y1,y2,tga));
}
void Hyst::Eval()
{
double x = InputValue();
double ys = stl;
ys = max(ys,y1); // in the case of bad initialization (out of range)
ys = min(ys,y2); // can be leaved out if correct init
double yn2 = (x-p2)*tga;
double yn1 = (x-p1)*tga;
double y = ys;
if(ys <= yn2)
y = min(yn2,y2);
if(ys >= yn1)
y = max(yn1,y1);
st=y; // new status
ValueOK = true;
}
////////////////////////////////////////////////////////////////////////////
// class Relay --
//
Relay::Relay(Input i, double _p1, double _p2, double _p3, double _p4,
double _y1, double _y2) :
Status(i),
p1(_p1), p2(_p2), p3(_p3), p4(_p4),
y1(_y1), y2(_y2)
{
// TODO: check
dprintf(("Relay::Relay(in,%g,%g,%g,%g,y1=%g,y2=%g)", p1,p2,p3,p4,y1,y2));
}
void Relay::Eval()
{
double x = InputValue();
double y;
if (x<p1) y = y1;
else if(x<p2) y = stl;
else if(x<p3) y = 0;
else if(x<p4) y = stl;
else y = y2;
if(y!=stl)
ContractStep(); // step change => detection
st=y;
ValueOK = true;
}
////////////////////////////////////////////////////////////////////////////
// class Blash --
//
Blash::Blash(Input i, double _p1, double _p2, double _tga) :
Status(i),
p1(_p1),
p2(_p2),
tga(_tga)
{
dprintf(("Blash::Blash(in,%g,%g,tga=%g)", p1, p2, tga));
}
void Blash::Eval()
{
// TODO: CHECK !!!
double x = InputValue();
double ys = stl;
double yn1 = (x-p1)*tga;
double yn2 = (x-p2)*tga;
double y = max(yn2,ys);
y = min(yn1,y);
st=y;
ValueOK = true;
}
////////////////////////////////////////////////////////////////////////////
// class Rline -- table-defined function (lin. int.)
//
// TODO: - variants
// - use data directly? (no new and copy),
// - read from input file
//
Rline::Rline(Input in, int num, double *X, double *Y):
aContiBlock1(in), n(num)
{
dprintf(("Rline::Rline(in,%i,X[],Y[])", n));
if(n<2)
SIMLIB_error(RlineErr1); // Rline: n<2
//
// OPTIMIZE: use arguments !!!
//
tableX = new double[n];
if(!tableX)
SIMLIB_error(MemoryError);
tableY = new double[n];
if(!tableY)
SIMLIB_error(MemoryError);
memcpy(tableX,X,n*sizeof(double));
memcpy(tableY,Y,n*sizeof(double));
for(int i=1; i<n; i++)
if(tableX[i]<tableX[i-1])
SIMLIB_error(RlineErr2); // Rline: tableX not ordered
//
// OPTIMIZE:
// count (tableY[i]-tableY[i-1]) / (tableX[i]-tableX[i-1])
// save: division, 4 -, 3 index; price: array[n]
}
Rline::~Rline()
{
dprintf(("Rline::~Rline()", n));
delete tableX;
delete tableY;
}
void Rline::_Eval()
{
}
double Rline::Value()
{
// REMARK:
// add step change detection ??? => Status!!!!!
double x = InputValue();
int i;
if (x >= tableX[n-1])
return tableY[n-1];
if (x <= tableX[0])
return tableY[0];
for(i=1; x > tableX[i]; i++); // search... (linear for now)
return (tableY[i]-tableY[i-1]) / (tableX[i]-tableX[i-1])
* (x-tableX[i-1])+tableY[i-1];
}
////////////////////////////////////////////////////////////////////////////
// end of STDBLOCK.CPP
////////////////////////////////////////////////////////////////////////////
syntax highlighted by Code2HTML, v. 0.9.1