ARTS  2.4.0(git:4fb77825)
jacobian.cc
Go to the documentation of this file.
1 /* Copyright (C) 2004-2012 Mattias Ekstrom <ekstrom@rss.chalmers.se>
2 
3  This program is free software; you can redistribute it and/or modify it
4  under the terms of the GNU General Public License as published by the
5  Free Software Foundation; either version 2, or (at your option) any
6  later version.
7 
8  This program is distributed in the hope that it will be useful,
9  but WITHOUT ANY WARRANTY; without even the implied warranty of
10  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11  GNU General Public License for more details.
12 
13  You should have received a copy of the GNU General Public License
14  along with this program; if not, write to the Free Software
15  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
16  USA. */
17 
26 #include "jacobian.h"
27 #include "arts.h"
28 #include "auto_md.h"
29 #include "check_input.h"
30 #include "global_data.h"
31 #include "lin_alg.h"
32 #include "physics_funcs.h"
33 #include "rte.h"
34 #include "special_interp.h"
35 
36 extern const Numeric NAT_LOG_TEN;
37 extern const Numeric PI;
38 
39 extern const String ABSSPECIES_MAINTAG;
40 extern const String SCATSPECIES_MAINTAG;
41 extern const String TEMPERATURE_MAINTAG;
42 extern const String WIND_MAINTAG;
43 extern const String MAGFIELD_MAINTAG;
44 extern const String FLUX_MAINTAG;
45 extern const String PROPMAT_SUBSUBTAG;
46 extern const String ELECTRONS_MAINTAG;
47 extern const String PARTICULATES_MAINTAG;
48 extern const String POLYFIT_MAINTAG;
49 extern const String SINEFIT_MAINTAG;
50 
51 ostream& operator<<(ostream& os, const RetrievalQuantity& ot) {
52  return os << "\n Main tag = " << ot.MainTag()
53  << "\n Sub tag = " << ot.Subtag()
54  << "\n Mode = " << ot.Mode()
55  << "\n Analytical = " << ot.Analytical();
56 }
57 
59  bool& any_affine,
60  const ArrayOfRetrievalQuantity& jqs,
61  const bool& before_affine) {
62  jis.resize(jqs.nelem());
63 
64  any_affine = false;
65 
66  // Indices before affine transformation
67  if (before_affine) {
68  for (Index i = 0; i < jqs.nelem(); ++i) {
69  jis[i] = ArrayOfIndex(2);
70  if (i > 0) {
71  jis[i][0] = jis[i - 1][1] + 1;
72  } else {
73  jis[i][0] = 0;
74  }
75  const RetrievalQuantity& jq = jqs[i];
76  jis[i][1] = jis[i][0] + jq.nelem() - 1;
77  if (jq.HasAffine()) {
78  any_affine = true;
79  }
80  }
81  }
82 
83  // After affine transformation
84  else {
85  for (Index i = 0; i < jqs.nelem(); ++i) {
86  jis[i] = ArrayOfIndex(2);
87  if (i > 0) {
88  jis[i][0] = jis[i - 1][1] + 1;
89  } else {
90  jis[i][0] = 0;
91  }
92  const RetrievalQuantity& jq = jqs[i];
93  if (jq.HasAffine()) {
94  jis[i][1] = jis[i][0] + jq.TransformationMatrix().ncols() - 1;
95  any_affine = true;
96  } else {
97  jis[i][1] = jis[i][0] + jq.nelem() - 1;
98  }
99  }
100  }
101 }
102 
104  const Vector x,
105  const ArrayOfRetrievalQuantity& jqs) {
106  // Range indices without affine trans
108  bool any_affine;
109  //
110  jac_ranges_indices(jis, any_affine, jqs, true);
111 
112  Vector x_t(x);
113  transform_x_back(x_t, jqs, false);
114 
115  // Apply functional transformations
116  for (Index i = 0; i < jqs.nelem(); ++i) {
117  const RetrievalQuantity& jq = jqs[i];
118  const String tfun = jq.TransformationFunc();
119  // Remember to add new functions also to transform_jacobian and transform_x_back
120  if (tfun == "") {
121  // Nothing to do
122  } else if (tfun == "log") {
123  for (Index c = jis[i][0]; c <= jis[i][1]; ++c) {
124  jacobian(joker, c) *= exp(x_t[c]);
125  }
126  } else if (tfun == "log10") {
127  for (Index c = jis[i][0]; c <= jis[i][1]; ++c) {
128  jacobian(joker, c) *= NAT_LOG_TEN * pow(10.0, x_t[c]);
129  }
130  } else if (tfun == "atanh") {
131  const Vector& pars = jq.TFuncParameters();
132  for (Index c = jis[i][0]; c <= jis[i][1]; ++c) {
133  jacobian(joker, c) *=
134  2 * (pars[1] - pars[0]) / pow(exp(-x_t[c]) + exp(x_t[c]), 2.0);
135  }
136  } else {
137  assert(0);
138  }
139  }
140 
141  // Apply affine transformations
142  if (any_affine) {
143  ArrayOfArrayOfIndex jis_t;
144  jac_ranges_indices(jis_t, any_affine, jqs);
145 
146  Matrix jacobian_t(jacobian.nrows(), jis_t.back()[1] + 1);
147 
148  for (Index i = 0; i < jqs.nelem(); ++i) {
149  const RetrievalQuantity& jq = jqs[i];
150  Index col_start = jis[i][0];
151  Index col_extent = jis[i][1] - jis[i][0] + 1;
152  Range col_range(col_start, col_extent);
153  Index col_start_t = jis_t[i][0];
154  Index col_extent_t = jis_t[i][1] - jis_t[i][0] + 1;
155  Range col_range_t(col_start_t, col_extent_t);
156  if (jq.HasAffine()) {
157  mult(jacobian_t(joker, col_range_t),
158  jacobian(joker, col_range),
159  jq.TransformationMatrix());
160  } else {
161  jacobian_t(joker, col_range_t) = jacobian(joker, col_range);
162  }
163  }
164  swap(jacobian_t, jacobian);
165  }
166 }
167 
169  // Range indices without affine trans
171  bool any_affine;
172  //
173  jac_ranges_indices(jis, any_affine, jqs, true);
174 
175  // Apply functional transformations
176  for (Index i = 0; i < jqs.nelem(); ++i) {
177  const RetrievalQuantity& jq = jqs[i];
178  const String tfun = jq.TransformationFunc();
179  // Remember to add new functions also to transform_jacobian and transform_x_back
180  if (tfun == "") {
181  // Nothing to do
182  } else if (tfun == "log") {
183  const Vector& pars = jq.TFuncParameters();
184  for (Index r = jis[i][0]; r <= jis[i][1]; ++r) {
185  if (x[r] <= pars[0]) {
186  ostringstream os;
187  os << "log-transformation selected for retrieval quantity with\n"
188  << "index " << i << " (0-based), but at least one value <= z_min\n"
189  << "found for this quantity. This is not allowed.";
190  throw std::runtime_error(os.str());
191  }
192  x[r] = log(x[r] - pars[0]);
193  }
194  } else if (tfun == "log10") {
195  const Vector& pars = jq.TFuncParameters();
196  for (Index r = jis[i][0]; r <= jis[i][1]; ++r) {
197  if (x[r] <= 0) {
198  ostringstream os;
199  os << "log10-transformation selected for retrieval quantity with\n"
200  << "index " << i << " (0-based), but at least one value <= z_min\n"
201  << "found for this quantity. This is not allowed.";
202  throw std::runtime_error(os.str());
203  }
204  x[r] = log10(x[r] - pars[0]);
205  }
206  } else if (tfun == "atanh") {
207  const Vector& pars = jq.TFuncParameters();
208  for (Index r = jis[i][0]; r <= jis[i][1]; ++r) {
209  if (x[r] <= pars[0]) {
210  ostringstream os;
211  os << "atanh-transformation selected for retrieval quantity with\n"
212  << "index " << i << " (0-based), but at least one value <= z_min\n"
213  << "found for this quantity. This is not allowed.";
214  throw std::runtime_error(os.str());
215  }
216  if (x[r] >= pars[1]) {
217  ostringstream os;
218  os << "atanh-transformation selected for retrieval quantity with\n"
219  << "index " << i << " (0-based), but at least one value is\n"
220  << ">= z_max. This is not allowed.";
221  throw std::runtime_error(os.str());
222  }
223  x[r] = atanh(2 * (x[r] - pars[0]) / (pars[1] - pars[0]) - 1);
224  }
225  } else {
226  assert(0);
227  }
228  }
229 
230  // Apply affine transformations
231  if (any_affine) {
232  ArrayOfArrayOfIndex jis_t;
233  jac_ranges_indices(jis_t, any_affine, jqs);
234 
235  Vector x_t(jis_t.back()[1] + 1);
236 
237  for (Index i = 0; i < jqs.nelem(); ++i) {
238  const RetrievalQuantity& jq = jqs[i];
239  Index col_start = jis[i][0];
240  Index col_extent = jis[i][1] - jis[i][0] + 1;
241  Range col_range(col_start, col_extent);
242  Index col_start_t = jis_t[i][0];
243  Index col_extent_t = jis_t[i][1] - jis_t[i][0] + 1;
244  Range col_range_t(col_start_t, col_extent_t);
245  if (jq.HasAffine()) {
246  Vector t(x[col_range]);
247  t -= jq.OffsetVector();
248  mult(x_t[col_range_t], transpose(jq.TransformationMatrix()), t);
249  } else {
250  x_t[col_range_t] = x[col_range];
251  }
252  }
253  swap(x, x_t);
254  }
255 }
256 
258  const ArrayOfRetrievalQuantity& jqs,
259  bool revert_functional_transforms) {
260  // Range indices without affine trans
262  bool any_affine;
263  //
264  jac_ranges_indices(jis, any_affine, jqs, true);
265 
266  // Revert affine transformations
267  // Apply affine transformations
268  if (any_affine) {
269  ArrayOfArrayOfIndex jis_t;
270  jac_ranges_indices(jis_t, any_affine, jqs);
271 
272  Vector x(jis.back()[1] + 1);
273 
274  for (Index i = 0; i < jqs.nelem(); ++i) {
275  const RetrievalQuantity& jq = jqs[i];
276  Index col_start = jis[i][0];
277  Index col_extent = jis[i][1] - jis[i][0] + 1;
278  Range col_range(col_start, col_extent);
279  Index col_start_t = jis_t[i][0];
280  Index col_extent_t = jis_t[i][1] - jis_t[i][0] + 1;
281  Range col_range_t(col_start_t, col_extent_t);
282  if (jq.HasAffine()) {
283  mult(x[col_range], jq.TransformationMatrix(), x_t[col_range_t]);
284  x[col_range] += jq.OffsetVector();
285  } else {
286  x[col_range] = x_t[col_range_t];
287  }
288  }
289  swap(x_t, x);
290  }
291 
292  if (revert_functional_transforms) {
293  // Revert functional transformations
294  for (Index i = 0; i < jqs.nelem(); ++i) {
295  const RetrievalQuantity& jq = jqs[i];
296  const String tfun = jq.TransformationFunc();
297  // Remember to add new functions also to transform_jacobian and transform_x_back
298  if (tfun == "") {
299  // Nothing to do
300  } else if (tfun == "log") {
301  const Vector& pars = jq.TFuncParameters();
302  for (Index r = jis[i][0]; r <= jis[i][1]; ++r) {
303  x_t[r] = pars[0] + exp(x_t[r]);
304  }
305  } else if (tfun == "log10") {
306  const Vector& pars = jq.TFuncParameters();
307  for (Index r = jis[i][0]; r <= jis[i][1]; ++r) {
308  x_t[r] = pars[0] + pow(10.0, x_t[r]);
309  }
310  } else if (tfun == "atanh") {
311  const Vector& pars = jq.TFuncParameters();
312  for (Index r = jis[i][0]; r <= jis[i][1]; ++r) {
313  x_t[r] = pars[0] + ((pars[1] - pars[0]) / 2) * (1 + tanh(x_t[r]));
314  }
315  } else {
316  assert(0);
317  }
318  }
319  }
320 }
321 
322 /*===========================================================================
323  === Help sub-functions to handle analytical jacobians (in alphabetical order)
324  ===========================================================================*/
325 
326 // Small help function, to make the code below cleaner
328  ConstMatrixView diy_dq,
329  const Numeric& w) {
330  for (Index irow = 0; irow < diy_dx.nrows(); irow++) {
331  for (Index icol = 0; icol < diy_dx.ncols(); icol++) {
332  diy_dx(irow, icol) += w * diy_dq(irow, icol);
333  }
334  }
335 }
336 
338  const RetrievalQuantity& jacobian_quantity,
339  ConstTensor3View diy_dpath,
340  const Index& atmosphere_dim,
341  const Ppath& ppath,
342  ConstVectorView ppath_p) {
343  // If this is an integration target then diy_dx is just the sum of all in diy_dpath
344  if (jacobian_quantity.Integration()) {
345  diy_dx(0, joker, joker) = diy_dpath(0, joker, joker);
346  for (Index i = 1; i < diy_dpath.npages(); i++)
347  diy_dx(0, joker, joker) += diy_dpath(i, joker, joker);
348  return;
349  }
350 
351  assert(jacobian_quantity.Grids().nelem() == atmosphere_dim);
352 
353  // We want here an extrapolation to infinity ->
354  // extremly high extrapolation factor
355  const Numeric extpolfac = 1.0e99;
356 
357  if (ppath.np > 1) // Otherwise nothing to do here
358  {
359  // Pressure
360  Index nr1 = jacobian_quantity.Grids()[0].nelem();
361  ArrayOfGridPos gp_p(ppath.np);
362  if (nr1 > 1) {
363  p2gridpos(gp_p, jacobian_quantity.Grids()[0], ppath_p, extpolfac);
365  } else {
366  gp4length1grid(gp_p);
367  }
368 
369  // Latitude
370  Index nr2 = 1;
371  ArrayOfGridPos gp_lat;
372  if (atmosphere_dim > 1) {
373  gp_lat.resize(ppath.np);
374  nr2 = jacobian_quantity.Grids()[1].nelem();
375  if (nr2 > 1) {
376  gridpos(gp_lat,
377  jacobian_quantity.Grids()[1],
378  ppath.pos(joker, 1),
379  extpolfac);
380  jacobian_type_extrapol(gp_lat);
381  } else {
382  gp4length1grid(gp_lat);
383  }
384  }
385 
386  // Longitude
387  ArrayOfGridPos gp_lon;
388  if (atmosphere_dim > 2) {
389  gp_lon.resize(ppath.np);
390  if (jacobian_quantity.Grids()[2].nelem() > 1) {
391  gridpos(gp_lon,
392  jacobian_quantity.Grids()[2],
393  ppath.pos(joker, 2),
394  extpolfac);
395  jacobian_type_extrapol(gp_lon);
396  } else {
397  gp4length1grid(gp_lon);
398  }
399  }
400 
401  //- 1D
402  if (atmosphere_dim == 1) {
403  for (Index ip = 0; ip < ppath.np; ip++) {
404  if (gp_p[ip].fd[1] > 0) {
405  from_dpath_to_dx(diy_dx(gp_p[ip].idx, joker, joker),
406  diy_dpath(ip, joker, joker),
407  gp_p[ip].fd[1]);
408  }
409  if (gp_p[ip].fd[0] > 0) {
410  from_dpath_to_dx(diy_dx(gp_p[ip].idx + 1, joker, joker),
411  diy_dpath(ip, joker, joker),
412  gp_p[ip].fd[0]);
413  }
414  }
415  }
416 
417  //- 2D
418  else if (atmosphere_dim == 2) {
419  for (Index ip = 0; ip < ppath.np; ip++) {
420  Index ix = nr1 * gp_lat[ip].idx + gp_p[ip].idx;
421  // Low lat, low p
422  if (gp_lat[ip].fd[1] > 0 && gp_p[ip].fd[1] > 0)
424  diy_dpath(ip, joker, joker),
425  gp_lat[ip].fd[1] * gp_p[ip].fd[1]);
426  // Low lat, high p
427  if (gp_lat[ip].fd[1] > 0 && gp_p[ip].fd[0] > 0)
429  diy_dpath(ip, joker, joker),
430  gp_lat[ip].fd[1] * gp_p[ip].fd[0]);
431  // High lat, low p
432  if (gp_lat[ip].fd[0] > 0 && gp_p[ip].fd[1] > 0)
433  from_dpath_to_dx(diy_dx(ix + nr1, joker, joker),
434  diy_dpath(ip, joker, joker),
435  gp_lat[ip].fd[0] * gp_p[ip].fd[1]);
436  // High lat, high p
437  if (gp_lat[ip].fd[0] > 0 && gp_p[ip].fd[0] > 0)
438  from_dpath_to_dx(diy_dx(ix + nr1 + 1, joker, joker),
439  diy_dpath(ip, joker, joker),
440  gp_lat[ip].fd[0] * gp_p[ip].fd[0]);
441  }
442  }
443 
444  //- 3D
445  else if (atmosphere_dim == 3) {
446  for (Index ip = 0; ip < ppath.np; ip++) {
447  Index ix =
448  nr2 * nr1 * gp_lon[ip].idx + nr1 * gp_lat[ip].idx + gp_p[ip].idx;
449  // Low lon, low lat, low p
450  if (gp_lon[ip].fd[1] > 0 && gp_lat[ip].fd[1] > 0 && gp_p[ip].fd[1] > 0)
452  diy_dx(ix, joker, joker),
453  diy_dpath(ip, joker, joker),
454  gp_lon[ip].fd[1] * gp_lat[ip].fd[1] * gp_p[ip].fd[1]);
455  // Low lon, low lat, high p
456  if (gp_lon[ip].fd[1] > 0 && gp_lat[ip].fd[1] > 0 && gp_p[ip].fd[0] > 0)
458  diy_dx(ix + 1, joker, joker),
459  diy_dpath(ip, joker, joker),
460  gp_lon[ip].fd[1] * gp_lat[ip].fd[1] * gp_p[ip].fd[0]);
461  // Low lon, high lat, low p
462  if (gp_lon[ip].fd[1] > 0 && gp_lat[ip].fd[0] > 0 && gp_p[ip].fd[1] > 0)
464  diy_dx(ix + nr1, joker, joker),
465  diy_dpath(ip, joker, joker),
466  gp_lon[ip].fd[1] * gp_lat[ip].fd[0] * gp_p[ip].fd[1]);
467  // Low lon, high lat, high p
468  if (gp_lon[ip].fd[1] > 0 && gp_lat[ip].fd[0] > 0 && gp_p[ip].fd[0] > 0)
470  diy_dx(ix + nr1 + 1, joker, joker),
471  diy_dpath(ip, joker, joker),
472  gp_lon[ip].fd[1] * gp_lat[ip].fd[0] * gp_p[ip].fd[0]);
473 
474  // Increase *ix* (to be valid for high lon level)
475  ix += nr2 * nr1;
476 
477  // High lon, low lat, low p
478  if (gp_lon[ip].fd[0] > 0 && gp_lat[ip].fd[1] > 0 && gp_p[ip].fd[1] > 0)
480  diy_dx(ix, joker, joker),
481  diy_dpath(ip, joker, joker),
482  gp_lon[ip].fd[0] * gp_lat[ip].fd[1] * gp_p[ip].fd[1]);
483  // High lon, low lat, high p
484  if (gp_lon[ip].fd[0] > 0 && gp_lat[ip].fd[1] > 0 && gp_p[ip].fd[0] > 0)
486  diy_dx(ix + 1, joker, joker),
487  diy_dpath(ip, joker, joker),
488  gp_lon[ip].fd[0] * gp_lat[ip].fd[1] * gp_p[ip].fd[0]);
489  // High lon, high lat, low p
490  if (gp_lon[ip].fd[0] > 0 && gp_lat[ip].fd[0] > 0 && gp_p[ip].fd[1] > 0)
492  diy_dx(ix + nr1, joker, joker),
493  diy_dpath(ip, joker, joker),
494  gp_lon[ip].fd[0] * gp_lat[ip].fd[0] * gp_p[ip].fd[1]);
495  // High lon, high lat, high p
496  if (gp_lon[ip].fd[0] > 0 && gp_lat[ip].fd[0] > 0 && gp_p[ip].fd[0] > 0)
498  diy_dx(ix + nr1 + 1, joker, joker),
499  diy_dpath(ip, joker, joker),
500  gp_lon[ip].fd[0] * gp_lat[ip].fd[0] * gp_p[ip].fd[0]);
501  }
502  }
503  }
504 }
505 
507  const RetrievalQuantity& jacobian_quantity,
508  ConstMatrixView diy_dpos,
509  const Index& atmosphere_dim,
511  assert(jacobian_quantity.Grids().nelem() ==
512  max(atmosphere_dim - 1, Index(1)));
513  assert(rtp_pos.nelem() == atmosphere_dim);
514 
515  // We want here an extrapolation to infinity ->
516  // extremly high extrapolation factor
517  const Numeric extpolfac = 1.0e99;
518 
519  // Handle 1D separately
520  if (atmosphere_dim == 1) {
521  diy_dx(0, joker, joker) = diy_dpos;
522  return;
523  }
524 
525  // Latitude
526  Index nr1 = 1;
527  ArrayOfGridPos gp_lat;
528  {
529  gp_lat.resize(1);
530  nr1 = jacobian_quantity.Grids()[0].nelem();
531  if (nr1 > 1) {
532  gridpos(gp_lat,
533  jacobian_quantity.Grids()[0],
534  Vector(1, rtp_pos[1]),
535  extpolfac);
536  jacobian_type_extrapol(gp_lat);
537  } else {
538  gp4length1grid(gp_lat);
539  }
540  }
541 
542  // Longitude
543  ArrayOfGridPos gp_lon;
544  if (atmosphere_dim > 2) {
545  gp_lon.resize(1);
546  if (jacobian_quantity.Grids()[1].nelem() > 1) {
547  gridpos(gp_lon,
548  jacobian_quantity.Grids()[1],
549  Vector(1, rtp_pos[2]),
550  extpolfac);
551  jacobian_type_extrapol(gp_lon);
552  } else {
553  gp4length1grid(gp_lon);
554  }
555  }
556 
557  //- 2D
558  if (atmosphere_dim == 2) {
559  if (gp_lat[0].fd[1] > 0) {
560  from_dpath_to_dx(diy_dx(gp_lat[0].idx, joker, joker),
561  diy_dpos(joker, joker),
562  gp_lat[0].fd[1]);
563  }
564  if (gp_lat[0].fd[0] > 0) {
565  from_dpath_to_dx(diy_dx(gp_lat[0].idx + 1, joker, joker),
566  diy_dpos(joker, joker),
567  gp_lat[0].fd[0]);
568  }
569  }
570  //- 3D
571  else {
572  Index ix = nr1 * gp_lon[0].idx + gp_lat[0].idx;
573  // Low lon, low lat
574  if (gp_lon[0].fd[1] > 0 && gp_lat[0].fd[1] > 0)
576  diy_dpos(joker, joker),
577  gp_lon[0].fd[1] * gp_lat[0].fd[1]);
578  // Low lon, high lat
579  if (gp_lon[0].fd[1] > 0 && gp_lat[0].fd[0] > 0)
581  diy_dpos(joker, joker),
582  gp_lon[0].fd[1] * gp_lat[0].fd[0]);
583  // High lon, low lat
584  if (gp_lon[0].fd[0] > 0 && gp_lat[0].fd[1] > 0)
585  from_dpath_to_dx(diy_dx(ix + nr1, joker, joker),
586  diy_dpos(joker, joker),
587  gp_lon[0].fd[0] * gp_lat[0].fd[1]);
588  // High lon, high lat
589  if (gp_lon[0].fd[0] > 0 && gp_lat[0].fd[0] > 0)
590  from_dpath_to_dx(diy_dx(ix + nr1 + 1, joker, joker),
591  diy_dpos(joker, joker),
592  gp_lon[0].fd[0] * gp_lat[0].fd[0]);
593  }
594 }
595 
597  ArrayOfIndex& abs_species_i,
598  ArrayOfIndex& scat_species_i,
599  ArrayOfIndex& is_t,
600  ArrayOfIndex& wind_i,
601  ArrayOfIndex& magfield_i,
604  const Index& cloudbox_on,
605  const ArrayOfString& scat_species) {
607  //
608  if (jacobian_quantities[iq].MainTag() == TEMPERATURE_MAINTAG &&
609  jacobian_quantities[iq].SubSubtag() == PROPMAT_SUBSUBTAG) {
610  is_t[iq] = Index(JacobianType::Temperature);
611  } else { is_t[iq] = Index(JacobianType::None); }
612  //
613  if (jacobian_quantities[iq].MainTag() == ABSSPECIES_MAINTAG) {
614  if (jacobian_quantities[iq].SubSubtag() == PROPMAT_SUBSUBTAG) {
615  bool test_available = false;
616  for (Index ii = 0; ii < abs_species.nelem(); ii++) {
617  if (abs_species[ii][0].Species() ==
618  SpeciesTag(jacobian_quantities[iq].Subtag()).Species()) {
619  test_available = true;
620  abs_species_i[iq] = ii;
621  break;
622  }
623  }
624  if (!test_available) {
625  ostringstream os;
626  os << "Could not find " << jacobian_quantities[iq].Subtag()
627  << " in species of abs_species.\n";
628  throw std::runtime_error(os.str());
629  }
630  } else {
631  ArrayOfSpeciesTag atag;
633  abs_species_i[iq] = chk_contains("abs_species", abs_species, atag);
634  }
635  } else if (jacobian_quantities[iq].MainTag() == PARTICULATES_MAINTAG ||
636  jacobian_quantities[iq].MainTag() == ELECTRONS_MAINTAG) {
637  abs_species_i[iq] = -9999;
638  } else { abs_species_i[iq] = -1; }
639  //
640  if (cloudbox_on &&
641  jacobian_quantities[iq].MainTag() == SCATSPECIES_MAINTAG) {
642  scat_species_i[iq] =
644  if (scat_species_i[iq] < 0) {
645  ostringstream os;
646  os << "Jacobian quantity with index " << iq << " refers to\n"
647  << " " << jacobian_quantities[iq].Subtag()
648  << "\nbut this species could not be found in *scat_species*.";
649  throw runtime_error(os.str());
650  }
651  } else { scat_species_i[iq] = -1; }
652  //
653  if (jacobian_quantities[iq].MainTag() == WIND_MAINTAG &&
654  jacobian_quantities[iq].SubSubtag() == PROPMAT_SUBSUBTAG) {
655  // Map u, v and w to 1, 2 and 3, respectively
656  char c = jacobian_quantities[iq].Subtag()[0];
657  const Index test = Index(c) - 116;
658  if (test == 1)
659  wind_i[iq] = Index(JacobianType::WindFieldU);
660  else if (test == 2)
661  wind_i[iq] = Index(JacobianType::WindFieldV);
662  else if (test == 3)
663  wind_i[iq] = Index(JacobianType::WindFieldW);
664  else if (test == (Index('s') - 116))
665  wind_i[iq] = Index(JacobianType::AbsWind);
666  } else { wind_i[iq] = Index(JacobianType::None); }
667  //
668  if (jacobian_quantities[iq].MainTag() == MAGFIELD_MAINTAG &&
669  jacobian_quantities[iq].SubSubtag() == PROPMAT_SUBSUBTAG) {
670  // Map u, v and w to 1, 2 and 3, respectively
671  char c = jacobian_quantities[iq].Subtag()[0];
672  const Index test = Index(c) - 116;
673  if (test == 1)
674  magfield_i[iq] = Index(JacobianType::MagFieldU);
675  else if (test == 2)
676  magfield_i[iq] = Index(JacobianType::MagFieldV);
677  else if (test == 3)
678  magfield_i[iq] = Index(JacobianType::MagFieldW);
679  else if (test == (Index('s') - 116))
680  magfield_i[iq] = Index(JacobianType::AbsMag);
681  } else { magfield_i[iq] = Index(JacobianType::None); }
682 
683  )
684 }
685 
686 /*===========================================================================
687  === Other functions, in alphabetical order
688  ===========================================================================*/
689 
691  ostringstream& os,
692  const Vector& p_grid,
693  const Vector& lat_grid,
694  const Vector& lon_grid,
695  const Vector& p_retr,
696  const Vector& lat_retr,
697  const Vector& lon_retr,
698  const String& p_retr_name,
699  const String& lat_retr_name,
700  const String& lon_retr_name,
701  const Index& dim) {
702  assert(grids.nelem() == dim);
703 
704  if (p_retr.nelem() == 0) {
705  os << "The grid vector *" << p_retr_name << "* is empty,"
706  << " at least one pressure level\n"
707  << "should be specified.";
708  return false;
709  } else if (!is_decreasing(p_retr)) {
710  os << "The pressure grid vector *" << p_retr_name << "* is not a\n"
711  << "strictly decreasing vector, which is required.";
712  return false;
713  } else if (p_grid.nelem() == 1 and p_grid.nelem() == p_retr.nelem()) {
714  if (p_grid[0] not_eq p_retr[0]) {
715  os << "Mismatching 1-long grids for " << p_retr_name;
716  return false;
717  }
718 
719  // Necessary repeat but grids are OK
720  grids[0] = p_retr;
721  } else if (log(p_retr[0]) > 1.5 * log(p_grid[0]) - 0.5 * log(p_grid[1]) ||
722  log(p_retr[p_retr.nelem() - 1]) <
723  1.5 * log(p_grid[p_grid.nelem() - 1]) -
724  0.5 * log(p_grid[p_grid.nelem() - 2])) {
725  os << "The grid vector *" << p_retr_name << "* is not covered by the\n"
726  << "corresponding atmospheric grid.";
727  return false;
728  } else {
729  // Pressure grid ok, add it to grids
730  grids[0] = p_retr;
731  }
732 
733  if (dim >= 2) {
734  // If 2D and 3D atmosphere, check latitude grid
735  if (lat_retr.nelem() == 0) {
736  os << "The grid vector *" << lat_retr_name << "* is empty,"
737  << " at least one latitude\n"
738  << "should be specified for a 2D/3D atmosphere.";
739  return false;
740  } else if (!is_increasing(lat_retr)) {
741  os << "The latitude grid vector *" << lat_retr_name << "* is not a\n"
742  << "strictly increasing vector, which is required.";
743  return false;
744  } else if (lat_grid.nelem() == 1 and lat_grid.nelem() == lat_retr.nelem()) {
745  if (lat_grid[0] not_eq lat_retr[0]) {
746  os << "Mismatching 1-long grids for " << lat_retr_name;
747  return false;
748  }
749 
750  // Necessary repeat but grids are OK
751  grids[1] = lat_retr;
752  } else if (lat_retr[0] < 1.5 * lat_grid[0] - 0.5 * lat_grid[1] ||
753  lat_retr[lat_retr.nelem() - 1] >
754  1.5 * lat_grid[lat_grid.nelem() - 1] -
755  0.5 * lat_grid[lat_grid.nelem() - 2]) {
756  os << "The grid vector *" << lat_retr_name << "* is not covered by the\n"
757  << "corresponding atmospheric grid.";
758  return false;
759  } else {
760  // Latitude grid ok, add it to grids
761  grids[1] = lat_retr;
762  }
763  if (dim == 3) {
764  // For 3D atmosphere check longitude grid
765  if (lon_retr.nelem() == 0) {
766  os << "The grid vector *" << lon_retr_name << "* is empty,"
767  << " at least one longitude\n"
768  << "should be specified for a 3D atmosphere.";
769  return false;
770  } else if (!is_increasing(lon_retr)) {
771  os << "The longitude grid vector *" << lon_retr_name << "* is not a\n"
772  << "strictly increasing vector, which is required.";
773  return false;
774  } else if (lon_grid.nelem() == 1 and
775  lon_grid.nelem() == lon_retr.nelem()) {
776  if (lon_grid[0] not_eq lon_retr[0]) {
777  os << "Mismatching 1-long grids for " << lon_retr_name;
778  return false;
779  }
780 
781  // Necessary repeat but grids are OK
782  grids[2] = lon_retr;
783  } else if (lon_retr[0] < 1.5 * lon_grid[0] - 0.5 * lon_grid[1] ||
784  lon_retr[lon_retr.nelem() - 1] >
785  1.5 * lon_grid[lon_grid.nelem() - 1] -
786  0.5 * lon_grid[lon_grid.nelem() - 2]) {
787  os << "The grid vector *" << lon_retr_name
788  << "* is not covered by the\n"
789  << "corresponding atmospheric grid.";
790  return false;
791  } else {
792  // Longitude grid ok, add it to grids
793  grids[2] = lon_retr;
794  }
795  }
796  }
797  return true;
798 }
799 
801  ostringstream& os,
802  const Vector& lat_grid,
803  const Vector& lon_grid,
804  const Vector& lat_retr,
805  const Vector& lon_retr,
806  const String& lat_retr_name,
807  const String& lon_retr_name,
808  const Index& dim) {
809  assert(grids.nelem() == max(dim - 1, Index(1)));
810 
811  if (dim == 1) {
812  // Here we only need to create a length 1 dummy grid
813  grids[0].resize(1);
814  grids[0][0] = 0;
815  }
816 
817  if (dim >= 2) {
818  // If 2D and 3D atmosphere, check latitude grid
819  if (lat_retr.nelem() == 0) {
820  os << "The grid vector *" << lat_retr_name << "* is empty,"
821  << " at least one latitude\n"
822  << "should be specified for a 2D/3D atmosphere.";
823  return false;
824  } else if (!is_increasing(lat_retr)) {
825  os << "The latitude grid vector *" << lat_retr_name << "* is not a\n"
826  << "strictly increasing vector, which is required.";
827  return false;
828  } else if (lat_grid.nelem() == 1 and lat_grid.nelem() == lat_retr.nelem()) {
829  if (lat_grid[0] not_eq lat_retr[0]) {
830  os << "Mismatching 1-long grids for " << lat_retr_name;
831  return false;
832  }
833 
834  // Necessary repeat but grids are OK
835  grids[0] = lat_retr;
836  } else if (lat_retr[0] < 1.5 * lat_grid[0] - 0.5 * lat_grid[1] ||
837  lat_retr[lat_retr.nelem() - 1] >
838  1.5 * lat_grid[lat_grid.nelem() - 1] -
839  0.5 * lat_grid[lat_grid.nelem() - 2]) {
840  os << "The grid vector *" << lat_retr_name << "* is not covered by the\n"
841  << "corresponding atmospheric grid.";
842  return false;
843  } else {
844  // Latitude grid ok, add it to grids
845  grids[0] = lat_retr;
846  }
847 
848  if (dim == 3) {
849  // For 3D atmosphere check longitude grid
850  if (lon_retr.nelem() == 0) {
851  os << "The grid vector *" << lon_retr_name << "* is empty,"
852  << " at least one longitude\n"
853  << "should be specified for a 3D atmosphere.";
854  return false;
855  } else if (!is_increasing(lon_retr)) {
856  os << "The longitude grid vector *" << lon_retr_name << "* is not a\n"
857  << "strictly increasing vector, which is required.";
858  return false;
859  } else if (lon_grid.nelem() == 1 and
860  lon_grid.nelem() == lon_retr.nelem()) {
861  if (lon_grid[0] not_eq lon_retr[0]) {
862  os << "Mismatching 1-long grids for " << lon_retr_name;
863  return false;
864  }
865 
866  // Necessary repeat but grids are OK
867  grids[1] = lon_retr;
868  } else if (lon_retr[0] < 1.5 * lon_grid[0] - 0.5 * lon_grid[1] ||
869  lon_retr[lon_retr.nelem() - 1] >
870  1.5 * lon_grid[lon_grid.nelem() - 1] -
871  0.5 * lon_grid[lon_grid.nelem() - 2]) {
872  os << "The grid vector *" << lon_retr_name
873  << "* is not covered by the\n"
874  << "corresponding atmospheric grid.";
875  return false;
876  } else {
877  // Longitude grid ok, add it to grids
878  grids[1] = lon_retr;
879  }
880  }
881  }
882  return true;
883 }
884 
886  for (Index i = 0; i < gp.nelem(); i++) {
887  if (gp[i].fd[0] < 0) {
888  gp[i].fd[0] = 0;
889  gp[i].fd[1] = 1;
890  } else if (gp[i].fd[0] > 1) {
891  gp[i].fd[0] = 1;
892  gp[i].fd[1] = 0;
893  }
894  }
895 }
896 
898  const Vector& x,
899  const Index& poly_coeff) {
900  const Index l = x.nelem();
901 
902  assert(l > poly_coeff);
903 
904  if (b.nelem() != l) b.resize(l);
905 
906  if (poly_coeff == 0) {
907  b = 1.0;
908  } else {
909  const Numeric xmin = min(x);
910  const Numeric dx = 0.5 * (max(x) - xmin);
911  //
912  for (Index i = 0; i < l; i++) {
913  b[i] = (x[i] - xmin) / dx - 1.0;
914  b[i] = pow(b[i], int(poly_coeff));
915  }
916  //
917  b -= mean(b);
918  }
919 }
920 
922  const Vector& x,
923  const Index& mblock_index,
924  const Sparse& sensor_response,
928  const RetrievalQuantity& rq,
929  const Index rq_index,
930  const ArrayOfArrayOfIndex& jacobian_indices) {
931  bool is_sine_fit = false;
932  if (rq.MainTag() == POLYFIT_MAINTAG) {
933  is_sine_fit = false;
934  } else if (rq.MainTag() == SINEFIT_MAINTAG) {
935  is_sine_fit = true;
936  } else {
937  throw runtime_error(
938  "Retrieval quantity is neither a polynomial or a sine "
939  " baseline fit.");
940  }
941 
942  // Size and check of sensor_response
943  //
944  const Index nf = sensor_response_f_grid.nelem();
945  const Index npol = sensor_response_pol_grid.nelem();
946  const Index nlos = sensor_response_dlos_grid.nrows();
947 
948  // Evaluate basis functions for fits.
949  Vector w, s, c;
950  if (is_sine_fit) {
951  s.resize(nf);
952  c.resize(nf);
953  Numeric period = rq.Grids()[0][0];
954  for (Index f = 0; f < nf; f++) {
956  PI / period;
957  s[f] = sin(a);
958  c[f] = cos(a);
959  }
960  } else {
961  Numeric poly_coeff = rq.Grids()[0][0];
963  w, sensor_response_f_grid, static_cast<Index>(poly_coeff));
964  }
965 
966  // Compute baseline
967  ArrayOfVector jg = rq.Grids();
968  const Index n1 = jg[1].nelem();
969  const Index n2 = jg[2].nelem();
970  const Index n3 = jg[3].nelem();
972  const Index row4 = rowind.get_start();
973  Index col4 = jacobian_indices[rq_index][0];
974 
975  if (n3 > 1) {
976  col4 += mblock_index * n2 * n1;
977  }
978 
979  for (Index l = 0; l < nlos; l++) {
980  const Index row3 = row4 + l * nf * npol;
981  const Index col3 = col4 + l * n1 * (is_sine_fit ? 2 : 1);
982 
983  for (Index f = 0; f < nf; f++) {
984  const Index row2 = row3 + f * npol;
985 
986  for (Index p = 0; p < npol; p++) {
987  Index col1 = col3;
988  if (n1 > 1) {
989  col1 += p;
990  }
991  if (is_sine_fit) {
992  y_baseline[row2 + p] += x[col1] * s[f] + x[col1 + 1] * c[f];
993  } else {
994  y_baseline[row2 + p] += w[f] * x[col1];
995  }
996  }
997  }
998  }
999 }
1000 
1002  const String& unit,
1003  const Numeric& vmr,
1004  const Numeric& p,
1005  const Numeric& t) {
1006  if (unit == "rel" || unit == "logrel") {
1007  x = 1;
1008  } else if (unit == "vmr") {
1009  if (vmr == 0) {
1010  x = 0;
1011  return;
1012  }
1013  x = 1 / vmr;
1014  } else if (unit == "nd") {
1015  if (vmr == 0) {
1016  x = 0;
1017  return;
1018  }
1019  x = 1 / (vmr * number_density(p, t));
1020  } else {
1021  ostringstream os;
1022  os << "Allowed options for gas species jacobians are "
1023  "\"rel\", \"vmr\" and \"nd\".\nYou have selected: "
1024  << unit << std::endl;
1025  throw std::runtime_error(os.str());
1026  }
1027 }
1028 
1030  const String& unit,
1031  const Numeric& vmr,
1032  const Numeric& p,
1033  const Numeric& t) {
1034  if (unit == "rel" || unit == "logrel") {
1035  x = vmr;
1036  } else if (unit == "vmr") {
1037  x = 1;
1038  } else if (unit == "nd") {
1039  x = 1 / number_density(p, t);
1040  } else {
1041  ostringstream os;
1042  os << "Allowed options for gas species jacobians are "
1043  "\"rel\", \"vmr\" and \"nd\".\nYou have selected: "
1044  << unit << std::endl;
1045  throw std::runtime_error(os.str());
1046  }
1047 }
1048 
1050  VectorView diy2,
1051  ConstMatrixView ImT,
1053  ConstMatrixView dT1,
1054  ConstMatrixView dT2,
1055  ConstVectorView iYmJ,
1056  ConstVectorView dJ1,
1057  ConstVectorView dJ2,
1058  const Index stokes_dim,
1059  const bool transmission_only) {
1060  /*
1061  * Solves
1062  *
1063  * diy1 = PiT [ dT1 iYmJ + (1-T) dJ1 ],
1064  *
1065  * and
1066  *
1067  * diy2 += PiT [ dT2 iYmJ + (1-T) dJ2 ],
1068  *
1069  * where diy2 is diy1 from a prior layer
1070  *
1071  * FIXME: Needs HSE
1072  */
1073 
1074  // Computation vectors
1075  Vector a(stokes_dim), b(stokes_dim);
1076 
1077  // The first time a level is involved in a layer
1078  mult(a, dT1, iYmJ);
1079  if (not transmission_only) {
1080  mult(b, ImT, dJ1);
1081  a += b;
1082  }
1083  mult(diy1, cumulative_transmission, a);
1084 
1085  // The second time a level is involved in a layer
1086  mult(a, dT2, iYmJ);
1087  if (not transmission_only) {
1088  mult(b, ImT, dJ2);
1089  a += b;
1090  }
1092  diy2 += b;
1093 }
1094 
1095 //======================================================================
1096 // Propmat partials descriptions
1097 //======================================================================
1098 
1100  ArrayOfIndex pos;
1101  pos.reserve(js.nelem());
1102  for (Index i = 0; i < js.nelem(); i++)
1103  if (js[i] not_eq JacPropMatType::NotPropagationMatrixType) pos.push_back(i);
1104  return pos;
1105 }
1106 
1108  const Index i) noexcept {
1109  Index j = -1;
1110  for (Index k = 0; k <= i; k++)
1111  if (js[k] not_eq JacPropMatType::NotPropagationMatrixType) j++;
1112  return j;
1113 }
1114 
1115 bool is_wind_parameter(const RetrievalQuantity& t) noexcept {
1116  return t == JacPropMatType::WindMagnitude or t == JacPropMatType::WindU or
1117  t == JacPropMatType::WindV or t == JacPropMatType::WindW;
1118 }
1119 
1121  return is_wind_parameter(t) or t == JacPropMatType::Frequency;
1122 }
1123 
1125  return t == JacPropMatType::MagneticMagnitude;
1126 }
1127 
1128 bool is_magnetic_parameter(const RetrievalQuantity& t) noexcept {
1129  return t == JacPropMatType::MagneticU or t == JacPropMatType::MagneticV or
1130  t == JacPropMatType::MagneticW or is_derived_magnetic_parameter(t);
1131 }
1132 
1133 bool is_nlte_parameter(const RetrievalQuantity& t) noexcept {
1134  return t == JacPropMatType::NLTE;
1135 }
1136 
1137 #define ISLINESHAPETYPE(X) \
1138  bool is_pressure_broadening_##X(const RetrievalQuantity& t) noexcept { \
1139  return t == JacPropMatType::LineShape##X##X0 or \
1140  t == JacPropMatType::LineShape##X##X1 or \
1141  t == JacPropMatType::LineShape##X##X2; \
1142  }
1143 ISLINESHAPETYPE(G0)
1144 ISLINESHAPETYPE(D0)
1145 ISLINESHAPETYPE(G2)
1146 ISLINESHAPETYPE(D2)
1147 ISLINESHAPETYPE(FVC)
1148 ISLINESHAPETYPE(ETA)
1149 ISLINESHAPETYPE(Y)
1150 ISLINESHAPETYPE(G)
1151 ISLINESHAPETYPE(DV)
1152 #undef ISLINESHAPETYPE
1153 
1154 #define VARISLINESHAPEPARAM(X, Y) (t == JacPropMatType::LineShape##X##Y)
1156  return VARISLINESHAPEPARAM(G0, X0) or VARISLINESHAPEPARAM(D0, X0) or
1157  VARISLINESHAPEPARAM(G2, X0) or VARISLINESHAPEPARAM(D2, X0) or
1158  VARISLINESHAPEPARAM(FVC, X0) or VARISLINESHAPEPARAM(ETA, X0) or
1159  VARISLINESHAPEPARAM(Y, X0) or VARISLINESHAPEPARAM(G, X0) or
1160  VARISLINESHAPEPARAM(DV, X0);
1161 }
1162 
1164  return VARISLINESHAPEPARAM(G0, X1) or VARISLINESHAPEPARAM(D0, X1) or
1165  VARISLINESHAPEPARAM(G2, X1) or VARISLINESHAPEPARAM(D2, X1) or
1166  VARISLINESHAPEPARAM(FVC, X1) or VARISLINESHAPEPARAM(ETA, X1) or
1167  VARISLINESHAPEPARAM(Y, X1) or VARISLINESHAPEPARAM(G, X1) or
1168  VARISLINESHAPEPARAM(DV, X1);
1169 }
1170 
1172  return VARISLINESHAPEPARAM(G0, X2) or VARISLINESHAPEPARAM(D0, X2) or
1173  VARISLINESHAPEPARAM(G2, X2) or VARISLINESHAPEPARAM(D2, X2) or
1174  VARISLINESHAPEPARAM(FVC, X2) or VARISLINESHAPEPARAM(ETA, X2) or
1175  VARISLINESHAPEPARAM(Y, X2) or VARISLINESHAPEPARAM(G, X2) or
1176  VARISLINESHAPEPARAM(DV, X2);
1177 }
1178 #undef VARISLINESHAPEPARAM
1179 
1181  const RetrievalQuantity& t) noexcept {
1185 }
1186 
1193 }
1194 
1195 bool is_line_parameter(const RetrievalQuantity& t) noexcept {
1196  return t == JacPropMatType::LineCenter or t == JacPropMatType::LineStrength or
1198 }
1199 
1201  return std::any_of(js.cbegin(), js.cend(), [](auto& j){return (j == JacPropMatType::Temperature or j == JacPropMatType::VMR or is_frequency_parameter(j));});
1202 }
1203 
1205  return std::any_of(js.cbegin(), js.cend(), [](auto& j){return (j == JacPropMatType::Temperature or j == JacPropMatType::VMR or is_frequency_parameter(j));});
1206 }
1207 
1209  if (std::any_of(js.cbegin(), js.cend(), [](auto& j){return is_line_parameter(j);}))
1210  throw std::runtime_error("Line specific parameters are not supported while using continuum tags.\nWe do not track what lines are in the continuum.\n");
1211  return std::any_of(js.cbegin(), js.cend(), [](auto& j){return (j == JacPropMatType::Temperature or j == JacPropMatType::VMR or is_frequency_parameter(j));});
1212 }
1213 
1215  return not std::any_of(js.cbegin(), js.cend(), [](auto& j){return j not_eq JacPropMatType::VMR or j not_eq JacPropMatType::LineStrength or not is_nlte_parameter(j);});
1216 }
1217 
1219  if (std::any_of(js.cbegin(), js.cend(), [](auto& j){return is_line_parameter(j);}))
1220  throw std::runtime_error("Line specific parameters are not supported while\n using the relaxation matrix line mixing routine.\n We do not yet track individual lines in the relaxation matrix calculations.\n");
1221  return std::any_of(js.cbegin(), js.cend(), [](auto& j){return (j == JacPropMatType::Temperature or is_frequency_parameter(j));});
1222 }
1223 
1225  if (std::any_of(js.cbegin(), js.cend(), [](auto& j){return is_line_parameter(j);}))
1226  throw std::runtime_error("Line specific parameters are not supported while using Lookup table.\nWe do not track lines in the Lookup.\n");
1227  return std::any_of(js.cbegin(), js.cend(), [](auto& j){return (j == JacPropMatType::Temperature or j == JacPropMatType::VMR or is_frequency_parameter(j));});
1228 }
1229 
1231  if (std::any_of(js.cbegin(), js.cend(), [](auto& j){return is_derived_magnetic_parameter(j);}))
1232  throw std::runtime_error("This method does not yet support Zeeman-style magnetic Jacobian calculations.\n Please use u, v, and w Jacobians instead.\n");
1233  return std::any_of(js.cbegin(), js.cend(), [](auto& j){return j == JacPropMatType::MagneticU or j == JacPropMatType::MagneticV or j == JacPropMatType::MagneticW or j == JacPropMatType::Electrons or is_frequency_parameter(j);});
1234 }
1235 
1237  return std::any_of(js.cbegin(), js.cend(), [](auto& j){return j not_eq JacPropMatType::NotPropagationMatrixType;});
1238 }
1239 
1241  return std::any_of(js.cbegin(), js.cend(), [](auto& j){return j not_eq JacPropMatType::NotPropagationMatrixType;});
1242 }
1243 
1245  if (rq.QuantumIdentity().Type() == QuantumIdentifier::ALL) { // Single tag
1246  for (const auto& s : ast) {
1247  if (rq.QuantumIdentity().Species() not_eq s.Species())
1248  return false; // Species must match
1249  if (rq.QuantumIdentity().Isotopologue() >= 0 and s.Isotopologue() >= 0 and
1250  rq.QuantumIdentity().Isotopologue() not_eq s.Isotopologue())
1251  return false; // Isotopologue must match or be undefined
1252  }
1253  } else {
1254  ArrayOfSpeciesTag test;
1256  if (ast not_eq test)
1257  return false; // Match single tag perfectly or throw out
1258  }
1259  return true;
1260 }
1261 
1262 bool species_match(const RetrievalQuantity& rq, const Index species) {
1263  if (rq == JacPropMatType::VMR)
1264  if (rq.QuantumIdentity().Species() == species) return true;
1265  return false;
1266 }
1267 
1269  const Index species,
1270  const Index iso) {
1271  const SpeciesRecord& spr = global_data::species_data[species];
1272  if (species_match(rq, species))
1273  if (rq.QuantumIdentity().Isotopologue() == iso or
1274  spr.Isotopologue().nelem() == iso or iso < 0)
1275  return true;
1276  return false;
1277 }
1278 
1280  return std::any_of(js.cbegin(), js.cend(), [](auto& j){return j == JacPropMatType::Temperature;});
1281 }
1282 
1284  const QuantumIdentifier& line_qid) noexcept {
1285  auto p = std::find_if(js.cbegin(), js.cend(), [&line_qid](auto& j){return j == JacPropMatType::VMR and j.QuantumIdentity().In(line_qid);});
1286  if (p not_eq js.cend())
1287  return {true, p -> QuantumIdentity()};
1288  else
1289  return {false, line_qid};
1290 }
1291 
1293  return std::any_of(js.cbegin(), js.cend(), [](auto& j){return j == JacPropMatType::LineCenter;});
1294 }
1295 
1297  return std::any_of(js.cbegin(), js.cend(), [](auto& j){return is_frequency_parameter(j);});
1298 }
1299 
1301  return std::any_of(js.cbegin(), js.cend(), [](auto& j){return is_magnetic_parameter(j);});
1302 }
1303 
1305  auto p = std::find_if(js.cbegin(), js.cend(), [](auto& j){return j == JacPropMatType::Temperature;});
1306  if (p not_eq js.cend())
1307  return p -> Perturbation();
1308  else
1309  return 0.0;
1310 }
1311 
1313  auto p = std::find_if(js.cbegin(), js.cend(), [](auto& j){return is_frequency_parameter(j);});
1314  if (p not_eq js.cend())
1315  return p -> Perturbation();
1316  else
1317  return 0.0;
1318 }
1319 
1321  auto p = std::find_if(js.cbegin(), js.cend(), [](auto& j){return is_magnetic_parameter(j);});
1322  if (p not_eq js.cend())
1323  return p -> Perturbation();
1324  else
1325  return 0.0;
1326 }
1327 
1329 #define lineshapevariable(X1, X2) \
1330  JacPropMatType::LineShape##X1##X2 : return "Line-Shape: " #X1 " " #X2
1331  switch (rq.PropMatType()) {
1332  case JacPropMatType::VMR:
1333  return "VMR";
1334  case JacPropMatType::Electrons:
1335  return "Electrons-VMR";
1336  case JacPropMatType::Particulates:
1337  return "Particulate-VMR";
1338  case JacPropMatType::Temperature:
1339  return "Temperature";
1340  case JacPropMatType::MagneticMagnitude:
1341  return "Magnetic-Strength";
1342  case JacPropMatType::MagneticU:
1343  return "Magnetic-u";
1344  case JacPropMatType::MagneticV:
1345  return "Magnetic-v";
1346  case JacPropMatType::MagneticW:
1347  return "Magnetic-w";
1348  case JacPropMatType::WindMagnitude:
1349  return "Wind-Strength";
1350  case JacPropMatType::WindU:
1351  return "Wind-u";
1352  case JacPropMatType::WindV:
1353  return "Wind-v";
1354  case JacPropMatType::WindW:
1355  return "Wind-w";
1356  case JacPropMatType::Frequency:
1357  return "Frequency";
1358  case JacPropMatType::LineStrength:
1359  return "Line-Strength";
1360  case JacPropMatType::LineCenter:
1361  return "Line-Center";
1362  case JacPropMatType::LineSpecialParameter1:
1363  return "Line-Special-Parameter-1";
1364  case JacPropMatType::NLTE:
1365  return "NLTE-Level";
1366  case lineshapevariable(G0, X0);
1367  case lineshapevariable(G0, X1);
1368  case lineshapevariable(G0, X2);
1369  case lineshapevariable(G0, X3);
1370  case lineshapevariable(D0, X0);
1371  case lineshapevariable(D0, X1);
1372  case lineshapevariable(D0, X2);
1373  case lineshapevariable(D0, X3);
1374  case lineshapevariable(G2, X0);
1375  case lineshapevariable(G2, X1);
1376  case lineshapevariable(G2, X2);
1377  case lineshapevariable(G2, X3);
1378  case lineshapevariable(D2, X0);
1379  case lineshapevariable(D2, X1);
1380  case lineshapevariable(D2, X2);
1381  case lineshapevariable(D2, X3);
1382  case lineshapevariable(ETA, X0);
1383  case lineshapevariable(ETA, X1);
1384  case lineshapevariable(ETA, X2);
1385  case lineshapevariable(ETA, X3);
1386  case lineshapevariable(FVC, X0);
1387  case lineshapevariable(FVC, X1);
1388  case lineshapevariable(FVC, X2);
1389  case lineshapevariable(FVC, X3);
1390  case lineshapevariable(Y, X0);
1391  case lineshapevariable(Y, X1);
1392  case lineshapevariable(Y, X2);
1393  case lineshapevariable(Y, X3);
1394  case lineshapevariable(G, X0);
1395  case lineshapevariable(G, X1);
1396  case lineshapevariable(G, X2);
1397  case lineshapevariable(G, X3);
1398  case lineshapevariable(DV, X0);
1399  case lineshapevariable(DV, X1);
1400  case lineshapevariable(DV, X2);
1401  case lineshapevariable(DV, X3);
1403  return "Not-A-Prop-Mat-Variable";
1404  }
1405 #undef lineshapevariable
1406 
1407  return "UNDEFINED-CHECK-IF-CASE-LIST-IS-COMPLETE";
1408 }
Matrix
The Matrix class.
Definition: matpackI.h:1193
supports_continuum
bool supports_continuum(const ArrayOfRetrievalQuantity &js)
Returns if the array supports continuum derivatives.
Definition: jacobian.cc:1208
ARTS::Var::atmosphere_dim
Index atmosphere_dim(Workspace &ws) noexcept
Definition: autoarts.h:2510
do_vmr_jacobian
jacobianVMRcheck do_vmr_jacobian(const ArrayOfRetrievalQuantity &js, const QuantumIdentifier &line_qid) noexcept
Returns the required info for VMR Jacobian.
Definition: jacobian.cc:1283
ARTS::Var::Ppath::pos
std::size_t pos() const noexcept
Definition: autoarts.h:1300
get_rowindex_for_mblock
Range get_rowindex_for_mblock(const Sparse &sensor_response, const Index &mblock_index)
Returns the "range" of y corresponding to a measurement block.
Definition: rte.cc:1301
ARTS::Var::sensor_response_dlos_grid
Matrix sensor_response_dlos_grid(Workspace &ws) noexcept
Definition: autoarts.h:6356
magnetic_field_perturbation
Numeric magnetic_field_perturbation(const ArrayOfRetrievalQuantity &js) noexcept
Returns the magnetic field perturbation if it exists.
Definition: jacobian.cc:1320
supports_relaxation_matrix
bool supports_relaxation_matrix(const ArrayOfRetrievalQuantity &js)
Returns if the array supports relaxation matrix derivatives.
Definition: jacobian.cc:1218
from_dpath_to_dx
void from_dpath_to_dx(MatrixView diy_dx, ConstMatrixView diy_dq, const Numeric &w)
Definition: jacobian.cc:327
QuantumIdentifier::Isotopologue
void Isotopologue(Index iso)
Set the Isotopologue.
Definition: quantum.h:487
RetrievalQuantity::Analytical
const Index & Analytical() const
Returns the analytical tag.
Definition: jacobian.h:227
NAT_LOG_TEN
const Numeric NAT_LOG_TEN
MatrixView
The MatrixView class.
Definition: matpackI.h:1093
is_pressure_broadening_Y
bool is_pressure_broadening_Y(const RetrievalQuantity &t) noexcept
Returns if the Retrieval quantity is a Y derivative.
QuantumIdentifier
Class to identify and match lines by their quantum numbers.
Definition: quantum.h:390
auto_md.h
ARTS::Var::jacobian_quantities
ArrayOfRetrievalQuantity jacobian_quantities(Workspace &ws) noexcept
Definition: autoarts.h:3924
array_species_tag_from_string
void array_species_tag_from_string(ArrayOfSpeciesTag &tags, const String &names)
Converts a String to ArrayOfSpeciesTag.
Definition: abs_species_tags.cc:586
w
Complex w(Complex z) noexcept
The Faddeeva function.
Definition: linefunctions.cc:42
RetrievalQuantity::Grids
const ArrayOfVector & Grids() const
Returns the grids of the retrieval.
Definition: jacobian.h:255
is_derived_magnetic_parameter
bool is_derived_magnetic_parameter(const RetrievalQuantity &t) noexcept
Returns if the Retrieval quantity is a derived magnetic parameter.
Definition: jacobian.cc:1124
gridpos
void gridpos(ArrayOfGridPos &gp, ConstVectorView old_grid, ConstVectorView new_grid, const Numeric &extpolfac)
Set up a grid position Array.
Definition: interpolation.cc:156
iso
void iso(Array< IsotopologueRecord >::iterator &ii, String name, const ArrayOfNumeric &coeff, const ArrayOfNumeric &temp_range, const Index &coefftype)
Initialize isotopologue and move iterator to next one.
Definition: partition_function_data.cc:1732
lineshapevariable
#define lineshapevariable(X1, X2)
species_iso_match
bool species_iso_match(const RetrievalQuantity &rq, const Index species, const Index iso)
Returns if the Retrieval quantity is VMR derivative for all the species in the species tags.
Definition: jacobian.cc:1268
is_lineshape_parameter_X1
bool is_lineshape_parameter_X1(const RetrievalQuantity &t) noexcept
Returns if the Retrieval quantity is a X1 derivative.
Definition: jacobian.cc:1163
operator<<
ostream & operator<<(ostream &os, const RetrievalQuantity &ot)
Output operator for RetrievalQuantity.
Definition: jacobian.cc:51
ARTS::Var::sensor_response
Sparse sensor_response(Workspace &ws) noexcept
Definition: autoarts.h:6300
VARISLINESHAPEPARAM
#define VARISLINESHAPEPARAM(X, Y)
Definition: jacobian.cc:1154
PI
const Numeric PI
p2gridpos
void p2gridpos(ArrayOfGridPos &gp, ConstVectorView old_pgrid, ConstVectorView new_pgrid, const Numeric &extpolfac)
Calculates grid positions for pressure values.
Definition: special_interp.cc:759
jacobian_type_extrapol
void jacobian_type_extrapol(ArrayOfGridPos &gp)
Adopts grid positions to extrapolation used for jacobians.
Definition: jacobian.cc:885
ARTS::Var::lat_grid
Vector lat_grid(Workspace &ws) noexcept
Definition: autoarts.h:3962
joker
const Joker joker
RetrievalQuantity::QuantumIdentity
const QuantumIdentifier & QuantumIdentity() const
Returns the identity of this Jacobian.
Definition: jacobian.h:311
ARTS::Var::y_baseline
Vector y_baseline(Workspace &ws) noexcept
Definition: autoarts.h:7447
mult
void mult(ComplexVectorView y, const ConstComplexMatrixView &M, const ConstComplexVectorView &x)
Matrix-Vector Multiplication.
Definition: complex.cc:1579
get_diydx
void get_diydx(VectorView diy1, VectorView diy2, ConstMatrixView ImT, ConstMatrixView cumulative_transmission, ConstMatrixView dT1, ConstMatrixView dT2, ConstVectorView iYmJ, ConstVectorView dJ1, ConstVectorView dJ2, const Index stokes_dim, const bool transmission_only)
Definition: jacobian.cc:1049
temperature_perturbation
Numeric temperature_perturbation(const ArrayOfRetrievalQuantity &js) noexcept
Returns the temperature perturbation if it exists.
Definition: jacobian.cc:1304
swap
void swap(ComplexVector &v1, ComplexVector &v2)
Swaps two objects.
Definition: complex.cc:731
Sparse
The Sparse class.
Definition: matpackII.h:60
vmrunitscf
void vmrunitscf(Numeric &x, const String &unit, const Numeric &vmr, const Numeric &p, const Numeric &t)
Scale factor for conversion between gas species units.
Definition: jacobian.cc:1001
Vector::resize
void resize(Index n)
Resize function.
Definition: matpackI.cc:404
ARTS::Var::diy_dx
ArrayOfTensor3 diy_dx(Workspace &ws) noexcept
Definition: autoarts.h:3007
diy_from_path_to_rgrids
void diy_from_path_to_rgrids(Tensor3View diy_dx, const RetrievalQuantity &jacobian_quantity, ConstTensor3View diy_dpath, const Index &atmosphere_dim, const Ppath &ppath, ConstVectorView ppath_p)
Maps jacobian data for points along the propagation path, to jacobian retrieval grid data.
Definition: jacobian.cc:337
is_nlte_parameter
bool is_nlte_parameter(const RetrievalQuantity &t) noexcept
Returns if the Retrieval quantity is a NLTE parameter.
Definition: jacobian.cc:1133
polynomial_basis_func
void polynomial_basis_func(Vector &b, const Vector &x, const Index &poly_coeff)
Calculates polynomial basis functions.
Definition: jacobian.cc:897
ELECTRONS_MAINTAG
const String ELECTRONS_MAINTAG
supports_lookup
bool supports_lookup(const ArrayOfRetrievalQuantity &js)
Returns if the array supports lookup table derivatives.
Definition: jacobian.cc:1224
is_pressure_broadening_FVC
bool is_pressure_broadening_FVC(const RetrievalQuantity &t) noexcept
Returns if the Retrieval quantity is a FVC derivative.
Species
QuantumIdentifier::QType Index LowerQuantumNumbers Species
Definition: arts_api_classes.cc:255
ARTS::Var::stokes_dim
Index stokes_dim(Workspace &ws) noexcept
Definition: autoarts.h:6650
supports_particles
bool supports_particles(const ArrayOfRetrievalQuantity &js)
Returns if the array supports particulate derivatives.
Definition: jacobian.cc:1236
is_pressure_broadening_DV
bool is_pressure_broadening_DV(const RetrievalQuantity &t) noexcept
Returns if the Retrieval quantity is a DV derivative.
RetrievalQuantity::OffsetVector
const Vector & OffsetVector() const
Definition: jacobian.h:347
FOR_ANALYTICAL_JACOBIANS_DO
#define FOR_ANALYTICAL_JACOBIANS_DO(what_to_do)
Definition: jacobian.h:405
do_temperature_jacobian
bool do_temperature_jacobian(const ArrayOfRetrievalQuantity &js) noexcept
Returns if the array wants the temperature derivative.
Definition: jacobian.cc:1279
global_data::species_data
const Array< SpeciesRecord > species_data
Species Data.
Definition: partition_function_data.cc:42
is_lineshape_parameter_X2
bool is_lineshape_parameter_X2(const RetrievalQuantity &t) noexcept
Returns if the Retrieval quantity is a X2 derivative.
Definition: jacobian.cc:1171
Ppath
The structure to describe a propagation path and releated quantities.
Definition: ppath.h:48
frequency_perturbation
Numeric frequency_perturbation(const ArrayOfRetrievalQuantity &js) noexcept
Returns the frequency perturbation if it exists.
Definition: jacobian.cc:1312
QuantumIdentifier::ALL
@ ALL
Definition: quantum.h:393
is_wind_parameter
bool is_wind_parameter(const RetrievalQuantity &t) noexcept
Returns if the Retrieval quantity is a wind parameter.
Definition: jacobian.cc:1115
dxdvmrscf
void dxdvmrscf(Numeric &x, const String &unit, const Numeric &vmr, const Numeric &p, const Numeric &t)
Scale factor for conversion of derivatives with respect to VMR.
Definition: jacobian.cc:1029
is_pressure_broadening_D0
bool is_pressure_broadening_D0(const RetrievalQuantity &t) noexcept
Returns if the Retrieval quantity is a D0 derivative.
ConstTensor3View::npages
Index npages() const
Returns the number of pages.
Definition: matpackIII.h:144
Range::get_start
constexpr Index get_start() const
Returns the start index of the range.
Definition: matpackI.h:327
transform_x_back
void transform_x_back(Vector &x_t, const ArrayOfRetrievalQuantity &jqs, bool revert_functional_transforms)
Handles back-transformations of the state vector.
Definition: jacobian.cc:257
supports_LBL_without_phase
bool supports_LBL_without_phase(const ArrayOfRetrievalQuantity &js)
Returns if the array supports line-by-line derivatives without requiring the phase.
Definition: jacobian.cc:1214
is_pressure_broadening_G0
bool is_pressure_broadening_G0(const RetrievalQuantity &t) noexcept
Returns if the Retrieval quantity is a G0 derivative.
MAGFIELD_MAINTAG
const String MAGFIELD_MAINTAG
Tensor3View
The Tensor3View class.
Definition: matpackIII.h:239
Array< ArrayOfIndex >
pow
Numeric pow(const Rational base, Numeric exp)
Power of.
Definition: rational.h:628
SpeciesTag
A tag group can consist of the sum of several of these.
Definition: abs_species_tags.h:44
number_density
Numeric number_density(const Numeric &p, const Numeric &t)
number_density
Definition: physics_funcs.cc:219
is_decreasing
bool is_decreasing(ConstVectorView x)
Checks if a vector is sorted in reversed order and is strictly decreasing.
Definition: logic.cc:252
RetrievalQuantity::TransformationMatrix
const Matrix & TransformationMatrix() const
Definition: jacobian.h:346
min
#define min(a, b)
Definition: legacy_continua.cc:20628
is_magnetic_parameter
bool is_magnetic_parameter(const RetrievalQuantity &t) noexcept
Returns if the Retrieval quantity is a magnetic parameter.
Definition: jacobian.cc:1128
transform_x
void transform_x(Vector &x, const ArrayOfRetrievalQuantity &jqs)
Handles transformations of the state vector.
Definition: jacobian.cc:168
SCATSPECIES_MAINTAG
const String SCATSPECIES_MAINTAG
QuantumIdentifier::Species
void Species(Index sp)
Set the Species.
Definition: quantum.h:481
ConstMatrixView::ncols
Index ncols() const
Returns the number of columns.
Definition: matpackI.cc:432
POLYFIT_MAINTAG
const String POLYFIT_MAINTAG
diy_from_pos_to_rgrids
void diy_from_pos_to_rgrids(Tensor3View diy_dx, const RetrievalQuantity &jacobian_quantity, ConstMatrixView diy_dpos, const Index &atmosphere_dim, ConstVectorView rtp_pos)
diy_from_pos_to_rgrids
Definition: jacobian.cc:506
my_basic_string< char >
equivalent_propmattype_indexes
ArrayOfIndex equivalent_propmattype_indexes(const ArrayOfRetrievalQuantity &js)
Returns a list of positions for the derivatives in Propagation Matrix calculations.
Definition: jacobian.cc:1099
RetrievalQuantity::Integration
bool Integration() const
Do integration?
Definition: jacobian.h:326
RetrievalQuantity::MainTag
const String & MainTag() const
Returns the main tag.
Definition: jacobian.h:170
ConstVectorView::nelem
Index nelem() const
Returns the number of elements.
Definition: matpackI.cc:51
ArrayOfIndex
Array< Index > ArrayOfIndex
An array of Index.
Definition: array.h:40
VectorView
The VectorView class.
Definition: matpackI.h:610
physics_funcs.h
This file contains declerations of functions of physical character.
ARTS::Var::abs_species
ArrayOfArrayOfSpeciesTag abs_species(Workspace &ws) noexcept
Definition: autoarts.h:2157
mean
Numeric mean(const ConstVectorView &x)
Mean function, vector version.
Definition: matpackI.cc:1589
is_lineshape_parameter_bar_linemixing
bool is_lineshape_parameter_bar_linemixing(const RetrievalQuantity &t) noexcept
Returns if the Retrieval quantity is a G0, D0, G2, D2, ETA, FVC derivative.
Definition: jacobian.cc:1180
ARTS::Var::p_grid
Vector p_grid(Workspace &ws) noexcept
Definition: autoarts.h:4763
ARTS::Var::ppath
Ppath ppath(Workspace &ws) noexcept
Definition: autoarts.h:5139
RetrievalQuantity::Mode
const String & Mode() const
Returns the mode.
Definition: jacobian.h:213
jacobian.h
Routines for setting up the jacobian.
Numeric
NUMERIC Numeric
The type to use for all floating point numbers.
Definition: matpack.h:33
lin_alg.h
Linear algebra functions.
global_data.h
do_frequency_jacobian
bool do_frequency_jacobian(const ArrayOfRetrievalQuantity &js) noexcept
Returns if the array wants a frequency derivative.
Definition: jacobian.cc:1296
FLUX_MAINTAG
const String FLUX_MAINTAG
TEMPERATURE_MAINTAG
const String TEMPERATURE_MAINTAG
ARTS::Var::sensor_response_f_grid
Vector sensor_response_f_grid(Workspace &ws) noexcept
Definition: autoarts.h:6392
max
#define max(a, b)
Definition: legacy_continua.cc:20629
calcBaselineFit
void calcBaselineFit(Vector &y_baseline, const Vector &x, const Index &mblock_index, const Sparse &sensor_response, const ArrayOfIndex &sensor_response_pol_grid, const Vector &sensor_response_f_grid, const Matrix &sensor_response_dlos_grid, const RetrievalQuantity &rq, const Index rq_index, const ArrayOfArrayOfIndex &jacobian_indices)
Calculate baseline fit.
Definition: jacobian.cc:921
RetrievalQuantity::HasAffine
bool HasAffine() const
Definition: jacobian.h:343
is_pressure_broadening_G
bool is_pressure_broadening_G(const RetrievalQuantity &t) noexcept
Returns if the Retrieval quantity is a G derivative.
is_line_parameter
bool is_line_parameter(const RetrievalQuantity &t) noexcept
Returns if the Retrieval quantity is related to the absorption line.
Definition: jacobian.cc:1195
SpeciesRecord
Contains the lookup data for one species.
Definition: absorption.h:144
ARTS::Var::lon_grid
Vector lon_grid(Workspace &ws) noexcept
Definition: autoarts.h:4090
ConstMatrixView
A constant view of a Matrix.
Definition: matpackI.h:982
QuantumIdentifier::Type
constexpr QType Type() const
Definition: quantum.h:526
supports_faraday
bool supports_faraday(const ArrayOfRetrievalQuantity &js)
Returns if the array supports Faraday derivatives.
Definition: jacobian.cc:1230
is_pressure_broadening_D2
bool is_pressure_broadening_D2(const RetrievalQuantity &t) noexcept
Returns if the Retrieval quantity is a D2 derivative.
cumulative_transmission
ArrayOfTransmissionMatrix cumulative_transmission(const ArrayOfTransmissionMatrix &T, const CumulativeTransmission type)
Accumulate the transmission matrix over all layers.
Definition: transmissionmatrix.cc:1527
SINEFIT_MAINTAG
const String SINEFIT_MAINTAG
Range
The range class.
Definition: matpackI.h:160
SpeciesRecord::Isotopologue
const Array< IsotopologueRecord > & Isotopologue() const
Definition: absorption.h:199
check_retrieval_grids
bool check_retrieval_grids(ArrayOfVector &grids, ostringstream &os, const Vector &p_grid, const Vector &lat_grid, const Vector &lon_grid, const Vector &p_retr, const Vector &lat_retr, const Vector &lon_retr, const String &p_retr_name, const String &lat_retr_name, const String &lon_retr_name, const Index &dim)
Check that the retrieval grids are defined for each atmosphere dim.
Definition: jacobian.cc:690
ARTS::Var::sensor_response_pol_grid
ArrayOfIndex sensor_response_pol_grid(Workspace &ws) noexcept
Definition: autoarts.h:6428
WIND_MAINTAG
const String WIND_MAINTAG
RetrievalQuantity::TransformationFunc
const String & TransformationFunc() const
Definition: jacobian.h:344
is_pressure_broadening_G2
bool is_pressure_broadening_G2(const RetrievalQuantity &t) noexcept
Returns if the Retrieval quantity is a G0 derivative.
gp4length1grid
void gp4length1grid(ArrayOfGridPos &gp)
Grid position matching a grid of length 1.
Definition: interpolation.cc:636
do_magnetic_jacobian
bool do_magnetic_jacobian(const ArrayOfRetrievalQuantity &js) noexcept
Returns if the array wants a magnetic derivative.
Definition: jacobian.cc:1300
is_increasing
bool is_increasing(ConstVectorView x)
Checks if a vector is sorted and strictly increasing.
Definition: logic.cc:215
PROPMAT_SUBSUBTAG
const String PROPMAT_SUBSUBTAG
PARTICULATES_MAINTAG
const String PARTICULATES_MAINTAG
RetrievalQuantity::TFuncParameters
const Vector & TFuncParameters() const
Definition: jacobian.h:345
rte.h
Declaration of functions in rte.cc.
ISLINESHAPETYPE
#define ISLINESHAPETYPE(X)
Definition: jacobian.cc:1137
ConstTensor3View
A constant view of a Tensor3.
Definition: matpackIII.h:132
dx
#define dx
Definition: legacy_continua.cc:22180
special_interp.h
Header file for special_interp.cc.
supports_hitran_xsec
bool supports_hitran_xsec(const ArrayOfRetrievalQuantity &js)
Returns if the array supports HITRAN cross-section derivatives.
Definition: jacobian.cc:1204
equivalent_propmattype_index
Index equivalent_propmattype_index(const ArrayOfRetrievalQuantity &js, const Index i) noexcept
Returns a list of positions for the derivatives in Propagation Matrix calculations.
Definition: jacobian.cc:1107
jacobianVMRcheck
Deals with whether or not we should do a VMR derivative.
Definition: jacobian.h:1160
is_lineshape_parameter_X0
bool is_lineshape_parameter_X0(const RetrievalQuantity &t) noexcept
Returns if the Retrieval quantity is a X0 derivative.
Definition: jacobian.cc:1155
chk_contains
Index chk_contains(const String &x_name, const Array< T > &x, const T &what)
Check if an array contains a value.
Definition: check_input.h:149
supports_CIA
bool supports_CIA(const ArrayOfRetrievalQuantity &js)
Returns if the array supports CIA derivatives.
Definition: jacobian.cc:1200
supports_propmat_clearsky
bool supports_propmat_clearsky(const ArrayOfRetrievalQuantity &js)
Returns if the array supports propagation matrix derivatives.
Definition: jacobian.cc:1240
ARTS::Var::jacobian
Matrix jacobian(Workspace &ws) noexcept
Definition: autoarts.h:3892
ARTS::Var::x
Vector x(Workspace &ws) noexcept
Definition: autoarts.h:7346
Index
INDEX Index
The type to use for all integer numbers and indices.
Definition: matpack.h:39
transpose
ConstComplexMatrixView transpose(ConstComplexMatrixView m)
Const version of transpose.
Definition: complex.cc:1509
ARTS::Var::scat_species
ArrayOfString scat_species(Workspace &ws) noexcept
Definition: autoarts.h:6086
RetrievalQuantity
Deals with internal derivatives, Jacobian definition, and OEM calculations.
Definition: jacobian.h:120
find_first
Index find_first(const Array< base > &x, const base &w)
Find first occurance.
Definition: array.h:292
check_input.h
ARTS::Var::mblock_index
Index mblock_index(Workspace &ws) noexcept
Definition: autoarts.h:4258
is_frequency_parameter
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
Vector
The Vector class.
Definition: matpackI.h:860
transform_jacobian
void transform_jacobian(Matrix &jacobian, const Vector x, const ArrayOfRetrievalQuantity &jqs)
Applies both functional and affine transformations.
Definition: jacobian.cc:103
jac_ranges_indices
void jac_ranges_indices(ArrayOfArrayOfIndex &jis, bool &any_affine, const ArrayOfRetrievalQuantity &jqs, const bool &before_affine)
Determines the index range inside x and the Jacobian for each retrieval quantity.
Definition: jacobian.cc:58
ConstVectorView
A constant view of a Vector.
Definition: matpackI.h:476
propmattype_string
String propmattype_string(const RetrievalQuantity &rq)
Returns a string of the retrieval quantity propagation matrix type.
Definition: jacobian.cc:1328
is_pressure_broadening_ETA
bool is_pressure_broadening_ETA(const RetrievalQuantity &t) noexcept
Returns if the Retrieval quantity is a ETA derivative.
species_match
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:1244
Array::nelem
Index nelem() const
Number of elements.
Definition: array.h:195
RetrievalQuantity::nelem
Index nelem() const
Number of elements in the grids.
Definition: jacobian.h:297
is_lineshape_parameter
bool is_lineshape_parameter(const RetrievalQuantity &t) noexcept
Returns if the Retrieval quantity is a G0, D0, G2, D2, ETA, FVC, Y, G, DV derivative.
Definition: jacobian.cc:1187
RetrievalQuantity::Subtag
const String & Subtag() const
Returns the sub-tag.
Definition: jacobian.h:184
get_pointers_for_analytical_jacobians
void get_pointers_for_analytical_jacobians(ArrayOfIndex &abs_species_i, ArrayOfIndex &scat_species_i, ArrayOfIndex &is_t, ArrayOfIndex &wind_i, ArrayOfIndex &magfield_i, const ArrayOfRetrievalQuantity &jacobian_quantities, const ArrayOfArrayOfSpeciesTag &abs_species, const Index &cloudbox_on, const ArrayOfString &scat_species)
Help function for analytical jacobian calculations.
Definition: jacobian.cc:596
JacPropMatType::VMR
@ VMR
ABSSPECIES_MAINTAG
const String ABSSPECIES_MAINTAG
ARTS::Var::rtp_pos
Vector rtp_pos(Workspace &ws) noexcept
Definition: autoarts.h:5774
arts.h
The global header file for ARTS.
RetrievalQuantity::PropMatType
JacPropMatType PropMatType() const
Returns the propagation matrix derivative type.
Definition: jacobian.h:267
ARTS::Var::cloudbox_on
Index cloudbox_on(Workspace &ws) noexcept
Definition: autoarts.h:2782
do_line_center_jacobian
bool do_line_center_jacobian(const ArrayOfRetrievalQuantity &js) noexcept
Returns if the array wants a line center derivative.
Definition: jacobian.cc:1292