Merge release-4-6 into master
[alexxy/gromacs.git] / src / gromacs / mdlib / qm_mopac.c
1 /*
2  * 
3  *                This source code is part of
4  * 
5  *                 G   R   O   M   A   C   S
6  * 
7  *          GROningen MAchine for Chemical Simulations
8  * 
9  *                        VERSION 3.2.0
10  * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
11  * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
12  * Copyright (c) 2001-2004, The GROMACS development team,
13  * check out http://www.gromacs.org for more information.
14  
15  * This program is free software; you can redistribute it and/or
16  * modify it under the terms of the GNU General Public License
17  * as published by the Free Software Foundation; either version 2
18  * of the License, or (at your option) any later version.
19  * 
20  * If you want to redistribute modifications, please consider that
21  * scientific software is very special. Version control is crucial -
22  * bugs must be traceable. We will be happy to consider code for
23  * inclusion in the official distribution, but derived work must not
24  * be called official GROMACS. Details are found in the README & COPYING
25  * files - if they are missing, get the official version at www.gromacs.org.
26  * 
27  * To help us fund GROMACS development, we humbly ask that you cite
28  * the papers on the package - you can find them in the top README file.
29  * 
30  * For more info, check our website at http://www.gromacs.org
31  * 
32  * And Hey:
33  * GROwing Monsters And Cloning Shrimps
34  */
35 #ifdef HAVE_CONFIG_H
36 #include <config.h>
37 #endif
38
39 #ifdef GMX_QMMM_MOPAC
40
41 #include <math.h>
42 #include "sysstuff.h"
43 #include "typedefs.h"
44 #include "macros.h"
45 #include "smalloc.h"
46 #include "physics.h"
47 #include "macros.h"
48 #include "vec.h"
49 #include "force.h"
50 #include "invblock.h"
51 #include "confio.h"
52 #include "names.h"
53 #include "network.h"
54 #include "pbc.h"
55 #include "ns.h"
56 #include "nrnb.h"
57 #include "bondf.h"
58 #include "mshift.h"
59 #include "txtdump.h"
60 #include "copyrite.h"
61 #include "qmmm.h"
62 #include <stdio.h>
63 #include <string.h>
64 #include "gmx_fatal.h"
65 #include "typedefs.h"
66 #include <stdlib.h>
67
68
69 /* mopac interface routines */
70 void 
71 F77_FUNC(domldt,DOMLDT)(int *nrqmat, int labels[], char keywords[]);
72
73 void 
74 F77_FUNC(domop,DOMOP)(int *nrqmat,double qmcrd[],int *nrmmat,
75                       double mmchrg[],double mmcrd[],double qmgrad[],
76                       double mmgrad[], double *energy,double qmcharges[]);
77
78
79
80 void init_mopac(t_commrec *cr, t_QMrec *qm, t_MMrec *mm)
81 {
82   /* initializes the mopac routines ans sets up the semiempirical
83    * computation by calling moldat(). The inline mopac routines can
84    * only perform gradient operations. If one would like to optimize a
85    * structure or find a transition state at PM3 level, gaussian is
86    * used instead.
87    */
88   char 
89     *keywords;
90   
91   snew(keywords,240);
92   
93   if(!qm->bSH){    /* if rerun then grad should not be done! */
94     sprintf(keywords,"PRECISE GEO-OK CHARGE=%d GRAD MMOK ANALYT %s\n",
95             qm->QMcharge,
96             eQMmethod_names[qm->QMmethod]);
97   }
98   else
99     sprintf(keywords,"PRECISE GEO-OK CHARGE=%d SINGLET GRAD %s C.I.=(%d,%d) root=2 MECI \n",
100             qm->QMcharge,
101             eQMmethod_names[qm->QMmethod],
102             qm->CASorbitals,qm->CASelectrons/2);
103   F77_FUNC(domldt,DOMLDT)(&qm->nrQMatoms,qm->atomicnumberQM,keywords);
104   fprintf(stderr,"keywords are: %s\n",keywords);
105   free(keywords);
106   
107 } /* init_mopac */
108
109 real call_mopac(t_commrec *cr, t_forcerec *fr, t_QMrec *qm, t_MMrec *mm, 
110                 rvec f[], rvec fshift[])
111 {
112   /* do the actual QMMM calculation using directly linked mopac subroutines 
113    */
114   double /* always double as the MOPAC routines are always compiled in
115             double precission! */
116     *qmcrd=NULL,*qmchrg=NULL,*mmcrd=NULL,*mmchrg=NULL,
117     *qmgrad,*mmgrad=NULL,energy;
118   int
119     i,j;
120   real
121     QMener=0.0;
122   snew(qmcrd, 3*(qm->nrQMatoms));
123   snew(qmgrad,3*(qm->nrQMatoms));
124   /* copy the data from qr into the arrays that are going to be used
125    * in the fortran routines of MOPAC
126    */
127   for(i=0;i<qm->nrQMatoms;i++){
128     for (j=0;j<DIM;j++){
129       qmcrd[3*i+j] = (double)qm->xQM[i][j]*10;
130     }
131   }
132   if(mm->nrMMatoms){
133     /* later we will add the point charges here. There are some
134      * conceptual problems with semi-empirical QM in combination with
135      * point charges that we need to solve first....  
136      */
137     gmx_fatal(FARGS,"At present only ONIOM is allowed in combination"
138                 " with MOPAC QM subroutines\n");
139   }
140   else {
141     /* now compute the energy and the gradients.
142      */
143       
144     snew(qmchrg,qm->nrQMatoms);    
145     F77_FUNC(domop,DOMOP)(&qm->nrQMatoms,qmcrd,&mm->nrMMatoms,
146            mmchrg,mmcrd,qmgrad,mmgrad,&energy,qmchrg);
147     /* add the gradients to the f[] array, and also to the fshift[].
148      * the mopac gradients are in kCal/angstrom.
149      */
150     for(i=0;i<qm->nrQMatoms;i++){
151       for(j=0;j<DIM;j++){
152         f[i][j]       = (real)10*CAL2JOULE*qmgrad[3*i+j];
153         fshift[i][j]  = (real)10*CAL2JOULE*qmgrad[3*i+j];
154       }
155     }
156     QMener = (real)CAL2JOULE*energy;
157     /* do we do something with the mulliken charges?? */
158
159     free(qmchrg);
160 }
161   free(qmgrad);
162   free(qmcrd);
163   return (QMener);
164 }
165
166 real call_mopac_SH(t_commrec *cr, t_forcerec *fr, t_QMrec *qm, t_MMrec *mm, 
167                    rvec f[], rvec fshift[])
168 {
169   /* do the actual SH QMMM calculation using directly linked mopac
170    subroutines */
171
172   double /* always double as the MOPAC routines are always compiled in
173             double precission! */
174     *qmcrd=NULL,*qmchrg=NULL,*mmcrd=NULL,*mmchrg=NULL,
175     *qmgrad,*mmgrad=NULL,energy;
176   int
177     i,j;
178   real
179     QMener=0.0;
180
181   snew(qmcrd, 3*(qm->nrQMatoms));
182   snew(qmgrad,3*(qm->nrQMatoms));
183   /* copy the data from qr into the arrays that are going to be used
184    * in the fortran routines of MOPAC
185    */
186   for(i=0;i<qm->nrQMatoms;i++){
187     for (j=0;j<DIM;j++){
188       qmcrd[3*i+j] = (double)qm->xQM[i][j]*10;
189     }
190   }
191   if(mm->nrMMatoms){
192     /* later we will add the point charges here. There are some
193      * conceptual problems with semi-empirical QM in combination with
194      * point charges that we need to solve first....  
195      */
196     gmx_fatal(FARGS,"At present only ONIOM is allowed in combination with MOPAC\n");
197   }
198   else {
199     /* now compute the energy and the gradients.
200      */
201     snew(qmchrg,qm->nrQMatoms);    
202
203     F77_FUNC(domop,DOMOP)(&qm->nrQMatoms,qmcrd,&mm->nrMMatoms,
204            mmchrg,mmcrd,qmgrad,mmgrad,&energy,qmchrg);
205     /* add the gradients to the f[] array, and also to the fshift[].
206      * the mopac gradients are in kCal/angstrom.
207      */
208     for(i=0;i<qm->nrQMatoms;i++){
209       for(j=0;j<DIM;j++){
210         f[i][j]      = (real)10*CAL2JOULE*qmgrad[3*i+j];
211         fshift[i][j] = (real)10*CAL2JOULE*qmgrad[3*i+j];
212       }
213     }
214     QMener = (real)CAL2JOULE*energy;
215   }
216   free(qmgrad);
217   free(qmcrd);
218   return (QMener);
219 } /* call_mopac_SH */
220
221 #else
222 int
223 gmx_qmmm_mopac_empty;
224 #endif