4 * This source code is part of
8 * GROningen MAchine for Chemical Simulations
12 * Copyright (c) 1991-1999
13 * BIOSON Research Institute, Dept. of Biophysical Chemistry
14 * University of Groningen, The Netherlands
17 * GROMACS: A message-passing parallel molecular dynamics implementation
18 * H.J.C. Berendsen, D. van der Spoel and R. van Drunen
19 * Comp. Phys. Comm. 91, 43-56 (1995)
21 * Also check out our WWW page:
22 * http://md.chem.rug.nl/~gmx
27 * GRowing Old MAkes el Chrono Sweat
29 static char *SRCID_dummies_c
= "$Id$";
40 static void constr_dum2(rvec xi
,rvec xj
,rvec x
,real a
)
47 x
[XX
]=b
*xi
[XX
]+a
*xj
[XX
];
48 x
[YY
]=b
*xi
[YY
]+a
*xj
[YY
];
49 x
[ZZ
]=b
*xi
[ZZ
]+a
*xj
[ZZ
];
55 static void constr_dum3(rvec xi
,rvec xj
,rvec xk
,rvec x
,real a
,real b
)
62 x
[XX
] = c
*xi
[XX
] + a
*xj
[XX
] + b
*xk
[XX
];
63 x
[YY
] = c
*xi
[YY
] + a
*xj
[YY
] + b
*xk
[YY
];
64 x
[ZZ
] = c
*xi
[ZZ
] + a
*xj
[ZZ
] + b
*xk
[ZZ
];
70 static void constr_dum3FD(rvec xi
,rvec xj
,rvec xk
,rvec x
,real a
,real b
)
79 /* temp goes from i to a point on the line jk */
80 temp
[XX
] = xij
[XX
] + a
*xjk
[XX
];
81 temp
[YY
] = xij
[YY
] + a
*xjk
[YY
];
82 temp
[ZZ
] = xij
[ZZ
] + a
*xjk
[ZZ
];
85 c
=b
*invsqrt(iprod(temp
,temp
));
88 x
[XX
] = xi
[XX
] + c
*temp
[XX
];
89 x
[YY
] = xi
[YY
] + c
*temp
[YY
];
90 x
[ZZ
] = xi
[ZZ
] + c
*temp
[ZZ
];
96 static void constr_dum3FAD(rvec xi
,rvec xj
,rvec xk
,rvec x
,real a
,real b
)
105 invdij
= invsqrt(iprod(xij
,xij
));
106 c1
= invdij
* invdij
* iprod(xij
,xjk
);
107 xp
[XX
] = xjk
[XX
] - c1
*xij
[XX
];
108 xp
[YY
] = xjk
[YY
] - c1
*xij
[YY
];
109 xp
[ZZ
] = xjk
[ZZ
] - c1
*xij
[ZZ
];
111 b1
= b
*invsqrt(iprod(xp
,xp
));
114 x
[XX
] = xi
[XX
] + a1
*xij
[XX
] + b1
*xp
[XX
];
115 x
[YY
] = xi
[YY
] + a1
*xij
[YY
] + b1
*xp
[YY
];
116 x
[ZZ
] = xi
[ZZ
] + a1
*xij
[ZZ
] + b1
*xp
[ZZ
];
119 /* TOTAL: 63 flops */
122 static void constr_dum3OUT(rvec xi
,rvec xj
,rvec xk
,rvec x
,real a
,real b
,real c
)
131 x
[XX
] = xi
[XX
] + a
*xij
[XX
] + b
*xik
[XX
] + c
*temp
[XX
];
132 x
[YY
] = xi
[YY
] + a
*xij
[YY
] + b
*xik
[YY
] + c
*temp
[YY
];
133 x
[ZZ
] = xi
[ZZ
] + a
*xij
[ZZ
] + b
*xik
[ZZ
] + c
*temp
[ZZ
];
136 /* TOTAL: 33 flops */
139 static void constr_dum4FD(rvec xi
,rvec xj
,rvec xk
,rvec xl
,rvec x
,
140 real a
,real b
,real c
)
142 rvec xij
,xjk
,xjl
,temp
;
150 /* temp goes from i to a point on the plane jkl */
151 temp
[XX
] = xij
[XX
] + a
*xjk
[XX
] + b
*xjl
[XX
];
152 temp
[YY
] = xij
[YY
] + a
*xjk
[YY
] + b
*xjl
[YY
];
153 temp
[ZZ
] = xij
[ZZ
] + a
*xjk
[ZZ
] + b
*xjl
[ZZ
];
156 d
=c
*invsqrt(iprod(temp
,temp
));
159 x
[XX
] = xi
[XX
] + d
*temp
[XX
];
160 x
[YY
] = xi
[YY
] + d
*temp
[YY
];
161 x
[ZZ
] = xi
[ZZ
] + d
*temp
[ZZ
];
164 /* TOTAL: 43 flops */
167 void construct_dummies(FILE *log
,rvec x
[],t_nrnb
*nrnb
,real dt
,
168 rvec
*v
,t_idef
*idef
)
171 real a1
,b1
,c1
,inv_dt
;
172 int i
,nra
,nrd
,tp
,ftype
;
173 t_iatom adum
,ai
,aj
,ak
,al
;
183 for(ftype
=0; (ftype
<F_NRE
); ftype
++) {
184 if (interaction_function
[ftype
].flags
& IF_DUMMY
) {
185 nra
= interaction_function
[ftype
].nratoms
;
186 nrd
= idef
->il
[ftype
].nr
;
187 ia
= idef
->il
[ftype
].iatoms
;
189 for(i
=0; (i
<nrd
); ) {
191 assert(ftype
== idef
->functype
[tp
]);
193 /* The dummy and constructing atoms */
198 /* Constants for constructing dummies */
201 /* Copy the old position */
202 copy_rvec(x
[adum
],xd
);
204 /* Construct the dummy depending on type */
207 constr_dum2(x
[ai
],x
[aj
],x
[adum
],a1
);
212 constr_dum3(x
[ai
],x
[aj
],x
[ak
],x
[adum
],a1
,b1
);
217 constr_dum3FD(x
[ai
],x
[aj
],x
[ak
],x
[adum
],a1
,b1
);
222 constr_dum3FAD(x
[ai
],x
[aj
],x
[ak
],x
[adum
],a1
,b1
);
228 constr_dum3OUT(x
[ai
],x
[aj
],x
[ak
],x
[adum
],a1
,b1
,c1
);
235 constr_dum4FD(x
[ai
],x
[aj
],x
[ak
],x
[al
],x
[adum
],a1
,b1
,c1
);
238 fatal_error(0,"No such dummy type %d in %s, line %d",
239 ftype
,__FILE__
,__LINE__
);
242 /* Calculate velocity of dummy... */
243 rvec_sub(x
[adum
],xd
,vv
);
244 svmul(inv_dt
,vv
,v
[adum
]);
246 /* Increment loop variables */
254 static void spread_dum2(rvec fi
,rvec fj
,rvec f
,real a
)
275 static void spread_dum3(rvec fi
,rvec fj
,rvec fk
,rvec f
,real a
,real b
)
296 /* TOTAL: 11 flops */
299 static void spread_dum3FD(rvec xi
,rvec xj
,rvec xk
,
300 rvec fi
,rvec fj
,rvec fk
,rvec f
,real a
,real b
)
302 real fx
,fy
,fz
,c
,invl
,fproj
,a1
;
303 rvec xij
,xjk
,xix
,temp
;
309 /* xix goes from i to point x on the line jk */
310 xix
[XX
]=xij
[XX
]+a
*xjk
[XX
];
311 xix
[YY
]=xij
[YY
]+a
*xjk
[YY
];
312 xix
[ZZ
]=xij
[ZZ
]+a
*xjk
[ZZ
];
315 invl
=invsqrt(iprod(xix
,xix
));
319 fproj
=iprod(xix
,f
)*invl
*invl
; /* = (xix . f)/(xix . xix) */
325 temp
[XX
]=c
*(fx
-fproj
*xix
[XX
]);
326 temp
[YY
]=c
*(fy
-fproj
*xix
[YY
]);
327 temp
[ZZ
]=c
*(fz
-fproj
*xix
[ZZ
]);
330 /* c is already calculated in constr_dum3FD
331 storing c somewhere will save 26 flops! */
345 /* TOTAL: 61 flops */
348 static void spread_dum3FAD(rvec xi
,rvec xj
,rvec xk
,
349 rvec fi
,rvec fj
,rvec fk
,rvec f
,real a
,real b
)
351 rvec xij
,xjk
,xperp
,Fpij
,Fppp
,f1
,f2
,f3
;
352 real a1
,b1
,c1
,c2
,invdij
,invdij2
,invdp
,fproj
;
359 invdij
= invsqrt(iprod(xij
,xij
));
360 invdij2
= invdij
* invdij
;
361 c1
= iprod(xij
,xjk
) * invdij2
;
362 xperp
[XX
] = xjk
[XX
] - c1
*xij
[XX
];
363 xperp
[YY
] = xjk
[YY
] - c1
*xij
[YY
];
364 xperp
[ZZ
] = xjk
[ZZ
] - c1
*xij
[ZZ
];
365 /* xperp in plane ijk, perp. to ij */
366 invdp
= invsqrt(iprod(xperp
,xperp
));
371 /* a1, b1 and c1 are already calculated in constr_dum3FAD
372 storing them somewhere will save 45 flops! */
374 fproj
=iprod(xij
,f
)*invdij2
;
375 svmul(fproj
, xij
, Fpij
); /* proj. f on xij */
376 svmul(iprod(xperp
,f
)*invdp
*invdp
,xperp
,Fppp
); /* proj. f on xperp */
377 svmul(b1
*fproj
, xperp
,f3
);
380 rvec_sub(f
,Fpij
,f1
); /* f1 = f - Fpij */
381 rvec_sub(f1
,Fppp
,f2
); /* f2 = f - Fpij - Fppp */
382 for (d
=0; (d
<DIM
); d
++) {
389 fi
[XX
] += f
[XX
] - f1
[XX
] + c1
*f2
[XX
] + f3
[XX
];
390 fi
[YY
] += f
[YY
] - f1
[YY
] + c1
*f2
[YY
] + f3
[YY
];
391 fi
[ZZ
] += f
[ZZ
] - f1
[ZZ
] + c1
*f2
[ZZ
] + f3
[ZZ
];
392 fj
[XX
] += f1
[XX
] - c2
*f2
[XX
] - f3
[XX
];
393 fj
[YY
] += f1
[YY
] - c2
*f2
[YY
] - f3
[YY
];
394 fj
[ZZ
] += f1
[ZZ
] - c2
*f2
[ZZ
] - f3
[ZZ
];
400 /* TOTAL: 113 flops */
403 static void spread_dum3OUT(rvec xi
,rvec xj
,rvec xk
,
404 rvec fi
,rvec fj
,rvec fk
,rvec f
,real a
,real b
,real c
)
406 rvec xij
,xik
,ffj
,ffk
;
419 ffj
[XX
] = a
*f
[XX
] - xik
[ZZ
]*cfy
+ xik
[YY
]*cfz
;
420 ffj
[YY
] = xik
[ZZ
]*cfx
+ a
*f
[YY
] - xik
[XX
]*cfz
;
421 ffj
[ZZ
] = -xik
[YY
]*cfx
+ xik
[XX
]*cfy
+ a
*f
[ZZ
];
423 ffk
[XX
] = b
*f
[XX
] + xij
[ZZ
]*cfy
- xij
[YY
]*cfz
;
424 ffk
[YY
] = -xij
[ZZ
]*cfx
+ b
*f
[YY
] + xij
[XX
]*cfz
;
425 ffk
[ZZ
] = xij
[YY
]*cfx
- xij
[XX
]*cfy
+ b
*f
[ZZ
];
428 for(m
=0; (m
<DIM
); m
++) {
429 fi
[m
]+=f
[m
]-ffj
[m
]-ffk
[m
];
435 /* TOTAL: 54 flops */
438 static void spread_dum4FD(rvec xi
,rvec xj
,rvec xk
,rvec xl
,
439 rvec fi
,rvec fj
,rvec fk
,rvec fl
,rvec f
,
440 real a
,real b
,real c
)
442 real fx
,fy
,fz
,d
,invl
,fproj
,a1
;
443 rvec xij
,xjk
,xjl
,xix
,temp
;
450 /* xix goes from i to point x on the plane jkl */
451 xix
[XX
]=xij
[XX
]+a
*xjk
[XX
]+b
*xjl
[XX
];
452 xix
[YY
]=xij
[YY
]+a
*xjk
[YY
]+b
*xjl
[YY
];
453 xix
[ZZ
]=xij
[ZZ
]+a
*xjk
[ZZ
]+b
*xjl
[ZZ
];
456 invl
=invsqrt(iprod(xix
,xix
));
460 fproj
=iprod(xix
,f
)*invl
*invl
; /* = (xix . f)/(xix . xix) */
466 temp
[XX
]=d
*(fx
-fproj
*xix
[XX
]);
467 temp
[YY
]=d
*(fy
-fproj
*xix
[YY
]);
468 temp
[ZZ
]=d
*(fz
-fproj
*xix
[ZZ
]);
471 /* c is already calculated in constr_dum3FD
472 storing c somewhere will save 35 flops! */
489 /* TOTAL: 77 flops */
492 void spread_dummy_f(FILE *log
,rvec x
[],rvec f
[],t_nrnb
*nrnb
,t_idef
*idef
)
495 int i
,nra
,nrd
,tp
,ftype
;
496 int nd2
,nd3
,nd3FD
,nd3FAD
,nd3OUT
,nd4FD
;
497 t_iatom adum
,ai
,aj
,ak
,al
;
509 /* this loop goes backwards to be able to build *
510 * higher type dummies from lower types */
511 for(ftype
=F_NRE
-1; (ftype
>=0); ftype
--) {
512 if (interaction_function
[ftype
].flags
& IF_DUMMY
) {
513 nra
= interaction_function
[ftype
].nratoms
;
514 nrd
= idef
->il
[ftype
].nr
;
515 ia
= idef
->il
[ftype
].iatoms
;
517 for(i
=0; (i
<nrd
); ) {
519 assert(ftype
== idef
->functype
[tp
]);
521 /* The dummy and constructing atoms */
526 /* Constants for constructing */
529 /* Construct the dummy depending on type */
532 spread_dum2(f
[ai
],f
[aj
],f
[adum
],a1
);
538 spread_dum3(f
[ai
],f
[aj
],f
[ak
],f
[adum
],a1
,b1
);
544 spread_dum3FD(x
[ai
],x
[aj
],x
[ak
],f
[ai
],f
[aj
],f
[ak
],f
[adum
],a1
,b1
);
550 spread_dum3FAD(x
[ai
],x
[aj
],x
[ak
],f
[ai
],f
[aj
],f
[ak
],f
[adum
],a1
,b1
);
557 spread_dum3OUT(x
[ai
],x
[aj
],x
[ak
],f
[ai
],f
[aj
],f
[ak
],f
[adum
],a1
,b1
,c1
);
565 spread_dum4FD(x
[ai
],x
[aj
],x
[ak
],x
[al
],
566 f
[ai
],f
[aj
],f
[ak
],f
[al
],f
[adum
],a1
,b1
,c1
);
570 fatal_error(0,"No such dummy type %d in %s, line %d",
571 ftype
,__FILE__
,__LINE__
);
575 /* Increment loop variables */
581 inc_nrnb(nrnb
,eNR_DUM2
, nd2
);
582 inc_nrnb(nrnb
,eNR_DUM3
, nd3
);
583 inc_nrnb(nrnb
,eNR_DUM3FD
, nd3FD
);
584 inc_nrnb(nrnb
,eNR_DUM3FAD
,nd3FAD
);
585 inc_nrnb(nrnb
,eNR_DUM3OUT
,nd3OUT
);
586 inc_nrnb(nrnb
,eNR_DUM4FD
, nd4FD
);