ARTS  2.4.0(git:4fb77825)
m_checked.cc
Go to the documentation of this file.
1 /* Copyright (C) 2013
2  Patrick Eriksson <Patrick.Eriksson@chalmers.se>
3  Stefan Buehler <sbuehler(at)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  === File description
22  ===========================================================================*/
23 
35 #include "arts.h"
36 #include "auto_md.h"
37 #include "cloudbox.h"
38 #include "matpackI.h"
39 
40 extern const Numeric DEG2RAD;
41 extern const Numeric LAT_LON_MIN;
42 
43 /* Workspace method: Doxygen documentation will be auto-generated */
46  // WS Input:
48  const Agenda& abs_xsec_agenda,
49  const Verbosity&) {
50  bool needs_lines = false;
51  bool needs_continua = false;
52  bool needs_cia = false;
53  bool needs_hxsec = false;
54 
55  for (Index sp = 0; sp < abs_species.nelem(); sp++) {
56  for (Index tgs = 0; tgs < abs_species[sp].nelem(); tgs++) {
57  switch (abs_species[sp][tgs].Type()) {
59  needs_lines = true;
60  break;
62  break;
64  needs_continua = true;
65  break;
67  needs_cia = true;
68  break;
70  break;
72  break;
74  needs_hxsec = true;
75  break;
76  default:
77  ostringstream os;
78  os << "Unknown species type: " << abs_species[sp][tgs].Type();
79  throw runtime_error(os.str());
80  break;
81  }
82  }
83  }
84 
85  if (needs_lines and
86  not(abs_xsec_agenda.has_method("abs_xsec_per_speciesAddLines"))) {
87  throw runtime_error(
88  "*abs_species* contains line species but *abs_xsec_agenda*\n"
89  "does not contain *abs_xsec_per_speciesAddLines*.");
90  }
91 
92  if (needs_continua &&
93  !abs_xsec_agenda.has_method("abs_xsec_per_speciesAddConts")) {
94  throw runtime_error(
95  "*abs_species* contains continuum species but *abs_xsec_agenda*\n"
96  "does not contain *abs_xsec_per_speciesAddConts*.");
97  }
98 
99  if (needs_cia && !abs_xsec_agenda.has_method("abs_xsec_per_speciesAddCIA")) {
100  throw runtime_error(
101  "*abs_species* contains CIA species but *abs_xsec_agenda*\n"
102  "does not contain *abs_xsec_per_speciesAddCIA*.");
103  }
104 
105  if (needs_hxsec &&
106  !abs_xsec_agenda.has_method("abs_xsec_per_speciesAddHitranXsec")) {
107  throw runtime_error(
108  "*abs_species* contains HITRAN xsec species but *abs_xsec_agenda*\n"
109  "does not contain *abs_xsec_per_speciesAddHitranXsec*.");
110  }
111 
112  if (find_first_species_tg(abs_species, SpeciesTag("O2-MPM2020")) >= 0) {
113  if (not abs_xsec_agenda.has_method("abs_xsec_per_speciesAddPredefinedO2MPM2020")) {
114  throw runtime_error(
115  "*abs_species contains \"O2-MPM2020\" but *abs_xsec_agenda*\n"
116  "does not contain *abs_xsec_per_speciesAddPredefinedO2MPM2020*.");
117  }
118  }
119 
120  // If here, all OK
122 }
123 
124 /* Workspace method: Doxygen documentation will be auto-generated */
126  const Index& atmosphere_dim,
127  const Vector& p_grid,
128  const Vector& lat_grid,
129  const Vector& lon_grid,
131  const Tensor3& t_field,
132  const Tensor4& vmr_field,
133  const Tensor3& wind_u_field,
134  const Tensor3& wind_v_field,
135  const Tensor3& wind_w_field,
136  const Tensor3& mag_u_field,
137  const Tensor3& mag_v_field,
138  const Tensor3& mag_w_field,
140  const Index& abs_f_interp_order,
141  const Index& negative_vmr_ok,
142  const Index& bad_partition_functions_ok,
143  const Verbosity&) {
144  // Consistency between dim, grids and atmospheric fields/surfaces
145  chk_if_in_range("atmosphere_dim", atmosphere_dim, 1, 3);
148  chk_atm_field("vmr_field",
149  vmr_field,
151  abs_species.nelem(),
152  p_grid,
153  lat_grid,
154  lon_grid);
155 
156  // More for vmr_field.
157  if (!negative_vmr_ok && abs_species.nelem() && min(vmr_field) < 0)
158  throw runtime_error("All values in *vmr_field* must be >= 0.");
159 
160  // More for t_field.
161  if (min(t_field) <= 0)
162  throw runtime_error("All temperatures in *t_field* must be > 0.");
163 
164  // Winds
165  if (wind_w_field.npages() > 0) {
166  chk_atm_field("wind_w_field",
167  wind_w_field,
169  p_grid,
170  lat_grid,
171  lon_grid);
172  }
173  if (atmosphere_dim < 3 && wind_v_field.npages() > 0) {
174  chk_atm_field("wind_v_field",
175  wind_v_field,
177  p_grid,
178  lat_grid,
179  lon_grid);
180  }
181  if (atmosphere_dim > 2) {
182  if (wind_u_field.npages() > 0) {
183  if (wind_v_field.npages() > 0) {
184  bool chk_poles = false;
185  chk_atm_field("wind_u_field",
186  wind_u_field,
188  p_grid,
189  lat_grid,
190  lon_grid,
191  chk_poles);
192  chk_atm_field("wind_v_field",
193  wind_v_field,
195  p_grid,
196  lat_grid,
197  lon_grid,
198  chk_poles);
199  chk_atm_vecfield_lat90("wind_v_field",
200  wind_v_field,
201  "wind_u_field",
202  wind_u_field,
204  lat_grid);
205  } else {
206  chk_atm_field("wind_u_field",
207  wind_u_field,
209  p_grid,
210  lat_grid,
211  lon_grid);
212  }
213  } else {
214  if (wind_v_field.npages() > 0) {
215  chk_atm_field("wind_v_field",
216  wind_v_field,
218  p_grid,
219  lat_grid,
220  lon_grid);
221  }
222  }
223  }
224 
225  // If any of the wind fields exist, abs_f_interp_order must not be zero.
226  if (wind_u_field.npages() > 0 || wind_v_field.npages() > 0 ||
227  wind_w_field.npages() > 0) {
228  if (abs_f_interp_order == 0) {
229  ostringstream os;
230  os << "You have a wind field set, but abs_f_interp_order zero.\n"
231  << "This is not allowed. Though abs_f_interp_order only is\n"
232  << "required and has an effect if absorption lookup tables\n"
233  << "are used, for safety reasons you also have to set it >0\n"
234  << "in case of on-the-fly absorption.";
235  throw runtime_error(os.str());
236  }
237  }
238 
239  // Magnetic field
240  if (mag_w_field.npages() > 0) {
241  chk_atm_field("mag_w_field (vertical magfield component)",
242  mag_w_field,
244  p_grid,
245  lat_grid,
246  lon_grid);
247  }
248  if (mag_u_field.npages() > 0) {
249  if (mag_v_field.npages() > 0) {
250  bool chk_poles = false;
251  chk_atm_field("mag_v_field",
252  mag_v_field,
254  p_grid,
255  lat_grid,
256  lon_grid,
257  chk_poles);
258  chk_atm_field("mag_u_field",
259  mag_u_field,
261  p_grid,
262  lat_grid,
263  lon_grid,
264  chk_poles);
265  chk_atm_vecfield_lat90("mag_v_field",
266  mag_v_field,
267  "mag_u_field",
268  mag_u_field,
270  lat_grid);
271  } else {
272  chk_atm_field("mag_u_field",
273  mag_u_field,
275  p_grid,
276  lat_grid,
277  lon_grid);
278  }
279  } else {
280  if (mag_v_field.npages() > 0) {
281  chk_atm_field("mag_v_field",
282  mag_v_field,
284  p_grid,
285  lat_grid,
286  lon_grid);
287  }
288  }
289 
290  if (partition_functions.nspecies()) {
291  // Partition functions have partition functions and finding their temperature limits?
292  Numeric min_T = 0, max_T = 1e6; //1 MK is max tested
293  for (Index ii = 0; ii < partition_functions.nspecies(); ii++)
294  for (Index jj = 0; jj < partition_functions.nisotopologues(ii); jj++) {
295  // Test if species is important at all (maybe, since code is unclear; will at worst cause failures later on in the program)
296  bool test_spec = false;
297  for (auto& as : abs_species)
298  for (auto& s : as)
299  if (s.Species() == ii and s.Isotopologue() == jj) test_spec = true;
300  if (not test_spec) continue;
301 
302  ArrayOfGriddedField1 part_fun;
303  switch (partition_functions.getParamType(ii, jj)) {
305  part_fun = partition_functions.getParam(ii, jj);
306  if (part_fun.nelem() == 2) {
307  if (part_fun[1].data.nelem() == 2 &&
308  part_fun[0].data.nelem() > 1) {
309  if (part_fun[1].data[0] > min_T) min_T = part_fun[1].data[0];
310  if (part_fun[1].data[1] < max_T) max_T = part_fun[1].data[1];
311  } else
312  throw std::runtime_error(
313  "Bad coefficient parameter in partition_function.\n");
314  } else
315  throw std::runtime_error(
316  "Bad coefficient parameter in partition_function.\n");
317  break;
318 
320  part_fun = partition_functions.getParam(ii, jj);
321  if (part_fun.nelem() == 3) {
322  if (part_fun[2].data.nelem() == 2 &&
323  (part_fun[1].data.nelem() == part_fun[0].data.nelem())) {
324  if (part_fun[2].data[0] > min_T) min_T = part_fun[2].data[0];
325  if (part_fun[2].data[1] < max_T) max_T = part_fun[2].data[1];
326  } else
327  throw std::runtime_error(
328  "Bad coefficient parameter in partition_function.\n");
329  } else
330  throw std::runtime_error(
331  "Bad coefficient parameter in partition_function.\n");
332  break;
333 
335  part_fun = partition_functions.getParam(ii, jj);
336  if (part_fun.nelem() == 1) {
337  if (part_fun[0].data.nelem() > 1) {
338  if (part_fun[0].get_numeric_grid(0)[0] > min_T)
339  min_T = part_fun[0].get_numeric_grid(0)[0];
340  if (part_fun[0].get_numeric_grid(
341  0)[part_fun[0].data.nelem() - 1] < max_T)
342  max_T = part_fun[0].get_numeric_grid(
343  0)[part_fun[0].data.nelem() - 1];
344  } else
345  throw std::runtime_error(
346  "Bad t_field parameter in partition_function.\n");
347  } else
348  throw std::runtime_error(
349  "Bad t_field parameter in partition_function.\n");
350  break;
351 
352  default:
353  throw std::runtime_error(
354  "Bad parameter type in partition_functions.\n");
355  break;
356  }
357  }
358 
359  // Check that partition functions are OK if not explicitly turned off
360  if (!bad_partition_functions_ok) {
361  for (Index ii = 0; ii < t_field.npages(); ii++)
362  for (Index jj = 0; jj < t_field.nrows(); jj++)
363  for (Index kk = 0; kk < t_field.ncols(); kk++) {
364  if (min_T > t_field(ii, jj, kk) || max_T < t_field(ii, jj, kk)) {
365  ostringstream os;
366  os << "There are bad partition functions in your setup.\n"
367  << "Minimum temperature for defined partition functions is: "
368  << min_T
369  << " K.\nMaximum temperature for defined partition functions is: "
370  << max_T << " K\nThere is a t_field entry of "
371  << t_field(ii, jj, kk) << " K.\n";
372  throw std::runtime_error(os.str());
373  }
374  }
375  }
376  }
377 
378  // If here, all OK
379  atmfields_checked = 1;
380 }
381 
382 /* Workspace method: Doxygen documentation will be auto-generated */
384  const Index& atmosphere_dim,
385  const Vector& p_grid,
386  const Vector& lat_grid,
387  const Vector& lon_grid,
388  const Tensor3& z_field,
389  const Vector& refellipsoid,
390  const Matrix& z_surface,
391  const Vector& lat_true,
392  const Vector& lon_true,
393  const Verbosity&) {
394  // A repetition from atmfields_checked, but we do this to make the two parts
395  // independent (the other option would be to demand atmfields_checkec == 1)
396  chk_if_in_range("atmosphere_dim", atmosphere_dim, 1, 3);
398 
399  // *refellipsoid*
400  if (refellipsoid.nelem() != 2)
401  throw runtime_error(
402  "The WSV *refellispoid* must be a vector of "
403  "length 2*.");
404  if (refellipsoid[0] <= 0)
405  throw runtime_error(
406  "The first element of *refellipsoid* must "
407  "be > 0.");
408  if (refellipsoid[1] < 0 || refellipsoid[1] > 1)
409  throw runtime_error(
410  "The second element of *refellipsoid* must be "
411  "inside [0,1].");
412  if (atmosphere_dim == 1 && refellipsoid[1] != 0)
413  throw runtime_error(
414  "For 1D, the second element of *refellipsoid* "
415  "(the eccentricity) must be 0.");
416 
419 
420  // Check that z_field has strictly increasing pages.
421  for (Index row = 0; row < z_field.nrows(); row++) {
422  for (Index col = 0; col < z_field.ncols(); col++) {
423  ostringstream os;
424  os << "z_field (for latitude nr " << row << " and longitude nr " << col
425  << ")";
426  chk_if_increasing(os.str(), z_field(joker, row, col));
427  }
428  }
429 
430  // Check that there is no gap between the surface and lowest pressure
431  // level
432  // (A copy of this code piece is found in z_fieldFromHSE. Make this to an
433  // internal function if used in more places.)
434  for (Index row = 0; row < z_surface.nrows(); row++) {
435  for (Index col = 0; col < z_surface.ncols(); col++) {
436  if (z_surface(row, col) < z_field(0, row, col) ||
437  z_surface(row, col) >= z_field(z_field.npages() - 1, row, col)) {
438  ostringstream os;
439  os << "The surface altitude (*z_surface*) cannot be outside\n"
440  << "of the altitudes in *z_field*.\n"
441  << "z_surface: " << z_surface(row, col) << "\n"
442  << "min of z_field: " << z_field(0, row, col) << "\n"
443  << "max of z_field: " << z_field(z_field.npages() - 1, row, col)
444  << "\n";
445  if (atmosphere_dim > 1)
446  os << "\nThis was found to be the case for:\n"
447  << "latitude " << lat_grid[row];
448  if (atmosphere_dim > 2) os << "\nlongitude " << lon_grid[col];
449  throw runtime_error(os.str());
450  }
451  }
452  }
453 
454  // lat/lon true
455  if (atmosphere_dim < 3 && (lat_true.nelem() || lon_true.nelem())) {
456  if (atmosphere_dim == 1) {
457  if (lat_true.nelem() != 1)
458  throw runtime_error("For 1D, *lat_true* must have length 1.");
459  if (lon_true.nelem() != 1)
460  throw runtime_error("For 1D, *lon_true* must have length 1.");
461  } else if (atmosphere_dim == 2) {
462  if (lat_true.nelem() != lat_grid.nelem())
463  throw runtime_error(
464  "For 2D, *lat_true* must have same length as *lat_grid*.");
465  if (lon_true.nelem() != lat_grid.nelem())
466  throw runtime_error(
467  "For 2D, *lon_true* must have same length as *lat_grid*.");
468  }
469  if (lon_true.nelem() != lat_true.nelem())
470  throw runtime_error(
471  "If *lat_true* is set, also *lon_true* must be "
472  "set (and have the same length).");
473  if (min(lat_true) < -90 || max(lat_true) > 90)
474  throw runtime_error("Values in *lat_true* must be inside [-90,90].");
475  if (min(lon_true) < -180 || max(lon_true) > 360)
476  throw runtime_error("Values in *lon_true* must be inside [-180,360].");
477  }
478 
479  // If here, all OK
480  atmgeom_checked = 1;
481 }
482 
483 /* Workspace method: Doxygen documentation will be auto-generated */
485  const Index& atmfields_checked,
486  const Index& atmosphere_dim,
487  const Vector& p_grid,
488  const Vector& lat_grid,
489  const Vector& lon_grid,
490  const Tensor3& z_field,
491  const Matrix& z_surface,
492  const Tensor3& wind_u_field,
493  const Tensor3& wind_v_field,
494  const Tensor3& wind_w_field,
495  const Index& cloudbox_on,
497  const Tensor4& pnd_field,
502  const Matrix& particle_masses,
504  const Index& negative_pnd_ok,
505  const Verbosity&) {
506  if (atmfields_checked != 1)
507  throw runtime_error(
508  "The atmospheric fields must be flagged to have "
509  "passed a consistency check (atmfields_checked=1).");
510 
511  chk_if_bool("cloudbox_on", cloudbox_on);
512 
513  if (cloudbox_on) {
514  // Winds, must be empty variables (i.e. no winds allowed)
515  {
516  ostringstream ow;
517  ow << "The scattering methods are not (yet?) handling winds. For this\n"
518  << "reason, the WSVs for wind fields must all be empty with an\n."
519  << "active cloudbox.";
520  if (!wind_w_field.empty() || !wind_v_field.empty() ||
521  !wind_u_field.empty()) {
522  throw runtime_error(ow.str());
523  }
524  }
525 
526  // no "particles" in abs_species if cloudbox is on (they act on the same
527  // scat_data! and there is no good reason to have some particles as
528  // abs-only, if we anyway do a scattering calculation.).
529  Index has_absparticles = 0;
530  for (Index sp = 0; sp < abs_species.nelem() && has_absparticles < 1; sp++) {
531  if (abs_species[sp][0].Type() == SpeciesTag::TYPE_PARTICLES) {
532  has_absparticles = 1;
533  }
534  }
535  if (has_absparticles) {
536  throw runtime_error(
537  "For scattering calculations (cloudbox is on),"
538  "abs_species is not allowed to contain\n"
539  "'particles' (absorbing-only particles)!");
540  }
541 
542  // Cloudbox limits
543  if (cloudbox_limits.nelem() != atmosphere_dim * 2) {
544  ostringstream os;
545  os << "The array *cloudbox_limits* has incorrect length.\n"
546  << "For atmospheric dim. = " << atmosphere_dim
547  << " the length shall be " << atmosphere_dim * 2 << " but it is "
548  << cloudbox_limits.nelem() << ".";
549  throw runtime_error(os.str());
550  }
551  if (cloudbox_limits[1] <= cloudbox_limits[0] || cloudbox_limits[0] < 0 ||
552  cloudbox_limits[1] >= p_grid.nelem()) {
553  ostringstream os;
554  os << "Incorrect value(s) for cloud box pressure limit(s) found."
555  << "\nValues are either out of range or upper limit is not "
556  << "greater than lower limit.\nWith present length of "
557  << "*p_grid*, OK values are 0 - " << p_grid.nelem() - 1
558  << ".\nThe pressure index limits are set to " << cloudbox_limits[0]
559  << " - " << cloudbox_limits[1] << ".";
560  throw runtime_error(os.str());
561  }
562 
563  Index nlat = 1, nlon = 1;
564 
565  if (atmosphere_dim > 1) {
566  nlat = lat_grid.nelem();
567  if (cloudbox_limits[3] <= cloudbox_limits[2] || cloudbox_limits[2] < 1 ||
568  cloudbox_limits[3] >= nlat - 1) {
569  ostringstream os;
570  os << "Incorrect value(s) for cloud box latitude limit(s) found."
571  << "\nValues are either out of range or upper limit is not "
572  << "greater than lower limit.\nWith present length of "
573  << "*lat_grid*, OK values are 1 - " << nlat - 2
574  << ".\nThe latitude index limits are set to " << cloudbox_limits[2]
575  << " - " << cloudbox_limits[3] << ".";
576  throw runtime_error(os.str());
577  }
578  if ((lat_grid[cloudbox_limits[2]] - lat_grid[0] < LAT_LON_MIN) &&
579  (atmosphere_dim == 2 || (atmosphere_dim == 3 && lat_grid[0] > -90))) {
580  ostringstream os;
581  os << "Too small distance between cloudbox and lower end of "
582  << "latitude grid.\n"
583  << "This distance must be " << LAT_LON_MIN << " degrees.\n"
584  << "Cloudbox ends at " << lat_grid[cloudbox_limits[2]]
585  << " and latitude grid starts at " << lat_grid[0] << ".";
586  throw runtime_error(os.str());
587  }
588  if ((lat_grid[nlat - 1] - lat_grid[cloudbox_limits[3]] < LAT_LON_MIN) &&
589  (atmosphere_dim == 2 ||
590  (atmosphere_dim == 3 && lat_grid[nlat - 1] < 90))) {
591  ostringstream os;
592  os << "Too small distance between cloudbox and upper end of "
593  << "latitude grid.\n"
594  << "This distance must be " << LAT_LON_MIN << " degrees.\n"
595  << "Cloudbox ends at " << lat_grid[cloudbox_limits[3]]
596  << " and latitude grid ends at " << lat_grid[nlat - 1] << ".";
597  throw runtime_error(os.str());
598  }
599  }
600 
601  if (atmosphere_dim > 2) {
602  nlon = lon_grid.nelem();
603  if (cloudbox_limits[5] <= cloudbox_limits[4] || cloudbox_limits[4] < 1 ||
604  cloudbox_limits[5] >= nlon - 1) {
605  ostringstream os;
606  os << "Incorrect value(s) for cloud box longitude limit(s) found"
607  << ".\nValues are either out of range or upper limit is not "
608  << "greater than lower limit.\nWith present length of "
609  << "*lon_grid*, OK values are 1 - " << nlon - 2
610  << ".\nThe longitude limits are set to " << cloudbox_limits[4]
611  << " - " << cloudbox_limits[5] << ".";
612  throw runtime_error(os.str());
613  }
614  if (lon_grid[nlon - 1] - lon_grid[0] < 360) {
615  const Numeric latmax = max(abs(lat_grid[cloudbox_limits[2]]),
617  const Numeric lfac = 1 / cos(DEG2RAD * latmax);
618  if (lon_grid[cloudbox_limits[4]] - lon_grid[0] < LAT_LON_MIN / lfac) {
619  ostringstream os;
620  os << "Too small distance between cloudbox and lower end of"
621  << "the longitude\ngrid. This distance must here be "
622  << LAT_LON_MIN / lfac << " degrees.";
623  throw runtime_error(os.str());
624  }
625  if (lon_grid[nlon - 1] - lon_grid[cloudbox_limits[5]] <
626  LAT_LON_MIN / lfac) {
627  ostringstream os;
628  os << "Too small distance between cloudbox and upper end of"
629  << "the longitude\ngrid. This distance must here be "
630  << LAT_LON_MIN / lfac << " degrees.";
631  throw runtime_error(os.str());
632  }
633  }
634  }
635 
636  // Check with respect to z_surface
637  for (Index o = 0; o < nlon; o++) {
638  for (Index a = 0; a < nlat; a++) {
639  if (z_field(cloudbox_limits[1], a, o) <= z_surface(a, o))
640  throw runtime_error(
641  "The upper vertical limit of the cloudbox must be above "
642  "the surface altitude (for all latitudes and longitudes).");
643  }
644  }
645 
646  // Check pnd_field
647  //
649  // Dummy variables to mimic grids of correct size
650  Vector g1(cloudbox_limits[1] - cloudbox_limits[0] + 1), g2(0), g3(0);
651  if (atmosphere_dim > 1) {
652  g2.resize(cloudbox_limits[3] - cloudbox_limits[2] + 1);
653  }
654  if (atmosphere_dim > 2) {
655  g3.resize(cloudbox_limits[5] - cloudbox_limits[4] + 1);
656  }
657 
658  chk_atm_field("pnd_field", pnd_field, atmosphere_dim, np, g1, g2, g3);
659 
660  if (!negative_pnd_ok && min(pnd_field) < 0)
661  throw runtime_error("Negative values in *pnd_field* not allowed.");
662 
663  // No non-zero pnd at lower boundary unless lower boundary is at or below
664  // surface
665  for (Index a = 0; a < g2.nelem(); a++) {
666  for (Index o = 0; o < g3.nelem(); o++) {
667  if (max(pnd_field(joker, 0, a, o)) > 0 &&
668  z_field(cloudbox_limits[0], a, o) > z_surface(a, o))
669  throw runtime_error(
670  "A non-zero value found in *pnd_field* at the"
671  " lower altitude limit of the cloudbox (but the "
672  "position is not at or below the surface altitude).");
673  }
674  }
675 
676  // No non-zero pnd at upper boundary unless upper boundary is top of
677  // atmosphere
678  if (cloudbox_limits[1] != p_grid.nelem() - 1)
679  if (max(pnd_field(joker, g1.nelem() - 1, joker, joker)) > 0)
680  throw runtime_error(
681  "A non-zero value found in *pnd_field* at "
682  "upper altitude limit of the cloudbox.");
683  if (atmosphere_dim >= 2) {
684  if (max(pnd_field(joker, joker, 0, joker)) > 0)
685  throw runtime_error(
686  "A non-zero value found in *pnd_field* at "
687  "lower latitude limit of the cloudbox.");
688  if (max(pnd_field(joker, joker, g2.nelem() - 1, joker)) > 0)
689  throw runtime_error(
690  "A non-zero value found in *pnd_field* at "
691  "upper latitude limit of the cloudbox.");
692  }
693  if (atmosphere_dim == 3) {
694  if (max(pnd_field(joker, joker, joker, 0)) > 0)
695  throw runtime_error(
696  "A non-zero value found in *pnd_field* at "
697  "lower longitude limit of the cloudbox.");
698  if (max(pnd_field(joker, joker, joker, g3.nelem() - 1)) > 0)
699  throw runtime_error(
700  "A non-zero value found in *pnd_field* at "
701  "upper longitude limit of the cloudbox.");
702  }
703 
704  // And dpnd_field_dx
705  if (dpnd_field_dx.nelem() != jacobian_quantities.nelem())
706  throw runtime_error(
707  "Size of *dpnd_field_dx* inconsistent with number "
708  "of *jacobian_quantities*.");
709 
710  // Check semi-mandatory variables, that are allowed to be empty
711  //
712 
713  // scat_species:
714  if (scat_species.nelem() > 0)
715  if (scat_species.nelem() != scat_data.nelem()) {
716  ostringstream os;
717  os << "Number of scattering species specified by scat_species does\n"
718  << "not agree with number of scattering species in scat_data:\n"
719  << "scat_species has " << scat_species.nelem()
720  << " entries, while scat_data has " << scat_data.nelem() << ".";
721  throw runtime_error(os.str());
722  }
723 
724  // particle_masses:
725  if (!particle_masses.empty()) {
726  if (particle_masses.nrows() != np)
727  throw runtime_error(
728  "The WSV *particle_masses* must either be "
729  "empty or have a row size matching the "
730  "length of *scat_data*.");
731  if (min(particle_masses) < 0)
732  throw runtime_error("All values in *particles_masses* must be >= 0.");
733  }
734  }
735 
736  // If here, all OK
737  cloudbox_checked = 1;
738 }
739 
740 /* Workspace method: Doxygen documentation will be auto-generated */
743  const Vector& f_grid,
744  const Numeric& dfrel_threshold,
745  const String& check_level,
746  const Numeric& sca_mat_threshold,
747  const Verbosity& verbosity)
748 // FIXME: when we allow K, a, Z to be on different f and T grids, their use in
749 // the scatt solvers needs to be reviewed again and adapted to this!
750 {
751  // Prevent the user from producing nonsense by using too much freedom in
752  // setting the single freq validity threshold...
753  if (dfrel_threshold > 0.5) {
754  ostringstream os;
755  os << "*dfrel_threshold* too large (max. allowed: 0.5, your's: "
756  << dfrel_threshold << ").";
757  throw runtime_error(os.str());
758  }
759 
760  // freq range of calc covered?
761  if (f_grid.empty()) throw runtime_error("The frequency grid is empty.");
762  if (f_grid.nelem() > 1) chk_if_increasing("f_grid", f_grid);
763 
764  Index nf = f_grid.nelem();
765  Index N_ss = scat_data.nelem();
766  for (Index i_ss = 0; i_ss < N_ss; i_ss++) {
767  Index N_se = scat_data[i_ss].nelem();
768  for (Index i_se = 0; i_se < N_se; i_se++) {
769  // For each scattering element (se) check that se's f_grid is either
770  // identical to f_grid or contains a single entry only. In the latter
771  // case, the f/f_grid-ratio (equv. to a size parameter ratio) not allowed
772  // to exceed the dfrel_threshold.
773  Index nf_se = scat_data[i_ss][i_se].f_grid.nelem();
774  if (nf_se != 1) {
775  if (nf_se != nf) {
776  ostringstream os;
777  os << "*scat_data* must have either one or *f_grid* (=" << nf
778  << ") frequency entries,\n"
779  << "but scattering element #" << i_se << " in scattering species #"
780  << i_ss << " has " << nf_se << ".";
781  throw runtime_error(os.str());
782  } else {
783  for (Index f = 0; f < nf_se; f++) {
785  scat_data[i_ss][i_se].f_grid[f], f_grid[f], 0.5e-9)) {
786  ostringstream os;
787  os << "*scat_data* frequency grid has to be identical to *f_grid*\n"
788  << "(or contain only a single entry),\n"
789  << "but scattering element #" << i_se
790  << " in scattering species #" << i_ss
791  << " deviates for f_index " << f << ".";
792  throw runtime_error(os.str());
793  }
794  }
795  }
796  } else {
797  if ((abs(1. - scat_data[i_ss][i_se].f_grid[0] / f_grid[0]) >
798  dfrel_threshold) or
799  (abs(1. - scat_data[i_ss][i_se].f_grid[0] / f_grid[nf - 1]) >
800  dfrel_threshold)) {
801  ostringstream os;
802  os << "Frequency entry (f=" << scat_data[i_ss][i_se].f_grid[0]
803  << "Hz) of scattering element #" << i_se << "\n"
804  << "in scattering species #" << i_ss << " is too far (>"
805  << dfrel_threshold * 1e2 << "%) from one or more\n"
806  << "of the f_grid limits (fmin=" << f_grid[0]
807  << "Hz, fmax=" << f_grid[nf - 1] << "Hz).";
808  throw runtime_error(os.str());
809  }
810  }
811 
812  // check that the freq dimension of sca_mat, ext_mat, and abs_vec is
813  // either ssd.f_grid.nelem() or 1 (FIXME: so far, being freq dim !=
814  // ssd.f_grid.nelem() switched off, as usage in scatt solvers so far
815  // doesn't allow this. see FIXME at start.).
816  {
817  ostringstream bs1, bs2;
818  bs1 << "Frequency dimension of ";
819  //bs2 << " must be either one or ssd.f_grid.nelem() (=" << nf_se << "),\n"
820  bs2 << " must be ssd.f_grid.nelem() (=" << nf_se << "),\n"
821  << "but scattering element #" << i_se << " in scattering species #"
822  << i_ss << " is ";
823  Index nf_sd = scat_data[i_ss][i_se].pha_mat_data.nlibraries();
824  if (nf_sd != nf_se) //&& nf_sd != 1)
825  {
826  ostringstream os;
827  os << bs1.str() << "pha_mat_data" << bs2.str() << nf_se << ".";
828  throw runtime_error(os.str());
829  }
830  nf_sd = scat_data[i_ss][i_se].ext_mat_data.nshelves();
831  if (nf_sd != nf_se) //&& nf_sd != 1)
832  {
833  ostringstream os;
834  os << bs1.str() << "ext_mat_data" << bs2.str() << nf_se << ".";
835  throw runtime_error(os.str());
836  }
837  nf_sd = scat_data[i_ss][i_se].abs_vec_data.nshelves();
838  if (nf_sd != nf_se) //&& nf_sd != 1)
839  {
840  ostringstream os;
841  os << bs1.str() << "abs_vec_data" << bs2.str() << nf_se << ".";
842  throw runtime_error(os.str());
843  }
844  }
845 
846  // check that the temp dimension of K and a is ssd.T_grid.nelem(). For Z
847  // it might be ssd.T_grid.nelem() or 1.
848  {
849  ostringstream bs1, bs2;
850  Index nt_se = scat_data[i_ss][i_se].T_grid.nelem();
851  bs1 << "Temperature dimension of ";
852  //bs2 << " must be either one or ssd.T_grid.nelem(),\n"
853  bs2 << " must be ssd.T_grid.nelem() (=" << nt_se << "),\n"
854  << "but for scattering element #" << i_se
855  << " in scattering species #" << i_ss << " it is ";
856  Index nt_sd = scat_data[i_ss][i_se].pha_mat_data.nvitrines();
857  if (nt_sd != nt_se and nt_sd != 1) {
858  ostringstream os;
859  os << bs1.str() << "pha_mat_data" << bs2.str() << nt_sd << ".";
860  throw runtime_error(os.str());
861  }
862  nt_sd = scat_data[i_ss][i_se].ext_mat_data.nbooks();
863  if (nt_sd != nt_se) // no need to check for 1 here. since if it is 1,
864  // also T_grid.nelem need to be 1
865  {
866  ostringstream os;
867  os << bs1.str() << "ext_mat_data" << bs2.str() << nt_se << ".";
868  throw runtime_error(os.str());
869  }
870  nt_sd = scat_data[i_ss][i_se].abs_vec_data.nbooks();
871  if (nt_sd != nt_se) {
872  ostringstream os;
873  os << bs1.str() << "abs_vec_data" << bs2.str() << nt_se << ".";
874  throw runtime_error(os.str());
875  }
876  }
877  }
878  }
879 
880  if (check_level.toupper() != "NONE") {
881  // handing over to scat_dataCheck which checks whether
882  // 1) scat_data containing any NaN?
883  // 2) any negative values in Z11, K11, or a1?
884  // 3) sca_mat norm sufficiently good (int(Z11)~=K11-a1?)
885  // 1) & 2) always done
886  // 3) only done if scat_data_check_level is "all"
887  scat_dataCheck(scat_data, check_level, sca_mat_threshold, verbosity);
888  }
889 
890  // If here, all OK
891  scat_data_checked = 1;
892 }
893 
894 /* Workspace method: Doxygen documentation will be auto-generated */
900  const Verbosity&)
901 {
904 
905  lbl_checked = false;
906 
907  if (abs_lines_per_species.nelem() not_eq abs_species.nelem()) {
908  std::ostringstream os;
909  os << "abs_lines_per_species and abs_species must have same length.\n"
910  << "Instead len(abs_lines_per_species) = "
911  << abs_lines_per_species.nelem()
912  << " and len(abs_species) = "
913  << abs_species.nelem()
914  << '\n';
915  throw std::runtime_error(os.str());
916  }
917 
918  for (Index i=0; i<abs_species.nelem(); i++) {
919  auto& specs = abs_species[i];
920  auto& lines = abs_lines_per_species[i];
921 
922  if (not specs.nelem()) {
923  if (not lines.nelem()) {
924  continue;
925  } else {
926  throw std::runtime_error("Lines for non-existent species discovered!\n");
927  }
928  }
929 
930  const bool any_zeeman = std::any_of(specs.cbegin(), specs.cend(), [](auto& x){return x.Type() == SpeciesTag::TYPE_ZEEMAN;});
931  if (any_zeeman and (not std::all_of(specs.cbegin(), specs.cend(), [](auto& x){return x.Type() == SpeciesTag::TYPE_ZEEMAN;}))) {
932  std::ostringstream os;
933  os << "Zeeman species found but not all sub-species tags support Zeeman effect.\n";
934  os << "Offending tag: " << specs << '\n';
935  throw std::runtime_error(os.str());
936  }
937 
938  if (any_zeeman) {
939  for (auto& band: lines) {
940  for (Index k=0; k<band.NumLines(); k++) {
941  auto Fu = band.UpperQuantumNumber(k, QuantumNumberType::F);
942  auto Fl = band.LowerQuantumNumber(k, QuantumNumberType::F);
943  auto Ju = band.UpperQuantumNumber(k, QuantumNumberType::J);
944  auto Jl = band.LowerQuantumNumber(k, QuantumNumberType::J);
945  auto Ze = band.Line(k).Zeeman();
946  if (Fu.isUndefined() and Ju.isUndefined()) {
947  throw std::runtime_error("Bad upper state F(s) or J(s).\n");
948  } else if (Fl.isUndefined() and Jl.isUndefined()) {
949  throw std::runtime_error("Bad lower state F(s) or J(s).\n");
950  } else if (not is_wigner3_ready(Fu.isUndefined() ? Ju : Fu)) {
951  throw std::runtime_error("Bad Wigner numbers for lower state F or J. Try increasing the Wigner memory allocation.\n");
952  } else if (not is_wigner3_ready(Fl.isUndefined() ? Jl : Fl)) {
953  throw std::runtime_error("Bad Wigner numbers for lower state F or J. Try increasing the Wigner memory allocation.\n");
954  } else if (Ze.gu() == 0 ? false : not std::isnormal(Ze.gu())) {
955  throw std::runtime_error("Bad value(s) in the upper Zeeman data not allowed when modeling Zeeman effect.\n");
956  } else if (Ze.gl() == 0 ? false : not std::isnormal(Ze.gl())) {
957  throw std::runtime_error("Bad value(s) in the lower Zeeman data not allowed when modeling Zeeman effect.\n");
958  }
959  }
960  }
961  } else /*if (not any any_zeeman)*/ {
962  }
963 
964  // Checks per band
965  for (auto& band: lines) {
966  if (band.Mirroring() not_eq Absorption::MirroringType::Manual and std::any_of(band.AllLines().cbegin(), band.AllLines().cend(), [](auto& x){return x.F0() <= 0;})) {
967  throw std::runtime_error("Negative or zero frequency in non-Manual mirrored band.\n");
968  }
969  }
970  }
971 
972  lbl_checked = true;
973 }
974 
975 /* Workspace method: Doxygen documentation will be auto-generated */
977  Workspace& ws _U_,
979  // WS Input:
982  const Verbosity&) {
983  bool needs_lines = false;
984  bool needs_zeeman = false;
985  bool needs_continua = false;
986  bool needs_cia = false;
987  //bool needs_free_electrons = false;
988  bool needs_particles = false;
989  bool needs_hxsec = false;
990 
991  for (Index sp = 0; sp < abs_species.nelem(); sp++) {
992  for (Index tgs = 0; tgs < abs_species[sp].nelem(); tgs++) {
993  switch (abs_species[sp][tgs].Type()) {
995  needs_lines = true;
996  break;
998  needs_zeeman = true;
999  break;
1001  needs_continua = true;
1002  break;
1003  case SpeciesTag::TYPE_CIA:
1004  needs_cia = true;
1005  break;
1007  break;
1009  needs_particles = true;
1010  break;
1012  needs_hxsec = true;
1013  break;
1014  default:
1015  ostringstream os;
1016  os << "Unknown species type: " << abs_species[sp][tgs].Type();
1017  throw runtime_error(os.str());
1018  break;
1019  }
1020  }
1021  }
1022 
1023  if ((needs_lines || needs_continua || needs_cia || needs_hxsec) &&
1024  !(propmat_clearsky_agenda.has_method("propmat_clearskyAddOnTheFly") ||
1025  propmat_clearsky_agenda.has_method("propmat_clearskyAddFromLookup"))) {
1026  throw runtime_error(
1027  "*abs_species* contains line species, CIA species, "
1028  "hitran xsec species or continua but *propmat_clearsky_agenda*\n"
1029  "does not contain *propmat_clearskyAddOnTheFly* nor "
1030  "*propmat_clearskyAddFromLookup*.");
1031  }
1032 
1033  if (needs_zeeman and
1034  not propmat_clearsky_agenda.has_method("propmat_clearskyAddZeeman")) {
1035  throw runtime_error(
1036  "*abs_species* contains Zeeman species but *propmat_clearsky_agenda*\n"
1037  "does not contain *propmat_clearskyAddZeeman*.");
1038  }
1039  /*
1040  if (needs_free_electrons
1041  && !propmat_clearsky_agenda.has_method("propmat_clearskyAddFaraday"))
1042  {
1043  throw runtime_error("*abs_species* contains free electrons but *propmat_clearsky_agenda*\n"
1044  "does not contain *propmat_clearskyAddFaraday*.");
1045  }
1046 */
1047  if (needs_particles &&
1048  !(propmat_clearsky_agenda.has_method("propmat_clearskyAddParticles") ||
1049  propmat_clearsky_agenda.has_method("propmat_clearskyAddParticles2"))) {
1050  throw runtime_error(
1051  "*abs_species* contains particles but *propmat_clearsky_agenda*\n"
1052  "does not contain *propmat_clearskyAddParticles*.");
1053  }
1054 
1056 }
1057 
1058 /* Workspace method: Doxygen documentation will be auto-generated */
1060  const Index& atmosphere_dim,
1061  const Index& stokes_dim,
1062  const Vector& f_grid,
1063  const Matrix& sensor_pos,
1064  const Matrix& sensor_los,
1065  const Matrix& transmitter_pos,
1066  const Matrix& mblock_dlos_grid,
1067  const Sparse& sensor_response,
1068  const Vector& sensor_response_f,
1071  const Verbosity&) {
1072  // Some sizes
1073  const Index nf = f_grid.nelem();
1074  const Index nlos = mblock_dlos_grid.nrows();
1075  const Index n1y = sensor_response.nrows();
1076  const Index nmblock = sensor_pos.nrows();
1077  const Index niyb = nf * nlos * stokes_dim;
1078 
1079  // Sensor position and LOS.
1080  //
1081  if (!is_increasing(f_grid))
1082  throw runtime_error("*f_grid* must be a strictly increasing vector.");
1083 
1084  // Sensor position and LOS.
1085  //
1086  if (sensor_pos.empty())
1087  throw runtime_error("*sensor_pos* is empty. This is not allowed.");
1088  if (sensor_los.empty())
1089  throw runtime_error("*sensor_los* is empty. This is not allowed.");
1090  //
1091  if (sensor_pos.ncols() != atmosphere_dim)
1092  throw runtime_error(
1093  "The number of columns of sensor_pos must be "
1094  "equal to the atmospheric dimensionality.");
1095  if (atmosphere_dim <= 2 && sensor_los.ncols() != 1)
1096  throw runtime_error("For 1D and 2D, sensor_los shall have one column.");
1097  if (atmosphere_dim == 3 && sensor_los.ncols() != 2)
1098  throw runtime_error("For 3D, sensor_los shall have two columns.");
1099  if (sensor_los.nrows() != nmblock) {
1100  ostringstream os;
1101  os << "The number of rows of sensor_pos and sensor_los must be "
1102  << "identical, but sensor_pos has " << nmblock << " rows,\n"
1103  << "while sensor_los has " << sensor_los.nrows() << " rows.";
1104  throw runtime_error(os.str());
1105  }
1106  if (max(sensor_los(joker, 0)) > 180)
1107  throw runtime_error(
1108  "First column of *sensor_los* is not allowed to have values above 180.");
1109  if (atmosphere_dim == 2) {
1110  if (min(sensor_los(joker, 0)) < -180)
1111  throw runtime_error(
1112  "For atmosphere_dim = 2, first column of "
1113  "*sensor_los* is not allowed to have values below -180.");
1114  } else {
1115  if (min(sensor_los(joker, 0)) < 0)
1116  throw runtime_error(
1117  "For atmosphere_dim != 2, first column of "
1118  "*sensor_los* is not allowed to have values below 0.");
1119  }
1120  if (atmosphere_dim == 3) {
1121  if (max(sensor_los(joker, 1)) > 180)
1122  throw runtime_error(
1123  "Second column of *sensor_los* is not allowed to have values above 180.");
1124  else if (min(sensor_los(joker, 1)) < -180)
1125  throw runtime_error(
1126  "Second column of *sensor_los* is not allowed to have values below -180.");
1127  }
1128 
1129  // Transmission position.
1130  if (transmitter_pos.ncols() > 0 && transmitter_pos.nrows() > 0) {
1131  if (transmitter_pos.nrows() != sensor_pos.nrows())
1132  throw runtime_error(
1133  "*transmitter_pos* must either be empty or have "
1134  "the same number of rows as *sensor_pos*.");
1135  if (transmitter_pos.ncols() != max(Index(2), atmosphere_dim))
1136  throw runtime_error(
1137  "*transmitter_pos* must either be empty, have "
1138  "2 for 1D/2D or 3 columns for 3D.");
1139  }
1140 
1141  // mblock_dlos_grid
1142  //
1143  if (mblock_dlos_grid.empty())
1144  throw runtime_error("*mblock_dlos_grid* is empty.");
1145  if (mblock_dlos_grid.ncols() > 2)
1146  throw runtime_error(
1147  "The maximum number of columns in *mblock_dlos_grid* is two.");
1148  if (atmosphere_dim < 3) {
1149  if (mblock_dlos_grid.ncols() != 1)
1150  throw runtime_error(
1151  "For 1D and 2D *mblock_dlos_grid* must have exactly one column.");
1152  }
1153 
1154  // Sensor
1155  //
1156  if (sensor_response.ncols() != niyb) {
1157  ostringstream os;
1158  os << "The *sensor_response* matrix does not have the right size,\n"
1159  << "either the method *sensor_responseInit* has not been run or some\n"
1160  << "of the other sensor response methods has not been correctly\n"
1161  << "configured.";
1162  throw runtime_error(os.str());
1163  }
1164 
1165  // Sensor aux variables
1166  //
1167  if (n1y != sensor_response_f.nelem() || n1y != sensor_response_pol.nelem() ||
1168  n1y != sensor_response_dlos.nrows()) {
1169  ostringstream os;
1170  os << "Sensor auxiliary variables do not have the correct size.\n"
1171  << "The following variables should all have same size:\n"
1172  << "length of y for one block : " << n1y << "\n"
1173  << "sensor_response_f.nelem() : " << sensor_response_f.nelem()
1174  << "\nsensor_response_pol.nelem() : " << sensor_response_pol.nelem()
1175  << "\nsensor_response_dlos.nrows(): " << sensor_response_dlos.nrows()
1176  << "\n";
1177  throw runtime_error(os.str());
1178  }
1179 
1180  // If here, all OK
1181  sensor_checked = 1;
1182 }
Matrix
The Matrix class.
Definition: matpackI.h:1193
checkPartitionFunctions
void checkPartitionFunctions(const ArrayOfArrayOfSpeciesTag &abs_species, const SpeciesAuxData &partfun)
Check that partition functions for the given species are correctly defined.
Definition: absorption.cc:356
ARTS::Var::atmosphere_dim
Index atmosphere_dim(Workspace &ws) noexcept
Definition: autoarts.h:2510
ARTS::Var::wind_v_field
Tensor3 wind_v_field(Workspace &ws) noexcept
Definition: autoarts.h:7246
is_same_within_epsilon
bool is_same_within_epsilon(const Numeric &a, const Numeric &b, const Numeric &epsilon)
Check, if two numbers agree within a given epsilon.
Definition: logic.cc:351
ARTS::Var::z_field
Tensor3 z_field(Workspace &ws) noexcept
Definition: autoarts.h:7690
my_basic_string::toupper
void toupper()
Convert to upper case.
Definition: mystring.h:74
auto_md.h
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:1689
ARTS::Var::atmgeom_checked
Index atmgeom_checked(Workspace &ws) noexcept
Definition: autoarts.h:2489
ARTS::Var::jacobian_quantities
ArrayOfRetrievalQuantity jacobian_quantities(Workspace &ws) noexcept
Definition: autoarts.h:3924
chk_if_increasing
void chk_if_increasing(const String &x_name, const ArrayOfIndex &x)
chk_if_increasing
Definition: check_input.cc:117
ARTS::Var::transmitter_pos
Matrix transmitter_pos(Workspace &ws) noexcept
Definition: autoarts.h:7093
Tensor3
The Tensor3 class.
Definition: matpackIII.h:339
LAT_LON_MIN
const Numeric LAT_LON_MIN
chk_if_bool
void chk_if_bool(const String &x_name, const Index &x)
chk_if_bool
Definition: check_input.cc:65
QuantumNumberType::F
@ F
ARTS::Var::sensor_response
Sparse sensor_response(Workspace &ws) noexcept
Definition: autoarts.h:6300
is_wigner3_ready
bool is_wigner3_ready(const Rational &J)
Tells if the function is ready for Wigner 3J calculations.
Definition: wigner_functions.cc:319
ARTS::Var::lat_grid
Vector lat_grid(Workspace &ws) noexcept
Definition: autoarts.h:3962
joker
const Joker joker
ARTS::Var::pnd_field
Tensor4 pnd_field(Workspace &ws) noexcept
Definition: autoarts.h:5081
abs
#define abs(x)
Definition: legacy_continua.cc:20626
ARTS::Var::verbosity
Verbosity verbosity(Workspace &ws) noexcept
Definition: autoarts.h:7112
Sparse
The Sparse class.
Definition: matpackII.h:60
ARTS::Var::cloudbox_limits
ArrayOfIndex cloudbox_limits(Workspace &ws) noexcept
Definition: autoarts.h:2762
ARTS::Var::wind_u_field
Tensor3 wind_u_field(Workspace &ws) noexcept
Definition: autoarts.h:7211
Vector::resize
void resize(Index n)
Resize function.
Definition: matpackI.cc:404
ARTS::Var::abs_lines_per_species
ArrayOfArrayOfAbsorptionLines abs_lines_per_species(Workspace &ws) noexcept
Definition: autoarts.h:2022
ARTS::Var::mag_w_field
Tensor3 mag_w_field(Workspace &ws) noexcept
Definition: autoarts.h:4197
data
G0 G2 FVC Y DV Numeric Numeric Numeric Zeeman LowerQuantumNumbers void * data
Definition: arts_api_classes.cc:232
ARTS::Var::stokes_dim
Index stokes_dim(Workspace &ws) noexcept
Definition: autoarts.h:6650
SpeciesAuxData::AT_PARTITIONFUNCTION_TFIELD
@ AT_PARTITIONFUNCTION_TFIELD
Definition: absorption.h:223
sensor_checkedCalc
void sensor_checkedCalc(Index &sensor_checked, const Index &atmosphere_dim, const Index &stokes_dim, const Vector &f_grid, const Matrix &sensor_pos, const Matrix &sensor_los, const Matrix &transmitter_pos, const Matrix &mblock_dlos_grid, const Sparse &sensor_response, const Vector &sensor_response_f, const ArrayOfIndex &sensor_response_pol, const Matrix &sensor_response_dlos, const Verbosity &)
WORKSPACE METHOD: sensor_checkedCalc.
Definition: m_checked.cc:1059
atmfields_checkedCalc
void atmfields_checkedCalc(Index &atmfields_checked, 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 Tensor3 &wind_u_field, const Tensor3 &wind_v_field, const Tensor3 &wind_w_field, const Tensor3 &mag_u_field, const Tensor3 &mag_v_field, const Tensor3 &mag_w_field, const SpeciesAuxData &partition_functions, const Index &abs_f_interp_order, const Index &negative_vmr_ok, const Index &bad_partition_functions_ok, const Verbosity &)
WORKSPACE METHOD: atmfields_checkedCalc.
Definition: m_checked.cc:125
scat_data_checkedCalc
void scat_data_checkedCalc(Index &scat_data_checked, const ArrayOfArrayOfSingleScatteringData &scat_data, const Vector &f_grid, const Numeric &dfrel_threshold, const String &check_level, const Numeric &sca_mat_threshold, const Verbosity &verbosity)
WORKSPACE METHOD: scat_data_checkedCalc.
Definition: m_checked.cc:741
TotalNumberOfElements
Index TotalNumberOfElements(const Array< Array< base > > &aa)
Determine total number of elements in an ArrayOfArray.
Definition: array.h:343
Tensor4
The Tensor4 class.
Definition: matpackIV.h:421
SpeciesAuxData
Auxiliary data for isotopologues.
Definition: absorption.h:217
Agenda
The Agenda class.
Definition: agenda_class.h:44
ARTS::Var::lon_true
Vector lon_true(Workspace &ws) noexcept
Definition: autoarts.h:4113
matpackI.h
Implementation of Matrix, Vector, and such stuff.
Array
This can be used to make arrays out of anything.
Definition: array.h:108
SpeciesTag
A tag group can consist of the sum of several of these.
Definition: abs_species_tags.h:44
SpeciesAuxData::AT_PARTITIONFUNCTION_COEFF
@ AT_PARTITIONFUNCTION_COEFF
Definition: absorption.h:224
ARTS::Var::sensor_response_f
Vector sensor_response_f(Workspace &ws) noexcept
Definition: autoarts.h:6376
checkIsotopologueRatios
void checkIsotopologueRatios(const ArrayOfArrayOfSpeciesTag &abs_species, const SpeciesAuxData &isoratios)
Check that isotopologue ratios for the given species are correctly defined.
Definition: absorption.cc:301
min
#define min(a, b)
Definition: legacy_continua.cc:20628
lbl_checkedCalc
void lbl_checkedCalc(Index &lbl_checked, const ArrayOfArrayOfAbsorptionLines &abs_lines_per_species, const ArrayOfArrayOfSpeciesTag &abs_species, const SpeciesAuxData &isotopologue_ratios, const SpeciesAuxData &partition_functions, const Verbosity &)
WORKSPACE METHOD: lbl_checkedCalc.
Definition: m_checked.cc:895
ARTS::Var::particle_masses
Matrix particle_masses(Workspace &ws) noexcept
Definition: autoarts.h:4850
_U_
#define _U_
Definition: config.h:183
my_basic_string< char >
ConstVectorView::nelem
Index nelem() const
Returns the number of elements.
Definition: matpackI.cc:51
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:532
ARTS::Var::vmr_field
Tensor4 vmr_field(Workspace &ws) noexcept
Definition: autoarts.h:7130
ARTS::Var::abs_species
ArrayOfArrayOfSpeciesTag abs_species(Workspace &ws) noexcept
Definition: autoarts.h:2157
ARTS::Var::atmfields_checked
Index atmfields_checked(Workspace &ws) noexcept
Definition: autoarts.h:2473
ARTS::Var::p_grid
Vector p_grid(Workspace &ws) noexcept
Definition: autoarts.h:4763
DEG2RAD
const Numeric DEG2RAD
SpeciesTag::TYPE_FREE_ELECTRONS
@ TYPE_FREE_ELECTRONS
Definition: abs_species_tags.h:152
Numeric
NUMERIC Numeric
The type to use for all floating point numbers.
Definition: matpack.h:33
Verbosity
Definition: messages.h:49
SpeciesTag::TYPE_ZEEMAN
@ TYPE_ZEEMAN
Definition: abs_species_tags.h:149
chk_atm_vecfield_lat90
void chk_atm_vecfield_lat90(const String &x1_name, ConstTensor3View x1, const String &x2_name, ConstTensor3View x2, const Index &dim, ConstVectorView lat_grid, const Numeric &threshold)
chk_atm_vecfield_lat90
Definition: check_input.cc:1540
ARTS::Var::refellipsoid
Vector refellipsoid(Workspace &ws) noexcept
Definition: autoarts.h:5519
ARTS::Var::f_grid
Vector f_grid(Workspace &ws) noexcept
Definition: autoarts.h:3449
ARTS::Var::lat_true
Vector lat_true(Workspace &ws) noexcept
Definition: autoarts.h:3985
ARTS::Var::sensor_pos
Matrix sensor_pos(Workspace &ws) noexcept
Definition: autoarts.h:6279
Absorption::MirroringType::None
@ None
ARTS::Var::abs_xsec_agenda
Agenda abs_xsec_agenda(Workspace &ws) noexcept
Definition: autoarts.h:2274
max
#define max(a, b)
Definition: legacy_continua.cc:20629
ARTS::Var::scat_data
ArrayOfArrayOfSingleScatteringData scat_data(Workspace &ws) noexcept
Definition: autoarts.h:5840
LineShape::Type
Type
Type of line shape to compute.
Definition: lineshapemodel.h:788
ARTS::Var::lon_grid
Vector lon_grid(Workspace &ws) noexcept
Definition: autoarts.h:4090
ARTS::Var::dpnd_field_dx
ArrayOfTensor4 dpnd_field_dx(Workspace &ws) noexcept
Definition: autoarts.h:3251
cloudbox.h
Internal cloudbox functions.
ARTS::Var::scat_data_checked
Index scat_data_checked(Workspace &ws) noexcept
Definition: autoarts.h:5850
ARTS::Var::mblock_dlos_grid
Matrix mblock_dlos_grid(Workspace &ws) noexcept
Definition: autoarts.h:4247
ARTS::Var::sensor_response_pol
ArrayOfIndex sensor_response_pol(Workspace &ws) noexcept
Definition: autoarts.h:6411
ARTS::Var::lbl_checked
Index lbl_checked(Workspace &ws) noexcept
Definition: autoarts.h:3996
ARTS::Var::propmat_clearsky_agenda_checked
Index propmat_clearsky_agenda_checked(Workspace &ws) noexcept
Definition: autoarts.h:5414
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, const bool &chk_lat90)
chk_atm_field (simple fields)
Definition: check_input.cc:1268
is_increasing
bool is_increasing(ConstVectorView x)
Checks if a vector is sorted and strictly increasing.
Definition: logic.cc:215
abs_xsec_agenda_checkedCalc
void abs_xsec_agenda_checkedCalc(Workspace &ws, Index &abs_xsec_agenda_checked, const ArrayOfArrayOfSpeciesTag &abs_species, const Agenda &abs_xsec_agenda, const Verbosity &)
WORKSPACE METHOD: abs_xsec_agenda_checkedCalc.
Definition: m_checked.cc:44
SpeciesTag::TYPE_PLAIN
@ TYPE_PLAIN
Definition: abs_species_tags.h:148
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:1201
atmgeom_checkedCalc
void atmgeom_checkedCalc(Index &atmgeom_checked, const Index &atmosphere_dim, const Vector &p_grid, const Vector &lat_grid, const Vector &lon_grid, const Tensor3 &z_field, const Vector &refellipsoid, const Matrix &z_surface, const Vector &lat_true, const Vector &lon_true, const Verbosity &)
WORKSPACE METHOD: atmgeom_checkedCalc.
Definition: m_checked.cc:383
ARTS::Var::mag_v_field
Tensor3 mag_v_field(Workspace &ws) noexcept
Definition: autoarts.h:4164
ARTS::Var::t_field
Tensor3 t_field(Workspace &ws) noexcept
Definition: autoarts.h:6947
Workspace
Workspace class.
Definition: workspace_ng.h:40
ARTS::Var::abs_xsec_agenda_checked
Index abs_xsec_agenda_checked(Workspace &ws) noexcept
Definition: autoarts.h:2283
scat_dataCheck
void scat_dataCheck(const ArrayOfArrayOfSingleScatteringData &scat_data, const String &check_type, const Numeric &threshold, const Verbosity &verbosity)
WORKSPACE METHOD: scat_dataCheck.
Definition: m_optproperties.cc:1094
ARTS::Var::partition_functions
SpeciesAuxData partition_functions(Workspace &ws) noexcept
Definition: autoarts.h:4860
ARTS::Var::wind_w_field
Tensor3 wind_w_field(Workspace &ws) noexcept
Definition: autoarts.h:7279
ARTS::Var::isotopologue_ratios
SpeciesAuxData isotopologue_ratios(Workspace &ws) noexcept
Definition: autoarts.h:3669
SpeciesTag::TYPE_PREDEF
@ TYPE_PREDEF
Definition: abs_species_tags.h:150
ARTS::Var::sensor_checked
Index sensor_checked(Workspace &ws) noexcept
Definition: autoarts.h:6144
ARTS::Var::propmat_clearsky_agenda
Agenda propmat_clearsky_agenda(Workspace &ws) noexcept
Definition: autoarts.h:5405
propmat_clearsky_agenda_checkedCalc
void propmat_clearsky_agenda_checkedCalc(Workspace &ws, Index &propmat_clearsky_agenda_checked, const ArrayOfArrayOfSpeciesTag &abs_species, const Agenda &propmat_clearsky_agenda, const Verbosity &)
WORKSPACE METHOD: propmat_clearsky_agenda_checkedCalc.
Definition: m_checked.cc:976
SpeciesAuxData::AT_PARTITIONFUNCTION_COEFF_VIBROT
@ AT_PARTITIONFUNCTION_COEFF_VIBROT
Definition: absorption.h:225
ARTS::Var::x
Vector x(Workspace &ws) noexcept
Definition: autoarts.h:7346
Index
INDEX Index
The type to use for all integer numbers and indices.
Definition: matpack.h:39
ARTS::Var::sensor_response_dlos
Matrix sensor_response_dlos(Workspace &ws) noexcept
Definition: autoarts.h:6340
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:89
ARTS::Var::scat_species
ArrayOfString scat_species(Workspace &ws) noexcept
Definition: autoarts.h:6086
ARTS::Var::mag_u_field
Tensor3 mag_u_field(Workspace &ws) noexcept
Definition: autoarts.h:4130
cloudbox_checkedCalc
void cloudbox_checkedCalc(Index &cloudbox_checked, const Index &atmfields_checked, const Index &atmosphere_dim, const Vector &p_grid, const Vector &lat_grid, const Vector &lon_grid, const Tensor3 &z_field, const Matrix &z_surface, const Tensor3 &wind_u_field, const Tensor3 &wind_v_field, const Tensor3 &wind_w_field, const Index &cloudbox_on, const ArrayOfIndex &cloudbox_limits, const Tensor4 &pnd_field, const ArrayOfTensor4 &dpnd_field_dx, const ArrayOfRetrievalQuantity &jacobian_quantities, const ArrayOfArrayOfSingleScatteringData &scat_data, const ArrayOfString &scat_species, const Matrix &particle_masses, const ArrayOfArrayOfSpeciesTag &abs_species, const Index &negative_pnd_ok, const Verbosity &)
WORKSPACE METHOD: cloudbox_checkedCalc.
Definition: m_checked.cc:484
SpeciesTag::TYPE_CIA
@ TYPE_CIA
Definition: abs_species_tags.h:151
Vector
The Vector class.
Definition: matpackI.h:860
SpeciesTag::TYPE_PARTICLES
@ TYPE_PARTICLES
Definition: abs_species_tags.h:153
SpeciesTag::TYPE_HITRAN_XSEC
@ TYPE_HITRAN_XSEC
Definition: abs_species_tags.h:154
Array::nelem
Index nelem() const
Number of elements.
Definition: array.h:195
ARTS::Var::sensor_los
Matrix sensor_los(Workspace &ws) noexcept
Definition: autoarts.h:6201
ARTS::Var::cloudbox_checked
Index cloudbox_checked(Workspace &ws) noexcept
Definition: autoarts.h:2650
ARTS::Var::z_surface
Matrix z_surface(Workspace &ws) noexcept
Definition: autoarts.h:7754
arts.h
The global header file for ARTS.
ARTS::Var::cloudbox_on
Index cloudbox_on(Workspace &ws) noexcept
Definition: autoarts.h:2782
ARTS::Var::abs_f_interp_order
Index abs_f_interp_order(Workspace &ws) noexcept
Definition: autoarts.h:1996
QuantumNumberType::J
@ J