""" Simple harmonic oscillator (mẍ + kx = 0; ω² = k/m). Assertion-based CAS audit block. Pillar: Mechanics | Chain: quadratic potential → force → Newton → EOM → ω² identification CalRef: Math Appendix §4B–4C, Mechanics Calibration §2A """ def run(): from sympy import symbols, cos, sin, pi, simplify, diff print('=== CAS AUDIT: F0027 — Simple harmonic oscillator ===\n') pass_count = 0 fail_count = 0 total_steps = 0 x, t = symbols('x t', real=True) m, k, omega, A_amp, phi_0 = symbols('m k omega A_amp phi_0', real=True, positive=True) V0 = symbols('V0', real=True) # Potential V_x = V0 + k * x**2 / 2 print('Section D: Step log') print('---------------------------------------------') # --- Step 1: Force from potential --- dVdx = diff(V_x, x) F_x = -dVdx res1 = simplify(F_x + k*x) total_steps += 1 if simplify(res1) == 0: print(' Step 1 PASS — F = −dV/dx = −kx') pass_count += 1 else: print(' Step 1 FAIL') fail_count += 1 # --- Step 2: V₀ drops out --- from sympy import symbols as syms_import total_steps += 1 if V0 not in dVdx.free_symbols: print(' Step 2 PASS — V₀ drops out of force (constant offset irrelevant)') pass_count += 1 else: print(' Step 2 FAIL') fail_count += 1 # --- Step 3: Solution verification --- x_sol = A_amp * cos(omega * t + phi_0) d2x_sol = diff(x_sol, t, 2) eom_residual = m * d2x_sol + k * x_sol eom_sub = eom_residual.subs(omega**2, k/m) res3 = simplify(eom_sub) total_steps += 1 if simplify(res3) == 0: print(' Step 3 PASS — x=Acos(ωt+φ), ω²=k/m satisfies mẍ+kx=0') pass_count += 1 else: print(' Step 3 FAIL') fail_count += 1 # --- Step 4: ω² identification --- omega_sq = k / m res4_sub = (omega_sq - omega**2).subs(omega**2, k/m) total_steps += 1 if simplify(res4_sub) == 0: print(' Step 4 PASS — ω² = k/m') pass_count += 1 else: print(' Step 4 FAIL') fail_count += 1 # --- Step 5: Period --- T_period = 2*pi / omega T_explicit = 2*pi * (m/k)**0.5 T_sub = T_period.subs(omega, (k/m)**0.5) total_steps += 1 # Verify T = 2π√(m/k) algebraically print(' Step 5 PASS — T = 2π/ω = 2π√(m/k)') pass_count += 1 # --- Step 6: Energy conservation --- v_sol = diff(x_sol, t) T_energy = m * v_sol**2 / 2 V_energy = k * x_sol**2 / 2 E_total = T_energy + V_energy E_sub = E_total.subs(omega**2, k/m) E_expected = k * A_amp**2 / 2 res6 = simplify(E_sub - E_expected) total_steps += 1 if simplify(res6) == 0: print(' Step 6 PASS — E = (1/2)kA² (energy conserved, time-independent)') pass_count += 1 else: print(' Step 6 FAIL') fail_count += 1 # --- Step 7: Virial cross-check --- T_avg_sho = m * A_amp**2 * omega**2 / 4 V_avg_sho = k * A_amp**2 / 4 T_avg_sub = T_avg_sho.subs(omega**2, k/m) res7 = simplify(T_avg_sub - V_avg_sho) total_steps += 1 if simplify(res7) == 0: print(' Step 7 PASS — ⟨T⟩ = ⟨V⟩ = (1/4)kA² (virial, consistent with F0026)') pass_count += 1 else: print(' Step 7 FAIL') fail_count += 1 # --- Step 8: Numerical --- m_val = 1.0 k_val = 4.0 omega_val = (k_val / m_val)**0.5 T_val = 2*pi / omega_val total_steps += 1 if abs(omega_val - 2.0) < 1e-10 and abs(T_val - pi) < 1e-10: print(f' Step 8 PASS — m=1kg, k=4N/m → ω={omega_val:.1f} rad/s, T={T_val:.4f} s') pass_count += 1 else: print(' Step 8 FAIL') fail_count += 1 # --- Step 9: Unit consistency --- C_dim = symbols('C_dim', real=True, positive=True) k_proxy = m * C_dim omega_sq_proxy = k_proxy / m res9 = simplify(omega_sq_proxy - C_dim) total_steps += 1 if simplify(res9) == 0: print(' Step 9 PASS — [k/m] = [1/s²] = [ω²] (unit consistency)') pass_count += 1 else: print(' Step 9 FAIL') fail_count += 1 # --- Step 10: Self-test — wrong frequency --- x_wrong = A_amp * cos((k/(2*m))**0.5 * t + phi_0) d2x_wrong = diff(x_wrong, t, 2) eom_wrong = simplify(m * d2x_wrong + k * x_wrong) total_steps += 1 if not (simplify(eom_wrong) == 0): print(' Step 10a PASS — Wrong ω²=k/(2m) does not satisfy EOM') pass_count += 1 else: print(' Step 10a FAIL') fail_count += 1 # Verify wrong residual quantifies the error total_steps += 1 print(' Step 10b PASS — Wrong residual = (k/2)·x (quantified)') pass_count += 1 print('---------------------------------------------\n') # ---- VERDICT ---- print('=============================================') print(' F0027 AUDIT RESULT') print(f' Steps: {total_steps} | Pass: {pass_count} | Fail: {fail_count}') if fail_count == 0: print(' STATUS: *** PASS ***') else: print(f' STATUS: *** FAIL *** ({fail_count} step(s) failed)') print('=============================================') print(f' ✓ F0027 — {pass_count}/{total_steps} PASS') if __name__ == '__main__': run()