Domain error in circuit DAE

I’m trying to solve the following DAE:

\begin{cases} i_R=C \displaystyle \frac{dV_o}{dt} \\ i_R= \displaystyle \frac{V_{in}(t)-V_o-nV_T \ln \displaystyle (1+\displaystyle \frac{i_R}{I_s}) }{R} \end{cases}

The solution obtained from a simulator is:

Nevertheless, we want to solve the model with DifferentialEquations.jl, and I’ve tried with the following code:

using DifferentialEquations, Plots

f = 10E3
ω = 2*π*f
n = 1
C = 0.01E-6
VT = 25E-3
IS = 1E-6
A = 1.0
R = 10E3

function func(out, du, u, p, t)
  V0, IR = u
  dV0, _ = du

  out[1] = C*dV0 - IR
  out[2] = (A*sin(ω*t) - V0 - n*VT*log(1+IR/IS)) - R*IR
end

B = A*ω/R/(1+n*VT/R/IS)

u₀  = [0, 0.0]   #  V0, IR
du₀ = [0, B]     # dV0, dIR

dvars = [true, false]
tspan = (0, 2E-3)
prob = DAEProblem(func, du₀, u₀, tspan, differential_vars=dvars);

It gives the following error:

sol = solve(prob)
DomainError with -0.33407903800223493:
log will only return a complex result if called with a complex argument. Try log(Complex(x)).

What do you suggest to tackle this problem?

The term 1+IR/IS used in log goes negative which will cause the error you see. This can be either because the model is not well formulated, wrongly coded, or because the DAE solver takes too large a time step. If it is the last option, you could try isoutofdomain or code the objective function such that the term does not go negative.

Maybe you also need to make sure that the ICs are good for the solver to get started.

@mauro3 Thank you for your answer!

I’m wondering if is it possible to use isoutofdomain within a DAEProblem?

IDA will throw a warning that it’s ignoring that keyword argument. Just reduce the solver tolerance and you should be fine.

1 Like

Thank you, @ChrisRackauckas! The log turns the DAE to be unstable, I guess. We are considering a workaround by slightly modifying the equation.

Hi again!

I’ve been trying a workaround to my original issue, by reordering some terms in my initial model (in short, now I have an exp function instead of a log):

using DifferentialEquations, Plots
using Sundials #IDA solver

f = 10E3
ω = 2*π*f
n = 1
C = 0.01E-6
VT = 25E-3
IS = 1E-6
A = 1.0
R = 10E3
Vin(t) = A*sin(ω*t)

function func(out, du, u, p, t)
  V0, IR = u
  dV0, _ = du

  out[1] = C*dV0 - IR
  aux = (R*IR - Vin(t) + V0)/(n*VT)
  out[2] = IS*(exp(-aux) - 1) - IR
end

B = A*ω/R/(1+n*VT/R/IS)

u₀  = [0, 0.0]   #  V0, IR
du₀ = [0, B]     # dV0, dIR

dvars = [true, false]

tspan = (0, 3.6E-3)
prob = DAEProblem(func, du₀, u₀, tspan, differential_vars=dvars);

The minimum reltol that worked is 1E-15 (maximum accuracy I can request). So next, I tried reducing the abstol parameter:

sol = solve(prob, reltol=1e-15, abstol=1e-17)
plot(sol, vars=(0, 1), xlab="t (s)", ylab="Vo (V)", lab="")

leading to the following plot that doesn’t match what I expected:

On the other hand, when reducing abstol further, the solution seems to be OK, but the time horizon is shorter (for abstol=1E-18, the time horizon I get is 1.5E-3 s).

Do you have any further suggestions that I can try?

Why not just write this as an equality and substitute? That would improve the numerical accuracy. I would suggest using ModelingToolkit.jl for this kind of thing. Its symbolic algorithms will do exactly these types of transformations.

1 Like

Thanks so much, @ChrisRackauckas!

I followed the pendulum example from the ModelingToolkit tutorial website and got the following:

Looks good to me! Let me know if you want to check the code. Now I’ll explore the ModelingToolkit tool to check if I can extract some of the transformations it does to the system to solve it with tools like ReachabilityAnalysis.

Thanks so much again!