Skip to content

Python API

This notebook demonstrates how to set up a Jetto interpretive simulation and run it via duqtools.

The cell below sets up logging for the notebook.

import logging

logging.basicConfig(
    level=logging.INFO,
    format='%(message)s',
)

Below is an example duqtools config.

The example below takes t_e (electron temperature) from the template, and multiplies it by 1.1.

It also sets a few machine specific parameters (major_radius, b_field), and adjusts the start (t_start) and end time (t_end) for the simulation.

For more documentation on the parameters, check out the documentation here: https://duqtools.readthedocs.io/en/latest/config/create/

from duqtools.api import create

config = {
    'tag': 'data_01',
    'create': {
        'runs_dir':
        '/afs/eufus.eu/user/g/g2ssmee/jetto_runs/duqduq/data_123',
        'template':
        '/afs/eufus.eu/user/g/g2ssmee/jetto_runs/interpretive_esco02',
        'template_data': {
            'user': 'g2aho',
            'db': 'aug',
            'shot': 36982,
            'run': 2,
        },
        'operations': [
            {
                'variable': 't_e',
                'operator': 'multiply',
                'value': 1.1,
            },
            {
                'variable': 'major_radius',
                'operator': 'copyto',
                'value': 165.0,
            },
            {
                'variable': 'b_field',
                'operator': 'copyto',
                'value': -2.5725,
            },
            {
                'variable': 't_start',
                'operator': 'copyto',
                'value': 2.875,
            },
            {
                'variable': 't_end',
                'operator': 'copyto',
                'value': 2.885,
            },
        ],
    },
    'system': {
        'name': 'jetto',
    },
}
10:27:13 [WARNING] Python module 'omas' not found. Submodule 'jams' needs it @jams.py:14
Python module 'omas' not found. Submodule 'jams' needs it
10:27:13 [WARNING] Python module 'netCDF4' not found. Submodule 'transp' needs it @transp.py:25
Python module 'netCDF4' not found. Submodule 'transp' needs it

Running create will create a new run from the template, copy over the template data, and apply the operations to the data. This will return a dictionary with jobs and runs (Job and Run objects).

jobs_and_runs = create(config)
job, run = jobs_and_runs['run_0000']
Source data: g2aho/aug/36982/2
- Creating run : /afs/eufus.eu/user/g/g2ssmee/jetto_runs/duqduq/data_123/run_0000
- Copy ids from template to : /gss_efgw_work/work/g2ssmee/jetto/runs/duqduq/data_123/run_0000/imasdb/aug/36982/1
- Copying template to : /afs/eufus.eu/user/g/g2ssmee/jetto_runs/duqduq/data_123/run_0000
- Setting inital condition of : /gss_efgw_work/work/g2ssmee/jetto/runs/duqduq/data_123/run_0000/imasdb/aug/36982/1
Apply operator='multiply' scale_to_error=False clip_min=None clip_max=None linear_ramp=None input_variables=None custom_code=None variable=IDSVariableModel(ids='core_profiles', path='profiles_1d/*/electrons/temperature', type='IDS-variable', name='t_e', dims=['time', '$rho_tor_norm']) value=1.1
Writing data entry: /gss_efgw_work/work/g2ssmee/jetto/runs/duqduq/data_123/run_0000/imasdb/aug/36982/1
- Writing new batchfile : run_0000
- Updating imas locations of : /afs/eufus.eu/user/g/g2ssmee/jetto_runs/duqduq/data_123/run_0000
- Writing runs : /afs/eufus.eu/g2itmuse/user/g2ssmee/duqtools/notebooks/runs.yaml
- Writing csv

run contains some metadata about the run and the locations to the input and output data for the run.

run.model_dump()
{'dirname': PosixPath('/afs/eufus.eu/user/g/g2ssmee/jetto_runs/duqduq/data_123/run_0000'),
 'shortname': PosixPath('run_0000'),
 'data_in': {'relative_location': None,
  'user': '/gss_efgw_work/work/g2ssmee/jetto/runs/duqduq/data_123/run_0000/imasdb',
  'db': 'aug',
  'shot': 36982,
  'run': 1},
 'data_out': {'relative_location': None,
  'user': '/gss_efgw_work/work/g2ssmee/jetto/runs/duqduq/data_123/run_0000/imasdb',
  'db': 'aug',
  'shot': 36982,
  'run': 2},
 'operations': [{'operator': 'multiply',
   'scale_to_error': False,
   'clip_min': None,
   'clip_max': None,
   'linear_ramp': None,
   'input_variables': None,
   'custom_code': None,
   'variable': {'ids': 'core_profiles',
    'path': 'profiles_1d/*/electrons/temperature',
    'type': 'IDS-variable',
    'name': 't_e',
    'dims': ['time', '$rho_tor_norm']},
   'value': 1.1},
  {'operator': 'copyto',
   'scale_to_error': False,
   'clip_min': None,
   'clip_max': None,
   'linear_ramp': None,
   'input_variables': None,
   'custom_code': None,
   'variable': {'type': 'jetto-variable',
    'name': 'major_radius',
    'lookup': {'doc': 'Reference major radius (R0)',
     'name': 'major_radius',
     'type': 'float',
     'dimension': None,
     'keys': [{'file': 'jetto.jset',
       'field': 'EquilEscoRefPanel.refMajorRadius'},
      {'file': 'jetto.in', 'field': 'RMJ', 'section': 'NLIST1'}]}},
   'value': 165.0},
  {'operator': 'copyto',
   'scale_to_error': False,
   'clip_min': None,
   'clip_max': None,
   'linear_ramp': None,
   'input_variables': None,
   'custom_code': None,
   'variable': {'type': 'jetto-variable',
    'name': 'b_field',
    'lookup': {'doc': 'B-field (B0)',
     'name': 'b_field',
     'type': 'float',
     'dimension': None,
     'keys': [{'file': 'jetto.jset',
       'field': 'EquilEscoRefPanel.BField.ConstValue'}]}},
   'value': -2.5725},
  {'operator': 'copyto',
   'scale_to_error': False,
   'clip_min': None,
   'clip_max': None,
   'linear_ramp': None,
   'input_variables': None,
   'custom_code': None,
   'variable': {'type': 'jetto-variable', 'name': 't_start', 'lookup': None},
   'value': 2.875},
  {'operator': 'copyto',
   'scale_to_error': False,
   'clip_min': None,
   'clip_max': None,
   'linear_ramp': None,
   'input_variables': None,
   'custom_code': None,
   'variable': {'type': 'jetto-variable', 'name': 't_end', 'lookup': None},
   'value': 2.885}]}

job contains information about the status of the job and the locations of the input and output files for the simulation.

print(job.in_file)
print(job.in_file.exists())
print(job.out_file)
print(job.out_file.exists())
print(job.status())
/gss_efgw_work/work/g2ssmee/jetto/runs/duqduq/data_123/run_0000/jetto.in
True
/gss_efgw_work/work/g2ssmee/jetto/runs/duqduq/data_123/run_0000/jetto.out
False
JobStatus.NOSTATUS

The job can be submitted using the configured submit system.

job.submit()
submitting script via slurm ['sbatch', '/gss_efgw_work/work/g2ssmee/jetto/runs/duqduq/data_123/run_0000/.llcmd']
submission returned: b'Submitted batch job 299958\n'

Track the status of the job through job.status().

import time

print(job.status())

t0 = time.time()

while not job.is_done:
    t1 = time.time() - t0
    print(f'{t1:10.2f} - {job.status()}')
    time.sleep(1)

print(job.status())
JobStatus.NOSTATUS
      0.00 - no status
      1.00 - no status
      2.00 - no status
      3.01 - no status
      4.01 - no status
      5.01 - no status
      6.01 - no status
      7.01 - no status
      8.02 - no status
      9.02 - running
     10.03 - running
     11.03 - running
     12.03 - running
     13.03 - running
     14.03 - running
     15.03 - running
     16.03 - running
     17.04 - running
     18.04 - running
     19.04 - running
     20.04 - running
     21.04 - running
     22.04 - running
     23.04 - running
     24.04 - running
     25.05 - running
     26.05 - running
     27.05 - running
     28.05 - running
     29.05 - running
     30.05 - running
JobStatus.COMPLETED

Check that the run has created some data.

print(run.data_out.exists())
True

Load the data into an xarray.Dataset and do things with it.

ds_out = run.data_out.get_variables(('time', 'rho_tor_norm', 't_e'))

ds_out.isel(time=[
    0,
]).plot.scatter('rho_tor_norm', 't_e', marker='.');
/gss_efgw_work/work/g2fjc/jintrac-pythontools-3.10/lib/python3.10/site-packages/xarray/core/concat.py:500: FutureWarning: unique with argument that is not not a Series, Index, ExtensionArray, or np.ndarray is deprecated and will raise in a future version.
  common_dims = tuple(pd.unique([d for v in vars for d in v.dims]))

No description has been provided for this image