Add built-in unidirectional time bridge - #418
LourensVeen wants to merge 3 commits into
Conversation
|
|
||
| If the two programs do not run on exactly the same timeline, but one has somewhat | ||
| smaller or larger time steps than the other or the size of the steps varies, then this | ||
| will no longer work, because the number of messages sent by one side will not match the |
There was a problem hiding this comment.
it is not just the number of messages, you could have equal number but still the clock skew you mention
There was a problem hiding this comment.
I'm trying to say too many things at the same time here maybe. But then you can get both clock skew and deadlocks with and without the same number of messages. Although you can't get clock skew if the time steps are the same. Okay, I'll try to phrase this better.
| Connecting components using a time bridge | ||
| ----------------------------------------- | ||
|
|
||
| The standard MUSCLE3 time bridge provides for unidirectional communication between two |
There was a problem hiding this comment.
maybe this is the 'simplest' one but not the standard one?
There was a problem hiding this comment.
There's only one now anyway, and I'm not sure which other ones could exist and be useful. I can't imagine a simpler one though, so that's a good point.
| The time bridge will ignore the contents of that message, but it will use the timestamps | ||
| to decide which input messages to send to the receiver in its next message. It will then | ||
| receive those messages from the sender if needed and available, collate them into a | ||
| list, and send that list to the receiver, after which it will receive the next clock |
There was a problem hiding this comment.
this sounds like the entire list is always sent, but actually you specify below what kind of aggegration functions exist. Maybe worth a pointer
| calculated based on the current state and any other inputs at ``t_r_cur``, and the | ||
| receiver will likely want to use the latest value before ``t_r_cur``. | ||
|
|
||
| - The receiver uses an implicit Euler solver. Its next state will be calculated based on |
There was a problem hiding this comment.
you can generalize the euler implicit/explicit to a theta scheme perhaps (gets you crank nicholson). But the implicit Euler coupling scheme through muscle3 confuses me anyway for now
There was a problem hiding this comment.
Hmm, never heard of but I looked it up and I'll put it on the list for the future. Ideally, we'd have a description of all the different coupling schemes and how to implement them, but that's a bit too much for right now.
There was a problem hiding this comment.
If you relate this to the theta-scheme:
- θ = 0: explicit Euler: evaluates at t_r_cur
- θ = 1: implicit Euler: evaluates at t_r_next
- θ = 0.5: Crank–Nicolson (2nd-order accurate): evaluates at the midpoint, (t_r_cur + \Delta t / 2)
The goal is to always obtain the timestamp that is closest to the desired timestamp.
| messages may be received twice, once as the last message before ``t_r_next`` and then | ||
| again on the next timestep as the last message before ``t_r_cur``. | ||
|
|
||
| At each time step, the receiver will receive a list from the time bridge, containing |
There was a problem hiding this comment.
But that would mean that the component gets a different interface just from being connected to the interface, because it may want to unpack the list? I think it is nicer to keep the interface (single messages) the same, because two of your typical settings are resulting in single messages being sent at all
There was a problem hiding this comment.
Good idea! I can also imagine a helper component in between the time bridge and the receiver that takes the list and processes it down to a single value somehow. But if you just want the latest value then it's nice to be able to connect directly. Should be a configuration option I think.
|
|
||
| If the two programs do not run on exactly the same timeline, but one has somewhat | ||
| smaller or larger time steps than the other, then we will get clock skew, where the | ||
| simulation time in the two components doesn't match anymore and information from the |
There was a problem hiding this comment.
I would use “simulated time” instead of “simulation time,” as the latter could be confusing. It might be interpreted as either the time it took to run the simulation or the amount of physics time being simulated.
|
|
||
| The simplest MUSCLE3 time bridge provides for unidirectional communication between two | ||
| instances' O_I and S ports. The sending side needs to have an O_I port sending the data | ||
| needed by the receiver, and the receiver needs the corresponding S port to receive it. |
| calculated based on the current state and any other inputs at ``t_r_cur``, and the | ||
| receiver will likely want to use the latest value before ``t_r_cur``. | ||
|
|
||
| - The receiver uses an implicit Euler solver. Its next state will be calculated based on |
There was a problem hiding this comment.
If you relate this to the theta-scheme:
- θ = 0: explicit Euler: evaluates at t_r_cur
- θ = 1: implicit Euler: evaluates at t_r_next
- θ = 0.5: Crank–Nicolson (2nd-order accurate): evaluates at the midpoint, (t_r_cur + \Delta t / 2)
The goal is to always obtain the timestamp that is closest to the desired timestamp.
| Note that if the time step of the receiver is smaller than that of the sender, or if the | ||
| receiver starts its simulation before the sender starts, then there may not be any | ||
| messages with timestamps between ``t_r_cur`` and ``t_r_next``, and the receiver may | ||
| receive an empty list. |
There was a problem hiding this comment.
What happens if it receives an empty list?
|
|
||
| If ``recv_last_before_cur`` and ``recv_last_before_next`` are both ``1``, then | ||
| messages may be received twice, once as the last message before ``t_r_next`` and then | ||
| again on the next timestep as the last message before ``t_r_cur``. |
There was a problem hiding this comment.
Why does it matter how many times the messages of a certain time stamp are included?
|
|
||
| If only ``recv_last_before_cur`` or ``recv_last_before_next`` is selected, then at most | ||
| one message will be sent to the receiver. In that case, you may want to set the setting | ||
| ``recv_list`` to ``false`` (it is ``true`` by default), to tell the time bridge to just |
There was a problem hiding this comment.
- If
recv_last_before_curorrecv_last_before_nextis set, can’t we automatically setrecv_listtofalseinstead of requiring the user to specify it? - Are there more settings next to
recv_last_before_cur,recv_last_before_next,recv_cur_to_next, andrecv_list?

This adds a new built-in time bridge actor to MUSCLE3.
It's only the documentation at the moment, describing how it will work, so that can be reviewed to make sure it makes sense before I add the implementation.