58 out2 <<
" Created an empty gas absorption lookup table.\n";
67 Index& abs_lookup_is_adapted,
76 const Vector& abs_nls_pert,
77 const Agenda& abs_xsec_agenda,
86 Matrix these_all_vmrs = abs_vmrs;
109 const Index n_nls_pert = abs_nls_pert.
nelem();
114 Matrix this_vmr(1,n_p_grid);
134 const Index h2o_index
146 os <<
"If you have nonlinear species, at least one\n"
147 <<
"species must be a H2O species.";
148 throw runtime_error( os.str() );
152 out2 <<
" You have no H2O species. Absorption continua will not work.\n"
153 <<
" You should get a runtime error if you try them anyway.\n";
163 os <<
"One of the required input variables is empty:\n"
164 <<
"abs_species.nelem() = " << n_species <<
",\n"
165 <<
"f_grid.nelem() = " << n_f_grid <<
",\n"
166 <<
"abs_p.nelem() = " << n_p_grid <<
".";
167 throw runtime_error( os.str() );
174 for (
Index i=0; i<n_nls; ++i)
177 for (s=0; s<n_species; ++s)
179 if (abs_nls[i]==abs_species[s])
181 abs_nls_idx.push_back(s);
188 os <<
"Did not find *abs_nls* tag group \""
190 <<
"\" in *abs_species*.";
191 throw runtime_error( os.str() );
199 os <<
"The variable *abs_nls* must not have duplicate species.\n"
200 <<
"Value of *abs_nls*: " << abs_nls_idx;
201 throw runtime_error( os.str() );
217 if ( ( (0==n_nls) && (0!=n_nls_pert) ) ||
218 ( (0!=n_nls) && (0==n_nls_pert) ) )
221 os <<
"You have to set both abs_nls and abs_nls_pert, or none.";
222 throw runtime_error( os.str() );
228 for (
Index s=0; s<n_nls; ++s )
230 non_linear[abs_nls_idx[s]] = 1;
235 abs_lookup.
species = abs_species;
237 abs_lookup.
f_grid = f_grid;
238 abs_lookup.
p_grid = abs_p;
240 abs_lookup.
t_ref = abs_t;
241 abs_lookup.
t_pert = abs_t_pert;
253 if ( 0 == n_t_pert ) a = 1;
256 b = n_species + n_nls * ( n_nls_pert - 1 );
263 abs_lookup.
xsec = NAN;
271 out2 <<
" With temperature perturbations.\n";
272 these_t_pert.
resize(n_t_pert);
273 these_t_pert = abs_t_pert;
277 out2 <<
" No temperature perturbations.\n";
282 const Index these_t_pert_nelem = these_t_pert.
nelem();
293 Agenda l_abs_xsec_agenda(abs_xsec_agenda);
296 for (
Index i=0,
spec=0; i<n_species; ++i )
311 out2 <<
" Doing species " << i+1 <<
" of " << n_species <<
": "
312 << abs_species[i] <<
".\n";
315 abs_species_active[0] = i;
318 this_species[0].resize(abs_species[i].nelem());
319 this_species[0] = abs_species[i];
327 out2 <<
" This is a species with H2O VMR perturbations.\n";
328 these_nls_pert.
resize(n_nls_pert);
329 these_nls_pert = abs_nls_pert;
345 out2 <<
" Doing H2O VMR variant " << s+1 <<
" of " << n_nls_pert <<
": "
346 << abs_nls_pert[s] <<
".\n";
355 if ( h2o_index >= 0 )
357 these_all_vmrs(h2o_index,
joker) = abs_vmrs(h2o_index,
joker);
358 these_all_vmrs(h2o_index,
joker) *= these_nls_pert[s];
375 if ( h2o_index == -1 )
384 abs_h2o = these_all_vmrs(h2o_index,
joker);
399 #pragma omp parallel for \
400 if (!arts_omp_in_parallel() \
401 && these_t_pert_nelem >= arts_omp_get_max_threads()) \
402 private(this_t, abs_xsec_per_species) \
403 firstprivate(l_ws, l_abs_xsec_agenda)
404 for (
Index j=0; j<these_t_pert_nelem; ++j )
407 if (failed)
continue;
421 os <<
" Doing temperature variant " << j+1
422 <<
" of " << n_t_pert <<
": "
423 << these_t_pert[j] <<
".\n";
429 this_t = abs_lookup.
t_ref;
430 this_t += these_t_pert[j];
435 abs_xsec_per_species,
447 for (
Index p=0; p<n_p_grid; ++p )
472 catch (runtime_error e)
474 #pragma omp critical (abs_lookupCalc_fail)
475 { fail_msg = e.what(); failed =
true; }
479 if (failed)
throw runtime_error(fail_msg);
489 abs_lookup_is_adapted = 1;
527 for (
Index s=0; s<abs_species[i].
nelem(); ++s )
534 const String thisname = abs_species[i][s].Name();
536 out3 <<
" Continuum tag: " << thisname;
552 "N2-"==thisname.substr(0,3) ||
553 "CO2-"==thisname.substr(0,4) ||
554 "O2-CIA"==thisname.substr(0,6) ||
555 "O2-v0v"==thisname.substr(0,6) ||
556 "O2-v1v"==thisname.substr(0,6) ||
557 "H2-CIA"==thisname.substr(0,6) ||
558 "He-CIA"==thisname.substr(0,6) ||
559 "CH4-CIA"==thisname.substr(0,7) )
561 out3 <<
" --> not added.\n";
566 if (
"O2-"==thisname.substr(0,3) )
569 out3 <<
" --> added to abs_nls.\n";
576 out3 <<
" --> unknown.\n";
577 throw runtime_error(
"I don't know whether this tag uses h2o_abs or not.\n"
578 "Cannot set abs_nls automatically.");
604 while (-1 != (next_h2o =
609 abs_nls.push_back(abs_species[next_h2o]);
621 abs_nls.push_back(abs_species[cont[i]]);
624 out2 <<
" Species marked for nonlinear treatment:\n";
630 if (j!=0) out2 <<
", ";
631 out2 << abs_nls[i][j].Name();
657 const Index& p_interp_order,
658 const Index& t_interp_order,
688 Numeric delta_min = tmin[i] - abs_t[gp.
idx[j]] - 10;
689 Numeric delta_max = tmax[i] - abs_t[gp.
idx[j]] + 10;
691 if ( delta_min < mindev ) mindev = delta_min;
692 if ( delta_max > maxdev ) maxdev = delta_max;
696 out3 <<
" abs_t_pert: mindev/maxdev : " << mindev <<
" / " << maxdev <<
"\n";
701 Index div = t_interp_order;
705 effective_step = (maxdev-mindev)/(
Numeric)div;
708 while (effective_step > step);
710 abs_t_pert =
Vector(mindev, div, effective_step);
712 out2 <<
" abs_t_pert: " << abs_t_pert[0] <<
" K to " << abs_t_pert[abs_t_pert.
nelem()-1]
713 <<
" K in steps of " << effective_step
714 <<
" K (" << abs_t_pert.
nelem() <<
" grid points)\n";
737 const Index& p_interp_order,
738 const Index& nls_interp_order,
781 Numeric delta_min = minprof[i] / refprof[gp.
idx[j]];
782 Numeric delta_max = 2*maxprof[i] / refprof[gp.
idx[j]];
784 if ( delta_min < mindev ) mindev = delta_min;
787 if ( !isinf(delta_max) && (delta_max > maxdev) ) maxdev = delta_max;
791 out3 <<
" abs_nls_pert: mindev/maxdev : " << mindev <<
" / " << maxdev <<
"\n";
793 bool allownegative =
false;
796 out2 <<
" Warning: I am getting a negative fractional distance to the H2O\n"
797 <<
" reference profile. Some of your H2O fields may contain negative values.\n"
798 <<
" Will allow negative values also for abs_nls_pert.\n";
799 allownegative =
true;
805 out3 <<
" Adjusted mindev : " << mindev <<
"\n";
811 os <<
"Perturbation upper limit is infinity (likely due to the reference\n"
812 <<
"profile being 0 at at least one pressure level). Can not work\n"
814 throw runtime_error( os.str() );
820 Index div = nls_interp_order;
824 effective_step = (maxdev-mindev)/(
Numeric)div;
827 while (effective_step > step);
829 abs_nls_pert =
Vector(mindev, div, effective_step);
836 out2 <<
" I am including also 0 in the abs_nls_pert, because it is a turning \n"
837 <<
" point. Consider to use a higher abs_nls_interp_order, for example 4.\n";
840 out2 <<
" abs_nls_pert: " << abs_nls_pert[0] <<
" to " << abs_nls_pert[abs_nls_pert.
nelem()-1]
841 <<
" (fractional units) in steps of " << abs_nls_pert[1]-abs_nls_pert[0]
842 <<
" (" << abs_nls_pert.
nelem() <<
" grid points)\n";
856 const Index& atmosphere_dim,
862 const Index& atmfields_checked,
864 const Index& abs_p_interp_order,
865 const Index& abs_t_interp_order,
866 const Index& abs_nls_interp_order,
875 if( atmfields_checked != 1 )
876 throw runtime_error(
"The atmospheric fields must be flagged to have "
877 "passed a consistency check (atmfields_checked=1)." );
888 if (p_grid.
nelem()<2)
891 os <<
"You need at least two pressure levels.";
892 throw runtime_error( os.str() );
904 if ( p_step10 <= 0 || t_step <= 0 || h2o_step <= 0 )
907 os <<
"The keyword arguments p_step, t_step, and h2o_step must be >0.";
908 throw runtime_error( os.str() );
917 const Numeric p_step = log(pow(10.0, p_step10));
938 log_abs_p_a.push_back(log_p_grid[0]);
942 const Numeric dp = log_p_grid[i-1] - log_p_grid[i];
944 const Numeric dp_by_p_step = dp/p_step;
957 for (
Index j=1; j<=n; ++j)
958 log_abs_p_a.push_back(log_p_grid[i-1] - (
Numeric)j*ddp);
965 log_abs_p[i] = log_abs_p_a[i];
972 if (abs_p.
nelem()<abs_p_interp_order+1)
975 os <<
"Your pressure grid does not have enough levels for the desired interpolation order.";
976 throw runtime_error( os.str() );
984 gridpos(gp, log_p_grid, log_abs_p);
993 if (1==atmosphere_dim)
1012 vmr_field(i,
joker,0,0),
1065 const Index h2o_index
1073 if (0<abs_nls.
nelem())
1079 os <<
"Some of your species require nonlinear treatment,\n"
1080 <<
"but you have no H2O species.";
1081 throw runtime_error( os.str() );
1109 abs_p_interp_order, abs_t_interp_order,
1122 if (0<abs_nls.
nelem())
1126 vmrmean(h2o_index,
joker),
1131 abs_nls_interp_order,
1156 const Index& abs_p_interp_order,
1157 const Index& abs_t_interp_order,
1158 const Index& abs_nls_interp_order,
1172 const Numeric p_step = log(pow(10.0, p_step10));
1178 const Index indoff = batch_fields[0].data.nbooks()-abs_species.
nelem();
1196 const ArrayOfString field_names = batch_fields[0].get_string_grid(0);
1203 if (field_names.
nelem() < 3)
1205 os <<
"Atmospheric states in batch_fields must have at\n"
1206 <<
"least three fields: T, z, and at least one species.";
1207 throw runtime_error( os.str() );
1210 if (abs_species.
nelem() < 1)
1212 os <<
"At least one absorption species needs to be defined "
1213 <<
"in abs_species.";
1214 throw runtime_error( os.str() );
1230 if (abs_species.
nelem() > field_names.
nelem()-2)
1232 os <<
"Dimension of fields in batch_fields does not match that of abs_species.\n"
1233 <<
"(First two fields must be T and z, the N last fields must match the\n"
1234 <<
"absorption species, where N is the number of species as defined in abs_species.)\n"
1235 <<
"Field names: " << field_names <<
"\n"
1236 <<
"Absorption species: " << species_names;
1237 throw runtime_error( os.str() );
1240 os <<
"The consistency check of the first compact atmospheric state in\n"
1241 <<
"batch_fields has shown one or more errors:\n";
1244 if (
"T" != field_names[0])
1246 os <<
"The first field name must be T.\n";
1251 if (
"z" != field_names[1])
1253 os <<
"The second field name must be z.\n";
1263 os <<
"One of the atmospheric fields must be H2O.\n";
1268 bool wrong_species =
false;
1270 if (field_names[indoff+i] != species_names[i])
1271 wrong_species =
true;
1275 os <<
"The " << abs_species.
nelem() <<
" last field names must "
1276 <<
"match the absorption species in\n"
1277 <<
"abs_species, which are:\n"
1278 << species_names <<
"\n";
1282 os <<
"Your field names are:\n"
1285 if (bail)
throw runtime_error( os.str() );
1308 os <<
"You need at least two pressure levels.";
1309 throw runtime_error( os.str() );
1318 Index np = (
Index) ceil((log(maxp)-log(minp))/p_step)+1;
1323 if (np < abs_p_interp_order+1)
1324 np = abs_p_interp_order+1;
1326 Vector log_abs_p(log(maxp), np, -p_step);
1327 log_abs_p[np-1] = log(minp);
1331 out2 <<
" abs_p: " << abs_p[0] <<
" Pa to " << abs_p[np-1]
1332 <<
" Pa in log10 steps of " << p_step10
1333 <<
" (" << np <<
" grid points)\n";
1349 Matrix datamean (n_variables, np, 0);
1368 throw runtime_error(
"All fields in the batch must have the same field names.");
1374 os <<
"The first variable in the compact atmospheric state must be \"T\",\n"
1376 throw runtime_error( os.str() );
1384 os <<
"According to abs_species setting the " << indoff+h2o_index
1385 <<
". variable in the compact\n"
1386 <<
"atmospheric state is supposed to be \"H2O\",\n"
1389 throw runtime_error( os.str() );
1394 const Tensor4& data = batch_fields[i].data;
1403 for (
Index ilat=0; ilat<data.
nrows(); ++ilat)
1404 for (
Index ilon=0; ilon<data.
ncols(); ++ilon)
1407 if (data(0,ip,ilat,ilon) < mint) mint = data(0,ip,ilat,ilon);
1408 if (data(0,ip,ilat,ilon) > maxt) maxt = data(0,ip,ilat,ilon);
1410 if (data(indoff+h2o_index,ip,ilat,ilon) < minh2o)
1411 { minh2o = data(indoff+h2o_index,ip,ilat,ilon); }
1412 if (data(indoff+h2o_index,ip,ilat,ilon) > maxh2o)
1413 { maxh2o = data(indoff+h2o_index,ip,ilat,ilon); }
1429 const Numeric eps_bottom = (log_p_grid[0]-log_p_grid[1])/2.1;
1431 while (log_abs_p[first_p] > log_p_grid[0]+eps_bottom) ++first_p;
1433 const Numeric eps_top = (log_p_grid[log_p_grid.
nelem()-2]-log_p_grid[log_p_grid.
nelem()-1])/2.1;
1435 while (log_abs_p[last_p] < log_p_grid[log_p_grid.
nelem()-1]-eps_top) --last_p;
1437 const Index extent_p = last_p - first_p + 1;
1455 gridpos(gp, log_p_grid, active_log_abs_p);
1471 Tensor4 data_interp(n_variables,
1472 active_log_abs_p.
nelem(),
1482 for (
Index fi=0; fi<2; ++fi)
1485 data(fi,
joker, la, lo),
1490 data(fi,
joker, la, lo),
1500 for (
Index lo=0; lo<data_interp.
ncols(); ++lo)
1501 for (
Index la=0; la<data_interp.
nrows(); ++la)
1509 if (0==fi || (h2o_index+2)==fi)
1511 if (data_interp(fi, pr, la, lo) < datamin(fi, first_p+pr))
1512 datamin(fi, first_p+pr) = data_interp(fi, pr, la, lo);
1513 if (data_interp(fi, pr, la, lo) > datamax(fi, first_p+pr))
1514 datamax(fi, first_p+pr) = data_interp(fi, pr, la, lo);
1517 datamean(fi, first_p+pr) += data_interp(fi, pr, la, lo);
1526 mean_norm[
Range(first_p, extent_p)] += 1;
1530 out2 <<
" Global statistics:\n"
1531 <<
" min(p) / max(p) [Pa]: " << minp <<
" / " << maxp <<
"\n"
1532 <<
" min(T) / max(T) [K]: " << mint <<
" / " << maxt <<
"\n"
1533 <<
" min(H2O) / max(H2O) [VMR]: " << minh2o <<
" / " << maxh2o <<
"\n";
1537 assert(np==mean_norm.
nelem());
1540 for (
Index pi=0; pi<np; ++pi)
1545 if (0<mean_norm[pi])
1546 datamean(fi,pi) /= mean_norm[pi];
1550 os <<
"No data at pressure level " << pi+1
1551 <<
" of "<< np <<
" (" << abs_p[pi] <<
" hPa).";
1552 throw runtime_error( os.str() );
1560 assert(log_abs_p.
nelem()==np);
1562 for (
Index i=0; i<np; ++i)
1565 gridpos_poly(gp, log_abs_p, log_abs_p[i], abs_p_interp_order);
1576 smooth_datamean(fi,i) += datamean(fi,gp.
idx[j]);
1590 for (
Index i=0; i<np; ++i)
1597 Numeric& mean_h2o = smooth_datamean(h2o_index+2,i);
1598 Numeric& max_h2o = datamax(h2o_index+2,i);
1603 out3 <<
" H2O profile contained zero values, adjusted to 1e-9.\n";
1609 abs_t = smooth_datamean(0,
joker);
1615 assert(abs_species.
nelem()==smooth_datamean.
nrows()-2);
1623 choose_abs_t_pert(abs_t_pert, abs_t, tmin, tmax, t_step, abs_p_interp_order, abs_t_interp_order,
1631 h2omin, h2omax, h2o_step,
1632 abs_p_interp_order, abs_nls_interp_order,
1637 if (0!=extremes.
nelem())
1640 if (4!=extremes.
nelem())
1643 os <<
"There must be exactly 4 elements in extremes:\n"
1644 <<
"min(abs_t_pert), max(abs_t_pert), min(abs_nls_pert), max(abs_nls_pert)";
1645 throw runtime_error( os.str() );
1649 if (extremes[0] < abs_t_pert[0])
1651 Vector dummy = abs_t_pert;
1653 abs_t_pert[0] = extremes[0];
1655 out2 <<
" Added min extreme value for abs_t_pert: "
1656 << abs_t_pert[0] <<
"\n";
1660 if (extremes[1] > abs_t_pert[abs_t_pert.
nelem()-1])
1662 Vector dummy = abs_t_pert;
1665 abs_t_pert[abs_t_pert.
nelem()-1] = extremes[1];
1666 out2 <<
" Added max extreme value for abs_t_pert: "
1667 << abs_t_pert[abs_t_pert.
nelem()-1] <<
"\n";
1671 if (extremes[2] < abs_nls_pert[0])
1673 Vector dummy = abs_nls_pert;
1675 abs_nls_pert[0] = extremes[2];
1676 abs_nls_pert[
Range(1,dummy.
nelem())] = dummy;
1677 out2 <<
" Added min extreme value for abs_nls_pert: "
1678 << abs_nls_pert[0] <<
"\n";
1682 if (extremes[3] > abs_nls_pert[abs_nls_pert.
nelem()-1])
1684 Vector dummy = abs_nls_pert;
1686 abs_nls_pert[
Range(0,dummy.
nelem())] = dummy;
1687 abs_nls_pert[abs_nls_pert.
nelem()-1] = extremes[3];
1688 out2 <<
" Added max extreme value for abs_nls_pert: "
1689 << abs_nls_pert[abs_nls_pert.
nelem()-1] <<
"\n";
1704 const Index& abs_p_interp_order,
1705 const Index& abs_t_interp_order,
1706 const Index& abs_nls_interp_order,
1722 const Numeric p_step = log(pow(10.0, p_step10));
1734 Index np = (
Index) ceil((log(p_max)-log(p_min))/p_step)+1;
1739 if (np < abs_p_interp_order+1)
1740 np = abs_p_interp_order+1;
1742 Vector log_abs_p(log(p_max), np, -p_step);
1746 out2 <<
" abs_p: " << abs_p[0] <<
" Pa to " << abs_p[np-1]
1747 <<
" Pa in log10 steps of " << p_step10
1748 <<
" (" << np <<
" grid points)\n";
1756 Numeric t_ref = (t_min + t_max) / 2;
1763 Vector min_prof(np), max_prof(np);
1769 abs_t, min_prof, max_prof, 20,
1770 abs_p_interp_order, abs_t_interp_order,
1781 Numeric const other_ref = 1e-9;
1788 abs_vmrs = other_ref;
1793 const Index o2_index
1798 abs_vmrs(o2_index,
joker) = 0.2095;
1801 const Index n2_index
1806 abs_vmrs(n2_index,
joker) = 0.7808;
1811 const Index h2o_index
1817 if (0<abs_nls.
nelem())
1822 os <<
"Some of your species require nonlinear treatment,\n"
1823 <<
"but you have no H2O species.";
1824 throw runtime_error( os.str() );
1828 abs_vmrs(h2o_index,
joker) = h2o_ref;
1839 abs_vmrs(h2o_index,
joker),
1844 abs_nls_interp_order,
1850 out1 <<
" WARNING:\n"
1851 <<
" You have no species that require H2O variations.\n"
1852 <<
" This case might work, but it has never been tested.\n"
1853 <<
" Please test it, then remove this warning.\n";
1861 Index& propmat_clearsky_agenda_checked,
1862 Index& abs_xsec_agenda_checked,
1870 propmat_clearsky_agenda_checked =
false;
1871 abs_xsec_agenda_checked =
false;
1884 abs_species.push_back(
temp);
1890 out3 <<
" Added tag groups:";
1891 for (
Index i=n_gs; i<abs_species.
nelem(); ++i )
1893 out3 <<
"\n " << i <<
":";
1894 for (
Index s=0; s<abs_species[i].
nelem(); ++s )
1896 out3 <<
" " << abs_species[i][s].Name();
1909 Index& propmat_clearsky_agenda_checked,
1910 Index& abs_xsec_agenda_checked,
1912 const Index& atmosphere_dim,
1918 const Vector& rq_lat_grid,
1919 const Vector& rq_lon_grid,
1930 propmat_clearsky_agenda_checked =
false;
1931 abs_xsec_agenda_checked =
false;
1936 abs_species.push_back( tags );
1941 out3 <<
" Appended tag group:";
1942 out3 <<
"\n " << abs_species.
nelem()-1 <<
":";
1945 out3 <<
" " << tags[s].Name();
1951 p_grid, lat_grid, lon_grid, rq_p_grid, rq_lat_grid,
1952 rq_lon_grid, species, method, mode,
dx,
1961 abs_species.resize(0);
1968 Index& abs_xsec_agenda_checked,
1969 Index& propmat_clearsky_agenda_checked,
1977 propmat_clearsky_agenda_checked =
false;
1978 abs_xsec_agenda_checked =
false;
1980 abs_species.resize(names.
nelem());
1996 out3 <<
" Defined tag groups: ";
1997 for (
Index i=0; i<abs_species.
nelem(); ++i )
1999 out3 <<
"\n " << i <<
":";
2000 for (
Index s=0; s<abs_species[i].
nelem(); ++s )
2001 out3 <<
" " << abs_species[i][s].Name();
2009 Index& abs_lookup_is_adapted,
2014 abs_lookup.
Adapt( abs_species, f_grid, verbosity );
2015 abs_lookup_is_adapted = 1;
2022 const Index& abs_lookup_is_adapted,
2023 const Index& abs_p_interp_order,
2024 const Index& abs_t_interp_order,
2025 const Index& abs_nls_interp_order,
2026 const Index& abs_f_interp_order,
2030 const Vector& a_vmr_list,
2040 if ( 1!=abs_lookup_is_adapted )
2041 throw runtime_error(
"Gas absorption lookup table must be adapted,\n"
2042 "use method abs_lookupAdapt.");
2047 abs_lookup.
Extract(abs_scalar_gas,
2050 abs_nls_interp_order,
2061 Index nr, nc, stokes_dim;
2066 nr = propmat_clearsky.
nrows();
2067 nc = propmat_clearsky.
ncols();
2071 os <<
"The last two dimensions of propmat_clearsky must be equal (stokes_dim).\n"
2072 <<
"But here they are " << nr <<
" and " << nc <<
".";
2073 throw runtime_error( os.str() );
2077 for(
Index ii = 0; ii < stokes_dim; ii++)
2079 propmat_clearsky(
joker,
joker,ii, ii) += abs_scalar_gas;
2088 Tensor7& propmat_clearsky_field,
2090 const Index& atmfields_checked,
2092 const Index& stokes_dim,
2101 const Agenda& abs_agenda,
2111 if( atmfields_checked != 1 )
2112 throw runtime_error(
"The atmospheric fields must be flagged to have "
2113 "passed a consistency check (atmfields_checked=1)." );
2138 os <<
"Variable doppler must either be empty, or match the dimension of "
2140 throw runtime_error( os.str() );
2147 <<
" Creating field with dimensions:\n"
2148 <<
" " << n_species <<
" gas species,\n"
2149 <<
" " << n_frequencies <<
" frequencies,\n"
2150 <<
" " << n_pressures <<
" pressures,\n"
2151 <<
" " << n_latitudes <<
" latitudes,\n"
2152 <<
" " << n_longitudes <<
" longitudes.\n";
2154 propmat_clearsky_field.
resize(n_species,
2166 Agenda l_abs_agenda (abs_agenda);
2169 bool failed =
false;
2172 Vector this_f_grid = f_grid;
2176 #pragma omp parallel for \
2177 if (!arts_omp_in_parallel() \
2178 && n_pressures >= arts_omp_get_max_threads()) \
2179 firstprivate(l_ws, l_abs_agenda, this_f_grid) \
2180 private(abs, a_vmr_list)
2181 for (
Index ipr=0; ipr<n_pressures; ++ipr )
2184 if (failed)
continue;
2190 Numeric a_pressure = p_grid[ipr];
2192 if (0!=doppler.
nelem())
2194 this_f_grid = f_grid;
2195 this_f_grid += doppler[ipr];
2200 os <<
" p_grid[" << ipr <<
"] = " << a_pressure <<
"\n";
2204 for (
Index ila=0; ila<n_latitudes; ++ila )
2205 for (
Index ilo=0; ilo<n_longitudes; ++ilo )
2207 Numeric a_temperature = t_field( ipr, ila, ilo );
2212 Vector this_rtp_mag(3, 0.);
2214 if (mag_u_field.
npages() != 0)
2216 this_rtp_mag[0] = mag_u_field(ipr, ila, ilo);
2218 if (mag_v_field.
npages() != 0)
2220 this_rtp_mag[1] = mag_v_field(ipr, ila, ilo);
2222 if (mag_w_field.
npages() != 0)
2224 this_rtp_mag[2] = mag_w_field(ipr, ila, ilo);
2235 a_temperature, a_vmr_list,
2240 if ( stokes_dim !=
abs.nrows() || stokes_dim !=
abs.ncols() )
2243 os <<
"propmat_clearsky_fieldCalc was called with stokes_dim = "
2244 << stokes_dim <<
",\n"
2245 <<
"but the stokes_dim returned by the agenda is "
2246 <<
abs.nrows() <<
".";
2247 throw runtime_error( os.str() );
2252 if ( n_species !=
abs.nbooks() )
2255 os <<
"The number of gas species in vmr_field is "
2256 << n_species <<
",\n"
2257 <<
"but the number of species returned by the agenda is "
2258 <<
abs.nbooks() <<
".";
2259 throw runtime_error( os.str() );
2264 if ( n_frequencies !=
abs.npages() )
2267 os <<
"The number of frequencies desired is "
2268 << n_frequencies <<
",\n"
2269 <<
"but the number of frequencies returned by the agenda is "
2270 <<
abs.npages() <<
".";
2271 throw runtime_error( os.str() );
2279 propmat_clearsky_field(
joker,
2283 ipr, ila, ilo ) =
abs ;
2287 catch (runtime_error e)
2289 #pragma omp critical (propmat_clearsky_fieldCalc_fail)
2290 { fail_msg = e.what(); failed =
true; }
2294 if (failed)
throw runtime_error(fail_msg);
2306 f_grid = lookup_f_grid;
2317 p_grid = lookup_p_grid;
2347 const Index& abs_p_interp_order,
2348 const Index& abs_t_interp_order,
2349 const Index& abs_nls_interp_order,
2350 const bool ignore_errors,
2352 const Agenda& abs_xsec_agenda,
2356 const Vector& local_vmrs,
2374 abs_nls_interp_order,
2382 catch (runtime_error x)
2390 throw runtime_error(x.what());
2401 Vector abs_rel_diff(n_f);
2404 for (
Index i=0; i<n_f; ++i)
2405 abs_tab[i] = sga_tab(
joker,i).sum();
2412 Index propmat_clearsky_checked = 1;
2419 propmat_clearsky_checked,
2436 for (
Index i=0; i<n_f; ++i)
2437 abs_lbl[i] = propmat_clearsky(
joker,i,0,0).sum();
2442 assert(abs_tab.
nelem()==n_f);
2443 assert(abs_lbl.
nelem()==n_f);
2444 assert(abs_rel_diff.
nelem()==n_f);
2445 for (
Index i=0; i<n_f; ++i)
2448 abs_rel_diff[i] = fabs( (abs_tab[i] - abs_lbl[i]) / abs_lbl[i] * 100);
2452 Numeric max_abs_rel_diff =
max(abs_rel_diff);
2456 return max_abs_rel_diff;
2466 const Index& abs_lookup_is_adapted,
2467 const Index& abs_p_interp_order,
2468 const Index& abs_t_interp_order,
2469 const Index& abs_nls_interp_order,
2470 const Agenda& abs_xsec_agenda,
2479 if ( 1!=abs_lookup_is_adapted )
2480 throw runtime_error(
"Gas absorption lookup table must be adapted,\n"
2481 "use method abs_lookupAdapt.");
2493 os <<
"This function currently works only with lookup tables\n"
2494 <<
"containing nonlinear species.";
2495 throw runtime_error( os.str() );
2501 Index h2o_index = -1;
2511 if ( h2o_index == -1 )
2514 os <<
"With nonlinear species, at least one species must be a H2O species.";
2515 throw runtime_error( os.str() );
2531 #pragma omp parallel for \
2532 if(!arts_omp_in_parallel())
2533 for (
Index pi=0; pi<n_p; ++pi)
2534 for (
Index ti=0; ti<inbet_t_pert.
nelem(); ++ti)
2550 local_vmrs[h2o_index] *= al.
nls_pert[0];
2558 abs_nls_interp_order,
2572 #pragma omp critical (abs_lookupTestAccuracy_piti)
2574 if (max_abs_rel_diff > err_t)
2575 err_t = max_abs_rel_diff;
2585 for (
Index i=0; i<inbet_nls_pert.
nelem(); ++i)
2593 #pragma omp parallel for \
2594 if(!arts_omp_in_parallel())
2595 for (
Index pi=0; pi<n_p; ++pi)
2596 for (
Index ni=0; ni<inbet_nls_pert.
nelem(); ++ni)
2615 local_vmrs[h2o_index] *= inbet_nls_pert[ni];
2623 abs_nls_interp_order,
2635 #pragma omp critical (abs_lookupTestAccuracy_pini)
2637 if (max_abs_rel_diff > err_nls)
2638 err_nls = max_abs_rel_diff;
2650 Vector inbet_p_grid(n_p-1);
2651 Vector inbet_t_ref(n_p-1);
2652 Matrix inbet_vmrs_ref(n_species, n_p-1);
2656 inbet_t_ref[i] = (al.
t_ref[i]+al.
t_ref[i+1])/2.0;
2657 for (
Index j=0; j<n_species; ++j)
2666 #pragma omp parallel for \
2667 if(!arts_omp_in_parallel())
2668 for (
Index pi=0; pi<n_p-1; ++pi)
2673 Numeric local_p = inbet_p_grid[pi];
2689 local_vmrs[h2o_index] *= al.
nls_pert[0];
2697 abs_nls_interp_order,
2709 #pragma omp critical (abs_lookupTestAccuracy_pi)
2711 if (max_abs_rel_diff > err_p)
2712 err_p = max_abs_rel_diff;
2724 #pragma omp parallel for \
2725 if(!arts_omp_in_parallel())
2726 for (
Index pi=0; pi<n_p-1; ++pi)
2727 for (
Index ti=0; ti<inbet_t_pert.
nelem(); ++ti)
2728 for (
Index ni=0; ni<inbet_nls_pert.
nelem(); ++ni)
2733 Numeric local_p = inbet_p_grid[pi];
2736 Numeric local_t = inbet_t_ref[pi] + inbet_t_pert[ti];
2742 local_vmrs[h2o_index] *= inbet_nls_pert[ni];
2750 abs_nls_interp_order,
2762 #pragma omp critical (abs_lookupTestAccuracy_pitini)
2764 if (max_abs_rel_diff > err_tot)
2766 err_tot = max_abs_rel_diff;
2775 out2 <<
" Max. of absolute value of relative error in percent:\n"
2776 <<
" Note: Unless you have constant reference profiles, the\n"
2777 <<
" pressure interpolation error will have other errors mixed in.\n"
2778 <<
" Temperature interpolation: " << err_t <<
"%\n"
2779 <<
" H2O (NLS) interpolation: " << err_nls <<
"%\n"
2780 <<
" Pressure interpolation: " << err_p <<
"%\n"
2781 <<
" Total error: " << err_tot <<
"%\n";
2804 const Index& abs_lookup_is_adapted,
2805 const Index& abs_p_interp_order,
2806 const Index& abs_t_interp_order,
2807 const Index& abs_nls_interp_order,
2808 const Index& mc_seed,
2809 const Agenda& abs_xsec_agenda,
2819 if ( 1!=abs_lookup_is_adapted )
2820 throw runtime_error(
"Gas absorption lookup table must be adapted,\n"
2821 "use method abs_lookupAdapt.");
2831 os <<
"This function currently works only with lookup tables\n"
2832 <<
"containing nonlinear species.";
2833 throw runtime_error( os.str() );
2839 Index h2o_index = -1;
2849 if ( h2o_index == -1 )
2852 os <<
"With nonlinear species, at least one species must be a H2O species.";
2853 throw runtime_error( os.str() );
2859 const Index chunksize = 100;
2863 rng.
seed(mc_seed, verbosity);
2883 Vector rand_lp(chunksize);
2884 Vector rand_dT(chunksize);
2885 Vector rand_dh2o(chunksize);
2888 Vector max_abs_rel_diff(chunksize);
2891 bool keep_looping=
true;
2897 while (keep_looping)
2901 for (
Index i=0; i<chunksize; ++i)
2905 rand_lp[i] = rng.
draw()*(lp_max-lp_min) + lp_min;
2906 rand_dT[i] = rng.
draw()*(dT_max-dT_min) + dT_min;
2907 rand_dh2o[i] = rng.
draw()*(dh2o_max-dh2o_min) + dh2o_min;
2910 for (
Index i=0; i<chunksize; ++i)
2913 const Numeric this_lp = rand_lp[i];
2923 abs_p_interp_order );
2927 pitw.
resize(abs_p_interp_order+1);
2936 Vector these_vmrs(n_species);
2937 for (
Index j=0; j<n_species; ++j)
2939 these_vmrs[j] =
interp(pitw,
2945 const Numeric this_p = exp(this_lp);
2946 const Numeric this_t = this_t_ref + rand_dT[i];
2947 these_vmrs[h2o_index] *= rand_dh2o[i];
2958 abs_nls_interp_order,
2978 for (
Index i=0; i<chunksize; ++i)
2980 const Numeric x = max_abs_rel_diff[i];
2998 for (
Index i=0; i<chunksize; ++i)
3000 const Numeric x = max_abs_rel_diff[i];
3003 variance += (x -
mean) * (x -
mean);
3014 total_std = sqrt(variance);
3018 const Numeric old_mean = total_mean;
3025 total_std = total_std * total_std;
3027 total_std *= (
Numeric)(N_chunk-1);
3029 total_std += variance;
3031 total_std /= (
Numeric)N_chunk;
3033 total_std = sqrt(total_std);
3037 if (
abs(total_mean-old_mean) < total_mean/100) keep_looping =
false;
3043 out3 <<
" Chunk " << N_chunk <<
": Mean estimate = " << total_mean
3044 <<
" Std estimate = " << total_std <<
"\n";
3048 out2 <<
" Mean relative error: " << total_mean <<
"%\n"
3049 <<
" Standard deviation: " << total_std <<
"%\n";