Skip to content

Commit 61430b7

Browse files
committed
Address Mike's requests to change component names
1 parent a7e94b0 commit 61430b7

File tree

1 file changed

+104
-37
lines changed

1 file changed

+104
-37
lines changed

src/boutupgrader/hermes_collisions_input_file_upgrader.py

Lines changed: 104 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
import re
21
from itertools import chain
32
from typing import TypedDict
3+
from warnings import warn
44

55
from boutdata.data import BoutOptionsFile
66

@@ -15,57 +15,124 @@ class Replacement(TypedDict):
1515
REPLACEMENTS = []
1616
DELETED = []
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

3278
def 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

71138
def run(args) -> None:

0 commit comments

Comments
 (0)