Skip to content

Duqtools demo: single UQ run

This notebook shows how to use duqtools to do validation for a single run.

It will go over the steps required to do uncertainty quantification from a template data set.

We define 2 directories:

  • duqtools directory, this is where the duqtools and UQ config resides. This is also the directory we work in with duqtools.
  • run directory, this is a directory where slurm has access and where all the simulation files and data are stored.
from pathlib import Path
import os

duqtools_dir = Path('/afs/eufus.eu/user/g/g2ssmee/duqtools_demo')
run_dir = Path('/afs/eufus.eu/user/g/g2ssmee/jetto_runs/duqtools_demo')

assert not duqtools_dir.exists()
duqtools_dir.mkdir()

os.chdir(duqtools_dir)

duqtools help

The main interface for duqtools is via the CLI. You can run duqtools --help to give a list of available subcommands.

!duqtools --help
Usage: duqtools [OPTIONS] COMMAND [ARGS]...

  For more information, check out the documentation:

  https://duqtools.readthedocs.io

Options:
  --help  Show this message and exit.

Commands:
  clean           Delete generated IDS data and the run dir.
  create          Create the UQ run files.
  dash            Open dashboard for evaluating IDS data.
  go              Run create, submit, status, dash in succession.
  init            Create a default config file.
  list-variables  List available variables.
  merge           Merge data sets with error propagation.
  plot            Plot some IDS data.
  recreate        Read `runs.yaml` and re-create the given runs.
  setup           Template substitution for duqtools config.
  status          Print the status of the UQ runs.
  submit          Submit the UQ runs.
  version         Print the version and exit.
  yolo            Live on the edge, run `duqtools go --force --yes --quiet`.

Each of the subcommands has its own help section.

!duqtools create --help
Usage: duqtools create [OPTIONS]

  Create the UQ run files.

Options:
  --force  Overwrite existing run directories and IDS data.
  --help   Show this message and exit.

Common options:
  --yes               Answer yes to questions automatically.
  --dry-run           Execute without any side-effects.
  -q, --quiet         Don't output anything to the screen (except mandatory
                      prompts).
  -c, --config TEXT   Path to config.
  --debug             Enable debug print statements.
  -l, --logfile TEXT  where to send the logfile, the special values
                      stderr/stdout will send it there respectively.

duqtools init

This is a tool to give you a generic duqtools config file that can be used as a starting point.

!duqtools init --yes
Refusing to overwrite existing CONFIG, duqtools.yaml, use --force if you really want to

duqtools init will write duqtools.yaml which can be edited with your favourite text editor.

Check out the documentation for an overview of what can be configured.

!gedit duqtools.yaml

Setup create step

Update data in duqtools.yaml:

create:
  runs_dir: /afs/eufus.eu/user/g/g2ssmee/jetto_runs/duqtools_demo
  template: /afs/eufus.eu/user/g/g2ssmee/jetto_runs/interpretive_esco02
  template_data:
    user: g2aho
    db: jet
    shot: 90350
    run: 2
  sampler:
    method: latin-hypercube
    n_samples: 3
  dimensions:
    - variable: zeff
      operator: multiply
      values: [0.8, 0.9, 1.0, 1.1, 1.2]
    - variable: t_e
      operator: multiply
      values: [0.8, 0.9, 1.0, 1.1, 1.2]

Prepare a new UQ run using duqtools create

The duqtools config (duqtools.yaml) together with the template run and template data can be used as a starting point to create a new UQ run. The example above will sample 3 runs from a matrix of 25 as the basis for the UQ.

Running duqtools create will create 3 new runs and modify the data according to the specification above.

!duqtools create --yes
15:16:53 [WARNING] Python module 'omas' not found. Submodule 'jams' needs it @jams.py:14
15:16:53 [WARNING] Python module 'netCDF4' not found. Submodule 'transp' needs it @transp.py:25

Operations in the Queue:
========================
- Creating run : /gss_efgw_work/work/g2ssmee/jetto/runs/duqtools_demo/run_0000
- Creating run : /gss_efgw_work/work/g2ssmee/jetto/runs/duqtools_demo/run_0001
- Creating run : /gss_efgw_work/work/g2ssmee/jetto/runs/duqtools_demo/run_0002
Applying Operations
21

  0%|                                                    | 0/21 [00:00<?, ?it/s]
Creating run : /gss_efgw_work/work/g2ssmee/jetto/runs/duqtools_demo/run_0000: 
Progress:  10%|███▏                              | 2/21 [00:04<00:44,  2.33s/it]
Progress:  14%|████▊                             | 3/21 [00:04<00:26,  1.46s/it]
Progress:  19%|██████▍                           | 4/21 [00:05<00:19,  1.13s/it]
Creating run : /gss_efgw_work/work/g2ssmee/jetto/runs/duqtools_demo/run_0001: 
Progress:  38%|████████████▉                     | 8/21 [00:10<00:16,  1.28s/it]
Progress:  43%|██████████████▌                   | 9/21 [00:10<00:12,  1.02s/it]
Progress:  48%|███████████████▋                 | 10/21 [00:10<00:09,  1.20it/s]
Creating run : /gss_efgw_work/work/g2ssmee/jetto/runs/duqtools_demo/run_0002: 
Progress:  67%|██████████████████████           | 14/21 [00:11<00:03,  1.84it/s]
Progress:  71%|███████████████████████▌         | 15/21 [00:12<00:02,  2.15it/s]
Progress:  76%|█████████████████████████▏       | 16/21 [00:12<00:02,  2.23it/s]
Creating run : /gss_efgw_work/work/g2ssmee/jetto/runs/duqtools_demo/run_0002: 
Progress: 100%|█████████████████████████████████| 21/21 [00:12<00:00,  1.66it/s]

Submit to slurm using duqtools submit

Use duqtools submit to submit the jobs to slurm. This tool will find all jobs (.llcmd files in the subdirectories) and submit them to slurm.

Use the --array option to submit the jobs as a slurm array.

!duqtools submit --array --yes
15:17:10 [WARNING] Python module 'omas' not found. Submodule 'jams' needs it @jams.py:14
15:17:10 [WARNING] Python module 'netCDF4' not found. Submodule 'transp' needs it @transp.py:25

Operations in the Queue:
========================
- Adding to array : Job('/gss_efgw_work/work/g2ssmee/jetto/runs/duqtools_demo/run_0000')
- Adding to array : Job('/gss_efgw_work/work/g2ssmee/jetto/runs/duqtools_demo/run_0001')
- Adding to array : Job('/gss_efgw_work/work/g2ssmee/jetto/runs/duqtools_demo/run_0002')
- Submit single array job : duqtools_slurm_array.sh
Applying Operations
4

  0%|                                                     | 0/4 [00:00<?, ?it/s]
Submit single array job : duqtools_slurm_array.sh:                                      
Progress: 100%|███████████████████████████████████| 4/4 [00:00<00:00, 50.03it/s]

duqtools status

Query the status using duqtools status. This essentially parses all the jetto.status files in the run directory.

!squeue -u g2ssmee
!duqtools status
             JOBID PARTITION     NAME     USER ST       TIME  NODES NODELIST(REASON)
          216865_0        gw duqtools  g2ssmee  R       0:04      1 r054c05s04
          216865_1        gw duqtools  g2ssmee  R       0:04      1 r054c05s04
          216865_2        gw duqtools  g2ssmee  R       0:04      1 r182c14s04
15:17:16 [WARNING] Python module 'omas' not found. Submodule 'jams' needs it @jams.py:14
15:17:16 [WARNING] Python module 'netCDF4' not found. Submodule 'transp' needs it @transp.py:25
Total number of directories with submit script     : 3
Total number of directories with unsubmitted jobs  : 3
Total number of directories with status script     : 0
Total number of directories with completed status  : 0
Total number of directories with failed status     : 0
Total number of directories with running status    : 0
Total number of directories with unknown status    : 0

Overview of run directory

Duqtools writes the data in the directory specified by run_dir in duqtools.yaml.

  • duqtools.yaml is a copy of the duqtools config
  • logs contains the logs from the slurm array
  • runs.yaml contains the metadata for each of the runs so that they can be reproduced
  • run_000{1..3} are the jetto run directories. There are 3 directories corresponding to n_samples: 3 in the duqtools config.
os.chdir(run_dir)
!tree -L 1
.
├── duqtools.yaml
├── logs
├── run_0000
├── run_0001
├── run_0002
└── runs.yaml

4 directories, 2 files

A jetto run directory.

os.chdir(run_dir / 'run_0000')
!tree -L 1
.
├── configs
├── data
├── duqtools.submit.lock
├── envs
├── fort.12
├── fort.13
├── fort.21
├── fort.260 -> jetto.nbip
├── fort.261 -> jetto.nbip1
├── fort.262 -> jetto.nbip2
├── fort.263 -> jetto.nbip3
├── fort.272 -> jetto.tip
├── fort.273 -> jetto.ni1p
├── fort.274 -> jetto.ni2p
├── fort.275 -> jetto.gasp
├── fort.278 -> jetto.eqt
├── fort.280 -> jetto.sadas
├── fort.29 -> jetto.restart
├── fort.300 -> jetto.ext
├── fort.364 -> jetto.beamionsource
├── fort.40 -> jetto.chksum
├── fort.400 -> pion.0
├── fort.401 -> pion.1
├── fort.402 -> pion.2
├── fort.406 -> pion.6
├── fort.407 -> pion.7
├── fort.419 -> pion.19
├── fort.420 -> pion.20
├── fort.45 -> jetto.mhddb
├── fort.451 -> pion.51
├── fort.452 -> pion.52
├── fort.453 -> pion.53
├── fort.454 -> pion.54
├── fort.455 -> pion.55
├── fort.456 -> pion.56
├── fort.470 -> pion.70
├── fort.471 -> pion.71
├── fort.472 -> pion.72
├── fort.48 -> configs/eigen
├── fort.491 -> configs/jht
├── fort.492 -> jetto.jht
├── fort.493 -> configs/jhp
├── fort.494 -> jetto.jhp
├── fort.60 -> jetto.history
├── fort.604 -> gray_central_ray_coord
├── fort.608 -> gray_beam_CS
├── fort.612 -> gray_beam_transv
├── fort.72 -> jetto.ec
├── fort.73 -> flistprm
├── fort.74 -> ntm.print
├── fort.75 -> ntm.out
├── fort.76 -> ntm.greout
├── fort.77 -> jetto.in
├── fort.78 -> jetto.sgrid
├── fort.79 -> jetto.str
├── fort.8 -> jetto.restart
├── fort.80 -> jetto.sin
├── fort.81 -> jetto.srestart
├── fort.82 -> jetto.srestart
├── fort.84 -> jetto.shistory
├── fort.87 -> jetto.shistory
├── fort.88 -> jetto.sout
├── fort.9 -> jetto.bnd
├── fort.95 -> jetto.eqfile
├── fort.96 -> jetto.stat
├── fort.97 -> jetto.eqdsk_out
├── fort.98 -> jetto.eqrestart
├── fort.99 -> jetto.cbank
├── global_configuration
├── hcd_batch
├── hcd_gui
├── hcd_gui.py
├── hcd_nogui
├── helena_bin -> /gss_efgw_work/work/g2fjc/cmg/jams/v220922/depot/helena/bin
├── imasdb
├── interface
├── ionatom -> /gss_efgw_work/work/g2fjc/jintrac/v220922/data/ionatom
├── jetto.catid
├── jetto.chksum
├── jetto.datadir
├── jetto.eqdsk_out
├── jetto.eqrestart
├── jetto.ex
├── jetto.grill -> configs/lhcd6/jetto.grill
├── jetto.in
├── jetto.jse
├── jetto.jset
├── jetto.jsp
├── jetto.jss
├── jetto.jst
├── jetto.out
├── jetto.ray -> configs/lhcd6/jetto.ray
├── jetto.restart
├── jetto.sadas
├── jetto.sgrid
├── jetto.shistory
├── jetto.sin
├── jetto.sout
├── jetto.srestart
├── jetto.ssp
├── jetto.ssp1
├── jetto.ssp2
├── jetto.sst
├── jetto.sst1
├── jetto.sst2
├── jetto.status
├── jintrac_imas_config.cfg
├── jintrac_prov
├── labels.yaml
├── linrad -> /gss_efgw_work/work/g2fjc/jintrac/v220922/data/linrad
├── lookup.json
├── mishka_bin -> /gss_efgw_work/work/g2fjc/cmg/jams/v220922/depot/mishka/bin/mishka
├── python.err
├── QLKNN-data -> /gss_efgw_work/work/g2fjc/jintrac/v220922/jetto/tci/transport/QLKNN/data
├── rjettov
├── serialisation.json
├── _template
├── tools
├── utils_jetto
└── workflow

14 directories, 106 files

The data are stored in the local imasdb (support for JINTRAC v220922+).

!tree imasdb
imasdb
└── jet
    └── 3
        ├── 0
        │   ├── ids_903500001.characteristics
        │   ├── ids_903500001.datafile
        │   ├── ids_903500001.tree
        │   ├── ids_903500002.characteristics
        │   ├── ids_903500002.datafile
        │   └── ids_903500002.tree
        ├── 1
        ├── 2
        ├── 3
        ├── 4
        ├── 5
        ├── 6
        ├── 7
        ├── 8
        └── 9

12 directories, 6 files

Data visualization with duqtools plot

Duqtools contains a tool to create plots for your data from the command line.

os.chdir(duqtools_dir)

!duqtools plot -i data.csv -v t_i_ave -v t_e -v zeff
You can now view your plot in your browser:

  rho_tor_norm vs. t_i_ave:

    file:////afs/eufus.eu/g2itmuse/user/g2ssmee/duqtools_demo/chart_rho_tor_norm-t_i_ave.html

You can now view your plot in your browser:

  rho_tor_norm vs. t_e:

    file:////afs/eufus.eu/g2itmuse/user/g2ssmee/duqtools_demo/chart_rho_tor_norm-t_e.html

You can now view your plot in your browser:

  rho_tor_norm vs. zeff:

    file:////afs/eufus.eu/g2itmuse/user/g2ssmee/duqtools_demo/chart_rho_tor_norm-zeff.html


Data exploration with duqtools dash

This is a tool for data exploration and visualization.

Use this data.csv:
/afs/eufus.eu/user/g/g2ssmee/jetto_runs/workspace_demo/data.csv

!duqtools dash

  You can now view your Streamlit app in your browser.

  Local URL: http://localhost:8501
  Network URL: http://130.186.25.53:8501

^C
  Stopping...

Canonical UQ with duqtools setup

Duqtools setup is a tool that can help with canonical UQ.

It takes a templated called duqtools.template.yaml which contains the canonical settings. duqtools setup uses this file to generate a duqtools.yaml file, which is compatible with duqtools create (see steps above).

You can specify the input imas data on the command line. Duqtools will fill some machine specific from the IDS directly. The rules are specified in variables_ids2jetto.yaml. See the documentation for more information about variable specification.

import os

os.chdir('/afs/eufus.eu/user/g/g2ssmee/duqtools_template')

Below is what the template looks like.

The template uses jinja2 as a templating language.

Accolades ({..}) denote placeholders that will be replaced by the templating jinja2. Three objects are currently available (run to denote the run name, handle to reference the imas data, and variables to reference variables from the IDS data. See the documentation for more information about these placeholders.

The template supports functions to modify the placeholders or do some simple logic. The example below does some rounding of the variables using the round() function. The end time is calculated by taking the start time and adding 0.01 s.

%cat duqtools.template.yaml
tag: {{ run.name }}
create:
  runs_dir: /afs/eufus.eu/user/g/g2ssmee/jetto_runs/{{ run.name }}
  template: /afs/eufus.eu/user/g/g2ssmee/jetto_runs/interpretive_esco02
  template_data:
    user: {{ handle.user }}
    db: {{ handle.db }}
    shot: {{ handle.shot }}
    run: {{ handle.run }}
  operations:
    - variable: major_radius
      operator: copyto
      {# Convert units from IDS (m) to Jetto.jset (cm) -#}
      value: {{ (variables.major_radius * 100) | round(4) }}
    - variable: b_field
      operator: copyto
      value: {{ variables.b_field | round(4) }}
    - variable: t_start
      operator: copyto
      value: {{ variables.t_start | round(4) }}
    - variable: t_end
      operator: copyto
      value: {{ (variables.t_start + 0.01) | round(4) }}
  sampler:
    method: latin-hypercube
    n_samples: 25
  dimensions:
    - variable: zeff
      operator: multiply
      values: [0.8, 0.9, 1.0, 1.1, 1.2]
    - variable: t_e
      operator: multiply
      values: [0.8, 0.9, 1.0, 1.1, 1.2]
system:
  name: jetto-v220922

Using duqtools setup replaces the handle attributes with the imas location given on the CLI, and the run.name with the name of the run.

!duqtools setup --handle g2aho/jet/90350/2 --run_name my_run --yes

Operations in the Queue:
========================
- Setup run : my_run
Applying Operations
1


  0%|                                                     | 0/1 [00:00<?, ?it/s]

Progress:   0%|                                           | 0/1 [00:00<?, ?it/s]

Setup run : my_run: 
Setup run : my_run: 

Progress: 100%|██████████████████████████████████| 1/1 [00:00<00:00, 415.03it/s]

Below is what the resulting duqtools.yaml looks like. It can be modified or directly used as input for duqtools create.

%cat my_run/duqtools.yaml
tag: my_run
create:
  runs_dir: /afs/eufus.eu/user/g/g2ssmee/jetto_runs/my_run
  template: /afs/eufus.eu/user/g/g2ssmee/jetto_runs/interpretive_esco02
  template_data:
    user: g2aho
    db: jet
    shot: 90350
    run: 2
  sampler:
    method: latin-hypercube
    n_samples: 25
  dimensions:
    - variable: zeff
      operator: multiply
      values: [0.8, 0.9, 1.0, 1.1, 1.2]
    - variable: t_e
      operator: multiply
      values: [0.8, 0.9, 1.0, 1.1, 1.2]
    - variable: major_radius
      operator: copyto
      values: [ 296.0 ]
    - variable: b_field
      operator: copyto
      values: [ 2.1155 ]
    - variable: t_start
      operator: copyto
      values: [ 45.75 ]
    - variable: t_end
      operator: copyto
      values: [ 45.76 ]
system:
  name: jetto-v220922