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