ARTS  2.0.49
m_atmosphere.cc
Go to the documentation of this file.
1 /* Copyright (C) 2002-2008
2  Patrick Eriksson <Patrick.Eriksson@rss.chalmers.se>
3  Stefan Buehler <sbuehler@ltu.se>
4 
5  This program is free software; you can redistribute it and/or modify it
6  under the terms of the GNU General Public License as published by the
7  Free Software Foundation; either version 2, or (at your option) any
8  later version.
9 
10  This program is distributed in the hope that it will be useful,
11  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  GNU General Public License for more details.
14 
15  You should have received a copy of the GNU General Public License
16  along with this program; if not, write to the Free Software
17  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
18  USA. */
19 
20 
21 
22 /*===========================================================================
23  === File description
24  ===========================================================================*/
25 
40 /*===========================================================================
41  === External declarations
42  ===========================================================================*/
43 
44 #include <cmath>
45 #include <algorithm>
46 #include "agenda_class.h"
47 #include "arts.h"
48 #include "check_input.h"
49 #include "matpackIII.h"
50 #include "messages.h"
51 #include "special_interp.h"
52 #include "absorption.h"
53 #include "abs_species_tags.h"
54 #include "gridded_fields.h"
55 #include "interpolation.h"
56 #include "interpolation_poly.h"
57 #include "xml_io.h"
58 
59 extern const Index GFIELD3_P_GRID;
60 extern const Index GFIELD3_LAT_GRID;
61 extern const Index GFIELD3_LON_GRID;
62 extern const Index GFIELD4_FIELD_NAMES;
63 extern const Index GFIELD4_P_GRID;
64 extern const Index GFIELD4_LAT_GRID;
65 extern const Index GFIELD4_LON_GRID;
66 
67 extern const Numeric DEG2RAD;
68 
69 /*===========================================================================
70  *=== Helper functions
71  *===========================================================================*/
72 
74 
90  Index& nf,
91  const String& name,
92  const Verbosity&)
93 {
94  // Number of fields already present:
96 
97 // Most of the functionality moved from atm_fields_compactAddConstant when
98 // atm_fields_compactAddSpecies was added, in order to share the code.
99 //
100 // Commented out by Gerrit 2011-05-04. I believe this check is not needed.
101 // Oliver agrees. We can still infer the dimensions even if there are zero
102 // fields; e.g., the data might have dimensions (0, 4, 3, 8).
103 //
104 // if (0==nf)
105 // {
106 // ostringstream os;
107 // os << "The *atm_fields_compact* must already contain at least one field,\n"
108 // << "so that we can infer the dimensions from that.";
109 // throw runtime_error( os.str() );
110 // }
111 
112  // Add name of new field to field name list:
113  af.get_string_grid(GFIELD4_FIELD_NAMES).push_back(name);
114 
115  // Save original fields:
116  const Tensor4 dummy = af.data;
117 
118  // Adjust size:
119  af.resize( nf+1, dummy.npages(), dummy.nrows(), dummy.ncols() );
120  nf++; // set to new number of fields
121 
122  // Copy back original field:
123  af.data( Range(0,nf-1), Range(joker), Range(joker), Range(joker) ) = dummy;
124 }
125 
126 
127 
128 /*===========================================================================
129  === The functions (in alphabetical order)
130  ===========================================================================*/
131 
132 
133 // Workspace method, doxygen header will be auto-generated.
134 // 2007-07-25 Stefan Buehler
136  GriddedField4& af, // atm_fields_compact
137  // WS Input:
138  const Index& atmosphere_dim,
139  // WS Generic Input:
140  const Matrix& im,
141  // Control Parameters:
142  const ArrayOfString& field_names,
143  const Verbosity&)
144 {
145  if (1!=atmosphere_dim)
146  {
147  ostringstream os;
148  os << "Atmospheric dimension must be one.";
149  throw runtime_error( os.str() );
150  }
151 
152  const Index np = im.nrows(); // Number of pressure levels.
153  const Index nf = im.ncols()-1; // Total number of fields.
154  Index nf_1; // Number of required fields.
155  // All fields called "ignore" are ignored.
156  String fn_upper; // Temporary variable to hold upper case field_names.
157 
158  if (field_names.nelem()!=nf)
159  {
160  ostringstream os;
161  os << "Cannot extract fields from Matrix.\n"
162  << "*field_names* must have one element less than there are\n"
163  << "matrix columns.";
164  throw runtime_error( os.str() );
165  }
166 
167 
168  // Remove additional fields from the field_names. All fields that
169  // are flagged by 'ignore' in the field names, small or large letters,
170  // are removed.
171  nf_1 = 0;
172  for(Index f = 0; f < field_names.nelem(); f++)
173  {
174  fn_upper = field_names[f];
175  std::transform ( fn_upper.begin(), fn_upper.end(), fn_upper.begin(), ::toupper);
176  if(fn_upper != "IGNORE") nf_1++;
177  }
178 
179  // Copy required field_names to a new variable called field_names_1
180  ArrayOfString field_names_1(nf_1);
181  for (Index f=0; f< nf_1; f++) field_names_1[f] = field_names[f];
182 
183 
184  // out3 << "Copying *" << im_name << "* to *atm_fields_compact*.\n";
185 
186  af.set_grid(GFIELD4_FIELD_NAMES, field_names_1);
187 
188  af.set_grid(GFIELD4_P_GRID, im(Range(joker),0));
189 
192 
193  af.resize(nf_1,np,1,1); // Resize it according to the required fields
194  af.data(Range(joker),Range(joker),0,0) = transpose(im(Range(joker),Range(1,nf_1)));
195 }
196 
197 // Workspace method, doxygen header will be auto-generated.
198 // 2011-01-24 Daniel Kreyling
200  GriddedField4& af_all, // atm_fields_compact_all
201  GriddedField4& af_vmr, // atm_fields_compact
202  // WS Input:
203  const Index& atmosphere_dim,
204  // WS Generic Input:
205  const Matrix& im,
206  // Control Parameters:
207  const ArrayOfString& field_names,
208  const Verbosity&)
209 {
210  // NOTE: follwoing section is HARD WIRED
211  // This method can only be applied to matrix data sets with a specific order of columns
212  // See method documentation!
213 
214  if (1!=atmosphere_dim)
215  {
216  ostringstream os;
217  os << "Atmospheric dimension must be one.";
218  throw runtime_error( os.str() );
219  }
220 
221  const Index np = im.nrows(); // Number of pressure levels.
222  const Index nf = im.ncols()-1; // Number of colums without pressure.
223 
224 
225  Index nf_1, nf_2; // Number of required fields.
226  // All fields called "ignore" are ignored.
227  String fn_upper; // Temporary variable to hold upper case field_names.
228 
229  if (field_names.nelem()!= nf)
230  {
231  ostringstream os;
232  os << "Cannot extract fields from Matrix.\n"
233  << "*field_names* must have one element less than there are\n"
234  << "matrix columns.";
235  throw runtime_error( os.str() );
236  }
237 
238 
239  // Remove additional fields from the field_names. All fields that
240  // are flagged by 'ignore' in the field names, small or large letters,
241  // are removed. The remaining number of fields is stored in *nf_1*.
242  // Usage: total batch_atm_fields_compact_all
243  nf_1 = 0;
244  nf_2 = 0;
245  ArrayOfIndex intarr;
246  for(Index f = 0; f < field_names.nelem(); f++)
247  {
248  fn_upper = field_names[f];
249  std::transform ( fn_upper.begin(), fn_upper.end(), fn_upper.begin(), ::toupper);
250  if(fn_upper != "IGNORE" ) nf_1++;
251 
252  // Remove all 'ignore' and massdensity fields in this step, so that only T, z and vmrs remain.
253  // The Index of these fields in stroed in *intarr*, for later access.
254  // The remaining number of fields is stored in *nf_2*.
255  if ( fn_upper !="IGNORE" && field_names[f] != "LWC" && field_names[f] != "IWC" &&
256  field_names[f] != "Rain" && field_names[f] != "Snow" )
257  {
258  nf_2++;
259  intarr.push_back(f);
260 
261  }
262  }
263 
264  //------- write batch_atm_fields_compact_all ----------------------------------------------------
265  // including massdenity fields!
266 
267  // Copy required field_names to a new variable called field_names_1
268  ArrayOfString field_names_1(nf_1); //f_names_2(2);
269  for (Index f=0; f< nf_1; f++) field_names_1[f] = field_names[f];
270 
271  // out3 << "Copying *" << im_name << "* to *atm_fields_compact*.\n";
272 
273  //cout<<nf<<"\t"<<nf_1<<"\t"<<field_names.nelem()<<endl;
274 
275 
276  af_all.set_grid(GFIELD4_FIELD_NAMES, field_names_1);
277 
278  af_all.set_grid(GFIELD4_P_GRID, im(Range(joker),0));
279 
280  af_all.set_grid(GFIELD4_LAT_GRID, Vector());
281  af_all.set_grid(GFIELD4_LON_GRID, Vector());
282 
283  af_all.resize(nf_1,np,1,1); // Resize it according to the required fields
284  af_all.data(Range(joker),Range(joker),0,0) = transpose(im(Range(joker),Range(1,nf_1)));
285 
286 
287  //------- write batch_atm_fields_compact -------------------------------------------------------------
288  // excluding massdenity fields!
289 
290  ArrayOfString field_names_2(nf_2);
291  for ( Index i=0; i<nf_2; i++ ) field_names_2[i] = field_names[intarr[i]] ;
292 
293  af_vmr.set_grid(GFIELD4_FIELD_NAMES, field_names_2);
294 
295  af_vmr.set_grid(GFIELD4_P_GRID, im(Range(joker),0));
296 
297  af_vmr.set_grid(GFIELD4_LAT_GRID, Vector());
298  af_vmr.set_grid ( GFIELD4_LON_GRID, Vector() );
299 
300  af_vmr.resize ( nf_2,np,1,1 ); // Resize it according to the required fields
301  for ( Index i=0; i<nf_2; i++ )
302  {
303  // write T, z and VMRs
304  af_vmr.data ( Range(i,1) ,Range ( joker ),0,0 ) = transpose ( im ( Range ( joker ), Range(intarr[i]+1,1)) );
305  }
306 }
307 
308 
309 // Workspace method, doxygen header is auto-generated.
310 // 2007-07-31 Stefan Buehler
311 // 2011-05-04 Adapted by Gerrit Holl
313  GriddedField4& af,
314  // Control Parameters:
315  const String& name,
316  const Numeric& value,
317  const Verbosity& verbosity)
318 {
319  Index nf; // Will hold new size
320 
321  // Add book
322  atm_fields_compactExpand(af, nf, name, verbosity);
323 
324  // Add the constant value:
325  af.data( nf-1, Range(joker), Range(joker), Range(joker) ) = value;
326 }
327 
328 // Workspace method, doxygen header is auto-generated
329 // 2011-05-02 Gerrit Holl
331  GriddedField4& atm_fields_compact,
332  // WS Generic Input:
333  const String& name,
334  const GriddedField3& species,
335  const Verbosity& verbosity)
336 {
337 
338  assert(atm_fields_compact.checksize());
339  assert(species.checksize());
340 
341  ConstVectorView af_p_grid = atm_fields_compact.get_numeric_grid(GFIELD4_P_GRID);
342  ConstVectorView af_lat_grid = atm_fields_compact.get_numeric_grid(GFIELD4_LAT_GRID);
343  ConstVectorView af_lon_grid = atm_fields_compact.get_numeric_grid(GFIELD4_LON_GRID);
344  ConstVectorView sp_p_grid = species.get_numeric_grid(GFIELD3_P_GRID);
345  ConstVectorView sp_lat_grid = species.get_numeric_grid(GFIELD3_LAT_GRID);
346  ConstVectorView sp_lon_grid = species.get_numeric_grid(GFIELD3_LON_GRID);
347 
348  Index new_n_fields; // To be set in next line
349  atm_fields_compactExpand(atm_fields_compact, new_n_fields, name, verbosity);
350 
351 
352  // Interpolate species to atm_fields_compact
353 
354  // Common for all dim
355  chk_interpolation_grids("species p_grid to atm_fields_compact p_grid",
356  sp_p_grid,
357  af_p_grid);
358  ArrayOfGridPos p_gridpos(af_p_grid.nelem());
359  // gridpos(p_gridpos, sp_p_grid, af_p_grid);
360  p2gridpos(p_gridpos, sp_p_grid, af_p_grid);
361 
362  if (sp_lat_grid.nelem() > 1)
363  {
364  // Common for all dim>=2
365  chk_interpolation_grids("species lat_grid to atm_fields_compact lat_grid",
366  sp_lat_grid,
367  af_lat_grid);
368  ArrayOfGridPos lat_gridpos(af_lat_grid.nelem());
369  gridpos(lat_gridpos, sp_lat_grid, af_lat_grid);
370 
371  if (sp_lon_grid.nelem() > 1)
372  { // 3D-case
373  chk_interpolation_grids("species lon_grid to atm_fields_compact lon_grid",
374  sp_lon_grid,
375  af_lon_grid);
376  ArrayOfGridPos lon_gridpos(af_lon_grid.nelem());
377  gridpos(lon_gridpos, sp_lon_grid, af_lon_grid);
378 
379  Tensor4 itw(p_gridpos.nelem(), lat_gridpos.nelem(), lon_gridpos.nelem(), 8);
380  interpweights(itw, p_gridpos, lat_gridpos, lon_gridpos);
381 
382  Tensor3 newfield(af_p_grid.nelem(), af_lat_grid.nelem(), af_lon_grid.nelem());
383  interp(newfield, itw, species.data, p_gridpos, lat_gridpos, lon_gridpos);
384 
385  atm_fields_compact.data(new_n_fields-1, joker, joker, joker) = newfield;
386  } else { // 2D-case
387 
388  Tensor3 itw(p_gridpos.nelem(), lat_gridpos.nelem(), 4);
389  interpweights(itw, p_gridpos, lat_gridpos);
390 
391  Matrix newfield(af_p_grid.nelem(), af_lat_grid.nelem());
392  interp(newfield, itw, species.data(joker, joker, 0), p_gridpos, lat_gridpos);
393 
394  atm_fields_compact.data(new_n_fields-1, joker, joker, 0) = newfield;
395  }
396  } else { // 1D-case
397  Matrix itw(p_gridpos.nelem(), 2);
398  interpweights(itw, p_gridpos);
399 
400  Vector newfield(af_p_grid.nelem());
401  interp(newfield, itw, species.data(joker, 0, 0), p_gridpos);
402 
403  atm_fields_compact.data(new_n_fields-1, joker, 0, 0) = newfield;
404  }
405 
406 }
407 
408 
409 
410 /* Workspace method: Doxygen documentation will be auto-generated */
412  Index& basics_checked,
413  const Index& atmosphere_dim,
414  const Vector& p_grid,
415  const Vector& lat_grid,
416  const Vector& lon_grid,
417  const ArrayOfArrayOfSpeciesTag& abs_species,
418  const Tensor3& z_field,
419  const Tensor3& t_field,
420  const Tensor4& vmr_field,
421  const Tensor3& wind_u_field,
422  const Tensor3& wind_v_field,
423  const Tensor3& wind_w_field,
424  const Matrix& r_geoid,
425  const Matrix& z_surface,
426  const Index& stokes_dim,
427  const Vector& f_grid,
428  const Verbosity&)
429 {
430  // Consistency between dim, grids and atmospheric fields/surfaces
431  chk_if_in_range( "atmosphere_dim", atmosphere_dim, 1, 3 );
432  chk_atm_grids( atmosphere_dim, p_grid, lat_grid, lon_grid );
433  chk_atm_field( "z_field", z_field, atmosphere_dim,
434  p_grid, lat_grid, lon_grid );
435  chk_atm_field( "t_field", t_field, atmosphere_dim,
436  p_grid, lat_grid, lon_grid );
437  // Ignore vmr_field if abs_species is empty
438  if( abs_species.nelem() )
439  chk_atm_field( "vmr_field", vmr_field, atmosphere_dim, abs_species.nelem(),
440  p_grid, lat_grid, lon_grid );
441  chk_atm_surface( "r_geoid", r_geoid, atmosphere_dim, lat_grid, lon_grid );
442  chk_atm_surface( "z_surface", z_surface, atmosphere_dim, lat_grid, lon_grid );
443 
444  // Check that z_field has strictly increasing pages.
445  for( Index row=0; row<z_field.nrows(); row++ )
446  {
447  for( Index col=0; col<z_field.ncols(); col++ )
448  {
449  ostringstream os;
450  os << "z_field (for latitude nr " << row << " and longitude nr "
451  << col << ")";
452  chk_if_increasing( os.str(), z_field(joker,row,col) );
453  }
454  }
455 
456  // Check that there is no gap between the surface and lowest pressure
457  // level
458  // (A copy of this code piece is found in z_fieldFromHSE. Make this to an
459  // internal function if used in more places.)
460  for( Index row=0; row<z_surface.nrows(); row++ )
461  {
462  for( Index col=0; col<z_surface.ncols(); col++ )
463  {
464  if( z_surface(row,col)<z_field(0,row,col) ||
465  z_surface(row,col)>=z_field(z_field.npages()-1,row,col) )
466  {
467  ostringstream os;
468  os << "The surface altitude (*z_surface*) cannot be outside "
469  << "of the altitudes in *z_field*.";
470  if( atmosphere_dim > 1 )
471  os << "\nThis was found to be the case for:\n"
472  << "latitude " << lat_grid[row];
473  if( atmosphere_dim > 2 )
474  os << "\nlongitude " << lon_grid[col];
475  throw runtime_error( os.str() );
476  }
477  }
478  }
479 
480  // Winds
481  if( wind_w_field.npages() > 0 )
482  {
483  chk_atm_field( "wind_w_field", wind_w_field, atmosphere_dim,
484  p_grid, lat_grid, lon_grid );
485  }
486  if( wind_v_field.npages() > 0 )
487  {
488  chk_atm_field( "wind_v_field", wind_v_field, atmosphere_dim,
489  p_grid, lat_grid, lon_grid );
490  }
491  if( atmosphere_dim > 2 && wind_u_field.npages() > 0 )
492  {
493  chk_atm_field( "wind_u_field", wind_u_field, atmosphere_dim,
494  p_grid, lat_grid, lon_grid );
495  }
496 
497  // Stokes and frequency grid
498  chk_if_in_range( "stokes_dim", stokes_dim, 1, 4 );
499  if ( f_grid.nelem() == 0 )
500  { throw runtime_error ( "The frequency grid is empty." ); }
501  chk_if_increasing ( "f_grid", f_grid );
502 
503  if (min(f_grid) <= 0) {
504  throw runtime_error("All frequencies in *f_grid* must be > 0.");
505  }
506 
507  // If here, all OK
508  basics_checked = 1;
509 }
510 
511 
512 
513 
514 // Workspace method, doxygen header is auto-generated
515 // 2011-05-11 Gerrit Holl
517  ArrayOfGriddedField4& batch_atm_fields_compact,
518  // WS Generic Input:
519  const String& name,
520  const Numeric& value,
521  const Verbosity& verbosity)
522 {
523  for (Index i=0; i<batch_atm_fields_compact.nelem(); i++)
524  {
525  atm_fields_compactAddConstant(batch_atm_fields_compact[i], name, value, verbosity);
526  }
527 
528 }
529 
530 // Workspace method, doxygen header is auto-generated
531 // 2011-05-09 Gerrit Holl
533  ArrayOfGriddedField4& batch_atm_fields_compact,
534  // WS Generic Input:
535  const String& name,
536  const GriddedField3& species,
537  const Verbosity& verbosity)
538 {
539  const Index nelem = batch_atm_fields_compact.nelem();
540 
541 // Parallelise this for-loop (some interpolation is being done, so it may
542 // be beneficial)
543 #pragma omp parallel for if(!arts_omp_in_parallel())
544  for (Index i=0; i<nelem; i++)
545  {
546  atm_fields_compactAddSpecies(batch_atm_fields_compact[i], name, species, verbosity);
547  }
548 }
549 
550 // Workspace method, doxygen header is auto-generated.
552  ArrayOfGriddedField4& batch_atm_fields_compact,
553  // WS Input:
554  const Index& atmosphere_dim,
555  // WS Generic Input:
556  const ArrayOfMatrix& am,
557  // Control Parameters:
558  const ArrayOfString& field_names,
559  const ArrayOfString& extra_field_names,
560  const Vector& extra_field_values,
561  const Verbosity& verbosity)
562 {
563  const Index amnelem = am.nelem();
564 
565  // We use the existing WSMs atm_fields_compactFromMatrix and
566  // atm_fields_compactAddConstant to do most of the work.
567 
568  // Check that extra_field_names and extra_field_values have matching
569  // dimensions:
570  if (extra_field_names.nelem() != extra_field_values.nelem())
571  {
572  ostringstream os;
573  os << "The keyword arguments extra_field_names and\n"
574  << "extra_field_values must have matching dimensions.";
575  throw runtime_error( os.str() );
576  }
577 
578  // Make output variable the proper size:
579  batch_atm_fields_compact.resize(amnelem);
580 
581  // Loop the batch cases:
582 /*#pragma omp parallel for \
583  if(!arts_omp_in_parallel()) \
584  default(none) \
585  shared(am, atmosphere_dim, batch_atm_fields_compact, \
586  extra_field_names, extra_field_values, field_names) */
587 #pragma omp parallel for \
588  if(!arts_omp_in_parallel())
589  for (Index i=0; i<amnelem; ++i)
590  {
591  // All the input variables are visible here, despite the
592  // "default(none)". The reason is that they are return by
593  // reference arguments of this function, which are shared
594  // automatically.
595 
596  // The try block here is necessary to correctly handle
597  // exceptions inside the parallel region.
598  try
599  {
600  atm_fields_compactFromMatrix(batch_atm_fields_compact[i],
601  atmosphere_dim,
602  am[i],
603  field_names,
604  verbosity);
605 
606  for (Index j=0; j<extra_field_names.nelem(); ++j)
607  atm_fields_compactAddConstant(batch_atm_fields_compact[i],
608  extra_field_names[j],
609  extra_field_values[j],
610  verbosity);
611  }
612  catch (runtime_error e)
613  {
615  exit_or_rethrow(e.what(), out0);
616  }
617  }
618 }
619 
620 
621 // Workspace method, doxygen header is auto-generated.
622 // 2011-01-24 Daniel Kreyling
624  ArrayOfGriddedField4& batch_atm_fields_compact,
625  ArrayOfGriddedField4& batch_atm_fields_compact_all,
626  // WS Input:
627  const Index& atmosphere_dim,
628  // WS Generic Input:
629  const ArrayOfMatrix& am,
630  // Control Parameters:
631  const ArrayOfString& field_names,
632  const ArrayOfString& extra_field_names,
633  const Vector& extra_field_values,
634  const Verbosity& verbosity)
635 {
636  const Index amnelem = am.nelem();
637 
638  // We use the existing WSMs atm_fields_compactFromMatrix and
639  // atm_fields_compactAddConstant to do most of the work.
640 
641  // Check that extra_field_names and extra_field_values have matching
642  // dimensions:
643  if (extra_field_names.nelem() != extra_field_values.nelem())
644  {
645  ostringstream os;
646  os << "The keyword arguments extra_field_names and\n"
647  << "extra_field_values must have matching dimensions.";
648  throw runtime_error( os.str() );
649  }
650 
651  // Make output variable the proper size:
652  batch_atm_fields_compact.resize(amnelem);
653  batch_atm_fields_compact_all.resize(amnelem);
654  // Loop the batch cases:
655 /*#pragma omp parallel for \
656  if(!arts_omp_in_parallel()) \
657  default(none) \
658  shared(am, atmosphere_dim, batch_atm_fields_compact, \
659  extra_field_names, extra_field_values, field_names) */
660 #pragma omp parallel for \
661  if(!arts_omp_in_parallel())
662  for (Index i=0; i<amnelem; ++i)
663  {
664  // All the input variables are visible here, despite the
665  // "default(none)". The reason is that they are return by
666  // reference arguments of this function, which are shared
667  // automatically.
668 
669  // The try block here is necessary to correctly handle
670  // exceptions inside the parallel region.
671  try
672  {
673  atm_fields_compactFromMatrixChevalAll(batch_atm_fields_compact_all[i],
674  batch_atm_fields_compact[i],
675  atmosphere_dim,
676  am[i],
677  field_names,
678  verbosity);
679 
680 
681  for (Index j=0; j<extra_field_names.nelem(); ++j){
682  atm_fields_compactAddConstant(batch_atm_fields_compact_all[i],
683  extra_field_names[j],
684  extra_field_values[j],
685  verbosity);
686 
687  atm_fields_compactAddConstant(batch_atm_fields_compact[i],
688  extra_field_names[j],
689  extra_field_values[j],
690  verbosity);
691  }
692  }
693  catch (runtime_error e)
694  {
696  exit_or_rethrow(e.what(), out0);
697  }
698  }
699 }
700 
701 // Workspace method, doxygen header will be auto-generated.
702 // 2010-11-29 Daniel Kreyling
704  Vector& p_grid,
705  Vector& lat_grid,
706  Vector& lon_grid,
707  Tensor3& t_field,
708  Tensor3& z_field,
709  Tensor4& massdensity_field,
710  Tensor4& vmr_field,
711  // WS Input:
712  const ArrayOfArrayOfSpeciesTag& abs_species,
713  // const ArrayOfArrayOfSpeciesTag&
714  const GriddedField4& atm_fields_compact_all,
715  const Index& atmosphere_dim,
716  const Verbosity&)
717 {
718  // Make a handle on atm_fields_compact to save typing:
719  const GriddedField4& c = atm_fields_compact_all;
720 
721  // Check if the grids in our data match atmosphere_dim
722  // (throws an error if the dimensionality is not correct):
723  chk_atm_grids(atmosphere_dim,
727 
729  const Index np = c.get_grid_size(GFIELD4_P_GRID);
730  const Index nlat = c.get_grid_size(GFIELD4_LAT_GRID);
731  const Index nlon = c.get_grid_size(GFIELD4_LON_GRID);
732 
733  // Grids:
734  p_grid = c.get_numeric_grid(GFIELD4_P_GRID);
735  lat_grid = c.get_numeric_grid(GFIELD4_LAT_GRID);
736  lon_grid = c.get_numeric_grid(GFIELD4_LON_GRID);
737 
738  // NOTE: follwoing section is HARD WIRED
739  // The order of the fields is:
740  // T[K] z[m] LWC[kg/m^3] IWC[kg/m^3] Rain[kg/(m2*s)] Snow[kg/(m2*s)] VMR_1[1] ... VMR_n[1]
741 
742  // Number of VMR species:
743  const Index ns = nf-6;
744 
745  // Check that there is at least one VMR species:
746  if (ns<1)
747  {
748  ostringstream os;
749  os << "There must be at least three fields in *atm_fields_compact*.\n"
750  << "T, z, and at least one VMR.";
751  throw runtime_error( os.str() );
752  }
753 
754  // Check that first field is T:
755  if (c.get_string_grid(GFIELD4_FIELD_NAMES)[0] != "T")
756  {
757  ostringstream os;
758  os << "The first field must be \"T\", but it is:"
760  throw runtime_error( os.str() );
761  }
762 
763  // Check that second field is z:
764  if (c.get_string_grid(GFIELD4_FIELD_NAMES)[1] != "z")
765  {
766  ostringstream os;
767  os << "The second field must be \"z\"*, but it is:"
769  throw runtime_error( os.str() );
770  }
771 
772  // Check that third field is LWC:
773  if (c.get_string_grid(GFIELD4_FIELD_NAMES)[2] != "LWC")
774  {
775  ostringstream os;
776  os << "The third field must be \"LWC\"*, but it is:"
778  throw runtime_error( os.str() );
779  }
780 
781  // Check that fourth field is IWC:
782  if (c.get_string_grid(GFIELD4_FIELD_NAMES)[3] != "IWC")
783  {
784  ostringstream os;
785  os << "The fourth field must be \"IWC\"*, but it is:"
787  throw runtime_error( os.str() );
788  }
789 
790  // Check that fifth field is Rain:
791  if (c.get_string_grid(GFIELD4_FIELD_NAMES)[4] != "Rain")
792  {
793  ostringstream os;
794  os << "The fifth field must be \"Rain\"*, but it is:"
796  throw runtime_error( os.str() );
797  }
798 
799  // Check that sixth field is Snow:
800  if (c.get_string_grid(GFIELD4_FIELD_NAMES)[5] != "Snow")
801  {
802  ostringstream os;
803  os << "The sixth field must be \"IWC\"*, but it is:"
805  throw runtime_error( os.str() );
806  }
807 
808  // Check that the other fields are VMR fields and match abs_species:
809  for (Index i=0; i<ns; ++i)
810  {
811  const String tf_species = c.get_string_grid(GFIELD4_FIELD_NAMES)[6+i];
812 
813  // Get name of species from abs_species:
814  extern const Array<SpeciesRecord> species_data; // The species lookup data:
815  const String as_species = species_data[abs_species[i][0].Species()].Name();
816 
817  // Species in field name and abs_species should be the same:
818  if (tf_species != as_species)
819  {
820  ostringstream os;
821  os << "Field name not valid: "
822  << tf_species << "\n"
823  << "Based on *abs_species*, the field name should be: "
824  << as_species;
825  throw runtime_error( os.str() );
826  }
827  }
828 
829  // Temperature field (first field):
830  t_field.resize(np,nlat,nlon);
831  t_field = c.data(0,Range(joker),Range(joker),Range(joker));
832 
833  // Altitude profile (second field):
834  z_field.resize(np,nlat,nlon);
835  z_field = c.data(1,Range(joker),Range(joker),Range(joker));
836 
837  //write all massdensity profile to one Tensor4
838  massdensity_field.resize(4,np,nlat,nlon);
839  massdensity_field = c.data(Range(2,4),Range(joker),Range(joker),Range(joker));
840 
841  // VMR profiles (remaining fields):
842  vmr_field.resize(ns,np,nlat,nlon);
843  vmr_field = c.data(Range(6,ns),Range(joker),Range(joker),Range(joker));
844 
845 }
846 
847 
848 // Workspace method, doxygen header will be auto-generated.
849 // 2007-07-24 Stefan Buehler
850 void AtmFieldsFromCompact(// WS Output:
851  Vector& p_grid,
852  Vector& lat_grid,
853  Vector& lon_grid,
854  Tensor3& t_field,
855  Tensor3& z_field,
856  Tensor4& vmr_field,
857  // WS Input:
858  const ArrayOfArrayOfSpeciesTag& abs_species,
859  const GriddedField4& atm_fields_compact,
860  const Index& atmosphere_dim,
861  const Verbosity&)
862 {
863  // Make a handle on atm_fields_compact to save typing:
864  const GriddedField4& c = atm_fields_compact;
865 
866  // Check if the grids in our data match atmosphere_dim
867  // (throws an error if the dimensionality is not correct):
868  chk_atm_grids(atmosphere_dim,
872 
874  const Index np = c.get_grid_size(GFIELD4_P_GRID);
875  const Index nlat = c.get_grid_size(GFIELD4_LAT_GRID);
876  const Index nlon = c.get_grid_size(GFIELD4_LON_GRID);
877 
878  // Grids:
879  p_grid = c.get_numeric_grid(GFIELD4_P_GRID);
880  lat_grid = c.get_numeric_grid(GFIELD4_LAT_GRID);
881  lon_grid = c.get_numeric_grid(GFIELD4_LON_GRID);
882 
883  // The order of the fields is:
884  // T[K] z[m] VMR_1[1] ... VMR_n[1]
885 
886  // Number of VMR species:
887  const Index ns = nf-2;
888 
889  // Check that there is at least one VMR species:
890  if (ns<1)
891  {
892  ostringstream os;
893  os << "There must be at least three fields in *atm_fields_compact*.\n"
894  << "T, z, and at least one VMR.";
895  throw runtime_error( os.str() );
896  }
897 
898  // Check that first field is T:
899  if (c.get_string_grid(GFIELD4_FIELD_NAMES)[0] != "T")
900  {
901  ostringstream os;
902  os << "The first field must be \"T\", but it is:"
904  throw runtime_error( os.str() );
905  }
906 
907  // Check that second field is z:
908  if (c.get_string_grid(GFIELD4_FIELD_NAMES)[1] != "z")
909  {
910  ostringstream os;
911  os << "The second field must be \"z\"*, but it is:"
913  throw runtime_error( os.str() );
914  }
915 
916  // Check that the other fields are VMR fields and match abs_species:
917  for (Index i=0; i<ns; ++i)
918  {
919  const String tf_species = c.get_string_grid(GFIELD4_FIELD_NAMES)[2+i];
920 
921  // Get name of species from abs_species:
922  extern const Array<SpeciesRecord> species_data; // The species lookup data:
923  const String as_species = species_data[abs_species[i][0].Species()].Name();
924 
925  // Species in field name and abs_species should be the same:
926  if (tf_species != as_species)
927  {
928  ostringstream os;
929  os << "Field name not valid: "
930  << tf_species << "\n"
931  << "Based on *abs_species*, the field name should be: "
932  << as_species;
933  throw runtime_error( os.str() );
934  }
935  }
936 
937  // Temperature field (first field):
938  t_field.resize(np,nlat,nlon);
939  t_field = c.data(0,Range(joker),Range(joker),Range(joker));
940 
941  // Altitude profile (second field):
942  z_field.resize(np,nlat,nlon);
943  z_field = c.data(1,Range(joker),Range(joker),Range(joker));
944 
945  // VMR profiles (remaining fields):
946  vmr_field.resize(ns,np,nlat,nlon);
947  vmr_field = c.data(Range(2,ns),Range(joker),Range(joker),Range(joker));
948 }
949 
950 
951 /* Workspace method: Doxygen documentation will be auto-generated */
952 void AtmosphereSet1D(// WS Output:
953  Index& atmosphere_dim,
954  Vector& lat_grid,
955  Vector& lon_grid,
956  const Verbosity& verbosity)
957 {
960 
961  out2 << " Sets the atmospheric dimensionality to 1.\n";
962  out3 << " atmosphere_dim = 1\n";
963  out3 << " lat_grid is set to be an empty vector\n";
964  out3 << " lon_grid is set to be an empty vector\n";
965 
966  atmosphere_dim = 1;
967  lat_grid.resize(0);
968  lon_grid.resize(0);
969 
970 }
971 
972 
973 /* Workspace method: Doxygen documentation will be auto-generated */
974 void AtmosphereSet2D(// WS Output:
975  Index& atmosphere_dim,
976  Vector& lon_grid,
977  const Verbosity& verbosity)
978 {
981 
982  out2 << " Sets the atmospheric dimensionality to 2.\n";
983  out3 << " atmosphere_dim = 2\n";
984  out3 << " lon_grid is set to be an empty vector\n";
985 
986  atmosphere_dim = 2;
987  lon_grid.resize(0);
988 }
989 
990 
991 /* Workspace method: Doxygen documentation will be auto-generated */
992 void AtmosphereSet3D(// WS Output:
993  Index& atmosphere_dim,
994  const Verbosity& verbosity)
995 {
998 
999  out2 << " Sets the atmospheric dimensionality to 3.\n";
1000  out3 << " atmosphere_dim = 3\n";
1001 
1002  atmosphere_dim = 3;
1003 }
1004 
1005 
1006 
1007 /* Workspace method: Doxygen documentation will be auto-generated */
1008 void AtmFieldsCalc(//WS Output:
1009  Tensor3& t_field,
1010  Tensor3& z_field,
1011  Tensor4& vmr_field,
1012  //WS Input
1013  const Vector& p_grid,
1014  const Vector& lat_grid,
1015  const Vector& lon_grid,
1016  const GriddedField3& t_field_raw,
1017  const GriddedField3& z_field_raw,
1018  const ArrayOfGriddedField3& vmr_field_raw,
1019  const Index& atmosphere_dim,
1020  // WS Generic Input:
1021  const Index& interp_order,
1022  const Verbosity& verbosity)
1023 {
1024  CREATE_OUT2
1025 
1026  const ConstVectorView tfr_p_grid = t_field_raw.get_numeric_grid(GFIELD3_P_GRID);
1027  const ConstVectorView tfr_lat_grid = t_field_raw.get_numeric_grid(GFIELD3_LAT_GRID);
1028  const ConstVectorView tfr_lon_grid = t_field_raw.get_numeric_grid(GFIELD3_LON_GRID);
1029  const ConstVectorView zfr_p_grid = z_field_raw.get_numeric_grid(GFIELD3_P_GRID);
1030  const ConstVectorView zfr_lat_grid = z_field_raw.get_numeric_grid(GFIELD3_LAT_GRID);
1031  const ConstVectorView zfr_lon_grid = z_field_raw.get_numeric_grid(GFIELD3_LON_GRID);
1032 
1033  out2 << " Interpolation order: " << interp_order << "\n";
1034 
1035  // Basic checks of input variables
1036  //
1037  // Atmosphere
1038  chk_if_in_range( "atmosphere_dim", atmosphere_dim, 1, 3 );
1039  chk_atm_grids( atmosphere_dim, p_grid, lat_grid, lon_grid );
1040 
1041 
1042  // Note that we are using the special function p2gridpos_poly below for
1043  // all pressure interpolations. This does the usual ARTS pressure
1044  // interpolation in log(p). We don't have to take logs here
1045  // explicitly, since it is done by p2gridpos.
1046 
1047 
1048  //==========================================================================
1049  if ( atmosphere_dim == 1)
1050  {
1051  if( !( tfr_lat_grid.nelem() == 1 &&
1052  tfr_lon_grid.nelem() == 1 ))
1053  throw runtime_error(
1054  "Temperature data (T_field) has wrong dimension "
1055  "(2D or 3D).\n"
1056  );
1057 
1058  if( !( zfr_lat_grid.nelem() == 1 &&
1059  zfr_lon_grid.nelem() == 1 ))
1060  throw runtime_error(
1061  "Altitude data (z_field) has wrong dimension "
1062  "(2D or 3D).\n"
1063  );
1064 
1065  //Resize variables
1066  t_field.resize(p_grid.nelem(), 1, 1);
1067  z_field.resize(p_grid.nelem(), 1, 1);
1068  vmr_field.resize(vmr_field_raw.nelem(), p_grid.nelem(), 1, 1);
1069 
1070  // Gridpositions:
1071  ArrayOfGridPosPoly gp_p(p_grid.nelem());
1072 
1073  // Interpolate t_field:
1074 
1075  // Check that interpolation grids are ok (and throw a detailed
1076  // error message if not):
1077  chk_interpolation_grids("Raw temperature to p_grid, 1D case",
1078  tfr_p_grid,
1079  p_grid,
1080  interp_order);
1081 
1082  // Calculate grid positions:
1083  p2gridpos_poly( gp_p, tfr_p_grid, p_grid, interp_order );
1084 
1085  // Interpolation weights:
1086  Matrix itw(p_grid.nelem(), interp_order+1);
1087  // (2 interpolation weights are required for 1D interpolation)
1088  interpweights( itw, gp_p);
1089 
1090  // Interpolate:
1091  interp( t_field(joker, 0, 0), itw,
1092  t_field_raw.data(joker, 0, 0), gp_p);
1093 
1094 
1095  // Interpolate z_field:
1096 
1097  // Check that interpolation grids are ok (and throw a detailed
1098  // error message if not):
1099  chk_interpolation_grids("Raw z to p_grid, 1D case",
1100  zfr_p_grid,
1101  p_grid,
1102  interp_order);
1103 
1104  // Calculate grid positions:
1105  p2gridpos_poly( gp_p, zfr_p_grid, p_grid, interp_order );
1106 
1107  // Interpolation weights:
1108  interpweights( itw, gp_p );
1109 
1110  // Interpolate:
1111  interp( z_field(joker, 0, 0), itw,
1112  z_field_raw.data(joker, 0, 0), gp_p);
1113 
1114 
1115  // Interpolate vmr_field.
1116  // Loop over the gaseous species:
1117  for (Index gas_i = 0; gas_i < vmr_field_raw.nelem(); gas_i++)
1118  {
1119  ostringstream os;
1120 
1121  if( !( vmr_field_raw[gas_i].get_numeric_grid(GFIELD3_LAT_GRID).nelem() == 1 &&
1122  vmr_field_raw[gas_i].get_numeric_grid(GFIELD3_LON_GRID).nelem() == 1 ))
1123  {
1124  os << "VMR data of the " << gas_i << "th species has "
1125  << "wrong dimension (2D or 3D). \n";
1126  throw runtime_error( os.str() );
1127  }
1128 
1129  // Check that interpolation grids are ok (and throw a detailed
1130  // error message if not):
1131  os << "Raw VMR[" << gas_i << "] to p_grid, 1D case";
1132  chk_interpolation_grids(os.str(),
1133  vmr_field_raw[gas_i].get_numeric_grid(GFIELD3_P_GRID),
1134  p_grid,
1135  interp_order);
1136 
1137  // Calculate grid positions:
1138  p2gridpos_poly(gp_p,
1139  vmr_field_raw[gas_i].get_numeric_grid(GFIELD3_P_GRID),
1140  p_grid,
1141  interp_order);
1142 
1143  // Interpolation weights:
1144  interpweights( itw, gp_p);
1145 
1146  // Interpolate:
1147  interp( vmr_field(gas_i, joker, 0, 0),
1148  itw, vmr_field_raw[gas_i].data(joker, 0, 0), gp_p);
1149  }
1150 
1151  }
1152 
1153  //=========================================================================
1154  else if(atmosphere_dim == 2)
1155  {
1156  if( tfr_lat_grid.nelem() == 1 &&
1157  tfr_lon_grid.nelem() == 1 )
1158  throw runtime_error(
1159  "Raw data has wrong dimension (1D). "
1160  "You have to use \n"
1161  "AtmFieldsCalcExpand1D instead of AtmFieldsCalc."
1162  );
1163 
1164  //Resize variables
1165  t_field.resize(p_grid.nelem(), lat_grid.nelem(), 1);
1166  z_field.resize(p_grid.nelem(), lat_grid.nelem(), 1);
1167  vmr_field.resize(vmr_field_raw.nelem(), p_grid.nelem(), lat_grid.nelem(),
1168  1);
1169 
1170 
1171  // Gridpositions:
1172  ArrayOfGridPosPoly gp_p(p_grid.nelem());
1173  ArrayOfGridPosPoly gp_lat(lat_grid.nelem());
1174 
1175  // Interpolate t_field:
1176 
1177  // Check that interpolation grids are ok (and throw a detailed
1178  // error message if not):
1179  chk_interpolation_grids("Raw temperature to p_grid, 2D case",
1180  tfr_p_grid,
1181  p_grid,
1182  interp_order);
1183  chk_interpolation_grids("Raw temperature to lat_grid, 2D case",
1184  tfr_lat_grid,
1185  lat_grid,
1186  interp_order);
1187 
1188  // Calculate grid positions:
1189  p2gridpos_poly( gp_p, tfr_p_grid, p_grid, interp_order );
1190  gridpos_poly( gp_lat, tfr_lat_grid, lat_grid, interp_order );
1191 
1192  // Interpolation weights:
1193  Tensor3 itw(p_grid.nelem(), lat_grid.nelem(), (interp_order+1)*(interp_order+1));
1194  // (4 interpolation weights are required for example for linear 2D interpolation)
1195  interpweights( itw, gp_p, gp_lat);
1196 
1197  // Interpolate:
1198  interp( t_field(joker, joker, 0 ), itw,
1199  t_field_raw.data(joker, joker, 0), gp_p, gp_lat);
1200 
1201 
1202  // Interpolate z_field:
1203 
1204  // Check that interpolation grids are ok (and throw a detailed
1205  // error message if not):
1206  chk_interpolation_grids("Raw z to p_grid, 2D case",
1207  zfr_p_grid,
1208  p_grid,
1209  interp_order);
1210  chk_interpolation_grids("Raw z to lat_grid, 2D case",
1211  zfr_lat_grid,
1212  lat_grid,
1213  interp_order);
1214 
1215  // Calculate grid positions:
1216  p2gridpos_poly( gp_p, zfr_p_grid, p_grid, interp_order );
1217  gridpos_poly( gp_lat, zfr_lat_grid, lat_grid, interp_order );
1218 
1219  // Interpolation weights:
1220  interpweights( itw, gp_p, gp_lat);
1221 
1222  // Interpolate:
1223  interp( z_field(joker, joker, 0), itw,
1224  z_field_raw.data(joker, joker, 0), gp_p, gp_lat);
1225 
1226 
1227  // Interpolate vmr_field.
1228  // Loop over the gaseous species:
1229  for (Index gas_i = 0; gas_i < vmr_field_raw.nelem(); gas_i++)
1230  {
1231  ostringstream os;
1232 
1233  if( !( vmr_field_raw[gas_i].get_numeric_grid(GFIELD3_LAT_GRID).nelem() != 1 &&
1234  vmr_field_raw[gas_i].get_numeric_grid(GFIELD3_LON_GRID).nelem() == 1 ))
1235  {
1236  os << "VMR data of the " << gas_i << "th species has "
1237  << "wrong dimension (1D or 3D). \n";
1238  throw runtime_error( os.str() );
1239  }
1240 
1241  // Check that interpolation grids are ok (and throw a detailed
1242  // error message if not):
1243  os << "Raw VMR[" << gas_i << "] to p_grid, 2D case";
1244  chk_interpolation_grids(os.str(),
1245  vmr_field_raw[gas_i].get_numeric_grid(GFIELD3_P_GRID),
1246  p_grid,
1247  interp_order);
1248  os.str("");
1249  os << "Raw VMR[" << gas_i << "] to lat_grid, 2D case";
1250  chk_interpolation_grids(os.str(),
1251  vmr_field_raw[gas_i].get_numeric_grid(GFIELD3_LAT_GRID),
1252  lat_grid,
1253  interp_order);
1254 
1255  // Calculate grid positions:
1256  p2gridpos_poly(gp_p, vmr_field_raw[gas_i].get_numeric_grid(GFIELD3_P_GRID),
1257  p_grid, interp_order);
1258  gridpos_poly(gp_lat, vmr_field_raw[gas_i].get_numeric_grid(GFIELD3_LAT_GRID),
1259  lat_grid, interp_order);
1260 
1261  // Interpolation weights:
1262  interpweights( itw, gp_p, gp_lat);
1263 
1264  // Interpolate:
1265  interp( vmr_field(gas_i, joker, joker, 0),
1266  itw, vmr_field_raw[gas_i].data(joker, joker, 0),
1267  gp_p, gp_lat);
1268  }
1269  }
1270 
1271  //================================================================
1272  // atmosphere_dim = 3
1273  else if(atmosphere_dim == 3)
1274  {
1275  if( tfr_lat_grid.nelem() == 1 &&
1276  tfr_lon_grid.nelem() == 1 )
1277  throw runtime_error(
1278  "Raw data has wrong dimension. You have to use \n"
1279  "AtmFieldsCalcExpand1D instead of AtmFieldsCalc."
1280  );
1281 
1282  //Resize variables
1283  t_field.resize(p_grid.nelem(), lat_grid.nelem(), lon_grid.nelem());
1284  z_field.resize(p_grid.nelem(), lat_grid.nelem(), lon_grid.nelem());
1285  vmr_field.resize(vmr_field_raw.nelem(), p_grid.nelem(), lat_grid.nelem(),
1286  lon_grid.nelem());
1287 
1288 
1289  // Gridpositions:
1290  ArrayOfGridPosPoly gp_p(p_grid.nelem());
1291  ArrayOfGridPosPoly gp_lat(lat_grid.nelem());
1292  ArrayOfGridPosPoly gp_lon(lon_grid.nelem());
1293 
1294 
1295  // Interpolate t_field:
1296 
1297  // Check that interpolation grids are ok (and throw a detailed
1298  // error message if not):
1299  chk_interpolation_grids("Raw temperature to p_grid, 3D case",
1300  tfr_p_grid,
1301  p_grid,
1302  interp_order);
1303  chk_interpolation_grids("Raw temperature to lat_grid, 3D case",
1304  tfr_lat_grid,
1305  lat_grid,
1306  interp_order);
1307  chk_interpolation_grids("Raw temperature to lon_grid, 3D case",
1308  tfr_lon_grid,
1309  lon_grid,
1310  interp_order);
1311 
1312  // Calculate grid positions:
1313  p2gridpos_poly( gp_p, tfr_p_grid, p_grid, interp_order );
1314  gridpos_poly( gp_lat, tfr_lat_grid, lat_grid, interp_order );
1315  gridpos_poly( gp_lon, tfr_lon_grid, lon_grid, interp_order );
1316 
1317  // Interpolation weights:
1318  Tensor4 itw(p_grid.nelem(), lat_grid.nelem(), lon_grid.nelem(),
1319  (interp_order+1)*(interp_order+1)*(interp_order+1));
1320  // (8 interpolation weights are required for example for linear 3D interpolation)
1321  interpweights( itw, gp_p, gp_lat, gp_lon );
1322 
1323  // Interpolate:
1324  interp( t_field, itw, t_field_raw.data, gp_p, gp_lat, gp_lon);
1325 
1326 
1327  // Interpolate z_field:
1328 
1329  // Check that interpolation grids are ok (and throw a detailed
1330  // error message if not):
1331  chk_interpolation_grids("Raw z to p_grid, 3D case",
1332  zfr_p_grid,
1333  p_grid,
1334  interp_order);
1335  chk_interpolation_grids("Raw z to lat_grid, 3D case",
1336  zfr_lat_grid,
1337  lat_grid,
1338  interp_order);
1339  chk_interpolation_grids("Raw z to lon_grid, 3D case",
1340  zfr_lon_grid,
1341  lon_grid,
1342  interp_order);
1343 
1344  // Calculate grid positions:
1345  p2gridpos_poly( gp_p, zfr_p_grid, p_grid, interp_order );
1346  gridpos_poly( gp_lat, zfr_lat_grid, lat_grid, interp_order );
1347  gridpos_poly( gp_lon, zfr_lon_grid, lon_grid, interp_order );
1348 
1349  // Interpolation weights:
1350  interpweights( itw, gp_p, gp_lat, gp_lon );
1351 
1352  // Interpolate:
1353  interp( z_field, itw, z_field_raw.data, gp_p, gp_lat, gp_lon);
1354 
1355 
1356  // Interpolate vmr_field.
1357  // Loop over the gaseous species:
1358  for (Index gas_i = 0; gas_i < vmr_field_raw.nelem(); gas_i++)
1359  {
1360  ostringstream os;
1361 
1362  if( !( vmr_field_raw[gas_i].get_numeric_grid(GFIELD3_LAT_GRID).nelem() != 1 &&
1363  vmr_field_raw[gas_i].get_numeric_grid(GFIELD3_LON_GRID).nelem() != 1 ))
1364  {
1365  os << "VMR data of the " << gas_i << "th species has "
1366  << "wrong dimension (1D or 2D). \n";
1367  throw runtime_error( os.str() );
1368  }
1369 
1370  // Check that interpolation grids are ok (and throw a detailed
1371  // error message if not):
1372  os << "Raw VMR[" << gas_i << "] to p_grid, 3D case";
1373  chk_interpolation_grids(os.str(),
1374  vmr_field_raw[gas_i].get_numeric_grid(GFIELD3_P_GRID),
1375  p_grid,
1376  interp_order);
1377  os.str("");
1378  os << "Raw VMR[" << gas_i << "] to lat_grid, 3D case";
1379  chk_interpolation_grids(os.str(),
1380  vmr_field_raw[gas_i].get_numeric_grid(GFIELD3_LAT_GRID),
1381  lat_grid,
1382  interp_order);
1383  os.str("");
1384  os << "Raw VMR[" << gas_i << "] to lon_grid, 3D case";
1385  chk_interpolation_grids(os.str(),
1386  vmr_field_raw[gas_i].get_numeric_grid(GFIELD3_LON_GRID),
1387  lon_grid,
1388  interp_order);
1389 
1390  // Calculate grid positions:
1391  p2gridpos_poly(gp_p, vmr_field_raw[gas_i].get_numeric_grid(GFIELD3_P_GRID),
1392  p_grid, interp_order);
1393  gridpos_poly(gp_lat, vmr_field_raw[gas_i].get_numeric_grid(GFIELD3_LAT_GRID),
1394  lat_grid, interp_order);
1395  gridpos_poly(gp_lon, vmr_field_raw[gas_i].get_numeric_grid(GFIELD3_LON_GRID),
1396  lon_grid, interp_order);
1397 
1398  // Interpolation weights:
1399  interpweights( itw, gp_p, gp_lat, gp_lon );
1400 
1401  // Interpolate:
1402  interp( vmr_field(gas_i, joker, joker, joker),
1403  itw, vmr_field_raw[gas_i].data, gp_p, gp_lat, gp_lon);
1404  }
1405  }
1406  else
1407  {
1408  // We can never get here, since there was a runtime
1409  // error check for atmosphere_dim at the beginning.
1410  assert(false);
1411  }
1412 }
1413 
1414 
1415 /* Workspace method: Doxygen documentation will be auto-generated */
1417  Tensor3& z_field,
1418  Tensor4& vmr_field,
1419  const Vector& p_grid,
1420  const Vector& lat_grid,
1421  const Vector& lon_grid,
1422  const GriddedField3& t_field_raw,
1423  const GriddedField3& z_field_raw,
1424  const ArrayOfGriddedField3& vmr_field_raw,
1425  const Index& atmosphere_dim,
1426  const Index& interp_order,
1427  const Verbosity& verbosity)
1428 {
1429  chk_if_in_range( "atmosphere_dim", atmosphere_dim, 1, 3 );
1430  chk_atm_grids( atmosphere_dim, p_grid, lat_grid, lon_grid );
1431 
1432  if( atmosphere_dim == 1 )
1433  { throw runtime_error(
1434  "This function is intended for 2D and 3D. For 1D, use *AtmFieldsCalc*.");}
1435 
1436  // Make 1D interpolation using some dummy variables
1437  Vector vempty(0);
1438  Tensor3 t_temp, z_temp;
1439  Tensor4 vmr_temp;
1440  AtmFieldsCalc(t_temp, z_temp, vmr_temp, p_grid, vempty, vempty,
1441  t_field_raw, z_field_raw, vmr_field_raw, 1, interp_order,
1442  verbosity);
1443 
1444  // Move values from the temporary tensors to the return arguments
1445  const Index np = p_grid.nelem();
1446  const Index nlat = lat_grid.nelem();
1447  Index nlon = lon_grid.nelem();
1448  if( atmosphere_dim == 2 )
1449  { nlon = 1; }
1450  const Index nspecies = vmr_temp.nbooks();
1451  //
1452  assert( t_temp.npages() == np );
1453  //
1454  t_field.resize( np, nlat, nlon );
1455  z_field.resize( np, nlat, nlon );
1456  vmr_field.resize( nspecies, np, nlat, nlon );
1457  //
1458  for( Index ilon=0; ilon<nlon; ilon++ )
1459  {
1460  for( Index ilat=0; ilat<nlat; ilat++ )
1461  {
1462  for( Index ip=0; ip<np; ip++ )
1463  {
1464  t_field(ip,ilat,ilon) = t_temp(ip,0,0);
1465  z_field(ip,ilat,ilon) = z_temp(ip,0,0);
1466  for( Index is=0; is<nspecies; is++ )
1467  { vmr_field(is,ip,ilat,ilon) = vmr_temp(is,ip,0,0); }
1468  }
1469  }
1470  }
1471 }
1472 
1473 
1474 /* Workspace method: Doxygen documentation will be auto-generated */
1476  Tensor3& z_field,
1477  Tensor4& vmr_field,
1478  const Vector& p_grid,
1479  const Vector& lat_grid,
1480  const Vector& lon_grid,
1481  const Index& atmosphere_dim,
1482  const Verbosity&)
1483 {
1484  chk_if_in_range( "atmosphere_dim", atmosphere_dim, 1, 3 );
1485  chk_atm_grids( atmosphere_dim, p_grid, lat_grid, lon_grid );
1486 
1487  // Sizes
1488  const Index np = p_grid.nelem();
1489  const Index nlat = lat_grid.nelem();
1490  const Index nlon = max( Index(1), lon_grid.nelem() );
1491  const Index nspecies = vmr_field.nbooks();
1492 
1493  if( atmosphere_dim == 1 )
1494  { throw runtime_error( "No use in calling this method for 1D.");}
1495  chk_atm_field( "t_field", t_field, 1, p_grid, Vector(0), Vector(0) );
1496  chk_atm_field( "z_field", z_field, 1, p_grid, Vector(0), Vector(0) );
1497  if( nspecies )
1498  chk_atm_field( "vmr_field", vmr_field, 1, nspecies, p_grid, Vector(0),
1499  Vector(0) );
1500 
1501  // Temporary containers
1502  Tensor3 t_temp = t_field, z_temp = z_field;
1503  Tensor4 vmr_temp = vmr_field;
1504 
1505  // Resize and fill
1506  t_field.resize( np, nlat, nlon );
1507  z_field.resize( np, nlat, nlon );
1508  vmr_field.resize( nspecies, np, nlat, nlon );
1509  //
1510  for( Index ilon=0; ilon<nlon; ilon++ )
1511  {
1512  for( Index ilat=0; ilat<nlat; ilat++ )
1513  {
1514  for( Index ip=0; ip<np; ip++ )
1515  {
1516  t_field(ip,ilat,ilon) = t_temp(ip,0,0);
1517  z_field(ip,ilat,ilon) = z_temp(ip,0,0);
1518  for( Index is=0; is<nspecies; is++ )
1519  { vmr_field(is,ip,ilat,ilon) = vmr_temp(is,ip,0,0); }
1520  }
1521  }
1522  }
1523 }
1524 
1525 
1526 
1527 /* Workspace method: Doxygen documentation will be auto-generated */
1528 void AtmFieldsRefinePgrid(// WS Output:
1529  Vector& p_grid,
1530  Tensor3& t_field,
1531  Tensor3& z_field,
1532  Tensor4& vmr_field,
1533  // WS Input:
1534  const Vector& lat_grid,
1535  const Vector& lon_grid,
1536  const Index& atmosphere_dim,
1537  // Control Parameters:
1538  const Numeric& p_step,
1539  const Verbosity&)
1540 {
1541  // Checks on input parameters:
1542 
1543  // We don't actually need lat_grid and lon_grid, but we have them as
1544  // input variables, so that we can use the standard functions to
1545  // check atmospheric fields and grids. A bit cheesy, but I don't
1546  // want to program all the checks explicitly.
1547 
1548  // Check grids:
1549  chk_atm_grids(atmosphere_dim, p_grid, lat_grid, lon_grid);
1550 
1551  // Check T field:
1552  chk_atm_field("t_field", t_field, atmosphere_dim,
1553  p_grid, lat_grid, lon_grid);
1554 
1555  // Check z field:
1556  chk_atm_field("z_field", z_field, atmosphere_dim,
1557  p_grid, lat_grid, lon_grid);
1558 
1559  // Check VMR field (and abs_species):
1560  chk_atm_field("vmr_field", vmr_field, atmosphere_dim,
1561  vmr_field.nbooks(), p_grid, lat_grid, lon_grid);
1562 
1563  // Check the keyword arguments:
1564  if ( p_step <= 0 )
1565  {
1566  ostringstream os;
1567  os << "The keyword argument p_step must be >0.";
1568  throw runtime_error( os.str() );
1569  }
1570 
1571  // Ok, all input parameters seem to be reasonable.
1572 
1573  // We will need the log of the pressure grid:
1574  Vector log_p_grid(p_grid.nelem());
1575  transform(log_p_grid, log, p_grid);
1576 
1577  // const Numeric epsilon = 0.01 * p_step; // This is the epsilon that
1578  // // we use for comparing p grid spacings.
1579 
1580  // Construct abs_p
1581  // ---------------
1582 
1583  ArrayOfNumeric log_abs_p_a; // We take log_abs_p_a as an array of
1584  // Numeric, so that we can easily
1585  // build it up by appending new elements to the end.
1586 
1587  // Check whether there are pressure levels that are further apart
1588  // (in log(p)) than p_step, and insert additional levels if
1589  // necessary:
1590 
1591  log_abs_p_a.push_back(log_p_grid[0]);
1592 
1593  for (Index i=1; i<log_p_grid.nelem(); ++i)
1594  {
1595  const Numeric dp = log_p_grid[i-1] - log_p_grid[i]; // The grid is descending.
1596 
1597  const Numeric dp_by_p_step = dp/p_step;
1598  // cout << "dp_by_p_step: " << dp_by_p_step << "\n";
1599 
1600  // How many times does p_step fit into dp?
1601  const Index n = (Index) ceil(dp_by_p_step);
1602  // n is the number of intervals that we want to have in the
1603  // new grid. The number of additional points to insert is
1604  // n-1. But we have to insert the original point as well.
1605  // cout << n << "\n";
1606 
1607  const Numeric ddp = dp/(Numeric)n;
1608  // cout << "ddp: " << ddp << "\n";
1609 
1610  for (Index j=1; j<=n; ++j)
1611  log_abs_p_a.push_back(log_p_grid[i-1] - (Numeric)j*ddp);
1612  }
1613 
1614  // Copy to a proper vector, we need this also later for
1615  // interpolation:
1616  Vector log_abs_p(log_abs_p_a.nelem());
1617  for (Index i=0; i<log_abs_p_a.nelem(); ++i)
1618  log_abs_p[i] = log_abs_p_a[i];
1619 
1620  // Copy the new grid to abs_p, removing the log:
1621  Vector abs_p(log_abs_p.nelem());
1622  transform(abs_p, exp, log_abs_p);
1623 
1624 
1625  // We will also have to interpolate T and VMR profiles to the new
1626  // pressure grid. We interpolate in log(p), as usual in ARTS.
1627 
1628  // Grid positions:
1629  ArrayOfGridPos gp(log_abs_p.nelem());
1630  gridpos(gp, log_p_grid, log_abs_p);
1631 
1632  // Interpolation weights:
1633  Matrix itw(gp.nelem(),2);
1634  interpweights(itw,gp);
1635 
1636  // Extent of latitude and longitude grids:
1637  Index nlat = lat_grid.nelem();
1638  Index nlon = lon_grid.nelem();
1639 
1640  // This here is needed so that the method works for 1D and 2D
1641  // atmospheres as well, not just for 3D:
1642  if (0 == nlat) nlat = 1;
1643  if (0 == nlon) nlon = 1;
1644 
1645  // Define variables for output fields:
1646  Tensor3 abs_t(log_abs_p.nelem(), nlat, nlon);
1647  Tensor3 abs_z(log_abs_p.nelem(), nlat, nlon);
1648  Tensor4 abs_vmr(vmr_field.nbooks(),
1649  log_abs_p.nelem(), nlat, nlon);
1650 
1651  for (Index ilat=0; ilat<nlat; ++ilat)
1652  for (Index ilon=0; ilon<nlon; ++ilon)
1653  {
1654  interp(abs_t(joker, ilat, ilon),
1655  itw,
1656  t_field(joker, ilat, ilon),
1657  gp);
1658 
1659  interp(abs_z(joker, ilat, ilon),
1660  itw,
1661  z_field(joker, ilat, ilon),
1662  gp);
1663 
1664  for (Index ivmr=0; ivmr<vmr_field.nbooks(); ++ivmr)
1665  interp(abs_vmr(ivmr, joker, ilat, ilon),
1666  itw,
1667  vmr_field(ivmr, joker, ilat, ilon),
1668  gp);
1669  }
1670 
1671 
1672  // Copy back the new fields to p_grid, t_field, z_field, vmr_field:
1673  p_grid = abs_p;
1674  t_field = abs_t;
1675  z_field = abs_z;
1676  vmr_field = abs_vmr;
1677 }
1678 
1679 
1680 
1681 /* Workspace method: Doxygen documentation will be auto-generated */
1682 void AtmRawRead(//WS Output:
1683  GriddedField3& t_field_raw,
1684  GriddedField3& z_field_raw,
1685  ArrayOfGriddedField3& vmr_field_raw,
1686  //WS Input:
1687  const ArrayOfArrayOfSpeciesTag& abs_species,
1688  //Keyword:
1689  const String& basename,
1690  const Verbosity& verbosity)
1691 {
1692  CREATE_OUT3
1693 
1694  // Read the temperature field:
1695  String file_name = basename + ".t.xml";
1696  xml_read_from_file( file_name, t_field_raw, verbosity);
1697 
1698  out3 << "Temperature field read from file: " << file_name << "\n";
1699 
1700  // Read geometrical altitude field:
1701  file_name = basename + ".z.xml";
1702  xml_read_from_file( file_name, z_field_raw, verbosity);
1703 
1704  out3 << "Altitude field read from file: " << file_name << "\n";
1705 
1706 
1707  // The species lookup data:
1708 
1709  extern const Array<SpeciesRecord> species_data;
1710 
1711  // We need to read one profile for each tag group.
1712  for ( Index i=0; i<abs_species.nelem(); i ++)
1713  {
1714  // Determine the name.
1715  file_name =
1716  basename + "." +
1717  species_data[abs_species[i][0].Species()].Name() + ".xml";
1718 
1719  // Add an element for this tag group to the vmr profiles:
1720  GriddedField3 vmr_field_data;
1721  vmr_field_raw.push_back(vmr_field_data);
1722 
1723  // Read the VMR:
1724  xml_read_from_file( file_name, vmr_field_raw[vmr_field_raw.nelem()-1], verbosity);
1725 
1726  // state the source of profile.
1727  out3 << " " << species_data[abs_species[i][0].Species()].Name()
1728  << " profile read from file: " << file_name << "\n";
1729  }
1730 }
1731 
1732 
1733 
1734 /* Workspace method: Doxygen documentation will be auto-generated */
1736  const Index& atmosphere_dim,
1737  const GridPos& rte_gp_p,
1738  const GridPos& rte_gp_lat,
1739  const GridPos& rte_gp_lon,
1740  const Tensor3& field,
1741  const Verbosity& verbosity)
1742 {
1743  CREATE_OUT3
1744 
1745  // Interpolate
1746  outvalue = interp_atmfield_by_gp( atmosphere_dim, field,
1747  rte_gp_p, rte_gp_lat, rte_gp_lon );
1748 
1749  out3 << " Result = " << outvalue << "\n";
1750 }
1751 
1752 /* Workspace method: Doxygen documentation will be auto-generated */
1753 void p_gridFromAtmRaw(//WS Output
1754  Vector& p_grid,
1755  //WS Input
1756  const GriddedField3& z_field_raw,
1757  const Verbosity&)
1758 {
1759 
1760  Index i=0;
1761  while ( z_field_raw.data(i,0,0)< 0.0 ) i++;
1762 
1763  Vector p_grid_raw=z_field_raw.get_numeric_grid(GFIELD3_P_GRID);
1764  p_grid=p_grid_raw[Range(i,p_grid_raw.nelem()-1)];
1765 }
1766 
1767 
1768 
1769 
1770 // A small help function
1771 void z2g(
1772  Numeric& g,
1773  const Numeric& r,
1774  const Numeric& g0,
1775  const Numeric& z )
1776 {
1777  g = g0 * pow( r/(r+z), 2 );
1778 }
1779 
1780 /* Workspace method: Doxygen documentation will be auto-generated */
1781 void z_fieldFromHSE(Tensor3& z_field,
1782  const Index& atmosphere_dim,
1783  const Vector& p_grid,
1784  const Vector& lat_grid,
1785  const Vector& lon_grid,
1786  const ArrayOfArrayOfSpeciesTag& abs_species,
1787  const Tensor3& t_field,
1788  const Tensor4& vmr_field,
1789  const Matrix& r_geoid,
1790  const Matrix& z_surface,
1791  const Index& basics_checked,
1792  const Numeric& p_hse,
1793  const Numeric& z_hse_accuracy,
1794  const Verbosity&)
1795 {
1796  // Some general variables
1797  const Index np = p_grid.nelem();
1798  const Index nlat = t_field.nrows();
1799  const Index nlon = t_field.ncols();
1800  //
1801  const Index firstH2O = find_first_species_tg( abs_species,
1803 
1804  // Input checks
1805  //
1806  if( !basics_checked )
1807  throw runtime_error( "The atmosphere must be flagged to have passed a "
1808  "consistency check (basics_checked=1)." );
1809  //
1810  if( atmosphere_dim == 1 && lat_grid.nelem() != 1 )
1811  { throw runtime_error(
1812  "The method requires that, for 1D, *lat_grid* has length 1." );
1813  }
1814  //
1815  if( firstH2O < 0 )
1816  throw runtime_error(
1817  "Water vapour is a requiered (must be a tag group in *abs_species*)." );
1818  //
1819  if( p_hse>p_grid[0] || p_hse < p_grid[np-1] )
1820  {
1821  ostringstream os;
1822  os << "The value of *p_hse* must be inside the range of *p_grid*:"
1823  << " p_hse = " << p_hse << " Pa\n"
1824  << " p_grid = << p_grid[np-1]" << " - " << p_grid[0] << " Pa\n";
1825  throw runtime_error( os.str() );
1826  }
1827  //
1828  if( z_hse_accuracy <= 0 )
1829  { throw runtime_error( "The value of *z_hse_accuracy* must be > 0." ); }
1830 
1831 
1832  // Determine interpolation weights for p_hse
1833  //
1834  ArrayOfGridPos gp(1);
1835  Matrix itw( 1, 2);
1836  p2gridpos( gp, p_grid, Vector(1,p_hse) );
1837  interpweights ( itw, gp );
1838 
1839 
1840  // The calculations
1841  //
1842  for( Index ilat=0; ilat<nlat; ilat++ )
1843  {
1844  // "Small g" at geoid altitude, g0:
1845  // Expression for g0 taken from Wikipedia page "Gravity of Earth", that
1846  // is stated to be: International Gravity Formula 1967, the 1967 Geodetic
1847  // Reference System Formula, Helmert's equation or Clairault's formula.
1848  const Numeric x = fabs( lat_grid[ilat] );
1849  const Numeric g0 = 9.780327 * ( 1 + 5.3024e-3*pow(sin(DEG2RAD*x),2) +
1850  5.8e-6*pow(sin(2*DEG2RAD*x),2) );
1851 
1852 
1853  for( Index ilon=0; ilon<nlon; ilon++ )
1854  {
1855  // Determine altitude for p_hse
1856  Vector z_hse(1);
1857  interp( z_hse, itw, z_field(joker,ilat,ilon), gp );
1858 
1859  Numeric z_acc = 2 * z_hse_accuracy;
1860 
1861  while( z_acc > z_hse_accuracy )
1862  {
1863  z_acc = 0;
1864  Numeric g1=g0, g2=g0;
1865 
1866  for( Index ip=0; ip<np-1; ip++ )
1867  {
1868  // Calculate average g
1869  if( ip == 0 )
1870  {
1871  z2g( g2, r_geoid(ilat,ilon), g0, z_field(ip,ilat,ilon) );
1872  }
1873  g1 = g2;
1874  z2g( g2, r_geoid(ilat,ilon), g0, z_field(ip+1,ilat,ilon) );
1875  //
1876  const Numeric g = ( g1 + g2 ) / 2.0;
1877 
1878  // Weight mixing ratio for water assuming constant average
1879  // molecular weight of the air
1880  // 0.3108 = 18/28.96 * 0.5
1881  const Numeric r = 0.3108 * ( vmr_field(firstH2O,ip,ilat,ilon)
1882  + vmr_field(firstH2O,ip+1,ilat,ilon) );
1883 
1884  // Virtual temperature (no liquid water)
1885  const Numeric tv = 0.5 * ( 1 + 0.61*r) * (
1886  t_field(ip,ilat,ilon) + t_field(ip+1,ilat,ilon) );
1887 
1888  // Change in vertical altitude from ip to ip+1
1889  const Numeric dz = 287.053 * (tv/g) *
1890  log( p_grid[ip]/p_grid[ip+1] );
1891 
1892  // New altitude
1893  Numeric znew = z_field(ip,ilat,ilon) + dz;
1894  z_acc = max( z_acc, fabs(znew-z_field(ip+1,ilat,ilon)) );
1895  z_field(ip+1,ilat,ilon) = znew;
1896  }
1897 
1898  // Adjust to z_hse
1899  Vector z_tmp(1);
1900  interp( z_tmp, itw, z_field(joker,ilat,ilon), gp );
1901  z_field(joker,ilat,ilon) -= z_tmp[0] - z_hse[0];
1902  }
1903  }
1904  }
1905 
1906  // Check that there is no gap between the surface and lowest pressure
1907  // level
1908  // (This code is copied from *basics_checkedCalc*. Make this to an internal
1909  // function if used in more places.)
1910  for( Index row=0; row<z_surface.nrows(); row++ )
1911  {
1912  for( Index col=0; col<z_surface.ncols(); col++ )
1913  {
1914  if( z_surface(row,col)<z_field(0,row,col) ||
1915  z_surface(row,col)>=z_field(z_field.npages()-1,row,col) )
1916  {
1917  ostringstream os;
1918  os << "The surface altitude (*z_surface*) cannot be outside "
1919  << "of the altitudes in *z_field*.";
1920  if( atmosphere_dim > 1 )
1921  os << "\nThis was found to be the case for:\n"
1922  << "latitude " << lat_grid[row];
1923  if( atmosphere_dim > 2 )
1924  os << "\nlongitude " << lon_grid[col];
1925  throw runtime_error( os.str() );
1926  }
1927  }
1928  }
1929 
1930 }
1931 
1932 
1933 
1934 
Matrix
The Matrix class.
Definition: matpackI.h:767
gridded_fields.h
Implementation of gridded fields.
basics_checkedCalc
void basics_checkedCalc(Index &basics_checked, const Index &atmosphere_dim, const Vector &p_grid, const Vector &lat_grid, const Vector &lon_grid, const ArrayOfArrayOfSpeciesTag &abs_species, const Tensor3 &z_field, const Tensor3 &t_field, const Tensor4 &vmr_field, const Tensor3 &wind_u_field, const Tensor3 &wind_v_field, const Tensor3 &wind_w_field, const Matrix &r_geoid, const Matrix &z_surface, const Index &stokes_dim, const Vector &f_grid, const Verbosity &)
WORKSPACE METHOD: basics_checkedCalc.
Definition: m_atmosphere.cc:411
transform
void transform(VectorView y, double(&my_func)(double), ConstVectorView x)
A generic transform function for vectors, which can be used to implement mathematical functions opera...
Definition: matpackI.cc:1728
species_index_from_species_name
Index species_index_from_species_name(String name)
Return species index for given species name.
Definition: abs_species_tags.cc:452
GriddedField::get_string_grid
const ArrayOfString & get_string_grid(Index i) const
Get a string grid.
Definition: gridded_fields.cc:157
Tensor4::resize
void resize(Index b, Index p, Index r, Index c)
Resize function.
Definition: matpackIV.cc:1404
chk_atm_surface
void chk_atm_surface(const String &x_name, const Matrix &x, const Index &dim, ConstVectorView lat_grid, ConstVectorView lon_grid)
chk_atm_surface
Definition: check_input.cc:821
absorption.h
Declarations required for the calculation of absorption coefficients.
batch_atm_fields_compactFromArrayOfMatrix
void batch_atm_fields_compactFromArrayOfMatrix(ArrayOfGriddedField4 &batch_atm_fields_compact, const Index &atmosphere_dim, const ArrayOfMatrix &am, const ArrayOfString &field_names, const ArrayOfString &extra_field_names, const Vector &extra_field_values, const Verbosity &verbosity)
WORKSPACE METHOD: batch_atm_fields_compactFromArrayOfMatrix.
Definition: m_atmosphere.cc:551
chk_if_increasing
void chk_if_increasing(const String &x_name, const ArrayOfIndex &x)
chk_if_increasing
Definition: check_input.cc:126
gridpos
void gridpos(ArrayOfGridPos &gp, ConstVectorView old_grid, ConstVectorView new_grid, const Numeric &extpolfac)
Set up a grid position Array.
Definition: interpolation.cc:167
Tensor3
The Tensor3 class.
Definition: matpackIII.h:340
atm_fields_compactAddSpecies
void atm_fields_compactAddSpecies(GriddedField4 &atm_fields_compact, const String &name, const GriddedField3 &species, const Verbosity &verbosity)
WORKSPACE METHOD: atm_fields_compactAddSpecies.
Definition: m_atmosphere.cc:330
GFIELD4_LAT_GRID
const Index GFIELD4_LAT_GRID
GFIELD4_LON_GRID
const Index GFIELD4_LON_GRID
p2gridpos
void p2gridpos(ArrayOfGridPos &gp, ConstVectorView old_pgrid, ConstVectorView new_pgrid, const Numeric &extpolfac)
p2gridpos
Definition: special_interp.cc:810
joker
const Joker joker
interpolation.h
Header file for interpolation.cc.
interp
Numeric interp(ConstVectorView itw, ConstVectorView a, const GridPos &tc)
Red 1D Interpolate.
Definition: interpolation.cc:1000
AtmFieldsCalc
void AtmFieldsCalc(Tensor3 &t_field, Tensor3 &z_field, Tensor4 &vmr_field, const Vector &p_grid, const Vector &lat_grid, const Vector &lon_grid, const GriddedField3 &t_field_raw, const GriddedField3 &z_field_raw, const ArrayOfGriddedField3 &vmr_field_raw, const Index &atmosphere_dim, const Index &interp_order, const Verbosity &verbosity)
WORKSPACE METHOD: AtmFieldsCalc.
Definition: m_atmosphere.cc:1008
GFIELD3_LON_GRID
const Index GFIELD3_LON_GRID
Vector::resize
void resize(Index n)
Resize function.
Definition: matpackI.cc:771
exit_or_rethrow
void exit_or_rethrow(const String &m, ArtsOut &out)
Exit ARTS or re-throw error.
Definition: arts.cc:98
p_gridFromAtmRaw
void p_gridFromAtmRaw(Vector &p_grid, const GriddedField3 &z_field_raw, const Verbosity &)
WORKSPACE METHOD: p_gridFromAtmRaw.
Definition: m_atmosphere.cc:1753
AtmosphereSet3D
void AtmosphereSet3D(Index &atmosphere_dim, const Verbosity &verbosity)
WORKSPACE METHOD: AtmosphereSet3D.
Definition: m_atmosphere.cc:992
ConstMatrixView::nrows
Index nrows() const
Returns the number of rows.
Definition: matpackI.cc:796
GFIELD3_P_GRID
const Index GFIELD3_P_GRID
atm_fields_compactFromMatrixChevalAll
void atm_fields_compactFromMatrixChevalAll(GriddedField4 &af_all, GriddedField4 &af_vmr, const Index &atmosphere_dim, const Matrix &im, const ArrayOfString &field_names, const Verbosity &)
WORKSPACE METHOD: atm_fields_compactFromMatrixChevalAll.
Definition: m_atmosphere.cc:199
batch_atm_fields_compactAddSpecies
void batch_atm_fields_compactAddSpecies(ArrayOfGriddedField4 &batch_atm_fields_compact, const String &name, const GriddedField3 &species, const Verbosity &verbosity)
WORKSPACE METHOD: batch_atm_fields_compactAddSpecies.
Definition: m_atmosphere.cc:532
CREATE_OUT2
#define CREATE_OUT2
Definition: messages.h:207
GriddedField::get_numeric_grid
ConstVectorView get_numeric_grid(Index i) const
Get a numeric grid.
Definition: gridded_fields.cc:91
GriddedField4::checksize
virtual bool checksize() const
Consistency check.
Definition: gridded_fields.h:342
Tensor4
The Tensor4 class.
Definition: matpackIV.h:375
Tensor3::resize
void resize(Index p, Index r, Index c)
Resize function.
Definition: matpackIII.cc:863
GriddedField3
Definition: gridded_fields.h:274
ConstTensor3View::npages
Index npages() const
Returns the number of pages.
Definition: matpackIII.h:151
DEG2RAD
const Numeric DEG2RAD
GriddedField::get_grid_size
Index get_grid_size(Index i) const
Get the size of a grid.
Definition: gridded_fields.h:116
Array
This can be used to make arrays out of anything.
Definition: array.h:103
batch_atm_fields_compactAddConstant
void batch_atm_fields_compactAddConstant(ArrayOfGriddedField4 &batch_atm_fields_compact, const String &name, const Numeric &value, const Verbosity &verbosity)
WORKSPACE METHOD: batch_atm_fields_compactAddConstant.
Definition: m_atmosphere.cc:516
GriddedField3::data
Tensor3 data
Definition: gridded_fields.h:323
agenda_class.h
Declarations for agendas.
xml_read_from_file
void xml_read_from_file(const String &filename, T &type, const Verbosity &verbosity)
Reads data from XML file.
Definition: xml_io.cc:850
CREATE_OUT3
#define CREATE_OUT3
Definition: messages.h:208
AtmFieldsRefinePgrid
void AtmFieldsRefinePgrid(Vector &p_grid, Tensor3 &t_field, Tensor3 &z_field, Tensor4 &vmr_field, const Vector &lat_grid, const Vector &lon_grid, const Index &atmosphere_dim, const Numeric &p_step, const Verbosity &)
WORKSPACE METHOD: AtmFieldsRefinePgrid.
Definition: m_atmosphere.cc:1528
CREATE_OUT0
#define CREATE_OUT0
Definition: messages.h:205
species_data
Array< SpeciesRecord > species_data
Definition: species_data.cc:40
messages.h
Declarations having to do with the four output streams.
GFIELD3_LAT_GRID
const Index GFIELD3_LAT_GRID
ConstMatrixView::ncols
Index ncols() const
Returns the number of columns.
Definition: matpackI.cc:802
my_basic_string
The implementation for String, the ARTS string class.
Definition: mystring.h:62
ConstVectorView::nelem
Index nelem() const
Returns the number of elements.
Definition: matpackI.cc:175
find_first_species_tg
Index find_first_species_tg(const ArrayOfArrayOfSpeciesTag &tgs, const Index &spec)
Find first occurrence of species in tag groups.
Definition: abs_species_tags.cc:393
ConstTensor4View::ncols
Index ncols() const
Returns the number of columns.
Definition: matpackIV.cc:78
ns
#define ns
Definition: continua.cc:14564
Numeric
NUMERIC Numeric
The type to use for all floating point numbers.
Definition: matpack.h:33
Verbosity
Definition: messages.h:50
ConstTensor4View::npages
Index npages() const
Returns the number of pages.
Definition: matpackIV.cc:66
GriddedField4
Definition: gridded_fields.h:328
chk_atm_field
void chk_atm_field(const String &x_name, ConstTensor3View x, const Index &dim, ConstVectorView p_grid, ConstVectorView lat_grid, ConstVectorView lon_grid)
chk_atm_field (simple fields)
Definition: check_input.cc:683
matpackIII.h
ConstTensor4View::nbooks
Index nbooks() const
Returns the number of books.
Definition: matpackIV.cc:60
transpose
ConstMatrixView transpose(ConstMatrixView m)
Const version of transpose.
Definition: matpackI.cc:1689
z2g
void z2g(Numeric &g, const Numeric &r, const Numeric &g0, const Numeric &z)
Definition: m_atmosphere.cc:1771
GriddedField4::resize
void resize(const GriddedField4 &gf)
Make this GriddedField4 the same size as the given one.
Definition: gridded_fields.h:356
atm_fields_compactFromMatrix
void atm_fields_compactFromMatrix(GriddedField4 &af, const Index &atmosphere_dim, const Matrix &im, const ArrayOfString &field_names, const Verbosity &)
WORKSPACE METHOD: atm_fields_compactFromMatrix.
Definition: m_atmosphere.cc:135
AtmRawRead
void AtmRawRead(GriddedField3 &t_field_raw, GriddedField3 &z_field_raw, ArrayOfGriddedField3 &vmr_field_raw, const ArrayOfArrayOfSpeciesTag &abs_species, const String &basename, const Verbosity &verbosity)
WORKSPACE METHOD: AtmRawRead.
Definition: m_atmosphere.cc:1682
abs_species_tags.h
Header file for stuff related to absorption species tags.
AtmFieldsFromCompactChevalAll
void AtmFieldsFromCompactChevalAll(Vector &p_grid, Vector &lat_grid, Vector &lon_grid, Tensor3 &t_field, Tensor3 &z_field, Tensor4 &massdensity_field, Tensor4 &vmr_field, const ArrayOfArrayOfSpeciesTag &abs_species, const GriddedField4 &atm_fields_compact_all, const Index &atmosphere_dim, const Verbosity &)
WORKSPACE METHOD: AtmFieldsFromCompactChevalAll.
Definition: m_atmosphere.cc:703
ConstTensor3View::nrows
Index nrows() const
Returns the number of rows.
Definition: matpackIII.h:154
max
#define max(a, b)
Definition: continua.cc:13097
interpolation_poly.h
Header file for interpolation_poly.cc.
AtmFieldsFromCompact
void AtmFieldsFromCompact(Vector &p_grid, Vector &lat_grid, Vector &lon_grid, Tensor3 &t_field, Tensor3 &z_field, Tensor4 &vmr_field, const ArrayOfArrayOfSpeciesTag &abs_species, const GriddedField4 &atm_fields_compact, const Index &atmosphere_dim, const Verbosity &)
WORKSPACE METHOD: AtmFieldsFromCompact.
Definition: m_atmosphere.cc:850
ConstTensor4View::nrows
Index nrows() const
Returns the number of rows.
Definition: matpackIV.cc:72
Range
The range class.
Definition: matpackI.h:148
GridPos
Structure to store a grid position.
Definition: interpolation.h:74
GriddedField::set_grid
void set_grid(Index i, const Vector &g)
Set a numeric grid.
Definition: gridded_fields.cc:223
AtmFieldsCalcExpand1D
void AtmFieldsCalcExpand1D(Tensor3 &t_field, Tensor3 &z_field, Tensor4 &vmr_field, const Vector &p_grid, const Vector &lat_grid, const Vector &lon_grid, const GriddedField3 &t_field_raw, const GriddedField3 &z_field_raw, const ArrayOfGriddedField3 &vmr_field_raw, const Index &atmosphere_dim, const Index &interp_order, const Verbosity &verbosity)
WORKSPACE METHOD: AtmFieldsCalcExpand1D.
Definition: m_atmosphere.cc:1416
GriddedField3::checksize
virtual bool checksize() const
Consistency check.
Definition: gridded_fields.h:295
atm_fields_compactAddConstant
void atm_fields_compactAddConstant(GriddedField4 &af, const String &name, const Numeric &value, const Verbosity &verbosity)
WORKSPACE METHOD: atm_fields_compactAddConstant.
Definition: m_atmosphere.cc:312
interp_atmfield_by_gp
void interp_atmfield_by_gp(VectorView x, const Index &atmosphere_dim, ConstTensor3View x_field, const ArrayOfGridPos &gp_p, const ArrayOfGridPos &gp_lat, const ArrayOfGridPos &gp_lon)
interp_atmfield_by_gp
Definition: special_interp.cc:215
z_fieldFromHSE
void z_fieldFromHSE(Tensor3 &z_field, const Index &atmosphere_dim, const Vector &p_grid, const Vector &lat_grid, const Vector &lon_grid, const ArrayOfArrayOfSpeciesTag &abs_species, const Tensor3 &t_field, const Tensor4 &vmr_field, const Matrix &r_geoid, const Matrix &z_surface, const Index &basics_checked, const Numeric &p_hse, const Numeric &z_hse_accuracy, const Verbosity &)
WORKSPACE METHOD: z_fieldFromHSE.
Definition: m_atmosphere.cc:1781
ConstTensor3View::ncols
Index ncols() const
Returns the number of columns.
Definition: matpackIII.h:157
chk_atm_grids
void chk_atm_grids(const Index &dim, ConstVectorView p_grid, ConstVectorView lat_grid, ConstVectorView lon_grid)
chk_atm_grids
Definition: check_input.cc:603
min
#define min(a, b)
Definition: continua.cc:13096
special_interp.h
Header file for special_interp.cc.
GFIELD4_P_GRID
const Index GFIELD4_P_GRID
GFIELD4_FIELD_NAMES
const Index GFIELD4_FIELD_NAMES
p2gridpos_poly
void p2gridpos_poly(ArrayOfGridPosPoly &gp, ConstVectorView old_pgrid, ConstVectorView new_pgrid, const Index order, const Numeric &extpolfac)
p2gridpos_poly
Definition: special_interp.cc:843
Index
INDEX Index
The type to use for all integer numbers and indices.
Definition: matpack.h:39
chk_if_in_range
void chk_if_in_range(const String &x_name, const Index &x, const Index &x_low, const Index &x_high)
chk_if_in_range
Definition: check_input.cc:95
AtmosphereSet1D
void AtmosphereSet1D(Index &atmosphere_dim, Vector &lat_grid, Vector &lon_grid, const Verbosity &verbosity)
WORKSPACE METHOD: AtmosphereSet1D.
Definition: m_atmosphere.cc:952
check_input.h
gridpos_poly
void gridpos_poly(ArrayOfGridPosPoly &gp, ConstVectorView old_grid, ConstVectorView new_grid, const Index order, const Numeric &extpolfac)
Set up grid positions for higher order interpolation.
Definition: interpolation_poly.cc:124
GriddedField4::data
Tensor4 data
Definition: gridded_fields.h:373
Vector
The Vector class.
Definition: matpackI.h:555
ConstVectorView
A constant view of a Vector.
Definition: matpackI.h:300
Array::nelem
Index nelem() const
Number of elements.
Definition: array.h:172
AtmFieldsExpand1D
void AtmFieldsExpand1D(Tensor3 &t_field, Tensor3 &z_field, Tensor4 &vmr_field, const Vector &p_grid, const Vector &lat_grid, const Vector &lon_grid, const Index &atmosphere_dim, const Verbosity &)
WORKSPACE METHOD: AtmFieldsExpand1D.
Definition: m_atmosphere.cc:1475
interpweights
void interpweights(VectorView itw, const GridPos &tc)
Red 1D interpolation weights.
Definition: interpolation.cc:756
atm_fields_compactExpand
void atm_fields_compactExpand(GriddedField4 &af, Index &nf, const String &name, const Verbosity &)
atm_fields_compactExpand
Definition: m_atmosphere.cc:89
batch_atm_fields_compactFromArrayOfMatrixChevalAll
void batch_atm_fields_compactFromArrayOfMatrixChevalAll(ArrayOfGriddedField4 &batch_atm_fields_compact, ArrayOfGriddedField4 &batch_atm_fields_compact_all, const Index &atmosphere_dim, const ArrayOfMatrix &am, const ArrayOfString &field_names, const ArrayOfString &extra_field_names, const Vector &extra_field_values, const Verbosity &verbosity)
WORKSPACE METHOD: batch_atm_fields_compactFromArrayOfMatrixChevalAll.
Definition: m_atmosphere.cc:623
AtmosphereSet2D
void AtmosphereSet2D(Index &atmosphere_dim, Vector &lon_grid, const Verbosity &verbosity)
WORKSPACE METHOD: AtmosphereSet2D.
Definition: m_atmosphere.cc:974
arts.h
The global header file for ARTS.
chk_interpolation_grids
void chk_interpolation_grids(const String &which_interpolation, ConstVectorView old_grid, ConstVectorView new_grid, const Index order, const Numeric &extpolfac)
Check interpolation grids.
Definition: check_input.cc:390
xml_io.h
This file contains basic functions to handle XML data files.
InterpAtmFieldToRteGps
void InterpAtmFieldToRteGps(Numeric &outvalue, const Index &atmosphere_dim, const GridPos &rte_gp_p, const GridPos &rte_gp_lat, const GridPos &rte_gp_lon, const Tensor3 &field, const Verbosity &verbosity)
WORKSPACE METHOD: InterpAtmFieldToRteGps.
Definition: m_atmosphere.cc:1735