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) 2010,2014,2015,2016,2019,2021, 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.
43 #include "gromacs/gmxpreprocess/notset.h"
44 #include "gromacs/math/functions.h"
45 #include "gromacs/math/units.h"
46 #include "gromacs/math/utilities.h"
47 #include "gromacs/math/vec.h"
48 #include "gromacs/utility/fatalerror.h"
59 /* The source code in this file should be thread-safe.
60 Please keep it that way. */
62 static void gen_waterhydrogen(int nh, rvec xa[], rvec xh[], int* l)
67 const dvec matrix1[6] = { { AA, BB, CC }, { AA, BB, CC }, { AA, BB, CC },
68 { -AA, BB, CC }, { -AA, BB, CC }, { BB, AA, -CC } };
69 const dvec matrix2[6] = { { -AA, BB, CC }, { BB, AA, -CC }, { BB, -AA, -CC },
70 { BB, AA, -CC }, { BB, -AA, -CC }, { BB, -AA, -CC } };
76 /* This was copied from Gromos */
77 for (m = 0; (m < DIM); m++)
79 xH1[m] = xAI[m] + matrix1[*l][m];
80 xH2[m] = xAI[m] + matrix2[*l][m];
94 void calc_h_pos(int nht, rvec xa[], rvec xh[], int* l)
96 #define alfaH (acos(-1 / 3.0)) /* 109.47 degrees */
97 #define alfaHpl (2 * M_PI / 3) /* 120 degrees */
100 #define alfaCOM (gmx::c_deg2Rad * 117)
101 #define alfaCO (gmx::c_deg2Rad * 121)
102 #define alfaCOA (gmx::c_deg2Rad * 115)
109 real s6, rij, ra, rb, xd;
112 s6 = 0.5 * std::sqrt(3.e0);
114 /* common work for constructing one, two or three dihedral hydrogens */
123 for (d = 0; (d < DIM); d++)
126 sij[d] = xAI[d] - xd;
128 rij += gmx::square(sij[d]);
130 rij = std::sqrt(rij);
131 sa[XX] = sij[YY] * sb[ZZ] - sij[ZZ] * sb[YY];
132 sa[YY] = sij[ZZ] * sb[XX] - sij[XX] * sb[ZZ];
133 sa[ZZ] = sij[XX] * sb[YY] - sij[YY] * sb[XX];
135 for (d = 0; (d < DIM); d++)
137 sij[d] = sij[d] / rij;
138 ra += gmx::square(sa[d]);
141 for (d = 0; (d < DIM); d++)
146 sb[XX] = sa[YY] * sij[ZZ] - sa[ZZ] * sij[YY];
147 sb[YY] = sa[ZZ] * sij[XX] - sa[XX] * sij[ZZ];
148 sb[ZZ] = sa[XX] * sij[YY] - sa[YY] * sij[XX];
154 case 1: /* construct one planar hydrogen (peptide,rings) */
157 for (d = 0; (d < DIM); d++)
159 sij[d] = xAI[d] - xAJ[d];
160 sb[d] = xAI[d] - xAK[d];
161 rij += gmx::square(sij[d]);
162 rb += gmx::square(sb[d]);
164 rij = std::sqrt(rij);
167 for (d = 0; (d < DIM); d++)
169 sa[d] = sij[d] / rij + sb[d] / rb;
170 ra += gmx::square(sa[d]);
173 for (d = 0; (d < DIM); d++)
175 xH1[d] = xAI[d] + distH * sa[d] / ra;
178 case 2: /* one single hydrogen, e.g. hydroxyl */
179 for (d = 0; (d < DIM); d++)
181 xH1[d] = xAI[d] + distH * sin(alfaH) * sb[d] - distH * cos(alfaH) * sij[d];
184 case 3: /* two planar hydrogens, e.g. -NH2 */
185 for (d = 0; (d < DIM); d++)
187 xH1[d] = xAI[d] - distH * sin(alfaHpl) * sb[d] - distH * cos(alfaHpl) * sij[d];
188 xH2[d] = xAI[d] + distH * sin(alfaHpl) * sb[d] - distH * cos(alfaHpl) * sij[d];
191 case 4: /* two or three tetrahedral hydrogens, e.g. -CH3 */
192 for (d = 0; (d < DIM); d++)
194 xH1[d] = xAI[d] + distH * sin(alfaH) * sb[d] - distH * cos(alfaH) * sij[d];
195 xH2[d] = (xAI[d] - distH * sin(alfaH) * 0.5 * sb[d]
196 + distH * sin(alfaH) * s6 * sa[d] - distH * cos(alfaH) * sij[d]);
197 if (xH3[XX] != NOTSET && xH3[YY] != NOTSET && xH3[ZZ] != NOTSET)
199 xH3[d] = (xAI[d] - distH * sin(alfaH) * 0.5 * sb[d]
200 - distH * sin(alfaH) * s6 * sa[d] - distH * cos(alfaH) * sij[d]);
204 case 5: /* one tetrahedral hydrogen, e.g. C3CH */
209 for (d = 0; (d < DIM); d++)
211 center = (xAJ[d] + xAK[d] + xAL[d]) / 3.0;
212 dxc[d] = xAI[d] - center;
215 for (d = 0; (d < DIM); d++)
217 xH1[d] = xAI[d] + dxc[d] * distH / center;
221 case 6: /* two tetrahedral hydrogens, e.g. C-CH2-C */
223 rvec rBB, rCC1, rCC2, rNN;
226 for (d = 0; (d < DIM); d++)
228 rBB[d] = xAI[d] - 0.5 * (xAJ[d] + xAK[d]);
232 rvec_sub(xAI, xAJ, rCC1);
233 rvec_sub(xAI, xAK, rCC2);
234 cprod(rCC1, rCC2, rNN);
237 for (d = 0; (d < DIM); d++)
239 xH1[d] = xAI[d] + distH * (cos(alfaH / 2.0) * rBB[d] / bb + sin(alfaH / 2.0) * rNN[d] / nn);
240 xH2[d] = xAI[d] + distH * (cos(alfaH / 2.0) * rBB[d] / bb - sin(alfaH / 2.0) * rNN[d] / nn);
244 case 7: /* two water hydrogens */ gen_waterhydrogen(2, xa, xh, l); break;
245 case 10: /* three water hydrogens */ gen_waterhydrogen(3, xa, xh, l); break;
246 case 11: /* four water hydrogens */ gen_waterhydrogen(4, xa, xh, l); break;
247 case 8: /* two carboxyl oxygens, -COO- */
248 for (d = 0; (d < DIM); d++)
250 xH1[d] = xAI[d] - distOM * sin(alfaCOM) * sb[d] - distOM * cos(alfaCOM) * sij[d];
251 xH2[d] = xAI[d] + distOM * sin(alfaCOM) * sb[d] - distOM * cos(alfaCOM) * sij[d];
254 case 9: /* carboxyl oxygens and hydrogen, -COOH */
256 rvec xa2[4]; /* i,j,k,l */
258 /* first add two oxygens */
259 for (d = 0; (d < DIM); d++)
261 xH1[d] = xAI[d] - distO * sin(alfaCO) * sb[d] - distO * cos(alfaCO) * sij[d];
262 xH2[d] = xAI[d] + distOA * sin(alfaCOA) * sb[d] - distOA * cos(alfaCOA) * sij[d];
265 /* now use rule 2 to add hydrogen to 2nd oxygen */
266 copy_rvec(xH2, xa2[0]); /* new i = n' */
267 copy_rvec(xAI, xa2[1]); /* new j = i */
268 copy_rvec(xAJ, xa2[2]); /* new k = j */
269 copy_rvec(xAK, xa2[3]); /* new l = k, not used */
270 calc_h_pos(2, xa2, (xh + 2), l);
274 default: gmx_fatal(FARGS, "Invalid argument (%d) for nht in routine genh\n", nht);