ARTS  2.0.49
absorption.cc
Go to the documentation of this file.
1 /* Copyright (C) 2000-2008
2  Stefan Buehler <sbuehler@ltu.se>
3  Axel von Engeln <engeln@uni-bremen.de>
4 
5  This program is free software; you can redistribute it and/or modify it
6  under the terms of the GNU General Public License as published by the
7  Free Software Foundation; either version 2, or (at your option) any
8  later version.
9 
10  This program is distributed in the hope that it will be useful,
11  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  GNU General Public License for more details.
14 
15  You should have received a copy of the GNU General Public License
16  along with this program; if not, write to the Free Software
17  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
18  USA. */
19 
33 #include "arts.h"
34 #include <map>
35 #include <cfloat>
36 #include <algorithm>
37 #include <cmath>
38 #include "absorption.h"
39 #include "math_funcs.h"
40 #include "messages.h"
41 #include "logic.h"
42 
43 
45 std::map<String, Index> SpeciesMap;
46 
47 
48 // member fct of isotoperecord, calculates the partition fct at the
49 // given temperature from the partition fct coefficients (3rd order
50 // polynomial in temperature)
52  temperature ) const
53 {
54  Numeric result = 0.;
55  Numeric exponent = 1.;
56 
57  ArrayOfNumeric::const_iterator it;
58 
59  for (it=mqcoeff.begin(); it != mqcoeff.end(); it++)
60  {
61  result += *it * exponent;
62  exponent *= temperature;
63  }
64  return result;
65 }
66 
71 {
73 
74  for ( Index i=0 ; i<species_data.nelem() ; ++i)
75  {
76  SpeciesMap[species_data[i].Name()] = i;
77  }
78 }
79 
80 ostream& operator<< (ostream& os, const LineRecord& lr)
81 {
82  // Determine the precision, depending on whether Numeric is double
83  // or float:
84  int precision;
85 #ifdef USE_FLOAT
86  precision = FLT_DIG;
87 #else
88 #ifdef USE_DOUBLE
89  precision = DBL_DIG;
90 #else
91 #error Numeric must be double or float
92 #endif
93 #endif
94 
95  switch (lr.Version()) {
96  case 3:
97  os << "@"
98  << " " << lr.Name ()
99  << " "
100  << setprecision(precision)
101  << lr.F ()
102  << " " << lr.Psf ()
103  << " " << lr.I0 ()
104  << " " << lr.Ti0 ()
105  << " " << lr.Elow ()
106  << " " << lr.Agam ()
107  << " " << lr.Sgam ()
108  << " " << lr.Nair ()
109  << " " << lr.Nself ()
110  << " " << lr.Tgam ()
111  << " " << lr.Naux ()
112  << " " << lr.dF ()
113  << " " << lr.dI0 ()
114  << " " << lr.dAgam ()
115  << " " << lr.dSgam ()
116  << " " << lr.dNair ()
117  << " " << lr.dNself()
118  << " " << lr.dPsf ();
119 
120  // Added new lines for the spectroscopic parameters accuracies.
121  for ( Index i=0; i<lr.Naux(); ++i )
122  os << " " << lr.Aux()[i];
123 
124  break;
125 
126  case 4:
127  os << "@"
128  << " " << lr.Name ()
129  << " "
130  << setprecision(precision)
131  << lr.F()
132  << " " << lr.I0()
133  << " " << lr.Ti0()
134  << " " << lr.Elow()
135  << " " << lr.A()
136  << " " << lr.G_upper()
137  << " " << lr.G_lower()
138  << " " << lr.Gamma_self()
139  << " " << lr.Gamma_N2()
140  << " " << lr.Gamma_O2()
141  << " " << lr.Gamma_H2O()
142  << " " << lr.Gamma_CO2()
143  << " " << lr.Gamma_H2()
144  << " " << lr.Gamma_He()
145  << " " << lr.Gam_N_self()
146  << " " << lr.Gam_N_N2()
147  << " " << lr.Gam_N_O2()
148  << " " << lr.Gam_N_H2O()
149  << " " << lr.Gam_N_CO2()
150  << " " << lr.Gam_N_H2()
151  << " " << lr.Gam_N_He()
152  << " " << lr.Delta_N2()
153  << " " << lr.Delta_O2()
154  << " " << lr.Delta_H2O()
155  << " " << lr.Delta_CO2()
156  << " " << lr.Delta_H2()
157  << " " << lr.Delta_He();
158 
159  break;
160 
161  default:
162  os << "Unknown ARTSCAT version: " << lr.Version();
163  break;
164  }
165 
166  return os;
167 }
168 
169 
178 template<class T>
179 void extract(T& x,
180  String& line,
181  Index n)
182 {
183  // Initialize output to zero! This is important, because otherwise
184  // the output variable could `remember' old values.
185  x = T(0);
186 
187  // This will contain the short subString with the item to extract.
188  // Make it a String stream, for easy parsing,
189  // extracting subString of width n from line:
190  istringstream item( line.substr(0,n) );
191 
192 // cout << "line = '" << line << "'\n";
193 // cout << "line.substr(0,n) = " << line.substr(0,n) << endl;
194 // cout << "item = " << item.str() << endl;
195 
196  // Shorten line by n:
197  line.erase(0,n);
198 // cout << "line = " << line << endl;
199 
200  // Convert with the aid of String stream item:
201  item >> x;
202 }
203 
208  // The species lookup data:
209  extern const Array<SpeciesRecord> species_data;
210  const SpeciesRecord& sr = species_data[mspecies];
211  return sr.Name() + "-" + sr.Isotope()[misotope].Name();
212 }
213 
214 
225  // The species lookup data:
226  extern const Array<SpeciesRecord> species_data;
227  return species_data[mspecies];
228 }
229 
230 
243  // The species lookup data:
244  extern const Array<SpeciesRecord> species_data;
245  return species_data[mspecies].Isotope()[misotope];
246 }
247 
248 
249 // This function reads line data in the Hitran 1986-2001 format. For the Hitran
250 // 2004 data format use ReadFromHitran2004Stream.
251 //
252 // 2005/03/29: A check for the right data record length (100 characters) has
253 // been added by Hermann Berg (h.berg@utoronto.ca)
254 //
255 bool LineRecord::ReadFromHitranStream(istream& is, const Verbosity& verbosity)
256 {
258 
259  // Global species lookup data:
260  extern const Array<SpeciesRecord> species_data;
261 
262  // This value is used to flag missing data both in species and
263  // isotope lists. Could be any number, it just has to be made sure
264  // that it is neither the index of a species nor of an isotope.
265  const Index missing = species_data.nelem() + 100;
266 
267  // We need a species index sorted by HITRAN tag. Keep this in a
268  // static variable, so that we have to do this only once. The ARTS
269  // species index is hind[<HITRAN tag>].
270  //
271  // Allow for up to 100 species in HITRAN in the future.
272  static Array< Index > hspec(100);
273 
274  // This is an array of arrays for each hitran tag. It contains the
275  // ARTS indices of the HITRAN isotopes.
276  static Array< ArrayOfIndex > hiso(100);
277 
278  // Remeber if this stuff has already been initialized:
279  static bool hinit = false;
280 
281  // Remember, about which missing species we have already issued a
282  // warning:
283  static ArrayOfIndex warned_missing;
284 
285  if ( !hinit )
286  {
287  // Initialize hspec.
288  // The value of missing means that we don't have this species.
289  hspec = missing; // Matpack can set all elements like this.
290 
291  for ( Index i=0; i<species_data.nelem(); ++i )
292  {
293  const SpeciesRecord& sr = species_data[i];
294 
295  // We have to be careful and check for the case that all
296  // HITRAN isotope tags are -1 (this species is missing in HITRAN).
297 
298  if ( 0 < sr.Isotope()[0].HitranTag() )
299  {
300  // The HITRAN tags are stored as species plus isotope tags
301  // (MO and ISO)
302  // in the Isotope() part of the species record.
303  // We can extract the MO part from any of the isotope tags,
304  // so we use the first one. We do this by taking an integer
305  // division by 10.
306 
307  Index mo = sr.Isotope()[0].HitranTag() / 10;
308  // cout << "mo = " << mo << endl;
309  hspec[mo] = i;
310 
311  // Get a nicer to handle array of HITRAN iso tags:
312  Index n_iso = sr.Isotope().nelem();
313  ArrayOfIndex iso_tags;
314  iso_tags.resize(n_iso);
315  for ( Index j=0; j<n_iso; ++j )
316  {
317  iso_tags[j] = sr.Isotope()[j].HitranTag();
318  }
319 
320  // Reserve elements for the isotope tags. How much do we
321  // need? This depends on the largest HITRAN tag that we know
322  // about!
323  // Also initialize the tags to missing.
324  // cout << "iso_tags = " << iso_tags << endl;
325  // cout << "static_cast<Index>(max(iso_tags))%10 + 1 = "
326  // << static_cast<Index>(max(iso_tags))%10 + 1 << endl;
327  hiso[mo].resize( max(iso_tags)%10 + 1 );
328  hiso[mo] = missing; // Matpack can set all elements like this.
329 
330 
331  // Set the isotope tags:
332  for ( Index j=0; j<n_iso; ++j )
333  {
334  if ( 0 < iso_tags[j] ) // ignore -1 elements
335  {
336  // To get the iso tags from HitranTag() we also have to take
337  // modulo 10 to get rid of mo.
338  hiso[mo][iso_tags[j] % 10] = j;
339  }
340  }
341  }
342  }
343 
344 
345  // Print the generated data structures (for debugging):
346  out3 << " HITRAN index table:\n";
347  for ( Index i=0; i<hspec.nelem(); ++i )
348  {
349  if ( missing != hspec[i] )
350  {
351  // The explicit conversion of Name to a c-String is
352  // necessary, because setw does not work correctly for
353  // stl Strings.
354  out3 << " mo = " << i << " Species = "
355  << setw(10) << setiosflags(ios::left)
356  << species_data[hspec[i]].Name().c_str()
357  << "iso = ";
358  for ( Index j=1; j<hiso[i].nelem(); ++j )
359  {
360  if ( missing==hiso[i][j] )
361  out3 << " " << "m";
362  else
363  out3 << " " << species_data[hspec[i]].Isotope()[hiso[i][j]].Name();
364  }
365  out3 << "\n";
366  }
367  }
368 
369  hinit = true;
370  }
371 
372 
373  // This contains the rest of the line to parse. At the beginning the
374  // entire line. Line gets shorter and shorter as we continue to
375  // extract stuff from the beginning.
376  String line;
377 
378  // The first item is the molecule number:
379  Index mo;
380 
381  // Look for more comments?
382  bool comment = true;
383 
384  while (comment)
385  {
386  // Return true if eof is reached:
387  if (is.eof()) return true;
388 
389  // Throw runtime_error if stream is bad:
390  if (!is) throw runtime_error ("Stream bad.");
391 
392  // Read line from file into linebuffer:
393  getline(is,line);
394 
395  // It is possible that we were exactly at the end of the file before
396  // calling getline. In that case the previous eof() was still false
397  // because eof() evaluates only to true if one tries to read after the
398  // end of the file. The following check catches this.
399  if (line.nelem() == 0 && is.eof()) return true;
400 
401  // If the catalogue is in dos encoding, throw away the
402  // additional carriage return
403  if (line[line.nelem () - 1] == 13)
404  {
405  line.erase (line.nelem () - 1, 1);
406  }
407 
408  // Because of the fixed FORTRAN format, we need to break up the line
409  // explicitly in apropriate pieces. Not elegant, but works!
410 
411  // Extract molecule number:
412  mo = 0;
413  // Initialization of mo is important, because mo stays the same
414  // if line is empty.
415  extract(mo,line,2);
416  // cout << "mo = " << mo << endl;
417 
418  // If mo == 0 this is just a comment line:
419  if ( 0 != mo )
420  {
421  // See if we know this species. Exit with an error if the species is unknown.
422  if ( missing != hspec[mo] )
423  {
424  comment = false;
425 
426  // Check if data record has the right number of characters for the
427  // in Hitran 1986-2001 format
428  Index nChar = line.nelem() + 2; // number of characters in data record;
429  if ( nChar != 100 )
430  {
431  ostringstream os;
432  os << "Invalid HITRAN 1986-2001 line data record with " << nChar <<
433  " characters (expected: 100)." << endl << line << " n: " << line.nelem ();
434  throw runtime_error(os.str());
435  }
436 
437  }
438  else
439  {
440  // See if this is already in warned_missing, use
441  // std::count for that:
442  if ( 0 == std::count(warned_missing.begin(),
443  warned_missing.end(),
444  mo) )
445  {
447  out0 << "Error: HITRAN mo = " << mo << " is not "
448  << "known to ARTS.\n";
449  warned_missing.push_back(mo);
450  arts_exit();
451  // SAB 08.08.2000 If you want to make the program
452  // continue anyway, just comment out the exit
453  // line.
454  }
455  }
456  }
457  }
458 
459  // Ok, we seem to have a valid species here.
460 
461  // Set mspecies from my cool index table:
462  mspecies = hspec[mo];
463 
464  // Extract isotope:
465  Index iso;
466  extract(iso,line,1);
467  // cout << "iso = " << iso << endl;
468 
469 
470  // Set misotope from the other cool index table.
471  // We have to be careful to issue an error for unknown iso tags. Iso
472  // could be either larger than the size of hiso[mo], or set
473  // explicitly to missing. Unfortunately we have to test both cases.
474  misotope = missing;
475  if ( iso < hiso[mo].nelem() )
476  if ( missing != hiso[mo][iso] )
477  misotope = hiso[mo][iso];
478 
479  // Issue error message if misotope is still missing:
480  if (missing == misotope)
481  {
482  ostringstream os;
483  os << "Species: " << species_data[mspecies].Name()
484  << ", isotope iso = " << iso
485  << " is unknown.";
486  throw runtime_error(os.str());
487  }
488 
489 
490  // Position.
491  {
492  // HITRAN position in wavenumbers (cm^-1):
493  Numeric v;
494  // External constant from constants.cc:
495  extern const Numeric SPEED_OF_LIGHT;
496  // Conversion from wavenumber to Hz. If you multiply a line
497  // position in wavenumber (cm^-1) by this constant, you get the
498  // frequency in Hz.
499  const Numeric w2Hz = SPEED_OF_LIGHT * 100.;
500 
501  // Extract HITRAN postion:
502  extract(v,line,12);
503 
504  // ARTS position in Hz:
505  mf = v * w2Hz;
506 // cout << "mf = " << mf << endl;
507  }
508 
509  // Intensity.
510  {
511  extern const Numeric SPEED_OF_LIGHT; // in [m/s]
512 
513  // HITRAN intensity is in cm-1/(molec * cm-2) at 296 Kelvin.
514  // It already includes the isotpic ratio.
515  // The first cm-1 is the frequency unit (it cancels with the
516  // 1/frequency unit of the line shape function).
517  //
518  // We need to do the following:
519  // 1. Convert frequency from wavenumber to Hz (factor 1e2 * c).
520  // 2. Convert [molec * cm-2] to [molec * m-2] (factor 1e-4).
521  // 3. Take out the isotopic ratio.
522 
523  const Numeric hi2arts = 1e-2 * SPEED_OF_LIGHT;
524 
525  Numeric s;
526 
527  // Extract HITRAN intensity:
528  extract(s,line,10);
529  // Convert to ARTS units (Hz / (molec * m-2) ), or shorter: Hz*m^2
530  mi0 = s * hi2arts;
531  // Take out isotopic ratio:
532  mi0 /= species_data[mspecies].Isotope()[misotope].Abundance();
533  }
534 
535  // Skip transition probability:
536  {
537  Numeric r;
538  extract(r,line,10);
539  }
540 
541 
542  // Air broadening parameters.
543  {
544  // HITRAN parameter is in cm-1/atm at 296 Kelvin
545  // All parameters are HWHM (I hope this is true!)
546  Numeric gam;
547  // External constant from constants.cc: Converts atm to
548  // Pa. Multiply value in atm by this number to get value in Pa.
549  extern const Numeric ATM2PA;
550  // External constant from constants.cc:
551  extern const Numeric SPEED_OF_LIGHT;
552  // Conversion from wavenumber to Hz. If you multiply a value in
553  // wavenumber (cm^-1) by this constant, you get the value in Hz.
554  const Numeric w2Hz = SPEED_OF_LIGHT * 1e2;
555  // Ok, put together the end-to-end conversion that we need:
556  const Numeric hi2arts = w2Hz / ATM2PA;
557 
558  // Extract HITRAN AGAM value:
559  extract(gam,line,5);
560 
561  // ARTS parameter in Hz/Pa:
562  magam = gam * hi2arts;
563 
564  // Extract HITRAN SGAM value:
565  extract(gam,line,5);
566 
567  // ARTS parameter in Hz/Pa:
568  msgam = gam * hi2arts;
569 
570  // If zero, set to agam:
571  if (0==msgam)
572  msgam = magam;
573 
574  // cout << "agam, sgam = " << magam << ", " << msgam << endl;
575  }
576 
577 
578  // Lower state energy.
579  {
580  // HITRAN parameter is in wavenumbers (cm^-1).
581  // We have to convert this to the ARTS unit Joule.
582 
583  // Extract from Catalogue line
584  extract(melow,line,10);
585 
586  // Convert to Joule:
588  }
589 
590 
591  // Temperature coefficient of broadening parameters.
592  {
593  // This is dimensionless, we can also extract directly.
594  extract(mnair,line,4);
595 
596  // Set self broadening temperature coefficient to the same value:
597  mnself = mnair;
598 // cout << "mnair = " << mnair << endl;
599  }
600 
601 
602  // Pressure shift.
603  {
604  // HITRAN value in cm^-1 / atm. So the conversion goes exactly as
605  // for the broadening parameters.
606  Numeric d;
607  // External constant from constants.cc: Converts atm to
608  // Pa. Multiply value in atm by this number to get value in Pa.
609  extern const Numeric ATM2PA;
610  // External constant from constants.cc:
611  extern const Numeric SPEED_OF_LIGHT;
612  // Conversion from wavenumber to Hz. If you multiply a value in
613  // wavenumber (cm^-1) by this constant, you get the value in Hz.
614  const Numeric w2Hz = SPEED_OF_LIGHT * 1e2;
615  // Ok, put together the end-to-end conversion that we need:
616  const Numeric hi2arts = w2Hz / ATM2PA;
617 
618  // Extract HITRAN value:
619  extract(d,line,8);
620 
621  // ARTS value in Hz/Pa
622  mpsf = d * hi2arts;
623  }
624  // Set the accuracies using the definition of HITRAN
625  // indices. If some are missing, they are set to -1.
626 
627  //Skip upper state global quanta index
628  {
629  Index eu;
630  extract(eu,line,3);
631  }
632 
633  //Skip lower state global quanta index
634  {
635  Index el;
636  extract(el,line,3);
637  }
638 
639  //Skip upper state local quanta
640  {
641  Index eul;
642  extract(eul,line,9);
643  }
644 
645  //Skip lower state local quanta
646  {
647  Index ell;
648  extract(ell,line,9);
649  }
650 
651  // Accuracy index for frequency reference
652  {
653  Index df;
654  // Extract HITRAN value:
655  extract(df,line,1);
656  // Convert it to ARTS units (Hz)
657  convHitranIERF(mdf,df);
658  }
659 
660  // Accuracy index for intensity reference
661  {
662  Index di0;
663  // Extract HITRAN value:
664  extract(di0,line,1);
665  convHitranIERSH(mdi0,di0);
666  }
667 
668  // Accuracy index for halfwidth reference
669  {
670  Index dgam;
671  // Extract HITRAN value:
672  extract(dgam,line,1);
673  //Convert to ARTS units (%)
674  convHitranIERSH(mdagam,dgam);
675  // convHitranIERSH(mdsgam,dgam);
676  // convHitranIERSH(mdnair,dgam);
677  // convHitranIERSH(mdnself,dgam);
678  }
679 
680  // Accuracy for pressure shift
681  // This is missing in HITRAN catalogue and it is set to -1.
682  mdpsf =-1;
683 
684  // These were all the parameters that we can extract from
685  // HITRAN. However, we still have to set the reference temperatures
686  // to the appropriate value:
687 
688  // Reference temperature for Intensity in K.
689  // (This is fix for HITRAN)
690  mti0 = 296.0;
691 
692  // Reference temperature for AGAM and SGAM in K.
693  // (This is also fix for HITRAN)
694  mtgam = 296.0;
695 
696  // That's it!
697  return false;
698 }
699 
700 
701 // This function reads line data in the Hitran 2004 format. For the Hitran
702 // 1986-2004 data format use ReadFromHitranStream().
703 //
704 // 2005/03/29: This function was added based on ReadFromHitranStream(). There
705 // is a check for the right data record length (160 characters).
706 // Hermann Berg (h.berg@utoronto.ca)
707 //
708 bool LineRecord::ReadFromHitran2004Stream(istream& is, const Verbosity& verbosity)
709 {
711 
712  // Global species lookup data:
713  extern const Array<SpeciesRecord> species_data;
714 
715  // This value is used to flag missing data both in species and
716  // isotope lists. Could be any number, it just has to be made sure
717  // that it is neither the index of a species nor of an isotope.
718  const Index missing = species_data.nelem() + 100;
719 
720  // We need a species index sorted by HITRAN tag. Keep this in a
721  // static variable, so that we have to do this only once. The ARTS
722  // species index is hind[<HITRAN tag>].
723  //
724  // Allow for up to 100 species in HITRAN in the future.
725  static Array< Index > hspec(100);
726 
727  // This is an array of arrays for each hitran tag. It contains the
728  // ARTS indices of the HITRAN isotopes.
729  static Array< ArrayOfIndex > hiso(100);
730 
731  // Remeber if this stuff has already been initialized:
732  static bool hinit = false;
733 
734  // Remember, about which missing species we have already issued a
735  // warning:
736  static ArrayOfIndex warned_missing;
737 
738  if ( !hinit )
739  {
740  // Initialize hspec.
741  // The value of missing means that we don't have this species.
742  hspec = missing; // Matpack can set all elements like this.
743 
744  for ( Index i=0; i<species_data.nelem(); ++i )
745  {
746  const SpeciesRecord& sr = species_data[i];
747 
748  // We have to be careful and check for the case that all
749  // HITRAN isotope tags are -1 (this species is missing in HITRAN).
750 
751  if ( 0 < sr.Isotope()[0].HitranTag() )
752  {
753  // The HITRAN tags are stored as species plus isotope tags
754  // (MO and ISO)
755  // in the Isotope() part of the species record.
756  // We can extract the MO part from any of the isotope tags,
757  // so we use the first one. We do this by taking an integer
758  // division by 10.
759 
760  Index mo = sr.Isotope()[0].HitranTag() / 10;
761  // cout << "mo = " << mo << endl;
762  hspec[mo] = i;
763 
764  // Get a nicer to handle array of HITRAN iso tags:
765  Index n_iso = sr.Isotope().nelem();
766  ArrayOfIndex iso_tags;
767  iso_tags.resize(n_iso);
768  for ( Index j=0; j<n_iso; ++j )
769  {
770  iso_tags[j] = sr.Isotope()[j].HitranTag();
771  }
772 
773  // Reserve elements for the isotope tags. How much do we
774  // need? This depends on the largest HITRAN tag that we know
775  // about!
776  // Also initialize the tags to missing.
777  // cout << "iso_tags = " << iso_tags << endl;
778  // cout << "static_cast<Index>(max(iso_tags))%10 + 1 = "
779  // << static_cast<Index>(max(iso_tags))%10 + 1 << endl;
780  hiso[mo].resize( max(iso_tags)%10 + 1 );
781  hiso[mo] = missing; // Matpack can set all elements like this.
782 
783 
784  // Set the isotope tags:
785  for ( Index j=0; j<n_iso; ++j )
786  {
787  if ( 0 < iso_tags[j] ) // ignore -1 elements
788  {
789  // To get the iso tags from HitranTag() we also have to take
790  // modulo 10 to get rid of mo.
791  hiso[mo][iso_tags[j] % 10] = j;
792  }
793  }
794  }
795  }
796 
797 
798  // Print the generated data structures (for debugging):
799  out3 << " HITRAN index table:\n";
800  for ( Index i=0; i<hspec.nelem(); ++i )
801  {
802  if ( missing != hspec[i] )
803  {
804  // The explicit conversion of Name to a c-String is
805  // necessary, because setw does not work correctly for
806  // stl Strings.
807  out3 << " mo = " << i << " Species = "
808  << setw(10) << setiosflags(ios::left)
809  << species_data[hspec[i]].Name().c_str()
810  << "iso = ";
811  for ( Index j=1; j<hiso[i].nelem(); ++j )
812  {
813  if ( missing==hiso[i][j] )
814  out3 << " " << "m";
815  else
816  out3 << " " << species_data[hspec[i]].Isotope()[hiso[i][j]].Name();
817  }
818  out3 << "\n";
819  }
820  }
821 
822  hinit = true;
823  }
824 
825 
826  // This contains the rest of the line to parse. At the beginning the
827  // entire line. Line gets shorter and shorter as we continue to
828  // extract stuff from the beginning.
829  String line;
830 
831  // The first item is the molecule number:
832  Index mo;
833 
834  // Look for more comments?
835  bool comment = true;
836 
837  while (comment)
838  {
839  // Return true if eof is reached:
840  if (is.eof()) return true;
841 
842  // Throw runtime_error if stream is bad:
843  if (!is) throw runtime_error ("Stream bad.");
844 
845  // Read line from file into linebuffer:
846  getline(is,line);
847 
848  // It is possible that we were exactly at the end of the file before
849  // calling getline. In that case the previous eof() was still false
850  // because eof() evaluates only to true if one tries to read after the
851  // end of the file. The following check catches this.
852  if (line.nelem() == 0 && is.eof()) return true;
853 
854  // If the catalogue is in dos encoding, throw away the
855  // additional carriage return
856  if (line[line.nelem () - 1] == 13)
857  {
858  line.erase (line.nelem () - 1, 1);
859  }
860 
861  // Because of the fixed FORTRAN format, we need to break up the line
862  // explicitly in apropriate pieces. Not elegant, but works!
863 
864  // Extract molecule number:
865  mo = 0;
866  // Initialization of mo is important, because mo stays the same
867  // if line is empty.
868  extract(mo,line,2);
869  // cout << "mo = " << mo << endl;
870 
871  // If mo == 0 this is just a comment line:
872  if ( 0 != mo )
873  {
874  // See if we know this species.
875  if ( missing != hspec[mo] )
876  {
877  comment = false;
878 
879  // Check if data record has the right number of characters for the
880  // in Hitran 2004 format
881  Index nChar = line.nelem() + 2; // number of characters in data record;
882  if ( nChar != 160 )
883  {
884  ostringstream os;
885  os << "Invalid HITRAN 2004 line data record with " << nChar <<
886  " characters (expected: 160).";
887  throw runtime_error(os.str());
888  }
889 
890  }
891  else
892  {
893  // See if this is already in warned_missing, use
894  // std::count for that:
895  if ( 0 == std::count(warned_missing.begin(),
896  warned_missing.end(),
897  mo) )
898  {
900  out1 << "Warning: HITRAN molecule number mo = " << mo << " is not "
901  << "known to ARTS.\n";
902  warned_missing.push_back(mo);
903  }
904  }
905  }
906  }
907 
908  // Ok, we seem to have a valid species here.
909 
910  // Set mspecies from my cool index table:
911  mspecies = hspec[mo];
912 
913  // Extract isotope:
914  Index iso;
915  extract(iso,line,1);
916  // cout << "iso = " << iso << endl;
917 
918 
919  // Set misotope from the other cool index table.
920  // We have to be careful to issue an error for unknown iso tags. Iso
921  // could be either larger than the size of hiso[mo], or set
922  // explicitly to missing. Unfortunately we have to test both cases.
923  misotope = missing;
924  if ( iso < hiso[mo].nelem() )
925  if ( missing != hiso[mo][iso] )
926  misotope = hiso[mo][iso];
927 
928  // Issue error message if misotope is still missing:
929  if (missing == misotope)
930  {
931  ostringstream os;
932  os << "Species: " << species_data[mspecies].Name()
933  << ", isotope iso = " << iso
934  << " is unknown.";
935  throw runtime_error(os.str());
936  }
937 
938 
939  // Position.
940  {
941  // HITRAN position in wavenumbers (cm^-1):
942  Numeric v;
943  // External constant from constants.cc:
944  extern const Numeric SPEED_OF_LIGHT;
945  // Conversion from wavenumber to Hz. If you multiply a line
946  // position in wavenumber (cm^-1) by this constant, you get the
947  // frequency in Hz.
948  const Numeric w2Hz = SPEED_OF_LIGHT * 100.;
949 
950  // Extract HITRAN postion:
951  extract(v,line,12);
952 
953  // ARTS position in Hz:
954  mf = v * w2Hz;
955 // cout << "mf = " << mf << endl;
956  }
957 
958  // Intensity.
959  {
960  extern const Numeric SPEED_OF_LIGHT; // in [m/s]
961 
962  // HITRAN intensity is in cm-1/(molec * cm-2) at 296 Kelvin.
963  // It already includes the isotpic ratio.
964  // The first cm-1 is the frequency unit (it cancels with the
965  // 1/frequency unit of the line shape function).
966  //
967  // We need to do the following:
968  // 1. Convert frequency from wavenumber to Hz (factor 1e2 * c).
969  // 2. Convert [molec * cm-2] to [molec * m-2] (factor 1e-4).
970  // 3. Take out the isotopic ratio.
971 
972  const Numeric hi2arts = 1e-2 * SPEED_OF_LIGHT;
973 
974  Numeric s;
975 
976  // Extract HITRAN intensity:
977  extract(s,line,10);
978  // Convert to ARTS units (Hz / (molec * m-2) ), or shorter: Hz*m^2
979  mi0 = s * hi2arts;
980  // Take out isotopic ratio:
981  mi0 /= species_data[mspecies].Isotope()[misotope].Abundance();
982  }
983 
984  // Skip Einstein coefficient
985  {
986  Numeric r;
987  extract(r,line,10);
988  }
989 
990 
991  // Air broadening parameters.
992  {
993  // HITRAN parameter is in cm-1/atm at 296 Kelvin
994  // All parameters are HWHM (I hope this is true!)
995  Numeric gam;
996  // External constant from constants.cc: Converts atm to
997  // Pa. Multiply value in atm by this number to get value in Pa.
998  extern const Numeric ATM2PA;
999  // External constant from constants.cc:
1000  extern const Numeric SPEED_OF_LIGHT;
1001  // Conversion from wavenumber to Hz. If you multiply a value in
1002  // wavenumber (cm^-1) by this constant, you get the value in Hz.
1003  const Numeric w2Hz = SPEED_OF_LIGHT * 1e2;
1004  // Ok, put together the end-to-end conversion that we need:
1005  const Numeric hi2arts = w2Hz / ATM2PA;
1006 
1007  // Extract HITRAN AGAM value:
1008  extract(gam,line,5);
1009 
1010  // ARTS parameter in Hz/Pa:
1011  magam = gam * hi2arts;
1012 
1013  // Extract HITRAN SGAM value:
1014  extract(gam,line,5);
1015 
1016  // ARTS parameter in Hz/Pa:
1017  msgam = gam * hi2arts;
1018 
1019  // If zero, set to agam:
1020  if (0==msgam)
1021  msgam = magam;
1022 
1023  // cout << "agam, sgam = " << magam << ", " << msgam << endl;
1024  }
1025 
1026 
1027  // Lower state energy.
1028  {
1029  // HITRAN parameter is in wavenumbers (cm^-1).
1030  // We have to convert this to the ARTS unit Joule.
1031 
1032  // Extract from Catalogue line
1033  extract(melow,line,10);
1034 
1035  // Convert to Joule:
1037  }
1038 
1039 
1040  // Temperature coefficient of broadening parameters.
1041  {
1042  // This is dimensionless, we can also extract directly.
1043  extract(mnair,line,4);
1044 
1045  // Set self broadening temperature coefficient to the same value:
1046  mnself = mnair;
1047 // cout << "mnair = " << mnair << endl;
1048  }
1049 
1050 
1051  // Pressure shift.
1052  {
1053  // HITRAN value in cm^-1 / atm. So the conversion goes exactly as
1054  // for the broadening parameters.
1055  Numeric d;
1056  // External constant from constants.cc: Converts atm to
1057  // Pa. Multiply value in atm by this number to get value in Pa.
1058  extern const Numeric ATM2PA;
1059  // External constant from constants.cc:
1060  extern const Numeric SPEED_OF_LIGHT;
1061  // Conversion from wavenumber to Hz. If you multiply a value in
1062  // wavenumber (cm^-1) by this constant, you get the value in Hz.
1063  const Numeric w2Hz = SPEED_OF_LIGHT * 1e2;
1064  // Ok, put together the end-to-end conversion that we need:
1065  const Numeric hi2arts = w2Hz / ATM2PA;
1066 
1067  // Extract HITRAN value:
1068  extract(d,line,8);
1069 
1070  // ARTS value in Hz/Pa
1071  mpsf = d * hi2arts;
1072  }
1073  // Set the accuracies using the definition of HITRAN
1074  // indices. If some are missing, they are set to -1.
1075 
1076  //Skip upper state global quanta index
1077  {
1078  Index eu;
1079  extract(eu,line,15);
1080  }
1081 
1082  //Skip lower state global quanta index
1083  {
1084  Index el;
1085  extract(el,line,15);
1086  }
1087 
1088  //Skip upper state local quanta
1089  {
1090  Index eul;
1091  extract(eul,line,15);
1092  }
1093 
1094  //Skip lower state local quanta
1095  {
1096  Index ell;
1097  extract(ell,line,15);
1098  }
1099 
1100  // Accuracy index for frequency
1101  {
1102  Index df;
1103  // Extract HITRAN value:
1104  extract(df,line,1);
1105  // Convert it to ARTS units (Hz)
1106  convHitranIERF(mdf,df);
1107  }
1108 
1109  // Accuracy index for intensity
1110  {
1111  Index di0;
1112  // Extract HITRAN value:
1113  extract(di0,line,1);
1114  //Convert to ARTS units (%)
1115  convHitranIERSH(mdi0,di0);
1116  }
1117 
1118  // Accuracy index for air-broadened halfwidth
1119  {
1120  Index dagam;
1121  // Extract HITRAN value:
1122  extract(dagam,line,1);
1123  //Convert to ARTS units (%)
1124  convHitranIERSH(mdagam,dagam);
1125  }
1126 
1127  // Accuracy index for self-broadened half-width
1128  {
1129  Index dsgam;
1130  // Extract HITRAN value:
1131  extract(dsgam,line,1);
1132  //Convert to ARTS units (%)
1133  convHitranIERSH(mdsgam,dsgam);
1134  }
1135 
1136  // Accuracy index for temperature-dependence exponent for agam
1137  {
1138  Index dnair;
1139  // Extract HITRAN value:
1140  extract(dnair,line,1);
1141  //Convert to ARTS units (%)
1142  convHitranIERSH(mdnair,dnair);
1143  }
1144 
1145  // Accuracy index for temperature-dependence exponent for sgam
1146  // This is missing in HITRAN catalogue and is set to -1.
1147  mdnself =-1;
1148 
1149  // Accuracy index for pressure shift
1150  {
1151  Index dpsf;
1152  // Extract HITRAN value (given in cm-1):
1153  extract(dpsf,line,1);
1154  // Convert it to ARTS units (Hz)
1155  convHitranIERF(mdpsf,dpsf);
1156  // ARTS wants this error in %
1157  mdpsf = mdpsf / mf;
1158  }
1159 
1160  // These were all the parameters that we can extract from
1161  // HITRAN 2004. However, we still have to set the reference temperatures
1162  // to the appropriate value:
1163 
1164  // Reference temperature for Intensity in K.
1165  // (This is fix for HITRAN 2004)
1166  mti0 = 296.0;
1167 
1168  // Reference temperature for AGAM and SGAM in K.
1169  // (This is also fix for HITRAN 2004)
1170  mtgam = 296.0;
1171 
1172  // That's it!
1173  return false;
1174 }
1175 
1176 
1177 bool LineRecord::ReadFromMytran2Stream(istream& is, const Verbosity& verbosity)
1178 {
1179  CREATE_OUT3
1180 
1181  // Global species lookup data:
1182  extern const Array<SpeciesRecord> species_data;
1183 
1184  // This value is used to flag missing data both in species and
1185  // isotope lists. Could be any number, it just has to be made sure
1186  // that it is neither the index of a species nor of an isotope.
1187  const Index missing = species_data.nelem() + 100;
1188 
1189  // We need a species index sorted by MYTRAN tag. Keep this in a
1190  // static variable, so that we have to do this only once. The ARTS
1191  // species index is hind[<MYTRAN tag>]. The value of
1192  // missing means that we don't have this species.
1193  //
1194  // Allow for up to 100 species in MYTRAN in the future.
1195  static Array< Index > hspec(100,missing);
1196 
1197  // This is an array of arrays for each mytran tag. It contains the
1198  // ARTS indices of the MYTRAN isotopes.
1199  static Array< ArrayOfIndex > hiso(100);
1200 
1201  // Remeber if this stuff has already been initialized:
1202  static bool hinit = false;
1203 
1204  // Remember, about which missing species we have already issued a
1205  // warning:
1206  static ArrayOfIndex warned_missing;
1207 
1208  if ( !hinit )
1209  {
1210  for ( Index i=0; i<species_data.nelem(); ++i )
1211  {
1212  const SpeciesRecord& sr = species_data[i];
1213 
1214  // We have to be careful and check for the case that all
1215  // MYTRAN isotope tags are -1 (this species is missing in MYTRAN).
1216 
1217  if ( 0 < sr.Isotope()[0].MytranTag() )
1218  {
1219  // The MYTRAN tags are stored as species plus isotope tags
1220  // (MO and ISO)
1221  // in the Isotope() part of the species record.
1222  // We can extract the MO part from any of the isotope tags,
1223  // so we use the first one. We do this by taking an integer
1224  // division by 10.
1225 
1226  Index mo = sr.Isotope()[0].MytranTag() / 10;
1227  // cout << "mo = " << mo << endl;
1228  hspec[mo] = i;
1229 
1230  // Get a nicer to handle array of MYTRAN iso tags:
1231  Index n_iso = sr.Isotope().nelem();
1232  ArrayOfIndex iso_tags;
1233  iso_tags.resize(n_iso);
1234  for ( Index j=0; j<n_iso; ++j )
1235  {
1236  iso_tags[j] = sr.Isotope()[j].MytranTag();
1237  }
1238 
1239  // Reserve elements for the isotope tags. How much do we
1240  // need? This depends on the largest MYTRAN tag that we know
1241  // about!
1242  // Also initialize the tags to missing.
1243  // cout << "iso_tags = " << iso_tags << endl;
1244  // cout << "static_cast<Index>(max(iso_tags))%10 + 1 = "
1245  // << static_cast<Index>(max(iso_tags))%10 + 1 << endl;
1246  hiso[mo].resize( max(iso_tags)%10 + 1 );
1247  hiso[mo] = missing; // Matpack can set all elements like this.
1248 
1249  // Set the isotope tags:
1250  for ( Index j=0; j<n_iso; ++j )
1251  {
1252  if ( 0 < iso_tags[j] ) // ignore -1 elements
1253  {
1254  // To get the iso tags from MytranTag() we also have to take
1255  // modulo 10 to get rid of mo.
1256  // cout << "iso_tags[j] % 10 = " << iso_tags[j] % 10 << endl;
1257  hiso[mo][iso_tags[j] % 10] = j;
1258  }
1259  }
1260  }
1261  }
1262 
1263 // cout << "hiso = " << hiso << endl << "***********" << endl;
1264 
1265 
1266  // Print the generated data structures (for debugging):
1267  out3 << " MYTRAN index table:\n";
1268  for ( Index i=0; i<hspec.nelem(); ++i )
1269  {
1270  if ( missing != hspec[i] )
1271  {
1272  // The explicit conversion of Name to a c-String is
1273  // necessary, because setw does not work correctly for
1274  // stl Strings.
1275  out3 << " mo = " << i << " Species = "
1276  << setw(10) << setiosflags(ios::left)
1277  << species_data[hspec[i]].Name().c_str()
1278  << "iso = ";
1279  for ( Index j=1; j<hiso[i].nelem(); ++j )
1280  {
1281  if ( missing==hiso[i][j] )
1282  out3 << " " << "m";
1283  else
1284  out3 << " " << species_data[hspec[i]].Isotope()[hiso[i][j]].Name();
1285  }
1286  out3 << "\n";
1287  }
1288  }
1289 
1290  hinit = true;
1291  }
1292 
1293 
1294  // This contains the rest of the line to parse. At the beginning the
1295  // entire line. Line gets shorter and shorter as we continue to
1296  // extract stuff from the beginning.
1297  String line;
1298 
1299  // The first item is the molecule number:
1300  Index mo;
1301 
1302  // Look for more comments?
1303  bool comment = true;
1304 
1305  while (comment)
1306  {
1307  // Return true if eof is reached:
1308  if (is.eof()) return true;
1309 
1310  // Throw runtime_error if stream is bad:
1311  if (!is) throw runtime_error ("Stream bad.");
1312 
1313  // Read line from file into linebuffer:
1314  getline(is,line);
1315 
1316  // It is possible that we were exactly at the end of the file before
1317  // calling getline. In that case the previous eof() was still false
1318  // because eof() evaluates only to true if one tries to read after the
1319  // end of the file. The following check catches this.
1320  if (line.nelem() == 0 && is.eof()) return true;
1321 
1322  // Because of the fixed FORTRAN format, we need to break up the line
1323  // explicitly in apropriate pieces. Not elegant, but works!
1324 
1325  // Extract molecule number:
1326  mo = 0;
1327  // Initialization of mo is important, because mo stays the same
1328  // if line is empty.
1329  extract(mo,line,2);
1330  // cout << "mo = " << mo << endl;
1331 
1332  // If mo == 0 this is just a comment line:
1333  if ( 0 != mo )
1334  {
1335  // See if we know this species. We will give an error if a
1336  // species is not known.
1337  if ( missing != hspec[mo] ) comment = false ;
1338  else
1339  {
1340  // See if this is already in warned_missing, use
1341  // std::count for that:
1342  if ( 0 == std::count(warned_missing.begin(),
1343  warned_missing.end(),
1344  mo) )
1345  {
1346  CREATE_OUT0
1347  out0 << "Error: MYTRAN mo = " << mo << " is not "
1348  << "known to ARTS.\n";
1349  warned_missing.push_back(mo);
1350  arts_exit();
1351  // SAB 08.08.2000 If you want to make the program
1352  // continue anyway, just comment out the exit
1353  // line.
1354  }
1355  }
1356  }
1357  }
1358 
1359  // Ok, we seem to have a valid species here.
1360 
1361  // Set mspecies from my cool index table:
1362  mspecies = hspec[mo];
1363 
1364  // Extract isotope:
1365  Index iso;
1366  extract(iso,line,1);
1367  // cout << "iso = " << iso << endl;
1368 
1369 
1370  // Set misotope from the other cool index table.
1371  // We have to be careful to issue an error for unknown iso tags. Iso
1372  // could be either larger than the size of hiso[mo], or set
1373  // explicitly to missing. Unfortunately we have to test both cases.
1374  misotope = missing;
1375  if ( iso < hiso[mo].nelem() )
1376  if ( missing != hiso[mo][iso] )
1377  misotope = hiso[mo][iso];
1378 
1379  // Issue error message if misotope is still missing:
1380  if (missing == misotope)
1381  {
1382  ostringstream os;
1383  os << "Species: " << species_data[mspecies].Name()
1384  << ", isotope iso = " << iso
1385  << " is unknown.";
1386  throw runtime_error(os.str());
1387  }
1388 
1389 
1390  // Position.
1391  {
1392  // MYTRAN position in MHz:
1393  Numeric v;
1394 
1395  // Extract MYTRAN postion:
1396  extract(v,line,13);
1397 
1398  // ARTS position in Hz:
1399  mf = v * 1E6;
1400  // cout << "mf = " << mf << endl;
1401  }
1402 
1403  // Accuracy for line position
1404  {
1405  // Extract MYTRAN postion accuracy:
1406  Numeric df;
1407  extract(df,line,8);
1408  // ARTS accuracy of line position in Hz:
1409  mdf = df * 1E6;
1410  }
1411 
1412  // Intensity.
1413  {
1414  extern const Numeric SPEED_OF_LIGHT; // in [m/s]
1415 
1416  // MYTRAN2 intensity is in cm-1/(molec * cm-2) at 296 Kelvin.
1417  // (just like HITRAN, only isotopic ratio is not included)
1418  // The first cm-1 is the frequency unit (it cancels with the
1419  // 1/frequency unit of the line shape function).
1420  //
1421  // We need to do the following:
1422  // 1. Convert frequency from wavenumber to Hz (factor 1e2 * c)
1423  // 2. Convert [molec * cm-2] to [molec * m-2] (factor 1e-4)
1424 
1425  const Numeric hi2arts = 1e-2 * SPEED_OF_LIGHT;
1426 
1427  Numeric s;
1428 
1429  // Extract HITRAN intensity:
1430  extract(s,line,10);
1431 
1432  // Convert to ARTS units (Hz / (molec * m-2) ), or shorter: Hz*m^2
1433  mi0 = s * hi2arts;
1434  }
1435 
1436 
1437  // Air broadening parameters.
1438  {
1439  // MYTRAN parameter is in MHz/Torr at reference temperature
1440  // All parameters are HWHM
1441  Numeric gam;
1442  // External constant from constants.cc: Converts torr to
1443  // Pa. Multiply value in torr by this number to get value in Pa.
1444  extern const Numeric TORR2PA;
1445 
1446  // Extract HITRAN AGAM value:
1447  extract(gam,line,5);
1448 
1449  // ARTS parameter in Hz/Pa:
1450  magam = gam * 1E6 / TORR2PA;
1451 
1452  // Extract MYTRAN SGAM value:
1453  extract(gam,line,5);
1454 
1455  // ARTS parameter in Hz/Pa:
1456  msgam = gam * 1E6 / TORR2PA;
1457 
1458 // cout << "agam, sgam = " << magam << ", " << msgam << endl;
1459  }
1460 
1461 
1462  // Lower state energy.
1463  {
1464  // MYTRAN parameter is in wavenumbers (cm^-1).
1465  // We have to convert this to the ARTS unit Joule.
1466 
1467  // Extract from Catalogue line
1468  extract(melow,line,10);
1469 
1470  // Convert to Joule:
1472  }
1473 
1474 
1475  // Temperature coefficient of broadening parameters.
1476  {
1477  // This is dimensionless, we can also extract directly.
1478  extract(mnair,line,4);
1479 
1480  // Extract the self broadening parameter:
1481  extract(mnself,line,4);
1482 // cout << "mnair = " << mnair << endl;
1483  }
1484 
1485 
1486  // Reference temperature for broadening parameter in K:
1487  {
1488  // correct units, extract directly
1489  extract(mtgam,line,7);
1490  }
1491 
1492 
1493  // Pressure shift.
1494  {
1495  // MYTRAN value in MHz/Torr
1496  Numeric d;
1497  // External constant from constants.cc: Converts torr to
1498  // Pa. Multiply value in torr by this number to get value in Pa.
1499  extern const Numeric TORR2PA;
1500 
1501  // Extract MYTRAN value:
1502  extract(d,line,9);
1503 
1504  // ARTS value in Hz/Pa
1505  mpsf = d * 1E6 / TORR2PA;
1506  }
1507  // Set the accuracies using the definition of MYTRAN accuracy
1508  // indices. If some are missing, they are set to -1.
1509 
1510  //Skip upper state global quanta index
1511  {
1512  Index eu;
1513  extract(eu,line,3);
1514  }
1515 
1516  //Skip lower state global quanta index
1517  {
1518  Index el;
1519  extract(el,line,3);
1520  }
1521 
1522  //Skip upper state local quanta
1523  {
1524  Index eul;
1525  extract(eul,line,9);
1526  }
1527 
1528  //Skip lower state local quanta
1529  {
1530  Index ell;
1531  extract(ell,line,9);
1532  }
1533  // Accuracy index for intensity
1534  {
1535  Index di0;
1536  // Extract MYTRAN value:
1537  extract(di0,line,1);
1538  //convert to ARTS units (%)
1539  convMytranIER(mdi0,di0);
1540  }
1541 
1542  // Accuracy index for AGAM
1543  {
1544  Index dgam;
1545  // Extract MYTRAN value:
1546  extract(dgam,line,1);
1547  //convert to ARTS units (%)
1548  convMytranIER(mdagam,dgam);
1549  }
1550 
1551  // Accuracy index for NAIR
1552  {
1553  Index dnair;
1554  // Extract MYTRAN value:
1555  extract(dnair,line,1);
1556  //convert to ARTS units (%);
1557  convMytranIER(mdnair,dnair);
1558  }
1559 
1560 
1561  // These were all the parameters that we can extract from
1562  // MYTRAN. However, we still have to set the reference temperatures
1563  // to the appropriate value:
1564 
1565  // Reference temperature for Intensity in K.
1566  // (This is fix for MYTRAN2)
1567  mti0 = 296.0;
1568 
1569  // It is important that you intialize here all the new parameters that
1570  // you added to the line record. (This applies to all the reading
1571  // functions, also for ARTS, JPL, and HITRAN format.) Parameters
1572  // should be either set from the catalogue, or set to -1.)
1573 
1574  // That's it!
1575  return false;
1576 }
1577 
1578 
1579 bool LineRecord::ReadFromJplStream(istream& is, const Verbosity& verbosity)
1580 {
1581  CREATE_OUT3
1582 
1583  // Global species lookup data:
1584  extern const Array<SpeciesRecord> species_data;
1585 
1586  // We need a species index sorted by JPL tag. Keep this in a
1587  // static variable, so that we have to do this only once. The ARTS
1588  // species index is JplMap[<JPL tag>]. We need Index in this map,
1589  // because the tag array within the species data is an Index array.
1590  static map<Index, SpecIsoMap> JplMap;
1591 
1592  // Remeber if this stuff has already been initialized:
1593  static bool hinit = false;
1594 
1595  if ( !hinit )
1596  {
1597 
1598  out3 << " JPL index table:\n";
1599 
1600  for ( Index i=0; i<species_data.nelem(); ++i )
1601  {
1602  const SpeciesRecord& sr = species_data[i];
1603 
1604 
1605  for ( Index j=0; j<sr.Isotope().nelem(); ++j)
1606  {
1607 
1608  for (Index k=0; k<sr.Isotope()[j].JplTags().nelem(); ++k)
1609  {
1610 
1611  SpecIsoMap indicies(i,j);
1612 
1613  JplMap[sr.Isotope()[j].JplTags()[k]] = indicies;
1614 
1615  // Print the generated data structures (for debugging):
1616  // The explicit conversion of Name to a c-String is
1617  // necessary, because setw does not work correctly for
1618  // stl Strings.
1619  const Index& i1 = JplMap[sr.Isotope()[j].JplTags()[k]].Speciesindex();
1620  const Index& i2 = JplMap[sr.Isotope()[j].JplTags()[k]].Isotopeindex();
1621 
1622  out3 << " JPL TAG = " << sr.Isotope()[j].JplTags()[k] << " Species = "
1623  << setw(10) << setiosflags(ios::left)
1624  << species_data[i1].Name().c_str()
1625  << "iso = "
1626  << species_data[i1].Isotope()[i2].Name().c_str()
1627  << "\n";
1628  }
1629 
1630  }
1631  }
1632  hinit = true;
1633  }
1634 
1635 
1636  // This contains the rest of the line to parse. At the beginning the
1637  // entire line. Line gets shorter and shorter as we continue to
1638  // extract stuff from the beginning.
1639  String line;
1640 
1641 
1642  // Look for more comments?
1643  bool comment = true;
1644 
1645  while (comment)
1646  {
1647  // Return true if eof is reached:
1648  if (is.eof()) return true;
1649 
1650  // Throw runtime_error if stream is bad:
1651  if (!is) throw runtime_error ("Stream bad.");
1652 
1653  // Read line from file into linebuffer:
1654  getline(is,line);
1655 
1656  // It is possible that we were exactly at the end of the file before
1657  // calling getline. In that case the previous eof() was still false
1658  // because eof() evaluates only to true if one tries to read after the
1659  // end of the file. The following check catches this.
1660  if (line.nelem() == 0 && is.eof()) return true;
1661 
1662  // Because of the fixed FORTRAN format, we need to break up the line
1663  // explicitly in apropriate pieces. Not elegant, but works!
1664 
1665  // Extract center frequency:
1666  // Initialization of v is important, because v stays the same
1667  // if line is empty.
1668  // JPL position in MHz:
1669  Numeric v = 0.0;
1670 
1671  // Extract JPL position:
1672  extract(v,line,13);
1673 
1674  // check for empty line
1675  if (v != 0.0)
1676  {
1677  // ARTS position in Hz:
1678  mf = v * 1E6;
1679 
1680  comment = false;
1681  }
1682  }
1683 
1684  // Accuracy for line position
1685  {
1686  Numeric df;
1687  extract(df,line,8);
1688  //convert to ARTS units (Hz)
1689  mdf = df * 1E6;
1690  }
1691 
1692  // Intensity.
1693  {
1694  // JPL has log (10) of intensity in nm2 MHz at 300 Kelvin.
1695  //
1696  // We need to do the following:
1697  // 1. take 10^intensity
1698  // 2. convert to cm-1/(molecule * cm-2): devide by c * 1e10
1699  // 3. Convert frequency from wavenumber to Hz (factor 1e2 * c)
1700  // 4. Convert [molec * cm-2] to [molec * m-2] (factor 1e-4)
1701 
1702  Numeric s;
1703 
1704  // Extract JPL intensity:
1705  extract(s,line,8);
1706 
1707  // remove log
1708  s = pow((Numeric)10.,s);
1709 
1710  // Convert to ARTS units (Hz / (molec * m-2) ), or shorter: Hz*m^2
1711  mi0 = s / 1E12;
1712  }
1713 
1714  // Degrees of freedom
1715  {
1716  Index dr;
1717 
1718  // Extract degrees of freedom
1719  extract(dr,line,2);
1720  }
1721 
1722  // Lower state energy.
1723  {
1724  // JPL parameter is in wavenumbers (cm^-1).
1725  // We have to convert this to the ARTS unit Joule.
1726 
1727  // Extract from Catalogue line
1728  extract(melow,line,10);
1729 
1730  // Convert to Joule:
1732  }
1733 
1734  // Upper state degeneracy
1735  {
1736  Index gup;
1737 
1738  // Extract upper state degeneracy
1739  extract(gup,line,3);
1740  }
1741 
1742  // Tag number
1743  Index tag;
1744  {
1745  // Extract Tag number
1746  extract(tag,line,7);
1747 
1748  // make sure tag is not negative (damned jpl cat):
1749  tag = tag > 0 ? tag : -tag;
1750  }
1751 
1752  // ok, now for the cool index map:
1753 
1754  // is this tag valid?
1755  const map<Index, SpecIsoMap>::const_iterator i = JplMap.find(tag);
1756  if ( i == JplMap.end() )
1757  {
1758  ostringstream os;
1759  os << "JPL Tag: " << tag << " is unknown.";
1760  throw runtime_error(os.str());
1761  }
1762 
1763  SpecIsoMap id = i->second;
1764 
1765 
1766  // Set mspecies:
1767  mspecies = id.Speciesindex();
1768 
1769  // Set misotope:
1770  misotope = id.Isotopeindex();
1771 
1772  // Air broadening parameters: unknown to jpl, use old iup forward
1773  // model default values, which is mostly set to 0.0025 GHz/hPa, even
1774  // though for some lines the pressure broadening is given explicitly
1775  // in the program code. The explicitly given values are ignored and
1776  // only the default value is set. Self broadening was in general not
1777  // considered in the old forward model.
1778  {
1779  // ARTS parameter in Hz/Pa:
1780  magam = 2.5E4;
1781 
1782  // ARTS parameter in Hz/Pa:
1783  msgam = magam;
1784  }
1785 
1786 
1787  // Temperature coefficient of broadening parameters. Was set to 0.75
1788  // in old forward model, even though for some lines the parameter is
1789  // given explicitly in the program code. The explicitly given values
1790  // are ignored and only the default value is set. Self broadening
1791  // not considered.
1792  {
1793  mnair = 0.75;
1794  mnself = 0.0;
1795  }
1796 
1797 
1798  // Reference temperature for broadening parameter in K, was
1799  // generally set to 300 K in old forward model, with the exceptions
1800  // as already mentioned above:
1801  {
1802  mtgam = 300.0;
1803  }
1804 
1805 
1806  // Pressure shift: not given in JPL, set to 0
1807  {
1808  mpsf = 0.0;
1809  }
1810 
1811 
1812  // These were all the parameters that we can extract from
1813  // JPL. However, we still have to set the reference temperatures
1814  // to the appropriate value:
1815 
1816  // Reference temperature for Intensity in K.
1817  // (This is fix for JPL)
1818  mti0 = 300.0;
1819 
1820  // That's it!
1821  return false;
1822 }
1823 
1824 
1825 bool LineRecord::ReadFromArtscat3Stream(istream& is, const Verbosity& verbosity)
1826 {
1827  CREATE_OUT3
1828 
1829  // Global species lookup data:
1830  extern const Array<SpeciesRecord> species_data;
1831 
1832  // We need a species index sorted by Arts identifier. Keep this in a
1833  // static variable, so that we have to do this only once. The ARTS
1834  // species index is ArtsMap[<Arts String>].
1835  static map<String, SpecIsoMap> ArtsMap;
1836 
1837  // Remeber if this stuff has already been initialized:
1838  static bool hinit = false;
1839 
1840  mversion = 3;
1841 
1842  if ( !hinit )
1843  {
1844 
1845  out3 << " ARTS index table:\n";
1846 
1847  for ( Index i=0; i<species_data.nelem(); ++i )
1848  {
1849  const SpeciesRecord& sr = species_data[i];
1850 
1851 
1852  for ( Index j=0; j<sr.Isotope().nelem(); ++j)
1853  {
1854 
1855  SpecIsoMap indicies(i,j);
1856  String buf = sr.Name()+"-"+sr.Isotope()[j].Name();
1857 
1858  ArtsMap[buf] = indicies;
1859 
1860  // Print the generated data structures (for debugging):
1861  // The explicit conversion of Name to a c-String is
1862  // necessary, because setw does not work correctly for
1863  // stl Strings.
1864  const Index& i1 = ArtsMap[buf].Speciesindex();
1865  const Index& i2 = ArtsMap[buf].Isotopeindex();
1866 
1867  out3 << " Arts Identifier = " << buf << " Species = "
1868  << setw(10) << setiosflags(ios::left)
1869  << species_data[i1].Name().c_str()
1870  << "iso = "
1871  << species_data[i1].Isotope()[i2].Name().c_str()
1872  << "\n";
1873 
1874  }
1875  }
1876  hinit = true;
1877  }
1878 
1879 
1880  // This always contains the rest of the line to parse. At the
1881  // beginning the entire line. Line gets shorter and shorter as we
1882  // continue to extract stuff from the beginning.
1883  String line;
1884 
1885  // Look for more comments?
1886  bool comment = true;
1887 
1888  while (comment)
1889  {
1890  // Return true if eof is reached:
1891  if (is.eof()) return true;
1892 
1893  // Throw runtime_error if stream is bad:
1894  if (!is) throw runtime_error ("Stream bad.");
1895 
1896  // Read line from file into linebuffer:
1897  getline(is,line);
1898 
1899  // It is possible that we were exactly at the end of the file before
1900  // calling getline. In that case the previous eof() was still false
1901  // because eof() evaluates only to true if one tries to read after the
1902  // end of the file. The following check catches this.
1903  if (line.nelem() == 0 && is.eof()) return true;
1904 
1905  // @ as first character marks catalogue entry
1906  char c;
1907  extract(c,line,1);
1908 
1909  // check for empty line
1910  if (c == '@')
1911  {
1912  comment = false;
1913  }
1914  }
1915 
1916 
1917  // read the arts identifier String
1918  istringstream icecream(line);
1919 
1920  String artsid;
1921  icecream >> artsid;
1922 
1923  if (artsid.length() != 0)
1924  {
1925 
1926  // ok, now for the cool index map:
1927  // is this arts identifier valid?
1928  const map<String, SpecIsoMap>::const_iterator i = ArtsMap.find(artsid);
1929  if ( i == ArtsMap.end() )
1930  {
1931  ostringstream os;
1932  os << "ARTS Tag: " << artsid << " is unknown.";
1933  throw runtime_error(os.str());
1934  }
1935 
1936  SpecIsoMap id = i->second;
1937 
1938 
1939  // Set mspecies:
1940  mspecies = id.Speciesindex();
1941 
1942  // Set misotope:
1943  misotope = id.Isotopeindex();
1944 
1945 
1946  // Extract center frequency:
1947  icecream >> mf;
1948 
1949 
1950  // Extract pressure shift:
1951  icecream >> mpsf;
1952 
1953  // Extract intensity:
1954  icecream >> mi0;
1955 
1956 
1957  // Extract reference temperature for Intensity in K:
1958  icecream >> mti0;
1959 
1960 
1961  // Extract lower state energy:
1962  icecream >> melow;
1963 
1964 
1965  // Extract air broadening parameters:
1966  icecream >> magam;
1967  icecream >> msgam;
1968 
1969  // Extract temperature coefficient of broadening parameters:
1970  icecream >> mnair;
1971  icecream >> mnself;
1972 
1973 
1974  // Extract reference temperature for broadening parameter in K:
1975  icecream >> mtgam;
1976 
1977  // Extract the aux parameters:
1978  Index naux;
1979  icecream >> naux;
1980 
1981  // resize the aux array and read it
1982  maux.resize(naux);
1983 
1984  for (Index j = 0; j<naux; j++)
1985  {
1986  icecream >> maux[j];
1987  //cout << "maux" << j << " = " << maux[j] << "\n";
1988  }
1989 
1990  // Extract accuracies:
1991  try
1992  {
1993  icecream >> mdf;
1994  icecream >> mdi0;
1995  icecream >> mdagam;
1996  icecream >> mdsgam;
1997  icecream >> mdnair;
1998  icecream >> mdnself;
1999  icecream >> mdpsf;
2000  }
2001  catch (runtime_error)
2002  {
2003  // Nothing to do here, the accuracies are optional, so we
2004  // just set them to -1 and continue reading the next line of
2005  // the catalogue
2006  mdf = -1;
2007  mdi0 = -1;
2008  mdagam = -1;
2009  mdsgam = -1;
2010  mdnair = -1;
2011  mdnself = -1;
2012  mdpsf = -1;
2013  }
2014  }
2015 
2016  // That's it!
2017  return false;
2018 }
2019 
2020 bool LineRecord::ReadFromArtscat4Stream(istream& is, const Verbosity& verbosity)
2021 {
2022  CREATE_OUT3
2023 
2024  // Global species lookup data:
2025  extern const Array<SpeciesRecord> species_data;
2026 
2027  // We need a species index sorted by Arts identifier. Keep this in a
2028  // static variable, so that we have to do this only once. The ARTS
2029  // species index is ArtsMap[<Arts String>].
2030  static map<String, SpecIsoMap> ArtsMap;
2031 
2032  // Remeber if this stuff has already been initialized:
2033  static bool hinit = false;
2034 
2035  mversion = 4;
2036 
2037  if ( !hinit )
2038  {
2039 
2040  out3 << " ARTS index table:\n";
2041 
2042  for ( Index i=0; i<species_data.nelem(); ++i )
2043  {
2044  const SpeciesRecord& sr = species_data[i];
2045 
2046 
2047  for ( Index j=0; j<sr.Isotope().nelem(); ++j)
2048  {
2049 
2050  SpecIsoMap indicies(i,j);
2051  String buf = sr.Name()+"-"+sr.Isotope()[j].Name();
2052 
2053  ArtsMap[buf] = indicies;
2054 
2055  // Print the generated data structures (for debugging):
2056  // The explicit conversion of Name to a c-String is
2057  // necessary, because setw does not work correctly for
2058  // stl Strings.
2059  const Index& i1 = ArtsMap[buf].Speciesindex();
2060  const Index& i2 = ArtsMap[buf].Isotopeindex();
2061 
2062  out3 << " Arts Identifier = " << buf << " Species = "
2063  << setw(10) << setiosflags(ios::left)
2064  << species_data[i1].Name().c_str()
2065  << "iso = "
2066  << species_data[i1].Isotope()[i2].Name().c_str()
2067  << "\n";
2068 
2069  }
2070  }
2071  hinit = true;
2072  }
2073 
2074 
2075  // This always contains the rest of the line to parse. At the
2076  // beginning the entire line. Line gets shorter and shorter as we
2077  // continue to extract stuff from the beginning.
2078  String line;
2079 
2080  // Look for more comments?
2081  bool comment = true;
2082 
2083  while (comment)
2084  {
2085  // Return true if eof is reached:
2086  if (is.eof()) return true;
2087 
2088  // Throw runtime_error if stream is bad:
2089  if (!is) throw runtime_error ("Stream bad.");
2090 
2091  // Read line from file into linebuffer:
2092  getline(is,line);
2093 
2094  // It is possible that we were exactly at the end of the file before
2095  // calling getline. In that case the previous eof() was still false
2096  // because eof() evaluates only to true if one tries to read after the
2097  // end of the file. The following check catches this.
2098  if (line.nelem() == 0 && is.eof()) return true;
2099 
2100  // @ as first character marks catalogue entry
2101  char c;
2102  extract(c,line,1);
2103 
2104  // check for empty line
2105  if (c == '@')
2106  {
2107  comment = false;
2108  }
2109  }
2110 
2111 
2112  // read the arts identifier String
2113  istringstream icecream(line);
2114 
2115  String artsid;
2116  icecream >> artsid;
2117 
2118  if (artsid.length() != 0)
2119  {
2120 
2121  // ok, now for the cool index map:
2122  // is this arts identifier valid?
2123  const map<String, SpecIsoMap>::const_iterator i = ArtsMap.find(artsid);
2124  if ( i == ArtsMap.end() )
2125  {
2126  ostringstream os;
2127  os << "ARTS Tag: " << artsid << " is unknown.";
2128  throw runtime_error(os.str());
2129  }
2130 
2131  SpecIsoMap id = i->second;
2132 
2133 
2134  // Set mspecies:
2135  mspecies = id.Speciesindex();
2136 
2137  // Set misotope:
2138  misotope = id.Isotopeindex();
2139 
2140 
2141  // Extract center frequency:
2142  icecream >> mf;
2143 
2144 
2145  // Extract intensity:
2146  icecream >> mi0;
2147 
2148  // Extract reference temperature for Intensity in K:
2149  icecream >> mti0;
2150 
2151  // Extract lower state energy:
2152  icecream >> melow;
2153 
2154  // Extract Einstein A-coefficient:
2155  icecream >> ma;
2156 
2157  // Extract upper state stat. weight:
2158  icecream >> mgupper;
2159 
2160  // Extract lower state stat. weight:
2161  icecream >> mglower;
2162 
2163  // Extract broadening parameters:
2164  icecream >> mgamma_self;
2165  icecream >> mgamma_n2;
2166  icecream >> mgamma_o2;
2167  icecream >> mgamma_h2o;
2168  icecream >> mgamma_co2;
2169  icecream >> mgamma_h2;
2170  icecream >> mgamma_he;
2171 
2172  // Extract GAM temp. exponents:
2173  icecream >> mn_self;
2174  icecream >> mn_n2;
2175  icecream >> mn_o2;
2176  icecream >> mn_h2o;
2177  icecream >> mn_co2;
2178  icecream >> mn_h2;
2179  icecream >> mn_he;
2180 
2181  // Extract F pressure shifts:
2182  icecream >> mdelta_n2;
2183  icecream >> mdelta_o2;
2184  icecream >> mdelta_h2o;
2185  icecream >> mdelta_co2;
2186  icecream >> mdelta_h2;
2187  icecream >> mdelta_he;
2188 
2189  // Resize aux array to 0, not used in ARTSCAT-4
2190  maux.resize(0);
2191 
2192  // Set values that are not used in ARTSCAT-4 to -1
2193  mdf = -1;
2194  mdi0 = -1;
2195  mdagam = -1;
2196  mdsgam = -1;
2197  mdnair = -1;
2198  mdnself = -1;
2199  mdpsf = -1;
2200  }
2201 
2202  // That's it!
2203  return false;
2204 }
2205 
2241  ConstVectorView f_grid,
2242  ConstVectorView abs_p,
2243  ConstVectorView abs_t,
2244  ConstVectorView abs_h2o_orig,
2245  ConstVectorView vmr,
2246  const ArrayOfLineRecord& abs_lines,
2247  const Index ind_ls,
2248  const Index ind_lsn,
2249  const Numeric cutoff,
2250  const Verbosity& verbosity )
2251 {
2252  // Make lineshape and species lookup data visible:
2255 
2256  // speed of light constant
2257  extern const Numeric SPEED_OF_LIGHT;
2258 
2259  // Boltzmann constant
2260  extern const Numeric BOLTZMAN_CONST;
2261 
2262  // Avogadros constant
2263  extern const Numeric AVOGADROS_NUMB;
2264 
2265  // Planck constant
2266  extern const Numeric PLANCK_CONST;
2267 
2268  // sqrt(ln(2))
2269  // extern const Numeric SQRT_NAT_LOG_2;
2270 
2271  // Constant within the Doppler Broadening calculation:
2272  const Numeric doppler_const = sqrt( 2.0 * BOLTZMAN_CONST *
2274 
2275  // dimension of f_grid, abs_lines
2276  const Index nf = f_grid.nelem();
2277  const Index nl = abs_lines.nelem();
2278 
2279  // number of pressure levels:
2280  const Index np = abs_p.nelem();
2281 
2282  // Define the vector for the line shape function and the
2283  // normalization factor of the lineshape here, so that we don't need
2284  // so many free store allocations. the last element is used to
2285  // calculate the value at the cutoff frequency
2286  Vector ls(nf+1);
2287  Vector fac(nf+1);
2288 
2289  const bool cut = (cutoff != -1) ? true : false;
2290 
2291  // Check that the frequency grid is sorted in the case of lineshape
2292  // with cutoff. Duplicate frequency values are allowed.
2293  if (cut)
2294  {
2295  if ( ! is_sorted( f_grid ) )
2296  {
2297  ostringstream os;
2298  os << "If you use a lineshape function with cutoff, your\n"
2299  << "frequency grid *f_grid* must be sorted.\n"
2300  << "(Duplicate values are allowed.)";
2301  throw runtime_error(os.str());
2302  }
2303  }
2304 
2305  // Check that all temperatures are non-negative
2306  bool negative = false;
2307 
2308  for (Index i = 0; !negative && i < abs_t.nelem (); i++)
2309  {
2310  if (abs_t[i] < 0.)
2311  negative = true;
2312  }
2313 
2314  if (negative)
2315  {
2316  ostringstream os;
2317  os << "abs_t contains at least one negative temperature value.\n"
2318  << "This is not allowed.";
2319  throw runtime_error(os.str());
2320  }
2321 
2322  // We need a local copy of f_grid which is 1 element longer, because
2323  // we append a possible cutoff to it.
2324  // The initialization of this has to be inside the line loop!
2325  Vector f_local( nf + 1 );
2326 
2327  // Voigt generally needs a different frequency grid. If we allocate
2328  // that in the outer loop, instead of in voigt, we don't have the
2329  // free store allocation at each lineshape call. Calculation is
2330  // still done in the voigt routine itself, this is just an auxillary
2331  // parameter, passed to lineshape. For selected lineshapes (e.g.,
2332  // Rosenkranz) it is used additionally to pass parameters needed in
2333  // the lineshape (e.g., overlap, ...). Consequently we have to
2334  // assure that aux has a dimension not less then the number of
2335  // parameters passed.
2336  Index ii = (nf+1 < 10) ? 10 : nf+1;
2337  Vector aux(ii);
2338 
2339  // Check that abs_p, abs_t, and abs_vmrs have the same
2340  // dimension. This could be a user error, so we throw a
2341  // runtime_error.
2342 
2343  if ( abs_t.nelem() != np )
2344  {
2345  ostringstream os;
2346  os << "Variable abs_t must have the same dimension as abs_p.\n"
2347  << "abs_t.nelem() = " << abs_t.nelem() << '\n'
2348  << "abs_p.nelem() = " << np;
2349  throw runtime_error(os.str());
2350  }
2351 
2352  if ( vmr.nelem() != np )
2353  {
2354  ostringstream os;
2355  os << "Variable vmr must have the same dimension as abs_p.\n"
2356  << "vmr.nelem() = " << vmr.nelem() << '\n'
2357  << "abs_p.nelem() = " << np;
2358  throw runtime_error(os.str());
2359  }
2360 
2361  // With abs_h2o it is different. We do not really need this in most
2362  // cases, only the Rosenkranz lineshape for oxygen uses it. There is
2363  // a global (scalar) default value of -1, that we are expanding to a
2364  // vector here if we find it. The Rosenkranz lineshape does a check
2365  // to make sure that the value is actually set, and not the default
2366  // value.
2367  Vector abs_h2o(np);
2368  if ( abs_h2o_orig.nelem() == np )
2369  {
2370  abs_h2o = abs_h2o_orig;
2371  }
2372  else
2373  {
2374  if ( ( 1 == abs_h2o_orig.nelem()) &&
2375  ( -.99 > abs_h2o_orig[0]) )
2376  {
2377  // We have found the global default value. Expand this to a
2378  // vector with the right length, by copying -1 to all
2379  // elements of abs_h2o.
2380  abs_h2o = -1;
2381  }
2382  else
2383  {
2384  ostringstream os;
2385  os << "Variable abs_h2o must have default value -1 or the\n"
2386  << "same dimension as abs_p.\n"
2387  << "abs_h2o.nelem() = " << abs_h2o.nelem() << '\n'
2388  << "abs_p.nelem() = " << np;
2389  throw runtime_error(os.str());
2390  }
2391  }
2392 
2393  // Check that the dimension of xsec is indeed [f_grid.nelem(),
2394  // abs_p.nelem()]:
2395  if ( xsec.nrows() != nf || xsec.ncols() != np )
2396  {
2397  ostringstream os;
2398  os << "Variable xsec must have dimensions [f_grid.nelem(),abs_p.nelem()].\n"
2399  << "[xsec.nrows(),xsec.ncols()] = [" << xsec.nrows()
2400  << ", " << xsec.ncols() << "]\n"
2401  << "f_grid.nelem() = " << nf << '\n'
2402  << "abs_p.nelem() = " << np;
2403  throw runtime_error(os.str());
2404  }
2405 
2406 
2407  // Loop all pressures:
2408 
2409 /*#pragma omp parallel for \
2410  if(!arts_omp_in_parallel() && np>=arts_omp_get_max_threads()) \
2411  default(none) \
2412  shared(joker, abs_lines, abs_p, abs_t, vmr, f_grid, \
2413  abs_h2o, xsec) \
2414  firstprivate(ls, fac, f_local, aux) */
2415 #pragma omp parallel for \
2416  if(!arts_omp_in_parallel() && np>=arts_omp_get_max_threads()) \
2417  firstprivate(ls, fac, f_local, aux)
2418  for ( Index i=0; i<np; ++i )
2419  {
2420  // Store input profile variables, this is perhaps slightly faster.
2421  const Numeric p_i = abs_p[i];
2422  const Numeric t_i = abs_t[i];
2423  const Numeric vmr_i = vmr[i];
2424  const Numeric abs_h2o_i = abs_h2o[i];
2425 
2426  //out3 << " p = " << p_i << " Pa\n";
2427 
2428  // Calculate total number density from pressure and temperature.
2429  // n = n0*T0/p0 * p/T or n = p/kB/t, ideal gas law
2430  // const Numeric n = p_i / BOLTZMAN_CONST / t_i;
2431  // This is not needed anymore, since we now calculate true cross
2432  // sections, which do not contain the n.
2433 
2434  // For the pressure broadening, we also need the partial pressure:
2435  const Numeric p_partial = p_i * vmr_i;
2436 
2437  // Get handle on xsec for this pressure level i.
2438  // Watch out! This is output, we have to be careful not to
2439  // introduce race conditions when writing to it.
2440  VectorView xsec_i = xsec(Range(joker),i);
2441 
2442 
2443 // if (omp_in_parallel())
2444 // cout << "omp_in_parallel: true\n";
2445 // else
2446 // cout << "omp_in_parallel: false\n";
2447 
2448 
2449  // Prepare a variable that can be used by the individual LBL
2450  // threads to add up absorption:
2451  Index n_lbl_threads;
2452  if (arts_omp_in_parallel())
2453  {
2454  // If we already are running parallel, then the LBL loop
2455  // will not be parallelized.
2456  n_lbl_threads = 1;
2457  }
2458  else
2459  {
2460  n_lbl_threads = arts_omp_get_max_threads();
2461  }
2462  Matrix xsec_accum(n_lbl_threads, xsec_i.nelem(), 0);
2463 
2464 
2465  // Loop all lines:
2466 
2467 /*#pragma omp parallel for \
2468  if(!arts_omp_in_parallel()) \
2469  default(none) \
2470  shared(abs_lines, abs_p, abs_t, vmr, f_grid, abs_h2o, xsec_accum) \
2471  firstprivate(ls, fac, f_local, aux) */
2472 #pragma omp parallel for \
2473  if(!arts_omp_in_parallel()) \
2474  firstprivate(ls, fac, f_local, aux)
2475  for ( Index l=0; l< nl; ++l )
2476  {
2477 // if (omp_in_parallel())
2478 // cout << "LBL: omp_in_parallel: true\n";
2479 // else
2480 // cout << "LBL: omp_in_parallel: false\n";
2481 
2482 
2483  // The try block here is necessary to correctly handle
2484  // exceptions inside the parallel region.
2485  try
2486  {
2487 
2488  // Copy f_grid to the beginning of f_local. There is one
2489  // element left at the end of f_local.
2490  // THIS HAS TO BE INSIDE THE LINE LOOP, BECAUSE THE CUTOFF
2491  // FREQUENCY IS ALWAYS PUT IN A DIFFERENT PLACE!
2492  f_local[Range(0,nf)] = f_grid;
2493 
2494  // This will hold the actual number of frequencies to add to
2495  // xsec later on:
2496  Index nfl = nf;
2497 
2498  // This will hold the actual number of frequencies for the
2499  // call to the lineshape functions later on:
2500  Index nfls = nf;
2501 
2502  // The baseline to substract for cutoff frequency
2503  Numeric base=0.0;
2504 
2505  // abs_lines[l] is used several times, this construct should be
2506  // faster (Oliver Lemke)
2507  LineRecord l_l = abs_lines[l]; // which line are we dealing with
2508  // Center frequency in vacuum:
2509  Numeric F0 = l_l.F();
2510 
2511  // Intensity is already in the right units (Hz*m^2). It also
2512  // includes already the isotopic ratio. Needs only to be
2513  // coverted to the actual temperature and multiplied by total
2514  // number density and lineshape.
2515  Numeric intensity = l_l.I0();
2516 
2517  // Lower state energy is already in the right unit (Joule).
2518  Numeric e_lower = l_l.Elow();
2519 
2520  // Upper state energy:
2521  Numeric e_upper = e_lower + F0 * PLANCK_CONST;
2522 
2523  // Get the ratio of the partition function.
2524  // This will throw a runtime error if no data exists.
2525  // Important: This function needs both the reference
2526  // temperature and the actual temperature, because the
2527  // reference temperature can be different for each line,
2528  // even of the same species.
2529  Numeric part_fct_ratio =
2531  t_i );
2532 
2533  // Boltzmann factors
2534  Numeric nom = exp(- e_lower / ( BOLTZMAN_CONST * t_i ) ) -
2535  exp(- e_upper / ( BOLTZMAN_CONST * t_i ) );
2536 
2537  Numeric denom = exp(- e_lower / ( BOLTZMAN_CONST * l_l.Ti0() ) ) -
2538  exp(- e_upper / ( BOLTZMAN_CONST * l_l.Ti0() ) );
2539 
2540 
2541  // intensity at temperature
2542  // (calculate the line intensity according to the standard
2543  // expression given in HITRAN)
2544  intensity *= part_fct_ratio * nom / denom;
2545 
2546  if (lineshape_norm_data[ind_lsn].Name() == "quadratic")
2547  {
2548  // in case of the quadratic normalization factor use the
2549  // so called 'microwave approximation' of the line intensity
2550  // given by
2551  // P. W. Rosenkranz, Chapter 2, Eq.(2.16), in M. A. Janssen,
2552  // Atmospheric Remote Sensing by Microwave Radiometry,
2553  // John Wiley & Sons, Inc., 1993
2554  Numeric mafac = (PLANCK_CONST * F0) / (2.000e0 * BOLTZMAN_CONST
2555  * t_i);
2556  intensity = intensity * mafac / sinh(mafac);
2557  }
2558 
2559 
2560  // 2. Get pressure broadened line width:
2561  // (Agam is in Hz/Pa, abs_p is in Pa, gamma is in Hz)
2562  const Numeric theta = l_l.Tgam() / t_i;
2563  const Numeric theta_Nair = pow(theta, l_l.Nair());
2564 
2565  Numeric gamma
2566  = l_l.Agam() * theta_Nair * (p_i - p_partial)
2567  + l_l.Sgam() * pow(theta, l_l.Nself()) * p_partial;
2568 
2569  // 3. Doppler broadening without the sqrt(ln(2)) factor, which
2570  // seems to be redundant FIXME: verify .
2571  Numeric sigma = F0 * doppler_const *
2572  sqrt( t_i / l_l.IsotopeData().Mass());
2573 
2574  // 3.a. Put in pressure shift.
2575  // The T dependence is connected to that of agam by:
2576  // n_shift = .25 + 1.5 * n_agam
2577  // Theta has been initialized above.
2578  F0 += l_l.Psf() * p_i *
2579  std::pow( theta , (Numeric).25 + (Numeric)1.5*l_l.Nair() );
2580 
2581  // 4. the rosenkranz lineshape for oxygen calculates the
2582  // pressure broadening, overlap, ... differently. Therefore
2583  // all required parameters are passed in the aux array, the
2584  // given order must agree with how they are accessed in the
2585  // used lineshape (currently only the Rosenkranz routines are
2586  // using this method of passing parameters). Parameters are
2587  // always passed, because the Rosenkranz lineshape function
2588  // can be used without overlap correction, which is then just
2589  // set to 0. I know, this is not very nice, but I suggested to
2590  // put the oxygen absorption into a different workspace
2591  // method, but nobody listened to me, Schnief.
2592  aux[0] = theta;
2593  aux[1] = theta_Nair;
2594  aux[2] = p_i;
2595  aux[3] = vmr_i;
2596  aux[4] = abs_h2o_i;
2597  aux[5] = l_l.Agam();
2598  aux[6] = l_l.Nair();
2599  // is overlap available, otherwise pass zero
2600  if (l_l.Naux() > 1)
2601  {
2602  aux[7] = l_l.Aux()[0];
2603  aux[8] = l_l.Aux()[1];
2604  // cout << "aux7, aux8: " << aux[7] << " " << aux[8] << "\n";
2605  }
2606  else
2607  {
2608  aux[7] = 0.0;
2609  aux[8] = 0.0;
2610  }
2611 
2612 
2613  // Indices pointing at begin/end frequencies of f_grid or at
2614  // the elements that have to be calculated in case of cutoff
2615  Index i_f_min = 0;
2616  Index i_f_max = nf-1;
2617 
2618  // cutoff ?
2619  if ( cut )
2620  {
2621  // Check whether we have elements in ls that can be
2622  // ignored at lower frequencies of f_grid.
2623  //
2624  // Loop through all frequencies, finding min value and
2625  // set all values to zero on that way.
2626  while ( i_f_min < nf && (F0 - cutoff) > f_grid[i_f_min] )
2627  {
2628  // ls[i_f_min] = 0;
2629  ++i_f_min;
2630  }
2631 
2632 
2633  // Check whether we have elements in ls that can be
2634  // ignored at higher frequencies of f_grid.
2635  //
2636  // Loop through all frequencies, finding max value and
2637  // set all values to zero on that way.
2638  while ( i_f_max >= 0 && (F0 + cutoff) < f_grid[i_f_max] )
2639  {
2640  // ls[i_f_max] = 0;
2641  --i_f_max;
2642  }
2643 
2644  // Append the cutoff frequency to f_local:
2645  ++i_f_max;
2646  f_local[i_f_max] = F0 + cutoff;
2647 
2648  // Number of frequencies to calculate:
2649  nfls = i_f_max - i_f_min + 1; // Add one because indices
2650  // are pointing to first and
2651  // last valid element. This
2652  // is for the lineshape
2653  // calls.
2654  nfl = nfls -1; // This is for xsec.
2655  }
2656  else
2657  {
2658  // Nothing to do here. Note that nfl and nfls are both still set to nf.
2659  }
2660 
2661  // cout << "nf, nfl, nfls = " << nf << ", " << nfl << ", " << nfls << ".\n";
2662 
2663  // Maybe there are no frequencies left to compute? Note that
2664  // the number that counts here is nfl, since only these are
2665  // the `real' frequencies, for which xsec is changed. nfls
2666  // will always be at least one, because it contains the cutoff.
2667  if ( nfl > 0 )
2668  {
2669  // cout << ls << endl
2670  // << "aux / F0 / gamma / sigma" << aux << "/" << F0 << "/" << gamma << "/" << sigma << endl
2671  // << f_local[Range(i_f_min,nfls)] << endl
2672  // << nfls << endl;
2673 
2674  // Calculate the line shape:
2675  lineshape_data[ind_ls].Function()(ls,
2676  aux,F0,gamma,sigma,
2677  f_local[Range(i_f_min,nfls)],
2678  nfls);
2679 
2680  // Calculate the chosen normalization factor:
2681  lineshape_norm_data[ind_lsn].Function()(fac,F0,
2682  f_local[Range(i_f_min,nfls)],
2683  t_i,nfls);
2684 
2685  // Get a handle on the range of xsec that we want to change.
2686  // We use nfl here, which could be one less than nfls.
2687  VectorView this_xsec = xsec_accum(arts_omp_get_thread_num(), Range(i_f_min,nfl));
2688 
2689  // Get handles on the range of ls and fac that we need.
2690  VectorView this_ls = ls[Range(0,nfl)];
2691  VectorView this_fac = fac[Range(0,nfl)];
2692 
2693  // cutoff ?
2694  if ( cut )
2695  {
2696  // The index nfls-1 should be exactly the index pointing
2697  // to the value at the cutoff frequency.
2698  base = ls[nfls-1];
2699 
2700  // Subtract baseline from xsec.
2701  // this_xsec -= base;
2702  this_ls -= base;
2703  }
2704 
2705  // Add line to xsec.
2706  {
2707  // To make the loop a bit faster, precompute all constant
2708  // factors. These are:
2709  // 1. Total number density of the air. --> Not
2710  // anymore, we now to real cross-sections
2711  // 2. Line intensity.
2712  // 3. Isotopic ratio.
2713  //
2714  // The isotopic ratio must be applied here, since we are
2715  // summing up lines belonging to different isotopes.
2716 
2717  // const Numeric factors = n * intensity * l_l.IsotopeData().Abundance();
2718  const Numeric factors = intensity * l_l.IsotopeData().Abundance();
2719 
2720  // We have to do:
2721  // xsec(j,i) += factors * ls[j] * fac[j];
2722  //
2723  // We use ls as a dummy to compute the product, then add it
2724  // to this_xsec.
2725 
2726  this_ls *= this_fac;
2727  this_ls *= factors;
2728 
2729  this_xsec += this_ls;
2730 
2731  }
2732  }
2733 
2734  } // end of try block
2735  catch (runtime_error e)
2736  {
2737  CREATE_OUT0
2738  exit_or_rethrow(e.what(), out0);
2739  }
2740 
2741  } // end of parallel LBL loop
2742 
2743  // Now we just have to add up all the rows of xsec_accum:
2744  for (Index j=0; j<xsec_accum.nrows(); ++j)
2745  {
2746  xsec_i += xsec_accum(j, Range(joker));
2747  }
2748 
2749  } // end of parallel pressure loop
2750 }
2751 
2752 
2753 
2754 
2755 //======================================================================
2756 // Functions related to refraction
2757 //======================================================================
2758 
2759 
2761 
2777  Vector& refr_index,
2778  ConstVectorView abs_p,
2779  ConstVectorView abs_t )
2780 {
2781  const Index n = abs_p.nelem();
2782  refr_index.resize( n );
2783 
2784  assert ( n == abs_t.nelem() );
2785 
2786  // N = 77.593e-2 * p / t ppm
2787  for ( Index i=0; i<n; i++ )
2788  refr_index[i] = 1.0 + 77.593e-8 * abs_p[i] / abs_t[i];
2789 }
2790 
2791 
2792 
2794 
2809  Vector& refr_index,
2810  ConstVectorView abs_p,
2811  ConstVectorView abs_t,
2812  ConstVectorView abs_h2o )
2813 {
2814  const Index n = abs_p.nelem();
2815  refr_index.resize( n );
2816 
2817  assert ( n == abs_t.nelem() );
2818  assert ( n == abs_h2o.nelem() );
2819 
2820  Numeric e; // Partial pressure of water in Pa
2821  Numeric p; // Partial pressure of the dry air: p = p_tot - e
2822 
2823  for ( Index i=0; i<n; i++ )
2824  {
2825  e = abs_p[i] * abs_h2o[i];
2826  p = abs_p[i] - e;
2827 
2828  refr_index[i] = 1.0 + 77.593e-8 * p / abs_t[i] +
2829  72e-8 * e / abs_t[i] +
2830  3.754e-3 * e / (abs_t[i]*abs_t[i]);
2831  }
2832 }
2833 
2846 {
2847  // Planck constant [Js]
2848  extern const Numeric PLANCK_CONST;
2849 
2850  // Speed of light [m/s]
2851  extern const Numeric SPEED_OF_LIGHT;
2852 
2853  // Constant to convert lower state energy from cm^-1 to J
2854  const Numeric lower_energy_const = PLANCK_CONST * SPEED_OF_LIGHT * 1E2;
2855 
2856  return e*lower_energy_const;
2857 }
2858 
2859 //======================================================================
2860 // Functions to convert the accuracy index to ARTS units
2861 //======================================================================
2862 
2863 // ********* for HITRAN database *************
2864 //convert HITRAN index for line position accuracy to ARTS
2865 //units (Hz).
2866 
2868  Numeric& mdf,
2869  const Index& df
2870  )
2871 {
2872  switch ( df )
2873  {
2874  case 0:
2875  {
2876  mdf = -1;
2877  break;
2878  }
2879  case 1:
2880  {
2881  mdf = 30*1E9;
2882  break;
2883  }
2884  case 2:
2885  {
2886  mdf = 3*1E9;
2887  break;
2888  }
2889  case 3:
2890  {
2891  mdf = 300*1E6;
2892  break;
2893  }
2894  case 4:
2895  {
2896  mdf = 30*1E6;
2897  break;
2898  }
2899  case 5:
2900  {
2901  mdf = 3*1E6;
2902  break;
2903  }
2904  case 6:
2905  {
2906  mdf = 0.3*1E6;
2907  break;
2908  }
2909  }
2910 }
2911 
2912 //convert HITRAN index for intensity and halfwidth accuracy to ARTS
2913 //units (relative difference).
2915  Numeric& mdh,
2916  const Index& dh
2917  )
2918 {
2919  switch ( dh )
2920  {
2921  case 0:
2922  {
2923  mdh = -1;
2924  break;
2925  }
2926  case 1:
2927  {
2928  mdh = -1;
2929  break;
2930  }
2931  case 2:
2932  {
2933  mdh = -1;
2934  break;
2935  }
2936  case 3:
2937  {
2938  mdh = 30;
2939  break;
2940  }
2941  case 4:
2942  {
2943  mdh = 20;
2944  break;
2945  }
2946  case 5:
2947  {
2948  mdh = 10;
2949  break;
2950  }
2951  case 6:
2952  {
2953  mdh =5;
2954  break;
2955  }
2956  case 7:
2957  {
2958  mdh =2;
2959  break;
2960  }
2961  case 8:
2962  {
2963  mdh =1;
2964  break;
2965  }
2966  }
2967  mdh=mdh/100;
2968 }
2969 
2970 // ********* for MYTRAN database *************
2971 //convert MYTRAN index for intensity and halfwidth accuracy to ARTS
2972 //units (relative difference).
2974  Numeric& mdh,
2975  const Index & dh
2976  )
2977 {
2978  switch ( dh )
2979  {
2980  case 0:
2981  {
2982  mdh = 200;
2983  break;
2984  }
2985  case 1:
2986  {
2987  mdh = 100;
2988  break;
2989  }
2990  case 2:
2991  {
2992  mdh = 50;
2993  break;
2994  }
2995  case 3:
2996  {
2997  mdh = 30;
2998  break;
2999  }
3000  case 4:
3001  {
3002  mdh = 20;
3003  break;
3004  }
3005  case 5:
3006  {
3007  mdh = 10;
3008  break;
3009  }
3010  case 6:
3011  {
3012  mdh =5;
3013  break;
3014  }
3015  case 7:
3016  {
3017  mdh = 2;
3018  break;
3019  }
3020  case 8:
3021  {
3022  mdh = 1;
3023  break;
3024  }
3025  case 9:
3026  {
3027  mdh = 0.5;
3028  break;
3029  }
3030  }
3031  mdh=mdh/100;
3032 }
3033 
3034 ostream& operator<< (ostream &os, const LineshapeSpec &/*lsspec*/)
3035 {
3036  os << "LineshapeSpec: Output operator not implemented";
3037  return os;
3038 }
3039 
extract
void extract(T &x, String &line, Index n)
Extract something from a catalogue line.
Definition: absorption.cc:179
Matrix
The Matrix class.
Definition: matpackI.h:767
LineRecord::Delta_N2
Numeric Delta_N2() const
F Pressure shift N2 in Hz/Pa :
Definition: absorption.h:744
LineRecord::mdnair
Numeric mdnair
Definition: absorption.h:1107
LineRecord::Ti0
Numeric Ti0() const
Reference temperature for I0 in K:
Definition: absorption.h:628
arts_omp_get_thread_num
int arts_omp_get_thread_num()
Wrapper for omp_get_thread_num.
Definition: arts_omp.cc:83
IsotopeRecord::CalculatePartitionFctAtTemp
Numeric CalculatePartitionFctAtTemp(Numeric temperature) const
Definition: absorption.cc:51
LineRecord::dNair
Numeric dNair() const
Accuracy for AGAM temperature exponent in relative value :
Definition: absorption.h:684
LineRecord::ReadFromArtscat3Stream
bool ReadFromArtscat3Stream(istream &is, const Verbosity &verbosity)
Read one line from a stream associated with an ARTSCAT-3 file.
Definition: absorption.cc:1825
LineRecord::Gamma_N2
Numeric Gamma_N2() const
Broadening parameter N2 in Hz/Pa :
Definition: absorption.h:705
fac
Numeric fac(const Index n)
fac
Definition: math_funcs.cc:68
MatrixView
The MatrixView class.
Definition: matpackI.h:668
LineRecord::Sgam
Numeric Sgam() const
Self broadened width in Hz/Pa:
Definition: absorption.h:640
SpecIsoMap
Definition: absorption.h:1168
AVOGADROS_NUMB
const Numeric AVOGADROS_NUMB
Global constant, the Avogadro's number [molec/kg].
LineRecord::melow
Numeric melow
Definition: absorption.h:1082
absorption.h
Declarations required for the calculation of absorption coefficients.
LineRecord::mgamma_self
Numeric mgamma_self
Definition: absorption.h:1123
LineRecord::mgamma_he
Numeric mgamma_he
Definition: absorption.h:1135
LineRecord::Gam_N_H2O
Numeric Gam_N_H2O() const
GAM temp.
Definition: absorption.h:732
LineRecord::mn_co2
Numeric mn_co2
Definition: absorption.h:1146
LineRecord::mn_h2
Numeric mn_h2
Definition: absorption.h:1148
LineRecord::Agam
Numeric Agam() const
Air broadened width in Hz/Pa:
Definition: absorption.h:634
joker
const Joker joker
LineRecord::mi0
Numeric mi0
Definition: absorption.h:1078
LineRecord::Nself
Numeric Nself() const
SGAM temperature exponent (dimensionless):
Definition: absorption.h:652
PLANCK_CONST
const Numeric PLANCK_CONST
Global constant, the Planck constant [Js].
LineRecord::Delta_O2
Numeric Delta_O2() const
F Pressure shift O2 in Hz/Pa :
Definition: absorption.h:747
LineRecord::Gam_N_CO2
Numeric Gam_N_CO2() const
GAM temp.
Definition: absorption.h:735
convMytranIER
void convMytranIER(Numeric &mdh, const Index &dh)
Definition: absorption.cc:2973
LineRecord::mn_he
Numeric mn_he
Definition: absorption.h:1150
convHitranIERSH
void convHitranIERSH(Numeric &mdh, const Index &dh)
Definition: absorption.cc:2914
LineRecord::A
Numeric A() const
Einstein A-coefficient in 1/s :
Definition: absorption.h:693
LineRecord::Gam_N_H2
Numeric Gam_N_H2() const
GAM temp.
Definition: absorption.h:738
operator<<
ostream & operator<<(ostream &os, const LineRecord &lr)
Output operator for LineRecord.
Definition: absorption.cc:80
Vector::resize
void resize(Index n)
Resize function.
Definition: matpackI.cc:771
exit_or_rethrow
void exit_or_rethrow(const String &m, ArtsOut &out)
Exit ARTS or re-throw error.
Definition: arts.cc:98
arts_omp_get_max_threads
int arts_omp_get_max_threads()
Wrapper for omp_get_max_threads.
Definition: arts_omp.cc:47
SpeciesMap
std::map< String, Index > SpeciesMap
The map associated with species_data.
Definition: absorption.cc:45
LineRecord::mdpsf
Numeric mdpsf
Definition: absorption.h:1111
ConstMatrixView::nrows
Index nrows() const
Returns the number of rows.
Definition: matpackI.cc:796
LineRecord::mpsf
Numeric mpsf
Definition: absorption.h:1076
refr_index_Boudouris
void refr_index_Boudouris(Vector &refr_index, ConstVectorView abs_p, ConstVectorView abs_t, ConstVectorView abs_h2o)
Calculates the refractive index at microwave frequncies following Boudouris 1963.
Definition: absorption.cc:2808
IsotopeRecord::Abundance
const Numeric & Abundance() const
Normal abundance ( = isotopic ratio).
Definition: absorption.h:238
LineRecord::mn_self
Numeric mn_self
Definition: absorption.h:1138
LineRecord::IsotopeData
const IsotopeRecord & IsotopeData() const
The matching IsotopeRecord from species_data.
Definition: absorption.cc:242
LineRecord::mnself
Numeric mnself
Definition: absorption.h:1090
CREATE_OUT1
#define CREATE_OUT1
Definition: messages.h:206
LineRecord::Delta_H2
Numeric Delta_H2() const
F Pressure shift H2 in Hz/Pa :
Definition: absorption.h:756
LineRecord::Delta_He
Numeric Delta_He() const
F Pressure shift He in Hz/Pa :
Definition: absorption.h:759
xsec_species
void xsec_species(MatrixView xsec, ConstVectorView f_grid, ConstVectorView abs_p, ConstVectorView abs_t, ConstVectorView abs_h2o_orig, ConstVectorView vmr, const ArrayOfLineRecord &abs_lines, const Index ind_ls, const Index ind_lsn, const Numeric cutoff, const Verbosity &verbosity)
Calculate line absorption cross sections for one tag group.
Definition: absorption.cc:2240
LineRecord::mdelta_o2
Numeric mdelta_o2
Definition: absorption.h:1155
LineRecord::mgamma_h2
Numeric mgamma_h2
Definition: absorption.h:1133
Array
This can be used to make arrays out of anything.
Definition: array.h:103
LineRecord::ReadFromHitranStream
bool ReadFromHitranStream(istream &is, const Verbosity &verbosity)
Read one line from a stream associated with a HITRAN 1986-2001 file.
Definition: absorption.cc:255
LineRecord::Elow
Numeric Elow() const
Lower state energy in cm^-1:
Definition: absorption.h:631
arts_omp_in_parallel
bool arts_omp_in_parallel()
Wrapper for omp_in_parallel.
Definition: arts_omp.cc:66
IsotopeRecord::mqcoeff
ArrayOfNumeric mqcoeff
Definition: absorption.h:300
LineRecord::SpeciesData
const SpeciesRecord & SpeciesData() const
The matching SpeciesRecord from species_data.
Definition: absorption.cc:224
LineRecord::mgamma_co2
Numeric mgamma_co2
Definition: absorption.h:1131
LineRecord::Psf
Numeric Psf() const
The pressure shift parameter in Hz/Pa.
Definition: absorption.h:605
CREATE_OUT3
#define CREATE_OUT3
Definition: messages.h:208
CREATE_OUT0
#define CREATE_OUT0
Definition: messages.h:205
LineRecord::mgamma_o2
Numeric mgamma_o2
Definition: absorption.h:1127
species_data
Array< SpeciesRecord > species_data
Definition: species_data.cc:40
messages.h
Declarations having to do with the four output streams.
LineRecord::Name
String Name() const
The full name of the species and isotope.
Definition: absorption.cc:207
LineRecord::mdelta_co2
Numeric mdelta_co2
Definition: absorption.h:1159
ConstMatrixView::ncols
Index ncols() const
Returns the number of columns.
Definition: matpackI.cc:802
TORR2PA
const Numeric TORR2PA
Global constant, converts torr to Pa.
my_basic_string
The implementation for String, the ARTS string class.
Definition: mystring.h:62
convHitranIERF
void convHitranIERF(Numeric &mdf, const Index &df)
Definition: absorption.cc:2867
LineRecord::mf
Numeric mf
Definition: absorption.h:1074
LineRecord::mti0
Numeric mti0
Definition: absorption.h:1080
LineRecord::misotope
Index misotope
Definition: absorption.h:1072
LineRecord::mdnself
Numeric mdnself
Definition: absorption.h:1109
LineRecord::Gamma_H2O
Numeric Gamma_H2O() const
Broadening parameter H2O in Hz/Pa :
Definition: absorption.h:711
LineRecord::dNself
Numeric dNself() const
Accuracy for SGAM temperature exponent in relative value:
Definition: absorption.h:687
LineRecord::Gamma_H2
Numeric Gamma_H2() const
Broadening parameter H2 in Hz/Pa :
Definition: absorption.h:717
LineRecord::G_upper
Numeric G_upper() const
Upper state stat.
Definition: absorption.h:696
SPEED_OF_LIGHT
const Numeric SPEED_OF_LIGHT
Global constant, spped of light in vaccum [m/s].
IsotopeRecord
Contains the lookup data for one isotope.
Definition: absorption.h:181
ConstVectorView::nelem
Index nelem() const
Returns the number of elements.
Definition: matpackI.cc:175
LineRecord::ReadFromJplStream
bool ReadFromJplStream(istream &is, const Verbosity &verbosity)
Read one line from a stream associated with a JPL file.
Definition: absorption.cc:1579
VectorView
The VectorView class.
Definition: matpackI.h:373
LineRecord::Delta_CO2
Numeric Delta_CO2() const
F Pressure shift CO2 in Hz/Pa :
Definition: absorption.h:753
SpeciesRecord::Isotope
const Array< IsotopeRecord > & Isotope() const
Definition: absorption.h:364
Numeric
NUMERIC Numeric
The type to use for all floating point numbers.
Definition: matpack.h:33
Verbosity
Definition: messages.h:50
LineRecord::mdelta_h2o
Numeric mdelta_h2o
Definition: absorption.h:1157
precision
#define precision
Definition: logic.cc:45
SpecIsoMap::Speciesindex
const Index & Speciesindex() const
Definition: absorption.h:1178
define_species_map
void define_species_map()
Define the species data map.
Definition: absorption.cc:70
LineRecord::Gam_N_O2
Numeric Gam_N_O2() const
GAM temp.
Definition: absorption.h:729
LineRecord::mn_o2
Numeric mn_o2
Definition: absorption.h:1142
math_funcs.h
LineRecord
Spectral line catalog data.
Definition: absorption.h:481
LineRecord::mdf
Numeric mdf
Definition: absorption.h:1099
ATM2PA
const Numeric ATM2PA
Global constant, converts atm to Pa.
refr_index_BoudourisDryAir
void refr_index_BoudourisDryAir(Vector &refr_index, ConstVectorView abs_p, ConstVectorView abs_t)
Calculates the refractive index for dry air at microwave frequncies following Boudouris 1963.
Definition: absorption.cc:2776
LineRecord::Gam_N_self
Numeric Gam_N_self() const
GAM temp.
Definition: absorption.h:723
LineRecord::magam
Numeric magam
Definition: absorption.h:1084
LineRecord::ReadFromArtscat4Stream
bool ReadFromArtscat4Stream(istream &is, const Verbosity &verbosity)
Read one line from a stream associated with an ARTSCAT-4 file.
Definition: absorption.cc:2020
LineRecord::mgamma_h2o
Numeric mgamma_h2o
Definition: absorption.h:1129
LineRecord::maux
ArrayOfNumeric maux
Definition: absorption.h:1094
SpeciesRecord
Contains the lookup data for one species.
Definition: absorption.h:307
max
#define max(a, b)
Definition: continua.cc:13097
my_basic_string::nelem
Index nelem() const
Number of elements.
Definition: mystring.h:242
LineshapeSpec
Lineshape related specification like which lineshape to use, the normalizationfactor,...
Definition: absorption.h:131
LineRecord::mspecies
Index mspecies
Definition: absorption.h:1070
LineRecord::mgupper
Numeric mgupper
Definition: absorption.h:1118
LineRecord::dSgam
Numeric dSgam() const
Accuracy for self broadened width in relative value :
Definition: absorption.h:681
LineRecord::dAgam
Numeric dAgam() const
Accuracy for air broadened width in relative value :
Definition: absorption.h:678
LineRecord::dF
Numeric dF() const
Accuracy for line position in Hz :
Definition: absorption.h:672
iso
void iso(Array< IsotopeRecord >::iterator &ii, String name, const ArrayOfNumeric &coeff)
Definition: partition_function_data.cc:708
Range
The range class.
Definition: matpackI.h:148
LineRecord::G_lower
Numeric G_lower() const
Lower state stat.
Definition: absorption.h:699
IsotopeRecord::Mass
const Numeric & Mass() const
Mass of the isotope.
Definition: absorption.h:241
LineRecord::mgamma_n2
Numeric mgamma_n2
Definition: absorption.h:1125
LineRecord::Gamma_CO2
Numeric Gamma_CO2() const
Broadening parameter CO2 in Hz/Pa :
Definition: absorption.h:714
wavenumber_to_joule
Numeric wavenumber_to_joule(Numeric e)
A little helper function to convert energy from units of wavenumber (cm^-1) to Joule (J).
Definition: absorption.cc:2845
LineRecord::ma
Numeric ma
Definition: absorption.h:1116
logic.h
Header file for logic.cc.
LineRecord::Gamma_self
Numeric Gamma_self() const
Broadening parameter self in Hz/Pa :
Definition: absorption.h:702
LineRecord::mtgam
Numeric mtgam
Definition: absorption.h:1092
SpeciesRecord::Name
const String & Name() const
Definition: absorption.h:362
LineRecord::Naux
Index Naux() const
Number of auxiliary parameters.
Definition: absorption.h:665
LineRecord::mn_h2o
Numeric mn_h2o
Definition: absorption.h:1144
LineRecord::Delta_H2O
Numeric Delta_H2O() const
F Pressure shift H2O in Hz/Pa :
Definition: absorption.h:750
LineRecord::Version
Index Version() const
Return the version number.
Definition: absorption.h:581
lineshape_data
Array< LineshapeRecord > lineshape_data
Definition: lineshapes.cc:2090
LineRecord::Gam_N_He
Numeric Gam_N_He() const
GAM temp.
Definition: absorption.h:741
LineRecord::msgam
Numeric msgam
Definition: absorption.h:1086
LineRecord::Gamma_O2
Numeric Gamma_O2() const
Broadening parameter O2 in Hz/Pa :
Definition: absorption.h:708
lineshape_norm_data
Array< LineshapeNormRecord > lineshape_norm_data
Definition: lineshapes.cc:2187
LineRecord::mdi0
Numeric mdi0
Definition: absorption.h:1101
Index
INDEX Index
The type to use for all integer numbers and indices.
Definition: matpack.h:39
LineRecord::mdelta_n2
Numeric mdelta_n2
Definition: absorption.h:1153
LineRecord::mdagam
Numeric mdagam
Definition: absorption.h:1103
arts_exit
void arts_exit(int status)
This is the exit function of ARTS.
Definition: arts.cc:42
LineRecord::mdelta_h2
Numeric mdelta_h2
Definition: absorption.h:1161
LineRecord::Tgam
Numeric Tgam() const
Reference temperature for AGAM and SGAM in K:
Definition: absorption.h:658
Vector
The Vector class.
Definition: matpackI.h:555
LineRecord::mglower
Numeric mglower
Definition: absorption.h:1120
LineRecord::F
Numeric F() const
The line center frequency in Hz.
Definition: absorption.h:599
is_sorted
bool is_sorted(ConstVectorView x)
Checks if a vector is sorted in ascending order.
Definition: logic.cc:238
LineRecord::Aux
const ArrayOfNumeric & Aux() const
Auxiliary parameters.
Definition: absorption.h:668
LineRecord::mdsgam
Numeric mdsgam
Definition: absorption.h:1105
ConstVectorView
A constant view of a Vector.
Definition: matpackI.h:300
LineRecord::ReadFromHitran2004Stream
bool ReadFromHitran2004Stream(istream &is, const Verbosity &verbosity)
Read one line from a stream associated with a HITRAN 2004 file.
Definition: absorption.cc:708
LineRecord::Gam_N_N2
Numeric Gam_N_N2() const
GAM temp.
Definition: absorption.h:726
Array::nelem
Index nelem() const
Number of elements.
Definition: array.h:172
LineRecord::mnair
Numeric mnair
Definition: absorption.h:1088
LineRecord::I0
Numeric I0() const
The line intensity in m^2*Hz at the reference temperature Ti0.
Definition: absorption.h:622
LineRecord::dPsf
Numeric dPsf() const
Accuracy for pressure shift in relative value :
Definition: absorption.h:690
LineRecord::ReadFromMytran2Stream
bool ReadFromMytran2Stream(istream &is, const Verbosity &verbosity)
Read one line from a stream associated with a MYTRAN2 file.
Definition: absorption.cc:1177
LineRecord::dI0
Numeric dI0() const
Accuracy for line intensity in relative value :
Definition: absorption.h:675
BOLTZMAN_CONST
const Numeric BOLTZMAN_CONST
Global constant, the Boltzmann constant [J/K].
arts.h
The global header file for ARTS.
LineRecord::Gamma_He
Numeric Gamma_He() const
Broadening parameter He in Hz/Pa :
Definition: absorption.h:720
LineRecord::Nair
Numeric Nair() const
AGAM temperature exponent (dimensionless):
Definition: absorption.h:646
LineRecord::mversion
Index mversion
Definition: absorption.h:1068
LineRecord::mn_n2
Numeric mn_n2
Definition: absorption.h:1140
IsotopeRecord::CalculatePartitionFctRatio
Numeric CalculatePartitionFctRatio(Numeric reference_temperature, Numeric actual_temperature) const
Calculate partition function ratio.
Definition: absorption.h:269
LineRecord::mdelta_he
Numeric mdelta_he
Definition: absorption.h:1163