From debf7d2af1e4e57ca18195748d57b1212b6c5a62 Mon Sep 17 00:00:00 2001 From: Timothy Nunn Date: Fri, 10 Oct 2025 14:38:17 +0100 Subject: [PATCH 1/4] Implement equality and repr method for INVariable --- process/io/in_dat.py | 15 +++++++++++++++ tests/integration/test_indat.py | 18 ++++++++++++++++++ 2 files changed, 33 insertions(+) create mode 100644 tests/integration/test_indat.py diff --git a/process/io/in_dat.py b/process/io/in_dat.py index f56552ae73..2b5c4dd990 100644 --- a/process/io/in_dat.py +++ b/process/io/in_dat.py @@ -867,6 +867,21 @@ def __init__(self, name, value, v_type, parameter_group, comment): self.parameter_group = parameter_group self.comment = comment + def __eq__(self, value): + # intentionally missing .comment, this is no necessary for the variable to be equal + return ( + self.name == value.name + and self.value == value.value + and self.v_type == value.v_type + and self.parameter_group == value.parameter_group + ) + + def __repr__(self): + return ( + f"{type(self).__name__}(name={self.name!r}, value={self.value!r}, v_type={self.v_type!r}), " + f"parameter_group={self.parameter_group!r}, comment={self.comment!r}" + ) + @property def get_value(self): """Return value in correct format""" diff --git a/tests/integration/test_indat.py b/tests/integration/test_indat.py new file mode 100644 index 0000000000..fd601f852b --- /dev/null +++ b/tests/integration/test_indat.py @@ -0,0 +1,18 @@ +"""Tests for InDat and INVariable classes""" + +import pytest + +from process.io.in_dat import INVariable + + +@pytest.mark.parametrize("value", ["1", "1.0", "1,2,3", "1.0, 2.0", "string"]) +def test_invariable_equality(value): + """A test to check equality between INVariable's""" + name = "test" + v_type = "Parameter" + parameter_group = "test_group" + + v1 = INVariable(name, value, v_type, parameter_group, "") + v2 = INVariable(name, value, v_type, parameter_group, "different comment") + + assert v1 == v2 From 39f79f39b06eb753da5eb7f34e6d6591305e0e88 Mon Sep 17 00:00:00 2001 From: Timothy Nunn Date: Fri, 10 Oct 2025 15:30:45 +0100 Subject: [PATCH 2/4] Add test to check re-written input files are the same as the source --- tests/integration/test_indat.py | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/tests/integration/test_indat.py b/tests/integration/test_indat.py index fd601f852b..7f5303d9eb 100644 --- a/tests/integration/test_indat.py +++ b/tests/integration/test_indat.py @@ -2,7 +2,7 @@ import pytest -from process.io.in_dat import INVariable +from process.io.in_dat import InDat, INVariable @pytest.mark.parametrize("value", ["1", "1.0", "1,2,3", "1.0, 2.0", "string"]) @@ -16,3 +16,12 @@ def test_invariable_equality(value): v2 = INVariable(name, value, v_type, parameter_group, "different comment") assert v1 == v2 + + +def test_rewritten_indat_identical(temp_data_cwd): + indat = InDat(filename=str(temp_data_cwd / "large_tokamak_IN.DAT")) + indat.write_in_dat("new.IN.DAT") + + new_indat = InDat(filename=str(temp_data_cwd / "new.IN.DAT")) + + assert indat.data == new_indat.data From 67dab7edb51973718143ebcd45837f1253dea3b6 Mon Sep 17 00:00:00 2001 From: Timothy Nunn Date: Fri, 10 Oct 2025 15:31:35 +0100 Subject: [PATCH 3/4] Correct get_constraint_equations incorrectly ignoring constraints --- process/io/data_structure_dicts.py | 17 ----------------- process/io/in_dat.py | 21 +++++++++++++-------- 2 files changed, 13 insertions(+), 25 deletions(-) diff --git a/process/io/data_structure_dicts.py b/process/io/data_structure_dicts.py index 0ec1b82248..72fd4f1765 100644 --- a/process/io/data_structure_dicts.py +++ b/process/io/data_structure_dicts.py @@ -248,22 +248,6 @@ def dict_var_type(): return di -def dict_icc_full(): - """Function to return a dictionary matching str(icc_no) to a dictionary - containing the name of that constraint equation. Looks in - numerics.f90 at !+ad_varc lines in lablcc to get icc_no and - variable names. - - Example of a lablxc line we are looking for: - !+ad_varc
  • ( 5) * beta - - Example dictionary entry: - DICT_IXC_FULL['5'] = {'name' : 'beta'} - """ - - return {str(k): {"name": v.name} for k, v in ITERATION_VARIABLES.items()} - - def dict_input_bounds(): """Returns a dictionary matching variable names to dictionary containing upper and lower bounds that PROCESS checks variable lies between when @@ -363,7 +347,6 @@ def get_dicts(): SourceDictionary("DICT_INPUT_BOUNDS", dict_input_bounds), SourceDictionary("DICT_NSWEEP2VARNAME", dict_nsweep2varname), SourceDictionary("DICT_VAR_TYPE", dict_var_type), - SourceDictionary("DICT_ICC_FULL", dict_icc_full), SourceDictionary("DICT_IXC2NSWEEP", dict_ixc2nsweep), SourceDictionary("DICT_NSWEEP2IXC", dict_nsweep2ixc), SourceDictionary("DICT_IXC_FULL", dict_ixc_full), diff --git a/process/io/in_dat.py b/process/io/in_dat.py index 2b5c4dd990..0278c4e778 100644 --- a/process/io/in_dat.py +++ b/process/io/in_dat.py @@ -16,6 +16,8 @@ from re import sub from sys import stderr +from process.constraints import ConstraintManager +from process.exceptions import ProcessValidationError from process.io.data_structure_dicts import get_dicts # ioptimz values @@ -188,20 +190,23 @@ def get_constraint_equations(data): :return: dict of the constraint numbers and their comments :rtype: dict """ - # Load dicts from dicts JSON file - dicts = get_dicts() - constraints = {} # List of constraint equation numbers in IN.DAT - constraint_numbers = data["icc"].value + constraint_numbers = [int(i) for i in data["icc"].value] # Find associated comments and create constraint dict for constraint_number in constraint_numbers: - if str(constraint_number) not in dicts["DICT_ICC_FULL"]: - continue - comment = dicts["DICT_ICC_FULL"][str(constraint_number)]["name"] - constraints[constraint_number] = comment + constraint = ConstraintManager.get_constraint(constraint_number) + + if constraint is None: + raise ProcessValidationError( + f"Constraint equation {constraint_number} requested but has not been registered" + ) + + # TODO: we should store a short description of each constraint that we can use here. + # Currently, no such information exists. + constraints[constraint_number] = "" return constraints From 5859d53433e7cd8d5ca7f577de3e51adbdb9e9cb Mon Sep 17 00:00:00 2001 From: Timothy Nunn Date: Mon, 13 Oct 2025 13:26:45 +0100 Subject: [PATCH 4/4] Correct comments and repr for INVariable --- process/io/in_dat.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/process/io/in_dat.py b/process/io/in_dat.py index 0278c4e778..e1c1daa8cf 100644 --- a/process/io/in_dat.py +++ b/process/io/in_dat.py @@ -873,7 +873,7 @@ def __init__(self, name, value, v_type, parameter_group, comment): self.comment = comment def __eq__(self, value): - # intentionally missing .comment, this is no necessary for the variable to be equal + # intentionally missing .comment, this is not necessary for the variables to be equal return ( self.name == value.name and self.value == value.value @@ -883,8 +883,8 @@ def __eq__(self, value): def __repr__(self): return ( - f"{type(self).__name__}(name={self.name!r}, value={self.value!r}, v_type={self.v_type!r}), " - f"parameter_group={self.parameter_group!r}, comment={self.comment!r}" + f"{type(self).__name__}(name={self.name!r}, value={self.value!r}, v_type={self.v_type!r}, " + f"parameter_group={self.parameter_group!r}, comment={self.comment!r})" ) @property