├── src ├── VERSION ├── print.c ├── hdf5io │ ├── hdf5_nbi.h │ ├── hdf5_wall.h │ ├── hdf5_plasma.h │ ├── hdf5_asigma.h │ ├── hdf5_neutral.h │ ├── hdf5_boozer.h │ ├── hdf5_orbit.h │ ├── hdf5_state.h │ ├── hdf5_mhd.h │ ├── hdf5_efield.h │ ├── hdf5_transcoef.h │ ├── hdf5_marker.h │ ├── hdf5_bfield.h │ ├── hdf5_options.h │ ├── hdf5_dist.h │ ├── hdf5_histogram.h │ ├── hdf5_helpers.h │ └── hdf5_transcoef.c ├── spline │ └── spline.h ├── bbnbi5.h ├── simulate │ ├── simulate_ml_adaptive.h │ ├── simulate_gc_fixed.h │ ├── simulate_fo_fixed.h │ ├── atomic.h │ ├── step │ │ ├── step_fo_vpa.h │ │ ├── step_gc_rk4.h │ │ ├── step_ml_cashkarp.h │ │ └── step_gc_cashkarp.h │ ├── mccc │ │ ├── mccc.c │ │ ├── mccc_wiener.h │ │ └── mccc.h │ └── simulate_gc_adaptive.h ├── biosaw.h ├── suzuki.h ├── libascot_mem.h ├── unit_tests │ ├── test_afsi.c │ ├── test_random.c │ ├── test_wall_2d.c │ ├── test_plasma_1DS.c │ ├── test_interp1Dcomp.c │ ├── test_N0_1D.c │ ├── test_linint3D.c │ ├── test_plasma.c │ └── test_bsearch.c ├── gitver.sh ├── boschhale.h ├── list.h ├── Efield │ ├── E_TC.h │ ├── E_1DS.h │ └── E_TC.c ├── ascot5_main.h ├── gctransform.h ├── print.h ├── libascot_mem.c ├── mpi_interface.h ├── wall │ └── wall_2d.h ├── neutral │ ├── N0_1D.h │ └── N0_3D.h ├── neutral.h ├── endcond.h ├── wall.h ├── E_field.h ├── octree.h ├── boozer.h ├── diag │ ├── dist_com.h │ ├── diag_transcoef.h │ ├── dist_rho5D.h │ ├── dist_6D.h │ └── dist_rho6D.h ├── afsi.h ├── hdf5_interface.h ├── consts.h ├── mhd │ ├── mhd_stat.h │ └── mhd_nonstat.h ├── plasma │ ├── plasma_1DS.h │ ├── plasma_1D.h │ └── plasma_1Dt.h ├── diag.h ├── Bfield │ ├── B_2DS.h │ ├── B_TC.h │ ├── B_3DS.h │ ├── B_STS.h │ └── B_GS.h ├── list.c ├── mhd.h ├── nbi.h ├── linint │ └── linint1D.c ├── rfof.h ├── asigma │ └── asigma_loc.h ├── biosaw.c └── plasma.h ├── a5py ├── m3_template │ ├── __init__.py │ ├── macro │ │ ├── __init__.py │ │ ├── test_macro.py │ │ └── tools.py │ ├── micro │ │ ├── __init__.py │ │ └── ascot.py │ ├── run.sh │ ├── set-env.sh │ ├── set-env_csh.sh │ ├── README.md │ ├── code_parameters │ │ └── input_physics.xml │ ├── workflow.ymmsl │ └── workflow_mpi.ymmsl ├── gui │ ├── __init__.py │ ├── icon.png │ ├── logo.png │ ├── contentinteractive.py │ └── guiparams.py ├── routines │ └── __init__.py ├── testascot │ ├── __init__.py │ └── tutorials.py ├── ascot5io │ ├── coreio │ │ └── __init__.py │ └── reaction.py ├── _nonfunctional │ ├── README.rst │ ├── write_to_imas.py │ ├── imas_container │ │ └── Containerfile │ ├── read_from_imas.py │ └── wrapper_test.py ├── exceptions.py ├── physlib │ ├── evaluate.py │ └── alias.py └── templates │ └── optiontemplates.py ├── doc ├── _static │ ├── logo.png │ └── custom.css ├── Makefile ├── papi │ ├── a5py.templates.rst │ ├── a5py.ascotpy.rst │ ├── a5py.physlib.rst │ ├── a5py.testascot.rst │ ├── a5py.ascot5io.asigma.rst │ ├── a5py.ascot5io.boozer.rst │ ├── a5py.ascot5io.neutral.rst │ ├── a5py.gui.rst │ ├── a5py.ascot5io.options.rst │ ├── a5py.routines.rst │ ├── a5py.ascot5io.nbi.rst │ ├── a5py.ascot5io.wall.rst │ ├── a5py.ascot5io.plasma.rst │ ├── a5py.ascot5io.mhd.rst │ ├── a5py.ascot5io.coreio.rst │ ├── a5py.ascot5io.marker.rst │ ├── a5py.ascot5io.bfield.rst │ ├── a5py.ascot5io.efield.rst │ ├── a5py.rst │ └── a5py.ascot5io.rst ├── gallery.rst ├── make.bat ├── testing.rst ├── tutorials.rst └── acknowledging.rst ├── setup.py ├── MANIFEST.in ├── bin ├── a5gui ├── a5update └── a5editoptions ├── environment-rfof.yaml ├── environment.yaml ├── .gitignore ├── environment-mpi.yaml ├── .github └── workflows │ ├── build-test-light.yaml │ ├── publish-docs.yaml │ ├── build-image.yaml │ ├── build-test.yaml │ ├── build.yaml │ ├── rebase-on-main.yaml │ ├── docs.yaml │ └── tests.yaml ├── Makefile ├── Dockerfile ├── environment-dev.yaml ├── environment-osx.yaml ├── .setcdllascot2py.py ├── pyproject.toml └── README.rst /src/VERSION: -------------------------------------------------------------------------------- 1 | 5.6.2 2 | -------------------------------------------------------------------------------- /a5py/m3_template/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /a5py/m3_template/macro/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /a5py/m3_template/micro/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /doc/_static/logo.png: -------------------------------------------------------------------------------- 1 | ../../a5py/gui/logo.png -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | from setuptools import setup 2 | 3 | setup() 4 | -------------------------------------------------------------------------------- /MANIFEST.in: -------------------------------------------------------------------------------- 1 | include a5py/gui/logo.png 2 | include a5py/gui/icon.png -------------------------------------------------------------------------------- /a5py/gui/__init__.py: -------------------------------------------------------------------------------- 1 | """Graphical user interface for ASCOT5. 2 | """ 3 | -------------------------------------------------------------------------------- /a5py/routines/__init__.py: -------------------------------------------------------------------------------- 1 | """Advanced pre- and postprocessing routines. 2 | """ 3 | -------------------------------------------------------------------------------- /a5py/gui/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ascot4fusion/ascot5/HEAD/a5py/gui/icon.png -------------------------------------------------------------------------------- /a5py/gui/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ascot4fusion/ascot5/HEAD/a5py/gui/logo.png -------------------------------------------------------------------------------- /a5py/testascot/__init__.py: -------------------------------------------------------------------------------- 1 | """Unit tests, physics tests and regressions runs. 2 | """ 3 | -------------------------------------------------------------------------------- /doc/Makefile: -------------------------------------------------------------------------------- 1 | doc: 2 | sphinx-build -b html . ../build/doc 3 | 4 | clean: 5 | rm -rf ../build/doc 6 | -------------------------------------------------------------------------------- /a5py/ascot5io/coreio/__init__.py: -------------------------------------------------------------------------------- 1 | """Low level API for HDF5 data access and building the treeview. 2 | """ 3 | -------------------------------------------------------------------------------- /a5py/m3_template/run.sh: -------------------------------------------------------------------------------- 1 | 2 | rm -rf ./run_ascot* 3 | 4 | muscle_manager --start-all --log-level DEBUG workflow.ymmsl -------------------------------------------------------------------------------- /a5py/_nonfunctional/README.rst: -------------------------------------------------------------------------------- 1 | Non-production code that could be useful but which has not been merged to a5py framework. 2 | -------------------------------------------------------------------------------- /doc/papi/a5py.templates.rst: -------------------------------------------------------------------------------- 1 | ============= 2 | ``templates`` 3 | ============= 4 | 5 | .. automodule:: a5py.templates 6 | :members: 7 | -------------------------------------------------------------------------------- /doc/papi/a5py.ascotpy.rst: -------------------------------------------------------------------------------- 1 | ================= 2 | ``ascotpy`` 3 | ================= 4 | 5 | .. automodule:: a5py.ascotpy 6 | :members: 7 | -------------------------------------------------------------------------------- /doc/papi/a5py.physlib.rst: -------------------------------------------------------------------------------- 1 | ================= 2 | ``physlib`` 3 | ================= 4 | 5 | .. automodule:: a5py.physlib 6 | :members: 7 | -------------------------------------------------------------------------------- /doc/papi/a5py.testascot.rst: -------------------------------------------------------------------------------- 1 | ============= 2 | ``testascot`` 3 | ============= 4 | 5 | .. note:: 6 | This module is for executing tests and the documentation is aimed for the developers. 7 | 8 | .. automodule:: a5py.testascot 9 | :members: 10 | -------------------------------------------------------------------------------- /src/print.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @file print.c 3 | * @brief Contains the initialization of VERBOSE_LEVEL 4 | */ 5 | #include "print.h" 6 | 7 | /** 8 | * @brief Controls the amount of information that is outputted to stdout 9 | */ 10 | const char VERBOSE_LEVEL = VERBOSE; 11 | -------------------------------------------------------------------------------- /src/hdf5io/hdf5_nbi.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file hdf5_nbi.h 3 | * @brief Header file for hdf5_nbi.c 4 | */ 5 | #ifndef HDF5_NBI_H 6 | #define HDF5_NBI_H 7 | 8 | #include 9 | #include "../ascot5.h" 10 | #include "../nbi.h" 11 | 12 | int hdf5_nbi_init(hid_t f, nbi_data* data, char* qid); 13 | 14 | #endif 15 | -------------------------------------------------------------------------------- /src/hdf5io/hdf5_wall.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file hdf5_wall.h 3 | * @brief Header file for hdf5_wall.c 4 | */ 5 | #ifndef HDF5_WALL_H 6 | #define HDF5_WALL_H 7 | 8 | #include 9 | #include "../ascot5.h" 10 | #include "../wall.h" 11 | 12 | int hdf5_wall_init(hid_t f, wall_data* data, char* qid); 13 | #endif 14 | -------------------------------------------------------------------------------- /src/spline/spline.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file spline.h 3 | * @brief Header file for splineexpl.c and splinecomp.c 4 | */ 5 | #ifndef SPLINE_H 6 | #define SPLINE_H 7 | #include "../ascot5.h" 8 | 9 | void splineexpl(real* f, int n, int bc, real* c); 10 | void splinecomp(real* f, int n, int bc, real* c); 11 | #endif 12 | -------------------------------------------------------------------------------- /doc/papi/a5py.ascot5io.asigma.rst: -------------------------------------------------------------------------------- 1 | ========== 2 | ``asigma`` 3 | ========== 4 | 5 | .. automodule:: a5py.ascot5io.asigma 6 | 7 | .. autosummary:: 8 | :nosignatures: 9 | 10 | a5py.ascot5io.asigma.Asigma_loc 11 | 12 | .. autoclass:: a5py.ascot5io.asigma.Asigma_loc 13 | :show-inheritance: 14 | :members: 15 | -------------------------------------------------------------------------------- /src/bbnbi5.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file bbnbi5.h 3 | * @brief Functions to execute bbnbi externally 4 | */ 5 | #ifndef BBNBI5_H 6 | #define BBNBI5_H 7 | 8 | #include "ascot5.h" 9 | #include "simulate.h" 10 | 11 | void bbnbi_simulate( 12 | sim_data* sim, int nprt, real t1, real t2, particle_state** p); 13 | 14 | #endif 15 | -------------------------------------------------------------------------------- /src/hdf5io/hdf5_plasma.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file hdf5_plasma.h 3 | * @brief Header file for hdf5_plasma.c 4 | */ 5 | #ifndef HDF5_PLASMA_H 6 | #define HDF5_PLASMA_H 7 | #include 8 | #include "../ascot5.h" 9 | #include "../plasma.h" 10 | 11 | int hdf5_plasma_init(hid_t f, plasma_data* data, char* qid); 12 | #endif 13 | -------------------------------------------------------------------------------- /a5py/m3_template/set-env.sh: -------------------------------------------------------------------------------- 1 | module purge 2 | module load cineca 3 | 4 | module load imasenv/3.42.0/foss/2023b/rc 5 | 6 | module load IMASPy/1.2.0-foss-2023b 7 | module load mpi4py/3.1.5-gompi-2023b 8 | 9 | module switch MUSCLE3/0.8.0-foss-2023b 10 | 11 | export TEST_DIR=$( realpath $( dirname -- "${BASH_SOURCE[0]}" ) ) 12 | -------------------------------------------------------------------------------- /src/hdf5io/hdf5_asigma.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file hdf5_asigma.h 3 | * @brief Header file for hdf5_asigma.c 4 | */ 5 | #ifndef HDF5_ASIGMA_H 6 | #define HDF5_ASIGMA_H 7 | 8 | #include 9 | #include "../ascot5.h" 10 | #include "../asigma.h" 11 | 12 | int hdf5_asigma_init(hid_t f, asigma_data* data, char* qid); 13 | #endif 14 | -------------------------------------------------------------------------------- /src/hdf5io/hdf5_neutral.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file hdf5_neutral.h 3 | * @brief Header file for hdf5_neutral.c 4 | */ 5 | #ifndef HDF5_NEUTRAL_H 6 | #define HDF5_NEUTRAL_H 7 | #include "../ascot5.h" 8 | #include "../neutral.h" 9 | #include "hdf5.h" 10 | 11 | int hdf5_neutral_init(hid_t f, neutral_data* data, char* qid); 12 | #endif 13 | -------------------------------------------------------------------------------- /src/hdf5io/hdf5_boozer.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file hdf5_boozer.h 3 | * @brief Header file for hdf5_boozer.c 4 | */ 5 | #ifndef HDF5_BOOZER_H 6 | #define HDF5_BOOZER_H 7 | 8 | #include 9 | #include "../ascot5.h" 10 | #include "../boozer.h" 11 | 12 | int hdf5_boozer_init(hid_t f, boozer_data* data, char* qid); 13 | 14 | #endif 15 | -------------------------------------------------------------------------------- /doc/papi/a5py.ascot5io.boozer.rst: -------------------------------------------------------------------------------- 1 | ======================== 2 | ``boozer`` 3 | ======================== 4 | 5 | .. automodule:: a5py.ascot5io.boozer 6 | 7 | .. autosummary:: 8 | :nosignatures: 9 | 10 | a5py.ascot5io.boozer.Boozer 11 | 12 | .. autoclass:: a5py.ascot5io.boozer.Boozer 13 | :show-inheritance: 14 | :members: 15 | -------------------------------------------------------------------------------- /doc/papi/a5py.ascot5io.neutral.rst: -------------------------------------------------------------------------------- 1 | ======================== 2 | ``neutral`` 3 | ======================== 4 | 5 | .. automodule:: a5py.ascot5io.neutral 6 | 7 | .. autosummary:: 8 | :nosignatures: 9 | 10 | a5py.ascot5io.neutral.N0_3D 11 | 12 | .. autoclass:: a5py.ascot5io.neutral.N0_3D 13 | :show-inheritance: 14 | :members: 15 | -------------------------------------------------------------------------------- /src/hdf5io/hdf5_orbit.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file hdf5_orbit.h 3 | * @brief Header file for hdf5_orbit.c 4 | */ 5 | #ifndef HDF5_ORBIT_H 6 | #define HDF5_ORBIT_H 7 | 8 | #include 9 | #include "../ascot5.h" 10 | #include "../diag/diag_orb.h" 11 | 12 | int hdf5_orbit_write(hid_t f, char* path, diag_orb_data* diag); 13 | 14 | #endif 15 | -------------------------------------------------------------------------------- /doc/papi/a5py.gui.rst: -------------------------------------------------------------------------------- 1 | ======= 2 | ``gui`` 3 | ======= 4 | 5 | .. note:: 6 | This documentation is for the implementation of the graphical user interface (GUI) of ASCOT5. 7 | The methods here are only relevant for the GUI, so this part of the documentation is aimed for the developers only. 8 | 9 | .. automodule:: a5py.gui 10 | :members: 11 | -------------------------------------------------------------------------------- /src/hdf5io/hdf5_state.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file hdf5_state.h 3 | * @brief Header file for hdf5_state.c 4 | */ 5 | #ifndef HDF5_STATE 6 | #define HDF5_STATE 7 | 8 | #include 9 | #include "../particle.h" 10 | 11 | int hdf5_state_write(hid_t f, char* run, char *state, integer n, 12 | particle_state* p); 13 | 14 | #endif 15 | -------------------------------------------------------------------------------- /src/hdf5io/hdf5_mhd.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file hdf5_mhd.h 3 | * @brief Header file for hdf5_mhd.c 4 | */ 5 | #ifndef HDF5_MHD_H 6 | #define HDF5_MHD_H 7 | 8 | #include 9 | #include "../mhd.h" 10 | #include "../mhd/mhd_stat.h" 11 | #include "../mhd/mhd_nonstat.h" 12 | 13 | int hdf5_mhd_init(hid_t f, mhd_data* data, char* qid); 14 | 15 | #endif 16 | -------------------------------------------------------------------------------- /src/simulate/simulate_ml_adaptive.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file simulate_ml_adaptive.h 3 | * @brief Header file for simulate_ml_adaptive.c 4 | */ 5 | #ifndef SIMULATE_ML_ADAPTIVE_H 6 | #define SIMULATE_ML_ADAPTIVE_H 7 | 8 | #include "../simulate.h" 9 | #include "../particle.h" 10 | 11 | void simulate_ml_adaptive(particle_queue* pq, sim_data* sim); 12 | 13 | #endif 14 | -------------------------------------------------------------------------------- /src/hdf5io/hdf5_efield.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file hdf5_efield.h 3 | * @brief Header file for hdf5_efielc.c 4 | */ 5 | #ifndef HDF5_EFIELD_H 6 | #define HDF5_EFIELD_H 7 | 8 | #include 9 | #include "../E_field.h" 10 | #include "../Efield/E_TC.h" 11 | #include "../Efield/E_1DS.h" 12 | 13 | int hdf5_efield_init(hid_t f, E_field_data* data, char* qid); 14 | #endif 15 | -------------------------------------------------------------------------------- /src/biosaw.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file biosaw.h 3 | * @brief Header file for biosaw.c 4 | */ 5 | #ifndef BIOSAW_H 6 | #define BIOSAW_H 7 | 8 | #include "ascot5.h" 9 | 10 | void biosaw_calc_B(int n, real* x, real* y, real* z, 11 | int coil_n, real* coil_x, real* coil_y, real* coil_z, 12 | real* Bx, real* By, real* Bz); 13 | 14 | #endif 15 | -------------------------------------------------------------------------------- /src/hdf5io/hdf5_transcoef.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file hdf5_transcoef.h 3 | * @brief Header file for hdf5_transcoef.c 4 | */ 5 | #ifndef HDF5_TRANSCOEF_H 6 | #define HDF5_TRANSCOEF_H 7 | 8 | #include 9 | #include "../ascot5.h" 10 | #include "../diag/diag_transcoef.h" 11 | 12 | int hdf5_transcoef_write(hid_t f, char* path, diag_transcoef_data* diag); 13 | 14 | #endif 15 | -------------------------------------------------------------------------------- /src/simulate/simulate_gc_fixed.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file simulate_gc_fixed.h 3 | * @brief Header file for simulate_gc_fixed.c 4 | */ 5 | #ifndef SIMULATE_GC_FIXED_H 6 | #define SIMULATE_GC_FIXED_H 7 | 8 | #include "../ascot5.h" 9 | #include "../simulate.h" 10 | #include "../particle.h" 11 | 12 | void simulate_gc_fixed(particle_queue* pq, sim_data* sim); 13 | 14 | #endif 15 | -------------------------------------------------------------------------------- /src/suzuki.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file suzuki.h 3 | * @brief Header file for suzuki.c 4 | */ 5 | #ifndef SUZUKI_H 6 | #define SUZUKI_H 7 | 8 | #include "ascot5.h" 9 | #include "error.h" 10 | 11 | a5err suzuki_sigmav(real* sigmav, real EperAmu, real vnorm, real ne, real te, 12 | integer nion, real* ni, const int* Anum, const int* Znum); 13 | 14 | #endif 15 | -------------------------------------------------------------------------------- /doc/papi/a5py.ascot5io.options.rst: -------------------------------------------------------------------------------- 1 | ======================== 2 | ``options`` 3 | ======================== 4 | 5 | .. automodule:: a5py.ascot5io.options 6 | 7 | .. autosummary:: 8 | :nosignatures: 9 | 10 | a5py.ascot5io.options.Opt 11 | 12 | .. autoclass:: a5py.ascot5io.options.Opt 13 | :show-inheritance: 14 | :members: 15 | :private-members: 16 | :member-order: bysource 17 | -------------------------------------------------------------------------------- /src/simulate/simulate_fo_fixed.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file simulate_fo_fixed.h 3 | * @brief Header file for simulate_fo_fixed.c 4 | */ 5 | #ifndef SIMULATE_FO_FIXED_H 6 | #define SIMULATE_FO_FIXED_H 7 | 8 | #include "../ascot5.h" 9 | #include "../simulate.h" 10 | #include "../particle.h" 11 | 12 | void simulate_fo_fixed(particle_queue* pq, sim_data* sim, int mrk_array_size); 13 | 14 | #endif 15 | -------------------------------------------------------------------------------- /src/hdf5io/hdf5_marker.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file hdf5_marker.h 3 | * @brief Header file for hdf5_marker.c 4 | */ 5 | #ifndef HDF5_MARKER_H 6 | #define HDF5_MARKER_H 7 | 8 | #include 9 | #include "../particle.h" 10 | 11 | int hdf5_marker_read(hid_t f, int *n, input_particle** p, char* qid); 12 | int hdf5_marker_write_particle(hid_t f, int n, input_particle* p, char* qid); 13 | 14 | #endif 15 | -------------------------------------------------------------------------------- /doc/papi/a5py.routines.rst: -------------------------------------------------------------------------------- 1 | ================= 2 | ``routines`` 3 | ================= 4 | 5 | .. note:: 6 | The routines in this module are either documented elsewhere (by the class that inherits them) or they are lower-level tools that are only documented here for the developers. 7 | 8 | .. automodule:: a5py.routines 9 | :members: 10 | 11 | .. automodule:: a5py.routines.plotting 12 | :members: 13 | -------------------------------------------------------------------------------- /bin/a5gui: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | """Open graphical user interface. 3 | """ 4 | import a5py.gui.gui as a5gui 5 | import argparse 6 | 7 | parser = argparse.ArgumentParser( 8 | description="Open ASCOT5 graphical user interface." 9 | ) 10 | parser.add_argument("FILE", help="ASCOT5 HDF5 file to view", nargs="?") 11 | 12 | args = parser.parse_args() 13 | gui = a5gui.GUI(args.FILE) 14 | gui.mainloop() 15 | -------------------------------------------------------------------------------- /doc/papi/a5py.ascot5io.nbi.rst: -------------------------------------------------------------------------------- 1 | ======================== 2 | ``nbi`` 3 | ======================== 4 | 5 | .. automodule:: a5py.ascot5io.nbi 6 | 7 | .. autosummary:: 8 | :nosignatures: 9 | 10 | a5py.ascot5io.nbi.NBI 11 | 12 | .. autoclass:: a5py.ascot5io.nbi.NBI 13 | :show-inheritance: 14 | :members: 15 | 16 | .. autoclass:: a5py.ascot5io.nbi.Injector 17 | :show-inheritance: 18 | :members: 19 | -------------------------------------------------------------------------------- /doc/papi/a5py.ascot5io.wall.rst: -------------------------------------------------------------------------------- 1 | ======================== 2 | ``wall`` 3 | ======================== 4 | 5 | .. automodule:: a5py.ascot5io.wall 6 | 7 | .. autosummary:: 8 | :nosignatures: 9 | 10 | a5py.ascot5io.wall.wall_2D 11 | a5py.ascot5io.wall.wall_3D 12 | 13 | .. autoclass:: a5py.ascot5io.wall.wall_2D 14 | :show-inheritance: 15 | :members: 16 | 17 | .. autoclass:: a5py.ascot5io.wall.wall_3D 18 | :members: 19 | -------------------------------------------------------------------------------- /environment-rfof.yaml: -------------------------------------------------------------------------------- 1 | name: ascot-rfof 2 | channels: 3 | - conda-forge 4 | dependencies: 5 | - fortran-compiler 6 | - c-compiler 7 | - make 8 | - libxml2 9 | - pkg-config 10 | - libgomp 11 | - python>=3.10 12 | - hdf5 13 | - zlib 14 | - setuptools 15 | - pip 16 | - ipython 17 | - numpy 18 | - scipy 19 | - h5py 20 | - unyt==2.9.5 21 | - wurlitzer 22 | - matplotlib 23 | - pyvista 24 | - freeqdsk 25 | -------------------------------------------------------------------------------- /environment.yaml: -------------------------------------------------------------------------------- 1 | name: ascot-env 2 | channels: 3 | - conda-forge 4 | dependencies: 5 | - c-compiler 6 | - make 7 | - llvm-openmp 8 | - python>=3.10 9 | - hdf5 10 | - zlib 11 | - setuptools 12 | - pip 13 | - ipython 14 | - numpy 15 | - scipy 16 | - h5py 17 | - xmlschema 18 | - unyt 19 | - wurlitzer 20 | - matplotlib 21 | - pyvista 22 | - freeqdsk 23 | - pip: 24 | - desc-opt 25 | - netCDF4 26 | -------------------------------------------------------------------------------- /src/libascot_mem.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file libascot_mem.h 3 | * @brief Header file for libascot_mem.c 4 | */ 5 | #ifndef LIBASCOT_MEM_H_ 6 | #define LIBASCOT_MEM_H_ 7 | 8 | #include "particle.h" 9 | 10 | input_particle* libascot_allocate_input_particles(int nmrk); 11 | particle_state* libascot_allocate_particle_states(int nmrk); 12 | real* libascot_allocate_reals(size_t size); 13 | 14 | void libascot_deallocate(void *arr); 15 | 16 | #endif 17 | -------------------------------------------------------------------------------- /doc/papi/a5py.ascot5io.plasma.rst: -------------------------------------------------------------------------------- 1 | ======================== 2 | ``plasma`` 3 | ======================== 4 | 5 | .. automodule:: a5py.ascot5io.plasma 6 | 7 | .. autosummary:: 8 | :nosignatures: 9 | 10 | a5py.ascot5io.plasma.plasma_1D 11 | a5py.ascot5io.plasma.plasma_1DS 12 | 13 | .. autoclass:: a5py.ascot5io.plasma.plasma_1D 14 | :show-inheritance: 15 | :members: 16 | 17 | .. autoclass:: a5py.ascot5io.plasma.plasma_1DS 18 | :members: 19 | -------------------------------------------------------------------------------- /doc/papi/a5py.ascot5io.mhd.rst: -------------------------------------------------------------------------------- 1 | ======================== 2 | ``mhd`` 3 | ======================== 4 | 5 | .. automodule:: a5py.ascot5io.mhd 6 | 7 | .. autosummary:: 8 | :nosignatures: 9 | 10 | a5py.ascot5io.mhd.MHD_STAT 11 | a5py.ascot5io.mhd.MHD_NONSTAT 12 | 13 | .. autoclass:: a5py.ascot5io.mhd.MHD_STAT 14 | :show-inheritance: 15 | :members: 16 | 17 | .. autoclass:: a5py.ascot5io.mhd.MHD_NONSTAT 18 | :show-inheritance: 19 | :members: 20 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.o 2 | *.optrpt 3 | *.pyc 4 | *.so 5 | *~ 6 | /build 7 | /doc/_static/doxygen 8 | /.metadata/ 9 | /a5py.egg-info/ 10 | /venv 11 | /.venv 12 | /env 13 | /.env 14 | gitver.h 15 | compiler_flags.h 16 | ascot.h5 17 | test_offload 18 | test_B 19 | test_E 20 | test_N0 21 | test_bsearch 22 | test_interp1Dcomp 23 | test_linint3D 24 | test_math 25 | test_plasma 26 | test_random 27 | test_spline 28 | test_wall_2d 29 | test_wall_3d 30 | ascot5_main 31 | bbnbi5 32 | -------------------------------------------------------------------------------- /src/unit_tests/test_afsi.c: -------------------------------------------------------------------------------- 1 | #include "../ascot5.h" 2 | #include 3 | #include "../boschhale.h" 4 | 5 | int main(int argc, char** argv) { 6 | for(int i = 1; i <= 10000; i++) { 7 | printf("%le ", 1e3*i); 8 | 9 | for(int j = 1; j <= 4; j++) { 10 | printf("%le ", boschhale_sigma(j, i)); 11 | printf("%le ", boschhale_sigmav(j, i)); 12 | } 13 | 14 | printf("\n"); 15 | } 16 | 17 | return 0; 18 | } 19 | -------------------------------------------------------------------------------- /environment-mpi.yaml: -------------------------------------------------------------------------------- 1 | name: ascot-env 2 | channels: 3 | - conda-forge 4 | dependencies: 5 | - c-compiler 6 | - make 7 | - llvm-openmp 8 | - python>=3.10 9 | - hdf5 10 | - zlib 11 | - setuptools 12 | - pip 13 | - ipython 14 | - numpy 15 | - scipy 16 | - mpi=*=*openmpi* 17 | - h5py=*=*openmpi* 18 | - mpi4py 19 | - xmlschema 20 | - unyt 21 | - wurlitzer 22 | - matplotlib 23 | - pyvista 24 | - freeqdsk 25 | - pip: 26 | - desc-opt 27 | - netCDF4 28 | -------------------------------------------------------------------------------- /src/hdf5io/hdf5_bfield.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file hdf5_bfield.h 3 | * @brief Header file for hdf5_bfield.c 4 | */ 5 | #ifndef HDF5_BFIELD_H 6 | #define HDF5_BFIELD_H 7 | #include "../ascot5.h" 8 | #include "../B_field.h" 9 | #include "../Bfield/B_2DS.h" 10 | #include "../Bfield/B_3DS.h" 11 | #include "../Bfield/B_STS.h" 12 | #include "../Bfield/B_GS.h" 13 | #include "../Bfield/B_TC.h" 14 | #include "hdf5.h" 15 | 16 | int hdf5_bfield_init(hid_t f, B_field_data* data, char* qid); 17 | 18 | #endif 19 | -------------------------------------------------------------------------------- /.github/workflows/build-test-light.yaml: -------------------------------------------------------------------------------- 1 | name: Run Tests (light) 2 | on: 3 | workflow_dispatch: 4 | push: 5 | branches-ignore: 6 | - main 7 | - develop 8 | - docs 9 | 10 | jobs: 11 | 12 | Prepare: 13 | permissions: 14 | contents: read 15 | packages: write 16 | uses: ascot4fusion/ascot5/.github/workflows/build.yaml@main 17 | 18 | Testing: 19 | needs: Prepare 20 | uses: ascot4fusion/ascot5/.github/workflows/tests.yaml@main 21 | with: 22 | run_unit_tests: true 23 | -------------------------------------------------------------------------------- /src/gitver.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | GIT_BRANCH="$(git branch | grep \* | cut -d ' ' -f2)" 3 | GIT_VERSION="$(git describe --abbrev=7 --dirty --always --tags)" 4 | 5 | if [ -z "$GIT_VERSION" ] 6 | then 7 | GIT_BRANCH="main" 8 | GIT_VERSION=$( gitver.h 12 | echo "#define GITVER_H" >> gitver.h 13 | echo "" >> gitver.h 14 | 15 | echo "#define GIT_BRANCH" \"$GIT_BRANCH\" >> gitver.h 16 | echo "#define GIT_VERSION" \"$GIT_VERSION\" >> gitver.h 17 | 18 | echo "" >> gitver.h 19 | echo "#endif" >> gitver.h 20 | -------------------------------------------------------------------------------- /src/hdf5io/hdf5_options.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file hdf5_options.h 3 | * @brief Header file for hdf5_options.c 4 | */ 5 | #ifndef HDF5_OPTIONS_H5 6 | #define HDF5_OPTIONS_H5 7 | 8 | #include "../simulate.h" 9 | #include 10 | 11 | int hdf5_options_read(hid_t f, sim_data* sim, char* qid); 12 | 13 | #define TOROIDAL_ANGLE_FILLER_VALUE 361 /**< Dummy value in poincare init */ 14 | #define POLOIDAL_ANGLE_FILLER_VALUE 361 /**< Dummy value in poincare init */ 15 | #define RADIAL_FILLER_VALUE 1000 /**< Dummy value in poincare init */ 16 | 17 | #endif 18 | -------------------------------------------------------------------------------- /doc/papi/a5py.ascot5io.coreio.rst: -------------------------------------------------------------------------------- 1 | ========== 2 | ``CoreIO`` 3 | ========== 4 | 5 | .. automodule:: a5py.ascot5io.coreio 6 | 7 | .. automodule:: a5py.ascot5io.coreio.treeview 8 | :show-inheritance: 9 | :members: 10 | :inherited-members: 11 | :undoc-members: 12 | 13 | .. automodule:: a5py.ascot5io.coreio.treedata 14 | :show-inheritance: 15 | :members: 16 | :inherited-members: 17 | :undoc-members: 18 | 19 | .. automodule:: a5py.ascot5io.coreio.fileapi 20 | :show-inheritance: 21 | :members: 22 | :inherited-members: 23 | :undoc-members: 24 | -------------------------------------------------------------------------------- /doc/papi/a5py.ascot5io.marker.rst: -------------------------------------------------------------------------------- 1 | ======================== 2 | ``marker`` 3 | ======================== 4 | 5 | .. automodule:: a5py.ascot5io.marker 6 | 7 | .. autosummary:: 8 | :nosignatures: 9 | 10 | a5py.ascot5io.marker.Prt 11 | a5py.ascot5io.marker.GC 12 | a5py.ascot5io.marker.FL 13 | 14 | .. autoclass:: a5py.ascot5io.marker.Prt 15 | :show-inheritance: 16 | :members: 17 | 18 | .. autoclass:: a5py.ascot5io.marker.GC 19 | :show-inheritance: 20 | :members: 21 | 22 | .. autoclass:: a5py.ascot5io.marker.FL 23 | :show-inheritance: 24 | :members: 25 | -------------------------------------------------------------------------------- /.github/workflows/publish-docs.yaml: -------------------------------------------------------------------------------- 1 | name: Publish Documentation 2 | on: 3 | push: 4 | branches: 5 | - docs 6 | 7 | jobs: 8 | 9 | Prepare: 10 | permissions: 11 | contents: read 12 | packages: write 13 | uses: ascot4fusion/ascot5/.github/workflows/build.yaml@main 14 | 15 | Docs: 16 | needs: Prepare 17 | permissions: 18 | contents: read 19 | packages: read 20 | pages: write 21 | id-token: write 22 | uses: ascot4fusion/ascot5/.github/workflows/docs.yaml@main 23 | with: 24 | publish: true 25 | secrets: inherit 26 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | .PHONY: doc 2 | 3 | ascot5_main: 4 | $(MAKE) -C src ascot5_main 5 | mkdir -p build 6 | mv src/ascot5_main build/ascot5_main 7 | 8 | libascot: 9 | $(MAKE) -C src libascot 10 | mkdir -p build 11 | mv src/libascot.so build/libascot.so 12 | 13 | bbnbi5: 14 | $(MAKE) -C src bbnbi5 15 | mkdir -p build 16 | mv src/bbnbi5 build/bbnbi5 17 | 18 | ascot2py.py: 19 | $(MAKE) -C src ascot2py.py 20 | python3 .setcdllascot2py.py 21 | mv src/ascot2py.py a5py/ascotpy/ascot2py.py 22 | 23 | doc: 24 | $(MAKE) -C src doc 25 | $(MAKE) -C doc 26 | 27 | clean: 28 | $(MAKE) -C src clean 29 | rm -rf build 30 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | # This container should include all the necessary libraries and tools 2 | # to compile and use ascot5. It can be used e.g. as the image for CI testing. 3 | 4 | FROM ubuntu:latest 5 | 6 | ENV TZ=Europe/Helsinki 7 | RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone 8 | 9 | RUN apt-get update && \ 10 | apt-get install -y \ 11 | libhdf5-openmpi-dev libhdf5-dev h5utils emacs \ 12 | make gcc libclang-12-dev git libgl1 python3-pip && \ 13 | pip3 install ctypeslib2 clang==12.0.1 --no-cache-dir 14 | COPY requirements.txt . 15 | RUN pip3 install -r requirements.txt 16 | -------------------------------------------------------------------------------- /a5py/m3_template/set-env_csh.sh: -------------------------------------------------------------------------------- 1 | 2 | module purge 3 | module load cineca 4 | 5 | 6 | 7 | module load imasenv/3.42.0/foss/2023b/rc 8 | #module unload HDF5/1.14.3-gompi-2023b 9 | #module load HDF5/1.14.4.3-gompi-2023b 10 | module load IMASPy/1.2.0-foss-2023b 11 | module load mpi4py/3.1.5-gompi-2023b 12 | 13 | module switch MUSCLE3/0.8.0-foss-2023b 14 | module switch HDF5/1.14.4.3-gompi-2023b 15 | 16 | setenv TEST_DIR $PWD 17 | setenv PYTHONPATH /gss_efgw_work/work/g2diy/public/ascot/test_branch\:$PYTHONPATH 18 | setenv PYTHONPATH /gss_efgw_work/work/g2diy/public/ascot/test_branch/venv/lib/python3.11/site-packages\:$PYTHONPATH 19 | -------------------------------------------------------------------------------- /src/simulate/atomic.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file atomic.h 3 | * @brief Header file for atomic.c 4 | */ 5 | #ifndef ATOMIC_H 6 | #define ATOMIC_H 7 | 8 | #include "../ascot5.h" 9 | #include "../plasma.h" 10 | #include "../neutral.h" 11 | #include "../particle.h" 12 | #include "../random.h" 13 | #include "../asigma.h" 14 | 15 | #ifndef GPU 16 | #pragma omp declare target 17 | #endif 18 | void atomic_fo(particle_simd_fo* p, real* h, 19 | plasma_data* p_data, neutral_data* n_data, 20 | random_data* r_data, asigma_data* asigma_data); 21 | #ifndef GPU 22 | #pragma omp end declare target 23 | #endif 24 | #endif 25 | -------------------------------------------------------------------------------- /src/simulate/step/step_fo_vpa.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file step_fo_vpa.h 3 | * @brief Header file for step_fo_vpa.c 4 | */ 5 | #ifndef STEP_FO_VPA_H 6 | #define STEP_FO_VPA_H 7 | #include "../../B_field.h" 8 | #include "../../E_field.h" 9 | #include "../../boozer.h" 10 | #include "../../mhd.h" 11 | #include "../../particle.h" 12 | 13 | void step_fo_vpa(particle_simd_fo* p, real* h, B_field_data* Bdata, 14 | E_field_data* Edata, int aldforce); 15 | void step_fo_vpa_mhd( 16 | particle_simd_fo* p, real* h, B_field_data* Bdata, E_field_data* Edata, 17 | boozer_data* boozer, mhd_data* mhd, int aldforce); 18 | 19 | #endif 20 | -------------------------------------------------------------------------------- /doc/_static/custom.css: -------------------------------------------------------------------------------- 1 | .wy-table-responsive table td { 2 | white-space: normal; 3 | } 4 | 5 | .wy-side-nav-search, .wy-nav-top { 6 | background: #ffeeaa; 7 | } 8 | 9 | code.literal { 10 | color: #404040 !important; 11 | } 12 | 13 | .mermaidTooltip { 14 | position: absolute; 15 | text-align: left; 16 | max-width: 320px; 17 | padding: 2px; 18 | font-family: 'trebuchet ms', verdana, arial; 19 | font-size: 12px; 20 | background: #ffffde; 21 | border: 1px solid #aaaa33; 22 | border-radius: 2px; 23 | pointer-events: none; 24 | z-index: 100; 25 | white-space: pre; 26 | } 27 | -------------------------------------------------------------------------------- /a5py/_nonfunctional/write_to_imas.py: -------------------------------------------------------------------------------- 1 | # coding: utf-8 2 | 3 | # get helloworld.h5 with 4 | # python ../preprocessing/simpleruns.py 5 | 6 | from a5py.ascot5io.ascot5 import Ascot 7 | import a5py.ascot5io.imas 8 | import a5py.ascot5io.wall_2D 9 | import a5py.ascot5io.wall_3D 10 | 11 | filename='helloworld.h5' 12 | a=Ascot(filename) 13 | wdict3 = a.wall.active.read() 14 | bsts = a.bfield.active.read() 15 | 16 | w3dimas=a5py.ascot5io.imas.wall_3d() 17 | bstsimas=a5py.ascot5io.imas.B_STS() 18 | w3dimas.write( wdict3,'akaslos','mywall', '3',201,101, {'comment':filename} ) 19 | bstsimas.write( bsts,'akaslos','ggdtest','3',32, 3, {'comment':filename} ) 20 | 21 | 22 | -------------------------------------------------------------------------------- /src/boschhale.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file boschhale.h 3 | * @brief Header file for boschdale.c 4 | */ 5 | #ifndef BOSCHHALE_H 6 | #define BOSCHHALE_H 7 | 8 | #include "ascot5.h" 9 | 10 | /** 11 | * @brief Available reactions 12 | */ 13 | typedef enum Reaction { 14 | DT_He4n = 1, 15 | DHe3_He4p = 2, 16 | DD_Tp = 3, 17 | DD_He3n = 4, 18 | } Reaction; 19 | 20 | void boschhale_reaction( 21 | Reaction reaction, real* m1, real* q1, real* m2, real* q2, 22 | real* mprod1, real* qprod1, real* mprod2, real* qprod2, real* Q); 23 | real boschhale_sigma(Reaction reaction, real E); 24 | real boschhale_sigmav(Reaction reaction, real Ti); 25 | 26 | #endif 27 | -------------------------------------------------------------------------------- /src/simulate/step/step_gc_rk4.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file step_gc_rk4.h 3 | * @brief Header file for step_gc_rk4.c 4 | */ 5 | #ifndef STEP_GC_RK4_H 6 | #define STEP_GC_RK4_H 7 | 8 | #include "../../ascot5.h" 9 | #include "../../B_field.h" 10 | #include "../../E_field.h" 11 | #include "../../boozer.h" 12 | #include "../../mhd.h" 13 | #include "../../particle.h" 14 | 15 | void step_gc_rk4(particle_simd_gc* p, real* h, B_field_data* Bdata, 16 | E_field_data* Edata, int aldforce); 17 | void step_gc_rk4_mhd(particle_simd_gc* p, real* h, B_field_data* Bdata, 18 | E_field_data* Edata, boozer_data* boozer, 19 | mhd_data* mhd, int aldforce); 20 | 21 | #endif 22 | -------------------------------------------------------------------------------- /src/simulate/step/step_ml_cashkarp.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file step_ml_cashkarp.h 3 | * @brief Header file for step_ml_cashkarp.c 4 | */ 5 | #ifndef STEP_ML_CASHKARP_H 6 | #define STEP_ML_CASHKARP_H 7 | 8 | #include "../../B_field.h" 9 | #include "../../boozer.h" 10 | #include "../../mhd.h" 11 | #include "../../particle.h" 12 | 13 | void step_ml_cashkarp(particle_simd_ml* p, real* h, real* hnext, 14 | real tol, B_field_data* Bdata); 15 | void step_ml_cashkarp_mhd(particle_simd_ml* p, real* h, real* hnext, 16 | real tol, B_field_data* Bdata, 17 | boozer_data* boozerdata, 18 | mhd_data* mhddata); 19 | 20 | #endif 21 | -------------------------------------------------------------------------------- /src/simulate/step/step_gc_cashkarp.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file step_gc_rk4.h 3 | * @brief Header file for step_gc_rk4.c 4 | */ 5 | #ifndef STEP_GC_CASHKARP_H 6 | #define STEP_GC_CASHKARP_H 7 | 8 | #include "../../B_field.h" 9 | #include "../../E_field.h" 10 | #include "../../boozer.h" 11 | #include "../../mhd.h" 12 | #include "../../particle.h" 13 | 14 | void step_gc_cashkarp(particle_simd_gc* p, real* h, real* hnext, real tol, 15 | B_field_data* Bdata, E_field_data* Edata, int aldforce); 16 | void step_gc_cashkarp_mhd( 17 | particle_simd_gc* p, real* h, real* hnext, real tol, B_field_data* Bdata, 18 | E_field_data* Edata, boozer_data* boozer, mhd_data* mhd, int aldforce); 19 | 20 | #endif 21 | -------------------------------------------------------------------------------- /bin/a5update: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | """Update ASCOT5 file from an old version to current version. 3 | """ 4 | import argparse 5 | import warnings 6 | 7 | with warnings.catch_warnings(): 8 | warnings.filterwarnings('ignore', message=".*libascot.so.*") 9 | warnings.filterwarnings('ignore', message=".*pyvista.*") 10 | warnings.filterwarnings('ignore', message=".*matplotlib.*") 11 | import a5py.ascot5io.coreio.compatibility as comp 12 | 13 | parser = argparse.ArgumentParser( 14 | description="Update an outdated Ascot5 HDF5 file to current version." 15 | ) 16 | parser.add_argument("FILE", help="Target file which is copied and updated") 17 | 18 | args = parser.parse_args() 19 | comp.convert(args.FILE) 20 | -------------------------------------------------------------------------------- /src/hdf5io/hdf5_dist.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @brief hdf5_dist.h 3 | * @brief Header file for hdf5_dist.c 4 | */ 5 | #ifndef HDF5_DIST_H 6 | #define HDF5_DIST_H 7 | 8 | #include 9 | #include "../ascot5.h" 10 | #include "../diag/dist_5D.h" 11 | #include "../diag/dist_6D.h" 12 | #include "../diag/dist_rho5D.h" 13 | #include "../diag/dist_rho6D.h" 14 | #include "../diag/dist_com.h" 15 | 16 | int hdf5_dist_write_5D(hid_t f, char* path, dist_5D_data* dist); 17 | int hdf5_dist_write_6D(hid_t f, char* path, dist_6D_data* dist); 18 | int hdf5_dist_write_rho5D(hid_t f, char* path, dist_rho5D_data* dist); 19 | int hdf5_dist_write_rho6D(hid_t f, char* path, dist_rho6D_data* dist); 20 | int hdf5_dist_write_COM(hid_t f, char* path, dist_COM_data* dist); 21 | 22 | #endif 23 | -------------------------------------------------------------------------------- /doc/gallery.rst: -------------------------------------------------------------------------------- 1 | ======= 2 | Gallery 3 | ======= 4 | 5 | WIP 6 | 7 | .. figure:: ../figures/sparcre.png 8 | :class: with-border 9 | :align: center 10 | :width: 300px 11 | 12 | Runaway electron transport coefficients calculated with ASCOT5. 13 | Ref. :cite:t:`tinguely2021modeling` studied an external coil for runaway electron mitigation in SPARC. 14 | Markers were traced with ASCOT5 using magnetic fields computed with NIMROD, and the resulting coefficients allowed DREAM to take losses into account when calculating runaway electron beam evolution. 15 | 16 | Publications using ASCOT 17 | ======================== 18 | 19 | These include ones that have used ASCOT5 or its predecessors ASCOT4 and ASCOT3. 20 | 21 | .. bibliography:: 22 | :all: 23 | :style: plain 24 | -------------------------------------------------------------------------------- /.github/workflows/build-image.yaml: -------------------------------------------------------------------------------- 1 | name: Build Dockerfile 2 | on: [workflow_dispatch] 3 | 4 | jobs: 5 | 6 | Build-Image: 7 | runs-on: ubuntu-latest 8 | permissions: 9 | contents: read 10 | packages: write 11 | steps: 12 | - uses: actions/checkout@v4 13 | 14 | - name: Login to GitHub Container Registry 15 | uses: docker/login-action@v3 16 | with: 17 | registry: ghcr.io 18 | username: ${{ github.actor }} 19 | password: ${{ secrets.GITHUB_TOKEN }} 20 | 21 | - name: Build and Push 22 | run: | 23 | docker build ./ --tag ghcr.io/ascot4fusion/ascot5deps:latest 24 | docker run ghcr.io/ascot4fusion/ascot5deps:latest 25 | docker push ghcr.io/ascot4fusion/ascot5deps:latest 26 | -------------------------------------------------------------------------------- /doc/papi/a5py.ascot5io.bfield.rst: -------------------------------------------------------------------------------- 1 | ======================== 2 | ``bfield`` 3 | ======================== 4 | 5 | .. automodule:: a5py.ascot5io.bfield 6 | 7 | .. autosummary:: 8 | :nosignatures: 9 | 10 | a5py.ascot5io.bfield.B_2DS 11 | a5py.ascot5io.bfield.B_3DS 12 | a5py.ascot5io.bfield.B_STS 13 | a5py.ascot5io.bfield.B_GS 14 | a5py.ascot5io.bfield.B_TC 15 | 16 | .. autoclass:: a5py.ascot5io.bfield.B_2DS 17 | :show-inheritance: 18 | :members: 19 | 20 | .. autoclass:: a5py.ascot5io.bfield.B_3DS 21 | :show-inheritance: 22 | :members: 23 | 24 | .. autoclass:: a5py.ascot5io.bfield.B_STS 25 | :show-inheritance: 26 | :members: 27 | 28 | .. autoclass:: a5py.ascot5io.bfield.B_GS 29 | :show-inheritance: 30 | :members: 31 | 32 | .. autoclass:: a5py.ascot5io.bfield.B_TC 33 | :show-inheritance: 34 | :members: 35 | -------------------------------------------------------------------------------- /a5py/m3_template/README.md: -------------------------------------------------------------------------------- 1 | #The directories content 2 | 3 | ## Micro 4 | 5 | The 'micro' model - provides a template of the MPI Python code that can interact with MUSCLE3 library 6 | 7 | ## Macro 8 | 9 | The 'macro' model - very simple logic, added to allow the micro model tests. 10 | The model launches the micro model several times, sending to it the input IDSes and receives the out IDS 11 | at every iteration 12 | 13 | ## Workflow 14 | yMMLS file that defines micr-macro models connections and their implementations. 15 | 16 | **WARNING!** 17 | Remember to correct the code parameter file path to point to a proper locations! 18 | (The MUSCLE3 0.8.0 cannot use system variables in 'settings' part of the yMMSL file.) 19 | 20 | ## Scripts 21 | `set-env.sh`, `run.sh`: Auxiliary scripts to set up the environment (IMAS/3.42.0/foss) and run the workflow. 22 | -------------------------------------------------------------------------------- /src/simulate/mccc/mccc.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @file mccc.c 3 | * @brief Interface for using mccc package within ascot5 4 | */ 5 | #include 6 | #include 7 | #include "mccc.h" 8 | 9 | /** 10 | * @brief Set collision operator data. 11 | * 12 | * @param mdata pointer to collision operator data struct 13 | * @param include_energy can collisions change marker energy, either 0 or 1 14 | * @param include_pitch can collisions change marker pitch, either 0 or 1 15 | * @param include_gcdiff can collisions change GC position, either 0 or 1 16 | */ 17 | void mccc_init(mccc_data* mdata, int include_energy, int include_pitch, 18 | int include_gcdiff) { 19 | mdata->include_energy = include_energy; 20 | mdata->include_pitch = include_pitch; 21 | mdata->include_gcdiff = include_gcdiff; 22 | 23 | mdata->usetabulated = 0; 24 | } 25 | -------------------------------------------------------------------------------- /.github/workflows/build-test.yaml: -------------------------------------------------------------------------------- 1 | name: Run Tests 2 | on: 3 | workflow_dispatch: 4 | pull_request: 5 | branches: 6 | - main 7 | push: 8 | branches: 9 | - develop 10 | 11 | jobs: 12 | 13 | Prepare: 14 | permissions: 15 | contents: read 16 | packages: write 17 | uses: ascot4fusion/ascot5/.github/workflows/build.yaml@main 18 | 19 | Testing: 20 | needs: Prepare 21 | permissions: 22 | contents: read 23 | packages: read 24 | uses: ascot4fusion/ascot5/.github/workflows/tests.yaml@main 25 | with: 26 | run_unit_tests: true 27 | run_physics_tests: true 28 | 29 | Docs: 30 | needs: Prepare 31 | permissions: 32 | contents: read 33 | packages: read 34 | pages: write 35 | id-token: write 36 | uses: ascot4fusion/ascot5/.github/workflows/docs.yaml@main 37 | secrets: inherit 38 | -------------------------------------------------------------------------------- /src/list.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file list.h 3 | * @brief Header file for list.c 4 | */ 5 | #ifndef LIST_H 6 | #define LIST_H 7 | #include "offload.h" 8 | 9 | /** 10 | * @brief Linked list node that stores int data 11 | */ 12 | typedef struct list_int_node { 13 | struct list_int_node* next; /**< Next node in chain */ 14 | int data; /**< Data that is stored in this node */ 15 | } list_int_node; 16 | 17 | DECLARE_TARGET 18 | void list_int_create(list_int_node** list); 19 | DECLARE_TARGET_END 20 | DECLARE_TARGET 21 | void list_int_free(list_int_node** list); 22 | DECLARE_TARGET_END 23 | DECLARE_TARGET 24 | void list_int_add(list_int_node* list, int data); 25 | DECLARE_TARGET_END 26 | DECLARE_TARGET 27 | int list_int_get(list_int_node* list, int index); 28 | DECLARE_TARGET_END 29 | DECLARE_TARGET 30 | int list_int_size(list_int_node* list); 31 | DECLARE_TARGET_END 32 | 33 | #endif 34 | -------------------------------------------------------------------------------- /doc/papi/a5py.ascot5io.efield.rst: -------------------------------------------------------------------------------- 1 | ======================== 2 | ``efield`` 3 | ======================== 4 | 5 | .. automodule:: a5py.ascot5io.efield 6 | 7 | .. autosummary:: 8 | :nosignatures: 9 | 10 | a5py.ascot5io.efield.E_TC 11 | a5py.ascot5io.efield.E_1DS 12 | 13 | .. 14 | a5py.ascot5io.efield.E_3D 15 | a5py.ascot5io.efield.E_3DS 16 | a5py.ascot5io.efield.E_3DST 17 | 18 | .. autoclass:: a5py.ascot5io.efield.E_TC 19 | :show-inheritance: 20 | :members: 21 | 22 | .. autoclass:: a5py.ascot5io.efield.E_1DS 23 | :show-inheritance: 24 | :members: 25 | 26 | .. 27 | These are not fully implemented yet 28 | .. autoclass:: a5py.ascot5io.efield.E_3D 29 | :show-inheritance: 30 | :members: 31 | 32 | .. autoclass:: a5py.ascot5io.efield.E_3DS 33 | :show-inheritance: 34 | :members: 35 | 36 | .. autoclass:: a5py.ascot5io.efield.E_3DST 37 | :show-inheritance: 38 | :members: 39 | -------------------------------------------------------------------------------- /src/Efield/E_TC.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file E_TC.h 3 | * @brief Header file for E_TC.c 4 | * 5 | * Contains declaration of E_TC_field_offload_data and E_TC_field_data structs. 6 | */ 7 | #ifndef E_TC_H 8 | #define E_TC_H 9 | 10 | #include "../offload.h" 11 | #include "../ascot5.h" 12 | #include "../error.h" 13 | #include "../B_field.h" 14 | 15 | /** 16 | * @brief Trivial Cartesian electric field simulation data 17 | */ 18 | typedef struct { 19 | real Exyz[3]; /**< Pointer to array holding constant [E_x, E_y, E_z] 20 | values [V/m] */ 21 | } E_TC_data; 22 | 23 | int E_TC_init(E_TC_data* Edata, real exyz[3]); 24 | void E_TC_free(E_TC_data* Edata); 25 | void E_TC_offload(E_TC_data* Edata); 26 | GPU_DECLARE_TARGET_SIMD_UNIFORM(Edata,Bdata) 27 | a5err E_TC_eval_E(real E[3], real r, real phi, real z, E_TC_data* Edata, 28 | B_field_data* Bdata); 29 | DECLARE_TARGET_END 30 | #endif 31 | -------------------------------------------------------------------------------- /doc/make.bat: -------------------------------------------------------------------------------- 1 | @ECHO OFF 2 | 3 | pushd %~dp0 4 | 5 | REM Command file for Sphinx documentation 6 | 7 | if "%SPHINXBUILD%" == "" ( 8 | set SPHINXBUILD=sphinx-build 9 | ) 10 | set SOURCEDIR=source 11 | set BUILDDIR=build 12 | 13 | %SPHINXBUILD% >NUL 2>NUL 14 | if errorlevel 9009 ( 15 | echo. 16 | echo.The 'sphinx-build' command was not found. Make sure you have Sphinx 17 | echo.installed, then set the SPHINXBUILD environment variable to point 18 | echo.to the full path of the 'sphinx-build' executable. Alternatively you 19 | echo.may add the Sphinx directory to PATH. 20 | echo. 21 | echo.If you don't have Sphinx installed, grab it from 22 | echo.https://www.sphinx-doc.org/ 23 | exit /b 1 24 | ) 25 | 26 | if "%1" == "" goto help 27 | 28 | %SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O% 29 | goto end 30 | 31 | :help 32 | %SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O% 33 | 34 | :end 35 | popd 36 | -------------------------------------------------------------------------------- /src/unit_tests/test_random.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @file test_random.c 3 | * @brief Test program for random number generator 4 | */ 5 | #include 6 | #include 7 | #include "../ascot5.h" 8 | #include "../random.h" 9 | 10 | #define N 1000000 /**< Number of random numbers to be genrated */ 11 | 12 | /** 13 | * Main function for the test program 14 | */ 15 | int main(int argc, char** argv) { 16 | random_data rdata; 17 | 18 | double r[N]; 19 | 20 | random_init(&rdata, 12345); 21 | 22 | double t1, t2, t3; 23 | t1 = omp_get_wtime(); 24 | 25 | for(int i = 0; i < N; i++) { 26 | r[i] = random_uniform(&rdata); 27 | } 28 | 29 | t2 = omp_get_wtime(); 30 | 31 | random_uniform_simd(&rdata, N, r); 32 | 33 | t3 = omp_get_wtime(); 34 | 35 | printf("Serial %lf, SIMD %lf\n", t2-t1, t3-t2); 36 | 37 | /* for(int i = 0; i < N; i++) { 38 | printf("%le\n", r[i]); 39 | }*/ 40 | 41 | return 0; 42 | } 43 | -------------------------------------------------------------------------------- /environment-dev.yaml: -------------------------------------------------------------------------------- 1 | name: ascot-dev 2 | channels: 3 | - conda-forge 4 | dependencies: 5 | - c-compiler 6 | - make 7 | - glib 8 | - llvm-openmp 9 | - python>=3.10 10 | - hdf5=*=*openmp* 11 | - mpi=*=*openmp* 12 | - zlib 13 | - setuptools 14 | - pip 15 | - ipython 16 | - numpy 17 | - scipy 18 | - h5py 19 | - mpi4py 20 | - xmlschema 21 | - unyt 22 | - wurlitzer 23 | - matplotlib 24 | - pyvista 25 | - freeqdsk 26 | - doxygen 27 | - ruff 28 | - ipykernel 29 | - pandoc 30 | - sphinx==6.* 31 | - numpydoc 32 | - nbsphinx 33 | - nbformat 34 | - breathe 35 | - sphinxcontrib-bibtex 36 | - sphinx-rtd-theme 37 | - sphinx-gallery 38 | - sphinx-design 39 | - sphinxcontrib-mermaid 40 | - clang==15.* 41 | - clang-tools==15.* 42 | - libclang==15.* 43 | - llvm-openmp==15.* 44 | - libsanitizer 45 | - pylint 46 | - pip: 47 | - clang==15.* 48 | - ctypeslib2 49 | - desc-opt 50 | - netCDF4 51 | -------------------------------------------------------------------------------- /src/hdf5io/hdf5_histogram.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file hdf5_histogram.h 3 | * @brief Header file for hdf5_histogram.c 4 | */ 5 | #ifndef HDF5_HISTOGRAM 6 | #define HDF5_HISTOGRAM 7 | 8 | #include 9 | #include "../diag/hist.h" 10 | 11 | int hdf5_hist_write(hid_t f, char* path, histogram* hist); 12 | 13 | int hdf5_histogram_write_uniform_double(hid_t f, const char *path, 14 | int abscissaDim, int ordinateDim, 15 | int *abscissaNslots, 16 | double *abscissaMin, 17 | double *abscissaMax, 18 | char **abscissaUnits, 19 | char **abscissaNames, 20 | char **ordinateUnits, 21 | char **ordinateNames, 22 | double *ordinate); 23 | #endif 24 | -------------------------------------------------------------------------------- /src/ascot5_main.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file ascot5_main.h 3 | * @brief Functions to execute main program externally 4 | * 5 | * The main progam for ascot5 is in ascot5_main.c. This header file declares 6 | * the functions needed to carry out the simulation, so that hey can be used by 7 | * an external program (i.e. via the python interface). 8 | */ 9 | #ifndef ASCOT5_MAIN_H 10 | #define ASCOT5_MAIN_H 11 | 12 | #include "ascot5.h" 13 | #include "simulate.h" 14 | 15 | int prepare_markers( 16 | sim_data* sim, int n_tot, input_particle* pin, particle_state** pout, 17 | int* nprts); 18 | 19 | int write_rungroup(sim_data* sim, particle_state* ps, int n_tot, char* qid); 20 | 21 | int offload_and_simulate( 22 | sim_data* sim, int n_tot, int n_proc, particle_state* pin, 23 | int* n_gather, particle_state** pout); 24 | 25 | int write_output(sim_data* sim, particle_state* ps_gathered, int n_tot); 26 | 27 | void print_marker_summary(particle_state* ps, int n_tot); 28 | 29 | #endif 30 | -------------------------------------------------------------------------------- /environment-osx.yaml: -------------------------------------------------------------------------------- 1 | name: ascot-osx 2 | channels: 3 | - conda-forge 4 | dependencies: 5 | - c-compiler 6 | - make 7 | - glib 8 | - python>=3.10 9 | - hdf5 10 | - zlib 11 | - setuptools 12 | - pip 13 | - ipython 14 | - numpy 15 | - scipy 16 | - h5py 17 | - xmlschema 18 | - unyt 19 | - wurlitzer 20 | - matplotlib 21 | - pyvista 22 | - freeqdsk 23 | - doxygen 24 | - ruff 25 | - ipykernel 26 | - pandoc 27 | - sphinx==6.* 28 | - numpydoc 29 | - nbsphinx 30 | - nbformat 31 | - breathe 32 | - sphinxcontrib-bibtex 33 | - sphinx-rtd-theme 34 | - sphinx-gallery 35 | - sphinx-design 36 | - sphinxcontrib-mermaid 37 | - clang==17.* 38 | - clang-tools==17* 39 | - libclang==17.* 40 | - llvm-openmp==17.* 41 | - pylint 42 | - pip: 43 | - libclang==17.* 44 | - desc-opt 45 | - netCDF4 46 | # PR branch for macos + clang-16+ support 47 | - ctypeslib2 @ git+https://github.com/dgarnier/ctypeslib.git@anon_union_macos 48 | -------------------------------------------------------------------------------- /src/simulate/simulate_gc_adaptive.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file simulate_gc_adaptive.h 3 | * @brief Header file for simulate_gc_adaptive.c 4 | */ 5 | #ifndef SIMULATE_GC_ADAPTIVE_H 6 | #define SIMULATE_GC_ADAPTIVE_H 7 | 8 | #include "../ascot5.h" 9 | #include "../simulate.h" 10 | #include "../particle.h" 11 | 12 | typedef struct { 13 | unsigned int crossed_once : 1; 14 | unsigned int crossed_twice : 1; 15 | unsigned int first_ppar : 1; 16 | } Crossing; 17 | 18 | typedef struct { 19 | /** Acceleration factor. */ 20 | real acc[NSIMD]; 21 | 22 | /** Orbit time [s]. */ 23 | real orbittime[NSIMD]; 24 | 25 | /** Collision frequency [1/s]. */ 26 | real collfreq[NSIMD]; 27 | 28 | /** Storage for OMP crossing data. */ 29 | Crossing cross[NSIMD]; 30 | } Acceleration; 31 | 32 | void recalculate_acceleration( 33 | Acceleration* acc, sim_data* sim, particle_simd_gc* p, particle_simd_gc* p0); 34 | 35 | void simulate_gc_adaptive(particle_queue* pq, sim_data* sim); 36 | 37 | #endif 38 | -------------------------------------------------------------------------------- /a5py/m3_template/code_parameters/input_physics.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 131024 5 | 6 | 7 | 1 8 | 9 | 10 | 10 11 | 12 | 13 | 2 14 | 15 | 16 | 1.5 17 | 18 | 19 | public 20 | 21 | 22 | iter 23 | 24 | 25 | user_environment_variable 26 | 27 | 28 | iter 29 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /src/gctransform.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file gctransform.h 3 | * @brief Header file for gctransform.c 4 | */ 5 | #ifndef GCTRANSFORM_H 6 | #define GCTRANSFORM_H 7 | 8 | #include "ascot5.h" 9 | 10 | 11 | void gctransform_setorder(int order); 12 | 13 | DECLARE_TARGET_SIMD 14 | void gctransform_particle2guidingcenter( 15 | real mass, real charge, real* B_dB, 16 | real r, real phi, real z, real pr, real pphi, real pz, 17 | real* R, real* Phi, real* Z, real* ppar, real* mu, real* zeta); 18 | 19 | DECLARE_TARGET_SIMD 20 | void gctransform_guidingcenter2particle( 21 | real mass, real charge, real* B_dB, 22 | real R, real Phi, real Z, real ppar, real mu, real zeta, 23 | real* r, real* phi, real* z, real* pparprt, real* muprt, real* zetaprt); 24 | 25 | DECLARE_TARGET_SIMD 26 | void gctransform_pparmuzeta2prpphipz(real mass, real charge, real* B_dB, 27 | real phi, real ppar, real mu, real zeta, 28 | real* pr, real* pphi, real* pz); 29 | 30 | #endif 31 | -------------------------------------------------------------------------------- /src/Efield/E_1DS.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @author Joona Kontula joona.kontula@aalto.fi 3 | * @file E_1DS.h 4 | * @brief Header file for E_1DS.c 5 | * 6 | * Contains declaration of E_1DS_field_offload_data and E_1DS_field_data 7 | * structs. 8 | */ 9 | #ifndef E_1DS_H 10 | #define E_1DS_H 11 | #include "../offload.h" 12 | #include "../ascot5.h" 13 | #include "../error.h" 14 | #include "../spline/interp.h" 15 | #include "../B_field.h" 16 | 17 | /** 18 | * @brief 1D spline electric field parameters on the target 19 | */ 20 | typedef struct { 21 | interp1D_data dV; /**< dV_drho 1D linear interpolation struct */ 22 | } E_1DS_data; 23 | 24 | int E_1DS_init(E_1DS_data* data, int nrho, real rhomin, real rhomax, real reff, 25 | real* dvdrho); 26 | void E_1DS_free(E_1DS_data* data); 27 | void E_1DS_offload(E_1DS_data* data); 28 | GPU_DECLARE_TARGET_SIMD_UNIFORM(Edata,Bdata) 29 | a5err E_1DS_eval_E(real E[3], real r, real phi, real z, E_1DS_data* Edata, 30 | B_field_data* Bdata); 31 | DECLARE_TARGET_END 32 | #endif 33 | -------------------------------------------------------------------------------- /src/unit_tests/test_wall_2d.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @file test_wall_2d.c 3 | * @brief Test program for 2D wall collision functions 4 | */ 5 | #include 6 | #include 7 | #include "../ascot5.h" 8 | #include "../wall/wall_2d.h" 9 | 10 | int main(int argc, char** argv) { 11 | real wall_r[] = {4.7, 6.1, 6.1, 8.4, 8.4, 7.6, 6.1, 4.8, 4.0, 4.0, 4.7, 12 | 4.7}; 13 | real wall_z[] = {-4.25, -4.25, -3.5, -1.1, 1.75, 2.5, 3.6, 3.6, 2.4, -1.5, 14 | -3.25, -4.25}; 15 | 16 | wall_2d_data wdata; 17 | wdata.n = 12; 18 | wdata.wall_r = wall_r; 19 | wdata.wall_z = wall_z; 20 | 21 | srand(0); 22 | 23 | real rmin = 0; 24 | real rmax = 10; 25 | real zmin = -6; 26 | real zmax = 6; 27 | 28 | int i; 29 | for(i = 0; i < 1000; i++) { 30 | real r = ((real)rand()/(real)RAND_MAX)*(rmax-rmin) + rmin; 31 | real z = ((real)rand()/(real)RAND_MAX)*(zmax-zmin) + zmin; 32 | int inside = wall_2d_inside(r, z, &wdata); 33 | printf("%lf, %lf, %d\n", r, z, inside); 34 | } 35 | 36 | return 0; 37 | } 38 | -------------------------------------------------------------------------------- /a5py/exceptions.py: -------------------------------------------------------------------------------- 1 | """Contains definitions of this package's exceptions. 2 | """ 3 | 4 | class AscotIOException(Exception): 5 | """Raised when there is an internal error in `Ascot5IO`. 6 | 7 | This exception should be raised in cases where the issue is most certainly 8 | a bug in code or inconsistent HDF5 file. 9 | """ 10 | pass 11 | 12 | class AscotNoDataException(Exception): 13 | """Raised when required input or output is not present. 14 | 15 | This exception should be raised when user tries to query input or results 16 | that is not present. Other case is when using methods that require the 17 | presence of certain input or output data (e.g. when plotting orbits but 18 | orbit data is not present). 19 | """ 20 | pass 21 | 22 | class AscotInitException(Exception): 23 | """Raised when there is an issue with data initialized by `Ascot`. 24 | 25 | This exception should be raised whenever there is an issue with `libascot` 26 | or any related data. 27 | """ 28 | pass 29 | 30 | class AscotUnitWarning(UserWarning): 31 | """Warning raised when quantities are provided without units. 32 | """ 33 | pass 34 | -------------------------------------------------------------------------------- /a5py/_nonfunctional/imas_container/Containerfile: -------------------------------------------------------------------------------- 1 | # Start from the specified base image 2 | FROM gitlab.eufus.psnc.pl:5050/containerization/imas/imas-installer/al:DD-4.0.0_AL-5.4.1-UDA-2.8.1-UDA-PLUGIN-1.5.0 3 | 4 | # Set the maintainer label 5 | LABEL maintainer="Simppa Akaslompolo " 6 | 7 | RUN ["dnf", "install", "-y", "hdf5-devel", "redhat-rpm-config", "emacs-nox"] 8 | 9 | WORKDIR /ascot 10 | RUN ["git", "clone", "https://github.com/ascot4fusion/ascot5.git"] 11 | 12 | WORKDIR ascot5 13 | 14 | RUN ["git", "checkout", "feature/54-imasify-ascot5-rebased"] 15 | 16 | 17 | RUN ["make", "libascot", "-j"] 18 | 19 | RUN ["pip", "install", "-e", "."] 20 | 21 | RUN ["pip", "install", "ipython"] 22 | 23 | ADD runexample.py runexample.py 24 | 25 | RUN ["ipython", "runexample.py" ] 26 | 27 | # podman build --format docker -t imas-ascot:latest . 28 | # podman run --rm -it localhost/imas-ascot:latest /bin/bash 29 | 30 | # podman build --format docker -t imas-ascot:latest . && podman run --rm -it localhost/imas-ascot:latest ipython getExample.py 31 | 32 | RUN mkdir -p /ids/ 33 | 34 | ADD getExample.py getExample.py 35 | 36 | RUN ipython getExample.py 37 | -------------------------------------------------------------------------------- /a5py/testascot/tutorials.py: -------------------------------------------------------------------------------- 1 | import os 2 | import glob 3 | import subprocess 4 | 5 | import nbformat 6 | from nbconvert.preprocessors import ExecutePreprocessor, CellExecutionError 7 | 8 | # Stores results in existing notebook 9 | inplace = True 10 | 11 | os.chdir("../../doc/tutorials/") 12 | notebooks = glob.glob("*.ipynb") 13 | 14 | preprocessor = ExecutePreprocessor(timeout=600) 15 | errors = {} 16 | for nb in notebooks: 17 | # Skip notebooks that are not standalone 18 | if nb in []: continue 19 | print(f"Processing notebook {nb}") 20 | subprocess.run(["rm", "-f", "ascot.h5"]) 21 | with open(nb) as f: 22 | nbin = nbformat.read(f, nbformat.NO_CONVERT) 23 | try: 24 | nbout,_ = preprocessor.preprocess(nbin) 25 | if inplace: 26 | with open(nb, "w", encoding="utf-8") as f: 27 | nbformat.write(nbout, f) 28 | except CellExecutionError as err: 29 | errors[nb] = err 30 | 31 | subprocess.run(["rm", "-f", "ascot.h5"]) 32 | if len(errors) > 0: 33 | print("\nFollowing exceptions were logged:\n") 34 | for f,e in errors.items(): 35 | print(f + ":\n") 36 | print(e) 37 | print("") 38 | raise Exception("Failed to run tutorials.") 39 | 40 | print("Tutorials completed without errors") 41 | -------------------------------------------------------------------------------- /src/print.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file print.h 3 | * @brief Macros for printing console output 4 | */ 5 | #ifndef PRINT_H 6 | #define PRINT_H 7 | 8 | #include 9 | 10 | /** 11 | * @brief Versbosity levels and definitions 12 | * 13 | * DEBUG, NORMAL, and MINIMAL are levels that can be specified and the rest are 14 | * used to specify to which levels operations belongs to. 15 | */ 16 | enum VERBOSE_RANK { 17 | VERBOSE_DEBUG = 2, /**< For debugging purposes */ 18 | VERBOSE_NORMAL = 1, /**< For normal output */ 19 | VERBOSE_MINIMAL = 0, /**< Only print version and simulation status */ 20 | VERBOSE_IO = 1 /**< Flag for IO operations */ 21 | }; 22 | 23 | /** 24 | * @brief Verbose level 25 | */ 26 | extern const char VERBOSE_LEVEL; 27 | 28 | /** 29 | * @brief Print to standard output 30 | */ 31 | #define print_out(v,...) { if(VERBOSE_LEVEL >= (v)) printf(__VA_ARGS__); } 32 | 33 | /** 34 | * @brief Print to standard output only for root process 35 | */ 36 | #define print_out0(v,rank,root,...) { \ 37 | if(VERBOSE_LEVEL >= (v) &&(rank)==(root)) printf(__VA_ARGS__); } 38 | 39 | /** 40 | * @brief Print to standard error 41 | */ 42 | #define print_err(...) fprintf(stderr,__VA_ARGS__) 43 | 44 | #endif 45 | -------------------------------------------------------------------------------- /src/unit_tests/test_plasma_1DS.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @file test_plasma_1DS.c 3 | * @brief Test program for 1D plasma evaluation functions 4 | */ 5 | #include 6 | #include 7 | #include "../ascot5.h" 8 | #include "../plasma_1DS.h" 9 | #include "../hdf5io/hdf5_plasma.h" 10 | #include "../hdf5.h" 11 | #include "../hdf5io/hdf5_helpers.h" 12 | #include "../hdf5_hl.h" 13 | #include "../math.h" 14 | 15 | int main(int argc, char** argv) { 16 | plasma_1DS_offload_data offload_data; 17 | real* offload_array; 18 | hid_t f = hdf5_open("ascot.h5"); 19 | hdf5_plasma_init_offload_1DS(f, &offload_data, &offload_array); 20 | 21 | plasma_1DS_data data; 22 | plasma_1DS_init(&data, &offload_data, offload_array); 23 | 24 | int nrho = 1000; 25 | real* rho = (real*) malloc(nrho * sizeof(real)); 26 | math_linspace(rho, 0.0, 1.0, nrho); 27 | real denss[data.n_species]; 28 | real temps[data.n_species]; 29 | for (int i = 0; i < nrho; i++) { 30 | printf("%le ", rho[i]); 31 | plasma_1DS_eval_densandtemp(denss, temps, rho[i], &data); 32 | for (int species = 0; species < data.n_species; species++) { 33 | printf("%le %le ", temps[species], denss[species]); 34 | } 35 | printf("\n"); 36 | } 37 | plasma_1DS_free(&data); 38 | 39 | return 0; 40 | } 41 | -------------------------------------------------------------------------------- /a5py/m3_template/workflow.ymmsl: -------------------------------------------------------------------------------- 1 | ymmsl_version: v0.1 2 | 3 | model: 4 | name: ascot_test 5 | components: 6 | macro: macro 7 | ascot: ascot_implementation 8 | conduits: 9 | macro.equilibrium_3d_out: ascot.equilibrium_3d_in 10 | macro.equilibrium_out: ascot.equilibrium_in 11 | macro.core_profiles_out: ascot.core_profiles_in 12 | macro.distribution_sources_out: ascot.distribution_sources_in 13 | macro.wall2d_out: ascot.wall2d_in 14 | macro.wall3d_out: ascot.wall3d_in 15 | ascot.distributions_out: macro.distributions_in 16 | 17 | implementations: 18 | macro: 19 | executable: python 20 | args: 21 | - ${TEST_DIR}/macro/test_macro.py 22 | ascot_implementation: 23 | execution_model: openmpi 24 | executable: python 25 | args: 26 | - ${TEST_DIR}/micro/test_micro.py 27 | 28 | resources: 29 | macro: 30 | threads: 1 31 | ascot: 32 | mpi_processes: 1 33 | #mpi_processes: 4 34 | # threads: 1 35 | 36 | settings: 37 | macro.t_max: 1.0 38 | macro.dt: 1.0 39 | muscle_remote_log_level: DEBUG 40 | # CHANGE IT TO YOUR PATH! 41 | code_parameters_file: /gss_efgw_work/work/g2diy/git_repos/psnc_git/imasification/ascot5_interface/m3_template/code_parameters/input_physics.xml -------------------------------------------------------------------------------- /a5py/m3_template/workflow_mpi.ymmsl: -------------------------------------------------------------------------------- 1 | ymmsl_version: v0.1 2 | 3 | model: 4 | name: ascot_test 5 | components: 6 | macro: macro 7 | ascot: ascot_implementation 8 | conduits: 9 | macro.equilibrium_3d_out: ascot.equilibrium_3d_in 10 | macro.equilibrium_out: ascot.equilibrium_in 11 | macro.core_profiles_out: ascot.core_profiles_in 12 | macro.distribution_sources_out: ascot.distribution_sources_in 13 | macro.wall2d_out: ascot.wall2d_in 14 | macro.wall3d_out: ascot.wall3d_in 15 | ascot.distributions_out: macro.distributions_in 16 | 17 | implementations: 18 | macro: 19 | executable: python 20 | args: 21 | - ${TEST_DIR}/macro/test_macro.py 22 | ascot_implementation: 23 | execution_model: openmpi 24 | executable: python 25 | args: 26 | - ${TEST_DIR}/micro/test_micro.py 27 | 28 | resources: 29 | macro: 30 | threads: 1 31 | ascot: 32 | #mpi_processes: 1 33 | mpi_processes: 4 34 | # threads: 1 35 | 36 | settings: 37 | macro.t_max: 1.0 38 | macro.dt: 1.0 39 | muscle_remote_log_level: DEBUG 40 | # CHANGE IT TO YOUR PATH! 41 | code_parameters_file: /gss_efgw_work/work/g2diy/git_repos/psnc_git/imasification/ascot5_interface/m3_template/code_parameters/input_physics.xml -------------------------------------------------------------------------------- /doc/papi/a5py.rst: -------------------------------------------------------------------------------- 1 | ========== 2 | Python API 3 | ========== 4 | 5 | .. rubric:: ``a5py`` 6 | 7 | .. automodule:: a5py 8 | 9 | .. toctree:: 10 | :hidden: 11 | 12 | a5py.ascot5io 13 | a5py.ascotpy 14 | a5py.templates 15 | a5py.physlib 16 | a5py.testascot 17 | a5py.routines 18 | a5py.gui 19 | 20 | .. autosummary:: 21 | 22 | a5py.ascot5io 23 | a5py.ascotpy 24 | a5py.templates 25 | a5py.physlib 26 | a5py.testascot 27 | a5py.routines 28 | a5py.gui 29 | 30 | .. rubric:: Important classes 31 | 32 | .. autosummary:: 33 | :nosignatures: 34 | 35 | ~a5py.Ascot 36 | ~a5py.ascot5io.Ascot5IO 37 | ~a5py.ascot5io.RunGroup 38 | ~a5py.ascot5io.AfsiGroup 39 | ~a5py.ascot5io.BBNBIGroup 40 | ~a5py.routines.afsi5.Afsi 41 | ~a5py.routines.biosaw5.BioSaw 42 | ~a5py.routines.markergen.MarkerGenerator 43 | 44 | .. rubric:: ``Ascot`` 45 | 46 | .. autoclass:: a5py.Ascot 47 | :members: 48 | :inherited-members: 49 | 50 | .. autoclass:: a5py.routines.afsi5.Afsi 51 | :members: 52 | :inherited-members: 53 | 54 | .. autoclass:: a5py.routines.biosaw5.BioSaw 55 | :members: 56 | :inherited-members: 57 | 58 | .. autoclass:: a5py.routines.markergen.MarkerGenerator 59 | :members: 60 | :inherited-members: 61 | 62 | .. rubric:: ``exceptions`` 63 | 64 | .. automodule:: a5py.exceptions 65 | :members: 66 | -------------------------------------------------------------------------------- /a5py/ascot5io/reaction.py: -------------------------------------------------------------------------------- 1 | """Fusion reaction data from AFSI. 2 | """ 3 | import numpy as np 4 | import h5py 5 | import unyt 6 | 7 | from .coreio import fileapi 8 | from .coreio.treedata import DataContainer 9 | 10 | class Reaction(DataContainer): 11 | """Class contining the stored fusion reaction data in AFSI run. 12 | """ 13 | 14 | def read(self): 15 | """Read raw reaction data to a dictionary. 16 | """ 17 | out = {} 18 | with self as f: 19 | for key in f: 20 | out[key] = f[key][:] 21 | 22 | return out 23 | 24 | def get(self): 25 | """Return reaction information. 26 | 27 | Returns 28 | ------- 29 | m1 : float 30 | Mass of the first reactant. 31 | m2 : float 32 | Mass of the second reactant. 33 | mprod1 : float 34 | Mass of the first product. 35 | mprod2 : float 36 | Mass of the second product. 37 | q : float 38 | Energy released. 39 | """ 40 | with self as f: 41 | m1 = f["m1"][:][0] * unyt.amu 42 | m2 = f["m2"][:][0] * unyt.amu 43 | mprod1 = f["mprod1"][:][0] * unyt.amu 44 | mprod2 = f["mprod2"][:][0] * unyt.amu 45 | q = f["q"][:][0] * unyt.eV 46 | 47 | return m1, m2, mprod1, mprod2, q 48 | -------------------------------------------------------------------------------- /src/libascot_mem.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @file libascot_mem.c 3 | * @brief Provides memory de/allocation routines for the libascot 4 | */ 5 | #include 6 | #include "libascot_mem.h" 7 | #include "particle.h" 8 | 9 | /** 10 | * @brief A routine to allocate an array of input particles 11 | * 12 | * @param nmrk number of markers for which space is allocated 13 | * 14 | * @return pointer to the allocated array 15 | */ 16 | input_particle* libascot_allocate_input_particles(int nmrk) { 17 | return (input_particle*) malloc(nmrk * sizeof(input_particle) ); 18 | } 19 | 20 | /** 21 | * @brief A routine to allocate an array of particle states 22 | * 23 | * @param nmrk number of markers for which space is allocated 24 | * 25 | * @return pointer to the allocated array 26 | */ 27 | particle_state* libascot_allocate_particle_states(int nmrk) { 28 | return (particle_state*) malloc(nmrk * sizeof(particle_state) ); 29 | } 30 | 31 | /** 32 | * @brief A routine to allocate an array of reals 33 | * 34 | * @param size size of the array 35 | * 36 | * @return pointer to the allocated array 37 | */ 38 | real* libascot_allocate_reals(size_t size) { 39 | return ( real* ) malloc( size * sizeof(real) ); 40 | } 41 | 42 | 43 | /** 44 | * @brief A wrapper to C stdlib free() 45 | * 46 | * @param arr array to be freed 47 | */ 48 | void libascot_deallocate(void *arr) { 49 | free(arr); 50 | } 51 | -------------------------------------------------------------------------------- /src/mpi_interface.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file mpi_interface.h 3 | * @brief Header file for mpi_interface.c 4 | */ 5 | #ifndef MPI_INTERFACE_H 6 | #define MPI_INTERFACE_H 7 | 8 | #ifdef MPI 9 | #include 10 | #endif 11 | #include "diag.h" 12 | #include "particle.h" 13 | 14 | /** @brief ASCOT integer in MPI standard */ 15 | #define mpi_type_integer MPI_LONG 16 | /** @brief ASCOT real in MPI standard */ 17 | #define mpi_type_real MPI_DOUBLE 18 | /** @brief ASCOT error in MPI standard */ 19 | #define mpi_type_a5err MPI_UNSIGNED_LONG_LONG 20 | 21 | void mpi_interface_barrier(); 22 | void mpi_interface_init(int argc, char** argv, int* mpi_rank, int* mpi_size, 23 | int* mpi_root); 24 | void mpi_interface_finalize(int err); 25 | void mpi_my_particles(int* start_index, int* n, int ntotal, int mpi_rank, 26 | int mpi_size); 27 | void mpi_gather_particlestate(particle_state* ps, particle_state** psgathered, 28 | int* ngathered, int ntotal, int mpi_rank, 29 | int mpi_size, int mpi_root); 30 | void mpi_gather_particlestate( 31 | particle_state* ps, particle_state** ps_gather, int* n_gather, int n_tot, 32 | int mpi_rank, int mpi_size, int mpi_root); 33 | void mpi_gather_diag(diag_data* data, int ntotal, int mpi_rank, int mpi_size, 34 | int mpi_root); 35 | 36 | #endif 37 | -------------------------------------------------------------------------------- /src/wall/wall_2d.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file wall_2d.h 3 | * @brief Header file for wall_2d.c 4 | */ 5 | #ifndef WALL_2D_H 6 | #define WALL_2D_H 7 | #include "../ascot5.h" 8 | #include "../offload.h" 9 | 10 | /** 11 | * @brief 2D wall data parameters 12 | * 13 | * Note: The start and end point of wall polygon does not have to concide. 14 | */ 15 | typedef struct { 16 | int n; /**< Number of points in the wall polygon */ 17 | real* wall_r; /**< R coordinates for the wall polygon points */ 18 | real* wall_z; /**< z coordinates for the wall polygon points */ 19 | int* flag; /**< Array of wall element flags */ 20 | } wall_2d_data; 21 | 22 | int wall_2d_init(wall_2d_data* data, int nelements, real* r, real* z, 23 | int* flag); 24 | void wall_2d_free(wall_2d_data* data); 25 | void wall_2d_offload(wall_2d_data* data); 26 | GPU_DECLARE_TARGET_SIMD_UNIFORM(w) 27 | int wall_2d_inside(real r, real z, wall_2d_data* w); 28 | DECLARE_TARGET_END 29 | GPU_DECLARE_TARGET_SIMD_UNIFORM(w) 30 | int wall_2d_hit_wall(real r1, real phi1, real z1, real r2, real phi2, real z2, 31 | wall_2d_data* w, real* w_coll); 32 | DECLARE_TARGET_END 33 | GPU_DECLARE_TARGET_SIMD_UNIFORM(w) 34 | int wall_2d_find_intersection(real r1, real z1, real r2, real z2, 35 | wall_2d_data* w, real* w_coll); 36 | DECLARE_TARGET_END 37 | #endif 38 | -------------------------------------------------------------------------------- /.setcdllascot2py.py: -------------------------------------------------------------------------------- 1 | """Modifies ascot2py.py so that it first try to find libascot.so using relative 2 | path (if installing from the source) and only then from LD_LIBRARY_PATH. 3 | """ 4 | import fileinput 5 | import sys 6 | 7 | for line in fileinput.input("src/ascot2py.py", inplace=True): 8 | if line.strip() == "_libraries['libascot.so'] = ctypes.CDLL('libascot.so')": 9 | sys.stdout.write( 10 | "# Try to locate libascot.so from ../../build/ or LD_LIBRARY_PATH\n" 11 | "from pathlib import Path\n" 12 | "err = 0\n" 13 | "libpath = str(Path(__file__).absolute().parent.parent.parent) \\\n" 14 | " + \"/build/libascot.so\"\n" 15 | "try:\n" 16 | " _libraries['libascot.so'] = ctypes.CDLL(libpath)\n" 17 | "except OSError as error:\n" 18 | " err = error\n" 19 | "if err:\n" 20 | " if not 'libascot.so' in str(err): raise ImportError(str(err))\n" 21 | "if 'libascot.so' not in _libraries:\n" 22 | " err = 0\n" 23 | " try:\n" 24 | " _libraries['libascot.so'] = ctypes.CDLL('libascot.so')\n" 25 | " except OSError as error:\n" 26 | " err = error\n" 27 | " if err: raise ImportError(str(err))\n" 28 | "\n" 29 | ) 30 | else: 31 | sys.stdout.write(line) 32 | -------------------------------------------------------------------------------- /a5py/_nonfunctional/read_from_imas.py: -------------------------------------------------------------------------------- 1 | # coding: utf-8 2 | 3 | # For Simppa at least, following recipe worked to get the below working: 4 | # 1. in ascot5.yml, set the python version: python=3.6, and create the environment 5 | # 2. module load imasenv 6 | # 3. conda activate ascot5 7 | # the below works. 8 | 9 | 10 | import a5py.ascot5io.imas 11 | import a5py.ascot5io.wall_2D 12 | import a5py.ascot5io.wall_3D 13 | import a5py.ascot5io.B_STS 14 | w2d=a5py.ascot5io.imas.wall_2d() 15 | w3d=a5py.ascot5io.imas.wall_3d() 16 | bst=a5py.ascot5io.imas.B_STS() 17 | # Gateway 18 | # wdict=w2d.read("g2jvarje","test","3",92436,272) 19 | 20 | # ITER SDCC 21 | print("Reading 3D wall") 22 | wdict3=w3d.read("akaslos","mywall","3",11,11) 23 | 24 | print("Reading 2D wall") 25 | wdict=w2d.read("akaslos","test","3",92436,272) 26 | 27 | print("Reading 3D field") 28 | #b3ddict = bst.read("akaslos","ggdtest","3",16,2) 29 | b3ddict = bst.read("akaslos","ggdtest","3",32,1) 30 | 31 | print("Writing to hdf5") 32 | a5py.ascot5io.wall_3D.write_hdf5('from_imas.h5',**wdict3) 33 | a5py.ascot5io.wall_2D.write_hdf5('from_imas.h5',**wdict) 34 | a5py.ascot5io.B_STS.write_hdf5('from_imas.h5',**b3ddict) 35 | 36 | 37 | print("Writing to IDS") 38 | #bst.write( b3ddict, "akaslos", "ggdtest", "3", 32, 1, metadata={'comment':'written by read_from_imas.py'}) 39 | bst.write( b3ddict, "akaslos", "ggdtest", "3", 32, 2, metadata={'comment':'written by read_from_imas.py'}) 40 | 41 | -------------------------------------------------------------------------------- /pyproject.toml: -------------------------------------------------------------------------------- 1 | [build-system] 2 | requires = ["setuptools>59", "setuptools-git-versioning"] 3 | build-backend = "setuptools.build_meta" 4 | 5 | [tool.setuptools-git-versioning] 6 | enabled = true 7 | version_file = "src/VERSION" 8 | 9 | [project] 10 | name = "a5py" 11 | dynamic = ["version"] 12 | description = "ASCOT5 is a high-performance orbit-following code for fusion plasma physics and engineering" 13 | authors = [ 14 | {name = "Konsta Särkimäki", email = "konsta.sarkimaki@gmail.com"}, 15 | ] 16 | readme = "README.rst" 17 | license = {text = "LGPL-3.0-or-later"} 18 | requires-python = ">=3.10" 19 | dependencies = [ 20 | "numpy", 21 | "scipy", 22 | "h5py", 23 | "unyt", 24 | "wurlitzer", 25 | "xmlschema", 26 | ] 27 | 28 | [project.optional-dependencies] 29 | mpi = [ 30 | "mpi4py", 31 | ] 32 | 33 | [tool.setuptools.packages.find] 34 | include = [ 35 | 'a5py', 36 | 'a5py.*', 37 | ] 38 | 39 | [project.urls] 40 | Homepage = "https://github.com/ascot4fusion/ascot5" 41 | Documentation = "https://ascot4fusion.github.io/ascot5/" 42 | Repository = "https://github.com/ascot4fusion/ascot5.git" 43 | "Bug Tracker" = "https://github.com/ascot4fusion/ascot5/issues" 44 | Changelog = "https://github.com/ascot4fusion/ascot5/releases" 45 | 46 | [tool.setuptools] 47 | zip-safe = false 48 | script-files=[ 49 | 'bin/a5manage', 50 | 'bin/a5editoptions', 51 | 'bin/a5combine', 52 | 'bin/a5gui', 53 | 'bin/a5update', 54 | ] 55 | -------------------------------------------------------------------------------- /a5py/_nonfunctional/wrapper_test.py: -------------------------------------------------------------------------------- 1 | from distsource_fun import * 2 | import imas 3 | from imas.imasdef import MDSPLUS_BACKEND 4 | from imas.imasdef import CLOSEST_SAMPLE 5 | 6 | #mrkr.read("g2diy","test","3",92436,306) 7 | #w2d.read("g2jvarje","test","3",92436,272) 8 | #w3d.read("g2diy","mywall","3",201,101) 9 | #bsts.read("g2diy","ggdtest","3",32,3) 10 | 11 | 12 | def get_ids(idsname,user,database,shot,run,time): 13 | DB = imas.DBEntry(MDSPLUS_BACKEND, database, shot, run, user_name=user) 14 | DB.open() 15 | ids = DB.get_slice(idsname, time, CLOSEST_SAMPLE) 16 | DB.close() 17 | return ids 18 | 19 | idsname='distribution_sources' 20 | uname='g2diy' 21 | dbname='test' 22 | shot=92436 23 | run=306 24 | time=0.0 25 | distr_sour=get_ids(idsname,uname,dbname,shot,run,time) 26 | 27 | idsname='wall' 28 | uname='g2jvarje' 29 | dbname='test' 30 | shot=92436 31 | run=272 32 | time=0.0 33 | wall2d=get_ids(idsname,uname,dbname,shot,run,time) 34 | 35 | 36 | idsname='wall' 37 | uname='g2diy' 38 | dbname='mywall' 39 | shot=201 40 | run=101 41 | time=0.0 42 | wall3d=get_ids(idsname,uname,dbname,shot,run,time) 43 | 44 | idsname='equilibrium' 45 | uname='g2diy' 46 | dbname='ggdtest' 47 | shot=32 48 | run=3 49 | time=0.0 50 | equil_b3f=get_ids(idsname,uname,dbname,shot,run,time) 51 | 52 | print('after_read_ids') 53 | 54 | print(type(distr_sour)) 55 | print('number of sources after read', len(distr_sour.source)) 56 | 57 | 58 | distsource_run(distr_sour,wall2d,wall3d,equil_b3f) 59 | 60 | 61 | -------------------------------------------------------------------------------- /src/neutral/N0_1D.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file N0_1D.h 3 | * @brief Header file for N0_1D.c 4 | */ 5 | #ifndef N0_1D_H 6 | #define N0_1D_H 7 | #include "../ascot5.h" 8 | #include "../offload.h" 9 | #include "../linint/linint.h" /* for 1D interpolation routines */ 10 | 11 | /** 12 | * @brief 1D neutral parameters on the target 13 | */ 14 | typedef struct { 15 | int n_species; /**< Number of neutral species */ 16 | int* anum; /**< Neutral species mass number */ 17 | int* znum; /**< Neutral species charge number */ 18 | int* maxwellian; /**< Is species distribution Maxwellian or 19 | monoenergetic */ 20 | linint1D_data* n0; /**< Density interpolation struct for each species */ 21 | linint1D_data* t0; /**< Temperature intepolation struct for each species */ 22 | } N0_1D_data; 23 | 24 | int N0_1D_init(N0_1D_data* data, int n_rho, real rho_min, real rho_max, 25 | int n_species, int* anum, int* znum, int* maxwellian, 26 | real* density, real* temperature); 27 | void N0_1D_free(N0_1D_data* data); 28 | void N0_1D_offload(N0_1D_data* data); 29 | DECLARE_TARGET_SIMD_UNIFORM(ndata) 30 | a5err N0_1D_eval_n0(real* n0, real rho, N0_1D_data* ndata); 31 | DECLARE_TARGET_SIMD_UNIFORM(ndata) 32 | a5err N0_1D_eval_t0(real* t0, real rho, N0_1D_data* ndata); 33 | DECLARE_TARGET_SIMD_UNIFORM(ndata) 34 | int N0_1D_get_n_species(N0_1D_data* ndata); 35 | #endif 36 | -------------------------------------------------------------------------------- /src/neutral.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file neutral.h 3 | * @brief Header file for neutral.c 4 | * 5 | * Contains a list declaring all neutral_types, and declaration of 6 | * neutral_offload_data and neutral_data structs. 7 | */ 8 | #ifndef NEUTRAL_H 9 | #define NEUTRAL_H 10 | 11 | #include "ascot5.h" 12 | #include "error.h" 13 | #include "neutral/N0_1D.h" 14 | #include "neutral/N0_3D.h" 15 | 16 | /** 17 | * @brief Neutral data types 18 | */ 19 | typedef enum neutral_type { 20 | neutral_type_1D, /**< Linearly-interpolated 1D neutral data */ 21 | neutral_type_3D, /**< Linearly-interpolated 3D neutral data */ 22 | } neutral_type; 23 | 24 | /** 25 | * @brief Neutral simulation data 26 | * 27 | * The intended usage is that only single type of data is used at a time. This 28 | * is declared using the `type` field. 29 | */ 30 | typedef struct { 31 | neutral_type type; /**< Neutral data type wrapped by this struct */ 32 | N0_1D_data N01D; /**< 1D field or NULL if not active */ 33 | N0_3D_data N03D; /**< 3D field or NULL if not active */ 34 | } neutral_data; 35 | 36 | void neutral_free(neutral_data* data); 37 | void neutral_offload(neutral_data* data); 38 | DECLARE_TARGET_SIMD_UNIFORM(ndata) 39 | a5err neutral_eval_n0(real* n0, real rho, real r, real phi, real z, real t, 40 | neutral_data* ndata); 41 | DECLARE_TARGET_SIMD_UNIFORM(ndata) 42 | a5err neutral_eval_t0(real* t0, real rho, real r, real phi, real z, real t, 43 | neutral_data* ndata); 44 | DECLARE_TARGET_SIMD_UNIFORM(ndata) 45 | int neutral_get_n_species(neutral_data* ndata); 46 | #endif 47 | -------------------------------------------------------------------------------- /.github/workflows/build.yaml: -------------------------------------------------------------------------------- 1 | name: (Reusable) Build 2 | on: [workflow_call] 3 | 4 | jobs: 5 | 6 | Build-Code: 7 | if: always() || failure() 8 | runs-on: ubuntu-latest 9 | defaults: 10 | run: 11 | shell: bash -el {0} 12 | steps: 13 | - uses: actions/checkout@v4 14 | 15 | - uses: conda-incubator/setup-miniconda@v3 16 | with: 17 | auto-update-conda: true 18 | python-version: "3.10" 19 | environment-file: environment-dev.yaml 20 | activate-environment: ascot-dev 21 | auto-activate-base: false 22 | 23 | - name: Make ascot5_main with MPI 24 | run: make ascot5_main MPI=1 -j 25 | 26 | - name: Make clean 27 | run: make clean 28 | 29 | - name: Make ascot5_main without MPI 30 | run: make ascot5_main CC=h5pcc -j 31 | 32 | - name: Make libascot.so 33 | run: make libascot CC=h5pcc 34 | 35 | - name: Make BBNBI 36 | run: make bbnbi5 CC=h5pcc 37 | 38 | - name: Make ascot2py 39 | run: make ascot2py.py CC=h5pcc 40 | 41 | - name: Set permissions and pack 42 | run: | 43 | cd ./build 44 | chmod +x ascot5_main bbnbi5 45 | tar -cf code.tar ascot5_main bbnbi5 libascot.so 46 | cd .. 47 | 48 | - name: Upload code 49 | uses: actions/upload-artifact@main 50 | with: 51 | name: code 52 | path: ./build/code.tar 53 | 54 | - name: Upload ascot2py.py 55 | uses: actions/upload-artifact@main 56 | with: 57 | name: ascot2py 58 | path: ./a5py/ascotpy/ascot2py.py 59 | -------------------------------------------------------------------------------- /a5py/gui/contentinteractive.py: -------------------------------------------------------------------------------- 1 | import tkinter as tk 2 | from tkinter import ttk 3 | 4 | from .interactiveorbit import OrbitFrame, OrbitCanvas 5 | 6 | class ContentInteractive: 7 | 8 | def __init__(self, gui, settings, canvas): 9 | self.gui = gui 10 | self.canvas = canvas 11 | 12 | runselection = ttk.Notebook(settings) 13 | 14 | runpoincare = ttk.Frame(runselection) 15 | runorbit = OrbitFrame(runselection) 16 | 17 | #runselection.add(runpoincare, text="Poincaré") 18 | runselection.add(runorbit, text="Orbit") 19 | 20 | canvaspoincare = ttk.Frame(canvas) 21 | canvasorbit = OrbitCanvas(canvas) 22 | 23 | def on_tab_change(event): 24 | tab = event.widget.tab('current')['text'] 25 | self.view(tab) 26 | 27 | runselection.bind('<>', on_tab_change) 28 | runselection.pack(fill="both", expand=True) 29 | 30 | runorbit.init(canvasorbit) 31 | canvasorbit.init() 32 | 33 | self.runpoincare = runpoincare 34 | self.runorbit = runorbit 35 | self.canvaspoincare = canvaspoincare 36 | self.canvasorbit = canvasorbit 37 | 38 | self.active_canvas = canvasorbit 39 | 40 | def display(self): 41 | pass 42 | #self.pack() 43 | 44 | def view(self, tab): 45 | if tab == "Orbit": 46 | self.gui.ascot.input_free() 47 | self.active_canvas.pack_forget() 48 | self.runorbit.display(self.gui) 49 | self.active_canvas = self.runorbit.canvas 50 | self.active_canvas.pack(fill="both", expand=True) 51 | -------------------------------------------------------------------------------- /src/endcond.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file endcond.h 3 | * @brief Header file for endcond.c 4 | * 5 | * Contains a list declaring all end conditions. 6 | */ 7 | #ifndef ENDCOND_H 8 | #define ENDCOND_H 9 | 10 | #include "particle.h" 11 | #include "simulate.h" 12 | 13 | /** 14 | * @brief Marker end condition bit masks 15 | * 16 | * These bit masks are used to mark specific end condition as being active. 17 | */ 18 | enum ENDCOND_FLAG { 19 | endcond_tlim = 0x1, /**< Simulation time limit */ 20 | endcond_emin = 0x2, /**< Minimum energy */ 21 | endcond_therm = 0x4, /**< Thermalized */ 22 | endcond_wall = 0x8, /**< Wall collision */ 23 | endcond_rhomin = 0x10, /**< Minimum rho */ 24 | endcond_rhomax = 0x20, /**< Maximum rho */ 25 | endcond_polmax = 0x40, /**< Poloidal limit */ 26 | endcond_tormax = 0x80, /**< Toroidal limit */ 27 | endcond_cpumax = 0x100, /**< Wall time exceeded */ 28 | endcond_hybrid = 0x200, /**< Hybrid mode condition */ 29 | endcond_neutr = 0x400, /**< Neutralized */ 30 | endcond_ioniz = 0x800 /**< Ionized */ 31 | 32 | }; 33 | 34 | void endcond_check_gc(particle_simd_gc* p_f, particle_simd_gc* p_i, 35 | sim_data* sim); 36 | void endcond_check_fo(particle_simd_fo* p_f, particle_simd_fo* p_i, 37 | sim_data* sim); 38 | void endcond_check_ml(particle_simd_ml* p_f, particle_simd_ml* p_i, 39 | sim_data* sim); 40 | 41 | void endcond_parse(int endcond, int* endconds); 42 | void endcond_parse2str(int endcond, char* str); 43 | 44 | #endif 45 | -------------------------------------------------------------------------------- /src/neutral/N0_3D.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file N0_3D.h 3 | * @brief Header file for N0_3D.c 4 | */ 5 | #ifndef N0_3D_H 6 | #define N0_3D_H 7 | #include "../ascot5.h" 8 | #include "../offload.h" 9 | #include "../linint/linint.h" /* for 3D interpolation routines */ 10 | 11 | /** 12 | * @brief 3D neutral parameters on the target 13 | */ 14 | typedef struct { 15 | int n_species; /**< Number of neutral species */ 16 | int* anum; /**< Neutral species mass number */ 17 | int* znum; /**< Neutral species charge number */ 18 | int* maxwellian; /**< Is species distribution Maxwellian or 19 | monoenergetic */ 20 | linint3D_data* n0; /**< Density interpolation struct for each species */ 21 | linint3D_data* t0; /**< Temperature intepolation struct for each species */ 22 | } N0_3D_data; 23 | 24 | int N0_3D_init(N0_3D_data* data, 25 | int n_r, real r_min, real r_max, 26 | int n_phi, real phi_min, real phi_max, 27 | int n_z, real z_min, real z_max, 28 | int n_species, int* anum, int* znum, int* maxwellian, 29 | real* density, real* temperature); 30 | void N0_3D_free(N0_3D_data* data); 31 | void N0_3D_offload(N0_3D_data* data); 32 | DECLARE_TARGET_SIMD_UNIFORM(ndata) 33 | a5err N0_3D_eval_n0(real* n0, real r, real phi, real z, N0_3D_data* ndata); 34 | DECLARE_TARGET_SIMD_UNIFORM(ndata) 35 | a5err N0_3D_eval_t0(real* t0, real r, real phi, real z, N0_3D_data* ndata); 36 | DECLARE_TARGET_SIMD_UNIFORM(ndata) 37 | int N0_3D_get_n_species(N0_3D_data* ndata); 38 | #endif 39 | -------------------------------------------------------------------------------- /src/wall.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file wall.h 3 | * @brief Header file for wall.c 4 | * 5 | * Contains a list declaring all wall_types, and declaration of 6 | * wall_offload_data and wall_data structs. 7 | * 8 | */ 9 | #ifndef WALL_H 10 | #define WALL_H 11 | 12 | #include "ascot5.h" 13 | #include "offload.h" 14 | #include "wall/wall_2d.h" 15 | #include "wall/wall_3d.h" 16 | 17 | /** 18 | * @brief Wall model types 19 | */ 20 | typedef enum wall_type { 21 | wall_type_2D, /**< Axisymmetric wall model consisting of single contour */ 22 | wall_type_3D, /**< 3D wall model consisting of triangles */ 23 | } wall_type; 24 | 25 | /** 26 | * @brief Wall model simulation data 27 | * 28 | * The intended usage is that only single type of data is used at a time. This 29 | * is declared using the `type` field. 30 | */ 31 | typedef struct { 32 | wall_type type; /**< Wall model type wrapped by this struct */ 33 | wall_2d_data w2d; /**< 2D model or NULL if not active */ 34 | wall_3d_data w3d; /**< 3D model or NULL if not active */ 35 | } wall_data; 36 | 37 | void wall_free(wall_data* data); 38 | void wall_offload(wall_data* data); 39 | GPU_DECLARE_TARGET_SIMD_UNIFORM(w) 40 | int wall_hit_wall(real r1, real phi1, real z1, real r2, real phi2, real z2, 41 | wall_data* w, real* w_coll); 42 | DECLARE_TARGET_END 43 | GPU_DECLARE_TARGET_SIMD_UNIFORM(w) 44 | int wall_get_n_elements(wall_data* w); 45 | DECLARE_TARGET_END 46 | GPU_DECLARE_TARGET_SIMD_UNIFORM(w) 47 | int wall_get_flag(wall_data* w, int idx); 48 | DECLARE_TARGET_END 49 | GPU_DECLARE_TARGET_SIMD_UNIFORM(w) 50 | int wall_get_n_elements(wall_data* w); 51 | DECLARE_TARGET_END 52 | #endif 53 | -------------------------------------------------------------------------------- /src/E_field.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file E_field.h 3 | * @brief Header file for E_field.c 4 | * 5 | * Contains a list declaring all E_field_types, and declaration of 6 | * E_field_offload_data and E_field_data structs. 7 | */ 8 | #ifndef E_FIELD_H 9 | #define E_FIELD_H 10 | 11 | #include "ascot5.h" 12 | #include "offload.h" 13 | #include "error.h" 14 | #include "B_field.h" 15 | #include "Efield/E_TC.h" 16 | #include "Efield/E_1DS.h" 17 | 18 | /** 19 | * @brief Electric field types 20 | * 21 | * Electric field types are used in the electric field interface (E_field.c) to 22 | * direct function calls to correct electric field instances. Each electric 23 | * field instance must have a corresponding type. 24 | */ 25 | typedef enum E_field_type { 26 | E_field_type_TC, /**< Trivial Cartesian electric field */ 27 | E_field_type_1DS /**< Spline-interpolated radial electric field */ 28 | } E_field_type; 29 | 30 | /** 31 | * @brief Electric field simulation data 32 | * 33 | * The intended usage is that only single type of data is used at a time. This 34 | * is declared using the `type` field. 35 | */ 36 | typedef struct { 37 | E_field_type type; /**< Electric field type wrapped by this struct */ 38 | E_TC_data ETC; /**< TC field or NULL if not active */ 39 | E_1DS_data E1DS; /**< 1DS field or NULL if not active */ 40 | } E_field_data; 41 | 42 | void E_field_free(E_field_data* data); 43 | void E_field_offload(E_field_data* data); 44 | GPU_DECLARE_TARGET_SIMD_UNIFORM(Edata, Bdata) 45 | a5err E_field_eval_E(real E[3], real r, real phi, real z, real t, 46 | E_field_data* Edata, B_field_data* Bdata); 47 | DECLARE_TARGET_END 48 | 49 | #endif 50 | -------------------------------------------------------------------------------- /src/simulate/mccc/mccc_wiener.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file mccc_wiener.h 3 | * @brief header file for mccc_wiener.c 4 | */ 5 | #ifndef MCCC_WIENER_H 6 | #define MCCC_WIENER_H 7 | 8 | #include "../../ascot5.h" 9 | #include "../../error.h" 10 | 11 | /** 12 | * Wiener process dimension. NDIM=5 because only guiding centers are simulated 13 | * with adaptive time step 14 | */ 15 | #define MCCC_NDIM 5 16 | 17 | /** 18 | * Maximum slots in Wiener array which means this is the maximum number of time 19 | * step reductions. 20 | */ 21 | #define MCCC_NSLOTS WIENERSLOTS 22 | 23 | /** 24 | * @brief Struct for storing Wiener processes. 25 | * 26 | * Elements of this struct should not be changed outside mccc package. 27 | */ 28 | typedef struct { 29 | int nextslot[MCCC_NSLOTS]; /**< Integer array where each element shows 30 | where the next wiener process is located. 31 | Indexing starts from 0 and element points 32 | to itself if it is the last element */ 33 | real time[MCCC_NSLOTS]; /**< Time instances for different Wiener 34 | processes */ 35 | real wiener[MCCC_NDIM*MCCC_NSLOTS]; /**< Ndim x Nslot array of Wiener 36 | process values */ 37 | } mccc_wienarr; 38 | 39 | DECLARE_TARGET_SIMD 40 | void mccc_wiener_initialize(mccc_wienarr* w, real initime); 41 | DECLARE_TARGET_SIMD 42 | a5err mccc_wiener_generate(mccc_wienarr* w, real t, int* windex, real* rand5); 43 | DECLARE_TARGET_SIMD 44 | a5err mccc_wiener_clean(mccc_wienarr* w, real t); 45 | 46 | #endif 47 | -------------------------------------------------------------------------------- /src/octree.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file octree.h 3 | * @brief Header file for octree.c 4 | */ 5 | #ifndef OCTREE_H 6 | #define OCTREE_H 7 | 8 | #include "ascot5.h" 9 | #include "list.h" 10 | 11 | /** 12 | * @brief Struct representing single octree node 13 | * 14 | * Stores eight child nodes, bounding box of the volume this node encloses, and 15 | * a linked list containing IDs of triangles belonging to this node. 16 | */ 17 | typedef struct octree_node { 18 | struct octree_node* n000; /**< [xmin, ymin, zmin] child node */ 19 | struct octree_node* n100; /**< [xmax, ymin, zmin] child node */ 20 | struct octree_node* n010; /**< [xmin, ymax, zmin] child node */ 21 | struct octree_node* n110; /**< [xmax, ymax, zmin] child node */ 22 | struct octree_node* n001; /**< [xmin, ymin, zmax] child node */ 23 | struct octree_node* n101; /**< [xmax, ymin, zmax] child node */ 24 | struct octree_node* n011; /**< [xmin, ymax, zmax] child node */ 25 | struct octree_node* n111; /**< [xmax, ymax, zmax] child node */ 26 | real bb1[3]; /**< Bounding box xyz minimum limit */ 27 | real bb2[3]; /**< Bounding box xyz maximum limit */ 28 | list_int_node* list; /**< Linked list for storing triangle IDs */ 29 | } octree_node; 30 | 31 | void octree_create(octree_node** node, real x_min, real x_max, 32 | real y_min, real y_max, real z_min, real z_max, 33 | int depth); 34 | void octree_free(octree_node** node); 35 | void octree_add(octree_node* node, real t1[3], real t2[3], real t3[3], int id); 36 | list_int_node* octree_get(octree_node* node, real p[3]); 37 | 38 | #endif 39 | -------------------------------------------------------------------------------- /src/simulate/mccc/mccc.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file mccc.h 3 | * @brief Header file for mccc package 4 | */ 5 | #ifndef MCCC_H 6 | #define MCCC_H 7 | 8 | #include "../../ascot5.h" 9 | #include "../../B_field.h" 10 | #include "../../plasma.h" 11 | #include "../../particle.h" 12 | #include "../../random.h" 13 | #include "mccc_wiener.h" 14 | 15 | /** 16 | * @brief Defines minimum energy boundary condition 17 | * 18 | * This times local electron temperature is minimum energy boundary. If guiding 19 | * center energy goes below this, it is mirrored to prevent collision 20 | * coefficients from diverging. 21 | */ 22 | #define MCCC_CUTOFF 0.1 23 | 24 | /** 25 | * @brief Parameters and data required to evaluate Coulomb collisions 26 | */ 27 | typedef struct { 28 | int usetabulated; /**< Use tabulated values for special functions */ 29 | int include_energy; /**< Let collisions change energy */ 30 | int include_pitch; /**< Let collisions change pitch */ 31 | int include_gcdiff; /**< Let collisions change guiding center position */ 32 | } mccc_data; 33 | 34 | 35 | void mccc_init(mccc_data* mdata, int include_energy, int include_pitch, 36 | int include_gcdiff); 37 | void mccc_fo_euler(particle_simd_fo* p, real* h, plasma_data* pdata, 38 | mccc_data* mdata, real* rnd); 39 | void mccc_gc_euler(particle_simd_gc* p, real* h, B_field_data* Bdata, 40 | plasma_data* pdata, mccc_data* mdata, real* rnd); 41 | void mccc_gc_milstein(particle_simd_gc* p, real* hin, real* acc, real* collfreq, real* hout, real tol, 42 | mccc_wienarr* w, B_field_data* Bdata, plasma_data* pdata, 43 | mccc_data* mdata, real* rnd); 44 | 45 | #endif 46 | -------------------------------------------------------------------------------- /doc/testing.rst: -------------------------------------------------------------------------------- 1 | ======= 2 | Testing 3 | ======= 4 | 5 | Verification 6 | ============ 7 | 8 | Comparisons to known analytical results ASCOT5 should be able to reproduce. 9 | 10 | .. rubric:: Neoclassical transport 11 | 12 | .. figure:: ../figures/neoclassical.png 13 | :class: with-border 14 | :align: center 15 | :width: 300px 16 | 17 | .. rubric:: Classical transport 18 | 19 | .. rubric:: Collisional equilibrium and slowing-down distribution 20 | 21 | .. rubric:: Conservation of :math:`\mu`, :math:`E_\mathrm{kin}`, and :math:`P_\mathrm{ctor}` 22 | 23 | .. rubric:: Guiding center transformation 24 | 25 | .. rubric:: Guiding center drifts and gyro-motion 26 | 27 | Benchmarks 28 | ========== 29 | 30 | Comparisons to other similar codes. 31 | 32 | .. list-table:: Studies where ASCOT5 is compared to other codes. 33 | :widths: 50 50 25 50 34 | :header-rows: 1 35 | 36 | * - Code 37 | - Study 38 | - Publication 39 | - Notes 40 | * - SPIRAL 41 | - Alpha particle transport due to TF ripple in SPARC 42 | - `S. D. Scott, et al., Fast-ion physics in SPARC `_ 43 | - Good match. 44 | 45 | Validation 46 | ========== 47 | 48 | Comparisons to experiments. 49 | 50 | .. list-table:: Studies where ASCOT5 output is compared to experimental results 51 | :widths: 50 50 50 52 | :header-rows: 1 53 | 54 | * - Study 55 | - Publication 56 | - Notes 57 | * - NBI current drive 58 | - `S. Mulas et al., *Validating neutral-beam current drive simulations in the TJ-II stellarator* `_ 59 | - Good match with counter-injection but for the co-injection the ASCOT5 results is approximately half of the measured value. 60 | -------------------------------------------------------------------------------- /src/boozer.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file boozer.h 3 | * @brief Header file for boozer.c 4 | */ 5 | #ifndef BOOZER_H 6 | #define BOOZER_H 7 | 8 | #include "ascot5.h" 9 | #include "error.h" 10 | #include "B_field.h" 11 | #include "spline/interp.h" 12 | 13 | /** 14 | * @brief Data for mapping between the cylindrical and Boozer coordinates 15 | */ 16 | typedef struct { 17 | real psi_min; /**< Minimum psi in other fields */ 18 | real psi_max; /**< Maximum psi in other fields */ 19 | real* rs; /**< R points of outermost poloidal psi-surface contour, 20 | nrzs elements, the first and last points are the same */ 21 | real* zs; /**< z points of outermost poloidal psi-surface contour, 22 | nrzs elements, the first and last points are the same */ 23 | int nrzs; /**< number of elements in rs and zs */ 24 | interp2D_data nu_psitheta; /**< the nu-function, phi=zeta+nu(psi,theta), 25 | with phi the cylindrical angle */ 26 | interp2D_data theta_psithetageom; /**< boozer_theta(psi,thetag) */ 27 | } boozer_data; 28 | 29 | int boozer_init(boozer_data* data, int npsi, real psi_min, real psi_max, 30 | int ntheta, int nthetag, real* nu, real* theta, 31 | int nrzs, real* rs, real* zs); 32 | void boozer_free(boozer_data* data); 33 | void boozer_offload(boozer_data* data); 34 | DECLARE_TARGET_SIMD_UNIFORM(Bdata, boozerdata) 35 | a5err boozer_eval_psithetazeta(real psithetazeta[12], int* isinside, real r, 36 | real phi, real z, B_field_data* Bdata, 37 | boozer_data* boozerdata); 38 | 39 | 40 | #endif 41 | -------------------------------------------------------------------------------- /src/diag/dist_com.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file dist_com.h 3 | * @brief Header file for dist_com.c 4 | */ 5 | #ifndef DIST_COM_H 6 | #define DIST_COM_H 7 | 8 | #include 9 | #include "../ascot5.h" 10 | #include "../particle.h" 11 | #include "../B_field.h" 12 | 13 | /** 14 | * @brief Histogram parameters on target 15 | */ 16 | typedef struct { 17 | int n_mu; /**< number of mu bins */ 18 | real min_mu; /**< value of lowest mu bin */ 19 | real max_mu; /**< value of highest ,u bin */ 20 | 21 | int n_Ekin; /**< number of Ekin bins */ 22 | real min_Ekin; /**< value of lowest Ekin bin */ 23 | real max_Ekin; /**< value of highest Ekin bin */ 24 | 25 | int n_Ptor; /**< number of Ptor bins */ 26 | real min_Ptor; /**< value of lowest Ptor bin */ 27 | real max_Ptor; /**< value of highest Ptor bin */ 28 | 29 | size_t step_1; /**< step for 2nd fastest running index */ 30 | size_t step_2; /**< step for 3rd fastest running index */ 31 | 32 | real* histogram; /**< pointer to start of histogram array */ 33 | } dist_COM_data; 34 | 35 | int dist_COM_init(dist_COM_data* data); 36 | void dist_COM_free(dist_COM_data* data); 37 | void dist_COM_offload(dist_COM_data* data); 38 | void dist_COM_onload(dist_COM_data* data); 39 | void dist_COM_update_fo(dist_COM_data* dist, B_field_data*Bdata, 40 | particle_simd_fo* p_f, particle_simd_fo* p_i); 41 | void dist_COM_update_gc(dist_COM_data* dist, B_field_data* Bdata, 42 | particle_simd_gc* p_f, particle_simd_gc* p_i); 43 | 44 | #endif 45 | -------------------------------------------------------------------------------- /.github/workflows/rebase-on-main.yaml: -------------------------------------------------------------------------------- 1 | name: Rebase Develop and Docs to Main 2 | on: 3 | push: 4 | branches: 5 | - main 6 | pull_request: 7 | types: 8 | - closed 9 | 10 | jobs: 11 | 12 | on_push: 13 | if: github.event_name == 'push' 14 | runs-on: ubuntu-latest 15 | 16 | steps: 17 | - uses: actions/checkout@v3 18 | with: 19 | fetch-depth: 0 20 | token: ${{ secrets.BOT_ACCESS_TOKEN }} 21 | 22 | - name: Set up Git 23 | run: | 24 | git config user.email "ascotbot@gmail.com" 25 | git config user.name "Reetta" 26 | git fetch --all 27 | 28 | - name: Rebase Docs on Main 29 | run: | 30 | git checkout docs 31 | git rebase origin/main 32 | git push --force origin docs 33 | 34 | - name: Rebase Develop on Main 35 | run: | 36 | git checkout develop 37 | git rebase origin/main 38 | git push --force origin develop 39 | 40 | on_pull_request: 41 | if: github.event.pull_request.merged == 'true' 42 | runs-on: ubuntu-latest 43 | steps: 44 | - uses: actions/checkout@v3 45 | with: 46 | fetch-depth: 0 47 | token: ${{ secrets.BOT_ACCESS_TOKEN }} 48 | 49 | - name: Set up Git 50 | run: | 51 | git config user.email "ascotbot@gmail.com" 52 | git config user.name "Reetta" 53 | git fetch --all 54 | 55 | - name: Rebase Docs on Main 56 | run: | 57 | git checkout docs 58 | git rebase origin/main 59 | git push --force origin docs 60 | 61 | - name: Rebase Develop on Main 62 | run: | 63 | git checkout develop 64 | git rebase origin/main 65 | git push --force origin develop 66 | -------------------------------------------------------------------------------- /src/afsi.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file afsi.c 3 | * @brief ASCOT Fusion Source Integrator AFSI 4 | */ 5 | #ifndef AFSI_H 6 | #define AFSI_H 7 | 8 | #include 9 | #include "ascot5.h" 10 | #include "consts.h" 11 | #include "simulate.h" 12 | #include "random.h" 13 | #include "boschhale.h" 14 | #include "diag/hist.h" 15 | 16 | /** 17 | * @brief Valid momentum space basis. 18 | */ 19 | typedef enum { 20 | PPARPPERP, 21 | EKINXI 22 | } mom_space_basis; 23 | 24 | /** 25 | * @brief Wrapper around input data structures 26 | */ 27 | typedef struct { 28 | int type1; /**< Distribution type (1:beam, 2:thermal) */ 29 | int type2; /**< Distribution type (1:beam, 2:thermal) */ 30 | int thermal1; /**< Thermal species index for reactant 1 */ 31 | int thermal2; /**< Thermal species index for reactant 2 */ 32 | histogram* beam1; /**< Distribution data for reactant 1 */ 33 | histogram* beam2; /**< Distribution data for reactant 2 */ 34 | real* r; /**< Radial coordinate at the grid center [m] */ 35 | real* phi; /**< Toroidal coordinate at the grid center [rad] */ 36 | real* z; /**< Axial coordinate at the grid center [m] */ 37 | real* vol; /**< Grid cell volume [m^3] */ 38 | size_t volshape[3]; /**< Dimensions of r, phi, z, and volume */ 39 | Reaction reaction; /**< The fusion reaction that is modelled */ 40 | real mult; /**< Multiplication factor which is 0.5 if species is 41 | interacting with itself, 1.0 otherwise */ 42 | } afsi_data; 43 | 44 | void afsi_run(sim_data* sim, afsi_data* data, int n, 45 | histogram* prod1, histogram* prod2); 46 | #endif 47 | -------------------------------------------------------------------------------- /src/unit_tests/test_interp1Dcomp.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @file test_interp1Dcomp.c 3 | * @brief Test program for 1D spline interpolation 4 | */ 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include "../math.h" 10 | #include "../spline/interp.h" 11 | 12 | /** 13 | * Main function for the test program. 14 | */ 15 | int main(int argc, char** argv) { 16 | 17 | if(argc < 2) { 18 | printf("Usage: test_interp1Dcomp fname\n"); 19 | exit(1); 20 | } 21 | 22 | FILE* f = fopen(argv[1], "w"); 23 | 24 | real B = 0; 25 | real B_dB[3]; 26 | 27 | int n_r = 100; 28 | real r_min = 0.0; 29 | real r_max = 2*acos(-1) - 2*acos(-1)/100; 30 | 31 | real* r = (real*) malloc(n_r * sizeof(real)); 32 | math_linspace(r, r_min, r_max, n_r); 33 | 34 | /* Initialize test data */ 35 | real* fn = (real*) malloc(n_r * sizeof(real)); 36 | for (int i = 0; i < n_r; i++) { 37 | /* fn[i] = r[i]*r[i]; */ 38 | fn[i] = sin(r[i]); 39 | } 40 | /* Periodic boundary conditions */ 41 | int bc_r = PERIODICBC; 42 | /* int bc_r = NATURALBC; */ 43 | real* c = malloc(n_r * NSIZE_COMP1D * sizeof(real)); 44 | interp1Dcomp_init_coeff(c, fn, n_r, bc_r, r_min, r_max); 45 | interp1D_data str; 46 | interp1Dcomp_init_spline(&str, c, n_r, bc_r, r_min, r_max); 47 | 48 | // New r for interpolation 49 | int n_ri = 500; 50 | real ri_min = -4*acos(-1); 51 | real ri_max = 4*acos(-1); 52 | 53 | real* ri = (real*) malloc(n_ri * sizeof(real)); 54 | math_linspace(ri, ri_min, ri_max, n_ri); 55 | 56 | for (int i = 0; i < n_ri; i++) { 57 | interp1Dcomp_eval_f(&B, &str, ri[i]); 58 | interp1Dcomp_eval_df(B_dB, &str, ri[i]); 59 | fprintf(f,"%le %le %le %le %le\n", ri[i], B, B_dB[0], B_dB[1], B_dB[2]); 60 | } 61 | fclose(f); 62 | return 0; 63 | } 64 | -------------------------------------------------------------------------------- /doc/papi/a5py.ascot5io.rst: -------------------------------------------------------------------------------- 1 | ================= 2 | ``ascot5io`` 3 | ================= 4 | 5 | .. automodule:: a5py.ascot5io 6 | 7 | .. toctree:: 8 | :maxdepth: 2 9 | :hidden: 10 | 11 | a5py.ascot5io.bfield 12 | a5py.ascot5io.efield 13 | a5py.ascot5io.plasma 14 | a5py.ascot5io.marker 15 | a5py.ascot5io.wall 16 | a5py.ascot5io.neutral 17 | a5py.ascot5io.boozer 18 | a5py.ascot5io.mhd 19 | a5py.ascot5io.asigma 20 | a5py.ascot5io.nbi 21 | a5py.ascot5io.options 22 | a5py.ascot5io.coreio 23 | 24 | .. autosummary:: 25 | 26 | a5py.ascot5io.bfield 27 | a5py.ascot5io.efield 28 | a5py.ascot5io.plasma 29 | a5py.ascot5io.marker 30 | a5py.ascot5io.wall 31 | a5py.ascot5io.neutral 32 | a5py.ascot5io.boozer 33 | a5py.ascot5io.mhd 34 | a5py.ascot5io.asigma 35 | a5py.ascot5io.nbi 36 | a5py.ascot5io.options 37 | a5py.ascot5io.coreio 38 | 39 | .. autoclass:: a5py.ascot5io.Ascot5IO 40 | :show-inheritance: 41 | :members: 42 | :inherited-members: 43 | :undoc-members: 44 | 45 | .. autoclass:: a5py.ascot5io.RunGroup 46 | :show-inheritance: 47 | :members: 48 | :inherited-members: 49 | :undoc-members: 50 | 51 | .. autoclass:: a5py.ascot5io.AfsiGroup 52 | :show-inheritance: 53 | :members: 54 | :inherited-members: 55 | :undoc-members: 56 | 57 | .. autoclass:: a5py.ascot5io.BBNBIGroup 58 | :show-inheritance: 59 | :members: 60 | :inherited-members: 61 | :undoc-members: 62 | 63 | .. autoclass:: a5py.ascot5io.InputGroup 64 | :show-inheritance: 65 | :members: 66 | :inherited-members: 67 | :undoc-members: 68 | 69 | .. autoclass:: a5py.ascot5io.dist.DistData 70 | :show-inheritance: 71 | :members: 72 | :inherited-members: 73 | :undoc-members: 74 | 75 | .. autoclass:: a5py.ascot5io.dist.DistMoment 76 | :show-inheritance: 77 | :members: 78 | :inherited-members: 79 | :undoc-members: 80 | -------------------------------------------------------------------------------- /doc/tutorials.rst: -------------------------------------------------------------------------------- 1 | .. _Tutorial: 2 | 3 | ========= 4 | Tutorials 5 | ========= 6 | 7 | These tutorials are implemented as Jupyter notebooks meaning that, while they appear as ordinary HTML documents here, you can also run them interactively. 8 | The notebooks are found in ``doc/tutorials`` folder in your cloned repository. 9 | To run them interactively, you need to have Jupyter installed and then configure it to use the virtual environment that you've created when installing ASCOT5: 10 | 11 | .. code-block:: 12 | 13 | pip install jupyter 14 | ipython kernel install --user --name=ascotenv 15 | 16 | Now you can run the examples interactively with e.g. VS Code, or even with your browser (remember to select the ``ascotenv`` kernel), 17 | 18 | .. code-block:: 19 | 20 | jupyter-notebook 21 | 22 | or you can convert these examples to ordinary Python scripts and execute them (executing them in ipython terminal is advised as otherwise the plotted figures close immediately): 23 | 24 | .. code-block:: 25 | 26 | jupyter-nbconvert --to python 27 | python tutorial.py 28 | 29 | .. _Examples: 30 | 31 | .. rubric:: Basics 32 | 33 | .. nbgallery:: 34 | :hidden: 35 | 36 | tutorials/introduction.ipynb 37 | tutorials/orbits.ipynb 38 | tutorials/distributions.ipynb 39 | 40 | .. rubric:: Marker generation 41 | 42 | .. nbgallery:: 43 | :hidden: 44 | 45 | tutorials/afsi.ipynb 46 | tutorials/bbnbi.ipynb 47 | tutorials/markergen.ipynb 48 | 49 | .. rubric:: Physics 50 | 51 | .. nbgallery:: 52 | :hidden: 53 | 54 | tutorials/slowingdown.ipynb 55 | tutorials/wallload.ipynb 56 | tutorials/mhd.ipynb 57 | tutorials/atomic.ipynb 58 | tutorials/reversetime.ipynb 59 | 60 | .. rubric:: Tools 61 | 62 | .. nbgallery:: 63 | :hidden: 64 | 65 | tutorials/poincare.ipynb 66 | tutorials/orbitanalysis.ipynb 67 | tutorials/biosaw.ipynb 68 | -------------------------------------------------------------------------------- /doc/acknowledging.rst: -------------------------------------------------------------------------------- 1 | .. _Citing: 2 | 3 | ============= 4 | Citing ASCOT5 5 | ============= 6 | 7 | It is sufficient to acknowledge ASCOT5 usage with something like: 8 | 9 | *Simulations were carried out using ASCOT5 orbit-following code [REF].* 10 | 11 | Where the refence is either the official (unpublished) ASCOT5 reference paper :cite:labelpar:`varje2019high`, Jari's thesis :cite:labelpar:`Varjephd`, Konsta's thesis :cite:labelpar:`Sarkimakiphd`, or ASCOT4 reference paper :cite:labelpar:`hirvijoki2014ascot`. 12 | 13 | If the work contains considerable ASCOT5 work, the referees might insist on a more detailed description. 14 | At minimum, describe i) how markers were generated and how many were used, ii) what physics were included or excluded, iii) when markers where terminated, and iv) whether the simulations were done in guiding-center or gyro-orbit mode. 15 | 16 | *Markers representing fusion-born alpha particles were sampled from a fusion source distribution.* 17 | *Total of 10^6 markers were traced until they made contact with the wall or cooled below 2 x Te.* 18 | *Markers were traced using the guiding-center approximation and the simulations included Coulomb collisions.* 19 | 20 | It is also a good practice to refer as *markers* the points whose trajectories ASCOT5 simulates, and *particles* when discussing physical particles (markers multiplied by their weight). 21 | Furthermore, *full orbit* can refer to both *poloidal orbit* and *gyro-orbit* meaning it is better to write "gyro-orbit" explicitly (e.g. when comparing the results to guiding-center simulations). 22 | Also, pitch can be defined either as the angle between velocity and magnetic field vectors but it can also be the cosine of that angle (the definition what ASCOT5 uses) so please be explicit when writing that "pitch is zero". 23 | 24 | License 25 | ======= 26 | 27 | This software is distributed under the `LGPLv3 `_ license. 28 | -------------------------------------------------------------------------------- /src/hdf5_interface.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file hdf5_interface.h 3 | * @brief Header file for hdf5_interface.c 4 | */ 5 | #ifndef HDF5_INTERFACE_H5 6 | #define HDF5_INTERFACE_H5 7 | 8 | #include 9 | 10 | #include "ascot5.h" 11 | #include "simulate.h" 12 | #include "particle.h" 13 | 14 | /** 15 | * @brief Enum to represent different input groups for HDF5 file reading. 16 | * 17 | * This enum is used to specify which input groups should be read from the HDF5 18 | * file. Each group corresponds to a specific data type in the simulationa. 19 | */ 20 | enum input_group { 21 | hdf5_input_options = 0x1, /**< Input group for simulation options */ 22 | hdf5_input_bfield = 0x2, /**< Input group for magnetic field data */ 23 | hdf5_input_efield = 0x4, /**< Input group for electric field data */ 24 | hdf5_input_plasma = 0x8, /**< Input group for plasma data */ 25 | hdf5_input_neutral = 0x10, /**< Input group for neutral gas data */ 26 | hdf5_input_wall = 0x20, /**< Input group for wall data */ 27 | hdf5_input_marker = 0x40, /**< Input group for marker data */ 28 | hdf5_input_boozer = 0x80, /**< Input group for boozer coordinates data */ 29 | hdf5_input_mhd = 0x100, /**< Input group for MHD data */ 30 | hdf5_input_asigma = 0x200, /**< Input group for atomic data */ 31 | hdf5_input_nbi = 0x400 /**< Input group for injector data */ 32 | }; 33 | 34 | int hdf5_interface_read_input(sim_data* sim, int input_active, 35 | input_particle** p, int* n_markers); 36 | 37 | int hdf5_interface_init_results(sim_data* sim, char* qid, char* run); 38 | 39 | int hdf5_interface_write_state(char* fn, char* state, integer n, 40 | particle_state* p); 41 | 42 | int hdf5_interface_write_diagnostics(sim_data* sim); 43 | 44 | void hdf5_generate_qid(char* qid); 45 | #endif 46 | -------------------------------------------------------------------------------- /src/hdf5io/hdf5_helpers.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file hdf5_helpers.h 3 | * @brief Header file for hdf5_helpers.h 4 | */ 5 | #ifndef HDF5_HELPERS_H 6 | #define HDF5_HELPERS_H 7 | 8 | #include 9 | #include "../ascot5.h" 10 | 11 | void hdf5_init(void); 12 | hid_t hdf5_create(const char* filename); 13 | hid_t hdf5_open(const char* filename); 14 | hid_t hdf5_open_ro(const char* filename); 15 | herr_t hdf5_close(hid_t file_id); 16 | hid_t hdf5_create_group(hid_t loc, const char* path); 17 | herr_t hdf5_find_group(hid_t loc, const char* path); 18 | char* hdf5_generate_qid_path(const char* original, char* qid, char* path); 19 | char* hdf5_gen_path(const char* original, char* qid, char* path); 20 | int hdf5_read_double(const char* var, real* ptr, hid_t file, char* qid, 21 | const char* errfile, int errline); 22 | int hdf5_read_short(const char* var, short* ptr, hid_t file, char* qid, 23 | const char* errfile, int errline); 24 | int hdf5_read_int(const char* var, int* ptr, hid_t file, char* qid, 25 | const char* errfile, int errline); 26 | int hdf5_read_long(const char* var, long* ptr, hid_t file, char* qid, 27 | const char* errfile, int errline); 28 | herr_t hdf5_write_string_attribute(hid_t loc, const char* path, 29 | const char* attrname, const char* string); 30 | herr_t hdf5_write_extendible_dataset_double(hid_t group, 31 | const char* datasetname, 32 | int length, double* data); 33 | herr_t hdf5_write_extendible_dataset_long(hid_t group, 34 | const char* datasetname, 35 | int length, long* data); 36 | herr_t hdf5_write_extendible_dataset_int(hid_t group, 37 | const char* datasetname, 38 | int length, int* data); 39 | 40 | #endif 41 | -------------------------------------------------------------------------------- /src/consts.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file consts.h 3 | * @brief Header file containing physical and mathematical constants 4 | */ 5 | #ifndef CONSTS_H 6 | #define CONSTS_H 7 | 8 | #include "ascot5.h" 9 | 10 | /** @brief pi */ 11 | #define CONST_PI 3.1415926535897932384626 12 | 13 | /** @brief 2*pi */ 14 | #define CONST_2PI 6.2831853071795862319959 15 | 16 | /** @brief sqrt(pi) */ 17 | #define CONST_SQRTPI 1.7724538509055160272982 18 | 19 | /** @brief sqr(2*pi) */ 20 | #define CONST_SQRT2PI 2.5066282746310005024158 21 | 22 | /** @brief Speed of light [m/s] */ 23 | #define CONST_C 299792458.0 24 | 25 | /** @brief Speed of light squared [m^2/s^2] */ 26 | #define CONST_C2 89875517873681760.0 27 | 28 | /** @brief Speed of light to power of three [m^3/s^3] */ 29 | #define CONST_C3 26944002417373989539335912.0 30 | 31 | /** @brief Atomic mass unit in kilograms [kg] */ 32 | #define CONST_U 1.660538921e-27 33 | 34 | /** @brief Elementary charge [C] */ 35 | #define CONST_E 1.602176565e-19 36 | 37 | /** @brief Boltzmann constant [J/K] */ 38 | #define CONST_KB 1.3807e-23 39 | 40 | /** @brief Electron mass [kg] */ 41 | #define CONST_M_E 9.1094e-31 42 | 43 | /** @brief Electric constant [m^-3*kg^-1*s^4*A^2] */ 44 | #define CONST_E0 8.8542e-12 45 | 46 | /** @brief Reduced Planck constant [m^2*kg/s] */ 47 | #define CONST_HBAR 1.0546e-34 48 | 49 | /** @brief Magnetic constant [kg*m*s^-2*A^-2] */ 50 | #define CONST_MU0 1.25663706212e-6 51 | 52 | #endif 53 | -------------------------------------------------------------------------------- /a5py/m3_template/micro/ascot.py: -------------------------------------------------------------------------------- 1 | import imas 2 | 3 | from mpi4py import MPI 4 | 5 | from a5py._nonfunctional.distsource_fun import * 6 | 7 | 8 | def check_ids(ids, rank, size): 9 | print('IDS [ ', ids.metadata.name, ' : ', rank, '/', size, '] time:' , ids.time) 10 | pass 11 | 12 | # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 13 | # MOCKS ASCOT MAIN METHOD 14 | # This is simple, sequential version of the code. To benefit from the parallel runs the data 15 | # should be 16 | # 17 | # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 18 | def ascot_main(equilibrium_3d_in, equilibrium_in, distribution_sources_in, core_profiles_in, wall2d_in, wall3d_in, distributions_out, code_parameters): 19 | 20 | comm = MPI.COMM_WORLD 21 | rank = comm.Get_rank() 22 | size = comm.Get_size() 23 | 24 | # print('=======================================') 25 | # print('START OF PHYSICS CODE') 26 | 27 | distsource_run(equilibrium_3d_in, equilibrium_in, distribution_sources_in, core_profiles_in, wall2d_in, wall3d_in,distributions_out, code_parameters) 28 | 29 | 30 | print('rank, size', rank, size) 31 | #check_ids(equilibrium_in, rank, size) 32 | #check_ids(distribution_sources_in, rank, size) 33 | #check_ids(wall2d_in, rank, size) 34 | #check_ids(wall3d_in, rank, size) 35 | 36 | # print('PROCESS [', rank, ':', size, ']') 37 | # print('=======================================') 38 | print(code_parameters) 39 | 40 | # MANDATORY FLAG (UNIFORM TIME HERE) 41 | distributions_out.ids_properties.homogeneous_time = 1 42 | 43 | distributions_out.code.name = 'EXAMPLE: code_restart' 44 | distributions_out.code.version = '1.0' 45 | 46 | distributions_out.time.resize(1) 47 | distributions_out.time[0] = 5 48 | 49 | # FINAL DISPLAY 50 | # print('END OF PHYSICS CODE') 51 | # print('=======================================') 52 | 53 | 54 | 55 | 56 | 57 | 58 | -------------------------------------------------------------------------------- /src/mhd/mhd_stat.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file mhd_stat.h 3 | * @brief Header file for mhd_stat.c 4 | */ 5 | #ifndef MHD_STAT_H 6 | #define MHD_STAT_H 7 | 8 | #include "../ascot5.h" 9 | #include "../offload.h" 10 | #include "../error.h" 11 | #include "../boozer.h" 12 | #include "../spline/interp.h" 13 | #include "../B_field.h" 14 | 15 | /** 16 | * @brief MHD stat parameters on the target 17 | */ 18 | typedef struct { 19 | int n_modes; /**< Number of modes */ 20 | real rho_min; /**< rho grid minimum value */ 21 | real rho_max; /**< rho grid maximum value */ 22 | int* nmode; /**< Toroidal mode numbers */ 23 | int* mmode; /**< Poloidal mode numbers */ 24 | real* amplitude_nm; /**< Amplitude of each mode */ 25 | real* omega_nm; /**< Toroidal frequency [rad/s] */ 26 | real* phase_nm; /**< Phase of each mode [rad] */ 27 | 28 | /** 29 | * @brief 1D splines (rho) for each mode's magnetic eigenfunction 30 | */ 31 | interp1D_data* alpha_nm; 32 | 33 | /** 34 | * @brief 1D splines (rho) for each mode's electric eigenfunction 35 | */ 36 | interp1D_data* phi_nm; 37 | } mhd_stat_data; 38 | 39 | int mhd_stat_init(mhd_stat_data* data, int nmode, int nrho, 40 | real rhomin, real rhomax, int* moden, int* modem, 41 | real* amplitude_nm, real* omega_nm, real* phase_nm, 42 | real* alpha, real* phi); 43 | void mhd_stat_free(mhd_stat_data* data); 44 | void mhd_stat_offload(mhd_stat_data* data); 45 | DECLARE_TARGET_SIMD_UNIFORM(boozerdata, mhddata, includemode) 46 | a5err mhd_stat_eval( 47 | real mhd_dmhd[10], real r, real phi, real z, real t, int includemode, 48 | boozer_data* boozerdata, mhd_stat_data* mhddata, B_field_data* Bdata); 49 | DECLARE_TARGET_SIMD_UNIFORM(boozerdata, mhddata, Bdata, pertonly, includemode) 50 | a5err mhd_stat_perturbations( 51 | real pert_field[7], real r, real phi, real z, real t, int pertonly, 52 | int includemode, boozer_data* boozerdata, mhd_stat_data* mhddata, 53 | B_field_data* Bdata); 54 | 55 | 56 | #endif 57 | -------------------------------------------------------------------------------- /src/unit_tests/test_N0_1D.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @file test_N0_1D.c 3 | * @brief Test program for 1D neutral data 4 | */ 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include "../math.h" 10 | #include "../spline/interp.h" 11 | #include "../neutral/N0_1D.h" 12 | 13 | /** 14 | * Main function for the test program. 15 | */ 16 | int main(int argc, char** argv) { 17 | 18 | if(argc < 2) { 19 | printf("Usage: test_N0_1D fname\n"); 20 | exit(1); 21 | } 22 | 23 | FILE* f = fopen(argv[1], "w"); 24 | 25 | real n0 = 0; 26 | real t0 = 0; 27 | 28 | /* Interpolate cosine shape from 0 to 90 deg */ 29 | int n_r = 100; 30 | real r_min = 0.0; 31 | real r_max = math_deg2rad(90.0); 32 | 33 | real* r = (real*) malloc(n_r * sizeof(real)); 34 | math_linspace(r, r_min, r_max, n_r); 35 | 36 | /* Initialize test data */ 37 | real* n0_ref = (real*) malloc(n_r * sizeof(real)); 38 | real* t0_ref = (real*) malloc(n_r * sizeof(real)); 39 | for (int i = 0; i < n_r; i++) { 40 | /* fn[i] = r[i]*r[i]; */ 41 | n0_ref[i] = cos(r[i]) + 1; 42 | t0_ref[i] = cos(r[i]) + 2; 43 | } 44 | /* Populate N0_1D data structs and dummy offload array */ 45 | N0_1D_offload_data* offload_data; 46 | real* offload_array; 47 | N0_1D_data* ndata; 48 | 49 | N0_1D_init(ndata); 50 | real* c = malloc(n_r * NSIZE_COMP1D * sizeof(real)); 51 | interp1Dcomp_init_coeff(c, fn, n_r, bc_r, r_min, r_max); 52 | interp1D_data str; 53 | interp1Dcomp_init_spline(&str, c, n_r, bc_r, r_min, r_max); 54 | 55 | // New r for interpolation 56 | int n_ri = 500; 57 | real ri_min = -4*acos(-1); 58 | real ri_max = 4*acos(-1); 59 | 60 | real* ri = (real*) malloc(n_ri * sizeof(real)); 61 | math_linspace(ri, ri_min, ri_max, n_ri); 62 | 63 | for (int i = 0; i < n_ri; i++) { 64 | interp1Dcomp_eval_f(&B, &str, ri[i]); 65 | interp1Dcomp_eval_df(B_dB, &str, ri[i]); 66 | fprintf(f,"%le %le %le %le %le\n", ri[i], B, B_dB[0], B_dB[1], B_dB[2]); 67 | } 68 | fclose(f); 69 | return 0; 70 | } 71 | -------------------------------------------------------------------------------- /src/plasma/plasma_1DS.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file plasma_1DS.h 3 | * @brief Header file for plasma_1DS.c 4 | */ 5 | #ifndef PLASMA_1DS_H 6 | #define PLASMA_1DS_H 7 | #include "../ascot5.h" 8 | #include "../offload.h" 9 | #include "../error.h" 10 | #include "../spline/interp.h" 11 | 12 | /** 13 | * @brief 1D spline plasma parameters on the target 14 | */ 15 | typedef struct { 16 | int n_species; /**< number of plasma species including electrons */ 17 | real* mass; /**< plasma species masses (kg) */ 18 | real* charge; /**< plasma species charges (C) */ 19 | int* anum; /**< ion species atomic number */ 20 | int* znum; /**< ion species charge number */ 21 | interp1D_data temp[2]; /**< electron and ion temperature interpolation */ 22 | interp1D_data* dens; /**< electron and ion density interpolation structs*/ 23 | interp1D_data vtor[0]; /**< toroidal rotation interpolation struct */ 24 | } plasma_1DS_data; 25 | 26 | int plasma_1DS_init(plasma_1DS_data* data, int nrho, real rhomin, real rhomax, 27 | int nion, int* anum, int* znum, real* mass, real* charge, 28 | real* Te, real* Ti, real* ne, real* ni, real* vtor); 29 | void plasma_1DS_free(plasma_1DS_data* data); 30 | void plasma_1DS_offload(plasma_1DS_data* data); 31 | GPU_DECLARE_TARGET_SIMD_UNIFORM(pls_data) 32 | a5err plasma_1DS_eval_temp(real* temp, real rho, int species, 33 | plasma_1DS_data* pls_data); 34 | DECLARE_TARGET_END 35 | GPU_DECLARE_TARGET_SIMD_UNIFORM(pls_data) 36 | a5err plasma_1DS_eval_dens(real* dens, real rho, int species, 37 | plasma_1DS_data* pls_data); 38 | DECLARE_TARGET_END 39 | GPU_DECLARE_TARGET_SIMD_UNIFORM(pls_data) 40 | a5err plasma_1DS_eval_densandtemp(real* dens, real* temp, real rho, 41 | plasma_1DS_data* pls_data); 42 | DECLARE_TARGET_END 43 | GPU_DECLARE_TARGET_SIMD_UNIFORM(pls_data) 44 | a5err plasma_1DS_eval_flow(real* vflow, real rho, real r, 45 | plasma_1DS_data* pls_data); 46 | DECLARE_TARGET_END 47 | #endif 48 | -------------------------------------------------------------------------------- /src/plasma/plasma_1D.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file plasma_1D.h 3 | * @brief Header file for plasma_1D.c 4 | */ 5 | #ifndef PLASMA_1D_H 6 | #define PLASMA_1D_H 7 | #include "../ascot5.h" 8 | #include "../offload.h" 9 | #include "../error.h" 10 | 11 | /** 12 | * @brief 1D plasma parameters on the target 13 | */ 14 | typedef struct { 15 | int n_rho; /**< number of rho values in the data */ 16 | int n_species; /**< number of plasma species including electrons */ 17 | real* mass; /**< plasma species masses [kg] */ 18 | real* charge; /**< plasma species charges [C] */ 19 | int* anum; /**< ion species atomic number */ 20 | int* znum; /**< ion species charge number */ 21 | real* rho; /**< pointer to start of rho values */ 22 | real* temp; /**< pointer to start of temperatures */ 23 | real* dens; /**< pointer to start of densities */ 24 | real* vtor; /**< pointer to start of toroidal rotation */ 25 | } plasma_1D_data; 26 | 27 | int plasma_1D_init(plasma_1D_data* data, int nrho, int nion, real* rho, 28 | int* anum, int* znum, real* mass, real* charge, 29 | real* Te, real* Ti, real* ne, real* ni, real* vtor); 30 | void plasma_1D_free(plasma_1D_data* data); 31 | void plasma_1D_offload(plasma_1D_data* data); 32 | GPU_DECLARE_TARGET_SIMD_UNIFORM(pls_data) 33 | a5err plasma_1D_eval_temp(real* dens, real rho, int species, 34 | plasma_1D_data* pls_data); 35 | DECLARE_TARGET_END 36 | GPU_DECLARE_TARGET_SIMD_UNIFORM(pls_data) 37 | a5err plasma_1D_eval_dens(real* temp, real rho, int species, 38 | plasma_1D_data* pls_data); 39 | DECLARE_TARGET_END 40 | GPU_DECLARE_TARGET_SIMD_UNIFORM(pls_data) 41 | a5err plasma_1D_eval_densandtemp(real* dens, real* temp, real rho, 42 | plasma_1D_data* pls_data); 43 | DECLARE_TARGET_END 44 | GPU_DECLARE_TARGET_SIMD_UNIFORM(pls_data) 45 | a5err plasma_1D_eval_flow(real* vflow, real rho, real r, 46 | plasma_1D_data* pls_data); 47 | DECLARE_TARGET_END 48 | 49 | #endif 50 | -------------------------------------------------------------------------------- /a5py/physlib/evaluate.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | 3 | 4 | def evaluate(quantity, m=None, q=None, r=None, phi=None, z=None, pvec=None, 5 | mu=None, ppar=None, zeta=None, b=None): 6 | """ 7 | Evaluate derived quantities from the given quantities. 8 | 9 | Note that it is enough to pass enough parameters that are needed to evaluate 10 | the queried quantity. 11 | """ 12 | 13 | if quantity in ["xprt", "xgc"]: 14 | return coords.xcoord(r=r, phi=phi) 15 | 16 | if quantity in ["yprt", "ygc"]: 17 | return coords.ycoord(r=r, phi=phi) 18 | 19 | if quantity in ["energyprt"]: 20 | return energy_momentum(m=m, p=pvec) 21 | 22 | if quantity in ["energygc"]: 23 | return energy_muppar(m=m, mu=mu, ppar=ppar, b=b) 24 | 25 | if quantity in ["pitchprt"]: 26 | return pitch_momentum(p=pvec, b=b) 27 | 28 | if quantity in ["pitchgc"]: 29 | return pitch_muppar(m=m, mu=mu, ppar=ppar, b=b) 30 | 31 | if quantity in ["muprt"]: 32 | return mu_momentum(m=m, p=pvec, b=b) 33 | 34 | if quantity in ["pparprt"]: 35 | return mu_momentum(m=m, p=pvec, b=b) 36 | 37 | if quantity in ["vparprt"]: 38 | return mu_momentum(m=m, p=pvec, b=b) 39 | 40 | if quantity in ["pnormprt"]: 41 | return np.sqrt( np.sum(pvec**2, axis=1) ) 42 | 43 | if quantity in ["vvecprt", "vrprt", "vphiprt", "vzprt", "vnormprt"]: 44 | vvec = velocity_momentum(pvec) 45 | if quantity == "vvecprt": 46 | return vvec 47 | if quantity == "vrprt": 48 | return vvec[0] 49 | if quantity == "vphiprt": 50 | return vvec[1] 51 | if quantity == "vzprt": 52 | return vvec[2] 53 | if quantity == "vnormprt": 54 | return np.sqrt( np.sum(vvec**2) ) 55 | 56 | if quantity in ["vrgc", "vphigc", "vzgc", "vnormgc", "vvecgc"]: 57 | if quantity == "vvecgc": 58 | return vvec 59 | if quantity == "vrgc": 60 | return vvec[0] 61 | if quantity == "vphigc": 62 | return vvec[1] 63 | if quantity == "vzgc": 64 | return vvec[2] 65 | if quantity == "vnormgc": 66 | return np.sqrt( np.sum(vvec**2) ) 67 | -------------------------------------------------------------------------------- /.github/workflows/docs.yaml: -------------------------------------------------------------------------------- 1 | name: (Reusable) Generate Documentation 2 | on: 3 | workflow_call: 4 | inputs: 5 | publish: 6 | description: "Publish generated docs" 7 | type: boolean 8 | required: false 9 | default: false 10 | 11 | jobs: 12 | Build-HTML: 13 | permissions: 14 | contents: read 15 | packages: read 16 | runs-on: ubuntu-latest 17 | defaults: 18 | run: 19 | shell: bash -el {0} 20 | 21 | steps: 22 | - uses: actions/checkout@v4 23 | 24 | - uses: conda-incubator/setup-miniconda@v3 25 | with: 26 | auto-update-conda: true 27 | python-version: "3.10" 28 | environment-file: environment-dev.yaml 29 | activate-environment: ascot-dev 30 | auto-activate-base: false 31 | 32 | - name: Setup headless display 33 | uses: pyvista/setup-headless-display-action@v3 34 | 35 | - name: Install a5py 36 | run: python -m pip install -e .[doc] 37 | 38 | - uses: actions/download-artifact@v4 39 | with: 40 | name: code 41 | 42 | - name: Unpack 43 | run: | 44 | mkdir build 45 | tar -xf code.tar -C ./build/ 46 | 47 | - name: Clone figures repository 48 | uses: actions/checkout@v4 49 | with: 50 | repository: ascot4fusion/figures 51 | ssh-key: ${{ secrets.SSH_KEY_FIGURES }} 52 | path: figures 53 | 54 | - name: Tutorials 55 | working-directory: ./a5py/testascot/ 56 | run: python tutorials.py 57 | 58 | - name: Sphinx build 59 | run: | 60 | make doc 61 | 62 | - name: Upload artifact 63 | if: ${{ inputs.publish == true }} 64 | uses: actions/upload-pages-artifact@v3 65 | with: 66 | path: ./build/doc 67 | 68 | Publish: 69 | needs: Build-HTML 70 | permissions: 71 | contents: read 72 | pages: write 73 | id-token: write 74 | environment: 75 | name: github-pages 76 | url: ${{ steps.deployment.outputs.page_url }} 77 | runs-on: ubuntu-latest 78 | if: ${{ inputs.publish == true }} 79 | 80 | steps: 81 | - name: Publish 82 | id: deployment 83 | uses: actions/deploy-pages@v4 84 | -------------------------------------------------------------------------------- /src/diag/diag_transcoef.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file diag_transcoef.h 3 | * @brief Header file for diag_transcoef.c. 4 | * 5 | * Contains definitions for transport coefficient data structures. 6 | */ 7 | #ifndef DIAG_TRANSCOEF_H 8 | #define DIAG_TRANSCOEF_H 9 | 10 | #include "../ascot5.h" 11 | #include "../particle.h" 12 | 13 | /** 14 | * @brief Simple linked list link for storing data points. 15 | */ 16 | typedef struct diag_transcoef_link{ 17 | real rho; /**< Current radial coordinate (R or rho) */ 18 | real time; /**< Current time */ 19 | int pitchsign; /**< Sign of the pitch at this point */ 20 | struct diag_transcoef_link* prevlink; /**< Pointer to the previous link */ 21 | } diag_transcoef_link; 22 | 23 | /** 24 | * @brief Transport coefficient diagnostics offload data struct. 25 | */ 26 | typedef struct{ 27 | integer Nmrk; /**< Number of markers in this simulation */ 28 | int Navg; /**< Data is divided into subarrays of length Navg, before 29 | taking average value and evaluating K and D */ 30 | int recordrho; /**< Flag for whether the spatial unit is rho or R. */ 31 | real interval; /**< Interval at which markers are recorded. */ 32 | diag_transcoef_link** datapoints; /**< Temporary data storage */ 33 | 34 | int* id; /**< Marker ID whose data is stored at this index */ 35 | real* Kcoef; /**< Calculated drift coefficients */ 36 | real* Dcoef; /**< Calculated diffusion coefficients where negative value 37 | means coefficients are/were not calculated */ 38 | 39 | } diag_transcoef_data; 40 | 41 | void diag_transcoef_init(diag_transcoef_data* data); 42 | void diag_transcoef_free(diag_transcoef_data* data); 43 | void diag_transcoef_update_fo(diag_transcoef_data* data, 44 | particle_simd_fo* p_f, particle_simd_fo* p_i); 45 | void diag_transcoef_update_gc(diag_transcoef_data* data, 46 | particle_simd_gc* p_f, particle_simd_gc* p_i); 47 | void diag_transcoef_update_ml(diag_transcoef_data* data, 48 | particle_simd_ml* p_f, particle_simd_ml* p_i); 49 | #endif 50 | -------------------------------------------------------------------------------- /src/diag.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file diag.h 3 | * @brief Header file for diag.c 4 | */ 5 | #ifndef DIAG_H 6 | #define DIAG_H 7 | #include "ascot5.h" 8 | #include "particle.h" 9 | #include "B_field.h" 10 | #include "diag/dist_5D.h" 11 | #include "diag/dist_6D.h" 12 | #include "diag/dist_rho5D.h" 13 | #include "diag/dist_rho6D.h" 14 | #include "diag/dist_com.h" 15 | #include "diag/diag_orb.h" 16 | #include "diag/diag_transcoef.h" 17 | 18 | /** 19 | * @brief Diagnostics data struct 20 | */ 21 | typedef struct { 22 | int diagorb_collect; /**< Flag for collecting orbit data */ 23 | int dist5D_collect; /**< Flag for collecting 5D distribution */ 24 | int dist6D_collect; /**< Flag for collecting 6D distribution */ 25 | int distrho5D_collect; /**< Flag for collecting 5D rho distribution */ 26 | int distrho6D_collect; /**< Flag for collecting 6D rho distribution */ 27 | int distCOM_collect; /**< Flag for collecting COM distribution */ 28 | int diagtrcof_collect; /**< Flag for collecting transport coefficients */ 29 | 30 | diag_orb_data diagorb; /**< Orbit diagnostics data */ 31 | dist_5D_data dist5D; /**< 5D distribution diagnostics data */ 32 | dist_6D_data dist6D; /**< 6D distribution diagnostics data */ 33 | dist_rho5D_data distrho5D; /**< 5D rho distribution diagnosticsd data */ 34 | dist_rho6D_data distrho6D; /**< 6D rho distribution diagnostics data */ 35 | dist_COM_data distCOM; /**< COM distribution diagnostics data */ 36 | diag_transcoef_data diagtrcof; /**< Transp. Coef. diagnostics data */ 37 | 38 | } diag_data; 39 | 40 | int diag_init(diag_data* data, int Nmrk); 41 | void diag_free(diag_data* data); 42 | void diag_offload(diag_data* data); 43 | void diag_onload(diag_data* data); 44 | 45 | void diag_sum(diag_data* data1, diag_data* data2); 46 | 47 | void diag_update_fo(diag_data* data, B_field_data* Bdata, particle_simd_fo* p_f, 48 | particle_simd_fo* p_i); 49 | 50 | void diag_update_gc(diag_data* data, B_field_data* Bdata, particle_simd_gc* p_f, 51 | particle_simd_gc* p_i); 52 | 53 | void diag_update_ml(diag_data* data, particle_simd_ml* p_f, 54 | particle_simd_ml* p_i); 55 | 56 | 57 | #endif 58 | -------------------------------------------------------------------------------- /src/Efield/E_TC.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @file E_TC.c 3 | * @brief Trivial Cartesian Electric field 4 | * 5 | * Electric field that has constant x, y, and z components. Note that this field 6 | * is defined in Cartesian coordinates and not cylindrical. This field is 7 | * intended for testing purposes and to act as a dummy input. 8 | */ 9 | #include 10 | #include "../ascot5.h" 11 | #include "../math.h" 12 | #include "../error.h" 13 | #include "../print.h" 14 | #include "../B_field.h" 15 | #include "E_TC.h" 16 | 17 | /** 18 | * @brief Initialize electric field data and check inputs 19 | * 20 | * @param data pointer to the data struct 21 | * @param exyz electric field vector on cartesian basis [V/m] 22 | * 23 | * @return Zero to indicate initialization succeeded 24 | */ 25 | int E_TC_init(E_TC_data* data, real exyz[3]) { 26 | 27 | data->Exyz[0] = exyz[0]; 28 | data->Exyz[1] = exyz[1]; 29 | data->Exyz[2] = exyz[2]; 30 | 31 | print_out(VERBOSE_IO, "\nTrivial Cartesian electric field (E_TC)\n"); 32 | print_out(VERBOSE_IO, "E_x = %le, E_y = %le, E_z = %le\n", 33 | data->Exyz[0], data->Exyz[1], data->Exyz[2]); 34 | return 0; 35 | } 36 | 37 | /** 38 | * @brief Free allocated resources 39 | * 40 | * @param data pointer to the data struct 41 | */ 42 | void E_TC_free(E_TC_data* data) { 43 | // No resources were allocated 44 | } 45 | 46 | /** 47 | * @brief Offload data to the accelerator. 48 | * 49 | * @param data pointer to the data struct 50 | */ 51 | void E_TC_offload(E_TC_data* data) { 52 | GPU_MAP_TO_DEVICE( data->Exyz[0:3] ) 53 | } 54 | 55 | /** 56 | * @brief Evaluate electric field 57 | * 58 | * Even though this module represents a Cartesian electric field, the returned 59 | * values are given in cylindrical coordinates. 60 | * 61 | * @param E pointer to array where electric field values are stored 62 | * @param r R coordinate [m] 63 | * @param phi phi coordinate [deg] 64 | * @param z z coordinate [m] 65 | * @param Edata pointer to magnetic field data struct 66 | * @param Bdata pointer to magnetic field data struct 67 | * 68 | * @return Zero to indicate success 69 | */ 70 | a5err E_TC_eval_E(real E[3], real r, real phi, real z, E_TC_data* Edata, 71 | B_field_data* Bdata) { 72 | math_vec_xyz2rpz(Edata->Exyz, E, phi); 73 | 74 | return 0; 75 | } 76 | -------------------------------------------------------------------------------- /src/unit_tests/test_linint3D.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @file test_linint3D.c 3 | * @brief Test program for trilinear interpolation 4 | */ 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include "../math.h" 10 | #include "../consts.h" 11 | #include "../linint/linint.h" 12 | 13 | /** 14 | * Main function for the test program. 15 | */ 16 | int main(int argc, char** argv) { 17 | 18 | if(argc < 2) { 19 | printf("Usage: test_linint3D fname\n"); 20 | exit(1); 21 | } 22 | 23 | FILE* f = fopen(argv[1], "w"); 24 | 25 | real val; 26 | 27 | int n_r = 14; 28 | real r_min = 0.0; 29 | real r_max = 2.0; 30 | real r_grid = (r_max - r_min)/(n_r-1); 31 | int n_phi = 4; 32 | real phi_min = 0.0; 33 | real phi_max = 2*CONST_PI; 34 | real phi_grid = (phi_max - phi_min)/(n_phi-1); 35 | int n_z = 70; 36 | real z_min = -2.0; 37 | real z_max = 2.0; 38 | real z_grid = (z_max - z_min)/(n_z-1); 39 | 40 | real* r = (real*) malloc(n_r*10 * sizeof(real)); 41 | math_linspace(r, r_min, r_max, n_r*10); 42 | real* phi = (real*) malloc(n_phi*10 * sizeof(real)); 43 | math_linspace(phi, phi_min, phi_max, n_phi*10); 44 | real* z = (real*) malloc(n_z*10 * sizeof(real)); 45 | math_linspace(z, z_min, z_max, n_z*10); 46 | 47 | /* Initialize test data */ 48 | real* fn = (real*) malloc(n_r * n_z * n_phi * sizeof(real)); 49 | for (int k = 0; k < n_phi; k++) { 50 | for (int j = 0; j < n_z; j++) { 51 | for (int i = 0; i < n_r; i++) { 52 | /* Constant for phi, varying with r and z */ 53 | fn[k*n_z*n_r + j*n_r + i] = z[j*10]*r[i*10]; 54 | } 55 | } 56 | } 57 | 58 | linint3D_data str; 59 | linint3D_init(&str, fn, n_r, n_phi, n_z, 60 | r_min, r_max, r_grid, 61 | phi_min, phi_max, phi_grid, 62 | z_min, z_max, z_grid); 63 | 64 | for (int k = 0; k < n_phi*10; k++) { 65 | for (int j = 0; j < n_z*10; j++) { 66 | for (int i = 0; i < n_r*10; i++) { 67 | linint3D_eval_f(&val, &str, r[i], phi[k], z[j]); 68 | fprintf(f,"%le %le %le %le\n", r[i], z[j], phi[k], val); 69 | } 70 | } 71 | } 72 | 73 | fclose(f); 74 | return 0; 75 | } 76 | -------------------------------------------------------------------------------- /src/mhd/mhd_nonstat.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file mhd_nonstat.h 3 | * @brief Header file for mhd_nonstat.c 4 | */ 5 | #ifndef MHD_NONSTAT_H 6 | #define MHD_NONSTAT_H 7 | 8 | #include "../ascot5.h" 9 | #include "../offload.h" 10 | #include "../error.h" 11 | #include "../boozer.h" 12 | #include "../spline/interp.h" 13 | #include "../B_field.h" 14 | 15 | /** 16 | * @brief MHD parameters 17 | */ 18 | typedef struct { 19 | int n_modes; /**< Number of modes */ 20 | real rho_min; /**< rho grid minimum value */ 21 | real rho_max; /**< rho grid maximum value */ 22 | int* nmode; /**< Toroidal mode numbers */ 23 | int* mmode; /**< Poloidal mode numbers */ 24 | real* amplitude_nm; /**< Amplitude of each mode */ 25 | real* omega_nm; /**< Toroidal frequency [rad/s] */ 26 | real* phase_nm; /**< Phase of each mode [rad] */ 27 | 28 | /** 29 | * @brief 2D splines (rho,time) for each mode's magnetic eigenfunction 30 | */ 31 | interp2D_data* alpha_nm; 32 | /** 33 | * @brief 2D splines (rho,time) for each mode's electric eigenfunction 34 | */ 35 | interp2D_data* phi_nm; 36 | } mhd_nonstat_data; 37 | 38 | int mhd_nonstat_init(mhd_nonstat_data* data, int nmode, int nrho, int ntime, 39 | real rhomin, real rhomax, real tmin, real tmax, 40 | int* moden, int* modem, real* amplitude_nm, 41 | real* omega_nm, real* phase_nm, real* alpha, real* phi); 42 | void mhd_nonstat_free(mhd_nonstat_data* data); 43 | void mhd_nonstat_offload(mhd_nonstat_data* data); 44 | DECLARE_TARGET_SIMD_UNIFORM(boozerdata, mhddata, Bdata, includemode) 45 | a5err mhd_nonstat_eval(real mhd_dmhd[10], real r, real phi, real z, real t, 46 | int includemode, boozer_data* boozerdata, 47 | mhd_nonstat_data* mhddata, B_field_data* Bdata); 48 | DECLARE_TARGET_SIMD_UNIFORM(boozerdata, mhddata, Bdata, pertonly,\ 49 | includemode) 50 | a5err mhd_nonstat_perturbations(real pert_field[7], real r, real phi, real z, 51 | real t, int pertonly, int includemode, 52 | boozer_data* boozerdata, 53 | mhd_nonstat_data* mhddata, B_field_data* Bdata); 54 | 55 | 56 | #endif 57 | -------------------------------------------------------------------------------- /a5py/gui/guiparams.py: -------------------------------------------------------------------------------- 1 | """Store and retrieve GUI related parameters to/from HDF5 2 | """ 3 | import numpy as np 4 | import h5py 5 | 6 | class GUIparams(): 7 | 8 | def __init__(self): 9 | self.params = {} 10 | 11 | def add(self, **kwargs): 12 | """Add parameters. 13 | """ 14 | for k in kwargs.keys(): 15 | self.params[k] = kwargs[k] 16 | 17 | def store(self, hdf5, params): 18 | """Stores parameter(s) to HDF5. 19 | 20 | Only stores the ones whose name is on the given list "params". 21 | """ 22 | 23 | with h5py.File(hdf5, "a") as h5: 24 | if "gui" not in h5.keys(): 25 | h5.create_group("gui") 26 | 27 | group = h5["gui"] 28 | def store_dataset(name, dtype): 29 | """For storing datasets 30 | """ 31 | if name not in params: 32 | return 33 | 34 | if name not in group.keys(): 35 | group.create_dataset(name, data=self.params[name].get(), 36 | dtype=dtype) 37 | else: 38 | group[name][()] = self.params[name].get() 39 | 40 | S = h5py.string_dtype(encoding='utf-8', length=None) 41 | store_dataset("input_rzplot_minr", "f8") 42 | store_dataset("input_rzplot_maxr", "f8") 43 | store_dataset("input_rzplot_numr", "i8") 44 | store_dataset("input_rzplot_minz", "f8") 45 | store_dataset("input_rzplot_maxz", "f8") 46 | store_dataset("input_rzplot_numz", "i8") 47 | store_dataset("input_rzplot_qnt", S) 48 | 49 | def retrieve(self, hdf5): 50 | """Retrieves parameter(s) from HDF5. 51 | """ 52 | S = h5py.string_dtype(encoding='utf-8', length=None) 53 | try: 54 | with h5py.File(hdf5, "r") as h5: 55 | if "gui" in h5.keys(): 56 | for k in h5["gui"]: 57 | if k in self.params.keys(): 58 | val = h5["gui"][k] 59 | if val.dtype == S: 60 | self.params[k].set(val.asstr()[()]) 61 | else: 62 | self.params[k].set(val[()]) 63 | 64 | except: 65 | pass 66 | -------------------------------------------------------------------------------- /src/unit_tests/test_plasma.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @file test_plasma.c 3 | * @brief Test program for plasma evaluation functions 4 | */ 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include "../math.h" 10 | #include "../plasma.h" 11 | #include "../hdf5_interface.h" 12 | #include "../offload.h" 13 | 14 | /** 15 | * Main function for the test program. 16 | */ 17 | int main(int argc, char** argv) { 18 | 19 | if(argc < 11) { 20 | printf("Usage: test_plasma nr rmin rmax nphi phimin phimax nz zmin zmax fname\n"); 21 | exit(1); 22 | } 23 | 24 | FILE* f = fopen(argv[10], "w"); 25 | 26 | sim_offload_data sim; 27 | sim.mpi_rank = 0; 28 | sim.mpi_size = 1; 29 | 30 | real* B_offload_array; 31 | real* E_offload_array; 32 | real* plasma_offload_array; 33 | real* neutral_offload_array; 34 | real* wall_offload_array; 35 | int* wall_int_offload_array; 36 | real* offload_array; 37 | int n; 38 | input_particle* p; 39 | 40 | /* read_options(argc, argv, &sim); */ 41 | strcpy(sim.hdf5_in, "ascot.h5"); 42 | strcpy(sim.hdf5_out, "ascot"); 43 | 44 | hdf5_interface_read_input(&sim, 45 | hdf5_input_plasma, 46 | &B_offload_array, 47 | &E_offload_array, 48 | &plasma_offload_array, 49 | &neutral_offload_array, 50 | &wall_offload_array, 51 | &wall_int_offload_array, 52 | NULL, 53 | NULL, 54 | &p, 55 | &n); 56 | /* Init plasma */ 57 | offload_package offload_data; 58 | offload_init_offload(&offload_data, &offload_array); 59 | offload_pack(&offload_data, &offload_array, plasma_offload_array, 60 | sim.plasma_offload_data.offload_array_length); 61 | 62 | plasma_data data; 63 | plasma_init(&data, &sim.plasma_offload_data, plasma_offload_array); 64 | 65 | int species = 1; 66 | 67 | real rho, dens; 68 | for(rho = 0.0; rho <= 1.1; rho += 0.005) { 69 | plasma_eval_dens(&dens, rho, 0, 0, 0, 0, species, &data); 70 | fprintf(f,"%le %le\n", rho, dens); 71 | } 72 | 73 | fclose(f); 74 | return 0; 75 | } 76 | -------------------------------------------------------------------------------- /a5py/m3_template/macro/test_macro.py: -------------------------------------------------------------------------------- 1 | import imaspy 2 | import libmuscle 3 | from ymmsl import Operator 4 | 5 | import tools 6 | 7 | # ---- IN/OUT IDSes ---- 8 | equilibrium_3d, equilibrium, core_profiles, distribution_sources, wall2d, wall3d = tools.get_inputs() 9 | distributions = imaspy.IDSFactory().distributions() 10 | 11 | # # # # - - - M3 INITIALISATION - - - # # # # 12 | ports = {Operator.O_I: ["equilibrium_3d_out","equilibrium_out", "core_profiles_out","distribution_sources_out", "wall2d_out", "wall3d_out"], 13 | Operator.S: ["distributions_in"]} 14 | 15 | m3_instance = libmuscle.Instance(ports) 16 | 17 | # # # # - - - MUSCLE3 LOOP - - - # # # # 18 | while m3_instance.reuse_instance(): 19 | 20 | # F_INIT 21 | t_max = m3_instance.get_setting('t_max', 'float') 22 | dt = m3_instance.get_setting('dt', 'float') 23 | 24 | t_cur = 0.0 25 | 26 | while t_cur + dt <= t_max: 27 | # O_I 28 | t_next = t_cur + dt 29 | 30 | if t_next + dt > t_max: 31 | t_next = None 32 | 33 | # # # # - - - SENDING OUTPUT IDSes - - - # # # # 34 | tools.send_ids(m3_instance, equilibrium_3d, "equilibrium_3d_out", t_cur, t_next) 35 | tools.send_ids(m3_instance, equilibrium, "equilibrium_out", t_cur, t_next) 36 | tools.send_ids(m3_instance, core_profiles, "core_profiles_out", t_cur, t_next) 37 | tools.send_ids(m3_instance, distribution_sources, "distribution_sources_out", t_cur, t_next) 38 | tools.send_ids(m3_instance, wall2d, "wall2d_out", t_cur, t_next) 39 | tools.send_ids(m3_instance, wall3d, "wall3d_out", t_cur, t_next) 40 | 41 | # # # # - - - RECEIVING INPUT IDSes - - - # # # # 42 | 43 | print('Waiting for distributions') 44 | # core_profiles_in 45 | m3_message = m3_instance.receive('distributions_in') 46 | print('DISTRIBUTIONS received') 47 | 48 | if m3_message.timestamp > t_cur + dt: 49 | m3_instance.error_shutdown('Received a message from the future!') 50 | 51 | ids_bytes = m3_message.data 52 | distributions.deserialize(ids_bytes) 53 | 54 | if len(distributions.time) < 1: 55 | m3_instance.error_shutdown("ERROR: Received empty TIME vector!") 56 | exit(1) 57 | 58 | print("TIME received ", distributions.time) 59 | 60 | t_cur = t_cur + dt 61 | # > > > > THE END OF MUSCLE3 LOOP 62 | -------------------------------------------------------------------------------- /src/Bfield/B_2DS.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file B_2DS.h 3 | * @brief Header file for B_2DS.c 4 | * 5 | * Contains declaration of B_2DS_offload_data and B_2DS_data structs. 6 | */ 7 | #ifndef B_2DS_H 8 | #define B_2DS_H 9 | #include "../offload.h" 10 | #include "../ascot5.h" 11 | #include "../error.h" 12 | #include "../spline/interp.h" 13 | 14 | /** 15 | * @brief 2D magnetic field parameters 16 | */ 17 | typedef struct { 18 | real psi0; /**< Poloidal flux value at magnetic axis [V*s*m^-1] */ 19 | real psi1; /**< Poloidal flux value at separatrix [V*s*m^-1] */ 20 | real axis_r; /**< R coordinate of magnetic axis [m] */ 21 | real axis_z; /**< z coordinate of magnetic axis [m] */ 22 | interp2D_data psi; /**< psi interpolation 2D spline struct */ 23 | interp2D_data B_r; /**< B_R interpolation 2D spline struct */ 24 | interp2D_data B_phi; /**< B_phi interpolation 2D spline struct */ 25 | interp2D_data B_z; /**< B_z interpolation 2D spline struct */ 26 | } B_2DS_data; 27 | 28 | int B_2DS_init(B_2DS_data* data, 29 | int n_r, real r_min, real r_max, 30 | int n_z, real z_min, real z_max, 31 | real axis_r, real axis_z, real psi0, real psi1, 32 | real* psi, real* B_r, real* B_phi, real* B_z); 33 | void B_2DS_free(B_2DS_data* data); 34 | void B_2DS_offload(B_2DS_data* data); 35 | GPU_DECLARE_TARGET_SIMD_UNIFORM(Bdata) 36 | a5err B_2DS_eval_psi(real* psi, real r, real phi, real z, B_2DS_data* Bdata); 37 | DECLARE_TARGET_END 38 | GPU_DECLARE_TARGET_SIMD_UNIFORM(Bdata) 39 | a5err B_2DS_eval_psi_dpsi(real psi_dpsi[4], real r, real phi, real z, 40 | B_2DS_data* Bdata); 41 | DECLARE_TARGET_END 42 | GPU_DECLARE_TARGET_SIMD_UNIFORM(Bdata) 43 | a5err B_2DS_eval_rho_drho(real rho_drho[4], real r, real phi, real z, 44 | B_2DS_data* Bdata); 45 | DECLARE_TARGET_END 46 | GPU_DECLARE_TARGET_SIMD_UNIFORM(Bdata) 47 | a5err B_2DS_eval_B(real B[3], real r, real phi, real z, B_2DS_data* Bdata); 48 | DECLARE_TARGET_END 49 | GPU_DECLARE_TARGET_SIMD_UNIFORM(Bdata) 50 | a5err B_2DS_eval_B_dB(real B_dB[12], real r, real phi, real z, B_2DS_data* Bdata); 51 | DECLARE_TARGET_END 52 | GPU_DECLARE_TARGET_SIMD_UNIFORM(Bdata) 53 | a5err B_2DS_get_axis_rz(real rz[2], B_2DS_data* Bdata); 54 | DECLARE_TARGET_END 55 | #endif 56 | -------------------------------------------------------------------------------- /src/list.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @file list.c 3 | * @brief Simple linked list 4 | * 5 | * Linked list where each node stores an int data and a pointer to the next node 6 | * in chain. 7 | */ 8 | #include 9 | #include "list.h" 10 | 11 | /** 12 | * @brief Create an empty list 13 | * 14 | * @param list pointer to the created list 15 | */ 16 | void list_int_create(list_int_node** list) { 17 | (*list) = (list_int_node*) malloc(sizeof(list_int_node)); 18 | (*list)->data = 0; 19 | (*list)->next = NULL; 20 | 21 | } 22 | 23 | /** 24 | * @brief Deallocate this list and all lists it is linked to 25 | * 26 | * @param list pointer to the list to be freed 27 | */ 28 | void list_int_free(list_int_node** list) { 29 | list_int_node* node = (*list); 30 | int n = list_int_size(*list); 31 | list_int_node* next_node = (*list)->next; 32 | int i; 33 | for(i = 0; i < n; i++) { 34 | free(node); 35 | node = next_node; 36 | next_node = next_node->next; 37 | } 38 | free(node); 39 | (*list) = NULL; 40 | } 41 | 42 | /** 43 | * @brief Add new node to the end of the chain 44 | * 45 | * @param list list node to which new node is linked 46 | * @param data int value to be stored in the new node 47 | */ 48 | void list_int_add(list_int_node* list, int data) { 49 | list_int_node* node = list; 50 | while(node->next != NULL) { 51 | node = node->next; 52 | } 53 | 54 | list_int_node* new_node = (list_int_node*) malloc(sizeof(list_int_node)); 55 | new_node->next = NULL; 56 | 57 | node->next = new_node; 58 | node->data = data; 59 | } 60 | 61 | /** 62 | * @brief Retrieve the data stored in a list node 63 | * 64 | * @param list list node 65 | * @param index node index where data is retrieved, zero refers to current node 66 | * 67 | * @return the stored data 68 | */ 69 | int list_int_get(list_int_node* list, int index) { 70 | int i = 0; 71 | list_int_node* node = list; 72 | while(i < index) { 73 | node = node->next; 74 | i++; 75 | } 76 | return node->data; 77 | } 78 | 79 | /** 80 | * @brief Get list size 81 | * 82 | * @param list list node 83 | * 84 | * @return number of nodes this node is linked to 85 | */ 86 | int list_int_size(list_int_node* list) { 87 | int i = 0; 88 | list_int_node* node = list; 89 | while(node->next != NULL) { 90 | node = node->next; 91 | i++; 92 | } 93 | return i; 94 | } 95 | -------------------------------------------------------------------------------- /a5py/templates/optiontemplates.py: -------------------------------------------------------------------------------- 1 | """Options templates for various simulations 2 | """ 3 | from a5py.ascot5io.options import Opt 4 | 5 | class OptionTemplates(): 6 | """All options templates. 7 | """ 8 | 9 | def options_tutorial(self): 10 | """Create fast slowing-down simulation options with orbits and 11 | distributions enabled. 12 | 13 | Returns 14 | ------- 15 | gtype : str 16 | Type of the generated input data. 17 | data : dict 18 | Input data that can be passed to ``write_hdf5`` method of 19 | a corresponding type. 20 | """ 21 | out = Opt.get_default() 22 | out.update( 23 | {"SIM_MODE":2, "ENABLE_ADAPTIVE":1, 24 | "ENDCOND_SIMTIMELIM":1, "ENDCOND_CPUTIMELIM":1, 25 | "ENDCOND_ENERGYLIM":1, "ENDCOND_WALLHIT":1, 26 | "ENDCOND_LIM_SIMTIME":0.5, "ENDCOND_MAX_MILEAGE":0.5, 27 | "ENDCOND_MAX_CPUTIME":1.0e1, "ENDCOND_MIN_ENERGY":2.0e3, 28 | "ENDCOND_MIN_THERMAL":2.0, 29 | "ENABLE_ORBIT_FOLLOWING":1, "ENABLE_COULOMB_COLLISIONS":1, 30 | "ENABLE_DIST_5D":1, "ENABLE_DIST_6D":1, 31 | "ENABLE_DIST_RHO5D":1, "ENABLE_DIST_RHO6D":1, 32 | "ENABLE_DIST_COM":1, 33 | "DIST_MIN_R":3.5, "DIST_MAX_R":8.5, "DIST_NBIN_R":12, 34 | "DIST_MIN_PHI":0, "DIST_MAX_PHI":360, "DIST_NBIN_PHI":20, 35 | "DIST_MIN_Z":-2.45, "DIST_MAX_Z":2.45, "DIST_NBIN_Z":24, 36 | "DIST_MIN_RHO":0, "DIST_MAX_RHO":1, "DIST_NBIN_RHO":11, 37 | "DIST_MIN_THETA":0, "DIST_MAX_THETA":360, "DIST_NBIN_THETA":13, 38 | "DIST_MIN_PPA":-10e-20,"DIST_MAX_PPA":10e-20,"DIST_NBIN_PPA":36, 39 | "DIST_MIN_PPE":0, "DIST_MAX_PPE":10e-20, "DIST_NBIN_PPE":18, 40 | "DIST_MIN_PR":-10e-20, "DIST_MAX_PR":10e-20, 41 | "DIST_NBIN_PR":14, 42 | "DIST_MIN_PPHI":-10e-20, "DIST_MAX_PPHI":10e-20, 43 | "DIST_NBIN_PPHI":15, 44 | "DIST_MIN_PZ":-10e-20, "DIST_MAX_PZ":10e-20, "DIST_NBIN_PZ":16, 45 | "DIST_MIN_TIME":0, "DIST_MAX_TIME":3e-2, "DIST_NBIN_TIME":2, 46 | "DIST_MIN_CHARGE":-1.5, "DIST_MAX_CHARGE":2.5, 47 | "DIST_NBIN_CHARGE":1, 48 | "ENABLE_ORBITWRITE":1, "ORBITWRITE_MODE":1, 49 | "ORBITWRITE_NPOINT":100, "ORBITWRITE_INTERVAL":0,} 50 | ) 51 | return ("opt", out) 52 | -------------------------------------------------------------------------------- /src/plasma/plasma_1Dt.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file plasma_1Dt.h 3 | * @brief Header file for plasma_1Dt.c 4 | */ 5 | #ifndef PLASMA_1DT_H 6 | #define PLASMA_1DT_H 7 | #include "../ascot5.h" 8 | #include "../offload.h" 9 | #include "../error.h" 10 | 11 | /** 12 | * @brief 1D plasma parameters on the target 13 | */ 14 | typedef struct { 15 | int n_rho; /**< number of rho values in the data */ 16 | int n_time; /**< number of time points */ 17 | int n_species; /**< number of plasma species including electrons */ 18 | real* mass; /**< plasma species masses [kg] */ 19 | real* charge; /**< plasma species charges [C] */ 20 | int* anum; /**< ion species atomic number */ 21 | int* znum; /**< ion species charge number */ 22 | real* rho; /**< pointer to start of rho values */ 23 | real* time; /**< pointer to start of time values */ 24 | real* temp; /**< pointer to start of temperatures */ 25 | real* dens; /**< pointer to start of densities */ 26 | real* vtor; /**< pointer to start of toroidal rotation */ 27 | } plasma_1Dt_data; 28 | 29 | int plasma_1Dt_init(plasma_1Dt_data* data, int nrho, int ntime, int nion, 30 | real* rho, real* time, int* anum, int* znum, real* mass, 31 | real* charge, real* Te, real* Ti, real* ne, real* ni, 32 | real* vtor); 33 | void plasma_1Dt_free(plasma_1Dt_data* pls_data); 34 | void plasma_1Dt_offload(plasma_1Dt_data* pls_data); 35 | GPU_DECLARE_TARGET_SIMD_UNIFORM(pls_data) 36 | a5err plasma_1Dt_eval_temp(real* dens, real rho, real t, int species, 37 | plasma_1Dt_data* pls_data); 38 | DECLARE_TARGET_END 39 | GPU_DECLARE_TARGET_SIMD_UNIFORM(pls_data) 40 | a5err plasma_1Dt_eval_dens(real* temp, real rho, real t, int species, 41 | plasma_1Dt_data* pls_data); 42 | DECLARE_TARGET_END 43 | GPU_DECLARE_TARGET_SIMD_UNIFORM(pls_data) 44 | a5err plasma_1Dt_eval_densandtemp(real* dens, real* temp, real rho, real t, 45 | plasma_1Dt_data* pls_data); 46 | DECLARE_TARGET_END 47 | GPU_DECLARE_TARGET_SIMD_UNIFORM(pls_data) 48 | a5err plasma_1Dt_eval_flow(real* vflow, real rho, real t, real r, 49 | plasma_1Dt_data* pls_data); 50 | DECLARE_TARGET_END 51 | 52 | #endif 53 | -------------------------------------------------------------------------------- /src/mhd.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file mhd.h 3 | * @brief Header file for mhd.c 4 | * 5 | * Contains a list declaring all mhd_types, and declaration of 6 | * mhd_offload_data and mhd_data structs. 7 | */ 8 | #ifndef MHD_H 9 | #define MHD_H 10 | 11 | #include "ascot5.h" 12 | #include "error.h" 13 | #include "B_field.h" 14 | #include "boozer.h" 15 | #include "mhd/mhd_stat.h" 16 | #include "mhd/mhd_nonstat.h" 17 | 18 | /** @brief includemode parameter to include all modes (default) */ 19 | #define MHD_INCLUDE_ALL -1 20 | 21 | /** 22 | * @brief MHD input types 23 | */ 24 | typedef enum mhd_type { 25 | mhd_type_stat, /**< MHD where mode amplitude does not depend on time */ 26 | mhd_type_nonstat /**< MHD where mode amplitude depends on time */ 27 | } mhd_type; 28 | 29 | /** 30 | * @brief MHD simulation data 31 | * 32 | * The intended usage is that only single type of data is used at a time. This 33 | * is declared using the `type` field. 34 | */ 35 | typedef struct { 36 | mhd_type type; /**< MHD type wrapped by this struct */ 37 | mhd_stat_data stat; /**< Stat field or NULL if not active */ 38 | mhd_nonstat_data nonstat; /**< Nonstat field or NULL if not active */ 39 | } mhd_data; 40 | 41 | void mhd_free(mhd_data* data); 42 | void mhd_offload(mhd_data* data); 43 | DECLARE_TARGET_SIMD_UNIFORM(boozerdata, mhddata, Bdata, includemode) 44 | a5err mhd_eval(real mhd_dmhd[10], real r, real phi, real z, real t, 45 | int includemode, boozer_data* boozerdata, mhd_data* mhddata, 46 | B_field_data* Bdata); 47 | DECLARE_TARGET_SIMD_UNIFORM(boozerdata, mhddata, Bdata, pertonly,\ 48 | includemode) 49 | a5err mhd_perturbations(real pert_field[7], real r, real phi, real z, 50 | real t, int pertonly, int includemode, 51 | boozer_data* boozerdata, mhd_data* mhddata, 52 | B_field_data* Bdata); 53 | DECLARE_TARGET_SIMD_UNIFORM(mhddata) 54 | int mhd_get_n_modes(mhd_data* mhddata); 55 | DECLARE_TARGET_SIMD_UNIFORM(mhddata) 56 | const int* mhd_get_nmode(mhd_data* mhddata); 57 | DECLARE_TARGET_SIMD_UNIFORM(mhddata) 58 | const int* mhd_get_mmode(mhd_data* mhddata); 59 | DECLARE_TARGET_SIMD_UNIFORM(mhddata) 60 | const real* mhd_get_amplitude(mhd_data* mhddata); 61 | DECLARE_TARGET_SIMD_UNIFORM(mhddata) 62 | const real* mhd_get_frequency(mhd_data* mhddata); 63 | DECLARE_TARGET_SIMD_UNIFORM(mhddata) 64 | const real* mhd_get_phase(mhd_data* mhddata); 65 | #endif 66 | -------------------------------------------------------------------------------- /src/nbi.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file nbi.h 3 | * @brief Header file for nbi.c 4 | */ 5 | #ifndef NBI_H 6 | #define NBI_H 7 | 8 | #include "ascot5.h" 9 | #include "particle.h" 10 | #include "random.h" 11 | 12 | /** 13 | * @brief Structure for describing an NBI injector 14 | */ 15 | typedef struct { 16 | int id; /**< integer identifier for this injector */ 17 | int n_beamlet; /**< number of beamlets in this injector */ 18 | real* beamlet_x; /**< x coordinates of beamlets [m] */ 19 | real* beamlet_y; /**< y coordinates of beamlets [m] */ 20 | real* beamlet_z; /**< z coordinates of beamlets [m] */ 21 | real* beamlet_dx; /**< x components of beamlet unit direction vectors */ 22 | real* beamlet_dy; /**< y components of beamlet unit direction vectors */ 23 | real* beamlet_dz; /**< z components of beamlet unit direction vectors */ 24 | real power; /**< this injector's power injected [W] */ 25 | real energy; /**< full energy of injected particles [J] */ 26 | real efrac[3]; /**< fractions of full, 1/2 and 1/3 energy */ 27 | real div_h; /**< vertical divergence [rad] */ 28 | real div_v; /**< horizontal divergence [rad] */ 29 | real div_halo_frac; /**< fraction of power in the halo */ 30 | real div_halo_h; /**< horizontal divergence of the halo [rad] */ 31 | real div_halo_v; /**< vertical divergence of the halo [rad] */ 32 | int anum; /**< mass number of injected species */ 33 | int znum; /**< charge number of injected species */ 34 | real mass; /**< mass of injected species [kg] */ 35 | } nbi_injector; 36 | 37 | /** 38 | * @brief NBI data consisting of `ninj` injectors. 39 | */ 40 | typedef struct { 41 | int ninj; /**< number of injectors */ 42 | nbi_injector* inj; /**< array of injectors */ 43 | } nbi_data; 44 | 45 | int nbi_init(nbi_data* data, int ninj, int* id, int* anum, int* znum, 46 | real* mass, real* power, real* efrac, real* energy, 47 | real* div_h, real* div_v, real* div_halo_v, real* div_halo_h, 48 | real* div_halo_frac, int* nbeamlet, real* beamlet_xyz); 49 | void nbi_free(nbi_data* nbi); 50 | void nbi_inject(real* xyz, real* vxyz, nbi_injector* inj, random_data* rng); 51 | 52 | #endif 53 | -------------------------------------------------------------------------------- /src/Bfield/B_TC.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file B_TC.h 3 | * @brief Header file for B_TC.c 4 | * 5 | * Contains declaration of B_TC_offload_data and B_TC_data structs. 6 | */ 7 | #ifndef B_TC_H 8 | #define B_TC_H 9 | #include "../offload.h" 10 | #include "../ascot5.h" 11 | #include "../error.h" 12 | 13 | /** 14 | * @brief TC magnetic field parameters on the target 15 | */ 16 | typedef struct { 17 | real axisr; /**< A value that is returned when magnetic axis 18 | R coordinate is requested [m] */ 19 | real axisz; /**< A value that is returned when magnetic axis 20 | z coordinate is requested [m] */ 21 | real psival; /**< A value that is returned when poloidal magnetic flux 22 | value is requested [V*s*m^-1] */ 23 | real rhoval; /**< A value that is returened when normalized poloidal flux 24 | value is requested */ 25 | real B[3]; /**< Magnetic field at origo: [B_x, B_y, B_z] [T] */ 26 | real dB[9]; /**< Magnetic field Jacobian: 27 | [dB_x/dx, dB_x/dy, dB_x/dz, 28 | dB_y/dx, dB_y/dy, dB_y/dz, 29 | dB_z/dx, dB_z/dy, dB_z/dz] [T/m] */ 30 | } B_TC_data; 31 | 32 | int B_TC_init(B_TC_data* data, real axisr, real axisz, real psival, real rhoval, 33 | real B[3], real dB[9]); 34 | void B_TC_free(B_TC_data* data); 35 | void B_TC_offload(B_TC_data* data); 36 | GPU_DECLARE_TARGET_SIMD_UNIFORM(Bdata) 37 | a5err B_TC_eval_B(real B[3], real r, real phi, real z, B_TC_data* Bdata); 38 | DECLARE_TARGET_END 39 | GPU_DECLARE_TARGET_SIMD_UNIFORM(Bdata) 40 | a5err B_TC_eval_psi(real* psi, real r, real phi, real z, B_TC_data* Bdata); 41 | DECLARE_TARGET_END 42 | GPU_DECLARE_TARGET_SIMD_UNIFORM(Bdata) 43 | a5err B_TC_eval_psi_dpsi(real psi_dpsi[4], real r, real phi, real z, 44 | B_TC_data* Bdata); 45 | DECLARE_TARGET_END 46 | GPU_DECLARE_TARGET_SIMD_UNIFORM(Bdata) 47 | a5err B_TC_eval_rho_drho(real rho_drho[4], real r, real phi, real z, 48 | B_TC_data* Bdata); 49 | DECLARE_TARGET_END 50 | GPU_DECLARE_TARGET_SIMD_UNIFORM(Bdata) 51 | a5err B_TC_eval_B_dB(real B_dB[12], real r, real phi, real z, B_TC_data* Bdata); 52 | DECLARE_TARGET_END 53 | GPU_DECLARE_TARGET_SIMD_UNIFORM(Bdata) 54 | a5err B_TC_get_axis_rz(real rz[2], B_TC_data* Bdata); 55 | DECLARE_TARGET_END 56 | 57 | #endif 58 | -------------------------------------------------------------------------------- /src/linint/linint1D.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @file linint1D.c 3 | * @brief Linear interpolation 4 | */ 5 | #include 6 | #include 7 | #include "../ascot5.h" 8 | #include "../math.h" 9 | #include "../spline/interp.h" 10 | #include "linint.h" 11 | 12 | /** 13 | * @brief Initialize linear interpolation struct for scalar 1D data 14 | * 15 | * @param str pointer to struct to be initialized 16 | * @param c array where data is stored 17 | * @param n_x number of data points in the x direction 18 | * @param bc_x boundary condition for x axis 19 | * @param x_min minimum value of the x axis 20 | * @param x_max maximum value of the x axis 21 | */ 22 | void linint1D_init(linint1D_data* str, real* c, 23 | int n_x, int bc_x, real x_min, real x_max) { 24 | 25 | real x_grid = (x_max - x_min) / ( n_x - 1 * (bc_x == NATURALBC) ); 26 | 27 | str->n_x = n_x; 28 | str->bc_x = bc_x; 29 | str->x_min = x_min; 30 | str->x_max = x_max; 31 | str->x_grid = x_grid; 32 | str->c = c; 33 | } 34 | 35 | /** 36 | * @brief Evaluate interpolated value of 1D scalar field 37 | * 38 | * This function evaluates the interpolated value of a 1D scalar field using 39 | * linear interpolation. 40 | * 41 | * @param f variable in which to place the evaluated value 42 | * @param str data struct for data interpolation 43 | * @param x x-coordinate 44 | * 45 | * @return zero on success and one if x point is outside the grid. 46 | */ 47 | int linint1D_eval_f(real* f, linint1D_data* str, real x) { 48 | 49 | /* Make sure periodic coordinates are within [max, min] region. */ 50 | if(str->bc_x == PERIODICBC) { 51 | x = fmod(x - str->x_min, str->x_max - str->x_min) + str->x_min; 52 | x = x + (x < str->x_min) * (str->x_max - str->x_min); 53 | } 54 | 55 | /* index for x variable */ 56 | int i_x = (x-str->x_min) / str->x_grid; 57 | /**< Normalized x coordinate in current cell */ 58 | real dx = ( x - (str->x_min + i_x*str->x_grid)) / str->x_grid; 59 | 60 | int x1 = 1; /* Index jump one x forward */ 61 | 62 | int err = 0; 63 | 64 | /* Enforce periodic BC or check that the coordinate is within the grid. */ 65 | if( str->bc_x == PERIODICBC && i_x == str->n_x-1 ) { 66 | x1 = -(str->n_x-1)*x1; 67 | } 68 | else if( str->bc_x == NATURALBC && !(x >= str->x_min && x <= str->x_max) ) { 69 | err = 1; 70 | } 71 | 72 | if(!err) { 73 | *f = str->c[i_x]*(1 - dx) + str->c[i_x+x1]*dx; 74 | } 75 | return err; 76 | } 77 | -------------------------------------------------------------------------------- /a5py/m3_template/macro/tools.py: -------------------------------------------------------------------------------- 1 | import imaspy 2 | import libmuscle 3 | from imas_core import imasdef 4 | from imas_core.imasdef import CLOSEST_SAMPLE 5 | from imaspy.ids_defs import MDSPLUS_BACKEND 6 | 7 | def send_ids(m3_instance, ids, port_name, t_cur, t_next): 8 | 9 | print('Sends: ', port_name, " : start") 10 | ids_bytes = ids.serialize(imasdef.DEFAULT_SERIALIZER_PROTOCOL) 11 | m3_message = libmuscle.Message(t_cur, t_next, ids_bytes) 12 | m3_instance.send(port_name, m3_message) 13 | print('Sends: ', port_name, " : end") 14 | 15 | def get_ids(ids_name, user, database, shot, run, time): 16 | 17 | print(ids_name, ": READING") 18 | 19 | db_entry = imaspy.DBEntry(MDSPLUS_BACKEND, database, shot, run, user_name=user) 20 | db_entry.open() 21 | ids = db_entry.get_slice(ids_name, time, CLOSEST_SAMPLE) 22 | db_entry.close() 23 | 24 | print(ids_name, ": OK") 25 | 26 | return ids 27 | 28 | 29 | def get_inputs(): 30 | 31 | idsname = 'equilibrium' 32 | uname = 'g2diy' 33 | dbname = 'ggdtest' 34 | shot = 32 35 | run = 3 36 | time = 0.0 37 | equilibrium_3d = get_ids(idsname, uname, dbname, shot, run, time) 38 | 39 | idsname = 'equilibrium' 40 | uname = 'g2diy' 41 | dbname = 'test' 42 | shot = 92436 43 | run = 306 44 | time = 0.0 45 | equilibrium = get_ids(idsname, uname, dbname, shot, run, time) 46 | 47 | idsname = 'core_profiles' 48 | uname = 'g2diy' 49 | dbname = 'test' 50 | shot = 92436 51 | run = 306 52 | time = 0.0 53 | core_profiles = get_ids(idsname, uname, dbname, shot, run, time) 54 | 55 | idsname = 'distribution_sources' 56 | uname = 'g2diy' 57 | dbname = 'test' 58 | shot = 92436 59 | run = 306 60 | time = 0.0 61 | distribution_sources = get_ids(idsname, uname, dbname, shot, run, time) 62 | 63 | idsname = 'wall' 64 | uname = 'g2diy' 65 | dbname = 'test' 66 | shot = 92436 67 | run = 272 68 | time = 0.0 69 | wall2d = get_ids(idsname, uname, dbname, shot, run, time) 70 | 71 | 72 | idsname = 'wall' 73 | uname = 'g2diy' 74 | dbname = 'mywall' 75 | shot = 201 76 | run = 101 77 | time = 0.0 78 | wall3d = get_ids(idsname, uname, dbname, shot, run, time) 79 | 80 | return equilibrium_3d, equilibrium, core_profiles, distribution_sources, wall2d, wall3d 81 | 82 | 83 | if __name__ == "__main__": 84 | equilibrium_3d, equilibrium, core_profiles, distribution_sources, wall2d, wall3d = get_inputs() 85 | print(equilibrium.metadata.name) 86 | -------------------------------------------------------------------------------- /src/Bfield/B_3DS.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file B_3DS.h 3 | * @brief Header file for B_3DS.c 4 | */ 5 | #ifndef B_3DS_H 6 | #define B_3DS_H 7 | #include "../offload.h" 8 | #include "../ascot5.h" 9 | #include "../error.h" 10 | #include "../spline/interp.h" 11 | 12 | /** 13 | * @brief 3D magnetic field parameters 14 | */ 15 | typedef struct { 16 | real psi0; /**< Poloidal flux value at magnetic axis [v*s*m^-1] */ 17 | real psi1; /**< Poloidal flux value at separatrix [V*s*m^-1] */ 18 | real axis_r; /**< R coordinate of magnetic axis [m] */ 19 | real axis_z; /**< z coordinate of magnetic axis [m] */ 20 | interp2D_data psi; /**< 2D psi interpolation data struct */ 21 | interp3D_data B_r; /**< 3D B_r interpolation data struct */ 22 | interp3D_data B_phi; /**< 3D B_phi interpolation data struct */ 23 | interp3D_data B_z; /**< 3D B_z interpolation data struct */ 24 | } B_3DS_data; 25 | 26 | int B_3DS_init(B_3DS_data* data, 27 | int p_n_r, real p_r_min, real p_r_max, 28 | int p_n_z, real p_z_min, real p_z_max, 29 | int b_n_r, real b_r_min, real b_r_max, 30 | int b_n_phi, real b_phi_min, real b_phi_max, 31 | int b_n_z, real b_z_min, real b_z_max, 32 | real axis_r, real axis_z, real psi0, real psi1, 33 | real* psi, real* B_r, real* B_phi, real* B_z); 34 | void B_3DS_free(B_3DS_data* data); 35 | void B_3DS_offload(B_3DS_data* data); 36 | GPU_DECLARE_TARGET_SIMD_UNIFORM(Bdata) 37 | a5err B_3DS_eval_psi(real* psi, real r, real phi, real z, B_3DS_data* Bdata); 38 | DECLARE_TARGET_END 39 | GPU_DECLARE_TARGET_SIMD_UNIFORM(Bdata) 40 | a5err B_3DS_eval_psi_dpsi(real psi_dpsi[4], real r, real phi, real z, 41 | B_3DS_data* Bdata); 42 | DECLARE_TARGET_END 43 | GPU_DECLARE_TARGET_SIMD_UNIFORM(Bdata) 44 | a5err B_3DS_eval_rho_drho(real rho_drho[4], real r, real phi, real z, 45 | B_3DS_data* Bdata); 46 | DECLARE_TARGET_END 47 | GPU_DECLARE_TARGET_SIMD_UNIFORM(Bdata) 48 | a5err B_3DS_eval_B(real B[3], real r, real phi, real z, B_3DS_data* Bdata); 49 | DECLARE_TARGET_END 50 | GPU_DECLARE_TARGET_SIMD_UNIFORM(Bdata) 51 | a5err B_3DS_eval_B_dB(real B_dB[12], real r, real phi, real z, 52 | B_3DS_data* Bdata); 53 | DECLARE_TARGET_END 54 | GPU_DECLARE_TARGET_SIMD_UNIFORM(Bdata) 55 | a5err B_3DS_get_axis_rz(real rz[2], B_3DS_data* Bdata); 56 | DECLARE_TARGET_END 57 | #endif 58 | -------------------------------------------------------------------------------- /a5py/physlib/alias.py: -------------------------------------------------------------------------------- 1 | """ 2 | Module containing widely used synonyms for different quantities. 3 | 4 | Examples: 5 | Check if quantity is mass: 6 | isalias("m", "mass") 7 | True 8 | 9 | Get standard name of the quantity: 10 | getalias("q") 11 | "charge" 12 | 13 | Note that the synonyms are case insensitive and ignore spaces, lowercases and 14 | dashes. 15 | 16 | File: alias.py 17 | """ 18 | 19 | ## Standard name : list of synonyms dictionary. Flag indicates whether quantity 20 | ## is common for both gyro-orbit and guiding-center. 21 | synonyms = { 22 | "ids" : ["id"], 23 | "mass" : ["m"], 24 | "charge" : ["q"], 25 | "vnorm" : ["v", "velocity", "velocitynorm", "|v|"], 26 | "bnorm" : ["b", "magneticfield", "magneticfieldnorm", "|b|"], 27 | "energy" : ["ekin", "e"], 28 | "pitch" : ["xi"], 29 | "mu" : ["magneticmoment"], 30 | "gamma" : ["lorentzfactor", "relativisticfactor"], 31 | "phi" : ["tor", "toroidalangle"], 32 | "phimod" : ["tormod", "phi(mod)", "tor(mod)"], 33 | "theta" : ["pol", "poloidalangle"], 34 | "thetamod" : ["polmod", "pol(mod)", "theta(mod)"], 35 | "zeta" : ["gyroangle"], 36 | "vpar" : ["parallelvelocity", "vparallel", "vpa", "vpara"], 37 | "ppar" : ["parallelmomentum", "pparallel", "ppa", "ppara"], 38 | "vperp" : ["perpendicularvelocity", "vperpendicular", "vpe"], 39 | "pparp" : ["perpendicularmomentum", "pperpendicular", "ppe"], 40 | "pnorm" : ["p", "momentum", "momentumnorm", "|p|"], 41 | "ptor" : ["canonicaltoroidalmomentum"], 42 | "wall" : ["lost"], 43 | "therm" : ["thermalized"] 44 | } 45 | 46 | 47 | def isalias(name, standardname): 48 | """ 49 | Check if name is an alias of the standardname. 50 | """ 51 | 52 | name = name.lower() 53 | name = name.replace(" ", "") 54 | name = name.replace("-", "") 55 | name = name.replace("_", "") 56 | 57 | suffix = "" 58 | if len(name) > 3 and name[-3:] == "prt": 59 | suffix = "prt" 60 | name = name[:-3] 61 | 62 | return name in synonyms[standardname] 63 | 64 | 65 | def getalias(name): 66 | """ 67 | Get standard name of the given quantity. 68 | """ 69 | 70 | name = name.lower() 71 | name = name.replace(" ", "") 72 | name = name.replace("-", "") 73 | name = name.replace("_", "") 74 | 75 | suffix = "" 76 | if len(name) > 3 and name[-3:] == "prt": 77 | suffix = "prt" 78 | name = name[:-3] 79 | 80 | for key in synonyms.keys(): 81 | if name in synonyms[key]: 82 | return key + suffix 83 | 84 | return name + suffix 85 | -------------------------------------------------------------------------------- /src/rfof.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file rfof.h 3 | * @brief Contains the functions to be called from the simulation loop when 4 | * using ICRH. 5 | **/ 6 | #include 7 | #include "ascot5.h" 8 | 9 | #ifndef RFOF_H 10 | #define RFOF_H 11 | 12 | /** 13 | * @brief Reusable struct for storing marker specific data during the simulation 14 | * loop. 15 | * 16 | * The data in this struct is altered during the simulation. Only pointers are 17 | * stored as the actual data is stored on the Fortran side. 18 | */ 19 | typedef struct rfof_marker { 20 | void* p[NSIMD]; /**< The marker struct in a format required by librfof */ 21 | void* history_array[NSIMD]; /**< Stores values of the resonance function for 22 | estimating the next time-step */ 23 | void* diag_array[NSIMD]; /**< C equivalents of Fortran diagnostics pointers 24 | which are required but unused at the moment */ 25 | int nrow[NSIMD]; /**< Number of rows in an resonance history matrix */ 26 | int ncol[NSIMD]; /**< Number of columns in an resonance history matrix */ 27 | 28 | } rfof_marker; 29 | 30 | /** @brief RFOF simulation input data 31 | * 32 | * Immutable input data shared between all markers. The actual data is stored 33 | * in the Fortran side and this struct only stores the pointers. 34 | */ 35 | typedef struct { 36 | void* rfof_input_params; /**< Pointer to rfof_input_param struct on 37 | the fortran side */ 38 | void* rfglobal; /**< Wave field; same for all markers */ 39 | } rfof_data; 40 | 41 | void rfof_init(rfof_data* rfof); 42 | 43 | void rfof_free(rfof_data* rfof); 44 | 45 | void rfof_set_marker_manually( 46 | rfof_marker* rfof_mrk, int* id, real* weight, real* R, real* phi, real* z, 47 | real* psi, real* charge, real* mass, real* Ekin, real* vnorm, real* mu, 48 | real* Pphi, real* vpar, real* vperp, real* gyrof, real* vdriftRho, 49 | real* acceleration, int* is_accelerated, int* is_already_allocated); 50 | 51 | void rfof_set_up(rfof_marker* rfof_mrk, rfof_data* rfof_data); 52 | 53 | void rfof_tear_down(rfof_marker* rfof_mrk); 54 | 55 | void rfof_clear_history(rfof_marker* rfof_mrk, int imrk); 56 | 57 | void rfof_resonance_check_and_kick_gc( 58 | particle_simd_gc* p, real* hin, real* hout_rfof, rfof_marker* rfof_mrk, 59 | rfof_data* rfof_data, B_field_data* Bdata); 60 | 61 | void rfof_eval_rf_wave( 62 | real* e_plus_real, real* e_minus_real, real* e_plus_imag, 63 | real* e_minus_imag, real R, real z, rfof_data* rfof); 64 | void rfof_eval_resonance_function( 65 | real* omega_res, int* nharm, rfof_marker* rfof_mrk, rfof_data* rfof); 66 | #endif 67 | -------------------------------------------------------------------------------- /src/asigma/asigma_loc.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file asigma_loc.h 3 | * @brief Header file for asigma_loc.c 4 | */ 5 | #ifndef ASIGMALOCAL_H 6 | #define ASIGMALOCAL_H 7 | 8 | #include "../ascot5.h" 9 | #include "../error.h" 10 | #include "../spline/interp.h" 11 | 12 | /** 13 | * @brief Local-files atomic reaction simulation data 14 | */ 15 | typedef struct { 16 | int N_reac; /**< Number of reactions */ 17 | int* z_1; /**< Atomic number of test particle */ 18 | int* a_1; /**< Mass number of test particle */ 19 | int* z_2; /**< Atomic number of bulk particle */ 20 | int* a_2; /**< Mass number of bulk particle */ 21 | int* reac_type; /**< Reaction type */ 22 | interp1D_data* sigma; /**< Spline of cross-sections */ 23 | interp2D_data* sigmav; /**< Spline of rate coefficients */ 24 | interp3D_data* BMSsigmav; /**< Spline of BMS rate coefficients */ 25 | } asigma_loc_data; 26 | 27 | 28 | int asigma_loc_init(asigma_loc_data* data, int nreac, 29 | int* z1, int* a1, int* z2, int* a2, int* reactype, 30 | int* ne, real* emin, real* emax, 31 | int* nn, real* nmin, real* nmax, 32 | int* nT, real* Tmin, real* Tmax, real* sigma); 33 | void asigma_loc_free(asigma_loc_data* data); 34 | void asigma_loc_offload(asigma_loc_data* data); 35 | #pragma omp declare target 36 | DECLARE_TARGET_SIMD_UNIFORM(asigma_data, reac_type, z_2, a_2,\ 37 | extrapolate) 38 | a5err asigma_loc_eval_sigma( 39 | real* sigma, int z_1, int a_1, int z_2, int a_2, real E_coll_per_amu, 40 | int reac_type, int extrapolate, asigma_loc_data* asigma_data); 41 | DECLARE_TARGET_SIMD_UNIFORM(asigma_data, reac_type, z_2, a_2,\ 42 | extrapolate) 43 | a5err asigma_loc_eval_sigmav( 44 | real* sigmav, int z_1, int a_1, real m_1, int z_2, int a_2, 45 | real E, real T_e, real T_0, real n_i, int reac_type, int extrapolate, 46 | asigma_loc_data* asigma_data); 47 | #pragma omp declare simd uniform(asigmadata, znum, anum, nspec, extrapolate) 48 | a5err asigma_loc_eval_cx( 49 | real* ratecoeff, int z_1, int a_1, real E, real mass, int nspec, 50 | const int* znum, const int* anum, real T_0, real* n_0, int extrapolate, 51 | asigma_loc_data* asigmadata); 52 | #pragma omp declare simd uniform(asigma_data, znum, anum, nion, extrapolate) 53 | a5err asigma_loc_eval_bms( 54 | real* sigmav, int z_1, int a_1, real E, real mass, int nion, 55 | const int* znum, const int* anum, real T_e, real* n_i, int extrapolate, 56 | asigma_loc_data* asigma_data); 57 | #pragma omp end declare target 58 | 59 | #endif 60 | -------------------------------------------------------------------------------- /src/Bfield/B_STS.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file B_STS.h 3 | * @brief Header file for B_STS.c 4 | */ 5 | #ifndef B_STS_H 6 | #define B_STS_H 7 | #include "../offload.h" 8 | #include "../ascot5.h" 9 | #include "../linint/linint.h" 10 | #include "../spline/interp.h" 11 | 12 | /** 13 | * @brief stellarator magnetic field parameters on the target 14 | */ 15 | typedef struct { 16 | real psi0; /**< Poloidal flux value at magnetic axis [v*s*m^-1] */ 17 | real psi1; /**< Poloidal flux value at separatrix [V*s*m^-1] */ 18 | linint1D_data axis_r;/**< 1D axis r-value interpolation data struct */ 19 | linint1D_data axis_z;/**< 1D axis z-value interpolation data struct */ 20 | interp3D_data psi; /**< 3D psi interpolation data struct */ 21 | interp3D_data B_r; /**< 3D B_r interpolation data struct */ 22 | interp3D_data B_phi ;/**< 3D B_phi interpolation data struct */ 23 | interp3D_data B_z; /**< 3D B_z interpolation data struct */ 24 | } B_STS_data; 25 | 26 | int B_STS_init(B_STS_data* data, 27 | int p_n_r, real p_r_min, real p_r_max, 28 | int p_n_phi, real p_phi_min, real p_phi_max, 29 | int p_n_z, real p_z_min, real p_z_max, 30 | int b_n_r, real b_r_min, real b_r_max, 31 | int b_n_phi, real b_phi_min, real b_phi_max, 32 | int b_n_z, real b_z_min, real b_z_max, 33 | int naxis, real axis_min, real axis_max, 34 | real* axis_r, real* axis_z, real psi0, real psi1, 35 | real* psi, real* B_r, real* B_phi, real* B_z); 36 | void B_STS_free(B_STS_data* data); 37 | void B_STS_offload(B_STS_data* data); 38 | GPU_DECLARE_TARGET_SIMD_UNIFORM(Bdata) 39 | a5err B_STS_eval_psi(real* psi, real r, real phi, real z, B_STS_data* Bdata); 40 | DECLARE_TARGET_END 41 | GPU_DECLARE_TARGET_SIMD_UNIFORM(Bdata) 42 | a5err B_STS_eval_psi_dpsi(real psi_dpsi[4], real r, real phi, real z, 43 | B_STS_data* Bdata); 44 | DECLARE_TARGET_END 45 | GPU_DECLARE_TARGET_SIMD_UNIFORM(Bdata) 46 | a5err B_STS_eval_rho_drho(real rho_drho[4], real r, real phi, real z, 47 | B_STS_data* Bdata); 48 | DECLARE_TARGET_END 49 | GPU_DECLARE_TARGET_SIMD_UNIFORM(Bdata) 50 | a5err B_STS_eval_B(real B[3], real r, real phi, real z, B_STS_data* Bdata); 51 | DECLARE_TARGET_END 52 | GPU_DECLARE_TARGET_SIMD_UNIFORM(Bdata) 53 | a5err B_STS_eval_B_dB(real B_dB[12], real r, real phi, real z, 54 | B_STS_data* Bdata); 55 | DECLARE_TARGET_END 56 | GPU_DECLARE_TARGET_SIMD_UNIFORM(Bdata) 57 | a5err B_STS_get_axis_rz(real rz[2], B_STS_data* Bdata, real phi); 58 | DECLARE_TARGET_END 59 | #endif 60 | -------------------------------------------------------------------------------- /src/Bfield/B_GS.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file B_GS.h 3 | * @brief Header file for B_GS.c 4 | */ 5 | #ifndef B_GS_H 6 | #define B_GS_H 7 | #include "../offload.h" 8 | #include "../ascot5.h" 9 | #include "../error.h" 10 | 11 | /** 12 | * @brief Analytic magnetic field parameters on the target 13 | */ 14 | typedef struct { 15 | real R0; /**< Major radius R coordinate */ 16 | real z0; /**< Midplane z coordinate */ 17 | real raxis; /**< Magnetic axis R coordinate */ 18 | real zaxis; /**< Magnetic axis z coordinate */ 19 | real B_phi0; /**< On-axis toroidal field */ 20 | real psi0; /**< Poloidal flux at axis [V*s*m^-1] */ 21 | real psi1; /**< Poloidal flux at separatrix [V*s*m^-1] */ 22 | real psi_mult; /**< Psi multiplier */ 23 | real psi_coeff[14]; /**< Coefficients for evaluating psi 24 | [c_1, c_2, ..., c_13, A] */ 25 | int Nripple; /**< Number of toroidal field coils */ 26 | real a0; /**< Minor radius [m] */ 27 | real alpha0; /**< Ripple r-dependency, delta ~ (r/a0)^alpha0 */ 28 | real delta0; /**< Ripple strength */ 29 | } B_GS_data; 30 | 31 | int B_GS_init(B_GS_data* data, real R0, real z0, real raxis, real zaxis, 32 | real B_phi0, real psi0, real psi1, real psi_mult, real c[14], 33 | int Nripple, real a0, real alpha0, real delta0); 34 | void B_GS_free(B_GS_data* data); 35 | void B_GS_offload(B_GS_data* data); 36 | GPU_DECLARE_TARGET_SIMD_UNIFORM(Bdata) 37 | a5err B_GS_eval_B(real B[3], real r, real phi, real z, B_GS_data* Bdata); 38 | DECLARE_TARGET_END 39 | GPU_DECLARE_TARGET_SIMD_UNIFORM(Bdata) 40 | a5err B_GS_eval_psi(real* psi, real r, real phi, real z, B_GS_data* Bdata); 41 | DECLARE_TARGET_END 42 | GPU_DECLARE_TARGET_SIMD_UNIFORM(Bdata) 43 | a5err B_GS_eval_psi_dpsi(real psi_dpsi[4], real r, real phi, real z, 44 | B_GS_data* Bdata); 45 | DECLARE_TARGET_END 46 | GPU_DECLARE_TARGET_SIMD_UNIFORM(Bdata) 47 | a5err B_GS_eval_rho_drho(real rho_drho[4], real r, real phi, real z, 48 | B_GS_data* Bdata); 49 | DECLARE_TARGET_END 50 | GPU_DECLARE_TARGET_SIMD_UNIFORM(Bdata) 51 | a5err B_GS_eval_B_dB(real B_dB[12], real r, real phi, real z, B_GS_data* Bdata); 52 | DECLARE_TARGET_END 53 | GPU_DECLARE_TARGET_SIMD_UNIFORM(Bdata) 54 | a5err B_GS_get_axis_rz(real rz[2], B_GS_data* Bdata); 55 | DECLARE_TARGET_END 56 | 57 | #endif 58 | -------------------------------------------------------------------------------- /.github/workflows/tests.yaml: -------------------------------------------------------------------------------- 1 | name: (Reusable) Tests 2 | on: 3 | workflow_call: 4 | inputs: 5 | run_unit_tests: 6 | description: "Unit tests are run if 'yes' and skipped otherwise." 7 | type: boolean 8 | required: false 9 | default: false 10 | 11 | run_physics_tests: 12 | description: "Physics tests are run if 'yes' and skipped otherwise." 13 | type: boolean 14 | required: false 15 | default: false 16 | 17 | jobs: 18 | 19 | Unit-Tests: 20 | if: ${{ inputs.run_unit_tests == true }} 21 | runs-on: ubuntu-latest 22 | defaults: 23 | run: 24 | shell: bash -el {0} 25 | permissions: 26 | contents: read 27 | packages: read 28 | steps: 29 | - uses: actions/checkout@v4 30 | 31 | - uses: conda-incubator/setup-miniconda@v3 32 | with: 33 | auto-update-conda: true 34 | python-version: "3.10" 35 | environment-file: environment-dev.yaml 36 | activate-environment: ascot-dev 37 | auto-activate-base: false 38 | 39 | - name: Install a5py 40 | run: python -m pip install -e . 41 | 42 | - uses: actions/download-artifact@main 43 | with: 44 | name: code 45 | 46 | - name: Unpack 47 | run: | 48 | mkdir build 49 | tar -xf code.tar -C ./build/ 50 | 51 | - name: Run 52 | working-directory: ./a5py/testascot/ 53 | run: python unittests.py 54 | 55 | Physics-Tests: 56 | if: ${{ inputs.run_physics_tests == true }} 57 | runs-on: ubuntu-latest 58 | defaults: 59 | run: 60 | shell: bash -el {0} 61 | permissions: 62 | contents: read 63 | packages: read 64 | steps: 65 | - uses: actions/checkout@v4 66 | 67 | - uses: conda-incubator/setup-miniconda@v3 68 | with: 69 | auto-update-conda: true 70 | python-version: "3.10" 71 | environment-file: environment-dev.yaml 72 | activate-environment: ascot-dev 73 | auto-activate-base: false 74 | 75 | - name: Install a5py 76 | run: python -m pip install -e . 77 | 78 | - uses: actions/download-artifact@main 79 | with: 80 | name: code 81 | 82 | - name: Unpack 83 | run: | 84 | mkdir build 85 | tar -xf code.tar -C ./build/ 86 | 87 | - name: Run 88 | working-directory: ./a5py/testascot/ 89 | run: python physicstests.py 90 | 91 | - name: Upload failed test file 92 | if: failure() 93 | uses: actions/upload-artifact@main 94 | with: 95 | name: testascot 96 | path: ./a5py/testascot/testascot.h5 97 | retention-days: 1 98 | -------------------------------------------------------------------------------- /src/diag/dist_rho5D.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file dist_rho5D.h 3 | * @brief Header file for dist_rho5D.c 4 | */ 5 | #ifndef DIST_RHO5D_H 6 | #define DIST_RHO5D_H 7 | 8 | #include 9 | #include "../ascot5.h" 10 | #include "../particle.h" 11 | 12 | /** 13 | * @brief Histogram parameters 14 | */ 15 | typedef struct { 16 | int n_rho; /**< number of rho bins */ 17 | real min_rho; /**< value of lowest rho bin */ 18 | real max_rho; /**< value of highest rho bin */ 19 | 20 | int n_theta; /**< number of poloidal angle bins */ 21 | real min_theta; /**< value of lowest pol bin */ 22 | real max_theta; /**< value of highest pol bin */ 23 | 24 | int n_phi; /**< number of phi bins */ 25 | real min_phi; /**< value of lowest phi bin */ 26 | real max_phi; /**< value of highest phi bin */ 27 | 28 | int n_ppara; /**< number of p_parallel bins */ 29 | real min_ppara; /**< value of lowest p_parallel bin */ 30 | real max_ppara; /**< value of highest p_parallel bin */ 31 | 32 | int n_pperp; /**< number of p_perpendicular bins */ 33 | real min_pperp; /**< value of lowest p_perpendicular bin */ 34 | real max_pperp; /**< value of highest p_perpendicular bin */ 35 | 36 | int n_time; /**< number of time bins */ 37 | real min_time; /**< value of lowest time bin */ 38 | real max_time; /**< value of highest time bin */ 39 | 40 | int n_q; /**< number of charge bins */ 41 | real min_q; /**< value of lowest charge bin */ 42 | real max_q; /**< value of highest charge bin */ 43 | 44 | size_t step_1; /**< step for 2nd fastest running index */ 45 | size_t step_2; /**< step for 3rd fastest running index */ 46 | size_t step_3; /**< step for 4th fastest running index */ 47 | size_t step_4; /**< step for 5th fastest running index */ 48 | size_t step_5; /**< step for 6th fastest running index */ 49 | size_t step_6; /**< step for 7th fastest running index */ 50 | 51 | real* histogram; /**< pointer to start of histogram array */ 52 | } dist_rho5D_data; 53 | 54 | int dist_rho5D_init(dist_rho5D_data* data); 55 | void dist_rho5D_free(dist_rho5D_data* data); 56 | void dist_rho5D_offload(dist_rho5D_data* data); 57 | void dist_rho5D_onload(dist_rho5D_data* data); 58 | void dist_rho5D_update_fo(dist_rho5D_data* dist, particle_simd_fo* p_f, 59 | particle_simd_fo* p_i); 60 | void dist_rho5D_update_gc(dist_rho5D_data* dist, particle_simd_gc* p_f, 61 | particle_simd_gc* p_i); 62 | 63 | #endif 64 | -------------------------------------------------------------------------------- /src/diag/dist_6D.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file dist_6D.h 3 | * @brief Header file for dist_6D.c 4 | */ 5 | #ifndef DIST_6D_H 6 | #define DIST_6D_H 7 | 8 | #include 9 | #include "../ascot5.h" 10 | #include "../particle.h" 11 | 12 | /** 13 | * @brief Histogram parameters on target 14 | */ 15 | typedef struct { 16 | int n_r; /**< number of r bins */ 17 | real min_r; /**< value of lowest r bin */ 18 | real max_r; /**< value of highest r bin */ 19 | 20 | int n_phi; /**< number of r bins */ 21 | real min_phi; /**< value of lowest r bin */ 22 | real max_phi; /**< value of highest r bin */ 23 | 24 | int n_z; /**< number of z bins */ 25 | real min_z; /**< value of lowest z bin */ 26 | real max_z; /**< value of highest z bin */ 27 | 28 | int n_pr; /**< number of p_r bins */ 29 | real min_pr; /**< value of lowest p_r bin */ 30 | real max_pr; /**< value of highest p_r bin */ 31 | 32 | int n_pphi; /**< number of p_phi bins */ 33 | real min_pphi; /**< value of lowest p_phi bin */ 34 | real max_pphi; /**< value of highest p_phi bin */ 35 | 36 | int n_pz; /**< number of p_z bins */ 37 | real min_pz; /**< value of lowest p_z bin */ 38 | real max_pz; /**< value of highest p_z bin */ 39 | 40 | int n_time; /**< number of r bins */ 41 | real min_time; /**< value of lowest r bin */ 42 | real max_time; /**< value of highest r bin */ 43 | 44 | int n_q; /**< number of r bins */ 45 | real min_q; /**< value of lowest r bin */ 46 | real max_q; /**< value of highest r bin */ 47 | 48 | size_t step_1; /**< step for 2nd fastest running index */ 49 | size_t step_2; /**< step for 3rd fastest running index */ 50 | size_t step_3; /**< step for 4th fastest running index */ 51 | size_t step_4; /**< step for 5th fastest running index */ 52 | size_t step_5; /**< step for 6th fastest running index */ 53 | size_t step_6; /**< step for 7th fastest running index */ 54 | size_t step_7; /**< step for 8th fastest running index */ 55 | 56 | real* histogram; /**< pointer to start of histogram array */ 57 | } dist_6D_data; 58 | 59 | int dist_6D_init(dist_6D_data* data); 60 | void dist_6D_free(dist_6D_data* data); 61 | void dist_6D_offload(dist_6D_data* data); 62 | void dist_6D_onload(dist_6D_data* data); 63 | void dist_6D_update_fo(dist_6D_data* dist, particle_simd_fo* p_f, 64 | particle_simd_fo* p_i); 65 | void dist_6D_update_gc(dist_6D_data* dist, particle_simd_gc* p_f, 66 | particle_simd_gc* p_i); 67 | 68 | #endif 69 | -------------------------------------------------------------------------------- /src/hdf5io/hdf5_transcoef.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @file hdf5_transcoef.c 3 | * @brief Module for writing transcport coefficients to a HDF5 file 4 | */ 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include "hdf5_helpers.h" 12 | #include "../ascot5.h" 13 | #include "../diag/diag_transcoef.h" 14 | #include "hdf5_transcoef.h" 15 | 16 | /** 17 | * @brief Write transport coefficients to a HDF5 file 18 | * 19 | * @param f hdf5 file 20 | * @param path path to group which is created here and where the data is stored 21 | * @param data transport coefficient diagnostics offload data 22 | * @param coefarr array storing the coefficient data [id, K, D] 23 | * 24 | * @return zero on success 25 | */ 26 | int hdf5_transcoef_write(hid_t f, char* path, diag_transcoef_data* data) { 27 | hid_t group = H5Gcreate2(f, path, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT); 28 | if(group < 0) { 29 | return 1; 30 | } 31 | 32 | /* Find number of (valid) data points in the coefarray */ 33 | int arrlen = data->Nmrk; 34 | int datasize = 0; 35 | integer* mask = malloc(arrlen*sizeof(real)); 36 | for(integer i=0; i < arrlen; i++) { 37 | mask[i] = data->id[i] > 0; 38 | if(mask[i]) { 39 | datasize++; 40 | } 41 | } 42 | 43 | /* Write IDs*/ 44 | integer j = 0; 45 | integer* idarr = (integer*) malloc(datasize * sizeof(integer)); 46 | for(integer i = 0; i < arrlen; i++) { 47 | if(mask[i]) { 48 | idarr[j] = data->id[i]; 49 | j++; 50 | } 51 | } 52 | hdf5_write_extendible_dataset_long(group, "ids", datasize, idarr); 53 | free(idarr); 54 | 55 | /* Write K and D */ 56 | j = 0; 57 | real* dataarr = (real*) malloc(datasize * sizeof(real)); 58 | for(integer i = 0; i < arrlen; i++) { 59 | if(mask[i]) { 60 | dataarr[j] = data->Kcoef[i]; 61 | j++; 62 | } 63 | } 64 | hdf5_write_extendible_dataset_double(group, "k", datasize, dataarr); 65 | 66 | j = 0; 67 | for(integer i = 0; i < arrlen; i++) { 68 | if(mask[i]) { 69 | dataarr[j] = data->Dcoef[i]; 70 | j++; 71 | } 72 | } 73 | hdf5_write_extendible_dataset_double(group, "d", datasize, dataarr); 74 | free(dataarr); 75 | free(mask); 76 | 77 | /* Write units */ 78 | H5LTset_attribute_string(group, "ids", "unit", "1"); 79 | if( data->recordrho ) { 80 | H5LTset_attribute_string(group, "k", "unit", "1/s"); 81 | H5LTset_attribute_string(group, "d", "unit", "1/s"); 82 | } 83 | else { 84 | H5LTset_attribute_string(group, "k", "unit", "m/s"); 85 | H5LTset_attribute_string(group, "d", "unit", "m^2/s"); 86 | } 87 | 88 | H5Gclose (group); 89 | 90 | return 0; 91 | } 92 | -------------------------------------------------------------------------------- /src/biosaw.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @file biosaw.c 3 | * @brief Functions for calculating fields from coil geometry 4 | */ 5 | #include "ascot5.h" 6 | #include "biosaw.h" 7 | #include "consts.h" 8 | #include "math.h" 9 | 10 | /** 11 | * @brief Evaluate magnetic field due to a coil at given points. 12 | * 13 | * The magnetic field is evaluated using Biot-Savart law. 14 | * 15 | * @param n number of query points 16 | * @param x x-coordinate of a query point [m] 17 | * @param y y-coordinate of a query point [m] 18 | * @param z z-coordinate of a query point [m] 19 | * @param coil_n number of points in coil geometry 20 | * @param coil_x coil geometry x-coordinate [m] 21 | * @param coil_y coil geometry y-coordinate [m] 22 | * @param coil_z coil geometry z-coordinate [m] 23 | * @param Bx evaluated magnetic field x-component [T] 24 | * @param By evaluated magnetic field y-component [T] 25 | * @param Bz evaluated magnetic field z-component [T] 26 | */ 27 | void biosaw_calc_B(int n, real* x, real* y, real* z, 28 | int coil_n, real* coil_x, real* coil_y, real* coil_z, 29 | real* Bx, real* By, real* Bz) { 30 | 31 | #pragma omp parallel for 32 | for(int ix = 0; ix < n; ix++) { 33 | Bx[ix] = 0; 34 | By[ix] = 0; 35 | Bz[ix] = 0; 36 | 37 | real p1[3], p2[3]; 38 | p2[0] = coil_x[0]; 39 | p2[1] = coil_y[0]; 40 | p2[2] = coil_z[0]; 41 | 42 | for(int i = 1; i < coil_n; i++) { 43 | math_copy(p1, p2); 44 | 45 | p2[0] = coil_x[i]; 46 | p2[1] = coil_y[i]; 47 | p2[2] = coil_z[i]; 48 | 49 | real p1p2[3]; 50 | p1p2[0] = p2[0] - p1[0]; 51 | p1p2[1] = p2[1] - p1[1]; 52 | p1p2[2] = p2[2] - p1[2]; 53 | 54 | real p1x[3]; 55 | p1x[0] = x[ix] - p1[0]; 56 | p1x[1] = y[ix] - p1[1]; 57 | p1x[2] = z[ix] - p1[2]; 58 | 59 | real p2x[3]; 60 | p2x[0] = x[ix] - p2[0]; 61 | p2x[1] = y[ix] - p2[1]; 62 | p2x[2] = z[ix] - p2[2]; 63 | 64 | real d1 = math_norm(p1x); 65 | real d2 = math_norm(p2x); 66 | real l = math_norm(p1p2); 67 | real s = math_dot(p1p2, p1x) / math_dot(p1p2, p1p2); 68 | real h = s * l; 69 | 70 | real xs[3]; 71 | xs[0] = p1[0] + s*p1p2[0] - x[ix]; 72 | xs[1] = p1[1] + s*p1p2[1] - y[ix]; 73 | xs[2] = p1[2] + s*p1p2[2] - z[ix]; 74 | 75 | real d = math_norm(xs); 76 | 77 | real abs_B = CONST_MU0 / (4*CONST_PI) * ((l-h)/d2 + h/d1)/d; 78 | 79 | real dir_B[3]; 80 | math_cross(p1x, p2x, dir_B); 81 | 82 | Bx[ix] += abs_B * dir_B[0] / math_norm(dir_B); 83 | By[ix] += abs_B * dir_B[1] / math_norm(dir_B); 84 | Bz[ix] += abs_B * dir_B[2] / math_norm(dir_B); 85 | } 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /bin/a5editoptions: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | """Edit simulation options with a text editor. 3 | """ 4 | import os 5 | import subprocess 6 | import tempfile 7 | import argparse 8 | import warnings 9 | 10 | with warnings.catch_warnings(): 11 | warnings.filterwarnings('ignore', message=".*libascot.so.*") 12 | warnings.filterwarnings('ignore', message=".*pyvista.*") 13 | warnings.filterwarnings('ignore', message=".*matplotlib.*") 14 | from a5py import Ascot, AscotIOException 15 | from a5py.ascot5io.options import Opt 16 | 17 | notes = """ 18 | notes: 19 | Options are edited using the text editor in variable EDITOR. Most likely 20 | the default is vim. Change it to emacs with \"export EDITOR=/usr/bin/emacs\". 21 | """ 22 | parser = argparse.ArgumentParser( 23 | description="Edit the active simulation options and store them as new " 24 | + "input.", epilog=notes, 25 | formatter_class=argparse.RawDescriptionHelpFormatter 26 | ) 27 | parser.add_argument("FILE", help="ASCOT5 HDF5 file whose options are edited.") 28 | parser.add_argument("-r", "--remove", action="store_true", dest="remove", 29 | default=False, 30 | help="Remove the original options from FILE if possible.") 31 | args = parser.parse_args() 32 | 33 | # Open file and read options 34 | a5 = Ascot(args.FILE) 35 | newopt = False 36 | if not "options" in a5.data: 37 | a5.data.create_input("opt") 38 | newopt = True 39 | args.remove = True 40 | options = a5.data.options.active.tostring(descriptions=True) 41 | 42 | # Write options to a temporary file for editing 43 | f, tmpfn = tempfile.mkstemp() 44 | with os.fdopen(f, "w") as f: 45 | f.write(options) 46 | 47 | # Get default text editor, use -nw for emacs 48 | ed = os.environ.get("EDITOR", "vim") 49 | if "emacs" in ed: 50 | subprocess.call([ed, "-nw", tmpfn]) 51 | else: 52 | subprocess.call([ed, tmpfn]) 53 | 54 | # Edit done, read options, remove temp file 55 | with open(tmpfn) as f: 56 | lines = f.readlines() 57 | os.remove(tmpfn) 58 | options = Opt.convert_string(lines) 59 | 60 | # Write options 61 | desc = input( 62 | "a5editoptions: give description or leave empty to undo changes:\n") 63 | 64 | if len(desc) == 0: 65 | print("a5editoptions: options closed without changes.") 66 | if newopt: 67 | # Destroy dummy options 68 | a5.data.options.active.destroy() 69 | else: 70 | name = a5.data.create_input("opt", activate=False, **options) 71 | old = a5.data.options.active.get_name() 72 | a5.data.options[name].set_desc(desc) 73 | a5.data.options[name].activate() 74 | print("a5editoptions: new options are now set as active.") 75 | 76 | if args.remove: 77 | try: 78 | a5.data.options[old].destroy() 79 | except AscotIOException: 80 | print( 81 | "a5editoptions: original options used in a simulation and " 82 | + "hence can't be removed") 83 | -------------------------------------------------------------------------------- /src/plasma.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file plasma.h 3 | * @brief Header file for plasma.c 4 | * 5 | * Contains a list declaring all plasma data, and declaration of 6 | * plasma_offload_data and plasma_data structs. 7 | */ 8 | #ifndef PLASMA_H 9 | #define PLASMA_H 10 | 11 | #include "ascot5.h" 12 | #include "error.h" 13 | #include "plasma/plasma_1D.h" 14 | #include "plasma/plasma_1Dt.h" 15 | #include "plasma/plasma_1DS.h" 16 | 17 | /** 18 | * @brief Plasma data types 19 | */ 20 | typedef enum plasma_type { 21 | plasma_type_1D, /**< Linear-interpolated 1D plasma data */ 22 | plasma_type_1Dt, /**< Linear-interpolated time-dependent 1D plasma data */ 23 | plasma_type_1DS /**< Spline-interpolated 1D plasma data */ 24 | } plasma_type; 25 | 26 | /** 27 | * @brief Plasma simulation data 28 | * 29 | * The intended usage is that only single type of data is used at a time. This 30 | * is declared using the `type` field. 31 | */ 32 | typedef struct { 33 | plasma_type type; /**< Plasma data type wrapped by this struct */ 34 | plasma_1D_data plasma_1D; /**< 1D data or NULL if not active */ 35 | plasma_1Dt_data plasma_1Dt; /**< 1D data or NULL if not active */ 36 | plasma_1DS_data plasma_1DS; /**< 1DS data or NULL if not active */ 37 | } plasma_data; 38 | 39 | void plasma_free(plasma_data* data); 40 | void plasma_offload(plasma_data* data); 41 | GPU_DECLARE_TARGET_SIMD_UNIFORM(pls_data) 42 | a5err plasma_eval_temp(real* temp, real rho, real r, real phi, real z, real t, 43 | int species, plasma_data* pls_data); 44 | DECLARE_TARGET_END 45 | GPU_DECLARE_TARGET_SIMD_UNIFORM(pls_data) 46 | a5err plasma_eval_dens(real* dens, real rho, real r, real phi, real z, real t, 47 | int species, plasma_data* pls_data); 48 | DECLARE_TARGET_END 49 | GPU_DECLARE_TARGET_SIMD_UNIFORM(pls_data) 50 | a5err plasma_eval_densandtemp(real* dens, real* temp, real rho, 51 | real r, real phi, real z, real t, 52 | plasma_data* pls_data); 53 | DECLARE_TARGET_END 54 | GPU_DECLARE_TARGET_SIMD_UNIFORM(pls_data) 55 | a5err plasma_eval_flow(real* vflow, real rho, real r, real phi, real z, real t, 56 | plasma_data* pls_data); 57 | DECLARE_TARGET_END 58 | GPU_DECLARE_TARGET_SIMD_UNIFORM(pls_data) 59 | int plasma_get_n_species(plasma_data* pls_data); 60 | DECLARE_TARGET_END 61 | GPU_DECLARE_TARGET_SIMD_UNIFORM(pls_data) 62 | const real* plasma_get_species_mass(plasma_data* pls_data); 63 | DECLARE_TARGET_END 64 | GPU_DECLARE_TARGET_SIMD_UNIFORM(pls_data) 65 | const real* plasma_get_species_charge(plasma_data* pls_data); 66 | DECLARE_TARGET_END 67 | GPU_DECLARE_TARGET_SIMD_UNIFORM(pls_data) 68 | const int* plasma_get_species_znum(plasma_data* pls_data); 69 | DECLARE_TARGET_END 70 | GPU_DECLARE_TARGET_SIMD_UNIFORM(pls_data) 71 | const int* plasma_get_species_anum(plasma_data* pls_data); 72 | DECLARE_TARGET_END 73 | 74 | #endif 75 | -------------------------------------------------------------------------------- /src/diag/dist_rho6D.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file dist_rho6D.h 3 | * @brief Header file for dist_rho6D.c 4 | */ 5 | #ifndef DIST_RHO6D_H 6 | #define DIST_RHO6D_H 7 | 8 | #include 9 | #include "../ascot5.h" 10 | #include "../particle.h" 11 | 12 | /** 13 | * @brief Histogram parameters on target 14 | */ 15 | typedef struct { 16 | int n_rho; /**< number of rho bins */ 17 | real min_rho; /**< value of lowest rho bin */ 18 | real max_rho; /**< value of highest rho bin */ 19 | 20 | int n_theta; /**< number of poloidal angle bins */ 21 | real min_theta; /**< value of lowest theta bin */ 22 | real max_theta; /**< value of highest theta bin */ 23 | 24 | int n_phi; /**< number of phi bins */ 25 | real min_phi; /**< value of lowest phi bin */ 26 | real max_phi; /**< value of highest phi bin */ 27 | 28 | int n_pr; /**< number of p_r bins */ 29 | real min_pr; /**< value of lowest p_r bin */ 30 | real max_pr; /**< value of highest p_r bin */ 31 | 32 | int n_pphi; /**< number of p_phi bins */ 33 | real min_pphi; /**< value of lowest p_phi bin */ 34 | real max_pphi; /**< value of highest p_phi bin */ 35 | 36 | int n_pz; /**< number of p_z bins */ 37 | real min_pz; /**< value of lowest p_z bin */ 38 | real max_pz; /**< value of highest p_z bin */ 39 | 40 | int n_time; /**< number of time bins */ 41 | real min_time; /**< value of lowest time bin */ 42 | real max_time; /**< value of highest time bin */ 43 | 44 | int n_q; /**< number of charge bins */ 45 | real min_q; /**< value of lowest charge bin */ 46 | real max_q; /**< value of highest charge bin */ 47 | 48 | size_t step_1; /**< step for 2nd fastest running index */ 49 | size_t step_2; /**< step for 3rd fastest running index */ 50 | size_t step_3; /**< step for 4th fastest running index */ 51 | size_t step_4; /**< step for 5th fastest running index */ 52 | size_t step_5; /**< step for 6th fastest running index */ 53 | size_t step_6; /**< step for 7th fastest running index */ 54 | size_t step_7; /**< step for 8th fastest running index */ 55 | 56 | real* histogram; /**< pointer to start of histogram array */ 57 | } dist_rho6D_data; 58 | 59 | int dist_rho6D_init(dist_rho6D_data* dist_data); 60 | void dist_rho6D_free(dist_rho6D_data* dist_data); 61 | void dist_rho6D_offload(dist_rho6D_data* dist_data); 62 | void dist_rho6D_onload(dist_rho6D_data* dist_data); 63 | void dist_rho6D_update_fo(dist_rho6D_data* dist, particle_simd_fo* p_f, 64 | particle_simd_fo* p_i); 65 | void dist_rho6D_update_gc(dist_rho6D_data* dist, particle_simd_gc* p_f, 66 | particle_simd_gc* p_i); 67 | 68 | #endif 69 | -------------------------------------------------------------------------------- /README.rst: -------------------------------------------------------------------------------- 1 | ASCOT5 2 | ====== 3 | 4 | `Documentation `_ 5 | 6 | High-performance orbit-following code for fusion plasma physics and engineering. 7 | 8 | New (and old) users are welcome to join our weekly meetings or Slack channel to discuss their research and plans with regards to ASCOT5. 9 | 10 | This repository is maintained by ASCOT team in Aalto University and VTT Technical Research Centre of Finland. 11 | 12 | Installation 13 | ============ 14 | 15 | Most convenient way to install ASCOT5 is to use the Conda environment that comes with the source code. 16 | Compile the main program and the library, and install the associated Python package with ``pip``. 17 | Note that this installation is suitable mostly for pre- and postprocessing since it does not use MPI. 18 | See the `documentation `_ for more detailed instructions. 19 | 20 | .. code-block:: bash 21 | 22 | git clone https://github.com/ascot4fusion/ascot5.git 23 | cd ascot5 24 | conda env create -f environment.yaml 25 | conda activate ascot-env 26 | make libascot -j 27 | make ascot5_main -j 28 | pip install -e . 29 | 30 | How to Contribute 31 | ================= 32 | 33 | .. admonition:: As an User: 34 | 35 | - Verify your results and report problems or physics violations in issues. 36 | - Add `compiling instructions `_ for popular platforms and consider updating `the table with example simulation times `_ for novel entries. 37 | - When `benchmarking `_ ASCOT5 against other codes or `validating `_ it against experiments, please contact the maintainers to archive the simulation for use as a regression test. 38 | 39 | .. admonition:: As a Developer: 40 | 41 | - Don't let the code daunt you! 42 | We're here to assist with any feature contributions, whether it's a small post-processing tool, a new plot, or an enhancement of an existing feature. 43 | - Start by creating an issue, then (fork and) make a branch ``feature/-issue`` from develop. 44 | - When ready to merge, create a pull request running automated tests on your branch. 45 | - Upon test completion and acceptance, your feature will be merged into develop for inclusion in the next release. 46 | 47 | Licence 48 | ======= 49 | 50 | The ASCOT5 and associated programs are distributed under the terms of the GNU Lesser General Public License (LGPL). 51 | Please see the files COPYING and COPYING.LESSER for more information. 52 | 53 | This has been done after the code was released to the original authors by the Dean of School of Science of Aalto University and discussion between the key contributors, including Jari Varje, Konsta Särkimäki, Antti Snicker and Simppa Äkäslompolo. 54 | -------------------------------------------------------------------------------- /src/unit_tests/test_bsearch.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "../math.h" 5 | 6 | int main() { 7 | int n = 30; 8 | real vec_min = (real) -n; 9 | real vec_max = (real) n; 10 | real vec[n]; 11 | math_linspace(vec, vec_min, vec_max, n); 12 | 13 | int success; 14 | 15 | int n_samples = n * 1000; 16 | printf("Checking %d random values...", n_samples); 17 | success = 1; 18 | for(int i = 0; i < n_samples; i++) { 19 | real sval = vec_min + (vec_max - vec_min)*(real)rand()/RAND_MAX; 20 | real* res = math_rsearch(sval, vec, n); 21 | if(!res) { 22 | printf("\nERROR: Number %.4f not in vector.\n", sval); 23 | success = 0; 24 | break; 25 | } 26 | else if(*res <= sval && *(res + 1) > sval) { 27 | /* Do nothing */ 28 | } 29 | else { 30 | printf("\nERROR: Number %.4f found between " 31 | "%.4f and %.4f = vec[%d] and vec[%d].\n", 32 | sval, *res, *(res + 1), 33 | (int)(res - vec), 34 | (int)(res + 1 - vec)); 35 | success = 0; 36 | break; 37 | } 38 | } 39 | if (success) printf("\t\t\t\tOK!\n"); 40 | 41 | printf("Checking %d first grid points...", n - 1); 42 | success = 1; 43 | for(int i = 0; i < n - 1; i++) { 44 | real* res = math_rsearch(vec[i], vec, n); 45 | if(!res) { 46 | printf("\nERROR: Grid point %.4f not found.\n", vec[i]); 47 | success = 0; 48 | break; 49 | } 50 | else if(res == vec + i) { 51 | /* Do nothing */ 52 | } 53 | else { 54 | printf("\nERROR: Grid point %.4f at wrong place %.4f = vec[%d]\n", 55 | vec[i], *res, i); 56 | success = 0; 57 | break; 58 | } 59 | } 60 | if(success) printf("\t\t\tOK!\n"); 61 | 62 | printf("Checking last grid point..."); 63 | real* res = math_rsearch(vec[n-1], vec, n); 64 | if(res) { 65 | printf("\nERROR: Found last grid point %.4f at %.4f = vec[%d].\n", 66 | vec[n-1], *res, (int)(res - vec)); 67 | success = 0; 68 | } 69 | else { 70 | printf("\t\t\t\tOK!\n"); 71 | } 72 | 73 | printf("Checking two points just outside grid..."); 74 | real tol = 0.0001; 75 | real sval1 = vec[0] - tol * (vec[1] - vec[0]); 76 | real sval2 = vec[n-1] + tol * (vec[n-1] - vec[n-2]); 77 | if(math_rsearch(sval1, vec, n)) { 78 | printf("\nERROR: Number %.4f found (less than %.4f = vec[0]).\n", 79 | sval1, vec[0]); 80 | success = 0; 81 | } 82 | if(math_rsearch(sval2, vec, n)) { 83 | printf("\nERROR: Number %.4f found (more than %.4f = vec[n-1]).\n", 84 | sval2, vec[n-1]); 85 | success = 0; 86 | } 87 | else { 88 | printf("\t\tOK!\n"); 89 | } 90 | 91 | return 0; 92 | } 93 | --------------------------------------------------------------------------------