Diode model not working as expected with ModelingToolkit

I am trying to port Modelica.Electrical.Analog.Semiconductors.Diode. The code I came up with is:

using ModelingToolkit
using ModelingToolkitStandardLibrary.Blocks
using ModelingToolkitStandardLibrary.Electrical
using OrdinaryDiffEq
using IfElse: ifelse
using Plots

@parameters t;

exlin(x, max_x) = ifelse(x > max_x, exp(max_x)*(1 + x - max_x), exp(x))

function Diode(;name, Ids=1e-6, Vt=0.04, max_exp=15, R=1e8)
    @named oneport = OnePort()
    @unpack v, i = oneport
    pars = @parameters Ids=Ids Vt=Vt max_exp=max_exp R=R
    eqs = [i ~ Ids*(exlin(v/Vt, max_exp) - 1) + (v/R)]
    extend(ODESystem(eqs, t, [], pars; name=name), oneport)
end

@named V = Voltage();
@named D = Diode();
@named R = Resistor(R=100);
@named Gnd = Ground();

connections = [
    V.V.u ~ 18*sin(2*pi*50*t)
    connect(V.p, D.p)
    connect(D.n, R.p)
    connect(V.n, R.n, Gnd.g)
]

@named model = ODESystem(connections, t, systems=[V, D, R, Gnd]);

sys = structural_simplify(model);

prob1c = ODEProblem(sys, Pair[], (0/50, 1/50), saveat=1/50e2);
sol1c = solve(prob1c, Rodas4());
Plots.plot(sol1c; idxs=[V.v, R.v, D.v], fmt = :png)

prob2c = ODEProblem(sys, Pair[], (0/50, 2/50), saveat=1/50e2);
sol2c = solve(prob2c, Rodas4());
Plots.plot(sol2c; idxs=[V.v, R.v, D.v], fmt = :png)

prob3c = ODEProblem(sys, Pair[], (1/50, 2/50), saveat=1/50e2);
sol3c = solve(prob3c, Rodas4());
Plots.plot(sol3c; idxs=[V.v, R.v, D.v], fmt = :png)

image
image
image

This diode model works fine for any first cycle of the signal, blowing up exponentially for any further cycles.

Hello and welcome to the community!

It might be the solvers adaptive step length that takes too large steps and misses the event implied by the ifelse. By limiting dtmax, you get what I think you’re looking for:

prob2c = ODEProblem(sys, Pair[], (0/50, 2/50), saveat=1/50e2);
sol2c = solve(prob2c, Rodas4(), dtmax=1e-3);
Plots.plot(sol2c; idxs=[V.v, R.v, D.v], fmt = :png)

3 Likes

Thank you so much for such a warm welcome and prompt and valuable information.

Is there a list of compatible solvers somewhere, which I’m missing? Also, why the solver can not detect this step size?

1 Like

The solver you have chosen is compatible, the problem is that no solver can “see” the fact that there is a discontinuity in the dynamics, based on the information it has available (the past, the current point and it’s derivative) it’s safe to take large steps. Suddenly, this is no longer true, but the solver didn’t notice because it stepped too far over the problematic point to notice that there was a problematic point in the first place. When you limit the maximum step size, the solver cannot step far over the discontinuity and the error control notices that something has happened and reduces the step size to accurately handle the discontinuity.

For an analogy, imagine that you’re keeping track of the weather outside. If it’s sunny for several days in a row, you might relax your sample interval slightly and not look outside as often anymore, but then you run the risk of missing the fact that a small storm passes by.

2 Likes

And we should auto-add tstops based on symbolic information like ifelse, but we don’t right now.

1 Like