votca 2024.1-dev
Loading...
Searching...
No Matches
molpol.cc
Go to the documentation of this file.
1/*
2 * Copyright 2009-2023 The VOTCA Development Team
3 * (http://www.votca.org)
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License")
6 *
7 * You may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
17 *
18 */
19
20// Local VOTCA includes
22#include "votca/xtp/qmpackage.h"
24
25// Local private VOTCA includes
26#include "molpol.h"
27
28namespace votca {
29namespace xtp {
30
32
33 std::string mps_input = options.ifExistsReturnElseReturnDefault<std::string>(
34 ".input", job_name_ + ".mps");
35
36 input_.LoadFromFile(mps_input);
37 mps_output_ = options.ifExistsReturnElseReturnDefault<std::string>(
38 ".output", job_name_ + "_polar.mps");
39 polar_options_ = options.get("polar");
40
41 // polar targer or qmpackage logfile
42 std::string mode = options.get("mode").as<std::string>();
43
44 if (mode == "file") {
45 Eigen::VectorXd target_vec =
46 options.get(".target_polarisability").as<Eigen::VectorXd>();
47 if (target_vec.size() != 6) {
48 throw std::runtime_error(
49 "ERROR <options.molpol.target> "
50 " should have this format: pxx pxy pxz pyy pyz pzz");
51 }
52 target_vec *= std::pow(tools::conv::ang2bohr, 3);
53 polarization_target_(0, 0) = target_vec(0);
54 polarization_target_(1, 0) = target_vec(1);
55 polarization_target_(0, 1) = target_vec(1);
56 polarization_target_(2, 0) = target_vec(2);
57 polarization_target_(0, 2) = target_vec(2);
58 polarization_target_(1, 1) = target_vec(3);
59 polarization_target_(2, 1) = target_vec(4);
60 polarization_target_(1, 2) = target_vec(4);
61 polarization_target_(2, 2) = target_vec(5);
62 } else {
63 std::string qm_package = options.get(".qmpackage").as<std::string>();
64 std::string log_file = options.get(".logfile").as<std::string>();
65 Logger log;
66 log.setPreface(Log::info, "\n ...");
67 log.setPreface(Log::error, "\n ...");
68 log.setPreface(Log::warning, "\n ...");
69 log.setPreface(Log::debug, "\n ...");
70 log.setReportLevel(Log::current_level);
71 log.setMultithreading(true);
72
73 // Set-up QM package
75 << "Using package <" << qm_package << ">" << std::flush;
77 std::unique_ptr<QMPackage> qmpack =
78 std::unique_ptr<QMPackage>(QMPackageFactory().Create(qm_package));
79 qmpack->setLog(&log);
80 qmpack->setRunDir(".");
81 qmpack->setLogFileName(log_file);
82 polarization_target_ = qmpack->GetPolarizability();
83 }
84
85 Eigen::VectorXd default_weights = Eigen::VectorXd::Ones(input_.size());
86 weights_ = options.ifExistsReturnElseReturnDefault<Eigen::VectorXd>(
87 ".weights", default_weights);
88
89 tolerance_pol_ = options.get(".tolerance").as<double>();
90 max_iter_ = options.get(".iterations").as<Index>();
91}
92
94 const PolarSegment& input, const Eigen::Vector3d& ext_field) const {
95 Logger log;
96 log.setMultithreading(false);
97 log.setCommonPreface("\n ...");
98
100
101 PolarRegion pol(0, log);
103 pol.push_back(input);
104
105 PolarSegment& workmol = pol[0];
106 for (PolarSite& site : workmol) {
107 site.V() = ext_field;
108 }
109 std::vector<std::unique_ptr<Region>> empty; // pol interacts with nobody else
110 pol.Evaluate(empty);
111 Eigen::Vector3d induced_dipole = Eigen::Vector3d::Zero();
112 for (const PolarSite& site : workmol) {
113 induced_dipole += site.Induced_Dipole();
114 }
115 if (Log::current_level > 0) {
116 std::cout << log;
117 }
118 return induced_dipole;
119}
120
121Eigen::Matrix3d MolPol::CalcClassicalPol(const PolarSegment& input) const {
122
123 double eVnm_2_hrtbohr = tools::conv::ev2hrt / tools::conv::nm2bohr;
124 double fieldstrength = (0.1 * eVnm_2_hrtbohr);
125 Eigen::Matrix3d polarization = Eigen::Matrix3d::Zero();
126 Eigen::Vector3d ext_field = fieldstrength * Eigen::Vector3d::UnitX();
127 // central differences scheme
128 Eigen::Vector3d dxplus = CalcInducedDipole(input, ext_field);
129 Eigen::Vector3d dxminus = CalcInducedDipole(input, -ext_field);
130 polarization.col(0) = dxplus - dxminus;
131 ext_field = fieldstrength * Eigen::Vector3d::UnitY();
132 Eigen::Vector3d dyplus = CalcInducedDipole(input, ext_field);
133 Eigen::Vector3d dyminus = CalcInducedDipole(input, -ext_field);
134 polarization.col(1) = dyplus - dyminus;
135 ext_field = fieldstrength * Eigen::Vector3d::UnitZ();
136 Eigen::Vector3d dzplus = CalcInducedDipole(input, ext_field);
137 Eigen::Vector3d dzminus = CalcInducedDipole(input, -ext_field);
138 polarization.col(2) = dzplus - dzminus;
139
140 return -polarization / (2 * fieldstrength);
141}
142
143void MolPol::Printpolarization(const Eigen::Matrix3d& result) const {
144 std::cout << std::endl << "First principle polarization [A^3]" << std::flush;
145 double conversion = std::pow(tools::conv::bohr2ang, 3);
146 std::cout << std::endl << polarization_target_ * conversion << std::flush;
147 std::cout << std::endl << "Scaled classical polarization [A^3]" << std::flush;
148 std::cout << std::endl << result * conversion << std::flush;
149 std::cout << std::endl
150 << "EigenValues classical polarization [A^3]" << std::flush;
151 Eigen::SelfAdjointEigenSolver<Eigen::Matrix3d> es2;
152 es2.computeDirect(result, Eigen::EigenvaluesOnly);
153 Eigen::Matrix3d diag = es2.eigenvalues().asDiagonal();
154 std::cout << std::endl << diag * conversion << std::flush;
155}
156
158
159 PolarSegment polar = input_;
160 Eigen::SelfAdjointEigenSolver<Eigen::Matrix3d> es;
161 es.computeDirect(polarization_target_, Eigen::EigenvaluesOnly);
162 const double pol_volume_target = std::pow(es.eigenvalues().prod(), 1.0 / 3.0);
163 for (Index iter = 0; iter < max_iter_; iter++) {
164
165 Eigen::SelfAdjointEigenSolver<Eigen::Matrix3d> es2;
166 Eigen::Matrix3d pol = CalcClassicalPol(polar);
167 es2.computeDirect(pol, Eigen::EigenvaluesOnly);
168 const double pol_volume_iter =
169 std::pow(es2.eigenvalues().prod(), 1.0 / 3.0);
170 double scale = pol_volume_target / pol_volume_iter - 1;
171 std::cout << "\nIteration " << iter + 1 << " of " << max_iter_
172 << " target:" << pol_volume_target
173 << " current:" << pol_volume_iter << std::endl;
174
175 for (Index i = 0; i < polar.size(); i++) {
176 Eigen::Matrix3d local_pol = polar[i].getpolarization();
177 polar[i].setpolarization(local_pol * (1 + scale * weights_[i]));
178 }
179
180 if (std::abs(scale) < tolerance_pol_) {
181 std::cout << std::endl
182 << "... ... Iterative refinement : *CONVERGED*" << std::flush;
183 std::cout << std::endl
184 << "... ... Scaling coefficient : " << scale << std::flush;
185 polar.WriteMPS(mps_output_, "MOLPOL (OPTIMIZED)");
187 break;
188 } else if (iter == (max_iter_ - 1)) {
189 std::cout << std::endl
190 << "... ... Iterative refinement : *FAILED*" << std::flush;
191 std::cout << std::endl
192 << "... ... ERROR Convergence not achieved. "
193 << "Check your input mps-file, target polarizability <target> "
194 << std::flush;
196 }
197 }
198 return true;
199}
200
201} // namespace xtp
202} // namespace votca
class to manage program options with xml serialization functionality
Definition property.h:55
Property & get(const std::string &key)
get existing property
Definition property.cc:79
T as() const
return value as type
Definition property.h:283
T ifExistsReturnElseReturnDefault(const std::string &key, T defaultvalue) const
Definition property.h:321
void LoadFromFile(std::string filename)
void WriteMPS(std::string filename, std::string header) const
Logger is used for thread-safe output of messages.
Definition logger.h:164
void setPreface(Log::Level level, const std::string &preface)
Definition logger.h:194
void setReportLevel(Log::Level ReportLevel)
Definition logger.h:185
void setMultithreading(bool maverick)
Definition logger.h:186
void setCommonPreface(const std::string &preface)
Definition logger.h:198
void push_back(const T &seg)
Definition mmregion.h:78
void Printpolarization(const Eigen::Matrix3d &result) const
Definition molpol.cc:143
std::string mps_output_
Definition molpol.h:55
tools::Property polar_options_
Definition molpol.h:61
void ParseOptions(const tools::Property &user_options)
Definition molpol.cc:31
PolarSegment input_
Definition molpol.h:56
Eigen::VectorXd weights_
Definition molpol.h:59
Eigen::Matrix3d CalcClassicalPol(const PolarSegment &input) const
Definition molpol.cc:121
double tolerance_pol_
Definition molpol.h:63
Eigen::Vector3d CalcInducedDipole(const PolarSegment &input, const Eigen::Vector3d &ext_field) const
Definition molpol.cc:93
Eigen::Matrix3d polarization_target_
Definition molpol.h:57
void Initialize(const tools::Property &prop) override
void Evaluate(std::vector< std::unique_ptr< Region > > &regions) override
Class to represent Atom/Site in electrostatic+polarization.
Definition polarsite.h:36
std::string job_name_
Definition qmtool.h:50
#define XTP_LOG(level, log)
Definition logger.h:40
const double ev2hrt
Definition constants.h:54
const double ang2bohr
Definition constants.h:48
const double bohr2ang
Definition constants.h:49
const double nm2bohr
Definition constants.h:47
base class for all analysis tools
Definition basebead.h:33
Eigen::Index Index
Definition types.h:26
static Level current_level
Definition globals.h:30