Step 4: DAG Blocks (Reusable Computation)¶
In this step, you'll write reusable computation using dag blocks and
learn how to instantiate them with include.
Defining a DAG Block¶
A dag block defines a reusable sub-DAG with its own parameters and
nodes. It uses the same param / node / @ syntax you already know:
dim GravParam = Length^3 / Time^2;
dag orbital_velocity {
param gm: GravParam;
param r: Length;
node v: Velocity = sqrt(@gm / @r);
}
A dag block is a named template — it does not execute until you
include it.
Including a DAG Block¶
Use include to instantiate a DAG block. The argument list is mandatory
(it may be empty); outputs are projected via the .{ ... } brace list,
and the statement ends with ;:
const node gm_earth: GravParam = 3.986004418e5 km^3/s^2;
const node r_earth: Length = 6371.0 km;
param parking_alt: Length = 200.0 km;
include orbital_velocity(gm: @gm_earth, r: @r_earth + @parking_alt)
.{ v as v_parking };
- Named arguments:
gm: @gm_earthpasses@gm_earthto thegmparameter. Arguments are evaluated in the surrounding scope. - Output selection:
.{ v as v_parking }selects thevnode and renames it tov_parking. - The included nodes become regular nodes in your computation graph.
Multi-Output DAGs¶
A dag can expose multiple outputs:
dag hohmann_transfer {
param gm: GravParam;
param r1: Length;
param r2: Length;
node v1: Velocity = sqrt(@gm / @r1);
node v2: Velocity = sqrt(@gm / @r2);
node dv1: Velocity = sqrt(2.0 * @gm * @r2 / (@r1 * (@r1 + @r2))) - @v1;
node dv2: Velocity = @v2 - sqrt(2.0 * @gm * @r1 / (@r2 * (@r1 + @r2)));
node total_dv: Velocity = @dv1 + @dv2;
}
Pick the outputs you need at the include site:
param target_alt: Length = 35786.0 km;
include hohmann_transfer(
gm: @gm_earth,
r1: @r_earth + @parking_alt,
r2: @r_earth + @target_alt,
).{ total_dv as transfer_dv, dv1 as departure_dv };
Aliasing the Whole Include¶
If you'd rather group the outputs under a single prefix, alias the entire instantiation instead of using a brace list:
include orbital_velocity(gm: @gm_earth, r: @r_earth + @parking_alt) as parking;
node v_parking: Velocity = @parking.v;
Alias and brace list are mutually exclusive on a single include.
Using DAG Results in the Graph¶
Included outputs are regular graph nodes, referenced with @:
include orbital_velocity(gm: @gm_earth, r: @r_earth + @parking_alt)
.{ v as v_parking };
include hohmann_transfer(
gm: @gm_earth,
r1: @r_earth + @parking_alt,
r2: @r_earth + @target_alt,
).{ total_dv as transfer_dv };
node total: Velocity = @v_parking + @transfer_dv;
DAG Bodies Are Isolated¶
A dag body sees only its own declarations, its own imports, and the
outputs of its own includes. There is no lexical inheritance from the
enclosing file's top-level scope. To use a top-level const node (or
any other compile-time name) inside a dag, either pass it in as a
param at the include site (as in the examples above) or import it
explicitly inside the dag body. See
Multi-File Projects for the full rules.
What You Learned¶
dagblocks for defining reusable computation templatesincludeto instantiate a DAG block with named arguments- Output selection with
.{ name as alias }to pick and rename outputs - Whole-include aliasing with
asfor grouping outputs under a prefix - Multiple outputs from a single DAG block
- DAG blocks use the same
param/node/@syntax as top-level declarations and have strict scope isolation
Try It in Your Browser¶
This complete example defines and instantiates both DAG blocks. Edit an include argument or selected output and rerun it.
The editable playground requires JavaScript. Read the tutorial above or open the static example source.
Expected initial output includes the selected v_parking, transfer_dv, and departure_dv outputs plus total.
Next Step¶
In Step 5, you'll split your project
across multiple files with import declarations.