Loading...
Searching...
No Matches
periodic_table.hpp
Go to the documentation of this file.
1#pragma once
2
3/**
4 * PeriodicTable: provides atomic number lookup from element symbol.
5 *
6 * Maps standard element symbols (e.g. "Si", "Fe") to their atomic numbers (Z).
7 * Handles symbols with trailing digits by stripping non-alphabetic characters.
8 */
9
10#include <cctype>
11#include <map>
12#include <string>
13
14namespace q3 {
15
16/**
17 * Provides element symbol to atomic number (Z) mapping.
18 */
20 public:
21 /**
22 * Return the atomic number for a given element symbol.
23 * Strips trailing digits (e.g. "Si1" → "Si").
24 * Returns 0 if the element is not found.
25 */
26 static int atomic_number_by_element_symbol(const std::string& symbol) {
27 // Strip trailing digits (e.g. "Si1" → "Si")
28 std::string clean;
29 for (char character : symbol) {
30 if (std::isalpha(character))
31 clean += character;
32 }
33
34 const auto& table = symbol_to_atomic_number_table();
35 auto iterator = table.find(clean);
36 if (iterator != table.end())
37 return iterator->second;
38 return 0;
39 }
40
41 /**
42 * Return the element symbol for a given atomic number, or an empty string
43 * when there is no such element.
44 *
45 * The inverse of the lookup above, which a file format that identifies its
46 * atoms by Z rather than by symbol needs on the way back in — a cube file
47 * does (see io/volumetric/cube_reader.hpp).
48 */
49 static const std::string& element_symbol_by_atomic_number(int atomic_number) {
50 static const std::map<int, std::string> symbol_table = [] {
51 std::map<int, std::string> inverted;
52 for (const auto& [symbol, number] : symbol_to_atomic_number_table())
53 inverted.emplace(number, symbol);
54 return inverted;
55 }();
56 static const std::string no_such_element;
57
58 auto iterator = symbol_table.find(atomic_number);
59 return iterator == symbol_table.end() ? no_such_element : iterator->second;
60 }
61
62 private:
63 /**
64 * The one element list, shared by both lookups so that neither direction
65 * can know an element the other does not.
66 */
67 static const std::map<std::string, int>& symbol_to_atomic_number_table() {
68 static const std::map<std::string, int> atomic_number_table = {
69 {"H", 1}, {"He", 2}, {"Li", 3}, {"Be", 4}, {"B", 5}, {"C", 6},
70 {"N", 7}, {"O", 8}, {"F", 9}, {"Ne", 10}, {"Na", 11}, {"Mg", 12},
71 {"Al", 13}, {"Si", 14}, {"P", 15}, {"S", 16}, {"Cl", 17}, {"Ar", 18},
72 {"K", 19}, {"Ca", 20}, {"Sc", 21}, {"Ti", 22}, {"V", 23}, {"Cr", 24},
73 {"Mn", 25}, {"Fe", 26}, {"Co", 27}, {"Ni", 28}, {"Cu", 29}, {"Zn", 30},
74 {"Ga", 31}, {"Ge", 32}, {"As", 33}, {"Se", 34}, {"Br", 35}, {"Kr", 36},
75 {"Rb", 37}, {"Sr", 38}, {"Y", 39}, {"Zr", 40}, {"Nb", 41}, {"Mo", 42},
76 {"Tc", 43}, {"Ru", 44}, {"Rh", 45}, {"Pd", 46}, {"Ag", 47}, {"Cd", 48},
77 {"In", 49}, {"Sn", 50}, {"Sb", 51}, {"Te", 52}, {"I", 53}, {"Xe", 54},
78 {"Cs", 55}, {"Ba", 56}, {"La", 57}, {"Ce", 58}, {"Pr", 59}, {"Nd", 60},
79 {"Pm", 61}, {"Sm", 62}, {"Eu", 63}, {"Gd", 64}, {"Tb", 65}, {"Dy", 66},
80 {"Ho", 67}, {"Er", 68}, {"Tm", 69}, {"Yb", 70}, {"Lu", 71}, {"Hf", 72},
81 {"Ta", 73}, {"W", 74}, {"Re", 75}, {"Os", 76}, {"Ir", 77}, {"Pt", 78},
82 {"Au", 79}, {"Hg", 80}, {"Tl", 81}, {"Pb", 82}, {"Bi", 83}, {"Po", 84},
83 {"At", 85}, {"Rn", 86}, {"Fr", 87}, {"Ra", 88}, {"Ac", 89}, {"Th", 90},
84 {"Pa", 91}, {"U", 92}, {"Np", 93}, {"Pu", 94}, {"Am", 95}, {"Cm", 96},
85 {"Bk", 97}, {"Cf", 98}, {"Es", 99}, {"Fm", 100}, {"Md", 101}, {"No", 102},
86 {"Lr", 103}, {"Rf", 104}, {"Db", 105}, {"Sg", 106}, {"Bh", 107}, {"Hs", 108},
87 {"Mt", 109}, {"Ds", 110}, {"Rg", 111}, {"Cn", 112}, {"Nh", 113}, {"Fl", 114},
88 {"Mc", 115}, {"Lv", 116}, {"Ts", 117}, {"Og", 118},
89 };
90 return atomic_number_table;
91 }
92};
93
94} // namespace q3
static int atomic_number_by_element_symbol(const std::string &symbol)
static const std::string & element_symbol_by_atomic_number(int atomic_number)