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