3 * This source code is part of
7 * GROningen MAchine for Chemical Simulations
9 * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
10 * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
11 * Copyright (c) 2001-2008, The GROMACS development team,
12 * check out http://www.gromacs.org for more information.
14 * This program is free software; you can redistribute it and/or
15 * modify it under the terms of the GNU General Public License
16 * as published by the Free Software Foundation; either version 2
17 * of the License, or (at your option) any later version.
19 * If you want to redistribute modifications, please consider that
20 * scientific software is very special. Version control is crucial -
21 * bugs must be traceable. We will be happy to consider code for
22 * inclusion in the official distribution, but derived work must not
23 * be called official GROMACS. Details are found in the README & COPYING
24 * files - if they are missing, get the official version at www.gromacs.org.
26 * To help us fund GROMACS development, we humbly ask that you cite
27 * the papers on the package - you can find them in the top README file.
29 * For more info, check our website at http://www.gromacs.org
32 * Gallium Rubidium Oxygen Manganese Argon Carbon Silicon
51 void make_wall_tables(FILE *fplog
,const output_env_t oenv
,
52 const t_inputrec
*ir
,const char *tabfn
,
53 const gmx_groups_t
*groups
,
56 int w
,negp_pp
,egp
,i
,j
;
61 negp_pp
= ir
->opts
.ngener
- ir
->nwall
;
62 nm_ind
= groups
->grps
[egcENER
].nm_ind
;
65 fprintf(fplog
,"Reading user tables for %d energy groups with %d walls\n",
69 snew(fr
->wall_tab
,ir
->nwall
);
70 for(w
=0; w
<ir
->nwall
; w
++) {
71 snew(fr
->wall_tab
[w
],negp_pp
);
72 for(egp
=0; egp
<negp_pp
; egp
++) {
73 /* If the energy group pair is excluded, we don't need a table */
74 if (!(fr
->egp_flags
[egp
*ir
->opts
.ngener
+negp_pp
+w
] & EGP_EXCL
)) {
75 tab
= &fr
->wall_tab
[w
][egp
];
76 sprintf(buf
,"%s",tabfn
);
77 sprintf(buf
+ strlen(tabfn
) - strlen(ftp2ext(efXVG
)) - 1,"_%s_%s.%s",
78 *groups
->grpname
[nm_ind
[egp
]],
79 *groups
->grpname
[nm_ind
[negp_pp
+w
]],
81 *tab
= make_tables(fplog
,oenv
,fr
,FALSE
,buf
,0,GMX_MAKETABLES_FORCEUSER
);
82 /* Since wall have no charge, we can compress the table */
83 for(i
=0; i
<=tab
->n
; i
++)
85 tab
->tab
[8*i
+j
] = tab
->tab
[12*i
+4+j
];
91 static void wall_error(int a
,rvec
*x
,real r
)
94 "An atom is beyond the wall: coordinates %f %f %f, distance %f\n"
95 "You might want to use the mdp option wall_r_linpot",
96 x
[a
][XX
],x
[a
][YY
],x
[a
][ZZ
],r
);
99 real
do_walls(t_inputrec
*ir
,t_forcerec
*fr
,matrix box
,t_mdatoms
*md
,
100 rvec x
[],rvec f
[],real lambda
,real Vlj
[],t_nrnb
*nrnb
)
103 int ntw
[2],at
,ntype
,ngid
,ggid
,*egp_flags
,*type
;
104 real
*nbfp
,lamfac
,fac_d
[2],fac_r
[2],Cd
,Cr
,Vtot
,Fwall
[2];
105 real wall_z
[2],r
,mr
,r1
,r2
,r4
,Vd
,Vr
,V
,Fd
,Fr
,F
,dvdlambda
;
108 real tabscale
,*VFtab
,rt
,eps
,eps2
,Yt
,Ft
,Geps
,Heps
,Heps2
,Fp
,VV
,FF
;
109 unsigned short *gid
=md
->cENER
;
113 ngid
= ir
->opts
.ngener
;
116 egp_flags
= fr
->egp_flags
;
118 for(w
=0; w
<nwall
; w
++) {
119 ntw
[w
] = 2*ntype
*ir
->wall_atomtype
[w
];
120 if (ir
->wall_type
== ewt93
) {
121 fac_d
[w
] = ir
->wall_density
[w
]*M_PI
/6;
122 fac_r
[w
] = ir
->wall_density
[w
]*M_PI
/45;
123 } else if (ir
->wall_type
== ewt104
) {
124 fac_d
[w
] = ir
->wall_density
[w
]*M_PI
/2;
125 fac_r
[w
] = ir
->wall_density
[w
]*M_PI
/5;
130 wall_z
[1] = box
[ZZ
][ZZ
];
135 for(lam
=0; lam
<(md
->nPerturbed
? 2 : 1); lam
++) {
136 if (md
->nPerturbed
) {
148 for(i
=md
->start
; i
<md
->start
+md
->homenr
; i
++) {
149 for(w
=0; w
<nwall
; w
++) {
150 /* The wall energy groups are always at the end of the list */
151 ggid
= gid
[i
]*ngid
+ ngid
- nwall
+ w
;
153 Cd
= nbfp
[ntw
[w
]+2*at
];
154 Cr
= nbfp
[ntw
[w
]+2*at
+1];
155 if (!((Cd
==0 && Cr
==0) || egp_flags
[ggid
] & EGP_EXCL
)) {
159 r
= wall_z
[1] - x
[i
][ZZ
];
161 if (r
< ir
->wall_r_linpot
) {
162 mr
= ir
->wall_r_linpot
- r
;
163 r
= ir
->wall_r_linpot
;
167 if (ir
->wall_type
== ewtTABLE
) {
170 tab
= &(fr
->wall_tab
[w
][gid
[i
]]);
171 tabscale
= tab
->scale
;
177 /* Beyond the table range, set V and F to zero */
187 Geps
= VFtab
[nnn
+2]*eps
;
188 Heps2
= VFtab
[nnn
+3]*eps2
;
189 Fp
= Ft
+ Geps
+ Heps2
;
191 FF
= Fp
+ Geps
+ 2.0*Heps2
;
198 Geps
= VFtab
[nnn
+2]*eps
;
199 Heps2
= VFtab
[nnn
+3]*eps2
;
200 Fp
= Ft
+ Geps
+ Heps2
;
202 FF
= Fp
+ Geps
+ 2.0*Heps2
;
206 F
= -lamfac
*(Fd
+ Fr
)*tabscale
;
208 } else if (ir
->wall_type
== ewt93
) {
214 Vd
= fac_d
[w
]*Cd
*r2
*r1
;
215 Vr
= fac_r
[w
]*Cr
*r4
*r4
*r1
;
217 F
= lamfac
*(9*Vr
- 3*Vd
)*r1
;
225 Vr
= fac_r
[w
]*Cr
*r4
*r4
*r2
;
227 F
= lamfac
*(10*Vr
- 4*Vd
)*r1
;
235 Vlj
[ggid
] += lamfac
*V
;
238 /* Because of the single sum virial calculation we need to add
239 * the full virial contribution of the walls.
240 * Since the force only has a z-component, there is only
241 * a contribution to the z component of the virial tensor.
242 * We could also determine the virial contribution directly,
243 * which would be cheaper here, but that would require extra
244 * communication for f_novirsum for with virtual sites in parallel.
246 xf_z
[XX
] -= x
[i
][XX
]*F
;
247 xf_z
[YY
] -= x
[i
][YY
]*F
;
248 xf_z
[ZZ
] -= wall_z
[w
]*F
;
253 dvdlambda
+= (lam
==0 ? -1 : 1)*Vtot
;
255 inc_nrnb(nrnb
,eNR_WALLS
,md
->homenr
);
258 for(i
=0; i
<DIM
; i
++) {
259 fr
->vir_wall_z
[i
] = -0.5*xf_z
[i
];