00001 /*************************************************************************** 00002 * RCS INFORMATION: 00003 * 00004 * $RCSfile: PeriodicTable.C,v $ 00005 * $Author: johns $ $Locker: $ $State: Exp $ 00006 * $Revision: 1.5 $ $Date: 2012年08月10日 14:42:37 $ 00007 * 00008 ***************************************************************************/ 00009 00010 /* 00011 * periodic table of elements and helper functions to convert 00012 * ordinal numbers to labels and back. 00013 * all tables and functions are declared static, so that it 00014 * can be safely included by all plugins that may need it. 00015 * 00016 * 2002-2005 axel.kohlmeyer@theochem.ruhr-uni-bochum.de, vmd@ks.uiuc.edu 00017 */ 00018 00019 #include <string.h> 00020 #include <ctype.h> 00021 00022 /* periodic table of elements for translation of ordinal to atom type */ 00023 static const char *pte_label[] = { 00024 "X", "H", "He", "Li", "Be", "B", "C", "N", "O", "F", "Ne", 00025 "Na", "Mg", "Al", "Si", "P" , "S", "Cl", "Ar", "K", "Ca", "Sc", 00026 "Ti", "V", "Cr", "Mn", "Fe", "Co", "Ni", "Cu", "Zn", "Ga", "Ge", 00027 "As", "Se", "Br", "Kr", "Rb", "Sr", "Y", "Zr", "Nb", "Mo", "Tc", 00028 "Ru", "Rh", "Pd", "Ag", "Cd", "In", "Sn", "Sb", "Te", "I", "Xe", 00029 "Cs", "Ba", "La", "Ce", "Pr", "Nd", "Pm", "Sm", "Eu", "Gd", "Tb", 00030 "Dy", "Ho", "Er", "Tm", "Yb", "Lu", "Hf", "Ta", "W", "Re", "Os", 00031 "Ir", "Pt", "Au", "Hg", "Tl", "Pb", "Bi", "Po", "At", "Rn", "Fr", 00032 "Ra", "Ac", "Th", "Pa", "U", "Np", "Pu", "Am", "Cm", "Bk", "Cf", 00033 "Es", "Fm", "Md", "No", "Lr", "Rf", "Db", "Sg", "Bh", "Hs", "Mt", 00034 "Ds", "Rg" 00035 }; 00036 static const int nr_pte_entries = sizeof(pte_label) / sizeof(char *); 00037 00038 /* corresponding table of masses. */ 00039 static const double pte_mass[] = { 00040 /* X */ 0.00000, 1.00794, 4.00260, 6.941, 9.012182, 10.811, 00041 /* C */ 12.0107, 14.0067, 15.9994, 18.9984032, 20.1797, 00042 /* Na */ 22.989770, 24.3050, 26.981538, 28.0855, 30.973761, 00043 /* S */ 32.065, 35.453, 39.948, 39.0983, 40.078, 44.955910, 00044 /* Ti */ 47.867, 50.9415, 51.9961, 54.938049, 55.845, 58.9332, 00045 /* Ni */ 58.6934, 63.546, 65.409, 69.723, 72.64, 74.92160, 00046 /* Se */ 78.96, 79.904, 83.798, 85.4678, 87.62, 88.90585, 00047 /* Zr */ 91.224, 92.90638, 95.94, 98.0, 101.07, 102.90550, 00048 /* Pd */ 106.42, 107.8682, 112.411, 114.818, 118.710, 121.760, 00049 /* Te */ 127.60, 126.90447, 131.293, 132.90545, 137.327, 00050 /* La */ 138.9055, 140.116, 140.90765, 144.24, 145.0, 150.36, 00051 /* Eu */ 151.964, 157.25, 158.92534, 162.500, 164.93032, 00052 /* Er */ 167.259, 168.93421, 173.04, 174.967, 178.49, 180.9479, 00053 /* W */ 183.84, 186.207, 190.23, 192.217, 195.078, 196.96655, 00054 /* Hg */ 200.59, 204.3833, 207.2, 208.98038, 209.0, 210.0, 222.0, 00055 /* Fr */ 223.0, 226.0, 227.0, 232.0381, 231.03588, 238.02891, 00056 /* Np */ 237.0, 244.0, 243.0, 247.0, 247.0, 251.0, 252.0, 257.0, 00057 /* Md */ 258.0, 259.0, 262.0, 261.0, 262.0, 266.0, 264.0, 269.0, 00058 /* Mt */ 268.0, 271.0, 272.0 00059 }; 00060 00061 /* 00062 * corresponding table of VDW radii. 00063 * van der Waals radii are taken from A. Bondi, 00064 * J. Phys. Chem., 68, 441 - 452, 1964, 00065 * except the value for H, which is taken from R.S. Rowland & R. Taylor, 00066 * J.Phys.Chem., 100, 7384 - 7391, 1996. Radii that are not available in 00067 * either of these publications have RvdW = 2.00 ナ. 00068 * The radii for Ions (Na, K, Cl, Ca, Mg, and Cs are based on the CHARMM27 00069 * Rmin/2 parameters for (SOD, POT, CLA, CAL, MG, CES) by default. 00070 */ 00071 static const float pte_vdw_radius[] = { 00072 /* X */ 1.50f, 1.20f, 1.40f, 1.82f, 2.00f, 2.00f, 00073 /* C */ 1.70f, 1.55f, 1.52f, 1.47f, 1.54f, 00074 /* Na */ 1.36f, 1.18f, 2.00f, 2.10f, 1.80f, 00075 /* S */ 1.80f, 2.27f, 1.88f, 1.76f, 1.37f, 2.00f, 00076 /* Ti */ 2.00f, 2.00f, 2.00f, 2.00f, 2.00f, 2.00f, 00077 /* Ni */ 1.63f, 1.40f, 1.39f, 1.07f, 2.00f, 1.85f, 00078 /* Se */ 1.90f, 1.85f, 2.02f, 2.00f, 2.00f, 2.00f, 00079 /* Zr */ 2.00f, 2.00f, 2.00f, 2.00f, 2.00f, 2.00f, 00080 /* Pd */ 1.63f, 1.72f, 1.58f, 1.93f, 2.17f, 2.00f, 00081 /* Te */ 2.06f, 1.98f, 2.16f, 2.10f, 2.00f, 00082 /* La */ 2.00f, 2.00f, 2.00f, 2.00f, 2.00f, 2.00f, 00083 /* Eu */ 2.00f, 2.00f, 2.00f, 2.00f, 2.00f, 00084 /* Er */ 2.00f, 2.00f, 2.00f, 2.00f, 2.00f, 2.00f, 00085 /* W */ 2.00f, 2.00f, 2.00f, 2.00f, 1.72f, 1.66f, 00086 /* Hg */ 1.55f, 1.96f, 2.02f, 2.00f, 2.00f, 2.00f, 2.00f, 00087 /* Fr */ 2.00f, 2.00f, 2.00f, 2.00f, 2.00f, 1.86f, 00088 /* Np */ 2.00f, 2.00f, 2.00f, 2.00f, 2.00f, 2.00f, 2.00f, 2.00f, 00089 /* Md */ 2.00f, 2.00f, 2.00f, 2.00f, 2.00f, 2.00f, 2.00f, 2.00f, 00090 /* Mt */ 2.00f, 2.00f, 2.00f 00091 }; 00092 00093 /* lookup functions */ 00094 00095 const char *get_pte_label(const int idx) { 00096 if ((idx < 1) || (idx >= nr_pte_entries)) 00097 return pte_label[0]; 00098 00099 return pte_label[idx]; 00100 } 00101 00102 float get_pte_mass(const int idx) { 00103 if ((idx < 1) || (idx >= nr_pte_entries)) 00104 return (float) pte_mass[0]; 00105 00106 return (float) pte_mass[idx]; 00107 } 00108 00109 float get_pte_vdw_radius(const int idx) { 00110 if ((idx < 1) || (idx >= nr_pte_entries)) 00111 return (float) pte_vdw_radius[0]; 00112 00113 #if 1 00114 /* Replace Hydrogen radius with an "all-atom" radius */ 00115 if (idx == 1) 00116 return 1.0f; /* H */ 00117 #else 00118 /* Replace with old VMD atom radii values */ 00119 switch (idx) { 00120 case 1: return 1.0; /* H */ 00121 case 6: return 1.5; /* C */ 00122 case 7: return 1.4; /* N */ 00123 case 8: return 1.3; /* O */ 00124 case 9: return 1.2; /* F */ 00125 case 15: return 1.5; /* P */ 00126 case 16: return 1.9; /* S */ 00127 } 00128 #endif 00129 00130 return (float) pte_vdw_radius[idx]; 00131 } 00132 00133 int get_pte_idx(const char *label) { 00134 int i; 00135 char atom[3]; 00136 00137 /* zap string */ 00138 atom[0] = (char) 0; 00139 atom[1] = (char) 0; 00140 atom[2] = (char) 0; 00141 00142 /* if we don't have a null-pointer, there must be at least two 00143 * chars, which is all we need. we convert to the capitalization 00144 * convention of the table above during assignment. */ 00145 if (label != NULL) { 00146 atom[0] = (char) toupper((int) label[0]); 00147 atom[1] = (char) tolower((int) label[1]); 00148 } 00149 00150 for (i=0; i < nr_pte_entries; ++i) { 00151 if ((pte_label[i][0] == atom[0]) && (pte_label[i][1] == atom[1])) 00152 return i; 00153 } 00154 00155 return 0; 00156 } 00157 00158 int get_pte_idx_from_string(const char *label) { 00159 int i, ind; 00160 char atom[3]; 00161 00162 if (label != NULL) { 00163 /* zap string */ 00164 atom[0] = atom[1] = atom[2] = '0円'; 00165 00166 for (ind=0,i=0; (ind<2) && (label[i]!='0円'); i++) { 00167 if (label[i] != ' ') { 00168 atom[ind] = toupper(label[i]); 00169 ind++; 00170 } 00171 } 00172 00173 if (ind < 1) 00174 return 0; /* no non-whitespace characters */ 00175 00176 for (i=0; i < nr_pte_entries; ++i) { 00177 if ((toupper(pte_label[i][0]) == atom[0]) && (toupper(pte_label[i][1]) == atom[1])) 00178 return i; 00179 } 00180 } 00181 00182 return 0; 00183 } 00184 00185 #if 0 00186 #include <stdio.h> 00187 00188 int main() { 00189 int i; 00190 00191 printf("Periodic table check/dump\n"); 00192 printf(" Table contains data for %d elements\n", nr_pte_entries); 00193 printf(" Mass table size check: %d\n", sizeof(pte_mass) / sizeof(float)); 00194 printf(" VDW table size check: %d\n", sizeof(pte_vdw_radius) / sizeof(float)); 00195 printf("\n"); 00196 printf("Symbol Num Mass rVDW\n"); 00197 for (i=0; i<nr_pte_entries; i++) { 00198 printf(" %-2s %3d %6.2f %4.2f\n", 00199 get_pte_label(i), i, get_pte_mass(i), get_pte_vdw_radius(i)); 00200 } 00201 return 0; 00202 } 00203 #endif 00204 00205 00206 00207