""" Hydrogen Balmer H-alpha dictionary hook. Assertion-based CAS audit block. Pillar: Spectroscopy Anchors | Chain: Rydberg -> Balmer -> H-alpha CalRef: Spectroscopy Anchors section Structure mirrors cas_F07.txt (= F0008) sections A-E. Verifies: 1. Rydberg wavelength formula derivation (symbolic) 2. Balmer H-alpha specialization (n=3->2) 3. H-beta (4->2) and H-gamma (5->2) 4. Wavelength ratio checks (R_inf cancels) 5. Numerical comparison with NIST ASD values 6. Rydberg constant from CODATA fundamentals """ def run(): from sympy import symbols, sqrt, simplify, Rational, pi print('=== CAS AUDIT: F0008 -- Hydrogen Balmer H-alpha dictionary hook ===\n') pass_count = 0 fail_count = 0 total_steps = 0 # ---- A. INPUTS ---- R_inf = symbols('R_inf', positive=True) h_planck = symbols('h_planck', positive=True) c_light = symbols('c_light', positive=True) n_i = symbols('n_i', positive=True, integer=True) n_f = symbols('n_f', positive=True, integer=True) lambda_sym = symbols('lambda_sym', positive=True) print('Section A: Inputs defined.') print(' R_inf, h, c, quantum numbers n_i, n_f\n') # ---- B. ASSUMPTIONS / DOMAINS ---- print('Section B: Nonrelativistic H, vacuum, infinite proton mass.') print(' CODATA 2022 values. Jc tolerance <= 1e-6 (ppm).\n') # ---- C. ALLOWED LEMMAS ---- print('Section C: Lemmas declared.') print(' C.1: E_gamma = hc/lambda = E_nf - E_ni') print(' C.2: Balmer specialization nf=2') print(' C.3: Wavelength ratios: R_inf cancels\n') # ---- D. STEP LOG ---- print('Section D: Step log') print('---------------------------------------------') # --- Step 1: Derive Rydberg wavelength formula symbolically --- E_nf = -h_planck * c_light * R_inf / n_f ** 2 E_ni = -h_planck * c_light * R_inf / n_i ** 2 delta_E = E_nf - E_ni delta_E = simplify(delta_E) expected_delta_E = -h_planck * c_light * R_inf * (1 / n_f ** 2 - 1 / n_i ** 2) step1_residual = simplify(delta_E - expected_delta_E) total_steps += 1 if simplify(step1_residual) == 0: print(' Step 1 PASS — Delta E = -hcR_inf*(1/nf^2 - 1/ni^2)') pass_count += 1 else: print(f' Step 1 FAIL — Delta E residual: {step1_residual}') fail_count += 1 # --- Step 2: Cancel h*c to get 1/lambda --- inv_lambda = R_inf * (1 / n_f ** 2 - 1 / n_i ** 2) ratio_check = simplify(-delta_E / (h_planck * c_light)) step2_residual = simplify(ratio_check - inv_lambda) total_steps += 1 if simplify(step2_residual) == 0: print(' Step 2 PASS — h*c cancels: 1/lambda = R_inf*(1/nf^2 - 1/ni^2)') pass_count += 1 else: print(f' Step 2 FAIL — Cancellation residual: {step2_residual}') fail_count += 1 # --- Step 3: h and c independence --- inv_lambda_vars = inv_lambda.free_symbols has_h = h_planck in inv_lambda_vars has_c = c_light in inv_lambda_vars total_steps += 1 if not has_h and not has_c: print(' Step 3 PASS — 1/lambda independent of h and c') pass_count += 1 else: print(f' Step 3 FAIL — 1/lambda still contains h={has_h}, c={has_c}') fail_count += 1 # --- Step 4: Balmer H-alpha specialization (3->2) --- inv_lambda_Ha = inv_lambda.subs([(n_f, 2), (n_i, 3)]) inv_lambda_Ha = simplify(inv_lambda_Ha) inv_lambda_Ha_expected = R_inf * Rational(5, 36) step4_residual = simplify(inv_lambda_Ha - inv_lambda_Ha_expected) total_steps += 1 if simplify(step4_residual) == 0: print(' Step 4 PASS — H-alpha: 1/lambda = (5/36)*R_inf') pass_count += 1 else: print(f' Step 4 FAIL — H-alpha residual: {step4_residual}') fail_count += 1 # --- Step 5: H-beta specialization (4->2) --- inv_lambda_Hb = inv_lambda.subs([(n_f, 2), (n_i, 4)]) inv_lambda_Hb = simplify(inv_lambda_Hb) inv_lambda_Hb_expected = R_inf * Rational(3, 16) step5_residual = simplify(inv_lambda_Hb - inv_lambda_Hb_expected) total_steps += 1 if simplify(step5_residual) == 0: print(' Step 5 PASS — H-beta: 1/lambda = (3/16)*R_inf') pass_count += 1 else: print(f' Step 5 FAIL — H-beta residual: {step5_residual}') fail_count += 1 # --- Step 6: H-gamma specialization (5->2) --- inv_lambda_Hg = inv_lambda.subs([(n_f, 2), (n_i, 5)]) inv_lambda_Hg = simplify(inv_lambda_Hg) inv_lambda_Hg_expected = R_inf * Rational(21, 100) step6_residual = simplify(inv_lambda_Hg - inv_lambda_Hg_expected) total_steps += 1 if simplify(step6_residual) == 0: print(' Step 6 PASS — H-gamma: 1/lambda = (21/100)*R_inf') pass_count += 1 else: print(f' Step 6 FAIL — H-gamma residual: {step6_residual}') fail_count += 1 # --- Step 7: Wavelength ratio H-alpha/H-beta (R_inf cancels) --- ratio_Ha_Hb = simplify(inv_lambda_Hb_expected / inv_lambda_Ha_expected) expected_ratio = Rational(27, 20) step7_residual = simplify(ratio_Ha_Hb - expected_ratio) total_steps += 1 if simplify(step7_residual) == 0: print(' Step 7 PASS — lambda_Ha/lambda_Hb = 27/20 = 1.35 (R_inf cancels)') pass_count += 1 else: print(f' Step 7 FAIL — Ratio residual: {step7_residual}') fail_count += 1 # --- Step 8: R_inf independence of wavelength ratios --- ratio_symbolic = simplify(inv_lambda_Hb / inv_lambda_Ha) has_R = R_inf in ratio_symbolic.free_symbols total_steps += 1 if not has_R: print(' Step 8 PASS — Wavelength ratio independent of R_inf') pass_count += 1 else: print(f' Step 8 FAIL — Ratio still contains R_inf: {ratio_symbolic}') fail_count += 1 # --- Step 9: Emission positivity check --- emission_factor_Ha = Rational(1, 4) - Rational(1, 9) emission_factor_Hb = Rational(1, 4) - Rational(1, 16) emission_factor_Hg = Rational(1, 4) - Rational(1, 25) total_steps += 1 if emission_factor_Ha > 0 and emission_factor_Hb > 0 and emission_factor_Hg > 0: print(' Step 9 PASS — Emission positivity: 1/nf^2 - 1/ni^2 > 0 for Ha,Hb,Hg') pass_count += 1 else: print(' Step 9 FAIL — Emission factor not positive') fail_count += 1 # --- Step 10: Numerical R_inf from CODATA fundamentals --- m_e_val = 9.1093837139e-31 e_val = 1.602176634e-19 eps0_val = 8.8541878128e-12 h_val = 6.62607015e-34 c_val = 299792458 R_inf_computed = m_e_val * e_val ** 4 / (8 * eps0_val ** 2 * h_val ** 3 * c_val) R_inf_CODATA = 10973731.568157 R_inf_rel_error = abs(R_inf_computed - R_inf_CODATA) / R_inf_CODATA total_steps += 1 if R_inf_rel_error < 1e-6: print(f' Step 10 PASS — R_inf = {R_inf_computed:.6f} 1/m (rel error: {R_inf_rel_error:.2e})') pass_count += 1 else: print(f' Step 10 FAIL — R_inf = {R_inf_computed:.6f}, expected {R_inf_CODATA:.6f} (rel error: {R_inf_rel_error:.2e})') fail_count += 1 # --- Step 11: Numerical H-alpha wavelength --- lambda_Ha_computed = 36 / (5 * R_inf_CODATA) lambda_Ha_nm = lambda_Ha_computed * 1e9 lambda_Ha_NIST = 656.281 lambda_Ha_rel_error = abs(lambda_Ha_nm - lambda_Ha_NIST) / lambda_Ha_NIST total_steps += 1 if lambda_Ha_rel_error < 1e-3: print(f' Step 11 PASS — lambda_Ha = {lambda_Ha_nm:.3f} nm (NIST: {lambda_Ha_NIST:.3f} nm, rel err: {lambda_Ha_rel_error:.2e})') pass_count += 1 else: print(f' Step 11 FAIL — lambda_Ha = {lambda_Ha_nm:.3f} nm (rel error: {lambda_Ha_rel_error:.2e})') fail_count += 1 # --- Step 12: Numerical ratio check vs NIST --- lambda_Hb_NIST = 486.133 lambda_Hg_NIST = 434.047 ratio_exp = lambda_Ha_NIST / lambda_Hb_NIST ratio_theory = 27 / 20 ratio_ppm = abs(ratio_exp - ratio_theory) / ratio_theory * 1e6 total_steps += 1 if ratio_ppm < 10: print(f' Step 12 PASS — Ha/Hb ratio: theory={ratio_theory:.6f}, NIST={ratio_exp:.6f} ({ratio_ppm:.1f} ppm)') pass_count += 1 else: print(f' Step 12 FAIL — Ha/Hb ratio discrepancy: {ratio_ppm:.1f} ppm') fail_count += 1 # --- Step 13: H-beta and H-gamma numerical wavelengths --- lambda_Hb_computed = 16 / (3 * R_inf_CODATA) * 1e9 lambda_Hg_computed = 100 / (21 * R_inf_CODATA) * 1e9 lambda_Hb_rel = abs(lambda_Hb_computed - lambda_Hb_NIST) / lambda_Hb_NIST lambda_Hg_rel = abs(lambda_Hg_computed - lambda_Hg_NIST) / lambda_Hg_NIST total_steps += 1 if lambda_Hb_rel < 1e-3 and lambda_Hg_rel < 1e-3: print(f' Step 13 PASS — Hb={lambda_Hb_computed:.3f} nm (NIST:{lambda_Hb_NIST:.3f}, err:{lambda_Hb_rel:.2e}), Hg={lambda_Hg_computed:.3f} nm (NIST:{lambda_Hg_NIST:.3f}, err:{lambda_Hg_rel:.2e})') pass_count += 1 else: print(f' Step 13 FAIL — Hb rel err: {lambda_Hb_rel:.2e}, Hg rel err: {lambda_Hg_rel:.2e}') fail_count += 1 print('---------------------------------------------\n') # ---- E. CHECK OUTPUTS ---- print('Section E: Output checks') print('---------------------------------------------') print(' Unit check:') print(' R_inf: [1/m]') print(' 1/lambda = R_inf*(..): [1/m] => lambda: [m]') print(' Ratios: [1/m]/[1/m] = [1] (dimensionless)') print(' PASS\n') # --- Self-test: wrong quantum numbers --- inv_lambda_wrong = inv_lambda.subs([(n_f, 3), (n_i, 2)]) inv_lambda_wrong = simplify(inv_lambda_wrong) inv_lambda_wrong_val = float(inv_lambda_wrong.subs(R_inf, R_inf_CODATA)) total_steps += 1 if inv_lambda_wrong_val < 0: print(' Self-test: swapped n_i/n_f gives 1/lambda < 0 (unphysical) PASS') pass_count += 1 else: print(' Self-test: FAIL (swapped quantum numbers not detected)') fail_count += 1 print('---------------------------------------------\n') # ---- VERDICT ---- print('=============================================') print(' F0008 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('Audit complete for F0008.') print(f' ✓ F0008 — {pass_count}/{total_steps} PASS') if __name__ == '__main__': run()