Re: Lahman, how ya doing?



In article <qN8ce.10126$O2.7169@trndny04>,
H. S. Lahman <hsl@xxxxxxxxxxxxxxxxx> wrote:
>Responding to Hansen...

Hi!

....
>Bottom line: one has to think about the simulation as-if it were
>real-time when dealing with synchronization, delays, etc. The closer
>the simulation structure reflects the real-time structure, the easier
>that will be. For example, the real-time system is proactively
>triggered by timer events. So don't have the tasks poll a timer and
>then make a decision about what to do. Construct the software so it
>reacts explicitly and unequivocally to the events that the timer
>generates just like the real system. Then you isolate the problem of
>generating the "real-time" events as a simulation implementation problem
>for the Timer object rather than as part of emulation abstractions.

There's also the matter of what resolution is needed. In the real system,
sometimes an event like adjusting the control is more than 1/60 second
late. But not 7/60 seconds late. And the thermal time constant of the
target is around 14 seconds, much longer than any delays in the control
loop. The data I've taken fits well to a model second-order control
system, and in general I've seen no reason to believe that processing lags
have any interesting effect, so I think the ideal computer approximation
will do.

>
>>>>I also need jobs that do task 1 at time interval 1, and task 2 at time
>>>>interval 2. But it won't be hard to add a
>>>>
>>>> time.add_task(&c3, 5, 20);
>>>
>>>At the risk of being picky, doesn't this do the /same/ task twice?
>>
>>
>> No. In the system I want to simulate, there's a sampling time of, say,
>> one second, and an averaging time of, say, 60 seconds. Once per second it
>> takes a data point and calculates a running total and total^2, and once
>> per 60 seconds it calculates and reports an average and standard
>> deviation, and zeroes the totals.
>
>OK, I thought the tasks would be in different objects. So the c3 object
>has a state machine like(?):
>
> E2:sixty ticks
>+--------> [Sampled] --------------> [Statistics Computed]
>| | ^ |
>| | | |
>+------------+ +--------------------------+
>E1:one tick E1:one tick
>
>and all you are doing is registering it to receive both the E1 and E2
>events from the Time object. If so, then it might be simpler to just
>register via
>
>time.add_task(&c3, 1);
>time.add_task(&c3, 60);
>
>since the Time object shouldn't care about duplicate handles; it just
>needs to know where to send the indicated event. Then you don't a
>special implementation in Time for this case.

Yes. Except it has to know that the first line refers to a sample and the
second line refers to an averaging. I can think of not-so-clean ways
around that, like a third parameter that specifies which task, or a
counter internal to the object which then wouldn't need a trigger for the
second event. Or maybe make every event a double even with a third
parameter 0=off by default. I can't think of a satisfactorily clean way.

>>>You kind of get that for free if you use a single event queue and
>>>popping an event doesn't return in the event queue manager until the
>>>task is completed. If, though, the timer event is only one of several
>>>events that may be issued to complete tasks, one needs a different
>>>mechanism.
>>
>>
>> What I've done so far, I don't think you could really call an event queue.
>> Each task keeps a wait_time and a next_event, and executes and updates
>> when polled with a time >= next_event. Since it's a simulation, I don't
>> think it's really sensible to have an event queue. It's not going to be
>> waiting for a user to decide to click the mouse or anything, except
>> externally to the simulation.
>
>If you have a timer at all it is easier to make it event-based. Then
>you don't have to write any conditional code or have history attributes.
> The serialization is essentially free, as in the 1, 60, and 7/60 event
>case above. At most you may have to have a prioritization scheme. The
>Timer will be a simpler and more generic as well. And the event queue
>manager will be entirely reusable (the target &cN is passed in the event).

I guess I'm not sure whether I'm event based. I gave a little more detail
elsewhere, but as I have it set up now, when timer.add_task(&c1,5) is
called, a Task internal to Timer (the user doesn't directly interact with
it) is created, and is given the Block pointer and the timing information.
Every time timer ticks, each Task is told the current time. The Task
decides whether to trigger. When it triggers, it sends the Block the
elapsed time since the last trigger, e.g. ptr->evolve(dt).

That sort of seems event based since each Task is really just sitting
there waiting for a kick in the pants, and each Block is sitting there
waiting for a kick. But I guess I don't know the language very well. The
timer still calls each task, one by one. I suppose it's not really an
event queue, anyway.

It's actually robust against delays as it's written, too. The time
interval passed is not the canonical wait_time, but dt =
current_time-last_time, and if the current_time is even many wait_time's
beyond the next scheduled event it will trigger once with the proper
elapsed time and then catch up and schedule the next event in the
appropriate time slot. That's sort of immaterial in a simulation, but it
was kind of satisfying to think it could be used in a real-time system if
I'd wanted to. If I did want to simulate delays I could, say, inactivate
the controller block for some time-- send it a number for "inactive until"
or something-- and then it would just keep going after that.

>
>>>Note that one can even change the role of the Timer from doling out
>>>events based on clock ticks to a arbitrator. Suppose you have an
>>>Activity Diagram with multiple dependencies among tasks like
>>>
>>>Task1 task2 task3
>>> | | |
>>> +----+ +----+ |
>>> | | |
>>> ===== |
>>> | |
>>> task4 |
>>> | |
>>> +-------+ +------+
>>> | |
>>> =====
>>> |
>>> task5
>>>
>>>Now the Timer can manage a suite of semaphores for the tasks. It starts
>>>off with one task, say task2 and sends it a trigger event. When task2
>>>completes, it sends back an I'm done event to Timer. Timer then sets
>>>the task2 semaphore and and checks its rules (each task has a bitmap of
>>>semaphores that must be set for it to execute). It selects some task
>>>whose prerequisites are done, say task3. And so on... When all the
>>>semaphores are set, Timer clears them and starts over.]
>>
>>
>> Not that I don't appreciate the insight; I'm reading it and thinking of
>> things to do with it. But I'm looking at a system more like
>>
>> beam
>> |
>> heater --- thermal block 1 --- heat link --- thermal block 2 --- He bath
>> |
>> thermometer
>>
>> There isn't a time sequence of events, every part of the system evolves
>> simultaneously. Heat goes from the heater to thermal block 1, heat goes
>> from thermal block 1 to the heat link and to block 2, the temperature and
>> resistance of the thermometer change as the heat load changes, all at the
>> same time. So at a given instant of simulation time I just freeze the
>> state and determine how much heat goes into and out of block 1, how much
>> heat goes into and out of block 2, how much does the temperature of the
>> thermometer change, etc.
>
>That's fine, but I don't think it is relevant to the sampling timer
>issues. B-) As I understand it you are computing what those actual
>transfers to the He bath would be in order to simulate what the
>thermometer would actually see (i.e., the simulated temperature will be
>the from the net residual heat in thermal block 1 after the heat flow is
>computed). IOW, you don't care about the propagation delays on the
>right because all you want is the heat out of the 1st thermal block.
>
>The simple way to march those calculations is to just daisy-chain them.

Daisy-chaining makes me nervous. I'm not really sure what you mean by it.
I imagine Blocks representing elements of the system, and they can be
connected together in any sort of pattern, with loops and interconnections
all over the place. Change any little thing and it's hard to maintain one
iteration. Or maybe you mean the blocks are just arranged in a queue,
and my code

for (ptr = list.begin(); ptr != list.end(); ptr++)
(*ptr)->timeis(t);

would be replaced by

ptr = list.begin();
(*ptr)->timeis(t); // rely on first object to tickle second, etc.

> In fact, from an OOA/D viewpoint the calculation of the residual heat
>the thermometer is sampling would probably be best done in a single
>realized method. The algorithms are rigidly defined mathematically so
>they aren't part of the OO problem solution flow of control, which is
>managing samples in the simulation. That is, the decisions made in the
>actual heat flow algorithm are orthogonal to the simulation problem,
>which is about managing when that calculation gets triggered relative to
>the thermometer sampling and statistics.

Yeah, I've been wondering how much compressing I want to do. A thermal
block, thermometer, bridge circuit, and lock-in amplifier can be reduced
to a single block-- analog heat input, voltage output to the digital
controller. I guess the only matter is configurability of the systems to
be simulated, but that can be addressed as needed. There's another
control system across the thermal link so it's not really independent. It
approximately is, there seems to be very little cross-talk and the second
block acts like a constant-temperature heat-sink, which is exactly what
it's supposed to do (the He bath is a noise source). But if I get one
working it would be trivial to add the second.


--
"Will we be suturing the anus?"
.



Relevant Pages

  • Re: Lahman, how ya doing?
    ... I assume this is a delay for settling ... It's a simulation, so simulated time will be frozen until all tasks ... If, though, the timer event is only one of several ... Heat goes from the heater to thermal block 1, ...
    (comp.object)
  • Re: Lahman, how ya doing?
    ... There will be event queue manager program unit and a Timer program unit that gets ticks from the system clock and generates events to other program units. ... My point in this context is that the closer your simulation models that actual software, the better and more robust it will be. ... Another way is to not use the system clock at all and just trigger the next simulation clock tick with an event to the Timer that is generated when all the processing for a single clock tick is done. ...
    (comp.object)
  • Re: Lahman, how ya doing?
    ... The closer the simulation structure reflects the real-time structure, ... So don't have the tasks poll a timer and then make a decision about what to do. ... Then you isolate the problem of generating the "real-time" events as a simulation implementation problem for the Timer object rather than as part of emulation abstractions. ... It just so happens that the rules of finite state machines coincide very nicely with fundamental OO practice. ...
    (comp.object)
  • Re: Lahman, how ya doing?
    ... >> target is around 14 seconds, much longer than any delays in the control ... >queue manager program unit and a Timer program unit that gets ticks from ... the Thermometer object reads an attribute in the simulation ... executes at a particular time, ...
    (comp.object)
  • Re: Havent done anything real with OOP yet.
    ... >>will be easier to deal with and will reduce risk of simulation errors. ... >>Thermometer, heat transfer to the Cell, and heat transfer to the heat ... > thermometer, cell, heatsink, and etc., don't exist. ... A simulation models something, in this case hardware. ...
    (comp.object)