1+ # Define and register smooth functions
2+ # These are "smooth" aka differentiable and avoid Gibbs effect
3+ # These follow: `offset` + `smooth_wave` * `smooth_step` with zero output for `t < start_time`
4+ function smooth_cos (x, δ, f, amplitude, ϕ, offset, start_time)
5+ offset + amplitude * cos (2 * π* f* (x - start_time) + ϕ) * smooth_step (x, δ, one (x), zero (x), start_time)
6+ end
7+
8+ function smooth_damped_sin (x, δ, f, amplitude, damping, ϕ, offset, start_time)
9+ offset + exp ((start_time - x)* damping)* amplitude* sin (2 * π* f* (x - start_time) + ϕ) * smooth_step (x, δ, one (x), zero (x), start_time)
10+ end
11+
12+ function smooth_ramp (x, δ, height, duration, offset, start_time)
13+ offset + height/ (duration) * (smooth_xH (x, δ, start_time) - smooth_xH (x, δ, start_time+ duration))
14+ end
15+
16+ function smooth_sin (x, δ, f, amplitude, ϕ, offset, start_time)
17+ offset + amplitude * sin (2 * pi * f* (x - start_time) + ϕ) * smooth_step (x, δ, one (x), zero (x), start_time)
18+ end
19+
20+ function smooth_square (x, δ, f, amplitude, offset, start_time)
21+ offset + amplitude* 2 atan (sin (2 π* (x - start_time)* f)/ δ)/ π * smooth_step (x, δ, one (x), zero (x), start_time)
22+ end
23+
24+ function smooth_step (x, δ, height, offset, start_time)
25+ offset + height* (atan ((x - start_time)/ δ)/ π + 0.5 )
26+ end
27+
28+ function smooth_triangular (x, δ, f, amplitude, offset, start_time)
29+ offset + amplitude * (1 - 2 acos ((1 - δ)sin (2 π* (x - start_time)* f))/ π) * smooth_step (x, δ, one (x), zero (x), start_time)
30+ end
31+
32+ function smooth_xH (x, δ, tₒ)
33+ 0.5 * (x- tₒ) * (1 + ((x- tₒ)/ sqrt ((x- tₒ)^ 2 + δ^ 2 )))
34+ end
35+
36+ function square (x, f, amplitude, offset, start_time)
37+ offset + (x > start_time) * (amplitude * (4 * floor (f* (x - start_time)) - 2 * floor (2 * (x - start_time)* f) + 1 ))
38+ end
39+
40+ function triangular (x, f, amplitude, offset, start_time)
41+ p = 1 / f # period
42+ offset + (x > start_time) * (4 * amplitude * f * abs (abs ((x - p/ 4 - start_time) % p) - p/ 2 ) - amplitude)
43+ end
44+
45+ @register_symbolic smooth_cos (x, δ, f, amplitude, ϕ, offset, start_time)
46+ @register_symbolic smooth_damped_sin (x, δ, f, amplitude, damping, ϕ, offset, start_time)
47+ @register_symbolic smooth_ramp (x, δ, height, duration, offset, start_time)
48+ @register_symbolic smooth_sin (x, δ, f, amplitude, ϕ, offset, start_time)
49+ @register_symbolic smooth_square (x, δ, f, amplitude, offset, start_time)
50+ @register_symbolic smooth_step (x, δ, height, offset, start_time)
51+ @register_symbolic smooth_triangular (x, δ, f, amplitude, offset, start_time)
52+ @register_symbolic triangular (x, f, amplitude, offset, start_time)
53+ @register_symbolic square (x, f, amplitude, offset, start_time)
54+
155"""
256Generate constant signal.
357
@@ -22,25 +76,36 @@ Generate sine signal.
2276# Parameters:
2377- `frequency`: [Hz] Frequency of sine wave
2478- `amplitude`: Amplitude of sine wave
25- - `phase`: [rad] Phase of sine wave
79+ - `phase`: [rad] Phase of sine wave
2680- `offset`: Offset of output signal
2781- `start_time`: [s] Output `y = offset` for `t < start_time`
82+ - `smooth`: If `true`, returns a smooth wave. Defaults to `false`
83+ It uses a smoothing factor of `δ=1e-5`
2884
2985# Connectors:
3086- `output`
3187"""
32- function Sine (;name,
33- frequency,
88+ function Sine (;name,
89+ frequency,
3490 amplitude= 1 ,
3591 phase= 0 ,
3692 offset= 0 ,
37- start_time= 0 )
93+ start_time= 0 ,
94+ smooth= false )
3895
3996 @named output = RealOutput ()
4097 pars = @parameters offset= offset start_time= start_time amplitude= amplitude frequency= frequency phase= phase
98+ equation = if smooth == false
99+ offset + ifelse (t < start_time, 0 , amplitude* sin (2 * pi * frequency* (t - start_time) + phase))
100+ else
101+ δ = 1e-5
102+ smooth_sin (t, δ, frequency, amplitude, phase, offset, start_time)
103+ end
104+
41105 eqs = [
42- output. u ~ offset + ifelse (t < start_time, 0 , amplitude * sin ( 2 * pi * frequency * (t - start_time) + phase))
106+ output. u ~ equation
43107 ]
108+
44109 compose (ODESystem (eqs, t, [], pars; name= name), [output])
45110end
46111
@@ -50,32 +115,43 @@ Generate cosine signal.
50115# Parameters:
51116- `frequency`: [Hz] Frequency of sine wave
52117- `amplitude`: Amplitude of sine wave
53- - `phase`: [rad] Phase of sine wave
118+ - `phase`: [rad] Phase of sine wave
54119- `offset`: Offset of output signal
55120- `start_time`: [s] Output `y = offset` for `t < start_time`
121+ - `smooth`: If `true`, returns a smooth wave. Defaults to `false`
122+ It uses a smoothing factor of `δ=1e-5`
56123
57124# Connectors:
58125- `output`
59126"""
60- function Cosine (;name,
61- frequency,
127+
128+ function Cosine (;name,
129+ frequency,
62130 amplitude= 1 ,
63131 phase= 0 ,
64132 offset= 0 ,
65- start_time= 0 )
133+ start_time= 0 ,
134+ smooth= false )
66135
67136 @named output = RealOutput ()
68137 pars = @parameters offset= offset start_time= start_time amplitude= amplitude frequency= frequency phase= phase
138+ equation = if smooth == false
139+ offset + ifelse (t < start_time, zero (t), amplitude* cos (2 * pi * frequency* (t - start_time) + phase))
140+ else
141+ δ = 1e-5
142+ smooth_cos (t, δ, frequency, amplitude, phase, offset, start_time)
143+ end
69144 eqs = [
70- output. u ~ offset + ifelse (t < start_time, 0 , amplitude * cos ( 2 * pi * frequency * (t - start_time) + phase))
145+ output. u ~ equation
71146 ]
147+
72148 compose (ODESystem (eqs, t, [], pars; name= name), [output])
73149end
74150
75151"""
76152Generate current time signal.
77153
78- # Parameters:
154+ # Parameters:
79155- `offset`: Offset of output signal
80156- `start_time`: [s] Output `y = offset` for `t < start_time`
81157
@@ -86,8 +162,9 @@ function ContinuousClock(;name, offset=0, start_time=0)
86162 @named output = RealOutput ()
87163 pars = @parameters offset= offset start_time= start_time
88164 eqs = [
89- output. u ~ offset + ifelse (t < start_time, 0 , t - start_time)
165+ output. u ~ offset + ifelse (t < start_time, zero (t) , t - start_time)
90166 ]
167+
91168 compose (ODESystem (eqs, t, [], pars; name= name), [output])
92169end
93170
@@ -99,22 +176,73 @@ Generate ramp signal.
99176- `duration`: [s] Duration of ramp (= 0.0 gives a Step)
100177- `offset`: Offset of output signal
101178- `start_time`: [s] Output `y = offset` for `t < start_time`
179+ - `smooth`: If `true`, returns a smooth wave. Defaults to `false`
180+ It uses a smoothing factor of `δ=1e-5`
102181
103182# Connectors:
104183- `output`
105184"""
106- function Ramp (;name,
107- offset= 0 ,
185+ function Ramp (;name,
108186 height= 1 ,
109- duration= 1 ,
110- start_time= 0 )
187+ duration= 1 ,
188+ offset= 0 ,
189+ start_time= 0 ,
190+ smooth= false )
111191
112192 @named output = RealOutput ()
113193 pars = @parameters offset= offset start_time= start_time height= height duration= duration
114- eqs = [
115- output . u ~ offset + ifelse (t < start_time, 0 ,
194+ equation = if smooth == false
195+ offset + ifelse (t < start_time, 0 ,
116196 ifelse (t < (start_time + duration), (t - start_time) * height / duration, height))
197+ else
198+ δ = 1e-5
199+ smooth_ramp (t, δ, height, duration, offset, start_time)
200+ end
201+
202+ eqs = [
203+ output. u ~ equation
204+ ]
205+
206+ compose (ODESystem (eqs, t, [], pars; name= name), [output])
207+ end
208+
209+ """
210+ Generate smooth square signal.
211+
212+ # Parameters:
213+ - `frequency`: [Hz] Frequency of square wave
214+ - `amplitude`: Amplitude of square wave
215+ - `offset`: Offset of output signal
216+ - `start_time`: [s] Output `y = offset` for `t < start_time`
217+ - `smooth`: If `true`, returns a smooth wave. Defaults to `false`
218+ It uses a smoothing factor of `δ=1e-5`
219+
220+ # Connectors:
221+ - `output`
222+ """
223+ function Square (; name, frequency= 1.0 , amplitude= 1.0 ,
224+ offset= 0.0 , start_time= 0.0 , smooth= false )
225+ δ = 1e-5
226+
227+ @named output = RealOutput ()
228+ pars = @parameters begin
229+ frequency= frequency
230+ amplitude= amplitude
231+ offset= offset
232+ start_time= start_time
233+ end
234+
235+ equation = if smooth == false
236+ square (t, frequency, amplitude, offset, start_time)
237+ else
238+ δ = 1e-5
239+ smooth_square (t, δ, frequency, amplitude, offset, start_time)
240+ end
241+
242+ eqs = [
243+ output. u ~ equation
117244 ]
245+
118246 compose (ODESystem (eqs, t, [], pars; name= name), [output])
119247end
120248
@@ -125,16 +253,26 @@ Generate step signal.
125253- `height`: Height of step
126254- `offset`: Offset of output signal
127255- `start_time`: [s] Output `y = offset` for `t < start_time`
256+ - `smooth`: If `true`, returns a smooth wave. Defaults to `false`
257+ It uses a smoothing factor of `δ=1e-5`
128258
129259# Connectors:
130260- `output`
131261"""
132- function Step (;name, offset = 0 , height = 1 , start_time= 0 )
262+ function Step (;name, height = 1 , offset = 0 , start_time= 0 , smooth = true )
133263 @named output = RealOutput ()
134264 pars = @parameters offset= offset start_time= start_time height= height
265+ equation = if smooth == false
266+ offset + ifelse (t < start_time, zero (t), height)
267+ else
268+ δ = 1e-5
269+ smooth_step (t, δ, height, offset, start_time)
270+ end
271+
135272 eqs = [
136- output. u ~ offset + ifelse (t < start_time, 0 , height)
273+ output. u ~ equation
137274 ]
275+
138276 compose (ODESystem (eqs, t, [], pars; name= name), [output])
139277end
140278
@@ -145,26 +283,81 @@ Generate exponentially damped sine signal.
145283- `frequency`: [Hz] Frequency of sine wave
146284- `amplitude`: Amplitude of sine wave
147285- `damping`: [1/s] Damping coefficient of sine wave
148- - `phase`: [rad] Phase of sine wave
286+ - `phase`: [rad] Phase of sine wave
149287- `offset`: Offset of output signal
150288- `start_time`: [s] Output `y = offset` for `t < start_time`
289+ - `smooth`: If `true`, returns a smooth wave. Defaults to `false`
290+ It uses a smoothing factor of `δ=1e-5`
151291
152292# Connectors:
153293- `output`
154294"""
155- function ExpSine (;name,
156- frequency,
295+ function ExpSine (; name,
296+ frequency,
157297 amplitude= 1 ,
158298 damping= 0.1 ,
159299 phase= 0 ,
160300 offset= 0 ,
161- start_time= 0 )
301+ start_time= 0 ,
302+ smooth= false )
162303
163304 @named output = RealOutput ()
164305 pars = @parameters offset= offset start_time= start_time amplitude= amplitude frequency= frequency phase= phase damping= damping
306+
307+ equation = if smooth == false
308+ offset + ifelse (t < start_time, 0 , amplitude * exp (- damping * (t - start_time)) * sin (2 * pi * frequency* (t - start_time) + phase))
309+ else
310+ δ = 1e-5
311+ smooth_damped_sin (t, δ, frequency, amplitude, damping, phase, offset, start_time)
312+ end
313+
314+ eqs = [
315+ output. u ~ equation
316+ ]
317+
318+ compose (ODESystem (eqs, t, [], pars; name= name), [output])
319+ end
320+
321+ """
322+ Generate smooth triangular signal for frequencies less than or equal to 25 Hz
323+
324+ # Parameters:
325+ - `frequency`: [Hz] Frequency of square wave
326+ - `amplitude`: Amplitude of square wave
327+ - `offset`: Offset of output signal.
328+ - `start_time`: [s] Output `y = offset` for `t < start_time`
329+ - `smooth`: If `true`, returns a smooth wave. Defaults to `false`
330+ It uses a smoothing factor of `δ=1e-5`
331+
332+ # Connectors:
333+ - `output`
334+ """
335+ function Triangular (; name, amplitude= 1.0 , frequency= 1.0 ,
336+ offset= 0.0 , start_time= 0.0 , smooth= false )
337+
338+ if smooth
339+ frequency > 25 && @warn " `frequency > 25` can lead to non-triangular wave pattern"
340+ end
341+
342+ @named output = RealOutput ()
343+ pars = @parameters begin
344+ amplitude= amplitude
345+ frequency= frequency
346+ offset= offset
347+ start_time= start_time
348+ end
349+
350+ equation = if smooth == false
351+ triangular (t, frequency, amplitude, offset, start_time)
352+ else
353+ δ = 1e-5
354+ smooth_triangular (t, δ, frequency, amplitude, offset, start_time)
355+ end
356+
165357 eqs = [
166- output. u ~ offset + ifelse (t < start_time, 0 , amplitude * exp ( - damping * (t - start_time)) * sin ( 2 * pi * frequency * (t - start_time) + phase))
358+ output. u ~ equation
167359 ]
360+
168361 compose (ODESystem (eqs, t, [], pars; name= name), [output])
169362end
170363
0 commit comments