b7c729b29d34b8b7c9c896eda8e5ca5f9970e1ac
[alexxy/gromacs.git] / src / gromacs / mdlib / qm_gamess.cpp
1 /*
2  * This file is part of the GROMACS molecular simulation package.
3  *
4  * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
5  * Copyright (c) 2001-2004, The GROMACS development team.
6  * Copyright (c) 2013,2014,2015, 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.
10  *
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.
15  *
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.
20  *
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.
25  *
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.
33  *
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.
36  */
37 #include "gmxpre.h"
38
39 #include "config.h"
40
41 #ifdef GMX_QMMM_GAMESS
42
43 #include <math.h>
44 #include <stdio.h>
45 #include <stdlib.h>
46 #include <string.h>
47
48 #include "gromacs/fileio/confio.h"
49 #include "gromacs/legacyheaders/force.h"
50 #include "gromacs/legacyheaders/macros.h"
51 #include "gromacs/legacyheaders/names.h"
52 #include "gromacs/legacyheaders/network.h"
53 #include "gromacs/legacyheaders/nrnb.h"
54 #include "gromacs/legacyheaders/ns.h"
55 #include "gromacs/legacyheaders/qmmm.h"
56 #include "gromacs/legacyheaders/txtdump.h"
57 #include "gromacs/legacyheaders/typedefs.h"
58 #include "gromacs/legacyheaders/types/commrec.h"
59 #include "gromacs/math/units.h"
60 #include "gromacs/math/vec.h"
61 #include "gromacs/utility/fatalerror.h"
62 #include "gromacs/utility/smalloc.h"
63
64
65 /* QMMM sub routines */
66 /* mopac interface routines */
67
68
69 void
70     F77_FUNC(inigms, IMIGMS) (void);
71
72 void
73     F77_FUNC(endgms, ENDGMS) (void);
74
75 void
76     F77_FUNC(grads, GRADS) (int *nrqmat, real *qmcrd, int *nrmmat, real *mmchrg,
77                             real *mmcrd, real *qmgrad, real *mmgrad, real *energy);
78
79
80
81 void init_gamess(t_commrec *cr, t_QMrec *qm, t_MMrec *mm)
82 {
83     /* it works hopelessly complicated :-)
84      * first a file is written. Then the standard gamess input/output
85      * routine is called (no system()!) to set up all fortran arrays.
86      * this routine writes a punch file, like in a normal gamess run.
87      * via this punch file the other games routines, needed for gradient
88      * and energy evaluations are called. This setup works fine for
89      * dynamics simulations. 7-6-2002 (London)
90      */
91     int
92         i, j;
93     FILE
94        *out;
95     char
96         periodic_system[37][3] = {
97         "XX", "H ", "He", "Li", "Be", "B ", "C ", "N ",
98         "O ", "F ", "Ne", "Na", "Mg", "Al", "Si", "P ",
99         "S ", "Cl", "Ar", "K ", "Ca", "Sc", "Ti", "V ",
100         "Cr", "Mn", "Fe", "Co", "Ni", "Cu", "Zn", "Ga",
101         "Ge", "As", "Se", "Br", "Kr"
102     };
103
104     if (PAR(cr))
105     {
106
107         if (MASTER(cr))
108         {
109             out = fopen("FOR009", "w");
110             /* of these options I am not completely sure....  the overall
111              * preformance on more than 4 cpu's is rather poor at the moment.
112              */
113             fprintf(out, "memory 48000000\nPARALLEL IOMODE SCREENED\n");
114             fprintf(out, "ELEC %d\nMULT %d\nSUPER ON\nNOSYM\nGEOMETRY ANGSTROM\n",
115                     qm->nelectrons, qm->multiplicity);
116             for (i = 0; i < qm->nrQMatoms; i++)
117             {
118 #ifdef DOUBLE
119                 fprintf(out, "%10.7lf  %10.7lf  %10.7lf  %5.3lf  %2s\n",
120                         i/2.,
121                         i/3.,
122                         i/4.,
123                         qm->atomicnumberQM[i]*1.0,
124                         periodic_system[qm->atomicnumberQM[i]]);
125 #else
126                 fprintf(out, "%10.7f  %10.7f  %10.7f  %5.3f  %2s\n",
127                         i/2.,
128                         i/3.,
129                         i/4.,
130                         qm->atomicnumberQM[i]*1.0,
131                         periodic_system[qm->atomicnumberQM[i]]);
132 #endif
133             }
134             if (mm->nrMMatoms)
135             {
136                 for (j = i; j < i+2; j++)
137                 {
138 #ifdef DOUBLE
139                     fprintf(out, "%10.7lf  %10.7lf  %10.7lf  %5.3lf  BQ\n",
140                             j/5.,
141                             j/6.,
142                             j/7.,
143                             1.0);
144 #else
145                     fprintf(out, "%10.7f  %10.7f  %10.7f  %5.3f  BQ\n",
146                             j/5.,
147                             j/6.,
148                             j/7.,
149                             2.0);
150 #endif
151                 }
152             }
153             if (!qm->bTS)
154             {
155                 fprintf(out, "END\nBASIS %s\nRUNTYPE GRADIENT\nSCFTYPE %s\n",
156                         eQMbasis_names[qm->QMbasis],
157                         eQMmethod_names[qm->QMmethod]); /* see enum.h */
158             }
159             else
160             {
161                 fprintf(out, "END\nBASIS %s\nRUNTYPE SADDLE\nSCFTYPE %s\n",
162                         eQMbasis_names[qm->QMbasis],
163                         eQMmethod_names[qm->QMmethod]); /* see enum.h */
164             }
165             fclose(out);
166         }
167         gmx_barrier(cr);
168         F77_FUNC(inigms, IMIGMS) ();
169     }
170     else /* normal serial run */
171
172     {
173         out = fopen("FOR009", "w");
174         /* of these options I am not completely sure....  the overall
175          * preformance on more than 4 cpu's is rather poor at the moment.
176          */
177         fprintf(out, "ELEC %d\nMULT %d\nSUPER ON\nNOSYM\nGEOMETRY ANGSTROM\n",
178                 qm->nelectrons, qm->multiplicity);
179         for (i = 0; i < qm->nrQMatoms; i++)
180         {
181 #ifdef DOUBLE
182             fprintf(out, "%10.7lf  %10.7lf  %10.7lf  %5.3lf  %2s\n",
183                     i/2.,
184                     i/3.,
185                     i/4.,
186                     qm->atomicnumberQM[i]*1.0,
187                     periodic_system[qm->atomicnumberQM[i]]);
188 #else
189             fprintf(out, "%10.7f  %10.7f  %10.7f  %5.3f  %2s\n",
190                     i/2.,
191                     i/3.,
192                     i/4.,
193                     qm->atomicnumberQM[i]*1.0,
194                     periodic_system[qm->atomicnumberQM[i]]);
195 #endif
196         }
197         if (mm->nrMMatoms)
198         {
199             for (j = i; j < i+2; j++)
200             {
201 #ifdef DOUBLE
202                 fprintf(out, "%10.7lf  %10.7lf  %10.7lf  %5.3lf  BQ\n",
203                         j/5.,
204                         j/6.,
205                         j/7.,
206                         1.0);
207 #else
208                 fprintf(out, "%10.7f  %10.7f  %10.7f  %5.3f  BQ\n",
209                         j/5.,
210                         j/6.,
211                         j/7.,
212                         2.0);
213 #endif
214             }
215         }
216         if (!qm->bTS)
217         {
218             fprintf(out, "END\nBASIS %s\nRUNTYPE GRADIENT\nSCFTYPE %s\n",
219                     eQMbasis_names[qm->QMbasis],
220                     eQMmethod_names[qm->QMmethod]); /* see enum.h */
221         }
222         else
223         {
224             fprintf(out, "END\nBASIS %s\nRUNTYPE SADDLE\nSCFTYPE %s\n",
225                     eQMbasis_names[qm->QMbasis],
226                     eQMmethod_names[qm->QMmethod]); /* see enum.h */
227         }
228         F77_FUNC(inigms, IMIGMS) ();
229     }
230 }
231
232 real call_gamess(t_forcerec *fr, t_QMrec *qm, t_MMrec *mm,
233                  rvec f[], rvec fshift[])
234 {
235     /* do the actual QMMM calculation using GAMESS-UK. In this
236      * implementation (3-2001) a system call is made to the GAMESS-UK
237      * binary. Now we are working to get the electron integral, SCF, and
238      * gradient routines linked directly
239      */
240     int
241         i, j;
242     real
243         QMener = 0.0, *qmgrad, *mmgrad, *mmcrd, *qmcrd, energy;
244     t_QMMMrec
245        *qr;
246
247     /* copy the QMMMrec pointer */
248     qr = fr->qr;
249     snew(qmcrd, 3*(qm->nrQMatoms));
250     snew(mmcrd, 3*(mm->nrMMatoms));
251     snew(qmgrad, 3*(qm->nrQMatoms));
252     snew(mmgrad, 3*(mm->nrMMatoms));
253
254     /* copy the data from qr into the arrays that are going to be used
255      * in the fortran routines of gamess
256      */
257     for (i = 0; i < qm->nrQMatoms; i++)
258     {
259         for (j = 0; j < DIM; j++)
260         {
261             qmcrd[DIM*i+j] = 1/BOHR2NM*qm->xQM[i][j];
262         }
263     }
264     for (i = 0; i < mm->nrMMatoms; i++)
265     {
266         for (j = 0; j < DIM; j++)
267         {
268             mmcrd[DIM*i+j] = 1/BOHR2NM*mm->xMM[i][j];
269         }
270     }
271     for (i = 0; i < 3*qm->nrQMatoms; i += 3)
272     {
273         fprintf(stderr, "%8.5f, %8.5f, %8.5f\n",
274                 qmcrd[i],
275                 qmcrd[i+1],
276                 qmcrd[i+2]);
277     }
278
279     F77_FUNC(grads, GRADS) (&qm->nrQMatoms, qmcrd, &mm->nrMMatoms, mm->MMcharges,
280                             mmcrd, qmgrad, mmgrad, &energy);
281
282     for (i = 0; i < qm->nrQMatoms; i++)
283     {
284         for (j = 0; j < DIM; j++)
285         {
286             f[i][j]      = HARTREE_BOHR2MD*qmgrad[3*i+j];
287             fshift[i][j] = HARTREE_BOHR2MD*qmgrad[3*i+j];
288         }
289     }
290     for (i = 0; i < mm->nrMMatoms; i++)
291     {
292         for (j = 0; j < DIM; j++)
293         {
294             f[i][j]      = HARTREE_BOHR2MD*mmgrad[3*i+j];
295             fshift[i][j] = HARTREE_BOHR2MD*mmgrad[3*i+j];
296         }
297     }
298     /* convert a.u to kJ/mol */
299     QMener = energy*HARTREE2KJ*AVOGADRO;
300     return(QMener);
301 }
302
303 #else
304 int
305     gmx_qmmm_gamess_empty;
306 #endif