ARTS  2.4.0(git:4fb77825)
quantum.cc
Go to the documentation of this file.
1 /* Copyright (C) 2013
2  Oliver Lemke <olemke@core-dump.info>
3 
4  This program is free software; you can redistribute it and/or modify it
5  under the terms of the GNU General Public License as published by the
6  Free Software Foundation; either version 2, or (at your option) any
7  later version.
8 
9  This program is distributed in the hope that it will be useful,
10  but WITHOUT ANY WARRANTY; without even the implied warranty of
11  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  GNU General Public License for more details.
13 
14  You should have received a copy of the GNU General Public License
15  along with this program; if not, write to the Free Software
16  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
17  USA. */
18 
27 #include "quantum.h"
28 #include <stdexcept>
29 #include "absorption.h"
30 #include "global_data.h"
31 #include "special_interp.h"
32 
33 bool QuantumNumbers::Compare(const QuantumNumbers& qn) const {
34  const QuantumContainer& qnumbers2 = qn.GetNumbers();
35 
36  bool match = true;
37 
38  Index qnri = 0;
39 
40  // Compare all quantum numbers in mqnumbers and qnumbers2
41  while (match && qnri != Index(QuantumNumberType::FINAL_ENTRY)) {
42  // If one of the two numbers is undefined, it is considered as
43  // a match.
44  if (!mqnumbers[qnri].isUndefined() && !qnumbers2[qnri].isUndefined() &&
45  mqnumbers[qnri] != qnumbers2[qnri])
46  match = false;
47 
48  qnri++;
49  }
50 
51  return match;
52 }
53 
54 // Tests if this is in other upper
56  if (mspecies not_eq other.mspecies) return false;
57  if (miso not_eq other.miso) return false;
58 
61  return false;
62  else if (mqtype == QuantumIdentifier::ALL or
64  return true;
65  else if (mqtype not_eq QuantumIdentifier::ENERGY_LEVEL or
67  throw runtime_error(
68  "One of your inputs is bad. You are using function comparing energy levels to the upper state of lines, but the types mismatch");
69 
70  Index qnri = 0;
71  while (qnri not_eq Index(QuantumNumberType::FINAL_ENTRY)) {
72  if (other.mqm[TRANSITION_UPPER_INDEX][qnri].isUndefined()) {
73  if (not mqm[ENERGY_LEVEL_INDEX][qnri].isUndefined()) return false;
74  } else {
75  if (other.mqm[TRANSITION_UPPER_INDEX][qnri] not_eq
76  mqm[ENERGY_LEVEL_INDEX][qnri])
77  return false;
78  }
79  qnri++;
80  }
81 
82  return true;
83 }
84 
85 // Tests that if this is in other lower
87  if (mspecies not_eq other.mspecies) return false;
88  if (miso not_eq other.miso) return false;
89 
92  return false;
93  else if (mqtype == QuantumIdentifier::ALL or
95  return true;
96  else if (mqtype not_eq QuantumIdentifier::ENERGY_LEVEL or
98  throw runtime_error(
99  "One of your inputs is bad. You are using function comparing energy levels to the lower state of lines, but the types mismatch");
100 
101  Index qnri = 0;
102  while (qnri not_eq Index(QuantumNumberType::FINAL_ENTRY)) {
103  if (other.mqm[TRANSITION_LOWER_INDEX][qnri].isUndefined()) {
104  if (not mqm[ENERGY_LEVEL_INDEX][qnri].isUndefined()) return false;
105  } else {
106  if (other.mqm[TRANSITION_LOWER_INDEX][qnri] not_eq
107  mqm[ENERGY_LEVEL_INDEX][qnri])
108  return false;
109  }
110  qnri++;
111  }
112 
113  return true;
114 }
115 
116 // Tests that all of this is in other
117 bool QuantumIdentifier::In(const QuantumIdentifier& other) const {
118  if (mspecies not_eq other.mspecies) return false;
119  if (miso not_eq other.miso) return false;
120 
123  return false;
124  else if (mqtype == QuantumIdentifier::ALL or
125  other.mqtype == QuantumIdentifier::ALL) {
126  } else if (mqtype not_eq other.mqtype)
127  throw std::runtime_error(
128  "Can never compare different types of identifiers with QID.In(QID), one of your inputs is of wrong QuantumIdentifier type");
130  auto& other_low = other.mqm[TRANSITION_LOWER_INDEX];
131  auto& other_upp = other.mqm[TRANSITION_UPPER_INDEX];
132  auto& this_low = mqm[TRANSITION_LOWER_INDEX];
133  auto& this_upp = mqm[TRANSITION_UPPER_INDEX];
134 
135  for (Index i = 0; i < Index(QuantumNumberType::FINAL_ENTRY); i++) {
136  if (other_low[i].isUndefined()) {
137  } else if (this_low[i].isUndefined())
138  return false;
139  else if (this_low[i] not_eq other_low[i])
140  return false;
141 
142  if (other_upp[i].isUndefined()) {
143  } else if (this_upp[i].isUndefined())
144  return false;
145  else if (this_upp[i] not_eq other_upp[i])
146  return false;
147  }
148  } else {
149  auto& other_qn = other.mqm[ENERGY_LEVEL_INDEX];
150  auto& this_qn = mqm[ENERGY_LEVEL_INDEX];
151 
152  for (Index i = 0; i < Index(QuantumNumberType::FINAL_ENTRY); i++) {
153  if (other_qn[i].isUndefined()) {
154  } else if (this_qn[i].isUndefined())
155  return false;
156  else if (this_qn[i] not_eq other_qn[i])
157  return false;
158  }
159  }
160 
161  return true;
162 }
163 
166 }
167 
169  if (!IsValidQuantumNumberName(name)) {
170  ostringstream os;
171  os << "Invalid quantum number: " << name;
172  throw std::runtime_error(os.str());
173  }
174 }
175 
176 std::istream& operator>>(std::istream& is, QuantumNumbers& qn) {
177  String name;
178  Rational r;
179 
180  is >> name >> r;
181 
182  qn.Set(name, r);
183 
184  return is;
185 }
186 
187 std::ostream& operator<<(std::ostream& os, const QuantumNumbers& qn) {
188  bool first = true;
189  for (Index i=0; i<Index(QuantumNumberType::FINAL_ENTRY); i++) {
190  if (qn[i].isDefined()) {
191  if (first) {
192  os << quantumnumbertype2string(QuantumNumberType(i)) << ' ' << qn[i];
193  first = false;
194  } else {
195  os << ' ' << quantumnumbertype2string(QuantumNumberType(i)) << ' ' << qn[i];
196  }
197  }
198  }
199 
200  return os;
201 }
202 
204  String t;
205  switch (mqtype) {
207  t = "TR";
208  break;
210  t = "EN";
211  break;
213  t = "ALL";
214  break;
216  t = "NONE";
217  break;
218  default:
219  assert(0);
220  break;
221  }
222  return t;
223 }
224 
227 }
228 
230  const QuantumNumbers& lower) {
232  mqm[TRANSITION_UPPER_INDEX] = upper;
233  mqm[TRANSITION_LOWER_INDEX] = lower;
234 }
235 
239 }
240 
242  // Global species lookup data:
244 
245  // We need a species index sorted by Arts identifier. Keep this in a
246  // static variable, so that we have to do this only once. The ARTS
247  // species index is ArtsMap[<Arts String>].
248  static map<String, SpecIsoMap> ArtsMap;
249 
250  // Remember if this stuff has already been initialized:
251  static bool hinit = false;
252 
253  if (!hinit) {
254  for (Index i = 0; i < species_data.nelem(); ++i) {
255  const SpeciesRecord& sr = species_data[i];
256 
257  for (Index j = 0; j < sr.Isotopologue().nelem(); ++j) {
258  SpecIsoMap indicies(i, j);
259  String buf = sr.Name() + "-" + sr.Isotopologue()[j].Name();
260 
261  ArtsMap[buf] = indicies;
262  }
263  }
264  hinit = true;
265  }
266 
267  std::istringstream is(str);
268  String token;
269 
270  is >> token;
271 
272  // ok, now for the cool index map:
273  // is this arts identifier valid?
274  const map<String, SpecIsoMap>::const_iterator i = ArtsMap.find(token);
275  if (i == ArtsMap.end()) {
276  ostringstream os;
277  os << "ARTS Tag: " << token << " is unknown.";
278  throw runtime_error(os.str());
279  }
280 
281  SpecIsoMap id = i->second;
282  Species(id.Speciesindex());
283  Isotopologue(id.Isotopologueindex());
284 
285  is >> token;
286  if (token == "TR") {
288  is >> token;
289  if (token != "UP") {
290  std::ostringstream os;
291  os << "Expected 'UP', but got: " << token;
292  throw std::runtime_error(os.str());
293  }
294 
295  is >> token;
296  Rational r;
297  while (is) {
299  is >> r;
301  is >> token;
302  if (token == "LO") break;
303  }
304 
305  if (!is) {
306  std::ostringstream os;
307  os << "Premature end of data, expected 'LO'.";
308  throw std::runtime_error(os.str());
309  }
310  is >> token;
311  while (is) {
313  is >> r;
315  is >> token;
316  }
317  } else if (token == "EN") {
319 
320  is >> token;
321  Rational r;
322  while (is) {
324  is >> r;
326  is >> token;
327  }
328  } else if (token == "ALL") {
330  } else if (token == "NONE") {
332  } else {
333  std::ostringstream os;
334  os << "Error parsing QuantumIdentifier. Expected TR or EN, but got: "
335  << token << "\n"
336  << "QI: " << str;
337  throw std::runtime_error(os.str());
338  }
339 }
340 
342  String lower,
343  String iso) {
344  assert(upper.nelem() == 5);
345  assert(lower.nelem() == 5);
346  assert(iso.nelem() == 3);
347 
348  std::ostringstream os;
349 
350  os << "CO2-" << iso << " TR "
351  << "UP "
352  << "v1 " << upper[0] << " v2 " << upper[1] << " l2 " << upper[2] << " v3 "
353  << upper[3] << " r " << upper[4] << " "
354  << "LO "
355  << "v1 " << lower[0] << " v2 " << lower[1] << " l2 " << lower[2] << " v3 "
356  << lower[3] << " r " << lower[4];
357 
358  SetFromString(os.str());
359 }
360 
361 std::ostream& operator<<(std::ostream& os, const QuantumIdentifier& qi) {
363 
364  if (qi.Species() < 0 || qi.Isotopologue() < 0)
365  return os;
366 
367  const SpeciesRecord& spr = species_data[qi.Species()];
368 
369  os << spr.Name() << "-";
370  if (qi.Isotopologue() == spr.Isotopologue().nelem())
371  os << "*";
372  else
373  os << spr.Isotopologue()[qi.Isotopologue()].Name();
374  os << " ";
375 
377  os << "TR UP "
380  else if (qi.Type() == QuantumIdentifier::ENERGY_LEVEL)
382  else if (qi.Type() == QuantumIdentifier::ALL)
383  os << "ALL";
384  else if (qi.Type() == QuantumIdentifier::NONE)
385  os << "NONE";
386  else
387  assert(0);
388 
389  return os;
390 }
391 
393  Index qni = 0;
394  switch (mqtype) {
397  for (const auto& qns : mqm) do {
398  if (not qns[qni].isUndefined()) return true;
399  qni++;
400  } while (qni not_eq Index(QuantumNumberType::FINAL_ENTRY));
401  break;
404  break;
405  }
406  return false;
407 }
408 
409 std::ostream& operator<<(std::ostream& os, QuantumNumberType t)
410 {
411  return os << quantumnumbertype2string(t);
412 }
413 
415  if (key == QuantumNumberType::parity) {
416  if (val == "+")
417  return 1_rat;
418  else if (val == "-")
419  return -1_rat;
420  } else if (key == QuantumNumberType::ElectronState) {
421  if (val == "X")
422  return Rational(int('X'));
423  } else if (key == QuantumNumberType::kronigParity) {
424  if (val == "f")
425  return Rational(int('f'));
426  else if (val == "e")
427  return Rational(int('e'));
428  } else {
429  return Rational(val);
430  }
431 
432  return RATIONAL_UNDEFINED;
433 }
434 
435 void update_id(QuantumIdentifier& qid, const std::vector<std::array<String, 2> >& upper_list, const std::vector<std::array<String, 2> >& lower_list)
436 {
437  for (auto& keyval: upper_list) {
438  auto key = string2quantumnumbertype(keyval[0]);
439  if (key == QuantumNumberType::FINAL_ENTRY) {
440  std::ostringstream os;
441  os << "The key \"" << keyval[0] << "\" is an invalid input as a quantum number key";
442  std::cout << "WARNING: " << os.str() << '\n';
443  } else {
444  auto val = interpret_stringdata(key, keyval[1]);
445  if (val != RATIONAL_UNDEFINED) {
446  qid.UpperQuantumNumber(key) = val;
447  } else {
448  std::ostringstream os;
449  os << "The key \"" << keyval[0] << "\" and value \"" << keyval[1] << "\" are invalid input as a quantum number key and value pair";
450  std::cout << "WARNING: " << os.str() << '\n';
451  }
452  }
453  }
454 
455  for (auto& keyval: lower_list) {
456  auto key = string2quantumnumbertype(keyval[0]);
457  if (key == QuantumNumberType::FINAL_ENTRY) {
458  std::ostringstream os;
459  os << "The key \"" << keyval[0] << "\" is an invalid input as a quantum number key";
460  std::cout << "WARNING: " << os.str() << '\n';
461  } else {
462  auto val = interpret_stringdata(key, keyval[1]);
463  if (val != RATIONAL_UNDEFINED) {
464  qid.LowerQuantumNumber(key) = val;
465  } else {
466  std::ostringstream os;
467  os << "The key \"" << keyval[0] << "\" and value \"" << keyval[1] << "\" are invalid input as a quantum number key and value pair";
468  std::cout << "WARNING: " << os.str() << '\n';
469  }
470  }
471  }
472 }
RATIONAL_UNDEFINED
#define RATIONAL_UNDEFINED
Definition: rational.h:361
QuantumIdentifier::Isotopologue
void Isotopologue(Index iso)
Set the Isotopologue.
Definition: quantum.h:487
QuantumIdentifier::ENERGY_LEVEL
@ ENERGY_LEVEL
Definition: quantum.h:393
QuantumNumbers
Container class for Quantum Numbers.
Definition: quantum.h:222
QuantumIdentifier
Class to identify and match lines by their quantum numbers.
Definition: quantum.h:390
SpecIsoMap
Definition: absorption.h:338
QuantumNumbers::GetNumbers
const QuantumContainer & GetNumbers() const
Get the numbers.
Definition: quantum.h:338
absorption.h
Declarations required for the calculation of absorption coefficients.
iso
void iso(Array< IsotopologueRecord >::iterator &ii, String name, const ArrayOfNumeric &coeff, const ArrayOfNumeric &temp_range, const Index &coefftype)
Initialize isotopologue and move iterator to next one.
Definition: partition_function_data.cc:1732
QuantumIdentifier::Isotopologue
constexpr Index Isotopologue() const
Return the Isotopologue by index.
Definition: quantum.h:565
QuantumIdentifier::Species
constexpr Index Species() const
Return the Species by index.
Definition: quantum.h:559
QuantumIdentifier::any_quantumnumbers
bool any_quantumnumbers() const
Check if there are any quantum numbers defined.
Definition: quantum.cc:392
QuantumIdentifier::InLower
bool InLower(const QuantumIdentifier &other) const
Return if this is in other's lower energy state.
Definition: quantum.cc:86
interpret_stringdata
Rational interpret_stringdata(const QuantumNumberType key, const String &val)
Definition: quantum.cc:414
QuantumNumberType
QuantumNumberType
Enum for Quantum Numbers used for indexing.
Definition: quantum.h:48
QuantumIdentifier::InUpper
bool InUpper(const QuantumIdentifier &other) const
Return if this is in other's upper energy state.
Definition: quantum.cc:55
QuantumIdentifier::TypeStr
String TypeStr() const
Definition: quantum.cc:203
global_data::species_data
const Array< SpeciesRecord > species_data
Species Data.
Definition: partition_function_data.cc:42
string2quantumnumbertype
QuantumNumberType string2quantumnumbertype(const String &s)
Definition: quantum.h:101
quantum.h
QuantumIdentifier::ALL
@ ALL
Definition: quantum.h:393
QuantumIdentifier::TRANSITION_LOWER_INDEX
static constexpr Index TRANSITION_LOWER_INDEX
Lower level index.
Definition: quantum.h:472
QuantumIdentifier::SetEnergyLevel
void SetEnergyLevel(const QuantumNumbers &q)
Set tp energy level identifier.
Definition: quantum.cc:236
QuantumIdentifier::SetFromString
void SetFromString(String str)
Set from a String object.
Definition: quantum.cc:241
QuantumIdentifier::NONE
@ NONE
Definition: quantum.h:393
Absorption::nelem
Index nelem(const Lines &l)
Number of lines.
Definition: absorptionlines.h:1820
IsValidQuantumNumberName
bool IsValidQuantumNumberName(String name)
Check for valid quantum number name.
Definition: quantum.cc:164
QuantumIdentifier::SpeciesName
String SpeciesName() const
Return the Species by name.
Definition: quantum.cc:225
QuantumIdentifier::TRANSITION_UPPER_INDEX
static constexpr Index TRANSITION_UPPER_INDEX
Upper level index.
Definition: quantum.h:469
species_name_from_species_index
String species_name_from_species_index(const Index spec_ind)
Return species name for given species index.
Definition: absorption.cc:569
QuantumIdentifier::Species
void Species(Index sp)
Set the Species.
Definition: quantum.h:481
my_basic_string< char >
quantumnumbertype2string
String quantumnumbertype2string(QuantumNumberType s)
Definition: quantum.h:162
QuantumIdentifier::mqm
std::array< QuantumNumbers, 2 > mqm
Definition: quantum.h:690
QuantumIdentifier::LowerQuantumNumber
constexpr Rational LowerQuantumNumber(QuantumNumberType X) const noexcept
Return a lower quantum number by copy.
Definition: quantum.h:602
ARTS::Group::Rational
Rational Rational
Definition: autoarts.h:96
QuantumIdentifier::ENERGY_LEVEL_INDEX
static constexpr Index ENERGY_LEVEL_INDEX
Energy level index.
Definition: quantum.h:475
operator<<
std::ostream & operator<<(std::ostream &os, const QuantumNumbers &qn)
Output operator.
Definition: quantum.cc:187
QuantumIdentifier::SetFromStringForCO2Band
void SetFromStringForCO2Band(String upper, String lower, String iso)
Set CO2 transition from String objects.
Definition: quantum.cc:341
global_data.h
QuantumIdentifier::TRANSITION
@ TRANSITION
Definition: quantum.h:393
QuantumIdentifier::mqtype
QType mqtype
Definition: quantum.h:687
SpeciesRecord
Contains the lookup data for one species.
Definition: absorption.h:144
my_basic_string::nelem
Index nelem() const
Number of elements.
Definition: mystring.h:246
update_id
void update_id(QuantumIdentifier &qid, const std::vector< std::array< String, 2 > > &upper_list, const std::vector< std::array< String, 2 > > &lower_list)
Updates the quantum identifier based on a lists of strings.
Definition: quantum.cc:435
QuantumIdentifier::Type
constexpr QType Type() const
Definition: quantum.h:526
QuantumIdentifier::mspecies
Index mspecies
Definition: quantum.h:688
QuantumIdentifier::SetTransition
void SetTransition()
Set key to transition type.
Definition: quantum.h:509
QuantumNumbers::QuantumContainer
std::array< Rational, Index(QuantumNumberType::FINAL_ENTRY)> QuantumContainer
Definition: quantum.h:225
SpeciesRecord::Isotopologue
const Array< IsotopologueRecord > & Isotopologue() const
Definition: absorption.h:199
q
#define q
Definition: legacy_continua.cc:21712
QuantumIdentifier::UpperQuantumNumber
constexpr Rational UpperQuantumNumber(QuantumNumberType X) const noexcept
Return a upper quantum number by copy.
Definition: quantum.h:597
QuantumNumbers::mqnumbers
QuantumContainer mqnumbers
Definition: quantum.h:362
SpeciesRecord::Name
const String & Name() const
Definition: absorption.h:197
QuantumIdentifier::miso
Index miso
Definition: quantum.h:689
operator>>
std::istream & operator>>(std::istream &is, QuantumNumbers &qn)
Input operator.
Definition: quantum.cc:176
special_interp.h
Header file for special_interp.cc.
ThrowIfQuantumNumberNameInvalid
void ThrowIfQuantumNumberNameInvalid(String name)
Check for valid quantum number name and throws if it is invalid.
Definition: quantum.cc:168
QuantumNumbers::Compare
bool Compare(const QuantumNumbers &qn) const
Compare Quantum Numbers Ignores any undefined numbers in the comparison.
Definition: quantum.cc:33
Index
INDEX Index
The type to use for all integer numbers and indices.
Definition: matpack.h:39
QuantumIdentifier::QuantumMatch
const std::array< QuantumNumbers, 2 > & QuantumMatch() const
Return the quantum numbers array const reference.
Definition: quantum.h:571
QuantumIdentifier::In
bool In(const QuantumIdentifier &other) const
Return if this is in other.
Definition: quantum.cc:117
QuantumNumbers::Set
void Set(Index qn, Rational r)
Set quantum number at position.
Definition: quantum.h:310
Array::nelem
Index nelem() const
Number of elements.
Definition: array.h:195
Rational
Implements rational numbers to work with other ARTS types.
Definition: rational.h:54
QuantumNumberType::J
@ J