ARTS 2.5.11 (git: 725533f0)
m_xsec_fit.cc
Go to the documentation of this file.
1
10#include "arts.h"
11#include "global_data.h"
12#include "xsec_fit.h"
13#include "jacobian.h"
14#include "m_xml.h"
15#include "messages.h"
16#include "physics_funcs.h"
17
18/* Workspace method: Doxygen documentation will be auto-generated */
19void ReadXsecData(ArrayOfXsecRecord& xsec_fit_data,
20 const ArrayOfArrayOfSpeciesTag& abs_species,
21 const String& basename,
22 const Verbosity& verbosity) {
23 // Build a set of species indices. Duplicates are ignored.
24 std::set<Species::Species> unique_species;
25 for (auto& asp : abs_species) {
26 for (auto& sp : asp) {
27 if (sp.Type() == Species::TagType::XsecFit) {
28 unique_species.insert(sp.Spec());
29 }
30 }
31 }
32
33 String tmpbasename = basename;
34 if (basename.length() && basename[basename.length() - 1] != '/') {
35 tmpbasename += '.';
36 }
37
38 // Read xsec data for all active species and collect them in xsec_fit_data
39 xsec_fit_data.clear();
40 for (auto& species_name : unique_species) {
41 XsecRecord xsec_coeffs;
42 const String filename{tmpbasename +
43 String(Species::toShortName(species_name)) + ".xml"};
44
45 try {
46 ReadXML(xsec_coeffs, "", filename, "", verbosity);
47
48 xsec_fit_data.push_back(xsec_coeffs);
49 } catch (const std::exception& e) {
51 "Error reading coefficients file:\n", filename, "\n", e.what());
52 }
53 }
54}
55
56/* Workspace method: Doxygen documentation will be auto-generated */
57void propmat_clearskyAddXsecFit( // WS Output:
58 PropagationMatrix& propmat_clearsky,
59 ArrayOfPropagationMatrix& dpropmat_clearsky_dx,
60 // WS Input:
61 const ArrayOfArrayOfSpeciesTag& abs_species,
62 const ArrayOfSpeciesTag& select_abs_species,
63 const ArrayOfRetrievalQuantity& jacobian_quantities,
64 const Vector& f_grid,
65 const Numeric& rtp_pressure,
66 const Numeric& rtp_temperature,
67 const Vector& rtp_vmr,
68 const ArrayOfXsecRecord& xsec_fit_data,
69 const Numeric& force_p,
70 const Numeric& force_t,
71 // Verbosity object:
72 const Verbosity& verbosity) {
74
75 // Forward simulations and their error handling
76 ARTS_USER_ERROR_IF(rtp_vmr.nelem() not_eq abs_species.nelem(),
77 "Mismatch dimensions on species and VMR inputs");
79 propmat_clearsky.NumberOfFrequencies() not_eq f_grid.nelem(),
80 "Mismatch dimensions on internal matrices of xsec and frequency");
81
82 // Derivatives and their error handling
83 if (dpropmat_clearsky_dx.nelem()) {
85 dpropmat_clearsky_dx.nelem() not_eq jacobian_quantities.nelem(),
86 "Mismatch dimensions on xsec derivatives and Jacobian grids");
88 std::any_of(dpropmat_clearsky_dx.cbegin(),
89 dpropmat_clearsky_dx.cend(),
90 [&f_grid](auto& x) {
91 return x.NumberOfFrequencies() not_eq f_grid.nelem();
92 }),
93 "Mismatch dimensions on internal matrices of xsec derivatives and frequency");
94 }
95
96 // Jacobian overhead START
97 /* NOTE: The calculations below are inefficient and could
98 be made much better by using interp in Extract to
99 return the derivatives as well. */
100 // Jacobian vectors START
101 Vector dxsec_temp_dT;
102 Vector dxsec_temp_dF;
103 Vector dfreq;
104 // Jacobian vectors END
105 const bool do_jac = supports_hitran_xsec(jacobian_quantities);
106 const bool do_freq_jac = do_frequency_jacobian(jacobian_quantities);
107 const bool do_temp_jac = do_temperature_jacobian(jacobian_quantities);
108 const Numeric df = frequency_perturbation(jacobian_quantities);
109 const Numeric dt = temperature_perturbation(jacobian_quantities);
110 if (do_freq_jac) {
111 dfreq.resize(f_grid.nelem());
112 dfreq = f_grid;
113 dfreq += df;
114 dxsec_temp_dF.resize(f_grid.nelem());
115 }
116 if (do_temp_jac) {
117 dxsec_temp_dT.resize(f_grid.nelem());
118 }
119 // Jacobian overhead END
120
121 // Useful if there is no Jacobian to calculate
122 ArrayOfMatrix empty;
123
124 // Allocate a vector with dimension frequencies for constructing our
125 // cross-sections before adding them (more efficient to allocate this here
126 // outside of the loops)
127 Vector xsec_temp(f_grid.nelem(), 0.);
128
129 ArrayOfString fail_msg;
130 bool do_abort = false;
131 // Loop over Xsec data sets.
132 // Index ii loops through the outer array (different tag groups),
133 // index s through the inner array (different tags within each goup).
134 for (Index i = 0; i < abs_species.nelem(); i++) {
135 if (select_abs_species.nelem() and abs_species[i] not_eq select_abs_species)
136 continue;
137
138 for (Index s = 0; s < abs_species[i].nelem(); s++) {
139 const SpeciesTag& this_species = abs_species[i][s];
140
141 // Check if this is a HITRAN cross section tag
142 if (this_species.Type() != Species::TagType::XsecFit) continue;
143
144 Index this_xdata_index =
145 hitran_xsec_get_index(xsec_fit_data, this_species.Spec());
146 ARTS_USER_ERROR_IF(this_xdata_index < 0,
147 "Cross-section species ",
148 this_species.Name(),
149 " not found in *xsec_fit_data*.")
150 const XsecRecord& this_xdata = xsec_fit_data[this_xdata_index];
151 // ArrayOfMatrix& this_dxsec = do_jac ? dpropmat_clearsky_dx[i] : empty;
152
153 if (do_abort) continue;
154 const Numeric current_p = force_p < 0 ? rtp_pressure : force_p;
155 const Numeric current_t = force_t < 0 ? rtp_temperature : force_t;
156
157 // Get the absorption cross sections from the HITRAN data:
158 this_xdata.Extract(xsec_temp, f_grid, current_p, current_t, verbosity);
159 if (do_freq_jac) {
160 this_xdata.Extract(
161 dxsec_temp_dF, dfreq, current_p, current_t, verbosity);
162 }
163 if (do_temp_jac) {
164 this_xdata.Extract(
165 dxsec_temp_dT, f_grid, current_p, current_t + dt, verbosity);
166 }
167 }
168
169 // Add to result variable:
170 Numeric nd = number_density(rtp_pressure, rtp_temperature);
171 if (!do_jac) {
172 xsec_temp *= nd * rtp_vmr[i];
173 propmat_clearsky.Kjj() += xsec_temp;
174 } else {
175 Numeric dnd_dt = dnumber_density_dt(rtp_pressure, rtp_temperature);
176 for (Index f = 0; f < f_grid.nelem(); f++) {
177 propmat_clearsky.Kjj()[f] += xsec_temp[f] * nd * rtp_vmr[i];
178 for (Index iq = 0; iq < jacobian_quantities.nelem(); iq++) {
179 const auto& deriv = jacobian_quantities[iq];
180
181 if (!deriv.propmattype()) continue;
182
183 if (is_frequency_parameter(deriv)) {
184 dpropmat_clearsky_dx[iq].Kjj()[f] +=
185 (dxsec_temp_dF[f] - xsec_temp[f]) * nd * rtp_vmr[i] / df;
186 } else if (deriv == Jacobian::Special::ArrayOfSpeciesTagVMR ||
187 deriv == Jacobian::Line::VMR) {
188 if (species_match(deriv, abs_species[i])) {
189 dpropmat_clearsky_dx[iq].Kjj()[f] +=
190 xsec_temp[f] * nd * rtp_vmr[i];
191 }
192 } else if (deriv == Jacobian::Atm::Temperature) {
193 dpropmat_clearsky_dx[iq].Kjj()[f] +=
194 ((dxsec_temp_dT[f] - xsec_temp[f]) / dt * nd +
195 xsec_temp[f] * dnd_dt) *
196 rtp_vmr[i];
197 }
198 }
199 }
200 }
201 }
202}
203
204/* Workspace method: Doxygen documentation will be auto-generated */
206 ArrayOfMatrix& abs_xsec_per_species,
207 ArrayOfArrayOfMatrix& /* dabs_xsec_per_species_dx */,
208 // WS Input:
209 const ArrayOfArrayOfSpeciesTag& abs_species,
210 const ArrayOfRetrievalQuantity& /* jacobian_quantities */,
211 const ArrayOfIndex& abs_species_active,
212 const Vector& f_grid,
213 const Vector& abs_p,
214 const Vector& abs_t,
215 const ArrayOfXsecRecord& xsec_fit_data,
216 const Numeric& force_p,
217 const Numeric& force_t,
218 // Verbosity object:
219 const Verbosity& verbosity) {
221
222 {
223 // Check that all parameters that should have the number of tag
224 // groups as a dimension are consistent:
225 const Index n_tgs = abs_species.nelem();
226 const Index n_xsec = abs_xsec_per_species.nelem();
227
229 n_tgs != n_xsec,
230 "The following variables must all have the same dimension:\n"
231 "abs_species: ",
232 n_tgs,
233 "\n"
234 "abs_xsec_per_species: ",
235 n_xsec)
236 }
237
238 // Useful if there is no Jacobian to calculate
239 ArrayOfMatrix empty;
240
241 {
242 // Check that all parameters that should have the the dimension of p_grid
243 // are consistent:
244 const Index n_p = abs_p.nelem();
245 const Index n_t = abs_t.nelem();
246
248 n_p != n_t,
249 "The following variables must all have the same dimension:\n"
250 "abs_p: ",
251 n_p,
252 "\n"
253 "abs_t: ",
254 n_t)
255 }
256
257 // Allocate a vector with dimension frequencies for constructing our
258 // cross-sections before adding them (more efficient to allocate this here
259 // outside of the loops)
260 Vector xsec_temp(f_grid.nelem(), 0.);
261
262 ArrayOfString fail_msg;
263 bool do_abort = false;
264
265 // Loop over Xsec data sets.
266 // Index ii loops through the outer array (different tag groups),
267 // index s through the inner array (different tags within each goup).
268 for (Index ii = 0; ii < abs_species_active.nelem(); ii++) {
269 const Index i = abs_species_active[ii];
270
271 for (Index s = 0; s < abs_species[i].nelem(); s++) {
272 const SpeciesTag& this_species = abs_species[i][s];
273
274 // Check if this is a HITRAN cross section tag
275 if (this_species.Type() != Species::TagType::XsecFit) continue;
276
277 Index this_xdata_index =
278 hitran_xsec_get_index(xsec_fit_data, this_species.Spec());
279 ARTS_USER_ERROR_IF(this_xdata_index < 0,
280 "Cross-section species ",
281 this_species.Name(),
282 " not found in *xsec_fit_data*.")
283 const XsecRecord& this_xdata = xsec_fit_data[this_xdata_index];
284 Matrix& this_xsec = abs_xsec_per_species[i];
285
286 // Loop over pressure:
287#pragma omp parallel for if (!arts_omp_in_parallel() && abs_p.nelem() >= 1) \
288 firstprivate(xsec_temp)
289 for (Index ip = 0; ip < abs_p.nelem(); ip++) {
290 if (do_abort) continue;
291 const Numeric current_p = force_p < 0 ? abs_p[ip] : force_p;
292 const Numeric current_t = force_t < 0 ? abs_t[ip] : force_t;
293
294 // Get the absorption cross sections from the HITRAN data:
295 try {
296 this_xdata.Extract(xsec_temp,
297 f_grid,
298 current_p,
299 current_t,
300 verbosity);
301 } catch (runtime_error& e) {
302 ostringstream os;
303 os << "Problem with HITRAN cross section species "
304 << this_species.Name() << " at pressure level " << ip << " ("
305 << abs_p[ip] / 100. << " hPa):\n"
306 << e.what() << "\n";
307#pragma omp critical(abs_xsec_per_speciesAddXsecFit)
308 {
309 do_abort = true;
310 fail_msg.push_back(os.str());
311 }
312 }
313 this_xsec(joker, ip) += xsec_temp;
314 }
315 }
316 }
317
318 if (do_abort) {
319 ARTS_USER_ERROR(fail_msg);
320 }
321}
The global header file for ARTS.
This can be used to make arrays out of anything.
Definition array.h:31
Index nelem() const ARTS_NOEXCEPT
Definition array.h:75
Hitran crosssection class.
Definition xsec_fit.h:28
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
#define ARTS_USER_ERROR(...)
Definition debug.h:153
#define ARTS_USER_ERROR_IF(condition,...)
Definition debug.h:137
bool do_frequency_jacobian(const ArrayOfRetrievalQuantity &js) noexcept
Returns if the array wants a frequency derivative.
Definition jacobian.cc:1158
bool species_match(const RetrievalQuantity &rq, const ArrayOfSpeciesTag &ast)
Returns if the Retrieval quantity is VMR derivative for all the species in the species tags.
Definition jacobian.cc:1102
bool do_temperature_jacobian(const ArrayOfRetrievalQuantity &js) noexcept
Returns if the array wants the temperature derivative.
Definition jacobian.cc:1133
bool supports_hitran_xsec(const ArrayOfRetrievalQuantity &js)
Returns if the array supports HITRAN cross-section derivatives.
Definition jacobian.cc:1076
bool is_frequency_parameter(const RetrievalQuantity &t) noexcept
Returns if the Retrieval quantity is a frequency parameter in propagation matrix calculations.
Definition jacobian.cc:989
Numeric temperature_perturbation(const ArrayOfRetrievalQuantity &js) noexcept
Returns the temperature perturbation if it exists.
Definition jacobian.cc:1166
Numeric frequency_perturbation(const ArrayOfRetrievalQuantity &js) noexcept
Returns the frequency perturbation if it exists.
Definition jacobian.cc:1174
Routines for setting up the jacobian.
Workspace methods and template functions for supergeneric XML IO.
void ReadXML(T &v, const String &v_name, const String &f, const String &f_name, const Verbosity &verbosity)
WORKSPACE METHOD: ReadXML.
Definition m_xml.h:24
void abs_xsec_per_speciesAddXsecFit(ArrayOfMatrix &abs_xsec_per_species, ArrayOfArrayOfMatrix &, const ArrayOfArrayOfSpeciesTag &abs_species, const ArrayOfRetrievalQuantity &, const ArrayOfIndex &abs_species_active, const Vector &f_grid, const Vector &abs_p, const Vector &abs_t, const ArrayOfXsecRecord &xsec_fit_data, const Numeric &force_p, const Numeric &force_t, const Verbosity &verbosity)
void propmat_clearskyAddXsecFit(PropagationMatrix &propmat_clearsky, ArrayOfPropagationMatrix &dpropmat_clearsky_dx, const ArrayOfArrayOfSpeciesTag &abs_species, const ArrayOfSpeciesTag &select_abs_species, const ArrayOfRetrievalQuantity &jacobian_quantities, const Vector &f_grid, const Numeric &rtp_pressure, const Numeric &rtp_temperature, const Vector &rtp_vmr, const ArrayOfXsecRecord &xsec_fit_data, const Numeric &force_p, const Numeric &force_t, const Verbosity &verbosity)
WORKSPACE METHOD: propmat_clearskyAddXsecFit.
Definition m_xsec_fit.cc:57
void ReadXsecData(ArrayOfXsecRecord &xsec_fit_data, const ArrayOfArrayOfSpeciesTag &abs_species, const String &basename, const Verbosity &verbosity)
WORKSPACE METHOD: ReadXsecData.
Definition m_xsec_fit.cc:19
Declarations having to do with the four output streams.
#define CREATE_OUTS
Definition messages.h:191
my_basic_string< char > String
The String type for ARTS.
Definition mystring.h:199
This file contains declerations of functions of physical character.
constexpr Numeric dnumber_density_dt(Numeric p, Numeric t) noexcept
dnumber_density_dT
constexpr Numeric number_density(Numeric p, Numeric t) noexcept
number_density
Species::Tag SpeciesTag
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
Methods and classes for HITRAN absorption cross section data.