ModelingToolkit, vars to varmap?

Hello,
Is there a function to get the index from variable names in ModelingToolkit.jl? Or a function that returns me a varmap (Vector{Pair{Num, Float64}})?
So the opposite of ModelingToolkit.varmap_to_vars()

I’m currently using:

function varname_to_varmapindex(varname)
    states_sys = states(sys)
    length_states = size(states_sys, 1)
    index = findfirst(i -> (states_sys[i].metadata)[Symbolics.VariableSource][2] == varname, 1:length_states)
    return isnothing(index) ? -1 : index  # Return -1 or another suitable value if not found
end

For example, in a callback I would like to call the variable by name and not by the index.

function affect!(integrator)
    index = varname_to_varmapindex(:varname)
    integrator.u[index] += 1.0
end

Or if I want the result at a specific timestep.

sol(timestep)[index]

You can index the solution object with symbols (and expressions) like so

sol(timestep, idxs = var) # Get the value at var at time timestep
sol(timestep, idxs = var^2 - 1) # Get the value of expression var^2 - 1

Otherwise you find the answer to your question here Frequently Asked Questions · ModelingToolkit.jl

and may also find

ModelingToolkit.defaults(sys)

useful.

1 Like

The integrator struct doesn’t have provide a way to access the system, so the only way I have figured out to do this is to create the affect (or condition) in a closure. You should modify your varname_to_varmapindex function to accept an argument for sys as well, creating sys as a global variable can lead to performance problems.

function create_increment_affect(sys, varname)
    let index = varname_to_varmapindex(sys, varname)
        function affect!(integrator)
            integrator.u[index] += 1.0
        end
    end
end
1 Like

Thanks! Both answers are my solution!

Another option, since you are already using ModelingToolkit, is to use the symbolic event handling interface. Most uses of callbacks can be fit into this framework, although you do need to occasionally mark a variable as irreducible (tell the simplification code not to elminiate this variable as a state).

1 Like

Do I understand correctly that the difference between Event Handling and Callback Functions is that an event is symbolically added to the ODE system and, after simplification, is executed as a callback?

“Event” and “Callback” is used almost interchangeably. An “event” is something that happens (condition triggers) that triggers an action, the callback function.

When you use the symbolically specified events in MTK, those are translated internally into callbacks, similar to how you would write the callbacks yourself.

1 Like