55 out2 <<
" Created an empty gas absorption lookup table.\n";
62 Index& abs_lookup_is_adapted,
73 const Vector& abs_nls_pert,
108 const Index n_nls_pert = abs_nls_pert.
nelem();
113 Matrix this_vmr(1,n_p_grid);
129 const Index h2o_index
141 os <<
"If you have nonlinear species, at least one\n"
142 <<
"species must be a H2O species.";
143 throw runtime_error( os.str() );
147 out2 <<
" You have no H2O species. Absorption continua will not work.\n"
148 <<
" You should get a runtime error if you try them anyway.\n";
158 os <<
"One of the required input variables is empty:\n"
159 <<
"abs_species.nelem() = " << n_species <<
",\n"
160 <<
"f_grid.nelem() = " << n_f_grid <<
",\n"
161 <<
"abs_p.nelem() = " << n_p_grid <<
".";
162 throw runtime_error( os.str() );
169 for (
Index i=0; i<n_nls; ++i)
172 for (s=0; s<n_species; ++s)
174 if (abs_nls[i]==abs_species[s])
176 abs_nls_idx.push_back(s);
183 os <<
"Did not find *abs_nls* tag group \""
185 <<
"\" in *abs_species*.";
186 throw runtime_error( os.str() );
194 os <<
"The variable *abs_nls* must not have duplicate species.\n"
195 <<
"Value of *abs_nls*: " << abs_nls_idx;
196 throw runtime_error( os.str() );
200 if (abs_lines_per_species.
nelem() != abs_species.
nelem())
203 os <<
"Dimensions of *abs_species* and *abs_lines_per_species* must match. "
204 <<
"*abs_species*: " << abs_species.
nelem() <<
" elements. "
205 <<
"*abs_lines_per_species*: " << abs_lines_per_species.
nelem() <<
" elements.";
206 throw runtime_error( os.str() );
221 if ( ( (0==n_nls) && (0!=n_nls_pert) ) ||
222 ( (0!=n_nls) && (0==n_nls_pert) ) )
225 os <<
"You have to set both abs_nls and abs_nls_pert, or none.";
226 throw runtime_error( os.str() );
232 for (
Index s=0; s<n_nls; ++s )
234 non_linear[abs_nls_idx[s]] = 1;
239 abs_lookup.
species = abs_species;
241 abs_lookup.
f_grid = f_grid;
242 abs_lookup.
p_grid = abs_p;
244 abs_lookup.
t_ref = abs_t;
245 abs_lookup.
t_pert = abs_t_pert;
257 if ( 0 == n_t_pert ) a = 1;
260 b = n_species + n_nls * ( n_nls_pert - 1 );
274 out2 <<
" With temperature perturbations.\n";
275 these_t_pert.
resize(n_t_pert);
276 these_t_pert = abs_t_pert;
280 out2 <<
" No temperature perturbations.\n";
291 const Index these_t_pert_nelem = these_t_pert.
nelem();
297 for (
Index i=0,
spec=0; i<n_species; ++i )
302 out2 <<
" Doing species " << i+1 <<
" of " << n_species <<
": "
303 << abs_species[i] <<
".\n";
306 this_species[0].resize(abs_species[i].nelem());
307 this_species[0] = abs_species[i];
310 these_lines[0].resize(abs_lines_per_species[i].nelem());
311 these_lines[0] = abs_lines_per_species[i];
316 if (1==abs_lineshape.
nelem())
317 this_lineshape[0] = abs_lineshape[0];
319 this_lineshape[0] = abs_lineshape[i];
326 out2 <<
" This is a species with H2O VMR perturbations.\n";
327 these_nls_pert.
resize(n_nls_pert);
328 these_nls_pert = abs_nls_pert;
344 out2 <<
" Doing H2O VMR variant " << s+1 <<
" of " << n_nls_pert <<
": "
345 << abs_nls_pert[s] <<
".\n";
353 this_vmr(0,
joker) *= these_nls_pert[s];
362 if ( h2o_index == -1 )
371 abs_h2o = abs_vmrs(h2o_index,
joker);
372 abs_h2o *= these_nls_pert[s];
397 #pragma omp parallel for \
398 if(!arts_omp_in_parallel() \
399 && these_t_pert_nelem>=arts_omp_get_max_threads()) \
400 private(this_t, abs_xsec_per_species)
401 for (
Index j=0; j<these_t_pert_nelem; ++j )
415 os <<
" Doing temperature variant " << j+1
416 <<
" of " << n_t_pert <<
": "
417 << these_t_pert[j] <<
".\n";
423 this_t = abs_lookup.
t_ref;
424 this_t += these_t_pert[j];
430 f_grid, abs_p, verbosity );
458 for (
Index p=0; p<n_p_grid; ++p )
483 catch (runtime_error e)
494 abs_lookup_is_adapted = 1;
537 for (
Index s=0; s<abs_species[i].
nelem(); ++s )
542 if ( abs_species[i][s].Isotope() <
543 species_data[abs_species[i][s].Species()].Isotope().nelem() )
547 species_data[abs_species[i][s].Species()].Isotope()[abs_species[i][s].Isotope()].Abundance() )
549 const String thisname = abs_species[i][s].Name();
551 out3 <<
" Continuum tag: " << thisname;
567 "N2-"==thisname.substr(0,3) ||
568 "CO2-"==thisname.substr(0,4) ||
569 "O2-CIA"==thisname.substr(0,6) ||
570 "O2-v0v"==thisname.substr(0,6) ||
571 "O2-v1v"==thisname.substr(0,6) )
573 out3 <<
" --> not added.\n";
578 if (
"O2-"==thisname.substr(0,3) )
581 out3 <<
" --> added to abs_nls.\n";
588 out3 <<
" --> unknown.\n";
589 throw runtime_error(
"I don't know whether this tag uses h2o_abs or not.\n"
590 "Cannot set abs_nls automatically.");
617 while (-1 != (next_h2o =
622 abs_nls.push_back(abs_species[next_h2o]);
634 abs_nls.push_back(abs_species[cont[i]]);
637 out2 <<
" Species marked for nonlinear treatment:\n";
643 if (j!=0) out2 <<
", ";
644 out2 << abs_nls[i][j].Name();
670 const Index& p_interp_order,
671 const Index& t_interp_order,
701 Numeric delta_min = tmin[i] - abs_t[gp.
idx[j]] - 10;
702 Numeric delta_max = tmax[i] - abs_t[gp.
idx[j]] + 10;
704 if ( delta_min < mindev ) mindev = delta_min;
705 if ( delta_max > maxdev ) maxdev = delta_max;
709 out3 <<
" abs_t_pert: mindev/maxdev : " << mindev <<
" / " << maxdev <<
"\n";
714 Index div = t_interp_order;
718 effective_step = (maxdev-mindev)/(
Numeric)div;
721 while (effective_step > step);
723 abs_t_pert =
Vector(mindev, div, effective_step);
725 out2 <<
" abs_t_pert: " << abs_t_pert[0] <<
" K to " << abs_t_pert[abs_t_pert.
nelem()-1]
726 <<
" K in steps of " << effective_step
727 <<
" K (" << abs_t_pert.
nelem() <<
" grid points)\n";
750 const Index& p_interp_order,
751 const Index& nls_interp_order,
794 Numeric delta_min = minprof[i] / refprof[gp.
idx[j]];
795 Numeric delta_max = 2*maxprof[i] / refprof[gp.
idx[j]];
797 if ( delta_min < mindev ) mindev = delta_min;
798 if ( delta_max > maxdev ) maxdev = delta_max;
802 out3 <<
" abs_nls_pert: mindev/maxdev : " << mindev <<
" / " << maxdev <<
"\n";
804 bool allownegative =
false;
807 out2 <<
" Warning: I am getting a negative fractional distance to the H2O\n"
808 <<
" reference profile. Some of your H2O fields may contain negative values.\n"
809 <<
" Will allow negative values also for abs_nls_pert.\n";
810 allownegative =
true;
816 out3 <<
" Adjusted mindev : " << mindev <<
"\n";
822 Index div = nls_interp_order;
826 effective_step = (maxdev-mindev)/(
Numeric)div;
829 while (effective_step > step);
831 abs_nls_pert =
Vector(mindev, div, effective_step);
838 out2 <<
" I am including also 0 in the abs_nls_pert, because it is a turning \n"
839 <<
" point. Consider to use a higher abs_nls_interp_order, for example 4.\n";
842 out2 <<
" abs_nls_pert: " << abs_nls_pert[0] <<
" to " << abs_nls_pert[abs_nls_pert.
nelem()-1]
843 <<
" (fractional units) in steps of " << abs_nls_pert[1]-abs_nls_pert[0]
844 <<
" (" << abs_nls_pert.
nelem() <<
" grid points)\n";
858 const Index& atmosphere_dim,
865 const Index& abs_p_interp_order,
866 const Index& abs_t_interp_order,
867 const Index& abs_nls_interp_order,
877 const Numeric p_step = log(pow(10.0, p_step10));
889 if (p_grid.
nelem()<2)
892 os <<
"You need at least two pressure levels.";
893 throw runtime_error( os.str() );
898 p_grid, lat_grid, lon_grid);
902 abs_species.
nelem(), p_grid, lat_grid, lon_grid);
905 if ( p_step <= 0 || t_step <= 0 || h2o_step <= 0 )
908 os <<
"The keyword arguments p_step, t_step, and h2o_step must be >0.";
909 throw runtime_error( os.str() );
933 log_abs_p_a.push_back(log_p_grid[0]);
937 const Numeric dp = log_p_grid[i-1] - log_p_grid[i];
939 const Numeric dp_by_p_step = dp/p_step;
952 for (
Index j=1; j<=n; ++j)
953 log_abs_p_a.push_back(log_p_grid[i-1] - (
Numeric)j*ddp);
960 log_abs_p[i] = log_abs_p_a[i];
967 if (abs_p.
nelem()<abs_p_interp_order+1)
970 os <<
"Your pressure grid does not have enough levels for the desired interpolation order.";
971 throw runtime_error( os.str() );
979 gridpos(gp, log_p_grid, log_abs_p);
988 if (1==atmosphere_dim)
1007 vmr_field(i,
joker,0,0),
1060 const Index h2o_index
1068 if (0<abs_nls.
nelem())
1074 os <<
"Some of your species require nonlinear treatment,\n"
1075 <<
"but you have no H2O species.";
1076 throw runtime_error( os.str() );
1104 abs_p_interp_order, abs_t_interp_order,
1117 if (0<abs_nls.
nelem())
1121 vmrmean(h2o_index,
joker),
1126 abs_nls_interp_order,
1151 const Index& abs_p_interp_order,
1152 const Index& abs_t_interp_order,
1153 const Index& abs_nls_interp_order,
1167 const Numeric p_step = log(pow(10.0, p_step10));
1173 const Index indoff = batch_fields[0].data.nbooks()-abs_species.
nelem();
1191 const ArrayOfString field_names = batch_fields[0].get_string_grid(0);
1198 if (field_names.
nelem() < 3)
1200 os <<
"Atmospheric states in batch_fields must have at\n"
1201 <<
"least three fields: T, z, and at least one species.";
1202 throw runtime_error( os.str() );
1205 if (abs_species.
nelem() < 1)
1207 os <<
"At least one absorption species needs to be defined "
1208 <<
"in abs_species.";
1209 throw runtime_error( os.str() );
1225 if (abs_species.
nelem() > field_names.
nelem()-2)
1227 os <<
"Dimension of fields in batch_fields does not match that of abs_species.\n"
1228 <<
"(First two fields must be T and z, the N last fields must match the\n"
1229 <<
"absorption species, where N is the number of species as defined in abs_species.)\n"
1230 <<
"Field names: " << field_names <<
"\n"
1231 <<
"Absorption species: " << species_names;
1232 throw runtime_error( os.str() );
1235 os <<
"The consistency check of the first compact atmospheric state in\n"
1236 <<
"batch_fields has shown one or more errors:\n";
1239 if (
"T" != field_names[0])
1241 os <<
"The first field name must be T.\n";
1246 if (
"z" != field_names[1])
1248 os <<
"The second field name must be z.\n";
1258 os <<
"One of the atmospheric fields must be H2O.\n";
1263 bool wrong_species =
false;
1265 if (field_names[indoff+i] != species_names[i])
1266 wrong_species =
true;
1270 os <<
"The " << abs_species.
nelem() <<
" last field names must "
1271 <<
"match the absorption species in\n"
1272 <<
"abs_species, which are:\n"
1273 << species_names <<
"\n";
1277 os <<
"Your field names are:\n"
1280 if (bail)
throw runtime_error( os.str() );
1303 os <<
"You need at least two pressure levels.";
1304 throw runtime_error( os.str() );
1313 Index np = (
Index) ceil((log(maxp)-log(minp))/p_step)+1;
1318 if (np < abs_p_interp_order+1)
1319 np = abs_p_interp_order+1;
1321 Vector log_abs_p(log(maxp), np, -p_step);
1322 log_abs_p[np-1] = log(minp);
1326 out2 <<
" abs_p: " << abs_p[0] <<
" Pa to " << abs_p[np-1]
1327 <<
" Pa in log10 steps of " << p_step10
1328 <<
" (" << np <<
" grid points)\n";
1344 Matrix datamean (n_variables, np, 0);
1363 throw runtime_error(
"All fields in the batch must have the same field names.");
1369 os <<
"The first variable in the compact atmospheric state must be \"T\",\n"
1371 throw runtime_error( os.str() );
1379 os <<
"According to abs_species setting the " << indoff+h2o_index
1380 <<
". variable in the compact\n"
1381 <<
"atmospheric state is supposed to be \"H2O\",\n"
1384 throw runtime_error( os.str() );
1389 const Tensor4& data = batch_fields[i].data;
1398 for (
Index ilat=0; ilat<data.
nrows(); ++ilat)
1399 for (
Index ilon=0; ilon<data.
ncols(); ++ilon)
1402 if (data(0,ip,ilat,ilon) < mint) mint = data(0,ip,ilat,ilon);
1403 if (data(0,ip,ilat,ilon) > maxt) maxt = data(0,ip,ilat,ilon);
1405 if (data(indoff+h2o_index,ip,ilat,ilon) < minh2o)
1406 { minh2o = data(indoff+h2o_index,ip,ilat,ilon); }
1407 if (data(indoff+h2o_index,ip,ilat,ilon) > maxh2o)
1408 { maxh2o = data(indoff+h2o_index,ip,ilat,ilon); }
1424 const Numeric eps_bottom = (log_p_grid[0]-log_p_grid[1])/2.1;
1426 while (log_abs_p[first_p] > log_p_grid[0]+eps_bottom) ++first_p;
1428 const Numeric eps_top = (log_p_grid[log_p_grid.
nelem()-2]-log_p_grid[log_p_grid.
nelem()-1])/2.1;
1430 while (log_abs_p[last_p] < log_p_grid[log_p_grid.
nelem()-1]-eps_top) --last_p;
1432 const Index extent_p = last_p - first_p + 1;
1450 gridpos(gp, log_p_grid, active_log_abs_p);
1466 Tensor4 data_interp(n_variables,
1467 active_log_abs_p.
nelem(),
1477 for (
Index fi=0; fi<2; ++fi)
1480 data(fi,
joker, la, lo),
1485 data(fi,
joker, la, lo),
1495 for (
Index lo=0; lo<data_interp.
ncols(); ++lo)
1496 for (
Index la=0; la<data_interp.
nrows(); ++la)
1504 if (0==fi || (h2o_index+2)==fi)
1506 if (data_interp(fi, pr, la, lo) < datamin(fi, first_p+pr))
1507 datamin(fi, first_p+pr) = data_interp(fi, pr, la, lo);
1508 if (data_interp(fi, pr, la, lo) > datamax(fi, first_p+pr))
1509 datamax(fi, first_p+pr) = data_interp(fi, pr, la, lo);
1512 datamean(fi, first_p+pr) += data_interp(fi, pr, la, lo);
1521 mean_norm[
Range(first_p, extent_p)] += 1;
1525 out2 <<
" Global statistics:\n"
1526 <<
" min(p) / max(p) [Pa]: " << minp <<
" / " << maxp <<
"\n"
1527 <<
" min(T) / max(T) [K]: " << mint <<
" / " << maxt <<
"\n"
1528 <<
" min(H2O) / max(H2O) [VMR]: " << minh2o <<
" / " << maxh2o <<
"\n";
1532 assert(np==mean_norm.
nelem());
1535 for (
Index pi=0; pi<np; ++pi)
1540 if (0<mean_norm[pi])
1541 datamean(fi,pi) /= mean_norm[pi];
1545 os <<
"No data at pressure level " << pi+1
1546 <<
" of "<< np <<
" (" << abs_p[pi] <<
" hPa).";
1547 throw runtime_error( os.str() );
1555 assert(log_abs_p.
nelem()==np);
1557 for (
Index i=0; i<np; ++i)
1560 gridpos_poly(gp, log_abs_p, log_abs_p[i], abs_p_interp_order);
1571 smooth_datamean(fi,i) += datamean(fi,gp.
idx[j]);
1585 for (
Index i=0; i<np; ++i)
1592 Numeric& mean_h2o = smooth_datamean(h2o_index+2,i);
1593 Numeric& max_h2o = datamax(h2o_index+2,i);
1598 out3 <<
" H2O profile contained zero values, adjusted to 1e-9.\n";
1604 abs_t = smooth_datamean(0,
joker);
1610 assert(abs_species.
nelem()==smooth_datamean.
nrows()-2);
1618 choose_abs_t_pert(abs_t_pert, abs_t, tmin, tmax, t_step, abs_p_interp_order, abs_t_interp_order,
1626 h2omin, h2omax, h2o_step,
1627 abs_p_interp_order, abs_nls_interp_order,
1632 if (0!=extremes.
nelem())
1635 if (4!=extremes.
nelem())
1638 os <<
"There must be exactly 4 elements in extremes:\n"
1639 <<
"min(abs_t_pert), max(abs_t_pert), min(abs_nls_pert), max(abs_nls_pert)";
1640 throw runtime_error( os.str() );
1644 if (extremes[0] < abs_t_pert[0])
1646 Vector dummy = abs_t_pert;
1648 abs_t_pert[0] = extremes[0];
1650 out2 <<
" Added min extreme value for abs_t_pert: "
1651 << abs_t_pert[0] <<
"\n";
1655 if (extremes[1] > abs_t_pert[abs_t_pert.
nelem()-1])
1657 Vector dummy = abs_t_pert;
1660 abs_t_pert[abs_t_pert.
nelem()-1] = extremes[1];
1661 out2 <<
" Added max extreme value for abs_t_pert: "
1662 << abs_t_pert[abs_t_pert.
nelem()-1] <<
"\n";
1666 if (extremes[2] < abs_nls_pert[0])
1668 Vector dummy = abs_nls_pert;
1670 abs_nls_pert[0] = extremes[2];
1671 abs_nls_pert[
Range(1,dummy.
nelem())] = dummy;
1672 out2 <<
" Added min extreme value for abs_nls_pert: "
1673 << abs_nls_pert[0] <<
"\n";
1677 if (extremes[3] > abs_nls_pert[abs_nls_pert.
nelem()-1])
1679 Vector dummy = abs_nls_pert;
1681 abs_nls_pert[
Range(0,dummy.
nelem())] = dummy;
1682 abs_nls_pert[abs_nls_pert.
nelem()-1] = extremes[3];
1683 out2 <<
" Added max extreme value for abs_nls_pert: "
1684 << abs_nls_pert[abs_nls_pert.
nelem()-1] <<
"\n";
1699 const Index& abs_p_interp_order,
1700 const Index& abs_t_interp_order,
1701 const Index& abs_nls_interp_order,
1717 const Numeric p_step = log(pow(10.0, p_step10));
1729 Index np = (
Index) ceil((log(p_max)-log(p_min))/p_step)+1;
1734 if (np < abs_p_interp_order+1)
1735 np = abs_p_interp_order+1;
1737 Vector log_abs_p(log(p_max), np, -p_step);
1741 out2 <<
" abs_p: " << abs_p[0] <<
" Pa to " << abs_p[np-1]
1742 <<
" Pa in log10 steps of " << p_step10
1743 <<
" (" << np <<
" grid points)\n";
1751 Numeric t_ref = (t_min + t_max) / 2;
1758 Vector min_prof(np), max_prof(np);
1764 abs_t, min_prof, max_prof, 20,
1765 abs_p_interp_order, abs_t_interp_order,
1786 const Index o2_index
1791 abs_vmrs(o2_index,
joker) = 0.2095;
1794 const Index n2_index
1799 abs_vmrs(n2_index,
joker) = 0.7808;
1804 const Index h2o_index
1810 if (0<abs_nls.
nelem())
1815 os <<
"Some of your species require nonlinear treatment,\n"
1816 <<
"but you have no H2O species.";
1817 throw runtime_error( os.str() );
1821 abs_vmrs(h2o_index,
joker) = h2o_ref;
1832 abs_vmrs(h2o_index,
joker),
1837 abs_nls_interp_order,
1843 out1 <<
" WARNING:\n"
1844 <<
" You have no species that require H2O variations.\n"
1845 <<
" This case might work, but it has never been tested.\n"
1846 <<
" Please test it, then remove this warning.\n";
1871 abs_species.push_back(
temp);
1875 out3 <<
" Added tag groups:";
1876 for (
Index i=n_gs; i<abs_species.
nelem(); ++i )
1878 out3 <<
"\n " << i <<
":";
1879 for (
Index s=0; s<abs_species[i].
nelem(); ++s )
1881 out3 <<
" " << abs_species[i][s].Name();
1895 const Index& atmosphere_dim,
1901 const Vector& rq_lat_grid,
1902 const Vector& rq_lon_grid,
1915 abs_species.push_back( tags );
1918 out3 <<
" Appended tag group:";
1919 out3 <<
"\n " << abs_species.
nelem()-1 <<
":";
1920 for (
Index s=0; s<tags.nelem(); ++s )
1922 out3 <<
" " << tags[s].Name();
1928 p_grid, lat_grid, lon_grid, rq_p_grid, rq_lat_grid,
1929 rq_lon_grid, species, method, mode,
dx,
1938 abs_species.resize(0);
1951 abs_species.resize(names.
nelem());
1965 out3 <<
" Defined tag groups: ";
1966 for (
Index i=0; i<abs_species.
nelem(); ++i )
1968 out3 <<
"\n " << i <<
":";
1969 for (
Index s=0; s<abs_species[i].
nelem(); ++s )
1971 out3 <<
" " << abs_species[i][s].Name();
1980 Index& abs_lookup_is_adapted,
1985 abs_lookup.
Adapt( abs_species, f_grid, verbosity );
1986 abs_lookup_is_adapted = 1;
1993 const Index& abs_lookup_is_adapted,
1994 const Index& abs_p_interp_order,
1995 const Index& abs_t_interp_order,
1996 const Index& abs_nls_interp_order,
1997 const Index& f_index,
2000 const Vector& a_vmr_list,
2008 if ( 1!=abs_lookup_is_adapted )
2009 throw runtime_error(
"Gas absorption lookup table must be adapted,\n"
2010 "use method abs_lookupAdapt.");
2015 abs_lookup.
Extract( abs_scalar_gas,
2018 abs_nls_interp_order,
2027 out3 <<
" Doppler shift: None\n";
2032 os <<
" Doppler shift: " << a_doppler <<
" Hz\n";
2037 const Index n_f_grid = f_grid_original.
nelem();
2040 Index f_start, f_extent;
2046 f_extent = n_f_grid;
2056 assert ( f_index < n_f_grid );
2061 const Range f_range(f_start,f_extent);
2065 Vector f_shifted = f_grid_original_view;
2066 f_shifted -= a_doppler;
2070 "to Doppler-shifted frequency grid",
2071 f_grid_original_view,
2078 gridpos(gp,f_grid_original_view,f_shifted,extpolfac);
2087 for (
Index i=0; i<abs_scalar_gas.
ncols(); ++i)
2094 abs_scalar_gas(
Range(
joker),i) = abs_interpolated;
2106 const Agenda& sga_agenda,
2107 const Index& f_index,
2109 const Index& atmosphere_dim,
2169 os <<
"Variable doppler must either be empty, or match the dimension of "
2171 throw runtime_error( os.str() );
2181 f_extent = n_frequencies;
2188 if ( f_index >= n_frequencies )
2191 os <<
"The frequency index f_index points to a frequency outside"
2192 <<
"the frequency grid. (f_index = " << f_index
2193 <<
", n_frequencies = " << n_frequencies <<
")";
2194 throw runtime_error( os.str() );
2203 out2 <<
" Creating field with dimensions:\n"
2204 <<
" " << n_species <<
" gas species,\n"
2205 <<
" " << f_extent <<
" frequencies,\n"
2206 <<
" " << n_pressures <<
" pressures,\n"
2207 <<
" " << n_latitudes <<
" latitudes,\n"
2208 <<
" " << n_longitudes <<
" longitudes.\n";
2210 asg_field.
resize( n_species,
2220 Agenda l_sga_agenda (sga_agenda);
2231 #pragma omp parallel for \
2232 if(!arts_omp_in_parallel() && n_pressures>=arts_omp_get_max_threads()) \
2233 firstprivate(l_ws, l_sga_agenda) \
2234 private(asg, a_vmr_list)
2235 for (
Index ipr=0; ipr<n_pressures; ++ipr )
2241 Numeric a_pressure = p_grid[ipr];
2244 if (0!=doppler.
nelem()) a_doppler = doppler[ipr];
2248 os <<
" p_grid[" << ipr <<
"] = " << a_pressure <<
"\n";
2252 for (
Index ila=0; ila<n_latitudes; ++ila )
2253 for (
Index ilo=0; ilo<n_longitudes; ++ilo )
2255 Numeric a_temperature = t_field( ipr, ila, ilo );
2264 f_index, a_doppler, a_pressure,
2265 a_temperature, a_vmr_list,
2270 if ( n_species != asg.ncols() )
2273 os <<
"The number of gas species in vmr_field is "
2274 << n_species <<
",\n"
2275 <<
"but the number of species returned by the agenda is "
2276 << asg.ncols() <<
".";
2277 throw runtime_error( os.str() );
2282 if ( f_extent != asg.nrows() )
2285 os <<
"The number of frequencies desired is "
2286 << n_frequencies <<
",\n"
2287 <<
"but the number of frequencies returned by the agenda is "
2288 << asg.nrows() <<
".";
2289 throw runtime_error( os.str() );
2303 catch (runtime_error e)
2320 f_grid = lookup_f_grid;
2331 p_grid = lookup_p_grid;
2360 const Index& abs_p_interp_order,
2361 const Index& abs_t_interp_order,
2362 const Index& abs_nls_interp_order,
2363 const bool ignore_errors,
2374 const Vector& local_vmrs,
2393 abs_nls_interp_order,
2399 catch (runtime_error x)
2407 throw runtime_error(x.what());
2418 Vector abs_rel_diff(n_f);
2421 for (
Index i=0; i<n_f; ++i)
2422 abs_tab[i] = sga_tab(i,
joker).sum();
2431 abs_lines_per_species,
2435 abs_cont_parameters,
2446 for (
Index i=0; i<n_f; ++i)
2447 abs_lbl[i] = sga_lbl(i,
joker).sum();
2452 assert(abs_tab.
nelem()==n_f);
2453 assert(abs_lbl.
nelem()==n_f);
2454 assert(abs_rel_diff.
nelem()==n_f);
2455 for (
Index i=0; i<n_f; ++i)
2458 abs_rel_diff[i] = fabs( (abs_tab[i] - abs_lbl[i]) / abs_lbl[i] * 100);
2462 Numeric max_abs_rel_diff =
max(abs_rel_diff);
2466 return max_abs_rel_diff;
2474 const Index& abs_lookup_is_adapted,
2475 const Index& abs_p_interp_order,
2476 const Index& abs_t_interp_order,
2477 const Index& abs_nls_interp_order,
2491 if ( 1!=abs_lookup_is_adapted )
2492 throw runtime_error(
"Gas absorption lookup table must be adapted,\n"
2493 "use method abs_lookupAdapt.");
2497 const Index n_nls = al.nonlinear_species.nelem();
2498 const Index n_species = al.species.nelem();
2500 const Index n_p = al.log_p_grid.nelem();
2505 os <<
"This function currently works only with lookup tables\n"
2506 <<
"containing nonlinear species.";
2507 throw runtime_error( os.str() );
2513 Index h2o_index = -1;
2523 if ( h2o_index == -1 )
2526 os <<
"With nonlinear species, at least one species must be a H2O species.";
2527 throw runtime_error( os.str() );
2534 Vector inbet_t_pert(al.t_pert.nelem()-1);
2536 inbet_t_pert[i] = (al.t_pert[i]+al.t_pert[i+1])/2.0;
2550 #pragma omp parallel for \
2551 if(!arts_omp_in_parallel())
2552 for (
Index pi=0; pi<n_p; ++pi)
2553 for (
Index ti=0; ti<inbet_t_pert.
nelem(); ++ti)
2558 Numeric local_p = al.p_grid[pi];
2561 Numeric local_t = al.t_ref[pi] + inbet_t_pert[ti];
2569 local_vmrs[h2o_index] *= al.nls_pert[0];
2576 abs_nls_interp_order,
2580 abs_lines_per_species,
2584 abs_cont_parameters,
2595 #pragma omp critical
2597 if (max_abs_rel_diff > err_t)
2598 err_t = max_abs_rel_diff;
2607 Vector inbet_nls_pert(al.nls_pert.nelem()-1);
2608 for (
Index i=0; i<inbet_nls_pert.
nelem(); ++i)
2609 inbet_nls_pert[i] = (al.nls_pert[i]+al.nls_pert[i+1])/2.0;
2623 #pragma omp parallel for \
2624 if(!arts_omp_in_parallel())
2625 for (
Index pi=0; pi<n_p; ++pi)
2626 for (
Index ni=0; ni<inbet_nls_pert.
nelem(); ++ni)
2631 Numeric local_p = al.p_grid[pi];
2639 Numeric local_t = al.t_ref[pi] + al.t_pert[0];
2645 local_vmrs[h2o_index] *= inbet_nls_pert[ni];
2652 abs_nls_interp_order,
2656 abs_lines_per_species,
2660 abs_cont_parameters,
2669 #pragma omp critical
2671 if (max_abs_rel_diff > err_nls)
2672 err_nls = max_abs_rel_diff;
2684 Vector inbet_p_grid(n_p-1);
2685 Vector inbet_t_ref(n_p-1);
2686 Matrix inbet_vmrs_ref(n_species, n_p-1);
2689 inbet_p_grid[i] = exp((al.log_p_grid[i]+al.log_p_grid[i+1])/2.0);
2690 inbet_t_ref[i] = (al.t_ref[i]+al.t_ref[i+1])/2.0;
2691 for (
Index j=0; j<n_species; ++j)
2692 inbet_vmrs_ref(j,i) = (al.vmrs_ref(j,i)+al.vmrs_ref(j,i+1))/2.0;
2707 #pragma omp parallel for \
2708 if(!arts_omp_in_parallel())
2709 for (
Index pi=0; pi<n_p-1; ++pi)
2714 Numeric local_p = inbet_p_grid[pi];
2722 Numeric local_t = inbet_t_ref[pi] + al.t_pert[0];
2730 local_vmrs[h2o_index] *= al.nls_pert[0];
2737 abs_nls_interp_order,
2741 abs_lines_per_species,
2745 abs_cont_parameters,
2754 #pragma omp critical
2756 if (max_abs_rel_diff > err_p)
2757 err_p = max_abs_rel_diff;
2778 #pragma omp parallel for \
2779 if(!arts_omp_in_parallel())
2780 for (
Index pi=0; pi<n_p-1; ++pi)
2781 for (
Index ti=0; ti<inbet_t_pert.
nelem(); ++ti)
2782 for (
Index ni=0; ni<inbet_nls_pert.
nelem(); ++ni)
2787 Numeric local_p = inbet_p_grid[pi];
2790 Numeric local_t = inbet_t_ref[pi] + inbet_t_pert[ti];
2796 local_vmrs[h2o_index] *= inbet_nls_pert[ni];
2803 abs_nls_interp_order,
2807 abs_lines_per_species,
2811 abs_cont_parameters,
2820 #pragma omp critical
2822 if (max_abs_rel_diff > err_tot)
2824 err_tot = max_abs_rel_diff;
2833 out2 <<
" Max. of absolute value of relative error in percent:\n"
2834 <<
" Note: Unless you have constant reference profiles, the\n"
2835 <<
" pressure interpolation error will have other errors mixed in.\n"
2836 <<
" Temperature interpolation: " << err_t <<
"%\n"
2837 <<
" H2O (NLS) interpolation: " << err_nls <<
"%\n"
2838 <<
" Pressure interpolation: " << err_p <<
"%\n"
2839 <<
" Total error: " << err_tot <<
"%\n";
2860 const Index& abs_lookup_is_adapted,
2861 const Index& abs_p_interp_order,
2862 const Index& abs_t_interp_order,
2863 const Index& abs_nls_interp_order,
2870 const Index& mc_seed,
2879 if ( 1!=abs_lookup_is_adapted )
2880 throw runtime_error(
"Gas absorption lookup table must be adapted,\n"
2881 "use method abs_lookupAdapt.");
2885 const Index n_nls = al.nonlinear_species.nelem();
2886 const Index n_species = al.species.nelem();
2891 os <<
"This function currently works only with lookup tables\n"
2892 <<
"containing nonlinear species.";
2893 throw runtime_error( os.str() );
2899 Index h2o_index = -1;
2909 if ( h2o_index == -1 )
2912 os <<
"With nonlinear species, at least one species must be a H2O species.";
2913 throw runtime_error( os.str() );
2919 const Index chunksize = 100;
2923 rng.
seed(mc_seed, verbosity);
2927 const Numeric lp_max = al.log_p_grid[0];
2928 const Numeric lp_min = al.log_p_grid[al.log_p_grid.nelem()-1];
2931 const Numeric dT_min = al.t_pert[0];
2932 const Numeric dT_max = al.t_pert[al.t_pert.nelem()-1];
2935 const Numeric dh2o_min = al.nls_pert[0];
2936 const Numeric dh2o_max = al.nls_pert[al.nls_pert.nelem()-1];
2943 Vector rand_lp(chunksize);
2944 Vector rand_dT(chunksize);
2945 Vector rand_dh2o(chunksize);
2948 Vector max_abs_rel_diff(chunksize);
2951 bool keep_looping=
true;
2957 while (keep_looping)
2961 for (
Index i=0; i<chunksize; ++i)
2965 rand_lp[i] = rng.
draw()*(lp_max-lp_min) + lp_min;
2966 rand_dT[i] = rng.
draw()*(dT_max-dT_min) + dT_min;
2967 rand_dh2o[i] = rng.
draw()*(dh2o_max-dh2o_min) + dh2o_min;
2970 for (
Index i=0; i<chunksize; ++i)
2973 const Numeric this_lp = rand_lp[i];
2983 abs_p_interp_order );
2987 pitw.
resize(abs_p_interp_order+1);
2996 Vector these_vmrs(n_species);
2997 for (
Index j=0; j<n_species; ++j)
2999 these_vmrs[j] =
interp(pitw,
3005 const Numeric this_p = exp(this_lp);
3006 const Numeric this_t = this_t_ref + rand_dT[i];
3007 these_vmrs[h2o_index] *= rand_dh2o[i];
3017 abs_nls_interp_order,
3021 abs_lines_per_species,
3025 abs_cont_parameters,
3042 for (
Index i=0; i<chunksize; ++i)
3044 const Numeric x = max_abs_rel_diff[i];
3062 for (
Index i=0; i<chunksize; ++i)
3064 const Numeric x = max_abs_rel_diff[i];
3067 variance += (x -
mean) * (x -
mean);
3078 total_std = sqrt(variance);
3082 const Numeric old_mean = total_mean;
3089 total_std = total_std * total_std;
3091 total_std *= (
Numeric)(N_chunk-1);
3093 total_std += variance;
3095 total_std /= (
Numeric)N_chunk;
3097 total_std = sqrt(total_std);
3101 if (
abs(total_mean-old_mean) < total_mean/100) keep_looping =
false;
3107 out3 <<
" Chunk " << N_chunk <<
": Mean estimate = " << total_mean
3108 <<
" Std estimate = " << total_std <<
"\n";
3112 out2 <<
" Mean relative error: " << total_mean <<
"%\n"
3113 <<
" Standard deviation: " << total_std <<
"%\n";