Closed ariel-phet closed 2 years ago
Wow, that looks awful and is easily reproducible in macOS 10.15.7/Chrome.
It reminds me a bit of the jagged graphs we saw in https://github.com/phetsims/circuit-construction-kit-common/issues/720
I experimented with reducing the MIN_DT and ERROR_THRESHOLD in TimestepSubdivisions.ts. However, reducing it lower and lower wrecked the performance before the curve smoothed out appreciably. This is an emergent behavior from our solver and I'm not sure how to investigate it next. @arouinfar or @ariel-phet can you brainstorm ideas where to look? Or workarounds we could explore? A smoothing step in the graph? Limiting the sliders to keep us out of troublesome areas?
I could also print out the equations and condition matrix at those trouble areas to help us try to understand what is wrong.
This case is not a problem for Java. I edited the Java to take the inductor below its default of 10, set up the same characteristics and it did OK. But it did print out "Time step too small" over and over:
This patch is smoother and seems to have qualitatively correct behavior for the battery-resistor-inductor circuit:
Still has a hitch every now and then but overall is smoother. Summary of the patch: sign changes and different way of computing voltage:
At today's design meeting, we saw that the jitter was only in the voltage across the inductor and not across any of the other components, or in any of the currents. @ariel-phet and I scheduled a meeting to take a closer look.
@ariel-phet and I identified this suspicious part:
const updatedCapacitors = this.dynamicCapacitors.map( capacitorAdapter => {
const newState = new DynamicElementState(
// TODO: This may have something to do with it? https://github.com/phetsims/circuit-construction-kit-common/issues/758
solution.getNodeVoltage( capacitorAdapter.capacitorVoltageNode1! ) - solution.getNodeVoltage( capacitorAdapter.capacitorVoltageNode0! ),
solution.getCurrent( capacitorAdapter )
);
return new DynamicCapacitor( capacitorAdapter.dynamicCircuitCapacitor, newState );
} );
const updatedInductors = this.dynamicInductors.map( inductorAdapter => {
const newState = new DynamicElementState(
// TODO: This may have something to do with it? https://github.com/phetsims/circuit-construction-kit-common/issues/758
solution.getNodeVoltage( inductorAdapter.dynamicCircuitInductor.nodeId1 ) - solution.getNodeVoltage( inductorAdapter.dynamicCircuitInductor.nodeId0 ),
solution.getCurrent( inductorAdapter )
);
return new DynamicInductor( inductorAdapter.dynamicCircuitInductor, newState );
} );
Note that the top part uses capacitorAdapter.capacitorVoltageNode1
but the bottom part uses inductorAdapter.dynamicCircuitInductor.nodeId1
. This is asymmetrical and may indicate a problem.
@ariel-phet and I noticed this other question, why is the sign negative at node 1 and positive at node 0?
// Each resistor with nonzero resistance has unknown voltages
nodeTerms.push( new Term( -sign / resistor.resistanceValue, new UnknownVoltage( resistor.nodeId1 ) ) );
nodeTerms.push( new Term( sign / resistor.resistanceValue, new UnknownVoltage( resistor.nodeId0 ) ) );
@ariel-phet and I noticed this asymmetrical code that ResistiveBatteryadapter is not put into the main list. Here is after our change:
DynamicCircuit line 161 or so.
const newBatteryList = [ ...this.resistiveBatteryAdapters, ...companionBatteries ];
const newResistorList = [ ...this.resistorAdapters, ...companionResistors ];
// const newCurrentList: MNACurrentSource[] = []; // Placeholder for if we add other circuit elements in the future
const mnaCircuit = new ModifiedNodalAnalysisCircuit( newBatteryList, newResistorList );
@ariel-phet recommends getting rid of current sources if they are currently unused. But maybe we should keep notes on how it is done, in case we need that for companion models for the future. @ariel-phet thinks it is unlikely we would add current sources to the toolbox.
There is something odd about the inductor model. We tried simulating it as a 10V battery, but it kept coming out as a 5V battery (but only for the first inductor). We also need to understand why https://github.com/phetsims/circuit-construction-kit-common/issues/762 is causing different physics. Then the problems seem isolated to the inductor, so we can take a closer look into it.
Patch of all working copy changes from collaboration with @ariel-phet:
The jitter is being caused by the variation in the dt parameters for the timestep. I discovered this by noticing that there is no jitter when pressing the "step" button. Here are some dt values when running the model in the first comment:
0.018
0.016
0.021
0.013
0.017
0.016
0.018
0.016
0.017
0.015
0.017
0.016
0.018
0.015
0.016
0.018
0.017
0.016
0.017
If I set it to be a steady 1/60 (60fps) then the jitter disappears. I observed that in Java, it is a very steady 0.03 seconds between frames.
I published a dev version here that uses a consistent dt of 1/60.0. That means on a slow computer, it won't keep pace with realtime. But we should evaluate and see if that is an acceptable tradeoff.
This also includes numerous critical internal fixes from https://github.com/phetsims/circuit-construction-kit-common/issues/764 which were not intended to have any change in observable behavior, but the changes were nontrivial and still need to be verified.
@ariel-phet can you please test? Please check the behavior for this issue, as well as one or more resonance test, and a few "wildcard" tests.
Today @ariel-phet and @arouinfar and I discussed this proposed solution, we think it is OK to run at 1/60 constant frame rate. The values in the sim will be internally consistent, even if they don't match up with wall clock time.
@samreid I have not seen any jitter in this kind of circuit in 1.0.0-dev.43 during testing.
Before closing the issue, we might want QA to check performance of a circuit like this on a Chromebook. Marking for design meeting so a test like this can be scheduled.
I can test on my son's school-issued chromebook, but I'll probably do so with capacitorResistance=1E-4 since we are considering that for https://github.com/phetsims/circuit-construction-kit-common/issues/769#issuecomment-961431451
Testing the resonant circuit in the top comment with dev.45 looks fine on the lenovo 300e chromebook. Despite the graininess of this video the motion seemed smooth and speedy.
Running with ?capacitorResistance=1E-4 seemed about the same. I compared sim time to wall time, and found that 3 cycles had passed in the current chart in 5 seconds of real time. I clocked the same circuit on my Macbook Air running 5 cycles in 5 seconds of realtime.
In https://github.com/phetsims/circuit-construction-kit-common/issues/758#issuecomment-953228045 we discussed that it is OK for the sim to be slower than realtime as long as it is internally consistent. But I thought it would be good to double check that it's OK to be as slow as a ratio of 3:5 on devices like this chromebook. But if we decide that is not ok, I'm not sure how to address it. @arouinfar can you please advise? Close if no more work is necessary for this issue.
@arouinfar and I discussed this today. Since it was smooth and speedy on the chromebook, and the time was internally consistent on the chromebook, this issue seems good to close. It is ok running at 3:5 time.
As discovered in https://github.com/phetsims/chipper/issues/946, there are TODOs in the code referring to this issue. Reopening.
I removed the TODO, closing.
Seen as part of testing in https://github.com/phetsims/circuit-construction-kit-common/issues/748
In the driven resonant circuit seen below, I was getting some nasty jitter in the voltage readout, but the current readout is clean.
Capacitance 0.10 F Inductance 0.253 H Resistance 40 Ohm AC source 100 V and 1 Hz
These values of capacitance and inductance were initially chosen to set up a natural frequency of 1 Hz. Adjusting the voltage does not improve the behavior much, nor does adjusting the driving frequency. Lowering the resistance does eventually clean up the voltage readout, but jitter can easily be seen as low as 10 Ohms in this circuit. Increasing the inductance to about 1.5 H also cleans up the behavior. But clearly there is currently a widely accessible range of values that produces poor behavior.