58 assert(n_new_grid == pos.
nelem());
64 for (
Index i = 0;
i < n_new_grid; ++
i) {
69 while (
abs(new_grid[
i] - old_grid[j]) >
70 max(
abs(new_grid[
i]),
abs(old_grid[j])) * DBL_EPSILON) {
72 if (j >= n_old_grid) {
74 os <<
"Cannot find new frequency " << i <<
" (" << new_grid[i]
75 <<
"Hz) in the lookup table frequency grid.";
76 throw runtime_error(os.
str());
81 out3 <<
" " << new_grid[i] <<
" found, index = " << pos[i] <<
".\n";
125 const Index n_current_species = current_species.
nelem();
126 const Index n_current_f_grid = current_f_grid.
nelem();
134 out2 <<
" Original table: " << n_species <<
" species, " << n_f_grid
136 <<
" Adapt to: " << n_current_species <<
" species, " 137 << n_current_f_grid <<
" frequencies.\n";
140 out2 <<
" Table contains no nonlinear species.\n";
145 for (
Index s = 0; s < n_nls; ++s) {
150 out2 <<
" Table contains no temperature perturbations.\n";
162 if (0 == n_species) {
164 os <<
"The lookup table should have at least one species.";
165 throw runtime_error(os.
str());
172 os <<
"The table must not have duplicate nonlinear species.\n" 174 throw runtime_error(os.
str());
180 os <<
"nonlinear_species[" <<
i <<
"]";
206 if (0 == n_nls_pert) {
208 os <<
"The vector nls_pert should contain the perturbations\n" 209 <<
"for the nonlinear species, but it is empty.";
210 throw runtime_error(os.
str());
229 chk_size(
"xsec",
xsec, 1, n_species, n_f_grid, n_p_grid);
247 Index b = n_species + n_nls * (n_nls_pert - 1);
258 for (
Index i = 0, sp = 0;
i < n_species; ++
i) {
259 original_spec_pos_in_xsec[
i] = sp;
269 if (0 == n_current_species) {
271 os <<
"The list of current species should not be empty.";
272 throw runtime_error(os.
str());
282 out3 <<
" Looking for species in lookup table:\n";
283 for (
Index i = 0;
i < n_current_species; ++
i) {
287 i_current_species[
i] =
292 const Index spec_type = current_species[
i][0].Type();
297 i_current_species[
i] = -1;
301 <<
" is missing in absorption lookup table.";
302 throw runtime_error(os.
str());
306 out3 <<
"found (or trivial).\n";
310 Index n_current_nonlinear_species = 0;
316 out3 <<
" Finding out which of the current species are nonlinear:\n";
317 for (
Index i = 0;
i < n_current_species; ++
i) {
318 if (i_current_species[
i] >= 0)
321 if (non_linear[i_current_species[
i]]) {
324 current_non_linear[
i] = 1;
325 ++n_current_nonlinear_species;
338 out3 <<
" Looking for Frequencies in lookup table:\n";
344 i_current_f_grid,
f_grid, current_f_grid, verbosity);
350 new_table.
species.resize(n_current_species);
351 for (
Index i = 0;
i < n_current_species; ++
i) {
352 if (i_current_species[
i] >= 0) {
361 new_table.
species[
i] = current_species[
i];
367 for (
Index i = 0;
i < n_current_f_grid; ++
i) {
377 for (
Index i = 0;
i < n_current_species; ++
i) {
378 if (i_current_species[
i] >= 0) {
406 n_current_species + n_current_nonlinear_species * (n_nls_pert - 1),
415 for (
Index i_s = 0, sp = 0; i_s < n_current_species; ++i_s) {
418 if (current_non_linear[i_s])
427 for (
Index i_f = 0; i_f < n_current_f_grid; ++i_f) {
428 if (i_current_species[i_s] >= 0) {
431 Range(original_spec_pos_in_xsec[i_current_species[i_s]], n_v),
432 i_current_f_grid[i_f],
516 const Index& p_interp_order,
517 const Index& t_interp_order,
518 const Index& h2o_interp_order,
519 const Index& f_interp_order,
524 const Numeric& extpolfac)
const {
547 const Index n_new_f_grid = new_f_grid.
nelem();
558 Index h2o_index = -1;
567 if (h2o_index == -1) {
569 os <<
"With nonlinear species, at least one species must be a H2O species.";
570 throw runtime_error(os.
str());
587 b = n_species + n_nls * (n_nls_pert - 1);
606 os <<
"The lookup table internal variable log_p_grid is not initialized.\n" 607 <<
"Use the abs_lookupAdapt method!";
608 throw runtime_error(os.
str());
617 if ((n_p_grid < p_interp_order + 1)) {
619 os <<
"The number of pressure grid points in the table (" << n_p_grid
620 <<
") is not enough for the desired order of interpolation (" 621 << p_interp_order <<
").";
622 throw runtime_error(os.
str());
625 if ((n_nls_pert != 0) && (n_nls_pert < h2o_interp_order + 1)) {
627 os <<
"The number of humidity perturbation grid points in the table (" 629 <<
") is not enough for the desired order of interpolation (" 630 << h2o_interp_order <<
").";
631 throw runtime_error(os.
str());
634 if ((n_t_pert != 0) && (n_t_pert < t_interp_order + 1)) {
636 os <<
"The number of temperature perturbation grid points in the table (" 637 << n_t_pert <<
") is not enough for the desired order of interpolation (" 638 << t_interp_order <<
").";
639 throw runtime_error(os.
str());
642 if ((n_f_grid < f_interp_order + 1)) {
644 os <<
"The number of frequency grid points in the table (" << n_f_grid
645 <<
") is not enough for the desired order of interpolation (" 646 << f_interp_order <<
").";
647 throw runtime_error(os.
str());
653 if (!
is_size(abs_vmrs, n_species)) {
655 os <<
"Number of species in lookup table does not match number\n" 656 <<
"of species for which you want to extract absorption.\n" 657 <<
"Have you used abs_lookupAdapt? Or did you miss to add\n" 658 <<
"some VRM fields (e.g. for free electrons or particles)?\n";
659 throw runtime_error(os.
str());
675 if (f_interp_order == 0) {
682 const Numeric allowed_f_margin = 0.09;
684 if (n_new_f_grid == n_f_grid) {
690 if (
abs(
f_grid[0] - new_f_grid[0]) > allowed_f_margin)
693 os <<
"First frequency in f_grid inconsistent with lookup table.\n" 694 <<
"f_grid[0] = " <<
f_grid[0] <<
"\n" 695 <<
"new_f_grid[0] = " << new_f_grid[0] <<
".";
696 throw runtime_error(os.
str());
700 if (
abs(
f_grid[n_f_grid - 1] - new_f_grid[n_new_f_grid - 1]) > allowed_f_margin)
703 os <<
"Last frequency in f_grid inconsistent with lookup table.\n" 704 <<
"f_grid[n_f_grid-1] = " <<
f_grid[n_f_grid - 1]
706 <<
"new_f_grid[n_new_f_grid-1] = " << new_f_grid[n_new_f_grid - 1]
708 throw runtime_error(os.
str());
710 }
else if (n_new_f_grid == 1) {
716 if (
abs(
f_grid[fgp_local[0].idx[0]] - new_f_grid[0]) > allowed_f_margin)
719 os <<
"Cannot find a matching lookup table frequency for frequency " 720 << new_f_grid[0] <<
".\n" 721 <<
"(This check has not been properly tested, so perhaps this is\n" 722 <<
"a false alarm. Check for this in file gas_abs_lookup.cc.)";
723 throw runtime_error(os.
str());
727 os <<
"With f_interp_order 0 the frequency grid has to have the same\n" 728 <<
"size as in the lookup table, or exactly one element.";
729 throw runtime_error(os.
str());
735 if (new_f_grid[0] < f_min) {
737 os <<
"Problem with gas absorption lookup table.\n" 738 <<
"At least one frequency is outside the range covered by the lookup table.\n" 739 <<
"Your new frequency value is " << new_f_grid[0] <<
" Hz.\n" 740 <<
"The allowed range is " << f_min <<
" to " << f_max <<
" Hz.";
741 throw runtime_error(os.
str());
743 if (new_f_grid[n_new_f_grid - 1] > f_max) {
745 os <<
"Problem with gas absorption lookup table.\n" 746 <<
"At least one frequency is outside the range covered by the lookup table.\n" 747 <<
"Your new frequency value is " << new_f_grid[n_new_f_grid - 1]
749 <<
"The allowed range is " << f_min <<
" to " << f_max <<
" Hz.";
750 throw runtime_error(os.
str());
755 fgp_local.resize(n_new_f_grid);
763 const Index do_T = n_t_pert;
767 for (
Index s = 0; s < n_nls; ++s) {
783 if ((p > p_max) || (p < p_min)) {
785 os <<
"Problem with gas absorption lookup table.\n" 786 <<
"Pressure p is outside the range covered by the lookup table.\n" 787 <<
"Your p value is " << p <<
" Pa.\n" 788 <<
"The allowed range is " << p_min <<
" to " << p_max <<
".\n" 789 <<
"The pressure grid range in the table is " <<
p_grid[n_p_grid - 1]
790 <<
" to " <<
p_grid[0] <<
".\n" 791 <<
"We allow a bit of extrapolation, but NOT SO MUCH!";
792 throw runtime_error(os.
str());
804 pitw.
resize(p_interp_order + 1);
812 gp_trivial[0].idx.resize(1);
813 gp_trivial[0].w.resize(1);
814 gp_trivial[0].idx[0] = 0;
815 gp_trivial[0].w[0] = 1;
822 Index this_t_interp_order;
824 this_t_interp_order = t_interp_order;
829 this_t_interp_order = 0;
857 xsec_pre_interpolated.
resize(
858 p_interp_order + 1, n_species, 1, 1, n_new_f_grid);
863 Tensor4 itw_withH2O, itw_noH2O, *itw;
865 for (
Index pi = 0; pi < p_interp_order + 1; ++pi) {
884 const Index this_p_grid_index = pgp[0].idx[pi];
916 const Numeric effective_T_ref =
t_ref[this_p_grid_index];
919 const Numeric T_offset = T - effective_T_ref;
928 extpolfac * (
t_pert[n_t_pert - 1] -
t_pert[n_t_pert - 2]);
929 if ((T_offset > t_max) || (T_offset < t_min)) {
931 os <<
"Problem with gas absorption lookup table.\n" 932 <<
"Temperature T is outside the range covered by the lookup table.\n" 933 <<
"Your temperature was " << T <<
" K at a pressure of " << p
935 <<
"The temperature offset value is " << T_offset <<
".\n" 936 <<
"The allowed range is " << t_min <<
" to " << t_max <<
".\n" 937 <<
"The temperature perturbation grid range in the table is " 939 <<
"We allow a bit of extrapolation, but NOT SO MUCH!";
940 throw runtime_error(os.
str());
970 const Numeric effective_vmr_ref =
vmrs_ref(h2o_index, this_p_grid_index);
973 const Numeric VMR_frac = abs_vmrs[h2o_index] / effective_vmr_ref;
984 if ((VMR_frac > x_max) || (VMR_frac < x_min)) {
986 os <<
"Problem with gas absorption lookup table.\n" 987 <<
"VMR for H2O (species " << h2o_index
988 <<
") is outside the range covered by the lookup table.\n" 989 <<
"Your VMR was " << abs_vmrs[h2o_index] <<
" at a pressure of " 991 <<
"The reference VMR value there is " << effective_vmr_ref <<
"\n" 992 <<
"The fractional VMR relative to the reference value is " 994 <<
"The allowed range is " << x_min <<
" to " << x_max <<
".\n" 995 <<
"The fractional VMR perturbation grid range in the table is " 997 <<
"We allow a bit of extrapolation, but NOT SO MUCH!";
998 throw runtime_error(os.
str());
1007 if (n_nls < n_species) {
1014 (this_t_interp_order + 1) * (1) *
1015 (f_interp_order + 1));
1024 (this_t_interp_order + 1) * (h2o_interp_order + 1) *
1025 (f_interp_order + 1));
1031 for (
Index si = 0; si < n_species; ++si) {
1034 const Index do_VMR = non_linear[si];
1049 os <<
"Problem with gas absorption lookup table.\n" 1050 <<
"VMR interpolation is not allowed for species \"" 1051 <<
species[si][0].Name() <<
"\"";
1052 throw runtime_error(os.
str());
1060 Index this_h2o_extent;
1063 this_h2o_extent = n_nls_pert;
1067 this_h2o_extent = 1;
1074 Range(fpi, this_h2o_extent),
1108 sga.
resize(n_species, n_new_f_grid);
1110 for (
Index pi = 0; pi < p_interp_order + 1; ++pi) {
1118 xsec_pre_interpolated(
1130 for (
Index si = 0; si < n_species; ++si)
1142 os <<
"GasAbsLookup: Output operator not implemented";
INDEX Index
The type to use for all integer numbers and indices.
void find_new_grid_in_old_grid(ArrayOfIndex &pos, ConstVectorView old_grid, ConstVectorView new_grid, const Verbosity &verbosity)
Find positions of new grid points in old grid.
Index nelem() const
Number of elements.
Vector nls_pert
The vector of perturbations for the VMRs of the nonlinear species.
void resize(Index s, Index b, Index p, Index r, Index c)
Resize function.
Vector t_pert
The vector of temperature perturbations [K].
Declarations having to do with the four output streams.
Numeric interp(ConstVectorView itw, ConstVectorView a, const GridPos &tc)
Red 1D Interpolate.
ostream & operator<<(ostream &os, const GasAbsLookup &)
Output operatior for GasAbsLookup.
Index npages() const
Returns the number of pages.
ArrayOfIndex nonlinear_species
The species tags with non-linear treatment.
Header file for interpolation.cc.
void Adapt(const ArrayOfArrayOfSpeciesTag ¤t_species, ConstVectorView current_f_grid, const Verbosity &verbosity)
Adapt lookup table to current calculation.
Vector log_p_grid
The natural log of the pressure grid.
Numeric number_density(const Numeric &p, const Numeric &t)
number_density
Index nelem() const
Returns the number of elements.
bool is_unique(const ArrayOfIndex &x)
Checks if an ArrayOfIndex is unique, i.e., has no duplicate values.
Tensor4 xsec
Absorption cross sections.
Matrix vmrs_ref
The reference VMR profiles.
Vector f_grid
The frequency grid [Hz].
_CS_string_type str() const
An absorption lookup table.
const Vector & GetFgrid() const
NUMERIC Numeric
The type to use for all floating point numbers.
Declarations for the gas absorption lookup table.
void gridpos_poly(ArrayOfGridPosPoly &gp, ConstVectorView old_grid, ConstVectorView new_grid, const Index order, const Numeric &extpolfac)
The maximum difference from 1 that we allow for a sum check.
Index species_index_from_species_name(String name)
Return species index for given species name.
Vector t_ref
The reference temperature profile [K].
Header file for logic.cc.
Vector p_grid
The pressure grid for the table [Pa].
This can be used to make arrays out of anything.
Header file for interpolation_poly.cc.
void Extract(Matrix &sga, const Index &p_interp_order, const Index &t_interp_order, const Index &h2o_interp_order, const Index &f_interp_order, const Numeric &p, const Numeric &T, ConstVectorView abs_vmrs, ConstVectorView new_f_grid, const Numeric &extpolfac) const
Extract scalar gas absorption coefficients from the lookup table.
void resize(Index n)
Resize function.
A constant view of a Tensor3.
A constant view of a Vector.
const Vector & GetPgrid() const
Index nbooks() const
Returns the number of books.
void transform(VectorView y, double(&my_func)(double), ConstVectorView x)
A generic transform function for vectors, which can be used to implement mathematical functions opera...
ArrayOfGridPosPoly fgp_default
Frequency grid positions.
Subclasses of runtime_error.
bool is_size(ConstVectorView x, const Index &n)
Verifies that the size of x is l.
Index ncols() const
Returns the number of columns.
void interpweights(VectorView itw, const GridPos &tc)
Red 1D interpolation weights.
ArrayOfArrayOfSpeciesTag species
The species tags for which the table is valid.
This file contains declerations of functions of physical character.
void resize(Index b, Index p, Index r, Index c)
Resize function.
void resize(Index r, Index c)
Resize function.