diff --git a/.vscode/c_cpp_properties.json b/.vscode/c_cpp_properties.json new file mode 100644 index 0000000..e3cf47b --- /dev/null +++ b/.vscode/c_cpp_properties.json @@ -0,0 +1,18 @@ +{ + "configurations": [ + { + "name": "Linux", + "includePath": [ + "${workspaceFolder}/**", + "/opt/software/openblas/**", + "/opt/software/lapack/**" + ], + "defines": [], + "compilerPath": "/usr/bin/gcc", + "cStandard": "c17", + "cppStandard": "gnu++17", + "intelliSenseMode": "linux-gcc-x64" + } + ], + "version": 4 +} \ No newline at end of file diff --git a/README.md b/README.md index 1711809..de9ae4f 100644 --- a/README.md +++ b/README.md @@ -6,8 +6,6 @@ This project is a port of the [`dftd4`](https://github.com/dftd4/dftd4) project to C++ and provides the D4(EEQ)-ATM method. -**NOTE:** This branch contains some adaptations for compatibility with the ORCA Quantum Chemistry program. This inludes some renaming of variables and functions, and, most notably, the handling of ghost atoms. - ## Building This Project This project is build with `meson`, to setup and perform a build run: diff --git a/app/main.cpp b/app/main.cpp index ffd9bbd..b9dd6a3 100644 --- a/app/main.cpp +++ b/app/main.cpp @@ -163,15 +163,6 @@ int main(int argc, char **argv) { dftd4::TCutoff cutoff; dftd4::TD4Model d4; - // masking (nothing excluded) - dftd4::TVector realIdx; - realIdx.NewVec(mol.NAtoms); - int nat = 0; - for (int i = 0; i != mol.NAtoms; i++) { - realIdx(i) = nat; - nat++; - } - // analytical gradient double *d4grad; if (lgrad) { @@ -183,9 +174,7 @@ int main(int argc, char **argv) { d4grad = nullptr; } - info = dftd4::get_dispersion( - mol, realIdx, charge, d4, par, cutoff, energy, d4grad - ); + info = dftd4::get_dispersion(mol, charge, d4, par, cutoff, energy, d4grad); if (info != EXIT_SUCCESS) return info; // Print results diff --git a/include/dftd_dispersion.h b/include/dftd_dispersion.h index edbdc44..f655d4e 100644 --- a/include/dftd_dispersion.h +++ b/include/dftd_dispersion.h @@ -27,6 +27,17 @@ namespace dftd4 { +/** + * @brief Container for DFT-D4 damping parameters. + * + * @param s6 C6 damping parameter. Usually 1. + * @param s8 C8 damping parameter. + * @param s10 C10 damping parameter. Always 0 currently. + * @param s9 ATM (three-body) damping parameter. Usually 1. + * @param a1 Becke-Johnson damping parameter. + * @param a2 Becke-Johnson damping parameter. + * @param alp ATM (three-body) damping parameter. Usually 16. + */ class dparam { public: double s6; @@ -42,7 +53,32 @@ class dparam { * @brief Wrapper to handle the evaluation of dispersion energy and derivatives. * * @param mol Molecular geometry. - * @param realIdx List for real atoms excluding ghost/non atoms + * @param charge Molecular charge. + * @param par DFT-D4 parameters. + * @param d4 Base D4 dispersion model. + * @param cutoff Real-space cutoffs for CN and dispersion. + * @param energy Dispersion energy (inout). + * @param GRAD Dispersion gradient (inout). + * @return Exit status. + */ +extern int get_dispersion( + const TMolecule &mol, + int charge, + const TD4Model &d4, + const dparam &par, + TCutoff cutoff, + double &energy, + double *GRAD +); + +/** + * @brief Wrapper to handle the evaluation of dispersion energy and derivatives. + * + * This function calculates the dispersion energy and gradients for the given + * molecular geometry, considering only the atoms specified in `realIdx`. + * + * @param mol Molecular geometry. + * @param realIdx List for real atoms excluding ghost/non atoms. * @param charge Molecular charge. * @param par DFT-D4 parameters. * @param d4 Base D4 dispersion model. diff --git a/include/dftd_eeq.h b/include/dftd_eeq.h index b66a052..dc55464 100644 --- a/include/dftd_eeq.h +++ b/include/dftd_eeq.h @@ -27,6 +27,44 @@ namespace dftd4 { +/** + * Get the EEQ charges for a given molecule. + * + * @param mol The molecule object + * @param dist The distance matrix + * @param charge The total charge of the molecule + * @param cutoff The cutoff for the EEQ coordination number + * @param q The EEQ charges + * @param dqdr The derivative of the EEQ charges + * @param lgrad Flag for the gradient + * + * @return 0 if successful, 1 otherwise + */ +extern int get_charges( + const TMolecule &mol, + const TMatrix &dist, + int charge, + double cutoff, + TVector &q, + TMatrix &dqdr, + bool lgrad +); + +/** + * Get the EEQ charges for a given molecule for the atoms specified by the + * indices in `realIdx`. + * + * @param mol The molecule object + * @param realIdx The real atom indices (for excluding dummy atoms) + * @param dist The distance matrix + * @param charge The total charge of the molecule + * @param cutoff The cutoff for the EEQ coordination number + * @param q The EEQ charges + * @param dqdr The derivative of the EEQ charges + * @param lgrad Flag for the gradient + * + * @return 0 if successful, 1 otherwise + */ extern int get_charges( const TMolecule &mol, const TIVector &realIdx, diff --git a/include/dftd_ncoord.h b/include/dftd_ncoord.h index d9d45b1..f512ecc 100644 --- a/include/dftd_ncoord.h +++ b/include/dftd_ncoord.h @@ -32,7 +32,7 @@ namespace dftd4 { * Calculate all distance pairs and store in matrix. * * @param mol Molecule object. - * @param realIdx List for real atoms excluding ghost/non atoms + * @param realIdx List for real atoms excluding ghost/non atoms. * @param dist Distance matrix (inout). * @return Exit status. */ @@ -42,11 +42,23 @@ extern int calc_distances( TMatrix &dist ); +/** + * Initialize real indices to all atoms in the molecule. + * + * @param nat Number of atoms in the molecule. + * @param realIdx Vector to store the real indices. + * @return void + */ +void initializeRealIdx(int nat, TVector &realIdx); + +/////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// + /** * Wrapper for error function coordination number. * * @param mol Molecule object. - * @param realIdx List for real atoms excluding ghost/non atoms + * @param realIdx List for real atoms excluding ghost/non atoms. * @param dist Distance matrix. * @param cn Vector of coordination numbers. * @param cutoff Real-space cutoff (default: @see {dftd_cutoff.h}). @@ -64,11 +76,31 @@ extern int get_ncoord_erf( bool lgrad = false ); +/** + * Wrapper for error function coordination number. + * + * @param mol Molecule object. + * @param dist Distance matrix. + * @param cn Vector of coordination numbers. + * @param cutoff Real-space cutoff (default: @see {dftd_cutoff.h}). + * @param dcndr Derivative of coordination number. + * @param lgrad Flag for gradient computation. + * @return Exit status. + */ +extern int get_ncoord_erf( + const TMolecule &mol, + const TMatrix &dist, + double cutoff, + TVector &cn, + TMatrix &dcndr, + bool lgrad = false +); + /** * Calculate error function coordination number. * * @param mol Molecule object. - * @param realIdx List for real atoms excluding ghost/non atoms + * @param realIdx List for real atoms excluding ghost/non atoms. * @param dist Distance matrix. * @param cutoff Real-space cutoff (default: @see {dftd_cutoff.h}). * @param cn Vector of coordination numbers. @@ -87,7 +119,7 @@ extern int ncoord_erf( * w.r.t. nuclear coordinates. * * @param mol Molecule object. - * @param realIdx List for real atoms excluding ghost/non atoms + * @param realIdx List for real atoms excluding ghost/non atoms. * @param dist Distance matrix. * @param cutoff Real-space cutoff (default: @see {dftd_cutoff.h}). * @param cn Vector of coordination numbers. @@ -103,11 +135,14 @@ extern int dncoord_erf( TMatrix &dcndr ); +/////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// + /** * Wrapper for error function coordination number for DFT-D4. * * @param mol Molecule object. - * @param realIdx List for real atoms excluding ghost/non atoms + * @param realIdx List for real atoms excluding ghost/non atoms. * @param dist Distance matrix. * @param cutoff Real-space cutoff (default: @see {dftd_cutoff.h}). * @param cn Vector of coordination numbers. @@ -123,11 +158,29 @@ extern int get_ncoord_d4( bool lgrad = false ); +/** + * Wrapper for error function coordination number for DFT-D4. + * + * @param mol Molecule object. + * @param dist Distance matrix. + * @param cutoff Real-space cutoff (default: @see {dftd_cutoff.h}). + * @param cn Vector of coordination numbers. + * @return Exit status. + */ +extern int get_ncoord_d4( + const TMolecule &mol, + const TMatrix &dist, + double cutoff, + TVector &cn, + TMatrix &dcndr, + bool lgrad = false +); + /** * Calculate covalent coordination number for DFT-D4. * * @param mol Molecule object. - * @param realIdx List for real atoms excluding ghost/non atoms + * @param realIdx List for real atoms excluding ghost/non atoms. * @param dist Distance matrix. * @param cutoff Real-space cutoff (default: @see {dftd_cutoff.h}). * @param cn Vector of coordination numbers. @@ -146,7 +199,7 @@ extern int ncoord_d4( * w.r.t. nuclear coordinates * * @param mol Molecule object. - * @param realIdx List for real atoms excluding ghost/non atoms + * @param realIdx List for real atoms excluding ghost/non atoms. * @param dist Distance matrix. * @param cutoff Real-space cutoff (default: @see {dftd_cutoff.h}). * @param cn Vector of coordination numbers. @@ -162,6 +215,9 @@ extern int dncoord_d4( TMatrix &dcndr ); +/////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// + /** * Error function counting function for coordination number contributions. * diff --git a/scripts/README.md b/scripts/README.md index 30c7133..c6accc9 100644 --- a/scripts/README.md +++ b/scripts/README.md @@ -1,3 +1,4 @@ # Scripts Scripts for creating the ORCA source files. This mainly concatenates the corresponding files and adds headers and footers. Execute within the `scripts` directory. +This is only useful for ORCA developers. diff --git a/src/dftd_dispersion.cpp b/src/dftd_dispersion.cpp index 4ad882b..5dff7f4 100644 --- a/src/dftd_dispersion.cpp +++ b/src/dftd_dispersion.cpp @@ -34,6 +34,21 @@ namespace dftd4 { +int get_dispersion( + const TMolecule &mol, + const int charge, + const TD4Model &d4, + const dparam &par, + const TCutoff cutoff, + double &energy, + double *GRAD +) { + TVector realIdx; + initializeRealIdx(mol.NAtoms, realIdx); + + return get_dispersion(mol, realIdx, charge, d4, par, cutoff, energy, GRAD); +} + int get_dispersion( const TMolecule &mol, const TIVector &realIdx, diff --git a/src/dftd_eeq.cpp b/src/dftd_eeq.cpp index 13fd734..80afda2 100644 --- a/src/dftd_eeq.cpp +++ b/src/dftd_eeq.cpp @@ -129,6 +129,21 @@ static const double pi = 3.1415926535897932384626433832795029; static const double sqrtpi = std::sqrt(pi); static const double sqrt2pi = std::sqrt(2.0 / pi); +int get_charges( + const TMolecule &mol, + const TMatrix &dist, + const int charge, + const double cutoff, + TVector &q, + TMatrix &dqdr, + bool lgrad +) { + TIVector realIdx; + initializeRealIdx(mol.NAtoms, realIdx); + + return get_charges(mol, realIdx, dist, charge, cutoff, q, dqdr, lgrad); +}; + int get_charges( const TMolecule &mol, const TIVector &realIdx, diff --git a/src/dftd_ncoord.cpp b/src/dftd_ncoord.cpp index a0272d4..a6cf431 100644 --- a/src/dftd_ncoord.cpp +++ b/src/dftd_ncoord.cpp @@ -234,6 +234,9 @@ static const double hlfosqrtpi = 1.0 / 1.7724538509055159; // Maximum CN (not strictly obeyed) static const double cn_max = 8.0; +/////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// + int calc_distances( const TMolecule &mol, const TIVector &realIdx, @@ -259,7 +262,31 @@ int calc_distances( } return EXIT_SUCCESS; -} +}; + +void initializeRealIdx(int nat, TVector &realIdx) { + realIdx.NewVec(nat); + for (int i = 0; i < nat; ++i) { + realIdx(i) = i; + } +}; + +/////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// + +int get_ncoord_erf( + const TMolecule &mol, + const TMatrix &dist, + const double cutoff, + TVector &cn, + TMatrix &dcndr, + bool lgrad +) { + TIVector realIdx; + initializeRealIdx(mol.NAtoms, realIdx); + + return get_ncoord_erf(mol, realIdx, dist, cutoff, cn, dcndr, lgrad); +}; int get_ncoord_erf( const TMolecule &mol, @@ -285,20 +312,7 @@ int get_ncoord_erf( return EXIT_SUCCESS; }; -int get_ncoord_d4( - const TMolecule &mol, - const TIVector &realIdx, - const TMatrix &dist, - const double cutoff, - TVector &cn, - TMatrix &dcndr, - bool lgrad -) { - if (lgrad) return dncoord_d4(mol, realIdx, dist, cutoff, cn, dcndr); - return ncoord_d4(mol, realIdx, dist, cutoff, cn); -}; - -int ncoord_d4( +int ncoord_erf( const TMolecule &mol, const TIVector &realIdx, const TMatrix &dist, @@ -306,15 +320,12 @@ int ncoord_d4( TVector &cn ) { double r = 0.0, rcovij = 0.0, rr = 0.0; - double den = 0.0; double countf = 0.0; - int izp, jzp; for (int i = 0, ii = 0; i != mol.NAtoms; i++) { ii = realIdx(i); if (ii < 0) continue; - izp = mol.ATNO(i); for (int j = 0, jj = 0; j != i; j++) { jj = realIdx(j); if (jj < 0) continue; @@ -322,20 +333,18 @@ int ncoord_d4( r = dist(ii, jj); if (r > cutoff) continue; - jzp = mol.ATNO(j); - rcovij = rad[izp] + rad[jzp]; + rcovij = rad[mol.ATNO(i)] + rad[mol.ATNO(j)]; rr = r / rcovij; - den = k4 * exp(-pow((fabs(en[izp] - en[jzp]) + k5), 2) / k6); - countf = den * erf_count(kn, rr); - + countf = erf_count(kn, rr); cn(ii) += countf; cn(jj) += countf; } } + return EXIT_SUCCESS; } -int dncoord_d4( +int dncoord_erf( const TMolecule &mol, const TIVector &realIdx, const TMatrix &dist, @@ -345,14 +354,12 @@ int dncoord_d4( ) { double r = 0.0, rcovij = 0.0, rr = 0.0; double rx = 0.0, ry = 0.0, rz = 0.0; - double countf = 0.0, dcountf = 0.0, den = 0.0; - int izp, jzp; + double countf = 0.0, dcountf = 0.0; for (int i = 0, ii = 0; i != mol.NAtoms; i++) { ii = realIdx(i); if (ii < 0) continue; - izp = mol.ATNO(i); for (int j = 0, jj = 0; j != i; j++) { jj = realIdx(j); if (jj < 0) continue; @@ -360,37 +367,70 @@ int dncoord_d4( r = dist(ii, jj); if (r > cutoff) continue; - jzp = mol.ATNO(j); rx = (mol.CC(j, 0) - mol.CC(i, 0)) / r; ry = (mol.CC(j, 1) - mol.CC(i, 1)) / r; rz = (mol.CC(j, 2) - mol.CC(i, 2)) / r; - rcovij = rad[izp] + rad[jzp]; + rcovij = rad[mol.ATNO(i)] + rad[mol.ATNO(j)]; rr = r / rcovij; - den = k4 * exp(-pow((fabs(en[izp] - en[jzp]) + k5), 2) / k6); - countf = den * erf_count(kn, rr); + + countf = erf_count(kn, rr); cn(ii) += countf; cn(jj) += countf; - dcountf = den * derf_count(kn, rr) / rcovij; - dcndr(3 * jj, jj) += dcountf * rx; - dcndr(3 * jj + 1, jj) += dcountf * ry; - dcndr(3 * jj + 2, jj) += dcountf * rz; - dcndr(3 * jj, ii) = dcountf * rx; - dcndr(3 * jj + 1, ii) = dcountf * ry; - dcndr(3 * jj + 2, ii) = dcountf * rz; - dcndr(3 * ii, jj) = -dcountf * rx; - dcndr(3 * ii + 1, jj) = -dcountf * ry; - dcndr(3 * ii + 2, jj) = -dcountf * rz; - dcndr(3 * ii, ii) += -dcountf * rx; - dcndr(3 * ii + 1, ii) += -dcountf * ry; - dcndr(3 * ii + 2, ii) += -dcountf * rz; + dcountf = derf_count(kn, rr) / rcovij; + dcndr(jj, 3 * jj) += dcountf * rx; + dcndr(jj, 3 * jj + 1) += dcountf * ry; + dcndr(jj, 3 * jj + 2) += dcountf * rz; + + dcndr(jj, 3 * ii) += dcountf * rx; + dcndr(jj, 3 * ii + 1) += dcountf * ry; + dcndr(jj, 3 * ii + 2) += dcountf * rz; + + dcndr(ii, 3 * jj) -= dcountf * rx; + dcndr(ii, 3 * jj + 1) -= dcountf * ry; + dcndr(ii, 3 * jj + 2) -= dcountf * rz; + + dcndr(ii, 3 * ii) -= dcountf * rx; + dcndr(ii, 3 * ii + 1) -= dcountf * ry; + dcndr(ii, 3 * ii + 2) -= dcountf * rz; } } + return EXIT_SUCCESS; } -int ncoord_erf( +/////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// + +int get_ncoord_d4( + const TMolecule &mol, + const TMatrix &dist, + const double cutoff, + TVector &cn, + TMatrix &dcndr, + bool lgrad +) { + TIVector realIdx; + initializeRealIdx(mol.NAtoms, realIdx); + + return get_ncoord_d4(mol, realIdx, dist, cutoff, cn, dcndr, lgrad); +}; + +int get_ncoord_d4( + const TMolecule &mol, + const TIVector &realIdx, + const TMatrix &dist, + const double cutoff, + TVector &cn, + TMatrix &dcndr, + bool lgrad +) { + if (lgrad) return dncoord_d4(mol, realIdx, dist, cutoff, cn, dcndr); + return ncoord_d4(mol, realIdx, dist, cutoff, cn); +}; + +int ncoord_d4( const TMolecule &mol, const TIVector &realIdx, const TMatrix &dist, @@ -398,12 +438,15 @@ int ncoord_erf( TVector &cn ) { double r = 0.0, rcovij = 0.0, rr = 0.0; + double den = 0.0; double countf = 0.0; + int izp, jzp; for (int i = 0, ii = 0; i != mol.NAtoms; i++) { ii = realIdx(i); if (ii < 0) continue; + izp = mol.ATNO(i); for (int j = 0, jj = 0; j != i; j++) { jj = realIdx(j); if (jj < 0) continue; @@ -411,18 +454,20 @@ int ncoord_erf( r = dist(ii, jj); if (r > cutoff) continue; - rcovij = rad[mol.ATNO(i)] + rad[mol.ATNO(j)]; + jzp = mol.ATNO(j); + rcovij = rad[izp] + rad[jzp]; rr = r / rcovij; - countf = erf_count(kn, rr); + den = k4 * exp(-pow((fabs(en[izp] - en[jzp]) + k5), 2) / k6); + countf = den * erf_count(kn, rr); + cn(ii) += countf; cn(jj) += countf; } } - return EXIT_SUCCESS; } -int dncoord_erf( +int dncoord_d4( const TMolecule &mol, const TIVector &realIdx, const TMatrix &dist, @@ -432,12 +477,14 @@ int dncoord_erf( ) { double r = 0.0, rcovij = 0.0, rr = 0.0; double rx = 0.0, ry = 0.0, rz = 0.0; - double countf = 0.0, dcountf = 0.0; + double countf = 0.0, dcountf = 0.0, den = 0.0; + int izp, jzp; for (int i = 0, ii = 0; i != mol.NAtoms; i++) { ii = realIdx(i); if (ii < 0) continue; + izp = mol.ATNO(i); for (int j = 0, jj = 0; j != i; j++) { jj = realIdx(j); if (jj < 0) continue; @@ -445,39 +492,39 @@ int dncoord_erf( r = dist(ii, jj); if (r > cutoff) continue; + jzp = mol.ATNO(j); rx = (mol.CC(j, 0) - mol.CC(i, 0)) / r; ry = (mol.CC(j, 1) - mol.CC(i, 1)) / r; rz = (mol.CC(j, 2) - mol.CC(i, 2)) / r; - rcovij = rad[mol.ATNO(i)] + rad[mol.ATNO(j)]; + rcovij = rad[izp] + rad[jzp]; rr = r / rcovij; - - countf = erf_count(kn, rr); + den = k4 * exp(-pow((fabs(en[izp] - en[jzp]) + k5), 2) / k6); + countf = den * erf_count(kn, rr); cn(ii) += countf; cn(jj) += countf; - dcountf = derf_count(kn, rr) / rcovij; - dcndr(jj, 3 * jj) += dcountf * rx; - dcndr(jj, 3 * jj + 1) += dcountf * ry; - dcndr(jj, 3 * jj + 2) += dcountf * rz; - - dcndr(jj, 3 * ii) += dcountf * rx; - dcndr(jj, 3 * ii + 1) += dcountf * ry; - dcndr(jj, 3 * ii + 2) += dcountf * rz; - - dcndr(ii, 3 * jj) -= dcountf * rx; - dcndr(ii, 3 * jj + 1) -= dcountf * ry; - dcndr(ii, 3 * jj + 2) -= dcountf * rz; - - dcndr(ii, 3 * ii) -= dcountf * rx; - dcndr(ii, 3 * ii + 1) -= dcountf * ry; - dcndr(ii, 3 * ii + 2) -= dcountf * rz; + dcountf = den * derf_count(kn, rr) / rcovij; + dcndr(3 * jj, jj) += dcountf * rx; + dcndr(3 * jj + 1, jj) += dcountf * ry; + dcndr(3 * jj + 2, jj) += dcountf * rz; + dcndr(3 * jj, ii) = dcountf * rx; + dcndr(3 * jj + 1, ii) = dcountf * ry; + dcndr(3 * jj + 2, ii) = dcountf * rz; + dcndr(3 * ii, jj) = -dcountf * rx; + dcndr(3 * ii + 1, jj) = -dcountf * ry; + dcndr(3 * ii + 2, jj) = -dcountf * rz; + dcndr(3 * ii, ii) += -dcountf * rx; + dcndr(3 * ii + 1, ii) += -dcountf * ry; + dcndr(3 * ii + 2, ii) += -dcountf * rz; } } - return EXIT_SUCCESS; } +/////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// + double erf_count(double k, double rr) { return 0.5 * (1.0 + erf(-k * (rr - 1.0))); }