ARTS  2.3.1285(git:92a29ea9-dirty)
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 
59  if (mqtype == QuantumIdentifier::NONE or
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 
90  if (mqtype == QuantumIdentifier::NONE or
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 
121  if (mqtype == QuantumIdentifier::NONE or
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");
129  else if (mqtype == QuantumIdentifier::TRANSITION) {
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;
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 
226  return species_name_from_species_index(mspecies);
227 }
228 
230  const QuantumNumbers& lower) {
232  mqm[TRANSITION_UPPER_INDEX] = upper;
233  mqm[TRANSITION_LOWER_INDEX] = lower;
234 }
235 
238  mqm[ENERGY_LEVEL_INDEX] = q;
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") {
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;
300  QuantumMatch()[QuantumIdentifier::TRANSITION_UPPER_INDEX].Set(token, r);
301  is >> token;
302  if (token == "LO") break;
303  }
304 
305  if (!is) {
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;
314  QuantumMatch()[QuantumIdentifier::TRANSITION_LOWER_INDEX].Set(token, r);
315  is >> token;
316  }
317  } else if (token == "EN") {
319 
320  is >> token;
321  Rational r;
322  while (is) {
324  is >> r;
325  QuantumMatch()[QuantumIdentifier::TRANSITION_UPPER_INDEX].Set(token, r);
326  is >> token;
327  }
328  } else if (token == "ALL") {
329  mqtype = QuantumIdentifier::ALL;
330  } else if (token == "NONE") {
331  mqtype = QuantumIdentifier::NONE;
332  } else {
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 
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) {
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 {
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) {
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 {
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 }
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.
INDEX Index
The type to use for all integer numbers and indices.
Definition: matpack.h:39
#define RATIONAL_UNDEFINED
Definition: rational.h:361
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
bool Compare(const QuantumNumbers &qn) const
Compare Quantum Numbers Ignores any undefined numbers in the comparison.
Definition: quantum.cc:33
bool any_quantumnumbers() const
Check if there are any quantum numbers defined.
Definition: quantum.cc:392
Index nelem() const
Number of elements.
Definition: array.h:195
void Isotopologue(Index iso)
Set the Isotopologue.
Definition: quantum.h:487
QuantumIdentifier::QType Index LowerQuantumNumbers Species
bool InLower(const QuantumIdentifier &other) const
Return if this is in other&#39;s lower energy state.
Definition: quantum.cc:86
std::istream & operator>>(std::istream &is, QuantumNumbers &qn)
Input operator.
Definition: quantum.cc:176
String TypeStr() const
Definition: quantum.cc:203
QuantumNumberType string2quantumnumbertype(const String &s)
Definition: quantum.h:101
bool InUpper(const QuantumIdentifier &other) const
Return if this is in other&#39;s upper energy state.
Definition: quantum.cc:55
void SetEnergyLevel(const QuantumNumbers &q)
Set tp energy level identifier.
Definition: quantum.cc:236
static constexpr Index TRANSITION_LOWER_INDEX
Lower level index.
Definition: quantum.h:472
void SetFromString(String str)
Set from a String object.
Definition: quantum.cc:241
basic_istringstream< char, string_char_traits< char >, alloc > istringstream
Definition: sstream.h:203
QuantumNumberType
Enum for Quantum Numbers used for indexing.
Definition: quantum.h:48
const Array< SpeciesRecord > species_data
Species Data.
String quantumnumbertype2string(QuantumNumberType s)
Definition: quantum.h:162
String species_name_from_species_index(const Index spec_ind)
Return species name for given species index.
Definition: absorption.cc:569
String SpeciesName() const
Return the Species by name.
Definition: quantum.cc:225
const Array< IsotopologueRecord > & Isotopologue() const
Definition: absorption.h:199
void ThrowIfQuantumNumberNameInvalid(String name)
Check for valid quantum number name and throws if it is invalid.
Definition: quantum.cc:168
std::array< QuantumNumbers, 2 > mqm
Definition: quantum.h:690
std::array< Rational, Index(QuantumNumberType::FINAL_ENTRY)> QuantumContainer
Definition: quantum.h:225
_CS_string_type str() const
Definition: sstream.h:491
static constexpr Index TRANSITION_UPPER_INDEX
Upper level index.
Definition: quantum.h:469
void Species(Index sp)
Set the Species.
Definition: quantum.h:481
static constexpr Index ENERGY_LEVEL_INDEX
Energy level index.
Definition: quantum.h:475
QuantumContainer mqnumbers
Definition: quantum.h:362
Implements rational numbers to work with other ARTS types.
Definition: rational.h:54
Contains the lookup data for one species.
Definition: absorption.h:144
void SetFromStringForCO2Band(String upper, String lower, String iso)
Set CO2 transition from String objects.
Definition: quantum.cc:341
QuantumIdentifier::QType Isotopologue
Rational interpret_stringdata(const QuantumNumberType key, const String &val)
Definition: quantum.cc:414
std::ostream & operator<<(std::ostream &os, const QuantumNumbers &qn)
Output operator.
Definition: quantum.cc:187
constexpr Rational LowerQuantumNumber(QuantumNumberType X) const noexcept
Return a lower quantum number by copy.
Definition: quantum.h:602
Class to identify and match lines by their quantum numbers.
Definition: quantum.h:390
Index nelem() const
Number of elements.
Definition: mystring.h:246
const String & Name() const
Definition: absorption.h:197
Declarations required for the calculation of absorption coefficients.
Header file for special_interp.cc.
void Set(Index qn, Rational r)
Set quantum number at position.
Definition: quantum.h:310
constexpr Rational UpperQuantumNumber(QuantumNumberType X) const noexcept
Return a upper quantum number by copy.
Definition: quantum.h:597
basic_ostringstream< char, string_char_traits< char >, alloc > ostringstream
Definition: sstream.h:204
Container class for Quantum Numbers.
Definition: quantum.h:222
constexpr QType Type() const
Definition: quantum.h:526
void SetTransition()
Set key to transition type.
Definition: quantum.h:509
const QuantumContainer & GetNumbers() const
Get the numbers.
Definition: quantum.h:338
bool IsValidQuantumNumberName(String name)
Check for valid quantum number name.
Definition: quantum.cc:164
const std::array< QuantumNumbers, 2 > & QuantumMatch() const
Return the quantum numbers array const reference.
Definition: quantum.h:571
#define q
bool In(const QuantumIdentifier &other) const
Return if this is in other.
Definition: quantum.cc:117