nx_stress_test.nx source
↩ module page · 86 lines · 3268 B
1// nx_stress_test.nx -- stress = force/area + per-material yield
2// classification against hand-computed reference cases.
3//
4// All Q14 throughout (force in Q14 N, area in Q14 m²). σ_Pa = F_q14 / A_q14
5// since Q14 cancels in the ratio.
6//
7// Closed-form invariants:
8// (a) Zero force on unit area: σ = 0 Pa.
9// (b) 100 N on 1 m² = 100 Pa.
10// F_q14 = 100 * 16384, A_q14 = 16384 → σ = 100*16384/16384 = 100 Pa.
11// (c) 100 N on 0.001 m² = 100000 Pa = 100 kPa.
12// (d) Zero area returns NULL (defensive).
13// (e) PLA yield = 50 MPa = 50000000 Pa.
14// (f) PEEK yield = 95 MPa, ultimate = 100 MPa.
15// (g) 25 MPa on PLA -> SAFE (< 50/2 = 25 MPa).
16// Actually 25 == yield/2 boundary; classifier uses `>=` so this
17//
18// is exactly WORKING. Let me use 24 MPa for SAFE.
19// (h) 30 MPa on PLA -> WORKING (>= 25, < 50).
20// (i) 50 MPa on PLA -> YIELDED.
21// (j) 70 MPa on PLA -> FRACTURED (>= 65 ultimate).
22// (k) Unknown material class (99) -> UNKNOWN_MAT verdict.
23// (l) MPa conversion: 50000000 Pa -> 50 MPa.
24//
25// expect_exit: 0
26// license_tier: ORIGINAL
27
28import "nx_syscalls.nx"
29import "nx_material_profile.nx"
30import "nx_stress.nx"
31
32const Q14: i64 = 16384
33
34func main() -> i64 {
35 // --- (a) zero force ---
36 let s0: *NxStress = nx_stress_from_force_area(0, Q14)
37 if s0.pa != 0 { return 10 }
38
39 // --- (b) 100 N / 1 m² = 100 Pa ---
40 let s100: *NxStress = nx_stress_from_force_area(100 * Q14, Q14)
41 if s100.pa != 100 { return 20 }
42
43 // --- (c) 100 N / 0.001 m² = 100000 Pa = 100 kPa ---
44 // 0.001 in Q14 = 16 (rounds 16.384 → 16; some Q14 loss)
45 let a_small: i64 = Q14 / 1000 // 16
46 let sk: *NxStress = nx_stress_from_force_area(100 * Q14, a_small)
47 // Expected: 100*16384/16 = 102400 Pa (slightly > 100000 due to rounding)
48 if sk.pa < 100000 { return 30 }
49 if sk.pa > 110000 { return 31 }
50
51 // --- (d) Zero area returns NULL ---
52 let s_bad: *NxStress = nx_stress_from_force_area(100 * Q14, 0)
53 if (s_bad as i64) != 0 { return 40 }
54
55 // --- (e) PLA yield = 50 MPa ---
56 if nx_stress_yield_pa(NX_MAT_PLA) != 50000000 { return 50 }
57
58 // --- (f) PEEK ---
59 if nx_stress_yield_pa(NX_MAT_PEEK) != 95000000 { return 60 }
60 if nx_stress_ultimate_pa(NX_MAT_PEEK) != 100000000 { return 61 }
61
62 // --- (g) 24 MPa on PLA -> SAFE ---
63 let s24mpa: *NxStress = nx_stress_new(24000000)
64 if nx_stress_classify(s24mpa, NX_MAT_PLA) != NX_STRESS_SAFE { return 70 }
65
66 // --- (h) 30 MPa on PLA -> WORKING ---
67 let s30mpa: *NxStress = nx_stress_new(30000000)
68 if nx_stress_classify(s30mpa, NX_MAT_PLA) != NX_STRESS_WORKING { return 80 }
69
70 // --- (i) 50 MPa on PLA -> YIELDED ---
71 let s50mpa: *NxStress = nx_stress_new(50000000)
72 if nx_stress_classify(s50mpa, NX_MAT_PLA) != NX_STRESS_YIELDED { return 90 }
73
74 // --- (j) 70 MPa on PLA -> FRACTURED ---
75 let s70mpa: *NxStress = nx_stress_new(70000000)
76 if nx_stress_classify(s70mpa, NX_MAT_PLA) != NX_STRESS_FRACTURED { return 100 }
77
78 // --- (k) Unknown material ---
79 if nx_stress_classify(s50mpa, 99) != NX_STRESS_UNKNOWN_MAT { return 110 }
80
81 // --- (l) MPa conversion ---
82 let s50: *NxStress = nx_stress_new(50000000)
83 if nx_stress_to_mpa(s50) != 50 { return 120 }
84
85 return 0
86}