SIMLIB/C++  3.07
stdblock.cc
Go to the documentation of this file.
1 /////////////////////////////////////////////////////////////////////////////
2 //! \file stdblock.cc Non-linear blocks
3 //
4 // Copyright (c) 1991-2007 Petr Peringer
5 //
6 // This library is licensed under GNU Library GPL. See the file COPYING.
7 //
8 
9 //
10 // standard non-linear continuous blocks
11 //
12 // class Lim -- limitation
13 // class Insv -- dead space
14 // class Qntzr -- quantizer
15 // class Frict -- friction
16 // class Hyst -- hysteresis
17 // class Relay -- relay
18 // class Blash -- backlash
19 // class Rline -- table-defined function (lin. interpolation)
20 //
21 // modification history:
22 // 930825 added Rline
23 // 2007-12-11 add Name() methods -- good for debugging
24 
25 
26 ////////////////////////////////////////////////////////////////////////////
27 // interface
28 //
29 
30 #include "simlib.h"
31 #include "internal.h"
32 
33 #include <cmath>
34 #include <cstring>
35 
36 
37 ////////////////////////////////////////////////////////////////////////////
38 // implementation
39 //
40 
41 namespace simlib3 {
42 
44 ////////////////////////////////////////////////////////////////////////////
45 /// constructor of limitation block
46 //
47 Lim::Lim(Input in, double l, double h, double tga)
48  : aContiBlock1(in), low(l), high(h), tgalpha(tga)
49 {
50  if (l >= h)
52  Dprintf(("Lim::Lim(in,l=%g,h=%g,tga=%g)", l, h, tga));
53 }
54 
55 void Lim::_Eval()
56 {
57 };
58 
59 double Lim::Value()
60 {
61  AlgLoopDetector _(this);
62  double x = InputValue();
63  if (x > high)
64  return high * tgalpha;
65  if (x < low)
66  return low * tgalpha;
67  return x * tgalpha;
68 }
69 
70 
71 #if 0
72 const char *Lim::Name() const
73 {
74  if (HasName())
75  return _name;
76  else
77  return SIMLIB_create_tmp_name("Lim{%p}", this);
78 }
79 #endif
80 
81 ////////////////////////////////////////////////////////////////////////////
82 /// dead space
83 Insv::Insv(Input in, double l, double h, double tga, double tgb)
84  : aContiBlock1(in), low(l), high(h), tgalpha(tga), tgbeta(tgb)
85 {
86  if (l >= h)
88  Dprintf(("Insv::Insv(in,l=%g,h=%g,tga=%g,tgb=%g)", l, h, tga, tgb));
89 }
90 
92 {
93 };
94 
95 double Insv::Value()
96 {
97  AlgLoopDetector _(this);
98  double x = InputValue();
99  if (x > high)
100  return ((x - high) * tgalpha);
101  if (x < low)
102  return ((x - low) * tgbeta);
103  return (0);
104 }
105 
106 #if 0
107 const char *Insv::Name() const
108 {
109  if (HasName())
110  return _name;
111  else
112  return SIMLIB_create_tmp_name("Insv{%p}", this);
113 }
114 #endif
115 
116 ////////////////////////////////////////////////////////////////////////////
117 /// quantizer constructor
118 Qntzr::Qntzr(Input in, double p) // p = quantiz. step
119  : aContiBlock1(in), step(p)
120 {
121  if (p <= 0)
123  Dprintf(("Qntzr::Qntzr(in,step=%g)", p));
124 }
125 
127 {
128 };
129 
130 double Qntzr::Value()
131 {
132  AlgLoopDetector _(this);
133  double x = InputValue();
134  double zn = (x > 0) ? 1 : ((x < 0) ? -1 : 0);
135  double k = zn * floor((fabs(x) - step / 2) / step + 1);
136  return (k * step);
137 }
138 
139 #if 0
140 const char *Qntzr::Name() const
141 {
142  if (HasName())
143  return _name;
144  else
145  return SIMLIB_create_tmp_name("Qntzr{%p}", this);
146 }
147 #endif
148 
149 ////////////////////////////////////////////////////////////////////////////
150 /// friction constructor
151 Frict::Frict(Input in, double l, double h, double tga)
152  : aContiBlock1(in), low(l), high(h), tgalpha(tga)
153 {
154  if (l >= h)
156  Dprintf(("Frict::Frict(in,l=%g,h=%g,tga=%g)", l, h, tga));
157 }
158 
160 {
161 };
162 
163 double Frict::Value()
164 {
165  AlgLoopDetector _(this);
166  double x = InputValue();
167  if (x < 0)
168  return (low + x * tgalpha);
169  if (x > 0)
170  return (high + x * tgalpha);
171  return (0);
172 }
173 
174 #if 0
175 const char *Frict::Name() const
176 {
177  if (HasName())
178  return _name;
179  else
180  return SIMLIB_create_tmp_name("Frict{%p}", this);
181 }
182 #endif
183 
184 ////////////////////////////////////////////////////////////////////////////
185 /// hysteresis constructor
186 Hyst::Hyst(Input i, double _p1, double _p2, double _y1, double _y2, double _tga)
187  : Status(i), p1(_p1), p2(_p2), y1(_y1), y2(_y2), tga(_tga)
188 {
189  Dprintf(("Hyst::Hyst(in,%g,%g,%g,%g,tga=%g)", p1, p2, y1, y2, tga));
190 }
191 
193 {
194  double x = InputValue();
195  double ys = stl;
196  ys = max(ys, y1); // in the case of bad initialization (out of range)
197  ys = min(ys, y2); // can be leaved out if correct init
198  double yn2 = (x - p2) * tga;
199  double yn1 = (x - p1) * tga;
200  double y = ys;
201  if (ys <= yn2)
202  y = min(yn2, y2);
203  if (ys >= yn1)
204  y = max(yn1, y1);
205  st = y; // new status
206  ValueOK = true;
207 }
208 
209 #if 0
210 const char *Hyst::Name() const
211 {
212  if (HasName())
213  return _name;
214  else
215  return SIMLIB_create_tmp_name("Hyst{%p}", this);
216 }
217 #endif
218 
219 ////////////////////////////////////////////////////////////////////////////
220 /// relay constructor
221 Relay::Relay(Input i, double _p1, double _p2, double _p3, double _p4, double _y1, double _y2)
222  : Status(i), p1(_p1), p2(_p2), p3(_p3), p4(_p4), y1(_y1), y2(_y2)
223 {
224  // TODO: check
225  Dprintf(("Relay::Relay(in,%g,%g,%g,%g,y1=%g,y2=%g)",
226  p1, p2, p3, p4, y1, y2));
227 }
228 
230 {
231  double x = InputValue();
232  double y;
233 
234  if (x < p1)
235  y = y1;
236  else if (x < p2)
237  y = stl;
238  else if (x < p3)
239  y = 0;
240  else if (x < p4)
241  y = stl;
242  else
243  y = y2;
244  if (y != stl)
245  ContractStep(); // forces step shortening
246  st = y;
247  ValueOK = true;
248 }
249 
250 #if 0
251 const char *Relay::Name() const
252 {
253  if (HasName())
254  return _name;
255  else
256  return SIMLIB_create_tmp_name("Relay{%p}", this);
257 }
258 #endif
259 
260 ////////////////////////////////////////////////////////////////////////////
261 /// blash constructor
262 Blash::Blash(Input i, double _p1, double _p2, double _tga)
263  : Status(i), p1(_p1), p2(_p2), tga(_tga)
264 {
265  Dprintf(("Blash::Blash(in,%g,%g,tga=%g)", p1, p2, tga));
266 }
267 
269 {
270  // TODO: CHECK !!!
271  double x = InputValue();
272  double ys = stl;
273  double yn1 = (x - p1) * tga;
274  double yn2 = (x - p2) * tga;
275  double y = max(yn2, ys);
276  y = min(yn1, y);
277  st = y;
278  ValueOK = true;
279 }
280 
281 #if 0
282 const char *Blash::Name() const
283 {
284  if (HasName())
285  return _name;
286  else
287  return SIMLIB_create_tmp_name("Blash{%p}", this);
288 }
289 #endif
290 
291 ////////////////////////////////////////////////////////////////////////////
292 /// constructor of class Rline
293 /// implements table-defined function (linear interpolation)
294 // TODO: variants
295 // - use data directly? (no new and copy),
296 // - read from input file
297 Rline::Rline(Input in, int num, double *X, double *Y)
298  : aContiBlock1(in), n(num)
299 {
300  Dprintf(("Rline::Rline(in,%i,X[],Y[])", n));
301  if (n < 2)
302  SIMLIB_error(RlineErr1); // Rline: n<2
303  //
304  // TODO: use vectors of (x,y) pairs
305  //
306  tableX = new double[n];
307 // if (!tableX)
308 // SIMLIB_error(MemoryError);
309  tableY = new double[n];
310 // if (!tableY)
311 // SIMLIB_error(MemoryError);
312  memcpy(tableX, X, n * sizeof(double));
313  memcpy(tableY, Y, n * sizeof(double));
314  for (int i = 1; i < n; i++)
315  if (tableX[i] < tableX[i - 1])
316  SIMLIB_error(RlineErr2); // Rline: tableX not ordered
317  //
318  // OPTIMIZE:
319  // count (tableY[i]-tableY[i-1]) / (tableX[i]-tableX[i-1])
320  // save: division, 4 -, 3 index; price: array[n]
321 }
322 
324 {
325  Dprintf(("Rline::~Rline()", n));
326  delete tableX;
327  delete tableY;
328 }
329 
331 {
332 }
333 
334 double Rline::Value()
335 {
336  AlgLoopDetector _(this);
337  // TODO: add step change detection => Status!
338  double x = InputValue();
339  int i;
340  if (x >= tableX[n - 1])
341  return tableY[n - 1];
342  if (x <= tableX[0])
343  return tableY[0];
344  for (i = 1; x > tableX[i]; i++) { /*empty*/ } // linear search
345  return (tableY[i] - tableY[i - 1]) / (tableX[i] - tableX[i - 1])
346  * (x - tableX[i - 1]) + tableY[i - 1];
347 }
348 
349 #if 0
350 const char *Rline::Name() const
351 {
352  if (HasName())
353  return _name;
354  else
355  return SIMLIB_create_tmp_name("Rline{%p}", this);
356 }
357 #endif
358 
359 } // namespace
Frict(Input in, double l, double h, double tga=1.0)
friction constructor
Definition: stdblock.cc:151
Relay(Input i, double p1, double p2, double p3, double p4, double y1, double y2)
relay constructor
Definition: stdblock.cc:221
double high
Definition: simlib.h:1575
void SIMLIB_error(const enum _ErrEnum N)
print error message and abort program
Definition: error.cc:38
double low
Definition: simlib.h:1558
State variables (memory) base for blocks with internal state (Relay, ...)
Definition: simlib.h:1335
double low
Definition: simlib.h:1608
double tgalpha
Definition: simlib.h:1609
double stl
status from previous step
Definition: simlib.h:1343
continuous block connection (transparent reference) wrapper for pointer to objects of aContiBlock der...
Definition: simlib.h:895
virtual void _Eval() override
evaluate block (with loop detection)
Definition: stdblock.cc:126
double tgalpha
Definition: simlib.h:1576
void ContractStep()
contract step of integration
Definition: intg.cc:64
bool HasName() const
Definition: simlib.h:321
double * tableX
Definition: simlib.h:1627
Lim(Input in, double l, double h, double tga=1.0)
constructor of limitation block
Definition: stdblock.cc:47
double p4
Definition: simlib.h:1404
Implementation of class CalendarList interface is static - using global functions in SQS namespace...
Definition: algloop.cc:32
double max(double a, double b)
Definition: internal.h:286
double * tableY
Definition: simlib.h:1628
virtual void _Eval() override
evaluate block (with loop detection)
Definition: stdblock.cc:330
virtual double Value() override
get block output value this method should be defined in classes derived from aContiBlock ...
Definition: stdblock.cc:130
double tgbeta
Definition: simlib.h:1576
class for algebraic loop detection AlgLoopDetector object should be used in Value() method only it ch...
Definition: internal.h:307
std::string SIMLIB_create_tmp_name(const char *fmt,...)
printf-like function to create temporary name (the length of temporary names is limited) used only ...
Definition: name.cc:80
double p1
Definition: simlib.h:1371
double y1
Definition: simlib.h:1372
Qntzr(Input in, double qstep=1.0)
quantizer constructor
Definition: stdblock.cc:118
double y2
Definition: simlib.h:1405
virtual void Eval() override
evaluate without loop detection
Definition: stdblock.cc:192
double tga
Definition: simlib.h:1389
double p1
Definition: simlib.h:1404
virtual double Value() override
get block output value this method should be defined in classes derived from aContiBlock ...
Definition: stdblock.cc:163
virtual void _Eval() override
evaluate block (with loop detection)
Definition: stdblock.cc:159
virtual void _Eval() override
evaluate block (with loop detection)
Definition: stdblock.cc:91
double tga
Definition: simlib.h:1373
double p2
Definition: simlib.h:1388
double min(double a, double b)
Definition: internal.h:285
double p3
Definition: simlib.h:1404
virtual double Value() override
get block output value this method should be defined in classes derived from aContiBlock ...
Definition: stdblock.cc:334
double high
Definition: simlib.h:1558
Rline(Input in, int num, double *X, double *Y)
constructor of class Rline implements table-defined function (linear interpolation) ...
Definition: stdblock.cc:297
Internal header file for SIMLIB/C++.
virtual void Eval() override
evaluate without loop detection
Definition: stdblock.cc:268
double y2
Definition: simlib.h:1372
Main SIMLIB/C++ interface.
double st
status
Definition: simlib.h:1342
virtual std::string Name() const
get object name
Definition: object.cc:134
SIMLIB_IMPLEMENTATION
Definition: algloop.cc:34
double InputValue()
Definition: simlib.h:944
base for continuous blocks with single input and algebraic loop check
Definition: simlib.h:940
virtual void Eval() override
block evaluation
Definition: stdblock.cc:229
Blash(Input i, double p1, double p2, double tga)
blash constructor
Definition: stdblock.cc:262
#define Dprintf(f)
Definition: internal.h:100
double p1
Definition: simlib.h:1388
double low
Definition: simlib.h:1575
double y1
Definition: simlib.h:1405
double high
Definition: simlib.h:1608
double p2
Definition: simlib.h:1371
double step
Definition: simlib.h:1592
virtual double Value() override
get block output value this method should be defined in classes derived from aContiBlock ...
Definition: stdblock.cc:59
Insv(Input in, double l, double h, double tga=1.0, double tgb=1.0)
dead space
Definition: stdblock.cc:83
virtual double Value() override
get block output value this method should be defined in classes derived from aContiBlock ...
Definition: stdblock.cc:95
double p2
Definition: simlib.h:1404
double tgalpha
Definition: simlib.h:1559
Hyst(Input i, double p1, double p2, double y1, double y2, double tga)
hysteresis constructor
Definition: stdblock.cc:186
virtual void _Eval() override
evaluate block (with loop detection)
Definition: stdblock.cc:55