diff --git a/CMakeLists.txt b/CMakeLists.txt index 069d1f072a..c44d8e64ff 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -87,7 +87,6 @@ LIST(APPEND PROCESS_SRCS ife_variables.f90 heat_transport_variables.f90 buildings_variables.f90 - iteration_variables.f90 water_usage_variables.f90 constraint_equations.f90 constants.f90 diff --git a/process/caller.py b/process/caller.py index 444f167037..7e30a20618 100644 --- a/process/caller.py +++ b/process/caller.py @@ -10,6 +10,7 @@ from process import fortran as ft from process.final import finalise from process.io.mfile import MFile +from process.iteration_variables import set_scaled_iteration_variable from process.objectives import objective_function from process.utilities.f2py_string_patch import f2py_compatible_to_string @@ -229,7 +230,7 @@ def _call_models_once(self, xc: np.ndarray) -> None: ft.numerics.ncalls = ft.numerics.ncalls + 1 # Convert variables - ft.define_iteration_variables.convxc(xc, nvars) + set_scaled_iteration_variable(xc, nvars) # Perform the various function calls # Stellarator caller diff --git a/process/init.py b/process/init.py index d6cd8ce946..654efc4627 100644 --- a/process/init.py +++ b/process/init.py @@ -7,6 +7,7 @@ import process import process.fortran as fortran +import process.iteration_variables as iteration_variables import process.process_output as process_output from process.blanket_library import init_blanket_library, init_primary_pumping_variables from process.build import init_build_variables @@ -53,7 +54,7 @@ def init_process(): fortran.error_handling.initialise_error_list() # Initialise the program variables - initialise_iterative_variables() + iteration_variables.initialise_iteration_variables() # Initialise the Fortran file specifiers # (creating and opening the files in the process) @@ -267,7 +268,6 @@ def init_all_module_vars(): init_pulse_variables() init_rebco_variables() init_reinke_variables() - fortran.define_iteration_variables.init_define_iteration_variables() init_watuse_variables() init_cs_fatigue_variables() init_blanket_library() @@ -276,176 +276,6 @@ def init_all_module_vars(): fortran.init_module.init_fortran_modules() -def initialise_iterative_variables(): - """Initialise each of the iteration variables""" - fortran.define_iteration_variables.init_itv_1() - fortran.define_iteration_variables.init_itv_2() - fortran.define_iteration_variables.init_itv_3() - fortran.define_iteration_variables.init_itv_4() - fortran.define_iteration_variables.init_itv_5() - fortran.define_iteration_variables.init_itv_6() - fortran.define_iteration_variables.init_itv_7() - fortran.define_iteration_variables.init_itv_8() - fortran.define_iteration_variables.init_itv_9() - fortran.define_iteration_variables.init_itv_10() - fortran.define_iteration_variables.init_itv_11() - fortran.define_iteration_variables.init_itv_12() - fortran.define_iteration_variables.init_itv_13() - fortran.define_iteration_variables.init_itv_14() - fortran.define_iteration_variables.init_itv_15() - fortran.define_iteration_variables.init_itv_16() - fortran.define_iteration_variables.init_itv_17() - fortran.define_iteration_variables.init_itv_18() - fortran.define_iteration_variables.init_itv_19() - fortran.define_iteration_variables.init_itv_20() - fortran.define_iteration_variables.init_itv_21() - - fortran.define_iteration_variables.init_itv_23() - - fortran.define_iteration_variables.init_itv_25() - fortran.define_iteration_variables.init_itv_26() - fortran.define_iteration_variables.init_itv_27() - fortran.define_iteration_variables.init_itv_28() - fortran.define_iteration_variables.init_itv_29() - fortran.define_iteration_variables.init_itv_30() - fortran.define_iteration_variables.init_itv_31() - fortran.define_iteration_variables.init_itv_32() - fortran.define_iteration_variables.init_itv_33() - fortran.define_iteration_variables.init_itv_35() - fortran.define_iteration_variables.init_itv_36() - fortran.define_iteration_variables.init_itv_37() - fortran.define_iteration_variables.init_itv_38() - fortran.define_iteration_variables.init_itv_39() - fortran.define_iteration_variables.init_itv_40() - fortran.define_iteration_variables.init_itv_41() - fortran.define_iteration_variables.init_itv_42() - - fortran.define_iteration_variables.init_itv_44() - fortran.define_iteration_variables.init_itv_45() - fortran.define_iteration_variables.init_itv_46() - fortran.define_iteration_variables.init_itv_47() - fortran.define_iteration_variables.init_itv_48() - fortran.define_iteration_variables.init_itv_49() - fortran.define_iteration_variables.init_itv_50() - fortran.define_iteration_variables.init_itv_51() - - fortran.define_iteration_variables.init_itv_53() - fortran.define_iteration_variables.init_itv_54() - - fortran.define_iteration_variables.init_itv_56() - fortran.define_iteration_variables.init_itv_57() - fortran.define_iteration_variables.init_itv_58() - fortran.define_iteration_variables.init_itv_59() - fortran.define_iteration_variables.init_itv_60() - fortran.define_iteration_variables.init_itv_61() - fortran.define_iteration_variables.init_itv_62() - fortran.define_iteration_variables.init_itv_63() - fortran.define_iteration_variables.init_itv_64() - fortran.define_iteration_variables.init_itv_65() - fortran.define_iteration_variables.init_itv_66() - fortran.define_iteration_variables.init_itv_67() - fortran.define_iteration_variables.init_itv_68() - fortran.define_iteration_variables.init_itv_69() - fortran.define_iteration_variables.init_itv_70() - fortran.define_iteration_variables.init_itv_71() - fortran.define_iteration_variables.init_itv_72() - fortran.define_iteration_variables.init_itv_73() - fortran.define_iteration_variables.init_itv_74() - fortran.define_iteration_variables.init_itv_75() - - fortran.define_iteration_variables.init_itv_79() - - fortran.define_iteration_variables.init_itv_81() - fortran.define_iteration_variables.init_itv_82() - fortran.define_iteration_variables.init_itv_83() - - fortran.define_iteration_variables.init_itv_85() - fortran.define_iteration_variables.init_itv_86() - - fortran.define_iteration_variables.init_itv_89() - fortran.define_iteration_variables.init_itv_90() - fortran.define_iteration_variables.init_itv_91() - fortran.define_iteration_variables.init_itv_92() - fortran.define_iteration_variables.init_itv_93() - fortran.define_iteration_variables.init_itv_94() - fortran.define_iteration_variables.init_itv_95() - fortran.define_iteration_variables.init_itv_96() - fortran.define_iteration_variables.init_itv_97() - fortran.define_iteration_variables.init_itv_98() - - fortran.define_iteration_variables.init_itv_103() - fortran.define_iteration_variables.init_itv_104() - fortran.define_iteration_variables.init_itv_105() - fortran.define_iteration_variables.init_itv_106() - fortran.define_iteration_variables.init_itv_107() - fortran.define_iteration_variables.init_itv_108() - fortran.define_iteration_variables.init_itv_109() - fortran.define_iteration_variables.init_itv_110() - fortran.define_iteration_variables.init_itv_111() - fortran.define_iteration_variables.init_itv_112() - fortran.define_iteration_variables.init_itv_113() - fortran.define_iteration_variables.init_itv_114() - fortran.define_iteration_variables.init_itv_115() - fortran.define_iteration_variables.init_itv_116() - fortran.define_iteration_variables.init_itv_117() - fortran.define_iteration_variables.init_itv_118() - fortran.define_iteration_variables.init_itv_119() - fortran.define_iteration_variables.init_itv_120() - fortran.define_iteration_variables.init_itv_121() - fortran.define_iteration_variables.init_itv_122() - fortran.define_iteration_variables.init_itv_123() - fortran.define_iteration_variables.init_itv_124() - fortran.define_iteration_variables.init_itv_125() - fortran.define_iteration_variables.init_itv_126() - fortran.define_iteration_variables.init_itv_127() - fortran.define_iteration_variables.init_itv_128() - fortran.define_iteration_variables.init_itv_129() - fortran.define_iteration_variables.init_itv_130() - fortran.define_iteration_variables.init_itv_131() - fortran.define_iteration_variables.init_itv_132() - fortran.define_iteration_variables.init_itv_133() - fortran.define_iteration_variables.init_itv_134() - fortran.define_iteration_variables.init_itv_135() - fortran.define_iteration_variables.init_itv_136() - fortran.define_iteration_variables.init_itv_137() - fortran.define_iteration_variables.init_itv_138() - fortran.define_iteration_variables.init_itv_139() - fortran.define_iteration_variables.init_itv_140() - fortran.define_iteration_variables.init_itv_141() - fortran.define_iteration_variables.init_itv_142() - fortran.define_iteration_variables.init_itv_143() - fortran.define_iteration_variables.init_itv_144() - fortran.define_iteration_variables.init_itv_145() - fortran.define_iteration_variables.init_itv_146() - fortran.define_iteration_variables.init_itv_147() - fortran.define_iteration_variables.init_itv_148() - fortran.define_iteration_variables.init_itv_149() - fortran.define_iteration_variables.init_itv_152() - fortran.define_iteration_variables.init_itv_153() - fortran.define_iteration_variables.init_itv_154() - fortran.define_iteration_variables.init_itv_155() - fortran.define_iteration_variables.init_itv_156() - fortran.define_iteration_variables.init_itv_157() - fortran.define_iteration_variables.init_itv_158() - fortran.define_iteration_variables.init_itv_159() - fortran.define_iteration_variables.init_itv_160() - fortran.define_iteration_variables.init_itv_161() - fortran.define_iteration_variables.init_itv_162() - fortran.define_iteration_variables.init_itv_163() - fortran.define_iteration_variables.init_itv_164() - fortran.define_iteration_variables.init_itv_165() - fortran.define_iteration_variables.init_itv_166() - fortran.define_iteration_variables.init_itv_167() - fortran.define_iteration_variables.init_itv_168() - fortran.define_iteration_variables.init_itv_169() - fortran.define_iteration_variables.init_itv_170() - fortran.define_iteration_variables.init_itv_171() - fortran.define_iteration_variables.init_itv_172() - fortran.define_iteration_variables.init_itv_173() - fortran.define_iteration_variables.init_itv_174() - fortran.define_iteration_variables.init_itv_175() - - def check_process(inputs): # noqa: ARG001 """Routine to reset specific variables if certain options are being used diff --git a/process/iteration_variables.py b/process/iteration_variables.py new file mode 100644 index 0000000000..5d7f73f298 --- /dev/null +++ b/process/iteration_variables.py @@ -0,0 +1,443 @@ +from copy import deepcopy +from dataclasses import dataclass +from typing import Any +from warnings import warn + +import numpy as np + +import process.fortran as fortran +from process.exceptions import ProcessValueError +from process.utilities.f2py_string_patch import ( + f2py_compatible_to_string, + string_to_f2py_compatible, +) + + +@dataclass +class IterationVariable: + name: str + """The name of the variable""" + module: Any + """The Fortran module that this variable should be set on.""" + lower_bound: float + """The default lower bound of the iteration variable""" + upper_bound: float + """The default upper bound of the iteration variable""" + target_name: str | None = None + """If specified, the iteration variable is set as `module.target_name` + rather than `module.name`. + """ + array_index: int | None = None + """If `module.name` is an array, the iteration variable can only modify + `array_index` of that array. + + NOTE: The indexes start at 0 (despite indexing Fortran arrays). + """ + + +ITERATION_VARIABLES = { + 1: IterationVariable("aspect", fortran.physics_variables, 1.1, 10.00), + 2: IterationVariable("bt", fortran.physics_variables, 0.010, 30.00), + 3: IterationVariable("rmajor", fortran.physics_variables, 0.1, 50.00), + 4: IterationVariable("te", fortran.physics_variables, 5.0, 150.0), + 5: IterationVariable("beta", fortran.physics_variables, 0.001, 1.0), + 6: IterationVariable("dene", fortran.physics_variables, 2.0e19, 1.0e21), + 7: IterationVariable("f_nd_beam_electron", fortran.physics_variables, 1.0e-6, 1.0), + 8: IterationVariable( + "fbeta_poloidal_eps", fortran.constraint_variables, 0.001, 1.0 + ), + 9: IterationVariable("fdene", fortran.constraint_variables, 0.001, 1.0), + 10: IterationVariable("hfact", fortran.physics_variables, 0.1, 3.0), + 11: IterationVariable("pheat", fortran.current_drive_variables, 1.0e-3, 1.0e3), + 12: IterationVariable("oacdcp", fortran.tfcoil_variables, 1.0e5, 1.50e8), + 13: IterationVariable("dr_tf_inboard", fortran.build_variables, 0.1, 5.0), + 14: IterationVariable("fwalld", fortran.constraint_variables, 0.001, 1.0), + 15: IterationVariable("fvs", fortran.constraint_variables, 0.001, 10.000), + 16: IterationVariable("dr_cs", fortran.build_variables, 0.01, 10.00), + 17: IterationVariable("t_between_pulse", fortran.times_variables, 0.1, 1.0e8), + 18: IterationVariable("q95", fortran.physics_variables, 2.0, 50.00), + 19: IterationVariable("beam_energy", fortran.current_drive_variables, 1.0, 1.0e6), + 20: IterationVariable("temp_cp_average", fortran.tfcoil_variables, 40.00, 3.0e2), + 21: IterationVariable("ft_burn", fortran.constraint_variables, 0.001, 1.0), + 23: IterationVariable("fcoolcp", fortran.tfcoil_variables, 0.1, 0.50), + 25: IterationVariable("fpnetel", fortran.constraint_variables, 0.001, 1.0), + 26: IterationVariable("ffuspow", fortran.constraint_variables, 0.001, 1.0), + 27: IterationVariable("fhldiv", fortran.constraint_variables, 0.001, 1.0), + 28: IterationVariable("fradpwr", fortran.constraint_variables, 0.001, 0.99), + 29: IterationVariable("dr_bore", fortran.build_variables, 0.1, 10.00), + 30: IterationVariable("fmva", fortran.constraint_variables, 0.010, 1.0), + 31: IterationVariable("gapomin", fortran.build_variables, 0.001, 1.0e1), + 32: IterationVariable("frminor", fortran.constraint_variables, 0.001, 1.0), + 33: IterationVariable("fportsz", fortran.constraint_variables, 0.001, 1.0), + 35: IterationVariable("fpeakb", fortran.constraint_variables, 0.001, 1.0), + 36: IterationVariable("fbeta_max", fortran.constraint_variables, 0.001, 1.0), + 37: IterationVariable("j_cs_flat_top_end", fortran.pfcoil_variables, 1.0e5, 1.0e8), + 38: IterationVariable("fjohc", fortran.constraint_variables, 0.010, 1.0), + 39: IterationVariable("fjohc0", fortran.constraint_variables, 0.001, 1.0), + 40: IterationVariable("fgamcd", fortran.constraint_variables, 0.001, 1.0), + 41: IterationVariable( + "f_j_cs_start_pulse_end_flat_top", fortran.pfcoil_variables, 0.001, 1.0 + ), + 42: IterationVariable("dr_cs_tf_gap", fortran.build_variables, 0.001, 10.00), + 44: IterationVariable("fvsbrnni", fortran.physics_variables, 0.001, 1.0), + 45: IterationVariable("fqval", fortran.constraint_variables, 0.001, 1.0), + 46: IterationVariable("fpinj", fortran.constraint_variables, 0.001, 1.0), + 47: IterationVariable("feffcd", fortran.current_drive_variables, 0.001, 1.0), + 48: IterationVariable("fstrcase", fortran.constraint_variables, 0.001, 1.0), + 49: IterationVariable("fstrcond", fortran.constraint_variables, 0.001, 1.0), + 50: IterationVariable("fiooic", fortran.constraint_variables, 0.001, 1.0), + 51: IterationVariable("fvdump", fortran.constraint_variables, 0.001, 1.0), + 53: IterationVariable("fjprot", fortran.constraint_variables, 0.001, 1.0), + 54: IterationVariable("ftmargtf", fortran.constraint_variables, 0.001, 1.0), + 56: IterationVariable("tdmptf", fortran.tfcoil_variables, 0.1, 100.0), + 57: IterationVariable("thkcas", fortran.tfcoil_variables, 0.05, 1.0), + 58: IterationVariable("thwcndut", fortran.tfcoil_variables, 0.001, 0.1), + 59: IterationVariable("fcutfsu", fortran.tfcoil_variables, 0.001, 1.0), + 60: IterationVariable("cpttf", fortran.tfcoil_variables, 0.001, 4.0e4), + 61: IterationVariable( + "dr_shld_vv_gap_inboard", fortran.build_variables, 0.001, 10.00 + ), + 62: IterationVariable("fdtmp", fortran.constraint_variables, 0.001, 1.0), + 63: IterationVariable("ftpeak", fortran.constraint_variables, 0.001, 1.0), + 64: IterationVariable("fauxmn", fortran.constraint_variables, 0.001, 1.0), + 65: IterationVariable("t_current_ramp_up", fortran.times_variables, 0.1, 1.0e3), + 66: IterationVariable( + "ft_current_ramp_up", fortran.constraint_variables, 0.001, 1.0 + ), + 67: IterationVariable("ftcycl", fortran.constraint_variables, 0.001, 1.0), + 68: IterationVariable("fptemp", fortran.constraint_variables, 0.001, 1.0), + 69: IterationVariable("rcool", fortran.tfcoil_variables, 0.001, 0.010), + 70: IterationVariable("vcool", fortran.tfcoil_variables, 1.0, 1.0e2), + 71: IterationVariable("fq", fortran.constraint_variables, 0.001, 1.0), + 72: IterationVariable("fipir", fortran.constraint_variables, 0.001, 1.0), + 73: IterationVariable( + "dr_fw_plasma_gap_inboard", fortran.build_variables, 0.001, 10.00 + ), + 74: IterationVariable( + "dr_fw_plasma_gap_outboard", fortran.build_variables, 0.001, 10.00 + ), + 75: IterationVariable("tfootfi", fortran.build_variables, 0.200, 5.0), + 79: IterationVariable("fbeta_poloidal", fortran.constraint_variables, 0.001, 1.0), + 81: IterationVariable("edrive", fortran.ife_variables, 1.0e5, 5.0e7), + 82: IterationVariable("drveff", fortran.ife_variables, 0.010, 1.0), + 83: IterationVariable("tgain", fortran.ife_variables, 1.0, 500.0), + 84: IterationVariable("chrad", fortran.ife_variables, 0.1, 20.00), + 85: IterationVariable("pdrive", fortran.ife_variables, 1.0e6, 200.0e6), + 86: IterationVariable("frrmax", fortran.ife_variables, 0.001, 1.0), + 89: IterationVariable("ftbr", fortran.constraint_variables, 0.001, 1.0), + 90: IterationVariable("blbuith", fortran.build_variables, 0.001, 2.0), + 91: IterationVariable("blbuoth", fortran.build_variables, 0.001, 2.0), + 92: IterationVariable("fflutf", fortran.constraint_variables, 0.001, 1.0), + 93: IterationVariable("dr_shld_inboard", fortran.build_variables, 0.001, 10.00), + 94: IterationVariable("dr_shld_outboard", fortran.build_variables, 0.001, 10.00), + 95: IterationVariable("fptfnuc", fortran.constraint_variables, 0.001, 1.0), + 96: IterationVariable("fvvhe", fortran.constraint_variables, 0.001, 1.0), + 97: IterationVariable("fpsepr", fortran.constraint_variables, 0.001, 1.0), + 98: IterationVariable( + "f_blkt_li6_enrichment", fortran.fwbs_variables, 10.00, 100.0 + ), + 103: IterationVariable("fl_h_threshold", fortran.constraint_variables, 0.001, 1.0), + 104: IterationVariable("fcwr", fortran.constraint_variables, 0.001, 1.0), + 105: IterationVariable("fnbshinef", fortran.constraint_variables, 0.001, 1.0), + 106: IterationVariable("ftmargoh", fortran.constraint_variables, 0.001, 1.0), + 107: IterationVariable("favail", fortran.cost_variables, 0.001, 1.0), + 108: IterationVariable("breeder_f", fortran.fwbs_variables, 0.060, 1.0), + 109: IterationVariable( + "f_nd_alpha_electron", fortran.physics_variables, 0.05, 0.15 + ), + 110: IterationVariable( + "falpha_energy_confinement", fortran.constraint_variables, 0.001, 1.0 + ), + 111: IterationVariable("fniterpump", fortran.constraint_variables, 0.001, 1.0), + 112: IterationVariable("fzeffmax", fortran.constraint_variables, 0.001, 1.0), + 113: IterationVariable("fmaxvvstress", fortran.constraint_variables, 0.001, 1.0), + 114: IterationVariable("len_fw_channel", fortran.fwbs_variables, 0.001, 1.0e3), + 115: IterationVariable("fpoloidalpower", fortran.constraint_variables, 0.001, 1.0), + 116: IterationVariable("fradwall", fortran.constraint_variables, 0.001, 1.0), + 117: IterationVariable("fpsepbqar", fortran.constraint_variables, 0.001, 1.0), + 118: IterationVariable("fpsep", fortran.constraint_variables, 0.001, 1.0), + 119: IterationVariable("tesep", fortran.physics_variables, 0.0, 1.0e1), + 122: IterationVariable("f_a_cs_steel", fortran.pfcoil_variables, 0.001, 0.950), + 123: IterationVariable("foh_stress", fortran.constraint_variables, 0.001, 1.0), + 125: IterationVariable( + "fimp(03)", + fortran.impurity_radiation_module, + 1e-8, + 0.01, + target_name="impurity_arr_frac", + array_index=2, + ), + 126: IterationVariable( + "fimp(04)", + fortran.impurity_radiation_module, + 1e-8, + 0.01, + target_name="impurity_arr_frac", + array_index=3, + ), + 127: IterationVariable( + "fimp(05)", + fortran.impurity_radiation_module, + 1e-8, + 0.01, + target_name="impurity_arr_frac", + array_index=4, + ), + 128: IterationVariable( + "fimp(06)", + fortran.impurity_radiation_module, + 1e-8, + 0.01, + target_name="impurity_arr_frac", + array_index=5, + ), + 129: IterationVariable( + "fimp(07)", + fortran.impurity_radiation_module, + 1e-8, + 0.01, + target_name="impurity_arr_frac", + array_index=6, + ), + 130: IterationVariable( + "fimp(08)", + fortran.impurity_radiation_module, + 1e-8, + 0.01, + target_name="impurity_arr_frac", + array_index=7, + ), + 131: IterationVariable( + "fimp(09)", + fortran.impurity_radiation_module, + 1e-8, + 0.01, + target_name="impurity_arr_frac", + array_index=8, + ), + 132: IterationVariable( + "fimp(10)", + fortran.impurity_radiation_module, + 1e-8, + 0.01, + target_name="impurity_arr_frac", + array_index=9, + ), + 133: IterationVariable( + "fimp(11)", + fortran.impurity_radiation_module, + 1e-8, + 0.01, + target_name="impurity_arr_frac", + array_index=10, + ), + 134: IterationVariable( + "fimp(12)", + fortran.impurity_radiation_module, + 1e-8, + 0.01, + target_name="impurity_arr_frac", + array_index=11, + ), + 135: IterationVariable( + "fimp(13)", + fortran.impurity_radiation_module, + 1e-8, + 0.01, + target_name="impurity_arr_frac", + array_index=12, + ), + 136: IterationVariable( + "fimp(14)", + fortran.impurity_radiation_module, + 1e-8, + 0.01, + target_name="impurity_arr_frac", + array_index=13, + ), + 137: IterationVariable("fplhsep", fortran.physics_variables, 0.001, 1.0), + 138: IterationVariable( + "rebco_thickness", fortran.physics_variables, 0.01e-6, 100.0e-6 + ), + 139: IterationVariable("copper_thick", fortran.rebco_variables, 1.0e-6, 1.0e-3), + 140: IterationVariable("dr_tf_wp", fortran.tfcoil_variables, 0.001, 2.0), + 141: IterationVariable("fcqt", fortran.constraint_variables, 0.001, 1.0), + 142: IterationVariable("nesep", fortran.physics_variables, 1.0e17, 1.0e20), + 143: IterationVariable("f_coppera_m2", fortran.rebco_variables, 0.001, 1.0), + 144: IterationVariable("fnesep", fortran.constraint_variables, 0.001, 1.0), + 145: IterationVariable("fgwped", fortran.physics_variables, 0.1, 0.9), + 146: IterationVariable("fcpttf", fortran.constraint_variables, 0.001, 1.0), + 147: IterationVariable("freinke", fortran.constraint_variables, 0.001, 1.0), + 149: IterationVariable("fb_cs_limit_max", fortran.pfcoil_variables, 0.001, 1.0), + 152: IterationVariable("fgwsep", fortran.physics_variables, 0.001, 0.5), + 153: IterationVariable("fpdivlim", fortran.physics_variables, 0.001, 1.0), + 154: IterationVariable("fne0", fortran.physics_variables, 0.001, 1.0), + 155: IterationVariable("pfusife", fortran.ife_variables, 5.0e2, 3.0e3), + 156: IterationVariable("rrin", fortran.ife_variables, 1.0, 1.0e1), + 157: IterationVariable( + "fvs_cs_pf_total_ramp", fortran.pfcoil_variables, 1.0e-3, 1.0e1 + ), + 158: IterationVariable("croco_thick", fortran.rebco_variables, 1.0e-3, 1.0e-1), + 159: IterationVariable("ftoroidalgap", fortran.tfcoil_variables, 1.0e-4, 1.0), + 160: IterationVariable("f_avspace", fortran.build_variables, 0.010, 1.0), + 161: IterationVariable("fbeta_min", fortran.constraint_variables, 0.010, 1.0), + 162: IterationVariable("r_cp_top", fortran.build_variables, 0.0010, 10.0), + 163: IterationVariable("f_t_turn_tf", fortran.tfcoil_variables, 0.0010, 1000.0), + 164: IterationVariable("f_crypmw", fortran.heat_transport_variables, 0.001, 1.0), + 165: IterationVariable("fstr_wp", fortran.constraint_variables, 1.0e-9, 1.0), + 166: IterationVariable("f_copperaoh_m2", fortran.rebco_variables, 0.001, 1.0), + 167: IterationVariable("fncycle", fortran.constraint_variables, 1.0e-8, 1.0), + 168: IterationVariable("fecrh_ignition", fortran.constraint_variables, 0.010, 2.0), + 169: IterationVariable( + "te0_ecrh_achievable", fortran.stellarator_variables, 1.0, 1.0e3 + ), + 170: IterationVariable("beta_div", fortran.divertor_variables, 0.49, 5.01), + 171: IterationVariable("casths_fraction", fortran.tfcoil_variables, 0.01, 0.99), + 172: IterationVariable("casths", fortran.tfcoil_variables, 0.001, 1.0), + 173: IterationVariable("f_tritium", fortran.physics_variables, 0.000, 1.000), + 174: IterationVariable("triang", fortran.physics_variables, 0.00, 1.00), + 175: IterationVariable("kappa", fortran.physics_variables, 0.00, 10.00), +} + + +def check_iteration_variable(iteration_variable_value, name: str = ""): + """Check that the iteration variable value is valid (not a weird number or too small). + + Raises an error upon encountering an invalid value, otherwise does nothing. + """ + if abs(iteration_variable_value) <= 1e-12: + error_msg = f"Iteration variable {name} is 0 (or very close)" + raise ProcessValueError( + error_msg, iteration_variable_value=iteration_variable_value + ) + + if np.isnan(iteration_variable_value) or np.isinf(iteration_variable_value): + error_msg = f"Iteration variable {name} invalid number" + raise ProcessValueError( + error_msg, iteration_variable_value=iteration_variable_value + ) + + +def load_iteration_variables(): + """Loads the physics and engineering variables into the optimisation variable array.""" + + for i in range(fortran.numerics.nvar): + variable_index = fortran.numerics.ixc[i].item() + iteration_variable = ITERATION_VARIABLES[variable_index] + + # use ... as the default return value because None might be a valid return from Fortran? + iteration_variable_value = getattr( + iteration_variable.module, + iteration_variable.target_name or iteration_variable.name, + ..., + ) + + if iteration_variable_value is ...: + error_msg = ( + f"Could not get the value for iteration variable {variable_index} " + f"({iteration_variable.name})" + ) + raise ProcessValueError(error_msg) + + # if an array index is specified, iteration_variable_value is currently + # the whole array and not just the element we are interested in. Lets extract + # the correct element + if iteration_variable.array_index is not None: + iteration_variable_value = iteration_variable_value[ + iteration_variable.array_index + ] + + fortran.numerics.xcm[i] = iteration_variable_value + fortran.numerics.name_xc[i] = string_to_f2py_compatible( + fortran.numerics.name_xc[i], iteration_variable.name + ) + + # warn of the iteration variable is also a scan variable because this will cause + # the optimiser and scan to overwrite the same variable and conflict + if iteration_variable.name in ( + f2py_compatible_to_string(fortran.global_variables.vlabel), + f2py_compatible_to_string(fortran.global_variables.vlabel_2), + ): + warn( + ( + "The sweep variable is also an iteration variable and will be " + "overwritten by the optimiser" + ), + stacklevel=3, + ) + + # check that the iteration variable is valid (not 0, NaN, inf, or very large) + + check_iteration_variable( + iteration_variable_value, + name=f"{variable_index} ({iteration_variable.name})", + ) + + fortran.numerics.scale[i] = 1.0 / iteration_variable_value + fortran.numerics.scafc[i] = 1.0 / fortran.numerics.scale[i] + + fortran.numerics.xcm[i] = iteration_variable_value * fortran.numerics.scale[i] + + +def set_scaled_iteration_variable(xc, nn: int): + """Converts scaled iteration variables back to their real values and sets them in the code. + + :param xc: scaled iteration variable values + :param nn: number of iteration variables + """ + + for i in range(nn): + # there is less error handling here than in load_iteration_variables + # because many errors will be caught in load_iteration_variables which is + # run first. This verifies the variables exist and the module target is correct. + variable_index = fortran.numerics.ixc[i].item() + iteration_variable = ITERATION_VARIABLES[variable_index] + + ratio = xc[i] / fortran.numerics.scale[i] + + if iteration_variable.array_index is None: + setattr( + iteration_variable.module, + iteration_variable.target_name or iteration_variable.name, + ratio, + ) + else: + current_array = getattr( + iteration_variable.module, + iteration_variable.target_name or iteration_variable.name, + ) + new_array = deepcopy(current_array) + new_array[iteration_variable.array_index] = ratio + setattr( + iteration_variable.module, + iteration_variable.target_name or iteration_variable.name, + new_array, + ) + + check_iteration_variable( + ratio, name=f"{variable_index} ({iteration_variable.name})" + ) + + +def load_scaled_bounds(): + """Sets the scaled bounds of the iteration variables.""" + + for i in range(fortran.numerics.nvar.item()): + variable_index = fortran.numerics.ixc[i].item() - 1 + fortran.numerics.itv_scaled_lower_bounds[i] = ( + fortran.numerics.boundl[variable_index] * fortran.numerics.scale[i] + ) + fortran.numerics.itv_scaled_upper_bounds[i] = ( + fortran.numerics.boundu[variable_index] * fortran.numerics.scale[i] + ) + + +def initialise_iteration_variables(): + """Initialise the iteration variables (label and default bounds)""" + for itv_index, itv in ITERATION_VARIABLES.items(): + fortran.numerics.lablxc[itv_index - 1] = string_to_f2py_compatible( + fortran.numerics.lablxc[itv_index - 1], itv.name + ) + + fortran.numerics.boundl[itv_index - 1] = itv.lower_bound + fortran.numerics.boundu[itv_index - 1] = itv.upper_bound diff --git a/process/main.py b/process/main.py index c95b612ad5..c1e022ba8e 100644 --- a/process/main.py +++ b/process/main.py @@ -80,6 +80,7 @@ process_warnings, vary_iteration_variables, ) +from process.iteration_variables import load_iteration_variables from process.pfcoil import PFCoil from process.physics import Physics from process.plasma_geometry import PlasmaGeom @@ -480,7 +481,7 @@ def run_scan(self, solver): elif fortran.numerics.ioptimz == -2: # No optimisation: compute the output variables now # Get optimisation parameters x, evaluate models - fortran.define_iteration_variables.loadxc() + load_iteration_variables() self.ifail = 6 write_output_files(models=self.models, ifail=self.ifail) self.show_errors() diff --git a/process/optimiser.py b/process/optimiser.py index 9cafbf7b18..92996c1416 100644 --- a/process/optimiser.py +++ b/process/optimiser.py @@ -1,5 +1,6 @@ from process.evaluators import Evaluators -from process.fortran import define_iteration_variables, numerics +from process.fortran import numerics +from process.iteration_variables import load_iteration_variables, load_scaled_bounds from process.solver import get_solver @@ -25,8 +26,8 @@ def __init__(self, models, solver_name): def run(self): """Run vmcon solver and retry if it fails in certain ways.""" # Initialise iteration variables and bounds in Fortran - define_iteration_variables.loadxc() - define_iteration_variables.boundxc() + load_iteration_variables() + load_scaled_bounds() # Initialise iteration variables and bounds in Python: relies on Fortran # iteration variables being defined above diff --git a/process/utilities/f2py_string_patch.py b/process/utilities/f2py_string_patch.py index ed4b2b83ac..aa60cf4d08 100644 --- a/process/utilities/f2py_string_patch.py +++ b/process/utilities/f2py_string_patch.py @@ -43,12 +43,14 @@ def string_to_f2py_compatible( if string: if len(string) > target_size and except_length: raise RuntimeError( - f"String string of length {len(string)} is trying to initiate as {target} with length {target_size}" + f"String {string} of length {len(string)} is trying to initiate as {target} with length {target_size}" ) if len(string) > target_size: warnings.warn( - f"String string of length {len(string)} is trying to initiate as {target} with length \ - {target_size}. String string will be truncated!", + ( + f"String {string} of length {len(string)} is trying to initiate as {target} with length" + f"{target_size}. String string will be truncated!" + ), stacklevel=2, ) diff --git a/scripts/create_dicts.py b/scripts/create_dicts.py index 3736ae6260..30b92c314b 100644 --- a/scripts/create_dicts.py +++ b/scripts/create_dicts.py @@ -28,6 +28,7 @@ from python_dicts import get_python_variables from process.input import INPUT_VARIABLES +from process.iteration_variables import ITERATION_VARIABLES from process.scan import SCAN_VARIABLES INPUT_TYPE_MAP = {int: "int", float: "real", str: "string"} @@ -803,57 +804,16 @@ def dict_nsweep2varname(): def dict_ixc_full(): """Function to return a dictionary matching str(ixc_no) to a dictionary - containing the name, lower and upper bounds of that variable. Looks in - numerics.f90 at !+ad_varc lines in lablxc to get ixc_no and - variable names, and looks at boundu and boundl for upper and - lower bounds. - - Example of a lablxc line we are looking for: - lablxc(1) = 'aspect ' - - Example of a boundl line we are looking for: - boundl(1) = 0.0D0 - - Example of a boundu line we are looking for: - boundu(1) = 1.0D0 + containing the name, lower and upper bounds of that variable. Example dictionary entry: DICT_IXC_FULL['5'] = {'name' : 'beta', 'lb' : 0.001, 'ub' : 1.0} """ - with open(SOURCEDIR + "/iteration_variables.f90") as my_file: - lines = my_file.readlines() - - ixc_full = {} - - for lline in lines: - if "subroutine init_itv_" in lline and "end" not in lline: - itv_num = lline.split("_")[-1].strip("\n").replace(" ", "") - ixc_full[itv_num] = {} - - for line in lines: - if ("lablxc" in line and "=" in line) and ( - "lablxc(i)" not in line and "lablxc(ixc(i))" not in line - ): - labl_num = line.split("(")[1].split(")")[0] - labl = line.split("=")[-1].strip("\n").replace(" ", "").replace("'", "") - ixc_full[labl_num]["name"] = labl - - if ("boundl(" in line and "=" in line) and ( - "boundl(i)" not in line and "boundl(ixc(i))" not in line - ): - boundl_num = line.split("(")[1].split(")")[0] - boundl_val = line.split("=")[-1].strip("\n").lower().replace("d", "e") - ixc_full[boundl_num]["lb"] = float(boundl_val) - - if ("boundu(" in line and "=" in line) and ( - "boundu(i)" not in line and "boundu(ixc(i))" not in line - ): - boundu_num = line.split("(")[1].split(")")[0] - boundu_val = line.split("=")[-1].strip("\n").lower().replace("d", "e") - ixc_full[boundu_num]["ub"] = float(boundu_val) - - return ixc_full + return { + str(k): {"name": v.name, "lb": v.lower_bound, "ub": v.upper_bound} + for k, v in ITERATION_VARIABLES.items() + } def dict_ixc_bounds(): diff --git a/source/fortran/iteration_variables.f90 b/source/fortran/iteration_variables.f90 deleted file mode 100755 index 34540907ed..0000000000 --- a/source/fortran/iteration_variables.f90 +++ /dev/null @@ -1,4479 +0,0 @@ -module define_iteration_variables - !! Module to define iteration variables - -#ifndef dp - use, intrinsic :: iso_fortran_env, only: dp=>real64 -#endif - implicit none - - public - - real(dp) :: DUMMY - -contains - - subroutine init_define_iteration_variables - !! Initialise module variables - implicit none - - DUMMY = 0.0D0 - end subroutine init_define_iteration_variables - - !! lablxc(ipnvars) : labels describing iteration variables