pyopensn.solver.DiscreteOrdinatesProblem

class pyopensn.solver.DiscreteOrdinatesProblem

Base class for discrete ordinates problems in Cartesian geometry.

This class implements the algorithms necessary to solve a problem using the discrete ordinates method. When paired with a solver base, the result is a solver instance configured for a specific problem type (steady-state, transient, adjoint, k-eigenvalue, etc.).

Wrapper of opensn::DiscreteOrdinatesProblem.

ComputeFieldFunctionPowerScaleFactor(self: pyopensn.solver.LBSProblem, power_normalization_target: float) → float

Compute the scale factor that would normalize the current scalar flux’s total power to a target value.

This is a collective operation and must be called on all MPI ranks.

Parameters:

power_normalization_target (float) – Target total power (must be positive). The returned factor is power_normalization_target / global_total_power, where global_total_power is the same MPI-reduced, kappa-weighted total power CreateFieldFunction(..., "power", ...) and the power field function use.

Notes

This does not mutate any solver state. It is the same scale factor CreateFieldFunction(..., "power", power_normalization_target) applies internally, exposed directly so callers can apply it to their own derived quantities (e.g. postprocessor output) without needing a field function.

ComputeFissionProduction(self: pyopensn.solver.LBSProblem, scalar_flux_iterate: str) → float

Computes the total fission production (nu*fission).

Parameters:

scalar_flux_iterate ({'old', 'new'}) –

Specifies which scalar flux vector to use in the calculation.
  • ’old’: Use the previous scalar flux iterate.

  • ’new’: Use the current scalar flux iterate.

Returns:

The total fission production, integrated over the physical volume. In RZ and 1D spherical geometry the integral covers the full revolution (factors of 2*pi and 4*pi).

Return type:

float

Raises:

ValueError – If scalar_flux_iterate is not ‘old’ or ‘new’.

ComputeFissionRate(self: pyopensn.solver.LBSProblem, scalar_flux_iterate: str) → float

Computes the total fission rate.

Parameters:

scalar_flux_iterate ({'old', 'new'}) –

Specifies which scalar flux vector to use in the calculation.
  • ’old’: Use the previous scalar flux iterate.

  • ’new’: Use the current scalar flux iterate.

Returns:

The total fission rate, integrated over the physical volume. In RZ and 1D spherical geometry the integral covers the full revolution (factors of 2*pi and 4*pi).

Return type:

float

Raises:

ValueError – If scalar_flux_iterate is not ‘old’ or ‘new’.

ComputeLeakage(self: pyopensn.solver.DiscreteOrdinatesProblem, bnd_names: list) → dict

Compute leakage for the problem.

Parameters:

bnd_names (List[str]) – A list of boundary names for which leakage should be computed. An empty list selects all boundaries. RZ problems use rmin, rmax, zmin, and zmax.

Returns:

A dictionary mapping boundary names to group-wise leakage vectors. Each array contains the net leakage (per group): the outgoing partial current minus the incoming partial current, integrated over the corresponding boundary surface. On a vacuum boundary this equals the outgoing current; on a boundary with an incident flux it is reduced by the inflow and can be negative; on a reflecting boundary it vanishes at convergence. In RZ geometry the surface integral covers the full revolution.

Return type:

Dict[str, numpy.ndarray]

Raises:

ValueError – If one or more boundary ids are not present on the current mesh.

CreateAndWriteSourceMoments(self: pyopensn.solver.LBSProblem, file_base: str) → None

Write source moments from latest flux iterate to file.

Parameters:

file_base (str) – File basename.

CreateFieldFunction(self: pyopensn.solver.LBSProblem, name: str, xs_name: str, power_normalization_target: float = -1.0) → pyopensn.fieldfunc.FieldFunctionGridBased

Create a named scalar field function derived from a 1D XS or power.

Parameters:
  • name (str) – Name to assign to the returned field function.

  • xs_name (str) – Built-in 1D XS name, custom XS name, or the special value power. CSDA-enabled discrete-ordinates problems also support csda_energy_deposition, cepxs_energy_deposition, csda_charge_deposition, csda_charge_deposition_term, and csda_charge_deposition_term_cellavg. When CSDA is enabled, energy_deposition is an alias for the conservative csda_energy_deposition. cepxs_energy_deposition preserves the imported CEPXS response plus the CSDA energy-space contribution.

  • power_normalization_target (float, default=-1.0) – If positive, scale the derived field function so that the raw power field would integrate to this total power.

Notes

The returned field function is created on demand from the current scalar-flux iterate. For ordinary XS names this computes sum_g xs[g] * phi_g at each node.

The returned field function is a snapshot of the solver state at creation time; it is not refreshed automatically if the solver state changes. It supports CanUpdate() and Update() while its owning problem is still alive. Calling Update() explicitly recomputes the same field function from the solver’s latest state.

If xs_name == "power", the same power-generation formula used elsewhere by the solver is applied on demand.

CSDA deposition fields are derived from the current scalar flux and terminal charged-particle current information. They should normally be created after the CSDA solve has converged.

If power_normalization_target > 0, the returned field function is scaled using the power implied by the current scalar flux. This scaling affects only the returned field function; it does not mutate the solver’s internal phi vectors.

The returned field function is a fresh object created for this call. It is not automatically updated by later solves or timesteps.

GetAngularFieldFunctionList(self: pyopensn.solver.DiscreteOrdinatesProblem, groups: list, angles: list) → list

Create field functions for selected angular flux components.

Note: You must enable angular flux storage (save_angular_flux=True) in the problem options. For transient problems this is required. The angular flux is also stored when deterministic_sweeps=True. If neither option is set, the returned field functions will remain zero.

Example

solver.Initialize()
solver.Execute()
ang_ff = phys.GetAngularFieldFunctionList(groups=[0], angles=[0])

For transient/time-dependent runs, each field function is still a snapshot. Either call this after each timestep to create a fresh object or keep the returned object and call Update() after each timestep before exporting or interpolating it. Two common patterns are:

  1. Use TransientSolver.Execute() with a post-advance callback:

solver = TransientSolver(problem=phys)
solver.Initialize()
ang_ff = phys.GetAngularFieldFunctionList(groups=[0], angles=[0])

def post_advance():
    for ff in ang_ff:
        ff.Update()
    FieldFunctionGridBased.ExportMultipleToPVTU(ang_ff, "angular_flux_t")

solver.SetPostAdvanceCallback(post_advance)
solver.Execute()
  1. Use a custom Python loop with TransientSolver.Advance():

solver = TransientSolver(problem=phys)
solver.Initialize()
ang_ff = phys.GetAngularFieldFunctionList(groups=[0], angles=[0])
for _ in range(num_steps):
    solver.Advance()
    for ff in ang_ff:
        ff.Update()
    FieldFunctionGridBased.ExportMultipleToPVTU(ang_ff, "angular_flux_t")
Parameters:
  • groups (List[int]) – Global group indices to export.

  • angles (List[int]) – Angle indices within the groupset quadrature for each group.

Returns:

Field functions for the requested (group, angle) pairs. Each returned field function is a snapshot, but supports CanUpdate() and Update() while its owning problem is alive.

Return type:

List[pyopensn.fieldfunc.FieldFunctionGridBased]

GetPhiNewLocal(self: pyopensn.solver.LBSProblem) → memoryview

Get the current scalar flux iterate (local vector).

Returns:

Memory view of the local new scalar flux vector.

Return type:

memoryview

GetPhiOldLocal(self: pyopensn.solver.LBSProblem) → memoryview

Get the previous scalar flux iterate (local vector).

Returns:

Memory view of the local old scalar flux vector.

Return type:

memoryview

GetPsi(self: pyopensn.solver.DiscreteOrdinatesProblem) → list

Return psi as a list of NumPy arrays (float64).

The arrays are copies of the current angular-flux state. Mutating them does not mutate the problem.

GetScalarFluxFieldFunction(self: pyopensn.solver.LBSProblem, only_scalar_flux: bool = True) → list

Return scalar-flux or flux-moment field functions grouped by energy group.

Parameters:

only_scalar_flux (bool, default=True) – If True, returns only the zeroth moment (scalar flux) field function for each group. If False, returns all moment field functions for each group.

Returns:

If only_scalar_flux=True: result[g] is the scalar-flux field function for group g.

If only_scalar_flux=False: result[g][m] is the field function for group g and moment m.

Return type:

Union[List[pyopensn.fieldfunc.FieldFunctionGridBased], List[List[pyopensn.fieldfunc.FieldFunctionGridBased]]]

Notes

Field functions are created on demand from the current solver state.

The returned field functions are snapshots of the solver state at creation time; they are not refreshed automatically if the solver state changes.

They support CanUpdate() and Update() while their owning problem is still alive. Calling Update() explicitly refreshes the same field-function object from the solver’s latest state.

Calling GetScalarFluxFieldFunction(only_scalar_flux=False) creates all requested moments from the current phi iterate at the time of the call.

In the nested form (only_scalar_flux=False), the moment index varies fastest within each group (inner index = moment, outer index = group).

GetTime(self: pyopensn.solver.LBSProblem) → float

Get the current simulation time in seconds.

GetTimeStep(self: pyopensn.solver.LBSProblem) → float

Get the current timestep size.

IsAdjoint(self: pyopensn.solver.LBSProblem) → bool

Return True if the problem is in adjoint mode, otherwise False.

IsTimeDependent(self: pyopensn.solver.DiscreteOrdinatesProblem) → bool

Return True if the problem is currently in time-dependent mode.

ReadAngularFluxes(self: opensn::DiscreteOrdinatesProblem, file_base: str) → None

Read angular fluxes from file.

Parameters:

file_base (str) – File basename.

ReadFluxMoments(self: pyopensn.solver.LBSProblem, file_base: str, single_file_flag: bool) → None

Read flux moment data.

Parameters:
  • file_base (str) – File basename.

  • single_file_flag (bool) – True to read the single file <file_base>.h5 instead of the per-rank file <file_base><rank>.h5. Serial runs only: a multi-rank run raises ValueError before any file is opened.

ReadFluxMomentsAndMakeSourceMoments(self: pyopensn.solver.LBSProblem, file_base: str, single_file_flag: bool) → None

Read flux moments and compute corresponding source moments.

Parameters:
  • file_base (str) – File basename.

  • single_file_flag (bool) – True to read the single file <file_base>.h5 instead of the per-rank file <file_base><rank>.h5. Serial runs only: a multi-rank run raises ValueError before any file is opened.

ReadSourceMoments(self: pyopensn.solver.LBSProblem, file_base: str, single_file_flag: bool) → None

Read source moments from file.

Parameters:
  • file_base (str) – File basename.

  • single_file_flag (bool) – True to read the single file <file_base>.h5 instead of the per-rank file <file_base><rank>.h5. Serial runs only: a multi-rank run raises ValueError before any file is opened.

ReadSurfaceAngularFluxes(self: opensn::DiscreteOrdinatesProblem, file_base: str, surfaces: list) → list

Read surface angular fluxes from file.

Parameters:
  • file_base (str) – File basename.

  • surfaces (list[str]) – Stored surface tags to read. Use the boundary name for an exterior boundary. For an interior surface named ‘<name>’, use ‘<name>_u’ for faces whose outward normal aligns with the positive axis and ‘<name>_d’ for faces with the opposite orientation.

Returns:

Surface mapping and angular-flux data for each groupset and requested surface. Each entry has keys ‘groupset_id’, ‘adjoint’, ‘surface_name’, ‘mapping’, and ‘data’. ‘adjoint’ is True when the file was written from an adjoint problem. The ‘cell_map’ in ‘mapping’ maps face centroids, with ‘centroid_origin’ subtracted before each coordinate is divided by ‘centroid_spacing’ (1e-9 times the global mesh extent) and rounded to an integer, to the surface face index. The same face has the same key from either side of an interior surface and in every file for the same mesh.

Return type:

List[dict]

Notes

Each rank reads <file_base><rank>.h5; the files must have been written with the same mesh partitioning.

SetAdjoint(self: pyopensn.solver.LBSProblem, adjoint: bool = True) → None

Set forward/adjoint transport mode.

Parameters:

adjoint (bool, default=True) – True enables adjoint mode and False enables forward mode. Adjoint mode is supported only for Cartesian geometries with standard quadrature operators (operator_method='standard'), in steady-state mode, and without an uncollided flux. Uncollided flux generation (UncollidedProblem) is forward only. An unsupported request raises ValueError before any state changes.

Raises:

ValueError – If adjoint=True and the problem is time-dependent, has options.csda_enabled=True, was constructed with an uncollided_flux file, or is an UncollidedProblem. The problem is left unchanged.

Notes

This is one of two supported mode-setting paths in Python:
  1. options={'adjoint': ...} in the problem constructor.

  2. SetAdjoint(...) (this method).

If this changes mode, OpenSn performs a full mode-transition reset:
  • Materials are reinitialized in the selected mode.

  • Point and volumetric sources are cleared.

  • Boundary conditions are cleared.

  • Scalar and angular flux vectors are zeroed.

If this is called with the same mode as the current setting, no reset is performed.

The block-id to cross-section map is preserved across the transition. The mode change applies to this problem only. Other problems that share the mapped MultiGroupXS objects keep their own mode.

After a mode change, reapply the desired driving terms before solving, typically:

This routine is intentionally destructive with respect to source/boundary/flux state to avoid hidden coupling between forward and adjoint setups.

This is a collective operation and must be called on all ranks.

SetBoundaryOptions(self: pyopensn.solver.DiscreteOrdinatesProblem, **kwargs) → None

Set or clear boundary conditions.

Parameters:
  • clear_boundary_conditions (bool, default=False) – If true, all current boundary conditions are deleted.

  • boundary_conditions (List[Dict]) –

    A list of boundary condition dictionaries. Each dictionary supports:
    • name: str (required)

      Boundary name that identifies the specific boundary.

    • type: {‘vacuum’, ‘isotropic’, ‘reflecting’, ‘arbitrary’} (required)

      Boundary type specification.

    • group_strength: List[float], optional

      Required when type='isotropic'. Isotropic strength per group.

    • start_time: float, optional

      Active start time for isotropic boundaries only. Defaults to -infinity.

    • end_time: float, optional

      Active end time for isotropic boundaries only. Defaults to infinity.

    • function: AngularFluxFunction, optional

      Required when type='arbitrary' unless time_function is supplied. Callable that returns incoming angular flux from group and direction.

    • time_function: AngularFluxTimeFunction, optional

      Required when type='arbitrary' unless function is supplied. Callable that returns incoming angular flux from group, direction, and time.

    Isotropic boundaries may use start_time/end_time for simple on/off behavior. Arbitrary boundaries must specify exactly one of function or time_function; use time_function for time-dependent arbitrary inflow and handle any active window inside that callback.

Notes

Mode transitions via LBSProblem.SetAdjoint() clear all boundary conditions. Reapply boundaries with this method before solving in the new mode.

This is a collective operation and must be called on all ranks.

SetForward(self: pyopensn.solver.LBSProblem) → None

Set forward transport mode.

Equivalent to SetAdjoint(False).

SetPointSources(self: pyopensn.solver.LBSProblem, **kwargs) → None

Set or clear point sources.

Parameters:
  • clear_point_sources (bool, default=False) – If true, all current the point sources of the problem are deleted.

  • point_sources (List[pyopensn.source.PointSource]) – List of new point sources to be added to the problem. When both arguments are given, the current sources are cleared before the new ones are added, regardless of keyword order. The new list is validated as a whole: a rejected call leaves the problem’s sources unchanged.

Notes

This is collective. A source caches mesh data when added. Prefer a separate source object for each problem. Share one only when both problems use the same mesh and spatial layout.

SetSteadyStateMode(self: pyopensn.solver.DiscreteOrdinatesProblem) → None

Set the problem to steady-state mode.

Notes

Switch problem from time-dependent to steady-state mode. This updates problem internals (sweep chunk mode and source-function) while preserving user boundary conditions and fixed sources.

This is a collective operation and must be called on all ranks.

SetTimeDependentMode(self: pyopensn.solver.DiscreteOrdinatesProblem) → None

Set the problem to time-dependent mode.

Notes

Switch problem from steady-state to time-dependent mode. This updates problem internals (sweep chunk mode and source-function) while preserving user boundary conditions and fixed sources.

Requires options.save_angular_flux=True at problem creation and VELOCITY or INV_VELOCITY data in every cross section. Not supported for adjoint, GPU, curvilinear, or uncollided-flux problems. An unsupported request raises ValueError before any state changes.

This is a collective operation and must be called on all ranks.

SetVolumetricSources(self: pyopensn.solver.LBSProblem, **kwargs) → None

Set or clear volumetric sources.

Parameters:
  • clear_volumetric_sources (bool, default=False) – If true, all current the volumetric sources of the problem are deleted.

  • volumetric_sources (List[pyopensn.source.VolumetricSource]) – List of new volumetric sources to be added to the problem. When both arguments are given, the current sources are cleared before the new ones are added, regardless of keyword order. The new list is validated as a whole: a rejected call leaves the problem’s sources unchanged.

Notes

This is collective. A source caches mesh data when added. Prefer a separate source object for each problem. Share one only when both problems use the same mesh and spatial layout.

SetXSMap(self: pyopensn.solver.LBSProblem, **kwargs) → None

Replace the block-id to cross-section map.

Parameters:

xs_map (List[Dict]) –

A list of block-id to cross-section mapping dictionaries. Each dictionary supports:
  • block_ids: List[int] (required)

    Mesh block ids to associate with the cross section.

  • xs: pyopensn.xs.MultiGroupXS (required)

    Cross section object.

Raises:

ValueError – If the problem was constructed with an uncollided_flux file, or if options.csda_enabled=True and the new cross sections split a charged-particle group block across groupsets, contain more than two charged-particle group ranges, have negative or non-finite stopping powers or non-positive energy-group widths, or have stopping power or energy bounds that do not match the problem’s group count. CSDA also rejects conflicting supplied energy structures, unknown or conflicting charged-particle species, or a map with no energy structure. Individual materials may omit bounds and use the shared structure.

Notes

This is collective.

The problem is refreshed immediately after replacing the map. Material metadata, precursor storage, GPU carriers, and derived solver state owned by the concrete problem are rebuilt for the new cross sections.

If options.use_precursors=True, this flag remains active across XS-map changes even when the current map has no precursor-bearing material. In that case delayed-neutron source terms are simply inactive until a later map provides precursor data again.

Existing precursor concentrations are remapped by local cell and precursor-family index. When the new material for a cell has fewer precursor families, extra old families are dropped. When it has more families, newly introduced families are initialized to zero. If a cell changes through a material with zero precursors, the precursor history for that cell is discarded and any later reintroduced precursor families start from zero.

If any fissionable material in the new map contains delayed-neutron precursor data and options.use_precursors=True, all fissionable materials in the map must contain precursor data. Non-fissionable materials may have zero precursors.

The new map is validated before it is committed. A validation error leaves the map unchanged. A later rebuild failure may leave partial changes. In time-dependent mode, every cross section must provide VELOCITY or INV_VELOCITY data.

Forward/adjoint mode toggles via LBSProblem.SetAdjoint() do not change this map. The MultiGroupXS objects themselves are mutable and shared by pointer, so a change to one, such as Scale, is seen by every problem that uses it. The transport mode belongs to each problem: problems that share a MultiGroupXS handle can run in different modes.

WriteAngularFluxes(self: opensn::DiscreteOrdinatesProblem, file_base: str) → None

Write angular flux data to file.

Parameters:

file_base (str) – File basename.

WriteFluxMoments(self: pyopensn.solver.LBSProblem, file_base: str) → None

Write flux moments to file.

Parameters:

file_base (str) – File basename.

WriteSurfaceAngularFluxes(self: opensn::DiscreteOrdinatesProblem, file_base: str, boundary_surfaces: list[str] = [], interior_surfaces: dict[str, tuple[str, float]] = {}) → None

Write surface angular flux data to file.

Parameters:
  • file_base (str) – File basename.

  • boundary_surfaces (list[str], default=[]) – Boundary names to export.

  • interior_surfaces (dict[str, tuple[str, float]], default={}) – Interior surfaces in the form {‘name’: (‘axis’, value)}, where axis is ‘x’, ‘y’, or ‘z’. Each interior surface is written under two tags: ‘<name>_u’ for faces whose outward normal aligns with the positive axis and ‘<name>_d’ for faces with the opposite orientation. An interior surface must match at least one cell face, must lie on cell faces inside the mesh, and may not share a plane with another interior surface. Its generated tags may not equal a requested boundary name. It may not coincide with an exterior boundary; export that boundary by name using boundary_surfaces instead.

Notes

Requires options.save_angular_flux=True. Collective over all ranks; surface selections may differ by rank. Each rank writes <file_base><rank>.h5. The file records whether the problem is in adjoint mode. After an adjoint steady-state solve, the stored angular flux is the adjoint flux for the listed direction, so forward and adjoint data with the same indices refer to the same direction.

ZeroPhi(self: pyopensn.solver.LBSProblem) → None

Zero the scalar-flux vectors (phi_old and phi_new) in-place.

ZeroPsi(self: pyopensn.solver.DiscreteOrdinatesProblem) → None

Zero the angular-flux storage.

__init__(self: pyopensn.solver.DiscreteOrdinatesProblem, **kwargs) → None

Construct a discrete ordinates problem with Cartesian geometry.

Parameters:
  • mesh (Mesh) – The spatial mesh.

  • num_groups (int) – The total number of energy groups.

  • groupsets (List[Dict]) –

    A list of input parameter blocks, each block provides the iterative properties for a groupset. The inclusive ranges must partition all groups in order, starting at group 0 and ending at num_groups - 1, without gaps or overlaps. Each dictionary supports:

    • groups_from_to: List[int] (required)

      Two-entry list with the first and last group id for the groupset, e.g. [0, 3].

    • angular_quadrature: pyopensn.aquad.AngularQuadrature, optional

      Handle to an angular quadrature.

    • angle_aggregation_type: {‘polar’, ‘single’, ‘azimuthal’, ‘quadrant’, ‘octant’}, default=’single’

      Angle aggregation method to use during sweeping. 'quadrant' (2D) and 'octant' (3D) put all directions in the same quadrant or octant in one angle set. They require a Cartesian orthogonal mesh and a quadrature in which every direction has nonzero Omega_x and Omega_y (and, for 'octant', Omega_z), so each direction lies strictly inside one quadrant or octant.

    • inner_linear_method: {‘classic_richardson’, ‘petsc_richardson’, ‘petsc_gmres’, ‘petsc_fgmres’, ‘petsc_bicgstab’}, default=’petsc_richardson’

      Iterative method used for inner linear solves. 'petsc_fgmres' is flexible GMRES with right preconditioning; it remains exact when the WGDSA/TGDSA preconditioner solves its diffusion system only approximately.

    • l_abs_tol: float, default=1.0e-6

      Inner linear solver absolute residual tolerance.

    • l_max_its: int, default=200

      Inner linear solver maximum iterations.

    • gmres_restart_interval: int, default=30

      GMRES restart interval, if GMRES is used.

    • allow_cycles: bool, default=True

      Whether cyclic dependencies are allowed in sweeps.

    • apply_wgdsa: bool, default=False

      Enable within-group DSA for this groupset. After each groupset iteration, one diffusion solve corrects the scalar flux of every group of the groupset. The system is block diagonal in energy: the source of group g is the change of its within-group scattering source, and the groups are not coupled. With csda_enabled and charged-particle groups in the groupset, each group’s diffusion operator also removes the CSDA slowing-down rate S_g / dE_g, and the groups are solved one at a time in energy order, coupled by in-groupset scattering and slowing-down. See Within-group diffusion synthetic acceleration.

    • wgdsa_l_abs_tol: float, default=1.0e-4

      Residual tolerance of the WGDSA diffusion solve, relative to the norm of its right-hand side (the name is historical).

    • wgdsa_l_max_its: int, default=30

      WGDSA maximum iterations.

    • wgdsa_verbose: bool, default=False

      Verbose WGDSA output.

    • wgdsa_petsc_options: str, default=’’

      PETSc options string for the WGDSA solver. Options must carry the solver’s prefix, the problem name followed by _WGDSA. With csda_enabled, a groupset with charged-particle groups has one solver per group, whose prefix is the problem name followed by _WGDSA_g and the global group index.

    • wgdsa_solver_policy: {‘auto’, ‘direct’, ‘iterative’, ‘petsc_options’}, default=’auto’

      WGDSA diffusion solver policy. auto uses a direct PETSc LU solve on one MPI process at or below wgdsa_direct_solve_threshold global unknowns, and conjugate gradients preconditioned by BoomerAMG otherwise. petsc_options lets wgdsa_petsc_options control the PETSc KSP/PC setup.

    • wgdsa_direct_solve_threshold: int, default=20000

      Maximum global WGDSA diffusion unknown count for the automatic direct solve, the number of spatial nodes times the number of groups in the groupset. The CSDA operator solves one group at a time, so the count is that of one group.

    • wgdsa_boundary_closure: {‘marshak’, ‘closure_r’, ‘dirichlet’}, default=’marshak’

      Boundary condition of the WGDSA diffusion correction on vacuum, isotropic and arbitrary boundaries. marshak imposes the natural Marshak condition, a face mass term with coefficient 1/2; closure_r blends the Marshak form written with the quadrature’s partial current (face mass coefficient 2 beta_f, beta_f the quadrature’s half-range moment, against the analytic 1/2) on thin boundary cells with the half-range transport form on thick ones, uses beta_f as the floor of the interior penalty, and is faster than marshak when boundary cells are many mean free paths thick; dirichlet (OpenSn’s original) imposes a zero correction weakly (interior-penalty term). Reflecting boundaries are zero-current, except that on a reflecting boundary that lags its incoming flux, WGDSA imposes the inward partial current of the change of the lagged flux.

    • apply_tgdsa: bool, default=False

      Enable two-grid DSA for this groupset. After each groupset iteration (after WGDSA), one energy-collapsed diffusion solve corrects the error mode that the scattering between the groups of the groupset couples. Requires at least two groups in the groupset.

    • tgdsa_l_abs_tol: float, default=1.0e-4

      Residual tolerance of the TGDSA diffusion solve, relative to the norm of its right-hand side (the name is historical).

    • tgdsa_l_max_its: int, default=30

      TGDSA maximum iterations.

    • tgdsa_verbose: bool, default=False

      Verbose TGDSA output.

    • tgdsa_petsc_options: str, default=’’

      PETSc options string for the TGDSA solver. Options must carry the solver’s prefix, the problem name followed by _TGDSA.

    • tgdsa_solver_policy: {‘auto’, ‘direct’, ‘iterative’, ‘petsc_options’}, default=’auto’

      TGDSA diffusion solver policy. auto uses a direct PETSc LU solve on one MPI process at or below tgdsa_direct_solve_threshold global unknowns, and conjugate gradients preconditioned by BoomerAMG otherwise. petsc_options lets tgdsa_petsc_options control the PETSc KSP/PC setup.

    • tgdsa_direct_solve_threshold: int, default=20000

      Maximum global TGDSA diffusion unknown count for the automatic direct solve, the number of spatial nodes.

    • tgdsa_boundary_closure: {‘marshak’, ‘closure_r’, ‘dirichlet’}, default=’marshak’

      Boundary condition of the TGDSA diffusion correction, with the same choices and boundaries as wgdsa_boundary_closure.

    • wgdsa_h_perp_convention: {‘face_side’, ‘cell’}, default=’face_side’

      Penalty length of the WGDSA MIP operator. face_side uses the face-dependent orthogonal length (3V/A_f tet, V/A_f hex and quad, 2V/A_f triangle) capped by four times the smallest height of the face’s PWLD side simplices, with an extra factor 2 on polygons and polyhedra; the cap keeps the operator positive definite on strongly distorted cells and is inactive on regular ones. cell (OpenSn’s original) uses the cell-wide lengths 3V/S (tet) and V/S (hex) with the extra factor 2, and on polygons the face-dependent lengths without the cap or the factor 2. On polyhedra its penalty is larger (six times on cubes), which slows DSA on cells a few mean free paths thick; on polygons it is half the face_side penalty and can make the operator indefinite on strongly distorted cells.

    • tgdsa_h_perp_convention: {‘face_side’, ‘cell’}, default=’face_side’

      Penalty length of the TGDSA MIP operator, as wgdsa_h_perp_convention.

  • xs_map (List[Dict]) –

    A list of mappings from block ids to cross-section definitions. Each dictionary supports:
    • block_ids: List[int] (required)

      Mesh block IDs to associate with the cross section.

    • xs: pyopensn.xs.MultiGroupXS (required)

      Cross-section object to assign to the specified blocks.

  • boundary_conditions (List[Dict], default=[]) –

    A list containing tables for each boundary specification. Each dictionary supports:
    • name: str (required)

      Boundary name that identifies the specific boundary.

    • type: {‘vacuum’, ‘isotropic’, ‘reflecting’, ‘arbitrary’} (required)

      Boundary type specification.

    • group_strength: List[float], optional

      Required when type='isotropic'. Isotropic strength per group.

    • start_time: float, optional

      Active start time for isotropic boundaries only. Defaults to -infinity.

    • end_time: float, optional

      Active end time for isotropic boundaries only. Defaults to infinity.

    • function: AngularFluxFunction, optional

      Required when type='arbitrary' unless time_function is supplied. Callable that returns incoming angular flux from group and direction.

    • time_function: AngularFluxTimeFunction, optional

      Required when type='arbitrary' unless function is supplied. Callable that returns incoming angular flux from group, direction, and time.

    Isotropic boundaries may use start_time/end_time for simple on/off behavior. Arbitrary boundaries must specify exactly one of function or time_function; use time_function for time-dependent arbitrary inflow and handle any active window inside that callback.

  • point_sources (List[pyopensn.source.PointSource], default=[]) – A list of point sources.

  • volumetric_sources (List[pyopensn.source.VolumetricSource], default=[]) – A list of volumetric sources.

  • options (Dict, default={}) –

    A block of optional configuration parameters, including:
    • max_mpi_message_size: int, default=4194304

      Maximum size in bytes of one sweep MPI message. Larger angular-flux transfers are split into messages of at most this size.

    • restart_writes_enabled: bool, default=False

      Enable restart dump writes for solvers that support restart output.

    • write_delayed_psi_to_restart: bool, default=True

      Include delayed sweep angular-flux buffers in steady-state restart dumps. These buffers are optional when a steady-state restart is used only as a transient initial condition because the transient initialization can reconstruct angular state from the flux moments. Time-dependent restart dumps always include them, regardless of this option, because continuing a transient requires them whenever the problem has delayed sweep angular state, including partitioned parallel, reflected-boundary, and cyclic-sweep cases.

    • write_angular_flux_to_restart: bool, default=True

      Include stored angular fluxes in steady-state restart dumps when save_angular_flux=True. They are optional when a steady-state restart is used only as a transient initial condition. Time-dependent restart dumps always include them, regardless of this option, because continuing a transient requires them.

    • read_restart_path: str, default=’’

      File stem for reading a full restart. Scalar flux and precursor data can be remapped when the MPI rank count or mesh partition changes. Full transient continuation still requires the original partitioned angular state layout.

    • read_initial_condition_path: str, default=’’

      File stem for reading restart data as an initial condition. Cannot be combined with read_restart_path. A steady-state restart may be used by TransientSolver through this option. The first TransientSolver.Initialize() loads it once; later initializations continue from the problem’s current state.

    • write_restart_path: str, default=’’

      File stem for restart dump writes. OpenSn appends the MPI rank and .restart.h5 to this stem.

    • write_restart_time_interval: int, default=0 (must be 0 or >=30)

    • use_precursors: bool, default=True Enable delayed neutrons. With False every solve (steady-state, k-eigenvalue and transient) uses prompt neutrons only, even if the cross sections have delayed-neutron data; a k-eigenvalue solve then gives the prompt eigenvalue. This is treated as user intent and remains active across later SetXSMap calls, even if the current XS map temporarily contains no precursor-bearing material. When XS maps are swapped, existing precursor concentrations are remapped by cell and precursor-family index; new families start at zero and removed families are discarded. If any fissionable material in the active map has precursor data and use_precursors=True, all fissionable materials in that map must have precursor data. Non-fissionable materials may have zero precursors.

    • delayed_neutrons: bool, default=True Alias of use_precursors. Give at most one of the two names.

    • use_source_moments: bool, default=False Use the problem’s source moments as the fixed source instead of its volumetric and point sources. Provide them (e.g. with ReadSourceMoments) after creating the problem and before solving; a solve without them raises ValueError. They are an external source, so the k-eigenvalue solvers reject a problem with this option.

    • save_angular_flux: bool, default=False Store angular flux state (psi) for transient mode, angular-flux field functions, and angular-flux I/O.

    • deterministic_sweeps: bool, default=False Make every sweep bitwise reproducible from run to run: the scalar flux moments and face outflows are summed on the host from stored angular fluxes in a fixed angle order instead of in the order that MPI messages and GPU threads complete. Stores the angular flux in host memory without enabling save_angular_flux. GPU sweeps also copy it to the host after every sweep, which makes them roughly 2-5 times slower. Meant for debugging and reproducible comparisons.

    • adjoint: bool, default=False

    • csda_enabled: bool, default=False Enable CSDA charged-particle transport for CEPXS data loaded with csda_format=True. CSDA requires a Cartesian SteadyStateSourceSolver solve, sweep_type='AAH', CPU sweeps, no apply_tgdsa in any groupset, and charged-particle group ranges that are not split across groupsets. apply_wgdsa uses a CSDA diffusion operator in groupsets with charged-particle groups. All materials must supply identical per-group energy bounds or omit them; at least one material must supply the shared structure.

    • verbose_inner_iterations: bool, default=True Print inner iteration details, including WGS and AGS iterations.

    • verbose_outer_iterations: bool, default=True Print outer solver progress, including PI/NLKE iterations and transient steps.

    • max_ags_iterations: int, optional Maximum across-groupset iterations per transport solve. A value set here is used by every solver. If it is not set, each solver uses its own default: 100 for the steady-state and transient solvers, and 1 in each power iteration of pyopensn.solver.PowerIterationKEigenSolver.

    • ags_tolerance: float, default=1.0e-6

    • ags_convergence_check: {‘l2’, ‘pointwise’}, default=’l2’

    • power_default_kappa: float, default=3.20435e-11

    • field_function_prefix_option: {‘prefix’, ‘solver_name’}, default=’prefix’

    • field_function_prefix: str, default=’’

    • fused_aao_sweep: bool, default=False Use the fused all-at-once GPU scheduler for AAH sweeps. Each kernel launch sweeps the current level of up to 256 ready angle sets instead of one, which reduces launch count when individual levels are too small to fill the GPU. Up to fused_aao_lanes such runs are in flight at once, so angle sets that become ready later (for example when upstream angular fluxes arrive from another rank) start without waiting for the others. The solution matches the default scheduler to floating-point rounding. Requires sweep_type="AAH" and use_gpus=True. Otherwise construction raises an error.

    • fused_aao_lanes: int, default=8 With fused_aao_sweep=True, the number of fused runs (each a batch of angle sets on its own GPU stream) that may be in flight at once on each rank. Must be at least 1. Ignored unless fused_aao_sweep=True.

    These options are applied at problem creation.

  • sweep_type (str, default="AAH") – The sweep type to use. Must be one of AAH or CBC. Defaults to AAH. Both sweep types support time-dependent (transient) mode.

  • time_dependent (bool, default=False) – If true, the problem starts in time-dependent mode. Otherwise it starts in steady-state mode. Requires options.save_angular_flux=True and VELOCITY or INV_VELOCITY data in every cross section. Both AAH and CBC sweep types support time-dependent mode.

  • uncollided_flux (str, default="") – HDF5 file generated by UncollidedSolver. For steady-state forward fixed-source calculations, OpenSn uses its moments to construct the first-collision scattering and fission source, solves for the collided component, and adds the uncollided moments back to the converged state. The file must match the current group count, mesh cell IDs, cell-node layout and coordinates, total cross sections, and reflecting boundary set. Its maximum moment order must be at least this problem’s scattering order. The same serial file may be read by any MPI partitioning of the matching mesh. The first-collision source replaces the fixed sources, so the problem must not also have volumetric or point sources or incoming-flux (isotropic or arbitrary) boundaries, and its cross sections cannot be replaced.

  • use_gpus (bool, default=False) – A flag specifying whether GPU acceleration is used for the sweep. Both `AAH` and `CBC` sweep types support GPU acceleration.

Notes

Construction validates and builds the runtime problem. It is collective. Use equivalent input on every MPI rank.