104 const Index& prepend,
112 as.insert(as.begin(), name);
154 const Index& interp_order,
158 out2 <<
" Interpolation order: " << interp_order <<
"\n";
161 ing_max = p_grid_out.
nelem() - 1;
163 "Atmospheric field to p_grid_out", p_grid_in, p_grid_out, interp_order);
165 Index nelem_in_range = ing_max - ing_min + 1;
168 if (nelem_in_range > 0) {
178 const Tensor3& atmtensor_in_orig,
181 const Index& interp_order,
186 "p_grid_old is supposed to be the p_grid associated with the "
187 "atmospheric field.\n"
188 "However, it is not as their sizes are inconsistent.\n")
190 const Tensor3* atmtensor_in_pnt;
193 if (&atmtensor_in_orig == &atmtensor_out) {
194 atmtensor_in_copy = atmtensor_in_orig;
195 atmtensor_in_pnt = &atmtensor_in_copy;
197 atmtensor_in_pnt = &atmtensor_in_orig;
199 const Tensor3& atmtensor_in = *atmtensor_in_pnt;
208 Index ing_min, ing_max;
221 (ing_max - ing_min + 1 != p_grid_new.
nelem()),
222 "New grid seems not to be sufficiently covered by old grid.\n")
224 for (
Index i = 0; i < atmtensor_in.
nrows(); i++)
225 for (
Index j = 0; j < atmtensor_in.
ncols(); j++)
226 reinterp(atmtensor_out(
joker, i, j), atmtensor_in(
joker, i, j), itw, lag_p);
233 const Tensor4& atmtensor_in_orig,
236 const Index& interp_order,
238 const Tensor4* atmtensor_in_pnt;
241 if (&atmtensor_in_orig == &atmtensor_out) {
242 atmtensor_in_copy = atmtensor_in_orig;
243 atmtensor_in_pnt = &atmtensor_in_copy;
245 atmtensor_in_pnt = &atmtensor_in_orig;
247 const Tensor4& atmtensor_in = *atmtensor_in_pnt;
252 atmtensor_in.
nrows(),
253 atmtensor_in.
ncols());
258 Index ing_min, ing_max;
271 (ing_max - ing_min + 1 != p_grid_new.
nelem()),
272 "New grid seems not to be sufficiently covered by old grid.\n")
275 for (
Index i = 0; i < atmtensor_in.
nrows(); i++)
276 for (
Index j = 0; j < atmtensor_in.
ncols(); j++)
277 reinterp(atmtensor_out(
b,
joker, i, j),
278 atmtensor_in(
b,
joker, i, j),
302 if (lon_grid.
empty()) {
305 if (lat_grid.
empty())
332 field_out = gfraw_in.
data;
350 field_out = gfraw_in.
data;
368 field_out = gfraw_in.
data;
381 if (!gfraw_in.
nelem()) {
383 out1 <<
" Warning: gfraw_in is empty, proceeding anyway\n";
384 field_out.
resize(0, 0, 0, 0);
388 gfraw_in[0].data.nrows(),
389 gfraw_in[0].data.ncols());
392 for (
Index i = 0; i < gfraw_in.
nelem(); i++) {
395 "p_grid",
"gfield.p_grid", p_grid, gfraw_in[i].get_numeric_grid(0));
398 lat_grid, lon_grid, 1, 2, gfraw_in[i]);
413 if (&gfraw_in_orig == &gfraw_out) {
414 gfraw_in_copy = gfraw_in_orig;
415 gfraw_in_pnt = &gfraw_in_copy;
417 gfraw_in_pnt = &gfraw_in_orig;
425 "Can't expand data because number of Latitudes and Longitudes is greater than 1");
456 gfraw_out.
data = gfraw_in.
data(0, 0);
469 if (&gfraw_in_orig == &gfraw_out) {
470 gfraw_in_copy = gfraw_in_orig;
471 gfraw_in_pnt = &gfraw_in_copy;
473 gfraw_in_pnt = &gfraw_in_orig;
481 "Can't expand data because number of Latitudes and Longitudes is greater than 1");
530 if (&gfraw_in_orig == &gfraw_out) {
531 gfraw_in_copy = gfraw_in_orig;
532 gfraw_in_pnt = &gfraw_in_copy;
534 gfraw_in_pnt = &gfraw_in_orig;
542 "Can't expand data because number of Latitudes and Longitudes is greater than 1");
601 gfraw_out.resize(gfraw_in.
nelem());
632 const Index p_grid_index,
634 const Index& interp_order,
635 const Index& zeropadding,
641 out2 <<
" Interpolation order: " << interp_order <<
"\n";
646 gfraw_out.
set_grid(p_grid_index, p_grid);
650 if (in_p_grid[0] < p_grid[p_grid.
nelem() - 1] ||
651 in_p_grid[in_p_grid.
nelem() - 1] > p_grid[0]) {
653 ing_max = ing_min - 1;
657 "Raw field to p_grid",
663 ing_max = p_grid.
nelem() - 1;
665 "Raw field to p_grid", in_p_grid, p_grid, interp_order);
667 Index nelem_in_range = ing_max - ing_min + 1;
670 if (nelem_in_range > 0) {
683 const Index& interp_order,
684 const Index& zeropadding,
689 if (&gfraw_in_orig == &gfraw_out) {
690 gfraw_in_copy = gfraw_in_orig;
691 gfraw_in_pnt = &gfraw_in_copy;
693 gfraw_in_pnt = &gfraw_in_orig;
697 const Index p_grid_index = 0;
710 Index ing_min, ing_max;
725 if (ing_max - ing_min < 0)
727 else if (ing_max - ing_min + 1 != p_grid.
nelem()) {
735 reinterp(gfraw_out.
data(
Range(ing_min, ing_max - ing_min + 1), i, j),
754 const Index& interp_order,
755 const Index& zeropadding,
760 if (&gfraw_in_orig == &gfraw_out) {
761 gfraw_in_copy = gfraw_in_orig;
762 gfraw_in_pnt = &gfraw_in_copy;
764 gfraw_in_pnt = &gfraw_in_orig;
768 const Index p_grid_index = 1;
785 Index ing_min, ing_max;
800 if (ing_max - ing_min < 0)
802 else if (ing_max - ing_min + 1 != p_grid.
nelem()) {
811 reinterp(gfraw_out.
data(
b,
Range(ing_min, ing_max - ing_min), i, j),
833 const Index& interp_order,
834 const Index& zeropadding,
836 agfraw_out.resize(agfraw_in.
nelem());
838 for (
Index i = 0; i < agfraw_in.
nelem(); i++) {
870 const Index lat_grid_index,
871 const Index lon_grid_index,
874 const Index& interp_order,
879 "The new latitude grid is not allowed to be empty.");
881 "The new longitude grid is not allowed to be empty.");
887 "Raw data has to be true 3D data (nlat>1 and nlon>1).");
889 out2 <<
" Interpolation order: " << interp_order <<
"\n";
895 gfraw_out.
set_grid(lat_grid_index, lat_true);
898 gfraw_out.
set_grid(lon_grid_index, lon_true);
903 "Raw field to lat_grid, 3D case", in_lat_grid, lat_true, interp_order);
919 const Index& interp_order,
922 "The new latitude grid is not allowed to be empty.");
924 "The new longitude grid is not allowed to be empty.");
929 if (&gfraw_in_orig == &gfraw_out) {
930 gfraw_in_copy = gfraw_in_orig;
931 gfraw_in_pnt = &gfraw_in_copy;
933 gfraw_in_pnt = &gfraw_in_orig;
937 const Index lat_grid_index = 0;
938 const Index lon_grid_index = 1;
942 "Raw data has to be true 3D data (nlat>1 and nlon>1).\n"
943 "Use GriddedFieldLatLonExpand to convert 1D or 2D data to 3D!\n")
953 const Vector& in_lat_grid =
955 const Vector& in_lon_grid =
959 for (
Index lat = 0; lat < in_lat_grid.
nelem(); lat++) {
961 gfraw_in.
data(lat, in_lon_grid.
nelem() - 1),
963 "Data values at 0 and 360 degrees for a cyclic longitude grid must match: \n"
964 ,
"Mismatch at latitude index : ", lat,
" ("
965 , in_lat_grid[lat],
" degrees)\n"
966 ,
"Value at 0 degrees longitude : ", gfraw_in.
data(lat, 0)
968 ,
"Value at 360 degrees longitude: "
969 , gfraw_in.
data(lat, in_lon_grid.
nelem() - 1),
"\n"
971 , gfraw_in.
data(lat, in_lon_grid.
nelem() - 1) -
972 gfraw_in.
data(lat, 0)
991 reinterp(gfraw_out.
data, gfraw_in.
data, itw, lag_lat, lag_lon);
1002 const Index& interp_order,
1005 "The new latitude grid is not allowed to be empty.");
1007 "The new longitude grid is not allowed to be empty.");
1012 if (&gfraw_in_orig == &gfraw_out) {
1013 gfraw_in_copy = gfraw_in_orig;
1014 gfraw_in_pnt = &gfraw_in_copy;
1016 gfraw_in_pnt = &gfraw_in_orig;
1020 const Index lat_grid_index = 1;
1021 const Index lon_grid_index = 2;
1025 "Raw data has to be true 3D data (nlat>1 and nlon>1).\n"
1026 "Use GriddedFieldLatLonExpand to convert 1D or 2D data to 3D!\n")
1039 const Vector& in_lat_grid =
1041 const Vector& in_lon_grid =
1045 for (
Index g0 = 0; g0 < in_grid0.
nelem(); g0++)
1046 for (
Index lat = 0; lat < in_lat_grid.
nelem(); lat++) {
1048 gfraw_in.
data(g0, lat, 0),
1049 gfraw_in.
data(g0, lat, in_lon_grid.
nelem() - 1),
1051 "Data values at 0 and 360 degrees for a cyclic longitude grid must match: \n"
1052 ,
"Mismatch at 1st grid index : " , g0 ,
" (" , in_grid0[g0]
1054 ,
" at latitude index : " , lat ,
" ("
1055 , in_lat_grid[lat] ,
" degrees)\n"
1056 ,
"Value at 0 degrees longitude : " , gfraw_in.
data(g0, lat, 0)
1058 ,
"Value at 360 degrees longitude: "
1059 , gfraw_in.
data(g0, lat, in_lon_grid.
nelem() - 1) ,
"\n"
1061 , gfraw_in.
data(g0, lat, in_lon_grid.
nelem() - 1) -
1062 gfraw_in.
data(g0, lat, 0)
1097 const Index& interp_order,
1100 "The new latitude grid is not allowed to be empty.");
1102 "The new longitude grid is not allowed to be empty.");
1107 if (&gfraw_in_orig == &gfraw_out) {
1108 gfraw_in_copy = gfraw_in_orig;
1109 gfraw_in_pnt = &gfraw_in_copy;
1111 gfraw_in_pnt = &gfraw_in_orig;
1115 const Index lat_grid_index = 2;
1116 const Index lon_grid_index = 3;
1120 "Raw data has to be true 3D data (nlat>1 and nlon>1).\n"
1121 "Use GriddedFieldLatLonExpand to convert 1D or 2D data to 3D!\n")
1152 const Vector& in_lat_grid =
1154 const Vector& in_lon_grid =
1158 for (
Index g0 = 0; g0 < in_grid0.
nelem(); g0++)
1159 for (
Index g1 = 0; g1 < in_grid1.
nelem(); g1++)
1160 for (
Index lat = 0; lat < in_lat_grid.
nelem(); lat++) {
1162 gfraw_in.
data(g0, g1, lat, 0),
1163 gfraw_in.
data(g0, g1, lat, in_lon_grid.
nelem() - 1),
1165 "Data values at 0 and 360 degrees for a cyclic longitude grid must match: \n"
1166 "Mismatch at 1st grid index : ", g0,
" ("
1167 , in_grid0[g0],
")\n"
1168 ,
" at 2nd grid index : ", g1,
" ("
1169 , in_grid1[g1],
")\n"
1170 ,
" at latitude index : ", lat,
" ("
1171 , in_lat_grid[lat],
" degrees)\n"
1172 ,
"Value at 0 degrees longitude : "
1173 , gfraw_in.
data(g0, g1, lat, 0),
"\n"
1174 ,
"Value at 360 degrees longitude: "
1175 , gfraw_in.
data(g0, g1, lat, in_lon_grid.
nelem() - 1),
"\n"
1177 , gfraw_in.
data(g0, g1, lat, in_lon_grid.
nelem() - 1) -
1178 gfraw_in.
data(g0, g1, lat, 0)
1202 const Index& interp_order,
1204 agfraw_out.resize(agfraw_in.
nelem());
1206 for (
Index i = 0; i < agfraw_in.
nelem(); i++) {
1239 const Index z_grid_index,
1241 const Index& interp_order,
1242 const Index& zeropadding,
1248 out2 <<
" Interpolation order: " << interp_order <<
"\n";
1253 if (in_z_grid[0] > z_grid[z_grid.
nelem() - 1] ||
1254 in_z_grid[in_z_grid.
nelem() - 1] < z_grid[0]) {
1256 ing_max = ing_min - 1;
1260 "Raw field to z_grid",
1266 ing_max = z_grid.
nelem() - 1;
1268 "Raw field to p_grid", in_z_grid, z_grid, interp_order);
1271 Index nelem_in_range = ing_max - ing_min + 1;
1274 if (nelem_in_range > 0) {
1290 const Index& interp_order,
1291 const Index& zeropadding,
1297 "*z_field* must be of the same size as *p_grid*, *lat_grid*, and *lon_grid* in *GriddedFieldZToPRegrid*.");
1307 "Gridding of field to regrid is bad.\n*GriddedFieldZToPRegrid* requires latitude and longitude to be on the same grid as *z_field*.");
1308 for (
Index ii = 0; ii < lat_grid.
nelem(); ii++)
1310 "Gridding of field to regrid is bad.\n*GriddedFieldZToPRegrid* requires latitude and longitude of the gridded field to be the same as for *z_field*.");
1311 for (
Index ii = 0; ii < lon_grid.
nelem(); ii++)
1313 "Gridding of field to regrid is bad.\n*GriddedFieldZToPRegrid* requires latitude and longitude of the gridded field to be the same as for *z_field*.");
1319 if (&gfraw_in_orig == &gfraw_out) {
1320 gfraw_in_copy = gfraw_in_orig;
1321 gfraw_in_pnt = &gfraw_in_copy;
1323 gfraw_in_pnt = &gfraw_in_orig;
1336 gfraw_out.
data = 0.;
1341 Index ing_min, ing_max;
1343 for (
Index lat_index = 0; lat_index < lat_grid.
nelem(); lat_index++) {
1344 for (
Index lon_index = 0; lon_index < lon_grid.
nelem(); lon_index++) {
1345 const Vector z_out = z_field(
joker, lat_index, lon_index);
1358 if (ing_max - ing_min >= 0) {
1361 if (ing_max - ing_min + 1 != z_out.
nelem()) {
1362 r =
Range(ing_min, ing_max - ing_min + 1);
1365 reinterp(gfraw_out.
data(r, lat_index, lon_index),
1366 gfraw_in.
data(
joker, lat_index, lon_index),
1379 const Index& atmosphere_dim,
1386 "Atmospheric dimension must be 1.")
1395 "Cannot extract fields from Matrix.\n"
1396 "*field_names* must have one element less than there are\n"
1402 for (
Index f = 0; f < field_names.
nelem(); f++) {
1403 fn_upper = field_names[f];
1406 if (fn_upper !=
"IGNORE") {
1413 Index nf_1 = f_1.size();
1415 for (
Index f = 0; f < nf_1; f++) {
1416 field_names_1[f] = field_names[f_1[f]];
1423 af.
set_grid(GFIELD4_FIELD_NAMES, field_names_1);
1430 af.
resize(nf_1, np, 1, 1);
1431 for (
Index f = 0; f < nf_1; f++)
1443 const Index& prepend,
1451 if (condensibles.
nelem()) {
1454 Tensor3 condensible_sum(vmrs.npages(), vmrs.nrows(), vmrs.ncols(), 1.);
1456 bool species_found =
false;
1457 for (
Index i = 0; !species_found && i < species.
nelem(); i++) {
1458 if (species[i] == condensibles[
c]) {
1460 species_found =
true;
1464 "Condensible species \"", condensibles[
c],
"\" not found "
1467 condensible_sum *= value;
1489 const Index& prepend,
1506 atm_fields_compact, new_n_fields, name, prepend, verbosity);
1508 const Index insert_pos = (prepend) ? 0 : new_n_fields - 1;
1514 "species p_grid to atm_fields_compact p_grid", sp_p_grid, af_p_grid);
1517 p2gridpos(p_gridpos, sp_p_grid, af_p_grid);
1519 if (sp_lat_grid.
nelem() > 1) {
1525 gridpos(lat_gridpos, sp_lat_grid, af_lat_grid);
1527 if (sp_lon_grid.
nelem() > 1) {
1532 gridpos(lon_gridpos, sp_lon_grid, af_lon_grid);
1540 interp(newfield, itw, species.
data, p_gridpos, lat_gridpos, lon_gridpos);
1550 newfield, itw, species.
data(
joker,
joker, 0), p_gridpos, lat_gridpos);
1561 atm_fields_compact.
data(insert_pos,
joker, 0, 0) = newfield;
1579 if (atm_fields_compact.
get_string_grid(GFIELD4_FIELD_NAMES)[i] !=
"T" &&
1584 if (afd(i, j, k, l) < threshold) afd(i, j, k, l) = 0.0;
1600 sp_name_grid[0] = name;
1602 atm_fields_compact.
set_grid(0, sp_name_grid);
1603 atm_fields_compact.
set_grid(1, sp_p_grid);
1604 atm_fields_compact.
set_grid(2, sp_lat_grid);
1605 atm_fields_compact.
set_grid(3, sp_lon_grid);
1620 const Index& prepend,
1623 for (
Index i = 0; i < batch_atm_fields_compact.
nelem(); i++) {
1640 const Index& prepend,
1642 const Index nelem = batch_atm_fields_compact.
nelem();
1645 bool failed =
false;
1649#pragma omp parallel for if (!arts_omp_in_parallel() && \
1650 nelem >= arts_omp_get_max_threads())
1651 for (
Index i = 0; i < nelem; i++) {
1654 batch_atm_fields_compact[i], name, species, prepend, verbosity);
1655 }
catch (
const std::exception& e) {
1656#pragma omp critical(batch_atm_fields_compactAddSpecies_fail)
1658 fail_msg = e.what();
1674 for (
Index i = 0; i < batch_atm_fields_compact.
nelem(); i++) {
1676 batch_atm_fields_compact[i], threshold, verbosity);
1684 const Index& atmosphere_dim,
1693 "No elements in atmospheric scenario batch.\n"
1694 "Check, whether any batch atmosphere file has been read!")
1700 batch_atm_fields_compact.resize(amnelem);
1703 bool failed =
false;
1706#pragma omp parallel for if (!arts_omp_in_parallel() && \
1707 amnelem >= arts_omp_get_max_threads())
1708 for (
Index i = 0; i < amnelem; ++i) {
1710 if (failed)
continue;
1725 }
catch (
const std::exception& e) {
1726#pragma omp critical(batch_atm_fields_compactFromArrayOfMatrix_fail)
1728 fail_msg = e.what();
1745 Tensor4& particle_bulkprop_field,
1751 const Index& atmosphere_dim,
1755 const Index& check_gridnames,
1763 c.get_numeric_grid(GFIELD4_P_GRID),
1764 c.get_numeric_grid(GFIELD4_LAT_GRID),
1765 c.get_numeric_grid(GFIELD4_LON_GRID));
1768 if (check_gridnames == 1) {
1774 const Index nf =
c.get_grid_size(GFIELD4_FIELD_NAMES);
1775 const Index np =
c.get_grid_size(GFIELD4_P_GRID);
1778 Index nlat =
c.get_grid_size(GFIELD4_LAT_GRID);
1779 Index nlon =
c.get_grid_size(GFIELD4_LON_GRID);
1780 if (nlat == 0) nlat++;
1781 if (nlon == 0) nlon++;
1784 p_grid =
c.get_numeric_grid(GFIELD4_P_GRID);
1785 lat_grid =
c.get_numeric_grid(GFIELD4_LAT_GRID);
1786 lon_grid =
c.get_numeric_grid(GFIELD4_LON_GRID);
1790 bool search_toa =
true;
1791 while (search_toa && l > 0) {
1792 if (p_grid[l - 1] < p_min)
1798 "At least one atmospheric level with pressure larger p_min (=",
1800 "is needed, but none is found.")
1801 const Index npn = l + 1;
1802 p_grid = p_grid[
Range(0, npn)];
1808 "There must be at least one absorption species.")
1823 const String as_type =
"abs_species";
1824 const String ss_type =
"scat_species";
1828 t_field.
resize(npn, nlat, nlon);
1829 for (
Index i = 0; i < nf; ++i) {
1830 if (
c.get_string_grid(GFIELD4_FIELD_NAMES)[i] ==
"T") {
1832 "Only one temperature ('T') field allowed,\n"
1833 "but found at least 2.")
1839 "One temperature ('T') field required, but none found")
1843 z_field.
resize(npn, nlat, nlon);
1844 for (
Index i = 0; i < nf; ++i) {
1845 if (
c.get_string_grid(GFIELD4_FIELD_NAMES)[i] ==
"z") {
1847 "Only one altitude ('z') field allowed,\n"
1848 "but found at least 2.")
1854 "One altitude ('z') field required, but none found")
1858 vmr_field.
resize(nsa, npn, nlat, nlon);
1859 for (
Index j = 0; j < nsa; ++j) {
1860 const String as_name = Species::toShortName(abs_species[j][0].Spec());
1865 while (!found && i < nf) {
1867 species_type,
c.get_string_grid(GFIELD4_FIELD_NAMES)[i], delim);
1869 if (species_type == as_type) {
1871 species_name,
c.get_string_grid(GFIELD4_FIELD_NAMES)[i], delim);
1872 if (species_name == as_name) {
1881 "No field for absorption species '", as_name,
"' found.")
1885 std::vector<Index> Idx;
1888 for (
Index i = 0; i < nf; ++i) {
1890 species_type,
c.get_string_grid(GFIELD4_FIELD_NAMES)[i], delim);
1892 if (species_type == ss_type) {
1897 const Index nsp = Idx.size();
1900 particle_bulkprop_field.
resize(nsp, npn, nlat, nlon);
1901 particle_bulkprop_field = NAN;
1902 particle_bulkprop_names.resize(nsp);
1906 for (
Index j = 0; j < nsp; ++j) {
1911 scat_type,
c.get_string_grid(GFIELD4_FIELD_NAMES)[Idx[j]], delim);
1914 species_name,
c.get_string_grid(GFIELD4_FIELD_NAMES)[Idx[j]], delim);
1919 particle_bulkprop_names[j] = species_name + delim + scat_type;
1925 Index& atmosphere_dim,
1932 out2 <<
" Sets the atmospheric dimensionality to 1.\n";
1933 out3 <<
" atmosphere_dim = 1\n";
1934 out3 <<
" lat_grid is set to be an empty vector\n";
1935 out3 <<
" lon_grid is set to be an empty vector\n";
1944 Index& atmosphere_dim,
1950 out2 <<
" Sets the atmospheric dimensionality to 2.\n";
1951 out3 <<
" atmosphere_dim = 2\n";
1952 out3 <<
" lon_grid is set to be an empty vector\n";
1960 Index& atmosphere_dim,
1967 out2 <<
" Sets the atmospheric dimensionality to 3.\n";
1968 out3 <<
" atmosphere_dim = 3\n";
1990 const Vector& nlte_energies,
1991 const Index& atmosphere_dim,
1993 const Index& interp_order,
1994 const Index& vmr_zeropadding,
1995 const Index& vmr_nonegative,
1996 const Index& nlte_when_negative,
2000 const Vector& tfr_p_grid =
2002 const Vector& tfr_lat_grid =
2004 const Vector& tfr_lon_grid =
2006 const Vector& zfr_p_grid =
2008 const Vector& zfr_lat_grid =
2010 const Vector& zfr_lon_grid =
2013 out2 <<
" Interpolation order: " << interp_order <<
"\n";
2027 if (atmosphere_dim == 1) {
2029 "Temperature data (T_field) has wrong dimension "
2033 "Altitude data (z_field) has wrong dimension "
2039 temp_gfield3, p_grid, t_field_raw, interp_order, 0, verbosity);
2040 t_field = temp_gfield3.
data;
2043 temp_gfield3, p_grid, z_field_raw, interp_order, 0, verbosity);
2044 z_field = temp_gfield3.
data;
2054 }
catch (
const std::runtime_error& e) {
2057 "Note that you can explicitly set vmr_zeropadding "
2058 "to 1 in the method call.")
2061 vmr_field, p_grid, lat_grid, lon_grid, temp_agfield3, verbosity);
2064 if (nlte_ids.
nelem() == nlte_field_raw.
nelem()) {
2066 temp_agfield3, p_grid, nlte_field_raw, interp_order, 0, verbosity);
2068 nlte_field.
value, p_grid, lat_grid, lon_grid, temp_agfield3, verbosity);
2076 else if (atmosphere_dim == 2) {
2078 "Raw data has wrong dimension (1D). "
2079 "You have to use \n"
2080 "AtmFieldsCalcExpand1D instead of AtmFieldsCalc.");
2087 if (nlte_ids.
nelem() == nlte_field_raw.
nelem())
2098 "Raw temperature to p_grid, 2D case", tfr_p_grid, p_grid, interp_order);
2121 "Raw z to p_grid, 2D case", zfr_p_grid, p_grid, interp_order);
2123 "Raw z to lat_grid, 2D case", zfr_lat_grid, lat_grid, interp_order);
2139 for (
Index gas_i = 0; gas_i < vmr_field_raw.
nelem(); gas_i++) {
2140 ARTS_USER_ERROR_IF(!(vmr_field_raw[gas_i].get_numeric_grid(GFIELD3_LAT_GRID).nelem() !=
2142 vmr_field_raw[gas_i].get_numeric_grid(GFIELD3_LON_GRID).nelem() ==
2144 "VMR data of the ", gas_i,
" the species has "
2145 "wrong dimension (1D or 3D). \n")
2150 var_string(
"Raw VMR[", gas_i,
"] to p_grid, 2D case"),
2151 vmr_field_raw[gas_i].get_numeric_grid(GFIELD3_P_GRID),
2155 var_string(
"Raw VMR[", gas_i,
"] to lat_grid, 2D case"),
2156 vmr_field_raw[gas_i].get_numeric_grid(GFIELD3_LAT_GRID),
2160 lag_p=
Interpolation::LagrangeVector(p_grid, vmr_field_raw[gas_i].get_numeric_grid(GFIELD3_P_GRID), interp_order, 0.5,
false, Interpolation::GridType::Log);
2173 for (
Index qi_i = 0; qi_i < nlte_field_raw.
nelem(); qi_i++) {
2174 ARTS_USER_ERROR_IF (!(nlte_field_raw[qi_i].get_numeric_grid(GFIELD3_LAT_GRID).nelem() !=
2176 nlte_field_raw[qi_i].get_numeric_grid(GFIELD3_LON_GRID).nelem() ==
2178 "NLTE data of the ", qi_i,
" temperature field has "
2179 "wrong dimension (1D or 3D). \n")
2184 var_string(
"Raw NLTE[", qi_i,
"] to p_grid, 2D case"),
2185 nlte_field_raw[qi_i].get_numeric_grid(GFIELD3_P_GRID),
2189 var_string(
"Raw NLTE[", qi_i,
"] to lat_grid, 2D case"),
2190 nlte_field_raw[qi_i].get_numeric_grid(GFIELD3_LAT_GRID),
2194 lag_p=
Interpolation::LagrangeVector(p_grid, nlte_field_raw[qi_i].get_numeric_grid(GFIELD3_P_GRID), interp_order, 0.5,
false, Interpolation::GridType::Log);
2199 if (nlte_ids.
nelem() == nlte_field_raw.
nelem())
2212 else if (atmosphere_dim == 3) {
2214 "Raw data has wrong dimension. You have to use \n"
2215 "AtmFieldsCalcExpand1D instead of AtmFieldsCalc.");
2220 temp_gfield3, lat_grid, lon_grid, t_field_raw, interp_order, verbosity);
2222 temp_gfield3, p_grid, temp_gfield3, interp_order, 0, verbosity);
2223 t_field = temp_gfield3.
data;
2226 temp_gfield3, lat_grid, lon_grid, z_field_raw, interp_order, verbosity);
2228 temp_gfield3, p_grid, temp_gfield3, interp_order, 0, verbosity);
2229 z_field = temp_gfield3.
data;
2245 }
catch (
const std::runtime_error& e) {
2248 "Note that you can explicitly set vmr_zeropadding "
2249 "to 1 in the method call.")
2252 vmr_field, p_grid, lat_grid, lon_grid, temp_agfield3, verbosity);
2254 if (nlte_field_raw.
nelem()) {
2264 temp_agfield3, p_grid, temp_agfield3, interp_order, 0, verbosity);
2265 }
catch (
const std::runtime_error& e) {
2267 "Note that you can explicitly set vmr_zeropadding "
2268 "to 1 in the method call.")
2271 if (nlte_ids.
nelem() == nlte_field_raw.
nelem())
2273 nlte_field.
value, p_grid, lat_grid, lon_grid, temp_agfield3, verbosity);
2284 if (vmr_nonegative) {
2285 for (
Index ib = 0; ib < vmr_field.
nbooks(); ib++) {
2286 for (
Index ip = 0; ip < vmr_field.
npages(); ip++) {
2287 for (
Index ir = 0; ir < vmr_field.
nrows(); ir++) {
2288 for (
Index ic = 0; ic < vmr_field.
ncols(); ic++) {
2289 if (vmr_field(ib, ip, ir, ic) < 0) {
2290 vmr_field(ib, ip, ir, ic) = 0;
2299 if (nlte_when_negative != -1) {
2300 if (nlte_field_raw.
nelem()) {
2305 if (nlte_field.
value(ib, ip, ir, ic) < 0) {
2307 nlte_field.
value(ib, ip, ir, ic) =
2308 nlte_when_negative == 1 ? t_field(ip, ir, ic) : 0;
2332 const Vector& refellipsoid,
2338 ARTS_USER_ERROR_IF(refellipsoid.
nelem() not_eq 2 or refellipsoid[0] < 1 or refellipsoid[1] >= 1 or refellipsoid[1] < 0,
"Bad refellipsoid: ", refellipsoid)
2342 mag_u_field = mag.u;
2343 mag_v_field = mag.v;
2344 mag_w_field = mag.w;
2359 const Index& atmosphere_dim,
2361 const Index& interp_order,
2365 const Vector& ufr_p_grid =
2367 const Vector& ufr_lat_grid =
2369 const Vector& ufr_lon_grid =
2371 const Vector& vfr_p_grid =
2373 const Vector& vfr_lat_grid =
2375 const Vector& vfr_lon_grid =
2377 const Vector& wfr_p_grid =
2379 const Vector& wfr_lat_grid =
2381 const Vector& wfr_lon_grid =
2384 out2 <<
" Interpolation order: " << interp_order <<
"\n";
2393 if (atmosphere_dim == 1) {
2395 "Magnetic u field data has wrong dimension (2D or 3D).\n");
2397 "Magnetic v field data has wrong dimension (2D or 3D).\n");
2399 "Magnetic w field data has wrong dimension (2D or 3D).\n");
2404 temp_gfield3, p_grid, mag_u_field_raw, interp_order, 0, verbosity);
2405 mag_u_field = temp_gfield3.
data;
2408 temp_gfield3, p_grid, mag_v_field_raw, interp_order, 0, verbosity);
2409 mag_v_field = temp_gfield3.
data;
2412 temp_gfield3, p_grid, mag_w_field_raw, interp_order, 0, verbosity);
2413 mag_w_field = temp_gfield3.
data;
2417 else if (atmosphere_dim == 2) {
2419 "Raw data has wrong dimension (1D). You have to use \n"
2420 "MagFieldsCalcExpand1D instead of MagFieldsCalc.");
2422 "Raw data has wrong dimension (1D). You have to use \n"
2423 "MagFieldsCalcExpand1D instead of MagFieldsCalc.");
2425 "Raw data has wrong dimension (1D). You have to use \n"
2426 "MagFieldsCalcExpand1D instead of MagFieldsCalc.");
2438 "Raw u field to p_grid, 2D case", ufr_p_grid, p_grid, interp_order);
2461 "Raw v field to p_grid, 2D case", vfr_p_grid, p_grid, interp_order);
2484 "Raw w field to p_grid, 2D case", wfr_p_grid, p_grid, interp_order);
2505 else if (atmosphere_dim == 3) {
2507 "Raw data has wrong dimension. You have to use \n"
2508 "MagFieldsCalcExpand1D instead of MagFieldsCalc.");
2510 "Raw data has wrong dimension. You have to use \n"
2511 "MagFieldsCalcExpand1D instead of MagFieldsCalc.");
2513 "Raw data has wrong dimension. You have to use \n"
2514 "MagFieldsCalcExpand1D instead of MagFieldsCalc.");
2525 temp_gfield3, p_grid, temp_gfield3, interp_order, 0, verbosity);
2526 mag_u_field = temp_gfield3.
data;
2535 temp_gfield3, p_grid, temp_gfield3, interp_order, 0, verbosity);
2536 mag_v_field = temp_gfield3.
data;
2545 temp_gfield3, p_grid, temp_gfield3, interp_order, 0, verbosity);
2546 mag_w_field = temp_gfield3.
data;
2568 const Index& interp_order,
2569 const Numeric& extrapolation_factor,
2571 const auto nalt = z_field.
npages();
2572 const auto nlat = z_field.
nrows();
2573 const auto nlon = z_field.
ncols();
2576 for (
auto& gf3 : {mag_u_field_raw, mag_v_field_raw, mag_w_field_raw}) {
2578 gf3.get_grid_name(1) not_eq
"Latitude" or
2579 gf3.get_grid_name(2) not_eq
"Longitude",
2581 "Grids must be Altitude, Latitude, Longitude, but are: ",
2582 gf3.get_grid_name(0),
", ", gf3.get_grid_name(1),
", ",
2583 gf3.get_grid_name(2),
'\n')
2589 u, lat_grid, lon_grid, mag_u_field_raw, interp_order, verbosity);
2591 v, lat_grid, lon_grid, mag_v_field_raw, interp_order, verbosity);
2593 w, lat_grid, lon_grid, mag_w_field_raw, interp_order, verbosity);
2596 mag_u_field.
resize(nalt, nlat, nlon);
2597 mag_v_field.
resize(nalt, nlat, nlon);
2598 mag_w_field.
resize(nalt, nlat, nlon);
2599 for (
Index ilat = 0; ilat < nlat; ilat++) {
2600 for (
Index ilon = 0; ilon < nlon; ilon++) {
2602 u.get_numeric_grid(0),
2603 z_field(
joker, ilat, ilon),
2605 extrapolation_factor,
2609 reinterp(mag_u_field(
joker, ilat, ilon),
u.data(
joker, ilat, ilon), itw, lag);
2612 v.get_numeric_grid(0),
2613 z_field(
joker, ilat, ilon),
2615 extrapolation_factor,
2620 reinterp(mag_v_field(
joker, ilat, ilon),
v.data(
joker, ilat, ilon), itw, lag);
2623 w.get_numeric_grid(0),
2624 z_field(
joker, ilat, ilon),
2626 extrapolation_factor,
2631 reinterp(mag_w_field(
joker, ilat, ilon),
w.data(
joker, ilat, ilon), itw, lag);
2648 const Index& atmosphere_dim,
2650 const Index& interp_order,
2654 const Vector& ufr_p_grid =
2656 const Vector& ufr_lat_grid =
2658 const Vector& ufr_lon_grid =
2660 const Vector& vfr_p_grid =
2662 const Vector& vfr_lat_grid =
2664 const Vector& vfr_lon_grid =
2666 const Vector& wfr_p_grid =
2668 const Vector& wfr_lat_grid =
2670 const Vector& wfr_lon_grid =
2673 out2 <<
" Interpolation order: " << interp_order <<
"\n";
2682 if (atmosphere_dim == 1) {
2684 "Wind u field data has wrong dimension (2D or 3D).\n");
2686 "Wind v field data has wrong dimension (2D or 3D).\n");
2688 "Wind w field data has wrong dimension (2D or 3D).\n");
2693 temp_gfield3, p_grid, wind_u_field_raw, interp_order, 0, verbosity);
2694 wind_u_field = temp_gfield3.
data;
2697 temp_gfield3, p_grid, wind_v_field_raw, interp_order, 0, verbosity);
2698 wind_v_field = temp_gfield3.
data;
2701 temp_gfield3, p_grid, wind_w_field_raw, interp_order, 0, verbosity);
2702 wind_w_field = temp_gfield3.
data;
2706 else if (atmosphere_dim == 2) {
2708 "Raw data has wrong dimension (1D). You have to use \n"
2709 "WindFieldsCalcExpand1D instead of WindFieldsCalc.");
2711 "Raw data has wrong dimension (1D). You have to use \n"
2712 "WindFieldsCalcExpand1D instead of WindFieldsCalc.");
2714 "Raw data has wrong dimension (1D). You have to use \n"
2715 "WindFieldsCalcExpand1D instead of WindFieldsCalc.");
2727 "Raw u field to p_grid, 2D case", ufr_p_grid, p_grid, interp_order);
2750 "Raw v field to p_grid, 2D case", vfr_p_grid, p_grid, interp_order);
2773 "Raw w field to p_grid, 2D case", wfr_p_grid, p_grid, interp_order);
2794 else if (atmosphere_dim == 3) {
2796 "Raw data has wrong dimension. You have to use \n"
2797 "WindFieldsCalcExpand1D instead of WindFieldsCalc.");
2799 "Raw data has wrong dimension. You have to use \n"
2800 "WindFieldsCalcExpand1D instead of WindFieldsCalc.");
2802 "Raw data has wrong dimension. You have to use \n"
2803 "WindFieldsCalcExpand1D instead of WindFieldsCalc.");
2814 temp_gfield3, p_grid, temp_gfield3, interp_order, 0, verbosity);
2815 wind_u_field = temp_gfield3.
data;
2824 temp_gfield3, p_grid, temp_gfield3, interp_order, 0, verbosity);
2825 wind_v_field = temp_gfield3.
data;
2834 temp_gfield3, p_grid, temp_gfield3, interp_order, 0, verbosity);
2835 wind_w_field = temp_gfield3.
data;
2857 const Vector& nlte_energies,
2858 const Index& atmosphere_dim,
2859 const Index& interp_order,
2860 const Index& vmr_zeropadding,
2861 const Index& vmr_nonegative,
2862 const Index& nlte_when_negative,
2868 "This function is intended for 2D and 3D. For 1D, use *AtmFieldsCalc*.");
2899 if (atmosphere_dim == 2) {
2906 t_field.
resize(np, nlat, nlon);
2907 z_field.
resize(np, nlat, nlon);
2908 vmr_field.
resize(nspecies, np, nlat, nlon);
2909 if (nlte_field_raw.
nelem()) {
2912 nlte_field.
levels = nlte_ids;
2918 for (
Index ilon = 0; ilon < nlon; ilon++) {
2919 for (
Index ilat = 0; ilat < nlat; ilat++) {
2920 for (
Index ip = 0; ip < np; ip++) {
2921 t_field(ip, ilat, ilon) = t_temp(ip, 0, 0);
2922 z_field(ip, ilat, ilon) = z_temp(ip, 0, 0);
2923 for (
Index is = 0; is < nspecies; is++) {
2924 vmr_field(is, ip, ilat, ilon) = vmr_temp(is, ip, 0, 0);
2926 for (
Index is = 0; is < nlte_field_raw.
nelem(); is++) {
2927 nlte_field.
value(is, ip, ilat, ilon) = nlte_temp.
value(is, ip, 0, 0);
2945 const Index& atmosphere_dim,
2946 const Index& interp_order,
2952 "This function is intended for 2D and 3D. For 1D, use *MagFieldsCalc*.");
2956 Tensor3 mag_u_field_temp, mag_v_field_temp, mag_w_field_temp;
2974 if (atmosphere_dim == 2) {
2982 mag_u_field.
resize(np, nlat, nlon);
2983 mag_v_field.
resize(np, nlat, nlon);
2984 mag_w_field.
resize(np, nlat, nlon);
2986 for (
Index ilon = 0; ilon < nlon; ilon++) {
2987 for (
Index ilat = 0; ilat < nlat; ilat++) {
2988 for (
Index ip = 0; ip < np; ip++) {
2989 mag_u_field(ip, ilat, ilon) = mag_u_field_temp(ip, 0, 0);
2990 mag_v_field(ip, ilat, ilon) = mag_v_field_temp(ip, 0, 0);
2991 mag_w_field(ip, ilat, ilon) = mag_w_field_temp(ip, 0, 0);
3007 const Index& atmosphere_dim,
3008 const Index& interp_order,
3014 "This function is intended for 2D and 3D. For 1D, use *WindFieldsCalc*.");
3018 Tensor3 wind_u_field_temp, wind_v_field_temp, wind_w_field_temp;
3036 if (atmosphere_dim == 2) {
3044 wind_u_field.
resize(np, nlat, nlon);
3045 wind_v_field.
resize(np, nlat, nlon);
3046 wind_w_field.
resize(np, nlat, nlon);
3048 for (
Index ilon = 0; ilon < nlon; ilon++) {
3049 for (
Index ilat = 0; ilat < nlat; ilat++) {
3050 for (
Index ip = 0; ip < np; ip++) {
3051 wind_u_field(ip, ilat, ilon) = wind_u_field_temp(ip, 0, 0);
3052 wind_v_field(ip, ilat, ilon) = wind_v_field_temp(ip, 0, 0);
3053 wind_w_field(ip, ilat, ilon) = wind_w_field_temp(ip, 0, 0);
3066 const Index& atmosphere_dim,
3067 const Index& chk_vmr_nan,
3078 const bool chknan = chk_vmr_nan;
3081 "No use in calling this method for 1D.");
3095 Tensor3 t_temp = t_field, z_temp = z_field;
3099 t_field.
resize(np, nlat, nlon);
3100 z_field.
resize(np, nlat, nlon);
3101 vmr_field.
resize(nspecies, np, nlat, nlon);
3103 for (
Index ilon = 0; ilon < nlon; ilon++) {
3104 for (
Index ilat = 0; ilat < nlat; ilat++) {
3105 for (
Index ip = 0; ip < np; ip++) {
3106 t_field(ip, ilat, ilon) = t_temp(ip, 0, 0);
3107 z_field(ip, ilat, ilon) = z_temp(ip, 0, 0);
3108 for (
Index is = 0; is < nspecies; is++) {
3109 vmr_field(is, ip, ilat, ilon) = vmr_temp(is, ip, 0, 0);
3126 if (atmosphere_dim == 1) {
3131 "Invalid of *ilat*. It must be >= 0 and less than "
3132 "length of *lat_grid*.");
3134 if (atmosphere_dim == 2) {
3136 vtmp = t_field(
joker, ilat, 0);
3138 t_field(
joker, 0, 0) = vtmp;
3139 vtmp = z_field(
joker, ilat, 0);
3141 z_field(
joker, 0, 0) = vtmp;
3146 }
else if (atmosphere_dim == 3) {
3148 "Invalid of *ilon*. It must be >= 0 and less than "
3149 "length of *lon_grid*.");
3151 vtmp = t_field(
joker, ilat, ilon);
3153 t_field(
joker, 0, 0) = vtmp;
3154 vtmp = z_field(
joker, ilat, ilon);
3156 z_field(
joker, 0, 0) = vtmp;
3176 Index& atmfields_checked,
3177 Index& atmgeom_checked,
3178 Index& cloudbox_checked,
3182 const Index& atmosphere_dim,
3185 const Index& interp_order,
3198 chk_atm_field(
"t_field", t_field, atmosphere_dim, p_grid, lat_grid, lon_grid);
3201 chk_atm_field(
"z_field", z_field, atmosphere_dim, p_grid, lat_grid, lon_grid);
3224 AtmFieldPRegrid(z_field, z_field, p_grid, p_old, interp_order, verbosity);
3225 AtmFieldPRegrid(t_field, t_field, p_grid, p_old, interp_order, verbosity);
3226 AtmFieldPRegrid(vmr_field, vmr_field, p_grid, p_old, interp_order, verbosity);
3236 Vector& nlte_vibrational_energies,
3244 String tmp_basename = basename;
3245 if (basename.length() && basename[basename.length() - 1] !=
'/')
3246 tmp_basename +=
".";
3249 String file_name = tmp_basename +
"t.xml";
3252 out3 <<
"Temperature field read from file: " << file_name <<
"\n";
3255 file_name = tmp_basename +
"z.xml";
3258 out3 <<
"Altitude field read from file: " << file_name <<
"\n";
3261 vmr_field_raw.resize(0);
3264 for (
Index i = 0; i < abs_species.
nelem(); i++) {
3266 file_name = tmp_basename +
3267 String(Species::toShortName(abs_species[i].
Species())) +
".xml";
3271 vmr_field_raw.push_back(vmr_field_data);
3275 file_name, vmr_field_raw[vmr_field_raw.
nelem() - 1], verbosity);
3278 out3 <<
" " << Species::toShortName(abs_species[i].
Species())
3279 <<
" profile read from file: " << file_name <<
"\n";
3283 nlte_field_raw.resize(0);
3284 nlte_quantum_identifiers.resize(0);
3285 nlte_vibrational_energies.
resize(0);
3298 String tmp_basename = basename;
3299 if (basename.length() && basename[basename.length() - 1] !=
'/')
3300 tmp_basename +=
".";
3303 String file_name = tmp_basename +
"mag_u.xml";
3306 out3 <<
"Bu field read from file: " << file_name <<
"\n";
3309 file_name = tmp_basename +
"mag_v.xml";
3312 out3 <<
"Bv field read from file: " << file_name <<
"\n";
3315 file_name = tmp_basename +
"mag_w.xml";
3318 out3 <<
"Bw field read from file: " << file_name <<
"\n";
3331 String tmp_basename = basename;
3332 if (basename.length() && basename[basename.length() - 1] !=
'/')
3333 tmp_basename +=
".";
3336 String file_name = tmp_basename +
"wind_u.xml";
3339 out3 <<
"Wind u field read from file: " << file_name <<
"\n";
3342 file_name = tmp_basename +
"wind_v.xml";
3345 out3 <<
"Wind v field read from file: " << file_name <<
"\n";
3348 file_name = tmp_basename +
"wind_w.xml";
3351 out3 <<
"Wind w field read from file: " << file_name <<
"\n";
3361 Vector& nlte_vibrational_energies,
3366 const Index& expect_vibrational_energies,
3370 String tmp_basename = basename;
3371 if (basename.length() && basename[basename.length() - 1] !=
'/')
3372 tmp_basename +=
".";
3375 String file_name = tmp_basename +
"t.xml";
3378 out3 <<
"Temperature field read from file: " << file_name <<
"\n";
3381 file_name = tmp_basename +
"z.xml";
3384 out3 <<
"Altitude field read from file: " << file_name <<
"\n";
3387 vmr_field_raw.resize(0);
3390 for (
Index i = 0; i < abs_species.
nelem(); i++) {
3392 file_name = tmp_basename +
3393 String(Species::toShortName(abs_species[i].
Species())) +
".xml";
3397 vmr_field_raw.push_back(vmr_field_data);
3401 file_name, vmr_field_raw[vmr_field_raw.
nelem() - 1], verbosity);
3404 out3 <<
" " << Species::toShortName(abs_species[i].
Species())
3405 <<
" profile read from file: " << file_name <<
"\n";
3409 file_name = tmp_basename +
"nlte.xml";
3412 out3 <<
"NLTE field array read from file: " << file_name <<
"\n";
3415 file_name = tmp_basename +
"qi.xml";
3418 out3 <<
"NLTE identifier array read from file: " << file_name <<
"\n";
3420 if (expect_vibrational_energies) {
3422 file_name = tmp_basename +
"ev.xml";
3425 out3 <<
"NLTE energy levels array read from file: " << file_name <<
"\n";
3428 nlte_vibrational_energies.
resize(0);
3432 (nlte_field_raw.
nelem() != nlte_vibrational_energies.
nelem() and
3433 0 != nlte_vibrational_energies.
nelem()),
3434 "The quantum identifers and the NLTE temperature fields\n"
3435 "are of different lengths. This should not be the case.\n"
3436 "please check the qi.xml and t_nlte.xml files under\n",
3438 "to correct this error.\n")
3446 const Index& interp_order,
3447 const Index& set_lowest_altitude_to_zero,
3451 out3 <<
"Reading GriddedField2 surface altitude from " << filename <<
"\n";
3455 out3 <<
"Surface altitude field interpolated back to lat_grid and lon_grid\n";
3462 z_surface = z_surface_field.
data;
3463 if (set_lowest_altitude_to_zero) {
3464 z_surface -=
min(z_surface);
3475 out3 <<
"Setting surface to constant altitude of " << altitude <<
" m\n";
3481 const Index& atmosphere_dim,
3515 out3 <<
" Result = " << outvalue <<
"\n";
3521 Index& atmfields_checked,
3522 Index& atmgeom_checked,
3523 Index& cloudbox_checked,
3525 const Vector& p_grid_old,
3533 "The old and new grids (p_grid and p_grid_old) are not allowed\n"
3534 "to be identical (pointing to same memory space).\n"
3535 "But they are doing in your case.")
3540 atmfields_checked = 0;
3541 atmgeom_checked = 0;
3542 cloudbox_checked = 0;
3547 // Nothing to do if nfill=0
3549 // Allocate new size for p_grid
3550 const Index n0 = p_grid_old.nelem();
3551 p_grid.resize((n0 - 1) * (1 + nfill) + 1);
3554 p_grid[0] = p_grid_old[0];
3556 for (Index i = 1; i < n0; i++) {
3559 pnew, 2 + nfill, p_grid_old[i - 1], p_grid_old[i], verbosity);
3560 for (Index j = 1; j < nfill + 2; j++) {
3562 p_grid[iout] = pnew[j];
3568/* Workspace method: Doxygen documentation will be auto-generated */
3569void p_gridRefine( // WS Output:
3571 Index& atmfields_checked,
3572 Index& atmgeom_checked,
3573 Index& cloudbox_checked,
3575 const Vector& p_grid_old,
3576 // Control Parameters:
3577 const Numeric& p_step10,
3579 // Check that p_grid and p_grid_old are not the same variable (pointing to the
3580 // same memory space). this as p_grid will be overwritten, but we will need
3581 // both data later on for data regridding.
3582 ARTS_USER_ERROR_IF (&p_grid == &p_grid_old,
3583 "The old and
new grids (p_grid and p_grid_old) are not allowed\n
"
3584 "to be identical (pointing to same memory space).\n
"
3585 "But they are doing in your
case.
")
3587 // as we manipoulate the overall vertical grid (but not simultaneously the
3588 // atmospheric fields), we reset all atmfields related checked WSV to
3589 // unchecked, forcing the user to do the checks again.
3590 atmfields_checked = 0;
3591 atmgeom_checked = 0;
3592 cloudbox_checked = 0;
3594 // Check the keyword argument:
3595 ARTS_USER_ERROR_IF (p_step10 <= 0,
3596 "The keyword argument p_step must be >0.
")
3598 // For consistency with other code around arts (e.g., correlation
3599 // lengths in atmlab), p_step is given as log10(p[Pa]). However, we
3600 // convert it here to the natural log:
3601 const Numeric p_step = log(pow(10.0, p_step10));
3603 // Now starting modification of p_grid
3605 // We will need the log of the pressure grid:
3606 Vector log_p_old(p_grid_old.nelem());
3607 transform(log_p_old, log, p_grid_old);
3609 // const Numeric epsilon = 0.01 * p_step; // This is the epsilon that
3610 // // we use for comparing p grid spacings.
3612 // Construct p_grid (new)
3613 // ----------------------
3615 ArrayOfNumeric log_p_new; // We take log_p_new as an array of Numeric, so
3616 // that we can easily build it up by appending new
3617 // elements to the end.
3619 // Check whether there are pressure levels that are further apart
3620 // (in log(p)) than p_step, and insert additional levels if
3623 log_p_new.push_back(log_p_old[0]);
3625 for (Index i = 1; i < log_p_old.nelem(); ++i) {
3627 log_p_old[i - 1] - log_p_old[i]; // The grid is descending.
3629 const Numeric dp_by_p_step = dp / p_step;
3630 // cout << "dp_by_p_step:
" << dp_by_p_step << "\n
";
3632 // How many times does p_step fit into dp?
3633 const Index n = (Index)ceil(dp_by_p_step);
3634 // n is the number of intervals that we want to have in the
3635 // new grid. The number of additional points to insert is
3636 // n-1. But we have to insert the original point as well.
3637 // cout << n << "\n
";
3639 const Numeric ddp = dp / (Numeric)n;
3640 // cout << "ddp:
" << ddp << "\n
";
3642 for (Index j = 1; j <= n; ++j)
3643 log_p_new.push_back(log_p_old[i - 1] - (Numeric)j * ddp);
3646 // Copy ArrayOfNumeric to proper vector.
3647 Vector log_p(log_p_new.nelem());
3648 for (Index i = 0; i < log_p_new.nelem(); ++i) log_p[i] = log_p_new[i];
3650 // Copy the new grid to abs_p, removing the log:
3651 p_grid.resize(log_p.nelem());
3652 transform(p_grid, exp, log_p);
3655/* Workspace method: Doxygen documentation will be auto-generated */
3656void p_gridFromZRaw( //WS Output
3659 const GriddedField3& z_field_raw,
3660 const Index& no_negZ,
3662 // original version excludes negative z. not clear, why this is. maybe is
3663 // currently a convention somehwere in ARTS (DOIT?). negative z seem, however,
3664 // to work fine for clear-sky cases. so we make the negative z exclude an
3665 // option (for consistency until unclarities solved, default: do exclude)
3666 Vector p_grid_raw = z_field_raw.get_numeric_grid(GFIELD3_P_GRID);
3669 if (is_increasing(z_field_raw.data(joker, 0, 0))) {
3672 while (z_field_raw.data(i, 0, 0) < 0.0) i++;
3674 p_grid = p_grid_raw[Range(i, joker)];
3675 } else if (is_decreasing(z_field_raw.data(joker, 0, 0))) {
3676 i = z_field_raw.data.npages() - 1;
3678 while (z_field_raw.data(i, 0, 0) < 0.0) i--;
3680 p_grid = p_grid_raw[Range(i, joker, -1)];
3683 "z_field_raw needs to be monotonous, but
this is not the
case.\n
")
3687/* Workspace method: Doxygen documentation will be auto-generated */
3688void lat_gridFromZRaw( //WS Output
3691 const GriddedField3& z_field_raw,
3693 lat_grid = z_field_raw.get_numeric_grid(GFIELD3_LAT_GRID);
3696/* Workspace method: Doxygen documentation will be auto-generated */
3697void lon_gridFromZRaw( //WS Output
3700 const GriddedField3& z_field_raw,
3702 lon_grid = z_field_raw.get_numeric_grid(GFIELD3_LON_GRID);
3705/* Workspace method: Doxygen documentation will be auto-generated */
3706void atm_gridsFromZRaw( //WS Output
3711 const GriddedField3& z_field_raw,
3712 const Index& no_negZ,
3713 const Verbosity& v) {
3714 p_gridFromZRaw(p_grid, z_field_raw, no_negZ, v);
3715 lat_gridFromZRaw(lat_grid, z_field_raw, v);
3716 lon_gridFromZRaw(lon_grid, z_field_raw, v);
3719/* Workspace method: Doxygen documentation will be auto-generated */
3720void lat_gridFromRawField( //WS Output
3723 const GriddedField3& field_raw,
3725 lat_grid = field_raw.get_numeric_grid(GFIELD3_LAT_GRID);
3728/* Workspace method: Doxygen documentation will be auto-generated */
3729void lon_gridFromRawField( //WS Output
3732 const GriddedField3& field_raw,
3734 lon_grid = field_raw.get_numeric_grid(GFIELD3_LON_GRID);
3737/* Workspace method: Doxygen documentation will be auto-generated */
3738void wind_u_fieldIncludePlanetRotation(Tensor3& wind_u_field,
3739 const Index& atmosphere_dim,
3740 const Vector& p_grid,
3741 const Vector& lat_grid,
3742 const Vector& lon_grid,
3743 const Vector& refellipsoid,
3744 const Tensor3& z_field,
3745 const Numeric& planet_rotation_period,
3747 ARTS_USER_ERROR_IF (atmosphere_dim < 3,
3748 "No need to use
this method
for 1D and 2D.
");
3750 const Index np = p_grid.nelem();
3751 const Index na = lat_grid.nelem();
3752 const Index no = lon_grid.nelem();
3754 chk_atm_field("z_field
", z_field, atmosphere_dim, p_grid, lat_grid, lon_grid);
3755 if (wind_u_field.npages() > 0) {
3756 chk_atm_field("wind_u_field
",
3763 wind_u_field.resize(np, na, no);
3767 const Numeric k1 = 2 * Constant::pi / planet_rotation_period;
3769 for (Index a = 0; a < na; a++) {
3770 const Numeric k2 = k1 * Conversion::cosd(lat_grid[a]);
3771 const Numeric re = refell2r(refellipsoid, lat_grid[a]);
3773 for (Index o = 0; o < no; o++) {
3774 for (Index p = 0; p < np; p++) {
3775 wind_u_field(p, a, o) += k2 * (re + z_field(p, a, o));
3781// A small help function
3782void z2g(Numeric& g, const Numeric& r, const Numeric& g0, const Numeric& z) {
3783 const Numeric x = r / (r + z);
3787/* Workspace method: Doxygen documentation will be auto-generated */
3788void z_fieldFromHSE(Workspace& ws,
3790 const Index& atmosphere_dim,
3791 const Vector& p_grid,
3792 const Vector& lat_grid,
3793 const Vector& lon_grid,
3794 const Vector& lat_true,
3795 const Vector& lon_true,
3796 const ArrayOfArrayOfSpeciesTag& abs_species,
3797 const Tensor3& t_field,
3798 const Tensor4& vmr_field,
3799 const Vector& refellipsoid,
3800 const Matrix& z_surface,
3801 const Index& atmfields_checked,
3802 const Agenda& g0_agenda,
3803 const Numeric& molarmass_dry_air,
3804 const Numeric& p_hse,
3805 const Numeric& z_hse_accuracy,
3806 const Verbosity& verbosity) {
3807 ARTS_USER_ERROR_IF (atmfields_checked != 1,
3808 "The atmospheric fields must be flagged to have
"
3809 "passed
a consistency check (atmfields_checked=1).
");
3811 // Some general variables
3812 const Index np = p_grid.nelem();
3813 const Index nlat = t_field.nrows();
3814 const Index nlon = t_field.ncols();
3816 const Index firstH2O = find_first_species(
3817 abs_species, Species::fromShortName("H2O
"));
3821 out1 << "No water vapour tag group in *abs_species*.\n
"
3822 << "Be aware that
this leads to significant variations in atmospheres\n
"
3823 << "that contain considerable amounts of water vapour (e.g. Earth)!\n
";
3826 ARTS_USER_ERROR_IF (p_hse > p_grid[0] || p_hse < p_grid[np - 1],
3827 "The value of *p_hse* must be inside the range of *p_grid*:
"
3828 " p_hse =
", p_hse, " Pa\n
"
3829 " p_grid =
", p_grid[np-1],
3830 " -
", p_grid[0], " Pa\n
")
3832 ARTS_USER_ERROR_IF (z_hse_accuracy <= 0,
3833 "The value of *z_hse_accuracy* must be > 0.
");
3835 chk_latlon_true(atmosphere_dim, lat_grid, lat_true, lon_true);
3837 // Determine interpolation weights for p_hse
3839 ArrayOfGridPos gp(1);
3841 p2gridpos(gp, p_grid, Vector(1, p_hse));
3842 interpweights(itw, gp);
3844 // // Molecular weight of water vapour
3845 const Numeric mw = 18.016;
3847 // mw/molarmass_dry_air matches eps in Eq. 3.14 in Wallace&Hobbs:
3848 const Numeric k = 1 - mw / molarmass_dry_air;
3850 // Gas constant for 1kg dry air:
3851 const Numeric rd = 1e3 * GAS_CONSTANT / molarmass_dry_air;
3855 for (Index ilat = 0; ilat < nlat; ilat++) {
3856 // The reference ellipsoid is already adjusted to internal 1D or 2D
3857 // views, and lat_grid is the relevant grid for *refellipsoid*, also
3858 // for 2D. On the other hand, extraction of g0 requires that the true
3859 // position is determined.
3861 // Radius of reference ellipsoid
3863 if (atmosphere_dim == 1) {
3864 re = refellipsoid[0];
3866 re = refell2r(refellipsoid, lat_grid[ilat]);
3869 for (Index ilon = 0; ilon < nlon; ilon++) {
3870 // Determine true latitude and longitude
3872 Vector pos(atmosphere_dim); // pos[0] can be a dummy value
3873 if (atmosphere_dim >= 2) {
3874 pos[1] = lat_grid[ilat];
3875 if (atmosphere_dim == 3) {
3876 pos[2] = lon_grid[ilon];
3880 lat, lon, atmosphere_dim, lat_grid, lat_true, lon_true, pos);
3884 g0_agendaExecute(ws, g0, lat, lon, g0_agenda);
3886 // Determine altitude for p_hse
3888 interp(z_hse, itw, z_field(joker, ilat, ilon), gp);
3890 Numeric z_acc = 2 * z_hse_accuracy;
3892 while (z_acc > z_hse_accuracy) {
3896 for (Index ip = 0; ip < np - 1; ip++) {
3897 // Calculate average g
3899 z2g(g2, re, g0, z_field(ip, ilat, ilon));
3901 const Numeric g1 = g2;
3902 z2g(g2, re, g0, z_field(ip + 1, ilat, ilon));
3904 const Numeric g = (g1 + g2) / 2.0;
3906 //Average water vapour VMR
3911 hm = 0.5 * (vmr_field(firstH2O, ip, ilat, ilon) +
3912 vmr_field(firstH2O, ip + 1, ilat, ilon));
3915 // Average virtual temperature (no liquid water)
3916 // (cf. e.g. Eq. 3.16 in Wallace&Hobbs)
3918 (1 / (2 * (1 - hm * k))) *
3919 (t_field(ip, ilat, ilon) + t_field(ip + 1, ilat, ilon));
3921 // Change in vertical altitude from ip to ip+1
3922 // (cf. e.g. Eq. 3.24 in Wallace&Hobbs)
3923 const Numeric dz = rd * (tv / g) * log(p_grid[ip] / p_grid[ip + 1]);
3926 Numeric znew = z_field(ip, ilat, ilon) + dz;
3927 z_acc = max(z_acc, fabs(znew - z_field(ip + 1, ilat, ilon)));
3928 z_field(ip + 1, ilat, ilon) = znew;
3933 interp(z_tmp, itw, z_field(joker, ilat, ilon), gp);
3934 z_field(joker, ilat, ilon) -= z_tmp[0] - z_hse[0];
3939 // Check that there is no gap between the surface and lowest pressure
3941 // (This code is copied from *basics_checkedCalc*. Make this to an internal
3942 // function if used in more places.)
3943 for (Index row = 0; row < z_surface.nrows(); row++) {
3944 for (Index col = 0; col < z_surface.ncols(); col++) {
3945 ARTS_USER_ERROR_IF (z_surface(row, col) < z_field(0, row, col) ||
3946 z_surface(row, col) >= z_field(z_field.npages() - 1, row, col),
3947 "The surface altitude (*z_surface*) cannot be outside
"
3948 "of the altitudes in *z_field*.
")
3953/* Workspace method: Doxygen documentation will be auto-generated */
3954void vmr_fieldSetConstant(Tensor4& vmr_field,
3955 const ArrayOfArrayOfSpeciesTag& abs_species,
3956 const String& species,
3957 const Numeric& vmr_value,
3960 chk_if_in_range("vmr_value
", vmr_value, 0, 1);
3962 ARTS_USER_ERROR_IF (abs_species.nelem() != vmr_field.nbooks(),
3963 "Size of *vmr_field* and length of *abs_species*
do not agree.
");
3965 // Find position for this species.
3966 const ArrayOfSpeciesTag tag(species);
3967 Index si = chk_contains("species
", abs_species, tag);
3970 vmr_field(si, joker, joker, joker) = vmr_value;
3973/* Workspace method: Doxygen documentation will be auto-generated */
3974void vmr_fieldSetAllConstant(Tensor4& vmr_field,
3975 const ArrayOfArrayOfSpeciesTag& abs_species,
3976 const Vector& vmr_values,
3977 const Verbosity& verbosity) {
3980 const Index nspecies = abs_species.nelem();
3982 ARTS_USER_ERROR_IF (vmr_values.nelem() not_eq nspecies,
3983 "Not same number of vmr_values as abs_species.
");
3985 out3 << "Setting all
" << nspecies << " species to constant VMR\n
";
3987 for (Index i = 0; i < nspecies; i++) {
3988 const ArrayOfSpeciesTag& a_abs_species = abs_species[i];
3989 const String species_tag_name = a_abs_species.Name();
3990 vmr_fieldSetConstant(
3991 vmr_field, abs_species, species_tag_name, vmr_values[i], verbosity);
3996/* Workspace method: Doxygen documentation will be auto-generated */
3997void vmr_fieldSetRh(Workspace& ws,
3999 const ArrayOfArrayOfSpeciesTag& abs_species,
4000 const Tensor3& t_field,
4001 const Vector& p_grid,
4002 const Agenda& water_p_eq_agenda,
4004 const Numeric& vmr_threshold,
4008 const Index ih2o = find_first_species(abs_species, Species::fromShortName("H2O
"));
4009 ARTS_USER_ERROR_IF (ih2o < 0, "There is no H2O species in *abs_species*.
")
4011 // Calculate partial pressure matching selected RH
4013 water_p_eq_agendaExecute(ws, p_rh, t_field, water_p_eq_agenda);
4017 for (Index p=0; p<vmr_field.npages(); ++p) {
4018 for (Index a=0; a<vmr_field.nrows(); ++a) {
4019 for (Index o=0; o<vmr_field.ncols(); ++o) {
4020 if (vmr_field(ih2o, p, a, o) > vmr_threshold) {
4021 vmr_field(ih2o, p, a, o) = p_rh(p, a, o) / p_grid[p];
4028/* Workspace method: Doxygen documentation will be auto-generated */
4029void nlte_fieldLteExternalPartitionFunction(
4031 EnergyLevelMap& nlte_field,
4032 ArrayOfArrayOfAbsorptionLines& abs_lines_per_species,
4033 const ArrayOfQuantumIdentifier& nlte_quantum_identifiers,
4034 const Tensor3& t_field,
4035 const Verbosity& verbosity) {
4039 const Index nn = nlte_quantum_identifiers.nelem(), np = t_field.npages(),
4040 nlat = t_field.nrows(), nlon = t_field.ncols();
4041 if (nn == 0) return;
4043 Tensor4 nlte_tensor4(nn, np, nlat, nlon);
4045 ArrayOfIndex checked(nn, 0);
4047 for (Index in = 0; in < nn; in++) {
4048 const QuantumIdentifier& qi = nlte_quantum_identifiers[in];
4049 Tensor3View lte = nlte_tensor4(in, joker, joker, joker);
4051 for (auto& abs_lines : abs_lines_per_species) {
4052 for (auto& band : abs_lines) {
4053 for (Index k=0; k<band.NumLines(); k++) {
4054 const Quantum::Number::StateMatch lt(qi, band.lines[k].localquanta, band.quantumidentity);
4055 if (lt == Quantum::Number::StateMatchType::Level and lt.low) {
4056 band.population = Absorption::PopulationType::NLTE;
4058 if (not checked[in]) {
4061 for (Index ip = 0; ip < np; ip++) {
4062 for (Index ilat = 0; ilat < nlat; ilat++) {
4063 for (Index ilon = 0; ilon < nlon; ilon++) {
4064 lte(ip, ilat, ilon) =
4065 boltzman_factor(t_field(ip, ilat, ilon), band.lines[k].E0) *
4066 band.lines[k].glow / single_partition_function(
4067 t_field(ip, ilat, ilon), band.Isotopologue());
4074 if (lt == Quantum::Number::StateMatchType::Level and lt.upp) {
4075 band.population = Absorption::PopulationType::NLTE;
4077 if (not checked[in]) {
4079 for (Index ip = 0; ip < np; ip++) {
4080 for (Index ilat = 0; ilat < nlat; ilat++) {
4081 for (Index ilon = 0; ilon < nlon; ilon++) {
4082 lte(ip, ilat, ilon) =
4083 boltzman_factor(t_field(ip, ilat, ilon), band.lines[k].E0 + h*band.lines[k].F0) *
4084 band.lines[k].gupp / single_partition_function(
4085 t_field(ip, ilat, ilon), band.Isotopologue());
4096 for (Index in = 0; in < nn; in++) {
4097 if (not checked[in]) {
4098 out2 << "Did not find match among lines
for:
"
4099 << nlte_quantum_identifiers[in] << "\n
";
4103 nlte_field = EnergyLevelMap(nlte_tensor4, nlte_quantum_identifiers);
4106/* Workspace method: Doxygen documentation will be auto-generated */
4107void nlte_fieldLteInternalPartitionFunction(
4109 EnergyLevelMap& nlte_field,
4110 ArrayOfArrayOfAbsorptionLines& abs_lines_per_species,
4111 const ArrayOfQuantumIdentifier& nlte_quantum_identifiers,
4112 const Tensor3& t_field,
4113 const Verbosity& verbosity) {
4117 const Index nn = nlte_quantum_identifiers.nelem(), np = t_field.npages(),
4118 nlat = t_field.nrows(), nlon = t_field.ncols();
4119 if (nn == 0) return;
4121 // Find where they are positioned and how many different molecules there are for the NLTE fields
4122 ArrayOfIndex part_fun_pos(nn, 0);
4124 for (Index in = 1; in < nn; in++) {
4126 for (Index ix = 0; ix < in; ix++) {
4127 if (nlte_quantum_identifiers[in].Species() ==
4128 nlte_quantum_identifiers[ix].Species() and
4129 nlte_quantum_identifiers[in].Isotopologue() ==
4130 nlte_quantum_identifiers[ix].Isotopologue()) {
4131 part_fun_pos[in] = part_fun_pos[ix];
4137 part_fun_pos[in] = x;
4142 Tensor4 part_fun(x, np, nlat, nlon, 0.0);
4143 Tensor4 nlte_tensor4(nn, np, nlat, nlon, 0);
4145 ArrayOfIndex checked(nn, 0);
4147 for (Index in = 0; in < nn; in++) {
4148 const QuantumIdentifier& qi = nlte_quantum_identifiers[in];
4149 Tensor3View lte = nlte_tensor4(in, joker, joker, joker);
4151 for (auto& abs_lines : abs_lines_per_species) {
4152 for (auto& band : abs_lines) {
4153 for (Index k=0; k<band.NumLines(); k++) {
4154 const Quantum::Number::StateMatch lt(qi, band.lines[k].localquanta, band.quantumidentity);
4155 if (lt == Quantum::Number::StateMatchType::Level and lt.low) {
4156 band.population = Absorption::PopulationType::NLTE;
4158 if (not checked[in]) {
4161 for (Index ip = 0; ip < np; ip++) {
4162 for (Index ilat = 0; ilat < nlat; ilat++) {
4163 for (Index ilon = 0; ilon < nlon; ilon++) {
4164 lte(ip, ilat, ilon) =
4165 boltzman_factor(t_field(ip, ilat, ilon), band.lines[k].E0) *
4167 part_fun(part_fun_pos[in], ip, ilat, ilon) +=
4168 lte(ip, ilat, ilon);
4175 if (lt == Quantum::Number::StateMatchType::Level and lt.upp) {
4176 band.population = Absorption::PopulationType::NLTE;
4178 if (not checked[in]) {
4181 for (Index ip = 0; ip < np; ip++) {
4182 for (Index ilat = 0; ilat < nlat; ilat++) {
4183 for (Index ilon = 0; ilon < nlon; ilon++) {
4184 lte(ip, ilat, ilon) =
4185 boltzman_factor(t_field(ip, ilat, ilon),
4186 band.lines[k].E0 + h * band.lines[k].F0) *
4188 part_fun(part_fun_pos[in], ip, ilat, ilon) +=
4189 lte(ip, ilat, ilon);
4200 for (Index in = 0; in < nn; in++) {
4201 if (not checked[in]) {
4202 out2 << "Did not find match among lines
for:
"
4203 << nlte_quantum_identifiers[in] << "\n
";
4207 for (Index in = 0; in < nn; in++) {
4209 nlte_tensor4(in, joker, joker, joker) /=
4210 part_fun(part_fun_pos[in], joker, joker, joker);
4214 nlte_field = EnergyLevelMap(nlte_tensor4, nlte_quantum_identifiers);
Declarations required for the calculation of absorption coefficients.
Declarations for agendas.
base max(const Array< base > &x)
Max function.
base min(const Array< base > &x)
Min function.
The global header file for ARTS.
Constants of physical expressions as constexpr.
Index nelem() const ARTS_NOEXCEPT
Index nrows() const noexcept
Index ncols() const noexcept
Index npages() const
Returns the number of pages.
Index nrows() const
Returns the number of rows.
Index ncols() const
Returns the number of columns.
Index ncols() const noexcept
Index nrows() const noexcept
Index nbooks() const noexcept
Index npages() const noexcept
A constant view of a Vector.
Index nelem() const noexcept
Returns the number of elements.
bool empty() const noexcept
Returns true if variable size is zero.
void resize(const GriddedField2 &gf)
Make this GriddedField2 the same size as the given one.
bool checksize() const final
Consistency check.
void resize(const GriddedField3 &gf)
Make this GriddedField3 the same size as the given one.
bool checksize() const final
Consistency check.
void resize(const GriddedField4 &gf)
Make this GriddedField4 the same size as the given one.
Index get_grid_size(Index i) const
Get the size of a grid.
const ArrayOfString & get_string_grid(Index i) const
Get a string grid.
void set_grid_name(Index i, const String &s)
Set grid name.
void set_grid(Index i, const Vector &g)
Set a numeric grid.
const Vector & get_numeric_grid(Index i) const
Get a numeric grid.
const String & get_grid_name(Index i) const
Get grid name.
void resize(Index p, Index r, Index c)
Resize function.
void resize(Index b, Index p, Index r, Index c)
Resize function.
void resize(Index n)
Resize function.
void toupper()
Convert to upper case.
void parse_atmcompact_speciesname(String &species_name, const String &field_name, const String &delim)
void parse_atmcompact_speciestype(String &species_type, const String &field_name, const String &delim)
void parse_atmcompact_scattype(String &scat_type, const String &field_name, const String &delim)
Internal cloudbox functions.
#define ARTS_ASSERT(condition,...)
#define ARTS_USER_ERROR(...)
std::string var_string(Args &&... args)
#define ARTS_USER_ERROR_IF(condition,...)
Implementation of gridded fields.
void gridpos(ArrayOfGridPos &gp, ConstVectorView old_grid, ConstVectorView new_grid, const Numeric &extpolfac)
Set up a grid position Array.
void interpweights(VectorView itw, const GridPos &tc)
Red 1D interpolation weights.
Numeric interp(ConstVectorView itw, ConstVectorView a, const GridPos &tc)
Red 1D Interpolate.
Header file for interpolation.cc.
Constains various line scaling functions.
bool is_same_within_epsilon(const Numeric &a, const Numeric &b, const Numeric &epsilon)
Check, if two numbers agree within a given epsilon.
bool is_lon_cyclic(ConstVectorView grid, const Numeric &epsilon)
Check if the given longitude grid is cyclic.
void AtmosphereSet2D(Index &atmosphere_dim, Vector &lon_grid, const Verbosity &verbosity)
WORKSPACE METHOD: AtmosphereSet2D.
void MagRawRead(GriddedField3 &mag_u_field_raw, GriddedField3 &mag_v_field_raw, GriddedField3 &mag_w_field_raw, const String &basename, const Verbosity &verbosity)
WORKSPACE METHOD: MagRawRead.
void GriddedFieldPRegridHelper(Index &ing_min, Index &ing_max, ArrayOfLagrangeInterpolation &lag_p, VectorOfVector &itw, GriddedField &gfraw_out, const GriddedField &gfraw_in, const Index p_grid_index, ConstVectorView p_grid, const Index &interp_order, const Index &zeropadding, const Verbosity &verbosity)
Calculate grid positions and interpolations weights for GriddedFieldPRegrid.
void atm_fields_compactCreateFromField(GriddedField4 &atm_fields_compact, const String &name, const GriddedField3 &field, const Verbosity &)
WORKSPACE METHOD: atm_fields_compactCreateFromField.
void AtmRawRead(GriddedField3 &t_field_raw, GriddedField3 &z_field_raw, ArrayOfGriddedField3 &vmr_field_raw, ArrayOfGriddedField3 &nlte_field_raw, ArrayOfQuantumIdentifier &nlte_quantum_identifiers, Vector &nlte_vibrational_energies, const ArrayOfArrayOfSpeciesTag &abs_species, const String &basename, const Verbosity &verbosity)
WORKSPACE METHOD: AtmRawRead.
void GriddedFieldPRegrid(GriddedField3 &gfraw_out, const Vector &p_grid, const GriddedField3 &gfraw_in_orig, const Index &interp_order, const Index &zeropadding, const Verbosity &verbosity)
WORKSPACE METHOD: GriddedFieldPRegrid.
void WindFieldsCalcExpand1D(Tensor3 &wind_u_field, Tensor3 &wind_v_field, Tensor3 &wind_w_field, const Vector &p_grid, const Vector &lat_grid, const Vector &lon_grid, const GriddedField3 &wind_u_field_raw, const GriddedField3 &wind_v_field_raw, const GriddedField3 &wind_w_field_raw, const Index &atmosphere_dim, const Index &interp_order, const Verbosity &verbosity)
WORKSPACE METHOD: WindFieldsCalcExpand1D.
void atm_fields_compactFromMatrix(GriddedField4 &af, const Index &atmosphere_dim, const Matrix &im, const ArrayOfString &field_names, const Verbosity &)
WORKSPACE METHOD: atm_fields_compactFromMatrix.
void AtmosphereSet1D(Index &atmosphere_dim, Vector &lat_grid, Vector &lon_grid, const Verbosity &verbosity)
WORKSPACE METHOD: AtmosphereSet1D.
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 Index &chk_vmr_nan, const Verbosity &)
WORKSPACE METHOD: AtmFieldsExpand1D.
void AtmFieldsExtract1D(Index &atmosphere_dim, Vector &lat_grid, Vector &lon_grid, Tensor3 &t_field, Tensor3 &z_field, Tensor4 &vmr_field, const Index &ilat, const Index &ilon, const Verbosity &verbosity)
WORKSPACE METHOD: AtmFieldsExtract1D.
void GriddedFieldZToPRegridHelper(Index &ing_min, Index &ing_max, ArrayOfLagrangeInterpolation &lag_p, VectorOfVector &itw, const GriddedField &gfraw_in, const Index z_grid_index, ConstVectorView z_grid, const Index &interp_order, const Index &zeropadding, const Verbosity &verbosity)
Calculate grid positions and interpolations weights for GriddedFieldZToPRegrid.
void AtmFieldsAndParticleBulkPropFieldFromCompact(Vector &p_grid, Vector &lat_grid, Vector &lon_grid, Tensor3 &t_field, Tensor3 &z_field, Tensor4 &vmr_field, Tensor4 &particle_bulkprop_field, ArrayOfString &particle_bulkprop_names, const ArrayOfArrayOfSpeciesTag &abs_species, const GriddedField4 &atm_fields_compact, const Index &atmosphere_dim, const String &delim, const Numeric &p_min, const Index &check_gridnames, const Verbosity &)
WORKSPACE METHOD: AtmFieldsAndParticleBulkPropFieldFromCompact.
void MagFieldsCalcIGRF(Tensor3 &mag_u_field, Tensor3 &mag_v_field, Tensor3 &mag_w_field, const Tensor3 &z_field, const Vector &lat_grid, const Vector &lon_grid, const Vector &refellipsoid, const Time &time, const Verbosity &)
WORKSPACE METHOD: MagFieldsCalcIGRF.
void MagFieldsCalc(Tensor3 &mag_u_field, Tensor3 &mag_v_field, Tensor3 &mag_w_field, const Vector &p_grid, const Vector &lat_grid, const Vector &lon_grid, const GriddedField3 &mag_u_field_raw, const GriddedField3 &mag_v_field_raw, const GriddedField3 &mag_w_field_raw, const Index &atmosphere_dim, const Index &interp_order, const Verbosity &verbosity)
WORKSPACE METHOD: MagFieldsCalc.
void GriddedFieldZToPRegrid(GriddedField3 &gfraw_out, const Vector &p_grid, const Vector &lat_grid, const Vector &lon_grid, const Tensor3 &z_field, const GriddedField3 &gfraw_in_orig, const Index &interp_order, const Index &zeropadding, const Verbosity &verbosity)
WORKSPACE METHOD: GriddedFieldZToPRegrid.
void GriddedFieldLatLonRegrid(GriddedField2 &gfraw_out, const Vector &lat_true, const Vector &lon_true, const GriddedField2 &gfraw_in_orig, const Index &interp_order, const Verbosity &verbosity)
WORKSPACE METHOD: GriddedFieldLatLonRegrid.
void GriddedFieldLatLonExpand(GriddedField2 &gfraw_out, const GriddedField2 &gfraw_in_orig, const Verbosity &)
WORKSPACE METHOD: GriddedFieldLatLonExpand.
void p_gridDensify(Vector &p_grid, Index &atmfields_checked, Index &atmgeom_checked, Index &cloudbox_checked, const Vector &p_grid_old, const Index &nfill, const Verbosity &verbosity)
WORKSPACE METHOD: p_gridDensify.
void InterpAtmFieldToPosition(Numeric &outvalue, const Index &atmosphere_dim, const Vector &p_grid, const Vector &lat_grid, const Vector &lon_grid, const Tensor3 &z_field, const Vector &rtp_pos, const Tensor3 &field, const Verbosity &verbosity)
WORKSPACE METHOD: InterpAtmFieldToPosition.
void batch_atm_fields_compactAddConstant(ArrayOfGriddedField4 &batch_atm_fields_compact, const String &name, const Numeric &value, const Index &prepend, const ArrayOfString &condensibles, const Verbosity &verbosity)
WORKSPACE METHOD: batch_atm_fields_compactAddConstant.
void FieldFromGriddedFieldCheckLatLonHelper(const Vector &lat_grid, const Vector &lon_grid, const Index ilat, const Index ilon, const GriddedField &gfield)
Check for correct grid dimensions.
void batch_atm_fields_compactAddSpecies(ArrayOfGriddedField4 &batch_atm_fields_compact, const String &name, const GriddedField3 &species, const Index &prepend, const Verbosity &verbosity)
WORKSPACE METHOD: batch_atm_fields_compactAddSpecies.
void AtmFieldsCalcExpand1D(Tensor3 &t_field, Tensor3 &z_field, Tensor4 &vmr_field, EnergyLevelMap &nlte_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 ArrayOfGriddedField3 &nlte_field_raw, const ArrayOfQuantumIdentifier &nlte_ids, const Vector &nlte_energies, const Index &atmosphere_dim, const Index &interp_order, const Index &vmr_zeropadding, const Index &vmr_nonegative, const Index &nlte_when_negative, const Verbosity &verbosity)
WORKSPACE METHOD: AtmFieldsCalcExpand1D.
void atm_fields_compactAddSpecies(GriddedField4 &atm_fields_compact, const String &name, const GriddedField3 &species, const Index &prepend, const Verbosity &verbosity)
WORKSPACE METHOD: atm_fields_compactAddSpecies.
void GriddedFieldLatLonRegridHelper(ArrayOfLagrangeInterpolation &lag_lat, ArrayOfLagrangeInterpolation &lag_lon, MatrixOfMatrix &itw, GriddedField &gfraw_out, const GriddedField &gfraw_in, const Index lat_grid_index, const Index lon_grid_index, ConstVectorView lat_true, ConstVectorView lon_true, const Index &interp_order, const Verbosity &verbosity)
Calculate grid positions and interpolations weights for GriddedFieldLatLonRegrid.
void MagFieldsCalcExpand1D(Tensor3 &mag_u_field, Tensor3 &mag_v_field, Tensor3 &mag_w_field, const Vector &p_grid, const Vector &lat_grid, const Vector &lon_grid, const GriddedField3 &mag_u_field_raw, const GriddedField3 &mag_v_field_raw, const GriddedField3 &mag_w_field_raw, const Index &atmosphere_dim, const Index &interp_order, const Verbosity &verbosity)
WORKSPACE METHOD: MagFieldsCalcExpand1D.
void AtmFieldPRegridHelper(Index &ing_min, Index &ing_max, ArrayOfLagrangeInterpolation &lag_p, VectorOfVector &itw, ConstVectorView p_grid_out, ConstVectorView p_grid_in, const Index &interp_order, const Verbosity &verbosity)
Calculate grid positions and interpolations weights for AtmFieldPRegrid.
constexpr Numeric GAS_CONSTANT
void AtmFieldsRefinePgrid(Vector &p_grid, Tensor3 &t_field, Tensor3 &z_field, Tensor4 &vmr_field, Index &atmfields_checked, Index &atmgeom_checked, Index &cloudbox_checked, const Vector &lat_grid, const Vector &lon_grid, const Index &atmosphere_dim, const Numeric &p_step, const Index &interp_order, const Verbosity &verbosity)
WORKSPACE METHOD: AtmFieldsRefinePgrid.
void MagFieldsFromAltitudeRawCalc(Tensor3 &mag_u_field, Tensor3 &mag_v_field, Tensor3 &mag_w_field, const Vector &lat_grid, const Vector &lon_grid, const Tensor3 &z_field, const GriddedField3 &mag_u_field_raw, const GriddedField3 &mag_v_field_raw, const GriddedField3 &mag_w_field_raw, const Index &interp_order, const Numeric &extrapolation_factor, const Verbosity &verbosity)
WORKSPACE METHOD: MagFieldsFromAltitudeRawCalc.
void WindFieldsCalc(Tensor3 &wind_u_field, Tensor3 &wind_v_field, Tensor3 &wind_w_field, const Vector &p_grid, const Vector &lat_grid, const Vector &lon_grid, const GriddedField3 &wind_u_field_raw, const GriddedField3 &wind_v_field_raw, const GriddedField3 &wind_w_field_raw, const Index &atmosphere_dim, const Index &interp_order, const Verbosity &verbosity)
WORKSPACE METHOD: WindFieldsCalc.
void AtmWithNLTERawRead(GriddedField3 &t_field_raw, GriddedField3 &z_field_raw, ArrayOfGriddedField3 &vmr_field_raw, ArrayOfGriddedField3 &nlte_field_raw, ArrayOfQuantumIdentifier &nlte_quantum_identifiers, Vector &nlte_vibrational_energies, const ArrayOfArrayOfSpeciesTag &abs_species, const String &basename, const Index &expect_vibrational_energies, const Verbosity &verbosity)
WORKSPACE METHOD: AtmWithNLTERawRead.
void atm_fields_compactAddConstant(GriddedField4 &af, const String &name, const Numeric &value, const Index &prepend, const ArrayOfString &condensibles, const Verbosity &verbosity)
WORKSPACE METHOD: atm_fields_compactAddConstant.
void atm_fields_compactCleanup(GriddedField4 &atm_fields_compact, const Numeric &threshold, const Verbosity &)
WORKSPACE METHOD: atm_fields_compactCleanup.
void atm_fields_compactExpand(GriddedField4 &af, Index &nf, const String &name, const Index &prepend, const Verbosity &)
atm_fields_compactExpand
void AtmosphereSet3D(Index &atmosphere_dim, Vector &lat_true, Vector &lon_true, const Verbosity &verbosity)
WORKSPACE METHOD: AtmosphereSet3D.
void FieldFromGriddedField(Matrix &field_out, const Vector &p_grid, const Vector &lat_grid, const Vector &lon_grid, const GriddedField2 &gfraw_in, const Verbosity &)
WORKSPACE METHOD: FieldFromGriddedField.
void z_surfaceConstantAltitude(Matrix &z_surface, const Vector &lat_grid, const Vector &lon_grid, const Numeric &altitude, const Verbosity &verbosity)
WORKSPACE METHOD: z_surfaceConstantAltitude.
constexpr Numeric EPSILON_LON_CYCLIC
Data value accuracy requirement for values at 0 and 360 deg if longitudes are cyclic.
void batch_atm_fields_compactCleanup(ArrayOfGriddedField4 &batch_atm_fields_compact, const Numeric &threshold, const Verbosity &verbosity)
WORKSPACE METHOD: batch_atm_fields_compactCleanup.
void AtmFieldsCalc(Tensor3 &t_field, Tensor3 &z_field, Tensor4 &vmr_field, EnergyLevelMap &nlte_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 ArrayOfGriddedField3 &nlte_field_raw, const ArrayOfQuantumIdentifier &nlte_ids, const Vector &nlte_energies, const Index &atmosphere_dim, const Index &interp_order, const Index &vmr_zeropadding, const Index &vmr_nonegative, const Index &nlte_when_negative, const Verbosity &verbosity)
WORKSPACE METHOD: AtmFieldsCalc.
void batch_atm_fields_compactFromArrayOfMatrix(ArrayOfGriddedField4 &batch_atm_fields_compact, const Index &atmosphere_dim, const ArrayOfMatrix &am, const ArrayOfString &field_names, const Verbosity &verbosity)
WORKSPACE METHOD: batch_atm_fields_compactFromArrayOfMatrix.
void WindRawRead(GriddedField3 &wind_u_field_raw, GriddedField3 &wind_v_field_raw, GriddedField3 &wind_w_field_raw, const String &basename, const Verbosity &verbosity)
WORKSPACE METHOD: WindRawRead.
void AtmFieldPRegrid(Tensor3 &atmtensor_out, const Tensor3 &atmtensor_in_orig, const Vector &p_grid_new, const Vector &p_grid_old, const Index &interp_order, const Verbosity &verbosity)
WORKSPACE METHOD: AtmFieldPRegrid.
void z_surfaceFromFileAndGrid(Matrix &z_surface, const Vector &lat_grid, const Vector &lon_grid, const String &filename, const Index &interp_order, const Index &set_lowest_altitude_to_zero, const Verbosity &verbosity)
WORKSPACE METHOD: z_surfaceFromFileAndGrid.
void p_gridRefine(Vector &p_grid, Index &atmfields_checked, Index &atmgeom_checked, Index &cloudbox_checked, const Vector &p_grid_old, const Numeric &p_step10, const Verbosity &)
WORKSPACE METHOD: p_gridRefine.
NUMERIC Numeric
The type to use for all floating point numbers.
INDEX Index
The type to use for all integer numbers and indices.
Declarations having to do with the four output streams.
my_basic_string< char > String
The String type for ARTS.
constexpr Numeric ideal_gas_constant
Ideal gas constant [J/mol K].
constexpr Index GFIELD3_LON_GRID
Global constant, Index of the longitude grid in GriddedField3.
constexpr Index GFIELD4_LAT_GRID
Global constant, Index of the latitude grid in GriddedField4.
constexpr Index GFIELD4_P_GRID
Global constant, Index of the pressure grid in GriddedField4.
constexpr Index GFIELD4_FIELD_NAMES
Global constant, Index of the field names in GriddedField4.
constexpr Index GFIELD3_P_GRID
Global constant, Index of the pressure grid in GriddedField3.
constexpr Index GFIELD4_LON_GRID
Global constant, Index of the longitude grid in GriddedField4.
constexpr Index GFIELD3_LAT_GRID
Global constant, Index of the latitude grid in GriddedField3.
MagneticField compute(const Tensor3 &z_field, const Vector &lat_grid, const Vector &lon_grid, const Time &time, const Vector &ell)
Computes the magnetic field based on IGRF13 coefficients.
Array< Lagrange > LagrangeVector(const ConstVectorView &xs, const ConstVectorView &xi, const Index polyorder, const Numeric extrapol, const bool do_derivs, const GridType type, const std::pair< Numeric, Numeric > cycle)
Array< QuantumIdentifier > ArrayOfQuantumIdentifier
Declaration of functions in rte.cc.
void p2gridpos(ArrayOfGridPos &gp, ConstVectorView old_pgrid, ConstVectorView new_pgrid, const Numeric &extpolfac)
Calculates grid positions for pressure values.
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)
Interpolates an atmospheric field given the grid positions.
void rte_pos2gridpos(GridPos &gp_p, GridPos &gp_lat, GridPos &gp_lon, const Index &atmosphere_dim, ConstVectorView p_grid, ConstVectorView lat_grid, ConstVectorView lon_grid, ConstTensor3View z_field, ConstVectorView rte_pos)
Converts a geographical position (rte_pos) to grid positions for p, lat and lon.
Header file for special_interp.cc.
ArrayOfQuantumIdentifier levels
void ThrowIfNotOK() const ARTS_NOEXCEPT
Structure to store a grid position.
Magnetic field for the east (u), north (v), and up (w) components as the ENU-coordinate system.
Class to handle time in ARTS.
This file contains basic functions to handle XML data files.
void xml_read_from_file(const String &filename, T &type, const Verbosity &verbosity)
Reads data from XML file.