43 assert(coeffs.
nelem() == 3);
44 return (
x <= coeffs[0]) ? coeffs[1] *
x
45 : coeffs[2] * (
x - coeffs[0]) + coeffs[1] * coeffs[0];
50 return gamma /
PI / (xx0 * xx0 + gamma * gamma);
67 for (
Index i = 0; i < n_xsec + n_lorentz - 1; ++i) {
69 for (
Index j = 0; j <= i; ++j) {
70 sum += ((j < n_xsec) && (i - j < n_lorentz)) ? xsec[j] * lorentz[i - j]
75 result =
temp[
Range(n_lorentz / 2, n_xsec, 1)];
83 int n_p = (int)(xsec.
nelem() + lorentz.
nelem() - 1);
84 int n_p_2 = n_p / 2 + 1;
86 double* xsec_in = fftw_alloc_real((
size_t)n_p);
87 fftw_complex* xsec_out = fftw_alloc_complex((
size_t)n_p_2);
89 memset(&xsec_in[xsec.
nelem()], 0,
sizeof(
double) * (n_p - xsec.
nelem()));
92 #pragma omp critical(fftw_call)
93 plan = fftw_plan_dft_r2c_1d(n_p, xsec_in, xsec_out, FFTW_ESTIMATE);
97 #pragma omp critical(fftw_call)
98 fftw_destroy_plan(plan);
102 double* lorentz_in = fftw_alloc_real((
size_t)n_p);
103 fftw_complex* lorentz_out = fftw_alloc_complex((
size_t)n_p_2);
104 memcpy(lorentz_in, lorentz.
get_c_array(),
sizeof(
double) * lorentz.
nelem());
105 memset(&lorentz_in[lorentz.
nelem()],
107 sizeof(
double) * (n_p - lorentz.
nelem()));
109 #pragma omp critical(fftw_call)
110 plan = fftw_plan_dft_r2c_1d(n_p, lorentz_in, lorentz_out, FFTW_ESTIMATE);
114 #pragma omp critical(fftw_call)
115 fftw_destroy_plan(plan);
117 fftw_free(lorentz_in);
119 fftw_complex* fft_in = fftw_alloc_complex((
size_t)n_p_2);
120 double* fft_out = fftw_alloc_real((
size_t)n_p);
121 memcpy(fft_in, xsec_out,
sizeof(fftw_complex) * n_p_2);
123 for (
Index i = 0; i < n_p_2; i++) {
125 xsec_out[i][0] * lorentz_out[i][0] - xsec_out[i][1] * lorentz_out[i][1];
127 xsec_out[i][0] * lorentz_out[i][1] + xsec_out[i][1] * lorentz_out[i][0];
130 #pragma omp critical(fftw_call)
131 plan = fftw_plan_dft_c2r_1d(n_p, fft_in, fft_out, FFTW_ESTIMATE);
135 #pragma omp critical(fftw_call)
136 fftw_destroy_plan(plan);
141 result[i] = fft_out[i + (int)lorentz.
nelem() / 2] / n_p;
145 fftw_free(lorentz_out);
155 const Index& apply_tfit,
162 assert(result.
nelem() == nf);
168 for (
Index this_dataset_i = 0; this_dataset_i < ndatasets; this_dataset_i++) {
170 const Numeric fmin = data_f_grid[0];
174 if (out3.sufficient_priority()) {
177 os <<
" f_grid: " <<
f_grid[0] <<
" - " <<
f_grid[nf - 1]
179 <<
" data_f_grid: " << fmin <<
" - " << fmax <<
" Hz\n"
180 <<
" pressure: " << pressure <<
" K\n";
188 Index i_fstart, i_fstop;
190 for (i_fstart = 0; i_fstart < nf; ++i_fstart)
191 if (
f_grid[i_fstart] >= fmin)
break;
194 if (i_fstart == nf)
continue;
196 for (i_fstop = nf - 1; i_fstop >= 0; --i_fstop)
197 if (
f_grid[i_fstop] <= fmax)
break;
200 if (i_fstop == -1)
continue;
203 const Index f_extent = i_fstop - i_fstart + 1;
205 if (out3.sufficient_priority()) {
207 os <<
" " << f_extent <<
" frequency extraction points starting at "
208 <<
"frequency index " << i_fstart <<
".\n";
215 if (f_extent < 3)
continue;
222 Index i_data_fstart, i_data_fstop;
224 for (i_data_fstart = 0; i_data_fstart < data_nf; ++i_data_fstart)
225 if (data_f_grid[i_data_fstart] >= fmin)
break;
227 for (i_data_fstop = data_nf - 1; i_data_fstop >= 0; --i_data_fstop)
228 if (data_f_grid[i_data_fstop] <= fmax)
break;
231 const Index data_f_extent = i_data_fstop - i_data_fstart + 1;
235 data_f_grid[
Range(i_data_fstart, data_f_extent)];
239 Range active_range(i_data_fstart, data_f_extent);
244 if (apply_tfit != 0 &&
mtslope[this_dataset_i].
nelem() > 1) {
245 xsec_active_tfit =
mtslope[this_dataset_i][active_range];
247 xsec_active_tfit +=
mtintersect[this_dataset_i][active_range];
248 xsec_active_tfit /= 10000;
249 xsec_active_tfit +=
mxsecs[this_dataset_i][active_range];
251 xsec_active = xsec_active_tfit;
255 Vector xsec_interp(f_extent);
258 const Index f_order = 3;
262 if (data_f_grid.
nelem() < f_order + 1) {
264 os <<
"Not enough frequency grid points in Hitran Xsec data.\n"
265 <<
"You have only " << data_f_grid.
nelem() <<
" grid points.\n"
266 <<
"But need at least " << f_order + 1 <<
".";
267 throw runtime_error(os.str());
280 Vector f_lorentz(data_f_extent);
282 for (
Index i = 0; i < data_f_extent; i++) {
285 data_f_grid[i_data_fstart + data_f_extent / 2 - 1],
287 lsum += f_lorentz[i];
315 gridpos_poly(f_gp, data_f_grid_active, f_grid_active, f_order);
317 Matrix itw(f_gp.nelem(), f_order + 1);
319 interp(xsec_interp, itw, data_result, f_gp);
324 gridpos_poly(f_gp, data_f_grid_active, f_grid_active, f_order);
326 Matrix itw(f_gp.nelem(), f_order + 1);
328 interp(xsec_interp, itw, xsec_active, f_gp);
331 result_active += xsec_interp;
343 const Index species) {
345 if (xsec_data[i].
Species() == species)
return i;
351 os <<
"Species: " << xd.
Species() << std::endl;