From f9ca114f238f7cf39f340bfeb5378c5d4995a94d Mon Sep 17 00:00:00 2001 From: Timothy Nunn Date: Wed, 19 Feb 2025 10:03:33 +0000 Subject: [PATCH 1/9] Remove test from input.f90 --- source/fortran/input.f90 | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/source/fortran/input.f90 b/source/fortran/input.f90 index 7c5d11a32a..29b6238731 100644 --- a/source/fortran/input.f90 +++ b/source/fortran/input.f90 @@ -4971,14 +4971,3 @@ subroutine lower_case(string,start,finish) end subroutine lower_case end module process_input - -#ifdef unit_test -program test - use process_input - implicit none - - open(unit=1,file='IN.DAT',status='old') - call parse_input_file(1,6,1) - close(unit=1) -end program test -#endif From 1840f44bc43d8cfe09dbdc154f2e76775e251214 Mon Sep 17 00:00:00 2001 From: Timothy Nunn Date: Wed, 19 Feb 2025 10:18:07 +0000 Subject: [PATCH 2/9] Convert input to Python --- process/init.py | 16 +++++++++++++- source/fortran/input.f90 | 45 +--------------------------------------- 2 files changed, 16 insertions(+), 45 deletions(-) diff --git a/process/init.py b/process/init.py index 1ac7ee85c8..55653ffb6d 100644 --- a/process/init.py +++ b/process/init.py @@ -30,7 +30,13 @@ def init_process(): fortran.init_module.open_files() # Input any desired new initial values - fortran.process_input.input() + fortran.process_input.parse_input_file(10, fortran.constants.nout, 0) + + # Set active constraints + set_active_constraints() + + # set the device type (icase) + fortran.process_input.devtyp() # Initialise the Stellarator fortran.stellarator_module.stinit() @@ -1260,3 +1266,11 @@ def check_process(): fortran.numerics.icc[: fortran.numerics.neqns + fortran.numerics.nineqns] == 88 ).any() and fortran.tfcoil_variables.i_str_wp == 0: raise ProcessValidationError("Can't use constraint 88 if i_strain_tf == 0") + + +def set_active_constraints(): + """Set constraints provided in the input file as 'active'""" + for i in range(fortran.numerics.ipeqns): + if fortran.numerics.icc[i] != 0: + fortran.numerics.active_constraints[fortran.numerics.icc[i] - 1] = True + fortran.process_input.constraints_exist = True diff --git a/source/fortran/input.f90 b/source/fortran/input.f90 index 29b6238731..711f940f30 100644 --- a/source/fortran/input.f90 +++ b/source/fortran/input.f90 @@ -65,13 +65,8 @@ module process_input #endif implicit none - private - public :: input, check_range_int, check_range_real, lower_case, init_input - integer, public, parameter :: nin = 10 + integer, parameter :: nin = 10 -#ifdef unit_test - public :: parse_input_file -#endif integer, parameter :: maxlen = 2000 ! maximum line length character(len=maxlen) :: line ! current line of text from input file integer :: linelen, lineno ! current line length, line number @@ -108,44 +103,6 @@ subroutine init_input error_message = "" end subroutine init_input - subroutine input - - !! Routine that calls the main input file parsing routines - !! author: P J Knight, CCFE, Culham Science Centre - !! None - !! This routine provides the interface between the input file - !! reading routines and the rest of PROCESS. - !! A User's Guide to the PROCESS Systems Code, P. J. Knight, - !! AEA Fusion Report AEA FUS 251, 1993 - ! - ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! - - use constants, only: nout - use numerics, only: ipeqns, icc, active_constraints - implicit none - - ! Arguments - - ! Local variables - - integer :: i - ! j - ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! - - call parse_input_file(nin,nout,show_changes) - - ! Set all the values of the active_constraints array - do i = 1, ipeqns - if (icc(i) /= 0) then - active_constraints(icc(i)) = .true. - constraints_exist = .true. - end if - end do - - ! Set the device type based on the input file's switches - call devtyp - end subroutine input - ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! subroutine devtyp From dae2c0eced7f598e9fa3c66a67300acae91bf321 Mon Sep 17 00:00:00 2001 From: Timothy Nunn Date: Wed, 19 Feb 2025 10:41:44 +0000 Subject: [PATCH 3/9] Convert devtyp to Python --- process/init.py | 9 ++++++++- source/fortran/input.f90 | 16 ---------------- 2 files changed, 8 insertions(+), 17 deletions(-) diff --git a/process/init.py b/process/init.py index 55653ffb6d..4edd357ab6 100644 --- a/process/init.py +++ b/process/init.py @@ -36,7 +36,7 @@ def init_process(): set_active_constraints() # set the device type (icase) - fortran.process_input.devtyp() + set_device_type() # Initialise the Stellarator fortran.stellarator_module.stinit() @@ -1274,3 +1274,10 @@ def set_active_constraints(): if fortran.numerics.icc[i] != 0: fortran.numerics.active_constraints[fortran.numerics.icc[i] - 1] = True fortran.process_input.constraints_exist = True + + +def set_device_type(): + if fortran.ife_variables.ife == 1: + fortran.global_variables.icase = "Inertial Fusion model" + elif fortran.stellarator_variables.istell != 0: + fortran.global_variables.icase = "Stellarator model" diff --git a/source/fortran/input.f90 b/source/fortran/input.f90 index 711f940f30..5b276588d3 100644 --- a/source/fortran/input.f90 +++ b/source/fortran/input.f90 @@ -103,22 +103,6 @@ subroutine init_input error_message = "" end subroutine init_input - ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! - - subroutine devtyp - !! Set icase description based on device type - use global_variables, only: icase - use ife_variables, only: ife - use stellarator_variables, only: istell - implicit none - - if (ife == 1) then - icase = 'Inertial Fusion model' - else if (istell /= 0) then - icase = 'Stellarator model' - end if - end subroutine devtyp - subroutine parse_input_file(in_file,out_file,show_changes) !! Routine that parses the contents of the input file From ccfcf39aee4aaef67f1649bd96d87199462044ee Mon Sep 17 00:00:00 2001 From: Timothy Nunn Date: Wed, 19 Feb 2025 14:29:04 +0000 Subject: [PATCH 4/9] Rewrite input file parsing in Python --- process/init.py | 85 ++++++------ process/input.py | 273 +++++++++++++++++++++++++++++++++++++++ source/fortran/input.f90 | 16 +-- tests/unit/test_input.py | 89 ++++++++++++- 4 files changed, 404 insertions(+), 59 deletions(-) create mode 100644 process/input.py diff --git a/process/init.py b/process/init.py index 4edd357ab6..10dfcdfac2 100644 --- a/process/init.py +++ b/process/init.py @@ -7,7 +7,9 @@ import process import process.fortran as fortran +import process.process_output as process_output from process.exceptions import ProcessValidationError +from process.input import parse_input_file from process.utilities.f2py_string_patch import f2py_compatible_to_string @@ -30,6 +32,7 @@ def init_process(): fortran.init_module.open_files() # Input any desired new initial values + parse_input_file() fortran.process_input.parse_input_file(10, fortran.constants.nout, 0) # Set active constraints @@ -85,71 +88,71 @@ def run_summary(): # Outfile and terminal # for outfile in [fortran.constants.nout, fortran.constants.iotty]: # PROCESS code header - process.process_output.oblnkl(outfile) - process.process_output.ostars(outfile, 110) - process.process_output.ocentr(outfile, "PROCESS", 110) - process.process_output.ocentr(outfile, "Power Reactor Optimisation Code", 110) - process.process_output.ostars(outfile, 110) - process.process_output.oblnkl(outfile) + process_output.oblnkl(outfile) + process_output.ostars(outfile, 110) + process_output.ocentr(outfile, "PROCESS", 110) + process_output.ocentr(outfile, "Power Reactor Optimisation Code", 110) + process_output.ostars(outfile, 110) + process_output.oblnkl(outfile) # Run execution details version = process.__version__ - process.process_output.ocmmnt(outfile, f"Version : {version}") + process_output.ocmmnt(outfile, f"Version : {version}") git_branch, git_tag = get_git_summary() - process.process_output.ocmmnt(outfile, f"Git Tag : {git_tag}") - process.process_output.ocmmnt(outfile, f"Git Branch : {git_branch}") + process_output.ocmmnt(outfile, f"Git Tag : {git_tag}") + process_output.ocmmnt(outfile, f"Git Branch : {git_branch}") date_string = datetime.datetime.now(datetime.timezone.utc).strftime( "%d/%m/%Y %Z" ) time_string = datetime.datetime.now(datetime.timezone.utc).strftime("%H:%M") - process.process_output.ocmmnt(outfile, f"Date : {date_string}") - process.process_output.ocmmnt(outfile, f"Time : {time_string}") + process_output.ocmmnt(outfile, f"Date : {date_string}") + process_output.ocmmnt(outfile, f"Time : {time_string}") user = getpass.getuser() machine = socket.gethostname() - process.process_output.ocmmnt(outfile, f"User : {user}") - process.process_output.ocmmnt(outfile, f"Computer : {machine}") - process.process_output.ocmmnt(outfile, f"Directory : {Path.cwd()}") + process_output.ocmmnt(outfile, f"User : {user}") + process_output.ocmmnt(outfile, f"Computer : {machine}") + process_output.ocmmnt(outfile, f"Directory : {Path.cwd()}") fileprefix = f2py_compatible_to_string(fortran.global_variables.fileprefix) - process.process_output.ocmmnt( + process_output.ocmmnt( outfile, f"Input : {fileprefix}", ) runtitle = f2py_compatible_to_string(fortran.global_variables.runtitle) - process.process_output.ocmmnt( + process_output.ocmmnt( outfile, f"Run title : {runtitle}", ) - process.process_output.ocmmnt( + process_output.ocmmnt( outfile, f"Run type : Reactor concept design: {f2py_compatible_to_string(fortran.global_variables.icase)}, (c) UK Atomic Energy Authority", ) - process.process_output.oblnkl(outfile) - process.process_output.ostars(outfile, 110) - process.process_output.oblnkl(outfile) + process_output.oblnkl(outfile) + process_output.ostars(outfile, 110) + process_output.oblnkl(outfile) - process.process_output.ocmmnt( + process_output.ocmmnt( outfile, f"Equality constraints : {fortran.numerics.neqns.item()}" ) - process.process_output.ocmmnt( + process_output.ocmmnt( outfile, f"Inequality constraints : {fortran.numerics.nineqns.item()}" ) - process.process_output.ocmmnt( + process_output.ocmmnt( outfile, f"Total constraints : {fortran.numerics.nineqns.item() + fortran.numerics.neqns.item()}", ) - process.process_output.ocmmnt( + process_output.ocmmnt( outfile, f"Iteration variables : {fortran.numerics.nvar.item()}" ) - process.process_output.ocmmnt( + process_output.ocmmnt( outfile, f"Max iterations : {fortran.global_variables.maxcal.item()}" ) @@ -163,41 +166,37 @@ def run_summary(): fom_string = f2py_compatible_to_string( fortran.numerics.lablmm[abs(fortran.numerics.minmax) - 1] ) - process.process_output.ocmmnt( + process_output.ocmmnt( outfile, f"Figure of merit : {minmax_sign}{abs(fortran.numerics.minmax)}{minmax_string}{fom_string}", ) - process.process_output.ocmmnt( + process_output.ocmmnt( outfile, f"Convergence parameter : {fortran.numerics.epsvmc}", ) - process.process_output.oblnkl(outfile) - process.process_output.ostars(outfile, 110) + process_output.oblnkl(outfile) + process_output.ostars(outfile, 110) # MFile # mfile = fortran.constants.mfile - process.process_output.ovarst(mfile, "PROCESS version", "(procver)", f'"{version}"') - process.process_output.ovarst(mfile, "Date of run", "(date)", f'"{date_string}"') - process.process_output.ovarst(mfile, "Time of run", "(time)", f'"{time_string}"') - process.process_output.ovarst(mfile, "User", "(username)", f'"{user}"') - process.process_output.ovarst( - mfile, "PROCESS run title", "(runtitle)", f'"{runtitle}"' - ) - process.process_output.ovarst(mfile, "PROCESS git tag", "(tagno)", f'"{git_tag}"') - process.process_output.ovarst( + process_output.ovarst(mfile, "PROCESS version", "(procver)", f'"{version}"') + process_output.ovarst(mfile, "Date of run", "(date)", f'"{date_string}"') + process_output.ovarst(mfile, "Time of run", "(time)", f'"{time_string}"') + process_output.ovarst(mfile, "User", "(username)", f'"{user}"') + process_output.ovarst(mfile, "PROCESS run title", "(runtitle)", f'"{runtitle}"') + process_output.ovarst(mfile, "PROCESS git tag", "(tagno)", f'"{git_tag}"') + process_output.ovarst( mfile, "PROCESS git branch", "(branch_name)", f'"{git_branch}"' ) - process.process_output.ovarst( - mfile, "Input filename", "(fileprefix)", f'"{fileprefix}"' - ) + process_output.ovarst(mfile, "Input filename", "(fileprefix)", f'"{fileprefix}"') - process.process_output.ovarin( + process_output.ovarin( mfile, "Optimisation switch", "(ioptimz)", fortran.numerics.ioptimz ) if fortran.numerics.ioptimz == -2: - process.process_output.ovarin( + process_output.ovarin( mfile, "Figure of merit switch", "(minmax)", fortran.numerics.minmax ) diff --git a/process/input.py b/process/input.py new file mode 100644 index 0000000000..868b686c6c --- /dev/null +++ b/process/input.py @@ -0,0 +1,273 @@ +"""Handle parsing, validation, and actioning of a PROCESS input file (*IN.DAT).""" + +import copy +import re +from collections.abc import Callable +from dataclasses import dataclass +from pathlib import Path +from typing import Any +from warnings import warn + +from process import fortran +from process.exceptions import ProcessValidationError, ProcessValueError +from process.utilities.f2py_string_patch import ( + f2py_compatible_to_string, + string_to_f2py_compatible, +) + +NumberType = int | float +ValidInputTypes = NumberType | str + +DataTypes = (int, float, str) +"""Valid input variable types alias""" + + +@dataclass +class InputVariable: + """A variable to be parsed from the input file.""" + + module: Any + """The Fortran module that this variable should be set on.""" + type: type + """The expected type of the variable""" + range: tuple[NumberType, NumberType] | None = None + """The valid range of values (int and float only) inclusive of the endpoints.""" + choices: list[ValidInputTypes] | None = None + """The valid values of this input.""" + array: bool = False + """Is this input assigning values to an array?""" + additional_validation: ( + Callable[[str, ValidInputTypes, int | None, "InputVariable"], ValidInputTypes] + | None + ) = None + """A function that takes the input variable: name, value, array index, and config (this dataclass) + as input and returns a cleaned version of the input value. May raise + a ProcessValidationError. + + NOTE: The value passed in has already been cleaned in the default way and has + been cast to the specified `type`. + """ + additional_actions: ( + Callable[[str, ValidInputTypes, int | None, "InputVariable"], None] | None + ) = None + """A function that takes the input variable: name, value, array index, and config (this dataclass) + as input and performs some additional action in addition to the default actions prescribed by the variables + config. May raise a ProcessValidationError. + + NOTE: The value passed in has already been cleaned in the default + way and has been cast to the specified `type`. + + NOTE: the input name is the cleaned name as in the input file NOT the `target_variable`. + """ + target_name: str | None = None + """Indicates the parsed variable name is different to its target on the `module`.""" + set_variable: bool = True + """Do not attempt to set the variable on the module. Instead only do any `additional_actions`.""" + + def __post_init__(self): + if self.type not in DataTypes: + error_msg = ( + f"Cannot parse variable of type {self.type}, must be one of {DataTypes}" + ) + raise ProcessValueError(error_msg) + + if self.type not in (int, float) and self.range is not None: + error_msg = "Can only apply a range to integer or float variables" + raise ProcessValueError(error_msg) + + if not self.set_variable and self.additional_actions is None: + warn( + "Not setting variable or performing an additional action. Why are you parsing this variable?", + stacklevel=2, + ) + + +INPUT_VARIABLES = { + "runtitle": InputVariable(fortran.global_variables, str), + "ioptimz": InputVariable(fortran.numerics, int, choices=[1, -2]), + "epsvmc": InputVariable(fortran.numerics, float, range=(0.0, 1.0)), + "boundl": InputVariable(fortran.numerics, float, array=True), +} + + +def parse_input_file(): + input_file = f2py_compatible_to_string(fortran.global_variables.fileprefix) + + input_file_path = Path("IN.DAT") + if input_file != "": + input_file_path = Path(input_file) + + with input_file_path.open("r") as f: + lines = f.readlines() + + for line_no, line in enumerate(lines, start=1): + stripped_line = line.strip() + + # don't bother trying to process blank lines + # or comment lines + if stripped_line == "" or stripped_line[0] == "*": + continue + + # matches (variable name, array index, value) + # NOTE: array index is Fortran-based hence starts at 1. + line_match = re.match( + r"([a-zA-Z0-9_]+)(?:\(([0-9]+)\))?[ ]*=[ ]*([ +\-a-zA-Z0-9.]+).*", + stripped_line, + ) + + if line_match is None: + error_msg = ( + f"Unable to parse line {line_no} of the input file ({stripped_line})" + ) + raise ProcessValueError(error_msg) + + variable_name, array_index, variable_value = line_match.groups() + + variable_config = INPUT_VARIABLES.get(variable_name) + + if variable_config is None: + error_msg = ( + f"Unrecognised input '{variable_name}' at line {line_no} of input file." + ) + warn(error_msg, stacklevel=1) + continue + # TODO: re-enable error instead + # raise ProcessValidationError(error_msg) + + # validate the variable and also clean it (cast to correct type) + + clean_variable_value = validate_variable( + variable_name, variable_value.strip(), array_index, variable_config, line_no + ) + + # check if the target name in the module is different to the variable name + # in the input file + variable_name_in_module = variable_config.target_name or variable_name + + if variable_config.set_variable: + if variable_config.array: + set_array_variable( + variable_name_in_module, + clean_variable_value, + int(array_index), + variable_config, + ) + else: + set_scalar_variable( + variable_name_in_module, clean_variable_value, variable_config + ) + + if variable_config.additional_actions is not None: + # intentionally passing the variable name as in the input file, + # not the module target name. + variable_config.additional_actions( + variable_name, + clean_variable_value, + None if array_index is None else int(array_index), + variable_config, + ) + + +def validate_variable( + name: str, + value: str, + array_index: int | None, + config: InputVariable, + line_number: int, +) -> ValidInputTypes: + """Validate an input. + + :param name: the name of the input. + :param value: the value of the input variable. + :param array_index: the array index of the variable in the input file. + :param config: the config of the variable that describes how to validate and process it. + + :returns: the input value with the correct type. + """ + # check its an array if and only if the config says so + if array_index is None and config.array: + error_msg = f"Expected '{name}' at line {line_number} to be an array." + raise ProcessValidationError(error_msg) + + if array_index is not None and not config.array: + error_msg = f"Not expecting '{name}' at line {line_number} to be an array." + raise ProcessValidationError(error_msg) + + if config.type in [float, int]: + value = value.lower().replace("d", "e") + + try: + clean_value = config.type(value) + except ValueError as e: + error_msg = f"Cannot cast variable name '{name}' at line {line_number} to a {config.type} (value = {value})" + raise ProcessValidationError(error_msg) from e + + if ( + config.range is not None + and not config.range[0] <= clean_value <= config.range[1] + ): + error_msg = ( + f"Variable '{name}' at line {line_number} is not on the prescribed range" + f" {config.range} (value = {value})" + ) + raise ProcessValidationError(error_msg) + + if config.choices is not None and clean_value not in config.choices: + error_msg = f"Variable '{name}' at line {line_number} is not one of {config.choices} (value = {value})" + raise ProcessValidationError(error_msg) + + if config.additional_validation is not None: + clean_value = config.additional_validation( + name, clean_value, int(array_index), config + ) + + return clean_value + + +def set_scalar_variable(name: str, value: ValidInputTypes, config: InputVariable): + """Set a scalar (not part of an array) variable in the `config.module`. + + :param name: the name of the input. + :param value: the value of the input variable. + :param config: the config of the variable that describes how to validate and process it. + """ + current_value = getattr(config.module, name, ...) + + # use ... sentinel because None is probably a valid return from Fortran + # and definately will be when moving to a Python data structure + if current_value is ...: + error_msg = ( + f"Fortran module '{config.module}' does not have a variable '{name}'." + ) + raise ProcessValueError(error_msg) + + if config.type is str: + setattr(config.module, name, string_to_f2py_compatible(current_value, value)) + else: + setattr(config.module, name, value) + + +def set_array_variable(name: str, value: str, array_index: int, config: InputVariable): + """Set an array variable in the `config.module`. + + The way PROCESS input files are structured, each element of the array is provided on one line + so this function just needs to set the `value` at `array_index` (-1) because of Fortran-based indexing. + + :param name: the name of the input. + :param value: the value of the input variable. + :param array_index: the array index of the variable in the input file. + :param config: the config of the variable that describes how to validate and process it. + """ + current_array = getattr(config.module, name, ...) + + # use ... sentinel for same reason as above + if current_array is ...: + error_msg = f"Fortran module '{config.module}' does not have an array '{name}'." + raise ProcessValueError(error_msg) + + if config.type is str: + raise NotImplementedError + + new_array = copy.deepcopy(current_array) + new_array[array_index - 1] = value + setattr(config.module, name, new_array) diff --git a/source/fortran/input.f90 b/source/fortran/input.f90 index 5b276588d3..e13b9df909 100644 --- a/source/fortran/input.f90 +++ b/source/fortran/input.f90 @@ -130,7 +130,7 @@ subroutine parse_input_file(in_file,out_file,show_changes) ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! use constants, only: dcopper, dalu - use global_variables, only: run_tests, verbose, maxcal, runtitle + use global_variables, only: run_tests, verbose, maxcal use build_variables, only: i_tf_inside_cs, blbmoth, blbuith, dr_shld_outboard, & dz_shld_upper, dz_shld_lower, dz_shld_vv_gap, plleni, dr_fw_outboard, dr_shld_blkt_gap, & dr_shld_thermal_inboard, dr_shld_thermal_outboard, dz_shld_thermal, i_cs_precomp, & @@ -234,8 +234,8 @@ subroutine parse_input_file(in_file,out_file,show_changes) blmatf, ife use impurity_radiation_module, only: radius_plasma_core_norm, n_impurities, & coreradiationfraction, fimp - use numerics, only: factor, boundl, minmax, neqns, nvar, epsfcn, ixc, & - epsvmc, ftol, ipnvars, ioptimz, nineqns, ipeqns, boundu, icc, ipnfoms, name_xc + use numerics, only: factor, minmax, neqns, nvar, epsfcn, ixc, & + ftol, ipnvars, nineqns, ipeqns, boundu, icc, ipnfoms, name_xc use pfcoil_variables, only: rhopfbus, j_pf_coil_wp_peak, zref, fcuohsu, f_a_cs_steel, f_a_pf_coil_void, & j_cs_flat_top_end, sigpfcalw, alstroh, i_pf_conductor, fcupfsu, fvs_cs_pf_total_ramp, etapsu, i_cs_stress, & fb_cs_limit_max, ngc, rpf2, f_j_cs_start_pulse_end_flat_top, f_z_cs_tf_internal, f_a_cs_void, i_cs_superconductor, n_pf_groups_max, ngc2, rpf1, & @@ -390,10 +390,7 @@ subroutine parse_input_file(in_file,out_file,show_changes) variable: select case (varnam(1:varlen)) ! General settings - case ('runtitle') - call parse_string_variable('runtitle', runtitle, & - 'title of run') case ('verbose') call parse_int_variable('verbose', verbose, 0, 1, & 'Switch for diagnostic output') @@ -403,8 +400,6 @@ subroutine parse_input_file(in_file,out_file,show_changes) ! Numerical solver settings case ('boundl') - call parse_real_array('boundl', boundl, isub1, ipnvars, & - 'Iteration variable lower bound', icode) case ('boundu') call parse_real_array('boundu', boundu, isub1, ipnvars, & 'Iteration variable upper bound', icode) @@ -412,8 +407,6 @@ subroutine parse_input_file(in_file,out_file,show_changes) call parse_real_variable('epsfcn', epsfcn, 0.0D0, 1.0D0, & 'HYBRD/VMCON derivative step length') case ('epsvmc') - call parse_real_variable('epsvmc', epsvmc, 0.0D0, 1.0D0, & - 'VMCON error tolerance') case ('factor') call parse_real_variable('factor', factor, 0.0D0, 10.0D0, & 'HYBRD initial step size') @@ -433,10 +426,7 @@ subroutine parse_input_file(in_file,out_file,show_changes) call parse_int_array('ixc', ixc, isub1, ipnvars, & 'Iteration variable', icode,no_iteration) no_iteration = isub1 - case ('ioptimz') - call parse_int_variable('ioptimz', ioptimz, -2, 1, & - 'Switch for solver method') case ('maxcal') call parse_int_variable('maxcal', maxcal, 0, 10000, & 'Max no of VMCON iterations') diff --git a/tests/unit/test_input.py b/tests/unit/test_input.py index c0eea11db3..1a6e159af3 100644 --- a/tests/unit/test_input.py +++ b/tests/unit/test_input.py @@ -1,8 +1,13 @@ import pytest import process.init as init +import process.input as process_input from process import fortran -from process.utilities.f2py_string_patch import string_to_f2py_compatible +from process.exceptions import ProcessValidationError +from process.utilities.f2py_string_patch import ( + f2py_compatible_to_string, + string_to_f2py_compatible, +) def _create_input_file(directory, content: str): @@ -48,7 +53,8 @@ def _create_input_file(directory, content: str): + [ (string, 0.0080000000000000002) for string in ["0.008", "8.0E-3", "8.0D-3", "8.0d-3", "8.0e-3"] - ], + ] + + [("0.546816593988753", 0.546816593988753)], ) def test_parse_real(epsvmc, expected, tmp_path): """Tests the parsing of real numbers into PROCESS. @@ -61,4 +67,81 @@ def test_parse_real(epsvmc, expected, tmp_path): ) init.init_process() - assert fortran.numerics.epsvmc.item() == expected + assert fortran.numerics.epsvmc == expected + + +def test_parse_input(tmp_path): + fortran.global_variables.fileprefix = string_to_f2py_compatible( + fortran.global_variables.fileprefix, + _create_input_file( + tmp_path, + ("runtitle = my run title\nioptimz = -2\nepsvmc = 0.6\nboundl(1) = 0.5"), + ), + ) + init.init_process() + + assert ( + f2py_compatible_to_string(fortran.global_variables.runtitle) == "my run title" + ) + assert fortran.numerics.ioptimz == -2 + assert pytest.approx(fortran.numerics.epsvmc) == 0.6 + assert pytest.approx(fortran.numerics.boundl[0]) == 0.5 + + +def test_input_choices(tmp_path): + fortran.global_variables.fileprefix = string_to_f2py_compatible( + fortran.global_variables.fileprefix, + _create_input_file(tmp_path, ("ioptimz = -1")), + ) + + # check that the test data doesn't change + assert process_input.INPUT_VARIABLES["ioptimz"].choices == [1, -2] + + with pytest.raises(ProcessValidationError): + init.init_process() + + +@pytest.mark.parametrize( + ("input_file_value"), ((-0.01,), (1.1,)), ids=("violate lower", "violate upper") +) +def test_input_range(tmp_path, input_file_value): + fortran.global_variables.fileprefix = string_to_f2py_compatible( + fortran.global_variables.fileprefix, + _create_input_file(tmp_path, (f"epsvmc = {input_file_value}")), + ) + + # check that the test data doesn't change + assert process_input.INPUT_VARIABLES["epsvmc"].range == (0.0, 1.0) + + with pytest.raises(ProcessValidationError): + init.init_process() + + +def test_input_array_when_not(tmp_path): + fortran.global_variables.fileprefix = string_to_f2py_compatible( + fortran.global_variables.fileprefix, + _create_input_file(tmp_path, ("epsvmc(1) = 0.5")), + ) + + with pytest.raises(ProcessValidationError): + init.init_process() + + +def test_input_not_array_when_is(tmp_path): + fortran.global_variables.fileprefix = string_to_f2py_compatible( + fortran.global_variables.fileprefix, + _create_input_file(tmp_path, ("boundl = 0.5")), + ) + + with pytest.raises(ProcessValidationError): + init.init_process() + + +def test_input_float_when_int(tmp_path): + fortran.global_variables.fileprefix = string_to_f2py_compatible( + fortran.global_variables.fileprefix, + _create_input_file(tmp_path, ("ioptimz = 0.5")), + ) + + with pytest.raises(ProcessValidationError): + init.init_process() From eb2861372159791dc406743badc95fc15ca07dff Mon Sep 17 00:00:00 2001 From: Timothy Nunn Date: Wed, 19 Feb 2025 17:13:51 +0000 Subject: [PATCH 5/9] Add variables parsed in Python to the dicts --- scripts/create_dicts.py | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/scripts/create_dicts.py b/scripts/create_dicts.py index 155aaf6d27..3736ae6260 100644 --- a/scripts/create_dicts.py +++ b/scripts/create_dicts.py @@ -27,8 +27,11 @@ import numpy as np from python_dicts import get_python_variables +from process.input import INPUT_VARIABLES from process.scan import SCAN_VARIABLES +INPUT_TYPE_MAP = {int: "int", float: "real", str: "string"} + output_dict = {} # Dict of nested dicts e.g. output_dict['DICT_DESCRIPTIONS'] = # {descriptions_dict} @@ -674,6 +677,14 @@ def dict_var_type(): DICT_VAR_TYPE['beta'] = 'real_variable' """ di = {} + + for var_name, config in INPUT_VARIABLES.items(): + var_type = ( + f"{INPUT_TYPE_MAP[config.type]}_{'array' if config.array else 'variable'}" + ) + + di[var_name] = var_type + regexp = r"call parse_(real|int|string)_(array|variable)\(" lines = grep(SOURCEDIR + "/input.f90", regexp) for line in lines: @@ -750,6 +761,18 @@ def dict_input_bounds(): regexp = r"call parse_(real|int)_variable\((.*)" lines = grep(SOURCEDIR + "/input.f90", regexp) + for var_name, config in INPUT_VARIABLES.items(): + lb, ub = None, None + if config.range is not None: + lb, ub = config.range + + elif config.choices is not None and config.type in [int, float]: + lb = min(config.choices) + ub = max(config.choices) + + if lb is not None: + di[var_name] = {"lb": lb, "ub": ub} + for line in lines: match = re.search(regexp, line) try: From 5a89c513d1e8b1d17ac29639ed5af998e88e1dd7 Mon Sep 17 00:00:00 2001 From: Timothy Nunn Date: Wed, 19 Feb 2025 17:25:38 +0000 Subject: [PATCH 6/9] Parse all inputs in Python --- CMakeLists.txt | 1 - process/init.py | 49 +- process/input.py | 1609 +++++++++++++++++++++++- scripts/create_dicts.py | 1 + source/fortran/init_module.f90 | 4 +- source/fortran/iteration_variables.f90 | 4 + source/fortran/numerics.f90 | 5 +- tests/unit/test_input.py | 12 + 8 files changed, 1661 insertions(+), 24 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 0a67fb136e..069d1f072a 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -114,7 +114,6 @@ LIST(APPEND PROCESS_SRCS stellarator_variables.f90 stellarator.f90 stellarator_configuration.f90 - input.f90 ) PREPROCESS() diff --git a/process/init.py b/process/init.py index 10dfcdfac2..b1c0030abb 100644 --- a/process/init.py +++ b/process/init.py @@ -32,8 +32,7 @@ def init_process(): fortran.init_module.open_files() # Input any desired new initial values - parse_input_file() - fortran.process_input.parse_input_file(10, fortran.constants.nout, 0) + inputs = parse_input_file() # Set active constraints set_active_constraints() @@ -45,7 +44,7 @@ def init_process(): fortran.stellarator_module.stinit() # Check input data for errors/ambiguities - check_process() + check_process(inputs) run_summary() @@ -209,7 +208,6 @@ def init_all_module_vars(): than a 'run-once' executable. """ fortran.numerics.init_numerics() - fortran.process_input.init_input() fortran.buildings_variables.init_buildings_variables() fortran.cost_variables.init_cost_variables() fortran.divertor_variables.init_divertor_variables() @@ -421,7 +419,7 @@ def initialise_iterative_variables(): fortran.define_iteration_variables.init_itv_175() -def check_process(): +def check_process(inputs): """Routine to reset specific variables if certain options are being used author: P J Knight, CCFE, Culham Science Centre @@ -429,7 +427,37 @@ def check_process(): This routine performs a sanity check of the input variables and ensures other dependent variables are given suitable values. """ - # error_handling.errors_on = True + # Inboard blanket does not exist if the thickness is below a certain limit. + if "dr_blkt_inboard" in inputs and fortran.fwbs_variables.i_blanket_type == 3: + warn( + "dr_blkt_inboard input is not required for CCFE HCPB model with Tritium Breeding Ratio calculation", + stacklevel=1, + ) + + if "dr_blkt_outboard" in inputs and fortran.fwbs_variables.i_blanket_type == 3: + warn( + "dr_blkt_outboard input is not required for CCFE HCPB model with Tritium Breeding Ratio calculation", + stacklevel=1, + ) + + if fortran.fwbs_variables.i_blanket_type == 3: + fortran.build_variables.dr_fw_inboard = 0.03 + fortran.build_variables.dr_fw_outboard = 0.03 + fortran.fwbs_variables.fw_armour_thickness = 0.003 + + if 0 <= fortran.build_variables.dr_blkt_inboard <= 1e-3: + fortran.build_variables.dr_blkt_inboard = 0.0 + fortran.fwbs_variables.i_blkt_inboard = 0 + + if fortran.fwbs_variables.iblanket_thickness == 1: + fortran.build_variables.dr_blkt_inboard = 0.53 + fortran.build_variables.dr_blkt_outboard = 0.91 + elif fortran.fwbs_variables.iblanket_thickness == 2: + fortran.build_variables.dr_blkt_inboard = 0.64 + fortran.build_variables.dr_blkt_outboard = 1.11 + elif fortran.fwbs_variables.iblanket_thickness == 3: + fortran.build_variables.dr_blkt_inboard = 0.75 + fortran.build_variables.dr_blkt_outboard = 1.30 # Check that there are sufficient iteration variables if fortran.numerics.nvar < fortran.numerics.neqns: @@ -1269,10 +1297,17 @@ def check_process(): def set_active_constraints(): """Set constraints provided in the input file as 'active'""" + num_constraints = 0 for i in range(fortran.numerics.ipeqns): if fortran.numerics.icc[i] != 0: fortran.numerics.active_constraints[fortran.numerics.icc[i] - 1] = True - fortran.process_input.constraints_exist = True + num_constraints += 1 + + if fortran.numerics.neqns == 0: + # The value of neqns has not been set in the input file. Default = 0. + fortran.numerics.neqns = num_constraints - fortran.numerics.nineqns + else: + fortran.numerics.nineqns = num_constraints - fortran.numerics.neqns def set_device_type(): diff --git a/process/input.py b/process/input.py index 868b686c6c..3d8252b580 100644 --- a/process/input.py +++ b/process/input.py @@ -22,6 +22,16 @@ """Valid input variable types alias""" +def _ixc_additional_actions(_name, value: int, _array_index, _config): + fortran.numerics.ixc[fortran.numerics.nvar.item()] = value + fortran.numerics.nvar += 1 + + +def _icc_additional_actions(_name, value: int, _array_index, _config): + fortran.numerics.icc[fortran.numerics.n_constraints.item()] = value + fortran.numerics.n_constraints += 1 + + @dataclass class InputVariable: """A variable to be parsed from the input file.""" @@ -84,9 +94,1546 @@ def __post_init__(self): INPUT_VARIABLES = { "runtitle": InputVariable(fortran.global_variables, str), + "verbose": InputVariable(fortran.global_variables, int, choices=[0, 1]), + "run_tests": InputVariable(fortran.global_variables, int, choices=[0, 1]), "ioptimz": InputVariable(fortran.numerics, int, choices=[1, -2]), "epsvmc": InputVariable(fortran.numerics, float, range=(0.0, 1.0)), "boundl": InputVariable(fortran.numerics, float, array=True), + "boundu": InputVariable(fortran.numerics, float, array=True), + "epsfcn": InputVariable(fortran.numerics, float, range=(0.0, 1.0)), + "maxcal": InputVariable(fortran.global_variables, int, range=(0, 10000)), + "minmax": InputVariable(fortran.numerics, int), + "neqns": InputVariable( + fortran.numerics, int, range=(1, fortran.numerics.ipeqns.item()) + ), + "nineqns": InputVariable( + fortran.numerics, int, range=(1, fortran.numerics.ipeqns.item()) + ), + "alphaj": InputVariable(fortran.physics_variables, float, range=(0.0, 10.0)), + "alphan": InputVariable(fortran.physics_variables, float, range=(0.0, 10.0)), + "alphat": InputVariable(fortran.physics_variables, float, range=(0.0, 10.0)), + "aspect": InputVariable(fortran.physics_variables, float, range=(1.001, 40.0)), + "beamfus0": InputVariable(fortran.physics_variables, float, range=(0.01, 10.0)), + "beta": InputVariable(fortran.physics_variables, float, range=(0.0, 1.0)), + "beta_max": InputVariable(fortran.physics_variables, float, range=(0.0, 1.0)), + "beta_min": InputVariable(fortran.physics_variables, float, range=(0.0, 1.0)), + "betbm0": InputVariable(fortran.physics_variables, float, range=(0.0, 10.0)), + "bt": InputVariable(fortran.physics_variables, float, range=(0.0, 30.0)), + "burnup_in": InputVariable(fortran.physics_variables, float, range=(0.0, 1.0)), + "radius_plasma_core_norm": InputVariable( + fortran.impurity_radiation_module, float, range=(0.0, 1.0) + ), + "coreradiationfraction": InputVariable( + fortran.impurity_radiation_module, float, range=(0.0, 1.0) + ), + "c_beta": InputVariable(fortran.physics_variables, float, range=(0.0, 1.0)), + "csawth": InputVariable(fortran.physics_variables, float, range=(0.0, 10.0)), + "f_vol_plasma": InputVariable( + fortran.physics_variables, float, range=(0.001, 10.0) + ), + "f_r_conducting_wall": InputVariable( + fortran.physics_variables, float, range=(1.0, 3.0) + ), + "dene": InputVariable(fortran.physics_variables, float, range=(1.0e18, 1.0e22)), + "beta_norm_max": InputVariable(fortran.physics_variables, float, range=(0.0, 20.0)), + "beta_poloidal_eps_max": InputVariable( + fortran.physics_variables, float, range=(0.01, 10.0) + ), + "f_alpha_plasma": InputVariable(fortran.physics_variables, float, range=(0.0, 1.0)), + "ftar": InputVariable(fortran.physics_variables, float, range=(0.0, 1.0)), + "f_deuterium": InputVariable(fortran.physics_variables, float, range=(0.0, 1.0)), + "ffwal": InputVariable(fortran.physics_variables, float, range=(0.0, 10.0)), + "fgwped": InputVariable(fortran.physics_variables, float, range=(-1.0, 5.0)), + "fgwsep": InputVariable(fortran.physics_variables, float, range=(-1.0, 5.0)), + "f_helium3": InputVariable(fortran.physics_variables, float, range=(-1.0, 5.0)), + # TODO: does fimp require an additional range? + "fimp": InputVariable(fortran.impurity_radiation_module, float, array=True), + "fkzohm": InputVariable(fortran.physics_variables, float, range=(0.5, 2.0)), + "fnesep": InputVariable(fortran.physics_variables, float, range=(0.1, 20.0)), + "abktflnc": InputVariable(fortran.cost_variables, float, range=(0.1, 100.0)), + "adivflnc": InputVariable(fortran.cost_variables, float, range=(0.1, 100.0)), + "admv": InputVariable(fortran.buildings_variables, float, range=(1.0e4, 1.0e6)), + "afwi": InputVariable(fortran.fwbs_variables, float, range=(0.001, 0.05)), + "afwo": InputVariable(fortran.fwbs_variables, float, range=(0.001, 0.05)), + "airtemp": InputVariable(fortran.water_usage_variables, float, range=(-15.0, 40.0)), + "alfapf": InputVariable(fortran.pfcoil_variables, float, range=(1e-12, 1.0)), + "alstroh": InputVariable( + fortran.pfcoil_variables, float, range=(1000000.0, 100000000000.0) + ), + "amortization": InputVariable(fortran.cost_variables, float, range=(1.0, 50.0)), + "anginc": InputVariable(fortran.divertor_variables, float, range=(0.0, 1.5707)), + "aplasmin": InputVariable(fortran.build_variables, float, range=(0.01, 10.0)), + "aux_build_h": InputVariable( + fortran.buildings_variables, float, range=(1.0, 100.0) + ), + "aux_build_l": InputVariable( + fortran.buildings_variables, float, range=(10.0, 1000.0) + ), + "aux_build_w": InputVariable( + fortran.buildings_variables, float, range=(10.0, 1000.0) + ), + "auxcool_h": InputVariable(fortran.buildings_variables, float, range=(1.0, 100.0)), + "auxcool_l": InputVariable( + fortran.buildings_variables, float, range=(10.0, 1000.0) + ), + "auxcool_w": InputVariable( + fortran.buildings_variables, float, range=(10.0, 1000.0) + ), + "auxmin": InputVariable(fortran.constraint_variables, float, range=(0.01, 100.0)), + "avail_min": InputVariable(fortran.cost_variables, float, range=(0.0, 1.0)), + "b_crit_upper_nbti": InputVariable( + fortran.tfcoil_variables, float, range=(0.0, 30.0) + ), + "baseel": InputVariable( + fortran.heat_transport_variables, float, range=(1000000.0, 10000000000.0) + ), + "bcritsc": InputVariable(fortran.tfcoil_variables, float, range=(10.0, 50.0)), + "bctmp": InputVariable(fortran.pulse_variables, float, range=(1.0, 800.0)), + "beam_energy": InputVariable( + fortran.current_drive_variables, float, range=(1.0, 1000000.0) + ), + "beamwd": InputVariable(fortran.current_drive_variables, float, range=(0.001, 5.0)), + "beta_div": InputVariable(fortran.divertor_variables, float, range=(0.0, 360.0)), + "beta_poloidal_max": InputVariable( + fortran.constraint_variables, float, range=(0.01, 2.0) + ), + "betai": InputVariable(fortran.divertor_variables, float, range=(0.0, 1.5707)), + "betao": InputVariable(fortran.divertor_variables, float, range=(0.0, 1.5707)), + "bigqmin": InputVariable(fortran.constraint_variables, float, range=(0.01, 100.0)), + "bioshld_thk": InputVariable( + fortran.buildings_variables, float, range=(0.25, 25.0) + ), + "bkt_life_csf": InputVariable( + fortran.cs_fatigue_variables, float, range=(0.0, 1.0) + ), + "blbmith": InputVariable(fortran.build_variables, float, range=(0.0, 2.0)), + "blbmoth": InputVariable(fortran.build_variables, float, range=(0.0, 2.0)), + "blbpith": InputVariable(fortran.build_variables, float, range=(0.0, 2.0)), + "blbpoth": InputVariable(fortran.build_variables, float, range=(0.0, 2.0)), + "blbuith": InputVariable(fortran.build_variables, float, range=(0.0, 2.0)), + "blbuoth": InputVariable(fortran.build_variables, float, range=(0.0, 2.0)), + "bldr": InputVariable(fortran.ife_variables, float, range=(0.0, 10.0)), + "bldrc": InputVariable(fortran.ife_variables, float, range=(0.0, 10.0)), + "bldzl": InputVariable(fortran.ife_variables, float, range=(0.0, 10.0)), + "bldzu": InputVariable(fortran.ife_variables, float, range=(0.0, 10.0)), + "blpressure": InputVariable( + fortran.fwbs_variables, float, range=(100000.0, 100000000.0) + ), + "blpressure_liq": InputVariable( + fortran.fwbs_variables, float, range=(100000.0, 100000000.0) + ), + "b_cs_limit_max": InputVariable( + fortran.pfcoil_variables, float, range=(0.01, 100.0) + ), + "bmn": InputVariable(fortran.stellarator_variables, float, range=(0.0001, 0.01)), + "bmxlim": InputVariable(fortran.constraint_variables, float, range=(0.1, 50.0)), + "bootstrap_current_fraction_max": InputVariable( + fortran.current_drive_variables, float, range=(-0.999, 0.999) + ), + "bpsout": InputVariable(fortran.divertor_variables, float, range=(0.0, 10.0)), + "breeder_f": InputVariable(fortran.fwbs_variables, float, range=(0.0, 1.0)), + "breeder_multiplier": InputVariable( + fortran.fwbs_variables, float, range=(0.0, 1.0) + ), + "bz_channel_conduct_liq": InputVariable( + fortran.fwbs_variables, float, range=(1e-06, 1000000.0) + ), + "c1div": InputVariable(fortran.divertor_variables, float, range=(-100.0, 100.0)), + "c2div": InputVariable(fortran.divertor_variables, float, range=(-100.0, 100.0)), + "c3div": InputVariable(fortran.divertor_variables, float, range=(-100.0, 100.0)), + "c4div": InputVariable(fortran.divertor_variables, float, range=(-100.0, 100.0)), + "c5div": InputVariable(fortran.divertor_variables, float, range=(-100.0, 100.0)), + "c6div": InputVariable(fortran.divertor_variables, float, range=(-100.0, 100.0)), + "casthi": InputVariable(fortran.tfcoil_variables, float, range=(0.0, 1.0)), + "casthi_fraction": InputVariable(fortran.tfcoil_variables, float, range=(0.0, 1.0)), + "casths": InputVariable(fortran.tfcoil_variables, float, range=(0.0, 1.0)), + "casths_fraction": InputVariable(fortran.tfcoil_variables, float, range=(0.0, 1.0)), + "cboot": InputVariable(fortran.current_drive_variables, float, range=(0.0, 10.0)), + "cconfix": InputVariable(fortran.cost_variables, float, range=(50.0, 200.0)), + "cconshpf": InputVariable(fortran.cost_variables, float, range=(50.0, 200.0)), + "cconshtf": InputVariable(fortran.cost_variables, float, range=(50.0, 200.0)), + "cdriv0": InputVariable(fortran.ife_variables, float, range=(50.0, 500.0)), + "cdriv1": InputVariable(fortran.ife_variables, float, range=(50.0, 500.0)), + "cdriv2": InputVariable(fortran.ife_variables, float, range=(50.0, 500.0)), + "cfactr": InputVariable(fortran.cost_variables, float, range=(0.0, 1.0)), + "chdzl": InputVariable(fortran.ife_variables, float, range=(0.0, 10.0)), + "chdzu": InputVariable(fortran.ife_variables, float, range=(0.0, 10.0)), + "chemlab_h": InputVariable(fortran.buildings_variables, float, range=(1.0, 100.0)), + "chemlab_l": InputVariable( + fortran.buildings_variables, float, range=(10.0, 1000.0) + ), + "chemlab_w": InputVariable( + fortran.buildings_variables, float, range=(10.0, 1000.0) + ), + "chrad": InputVariable(fortran.ife_variables, float, range=(0.1, 20.0)), + "cland": InputVariable(fortran.cost_variables, float, range=(10.0, 100.0)), + "clh2": InputVariable(fortran.buildings_variables, float, range=(0.0, 30.0)), + "j_cs_flat_top_end": InputVariable( + fortran.pfcoil_variables, float, range=(10000.0, 500000000.0) + ), + "conf_mag": InputVariable(fortran.cost_variables, float, range=(0.9, 1.0)), + "control_buildings_h": InputVariable( + fortran.buildings_variables, float, range=(1.0, 100.0) + ), + "control_buildings_l": InputVariable( + fortran.buildings_variables, float, range=(10.0, 1000.0) + ), + "control_buildings_w": InputVariable( + fortran.buildings_variables, float, range=(10.0, 1000.0) + ), + "conv": InputVariable( + fortran.buildings_variables, float, range=(10000.0, 1000000.0) + ), + "coolp": InputVariable( + fortran.fwbs_variables, float, range=(100000.0, 100000000.0) + ), + "copper_rrr": InputVariable(fortran.rebco_variables, float, range=(1.0, 10000.0)), + "copper_thick": InputVariable(fortran.rebco_variables, float, range=(0.0, 0.001)), + "copperaoh_m2": InputVariable( + fortran.rebco_variables, float, range=(1.0, 10000000000.0) + ), + "copperaoh_m2_max": InputVariable( + fortran.rebco_variables, float, range=(10000.0, 10000000000.0) + ), + "cost_factor_bop": InputVariable(fortran.cost_variables, float, range=(0.1, 10.0)), + "cost_factor_buildings": InputVariable( + fortran.cost_variables, float, range=(0.1, 10.0) + ), + "cost_factor_fwbs": InputVariable(fortran.cost_variables, float, range=(0.1, 10.0)), + "cost_factor_land": InputVariable(fortran.cost_variables, float, range=(0.1, 10.0)), + "cost_factor_misc": InputVariable(fortran.cost_variables, float, range=(0.1, 10.0)), + "cost_factor_rh": InputVariable(fortran.cost_variables, float, range=(0.1, 10.0)), + "cost_factor_tf_coils": InputVariable( + fortran.cost_variables, float, range=(0.1, 10.0) + ), + "cost_factor_vv": InputVariable(fortran.cost_variables, float, range=(0.1, 10.0)), + "costexp": InputVariable(fortran.cost_variables, float, range=(0.01, 5.0)), + "costexp_pebbles": InputVariable(fortran.cost_variables, float, range=(0.01, 5.0)), + "cowner": InputVariable(fortran.cost_variables, float, range=(0.0, 1.0)), + "cplife_input": InputVariable(fortran.cost_variables, float, range=(0.001, 50.0)), + "cpstflnc": InputVariable(fortran.cost_variables, float, range=(0.01, 30.0)), + "cpttf": InputVariable(fortran.tfcoil_variables, float, range=(0.001, 1000000.0)), + "cpttf_max": InputVariable(fortran.tfcoil_variables, float, range=(1.0, 1000000.0)), + "crane_arm_h": InputVariable( + fortran.buildings_variables, float, range=(1.0, 100.0) + ), + "crane_clrnc_h": InputVariable( + fortran.buildings_variables, float, range=(0.0, 10.0) + ), + "crane_clrnc_v": InputVariable( + fortran.buildings_variables, float, range=(0.0, 10.0) + ), + "croco_thick": InputVariable(fortran.rebco_variables, float, range=(0.001, 0.1)), + "cryomag_h": InputVariable(fortran.buildings_variables, float, range=(1.0, 100.0)), + "cryomag_l": InputVariable( + fortran.buildings_variables, float, range=(10.0, 1000.0) + ), + "cryomag_w": InputVariable( + fortran.buildings_variables, float, range=(10.0, 1000.0) + ), + "cryostat_clrnc": InputVariable( + fortran.buildings_variables, float, range=(0.0, 10.0) + ), + "cryostore_h": InputVariable( + fortran.buildings_variables, float, range=(1.0, 100.0) + ), + "cryostore_l": InputVariable( + fortran.buildings_variables, float, range=(10.0, 1000.0) + ), + "cryostore_w": InputVariable( + fortran.buildings_variables, float, range=(10.0, 1000.0) + ), + "crypmw_max": InputVariable( + fortran.heat_transport_variables, float, range=(0.01, 200.0) + ), + "csi": InputVariable(fortran.cost_variables, float, range=(1.0, 100.0)), + "cturbb": InputVariable(fortran.cost_variables, float, range=(100.0, 1000.0)), + "dz_vv_lower": InputVariable(fortran.build_variables, float, range=(0.0, 10.0)), + "dz_vv_upper": InputVariable(fortran.build_variables, float, range=(0.0, 10.0)), + "dalu": InputVariable(fortran.constants, float, range=(2500.0, 30000.0)), + "dcase": InputVariable(fortran.tfcoil_variables, float, range=(1000.0, 100000.0)), + "dcdrv0": InputVariable(fortran.ife_variables, float, range=(0.0, 200.0)), + "dcdrv1": InputVariable(fortran.ife_variables, float, range=(0.0, 200.0)), + "dcdrv2": InputVariable(fortran.ife_variables, float, range=(0.0, 200.0)), + "dcondins": InputVariable(fortran.tfcoil_variables, float, range=(500.0, 10000.0)), + "dcopper": InputVariable(fortran.constants, float, range=(8000.0, 10000.0)), + "declblkt": InputVariable(fortran.fwbs_variables, float, range=(0.01, 0.2)), + "declfw": InputVariable(fortran.fwbs_variables, float, range=(0.01, 0.2)), + "declshld": InputVariable(fortran.fwbs_variables, float, range=(0.01, 0.2)), + "decomf": InputVariable(fortran.cost_variables, float, range=(0.0, 1.0)), + "delld": InputVariable(fortran.divertor_variables, float, range=(0.1, 2.0)), + "denstl": InputVariable(fortran.fwbs_variables, float, range=(5000.0, 10000.0)), + "dhecoil": InputVariable(fortran.tfcoil_variables, float, range=(0.0, 0.1)), + "dintrt": InputVariable(fortran.cost_variables, float, range=(0.0, 0.1)), + "discount_rate": InputVariable(fortran.cost_variables, float, range=(0.0, 0.5)), + "div_nref": InputVariable( + fortran.cost_variables, float, range=(1000.0, 100000000.0) + ), + "div_nu": InputVariable(fortran.cost_variables, float, range=(1000.0, 100000000.0)), + "div_prob_fail": InputVariable(fortran.cost_variables, float, range=(0.0, 1.0)), + "div_umain_time": InputVariable(fortran.cost_variables, float, range=(0.1, 2.0)), + "divclfr": InputVariable(fortran.divertor_variables, float, range=(0.0, 1.0)), + "divdens": InputVariable(fortran.divertor_variables, float, range=(0.1, 100000.0)), + "dz_divertor": InputVariable(fortran.divertor_variables, float, range=(0.1, 5.0)), + "divplt": InputVariable(fortran.divertor_variables, float, range=(0.01, 1.0)), + "dp_blkt": InputVariable( + fortran.primary_pumping_variables, float, range=(0.0, 10000000.0) + ), + "dp_fw": InputVariable( + fortran.primary_pumping_variables, float, range=(0.0, 10000000.0) + ), + "dp_fw_blkt": InputVariable( + fortran.primary_pumping_variables, float, range=(0.0, 10000000.0) + ), + "dp_he": InputVariable( + fortran.primary_pumping_variables, float, range=(0.0, 10000000.0) + ), + "dp_liq": InputVariable( + fortran.primary_pumping_variables, float, range=(0.0, 10000000.0) + ), + "dr_blkt_inboard": InputVariable(fortran.build_variables, float, range=(0.0, 10.0)), + "dr_blkt_outboard": InputVariable( + fortran.build_variables, float, range=(0.0, 10.0) + ), + "dr_bore": InputVariable(fortran.build_variables, float, range=(0.0, 50.0)), + "dr_cryostat": InputVariable(fortran.build_variables, float, range=(0.0, 10.0)), + "dr_cs": InputVariable(fortran.build_variables, float, range=(0.0, 10.0)), + "dr_cs_tf_gap": InputVariable(fortran.build_variables, float, range=(0.0, 10.0)), + "dr_fw_plasma_gap_inboard": InputVariable( + fortran.build_variables, float, range=(0.0, 10.0) + ), + "dr_fw_plasma_gap_outboard": InputVariable( + fortran.build_variables, float, range=(0.0, 10.0) + ), + "dr_fw_wall": InputVariable(fortran.fwbs_variables, float, range=(0.0005, 0.1)), + "dr_pf_cryostat": InputVariable(fortran.fwbs_variables, float, range=(0.1, 5.0)), + "dr_shld_blkt_gap": InputVariable(fortran.build_variables, float, range=(0.0, 5.0)), + "dr_shld_inboard": InputVariable(fortran.build_variables, float, range=(0.0, 10.0)), + "dr_shld_outboard": InputVariable( + fortran.build_variables, float, range=(0.0, 10.0) + ), + "dr_shld_thermal_inboard": InputVariable( + fortran.build_variables, float, range=(0.0, 10.0) + ), + "dr_shld_thermal_outboard": InputVariable( + fortran.build_variables, float, range=(0.0, 10.0) + ), + "dr_shld_vv_gap_inboard": InputVariable( + fortran.build_variables, float, range=(0.0, 10.0) + ), + "dr_tf_inboard": InputVariable(fortran.build_variables, float, range=(0.0, 10.0)), + "dr_tf_shld_gap": InputVariable(fortran.build_variables, float, range=(0.0, 5.0)), + "dr_tf_wp": InputVariable(fortran.tfcoil_variables, float, range=(0.0, 10.0)), + "dr_vv_inboard": InputVariable(fortran.build_variables, float, range=(0.0, 10.0)), + "dr_vv_outboard": InputVariable(fortran.build_variables, float, range=(0.0, 10.0)), + "drtop": InputVariable(fortran.tfcoil_variables, float, range=(-1.5, 1.5)), + "drveff": InputVariable(fortran.ife_variables, float, range=(0.01, 1.0)), + "dtlife": InputVariable(fortran.cost_variables, float, range=(0.0, 15.0)), + "dtstor": InputVariable(fortran.pulse_variables, float, range=(50.0, 500.0)), + "dx_fw_module": InputVariable(fortran.fwbs_variables, float, range=(0.0005, 0.1)), + "dz_tf_cryostat": InputVariable( + fortran.buildings_variables, float, range=(0.0, 20.0) + ), + "dztop": InputVariable(fortran.tfcoil_variables, float, range=(-0.5, 0.5)), + "edrive": InputVariable( + fortran.ife_variables, float, range=(100000.0, 5000000000.0) + ), + "eff_tf_cryo": InputVariable(fortran.tfcoil_variables, float, range=(0.0, 1.0)), + "ejima_coeff": InputVariable(fortran.physics_variables, float, range=(0.1, 1.0)), + "elecdist_h": InputVariable(fortran.buildings_variables, float, range=(1.0, 100.0)), + "elecdist_l": InputVariable( + fortran.buildings_variables, float, range=(10.0, 1000.0) + ), + "elecdist_w": InputVariable( + fortran.buildings_variables, float, range=(10.0, 1000.0) + ), + "elecload_h": InputVariable(fortran.buildings_variables, float, range=(1.0, 100.0)), + "elecload_l": InputVariable( + fortran.buildings_variables, float, range=(10.0, 1000.0) + ), + "elecload_w": InputVariable( + fortran.buildings_variables, float, range=(10.0, 1000.0) + ), + "elecstore_h": InputVariable( + fortran.buildings_variables, float, range=(1.0, 100.0) + ), + "elecstore_l": InputVariable( + fortran.buildings_variables, float, range=(10.0, 1000.0) + ), + "elecstore_w": InputVariable( + fortran.buildings_variables, float, range=(10.0, 1000.0) + ), + "emult": InputVariable(fortran.fwbs_variables, float, range=(1.0, 2.0)), + "esbldgm3": InputVariable( + fortran.buildings_variables, float, range=(1000.0, 1000000.0) + ), + "etaech": InputVariable(fortran.current_drive_variables, float, range=(0.0, 1.0)), + "etahtp": InputVariable(fortran.fwbs_variables, float, range=(0.1, 1.0)), + "etaiso": InputVariable(fortran.fwbs_variables, float, range=(0.1, 1.0)), + "etalh": InputVariable(fortran.current_drive_variables, float, range=(0.0, 1.0)), + "etali": InputVariable(fortran.ife_variables, float, range=(0.0, 1.0)), + "etanbi": InputVariable(fortran.current_drive_variables, float, range=(0.0, 1.0)), + "etapsu": InputVariable(fortran.pfcoil_variables, float, range=(0.0, 1.0)), + "etapump": InputVariable(fortran.tfcoil_variables, float, range=(0.0, 1.0)), + "etatf": InputVariable(fortran.heat_transport_variables, float, range=(0.0, 1.0)), + "etath": InputVariable(fortran.heat_transport_variables, float, range=(0.0, 1.0)), + "eyoung_al": InputVariable(fortran.tfcoil_variables, float, range=(0.0, 1.0)), + "eyoung_cond_axial": InputVariable( + fortran.tfcoil_variables, float, range=(0.0, 10000000000000.0) + ), + "eyoung_cond_trans": InputVariable( + fortran.tfcoil_variables, float, range=(0.0, 10000000000000.0) + ), + "eyoung_ins": InputVariable( + fortran.tfcoil_variables, float, range=(100000000.0, 10000000000000.0) + ), + "eyoung_res_tf_buck": InputVariable( + fortran.tfcoil_variables, float, range=(1e-10, 1000000000000.0) + ), + "eyoung_steel": InputVariable( + fortran.tfcoil_variables, float, range=(100000000.0, 10000000000000.0) + ), + "f_a_tf_cool_outboard": InputVariable( + fortran.tfcoil_variables, float, range=(0.0, 1.0) + ), + "f_alpha_energy_confinement_min": InputVariable( + fortran.constraint_variables, float, range=(1.0, 100.0) + ), + "f_asym": InputVariable(fortran.stellarator_variables, float, range=(0.9, 2.0)), + "f_avspace": InputVariable(fortran.build_variables, float, range=(0.001, 10.0)), + "f_coppera_m2": InputVariable(fortran.rebco_variables, float, range=(0.001, 10.0)), + "f_copperaoh_m2": InputVariable(fortran.rebco_variables, float, range=(0.001, 1.0)), + "f_crypmw": InputVariable( + fortran.heat_transport_variables, float, range=(0.0, 100.0) + ), + "f_fw_peak": InputVariable(fortran.fwbs_variables, float, range=(1.0, 100.0)), + "f_fw_rad_max": InputVariable(fortran.constraint_variables, float, range=(0.1, 10)), + "f_nd_alpha_electron": InputVariable( + fortran.physics_variables, float, range=(1e-12, 1.0) + ), + "f_nd_beam_electron": InputVariable( + fortran.physics_variables, float, range=(0.0, 1.0) + ), + "f_nd_protium_electrons": InputVariable( + fortran.physics_variables, float, range=(0.0, 1.0) + ), + "f_neut_shield": InputVariable(fortran.fwbs_variables, float, range=(0.0, 1.0)), + "f_nuc_pow_bz_struct": InputVariable( + fortran.fwbs_variables, float, range=(0.0, 1.0) + ), + "f_r_cp": InputVariable(fortran.build_variables, float, range=(1.0, 100.0)), + "f_rad": InputVariable(fortran.stellarator_variables, float, range=(0.0, 1.0)), + "f_sync_reflect": InputVariable(fortran.physics_variables, float, range=(0.0, 1.0)), + "f_t_turn_tf": InputVariable(fortran.tfcoil_variables, float, range=(0.0, 1.0)), + "f_tritium": InputVariable(fortran.physics_variables, float, range=(0.0, 1.0)), + "f_tritium_beam": InputVariable( + fortran.current_drive_variables, float, range=(0.0, 1.0) + ), + "f_vforce_inboard": InputVariable( + fortran.tfcoil_variables, float, range=(0.0, 1.0) + ), + "f_w": InputVariable(fortran.stellarator_variables, float, range=(0.1, 1.0)), + "f_z_cryostat": InputVariable(fortran.build_variables, float, range=(2.0, 10.0)), + "falpha_energy_confinement": InputVariable( + fortran.constraint_variables, float, range=(0.001, 1.0) + ), + "fauxbop": InputVariable(fortran.ife_variables, float, range=(0.0, 1.0)), + "fauxmn": InputVariable(fortran.constraint_variables, float, range=(0.001, 10.0)), + "favail": InputVariable(fortran.cost_variables, float, range=(0.0, 1.0)), + "fbeta_max": InputVariable( + fortran.constraint_variables, float, range=(0.001, 10.0) + ), + "fbeta_min": InputVariable( + fortran.constraint_variables, float, range=(0.001, 10.0) + ), + "fbeta_poloidal": InputVariable( + fortran.constraint_variables, float, range=(0.001, 10.0) + ), + "fbeta_poloidal_eps": InputVariable( + fortran.constraint_variables, float, range=(0.001, 10.0) + ), + "fblbe": InputVariable(fortran.fwbs_variables, float, range=(0.0, 1.0)), + "fblbreed": InputVariable(fortran.fwbs_variables, float, range=(0.0, 1.0)), + "fblhebmi": InputVariable(fortran.fwbs_variables, float, range=(0.0, 1.0)), + "fblhebmo": InputVariable(fortran.fwbs_variables, float, range=(0.0, 1.0)), + "fblhebpi": InputVariable(fortran.fwbs_variables, float, range=(0.0, 1.0)), + "fblhebpo": InputVariable(fortran.fwbs_variables, float, range=(0.0, 1.0)), + "fblli": InputVariable(fortran.fwbs_variables, float, range=(0.0, 1.0)), + "fblli2o": InputVariable(fortran.fwbs_variables, float, range=(0.0, 1.0)), + "fbllipb": InputVariable(fortran.fwbs_variables, float, range=(0.0, 1.0)), + "fblss": InputVariable(fortran.fwbs_variables, float, range=(0.0, 1.0)), + "fblvd": InputVariable(fortran.fwbs_variables, float, range=(0.0, 1.0)), + "fb_cs_limit_max": InputVariable( + fortran.pfcoil_variables, float, range=(0.01, 1.0) + ), + "fbreed": InputVariable(fortran.ife_variables, float, range=(0.0, 0.999)), + "fburn": InputVariable(fortran.ife_variables, float, range=(0.01, 1.0)), + "fc_building_l": InputVariable( + fortran.buildings_variables, float, range=(10.0, 1000.0) + ), + "fc_building_w": InputVariable( + fortran.buildings_variables, float, range=(10.0, 1000.0) + ), + "fcap0": InputVariable(fortran.cost_variables, float, range=(1.0, 1.5)), + "fcap0cp": InputVariable(fortran.cost_variables, float, range=(1.0, 1.5)), + "fcdfuel": InputVariable(fortran.cost_variables, float, range=(0.0, 1.0)), + "f_j_cs_start_pulse_end_flat_top": InputVariable( + fortran.pfcoil_variables, float, range=(0.0, 1.0) + ), + "fcontng": InputVariable(fortran.cost_variables, float, range=(0.0, 1.0)), + "fcoolcp": InputVariable(fortran.tfcoil_variables, float, range=(0.0, 1.0)), + "fcqt": InputVariable(fortran.constraint_variables, float, range=(0.001, 1.0)), + "fcr0": InputVariable(fortran.cost_variables, float, range=(0.0, 1.0)), + "fcspc": InputVariable(fortran.build_variables, float, range=(0.0, 1.0)), + "fcuohsu": InputVariable(fortran.pfcoil_variables, float, range=(0.0, 1.0)), + "fcupfsu": InputVariable(fortran.pfcoil_variables, float, range=(0.0, 1.0)), + "fcutfsu": InputVariable(fortran.tfcoil_variables, float, range=(0.0, 1.0)), + "fdene": InputVariable(fortran.constraint_variables, float, range=(0.001, 10.0)), + "fdfs": InputVariable(fortran.divertor_variables, float, range=(0.0, 20.0)), + "fdiv": InputVariable(fortran.fwbs_variables, float, range=(0.0, 1.0)), + "fdiva": InputVariable(fortran.divertor_variables, float, range=(0.1, 2.0)), + "fdivcol": InputVariable(fortran.constraint_variables, float, range=(0.001, 10.0)), + "fdivwet": InputVariable(fortran.stellarator_variables, float, range=(0.01, 1.0)), + "fdtmp": InputVariable(fortran.constraint_variables, float, range=(0.001, 10.0)), + "fecrh_ignition": InputVariable( + fortran.constraint_variables, float, range=(0.001, 10.0) + ), + "feffcd": InputVariable(fortran.current_drive_variables, float, range=(0.0, 20.0)), + "fflutf": InputVariable(fortran.constraint_variables, float, range=(0.001, 10.0)), + "ffuspow": InputVariable(fortran.constraint_variables, float, range=(0.001, 10.0)), + "fgamcd": InputVariable(fortran.constraint_variables, float, range=(0.001, 10.0)), + "fhcd": InputVariable(fortran.fwbs_variables, float, range=(0.0, 1.0)), + "fhldiv": InputVariable(fortran.constraint_variables, float, range=(0.001, 10.0)), + "fhole": InputVariable(fortran.fwbs_variables, float, range=(0.0, 1.0)), + "fhts": InputVariable(fortran.tfcoil_variables, float, range=(0.01, 1.0)), + "fififi": InputVariable(fortran.divertor_variables, float, range=(1e-06, 1.0)), + "fiooic": InputVariable(fortran.constraint_variables, float, range=(0.001, 10.0)), + "fipir": InputVariable(fortran.constraint_variables, float, range=(0.001, 10.0)), + "fjohc": InputVariable(fortran.constraint_variables, float, range=(0.001, 10.0)), + "fjohc0": InputVariable(fortran.constraint_variables, float, range=(0.001, 10.0)), + "fjprot": InputVariable(fortran.constraint_variables, float, range=(0.001, 10.0)), + "fkind": InputVariable(fortran.cost_variables, float, range=(0.5, 1.0)), + "fl_h_threshold": InputVariable( + fortran.constraint_variables, float, range=(0.001, 1000000.0) + ), + "flirad": InputVariable(fortran.ife_variables, float, range=(0.0, 10.0)), + "flpitch": InputVariable( + fortran.stellarator_variables, float, range=(0.0001, 0.01) + ), + "flux_exp": InputVariable(fortran.divertor_variables, float, range=(0.0, 10.0)), + "fmaxvvstress": InputVariable( + fortran.constraint_variables, float, range=(0.001, 1.0) + ), + "fmgdmw": InputVariable( + fortran.heat_transport_variables, float, range=(0.0, 100.0) + ), + "fmva": InputVariable(fortran.constraint_variables, float, range=(0.001, 10.0)), + "fnbshinef": InputVariable( + fortran.constraint_variables, float, range=(0.001, 10.0) + ), + "fncycle": InputVariable(fortran.constraint_variables, float, range=(1e-08, 1.0)), + "fndt": InputVariable(fortran.buildings_variables, float, range=(0.0, 10.0)), + "fne0": InputVariable(fortran.physics_variables, float, range=(0.001, 1.0)), + "fniterpump": InputVariable( + fortran.constraint_variables, float, range=(0.001, 10.0) + ), + "foh_stress": InputVariable( + fortran.constraint_variables, float, range=(0.001, 1.0) + ), + "forbitloss": InputVariable( + fortran.current_drive_variables, float, range=(0.0, 0.999) + ), + "fpdivlim": InputVariable(fortran.physics_variables, float, range=(0.001, 1.0)), + "fpeakb": InputVariable(fortran.constraint_variables, float, range=(0.001, 10.0)), + "fpinj": InputVariable(fortran.constraint_variables, float, range=(0.001, 10.0)), + "fpnetel": InputVariable(fortran.constraint_variables, float, range=(0.001, 10.0)), + "fpoloidalpower": InputVariable( + fortran.constraint_variables, float, range=(0.001, 1.0) + ), + "fportsz": InputVariable(fortran.constraint_variables, float, range=(0.001, 10.0)), + "fpsep": InputVariable(fortran.constraint_variables, float, range=(0.001, 1.0)), + "fpsepbqar": InputVariable(fortran.constraint_variables, float, range=(0.001, 1.0)), + "fpsepr": InputVariable(fortran.constraint_variables, float, range=(0.001, 10.0)), + "fptemp": InputVariable(fortran.constraint_variables, float, range=(0.001, 10.0)), + "fptfnuc": InputVariable(fortran.constraint_variables, float, range=(0.001, 10.0)), + "fpumpblkt": InputVariable( + fortran.heat_transport_variables, float, range=(0.0, 0.2) + ), + "fpumpdiv": InputVariable( + fortran.heat_transport_variables, float, range=(0.0, 0.2) + ), + "fpumpfw": InputVariable(fortran.heat_transport_variables, float, range=(0.0, 0.2)), + "fpumpshld": InputVariable( + fortran.heat_transport_variables, float, range=(0.0, 0.2) + ), + "fq": InputVariable(fortran.constraint_variables, float, range=(0.001, 10.0)), + "fqval": InputVariable(fortran.constraint_variables, float, range=(0.001, 10.0)), + "fr_conducting_wall": InputVariable( + fortran.constraint_variables, float, range=(0.001, 10.0) + ), + "fracture_toughness": InputVariable( + fortran.cs_fatigue_variables, float, range=(0.1, 100000000.0) + ), + "fradpwr": InputVariable(fortran.constraint_variables, float, range=(0.0, 1.0)), + "fradwall": InputVariable(fortran.constraint_variables, float, range=(0.001, 1.0)), + "frbeam": InputVariable(fortran.current_drive_variables, float, range=(0.5, 2.0)), + "freinke": InputVariable(fortran.constraint_variables, float, range=(0.001, 1.0)), + "frhocp": InputVariable(fortran.tfcoil_variables, float, range=(0.01, 5.0)), + "frholeg": InputVariable(fortran.tfcoil_variables, float, range=(0.01, 5.0)), + "frminor": InputVariable(fortran.constraint_variables, float, range=(0.001, 10.0)), + "frrmax": InputVariable(fortran.ife_variables, float, range=(1e-06, 1.0)), + "frrp": InputVariable(fortran.divertor_variables, float, range=(0.0, 1.0)), + "fseppc": InputVariable( + fortran.build_variables, float, range=(1000000.0, 1000000000.0) + ), + "fstr_wp": InputVariable(fortran.constraint_variables, float, range=(1e-09, 10.0)), + "fstrcase": InputVariable(fortran.constraint_variables, float, range=(0.001, 10.0)), + "fstrcond": InputVariable(fortran.constraint_variables, float, range=(0.001, 10.0)), + "ft_burn": InputVariable(fortran.constraint_variables, float, range=(0.001, 10.0)), + "ft_current_ramp_up": InputVariable( + fortran.constraint_variables, float, range=(0.001, 10.0) + ), + "ftbr": InputVariable(fortran.constraint_variables, float, range=(0.001, 10.0)), + "ftcycl": InputVariable(fortran.constraint_variables, float, range=(0.001, 10.0)), + "ftmargoh": InputVariable(fortran.constraint_variables, float, range=(0.001, 10.0)), + "ftmargtf": InputVariable(fortran.constraint_variables, float, range=(0.001, 10.0)), + "ftoroidalgap": InputVariable(fortran.tfcoil_variables, float, range=(0.001, 10.0)), + "ftpeak": InputVariable(fortran.constraint_variables, float, range=(0.001, 10.0)), + "fvdump": InputVariable(fortran.constraint_variables, float, range=(0.001, 10.0)), + "fvoldw": InputVariable(fortran.fwbs_variables, float, range=(0.0, 10.0)), + "fvolsi": InputVariable(fortran.fwbs_variables, float, range=(0.0, 10.0)), + "fvolso": InputVariable(fortran.fwbs_variables, float, range=(0.0, 10.0)), + "fvs": InputVariable(fortran.constraint_variables, float, range=(0.001, 10.0)), + "fvsbrnni": InputVariable(fortran.physics_variables, float, range=(0.0, 1.0)), + "fvs_cs_pf_total_ramp": InputVariable( + fortran.pfcoil_variables, float, range=(0.001, 10.0) + ), + "fvvhe": InputVariable(fortran.constraint_variables, float, range=(0.001, 10.0)), + "fw_armour_thickness": InputVariable( + fortran.fwbs_variables, float, range=(0.0, 1.0) + ), + "fw_th_conductivity": InputVariable( + fortran.fwbs_variables, float, range=(1.0, 100.0) + ), + "fwalld": InputVariable(fortran.constraint_variables, float, range=(0.001, 10.0)), + "fwbs_nref": InputVariable( + fortran.cost_variables, float, range=(1000.0, 100000000.0) + ), + "fwbs_nu": InputVariable( + fortran.cost_variables, float, range=(1000.0, 100000000.0) + ), + "fwbs_prob_fail": InputVariable(fortran.cost_variables, float, range=(0.0, 1.0)), + "fwbs_umain_time": InputVariable(fortran.cost_variables, float, range=(0.1, 2.0)), + "fwclfr": InputVariable(fortran.fwbs_variables, float, range=(0.0, 1.0)), + "fwdr": InputVariable(fortran.ife_variables, float, range=(0.0, 10.0)), + "fwdzl": InputVariable(fortran.ife_variables, float, range=(0.0, 10.0)), + "fwdzu": InputVariable(fortran.ife_variables, float, range=(0.0, 10.0)), + "fzactual": InputVariable(fortran.reinke_variables, float, range=(0.0, 1.0)), + "fzeffmax": InputVariable(fortran.constraint_variables, float, range=(0.001, 1.0)), + "gamma_ecrh": InputVariable( + fortran.current_drive_variables, float, range=(0.0, 1.0) + ), + "gamma_he": InputVariable( + fortran.primary_pumping_variables, float, range=(1.0, 2.0) + ), + "gammax": InputVariable(fortran.constraint_variables, float, range=(0.01, 10.0)), + "gapomin": InputVariable(fortran.build_variables, float, range=(0.0, 10.0)), + "gas_buildings_h": InputVariable( + fortran.buildings_variables, float, range=(1.0, 100.0) + ), + "gas_buildings_l": InputVariable( + fortran.buildings_variables, float, range=(10.0, 1000.0) + ), + "gas_buildings_w": InputVariable( + fortran.buildings_variables, float, range=(10.0, 1000.0) + ), + "ground_clrnc": InputVariable( + fortran.buildings_variables, float, range=(0.0, 10.0) + ), + "harnum": InputVariable(fortran.current_drive_variables, float, range=(1.0, 10.0)), + "hastelloy_thickness": InputVariable( + fortran.rebco_variables, float, range=(1e-08, 0.001) + ), + "hccl": InputVariable(fortran.buildings_variables, float, range=(0.0, 10.0)), + "hcd_building_h": InputVariable( + fortran.buildings_variables, float, range=(1.0, 100.0) + ), + "hcd_building_l": InputVariable( + fortran.buildings_variables, float, range=(10.0, 1000.0) + ), + "hcd_building_w": InputVariable( + fortran.buildings_variables, float, range=(10.0, 1000.0) + ), + "hcwt": InputVariable(fortran.buildings_variables, float, range=(0.0, 10.0)), + "heat_sink_h": InputVariable( + fortran.buildings_variables, float, range=(1.0, 100.0) + ), + "heat_sink_l": InputVariable( + fortran.buildings_variables, float, range=(10.0, 1000.0) + ), + "heat_sink_w": InputVariable( + fortran.buildings_variables, float, range=(10.0, 1000.0) + ), + "hfact": InputVariable(fortran.physics_variables, float, range=(0.01, 10.0)), + "hldiv": InputVariable(fortran.divertor_variables, float, range=(0.0, 10.0)), + "hldivlim": InputVariable(fortran.divertor_variables, float, range=(0.1, 20.0)), + "hot_sepdist": InputVariable(fortran.buildings_variables, float, range=(0.0, 10.0)), + "hotcell_h": InputVariable(fortran.buildings_variables, float, range=(1.0, 100.0)), + "htpmw_blkt": InputVariable( + fortran.heat_transport_variables, float, range=(0.0, 1000.0) + ), + "htpmw_div": InputVariable( + fortran.heat_transport_variables, float, range=(0.0, 1000.0) + ), + "htpmw_fw": InputVariable( + fortran.heat_transport_variables, float, range=(0.0, 1000.0) + ), + "htpmw_ife": InputVariable(fortran.ife_variables, float, range=(0.0, 1000.0)), + "htpmw_min": InputVariable( + fortran.heat_transport_variables, float, range=(0.0, 500.0) + ), + "htpmw_shld": InputVariable( + fortran.heat_transport_variables, float, range=(0.0, 1000.0) + ), + "hw_storage_h": InputVariable( + fortran.buildings_variables, float, range=(1.0, 100.0) + ), + "hw_storage_l": InputVariable( + fortran.buildings_variables, float, range=(10.0, 1000.0) + ), + "hw_storage_w": InputVariable( + fortran.buildings_variables, float, range=(10.0, 1000.0) + ), + "ilw_smelter_h": InputVariable( + fortran.buildings_variables, float, range=(1.0, 100.0) + ), + "ilw_smelter_l": InputVariable( + fortran.buildings_variables, float, range=(10.0, 1000.0) + ), + "ilw_smelter_w": InputVariable( + fortran.buildings_variables, float, range=(10.0, 1000.0) + ), + "ilw_storage_h": InputVariable( + fortran.buildings_variables, float, range=(1.0, 100.0) + ), + "ilw_storage_l": InputVariable( + fortran.buildings_variables, float, range=(10.0, 1000.0) + ), + "ilw_storage_w": InputVariable( + fortran.buildings_variables, float, range=(10.0, 1000.0) + ), + "ind_plasma_internal_norm": InputVariable( + fortran.physics_variables, float, range=(0.0, 10.0) + ), + "initialpressure": InputVariable( + fortran.vacuum_variables, float, range=(1e-06, 10000.0) + ), + "inlet_temp": InputVariable(fortran.fwbs_variables, float, range=(200.0, 600.0)), + "inlet_temp_liq": InputVariable( + fortran.fwbs_variables, float, range=(508.0, 1500.0) + ), + "iotabar": InputVariable(fortran.stellarator_variables, float, range=(0.1, 10.0)), + "j_tf_bus": InputVariable( + fortran.tfcoil_variables, float, range=(10000.0, 100000000.0) + ), + "kappa": InputVariable(fortran.physics_variables, float, range=(0.99, 5.0)), + "kappa95": InputVariable(fortran.physics_variables, float, range=(0.99, 5.0)), + "ksic": InputVariable(fortran.divertor_variables, float, range=(0.0, 2.0)), + "layer_ins": InputVariable(fortran.tfcoil_variables, float, range=(0.0, 0.1)), + "ld_ratio_cst": InputVariable(fortran.pfcoil_variables, float, range=(0.0, 5.0)), + "len_fw_channel": InputVariable( + fortran.fwbs_variables, float, range=(0.001, 1000.0) + ), + "len_tf_bus": InputVariable(fortran.tfcoil_variables, float, range=(0.01, 1000.0)), + "lhat": InputVariable(fortran.reinke_variables, float, range=(1.0, 15.0)), + "li6enrich": InputVariable(fortran.fwbs_variables, float, range=(7.4, 100.0)), + "life_dpa": InputVariable(fortran.cost_variables, float, range=(10.0, 100.0)), + "llw_storage_h": InputVariable( + fortran.buildings_variables, float, range=(1.0, 100.0) + ), + "llw_storage_l": InputVariable( + fortran.buildings_variables, float, range=(10.0, 1000.0) + ), + "llw_storage_w": InputVariable( + fortran.buildings_variables, float, range=(10.0, 1000.0) + ), + "m_s_limit": InputVariable(fortran.physics_variables, float, range=(0.0, 1.0)), + "magnet_pulse_h": InputVariable( + fortran.buildings_variables, float, range=(1.0, 100.0) + ), + "magnet_pulse_l": InputVariable( + fortran.buildings_variables, float, range=(10.0, 1000.0) + ), + "magnet_pulse_w": InputVariable( + fortran.buildings_variables, float, range=(10.0, 1000.0) + ), + "magnet_trains_h": InputVariable( + fortran.buildings_variables, float, range=(1.0, 100.0) + ), + "magnet_trains_l": InputVariable( + fortran.buildings_variables, float, range=(10.0, 1000.0) + ), + "magnet_trains_w": InputVariable( + fortran.buildings_variables, float, range=(10.0, 1000.0) + ), + "maint_cont_h": InputVariable( + fortran.buildings_variables, float, range=(1.0, 100.0) + ), + "maint_cont_l": InputVariable( + fortran.buildings_variables, float, range=(10.0, 1000.0) + ), + "maint_cont_w": InputVariable( + fortran.buildings_variables, float, range=(10.0, 1000.0) + ), + "maintenance_fwbs": InputVariable(fortran.cost_variables, float, range=(0.0, 1.0)), + "maintenance_gen": InputVariable(fortran.cost_variables, float, range=(0.0, 1.0)), + "max_gyrotron_frequency": InputVariable( + fortran.stellarator_variables, float, range=(1000000000.0, 100000000000000.0) + ), + "max_vv_stress": InputVariable( + fortran.tfcoil_variables, float, range=(100000.0, 500000000.0) + ), + "maxpoloidalpower": InputVariable( + fortran.pf_power_variables, float, range=(0.0, 2000.0) + ), + "pflux_fw_rad_max": InputVariable( + fortran.constraint_variables, float, range=(0.1, 10.0) + ), + "mbvfac": InputVariable(fortran.buildings_variables, float, range=(0.9, 3.0)), + "mcdriv": InputVariable(fortran.ife_variables, float, range=(0.1, 10.0)), + "mvalim": InputVariable(fortran.constraint_variables, float, range=(0.0, 1000.0)), + "n_cycle_min": InputVariable( + fortran.cs_fatigue_variables, float, range=(0.0, 100000000.0) + ), + "n_tf_coils": InputVariable(fortran.tfcoil_variables, float, range=(0.0, 100.0)), + "n_tf_turn": InputVariable(fortran.tfcoil_variables, float, range=(0.0, 100.0)), + "nbi_sys_l": InputVariable( + fortran.buildings_variables, float, range=(10.0, 1000.0) + ), + "nbi_sys_w": InputVariable( + fortran.buildings_variables, float, range=(10.0, 1000.0) + ), + "nbshield": InputVariable( + fortran.current_drive_variables, float, range=(0.01, 0.5) + ), + "nbshinefmax": InputVariable( + fortran.constraint_variables, float, range=(1e-20, 0.1) + ), + "neped": InputVariable(fortran.physics_variables, float, range=(0.0, 1e21)), + "nesep": InputVariable(fortran.physics_variables, float, range=(0.0, 1e21)), + "nflutfmax": InputVariable(fortran.constraint_variables, float, range=(1e20, 1e24)), + "oacdcp": InputVariable( + fortran.tfcoil_variables, float, range=(10000.0, 1000000000.0) + ), + "f_a_cs_steel": InputVariable( + fortran.pfcoil_variables, float, range=(0.001, 0.999) + ), + "f_z_cs_tf_internal": InputVariable( + fortran.pfcoil_variables, float, range=(0.0, 2.0) + ), + "omegan": InputVariable(fortran.divertor_variables, float, range=(0.1, 10.0)), + "outgasfactor": InputVariable( + fortran.vacuum_variables, float, range=(1e-06, 1000.0) + ), + "outgasindex": InputVariable( + fortran.vacuum_variables, float, range=(1e-06, 1000.0) + ), + "outlet_temp": InputVariable(fortran.fwbs_variables, float, range=(450.0, 900.0)), + "outlet_temp_liq": InputVariable( + fortran.fwbs_variables, float, range=(508.0, 1500.0) + ), + "p_he": InputVariable( + fortran.primary_pumping_variables, float, range=(0.0, 100000000.0) + ), + "paris_coefficient": InputVariable( + fortran.cs_fatigue_variables, float, range=(1e-20, 10.0) + ), + "paris_power_law": InputVariable( + fortran.cs_fatigue_variables, float, range=(1.0, 10.0) + ), + "pbase": InputVariable(fortran.vacuum_variables, float, range=(1e-08, 0.001)), + "pdivtlim": InputVariable(fortran.constraint_variables, float, range=(0.1, 1000.0)), + "pdrive": InputVariable( + fortran.ife_variables, float, range=(1000000.0, 200000000.0) + ), + "pfbldgm3": InputVariable( + fortran.buildings_variables, float, range=(10000.0, 1000000.0) + ), + "rho_pf_coil": InputVariable(fortran.pfcoil_variables, float, range=(0.0, 0.0001)), + "pfusife": InputVariable(fortran.ife_variables, float, range=(0.0, 10000.0)), + "pheat": InputVariable(fortran.current_drive_variables, float, range=(0.0, 1000.0)), + "pheatfix": InputVariable( + fortran.current_drive_variables, float, range=(0.0, 1000.0) + ), + "pibv": InputVariable(fortran.buildings_variables, float, range=(1000.0, 100000.0)), + "pifecr": InputVariable(fortran.ife_variables, float, range=(0.0, 100.0)), + "pinjalw": InputVariable( + fortran.current_drive_variables, float, range=(0.0, 1000.0) + ), + "pinjfixmw": InputVariable( + fortran.current_drive_variables, float, range=(0.0, 1000.0) + ), + "pinjmax": InputVariable( + fortran.heat_transport_variables, float, range=(0.0, 1000.0) + ), + "plasma_res_factor": InputVariable( + fortran.physics_variables, float, range=(0.0, 1.0) + ), + "plasma_square": InputVariable(fortran.physics_variables, float, range=(-5.0, 5.0)), + "plleni": InputVariable(fortran.build_variables, float, range=(0.1, 10.0)), + "plleno": InputVariable(fortran.build_variables, float, range=(0.1, 10.0)), + "plsepi": InputVariable(fortran.build_variables, float, range=(0.1, 10.0)), + "plsepo": InputVariable(fortran.build_variables, float, range=(0.1, 10.0)), + "pnetelin": InputVariable( + fortran.constraint_variables, float, range=(1.0, 10000.0) + ), + "pnuc_fw_ratio_dcll": InputVariable( + fortran.fwbs_variables, float, range=(0.0, 1.0) + ), + "poisson_al": InputVariable(fortran.tfcoil_variables, float, range=(0.0, 1.0)), + "poisson_copper": InputVariable(fortran.tfcoil_variables, float, range=(0.0, 1.0)), + "poisson_steel": InputVariable(fortran.tfcoil_variables, float, range=(0.0, 1.0)), + "powfmax": InputVariable(fortran.constraint_variables, float, range=(1.0, 10000.0)), + "prdiv": InputVariable(fortran.vacuum_variables, float, range=(0.0, 10.0)), + "pres_fw_coolant": InputVariable( + fortran.fwbs_variables, float, range=(100000.0, 100000000.0) + ), + "prn1": InputVariable(fortran.divertor_variables, float, range=(0.0, 1.0)), + "psepbqarmax": InputVariable( + fortran.constraint_variables, float, range=(1.0, 50.0) + ), + "pseprmax": InputVariable(fortran.constraint_variables, float, range=(1.0, 60.0)), + "ptargf": InputVariable(fortran.ife_variables, float, range=(0.1, 100.0)), + "ptempalw": InputVariable(fortran.tfcoil_variables, float, range=(4.0, 573.15)), + "ptfnucmax": InputVariable(fortran.constraint_variables, float, range=(1e-06, 1.0)), + "pulsetimings": InputVariable(fortran.times_variables, float, range=(0.0, 1.0)), + "pumpareafraction": InputVariable( + fortran.vacuum_variables, float, range=(1e-06, 1.0) + ), + "pumpspeedfactor": InputVariable( + fortran.vacuum_variables, float, range=(1e-06, 1.0) + ), + "pumpspeedmax": InputVariable( + fortran.vacuum_variables, float, range=(1e-06, 1000.0) + ), + "pumptp": InputVariable(fortran.vacuum_variables, float, range=(0.0, 1e30)), + "pwpm2": InputVariable( + fortran.heat_transport_variables, float, range=(0.0, 1000.0) + ), + "q0": InputVariable(fortran.physics_variables, float, range=(0.01, 20.0)), + "q95": InputVariable(fortran.physics_variables, float, range=(1.0, 50.0)), + "qnty_sfty_fac": InputVariable( + fortran.buildings_variables, float, range=(0.0, 10.0) + ), + "qnuc": InputVariable(fortran.fwbs_variables, float, range=(0.0, 1000000.0)), + "r_cp_top": InputVariable(fortran.build_variables, float, range=(0.001, 10.0)), + "rad_fraction_sol": InputVariable( + fortran.physics_variables, float, range=(0.0, 1.0) + ), + "radius_fw_channel": InputVariable( + fortran.fwbs_variables, float, range=(0.001, 0.5) + ), + "rat": InputVariable(fortran.vacuum_variables, float, range=(1e-10, 1e-06)), + "rbrt": InputVariable(fortran.buildings_variables, float, range=(0.0, 10.0)), + "rbvfac": InputVariable(fortran.buildings_variables, float, range=(0.9, 3.0)), + "rbwt": InputVariable(fortran.buildings_variables, float, range=(0.0, 10.0)), + "rcool": InputVariable(fortran.tfcoil_variables, float, range=(1e-06, 1.0)), + "reactor_clrnc": InputVariable( + fortran.buildings_variables, float, range=(0.0, 10.0) + ), + "reactor_fndtn_thk": InputVariable( + fortran.buildings_variables, float, range=(0.25, 25.0) + ), + "reactor_hall_h": InputVariable( + fortran.buildings_variables, float, range=(1.0, 100.0) + ), + "reactor_hall_l": InputVariable( + fortran.buildings_variables, float, range=(10.0, 1000.0) + ), + "reactor_hall_w": InputVariable( + fortran.buildings_variables, float, range=(10.0, 1000.0) + ), + "reactor_roof_thk": InputVariable( + fortran.buildings_variables, float, range=(0.25, 25.0) + ), + "reactor_wall_thk": InputVariable( + fortran.buildings_variables, float, range=(0.25, 25.0) + ), + "rebco_thickness": InputVariable( + fortran.rebco_variables, + float, + range=(1e-08, 0.0001), + additional_actions=lambda _n, rt, _i, _c: rt <= 1e-6 + or warn( + ( + "the relationship between REBCO layer thickness and current density is not linear." + "REBCO layer thicknesses > 1um should be considered an aggressive extrapolation of" + "current HTS technology and any results must be considered speculative." + ), + stacklevel=1, + ), + ), + "redun_vacp": InputVariable(fortran.cost_variables, float, range=(0.0, 100.0)), + "residual_sig_hoop": InputVariable( + fortran.cs_fatigue_variables, float, range=(0.0, 1000000000.0) + ), + "rho_tf_bus": InputVariable(fortran.tfcoil_variables, float, range=(0.0, 1e-05)), + "rho_tf_joints": InputVariable(fortran.tfcoil_variables, float, range=(0.0, 0.01)), + "rhopedn": InputVariable(fortran.physics_variables, float, range=(0.01, 1.0)), + "rhopedt": InputVariable(fortran.physics_variables, float, range=(0.01, 1.0)), + "rhopfbus": InputVariable(fortran.pfcoil_variables, float, range=(0.0, 1e-05)), + "rinboard": InputVariable(fortran.build_variables, float, range=(0.1, 10.0)), + "ripmax": InputVariable(fortran.tfcoil_variables, float, range=(0.1, 100.0)), + "rlenmax": InputVariable(fortran.divertor_variables, float, range=(0.0, 1.0)), + "rmajor": InputVariable(fortran.physics_variables, float, range=(0.1, 50.0)), + "robotics_h": InputVariable(fortran.buildings_variables, float, range=(1.0, 100.0)), + "robotics_l": InputVariable( + fortran.buildings_variables, float, range=(10.0, 1000.0) + ), + "robotics_w": InputVariable( + fortran.buildings_variables, float, range=(10.0, 1000.0) + ), + "roughness": InputVariable(fortran.fwbs_variables, float, range=(0.0, 0.01)), + "routr": InputVariable(fortran.pfcoil_variables, float, range=(-3.0, 3.0)), + "row": InputVariable(fortran.buildings_variables, float, range=(0.0, 10.0)), + "rpf1": InputVariable(fortran.pfcoil_variables, float, range=(0.0, 3.0)), + "rpf2": InputVariable(fortran.pfcoil_variables, float, range=(-3.0, 3.0)), + "rrin": InputVariable(fortran.ife_variables, float, range=(0.1, 50.0)), + "rrmax": InputVariable(fortran.ife_variables, float, range=(1.0, 50.0)), + "rxcl": InputVariable(fortran.buildings_variables, float, range=(0.0, 10.0)), + "sec_buildings_h": InputVariable( + fortran.buildings_variables, float, range=(1.0, 100.0) + ), + "sec_buildings_l": InputVariable( + fortran.buildings_variables, float, range=(10.0, 1000.0) + ), + "sec_buildings_w": InputVariable( + fortran.buildings_variables, float, range=(10.0, 1000.0) + ), + "sf_fast_fracture": InputVariable( + fortran.cs_fatigue_variables, float, range=(1.0, 10.0) + ), + "sf_radial_crack": InputVariable( + fortran.cs_fatigue_variables, float, range=(1.0, 10.0) + ), + "sf_vertical_crack": InputVariable( + fortran.cs_fatigue_variables, float, range=(1.0, 10.0) + ), + "shdr": InputVariable(fortran.ife_variables, float, range=(0.0, 10.0)), + "shdzl": InputVariable(fortran.ife_variables, float, range=(0.0, 10.0)), + "shdzu": InputVariable(fortran.ife_variables, float, range=(0.0, 10.0)), + "shear": InputVariable(fortran.stellarator_variables, float, range=(0.1, 10.0)), + "dz_shld_lower": InputVariable(fortran.build_variables, float, range=(0.0, 10.0)), + "dz_shld_upper": InputVariable(fortran.build_variables, float, range=(0.0, 10.0)), + "shmf": InputVariable(fortran.buildings_variables, float, range=(0.0, 1.0)), + "shov": InputVariable( + fortran.buildings_variables, float, range=(1000.0, 1000000.0) + ), + "sig_tf_case_max": InputVariable( + fortran.tfcoil_variables, float, range=(1000000.0, 100000000000.0) + ), + "sig_tf_wp_max": InputVariable( + fortran.tfcoil_variables, float, range=(1000000.0, 100000000000.0) + ), + "sigallpc": InputVariable( + fortran.build_variables, float, range=(0.0, 1000000000.0) + ), + "sigpfcalw": InputVariable(fortran.pfcoil_variables, float, range=(1.0, 1000.0)), + "sigpfcf": InputVariable(fortran.pfcoil_variables, float, range=(0.1, 1.0)), + "sombdr": InputVariable(fortran.ife_variables, float, range=(0.0, 10.0)), + "somtdr": InputVariable(fortran.ife_variables, float, range=(0.0, 10.0)), + "staff_buildings_area": InputVariable( + fortran.buildings_variables, float, range=(10000.0, 1000000.0) + ), + "staff_buildings_h": InputVariable( + fortran.buildings_variables, float, range=(1.0, 100.0) + ), + "startupratio": InputVariable(fortran.cost_variables, float, range=(0.0, 10.0)), + "stcl": InputVariable(fortran.buildings_variables, float, range=(0.0, 10.0)), + "str_cs_con_res": InputVariable( + fortran.tfcoil_variables, float, range=(-0.02, 0.02) + ), + "str_pf_con_res": InputVariable( + fortran.tfcoil_variables, float, range=(-0.02, 0.02) + ), + "str_tf_con_res": InputVariable( + fortran.tfcoil_variables, float, range=(-0.02, 0.02) + ), + "str_wp_max": InputVariable(fortran.tfcoil_variables, float, range=(0.0, 0.3)), + "t_between_pulse": InputVariable( + fortran.times_variables, float, range=(0.0, 100000000.0) + ), + "t_burn": InputVariable(fortran.times_variables, float, range=(0.0, 100000000.0)), + "t_burn_min": InputVariable( + fortran.constraint_variables, float, range=(0.001, 1000000.0) + ), + "t_cable_tf": InputVariable(fortran.tfcoil_variables, float, range=(0.0, 0.1)), + "t_crack_radial": InputVariable( + fortran.cs_fatigue_variables, float, range=(1e-05, 1.0) + ), + "t_crack_vertical": InputVariable( + fortran.cs_fatigue_variables, float, range=(1e-05, 1.0) + ), + "t_crit_nbti": InputVariable(fortran.tfcoil_variables, float, range=(0.0, 15.0)), + "t_current_ramp_up": InputVariable( + fortran.times_variables, float, range=(0.0, 10000.0) + ), + "t_fusion_ramp": InputVariable( + fortran.times_variables, float, range=(0.0, 10000.0) + ), + "t_in_bb": InputVariable( + fortran.primary_pumping_variables, float, range=(200.0, 1000.0) + ), + "t_out_bb": InputVariable( + fortran.primary_pumping_variables, float, range=(200.0, 1000.0) + ), + "t_precharge": InputVariable(fortran.times_variables, float, range=(0.0, 10000.0)), + "t_ramp_down": InputVariable(fortran.times_variables, float, range=(0.0, 10000.0)), + "t_structural_radial": InputVariable( + fortran.cs_fatigue_variables, float, range=(0.001, 1.0) + ), + "t_structural_vertical": InputVariable( + fortran.cs_fatigue_variables, float, range=(0.001, 1.0) + ), + "t_turn_tf": InputVariable(fortran.tfcoil_variables, float, range=(0.0, 0.1)), + "t_turn_tf_max": InputVariable(fortran.tfcoil_variables, float, range=(0.0, 1.0)), + "tape_thickness": InputVariable(fortran.rebco_variables, float, range=(0.0, 0.1)), + "tape_width": InputVariable(fortran.rebco_variables, float, range=(0.0, 0.1)), + "tauee_in": InputVariable(fortran.physics_variables, float, range=(0.0, 100.0)), + "taumax": InputVariable(fortran.physics_variables, float, range=(0.1, 100.0)), + "tauratio": InputVariable(fortran.physics_variables, float, range=(0.1, 100.0)), + "tbeamin": InputVariable(fortran.current_drive_variables, float, range=(0.0, 10.0)), + "tbeta": InputVariable(fortran.physics_variables, float, range=(0.0, 4.0)), + "tbktrepl": InputVariable(fortran.cost_variables, float, range=(0.01, 2.0)), + "tbrmin": InputVariable(fortran.constraint_variables, float, range=(0.001, 2.0)), + "tcomrepl": InputVariable(fortran.cost_variables, float, range=(0.01, 2.0)), + "tcoolin": InputVariable(fortran.tfcoil_variables, float, range=(4.0, 373.15)), + "tcritsc": InputVariable(fortran.tfcoil_variables, float, range=(1.0, 300.0)), + "tcycmn": InputVariable( + fortran.constraint_variables, float, range=(0.001, 2000000.0) + ), + "tdiv": InputVariable(fortran.divertor_variables, float, range=(0.1, 100.0)), + "tdivrepl": InputVariable(fortran.cost_variables, float, range=(0.01, 2.0)), + "tdmptf": InputVariable(fortran.tfcoil_variables, float, range=(0.1, 100.0)), + "te": InputVariable(fortran.physics_variables, float, range=(1.0, 200.0)), + "te0_ecrh_achievable": InputVariable( + fortran.stellarator_variables, float, range=(1.0, 1000.0) + ), + "temp_cp_average": InputVariable( + fortran.tfcoil_variables, float, range=(4.0, 573.15) + ), + "temp_fw_coolant_in": InputVariable( + fortran.fwbs_variables, float, range=(300.0, 1500.0) + ), + "temp_fw_coolant_out": InputVariable( + fortran.fwbs_variables, float, range=(300.0, 1500.0) + ), + "temp_fw_max": InputVariable(fortran.fwbs_variables, float, range=(500.0, 2000.0)), + "teped": InputVariable(fortran.physics_variables, float, range=(0.0, 20.0)), + "tesep": InputVariable(fortran.physics_variables, float, range=(0.0, 20.0)), + "tfcbv": InputVariable( + fortran.buildings_variables, float, range=(10000.0, 1000000.0) + ), + "tfinsgap": InputVariable(fortran.tfcoil_variables, float, range=(1e-10, 0.1)), + "tfootfi": InputVariable(fortran.build_variables, float, range=(0.2, 5.0)), + "tftmp": InputVariable(fortran.tfcoil_variables, float, range=(0.01, 293.0)), + "tgain": InputVariable(fortran.ife_variables, float, range=(1.0, 500.0)), + "th_joint_contact": InputVariable( + fortran.tfcoil_variables, float, range=(0.0, 1.0) + ), + "theta1_coil": InputVariable(fortran.tfcoil_variables, float, range=(0.1, 60.0)), + "theta1_vv": InputVariable(fortran.tfcoil_variables, float, range=(0.1, 60.0)), + "thicndut": InputVariable(fortran.tfcoil_variables, float, range=(0.0, 0.1)), + "thkcas": InputVariable(fortran.tfcoil_variables, float, range=(0.0, 1.0)), + "dz_shld_thermal": InputVariable(fortran.build_variables, float, range=(0.0, 10.0)), + "thwcndut": InputVariable(fortran.tfcoil_variables, float, range=(0.0, 0.1)), + "ti": InputVariable(fortran.physics_variables, float, range=(5.0, 50.0)), + "tinstf": InputVariable(fortran.tfcoil_variables, float, range=(0.0, 0.1)), + "tlife": InputVariable(fortran.cost_variables, float, range=(1.0, 100.0)), + "tmain": InputVariable(fortran.cost_variables, float, range=(0.0, 100.0)), + "tmargmin": InputVariable(fortran.tfcoil_variables, float, range=(0.0, 20.0)), + "tmargmin_cs": InputVariable(fortran.tfcoil_variables, float, range=(0.0, 20.0)), + "tmargmin_tf": InputVariable(fortran.tfcoil_variables, float, range=(0.0, 20.0)), + "tmax_croco": InputVariable(fortran.tfcoil_variables, float, range=(4.0, 1000.0)), + "tmaxpro": InputVariable(fortran.tfcoil_variables, float, range=(0.0, 1000.0)), + "tmpcry": InputVariable(fortran.tfcoil_variables, float, range=(0.01, 293.0)), + "tn": InputVariable(fortran.vacuum_variables, float, range=(1.0, 1000.0)), + "i_t_current_ramp_up": InputVariable(fortran.times_variables, int, choices=[0, 1]), + "transp_clrnc": InputVariable( + fortran.buildings_variables, float, range=(0.0, 10.0) + ), + "tratio": InputVariable(fortran.physics_variables, float, range=(0.0, 2.0)), + "trcl": InputVariable(fortran.buildings_variables, float, range=(0.0, 10.0)), + "triang": InputVariable(fortran.physics_variables, float, range=(-1.0, 1.0)), + "triang95": InputVariable(fortran.physics_variables, float, range=(0.0, 1.0)), + "trithtmw": InputVariable( + fortran.heat_transport_variables, float, range=(0.0, 100.0) + ), + "triv": InputVariable( + fortran.buildings_variables, float, range=(10000.0, 1000000.0) + ), + "turbine_hall_h": InputVariable( + fortran.buildings_variables, float, range=(1.0, 100.0) + ), + "turbine_hall_l": InputVariable( + fortran.buildings_variables, float, range=(10.0, 1000.0) + ), + "turbine_hall_w": InputVariable( + fortran.buildings_variables, float, range=(10.0, 1000.0) + ), + "tw_storage_h": InputVariable( + fortran.buildings_variables, float, range=(1.0, 100.0) + ), + "tw_storage_l": InputVariable( + fortran.buildings_variables, float, range=(10.0, 1000.0) + ), + "tw_storage_w": InputVariable( + fortran.buildings_variables, float, range=(10.0, 1000.0) + ), + "u_unplanned_cp": InputVariable(fortran.cost_variables, float, range=(0.0, 1.0)), + "ucblbe": InputVariable(fortran.cost_variables, float, range=(1.0, 1000.0)), + "ucblbreed": InputVariable(fortran.cost_variables, float, range=(1.0, 1000.0)), + "ucblli": InputVariable(fortran.cost_variables, float, range=(10.0, 10000.0)), + "ucblli2o": InputVariable(fortran.cost_variables, float, range=(100.0, 10000.0)), + "ucbllipb": InputVariable(fortran.cost_variables, float, range=(100.0, 10000.0)), + "ucblss": InputVariable(fortran.cost_variables, float, range=(10.0, 1000.0)), + "ucblvd": InputVariable(fortran.cost_variables, float, range=(100.0, 1000.0)), + "ucbus": InputVariable(fortran.cost_variables, float, range=(0.01, 10.0)), + "uccarb": InputVariable(fortran.ife_variables, float, range=(10.0, 1000.0)), + "uccase": InputVariable(fortran.cost_variables, float, range=(1.0, 1000.0)), + "ucconc": InputVariable(fortran.ife_variables, float, range=(0.1, 1000.0)), + "uccpcl1": InputVariable(fortran.cost_variables, float, range=(1.0, 1000.0)), + "uccpclb": InputVariable(fortran.cost_variables, float, range=(1.0, 1000.0)), + "uccry": InputVariable(fortran.cost_variables, float, range=(10000.0, 1000000.0)), + "uccryo": InputVariable(fortran.cost_variables, float, range=(1.0, 1000.0)), + "uccu": InputVariable(fortran.cost_variables, float, range=(10.0, 100.0)), + "ucdiv": InputVariable(fortran.cost_variables, float, range=(1000.0, 10000000.0)), + "ucech": InputVariable(fortran.cost_variables, float, range=(1.0, 10.0)), + "ucf1": InputVariable(fortran.cost_variables, float, range=(1000000.0, 50000000.0)), + "ucflib": InputVariable(fortran.ife_variables, float, range=(10.0, 1000.0)), + "ucfnc": InputVariable(fortran.cost_variables, float, range=(10.0, 100.0)), + "ucfuel": InputVariable(fortran.cost_variables, float, range=(1.0, 10.0)), + "uche3": InputVariable(fortran.cost_variables, float, range=(100000.0, 10000000.0)), + "uchrs": InputVariable( + fortran.cost_variables, float, range=(10000000.0, 500000000.0) + ), + "uciac": InputVariable( + fortran.cost_variables, float, range=(10000000.0, 1000000000.0) + ), + "ucich": InputVariable(fortran.cost_variables, float, range=(1.0, 10.0)), + "uclh": InputVariable(fortran.cost_variables, float, range=(1.0, 10.0)), + "ucme": InputVariable( + fortran.cost_variables, float, range=(10000000.0, 1000000000.0) + ), + "ucmisc": InputVariable( + fortran.cost_variables, float, range=(10000000.0, 50000000.0) + ), + "ucnbi": InputVariable(fortran.cost_variables, float, range=(1.0, 10.0)), + "ucpens": InputVariable(fortran.cost_variables, float, range=(1.0, 100.0)), + "ucpfb": InputVariable(fortran.cost_variables, float, range=(1.0, 1000.0)), + "ucpfbk": InputVariable(fortran.cost_variables, float, range=(1000.0, 100000.0)), + "ucpfbs": InputVariable(fortran.cost_variables, float, range=(1000.0, 10000.0)), + "ucpfcb": InputVariable(fortran.cost_variables, float, range=(1000.0, 100000.0)), + "ucpfdr1": InputVariable(fortran.cost_variables, float, range=(1.0, 1000.0)), + "ucpfic": InputVariable(fortran.cost_variables, float, range=(1000.0, 100000.0)), + "ucpfps": InputVariable(fortran.cost_variables, float, range=(1000.0, 100000.0)), + "ucrb": InputVariable(fortran.cost_variables, float, range=(100.0, 1000.0)), + "ucshld": InputVariable(fortran.cost_variables, float, range=(1.0, 100.0)), + "uctarg": InputVariable(fortran.ife_variables, float, range=(0.1, 1000.0)), + "uctfbr": InputVariable(fortran.cost_variables, float, range=(1.0, 10.0)), + "uctfbus": InputVariable(fortran.cost_variables, float, range=(1.0, 1000.0)), + "uctfps": InputVariable(fortran.cost_variables, float, range=(1.0, 1000.0)), + "uctfsw": InputVariable(fortran.cost_variables, float, range=(0.1, 10.0)), + "ucwindpf": InputVariable(fortran.cost_variables, float, range=(100.0, 1000.0)), + "ucwindtf": InputVariable(fortran.cost_variables, float, range=(100.0, 1000.0)), + "uubop": InputVariable(fortran.cost_variables, float, range=(0.005, 0.1)), + "uucd": InputVariable(fortran.cost_variables, float, range=(0.005, 0.1)), + "uudiv": InputVariable(fortran.cost_variables, float, range=(0.005, 0.1)), + "uufuel": InputVariable(fortran.cost_variables, float, range=(0.005, 0.1)), + "uufw": InputVariable(fortran.cost_variables, float, range=(0.005, 0.1)), + "uumag": InputVariable(fortran.cost_variables, float, range=(0.005, 0.1)), + "uuves": InputVariable(fortran.cost_variables, float, range=(0.005, 0.1)), + "v1dr": InputVariable(fortran.ife_variables, float, range=(0.0, 10.0)), + "v1dzl": InputVariable(fortran.ife_variables, float, range=(0.0, 10.0)), + "v1dzu": InputVariable(fortran.ife_variables, float, range=(0.0, 10.0)), + "v2dr": InputVariable(fortran.ife_variables, float, range=(0.0, 10.0)), + "v2dzl": InputVariable(fortran.ife_variables, float, range=(0.0, 10.0)), + "v2dzu": InputVariable(fortran.ife_variables, float, range=(0.0, 10.0)), + "v3dr": InputVariable(fortran.ife_variables, float, range=(0.0, 50.0)), + "v3dzl": InputVariable(fortran.ife_variables, float, range=(0.0, 30.0)), + "v3dzu": InputVariable(fortran.ife_variables, float, range=(0.0, 30.0)), + "vachtmw": InputVariable( + fortran.heat_transport_variables, float, range=(0.0, 100.0) + ), + "vcool": InputVariable(fortran.tfcoil_variables, float, range=(0.001, 100.0)), + "vdalw": InputVariable(fortran.tfcoil_variables, float, range=(0.0, 100.0)), + "vfblkt": InputVariable(fortran.fwbs_variables, float, range=(0.0, 1.0)), + "vfcblkt": InputVariable(fortran.fwbs_variables, float, range=(0.0, 1.0)), + "f_a_cs_void": InputVariable(fortran.pfcoil_variables, float, range=(0.0, 1.0)), + "vfpblkt": InputVariable(fortran.fwbs_variables, float, range=(0.0, 1.0)), + "vfshld": InputVariable(fortran.fwbs_variables, float, range=(0.0, 1.0)), + "vftf": InputVariable(fortran.tfcoil_variables, float, range=(0.0, 1.0)), + "dz_shld_vv_gap": InputVariable(fortran.build_variables, float, range=(0.0, 10.0)), + "dz_xpoint_divertor": InputVariable( + fortran.build_variables, float, range=(0.0, 10.0) + ), + "dz_fw_plasma_gap": InputVariable( + fortran.build_variables, float, range=(0.0, 10.0) + ), + "vvhealw": InputVariable(fortran.constraint_variables, float, range=(0.01, 10.0)), + "walalw": InputVariable(fortran.constraint_variables, float, range=(0.001, 50.0)), + "walker_coefficient": InputVariable( + fortran.cs_fatigue_variables, float, range=(0.1, 10.0) + ), + "wallpf": InputVariable(fortran.fwbs_variables, float, range=(1.0, 2.0)), + "warm_shop_h": InputVariable( + fortran.buildings_variables, float, range=(1.0, 100.0) + ), + "warm_shop_l": InputVariable( + fortran.buildings_variables, float, range=(10.0, 1000.0) + ), + "warm_shop_w": InputVariable( + fortran.buildings_variables, float, range=(10.0, 1000.0) + ), + "water_buildings_h": InputVariable( + fortran.buildings_variables, float, range=(1.0, 100.0) + ), + "water_buildings_l": InputVariable( + fortran.buildings_variables, float, range=(10.0, 1000.0) + ), + "water_buildings_w": InputVariable( + fortran.buildings_variables, float, range=(10.0, 1000.0) + ), + "watertemp": InputVariable(fortran.water_usage_variables, float, range=(0.0, 25.0)), + "wgt": InputVariable( + fortran.buildings_variables, float, range=(10000.0, 1000000.0) + ), + "wgt2": InputVariable( + fortran.buildings_variables, float, range=(10000.0, 1000000.0) + ), + "windspeed": InputVariable(fortran.water_usage_variables, float, range=(0.0, 10.0)), + "workshop_h": InputVariable(fortran.buildings_variables, float, range=(1.0, 100.0)), + "workshop_l": InputVariable( + fortran.buildings_variables, float, range=(10.0, 1000.0) + ), + "workshop_w": InputVariable( + fortran.buildings_variables, float, range=(10.0, 1000.0) + ), + "wsvfac": InputVariable(fortran.buildings_variables, float, range=(0.9, 3.0)), + "xi_ebw": InputVariable(fortran.current_drive_variables, float, range=(0.0, 1.0)), + "xparain": InputVariable(fortran.divertor_variables, float, range=(0.01, 10000.0)), + "xpertin": InputVariable(fortran.divertor_variables, float, range=(0.0, 10.0)), + "zeffdiv": InputVariable(fortran.divertor_variables, float, range=(0.01, 100.0)), + "zeffmax": InputVariable(fortran.constraint_variables, float, range=(1.0, 10.0)), + "blktmodel": InputVariable(fortran.fwbs_variables, int, choices=[0, 1]), + "blkttype": InputVariable(fortran.fwbs_variables, int, choices=[1, 2, 3]), + "breedmat": InputVariable(fortran.fwbs_variables, int, choices=[1, 2, 3]), + "ccl0_ma": InputVariable(fortran.pfcoil_variables, float, array=True), + "ccls_ma": InputVariable(fortran.pfcoil_variables, float, array=True), + "cfind": InputVariable(fortran.cost_variables, float, array=True), + "coolwh": InputVariable(fortran.fwbs_variables, int, choices=[1, 2]), + "copperA_m2_max": InputVariable( + fortran.rebco_variables, float, range=(1.0e6, 1.0e10) + ), + "cost_model": InputVariable(fortran.cost_variables, int, choices=[0, 1]), + "divdum": InputVariable(fortran.divertor_variables, int, choices=[0, 1]), + "dwell_pump": InputVariable(fortran.vacuum_variables, int, choices=[0, 1, 2]), + "fwbsshape": InputVariable(fortran.fwbs_variables, int, range=(1, 2)), + "hcdportsize": InputVariable(fortran.fwbs_variables, int, range=(1, 2)), + "i_bb_liq": InputVariable(fortran.fwbs_variables, int, choices=[0, 1]), + "i_beta_component": InputVariable(fortran.physics_variables, int, range=(0, 3)), + "i_beta_fast_alpha": InputVariable(fortran.physics_variables, int, choices=[0, 1]), + "i_blanket_type": InputVariable(fortran.fwbs_variables, int, choices=[1, 3, 5]), + "i_bldgs_size": InputVariable(fortran.buildings_variables, int, choices=[0, 1]), + "i_bldgs_v": InputVariable(fortran.buildings_variables, int, choices=[0, 1]), + "i_blkt_inboard": InputVariable(fortran.fwbs_variables, int, choices=[0, 1]), + "i_bootstrap_current": InputVariable(fortran.physics_variables, int, range=(1, 11)), + "i_cp_joints": InputVariable(fortran.tfcoil_variables, int, choices=[0, 1]), + "i_cp_lifetime": InputVariable(fortran.cost_variables, int, range=(0, 3)), + "i_cs_precomp": InputVariable(fortran.build_variables, int, choices=[0, 1]), + "i_cs_stress": InputVariable(fortran.pfcoil_variables, int, choices=[0, 1]), + "i_density_limit": InputVariable(fortran.physics_variables, int, range=(1, 7)), + "i_diamagnetic_current": InputVariable( + fortran.physics_variables, int, choices=[0, 1, 2] + ), + "i_hldiv": InputVariable(fortran.divertor_variables, int, choices=[0, 1, 2]), + "i_l_h_threshold": InputVariable(fortran.physics_variables, int, range=(1, 21)), + "i_pf_current": InputVariable(fortran.pfcoil_variables, int, choices=[0, 1, 2]), + "i_pfirsch_schluter_current": InputVariable( + fortran.physics_variables, int, choices=[0, 1] + ), + "i_plasma_current": InputVariable(fortran.physics_variables, int, range=(1, 9)), + "i_plasma_geometry": InputVariable(fortran.physics_variables, int, range=(0, 11)), + "i_plasma_shape": InputVariable(fortran.physics_variables, int, choices=[0, 1]), + "i_plasma_wall_gap": InputVariable(fortran.physics_variables, int, choices=[0, 1]), + "i_pulsed_plant": InputVariable(fortran.pulse_variables, int, choices=[0, 1]), + "i_r_cp_top": InputVariable(fortran.build_variables, int, choices=[0, 1, 2]), + "i_rad_loss": InputVariable(fortran.physics_variables, int, choices=[0, 1, 2]), + "i_shield_mat": InputVariable(fortran.fwbs_variables, int, choices=[0, 1]), + "i_single_null": InputVariable(fortran.physics_variables, int, choices=[0, 1]), + "i_str_wp": InputVariable(fortran.tfcoil_variables, int, choices=[0, 1]), + "i_sup_pf_shape": InputVariable(fortran.pfcoil_variables, int, choices=[0, 1]), + "i_tf_bucking": InputVariable(fortran.tfcoil_variables, int, range=(0, 3)), + "i_tf_case_geom": InputVariable(fortran.tfcoil_variables, int, choices=[0, 1]), + "i_tf_cond_eyoung_axial": InputVariable( + fortran.tfcoil_variables, int, choices=[0, 1, 2] + ), + "i_tf_cond_eyoung_trans": InputVariable( + fortran.tfcoil_variables, int, choices=[0, 1] + ), + "i_tf_sc_mat": InputVariable(fortran.tfcoil_variables, int, range=(1, 9)), + "i_tf_shape": InputVariable(fortran.tfcoil_variables, int, choices=[0, 1, 2]), + "i_tf_stress_model": InputVariable( + fortran.tfcoil_variables, int, choices=[0, 1, 2] + ), + "i_tf_sup": InputVariable(fortran.tfcoil_variables, int, choices=[0, 1, 2]), + "i_tf_tresca": InputVariable(fortran.tfcoil_variables, int, choices=[0, 1]), + "i_tf_turns_integer": InputVariable(fortran.tfcoil_variables, int, choices=[0, 1]), + "i_tf_wp_geom": InputVariable(fortran.tfcoil_variables, int, choices=[0, 1, 2]), + "iavail": InputVariable(fortran.cost_variables, int, range=(0, 3)), + "ibkt_life": InputVariable(fortran.cost_variables, int, choices=[0, 1, 2]), + "iblanket_thickness": InputVariable(fortran.fwbs_variables, int, choices=[1, 2, 3]), + "icooldual": InputVariable(fortran.fwbs_variables, int, choices=[0, 1, 2]), + "iefrf": InputVariable(fortran.current_drive_variables, int, range=(1, 13)), + "iefrffix": InputVariable(fortran.current_drive_variables, int, range=(0, 13)), + "ifci": InputVariable(fortran.fwbs_variables, int, choices=[0, 1, 2]), + "ife": InputVariable(fortran.ife_variables, int, choices=[0, 1]), + "ifedrv": InputVariable(fortran.ife_variables, int, range=(-1, 3)), + "ifetyp": InputVariable(fortran.ife_variables, int, range=(0, 4)), + "ifueltyp": InputVariable(fortran.cost_variables, int, choices=[0, 1, 2]), + "ignite": InputVariable(fortran.physics_variables, int, choices=[0, 1]), + "ims": InputVariable(fortran.fwbs_variables, int, choices=[0, 1]), + "inuclear": InputVariable(fortran.fwbs_variables, int, choices=[0, 1]), + "iohcl": InputVariable(fortran.build_variables, int, choices=[0, 1]), + "ipedestal": InputVariable(fortran.physics_variables, int, choices=[0, 1]), + "i_pf_conductor": InputVariable(fortran.pfcoil_variables, int, choices=[0, 1]), + "ipnet": InputVariable(fortran.cost_variables, int, choices=[0, 1]), + "ipowerflow": InputVariable(fortran.heat_transport_variables, int, choices=[0, 1]), + "iprimshld": InputVariable(fortran.heat_transport_variables, int, choices=[0, 1]), + "iprofile": InputVariable(fortran.physics_variables, int, range=(0, 6)), + "ipump": InputVariable(fortran.fwbs_variables, int, choices=[0, 1, 2]), + "ireactor": InputVariable(fortran.cost_variables, int, choices=[0, 1]), + "irefprop": InputVariable(fortran.fwbs_variables, int, choices=[0, 1]), + "irfcd": InputVariable(fortran.current_drive_variables, int, choices=[0, 1]), + "iscenr": InputVariable(fortran.pf_power_variables, int, range=(1, 3)), + "istell": InputVariable(fortran.stellarator_variables, int, range=(0, 6)), + "isthtr": InputVariable(fortran.stellarator_variables, int, range=(1, 3)), + "istore": InputVariable(fortran.pulse_variables, int, range=(1, 3)), + "i_cs_superconductor": InputVariable(fortran.pfcoil_variables, int, range=(1, 9)), + "i_pf_superconductor": InputVariable(fortran.pfcoil_variables, int, range=(1, 9)), + "itart": InputVariable(fortran.physics_variables, int, choices=[0, 1]), + "itartpf": InputVariable(fortran.physics_variables, int, choices=[0, 1]), + "itcycl": InputVariable(fortran.pulse_variables, int, range=(1, 3)), + "iwalld": InputVariable(fortran.physics_variables, int, range=(1, 2)), + "lsa": InputVariable(fortran.cost_variables, int, range=(1, 4)), + "m_res": InputVariable(fortran.stellarator_variables, int, range=(1, 10)), + "n_layer": InputVariable(fortran.tfcoil_variables, int, range=(1, 100)), + "n_liq_recirc": InputVariable(fortran.fwbs_variables, int, range=(1, 50)), + "n_pancake": InputVariable(fortran.tfcoil_variables, int, range=(1, 100)), + "n_rad_per_layer": InputVariable(fortran.tfcoil_variables, int, range=(1, 500)), + "n_res": InputVariable(fortran.stellarator_variables, int, range=(3, 6)), + "n_tf_graded_layers": InputVariable(fortran.tfcoil_variables, int, range=(1, 20)), + "n_tf_joints": InputVariable(fortran.tfcoil_variables, int, range=(1, 50)), + "n_tf_joints_contact": InputVariable(fortran.tfcoil_variables, int, range=(1, 50)), + "nblktmodpi": InputVariable(fortran.fwbs_variables, int, range=(1, 16)), + "nblktmodpo": InputVariable(fortran.fwbs_variables, int, range=(1, 16)), + "nblktmodti": InputVariable(fortran.fwbs_variables, int, range=(8, 96)), + "nblktmodto": InputVariable(fortran.fwbs_variables, int, range=(8, 96)), + "npdiv": InputVariable(fortran.fwbs_variables, int, range=(0, 4)), + "nphcdin": InputVariable(fortran.fwbs_variables, int, range=(0, 4)), + "nphcdout": InputVariable(fortran.fwbs_variables, int, range=(0, 4)), + "ntype": InputVariable(fortran.vacuum_variables, int, choices=[0, 1]), + "num_rh_systems": InputVariable(fortran.cost_variables, int, range=(1, 10)), + "output_costs": InputVariable(fortran.cost_variables, int, choices=[0, 1]), + "primary_pumping": InputVariable(fortran.fwbs_variables, int, range=(0, 3)), + "reinke_mode": InputVariable(fortran.reinke_variables, int, choices=[0, 1]), + "scan_dim": InputVariable(fortran.scan_module, int, range=(1, 2)), + "secondary_cycle": InputVariable(fortran.fwbs_variables, int, range=(0, 4)), + "secondary_cycle_liq": InputVariable(fortran.fwbs_variables, int, range=(2, 4)), + "supercond_cost_model": InputVariable(fortran.cost_variables, int, choices=[0, 1]), + "i_tf_inside_cs": InputVariable(fortran.build_variables, int, choices=[0, 1]), + "wave_mode": InputVariable(fortran.current_drive_variables, int, choices=[0, 1]), + "i_confinement_time": InputVariable( + fortran.physics_variables, + int, + choices=list(range(fortran.physics_variables.n_confinement_scalings)), + ), + "quench_model": InputVariable( + fortran.tfcoil_variables, str, choices=["exponential", "linear"] + ), + "i_fw_coolant_type": InputVariable( + fortran.fwbs_variables, str, choices=["helium", "water"] + ), + "vacuum_model": InputVariable( + fortran.vacuum_variables, str, choices=["old", "simple"] + ), + "dcond": InputVariable(fortran.tfcoil_variables, float, array=True), + "c_pf_coil_turn_peak_input": InputVariable( + fortran.pfcoil_variables, float, array=True + ), + "i_pf_location": InputVariable(fortran.pfcoil_variables, int, array=True), + "n_pf_coils_in_group": InputVariable(fortran.pfcoil_variables, int, array=True), + "nfxfh": InputVariable(fortran.pfcoil_variables, int, array=True), + "n_pf_coil_groups": InputVariable( + fortran.pfcoil_variables, + int, + range=(0, fortran.pfcoil_variables.n_pf_groups_max.item()), + ), + "rref": InputVariable(fortran.pfcoil_variables, float, array=True), + "f_a_pf_coil_void": InputVariable(fortran.pfcoil_variables, float, array=True), + "zref": InputVariable(fortran.pfcoil_variables, float, array=True), + "uchts": InputVariable(fortran.cost_variables, float, array=True), + "ucoam": InputVariable(fortran.cost_variables, float, array=True), + "ucsc": InputVariable(fortran.cost_variables, float, array=True), + "ucturb": InputVariable(fortran.cost_variables, float, array=True), + "ucwst": InputVariable(fortran.cost_variables, float, array=True), + "blmatf": InputVariable(fortran.ife_variables, float, array=True), + "chmatf": InputVariable(fortran.ife_variables, float, array=True), + "etave": InputVariable(fortran.ife_variables, float, array=True), + "fwmatf": InputVariable(fortran.ife_variables, float, array=True), + "gainve": InputVariable(fortran.ife_variables, float, array=True), + "shmatf": InputVariable(fortran.ife_variables, float, array=True), + "v1matf": InputVariable(fortran.ife_variables, float, array=True), + "v2matf": InputVariable(fortran.ife_variables, float, array=True), + "v3matf": InputVariable(fortran.ife_variables, float, array=True), + "isweep": InputVariable( + fortran.scan_module, int, choices=range(fortran.scan_module.ipnscns.item() + 1) + ), + "nsweep": InputVariable( + fortran.scan_module, + int, + choices=range(1, fortran.scan_module.ipnscnv.item() + 1), + ), + "isweep_2": InputVariable( + fortran.scan_module, int, choices=range(fortran.scan_module.ipnscns.item() + 1) + ), + "nsweep_2": InputVariable( + fortran.scan_module, + int, + choices=range(1, fortran.scan_module.ipnscnv.item() + 1), + ), + "sweep": InputVariable(fortran.scan_module, float, array=True), + "sweep_2": InputVariable(fortran.scan_module, float, array=True), + "impvardiv": InputVariable( + fortran.reinke_variables, + int, + choices=range(3, fortran.impurity_radiation_module.n_impurities.item() + 1), + ), + "j_pf_coil_wp_peak": InputVariable(fortran.pfcoil_variables, float, array=True), + "ixc": InputVariable( + None, + int, + range=(1, fortran.numerics.ipnvars.item()), + additional_actions=_ixc_additional_actions, + set_variable=False, + ), + "icc": InputVariable( + None, + int, + range=(1, fortran.numerics.ipeqns.item()), + additional_actions=_icc_additional_actions, + set_variable=False, + ), } @@ -100,6 +1647,8 @@ def parse_input_file(): with input_file_path.open("r") as f: lines = f.readlines() + variables = {} + for line_no, line in enumerate(lines, start=1): stripped_line = line.strip() @@ -111,7 +1660,7 @@ def parse_input_file(): # matches (variable name, array index, value) # NOTE: array index is Fortran-based hence starts at 1. line_match = re.match( - r"([a-zA-Z0-9_]+)(?:\(([0-9]+)\))?[ ]*=[ ]*([ +\-a-zA-Z0-9.]+).*", + r"([a-zA-Z0-9_]+)(?:\(([0-9]+)\))?[ ]*=[ ]*([ +\-a-zA-Z0-9.,]+).*", stripped_line, ) @@ -129,27 +1678,50 @@ def parse_input_file(): error_msg = ( f"Unrecognised input '{variable_name}' at line {line_no} of input file." ) - warn(error_msg, stacklevel=1) - continue - # TODO: re-enable error instead - # raise ProcessValidationError(error_msg) + raise ProcessValidationError(error_msg) # validate the variable and also clean it (cast to correct type) - - clean_variable_value = validate_variable( - variable_name, variable_value.strip(), array_index, variable_config, line_no - ) + if "," in variable_value: + clean_variable_value = [ + validate_variable( + variable_name, + v.strip(), + str(i), + variable_config, + line_no, + check_array=False, + ) + for i, v in enumerate(variable_value.split(","), start=1) + ] + else: + clean_variable_value = validate_variable( + variable_name, + variable_value.strip(), + array_index, + variable_config, + line_no, + ) # check if the target name in the module is different to the variable name # in the input file variable_name_in_module = variable_config.target_name or variable_name + array_index_clean = None if array_index is None else int(array_index) + if variable_config.set_variable: - if variable_config.array: + if isinstance(clean_variable_value, list): + for idx, value in enumerate(clean_variable_value, start=1): + set_array_variable( + variable_name_in_module, + value, + idx, + variable_config, + ) + elif variable_config.array: set_array_variable( variable_name_in_module, clean_variable_value, - int(array_index), + array_index_clean, variable_config, ) else: @@ -163,10 +1735,19 @@ def parse_input_file(): variable_config.additional_actions( variable_name, clean_variable_value, - None if array_index is None else int(array_index), + array_index_clean, variable_config, ) + # again its the input name not the target name + variables[variable_name] = { + "value": clean_variable_value, + "index": array_index_clean, + "config": variable_config, + } + + return variables + def validate_variable( name: str, @@ -174,6 +1755,8 @@ def validate_variable( array_index: int | None, config: InputVariable, line_number: int, + *, + check_array=True, ) -> ValidInputTypes: """Validate an input. @@ -185,7 +1768,7 @@ def validate_variable( :returns: the input value with the correct type. """ # check its an array if and only if the config says so - if array_index is None and config.array: + if array_index is None and config.array and check_array: error_msg = f"Expected '{name}' at line {line_number} to be an array." raise ProcessValidationError(error_msg) diff --git a/scripts/create_dicts.py b/scripts/create_dicts.py index 3736ae6260..f57d4ab29f 100644 --- a/scripts/create_dicts.py +++ b/scripts/create_dicts.py @@ -764,6 +764,7 @@ def dict_input_bounds(): for var_name, config in INPUT_VARIABLES.items(): lb, ub = None, None if config.range is not None: + print(var_name) lb, ub = config.range elif config.choices is not None and config.type in [int, float]: diff --git a/source/fortran/init_module.f90 b/source/fortran/init_module.f90 index 4b6ad29b80..59b2d69edb 100644 --- a/source/fortran/init_module.f90 +++ b/source/fortran/init_module.f90 @@ -6,6 +6,8 @@ module init_module implicit none + integer, parameter :: nin = 10 + contains subroutine init_fortran_modules @@ -23,7 +25,6 @@ end subroutine init_fortran_modules subroutine open_files use global_variables, only: verbose, fileprefix, output_prefix use constants, only: nout, mfile - use process_input, only: nin implicit none @@ -79,7 +80,6 @@ subroutine finish ! completely dealt with in Python ! # TODO Move this output and file handling to Python - use process_input, only: nin use constants, only: iotty, mfile, nout, nplot, opt_file, vfile use process_output_fortran, only: oheadr use global_variables, only: verbose diff --git a/source/fortran/iteration_variables.f90 b/source/fortran/iteration_variables.f90 index f46c4a0f4f..06918bbafe 100755 --- a/source/fortran/iteration_variables.f90 +++ b/source/fortran/iteration_variables.f90 @@ -3981,6 +3981,10 @@ subroutine loadxc ! Local variables integer :: i ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + if (allocated(name_xc)) deallocate(name_xc) + allocate(name_xc(nvar)) + name_xc = "" + do i = 1,nvar select case (ixc(i)) diff --git a/source/fortran/numerics.f90 b/source/fortran/numerics.f90 index 1c4e4d628e..3f71b9bf36 100755 --- a/source/fortran/numerics.f90 +++ b/source/fortran/numerics.f90 @@ -64,6 +64,8 @@ module numerics !!
  • (18) Null Figure of Merit !!
  • (19) linear combination of big Q and pulse length (maximised) !! note: FoM should be minimised only! + integer :: n_constraints + !! Total number of constraints (neqns + nineqns) integer :: ncalls !! ncalls : number of function calls during solution @@ -461,7 +463,8 @@ subroutine init_numerics() nfev1 = 0 nfev2 = 0 nineqns = 0 - nvar = 16 + nvar = 0 + n_constraints = 0 nviter = 0 icc = 0 active_constraints = .false. diff --git a/tests/unit/test_input.py b/tests/unit/test_input.py index 1a6e159af3..72a3c4cb7c 100644 --- a/tests/unit/test_input.py +++ b/tests/unit/test_input.py @@ -1,3 +1,4 @@ +import numpy as np import pytest import process.init as init @@ -145,3 +146,14 @@ def test_input_float_when_int(tmp_path): with pytest.raises(ProcessValidationError): init.init_process() + + +def test_input_array(tmp_path): + fortran.global_variables.fileprefix = string_to_f2py_compatible( + fortran.global_variables.fileprefix, + _create_input_file(tmp_path, ("boundl = 0.1, 0.2, 1.0, 0.0, 1.0e2")), + ) + init.init_process() + np.testing.assert_array_equal( + fortran.numerics.boundl[:6], [0.1, 0.2, 1.0, 0.0, 1.0e2, 0] + ) From f4a24d154a2919dd8bd1815e477f762807e85f18 Mon Sep 17 00:00:00 2001 From: Timothy Nunn Date: Thu, 27 Feb 2025 11:53:51 +0000 Subject: [PATCH 7/9] Correct bug reseting blanket thicknesses, add test to verify python parser --- process/init.py | 37 +++++++++++++++++++------------------ tests/unit/test_input.py | 26 ++++++++++++++++++++++++++ 2 files changed, 45 insertions(+), 18 deletions(-) diff --git a/process/init.py b/process/init.py index b1c0030abb..25785ecee6 100644 --- a/process/init.py +++ b/process/init.py @@ -440,24 +440,25 @@ def check_process(inputs): stacklevel=1, ) - if fortran.fwbs_variables.i_blanket_type == 3: - fortran.build_variables.dr_fw_inboard = 0.03 - fortran.build_variables.dr_fw_outboard = 0.03 - fortran.fwbs_variables.fw_armour_thickness = 0.003 - - if 0 <= fortran.build_variables.dr_blkt_inboard <= 1e-3: - fortran.build_variables.dr_blkt_inboard = 0.0 - fortran.fwbs_variables.i_blkt_inboard = 0 - - if fortran.fwbs_variables.iblanket_thickness == 1: - fortran.build_variables.dr_blkt_inboard = 0.53 - fortran.build_variables.dr_blkt_outboard = 0.91 - elif fortran.fwbs_variables.iblanket_thickness == 2: - fortran.build_variables.dr_blkt_inboard = 0.64 - fortran.build_variables.dr_blkt_outboard = 1.11 - elif fortran.fwbs_variables.iblanket_thickness == 3: - fortran.build_variables.dr_blkt_inboard = 0.75 - fortran.build_variables.dr_blkt_outboard = 1.30 + if "iblanket_thickness" in inputs: + if fortran.fwbs_variables.i_blanket_type == 3: + fortran.build_variables.dr_fw_inboard = 0.03 + fortran.build_variables.dr_fw_outboard = 0.03 + fortran.fwbs_variables.fw_armour_thickness = 0.003 + + if 0 <= fortran.build_variables.dr_blkt_inboard <= 1e-3: + fortran.build_variables.dr_blkt_inboard = 0.0 + fortran.fwbs_variables.i_blkt_inboard = 0 + + if fortran.fwbs_variables.iblanket_thickness == 1: + fortran.build_variables.dr_blkt_inboard = 0.53 + fortran.build_variables.dr_blkt_outboard = 0.91 + elif fortran.fwbs_variables.iblanket_thickness == 2: + fortran.build_variables.dr_blkt_inboard = 0.64 + fortran.build_variables.dr_blkt_outboard = 1.11 + elif fortran.fwbs_variables.iblanket_thickness == 3: + fortran.build_variables.dr_blkt_inboard = 0.75 + fortran.build_variables.dr_blkt_outboard = 1.30 # Check that there are sufficient iteration variables if fortran.numerics.nvar < fortran.numerics.neqns: diff --git a/tests/unit/test_input.py b/tests/unit/test_input.py index 72a3c4cb7c..603bed3ae2 100644 --- a/tests/unit/test_input.py +++ b/tests/unit/test_input.py @@ -71,6 +71,32 @@ def test_parse_real(epsvmc, expected, tmp_path): assert fortran.numerics.epsvmc == expected +@pytest.mark.parametrize( + ["value"], + [ + [0.546816593988753], + [0.13134204235647895], + [0.75], + [0.7], + [0.3], + [0.1293140904093427], + ], +) +def test_parse_real_didnt_work_in_f90(value, tmp_path): + """Tests the parsing of real numbers into PROCESS. + + These tests failed using the old input parser and serve to show that the Python parser generally + produces more accurate floats and accumulates less error. + """ + fortran.global_variables.fileprefix = string_to_f2py_compatible( + fortran.global_variables.fileprefix, + _create_input_file(tmp_path, f"epsvmc = {value}"), + ) + init.init_process() + + assert fortran.numerics.epsvmc == value + + def test_parse_input(tmp_path): fortran.global_variables.fileprefix = string_to_f2py_compatible( fortran.global_variables.fileprefix, From 79927b330152676d58e3b292f207ccfae05f61f7 Mon Sep 17 00:00:00 2001 From: Timothy Nunn Date: Thu, 27 Feb 2025 13:17:53 +0000 Subject: [PATCH 8/9] 0 arrays fully specified in IN.DAT --- process/input.py | 1 + 1 file changed, 1 insertion(+) diff --git a/process/input.py b/process/input.py index 3d8252b580..f5a8cfef21 100644 --- a/process/input.py +++ b/process/input.py @@ -1682,6 +1682,7 @@ def parse_input_file(): # validate the variable and also clean it (cast to correct type) if "," in variable_value: + getattr(variable_config.module, variable_name)[:] = 0.0 clean_variable_value = [ validate_variable( variable_name, From 25f4001d01ac2bc17eb084eb87c4b3ef252ddbb9 Mon Sep 17 00:00:00 2001 From: Timothy Nunn Date: Thu, 6 Mar 2025 10:15:50 +0000 Subject: [PATCH 9/9] Clarify comments and remove unnecessary code --- process/input.py | 23 +++++++++++++---------- scripts/create_dicts.py | 1 - tests/unit/test_input.py | 5 +---- 3 files changed, 14 insertions(+), 15 deletions(-) diff --git a/process/input.py b/process/input.py index f5a8cfef21..d2026b500d 100644 --- a/process/input.py +++ b/process/input.py @@ -149,7 +149,7 @@ def __post_init__(self): # TODO: does fimp require an additional range? "fimp": InputVariable(fortran.impurity_radiation_module, float, array=True), "fkzohm": InputVariable(fortran.physics_variables, float, range=(0.5, 2.0)), - "fnesep": InputVariable(fortran.physics_variables, float, range=(0.1, 20.0)), + "fnesep": InputVariable(fortran.constraint_variables, float, range=(0.1, 20.0)), "abktflnc": InputVariable(fortran.cost_variables, float, range=(0.1, 100.0)), "adivflnc": InputVariable(fortran.cost_variables, float, range=(0.1, 100.0)), "admv": InputVariable(fortran.buildings_variables, float, range=(1.0e4, 1.0e6)), @@ -1432,7 +1432,7 @@ def __post_init__(self): "ccls_ma": InputVariable(fortran.pfcoil_variables, float, array=True), "cfind": InputVariable(fortran.cost_variables, float, array=True), "coolwh": InputVariable(fortran.fwbs_variables, int, choices=[1, 2]), - "copperA_m2_max": InputVariable( + "coppera_m2_max": InputVariable( fortran.rebco_variables, float, range=(1.0e6, 1.0e10) ), "cost_model": InputVariable(fortran.cost_variables, int, choices=[0, 1]), @@ -1680,17 +1680,19 @@ def parse_input_file(): ) raise ProcessValidationError(error_msg) - # validate the variable and also clean it (cast to correct type) + # Validate the variable and also clean it (cast to correct type) + # If the variable value (after the = sign) contains a ',' then it + # defines the whole array so needs to be split down into its elements + # and the parsed like an array defined as 'my_array() = ' if "," in variable_value: getattr(variable_config.module, variable_name)[:] = 0.0 clean_variable_value = [ validate_variable( variable_name, v.strip(), - str(i), + str(i + 1), variable_config, line_no, - check_array=False, ) for i, v in enumerate(variable_value.split(","), start=1) ] @@ -1740,7 +1742,7 @@ def parse_input_file(): variable_config, ) - # again its the input name not the target name + # add the variable to a dictionary indexed by the variable name (in the input file) variables[variable_name] = { "value": clean_variable_value, "index": array_index_clean, @@ -1756,8 +1758,6 @@ def validate_variable( array_index: int | None, config: InputVariable, line_number: int, - *, - check_array=True, ) -> ValidInputTypes: """Validate an input. @@ -1765,11 +1765,14 @@ def validate_variable( :param value: the value of the input variable. :param array_index: the array index of the variable in the input file. :param config: the config of the variable that describes how to validate and process it. + :param line_number: line number of current line being parsed for error reporting. :returns: the input value with the correct type. """ - # check its an array if and only if the config says so - if array_index is None and config.array and check_array: + # check that if the variable should be an array, then an array index is provided + # EXCEPT for if check_array is False. This should only be the case when parsing + # entire arrays (e.g. my_array = 1,2,2,4,5) where there will be no array index. + if array_index is None and config.array: error_msg = f"Expected '{name}' at line {line_number} to be an array." raise ProcessValidationError(error_msg) diff --git a/scripts/create_dicts.py b/scripts/create_dicts.py index f57d4ab29f..3736ae6260 100644 --- a/scripts/create_dicts.py +++ b/scripts/create_dicts.py @@ -764,7 +764,6 @@ def dict_input_bounds(): for var_name, config in INPUT_VARIABLES.items(): lb, ub = None, None if config.range is not None: - print(var_name) lb, ub = config.range elif config.choices is not None and config.type in [int, float]: diff --git a/tests/unit/test_input.py b/tests/unit/test_input.py index 603bed3ae2..47dcccf7bb 100644 --- a/tests/unit/test_input.py +++ b/tests/unit/test_input.py @@ -82,7 +82,7 @@ def test_parse_real(epsvmc, expected, tmp_path): [0.1293140904093427], ], ) -def test_parse_real_didnt_work_in_f90(value, tmp_path): +def test_exact_parsing(value, tmp_path): """Tests the parsing of real numbers into PROCESS. These tests failed using the old input parser and serve to show that the Python parser generally @@ -121,9 +121,6 @@ def test_input_choices(tmp_path): _create_input_file(tmp_path, ("ioptimz = -1")), ) - # check that the test data doesn't change - assert process_input.INPUT_VARIABLES["ioptimz"].choices == [1, -2] - with pytest.raises(ProcessValidationError): init.init_process()