code wiki / (root) / nx_estimate_test.nx

nx_estimate_test.nx source

↩ module page · 95 lines · 4200 B

1// nx_estimate_test.nx -- pre-print estimate sanity checks against 2// hand-computed expected ranges. 3// 4// Test inputs: tetrahedron at edge=10mm (Q14 = 10*16384=163840), 5// Qidi X-Max 3 + Generic PLA, 20% infill. 6// 7// Expected math: 8// bbox extent = 10mm × 10mm × 10mm 9// bbox volume = 1000 mm³ 10// perim_fraction = 8%; infill_fraction = (100-8)*20/100 = 18.4% 11// solid_pct = 26% -> solid_volume ≈ 260 mm³ (with integer trunc, 260) 12// filament_xsect (1.75mm) = π × 0.875² ≈ 2.405 mm² 13// filament_mm = 260 / 2.405 ≈ 108 mm 14// sustainable_flow = min(machine 35, material 15) = 15 mm³/s 15// extrude_time = 260 / 15 ≈ 17.3 sec; with 25% overhead ≈ 21.7 sec 16// print_minutes ≈ 0 (rounds down from 21 sec) 17// 18// Closed-form invariants: 19// (a) OK verdict for 10mm tetrahedron + 20% infill PLA on Qidi. 20// (b) volume_mm3 in [200, 320] 21// (c) filament_mm in [80, 140] 22// (d) print_minutes in [0, 1] 23// (e) WARN_TINY for 1mm tetrahedron (tiny volume) 24// (f) WARN_LONG for huge mesh (200mm cube ≈ 8M mm³ -> >24h at low 25// flow). 26// (g) WARN_FIL for medium-large mesh consuming > 250m filament. 27// (h) ERR_INPUT for negative density. 28// (i) Verdict names non-NULL. 29// 30// expect_exit: 0 31// license_tier: ORIGINAL 32 33import "nx_syscalls.nx" 34import "nx_mesh.nx" 35import "nx_machine_graph.nx" 36import "nx_material_profile.nx" 37import "nx_estimate.nx" 38 39const Q14: i64 = 16384 40 41func main() -> i64 { 42 let qidi: *NxMachineGraph = nx_machine_graph_qidi_xmax3() 43 let pla: *NxMaterialProfile = nx_material_profile_generic_pla() 44 45 // --- (a)(b)(c)(d) 10mm tetrahedron, 20% infill --- 46 let tet: *NxMesh = nx_mesh_make_tetrahedron(10 * Q14, 0) 47 let r: *NxPrintEstimate = nx_estimate_print(tet, qidi, pla, 20) 48 if r.verdict != NX_EST_OK { return 10 } 49 if r.volume_mm3 < 200 { return 11 } 50 if r.volume_mm3 > 320 { return 12 } 51 if r.filament_mm < 80 { return 13 } 52 if r.filament_mm > 140 { return 14 } 53 if r.print_minutes < 0 { return 15 } 54 if r.print_minutes > 1 { return 16 } 55 56 // --- (e) 3mm tetrahedron -> WARN_TINY (1mm would round volume to 0) --- 57 let tiny: *NxMesh = nx_mesh_make_tetrahedron(3 * Q14, 0) 58 let r_tiny: *NxPrintEstimate = nx_estimate_print(tiny, qidi, pla, 20) 59 if r_tiny.verdict != NX_EST_WARN_TINY { return 20 } 60 61 // --- (f) 200mm tetrahedron, 100% infill -> WARN_LONG --- 62 // bbox volume = 200³ = 8e6 mm³ × 92% solid (perim+full infill) 63 // = ~7.4M mm³ / 15 mm³/s ≈ 137 hours -> WARN_LONG (>1440 min) 64 let big: *NxMesh = nx_mesh_make_tetrahedron(200 * Q14, 0) 65 let r_big: *NxPrintEstimate = nx_estimate_print(big, qidi, pla, 100) 66 if r_big.verdict != NX_EST_WARN_LONG { return 30 } 67 68 // --- (g) 100mm tetrahedron, 100% infill -> WARN_FIL --- 69 // bbox 1e6 mm³ × 92% = 920000 / 2.405 = ~382k mm filament > 250k 70 // BUT also long print -- WARN_LONG fires first per check order. 71 // Use 60mm tetrahedron with 100% infill: 72 // bbox 216000 × 92% = 198720 / 2.405 ≈ 82600mm = 82m filament -- under 250k 73 // Need exactly the in-between case... try 80mm 100%: 74 // bbox 512000 × 92% = 471000 / 2.405 = ~196000 mm = 196m -- still under 75 // Try 95mm 100%: 76 // bbox 857375 × 92% = 788785 / 2.405 = ~328000mm = 328m -- > 250m! YES 77 // But also check time: 788785 / 15 = ~52600 sec * 1.25 = 65750 sec = 1095 min 78 // < 1440 so WARN_FIL fires before WARN_LONG. 79 let med: *NxMesh = nx_mesh_make_tetrahedron(95 * Q14, 0) 80 let r_med: *NxPrintEstimate = nx_estimate_print(med, qidi, pla, 100) 81 if r_med.verdict != NX_EST_WARN_FIL { return 40 } 82 83 // --- (h) ERR_INPUT for negative density --- 84 let r_bad: *NxPrintEstimate = nx_estimate_print(tet, qidi, pla, -10) 85 if r_bad.verdict != NX_EST_ERR_INPUT { return 50 } 86 87 // --- (i) Verdict names --- 88 if (nx_est_verdict_name(NX_EST_OK) as i64) == 0 { return 60 } 89 if (nx_est_verdict_name(NX_EST_WARN_LONG) as i64) == 0 { return 61 } 90 if (nx_est_verdict_name(NX_EST_WARN_FIL) as i64) == 0 { return 62 } 91 if (nx_est_verdict_name(NX_EST_WARN_TINY) as i64) == 0 { return 63 } 92 if (nx_est_verdict_name(NX_EST_ERR_INPUT) as i64) == 0 { return 64 } 93 94 return 0 95}