ARTS  2.3.1285(git:92a29ea9-dirty)
partial_derivatives.cc
Go to the documentation of this file.
1 /* Copyright (C) 2015
2  Richard Larsson <ric.larsson@gmail.com>
3 
4  This program is free software; you can redistribute it and/or modify it
5  under the terms of the GNU General Public License as published by the
6  Free Software Foundation; either version 2, or (at your option) any
7  later version.
8 
9  This program is distributed in the hope that it will be useful,
10  but WITHOUT ANY WARRANTY; without even the implied warranty of
11  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  GNU General Public License for more details.
13 
14  You should have received a copy of the GNU General Public License
15  along with this program; if not, write to the Free Software
16  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
17  USA. */
18 
27 #include "partial_derivatives.h"
28 #include "absorption.h"
29 #include "arts.h"
30 #include "global_data.h"
31 #include "linescaling.h"
32 #include "quantum.h"
33 
34 extern const String PROPMAT_SUBSUBTAG;
35 
36 /* Helper function.
37  *
38  * Function to calculate the partial deivative in a standardized manner.
39  * We allow the partial derivative to propagate in three ways:
40  *
41  * 1) The derivation of the line shape and the chain rule.
42  * This is the most theoretical method and is from direct derivations.
43  * A perfect example of this is the frequency derivations for wind calculations,
44  * where it is straightforward to calculate the derivative from the lineshape.
45  *
46  * Input parameters:
47  *
48  * 2) As a ratio on the output cross-section of the line.
49  * Some derivations are not necessary to perform because they only result in
50  * very simple ratios. For instance, the derivation of Doppler broadening w.r.t.
51  * temperature is simple one over the temperature. It is therefore convenient to
52  * use this property rather than to perform the long derivation of the line shape.
53  *
54  * 3) As a ratio on the phase or attenuation of unmixed lines.
55  * This is necessary for line mixing.
56  */
57 inline void calc_derivative(Numeric& dxsec_dtarget,
58  Numeric& dphase_dtarget,
59  Numeric& dsrc_dtarget,
60  const Numeric& dFA_dx,
61  const Numeric& dFB_dx,
62  const Numeric& dFA_dy,
63  const Numeric& dFB_dy,
64  const Numeric& dx_dtarget,
65  const Numeric& dy_dtarget,
66  const Numeric& FA,
67  const Numeric& FB,
68  const Numeric& FA_ratio_to_dtarget,
69  const Numeric& FB_ratio_to_dtarget,
70  const Numeric& lma,
71  const Numeric& lmb,
72  const Numeric& lma_real_ratio_to_dtarget,
73  const Numeric& lma_imag_ratio_to_dtarget,
74  const Numeric& lmb_real_ratio_to_dtarget,
75  const Numeric& lmb_imag_ratio_to_dtarget,
76  const Numeric& nlte,
77  const Numeric& dnlte_dtarget,
78  const bool do_phase,
79  const bool do_src) {
80  if (do_src) {
81  const Numeric dtarget =
82  dFA_dx *
83  dx_dtarget + // Lineshape attenuation derivative with frequency term
84  dFA_dy *
85  dy_dtarget + // Lineshape attenuation derivative with pressure term
86  FA * FA_ratio_to_dtarget + // When derivation is just a ratio away
87  lma *
88  lma_real_ratio_to_dtarget + // line mixing attenuation contribution
89  lmb * lmb_real_ratio_to_dtarget; // line mixing phase contribution
90  dxsec_dtarget += dtarget;
91  dsrc_dtarget += dtarget * nlte + FA * dnlte_dtarget;
92  } else
93  dxsec_dtarget +=
94  dFA_dx *
95  dx_dtarget + // Lineshape attenuation derivative with frequency term
96  dFA_dy *
97  dy_dtarget + // Lineshape attenuation derivative with pressure term
98  FA * FA_ratio_to_dtarget + // When derivation is just a ratio away
99  lma *
100  lma_real_ratio_to_dtarget + // line mixing attenuation contribution
101  lmb * lmb_real_ratio_to_dtarget; // line mixing phase contribution
102 
103  if (do_phase)
104  dphase_dtarget +=
105  dFB_dx * dx_dtarget + // Lineshape phase derivative with frequency term
106  dFB_dy * dy_dtarget + // Lineshape phase derivative with pressure term
107  FB * FB_ratio_to_dtarget + // When derivation is just a ratio away
108  lma *
109  lma_imag_ratio_to_dtarget + // line mixing attenuation contribution
110  lmb * lmb_imag_ratio_to_dtarget; // line mixing phase contribution
111 }
112 
113 //This function will require much more inputs in the future
115  ArrayOfMatrix& partials_attenuation,
116  ArrayOfMatrix& partials_phase,
117  ArrayOfMatrix& partials_src,
118  const ArrayOfRetrievalQuantity& flag_partials,
119  const ArrayOfIndex& flag_partials_position,
120  ConstVectorView CF_A, //no linemixing except DV!
121  ConstVectorView CF_B, //no linemixing except DV!
122  ConstVectorView C,
123  ConstVectorView dFa_dx,
124  ConstVectorView dFb_dx,
125  ConstVectorView dFa_dy,
126  ConstVectorView dFb_dy,
127  ConstVectorView f_grid,
128  const Range& this_f_grid,
129  const Numeric& temperature,
130  const Numeric& sigma,
131  const Numeric& K2,
132  const Numeric& dK2_dT,
133  const Numeric& K3,
134  const Numeric& dK3_dT,
135  const Numeric& K4,
136  // Line parameters
137  const Numeric& line_frequency,
138  const Numeric& line_strength,
139  const Numeric& line_temperature,
140  const Numeric& line_E_low,
141  const Numeric& line_E_v_low,
142  const Numeric& line_E_v_upp,
143  const Numeric& line_T_v_low,
144  const Numeric& line_T_v_upp,
145  const Numeric& Y_LM,
146  const Numeric& dY_LM_dT,
147  const Numeric& G_LM,
148  const Numeric& dG_LM_dT,
149  const Numeric& DF_LM,
150  const Numeric& dDF_LM_dT,
151  const QuantumIdentifier& qi,
152  // LINE SHAPE
153  const Index& ind_ls,
154  const Index& ind_lsn,
155  const Numeric& df_0,
156  const Numeric& ddf_dT,
157  const Numeric& gamma,
158  const Numeric& dgamma_dT,
159  // Partition data parameters
160  const Numeric& dQ_dT,
161  // Magnetic variables
162  const Numeric& DF_Zeeman,
163  const Numeric& H_mag_Zeeman,
164  const bool do_zeeman,
165  // Programming variables
166  const Index& pressure_level_index,
167  const bool do_partials_phase,
168  const bool do_src) {
169  extern const Numeric PLANCK_CONST;
170  extern const Numeric BOLTZMAN_CONST;
171 
172  if (this_f_grid.get_extent() == 0) return;
173 
174  ConstVectorView this_f = f_grid[this_f_grid];
175  const Index nv = this_f.nelem();
176  const Numeric nlte = do_src ? K4 / K3 - 1.0 : 0.0;
177  const Numeric f0 = line_frequency + df_0 + DF_LM + DF_Zeeman * H_mag_Zeeman;
178 
179  Vector LM_Fa(nv), LM_Fb(nv), empty_vector(nv);
180  for (Index iv = 0; iv < nv; iv++) {
181  LM_Fa[iv] = ((1.0 + G_LM) * CF_A[iv] + Y_LM * CF_B[iv]);
182  if (do_partials_phase)
183  LM_Fb[iv] = ((1.0 + G_LM) * CF_B[iv] - Y_LM * CF_A[iv]);
184  }
185 
186  // Loop over all jacobian_quantities, if a matching quantity is found, then apply the necessary steps to make the jacobian matrix
187  for (Index ii = 0; ii < flag_partials_position.nelem(); ii++) {
188  if ((flag_partials[flag_partials_position[ii]] ==
190  if (!do_zeeman) continue;
191 
192  VectorView this_partial_attenuation =
193  partials_attenuation[ii](this_f_grid, pressure_level_index);
194  VectorView this_partial_phase =
195  partials_phase[ii](this_f_grid, pressure_level_index);
196  VectorView this_partial_src =
197  do_src ? partials_src[ii](this_f_grid, pressure_level_index)
198  : empty_vector;
199 
200  const Numeric& dF_dH = DF_Zeeman;
201 
202  Numeric dx_dH;
203  Vector dfn_dH_div_dF_dH(nv);
204 
205  // Calculate the line shape derivative:
206  global_data::lineshape_data[ind_ls].dInput_dH()(dx_dH, sigma, dF_dH);
207  global_data::lineshape_norm_data[ind_lsn].dFunction_dF0()(
208  dfn_dH_div_dF_dH, f0, this_f, temperature);
209  for (Index iv = 0; iv < nv; iv++) {
210  const Numeric ls_A = ((1.0 + G_LM) * CF_A[iv] + Y_LM * CF_B[iv]),
211  ls_B = ((1.0 + G_LM) * CF_B[iv] - Y_LM * CF_A[iv]);
212 
213  this_partial_attenuation[iv] +=
214  dFa_dx[iv] * dx_dH + ls_A * dfn_dH_div_dF_dH[iv] * dF_dH / C[iv];
215  this_partial_phase[iv] +=
216  dFb_dx[iv] * dx_dH + ls_B * dfn_dH_div_dF_dH[iv] * dF_dH / C[iv];
217  if (do_src)
218  this_partial_src[iv] +=
219  (dFa_dx[iv] * dx_dH +
220  ls_A * dfn_dH_div_dF_dH[iv] * dF_dH / C[iv]) *
221  nlte;
222  }
223  } else if (
224  flag_partials[flag_partials_position[ii]] ==
226  flag_partials[flag_partials_position[ii]] ==
228  flag_partials[flag_partials_position[ii]] ==
230  MagneticW) { /* Pass on these. These are done by perturbation in later parts of the code execution since I found it too complicated for now. FIXME: Richard */
231  } else if (is_frequency_parameter(
232  flag_partials[flag_partials_position[ii]])) {
233  VectorView this_partial_attenuation =
234  partials_attenuation[ii](this_f_grid, pressure_level_index);
235  VectorView this_partial_phase =
236  do_partials_phase
237  ? partials_phase[ii](this_f_grid, pressure_level_index)
238  : empty_vector;
239  VectorView this_partial_src =
240  do_src ? partials_src[ii](this_f_grid, pressure_level_index)
241  : empty_vector;
242 
243  Numeric dF_dF;
244  Vector dfn_dF(nv);
245 
246  // Calculate the line shape derivative:
247  global_data::lineshape_data[ind_ls].dInput_dF()(dF_dF, sigma);
248  global_data::lineshape_norm_data[ind_lsn].dFunction_dF()(
249  dfn_dF, f0, this_f, temperature);
250 
251  for (Index iv = 0; iv < nv; iv++) {
252  const Numeric ls_A = ((1.0 + G_LM) * CF_A[iv] + Y_LM * CF_B[iv]),
253  ls_B = ((1.0 + G_LM) * CF_B[iv] - Y_LM * CF_A[iv]);
254 
255  this_partial_attenuation[iv] +=
256  dfn_dF[iv] / C[iv] * ls_A + dFa_dx[iv] * dF_dF;
257  if (do_partials_phase)
258  this_partial_phase[iv] +=
259  dfn_dF[iv] / C[iv] * ls_B + dFb_dx[iv] * dF_dF;
260  if (do_src)
261  this_partial_src[iv] +=
262  (dfn_dF[iv] / C[iv] * ls_A + dFa_dx[iv] * dF_dF) * nlte;
263 
264  //NOTE: Still missing wind term in this derivative. Must be multiplied by cf/(c+W)^2 at some point to get this correct... As it stands though, this is the frequency derivative
265  //NOTE: Another missing aspect is that the dW/d{u,v,w} term must also be added for those components
266  }
267  } else if (flag_partials[flag_partials_position[ii]] ==
269  VectorView this_partial_attenuation =
270  partials_attenuation[ii](this_f_grid, pressure_level_index);
271  VectorView this_partial_phase =
272  do_partials_phase
273  ? partials_phase[ii](this_f_grid, pressure_level_index)
274  : empty_vector;
275  VectorView this_partial_src =
276  do_src ? partials_src[ii](this_f_grid, pressure_level_index)
277  : empty_vector;
278 
279  const Numeric kT2 = BOLTZMAN_CONST * temperature * temperature;
280 
281  // Line strength partials... NOTE: All but dK4 are divided by original values to fit ls_A/B
282  const Numeric dK1 = line_E_low / kT2;
283  const Numeric dK2 = dK2_dT / K2;
284  const Numeric dK3 = do_src ? (dK3_dT / K3) : 0.0;
285  const Numeric dK4 = line_E_v_upp >= 0 ? -K4 * line_E_v_upp / kT2 : 0.0;
286  const Numeric dS_dT =
287  dK1 + dK2 + dQ_dT + dK3; // Note that missing dn/dT is handled later
288 
289  // Derivative of sigma with regards to temperature
290  const Numeric dsigma_dT = 0.5 * sigma / temperature;
291 
292  // Setting up for the partials of the inner loop
293  Numeric dP_dT, dFu_dT;
294  Vector dfn_dT(nv), dF_dT(nv);
295 
296  // Calculate the line shape derivative:
297  global_data::lineshape_data[ind_ls].dInput_dT()(dF_dT,
298  dP_dT,
299  dFu_dT,
300  this_f,
301  f0,
302  sigma,
303  ddf_dT,
304  dDF_LM_dT,
305  dsigma_dT,
306  gamma,
307  dgamma_dT);
308  global_data::lineshape_norm_data[ind_lsn].dFunction_dT()(
309  dfn_dT, f0, this_f, temperature);
310 
311  for (Index iv = 0; iv < nv; iv++) {
312  const Numeric ls_A = ((1.0 + G_LM) * CF_A[iv] + Y_LM * CF_B[iv]),
313  ls_B = ((1.0 + G_LM) * CF_B[iv] - Y_LM * CF_A[iv]);
314 
315  this_partial_attenuation[iv] +=
316  (dS_dT + dfn_dT[iv] / C[iv] + dFu_dT) *
317  ls_A + //Line strength and factors
318  dG_LM_dT * CF_A[iv] +
319  dY_LM_dT * CF_B[iv] + //Line Mixing (absolute)
320  dF_dT[iv] * dFa_dx[iv] + //Frequency line shape
321  dP_dT * dFa_dy[iv]; //Pressure line shape
322 
323  if (do_partials_phase) // Minus signs should be here due to iFb, though this must be tested!
324  this_partial_phase[iv] +=
325  (dS_dT + dfn_dT[iv] / C[iv] + dFu_dT) * ls_B + //Line strength
326  dG_LM_dT * CF_B[iv] -
327  dY_LM_dT * CF_A[iv] + //Line Mixing (absolute)
328  dF_dT[iv] * dFb_dx[iv] + //Frequency line shape
329  dP_dT * dFb_dy[iv]; //Pressure line shape
330 
331  if (do_src)
332  this_partial_src[iv] +=
333  nlte * /*partial attenuation*/
334  ((dS_dT + dfn_dT[iv] / C[iv] + dFu_dT) *
335  ls_A + //Line strength
336  dG_LM_dT * CF_A[iv] +
337  dY_LM_dT * CF_B[iv] + //Line Mixing (absolute)
338  dF_dT[iv] * dFa_dx[iv] + //Frequency line shape
339  dP_dT * dFa_dy[iv]) + //Pressure line shape
340  ls_A / K3 * (dK4 - K4 * dK3); //Source term ratio
341  }
342 
343  // Ready and done! So complicated that I need plenty of testing!
344 
345  } else if (flag_partials[flag_partials_position[ii]] ==
347  // Line shape cross section does not depend on VMR. NOTE: Ignoring self-pressure broadening.
348  } else if (flag_partials[flag_partials_position[ii]] ==
350  if (!line_match_line(
351  flag_partials[flag_partials_position[ii]].QuantumIdentity(),
352  qi.Species(),
353  qi.Isotopologue(),
354  qi.LowerQuantumNumbers(),
355  qi.UpperQuantumNumbers()))
356  continue;
357 
358  VectorView this_partial_attenuation =
359  partials_attenuation[ii](this_f_grid, pressure_level_index);
360  VectorView this_partial_phase =
361  do_partials_phase
362  ? partials_phase[ii](this_f_grid, pressure_level_index)
363  : empty_vector;
364  VectorView this_partial_src =
365  do_src ? partials_src[ii](this_f_grid, pressure_level_index)
366  : empty_vector;
367 
368  Numeric dK2_dF0, dK3_dF0 = 0.0;
369  GetLineScalingData_dF0(dK2_dF0,
370  dK3_dF0,
371  temperature,
372  line_temperature,
373  line_T_v_low,
374  line_T_v_upp,
375  line_E_v_low,
376  line_E_v_upp,
377  line_frequency);
378  dK2_dF0 /= K2; // to just multiply with ls_{A,B}
379  if (do_src) dK3_dF0 /= K3;
380  const Numeric dS_dF0 = dK2_dF0 + dK3_dF0;
381 
382  Numeric dF_dF0;
383  global_data::lineshape_data[ind_ls].dInput_dF0()(dF_dF0, sigma);
384 
385  Vector dfn_dF0(nv);
386  global_data::lineshape_norm_data[ind_lsn].dFunction_dF0()(
387  dfn_dF0, f0, this_f, temperature);
388 
389  const Numeric dx_dF0_part = dF_dF0 / f0, dy_dF0 = gamma * dF_dF0 / f0;
390 
391  for (Index iv = 0; iv < nv; iv++) {
392  const Numeric ratio = (dS_dF0 + dfn_dF0[iv] / C[iv] - 1.0 / f0);
393  calc_derivative(this_partial_attenuation[iv],
394  this_partial_phase[iv],
395  this_partial_src[iv],
396  dFa_dx[iv],
397  dFb_dx[iv],
398  dFa_dy[iv],
399  dFb_dy[iv],
400  dx_dF0_part * this_f[iv],
401  dy_dF0, // dx_dtarget, dy_target
402  LM_Fa[iv],
403  LM_Fb[iv], // Full calculations
404  ratio,
405  ratio, // ratios
406  CF_A[iv],
407  CF_B[iv],
408  0.0,
409  0.0,
410  0.0,
411  0.0, // When attenuation and phase matters
412  nlte,
413  0.0,
414  do_partials_phase,
415  do_src);
416  }
417 
418  // That's it! Note that the output should be strongly correlated to Temperature and Pressure.
419  // Also note that to do the fit for the catalog gamma is somewhat different than this
420  } else if (flag_partials[flag_partials_position[ii]] ==
422  if (!line_match_line(
423  flag_partials[flag_partials_position[ii]].QuantumIdentity(),
424  qi.Species(),
425  qi.Isotopologue(),
426  qi.LowerQuantumNumbers(),
427  qi.UpperQuantumNumbers()))
428  continue;
429 
430  VectorView this_partial_attenuation =
431  partials_attenuation[ii](this_f_grid, pressure_level_index);
432  VectorView this_partial_phase =
433  do_partials_phase
434  ? partials_phase[ii](this_f_grid, pressure_level_index)
435  : empty_vector;
436  VectorView this_partial_src =
437  do_src ? partials_src[ii](this_f_grid, pressure_level_index)
438  : empty_vector;
439 
440  const Numeric ratio = 1.0 / line_strength;
441 
442  for (Index iv = 0; iv < nv; iv++) {
443  calc_derivative(this_partial_attenuation[iv],
444  this_partial_phase[iv],
445  this_partial_src[iv],
446  dFa_dx[iv],
447  dFb_dx[iv],
448  dFa_dy[iv],
449  dFb_dy[iv],
450  0.0,
451  0.0, // dx_dtarget, dy_target
452  LM_Fa[iv],
453  LM_Fb[iv], // Full calculations
454  ratio,
455  ratio, // ratios
456  CF_A[iv],
457  CF_B[iv],
458  0.0,
459  0.0,
460  0.0,
461  0.0, // When attenuation and phase matters
462  nlte,
463  0.0,
464  do_partials_phase,
465  do_src);
466  }
467 
468  // That's it! Now to wonder if this will grow extremely large, creating an unrealistic jacobian...
469  } else if (flag_partials[flag_partials_position[ii]] ==
471  /*
472  * WARNING: This part will be in accordance with simplified formalism used in the transfer code
473  * so that d/dTnlte[exp(f(Tnlte))/Q(T)], where Q(T) is independent of Tnlte. In practice, Q(T)
474  * will be Q(T)-exp(f(T))+exp(f(Tnlte)), and so there should be an additional term involved
475  * in the calculation of this partial derivative. However, as this is not required in the simplified
476  * formalism we presently include in ARTS, this is also not accounted for below. I am not sure what
477  * this implies for usability of these partial derivatives.
478  */
479 
480  bool lower, upper;
482  lower,
483  upper,
484  flag_partials[flag_partials_position[ii]].QuantumIdentity(),
485  qi.Species(),
486  qi.Isotopologue(),
487  qi.LowerQuantumNumbers(),
488  qi.UpperQuantumNumbers());
489  if (!(lower || upper)) continue;
490 
491  VectorView this_partial_attenuation =
492  partials_attenuation[ii](this_f_grid, pressure_level_index);
493  VectorView this_partial_phase =
494  do_partials_phase
495  ? partials_phase[ii](this_f_grid, pressure_level_index)
496  : empty_vector;
497  VectorView this_partial_src =
498  do_src ? partials_src[ii](this_f_grid, pressure_level_index)
499  : empty_vector;
500 
501  const Numeric Gamma =
502  exp(-PLANCK_CONST * line_frequency / BOLTZMAN_CONST / temperature);
503 
504  Numeric dK4_dTu = 0., dK3_dTu = 0., dK3_dTl = 0.;
505 
506  if (upper) {
507  dK4_dTu = K4 * line_E_v_upp / line_T_v_upp / line_T_v_upp;
508  dK3_dTu = -K4 * line_E_v_upp / line_T_v_upp / line_T_v_upp /
509  BOLTZMAN_CONST * Gamma / (Gamma - 1.0);
510  }
511 
512  if (lower) {
513  dK3_dTl = -K4 * line_E_v_low / line_T_v_low / line_T_v_low /
514  BOLTZMAN_CONST * Gamma / (Gamma - 1.0);
515  //dK4_dTl = 0.0;
516  }
517 
518  const Numeric dK_dTl =
519  nlte * dK3_dTl /
520  K3; // div K3 since there is a K3 in ls_A later that should not be there...
521  const Numeric dK_dTu = nlte * dK3_dTu / K3;
522 
523  const Numeric dsourceC_dTl = -dK3_dTl / K3; // Simplifying some terms
524  const Numeric dsourceC_dTu = (dK4_dTu - dK3_dTu) / K3;
525 
526  for (Index iv = 0; iv < nv; iv++) {
527  const Numeric ls_A = ((1.0 + G_LM) * CF_A[iv] + Y_LM * CF_B[iv]),
528  ls_B = ((1.0 + G_LM) * CF_B[iv] - Y_LM * CF_A[iv]);
529 
530  this_partial_src[iv] +=
531  (dsourceC_dTl + dsourceC_dTu) * ls_A; //Note that this works since
532  this_partial_attenuation[iv] +=
533  (dK_dTl + dK_dTu) * ls_A; //Tu and Tl are independently
534  if (do_partials_phase) //changing absorption...
535  this_partial_phase[iv] +=
536  (dK_dTl + dK_dTu) * ls_B; //Also, they are 0 when inactive...
537  }
538  }
539  }
540 }
541 
542 bool line_match_line(const QuantumIdentifier& from_jac,
543  const Index& species,
544  const Index& isotopologue,
545  const QuantumNumbers& lower_qn,
546  const QuantumNumbers& upper_qn) {
547  if (species not_eq from_jac.Species() or
548  isotopologue not_eq from_jac.Isotopologue()) {
549  return false;
550  } else {
551  if (from_jac.Type() == QuantumIdentifier::TRANSITION) {
552  return lower_qn ==
553  from_jac.QuantumMatch()[from_jac.TRANSITION_LOWER_INDEX] and
554  upper_qn ==
555  from_jac.QuantumMatch()[from_jac.TRANSITION_UPPER_INDEX];
556  } else if (from_jac.Type() == QuantumIdentifier::ALL) {
557  return true;
558  } else {
559  return false;
560  }
561  }
562 }
563 
564 void line_match_level(bool& lower_energy_level,
565  bool& upper_energy_level,
566  const QuantumIdentifier& from_jac,
567  const Index& species,
568  const Index& isotopologue,
569  const QuantumNumbers& lower_qn,
570  const QuantumNumbers& upper_qn) {
571  if (species not_eq from_jac.Species() or
572  isotopologue not_eq from_jac.Isotopologue()) {
573  lower_energy_level = false;
574  upper_energy_level = false;
575  } else {
576  // These can be partial, because vibrational energy levels are partial matches, so using simpler function
577  lower_energy_level = lower_qn.Compare(
578  from_jac.QuantumMatch()[from_jac.TRANSITION_UPPER_INDEX]);
579  upper_energy_level = upper_qn.Compare(
580  from_jac.QuantumMatch()[from_jac.TRANSITION_UPPER_INDEX]);
581  }
582 }
INDEX Index
The type to use for all integer numbers and indices.
Definition: matpack.h:39
const Numeric PLANCK_CONST
Global constant, the Planck constant [Js].
const String PROPMAT_SUBSUBTAG
const QuantumNumbers & UpperQuantumNumbers() const noexcept
Return the upper quantum numbers by const reference.
Definition: quantum.h:587
The VectorView class.
Definition: matpackI.h:610
Array< LineshapeNormRecord > lineshape_norm_data
Definition: lineshapes.cc:2537
bool Compare(const QuantumNumbers &qn) const
Compare Quantum Numbers Ignores any undefined numbers in the comparison.
Definition: quantum.cc:33
Index nelem() const
Number of elements.
Definition: array.h:195
void Isotopologue(Index iso)
Set the Isotopologue.
Definition: quantum.h:487
const Numeric BOLTZMAN_CONST
Global constant, the Boltzmann constant [J/K].
The Vector class.
Definition: matpackI.h:860
The range class.
Definition: matpackI.h:160
static constexpr Index TRANSITION_LOWER_INDEX
Lower level index.
Definition: quantum.h:472
Index nelem() const
Returns the number of elements.
Definition: matpackI.cc:51
JacPropMatType
List of Jacobian properties for analytical line shape related derivatives.
Definition: jacobian.h:46
bool is_frequency_parameter(const RetrievalQuantity &t) noexcept
Returns if the Retrieval quantity is a frequency parameter in propagation matrix calculations.
Definition: jacobian.cc:1120
The global header file for ARTS.
static constexpr Index TRANSITION_UPPER_INDEX
Upper level index.
Definition: quantum.h:469
void Species(Index sp)
Set the Species.
Definition: quantum.h:481
constexpr Index get_extent() const
Returns the extent of the range.
Definition: matpackI.h:329
void partial_derivatives_lineshape_dependency(ArrayOfMatrix &partials_attenuation, ArrayOfMatrix &partials_phase, ArrayOfMatrix &partials_src, const ArrayOfRetrievalQuantity &flag_partials, const ArrayOfIndex &flag_partials_position, ConstVectorView CF_A, ConstVectorView CF_B, ConstVectorView C, ConstVectorView dFa_dx, ConstVectorView dFb_dx, ConstVectorView dFa_dy, ConstVectorView dFb_dy, ConstVectorView f_grid, const Range &this_f_grid, const Numeric &temperature, const Numeric &sigma, const Numeric &K2, const Numeric &dK2_dT, const Numeric &K3, const Numeric &dK3_dT, const Numeric &K4, const Numeric &line_frequency, const Numeric &line_strength, const Numeric &line_temperature, const Numeric &line_E_low, const Numeric &line_E_v_low, const Numeric &line_E_v_upp, const Numeric &line_T_v_low, const Numeric &line_T_v_upp, const Numeric &Y_LM, const Numeric &dY_LM_dT, const Numeric &G_LM, const Numeric &dG_LM_dT, const Numeric &DF_LM, const Numeric &dDF_LM_dT, const QuantumIdentifier &qi, const Index &ind_ls, const Index &ind_lsn, const Numeric &df_0, const Numeric &ddf_dT, const Numeric &gamma, const Numeric &dgamma_dT, const Numeric &dQ_dT, const Numeric &DF_Zeeman, const Numeric &H_mag_Zeeman, const bool do_zeeman, const Index &pressure_level_index, const bool do_partials_phase, const bool do_src)
Computes all partial derivatives in old method.
void calc_derivative(Numeric &dxsec_dtarget, Numeric &dphase_dtarget, Numeric &dsrc_dtarget, const Numeric &dFA_dx, const Numeric &dFB_dx, const Numeric &dFA_dy, const Numeric &dFB_dy, const Numeric &dx_dtarget, const Numeric &dy_dtarget, const Numeric &FA, const Numeric &FB, const Numeric &FA_ratio_to_dtarget, const Numeric &FB_ratio_to_dtarget, const Numeric &lma, const Numeric &lmb, const Numeric &lma_real_ratio_to_dtarget, const Numeric &lma_imag_ratio_to_dtarget, const Numeric &lmb_real_ratio_to_dtarget, const Numeric &lmb_imag_ratio_to_dtarget, const Numeric &nlte, const Numeric &dnlte_dtarget, const bool do_phase, const bool do_src)
Class to identify and match lines by their quantum numbers.
Definition: quantum.h:390
NUMERIC Numeric
The type to use for all floating point numbers.
Definition: matpack.h:33
Declarations required for the calculation of absorption coefficients.
Computes partial derivatives (old method)
Container class for Quantum Numbers.
Definition: quantum.h:222
This can be used to make arrays out of anything.
Definition: array.h:40
constexpr QType Type() const
Definition: quantum.h:526
const QuantumNumbers & LowerQuantumNumbers() const noexcept
Return the lower quantum numbers by const reference.
Definition: quantum.h:592
Constains various line scaling functions.
Array< LineshapeRecord > lineshape_data
Definition: lineshapes.cc:2390
A constant view of a Vector.
Definition: matpackI.h:476
const std::array< QuantumNumbers, 2 > & QuantumMatch() const
Return the quantum numbers array const reference.
Definition: quantum.h:571
bool line_match_line(const QuantumIdentifier &from_jac, const Index &species, const Index &isotopologue, const QuantumNumbers &lower_qn, const QuantumNumbers &upper_qn)
Does this line match the identifier.
void line_match_level(bool &lower_energy_level, bool &upper_energy_level, const QuantumIdentifier &from_jac, const Index &species, const Index &isotopologue, const QuantumNumbers &lower_qn, const QuantumNumbers &upper_qn)
Match energy level to the identifier.