Commit 21f509ef authored by Paul Bauer's avatar Paul Bauer Committed by Mark Abraham
Browse files

Make QM/MM code always compile

Brought all the old interfaces back to a state where they can always
compile regardless of the build configuration, and give fatal errors
if used from a configuration that didn't support the method.

When configured, this should work as before, but we have no ability to
test that in Jenkins.

Added some necessary const correctness.

Did QM/MM preparation all in the same place, to simplify runner.cpp

Added deprecation status to release notes.

Refs #2706, #2569

Change-Id: I4a6566c60bfbf27a7b1916be1874b36987fb7da5
parent 6c2eb228
......@@ -82,3 +82,8 @@ All remaining aspects of the group cutoff scheme will be removed, once
a few remaining features (e.g. tabulated interactions, energy-group
exclusions, and vacuum simulations) are available with the Verlet
scheme. Deprecated in GROMACS 5.1
QM/MM support for ORCA, GAMESS and MOPAC
""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
These interfaces are untested, and no maintainer has been found for them.
Deprecated in GROMACS 2018.
......@@ -3004,16 +3004,27 @@ void init_forcerec(FILE *fp,
}
}
/* QM/MM initialization if requested
*/
if (ir->bQMMM)
// QM/MM initialization if requested
fr->bQMMM = ir->bQMMM;
if (fr->bQMMM)
{
fprintf(stderr, "QM/MM calculation requested.\n");
// Initialize QM/MM if supported
if (GMX_QMMM)
{
GMX_LOG(mdlog.info).asParagraph().
appendText("Large parts of the QM/MM support is deprecated, and may be removed in a future "
"version. Please get in touch with the developers if you find the support useful, "
"as help is needed if the functionality is to continue to be available.");
fr->qr = mk_QMMMrec();
init_QMMMrec(cr, mtop, ir, fr);
}
else
{
gmx_incons("QM/MM was requested, but is only available when GROMACS "
"is configured with QM/MM support");
}
}
fr->bQMMM = ir->bQMMM;
fr->qr = mk_QMMMrec();
/* Set all the static charge group info */
fr->cginfo_mb = init_cginfo_mb(fp, mtop, fr, bNoSolvOpt,
&bFEP_NonBonded,
......
......@@ -36,9 +36,9 @@
*/
#include "gmxpre.h"
#include "config.h"
#include "qm_gamess.h"
#if GMX_QMMM_GAMESS
#include "config.h"
#include <stdio.h>
#include <stdlib.h>
......@@ -54,28 +54,41 @@
#include "gromacs/mdlib/ns.h"
#include "gromacs/mdlib/qmmm.h"
#include "gromacs/mdtypes/commrec.h"
#include "gromacs/mdtypes/forcerec.h"
#include "gromacs/mdtypes/md_enums.h"
#include "gromacs/utility/fatalerror.h"
#include "gromacs/utility/smalloc.h"
/* QMMM sub routines */
/* mopac interface routines */
void
F77_FUNC(inigms, IMIGMS) (void);
static void
F77_FUNC(inigms, IMIGMS) ();
void
F77_FUNC(endgms, ENDGMS) (void);
void
F77_FUNC(grads, GRADS) (int *nrqmat, real *qmcrd, int *nrmmat, real *mmchrg,
static void
F77_FUNC(grads, GRADS) (const int *nrqmat, real *qmcrd, const int *nrmmat, const real *mmchrg,
real *mmcrd, real *qmgrad, real *mmgrad, real *energy);
#if !GMX_QMMM_GAMESS
// Stub definitions to make compilation succeed when not configured
// for GAMESS support. In that case, the module gives a fatal error
// when the initialization function is called, so there is no need to
// issue fatal errors here, because that introduces problems with
// tools suggesting and prohibiting noreturn attributes.
void F77_FUNC(inigms, IMIGMS) ()
{
};
// NOLINTNEXTLINE(readability-named-parameter)
void F77_FUNC(grads, GRADS) (const int *, real *, const int *,
const real *, real *, real *,
real *, real *)
{
};
#endif
void init_gamess(t_commrec *cr, t_QMrec *qm, t_MMrec *mm)
void init_gamess(const t_commrec *cr, t_QMrec *qm, t_MMrec *mm)
{
/* it works hopelessly complicated :-)
* first a file is written. Then the standard gamess input/output
......@@ -97,6 +110,10 @@ void init_gamess(t_commrec *cr, t_QMrec *qm, t_MMrec *mm)
"Cr", "Mn", "Fe", "Co", "Ni", "Cu", "Zn", "Ga",
"Ge", "As", "Se", "Br", "Kr"
};
if (!GMX_QMMM_GAMESS)
{
gmx_fatal(FARGS, "Cannot call GAMESS unless linked against it. Use cmake -DGMX_QMMM_PROGRAM=GAMESS, and ensure that linking will work correctly.");
}
if (PAR(cr))
{
......@@ -208,7 +225,7 @@ void init_gamess(t_commrec *cr, t_QMrec *qm, t_MMrec *mm)
}
}
real call_gamess(t_forcerec *fr, t_QMrec *qm, t_MMrec *mm,
real call_gamess(const t_QMrec *qm, const t_MMrec *mm,
rvec f[], rvec fshift[])
{
/* do the actual QMMM calculation using GAMESS-UK. In this
......@@ -219,12 +236,8 @@ real call_gamess(t_forcerec *fr, t_QMrec *qm, t_MMrec *mm,
int
i, j;
real
QMener = 0.0, *qmgrad, *mmgrad, *mmcrd, *qmcrd, energy;
t_QMMMrec
*qr;
QMener = 0.0, *qmgrad, *mmgrad, *mmcrd, *qmcrd, energy = 0;
/* copy the QMMMrec pointer */
qr = fr->qr;
snew(qmcrd, 3*(qm->nrQMatoms));
snew(mmcrd, 3*(mm->nrMMatoms));
snew(qmgrad, 3*(qm->nrQMatoms));
......@@ -278,4 +291,3 @@ real call_gamess(t_forcerec *fr, t_QMrec *qm, t_MMrec *mm,
QMener = energy*HARTREE2KJ*AVOGADRO;
return(QMener);
}
#endif
/*
* This file is part of the GROMACS molecular simulation package.
*
* Copyright (c) 2018, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
*
* GROMACS is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
* as published by the Free Software Foundation; either version 2.1
* of the License, or (at your option) any later version.
*
* GROMACS is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with GROMACS; if not, see
* http://www.gnu.org/licenses, or write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* If you want to redistribute modifications to GROMACS, please
* consider that scientific software is very special. Version
* control is crucial - bugs must be traceable. We will be happy to
* consider code for inclusion in the official distribution, but
* derived work must not be called official GROMACS. Details are found
* in the README & COPYING files - if they are missing, get the
* official version at http://www.gromacs.org.
*
* To help us fund GROMACS development, we humbly ask that you cite
* the research papers on the package. Check out http://www.gromacs.org.
*/
#ifndef GMX_MDLIB_QMGAMESS_H
#define GMX_MDLIB_QMGAMESS_H
#include "gromacs/mdlib/qmmm.h"
/*! \brief
* Initialize gamess datastructures.
*
* \param[in] cr Commrec datastructure.
* \param[in] qm QM forcerec.
* \param[in] mm MM part of forcerec.
*/
void init_gamess(const t_commrec *cr, t_QMrec *qm, t_MMrec *mm);
/*! \brief
* Run calculation with Gamess.
*
* \param[in] qm QM part of forcerec.
* \param[in] mm MM part of forcerec.
* \param[in] f Force vector.
* \param[in] fshift Force shift vector.
*/
real call_gamess(const t_QMrec *qm, const t_MMrec *mm,
rvec f[], rvec fshift[]);
#endif
......@@ -36,12 +36,10 @@
*/
#include "gmxpre.h"
#include "config.h"
#if GMX_QMMM_GAUSSIAN
#include "qm_gaussian.h"
#include "config.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
......@@ -84,6 +82,11 @@ void init_gaussian(t_QMrec *qm)
int
i;
if (!GMX_QMMM_GAUSSIAN)
{
gmx_fatal(FARGS, "Cannot call GAUSSIAN unless linked against it. Use cmake -DGMX_QMMM_PROGRAM=GAUSSIAN, and ensure that linking will work correctly.");
}
/* using the ivec above to convert the basis read form the mdp file
* in a human readable format into some numbers for the gaussian
* route. This is necessary as we are using non standard routes to
......@@ -1022,6 +1025,3 @@ real call_gaussian_SH(const t_forcerec *fr, t_QMrec *qm, t_MMrec *mm, rvec f[],
return(QMener);
} /* call_gaussian_SH */
/* end of gaussian sub routines */
#endif
......@@ -36,9 +36,9 @@
*/
#include "gmxpre.h"
#include "config.h"
#include "qm_mopac.h"
#if GMX_QMMM_MOPAC
#include "config.h"
#include <stdio.h>
#include <stdlib.h>
......@@ -58,6 +58,7 @@
#include "gromacs/utility/smalloc.h"
#if GMX_QMMM_MOPAC
/* mopac interface routines */
void
F77_FUNC(domldt, DOMLDT) (int *nrqmat, int labels[], char keywords[]);
......@@ -67,6 +68,24 @@ void
double mmchrg[], double mmcrd[], double qmgrad[],
double mmgrad[], double *energy, double qmcharges[]);
#else /* GMX_QMMM_MOPAC */
// Stub definitions to make compilation succeed when not configured
// for MOPAC support. In that case, the module gives a fatal error
// when the initialization function is called, so there is no need to
// issue fatal errors here, because that introduces problems with
// tools suggesting and prohibiting noreturn attributes.
static void F77_FUNC(domldt, DOMLDT) (int * /*unused*/, int /*unused*/[], char /*unused*/[])
{
}
static void F77_FUNC(domop, DOMOP) (int * /*unused*/, double /*unused*/[], int * /*unused*/,
double /*unused*/[], double /*unused*/[], double /*unused*/[],
double /*unused*/[], double * /*unused*/, double /*unused*/[])
{
}
#endif
void init_mopac(t_QMrec *qm)
......@@ -80,6 +99,11 @@ void init_mopac(t_QMrec *qm)
char
*keywords;
if (!GMX_QMMM_MOPAC)
{
gmx_fatal(FARGS, "Cannot call MOPAC unless linked against it. Use cmake -DGMX_QMMM_PROGRAM=MOPAC, and ensure that linking will work correctly.");
}
snew(keywords, 240);
if (!qm->bSH) /* if rerun then grad should not be done! */
......@@ -107,8 +131,8 @@ real call_mopac(t_QMrec *qm, t_MMrec *mm, rvec f[], rvec fshift[])
*/
double /* always double as the MOPAC routines are always compiled in
double precission! */
*qmcrd = NULL, *qmchrg = NULL, *mmcrd = NULL, *mmchrg = NULL,
*qmgrad, *mmgrad = NULL, energy;
*qmcrd = nullptr, *qmchrg = nullptr, *mmcrd = nullptr, *mmchrg = nullptr,
*qmgrad, *mmgrad = nullptr, energy = 0;
int
i, j;
real
......@@ -122,7 +146,7 @@ real call_mopac(t_QMrec *qm, t_MMrec *mm, rvec f[], rvec fshift[])
{
for (j = 0; j < DIM; j++)
{
qmcrd[3*i+j] = (double)qm->xQM[i][j]*10;
qmcrd[3*i+j] = static_cast<double>(qm->xQM[i][j])*10;
}
}
if (mm->nrMMatoms)
......@@ -149,11 +173,11 @@ real call_mopac(t_QMrec *qm, t_MMrec *mm, rvec f[], rvec fshift[])
{
for (j = 0; j < DIM; j++)
{
f[i][j] = (real)10*CAL2JOULE*qmgrad[3*i+j];
fshift[i][j] = (real)10*CAL2JOULE*qmgrad[3*i+j];
f[i][j] = static_cast<real>(10)*CAL2JOULE*qmgrad[3*i+j];
fshift[i][j] = static_cast<real>(10)*CAL2JOULE*qmgrad[3*i+j];
}
}
QMener = (real)CAL2JOULE*energy;
QMener = static_cast<real>CAL2JOULE*energy;
/* do we do something with the mulliken charges?? */
free(qmchrg);
......@@ -170,8 +194,8 @@ real call_mopac_SH(t_QMrec *qm, t_MMrec *mm, rvec f[], rvec fshift[])
double /* always double as the MOPAC routines are always compiled in
double precission! */
*qmcrd = NULL, *qmchrg = NULL, *mmcrd = NULL, *mmchrg = NULL,
*qmgrad, *mmgrad = NULL, energy;
*qmcrd = nullptr, *qmchrg = nullptr, *mmcrd = nullptr, *mmchrg = nullptr,
*qmgrad, *mmgrad = nullptr, energy = 0;
int
i, j;
real
......@@ -186,7 +210,7 @@ real call_mopac_SH(t_QMrec *qm, t_MMrec *mm, rvec f[], rvec fshift[])
{
for (j = 0; j < DIM; j++)
{
qmcrd[3*i+j] = (double)qm->xQM[i][j]*10;
qmcrd[3*i+j] = static_cast<double>(qm->xQM[i][j])*10;
}
}
if (mm->nrMMatoms)
......@@ -212,14 +236,13 @@ real call_mopac_SH(t_QMrec *qm, t_MMrec *mm, rvec f[], rvec fshift[])
{
for (j = 0; j < DIM; j++)
{
f[i][j] = (real)10*CAL2JOULE*qmgrad[3*i+j];
fshift[i][j] = (real)10*CAL2JOULE*qmgrad[3*i+j];
f[i][j] = static_cast<real>(10)*CAL2JOULE*qmgrad[3*i+j];
fshift[i][j] = static_cast<real>(10)*CAL2JOULE*qmgrad[3*i+j];
}
}
QMener = (real)CAL2JOULE*energy;
QMener = static_cast<real>CAL2JOULE*energy;
}
free(qmgrad);
free(qmcrd);
return (QMener);
} /* call_mopac_SH */
#endif
/*
* This file is part of the GROMACS molecular simulation package.
*
* Copyright (c) 2018, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
*
* GROMACS is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
* as published by the Free Software Foundation; either version 2.1
* of the License, or (at your option) any later version.
*
* GROMACS is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with GROMACS; if not, see
* http://www.gnu.org/licenses, or write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* If you want to redistribute modifications to GROMACS, please
* consider that scientific software is very special. Version
* control is crucial - bugs must be traceable. We will be happy to
* consider code for inclusion in the official distribution, but
* derived work must not be called official GROMACS. Details are found
* in the README & COPYING files - if they are missing, get the
* official version at http://www.gromacs.org.
*
* To help us fund GROMACS development, we humbly ask that you cite
* the research papers on the package. Check out http://www.gromacs.org.
*/
#ifndef GMX_MDLIB_QMMOPAC_H
#define GMX_MDLIB_QMMOPAC_H
#include "gromacs/mdlib/qmmm.h"
/*! \brief
* Initialize mopac datastructures.
*
* \param[in] qm QM forcerec.
*/
void
init_mopac(t_QMrec *qm);
/*! \brief
* Run calculation with MOPAC.
*
* \param[in] qm QM part of forcerec.
* \param[in] mm MM part of forcerec.
* \param[in] f Force vector.
* \param[in] fshift Force shift vector.
*/
real
call_mopac(t_QMrec *qm, t_MMrec *mm, rvec f[], rvec fshift[]);
/*! \brief
* Run surface-hopping calculation with MOPAC.
*
* \param[in] qm QM part of forcerec.
* \param[in] mm MM part of forcerec.
* \param[in] f Force vector.
* \param[in] fshift Force shift vector.
*/
real
call_mopac_SH(t_QMrec *qm, t_MMrec *mm, rvec f[], rvec fshift[]);
#endif
......@@ -38,6 +38,8 @@
#include "qm_orca.h"
#include "config.h"
#include <cmath>
#include <cstdio>
#include <cstdlib>
......@@ -62,6 +64,11 @@ void init_orca(t_QMrec *qm)
char *buf;
snew(buf, 200);
if (!GMX_QMMM_ORCA)
{
gmx_fatal(FARGS, "Cannot call ORCA unless linked against it. Use cmake -DGMX_QMMM_PROGRAM=ORCA, and ensure that linking will work correctly.");
}
/* ORCA settings on the system */
buf = getenv("GMX_QM_ORCA_BASENAME");
if (buf)
......@@ -97,7 +104,7 @@ void init_orca(t_QMrec *qm)
}
static void write_orca_input(t_forcerec *fr, t_QMrec *qm, t_MMrec *mm)
static void write_orca_input(const t_forcerec *fr, t_QMrec *qm, t_MMrec *mm)
{
int i;
t_QMMMrec *QMMMrec;
......@@ -186,7 +193,7 @@ static void write_orca_input(t_forcerec *fr, t_QMrec *qm, t_MMrec *mm)
fclose(out);
} /* write_orca_input */
static real read_orca_output(rvec QMgrad[], rvec MMgrad[], t_forcerec *fr,
static real read_orca_output(rvec QMgrad[], rvec MMgrad[], const t_forcerec *fr,
t_QMrec *qm, t_MMrec *mm)
{
int
......@@ -338,7 +345,7 @@ static void do_orca(char *orca_dir, char *basename)
}
}
real call_orca(t_forcerec *fr,
real call_orca(const t_forcerec *fr,
t_QMrec *qm, t_MMrec *mm, rvec f[], rvec fshift[])
{
/* normal orca jobs */
......
/*
* This file is part of the GROMACS molecular simulation package.
*
* Copyright (c) 2017, by the GROMACS development team, led by
* Copyright (c) 2017,2018, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
......@@ -41,7 +41,7 @@ void
init_orca(t_QMrec *qm);
real
call_orca(t_forcerec *fr, t_QMrec *qm,
call_orca(const t_forcerec *fr, t_QMrec *qm,
t_MMrec *mm, rvec f[], rvec fshift[]);
#endif
......@@ -55,6 +55,10 @@
#include "gromacs/math/units.h"
#include "gromacs/math/vec.h"
#include "gromacs/mdlib/ns.h"
#include "gromacs/mdlib/qm_gamess.h"
#include "gromacs/mdlib/qm_gaussian.h"
#include "gromacs/mdlib/qm_mopac.h"
#include "gromacs/mdlib/qm_orca.h"
#include "gromacs/mdtypes/commrec.h"
#include "gromacs/mdtypes/forcerec.h"
#include "gromacs/mdtypes/inputrec.h"
......@@ -69,48 +73,6 @@
#include "gromacs/utility/fatalerror.h"
#include "gromacs/utility/smalloc.h"
/* declarations of the interfaces to the QM packages. The _SH indicate
* the QM interfaces can be used for Surface Hopping simulations
*/
#if GMX_QMMM_GAMESS
/* GAMESS interface */
void
init_gamess(const t_commrec *cr, t_QMrec *qm, t_MMrec *mm);
real
call_gamess(const t_forcerec *fr,
t_QMrec *qm, t_MMrec *mm, rvec f[], rvec fshift[]);
#elif GMX_QMMM_MOPAC
/* MOPAC interface */
void
init_mopac(t_QMrec *qm);
real
call_mopac(t_QMrec *qm, t_MMrec *mm, rvec f[], rvec fshift[]);
real
call_mopac_SH(t_QMrec *qm, t_MMrec *mm, rvec f[], rvec fshift[]);
#elif GMX_QMMM_GAUSSIAN
/* GAUSSIAN interface */
void
init_gaussian(t_QMrec *qm);
real
call_gaussian_SH(const t_forcerec *fr, t_QMrec *qm, t_MMrec *mm, rvec f[], rvec fshift[]);
real
call_gaussian(const t_forcerec *fr, t_QMrec *qm, t_MMrec *mm, rvec f[], rvec fshift[]);
#elif GMX_QMMM_ORCA
#include "gromacs/mdlib/qm_orca.h"
#endif
#if GMX_QMMM
/* this struct and these comparison functions are needed for creating
* a QMMM input for the QM routines from the QMMM neighbor list.
*/
......@@ -135,41 +97,54 @@ static real call_QMroutine(const t_commrec gmx_unused *cr, const t_forcerec gmx_
if (qm->QMmethod < eQMmethodRHF && !(mm->nrMMatoms))
{
#if GMX_QMMM_MOPAC
if (qm->bSH)
if (GMX_QMMM_MOPAC)
{
return call_mopac_SH(qm, mm, f, fshift);
if (qm->bSH)
{
return call_mopac_SH(qm, mm, f, fshift);
}
else
{
return call_mopac(qm, mm, f, fshift);
}
}
else
{
return call_mopac(qm, mm, f, fshift);
gmx_fatal(FARGS, "Semi-empirical QM only supported with Mopac.");
}
#else
gmx_fatal(FARGS, "Semi-empirical QM only supported with Mopac.");
#endif
}
else
{
/* do an ab-initio calculation */
if (qm->bSH && qm->QMmethod == eQMmethodCASSCF)
{
#if GMX_QMMM_GAUSSIAN
return call_gaussian_SH(fr, qm, mm, f, fshift);
#else
gmx_fatal(FARGS, "Ab-initio Surface-hopping only supported with Gaussian.");
#endif
if (GMX_QMMM_GAUSSIAN)
{
return call_gaussian_SH(fr, qm, mm, f, fshift);
}
else
{
gmx_fatal(FARGS, "Ab-initio Surface-hopping only supported with Gaussian.");
}
}
else
{
#if GMX_QMMM_GAMESS
return call_gamess(fr, qm, mm, f, fshift);
#elif GMX_QMMM_GAUSSIAN
return call_gaussian(fr, qm, mm, f, fshift);