First, I'm having a blast learning Julia. Thanks to all those who have
worked on it.
I'm an aerospace engineer who works on the design and analysis of planetary
entry vehicles. Our workhorse tools are flight mechanics/dynamics
simulations, which at their core just integrate the equations of motion of
the vehicles. We make extensive use of Monte Carlo for our analyses. We
have historically had a clear separation between the simulation model code
and the "input deck" (we still use the term, even though it is originally
from when my older colleagues were using decks of punch cards to run their
simulations). The input deck defines the case to be simulated: how many
vehicles, the aerodynamic properties of the vehicles, etc. This clear
distinction allows us to run a variety of cases with a single set of
simulation model code.
Our current simulations use C++ for the model code. The input deck is in
Python, and has access to the model code thanks to SWIG. It works pretty
nicely.
But C++ is daunting to my colleagues (and I grow weary of it myself). I
think Julia would be more approachable. It would also be nice to have the
input deck and model code be the same language.
So I've started experimenting with making a simple simulation in Julia.
I'm having some trouble figuring out the best way to implement some of the
features, and I was hoping that you might have some advice.
There are two things I'm struggling with. First, how could I implement our
"input deck" concept with Julia? The main issue I see is that I'd like to
have a function that performs a single run of the simulation with a
specified input deck, since that would so easily grow to a Monte Carlo
capability. But I can't use include("input_deck.jl") inside a function
body. Our input decks can be complex, and we often organize them into
multiple files, so I'd also like to be able to "include" those other files
from within the input deck. The only way I can think to do this right now
is to work in the global scope, and then have a second Julia program that I
can parallelize that would then start a new Julia process to run each case.
Second, the input deck specifies which variables are to be recorded during
the run. In C, it's easy to just keep a pointer to a variable and grab
it's value whenever the data recording code needs it. In Julia, it seems
like closures/anonymous functions are probably the best way to do this.
That is, in the input deck, the user would do:
# Somewhere earlier in the input deck, the user has done
some_vehicle = new_vehicle()
# Then they set up the data recording
data_record_file = new_data_record_file()
add_variable(data_record_file,()->some_vehicle.some_model.some_variable)
Which I could of course make more convenient with a macro. Is there a
better way? I was tinkering with using Expressions and automatically
building the functions (for speed), but that again limits me to working in
the global scope.
Thank you all for reading such a long post. I hope my explanation make
sense, but if not, I'd be happy to attempt to clarify. I really appreciate
the help!
Daniel