Skip to content

Commit e4db6f8

Browse files
committed
'0304'
1 parent fed875f commit e4db6f8

5 files changed

Lines changed: 118 additions & 73 deletions

File tree

model/APEX/ds_param.yaml

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,10 @@
11
design_parameters:
2+
- name: SOL_K
3+
type: float
4+
mode: v
5+
bounds: [0.0001, 10]
6+
cache: True
7+
28
- name: GWSO
39
type: float
410
mode: v
@@ -183,4 +189,4 @@ design_parameters:
183189
type: float
184190
mode: v
185191
bounds: [0.01, 0.05]
186-
cache: True
192+
cache: True

model/APEX/paraLibrary.yaml

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -308,3 +308,14 @@ parameter_library:
308308
start: 25
309309
width: 8
310310
precision: 2
311+
312+
- name: SOL_K
313+
type: float
314+
bounds: [0.0001, 100]
315+
file:
316+
name: "*.SOL"
317+
line: 22
318+
start: 1
319+
width: 8
320+
precision: 2
321+
maxNum: 10

model/APEX/param_manager.py

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ class ParamFileSpec:
2424
start: int
2525
width: int
2626
precision: int
27+
maxNum: int
2728

2829
@dataclass
2930
class ParamSpec:
@@ -39,7 +40,10 @@ def from_dict(d: Dict[str, Any]) -> "ParamSpec":
3940
name=d["name"],
4041
type=TYPE_MAP.get(d["type"], 0),
4142
bounds=d["bounds"],
42-
file=ParamFileSpec(**d["file"])
43+
file=ParamFileSpec(name=d["file"]["name"], line=d["file"]["line"],
44+
start=d["file"]["start"], width=d["file"]["width"],
45+
precision=d["file"]["precision"],
46+
maxNum=int(d["file"].get("maxNum", 1))),
4347
)
4448

4549
@property
@@ -101,7 +105,7 @@ def from_dict(d: Dict[str, Any], index: int):
101105
)
102106

103107
# -------------------------------------------------------------
104-
# Parameter Manager (重构版)
108+
# Parameter Manager
105109
# -------------------------------------------------------------
106110

107111
class ParamManager:

model/APEX/runoff.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ basic:
55
workPath: "E:/Apex_workPath"
66
command: "APEX1501_rel32.exe"
77
timeout: 120
8-
parallel: 15
8+
parallel: 1
99

1010
parameters:
1111
library: "paraLibrary.yaml"

model/APEX/write_in_handler.py

Lines changed: 93 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ class SubEntry:
1111
class Parameter:
1212
name: str
1313
index: int
14-
entry: SubEntry
14+
entries: List[SubEntry]
1515
mode: int # 0: orig*(1+x), 1: =x, 2: orig+x
1616
typ: int # 1: int, else: float
1717
precision: int
@@ -85,7 +85,7 @@ def register_param(
8585
precision = lib_info.file.precision
8686
lb = lib_info.lb if hardBound else None
8787
ub = lib_info.ub if hardBound else None
88-
88+
maxNum = lib_info.file.maxNum
8989
line_idx = linePos - 1
9090

9191
if typ == 1:
@@ -95,18 +95,23 @@ def register_param(
9595
ub = int(ub)
9696

9797
line_start = self.line_offsets[line_idx]
98-
99-
off = line_start + (staPos - 1)
100-
101-
field = bytes(self.base_content[off:off + width])
102-
val = self._parse_float_field(field)
103-
104-
entry = SubEntry(offset=off, original_val=val)
98+
# TODO
99+
if line_idx + 1 < len(self.line_offsets):
100+
line_end = self.line_offsets[line_idx + 1]
101+
else:
102+
line_end = len(self.base_content)
103+
base_offset = line_start + (staPos - 1)
104+
entries = self._scan_entries(
105+
start_offset=base_offset,
106+
width=width,
107+
max_num=maxNum,
108+
line_end_offset=line_end
109+
)
105110

106111
self.params[index] = Parameter(
107112
name = name,
108113
index = index,
109-
entry = entry,
114+
entries = entries,
110115
mode = mode,
111116
typ = typ,
112117
precision = precision,
@@ -118,66 +123,85 @@ def register_param(
118123
return True
119124

120125
def set_values_and_save(
121-
self,
122-
output_filepath: str,
123-
indices: List[int],
124-
vals: List[float],
125-
warn_stacklevel: int = 2,
126-
warn_detail_limit: int = 20,
127-
):
126+
self,
127+
output_filepath: str,
128+
indices: List[int],
129+
vals: List[float],
130+
warn_stacklevel: int = 2,
131+
warn_detail_limit: int = 20,
132+
):
133+
134+
self.file_content = bytearray(self.base_content)
135+
mods: List[Modification] = []
136+
clamp_events = []
137+
138+
for idx, input_val in zip(indices, vals):
139+
p = self.params.get(idx)
140+
if not p:
141+
continue
142+
143+
for e in p.entries:
144+
145+
if p.mode == 0: # relative %
146+
raw = e.original_val * (1.0 + float(input_val))
147+
elif p.mode == 1: # replace
148+
raw = float(input_val)
149+
elif p.mode == 2: # absolute add
150+
raw = e.original_val + float(input_val)
151+
else:
152+
raw = float(input_val)
153+
154+
raw2 = int(raw) if p.typ == 1 else raw
155+
156+
clamped = raw2
157+
if p.lb is not None and clamped < p.lb:
158+
clamped = p.lb
159+
if p.ub is not None and clamped > p.ub:
160+
clamped = p.ub
161+
162+
if clamped != raw2:
163+
clamp_events.append((idx, p.name, raw2, clamped, p.lb, p.ub))
164+
165+
b = self._format_value(clamped, p.width, p.precision, p.typ)
166+
mods.append(Modification(offset=e.offset, width=p.width, data=b))
167+
168+
for m in mods:
169+
self.file_content[m.offset : m.offset + m.width] = m.data
170+
171+
if clamp_events:
172+
head = clamp_events[:warn_detail_limit]
173+
msg_lines = [
174+
f"Param clamp: {output_filepath}, idx={i}, raw={raw:.2f}->{clamped:.2f}"
175+
for (i, name, raw, clamped, lb, ub) in head
176+
]
177+
more = "" if len(clamp_events) <= warn_detail_limit else f"\n... {len(clamp_events)-warn_detail_limit} more"
178+
warnings.warn("\n".join(msg_lines) + more, stacklevel=warn_stacklevel)
179+
180+
with open(output_filepath, "wb") as out:
181+
out.write(self.file_content)
182+
183+
def _scan_entries(
184+
self, start_offset: int, width: int, max_num: int, line_end_offset: int
185+
) -> List[SubEntry]:
186+
187+
entries = []
128188

129-
self.file_content = bytearray(self.base_content)
189+
for i in range(max_num):
190+
curr_off = start_offset + (i * width)
191+
curr_end = curr_off + width
192+
193+
if curr_end > line_end_offset:
194+
break
195+
196+
if curr_end > len(self.base_content):
197+
break
198+
199+
field = bytes(self.base_content[curr_off : curr_end])
200+
val = self._parse_float_field(field)
130201

131-
mods: List[Modification] = []
132-
clamp_events = []
202+
if val is None:
203+
break
133204

134-
for idx, input_val in zip(indices, vals):
205+
entries.append(SubEntry(offset=curr_off, original_val=val))
135206

136-
p = self.params.get(idx)
137-
if not p:
138-
continue
139-
140-
e = p.entry
141-
142-
# 1) calculate raw
143-
if p.mode == 0:
144-
raw = e.original_val * (1.0 + float(input_val))
145-
elif p.mode == 1:
146-
raw = float(input_val)
147-
elif p.mode == 2:
148-
raw = e.original_val + float(input_val)
149-
else:
150-
raw = float(input_val)
151-
152-
# 2) transform type
153-
raw2 = int(raw) if p.typ == 1 else raw
154-
155-
# 3) clamp (warning)
156-
clamped = raw2
157-
if p.lb is not None and clamped < p.lb:
158-
clamped = p.lb
159-
if p.ub is not None and clamped > p.ub:
160-
clamped = p.ub
161-
162-
if clamped != raw2:
163-
clamp_events.append((idx, p.name, raw2, clamped, p.lb, p.ub))
164-
165-
b = self._format_value(clamped, p.width, p.precision, p.typ)
166-
mods.append(Modification(offset=e.offset, width=p.width, data=b))
167-
168-
for m in mods:
169-
self.file_content[m.offset:m.offset + m.width] = m.data
170-
171-
if clamp_events:
172-
head = clamp_events[:warn_detail_limit]
173-
msg_lines = [
174-
f"Param clamp: in file {output_filepath}, idx={i}, name={name}, {raw} -> {clamped}, hardBounds=[{lb},{ub}]"
175-
for (i, name, raw, clamped, lb, ub) in head
176-
]
177-
more = "" if len(clamp_events) <= warn_detail_limit else (
178-
f"\n... and {len(clamp_events) - warn_detail_limit} more clamps"
179-
)
180-
warnings.warn("\n".join(msg_lines) + more, stacklevel=warn_stacklevel)
181-
182-
with open(output_filepath, "wb") as out:
183-
out.write(self.file_content)
207+
return entries

0 commit comments

Comments
 (0)