ARTS 2.5.11 (git: 725533f0)
xsec_fit.cc
Go to the documentation of this file.
1
9#include "xsec_fit.h"
10
11#include <algorithm>
12#include <memory>
13#include <numeric>
14
15#include "absorption.h"
16#include "arts.h"
17#include "check_input.h"
18#include "debug.h"
19#include "interpolation.h"
20#include "physics_funcs.h"
21
22
23void RemoveNegativeXsec(Vector& xsec) {
24 Numeric sum_xsec{};
25 Numeric sum_xsec_non_negative{};
26 for (auto& x : xsec) {
27 sum_xsec += x;
28 if (x < 0.) x = 0.;
29 sum_xsec_non_negative += x;
30 }
31
32 if (sum_xsec > 0. && sum_xsec != sum_xsec_non_negative) {
33 xsec *= sum_xsec / sum_xsec_non_negative;
34 }
35}
36
38 // The function species_name_from_species_index internally does an assertion
39 // that the species with this index really exists.
40 return Species::toShortName(mspecies);
41}
42
43void XsecRecord::SetVersion(const Index version) {
44 if (version != mversion) {
46 "Invalid version ", version, ", only version ", mversion, " supported")
47 }
48}
49
50void XsecRecord::Extract(VectorView result,
51 const Vector& f_grid,
52 const Numeric pressure,
53 const Numeric temperature,
54 const Verbosity& verbosity) const {
56
57 const Index nf = f_grid.nelem();
58
59 ARTS_ASSERT(result.nelem() == nf)
60
61 result = 0.;
62
63 const Index ndatasets = mfitcoeffs.nelem();
64 for (Index this_dataset_i = 0; this_dataset_i < ndatasets; this_dataset_i++) {
65 const Vector& data_f_grid = mfitcoeffs[this_dataset_i].get_numeric_grid(0);
66 const Numeric data_fmin = data_f_grid[0];
67 const Numeric data_fmax = data_f_grid[data_f_grid.nelem() - 1];
68
69 if (out3.sufficient_priority()) {
70 ostringstream os;
71 os << " f_grid: " << f_grid[0] << " - " << f_grid[nf - 1]
72 << " Hz\n"
73 << " data_f_grid: " << data_fmin << " - " << data_fmax << " Hz\n"
74 << " pressure: " << pressure << " K\n";
75 out3 << os.str();
76 }
77
78 // We want to return result zero for all f_grid points that are outside the
79 // data_f_grid, because xsec datasets are defined only where the absorption
80 // was measured. So, we have to find out which part of f_grid is inside
81 // data_f_grid.
82 const Numeric* f_grid_begin = f_grid.data_handle();
83 const Numeric* f_grid_end = f_grid_begin + f_grid.nelem();
84 const Index i_fstart = std::distance(
85 f_grid_begin, std::lower_bound(f_grid_begin, f_grid_end, data_fmin));
86 const Index i_fstop =
87 std::distance(
88 f_grid_begin,
89 std::upper_bound(f_grid_begin + i_fstart, f_grid_end, data_fmax)) -
90 1;
91
92 // Ignore band if all frequencies are below or above data_f_grid:
93 if (i_fstart == nf || i_fstop == -1) continue;
94
95 const Index f_extent = i_fstop - i_fstart + 1;
96
97 if (out3.sufficient_priority()) {
98 ostringstream os;
99 os << " " << f_extent << " frequency extraction points starting at "
100 << "frequency index " << i_fstart << ".\n";
101 out3 << os.str();
102 }
103
104 // If f_extent is less than one, then the entire data_f_grid is between two
105 // grid points of f_grid. (So that we do not have any f_grid points inside
106 // data_f_grid.) Return also in this case.
107 if (f_extent < 1) continue;
108
109 // This is the part of f_grid that lies inside the xsec band
110 const ConstVectorView f_grid_active = f_grid[Range(i_fstart, f_extent)];
111
112 // Determine the index of the first grid points in the xsec band that lie
113 // outside or on the boundary of the part of f_grid that lies inside the
114 // xsec band. We can ignore the remaining data.
115 const Numeric f_grid_fmin = f_grid[i_fstart];
116 const Numeric f_grid_fmax = f_grid[i_fstop];
117
118 const Numeric* data_f_grid_begin = data_f_grid.data_handle();
119 const Numeric* data_f_grid_end = data_f_grid_begin + data_f_grid.size() - 1;
120 const Index i_data_fstart =
121 std::distance(
122 data_f_grid_begin,
123 std::upper_bound(data_f_grid_begin, data_f_grid_end, f_grid_fmin)) -
124 1;
125 const Index i_data_fstop = std::distance(
126 data_f_grid_begin,
127 std::upper_bound(
128 data_f_grid_begin + i_data_fstart, data_f_grid_end, f_grid_fmax));
129
130 ARTS_ASSERT(i_data_fstart >= 0)
131 ARTS_ASSERT(f_grid[i_fstart] > data_f_grid[i_data_fstart])
132 ARTS_ASSERT(f_grid[i_fstart] < data_f_grid[i_data_fstart + 1])
133 ARTS_ASSERT(f_grid[i_fstop] < data_f_grid[i_data_fstop])
134 ARTS_ASSERT(f_grid[i_fstop] > data_f_grid[i_data_fstop - 1])
135
136 // Extent for active data frequency vector:
137 const Index data_f_extent = i_data_fstop - i_data_fstart + 1;
138
139 // This is the part of the xsec dataset for which we have to do the
140 // interpolation.
141 const Range active_range(i_data_fstart, data_f_extent);
142 const ConstVectorView data_f_grid_active = data_f_grid[active_range];
143
144 Vector fit_result(data_f_grid.nelem());
145 VectorView fit_result_active = fit_result[active_range];
146
147 // We have to create a matching view on the result vector:
148 VectorView result_active = result[Range(i_fstart, f_extent)];
149 Vector xsec_interp(f_extent);
150
151 CalcXsec(fit_result, this_dataset_i, pressure, temperature);
152
153 RemoveNegativeXsec(fit_result);
154
155 // Check if frequency is inside the range covered by the data:
156 chk_interpolation_grids("Frequency interpolation for cross sections",
157 data_f_grid,
158 f_grid_active);
159
160 {
161 // Find frequency grid positions:
162 ArrayOfGridPos f_gp(f_grid_active.nelem());
163 gridpos(f_gp, data_f_grid_active, f_grid_active);
164
165 Matrix itw(f_gp.nelem(), 2);
166 interpweights(itw, f_gp);
167 interp(xsec_interp, itw, fit_result_active, f_gp);
168 }
169
170 result_active += xsec_interp;
171 }
172}
173
174void XsecRecord::CalcXsec(VectorView xsec,
175 const Index dataset,
176 const Numeric pressure,
177 const Numeric temperature) const {
178 for (Index i = 0; i < xsec.nelem(); i++) {
179 const ConstVectorView coeffs = mfitcoeffs[dataset].data(i, joker);
180 xsec[i] = coeffs[P00] + coeffs[P10] * temperature + coeffs[P01] * pressure +
181 coeffs[P20] * temperature * temperature;
182 }
183}
184
185// void XsecRecord::CalcDT(VectorView xsec_dt,
186// const Index dataset,
187// const Numeric temperature) const {
188// for (Index i = 0; i < xsec_dt.nelem(); i++) {
189// const ConstVectorView coeffs = mfitcoeffs[dataset].data(i, joker);
190// xsec_dt[i] = coeffs[P10] + 2. * coeffs[P20] * temperature;
191// }
192// }
193
194// void XsecRecord::CalcDP(VectorView xsec_dp,
195// const Index dataset,
196// const Numeric pressure) const {
197// for (Index i = 0; i < xsec_dp.nelem(); i++) {
198// const ConstVectorView coeffs = mfitcoeffs[dataset].data(i, joker);
199// xsec_dp[i] = coeffs[P01] + 2. * coeffs[P02] * pressure;
200// }
201// }
202
211 const Species::Species species) {
212 for (Index i = 0; i < xsec_data.nelem(); i++)
213 if (xsec_data[i].Species() == species) return i;
214
215 return -1;
216}
217
225std::shared_ptr<XsecRecord> hitran_xsec_get_data(
226 const std::vector<std::shared_ptr<XsecRecord>>& xsec_data,
227 const Species::Species species) {
228 for (auto& xsec : xsec_data) {
229 if (xsec->Species() == species) return xsec;
230 }
231 return nullptr;
232}
233
234std::ostream& operator<<(std::ostream& os, const XsecRecord& xd) {
235 os << "Species: " << xd.Species() << std::endl;
236 return os;
237}
Declarations required for the calculation of absorption coefficients.
The global header file for ARTS.
void chk_interpolation_grids(const String &which_interpolation, ConstVectorView old_grid, ConstVectorView new_grid, const Index order, const Numeric &extpolfac, const bool islog)
Check interpolation grids.
Index nelem() const ARTS_NOEXCEPT
Definition array.h:75
Hitran crosssection class.
Definition xsec_fit.h:28
static constexpr Index mversion
Definition xsec_fit.h:127
Species::Species mspecies
Definition xsec_fit.h:128
static constexpr Index P20
Definition xsec_fit.h:125
ArrayOfGriddedField2 mfitcoeffs
Definition xsec_fit.h:134
static constexpr Index P00
Definition xsec_fit.h:122
String SpeciesName() const
Return species name.
Definition xsec_fit.cc:37
static constexpr Index P01
Definition xsec_fit.h:124
void SetVersion(Index version)
Set species name.
Definition xsec_fit.cc:43
static constexpr Index P10
Definition xsec_fit.h:123
void Extract(VectorView result, const Vector &f_grid, Numeric pressure, Numeric temperature, const Verbosity &verbosity) const
Calculate hitran cross section data.
Definition xsec_fit.cc:50
void CalcXsec(VectorView xsec, const Index dataset, const Numeric pressure, const Numeric temperature) const
Calculate crosssections.
Definition xsec_fit.cc:174
const Species::Species & Species() const
Return species index.
Definition xsec_fit.h:31
Helper macros for debugging.
#define ARTS_ASSERT(condition,...)
Definition debug.h:86
#define ARTS_USER_ERROR(...)
Definition debug.h:153
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.
#define CREATE_OUTS
Definition messages.h:191
This file contains declerations of functions of physical character.
std::ostream & operator<<(std::ostream &os, const XsecRecord &xd)
Definition xsec_fit.cc:234
Index hitran_xsec_get_index(const ArrayOfXsecRecord &xsec_data, const Species::Species species)
Get the index in xsec_fit_data for the given species.
Definition xsec_fit.cc:210
std::shared_ptr< XsecRecord > hitran_xsec_get_data(const std::vector< std::shared_ptr< XsecRecord > > &xsec_data, const Species::Species species)
Get the index in xsec_fit_data for the given species.
Definition xsec_fit.cc:225
void RemoveNegativeXsec(Vector &xsec)
Definition xsec_fit.cc:23
Methods and classes for HITRAN absorption cross section data.