From 234c0360c3062dfc3d9e5ce0b7fadcd4891b10b3 Mon Sep 17 00:00:00 2001 From: Gerd Gehrisch Date: Thu, 5 Sep 2024 19:45:09 +0200 Subject: [PATCH 1/9] main: clean up dipole MD: implement dipole calculation --- src/capabilities/simplemd.cpp | 46 ++++++++++++++++++++--- src/capabilities/simplemd.h | 2 +- src/core/molecule.cpp | 1 + src/main.cpp | 70 +++++------------------------------ 4 files changed, 51 insertions(+), 68 deletions(-) diff --git a/src/capabilities/simplemd.cpp b/src/capabilities/simplemd.cpp index 30d15d1..887772f 100644 --- a/src/capabilities/simplemd.cpp +++ b/src/capabilities/simplemd.cpp @@ -324,8 +324,8 @@ bool SimpleMD::Initialise() throw 404; } LoadRestartInformation(md); - m_restart = true; - } else if (!m_norestart) + + } else if (!m_restart) LoadRestartInformation(); if (m_molecule.AtomCount() == 0) @@ -1115,12 +1115,46 @@ void SimpleMD::start() } } -/////////// Dipole calc - + /////////// Dipole calc + //def scaling coefficient + std::vector dipole_scale; + //set coefficients some values + for (auto i = 0; i < m_natoms; i++) { + dipole_scale.push_back(1); + } + dipole_scale = {-0.0850725,1.2296, -0.490071,-0.389245,-0.41952,0.853822,-0.0850725,1.2296, -0.490071,-0.389245,-0.41952,0.853822}; + + json blob; + //calc partialCharge with gnf2-xtb + EnergyCalculator interface("gfn2", blob); // set method to gfn2-xtb + interface.setMolecule(m_molecule); // set molecule for calc + interface.CalculateEnergy(false, true); // calc energy and charges and dipole moment + m_molecule.setPartialCharges(interface.Charges()); // calc Partial Charges and give it to mol + m_molecule.setDipole(interface.Dipole()*au); + + //calc Dipoles from partial Charges and Scaling + auto dipoles = m_molecule.CalculateDipoleMoments(dipole_scale); + int i=0; + Position dipole_sum = {0,0,0}; + for (auto dipole : dipoles) { + //Calc Dipole of System from fragments + dipole_sum[0] += dipole[0]; + dipole_sum[1] += dipole[1]; + dipole_sum[2] += dipole[2]; + + std::cout << "Dipole (Fragment" << i << "): " + << dipole[0] << " " + << dipole[1] << " " + << dipole[2] << " D = " + << dipole.norm() << " " + << std::endl; + i++; + } + std::cout << "Dipole Sum: " << dipole_sum.norm() << " XTB2-Dipol: " << m_molecule.getDipole().norm() << std::endl; + /////////// Dipole calc -/////////// Dipole calc if (m_step % m_dump == 0) { bool write = WriteGeometry(); if (write) { @@ -2084,7 +2118,7 @@ void SimpleMD::CSVR() static std::default_random_engine rd{}; static std::mt19937 gen{ rd() }; static std::normal_distribution<> d{ 0, 1 }; - static std::chi_squared_distribution dchi{ m_dof }; + static std::chi_squared_distribution dchi{ static_cast(m_dof) }; double R = d(gen); double SNf = dchi(gen); diff --git a/src/capabilities/simplemd.h b/src/capabilities/simplemd.h index bde0e7e..7ddfcbc 100644 --- a/src/capabilities/simplemd.h +++ b/src/capabilities/simplemd.h @@ -1,5 +1,5 @@ /* - * + * * Copyright (C) 2023 - 2024 Conrad Hübler * * This program is free software: you can redistribute it and/or modify diff --git a/src/core/molecule.cpp b/src/core/molecule.cpp index 6aac8ae..7b692ab 100644 --- a/src/core/molecule.cpp +++ b/src/core/molecule.cpp @@ -704,6 +704,7 @@ Molecule Molecule::getFragmentMolecule(int fragment) const for (auto atom : atoms) { result.addPair(Atom(atom)); } + //result.setPartialCharges(m_charges[atoms]); return result; } Geometry Molecule::getGeometry(bool protons) const diff --git a/src/main.cpp b/src/main.cpp index 3fe9f09..d2bafe5 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -917,7 +917,8 @@ int main(int argc, char **argv) { return 0; } FileIterator file(argv[2]); - Position target_dipole; + + // TODO: if -md then do first molecular dynamic to generate some confomers, then fit double target = 0, threshold = 1e-1, initial = 3, dx = 5e-1; // dec bool target_set = false; @@ -961,71 +962,18 @@ int main(int argc, char **argv) { mol.setPartialCharges(interface.Charges()); // calc Partial Charges and give it to mol auto charges = interface.Charges(); // dec and init charges mol.setDipole(interface.Dipole() * au); - auto dipole_moment = interface.Dipole() * au; // get dipole moment from gfn2-xtb methode in au - /*std::cout << mol.AtomCount() << "\n" + /* Output Dipole from XTB2 + *std::cout << mol.AtomCount() << "\n" << "Dipole " - << dipole_moment[0] << " " - << dipole_moment[1] << " " - << dipole_moment[2] << " " - << std::endl; - - for (int i = 0; i < charges.size(); ++i ){ // Output partial charges from gfn2-xtb methode - std::string col = mol.Atom2String(i); - col.pop_back(); - std::cout << col; - std::cout << " "; - std::cout << charges[i] << "\n"; - } - std::cout << std::endl;*/ + << mol.getDipole()[0] << " " + << mol.getDipole()[1] << " " + << mol.getDipole()[2] << " " + << std::endl;*/ conformers.push_back(mol); - mol.appendDipoleFile(file.Basename() + ".dip"); - - /*if (!target_set) { // calc target if not set - target = dipole_moment.norm(); - target_dipole = dipole_moment; - }*/ - /*std::cout << "Target dipole moment [eA, ea or D?]: " - << target << "\n" - << target_dipole[0] << ", " << target_dipole[1] << ", " << target_dipole[2] << "\n" - << std::endl; - - auto dipoles = mol.CalculateDipoleMoments();//calc Dipole for every Molecule with partial charges - for (const auto& dipole : dipoles) { - std::cout << std::endl - << "Dipole moment for single molecule [eA]: " << dipole.norm() << "\n" - << dipole[0] << ", " << dipole[1] << ", " << dipole[2] << "\n" - << std::endl; - }*/ - /*auto dipole = mol.CalculateDipoleMoment();//calc Dipole for whole system with partial charges - std::cout << std::endl - << "Dipole moment for whole structure [eA]: " << dipole.norm() << "\n" - << dipole[0] << ", " << dipole[1] << ", " << dipole[2] << "\n" - << std::endl; - std::cout << std::endl; - */ - - /* - auto result = OptimiseDipoleScaling(&conformers, initial); - std::cout << "Final dipole moment [eA]: " << result.first.norm() << "\n" - << result.first[0] << ", " << result.first[1] << ", " << result.first[2] << std::endl; - std::cout << std::endl; - std::cout << std::endl; - - std::cout << "Fitted scalar:\n"; - - double sum = 0; - - for (int i = 0; i < result.second.size(); ++i ) { //(auto i : result.second) - sum += result.second[i]; - std::cout << mol.Atom2String(i).substr(0, 1) - << i + 1 << ": " - << result.second[i] << "\n"; - } - std::cout << std::endl; - std::cout << "mean of scalar: " << sum / mol.AtomCount();*/ } + Vector scaling(mol.AtomCount()); for (int i = 0; i < mol.AtomCount(); ++i) { scaling(i) = 1; From a4d15f16bf71d7489eee2c03c1e865e73729477a Mon Sep 17 00:00:00 2001 From: Gerd Gehrisch Date: Mon, 9 Sep 2024 19:29:47 +0200 Subject: [PATCH 2/9] main: clean up dipole MD: implement dipole calculation --- .../optimiser/OptimiseDipoleScaling.h | 32 ++++++++--------- src/capabilities/simplemd.cpp | 32 ++++++++++++----- src/core/global.h | 2 +- src/core/molecule.cpp | 7 ++-- src/main.cpp | 36 +++++++++++-------- 5 files changed, 66 insertions(+), 43 deletions(-) diff --git a/src/capabilities/optimiser/OptimiseDipoleScaling.h b/src/capabilities/optimiser/OptimiseDipoleScaling.h index a7353c5..c986413 100644 --- a/src/capabilities/optimiser/OptimiseDipoleScaling.h +++ b/src/capabilities/optimiser/OptimiseDipoleScaling.h @@ -124,21 +124,21 @@ inline Vector OptimiseDipoleScaling(const std::vector& conformers, Vec inline Matrix DipoleScalingCalculation(const std::vector& conformers) { - std::vector y; - std::vector F; - auto para_size = conformers[0].AtomCount(); - auto conformer_size = conformers.size(); - Matrix FTF(para_size, para_size); - Vector FTy(para_size); - for (const auto& conformer : conformers) { - y.push_back(conformer.getDipole()); // TODO Einheit überprüfen - F.push_back(conformer.ChargeDistribution()); + std::vector y; //Dipole moments + std::vector F; // Geometry multiplied with partial Charge + const auto para_size = conformers[0].AtomCount(); + const auto conformer_size = conformers.size(); + Matrix FTF = Matrix::Zero(para_size, para_size); + Matrix FTy = Matrix::Zero(para_size, 1); + for (int i = 0; i < conformer_size; ++i) { + y.push_back(conformers[i].getDipole()); // in eA + F.push_back(conformers[i].ChargeDistribution()); } - - for (int i = 0; i < para_size; ++i) { - for (int j = 0; j < para_size; ++j) { - for (auto& k : F) - FTF(i, j) += k(i, 0) * k(j, 0) + k(i, 1) * k(j, 1) + k(i, 2) * k(j, 2); + for (int k = 0; k < conformer_size; ++k) { + for (int i = 0; i < para_size; ++i) { + for (int j = 0; j < para_size; ++j) { + FTF(i, j) += F[k](i, 0) * F[k](j, 0) + F[k](i, 1) * F[k](j, 1) + F[k](i, 2) * F[k](j, 2); + } } } @@ -149,9 +149,7 @@ inline Matrix DipoleScalingCalculation(const std::vector& conformers) } Matrix Theta(para_size, 1); + Theta = FTF.colPivHouseholderQr().solve(FTy); - Theta = FTF.inverse() * FTy; - - // inv(F.t@F)@(F.t@y); return Theta; } \ No newline at end of file diff --git a/src/capabilities/simplemd.cpp b/src/capabilities/simplemd.cpp index 887772f..d2f660b 100644 --- a/src/capabilities/simplemd.cpp +++ b/src/capabilities/simplemd.cpp @@ -1123,7 +1123,12 @@ void SimpleMD::start() for (auto i = 0; i < m_natoms; i++) { dipole_scale.push_back(1); } - dipole_scale = {-0.0850725,1.2296, -0.490071,-0.389245,-0.41952,0.853822,-0.0850725,1.2296, -0.490071,-0.389245,-0.41952,0.853822}; + dipole_scale = {1.56698, +1.35181, +1.51389, +1.52117, +1.50273, +1.46733}; //from -dipole LM json blob; //calc partialCharge with gnf2-xtb @@ -1133,25 +1138,34 @@ void SimpleMD::start() m_molecule.setPartialCharges(interface.Charges()); // calc Partial Charges and give it to mol m_molecule.setDipole(interface.Dipole()*au); + Molecule mol; + //calc Dipoles from partial Charges and Scaling auto dipoles = m_molecule.CalculateDipoleMoments(dipole_scale); int i=0; + Position dipole_sum = {0,0,0}; for (auto dipole : dipoles) { - //Calc Dipole of System from fragments + double charge = 0; + mol = m_molecule.getFragmentMolecule(i); + + //dipole of system dipole_sum[0] += dipole[0]; dipole_sum[1] += dipole[1]; dipole_sum[2] += dipole[2]; - std::cout << "Dipole (Fragment" << i << "): " - << dipole[0] << " " - << dipole[1] << " " - << dipole[2] << " D = " - << dipole.norm() << " " - << std::endl; + std::cout << "Fragment" << i << "\nDipole classic " << " = " << dipole.norm() << std::endl; + std::cout << "p.Charge: " << std::endl; + for (auto p : mol.getPartialCharges()) { + std::cout << p << std::endl; + charge += p; + } + std::cout << "charge: " << charge << std::endl; i++; } - std::cout << "Dipole Sum: " << dipole_sum.norm() << " XTB2-Dipol: " << m_molecule.getDipole().norm() << std::endl; + + std::cout << "Dipole Sum: " << dipole_sum.norm() + << " XTB2-Dipole: " << m_molecule.getDipole().norm() << "\n---------" << std::endl; /////////// Dipole calc diff --git a/src/core/global.h b/src/core/global.h index 1746ce4..52aa487 100644 --- a/src/core/global.h +++ b/src/core/global.h @@ -32,7 +32,7 @@ using json = nlohmann::json; const double pi = 3.14159265359; -const double au = 0.52917721092; +const double au = 0.52917721092; // Angstrom const double amu2au = 1822.8884850; const double kb_Eh = 3.166811e-6; // Hartree const double kb_SI = 1.380649e-23; // SI diff --git a/src/core/molecule.cpp b/src/core/molecule.cpp index 7b692ab..515f8e8 100644 --- a/src/core/molecule.cpp +++ b/src/core/molecule.cpp @@ -698,13 +698,16 @@ void Molecule::LoadMolecule(const Mol* molecule) Molecule Molecule::getFragmentMolecule(int fragment) const { - // Lets make that one day faster, but not today ... + // Let's make that one day faster, but not today ... + // TODO inherit some more properties ... Molecule result; + std::vector pCharges; auto atoms = GetFragments()[fragment]; for (auto atom : atoms) { result.addPair(Atom(atom)); + pCharges.push_back(m_charges[atom]); } - //result.setPartialCharges(m_charges[atoms]); + result.setPartialCharges(pCharges); return result; } Geometry Molecule::getGeometry(bool protons) const diff --git a/src/main.cpp b/src/main.cpp index d2bafe5..bed946c 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -46,6 +46,7 @@ #include #include #include +#include #include #include @@ -950,9 +951,8 @@ int main(int argc, char **argv) { << std::endl;*/ std::vector conformers; - Molecule mol; while (!file.AtEnd()) { // calculation and output dipole moment - mol = file.Next(); // load Molecule + Molecule mol = file.Next(); // load Molecule mol.Center(false); EnergyCalculator interface("gfn2", blob); // set method to gfn2-xtb and give @@ -961,27 +961,21 @@ int main(int argc, char **argv) { mol.setPartialCharges(interface.Charges()); // calc Partial Charges and give it to mol auto charges = interface.Charges(); // dec and init charges - mol.setDipole(interface.Dipole() * au); + mol.setDipole(interface.Dipole() * au); // in eA /* Output Dipole from XTB2 - *std::cout << mol.AtomCount() << "\n" + std::cout << mol.AtomCount() << "\n" << "Dipole " << mol.getDipole()[0] << " " << mol.getDipole()[1] << " " - << mol.getDipole()[2] << " " + << mol.getDipole()[2] << " : " + << mol.getDipole().norm() << "\n" << std::endl;*/ conformers.push_back(mol); + mol.appendDipoleFile(file.Basename() + ".dip"); } - - Vector scaling(mol.AtomCount()); - for (int i = 0; i < mol.AtomCount(); ++i) { - scaling(i) = 1; - } - auto result = OptimiseDipoleScaling(conformers, scaling); - std::cout << "LM-Scaler:\n" - << result << "\n" - << std::endl; + Molecule mol = conformers.at(0); Matrix Theta(mol.AtomCount(), 1); Theta = DipoleScalingCalculation(conformers); @@ -989,6 +983,20 @@ int main(int argc, char **argv) { << Theta << "\n" << std::endl; + auto result = OptimiseDipoleScaling(conformers, Theta); + std::cout << "LM-Scaler:\n" + << result << "\n" + << std::endl; + double r2_LM = 0; + double r2_classic = 0; + + std::cout << "LM : classic" << std::endl; + for (const auto& conformer : conformers) { + r2_LM += std::pow(conformer.CalculateDipoleMoment(result).norm() - conformer.getDipole().norm(), 2); + r2_classic += std::pow(conformer.CalculateDipoleMoment(Theta).norm() -conformer.getDipole().norm(), 2); + } + std::cout << r2_LM << " " << r2_classic << std::endl; + } else if (strcmp(argv[1], "-stride") == 0) { if (argc < 4) { From 4fd20f0da519fe76892f813a8bcb1efa92404713 Mon Sep 17 00:00:00 2001 From: Gerd Gehrisch Date: Mon, 23 Sep 2024 18:08:08 +0200 Subject: [PATCH 3/9] main: clean up dipole MD: implement dipole calculat --- .../optimiser/OptimiseDipoleScaling.h | 44 +++++--------- src/capabilities/simplemd.cpp | 52 +++++++++++----- src/core/molecule.cpp | 1 + src/main.cpp | 60 +++++++------------ 4 files changed, 76 insertions(+), 81 deletions(-) diff --git a/src/capabilities/optimiser/OptimiseDipoleScaling.h b/src/capabilities/optimiser/OptimiseDipoleScaling.h index c986413..9308f6e 100644 --- a/src/capabilities/optimiser/OptimiseDipoleScaling.h +++ b/src/capabilities/optimiser/OptimiseDipoleScaling.h @@ -20,24 +20,15 @@ #pragma once #include -#include #include #include -#include "src/capabilities/optimiser/LevMarDocking.h" -#include "src/core/elements.h" #include "src/core/global.h" #include "src/core/molecule.h" -#include "src/core/pseudoff.h" -#include "src/tools/geometry.h" template - -// Implement argmin x: F(x) = sum_i^N (y_i - f_i(x))**2 -// f_i(x) = sum_j (x*q_j*r_j), N... number of confomere -// r_j=[ [xyz]_1, [xyz]_2, ..., [xyz]_m] m... number of atoms/parameter struct TFunctor { typedef _Scalar Scalar; enum { @@ -50,31 +41,28 @@ struct TFunctor { int m_inputs, m_values; - inline TFunctor(int inputs, int values) + TFunctor(int inputs, int values) : m_inputs(inputs) , m_values(values) - { - } + {} int inputs() const { return m_inputs; } int values() const { return m_values; } }; struct OptDipoleFunctor : TFunctor { - inline OptDipoleFunctor(int inputs, int values) + OptDipoleFunctor(int inputs, int values) : TFunctor(inputs, values) , no_parameter(inputs) - , no_points(values) - { + , no_points(values) { } - inline ~OptDipoleFunctor() = default; - inline int operator()(const Vector& scaling, Eigen::VectorXd& fvec) const - { + ~OptDipoleFunctor() = default; + int operator()(const Vector& scaling, Eigen::VectorXd& fvec) const { + // calculation of residuals for (int i = 0; i < m_conformers.size(); ++i) { auto conf = m_conformers.at(i); fvec(i) = (conf.getDipole() - conf.CalculateDipoleMoment(scaling)).norm(); } - return 0; } int no_parameter; @@ -85,16 +73,14 @@ struct OptDipoleFunctor : TFunctor { int values() const { return no_points; } }; -struct OptDipoleFunctorNumericalDiff : Eigen::NumericalDiff { -}; +struct OptDipoleFunctorNumericalDiff : Eigen::NumericalDiff {}; -inline Vector OptimiseDipoleScaling(const std::vector& conformers, Vector scaling) -{ +inline Vector OptimiseDipoleScaling(const std::vector& conformers, Vector scaling) { OptDipoleFunctor functor(6, conformers.size()); functor.m_conformers = conformers; - Eigen::NumericalDiff numDiff(functor); - Eigen::LevenbergMarquardt> lm(numDiff); + Eigen::NumericalDiff numDiff(functor); + Eigen::LevenbergMarquardt lm(numDiff); /* lm.parameters.factor = config["LevMar_Factor"].toInt(); //step bound for the diagonal shift, is this related to damping parameter, lambda? @@ -134,16 +120,16 @@ inline Matrix DipoleScalingCalculation(const std::vector& conformers) y.push_back(conformers[i].getDipole()); // in eA F.push_back(conformers[i].ChargeDistribution()); } - for (int k = 0; k < conformer_size; ++k) { + for (auto k : F) { for (int i = 0; i < para_size; ++i) { for (int j = 0; j < para_size; ++j) { - FTF(i, j) += F[k](i, 0) * F[k](j, 0) + F[k](i, 1) * F[k](j, 1) + F[k](i, 2) * F[k](j, 2); + FTF(i, j) += k(i, 0) * k(j, 0) + k(i, 1) * k(j, 1) + k(i, 2) * k(j, 2); } } } - for (int j = 0; j < para_size; ++j) { - for (int i = 0; i < conformer_size; ++i) { + for (int i = 0; i < conformer_size; ++i) { + for (int j = 0; j < para_size; ++j) { FTy(j) += y[i](0) * F[i](j, 0) + y[i](1) * F[i](j, 1) + y[i](2) * F[i](j, 2); } } diff --git a/src/capabilities/simplemd.cpp b/src/capabilities/simplemd.cpp index d2f660b..66315b5 100644 --- a/src/capabilities/simplemd.cpp +++ b/src/capabilities/simplemd.cpp @@ -1123,15 +1123,29 @@ void SimpleMD::start() for (auto i = 0; i < m_natoms; i++) { dipole_scale.push_back(1); } - dipole_scale = {1.56698, -1.35181, -1.51389, -1.52117, -1.50273, -1.46733}; //from -dipole LM + dipole_scale = { + 1.16126,//Wasser + 1.44224,//* + 1.44256,//* + 1.56764,//Methanol + 1.35206,//* + 1.51374,//* + 1.52110,//* + 1.50372,//* + 1.46760,//* + 1.61581,//Ethanol + 1.86773,//* + 1.54639,//* + 1.60913,//* + 1.62602,//* + 1.37539,//* + 1.50891,//* + 1.53962,//* + 1.46714//* + }; // from -dipole LM json blob; - //calc partialCharge with gnf2-xtb + // calc partialCharge with gnf2-xtb EnergyCalculator interface("gfn2", blob); // set method to gfn2-xtb interface.setMolecule(m_molecule); // set molecule for calc interface.CalculateEnergy(false, true); // calc energy and charges and dipole moment @@ -1146,7 +1160,7 @@ void SimpleMD::start() Position dipole_sum = {0,0,0}; for (auto dipole : dipoles) { - double charge = 0; + // double frag_charge = 0; mol = m_molecule.getFragmentMolecule(i); //dipole of system @@ -1154,18 +1168,26 @@ void SimpleMD::start() dipole_sum[1] += dipole[1]; dipole_sum[2] += dipole[2]; - std::cout << "Fragment" << i << "\nDipole classic " << " = " << dipole.norm() << std::endl; - std::cout << "p.Charge: " << std::endl; + + //std::cout << "Fragment" << i << std::endl; + std::cout << dipole.norm() << " " << mol.getDipole().norm() << " "; + //std::cout << dipole[0] << " " << dipole[1] << " " << dipole[2] << std::endl; + //std::cout << mol.getDipole()[0] << " " << mol.getDipole()[1] << " " << mol.getDipole()[2] << std::endl; + + /*std::cout << "p.Charge: " << std::endl; for (auto p : mol.getPartialCharges()) { std::cout << p << std::endl; - charge += p; + frag_charge += p; } - std::cout << "charge: " << charge << std::endl; + std::cout << "charge: " << frag_charge << std::endl;*/ i++; } - - std::cout << "Dipole Sum: " << dipole_sum.norm() - << " XTB2-Dipole: " << m_molecule.getDipole().norm() << "\n---------" << std::endl; + Position d = m_molecule.getDipole(); + std::cout << std::endl; + /*std::cout << std::endl; + std::cout << "Dipole Sum: " << dipole_sum.norm() << std::endl << dipole_sum[0] << " " << dipole_sum[1] << " " << dipole_sum[2] << std::endl; + std::cout << "XTB2-Dipole: " << d.norm() << std::endl << d[0] << " " << d[1] << " " << d[2] << std::endl + << "---------" << std::endl;*/ /////////// Dipole calc diff --git a/src/core/molecule.cpp b/src/core/molecule.cpp index 515f8e8..c7072d2 100644 --- a/src/core/molecule.cpp +++ b/src/core/molecule.cpp @@ -937,6 +937,7 @@ std::vector Molecule::CalculateDipoleMoments(const std::vector dipole(2) += m_charges[i] * (m_geometry(i, 2) - pos(2)) * scale; // std::cout << scale << " "; } + // std::cout << std::endl; dipole_moments.push_back(dipole); } diff --git a/src/main.cpp b/src/main.cpp index bed946c..79a2b99 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -917,38 +917,15 @@ int main(int argc, char **argv) { std::cerr << "Please use curcuma to optimise the dipole of molecules as follow:\ncurcuma -dipole molecule.xyz" << std::endl; return 0; } - FileIterator file(argv[2]); - // TODO: if -md then do first molecular dynamic to generate some confomers, then fit + FileIterator file(argv[2]); + // TODO: Add additional arguments... + // TODO: if -md then do first molecular dynamic to generate some conformers, then fit + // TODO: if -scale then calc dipole with scalor and xtb2 + // TODO: if -methode then change methode - double target = 0, threshold = 1e-1, initial = 3, dx = 5e-1; // dec - bool target_set = false; - int maxiter = 10; json blob = controller["dipole"]; // declare blob as json, - if (blob.contains("target")) { - target = blob["target"]; - target_set = true; - } - if (blob.contains("threshold")) { - threshold = blob["threshold"]; - } - if (blob.contains("initial")) { - initial = blob["initial"]; - } - if (blob.contains("maxiter")) { - maxiter = blob["maxiter"]; - } - if (blob.contains("dx")) { - dx = blob["dx"]; - } - /*std::cout << "Parameter: " << "\n" - << "target " << target << "\n" - << "threshold " << threshold << "\n" - << "initial " << initial << "\n" - << "maxiter " << maxiter << "\n" - << "dx " << dx << "\n" - << std::endl;*/ std::vector conformers; while (!file.AtEnd()) { // calculation and output dipole moment @@ -973,29 +950,38 @@ int main(int argc, char **argv) { << std::endl;*/ conformers.push_back(mol); - mol.appendDipoleFile(file.Basename() + ".dip"); + //mol.appendDipoleFile(file.Basename() + ".dip"); } - Molecule mol = conformers.at(0); + Molecule mol = conformers.at(0); // molecule in ground state - Matrix Theta(mol.AtomCount(), 1); - Theta = DipoleScalingCalculation(conformers); + std::cout << "\nxtb2-Dipole: " << mol.getDipole().norm() << std::endl << std::endl; + + Matrix theta (mol.AtomCount(), 1); + theta = DipoleScalingCalculation(conformers); std::cout << "Analytic-Scaler:\n" - << Theta << "\n" + << theta << "\n" + << "Dipole: " << mol.CalculateDipoleMoment(theta).norm() << std::endl << std::endl; - auto result = OptimiseDipoleScaling(conformers, Theta); + + auto result = OptimiseDipoleScaling(conformers, theta); std::cout << "LM-Scaler:\n" << result << "\n" + << "Dipole: " << mol.CalculateDipoleMoment(result).norm() << std::endl << std::endl; double r2_LM = 0; double r2_classic = 0; + double r2_LM_dn = 0; + double r2_classic_dn = 0; - std::cout << "LM : classic" << std::endl; + std::cout << "LM : classic : LM_dn : classic_dn" << std::endl; for (const auto& conformer : conformers) { r2_LM += std::pow(conformer.CalculateDipoleMoment(result).norm() - conformer.getDipole().norm(), 2); - r2_classic += std::pow(conformer.CalculateDipoleMoment(Theta).norm() -conformer.getDipole().norm(), 2); + r2_classic += std::pow(conformer.CalculateDipoleMoment(theta).norm() - conformer.getDipole().norm(), 2); + r2_LM_dn += std::pow((conformer.CalculateDipoleMoment(result) - conformer.getDipole()).norm(), 2); + r2_classic_dn += std::pow((conformer.CalculateDipoleMoment(theta) - conformer.getDipole()).norm(), 2); } - std::cout << r2_LM << " " << r2_classic << std::endl; + std::cout << r2_LM << " : " << r2_classic << " : " << r2_LM_dn << " : " << r2_classic_dn << std::endl; } else if (strcmp(argv[1], "-stride") == 0) { From b3988643dc9b1a5dd2ba673b2f575da9e85cc914 Mon Sep 17 00:00:00 2001 From: Gerd Gehrisch Date: Wed, 2 Oct 2024 00:18:34 +0200 Subject: [PATCH 4/9] JSON-Output and updated scaling calculation --- .../optimiser/OptimiseDipoleScaling.h | 15 +-- src/core/molecule.cpp | 119 +++++++++++------- src/core/molecule.h | 3 +- src/main.cpp | 63 ++++++++-- 4 files changed, 131 insertions(+), 69 deletions(-) diff --git a/src/capabilities/optimiser/OptimiseDipoleScaling.h b/src/capabilities/optimiser/OptimiseDipoleScaling.h index 9308f6e..44e36a2 100644 --- a/src/capabilities/optimiser/OptimiseDipoleScaling.h +++ b/src/capabilities/optimiser/OptimiseDipoleScaling.h @@ -61,13 +61,14 @@ struct OptDipoleFunctor : TFunctor { // calculation of residuals for (int i = 0; i < m_conformers.size(); ++i) { auto conf = m_conformers.at(i); - fvec(i) = (conf.getDipole() - conf.CalculateDipoleMoment(scaling)).norm(); + fvec(i) = (conf.getDipole() - conf.CalculateDipoleMoment(scaling, m_bond)).norm(); } return 0; } int no_parameter; int no_points; std::vector m_conformers; + bool m_bond; int inputs() const { return no_parameter; } int values() const { return no_points; } @@ -75,10 +76,11 @@ struct OptDipoleFunctor : TFunctor { struct OptDipoleFunctorNumericalDiff : Eigen::NumericalDiff {}; -inline Vector OptimiseDipoleScaling(const std::vector& conformers, Vector scaling) { +inline Vector OptimiseDipoleScaling(const std::vector& conformers, Vector scaling, const bool bond = false) { - OptDipoleFunctor functor(6, conformers.size()); + OptDipoleFunctor functor(2, conformers.size()); functor.m_conformers = conformers; + functor.m_bond = bond; Eigen::NumericalDiff numDiff(functor); Eigen::LevenbergMarquardt lm(numDiff); @@ -93,13 +95,13 @@ inline Vector OptimiseDipoleScaling(const std::vector& conformers, Vec Eigen::LevenbergMarquardtSpace::Status status = lm.minimizeInit(scaling); - int MaxIter = 3000; + constexpr int MaxIter = 3000; Vector old_param = scaling; for (int iter = 0; iter < MaxIter; ++iter) { status = lm.minimizeOneStep(scaling); - if ((old_param - scaling).norm() < 1e-5) + if ((old_param - scaling).norm() < 1e-6) break; old_param = scaling; @@ -134,8 +136,7 @@ inline Matrix DipoleScalingCalculation(const std::vector& conformers) } } - Matrix Theta(para_size, 1); - Theta = FTF.colPivHouseholderQr().solve(FTy); + Matrix Theta = FTF.colPivHouseholderQr().solve(FTy); return Theta; } \ No newline at end of file diff --git a/src/core/molecule.cpp b/src/core/molecule.cpp index c7072d2..8e355a6 100644 --- a/src/core/molecule.cpp +++ b/src/core/molecule.cpp @@ -905,48 +905,66 @@ Eigen::Vector3d Molecule::COM(bool protons, int fragment) } std::vector Molecule::CalculateDipoleMoments(const std::vector& scaling) const -{ // calc classic dipole moment of the system with partial charges +{ // calc classic dipole moments of the every fragment with partial charges std::vector dipole_moments; - if (m_charges.size() != m_geometry.rows()) { std::cout << "No partial charges available" << std::endl; return dipole_moments; } - // calc center of mass and dipole for every fragment - for (int f = 0; f < GetFragments().size(); ++f) { - Position pos = { 0, 0, 0 }, dipole = { 0, 0, 0 }; - double mass = 0; - // calc center of mass of the molecule - for (int i : m_fragments[f]) { - double m = Elements::AtomicMass[m_atoms[i]]; - mass += m; - pos(0) += m * m_geometry(i, 0); - pos(1) += m * m_geometry(i, 1); - pos(2) += m * m_geometry(i, 2); + for (int i = 0; i < GetFragments().size(); ++i) { + std::vector frag_scaling = {}; + for (int j = 0; j < m_fragments[i].size(); ++j) { + if (scaling.size() > j) + frag_scaling.push_back(scaling[j]); + else + frag_scaling.push_back(1.0); } - pos(0) /= mass; - pos(1) /= mass; - pos(2) /= mass; - // calc dipole moment with scalar - for (int i : m_fragments[f]) { - double scale = 1; - if (scaling.size() > i) - scale = scaling[i]; - dipole(0) += m_charges[i] * (m_geometry(i, 0) - pos(0)) * scale; - dipole(1) += m_charges[i] * (m_geometry(i, 1) - pos(1)) * scale; - dipole(2) += m_charges[i] * (m_geometry(i, 2) - pos(2)) * scale; - // std::cout << scale << " "; - } - - // std::cout << std::endl; - dipole_moments.push_back(dipole); + Molecule mol = getFragmentMolecule(i); + dipole_moments.push_back(mol.CalculateDipoleMoment(frag_scaling)); } return dipole_moments; } -Position Molecule::CalculateDipoleMoment(const Vector& scaling) const +Position Molecule::CalculateDipoleMoment(const Vector& scaling, const bool bond) const +{ // dec and init + Position pos = { 0, 0, 0 }, dipole = { 0, 0, 0 }; + if (m_charges.size() != m_geometry.rows()) { + std::cout << "No partial charges available" << std::endl; + return dipole; + } + // calc center of geometry + pos = Centroid(); + if constexpr (false) + pos = MassCentroid(); + + // calc of the dipole moment with scalar + for (int i = 0; i < m_geometry.rows(); ++i) { + double scale = 1; + if (scaling.size() > i) + scale = scaling[i]; + dipole(0) += m_charges[i] * (m_geometry(i, 0) - pos(0)) * scale; + dipole(1) += m_charges[i] * (m_geometry(i, 1) - pos(1)) * scale; + dipole(2) += m_charges[i] * (m_geometry(i, 2) - pos(2)) * scale; + if (bond) { + for (int j = 0; j < m_geometry.rows(); ++j) { + if (i == j) + continue; + double revr = 1 / (m_geometry.row(i) - m_geometry.row(j)).norm(); + // std::cout << m_charges[i] *revr * scale << " "; + + dipole(0) -= m_charges[i] * revr * scale; + dipole(1) -= m_charges[i] * revr * scale; + dipole(2) -= m_charges[i] * revr * scale; + } + // std::cout << scale << " "; + } + } + // std::cout << std::endl; + return dipole; +} + +Position Molecule::CalculateDipoleMoment(const std::vector& scaling, const bool bond) const { // dec and init - double mass = 0; Position pos = { 0, 0, 0 }, dipole = { 0, 0, 0 }; if (m_charges.size() != m_geometry.rows()) { @@ -954,7 +972,9 @@ Position Molecule::CalculateDipoleMoment(const Vector& scaling) const return dipole; } // calc center of mass - pos = MassCentroid(); + pos = Centroid(); + if constexpr (false) + pos = MassCentroid(); // calc of the dipole moment with scalar for (int i = 0; i < m_geometry.rows(); ++i) { @@ -964,20 +984,19 @@ Position Molecule::CalculateDipoleMoment(const Vector& scaling) const dipole(0) += m_charges[i] * (m_geometry(i, 0) - pos(0)) * scale; dipole(1) += m_charges[i] * (m_geometry(i, 1) - pos(1)) * scale; dipole(2) += m_charges[i] * (m_geometry(i, 2) - pos(2)) * scale; - for (int j = 0; j < m_geometry.rows(); ++j) { - if (i == j) - continue; - double scale = 3; - if (scaling.size() > i) - scale = scaling[i]; - double revr = 1 / (m_geometry.row(i) - m_geometry.row(j)).norm(); - // std::cout << m_charges[i] *revr * scale << " "; - - dipole(0) -= m_charges[i] * revr * scale; - dipole(1) -= m_charges[i] * revr * scale; - dipole(2) -= m_charges[i] * revr * scale; + if (bond) { + for (int j = 0; j < m_geometry.rows(); ++j) { + if (i == j) + continue; + double revr = 1 / (m_geometry.row(i) - m_geometry.row(j)).norm(); + // std::cout << m_charges[i] *revr * scale << " "; + + dipole(0) -= m_charges[i] * revr * scale; + dipole(1) -= m_charges[i] * revr * scale; + dipole(2) -= m_charges[i] * revr * scale; + } + // std::cout << scale << " "; } - // std::cout << scale << " "; } // std::cout << std::endl; return dipole; @@ -1509,15 +1528,19 @@ std::vector Molecule::GetBox() const Geometry Molecule::ChargeDistribution() const { + Position pos = Centroid(); + if constexpr (false) + pos = MassCentroid(); + Geometry point_charge(m_geometry.rows(), 3); if (m_charges.size() != m_geometry.rows()) { std::cerr << "No partial charges available" << std::endl; return point_charge.setZero(m_geometry.rows(), 3); } for (int i = 0; i < m_charges.size(); ++i) { - point_charge(i, 0) = m_geometry(i, 0) * m_charges[i]; - point_charge(i, 1) = m_geometry(i, 1) * m_charges[i]; - point_charge(i, 2) = m_geometry(i, 2) * m_charges[i]; + point_charge(i, 0) = (m_geometry(i, 0) - pos(0)) * m_charges[i]; + point_charge(i, 1) = (m_geometry(i, 1) - pos(1)) * m_charges[i]; + point_charge(i, 2) = (m_geometry(i, 2) - pos(2)) * m_charges[i]; } return point_charge; } diff --git a/src/core/molecule.h b/src/core/molecule.h index bb9f55e..9666271 100644 --- a/src/core/molecule.h +++ b/src/core/molecule.h @@ -178,7 +178,8 @@ class Molecule /*! \brief Methode to calculate the dipole moments of whole structure * unit of dipol is electron times angstron */ - Position CalculateDipoleMoment(const Vector& scaling = Vector()) const; + Position CalculateDipoleMoment(const Vector& scaling = Vector(), bool bond = false) const; + Position CalculateDipoleMoment(const std::vector& scaling = std::vector(), bool bond = false) const; Geometry ChargeDistribution() const; diff --git a/src/main.cpp b/src/main.cpp index 79a2b99..e7af60a 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -919,9 +919,10 @@ int main(int argc, char **argv) { } FileIterator file(argv[2]); + auto lm_basename = file.Basename(); // TODO: Add additional arguments... // TODO: if -md then do first molecular dynamic to generate some conformers, then fit - // TODO: if -scale then calc dipole with scalor and xtb2 + // TODO: if -scale then calc dipole with scalingfactor and xtb2 // TODO: if -methode then change methode json blob = controller["dipole"]; // declare blob as json, @@ -963,25 +964,61 @@ int main(int argc, char **argv) { << "Dipole: " << mol.CalculateDipoleMoment(theta).norm() << std::endl << std::endl; + Vector one = Eigen::VectorXd::Ones(mol.AtomCount()); - auto result = OptimiseDipoleScaling(conformers, theta); - std::cout << "LM-Scaler:\n" + auto result = OptimiseDipoleScaling(conformers, one); + std::cout << "LM-Scaler 1 as initial guess:\n" << result << "\n" << "Dipole: " << mol.CalculateDipoleMoment(result).norm() << std::endl << std::endl; + + auto result1 = OptimiseDipoleScaling(conformers, theta); + std::cout << "LM-Scaler theta as initial guess:\n" + << result1 << "\n" + << "Dipole: " << mol.CalculateDipoleMoment(result1).norm() << std::endl + << std::endl; + + + auto result2 = OptimiseDipoleScaling(conformers, theta, true); + std::cout << "LM-Scaler with bond true:\n" + << result2 << "\n" + << "Dipole: " << mol.CalculateDipoleMoment(result2, true).norm() << std::endl + << std::endl; + + double r2_anal = 0; double r2_LM = 0; - double r2_classic = 0; + double r2_LM1 = 0; + double r2_LM2 = 0; + double r2_anal_dn = 0; double r2_LM_dn = 0; - double r2_classic_dn = 0; - - std::cout << "LM : classic : LM_dn : classic_dn" << std::endl; - for (const auto& conformer : conformers) { - r2_LM += std::pow(conformer.CalculateDipoleMoment(result).norm() - conformer.getDipole().norm(), 2); - r2_classic += std::pow(conformer.CalculateDipoleMoment(theta).norm() - conformer.getDipole().norm(), 2); - r2_LM_dn += std::pow((conformer.CalculateDipoleMoment(result) - conformer.getDipole()).norm(), 2); - r2_classic_dn += std::pow((conformer.CalculateDipoleMoment(theta) - conformer.getDipole()).norm(), 2); + double r2_LM1_dn = 0; + double r2_LM2_dn = 0; + + + for (const auto& conf : conformers) { + r2_anal += std::pow(conf.CalculateDipoleMoment(theta).norm() - conf.getDipole().norm(), 2); + r2_LM += std::pow(conf.CalculateDipoleMoment(result).norm() - conf.getDipole().norm(), 2); + r2_LM1 += std::pow(conf.CalculateDipoleMoment(result1).norm() - conf.getDipole().norm(), 2); + r2_LM2 += std::pow(conf.CalculateDipoleMoment(result2).norm() - conf.getDipole().norm(), 2); + /*r2_anal_dn += std::pow((conf.CalculateDipoleMoment(theta) - conf.getDipole()).norm(), 2); + r2_LM_dn += std::pow((conf.CalculateDipoleMoment(result) - conf.getDipole()).norm(), 2); + r2_LM1_dn += std::pow((conf.CalculateDipoleMoment(result1) - conf.getDipole()).norm(), 2); + r2_LM2_dn += std::pow((conf.CalculateDipoleMoment(result2) - conf.getDipole()).norm(), 2);*/ } - std::cout << r2_LM << " : " << r2_classic << " : " << r2_LM_dn << " : " << r2_classic_dn << std::endl; + std::cout << "Residuals:" << std::endl + << "anal: " << r2_anal << std::endl + << "LM 1 as initial guess: " << r2_LM << std::endl + << "LM theta as initial guess: " << r2_LM1 << std::endl + << "LM bond true: " << r2_LM2 << std::endl; + + //TODO add JSON output + std::vector vec_theta(theta.data(), theta.data() + theta.rows() * theta.cols()); + json scaling_vector; + scaling_vector["scaling_vector"] = Tools::DoubleVector2String(vec_theta); + std::ofstream out(lm_basename + "_scaling_vector.json"); + out << scaling_vector << std::endl; + + } else if (strcmp(argv[1], "-stride") == 0) { From 8ef4695d8b37818dab3862d9dc0e15308bdb4a0a Mon Sep 17 00:00:00 2001 From: Gerd Gehrisch Date: Wed, 2 Oct 2024 00:22:51 +0200 Subject: [PATCH 5/9] better use of C++11 method to load JSON scaling factors for Dipole calculation method to write a file with dipoles --- src/capabilities/simplemd.cpp | 365 ++++++++++++++++------------------ src/capabilities/simplemd.h | 14 +- 2 files changed, 181 insertions(+), 198 deletions(-) diff --git a/src/capabilities/simplemd.cpp b/src/capabilities/simplemd.cpp index 66315b5..c7db6ea 100644 --- a/src/capabilities/simplemd.cpp +++ b/src/capabilities/simplemd.cpp @@ -68,7 +68,7 @@ BiasThread::~BiasThread() int BiasThread::execute() { - if (m_biased_structures.size() == 0) + if (m_biased_structures.empty()) return 0; m_current_bias = 0; m_counter = 0; @@ -141,7 +141,7 @@ std::vector BiasThread::getBias() const return bias; } -SimpleMD::SimpleMD(const json& controller, bool silent) +SimpleMD::SimpleMD(const json& controller, const bool silent) : CurcumaMethod(CurcumaMDJson, controller, silent) { UpdateController(controller); @@ -150,8 +150,8 @@ SimpleMD::SimpleMD(const json& controller, bool silent) SimpleMD::~SimpleMD() { - for (int i = 0; i < m_unique_structures.size(); ++i) - delete m_unique_structures[i]; + for (const auto & m_unique_structure : m_unique_structures) + delete m_unique_structure; // delete m_bias_pool; } @@ -173,10 +173,10 @@ void SimpleMD::LoadControlJson() m_print = Json2KeyWord(m_defaults, "print"); m_max_top_diff = Json2KeyWord(m_defaults, "MaxTopoDiff"); m_seed = Json2KeyWord(m_defaults, "seed"); - m_threads = Json2KeyWord(m_defaults, "threads"); + m_threads = Json2KeyWord(m_defaults, "threads"); m_rmsd = Json2KeyWord(m_defaults, "rmsd"); - m_hmass = Json2KeyWord(m_defaults, "hmass"); + m_hmass = Json2KeyWord(m_defaults, "hmass"); m_impuls = Json2KeyWord(m_defaults, "impuls"); m_impuls_scaling = Json2KeyWord(m_defaults, "impuls_scaling"); @@ -188,7 +188,6 @@ void SimpleMD::LoadControlJson() m_coupling = Json2KeyWord(m_defaults, "coupling"); m_anderson = Json2KeyWord(m_defaults, "anderson"); - m_threads = Json2KeyWord(m_defaults, "threads"); if (m_coupling < m_dT) m_coupling = m_dT; @@ -211,6 +210,7 @@ void SimpleMD::LoadControlJson() m_writerestart = Json2KeyWord(m_defaults, "writerestart"); m_respa = Json2KeyWord(m_defaults, "respa"); m_dipole = Json2KeyWord(m_defaults, "dipole"); + m_scaling_json = Json2KeyWord(m_defaults, "scaling_json"); m_writeXYZ = Json2KeyWord(m_defaults, "writeXYZ"); m_writeinit = Json2KeyWord(m_defaults, "writeinit"); @@ -256,14 +256,14 @@ void SimpleMD::LoadControlJson() std::cout << "Energy Calculator will NOT be set up for each step! Fast energy calculation! This is the default way and should not be changed unless the energy and gradient calculation are unstable (happens with GFN2 and solvation)." << std::endl; } - if (Json2KeyWord(m_defaults, "wall").compare("spheric") == 0) { - if (Json2KeyWord(m_defaults, "wall_type").compare("logfermi") == 0) { + if (Json2KeyWord(m_defaults, "wall") == "spheric") { + if (Json2KeyWord(m_defaults, "wall_type") == "logfermi") { m_wall_type = 1; WallPotential = [=](double* grad) -> double { this->m_wall_potential = this->ApplySphericLogFermiWalls(grad); return m_wall_potential; }; - } else if (Json2KeyWord(m_defaults, "wall_type").compare("harmonic") == 0) { + } else if (Json2KeyWord(m_defaults, "wall_type") == "harmonic") { m_wall_type = 1; WallPotential = [=](double* grad) -> double { this->m_wall_potential = this->ApplySphericHarmonicWalls(grad); @@ -275,14 +275,14 @@ void SimpleMD::LoadControlJson() } std::cout << "Setting up spherical potential" << std::endl; - } else if (Json2KeyWord(m_defaults, "wall").compare("rect") == 0) { - if (Json2KeyWord(m_defaults, "wall_type").compare("logfermi") == 0) { + } else if (Json2KeyWord(m_defaults, "wall") == "rect") { + if (Json2KeyWord(m_defaults, "wall_type") == "logfermi") { m_wall_type = 2; WallPotential = [=](double* grad) -> double { this->m_wall_potential = this->ApplyRectLogFermiWalls(grad); return m_wall_potential; }; - } else if (Json2KeyWord(m_defaults, "wall_type").compare("harmonic") == 0) { + } else if (Json2KeyWord(m_defaults, "wall_type") == "harmonic") { m_wall_type = 2; WallPotential = [=](double* grad) -> double { this->m_wall_potential = this->ApplyRectHarmonicWalls(grad); @@ -298,7 +298,7 @@ void SimpleMD::LoadControlJson() WallPotential = [=](double* grad) -> double { return 0; }; - m_rm_COM_step = m_rm_COM / m_dT; + m_rm_COM_step = static_cast(m_rm_COM / m_dT); } bool SimpleMD::Initialise() @@ -313,14 +313,14 @@ bool SimpleMD::Initialise() std::cout << "Random seed is " << m_seed << std::endl; gen.seed(m_seed); - if (m_initfile.compare("none") != 0) { + if (m_initfile != "none") { json md; std::ifstream restart_file(m_initfile); try { restart_file >> md; - } catch (nlohmann::json::type_error& e) { + } catch ([[maybe_unused]] nlohmann::json::type_error& e) { throw 404; - } catch (nlohmann::json::parse_error& e) { + } catch ([[maybe_unused]] nlohmann::json::parse_error& e) { throw 404; } LoadRestartInformation(md); @@ -337,6 +337,28 @@ bool SimpleMD::Initialise() result_file.close(); } m_natoms = m_molecule.AtomCount(); + + m_scaling_vector = std::vector(m_natoms, 1); + if (m_scaling_json != "none") { + json scaling; + std::ifstream file(m_scaling_json); + try { + file >> scaling; + } catch ([[maybe_unused]] nlohmann::json::type_error& e) { + throw 404; + } catch ([[maybe_unused]] nlohmann::json::parse_error& e) { + throw 404; + } + std::string scaling_vector; + try { + scaling_vector = scaling["scaling_vector"]; + } catch ([[maybe_unused]] json::type_error& e) { + } + if (!scaling_vector.empty()) { + m_scaling_vector = Tools::String2DoubleVec(scaling_vector, "|"); + } + } + m_molecule.setCharge(0); if (!m_nocenter) { std::cout << "Move stucture to the origin ... " << std::endl; @@ -431,7 +453,7 @@ bool SimpleMD::Initialise() m_xi.resize(m_chain_length, 0.0); m_Q.resize(m_chain_length, 100); // Setze eine geeignete Masse für jede Kette for (int i = 0; i < m_chain_length; ++i) { - m_xi[i] = pow(10.0, double(i)) - 1; + m_xi[i] = pow(10.0, static_cast(i)) - 1; m_Q[i] = pow(10, i) * kb_Eh * m_T0 * m_dof * 100; std::cout << m_xi[i] << " " << m_Q[i] << std::endl; } @@ -463,7 +485,7 @@ bool SimpleMD::Initialise() config["silent"] = true; config["reorder"] = false; for (int i = 0; i < m_threads; ++i) { - BiasThread* thread = new BiasThread(m_rmsd_mtd_molecule, config); + auto* thread = new BiasThread(m_rmsd_mtd_molecule, config); thread->setDT(m_rmsd_DT); thread->setk(m_k_rmsd); thread->setalpha(m_alpha_rmsd); @@ -487,7 +509,7 @@ bool SimpleMD::Initialise() } m_bias_structure_count = index; } else { - if (m_rmsd_ref_file.compare("none") != 0) { + if (m_rmsd_ref_file != "none") { std::cout << "Reading structure files from " << m_rmsd_ref_file << std::endl; int index = 0; @@ -523,7 +545,7 @@ void SimpleMD::InitConstrainedBonds() std::pair indicies(i, j); std::pair minmax(m_molecule.CalculateDistance(i, j) * m_molecule.CalculateDistance(i, j), m_molecule.CalculateDistance(i, j) * m_molecule.CalculateDistance(i, j)); std::pair, double> bond(indicies, m_molecule.CalculateDistance(i, j) * m_molecule.CalculateDistance(i, j)); - m_bond_constrained.push_back(std::pair, double>(bond)); + m_bond_constrained.emplace_back(bond); // std::cout << i << " " << j << " " << bond.second << std::endl; } @@ -723,6 +745,8 @@ nlohmann::json SimpleMD::WriteRestartInformation() restart["average_Virial"] = m_average_virial_correction; restart["average_Wall"] = m_average_wall_potential; + restart["scaling_vector"] = Tools::DoubleVector2String(m_scaling_vector); + restart["rattle"] = m_rattle; restart["rattle_maxiter"] = m_rattle_maxiter; restart["rattle_dynamic_tol"] = m_rattle_tolerance; @@ -752,8 +776,8 @@ nlohmann::json SimpleMD::WriteRestartInformation() restart["counter"] = m_bias_structure_count; restart["rmsd_atoms"] = m_rmsd_atoms; std::vector bias(m_bias_structure_count); - for (int i = 0; i < m_bias_threads.size(); ++i) { - for (const auto& stored_bias : m_bias_threads[i]->getBias()) { + for (const auto & m_bias_thread : m_bias_threads) { + for (const auto& stored_bias : m_bias_thread->getBias()) { bias[stored_bias["index"]] = stored_bias; } } @@ -777,10 +801,10 @@ bool SimpleMD::LoadRestartInformation() json restart; try { file >> restart; - } catch (json::type_error& e) { + } catch ([[maybe_unused]] json::type_error& e) { error++; continue; - } catch (json::parse_error& e) { + } catch ([[maybe_unused]] json::parse_error& e) { error++; continue; } @@ -788,7 +812,7 @@ bool SimpleMD::LoadRestartInformation() json md; try { md = restart[MethodName()[0]]; - } catch (json::type_error& e) { + } catch ([[maybe_unused]] json::type_error& e) { error++; continue; } @@ -799,137 +823,142 @@ bool SimpleMD::LoadRestartInformation() bool SimpleMD::LoadRestartInformation(const json& state) { - std::string geometry, velocities, constrains, xi, Q; + std::string geometry, scaling_vector, velocities, constrains, xi, Q; try { m_method = state["method"]; - } catch (json::type_error& e) { + } catch ([[maybe_unused]] json::type_error& e) { } try { m_dT = state["dT"]; - } catch (json::type_error& e) { + } catch ([[maybe_unused]] json::type_error& e) { } try { m_maxtime = state["MaxTime"]; - } catch (json::type_error& e) { + } catch ([[maybe_unused]] json::type_error& e) { } try { m_rmrottrans = state["rmrottrans"]; - } catch (json::type_error& e) { + } catch ([[maybe_unused]] json::type_error& e) { } try { m_nocenter = state["nocenter"]; - } catch (json::type_error& e) { + } catch ([[maybe_unused]] json::type_error& e) { } try { m_COM = state["COM"]; - } catch (json::type_error& e) { + } catch ([[maybe_unused]] json::type_error& e) { } try { m_T0 = state["T"]; - } catch (json::type_error& e) { + } catch ([[maybe_unused]] json::type_error& e) { } try { m_currentStep = state["currentStep"]; - } catch (json::type_error& e) { + } catch ([[maybe_unused]] json::type_error& e) { } try { m_aver_Epot = state["average_Epot"]; - } catch (json::type_error& e) { + } catch ([[maybe_unused]] json::type_error& e) { } try { m_aver_Ekin = state["average_Ekin"]; - } catch (json::type_error& e) { + } catch ([[maybe_unused]] json::type_error& e) { } try { m_aver_Etot = state["average_Etot"]; - } catch (json::type_error& e) { + } catch ([[maybe_unused]] json::type_error& e) { } try { m_aver_Temp = state["average_T"]; - } catch (json::type_error& e) { + } catch ([[maybe_unused]] json::type_error& e) { } try { m_average_virial_correction = state["average_Virial"]; - } catch (json::type_error& e) { + } catch ([[maybe_unused]] json::type_error& e) { } try { m_average_wall_potential = state["average_Wall"]; - } catch (json::type_error& e) { + } catch ([[maybe_unused]] json::type_error& e) { } try { m_coupling = state["coupling"]; - } catch (json::type_error& e) { + } catch ([[maybe_unused]] json::type_error& e) { } try { m_respa = state["respa"]; - } catch (json::type_error& e) { + } catch ([[maybe_unused]] json::type_error& e) { } try { m_eta = state["eta"]; - } catch (json::type_error& e) { + } catch ([[maybe_unused]] json::type_error& e) { } try { m_thermostat = state["thermostat"]; - } catch (json::type_error& e) { + } catch ([[maybe_unused]] json::type_error& e) { } try { geometry = state["geometry"]; - } catch (json::type_error& e) { + } catch ([[maybe_unused]] json::type_error& e) { + } + + try { + scaling_vector = state["scaling_vector"]; + } catch ([[maybe_unused]] json::type_error& e) { } try { velocities = state["velocities"]; - } catch (json::type_error& e) { + } catch ([[maybe_unused]] json::type_error& e) { } try { xi = state["xi"]; - } catch (json::type_error& e) { + } catch ([[maybe_unused]] json::type_error& e) { } try { Q = state["Q"]; - } catch (json::type_error& e) { + } catch ([[maybe_unused]] json::type_error& e) { } try { m_mtd = state["mtd"]; - } catch (json::type_error& e) { + } catch ([[maybe_unused]] json::type_error& e) { } try { m_rattle = state["rattle"]; - } catch (json::type_error& e) { + } catch ([[maybe_unused]] json::type_error& e) { } try { m_rattle_tolerance = state["rattle_tolerance"]; - } catch (json::type_error& e) { + } catch ([[maybe_unused]] json::type_error& e) { } try { m_rattle_maxiter = state["rattle_maxiter"]; - } catch (json::type_error& e) { + } catch ([[maybe_unused]] json::type_error& e) { } try { m_rattle_dynamic_tol = state["rattle_dynamic_tol"]; - } catch (json::type_error& e) { + } catch ([[maybe_unused]] json::type_error& e) { } try { m_rattle_dynamic_tol_iter = state["rattle_dynamic_tol_iter"]; - } catch (json::type_error& e) { + } catch ([[maybe_unused]] json::type_error& e) { } try { m_rmsd_mtd = state["rmsd_mtd"]; @@ -944,25 +973,28 @@ bool SimpleMD::LoadRestartInformation(const json& state) m_rmsd_ref_file = state["rmsd_ref_file"]; m_bias_json = state["bias"]; } - } catch (json::type_error& e) { + } catch ([[maybe_unused]] json::type_error& e) { } - if (geometry.size()) { + if (!geometry.empty()) { m_current_geometry = Tools::String2DoubleVec(geometry, "|"); } - if (velocities.size()) { + if (!scaling_vector.empty()) { + m_scaling_vector = Tools::String2DoubleVec(scaling_vector, "|"); + } + if (!velocities.empty()) { m_velocities = Tools::String2DoubleVec(velocities, "|"); } - if (xi.size()) { + if (!xi.empty()) { m_xi = Tools::String2DoubleVec(xi, "|"); } - if (Q.size()) { + if (!Q.empty()) { m_Q = Tools::String2DoubleVec(Q, "|"); } - m_restart = geometry.size() && velocities.size(); + m_restart = !geometry.empty() && !velocities.empty(); return true; } @@ -972,28 +1004,28 @@ void SimpleMD::start() if (m_initialised == false) return; bool aborted = false; - auto unix_timestamp = std::chrono::seconds(std::time(NULL)); + auto unix_timestamp = std::chrono::seconds(std::time(nullptr)); m_unix_started = std::chrono::milliseconds(unix_timestamp).count(); - double* gradient = new double[3 * m_natoms]; + auto* gradient = new double[3 * m_natoms]; std::vector states; for (int i = 0; i < 3 * m_natoms; ++i) { gradient[i] = 0; } - if (m_thermostat.compare("csvr") == 0) { + if (m_thermostat == "csvr") { fmt::print(fg(fmt::color::green) | fmt::emphasis::bold, "\nUsing Canonical sampling through velocity rescaling (CSVR) Thermostat\nJ. Chem. Phys. 126, 014101 (2007) - DOI: 10.1063/1.2408420\n\n"); - ThermostatFunction = std::bind(&SimpleMD::CSVR, this); - } else if (m_thermostat.compare("berendson") == 0) { + ThermostatFunction = [this] { CSVR(); }; + } else if (m_thermostat == "berendson") { fmt::print(fg(fmt::color::green) | fmt::emphasis::bold, "\nUsing Berendson Thermostat\nJ. Chem. Phys. 81, 3684 (1984) - DOI: 10.1063/1.448118\n\n"); - ThermostatFunction = std::bind(&SimpleMD::Berendson, this); - } else if (m_thermostat.compare("anderson") == 0) { + ThermostatFunction = [this] { Berendson(); }; + } else if (m_thermostat == "anderson") { fmt::print(fg(fmt::color::green) | fmt::emphasis::bold, "\nUsing Anderson Thermostat\n ... \n\n"); - ThermostatFunction = std::bind(&SimpleMD::Anderson, this); - } else if (m_thermostat.compare("nosehover") == 0) { + ThermostatFunction = [this] { Anderson(); }; + } else if (m_thermostat == "nosehover") { fmt::print(fg(fmt::color::green) | fmt::emphasis::bold, "\nUsing Nosé-Hoover-Chain Thermostat\n ... \n\n"); - ThermostatFunction = std::bind(&SimpleMD::NoseHover, this); + ThermostatFunction = [this] { NoseHover(); }; } else { - ThermostatFunction = std::bind(&SimpleMD::None, this); + ThermostatFunction = [this] { None(); }; std::cout << "No Thermostat applied\n" << std::endl; } @@ -1115,85 +1147,36 @@ void SimpleMD::start() } } + /////////// Dipole + if (m_dipole && m_method == "gfn2") { + + //json blob; + // calc partialCharge with gnf2-xtb + //EnergyCalculator interface("gfn2", blob); // set method to gfn2-xtb + //interface.setMolecule(m_molecule); // set molecule for calc + //interface.CalculateEnergy(false, true); // calc energy and charges and dipole moment + //m_molecule.setPartialCharges(interface.Charges()); // calc Partial Charges and give it to mol + //m_molecule.setDipole(interface.Dipole()*au); + + m_curr_dipoles = m_molecule.CalculateDipoleMoments(m_scaling_vector); + std::ofstream file; + file.open(Basename() + "_dipole.out", std::ios_base::app); + + Position d = {0,0,0}; + for (const auto& dipole : m_curr_dipoles) { + d += dipole; + file << dipole.norm() << ", "; + } - /////////// Dipole calc - //def scaling coefficient - std::vector dipole_scale; - //set coefficients some values - for (auto i = 0; i < m_natoms; i++) { - dipole_scale.push_back(1); - } - dipole_scale = { - 1.16126,//Wasser - 1.44224,//* - 1.44256,//* - 1.56764,//Methanol - 1.35206,//* - 1.51374,//* - 1.52110,//* - 1.50372,//* - 1.46760,//* - 1.61581,//Ethanol - 1.86773,//* - 1.54639,//* - 1.60913,//* - 1.62602,//* - 1.37539,//* - 1.50891,//* - 1.53962,//* - 1.46714//* - }; // from -dipole LM - - json blob; - // calc partialCharge with gnf2-xtb - EnergyCalculator interface("gfn2", blob); // set method to gfn2-xtb - interface.setMolecule(m_molecule); // set molecule for calc - interface.CalculateEnergy(false, true); // calc energy and charges and dipole moment - m_molecule.setPartialCharges(interface.Charges()); // calc Partial Charges and give it to mol - m_molecule.setDipole(interface.Dipole()*au); - - Molecule mol; - - //calc Dipoles from partial Charges and Scaling - auto dipoles = m_molecule.CalculateDipoleMoments(dipole_scale); - int i=0; - - Position dipole_sum = {0,0,0}; - for (auto dipole : dipoles) { - // double frag_charge = 0; - mol = m_molecule.getFragmentMolecule(i); - - //dipole of system - dipole_sum[0] += dipole[0]; - dipole_sum[1] += dipole[1]; - dipole_sum[2] += dipole[2]; - - - //std::cout << "Fragment" << i << std::endl; - std::cout << dipole.norm() << " " << mol.getDipole().norm() << " "; - //std::cout << dipole[0] << " " << dipole[1] << " " << dipole[2] << std::endl; - //std::cout << mol.getDipole()[0] << " " << mol.getDipole()[1] << " " << mol.getDipole()[2] << std::endl; + file << d.norm() << " " << m_molecule.getDipole().norm() << std::endl; + file.close(); - /*std::cout << "p.Charge: " << std::endl; - for (auto p : mol.getPartialCharges()) { - std::cout << p << std::endl; - frag_charge += p; - } - std::cout << "charge: " << frag_charge << std::endl;*/ - i++; } - Position d = m_molecule.getDipole(); - std::cout << std::endl; - /*std::cout << std::endl; - std::cout << "Dipole Sum: " << dipole_sum.norm() << std::endl << dipole_sum[0] << " " << dipole_sum[1] << " " << dipole_sum[2] << std::endl; - std::cout << "XTB2-Dipole: " << d.norm() << std::endl << d[0] << " " << d[1] << " " << d[2] << std::endl - << "---------" << std::endl;*/ + //////////// Dipole - /////////// Dipole calc if (m_step % m_dump == 0) { - bool write = WriteGeometry(); - if (write) { + if (bool write = WriteGeometry()) { states.push_back(WriteRestartInformation()); m_current_rescue = 0; } else if (!write && m_rescue && states.size() > (1 - m_current_rescue)) { @@ -1239,7 +1222,7 @@ void SimpleMD::start() if (m_writerestart > -1 && m_step % m_writerestart == 0) { std::ofstream restart_file("curcuma_step_" + std::to_string(int(m_step * m_dT)) + ".json"); - nlohmann::json restart; + json restart; restart[MethodName()[0]] = WriteRestartInformation(); restart_file << restart << std::endl; } @@ -1268,9 +1251,9 @@ void SimpleMD::start() m_step++; m_currentStep += m_dT; m_time_step += std::chrono::duration_cast(std::chrono::system_clock::now() - step0).count(); - } + } //MD Loop end here PrintStatus(); - if (m_thermostat.compare("csvr") == 0) + if (m_thermostat == "csvr") std::cout << "Exchange with heat bath " << m_Ekin_exchange << "Eh" << std::endl; if (m_dipole) { /* @@ -1413,7 +1396,7 @@ void SimpleMD::Rattle(double* grad) * updated velocities of the second atom (minus instead of plus) */ TriggerWriteRestart(); - double* coord = new double[3 * m_natoms]; + auto* coord = new double[3 * m_natoms]; double m_dT_inverse = 1 / m_dT; std::vector moved(m_natoms, 0); bool move = false; @@ -1625,17 +1608,17 @@ void SimpleMD::ApplyRMSDMTD(double* grad) colvarfile.close(); } if (m_threads == 1 || m_bias_structure_count == 1) { - for (int i = 0; i < m_bias_threads.size(); ++i) { - m_bias_threads[i]->setCurrentGeometry(current_geometry, m_currentStep); - m_bias_threads[i]->start(); - current_bias += m_bias_threads[i]->BiasEnergy(); + for (auto & m_bias_thread : m_bias_threads) { + m_bias_thread->setCurrentGeometry(current_geometry, m_currentStep); + m_bias_thread->start(); + current_bias += m_bias_thread->BiasEnergy(); for (int j = 0; j < m_rmsd_indicies.size(); ++j) { - grad[3 * m_rmsd_indicies[j] + 0] += m_bias_threads[i]->Gradient()(j, 0); - grad[3 * m_rmsd_indicies[j] + 1] += m_bias_threads[i]->Gradient()(j, 1); - grad[3 * m_rmsd_indicies[j] + 2] += m_bias_threads[i]->Gradient()(j, 2); + grad[3 * m_rmsd_indicies[j] + 0] += m_bias_thread->Gradient()(j, 0); + grad[3 * m_rmsd_indicies[j] + 1] += m_bias_thread->Gradient()(j, 1); + grad[3 * m_rmsd_indicies[j] + 2] += m_bias_thread->Gradient()(j, 2); } - m_colvar_incr += m_bias_threads[i]->Counter(); - m_loop_time += m_bias_threads[i]->Time(); + m_colvar_incr += m_bias_thread->Counter(); + m_loop_time += m_bias_thread->Time(); } } else { if (m_bias_structure_count < m_threads) { @@ -1643,8 +1626,8 @@ void SimpleMD::ApplyRMSDMTD(double* grad) m_bias_threads[i]->setCurrentGeometry(current_geometry, m_currentStep); } } else { - for (int i = 0; i < m_bias_threads.size(); ++i) { - m_bias_threads[i]->setCurrentGeometry(current_geometry, m_currentStep); + for (auto & m_bias_thread : m_bias_threads) { + m_bias_thread->setCurrentGeometry(current_geometry, m_currentStep); } } @@ -1653,18 +1636,18 @@ void SimpleMD::ApplyRMSDMTD(double* grad) m_bias_pool->StartAndWait(); m_bias_pool->setWakeUp(m_bias_pool->WakeUp() / 2); - for (int i = 0; i < m_bias_threads.size(); ++i) { - if (m_bias_threads[i]->Return() == 1) { + for (auto & m_bias_thread : m_bias_threads) { + if (m_bias_thread->Return() == 1) { - current_bias += m_bias_threads[i]->BiasEnergy(); + current_bias += m_bias_thread->BiasEnergy(); for (int j = 0; j < m_rmsd_indicies.size(); ++j) { - grad[3 * m_rmsd_indicies[j] + 0] += m_bias_threads[i]->Gradient()(j, 0); - grad[3 * m_rmsd_indicies[j] + 1] += m_bias_threads[i]->Gradient()(j, 1); - grad[3 * m_rmsd_indicies[j] + 2] += m_bias_threads[i]->Gradient()(j, 2); + grad[3 * m_rmsd_indicies[j] + 0] += m_bias_thread->Gradient()(j, 0); + grad[3 * m_rmsd_indicies[j] + 1] += m_bias_thread->Gradient()(j, 1); + grad[3 * m_rmsd_indicies[j] + 2] += m_bias_thread->Gradient()(j, 2); } - m_colvar_incr += m_bias_threads[i]->Counter(); + m_colvar_incr += m_bias_thread->Counter(); } - m_loop_time += m_bias_threads[i]->Time(); + m_loop_time += m_bias_thread->Time(); } m_bias_pool->Reset(); } @@ -1868,9 +1851,9 @@ void SimpleMD::RemoveRotations(std::vector& velo) std::vector> fragments = m_molecule.GetFragments(); // std::cout << fragments.size() << std::endl; - for (int f = 0; f < fragments.size(); ++f) { - for (int i : fragments[f]) { - double m = m_mass[i]; + for (auto & fragment : fragments) { + for (const int i : fragment) { + const double m = m_mass[i]; mass += m; pos(0) += m * m_current_geometry[3 * i + 0]; pos(1) += m * m_current_geometry[3 * i + 1]; @@ -1885,21 +1868,21 @@ void SimpleMD::RemoveRotations(std::vector& velo) pos(2) /= mass; Geometry matrix = Geometry::Zero(3, 3); - for (int i : fragments[f]) { - double m = m_mass[i]; + for (const int i : fragment) { + const double m = m_mass[i]; geom(i, 0) -= pos(0); geom(i, 1) -= pos(1); geom(i, 2) -= pos(2); - double x = geom(i, 0); - double y = geom(i, 1); - double z = geom(i, 2); + const double x = geom(i, 0); + const double y = geom(i, 1); + const double z = geom(i, 2); angom(0) += m_mass[i] * (geom(i, 1) * velo[3 * i + 2] - geom(i, 2) * velo[3 * i + 1]); angom(1) += m_mass[i] * (geom(i, 2) * velo[3 * i + 0] - geom(i, 0) * velo[3 * i + 2]); angom(2) += m_mass[i] * (geom(i, 0) * velo[3 * i + 1] - geom(i, 1) * velo[3 * i + 0]); - double x2 = x * x; - double y2 = y * y; - double z2 = z * z; + const double x2 = x * x; + const double y2 = y * y; + const double z2 = z * z; matrix(0, 0) += m * (y2 + z2); matrix(1, 1) += m * (x2 + z2); matrix(2, 2) += m * (x2 + y2); @@ -1914,13 +1897,13 @@ void SimpleMD::RemoveRotations(std::vector& velo) Position omega = matrix.inverse() * angom; Position rlm = { 0, 0, 0 }, ram = { 0, 0, 0 }; - for (int i : fragments[f]) { + for (const int i : fragment) { rlm(0) = rlm(0) + m_mass[i] * velo[3 * i + 0]; rlm(1) = rlm(1) + m_mass[i] * velo[3 * i + 1]; rlm(2) = rlm(2) + m_mass[i] * velo[3 * i + 2]; } - for (int i : fragments[f]) { + for (const int i : fragment) { ram(0) = (omega(1) * geom(i, 2) - omega(2) * geom(i, 1)); ram(1) = (omega(2) * geom(i, 0) - omega(0) * geom(i, 2)); ram(2) = (omega(0) * geom(i, 1) - omega(1) * geom(i, 0)); @@ -2007,7 +1990,7 @@ void SimpleMD::RemoveRotation(std::vector& velo) void SimpleMD::PrintStatus() const { - auto unix_timestamp = std::chrono::seconds(std::time(NULL)); + const auto unix_timestamp = std::chrono::seconds(std::time(NULL)); int current = std::chrono::milliseconds(unix_timestamp).count(); double duration = (current - m_unix_started) / (1000.0 * double(m_currentStep)); @@ -2042,7 +2025,7 @@ void SimpleMD::PrintStatus() const //std::cout << m_mtd_time << " " << m_loop_time << std::endl; } -void SimpleMD::PrintMatrix(const double* matrix) +void SimpleMD::PrintMatrix(const double* matrix) const { std::cout << "Print Matrix" << std::endl; for (int i = 0; i < m_natoms; ++i) { @@ -2059,10 +2042,9 @@ double SimpleMD::CleanEnergy(double* grad) double Energy = interface.CalculateEnergy(true); interface.getGradient(grad); - if (m_dipole) { - auto dipole = interface.Dipole(); - m_curr_dipole = sqrt(dipole[0] * dipole[0] + dipole[1] * dipole[1] + dipole[2] * dipole[2]); - m_collected_dipole.push_back(sqrt(dipole[0] * dipole[0] + dipole[1] * dipole[1] + dipole[2] * dipole[2])); + if (m_dipole && m_method == "gfn2") { + m_molecule.setDipole(interface.Dipole()*au); + m_molecule.setPartialCharges(interface.Charges()); } return Energy; } @@ -2073,10 +2055,9 @@ double SimpleMD::FastEnergy(double* grad) double Energy = m_interface->CalculateEnergy(true); m_interface->getGradient(grad); - if (m_dipole) { - auto dipole = m_interface->Dipole(); - m_curr_dipole = sqrt(dipole[0] * dipole[0] + dipole[1] * dipole[1] + dipole[2] * dipole[2]); - m_collected_dipole.push_back(sqrt(dipole[0] * dipole[0] + dipole[1] * dipole[1] + dipole[2] * dipole[2])); + if (m_dipole && m_method == "gfn2") { + m_molecule.setDipole(m_interface->Dipole()*au); + m_molecule.setPartialCharges(m_interface->Charges()); } return Energy; } @@ -2099,7 +2080,7 @@ void SimpleMD::AverageQuantities() m_aver_Ekin = (m_Ekin + (m_currentStep)*m_aver_Ekin) / (m_currentStep + 1); m_aver_Etot = (m_Etot + (m_currentStep)*m_aver_Etot) / (m_currentStep + 1); if (m_dipole) { - m_aver_dipol = (m_curr_dipole + (m_currentStep)*m_aver_dipol) / (m_currentStep + 1); + //m_aver_dipol = (m_curr_dipoles + (m_currentStep)*m_aver_dipol) / (m_currentStep + 1); } m_average_wall_potential = (m_wall_potential + (m_currentStep)*m_average_wall_potential) / (m_currentStep + 1); m_average_virial_correction = (m_virial_correction + (m_currentStep)*m_average_virial_correction) / (m_currentStep + 1); diff --git a/src/capabilities/simplemd.h b/src/capabilities/simplemd.h index 7ddfcbc..cebbbe7 100644 --- a/src/capabilities/simplemd.h +++ b/src/capabilities/simplemd.h @@ -156,8 +156,8 @@ static json CurcumaMDJson{ { "rattle_dynamic_tol_iter", 100 }, { "thermostat", "csvr" }, // can be csvr (default), berendson, none, anderson or nosehover { "respa", 1 }, - { "threads", 1 }, { "dipole", false }, + { "scaling_json", "none" }, { "seed", 1 }, { "cleanenergy", false }, { "wall", "none" }, // can be spheric or rect @@ -245,7 +245,7 @@ class SimpleMD : public CurcumaMethod { double FastEnergy(double* grad); double CleanEnergy(double* grad); - void PrintMatrix(const double* matrix); + void PrintMatrix(const double* matrix) const; bool WriteGeometry(); void Verlet(double* grad); @@ -292,17 +292,18 @@ class SimpleMD : public CurcumaMethod { int m_natoms = 0; int m_dump = 1; - double m_T = 0, m_Epot = 0, m_aver_Epot = 0, m_Ekin = 0, m_aver_Ekin = 0, m_Etot = 0, m_aver_Etot = 0, m_aver_dipol = 0, m_curr_dipole = 0; + double m_T = 0, m_Epot = 0, m_aver_Epot = 0, m_Ekin = 0, m_aver_Ekin = 0, m_Etot = 0, m_aver_Etot = 0, m_aver_dipol = 0; double m_rm_COM = 100; int m_rm_COM_step = -1; int m_hmass = 1; double m_single_step = 1; double m_dT = 0.5, m_currentStep = 0, m_maxtime = 1000; int m_spin = 0, m_charge = 0, m_print = 100; - double m_T0 = 298.13, m_aver_Temp = 0, m_aver_rattle_Temp = 0, m_rmsd = 1.5; + double m_T0 = 298.15, m_aver_Temp = 0, m_aver_rattle_Temp = 0, m_rmsd = 1.5; double m_x0 = 0, m_y0 = 0, m_z0 = 0; double m_Ekin_exchange = 0.0; - std::vector m_current_geometry, m_mass, m_velocities, m_gradient, m_rmass, m_virial, m_gradient_bias; + std::vector m_current_geometry, m_mass, m_velocities, m_gradient, m_rmass, m_virial, m_gradient_bias, m_scaling_vector; + std::vector m_curr_dipoles; std::vector m_atomtype; Molecule m_molecule, m_reference, m_target, m_rmsd_mtd_molecule; bool m_initialised = false, m_restart = false, m_writeUnique = true, m_opt = false, m_rescue = false, m_writeXYZ = true, m_writeinit = false, m_norestart = false; @@ -316,6 +317,7 @@ class SimpleMD : public CurcumaMethod { std::vector m_rmsd_indicies; std::vector > m_rmsd_fragments; + std::vector m_bias_structures; std::vector m_biased_structures; std::vector m_bias_threads; @@ -351,7 +353,7 @@ class SimpleMD : public CurcumaMethod { std::vector m_collected_dipole; Matrix m_topo_initial; std::vector m_unique_structures; - std::string m_method = "UFF", m_initfile = "none", m_thermostat = "csvr", m_plumed, m_rmsd_ref_file, m_rmsd_atoms = "-1"; + std::string m_method = "UFF", m_initfile = "none", m_thermostat = "csvr", m_plumed, m_rmsd_ref_file, m_rmsd_atoms = "-1", m_scaling_json = "none"; bool m_unstable = false; bool m_dipole = false; bool m_clean_energy = false; From 0981067c0a90e18444fbbe913eb6b28adfcf7b28 Mon Sep 17 00:00:00 2001 From: Gerd Gehrisch Date: Mon, 7 Oct 2024 00:29:29 +0200 Subject: [PATCH 6/9] small changes, delete oneapi --- src/main.cpp | 87 ++++++++++++++++++++-------------------------------- 1 file changed, 34 insertions(+), 53 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index e7af60a..7023bdb 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -46,7 +46,7 @@ #include #include #include -#include + #include #include @@ -224,7 +224,7 @@ int main(int argc, char **argv) { exit(0); } - RMSDDriver* driver = new RMSDDriver(controller, false); + auto* driver = new RMSDDriver(controller, false); driver->setReference(molecule1); driver->setTarget(molecule2); driver->start(); @@ -245,7 +245,7 @@ int main(int argc, char **argv) { exit(1); } - Docking* docking = new Docking(controller, false); + auto* docking = new Docking(controller, false); if (!docking->Initialise()) { docking->printError(); return 0; @@ -287,7 +287,7 @@ int main(int argc, char **argv) { return -1; } std::cout << controller << std::endl; - ConfScan* scan = new ConfScan(controller); + auto* scan = new ConfScan(controller); scan->setFileName(argv[2]); scan->start(); return 0; @@ -298,7 +298,7 @@ int main(int argc, char **argv) { return -1; } - ConfStat* stat = new ConfStat(controller); + auto* stat = new ConfStat(controller); stat->setFileName(argv[2]); stat->start(); return 0; @@ -496,7 +496,7 @@ int main(int argc, char **argv) { Molecule mol1 = Files::LoadFile(argv[2]); Molecule mol2 = Files::LoadFile(argv[3]); - NEBDocking* nebdock = new NEBDocking; + auto* nebdock = new NEBDocking; nebdock->setStructures(mol1, mol2); nebdock->setProtonTransfer(pt); nebdock->Prepare(); @@ -909,7 +909,7 @@ int main(int argc, char **argv) { sum_mass += gyr.second; sqrt_sum += sqrt(gyr.first); sqrt_sum_mass += sqrt(gyr.second); - std::cout << ":: " << gyr.first << " " << sum / double(count) << " " << gyr.second << " " << sum_mass / double(count) << " " << sqrt(gyr.first) << " " << sqrt_sum / double(count) << " " << sqrt(gyr.second) << " " << sqrt_sum_mass / double(count) << std::endl; + std::cout << ":: " << gyr.first << " " << sum / static_cast(count) << " " << gyr.second << " " << sum_mass / static_cast(count) << " " << sqrt(gyr.first) << " " << sqrt_sum / static_cast(count) << " " << sqrt(gyr.second) << " " << sqrt_sum_mass / static_cast(count) << std::endl; count++; } } else if (strcmp(argv[1], "-dipole") == 0) { @@ -925,7 +925,7 @@ int main(int argc, char **argv) { // TODO: if -scale then calc dipole with scalingfactor and xtb2 // TODO: if -methode then change methode - json blob = controller["dipole"]; // declare blob as json, + const json blob = controller["dipole"]; // declare blob as json, const why not used for now std::vector conformers; @@ -938,80 +938,61 @@ int main(int argc, char **argv) { interface.CalculateEnergy(false, true); // calc energy and charges and dipole moment mol.setPartialCharges(interface.Charges()); // calc Partial Charges and give it to mol - auto charges = interface.Charges(); // dec and init charges mol.setDipole(interface.Dipole() * au); // in eA - /* Output Dipole from XTB2 - std::cout << mol.AtomCount() << "\n" - << "Dipole " - << mol.getDipole()[0] << " " - << mol.getDipole()[1] << " " - << mol.getDipole()[2] << " : " - << mol.getDipole().norm() << "\n" - << std::endl;*/ - conformers.push_back(mol); - //mol.appendDipoleFile(file.Basename() + ".dip"); } - Molecule mol = conformers.at(0); // molecule in ground state + Molecule mol = conformers.at(0); // maybe molecule in ground state - std::cout << "\nxtb2-Dipole: " << mol.getDipole().norm() << std::endl << std::endl; + std::cout << "\n xtb2-Dipole: " << mol.getDipole().norm() << std::endl << std::endl; - Matrix theta (mol.AtomCount(), 1); - theta = DipoleScalingCalculation(conformers); - std::cout << "Analytic-Scaler:\n" + const auto theta = DipoleScalingCalculation(conformers); + std::cout << "Analytical Scaling vector:\n" << theta << "\n" << "Dipole: " << mol.CalculateDipoleMoment(theta).norm() << std::endl << std::endl; - Vector one = Eigen::VectorXd::Ones(mol.AtomCount()); + const Vector one = VectorXd::Ones(mol.AtomCount()); - auto result = OptimiseDipoleScaling(conformers, one); - std::cout << "LM-Scaler 1 as initial guess:\n" + const auto result = OptimiseDipoleScaling(conformers, one); + std::cout << "nonlinear Scaling vector, 1 as initial guess:\n" << result << "\n" << "Dipole: " << mol.CalculateDipoleMoment(result).norm() << std::endl << std::endl; - auto result1 = OptimiseDipoleScaling(conformers, theta); - std::cout << "LM-Scaler theta as initial guess:\n" - << result1 << "\n" - << "Dipole: " << mol.CalculateDipoleMoment(result1).norm() << std::endl - << std::endl; - - - auto result2 = OptimiseDipoleScaling(conformers, theta, true); - std::cout << "LM-Scaler with bond true:\n" + const auto result2 = OptimiseDipoleScaling(conformers, theta, true); + std::cout << "nonlinear Scaling vector, with bond true:\n" << result2 << "\n" << "Dipole: " << mol.CalculateDipoleMoment(result2, true).norm() << std::endl << std::endl; + //TODO make it faster... + double r2_anal = 0; double r2_LM = 0; - double r2_LM1 = 0; double r2_LM2 = 0; - double r2_anal_dn = 0; - double r2_LM_dn = 0; - double r2_LM1_dn = 0; - double r2_LM2_dn = 0; - + //double r2_anal_dn = 0; + //double r2_LM_dn = 0; + //double r2_LM1_dn = 0; + //double r2_LM2_dn = 0; for (const auto& conf : conformers) { - r2_anal += std::pow(conf.CalculateDipoleMoment(theta).norm() - conf.getDipole().norm(), 2); - r2_LM += std::pow(conf.CalculateDipoleMoment(result).norm() - conf.getDipole().norm(), 2); - r2_LM1 += std::pow(conf.CalculateDipoleMoment(result1).norm() - conf.getDipole().norm(), 2); - r2_LM2 += std::pow(conf.CalculateDipoleMoment(result2).norm() - conf.getDipole().norm(), 2); - /*r2_anal_dn += std::pow((conf.CalculateDipoleMoment(theta) - conf.getDipole()).norm(), 2); - r2_LM_dn += std::pow((conf.CalculateDipoleMoment(result) - conf.getDipole()).norm(), 2); - r2_LM1_dn += std::pow((conf.CalculateDipoleMoment(result1) - conf.getDipole()).norm(), 2); - r2_LM2_dn += std::pow((conf.CalculateDipoleMoment(result2) - conf.getDipole()).norm(), 2);*/ + const double residual = conf.CalculateDipoleMoment(theta).norm() - conf.getDipole().norm(); + r2_anal += residual * residual; + const double residual_1 = conf.CalculateDipoleMoment(result).norm() - conf.getDipole().norm(); + r2_LM += residual_1 * residual_1; + const double residual_2 = conf.CalculateDipoleMoment(result2).norm() - conf.getDipole().norm(); + r2_LM2 += residual_2 * residual_2; + //r2_anal_dn += std::pow((conf.CalculateDipoleMoment(theta) - conf.getDipole()).norm(), 2); + //r2_LM_dn += std::pow((conf.CalculateDipoleMoment(result) - conf.getDipole()).norm(), 2); + //r2_LM1_dn += std::pow((conf.CalculateDipoleMoment(result1) - conf.getDipole()).norm(), 2); + //r2_LM2_dn += std::pow((conf.CalculateDipoleMoment(result2) - conf.getDipole()).norm(), 2); } std::cout << "Residuals:" << std::endl << "anal: " << r2_anal << std::endl << "LM 1 as initial guess: " << r2_LM << std::endl - << "LM theta as initial guess: " << r2_LM1 << std::endl << "LM bond true: " << r2_LM2 << std::endl; - //TODO add JSON output std::vector vec_theta(theta.data(), theta.data() + theta.rows() * theta.cols()); json scaling_vector; scaling_vector["scaling_vector"] = Tools::DoubleVector2String(vec_theta); @@ -1038,7 +1019,7 @@ int main(int argc, char **argv) { } } else { bool centered = false; - bool hmass = 1; + bool hmass = true; for (std::size_t i = 2; i < argc; ++i) { if (strcmp(argv[i], "-center") == 0) { centered = true; From 6bfd1a2d86d2a46524ba2d26b2eea7047a3ac312 Mon Sep 17 00:00:00 2001 From: Gerd Gehrisch Date: Wed, 16 Oct 2024 17:23:00 +0200 Subject: [PATCH 7/9] change in fragments' dipole calculation --- src/capabilities/simplemd.cpp | 5 ++-- src/capabilities/simplemd.h | 2 +- src/core/molecule.cpp | 52 +++++++++++++++++++++++++++-------- src/core/molecule.h | 3 +- 4 files changed, 46 insertions(+), 16 deletions(-) diff --git a/src/capabilities/simplemd.cpp b/src/capabilities/simplemd.cpp index c7db6ea..db40c4a 100644 --- a/src/capabilities/simplemd.cpp +++ b/src/capabilities/simplemd.cpp @@ -338,6 +338,7 @@ bool SimpleMD::Initialise() } m_natoms = m_molecule.AtomCount(); + m_start_fragments = m_molecule.GetFragments(); m_scaling_vector = std::vector(m_natoms, 1); if (m_scaling_json != "none") { json scaling; @@ -1158,7 +1159,7 @@ void SimpleMD::start() //m_molecule.setPartialCharges(interface.Charges()); // calc Partial Charges and give it to mol //m_molecule.setDipole(interface.Dipole()*au); - m_curr_dipoles = m_molecule.CalculateDipoleMoments(m_scaling_vector); + m_curr_dipoles = m_molecule.CalculateDipoleMoments(m_scaling_vector, m_start_fragments); std::ofstream file; file.open(Basename() + "_dipole.out", std::ios_base::app); @@ -1168,7 +1169,7 @@ void SimpleMD::start() file << dipole.norm() << ", "; } - file << d.norm() << " " << m_molecule.getDipole().norm() << std::endl; + file << d[0] << " " << d[1] << " " << d[2] << " " << m_molecule.getDipole()[0] << " " << m_molecule.getDipole()[1] << " " << m_molecule.getDipole()[2] << std::endl; file.close(); } diff --git a/src/capabilities/simplemd.h b/src/capabilities/simplemd.h index cebbbe7..ee28db8 100644 --- a/src/capabilities/simplemd.h +++ b/src/capabilities/simplemd.h @@ -315,7 +315,7 @@ class SimpleMD : public CurcumaMethod { RMSDTraj* m_unqiue; const std::vector m_used_mass; std::vector m_rmsd_indicies; - std::vector > m_rmsd_fragments; + std::vector > m_rmsd_fragments, m_start_fragments; std::vector m_bias_structures; diff --git a/src/core/molecule.cpp b/src/core/molecule.cpp index 8e355a6..393cb72 100644 --- a/src/core/molecule.cpp +++ b/src/core/molecule.cpp @@ -696,14 +696,27 @@ void Molecule::LoadMolecule(const Mol* molecule) m_bonds = molecule->m_bonds; } -Molecule Molecule::getFragmentMolecule(int fragment) const +Molecule Molecule::getFragmentMolecule(const int fragment) const { // Let's make that one day faster, but not today ... // TODO inherit some more properties ... Molecule result; std::vector pCharges; auto atoms = GetFragments()[fragment]; - for (auto atom : atoms) { + for (const auto atom : atoms) { + result.addPair(Atom(atom)); + pCharges.push_back(m_charges[atom]); + } + result.setPartialCharges(pCharges); + return result; +} +Molecule Molecule::getFragmentMolecule(const std::vector& atoms) const +{ + // Let's make that one day faster, but not today ... + // TODO inherit some more properties ... + Molecule result; + std::vector pCharges; + for (const auto atom : atoms) { result.addPair(Atom(atom)); pCharges.push_back(m_charges[atom]); } @@ -904,23 +917,38 @@ Eigen::Vector3d Molecule::COM(bool protons, int fragment) return com; } -std::vector Molecule::CalculateDipoleMoments(const std::vector& scaling) const +std::vector Molecule::CalculateDipoleMoments(const std::vector& scaling, const std::vector>& fragments) const { // calc classic dipole moments of the every fragment with partial charges std::vector dipole_moments; if (m_charges.size() != m_geometry.rows()) { std::cout << "No partial charges available" << std::endl; return dipole_moments; } - for (int i = 0; i < GetFragments().size(); ++i) { - std::vector frag_scaling = {}; - for (int j = 0; j < m_fragments[i].size(); ++j) { - if (scaling.size() > j) - frag_scaling.push_back(scaling[j]); - else - frag_scaling.push_back(1.0); + if (!fragments.empty()) { + for (int i = 0; i < fragments.size(); ++i) { + std::vector frag_scaling = {}; + for (int j = 0; j < fragments[i].size(); ++j) { + if (scaling.size() > j) + frag_scaling.push_back(scaling[j]); + else + frag_scaling.push_back(1.0); + } + Molecule mol = getFragmentMolecule(fragments[i]); + dipole_moments.push_back(mol.CalculateDipoleMoment(frag_scaling)); + } + } + else { + for (int i = 0; i < GetFragments().size(); ++i) { + std::vector frag_scaling = {}; + for (int j = 0; j < m_fragments[i].size(); ++j) { + if (scaling.size() > j) + frag_scaling.push_back(scaling[j]); + else + frag_scaling.push_back(1.0); + } + Molecule mol = getFragmentMolecule(i); + dipole_moments.push_back(mol.CalculateDipoleMoment(frag_scaling)); } - Molecule mol = getFragmentMolecule(i); - dipole_moments.push_back(mol.CalculateDipoleMoment(frag_scaling)); } return dipole_moments; } diff --git a/src/core/molecule.h b/src/core/molecule.h index 9666271..8006a71 100644 --- a/src/core/molecule.h +++ b/src/core/molecule.h @@ -108,6 +108,7 @@ class Molecule std::vector GetBox() const; Molecule getFragmentMolecule(int fragment) const; + Molecule getFragmentMolecule(const std::vector& atoms) const; double CalculateDistance(int i, int j) const; std::pair GyrationRadius(double hmass = 1, bool hydrogen = true, int fragment = -1); @@ -173,7 +174,7 @@ class Molecule /*! \brief Methode to calculate the dipole moments of single molecules * */ - std::vector CalculateDipoleMoments(const std::vector& scaling = std::vector()) const; + std::vector CalculateDipoleMoments(const std::vector& scaling = std::vector(), const std::vector>& fragments = std::vector>()) const; /*! \brief Methode to calculate the dipole moments of whole structure * unit of dipol is electron times angstron From c66dc6dc7ede2ba6a94a07874215377529699cb0 Mon Sep 17 00:00:00 2001 From: Gerd Gehrisch Date: Mon, 28 Oct 2024 09:51:17 +0100 Subject: [PATCH 8/9] output of dipole from -dipole --- external/CxxThreadPool | 2 +- external/tblite | 2 +- external/xtb | 2 +- .../optimiser/OptimiseDipoleScaling.h | 6 +- src/main.cpp | 61 ++++++++++--------- 5 files changed, 38 insertions(+), 35 deletions(-) diff --git a/external/CxxThreadPool b/external/CxxThreadPool index ca5058b..e0f2fec 160000 --- a/external/CxxThreadPool +++ b/external/CxxThreadPool @@ -1 +1 @@ -Subproject commit ca5058bd27ec88cb7291781068a8635eab74bd32 +Subproject commit e0f2fec388d0fb1f58f6da1894729a04aa407cbb diff --git a/external/tblite b/external/tblite index c5844a4..9075e2e 160000 --- a/external/tblite +++ b/external/tblite @@ -1 +1 @@ -Subproject commit c5844a4d34d30a03118e54a87e3f9fd46b915ee9 +Subproject commit 9075e2e34d5e5b8a2db2d740c3310a0b35c46106 diff --git a/external/xtb b/external/xtb index 26b2801..d7a364b 160000 --- a/external/xtb +++ b/external/xtb @@ -1 +1 @@ -Subproject commit 26b28010e805f7d1aeeef39813feb473e69cc4be +Subproject commit d7a364b353c1f845b22192e0ab505f1c74cea209 diff --git a/src/capabilities/optimiser/OptimiseDipoleScaling.h b/src/capabilities/optimiser/OptimiseDipoleScaling.h index 44e36a2..d5e9954 100644 --- a/src/capabilities/optimiser/OptimiseDipoleScaling.h +++ b/src/capabilities/optimiser/OptimiseDipoleScaling.h @@ -60,15 +60,14 @@ struct OptDipoleFunctor : TFunctor { int operator()(const Vector& scaling, Eigen::VectorXd& fvec) const { // calculation of residuals for (int i = 0; i < m_conformers.size(); ++i) { - auto conf = m_conformers.at(i); - fvec(i) = (conf.getDipole() - conf.CalculateDipoleMoment(scaling, m_bond)).norm(); + const auto& conf = m_conformers.at(i); + fvec(i) = conf.getDipole().norm() - conf.CalculateDipoleMoment(scaling).norm(); } return 0; } int no_parameter; int no_points; std::vector m_conformers; - bool m_bond; int inputs() const { return no_parameter; } int values() const { return no_points; } @@ -80,7 +79,6 @@ inline Vector OptimiseDipoleScaling(const std::vector& conformers, Vec OptDipoleFunctor functor(2, conformers.size()); functor.m_conformers = conformers; - functor.m_bond = bond; Eigen::NumericalDiff numDiff(functor); Eigen::LevenbergMarquardt lm(numDiff); diff --git a/src/main.cpp b/src/main.cpp index 7023bdb..32e2ffd 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -955,50 +955,55 @@ int main(int argc, char **argv) { const Vector one = VectorXd::Ones(mol.AtomCount()); const auto result = OptimiseDipoleScaling(conformers, one); - std::cout << "nonlinear Scaling vector, 1 as initial guess:\n" + std::cout << "nonlinear Scaling vector:\n" << result << "\n" << "Dipole: " << mol.CalculateDipoleMoment(result).norm() << std::endl << std::endl; - const auto result2 = OptimiseDipoleScaling(conformers, theta, true); - std::cout << "nonlinear Scaling vector, with bond true:\n" - << result2 << "\n" - << "Dipole: " << mol.CalculateDipoleMoment(result2, true).norm() << std::endl - << std::endl; - //TODO make it faster... - double r2_anal = 0; - double r2_LM = 0; - double r2_LM2 = 0; - //double r2_anal_dn = 0; - //double r2_LM_dn = 0; - //double r2_LM1_dn = 0; - //double r2_LM2_dn = 0; + double r2_lin = 0; + double r2_nlin = 0; + double r2_lin_diffofnorm = 0; + double r2_nlin_diffofnorm = 0; for (const auto& conf : conformers) { - const double residual = conf.CalculateDipoleMoment(theta).norm() - conf.getDipole().norm(); - r2_anal += residual * residual; - const double residual_1 = conf.CalculateDipoleMoment(result).norm() - conf.getDipole().norm(); - r2_LM += residual_1 * residual_1; - const double residual_2 = conf.CalculateDipoleMoment(result2).norm() - conf.getDipole().norm(); - r2_LM2 += residual_2 * residual_2; - //r2_anal_dn += std::pow((conf.CalculateDipoleMoment(theta) - conf.getDipole()).norm(), 2); - //r2_LM_dn += std::pow((conf.CalculateDipoleMoment(result) - conf.getDipole()).norm(), 2); - //r2_LM1_dn += std::pow((conf.CalculateDipoleMoment(result1) - conf.getDipole()).norm(), 2); - //r2_LM2_dn += std::pow((conf.CalculateDipoleMoment(result2) - conf.getDipole()).norm(), 2); + const double residual = (conf.CalculateDipoleMoment(theta) - conf.getDipole()).norm(); + r2_lin += residual * residual; + const double residual_1 = (conf.CalculateDipoleMoment(result) - conf.getDipole()).norm(); + r2_nlin += residual_1 * residual_1; + const double residual_2 = conf.CalculateDipoleMoment(theta).norm() - conf.getDipole().norm(); + r2_lin_diffofnorm += residual_2 * residual_2; + const double residual_3 = conf.CalculateDipoleMoment(result).norm() - conf.getDipole().norm(); + r2_nlin_diffofnorm += residual_3 * residual_3; } - std::cout << "Residuals:" << std::endl - << "anal: " << r2_anal << std::endl - << "LM 1 as initial guess: " << r2_LM << std::endl - << "LM bond true: " << r2_LM2 << std::endl; + std::cout << "Residuals magnitute of diffrence of Vector:" << std::endl + << "linear: " << r2_lin << std::endl + << "nonlinear " << r2_nlin << std::endl; + std::cout << "Residuals diffrence of magnitute of Vector:" << std::endl + << "linear: " << r2_lin_diffofnorm << std::endl + << "nonlinear: " << r2_lin_diffofnorm << std::endl; std::vector vec_theta(theta.data(), theta.data() + theta.rows() * theta.cols()); + std::vector vec_nonlinear_scaling(result.data(), result.data() + result.rows() * result.cols()); json scaling_vector; scaling_vector["scaling_vector"] = Tools::DoubleVector2String(vec_theta); std::ofstream out(lm_basename + "_scaling_vector.json"); out << scaling_vector << std::endl; + std::ofstream file_dipole; + file_dipole.open(lm_basename + "_dipole.out", std::ios_base::app); + file_dipole << "linear Dipole of Fragments (x y z magn.); nonlinear Dipole of Fragments (x y z magn.); gfn2 Dipoles (x y z magn.)" << std::endl; + for (const auto& conf : conformers){ + const auto dipole_lin = conf.CalculateDipoleMoment(vec_theta); + const auto dipole_nlin = conf.CalculateDipoleMoment(vec_nonlinear_scaling); + const auto dipole_gfn2 = conf.getDipole(); + file_dipole << dipole_lin[0] << " " << dipole_lin[1] << " " << dipole_lin[2] << " " << dipole_lin.norm() << "; "; + file_dipole << dipole_nlin[0] << " " << dipole_nlin[1] << " " << dipole_nlin[2] << " " << dipole_nlin.norm() << "; "; + file_dipole << dipole_gfn2[0] << " " << dipole_gfn2[1] << " " << dipole_gfn2[2] << " " << dipole_gfn2.norm() << std::endl; + }; + file_dipole.close(); + } else if (strcmp(argv[1], "-stride") == 0) { From a8af13f2edd41a7e8af2743b6ad32612bb4b1f68 Mon Sep 17 00:00:00 2001 From: Gerd Gehrisch Date: Tue, 29 Oct 2024 18:00:12 +0100 Subject: [PATCH 9/9] dipole Calculation with linear and nonlinear scaling vector --- external/CxxThreadPool | 2 +- external/tblite | 2 +- external/xtb | 2 +- .../optimiser/OptimiseDipoleScaling.h | 36 +++--- src/capabilities/simplemd.cpp | 103 ++++++++--------- src/capabilities/simplemd.h | 4 +- src/main.cpp | 106 +++++++++--------- 7 files changed, 122 insertions(+), 133 deletions(-) diff --git a/external/CxxThreadPool b/external/CxxThreadPool index e0f2fec..ca5058b 160000 --- a/external/CxxThreadPool +++ b/external/CxxThreadPool @@ -1 +1 @@ -Subproject commit e0f2fec388d0fb1f58f6da1894729a04aa407cbb +Subproject commit ca5058bd27ec88cb7291781068a8635eab74bd32 diff --git a/external/tblite b/external/tblite index 9075e2e..c5844a4 160000 --- a/external/tblite +++ b/external/tblite @@ -1 +1 @@ -Subproject commit 9075e2e34d5e5b8a2db2d740c3310a0b35c46106 +Subproject commit c5844a4d34d30a03118e54a87e3f9fd46b915ee9 diff --git a/external/xtb b/external/xtb index d7a364b..26b2801 160000 --- a/external/xtb +++ b/external/xtb @@ -1 +1 @@ -Subproject commit d7a364b353c1f845b22192e0ab505f1c74cea209 +Subproject commit 26b28010e805f7d1aeeef39813feb473e69cc4be diff --git a/src/capabilities/optimiser/OptimiseDipoleScaling.h b/src/capabilities/optimiser/OptimiseDipoleScaling.h index d5e9954..f1cfc14 100644 --- a/src/capabilities/optimiser/OptimiseDipoleScaling.h +++ b/src/capabilities/optimiser/OptimiseDipoleScaling.h @@ -68,6 +68,7 @@ struct OptDipoleFunctor : TFunctor { int no_parameter; int no_points; std::vector m_conformers; + bool m_bond; int inputs() const { return no_parameter; } int values() const { return no_points; } @@ -79,6 +80,7 @@ inline Vector OptimiseDipoleScaling(const std::vector& conformers, Vec OptDipoleFunctor functor(2, conformers.size()); functor.m_conformers = conformers; + functor.m_bond = bond; Eigen::NumericalDiff numDiff(functor); Eigen::LevenbergMarquardt lm(numDiff); @@ -108,33 +110,29 @@ inline Vector OptimiseDipoleScaling(const std::vector& conformers, Vec return scaling; } -inline Matrix DipoleScalingCalculation(const std::vector& conformers) +inline Vector DipoleScalingCalculation(const std::vector& conformers) { - std::vector y; //Dipole moments - std::vector F; // Geometry multiplied with partial Charge const auto para_size = conformers[0].AtomCount(); const auto conformer_size = conformers.size(); + Matrix F(3*conformer_size,para_size); // Geometry multiplied with partial Charge + Matrix y(3*conformer_size,1); //Dipoles Matrix FTF = Matrix::Zero(para_size, para_size); Matrix FTy = Matrix::Zero(para_size, 1); for (int i = 0; i < conformer_size; ++i) { - y.push_back(conformers[i].getDipole()); // in eA - F.push_back(conformers[i].ChargeDistribution()); - } - for (auto k : F) { - for (int i = 0; i < para_size; ++i) { - for (int j = 0; j < para_size; ++j) { - FTF(i, j) += k(i, 0) * k(j, 0) + k(i, 1) * k(j, 1) + k(i, 2) * k(j, 2); - } - } - } - - for (int i = 0; i < conformer_size; ++i) { + y(3*i,0) = conformers[i].getDipole()[0]; + y(3*i+1,0) = conformers[i].getDipole()[1]; + y(3*i+2,0) = conformers[i].getDipole()[2]; + const auto& f = conformers[i].ChargeDistribution(); for (int j = 0; j < para_size; ++j) { - FTy(j) += y[i](0) * F[i](j, 0) + y[i](1) * F[i](j, 1) + y[i](2) * F[i](j, 2); + F(3*i,j) = f(j,0); + F(3*i+1,j) = f(j,1); + F(3*i+2,j) = f(j,2); } } - - Matrix Theta = FTF.colPivHouseholderQr().solve(FTy); - + const Vector Theta = (F.transpose()*F).colPivHouseholderQr().solve(F.transpose()*y); + //const Matrix H = (F*(F.transpose()*F).inverse()*F.transpose()).diagonal(); + //std::cout << "diag(H) x y z:" << std::endl; + //for (int i = 0; i < H.rows()/3; ++i) + // std::cout << H(3*i,0) << " " << H(3*i+1,0) << " " << H(3*i+2,0) << " " << std::endl; return Theta; } \ No newline at end of file diff --git a/src/capabilities/simplemd.cpp b/src/capabilities/simplemd.cpp index db40c4a..f6052a3 100644 --- a/src/capabilities/simplemd.cpp +++ b/src/capabilities/simplemd.cpp @@ -339,7 +339,8 @@ bool SimpleMD::Initialise() m_natoms = m_molecule.AtomCount(); m_start_fragments = m_molecule.GetFragments(); - m_scaling_vector = std::vector(m_natoms, 1); + m_scaling_vector_linear = std::vector(m_natoms, 1); + m_scaling_vector_nonlinear = std::vector(m_natoms, 1); if (m_scaling_json != "none") { json scaling; std::ifstream file(m_scaling_json); @@ -350,13 +351,17 @@ bool SimpleMD::Initialise() } catch ([[maybe_unused]] nlohmann::json::parse_error& e) { throw 404; } - std::string scaling_vector; + std::string scaling_vector_linear, scaling_vector_nonlinear; try { - scaling_vector = scaling["scaling_vector"]; + scaling_vector_linear = scaling["scaling_vector_linear"]; + scaling_vector_nonlinear = scaling["scaling_vector_nonlinear"]; } catch ([[maybe_unused]] json::type_error& e) { } - if (!scaling_vector.empty()) { - m_scaling_vector = Tools::String2DoubleVec(scaling_vector, "|"); + if (!scaling_vector_linear.empty()) { + m_scaling_vector_linear = Tools::String2DoubleVec(scaling_vector_linear, "|"); + } + if (!scaling_vector_nonlinear.empty()) { + m_scaling_vector_nonlinear = Tools::String2DoubleVec(scaling_vector_nonlinear, "|"); } } @@ -746,8 +751,6 @@ nlohmann::json SimpleMD::WriteRestartInformation() restart["average_Virial"] = m_average_virial_correction; restart["average_Wall"] = m_average_wall_potential; - restart["scaling_vector"] = Tools::DoubleVector2String(m_scaling_vector); - restart["rattle"] = m_rattle; restart["rattle_maxiter"] = m_rattle_maxiter; restart["rattle_dynamic_tol"] = m_rattle_tolerance; @@ -824,7 +827,7 @@ bool SimpleMD::LoadRestartInformation() bool SimpleMD::LoadRestartInformation(const json& state) { - std::string geometry, scaling_vector, velocities, constrains, xi, Q; + std::string geometry, velocities, constrains, xi, Q; try { m_method = state["method"]; @@ -913,11 +916,6 @@ bool SimpleMD::LoadRestartInformation(const json& state) } catch ([[maybe_unused]] json::type_error& e) { } - try { - scaling_vector = state["scaling_vector"]; - } catch ([[maybe_unused]] json::type_error& e) { - } - try { velocities = state["velocities"]; } catch ([[maybe_unused]] json::type_error& e) { @@ -980,9 +978,6 @@ bool SimpleMD::LoadRestartInformation(const json& state) if (!geometry.empty()) { m_current_geometry = Tools::String2DoubleVec(geometry, "|"); } - if (!scaling_vector.empty()) { - m_scaling_vector = Tools::String2DoubleVec(scaling_vector, "|"); - } if (!velocities.empty()) { m_velocities = Tools::String2DoubleVec(velocities, "|"); } @@ -1109,7 +1104,7 @@ void SimpleMD::start() PrintStatus(); /* Start MD Lopp here */ - for (; m_currentStep < m_maxtime;) { + while (m_currentStep < m_maxtime) { auto step0 = std::chrono::system_clock::now(); if (CheckStop() == true) { @@ -1150,28 +1145,30 @@ void SimpleMD::start() /////////// Dipole if (m_dipole && m_method == "gfn2") { - - //json blob; - // calc partialCharge with gnf2-xtb - //EnergyCalculator interface("gfn2", blob); // set method to gfn2-xtb - //interface.setMolecule(m_molecule); // set molecule for calc - //interface.CalculateEnergy(false, true); // calc energy and charges and dipole moment - //m_molecule.setPartialCharges(interface.Charges()); // calc Partial Charges and give it to mol - //m_molecule.setDipole(interface.Dipole()*au); - - m_curr_dipoles = m_molecule.CalculateDipoleMoments(m_scaling_vector, m_start_fragments); + //linear Dipoles + auto curr_dipoles_lin = m_molecule.CalculateDipoleMoments(m_scaling_vector_linear, m_start_fragments); + std::cout << m_scaling_vector_linear[0] << std::endl; std::ofstream file; - file.open(Basename() + "_dipole.out", std::ios_base::app); - + file.open(Basename() + "_dipole_linear.out", std::ios_base::app); Position d = {0,0,0}; - for (const auto& dipole : m_curr_dipoles) { - d += dipole; - file << dipole.norm() << ", "; + for (const auto& dipole_lin : curr_dipoles_lin) { + d += dipole_lin; + file << dipole_lin[0] << " " << dipole_lin[1] << " " << dipole_lin[2] << " " << dipole_lin.norm() << ", "; } - - file << d[0] << " " << d[1] << " " << d[2] << " " << m_molecule.getDipole()[0] << " " << m_molecule.getDipole()[1] << " " << m_molecule.getDipole()[2] << std::endl; + file << d[0] << " " << d[1] << " " << d[2] << ", " << m_molecule.getDipole()[0] << " " << m_molecule.getDipole()[1] << " " << m_molecule.getDipole()[2] << std::endl; file.close(); - + //nonlinear Dipoles + auto curr_dipoles_nlin = m_molecule.CalculateDipoleMoments(m_scaling_vector_nonlinear, m_start_fragments); + std::cout << m_scaling_vector_nonlinear[0] << std::endl; + std::ofstream file2; + file2.open(Basename() + "_dipole_nonlinear.out", std::ios_base::app); + Position sum = {0,0,0}; + for (const auto& dipole_nlin : curr_dipoles_nlin) { + sum += dipole_nlin; + file2 << dipole_nlin[0] << " " << dipole_nlin[1] << " " << dipole_nlin[2] << " " << dipole_nlin.norm() <<", "; + } + file2 << sum[0] << " " << sum[1] << " " << sum[2] << ", " << m_molecule.getDipole()[0] << " " << m_molecule.getDipole()[1] << " " << m_molecule.getDipole()[2] << std::endl; + file2.close(); } //////////// Dipole @@ -1222,12 +1219,12 @@ void SimpleMD::start() } if (m_writerestart > -1 && m_step % m_writerestart == 0) { - std::ofstream restart_file("curcuma_step_" + std::to_string(int(m_step * m_dT)) + ".json"); + std::ofstream restart_file("curcuma_step_" + std::to_string(static_cast(m_step * m_dT)) + ".json"); json restart; restart[MethodName()[0]] = WriteRestartInformation(); restart_file << restart << std::endl; } - if ((m_step && int(m_step * m_dT) % m_print == 0)) { + if ((m_step && static_cast(m_step * m_dT) % m_print == 0)) { m_Etot = m_Epot + m_Ekin; PrintStatus(); m_time_step = 0; @@ -1257,14 +1254,11 @@ void SimpleMD::start() if (m_thermostat == "csvr") std::cout << "Exchange with heat bath " << m_Ekin_exchange << "Eh" << std::endl; if (m_dipole) { - /* + double dipole = 0.0; - for( auto d : m_collected_dipole) - dipole += d; - dipole /= m_collected_dipole.size(); - std::cout << dipole*2.5418 << " average dipole in Debye and " << dipole*2.5418*3.3356e-30 << " Cm" << std::endl; - */ - std::cout << "Calculated averaged dipole moment " << m_aver_dipol * 2.5418 << " Debye and " << m_aver_dipol * 2.5418 * 3.3356 << " Cm [e-30]" << std::endl; + //std::cout << dipole*2.5418 << " average dipole in Debye and " << dipole*2.5418*3.3356e-30 << " Cm" << std::endl; + + std::cout << "Calculated averaged dipole moment " << m_aver_dipol_linear * 2.5418 << " Debye and " << m_aver_dipol_linear * 2.5418 * 3.3356 << " Cm [e-30]" << std::endl; } #ifdef USE_Plumed @@ -1277,7 +1271,7 @@ void SimpleMD::start() for (int i = 0; i < m_bias_threads.size(); ++i) { auto structures = m_bias_threads[i]->getBiasStructure(); for (int j = 0; j < structures.size(); ++j) { - std::cout << structures[j].rmsd_reference << "\t" << structures[j].energy << "\t" << structures[j].counter / double(m_colvar_incr) * 100 << std::endl; + std::cout << structures[j].rmsd_reference << "\t" << structures[j].energy << "\t" << structures[j].counter / static_cast(m_colvar_incr) * 100 << std::endl; m_rmsd_mtd_molecule.setGeometry(structures[j].geometry); m_rmsd_mtd_molecule.setEnergy(structures[j].energy); @@ -1300,7 +1294,7 @@ void SimpleMD::start() void SimpleMD::AdjustRattleTolerance() { - m_aver_rattle_Temp /= double(m_rattle_counter); + m_aver_rattle_Temp /= static_cast(m_rattle_counter); // std::pair pair(m_rattle_tolerance, m_aver_Temp); @@ -1993,11 +1987,10 @@ void SimpleMD::PrintStatus() const { const auto unix_timestamp = std::chrono::seconds(std::time(NULL)); - int current = std::chrono::milliseconds(unix_timestamp).count(); - double duration = (current - m_unix_started) / (1000.0 * double(m_currentStep)); + const int current = std::chrono::milliseconds(unix_timestamp).count(); + const double duration = (current - m_unix_started) / (1000.0 * static_cast(m_currentStep)); double remaining; - double tmp = (m_maxtime - m_currentStep) * duration / 60; - if (tmp >= 1) + if (const double tmp = (m_maxtime - m_currentStep) * duration / 60; tmp >= 1) remaining = tmp; else remaining = (m_maxtime - m_currentStep) * duration; @@ -2014,7 +2007,7 @@ void SimpleMD::PrintStatus() const #ifdef GCC if (m_dipole) std::cout << fmt::format("{1: ^{0}f} {2: ^{0}f} {3: ^{0}f} {4: ^{0}f} {5: ^{0}f} {6: ^{0}f} {7: ^{0}f} {8: ^{0}f} {9: ^{0}f} {10: ^{0}f} {11: ^{0}f} {12: ^{0}f} {13: ^{0}f} {14: ^{0}f} {15: ^{0}f} {16: ^{0}f}\n", 15, - m_currentStep / 1000, m_Epot, m_aver_Epot, m_Ekin, m_aver_Ekin, m_Etot, m_aver_Etot, m_T, m_aver_Temp, m_wall_potential, m_average_wall_potential, m_aver_dipol * 2.5418 * 3.3356, m_virial_correction, m_average_virial_correction, remaining, m_time_step / 1000.0); + m_currentStep / 1000, m_Epot, m_aver_Epot, m_Ekin, m_aver_Ekin, m_Etot, m_aver_Etot, m_T, m_aver_Temp, m_wall_potential, m_average_wall_potential, m_aver_dipol_linear * 2.5418 * 3.3356, m_virial_correction, m_average_virial_correction, remaining, m_time_step / 1000.0); else std::cout << fmt::format("{1: ^{0}f} {2: ^{0}f} {3: ^{0}f} {4: ^{0}f} {5: ^{0}f} {6: ^{0}f} {7: ^{0}f} {8: ^{0}f} {9: ^{0}f} {10: ^{0}f} {11: ^{0}f} {12: ^{0}f} {13: ^{0}f} {14: ^{0}f} {15: ^{0}f}\n", 15, m_currentStep / 1000, m_Epot, m_aver_Epot, m_Ekin, m_aver_Ekin, m_Etot, m_aver_Etot, m_T, m_aver_Temp, m_wall_potential, m_average_wall_potential, m_virial_correction, m_average_virial_correction, remaining, m_time_step / 1000.0); @@ -2041,10 +2034,10 @@ double SimpleMD::CleanEnergy(double* grad) interface.setMolecule(m_molecule); interface.updateGeometry(m_current_geometry); - double Energy = interface.CalculateEnergy(true); + const double Energy = interface.CalculateEnergy(true); interface.getGradient(grad); if (m_dipole && m_method == "gfn2") { - m_molecule.setDipole(interface.Dipole()*au); + m_molecule.setDipole(interface.Dipole()*au);//in eA m_molecule.setPartialCharges(interface.Charges()); } return Energy; @@ -2054,10 +2047,10 @@ double SimpleMD::FastEnergy(double* grad) { m_interface->updateGeometry(m_current_geometry); - double Energy = m_interface->CalculateEnergy(true); + const double Energy = m_interface->CalculateEnergy(true); m_interface->getGradient(grad); if (m_dipole && m_method == "gfn2") { - m_molecule.setDipole(m_interface->Dipole()*au); + m_molecule.setDipole(m_interface->Dipole()*au);// in eA m_molecule.setPartialCharges(m_interface->Charges()); } return Energy; diff --git a/src/capabilities/simplemd.h b/src/capabilities/simplemd.h index ee28db8..9af4c5b 100644 --- a/src/capabilities/simplemd.h +++ b/src/capabilities/simplemd.h @@ -292,7 +292,7 @@ class SimpleMD : public CurcumaMethod { int m_natoms = 0; int m_dump = 1; - double m_T = 0, m_Epot = 0, m_aver_Epot = 0, m_Ekin = 0, m_aver_Ekin = 0, m_Etot = 0, m_aver_Etot = 0, m_aver_dipol = 0; + double m_T = 0, m_Epot = 0, m_aver_Epot = 0, m_Ekin = 0, m_aver_Ekin = 0, m_Etot = 0, m_aver_Etot = 0, m_aver_dipol_linear = 0; double m_rm_COM = 100; int m_rm_COM_step = -1; int m_hmass = 1; @@ -302,7 +302,7 @@ class SimpleMD : public CurcumaMethod { double m_T0 = 298.15, m_aver_Temp = 0, m_aver_rattle_Temp = 0, m_rmsd = 1.5; double m_x0 = 0, m_y0 = 0, m_z0 = 0; double m_Ekin_exchange = 0.0; - std::vector m_current_geometry, m_mass, m_velocities, m_gradient, m_rmass, m_virial, m_gradient_bias, m_scaling_vector; + std::vector m_current_geometry, m_mass, m_velocities, m_gradient, m_rmass, m_virial, m_gradient_bias, m_scaling_vector_linear, m_scaling_vector_nonlinear; std::vector m_curr_dipoles; std::vector m_atomtype; Molecule m_molecule, m_reference, m_target, m_rmsd_mtd_molecule; diff --git a/src/main.cpp b/src/main.cpp index 32e2ffd..49b194c 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -931,79 +931,77 @@ int main(int argc, char **argv) { std::vector conformers; while (!file.AtEnd()) { // calculation and output dipole moment Molecule mol = file.Next(); // load Molecule - mol.Center(false); - - EnergyCalculator interface("gfn2", blob); // set method to gfn2-xtb and give - interface.setMolecule(mol); // set molecule for calc - interface.CalculateEnergy(false, true); // calc energy and charges and dipole moment - - mol.setPartialCharges(interface.Charges()); // calc Partial Charges and give it to mol - mol.setDipole(interface.Dipole() * au); // in eA - + mol.Center(false); //sets the Centroid to the origin + EnergyCalculator interface("gfn2", blob); // set method to gfn2-xtb + interface.setMolecule(mol); // set molecule + interface.CalculateEnergy(false, true); // calc energy and Wave function + mol.setPartialCharges(interface.Charges()); // calc partial Charges and set it to mol + mol.setDipole(interface.Dipole() * au); //calc dipole moments and set it to mol in eA conformers.push_back(mol); } Molecule mol = conformers.at(0); // maybe molecule in ground state + //Calculation of the scaling vector linear and nonlinear + const auto linear_vector = DipoleScalingCalculation(conformers); //linear + const auto nonlinear_vector = OptimiseDipoleScaling(conformers, linear_vector); //nonlinear + // output scaling vector as JSON + std::vector vec_linear_scaling(linear_vector.data(), linear_vector.data() + linear_vector.rows() * linear_vector.cols()); + std::vector vec_nonlinear_scaling(nonlinear_vector.data(), nonlinear_vector.data() + nonlinear_vector.rows() * nonlinear_vector.cols()); + json scaling_vector; + scaling_vector["scaling_vector_linear"] = Tools::DoubleVector2String(vec_linear_scaling); + scaling_vector["scaling_vector_nonlinear"] = Tools::DoubleVector2String(vec_nonlinear_scaling); + std::ofstream out(lm_basename + "_scaling_vector.json"); + out << scaling_vector << std::endl; - std::cout << "\n xtb2-Dipole: " << mol.getDipole().norm() << std::endl << std::endl; - - const auto theta = DipoleScalingCalculation(conformers); - std::cout << "Analytical Scaling vector:\n" - << theta << "\n" - << "Dipole: " << mol.CalculateDipoleMoment(theta).norm() << std::endl - << std::endl; - - const Vector one = VectorXd::Ones(mol.AtomCount()); - - const auto result = OptimiseDipoleScaling(conformers, one); - std::cout << "nonlinear Scaling vector:\n" - << result << "\n" - << "Dipole: " << mol.CalculateDipoleMoment(result).norm() << std::endl - << std::endl; - - //TODO make it faster... - + double mean_dipole_gfn2 = 0; + double mean_dipole_nonlinear = 0; + double mean_dipole_linear = 0; double r2_lin = 0; double r2_nlin = 0; double r2_lin_diffofnorm = 0; double r2_nlin_diffofnorm = 0; - - for (const auto& conf : conformers) { - const double residual = (conf.CalculateDipoleMoment(theta) - conf.getDipole()).norm(); - r2_lin += residual * residual; - const double residual_1 = (conf.CalculateDipoleMoment(result) - conf.getDipole()).norm(); - r2_nlin += residual_1 * residual_1; - const double residual_2 = conf.CalculateDipoleMoment(theta).norm() - conf.getDipole().norm(); - r2_lin_diffofnorm += residual_2 * residual_2; - const double residual_3 = conf.CalculateDipoleMoment(result).norm() - conf.getDipole().norm(); - r2_nlin_diffofnorm += residual_3 * residual_3; - } - std::cout << "Residuals magnitute of diffrence of Vector:" << std::endl - << "linear: " << r2_lin << std::endl - << "nonlinear " << r2_nlin << std::endl; - std::cout << "Residuals diffrence of magnitute of Vector:" << std::endl - << "linear: " << r2_lin_diffofnorm << std::endl - << "nonlinear: " << r2_lin_diffofnorm << std::endl; - - std::vector vec_theta(theta.data(), theta.data() + theta.rows() * theta.cols()); - std::vector vec_nonlinear_scaling(result.data(), result.data() + result.rows() * result.cols()); - json scaling_vector; - scaling_vector["scaling_vector"] = Tools::DoubleVector2String(vec_theta); - std::ofstream out(lm_basename + "_scaling_vector.json"); - out << scaling_vector << std::endl; - + //output Dipole moments + Calculation of Mean Dipole std::ofstream file_dipole; file_dipole.open(lm_basename + "_dipole.out", std::ios_base::app); - file_dipole << "linear Dipole of Fragments (x y z magn.); nonlinear Dipole of Fragments (x y z magn.); gfn2 Dipoles (x y z magn.)" << std::endl; + file_dipole << "linear Dipole (x y z magn.); nonlinear Dipole (x y z magn.); gfn2 Dipoles (x y z magn.)" << std::endl; for (const auto& conf : conformers){ - const auto dipole_lin = conf.CalculateDipoleMoment(vec_theta); + const auto dipole_lin = conf.CalculateDipoleMoment(vec_linear_scaling); const auto dipole_nlin = conf.CalculateDipoleMoment(vec_nonlinear_scaling); const auto dipole_gfn2 = conf.getDipole(); + mean_dipole_linear += dipole_lin.norm()/ conformers.size(); + mean_dipole_nonlinear += dipole_nlin.norm()/ conformers.size(); + mean_dipole_gfn2 += dipole_gfn2.norm()/ conformers.size(); file_dipole << dipole_lin[0] << " " << dipole_lin[1] << " " << dipole_lin[2] << " " << dipole_lin.norm() << "; "; file_dipole << dipole_nlin[0] << " " << dipole_nlin[1] << " " << dipole_nlin[2] << " " << dipole_nlin.norm() << "; "; file_dipole << dipole_gfn2[0] << " " << dipole_gfn2[1] << " " << dipole_gfn2[2] << " " << dipole_gfn2.norm() << std::endl; + const double residual = (conf.CalculateDipoleMoment(linear_vector) - conf.getDipole()).norm(); + r2_lin += residual * residual; + const double residual_1 = (conf.CalculateDipoleMoment(nonlinear_vector) - conf.getDipole()).norm(); + r2_nlin += residual_1 * residual_1; + const double residual_2 = conf.CalculateDipoleMoment(linear_vector).norm() - conf.getDipole().norm(); + r2_lin_diffofnorm += residual_2 * residual_2; + const double residual_3 = conf.CalculateDipoleMoment(nonlinear_vector).norm() - conf.getDipole().norm(); + r2_nlin_diffofnorm += residual_3 * residual_3; }; file_dipole.close(); + std::cout << "\nMean xtb2-Dipole: " << mean_dipole_gfn2 << " [eA], " << mean_dipole_gfn2/0.2082 << " [D]" << std::endl; + std::cout << "Mean linear Dipole: " << mean_dipole_linear << " [eA], " << mean_dipole_linear/0.2082 << " [D]" << std::endl + << "Mean nonlinear Dipole: " << mean_dipole_nonlinear << " [eA], " << mean_dipole_nonlinear/0.2082 << " [D]" << std::endl + << std::endl; + + std::cout << "linear Scaling vector:\n" + << linear_vector << "\n" + << "nonlinear Scaling vector:\n" + << nonlinear_vector << "\n" + << std::endl; + + std::cout << "Square Sum of Residuals of Components:" << std::endl + << "linear: " << r2_lin << std::endl + << "nonlinear " << r2_nlin << std::endl; + std::cout << "Square Sum of Residuals of Magnitudes" << std::endl + << "linear: " << r2_lin_diffofnorm << std::endl + << "nonlinear: " << r2_nlin_diffofnorm << std::endl; + } else if (strcmp(argv[1], "-stride") == 0) {