code wiki / (root) / nx_vessel_twin.nx

nx_vessel_twin.nx source

↩ module page · 60 lines · 2772 B

1// nx_vessel_twin.nx -- CAPSTONE of the HARDWARE-IN-THE-LOOP ladder: the 2// full DIGITAL TWIN sign-off. Given a candidate device (thermal mass, 3// heater, insulation, thermal-cutoff) and a target recipe, it certifies 4// the COMPLETE system end-to-end in software: 5// 6// 1. HARDWARE (H3 = H0 sizing + H1 control + H2 faults): the device can 7// reach, hold, and fail safe. 8// 2. PROCESS (R3 kinetics): at the recipe's hold temperature the ferment 9// actually acidifies to a safe pH within the never-poison window. 10// 3. SAFETY (H2): a stuck heater is contained by the independent fuse. 11// 12// Only if all three pass is the (device, recipe) pair CERTIFIED for build. 13// This is the model-based "iron-bird + flight-sim" certification a fighter 14// programme completes before the first metal is cut -- here for a fermenter 15// so the hardware is the LAST, de-risked step. 16// 17// genealogy_id: nishi_hil_h3 + nishi_ferment_kinetics_r3 + nishi_ferment_recipes_r4 18 19import "nx_syscalls.nx" 20import "nx_ferment_safety.nx" 21import "nx_ferment_kinetics.nx" 22import "nx_ferment_recipes.nx" 23import "nx_vessel_thermal.nx" 24import "nx_vessel_io.nx" 25import "nx_vessel_faults.nx" 26import "nx_vessel_design.nx" 27const NX_MAGIC_2000: i64 = 2000 28 29const NX_TWIN_CERTIFIED: i64 = 0 30const NX_TWIN_FAIL_DESIGN: i64 = 1 // hardware design rejected (H3) 31const NX_TWIN_FAIL_WONT_FERMENT:i64 = 2 // won't acidify in the window (R3) 32const NX_TWIN_FAIL_UNSAFE_FAULT:i64 = 3 // not contained under a fault (H2) 33 34func nx_vessel_twin_certify(env: *NxFermentSafetyEnvelope, twin: *NxVesselThermal, 35 cutoff_mc: i64, recipe_id: i64) -> i64 { 36 let r: *NxFermentRecipeSpec = nx_ferment_recipe(recipe_id) 37 let setpoint_c: i64 = r.hold_temp_c 38 let setpoint_mc: i64 = setpoint_c * 1000 39 let oxygen: i64 = r.oxygen 40 41 // 1. HARDWARE design certification (H3 rolls up H0 + H1 + H2). 42 if nx_vessel_design_verify(env, twin, cutoff_mc, setpoint_mc, 300) != NX_DV_PASS { 43 return NX_TWIN_FAIL_DESIGN 44 } 45 46 // 2. PROCESS feasibility: an anaerobic ferment must reach safe pH within 47 // the never-poison window at this hold temperature (R3 kinetics). 48 if oxygen == NX_OX_ANAEROBIC { 49 let set_h: i64 = nx_ferment_kinetics_set_time(setpoint_c) 50 if set_h <= 0 { return NX_TWIN_FAIL_WONT_FERMENT } 51 if set_h > (env.max_hours_to_acidify as i64) { return NX_TWIN_FAIL_WONT_FERMENT } 52 } 53 54 // 3. SAFETY: a stuck-on heater is bounded by the independent fuse (H2). 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_TWIN_FAIL_UNSAFE_FAULT } 58 59 return NX_TWIN_CERTIFIED 60}