Getting started#
This notebook introduces some of the core functionality of TetraX. To download and run it on your machine, just use the saving function of your browser (CTRL+S on Windows/Linux or CMD+S on OSX).
Installation#
Install this package using
pip install git+https://gitlab.hzdr.de/micromagnetic-modeling/tetrax.git
To allow for 3D visualization in Jupyter notebooks, you additionally need to activate the k3d extension in your shell using
jupyter nbextension install --py --sys-prefix k3d
jupyter nbextension enable --py --sys-prefix k3d
NOTE: In newer python environments and jupyter packages the activation of the k3d extension is not needed anymore.
Now you are ready to use TetraX in your python scripts or Jupyter notebook.
[1]:
from tetrax import geometries, Sample
For details, see User Guide: Installation.
Create a sample#
Using template geometries#
In order to conduct any sort of numerical experiments, we first need to create a Sample. This object consists of a geometry, a set of material parameters and other parameters, such as the externally applied magnetic field or a microwave antenna. To create a sample, we need to supply a geometry in the form of a mesh. TetraX provides a number of template geometries in the tetrax.geometries module. To view all available geometries, simply access
[2]:
geometries.available
[2]:
['from_file',
'confined.disk',
'confined.prism',
'confined.tube',
'confined_axial.disk',
'confined_axial.ring',
'waveguide.polygonal',
'waveguide.rectangular',
'waveguide.round_wire',
'waveguide.round_wire_refined',
'waveguide.tube',
'waveguide.tube_segment',
'waveguide_axial.multitube',
'waveguide_axial.round_wire',
'waveguide_axial.tube',
'layer.bilayer',
'layer.monolayer',
'layer.multilayer']
or, if you want you want more detailed informations on which parameters to supply,
[3]:
geometries.show_available()
from_file
(filename: 'Union[str, pathlib.Path]', file_format: 'Optional[str]' = None) -> 'meshio.Mesh'
confined.disk
(radius: 'float', thickness: 'float', cell_size_lateral: 'float' = 5, nl: 'int' = 0, x0: 'float' = 0, y0: 'float' = 0) -> 'MeshioMesh'
confined.prism
(length: 'float', width: 'float', thickness: 'float', cell_size_length: 'float' = 5, cell_size_width: 'float' = 5, cell_size_thickness: 'float' = 5) -> 'MeshioMesh'
confined.tube
(inner_radius: 'float', outer_radius: 'float', length: 'float', cell_size_lateral: 'float' = 5, nl: 'int' = 2, x0: 'float' = 0, y0: 'float' = 0) -> 'MeshioMesh'
confined_axial.disk
(radius: 'float', thickness: 'float', cell_size_radius: 'float' = 5, cell_size_thickness: 'float' = 5, x0: 'float' = 0) -> 'MeshioMesh'
confined_axial.ring
(inner_radius: 'float', outer_radius: 'float', thickness: 'float', cell_size_radius: 'float' = 5, cell_size_thickness: 'float' = 5, z0: 'float' = 0) -> 'MeshioMesh'
waveguide.polygonal
(points: 'List[List]', cell_size: 'float' = 5) -> 'MeshioMesh'
waveguide.rectangular
(width: 'float', thickness: 'float', cell_size_width: 'float' = 5, cell_size_thickness: 'float' = 5, x0: 'float' = 0, y0: 'float' = 0) -> 'MeshioMesh'
waveguide.round_wire
(radius: 'float', cell_size: 'float' = 5, x0: 'float' = 0, y0: 'float' = 0) -> 'MeshioMesh'
waveguide.round_wire_refined
(radius: 'float', refinement_function: 'Callable[[float, float, float], float]', x0: 'float' = 0, y0: 'float' = 0) -> 'MeshioMesh'
waveguide.tube
(inner_radius: 'float', outer_radius: 'float', cell_size: 'float' = 5, x0: 'float' = 0, y0: 'float' = 0) -> 'MeshioMesh'
waveguide.tube_segment
(arc_length: 'float', thickness: 'float', angle: 'float', cell_size: 'float' = 5, shifted_to_origin: 'bool' = True) -> 'MeshioMesh'
waveguide_axial.multitube
(radii: 'List[float]', cell_sizes: 'Union[float, List[float]]') -> 'MeshioMesh'
waveguide_axial.round_wire
(radius: 'float', cell_size: 'float' = 2) -> 'MeshioMesh'
waveguide_axial.tube
(inner_radius: 'float', outer_radius: 'float', cell_size: 'float') -> 'MeshioMesh'
layer.bilayer
(thickness1: 'float', thickness2: 'float', spacing: 'float', cell_sizes: 'Union[float, List[float]]', y0: 'float' = 0) -> 'MeshioMesh'
layer.monolayer
(thickness: 'float', cell_size: 'float' = 2, y0: 'float' = 0) -> 'MeshioMesh'
layer.multilayer
(thicknesses: 'List[float]', spacings: 'List[float]', cell_sizes: 'Union[float, List[float]]', y0: 'float' = 0) -> 'MeshioMesh'
Notice, that the geometries are collected into different subcategorizes such as confined, waveguide or layer. These geometry types describe magnetic objects that are of arbitrary shape (confined) or exhibit one or more symmtries (such as translational, rotational, or a combination, thereof). This exploitation of spatial symmetries is a key ingedrient in the efficiency of TetraX. More information on these different geometries types is found in the User Guide:
Sample.
To start of, let us create a magnetic nanotube whose geometry, magnetic parameters and equilibrium state a assumed to be translationally invariant along the tube’s axis. Such a system can be efficiently modeled using the waveguide geometry.
[4]:
mesh = geometries.waveguide.tube(inner_radius=20, outer_radius=30, cell_size=3)
tube = Sample(mesh, name="nanotube_r20_R30")
Let us inspect the geometry of the sample we just created using
[5]:
tube.show()
/Users/attilak/gitlab/tetrax/features/tetrax_venv_3.13/lib/python3.13/site-packages/traittypes/traittypes.py:97: UserWarning: Given trait value dtype "float32" does not match required type "float32". A coerced copy has been created.
warnings.warn(
[5]:
We can see that tube.show() displays the two-dimensional mesh of the waveguide together with an extruded shaded volume that hints at the geometry of the full three-dimensional tube (this can be hidden with show_extrusion=False).
In order to see some detailed information about the mesh, we can use
[6]:
tube.mesh
[6]:
SampleMesh (Sample.mesh) of 'nanotube_r20_R30'
| attribute | value | description |
|---|---|---|
| geometry_type | waveguide | geometry type |
| nx | 273 | total nodes |
| nb | 105 | boundary nodes |
| scale | 1e-09 |
which shows us that, per default, the mesh is scaled with scale=1e-09. Thus all length units (here, the radii of the tube), are in nanometers.
Using custom meshes#
TetraX also provides the possibility to use custom meshes. For example, using pygmsh in a notebook
import pygmsh
with pygmsh.occ.Geometry() as geom:
geom.characteristic_length_min = lc
geom.characteristic_length_max = lc
disk1 = geom.add_disk([0, 0.0], R)
disk2 = geom.add_disk([0, 0.0], r)
geom.boolean_difference(disk1,disk2)
mesh = geom.generate_mesh()
tube = Sample(mesh, geometry_type="waveguide")
or, from a file,
mesh = geometries.from_file("mesh.vtk")
tube = Sample(mesh, geometry_type="waveguide")
When using custom meshes, the geometry_type of the sample needs to be specified manually. When using template geometries, this parameter is inferred automatically.
Note, that meshes for waveguide cross sections need to be embedded in the \(xy\) plane, whereas meshes for layer samples need to be embedded on the \(y\) axis, confined axial waveguides on the \(x\)/\(\rho\) axis, and so on. More information is found in the User Guide: Sample.
If you model your geometry using COMSOL it is not possible to directly export the mesh into a format readable by TetraX, as COMSOL somehow only saves disconnected nodes and no elements. However, you can simply define an arbitrary vector field on your mesh in COMSOL, export it in vtk/vtu format and read-in this file as the mesh in TetraX.
Material parameters#
To inspect and manipulate the material parameters of the sample, we use the
[7]:
tube.material
[7]:
SampleMaterial (Sample.material) of 'nanotube_r20_R30'
| name | average | description |
|---|---|---|
| Msat | 795000.0 A/m | saturation magnetization |
| Aex | 1.2999999999999999e-11 J/m | exchange stiffness |
| gamma | 176085964399.99997 radHz/T | gyromagnetic ratio |
| alpha | 0.008 (is_global) | Gilbert damping |
| Ku1 | 0.0 J/m^3 | first-order unaxial-anistropy constant |
| e_u | [0. 0. 1.] | uniaxial anistropy direction |
| Dbulk | 0 (is_global) | bulk DMI constant |
| Didmi | 0 (is_global) | interfacial DMI constant |
| e_d | [0. 1. 0.] | interfacial DMI direction |
| Kc1 | 0.0 J/m^3 | first-order cubic-anistropy constant |
| e_c1 | [1. 0. 0.] | first cubic anistropy direction |
| e_c2 | [0. 1. 0.] | second cubic anistropy direction |
| e_c3 | [0. 0. 1.] | third cubic anistropy direction |
Each new ferromagnetic sample is initialized with micromagnetic parameters of the softmagnetic material Ni80Fe20 (permalloy). We can change each of these material parameters easily
[8]:
tube.material["Msat"] = 810e3
tube.material["Aex"] = 810e3
Notice that almost all material parameters can be spatially dependent (except the ones flagged with “is_global”). In fact, if we just run
[9]:
tube.material["Msat"]
[9]:
MaterialParameter
| attribute | value |
|---|---|
| name | Msat |
| description | saturation magnetization |
| sample | nanotube_r20_R30 |
| param_type | scalar |
| is_global | False |
| read_only | False |
| constraint | is_strictly_positive |
| unit | A/m |
| average | [MeshScalar(810000.)] |
value: MeshScalar([810000., 810000., 810000., 810000., 810000., 810000., 810000., 810000., 810000., 810000., 810000., 810000., 810000., 810000., 810000., 810000., 810000., 810000., 810000., 810000., 810000., 810000., 810000., 810000., 810000., 810000., 810000., 810000., 810000., 810000., 810000., 810000., 810000., 810000., 810000., 810000., 810000., 810000., 810000., 810000., 810000., 810000., 810000., 810000., 810000., 810000., 810000., 810000., 810000., 810000., 810000., 810000., 810000., 810000., 810000., 810000., 810000., 810000., 810000., 810000., 810000., 810000., 810000., 810000., 810000., 810000., 810000., 810000., 810000., 810000., 810000., 810000., 810000., 810000., 810000., 810000., 810000., 810000., 810000., 810000., 810000., 810000., 810000., 810000., 810000., 810000., 810000., 810000., 810000., 810000., 810000., 810000., 810000., 810000., 810000., 810000., 810000., 810000., 810000., 810000., 810000., 810000., 810000., 810000., 810000., 810000., 810000., 810000., 810000., 810000., 810000., 810000., 810000., 810000., 810000., 810000., 810000., 810000., 810000., 810000., 810000., 810000., 810000., 810000., 810000., 810000., 810000., 810000., 810000., 810000., 810000., 810000., 810000., 810000., 810000., 810000., 810000., 810000., 810000., 810000., 810000., 810000., 810000., 810000., 810000., 810000., 810000., 810000., 810000., 810000., 810000., 810000., 810000., 810000., 810000., 810000., 810000., 810000., 810000., 810000., 810000., 810000., 810000., 810000., 810000., 810000., 810000., 810000., 810000., 810000., 810000., 810000., 810000., 810000., 810000., 810000., 810000., 810000., 810000., 810000., 810000., 810000., 810000., 810000., 810000., 810000., 810000., 810000., 810000., 810000., 810000., 810000., 810000., 810000., 810000., 810000., 810000., 810000., 810000., 810000., 810000., 810000., 810000., 810000., 810000., 810000., 810000., 810000., 810000., 810000., 810000., 810000., 810000., 810000., 810000., 810000., 810000., 810000., 810000., 810000., 810000., 810000., 810000., 810000., 810000., 810000., 810000., 810000., 810000., 810000., 810000., 810000., 810000., 810000., 810000., 810000., 810000., 810000., 810000., 810000., 810000., 810000., 810000., 810000., 810000., 810000., 810000., 810000., 810000., 810000., 810000., 810000., 810000., 810000., 810000., 810000., 810000., 810000., 810000., 810000., 810000., 810000., 810000., 810000., 810000., 810000., 810000., 810000., 810000., 810000., 810000., 810000., 810000.])
we see more information about the saturation magnetization, for example that is has a value defined at each node of the mesh. We can use this to make it inhomogeneous.
[10]:
tube.material["Msat"] = tube.xyz.x ** 2
tube.material["Msat"].value
[10]:
MeshScalar([4.00000000e+02, 9.00000000e+02, 3.91114561e+02,
3.65247755e+02, 3.24697960e+02, 2.73068205e+02,
2.14946019e+02, 1.55495813e+02, 1.00000000e+02,
5.33896256e+01, 1.98062264e+01, 2.23383475e+00,
2.23383475e+00, 1.98062264e+01, 5.33896256e+01,
1.00000000e+02, 1.55495813e+02, 2.14946019e+02,
2.73068205e+02, 3.24697960e+02, 3.65247755e+02,
3.91114561e+02, 4.00000000e+02, 3.91114561e+02,
3.65247755e+02, 3.24697960e+02, 2.73068205e+02,
2.14946019e+02, 1.55495813e+02, 1.00000000e+02,
5.33896256e+01, 1.98062264e+01, 2.23383475e+00,
2.23383475e+00, 1.98062264e+01, 5.33896256e+01,
1.00000000e+02, 1.55495813e+02, 2.14946019e+02,
2.73068205e+02, 3.24697960e+02, 3.65247755e+02,
3.91114561e+02, 8.91077620e+02, 8.64664295e+02,
8.21807448e+02, 7.64206568e+02, 6.94145819e+02,
6.14403461e+02, 5.28141680e+02, 4.38781189e+02,
3.49865580e+02, 2.64920804e+02, 1.87315347e+02,
1.20126658e+02, 6.60191033e+01, 2.71383206e+01,
5.02612820e+00, 5.59385451e-01, 1.39152212e+01,
4.45640094e+01, 9.12903717e+01, 1.52241373e+02,
2.25000000e+02, 3.06681007e+02, 3.94045333e+02,
4.83628542e+02, 5.71878211e+02, 6.55294796e+02,
7.30570411e+02, 7.94719999e+02, 8.45199708e+02,
8.80007763e+02, 8.97763849e+02, 8.97763849e+02,
8.80007763e+02, 8.45199708e+02, 7.94719999e+02,
7.30570411e+02, 6.55294796e+02, 5.71878211e+02,
4.83628542e+02, 3.94045333e+02, 3.06681007e+02,
2.25000000e+02, 1.52241373e+02, 9.12903717e+01,
4.45640094e+01, 1.39152212e+01, 5.59385451e-01,
5.02612820e+00, 2.71383206e+01, 6.60191033e+01,
1.20126658e+02, 1.87315347e+02, 2.64920804e+02,
3.49865580e+02, 4.38781189e+02, 5.28141680e+02,
6.14403461e+02, 6.94145819e+02, 7.64206568e+02,
8.21807448e+02, 8.64664295e+02, 8.91077620e+02,
1.46691671e+01, 5.04662398e+02, 3.09782018e+02,
3.75390147e+02, 9.24795176e+00, 4.96855032e+02,
2.33580246e+02, 4.46504638e+02, 9.55822307e+01,
3.81570052e+02, 2.31674877e+02, 2.32804827e+02,
1.03950504e+02, 9.24795176e+00, 4.78838537e+02,
9.13072044e+01, 4.79963239e+02, 1.40145518e+01,
3.81535560e+02, 9.13072044e+01, 2.97031401e+02,
7.50011625e+02, 5.68689999e+02, 7.11019201e+02,
4.66980239e+02, 4.91525104e+02, 2.49416190e+02,
6.61884137e+02, 7.34935201e+01, 3.49307507e-01,
7.32402290e+02, 5.54028081e+01, 4.36622278e+02,
6.33488127e+02, 2.19521694e+02, 6.45802042e+02,
3.49307507e-01, 5.16641459e+01, 2.46119947e+02,
7.34935201e+01, 7.41748058e+02, 4.44934394e+02,
1.55085797e+02, 5.00820850e+02, 5.08662655e+02,
6.20514335e+02, 1.61116806e+02, 1.38930188e-01,
3.06866582e+02, 2.99903853e+02, 3.21756031e+02,
3.93669796e+01, 2.43291336e+02, 1.92006315e+02,
1.65512970e+02, 3.71969210e+02, 4.39958770e+02,
1.28398835e-01, 4.38095894e+02, 3.00234839e+02,
4.94906209e+02, 4.84294591e+01, 5.01145808e+02,
4.89625213e+01, 3.93669796e+01, 4.41366770e+02,
1.52508914e+02, 3.87300537e+00, 3.04619685e+01,
1.56659051e+02, 8.59389910e+01, 6.34683138e+02,
2.48608474e+02, 5.11505512e+02, 3.85236960e+00,
3.04619685e+01, 5.14415457e+02, 4.28681370e+02,
1.56520355e+02, 3.38219409e+02, 4.25824414e+02,
5.75663192e+02, 5.78335871e+02, 9.54113803e+01,
5.39848207e+02, 6.22245856e+02, 5.04609258e+02,
4.56655464e+02, 6.32489873e+02, 2.69440666e+02,
7.28601485e+00, 1.00025680e+02, 4.56655464e+02,
2.34507878e+01, 3.24128673e+02, 1.42902377e+02,
7.28601485e+00, 2.34507878e+01, 1.00025680e+02,
2.56741463e+02, 5.68716062e+02, 5.61795117e+02,
3.70500317e+02, 2.23728675e+02, 1.56514020e+02,
7.04988751e+02, 7.51510873e+02, 3.35205506e+02,
7.08562434e+02, 3.40264085e+02, 4.49375258e+00,
7.82914714e+02, 3.05547050e+02, 4.17510926e+02,
3.81498646e+01, 1.04580509e+02, 6.33279010e+02,
1.93861023e+02, 3.81498646e+01, 4.49057346e+00,
1.93466740e+02, 6.30558975e+02, 5.30454725e+02,
7.63653423e+02, 4.14251237e+02, 9.46367066e+01,
6.94105443e+02, 5.27986823e+02, 7.01152259e+02,
2.73627129e+02, 6.03832735e+02, 6.31002767e+02,
1.95425304e+01, 1.39843917e+01, 7.52729145e+02,
5.63279776e+02, 3.60926796e+02, 1.34772280e+02,
1.50495014e+02, 1.39843917e+01, 1.99119569e+01,
1.34738908e+02, 3.40299120e+02, 5.59786125e+02,
6.16737157e+02, 6.07508680e+02, 7.53220467e+02,
6.62008008e+02, 3.89936856e+02, 4.99372561e+01,
2.25606592e+02, 6.11438303e+02, 4.69536669e+02,
5.95362880e+01, 1.80831370e-01, 4.76552112e+01,
2.05094227e+02, 5.95362880e+01, 1.80831370e-01,
1.85461015e+02, 3.86269997e+02, 5.33554180e+02,
3.70045238e+02, 5.97779620e+02, 5.18976910e+02,
1.35432484e+02, 2.02499270e+02, 5.38844364e+02])
We can also assign all material paramaters at once by asigning a python dictionary to the Sample.material. The tetrax.materials submodule provides a couple of template materials.
[11]:
from tetrax import materials
tube.material = materials.permalloy
[12]:
# Use materials.available to list all pre-defined materials
materials.available
[12]:
['permalloy', 'yig', 'iron', 'cobalt_fcc', 'cobalt_hcp', 'nickel_fcc']
Sample summary#
To see a full summary of the sample, together with the mesh and material information, simply run
[13]:
tube
[13]:
Sample
| attribute | value |
|---|---|
| name | nanotube_r20_R30 |
| magnetic_order | FM |
| interactions | ['exchange', 'dipole', 'zeeman', 'uniaxial_anisotropy', 'cubic_anisotropy', 'dmi_bulk', 'dmi_interfacial'] |
| external_field (avrg.) | [0. 0. 0.] T |
| antenna | None |
| mag (avrg.) | [0. 0. 1.] |
SampleMesh (Sample.mesh) of 'nanotube_r20_R30'
| attribute | value | description |
|---|---|---|
| geometry_type | waveguide | geometry type |
| nx | 273 | total nodes |
| nb | 105 | boundary nodes |
| scale | 1e-09 |
SampleMaterial (Sample.material) of 'nanotube_r20_R30'
| name | average | description |
|---|---|---|
| Msat | 810000.0000000001 A/m | saturation magnetization |
| Aex | 1.2999999999999999e-11 J/m | exchange stiffness |
| gamma | 185982240000.0 radHz/T | gyromagnetic ratio |
| alpha | 0.008 (is_global) | Gilbert damping |
| Ku1 | 0.0 J/m^3 | first-order unaxial-anistropy constant |
| e_u | [0. 0. 1.] | uniaxial anistropy direction |
| Dbulk | 0 (is_global) | bulk DMI constant |
| Didmi | 0 (is_global) | interfacial DMI constant |
| e_d | [0. 1. 0.] | interfacial DMI direction |
| Kc1 | 0.0 J/m^3 | first-order cubic-anistropy constant |
| e_c1 | [1. 0. 0.] | first cubic anistropy direction |
| e_c2 | [0. 1. 0.] | second cubic anistropy direction |
| e_c3 | [0. 0. 1.] | third cubic anistropy direction |
Hint: You can use Sample.get_field('interaction_name'). Same with get_energy and get_interaction.
We see that, the sample can also have an externally applied field or a microwave antenna and possesses different magnetic interactions. More information about these is found in the User Guide.
Running experiments#
Before running an experiment we migth want to set an external field or an atenna type for spin-wave excitation. Here we will set a helical external field and compute the equiliubrium magnetization of the tube in this field.
We need the vectorfields and the experiments modules:
[14]:
from tetrax import experiments, vectorfields
[15]:
# An 80mT circular field is applied
tube.external_field = 80e-3*vectorfields.helical(tube.xyz, 90, 1)
# Show both the magnetization and the external static field:
tube.show([tube.mag, tube.external_field])
[15]:

Relaxation based on energy minimization#
We use the relax() method of the experiments on the tube sample, to perform the energy minimization:
[16]:
relaxation_results = experiments.relax(tube)
Minimizing energy in using 'L-BFGS-B' (tolerance 1e-12) ...
energy length density: -6.852892375740077e-11 J/m, <mag.x> = 0.00, <mag.y> = 0.00, <mag.z> = -0.0000
Success!
[17]:
# The ``relax()`` method will return a result objext
relaxation_results
[17]:
RelaxationResult of 'nanotube_r20_R30'
| attribute | value |
|---|---|
| path | nanotube_r20_R30/relax |
| created | 2025-01-27T15:30:55.891193 |
| geometry_type | waveguide |
| magnetic_order | waveguide |
| interactions | exchange, dipole, zeeman, (uniaxial_anisotropy, cubic_anisotropy, dmi_bulk, dmi_interfacial) |
| external_field (avrg.) | [1.12201682e-06 5.34164534e-06 4.89858720e-18] T |
| initial_state (avrg.) | [0. 0. 1.] |
| final_state (avrg.) | [ 7.72935506e-06 9.00815200e-06 -4.23227220e-06] |
| was_success | True |
| message | CONVERGENCE: REL_REDUCTION_OF_F_<=_FACTR*EPSMCH |
| iterations | 271 |
Hint: Call plot() method to show a energy_mag_log of the energies and componentes.
Hint: Access the RelaxationResult.energy_mag_log or .config directly.
Hint: Call show() to show initial and final states.
[18]:
# One can plot the results:
relaxation_results.plot()
[19]:
# Show the obtained equilibrium magnetization, aligned with the external field
tube.show()
/Users/attilak/gitlab/tetrax/features/tetrax_venv_3.13/lib/python3.13/site-packages/traittypes/traittypes.py:97: UserWarning:
Given trait value dtype "float32" does not match required type "float32". A coerced copy has been created.
[19]:
Computation of the spin-wave spectrum#
using the
eigenmodesmethod from the experiments on thetubesamplefor the previsouly obtained equilibrium magnetization
[20]:
spectrum = experiments.eigenmodes(tube)
100%|███████████████████████████████████████████| 41/41 [00:01<00:00, 21.22it/s]
[21]:
# Plot the spectrum using the build it plotting method
# of the resulting spectrum object:
spectrum.plot(n=[0,4], kscale='u', fscale='G')
# ``n=[0,4]`` - first 5 modes
# ``kscale='u'`` - wave vector units on the axis in rad/µm
# ``fscale='G'`` - frequency axis in GHz.
For further experiments, such as dynamic relaxation, computation of the eigenmodes with perturbation or possible post processings, as absorption, please check the Examples.
Run as a script#
Of course, you can also run TetraX experiments in Python scripts (e.g. my_simulation.py), for example, to deploy them on a cluster. For this, it is important to add if __name__ == ‘__main__’ to the beginning of your script, otherwise the multiprocessing will overflow your memory and your script will crash. A valid script will look like this:
if __name__ == ‘__main__’:
import tetrax as tx
sample = tx.Sample(...)
...