votca 2024.1-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
39using boost::format;
40
41namespace votca {
42namespace xtp {
43
45
47
48 // job tasks
49 std::string tasks_string = options.get(".tasks").as<std::string>();
50
51 // We split either on a space or a comma
52 tools::Tokenizer tokenizedTasks(tasks_string, " ,");
53 std::vector<std::string> tasks = tokenizedTasks.ToVector();
54
55 // Check which tasks exist and set them to true
56 do_dft_input_ = std::find(tasks.begin(), tasks.end(), "input") != tasks.end();
57 do_dft_run_ = std::find(tasks.begin(), tasks.end(), "dft") != tasks.end();
58 do_dft_parse_ = std::find(tasks.begin(), tasks.end(), "parse") != tasks.end();
60 std::find(tasks.begin(), tasks.end(), "dftcoupling") != tasks.end();
61 do_gwbse_ = std::find(tasks.begin(), tasks.end(), "gwbse") != tasks.end();
63 std::find(tasks.begin(), tasks.end(), "bsecoupling") != tasks.end();
64
65 // storage options
66 std::string store_string = options.get(".store").as<std::string>();
67 if (store_string.find("dft") != std::string::npos) {
68 store_dft_ = true;
69 }
70 if (store_string.find("gw") != std::string::npos) {
71 store_gw_ = true;
72 }
73
74 dftpackage_options_ = options.get(".dftpackage");
75 gwbse_options_ = options.get("gwbse");
76 dftcoupling_options_ = options.get(".dftcoupling");
77 bsecoupling_options_ = options.get("bsecoupling");
78
79 // read linker groups
80 std::string linker =
81 options.ifExistsReturnElseReturnDefault<std::string>(".linker_names", "");
82
83 for (const std::string& link :
84 tools::Tokenizer(linker, ", \t\n").ToVector()) {
85 tools::Tokenizer toker2(link, ":");
86 std::vector<std::string> link_split = toker2.ToVector();
87 if (link_split.size() != 2) {
88 throw std::runtime_error(
89 "Linker molecule has to be defined NAME:STATEGEO .e.g. DCV5T:n");
90 }
91 linkers_[link_split[0]] = QMState(link_split[1]);
92 }
93
94 // options for parsing data into state file
95 std::string key_read = ".readjobfile";
96 if (options.exists(key_read + ".singlet")) {
97 std::string parse_string_s =
98 options.get(key_read + ".singlet").as<std::string>();
99 singlet_levels_ = FillParseMaps(parse_string_s);
100 }
101 if (options.exists(key_read + ".triplet")) {
102 std::string parse_string_t =
103 options.get(key_read + ".triplet").as<std::string>();
104 triplet_levels_ = FillParseMaps(parse_string_t);
105 }
106
107 if (options.exists(key_read + ".hole")) {
108 std::string parse_string_h =
109 options.get(key_read + ".hole").as<std::string>();
110 hole_levels_ = FillParseMaps(parse_string_h);
111 }
112 if (options.exists(key_read + ".electron")) {
113 std::string parse_string_e =
114 options.get(key_read + ".electron").as<std::string>();
115 electron_levels_ = FillParseMaps(parse_string_e);
116 }
117}
118
119std::map<std::string, QMState> IQM::FillParseMaps(
120 const std::string& Mapstring) {
121 std::map<std::string, QMState> type2level;
122 for (const std::string& substring : tools::Tokenizer(Mapstring, ", \t\n")) {
123 std::vector<std::string> segmentpnumber =
124 tools::Tokenizer(substring, ":").ToVector();
125 if (segmentpnumber.size() != 2) {
126 throw std::runtime_error("Parser iqm: Segment and exciton labels:" +
127 substring + "are not separated properly");
128 }
129 QMState state = QMState(segmentpnumber[1]);
130 std::string segmentname = segmentpnumber[0];
131 type2level[segmentname] = state;
132 }
133 return type2level;
134}
135
136void IQM::addLinkers(std::vector<const Segment*>& segments,
137 const Topology& top) {
138 const Segment* seg1 = segments[0];
139 const Segment* seg2 = segments[1];
140 std::vector<const Segment*> segmentsInMolecule =
141 top.FindAllSegmentsOnMolecule(*seg1, *seg2);
142
143 for (const Segment* segment : segmentsInMolecule) {
144 Index idIterator = segment->getId();
145 if (idIterator != seg1->getId() && idIterator != seg2->getId() &&
146 isLinker(segment->getType())) {
147 segments.push_back(segment);
148 }
149 }
150}
151
152bool IQM::isLinker(const std::string& name) {
153 return linkers_.count(name) == 1;
154}
155
157 const std::string& errormessage) {
158 XTP_LOG(Log::error, pLog) << errormessage << std::flush;
159 std::cout << pLog;
160 jres.setError(errormessage);
162}
163
164void IQM::WriteLoggerToFile(const std::string& logfile, Logger& logger) {
165 std::ofstream ofs;
166 ofs.open(logfile, std::ofstream::out);
167 if (!ofs.is_open()) {
168 throw std::runtime_error("Bad file handle: " + logfile);
169 }
170 ofs << logger << std::endl;
171 ofs.close();
172}
173
174Job::JobResult IQM::EvalJob(const Topology& top, Job& job, QMThread& opThread) {
175
176 // report back to the progress observer
178
179 std::string iqm_work_dir = "OR_FILES";
180 std::string eqm_work_dir = "OR_FILES";
181 std::string frame_dir =
182 "frame_" + boost::lexical_cast<std::string>(top.getStep());
183
184 Logger& pLog = opThread.getLogger();
185
186 QMMapper mapper(pLog);
188
189 // get the information about the job executed by the thread
190 Index job_ID = job.getId();
191 tools::Property job_input = job.getInput();
192 std::vector<tools::Property*> segment_list = job_input.Select("segment");
193 Index ID_A = segment_list.front()->getAttribute<Index>("id");
194 std::string type_A = segment_list.front()->getAttribute<std::string>("type");
195 Index ID_B = segment_list.back()->getAttribute<Index>("id");
196 std::string type_B = segment_list.back()->getAttribute<std::string>("type");
197
198 std::string qmgeo_state_A = "n";
199 if (segment_list.front()->exists("qm_geometry")) {
200 qmgeo_state_A =
201 segment_list.front()->getAttribute<std::string>("qm_geometry");
202 }
203
204 std::string qmgeo_state_B = "n";
205 if (segment_list.back()->exists("qm_geometry")) {
206 qmgeo_state_B =
207 segment_list.back()->getAttribute<std::string>("qm_geometry");
208 }
209 QMState stateA(qmgeo_state_A);
210 QMState stateB(qmgeo_state_B);
211
212 // set the folders
213 std::string pair_dir =
214 (format("%1%%2%%3%%4%%5%") % "pair" % "_" % ID_A % "_" % ID_B).str();
215
216 std::filesystem::path arg_path, arg_pathA, arg_pathB, arg_pathAB;
217
218 std::string orbFileA =
219 (arg_pathA / eqm_work_dir / "molecules" / frame_dir /
220 (format("%1%_%2%%3%") % "molecule" % ID_A % ".orb").str())
221 .generic_string();
222 ;
223 std::string orbFileB =
224 (arg_pathB / eqm_work_dir / "molecules" / frame_dir /
225 (format("%1%_%2%%3%") % "molecule" % ID_B % ".orb").str())
226 .generic_string();
227 ;
228 std::string orbFileAB =
229 (arg_pathAB / iqm_work_dir / "pairs_iqm" / frame_dir /
230 (format("%1%%2%%3%%4%%5%") % "pair_" % ID_A % "_" % ID_B % ".orb").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, (format("\nDFT INF ...")).str());
291 dft_logger.setPreface(Log::error, (format("\nDFT ERR ...")).str());
292 dft_logger.setPreface(Log::warning, (format("\nDFT WAR ...")).str());
293 dft_logger.setPreface(Log::debug, (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 (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 (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&) {
350 SetJobToFailed(
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&) {
361 SetJobToFailed(
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, (format("\nGWBSE INF ...")).str());
455 gwbse_logger.setPreface(Log::error, (format("\nGWBSE ERR ...")).str());
456 gwbse_logger.setPreface(Log::warning, (format("\nGWBSE WAR ...")).str());
457 gwbse_logger.setPreface(Log::debug, (format("\nGWBSE DBG ...")).str());
458 GWBSE gwbse = GWBSE(orbitalsAB);
459 gwbse.setLogger(&gwbse_logger);
461 gwbse.Evaluate();
462 WriteLoggerToFile(work_dir + "/gwbse.log", gwbse_logger);
463 } catch (std::runtime_error& error) {
464 std::string errormessage(error.what());
465 SetJobToFailed(jres, pLog, errormessage);
466 return jres;
467 }
468
469 } // end of excited state calculation, exciton data is in orbitalsAB_
470
471 // calculate the coupling
472
473 if (do_bsecoupling_) {
474 XTP_LOG(Log::error, pLog) << "Running BSECoupling" << std::flush;
475 BSECoupling bsecoupling;
476 // orbitals must be loaded from a file
477 if (!do_gwbse_) {
478 try {
479 orbitalsAB.ReadFromCpt(orbFileAB);
480 } catch (std::runtime_error&) {
481 SetJobToFailed(jres, pLog,
482 "Do input: failed loading orbitals from " + orbFileAB);
483 return jres;
484 }
485 }
486
487 Orbitals orbitalsB;
488 Orbitals orbitalsA;
489
490 try {
491 orbitalsA.ReadFromCpt(orbFileA);
492 } catch (std::runtime_error&) {
493 SetJobToFailed(jres, pLog,
494 "Do input: failed loading orbitals from " + orbFileA);
495 return jres;
496 }
497
498 try {
499 orbitalsB.ReadFromCpt(orbFileB);
500 } catch (std::runtime_error&) {
501 SetJobToFailed(jres, pLog,
502 "Do input: failed loading orbitals from " + orbFileB);
503 return jres;
504 }
505
506 try {
507 Logger bsecoupling_logger(Log::current_level);
508 bsecoupling_logger.setMultithreading(false);
509 bsecoupling_logger.setPreface(Log::info,
510 (format("\nBSECOU INF ...")).str());
511 bsecoupling_logger.setPreface(Log::error,
512 (format("\nBSECOU ERR ...")).str());
513 bsecoupling_logger.setPreface(Log::warning,
514 (format("\nBSECOU WAR ...")).str());
515 bsecoupling_logger.setPreface(Log::debug,
516 (format("\nBSECOU DBG ...")).str());
517 bsecoupling.setLogger(&bsecoupling_logger);
518 bsecoupling.Initialize(bsecoupling_options_);
519 bsecoupling.CalculateCouplings(orbitalsA, orbitalsB, orbitalsAB);
520 bsecoupling.Addoutput(job_output, orbitalsA, orbitalsB);
521 WriteLoggerToFile(work_dir + "/bsecoupling.log", bsecoupling_logger);
522 } catch (std::runtime_error& error) {
523 std::string errormessage(error.what());
524 SetJobToFailed(jres, pLog, errormessage);
525 return jres;
526 }
527 }
528
530 std::stringstream sout;
531 sout << iomXML << job_summary;
532 XTP_LOG(Log::error, pLog) << TimeStamp() << " Finished evaluating pair "
533 << ID_A << ":" << ID_B << std::flush;
534 if (store_dft_ || store_gw_) {
535 std::filesystem::create_directories(orb_dir);
536 XTP_LOG(Log::error, pLog)
537 << "Saving orbitals to " << orbFileAB << std::flush;
538 if (!store_dft_) {
539 orbitalsAB.MOs().clear();
540 }
541 if (!store_gw_) {
542 orbitalsAB.QPdiag().clear();
543 orbitalsAB.QPpertEnergies().resize(0);
544 }
545 orbitalsAB.WriteToCpt(orbFileAB);
546 } else {
547 XTP_LOG(Log::error, pLog)
548 << "Orb file is not saved according to options " << std::flush;
549 }
550
551 jres.setOutput(job_summary);
553
554 return jres;
555}
556
557void IQM::WriteJobFile(const Topology& top) {
558
559 std::cout << std::endl
560 << "... ... Writing job file " << jobfile_ << std::flush;
561 std::ofstream ofs;
562 ofs.open(jobfile_, std::ofstream::out);
563 if (!ofs.is_open()) {
564 throw std::runtime_error("\nERROR: bad file handle: " + jobfile_);
565 }
566
567 const QMNBList& nblist = top.NBList();
568
569 Index jobCount = 0;
570 if (nblist.size() == 0) {
571 std::cout << std::endl
572 << "... ... No pairs in neighbor list, skip." << std::flush;
573 return;
574 }
575
576 ofs << "<jobs>" << std::endl;
577 std::string tag = "";
578
579 for (const QMPair* pair : nblist) {
580 if (pair->getType() == QMPair::Excitoncl) {
581 continue;
582 }
583 Index id1 = pair->Seg1()->getId();
584 std::string name1 = pair->Seg1()->getType();
585 Index id2 = pair->Seg2()->getId();
586 std::string name2 = pair->Seg2()->getType();
587 Index id = jobCount;
588 tools::Property Input;
589 tools::Property& pInput = Input.add("input", "");
590 tools::Property& pSegmentA =
591 pInput.add("segment", boost::lexical_cast<std::string>(id1));
592 pSegmentA.setAttribute<std::string>("type", name1);
593 pSegmentA.setAttribute<Index>("id", id1);
594 tools::Property& pSegmentB =
595 pInput.add("segment", boost::lexical_cast<std::string>(id2));
596 pSegmentB.setAttribute<std::string>("type", name2);
597 pSegmentB.setAttribute<Index>("id", id2);
598 Job job(id, tag, Input, Job::AVAILABLE);
599 job.ToStream(ofs);
600 jobCount++;
601 }
602 // CLOSE STREAM
603 ofs << "</jobs>" << std::endl;
604 ofs.close();
605 std::cout << std::endl
606 << "... ... In total " << jobCount << " jobs" << std::flush;
607 return;
608}
609
611 Index stateB) {
612 double J = 0;
613 bool found = false;
614 for (const tools::Property* state : dftprop.Select("coupling")) {
615 Index state1 = state->getAttribute<Index>("levelA");
616 Index state2 = state->getAttribute<Index>("levelB");
617 if (state1 == stateA && state2 == stateB) {
618 J = state->getAttribute<double>("j") * tools::conv::ev2hrt;
619 found = true;
620 break;
621 }
622 }
623 if (found) {
624 return J * J;
625 } else {
626 return -1;
627 }
628}
629
631 const QMState& stateA,
632 const QMState& stateB) {
633 double J = 0;
634 std::string algorithm = bseprop.getAttribute<std::string>("algorithm");
635 bool found = false;
636 for (const tools::Property* state : bseprop.Select("coupling")) {
637 QMState state1 = state->getAttribute<QMState>("stateA");
638 QMState state2 = state->getAttribute<QMState>("stateB");
639 if (state1 == stateA && state2 == stateB) {
640 J = state->getAttribute<double>(algorithm) * tools::conv::ev2hrt;
641 found = true;
642 break;
643 }
644 }
645 if (found) {
646 return J * J;
647 } else {
648 return -1;
649 }
650}
651
652QMState IQM::GetElementFromMap(const std::map<std::string, QMState>& elementmap,
653 const std::string& elementname) const {
654 QMState state;
655 try {
656 state = elementmap.at(elementname);
657 } catch (std::out_of_range&) {
658 std::string errormessage =
659 "Map does not have segment of type: " + elementname;
660 errormessage += "\n segments in map are:";
661 for (const auto& s : elementmap) {
662 errormessage += "\n\t" + s.first;
663 }
664 throw std::runtime_error(errormessage);
665 }
666 return state;
667}
668
670 // gets the neighborlist from the topology
671 QMNBList& nblist = top.NBList();
672 Index number_of_pairs = nblist.size();
673 Index dft_h = 0;
674 Index dft_e = 0;
675 Index bse_s = 0;
676 Index bse_t = 0;
677 Index incomplete_jobs = 0;
678 Logger log;
680
681 tools::Property xml;
682 // load the QC results in a vector indexed by the pair ID
684
685 // loop over all jobs = pair records in the job file
686 for (tools::Property* job : xml.Select("jobs.job")) {
687 if (!job->exists("status")) {
688 throw std::runtime_error(
689 "Jobfile is malformed. <status> tag missing on job.");
690 }
691 if (job->get("status").as<std::string>() != "COMPLETE" ||
692 !job->exists("output")) {
693 incomplete_jobs++;
694 continue;
695 }
696
697 // job file is stupid, because segment ids are only in input have to get
698 // them out l
699 std::vector<Index> id;
700 for (tools::Property* segment : job->Select("input.segment")) {
701 id.push_back(segment->getAttribute<Index>("id"));
702 }
703 if (id.size() != 2) {
704 throw std::runtime_error(
705 "Getting pair ids from jobfile failed, check jobfile.");
706 }
707
708 // segments which correspond to these ids
709 Segment& segA = top.getSegment(id[0]);
710 Segment& segB = top.getSegment(id[1]);
711 // pair that corresponds to the two segments
712 QMPair* qmp = nblist.FindPair(&segA, &segB);
713
714 if (qmp == nullptr) { // there is no pair in the neighbor list with this
715 // name
716 XTP_LOG(Log::error, log)
717 << "No pair " << id[0] << ":" << id[1]
718 << " found in the neighbor list. Ignoring" << std::flush;
719 continue;
720 }
721 if (qmp->getType() != QMPair::PairType::Hopping) {
722 XTP_LOG(Log::error, log) << "WARNING Pair " << qmp->getId()
723 << " is not of any of the "
724 "Hopping type. Skipping pair"
725 << std::flush;
726 continue;
727 }
728
729 const tools::Property& pair_property = job->get("output");
730
731 if (pair_property.exists("dftcoupling")) {
732 const tools::Property& dftprop = pair_property.get("dftcoupling");
733 Index homoA = dftprop.getAttribute<Index>("homoA");
734 Index homoB = dftprop.getAttribute<Index>("homoB");
736 if (dftprop.exists(hole.ToLongString())) {
737 const tools::Property& holes = dftprop.get(hole.ToLongString());
740 Index levelA = homoA - stateA.StateIdx(); // h1 is is homo;
741 Index levelB = homoB - stateB.StateIdx();
742 double J2 = GetDFTCouplingFromProp(holes, levelA, levelB);
743 if (J2 >= 0) {
744 qmp->setJeff2(J2, hole);
745 dft_h++;
746 }
747 }
749 if (dftprop.exists(electron.ToLongString())) {
750 const tools::Property& electrons = dftprop.get(electron.ToLongString());
753 Index levelA = homoA + 1 + stateA.StateIdx(); // e1 is lumo;
754 Index levelB = homoB + 1 + stateB.StateIdx();
755 double J2 = GetDFTCouplingFromProp(electrons, levelA, levelB);
756 if (J2 >= 0) {
757 qmp->setJeff2(J2, electron);
758 dft_e++;
759 }
760 }
761 }
762 if (pair_property.exists("bsecoupling")) {
763 const tools::Property& bseprop = pair_property.get("bsecoupling");
765 if (bseprop.exists(singlet.ToLongString())) {
766 const tools::Property& singlets = bseprop.get(singlet.ToLongString());
769 double J2 = GetBSECouplingFromProp(singlets, stateA, stateB);
770 if (J2 >= 0) {
771 qmp->setJeff2(J2, singlet);
772 bse_s++;
773 }
774 }
776 if (bseprop.exists(triplet.ToLongString())) {
777 const tools::Property& triplets = bseprop.get(triplet.ToLongString());
780 double J2 = GetBSECouplingFromProp(triplets, stateA, stateB);
781 if (J2 >= 0) {
782 qmp->setJeff2(J2, triplet);
783 bse_t++;
784 }
785 }
786 }
787 }
788 XTP_LOG(Log::error, log) << "Pairs [total:updated(e,h,s,t)] "
789 << number_of_pairs << ":(" << dft_e << "," << dft_h
790 << "," << bse_s << "," << bse_t
791 << ") Incomplete jobs: " << incomplete_jobs << "\n"
792 << std::flush;
793 std::cout << log;
794 return;
795}
796} // namespace xtp
797} // 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:544
void Initialize(tools::Property &options)
Definition gwbse.cc:60
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:119
void SetJobToFailed(Job::JobResult &jres, Logger &pLog, const std::string &errormessage)
Definition iqm.cc:156
Job::JobResult EvalJob(const Topology &top, Job &job, QMThread &opThread)
Definition iqm.cc:174
tools::Property dftcoupling_options_
Definition iqm.h:79
double GetBSECouplingFromProp(const tools::Property &bseprop, const QMState &stateA, const QMState &stateB)
Definition iqm.cc:630
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:652
void WriteJobFile(const Topology &top)
Definition iqm.cc:557
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:44
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:164
std::map< std::string, QMState > singlet_levels_
Definition iqm.h:96
bool isLinker(const std::string &name)
Definition iqm.cc:152
void addLinkers(std::vector< const Segment * > &segments, const Topology &top)
Definition iqm.cc:136
bool do_dft_parse_
Definition iqm.h:84
double GetDFTCouplingFromProp(const tools::Property &dftprop, Index stateA, Index stateB)
Definition iqm.cc:610
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:669
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
Definition orbitals.h:46
const tools::EigenSystem & QPdiag() const
Definition orbitals.h:317
const Eigen::VectorXd & QPpertEnergies() const
Definition orbitals.h:308
void PrepareDimerGuess(const Orbitals &orbitalsA, const Orbitals &orbitalsB)
Guess for a dimer based on monomer orbitals.
Definition orbitals.cc:571
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 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:132
Index StateIdx() const
Definition qmstate.h:154
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
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