1 | //
|
---|
2 | // units.cc
|
---|
3 | //
|
---|
4 | // Copyright (C) 1997 Limit Point Systems, Inc.
|
---|
5 | //
|
---|
6 | // Author: Curtis Janssen <cljanss@limitpt.com>
|
---|
7 | // Maintainer: LPS
|
---|
8 | //
|
---|
9 | // This file is part of the SC Toolkit.
|
---|
10 | //
|
---|
11 | // The SC Toolkit is free software; you can redistribute it and/or modify
|
---|
12 | // it under the terms of the GNU Library General Public License as published by
|
---|
13 | // the Free Software Foundation; either version 2, or (at your option)
|
---|
14 | // any later version.
|
---|
15 | //
|
---|
16 | // The SC Toolkit is distributed in the hope that it will be useful,
|
---|
17 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
|
---|
18 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
---|
19 | // GNU Library General Public License for more details.
|
---|
20 | //
|
---|
21 | // You should have received a copy of the GNU Library General Public License
|
---|
22 | // along with the SC Toolkit; see the file COPYING.LIB. If not, write to
|
---|
23 | // the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
|
---|
24 | //
|
---|
25 | // The U.S. Government is granted a limited license as per AL 91-7.
|
---|
26 | //
|
---|
27 |
|
---|
28 | #ifdef __GNUG__
|
---|
29 | #pragma implementation
|
---|
30 | #endif
|
---|
31 |
|
---|
32 | #include <util/misc/math.h>
|
---|
33 | #include <string.h>
|
---|
34 | #include <util/misc/units.h>
|
---|
35 | #include <util/state/stateio.h>
|
---|
36 |
|
---|
37 | #include <util/state/linkage.h>
|
---|
38 |
|
---|
39 | using namespace std;
|
---|
40 | using namespace sc;
|
---|
41 |
|
---|
42 | namespace sc {
|
---|
43 |
|
---|
44 | //////////////////////////////////////////////////////////////////////
|
---|
45 | // Utility functions
|
---|
46 |
|
---|
47 | static inline int eq(const char* a, const char* b)
|
---|
48 | {
|
---|
49 | return !strcmp(a,b);
|
---|
50 | }
|
---|
51 |
|
---|
52 | //////////////////////////////////////////////////////////////////////
|
---|
53 | // Units class definition
|
---|
54 |
|
---|
55 | static ClassDesc Units_cd(typeid(Units),"Units",1,"public SavableState",
|
---|
56 | 0, 0, create<Units>);
|
---|
57 |
|
---|
58 | Units::Units(const char *strrep)
|
---|
59 | {
|
---|
60 | if (strrep) strrep_ = strcpy(new char[strlen(strrep)+1], strrep);
|
---|
61 | else strrep_ = 0;
|
---|
62 | parse_unit();
|
---|
63 | }
|
---|
64 |
|
---|
65 | Units::Units(char *strrep, Units::Storage action)
|
---|
66 | {
|
---|
67 | if (action == Copy) {
|
---|
68 | if (strrep) strrep_ = strcpy(new char[strlen(strrep)+1], strrep);
|
---|
69 | else strrep_ = 0;
|
---|
70 | }
|
---|
71 | else {
|
---|
72 | strrep_ = strrep;
|
---|
73 | }
|
---|
74 | parse_unit();
|
---|
75 | }
|
---|
76 |
|
---|
77 | Units::Units(StateIn&s):
|
---|
78 | SavableState(s)
|
---|
79 | {
|
---|
80 | s.getstring(strrep_);
|
---|
81 | parse_unit();
|
---|
82 | }
|
---|
83 |
|
---|
84 | Units::~Units()
|
---|
85 | {
|
---|
86 | delete[] strrep_;
|
---|
87 | }
|
---|
88 |
|
---|
89 | void
|
---|
90 | Units::save_data_state(StateOut&s)
|
---|
91 | {
|
---|
92 | s.putstring(strrep_);
|
---|
93 | }
|
---|
94 |
|
---|
95 | double
|
---|
96 | Units::to(const Ref<Units> &units) const
|
---|
97 | {
|
---|
98 | return to_atomic_units_/units->to_atomic_units_;
|
---|
99 | }
|
---|
100 |
|
---|
101 | double
|
---|
102 | Units::from(const Ref<Units> &units) const
|
---|
103 | {
|
---|
104 | return 1.0/to(units);
|
---|
105 | }
|
---|
106 |
|
---|
107 | double
|
---|
108 | Units::to_atomic_units() const
|
---|
109 | {
|
---|
110 | return to_atomic_units_;
|
---|
111 | }
|
---|
112 |
|
---|
113 | double
|
---|
114 | Units::from_atomic_units() const
|
---|
115 | {
|
---|
116 | return 1.0/to_atomic_units_;
|
---|
117 | }
|
---|
118 |
|
---|
119 | const char *
|
---|
120 | Units::string_rep() const
|
---|
121 | {
|
---|
122 | return strrep_;
|
---|
123 | }
|
---|
124 |
|
---|
125 | void
|
---|
126 | Units::parse_unit()
|
---|
127 | {
|
---|
128 | to_atomic_units_ = 1.0;
|
---|
129 |
|
---|
130 | int invert = 0;
|
---|
131 | const char *rest = strrep_;
|
---|
132 |
|
---|
133 | while (rest) {
|
---|
134 | const char *end = ::strpbrk(rest, " */");
|
---|
135 | int nchar;
|
---|
136 | if (end) {
|
---|
137 | nchar = end - rest;
|
---|
138 | }
|
---|
139 | else {
|
---|
140 | nchar = strlen(rest);
|
---|
141 | }
|
---|
142 | char *unitstring = new char[nchar+1];
|
---|
143 | memcpy(unitstring,rest,nchar);
|
---|
144 | unitstring[nchar] = '\0';
|
---|
145 |
|
---|
146 | // physical constants used for atomic unit conversion factors
|
---|
147 | // from CRC Handbook 77th Ed. Tables 1&2 (CODATA 1986)
|
---|
148 | const double a0 = 5.29177249e-11; // m
|
---|
149 | //const double hbar = 1.05457266e-34; // J s
|
---|
150 | const double e = 1.60217733e-19; // C
|
---|
151 | const double me = 9.1093897e-31; // kg
|
---|
152 | const double e0 = 8.854187817e-12; // F/m
|
---|
153 | const double NA = 6.0221367e23; // mol-1 (from CRC Handbook)
|
---|
154 |
|
---|
155 | // derived au conversion factors
|
---|
156 | const double Ea = e*e/((4.0*M_PI*e0)*a0); // J
|
---|
157 | //const double time = hbar/Ea; // s
|
---|
158 |
|
---|
159 | // other conversions
|
---|
160 | const double amu = 1.6605655e-27; // kg
|
---|
161 | const double cal = 4.184; // J
|
---|
162 |
|
---|
163 | double factor = 1.0;
|
---|
164 | if (eq(unitstring, "bohr")
|
---|
165 | ||eq(unitstring, "bohrs")) {
|
---|
166 | }
|
---|
167 | else if (eq(unitstring, "hartree")
|
---|
168 | ||eq(unitstring, "hartrees")
|
---|
169 | ||eq(unitstring, "Hartree")
|
---|
170 | ||eq(unitstring, "Hartrees")) {
|
---|
171 | }
|
---|
172 | else if (eq(unitstring, "ev")
|
---|
173 | ||eq(unitstring, "eV")) {
|
---|
174 | factor = 1.0/27.2113834; // physics.nist.gov/constants
|
---|
175 | }
|
---|
176 | else if (eq(unitstring, "debye")) {
|
---|
177 | factor = 1.0/2.541765; // several WWW sources
|
---|
178 | }
|
---|
179 | else if (eq(unitstring, "radian")
|
---|
180 | ||eq(unitstring, "radians")) {
|
---|
181 | }
|
---|
182 | else if (eq(unitstring, "mol")
|
---|
183 | ||eq(unitstring, "mole")) {
|
---|
184 | factor = NA;
|
---|
185 | }
|
---|
186 | else if (eq(unitstring, "kcal")) {
|
---|
187 | factor = 1000.0*cal/Ea;
|
---|
188 | }
|
---|
189 | else if (eq(unitstring, "kcal_per_mol")) {
|
---|
190 | factor = 1000.0*cal/(Ea*NA);
|
---|
191 | }
|
---|
192 | else if (eq(unitstring, "N")
|
---|
193 | ||eq(unitstring, "newton")) {
|
---|
194 | factor = a0/Ea;
|
---|
195 | }
|
---|
196 | else if (eq(unitstring, "dyne")) {
|
---|
197 | factor = 1.0e-5*a0/Ea;
|
---|
198 | }
|
---|
199 | else if (eq(unitstring, "m")
|
---|
200 | ||eq(unitstring, "meter")) {
|
---|
201 | factor = 1.0/a0;
|
---|
202 | }
|
---|
203 | else if (eq(unitstring, "cm")
|
---|
204 | ||eq(unitstring, "centimeter")) {
|
---|
205 | factor = 1.0e-2/a0;
|
---|
206 | }
|
---|
207 | else if (eq(unitstring, "angstrom")
|
---|
208 | ||eq(unitstring, "angstroms")
|
---|
209 | ||eq(unitstring, "aangstrom")
|
---|
210 | ||eq(unitstring, "aangstroms")) {
|
---|
211 | factor = 1.0e-10/a0;
|
---|
212 | }
|
---|
213 | else if (eq(unitstring, "amu")) {
|
---|
214 | factor = amu/me;
|
---|
215 | }
|
---|
216 | else if (eq(unitstring, "degree")
|
---|
217 | ||eq(unitstring, "degrees")) {
|
---|
218 | factor = M_PI/180.0;
|
---|
219 | }
|
---|
220 | else {
|
---|
221 | ExEnv::errn() << "Units: Cannot handle \"" << unitstring << "\"" << endl;
|
---|
222 | abort();
|
---|
223 | }
|
---|
224 | delete[] unitstring;
|
---|
225 | if (invert) factor = 1.0/factor;
|
---|
226 | to_atomic_units_ *= factor;
|
---|
227 | rest = ::strpbrk(rest, " */");
|
---|
228 | while (rest && (*rest == ' ' || *rest == '*' || *rest == '/')) {
|
---|
229 | if (*rest == '/') invert = !invert;
|
---|
230 | rest++;
|
---|
231 | }
|
---|
232 | }
|
---|
233 | }
|
---|
234 |
|
---|
235 | /////////////////////////////////////////////////////////////////////////////
|
---|
236 |
|
---|
237 | }
|
---|
238 |
|
---|
239 | // Local Variables:
|
---|
240 | // mode: c++
|
---|
241 | // c-file-style: "CLJ"
|
---|
242 | // End:
|
---|