2 * This file is part of the GROMACS molecular simulation package.
4 * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
5 * Copyright (c) 2001-2004, The GROMACS development team.
6 * Copyright (c) 2013,2014, by the GROMACS development team, led by
7 * Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
8 * and including many others, as listed in the AUTHORS file in the
9 * top-level source directory and at http://www.gromacs.org.
11 * GROMACS is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU Lesser General Public License
13 * as published by the Free Software Foundation; either version 2.1
14 * of the License, or (at your option) any later version.
16 * GROMACS is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 * Lesser General Public License for more details.
21 * You should have received a copy of the GNU Lesser General Public
22 * License along with GROMACS; if not, see
23 * http://www.gnu.org/licenses, or write to the Free Software Foundation,
24 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
26 * If you want to redistribute modifications to GROMACS, please
27 * consider that scientific software is very special. Version
28 * control is crucial - bugs must be traceable. We will be happy to
29 * consider code for inclusion in the official distribution, but
30 * derived work must not be called official GROMACS. Details are found
31 * in the README & COPYING files - if they are missing, get the
32 * official version at http://www.gromacs.org.
34 * To help us fund GROMACS development, we humbly ask that you cite
35 * the research papers on the package. Check out http://www.gromacs.org.
44 #include "types/commrec.h"
45 #include "gromacs/math/vec.h"
46 #include "gromacs/utility/smalloc.h"
47 #include "gromacs/utility/fatalerror.h"
48 #include "gromacs/math/units.h"
52 #include "gromacs/utility/futil.h"
53 #include "gromacs/math/gmxcomplex.h"
61 t_complex
*tab_xy
, *tab_qxyz
;
66 /* TODO: fix thread-safety */
68 /* the other routines are in complex.h */
69 static t_complex
conjmul(t_complex a
, t_complex b
)
73 c
.re
= a
.re
*b
.re
+ a
.im
*b
.im
;
74 c
.im
= a
.im
*b
.re
- a
.re
*b
.im
;
82 static void tabulate_eir(int natom
, rvec x
[], int kmax
, cvec
**eir
, rvec lll
)
88 printf("Go away! kmax = %d\n", kmax
);
92 for (i
= 0; (i
< natom
); i
++)
94 for (m
= 0; (m
< 3); m
++)
100 for (m
= 0; (m
< 3); m
++)
102 eir
[1][i
][m
].re
= cos(x
[i
][m
]*lll
[m
]);
103 eir
[1][i
][m
].im
= sin(x
[i
][m
]*lll
[m
]);
105 for (j
= 2; (j
< kmax
); j
++)
107 for (m
= 0; (m
< 3); m
++)
109 eir
[j
][i
][m
] = cmul(eir
[j
-1][i
][m
], eir
[1][i
][m
]);
115 void init_ewald_tab(ewald_tab_t
*et
, const t_inputrec
*ir
, FILE *fp
)
122 fprintf(fp
, "Will do ordinary reciprocal space Ewald sum.\n");
125 (*et
)->nx
= ir
->nkx
+1;
126 (*et
)->ny
= ir
->nky
+1;
127 (*et
)->nz
= ir
->nkz
+1;
128 (*et
)->kmax
= max((*et
)->nx
, max((*et
)->ny
, (*et
)->nz
));
130 (*et
)->tab_xy
= NULL
;
131 (*et
)->tab_qxyz
= NULL
;
136 real
do_ewald(t_inputrec
*ir
,
138 real chargeA
[], real chargeB
[],
140 t_commrec
*cr
, int natoms
,
141 matrix lrvir
, real ewaldcoeff
,
142 real lambda
, real
*dvdlambda
,
145 real factor
= -1.0/(4*ewaldcoeff
*ewaldcoeff
);
146 real scaleRecip
= 4.0*M_PI
/(box
[XX
]*box
[YY
]*box
[ZZ
])*ONE_4PI_EPS0
/ir
->epsilon_r
; /* 1/(Vol*e0) */
147 real
*charge
, energy_AB
[2], energy
;
149 int lowiy
, lowiz
, ix
, iy
, iz
, n
, q
;
150 real tmp
, cs
, ss
, ak
, akv
, mx
, my
, mz
, m2
, scale
;
151 gmx_bool bFreeEnergy
;
157 gmx_fatal(FARGS
, "No parallel Ewald. Use PME instead.\n");
162 if (!et
->eir
) /* allocate if we need to */
164 snew(et
->eir
, et
->kmax
);
165 for (n
= 0; n
< et
->kmax
; n
++)
167 snew(et
->eir
[n
], natoms
);
169 snew(et
->tab_xy
, natoms
);
170 snew(et
->tab_qxyz
, natoms
);
173 bFreeEnergy
= (ir
->efep
!= efepNO
);
178 /* make tables for the structure factor parts */
179 tabulate_eir(natoms
, x
, et
->kmax
, et
->eir
, lll
);
181 for (q
= 0; q
< (bFreeEnergy
? 2 : 1); q
++)
191 scale
= 1.0 - lambda
;
201 for (ix
= 0; ix
< et
->nx
; ix
++)
204 for (iy
= lowiy
; iy
< et
->ny
; iy
++)
209 for (n
= 0; n
< natoms
; n
++)
211 et
->tab_xy
[n
] = cmul(et
->eir
[ix
][n
][XX
], et
->eir
[iy
][n
][YY
]);
216 for (n
= 0; n
< natoms
; n
++)
218 et
->tab_xy
[n
] = conjmul(et
->eir
[ix
][n
][XX
], et
->eir
[-iy
][n
][YY
]);
221 for (iz
= lowiz
; iz
< et
->nz
; iz
++)
224 m2
= mx
*mx
+my
*my
+mz
*mz
;
225 ak
= exp(m2
*factor
)/m2
;
226 akv
= 2.0*ak
*(1.0/m2
-factor
);
229 for (n
= 0; n
< natoms
; n
++)
231 et
->tab_qxyz
[n
] = rcmul(charge
[n
], cmul(et
->tab_xy
[n
],
232 et
->eir
[iz
][n
][ZZ
]));
237 for (n
= 0; n
< natoms
; n
++)
239 et
->tab_qxyz
[n
] = rcmul(charge
[n
], conjmul(et
->tab_xy
[n
],
240 et
->eir
[-iz
][n
][ZZ
]));
245 for (n
= 0; n
< natoms
; n
++)
247 cs
+= et
->tab_qxyz
[n
].re
;
248 ss
+= et
->tab_qxyz
[n
].im
;
250 energy_AB
[q
] += ak
*(cs
*cs
+ss
*ss
);
251 tmp
= scale
*akv
*(cs
*cs
+ss
*ss
);
252 lrvir
[XX
][XX
] -= tmp
*mx
*mx
;
253 lrvir
[XX
][YY
] -= tmp
*mx
*my
;
254 lrvir
[XX
][ZZ
] -= tmp
*mx
*mz
;
255 lrvir
[YY
][YY
] -= tmp
*my
*my
;
256 lrvir
[YY
][ZZ
] -= tmp
*my
*mz
;
257 lrvir
[ZZ
][ZZ
] -= tmp
*mz
*mz
;
258 for (n
= 0; n
< natoms
; n
++)
260 /*tmp=scale*ak*(cs*tab_qxyz[n].im-ss*tab_qxyz[n].re);*/
261 tmp
= scale
*ak
*(cs
*et
->tab_qxyz
[n
].im
-ss
*et
->tab_qxyz
[n
].re
);
262 f
[n
][XX
] += tmp
*mx
*2*scaleRecip
;
263 f
[n
][YY
] += tmp
*my
*2*scaleRecip
;
264 f
[n
][ZZ
] += tmp
*mz
*2*scaleRecip
;
280 energy
= energy_AB
[0];
284 energy
= (1.0 - lambda
)*energy_AB
[0] + lambda
*energy_AB
[1];
285 *dvdlambda
+= scaleRecip
*(energy_AB
[1] - energy_AB
[0]);
288 lrvir
[XX
][XX
] = -0.5*scaleRecip
*(lrvir
[XX
][XX
]+energy
);
289 lrvir
[XX
][YY
] = -0.5*scaleRecip
*(lrvir
[XX
][YY
]);
290 lrvir
[XX
][ZZ
] = -0.5*scaleRecip
*(lrvir
[XX
][ZZ
]);
291 lrvir
[YY
][YY
] = -0.5*scaleRecip
*(lrvir
[YY
][YY
]+energy
);
292 lrvir
[YY
][ZZ
] = -0.5*scaleRecip
*(lrvir
[YY
][ZZ
]);
293 lrvir
[ZZ
][ZZ
] = -0.5*scaleRecip
*(lrvir
[ZZ
][ZZ
]+energy
);
295 lrvir
[YY
][XX
] = lrvir
[XX
][YY
];
296 lrvir
[ZZ
][XX
] = lrvir
[XX
][ZZ
];
297 lrvir
[ZZ
][YY
] = lrvir
[YY
][ZZ
];
299 energy
*= scaleRecip
;