Differentiation of struct based simulations and applications

Hello,

I’m building an aerospace simulator and solver in Julia. It’s coming together well, and I plan to release the first public version in about a month. The system models spacecraft, maneuvers, events, and so on, and interfaces with solvers to optimize (and eventually estimate). It’s structured heavily around structs. Here are some sample toy structs (actual structs are quite a bit more complex, I am simplifying to focus on the question here)

using StaticArrays

A simple force model with gravitational parameter mu

struct ForceModel{T}
mu::T
end

Impulsive maneuver model with delta-v vector

struct ImpulsiveManeuver{T}
Δv::SVector{3,T}
end

Spacecraft includes mass and state vector

struct Spacecraft{T}
mass::T
state::SVector{6,T}
end

Construct an impulsive maneuver

moi = ImpulsiveManeuver(SVector(0.4, 0.5, 0.6))

There is an interface that allows users to define which fields on structs they want to treat as variables in the problem, and to flexibly define functions for constraints (and eventually measurements for estimation).

Define moi as a solver variable (left out the constructor for this for conciseness)

var_toi = SolverVariable(
obj = moi,
variable = DeltaV(),
)

Under the hood I use dispatch on the variable type (called DeltaV()), for getting and setting values. Here I only show the spec for treating the maneuver components as solver variables, but in general, fields on spacecraft, force model, and other structs can be variables.

The simulation code allows users to register events like a sequence of propagations and maneuvers (not shown here to avoid obfuscating) and functions to be satisfied via solvers. When a user defines a field to treat as a variable as shown above, and I use ForwardDiff for derivatives in the code, the fields change type from typically Float64 (which is how the user initializes with actual numbers) to a dual for differentiability.

Before working on too much implementation, I want to make sure I get the design right. I think I need to deepcopy these structs and change the types for fields being treated as variables to dual “under the hood” for differentiability.

Is there a better way to handle this? Am I on the right track? Are the existing packages I can lean on here?

Thanks in advance for any help!

use accessors.jl