Skip to content

Commit

Permalink
reimplement extra UFF
Browse files Browse the repository at this point in the history
Signed-off-by: Conrad Hübler <[email protected]>
  • Loading branch information
conradhuebler committed Mar 5, 2024
1 parent a4cb930 commit a1d8d55
Show file tree
Hide file tree
Showing 9 changed files with 98 additions and 47 deletions.
1 change: 1 addition & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,7 @@ set(curcuma_core_SRC

add_executable(curcuma
src/main.cpp
src/core/forcefieldgenerator.h src/core/forcefieldgenerator.cpp

)

Expand Down
7 changes: 3 additions & 4 deletions src/core/eigen_uff.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ double UFFThread::Distance(double x1, double x2, double y1, double y2, double z1

double UFFThread::BondEnergy(double distance, double r, double kij, double D_ij)
{
double energy = (0.25 * kij * (distance - r) * (distance - r)) * m_final_factor * m_bond_scaling;
double energy = (0.5 * kij * (distance - r) * (distance - r)) * m_final_factor * m_bond_scaling;
if (isnan(energy))
return 0;
else
Expand All @@ -106,7 +106,7 @@ double UFFThread::CalculateBondStretching()
Matrix derivate;
double r0 = BondStretching(x, y, derivate, m_CalculateGradient);

energy += (0.25 * bond.kij * (r0 - bond.r0) * (r0 - bond.r0)) * m_final_factor * m_bond_scaling;
energy += (0.5 * bond.kij * (r0 - bond.r0) * (r0 - bond.r0)) * m_final_factor * m_bond_scaling;
if (m_CalculateGradient) {
if (m_calc_gradient == 0) {
double diff = (bond.kij) * (r0 - bond.r0) * m_final_factor * m_bond_scaling;
Expand Down Expand Up @@ -167,7 +167,7 @@ double UFFThread::CalculateAngleBending()
Matrix derivate;
double costheta = AngleBending(atom_i, atom_j, atom_k, derivate, m_CalculateGradient);
double e = (angle.kijk * (angle.C0 + angle.C1 * costheta + angle.C2 * (2 * costheta * costheta - 1))) * m_final_factor * m_angle_scaling;

energy += e;
if (m_CalculateGradient) {
if (m_calc_gradient == 0) {
double sintheta = sin(acos(costheta));
Expand Down Expand Up @@ -396,7 +396,6 @@ double UFFThread::FullInversion(const int& i, const int& j, const int& k, const
Eigen::Vector3d atom_j = Position(j);
Eigen::Vector3d atom_k = Position(k);
Eigen::Vector3d atom_l = Position(l);

energy += Inversion(atom_i, atom_j, atom_k, atom_l, d_forceConstant, C0, C1, C2);
if (m_CalculateGradient) {
if (m_calc_gradient == 0) {
Expand Down
4 changes: 4 additions & 0 deletions src/core/energycalculator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -232,7 +232,10 @@ void EnergyCalculator::setMolecule(const Molecule& molecule)
ff.setMolecule(molecule);
ff.Generate();
json parameters = ff.getParameter();
// std::ofstream parameterfile("uff.json");
// parameterfile << parameters;
m_forcefield->setParameter(parameters);
m_forcefield->setAtomCount(molecule.AtomCount());
// m_forcefield->setMolecule(atoms, geom);
// m_forcefield->Initialise();

Expand Down Expand Up @@ -396,6 +399,7 @@ void EnergyCalculator::CalculateFF(bool gradient, bool verbose)
m_energy = m_forcefield->Calculate(gradient, verbose);
if (gradient) {
m_gradient = m_forcefield->Gradient();
// m_gradient = m_forcefield->NumGrad();
}
}

Expand Down
30 changes: 27 additions & 3 deletions src/core/forcefield.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ ForceField::ForceField(const json& controller)
{
m_threadpool = new CxxThreadPool();
m_threadpool->setProgressBar(CxxThreadPool::ProgressBarType::None);
m_threads = 16;
}

void ForceField::UpdateGeometry(const Matrix& geometry)
Expand Down Expand Up @@ -194,6 +195,29 @@ void ForceField::AutoRanges()
thread->addEQ(m_EQs[j]);
}
}

Eigen::MatrixXd ForceField::NumGrad()
{
Eigen::MatrixXd gradient = Eigen::MatrixXd::Zero(m_natoms, 3);

double dx = 1e-6; // m_d;
// bool g = m_CalculateGradient;
// m_CalculateGradient = false;
double E1, E2;
for (int i = 0; i < m_natoms; ++i) {
for (int j = 0; j < 3; ++j) {
m_geometry(i, j) += dx;
E1 = Calculate(false, false);
m_geometry(i, j) -= 2 * dx;
E2 = Calculate(false, false);
gradient(i, j) = (E1 - E2) / (2 * dx);
m_geometry(i, j) += dx;
}
}
// m_CalculateGradient = g;
return gradient;
}

double ForceField::Calculate(bool gradient, bool verbose)
{
m_gradient = Eigen::MatrixXd::Zero(m_geometry.rows(), 3);
Expand Down Expand Up @@ -225,19 +249,19 @@ double ForceField::Calculate(bool gradient, bool verbose)
inversion_energy += m_stored_threads[i]->InversionEnergy();
vdw_energy += m_stored_threads[i]->VdWEnergy();
rep_energy += m_stored_threads[i]->RepEnergy();
eq_energy += m_stored_threads[i]->RepEnergy();
// eq_energy += m_stored_threads[i]->RepEnergy();

m_gradient += m_stored_threads[i]->Gradient();
}

energy = bond_energy + angle_energy + dihedral_energy + inversion_energy + vdw_energy;
energy = bond_energy + angle_energy + dihedral_energy + inversion_energy + vdw_energy + rep_energy + eq_energy;
if (verbose) {
std::cout << "Total energy " << energy << " Eh. Sum of " << std::endl
<< "Bond Energy " << bond_energy << " Eh" << std::endl
<< "Angle Energy " << angle_energy << " Eh" << std::endl
<< "Dihedral Energy " << dihedral_energy << " Eh" << std::endl
<< "Inversion Energy " << inversion_energy << " Eh" << std::endl
<< "Nonbonded Energy " << vdw_energy << " Eh" << std::endl
<< "Nonbonded Energy " << vdw_energy + rep_energy << " Eh" << std::endl
<< "D3 Energy " << d3_energy << " Eh" << std::endl
<< "D4 Energy " << d4_energy << " Eh" << std::endl
<< "HBondCorrection " << h4_energy << " Eh" << std::endl
Expand Down
2 changes: 2 additions & 0 deletions src/core/forcefield.h
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ class ForceField {
ForceField(const json& controller);
~ForceField();

inline void setAtomCount(int atom) { m_natoms = atom; }
void UpdateGeometry(const Matrix& geometry);
inline void UpdateGeometry(const double* coord);
inline void UpdateGeometry(const std::vector<std::array<double, 3>>& geometry);
Expand All @@ -63,6 +64,7 @@ class ForceField {

void setParameter(const json& parameter);
void setParameterFile(const std::string& file);
Eigen::MatrixXd NumGrad();

private:
void AutoRanges();
Expand Down
9 changes: 5 additions & 4 deletions src/core/forcefieldfunctions.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@

#pragma once

#include "src/core/global.h"
#include "src/core/qmdff_par.h"
#include "src/core/uff_par.h"

Expand Down Expand Up @@ -69,7 +70,7 @@ inline Eigen::Vector3d NormalVector(const Eigen::Vector3d& i, const Eigen::Vecto
{
return (j - i).cross(j - k);
}
/*

inline double Dihedral(const Eigen::Vector3d& i, const Eigen::Vector3d& j, const Eigen::Vector3d& k, const Eigen::Vector3d& l, double V, double n, double phi0)
{
Eigen::Vector3d nijk = NormalVector(i, j, k);
Expand All @@ -80,12 +81,12 @@ inline double Dihedral(const Eigen::Vector3d& i, const Eigen::Vector3d& j, const
Eigen::Vector3d ji = j - i;
double sign = (-1 * ji).dot(njkl) < 0 ? -1 : 1;
double phi = pi + sign * acos(dotpr / (n_ijk * n_jkl));
double energy = (1 / 2.0 * V * (1 - cos(n * phi0) * cos(n * phi))) * m_final_factor * m_dihedral_scaling;
if (isnan(energy))
double energy = (1 / 2.0 * V * (1 - cos(n * phi0) * cos(n * phi)));
if (std::isnan(energy))
return 0;
else
return energy;
} */
}
}

namespace QMDFF {
Expand Down
64 changes: 41 additions & 23 deletions src/core/forcefieldgenerator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ void ForceFieldGenerator::Generate(const std::vector<std::pair<int, int>>& forme
}
AssignUffAtomTypes();
// if (m_rings)
m_identified_rings = Topology::FindRings(m_stored_bonds, m_atom_types.size());
// m_identified_rings = Topology::FindRings(m_stored_bonds, m_atom_types.size());

setBonds(bonds);

Expand Down Expand Up @@ -143,7 +143,7 @@ void ForceFieldGenerator::setBonds(const TContainer& bonds)
else
bond_order = 1;
double r0_ij = UFFBondRestLength(bond[0], bond[1], bond_order);
uffbond["r_ij"] = r0_ij;
uffbond["r0_ij"] = r0_ij;
double cZi = UFFParameters[m_atom_types[bond[0]]][cZ];
double cZj = UFFParameters[m_atom_types[bond[1]]][cZ];
uffbond["fc"] = 0.5 * m_uff_bond_force * cZi * cZj / (r0_ij * r0_ij * r0_ij);
Expand All @@ -160,8 +160,8 @@ void ForceFieldGenerator::setBonds(const TContainer& bonds)
if (t == j)
continue;
json uffangle = AngleJson;
uffangle["i"] = i;
uffangle["j"] = std::min(t, j);
uffangle["j"] = i;
uffangle["i"] = std::min(t, j);
uffangle["k"] = std::max(j, t);

// angels.insert({ std::min(t, j), i, std::max(j, t) });
Expand All @@ -177,9 +177,9 @@ void ForceFieldGenerator::setBonds(const TContainer& bonds)
if (t == i)
continue;
json uffangle = AngleJson;
uffangle["i"] = i;
uffangle["j"] = std::min(t, j);
uffangle["k"] = std::max(j, t);
uffangle["j"] = j;
uffangle["i"] = std::min(t, i);
uffangle["k"] = std::max(i, t);
if (std::find(m_angles.begin(), m_angles.end(), uffangle) == m_angles.end())
m_angles.push_back(uffangle);

Expand All @@ -192,9 +192,9 @@ void ForceFieldGenerator::setBonds(const TContainer& bonds)
if (k == i || k == j || k == l || i == j || i == l || j == l)
continue;
json uffdihedral = DihedralJson;
uffdihedral["i"] = i;
uffdihedral["j"] = j;
uffdihedral["k"] = k;
uffdihedral["i"] = k;
uffdihedral["j"] = i;
uffdihedral["k"] = j;
uffdihedral["l"] = l;
if (std::find(m_dihedrals.begin(), m_dihedrals.end(), uffdihedral) == m_dihedrals.end()) {
m_dihedrals.push_back(uffdihedral);
Expand Down Expand Up @@ -340,16 +340,16 @@ void ForceFieldGenerator::setInversions()
double C2 = 0.0;
double f = pi / 180.0;
double kijkl = 0;
if (6 <= m_atom_types[i] && m_atom_types[i] <= 8) {
if (6 <= m_molecule.Atoms()[i] && m_molecule.Atoms()[i] <= 8) {
C0 = 1.0;
C1 = -1.0;
C2 = 0.0;
kijkl = 6;
if (m_atom_types[j] == 8 || m_atom_types[k] == 8 || m_atom_types[l] == 8)
if (m_molecule.Atoms()[j] == 8 || m_molecule.Atoms()[k] == 8 || m_molecule.Atoms()[l] == 8)
kijkl = 50;
} else {
double w0 = pi / 180.0;
switch (m_atom_types[i]) {
switch (m_molecule.Atoms()[i]) {
// if the central atom is phosphorous
case 15:
w0 *= 84.4339;
Expand Down Expand Up @@ -701,50 +701,68 @@ void ForceFieldGenerator::writeUFFFile(const std::string& file) const
json ForceFieldGenerator::Bonds() const
{
json bonds;
int index = 0;

for (int i = 0; i < m_bonds.size(); ++i) {
if (m_bonds[i]["type"] != 0)
bonds[i] = m_bonds[i];
if (m_bonds[i]["type"] != 0) {
bonds[index] = m_bonds[i];
index++;
}
}
return bonds;
}

json ForceFieldGenerator::Angles() const
{
json angles;
int index = 0;

for (int i = 0; i < m_angles.size(); ++i) {
if (m_angles[i]["type"] != 0)
angles[i] = m_angles[i];
if (m_angles[i]["type"] != 0) {
angles[index] = m_angles[i];
index++;
}
}
return angles;
}

json ForceFieldGenerator::Dihedrals() const
{
json dihedrals;
int index = 0;

for (int i = 0; i < m_dihedrals.size(); ++i) {
if (m_dihedrals[i]["type"] != 0)
dihedrals[i] = m_dihedrals[i];
if (m_dihedrals[i]["type"] != 0) {
dihedrals[index] = m_dihedrals[i];
index++;
}
}
return dihedrals;
}

json ForceFieldGenerator::Inversions() const
{
json inversions;
int index = 0;
for (int i = 0; i < m_inversions.size(); ++i) {
if (m_inversions[i]["type"] != 0)
inversions[i] = m_inversions[i];
if (m_inversions[i]["type"] != 0 && m_inversions[i]["fc"] != 0) {
inversions[index] = m_inversions[i];
index++;
}
}
return inversions;
}

json ForceFieldGenerator::vdWs() const
{
json vdws;
int index = 0;

for (int i = 0; i < m_vdws.size(); ++i) {
if (m_vdws[i]["type"] != 0)
vdws[i] = m_vdws[i];
if (m_vdws[i]["type"] != 0) {
vdws[index] = m_vdws[i];
index++;
}
}
return vdws;
}
2 changes: 1 addition & 1 deletion src/core/forcefieldgenerator.h
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,7 @@ class ForceFieldGenerator {
std::vector<int> m_atom_types, m_coordination;
std::vector<std::set<int>> m_ignored_vdw;
std::vector<json> m_bonds, m_angles, m_dihedrals, m_inversions, m_vdws, m_eqs;
double m_uff_bond_force = 1, m_uff_angle_force = 1, m_scaling = 1.4;
double m_uff_bond_force = 664.12, m_uff_angle_force = 664.12, m_scaling = 1.4;
double m_au = 1;

int m_ff_type = 1;
Expand Down
26 changes: 14 additions & 12 deletions src/core/forcefieldthread.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -135,15 +135,13 @@ void ForceFieldThread::CalculateUFFAngleContribution()
Matrix derivate;
double costheta = UFF::AngleBending(i, j, k, derivate, m_calculate_gradient);
m_angle_energy += (angle.fc * (angle.C0 + angle.C1 * costheta + angle.C2 * (2 * costheta * costheta - 1))) * m_final_factor * m_angle_scaling;

// std::cout << (angle.fc * (angle.C0 + angle.C1 * costheta + angle.C2 * (2 * costheta * costheta - 1))) * m_final_factor * m_angle_scaling << " ";
if (m_calculate_gradient) {
if (m_calc_gradient == 0) {
double sintheta = sin(acos(costheta));
double dEdtheta = -angle.fc * sintheta * (angle.C1 + 4 * angle.C2 * costheta) * m_final_factor * m_angle_scaling;
m_gradient.row(angle.i) += dEdtheta * derivate.row(0);
m_gradient.row(angle.j) += dEdtheta * derivate.row(1);
m_gradient.row(angle.k) += dEdtheta * derivate.row(2);
}
double sintheta = sin(acos(costheta));
double dEdtheta = -angle.fc * sintheta * (angle.C1 + 4 * angle.C2 * costheta) * m_final_factor * m_angle_scaling;
m_gradient.row(angle.i) += dEdtheta * derivate.row(0);
m_gradient.row(angle.j) += dEdtheta * derivate.row(1);
m_gradient.row(angle.k) += dEdtheta * derivate.row(2);
}
}
}
Expand All @@ -159,7 +157,9 @@ void ForceFieldThread::CalculateUFFDihedralContribution()
Eigen::Vector3d eins = { 1.0, 1.0, 1.0 };
Eigen::Vector3d nijk = UFF::NormalVector(i, j, k);
Eigen::Vector3d njkl = UFF::NormalVector(j, k, l);

Eigen::Vector3d dx = { m_d, 0, 0 };
Eigen::Vector3d dy = { 0, m_d, 0 };
Eigen::Vector3d dz = { 0, 0, m_d };
double n_ijk = (nijk).norm();
double n_jkl = (njkl).norm();
double dotpr = nijk.dot(njkl);
Expand All @@ -168,16 +168,18 @@ void ForceFieldThread::CalculateUFFDihedralContribution()
double sign = (-1 * ji).dot(njkl) < 0 ? -1 : 1;
double phi = pi + sign * acos(dotpr / (n_ijk * n_jkl));
double sinphi = sin(phi);
double tmp_energy = (1 / 2.0 * dihedral.V * (1 - cos(dihedral.n * dihedral.phi0) * cos(dihedral.n * dihedral.phi0))) * m_final_factor * m_dihedral_scaling;
// Dihedral(i, j, k, l, dihedral.V, dihedral.n, dihedral.phi0) * m_final_factor * m_dihedral_scaling;
double tmp_energy = (1 / 2.0 * dihedral.V * (1 - cos(dihedral.n * dihedral.phi0) * cos(dihedral.n * phi))) * m_final_factor * m_dihedral_scaling;
// std::cout << tmp_energy << ": ";
// m_dihedral_energy +=UFF::Dihedral(i, j, k, l, dihedral.V, dihedral.n, dihedral.phi0) * m_final_factor * m_dihedral_scaling;
if (isnan(tmp_energy))
continue;
m_dihedral_energy += tmp_energy;
if (m_calculate_gradient) {

Eigen::Vector3d kj = k - j;
Eigen::Vector3d kl = k - l;
double tmp = 0;
double dEdphi = (1 / 2.0 * dihedral.V * dihedral.n * (cos(dihedral.n * dihedral.phi0) * sin(dihedral.n * phi)));
double dEdphi = (1 / 2.0 * dihedral.V * dihedral.n * (cos(dihedral.n * dihedral.phi0) * sin(dihedral.n * phi))) * m_final_factor * m_dihedral_scaling;
if (isnan(dEdphi))
continue;

Expand Down

0 comments on commit a1d8d55

Please sign in to comment.