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