Skip to content

Exporting a model

A model runs in more places than magnet simulate:

  • inside a co-simulation master;
  • under a scheduler;
  • on a board under your own firmware.

Each of those is a runtime, meaning whatever calls the model’s step. One command exports a model for it:

Terminal window
magnet build --runtime fmi3 # an FMU a co-simulation master steps
magnet build --runtime fmi3 --interface scheduled-execution # an FMU whose clock a scheduler ticks
magnet build --runtime embassy # the glue an embassy firmware steps the model through

The editor has the same two FMU exports under File › Export › FMU.

The first of these that is set picks the model:

  1. --model, as a use path (controller::Controller);
  2. the manifest’s [deploy] model;
  3. the model magnet simulate runs, which is the package’s only one, or the one at the top that steps the others.

A generic model is a template and cannot be exported, so name an instantiation of it.

--runtime exports the release crate as files and takes neither --profile nor --format. [deploy] runtime is magnet flash’s key, and build does not read it.

Deliverables land in target/export/.

The model crate does not change. An export writes the same #![no_std] crate magnet build writes to target/codegen/release/<package>/. Beside it goes a glue crate, target/codegen/<runtime>/<package>/, which depends on:

  • the model crate;
  • one crate from crates.io: fmite for an FMU, embassy-time for a firmware;
  • the crates behind any extern blocks the model uses.

The glue is what a runtime needs and the model does not, written out in plain Rust you can read. For an FMU it is a struct whose fields are the variables and whose private field is the model. For a firmware it is a driver around the model.

Settings are the constructor’s arguments. What an FMU calls parameters and a host sets is what params takes and magnet simulate --param writes. They are not the fields of the parameters struct, which the constructor derives from them. A change to one takes effect from the next tick.

An argument whose type is a model is a child’s whole parameters. It is fixed at its default, and a model that gives it none cannot be exported.

Only the interface crosses. Settings, inputs and outputs are what a runtime sees. Probes are the simulation’s: the export is the release crate, which strips them with the rest of the sim profile.

The model only ever steps at the sample time it declares. A step with @every(10ms) runs at 10 ms. A model whose children are rated runs at the largest step all their rates are a whole number of. A host’s interval is cut into whole ticks of that step, and an interval that does not divide into them is refused, because a model is only verified at the sample times it declares.

A model with no rate anywhere takes a Co-Simulation master’s interval as its dt, exactly as magnet simulate --dt does. A Scheduled Execution FMU and an embassy loop need a period of the model’s own and refuse one without.

Next: an FMU, with the GNC controller exported and stepped, or a firmware, from the glue to a board on your desk.