FUSE Introductory Tutorial

Download this tutorial from the FuseExamples repository


Import the necessary packages

using Plots # for plotting
using FUSE # this will also import IMAS in the current namespace

Starting from a use-case

FUSE comes with some predefined use-cases, some of which are used for regression testing. Note that some use cases are for non-nuclear experiments and certain Actors like Blankets or BalanceOfPlant will not perform any actions.

FUSE.test_cases
ARC            ini, act = FUSE.case_parameters(:ARC)
CAT            ini, act = FUSE.case_parameters(:CAT)
D3D            ini, act = FUSE.case_parameters(:D3D; scenario=:default)
D3D_Hmode      ini, act = FUSE.case_parameters(:D3D; use_scenario_sources=true, scenario=:H_mode)
D3D_Lmode      ini, act = FUSE.case_parameters(:D3D; use_scenario_sources=false, scenario=:L_mode)
DTT            ini, act = FUSE.case_parameters(:DTT)
EXCITE         ini, act = FUSE.case_parameters(:EXCITE)
FPP            ini, act = FUSE.case_parameters(:FPP)
ITER_ods       ini, act = FUSE.case_parameters(:ITER; init_from=:ods)
ITER_scalars   ini, act = FUSE.case_parameters(:ITER; init_from=:scalars)
JET_HDB5       ini, act = FUSE.case_parameters(:HDB5; case=500, tokamak=:JET)
KDEMO          ini, act = FUSE.case_parameters(:KDEMO)
MANTA          ini, act = FUSE.case_parameters(:MANTA)
SPARC          ini, act = FUSE.case_parameters(:SPARC)

Get initial parameters (ini) and actions (act) for a given use-case

ini, act = FUSE.case_parameters(:KDEMO);

Modifying ini parameters.

ini.equilibrium.B0 = 7.8
ini.equilibrium.R0 = 6.5;

Modifying act parameters.

act.ActorCoreTransport.model = :FluxMatcher;

Initialize the data dictionary (dd) using the 0D parameters.

NOTE: init() does not return a self-consistent solution, just a plausible starting point to initialize our simulations!

dd = FUSE.init(ini, act);
actors: Equilibrium
actors:  TEQUILA
actors: HCD
actors:  SimpleEC
actors:  SimpleIC
actors:  SimpleLH
actors:  SimpleNB
actors:  SimplePellet
actors: Current
actors:  SteadyStateCurrent
actors: CXbuild

Using checkpoints to save and restore states (we'll use this later)

chk = FUSE.Checkpoint()
@checkin chk :init dd ini act

Exploring the data dictionary

  • FUSE stores data following the IMAS data schema.
  • The root of the data structure is dd, which stands for "Data Dictionary".
  • More details are available in the documentation.

Display part of the equilibrium data in dd

dd.equilibrium.time_slice[2].boundary
boundary
├─ elongation ➡ 1.85224
├─ elongation_lowerFunction
├─ elongation_upperFunction
├─ geometric_axis
│  ├─ r ➡ 6.49979 [m]
│  └─ z ➡ -0.0310891 [m]
├─ minor_radius ➡ 2.00733 [m]
├─ outline
│  ├─ r249-element Vector{Float64} [m]
│  └─ z249-element Vector{Float64} [m]
├─ ovality ➡ 0.00757888
├─ squareness ➡ -0.018488
├─ squareness_lower_innerFunction
├─ squareness_lower_outerFunction
├─ squareness_upper_innerFunction
├─ squareness_upper_outerFunction
├─ strike_point
│  ├─ 1
│  │  ├─ r ➡ 5.62751 [m]
│  │  └─ z ➡ -4.69118 [m]
│  └─ 2
│     ├─ r ➡ 4.42185 [m]
│     └─ z ➡ -4.37596 [m]
├─ tilt ➡ -0.00805605
├─ triangularity ➡ 0.481243
├─ triangularity_lowerFunction
├─ triangularity_upperFunction
├─ twist ➡ -0.0101106
└─ x_point
   ├─ 1
   │  ├─ r ➡ 5.25721 [m]
   │  └─ z ➡ -3.77932 [m]
   └─ 2
      ├─ r ➡ 4.97495 [m]
      └─ z ➡ 4.07086 [m]

this can be done up to a certain depth with print_tree

print_tree(dd.equilibrium.time_slice[2].boundary; maxdepth=1)
boundary
├─ elongation ➡ 1.85224
├─ elongation_lower ➡ Function
├─ elongation_upper ➡ Function
├─ geometric_axis
│  ⋮
│
├─ minor_radius ➡ 2.00733 [m]
├─ outline
│  ⋮
│
├─ ovality ➡ 0.00757888
├─ squareness ➡ -0.018488
├─ squareness_lower_inner ➡ Function
├─ squareness_lower_outer ➡ Function
├─ squareness_upper_inner ➡ Function
├─ squareness_upper_outer ➡ Function
├─ strike_point
│  ⋮
│
├─ tilt ➡ -0.00805605
├─ triangularity ➡ 0.481243
├─ triangularity_lower ➡ Function
├─ triangularity_upper ➡ Function
├─ twist ➡ -0.0101106
└─ x_point
   ⋮

Plotting data from dd

FUSE provides Plots.jl recipes for visualizing data from dd, this means different plots are shown by calling the same plot() function on different items in the data structure. Learn more about Plots.jl here

For example plotting the equilibrium...

plot(dd.equilibrium)
Example block output

...or the core profiles

plot(dd.core_profiles)
Example block output

Whant to know what arguments can be passed? use help_plot() function

help_plot(dd.equilibrium; core_profiles_overlay=true, psi_levels_in=21, psi_levels_out=5, show_secondary_separatrix=true, coordinate=:psi_norm)
Example block output

These plots can be composed by calling plot!() instead of plot()

plot(dd.equilibrium; color=:gray, cx=true)
plot!(dd.build; equilibrium=false, pf_active=false)
plot!(dd.pf_active)
Example block output

Plotting an array...

plot(dd.core_profiles.profiles_1d[1].pressure_thermal)
Example block output

...is different from plotting a field from the IDS (which plots the quantity against its coordinate and with units)

plot(dd.core_profiles.profiles_1d[1], :pressure_thermal)
Example block output

Customizing plot attributes:

plot(dd.core_profiles.profiles_1d[1], :pressure_thermal; label="", linewidth=2, color=:red, labelfontsize=25)
Example block output

Working with time series

The IMAS data structure supports time-dependent data, and IMAS.jl provides ways to handle time data efficiently.

Each dd has a global_time attribute, and actors operate at such time

dd.global_time
0.0

Here we see that equilibrium has mulitiple time_slices

dd.equilibrium.time
2-element Vector{Float64}:
 -Inf
   0.0

Accessing time-dependent arrays of structures, via integer index

eqt = dd.equilibrium.time_slice[2]
eqt.time
0.0

At a given time, by passing the time as a floating point number (in seconds)

eqt = dd.equilibrium.time_slice[0.0]
eqt.time
0.0

At the global time, leaving the square brackets empty

eqt = dd.equilibrium.time_slice[]
eqt.time
0.0

Using the @ddtime macro to access and modify time-dependent arrays at dd.global_time:

dd.equilibrium.vacuum_toroidal_field.b0
2-element Vector{Float64}:
 7.800247146670339
 7.800247146670339

Accessing data at dd.global_time

my_b0 = @ddtime(dd.equilibrium.vacuum_toroidal_field.b0)
7.800247146670339

Writin data at dd.global_time

@ddtime(dd.equilibrium.vacuum_toroidal_field.b0 = my_b0 + 1)

dd.equilibrium.vacuum_toroidal_field.b0
2-element Vector{Float64}:
 7.800247146670339
 8.800247146670339

Expressions in dd

Some fields in the data dictionary are expressions (ie. Functions). For example dd.core_profiles.profiles_1d[].pressure is dynamically calculated as the product of thermal densities and temperature with addition of fast ions contributions

print_tree(dd.core_profiles.profiles_1d[1]; maxdepth=1)
1
├─ conductivity_parallel ➡ Function [ohm^-1.m^-1]
├─ electrons
│  ⋮
│
├─ grid
│  ⋮
│
├─ ion
│  ⋮
│
├─ j_bootstrap ➡ 101-element Vector{Float64} [A/m^2]
├─ j_non_inductive ➡ 101-element Vector{Float64} [A/m^2]
├─ j_ohmic ➡ 101-element Vector{Float64} [A/m^2]
├─ j_tor ➡ 101-element Vector{Float64} [A/m^2]
├─ j_total ➡ 101-element Vector{Float64} [A/m^2]
├─ pressure ➡ Function [Pa]
├─ pressure_ion_total ➡ Function [Pa]
├─ pressure_parallel ➡ Function [Pa]
├─ pressure_perpendicular ➡ Function [Pa]
├─ pressure_thermal ➡ Function [Pa]
├─ rotation_frequency_tor_sonic ➡ 101-element Vector{Float64} [s^-1] (all 0.0)
├─ t_i_average ➡ Function [eV]
├─ time ➡ 0 [s]
└─ zeff ➡ 101-element Vector{Float64} (all 2.0)

accessing a dynamic expression, automatically evaluates it (in the pressure example, we get an array with data)

dd.core_profiles.profiles_1d[1].electrons.pressure
101-element Vector{Float64}:
 509778.0126849895
 508015.5331093556
 506127.28780267714
 504028.00007398083
 501717.15032383427
 499200.12767841236
 496483.3555013101
 493573.28920922783
 490476.16916452086
 487197.9732256502
      ⋮
  46626.92127783749
  44144.01976857093
  40639.38635979532
  35110.15583254905
  26731.20893773121
  16181.017308016682
   7134.484709151893
   2115.9915462260783
    203.1251505568497

In addition to evaluating expressions by accessing them, expressions in the tree can be evaluated using IMAS.freeze()

print_tree(IMAS.freeze(dd.core_profiles.profiles_1d[1]); maxdepth=1)
profiles_1d
├─ conductivity_parallel ➡ 101-element Vector{Float64} [ohm^-1.m^-1]
├─ electrons
│  ⋮
│
├─ grid
│  ⋮
│
├─ ion
│  ⋮
│
├─ j_bootstrap ➡ 101-element Vector{Float64} [A/m^2]
├─ j_non_inductive ➡ 101-element Vector{Float64} [A/m^2]
├─ j_ohmic ➡ 101-element Vector{Float64} [A/m^2]
├─ j_tor ➡ 101-element Vector{Float64} [A/m^2]
├─ j_total ➡ 101-element Vector{Float64} [A/m^2]
├─ pressure ➡ 101-element Vector{Float64} [Pa]
├─ pressure_ion_total ➡ 101-element Vector{Float64} [Pa]
├─ pressure_parallel ➡ 101-element Vector{Float64} [Pa]
├─ pressure_perpendicular ➡ 101-element Vector{Float64} [Pa]
├─ pressure_thermal ➡ 101-element Vector{Float64} [Pa]
├─ rotation_frequency_tor_sonic ➡ 101-element Vector{Float64} [s^-1] (all 0.0)
├─ t_i_average ➡ 101-element Vector{Float64} [eV]
├─ time ➡ 0 [s]
└─ zeff ➡ 101-element Vector{Float64} (all 2.0)

Whole facility design

Here we restore the :init checkpoint that we had previously stored. Resetting any changes to dd, ini, and act that we did in the meantime.

@checkout chk :init dd ini act

Actors in FUSE can be executed by passing two arguments to them: dd and act. Internally, actors can call other actors, creating workflows. For example, the ActorWholeFacility can be used to to get a self-consistent stationary whole facility design. The actors: print statements with their nested output tell us what actors are calling other actors.

FUSE.ActorWholeFacility(dd, act);
actors: WholeFacility
actors:  PFdesign
actors:  StationaryPlasma
actors:   --------------- 1/5
actors:   HCD
actors:    SimpleEC
actors:    SimpleIC
actors:    SimpleLH
actors:    SimpleNB
actors:    SimplePellet
actors:   Current
actors:    QED
actors:   Pedestal
actors:    EPED
actors:   CoreTransport
actors:    FluxMatcher
actors:     FluxCalculator
actors:      TGLF
actors:      Neoclassical
actors:   Current
actors:    QED
actors:   Equilibrium
actors:    TEQUILA
actors:   --------------- 1/5 @ 627.00%
actors:   HCD
actors:    SimpleEC
actors:    SimpleIC
actors:    SimpleLH
actors:    SimpleNB
actors:    SimplePellet
actors:   Current
actors:    QED
actors:   Pedestal
actors:    EPED
actors:   CoreTransport
actors:    FluxMatcher
actors:   Current
actors:    QED
actors:   Equilibrium
actors:    TEQUILA
actors:   --------------- 2/5 @ 437.71%
actors:   HCD
actors:    SimpleEC
actors:    SimpleIC
actors:    SimpleLH
actors:    SimpleNB
actors:    SimplePellet
actors:   Current
actors:    QED
actors:   Pedestal
actors:    EPED
actors:   CoreTransport
actors:    FluxMatcher
actors:   Current
actors:    QED
actors:   Equilibrium
actors:    TEQUILA
actors:   --------------- 3/5 @ 137.90%
actors:   HCD
actors:    SimpleEC
actors:    SimpleIC
actors:    SimpleLH
actors:    SimpleNB
actors:    SimplePellet
actors:   Current
actors:    QED
actors:   Pedestal
actors:    EPED
actors:   CoreTransport
actors:    FluxMatcher
actors:   Current
actors:    QED
actors:   Equilibrium
actors:    TEQUILA
actors:   --------------- 4/5 @ 68.83%
actors:  StabilityLimits
actors:  HFSsizing
actors:   FluxSwing
actors:   Stresses
actors:  LFSsizing
actors:  CXbuild
actors:  PFdesign
actors:  PassiveStructures
actors:  VerticalStability
actors:  Neutronics
actors:  Blanket
actors:   CXbuild
actors:  Divertors
actors:  BalanceOfPlant
actors:   ThermalPlant
actors:   PowerNeeds
actors:  Costing
actors:   CostingARIES

Like before we can checkpoint results for later use

@checkin chk :awf dd ini act

Running a custom workflow

Let's now run a series of actors similar to what ActorWholeFacility does and play around with plotting to get a sense of what each individual actor does.

Let's start again from after the initialization stage

@checkout chk :init dd ini act

Let's start by positioning the PF coils, so that we stand a chance to reproduce the desired plasma shape. This will be important to ensure the stability of the ActorStationaryPlasma that we are going to run next.

actor = FUSE.ActorPFdesign(dd, act);
actors: PFdesign

The ActorStationaryPlasma iterates between plasma transport, pedestal, equilibrium and sources to return a self-consistent plasma solution

peq = plot(dd.equilibrium; label="before")
pcp = plot(dd.core_profiles; color=:gray, label="before")
FUSE.ActorStationaryPlasma(dd, act);
actors: StationaryPlasma
actors:  --------------- 1/5
actors:  HCD
actors:   SimpleEC
actors:   SimpleIC
actors:   SimpleLH
actors:   SimpleNB
actors:   SimplePellet
actors:  Current
actors:   QED
actors:  Pedestal
actors:   EPED
actors:  CoreTransport
actors:   FluxMatcher
actors:    FluxCalculator
actors:     TGLF
actors:     Neoclassical
actors:  Current
actors:   QED
actors:  Equilibrium
actors:   TEQUILA
actors:  --------------- 1/5 @ 627.00%
actors:  HCD
actors:   SimpleEC
actors:   SimpleIC
actors:   SimpleLH
actors:   SimpleNB
actors:   SimplePellet
actors:  Current
actors:   QED
actors:  Pedestal
actors:   EPED
actors:  CoreTransport
actors:   FluxMatcher
actors:  Current
actors:   QED
actors:  Equilibrium
actors:   TEQUILA
actors:  --------------- 2/5 @ 437.71%
actors:  HCD
actors:   SimpleEC
actors:   SimpleIC
actors:   SimpleLH
actors:   SimpleNB
actors:   SimplePellet
actors:  Current
actors:   QED
actors:  Pedestal
actors:   EPED
actors:  CoreTransport
actors:   FluxMatcher
actors:  Current
actors:   QED
actors:  Equilibrium
actors:   TEQUILA
actors:  --------------- 3/5 @ 137.90%
actors:  HCD
actors:   SimpleEC
actors:   SimpleIC
actors:   SimpleLH
actors:   SimpleNB
actors:   SimplePellet
actors:  Current
actors:   QED
actors:  Pedestal
actors:   EPED
actors:  CoreTransport
actors:   FluxMatcher
actors:  Current
actors:   QED
actors:  Equilibrium
actors:   TEQUILA
actors:  --------------- 4/5 @ 68.83%

we can compare equilibrium before and after the self-consistency loop

plot!(peq, dd.equilibrium; label="after")
Example block output

we can compare core_profiles before and after the self-consistency loop

plot!(pcp, dd.core_profiles; label="after")
Example block output

here are the sources

plot(dd.core_sources)
Example block output

and the flux-matched transport

plot(dd.core_transport)
Example block output

HFS sizing actor changes the thickness of the OH and TF layers on the high field side to satisfy current and stresses constraints

plot(dd.build)
FUSE.ActorHFSsizing(dd, act);
plot!(dd.build; cx=false)
Example block output

The stresses on the center stack are stored in the solid_mechanics IDS

plot(dd.solid_mechanics.center_stack.stress)
Example block output

LFS sizing actors change location of the outer TF leg to meet ripple requirements

plot(dd.build)
FUSE.ActorLFSsizing(dd, act);
plot!(dd.build; cx=false)
Example block output

A custom show() method is defined to print the summary of dd.build.layer

dd.build.layer
23×10 DataFrame
 Row │ group   details                            type      ΔR        R_start   R_end     material      area        volume     shape
     │ String  String                             String    Float64   Float64   Float64   String        Float64     Float64    String
─────┼─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
   1 │ in                                                   2.26642    0.0       2.26642  steel          24.4421     138.231
   2 │ in                                         oh        0.251826   2.26642   2.51825  nb3sn           7.36386     95.8389
   3 │ hfs                                        tf        0.293323   2.51825   2.81157  nb3sn_kdemo    17.5432     309.912   convex hull
   4 │ hfs     gap tf vacuum vessel                         0.210263   2.81157   3.02183  vacuum          7.41625    309.892   double ellipse
   5 │ hfs     vacuum vessel  outer               wall      0.030508   3.02183   3.05234  steel           1.05298     44.0194  negative offset
   6 │ hfs     vacuum                             vessel    0.201812   3.05234   3.25416  water           6.81818    285.164   negative offset
   7 │ hfs     vacuum vessel  inner               wall      0.030508   3.25416   3.28466  steel           1.00843     42.1972  negative offset
   8 │ hfs     gap high temp shield vacuum vess…            0.105131   3.28466   3.38979  vacuum         10.0824     511.381   negative offset
   9 │ hfs     high temp                          shield    0.315394   3.38979   3.70519  steel           9.45729    384.143   negative offset
  10 │ hfs                                        blanket   0.505853   3.70519   4.21104  lithium_lead   24.5246    1070.26    negative offset
  11 │ hfs     first                              wall      0.030508   4.21104   4.24155  tungsten        0.711739    27.4879  offset
  12 │ lhfs                                       plasma    4.53863    4.24155   8.78018  plasma         32.8009    1292.7
  13 │ lfs     first                              wall      0.030508   8.78018   8.81068  tungsten        0.711455    27.4729  offset
  14 │ lfs                                        blanket   1.16754    8.81068   9.97823  lithium_lead   24.5249    1070.28    negative offset
  15 │ lfs     high temp                          shield    0.315394   9.97823  10.2936   steel           9.45729    384.143   negative offset
  16 │ lfs     gap high temp shield vacuum vess…            0.579589  10.2936   10.8732   vacuum         10.0824     511.381   negative offset
  17 │ lfs     vacuum vessel  inner               wall      0.030508  10.8732   10.9037   steel           1.00843     42.1972  negative offset
  18 │ lfs     vacuum                             vessel    0.201812  10.9037   11.1055   water           6.81818    285.164   negative offset
  19 │ lfs     vacuum vessel  outer               wall      0.030508  11.1055   11.136    steel           1.05298     44.0194  negative offset
  20 │ lfs     gap tf vacuum vessel                         0.210263  11.136    11.3463   vacuum          7.41625    309.892   double ellipse
  21 │ lfs                                        tf        0.293323  11.3463   11.6396   nb3sn_kdemo    17.541      309.873   convex hull
  22 │ out                                                  2.16943   11.6396   13.8091   vacuum        124.041     6312.85
  23 │ out                                        cryostat  0.32353   13.8091   14.1326   steel          10.643      717.73    silo

ActorHFSsizing and ActorLFSsizing only change the layer's thicknesses, so we then need to trigger a build of the 2D cross-sections after them:

FUSE.ActorCXbuild(dd, act);
plot(dd.build)
Example block output

Generate passive structures information (for now the vacuum vessel)

FUSE.ActorPassiveStructures(dd, act)
plot(dd.pf_passive)
Example block output

We can now give the PF coils their final position given the new build

actor = FUSE.ActorPFdesign(dd, act);
plot(actor)
Example block output

With information about both pfactive and pfpassive we can now evaluate vertical stability

ActorVerticalStability(dd, act)
IMAS.freeze(dd.mhd_linear)

The ActorNeutronics calculates the heat flux on the first wall

FUSE.ActorNeutronics(dd, act);
p = plot(; layout=2, size=(900, 350))
plot!(p, dd.neutronics.time_slice[].wall_loading, subplot=1)
plot!(p, FUSE.define_neutrons(dd, 100000)[1], dd.equilibrium.time_slice[]; subplot=1, colorbar_entry=false)
plot!(p, dd.neutronics.time_slice[].wall_loading; cx=false, subplot=2, ylabel="")
Example block output

The ActorBlanket will change the thickess of the first wall, breeder, shield, and Li6 enrichment to achieve target TBR

FUSE.ActorBlanket(dd, act);
print_tree(IMAS.freeze(dd.blanket); maxdepth=5)
actors: Blanket
actors:  CXbuild
blanket
├─ module
│  └─ 1
│     ├─ layer
│     │  ├─ 1
│     │  │  ├─ material ➡ "tungsten"
│     │  │  ├─ midplane_thickness ➡ 0.02 [m]
│     │  │  └─ name ➡ "lfs first wall"
│     │  ├─ 2
│     │  │  ├─ material ➡ "lithium-lead: Li6/7=24.522"
│     │  │  ├─ midplane_thickness ➡ 1.16754 [m]
│     │  │  └─ name ➡ "lfs blanket"
│     │  └─ 3
│     │     ├─ material ➡ "steel"
│     │     ├─ midplane_thickness ➡ 0.558922 [m]
│     │     └─ name ➡ "lfs high temp shield"
│     ├─ name ➡ "blanket"
│     └─ time_slice
│        └─ 1
│           ├─ peak_escape_flux ➡ 680909 [W/m^2]
│           ├─ peak_wall_flux ➡ 1.98379e+06 [W/m^2]
│           ├─ power_incident_neutrons ➡ 2.01961e+08 [W]
│           ├─ power_incident_radiated ➡ 0 [W]
│           ├─ power_thermal_extracted ➡ 2.42353e+08 [W]
│           ├─ power_thermal_neutrons ➡ 2.42353e+08 [W]
│           ├─ power_thermal_radiated ➡ 0 [W]
│           ├─ time ➡ 0 [s]
│           └─ tritium_breeding_ratio ➡ 1.26465
├─ time ➡ [0] [s]
└─ tritium_breeding_ratio ➡ [1.19083]

The ActorDivertors actor calculates the divertors heat flux

FUSE.ActorDivertors(dd, act);
print_tree(IMAS.freeze(dd.divertors); maxdepth=4)
actors: Divertors
divertors
├─ divertor
│  └─ 1
│     ├─ power_conducted
│     │  ├─ data ➡ [1.19054e+08] [W]
│     │  └─ time ➡ [0] [s]
│     ├─ power_convected
│     │  ├─ data ➡ [0] [W]
│     │  └─ time ➡ [0] [s]
│     ├─ power_incident
│     │  ├─ data ➡ [4.30469e+07] [W]
│     │  └─ time ➡ [0] [s]
│     ├─ power_thermal_extracted
│     │  ├─ data ➡ [4.30469e+07] [W]
│     │  └─ time ➡ [0] [s]
│     └─ target
│        ├─ 1
│        │  ⋮
│        │
│        └─ 2
│           ⋮
│
└─ time ➡ [0] [s]

The ActorBalanceOfPlant calculates the optimal cooling flow rates for the heat sources (breeder, divertor, and wall) and get an efficiency for the electricity conversion cycle

actor = FUSE.ActorBalanceOfPlant(dd, act);
plot(actor)

ActorCosting will break down the capital and operational costs

FUSE.ActorCosting(dd, act)
plot(dd.costing)
Example block output

Let's checkpoint our results

@checkin chk :manual dd ini act

Saving and loading data

tutorial_temp_dir = tempdir()
filename = joinpath(tutorial_temp_dir, "$(ini.general.casename).json")
"/tmp/K-DEMO.json"

When saving data to be shared outside of FUSE, one can set freeze=true so that all expressions in the dd are evaluated and saved to file.

IMAS.imas2json(dd, filename; freeze=false, strict=false);

Load from JSON

dd1 = IMAS.json2imas(filename);

Comparing two IDSs

We can introduce a change in the dd1 and spot it with the diff function

dd1.equilibrium.time_slice[1].time = -100.0
IMAS.diff(dd.equilibrium, dd1.equilibrium)
Dict{String, String} with 1 entry:
  "time_slice[1].time" => "value:  -Inf --  -100.0"

Summary

Snapshot of dd in 0D quantities (evaluated at dd.global_time)

FUSE.extract(dd)
GEOMETRY                               EQUILIBRIUM                            TEMPERATURES                           
───────────────────────────────────    ───────────────────────────────────    ───────────────────────────────────    
R0 → 6.5 [m]                           B0 → 7.8 [T]                           Te0 → 20.4 [keV]                       
a → 2.01 [m]                           ip → 12 [MA]                           Ti0 → 19.5 [keV]                       
1/ϵ → 3.24                             q95 → 5.97                             <Te> → 9.32 [keV]                      
κ → 1.85                               <Bpol> → 0.802 [T]                     <Ti> → 8.27 [keV]                      
δ → 0.481                              βpol_MHD → 0.851                       Te0/<Te> → 2.18                        
ζ → -0.0185                            βtor_MHD → 0.00888                     Ti0/<Ti> → 2.36                        
Volume → 909 [m³]                      βn_MHD → 1.17                                                                 
Surface → 739 [m²]                                                                                                   
                                                                                                                     
DENSITIES                              PRESSURES                              TRANSPORT                              
───────────────────────────────────    ───────────────────────────────────    ───────────────────────────────────    
ne0 → 8.81e+19 [m⁻³]                   P0 → 0.621 [MPa]                       τe → 1.84 [s]                          
ne_ped → 6.4e+19 [m⁻³]                 <P> → 0.217 [MPa]                      τe_exp → 2.38 [s]                      
ne_line → 7.91e+19 [m⁻³]               P0/<P> → 2.86                          H98y2 → 0.879                          
<ne> → 7.25e+19 [m⁻³]                  βn → 1.17                              H98y2_exp → 0.952                      
ne0/<ne> → 1.21                        βn_th → 1.12                           Hds03 → 0.664                          
fGW → 0.835                                                                   Hds03_exp → 0.745                      
zeff_ped → 2                                                                  τα_thermalization → 0.896 [s]          
<zeff> → 2                                                                    τα_slowing_down → 1.16 [s]             
impurities → DT Ne20 He4                                                                                             
                                                                                                                     
SOURCES                                EXHAUST                                CURRENTS                               
───────────────────────────────────    ───────────────────────────────────    ───────────────────────────────────    
Pec → 50 [MW]                          Psol → 119 [MW]                        ip_bs_aux_ohm → 12 [MA]                
rho0_ec → 0.5 [MW]                     PLH → 63.6 [MW]                        ip_ni → 6.74 [MA]                      
PnbiNaN [MW]                        Bpol_omp → 1.15 [T]                    ip_bs → 3.13 [MA]                      
Enbi1NaN [MeV]                      λq → 0.949 [mm]                        ip_aux → 3.61 [MA]                     
Pic → 50 [MW]                          qpol → 2.34e+03 [MW/m²]                ip_ohm → 5.28 [MA]                     
PlhNaN [MW]                         qpar → 1.23e+04 [MW/m²]                ejima → 0.4                            
Paux_tot → 100 [MW]                    P/R0 → 18.3 [MW/m]                     flattop → 0.5 [Hours]                  
 → 53.6 [MW]                         PB/R0 → 143 [MW T/m]                                                          
Pohm → 0.0749 [MW]                     PBp/R0 → 14.7 [MW T/m]                                                        
Pheat → 154 [MW]                       PBϵ/R0q95 → 7.39 [MW T/m]                                                     
Prad_tot → -34.6 [MW]                  neutrons_peak → 0.36 [MW/m²]                                                  
                                                                                                                     
BOP                                    BUILD                                  COSTING                                
───────────────────────────────────    ───────────────────────────────────    ───────────────────────────────────    
Pfusion → 268 [MW]                     PF_material → nb3sn                    capital_cost → 4.49 [$B]               
Qfusion → 2.68                         TF_material → nb3sn_kdemo              levelized_CoE → Inf [$/kWh]            
thermal_cycle_type → rankine           OH_material → nb3sn                    TF_of_total → 4.6 [%]                  
thermal_efficiency_plant → 34 [%]      TF_max_b → 18.1 [T]                    BOP_of_total → 5.33 [%]                
thermal_efficiency_cycleNaN [%]     OH_max_b → 4.19 [T]                    blanket_of_total → 23.1 [%]            
power_electric_generated → 109 [MW]    TF_j_margin → 1.4                      cryostat_of_total → 7.27 [%]           
Pelectric_net → -36.1 [MW]             OH_j_margin → 8.52                                                            
Qplant → 0.751                         TF_stress_margin → 2.12                                                       
TBR → 1.19                             OH_stress_margin → 3.11                                                       
                                                                                                                     

Extract + plots saved to PDF (or printed to screen it filename is omitted)

filename = joinpath(tutorial_temp_dir, "$(ini.general.casename).pdf")
FUSE.digest(dd)#, filename)
GEOMETRY                               EQUILIBRIUM                            TEMPERATURES
───────────────────────────────────    ───────────────────────────────────    ───────────────────────────────────
R0 → 6.5 [m]                           B0 → 7.8 [T]                           Te0 → 20.4 [keV]
a → 2.01 [m]                           ip → 12 [MA]                           Ti0 → 19.5 [keV]
1/ϵ → 3.24                             q95 → 5.97                             <Te> → 9.32 [keV]
κ → 1.85                               <Bpol> → 0.802 [T]                     <Ti> → 8.27 [keV]
δ → 0.481                              βpol_MHD → 0.851                       Te0/<Te> → 2.18
ζ → -0.0185                            βtor_MHD → 0.00888                     Ti0/<Ti> → 2.36
Volume → 909 [m³]                      βn_MHD → 1.17
Surface → 739 [m²]

DENSITIES                              PRESSURES                              TRANSPORT
───────────────────────────────────    ───────────────────────────────────    ───────────────────────────────────
ne0 → 8.81e+19 [m⁻³]                   P0 → 0.621 [MPa]                       τe → 1.84 [s]
ne_ped → 6.4e+19 [m⁻³]                 <P> → 0.217 [MPa]                      τe_exp → 2.38 [s]
ne_line → 7.91e+19 [m⁻³]               P0/<P> → 2.86                          H98y2 → 0.879
<ne> → 7.25e+19 [m⁻³]                  βn → 1.17                              H98y2_exp → 0.952
ne0/<ne> → 1.21                        βn_th → 1.12                           Hds03 → 0.664
fGW → 0.835                                                                   Hds03_exp → 0.745
zeff_ped → 2                                                                  τα_thermalization → 0.896 [s]
<zeff> → 2                                                                    τα_slowing_down → 1.16 [s]
impurities → DT Ne20 He4

SOURCES                                EXHAUST                                CURRENTS
───────────────────────────────────    ───────────────────────────────────    ───────────────────────────────────
Pec → 50 [MW]                          Psol → 119 [MW]                        ip_bs_aux_ohm → 12 [MA]
rho0_ec → 0.5 [MW]                     PLH → 63.6 [MW]                        ip_ni → 6.74 [MA]
Pnbi → NaN [MW]                        Bpol_omp → 1.15 [T]                    ip_bs → 3.13 [MA]
Enbi1 → NaN [MeV]                      λq → 0.949 [mm]                        ip_aux → 3.61 [MA]
Pic → 50 [MW]                          qpol → 2.34e+03 [MW/m²]                ip_ohm → 5.28 [MA]
Plh → NaN [MW]                         qpar → 1.23e+04 [MW/m²]                ejima → 0.4
Paux_tot → 100 [MW]                    P/R0 → 18.3 [MW/m]                     flattop → 0.5 [Hours]
Pα → 53.6 [MW]                         PB/R0 → 143 [MW T/m]
Pohm → 0.0749 [MW]                     PBp/R0 → 14.7 [MW T/m]
Pheat → 154 [MW]                       PBϵ/R0q95 → 7.39 [MW T/m]
Prad_tot → -34.6 [MW]                  neutrons_peak → 0.36 [MW/m²]

BOP                                    BUILD                                  COSTING
───────────────────────────────────    ───────────────────────────────────    ───────────────────────────────────
Pfusion → 268 [MW]                     PF_material → nb3sn                    capital_cost → 4.49 [$B]
Qfusion → 2.68                         TF_material → nb3sn_kdemo              levelized_CoE → Inf [$/kWh]
thermal_cycle_type → rankine           OH_material → nb3sn                    TF_of_total → 4.6 [%]
thermal_efficiency_plant → 34 [%]      TF_max_b → 18.1 [T]                    BOP_of_total → 5.33 [%]
thermal_efficiency_cycle → NaN [%]     OH_max_b → 4.19 [T]                    blanket_of_total → 23.1 [%]
power_electric_generated → 109 [MW]    TF_j_margin → 1.4                      cryostat_of_total → 7.27 [%]
Pelectric_net → -36.1 [MW]             OH_j_margin → 8.52
Qplant → 0.751                         TF_stress_margin → 2.12
TBR → 1.19                             OH_stress_margin → 3.11

@ time = 0.0 [s]
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
GKS: could not find font middle.ttf
​
​
​