Tutorial

Solving a Nonlinear ODE Problem with NLodeProblem in Julia

In this tutorial, we will go through the process of setting up, solving, querying, and plotting a nonlinear ordinary differential equation (ODE) problem using the NLodeProblem function. We will use a buck converter circuit model as an example.

Step 1: Define the ODE Problem

The first step is to define the ODE problem using the NLodeProblem function. We provide the function with user code that specifies the parameters, variables, and differential equations. Here is the example code for a buck converter circuit model with detailed explanations:

odeprob = NLodeProblem(quote
    name = (buck,) # Define the name of the problem for identification
    
    # Parameters
    C = 1e-4          # Capacitance in farads
    L = 1e-4          # Inductance in henrys
    R = 10.0          # Resistance in ohms
    U = 24.0          # Input voltage in volts
    T = 1e-4          # Switching period in seconds
    DC = 0.5          # Duty cycle
    ROn = 1e-5        # On-state resistance of the switch in ohms
    ROff = 1e5        # Off-state resistance of the switch in ohms
    
    # Discrete and continuous variables
    discrete = [1e5, 1e-5, 1e-4, 0.0, 0.0] # Initial discrete states
    u = [0.0, 0.0]                        # Initial continuous states
    
    # Rename for convenience
    rd = discrete[1]       # Diode resistance
    rs = discrete[2]       # Switch resistance
    nextT = discrete[3]    # Next switching time
    lastT = discrete[4]    # Last switching time
    diodeon = discrete[5]  # Diode state (on/off)
    il = u[1]              # Inductor current
    uc = u[2]              # Capacitor voltage
    
    # Helper equations
    id = (il * rs - U) / (rd + rs)  # Diode current calculation
    
    # Differential equations
    du[1] = (-id * rd - uc) / L     # Derivative of inductor current
    du[2] = (il - uc / R) / C       # Derivative of capacitor voltage
    
    # Events
    if t - nextT > 0.0 
        lastT = nextT             # Update last switching time
        nextT = nextT + T         # Schedule next switching time
        rs = ROn                  # Set switch to on-state
    end
    
    if t - lastT - DC * T > 0.0 
        rs = ROff                 # Set switch to off-state
    end
    
    if diodeon * id + (1.0 - diodeon) * (id * rd - 0.6) > 0
        rd = ROn                  # Diode is on
        diodeon = 1.0
    else
        rd = ROff                 # Diode is off
        diodeon = 0.0
    end
end)

Explanation:

Parameters: These are constants used in the model. C, L, R, U, T, DC, ROn, ROff are physical constants related to the buck converter circuit.
Discrete and continuous variables: These represent the initial states of discrete and continuous variables in the model.
Renaming variables: For convenience, the elements of discrete and u are renamed to more descriptive variable names (rd, rs, nextT, lastT, diodeon, il, uc).
Helper equations: These are intermediate expressions needed for the differential equations. id is the current through the diode.
Differential equations: These represent the system's dynamics. du[1] is the rate of change of the inductor current. du[2] is the rate of change of the capacitor voltage.
Events: These are conditions that modify the continous and discrete variables. They handle the switching behavior of the buck converter and the diode's state transitions.

Step 2: Solve the ODE Problem

Next, we solve the ODE problem using the solve function. We need to specify the problem, the algorithm, and the simulation settings.

# Define the time span for the simulation
tspan = (0.0, 0.001)  # Start at 0 seconds, end at 0.001 seconds
# Solve the ODE problem with the chosen algorithm and settings
sol = solve(odeprob, nmliqss2(), tspan, abstol=1e-4, reltol=1e-3)

Explanation:

Time span: tspan defines the interval over which the solution is computed, from 0.0 to 0.001 seconds.
Solver function: solve is used to compute the solution.
odeprob is the ODE problem we defined.
nmliqss2() specifies the algorithm used to solve the problem (e.g., qss2,nmliqss1... might be other algorithms).
abstol and reltol are the absolute and relative tolerances for the solver, controlling the accuracy of the solution.

Step 3: Query the Solution

After solving the problem, we can query the solution to extract useful information such as variable values at specific times, the number of steps, events, and more.

# Get the value of variable 2 at time 0.0005
value_at_time = sol(2, 0.0005)

# Get the total number of steps to end the simulation
total_steps = sol.totalSteps

# Get the number of simultaneous steps during the simulation
simul_step_count = sol.simulStepCount

# Get the total number of events during the simulation
event_count = sol.evCount

# Get the saved times and variables
saved_times = sol.savedTimes
saved_vars = sol.savedVars

# Print the results
println("Value of variable 2 at time 0.0005: ", value_at_time)
println("Total number of steps: ", total_steps)
println("Number of simultaneous steps: ", simul_step_count)
println("Total number of events: ", event_count)

Explanation:

Value of variable 2 at a specific time: sol(2, 0.0005) returns the value of the second variable (capacitor voltage uc) at time 0.0005 seconds. Total steps: sol.totalSteps gives the total number of steps taken by the solver to reach the end of the simulation.
Simultaneous steps: sol.simulStepCount provides the number of steps where simultaneous updates occurred.
Total events: sol.evCount gives the total number of events (e.g., switch state changes) during the simulation.
Saved times and variables: sol.savedTimes and sol.savedVars store the time points and corresponding variable values computed during the simulation.

Step 4: Plot the Solution

Finally, we can plot the solution to visualize the results. We have two options: generate a plot object for further customization or save the plot directly to a file.

# Generate a plot object for all variables of the solution
plot_obj = plot_Sol(sol)
# Generate a plot object for variable 1 of the solution
plot_Sol(sol,1)
# Display the plot
display(plot_obj)


#plot  variables 1 and 2 of the solution
plot_Sol(sol,1,2,note=" ",xlims=(0.0,1.0),ylims=(-0.5,0.5),legend=false) 
#plot  the sum of variables 1 and 2 of the solution
plot_SolSum(sol,1,2)

# Save the plot to a file
save_Sol(sol, note=" ",xlims=(0.0,1.0),ylims=(-0.5,0.5),legend=false)

Explanation:

Generate plot object: plotSol(sol) creates a plot object from the solution data. Display the plot: display(plotobj) shows the plot in the current environment. Save the plot: save_Sol(sol, ...) saves the plot to a file *.png.

plot_buck_qss2

User Documentation

More about the user documentation can be found in:

Application Programming Interface

Available Algorithms