45 Index& abs_xsec_agenda_checked,
48 const Agenda& abs_xsec_agenda,
50 bool needs_lines =
false;
51 bool needs_continua =
false;
52 bool needs_cia =
false;
53 bool needs_hxsec =
false;
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()) {
64 needs_continua =
true;
78 os <<
"Unknown species type: " << abs_species[sp][tgs].Type();
79 throw runtime_error(os.
str());
86 not(abs_xsec_agenda.
has_method(
"abs_xsec_per_speciesAddLines"))) {
88 "*abs_species* contains line species but *abs_xsec_agenda*\n" 89 "does not contain *abs_xsec_per_speciesAddLines*.");
93 !abs_xsec_agenda.
has_method(
"abs_xsec_per_speciesAddConts")) {
95 "*abs_species* contains continuum species but *abs_xsec_agenda*\n" 96 "does not contain *abs_xsec_per_speciesAddConts*.");
99 if (needs_cia && !abs_xsec_agenda.
has_method(
"abs_xsec_per_speciesAddCIA")) {
101 "*abs_species* contains CIA species but *abs_xsec_agenda*\n" 102 "does not contain *abs_xsec_per_speciesAddCIA*.");
106 !abs_xsec_agenda.
has_method(
"abs_xsec_per_speciesAddHitranXsec")) {
108 "*abs_species* contains HITRAN xsec species but *abs_xsec_agenda*\n" 109 "does not contain *abs_xsec_per_speciesAddHitranXsec*.");
113 if (not abs_xsec_agenda.
has_method(
"abs_xsec_per_speciesAddPredefinedO2MPM2020")) {
115 "*abs_species contains \"O2-MPM2020\" but *abs_xsec_agenda*\n" 116 "does not contain *abs_xsec_per_speciesAddPredefinedO2MPM2020*.");
121 abs_xsec_agenda_checked = 1;
126 const Index& atmosphere_dim,
140 const Index& abs_f_interp_order,
141 const Index& negative_vmr_ok,
142 const Index& bad_partition_functions_ok,
147 chk_atm_field(
"t_field", t_field, atmosphere_dim, p_grid, lat_grid, lon_grid);
157 if (!negative_vmr_ok && abs_species.
nelem() &&
min(vmr_field) < 0)
158 throw runtime_error(
"All values in *vmr_field* must be >= 0.");
161 if (
min(t_field) <= 0)
162 throw runtime_error(
"All temperatures in *t_field* must be > 0.");
165 if (wind_w_field.
npages() > 0) {
173 if (atmosphere_dim < 3 && wind_v_field.
npages() > 0) {
181 if (atmosphere_dim > 2) {
182 if (wind_u_field.
npages() > 0) {
183 if (wind_v_field.
npages() > 0) {
184 bool chk_poles =
false;
214 if (wind_v_field.
npages() > 0) {
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) {
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());
240 if (mag_w_field.
npages() > 0) {
248 if (mag_u_field.
npages() > 0) {
249 if (mag_v_field.
npages() > 0) {
250 bool chk_poles =
false;
280 if (mag_v_field.
npages() > 0) {
290 if (partition_functions.
nspecies()) {
292 Numeric min_T = 0, max_T = 1e6;
293 for (
Index ii = 0; ii < partition_functions.
nspecies(); ii++)
296 bool test_spec =
false;
297 for (
auto& as : abs_species)
299 if (s.Species() == ii and s.Isotopologue() == jj) test_spec =
true;
300 if (not test_spec)
continue;
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];
312 throw std::runtime_error(
313 "Bad coefficient parameter in partition_function.\n");
315 throw std::runtime_error(
316 "Bad coefficient parameter in partition_function.\n");
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];
327 throw std::runtime_error(
328 "Bad coefficient parameter in partition_function.\n");
330 throw std::runtime_error(
331 "Bad coefficient parameter in partition_function.\n");
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];
345 throw std::runtime_error(
346 "Bad t_field parameter in partition_function.\n");
348 throw std::runtime_error(
349 "Bad t_field parameter in partition_function.\n");
353 throw std::runtime_error(
354 "Bad parameter type in partition_functions.\n");
360 if (!bad_partition_functions_ok) {
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)) {
366 os <<
"There are bad partition functions in your setup.\n" 367 <<
"Minimum temperature for defined partition functions is: " 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());
379 atmfields_checked = 1;
384 const Index& atmosphere_dim,
389 const Vector& refellipsoid,
400 if (refellipsoid.
nelem() != 2)
402 "The WSV *refellispoid* must be a vector of " 404 if (refellipsoid[0] <= 0)
406 "The first element of *refellipsoid* must " 408 if (refellipsoid[1] < 0 || refellipsoid[1] > 1)
410 "The second element of *refellipsoid* must be " 412 if (atmosphere_dim == 1 && refellipsoid[1] != 0)
414 "For 1D, the second element of *refellipsoid* " 415 "(the eccentricity) must be 0.");
417 chk_atm_field(
"z_field", z_field, atmosphere_dim, p_grid, lat_grid, lon_grid);
418 chk_atm_surface(
"z_surface", z_surface, atmosphere_dim, lat_grid, lon_grid);
421 for (
Index row = 0; row < z_field.
nrows(); row++) {
422 for (
Index col = 0; col < z_field.
ncols(); col++) {
424 os <<
"z_field (for latitude nr " << row <<
" and longitude nr " << col
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)) {
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)
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());
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) {
464 "For 2D, *lat_true* must have same length as *lat_grid*.");
467 "For 2D, *lon_true* must have same length as *lat_grid*.");
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].");
485 const Index& atmfields_checked,
486 const Index& atmosphere_dim,
495 const Index& cloudbox_on,
502 const Matrix& particle_masses,
504 const Index& negative_pnd_ok,
506 if (atmfields_checked != 1)
508 "The atmospheric fields must be flagged to have " 509 "passed a consistency check (atmfields_checked=1).");
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());
529 Index has_absparticles = 0;
530 for (
Index sp = 0; sp < abs_species.
nelem() && has_absparticles < 1; sp++) {
532 has_absparticles = 1;
535 if (has_absparticles) {
537 "For scattering calculations (cloudbox is on)," 538 "abs_species is not allowed to contain\n" 539 "'particles' (absorbing-only particles)!");
543 if (cloudbox_limits.
nelem() != atmosphere_dim * 2) {
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());
551 if (cloudbox_limits[1] <= cloudbox_limits[0] || cloudbox_limits[0] < 0 ||
552 cloudbox_limits[1] >= p_grid.
nelem()) {
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());
563 Index nlat = 1, nlon = 1;
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) {
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());
578 if ((lat_grid[cloudbox_limits[2]] - lat_grid[0] <
LAT_LON_MIN) &&
579 (atmosphere_dim == 2 || (atmosphere_dim == 3 && lat_grid[0] > -90))) {
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());
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))) {
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());
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) {
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());
614 if (lon_grid[nlon - 1] - lon_grid[0] < 360) {
615 const Numeric latmax =
max(
abs(lat_grid[cloudbox_limits[2]]),
616 abs(lat_grid[cloudbox_limits[3]]));
618 if (lon_grid[cloudbox_limits[4]] - lon_grid[0] <
LAT_LON_MIN / lfac) {
620 os <<
"Too small distance between cloudbox and lower end of" 621 <<
"the longitude\ngrid. This distance must here be " 623 throw runtime_error(os.
str());
625 if (lon_grid[nlon - 1] - lon_grid[cloudbox_limits[5]] <
628 os <<
"Too small distance between cloudbox and upper end of" 629 <<
"the longitude\ngrid. This distance must here be " 631 throw runtime_error(os.
str());
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))
641 "The upper vertical limit of the cloudbox must be above " 642 "the surface altitude (for all latitudes and longitudes).");
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);
654 if (atmosphere_dim > 2) {
655 g3.
resize(cloudbox_limits[5] - cloudbox_limits[4] + 1);
658 chk_atm_field(
"pnd_field", pnd_field, atmosphere_dim, np, g1, g2, g3);
660 if (!negative_pnd_ok &&
min(pnd_field) < 0)
661 throw runtime_error(
"Negative values in *pnd_field* not allowed.");
665 for (
Index a = 0; a < g2.nelem(); a++) {
667 if (
max(pnd_field(
joker, 0, a, o)) > 0 &&
668 z_field(cloudbox_limits[0], a, o) > z_surface(a, o))
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).");
678 if (cloudbox_limits[1] != p_grid.
nelem() - 1)
681 "A non-zero value found in *pnd_field* at " 682 "upper altitude limit of the cloudbox.");
683 if (atmosphere_dim >= 2) {
686 "A non-zero value found in *pnd_field* at " 687 "lower latitude limit of the cloudbox.");
690 "A non-zero value found in *pnd_field* at " 691 "upper latitude limit of the cloudbox.");
693 if (atmosphere_dim == 3) {
696 "A non-zero value found in *pnd_field* at " 697 "lower longitude limit of the cloudbox.");
700 "A non-zero value found in *pnd_field* at " 701 "upper longitude limit of the cloudbox.");
705 if (dpnd_field_dx.
nelem() != jacobian_quantities.
nelem())
707 "Size of *dpnd_field_dx* inconsistent with number " 708 "of *jacobian_quantities*.");
714 if (scat_species.
nelem() > 0)
715 if (scat_species.
nelem() != scat_data.
nelem()) {
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());
725 if (!particle_masses.
empty()) {
726 if (particle_masses.
nrows() != np)
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.");
737 cloudbox_checked = 1;
744 const Numeric& dfrel_threshold,
745 const String& check_level,
746 const Numeric& sca_mat_threshold,
753 if (dfrel_threshold > 0.5) {
755 os <<
"*dfrel_threshold* too large (max. allowed: 0.5, your's: " 756 << dfrel_threshold <<
").";
757 throw runtime_error(os.
str());
761 if (f_grid.
empty())
throw runtime_error(
"The frequency grid is empty.");
766 for (
Index i_ss = 0; i_ss < N_ss; i_ss++) {
768 for (
Index i_se = 0; i_se < N_se; i_se++) {
773 Index nf_se = scat_data[i_ss][i_se].f_grid.
nelem();
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());
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)) {
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());
797 if ((
abs(1. - scat_data[i_ss][i_se].f_grid[0] / f_grid[0]) >
799 (
abs(1. - scat_data[i_ss][i_se].f_grid[0] / f_grid[nf - 1]) >
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());
818 bs1 <<
"Frequency dimension of ";
820 bs2 <<
" must be ssd.f_grid.nelem() (=" << nf_se <<
"),\n" 821 <<
"but scattering element #" << i_se <<
" in scattering species #" 823 Index nf_sd = scat_data[i_ss][i_se].pha_mat_data.nlibraries();
827 os << bs1.
str() <<
"pha_mat_data" << bs2.
str() << nf_se <<
".";
828 throw runtime_error(os.
str());
830 nf_sd = scat_data[i_ss][i_se].ext_mat_data.nshelves();
834 os << bs1.
str() <<
"ext_mat_data" << bs2.
str() << nf_se <<
".";
835 throw runtime_error(os.
str());
837 nf_sd = scat_data[i_ss][i_se].abs_vec_data.nshelves();
841 os << bs1.
str() <<
"abs_vec_data" << bs2.
str() << nf_se <<
".";
842 throw runtime_error(os.
str());
850 Index nt_se = scat_data[i_ss][i_se].T_grid.
nelem();
851 bs1 <<
"Temperature dimension of ";
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) {
859 os << bs1.
str() <<
"pha_mat_data" << bs2.
str() << nt_sd <<
".";
860 throw runtime_error(os.
str());
862 nt_sd = scat_data[i_ss][i_se].ext_mat_data.nbooks();
867 os << bs1.
str() <<
"ext_mat_data" << bs2.
str() << nt_se <<
".";
868 throw runtime_error(os.
str());
870 nt_sd = scat_data[i_ss][i_se].abs_vec_data.nbooks();
871 if (nt_sd != nt_se) {
873 os << bs1.
str() <<
"abs_vec_data" << bs2.
str() << nt_se <<
".";
874 throw runtime_error(os.
str());
880 if (check_level.
toupper() !=
"NONE") {
887 scat_dataCheck(scat_data, check_level, sca_mat_threshold, verbosity);
891 scat_data_checked = 1;
907 if (abs_lines_per_species.
nelem() not_eq abs_species.
nelem()) {
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()
915 throw std::runtime_error(os.str());
919 auto& specs = abs_species[
i];
920 auto& lines = abs_lines_per_species[
i];
922 if (not specs.nelem()) {
923 if (not lines.nelem()) {
926 throw std::runtime_error(
"Lines for non-existent species discovered!\n");
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;}))) {
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());
939 for (
auto& band: lines) {
940 for (
Index k=0; k<band.NumLines(); k++) {
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");
951 throw std::runtime_error(
"Bad Wigner numbers for lower state F or J. Try increasing the Wigner memory allocation.\n");
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");
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");
978 Index& propmat_clearsky_agenda_checked,
981 const Agenda& propmat_clearsky_agenda,
983 bool needs_lines =
false;
984 bool needs_zeeman =
false;
985 bool needs_continua =
false;
986 bool needs_cia =
false;
988 bool needs_particles =
false;
989 bool needs_hxsec =
false;
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()) {
1001 needs_continua =
true;
1009 needs_particles =
true;
1016 os <<
"Unknown species type: " << abs_species[sp][tgs].Type();
1017 throw runtime_error(os.
str());
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*.");
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*.");
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*.");
1055 propmat_clearsky_agenda_checked = 1;
1060 const Index& atmosphere_dim,
1061 const Index& stokes_dim,
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,
1070 const Matrix& sensor_response_dlos,
1077 const Index niyb = nf * nlos * stokes_dim;
1082 throw runtime_error(
"*f_grid* must be a strictly increasing vector.");
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.");
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) {
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());
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.");
1116 throw runtime_error(
1117 "For atmosphere_dim != 2, first column of " 1118 "*sensor_los* is not allowed to have values below 0.");
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.");
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.");
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.");
1156 if (sensor_response.
ncols() != niyb) {
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" 1162 throw runtime_error(os.
str());
1167 if (n1y != sensor_response_f.
nelem() || n1y != sensor_response_pol.
nelem() ||
1168 n1y != sensor_response_dlos.
nrows()) {
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()
1177 throw runtime_error(os.
str());
INDEX Index
The type to use for all integer numbers and indices.
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.
Index nelem() const
Number of elements.
bool empty() const
Returns true if variable size is zero.
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.
void scat_dataCheck(const ArrayOfArrayOfSingleScatteringData &scat_data, const String &check_type, const Numeric &threshold, const Verbosity &verbosity)
WORKSPACE METHOD: scat_dataCheck.
bool is_increasing(ConstVectorView x)
Checks if a vector is sorted and strictly increasing.
const Numeric LAT_LON_MIN
bool empty() const
Returns true if variable size is zero.
Index ncols() const
Returns the number of columns.
bool empty() const
Check if variable is empty.
Index nrows() const
Returns the number of rows.
G0 G2 FVC Y DV Numeric Numeric Numeric Zeeman LowerQuantumNumbers void * data
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.
Index nelem() const
Returns the number of elements.
Index ncols() const
Returns the number of columns.
const AuxType & getParamType(const Index species, const Index isotopologue) const
Return a constant reference to the parameter types.
Index TotalNumberOfElements(const Array< Array< base > > &aa)
Determine total number of elements in an ArrayOfArray.
The global header file for ARTS.
bool has_method(const String &methodname) const
Check if method is in Agenda.
bool is_same_within_epsilon(const Numeric &a, const Numeric &b, const Numeric &epsilon)
Check, if two numbers agree within a given epsilon.
_CS_string_type str() const
Index ncols() const
Returns the number of columns.
void toupper()
Convert to upper case.
Index nrows() const
Returns the number of rows.
A tag group can consist of the sum of several of these.
const ArrayOfGriddedField1 & getParam(const Index species, const Index isotopologue) const
Return a constant reference to the parameters.
NUMERIC Numeric
The type to use for all floating point numbers.
Index nspecies() const
Returns number of species.
Implementation of Matrix, Vector, and such stuff.
Index nisotopologues(const Index species) const
Returns number of isotopologues for a certain species.
basic_ostringstream< char, string_char_traits< char >, alloc > ostringstream
Index npages() const
Returns the number of pages.
bool is_wigner3_ready(const Rational &J)
Tells if the function is ready for Wigner 3J calculations.
void checkIsotopologueRatios(const ArrayOfArrayOfSpeciesTag &abs_species, const SpeciesAuxData &isoratios)
Check that isotopologue ratios for the given species are correctly defined.
void checkPartitionFunctions(const ArrayOfArrayOfSpeciesTag &abs_species, const SpeciesAuxData &partfun)
Check that partition functions for the given species are correctly defined.
void resize(Index n)
Resize function.
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.
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.
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.
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.
Auxiliary data for isotopologues.
Internal cloudbox functions.
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.
Index nrows() const
Returns the number of rows.