ARTS  2.3.1285(git:92a29ea9-dirty)
quantum_parser_hitran.cc
Go to the documentation of this file.
1 /* Copyright (C) 2015, The ARTS Developers.
2 
3  This program is free software; you can redistribute it and/or modify it
4  under the terms of the GNU General Public License as published by the
5  Free Software Foundation; either version 2, or (at your option) any
6  later version.
7 
8  This program is distributed in the hope that it will be useful,
9  but WITHOUT ANY WARRANTY; without even the implied warranty of
10  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11  GNU General Public License for more details.
12 
13  You should have received a copy of the GNU General Public License
14  along with this program; if not, write to the Free Software
15  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
16  USA. */
17 
25 #include "quantum_parser_hitran.h"
26 #include "absorption.h"
27 #include "global_data.h"
28 #include "messages.h"
29 
30 // Parsing functions for fields
31 void parse_space(Rational& qn, String& s, const Index species);
32 void parse_a1_br_hitran(Rational& qn, String& s, const Index species);
33 void parse_a1_pm_hitran(Rational& qn, String& s, const Index species);
34 void parse_a1_sym_hitran(Rational& qn, String& s, const Index species);
35 void parse_a1_s_hitran(Rational& qn, String& s, const Index species);
36 void parse_a1_x_hitran(Rational& qn, String& s, const Index species);
37 void parse_a2_hitran(Rational& qn, String& s, const Index species);
38 void parse_a3_hitran(Rational& qn, String& s, const Index species);
39 void parse_a4_hitran(Rational& qn, String& s, const Index species);
40 void parse_a5_hitran(Rational& qn, String& s, const Index species);
41 void parse_i1_hitran(Rational& qn, String& s, const Index species);
42 void parse_i2_hitran(Rational& qn, String& s, const Index species);
43 void parse_i3_hitran(Rational& qn, String& s, const Index species);
44 void parse_f51_hitran(Rational& qn, String& s, const Index species);
45 
46 // Postprocessing functions for calculation of implicit quantum numbers
52 
55 
56 #define SKIP_X_SPACES(container, nspaces) \
57  container.push_back_n( \
58  QuantumFieldDescription(QuantumNumberType::FINAL_ENTRY, parse_space), \
59  nspaces)
60 
61  // HITRAN Classes
62  mclass.resize(CI_FINAL);
63 
64  // Class 1
65  {
67  SKIP_X_SPACES(this_class, 13);
68  this_class.push_back(
70  }
71 
72  // Class 2
73  {
75  SKIP_X_SPACES(this_class, 7);
76  this_class.push_back(
78  SKIP_X_SPACES(this_class, 5);
79  this_class.push_back(
81  }
82 
83  // Class 3
84  {
86  SKIP_X_SPACES(this_class, 7);
87  this_class.push_back(
89  this_class.push_back(
91  SKIP_X_SPACES(this_class, 2);
92  this_class.push_back(
94  }
95 
96  // Class 4
97  {
99  SKIP_X_SPACES(this_class, 7);
100  this_class.push_back(
102  this_class.push_back(
104  this_class.push_back(
106  this_class.push_back(
108  }
109 
110  // Class 5
111  {
113  SKIP_X_SPACES(this_class, 6);
114  this_class.push_back(
116  this_class.push_back(
118  this_class.push_back(
120  this_class.push_back(
122  this_class.push_back(
124  }
125 
126  // Class 6
127  {
129  SKIP_X_SPACES(this_class, 9);
130  this_class.push_back(
132  this_class.push_back(
134  this_class.push_back(
136  }
137 
138  // Class 7
139  {
141  this_class.push_back(
143  this_class.push_back(
145  this_class.push_back(
147  this_class.push_back(
149  this_class.push_back(
151  this_class.push_back(
153  this_class.push_back(
155  this_class.push_back(
159  }
160 
161  // Class 8
162  {
164  SKIP_X_SPACES(this_class, 5);
165  this_class.push_back(
167  this_class.push_back(
169  this_class.push_back(
171  this_class.push_back(
173  this_class.push_back(
175  }
176 
177  // Class 9
178  {
180  SKIP_X_SPACES(this_class, 3);
181  this_class.push_back(
183  this_class.push_back(
185  this_class.push_back(
187  this_class.push_back(
189  this_class.push_back(
191  this_class.push_back(
193  }
194 
195  // Class 10
196  {
198  SKIP_X_SPACES(this_class, 3);
199  this_class.push_back(
201  this_class.push_back(
203  this_class.push_back(
205  this_class.push_back(
207  this_class.push_back(
209  this_class.push_back(
211  }
212 
213  // HITRAN Groups
214  mgroup.resize(GI_FINAL);
215 
216  // Group 1
217  {
218  Array<QuantumFieldDescription>& this_group = mgroup[GI_GROUP1].upper;
219  this_group.push_back(
221  this_group.push_back(
223  this_group.push_back(
225  this_group.push_back(
227  this_group.push_back(
229  }
230 
231  {
232  Array<QuantumFieldDescription>& this_group = mgroup[GI_GROUP1].lower;
233  this_group.push_back(
235  this_group.push_back(
237  this_group.push_back(
239  this_group.push_back(
241  this_group.push_back(
243  }
244 
245  // Group 2
246  {
247  Array<QuantumFieldDescription>& this_group = mgroup[GI_GROUP2].upper;
248  SKIP_X_SPACES(this_group, 10);
249  this_group.push_back(
251  }
252 
253  {
254  Array<QuantumFieldDescription>& this_group = mgroup[GI_GROUP2].lower;
255  SKIP_X_SPACES(this_group, 5);
256  this_group.push_back(
258  this_group.push_back(
260  this_group.push_back(
262  this_group.push_back(
264  }
265 
266  // Group 3
267  {
268  Array<QuantumFieldDescription>& this_group = mgroup[GI_GROUP3].upper;
269  SKIP_X_SPACES(this_group, 2);
270  this_group.push_back(
272  this_group.push_back(
274  this_group.push_back(
276  this_group.push_back(
278  }
279 
280  {
281  Array<QuantumFieldDescription>& this_group = mgroup[GI_GROUP3].lower;
282  SKIP_X_SPACES(this_group, 2);
283  this_group.push_back(
285  this_group.push_back(
287  this_group.push_back(
289  this_group.push_back(
291  }
292 
293  // Group 4
294  {
295  Array<QuantumFieldDescription>& this_group = mgroup[GI_GROUP4].upper;
296  this_group.push_back(
298  this_group.push_back(
300  this_group.push_back(
302  this_group.push_back(
304  this_group.push_back(
306  this_group.push_back(
308  }
309 
310  {
311  Array<QuantumFieldDescription>& this_group = mgroup[GI_GROUP4].lower;
312  this_group.push_back(
314  this_group.push_back(
316  this_group.push_back(
318  this_group.push_back(
320  this_group.push_back(
322  this_group.push_back(
324  }
325 
326  // Group 5
327  {
328  Array<QuantumFieldDescription>& this_group = mgroup[GI_GROUP5].upper;
329  SKIP_X_SPACES(this_group, 10);
330  this_group.push_back(
332  }
333 
334  {
335  Array<QuantumFieldDescription>& this_group = mgroup[GI_GROUP5].lower;
336  SKIP_X_SPACES(this_group, 1);
337  this_group.push_back(
339  this_group.push_back(
341  this_group.push_back(
343  this_group.push_back(
345  this_group.push_back(
347  this_group.push_back(
349  }
350 
351  // Group 6
352  {
353  Array<QuantumFieldDescription>& this_group = mgroup[GI_GROUP6].upper;
354  SKIP_X_SPACES(this_group, 10);
355  this_group.push_back(
357  }
358 
359  {
360  Array<QuantumFieldDescription>& this_group = mgroup[GI_GROUP6].lower;
361  SKIP_X_SPACES(this_group, 3);
362  this_group.push_back(
364  this_group.push_back(
366  this_group.push_back(
368  this_group.push_back(
370  }
371 
372  // Group 6 (OH)
373  {
375  SKIP_X_SPACES(this_group, 10);
376  this_group.push_back(
378  }
379 
380  {
382  SKIP_X_SPACES(this_group, 1);
383  this_group.push_back(
385  this_group.push_back(
387  this_group.push_back(
389  this_group.push_back(
391  this_group.push_back(
393  }
394 
395  mspecies.resize(species_data.nelem());
396 
406 
407 #undef SKIP_X_SPACES
408 }
409 
411  const String& quantum_string) const {
412  qid.SetTransition();
413 
414  const QuantumClassGroup& qcg = mspecies[qid.Species()];
415  const Index qclass = mspecies[qid.Species()].iclass;
416  const Index qgroup = mspecies[qid.Species()].igroup;
417 
418  if (qcg.iclass == -1 || qcg.igroup == -1) return;
419 
420  String qstr;
421 
422  qstr = quantum_string.substr(0, 15);
423  for (Index i = 0; i < mclass[qclass].nelem(); i++) {
424  mclass[qclass][i].Parse(qid.UpperQuantumNumbers(), qstr, qid.Species());
425  }
426 
427  qstr = quantum_string.substr(15, 15);
428  for (Index i = 0; i < mclass[qclass].nelem(); i++) {
429  mclass[qclass][i].Parse(qid.LowerQuantumNumbers(), qstr, qid.Species());
430  }
431 
432  if (qgroup != GI_UNDEFINED) {
433  qstr = quantum_string.substr(30, 15);
434  for (Index i = 0; i < mgroup[qgroup].upper.nelem(); i++) {
435  mgroup[qgroup].upper[i].Parse(
436  qid.UpperQuantumNumbers(), qstr, qid.Species());
437  }
438  }
439 
440  if (qgroup != GI_UNDEFINED) {
441  qstr = quantum_string.substr(45, 15);
442  for (Index i = 0; i < mgroup[qgroup].lower.nelem(); i++) {
443  mgroup[qgroup].lower[i].Parse(
444  qid.LowerQuantumNumbers(), qstr, qid.Species());
445  }
446  }
447 
448  switch (qgroup) {
449  case GI_GROUP1:
451  break;
452  case GI_GROUP2:
454  break;
455  case GI_GROUP5:
457  break;
458  case GI_GROUP6:
460  break;
461  case GI_GROUP6OH:
463  break;
464  default:
465  break;
466  }
467 }
468 
470  const ClassIds iclass,
471  const GroupIds igroup) {
472  Index species = species_index_from_species_name(species_name);
473  mspecies[species].iclass = iclass;
474  mspecies[species].igroup = igroup;
475 }
476 
480 
481 void parse_space(Rational& qn, String& s, const Index /* species */) {
482  s.erase(0, 1);
483  qn = RATIONAL_UNDEFINED;
484 }
485 
486 void parse_a1_br_hitran(Rational& qn, String& s, const Index /* species */) {
487  qn = Rational('Q' - s[0]);
488  if (abs(qn) > 4) qn = RATIONAL_UNDEFINED;
489  s.erase(0, 1);
490 }
491 
492 void parse_a1_pm_hitran(Rational& qn, String& s, const Index /* species */) {
493  // FIXME: How to handle plus/minus?
494  s.erase(0, 1);
495  qn = RATIONAL_UNDEFINED;
496 }
497 
498 void parse_a1_sym_hitran(Rational& qn, String& s, const Index species) {
499  qn = RATIONAL_UNDEFINED;
500  const char ch = s[0];
501 
502  if ((ch == '+' || ch == '-') &&
503  (species == species_index_from_species_name("HO2") ||
504  species == species_index_from_species_name("NO2"))) {
505  if (ch == '+')
506  qn = Rational(1, 2);
507  else if (ch == '-')
508  qn = Rational(-1, 2);
509  else
510  throw std::runtime_error("Error parsing quantum number Sym");
511  } else if ((ch == 'd' || ch == 'q') &&
512  (species == species_index_from_species_name("O2") ||
513  species == species_index_from_species_name("N2"))) {
514  // FIXME: How to deal with symmetry parameter?
515  } else if (ch == 'g' && species == species_index_from_species_name("O2")) {
516  // FIXME: What does 'g' mean? Docs only talk about d and q for O2
517  } else if (ch == 'e' || ch == 'f') {
518  // FIXME: How to handle linedoubling values?
519  } else if (ch == '+' || ch == '-') {
520  // FIXME: How to handle symmetry parameter?
521  } else if (ch != ' ')
522  throw std::runtime_error("Error parsing quantum number Sym");
523 
524  s.erase(0, 1);
525 }
526 
527 void parse_a1_s_hitran(Rational& qn, String& s, const Index /* species */) {
528  // FIXME: How to handle S?
529  s.erase(0, 1);
530  qn = RATIONAL_UNDEFINED;
531 }
532 
533 void parse_a1_x_hitran(Rational& qn, String& s, const Index species) {
534  const char ch = s[0];
535 
536  if (species == species_index_from_species_name("O2")) {
537  if (ch == 'X')
539  else if (ch == 'a')
541  else if (ch == 'b')
543  else
544  throw std::runtime_error("Unidentified X for O2 in HITRAN parsing...");
545  } else if (species == species_index_from_species_name("NO")) {
546  if (ch == 'X')
548  else
549  throw std::runtime_error("Unidentified X for NO in HITRAN parsing...");
550 
551  } else if (species == species_index_from_species_name("OH")) {
552  if (ch == 'X')
554  else if (ch == 'A')
556  else
557  throw std::runtime_error("Unidentified X for OH in HITRAN parsing...");
558 
559  } else if (species == species_index_from_species_name("ClO")) {
560  if (ch == 'X')
562  else
563  throw std::runtime_error("Unidentified X for ClO in HITRAN parsing...");
564 
565  } else
566  qn = RATIONAL_UNDEFINED;
567 
568  s.erase(0, 1);
569 }
570 
571 void parse_a2_hitran(Rational& qn, String& s, const Index /* species */) {
572  // FIXME OLE
573  s.erase(0, 2);
574  qn = RATIONAL_UNDEFINED;
575 }
576 
577 void parse_a3_hitran(Rational& qn, String& s, const Index /* species */) {
578  extract(qn, s, 3);
579 }
580 
581 void parse_a4_hitran(Rational& qn, String& s, const Index /* species */) {
582  // FIXME OLE
583  s.erase(0, 4);
584  qn = RATIONAL_UNDEFINED;
585 }
586 
587 void parse_a5_hitran(Rational& qn, String& s, const Index /* species */) {
588  String qnf = s.substr(0, 5);
589  qn = RATIONAL_UNDEFINED;
590 
591  qnf.trim();
592  if (qnf.nelem()) {
593  ArrayOfString as;
594  qnf.split(as, ".");
595  if (as.nelem() == 2) {
596  Index nom;
597  char* endptr;
598 
599  nom = strtol(as[0].c_str(), &endptr, 10);
600  if (endptr != as[0].c_str() + as[0].nelem()) {
601  throw std::runtime_error("Error parsing quantum number of type A5");
602  }
603 
604  if (as[1] == "5")
605  qn = Rational(nom * 2 + 1, 2);
606  else if (as[1] == "0")
607  qn = Rational(nom);
608  else {
609  throw std::runtime_error("Error parsing quantum number of type A5");
610  }
611  }
612  }
613  s.erase(0, 5);
614 }
615 
616 void parse_i1_hitran(Rational& qn, String& s, const Index /* species */) {
617  Index i;
618  extract(i, s, 1);
619  qn = Rational(i);
620 }
621 
622 void parse_i2_hitran(Rational& qn, String& s, const Index /* species */) {
623  Index i;
624  extract(i, s, 2);
625  qn = Rational(i);
626 }
627 
628 void parse_i3_hitran(Rational& qn, String& s, const Index /* species */) {
629  Index i;
630  extract(i, s, 3);
631  qn = Rational(i);
632 }
633 
634 void parse_f51_hitran(Rational& qn, String& s, const Index /* species */) {
635  String qnf = s.substr(0, 5);
636  qn = RATIONAL_UNDEFINED;
637 
638  qnf.trim();
639  if (qnf.nelem()) {
640  ArrayOfString as;
641  qnf.split(as, ".");
642  if (as.nelem() == 2) {
643  Index nom;
644  char* endptr;
645 
646  nom = strtol(as[0].c_str(), &endptr, 10);
647  if (endptr != as[0].c_str() + as[0].nelem()) {
648  throw std::runtime_error("Error parsing quantum number of type F5.1");
649  }
650 
651  if (as[1] == "5")
652  qn = Rational(nom * 2 + 1, 2);
653  else if (as[1] == "0")
654  qn = Rational(nom);
655  else {
656  throw std::runtime_error("Error parsing quantum number of type F5.1");
657  }
658  s.erase(0, 5);
659  } else {
660  bool valid_num = true;
661  for (Index i = 0; valid_num && i < qnf.nelem(); i++)
662  if (qnf[i] < '0' || qnf[i] > '9') valid_num = false;
663  if (!valid_num)
664  throw std::runtime_error("Error parsing quantum number of type F5.1");
665 
666  Index q;
667  extract(q, s, qnf.nelem());
668  }
669  }
670 }
671 
675 
677  if (qid.Species() == species_index_from_species_name("HO2") ||
678  qid.Species() == species_index_from_species_name("NO2")) {
679  // For these species, N is stored in field J, so we copy it here
680  // to the correct quantum number
685  // Now we can calculate the correct J by using the Symmetry quantum
686  // number. However, it does not represent Symmetry for these
687  // species, but +1/2 or -1/2
688  qid.UpperQuantumNumbers().Set(
692  qid.LowerQuantumNumbers().Set(
696 
697  // We don't need Sym after this point
700  }
701 }
702 
704  qid.UpperQuantumNumbers().Set(
708 
709  // We don't need dN and dJ after this point
711 }
712 
714  qid.UpperQuantumNumbers().Set(
718  qid.UpperQuantumNumbers().Set(
722 
723  assert(qid.Species() == species_index_from_species_name("O2"));
724 
740  }
741 
757  }
758 
759  // We don't need these after this point
764 }
765 
767  qid.UpperQuantumNumbers().Set(
771 
772  if (qid.Species() == species_index_from_species_name("NO")) {
779  } else
780  throw std::runtime_error(
781  "Missing definition of NO... this is a developer bug because it should fail earlier...");
782 
789  } else
790  throw std::runtime_error(
791  "Missing definition of NO... this is a developer bug because it should fail earlier...");
792  } else if (qid.Species() == species_index_from_species_name("ClO")) {
799  } else
800  throw std::runtime_error(
801  "Missing definition of ClO... this is a developer bug because it should fail earlier...");
802 
809  } else
810  throw std::runtime_error(
811  "Missing definition of ClO... this is a developer bug because it should fail earlier...");
812  } else
813  throw std::runtime_error(
814  "Unknown species accessing postprocessing of Hitran data... this is a developer bug");
815 
816  // We don't need these after this point
820 }
821 
823  assert(qid.Species() == species_index_from_species_name("OH"));
824 
825  qid.UpperQuantumNumbers().Set(
829 
840  qid.LowerQuantumNumbers().Set(
844  else if (qid.LowerQuantumNumber(QuantumNumberType::Omega) == 2)
845  qid.LowerQuantumNumbers().Set(
849  else
850  throw std::runtime_error("Cannot understand value for OH");
851  } else
852  throw std::runtime_error(
853  "Missing definition of OH... this is a developer bug because it should fail earlier...");
854 
865  qid.UpperQuantumNumbers().Set(
869  else if (qid.UpperQuantumNumber(QuantumNumberType::Omega) == 2)
870  qid.UpperQuantumNumbers().Set(
874  else
875  throw std::runtime_error("Cannot understand value for OH");
876 
879  } else
880  throw std::runtime_error(
881  "Missing definition of OH... this is a developer bug because it should fail earlier...");
882 
883  // We don't need these after this point
888 }
INDEX Index
The type to use for all integer numbers and indices.
Definition: matpack.h:39
#define RATIONAL_UNDEFINED
Definition: rational.h:361
const QuantumNumbers & UpperQuantumNumbers() const noexcept
Return the upper quantum numbers by const reference.
Definition: quantum.h:587
Array< QuantumClassGroup > mspecies
void postprocess_group2_hitran(QuantumIdentifier &qnr)
Index nelem() const
Number of elements.
Definition: array.h:195
#define SKIP_X_SPACES(container, nspaces)
Declarations having to do with the four output streams.
void parse_a2_hitran(Rational &qn, String &s, const Index species)
#define abs(x)
void parse_i2_hitran(Rational &qn, String &s, const Index species)
void postprocess_group5_hitran(QuantumIdentifier &qnr)
void postprocess_group6_hitran(QuantumIdentifier &qnr)
void parse_a1_pm_hitran(Rational &qn, String &s, const Index species)
void parse_a1_x_hitran(Rational &qn, String &s, const Index species)
void parse_a1_s_hitran(Rational &qn, String &s, const Index species)
const Array< SpeciesRecord > species_data
Species Data.
void parse_i3_hitran(Rational &qn, String &s, const Index species)
Parser for quantum numbers from HITRAN 2004 and later.
void parse_f51_hitran(Rational &qn, String &s, const Index species)
Array< QuantumClass > mclass
Array< QuantumGroup > mgroup
void parse_a1_sym_hitran(Rational &qn, String &s, const Index species)
void Species(Index sp)
Set the Species.
Definition: quantum.h:481
Implements rational numbers to work with other ARTS types.
Definition: rational.h:54
constexpr Index toIndex(int n=1) const
Converts the value to index by n-scaled division.
Definition: rational.h:136
void SetClassGroup(const String &species_name, const ClassIds iclass, const GroupIds igroup)
void extract(T &x, String &line, Index n)
Extract something from the beginning of a string.
Definition: mystring.h:297
void SetTransition(const QuantumNumbers &upper, const QuantumNumbers &lower)
Set to transition type identifier.
Definition: quantum.cc:229
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
void postprocess_group6oh_hitran(QuantumIdentifier &qnr)
void parse_a3_hitran(Rational &qn, String &s, const Index species)
Index nelem() const
Number of elements.
Definition: mystring.h:246
Declarations required for the calculation of absorption coefficients.
void parse_a5_hitran(Rational &qn, String &s, const Index species)
Index species_index_from_species_name(String name)
Return species index for given species name.
Definition: absorption.cc:531
void trim()
Trim leading and trailing whitespace.
Definition: mystring.h:225
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
void postprocess_group1_hitran(QuantumIdentifier &qnr)
Post-processing functions.
void split(Array< my_basic_string< charT > > &aos, const my_basic_string< charT > &delim) const
Split string into substrings.
Definition: mystring.h:206
void parse_a1_br_hitran(Rational &qn, String &s, const Index species)
const QuantumNumbers & LowerQuantumNumbers() const noexcept
Return the lower quantum numbers by const reference.
Definition: quantum.h:592
void parse_space(Rational &qn, String &s, const Index species)
Parsing functions.
void Parse(QuantumIdentifier &qid, const String &quantum_string) const
Parse quantum numbers from string.
Index nelem(const Lines &l)
Number of lines.
#define q
void parse_i1_hitran(Rational &qn, String &s, const Index species)
void parse_a4_hitran(Rational &qn, String &s, const Index species)
QuantumParserHITRAN2004()
Constructor initializing the parser.
Class mapping quantum numbers to parsing functions.