1.6. DataTypes Reference#

All ANTS solvers accept typed dataclass objects rather than raw arrays and dictionaries. These objects group related inputs, provide defaults, and make the solver signatures self-documenting.

The main dataclasses are defined in ants.datatypes:

from ants.datatypes import (
    GeometryData,
    HybridData,
    MaterialData,
    QuadratureData,
    SolverData,
    SourceData,
    TemporalDiscretization,
    TimeDependentData,
)

1.6.1. MaterialData#

Holds cross sections and neutron velocity for a set of materials.

mat_data = MaterialData(
    total=xs_total,       # shape (M, G)
    scatter=xs_scatter,   # shape (M, G, G)
    fission=xs_fission,   # shape (M, G, G)
    velocity=velocity,    # shape (G,) — required for time-dependent problems
)

For fixed-source and criticality problems velocity can be omitted. The cross sections can be built from an HDF5 library via ants.materials() (see Standard Inputs), which also sets the velocity:

mat_data = ants.materials(70, ["uranium-%0.7%", "high-density-polyethylene"],
                          library="endf_lanl70.h5")

1.6.2. SourceData#

Holds initial conditions, external source, and boundary conditions. The required fields depend on the problem type and time integrator. The inline shapes below are illustrative — see Standard Inputs for the authoritative broadcast-shape rules of external, boundary_x, and boundary_y.

Fixed source / criticality (1D):

sources = SourceData(
    external=np.ones((cells_x, 1, 1)),  # shape (I, N, G) or broadcast
    boundary_x=np.zeros((2, 1, 1)),     # shape (2, N, G) or broadcast
)

Time-dependent 1D (BDF1):

sources = SourceData(
    initial_flux=np.zeros((cells_x, angles, groups)),  # shape (I, N, G)
    external=external,                                  # shape (T, I, N, G)
    boundary_x=boundary_x,                             # shape (T, 2, N, G)
)

Time-dependent 2D with TR-BDF2 (edge-based flux):

sources = SourceData(
    initial_flux_x=np.zeros((cells_x + 1, cells_y, angles**2, groups)),
    initial_flux_y=np.zeros((cells_x, cells_y + 1, angles**2, groups)),
    external=np.zeros((1, cells_x, cells_y, 1, 1)),
    boundary_x=boundary_x,  # shape (T, 2, J, N², G)
    boundary_y=boundary_y,  # shape (T, 2, I, N², G)
)

See Time-Dependent Problems for the complete initial flux shape rules for each time integrator.

1.6.3. GeometryData#

Describes the spatial grid, material layout, and geometry type. See Standard Inputs for the medium_map, delta_x/delta_y array shapes.

# 1D
geometry = GeometryData(
    medium_map=medium_map,  # shape (I,), integer material indices
    delta_x=delta_x,        # shape (I,), cell widths
    bc_x=bc_x,              # [left_bc, right_bc]; 0=vacuum, 1=reflective
    geometry=1,             # 1 = 1D slab, 2 = 1D sphere
)

# 2D
geometry = GeometryData(
    medium_map=medium_map,  # shape (I*J,), integer material indices
    delta_x=delta_x,        # shape (I,)
    delta_y=delta_y,        # shape (J,)
    bc_x=bc_x,
    bc_y=bc_y,
    geometry=3,             # 3 = 2D slab
)

# 3D
geometry = GeometryData(
    medium_map=medium_map,  # shape (I, J, K), integer material indices
    delta_x=delta_x,        # shape (I,)
    delta_y=delta_y,        # shape (J,)
    delta_z=delta_z,        # shape (K,)
    bc_x=bc_x,
    bc_y=bc_y,
    bc_z=bc_z,
    geometry=4,             # 4 = 3D slab
)

1.6.4. SolverData#

Controls solver behavior and output format. All fields have defaults.

solver = SolverData(
    angular=False,          # True → return angular flux; False → scalar flux
    spatial=2,              # 1 = step method, 2 = diamond difference
    max_iter_angular=100,
    tol_angular=1e-6,
    max_iter_energy=100,
    tol_energy=1e-6,
)

1.6.5. TimeDependentData#

Configures the time integration.

from ants.datatypes import TimeDependentData, TemporalDiscretization

time_data = TimeDependentData(
    steps=100,
    dt=0.01,
    time_disc=TemporalDiscretization.TR_BDF2,  # default: BDF1
)

Available TemporalDiscretization values: BDF1, BDF2, CN, TR_BDF2.

1.6.6. HybridData#

Required for the standard collision-based hybrid solvers (hybrid1d, hybrid2d). Generated from the group indexing arrays:

from ants.utils import hybrid as hytools

fine_idx, coarse_idx, factor = hytools.indexing(edges_g, edges_gidx_u, edges_gidx_c)
hybrid_data = HybridData(fine_idx=fine_idx, coarse_idx=coarse_idx, factor=factor)

Not needed for the vectorized hybrid (vhybrid1d, vhybrid2d).

1.6.7. Complete Example: Fixed Source 1D#

import numpy as np
import ants
from ants.datatypes import GeometryData, MaterialData, SolverData, SourceData
from ants.fixed1d import fixed_source

cells_x = 100
angles = 4
groups = 1
bc_x = [0, 0]

length = 1.0
delta_x = np.repeat(length / cells_x, cells_x)
edges_x = np.linspace(0, length, cells_x + 1)

edges_g, _ = ants.energy_grid(None, groups)

medium_map = np.zeros(cells_x, dtype=np.int32)
xs_total = np.array([[1.0]])
xs_scatter = np.array([[[0.0]]])
xs_fission = np.array([[[0.0]]])

quadrature = ants.angular_x(angles, bc_x=bc_x)

mat_data = MaterialData(total=xs_total, scatter=xs_scatter, fission=xs_fission)
sources = SourceData(
    external=np.ones((cells_x, 1, 1)),
    boundary_x=np.zeros((2, 1, 1)),
)
geometry = GeometryData(medium_map=medium_map, delta_x=delta_x, bc_x=bc_x, geometry=1)
solver = SolverData(angular=True)

flux = fixed_source(mat_data, sources, geometry, quadrature, solver)
# flux shape: (I, N, G) if angular=True, else (I, G)

1.6.8. Complete Example: Criticality 1D#

import numpy as np
import ants
from ants.datatypes import GeometryData, SolverData
from ants.critical1d import k_criticality

cells_x = 200
angles = 8
groups = 87
bc_x = [1, 0]  # reflective at origin, vacuum at surface

length = 10.0
delta_x = np.repeat(length / cells_x, cells_x)
edges_x = np.linspace(0, length, cells_x + 1)
edges_g, _ = ants.energy_grid(87, groups)

layers = [[0, "uranium-%20%", "0-4"],
          [1, "uranium-%0%",  "4-6"],
          [2, "stainless-steel-440", "6-10"]]
medium_map = ants.spatial1d(layers, edges_x)

quadrature = ants.angular_x(angles, bc_x=bc_x)
mat_data = ants.materials(87, np.array(layers)[:, 1], datatype=True)

geometry = GeometryData(medium_map=medium_map, delta_x=delta_x, bc_x=bc_x, geometry=2)
solver = SolverData()

flux, keff = k_criticality(mat_data, geometry, quadrature, solver)

1.6.9. Complete Example: Time-Dependent 2D#

import numpy as np
import ants
from ants.datatypes import (
    GeometryData, MaterialData, SolverData, SourceData,
    TemporalDiscretization, TimeDependentData,
)
from ants.timed2d import time_dependent

cells_x = cells_y = 50
angles = 4
groups = 1
steps = 10
dt = 0.1
bc_x = bc_y = [0, 0]

delta_x = np.repeat(1.0 / cells_x, cells_x)
delta_y = np.repeat(1.0 / cells_y, cells_y)
edges_g, _ = ants.energy_grid(None, groups)
velocity = ants.energy_velocity(groups, edges_g)

medium_map = np.zeros(cells_x * cells_y, dtype=np.int32)
xs_total = np.array([[1.0]])
xs_scatter = np.array([[[0.0]]])
xs_fission = np.array([[[0.0]]])

quadrature = ants.angular_xy(angles, bc_x=bc_x, bc_y=bc_y)

mat_data = MaterialData(total=xs_total, scatter=xs_scatter,
                        fission=xs_fission, velocity=velocity)
sources = SourceData(
    initial_flux=np.zeros((cells_x, cells_y, angles**2, groups)),
    external=np.zeros((1, cells_x, cells_y, 1, 1)),
    boundary_x=np.zeros((1, 2, 1, 1, 1)),
    boundary_y=np.zeros((1, 2, 1, 1, 1)),
)
geometry = GeometryData(
    medium_map=medium_map, delta_x=delta_x, delta_y=delta_y,
    bc_x=bc_x, bc_y=bc_y, geometry=3,
)
solver = SolverData()
time_data = TimeDependentData(steps=steps, dt=dt)

flux = time_dependent(mat_data, sources, geometry, quadrature, solver, time_data)
# flux shape: (T, I, J, G)