问题
Suppose that I'd like to model an alarm clock that produces 10 beeps (one per second) every morning at 01:00:
model DailyBeep
import SI = Modelica.SIunits;
import Modelica.SIunits.Conversions.*;
constant SI.Time oneDay = 86459.17808 "one day in seconds";
parameter SI.Time startTime = from_hour(1) "time to start beeping";
parameter Real numBeeps = 10 "the number of beeps to make";
Boolean beeping "true when we should beep every second";
Real beepsRemaining "the number of beeps remaining";
initial equation
beeping = false;
beepsRemaining = numBeeps;
algorithm
when sample(startTime, oneDay) then
beeping := true;
beepsRemaining := numBeeps;
end when "starts the beeping state";
when beeping and sample(0, 1) then
if beepsRemaining == 0 then
beeping := false;
else
// beep() // makes a sound
beepsRemaining := beepsRemaining - 1;
end if;
end when "beep every second, only when beeping is enabled";
end DailyBeep;
In the model above, I produce a 'beep' every second (sample(0,1)
) so long as beeping
is true. I would expect to get 10 time events in my simulation at 01:00 each morning if I run the simulation for several days.
However, running the simulation with my end time set to 3600 seconds under OpenModelica results in slightly over 3600 time events--one for every second!
### STATISTICS ###
events
3601 time events
This doesn't scale well if I want to simulate my alarm clock over a period of several months. Is there a way to gate when
statements in Modelica such that they only produce time events when they're enabled? Should I use something else in this case instead of a when
statement?
回答1:
Modelica will always sample at the high rate when you use time events, you might be able to get around it using state events.
I think there is another alternative using clocks and the new synchronous features in Modelica 3.x, you could try and see.
回答2:
This depends on the optimizations performed in the Modelica tool. Dymola only generates 12 time events for this (going from 10 to 0 should generate 11 time events - not just 10; I haven't checked for the 12th one).
As indicated by @sjoelund.se you can use time>=nextTime
, but to be simple and safe instead of time>=nextTime and numTicks>0
only set nextTime
when there is an event:
when time>=nextTime then
if beepsRemaining>0 then
nextTime:=nextTime+1.0;
beepsRemaining:=pre(beepsRemaining)-1;
end if;
end when;
I believe all Modelica tools will handle that.
Note that beepsRemaining==0
is not correct Modelica, since you are comparing Reals for equality. I would recommend using Integer and replacing the test by beepsRemaining<=0
(or the inverse as above).
And the oneDay value looks weird to me. I would use from_hour(24)
.
来源:https://stackoverflow.com/questions/42815089/how-do-i-gate-a-when-statement-in-modelica-to-limit-time-event-generation