Hi everyone — I’m new to Julia. I’ve known about the language for years but only recently started using it seriously.
I’m prototyping a space systems modeling tool — something that propagates orbits and performs optimization/estimation over complex physical models. Performance matters a lot here, and traditionally, systems like this have been written in Fortran, C, or C++ for that reason.
The core of the system involves evaluating flat physics models. But the interface is structured around structs to represent things like spacecraft, force models, etc. Most of these structs need to model change over time. For example, position, velocity, and mass may change during propagation or optimization.
So here’s the design tension:
Mutable structs are idiomatic in Julia, but I’m building a system that fundamentally models change. If I use immutable structs, I need to create new objects on every update, which breaks references used elsewhere to manage system state — and that gets messy fast. On the other hand, the actual mutation events (e.g., updating the struct after propagation) happen far less frequently than the inner calls to the ODE/physics models. So I suspect the cost of mutating the structs is negligible compared to the rest of the computation.
Right now, I’m using mutable structs and exposing the data using something like ComponentArrays (I rolled my own for now, but plan to migrate). This gives me a clean way to extract state into flat vectors for solvers, then write results back after each iteration or propagation.
So here’s my question:
What are the best practices in Julia for building complex, time-evolving systems like this?
Are there established design patterns or approaches for managing change cleanly in struct-based systems? Is mutability the right answer here, or is there a more Julian way I’m missing?
This seems like a well-trodden problem space, but I haven’t found a clear, idiomatic answer yet. I’d love to hear how others have tackled this — especially in simulation, modeling, or control system applications.
Thanks for any help or insights here!
Some simple sample structs, most of the fields change during propagation, optimization, or estimation.
mutable struct Spacecraft <: AbstractPoint
_state::AbstractState
_time::AbstractTime
_mass::AbstractMassModel
_tanks::AstractPropulsionModel
… this makes the point
end
mutable struct CelestialBody <: AbstractPoint
_name::String # i.e. Earth, Venus
_mu::Float64 # Gravitational parameter (km^3/s^2)
_equatorial_radius::Float64 # Equatorial radius (km)
_flattening::Float64 # Flattening (unitless)
end