Skip to main content

molrs/
element.rs

1//! Element data and basic lookup utilities.
2use core::str::FromStr;
3
4/// Chemical element with complete periodic table (elements 1-118)
5#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
6#[repr(u8)]
7pub enum Element {
8    H = 1,
9    He = 2,
10    Li = 3,
11    Be = 4,
12    B = 5,
13    C = 6,
14    N = 7,
15    O = 8,
16    F = 9,
17    Ne = 10,
18    Na = 11,
19    Mg = 12,
20    Al = 13,
21    Si = 14,
22    P = 15,
23    S = 16,
24    Cl = 17,
25    Ar = 18,
26    K = 19,
27    Ca = 20,
28    Sc = 21,
29    Ti = 22,
30    V = 23,
31    Cr = 24,
32    Mn = 25,
33    Fe = 26,
34    Co = 27,
35    Ni = 28,
36    Cu = 29,
37    Zn = 30,
38    Ga = 31,
39    Ge = 32,
40    As = 33,
41    Se = 34,
42    Br = 35,
43    Kr = 36,
44    Rb = 37,
45    Sr = 38,
46    Y = 39,
47    Zr = 40,
48    Nb = 41,
49    Mo = 42,
50    Tc = 43,
51    Ru = 44,
52    Rh = 45,
53    Pd = 46,
54    Ag = 47,
55    Cd = 48,
56    In = 49,
57    Sn = 50,
58    Sb = 51,
59    Te = 52,
60    I = 53,
61    Xe = 54,
62    Cs = 55,
63    Ba = 56,
64    La = 57,
65    Ce = 58,
66    Pr = 59,
67    Nd = 60,
68    Pm = 61,
69    Sm = 62,
70    Eu = 63,
71    Gd = 64,
72    Tb = 65,
73    Dy = 66,
74    Ho = 67,
75    Er = 68,
76    Tm = 69,
77    Yb = 70,
78    Lu = 71,
79    Hf = 72,
80    Ta = 73,
81    W = 74,
82    Re = 75,
83    Os = 76,
84    Ir = 77,
85    Pt = 78,
86    Au = 79,
87    Hg = 80,
88    Tl = 81,
89    Pb = 82,
90    Bi = 83,
91    Po = 84,
92    At = 85,
93    Rn = 86,
94    Fr = 87,
95    Ra = 88,
96    Ac = 89,
97    Th = 90,
98    Pa = 91,
99    U = 92,
100    Np = 93,
101    Pu = 94,
102    Am = 95,
103    Cm = 96,
104    Bk = 97,
105    Cf = 98,
106    Es = 99,
107    Fm = 100,
108    Md = 101,
109    No = 102,
110    Lr = 103,
111    Rf = 104,
112    Db = 105,
113    Sg = 106,
114    Bh = 107,
115    Hs = 108,
116    Mt = 109,
117    Ds = 110,
118    Rg = 111,
119    Cn = 112,
120    Nh = 113,
121    Fl = 114,
122    Mc = 115,
123    Lv = 116,
124    Ts = 117,
125    Og = 118,
126}
127
128/// Element properties data structure
129struct ElementData {
130    symbol: &'static str,
131    name: &'static str,
132    mass: f32,
133    covalent_radius: f32, // in Angstroms
134    vdw_radius: f32,      // in Angstroms
135}
136
137// Element data table (indexed by atomic number - 1)
138const ELEMENT_DATA: [ElementData; 118] = [
139    ElementData {
140        symbol: "H",
141        name: "Hydrogen",
142        mass: 1.008,
143        covalent_radius: 0.31,
144        vdw_radius: 1.20,
145    },
146    ElementData {
147        symbol: "He",
148        name: "Helium",
149        mass: 4.003,
150        covalent_radius: 0.28,
151        vdw_radius: 1.40,
152    },
153    ElementData {
154        symbol: "Li",
155        name: "Lithium",
156        mass: 6.941,
157        covalent_radius: 1.28,
158        vdw_radius: 1.82,
159    },
160    ElementData {
161        symbol: "Be",
162        name: "Beryllium",
163        mass: 9.012,
164        covalent_radius: 0.96,
165        vdw_radius: 1.53,
166    },
167    ElementData {
168        symbol: "B",
169        name: "Boron",
170        mass: 10.81,
171        covalent_radius: 0.84,
172        vdw_radius: 1.92,
173    },
174    ElementData {
175        symbol: "C",
176        name: "Carbon",
177        mass: 12.01,
178        covalent_radius: 0.76,
179        vdw_radius: 1.70,
180    },
181    ElementData {
182        symbol: "N",
183        name: "Nitrogen",
184        mass: 14.01,
185        covalent_radius: 0.71,
186        vdw_radius: 1.55,
187    },
188    ElementData {
189        symbol: "O",
190        name: "Oxygen",
191        mass: 16.00,
192        covalent_radius: 0.66,
193        vdw_radius: 1.52,
194    },
195    ElementData {
196        symbol: "F",
197        name: "Fluorine",
198        mass: 19.00,
199        covalent_radius: 0.57,
200        vdw_radius: 1.47,
201    },
202    ElementData {
203        symbol: "Ne",
204        name: "Neon",
205        mass: 20.18,
206        covalent_radius: 0.58,
207        vdw_radius: 1.54,
208    },
209    ElementData {
210        symbol: "Na",
211        name: "Sodium",
212        mass: 22.99,
213        covalent_radius: 1.66,
214        vdw_radius: 2.27,
215    },
216    ElementData {
217        symbol: "Mg",
218        name: "Magnesium",
219        mass: 24.31,
220        covalent_radius: 1.41,
221        vdw_radius: 1.73,
222    },
223    ElementData {
224        symbol: "Al",
225        name: "Aluminum",
226        mass: 26.98,
227        covalent_radius: 1.21,
228        vdw_radius: 1.84,
229    },
230    ElementData {
231        symbol: "Si",
232        name: "Silicon",
233        mass: 28.09,
234        covalent_radius: 1.11,
235        vdw_radius: 2.10,
236    },
237    ElementData {
238        symbol: "P",
239        name: "Phosphorus",
240        mass: 30.97,
241        covalent_radius: 1.07,
242        vdw_radius: 1.80,
243    },
244    ElementData {
245        symbol: "S",
246        name: "Sulfur",
247        mass: 32.07,
248        covalent_radius: 1.05,
249        vdw_radius: 1.80,
250    },
251    ElementData {
252        symbol: "Cl",
253        name: "Chlorine",
254        mass: 35.45,
255        covalent_radius: 1.02,
256        vdw_radius: 1.75,
257    },
258    ElementData {
259        symbol: "Ar",
260        name: "Argon",
261        mass: 39.95,
262        covalent_radius: 1.06,
263        vdw_radius: 1.88,
264    },
265    ElementData {
266        symbol: "K",
267        name: "Potassium",
268        mass: 39.10,
269        covalent_radius: 2.03,
270        vdw_radius: 2.75,
271    },
272    ElementData {
273        symbol: "Ca",
274        name: "Calcium",
275        mass: 40.08,
276        covalent_radius: 1.76,
277        vdw_radius: 2.31,
278    },
279    ElementData {
280        symbol: "Sc",
281        name: "Scandium",
282        mass: 44.96,
283        covalent_radius: 1.70,
284        vdw_radius: 2.11,
285    },
286    ElementData {
287        symbol: "Ti",
288        name: "Titanium",
289        mass: 47.87,
290        covalent_radius: 1.60,
291        vdw_radius: 2.00,
292    },
293    ElementData {
294        symbol: "V",
295        name: "Vanadium",
296        mass: 50.94,
297        covalent_radius: 1.53,
298        vdw_radius: 2.00,
299    },
300    ElementData {
301        symbol: "Cr",
302        name: "Chromium",
303        mass: 52.00,
304        covalent_radius: 1.39,
305        vdw_radius: 2.00,
306    },
307    ElementData {
308        symbol: "Mn",
309        name: "Manganese",
310        mass: 54.94,
311        covalent_radius: 1.39,
312        vdw_radius: 2.00,
313    },
314    ElementData {
315        symbol: "Fe",
316        name: "Iron",
317        mass: 55.85,
318        covalent_radius: 1.32,
319        vdw_radius: 2.00,
320    },
321    ElementData {
322        symbol: "Co",
323        name: "Cobalt",
324        mass: 58.93,
325        covalent_radius: 1.26,
326        vdw_radius: 2.00,
327    },
328    ElementData {
329        symbol: "Ni",
330        name: "Nickel",
331        mass: 58.69,
332        covalent_radius: 1.24,
333        vdw_radius: 1.63,
334    },
335    ElementData {
336        symbol: "Cu",
337        name: "Copper",
338        mass: 63.55,
339        covalent_radius: 1.32,
340        vdw_radius: 1.40,
341    },
342    ElementData {
343        symbol: "Zn",
344        name: "Zinc",
345        mass: 65.39,
346        covalent_radius: 1.22,
347        vdw_radius: 1.39,
348    },
349    ElementData {
350        symbol: "Ga",
351        name: "Gallium",
352        mass: 69.72,
353        covalent_radius: 1.22,
354        vdw_radius: 1.87,
355    },
356    ElementData {
357        symbol: "Ge",
358        name: "Germanium",
359        mass: 72.61,
360        covalent_radius: 1.20,
361        vdw_radius: 2.11,
362    },
363    ElementData {
364        symbol: "As",
365        name: "Arsenic",
366        mass: 74.92,
367        covalent_radius: 1.19,
368        vdw_radius: 1.85,
369    },
370    ElementData {
371        symbol: "Se",
372        name: "Selenium",
373        mass: 78.96,
374        covalent_radius: 1.20,
375        vdw_radius: 1.90,
376    },
377    ElementData {
378        symbol: "Br",
379        name: "Bromine",
380        mass: 79.90,
381        covalent_radius: 1.20,
382        vdw_radius: 1.85,
383    },
384    ElementData {
385        symbol: "Kr",
386        name: "Krypton",
387        mass: 83.80,
388        covalent_radius: 1.16,
389        vdw_radius: 2.02,
390    },
391    ElementData {
392        symbol: "Rb",
393        name: "Rubidium",
394        mass: 85.47,
395        covalent_radius: 2.20,
396        vdw_radius: 3.03,
397    },
398    ElementData {
399        symbol: "Sr",
400        name: "Strontium",
401        mass: 87.62,
402        covalent_radius: 1.95,
403        vdw_radius: 2.49,
404    },
405    ElementData {
406        symbol: "Y",
407        name: "Yttrium",
408        mass: 88.91,
409        covalent_radius: 1.90,
410        vdw_radius: 2.00,
411    },
412    ElementData {
413        symbol: "Zr",
414        name: "Zirconium",
415        mass: 91.22,
416        covalent_radius: 1.75,
417        vdw_radius: 2.00,
418    },
419    ElementData {
420        symbol: "Nb",
421        name: "Niobium",
422        mass: 92.91,
423        covalent_radius: 1.64,
424        vdw_radius: 2.00,
425    },
426    ElementData {
427        symbol: "Mo",
428        name: "Molybdenum",
429        mass: 95.94,
430        covalent_radius: 1.54,
431        vdw_radius: 2.00,
432    },
433    ElementData {
434        symbol: "Tc",
435        name: "Technetium",
436        mass: 98.00,
437        covalent_radius: 1.47,
438        vdw_radius: 2.00,
439    },
440    ElementData {
441        symbol: "Ru",
442        name: "Ruthenium",
443        mass: 101.1,
444        covalent_radius: 1.46,
445        vdw_radius: 2.00,
446    },
447    ElementData {
448        symbol: "Rh",
449        name: "Rhodium",
450        mass: 102.9,
451        covalent_radius: 1.42,
452        vdw_radius: 2.00,
453    },
454    ElementData {
455        symbol: "Pd",
456        name: "Palladium",
457        mass: 106.4,
458        covalent_radius: 1.39,
459        vdw_radius: 1.63,
460    },
461    ElementData {
462        symbol: "Ag",
463        name: "Silver",
464        mass: 107.9,
465        covalent_radius: 1.45,
466        vdw_radius: 1.72,
467    },
468    ElementData {
469        symbol: "Cd",
470        name: "Cadmium",
471        mass: 112.4,
472        covalent_radius: 1.44,
473        vdw_radius: 1.58,
474    },
475    ElementData {
476        symbol: "In",
477        name: "Indium",
478        mass: 114.8,
479        covalent_radius: 1.42,
480        vdw_radius: 1.93,
481    },
482    ElementData {
483        symbol: "Sn",
484        name: "Tin",
485        mass: 118.7,
486        covalent_radius: 1.39,
487        vdw_radius: 2.17,
488    },
489    ElementData {
490        symbol: "Sb",
491        name: "Antimony",
492        mass: 121.8,
493        covalent_radius: 1.39,
494        vdw_radius: 2.06,
495    },
496    ElementData {
497        symbol: "Te",
498        name: "Tellurium",
499        mass: 127.6,
500        covalent_radius: 1.38,
501        vdw_radius: 2.06,
502    },
503    ElementData {
504        symbol: "I",
505        name: "Iodine",
506        mass: 126.9,
507        covalent_radius: 1.39,
508        vdw_radius: 1.98,
509    },
510    ElementData {
511        symbol: "Xe",
512        name: "Xenon",
513        mass: 131.3,
514        covalent_radius: 1.40,
515        vdw_radius: 2.16,
516    },
517    ElementData {
518        symbol: "Cs",
519        name: "Cesium",
520        mass: 132.9,
521        covalent_radius: 2.44,
522        vdw_radius: 3.43,
523    },
524    ElementData {
525        symbol: "Ba",
526        name: "Barium",
527        mass: 137.3,
528        covalent_radius: 2.15,
529        vdw_radius: 2.68,
530    },
531    ElementData {
532        symbol: "La",
533        name: "Lanthanum",
534        mass: 138.9,
535        covalent_radius: 2.07,
536        vdw_radius: 2.00,
537    },
538    ElementData {
539        symbol: "Ce",
540        name: "Cerium",
541        mass: 140.1,
542        covalent_radius: 2.04,
543        vdw_radius: 2.00,
544    },
545    ElementData {
546        symbol: "Pr",
547        name: "Praseodymium",
548        mass: 140.9,
549        covalent_radius: 2.03,
550        vdw_radius: 2.00,
551    },
552    ElementData {
553        symbol: "Nd",
554        name: "Neodymium",
555        mass: 144.2,
556        covalent_radius: 2.01,
557        vdw_radius: 2.00,
558    },
559    ElementData {
560        symbol: "Pm",
561        name: "Promethium",
562        mass: 145.0,
563        covalent_radius: 1.99,
564        vdw_radius: 2.00,
565    },
566    ElementData {
567        symbol: "Sm",
568        name: "Samarium",
569        mass: 150.4,
570        covalent_radius: 1.98,
571        vdw_radius: 2.00,
572    },
573    ElementData {
574        symbol: "Eu",
575        name: "Europium",
576        mass: 152.0,
577        covalent_radius: 1.98,
578        vdw_radius: 2.00,
579    },
580    ElementData {
581        symbol: "Gd",
582        name: "Gadolinium",
583        mass: 157.3,
584        covalent_radius: 1.96,
585        vdw_radius: 2.00,
586    },
587    ElementData {
588        symbol: "Tb",
589        name: "Terbium",
590        mass: 158.9,
591        covalent_radius: 1.94,
592        vdw_radius: 2.00,
593    },
594    ElementData {
595        symbol: "Dy",
596        name: "Dysprosium",
597        mass: 162.5,
598        covalent_radius: 1.92,
599        vdw_radius: 2.00,
600    },
601    ElementData {
602        symbol: "Ho",
603        name: "Holmium",
604        mass: 164.9,
605        covalent_radius: 1.92,
606        vdw_radius: 2.00,
607    },
608    ElementData {
609        symbol: "Er",
610        name: "Erbium",
611        mass: 167.3,
612        covalent_radius: 1.89,
613        vdw_radius: 2.00,
614    },
615    ElementData {
616        symbol: "Tm",
617        name: "Thulium",
618        mass: 168.9,
619        covalent_radius: 1.90,
620        vdw_radius: 2.00,
621    },
622    ElementData {
623        symbol: "Yb",
624        name: "Ytterbium",
625        mass: 173.0,
626        covalent_radius: 1.87,
627        vdw_radius: 2.00,
628    },
629    ElementData {
630        symbol: "Lu",
631        name: "Lutetium",
632        mass: 175.0,
633        covalent_radius: 1.87,
634        vdw_radius: 2.00,
635    },
636    ElementData {
637        symbol: "Hf",
638        name: "Hafnium",
639        mass: 178.5,
640        covalent_radius: 1.75,
641        vdw_radius: 2.00,
642    },
643    ElementData {
644        symbol: "Ta",
645        name: "Tantalum",
646        mass: 180.9,
647        covalent_radius: 1.70,
648        vdw_radius: 2.00,
649    },
650    ElementData {
651        symbol: "W",
652        name: "Tungsten",
653        mass: 183.8,
654        covalent_radius: 1.62,
655        vdw_radius: 2.00,
656    },
657    ElementData {
658        symbol: "Re",
659        name: "Rhenium",
660        mass: 186.2,
661        covalent_radius: 1.51,
662        vdw_radius: 2.00,
663    },
664    ElementData {
665        symbol: "Os",
666        name: "Osmium",
667        mass: 190.2,
668        covalent_radius: 1.44,
669        vdw_radius: 2.00,
670    },
671    ElementData {
672        symbol: "Ir",
673        name: "Iridium",
674        mass: 192.2,
675        covalent_radius: 1.41,
676        vdw_radius: 2.00,
677    },
678    ElementData {
679        symbol: "Pt",
680        name: "Platinum",
681        mass: 195.1,
682        covalent_radius: 1.36,
683        vdw_radius: 1.75,
684    },
685    ElementData {
686        symbol: "Au",
687        name: "Gold",
688        mass: 197.0,
689        covalent_radius: 1.36,
690        vdw_radius: 1.66,
691    },
692    ElementData {
693        symbol: "Hg",
694        name: "Mercury",
695        mass: 200.6,
696        covalent_radius: 1.32,
697        vdw_radius: 1.55,
698    },
699    ElementData {
700        symbol: "Tl",
701        name: "Thallium",
702        mass: 204.4,
703        covalent_radius: 1.45,
704        vdw_radius: 1.96,
705    },
706    ElementData {
707        symbol: "Pb",
708        name: "Lead",
709        mass: 207.2,
710        covalent_radius: 1.46,
711        vdw_radius: 2.02,
712    },
713    ElementData {
714        symbol: "Bi",
715        name: "Bismuth",
716        mass: 209.0,
717        covalent_radius: 1.48,
718        vdw_radius: 2.07,
719    },
720    ElementData {
721        symbol: "Po",
722        name: "Polonium",
723        mass: 209.0,
724        covalent_radius: 1.40,
725        vdw_radius: 1.97,
726    },
727    ElementData {
728        symbol: "At",
729        name: "Astatine",
730        mass: 210.0,
731        covalent_radius: 1.50,
732        vdw_radius: 2.02,
733    },
734    ElementData {
735        symbol: "Rn",
736        name: "Radon",
737        mass: 222.0,
738        covalent_radius: 1.50,
739        vdw_radius: 2.20,
740    },
741    ElementData {
742        symbol: "Fr",
743        name: "Francium",
744        mass: 223.0,
745        covalent_radius: 2.60,
746        vdw_radius: 3.48,
747    },
748    ElementData {
749        symbol: "Ra",
750        name: "Radium",
751        mass: 226.0,
752        covalent_radius: 2.21,
753        vdw_radius: 2.83,
754    },
755    ElementData {
756        symbol: "Ac",
757        name: "Actinium",
758        mass: 227.0,
759        covalent_radius: 2.15,
760        vdw_radius: 2.00,
761    },
762    ElementData {
763        symbol: "Th",
764        name: "Thorium",
765        mass: 232.0,
766        covalent_radius: 2.06,
767        vdw_radius: 2.00,
768    },
769    ElementData {
770        symbol: "Pa",
771        name: "Protactinium",
772        mass: 231.0,
773        covalent_radius: 2.00,
774        vdw_radius: 2.00,
775    },
776    ElementData {
777        symbol: "U",
778        name: "Uranium",
779        mass: 238.0,
780        covalent_radius: 1.96,
781        vdw_radius: 1.86,
782    },
783    ElementData {
784        symbol: "Np",
785        name: "Neptunium",
786        mass: 237.0,
787        covalent_radius: 1.90,
788        vdw_radius: 2.00,
789    },
790    ElementData {
791        symbol: "Pu",
792        name: "Plutonium",
793        mass: 244.0,
794        covalent_radius: 1.87,
795        vdw_radius: 2.00,
796    },
797    ElementData {
798        symbol: "Am",
799        name: "Americium",
800        mass: 243.0,
801        covalent_radius: 1.80,
802        vdw_radius: 2.00,
803    },
804    ElementData {
805        symbol: "Cm",
806        name: "Curium",
807        mass: 247.0,
808        covalent_radius: 1.69,
809        vdw_radius: 2.00,
810    },
811    ElementData {
812        symbol: "Bk",
813        name: "Berkelium",
814        mass: 247.0,
815        covalent_radius: 1.60,
816        vdw_radius: 2.00,
817    },
818    ElementData {
819        symbol: "Cf",
820        name: "Californium",
821        mass: 251.0,
822        covalent_radius: 1.60,
823        vdw_radius: 2.00,
824    },
825    ElementData {
826        symbol: "Es",
827        name: "Einsteinium",
828        mass: 252.0,
829        covalent_radius: 1.60,
830        vdw_radius: 2.00,
831    },
832    ElementData {
833        symbol: "Fm",
834        name: "Fermium",
835        mass: 257.0,
836        covalent_radius: 1.60,
837        vdw_radius: 2.00,
838    },
839    ElementData {
840        symbol: "Md",
841        name: "Mendelevium",
842        mass: 258.0,
843        covalent_radius: 1.60,
844        vdw_radius: 2.00,
845    },
846    ElementData {
847        symbol: "No",
848        name: "Nobelium",
849        mass: 259.0,
850        covalent_radius: 1.60,
851        vdw_radius: 2.00,
852    },
853    ElementData {
854        symbol: "Lr",
855        name: "Lawrencium",
856        mass: 262.0,
857        covalent_radius: 1.60,
858        vdw_radius: 2.00,
859    },
860    ElementData {
861        symbol: "Rf",
862        name: "Rutherfordium",
863        mass: 267.0,
864        covalent_radius: 1.60,
865        vdw_radius: 2.00,
866    },
867    ElementData {
868        symbol: "Db",
869        name: "Dubnium",
870        mass: 268.0,
871        covalent_radius: 1.60,
872        vdw_radius: 2.00,
873    },
874    ElementData {
875        symbol: "Sg",
876        name: "Seaborgium",
877        mass: 271.0,
878        covalent_radius: 1.60,
879        vdw_radius: 2.00,
880    },
881    ElementData {
882        symbol: "Bh",
883        name: "Bohrium",
884        mass: 272.0,
885        covalent_radius: 1.60,
886        vdw_radius: 2.00,
887    },
888    ElementData {
889        symbol: "Hs",
890        name: "Hassium",
891        mass: 270.0,
892        covalent_radius: 1.60,
893        vdw_radius: 2.00,
894    },
895    ElementData {
896        symbol: "Mt",
897        name: "Meitnerium",
898        mass: 276.0,
899        covalent_radius: 1.60,
900        vdw_radius: 2.00,
901    },
902    ElementData {
903        symbol: "Ds",
904        name: "Darmstadtium",
905        mass: 281.0,
906        covalent_radius: 1.60,
907        vdw_radius: 2.00,
908    },
909    ElementData {
910        symbol: "Rg",
911        name: "Roentgenium",
912        mass: 280.0,
913        covalent_radius: 1.60,
914        vdw_radius: 2.00,
915    },
916    ElementData {
917        symbol: "Cn",
918        name: "Copernicium",
919        mass: 285.0,
920        covalent_radius: 1.60,
921        vdw_radius: 2.00,
922    },
923    ElementData {
924        symbol: "Nh",
925        name: "Nihonium",
926        mass: 284.0,
927        covalent_radius: 1.60,
928        vdw_radius: 2.00,
929    },
930    ElementData {
931        symbol: "Fl",
932        name: "Flerovium",
933        mass: 289.0,
934        covalent_radius: 1.60,
935        vdw_radius: 2.00,
936    },
937    ElementData {
938        symbol: "Mc",
939        name: "Moscovium",
940        mass: 288.0,
941        covalent_radius: 1.60,
942        vdw_radius: 2.00,
943    },
944    ElementData {
945        symbol: "Lv",
946        name: "Livermorium",
947        mass: 293.0,
948        covalent_radius: 1.60,
949        vdw_radius: 2.00,
950    },
951    ElementData {
952        symbol: "Ts",
953        name: "Tennessine",
954        mass: 294.0,
955        covalent_radius: 1.60,
956        vdw_radius: 2.00,
957    },
958    ElementData {
959        symbol: "Og",
960        name: "Oganesson",
961        mass: 294.0,
962        covalent_radius: 1.60,
963        vdw_radius: 2.00,
964    },
965];
966
967impl Element {
968    /// Atomic number (Z)
969    #[inline]
970    pub const fn z(self) -> u8 {
971        self as u8
972    }
973
974    /// Chemical symbol (e.g., "H", "C", "Fe")
975    #[inline]
976    pub fn symbol(self) -> &'static str {
977        ELEMENT_DATA[self.z() as usize - 1].symbol
978    }
979
980    /// English element name
981    #[inline]
982    pub fn name(self) -> &'static str {
983        ELEMENT_DATA[self.z() as usize - 1].name
984    }
985
986    /// Standard atomic mass (in atomic mass units)
987    #[inline]
988    pub fn atomic_mass(self) -> f32 {
989        ELEMENT_DATA[self.z() as usize - 1].mass
990    }
991
992    /// Covalent radius (in Angstroms)
993    #[inline]
994    pub fn covalent_radius(self) -> f32 {
995        ELEMENT_DATA[self.z() as usize - 1].covalent_radius
996    }
997
998    /// Van der Waals radius (in Angstroms)
999    #[inline]
1000    pub fn vdw_radius(self) -> f32 {
1001        ELEMENT_DATA[self.z() as usize - 1].vdw_radius
1002    }
1003
1004    /// All supported elements (1-118)
1005    pub const ALL: &'static [Element] = &[
1006        Element::H,
1007        Element::He,
1008        Element::Li,
1009        Element::Be,
1010        Element::B,
1011        Element::C,
1012        Element::N,
1013        Element::O,
1014        Element::F,
1015        Element::Ne,
1016        Element::Na,
1017        Element::Mg,
1018        Element::Al,
1019        Element::Si,
1020        Element::P,
1021        Element::S,
1022        Element::Cl,
1023        Element::Ar,
1024        Element::K,
1025        Element::Ca,
1026        Element::Sc,
1027        Element::Ti,
1028        Element::V,
1029        Element::Cr,
1030        Element::Mn,
1031        Element::Fe,
1032        Element::Co,
1033        Element::Ni,
1034        Element::Cu,
1035        Element::Zn,
1036        Element::Ga,
1037        Element::Ge,
1038        Element::As,
1039        Element::Se,
1040        Element::Br,
1041        Element::Kr,
1042        Element::Rb,
1043        Element::Sr,
1044        Element::Y,
1045        Element::Zr,
1046        Element::Nb,
1047        Element::Mo,
1048        Element::Tc,
1049        Element::Ru,
1050        Element::Rh,
1051        Element::Pd,
1052        Element::Ag,
1053        Element::Cd,
1054        Element::In,
1055        Element::Sn,
1056        Element::Sb,
1057        Element::Te,
1058        Element::I,
1059        Element::Xe,
1060        Element::Cs,
1061        Element::Ba,
1062        Element::La,
1063        Element::Ce,
1064        Element::Pr,
1065        Element::Nd,
1066        Element::Pm,
1067        Element::Sm,
1068        Element::Eu,
1069        Element::Gd,
1070        Element::Tb,
1071        Element::Dy,
1072        Element::Ho,
1073        Element::Er,
1074        Element::Tm,
1075        Element::Yb,
1076        Element::Lu,
1077        Element::Hf,
1078        Element::Ta,
1079        Element::W,
1080        Element::Re,
1081        Element::Os,
1082        Element::Ir,
1083        Element::Pt,
1084        Element::Au,
1085        Element::Hg,
1086        Element::Tl,
1087        Element::Pb,
1088        Element::Bi,
1089        Element::Po,
1090        Element::At,
1091        Element::Rn,
1092        Element::Fr,
1093        Element::Ra,
1094        Element::Ac,
1095        Element::Th,
1096        Element::Pa,
1097        Element::U,
1098        Element::Np,
1099        Element::Pu,
1100        Element::Am,
1101        Element::Cm,
1102        Element::Bk,
1103        Element::Cf,
1104        Element::Es,
1105        Element::Fm,
1106        Element::Md,
1107        Element::No,
1108        Element::Lr,
1109        Element::Rf,
1110        Element::Db,
1111        Element::Sg,
1112        Element::Bh,
1113        Element::Hs,
1114        Element::Mt,
1115        Element::Ds,
1116        Element::Rg,
1117        Element::Cn,
1118        Element::Nh,
1119        Element::Fl,
1120        Element::Mc,
1121        Element::Lv,
1122        Element::Ts,
1123        Element::Og,
1124    ];
1125
1126    /// Lookup by atomic number
1127    #[inline]
1128    pub fn by_number(z: u8) -> Option<Element> {
1129        if (1..=118).contains(&z) {
1130            Some(Self::ALL[(z - 1) as usize])
1131        } else {
1132            None
1133        }
1134    }
1135
1136    /// Lookup by symbol (case-insensitive)
1137    pub fn by_symbol(sym: &str) -> Option<Element> {
1138        Self::ALL
1139            .iter()
1140            .copied()
1141            .find(|e| e.symbol().eq_ignore_ascii_case(sym))
1142    }
1143
1144    /// Default allowed valences for this element (ascending order).
1145    ///
1146    /// Returns the list of typical valences used for implicit hydrogen
1147    /// calculation. The smallest value ≥ current bond-order sum is chosen.
1148    /// Returns `&[]` for noble gases and elements without standard valences.
1149    pub fn default_valences(self) -> &'static [u8] {
1150        match self {
1151            Element::H => &[1],
1152            Element::He => &[],
1153            Element::Li => &[1],
1154            Element::Be => &[2],
1155            Element::B => &[3],
1156            Element::C => &[4],
1157            Element::N => &[3, 5],
1158            Element::O => &[2],
1159            Element::F => &[1],
1160            Element::Ne => &[],
1161            Element::Na => &[1],
1162            Element::Mg => &[2],
1163            Element::Al => &[3],
1164            Element::Si => &[4],
1165            Element::P => &[3, 5],
1166            Element::S => &[2, 4, 6],
1167            Element::Cl => &[1, 3, 5, 7],
1168            Element::Ar => &[],
1169            Element::K => &[1],
1170            Element::Ca => &[2],
1171            Element::Sc => &[3],
1172            Element::Ti => &[2, 3, 4],
1173            Element::V => &[2, 3, 4, 5],
1174            Element::Cr => &[2, 3, 6],
1175            Element::Mn => &[2, 3, 4, 6, 7],
1176            Element::Fe => &[2, 3],
1177            Element::Co => &[2, 3],
1178            Element::Ni => &[2, 3],
1179            Element::Cu => &[1, 2],
1180            Element::Zn => &[2],
1181            Element::Ga => &[3],
1182            Element::Ge => &[2, 4],
1183            Element::As => &[3, 5],
1184            Element::Se => &[2, 4, 6],
1185            Element::Br => &[1, 3, 5, 7],
1186            Element::Kr => &[],
1187            Element::Rb => &[1],
1188            Element::Sr => &[2],
1189            Element::Y => &[3],
1190            Element::Zr => &[4],
1191            Element::Nb => &[3, 5],
1192            Element::Mo => &[2, 3, 4, 5, 6],
1193            Element::Tc => &[4, 6, 7],
1194            Element::Ru => &[2, 3, 4, 6, 8],
1195            Element::Rh => &[2, 3],
1196            Element::Pd => &[2, 4],
1197            Element::Ag => &[1],
1198            Element::Cd => &[2],
1199            Element::In => &[3],
1200            Element::Sn => &[2, 4],
1201            Element::Sb => &[3, 5],
1202            Element::Te => &[2, 4, 6],
1203            Element::I => &[1, 3, 5, 7],
1204            Element::Xe => &[],
1205            Element::Cs => &[1],
1206            Element::Ba => &[2],
1207            Element::La => &[3],
1208            Element::Ce => &[3, 4],
1209            Element::Pr => &[3, 4],
1210            Element::Nd => &[3],
1211            Element::Pm => &[3],
1212            Element::Sm => &[2, 3],
1213            Element::Eu => &[2, 3],
1214            Element::Gd => &[3],
1215            Element::Tb => &[3, 4],
1216            Element::Dy => &[3],
1217            Element::Ho => &[3],
1218            Element::Er => &[3],
1219            Element::Tm => &[2, 3],
1220            Element::Yb => &[2, 3],
1221            Element::Lu => &[3],
1222            Element::Hf => &[4],
1223            Element::Ta => &[5],
1224            Element::W => &[2, 3, 4, 5, 6],
1225            Element::Re => &[2, 4, 6, 7],
1226            Element::Os => &[2, 3, 4, 6, 8],
1227            Element::Ir => &[2, 3, 4],
1228            Element::Pt => &[2, 4],
1229            Element::Au => &[1, 3],
1230            Element::Hg => &[1, 2],
1231            Element::Tl => &[1, 3],
1232            Element::Pb => &[2, 4],
1233            Element::Bi => &[3, 5],
1234            Element::Po => &[2, 4],
1235            Element::At => &[1],
1236            Element::Rn => &[],
1237            Element::Fr => &[1],
1238            Element::Ra => &[2],
1239            Element::Ac => &[3],
1240            Element::Th => &[4],
1241            Element::Pa => &[4, 5],
1242            Element::U => &[3, 4, 5, 6],
1243            Element::Np => &[3, 4, 5, 6],
1244            Element::Pu => &[3, 4, 5, 6],
1245            Element::Am => &[2, 3, 4, 5, 6],
1246            Element::Cm => &[3],
1247            Element::Bk => &[3, 4],
1248            Element::Cf => &[2, 3, 4],
1249            Element::Es => &[2, 3],
1250            Element::Fm => &[2, 3],
1251            Element::Md => &[2, 3],
1252            Element::No => &[2, 3],
1253            Element::Lr => &[3],
1254            // Transactinides and superheavy – no meaningful organic valence
1255            _ => &[],
1256        }
1257    }
1258}
1259
1260impl FromStr for Element {
1261    type Err = ();
1262    fn from_str(s: &str) -> Result<Self, Self::Err> {
1263        Element::by_symbol(s).ok_or(())
1264    }
1265}
1266
1267impl core::fmt::Display for Element {
1268    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
1269        f.write_str(self.symbol())
1270    }
1271}
1272
1273#[cfg(test)]
1274mod test_element {
1275    use super::*;
1276
1277    #[test]
1278    fn test_accessors() {
1279        assert_eq!(Element::by_number(1), Some(Element::H));
1280        assert_eq!(Element::by_symbol("H"), Some(Element::H));
1281        assert_eq!(Element::by_symbol("h"), Some(Element::H));
1282        assert_eq!(Element::by_symbol("X"), None);
1283        assert_eq!(Element::by_number(0), None);
1284        assert_eq!(Element::by_number(119), None);
1285    }
1286
1287    #[test]
1288    fn test_props() {
1289        let e = Element::H;
1290        assert_eq!(e.z(), 1);
1291        assert_eq!(e.symbol(), "H");
1292        assert_eq!(e.name(), "Hydrogen");
1293        assert_eq!(e.atomic_mass(), 1.008);
1294        assert_eq!(format!("{}", e), "H");
1295    }
1296
1297    #[test]
1298    fn test_common_elements() {
1299        let c = Element::C;
1300        assert_eq!(c.z(), 6);
1301        assert_eq!(c.symbol(), "C");
1302        assert_eq!(c.name(), "Carbon");
1303        assert!((c.atomic_mass() - 12.01).abs() < 0.01);
1304
1305        let fe = Element::Fe;
1306        assert_eq!(fe.z(), 26);
1307        assert_eq!(fe.symbol(), "Fe");
1308        assert_eq!(fe.name(), "Iron");
1309
1310        let au = Element::Au;
1311        assert_eq!(au.z(), 79);
1312        assert_eq!(au.symbol(), "Au");
1313        assert_eq!(au.name(), "Gold");
1314    }
1315
1316    #[test]
1317    fn test_new_properties() {
1318        let c = Element::C;
1319        assert!((c.covalent_radius() - 0.76).abs() < 0.01);
1320        assert!((c.vdw_radius() - 1.70).abs() < 0.01);
1321
1322        let h = Element::H;
1323        assert!((h.covalent_radius() - 0.31).abs() < 0.01);
1324        assert!((h.vdw_radius() - 1.20).abs() < 0.01);
1325    }
1326
1327    #[test]
1328    fn test_all_elements() {
1329        assert_eq!(Element::ALL.len(), 118);
1330
1331        // Test first and last
1332        assert_eq!(Element::ALL[0], Element::H);
1333        assert_eq!(Element::ALL[117], Element::Og);
1334
1335        // Test all elements have valid z
1336        for (i, elem) in Element::ALL.iter().enumerate() {
1337            assert_eq!(elem.z() as usize, i + 1);
1338        }
1339    }
1340
1341    #[test]
1342    fn test_symbol_lookup() {
1343        assert_eq!(Element::by_symbol("C"), Some(Element::C));
1344        assert_eq!(Element::by_symbol("c"), Some(Element::C));
1345        assert_eq!(Element::by_symbol("Fe"), Some(Element::Fe));
1346        assert_eq!(Element::by_symbol("fe"), Some(Element::Fe));
1347        assert_eq!(Element::by_symbol("FE"), Some(Element::Fe));
1348        assert_eq!(Element::by_symbol("Og"), Some(Element::Og));
1349    }
1350}