ARTS 2.5.11 (git: 725533f0)
predefined_absorption_models.cc
Go to the documentation of this file.
1
9
10#include <Faddeeva/Faddeeva.hh>
11#include <algorithm>
12#include <iomanip>
13#include <predef.h>
14
15#include "debug.h"
16#include "jacobian.h"
17#include "lin_alg.h"
18#include "linescaling.h"
19#include "matpack_data.h"
20#include "predefined/predef_data.h"
21#include "propagationmatrix.h"
22#include "quantum_numbers.h"
23#include "species.h"
24
42template <bool check_exist>
43bool compute_selection(PropagationMatrix& pm [[maybe_unused]],
44 const SpeciesIsotopeRecord& model,
45 const Vector& f [[maybe_unused]],
46 const Numeric& p [[maybe_unused]],
47 const Numeric& t [[maybe_unused]],
48 const VMRS& vmr [[maybe_unused]],
49 const PredefinedModelData& predefined_model_data
50 [[maybe_unused]]) {
51 switch (Species::find_species_index(model)) {
52 case find_species_index(Species::Species::Water, "ForeignContCKDMT400"):
53 if constexpr (not check_exist) MT_CKD400::compute_foreign_h2o(pm, f, p, t, vmr.H2O, predefined_model_data.get<MT_CKD400::WaterData>());
54 return true;
55 case find_species_index(Species::Species::Water, "SelfContCKDMT400"):
56 if constexpr (not check_exist) MT_CKD400::compute_self_h2o(pm, f, p, t, vmr.H2O, predefined_model_data.get<MT_CKD400::WaterData>());
57 return true;
58 case find_species_index(Species::Species::Oxygen, "MPM2020"):
59 if constexpr (not check_exist) MPM2020::compute(pm, f, p, t, vmr.O2);
60 return true;
61 case find_species_index(Species::Species::Oxygen, "PWR2021"):
62 if constexpr (not check_exist) PWR20xx::compute_o2_2021(pm, f, p, t, vmr.O2, vmr.H2O);
63 return true;
64 case find_species_index(Species::Species::Water, "PWR2021"):
65 if constexpr (not check_exist) PWR20xx::compute_h2o_2021(pm, f, p, t, vmr.H2O);
66 return true;
67 case find_species_index(Species::Species::Nitrogen, "SelfContPWR2021"):
68 if constexpr (not check_exist) PWR20xx::compute_n2(pm, f, p, t, vmr.N2, vmr.H2O);
69 return true;
70 case find_species_index(Species::Species::Oxygen, "PWR2022"):
71 if constexpr (not check_exist) PWR20xx::compute_o2_2022(pm, f, p, t, vmr.O2, vmr.H2O);
72 return true;
73 case find_species_index(Species::Species::Water, "PWR2022"):
74 if constexpr (not check_exist) PWR20xx::compute_h2o_2022(pm, f, p, t, vmr.H2O);
75 return true;
76 case find_species_index(Species::Species::Oxygen, "PWR98"):
77 if constexpr (not check_exist) PWR98::oxygen(pm, f, p, t, vmr.O2, vmr.H2O);
78 return true;
79 case find_species_index(Species::Species::Oxygen, "TRE05"):
80 if constexpr (not check_exist) TRE05::oxygen(pm, f, p, t, vmr.O2, vmr.H2O);
81 return true;
82 case find_species_index(Species::Species::Water, "PWR98"):
83 if constexpr (not check_exist) PWR98::water(pm, f, p, t, vmr.H2O);
84 return true;
85 case find_species_index(Species::Species::Oxygen, "MPM89"):
86 if constexpr (not check_exist) MPM89::oxygen(pm, f, p, t, vmr.O2, vmr.H2O);
87 return true;
88 case find_species_index(Species::Species::Water, "MPM89"):
89 if constexpr (not check_exist) MPM89::water(pm, f, p, t, vmr.H2O);
90 return true;
91 case find_species_index(Species::Species::Nitrogen, "SelfContMPM93"):
92 if constexpr (not check_exist) MPM93::nitrogen(pm, f, p, t, vmr.N2, vmr.H2O);
93 return true;
94 case find_species_index(Species::Species::Water, "ForeignContCKDMT350"):
95 if constexpr (not check_exist) CKDMT350::compute_foreign_h2o(pm, f, p, t, vmr.H2O);
96 return true;
97 case find_species_index(Species::Species::Water, "SelfContCKDMT350"):
98 if constexpr (not check_exist) CKDMT350::compute_self_h2o(pm, f, p, t, vmr.H2O);
99 return true;
100 case find_species_index(Species::Species::Water, "ForeignContCKDMT320"):
101 if constexpr (not check_exist) CKDMT320::compute_foreign_h2o(pm, f, p, t, vmr.H2O);
102 return true;
103 case find_species_index(Species::Species::Water, "SelfContCKDMT320"):
104 if constexpr (not check_exist) CKDMT320::compute_self_h2o(pm, f, p, t, vmr.H2O);
105 return true;
106 case find_species_index(Species::Species::Water, "ForeignContStandardType"):
107 if constexpr (not check_exist) Standard::water_foreign(pm, f, p, t, vmr.H2O);
108 return true;
109 case find_species_index(Species::Species::Water, "SelfContStandardType"):
110 if constexpr (not check_exist) Standard::water_self(pm, f, p, t, vmr.H2O);
111 return true;
112 case find_species_index(Species::Species::Oxygen, "SelfContStandardType"):
113 if constexpr (not check_exist) Standard::oxygen(pm, f, p, t, vmr.O2, vmr.H2O);
114 return true;
115 case find_species_index(Species::Species::Nitrogen, "SelfContStandardType"):
116 if constexpr (not check_exist) Standard::nitrogen(pm, f, p, t, vmr.N2);
117 return true;
118 case find_species_index(Species::Species::CarbonDioxide, "CKDMT252"):
119 if constexpr (not check_exist) MT_CKD252::carbon_dioxide(pm, f, p, t, vmr.CO2);
120 return true;
121 case find_species_index(Species::Species::Oxygen, "visCKDMT252"):
122 if constexpr (not check_exist) MT_CKD252::oxygen_vis(pm, f, p, t, vmr.O2);
123 return true;
124 case find_species_index(Species::Species::Nitrogen, "CIAfunCKDMT252"):
125 if constexpr (not check_exist) MT_CKD252::nitrogen_fun(pm, f, p, t, vmr.N2, vmr.H2O, vmr.O2);
126 return true;
127 case find_species_index(Species::Species::Nitrogen, "CIArotCKDMT252"):
128 if constexpr (not check_exist) MT_CKD252::nitrogen_rot(pm, f, p, t, vmr.N2, vmr.H2O, vmr.O2);
129 return true;
130 case find_species_index(Species::Species::Oxygen, "CIAfunCKDMT100"):
131 if constexpr (not check_exist) MT_CKD100::oxygen_cia(pm, f, p, t, vmr.O2);
132 return true;
133 case find_species_index(Species::Species::Oxygen, "v0v0CKDMT100"):
134 if constexpr (not check_exist) MT_CKD100::oxygen_v0v0(pm, f, p, t, vmr.O2, vmr.N2);
135 return true;
136 case find_species_index(Species::Species::Oxygen, "v1v0CKDMT100"):
137 if constexpr (not check_exist) MT_CKD100::oxygen_v0v1(pm, f, p, t, vmr.O2);
138 return true;
139 case find_species_index(Species::Species::liquidcloud, "ELL07"):
140 if constexpr (not check_exist) ELL07::compute(pm, f, t, vmr.LWC);
141 return true;
142 case find_species_index(Species::Species::FINAL, "Not A Model"): break;
143 }
144 return false;
145}
146
148 PropagationMatrix pm;
149 return compute_selection<true>(pm, model, {}, {}, {}, {}, {});
150}
151
158template <bool special>
159constexpr Numeric dvmr_calc(Numeric x) noexcept {
160 if constexpr (special) {
161 return x;
162 } else {
163 constexpr Numeric d = 1e-6;
164 constexpr Numeric l = d * 1e-4;
165 return x < l ? d : x * d;
166 }
167}
168
186template <bool special>
187bool compute_vmr_deriv(PropagationMatrix& dpm,
188 const PropagationMatrix& pm,
189 const SpeciesIsotopeRecord& model,
190 const Vector& f,
191 const Numeric& p,
192 const Numeric& t,
193 VMRS vmr,
194 const Species::Species spec,
195 const PredefinedModelData& predefined_model_data
196 [[maybe_unused]]) {
197 Numeric dvmr = 0;
198
199 switch (spec) {
200 case Species::Species::Oxygen:
201 dvmr = dvmr_calc<special>(vmr.O2);
202 if constexpr (not special) vmr.O2 += dvmr;
203 break;
204 case Species::Species::Water:
205 dvmr = dvmr_calc<special>(vmr.H2O);
206 if constexpr (not special) vmr.H2O += dvmr;
207 break;
208 case Species::Species::Nitrogen:
209 dvmr = dvmr_calc<special>(vmr.N2);
210 if constexpr (not special) vmr.N2 += dvmr;
211 break;
212 case Species::Species::CarbonDioxide:
213 dvmr = dvmr_calc<special>(vmr.CO2);
214 if constexpr (not special) vmr.CO2 += dvmr;
215 break;
216 case Species::Species::liquidcloud:
217 dvmr = dvmr_calc<special>(vmr.LWC);
218 if constexpr (not special) vmr.LWC += dvmr;
219 break;
220 default:
221 return false; // Escape mechanism when nothing should be done
222 }
223 static_assert(
224 sizeof(VMRS) / sizeof(Numeric) == 5,
225 "It seems you have changed VMRS. Please check that the derivatives are up-to-date above this assert");
226
227 if constexpr (not special) {
228 dpm.SetZero();
229 compute_selection<false>(dpm, model, f, p, t, vmr, predefined_model_data);
230 dpm -= pm;
231 dpm /= dvmr;
232 } else {
233 if (dvmr not_eq 0) {
234 dpm = pm;
235 dpm /= dvmr;
236 } else {
237 compute_vmr_deriv<false>(
238 dpm, pm, model, f, p, t, vmr, spec, predefined_model_data);
239 }
240 }
241 return true;
242}
243
244void compute(PropagationMatrix& propmat_clearsky,
245 ArrayOfPropagationMatrix& dpropmat_clearsky_dx,
246 const SpeciesIsotopeRecord& model,
247 const Vector& f_grid,
248 const Numeric& rtp_pressure,
249 const Numeric& rtp_temperature,
250 const VMRS& vmr,
251 const ArrayOfRetrievalQuantity& jacobian_quantities,
252 const PredefinedModelData& predefined_model_data) {
253 if (not compute_selection<true>(propmat_clearsky,
254 model,
255 f_grid,
256 rtp_pressure,
257 rtp_temperature,
258 vmr,
259 predefined_model_data))
260 return;
261
262 const bool do_freq_jac = do_frequency_jacobian(jacobian_quantities);
263 const bool do_temp_jac = do_temperature_jacobian(jacobian_quantities);
264 const bool do_vmrs_jac =
265 std::any_of(jacobian_quantities.begin(),
266 jacobian_quantities.end(),
267 [](auto& deriv) { return deriv == Jacobian::Line::VMR; }) or
268 std::any_of(jacobian_quantities.begin(),
269 jacobian_quantities.end(),
270 [model](auto& deriv) {
271 return deriv == Jacobian::Special::ArrayOfSpeciesTagVMR and
272 std::any_of(deriv.Target().species_array_id.begin(),
273 deriv.Target().species_array_id.end(),
274 [model](auto& tag) {
275 return tag.Isotopologue() == model;
276 });
277 });
278
279 if (do_freq_jac or do_temp_jac or do_vmrs_jac) {
281 PropagationMatrix pm(f_grid.nelem());
282 PropagationMatrix dpm(f_grid.nelem());
283 compute_selection<false>(pm,
284 model,
285 f_grid,
286 rtp_pressure,
287 rtp_temperature,
288 vmr,
289 predefined_model_data);
290
291 // Add absorption to the forward parameter
292 propmat_clearsky.Kjj() += pm.Kjj();
293
294 if (do_temp_jac) {
295 const Numeric d = temperature_perturbation(jacobian_quantities);
296 ARTS_ASSERT(d not_eq 0)
297
298 dpm.SetZero();
299 compute_selection<false>(dpm,
300 model,
301 f_grid,
302 rtp_pressure,
303 rtp_temperature + d,
304 vmr,
305 predefined_model_data);
306 dpm -= pm;
307 dpm /= d;
308 for (Index iq = 0; iq < dpropmat_clearsky_dx.nelem(); iq++) {
309 if (jacobian_quantities[iq] == Jacobian::Atm::Temperature) {
310 dpropmat_clearsky_dx[iq].Kjj() += dpm.Kjj();
311 }
312 }
313 }
314
315 if (do_freq_jac) {
316 const Numeric d = frequency_perturbation(jacobian_quantities);
317 ARTS_ASSERT(d not_eq 0)
318
319 Vector f_grid_d{f_grid};
320 f_grid_d += d;
321
322 dpm.SetZero();
323 compute_selection<false>(dpm,
324 model,
325 f_grid_d,
326 rtp_pressure,
327 rtp_temperature,
328 vmr,
329 predefined_model_data);
330 dpm -= pm;
331 dpm /= d;
332 for (Index iq = 0; iq < dpropmat_clearsky_dx.nelem(); iq++) {
333 if (is_frequency_parameter(jacobian_quantities[iq])) {
334 dpropmat_clearsky_dx[iq].Kjj() += dpm.Kjj();
335 }
336 }
337 }
338
339 for (Index iq = 0; iq < dpropmat_clearsky_dx.nelem(); iq++) {
340 auto& deriv = jacobian_quantities[iq];
341 if (deriv == Jacobian::Line::VMR) {
342 if (compute_vmr_deriv<false>(dpm,
343 pm,
344 model,
345 f_grid,
346 rtp_pressure,
347 rtp_temperature,
348 vmr,
349 deriv.QuantumIdentity().Species(),
350 predefined_model_data))
351 dpropmat_clearsky_dx[iq].Kjj() += dpm.Kjj();
352 } else if (deriv == Jacobian::Special::ArrayOfSpeciesTagVMR and
353 std::any_of(deriv.Target().species_array_id.begin(),
354 deriv.Target().species_array_id.end(),
355 [model](auto& tag) {
356 return tag.Isotopologue() == model;
357 })) {
358 if (compute_vmr_deriv<true>(
359 dpm,
360 pm,
361 model,
362 f_grid,
363 rtp_pressure,
364 rtp_temperature,
365 vmr,
366 deriv.Target().species_array_id.front().Spec(),
367 predefined_model_data))
368 dpropmat_clearsky_dx[iq].Kjj() += dpm.Kjj();
369 }
370 }
371 } else {
372 compute_selection<false>(propmat_clearsky,
373 model,
374 f_grid,
375 rtp_pressure,
376 rtp_temperature,
377 vmr,
378 predefined_model_data);
379 }
380}
381} // namespace Absorption::PredefinedModel
This can be used to make arrays out of anything.
Definition array.h:31
Helper macros for debugging.
#define ARTS_ASSERT(condition,...)
Definition debug.h:86
bool do_frequency_jacobian(const ArrayOfRetrievalQuantity &js) noexcept
Returns if the array wants a frequency derivative.
Definition jacobian.cc:1158
bool do_temperature_jacobian(const ArrayOfRetrievalQuantity &js) noexcept
Returns if the array wants the temperature derivative.
Definition jacobian.cc:1133
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.
Constains various line scaling functions.
bool compute_vmr_deriv(PropagationMatrix &dpm, const PropagationMatrix &pm, const SpeciesIsotopeRecord &model, const Vector &f, const Numeric &p, const Numeric &t, VMRS vmr, const Species::Species spec, const PredefinedModelData &predefined_model_data)
Compute the partial VMR derivative.
bool compute_selection(PropagationMatrix &pm, const SpeciesIsotopeRecord &model, const Vector &f, const Numeric &p, const Numeric &t, const VMRS &vmr, const PredefinedModelData &predefined_model_data)
Compute the selected model and returns if it can be computed.
constexpr Numeric dvmr_calc(Numeric x) noexcept
Sets a VMR perturbation.
bool can_compute(const SpeciesIsotopeRecord &model)
Returns true if the model can be computed.
void compute(PropagationMatrix &propmat_clearsky, ArrayOfPropagationMatrix &dpropmat_clearsky_dx, const SpeciesIsotopeRecord &model, const Vector &f_grid, const Numeric &rtp_pressure, const Numeric &rtp_temperature, const VMRS &vmr, const ArrayOfRetrievalQuantity &jacobian_quantities, const PredefinedModelData &predefined_model_data)
Compute the predefined model.
constexpr Index find_species_index(const Species spec, const std::string_view isot) noexcept
invlib::Vector< ArtsVector > Vector
invlib wrapper type for ARTS vectors.
Definition oem.h:31
Contains known required VMR values.
Struct containing all information needed about one isotope.
#define d