1- import re
21from itertools import chain
32from typing import TypedDict
3+ from warnings import warn
44
55from boutdata .data import BoutOptionsFile
66
@@ -15,57 +15,124 @@ class Replacement(TypedDict):
1515REPLACEMENTS = []
1616DELETED = []
1717
18- NEW_NAMES = {
19- "collisions" : [
20- "braginskii_collisions" ,
21- "braginskii_friction" ,
22- "braginskii_heat_exchange" ,
23- ],
24- "electron_viscosity" : ["braginskii_electron_viscosity" ],
25- "ion_viscosity" : ["braginskii_ion_viscosity" ],
26- "thermal_force" : ["braginskii_thermal_force" ],
18+ NEW_NAMES : dict [str , str | dict [str , list [str ]]] = {
19+ "collisions" : {
20+ "braginskii_collisions" : [
21+ "electron_electron" ,
22+ "electron_ion" ,
23+ "electron_neutral" ,
24+ "ion_ion" ,
25+ "ion_neutral" ,
26+ "neutral_neutral" ,
27+ "ei_multiplier" ,
28+ "diagnose" ,
29+ ],
30+ "braginskii_friction" : ["frictional_heating" , "diagnose" ],
31+ "braginskii_heat_exchange" : ["diagnose" ],
32+ },
33+ "electron_viscosity" : "braginskii_electron_viscosity" ,
34+ "ion_viscosity" : "braginskii_ion_viscosity" ,
35+ "thermal_force" : "braginskii_thermal_force" ,
2736}
2837
29- COMPONENT_RE = re .compile (r"[+\-\w]+" )
38+ # If name in `components` and type not given then change the name in components and heading; if a multi-replacement, duplicate the section
39+ # If type is same as name, duplicate section
40+ # If name in type of any component, change it there (don't duplicate)
41+
42+
43+ def split_list_string (list_string : str ) -> tuple [list [str ], bool ]:
44+ result = [tname .strip () for tname in list_string .split ("," )]
45+ open_paren = result [0 ][0 ] == "("
46+ close_paren = result [- 1 ][- 1 ] == ")"
47+ if open_paren != close_paren :
48+ warn (f'Unmatched parentheses around "{ list_string } "' )
49+ if open_paren :
50+ result [0 ] = result [0 ][1 :]
51+ if close_paren :
52+ result [- 1 ] = result [- 1 ][:- 1 ]
53+ return result , open_paren and close_paren
54+
55+
56+ def rename_simple_component (
57+ options_file : BoutOptionsFile , section_name : str
58+ ) -> list [str ]:
59+ """Rename a component when its type is the same as its name."""
60+ if section_name in NEW_NAMES :
61+ new_names = NEW_NAMES [section_name ]
62+ if isinstance (new_names , dict ):
63+ old_section = options_file .getSection (section_name )
64+ new_components = []
65+ for new_name , configs in new_names .items ():
66+ new_components .append (new_name )
67+ new_section = options_file .getSection (new_name )
68+ for conf in configs :
69+ if conf in old_section :
70+ new_section [conf ] = old_section [conf ]
71+ return new_components
72+ else :
73+ options_file .rename (section_name , new_names )
74+ return [new_names ]
75+ return [section_name ]
3076
3177
3278def update_component_names (options_file : BoutOptionsFile ) -> None :
3379 """Change the names of closure-related components to reflect the refactor"""
3480 has_collisions = False
3581 recycling_component = ""
36- components = re .findall (COMPONENT_RE , options_file ["hermes:components" ])
37- for section_name in components :
82+ old_components , has_parens = split_list_string (options_file ["hermes:components" ])
83+ new_components = []
84+ for section_name in old_components :
3885 section = options_file .getSection (section_name )
39- explicit_types = "type" in section
40- types = (
41- [tname .strip () for tname in section ["type" ].split ("," )]
42- if explicit_types
43- else [section_name ]
44- )
45- open_paren = types [0 ][0 ] == "("
46- close_paren = types [- 1 ][- 1 ] == ")"
47- if open_paren :
48- types [0 ] = types [0 ][1 :]
49- if close_paren :
50- types [- 1 ] = types [- 1 ][:- 1 ]
51- new_types = list (chain .from_iterable (NEW_NAMES .get (t , [t ]) for t in types ))
52- has_collisions = has_collisions or "collisions" in types
86+ # Component type is set explicitly
87+ if "type" in section :
88+ old_types , types_have_parens = split_list_string (section ["type" ])
89+ # If component name and type match, treat similarly to if no type were given (see below)
90+ if len (old_types ) == 1 and old_types [0 ] == section_name :
91+ has_collisions = has_collisions or section_name == "collisions"
92+ new_types = rename_simple_component (options_file , section_name )
93+ for t in new_types :
94+ options_file [f"{ t } :type" ] = (
95+ ("(" if types_have_parens else "" )
96+ + t
97+ + (")" if types_have_parens else "" )
98+ )
99+ new_components .extend (new_types )
100+ # Otherwise simply replace any type-names that need changing
101+ else :
102+ has_collisions = has_collisions or section_name in old_types
103+ new_types = list (
104+ chain .from_iterable (
105+ [nt ] if isinstance ((nt := NEW_NAMES .get (t , t )), str ) else nt
106+ for t in old_types
107+ )
108+ )
109+ if new_types != old_types :
110+ section ["type" ] = (
111+ ("(" if types_have_parens else "" )
112+ + ", " .join (new_types )
113+ + (")" if types_have_parens else "" )
114+ )
115+ new_components .append (section_name )
116+ # Component type is same as component name
117+ else :
118+ has_collisions = has_collisions or section_name == "collisions"
119+ new_types = rename_simple_component (options_file , section_name )
120+ new_components .extend (new_types )
53121 if "recycling" in new_types :
54122 recycling_component = section_name
55- if new_types != types :
56- section ["type" ] = (
57- ("(" if open_paren else "" )
58- + ", " .join (new_types )
59- + (")" if close_paren else "" )
60- )
61123 # Add braginskii_conduction to the end of the list of components
62124 if has_collisions :
63- components .append ("braginskii_conduction" )
125+ new_components .append ("braginskii_conduction" )
64126 # Make sure recycling is evaluated after conduction
65127 if recycling_component != "" :
66- components .remove (recycling_component )
67- components .append (recycling_component )
68- options_file ["hermes:components" ] = "(" + ", " .join (components ) + ")"
128+ new_components .remove (recycling_component )
129+ new_components .append (recycling_component )
130+ if new_components != old_components :
131+ options_file ["hermes:components" ] = (
132+ ("(" if has_parens else "" )
133+ + ", " .join (new_components )
134+ + (")" if has_parens else "" )
135+ )
69136
70137
71138def run (args ) -> None :
0 commit comments