#!/usr/bin/env python3 """ COMPOSITIONAL TRACE — Particles → Atoms → Crystal Structures ============================================================== Date: 2026-03-17 PURPOSE: Trace backwards from each element's crystal structure to its atomic composition (protons, neutrons, electrons) and look for geometric patterns that predict WHY elements choose their structures. If geometry is the organizing principle: 1. Each particle has a Compton frequency (scale of its geometry) 2. Atoms combine particles at different scales 3. The COMBINATION should determine the crystal structure 4. This should be traceable through {2,3} building blocks We examine: A. Does electron count (Z) predict structure? B. Does neutron count predict structure? C. Do valence electrons predict structure? D. Are there {2,3} patterns in the particle counts? E. What changes at structure BOUNDARIES (where one structure switches to another)? """ import sys from collections import Counter, defaultdict from pathlib import Path sys.path.insert(0, str(Path(__file__).parent.parent)) from full_element_database import build_elements_dict # ====================================================================== # ATOMIC COMPOSITION DATA # ====================================================================== # Most stable isotope neutron counts + electron configuration # Source: IUPAC, NIST Atomic Spectra Database ATOM_DATA = { # Period 1 "H": {"Z": 1, "N_neutrons": 0, "valence": 1, "group": 1, "block": "s", "config": "1s1"}, "He": {"Z": 2, "N_neutrons": 2, "valence": 2, "group": 18, "block": "s", "config": "1s2"}, # Period 2 "Li": {"Z": 3, "N_neutrons": 4, "valence": 1, "group": 1, "block": "s", "config": "[He]2s1"}, "Be": {"Z": 4, "N_neutrons": 5, "valence": 2, "group": 2, "block": "s", "config": "[He]2s2"}, "B": {"Z": 5, "N_neutrons": 6, "valence": 3, "group": 13, "block": "p", "config": "[He]2s2 2p1"}, "C": {"Z": 6, "N_neutrons": 6, "valence": 4, "group": 14, "block": "p", "config": "[He]2s2 2p2"}, "N": {"Z": 7, "N_neutrons": 7, "valence": 5, "group": 15, "block": "p", "config": "[He]2s2 2p3"}, "O": {"Z": 8, "N_neutrons": 8, "valence": 6, "group": 16, "block": "p", "config": "[He]2s2 2p4"}, "F": {"Z": 9, "N_neutrons": 10, "valence": 7, "group": 17, "block": "p", "config": "[He]2s2 2p5"}, "Ne": {"Z": 10, "N_neutrons": 10, "valence": 8, "group": 18, "block": "p", "config": "[He]2s2 2p6"}, # Period 3 "Na": {"Z": 11, "N_neutrons": 12, "valence": 1, "group": 1, "block": "s", "config": "[Ne]3s1"}, "Mg": {"Z": 12, "N_neutrons": 12, "valence": 2, "group": 2, "block": "s", "config": "[Ne]3s2"}, "Al": {"Z": 13, "N_neutrons": 14, "valence": 3, "group": 13, "block": "p", "config": "[Ne]3s2 3p1"}, "Si": {"Z": 14, "N_neutrons": 14, "valence": 4, "group": 14, "block": "p", "config": "[Ne]3s2 3p2"}, "P": {"Z": 15, "N_neutrons": 16, "valence": 5, "group": 15, "block": "p", "config": "[Ne]3s2 3p3"}, "S": {"Z": 16, "N_neutrons": 16, "valence": 6, "group": 16, "block": "p", "config": "[Ne]3s2 3p4"}, "Cl": {"Z": 17, "N_neutrons": 18, "valence": 7, "group": 17, "block": "p", "config": "[Ne]3s2 3p5"}, "Ar": {"Z": 18, "N_neutrons": 22, "valence": 8, "group": 18, "block": "p", "config": "[Ne]3s2 3p6"}, # Period 4 "K": {"Z": 19, "N_neutrons": 20, "valence": 1, "group": 1, "block": "s", "config": "[Ar]4s1"}, "Ca": {"Z": 20, "N_neutrons": 20, "valence": 2, "group": 2, "block": "s", "config": "[Ar]4s2"}, "Sc": {"Z": 21, "N_neutrons": 24, "valence": 3, "group": 3, "block": "d", "config": "[Ar]3d1 4s2"}, "Ti": {"Z": 22, "N_neutrons": 26, "valence": 4, "group": 4, "block": "d", "config": "[Ar]3d2 4s2"}, "V": {"Z": 23, "N_neutrons": 28, "valence": 5, "group": 5, "block": "d", "config": "[Ar]3d3 4s2"}, "Cr": {"Z": 24, "N_neutrons": 28, "valence": 6, "group": 6, "block": "d", "config": "[Ar]3d5 4s1"}, "Mn": {"Z": 25, "N_neutrons": 30, "valence": 7, "group": 7, "block": "d", "config": "[Ar]3d5 4s2"}, "Fe": {"Z": 26, "N_neutrons": 30, "valence": 8, "group": 8, "block": "d", "config": "[Ar]3d6 4s2"}, "Co": {"Z": 27, "N_neutrons": 32, "valence": 9, "group": 9, "block": "d", "config": "[Ar]3d7 4s2"}, "Ni": {"Z": 28, "N_neutrons": 30, "valence": 10,"group": 10, "block": "d", "config": "[Ar]3d8 4s2"}, "Cu": {"Z": 29, "N_neutrons": 34, "valence": 11,"group": 11, "block": "d", "config": "[Ar]3d10 4s1"}, "Zn": {"Z": 30, "N_neutrons": 34, "valence": 12,"group": 12, "block": "d", "config": "[Ar]3d10 4s2"}, "Ga": {"Z": 31, "N_neutrons": 38, "valence": 3, "group": 13, "block": "p", "config": "[Ar]3d10 4s2 4p1"}, "Ge": {"Z": 32, "N_neutrons": 41, "valence": 4, "group": 14, "block": "p", "config": "[Ar]3d10 4s2 4p2"}, "As": {"Z": 33, "N_neutrons": 42, "valence": 5, "group": 15, "block": "p", "config": "[Ar]3d10 4s2 4p3"}, "Se": {"Z": 34, "N_neutrons": 45, "valence": 6, "group": 16, "block": "p", "config": "[Ar]3d10 4s2 4p4"}, "Br": {"Z": 35, "N_neutrons": 44, "valence": 7, "group": 17, "block": "p", "config": "[Ar]3d10 4s2 4p5"}, "Kr": {"Z": 36, "N_neutrons": 48, "valence": 8, "group": 18, "block": "p", "config": "[Ar]3d10 4s2 4p6"}, } # ====================================================================== # ANALYSIS # ====================================================================== def factorize_23(n): """Express n in terms of factors of 2 and 3. Returns (power_of_2, power_of_3, remainder).""" p2, p3 = 0, 0 rem = n while rem > 0 and rem % 2 == 0: p2 += 1 rem //= 2 while rem > 0 and rem % 3 == 0: p3 += 1 rem //= 3 return p2, p3, rem def main(): elements = build_elements_dict() print("=" * 80) print("COMPOSITIONAL TRACE: Particles → Atoms → Crystal Structures") print("=" * 80) # ── A: Does electron count (Z) predict structure? ── print("\n\nA. ELECTRON COUNT (Z) vs CRYSTAL STRUCTURE") print("-" * 80) struct_by_z = defaultdict(list) for sym, atom in sorted(ATOM_DATA.items(), key=lambda x: x[1]["Z"]): if sym in elements: struct = elements[sym]["crystal_structure"] struct_by_z[struct].append((sym, atom["Z"])) for struct in ["FCC", "BCC", "HCP", "Diamond", "Orthorhombic", "Rhombohedral", "Monoclinic", "Hexagonal"]: if struct in struct_by_z: items = struct_by_z[struct] zvals = [z for _, z in items] syms = [s for s, _ in items] print(f"\n {struct:15s} ({len(items)} elements):") print(f" Z values: {zvals}") print(f" Elements: {', '.join(syms)}") # ── B: VALENCE ELECTRONS vs CRYSTAL STRUCTURE ── print("\n\nB. VALENCE ELECTRONS vs CRYSTAL STRUCTURE") print("-" * 80) struct_by_valence = defaultdict(lambda: defaultdict(list)) for sym, atom in sorted(ATOM_DATA.items(), key=lambda x: x[1]["Z"]): if sym in elements: struct = elements[sym]["crystal_structure"] struct_by_valence[struct][atom["valence"]].append(sym) for struct in ["FCC", "BCC", "HCP", "Diamond"]: if struct in struct_by_valence: print(f"\n {struct}:") for v in sorted(struct_by_valence[struct].keys()): syms = struct_by_valence[struct][v] print(f" {v} valence e⁻: {', '.join(syms)}") # ── C: ELECTRON BLOCK (s/p/d/f) vs CRYSTAL STRUCTURE ── print("\n\nC. ELECTRON BLOCK (s/p/d/f) vs CRYSTAL STRUCTURE") print("-" * 80) struct_by_block = defaultdict(lambda: Counter()) for sym, atom in ATOM_DATA.items(): if sym in elements: struct = elements[sym]["crystal_structure"] struct_by_block[struct][atom["block"]] += 1 for struct in ["FCC", "BCC", "HCP", "Diamond", "Orthorhombic"]: if struct in struct_by_block: print(f" {struct:15s}: {dict(struct_by_block[struct])}") # ── D: {2,3} FACTORIZATION OF PARTICLE COUNTS ── print("\n\nD. {2,3} FACTORIZATION OF PARTICLE COUNTS") print("-" * 80) print(f" {'Sym':4s} {'Z':>3s} {'N_n':>3s} {'A':>3s} {'Struct':12s} " f"{'Z=2^a×3^b':15s} {'N=2^a×3^b':15s} {'A=2^a×3^b':15s} {'Val':>3s}") print(f" {'-'*4} {'-'*3} {'-'*3} {'-'*3} {'-'*12} {'-'*15} {'-'*15} {'-'*15} {'-'*3}") for sym, atom in sorted(ATOM_DATA.items(), key=lambda x: x[1]["Z"]): if sym not in elements: continue Z = atom["Z"] Nn = atom["N_neutrons"] A = Z + Nn struct = elements[sym]["crystal_structure"] val = atom["valence"] z2, z3, zr = factorize_23(Z) n2, n3, nr = factorize_23(Nn) a2, a3, ar = factorize_23(A) z_str = f"2^{z2}×3^{z3}" + (f"×{zr}" if zr > 1 else "") n_str = f"2^{n2}×3^{n3}" + (f"×{nr}" if nr > 1 else "") if Nn > 0 else "0" a_str = f"2^{a2}×3^{a3}" + (f"×{ar}" if ar > 1 else "") # Mark pure {2,3} numbers z_pure = "✓" if zr <= 1 else "" n_pure = "✓" if nr <= 1 or Nn == 0 else "" a_pure = "✓" if ar <= 1 else "" print(f" {sym:4s} {Z:3d} {Nn:3d} {A:3d} {struct:12s} " f"{z_str:>12s}{z_pure:2s} {n_str:>12s}{n_pure:2s} " f"{a_str:>12s}{a_pure:2s} {val:3d}") # ── E: STRUCTURE BOUNDARIES ── print("\n\nE. STRUCTURE BOUNDARIES (where structure changes)") print("-" * 80) print(" Walking across the periodic table by Z, noting where crystal") print(" structure SWITCHES. What changes at the boundary?") print() prev_struct = None prev_sym = None for sym, atom in sorted(ATOM_DATA.items(), key=lambda x: x[1]["Z"]): if sym not in elements: continue struct = elements[sym]["crystal_structure"] if prev_struct is not None and struct != prev_struct: prev_atom = ATOM_DATA[prev_sym] print(f" BOUNDARY: {prev_sym}({prev_atom['Z']}) {prev_struct} " f"→ {sym}({atom['Z']}) {struct}") print(f" {prev_sym}: val={prev_atom['valence']}, " f"block={prev_atom['block']}, config={prev_atom['config']}") print(f" {sym}: val={atom['valence']}, " f"block={atom['block']}, config={atom['config']}") # What changed? changes = [] if prev_atom["valence"] != atom["valence"]: changes.append(f"valence {prev_atom['valence']}→{atom['valence']}") if prev_atom["block"] != atom["block"]: changes.append(f"block {prev_atom['block']}→{atom['block']}") if prev_atom["group"] != atom["group"]: changes.append(f"group {prev_atom['group']}→{atom['group']}") print(f" Changed: {', '.join(changes) if changes else 'SAME block/group'}") print() prev_struct = struct prev_sym = sym # ── F: GROUP (COLUMN) vs CRYSTAL STRUCTURE ── print("\n\nF. PERIODIC TABLE GROUP vs CRYSTAL STRUCTURE") print("-" * 80) group_struct = defaultdict(list) for sym, atom in sorted(ATOM_DATA.items(), key=lambda x: x[1]["Z"]): if sym in elements: struct = elements[sym]["crystal_structure"] group_struct[atom["group"]].append((sym, struct)) for group in sorted(group_struct.keys()): items = group_struct[group] structs = [s for _, s in items] syms = [f"{sym}({s})" for sym, s in items] unique = set(structs) consistency = "UNIFORM" if len(unique) == 1 else f"MIXED ({len(unique)} types)" print(f" Group {group:2d}: {consistency:20s} {', '.join(syms)}") # ── G: SUMMARY ── print("\n\n" + "=" * 80) print("SUMMARY: WHAT PREDICTS CRYSTAL STRUCTURE?") print("=" * 80) # Count how well each predictor works # Valence electrons val_struct = defaultdict(Counter) for sym, atom in ATOM_DATA.items(): if sym in elements: struct = elements[sym]["crystal_structure"] if struct in ("FCC", "BCC", "HCP", "Diamond"): val_struct[atom["valence"]][struct] += 1 print("\n VALENCE ELECTRONS → STRUCTURE (for cipher-covered elements):") print(f" {'Val':>3s} {'Dominant':12s} {'Distribution'}") print(f" {'-'*3} {'-'*12} {'-'*40}") for v in sorted(val_struct.keys()): total = sum(val_struct[v].values()) dominant = val_struct[v].most_common(1)[0] pct = dominant[1] / total * 100 dist = ", ".join(f"{s}={c}" for s, c in val_struct[v].most_common()) print(f" {v:3d} {dominant[0]:12s} {dist} ({pct:.0f}% dominant)") if __name__ == "__main__": main()