SIMLIB/C++ 3.09
Loading...
Searching...
No Matches
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
41namespace simlib3 {
42
44////////////////////////////////////////////////////////////////////////////
45/// constructor of limitation block
46//
47Lim::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
56{
57};
58
59double 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
72const 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
83Insv::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
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
107const 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
118Qntzr::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
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
140const 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
151Frict::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
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
175const 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
186Hyst::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
210const 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
221Relay::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
251const 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
262Blash::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
282const 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
297Rline::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
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
350const 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
class for algebraic loop detection AlgLoopDetector object should be used in Value() method only it ch...
Definition: internal.h:307
double p2
Definition: simlib.h:1388
double p1
Definition: simlib.h:1388
double tga
Definition: simlib.h:1389
Blash(Input i, double p1, double p2, double tga)
blash constructor
Definition: stdblock.cc:262
virtual void Eval() override
evaluate without loop detection
Definition: stdblock.cc:268
double low
Definition: simlib.h:1608
virtual void _Eval() override
evaluate block (with loop detection)
Definition: stdblock.cc:159
virtual double Value() override
get block output value this method should be defined in classes derived from aContiBlock
Definition: stdblock.cc:163
double tgalpha
Definition: simlib.h:1609
double high
Definition: simlib.h:1608
Frict(Input in, double l, double h, double tga=1.0)
friction constructor
Definition: stdblock.cc:151
double tga
Definition: simlib.h:1373
virtual void Eval() override
evaluate without loop detection
Definition: stdblock.cc:192
double p2
Definition: simlib.h:1371
Hyst(Input i, double p1, double p2, double y1, double y2, double tga)
hysteresis constructor
Definition: stdblock.cc:186
double y1
Definition: simlib.h:1372
double y2
Definition: simlib.h:1372
double p1
Definition: simlib.h:1371
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:91
Insv(Input in, double l, double h, double tga=1.0, double tgb=1.0)
dead space
Definition: stdblock.cc:83
double high
Definition: simlib.h:1575
double tgalpha
Definition: simlib.h:1576
double low
Definition: simlib.h:1575
double tgbeta
Definition: simlib.h:1576
virtual double Value() override
get block output value this method should be defined in classes derived from aContiBlock
Definition: stdblock.cc:95
double tgalpha
Definition: simlib.h:1559
double low
Definition: simlib.h:1558
virtual void _Eval() override
evaluate block (with loop detection)
Definition: stdblock.cc:55
virtual double Value() override
get block output value this method should be defined in classes derived from aContiBlock
Definition: stdblock.cc:59
double high
Definition: simlib.h:1558
Lim(Input in, double l, double h, double tga=1.0)
constructor of limitation block
Definition: stdblock.cc:47
virtual void _Eval() override
evaluate block (with loop detection)
Definition: stdblock.cc:126
double step
Definition: simlib.h:1592
Qntzr(Input in, double qstep=1.0)
quantizer constructor
Definition: stdblock.cc:118
virtual double Value() override
get block output value this method should be defined in classes derived from aContiBlock
Definition: stdblock.cc:130
double p3
Definition: simlib.h:1404
Relay(Input i, double p1, double p2, double p3, double p4, double y1, double y2)
relay constructor
Definition: stdblock.cc:221
double y1
Definition: simlib.h:1405
double y2
Definition: simlib.h:1405
virtual void Eval() override
block evaluation
Definition: stdblock.cc:229
double p4
Definition: simlib.h:1404
double p2
Definition: simlib.h:1404
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:334
double * tableX
Definition: simlib.h:1627
virtual void _Eval() override
evaluate block (with loop detection)
Definition: stdblock.cc:330
Rline(Input in, int num, double *X, double *Y)
constructor of class Rline implements table-defined function (linear interpolation)
Definition: stdblock.cc:297
double * tableY
Definition: simlib.h:1628
bool HasName() const
Definition: simlib.h:321
virtual std::string Name() const
get object name
Definition: object.cc:134
State variables (memory) base for blocks with internal state (Relay, ...)
Definition: simlib.h:1335
double st
status
Definition: simlib.h:1342
double stl
status from previous step
Definition: simlib.h:1343
base for continuous blocks with single input and algebraic loop check
Definition: simlib.h:940
double InputValue()
Definition: simlib.h:944
@ RlineErr2
Definition: errors.h:86
@ BadQntzrStep
Definition: errors.h:67
@ LowGreaterHigh
Definition: errors.h:66
@ RlineErr1
Definition: errors.h:85
Internal header file for SIMLIB/C++.
#define Dprintf(f)
Definition: internal.h:100
Implementation of class CalendarList interface is static - using global functions in SQS namespace.
Definition: algloop.cc:32
void SIMLIB_error(const enum _ErrEnum N)
print error message and abort program
Definition: error.cc:38
SIMLIB_IMPLEMENTATION
Definition: algloop.cc:34
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 min(double a, double b)
Definition: internal.h:285
double max(double a, double b)
Definition: internal.h:286
void ContractStep()
contract step of integration
Definition: intg.cc:64
Main SIMLIB/C++ interface.