nx_vessel_design.nx source
↩ module page · 60 lines · 2717 B
1// nx_vessel_design.nx -- H3 of the HARDWARE-IN-THE-LOOP ladder: DESIGN
2// CERTIFICATION. Feed in a candidate hardware spec (vessel thermal mass,
3// heater watts, insulation, thermal-cutoff setpoint) and a target recipe,
4// and it runs the full verification battery -- sizing, heat-up time,
5// closed-loop stability, fault containment -- returning PASS or a specific
6// FAIL reason. This is the model-based-systems-engineering sign-off a
7// fighter programme does before committing to the build.
8//
9// Composes the whole HIL stack: H0 sizing, H1 control loop, H2 fault
10// injection, and the R4 recipe for the target setpoint.
11//
12// genealogy_id: mbse_design_verification + nishi_hil_h0_h1_h2
13
14import "nx_syscalls.nx"
15import "nx_ferment_safety.nx"
16import "nx_ferment_thermal.nx"
17import "nx_vessel_thermal.nx"
18import "nx_vessel_io.nx"
19import "nx_vessel_faults.nx"
20const NX_MAGIC_2000: i64 = 2000
21
22const NX_DV_PASS: i64 = 0
23const NX_DV_FAIL_UNDERSIZED: i64 = 1 // heater can't reach the setpoint
24const NX_DV_FAIL_CUTOFF_TOO_LOW: i64 = 2 // fuse would trip during normal hold
25const NX_DV_FAIL_TOO_SLOW: i64 = 3 // can't reach setpoint within budget
26const NX_DV_FAIL_NO_CONTAINMENT: i64 = 4 // fuse fails to bound a stuck heater
27
28// Certify a hardware design against a target setpoint. heatup_budget_steps
29// is the allowed heat-up time (in 60 s steps).
30func nx_vessel_design_verify(env: *NxFermentSafetyEnvelope, twin: *NxVesselThermal,
31 cutoff_mc: i64, setpoint_mc: i64,
32 heatup_budget_steps: i64) -> i64 {
33 // 1. SIZING: can the heater overcome the losses to reach the setpoint?
34 if nx_vessel_can_reach(twin, setpoint_mc) == 0 { return NX_DV_FAIL_UNDERSIZED }
35
36 // 2. CUTOFF placement: the fuse must sit ABOVE the setpoint, or it would
37 // trip during normal operation.
38 if cutoff_mc <= setpoint_mc { return NX_DV_FAIL_CUTOFF_TOO_LOW }
39
40 // 3. HEAT-UP TIME: reach the setpoint within the budget at full duty.
41 var temp: i64 = twin.ambient_mc
42 var steps: i64 = 0
43 var reached: i64 = 0
44 while steps < heatup_budget_steps {
45 temp = nx_vessel_thermal_step(twin, temp, 1000, 60)
46 if temp >= setpoint_mc {
47 reached = 1
48 steps = heatup_budget_steps
49 }
50 steps = steps + 1
51 }
52 if reached == 0 { return NX_DV_FAIL_TOO_SLOW }
53
54 // 4. FAULT CONTAINMENT: a stuck-on heater must be bounded by the fuse.
55 let fin: *i64 = (sys_mmap(8)) as *i64
56 let maxt: i64 = nx_vessel_fault_run(env, twin, NX_VFAULT_HEATER_STUCK_ON, cutoff_mc, 800, fin)
57 if maxt >= cutoff_mc + NX_MAGIC_2000 { return NX_DV_FAIL_NO_CONTAINMENT }
58
59 return NX_DV_PASS
60}