NAPISD
PAHdb website C++ backend
Loading...
Searching...
No Matches
PAHGeometry.cpp
1#include "PAHGeometry.h"
2
3PAHGeometry::PAHGeometry() : _mass(0.0), _dimensions(3, {2.0, 0.0, 0.0}) {
4 _atoms.reserve(16);
5}
6
7PAHGeometry::PAHGeometry(const std::vector<Atom> &atoms)
8 : _atoms(atoms.cbegin(), atoms.cend()), _mass(0.0),
9 _dimensions(3, {2.0, 0.0, 0.0}) {
10
11 for (const auto &atom : _atoms) {
12
13 _mass += atom.getMass();
14 }
15}
16
17void PAHGeometry::diagonalize() {
18
19 double x_com = 0, y_com = 0, z_com = 0, m_tot = 0;
20
21 for (const auto &atom : _atoms) {
22
23 if (atom.getType() == 12 || atom.getType() == 26)
24 continue;
25
26 x_com += atom.getMass() * atom.getX();
27 y_com += atom.getMass() * atom.getY();
28 z_com += atom.getMass() * atom.getZ();
29 m_tot += atom.getMass();
30 }
31
32 x_com /= m_tot;
33 y_com /= m_tot;
34 z_com /= m_tot;
35
36 for (auto &atom : _atoms) {
37
38 atom.setX(atom.getX() - x_com);
39 atom.setY(atom.getY() - y_com);
40 atom.setZ(atom.getZ() - z_com);
41 }
42
43 double I[3][3] = {{0, 0, 0}, {0, 0, 0}, {0, 0, 0}};
44
45 for (const auto &atom : _atoms) {
46
47 if (atom.getType() == 12 || atom.getType() == 26)
48 continue;
49
50 I[0][0] += atom.getMass() *
51 (atom.getY() * atom.getY() + atom.getZ() * atom.getZ());
52 I[1][1] += atom.getMass() *
53 (atom.getX() * atom.getX() + atom.getZ() * atom.getZ());
54 I[2][2] += atom.getMass() *
55 (atom.getX() * atom.getX() + atom.getY() * atom.getY());
56
57 // I[0][1] -= atom.getMass() * atom.getX() * atom.getY();
58 // I[0][2] -= atom.getMass() * atom.getX() * atom.getZ();
59 // I[1][2] -= atom.getMass() * atom.getY() * atoml.getZ();
60 }
61 /*
62 if (abs(I[0][1] / I[0][0]) < 1e-3 && abs(I[0][1] / I[1][1]) < 1e-3) {
63
64 I[0][1] = 0.0;
65 }
66
67 if (abs(I[0][2] / I[0][0]) < 1e-3 && abs(I[0][2] / I[2][2]) < 1e-3) {
68
69 I[0][2] = 0.0;
70 }
71
72 if (abs(I[1][2] / I[1][1]) < 1e-3 && abs(I[1][2] / I[2][2]) < 1e-3){
73
74 I[1][2] = 0.0;
75 }
76 */
77 double v[3][3] = {{1.0, 0.0, 0.0}, {0.0, 1.0, 0.0}, {0.0, 0.0, 1.0}},
78 b[3] = {I[0][0], I[1][1], I[2][2]}, *d = b, f[3] = {0.0, 0.0, 0.0};
79
80 int nrot = 0;
81
82 double sm, tresh, g, h, t, theta, c, s, tau;
83
84 for (size_t run = 0; run < 50; run++) {
85
86 sm = fabs(I[0][1]) + fabs(I[0][2]) + fabs(I[1][2]);
87
88 if (sm == 0.0)
89 break;
90
91 if (run < 4)
92 tresh = 0.2 * sm / 9.0;
93 else
94 tresh = 0.0;
95
96 for (size_t ip = 0; ip < 2; ip++) {
97 for (size_t iq = ip + 1; iq < 3; iq++) {
98 g = 100.0 * fabs(I[ip][iq]);
99 if (run > 4 && fabs(d[ip]) + g == fabs(d[ip]) &&
100 fabs(d[iq]) + g == fabs(d[iq]))
101 I[ip][iq] = 0.0;
102 else if (fabs(I[ip][iq]) > tresh) {
103 h = d[iq] - d[ip];
104 if (fabs(h) + g == fabs(h))
105 t = I[ip][iq] / h;
106 else {
107 theta = 0.5 * h / I[ip][iq];
108 t = 1.0 / (fabs(theta) + sqrt(1.0 + theta * theta));
109 if (theta < 0.0)
110 t = -t;
111 }
112
113 c = 1.0 / sqrt(1.0 + t * t);
114 s = t * c;
115 tau = s / (1.0 + c);
116 h = t * I[ip][iq];
117 f[ip] -= h;
118 f[iq] += h;
119 d[ip] -= h;
120 d[iq] += h;
121 I[ip][iq] = 0.0;
122
123 for (size_t j = 0; j <= ip - 1; j++) {
124 g = I[j][ip];
125 h = I[j][iq];
126 I[j][ip] = g - s * (h + g * tau);
127 I[j][iq] = h + s * (g - h * tau);
128 }
129
130 for (size_t j = ip + 1; j <= iq - 1; j++) {
131 g = I[ip][j];
132 h = I[j][iq];
133 I[ip][j] = g - s * (h + g * tau);
134 I[j][iq] = h + s * (g - h * tau);
135 }
136
137 for (size_t j = iq + 1; j < 3; j++) {
138 g = I[ip][j];
139 h = I[iq][j];
140 I[ip][j] = g - s * (h + g * tau);
141 I[iq][j] = h + s * (g - h * tau);
142 }
143
144 for (size_t j = 0; j < 3; j++) {
145 g = v[j][ip];
146 h = v[j][iq];
147 v[j][ip] = g - s * (h + g * tau);
148 v[j][iq] = h + s * (g - h * tau);
149 }
150 ++nrot;
151 }
152 }
153 }
154
155 for (size_t ip = 0; ip < 3; ip++) {
156 b[ip] += f[ip];
157 d[ip] = b[ip];
158 f[ip] = 0.0;
159 }
160 }
161
162 size_t k, j;
163
164 double p;
165
166 for (size_t i = 0; i < 3; i++) {
167 p = d[k = i];
168 for (j = i + 1; j < 3; j++) {
169 if (d[j] < p)
170 p = d[k = j];
171 }
172
173 if (k != i) {
174 d[k] = d[i];
175 d[i] = p;
176 for (j = 0; j < 3; j++) {
177 p = v[i][j];
178 v[i][j] = v[k][j];
179 v[k][j] = p;
180 }
181 }
182 }
183
184 double x, y, z;
185
186 for (auto &atom : _atoms) {
187
188 x = atom.getX() * v[0][0] + atom.getY() * v[0][1] + atom.getZ() * v[0][2];
189 y = atom.getX() * v[1][0] + atom.getY() * v[1][1] + atom.getZ() * v[1][2];
190 z = atom.getX() * v[2][0] + atom.getY() * v[2][1] + atom.getZ() * v[2][2];
191
192 atom.setX(x);
193 atom.setY(y);
194 atom.setZ(z);
195 }
196}
197
198std::vector<std::vector<int>> &PAHGeometry::getBonds() {
199
200 if (_bonds.size() > 0) {
201
202 return _bonds;
203 }
204
205 _bonds.reserve(64);
206
207 std::vector<int> ls;
208
209 ls.reserve(32);
210
211 for (const auto &atom1 : _atoms) {
212
213 int i = 0;
214
215 for (const auto &atom2 : _atoms) {
216
217 double d = sqrt(pow(atom1.getX() - atom2.getX(), 2) +
218 pow(atom1.getY() - atom2.getY(), 2));
219
220 if (d > 0 && d < 1.6) {
221
222 ls.push_back(i);
223 }
224 ++i;
225 }
226
227 _bonds.push_back(ls);
228
229 ls.clear();
230 }
231
232 for (auto &bond : _bonds) {
233
234 for (const auto &b : bond) {
235
236 _bonds[b].erase(_bonds[b].begin());
237 }
238 }
239
240 return _bonds;
241}

Since FY2019 the NASA Ames PAH IR Spectroscopic Database is being supported through a directed Work Package at NASA Ames titled: "Laboratory Astrophysics - The NASA Ames PAH IR Spectroscopic Database".
Since FY2023 the NASA Ames PAH IR Spectroscopic Database is being supported through the Laboratory Astrophysics Rd 2 directed Work Package at NASA Ames.
© Copyright 2021-2025, Christiaan Boersma