From a9e53fd3a8c3d4421ca0ea30f216636dc9836e01 Mon Sep 17 00:00:00 2001 From: Timothy Nunn Date: Wed, 17 Jun 2026 15:11:27 +0100 Subject: [PATCH 1/3] Move data structure to its own class --- process/core/caller.py | 2 +- process/core/data_structure.py | 87 +++++++++++++++++ process/core/init.py | 2 +- process/core/input.py | 2 +- process/core/io/mfile/base.py | 2 +- process/core/io/vary_run/config.py | 2 +- process/core/model.py | 94 +------------------ process/core/scan.py | 3 +- process/core/solver/constraints.py | 8 +- process/core/solver/evaluators.py | 2 +- process/core/solver/iteration_variables.py | 2 +- process/core/solver/objectives.py | 2 +- process/core/solver/solver.py | 2 +- process/main.py | 3 +- process/models/pfcoil.py | 3 +- process/models/physics/fusion_reactions.py | 2 +- process/models/physics/impurity_radiation.py | 1 + process/models/physics/radiation_power.py | 2 +- process/models/stellarator/build.py | 2 +- process/models/stellarator/coils/calculate.py | 2 +- process/models/stellarator/coils/coils.py | 2 +- process/models/stellarator/coils/forces.py | 2 +- process/models/stellarator/coils/mass.py | 2 +- process/models/stellarator/coils/quench.py | 2 +- process/models/stellarator/divertor.py | 2 +- process/models/stellarator/heating.py | 2 +- process/models/stellarator/initialization.py | 8 +- process/models/stellarator/preset_config.py | 2 +- process/models/tfcoil/base.py | 6 +- process/models/tfcoil/superconducting.py | 2 +- tests/conftest.py | 2 +- tests/integration/test_vmcon.py | 2 +- tests/unit/core/test_constraints.py | 2 +- tests/unit/core/test_data_structure.py | 2 +- tests/unit/core/test_input.py | 2 +- tests/unit/core/test_mfile.py | 2 +- tests/unit/test_main.py | 2 +- 37 files changed, 145 insertions(+), 124 deletions(-) create mode 100644 process/core/data_structure.py diff --git a/process/core/caller.py b/process/core/caller.py index 2388366429..6408e41fb8 100644 --- a/process/core/caller.py +++ b/process/core/caller.py @@ -22,7 +22,7 @@ from process.models.tfcoil.superconducting import SuperconductingTFTurnType if TYPE_CHECKING: - from process.core.model import DataStructure + from process.core.data_structure import DataStructure from process.main import Models logger = logging.getLogger(__name__) diff --git a/process/core/data_structure.py b/process/core/data_structure.py new file mode 100644 index 0000000000..f8223fed58 --- /dev/null +++ b/process/core/data_structure.py @@ -0,0 +1,87 @@ +from dataclasses import dataclass, fields + +from process.data_structure.blanket_variables import BlanketData +from process.data_structure.build_variables import BuildData +from process.data_structure.buildings_variables import BuildingsData +from process.data_structure.ccfe_hcpb_variables import CCFEHCPBData +from process.data_structure.constraint_variables import ConstraintData +from process.data_structure.cost_2015_variables import Cost2015Data +from process.data_structure.cost_variables import CostData +from process.data_structure.cs_fatigue_variables import CSFatigueData +from process.data_structure.current_drive_variables import CurrentDriveData +from process.data_structure.dcll_variables import DCLLData +from process.data_structure.divertor_variables import DivertorData +from process.data_structure.first_wall_variables import FirstWallData +from process.data_structure.fwbs_variables import FWBSData +from process.data_structure.global_variables import GlobalData +from process.data_structure.heat_transport_variables import HeatTransportData +from process.data_structure.ife_variables import IFEData +from process.data_structure.impurity_radiation_variables import ImpurityRadiationData +from process.data_structure.neoclassics_variables import NeoclassicsData +from process.data_structure.numerics import NumericsData +from process.data_structure.pf_power_variables import PFPowerData +from process.data_structure.pfcoil_variables import PFCoilData +from process.data_structure.physics_variables import PhysicsData +from process.data_structure.power_variables import PowerData +from process.data_structure.primary_pumping_variables import PrimaryPumpingData +from process.data_structure.pulse_variables import PulseData +from process.data_structure.rebco_variables import RebcoData +from process.data_structure.reinke_variables import ReinkeData +from process.data_structure.scan_variables import ScanData +from process.data_structure.stellarator_configuration import StellaratorConfigData +from process.data_structure.stellarator_variables import StellaratorData +from process.data_structure.structure_variables import StructureData +from process.data_structure.superconducting_tf_coil_variables import ( + SuperconductingTFData, +) +from process.data_structure.tfcoil_variables import TFData +from process.data_structure.times_variables import TimesData +from process.data_structure.vacuum_variables import VacuumData +from process.data_structure.water_usage_variables import WaterUseData + +initialise_later = object() + + +@dataclass(kw_only=True) +class DataStructure: + water_use: WaterUseData = initialise_later + costs_2015: Cost2015Data = initialise_later + cs_fatigue: CSFatigueData = initialise_later + vacuum: VacuumData = initialise_later + costs: CostData = initialise_later + first_wall: FirstWallData = initialise_later + fwbs: FWBSData = initialise_later + blanket: BlanketData = initialise_later + structure: StructureData = initialise_later + times: TimesData = initialise_later + reinke: ReinkeData = initialise_later + ccfe_hcpb: CCFEHCPBData = initialise_later + pulse: PulseData = initialise_later + build: BuildData = initialise_later + primary_pumping: PrimaryPumpingData = initialise_later + buildings: BuildingsData = initialise_later + constraints: ConstraintData = initialise_later + dcll: DCLLData = initialise_later + current_drive: CurrentDriveData = initialise_later + heat_transport: HeatTransportData = initialise_later + ife: IFEData = initialise_later + divertor: DivertorData = initialise_later + pf_coil: PFCoilData = initialise_later + power: PowerData = initialise_later + stellarator: StellaratorData = initialise_later + stellarator_config: StellaratorConfigData = initialise_later + pf_power: PFPowerData = initialise_later + neoclassics: NeoclassicsData = initialise_later + impurity_radiation: ImpurityRadiationData = initialise_later + physics: PhysicsData = initialise_later + rebco: RebcoData = initialise_later + tfcoil: TFData = initialise_later + superconducting_tfcoil: SuperconductingTFData = initialise_later + globals: GlobalData = initialise_later + scan: ScanData = initialise_later + numerics: NumericsData = initialise_later + + def __post_init__(self): + for f in fields(self): + if getattr(self, f.name) is initialise_later: + setattr(self, f.name, f.type()) diff --git a/process/core/init.py b/process/core/init.py index 8a77a2764c..88e743fd34 100644 --- a/process/core/init.py +++ b/process/core/init.py @@ -49,7 +49,7 @@ logger = logging.getLogger(__name__) if TYPE_CHECKING: - from process.core.model import DataStructure + from process.core.data_structure import DataStructure def init_process(data: DataStructure): diff --git a/process/core/input.py b/process/core/input.py index fb282b26ec..1e867cbf4b 100644 --- a/process/core/input.py +++ b/process/core/input.py @@ -23,7 +23,7 @@ if TYPE_CHECKING: from collections.abc import Callable - from process.core.model import DataStructure + from process.core.data_structure import DataStructure NumberType = int | float ValidInputTypes = NumberType | str diff --git a/process/core/io/mfile/base.py b/process/core/io/mfile/base.py index 51aa59fd22..dd65ed994f 100644 --- a/process/core/io/mfile/base.py +++ b/process/core/io/mfile/base.py @@ -13,7 +13,7 @@ import numpy as np -from process.core.model import DataStructure +from process.core.data_structure import DataStructure from process.core.solver import iteration_variables logger = logging.getLogger(__name__) diff --git a/process/core/io/vary_run/config.py b/process/core/io/vary_run/config.py index 5e3fd107ed..9f21a3ce49 100644 --- a/process/core/io/vary_run/config.py +++ b/process/core/io/vary_run/config.py @@ -13,6 +13,7 @@ import click from numpy.random import default_rng +from process.core.data_structure import DataStructure from process.core.io.in_dat import InDat from process.core.io.mfile import MFile from process.core.io.vary_run.tools import ( @@ -25,7 +26,6 @@ process_warnings, set_variable_in_indat, ) -from process.core.model import DataStructure from process.data_structure.numerics import SolverOutputCondition logger = logging.getLogger(__name__) diff --git a/process/core/model.py b/process/core/model.py index ba564d244f..857e032688 100644 --- a/process/core/model.py +++ b/process/core/model.py @@ -1,96 +1,12 @@ """Module containing routines to set up the data structure and models""" -import abc -from dataclasses import dataclass, fields - -from process.data_structure.blanket_variables import BlanketData -from process.data_structure.build_variables import BuildData -from process.data_structure.buildings_variables import BuildingsData -from process.data_structure.ccfe_hcpb_variables import CCFEHCPBData -from process.data_structure.constraint_variables import ConstraintData -from process.data_structure.cost_2015_variables import Cost2015Data -from process.data_structure.cost_variables import CostData -from process.data_structure.cs_fatigue_variables import CSFatigueData -from process.data_structure.current_drive_variables import CurrentDriveData -from process.data_structure.dcll_variables import DCLLData -from process.data_structure.divertor_variables import DivertorData -from process.data_structure.first_wall_variables import FirstWallData -from process.data_structure.fwbs_variables import FWBSData -from process.data_structure.global_variables import GlobalData -from process.data_structure.heat_transport_variables import HeatTransportData -from process.data_structure.ife_variables import IFEData -from process.data_structure.impurity_radiation_variables import ImpurityRadiationData -from process.data_structure.neoclassics_variables import NeoclassicsData -from process.data_structure.numerics import NumericsData -from process.data_structure.pf_power_variables import PFPowerData -from process.data_structure.pfcoil_variables import PFCoilData -from process.data_structure.physics_variables import PhysicsData -from process.data_structure.power_variables import PowerData -from process.data_structure.primary_pumping_variables import PrimaryPumpingData -from process.data_structure.pulse_variables import PulseData -from process.data_structure.rebco_variables import RebcoData -from process.data_structure.reinke_variables import ReinkeData -from process.data_structure.scan_variables import ScanData -from process.data_structure.stellarator_configuration import StellaratorConfigData -from process.data_structure.stellarator_variables import StellaratorData -from process.data_structure.structure_variables import StructureData -from process.data_structure.superconducting_tf_coil_variables import ( - SuperconductingTFData, -) -from process.data_structure.tfcoil_variables import TFData -from process.data_structure.times_variables import TimesData -from process.data_structure.vacuum_variables import VacuumData -from process.data_structure.water_usage_variables import WaterUseData - -initialise_later = object() +from __future__ import annotations +import abc +from typing import TYPE_CHECKING -@dataclass(kw_only=True) -class DataStructure: - """Dataclass holding the data structure""" - - water_use: WaterUseData = initialise_later - costs_2015: Cost2015Data = initialise_later - cs_fatigue: CSFatigueData = initialise_later - vacuum: VacuumData = initialise_later - costs: CostData = initialise_later - first_wall: FirstWallData = initialise_later - fwbs: FWBSData = initialise_later - blanket: BlanketData = initialise_later - structure: StructureData = initialise_later - times: TimesData = initialise_later - reinke: ReinkeData = initialise_later - ccfe_hcpb: CCFEHCPBData = initialise_later - pulse: PulseData = initialise_later - build: BuildData = initialise_later - primary_pumping: PrimaryPumpingData = initialise_later - buildings: BuildingsData = initialise_later - constraints: ConstraintData = initialise_later - dcll: DCLLData = initialise_later - current_drive: CurrentDriveData = initialise_later - heat_transport: HeatTransportData = initialise_later - ife: IFEData = initialise_later - divertor: DivertorData = initialise_later - pf_coil: PFCoilData = initialise_later - power: PowerData = initialise_later - stellarator: StellaratorData = initialise_later - stellarator_config: StellaratorConfigData = initialise_later - pf_power: PFPowerData = initialise_later - neoclassics: NeoclassicsData = initialise_later - impurity_radiation: ImpurityRadiationData = initialise_later - physics: PhysicsData = initialise_later - rebco: RebcoData = initialise_later - tfcoil: TFData = initialise_later - superconducting_tfcoil: SuperconductingTFData = initialise_later - globals: GlobalData = initialise_later - scan: ScanData = initialise_later - numerics: NumericsData = initialise_later - - def __post_init__(self): - """Set up the data structure""" - for f in fields(self): - if getattr(self, f.name) is initialise_later: - setattr(self, f.name, f.type()) +if TYPE_CHECKING: + from process.core.data_structure import DataStructure class Model(abc.ABC): diff --git a/process/core/scan.py b/process/core/scan.py index f7fa304e8e..f6bec70a59 100644 --- a/process/core/scan.py +++ b/process/core/scan.py @@ -22,7 +22,8 @@ from process.models.availability import AvailabilityModel if TYPE_CHECKING: - from process.core.model import DataStructure, Model + from process.core.data_structure import DataStructure + from process.core.model import Model logger = logging.getLogger(__name__) diff --git a/process/core/solver/constraints.py b/process/core/solver/constraints.py index b2ad83e0f4..60dcd3c953 100644 --- a/process/core/solver/constraints.py +++ b/process/core/solver/constraints.py @@ -9,8 +9,8 @@ from tabulate import tabulate from process.core import constants, process_output +from process.core.data_structure import DataStructure from process.core.exceptions import ProcessError, ProcessValueError -from process.core.model import DataStructure from process.data_structure.build_variables import TFCSRadialConfiguration from process.data_structure.stellarator_variables import StellaratorModel from process.models.physics.density_limit import DensityLimitModel @@ -2112,7 +2112,11 @@ def constraints_output(data: DataStructure, solver_name: str): f"(ineq_symbol_con{nums.icc[i]:03d})", f"'{constraint.symbol}'", ), - ("units", f"(ineq_units_con{nums.icc[i]:03d})", f"'{constraint.units}'"), + ( + "units", + f"(ineq_units_con{nums.icc[i]:03d})", + f"'{constraint.units}'", + ), ( "physical bound", f"(ineq_bound_con{nums.icc[i]:03d})", diff --git a/process/core/solver/evaluators.py b/process/core/solver/evaluators.py index 9a672e1884..57ce6bf898 100644 --- a/process/core/solver/evaluators.py +++ b/process/core/solver/evaluators.py @@ -6,7 +6,7 @@ import numpy as np from process.core.caller import Caller -from process.core.model import DataStructure +from process.core.data_structure import DataStructure logger = logging.getLogger(__name__) diff --git a/process/core/solver/iteration_variables.py b/process/core/solver/iteration_variables.py index d1df7c6feb..c02b5be484 100644 --- a/process/core/solver/iteration_variables.py +++ b/process/core/solver/iteration_variables.py @@ -12,7 +12,7 @@ from process.core.exceptions import ProcessValueError if TYPE_CHECKING: - from process.core.model import DataStructure + from process.core.data_structure import DataStructure logger = logging.getLogger(__name__) diff --git a/process/core/solver/objectives.py b/process/core/solver/objectives.py index bd99f5664c..b5238ebadb 100644 --- a/process/core/solver/objectives.py +++ b/process/core/solver/objectives.py @@ -2,8 +2,8 @@ import numpy as np +from process.core.data_structure import DataStructure from process.core.exceptions import ProcessValueError -from process.core.model import DataStructure from process.data_structure.numerics import FiguresOfMerit from process.models.availability import AvailabilityModel diff --git a/process/core/solver/solver.py b/process/core/solver/solver.py index 25fbd624bf..cea078e3bd 100644 --- a/process/core/solver/solver.py +++ b/process/core/solver/solver.py @@ -17,8 +17,8 @@ from scipy.optimize import fsolve from process.core import constants, process_output +from process.core.data_structure import DataStructure from process.core.exceptions import ProcessValueError -from process.core.model import DataStructure from process.core.solver.evaluators import Evaluators from process.data_structure.numerics import SolverOutputCondition diff --git a/process/main.py b/process/main.py index 2f8041c5ee..0cfec01a85 100644 --- a/process/main.py +++ b/process/main.py @@ -39,13 +39,14 @@ import process # noqa: F401 from process.core import constants, init +from process.core.data_structure import DataStructure from process.core.io import obsolete_vars as ov from process.core.io.cli_tools import LazyGroup, help_opt, indat_opt from process.core.io.mfile import MFile from process.core.io.plot import plot_sankey_plotly, plot_summary from process.core.io.vary_run import RunProcessConfig, vary_iteration_variables from process.core.log import logging_model_handler, show_errors -from process.core.model import DataStructure, Model +from process.core.model import Model from process.core.process_output import OutputFileManager, oheadr from process.core.scan import Scan from process.data_structure.blanket_variables import BlktModelTypes diff --git a/process/models/pfcoil.py b/process/models/pfcoil.py index 3ffe918a86..6c7c2fa7bf 100644 --- a/process/models/pfcoil.py +++ b/process/models/pfcoil.py @@ -14,8 +14,9 @@ from process.core import constants from process.core import process_output as op +from process.core.data_structure import DataStructure from process.core.exceptions import ProcessValueError -from process.core.model import DataStructure, Model +from process.core.model import Model from process.data_structure.pfcoil_variables import ( N_PF_COILS_IN_GROUP_MAX, N_PF_GROUPS_MAX, diff --git a/process/models/physics/fusion_reactions.py b/process/models/physics/fusion_reactions.py index 53d44266ff..59b506c005 100644 --- a/process/models/physics/fusion_reactions.py +++ b/process/models/physics/fusion_reactions.py @@ -7,7 +7,7 @@ from scipy import integrate from process.core import constants -from process.core.model import DataStructure +from process.core.data_structure import DataStructure from process.data_structure.physics_variables import PhysicsData from process.models.physics.plasma_profiles import PlasmaProfile diff --git a/process/models/physics/impurity_radiation.py b/process/models/physics/impurity_radiation.py index 4cbef27782..396d6c1d6f 100644 --- a/process/models/physics/impurity_radiation.py +++ b/process/models/physics/impurity_radiation.py @@ -13,6 +13,7 @@ from scipy import integrate from process.core import constants +from process.core.data_structure import DataStructure from process.core.exceptions import ProcessError, ProcessValueError from process.data_structure.impurity_radiation_variables import ( N_IMPURITIY_LOSS_FUNCTION_POINTS, diff --git a/process/models/physics/radiation_power.py b/process/models/physics/radiation_power.py index 0b19e1451b..7d779b2dcb 100644 --- a/process/models/physics/radiation_power.py +++ b/process/models/physics/radiation_power.py @@ -10,7 +10,7 @@ import numpy as np import process.models.physics.impurity_radiation as impurity -from process.core.model import DataStructure +from process.core.data_structure import DataStructure from process.models.physics.plasma_profiles import PlasmaProfile logger = logging.getLogger(__name__) diff --git a/process/models/stellarator/build.py b/process/models/stellarator/build.py index eb43d88bd3..bf53183f21 100644 --- a/process/models/stellarator/build.py +++ b/process/models/stellarator/build.py @@ -1,7 +1,7 @@ """Module containing stellarator build routines""" from process.core import process_output as po -from process.core.model import DataStructure +from process.core.data_structure import DataStructure def st_build(stellarator, f_output: bool, data: DataStructure): diff --git a/process/models/stellarator/coils/calculate.py b/process/models/stellarator/coils/calculate.py index bb273f81c3..acb864e04e 100644 --- a/process/models/stellarator/coils/calculate.py +++ b/process/models/stellarator/coils/calculate.py @@ -4,7 +4,7 @@ import numpy as np -from process.core.model import DataStructure +from process.core.data_structure import DataStructure from process.models.stellarator.coils import forces from process.models.stellarator.coils.coils import ( bmax_from_awp, diff --git a/process/models/stellarator/coils/coils.py b/process/models/stellarator/coils/coils.py index fd927eaf6b..23c1240167 100644 --- a/process/models/stellarator/coils/coils.py +++ b/process/models/stellarator/coils/coils.py @@ -4,8 +4,8 @@ import numpy as np +from process.core.data_structure import DataStructure from process.core.exceptions import ProcessValueError -from process.core.model import DataStructure from process.models import superconductors from process.models.superconductors import SuperconductorModel diff --git a/process/models/stellarator/coils/forces.py b/process/models/stellarator/coils/forces.py index 8233100061..3fb77dfd8b 100644 --- a/process/models/stellarator/coils/forces.py +++ b/process/models/stellarator/coils/forces.py @@ -1,6 +1,6 @@ """Module for coil force calculations in stellarators.""" -from process.core.model import DataStructure +from process.core.data_structure import DataStructure def calculate_max_force_density(a_tf_wp_no_insulation, data: DataStructure): diff --git a/process/models/stellarator/coils/mass.py b/process/models/stellarator/coils/mass.py index bd9e486a73..dc23a5a349 100644 --- a/process/models/stellarator/coils/mass.py +++ b/process/models/stellarator/coils/mass.py @@ -1,7 +1,7 @@ """Module for coil mass calculations in stellarators.""" from process.core import constants -from process.core.model import DataStructure +from process.core.data_structure import DataStructure def calculate_coils_mass( diff --git a/process/models/stellarator/coils/quench.py b/process/models/stellarator/coils/quench.py index 0b32009bc3..8469eb35d4 100644 --- a/process/models/stellarator/coils/quench.py +++ b/process/models/stellarator/coils/quench.py @@ -2,7 +2,7 @@ import numpy as np -from process.core.model import DataStructure +from process.core.data_structure import DataStructure def calculate_quench_protection(coilcurrent, data: DataStructure): diff --git a/process/models/stellarator/divertor.py b/process/models/stellarator/divertor.py index ae1047f4db..729d5e93ad 100644 --- a/process/models/stellarator/divertor.py +++ b/process/models/stellarator/divertor.py @@ -4,7 +4,7 @@ from process.core import constants from process.core import process_output as po -from process.core.model import DataStructure +from process.core.data_structure import DataStructure def st_div(stellarator, f_output: bool, data: DataStructure): diff --git a/process/models/stellarator/heating.py b/process/models/stellarator/heating.py index b81e930973..adc15f692b 100644 --- a/process/models/stellarator/heating.py +++ b/process/models/stellarator/heating.py @@ -3,8 +3,8 @@ import logging from process.core import process_output as po +from process.core.data_structure import DataStructure from process.core.exceptions import ProcessValueError -from process.core.model import DataStructure from process.data_structure.physics_variables import PlasmaIgnitionModel logger = logging.getLogger(__name__) diff --git a/process/models/stellarator/initialization.py b/process/models/stellarator/initialization.py index b5eb2ec67a..b0a7af71ca 100644 --- a/process/models/stellarator/initialization.py +++ b/process/models/stellarator/initialization.py @@ -1,8 +1,14 @@ """Module to initialise variables relevant to stellarators.""" -from process.core.model import DataStructure +from __future__ import annotations + +from typing import TYPE_CHECKING + from process.data_structure.stellarator_variables import StellaratorModel +if TYPE_CHECKING: + from process.core.data_structure import DataStructure + def st_init(data: DataStructure): """Routine to initialise the variables relevant to stellarators diff --git a/process/models/stellarator/preset_config.py b/process/models/stellarator/preset_config.py index 6a75ac4178..51362ccf2d 100644 --- a/process/models/stellarator/preset_config.py +++ b/process/models/stellarator/preset_config.py @@ -3,8 +3,8 @@ import json from pathlib import Path +from process.core.data_structure import DataStructure from process.core.exceptions import ProcessValueError -from process.core.model import DataStructure HELIAS5B = { "name": "Helias 5b", diff --git a/process/models/tfcoil/base.py b/process/models/tfcoil/base.py index ce106eee3b..bc58a71d8a 100644 --- a/process/models/tfcoil/base.py +++ b/process/models/tfcoil/base.py @@ -8,6 +8,7 @@ from dataclasses import dataclass from enum import IntEnum, unique from types import DynamicClassAttribute +from typing import TYPE_CHECKING import numba import numpy as np @@ -15,7 +16,7 @@ from process.core import constants from process.core import process_output as po from process.core.exceptions import ProcessValueError -from process.core.model import DataStructure, Model +from process.core.model import Model from process.data_structure.build_variables import TFCSRadialConfiguration from process.data_structure.pfcoil_variables import PFConductorModel from process.data_structure.physics_variables import DivertorNumberModels @@ -25,6 +26,9 @@ calculate_von_mises_stress, ) +if TYPE_CHECKING: + from process.core.data_structure import DataStructure + logger = logging.getLogger(__name__) diff --git a/process/models/tfcoil/superconducting.py b/process/models/tfcoil/superconducting.py index 4bc42890d6..6d9c755be8 100644 --- a/process/models/tfcoil/superconducting.py +++ b/process/models/tfcoil/superconducting.py @@ -10,8 +10,8 @@ from process.core import constants from process.core import process_output as po +from process.core.data_structure import DataStructure from process.core.exceptions import ProcessValueError -from process.core.model import DataStructure from process.data_structure.superconducting_tf_coil_variables import TFWPIntegerTurnType from process.models import superconductors from process.models.superconductors import ( diff --git a/tests/conftest.py b/tests/conftest.py index 9805a844d1..d59beba96b 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -14,8 +14,8 @@ from system_check import system_compatible from process import main +from process.core.data_structure import DataStructure from process.core.log import logging_model_handler -from process.core.model import DataStructure from process.main import Models diff --git a/tests/integration/test_vmcon.py b/tests/integration/test_vmcon.py index 81eceac1d3..adb9272f58 100644 --- a/tests/integration/test_vmcon.py +++ b/tests/integration/test_vmcon.py @@ -12,7 +12,7 @@ import numpy as np import pytest -from process.core.model import DataStructure +from process.core.data_structure import DataStructure from process.core.solver.evaluators import Evaluators from process.core.solver.solver import get_solver from process.data_structure.numerics import SolverOutputCondition diff --git a/tests/unit/core/test_constraints.py b/tests/unit/core/test_constraints.py index 9c66703157..b19dedec8d 100644 --- a/tests/unit/core/test_constraints.py +++ b/tests/unit/core/test_constraints.py @@ -2,8 +2,8 @@ import pytest +from process.core.data_structure import DataStructure from process.core.exceptions import ProcessValueError -from process.core.model import DataStructure from process.core.solver.constraints import ConstraintManager diff --git a/tests/unit/core/test_data_structure.py b/tests/unit/core/test_data_structure.py index 62702bd26c..8072dec2d0 100644 --- a/tests/unit/core/test_data_structure.py +++ b/tests/unit/core/test_data_structure.py @@ -2,7 +2,7 @@ import pytest -from process.core.model import DataStructure +from process.core.data_structure import DataStructure DATA_STRUCTURES = {f.name: f.type() for f in fields(DataStructure)} diff --git a/tests/unit/core/test_input.py b/tests/unit/core/test_input.py index 65cb364b80..7deb6b1eda 100644 --- a/tests/unit/core/test_input.py +++ b/tests/unit/core/test_input.py @@ -5,8 +5,8 @@ import process.core.input as process_input from process.core import init +from process.core.data_structure import DataStructure from process.core.exceptions import ProcessValidationError -from process.core.model import DataStructure from process.data_structure.numerics import PROCESSRunMode diff --git a/tests/unit/core/test_mfile.py b/tests/unit/core/test_mfile.py index 019317d0ef..b3f0c50b93 100644 --- a/tests/unit/core/test_mfile.py +++ b/tests/unit/core/test_mfile.py @@ -5,8 +5,8 @@ import pytest +from process.core.data_structure import DataStructure from process.core.io.mfile import MFile, get_mfile_initial_ixc_values -from process.core.model import DataStructure @pytest.fixture diff --git a/tests/unit/test_main.py b/tests/unit/test_main.py index bca24cbc1c..0828a08315 100644 --- a/tests/unit/test_main.py +++ b/tests/unit/test_main.py @@ -5,7 +5,7 @@ import pytest -from process.core.model import DataStructure +from process.core.data_structure import DataStructure from process.main import SingleRun, VaryRun From 7b9a565643b04dad6297f978eca4cf5450f93f51 Mon Sep 17 00:00:00 2001 From: Timothy Nunn Date: Tue, 25 Aug 2026 17:29:29 +0100 Subject: [PATCH 2/3] Fix pre-commit failures --- process/core/data_structure.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/process/core/data_structure.py b/process/core/data_structure.py index f8223fed58..a62df8a85c 100644 --- a/process/core/data_structure.py +++ b/process/core/data_structure.py @@ -1,3 +1,5 @@ +"""The PROCESS data structure dataclass.""" + from dataclasses import dataclass, fields from process.data_structure.blanket_variables import BlanketData @@ -44,6 +46,8 @@ @dataclass(kw_only=True) class DataStructure: + """Dataclass holding the data structure""" + water_use: WaterUseData = initialise_later costs_2015: Cost2015Data = initialise_later cs_fatigue: CSFatigueData = initialise_later @@ -82,6 +86,7 @@ class DataStructure: numerics: NumericsData = initialise_later def __post_init__(self): + """Set up the data structure""" for f in fields(self): if getattr(self, f.name) is initialise_later: setattr(self, f.name, f.type()) From 91d38f9e9189063b467d2c1606804ad0051755a4 Mon Sep 17 00:00:00 2001 From: Timothy Nunn Date: Wed, 26 Aug 2026 14:40:44 +0100 Subject: [PATCH 3/3] Create data_structure submodule in core --- process/core/caller.py | 2 +- process/core/data_structure/__init__.py | 1 + .../core/{data_structure.py => data_structure/base.py} | 0 process/core/init.py | 2 +- process/core/input.py | 2 +- process/core/io/mfile/base.py | 2 +- process/core/io/vary_run/config.py | 2 +- process/core/model.py | 2 +- process/core/scan.py | 2 +- process/core/solver/constraints.py | 2 +- process/core/solver/evaluators.py | 2 +- process/core/solver/iteration_variables.py | 2 +- process/core/solver/objectives.py | 2 +- process/core/solver/solver.py | 2 +- process/main.py | 2 +- process/models/pfcoil.py | 2 +- process/models/physics/fusion_reactions.py | 2 +- process/models/physics/impurity_radiation.py | 2 +- process/models/physics/radiation_power.py | 2 +- process/models/stellarator/build.py | 2 +- process/models/stellarator/coils/calculate.py | 2 +- process/models/stellarator/coils/coils.py | 9 +++++++-- process/models/stellarator/coils/forces.py | 2 +- process/models/stellarator/coils/mass.py | 2 +- process/models/stellarator/coils/quench.py | 2 +- process/models/stellarator/divertor.py | 2 +- process/models/stellarator/heating.py | 2 +- process/models/stellarator/initialization.py | 2 +- process/models/stellarator/preset_config.py | 2 +- process/models/tfcoil/base.py | 2 +- process/models/tfcoil/superconducting.py | 2 +- tests/conftest.py | 2 +- tests/integration/test_vmcon.py | 2 +- tests/unit/core/test_constraints.py | 2 +- tests/unit/core/test_data_structure.py | 2 +- tests/unit/core/test_input.py | 2 +- tests/unit/core/test_mfile.py | 2 +- tests/unit/test_main.py | 2 +- 38 files changed, 43 insertions(+), 37 deletions(-) create mode 100644 process/core/data_structure/__init__.py rename process/core/{data_structure.py => data_structure/base.py} (100%) diff --git a/process/core/caller.py b/process/core/caller.py index 6408e41fb8..dc743b0d45 100644 --- a/process/core/caller.py +++ b/process/core/caller.py @@ -22,7 +22,7 @@ from process.models.tfcoil.superconducting import SuperconductingTFTurnType if TYPE_CHECKING: - from process.core.data_structure import DataStructure + from process.core.data_structure.base import DataStructure from process.main import Models logger = logging.getLogger(__name__) diff --git a/process/core/data_structure/__init__.py b/process/core/data_structure/__init__.py new file mode 100644 index 0000000000..7f1e566f13 --- /dev/null +++ b/process/core/data_structure/__init__.py @@ -0,0 +1 @@ +"""Contains classes related to the PROCESS data structure.""" diff --git a/process/core/data_structure.py b/process/core/data_structure/base.py similarity index 100% rename from process/core/data_structure.py rename to process/core/data_structure/base.py diff --git a/process/core/init.py b/process/core/init.py index 88e743fd34..f4567df36c 100644 --- a/process/core/init.py +++ b/process/core/init.py @@ -49,7 +49,7 @@ logger = logging.getLogger(__name__) if TYPE_CHECKING: - from process.core.data_structure import DataStructure + from process.core.data_structure.base import DataStructure def init_process(data: DataStructure): diff --git a/process/core/input.py b/process/core/input.py index 1e867cbf4b..98d2ce0f09 100644 --- a/process/core/input.py +++ b/process/core/input.py @@ -23,7 +23,7 @@ if TYPE_CHECKING: from collections.abc import Callable - from process.core.data_structure import DataStructure + from process.core.data_structure.base import DataStructure NumberType = int | float ValidInputTypes = NumberType | str diff --git a/process/core/io/mfile/base.py b/process/core/io/mfile/base.py index dd65ed994f..b2935d5c69 100644 --- a/process/core/io/mfile/base.py +++ b/process/core/io/mfile/base.py @@ -13,7 +13,7 @@ import numpy as np -from process.core.data_structure import DataStructure +from process.core.data_structure.base import DataStructure from process.core.solver import iteration_variables logger = logging.getLogger(__name__) diff --git a/process/core/io/vary_run/config.py b/process/core/io/vary_run/config.py index 9f21a3ce49..3279eae43f 100644 --- a/process/core/io/vary_run/config.py +++ b/process/core/io/vary_run/config.py @@ -13,7 +13,7 @@ import click from numpy.random import default_rng -from process.core.data_structure import DataStructure +from process.core.data_structure.base import DataStructure from process.core.io.in_dat import InDat from process.core.io.mfile import MFile from process.core.io.vary_run.tools import ( diff --git a/process/core/model.py b/process/core/model.py index 857e032688..f7365ce970 100644 --- a/process/core/model.py +++ b/process/core/model.py @@ -6,7 +6,7 @@ from typing import TYPE_CHECKING if TYPE_CHECKING: - from process.core.data_structure import DataStructure + from process.core.data_structure.base import DataStructure class Model(abc.ABC): diff --git a/process/core/scan.py b/process/core/scan.py index f6bec70a59..6c974a1a12 100644 --- a/process/core/scan.py +++ b/process/core/scan.py @@ -22,7 +22,7 @@ from process.models.availability import AvailabilityModel if TYPE_CHECKING: - from process.core.data_structure import DataStructure + from process.core.data_structure.base import DataStructure from process.core.model import Model diff --git a/process/core/solver/constraints.py b/process/core/solver/constraints.py index 60dcd3c953..c224110cde 100644 --- a/process/core/solver/constraints.py +++ b/process/core/solver/constraints.py @@ -9,7 +9,7 @@ from tabulate import tabulate from process.core import constants, process_output -from process.core.data_structure import DataStructure +from process.core.data_structure.base import DataStructure from process.core.exceptions import ProcessError, ProcessValueError from process.data_structure.build_variables import TFCSRadialConfiguration from process.data_structure.stellarator_variables import StellaratorModel diff --git a/process/core/solver/evaluators.py b/process/core/solver/evaluators.py index 57ce6bf898..2faa8f56ad 100644 --- a/process/core/solver/evaluators.py +++ b/process/core/solver/evaluators.py @@ -6,7 +6,7 @@ import numpy as np from process.core.caller import Caller -from process.core.data_structure import DataStructure +from process.core.data_structure.base import DataStructure logger = logging.getLogger(__name__) diff --git a/process/core/solver/iteration_variables.py b/process/core/solver/iteration_variables.py index c02b5be484..a284998ac5 100644 --- a/process/core/solver/iteration_variables.py +++ b/process/core/solver/iteration_variables.py @@ -12,7 +12,7 @@ from process.core.exceptions import ProcessValueError if TYPE_CHECKING: - from process.core.data_structure import DataStructure + from process.core.data_structure.base import DataStructure logger = logging.getLogger(__name__) diff --git a/process/core/solver/objectives.py b/process/core/solver/objectives.py index b5238ebadb..5536b1fd15 100644 --- a/process/core/solver/objectives.py +++ b/process/core/solver/objectives.py @@ -2,7 +2,7 @@ import numpy as np -from process.core.data_structure import DataStructure +from process.core.data_structure.base import DataStructure from process.core.exceptions import ProcessValueError from process.data_structure.numerics import FiguresOfMerit from process.models.availability import AvailabilityModel diff --git a/process/core/solver/solver.py b/process/core/solver/solver.py index cea078e3bd..9e6f17d99a 100644 --- a/process/core/solver/solver.py +++ b/process/core/solver/solver.py @@ -17,7 +17,7 @@ from scipy.optimize import fsolve from process.core import constants, process_output -from process.core.data_structure import DataStructure +from process.core.data_structure.base import DataStructure from process.core.exceptions import ProcessValueError from process.core.solver.evaluators import Evaluators from process.data_structure.numerics import SolverOutputCondition diff --git a/process/main.py b/process/main.py index 0cfec01a85..ac155c4d68 100644 --- a/process/main.py +++ b/process/main.py @@ -39,7 +39,7 @@ import process # noqa: F401 from process.core import constants, init -from process.core.data_structure import DataStructure +from process.core.data_structure.base import DataStructure from process.core.io import obsolete_vars as ov from process.core.io.cli_tools import LazyGroup, help_opt, indat_opt from process.core.io.mfile import MFile diff --git a/process/models/pfcoil.py b/process/models/pfcoil.py index 6c7c2fa7bf..33f19af83b 100644 --- a/process/models/pfcoil.py +++ b/process/models/pfcoil.py @@ -14,7 +14,7 @@ from process.core import constants from process.core import process_output as op -from process.core.data_structure import DataStructure +from process.core.data_structure.base import DataStructure from process.core.exceptions import ProcessValueError from process.core.model import Model from process.data_structure.pfcoil_variables import ( diff --git a/process/models/physics/fusion_reactions.py b/process/models/physics/fusion_reactions.py index 59b506c005..30b2009ee6 100644 --- a/process/models/physics/fusion_reactions.py +++ b/process/models/physics/fusion_reactions.py @@ -7,7 +7,7 @@ from scipy import integrate from process.core import constants -from process.core.data_structure import DataStructure +from process.core.data_structure.base import DataStructure from process.data_structure.physics_variables import PhysicsData from process.models.physics.plasma_profiles import PlasmaProfile diff --git a/process/models/physics/impurity_radiation.py b/process/models/physics/impurity_radiation.py index 396d6c1d6f..f6b192fbc8 100644 --- a/process/models/physics/impurity_radiation.py +++ b/process/models/physics/impurity_radiation.py @@ -13,7 +13,7 @@ from scipy import integrate from process.core import constants -from process.core.data_structure import DataStructure +from process.core.data_structure.base import DataStructure from process.core.exceptions import ProcessError, ProcessValueError from process.data_structure.impurity_radiation_variables import ( N_IMPURITIY_LOSS_FUNCTION_POINTS, diff --git a/process/models/physics/radiation_power.py b/process/models/physics/radiation_power.py index 7d779b2dcb..0fba6e92d2 100644 --- a/process/models/physics/radiation_power.py +++ b/process/models/physics/radiation_power.py @@ -10,7 +10,7 @@ import numpy as np import process.models.physics.impurity_radiation as impurity -from process.core.data_structure import DataStructure +from process.core.data_structure.base import DataStructure from process.models.physics.plasma_profiles import PlasmaProfile logger = logging.getLogger(__name__) diff --git a/process/models/stellarator/build.py b/process/models/stellarator/build.py index bf53183f21..53937df504 100644 --- a/process/models/stellarator/build.py +++ b/process/models/stellarator/build.py @@ -1,7 +1,7 @@ """Module containing stellarator build routines""" from process.core import process_output as po -from process.core.data_structure import DataStructure +from process.core.data_structure.base import DataStructure def st_build(stellarator, f_output: bool, data: DataStructure): diff --git a/process/models/stellarator/coils/calculate.py b/process/models/stellarator/coils/calculate.py index acb864e04e..05ebb36819 100644 --- a/process/models/stellarator/coils/calculate.py +++ b/process/models/stellarator/coils/calculate.py @@ -4,7 +4,7 @@ import numpy as np -from process.core.data_structure import DataStructure +from process.core.data_structure.base import DataStructure from process.models.stellarator.coils import forces from process.models.stellarator.coils.coils import ( bmax_from_awp, diff --git a/process/models/stellarator/coils/coils.py b/process/models/stellarator/coils/coils.py index 23c1240167..767e93f49a 100644 --- a/process/models/stellarator/coils/coils.py +++ b/process/models/stellarator/coils/coils.py @@ -4,7 +4,7 @@ import numpy as np -from process.core.data_structure import DataStructure +from process.core.data_structure.base import DataStructure from process.core.exceptions import ProcessValueError from process.models import superconductors from process.models.superconductors import SuperconductorModel @@ -282,7 +282,12 @@ def intersect(x1, y1, x2, y2, xin): def bmax_from_awp( - wp_width_radial, current, n_tf_coils, r_coil_major, r_coil_minor, data: DataStructure + wp_width_radial, + current, + n_tf_coils, + r_coil_major, + r_coil_minor, + data: DataStructure, ): """Returns a fitted function for bmax for stellarators diff --git a/process/models/stellarator/coils/forces.py b/process/models/stellarator/coils/forces.py index 3fb77dfd8b..4b45a84a02 100644 --- a/process/models/stellarator/coils/forces.py +++ b/process/models/stellarator/coils/forces.py @@ -1,6 +1,6 @@ """Module for coil force calculations in stellarators.""" -from process.core.data_structure import DataStructure +from process.core.data_structure.base import DataStructure def calculate_max_force_density(a_tf_wp_no_insulation, data: DataStructure): diff --git a/process/models/stellarator/coils/mass.py b/process/models/stellarator/coils/mass.py index dc23a5a349..ca89cdda81 100644 --- a/process/models/stellarator/coils/mass.py +++ b/process/models/stellarator/coils/mass.py @@ -1,7 +1,7 @@ """Module for coil mass calculations in stellarators.""" from process.core import constants -from process.core.data_structure import DataStructure +from process.core.data_structure.base import DataStructure def calculate_coils_mass( diff --git a/process/models/stellarator/coils/quench.py b/process/models/stellarator/coils/quench.py index 8469eb35d4..1b0c1b1667 100644 --- a/process/models/stellarator/coils/quench.py +++ b/process/models/stellarator/coils/quench.py @@ -2,7 +2,7 @@ import numpy as np -from process.core.data_structure import DataStructure +from process.core.data_structure.base import DataStructure def calculate_quench_protection(coilcurrent, data: DataStructure): diff --git a/process/models/stellarator/divertor.py b/process/models/stellarator/divertor.py index 729d5e93ad..282fef927b 100644 --- a/process/models/stellarator/divertor.py +++ b/process/models/stellarator/divertor.py @@ -4,7 +4,7 @@ from process.core import constants from process.core import process_output as po -from process.core.data_structure import DataStructure +from process.core.data_structure.base import DataStructure def st_div(stellarator, f_output: bool, data: DataStructure): diff --git a/process/models/stellarator/heating.py b/process/models/stellarator/heating.py index adc15f692b..5d7d815c98 100644 --- a/process/models/stellarator/heating.py +++ b/process/models/stellarator/heating.py @@ -3,7 +3,7 @@ import logging from process.core import process_output as po -from process.core.data_structure import DataStructure +from process.core.data_structure.base import DataStructure from process.core.exceptions import ProcessValueError from process.data_structure.physics_variables import PlasmaIgnitionModel diff --git a/process/models/stellarator/initialization.py b/process/models/stellarator/initialization.py index b0a7af71ca..2720190ceb 100644 --- a/process/models/stellarator/initialization.py +++ b/process/models/stellarator/initialization.py @@ -7,7 +7,7 @@ from process.data_structure.stellarator_variables import StellaratorModel if TYPE_CHECKING: - from process.core.data_structure import DataStructure + from process.core.data_structure.base import DataStructure def st_init(data: DataStructure): diff --git a/process/models/stellarator/preset_config.py b/process/models/stellarator/preset_config.py index 51362ccf2d..b63ab9c148 100644 --- a/process/models/stellarator/preset_config.py +++ b/process/models/stellarator/preset_config.py @@ -3,7 +3,7 @@ import json from pathlib import Path -from process.core.data_structure import DataStructure +from process.core.data_structure.base import DataStructure from process.core.exceptions import ProcessValueError HELIAS5B = { diff --git a/process/models/tfcoil/base.py b/process/models/tfcoil/base.py index bc58a71d8a..871cad4bba 100644 --- a/process/models/tfcoil/base.py +++ b/process/models/tfcoil/base.py @@ -27,7 +27,7 @@ ) if TYPE_CHECKING: - from process.core.data_structure import DataStructure + from process.core.data_structure.base import DataStructure logger = logging.getLogger(__name__) diff --git a/process/models/tfcoil/superconducting.py b/process/models/tfcoil/superconducting.py index 6d9c755be8..836d28c674 100644 --- a/process/models/tfcoil/superconducting.py +++ b/process/models/tfcoil/superconducting.py @@ -10,7 +10,7 @@ from process.core import constants from process.core import process_output as po -from process.core.data_structure import DataStructure +from process.core.data_structure.base import DataStructure from process.core.exceptions import ProcessValueError from process.data_structure.superconducting_tf_coil_variables import TFWPIntegerTurnType from process.models import superconductors diff --git a/tests/conftest.py b/tests/conftest.py index d59beba96b..f5632734a6 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -14,7 +14,7 @@ from system_check import system_compatible from process import main -from process.core.data_structure import DataStructure +from process.core.data_structure.base import DataStructure from process.core.log import logging_model_handler from process.main import Models diff --git a/tests/integration/test_vmcon.py b/tests/integration/test_vmcon.py index adb9272f58..114a74cc2b 100644 --- a/tests/integration/test_vmcon.py +++ b/tests/integration/test_vmcon.py @@ -12,7 +12,7 @@ import numpy as np import pytest -from process.core.data_structure import DataStructure +from process.core.data_structure.base import DataStructure from process.core.solver.evaluators import Evaluators from process.core.solver.solver import get_solver from process.data_structure.numerics import SolverOutputCondition diff --git a/tests/unit/core/test_constraints.py b/tests/unit/core/test_constraints.py index b19dedec8d..d920130cc0 100644 --- a/tests/unit/core/test_constraints.py +++ b/tests/unit/core/test_constraints.py @@ -2,7 +2,7 @@ import pytest -from process.core.data_structure import DataStructure +from process.core.data_structure.base import DataStructure from process.core.exceptions import ProcessValueError from process.core.solver.constraints import ConstraintManager diff --git a/tests/unit/core/test_data_structure.py b/tests/unit/core/test_data_structure.py index 8072dec2d0..f3e77234ce 100644 --- a/tests/unit/core/test_data_structure.py +++ b/tests/unit/core/test_data_structure.py @@ -2,7 +2,7 @@ import pytest -from process.core.data_structure import DataStructure +from process.core.data_structure.base import DataStructure DATA_STRUCTURES = {f.name: f.type() for f in fields(DataStructure)} diff --git a/tests/unit/core/test_input.py b/tests/unit/core/test_input.py index 7deb6b1eda..9bb4b82303 100644 --- a/tests/unit/core/test_input.py +++ b/tests/unit/core/test_input.py @@ -5,7 +5,7 @@ import process.core.input as process_input from process.core import init -from process.core.data_structure import DataStructure +from process.core.data_structure.base import DataStructure from process.core.exceptions import ProcessValidationError from process.data_structure.numerics import PROCESSRunMode diff --git a/tests/unit/core/test_mfile.py b/tests/unit/core/test_mfile.py index b3f0c50b93..1868af608d 100644 --- a/tests/unit/core/test_mfile.py +++ b/tests/unit/core/test_mfile.py @@ -5,7 +5,7 @@ import pytest -from process.core.data_structure import DataStructure +from process.core.data_structure.base import DataStructure from process.core.io.mfile import MFile, get_mfile_initial_ixc_values diff --git a/tests/unit/test_main.py b/tests/unit/test_main.py index 0828a08315..98de7df22b 100644 --- a/tests/unit/test_main.py +++ b/tests/unit/test_main.py @@ -5,7 +5,7 @@ import pytest -from process.core.data_structure import DataStructure +from process.core.data_structure.base import DataStructure from process.main import SingleRun, VaryRun