1 /* -*- mode: c; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; c-file-style: "stroustrup"; -*-
3 * This source code is part of
7 * GROningen MAchine for Chemical Simulations
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-2008, The GROMACS development team,
13 * check out http://www.gromacs.org for more information.
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.
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.
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.
30 * For more info, check our website at http://www.gromacs.org
33 * Groningen Machine for Chemical Simulation
63 #include "gmx_fatal.h"
67 /* ORCA interface routines */
69 void init_orca(t_commrec
*cr
, t_QMrec
*qm
, t_MMrec
*mm
)
74 /* ORCA settings on the system */
75 buf
= getenv("BASENAME");
77 snew(qm
->orca_basename
,200);
78 sscanf(buf
,"%s",qm
->orca_basename
);
81 gmx_fatal(FARGS
,"no $BASENAME\n");
83 /* ORCA directory on the system */
85 buf
= getenv("ORCA_PATH");
86 fprintf(stderr
,"%s",buf
);
89 snew(qm
->orca_dir
,200);
90 sscanf(buf
,"%s",qm
->orca_dir
);
93 gmx_fatal(FARGS
,"no $ORCA_PATH, check manual\n");
95 fprintf(stderr
,"%s...\n",qm
->orca_dir
);
96 fprintf(stderr
,"orca initialised...\n");
97 /* since we append the output to the BASENAME.out file,
98 we should delete an existent old out-file here. */
99 sprintf(buf
,"%s.out",qm
->orca_basename
);
104 void write_orca_input(int step
,t_forcerec
*fr
, t_QMrec
*qm
, t_MMrec
*mm
)
111 *out
, *pcFile
, *addInputFile
, *LJCoeff
;
113 *buf
,*orcaInput
,*addInputFilename
,*LJCoeffFilename
,
114 *pcFilename
,*exclInName
,*exclOutName
;
116 /* write the first part of the input-file */
118 sprintf(orcaInput
,"%s.inp",qm
->orca_basename
);
119 out
= fopen(orcaInput
,"w");
120 snew(addInputFilename
,200);
121 sprintf(addInputFilename
,"%s.ORCAINFO",qm
->orca_basename
);
122 addInputFile
= fopen(addInputFilename
,"r");
123 fprintf(out
, "#input-file generated by gromacs\n");
125 fprintf(out
,"!QMMMOpt TightSCF\n");
126 fprintf(out
,"%s\n","%geom TS_Search EF end");
129 fprintf(out
,"!QMMMOpt TightSCF\n");
132 fprintf(out
,"!EnGrad TightSCF\n");
134 /* here we include the insertion of the additional orca-input */
136 if (addInputFile
!=NULL
) {
137 while (!feof(addInputFile
)) {
138 if (fgets(buf
, 200, addInputFile
) != NULL
)
143 fprintf(stderr
,"No information on the calculation given in <%s>\n",addInputFilename
);
144 gmx_call("qm_orca.c");
146 fclose(addInputFile
);
147 if(qm
->bTS
||qm
->bOPT
){
148 /* freeze the frontier QM atoms and Link atoms. This is
149 * important only if a full QM subsystem optimization is done
150 * with a frozen MM environmeent. For dynamics, or gromacs's own
151 * optimization routines this is not important.
153 /* ORCA reads the exclusions from LJCoeffFilename.Excl,
154 *so we have to rename the file
157 for(i
=0;i
<qm
->nrQMatoms
;i
++){
158 if(qm
->frontatoms
[i
]){
160 fprintf(out
,"%s\n","%geom");
161 fprintf(out
," Constraints \n");
164 fprintf(out
," {C %d C}\n",i
); /* counting from 0 */
167 if (didStart
) fprintf(out
," end\n end\n");
168 /* make a file with information on the C6 and C12 coefficients */
169 if(QMMMrec
->QMMMscheme
!=eQMMMschemeoniom
&& mm
->nrMMatoms
){
170 snew(exclInName
,200);
171 snew(exclOutName
,200);
172 sprintf(exclInName
,"QMMMexcl.dat");
173 sprintf(exclOutName
,"%s.LJ.Excl",qm
->orca_basename
);
174 rename(exclInName
,exclOutName
);
175 snew(LJCoeffFilename
,200);
176 sprintf(LJCoeffFilename
,"%s.LJ",qm
->orca_basename
);
177 fprintf(out
,"%s%s%s\n","%LJCOEFFICIENTS \"",LJCoeffFilename
,"\"");
178 /* make a file with information on the C6 and C12 coefficients */
179 LJCoeff
= fopen(LJCoeffFilename
,"w");
180 fprintf(LJCoeff
,"%d\n",qm
->nrQMatoms
);
181 for (i
=0;i
<qm
->nrQMatoms
;i
++){
183 fprintf(LJCoeff
,"%10.7lf %10.7lf\n",qm
->c6
[i
],qm
->c12
[i
]);
185 fprintf(LJCoeff
,"%10.7f %10.7f\n",qm
->c6
[i
],qm
->c12
[i
]);
188 fprintf(LJCoeff
,"%d\n",mm
->nrMMatoms
);
189 for (i
=0;i
<mm
->nrMMatoms
;i
++){
191 fprintf(LJCoeff
,"%10.7lf %10.7lf\n",mm
->c6
[i
],mm
->c12
[i
]);
193 fprintf(LJCoeff
,"%10.7f %10.7f\n",mm
->c6
[i
],mm
->c12
[i
]);
199 /* write charge and multiplicity
201 fprintf(out
,"*xyz %2d%2d\n",qm
->QMcharge
,qm
->multiplicity
);
202 /* write the QM coordinates
204 for (i
=0;i
<qm
->nrQMatoms
;i
++){
206 if (qm
->atomicnumberQM
[i
]==0)
209 atomNr
= qm
->atomicnumberQM
[i
];
211 fprintf(out
,"%3d %10.7lf %10.7lf %10.7lf\n",
217 fprintf(out
,"%3d %10.7f %10.7f %10.7f\n",
225 /* write the MM point charge data
227 if(QMMMrec
->QMMMscheme
!=eQMMMschemeoniom
&& mm
->nrMMatoms
){
228 /* name of the point charge file */
229 snew(pcFilename
,200);
230 sprintf(pcFilename
,"%s.pc",qm
->orca_basename
);
231 fprintf(out
,"%s%s%s\n","%pointcharges \"",pcFilename
,"\"");
232 pcFile
= fopen(pcFilename
,"w");
233 fprintf(pcFile
,"%d\n",mm
->nrMMatoms
);
234 for(i
=0;i
<mm
->nrMMatoms
;i
++){
236 fprintf(pcFile
,"%8.4lf %10.7lf %10.7lf %10.7lf\n",
242 fprintf(pcFile
,"%8.4f %10.7f %10.7f %10.7f\n",
249 fprintf(pcFile
,"\n");
255 } /* write_orca_input */
257 real
read_orca_output(rvec QMgrad
[],rvec MMgrad
[],int step
,t_forcerec
*fr
,
258 t_QMrec
*qm
, t_MMrec
*mm
)
263 buf
[300], tmp
[300], orca_xyzFilename
[300], orca_pcgradFilename
[300], orca_engradFilename
[300];
267 *xyz
, *pcgrad
, *engrad
;
272 /* in case of an optimization, the coordinates are printed in the
273 * xyz file, the energy and gradients for the QM part are stored in the engrad file
274 * and the gradients for the point charges are stored in the pc file.
277 /* we need the new xyz coordinates of the QM atoms only for separate QM-optimization
280 if(qm
->bTS
||qm
->bOPT
){
281 sprintf(orca_xyzFilename
,"%s.xyz",qm
->orca_basename
);
282 xyz
=fopen(orca_xyzFilename
,"r");
283 if (fgets(buf
,300,xyz
) == NULL
)
284 gmx_fatal(FARGS
, "Unexpected end of ORCA output");
285 if (fgets(buf
,300,xyz
) == NULL
)
286 gmx_fatal(FARGS
, "Unexpected end of ORCA output");
287 for(i
=0;i
<qm
->nrQMatoms
;i
++){
288 if (fgets(buf
,300,xyz
) == NULL
)
289 gmx_fatal(FARGS
, "Unexpected end of ORCA output");
291 sscanf(buf
,"%s%lf%lf%lf\n",
297 sscanf(buf
,"%d%f%f%f\n",
309 sprintf(orca_engradFilename
,"%s.engrad",qm
->orca_basename
);
310 engrad
=fopen(orca_engradFilename
,"r");
311 /* we read the energy and the gradient for the qm-atoms from the engrad file
313 /* we can skip the first seven lines
316 if (fgets(buf
,300,engrad
) == NULL
)
317 gmx_fatal(FARGS
, "Unexpected end of ORCA output");
319 /* now comes the energy
321 if (fgets(buf
,300,engrad
) == NULL
)
322 gmx_fatal(FARGS
, "Unexpected end of ORCA output");
324 sscanf(buf
,"%lf\n",&QMener
);
326 sscanf(buf
,"%f\n", &QMener
);
328 /* we can skip the next three lines
331 if (fgets(buf
,300,engrad
) == NULL
)
332 gmx_fatal(FARGS
, "Unexpected end of ORCA output");
334 /* next lines contain the gradients of the QM atoms
335 * now comes the gradient, one value per line:
336 * (atom1 x \n atom1 y \n atom1 z \n atom2 x ...
339 for(i
=0;i
<3*qm
->nrQMatoms
;i
++){
341 if (fgets(buf
,300,engrad
) == NULL
)
342 gmx_fatal(FARGS
, "Unexpected end of ORCA output");
345 sscanf(buf
,"%lf\n", &QMgrad
[k
][XX
]);
347 sscanf(buf
,"%lf\n", &QMgrad
[k
][YY
]);
349 sscanf(buf
,"%lf\n", &QMgrad
[k
][ZZ
]);
352 sscanf(buf
,"%f\n", &QMgrad
[k
][XX
]);
354 sscanf(buf
,"%f\n", &QMgrad
[k
][YY
]);
356 sscanf(buf
,"%f\n", &QMgrad
[k
][ZZ
]);
360 /* write the MM point charge data
362 if(QMMMrec
->QMMMscheme
!=eQMMMschemeoniom
&& mm
->nrMMatoms
){
363 sprintf(orca_pcgradFilename
,"%s.pcgrad",qm
->orca_basename
);
364 pcgrad
=fopen(orca_pcgradFilename
,"r");
366 /* we read the gradient for the mm-atoms from the pcgrad file
368 /* we can skip the first line
370 if (fgets(buf
,300,pcgrad
) == NULL
)
371 gmx_fatal(FARGS
, "Unexpected end of ORCA output");
372 for(i
=0;i
<mm
->nrMMatoms
;i
++){
373 if (fgets(buf
,300,pcgrad
) == NULL
)
374 gmx_fatal(FARGS
, "Unexpected end of ORCA output");
376 sscanf(buf
,"%lf%lf%lf\n",
381 sscanf(buf
,"%f%f%f\n",
392 void do_orca(int step
,char *exe
, char *orca_dir
, char *basename
)
395 /* make the call to the orca binary through system()
396 * The location of the binary is set through the
401 sprintf(buf
,"%s/%s %s.inp >> %s.out",
406 fprintf(stderr
,"Calling '%s'\n",buf
);
407 if ( system(buf
) != 0 )
408 gmx_fatal(FARGS
,"Call to '%s' failed\n",buf
);
411 real
call_orca(t_commrec
*cr
, t_forcerec
*fr
,
412 t_QMrec
*qm
, t_MMrec
*mm
, rvec f
[], rvec fshift
[])
414 /* normal orca jobs */
427 sprintf(exe
,"%s","orca");
428 snew(QMgrad
,qm
->nrQMatoms
);
429 snew(MMgrad
,mm
->nrMMatoms
);
431 write_orca_input(step
,fr
,qm
,mm
);
432 do_orca(step
,exe
,qm
->orca_dir
,qm
->orca_basename
);
433 QMener
= read_orca_output(QMgrad
,MMgrad
,step
,fr
,qm
,mm
);
434 /* put the QMMM forces in the force array and to the fshift
436 for(i
=0;i
<qm
->nrQMatoms
;i
++){
438 f
[i
][j
] = HARTREE_BOHR2MD
*QMgrad
[i
][j
];
439 fshift
[i
][j
] = HARTREE_BOHR2MD
*QMgrad
[i
][j
];
442 for(i
=0;i
<mm
->nrMMatoms
;i
++){
444 f
[i
+qm
->nrQMatoms
][j
] = HARTREE_BOHR2MD
*MMgrad
[i
][j
];
445 fshift
[i
+qm
->nrQMatoms
][j
] = HARTREE_BOHR2MD
*MMgrad
[i
][j
];
448 QMener
= QMener
*HARTREE2KJ
*AVOGADRO
;
454 /* end of orca sub routines */