1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38 package ffx.algorithms.dynamics.integrators;
39
40 import static java.lang.Math.abs;
41
42 import ffx.crystal.Crystal;
43 import ffx.potential.MolecularAssembly;
44 import ffx.potential.bonded.Atom;
45 import java.util.logging.Level;
46 import java.util.logging.Logger;
47
48
49
50
51
52
53 public class Rattle {
54
55
56
57
58
59
60
61 private static final Logger logger = Logger.getLogger(Rattle.class.getName());
62
63 private MolecularAssembly molAss;
64 private double[] xold;
65 private double[] yold;
66 private double[] zold;
67 private double[][] vel;
68 private final int nVariables;
69 private final Crystal cryst = molAss.getCrystal();
70
71
72
73
74
75
76
77
78
79
80 public Rattle(int nVariables, MolecularAssembly molAss, double[] v) {
81
82 int i, j = 0;
83 Atom[] tempArray = molAss.getAtomArray();
84 int size = tempArray.length;
85 this.nVariables = nVariables;
86
87
88 for (i = 0; i < v.length; i = i + 3) {
89 this.vel[j][0] = v[i];
90 this.vel[j][1] = v[i + 1];
91 this.vel[j][2] = v[i + 2];
92 j++;
93 }
94
95
96 for (i = 0; i < size; i++) {
97 this.xold[i] = tempArray[i].getX();
98 this.yold[i] = tempArray[i].getY();
99 this.zold[i] = tempArray[i].getZ();
100 }
101 }
102
103
104
105
106
107
108
109
110
111 public void postForce1(MolecularAssembly molAss, double dt) {
112 int i, n;
113 int niter, maxiter;
114 int ia, ib;
115 int nrat;
116 double eps, sor;
117 double rateps;
118 double xr, yr, zr;
119 double xo, yo, zo;
120 double dot, rma, rmb;
121 double dist2;
122 double delta;
123 double term;
124 double xterm, yterm, zterm;
125 double[] xyzr = new double[3];
126 double[] xyzo = new double[3];
127 boolean done;
128
129 n = molAss.getAtomArray().length;
130 nrat = molAss.getBondList().size();
131
132
133 boolean[] moved = new boolean[n];
134 boolean[] update = new boolean[n];
135 Atom[] atomArray = new Atom[n];
136 double[] x = new double[n];
137 double[] y = new double[n];
138 double[] z = new double[n];
139 double[] krat = new double[nrat];
140 int[][] bondAtmNum = new int[nrat][2];
141
142
143 for (i = 0; i < nrat; i++) {
144 bondAtmNum[i][0] = molAss.getBond(i).getAtomArray()[0].getIndex();
145 bondAtmNum[i][1] = molAss.getBond(i).getAtomArray()[1].getIndex();
146 krat[i] = molAss.getBond(i).bondType.distance;
147 }
148
149
150 for (i = 0; i < n; i++) {
151 moved[i] = atomArray[i].isActive();
152
153 update[i] = false;
154 }
155
156
157 maxiter = 500;
158 sor = 1.250;
159 rateps = 0.0000010;
160 eps = rateps;
161
162
163 niter = 0;
164 done = false;
165
166 while ((!done) && (niter < maxiter)) {
167 niter++;
168 done = true;
169
170 for (i = 0; i < nrat; i++) {
171 ia = bondAtmNum[i][0];
172 ib = bondAtmNum[i][1];
173 if (moved[ia] || moved[ib]) {
174 xr = x[ib] - x[ia];
175 yr = y[ib] - y[ia];
176 zr = z[ib] - z[ia];
177 xyzr[0] = xr;
178 xyzr[1] = yr;
179 xyzr[2] = zr;
180
181 dist2 = cryst.image(xyzr);
182
183
184 xr = xyzr[0];
185 yr = xyzr[1];
186 zr = xyzr[2];
187 delta = (krat[i] * krat[i]) - dist2;
188
189 if (abs(delta) > eps) {
190 done = false;
191 update[ia] = true;
192 update[ib] = true;
193
194 xo = this.xold[ib] - this.xold[ia];
195 yo = this.yold[ib] - this.yold[ia];
196 zo = this.zold[ib] - this.zold[ia];
197 xyzo[0] = xo;
198 xyzo[1] = yo;
199 xyzo[2] = zo;
200
201 cryst.image(xyzo);
202 xo = xyzo[0];
203 yo = xyzo[1];
204 zo = xyzo[2];
205
206 dot = (xr * xo) + (yr * yo) + (zr * zo);
207 rma = 1.00 / atomArray[ia].getMass();
208 rmb = 1.00 / atomArray[ib].getMass();
209 term = sor * delta / (2 * (rma + rmb) * dot);
210 xterm = xo * term;
211 yterm = yo * term;
212 zterm = zo * term;
213
214 x[ia] = x[ia] - (xterm * rma);
215 y[ia] = y[ia] - (yterm * rma);
216 z[ia] = z[ia] - (zterm * rma);
217 x[ib] = x[ib] - (xterm * rmb);
218 y[ib] = y[ib] - (yterm * rmb);
219 z[ib] = z[ib] - (zterm * rmb);
220 rma = rma / dt;
221 rmb = rmb / dt;
222
223 this.vel[ia][0] = this.vel[ia][0] - (xterm * rma);
224 this.vel[ia][1] = this.vel[ia][1] - (yterm * rma);
225 this.vel[ia][2] = this.vel[ia][2] - (zterm * rma);
226 this.vel[ib][0] = this.vel[ib][0] - (xterm * rmb);
227 this.vel[ib][1] = this.vel[ib][1] - (yterm * rmb);
228 this.vel[ib][2] = this.vel[ib][2] - (zterm * rmb);
229 }
230 }
231 }
232
233 for (i = 0; i < n; i++) {
234 moved[i] = update[i];
235 update[i] = false;
236 }
237 }
238
239
240 if (niter == maxiter) {
241 logger.log(Level.SEVERE, "Rattle: Distance constraints not satisfied.\n");
242 }
243 }
244
245
246
247
248
249
250 public void postForce2(double dt) {
251 int i, n;
252 int ia, ib;
253 int niter, maxiter;
254 int nrat;
255 double eps, sor;
256 double xr, yr, zr;
257 double xv, yv, zv;
258 double dot, rma, rmb;
259 double term;
260 double xterm, yterm, zterm;
261 boolean done;
262 double[] xyzr = new double[3];
263
264
265 n = molAss.getAtomArray().length;
266 boolean[] moved = new boolean[n];
267 boolean[] update = new boolean[n];
268 boolean[] ratimage =
269 new boolean
270 [molAss.getBondList().size()];
271 Atom[] atomArray = new Atom[n];
272 int[][] bondAtmNum = new int[molAss.getBondList().size()][2];
273 double[] krat = new double[molAss.getBondList().size()];
274 double[] x = new double[molAss.getAtomArray().length];
275 double[] y = new double[molAss.getAtomArray().length];
276 double[] z = new double[molAss.getAtomArray().length];
277
278
279 n = molAss.getAtomArray().length;
280 for (i = 0; i < n; i++) {
281 x[i] = atomArray[i].getX();
282 y[i] = atomArray[i].getY();
283 z[i] = atomArray[i].getZ();
284 }
285
286
287 nrat = molAss.getBondList().size();
288 for (i = 0; i < nrat; i++) {
289 bondAtmNum[i][0] = molAss.getBond(i).getAtomArray()[0].getIndex();
290 bondAtmNum[i][1] = molAss.getBond(i).getAtomArray()[1].getIndex();
291 krat[i] = molAss.getBond(i).bondType.distance;
292 }
293
294
295 for (i = 0; i < nrat; i++) {
296 ratimage[i] = true;
297 }
298
299
300 atomArray = molAss.getAtomArray();
301 for (i = 0; i < n; i++) {
302 moved[i] = atomArray[i].isActive();
303
304 update[i] = false;
305 }
306
307
308 maxiter = 500;
309 niter = 0;
310 done = false;
311 sor = 1.25;
312 eps = 0.000001 / dt;
313
314
315 while ((!done) && (niter < maxiter)) {
316 niter++;
317 done = true;
318 for (i = 1; i < nrat; i++) {
319 ia = bondAtmNum[i][0];
320 ib = bondAtmNum[i][1];
321
322 if (moved[ia] || moved[ib]) {
323 xr = x[ib] - x[ia];
324 yr = y[ib] - y[ia];
325 zr = z[ib] - z[ia];
326
327 xyzr[0] = xr;
328 xyzr[1] = yr;
329 xyzr[2] = zr;
330
331 cryst.image(xyzr);
332 xr = xyzr[0];
333 yr = xyzr[1];
334 zr = xyzr[2];
335
336 xv = this.vel[ib][0] - this.vel[ia][0];
337 yv = this.vel[ib][1] - this.vel[ia][1];
338 zv = this.vel[ib][2] - this.vel[ia][2];
339 dot = (xr * xv) + (yr * yv) + (zr * zv);
340 rma = 1.00 / atomArray[ia].getMass();
341 rmb = 1.00 / atomArray[ib].getMass();
342 term = -dot / ((rma + rmb) * (krat[i] * krat[i]));
343
344 if (abs(term) > eps) {
345 done = false;
346 update[ia] = true;
347 update[ib] = true;
348 term = sor * term;
349 xterm = xr * term;
350 yterm = yr * term;
351 zterm = zr * term;
352 this.vel[ia][0] = this.vel[ia][0] - (xterm * rma);
353 this.vel[ia][1] = this.vel[ia][1] - (yterm * rma);
354 this.vel[ia][2] = this.vel[ia][2] - (zterm * rma);
355 this.vel[ib][0] = this.vel[ib][0] + (xterm * rma);
356 this.vel[ib][1] = this.vel[ib][1] + (yterm * rma);
357 this.vel[ib][2] = this.vel[ib][2] + (zterm * rma);
358 }
359 }
360 }
361 for (i = 0; i < n; i++) {
362 moved[i] = update[i];
363 update[i] = false;
364 }
365 }
366
367
368 if (niter == maxiter) {
369 logger.log(Level.SEVERE, "Rattle: Velocity constraints not satisfied.\n");
370 }
371 }
372 }