Thank you @ChrisRackauckas for all the help!
Hi @ChrisRackauckas,
I have one more doubt. Sometimes, I need to add a new sampling interval just after the callback function. Otherwise, the changes I made inside the callback will be seen by the solver only in the next step, leading to wrong results. Is it possible?
Can you show an example?
Hum, not a simple one, let’s try to explain better:
(MTR is an actuator)
The callback is something like this:
If t in tstops_mtr
Turn off MTR
elseif t in tstops_ctr
Turn on MTR
end
I need to simulate a PWM turning off and on the MTR. The problem is that when the MTR is turned off, the solver will only “see” this in the dynamics in next update step, which happens very close to the instant in which it will be turned on. Conclusion: if I limit the maximum step of the simulation to a very small number, then the solution matches that of Simulink. Otherwise, it does not.
Unfortunately, I cannot show the entire code yet. But it will be solved if I am capable to add a new solver step just after I turn off the MTR.
So the problem is that you have a discontinuous change, and so after turn off the MTR you need to restrict the solver to only step to the next tstops_ctr
? If
tstops = union(tstops_mtr,tstops_ctr)
Then that’s what it should be doing. An I am not sure how you’d get around this: you have to hit every discontinuity directly.
Just to see if I’m getting this correctly, what the solver should be doing is:
- As big of a step as possible until the next
tstops_mtr
. - As big of a step as possible until the next
tstops_ctr
. - Repeat 1.
Is it overshooting and causing a problem?
Yes, this is right. The problem is that the solver is doing that:
- Solve for instant k (in
tstops_mtr
); - Call the callback function that disable MTR;
- Go the the next step that is close to
tstops_ctr
.
In this case, the dynamics is not updated with the MTRs off. I think it should work if the callback was called before the update step, but I am not sure.
It is not actually an overshoot, the behavior is not very well defined because it also depends on the magnetic field. I just can assure that the answer is not correct. For example, I am trying to let the MTR turned on 70% of the time. The answer should be very close to that of a MTR 100% on but with 70% of torque capability.
I still don’t think I am completely understanding what you mean. Could you try to explain another way?
One thing I did notice (that I will comment about in your issue) is that you probably want to save just before applying the discontinuity. It should be like:
- Save
- Discontinuous change
- Save
so that way the solution interpolates correctly on both sides, but I think that might be a separate issue (and will only show up with dense plotting and/or dense=true
(which is a default)).
Hi @ChrisRackauckas!
I am almost finishing the simulation. After I changed everything to events, everything seems to be working fine. Can you tell me if I can use as many event I want? Should I do something additional or just add many @ode_event
as you described?
EDIT: There is a bug, I think, when you set two events. I opened a bug here: https://github.com/JuliaDiffEq/OrdinaryDiffEq.jl/issues/16
Hi,
I recently encounter similar probably as well. This discussion had been tremendously helpful. However, there is one I don’t quite get. Why do we dispatch getfield
via ::Type{Val{:continous_field1}}
instead of just simply Val{:contnous_field1}
? Is there a benefit to this approach?