1 //
2 // elements.c
3 // libmsym
4 //
5 // Created by Marcus Johansson on 17/02/15.
6 // Copyright (c) 2015 Marcus Johansson.
7 //
8 // Distributed under the MIT License ( See LICENSE file or copy at http://opensource.org/licenses/MIT )
9 //
10
11 #include <string.h>
12 #include <math.h>
13
14 #include "elements.h"
15
16 #include "debug.h"
17
18 const struct _periodic_table {
19 int n;
20 char *name;
21 int massnr;
22 } periodic_table[] = {
23 { 1, "H", 1 },
24 { 1, "D", 2 },
25 { 1, "T", 3 },
26 { 2, "He", 4 },
27 { 3, "Li", 7 },
28 { 4, "Be", 9 },
29 { 5, "B", 11 },
30 { 6, "C", 12 },
31 { 7, "N", 14 },
32 { 8, "O", 16 },
33 { 9, "F", 19 },
34 { 10, "Ne", 20 },
35 { 11, "Na", 23 },
36 { 12, "Mg", 24 },
37 { 13, "Al", 27 },
38 { 14, "Si", 28 },
39 { 15, "P", 31 },
40 { 16, "S", 32 },
41 { 17, "Cl", 35 },
42 { 18, "Ar", 40 },
43 { 19, "K", 39 },
44 { 20, "Ca", 40 },
45 { 21, "Sc", 45 },
46 { 22, "Ti", 48 },
47 { 23, "V", 51 },
48 { 24, "Cr", 52 },
49 { 25, "Mn", 55 },
50 { 26, "Fe", 56 },
51 { 27, "Co", 58 },
52 { 28, "Ni", 58 },
53 { 29, "Cu", 64 },
54 { 30, "Zn", 65 },
55 { 31, "Ga", 70 },
56 { 32, "Ge", 73 },
57 { 33, "As", 75 },
58 { 34, "Se", 79 },
59 { 35, "Br", 80 },
60 { 36, "Kr", 84 },
61 { 37, "Rb", 85 },
62 { 38, "Sr", 88 },
63 { 39, "Y", 89 },
64 { 40, "Zr", 91 },
65 { 41, "Nb", 93 },
66 { 42, "Mo", 96 },
67 { 43, "Tc", 98 },
68 { 44, "Ru", 101 },
69 { 45, "Rh", 103 },
70 { 46, "Pd", 106 },
71 { 47, "Ag", 108 },
72 { 48, "Cd", 112 },
73 { 49, "In", 115 },
74 { 50, "Sn", 119 },
75 { 51, "Sb", 122 },
76 { 52, "Te", 128 },
77 { 53, "I", 127 },
78 { 54, "Xe", 131 },
79 { 55, "Cs", 133 },
80 { 56, "Ba", 137 },
81 { 57, "La", 139 },
82 { 58, "Ce", 140 },
83 { 59, "Pr", 141 },
84 { 60, "Nd", 144 },
85 { 61, "Pm", 145 },
86 { 62, "Sm", 150 },
87 { 63, "Eu", 152 },
88 { 64, "Gd", 157 },
89 { 65, "Tb", 159 },
90 { 66, "Dy", 163 },
91 { 67, "Ho", 165 },
92 { 68, "Er", 167 },
93 { 69, "Tm", 169 },
94 { 70, "Yb", 173 },
95 { 71, "Lu", 175 },
96 { 72, "Hf", 178 },
97 { 73, "Ta", 181 },
98 { 74, "W", 184 },
99 { 75, "Re", 186 },
100 { 76, "Os", 190 },
101 { 77, "Ir", 192 },
102 { 78, "Pt", 195 },
103 { 79, "Au", 197 },
104 { 80, "Hg", 201 },
105 { 81, "Tl", 204 },
106 { 82, "Pb", 207 },
107 { 83, "Bi", 209 },
108 { 84, "Po", 209 },
109 { 85, "At", 210 },
110 { 86, "Rn", 222 },
111 { 87, "Fr", 223 },
112 { 88, "Ra", 226 },
113 { 89, "Ac", 227 },
114 { 90, "Th", 232 },
115 { 91, "Pa", 231 },
116 { 92, "U", 238 },
117 { 93, "Np", 237 },
118 { 94, "Pu", 244 },
119 { 95, "Am", 243 },
120 { 96, "Cm", 247 },
121 { 97, "Bk", 247 },
122 { 98, "Cf", 251 },
123 { 99, "Es", 252 },
124 { 100, "Fm", 257 },
125 { 101, "Md", 258 },
126 { 102, "No", 259 },
127 { 103, "Lr", 262 },
128 { 104, "Rf", 261 },
129 { 105, "Db", 268 },
130 { 106, "Sg", 263 },
131 { 107, "Bh", 264 },
132 { 108, "Hs", 269 },
133 { 109, "Mt", 268 },
134 { 110, "Ds", 272 },
135 { 111, "Rg", 273 },
136 { 112, "Uub", 277 },
137 { 113, "Uut", 286 },
138 { 114, "Uuq", 289 },
139 { 115, "Uup", 288 },
140 { 116, "Uuh", 292 },
141 { 117, "Uus", 292 },
142 { 118, "Uuo", 293 }
143 };
144
printElement(msym_element_t * element)145 void printElement(msym_element_t *element){
146 clean_debug_printf("%s (nuclear charge:%d, mass:%lf) [%lf;%lf;%lf]\n",element->name, element->n, element->m, element->v[0], element->v[1], element->v[2]);
147 }
148
complementElementData(msym_element_t * element)149 msym_error_t complementElementData(msym_element_t *element){
150 msym_error_t ret = MSYM_SUCCESS;
151 element->name[sizeof(element->name)-1] = '\0';
152 size_t strl = strlen(element->name);
153 if(strl <= 0 && element->n <= 0 && element->m <= 0.0){
154 msymSetErrorDetails("Element has no mass, name or nuclear charge");
155 ret = MSYM_INVALID_ELEMENTS;
156 goto err;
157 }
158 if(element->n >= sizeof(periodic_table)/sizeof(periodic_table[0]) && element->m <= 0.0 && strl <= 0){
159 msymSetErrorDetails("Element has no mass or name and a nuclear charge of %d",element->n);
160 ret = MSYM_INVALID_ELEMENTS;
161 goto err;
162 }
163
164 if(element->n > 0 && (element->m <= 0.0 || strl <= 0)){
165 int fi, fil = sizeof(periodic_table)/sizeof(periodic_table[0]);
166 for(fi = 0; fi < fil;fi++){
167 if(periodic_table[fi].n == element->n) {
168 if(element->m <= 0.0) element->m = (double) periodic_table[fi].massnr;
169 if(strl <= 0) snprintf(element->name, sizeof(element->name), "%s",periodic_table[fi].name);
170 break;
171 }
172 }
173
174 if(fi == fil){
175 msymSetErrorDetails("Unknown element with nuclear charge %d",fi);
176 ret = MSYM_INVALID_ELEMENTS;
177 goto err;
178 }
179 } else if(strl > 0 && (element->m <= 0.0 || element->n <= 0)){
180 int fi, fil = sizeof(periodic_table)/sizeof(periodic_table[0]);
181
182 for(fi = 0; fi < fil;fi++){
183 int stre = 0;
184 for(int i = 0;i < sizeof(element->name) && i < sizeof(periodic_table[fi].name);i++){
185 char ec = element->name[i], ep = periodic_table[fi].name[i];
186 char cmp[2] = {
187 ec >= 'A' && ec <= 'Z' ? ec | 0x60 : ec,
188 ep >= 'A' && ep <= 'Z' ? ep | 0x60 : ep
189 };
190 if(cmp[0] != cmp[1]){
191 stre = cmp[0] - cmp[1];
192 break;
193 } else if (cmp[0] == '\0'){
194 break;
195 }
196 }
197
198 //if(0 == strncmp(periodic_table[fi].name, element->name, strnlen(periodic_table[fi].name, sizeof(element->name)))) {
199 if(0 == stre){
200 if(element->m <= 0.0) element->m = (double) periodic_table[fi].massnr;
201 if(element->n <= 0) element->n = periodic_table[fi].n;
202 break;
203 }
204 }
205
206 if(fi == fil){
207 char buf[sizeof(element->name)];
208 snprintf(buf, sizeof(element->name), "%s",element->name); //in case someone forgets to null terminate
209 msymSetErrorDetails("Unknown element with name %s",buf);
210 ret = MSYM_INVALID_ELEMENTS;
211 goto err;
212 }
213 } else if(element->m > 0.0 && (strl <= 0 || element->n <= 0)){
214 int fim = 0, fil = sizeof(periodic_table)/sizeof(periodic_table[0]);
215 double last = -1.0;
216 for(int fi = 0; fi < fil;fi++){
217 double diff = fabs(periodic_table[fi].massnr - element->m);
218 if(diff < last || last < 0.0){
219 last = diff;
220 fim = fi;
221 }
222 }
223 if(strl <= 0) snprintf(element->name, sizeof(element->name), "%s",periodic_table[fim].name);
224 if(element->n <= 0) element->n = periodic_table[fim].n;
225 }
226
227 err:
228 return ret;
229
230 }
231