diff --git a/CMakeLists.txt b/CMakeLists.txt index 86eadf3..f68425d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -171,7 +171,7 @@ file(ARCHIVE_EXTRACT INPUT ${PROJECT_SOURCE_DIR}/external/eigen-3.4.0.zip DESTIN if(NOT EXISTS ${PROJECT_SOURCE_DIR}/external/ulysses.zip) file(DOWNLOAD https://gitlab.com/siriius/ulysses/-/archive/main/ulysses-main.zip ${PROJECT_SOURCE_DIR}/external/ulysses.zip TIMEOUT 60 # seconds - EXPECTED_HASH SHA256=1b55f9368c95f5a6dc334b6a86ad5a7583a397c9c59b4abb04f73ca4535cc393) + EXPECTED_HASH SHA256=af676fd3f0b98528bd6f7d12064192af6e4190d6da9808bdad803f1201c9feb6) endif() file(ARCHIVE_EXTRACT INPUT ${PROJECT_SOURCE_DIR}/external/ulysses.zip DESTINATION ${PROJECT_SOURCE_DIR}/external) @@ -204,18 +204,17 @@ set(curcuma_core_SRC src/capabilities/simplemd.cpp src/capabilities/hessian.cpp src/capabilities/qmdfffit.cpp - src/core/ulyssesinterface.cpp + src/core/qm_methods/eht.cpp + src/core/qm_methods/ulyssesinterface.cpp src/core/energycalculator.cpp src/core/molecule.cpp src/core/fileiterator.cpp - src/core/eigen_uff.cpp - src/core/qmdff.cpp - src/core/eht.cpp + #src/core/eigen_uff.cpp + #src/core/qmdff.cpp src/core/forcefieldthread.cpp src/core/forcefield.cpp src/core/forcefieldfunctions.h src/core/forcefieldgenerator.cpp - #src/core/forcefield_terms/qmdff_terms.h src/tools/formats.h src/tools/geometry.h src/tools/general.h @@ -231,7 +230,7 @@ set(curcuma_core_SRC add_library(km ${km_SRC}) set(ulysess_SRC - src/core/interface/ulysses.cpp + src/core/qm_methods/interface/ulysses.cpp ) add_library(ulysses_lib ${ulysess_SRC}) add_executable(ulysses_helper @@ -301,7 +300,7 @@ if(USE_XTB) target_link_libraries(xtb_helper lib-xtb-shared pthread dl) endif() set(curcuma_xtb_SRC - src/core/xtbinterface.cpp + src/core/qm_methods/xtbinterface.cpp ) add_library(curcuma_xtb ${curcuma_xtb_SRC}) @@ -343,7 +342,7 @@ if(USE_TBLITE) target_link_libraries(tblite_helper PUBLIC tblite-lib gfortran pthread) endif() set(curcuma_tblite_SRC - src/core/tbliteinterface.cpp + src/core/qm_methods/tbliteinterface.cpp ) add_library(curcuma_tblite ${curcuma_tblite_SRC}) @@ -362,7 +361,7 @@ if(USE_D3) target_link_libraries(dftd3_helper PUBLIC s-dftd3 gfortran pthread) endif() set(curcuma_D3_SRC - src/core/dftd3interface.cpp + src/core/qm_methods/dftd3interface.cpp ) add_library(curcuma_D3 ${curcuma_D3_SRC}) target_link_libraries(curcuma_D3 s-dftd3) @@ -396,7 +395,7 @@ if(USE_D4) endif() set(curcuma_d4_SRC - src/core/dftd4interface.cpp + src/core/qm_methods/dftd4interface.cpp ) add_library(curcuma_d4 ${curcuma_d4_SRC}) if(DEFINED D4LIBS_DIR AND DEFINED D4INCLUDE_DIR) @@ -452,13 +451,20 @@ target_sources(Continuous PRIVATE src/core/qmdff_par.h ) -add_test(NAME AAAbGal_mtemplate COMMAND AAAbGal mtemplate WORKING_DIRECTORY ${PROJECT_BINARY_DIR}/test_cases) -add_test(NAME AAAbGal_mhybrid COMMAND AAAbGal mhybrid WORKING_DIRECTORY ${PROJECT_BINARY_DIR}/test_cases) -add_test(NAME AAAbGal_template COMMAND AAAbGal template WORKING_DIRECTORY ${PROJECT_BINARY_DIR}/test_cases) -add_test(NAME AAAbGal_hybrid COMMAND AAAbGal hybrid WORKING_DIRECTORY ${PROJECT_BINARY_DIR}/test_cases) -add_test(NAME AAAbGal_incremental COMMAND AAAbGal incr WORKING_DIRECTORY ${PROJECT_BINARY_DIR}/test_cases) +#add_test(NAME AAAbGal_mtemplate COMMAND AAAbGal mtemplate WORKING_DIRECTORY ${PROJECT_BINARY_DIR}/test_cases) +#add_test(NAME AAAbGal_mhybrid COMMAND AAAbGal mhybrid WORKING_DIRECTORY ${PROJECT_BINARY_DIR}/test_cases) +#add_test(NAME AAAbGal_template COMMAND AAAbGal template WORKING_DIRECTORY ${PROJECT_BINARY_DIR}/test_cases) +add_test(NAME AAAbGal_subspace COMMAND AAAbGal subspace WORKING_DIRECTORY ${PROJECT_BINARY_DIR}/test_cases) +#add_test(NAME AAAbGal_incremental COMMAND AAAbGal incr WORKING_DIRECTORY ${PROJECT_BINARY_DIR}/test_cases) + +#set_tests_properties(AAAbGal_incremental PROPERTIES TIMEOUT 300) + +add_test(NAME confscan_subspace COMMAND confscan_test subspace WORKING_DIRECTORY ${PROJECT_BINARY_DIR}/test_cases) +add_test(NAME confscan_free COMMAND AAAbGal free WORKING_DIRECTORY ${PROJECT_BINARY_DIR}/test_cases) +add_test(NAME confscan_dtemplate COMMAND AAAbGal dtemplate WORKING_DIRECTORY ${PROJECT_BINARY_DIR}/test_cases) +add_test(NAME confscan_template COMMAND AAAbGal template WORKING_DIRECTORY ${PROJECT_BINARY_DIR}/test_cases) +add_test(NAME confscan_molalign COMMAND AAAbGal molalign WORKING_DIRECTORY ${PROJECT_BINARY_DIR}/test_cases) -set_tests_properties(AAAbGal_incremental PROPERTIES TIMEOUT 300) install(TARGETS curcuma RUNTIME DESTINATION bin) diff --git a/src/capabilities/confscan.cpp b/src/capabilities/confscan.cpp index e634bd5..9644b07 100644 --- a/src/capabilities/confscan.cpp +++ b/src/capabilities/confscan.cpp @@ -229,6 +229,7 @@ void ConfScan::LoadControlJson() m_MaxHTopoDiff = Json2KeyWord(m_defaults, "MaxHTopoDiff"); m_threads = m_defaults["threads"].get(); m_RMSDmethod = Json2KeyWord(m_defaults, "method"); + fmt::print(fg(fmt::color::green) | fmt::emphasis::bold, "\nPermutation of atomic indices performed according to {0} \n\n", m_RMSDmethod); if (m_RMSDmethod == "molalign") { @@ -271,6 +272,20 @@ void ConfScan::LoadControlJson() if (m_useorders == -1) m_useorders = 10; + + if (!m_silent) { + fmt::print(fg(fmt::color::cyan) | fmt::emphasis::bold, "\nCurrent Configuration:\n"); + fmt::print("Threads: {}\n", m_threads); + fmt::print("Molalign Tolerance: {}\n", m_molaligntol); + fmt::print("Force Reorder: {}\n", m_force_reorder); + fmt::print("Silent: {}\n", m_silent); + fmt::print("Write: {}\n", m_write); + fmt::print("Update Rotation: {}\n", m_update_rotation); + fmt::print("Split: {}\n", m_split); + fmt::print("Damping: {}\n", m_damping); + fmt::print("Molalign Bin: {}\n", m_molalign); + fmt::print("Method: {}\n", m_method); + } } bool ConfScan::openFile() @@ -451,9 +466,11 @@ bool ConfScan::LoadRestartInformation() } catch (json::type_error& e) { } } - for (const auto& vector : reorder_cached) - if (std::find(m_reorder_rules.begin(), m_reorder_rules.end(), vector) == m_reorder_rules.end()) - m_reorder_rules.push_back(vector); + if (m_restart) { + for (const auto& vector : reorder_cached) + if (std::find(m_reorder_rules.begin(), m_reorder_rules.end(), vector) == m_reorder_rules.end()) + m_reorder_rules.push_back(vector); + } } m_useRestart = files.size() == 1 && error != int(files.size()); std::cout << "Starting with " << m_reorder_rules.size() << " initial reorder rules." << std::endl; diff --git a/src/capabilities/confscan.h b/src/capabilities/confscan.h index 7b651c6..8bf56ae 100644 --- a/src/capabilities/confscan.h +++ b/src/capabilities/confscan.h @@ -271,6 +271,12 @@ class ConfScan : public CurcumaMethod { ConfScanThread* addThread(const Molecule* reference, const json& config, bool reuse_only = false); ConfScanThreadNoReorder* addThreadNoreorder(const Molecule* reference, const json& config); + inline int AcceptedCount() const { return m_stored_structures.size(); } + inline int ReorderSuccessfull() const { return m_reorder_successfull_count; } + inline int ReorderCount() const { return m_reorder_count; } + inline int ReorderSkippedCount() const { return m_skipped_count; } + inline int ReuseCount() const { return m_reordered_reused; } + private: void PrintSetUp(double dLE, double dLI, double dLH); void SetUp(); diff --git a/src/capabilities/curcumamethod.cpp b/src/capabilities/curcumamethod.cpp index 18d791e..9f47829 100644 --- a/src/capabilities/curcumamethod.cpp +++ b/src/capabilities/curcumamethod.cpp @@ -38,6 +38,10 @@ CurcumaMethod::CurcumaMethod(const json& defaults, const json& controller, bool , m_controller(controller) , m_silent(silent) { + if (controller.count("verbose") > 0) { + m_silent = false; + m_verbose = true; + } //m_curcuma_progress.open("curcuma_progress", std::ios::out); } diff --git a/src/capabilities/curcumamethod.h b/src/capabilities/curcumamethod.h index ca4d0cf..1942cae 100644 --- a/src/capabilities/curcumamethod.h +++ b/src/capabilities/curcumamethod.h @@ -68,6 +68,7 @@ class CurcumaMethod { void AppendError(const std::string& error) { m_error_list.push_back(error); } //std::filebuf m_curcuma_progress; bool m_silent = true; + bool m_verbose = false; private: /* Lets have this for all modules */ diff --git a/src/capabilities/rmsd.cpp b/src/capabilities/rmsd.cpp index 30abe44..0f8819c 100644 --- a/src/capabilities/rmsd.cpp +++ b/src/capabilities/rmsd.cpp @@ -1,6 +1,6 @@ /* * - * Copyright (C) 2019 - 2024 Conrad Hübler + * Copyright (C) 2019 - 2025 Conrad Hübler * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -167,7 +167,8 @@ void RMSDDriver::LoadControlJson() m_force_reorder = Json2KeyWord(m_defaults, "reorder"); m_protons = !Json2KeyWord(m_defaults, "heavy"); - m_silent = Json2KeyWord(m_defaults, "silent"); + if (!m_verbose) + m_silent = Json2KeyWord(m_defaults, "silent"); m_intermedia_storage = Json2KeyWord(m_defaults, "storage"); m_dynamic_center = Json2KeyWord(m_defaults, "DynamicCenter"); m_topo = Json2KeyWord(m_defaults, "topo"); @@ -235,6 +236,66 @@ void RMSDDriver::LoadControlJson() std::vector vector = Tools::String2Vector(order); if (vector.size() != 0) m_reorder_rules = vector; + + std::cout << m_defaults["reference_atoms"] << std::endl; + std::string reference_atoms = Json2KeyWord(m_defaults, "reference_atoms"); + std::string target_atoms = Json2KeyWord(m_defaults, "target_atoms"); + if (reference_atoms.size() > 0) + m_reference_atoms = Tools::ParseStringToVector(reference_atoms); + + if (target_atoms.size() > 0) { + m_target_atoms = Tools::ParseStringToVector(target_atoms); + } + if (m_reference_atoms.size() != m_target_atoms.size()) { + std::cout << "Number of reference and target atoms must be the same, exiting ..."; + exit(1); + } else if (m_reference_atoms.size() > 0) { + std::cout << "Aligning molecules using atoms: "; + for (int i = 0; i < m_reference_atoms.size(); ++i) + std::cout << m_reference_atoms[i] << " " << m_target_atoms[i] << "\n"; + } + if (!m_silent) { + fmt::print(fg(fmt::color::cyan) | fmt::emphasis::bold, "\nCurrent Configuration:\n"); + fmt::print("Fragment Reference: {}\n", m_fragment_reference); + fmt::print("Fragment Target: {}\n", m_fragment_target); + fmt::print("Fragment: {}\n", m_fragment); + fmt::print("Threads: {}\n", m_threads); + fmt::print("Initial Fragment: {}\n", m_initial_fragment); + fmt::print("PT: {}\n", m_pt); + fmt::print("Molalign Tolerance: {}\n", m_molaligntol); + fmt::print("Force Reorder: {}\n", m_force_reorder); + fmt::print("Protons: {}\n", m_protons); + fmt::print("Silent: {}\n", m_silent); + fmt::print("Intermedia Storage: {}\n", m_intermedia_storage); + fmt::print("Dynamic Center: {}\n", m_dynamic_center); + fmt::print("Topo: {}\n", m_topo); + fmt::print("Write: {}\n", m_write); + fmt::print("No Reorder: {}\n", m_noreorder); + fmt::print("Update Rotation: {}\n", m_update_rotation); + fmt::print("Split: {}\n", m_split); + fmt::print("No Free: {}\n", m_nofree); + fmt::print("Max Trial: {}\n", m_maxtrial); + fmt::print("KM Stat: {}\n", m_kmstat); + fmt::print("KM Convergence: {}\n", m_km_convergence); + fmt::print("Element: {}\n", m_element); + fmt::print("Check: {}\n", m_check); + fmt::print("Damping: {}\n", m_damping); + fmt::print("Molalign Bin: {}\n", m_molalign); + fmt::print("Method: {}\n", m_method); + fmt::print("Cost Matrix: {}\n", m_costmatrix); + fmt::print("Order: {}\n", order); + fmt::print("Cycles: {}\n", m_munkress_cycle); + fmt::print("Reference Atoms: {}\n", fmt::join(m_reference_atoms, ", ")); + fmt::print("Target Atoms: {}\n", fmt::join(m_target_atoms, ", ")); + } +} + +void RMSDDriver::setMatchingAtoms(const std::vector& reference_atoms, const std::vector& target_atoms) +{ + m_reference_atoms = reference_atoms; + m_target_atoms = target_atoms; +#pragma message("TODO: remove notreorder in the future") + m_noreorder = true; } void RMSDDriver::start() @@ -246,6 +307,18 @@ void RMSDDriver::start() RunTimer timer(false); clear(); bool rmsd_calculated = false; + + if (m_reference_atoms.size() == m_target_atoms.size() && m_reference_atoms.size() > 0) { + m_target_original = m_target; + m_reference_original = m_reference; + m_target.clear(); + m_reference.clear(); + for (int i = 0; i < m_reference_atoms.size(); ++i) { + m_reference.addPair(m_reference_original.Atom(m_reference_atoms[i])); + m_target.addPair(m_target_original.Atom(m_target_atoms[i])); + } + } + if (m_reference.AtomCount() < m_target.AtomCount()) { m_swap = true; Molecule tmp = m_reference; @@ -288,30 +361,42 @@ void RMSDDriver::start() } } Molecule temp_ref, temp_tar; - int consent = true; - for (int i = 0; i < m_reference.AtomCount() && i < m_target.AtomCount(); ++i) { - // std::cout << m_reference.Atom(i).first << " " << m_target.Atom(i).first << std::endl; - if (m_reference.Atom(i).first == m_target.Atom(i).first) { - temp_ref.addPair(m_reference.Atom(i)); - temp_tar.addPair(m_target.Atom(i)); - } else - consent = false; - } - if (consent) { - if (m_fragment_reference != -1 && m_fragment_target != -1) { - m_rmsd = CustomRotation(); - } else if (!rmsd_calculated) - m_rmsd = BestFitRMSD(); + if (m_target_atoms.size() == 0) { + int consent = true; + for (int i = 0; i < m_reference.AtomCount() && i < m_target.AtomCount(); ++i) { + if (m_reference.Atom(i).first == m_target.Atom(i).first) { + temp_ref.addPair(m_reference.Atom(i)); + temp_tar.addPair(m_target.Atom(i)); + } else + consent = false; + } + if (consent) { + if (m_fragment_reference != -1 && m_fragment_target != -1) { + m_rmsd = CustomRotation(); + } else if (!rmsd_calculated) + m_rmsd = BestFitRMSD(); + } else { + if (!m_silent) + fmt::print("Partial RMSD is calculated, only from those atoms, that match each other.\n\n\n"); + m_rmsd = PartialRMSD(temp_ref, temp_tar); + } } else { - if (!m_silent) - fmt::print("Partial RMSD is calculated, only from those atoms, that match each other.\n\n\n"); - m_rmsd = PartialRMSD(temp_ref, temp_tar); + m_rmsd = BestFitRMSD(); + Eigen::Matrix3d R = m_rotation; + auto reference = CenterMolecule(m_reference_original.getGeometry()); + auto target = CenterMolecule(m_target_original.getGeometry()); + m_target.clear(); + m_reference.clear(); + m_reference_aligned = m_reference_original; + m_target_aligned = m_target_original; + const auto t = RMSDFunctions::applyRotation(target, R); + m_reference_aligned.setGeometry(reference); + m_target_aligned.setGeometry(t); + m_reference.setGeometry(reference); + m_target.setGeometry(t); + // rmsd = RMSDFunctions::getRMSD(reference, t); } - /* - auto terms = IndivRMSD(m_reference, m_target); - for(const auto &i:terms) - std::cout << i << std::endl; - */ + m_htopo_diff = CompareTopoMatrix(m_reference_aligned.HydrogenBondMatrix(-1, -1), m_target_aligned.HydrogenBondMatrix(-1, -1)); if (!m_silent) { std::cout << std::endl @@ -323,13 +408,10 @@ void RMSDDriver::start() } if (m_swap) { Molecule reference = m_reference; - //Molecule reference_reorder = m_reference_reordered; Molecule reference_aligned = m_reference_aligned; m_reference = m_target; m_reference_aligned = m_target_aligned; - // m_reference_reordered = m_target_reordered; m_target = reference; - //m_target_reordered = reference_reorder; m_target_aligned = reference_aligned; } } @@ -346,13 +428,16 @@ double RMSDDriver::BestFitRMSD() double rmsd = 0; auto reference = CenterMolecule(m_reference.getGeometry()); auto target = CenterMolecule(m_target.getGeometry()); - const auto t = RMSDFunctions::getAligned(reference, target, 1); + // const auto t = RMSDFunctions::getAligned(reference, target, 1); + Eigen::Matrix3d R = RMSDFunctions::BestFitRotation(reference, target, 1); + const auto t = RMSDFunctions::applyRotation(target, R); m_reference_aligned.setGeometry(reference); m_target_aligned.setGeometry(t); m_reference.setGeometry(reference); m_target.setGeometry(t); rmsd = RMSDFunctions::getRMSD(reference, t); m_rmsd = rmsd; + m_rotation = R; return rmsd; } @@ -392,7 +477,7 @@ double RMSDDriver::CustomRotation() m_reference_aligned.setGeometry(reference); m_target_aligned.setGeometry(t); rmsd = RMSDFunctions::getRMSD(reference, t); - + m_rotation = rotation; return rmsd; } @@ -1364,21 +1449,7 @@ std::pair RMSDDriver::MakeCostMatrix(const Geometry& reference, for (int j = 0; j < m_reference.AtomCount(); ++j) { double d = (target.row(j) - reference.row(i)).norm(); double norm = (target.row(j).norm() - reference.row(i).norm()); - if (m_costmatrix == 2) - distance(i, j) = d; - else if (m_costmatrix == 1) - distance(i, j) = d * d; - else if (m_costmatrix == 3) - distance(i, j) = d + norm; - else if (m_costmatrix == 4) - distance(i, j) = d * d + norm * norm; - else if (m_costmatrix == 5) - distance(i, j) = d * norm; - else if (m_costmatrix == 5) - distance(i, j) = d * d * norm * norm; - else - distance(i, j) = d * d; - // + norm + distance(i, j) = Cost(d, norm, m_costmatrix); distance(i, j) += penalty * (m_reference.Atom(i).first != m_target.Atom(j).first); min = std::min(min, distance(i, j)); } @@ -1398,22 +1469,8 @@ std::pair RMSDDriver::MakeCostMatrix(const Geometry& reference, for (int j = 0; j < reference_atoms.size(); ++j) { double d = (target.row(j) - reference.row(i)).norm(); double norm = (target.row(j).norm() - reference.row(i).norm()); - if (costmatrix == 2) - distance(i, j) = d; - else if (costmatrix == 1) - distance(i, j) = d * d; - else if (costmatrix == 3) - distance(i, j) = d + norm; - else if (costmatrix == 4) - distance(i, j) = d * d + norm * norm; - else if (costmatrix == 5) - distance(i, j) = d * norm; - else if (costmatrix == 5) - distance(i, j) = d * d * norm * norm; - else - distance(i, j) = d * d; - - // + norm + distance(i, j) = Cost(d, norm, costmatrix); + distance(i, j) += penalty * (reference_atoms[i] != target_atoms[j]); min = std::min(min, distance(i, j)); } diff --git a/src/capabilities/rmsd.h b/src/capabilities/rmsd.h index 5592fc6..39823c9 100644 --- a/src/capabilities/rmsd.h +++ b/src/capabilities/rmsd.h @@ -1,6 +1,6 @@ /* * - * Copyright (C) 2019 - 2024 Conrad Hübler + * Copyright (C) 2019 - 2025 Conrad Hübler * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -77,6 +77,8 @@ static const json RMSDJson = { { "fragment", -1 }, { "fragment_reference", -1 }, { "fragment_target", -1 }, + { "reference_atoms", "" }, + { "target_atoms", "" }, { "init", -1 }, { "pt", 0 }, { "silent", false }, @@ -119,6 +121,8 @@ class RMSDDriver : public CurcumaMethod { m_target_original = target; } + void setMatchingAtoms(const std::vector& reference_atoms, const std::vector& target_atoms); + double Rules2RMSD(const std::vector rules, int fragment = -1); StructComp Rule2RMSD(const std::vector rules, int fragment = 1); @@ -278,6 +282,23 @@ class RMSDDriver : public CurcumaMethod { return AlignByVectorPair(pair.first, pair.second); } + static inline double Cost(double distance, double norm, int costmatrix) + { + if (costmatrix == 1) + return distance * distance; + else if (costmatrix == 2) + return distance; + else if (costmatrix == 3) + return distance + norm; + else if (costmatrix == 4) + return distance * distance + norm * norm; + else if (costmatrix == 5) + return distance * norm; + else if (costmatrix == 6) + return distance * distance * norm * norm; + else + return distance * distance; + } std::vector FillMissing(const Molecule& molecule, const std::vector& order); void InsertRotation(std::pair& rotation); @@ -305,7 +326,7 @@ class RMSDDriver : public CurcumaMethod { std::pair GetOperateVectors(const std::vector& reference_atoms, const std::vector& target_atoms); std::pair GetOperateVectors(const Molecule& reference, const Molecule& target); - Molecule m_reference, m_target, m_target_original, m_reference_aligned, m_target_aligned, m_target_reordered, m_reorder_reference, m_reorder_target, m_reference_centered, m_target_centered; + Molecule m_reference, m_target, m_target_original, m_reference_aligned, m_reference_original, m_target_aligned, m_target_reordered, m_reorder_reference, m_reorder_target, m_reference_centered, m_target_centered; Geometry m_reorder_reference_geometry; bool m_force_reorder = false, m_protons = true, m_print_intermediate = false, m_silent = false; std::vector> m_intermediate_results; @@ -329,6 +350,8 @@ class RMSDDriver : public CurcumaMethod { double m_cost_limit = 0; mutable int m_fragment = -1, m_fragment_reference = -1, m_fragment_target = -1; std::vector m_initial, m_element_templates; + std::vector m_reference_atoms, m_target_atoms; + Eigen::Matrix3d m_rotation; std::string m_molalign = "molalign", m_molalignarg = " -remap -fast -tol 10"; std::map m_prepared_cost_matrices; }; diff --git a/src/capabilities/simplemd.cpp b/src/capabilities/simplemd.cpp index 4b3cd2b..b49f2c9 100644 --- a/src/capabilities/simplemd.cpp +++ b/src/capabilities/simplemd.cpp @@ -1226,7 +1226,7 @@ void SimpleMD::start() plumed_cmd(m_plumedmain, "setStep", &m_step); plumed_cmd(m_plumedmain, "setPositions", &m_eigen_geometry.data()[0]); plumed_cmd(m_plumedmain, "setEnergy", &m_Epot); - plumed_cmd(m_plumedmain, "setForces", &m_gradient[0]); + plumed_cmd(m_plumedmain, "setForces", &m_eigen_gradient.data()[0]); plumed_cmd(m_plumedmain, "setVirial", &m_virial[0]); plumed_cmd(m_plumedmain, "setMasses", &m_eigen_masses.data()[0]); plumed_cmd(m_plumedmain, "prepareCalc", NULL); @@ -1506,7 +1506,7 @@ void SimpleMD::Verlet() plumed_cmd(m_plumedmain, "setPositions", &m_eigen_geometry.data()[0]); plumed_cmd(m_plumedmain, "setEnergy", &m_Epot); - plumed_cmd(m_plumedmain, "setForces", &m_gradient[0]); + plumed_cmd(m_plumedmain, "setForces", &m_eigen_gradient.data()[0]); plumed_cmd(m_plumedmain, "setVirial", &m_virial[0]); plumed_cmd(m_plumedmain, "setMasses", &m_eigen_masses.data()[0]); @@ -1917,7 +1917,7 @@ void SimpleMD::Rattle() plumed_cmd(m_plumedmain, "setPositions", &m_eigen_geometry.data()[0]); plumed_cmd(m_plumedmain, "setEnergy", &m_Epot); - plumed_cmd(m_plumedmain, "setForces", &m_gradient[0]); + plumed_cmd(m_plumedmain, "setForces", &m_eigen_gradient.data()[0]); plumed_cmd(m_plumedmain, "setVirial", &m_virial[0]); plumed_cmd(m_plumedmain, "setMasses", &m_eigen_masses.data()[0]); diff --git a/src/core/eht.cpp b/src/core/eht.cpp deleted file mode 100644 index dd1c8eb..0000000 --- a/src/core/eht.cpp +++ /dev/null @@ -1,387 +0,0 @@ -/* - * - * Copyright (C) 2023 Conrad Hübler - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - */ - -#include "src/core/global.h" -#include "src/core/molecule.h" - -#include "external/CxxThreadPool/include/CxxThreadPool.h" - -#include -#include - -#include - -#include "json.hpp" - -#include "eht.h" - -#include - -EHT::EHT() -{ -} - -std::vector EHT::MakeBasis() -{ - std::vector basisset; - for (int i = 0; i < m_mol.m_number_atoms; ++i) { - if (m_mol.m_atoms[i] == 1) { - m_num_electrons += 1; - STO_6G b; - b.index = i; - - ehtSTO_6GHs t; - b.alpha = t.alpha; - b.coeff = t.coeff; - b.sym = "s"; - b.e = -0.5; - basisset.push_back(b); - std::cout << "H" << std::endl; - } else if (m_mol.m_atoms[i] == 6) { - m_num_electrons += 4; - - STO_6G b; - b.index = i; - b.sym = "s"; - ehtSTO_6GCs t; - b.alpha = t.alpha; - b.coeff = t.coeff; - b.e = -0.7144; - - basisset.push_back(b); - ehtSTO_6GCp t2; - b.alpha = t2.alpha; - b.coeff = t2.coeff; - b.x = 1; - b.sym = "pz"; - b.e = -0.3921; - - basisset.push_back(b); - - b.x = 0; - b.y = 1; - b.sym = "px"; - basisset.push_back(b); - - b.y = 0; - b.z = 1; - b.sym = "py"; - basisset.push_back(b); - std::cout << "C" << std::endl; - } else if (m_mol.m_atoms[i] == 8) { - m_num_electrons += 6; - - STO_6G b; - b.index = i; - b.sym = "s"; - ehtSTO_6GOs t; - b.alpha = t.alpha; - b.coeff = t.coeff; - b.e = -1.1904; - - basisset.push_back(b); - ehtSTO_6GOp t2; - b.alpha = t2.alpha; - b.coeff = t2.coeff; - b.x = 1; - b.sym = "pz"; - b.e = -0.5827; - - basisset.push_back(b); - - b.x = 0; - b.y = 1; - b.sym = "px"; - basisset.push_back(b); - - b.y = 0; - b.z = 1; - b.sym = "py"; - basisset.push_back(b); - std::cout << "O" << std::endl; - } else if (m_mol.m_atoms[i] == 7) { - m_num_electrons += 5; - - STO_6G b; - b.index = i; - b.sym = "s"; - ehtSTO_6GNs t; - b.alpha = t.alpha; - b.coeff = t.coeff; - b.e = -0.9404; - - basisset.push_back(b); - ehtSTO_6GNp t2; - b.alpha = t2.alpha; - b.coeff = t2.coeff; - b.x = 1; - b.sym = "pz"; - b.e = -0.5110; - - basisset.push_back(b); - - b.x = 0; - b.y = 1; - b.sym = "px"; - basisset.push_back(b); - - b.y = 0; - b.z = 1; - b.sym = "py"; - basisset.push_back(b); - std::cout << "O" << std::endl; - } - } - return basisset; -} - -void EHT::Initialise() -{ - m_num_electrons = 0; - m_mo = Matrix::Zero(m_mol.m_number_atoms, m_mol.m_number_atoms); - m_energies = Vector::Zero(m_mol.m_number_atoms); -} - -void EHT::Calculate(double* gradient, bool verbose) -{ - m_verbose = verbose; - if (gradient) { - std::cout << "EHT does not support gradients." << std::endl; - } - - if (m_mol.m_number_atoms == 0) { - std::cout << "No molecule set." << std::endl; - return; - } - - // m_molecule.print_geom(); - auto basisset = MakeBasis(); - if (m_verbose) - std::cout << basisset.size() << std::endl; - Matrix S = MakeOverlap(basisset); - // std::cout << S << std::endl; - Matrix H = MakeH(S, basisset); - if (m_verbose) { - std::cout << std::endl - << std::endl; - // std::cout << H << std::endl; - } - Matrix S_1_2 = Matrix::Zero(basisset.size(), basisset.size()); - Eigen::JacobiSVD svd(S, Eigen::ComputeThinU | Eigen::ComputeThinV); - - Matrix IntS; - IntS.setZero(basisset.size(), basisset.size()); - - for (int i = 0; i < basisset.size(); ++i) - IntS(i, i) = 1 / sqrt(svd.singularValues()(i)); - - S_1_2 = svd.matrixU() * IntS * svd.matrixV().transpose(); - - Eigen::SelfAdjointEigenSolver diag_F; - Matrix F = S_1_2.transpose() * H * S_1_2; - diag_F.compute(F); - std::cout << std::endl; - m_energies = diag_F.eigenvalues(); - m_mo = diag_F.eigenvectors(); - - double energy = 0; - for (int i = 0; i < m_num_electrons / 2; ++i) { - energy += diag_F.eigenvalues()(i) * 2; - if (m_verbose) - std::cout << diag_F.eigenvalues()(i) << " 2" << std::endl; - } - std::cout << "Total electronic energy = " << energy << " Eh." << std::endl; - - // std::cout << diag_F.eigenvalues().sum(); -} - -Matrix EHT::MakeOverlap(const std::vector& basisset) -{ - Matrix S = Eigen::MatrixXd::Zero(basisset.size(), basisset.size()); - - std::vector norm(basisset.size(), 0); - - for (int i = 0; i < basisset.size(); ++i) { - STO_6G bi = basisset[i]; - Vector pi = m_mol.m_geometry.row(bi.index); // m_molecule.Atom(bi.index).second; - STO_6G bj = basisset[i]; - Vector pj = m_mol.m_geometry.row(bi.index); //.second; - double xx = 0; - if (bi.sym.compare("s") == 0 && bj.sym.compare("s") == 0) { - for (int c1 = 0; c1 < 6; ++c1) - for (int c2 = 0; c2 < 6; ++c2) - xx += ss(pi(0), pj(0), pi(1), pj(1), pi(2), pj(2), bi.alpha[c1], bj.alpha[c1], bi.coeff[c2], bj.coeff[c2]); - } else if ((bi.sym.compare("px") == 0 && bj.sym.compare("px") == 0)) { - for (int c1 = 0; c1 < 6; ++c1) - for (int c2 = 0; c2 < 6; ++c2) - xx += p2(pi(0), pj(0), pi(1), pj(1), pi(2), pj(2), bi.alpha[c1], bj.alpha[c1], bi.coeff[c2], bj.coeff[c2]); - } else if ((bi.sym.compare("py") == 0 && bj.sym.compare("py") == 0)) { - for (int c1 = 0; c1 < 6; ++c1) - for (int c2 = 0; c2 < 6; ++c2) - xx += p2(pi(1), pj(1), pi(0), pj(0), pi(2), pj(2), bi.alpha[c1], bj.alpha[c1], bi.coeff[c2], bj.coeff[c2]); - } else if ((bi.sym.compare("pz") == 0 && bj.sym.compare("pz") == 0)) { - for (int c1 = 0; c1 < 6; ++c1) - for (int c2 = 0; c2 < 6; ++c2) - xx += p2(pi(2), pj(2), pi(1), pj(1), pi(0), pj(0), bi.alpha[c1], bj.alpha[c1], bi.coeff[c2], bj.coeff[c2]); - } - norm[i] = 1 / sqrt(xx); - } - - for (int i = 0; i < basisset.size(); ++i) { - STO_6G bi = basisset[i]; - Vector pi = m_mol.m_geometry.row(bi.index); - for (int j = i; j < basisset.size(); ++j) { - STO_6G bj = basisset[j]; - Vector pj = m_mol.m_geometry.row(bj.index); - - double xx = 0; - - if (bi.sym.compare("s") == 0 && bj.sym.compare("s") == 0) { /* s-s orbitals */ - for (int c1 = 0; c1 < 6; ++c1) - for (int c2 = 0; c2 < 6; ++c2) - xx += ss(pi(0), pj(0), pi(1), pj(1), pi(2), pj(2), bi.alpha[c1], bj.alpha[c1], bi.coeff[c2], bj.coeff[c2]); - } else if ((bi.sym.compare("s") == 0 && bj.sym.compare("px") == 0) || (bi.sym.compare("px") == 0 && bj.sym.compare("s") == 0)) { /* s-px orbitals */ - if (bj.sym.compare("px") == 0) { - for (int c1 = 0; c1 < 6; ++c1) - for (int c2 = 0; c2 < 6; ++c2) - xx += sp(pi(0), pj(0), pi(1), pj(1), pi(2), pj(2), bi.alpha[c1], bj.alpha[c1], bi.coeff[c2], bj.coeff[c2]); - } else if (bi.sym.compare("px") == 0) { - for (int c1 = 0; c1 < 6; ++c1) - for (int c2 = 0; c2 < 6; ++c2) - xx += sp(pj(0), pi(0), pj(1), pi(1), pj(2), pi(2), bj.alpha[c2], bi.alpha[c2], bj.coeff[c1], bi.coeff[c1]); - } - } else if ((bi.sym.compare("s") == 0 && bj.sym.compare("py") == 0) || (bi.sym.compare("py") == 0 && bj.sym.compare("s") == 0)) { /* s-py orbitals */ - if (bj.sym.compare("py") == 0) { - for (int c1 = 0; c1 < 6; ++c1) - for (int c2 = 0; c2 < 6; ++c2) - xx += sp(pi(0), pj(1), pi(1), pj(0), pi(2), pj(2), bi.alpha[c1], bj.alpha[c1], bi.coeff[c2], bj.coeff[c2]); - } else if (bi.sym.compare("py") == 0) { - for (int c1 = 0; c1 < 6; ++c1) - for (int c2 = 0; c2 < 6; ++c2) - xx += sp(pj(1), pi(0), pj(0), pi(1), pj(2), pi(2), bj.alpha[c2], bi.alpha[c2], bj.coeff[c1], bi.coeff[c1]); - } - } else if ((bi.sym.compare("s") == 0 && bj.sym.compare("pz") == 0) || (bi.sym.compare("pz") == 0 && bj.sym.compare("s") == 0)) { /* s-pz orbitals */ - if (bj.sym.compare("pz") == 0) { - for (int c1 = 0; c1 < 6; ++c1) - for (int c2 = 0; c2 < 6; ++c2) - xx += sp(pi(0), pj(2), pi(1), pj(1), pi(2), pj(0), bi.alpha[c1], bj.alpha[c1], bi.coeff[c2], bj.coeff[c2]); - } else if (bi.sym.compare("pz") == 0) { - for (int c1 = 0; c1 < 6; ++c1) - for (int c2 = 0; c2 < 6; ++c2) - xx += sp(pj(2), pi(0), pj(1), pi(1), pj(0), pi(2), bj.alpha[c2], bi.alpha[c2], bj.coeff[c1], bi.coeff[c1]); - } - } else if ((bi.sym.compare("px") == 0 && bj.sym.compare("px") == 0)) { /* px-px orbitals */ - for (int c1 = 0; c1 < 6; ++c1) - for (int c2 = 0; c2 < 6; ++c2) - xx += p2(pi(0), pj(0), pi(1), pj(1), pi(2), pj(2), bi.alpha[c1], bj.alpha[c1], bi.coeff[c2], bj.coeff[c2]); - } else if ((bi.sym.compare("py") == 0 && bj.sym.compare("py") == 0)) { /* py-py orbitals */ - for (int c1 = 0; c1 < 6; ++c1) - for (int c2 = 0; c2 < 6; ++c2) - xx += p2(pi(1), pj(1), pi(0), pj(0), pi(2), pj(2), bi.alpha[c1], bj.alpha[c1], bi.coeff[c2], bj.coeff[c2]); - } else if ((bi.sym.compare("pz") == 0 && bj.sym.compare("pz") == 0)) { /* pz-pz orbitals */ - for (int c1 = 0; c1 < 6; ++c1) - for (int c2 = 0; c2 < 6; ++c2) - xx += p2(pi(2), pj(2), pi(1), pj(1), pi(0), pj(0), bi.alpha[c1], bj.alpha[c1], bi.coeff[c2], bj.coeff[c2]); - } else if ((bi.sym.compare("px") == 0 && bj.sym.compare("py") == 0) || (bi.sym.compare("py") == 0 && bj.sym.compare("px") == 0)) { /* px-py orbitals */ - if (bj.sym.compare("py") == 0) { - for (int c1 = 0; c1 < 6; ++c1) - for (int c2 = 0; c2 < 6; ++c2) - xx += pp(pi(0), pj(1), pi(1), pj(0), pi(2), pj(2), bi.alpha[c1], bj.alpha[c1], bi.coeff[c2], bj.coeff[c2]); - } else if (bi.sym.compare("py") == 0) { - for (int c1 = 0; c1 < 6; ++c1) - for (int c2 = 0; c2 < 6; ++c2) - xx += pp(pi(1), pj(0), pi(0), pj(1), pi(2), pj(2), bi.alpha[c1], bj.alpha[c1], bi.coeff[c2], bj.coeff[c2]); - } - } else if ((bi.sym.compare("px") == 0 && bj.sym.compare("pz") == 0) || (bi.sym.compare("pz") == 0 && bj.sym.compare("px") == 0)) { /* px-pz-orbitals */ - if (bj.sym.compare("pz") == 0) { - for (int c1 = 0; c1 < 6; ++c1) - for (int c2 = 0; c2 < 6; ++c2) - xx += pp(pi(0), pj(2), pi(1), pj(1), pi(2), pj(0), bi.alpha[c1], bj.alpha[c1], bi.coeff[c2], bj.coeff[c2]); - } else if (bi.sym.compare("pz") == 0) { - for (int c1 = 0; c1 < 6; ++c1) - for (int c2 = 0; c2 < 6; ++c2) - xx += pp(pi(2), pj(0), pi(1), pj(1), pi(0), pj(2), bi.alpha[c1], bj.alpha[c1], bi.coeff[c2], bj.coeff[c2]); - } - } else if ((bi.sym.compare("py") == 0 && bj.sym.compare("pz") == 0)) { /* py-pz-orbitals */ - - for (int c1 = 0; c1 < 6; ++c1) - for (int c2 = 0; c2 < 6; ++c2) - xx += pp(pi(1), pj(2), pi(0), pj(1), pi(2), pj(0), bi.alpha[c1], bj.alpha[c1], bi.coeff[c2], bj.coeff[c2]); - - } else if (bi.sym.compare("pz") == 0 && bj.sym.compare("py") == 0) { /* pz-py-orbitals */ - for (int c1 = 0; c1 < 6; ++c1) - for (int c2 = 0; c2 < 6; ++c2) - xx += pp(pi(2), pj(1), pi(1), pj(0), pi(0), pj(2), bi.alpha[c1], bj.alpha[c1], bi.coeff[c2], bj.coeff[c2]); - } else - std::cout << "something is missing " << bi.sym << " " << bj.sym << std::endl; - S(i, j) = xx * norm[i] * norm[j]; - S(j, i) = xx * norm[j] * norm[i]; - - // S(j,i) += xx*norm[j]*norm[i]*0.5; - - // std::cout << i << " " << j << " " << bi.sym << " " << bj.sym << " " << " "<< xx << " " <& basisset) -{ - double K = 1.75; - Matrix H = Eigen::MatrixXd::Zero(basisset.size(), basisset.size()); - for (int i = 0; i < basisset.size(); ++i) { - STO_6G bi = basisset[i]; - Vector pi = m_mol.m_geometry.row(bi.index); - for (int j = 0; j < basisset.size(); ++j) { - STO_6G bj = basisset[j]; - Vector pj = m_mol.m_geometry.row(bj.index); - if (i == j) - H(i, j) = bi.e; - else { - H(i, j) = K * S(i, j) * (bi.e + bj.e) / 2.0; - H(j, i) = K * S(j, i) * (bi.e + bj.e) / 2.0; - } - } - } - return H; -} - -double EHT::ss(double x1, double x2, double y1, double y2, double z1, double z2, double alpha1, double alpha2, double c1, double c2) -{ - double ex = exp(-((alpha1 * alpha2) / (alpha1 + alpha2)) * ((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2) + (z1 - z2) * (z1 - z2))); - return (c1 * c2 * (pow(2, 1.5) * pow(alpha1 * alpha2, 0.75) * pow(alpha1 + alpha2, -1.5) * ex)); -} - -double EHT::sp(double x1, double x2, double y1, double y2, double z1, double z2, double alpha1, double alpha2, double c1, double c2) -{ - double ex = exp(-((alpha1 * alpha2) / (alpha1 + alpha2)) * ((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2) + (z1 - z2) * (z1 - z2))); - return ((c1 * c2 * (4 * pow(2, 0.5) * pow(alpha1, 1.75) * pow(alpha2, 1.25) * ex * (x1 - x2))) * (pow(alpha1 + alpha2, -2.5))); -} - -double EHT::pp(double x1, double x2, double y1, double y2, double z1, double z2, double alpha1, double alpha2, double c1, double c2) -{ - double ex = exp(-((alpha1 * alpha2) / (alpha1 + alpha2)) * ((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2) + (z1 - z2) * (z1 - z2))); - return (c1 * c2 * ((-8 * (pow(2, 0.5) * (pow(alpha1 * alpha2, 2.25)) * ex * (x1 - x2) * (y1 - y2))) * (pow(alpha1 + alpha2, -3.5)))); -} - -double EHT::p2(double x1, double x2, double y1, double y2, double z1, double z2, double alpha1, double alpha2, double c1, double c2) -{ - double ex = exp(-((alpha1 * alpha2) / (alpha1 + alpha2)) * ((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2) + (z1 - z2) * (z1 - z2))); - return (c1 * c2 * ((4 * pow(2, 0.5) * pow(alpha1 * alpha2, 1.25) * ex * (alpha2 + alpha1 * (1 - 2 * alpha2 * (x1 - x2) * (x1 - x2))) * (pow(alpha1 + alpha2, -3.5))))); -} diff --git a/src/core/energycalculator.cpp b/src/core/energycalculator.cpp index a4d8ae4..c563d62 100644 --- a/src/core/energycalculator.cpp +++ b/src/core/energycalculator.cpp @@ -81,7 +81,10 @@ EnergyCalculator::EnergyCalculator(const std::string& method, const json& contro break; case 6: - delete m_eht; + m_qminterface = new EHT(); + m_ecengine = [this](bool gradient, bool verbose) { + m_qminterface->Calculation(gradient, verbose); + }; break; case 5: @@ -165,7 +168,7 @@ EnergyCalculator::~EnergyCalculator() break; case 6: - delete m_eht; + delete m_qminterface; break; case 5: @@ -223,8 +226,8 @@ void EnergyCalculator::setMolecule(const Mol& mol) break; case 6: - m_eht->setMolecule(mol); - m_eht->Initialise(); + m_qminterface->InitialiseMolecule(mol); + // m_eht->Initialise(); break; case 5: diff --git a/src/core/energycalculator.h b/src/core/energycalculator.h index 6a4b7b5..c728d10 100644 --- a/src/core/energycalculator.h +++ b/src/core/energycalculator.h @@ -22,26 +22,26 @@ // #include "src/tools/general.h" #ifdef USE_TBLITE -#include "src/core/tbliteinterface.h" +#include "src/core/qm_methods/tbliteinterface.h" #endif #ifdef USE_XTB -#include "src/core/xtbinterface.h" +#include "src/core/qm_methods/xtbinterface.h" #endif #ifdef USE_D3 -#include "src/core/dftd3interface.h" +#include "src/core/qm_methods/dftd3interface.h" #endif #ifdef USE_D4 -#include "src/core/dftd4interface.h" +#include "src/core/qqm_methods/dftd4interface.h" #endif -#include "src/core/eht.h" +#include "src/core/qm_methods/eht.h" // #include "src/core/eigen_uff.h" #include "src/core/forcefield.h" // #include "src/core/qmdff.h" -#include "src/core/ulyssesinterface.h" +#include "src/core/qm_methods/ulyssesinterface.h" #include diff --git a/src/core/forcefield.h b/src/core/forcefield.h index 81c1970..037290b 100644 --- a/src/core/forcefield.h +++ b/src/core/forcefield.h @@ -28,11 +28,11 @@ #include "external/CxxThreadPool/include/CxxThreadPool.h" #ifdef USE_D3 -#include "src/core/dftd3interface.h" +#include "src/core/qm_methods/dftd3interface.h" #endif #ifdef USE_D4 -#include "src/core/dftd4interface.h" +#include "src/core/qm_methods/dftd4interface.h" #endif #include "src/core/qmdff_par.h" diff --git a/src/core/forcefieldthread.h b/src/core/forcefieldthread.h index 3696687..90da3a8 100644 --- a/src/core/forcefieldthread.h +++ b/src/core/forcefieldthread.h @@ -26,11 +26,11 @@ #include "external/CxxThreadPool/include/CxxThreadPool.h" #ifdef USE_D3 -#include "src/core/dftd3interface.h" +#include "src/core/qm_methods/dftd3interface.h" #endif #ifdef USE_D4 -#include "src/core/dftd4interface.h" +#include "src/core/qm_methods/dftd4interface.h" #endif #include "src/core/qmdff_par.h" diff --git a/src/core/global.h b/src/core/global.h index 5c3b74b..17c78ce 100644 --- a/src/core/global.h +++ b/src/core/global.h @@ -215,8 +215,60 @@ inline json CLI2Json(int argc, char** argv) return controller; } */ +/* this is the 2nd github copilot version */ +/* +inline json CLI2Json(int argc, char** argv) +{ + json controller; + json key; + if (argc < 2) + return controller; + + std::string keyword = argv[1]; + keyword.erase(0, 1); + + for (int i = 2; i < argc; ++i) { + std::string current = argv[i]; + std::string sub = current.substr(0, 1); + if (sub == "-") { + current.erase(0, 1); + if ((i + 1) >= argc || argv[i + 1][0] == '-' || argv[i + 1] == std::string("true") || argv[i + 1] == std::string("+")) { + key[current] = true; + } else if (argv[i + 1] == std::string("false")) { + key[current] = false; + ++i; + } else { + std::string next = argv[i + 1]; + bool isNumber = true; + bool isVector = next.find("|") != std::string::npos || next.find(",") != std::string::npos || next.find(":") != std::string::npos; + bool isRange = next.find("-") != std::string::npos; + + if (!isVector && !isRange) { + try { + std::stod(next); + } catch (const std::invalid_argument&) { + isNumber = false; + } + } + + if (isNumber) { + key[current] = std::stod(next); + } else if (isVector || isRange) { + key[current] = next; + } else { + key[current] = next; + } + ++i; + } + } + } + + controller[keyword] = key; + return controller; +}*/ /* this is the github copilot version */ + inline json CLI2Json(int argc, char** argv) { json controller; diff --git a/src/core/molecule.cpp b/src/core/molecule.cpp index d5f5e31..be8e493 100644 --- a/src/core/molecule.cpp +++ b/src/core/molecule.cpp @@ -721,9 +721,11 @@ Molecule Molecule::getFragmentMolecule(const int fragment) const auto atoms = GetFragments()[fragment]; for (const auto atom : atoms) { result.addPair(Atom(atom)); - pCharges.push_back(m_charges[atom]); + if (atom < m_charges.size()) + pCharges.push_back(m_charges[atom]); } - result.setPartialCharges(pCharges); + if (pCharges.size() == atoms.size()) + result.setPartialCharges(pCharges); return result; } Molecule Molecule::getFragmentMolecule(const std::vector& atoms) const @@ -734,9 +736,11 @@ Molecule Molecule::getFragmentMolecule(const std::vector& atoms) const std::vector pCharges; for (const auto atom : atoms) { result.addPair(Atom(atom)); - pCharges.push_back(m_charges[atom]); + if (atom < m_charges.size()) + pCharges.push_back(m_charges[atom]); } - result.setPartialCharges(pCharges); + if (pCharges.size() == atoms.size()) + result.setPartialCharges(pCharges); return result; } Geometry Molecule::getGeometry(bool protons) const diff --git a/src/core/dftd3interface.cpp b/src/core/qm_methods/dftd3interface.cpp similarity index 99% rename from src/core/dftd3interface.cpp rename to src/core/qm_methods/dftd3interface.cpp index 58eb5da..87e9e5e 100644 --- a/src/core/dftd3interface.cpp +++ b/src/core/qm_methods/dftd3interface.cpp @@ -22,7 +22,7 @@ #include "src/core/global.h" #include "src/tools/general.h" -#include "src/core/interface/abstract_interface.h" +#include "interface/abstract_interface.h" #include #include diff --git a/src/core/dftd3interface.h b/src/core/qm_methods/dftd3interface.h similarity index 98% rename from src/core/dftd3interface.h rename to src/core/qm_methods/dftd3interface.h index be77a93..a934c2f 100644 --- a/src/core/dftd3interface.h +++ b/src/core/qm_methods/dftd3interface.h @@ -24,8 +24,8 @@ #include "s-dftd3.h" #endif +#include "interface/abstract_interface.h" #include "src/core/global.h" -#include "src/core/interface/abstract_interface.h" static json DFTD3Settings{ { "d_s6", 0 }, diff --git a/src/core/dftd4interface.cpp b/src/core/qm_methods/dftd4interface.cpp similarity index 98% rename from src/core/dftd4interface.cpp rename to src/core/qm_methods/dftd4interface.cpp index 0062db2..6b80d01 100644 --- a/src/core/dftd4interface.cpp +++ b/src/core/qm_methods/dftd4interface.cpp @@ -22,7 +22,7 @@ #include "dftd_econv.h" #include "dftd_geometry.h" -#include "src/core/interface/abstract_interface.h" +#include "core/qm_methods/interface/abstract_interface.h" #include "src/core/global.h" #include "src/tools/general.h" diff --git a/src/core/dftd4interface.h b/src/core/qm_methods/dftd4interface.h similarity index 97% rename from src/core/dftd4interface.h rename to src/core/qm_methods/dftd4interface.h index 1ff8d28..71040ec 100644 --- a/src/core/dftd4interface.h +++ b/src/core/qm_methods/dftd4interface.h @@ -26,8 +26,8 @@ #include "dftd_econv.h" #include "dftd_geometry.h" +#include "core/qm_methods/interface/abstract_interface.h" #include "src/core/global.h" -#include "src/core/interface/abstract_interface.h" static json DFTD4Settings{ { "d4_s6", 1.00 }, diff --git a/src/core/qm_methods/eht.cpp b/src/core/qm_methods/eht.cpp new file mode 100644 index 0000000..49f021b --- /dev/null +++ b/src/core/qm_methods/eht.cpp @@ -0,0 +1,265 @@ +/* + * + * Copyright (C) 2023 Conrad Hübler + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ + +#include "interface/abstract_interface.h" +#include "src/core/global.h" +#include "src/core/molecule.h" + +#include "external/CxxThreadPool/include/CxxThreadPool.h" + +#include +#include + +#include + +#include "integrals.h" + +#include "json.hpp" + +#include "eht.h" + +#include + +EHT::EHT() +{ +} + +Basisset EHT::MakeBasis() +{ + m_num_electrons = 0; + std::vector orbitals; + for (int i = 0; i < m_mol.m_number_atoms; ++i) { + if (m_mol.m_atoms[i] == 1) { + m_num_electrons += 1; + STO::Orbital o; + o.type = STO::S; + o.x = m_mol.m_geometry(i, 0); + o.y = m_mol.m_geometry(i, 1); + o.z = m_mol.m_geometry(i, 2); + o.zeta = 1.0; + o.VSIP = -0.5; + o.atom = i; + orbitals.push_back(o); + } else if (m_mol.m_atoms[i] == 6) { + m_num_electrons += 4; + STO::Orbital o; + o.type = STO::S; + o.x = m_mol.m_geometry(i, 0); + o.y = m_mol.m_geometry(i, 1); + o.z = m_mol.m_geometry(i, 2); + o.zeta = 1.7210; + o.VSIP = -0.7144; + o.atom = i; + orbitals.push_back(o); + + o.type = STO::PX; + o.x = m_mol.m_geometry(i, 0); + o.y = m_mol.m_geometry(i, 1); + o.z = m_mol.m_geometry(i, 2); + o.zeta = 1.62105; + o.VSIP = -0.3921; + orbitals.push_back(o); + + o.type = STO::PY; + o.x = m_mol.m_geometry(i, 0); + o.y = m_mol.m_geometry(i, 1); + o.z = m_mol.m_geometry(i, 2); + o.zeta = 1.62105; + o.VSIP = -0.3921; + orbitals.push_back(o); + + o.type = STO::PZ; + o.x = m_mol.m_geometry(i, 0); + o.y = m_mol.m_geometry(i, 1); + o.z = m_mol.m_geometry(i, 2); + o.zeta = 1.62105; + o.VSIP = -0.3921; + orbitals.push_back(o); + } else if (m_mol.m_atoms[i] == 8) { + m_num_electrons += 6; + STO::Orbital o; + o.type = STO::S; + o.x = m_mol.m_geometry(i, 0); + o.y = m_mol.m_geometry(i, 1); + o.z = m_mol.m_geometry(i, 2); + o.zeta = 2.2399; + o.VSIP = -1.1904; + o.atom = i; + orbitals.push_back(o); + + o.type = STO::PX; + o.x = m_mol.m_geometry(i, 0); + o.y = m_mol.m_geometry(i, 1); + o.z = m_mol.m_geometry(i, 2); + o.zeta = 2.0477; + o.VSIP = -1.1904; + o.atom = i; + orbitals.push_back(o); + + o.type = STO::PY; + o.x = m_mol.m_geometry(i, 0); + o.y = m_mol.m_geometry(i, 1); + o.z = m_mol.m_geometry(i, 2); + o.zeta = 2.0477; + o.VSIP = -1.1904; + o.atom = i; + orbitals.push_back(o); + + o.type = STO::PZ; + o.x = m_mol.m_geometry(i, 0); + o.y = m_mol.m_geometry(i, 1); + o.z = m_mol.m_geometry(i, 2); + o.zeta = 2.0477; + o.VSIP = -1.1904; + o.atom = i; + orbitals.push_back(o); + } + } + return orbitals; +} + +bool EHT::InitialiseMolecule() +{ + m_num_electrons = 0; + m_mo = Matrix::Zero(m_mol.m_number_atoms, m_mol.m_number_atoms); + m_energies = Vector::Zero(m_mol.m_number_atoms); + return true; +} + +double EHT::Calculation(bool gradient, bool verbose) +{ + double energy = 0; + m_verbose = verbose; + if (gradient) { + std::cout << "EHT does not support gradients." << std::endl; + } + + if (m_mol.m_number_atoms == 0) { + std::cout << "No molecule set." << std::endl; + return 0; + } + + // m_molecule.print_geom(); + auto basisset = MakeBasis(); + if (m_verbose) + std::cout << basisset.size() << std::endl; + Matrix S = MakeOverlap(basisset); + if (m_verbose) + std::cout << S << std::endl; + Matrix H = MakeH(S, basisset); + if (m_verbose) { + std::cout << std::endl + << std::endl; + std::cout << H << std::endl; + } + Matrix S_1_2 = Matrix::Zero(basisset.size(), basisset.size()); + Eigen::JacobiSVD svd(S, Eigen::ComputeThinU | Eigen::ComputeThinV); + + Matrix IntS; + IntS.setZero(basisset.size(), basisset.size()); + + for (int i = 0; i < basisset.size(); ++i) + IntS(i, i) = 1 / sqrt(svd.singularValues()(i)); + + S_1_2 = svd.matrixU() * IntS * svd.matrixV().transpose(); + + Eigen::SelfAdjointEigenSolver diag_F; + Matrix F = S_1_2.transpose() * H * S_1_2; + diag_F.compute(F); + std::cout << std::endl; + m_energies = diag_F.eigenvalues(); + m_mo = diag_F.eigenvectors(); + + for (int i = 0; i < m_num_electrons / 2; ++i) { + energy += diag_F.eigenvalues()(i) * 2; + if (m_verbose) + std::cout << diag_F.eigenvalues()(i) << " 2" << std::endl; + } + if (m_verbose) + std::cout << "Total electronic energy = " << energy << " Eh." << std::endl; + return energy; + + // std::cout << diag_F.eigenvalues().sum(); +} + +Matrix EHT::MakeOverlap(Basisset& basisset) +{ + Matrix S = Eigen::MatrixXd::Zero(basisset.size(), basisset.size()); + + std::vector norm(basisset.size(), 0); + /* for(int i = 0; i < basisset.size(); ++i) + { + norm[i] = STO::calculateOverlap(basisset[i], basisset[i]); + }*/ + for (int i = 0; i < basisset.size(); ++i) { + basisset[i].x = m_mol.m_geometry(basisset[i].atom, 0); + basisset[i].y = m_mol.m_geometry(basisset[i].atom, 1); + basisset[i].z = m_mol.m_geometry(basisset[i].atom, 2); + norm[i] = STO::calculateOverlap(basisset[i], basisset[i]); + std::cout << norm[i] << std::endl; + for (int j = 0; j <= i; ++j) { + basisset[j].x = m_mol.m_geometry(basisset[j].atom, 0); + basisset[j].y = m_mol.m_geometry(basisset[j].atom, 1); + basisset[j].z = m_mol.m_geometry(basisset[j].atom, 2); + + // if(norm[i] == 0 || norm[j] == 0) + // continue; + std::cout << basisset[i].x << " " << basisset[i].y << " " << basisset[i].z << std::endl; + std::cout << basisset[j].x << " " << basisset[j].y << " " << basisset[j].z << std::endl; + + double overlap = 0; + if (i != j) { + if (basisset[i].atom != basisset[j].atom) + overlap = STO::calculateOverlap(basisset[i], basisset[j]); + } else + overlap = 1; + + overlap = STO::calculateOverlap(basisset[i], basisset[j]); + + S(i, j) = S(j, i) = overlap; + std::cout << i << " " << j << " " << S(i, j) << " " << std::endl; + } + } + for (int i = 0; i < basisset.size(); ++i) + for (int j = 0; j <= i; ++j) { + S(i, j) /= sqrt(norm[i] * norm[j]); + S(j, i) = S(i, j); + } + + return S; +} + +Matrix EHT::MakeH(const Matrix& S, const Basisset& basisset) +{ + double K = 1.75; + Matrix H = Eigen::MatrixXd::Zero(basisset.size(), basisset.size()); + for (int i = 0; i < basisset.size(); ++i) { + STO::Orbital bi = basisset[i]; + for (int j = 0; j < basisset.size(); ++j) { + STO::Orbital bj = basisset[j]; + if (i == j) + H(i, j) = bi.VSIP; + else { + H(i, j) = K * S(i, j) * (bi.VSIP + bj.VSIP) / 2.0; + H(j, i) = K * S(j, i) * (bi.VSIP + bj.VSIP) / 2.0; + } + } + } + return H; +} diff --git a/src/core/eht.h b/src/core/qm_methods/eht.h similarity index 87% rename from src/core/eht.h rename to src/core/qm_methods/eht.h index 58d45b4..417e6fc 100644 --- a/src/core/eht.h +++ b/src/core/qm_methods/eht.h @@ -27,6 +27,10 @@ #include +#include "integrals.h" + +#include "interface/abstract_interface.h" + #include "json.hpp" struct ehtSTO_6GHs { @@ -72,22 +76,29 @@ struct STO_6G { double e = 0; }; -class EHT { +typedef std::vector Basisset; + +class EHT : public QMInterface { public: EHT(); - - void setMolecule(const Mol& mol) { m_mol = mol; } - void Initialise(); - void Calculate(double* gradient = nullptr, bool verbose = false); + virtual bool InitialiseMolecule(const Mol& molecule) override + { + m_mol = molecule; + return InitialiseMolecule(); + } + virtual bool InitialiseMolecule() override; + virtual double Calculation(bool gradient = false, bool verbose = false); Matrix MolecularOrbitals() const { return m_mo; } Vector Energies() const { return m_energies; } int NumElectrons() const { return m_num_electrons; } private: - std::vector MakeBasis(); - + // std::vector MakeBasis(); + Basisset MakeBasis(); Mol m_mol; + Matrix m_H, m_S; + /* Some integrals */ /* s - s - sigma bond */ double ss(double x1, double x2, double y1, double y2, double z1, double z2, double alpha1, double alpha2, double c1, double c2); @@ -101,8 +112,8 @@ class EHT { /* p - p - sigma bond */ double p2(double x1, double x2, double y1, double y2, double z1, double z2, double alpha1, double alpha2, double c1, double c2); - Matrix MakeOverlap(const std::vector& basisset); - Matrix MakeH(const Matrix& S, const std::vector& basisset); + Matrix MakeOverlap(Basisset& basisset); + Matrix MakeH(const Matrix& S, const Basisset& basisset); int m_num_electrons = 0; diff --git a/src/core/qm_methods/integrals.h b/src/core/qm_methods/integrals.h new file mode 100644 index 0000000..21fbcb4 --- /dev/null +++ b/src/core/qm_methods/integrals.h @@ -0,0 +1,333 @@ + + +#pragma once + +#include +static inline double factorial(int n) +{ + if (n <= 1) + return 1; + return n * factorial(n - 1); +} + +static inline double binomial(int n, int k) +{ + return factorial(n) / (factorial(k) * factorial(n - k)); +} + +// Richtungskosinusse +struct DirectionCosines { + double l, m, n; +}; +/* Integrals for Slater Type Orbitals */ + +namespace STO { + +enum OrbitalType { + S = 0, + PX = 1, + PY = 2, + PZ = 3, + DXY = 4, + DYZ = 5, + DZX = 6, + DX2Y2 = 7, + DZ2 = 8 +}; + +struct Orbital { + double x = 0, y = 0, z = 0; // Position + double zeta; // Slater exponent + double VSIP; // Valence State Ionization Potential + OrbitalType type; // Orbital type + int atom; +}; + +static inline DirectionCosines getDirectionCosines(const Orbital& orb1, const Orbital& orb2) +{ + double dx = orb2.x - orb1.x; + double dy = orb2.y - orb1.y; + double dz = orb2.z - orb1.z; + double R = std::sqrt(dx * dx + dy * dy + dz * dz); + + if (std::abs(dx) < 1e-8) + return { 1.0, 0.0, 0.0 }; + else if (std::abs(dy) < 1e-8) + return { 0.0, 1.0, 0.0 }; + else if (std::abs(dz) < 1e-8) + return { 0.0, 0.0, 1.0 }; + else + return { dx / R, dy / R, dz / R }; +} + +// Slater-Knotenfunktionen +static inline double SlaterRadial(int n, double zeta, double r) +{ + double norm = std::pow(2 * zeta, n + 0.5) / std::sqrt(factorial(2 * n)); + return norm * std::pow(r, n - 1) * std::exp(-zeta * r); +} + +static inline double calculateSSOverlap(double zeta1, double zeta2, double R) +{ + std::cout << "zeta1: " << zeta1 << " zeta2: " << zeta2 << " R: " << R << std::endl; + /* + double zeta_sum = zeta1 + zeta2; + double prefactor = 8.0 * pow(zeta1 * zeta2, 1.5) / pow(zeta_sum, 3); + double exponent = exp(-zeta_sum * R / 2.0); + double polynomial = 1.0 + (zeta_sum * R)/2.0 + (pow(zeta_sum, 2) * pow(R, 2))/12.0; + return prefactor * exponent * polynomial; + */ + double N = std::pow(zeta1 * zeta2, 0.75); + return N * std::exp(-0.5 * (zeta1 + zeta2) * R); +} + +static inline double calculateSPOverlap(double zeta_s, double zeta_p, double R, double l) +{ + /* + double zeta_sum = zeta_s + zeta_p; + double prefactor = sqrt(pow(zeta_s, 3) * pow(zeta_p, 5)) * 8.0 / pow(zeta_sum, 4); + double exponent = exp(-zeta_sum * R / 2.0); + double polynomial = (zeta_sum * R)/2.0 * (1.0 + (zeta_sum * R)/6.0); + return l*prefactor * exponent * polynomial; + */ + + double N = std::pow(zeta_s * zeta_p, 0.75); + double rho = (zeta_s + zeta_p) * R / 2.0; + return N * l * R * std::exp(-rho) * (1.0 + rho); +} + +static inline double calculatePPOverlap(double zeta1, double zeta2, double R, double l, bool same_axis) +{ + double N = std::pow(zeta1 * zeta2, 0.75); + double rho = (zeta1 + zeta2) * R / 2.0; + if (same_axis) { + if (R < 1e-10) + return N; + std::cout << N << "* " << std::exp(-rho) << "* (" << l * l << "* )" << 1.0 << "+ " << rho << " +" << rho * rho / 3.0 << " - " + << (rho * rho / 3.0) << "=" << N * std::exp(-rho) * (l * l * (1.0 + rho + rho * rho / 3.0) - (rho * rho / 3.0)) << std::endl; + return N * std::exp(-rho) * (l * l * (1.0 + rho + rho * rho / 3.0) - (rho * rho / 3.0)); + } else { + return N * l * l * std::exp(-rho) * (1.0 + rho + rho * rho / 3.0); + } +} + +static inline double calculateSDOverlap(double zeta1, double zeta2, double R, + const DirectionCosines& dc, OrbitalType d_type) +{ + double N = std::pow(zeta1 * zeta2, 0.75); + double rho = (zeta1 + zeta2) * R / 2.0; + + switch (d_type) { + case DXY: + return N * std::sqrt(3.0) * dc.l * dc.m * R * R * std::exp(-rho) * (1.0 + rho); + case DYZ: + return N * std::sqrt(3.0) * dc.m * dc.n * R * R * std::exp(-rho) * (1.0 + rho); + case DZX: + return N * std::sqrt(3.0) * dc.n * dc.l * R * R * std::exp(-rho) * (1.0 + rho); + case DX2Y2: + return N * 0.5 * std::sqrt(3.0) * (dc.l * dc.l - dc.m * dc.m) * R * R * std::exp(-rho) * (1.0 + rho); + case DZ2: + return N * (3.0 * dc.n * dc.n - 1.0) * R * R * std::exp(-rho) * (1.0 + rho); + default: + return 0.0; + } +} + +static inline double calculatePDOverlap(double zeta1, double zeta2, double R, + const DirectionCosines& dc, + OrbitalType p_type, OrbitalType d_type) +{ + double N = std::pow(zeta1 * zeta2, 0.75); + double rho = (zeta1 + zeta2) * R / 2.0; + double exp_term = std::exp(-rho); + + // Beispiel für px mit verschiedenen d-Orbitalen + if (p_type == PX) { + switch (d_type) { + case DXY: + return N * std::sqrt(3.0) * dc.m * R * exp_term * (1.0 + rho + rho * rho / 3.0); + case DYZ: + return 0.0; // Symmetriebedingt + case DZX: + return N * std::sqrt(3.0) * dc.n * R * exp_term * (1.0 + rho + rho * rho / 3.0); + case DX2Y2: + return N * std::sqrt(3.0) * dc.l * R * exp_term * (1.0 + rho + rho * rho / 3.0); + case DZ2: + return N * std::sqrt(3.0) * dc.l * R * exp_term * (1.0 + rho + rho * rho / 3.0); + } + } else if (p_type == PY) { + switch (d_type) { + case DXY: + return N * std::sqrt(3.0) * dc.l * R * exp_term * (1.0 + rho + rho * rho / 3.0); + case DYZ: + return N * std::sqrt(3.0) * dc.n * R * exp_term * (1.0 + rho + rho * rho / 3.0); + case DZX: + return 0.0; // Symmetriebedingt + case DX2Y2: + return -N * std::sqrt(3.0) * dc.m * R * exp_term * (1.0 + rho + rho * rho / 3.0); + case DZ2: + return -N * std::sqrt(3.0) * dc.m * R * exp_term * (1.0 + rho + rho * rho / 3.0); + } + } else if (p_type == PZ) { + switch (d_type) { + case DXY: + return 0.0; // Symmetriebedingt + case DYZ: + return N * std::sqrt(3.0) * dc.m * R * exp_term * (1.0 + rho + rho * rho / 3.0); + case DZX: + return N * std::sqrt(3.0) * dc.l * R * exp_term * (1.0 + rho + rho * rho / 3.0); + case DX2Y2: + return 0.0; // Symmetriebedingt + case DZ2: + return N * 2.0 * dc.n * R * exp_term * (1.0 + rho + rho * rho / 3.0); + } + } + return 0.0; +} + +static inline double calculateDDOverlap(double zeta1, double zeta2, double R, + const DirectionCosines& dc, + OrbitalType d_type1, OrbitalType d_type2) +{ + double N = std::pow(zeta1 * zeta2, 0.75); + double rho = (zeta1 + zeta2) * R / 2.0; + double exp_term = std::exp(-rho); + + // Matrix-Elemente für d-d Überlappung + if (d_type1 == d_type2) { + switch (d_type1) { + case DXY: + case DYZ: + case DZX: + return N * exp_term * (3.0 * std::pow(dc.l * dc.m, 2) * (1.0 + rho + rho * rho / 3.0 + rho * rho * rho / 15.0) - (rho * rho / 3.0 + rho * rho * rho / 15.0)); + case DX2Y2: + return N * exp_term * (0.75 * std::pow(dc.l * dc.l - dc.m * dc.m, 2) * (1.0 + rho + rho * rho / 3.0 + rho * rho * rho / 15.0)); + case DZ2: + return N * exp_term * (std::pow(3.0 * dc.n * dc.n - 1.0, 2) * (1.0 + rho + rho * rho / 3.0 + rho * rho * rho / 15.0)); + } + } + + // D-D Kreuzterme + // DXY mit anderen + if (d_type1 == DXY && d_type2 == DYZ) + return N * 3.0 * dc.l * dc.m * dc.m * dc.n * exp_term * (1.0 + rho + rho * rho / 3.0 + rho * rho * rho / 15.0); + + if (d_type1 == DXY && d_type2 == DZX) + return N * 3.0 * dc.l * dc.l * dc.m * dc.n * exp_term * (1.0 + rho + rho * rho / 3.0 + rho * rho * rho / 15.0); + + if (d_type1 == DXY && d_type2 == DX2Y2) + return N * 1.5 * dc.l * dc.m * (dc.l * dc.l - dc.m * dc.m) * exp_term * (1.0 + rho + rho * rho / 3.0 + rho * rho * rho / 15.0); + + if (d_type1 == DXY && d_type2 == DZ2) + return N * std::sqrt(3.0) * dc.l * dc.m * (3.0 * dc.n * dc.n - 1.0) * exp_term * (1.0 + rho + rho * rho / 3.0 + rho * rho * rho / 15.0); + + // DYZ mit anderen + if (d_type1 == DYZ && d_type2 == DZX) + return N * 3.0 * dc.l * dc.m * dc.n * dc.n * exp_term * (1.0 + rho + rho * rho / 3.0 + rho * rho * rho / 15.0); + + if (d_type1 == DYZ && d_type2 == DX2Y2) + return N * 1.5 * dc.m * dc.n * (dc.l * dc.l - dc.m * dc.m) * exp_term * (1.0 + rho + rho * rho / 3.0 + rho * rho * rho / 15.0); + + if (d_type1 == DYZ && d_type2 == DZ2) + return N * std::sqrt(3.0) * dc.m * dc.n * (3.0 * dc.n * dc.n - 1.0) * exp_term * (1.0 + rho + rho * rho / 3.0 + rho * rho * rho / 15.0); + + // DZX mit anderen + if (d_type1 == DZX && d_type2 == DX2Y2) + return N * 1.5 * dc.n * dc.l * (dc.l * dc.l - dc.m * dc.m) * exp_term * (1.0 + rho + rho * rho / 3.0 + rho * rho * rho / 15.0); + + if (d_type1 == DZX && d_type2 == DZ2) + return N * std::sqrt(3.0) * dc.n * dc.l * (3.0 * dc.n * dc.n - 1.0) * exp_term * (1.0 + rho + rho * rho / 3.0 + rho * rho * rho / 15.0); + + // DX2Y2 mit DZ2 + if (d_type1 == DX2Y2 && d_type2 == DZ2) + return N * 0.5 * std::sqrt(3.0) * (dc.l * dc.l - dc.m * dc.m) * (3.0 * dc.n * dc.n - 1.0) * exp_term * (1.0 + rho + rho * rho / 3.0 + rho * rho * rho / 15.0); + + // Symmetrische Matrix: wenn d_type1 > d_type2, rekursiver Aufruf mit vertauschten Argumenten + if (d_type1 > d_type2) + return calculateDDOverlap(zeta2, zeta1, R, dc, d_type2, d_type1); + + return 0.0; +} + +static inline double calculateOverlap(const Orbital& orb1, const Orbital& orb2) +{ + // Wenn gleiche Orbitale am gleichen Ort -> Überlappung = 1 + /* if (orb1.type == orb2.type && + std::abs(orb1.x - orb2.x) < 1e-10 && + std::abs(orb1.y - orb2.y) < 1e-10 && + std::abs(orb1.z - orb2.z) < 1e-10) { + return 1.0; + }*/ + + DirectionCosines dc = getDirectionCosines(orb1, orb2); + double R = std::sqrt(std::pow(orb2.x - orb1.x, 2) + std::pow(orb2.y - orb2.y, 2) + std::pow(orb2.z - orb2.z, 2)); + std::cout << "R: " << R << " "; + // if(R < 1e-10) + // return 1.0; + // Sortierung der Orbitale nach Typ für eindeutige Behandlung + OrbitalType type1 = orb1.type; + OrbitalType type2 = orb2.type; + double zeta1 = orb1.zeta; + double zeta2 = orb2.zeta; + + // Symmetrische Behandlung: Immer niedrigeren Typ zuerst + if (type1 > type2) { + std::swap(type1, type2); + std::swap(zeta1, zeta2); + } + + // Auswahl des richtigen Überlappungsintegrals basierend auf Orbital-Typen + if (type1 == S) { + std::cout << " S - "; + if (type2 == S) { + std::cout << "S "; + // s-s Überlappung + return calculateSSOverlap(zeta1, zeta2, R); + } else if (type2 <= PZ) { + std::cout << "P "; + // s-p Überlappung + double direction = 0.0; + if (type2 == PX) + direction = dc.l; + else if (type2 == PY) + direction = dc.m; + else + direction = dc.n; + return calculateSPOverlap(zeta1, zeta2, R, direction); + } else { + std::cout << "D "; + // s-d Überlappung + return calculateSDOverlap(zeta1, zeta2, R, dc, type2); + } + } else if (type1 <= PZ) { + std::cout << " P - "; + if (type2 <= PZ) { + std::cout << "P "; + // p-p Überlappung + bool same_axis = (type1 == type2); + double l1, l2; + if (type1 == PX) + l1 = dc.l; + else if (type1 == PY) + l1 = dc.m; + else + l1 = dc.n; + if (type2 == PX) + l2 = dc.l; + else if (type2 == PY) + l2 = dc.m; + else + l2 = dc.n; + return calculatePPOverlap(zeta1, zeta2, R, l1 * l2, same_axis); + } else { + std::cout << "D "; + // p-d Überlappung + return calculatePDOverlap(zeta1, zeta2, R, dc, type1, type2); + } + } else { + std::cout << " D - D "; + // d-d Überlappung + return calculateDDOverlap(zeta1, zeta2, R, dc, type1, type2); + } +} +} // namespace STO \ No newline at end of file diff --git a/src/core/interface/abstract_interface.h b/src/core/qm_methods/interface/abstract_interface.h similarity index 99% rename from src/core/interface/abstract_interface.h rename to src/core/qm_methods/interface/abstract_interface.h index 799f892..f021266 100644 --- a/src/core/interface/abstract_interface.h +++ b/src/core/qm_methods/interface/abstract_interface.h @@ -132,6 +132,7 @@ class QMInterface { m_spin = multi - 1; m_muli = multi; } + protected: bool m_initialised = false; Matrix m_geometry, m_gradient; diff --git a/src/core/interface/ulysses.cpp b/src/core/qm_methods/interface/ulysses.cpp similarity index 88% rename from src/core/interface/ulysses.cpp rename to src/core/qm_methods/interface/ulysses.cpp index 7524d4a..2c80ccf 100644 --- a/src/core/interface/ulysses.cpp +++ b/src/core/qm_methods/interface/ulysses.cpp @@ -17,16 +17,15 @@ * */ - #include "src/global_config.h" #ifdef USE_BLAS - #define EIGEN_USE_BLAS +#define EIGEN_USE_BLAS #endif #ifdef USE_MKL - #define EIGEN_USE_BLAS - #define EIGEN_USE_LAPACK +#define EIGEN_USE_BLAS +#define EIGEN_USE_LAPACK #endif #include "Eigen/Dense" @@ -39,8 +38,8 @@ #include "MNDOd.hpp" #include "Molecule.hpp" -#include #include +#include #include #include "ulysses.h" @@ -103,25 +102,23 @@ void UlyssesObject::Calculate(bool gradient, bool verbose) m_gradient = Matrix2Geom(grad); } } - } void UlyssesObject::setMethod(std::string& method) { if (method == "ugfn2") m_method = "gfn2"; - else - { - if (method.find("d3h4x") != std::string::npos) { - m_method = method.replace(method.find("-d3h4x"), 6, ""); - m_correction = "D3H4X"; - } else if (method.find("d3h+") != std::string::npos) { - m_method = method.replace(method.find("-d3h+"), 5, ""); - m_correction = "D3H+"; - } else { - m_method = method; - m_correction = "0"; - } + else { + if (method.find("d3h4x") != std::string::npos) { + m_method = method.replace(method.find("-d3h4x"), 6, ""); + m_correction = "D3H4X"; + } else if (method.find("d3h+") != std::string::npos) { + m_method = method.replace(method.find("-d3h+"), 5, ""); + m_correction = "D3H+"; + } else { + m_method = method; + m_correction = "0"; + } } } @@ -151,7 +148,7 @@ void UlyssesObject::UpdateGeometry(const Geometry& geom) } else if (m_method == "pm6") { m_electron->setGeometry(matrix); } - //m_electron->setGeometry(matrix); + // m_electron->setGeometry(matrix); } Vector UlyssesObject::Charges() const @@ -166,7 +163,6 @@ Vector UlyssesObject::Charges() const return Vector(); } - Vector UlyssesObject::OrbitalEnergies() const { std::vector OrbE = m_electron->EnMOs(); diff --git a/src/core/interface/ulysses.h b/src/core/qm_methods/interface/ulysses.h similarity index 94% rename from src/core/interface/ulysses.h rename to src/core/qm_methods/interface/ulysses.h index 4556388..01cb8ef 100644 --- a/src/core/interface/ulysses.h +++ b/src/core/qm_methods/interface/ulysses.h @@ -46,15 +46,16 @@ class UlyssesObject { Vector Charges() const; Vector OrbitalEnergies() const; Vector OrbitalOccupations() const; + private: BSet* m_bset; QCbasis* m_electron; - //MNDOd* m_mndo; - //GFN2* m_gfn2; + // MNDOd* m_mndo; + // GFN2* m_gfn2; std::string m_method, m_correction = "0"; double m_Tele; int m_SCFmaxiter; double m_energy; Geometry m_gradient; - //Vector m_charges, m_dipole, m_orbital_energies; + // Vector m_charges, m_dipole, m_orbital_energies; }; diff --git a/src/core/tbliteinterface.cpp b/src/core/qm_methods/tbliteinterface.cpp similarity index 99% rename from src/core/tbliteinterface.cpp rename to src/core/qm_methods/tbliteinterface.cpp index 3abba87..e5c46ca 100644 --- a/src/core/tbliteinterface.cpp +++ b/src/core/qm_methods/tbliteinterface.cpp @@ -70,7 +70,6 @@ TBLiteInterface::TBLiteInterface(const json& tblitesettings) tblite_set_context_verbosity(m_ctx, m_verbose); std::cout << "Initialising tblite with accuracy " << m_acc << " and SCFmaxiter " << m_SCFmaxiter << std::endl; - } TBLiteInterface::~TBLiteInterface() diff --git a/src/core/tbliteinterface.h b/src/core/qm_methods/tbliteinterface.h similarity index 96% rename from src/core/tbliteinterface.h rename to src/core/qm_methods/tbliteinterface.h index 2a9cb51..97d7495 100644 --- a/src/core/tbliteinterface.h +++ b/src/core/qm_methods/tbliteinterface.h @@ -19,14 +19,12 @@ #pragma once -#include "src/core/global.h" +#include "interface/abstract_interface.h" #ifndef tblite_delete #include "tblite.h" #endif -#include "src/core/interface/abstract_interface.h" - static json TBLiteSettings{ { "tb_acc", 1 }, { "SCFmaxiter", 100 }, @@ -36,7 +34,7 @@ static json TBLiteSettings{ { "tb_guess", "SAD" }, { "solv", "none" }, { "solv_eps", -1 }, - { "spin", 0} + { "spin", 0 } }; class TBLiteInterface : public QMInterface { diff --git a/src/core/ulyssesinterface.cpp b/src/core/qm_methods/ulyssesinterface.cpp similarity index 93% rename from src/core/ulyssesinterface.cpp rename to src/core/qm_methods/ulyssesinterface.cpp index 0d43f63..c038505 100644 --- a/src/core/ulyssesinterface.cpp +++ b/src/core/qm_methods/ulyssesinterface.cpp @@ -17,12 +17,11 @@ * */ -#include "interface/abstract_interface.h" - #include #include -#include "src/core/interface/ulysses.h" +#include "interface/abstract_interface.h" +#include "interface/ulysses.h" #include "ulyssesinterface.h" @@ -35,7 +34,6 @@ UlyssesInterface::UlyssesInterface(const json& ulyssessettings) m_method = m_ulyssessettings["method"]; m_mult = m_ulyssessettings["mult"]; m_ulysses = new UlyssesObject(); - } UlyssesInterface::~UlyssesInterface() @@ -47,7 +45,7 @@ bool UlyssesInterface::InitialiseMolecule() { m_ulysses->setMethod(m_method); m_ulysses->setMolecule(m_geometry, m_atoms, m_charge, m_mult, "C1"); - std::cout << "Initialising Ulysses with method " < diff --git a/src/main.cpp b/src/main.cpp index 6fbf94a..4fc324c 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -17,10 +17,10 @@ * along with this program. If not, see . * */ -#include "src/core/orcainterface.h" -#include "src/core/eht.h" #include "src/core/fileiterator.h" #include "src/core/molecule.h" +#include "src/core/orcainterface.h" +#include "src/core/qm_methods/eht.h" #include "src/capabilities/analysenciplot.h" #include "src/capabilities/confscan.h" @@ -235,7 +235,6 @@ int main(int argc, char **argv) { driver->TargetReorderd().writeXYZFile(tarfile + ".reordered.xyz"); std::cout << Tools::Vector2String(driver->ReorderRules()) << std::endl; - std::cout << driver->Gradient() << std::endl; delete driver; exit(0); @@ -886,11 +885,13 @@ int main(int argc, char **argv) { } FileIterator file(argv[2]); while (!file.AtEnd()) { + /* Molecule mol1 = file.Next(); EHT eht; - eht.setMolecule(mol1.getMolInfo()); - eht.Calculate(); + eht.InitialiseMolecule(mol1.getMolInfo()); + eht.Calculation(); + */ } } else if (strcmp(argv[1], "-gyration") == 0) { diff --git a/src/tools/general.h b/src/tools/general.h index a596802..329faf3 100644 --- a/src/tools/general.h +++ b/src/tools/general.h @@ -84,6 +84,29 @@ class RunTimer { namespace Tools { +inline std::vector ParseStringToVector(const std::string& input) +{ + std::vector result; + std::stringstream ss(input); + std::string token; + + while (std::getline(ss, token, ';')) { + size_t dash_pos = token.find('-'); + if (dash_pos != std::string::npos) { + int start = std::stoi(token.substr(0, dash_pos)); + int end = std::stoi(token.substr(dash_pos + 1)); + for (int i = start; i <= end; ++i) { + result.push_back(i); + } + } else { + result.push_back(std::stoi(token)); + } + } + + std::sort(result.begin(), result.end()); + return result; +} + inline StringList SplitString(const std::string& string) { StringList elements; diff --git a/test_cases/AAAbGal.cpp b/test_cases/AAAbGal.cpp index fd90355..3abb70c 100644 --- a/test_cases/AAAbGal.cpp +++ b/test_cases/AAAbGal.cpp @@ -44,6 +44,7 @@ int AAAbGal_mtemplate() // template driver->setReference(m1); driver->setTarget(m2); driver->start(); + std::cout << driver->RMSD() << std::endl; if (abs(driver->RMSD() - 0.457061) < 1e-5) { std::cout << "RMSD calculation with reordering passed (" << driver->RMSD() << ")." << std::endl; return 0; @@ -63,7 +64,7 @@ int AAAbGal_mhybrid() // hybrid json controller = RMSDJson; controller["threads"] = threads; controller["reorder"] = true; - controller["method"] = "hybrid"; + controller["method"] = "subspace"; RMSDDriver* driver = new RMSDDriver(controller, false); driver->setReference(m1); driver->setTarget(m2); @@ -102,7 +103,7 @@ int AAAbGal_template() // template } } -int AAAbGal_hybrid() // hybrid +int AAAbGal_subspace() // subspace { int threads = MaxThreads(); @@ -112,14 +113,14 @@ int AAAbGal_hybrid() // hybrid json controller = RMSDJson; controller["threads"] = threads; controller["reorder"] = true; - controller["method"] = "hybrid"; + controller["method"] = "subspace"; controller["nomunkres"] = true; RMSDDriver* driver = new RMSDDriver(controller, false); driver->setReference(m1); driver->setTarget(m2); driver->start(); - if (abs(driver->RMSD() - 1.21963) < 1e-5) { + if (abs(driver->RMSD() - 0.457061) < 1e-5) { std::cout << "RMSD calculation with reordering passed (" << driver->RMSD() << ")." << std::endl; return EXIT_SUCCESS; } else { @@ -159,8 +160,8 @@ int main(int argc, char** argv) return EXIT_FAILURE; if(std::string(argv[1]).compare("template") == 0) return AAAbGal_template(); - else if(std::string(argv[1]).compare("hybrid") == 0) - return AAAbGal_hybrid(); + else if (std::string(argv[1]).compare("subspace") == 0) + return AAAbGal_subspace(); else if(std::string(argv[1]).compare("incr") == 0) return AAAbGal_incr(); else if (std::string(argv[1]).compare("mhybrid") == 0) diff --git a/test_cases/CMakeLists.txt b/test_cases/CMakeLists.txt index 56e2c9e..6526a5a 100644 --- a/test_cases/CMakeLists.txt +++ b/test_cases/CMakeLists.txt @@ -24,6 +24,13 @@ target_link_libraries(AAAbGal curcuma_core) target_link_libraries(reorder_test curcuma_core) +file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/confscan/input.xyz + DESTINATION ${CMAKE_CURRENT_BINARY_DIR}) + +add_executable(confscan_test + confscan.cpp) + +target_link_libraries(confscan_test curcuma_core) #target_link_libraries(curcuma_tests curcuma_core)