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 <regex>
22 
23 // Third party includes
24 #include <boost/algorithm/string.hpp>
25 #include <boost/format.hpp>
26 #include <boost/lexical_cast.hpp>
27 #include <boost/regex.hpp>
28 
29 // Local VOTCA includes
30 #include "votca/xtp/qmstate.h"
31 
32 namespace votca {
33 namespace xtp {
34 
ToString() const35 std::string QMStateType::ToString() const {
36   std::string identifier = "";
37   switch (type_) {
38     case QMStateType::Singlet:
39       identifier = "s";
40       break;
41     case QMStateType::Triplet:
42       identifier = "t";
43       break;
44     case QMStateType::PQPstate:
45       identifier = "pqp";
46       break;
47     case QMStateType::DQPstate:
48       identifier = "dqp";
49       break;
50     case QMStateType::KSstate:
51       identifier = "ks";
52       break;
53     case QMStateType::Gstate:
54       identifier = "n";
55       break;
56     case QMStateType::Hole:
57       identifier = "h";
58       break;
59     case QMStateType::Electron:
60       identifier = "e";
61       break;
62   }
63   return identifier;
64 }
65 
ToLongString() const66 std::string QMStateType::ToLongString() const {
67   std::string identifier = "";
68   switch (type_) {
69     case QMStateType::Singlet:
70       identifier = "singlet";
71       break;
72     case QMStateType::Triplet:
73       identifier = "triplet";
74       break;
75     case QMStateType::PQPstate:
76       identifier = "pert-qparticle";
77       break;
78     case QMStateType::DQPstate:
79       identifier = "diag-qparticle";
80       break;
81     case QMStateType::KSstate:
82       identifier = "Kohn-Sham-orbital";
83       break;
84     case QMStateType::Gstate:
85       identifier = "groundstate";
86       break;
87     case QMStateType::Hole:
88       identifier = "hole";
89       break;
90     case QMStateType::Electron:
91       identifier = "electron";
92       break;
93   }
94   return identifier;
95 }
96 
FromString(const std::string & statetypestring)97 void QMStateType::FromString(const std::string& statetypestring) {
98   std::string lower = boost::algorithm::to_lower_copy(statetypestring);
99   boost::trim(lower);
100   if (lower == "s" || lower == "singlet") {
101     type_ = QMStateType::Singlet;
102   } else if (lower == "t" || lower == "triplet") {
103     type_ = QMStateType::Triplet;
104   } else if (lower == "pqp" || lower == "pert-qparticle") {
105     type_ = QMStateType::PQPstate;
106   } else if (lower == "dqp" || lower == "diag-qparticle" || lower == "qpdiag") {
107     type_ = QMStateType::DQPstate;
108   } else if (lower == "ks" || lower == "kohn-sham-orbital") {
109     type_ = QMStateType::KSstate;
110   } else if (lower == "n" || lower == "groundstate" || lower == "gs") {
111     type_ = QMStateType::Gstate;
112   } else if (lower == "h" || lower == "hole") {
113     type_ = QMStateType::Hole;
114   } else if (lower == "e" || lower == "electron") {
115     type_ = QMStateType::Electron;
116   } else {
117     throw std::runtime_error("Statetype:" + statetypestring +
118                              " not recognized");
119   }
120 }
121 
ToLongString() const122 std::string QMState::ToLongString() const {
123   Index index = index_;
124   if (type_ == QMStateType::Singlet || type_ == QMStateType::Triplet) {
125     index++;
126   } else if (type_ == QMStateType::Gstate || type_ == QMStateType::Electron ||
127              type_ == QMStateType::Hole) {
128     return type_.ToLongString();
129   }
130   std::string result =
131       type_.ToLongString() + (boost::format(" %i") % index).str();
132   if (transition_) {
133     result = "Groundstate to " + result;
134   }
135   return result;
136 }
137 
ToString() const138 std::string QMState::ToString() const {
139   Index index = index_;
140   if (type_ == QMStateType::Singlet || type_ == QMStateType::Triplet) {
141     index++;
142   } else if (type_ == QMStateType::Gstate || type_ == QMStateType::Electron ||
143              type_ == QMStateType::Hole) {
144     return type_.ToString();
145   }
146   std::string result = type_.ToString() + (boost::format("%i") % index).str();
147   if (transition_) {
148     result = "n2" + result;
149   }
150   return result;
151 }
152 
DetermineIndex(const std::string & statestring)153 Index QMState::DetermineIndex(const std::string& statestring) {
154 
155   std::smatch search;
156   std::regex reg("[0-9]+");
157 
158   bool found_integer = std::regex_search(statestring, search, reg);
159   if (!found_integer) {
160 
161     if (type_ == QMStateType::Hole || type_ == QMStateType::Electron) {
162       return 0;
163     }
164 
165     throw std::runtime_error("Found no index in string: " + statestring);
166   }
167   if (search.size() > 1) {
168     throw std::runtime_error("Found more than 1 index in string: " +
169                              statestring);
170   }
171 
172   Index index = boost::lexical_cast<Index>(search.str(0));
173   if (type_.isExciton() || type_ == QMStateType::Electron ||
174       type_ == QMStateType::Hole) {
175     index--;
176   }
177   return index;
178 }
179 
DetermineType(const std::string & statestring)180 QMStateType QMState::DetermineType(const std::string& statestring) {
181   std::regex reg("[^0-9]+");
182   std::smatch search;
183 
184   bool found_typestring = std::regex_search(statestring, search, reg);
185   if (!found_typestring) {
186     throw std::runtime_error("Found no type in string: " + statestring);
187   }
188   if (search.size() > 1) {
189     throw std::runtime_error("Found more than one type in string: " +
190                              statestring);
191   }
192   return QMStateType(search.str(0));
193 }
194 
FromString(const std::string & statestring)195 void QMState::FromString(const std::string& statestring) {
196   std::string lower = boost::algorithm::to_lower_copy(statestring);
197   boost::trim(lower);
198   std::string rest;
199   if (boost::starts_with(lower, "n2")) {
200     transition_ = true;
201     rest = lower.substr(2);
202   } else if (boost::starts_with(lower, "groundstate to")) {
203     transition_ = true;
204     rest = lower.substr(14);
205   } else {
206     rest = lower;
207     transition_ = false;
208   }
209   boost::trim(rest);
210 
211   type_ = DetermineType(rest);
212   if (type_ != QMStateType::Singlet && transition_ == true) {
213     throw std::runtime_error("Transition states only exist for singlets.");
214   }
215   if (type_ == QMStateType::Gstate) {
216     index_ = -1;
217   } else {
218     index_ = DetermineIndex(rest);
219   }
220 }
221 
222 }  // namespace xtp
223 }  // namespace votca
224