votca 2026-dev
Loading...
Searching...
No Matches
classicalsegment.cc
Go to the documentation of this file.
1/*
2 * Copyright 2009-2020 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// Standard includes
21#include <algorithm>
22#include <type_traits>
23
24// Third party includes
25#include <boost/format.hpp>
26
27// VOTCA includes
29#include <votca/tools/getline.h>
31
32// Local VOTCA includes
35
36namespace votca {
37namespace xtp {
38
39// MPS files have a weird format positions can be in bohr or angstroem,
40// multipoles are in q*bohr^k, with k rank of multipole and polarisabilities are
41// in angstroem^3
42template <class T>
43void ClassicalSegment<T>::LoadFromFile(std::string filename) {
44
45 std::string line;
46 std::ifstream intt;
47 intt.open(filename);
48 double unit_conversion = tools::conv::ang2bohr;
49
50 Index readinmultipoles = 0;
51 Index numberofmultipoles = 0;
52 Vector9d multipoles = Vector9d::Zero();
53 Index rank = 0;
54
55 if (!intt.is_open()) {
56 throw std::runtime_error("File:" + filename + " could not be opened");
57 }
58 while (intt.good()) {
59
60 tools::getline(intt, line);
61 tools::Tokenizer toker(line, " \t");
62 std::vector<std::string> split = toker.ToVector();
63
64 if (!split.size() || split[0] == "!" || split[0].substr(0, 1) == "!") {
65 continue;
66 }
67
68 // ! Interesting information here, e.g.
69 // ! DCV2T opt
70 // ! SP RB3LYP 6-311+G(d,p)
71 // Units bohr
72 //
73 // C -4.2414603400 -3.8124751600 0.0017575736 Rank 2
74 // -0.3853409355
75 // -0.0002321905 0.2401559510 0.6602334308
76 // -0.7220625314 0.0004894995 -0.0003833545 0.4526409813 -0.50937399
77 // P 1.75
78
79 // Units used
80 if (split[0] == "Units") {
81 std::string units = split[1];
82 if (units != "bohr" && units != "angstrom") {
83 throw std::runtime_error("Unit " + units + " in file " + filename +
84 " not supported.");
85 }
86 if (units == "bohr") {
87 unit_conversion = 1.0;
88 }
89 } else if (split.size() == 6) {
90 // element, position, rank limit convert to bohr
91 std::string name = split[0];
92 Eigen::Vector3d pos;
93 Index id = Index(this->atomlist_.size());
94 pos[0] = boost::lexical_cast<double>(split[1]);
95 pos[1] = boost::lexical_cast<double>(split[2]);
96 pos[2] = boost::lexical_cast<double>(split[3]);
97 rank = boost::lexical_cast<Index>(split[5]);
98 numberofmultipoles = (rank + 1) * (rank + 1);
99 multipoles = Vector9d::Zero();
100 pos *= unit_conversion;
101 this->atomlist_.push_back(T(id, name, pos));
102 }
103 // 'P', dipole polarizability
104 else if (split[0] == "P") {
105 Eigen::Matrix3d p1;
106 if (split.size() == 7) {
107 double pxx = boost::lexical_cast<double>(split[1]);
108 double pxy = boost::lexical_cast<double>(split[2]);
109 double pxz = boost::lexical_cast<double>(split[3]);
110 double pyy = boost::lexical_cast<double>(split[4]);
111 double pyz = boost::lexical_cast<double>(split[5]);
112 double pzz = boost::lexical_cast<double>(split[6]);
113 p1 << pxx, pxy, pxz, pxy, pyy, pyz, pxz, pyz, pzz;
114 } else if (split.size() == 2) {
115 double pxx = boost::lexical_cast<double>(split[1]);
116 p1 = pxx * Eigen::Matrix3d::Identity();
117 } else {
118 throw std::runtime_error("Invalid line in " + filename + ": " + line);
119 }
120 double unit_conversion_3 = std::pow(tools::conv::ang2bohr, 3);
121 p1 = p1 * unit_conversion_3;
122 this->atomlist_.back().setpolarization(p1);
123 }
124 // Multipole lines
125 else {
126 // stay in bohr
127 for (const std::string& entry : split) {
128 double qXYZ = boost::lexical_cast<double>(entry);
129 if (multipoles.size() < readinmultipoles) {
130 throw std::runtime_error("ReadMpsFile: File" + filename +
131 "is not properly formatted");
132 }
133 multipoles(readinmultipoles) = qXYZ;
134 readinmultipoles++;
135 }
136 if (readinmultipoles == numberofmultipoles) {
137 Eigen::Vector3d temp_dipoles = multipoles.segment<3>(1);
138 // mps format for dipoles is z x y
139 // we need x y z
140 multipoles(1) = temp_dipoles(1);
141 multipoles(2) = temp_dipoles(2);
142 multipoles(3) = temp_dipoles(0);
143 this->atomlist_.back().setMultipole(multipoles, rank);
144 readinmultipoles = 0;
145 }
146 }
147 }
148 this->calcPos();
149}
150
151template <class T>
153 double Q = 0;
154 for (const T& site : this->atomlist_) {
155 Q += site.getCharge();
156 }
157 return Q;
158}
159
160template <class T>
161Eigen::Vector3d ClassicalSegment<T>::CalcDipole() const {
162 Eigen::Vector3d dipole = Eigen::Vector3d::Zero();
163
164 Eigen::Vector3d CoM = this->getPos();
165 for (const T& site : this->atomlist_) {
166 dipole += (site.getPos() - CoM) * site.getCharge();
167 dipole += site.getDipole();
168 }
169 return dipole;
170}
171
172template <class T>
174 Eigen::Vector3d dipole = Eigen::Vector3d::Zero();
175
176 Eigen::Vector3d CoM = this->getPos();
177 for (const T& site : this->atomlist_) {
178 dipole += (site.getPos() - CoM) * site.getCharge();
179 dipole += site.getStaticDipole();
180 }
181 return dipole;
182}
183
184template <class T>
185void ClassicalSegment<T>::WriteMPS(std::string filename,
186 std::string header) const {
187
188 std::ofstream ofs;
189 ofs.open(filename, std::ofstream::out);
190 if (!ofs.is_open()) {
191 throw std::runtime_error("Bad file handle: " + filename);
192 }
193
194 ofs << (boost::format("! GENERATED BY VOTCA::XTP::%1$s\n") % header);
195 ofs << (boost::format("! N=%2$d Q[e]=%1$+1.7f\n") % CalcTotalQ() %
196 this->size());
197 ofs << boost::format("Units angstrom\n");
198
199 for (const T& site : this->atomlist_) {
200 ofs << site.WriteMpsLine("angstrom");
201 }
202 ofs.close();
203}
204
205template <class T>
207 if (cr.size() != this->size()) {
208 throw std::runtime_error(
209 "Segment " + this->getType() + " " + std::to_string(this->getId()) +
210 " has " + std::to_string(this->size()) +
211 " sites, its charge-response matrix " + std::to_string(cr.size()));
212 }
213 for (Index i = 0; i < this->size(); ++i) {
214 if (cr.Elements()[std::size_t(i)] != this->atomlist_[i].getElement()) {
215 throw std::runtime_error(
216 "Segment " + this->getType() + " " + std::to_string(this->getId()) +
217 ": site " + std::to_string(i) + " is " +
218 this->atomlist_[i].getElement() +
219 ", but the charge-response matrix has " +
220 cr.Elements()[std::size_t(i)] + " there (atom order must agree)");
221 }
222 }
223 chargeresponse_ = cr;
224}
225
226template <class T>
229 if (hasChargeResponse()) {
230 CheckpointWriter v = w.openChild("chargeresponse");
231 chargeresponse_.WriteToCpt(v);
232 if constexpr (std::is_same_v<T, PolarSite>) {
233 Eigen::VectorXd dq(this->size());
234 for (Index i = 0; i < this->size(); ++i) {
235 dq(i) = this->atomlist_[i].Induced_Charge();
236 }
237 v(dq, "induced_charges");
238 }
239 }
240}
241
242template <class T>
247
248template <class T>
251 // optional: checkpoints without it (and all older ones) are Thole segments
252 const std::vector<std::string> children = r.getChildGroupNames();
253 if (std::find(children.begin(), children.end(), "chargeresponse") !=
254 children.end()) {
255 CheckpointReader v = r.openChild("chargeresponse");
257 cr.ReadFromCpt(v);
259 if constexpr (std::is_same_v<T, PolarSite>) {
260 Eigen::VectorXd dq;
261 v(dq, "induced_charges");
262 if (dq.size() != this->size()) {
263 throw std::runtime_error("Segment " + this->getType() +
264 ": induced charges in the checkpoint do not "
265 "match its sites");
266 }
267 for (Index i = 0; i < this->size(); ++i) {
268 this->atomlist_[i].setInduced_Charge(dq(i));
269 }
270 }
271 }
272}
273
274template <class T>
275std::string ClassicalSegment<T>::identify() const {
276 return "";
277}
278
279template <>
281 return "PolarSegment";
282}
283template <>
285 return "StaticSegment";
286}
287
288// additional access functions and methods for Ewald
289template <class T>
291 for (const T& site : this->atomlist_) {
292 if (std::abs(site.getCharge()) > 1e-4) {
293 return true;
294 }
295 }
296 return false;
297}
298
299template <class T>
301 return false;
302}
303
304template <>
306 for (const PolarSite& site : this->atomlist_) {
307
308 (site.getpolarization().array().abs() > 1e-4).any();
309 if ((site.getpolarization().array().abs() > 1e-4).any()) {
310 return true;
311 }
312 }
313 return false;
314}
315
316template <>
318 return false;
319}
320
321template class ClassicalSegment<PolarSite>;
322template class ClassicalSegment<StaticSite>;
323
324} // namespace xtp
325} // namespace votca
break string into words
Definition tokenizer.h:72
std::vector< T > ToVector()
store all words in a vector of type T, does type conversion.
Definition tokenizer.h:109
const std::string & getType() const
virtual void WriteToCpt(CheckpointWriter &w) const
virtual void ReadFromCpt(CheckpointReader &r)
const Eigen::Vector3d & getPos() const
std::vector< T > atomlist_
Charge-response matrix Pi of one molecule type.
const std::vector< std::string > & Elements() const
void ReadFromCpt(CheckpointReader &r)
std::vector< std::string > getChildGroupNames() const
CheckpointReader openChild(const std::string &childName) const
CheckpointWriter openChild(const std::string &childName) const
Eigen::Vector3d CalcStaticDipole() const
void ReadFromCpt(CheckpointReader &r) override
void ReadChargeResponseFromCpt(CheckpointReader &r)
void WriteToCpt(CheckpointWriter &w) const override
void LoadFromFile(std::string filename)
Eigen::Vector3d CalcDipole() const
void WriteMPS(std::string filename, std::string header) const
void setChargeResponse(const ChargeResponse &cr)
Class to represent Atom/Site in electrostatic+polarization.
Definition polarsite.h:36
const double ang2bohr
Definition constants.h:48
std::istream & getline(std::istream &is, std::string &str)
Wrapper for a getline function.
Definition getline.h:35
Charge transport classes.
Definition ERIs.h:28
Provides a means for comparing floating point numbers.
Definition basebead.h:33
Eigen::Index Index
Definition types.h:26
Eigen::Matrix< double, 9, 1 > Vector9d
Definition eigen.h:37