votca 2026-dev
Loading...
Searching...
No Matches
iqm.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#include <filesystem>
21
22// Third party includes
23#include <boost/algorithm/string/split.hpp>
24#include <boost/format.hpp>
25
26// VOTCA includes
28
29// Local VOTCA includes
31#include "votca/xtp/atom.h"
32#include "votca/xtp/logger.h"
35
36// Local private VOTCA includes
37#include "iqm.h"
38
39namespace votca {
40namespace xtp {
41
43
45
46 // job tasks
47 std::string tasks_string = options.get(".tasks").as<std::string>();
48
49 // We split either on a space or a comma
50 tools::Tokenizer tokenizedTasks(tasks_string, " ,");
51 std::vector<std::string> tasks = tokenizedTasks.ToVector();
52
53 // Check which tasks exist and set them to true
54 do_dft_input_ = std::find(tasks.begin(), tasks.end(), "input") != tasks.end();
55 do_dft_run_ = std::find(tasks.begin(), tasks.end(), "dft") != tasks.end();
56 do_dft_parse_ = std::find(tasks.begin(), tasks.end(), "parse") != tasks.end();
58 std::find(tasks.begin(), tasks.end(), "dftcoupling") != tasks.end();
59 do_gwbse_ = std::find(tasks.begin(), tasks.end(), "gwbse") != tasks.end();
61 std::find(tasks.begin(), tasks.end(), "bsecoupling") != tasks.end();
62
63 // storage options
64 std::string store_string = options.get(".store").as<std::string>();
65 if (store_string.find("dft") != std::string::npos) {
66 store_dft_ = true;
67 }
68 if (store_string.find("gw") != std::string::npos) {
69 store_gw_ = true;
70 }
71
72 dftpackage_options_ = options.get(".dftpackage");
73 gwbse_options_ = options.get("gwbse");
74 dftcoupling_options_ = options.get(".dftcoupling");
75 bsecoupling_options_ = options.get("bsecoupling");
76
77 // read linker groups
78 std::string linker =
79 options.ifExistsReturnElseReturnDefault<std::string>(".linker_names", "");
80
81 for (const std::string& link :
82 tools::Tokenizer(linker, ", \t\n").ToVector()) {
83 tools::Tokenizer toker2(link, ":");
84 std::vector<std::string> link_split = toker2.ToVector();
85 if (link_split.size() != 2) {
86 throw std::runtime_error(
87 "Linker molecule has to be defined NAME:STATEGEO .e.g. DCV5T:n");
88 }
89 linkers_[link_split[0]] = QMState(link_split[1]);
90 }
91
92 // options for parsing data into state file
93 std::string key_read = ".readjobfile";
94 if (options.exists(key_read + ".singlet")) {
95 std::string parse_string_s =
96 options.get(key_read + ".singlet").as<std::string>();
97 singlet_levels_ = FillParseMaps(parse_string_s);
98 }
99 if (options.exists(key_read + ".triplet")) {
100 std::string parse_string_t =
101 options.get(key_read + ".triplet").as<std::string>();
102 triplet_levels_ = FillParseMaps(parse_string_t);
103 }
104
105 if (options.exists(key_read + ".hole")) {
106 std::string parse_string_h =
107 options.get(key_read + ".hole").as<std::string>();
108 hole_levels_ = FillParseMaps(parse_string_h);
109 }
110 if (options.exists(key_read + ".electron")) {
111 std::string parse_string_e =
112 options.get(key_read + ".electron").as<std::string>();
113 electron_levels_ = FillParseMaps(parse_string_e);
114 }
115}
116
117std::map<std::string, QMState> IQM::FillParseMaps(
118 const std::string& Mapstring) {
119 std::map<std::string, QMState> type2level;
120 for (const std::string& substring : tools::Tokenizer(Mapstring, ", \t\n")) {
121 std::vector<std::string> segmentpnumber =
122 tools::Tokenizer(substring, ":").ToVector();
123 if (segmentpnumber.size() != 2) {
124 throw std::runtime_error("Parser iqm: Segment and exciton labels:" +
125 substring + "are not separated properly");
126 }
127 QMState state = QMState(segmentpnumber[1]);
128 std::string segmentname = segmentpnumber[0];
129 type2level[segmentname] = state;
130 }
131 return type2level;
132}
133
134void IQM::addLinkers(std::vector<const Segment*>& segments,
135 const Topology& top) {
136 const Segment* seg1 = segments[0];
137 const Segment* seg2 = segments[1];
138 std::vector<const Segment*> segmentsInMolecule =
139 top.FindAllSegmentsOnMolecule(*seg1, *seg2);
140
141 for (const Segment* segment : segmentsInMolecule) {
142 Index idIterator = segment->getId();
143 if (idIterator != seg1->getId() && idIterator != seg2->getId() &&
144 isLinker(segment->getType())) {
145 segments.push_back(segment);
146 }
147 }
148}
149
150bool IQM::isLinker(const std::string& name) {
151 return linkers_.count(name) == 1;
152}
153
155 const std::string& errormessage) {
156 XTP_LOG(Log::error, pLog) << errormessage << std::flush;
157 std::cout << pLog;
158 jres.setError(errormessage);
160}
161
162void IQM::WriteLoggerToFile(const std::string& logfile, Logger& logger) {
163 std::ofstream ofs;
164 ofs.open(logfile, std::ofstream::out);
165 if (!ofs.is_open()) {
166 throw std::runtime_error("Bad file handle: " + logfile);
167 }
168 ofs << logger << std::endl;
169 ofs.close();
170}
171
172Job::JobResult IQM::EvalJob(const Topology& top, Job& job, QMThread& opThread) {
173
174 // report back to the progress observer
176
177 std::string iqm_work_dir = "OR_FILES";
178 std::string eqm_work_dir = "OR_FILES";
179 std::string frame_dir =
180 "frame_" + boost::lexical_cast<std::string>(top.getStep());
181
182 Logger& pLog = opThread.getLogger();
183
184 QMMapper mapper(pLog);
186
187 // get the information about the job executed by the thread
188 Index job_ID = job.getId();
189 tools::Property job_input = job.getInput();
190 std::vector<tools::Property*> segment_list = job_input.Select("segment");
191 Index ID_A = segment_list.front()->getAttribute<Index>("id");
192 std::string type_A = segment_list.front()->getAttribute<std::string>("type");
193 Index ID_B = segment_list.back()->getAttribute<Index>("id");
194 std::string type_B = segment_list.back()->getAttribute<std::string>("type");
195
196 std::string qmgeo_state_A = "n";
197 if (segment_list.front()->exists("qm_geometry")) {
198 qmgeo_state_A =
199 segment_list.front()->getAttribute<std::string>("qm_geometry");
200 }
201
202 std::string qmgeo_state_B = "n";
203 if (segment_list.back()->exists("qm_geometry")) {
204 qmgeo_state_B =
205 segment_list.back()->getAttribute<std::string>("qm_geometry");
206 }
207 QMState stateA(qmgeo_state_A);
208 QMState stateB(qmgeo_state_B);
209
210 // set the folders
211 std::string pair_dir =
212 (boost::format("%1%%2%%3%%4%%5%") % "pair" % "_" % ID_A % "_" % ID_B)
213 .str();
214
215 std::filesystem::path arg_path, arg_pathA, arg_pathB, arg_pathAB;
216
217 std::string orbFileA =
218 (arg_pathA / eqm_work_dir / "molecules" / frame_dir /
219 (boost::format("%1%_%2%%3%") % "molecule" % ID_A % ".orb").str())
220 .generic_string();
221 ;
222 std::string orbFileB =
223 (arg_pathB / eqm_work_dir / "molecules" / frame_dir /
224 (boost::format("%1%_%2%%3%") % "molecule" % ID_B % ".orb").str())
225 .generic_string();
226 ;
227 std::string orbFileAB =
228 (arg_pathAB / iqm_work_dir / "pairs_iqm" / frame_dir /
229 (boost::format("%1%%2%%3%%4%%5%") % "pair_" % ID_A % "_" % ID_B % ".orb")
230 .str())
231 .generic_string();
232 ;
233 std::string orb_dir =
234 (arg_path / iqm_work_dir / "pairs_iqm" / frame_dir).generic_string();
235 ;
236
237 const Segment& seg_A = top.getSegment(ID_A);
238 const Segment& seg_B = top.getSegment(ID_B);
239 const QMNBList& nblist = top.NBList();
240 const QMPair* pair = nblist.FindPair(&seg_A, &seg_B);
241
242 XTP_LOG(Log::error, pLog)
243 << TimeStamp() << " Evaluating pair " << job_ID << " [" << ID_A << ":"
244 << ID_B << "] out of " << (top.NBList()).size() << std::flush;
245
246 std::string package_append = "workdir_" + Identify();
247 std::vector<const Segment*> segments;
248 segments.push_back(&seg_A);
249 segments.push_back(&seg_B);
250 std::string work_dir =
251 (arg_path / iqm_work_dir / package_append / frame_dir / pair_dir)
252 .generic_string();
253
254 if (linkers_.size() > 0) {
255 addLinkers(segments, top);
256 }
257 Orbitals orbitalsAB;
258 // if a pair object is available and is not linked take into account PBC,
259 // otherwise write as is
260 if (pair == nullptr || segments.size() > 2) {
261 if (pair == nullptr) {
262 XTP_LOG(Log::warning, pLog)
263 << "PBCs are not taken into account when writing the coordinate file!"
264 << std::flush;
265 }
266
267 orbitalsAB.QMAtoms() = mapper.map(*(segments[0]), stateA);
268 orbitalsAB.QMAtoms().AddContainer(mapper.map(*(segments[1]), stateB));
269
270 for (Index i = 2; i < Index(segments.size()); i++) {
271 QMState linker_state = linkers_.at(segments[i]->getType());
272 orbitalsAB.QMAtoms().AddContainer(
273 mapper.map(*(segments[i]), linker_state));
274 }
275
276 } else {
277 const Segment* seg1 = pair->Seg1();
278 orbitalsAB.QMAtoms() = mapper.map(*seg1, stateA);
279 Segment seg2 = pair->Seg2PbCopy();
280 orbitalsAB.QMAtoms().AddContainer(mapper.map(seg2, stateB));
281 }
282
284 std::string qmpackage_work_dir =
285 (arg_path / iqm_work_dir / package_append / frame_dir / pair_dir)
286 .generic_string();
287
288 Logger dft_logger(Log::current_level);
289 dft_logger.setMultithreading(false);
290 dft_logger.setPreface(Log::info, (boost::format("\nDFT INF ...")).str());
291 dft_logger.setPreface(Log::error, (boost::format("\nDFT ERR ...")).str());
292 dft_logger.setPreface(Log::warning, (boost::format("\nDFT WAR ...")).str());
293 dft_logger.setPreface(Log::debug, (boost::format("\nDFT DBG ...")).str());
294 std::string package = dftpackage_options_.get("name").as<std::string>();
295 std::unique_ptr<QMPackage> qmpackage = QMPackageFactory().Create(package);
296 qmpackage->setLog(&dft_logger);
297 qmpackage->setRunDir(qmpackage_work_dir);
298 qmpackage->Initialize(dftpackage_options_);
299
300 // if asked, prepare the input files
301 if (do_dft_input_) {
302 std::filesystem::create_directories(qmpackage_work_dir);
303 if (qmpackage->GuessRequested()) {
304 if (linkers_.size() > 0) {
305 throw std::runtime_error(
306 "Error: You are using a linker and want "
307 "to use a monomer guess for the dimer. These are mutually "
308 "exclusive.");
309 }
310
311 XTP_LOG(Log::error, pLog)
312 << "Guess requested, reading molecular orbitals" << std::flush;
313
314 if (qmpackage->getPackageName() == "orca") {
315 XTP_LOG(Log::info, pLog)
316 << "Copying monomer .gbw files to pair folder" << std::flush;
317 std::string gbwFileA =
318 (arg_pathA / eqm_work_dir / "molecules" / frame_dir /
319 (boost::format("%1%_%2%%3%") % "molecule" % ID_A % ".gbw").str())
320 .generic_string();
321 ;
322 std::string gbwFileB =
323 (arg_pathB / eqm_work_dir / "molecules" / frame_dir /
324 (boost::format("%1%_%2%%3%") % "molecule" % ID_B % ".gbw").str())
325 .generic_string();
326 ;
327 std::string gbwFileA_workdir =
328 (std::filesystem::path(qmpackage_work_dir) / "molA.gbw")
329 .generic_string();
330 ;
331 std::string gbwFileB_workdir =
332 (std::filesystem::path(qmpackage_work_dir) / "molB.gbw")
333 .generic_string();
334 ;
335 std::filesystem::copy_file(
336 gbwFileA, gbwFileA_workdir,
337 std::filesystem::copy_options::overwrite_existing);
338 std::filesystem::copy_file(
339 gbwFileB, gbwFileB_workdir,
340 std::filesystem::copy_options::overwrite_existing);
341 } else {
342 Orbitals orbitalsB;
343 Orbitals orbitalsA;
344
345 try {
346 XTP_LOG(Log::error, pLog)
347 << "Reading MoleculeA from " << orbFileA << std::flush;
348 orbitalsA.ReadFromCpt(orbFileA);
349 } catch (std::runtime_error&) {
351 jres, pLog,
352 "Do input: failed loading orbitals from " + orbFileA);
353 return jres;
354 }
355
356 try {
357 XTP_LOG(Log::error, pLog)
358 << "Reading MoleculeB from " << orbFileB << std::flush;
359 orbitalsB.ReadFromCpt(orbFileB);
360 } catch (std::runtime_error&) {
362 jres, pLog,
363 "Do input: failed loading orbitals from " + orbFileB);
364 return jres;
365 }
366 XTP_LOG(Log::info, pLog)
367 << "Constructing the guess for dimer orbitals" << std::flush;
368 orbitalsAB.PrepareDimerGuess(orbitalsA, orbitalsB);
369 }
370 } else {
371 XTP_LOG(Log::info, pLog)
372 << "No Guess requested, starting from DFT starting Guess"
373 << std::flush;
374 }
375 qmpackage->WriteInputFile(orbitalsAB);
376 }
377
378 if (do_dft_run_) {
379 XTP_LOG(Log::error, pLog) << "Running DFT" << std::flush;
380 bool run_dft_status_ = qmpackage->Run();
381 if (!run_dft_status_) {
382 SetJobToFailed(jres, pLog, qmpackage->getPackageName() + " run failed");
383 WriteLoggerToFile(work_dir + "/dft.log", dft_logger);
384 return jres;
385 }
386 }
387
388 if (do_dft_parse_) {
389 bool parse_log_status = qmpackage->ParseLogFile(orbitalsAB);
390 if (!parse_log_status) {
391 SetJobToFailed(jres, pLog, "LOG parsing failed");
392 return jres;
393 }
394
395 bool parse_orbitals_status = qmpackage->ParseMOsFile(orbitalsAB);
396
397 if (!parse_orbitals_status) {
398 SetJobToFailed(jres, pLog, "Orbitals parsing failed");
399 return jres;
400 }
401
402 } // end of the parse orbitals/log
403 qmpackage->CleanUp();
404 WriteLoggerToFile(work_dir + "/dft.log", dft_logger);
405 } else {
406 try {
407 orbitalsAB.ReadFromCpt(orbFileAB);
408 } catch (std::runtime_error&) {
409 SetJobToFailed(jres, pLog,
410 "Do input: failed loading orbitals from " + orbFileAB);
411 return jres;
412 }
413 }
414 tools::Property job_summary;
415 tools::Property& job_output = job_summary.add("output", "");
416 if (do_dftcoupling_) {
417 DFTcoupling dftcoupling;
418 dftcoupling.setLogger(&pLog);
419 dftcoupling.Initialize(dftcoupling_options_);
420 Orbitals orbitalsB;
421 Orbitals orbitalsA;
422
423 try {
424 orbitalsA.ReadFromCpt(orbFileA);
425 } catch (std::runtime_error&) {
426 SetJobToFailed(jres, pLog,
427 "Do input: failed loading orbitals from " + orbFileA);
428 return jres;
429 }
430
431 try {
432 orbitalsB.ReadFromCpt(orbFileB);
433 } catch (std::runtime_error&) {
434 SetJobToFailed(jres, pLog,
435 "Do input: failed loading orbitals from " + orbFileB);
436 return jres;
437 }
438 try {
439 dftcoupling.CalculateCouplings(orbitalsA, orbitalsB, orbitalsAB);
440 dftcoupling.Addoutput(job_output, orbitalsA, orbitalsB);
441 } catch (std::runtime_error& error) {
442 std::string errormessage(error.what());
443 SetJobToFailed(jres, pLog, errormessage);
444 return jres;
445 }
446 }
447
448 // do excited states calculation
449 if (do_gwbse_) {
450 try {
451 XTP_LOG(Log::error, pLog) << "Running GWBSE" << std::flush;
452 Logger gwbse_logger(Log::current_level);
453 gwbse_logger.setMultithreading(false);
454 gwbse_logger.setPreface(Log::info,
455 (boost::format("\nGWBSE INF ...")).str());
456 gwbse_logger.setPreface(Log::error,
457 (boost::format("\nGWBSE ERR ...")).str());
458 gwbse_logger.setPreface(Log::warning,
459 (boost::format("\nGWBSE WAR ...")).str());
460 gwbse_logger.setPreface(Log::debug,
461 (boost::format("\nGWBSE DBG ...")).str());
462 GWBSE gwbse = GWBSE(orbitalsAB);
463 gwbse.setLogger(&gwbse_logger);
465 gwbse.Evaluate();
466 WriteLoggerToFile(work_dir + "/gwbse.log", gwbse_logger);
467 } catch (std::runtime_error& error) {
468 std::string errormessage(error.what());
469 SetJobToFailed(jres, pLog, errormessage);
470 return jres;
471 }
472
473 } // end of excited state calculation, exciton data is in orbitalsAB_
474
475 // calculate the coupling
476
477 if (do_bsecoupling_) {
478 XTP_LOG(Log::error, pLog) << "Running BSECoupling" << std::flush;
479 BSECoupling bsecoupling;
480 // orbitals must be loaded from a file
481 if (!do_gwbse_) {
482 try {
483 orbitalsAB.ReadFromCpt(orbFileAB);
484 } catch (std::runtime_error&) {
485 SetJobToFailed(jres, pLog,
486 "Do input: failed loading orbitals from " + orbFileAB);
487 return jres;
488 }
489 }
490
491 Orbitals orbitalsB;
492 Orbitals orbitalsA;
493
494 try {
495 orbitalsA.ReadFromCpt(orbFileA);
496 } catch (std::runtime_error&) {
497 SetJobToFailed(jres, pLog,
498 "Do input: failed loading orbitals from " + orbFileA);
499 return jres;
500 }
501
502 try {
503 orbitalsB.ReadFromCpt(orbFileB);
504 } catch (std::runtime_error&) {
505 SetJobToFailed(jres, pLog,
506 "Do input: failed loading orbitals from " + orbFileB);
507 return jres;
508 }
509
510 try {
511 Logger bsecoupling_logger(Log::current_level);
512 bsecoupling_logger.setMultithreading(false);
513 bsecoupling_logger.setPreface(Log::info,
514 (boost::format("\nBSECOU INF ...")).str());
515 bsecoupling_logger.setPreface(Log::error,
516 (boost::format("\nBSECOU ERR ...")).str());
517 bsecoupling_logger.setPreface(Log::warning,
518 (boost::format("\nBSECOU WAR ...")).str());
519 bsecoupling_logger.setPreface(Log::debug,
520 (boost::format("\nBSECOU DBG ...")).str());
521 bsecoupling.setLogger(&bsecoupling_logger);
522 bsecoupling.Initialize(bsecoupling_options_);
523 bsecoupling.CalculateCouplings(orbitalsA, orbitalsB, orbitalsAB);
524 bsecoupling.Addoutput(job_output, orbitalsA, orbitalsB);
525 WriteLoggerToFile(work_dir + "/bsecoupling.log", bsecoupling_logger);
526 } catch (std::runtime_error& error) {
527 std::string errormessage(error.what());
528 SetJobToFailed(jres, pLog, errormessage);
529 return jres;
530 }
531 }
532
534 std::stringstream sout;
535 sout << iomXML << job_summary;
536 XTP_LOG(Log::error, pLog) << TimeStamp() << " Finished evaluating pair "
537 << ID_A << ":" << ID_B << std::flush;
538 if (store_dft_ || store_gw_) {
539 std::filesystem::create_directories(orb_dir);
540 XTP_LOG(Log::error, pLog)
541 << "Saving orbitals to " << orbFileAB << std::flush;
542 if (!store_dft_) {
543 orbitalsAB.MOs().clear();
544 }
545 if (!store_gw_) {
546 orbitalsAB.QPdiag().clear();
547 orbitalsAB.QPpertEnergies().resize(0);
548 }
549 orbitalsAB.WriteToCpt(orbFileAB);
550 } else {
551 XTP_LOG(Log::error, pLog)
552 << "Orb file is not saved according to options " << std::flush;
553 }
554
555 jres.setOutput(job_summary);
557
558 return jres;
559}
560
561void IQM::WriteJobFile(const Topology& top) {
562
563 std::cout << std::endl
564 << "... ... Writing job file " << jobfile_ << std::flush;
565 std::ofstream ofs;
566 ofs.open(jobfile_, std::ofstream::out);
567 if (!ofs.is_open()) {
568 throw std::runtime_error("\nERROR: bad file handle: " + jobfile_);
569 }
570
571 const QMNBList& nblist = top.NBList();
572
573 Index jobCount = 0;
574 if (nblist.size() == 0) {
575 std::cout << std::endl
576 << "... ... No pairs in neighbor list, skip." << std::flush;
577 return;
578 }
579
580 ofs << "<jobs>" << std::endl;
581 std::string tag = "";
582
583 for (const QMPair* pair : nblist) {
584 if (pair->getType() == QMPair::Excitoncl) {
585 continue;
586 }
587 Index id1 = pair->Seg1()->getId();
588 std::string name1 = pair->Seg1()->getType();
589 Index id2 = pair->Seg2()->getId();
590 std::string name2 = pair->Seg2()->getType();
591 Index id = jobCount;
592 tools::Property Input;
593 tools::Property& pInput = Input.add("input", "");
594 tools::Property& pSegmentA =
595 pInput.add("segment", boost::lexical_cast<std::string>(id1));
596 pSegmentA.setAttribute<std::string>("type", name1);
597 pSegmentA.setAttribute<Index>("id", id1);
598 tools::Property& pSegmentB =
599 pInput.add("segment", boost::lexical_cast<std::string>(id2));
600 pSegmentB.setAttribute<std::string>("type", name2);
601 pSegmentB.setAttribute<Index>("id", id2);
602 Job job(id, tag, Input, Job::AVAILABLE);
603 job.ToStream(ofs);
604 jobCount++;
605 }
606 // CLOSE STREAM
607 ofs << "</jobs>" << std::endl;
608 ofs.close();
609 std::cout << std::endl
610 << "... ... In total " << jobCount << " jobs" << std::flush;
611 return;
612}
613
615 Index stateB) {
616 double J = 0;
617 bool found = false;
618 for (const tools::Property* state : dftprop.Select("coupling")) {
619 Index state1 = state->getAttribute<Index>("levelA");
620 Index state2 = state->getAttribute<Index>("levelB");
621 if (state1 == stateA && state2 == stateB) {
622 J = state->getAttribute<double>("j") * tools::conv::ev2hrt;
623 found = true;
624 break;
625 }
626 }
627 if (found) {
628 return J * J;
629 } else {
630 return -1;
631 }
632}
633
635 const QMState& stateA,
636 const QMState& stateB) {
637 double J = 0;
638 std::string algorithm = bseprop.getAttribute<std::string>("algorithm");
639 bool found = false;
640 for (const tools::Property* state : bseprop.Select("coupling")) {
641 QMState state1 = state->getAttribute<QMState>("stateA");
642 QMState state2 = state->getAttribute<QMState>("stateB");
643 if (state1 == stateA && state2 == stateB) {
644 J = state->getAttribute<double>(algorithm) * tools::conv::ev2hrt;
645 found = true;
646 break;
647 }
648 }
649 if (found) {
650 return J * J;
651 } else {
652 return -1;
653 }
654}
655
656QMState IQM::GetElementFromMap(const std::map<std::string, QMState>& elementmap,
657 const std::string& elementname) const {
658 QMState state;
659 try {
660 state = elementmap.at(elementname);
661 } catch (std::out_of_range&) {
662 std::string errormessage =
663 "Map does not have segment of type: " + elementname;
664 errormessage += "\n segments in map are:";
665 for (const auto& s : elementmap) {
666 errormessage += "\n\t" + s.first;
667 }
668 throw std::runtime_error(errormessage);
669 }
670 return state;
671}
672
674 // gets the neighborlist from the topology
675 QMNBList& nblist = top.NBList();
676 Index number_of_pairs = nblist.size();
677 Index dft_h = 0;
678 Index dft_e = 0;
679 Index bse_s = 0;
680 Index bse_t = 0;
681 Index incomplete_jobs = 0;
682 Logger log;
684
685 tools::Property xml;
686 // load the QC results in a vector indexed by the pair ID
688
689 // loop over all jobs = pair records in the job file
690 for (tools::Property* job : xml.Select("jobs.job")) {
691 if (!job->exists("status")) {
692 throw std::runtime_error(
693 "Jobfile is malformed. <status> tag missing on job.");
694 }
695 if (job->get("status").as<std::string>() != "COMPLETE" ||
696 !job->exists("output")) {
697 incomplete_jobs++;
698 continue;
699 }
700
701 // job file is stupid, because segment ids are only in input have to get
702 // them out l
703 std::vector<Index> id;
704 for (tools::Property* segment : job->Select("input.segment")) {
705 id.push_back(segment->getAttribute<Index>("id"));
706 }
707 if (id.size() != 2) {
708 throw std::runtime_error(
709 "Getting pair ids from jobfile failed, check jobfile.");
710 }
711
712 // segments which correspond to these ids
713 Segment& segA = top.getSegment(id[0]);
714 Segment& segB = top.getSegment(id[1]);
715 // pair that corresponds to the two segments
716 QMPair* qmp = nblist.FindPair(&segA, &segB);
717
718 if (qmp == nullptr) { // there is no pair in the neighbor list with this
719 // name
720 XTP_LOG(Log::error, log)
721 << "No pair " << id[0] << ":" << id[1]
722 << " found in the neighbor list. Ignoring" << std::flush;
723 continue;
724 }
725 if (qmp->getType() != QMPair::PairType::Hopping) {
726 XTP_LOG(Log::error, log) << "WARNING Pair " << qmp->getId()
727 << " is not of any of the "
728 "Hopping type. Skipping pair"
729 << std::flush;
730 continue;
731 }
732
733 const tools::Property& pair_property = job->get("output");
734
735 if (pair_property.exists("dftcoupling")) {
736 const tools::Property& dftprop = pair_property.get("dftcoupling");
737 Index homoA = dftprop.getAttribute<Index>("homoA");
738 Index homoB = dftprop.getAttribute<Index>("homoB");
740 if (dftprop.exists(hole.ToLongString())) {
741 const tools::Property& holes = dftprop.get(hole.ToLongString());
744 Index levelA = homoA - stateA.StateIdx(); // h1 is is homo;
745 Index levelB = homoB - stateB.StateIdx();
746 double J2 = GetDFTCouplingFromProp(holes, levelA, levelB);
747 if (J2 >= 0) {
748 qmp->setJeff2(J2, hole);
749 dft_h++;
750 }
751 }
753 if (dftprop.exists(electron.ToLongString())) {
754 const tools::Property& electrons = dftprop.get(electron.ToLongString());
757 Index levelA = homoA + 1 + stateA.StateIdx(); // e1 is lumo;
758 Index levelB = homoB + 1 + stateB.StateIdx();
759 double J2 = GetDFTCouplingFromProp(electrons, levelA, levelB);
760 if (J2 >= 0) {
761 qmp->setJeff2(J2, electron);
762 dft_e++;
763 }
764 }
765 }
766 if (pair_property.exists("bsecoupling")) {
767 const tools::Property& bseprop = pair_property.get("bsecoupling");
769 if (bseprop.exists(singlet.ToLongString())) {
770 const tools::Property& singlets = bseprop.get(singlet.ToLongString());
773 double J2 = GetBSECouplingFromProp(singlets, stateA, stateB);
774 if (J2 >= 0) {
775 qmp->setJeff2(J2, singlet);
776 bse_s++;
777 }
778 }
780 if (bseprop.exists(triplet.ToLongString())) {
781 const tools::Property& triplets = bseprop.get(triplet.ToLongString());
784 double J2 = GetBSECouplingFromProp(triplets, stateA, stateB);
785 if (J2 >= 0) {
786 qmp->setJeff2(J2, triplet);
787 bse_t++;
788 }
789 }
790 }
791 }
792 XTP_LOG(Log::error, log) << "Pairs [total:updated(e,h,s,t)] "
793 << number_of_pairs << ":(" << dft_e << "," << dft_h
794 << "," << bse_s << "," << bse_t
795 << ") Incomplete jobs: " << incomplete_jobs << "\n"
796 << std::flush;
797 std::cout << log;
798 return;
799}
800} // namespace xtp
801} // namespace votca
pair_type * FindPair(element_type e1, element_type e2)
Definition pairlist.h:93
Index size() const
Definition pairlist.h:53
virtual std::unique_ptr< T > Create(const key_t &key, args_t &&...arguments)
Manipulates the format state of the output stream.
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
T ifExistsReturnElseReturnDefault(const std::string &key, T defaultvalue) const
Definition property.h:321
T getAttribute(const std::string &attribute) const
return attribute as type
Definition property.h:308
std::vector< Property * > Select(const std::string &filter)
select property based on a filter
Definition property.cc:185
void setAttribute(const std::string &attribute, const T &value)
set an attribute
Definition property.h:314
void LoadFromXML(std::string filename)
Definition property.cc:238
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
Evaluates electronic coupling elements.
Definition bsecoupling.h:40
void CalculateCouplings(const Orbitals &orbitalsA, const Orbitals &orbitalsB, const Orbitals &orbitalsAB) override
evaluates electronic couplings
void Addoutput(tools::Property &type_summary, const Orbitals &orbitalsA, const Orbitals &orbitalsB) const override
void Initialize(tools::Property &options) override
void setLogger(Logger *pLog)
Evaluates electronic coupling elements.
Definition dftcoupling.h:38
void Initialize(tools::Property &) override
void Addoutput(tools::Property &type_summary, const Orbitals &orbitalsA, const Orbitals &orbitalsB) const override
void CalculateCouplings(const Orbitals &orbitalsA, const Orbitals &orbitalsB, const Orbitals &orbitalsAB) override
evaluates electronic couplings
Electronic excitations from GW-BSE.
Definition gwbse.h:56
bool Evaluate()
Definition gwbse.cc:568
void Initialize(tools::Property &options)
Definition gwbse.cc:59
void setLogger(Logger *pLog)
Definition gwbse.h:63
bool do_dft_input_
Definition iqm.h:82
std::map< std::string, QMState > FillParseMaps(const std::string &Mapstring)
Definition iqm.cc:117
void SetJobToFailed(Job::JobResult &jres, Logger &pLog, const std::string &errormessage)
Definition iqm.cc:154
Job::JobResult EvalJob(const Topology &top, Job &job, QMThread &opThread)
Definition iqm.cc:172
tools::Property dftcoupling_options_
Definition iqm.h:79
double GetBSECouplingFromProp(const tools::Property &bseprop, const QMState &stateA, const QMState &stateB)
Definition iqm.cc:634
bool do_bsecoupling_
Definition iqm.h:87
tools::Property dftpackage_options_
Definition iqm.h:76
QMState GetElementFromMap(const std::map< std::string, QMState > &elementmap, const std::string &elementname) const
Definition iqm.cc:656
void WriteJobFile(const Topology &top)
Definition iqm.cc:561
std::map< std::string, QMState > triplet_levels_
Definition iqm.h:97
bool do_dftcoupling_
Definition iqm.h:85
bool store_dft_
Definition iqm.h:92
tools::Property gwbse_options_
Definition iqm.h:77
void ParseSpecificOptions(const tools::Property &user_options)
Definition iqm.cc:42
std::map< std::string, QMState > electron_levels_
Definition iqm.h:100
tools::Property bsecoupling_options_
Definition iqm.h:78
std::string Identify() const
Calculator name.
Definition iqm.h:53
void WriteLoggerToFile(const std::string &logfile, Logger &logger)
Definition iqm.cc:162
std::map< std::string, QMState > singlet_levels_
Definition iqm.h:96
bool isLinker(const std::string &name)
Definition iqm.cc:150
void addLinkers(std::vector< const Segment * > &segments, const Topology &top)
Definition iqm.cc:134
bool do_dft_parse_
Definition iqm.h:84
double GetDFTCouplingFromProp(const tools::Property &dftprop, Index stateA, Index stateB)
Definition iqm.cc:614
std::map< std::string, QMState > hole_levels_
Definition iqm.h:99
bool do_gwbse_
Definition iqm.h:86
std::map< std::string, QMState > linkers_
Definition iqm.h:89
bool do_dft_run_
Definition iqm.h:83
bool store_gw_
Definition iqm.h:93
void ReadJobFile(Topology &top)
Definition iqm.cc:673
void setError(std::string error)
Definition job.h:67
void setOutput(std::string output)
Definition job.h:50
void setStatus(JobStatus stat)
Definition job.h:49
tools::Property & getInput()
Definition job.h:87
Index getId() const
Definition job.h:85
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
Container for molecular orbitals and derived one-particle data.
Definition orbitals.h:47
const tools::EigenSystem & QPdiag() const
Return read-only access to the diagonalized quasiparticle representation.
Definition orbitals.h:451
const Eigen::VectorXd & QPpertEnergies() const
Return read-only access to perturbative quasiparticle energies.
Definition orbitals.h:438
void PrepareDimerGuess(const Orbitals &orbitalsA, const Orbitals &orbitalsB)
Guess for a dimer based on monomer orbitals.
Definition orbitals.cc:626
const tools::EigenSystem & MOs() const
Return read-only access to alpha/restricted molecular orbitals.
Definition orbitals.h:192
const QMMolecule & QMAtoms() const
Return read-only access to the molecular geometry.
Definition orbitals.h:259
void ReadFromCpt(const std::string &filename)
Read the orbital container from a checkpoint file on disk.
Definition orbitals.cc:770
void WriteToCpt(const std::string &filename) const
Write the orbital container to a checkpoint file on disk.
Definition orbitals.cc:690
typename std::vector< Job >::value_type Job
void AddContainer(const AtomContainer< QMAtom > &container)
Definition qmmolecule.h:40
void setJeff2(double Jeff2, QMStateType state)
Definition qmpair.h:113
const PairType & getType() const
Definition qmpair.h:130
Index getId() const
Definition qmpair.h:90
std::string ToLongString() const
Definition qmstate.cc:69
Identifier for QMstates. Strings like S1 are converted into enum +zero indexed int.
Definition qmstate.h:133
Index StateIdx() const
Definition qmstate.h:155
Logger & getLogger()
Definition qmthread.h:55
void LoadMappingFile(const std::string &mapfile)
AtomContainer map(const Segment &seg, const SegId &segid) const
Timestamp returns the current time as a string Example: cout << TimeStamp()
Definition logger.h:224
Container for segments and box and atoms.
Definition topology.h:41
Index getStep() const
Definition topology.h:75
std::vector< const Segment * > FindAllSegmentsOnMolecule(const Segment &seg1, const Segment &seg2) const
Definition topology.cc:149
QMNBList & NBList()
Definition topology.h:70
Segment & getSegment(Index id)
Definition topology.h:55
#define XTP_LOG(level, log)
Definition logger.h:40
const double ev2hrt
Definition constants.h:54
Charge transport classes.
Definition ERIs.h:28
SegmentMapper< QMMolecule > QMMapper
Provides a means for comparing floating point numbers.
Definition basebead.h:33
Eigen::Index Index
Definition types.h:26
static Level current_level
Definition globals.h:30