ARTS  1.0.222
m_abs.cc
Go to the documentation of this file.
1 /* Copyright (C) 2000, 2001 Stefan Buehler <sbuehler@uni-bremen.de>
2  Patrick Eriksson <patrick@rss.chalmers.se>
3  Axel von Engeln <engeln@uni-bremen.de>
4  Thomas Kuhn <tkuhn@uni-bremen.de>
5 
6  This program is free software; you can redistribute it and/or modify it
7  under the terms of the GNU General Public License as published by the
8  Free Software Foundation; either version 2, or (at your option) any
9  later version.
10 
11  This program is distributed in the hope that it will be useful,
12  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  GNU General Public License for more details.
15 
16  You should have received a copy of the GNU General Public License
17  along with this program; if not, write to the Free Software
18  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
19  USA. */
20 
21 //
22 
32 #include <math.h>
33 #include <algorithm>
34 #include "arts.h"
35 #include "matpackI.h"
36 #include "array.h"
37 #include "messages.h"
38 #include "file.h"
39 #include "absorption.h"
40 #include "auto_wsv.h"
41 #include "auto_md.h"
42 #include "math_funcs.h"
43 #include "make_array.h"
44 #include "atm_funcs.h"
45 #include "continua.h"
46 #include "make_vector.h"
47 
54 void lines_per_tgSetEmpty(// WS Output:
55  ArrayOfArrayOfLineRecord& lines_per_tg,
56  // WS Input:
57  const TagGroups& tgs)
58 {
59  // Make lines_per_tg the right size:
60  lines_per_tg.resize( tgs.nelem() );
61 
62  for (Index i=0; i<tgs.nelem(); ++i)
63  {
64  lines_per_tg[i].resize(0);
65  }
66 }
67 
77 void linesReadFromHitran(// WS Output:
78  ArrayOfLineRecord& lines,
79  // Control Parameters:
80  const String& filename,
81  const Numeric& fmin,
82  const Numeric& fmax)
83 {
84  ifstream is;
85 
86  // Reset lines in case it already existed:
87  lines.resize(0);
88 
89  out2 << " Reading file: " << filename << '\n';
90  open_input_file(is, filename);
91 
92  bool go_on = true;
93  while ( go_on )
94  {
95  LineRecord lr;
96  if ( lr.ReadFromHitranStream(is) )
97  {
98  // If we are here the read function has reached eof and has
99  // returned no data.
100  go_on = false;
101  }
102  else
103  {
104  if ( fmin <= lr.F() )
105  {
106  if ( lr.F() <= fmax )
107  lines.push_back(lr);
108  else
109  go_on = false;
110  }
111  }
112  }
113  out2 << " Read " << lines.nelem() << " lines.\n";
114 }
115 
116 
126 void linesReadFromHitran2004(// WS Output:
127  ArrayOfLineRecord& lines,
128  // Control Parameters:
129  const String& filename,
130  const Numeric& fmin,
131  const Numeric& fmax)
132 {
133  ifstream is;
134 
135  // Reset lines in case it already existed:
136  lines.resize(0);
137 
138  out2 << " Reading file: " << filename << '\n';
139  open_input_file(is, filename);
140 
141  bool go_on = true;
142  while ( go_on )
143  {
144  LineRecord lr;
145  if ( lr.ReadFromHitran2004Stream(is) )
146  {
147  // If we are here the read function has reached eof and has
148  // returned no data.
149  go_on = false;
150  }
151  else
152  {
153  if ( fmin <= lr.F() )
154  {
155  if ( lr.F() <= fmax )
156  lines.push_back(lr);
157  else
158  go_on = false;
159  }
160  }
161  }
162  out2 << " Read " << lines.nelem() << " lines.\n";
163 }
164 
165 
166 void linesReadFromMytran2(// WS Output:
167  ArrayOfLineRecord& lines,
168  // Control Parameters:
169  const String& filename,
170  const Numeric& fmin,
171  const Numeric& fmax)
172 {
173  ifstream is;
174 
175  // Reset lines in case it already existed:
176  lines.resize(0);
177 
178  out2 << " Reading file: " << filename << '\n';
179  open_input_file(is, filename);
180 
181  bool go_on = true;
182  while ( go_on )
183  {
184  LineRecord lr;
185  if ( lr.ReadFromMytran2Stream(is) )
186  {
187  // If we are here the read function has reached eof and has
188  // returned no data.
189  go_on = false;
190  }
191  else
192  {
193  // lines are not necessarily frequency sorted
194  if ( fmin <= lr.F() )
195  if ( lr.F() <= fmax )
196  lines.push_back(lr);
197  }
198  }
199  out2 << " Read " << lines.nelem() << " lines.\n";
200 }
201 
202 
210 void linesReadFromJpl(// WS Output:
211  ArrayOfLineRecord& lines,
212  // Control Parameters:
213  const String& filename,
214  const Numeric& fmin,
215  const Numeric& fmax)
216 {
217  ifstream is;
218 
219  // Reset lines in case it already existed:
220  lines.resize(0);
221 
222  out2 << " Reading file: " << filename << '\n';
223  open_input_file(is, filename);
224 
225  bool go_on = true;
226  while ( go_on )
227  {
228  LineRecord lr;
229  if ( lr.ReadFromJplStream(is) )
230  {
231  // If we are here the read function has reached eof and has
232  // returned no data.
233  go_on = false;
234  }
235  else
236  {
237  // we expect lines to be sorted
238  if ( fmin <= lr.F() )
239  {
240  if ( lr.F() <= fmax )
241  lines.push_back(lr);
242  else
243  go_on = false;
244  }
245  }
246  }
247  out2 << " Read " << lines.nelem() << " lines.\n";
248 }
249 
250 
251 void linesReadFromArts(// WS Output:
252  ArrayOfLineRecord& lines,
253  // Control Parameters:
254  const String& filename,
255  const Numeric& fmin,
256  const Numeric& fmax)
257 {
258  // The input stream:
259  ifstream is;
260 
261  // We will use this line record to read in the line records in the
262  // file one after another:
263  LineRecord lr;
264 
265  // Reset lines in case it already existed:
266  lines.resize(0);
267 
268  out2 << " Reading file: " << filename << '\n';
269  open_input_file(is, filename);
270 
271  // Get version tag and check that it corresponds to the current version.
272  {
273  String v;
274  is >> v;
275  if ( v!=lr.Version() )
276  {
277  ostringstream os;
278 
279  // If what we read is the version String, it should have at elast 9 characters.
280  if ( 9 <= v.nelem() )
281  {
282  if ( "ARTSCAT" == v.substr(0,7) )
283  {
284  os << "The ARTS line file you are trying contains a version tag "
285  << "different from the current version.\n"
286  << "Tag in file: " << v << "\n"
287  << "Current version: " << lr.Version();
288  throw runtime_error(os.str());
289  }
290  }
291 
292  os << "The ARTS line file you are trying to read does not contain a valid version tag.\n"
293  << "Probably it was created with an older version of ARTS that used different units.";
294  throw runtime_error(os.str());
295  }
296  }
297 
298  bool go_on = true;
299  while ( go_on )
300  {
301  if ( lr.ReadFromArtsStream(is) )
302  {
303  // If we are here the read function has reached eof and has
304  // returned no data.
305  go_on = false;
306  }
307  else
308  {
309  // lines are not necessarily frequency sorted
310  if ( fmin <= lr.F() && lr.F() <= fmax )
311  {
312  lines.push_back(lr);
313  }
314  }
315  }
316  out2 << " Read " << lines.nelem() << " lines.\n";
317 }
318 
319 void linesElowToJoule(// WS Output:
320  ArrayOfLineRecord& lines )
321 {
322  for ( Index i=0; i<lines.nelem(); ++i )
323  lines[i].melow = wavenumber_to_joule(lines[i].melow);
324 }
325 
372  ArrayOfArrayOfLineRecord& lines_per_tg,
373  // WS Input:
374  const TagGroups& tgs,
375  // Control Parameters:
376  const ArrayOfString& filenames,
377  const ArrayOfString& formats,
378  const Vector& fmin,
379  const Vector& fmax)
380 {
381  const Index n_tg = tgs.nelem(); // # tag groups
382  const Index n_cat = filenames.nelem(); // # tag Catalogues
383 
384  // Check that dimensions of the keyword parameters are consistent
385  // (must all be the same).
386 
387  if ( n_cat != formats.nelem() ||
388  n_cat != fmin.nelem() ||
389  n_cat != fmax.nelem() )
390  {
391  ostringstream os;
392  os << "lines_per_tgReadFromCatalogues: All keyword\n"
393  << "parameters must get the same number of arguments.\n"
394  << "You specified:\n"
395  << "filenames: " << n_cat << "\n"
396  << "formats: " << formats.nelem() << "\n"
397  << "fmin: " << fmin.nelem() << "\n"
398  << "fmax: " << fmax.nelem();
399  throw runtime_error(os.str());
400  }
401 
402  // Furthermore, the dimension must be
403  // smaller than or equal to the number of tag groups.
404 
405  if ( n_cat > n_tg )
406  {
407  ostringstream os;
408  os << "lines_per_tgReadFromCatalogues: You specified more\n"
409  << "catalugues than you have tag groups.\n"
410  << "You specified:\n"
411  << "Catalogues: " << n_cat << "\n"
412  << "tgs: " << n_tg;
413  throw runtime_error(os.str());
414  }
415 
416  // There must be at least one tag group and at least one catalogue:
417 
418  if ( n_cat < 1 ||
419  n_tg < 1 )
420  {
421  ostringstream os;
422  os << "lines_per_tgReadFromCatalogues: You must have at\n"
423  << "least one catalogue and at least one tag group.\n"
424  << "You specified:\n"
425  << "Catalogues: " << n_cat << "\n"
426  << "tgs: " << n_tg;
427  throw runtime_error(os.str());
428  }
429 
430  // There can be repetitions in the keyword paramters. We want to read
431  // and process each catalogue only once, so we'll compile a set of
432  // real catalogues, along with a data structure that tells us which
433  // tag groups should use this catalogue.
434 
435  MakeArray<String> real_filenames ( filenames[0] );
436  MakeArray<String> real_formats ( formats[0] );
437  MakeArray<Numeric> real_fmin ( fmin[0] );
438  MakeArray<Numeric> real_fmax ( fmax[0] );
439 
440  Array< ArrayOfIndex > real_tgs(1);
441  real_tgs[0].resize(1);
442  real_tgs[0][0] = 0;
443 
444  // The last specified catalogue, to which we should assign all
445  // remaining lines. Index of this one in real_ arrays.
446  Index last_cat = 0;
447 
448  for ( Index i=1; i<n_tg; ++i )
449  {
450  // Is there a catalogue specified?
451  if ( n_cat > i )
452  {
453  // Yes, there is a catalogue.
454 
455  // Has this been specified before?
456  // We use the STL find algorithm to look for the catalogue
457  // name in the real_catalogues. Find returns an iterator, so
458  // to get an index we have to take the difference to
459  // .begin().
460  const Index that_cat =
461  (Index)(find( real_filenames.begin(),
462  real_filenames.end(),
463  filenames[i] ) - real_filenames.begin());
464  if ( that_cat < real_filenames.nelem() )
465  {
466  // Yes, it has been specified before
467  // ==> Assign to that catalogue
468  real_tgs[that_cat].push_back(i);
469 
470  // Verify, that format, fmin, and fmax are consistent:
471  if ( formats[i] != real_formats[that_cat] ||
472  fmin[i] != real_fmin[that_cat] ||
473  fmax[i] != real_fmax[that_cat] )
474  {
475  ostringstream os;
476  os << "lines_per_tgReadFromCatalogues: If you specify the\n"
477  << "same catalogue repeatedly, format, fmin, and fmax must be\n"
478  << "consistent. There is an inconsistency between\n"
479  << "catalogue " << that_cat << " and " << i << ".";
480  throw runtime_error(os.str());
481  }
482  }
483  else
484  {
485  // No, it has not been specified before.
486  // ==> Add an entry to real_tgs and the other real_ variables:
487  real_tgs.push_back( MakeArray<Index>(i) );
488 
489  real_filenames.push_back( filenames[i] );
490  real_formats.push_back ( formats[i] );
491  real_fmin.push_back ( fmin[i] );
492  real_fmax.push_back ( fmax[i] );
493 
494  last_cat = i; // assign remainder of lines to this
495  // catalogue, if there is no other catalogue.
496  }
497  }
498  else
499  {
500  // No, there is no catalogue.
501  // ==> Assign to the last catalogue
502  real_tgs[last_cat].push_back(i);
503  }
504  }
505 
506  Index n_real_cat = real_filenames.nelem(); // # real catalogues to read
507 
508  // Some output to low priority stream:
509  out3 << " Catalogues to read and tgs for which these will be used:\n";
510  for ( Index i=0; i<n_real_cat; ++i )
511  {
512  out3 << " " << real_filenames[i] << ":";
513  for ( Index s=0; s<real_tgs[i].nelem(); ++s )
514  out3 << " " << real_tgs[i][s];
515  out3 << "\n";
516  }
517 
518  // Make lines_per_tg the right size:
519  lines_per_tg.resize( tgs.nelem() );
520 
521  // Loop through the catalogues to read:
522  for ( Index i=0; i<n_real_cat; ++i )
523  {
524  ArrayOfLineRecord lines;
525 
526  // Read catalogue:
527 
528  if ( "HITRAN96"==real_formats[i] )
529  {
530  linesReadFromHitran( lines, real_filenames[i], real_fmin[i], real_fmax[i] );
531  }
532  else if ( "HITRAN04"==real_formats[i] )
533  {
534  linesReadFromHitran2004( lines, real_filenames[i], real_fmin[i], real_fmax[i] );
535  }
536  else if ( "MYTRAN2"==real_formats[i] )
537  {
538  linesReadFromMytran2( lines, real_filenames[i], real_fmin[i], real_fmax[i] );
539  }
540  else if ( "JPL"==real_formats[i] )
541  {
542  linesReadFromJpl( lines, real_filenames[i], real_fmin[i], real_fmax[i] );
543  }
544  else if ( "ARTS"==real_formats[i] )
545  {
546  linesReadFromArts( lines, real_filenames[i], real_fmin[i], real_fmax[i] );
547  }
548  else
549  {
550  ostringstream os;
551  os << "lines_per_tgReadFromCatalogues: You specified the\n"
552  << "format `" << real_formats[i] << "', which is unknown.\n"
553  << "Allowd formats are: HITRAN96, HITRAN04, MYTRAN2, JPL, ARTS.";
554  throw runtime_error(os.str());
555  }
556 
557  // We need to make subset tgs for the groups that should
558  // be read from this catalogue.
559  TagGroups these_tgs(real_tgs[i].nelem());
560  for ( Index s=0; s<real_tgs[i].nelem(); ++s )
561  {
562  these_tgs[s] = tgs[real_tgs[i][s]];
563  }
564 
565  // Create these_lines_per_tg:
566  ArrayOfArrayOfLineRecord these_lines_per_tg;
567  lines_per_tgCreateFromLines( these_lines_per_tg, lines, these_tgs );
568 
569  // Put these lines in the right place in lines_per_tg:
570  for ( Index s=0; s<real_tgs[i].nelem(); ++s )
571  {
572  lines_per_tg[real_tgs[i][s]] = these_lines_per_tg[s];
573  }
574  }
575 }
576 
577 
578 void lines_per_tgCreateFromLines(// WS Output:
579  ArrayOfArrayOfLineRecord& lines_per_tg,
580  // WS Input:
581  const ArrayOfLineRecord& lines,
582  const TagGroups& tgs)
583 {
584  // The species lookup data:
585  extern const Array<SpeciesRecord> species_data;
586 
587  // As a safety feature, we will watch out for the case that a
588  // species is included in the calculation, but not all lines are
589  // used. For this we need an array to flag the used species:
590 
591  // For some weird reason, Arrays of bool do not work, although all
592  // other types seem to work fine. So in this single case, I'll use
593  // the stl vector directly. The other place where this is done is in
594  // the function executor in main.cc.
595  // FIXME: Fix this when Array<bool> works.
596  std::vector<bool> species_used (species_data.nelem(),false);
597 
598  // Make lines_per_tg the right size:
599  lines_per_tg = ArrayOfArrayOfLineRecord(tgs.nelem());
600 
601  // Unfortunately, MTL conatains a bug that leads to all elements of
602  // the outer Array of an Array<Array>> pointing to the same data
603  // after creation. So we need to fix this explicitly:
604  for ( Index i=0; i<lines_per_tg.nelem(); ++i )
605  lines_per_tg[i] = ArrayOfLineRecord();
606 
607  // Loop all lines in the input line list:
608  for ( Index i=0; i<lines.nelem(); ++i )
609  {
610  // Get a convenient reference to the current line:
611  const LineRecord& this_line = lines[i];
612 
613  // We have to test each tag group in turn (in the order in which
614  // they appear in the controlfile). The line is assigned to the
615  // first tag group that fits.
616 
617  // The flag found is used to break the for loops when the right
618  bool found = false;
619 
620  // We need to define j here, since we need the value outside the
621  // for loop:
622  Index j;
623 
624  // Loop the tag groups:
625  for ( j=0; j<tgs.nelem() && !found ; ++j )
626  {
627  // A tag group can contain several tags:
628  for ( Index k=0; k<tgs[j].nelem() && !found; ++k )
629  {
630  // Get a reference to the current tag (not really
631  // necessary, but makes for nicer notation below):
632  const OneTag& this_tag = tgs[j][k];
633 
634  // Now we will test different attributes of the line
635  // against matching attributes of the tag. If any
636  // attribute does not match, we continue with the next tag
637  // in the tag group. (Exception: Species, see just below.)
638 
639  // Test species. If this attribute does not match we don`t
640  // have to test the other tags in this group, since all
641  // tags must belong to the same species.
642  if ( this_tag.Species() != this_line.Species() ) break;
643 
644  // Test isotope. The isotope can either match directly, or
645  // the Isotope of the tag can be one larger than the
646  // number of isotopes, which means `all'. Test the second
647  // condition first, since this will probably be more often
648  // used.
649  if ( this_tag.Isotope() != this_line.SpeciesData().Isotope().nelem() )
650  if ( this_tag.Isotope() != this_line.Isotope() )
651  continue;
652 
653  // Test frequncy range we take both the lower (Lf) and the
654  // upper (Uf) border frequency to include the `equal' case.
655  // Both Lf and Uf can also be negative, which means `no limit'
656 
657  // Take the lower limit first:
658  if ( this_tag.Lf() >= 0 )
659  if ( this_tag.Lf() > this_line.F() )
660  continue;
661 
662  // Then the upper limit:
663  if ( this_tag.Uf() >= 0 )
664  if ( this_tag.Uf() < this_line.F() )
665  continue;
666 
667  // When we get here, this_tag has survived all tests. That
668  // means it matches the line perfectly!
669  found = true;
670  }
671  }
672 
673  // If a matching tag was found, this line can be used in the
674  // calculation. Add it to the line list for this tag group.
675  if (found)
676  {
677  // We have to use j-1 here, since j was still increased by
678  // one after the matching tag has been found.
679  lines_per_tg[j-1].push_back(this_line);
680 
681  // Flag this species as used, if not already done:
682  if ( !species_used[this_line.Species()] )
683  species_used[this_line.Species()] = true;
684  }
685  else
686  {
687  // Safety feature: Issue a warning messages if the lines for a
688  // species are only partly covered by tags.
689  if ( species_used[this_line.Species()] )
690  {
691  out2 << "Your tags include other lines of species "
692  << this_line.SpeciesData().Name()
693  << ",\n"
694  << "why do you not include line "
695  << i
696  << " (at "
697  << this_line.F()
698  << " Hz)?\n";
699  }
700  }
701  }
702 
703  // Write some information to the lowest priority output stream.
704  for (Index i=0; i<tgs.nelem(); ++i)
705  {
706  out3 << " " << i << ":";
707 
708  for (Index s=0; s<tgs[i].nelem(); ++s)
709  out3 << " " << tgs[i][s].Name();
710 
711  out3 << ": " << lines_per_tg[i].nelem() << " lines\n";
712  }
713 
714 }
715 
723 void lines_per_tgAddMirrorLines(// WS Output:
724  ArrayOfArrayOfLineRecord& lines_per_tg)
725 {
726  // We will simply append the mirror lines after the original
727  // lines. This way we don't have to make a backup copy of the
728  // original lines.
729 
730  for ( Index i=0; i<lines_per_tg.nelem(); ++i )
731  {
732  // Get a reference to the current list of lines to save typing:
733  ArrayOfLineRecord& ll = lines_per_tg[i];
734 
735  // For increased efficiency, reserve the necessary space:
736  ll.reserve(2*ll.nelem());
737 
738  // Loop through all lines of this tag group:
739  {
740  // It is important that we determine the size of ll *before*
741  // we start the loop. After all, we are adding elements. And
742  // we cerainly don't want to continue looping the newly added
743  // elements, we want to loop only the original elements.
744  Index n=ll.nelem();
745  for ( Index j=0; j<n; ++j )
746  {
747  LineRecord dummy = ll[j];
748  dummy.setF( -dummy.F() );
749  // cout << "Adding ML at f = " << dummy.F() << "\n";
750  ll.push_back(dummy);
751  }
752  }
753  }
754 
755 }
756 
767 void lines_per_tgCompact(// WS Output:
768  ArrayOfArrayOfLineRecord& lines_per_tg,
769  // WS Input:
770  const ArrayOfLineshapeSpec& lineshape,
771  const Vector& f_mono)
772 {
773 
774  // Make sure lines_per_tg and lineshape have the same dimension:
775  if ( lines_per_tg.nelem() != lineshape.nelem() )
776  {
777  ostringstream os;
778  os << "Dimension of lines_per_tg does\n"
779  << "not match that of lineshape.";
780  throw runtime_error(os.str());
781  }
782 
783  // Make sure that the frequency grid is properly sorted:
784  for ( Index s=0; s<f_mono.nelem()-1; ++s )
785  {
786  if ( f_mono[s+1] <= f_mono[s] )
787  {
788  ostringstream os;
789  os << "The frequency grid f_mono is not properly sorted.\n"
790  << "f_mono[" << s << "] = " << f_mono[s] << "\n"
791  << "f_mono[" << s+1 << "] = " << f_mono[s+1];
792  throw runtime_error(os.str());
793  }
794  }
795 
796  // Cycle through all tag groups:
797  for ( Index i=0; i<lines_per_tg.nelem(); ++i )
798  {
799  // Get cutoff frequency of this tag group:
800  Numeric cutoff = lineshape[i].Cutoff();
801 
802  // Check whether cutoff is defined:
803  if ( cutoff != -1)
804  {
805  // Get a reference to the current list of lines to save typing:
806  ArrayOfLineRecord& ll = lines_per_tg[i];
807 
808  // Calculate the borders:
809  Numeric upp = f_mono[f_mono.nelem()-1] + cutoff;
810  Numeric low = f_mono[0] - cutoff;
811 
812  // Cycle through all lines within this tag group.
814  for ( ArrayOfLineRecord::iterator j=ll.begin(); j<ll.end(); ++j )
815  {
816  // Center frequency:
817  const Numeric F0 = j->F();
818 
819  if ( ( F0 >= low) && ( F0 <= upp) )
820  {
821  // Build list of elements which should be kept
822  keep.push_back (j);
823  // The original implementation just erased the non-wanted
824  // elements from the array. Problem: On every erase the
825  // whole array will be copied which actually kills
826  // performance.
827  }
828  }
829 
830  // If next comparison is false, some elements have to be removed
831  if (keep.nelem () != ll.nelem ())
832  {
833  ArrayOfLineRecord nll;
834  // Copy all elements that should be kept to a new Array
836  = keep.begin(); j != keep.end(); j++)
837  {
838  nll.push_back (**j);
839  }
840  // Overwrite the old array with the new one
841  ll.resize (nll.nelem ());
842  ll = nll;
843  }
844  }
845  }
846 }
847 
848 
849 void linesWriteAscii(// WS Input:
850  const ArrayOfLineRecord& lines,
851  // Control Parameters:
852  const String& f)
853 {
854  String filename = f;
855 
856  // If filename is empty then set the default filename:
857  if ( "" == filename )
858  {
859  extern const String out_basename;
860  filename = out_basename+".lines.aa";
861  }
862 
863  ofstream os;
864 
865  out2 << " Writing file: " << filename << '\n';
866  open_output_file(os, filename);
867 
868  write_lines_to_stream(os,lines);
869 }
870 
871 
872 void lines_per_tgWriteAscii(// WS Input:
873  const ArrayOfArrayOfLineRecord& lines_per_tg,
874  // Control Parameters:
875  const String& f)
876 {
877  String filename = f;
878 
879  // If filename is empty then set the default filename:
880  if ( "" == filename )
881  {
882  extern const String out_basename;
883  filename = out_basename+".lines_per_tg.aa";
884  }
885 
886  ofstream os;
887 
888  out2 << " Writing file: " << filename << '\n';
889  open_output_file(os, filename);
890 
891  os << lines_per_tg.nelem() << '\n';
892 
893  for ( Index i=0; i<lines_per_tg.nelem(); ++i )
894  {
895  const ArrayOfLineRecord& lines = lines_per_tg[i];
896  write_lines_to_stream( os, lines );
897  }
898 }
899 
900 
901 void tgsDefine(// WS Output:
902  TagGroups& tgs,
903  // Control Parameters:
904  const ArrayOfString& tags)
905 {
906  tgs.resize(tags.nelem());
907 
908  //cout << "Tags: " << tags << "\n";
909 
910  // Each element of the array of Strings tags defines one tag
911  // group. Let's work through them one by one.
912  for ( Index i=0; i<tags.nelem(); ++i )
913  {
914  // There can be a comma separated list of tag definitions, so we
915  // need to break the String apart at the commas.
916  ArrayOfString tag_def;
917 
918  bool go_on = true;
919  String these_tags = tags[i];
920  while (go_on)
921  {
922  Index n = (Index)these_tags.find(',');
923  if ( n == these_tags.npos ) // npos indicates `not found'
924  {
925  // There are no more commas.
926  // cout << "these_tags: (" << these_tags << ")\n";
927  tag_def.push_back(these_tags);
928  go_on = false;
929  }
930  else
931  {
932  tag_def.push_back(these_tags.substr(0,n));
933  these_tags.erase(0,n+1);
934  }
935  }
936 
937  // tag_def now holds the different tag Strings for this group.
938  // cout << "tag_def =\n" << tag_def << endl;
939 
940  // Set size to zero, in case the method has been called before.
941  tgs[i].resize(0);
942 
943  for ( Index s=0; s<tag_def.nelem(); ++s )
944  {
945  // Remove leading whitespace, if there is any:
946  while ( ' ' == tag_def[s][0] ||
947  '\t' == tag_def[s][0] ) tag_def[s].erase(0,1);
948 
949  OneTag this_tag(tag_def[s]);
950 
951  // Safety check: For s>0 check that the tags belong to the same species.
952  if (s>0)
953  if ( tgs[i][0].Species() != this_tag.Species() )
954  throw runtime_error("Tags in a tag group must belong to the same species.");
955 
956  tgs[i].push_back(this_tag);
957  }
958  }
959 
960  // Print list of tag groups to the most verbose output stream:
961  out3 << " Defined tag groups:";
962  for ( Index i=0; i<tgs.nelem(); ++i )
963  {
964  out3 << "\n " << i << ":";
965  for ( Index s=0; s<tgs[i].nelem(); ++s )
966  {
967  out3 << " " << tgs[i][s].Name();
968  }
969  }
970  out3 << '\n';
971 
972 // cout << endl << endl << tgs << endl;
973 }
974 
975 void tgsDefineAllInScenario(// WS Output:
976  TagGroups& tgs,
977  // Control Parameters:
978  const String& basename)
979 {
980  // Species lookup data:
981  extern const Array<SpeciesRecord> species_data;
982 
983  // We want to make lists of included and excluded species:
984  ArrayOfString included(0), excluded(0);
985 
986  tgs.resize(0);
987 
988  for ( Index i=0; i<species_data.nelem(); ++i )
989  {
990  const String specname = species_data[i].Name();
991  const String filename = basename + "." + specname + ".aa";
992 
993  // Try to open VMR file:
994  try
995  {
996  ifstream file;
997  open_input_file(file, filename);
998 
999  // Ok, if we get here the file was found.
1000 
1001  // Add to included list:
1002  included.push_back(specname);
1003 
1004  // Convert name of species to a OneTag object:
1005  OneTag this_tag(specname);
1006 
1007  // Create Array of OneTags with length 1 (our tag group has only one tag):
1008  Array<OneTag> this_group(1);
1009  this_group[0] = this_tag;
1010 
1011  // Add this tag group to tgs:
1012  tgs.push_back(this_group);
1013  }
1014  catch (runtime_error x)
1015  {
1016  // Ok, the file for the species could not be found.
1017  excluded.push_back(specname);
1018  }
1019  }
1020 
1021  // Some nice output:
1022  out2 << " Included Species (" << included.nelem() << "):\n";
1023  for ( Index i=0; i<included.nelem(); ++i )
1024  out2 << " " << included[i] << "\n";
1025 
1026  out2 << " Excluded Species (" << excluded.nelem() << "):\n";
1027  for ( Index i=0; i<excluded.nelem(); ++i )
1028  out2 << " " << excluded[i] << "\n";
1029 }
1030 
1031 void lineshapeDefine(// WS Output:
1032  ArrayOfLineshapeSpec& lineshape,
1033  // WS Input:
1034  const TagGroups& tgs,
1035  const String& shape,
1036  const String& normalizationfactor,
1037  const Numeric& cutoff)
1038 {
1039  // Make lineshape and normalization factor data visible:
1042 
1043 
1044  // generate the right number of elements
1045  Index tag_sz = tgs.nelem();
1046  lineshape.resize(tag_sz);
1047 
1048  // Is this lineshape available?
1049  Index found0=-1;
1050  for ( Index i=0; i<lineshape_data.nelem() && (found0 == -1) ; ++i )
1051  {
1052  const String& str = lineshape_data[i].Name();
1053  if (str == shape)
1054  {
1055  out2 << " Selected lineshape: " << str << "\n";
1056  found0=i;
1057  }
1058  }
1059 
1060  // Is this normalization to the lineshape available?
1061  Index found1=-1;
1062  for ( Index i=0; i<lineshape_norm_data.nelem() && (found1 == -1); ++i )
1063  {
1064  const String& str = lineshape_norm_data[i].Name();
1065  if (str == normalizationfactor)
1066  {
1067  out2 << " Selected normalization factor : " << normalizationfactor << "\n";
1068 
1069  if ( (cutoff != -1) && (cutoff < 0.0) )
1070  throw runtime_error(" Cutoff must be -1 or positive.");
1071  out2 << " Selected cutoff frequency [Hz] : " << cutoff << "\n";
1072  found1=i;
1073  }
1074  }
1075 
1076 
1077  // did we find the lineshape and normalization factor?
1078  if (found0 == -1)
1079  throw runtime_error("Selected lineshape not available.");
1080  if (found1 == -1)
1081  throw runtime_error("Selected normalization to lineshape not available.");
1082 
1083 
1084  // now set the lineshape
1085  for (Index i=0; i<tag_sz; i++)
1086  {
1087  lineshape[i].SetInd_ls( found0 );
1088  lineshape[i].SetInd_lsn( found1 );
1089  lineshape[i].SetCutoff( cutoff );
1090  }
1091 }
1092 
1093 void lineshape_per_tgDefine(// WS Output:
1094  ArrayOfLineshapeSpec& lineshape,
1095  // WS Input:
1096  const TagGroups& tgs,
1097  const ArrayOfString& shape,
1098  const ArrayOfString& normalizationfactor,
1099  const Vector& cutoff )
1100 {
1101  // Make lineshape and normalization factor data visible:
1104 
1105  // check that the number of elements are equal
1106  Index tg_sz = tgs.nelem();
1107  if ( (tg_sz != shape.nelem()) ||
1108  (tg_sz != normalizationfactor.nelem()) ||
1109  (tg_sz != cutoff.nelem()) )
1110  {
1111  ostringstream os;
1112  os << "lineshape_per_tgDefine: number of elements does\n"
1113  << "not match the number of tag groups defined.";
1114  throw runtime_error(os.str());
1115  }
1116 
1117 
1118  // generate the right number of elements
1119  lineshape.resize(tg_sz);
1120 
1121  // Is this lineshape available?
1122  for (Index k=0; k<tg_sz; ++k)
1123  {
1124  Index found0=-1;
1125  for ( Index i=0; i<lineshape_data.nelem() && (found0 == -1); ++i )
1126  {
1127  const String& str = lineshape_data[i].Name();
1128  if (str == shape[k])
1129  {
1130  out2 << " Tag Group: [";
1131  for (Index s=0; s<tgs[k].nelem()-1; ++s)
1132  out2 << tgs[k][s].Name() << ", ";
1133  out2 << tgs[k][tgs[k].nelem()-1].Name() << "]\n";
1134  out2 << " Selected lineshape: " << str << "\n";
1135  found0=i;
1136  }
1137  }
1138 
1139  // Is this normalization to the lineshape available?
1140  Index found1=-1;
1141  for ( Index i=0; i<lineshape_norm_data.nelem() && (found1 == -1); ++i )
1142  {
1143  const String& str = lineshape_norm_data[i].Name();
1144  if (str == normalizationfactor[k])
1145  {
1146  out2 << " Selected normalization factor: " << normalizationfactor[k] << "\n";
1147  if ( (cutoff[k] != -1) && (cutoff[k] < 0.0) )
1148  throw runtime_error(" Cutoff must be -1 or positive.");
1149  out2 << " Selected cutoff frequency : " << cutoff[k] << "\n";
1150  found1=i;
1151  }
1152  }
1153 
1154 
1155  // did we find the lineshape and normalization factor?
1156  if (found0 == -1)
1157  {
1158  ostringstream os;
1159  os << "Selected lineshape not available: "<< shape[k] <<"\n";
1160  throw runtime_error(os.str());
1161  }
1162  if (found1 == -1)
1163  {
1164  ostringstream os;
1165  os << "Selected normalization to lineshape not available: "<<
1166  normalizationfactor[k] <<"\n";
1167  throw runtime_error(os.str());
1168  }
1169 
1170  // now set the lineshape variables
1171  lineshape[k].SetInd_ls( found0 );
1172  lineshape[k].SetInd_lsn( found1 );
1173  lineshape[k].SetCutoff( cutoff[k] );
1174  }
1175 }
1176 
1177 
1178 
1179 void raw_vmrsReadFromScenario(// WS Output:
1180  ArrayOfMatrix& raw_vmrs,
1181  // WS Input:
1182  const TagGroups& tgs,
1183  // Control Parameters:
1184  const String& basename)
1185 {
1186  // The species lookup data:
1187  extern const Array<SpeciesRecord> species_data;
1188 
1189  // We need to read one profile for each tag group.
1190  for ( Index i=0; i<tgs.nelem(); ++i )
1191  {
1192  // Determine the name.
1193  String name =
1194  basename + "." +
1195  species_data[tgs[i][0].Species()].Name() + ".aa";
1196 
1197  // Add an element for this tag group to the vmr profiles:
1198  raw_vmrs.push_back(Matrix());
1199 
1200  // Read the VMR:
1201  // (We use the workspace method MatrixReadAscii for this.)
1202  MatrixReadAscii(raw_vmrs[i],"",name);
1203 
1204  // state the source of profile.
1205  out3 << " " << species_data[tgs[i][0].Species()].Name()
1206  << " profile read from file: " << name << "\n";
1207  }
1208 }
1209 
1223 void raw_vmrsReadFromFiles(// WS Output:
1224  ArrayOfMatrix& raw_vmrs,
1225  // WS Input:
1226  const TagGroups& tgs,
1227  // Control Parameters:
1228  const ArrayOfString& seltags,
1229  const ArrayOfString& filenames,
1230  const String& basename)
1231 {
1232  // The species lookup data:
1233  extern const Array<SpeciesRecord> species_data;
1234  ArrayOfIndex i_seltags;
1235 
1236  // Get indices of seltags in tgs. The function will throw an error
1237  // unless each tg in seltags corresponds exactly to a tg
1238  // in tgs.
1239  get_tagindex_for_Strings( i_seltags, tgs, seltags );
1240 
1241  // Now we have to build an Array of the filenames to use for all the
1242  // tag groups. Initialize it with basename...
1243  ArrayOfString true_filenames(tgs.nelem());
1244  true_filenames = basename + '.';
1245 
1246  // Initialize to the standard scenario (see function
1247  // raw_vmrsReadFromScenario):
1248  for ( Index i=0; i<tgs.nelem(); ++i )
1249  {
1250  true_filenames[i] +=
1251  species_data[tgs[i][0].Species()].Name() + ".aa";
1252  // Should be identical to how the filenames are constructed in
1253  // raw_vmrsReadFromScenario!
1254  }
1255 
1256  // Replace the names of the tgs given in seltags with the names in
1257  // filenames:
1258  for ( Index i=0; i<seltags.nelem(); ++i )
1259  {
1260  true_filenames[i_seltags[i]] = filenames[i];
1261  }
1262 
1263  // Read the files:
1264  for ( Index i=0; i<tgs.nelem(); ++i )
1265  {
1266  // Add an element for this tag group to the vmr profiles:
1267  raw_vmrs.push_back(Matrix());
1268 
1269  // Read the VMR:
1270  // (We use the workspace method MatrixReadAscii for this.)
1271  MatrixReadAscii(raw_vmrs[i],"",true_filenames[i]);
1272 
1273  // state the source of profile.
1274  out3 << " " << species_data[tgs[i][0].Species()].Name()
1275  << " profile read from file: " << true_filenames[i] << "\n";
1276  }
1277 }
1278 
1346 void WaterVaporSaturationInClouds( // WS Input/Output
1347  Matrix& vmrs, // manipulates this WS
1348  Vector& p_abs, // manipulates this WS
1349  // WS Input
1350  const Vector& t_abs, // constant
1351  const TagGroups& tgs ) // constant
1352 {
1353 
1354  // make sure that the VMR and pressure grid are the same
1355  assert ( vmrs.ncols() == p_abs.nelem() );
1356 
1357  // The species lookup data
1358  extern const Array<SpeciesRecord> species_data;
1359  // cloud tag numbers:
1360  Index liquid_index = 1+tgs.nelem();
1361  Index ice_index = 1+tgs.nelem();
1362  Index h2o_index[tgs.nelem()];
1363 
1364  // check size of input vectors.
1365  assert ( t_abs.nelem() == p_abs.nelem() );
1366  assert ( vmrs.ncols() == p_abs.nelem() );
1367 
1368  // find tags for clouds and for water vapor
1369  Index u = 0;
1370  for ( Index i=0; i<tgs.nelem(); ++i )
1371  {
1372  String tag_name = species_data[tgs[i][0].Species()].Name();
1373  if (tag_name == "liquidcloud") // <=== liquid water clouds tag name
1374  {
1375  liquid_index = i;
1376  }
1377  if (tag_name == "icecloud") // <====== ice water clouds tag name
1378  {
1379  ice_index = i;
1380  }
1381  if (tag_name == "H2O") // <=========== water vapor tags to change VMR
1382  {
1383  h2o_index[u++] = i;
1384  //cout << "tag_name=" << tag_name << ", tag=" << i << ", u=" << u
1385  // << ", h2o_index[u]=" << h2o_index[u] << "\n";
1386  }
1387  }
1388 
1389 
1390  // if no water vapor profile is in use do not go further
1391  if (u < 1)
1392  {
1393  out2 << "WaterVaporSaturationInClouds: no H2O profile found to adjust for clouds.\n"
1394  << "Therefore no saturation calculation is performed\n";
1395  return;
1396  }
1397 
1398  // ------------------------< saturation over liquid water >------------------------
1399  // modify the water vapor profiles for saturation over liquid water in a liquid water cloud
1400  if ( (liquid_index >= 0) && (liquid_index < tgs.nelem()) )
1401  {
1402  // sauration over liquid water
1403  for (Index uu=0; uu<u; ++uu) // --- loop over all H2O tags
1404  {
1405  for (Index i=0; i<vmrs.ncols() ; ++i) // --- loop over altitude grid
1406  {
1407  if (vmrs(liquid_index,i) > 0.000) // --- cloud present or not?
1408  {
1409  // dry air part of the total pressure
1410  Numeric p_dry = p_abs[i] * ( 1.000e0 - vmrs(h2o_index[uu],i) );
1411  // water vapor saturation over liquid water
1412  Numeric e_s = WVSatPressureLiquidWater( t_abs[i] );
1413  // new total pressure = dry air pressure + water vapor saturation pressure
1414  p_abs[i] = e_s + p_dry;
1415  // new water vapor volume mixing ratio
1416  vmrs(h2o_index[uu],i) = e_s / p_abs[i];
1417  // check if VMR has strange value
1418  if ( (vmrs(h2o_index[uu],i) < 0.000e0) || (vmrs(h2o_index[uu],i) > 1.000e0) )
1419  {
1420  ostringstream os;
1421  os << "WaterVaporSaturationInClouds: The water vapor VMR value "
1422  << vmrs(h2o_index[uu],i) << "\n"
1423  << " looks strange after setting it to the saturation pressure over liquid water.";
1424  throw runtime_error(os.str());
1425  return;
1426  }
1427  }
1428  }
1429  }
1430  }
1431 
1432 
1433  // ------------------------< saturation over ice water >------------------------
1434  // modify the water vapor profiles for saturation over ice water in a ice water cloud
1435  if ( (ice_index >= 0) && (ice_index < tgs.nelem()) )
1436  {
1437  for (Index uu=0; uu<u; ++uu) // --- loop over all H2O tags
1438  {
1439  for (Index i=0; i<vmrs.ncols() ; ++i) // --- loop over altitude grid
1440  {
1441  if (vmrs(ice_index,i) > 0.000) // --- cloud present or not?
1442  {
1443  // dry air part of the total pressure
1444  Numeric p_dry = p_abs[i] * ( 1.000e0 - vmrs(h2o_index[uu],i) );
1445  // water vapor saturation over ice
1446  Numeric e_s = WVSatPressureIce( t_abs[i] );
1447  // new total pressure = dry air pressure + water vapor saturation pressure
1448  p_abs[i] = e_s + p_dry;
1449  // new water vapor volume mixing ratio
1450  vmrs(h2o_index[uu],i) = e_s / p_abs[i];
1451  // check if VMR has strange value
1452  if ( (vmrs(h2o_index[uu],i) < 0.000e0) || (vmrs(h2o_index[uu],i) > 1.000e0) )
1453  {
1454  ostringstream os;
1455  os << "WaterVaporSaturationInClouds: The water vapor VMR value "
1456  << vmrs(h2o_index[uu],i) << "\n"
1457  << " looks strange after setting it to the saturation pressure over ice.";
1458  throw runtime_error(os.str());
1459  return;
1460  }
1461  }
1462  }
1463  }
1464  }
1465 
1466  return;
1467 }
1468 
1469 
1470 
1483 void AtmFromRaw(// WS Output:
1484  Vector& t_abs,
1485  Vector& z_abs,
1486  Matrix& vmrs,
1487  // WS Input:
1488  const TagGroups& tgs,
1489  const Vector& p_abs,
1490  const Matrix& raw_ptz,
1491  const ArrayOfMatrix& raw_vmrs)
1492 {
1493 
1494  //---------------< 1. Interpolation of temperature and altitude >---------------
1495  {
1496  // Safety check: Make sure that raw_ptz really is a [x,3] matrix:
1497  if ( 3 != raw_ptz.ncols() )
1498  {
1499  ostringstream os;
1500  os << "The variable raw_ptz does not have the right dimensions,\n"
1501  << "ncols() should be 3, but is actually "<< raw_ptz.ncols();
1502  throw runtime_error(os.str());
1503  }
1504 
1505 
1506  // Contents of raw_ptz: p_raw is column 1, tz_raw is column 2-3.
1507 
1508  // Interpolate tz_raw to p_abs grid.
1509  // The reason why we take tz_raw as a matrix is that the
1510  // interpolation can then be done simultaneously, hence slightly
1511  // more efficient.
1512 
1513  // For the interpolated profiles:
1514  Matrix tz_intp( 2, p_abs.nelem() );
1515 
1516  interpp( tz_intp,
1517  raw_ptz(Range(joker),0),
1518  transpose(raw_ptz(Range(joker),Range(1,joker))),
1519  p_abs );
1520 
1521  // The first Matpack expression selects the first column of
1522  // raw_ptz as a vector. The second Matpack expression gives the
1523  // transpose of the last two columns of raw_ptz. The function
1524  // interpp can be called with these selections directly.
1525 
1526  // Extract t_abs:
1527  t_abs.resize( tz_intp.ncols() );
1528  t_abs = tz_intp(0,Range(joker)); // Matpack can copy the first row of
1529  // tz_intp to t_abs like this. But
1530  // t_abs has to have the right size!
1531 
1532  // Extract z_abs:
1533  z_abs.resize( tz_intp.ncols() );
1534  z_abs = tz_intp(1,Range(joker)); // Matpack can copy the second row of
1535  // tz_intp to t_abs like this. But
1536  // t_abs has to have the right size!
1537  }
1538 
1539  //---------------< 2. Interpolation of VMR profiles >---------------
1540  {
1541  // check size of input String vectors.
1542  assert ( tgs.nelem() == raw_vmrs.nelem() );
1543 
1544  // Make vmrs the right size:
1545  vmrs.resize( raw_vmrs.nelem(), p_abs.nelem() );
1546 
1547  // For sure, we need to loop through all VMR profiles:
1548  for ( Index j=0; j<raw_vmrs.nelem(); ++j )
1549  {
1550 
1551  // Get a reference to the profile we are concerned with:
1552  const Matrix& raw = raw_vmrs[j];
1553 
1554  // Raw should be a matrix with dimension [x,2], the first column
1555  // is the raw pressure grid, the second column the VMR values.
1556 
1557  // Safety check to ensure this:
1558  if ( 2 != raw.ncols() )
1559  {
1560  ostringstream os;
1561  os << "The variable raw_vmrs("
1562  << j
1563  << ") does not have the right dimensions,\n"
1564  << "ncols() should be 2, but is actually "<< raw.ncols();
1565  throw runtime_error(os.str());
1566  }
1567 
1568  // Interpolate the profile to the predefined pressure grid:
1569  //String tag_name = species_data[tgs[j][0].Species()].Name(); // name of the tag
1570  // if ( (tag_name == "liquidcloud") || (tag_name == "icecloud") )
1571  // {
1572  // // Interpolate linearly the cloud profiles
1573  // interpp_cloud( vmrs(j,Range(joker)),
1574  // raw(Range(joker),0),
1575  // raw(Range(joker),1),
1576  // p_abs );
1577  // out3 << "This VMR: " << vmrs(j,Range(joker)) << "\n";
1578  // }
1579  // else
1580  // {
1581  // Interpolate VMRs:
1582  interpp( vmrs(j,Range(joker)),
1583  raw(Range(joker),0),
1584  raw(Range(joker),1),
1585  p_abs );
1586  // out3 << "This VMR: " << vmrs(j,Range(joker)) << "\n";
1587  // }
1588  // The calls to interpp_cloud and inerpp contain some nice
1589  // Matpack features:
1590  // 1. vmrs(j,Range(joker)) selects the jth row of vmrs.
1591  // 2. raw(Range(joker),0) and raw(Range(joker),1) select the
1592  // first and second column of raw. We don't need transpose
1593  // here, since the selected objects are vectors.
1594  //
1595  // Note that you can call the interpolation functions directly
1596  // with these selections.
1597  }
1598  }
1599 }
1600 
1601 
1608 void hseSet(
1609  Vector& hse,
1610  const Numeric& pref,
1611  const Numeric& zref,
1612  const Numeric& g0,
1613  const Index& niter )
1614 {
1615  hse.resize( 5 );
1616 
1617  hse[0] = 1;
1618  hse[1] = pref;
1619  hse[2] = zref;
1620  hse[3] = g0;
1621  hse[4] = Numeric( niter );
1622 }
1623 
1631  Vector& hse,
1632  const Numeric& pref,
1633  const Numeric& zref,
1634  const Numeric& latitude,
1635  const Index& niter )
1636 {
1637 
1638  hse.resize( 5 );
1639 
1640  hse[0] = 1;
1641  hse[1] = pref;
1642  hse[2] = zref;
1643  hse[3] = g_of_lat(latitude);
1644  hse[4] = Numeric( niter );
1645 }
1646 
1654  Vector& hse,
1655  const Vector& p_abs,
1656  const Vector& z_abs,
1657  const Numeric& latitude,
1658  const Index& index,
1659  const Index& niter )
1660 {
1661 
1662  /* check index range */
1663  check_if_in_range( 0, (Numeric)p_abs.nelem()-1, (Numeric)index, "index" );
1664 
1665  hse.resize( 5 );
1666 
1667  hse[0] = 1;
1668  hse[1] = p_abs[index];
1669  hse[2] = z_abs[index];
1670  hse[3] = g_of_lat(latitude);
1671  hse[4] = Numeric( niter );
1672 }
1673 
1674 
1682  Vector& hse,
1683  const Vector& p_abs,
1684  const Vector& z_abs,
1685  const Numeric& g0,
1686  const Index& niter )
1687 {
1688  hseSet( hse, p_abs[0], z_abs[0], g0, niter );
1689 }
1690 
1691 
1692 
1699 void hseOff(
1700  Vector& hse )
1701 {
1702  hse.resize( 1 );
1703  hse[0] = 0;
1704 }
1705 
1706 
1707 
1708 // Algorithm based on equations from my (PE) thesis (page 274) and the book
1709 // Meteorology today for scientists and engineers by R.B. Stull (pages 9-10).
1710 //
1717 void hseCalc(
1718  Vector& z_abs,
1719  const Vector& p_abs,
1720  const Vector& t_abs,
1721  const Vector& h2o_abs,
1722  const Numeric& r_geoid,
1723  const Vector& hse )
1724 {
1725  check_if_bool( static_cast<Index>(hse[0]),
1726  "the HSE flag (first element of hse)");
1727 
1728  if ( hse[0] )
1729  {
1730  if ( hse.nelem() != 5 )
1731  throw runtime_error("The length of the *hse* vector must be 5.");
1732 
1733  const Index np = p_abs.nelem();
1734  Index i; // altitude index
1735  Numeric g; // gravitational acceleration
1736  Numeric r; // water mixing ratio in gram/gram
1737  Numeric tv; // virtual temperature
1738  Numeric dz; // step geometrical altitude
1739  Vector ztmp(np); // temporary storage for z_abs
1740 
1741  // Pick out values from hse
1742  const Numeric pref = hse[1];
1743  const Numeric zref = hse[2];
1744  const Numeric g0 = hse[3];
1745  const Index niter = Index( hse[4] );
1746 
1747  check_lengths( z_abs, "z_abs", t_abs, "t_abs" );
1748  check_lengths( z_abs, "z_abs", h2o_abs, "h2o_abs" );
1749  if ( niter < 1 )
1750  throw runtime_error("The number of iterations must be > 0.");
1751 
1752  for ( Index iter=0; iter<niter; iter++ )
1753  {
1754  // Init ztmp
1755  ztmp[0] = z_abs[0];
1756 
1757  // Calculate new altitudes (relative z_abs(1)) and store in ztmp
1758  for ( i=0; i<np-1; i++ )
1759  {
1760  // Calculate g
1761  g = ( g_of_z(r_geoid,g0,z_abs[i]) +
1762  g_of_z(r_geoid,g0,z_abs[i+1]) ) / 2.0;
1763 
1764  // Calculate weight mixing ratio for water assuming constant average
1765  // molecular weight of the air
1766  r = 18/28.96 * (h2o_abs[i]+h2o_abs[i+1])/2;
1767 
1768  // The virtual temperature (no liquid water)
1769  tv = (1+0.61*r) * (t_abs[i]+t_abs[i+1])/2;
1770 
1771  // The change in vertical altitude from i to i+1
1772  dz = 287.053*tv/g * log( p_abs[i]/p_abs[i+1] );
1773  ztmp[i+1] = ztmp[i] + dz;
1774  }
1775 
1776  // Match the altitude of the reference point
1777  dz = interpp( p_abs, ztmp, pref ) - zref;
1778 
1779  // z_abs = ztmp - dz;
1780  z_abs = ztmp;
1781  z_abs -= dz;
1782  }
1783  }
1784 }
1785 
1786 
1794  Vector& h2o_abs,
1795  const TagGroups& tgs,
1796  const Matrix& vmrs )
1797 {
1798  const Index n = tgs.nelem();
1799  Index found = -1;
1800  String s;
1801 
1802  for( Index i=0; i<n && found<0; i++ )
1803  {
1804  s = tgs[i][0].Name();
1805 
1806  if ( s.substr(0,4) == "H2O-" )
1807  found = i;
1808  }
1809 
1810  /* ----- original version -------------------------------------------
1811 
1812  if ( found < 0 )
1813  throw runtime_error("h2o_absSet: No tag group contains water!");
1814 
1815  h2o_abs.resize( vmrs.ncols() );
1816  h2o_abs = vmrs(found,Range(joker));
1817  // Matpack can copy the contents of vectors like this. The
1818  // dimensions must be the same! The expression
1819  // vmrs(found,Range(joker)) selects the row with index corresponding
1820  // to found.
1821 
1822  ---------------------------------------------------------------------
1823  */
1824 
1825  h2o_abs.resize( vmrs.ncols() );
1826  if ( found >= 0 )
1827  {
1828  h2o_abs = vmrs(found,Range(joker));
1829  } else {
1830  out2 << " WARNING in h2o_absSet: could not find any H2O tag. So H2O vmr is set to zero!\n";
1831  for( Index i=0; i<h2o_abs.nelem(); i++ ) h2o_abs[i] = 0.0000000000e0;
1832  }
1833 
1834 
1835 
1836 
1837 }
1838 
1839 
1840 
1841 
1849  Matrix& vmrs,
1850  const TagGroups& tgs,
1851  const ArrayOfString& scaltgs,
1852  const Vector& scalfac)
1853 {
1854  Index itag;
1855  ArrayOfIndex tagindex;
1856 
1857  if ( scalfac.nelem() != scaltgs.nelem() )
1858  throw runtime_error("vmrScale: Number of tgs and fac are different!");
1859 
1860  get_tagindex_for_Strings( tagindex, tgs, scaltgs );
1861 
1862  const Index n = tagindex.nelem();
1863 
1864  for ( itag=0; itag<n; itag++ )
1865  {
1866  //out2 << scalfac[itag] << ".\n";
1867  vmrs(tagindex[itag],Range(joker)) *= scalfac[itag];
1868  // Matpack can multiply all elements of a vector with a constant
1869  // factor like this. In this case the vector is the selected row
1870  // of Matrix vmrs.
1871 
1872  //out2 << vmrs(tagindex[itag],Range(joker)) << ".\n";
1873  }
1874 }
1875 
1876 
1877 
1887  Vector& n2_abs,
1888  const TagGroups& tgs,
1889  const Matrix& vmrs )
1890 {
1891  const Index n = tgs.nelem();
1892  Index found = -1;
1893  String s;
1894 
1895  for( Index i=0; i<n && found<0; i++ )
1896  {
1897  s = tgs[i][0].Name();
1898 
1899  if ( s.substr(0,3) == "N2-" )
1900  found = i;
1901  }
1902 
1903  /* ----- original version -------------------------------------------
1904 
1905  if ( found < 0 )
1906  throw runtime_error("n2_absSet: No tag group contains nitrogen!");
1907 
1908  n2_abs.resize( vmrs.ncols() );
1909  n2_abs = vmrs(found,Range(joker));
1910  // Matpack can copy the contents of vectors like this. The
1911  // dimensions must be the same! The expression
1912  // vmrs(found,Range(joker)) selects the row with index corresponding
1913  // to found.
1914 
1915  ---------------------------------------------------------------------
1916  */
1917 
1918  n2_abs.resize( vmrs.ncols() );
1919  if ( found >= 0 )
1920  {
1921  n2_abs = vmrs(found,Range(joker));
1922  } else {
1923  out2 << " WARNING in n2_absSet: could not find any N2 tag. So N2 vmr is set to zero!\n";
1924  for( Index i=0; i<n2_abs.nelem(); i++ ) n2_abs[i] = 0.0000000000e0;
1925  }
1926 }
1927 
1928 
1956 void absCalc(// WS Output:
1957  Matrix& abs,
1958  ArrayOfMatrix& abs_per_tg,
1959  // WS Input:
1960  const TagGroups& tgs,
1961  const Vector& f_mono,
1962  const Vector& p_abs,
1963  const Vector& t_abs,
1964  const Vector& n2_abs,
1965  const Vector& h2o_abs,
1966  const Matrix& vmrs,
1967  const ArrayOfArrayOfLineRecord& lines_per_tg,
1968  const ArrayOfLineshapeSpec& lineshape,
1969  const ArrayOfString& cont_description_names,
1970  const ArrayOfString& cont_description_models,
1971  const ArrayOfVector& cont_description_parameters)
1972 {
1973  // Dimension checks are performed in the executed functions
1974 
1975  // allocate local variable to hold the cross sections per tag group
1976  ArrayOfMatrix xsec_per_tg;
1977 
1978  xsec_per_tgInit( xsec_per_tg, tgs, f_mono, p_abs );
1979 
1980  xsec_per_tgAddLines( xsec_per_tg,
1981  tgs,
1982  f_mono,
1983  p_abs,
1984  t_abs,
1985  h2o_abs,
1986  vmrs,
1987  lines_per_tg,
1988  lineshape );
1989 
1990  xsec_per_tgAddConts( xsec_per_tg,
1991  tgs,
1992  f_mono,
1993  p_abs,
1994  t_abs,
1995  n2_abs,
1996  h2o_abs,
1997  vmrs,
1998  cont_description_names,
1999  cont_description_parameters,
2000  cont_description_models);
2001 
2003  abs_per_tg,
2004  xsec_per_tg,
2005  vmrs );
2006 
2007 }
2008 
2034 void absCalcSaveMemory(// WS Output:
2035  Matrix& abs,
2036  // WS Input:
2037  const TagGroups& tgs,
2038  const Vector& f_mono,
2039  const Vector& p_abs,
2040  const Vector& t_abs,
2041  const Vector& n2_abs,
2042  const Vector& h2o_abs,
2043  const Matrix& vmrs,
2044  const ArrayOfArrayOfLineRecord& lines_per_tg,
2045  const ArrayOfLineshapeSpec& lineshape,
2046  const ArrayOfString& cont_description_names,
2047  const ArrayOfString& cont_description_models,
2048  const ArrayOfVector& cont_description_parameters)
2049 {
2050  // Dimension checks are performed in the executed functions
2051 
2052  // Allocate local variable to hold the cross sections per tag group:
2053  ArrayOfMatrix xsec_per_tg;
2054 
2055  // Allocate local variable to hold the absorption for each tag group:
2056  Matrix this_abs;
2057 
2058  // Allocate local variable to hold abs_per_tg for each tag
2059  // group. This is just a dummy, we need it, since it is a formal
2060  // argument of absCalcFromXsec.
2061  ArrayOfMatrix this_abs_per_tg;
2062 
2063  // Define variable to hold a dummy list of tag groups with only 1 element:
2064  TagGroups this_tg(1);
2065 
2066  // Local list of VMRs, only 1 element:
2067  Matrix this_vmr(1,p_abs.nelem());
2068 
2069  // Local lines_per_tg, only 1 element:
2070  ArrayOfArrayOfLineRecord these_lines(1);
2071 
2072  // Local lineshape list, only 1 element:
2073  ArrayOfLineshapeSpec this_lineshape(1);
2074 
2075  // Initialize the output variable abs:
2076  abs.resize( f_mono.nelem(), p_abs.nelem() );
2077  abs = 0; // Matpack can set all elements like this.
2078 
2079  out2 << " Number of tag groups to do: " << tgs.nelem() << "\n";
2080 
2081  // Loop over all species:
2082  for ( Index i=0; i<tgs.nelem(); ++i )
2083  {
2084  out2 << " Doing tag group " << i << ".\n";
2085 
2086  // Get a dummy list of tag groups with only the current element:
2087  this_tg[0].resize(tgs[i].nelem());
2088  this_tg[0] = tgs[i];
2089 
2090  // VMR for this species:
2091  this_vmr(0,joker) = vmrs(i,joker);
2092 
2093  // List of lines:
2094  these_lines[0].resize(lines_per_tg[i].nelem());
2095  these_lines[0] = lines_per_tg[i];
2096 
2097  // List of lineshapes:
2098  this_lineshape[0] = lineshape[i];
2099 
2100  xsec_per_tgInit( xsec_per_tg, this_tg, f_mono, p_abs );
2101 
2102  xsec_per_tgAddLines( xsec_per_tg,
2103  this_tg,
2104  f_mono,
2105  p_abs,
2106  t_abs,
2107  h2o_abs,
2108  this_vmr,
2109  these_lines,
2110  this_lineshape );
2111 
2112  xsec_per_tgAddConts( xsec_per_tg,
2113  this_tg,
2114  f_mono,
2115  p_abs,
2116  t_abs,
2117  n2_abs,
2118  h2o_abs,
2119  this_vmr,
2120  cont_description_names,
2121  cont_description_parameters,
2122  cont_description_models);
2123 
2124  absCalcFromXsec(this_abs,
2125  this_abs_per_tg,
2126  xsec_per_tg,
2127  this_vmr );
2128 
2129  // Add absorption of this species to total absorption:
2130  assert(abs.nrows()==this_abs.nrows());
2131  assert(abs.ncols()==this_abs.ncols());
2132  abs += this_abs;
2133  }
2134 }
2135 
2136 
2152 void absCalcFromXsec(// WS Output:
2153  Matrix& abs,
2154  ArrayOfMatrix& abs_per_tg,
2155  // WS Input:
2156  const ArrayOfMatrix& xsec_per_tg,
2157  const Matrix& vmrs)
2158 {
2159  // Check that vmrs and xsec_per_tg really have compatible
2160  // dimensions. In vmrs there should be one row for each tg:
2161  if ( vmrs.nrows() != xsec_per_tg.nelem() )
2162  {
2163  ostringstream os;
2164  os << "Variable vmrs must have compatible dimension to xsec_per_tg.\n"
2165  << "vmrs.nrows() = " << vmrs.nrows() << '\n'
2166  << "xsec_per_tg.nelem() = " << xsec_per_tg.nelem();
2167  throw runtime_error(os.str());
2168  }
2169 
2170  // Check that number of altitudes are compatible. We only check the
2171  // first element, this is possilble because within arts all elements
2172  // are on the same altitude grid.
2173  if ( vmrs.ncols() != xsec_per_tg[0].ncols() )
2174  {
2175  ostringstream os;
2176  os << "Variable vmrs must have same numbers of altitudes as xsec_per_tg.\n"
2177  << "vmrs.ncols() = " << vmrs.ncols() << '\n'
2178  << "xsec_per_tg[0].ncols() = " << xsec_per_tg[0].ncols();
2179  throw runtime_error(os.str());
2180  }
2181 
2182  // Initialize abs and abs_per_tg. The array dimension of abs_per_tg
2183  // is the same as that of xsec_per_tg. The dimension of abs should
2184  // be equal to one of the xsec_per_tg enries.
2185  abs.resize( xsec_per_tg[0].nrows(), xsec_per_tg[0].ncols() );
2186  abs = 0; // Matpack can set all elements like this.
2187 
2188  abs_per_tg.resize( xsec_per_tg.nelem() );
2189 
2190  out2 << " Computing abs and abs_per_tg from xsec_per_tg.\n";
2191 
2192  // Loop through all tag groups
2193  for ( Index i=0; i<xsec_per_tg.nelem(); ++i )
2194  {
2195  out2 << " Tag group " << i << '\n';
2196 
2197  // Make this element of xsec_per_tg the right size:
2198  abs_per_tg[i].resize( xsec_per_tg[i].nrows(), xsec_per_tg[i].ncols() );
2199  abs_per_tg[i] = 0; // Initialize all elements to 0.
2200 
2201  // Loop through all altitudes
2202  for ( Index j=0; j<xsec_per_tg[i].ncols(); j++)
2203  {
2204  // Loop through all frequencies
2205  for ( Index k=0; k<xsec_per_tg[i].nrows(); k++)
2206  {
2207  abs_per_tg[i](k,j) = xsec_per_tg[i](k,j) * vmrs(i,j);
2208  }
2209  }
2210 
2211  // Add up to the total absorption:
2212  abs += abs_per_tg[i]; // In Matpack you can use the +=
2213  // operator to do elementwise addition.
2214  }
2215 }
2216 
2217 
2231 void xsec_per_tgInit(// WS Output:
2232  ArrayOfMatrix& xsec_per_tg,
2233  // WS Input:
2234  const TagGroups& tgs,
2235  const Vector& f_mono,
2236  const Vector& p_abs
2237  )
2238 {
2239  // Initialize xsec_per_tg. The array dimension of xsec_per_tg
2240  // is the same as that of lines_per_tg.
2241  xsec_per_tg.resize( tgs.nelem() );
2242 
2243  // Loop xsec_per_tg and make each matrix the right size,
2244  // initializing to zero:
2245  for ( Index i=0; i<tgs.nelem(); ++i )
2246  {
2247  // Make this element of abs_per_tg the right size:
2248  xsec_per_tg[i].resize( f_mono.nelem(), p_abs.nelem() );
2249  xsec_per_tg[i] = 0; // Matpack can set all elements like this.
2250  }
2251 
2252  out2 << " Initialized xsec_per_tg.\n"
2253  << " Number of frequencies : " << f_mono.nelem() << "\n"
2254  << " Number of pressure levels : " << p_abs.nelem() << "\n";
2255 }
2256 
2274 void xsec_per_tgAddLines(// WS Output:
2275  ArrayOfMatrix& xsec_per_tg,
2276  // WS Input:
2277  const TagGroups& tgs,
2278  const Vector& f_mono,
2279  const Vector& p_abs,
2280  const Vector& t_abs,
2281  const Vector& h2o_abs,
2282  const Matrix& vmrs,
2283  const ArrayOfArrayOfLineRecord& lines_per_tg,
2284  const ArrayOfLineshapeSpec& lineshape)
2285 {
2286  // Check that all paramters that should have the number of tag
2287  // groups as a dimension are consistent.
2288  {
2289  const Index n_tgs = tgs.nelem();
2290  const Index n_xsec = xsec_per_tg.nelem();
2291  const Index n_vmrs = vmrs.nrows();
2292  const Index n_lines = lines_per_tg.nelem();
2293  const Index n_shapes = lineshape.nelem();
2294 
2295  if ( n_tgs != n_xsec ||
2296  n_tgs != n_vmrs ||
2297  n_tgs != n_lines ||
2298  n_tgs != n_shapes )
2299  {
2300  ostringstream os;
2301  os << "The following variables must all have the same dimension:\n"
2302  << "tgs: " << tgs.nelem() << '\n'
2303  << "xsec_per_tg: " << xsec_per_tg.nelem() << '\n'
2304  << "vmrs: " << vmrs.nrows() << '\n'
2305  << "lines_per_tg: " << lines_per_tg.nelem() << '\n'
2306  << "lineshape: " << lineshape.nelem();
2307  throw runtime_error(os.str());
2308  }
2309  }
2310 
2311  // Print information:
2312  //
2313  out2 << " Calculating line spectra.\n";
2314  //
2315  // Uncomment the part below if you temporarily want detailed info about
2316  // transitions to be done
2317 
2318  // The variables defined here (in particular the frequency
2319  // conversion) are just to make the output nice. They are not used
2320  // in subsequent calculations.
2321  // cout << " Transitions to do: \n";
2322  // Index nlines = 0;
2323  // String funit;
2324  // Numeric ffac;
2325  // if ( f_mono[0] < 3e12 )
2326  // {
2327  // funit = "GHz"; ffac = 1e9;
2328  // }
2329  // else
2330  // {
2331  // extern const Numeric SPEED_OF_LIGHT;
2332  // funit = "cm-1"; ffac = SPEED_OF_LIGHT*100;
2333  // }
2334  // for ( Index i=0; i<lines_per_tg.nelem(); ++i )
2335  // {
2336  // for ( Index l=0; l<lines_per_tg[i].nelem(); ++l )
2337  // {
2338  // cout << " " << lines_per_tg[i][l].Name() << " @ "
2339  // << lines_per_tg[i][l].F()/ffac << " " << funit << " ("
2340  // << lines_per_tg[i][l].I0() << " "
2341  // << lines_per_tg[i][l].Agam() << ")\n";
2342  // nlines++;
2343  // }
2344  // }
2345  // out2 << " Total number of transistions : " << nlines << "\n";
2346 
2347  // Call xsec_species for each tag group.
2348  for ( Index i=0; i<tgs.nelem(); ++i )
2349  {
2350  out2 << " Tag group " << i
2351  << " (" << get_tag_group_name(tgs[i]) << "): ";
2352 
2353  // Get a pointer to the line list for the current species. This
2354  // is just so that we don't have to type lines_per_tg[i] over
2355  // and over again.
2356  const ArrayOfLineRecord& ll = lines_per_tg[i];
2357 
2358  // Also get a pointer to the lineshape specification:
2359  const LineshapeSpec& ls = lineshape[i];
2360 
2361  // Skip the call to xsec_per_tg if the line list is empty.
2362  if ( 0 < ll.nelem() )
2363  {
2364 
2365  // Get the name of the species. The member function name of a
2366  // LineRecord returns the full name (species + isotope). So
2367  // it is for us more convenient to get the species index
2368  // from the LineRecord member function Species(), and then
2369  // use this to look up the species name in species_data.
2370  extern const Array<SpeciesRecord> species_data;
2371  String species_name = species_data[ll[0].Species()].Name();
2372 
2373  // Get the name of the lineshape. For that we use the member
2374  // function Ind_ls() to the lineshape data ls, which returns
2375  // an index. With that index we can go into lineshape_data
2376  // to get the name.
2377  // We will need this for safety checks later on.
2379  String lineshape_name = lineshape_data[ls.Ind_ls()].Name();
2380 
2381 
2382  // The use of overlap parameters for oxygen lines only makes
2383  // sense if the special Rosenkranz lineshape is used
2384  // (Rosenkranz_Voigt_Drayson or Rosenkranz_Voigt_Kuntz6).
2385  // Likewise, the use of these lineshapes only makes sense if
2386  // overlap parameters are available. We will test both these
2387  // conditions.
2388 
2389  // First of all, let's find out if the species we are
2390  // dealing with is oxygen.
2391  if ( "O2" == species_name )
2392  {
2393  // Do we have overlap parameters in the aux fields of
2394  // the LineRecord?
2395  if ( 0 != ll[0].Naux() )
2396  {
2397  // Yes. So let's make sure that the lineshape is one
2398  // that can use these parameters.
2399  if ( "Rosenkranz_Voigt_Drayson" != lineshape_name &&
2400  "Rosenkranz_Voigt_Kuntz6" != lineshape_name )
2401  {
2402  ostringstream os;
2403  os
2404  << "You are using a line catalogue that contains auxiliary parameters to\n"
2405  << "take care of overlap for oxygen lines. But you are not using a\n"
2406  << "lineshape that uses these parameters. Use Rosenkranz_Voigt_Drayson or\n"
2407  << "Rosenkranz_Voigt_Kuntz6.";
2408  throw runtime_error(os.str());
2409  }
2410  }
2411  }
2412 
2413  // Now we go the opposite way. Let's see if the Rosenkranz
2414  // lineshapes are used.
2415  if ( "Rosenkranz_Voigt_Drayson" == lineshape_name ||
2416  "Rosenkranz_Voigt_Kuntz6" == lineshape_name )
2417  {
2418  // Is the species oxygen, as it should be?
2419  if ( "O2" != species_name )
2420  {
2421  ostringstream os;
2422  os
2423  << "You are trying to use one of the special Rosenkranz lineshapes with\n"
2424  << "overlap correction for a species other than oxygen. Your species is\n"
2425  << species_name << ".\n"
2426  << "Select another lineshape for this species.";
2427  throw runtime_error(os.str());
2428  }
2429  else
2430  {
2431  // Do we have overlap parameters in the aux fields of
2432  // the LineRecord?
2433  if ( 0 == ll[0].Naux() )
2434  {
2435  ostringstream os;
2436  os
2437  << "You are trying to use one of the special Rosenkranz lineshapes with\n"
2438  << "overlap correction. But your line file does not contain aux\n"
2439  << "parameters. (I've checked only the first LineRecord). Use a line file\n"
2440  << "with overlap parameters.";
2441  throw runtime_error(os.str());
2442  }
2443  }
2444  }
2445 
2446  out2 << ll.nelem() << " transitions\n";
2447  xsec_species( xsec_per_tg[i],
2448  f_mono,
2449  p_abs,
2450  t_abs,
2451  h2o_abs,
2452  vmrs(i,Range(joker)),
2453  ll,
2454  ls.Ind_ls(),
2455  ls.Ind_lsn(),
2456  ls.Cutoff());
2457  // Note that we call xsec_species with a row of vmrs,
2458  // selected by the above Matpack expression. This is
2459  // possible, because xsec_species is using Views.
2460  }
2461  else
2462  {
2463  out2 << ll.nelem() << " transitions, skipping\n";
2464  }
2465  }
2466 }
2467 
2491 void xsec_per_tgAddConts(// WS Output:
2492  ArrayOfMatrix& xsec_per_tg,
2493  // WS Input:
2494  const TagGroups& tgs,
2495  const Vector& f_mono,
2496  const Vector& p_abs,
2497  const Vector& t_abs,
2498  const Vector& n2_abs,
2499  const Vector& h2o_abs,
2500  const Matrix& vmrs,
2501  const ArrayOfString& cont_description_names,
2502  const ArrayOfVector& cont_description_parameters,
2503  const ArrayOfString& cont_description_models )
2504 {
2505  // Check that all paramters that should have the number of tag
2506  // groups as a dimension are consistent.
2507  {
2508  const Index n_tgs = tgs.nelem();
2509  const Index n_xsec = xsec_per_tg.nelem();
2510  const Index n_vmrs = vmrs.nrows();
2511 
2512  if ( n_tgs != n_xsec || n_tgs != n_vmrs )
2513  {
2514  ostringstream os;
2515  os << "The following variables must all have the same dimension:\n"
2516  << "tgs: " << tgs.nelem() << '\n'
2517  << "xsec_per_tg: " << xsec_per_tg.nelem() << '\n'
2518  << "vmrs: " << vmrs.nrows();
2519  throw runtime_error(os.str());
2520  }
2521  }
2522 
2523  // Check, that dimensions of cont_description_names and
2524  // cont_description_parameters are consistent...
2525  if ( cont_description_names.nelem() !=
2526  cont_description_parameters.nelem() )
2527  {
2528  for (Index i=0; i < cont_description_names.nelem(); ++i)
2529  {
2530  cout << "xsec_per_tgAddConts: " << i << " name : " << cont_description_names[i] << "\n";
2531  }
2532  for (Index i=0; i < cont_description_parameters.nelem(); ++i)
2533  {
2534  cout << "xsec_per_tgAddConts: " << i << " param: " << cont_description_parameters[i] << "\n";
2535  }
2536  for (Index i=0; i < cont_description_models.nelem(); ++i)
2537  {
2538  cout << "xsec_per_tgAddConts: " << i << " option: " << cont_description_models[i] << "\n";
2539  }
2540  ostringstream os;
2541  os << "The following variables must have the same dimension:\n"
2542  << "cont_description_names: " << cont_description_names.nelem() << '\n'
2543  << "cont_description_parameters: " << cont_description_parameters.nelem();
2544  throw runtime_error(os.str());
2545  }
2546 
2547  // ...and that indeed the names match valid continuum models:
2548  for ( Index i=0; i<cont_description_names.nelem(); ++i )
2549  {
2550  check_continuum_model(cont_description_names[i]);
2551  }
2552 
2553  out2 << " Calculating continuum spectra.\n";
2554 
2555  // Loop tag groups:
2556  for ( Index i=0; i<tgs.nelem(); ++i )
2557  {
2558  extern const Array<SpeciesRecord> species_data;
2559 
2560  // Go through the tags in the current tag group to see if they
2561  // are continuum tags:
2562  for ( Index s=0; s<tgs[i].nelem(); ++s )
2563  {
2564  // First of all, we have to make sure that this is not a
2565  // tag that means `all isotopes', because this should not
2566  // include continuum. For such tags, tag.Isotope() will
2567  // return the number of isotopes (i.e., one more than the
2568  // allowed index range).
2569  if ( tgs[i][s].Isotope() <
2570  species_data[tgs[i][s].Species()].Isotope().nelem() )
2571  {
2572  // If we get here, it means that the tag describes a
2573  // specific isotope. Could be a continuum tag!
2574 
2575  // The if clause below checks whether the abundance of this tag
2576  // is negative. (Negative abundance marks continuum tags.)
2577  // It does the following:
2578  //
2579  // 1. species_data contains the lookup table of species
2580  // specific data. We need the right entry in this
2581  // table. The index of this is obtained by calling member function
2582  // Species() on the tag. Thus we have:
2583  // species_data[tgs[i][s].Species()].
2584  //
2585  // 2. Member function Isotope() on the above biest gives
2586  // us the array of isotope specific data. This we have
2587  // to subscribe with the right isotope index, which we
2588  // get by calling member function Isotope on the
2589  // tag. Thus we have:
2590  // Isotope()[tgs[i][s].Isotope()]
2591  //
2592  // 3. Finally, from the isotope data we need to get the mixing
2593  // ratio by calling the member function Abundance().
2594  if ( 0 >
2595  species_data[tgs[i][s].Species()].Isotope()[tgs[i][s].Isotope()].Abundance() )
2596  {
2597  // We have identified a continuum tag!
2598 
2599  // Get only the continuum name. The full tag name is something like:
2600  // H2O-HITRAN96Self-*-*. We want only the `H2O-HITRAN96Self' part:
2601  const String name =
2602  species_data[tgs[i][s].Species()].Name() + "-"
2603  + species_data[tgs[i][s].Species()].Isotope()[tgs[i][s].Isotope()].Name();
2604 
2605  // Check that this corresponds to a valid continuum
2606  // model:
2607  check_continuum_model(name);
2608 
2609  // Check, if we have parameters for this model. For
2610  // this, the model name must be listed in
2611  // cont_description_names.
2612  const Index n =
2613  (Index)(find( cont_description_names.begin(),
2614  cont_description_names.end(),
2615  name ) - cont_description_names.begin());
2616 
2617  // n==cont_description_names.nelem() indicates that
2618  // the name was not found.
2619  if ( n==cont_description_names.nelem() )
2620  {
2621  ostringstream os;
2622  os << "Cannot find model " << name
2623  << " in cont_description_names.";
2624  throw runtime_error(os.str());
2625  }
2626 
2627  // Ok, the tag specifies a valid continuum model and
2628  // we have continuum parameters.
2629 
2630  out2 << " Adding " << name
2631  << " to tag group " << i << ".\n";
2632 
2633  // find the options for this continuum tag from the input array
2634  // of options. The actual field of the array is n:
2635  const String ContOption = cont_description_models[n];
2636 
2637  // Add the continuum for this tag. The parameters in
2638  // this call should be clear. The vmr is in
2639  // vmrs(i,Range(joker)). The other vmr variable, `h2o_abs'
2640  // contains the real H2O vmr, which is needed for
2641  // the oxygen continuum.
2642  xsec_continuum_tag( xsec_per_tg[i],
2643  name,
2644  cont_description_parameters[n],
2645  cont_description_models[n],
2646  f_mono,
2647  p_abs,
2648  t_abs,
2649  n2_abs,
2650  h2o_abs,
2651  vmrs(i,Range(joker)) );
2652  // Calling this function with a row of Matrix vmrs
2653  // is possible because it uses Views.
2654  }
2655  }
2656  }
2657  }
2658 
2659 }
2660 
2669 void abs_per_tgReduce(// WS Output:
2670  ArrayOfMatrix& abs_per_tg,
2671  // WS Input:
2672  const TagGroups& tgs,
2673  const TagGroups& wfs_tgs)
2674 {
2675 
2676  // Make a safety check that the dimensions of tgs and
2677  // abs_per_tg are the same (could happen that we call this workspace
2678  // method twice by accident).
2679  if ( abs_per_tg.nelem()!=tgs.nelem() )
2680  throw(runtime_error("The variables abs_per_tg and tgs must\n"
2681  "have the same dimension."));
2682 
2683  // Erase could be very inefficient in this case, since elements
2684  // behind the erased one are copied in order to fill the
2685  // gap. Therefore, we will construct a new abs_per_tg, and finally
2686  // use it to replace the old one.
2687  ArrayOfMatrix abs_per_tg_out( wfs_tgs.nelem() );
2688 
2689  // Go through the weighting function tag groups:
2690  for ( Index i=0; i<wfs_tgs.nelem(); ++i )
2691  {
2692  // Index to the elements of wfs_tgs in tgs:
2693  Index n;
2694  get_tag_group_index_for_tag_group( n, tgs, wfs_tgs[i] );
2695 
2696  abs_per_tg_out[i].resize( abs_per_tg[n].nrows(), abs_per_tg[n].ncols() );
2697  abs_per_tg_out[i] = abs_per_tg[n]; // Matpack can copy the contents of
2698  // matrices like this. The dimensions
2699  // must be the same!
2700  }
2701 
2702  // Copy the generated matrices back to abs_per_tg
2703  abs_per_tg.resize( wfs_tgs.nelem() );
2704  abs_per_tg = abs_per_tg_out; // FIXME: It should be checked whether
2705  // this works correctly. Does my Array
2706  // implementation work as it should?
2707 }
2708 
2709 
2710 
2711 //======================================================================
2712 // Methods related to refraction
2713 //======================================================================
2714 
2721 void refrSet(
2722  Index& refr,
2723  Index& refr_lfac,
2724  String& refr_model,
2725  const Index& on,
2726  const String& model,
2727  const Index& lfac )
2728 {
2729  check_if_bool( on, "on" );
2730  if ( lfac < 1 )
2731  throw runtime_error("The length factor cannot be smaller than 1.");
2732 
2733  refr = on;
2734  refr_lfac = lfac;
2735  refr_model = model;
2736 }
2737 
2738 
2739 
2746 void refrOff(
2747  Index& refr,
2748  Index& refr_lfac,
2749  String& refr_model )
2750 {
2751  refrSet( refr, refr_lfac, refr_model, 0, "", 1 );
2752  refr_lfac = 0;
2753 }
2754 
2755 
2756 
2763 void refrCalc (
2764  Vector& refr_index,
2765  const Vector& p_abs,
2766  const Vector& t_abs,
2767  const Vector& h2o_abs,
2768  const Index& refr,
2769  const String& refr_model )
2770 {
2771  check_if_bool( refr, "refr" );
2772 
2773  if ( refr == 0 )
2774  refr_index.resize( 0 );
2775 
2776  else
2777  {
2778  if ( refr_model == "Unity" )
2779  {
2780  const Index n = p_abs.nelem();
2781  refr_index.resize( n );
2782  refr_index = 1.0;
2783  }
2784 
2785  else if ( refr_model == "Boudouris" )
2786  refr_index_Boudouris( refr_index, p_abs, t_abs, h2o_abs );
2787 
2788  else if ( refr_model == "BoudourisDryAir" )
2789  refr_index_BoudourisDryAir( refr_index, p_abs, t_abs );
2790 
2791  else
2792  {
2793  ostringstream os;
2794  os << "Unknown refraction parameterization: " << refr_model << "\n"
2795  << "Existing parameterizations are: \n"
2796  << "Unity\n"
2797  << "Boudouris\n"
2798  << "BoudourisDryAir";
2799  throw runtime_error(os.str());
2800  }
2801  }
2802 }
2803 
2804 
2805 
2806 
2807 //======================================================================
2808 // Methods related to continua
2809 //======================================================================
2810 
2827 void cont_descriptionInit(// WS Output:
2828  ArrayOfString& names,
2829  ArrayOfString& options,
2831 {
2832  names.resize(0);
2833  options.resize(0);
2834  parameters.resize(0);
2835  out2 << " Initialized cont_description_names \n"
2836  " cont_description_models\n"
2837  " cont_description_parameters.\n";
2838 }
2839 
2840 
2851 void cont_descriptionAppend(// WS Output:
2852  ArrayOfString& cont_description_names,
2853  ArrayOfString& cont_description_models,
2854  ArrayOfVector& cont_description_parameters,
2855  // Control Parameters:
2856  const String& tagname,
2857  const String& model,
2858  const Vector& userparameters)
2859 {
2860  // First we have to check that name matches a continuum species tag.
2861  check_continuum_model(tagname);
2862 
2863  //cout << " + tagname: " << tagname << "\n";
2864  //cout << " + model: " << model << "\n";
2865  //cout << " + parameters: " << userparameters << "\n";
2866 
2867  // Add name and parameters to the apropriate variables:
2868  cont_description_names.push_back(tagname);
2869  cont_description_models.push_back(model);
2870  cont_description_parameters.push_back(userparameters);
2871 }
Matrix
The Matrix class.
Definition: matpackI.h:544
tgsDefineAllInScenario
void tgsDefineAllInScenario(TagGroups &tgs, const String &basename)
Definition: m_abs.cc:975
out2
Out2 out2
Level 2 output stream.
Definition: messages.cc:54
OneTag::Uf
Numeric Uf() const
The upper line center frequency in Hz: If this is <0 it means no upper limit.
Definition: absorption.h:1096
refr_index_Boudouris
void refr_index_Boudouris(Vector &refr_index, ConstVectorView p_abs, ConstVectorView t_abs, ConstVectorView h2o_abs)
Calculates the refractive index at microwave frequncies following Boudouris 1963.
Definition: absorption.cc:2842
auto_md.h
refr_index_BoudourisDryAir
void refr_index_BoudourisDryAir(Vector &refr_index, ConstVectorView p_abs, ConstVectorView t_abs)
Calculates the refractive index for dry air at microwave frequncies following Boudouris 1963.
Definition: absorption.cc:2810
absorption.h
Declarations required for the calculation of absorption coefficients.
atm_funcs.h
This file contains declerations of functions releated to atmospheric physics or geometry.
cont_descriptionAppend
void cont_descriptionAppend(ArrayOfString &cont_description_names, ArrayOfString &cont_description_models, ArrayOfVector &cont_description_parameters, const String &tagname, const String &model, const Vector &userparameters)
Append a continuum description to ‘cont_description_names’ and ‘cont_description_parameters’.
Definition: m_abs.cc:2851
ArrayOfLineRecord
Array< LineRecord > ArrayOfLineRecord
Holds a list of spectral line data.
Definition: absorption.h:1032
transpose
ConstMatrixView transpose(ConstMatrixView m)
Const version of transpose.
Definition: matpackI.h:2373
LineshapeSpec::Ind_ls
const Index & Ind_ls() const
Return the index of this lineshape.
Definition: absorption.h:139
h2o_absSet
void h2o_absSet(Vector &h2o_abs, const TagGroups &tgs, const Matrix &vmrs)
See the the online help (arts -d FUNCTION_NAME)
Definition: m_abs.cc:1793
raw_vmrsReadFromFiles
void raw_vmrsReadFromFiles(ArrayOfMatrix &raw_vmrs, const TagGroups &tgs, const ArrayOfString &seltags, const ArrayOfString &filenames, const String &basename)
Reads in the profiles from the specified files in filenames for the tag list seltags and for all the ...
Definition: m_abs.cc:1223
get_tag_group_name
String get_tag_group_name(const Array< OneTag > &tg)
Print the name of a tag group.
Definition: absorption.cc:2286
check_lengths
void check_lengths(const Vector &x1, const String &x1_name, const Vector &x2, const String &x2_name)
Checks that two vectors have the same length.
Definition: math_funcs.cc:527
LineRecord::Version
String Version() const
Return the version String.
Definition: absorption.h:521
tgsDefine
void tgsDefine(TagGroups &tgs, const ArrayOfString &tags)
Definition: m_abs.cc:901
Vector::resize
void resize(Index n)
Resize function.
Definition: matpackI.h:1467
linesReadFromMytran2
void linesReadFromMytran2(ArrayOfLineRecord &lines, const String &filename, const Numeric &fmin, const Numeric &fmax)
Definition: m_abs.cc:166
open_input_file
void open_input_file(ifstream &file, const String &name)
Open a file for reading.
Definition: file.cc:130
OneTag::Species
Index Species() const
Molecular species index.
Definition: absorption.h:1083
ConstMatrixView::nrows
Index nrows() const
Returns the number of rows.
Definition: matpackI.h:1491
hseCalc
void hseCalc(Vector &z_abs, const Vector &p_abs, const Vector &t_abs, const Vector &h2o_abs, const Numeric &r_geoid, const Vector &hse)
See the the online help (arts -d FUNCTION_NAME)
Definition: m_abs.cc:1717
n2_absSet
void n2_absSet(Vector &n2_abs, const TagGroups &tgs, const Matrix &vmrs)
See the the online help (arts -d FUNCTION_NAME) Just a copy of the function 'h2o_absSet' but now for ...
Definition: m_abs.cc:1886
lines_per_tgCreateFromLines
void lines_per_tgCreateFromLines(ArrayOfArrayOfLineRecord &lines_per_tg, const ArrayOfLineRecord &lines, const TagGroups &tgs)
Definition: m_abs.cc:578
get_tag_group_index_for_tag_group
void get_tag_group_index_for_tag_group(Index &tgs1_index, const TagGroups &tgs1, const Array< OneTag > &tg2)
Returns the index of the tag group tg2 within the array of tag groups tgs1.
Definition: absorption.cc:2233
LineRecord::ReadFromHitran2004Stream
bool ReadFromHitran2004Stream(istream &is)
Read one line from a stream associated with a HITRAN 2004 file.
Definition: absorption.cc:609
xsec_species
void xsec_species(MatrixView xsec, ConstVectorView f_mono, ConstVectorView p_abs, ConstVectorView t_abs, ConstVectorView h2o_abs, ConstVectorView vmr, const ArrayOfLineRecord &lines, const Index ind_ls, const Index ind_lsn, const Numeric cutoff)
Calculate line absorption cross sections for one tag group.
Definition: absorption.cc:2379
linesReadFromHitran
void linesReadFromHitran(ArrayOfLineRecord &lines, const String &filename, const Numeric &fmin, const Numeric &fmax)
Reads line data in the Hitran 1986-2001 format (100 characters/record).
Definition: m_abs.cc:77
array.h
This file contains the definition of Array.
joker
Joker joker
Define the global joker objekt.
Definition: constants.cc:233
refrCalc
void refrCalc(Vector &refr_index, const Vector &p_abs, const Vector &t_abs, const Vector &h2o_abs, const Index &refr, const String &refr_model)
See the the online help (arts -d FUNCTION_NAME)
Definition: m_abs.cc:2763
refrOff
void refrOff(Index &refr, Index &refr_lfac, String &refr_model)
See the the online help (arts -d FUNCTION_NAME)
Definition: m_abs.cc:2746
LineshapeSpec::Cutoff
const Numeric & Cutoff() const
Return the cutoff frequency (in Hz).
Definition: absorption.h:151
vmrsScale
void vmrsScale(Matrix &vmrs, const TagGroups &tgs, const ArrayOfString &scaltgs, const Vector &scalfac)
See the the online help (arts -d FUNCTION_NAME)
Definition: m_abs.cc:1848
continua.h
This header file contains all the declarations of the implemented continua and full absorption (lines...
LineRecord::ReadFromJplStream
bool ReadFromJplStream(istream &is)
Read one line from a stream associated with a JPL file.
Definition: absorption.cc:1474
matpackI.h
LineshapeSpec::Ind_lsn
const Index & Ind_lsn() const
Return the index of the normalization factor.
Definition: absorption.h:144
xsec_per_tgAddConts
void xsec_per_tgAddConts(ArrayOfMatrix &xsec_per_tg, const TagGroups &tgs, const Vector &f_mono, const Vector &p_abs, const Vector &t_abs, const Vector &n2_abs, const Vector &h2o_abs, const Matrix &vmrs, const ArrayOfString &cont_description_names, const ArrayOfVector &cont_description_parameters, const ArrayOfString &cont_description_models)
Calculates the continuum for each tag group and adds it to xsec_per_tg.
Definition: m_abs.cc:2491
lineshape_per_tgDefine
void lineshape_per_tgDefine(ArrayOfLineshapeSpec &lineshape, const TagGroups &tgs, const ArrayOfString &shape, const ArrayOfString &normalizationfactor, const Vector &cutoff)
Definition: m_abs.cc:1093
Array< Array< LineRecord > >
check_continuum_model
void check_continuum_model(const String &name)
An auxiliary functions that checks if a given continuum model is listed in species_data....
Definition: continua.cc:12724
linesReadFromArts
void linesReadFromArts(ArrayOfLineRecord &lines, const String &filename, const Numeric &fmin, const Numeric &fmax)
Definition: m_abs.cc:251
check_if_bool
void check_if_bool(const Index &x, const String &x_name)
Checks if an integer is 0 or 1.
Definition: math_funcs.cc:468
hseSet
void hseSet(Vector &hse, const Numeric &pref, const Numeric &zref, const Numeric &g0, const Index &niter)
See the the online help (arts -d FUNCTION_NAME)
Definition: m_abs.cc:1608
species_data
Array< SpeciesRecord > species_data
Definition: species_data.cc:36
messages.h
Declarations having to do with the four output streams.
LineRecord::ReadFromMytran2Stream
bool ReadFromMytran2Stream(istream &is)
Read one line from a stream associated with a MYTRAN2 file.
Definition: absorption.cc:1075
write_lines_to_stream
void write_lines_to_stream(ostream &os, const ArrayOfLineRecord &lines)
A helper function that writes lines in a line list to a stream.
Definition: absorption.cc:2309
ConstMatrixView::ncols
Index ncols() const
Returns the number of columns.
Definition: matpackI.h:1497
my_basic_string< char >
g_of_lat
Numeric g_of_lat(Numeric latitude)
Calculates the gravitational accelaration for a geocentric latitude.
Definition: atm_funcs.cc:340
abs
#define abs(x)
Definition: continua.cc:12946
LineRecord::ReadFromHitranStream
bool ReadFromHitranStream(istream &is)
Read one line from a stream associated with a HITRAN 1986-2001 file.
Definition: absorption.cc:159
hseOff
void hseOff(Vector &hse)
See the the online help (arts -d FUNCTION_NAME)
Definition: m_abs.cc:1699
lines_per_tgAddMirrorLines
void lines_per_tgAddMirrorLines(ArrayOfArrayOfLineRecord &lines_per_tg)
Adds mirror lines at negative frequencies to the lines_per_tg.
Definition: m_abs.cc:723
cont_descriptionInit
void cont_descriptionInit(ArrayOfString &names, ArrayOfString &options, ArrayOfVector &parameters)
Initializes the two continuum description WSVs, ‘cont_description_names’ and ‘cont_description_parame...
Definition: m_abs.cc:2827
Numeric
NUMERIC Numeric
The type to use for all floating point numbers.
Definition: arts.h:147
linesReadFromJpl
void linesReadFromJpl(ArrayOfLineRecord &lines, const String &filename, const Numeric &fmin, const Numeric &fmax)
Definition: m_abs.cc:210
ConstVectorView::nelem
Index nelem() const
Returns the number of elements.
Definition: matpackI.h:937
lines_per_tgReadFromCatalogues
void lines_per_tgReadFromCatalogues(ArrayOfArrayOfLineRecord &lines_per_tg, const TagGroups &tgs, const ArrayOfString &filenames, const ArrayOfString &formats, const Vector &fmin, const Vector &fmax)
This method can read lines from different line catalogues.
Definition: m_abs.cc:371
LineRecord::Isotope
Index Isotope() const
The index of the isotopic species that this line belongs to.
Definition: absorption.h:535
ArrayOfArrayOfLineRecord
Array< Array< LineRecord > > ArrayOfArrayOfLineRecord
Holds a lists of spectral line data for each tag group.
Definition: absorption.h:1037
lineshapeDefine
void lineshapeDefine(ArrayOfLineshapeSpec &lineshape, const TagGroups &tgs, const String &shape, const String &normalizationfactor, const Numeric &cutoff)
Definition: m_abs.cc:1031
SpeciesRecord::Isotope
const Array< IsotopeRecord > & Isotope() const
Definition: absorption.h:339
WVSatPressureLiquidWater
Numeric WVSatPressureLiquidWater(const Numeric t)
Definition: continua.cc:9268
make_array.h
Implements the class MakeArray, which is a derived class of Array, allowing explicit initialization.
math_funcs.h
Contains declerations of basic mathematical and vector/matrix functions.
LineRecord
Spectral line catalog data.
Definition: absorption.h:438
make_vector.h
The class MakeVector is a special kind of Vector that can be initialized explicitly from one or more ...
linesWriteAscii
void linesWriteAscii(const ArrayOfLineRecord &lines, const String &f)
Definition: m_abs.cc:849
xsec_per_tgAddLines
void xsec_per_tgAddLines(ArrayOfMatrix &xsec_per_tg, const TagGroups &tgs, const Vector &f_mono, const Vector &p_abs, const Vector &t_abs, const Vector &h2o_abs, const Matrix &vmrs, const ArrayOfArrayOfLineRecord &lines_per_tg, const ArrayOfLineshapeSpec &lineshape)
Calculates the line spectrum for each tag group and adds it to xsec_per_tg.
Definition: m_abs.cc:2274
xsec_per_tgInit
void xsec_per_tgInit(ArrayOfMatrix &xsec_per_tg, const TagGroups &tgs, const Vector &f_mono, const Vector &p_abs)
Initialize xsec_per_tg.
Definition: m_abs.cc:2231
LineRecord::setF
void setF(Numeric new_mf)
Set the line center frequency in Hz.
Definition: absorption.h:583
Matrix::resize
void resize(Index r, Index c)
Resize function.
Definition: matpackI.h:2237
LineRecord::Species
Index Species() const
The index of the molecular species that this line belongs to.
Definition: absorption.h:530
out_basename
String out_basename
The basename for the report file and for all other output files.
Definition: messages.cc:38
open_output_file
void open_output_file(ofstream &file, const String &name)
Open a file for writing.
Definition: file.cc:91
LineshapeSpec
Lineshape related specification like which lineshape to use, the normalizationfactor,...
Definition: absorption.h:123
OneTag
A tag group can consist of the sum of several of these.
Definition: absorption.h:1061
hseSetFromLatitude
void hseSetFromLatitude(Vector &hse, const Numeric &pref, const Numeric &zref, const Numeric &latitude, const Index &niter)
See the the online help (arts -d FUNCTION_NAME)
Definition: m_abs.cc:1630
g_of_z
Numeric g_of_z(Numeric r_geoid, Numeric g0, Numeric z)
Calculates the gravitational accelaration for a geometrical altitude.
Definition: atm_funcs.cc:322
Range
The range class.
Definition: matpackI.h:139
AtmFromRaw
void AtmFromRaw(Vector &t_abs, Vector &z_abs, Matrix &vmrs, const TagGroups &tgs, const Vector &p_abs, const Matrix &raw_ptz, const ArrayOfMatrix &raw_vmrs)
Interpolate atmospheric quantities from their individual grids to the common p_abs grid.
Definition: m_abs.cc:1483
out3
Out3 out3
Level 3 output stream.
Definition: messages.cc:56
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:2879
Index
INDEX Index
The type to use for all integer numbers and indices.
Definition: arts.h:153
lines_per_tgSetEmpty
void lines_per_tgSetEmpty(ArrayOfArrayOfLineRecord &lines_per_tg, const TagGroups &tgs)
See the the online help (arts -d FUNCTION_NAME)
Definition: m_abs.cc:54
LineRecord::ReadFromArtsStream
bool ReadFromArtsStream(istream &is)
Read one line from a stream associated with an Arts file.
Definition: absorption.cc:1718
SpeciesRecord::Name
const String & Name() const
Definition: absorption.h:337
raw_vmrsReadFromScenario
void raw_vmrsReadFromScenario(ArrayOfMatrix &raw_vmrs, const TagGroups &tgs, const String &basename)
Definition: m_abs.cc:1179
parameters
Parameters parameters
Holds the command line parameters.
Definition: parameters.cc:34
LineRecord::SpeciesData
const SpeciesRecord & SpeciesData() const
The matching SpeciesRecord from species_data.
Definition: absorption.h:556
hseSetFromLatitudeIndex
void hseSetFromLatitudeIndex(Vector &hse, const Vector &p_abs, const Vector &z_abs, const Numeric &latitude, const Index &index, const Index &niter)
See the the online help (arts -d FUNCTION_NAME)
Definition: m_abs.cc:1653
lineshape_data
Array< LineshapeRecord > lineshape_data
Definition: lineshapes.cc:2062
absCalcFromXsec
void absCalcFromXsec(Matrix &abs, ArrayOfMatrix &abs_per_tg, const ArrayOfMatrix &xsec_per_tg, const Matrix &vmrs)
Calculates the absorption from a given cross section.
Definition: m_abs.cc:2152
MatrixReadAscii
void MatrixReadAscii(Matrix &, const String &, const String &filename)
Definition: m_io.cc:371
interpp
void interpp(VectorView x, ConstVectorView p0, ConstVectorView x0, ConstVectorView p)
Interpolates a vertical profile at a new set of pressures.
Definition: atm_funcs.cc:658
OneTag::Isotope
Index Isotope() const
Isotopic species index.
Definition: absorption.h:1088
get_tagindex_for_Strings
void get_tagindex_for_Strings(ArrayOfIndex &tags1_index, const TagGroups &tags1, const ArrayOfString &tags2_Strings)
Returns the index among some tag groups for an array of tag Strings.
Definition: absorption.cc:2176
OneTag::Lf
Numeric Lf() const
The lower line center frequency in Hz.
Definition: absorption.h:1092
file.h
This file contains basic functions to handle ASCII and binary (HDF) data files.
MakeArray
Explicit construction of Arrays.
Definition: make_array.h:52
linesReadFromHitran2004
void linesReadFromHitran2004(ArrayOfLineRecord &lines, const String &filename, const Numeric &fmin, const Numeric &fmax)
Reads line data in the Hitran 2004 format (160 characters/record).
Definition: m_abs.cc:126
hseFromBottom
void hseFromBottom(Vector &hse, const Vector &p_abs, const Vector &z_abs, const Numeric &g0, const Index &niter)
See the the online help (arts -d FUNCTION_NAME)
Definition: m_abs.cc:1681
lineshape_norm_data
Array< LineshapeNormRecord > lineshape_norm_data
Definition: lineshapes.cc:2159
WaterVaporSaturationInClouds
void WaterVaporSaturationInClouds(Matrix &vmrs, Vector &p_abs, const Vector &t_abs, const TagGroups &tgs)
Calculates the water vapor saturation volume mixing ratio (VMR) in the vertical range where liquid or...
Definition: m_abs.cc:1346
linesElowToJoule
void linesElowToJoule(ArrayOfLineRecord &lines)
Definition: m_abs.cc:319
my_basic_string::npos
static const Index npos
Define npos:
Definition: mystring.h:87
abs_per_tgReduce
void abs_per_tgReduce(ArrayOfMatrix &abs_per_tg, const TagGroups &tgs, const TagGroups &wfs_tgs)
Reduces the size of abs_per_tg.
Definition: m_abs.cc:2669
Vector
The Vector class.
Definition: matpackI.h:389
LineRecord::F
Numeric F() const
The line center frequency in Hz.
Definition: absorption.h:580
lines_per_tgWriteAscii
void lines_per_tgWriteAscii(const ArrayOfArrayOfLineRecord &lines_per_tg, const String &f)
Definition: m_abs.cc:872
lines_per_tgCompact
void lines_per_tgCompact(ArrayOfArrayOfLineRecord &lines_per_tg, const ArrayOfLineshapeSpec &lineshape, const Vector &f_mono)
Removes all lines outside the defined lineshape cutoff frequency from the lines_per_tg,...
Definition: m_abs.cc:767
refrSet
void refrSet(Index &refr, Index &refr_lfac, String &refr_model, const Index &on, const String &model, const Index &lfac)
See the the online help (arts -d FUNCTION_NAME)
Definition: m_abs.cc:2721
absCalcSaveMemory
void absCalcSaveMemory(Matrix &abs, const TagGroups &tgs, const Vector &f_mono, const Vector &p_abs, const Vector &t_abs, const Vector &n2_abs, const Vector &h2o_abs, const Matrix &vmrs, const ArrayOfArrayOfLineRecord &lines_per_tg, const ArrayOfLineshapeSpec &lineshape, const ArrayOfString &cont_description_names, const ArrayOfString &cont_description_models, const ArrayOfVector &cont_description_parameters)
Calculates the absorption coefficients by first calculating the cross sections per tag group and then...
Definition: m_abs.cc:2034
Array::nelem
Index nelem() const
Number of elements.
Definition: array.h:115
xsec_continuum_tag
void xsec_continuum_tag(MatrixView xsec, const String &name, ConstVectorView parameters, const String &model, ConstVectorView f_mono, ConstVectorView p_abs, ConstVectorView t_abs, ConstVectorView n2_abs, ConstVectorView h2o_abs, ConstVectorView vmr)
Calculates model absorption for one continuum or full model tag.
Definition: continua.cc:9392
WVSatPressureIce
Numeric WVSatPressureIce(const Numeric t)
Definition: continua.cc:9333
check_if_in_range
void check_if_in_range(const Numeric &x_low, const Numeric &x_high, const Numeric &x, const String &x_name)
Checks if a numeric variable is inside a specified range.
Definition: math_funcs.cc:495
auto_wsv.h
Declares the enum type that acts as a handle for workspace variables. Also declares the workspace its...
arts.h
The global header file for ARTS.
ll
#define ll
Definition: continua.cc:14191
absCalc
void absCalc(Matrix &abs, ArrayOfMatrix &abs_per_tg, const TagGroups &tgs, const Vector &f_mono, const Vector &p_abs, const Vector &t_abs, const Vector &n2_abs, const Vector &h2o_abs, const Matrix &vmrs, const ArrayOfArrayOfLineRecord &lines_per_tg, const ArrayOfLineshapeSpec &lineshape, const ArrayOfString &cont_description_names, const ArrayOfString &cont_description_models, const ArrayOfVector &cont_description_parameters)
Calculates the absorption coefficients by first calculating the cross sections per tag group and then...
Definition: m_abs.cc:1956