Skip to content

Commit fb73094

Browse files
feat(parametricbuilder): add determinize.jl
1 parent 1889f1f commit fb73094

1 file changed

Lines changed: 122 additions & 0 deletions

File tree

Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
# ─────────────────────────────────────────────────────────────────────────────
2+
# Deterministic collapse (Monte Carlo on deterministic ranges only)
3+
# Policy: transform (valuespec, pctspec) → (merged_valuespec, nothing)
4+
# ─────────────────────────────────────────────────────────────────────────────
5+
6+
# Percent helpers
7+
@inline _pct(u) = float(u) / 100
8+
@inline _expand_nom(nom::Number, u::Number) = (nom*(1 - _pct(u)), nom*(1 + _pct(u)))
9+
@inline _expand_bounds(lo::Number, hi::Number, u1::Number, u2::Number) =
10+
(lo*(1 - _pct(u1)), hi*(1 + _pct(u2)))
11+
12+
# Deterministic collapse with pct interpreted as percent (not absolute)
13+
@inline function _det_pair(spec, pct)
14+
pct === nothing && return (spec, nothing)
15+
16+
# A) spec = (lo,hi,N1), pct = (u1,u2,N2) → ((lo(1-u1%), hi(1+u2%), N1*N2), nothing)
17+
if (spec isa Tuple && length(spec)==3 && all(x->x isa Number, spec)) &&
18+
(pct isa Tuple && length(pct) == 3 && all(x->x isa Number, pct))
19+
lo, hi, N1 = float(spec[1]), float(spec[2]), Int(spec[3])
20+
u1, u2, N2 = float(pct[1]), float(pct[2]), Int(pct[3])
21+
lo_det, hi_det = _expand_bounds(lo, hi, u1, u2)
22+
return ((lo_det, hi_det, N1 * N2), nothing)
23+
end
24+
25+
# B) spec = (lo,hi,N1), pct = u → ((lo(1-u%), hi(1+u%), N1), nothing)
26+
if (spec isa Tuple && length(spec)==3 && all(x->x isa Number, spec)) && (pct isa Number)
27+
lo, hi, N1 = float(spec[1]), float(spec[2]), Int(spec[3])
28+
u = float(pct)
29+
lo_det, hi_det = _expand_bounds(lo, hi, u, u)
30+
return ((lo_det, hi_det, N1), nothing)
31+
end
32+
33+
# C) spec = nom, pct = (u1,u2,N2) → ((nom(1-u1%), nom(1+u2%), N2), nothing)
34+
if (spec isa Number) && (pct isa Tuple && length(pct)==3 && all(x->x isa Number, pct))
35+
nom = float(spec)
36+
u1, u2, N2 = float(pct[1]), float(pct[2]), Int(pct[3])
37+
lo_det, hi_det = _expand_nom(nom, u1);
38+
_, hi2 = _expand_nom(nom, u2)
39+
# reuse lo_det from u1 and hi from u2 to respect asymmetric pct
40+
return ((lo_det, hi2, N2), nothing)
41+
end
42+
43+
# D) spec = nom, pct = u → ((nom(1-u%), nom(1+u%), 2), nothing)
44+
if (spec isa Number) && (pct isa Number)
45+
nom = float(spec);
46+
u = float(pct)
47+
lo_det, hi_det = _expand_nom(nom, u)
48+
return ((lo_det, hi_det, 2), nothing)
49+
end
50+
51+
# E) spec === nothing — no sensible base for %; safest is to drop pct
52+
return (spec, nothing)
53+
end
54+
55+
# Normalizer: accept a field already in (spec,pct) or as a scalar → return (spec’, nothing)
56+
@inline _det_field(x) = (x isa Tuple && length(x)==2) ? _det_pair(x[1], x[2]) : (x, nothing)
57+
58+
# ---- MaterialSpec ----
59+
function determinize(ms::MaterialSpec)
60+
MaterialSpec(
61+
rho = _det_field(ms.rho),
62+
eps_r = _det_field(ms.eps_r),
63+
mu_r = _det_field(ms.mu_r),
64+
T0 = _det_field(ms.T0),
65+
alpha = _det_field(ms.alpha),
66+
)
67+
end
68+
69+
# ---- PartSpec (dim, args, material) ----
70+
function determinize(ps::PartSpec)
71+
dim_det = _det_field(ps.dim)
72+
# each arg can be scalar or (spec,pct)
73+
args_det = map(a -> (a isa Tuple && length(a)==2) ? _det_field(a) : a, ps.args) |> Tuple
74+
mat_det = determinize(ps.material)
75+
return PartSpec(
76+
ps.component,
77+
ps.part_type,
78+
ps.n_layers;
79+
dim = dim_det,
80+
args = args_det,
81+
material = mat_det,
82+
)
83+
end
84+
85+
# ---- CableBuilderSpec (vector/nested parts) ----
86+
function determinize(cbs::CableBuilderSpec)
87+
parts_det = PartSpec[determinize(p) for p in cbs.parts]
88+
return CableBuilderSpec(cbs.cable_id, parts_det, cbs.nominal)
89+
end
90+
91+
# ─────────────────────────────────────────────────────────────────────────────
92+
# Deterministic collapse for SystemBuilderSpec (non-materializing)
93+
# ─────────────────────────────────────────────────────────────────────────────
94+
95+
@inline _det_axis(a) = (a isa Tuple && length(a)==2) ? _det_pair(a[1], a[2]) : a
96+
# determinize EarthSpec
97+
function determinize(e::EarthSpec)
98+
EarthSpec(
99+
rho = _det_field(e.rho),
100+
eps_r = _det_field(e.eps_r),
101+
mu_r = _det_field(e.mu_r),
102+
t = _det_field(e.t),
103+
)
104+
end
105+
106+
# determinize _Pos (keep anchors; just collapse dx/dy specs)
107+
function determinize(p::_Pos)
108+
_Pos(p.x0, p.y0, _det_axis(p.dx), _det_axis(p.dy), p.conn)
109+
end
110+
111+
# determinize SystemBuilderSpec
112+
function determinize(s::SystemBuilderSpec)
113+
SystemBuilderSpec(
114+
s.system_id,
115+
determinize(s.builder),
116+
[determinize(p) for p in s.positions];
117+
length = _det_field(s.length),
118+
temperature = _det_field(s.temperature),
119+
earth = determinize(s.earth),
120+
f = s.frequencies,
121+
)
122+
end

0 commit comments

Comments
 (0)