2 * This file is part of the GROMACS molecular simulation package.
4 * Copyright (c) 2009 Christoph Junghans, Brad Lambeth.
5 * Copyright (c) 2012, by the GROMACS development team, led by
6 * David van der Spoel, Berk Hess, Erik Lindahl, and including many
7 * others, as listed in the AUTHORS file in the top-level source
8 * directory and at http://www.gromacs.org.
10 * GROMACS is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU Lesser General Public License
12 * as published by the Free Software Foundation; either version 2.1
13 * of the License, or (at your option) any later version.
15 * GROMACS is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 * Lesser General Public License for more details.
20 * You should have received a copy of the GNU Lesser General Public
21 * License along with GROMACS; if not, see
22 * http://www.gnu.org/licenses, or write to the Free Software Foundation,
23 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
25 * If you want to redistribute modifications to GROMACS, please
26 * consider that scientific software is very special. Version
27 * control is crucial - bugs must be traceable. We will be happy to
28 * consider code for inclusion in the official distribution, but
29 * derived work must not be called official GROMACS. Details are found
30 * in the README & COPYING files - if they are missing, get the
31 * official version at http://www.gromacs.org.
33 * To help us fund GROMACS development, we humbly ask that you cite
34 * the research papers on the package. Check out http://www.gromacs.org.
40 #include "types/simple.h"
54 real l2 = adressr+adressw;
63 pbc_dx(pbc,(*ref),x,dx);
67 rvec_sub((*ref),x,dx);
73 /* default to explicit simulation */
76 /* constant value for weighting function = adressw */
77 return fr->adress_const_wf;
79 /* plane through center of ref, varies in x direction */
83 /* point at center of ref, assuming cubic geometry */
85 sqr_dl += dx[i]*dx[i];
89 /* default to explicit simulation */
95 /* molecule is coarse grained */
100 /* molecule is explicit */
101 else if (dl < adressr)
108 tmp=cos((dl-adressr)*M_PI/2/adressw);
114 update_adress_weights_com(FILE * fplog,
124 real nrcg,inv_ncg,mtot,inv_mtot;
128 real adressr,adressw;
134 int n_hyb, n_ex, n_cg;
140 adresstype = fr->adress_type;
141 adressr = fr->adress_ex_width;
142 adressw = fr->adress_hy_width;
143 massT = mdatoms->massT;
145 ref = &(fr->adress_refs);
148 /* Since this is center of mass AdResS, the vsite is not guaranteed
149 * to be on the same node as the constructing atoms. Therefore we
150 * loop over the charge groups, calculate their center of mass,
151 * then use this to calculate wf for each atom. This wastes vsite
152 * construction, but it's the only way to assure that the explicit
153 * atoms have the same wf as their vsite. */
156 fprintf(fplog,"Calculating center of mass for charge groups %d to %d\n",
159 cgindex = cgs->index;
161 /* Compute the center of mass for all charge groups */
162 for(icg=cg0; (icg<cg1); icg++)
169 wf[k0] = adress_weight(x[k0],adresstype,adressr,adressw,ref,pbc,fr);
170 if (wf[k0]==0){ n_cg++;}
171 else if (wf[k0]==1){ n_ex++;}
177 for(k=k0; (k<k1); k++)
186 for(k=k0; (k<k1); k++)
188 for(d=0; (d<DIM); d++)
190 ix[d] += x[k][d]*massT[k];
193 for(d=0; (d<DIM); d++)
198 /* Calculate the center of gravity if the charge group mtot=0 (only vsites) */
204 for(k=k0; (k<k1); k++)
206 for(d=0; (d<DIM); d++)
211 for(d=0; (d<DIM); d++)
217 /* Set wf of all atoms in charge group equal to wf of com */
218 wf[k0] = adress_weight(ix,adresstype,adressr,adressw,ref,pbc, fr);
220 if (wf[k0]==0){ n_cg++;}
221 else if (wf[k0]==1){ n_ex++;}
224 for(k=(k0+1); (k<k1); k++)
232 adress_set_kernel_flags(n_ex, n_hyb, n_cg, mdatoms);
236 void update_adress_weights_atom_per_atom(
246 real nrcg,inv_ncg,mtot,inv_mtot;
250 real adressr,adressw;
256 int n_hyb, n_ex, n_cg;
262 adresstype = fr->adress_type;
263 adressr = fr->adress_ex_width;
264 adressw = fr->adress_hy_width;
265 massT = mdatoms->massT;
267 ref = &(fr->adress_refs);
269 cgindex = cgs->index;
271 /* Weighting function is determined for each atom individually.
272 * This is an approximation
273 * as in the theory requires an interpolation based on the center of masses.
274 * Should be used with caution */
276 for (icg = cg0; (icg < cg1); icg++) {
278 k1 = cgindex[icg + 1];
281 for (k = (k0); (k < k1); k++) {
282 wf[k] = adress_weight(x[k], adresstype, adressr, adressw, ref, pbc, fr);
285 } else if (wf[k] == 1) {
293 adress_set_kernel_flags(n_ex, n_hyb, n_cg, mdatoms);
297 update_adress_weights_cog(t_iparams ip[],
304 int i,j,k,nr,nra,inc;
305 int ftype,adresstype;
306 t_iatom avsite,ai,aj,ak,al;
308 real adressr,adressw;
311 int n_hyb, n_ex, n_cg;
313 adresstype = fr->adress_type;
314 adressr = fr->adress_ex_width;
315 adressw = fr->adress_hy_width;
317 ref = &(fr->adress_refs);
325 /* Since this is center of geometry AdResS, we know the vsite
326 * is in the same charge group node as the constructing atoms.
327 * Loop over vsite types, calculate the weight of the vsite,
328 * then assign that weight to the constructing atoms. */
330 for(ftype=0; (ftype<F_NRE); ftype++)
332 if (interaction_function[ftype].flags & IF_VSITE)
334 nra = interaction_function[ftype].nratoms;
335 nr = ilist[ftype].nr;
336 ia = ilist[ftype].iatoms;
340 /* The vsite and first constructing atom */
343 wf[avsite] = adress_weight(x[avsite],adresstype,adressr,adressw,ref,pbc,fr);
348 } else if (wf[ai] == 1) {
354 /* Assign the vsite wf to rest of constructing atoms depending on type */
402 inc = 3*ip[ia[0]].vsiten.n;
403 for(j=3; j<inc; j+=3)
410 gmx_fatal(FARGS,"No such vsite type %d in %s, line %d",
411 ftype,__FILE__,__LINE__);
414 /* Increment loop variables */
421 adress_set_kernel_flags(n_ex, n_hyb, n_cg, mdatoms);
425 update_adress_weights_atom(int cg0,
436 real adressr,adressw;
441 adresstype = fr->adress_type;
442 adressr = fr->adress_ex_width;
443 adressw = fr->adress_hy_width;
444 massT = mdatoms->massT;
446 ref = &(fr->adress_refs);
447 cgindex = cgs->index;
449 /* Only use first atom in charge group.
450 * We still can't be sure that the vsite and constructing
451 * atoms are on the same processor, so we must calculate
452 * in the same way as com adress. */
454 for(icg=cg0; (icg<cg1); icg++)
458 wf[k0] = adress_weight(x[k0],adresstype,adressr,adressw,ref,pbc,fr);
460 /* Set wf of all atoms in charge group equal to wf of first atom in charge group*/
461 for(k=(k0+1); (k<k1); k++)
468 void adress_set_kernel_flags(int n_ex, int n_hyb, int n_cg, t_mdatoms * mdatoms){
470 /* With domain decomposition we can check weather a cpu calculates only
471 * coarse-grained or explicit interactions. If so we use standard gromacs kernels
472 * on this proc. See also nonbonded.c */
474 if (n_hyb ==0 && n_ex == 0){
475 /* all particles on this proc are coarse-grained, use standard gromacs kernels */
476 if (!mdatoms->purecg){
477 mdatoms->purecg = TRUE;
478 if (debug) fprintf (debug, "adress.c: pure cg kernels on this proc\n");
483 if (mdatoms->purecg){
484 /* now this processor has hybrid particles again, call the hybrid kernels */
485 mdatoms->purecg = FALSE;
489 if (n_hyb ==0 && n_cg == 0){
490 /* all particles on this proc are atomistic, use standard gromacs kernels */
491 if (!mdatoms->pureex){
492 mdatoms->pureex = TRUE;
493 if (debug) fprintf (debug, "adress.c: pure ex kernels on this proc\n");
498 if (mdatoms->pureex){
499 mdatoms->pureex = FALSE;
505 adress_thermo_force(int start,
514 int iatom,n0,nnn,nrcg, i;
516 real adressw, adressr;
518 unsigned short * ptype;
524 real w,wsq,wmin1,wmin1sq,wp,wt,rinv, sqr_dl, dl;
525 real eps,eps2,F,Geps,Heps2,Fp,dmu_dwp,dwp_dr,fscal;
527 adresstype = fr->adress_type;
528 adressw = fr->adress_hy_width;
529 adressr = fr->adress_ex_width;
530 cgindex = cgs->index;
531 ptype = mdatoms->ptype;
532 ref = &(fr->adress_refs);
535 for(iatom=start; (iatom<start+homenr); iatom++)
537 if (egp_coarsegrained(fr, mdatoms->cENER[iatom]))
539 if (ptype[iatom] == eptVSite)
542 /* is it hybrid or apply the thermodynamics force everywhere?*/
543 if ( mdatoms->tf_table_index[iatom] != NO_TF_TABLE)
545 if (fr->n_adress_tf_grps > 0 ){
546 /* multi component tf is on, select the right table */
547 ATFtab = fr->atf_tabs[mdatoms->tf_table_index[iatom]].data;
548 tabscale = fr->atf_tabs[mdatoms->tf_table_index[iatom]].scale;
551 /* just on component*/
552 ATFtab = fr->atf_tabs[DEFAULT_TF_TABLE].data;
553 tabscale = fr->atf_tabs[DEFAULT_TF_TABLE].scale;
559 pbc_dx(pbc,(*ref),x[iatom],dr);
563 rvec_sub((*ref),x[iatom],dr);
569 /* calculate distace to adress center again */
574 /* plane through center of ref, varies in x direction */
575 sqr_dl = dr[0]*dr[0];
576 rinv = gmx_invsqrt(dr[0]*dr[0]);
579 /* point at center of ref, assuming cubic geometry */
581 sqr_dl += dr[i]*dr[i];
583 rinv = gmx_invsqrt(sqr_dl);
586 /* This case should not happen */
591 /* table origin is adress center */
598 Geps = eps*ATFtab[nnn+2];
599 Heps2 = eps2*ATFtab[nnn+3];
601 F = (Fp+Geps+2.0*Heps2)*tabscale;
605 f[iatom][0] += fscal*dr[0];
606 if (adresstype != eAdressXSplit)
608 f[iatom][1] += fscal*dr[1];
609 f[iatom][2] += fscal*dr[2];
617 gmx_bool egp_explicit(t_forcerec * fr, int egp_nr)
619 return fr->adress_group_explicit[egp_nr];
622 gmx_bool egp_coarsegrained(t_forcerec * fr, int egp_nr)
624 return !fr->adress_group_explicit[egp_nr];