votca 2024.2-dev
Loading...
Searching...
No Matches
qmregion.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
21#include "votca/xtp/qmregion.h"
22#include "votca/xtp/aomatrix.h"
26#include "votca/xtp/gwbse.h"
29#include "votca/xtp/qmstate.h"
31#include "votca/xtp/vxc_grid.h"
32
33namespace votca {
34namespace xtp {
35
37 if (this->id_ != 0) {
38 throw std::runtime_error(
39 this->identify() +
40 " must always be region 0. Currently only one qm region is possible.");
41 }
42
43 initstate_ = prop.get("state").as<QMState>();
44 /*if (initstate_.Type() == QMStateType::Hole ||
45 initstate_.Type() == QMStateType::Electron) {
46 throw std::runtime_error(
47 "Charged QM Regions are not implemented currently");
48 }*/
50
51 do_gwbse_ = true;
52 gwbseoptions_ = prop.get("gwbse");
53 if (prop.exists("statetracker")) {
54 tools::Property filter = prop.get("statetracker");
59 } else {
60 throw std::runtime_error(
61 "No statetracker options for excited states found");
62 }
63 }
64
65 if (initstate_.Type().isKSState()) {
66
67 if (prop.exists("statetracker")) {
68 tools::Property filter = prop.get("statetracker");
73 } else {
74 throw std::runtime_error("No statetracker options for KS states found");
75 }
76 }
77
79 prop.get("grid_for_potential").as<std::string>();
80 DeltaE_ = prop.get("tolerance_energy").as<double>();
81 DeltaD_ = prop.get("tolerance_density").as<double>();
82 DeltaDmax_ = prop.get("tolerance_density_max").as<double>();
83
84 dftoptions_ = prop.get("dftpackage");
85 localize_options_ = prop.get("localize");
86
87 if (prop.get("dftpackage.xtpdft.dft_in_dft.activeatoms")
88 .as<std::string>()
89 .size() != 0) {
90 do_localize_ = true;
91 do_dft_in_dft_ = true;
92 }
93}
94
95bool QMRegion::Converged() const {
96 if (!E_hist_.filled()) {
97 return false;
98 }
99
100 double Echange = E_hist_.getDiff();
101 double Dchange =
102 Dmat_hist_.getDiff().norm() / double(Dmat_hist_.back().cols());
103 double Dmax = Dmat_hist_.getDiff().cwiseAbs().maxCoeff();
104 std::string info = "not converged";
105 bool converged = false;
106 if (Dchange < DeltaD_ && Dmax < DeltaDmax_ && std::abs(Echange) < DeltaE_) {
107 info = "converged";
108 converged = true;
109 }
111 << " Region:" << this->identify() << " " << this->getId() << " is "
112 << info << " deltaE=" << Echange << " RMS Dmat=" << Dchange
113 << " MaxDmat=" << Dmax << std::flush;
114 return converged;
115}
116
117void QMRegion::Evaluate(std::vector<std::unique_ptr<Region> >& regions) {
118
119 std::vector<double> interact_energies = ApplyInfluenceOfOtherRegions(regions);
120 double e_ext =
121 std::accumulate(interact_energies.begin(), interact_energies.end(), 0.0);
123 << TimeStamp()
124 << " Calculated interaction potentials with other regions. E[hrt]= "
125 << e_ext << std::flush;
126 XTP_LOG(Log::info, log_) << "Writing inputs" << std::flush;
127 Index crg = 0;
129 crg = -1;
130 } else if (initstate_.Type() == QMStateType::Hole) {
131 crg = +1;
132 }
133 qmpackage_->setCharge(crg);
134 qmpackage_->setRunDir(workdir_);
135 qmpackage_->WriteInputFile(orb_);
136
137 XTP_LOG(Log::error, log_) << "Running DFT calculation" << std::flush;
138 bool run_success = qmpackage_->Run();
139 if (!run_success) {
140 info_ = false;
141 errormsg_ = "DFT-run failed";
142 return;
143 }
144
145 bool Logfile_parse = qmpackage_->ParseLogFile(orb_);
146 if (!Logfile_parse) {
147 info_ = false;
148 errormsg_ = "Parsing DFT logfile failed.";
149 return;
150 }
151 bool Orbfile_parse = qmpackage_->ParseMOsFile(orb_);
152 if (!Orbfile_parse) {
153 info_ = false;
154 errormsg_ = "Parsing DFT orbfile failed.";
155 return;
156 }
157 if (do_localize_) {
158 if (orb_.isOpenShell()) {
159 throw std::runtime_error(
160 "MO localization not implemented for open-shell systems");
161 }
163 pml.computePML(orb_);
164 }
165 QMMolecule originalmol = orb_.QMAtoms();
166 if (do_dft_in_dft_) {
167 if (orb_.isOpenShell()) {
168 throw std::runtime_error(
169 "DFT-in-DFT not implemented for open-shell systems");
170 }
171 // this only works with XTPDFT, so locally override global qmpackage_
172 std::unique_ptr<QMPackage> xtpdft =
173 std::unique_ptr<QMPackage>(QMPackageFactory().Create("xtp"));
174 xtpdft->setLog(&log_);
175 xtpdft->Initialize(dftoptions_);
176 xtpdft->setRunDir(workdir_);
177 Index charge = 0;
179 charge = -1;
180 } else if (initstate_.Type() == QMStateType::Hole) {
181 charge = +1;
182 }
183 xtpdft->setCharge(charge);
184
185 std::vector<double> energies = std::vector<double>(regions.size(), 0.0);
186 for (std::unique_ptr<Region>& reg : regions) {
187 Index id = reg->getId();
188 if (id == this->getId()) {
189 continue;
190 }
191
192 StaticRegion Staticdummy(0, log_);
193 PolarRegion Polardummy(0, log_);
195 << TimeStamp() << " Evaluating interaction between "
196 << this->identify() << " " << this->getId() << " and "
197 << reg->identify() << " " << reg->getId() << std::flush;
198 if (reg->identify() == Staticdummy.identify()) {
199 StaticRegion* staticregion = dynamic_cast<StaticRegion*>(reg.get());
200 xtpdft->AddRegion(*staticregion);
201 } else if (reg->identify() == Polardummy.identify()) {
202 PolarRegion* polarregion = dynamic_cast<PolarRegion*>(reg.get());
203 xtpdft->AddRegion(*polarregion);
204 } else {
205 throw std::runtime_error(
206 "Interaction of regions with types:" + this->identify() + " and " +
207 reg->identify() + " not implemented");
208 }
209 }
210
211 e_ext = std::accumulate(interact_energies.begin(), interact_energies.end(),
212 0.0);
214 << TimeStamp()
215 << " Calculated interaction potentials with other regions. E[hrt]= "
216 << e_ext << std::flush;
217 XTP_LOG(Log::info, log_) << "Writing inputs" << std::flush;
218 xtpdft->WriteInputFile(orb_);
219 bool active_run = xtpdft->RunActiveRegion();
220 if (!active_run) {
221 throw std::runtime_error("\n DFT in DFT embedding failed. Stopping!");
222 }
223 Logfile_parse = xtpdft->ParseLogFile(orb_);
224 if (!Logfile_parse) {
225 throw std::runtime_error("\n Parsing DFT logfile failed. Stopping!");
226 }
227 }
228
229 QMState state = QMState("groundstate");
230 double energy = orb_.getDFTTotalEnergy();
231
232 if (initstate_.Type().isKSState()) {
234 // if unoccupied, add QP level energy
235 if (state.StateIdx() > orb_.getHomo()) {
236 energy += orb_.getExcitedStateEnergy(state);
237 } else {
238 // if unoccupied, subtract QP level energy
239 energy -= orb_.getExcitedStateEnergy(state);
240 }
241 }
242
243 if (do_gwbse_) {
244 if (orb_.isOpenShell()) {
245 throw std::runtime_error("GWBSE not implemented for open-shell systems");
246 }
247 if (do_dft_in_dft_) {
248 Index active_electrons = orb_.getNumOfActiveElectrons();
250 orb_.setNumberOfAlphaElectrons(active_electrons);
251 orb_.setNumberOfOccupiedLevels(active_electrons / 2);
252 }
253 GWBSE gwbse(orb_);
254 gwbse.setLogger(&log_);
256 gwbse.Evaluate();
258 if (state.Type().isExciton()) {
259 energy += orb_.getExcitedStateEnergy(state);
260 } else {
261 // if unoccupied, add QP level energy
262 if (state.StateIdx() > orb_.getHomo()) {
263 energy += orb_.getExcitedStateEnergy(state);
264 } else {
265 // if unoccupied, subtract QP level energy
266 energy -= orb_.getExcitedStateEnergy(state);
267 }
268 }
269 }
270 // If truncation was enabled then rewrite full basis/aux-basis, MOs in full
271 // basis and full QMAtoms
272 if (orb_.getCalculationType() == "Truncated") {
275 orb_.QMAtoms() = originalmol;
278 }
279 E_hist_.push_back(energy);
280
282 return;
283}
284
286 if (orb_.QMAtoms().size() == 0) {
287 orb_.QMAtoms() = mol;
288 } else {
290 }
291 size_++;
292}
293
294double QMRegion::charge() const {
295 double charge = 0.0;
296 if (!do_gwbse_) {
297 Index nuccharge = 0;
298 for (const QMAtom& a : orb_.QMAtoms()) {
299 nuccharge += a.getNuccharge();
300 }
301
303 if (orb_.isOpenShell()) {
304 electrons += orb_.getNumberOfBetaElectrons();
305 } else {
306 electrons *= 2;
307 }
308
309 charge = double(nuccharge - electrons);
310 } else {
312 if (state.Type().isExciton()) {
313 charge = 0.0;
314 } else if (state.Type().isSingleParticleState() ||
315 state.Type().isKSState()) {
316 if (state.StateIdx() <= orb_.getHomo()) {
317 charge = +1.0;
318 } else {
319 charge = -1.0;
320 }
321 }
322 }
323 return charge;
324}
325
327 prop.add("E_total", std::to_string(E_hist_.back() * tools::conv::hrt2ev));
328 if (do_gwbse_) {
329 prop.add("Initial_State", statetracker_.InitialState().ToString());
330 prop.add("Final_State", statetracker_.CalcState(orb_).ToString());
331 }
332}
333
335
336 std::string dft_package_name = dftoptions_.get("name").as<std::string>();
337 qmpackage_ =
338 std::unique_ptr<QMPackage>(QMPackageFactory().Create(dft_package_name));
339 qmpackage_->setLog(&log_);
340 qmpackage_->Initialize(dftoptions_);
341 Index charge = 0;
343 charge = -1;
344 } else if (initstate_.Type() == QMStateType::Hole) {
345 charge = +1;
346 }
347 qmpackage_->setCharge(charge);
348 return;
349}
351 throw std::runtime_error(
352 "QMRegion-QMRegion interaction is not implemented yet.");
353 return 0.0;
354}
356 qmpackage_->AddRegion(region);
357 return 0.0;
358}
360 qmpackage_->AddRegion(region);
361 return 0.0;
362}
363
365 writer.WriteContainer(orb_.QMAtoms());
366}
367
368void QMRegion::AddNucleiFields(std::vector<PolarSegment>& segments,
369 const StaticSegment& seg) const {
371#pragma omp parallel for
372 for (Index i = 0; i < Index(segments.size()); ++i) {
373 e.ApplyStaticField<StaticSegment, Estatic::noE_V>(seg, segments[i]);
374 }
375}
376
378 std::vector<PolarSegment>& segments) const {
379
380 Vxc_Grid grid;
381 AOBasis basis =
382 orb_.getDftBasis(); // grid needs a basis in scope all the time
384 DensityIntegration<Vxc_Grid> numint(grid);
385
386 QMState state = QMState("groundstate");
387 if (do_gwbse_ || initstate_.Type().isKSState()) {
389 }
390 Eigen::MatrixXd dmat = orb_.DensityMatrixFull(state);
391 double Ngrid = numint.IntegrateDensity(dmat);
392 AOOverlap overlap;
393 overlap.Fill(basis);
394 double N_comp = dmat.cwiseProduct(overlap.Matrix()).sum();
395 if (std::abs(Ngrid - N_comp) > 0.001) {
396 XTP_LOG(Log::error, log_) << "=======================" << std::flush;
398 << "WARNING: Calculated Densities at Numerical Grid, Number of "
399 "electrons "
400 << Ngrid << " is far away from the the real value " << N_comp
401 << ", you should increase the accuracy of the integration grid."
402 << std::flush;
403 }
404#pragma omp parallel for
405 for (Index i = 0; i < Index(segments.size()); ++i) {
406 PolarSegment& seg = segments[i];
407 for (PolarSite& site : seg) {
408 site.V_noE() += numint.IntegrateField(site.getPos());
409 }
410 }
411
413 for (const QMAtom& atom : orb_.QMAtoms()) {
414 seg.push_back(StaticSite(atom, double(atom.getNuccharge())));
415 }
416 AddNucleiFields(segments, seg);
417}
418
420 w(id_, "id");
421 w(identify(), "type");
422 w(size_, "size");
423 w(do_gwbse_, "GWBSE");
424 w(initstate_.ToString(), "initial_state");
426 CheckpointWriter v = w.openChild("QMdata");
427 orb_.WriteToCpt(v);
429
430 CheckpointWriter v2 = w.openChild("E-hist");
432
433 CheckpointWriter v3 = w.openChild("D-hist");
435 if (do_gwbse_) {
436 CheckpointWriter v4 = w.openChild("statefilter");
438 }
439}
440
442 r(id_, "id");
443 r(size_, "size");
444 r(do_gwbse_, "GWBSE");
445 std::string state;
446 r(state, "initial_state");
447 initstate_.FromString(state);
449 CheckpointReader rr = r.openChild("QMdata");
450 orb_.ReadFromCpt(rr);
452
453 CheckpointReader rr2 = r.openChild("E-hist");
454 E_hist_.ReadFromCpt(rr2);
455
456 CheckpointReader rr3 = r.openChild("D-hist");
458 if (do_gwbse_) {
459 CheckpointReader rr4 = r.openChild("statefilter");
461 }
462}
463
464} // namespace xtp
465} // namespace votca
void WriteContainer(T &container)
Definition pdbwriter.h:102
const Eigen::MatrixXd & eigenvectors() const
Definition eigensystem.h:33
class to manage program options with xml serialization functionality
Definition property.h:55
Property & add(const std::string &key, const std::string &value)
add a new property to structure
Definition property.cc:108
Property & get(const std::string &key)
get existing property
Definition property.cc:79
bool exists(const std::string &key) const
check whether property exists
Definition property.cc:122
T as() const
return value as type
Definition property.h:283
Container to hold Basisfunctions for all atoms.
Definition aobasis.h:42
const std::string & Name() const
Definition aobasis.h:81
void Fill(const AOBasis &aobasis) final
const Eigen::MatrixXd & Matrix() const
Definition aomatrix.h:52
const std::string & getType() const
void push_back(const T &atom)
CheckpointReader openChild(const std::string &childName) const
CheckpointWriter openChild(const std::string &childName) const
Eigen::Vector3d IntegrateField(const Eigen::Vector3d &rvector) const
double IntegrateDensity(const Eigen::MatrixXd &density_matrix)
Electronic excitations from GW-BSE.
Definition gwbse.h:56
bool Evaluate()
Definition gwbse.cc:544
void Initialize(tools::Property &options)
Definition gwbse.cc:60
void setLogger(Logger *pLog)
Definition gwbse.h:63
const Eigen::MatrixXd getTruncMOsFullBasis() const
Definition orbitals.h:62
Index getNumOfActiveElectrons()
Definition orbitals.h:419
Index getHomo() const
Definition orbitals.h:68
void ReadBasisSetsFromCpt(CheckpointReader r)
Definition orbitals.cc:703
double getDFTTotalEnergy() const
Definition orbitals.h:193
const AOBasis & getAuxBasis() const
Definition orbitals.h:218
Index getNumberOfAlphaElectrons() const
Definition orbitals.h:93
std::string getCalculationType() const
Definition orbitals.h:159
void setNumberOfAlphaElectrons(Index electrons)
Definition orbitals.h:96
void WriteBasisSetsToCpt(CheckpointWriter w) const
Definition orbitals.cc:626
Eigen::MatrixXd DensityMatrixFull(const QMState &state) const
Definition orbitals.cc:140
void SetupAuxBasis(std::string aux_basis_name)
Definition orbitals.cc:99
double getExcitedStateEnergy(const QMState &state) const
Definition orbitals.cc:451
void setNumberOfOccupiedLevels(Index occupied_levels)
Definition orbitals.h:78
const tools::EigenSystem & MOs() const
Definition orbitals.h:122
const QMMolecule & QMAtoms() const
Definition orbitals.h:172
void ReadFromCpt(const std::string &filename)
Definition orbitals.cc:692
void WriteToCpt(const std::string &filename) const
Definition orbitals.cc:615
void SetupDftBasis(std::string basis_name)
Definition orbitals.cc:90
bool isOpenShell() const
Definition orbitals.h:168
const tools::EigenSystem & getEmbeddedMOs() const
Definition orbitals.h:56
Index getNumberOfBetaElectrons() const
Definition orbitals.h:94
const AOBasis & getDftBasis() const
Definition orbitals.h:208
void computePML(Orbitals &orbitals)
std::string identify() const override
Definition polarregion.h:48
Class to represent Atom/Site in electrostatic+polarization.
Definition polarsite.h:36
container for QM atoms
Definition qmatom.h:37
void AddContainer(const AtomContainer< QMAtom > &container)
Definition qmmolecule.h:40
void AppendResult(tools::Property &prop) const override
Definition qmregion.cc:326
StateTracker statetracker_
Definition qmregion.h:110
hist< Eigen::MatrixXd > Dmat_hist_
Definition qmregion.h:95
std::string grid_accuracy_for_ext_interaction_
Definition qmregion.h:92
std::string identify() const override
Definition qmregion.h:66
hist< double > E_hist_
Definition qmregion.h:94
void AddNucleiFields(std::vector< PolarSegment > &segments, const StaticSegment &seg) const
Definition qmregion.cc:368
std::unique_ptr< QMPackage > qmpackage_
Definition qmregion.h:90
void push_back(const QMMolecule &mol)
Definition qmregion.cc:285
void WriteToCpt(CheckpointWriter &w) const override
Definition qmregion.cc:419
double InteractwithStaticRegion(const StaticRegion &region) override
Definition qmregion.cc:359
double InteractwithPolarRegion(const PolarRegion &region) override
Definition qmregion.cc:355
std::string workdir_
Definition qmregion.h:89
void Reset() override
Definition qmregion.cc:334
void WritePDB(csg::PDBWriter &writer) const override
Definition qmregion.cc:364
void ReadFromCpt(CheckpointReader &r) override
Definition qmregion.cc:441
bool Converged() const override
Definition qmregion.cc:95
void Evaluate(std::vector< std::unique_ptr< Region > > &regions) override
Definition qmregion.cc:117
tools::Property localize_options_
Definition qmregion.h:108
double InteractwithQMRegion(const QMRegion &region) override
Definition qmregion.cc:350
void ApplyQMFieldToPolarSegments(std::vector< PolarSegment > &segments) const
Definition qmregion.cc:377
void Initialize(const tools::Property &prop) override
Definition qmregion.cc:36
double charge() const override
Definition qmregion.cc:294
tools::Property dftoptions_
Definition qmregion.h:106
tools::Property gwbseoptions_
Definition qmregion.h:107
bool isKSState() const
Definition qmstate.h:89
bool isGWState() const
Definition qmstate.h:85
bool isSingleParticleState() const
Definition qmstate.h:80
bool isExciton() const
Definition qmstate.h:71
Identifier for QMstates. Strings like S1 are converted into enum +zero indexed int.
Definition qmstate.h:132
void FromString(const std::string &statestring)
Definition qmstate.cc:203
std::string ToString() const
Definition qmstate.cc:146
Index StateIdx() const
Definition qmstate.h:154
const QMStateType & Type() const
Definition qmstate.h:151
std::vector< double > ApplyInfluenceOfOtherRegions(std::vector< std::unique_ptr< Region > > &regions)
Definition region.cc:32
Index getId() const
Definition region.h:79
std::string errormsg_
Definition region.h:91
Logger & log_
Definition region.h:100
void Initialize(const tools::Property &options)
void setLogger(Logger *log)
QMState CalcStateAndUpdate(const Orbitals &orbitals)
void setInitialState(const QMState &state)
void ReadFromCpt(CheckpointReader &r)
void WriteToCpt(CheckpointWriter &w) const
QMState CalcState(const Orbitals &orbitals) const
QMState InitialState() const
std::string identify() const override
Class to represent Atom/Site in electrostatic.
Definition staticsite.h:37
Timestamp returns the current time as a string Example: cout << TimeStamp()
Definition logger.h:224
void GridSetup(const std::string &type, const QMMolecule &atoms, const AOBasis &basis)
Definition vxc_grid.cc:229
Mediates interaction between polar and static sites.
void WriteToCpt(CheckpointWriter &w) const
Definition hist.h:65
const T & back() const
Definition hist.h:51
T getDiff() const
Definition hist.h:41
bool filled() const
Definition hist.h:63
void ReadFromCpt(CheckpointReader &r)
Definition hist.h:75
void push_back(const T &metric)
Definition hist.h:52
#define XTP_LOG(level, log)
Definition logger.h:40
const double hrt2ev
Definition constants.h:53
ClassicalSegment< StaticSite > StaticSegment
base class for all analysis tools
Definition basebead.h:33
Eigen::Index Index
Definition types.h:26