Open jmaedler opened 1 week ago
In the discussion with @YingboMa we already figured out that the initial condition before starting the simulation is not consistent... even if the system of equations for the initialization is actually only linear I am a bit confused...
Now my problem: If I use the code above the volumes V and the levels L are set back to the initial each time the callback is called. I do not change anything about the variables... so I did not expect this behavior. Is this intentional? What am I doing wrong here?
This, unfortunately, is due to a known issue with the initialization system that's ran after the callback happens. It reruns the initialization system that it runs at the beginning of the simulation, which then usually sets everything to 0s. There's a change in PR right now that fixes this behavior (it's come up a few times, so I'll probably cherry-pick that out into its own PR and then ask for that to be merged in advance of the rest of the stuff that's holding that big PR up). Right now, the only workaround to this issue is to disable the initialization system.
I'll try to get that fix out this weekend.
Hi @BenChung, thank you for the explanation. ...And thank you for pushing for a fix :-)
Is there also development going on to get rid of the irreducible = true
workarround by providing a way to use observed variables in callbacks? I am just asking because this would be the ultimate fix to my issue.
Yes, though it's probably going to be at least a couple of months, unfortunately.
Ultimately, we need to generate custom InitializationSystems for each callback. Once we do this, it's easy to let you use observed values in callbacks; we just stuff the new value into the initialization system and use the nonlinear solve to restore consistency. At the moment, though, our main priority is improving our handling of modular discrete systems (e.g. clocked behavior) and then proper use of InitializationSystems to restore consistency with observables will be part of what's needed to make that work correctly.
Thanks for the explanation! That helps me a lot!
Please allow me one more question: Your explanation sounds to me as if you need the individual initialization systems if you want to write the observed variables in the callback. Would a generic read access be easier to implement as an intermediate step?
Here is why I ask: I got the impression that I am not alone with my Hardware-in-the-Loop (HIL) / Software-in-the-Loop (SIL) use case for ModelingToolkit. Time-dependent parameters offer an excellent solution for writing to actuators. What is missing is a simple, generic solution for reading sensor values, which after simplification are either in the unkown or the observed variables. Such sensor values only need to be passed on to the programmable logic controller (PLC) using shared memory or similar, but do not need to be able to be written back to the simulation. This is done indirectly via the time-dependent parameters after processing by the PLC.
P.S.: Would it be interesting for you guys if I prepared my example as a tutorial for MTK and prepared a corresponding PR?
Question❓
Hi everyone,
I am running into an issues using discrete events and irreducible variables in ModelingToolkit.jl. I made a post and Discourse and had brief Slack chat with @YingboMa. He asked me to ping @BenChung.
I hope the following example is sufficent as an MWE. It is a composite model of two tanks in sequence which are connected with valves. In the future, I want to set the valve position
S
from a soft-controller in a discrete event. For now, I just use a sine function. Furthermore, a level sensor should send back the level in the tankL
to the soft-controller, which is "simulated" byprintln()
within the Callback.Now the issue is, that
structural_simplify()
inmtkbuild()
does eliminateL
, if you do not apply a workarround. I studied multiple issues on this topic, e.g. #1646, #1797. They are still open but have been arround for quite a while already. They suggest to useirreducible = true
to avoid that the required variables are eliminated from the system.Now my problem: If I use the code above the volumes
V
and the levelsL
are set back to the initial each time the callback is called. I do not change anything about the variables... so I did not expect this behavior. Is this intentional? What am I doing wrong here?Furthermore: Have other solutions to this problem perhaps been worked out in the meantime?
irreducible
. I could hardcode this in the callback usinginteg.sol[integ.f.sys.tank1.L][end]
, but I am not sure what this does to performance of the simulation for a growing number of timesteps saved withinsol
. I have the impression that the whole time history is calculated each time I callinteg.sol
. Furthermore, I would like to construct more complex systems in future and am not sure yet, how to get the path to the specific tank in a generic form into the callback.Thank you for your help :-) !