An example would be ModelingToolkitNeuralNets.jl where NeuralNetworkBlock wraps a function call.
What you need to do it to create a System with a pos ~ solar_position(observer, ...) equation (or whatever relations would define the system) and then you would define the parameters of your system as the non-numeric constants that your function needs.
Currently using the struct symbolically might be a bit tricky, but if you have just have 3 separate variables, then the last code block would just work since azimuth and elevation would just be @variables in the system and you would have some equations for them.
Got exception outside of a @test
MethodError: no method matching seconds_to_datetime(::Symbolics.Num, ::SymbolicUtils.BasicSymbolic{DateTime})
The function `seconds_to_datetime` exists, but no method is defined for this combination of argument types.
using SolarPosition: Observer, SolarAlgorithm, RefractionAlgorithm, PSA, NoRefraction
using ModelingToolkit: @parameters, @variables, System, @register_symbolic, t_nounits
using Symbolics
using Symbolics: term
using Dates: DateTime, Millisecond
import SolarPosition: SolarPositionBlock, solar_position
seconds_to_datetime(t_sec, t0::DateTime) = t0 + Millisecond(round(Int, t_sec * 1e3))
@register_symbolic seconds_to_datetime(t_sec, t0::DateTime)
@register_symbolic solar_position(
observer::Observer,
time::DateTime,
algorithm::SolarAlgorithm,
refraction::RefractionAlgorithm,
)
function SolarPositionBlock(; name)
@parameters t0::DateTime [tunable = false] observer::Observer [tunable = false]
@parameters algorithm::SolarAlgorithm = PSA() [tunable = false]
@parameters refraction::RefractionAlgorithm = NoRefraction() [tunable = false]
@variables pos(t_nounits) [output = true]
time_expr = term(seconds_to_datetime, t_nounits, t0; type = DateTime)
eqs = [pos ~ solar_position(observer, time_expr, algorithm, refraction)]
return System(eqs, t_nounits; name = name)
end
Now @named sun = SolarPositionBlock() works and gives:
Model sun:
Equations (1):
1 standard: see equations(sun)
Unknowns (1): see unknowns(sun)
pos(t)
Parameters (4): see parameters(sun)
observer
algorithm [defaults to PSA(2020)]
t0
refraction [defaults to NoRefraction()]Variables: SymbolicUtils.BasicSymbolic[]
I don’t see how to get to azimuth and elevation from here.
After struggling a little bit more this seems to work beautifully now. Some critical feedback to the efficiency of this method would be greatly appreciated.