24 return os <<
"\n Target = " << ot.
Target()
25 <<
"\n Sub tag = " << ot.
Subtag()
26 <<
"\n Mode = " << ot.
Mode();
32 const bool& before_affine) {
33 jis.resize(jqs.
nelem());
39 for (Index i = 0; i < jqs.
nelem(); ++i) {
42 jis[i][0] = jis[i - 1][1] + 1;
47 jis[i][1] = jis[i][0] + jq.
nelem() - 1;
56 for (Index i = 0; i < jqs.
nelem(); ++i) {
59 jis[i][0] = jis[i - 1][1] + 1;
68 jis[i][1] = jis[i][0] + jq.
nelem() - 1;
87 for (Index i = 0; i < jqs.
nelem(); ++i) {
93 }
else if (tfun ==
"log") {
94 for (Index
c = jis[i][0];
c <= jis[i][1]; ++
c) {
95 jacobian(joker,
c) *= exp(x_t[
c]);
97 }
else if (tfun ==
"log10") {
98 for (Index
c = jis[i][0];
c <= jis[i][1]; ++
c) {
101 }
else if (tfun ==
"atanh") {
103 for (Index
c = jis[i][0];
c <= jis[i][1]; ++
c) {
104 jacobian(joker,
c) *=
105 2 * (pars[1] - pars[0]) / pow(exp(-x_t[
c]) + exp(x_t[
c]), 2.0);
117 Matrix jacobian_t(jacobian.nrows(), jis_t.back()[1] + 1);
119 for (Index i = 0; i < jqs.
nelem(); ++i) {
121 Index col_start = jis[i][0];
122 Index col_extent = jis[i][1] - jis[i][0] + 1;
123 Range col_range(col_start, col_extent);
124 Index col_start_t = jis_t[i][0];
125 Index col_extent_t = jis_t[i][1] - jis_t[i][0] + 1;
126 Range col_range_t(col_start_t, col_extent_t);
128 mult(jacobian_t(joker, col_range_t),
129 jacobian(joker, col_range),
132 jacobian_t(joker, col_range_t) = jacobian(joker, col_range);
135 swap(jacobian_t, jacobian);
147 for (Index i = 0; i < jqs.
nelem(); ++i) {
153 }
else if (tfun ==
"log") {
155 for (Index r = jis[i][0]; r <= jis[i][1]; ++r) {
157 "log-transformation selected for retrieval quantity with\n"
158 "index ", i,
" (0-based), but at least one value <= z_min\n"
159 "found for this quantity. This is not allowed.")
160 x[r] = log(x[r] - pars[0]);
162 }
else if (tfun ==
"log10") {
164 for (Index r = jis[i][0]; r <= jis[i][1]; ++r) {
166 "log10-transformation selected for retrieval quantity with\n"
167 "index ", i,
" (0-based), but at least one value <= z_min\n"
168 "found for this quantity. This is not allowed.")
169 x[r] = log10(x[r] - pars[0]);
171 }
else if (tfun ==
"atanh") {
173 for (Index r = jis[i][0]; r <= jis[i][1]; ++r) {
175 "atanh-transformation selected for retrieval quantity with\n"
176 "index ", i,
" (0-based), but at least one value <= z_min\n"
177 "found for this quantity. This is not allowed.")
179 "atanh-transformation selected for retrieval quantity with\n"
180 "index ", i,
" (0-based), but at least one value is\n"
181 ">= z_max. This is not allowed.")
182 x[r] = atanh(2 * (x[r] - pars[0]) / (pars[1] - pars[0]) - 1);
194 Vector x_t(jis_t.back()[1] + 1);
196 for (Index i = 0; i < jqs.
nelem(); ++i) {
198 Index col_start = jis[i][0];
199 Index col_extent = jis[i][1] - jis[i][0] + 1;
200 Range col_range(col_start, col_extent);
201 Index col_start_t = jis_t[i][0];
202 Index col_extent_t = jis_t[i][1] - jis_t[i][0] + 1;
203 Range col_range_t(col_start_t, col_extent_t);
205 Vector t(x[col_range]);
209 x_t[col_range_t] = x[col_range];
218 bool revert_functional_transforms) {
231 Vector x(jis.back()[1] + 1);
233 for (Index i = 0; i < jqs.
nelem(); ++i) {
235 Index col_start = jis[i][0];
236 Index col_extent = jis[i][1] - jis[i][0] + 1;
237 Range col_range(col_start, col_extent);
238 Index col_start_t = jis_t[i][0];
239 Index col_extent_t = jis_t[i][1] - jis_t[i][0] + 1;
240 Range col_range_t(col_start_t, col_extent_t);
245 x[col_range] = x_t[col_range_t];
251 if (revert_functional_transforms) {
253 for (Index i = 0; i < jqs.
nelem(); ++i) {
259 }
else if (tfun ==
"log") {
261 for (Index r = jis[i][0]; r <= jis[i][1]; ++r) {
262 x_t[r] = pars[0] + exp(x_t[r]);
264 }
else if (tfun ==
"log10") {
266 for (Index r = jis[i][0]; r <= jis[i][1]; ++r) {
267 x_t[r] = pars[0] + pow(10.0, x_t[r]);
269 }
else if (tfun ==
"atanh") {
271 for (Index r = jis[i][0]; r <= jis[i][1]; ++r) {
272 x_t[r] = pars[0] + ((pars[1] - pars[0]) / 2) * (1 + tanh(x_t[r]));
287 ConstMatrixView diy_dq,
289 for (Index irow = 0; irow < diy_dx.nrows(); irow++) {
290 for (Index icol = 0; icol < diy_dx.ncols(); icol++) {
291 diy_dx(irow, icol) +=
w * diy_dq(irow, icol);
298 ConstTensor3View diy_dpath,
299 const Index& atmosphere_dim,
301 ConstVectorView ppath_p) {
302 ARTS_ASSERT(jacobian_quantity.
Grids().nelem() == atmosphere_dim or jacobian_quantity.
Grids().empty());
306 const Numeric extpolfac = 1.0e99;
311 Index nr1 = jacobian_quantity.
Grids().empty() ? 0 : jacobian_quantity.
Grids()[0].nelem();
314 p2gridpos(gp_p, jacobian_quantity.
Grids()[0], ppath_p, extpolfac);
323 if (atmosphere_dim > 1) {
324 gp_lat.resize(ppath.
np);
325 nr2 = jacobian_quantity.
Grids().empty() ? 0 : jacobian_quantity.
Grids()[1].nelem();
328 jacobian_quantity.
Grids()[1],
339 if (atmosphere_dim > 2) {
340 Index nr3 = jacobian_quantity.
Grids().empty() ? 0 : jacobian_quantity.
Grids()[2].nelem();
341 gp_lon.resize(ppath.
np);
344 jacobian_quantity.
Grids()[2],
354 if (atmosphere_dim == 1) {
355 for (Index ip = 0; ip < ppath.
np; ip++) {
356 if (gp_p[ip].fd[1] > 0) {
358 diy_dpath(ip, joker, joker),
361 if (gp_p[ip].fd[0] > 0) {
363 diy_dpath(ip, joker, joker),
370 else if (atmosphere_dim == 2) {
371 for (Index ip = 0; ip < ppath.
np; ip++) {
372 Index ix = nr1 * gp_lat[ip].idx + gp_p[ip].idx;
374 if (gp_lat[ip].fd[1] > 0 && gp_p[ip].fd[1] > 0)
376 diy_dpath(ip, joker, joker),
377 gp_lat[ip].fd[1] * gp_p[ip].fd[1]);
379 if (gp_lat[ip].fd[1] > 0 && gp_p[ip].fd[0] > 0)
381 diy_dpath(ip, joker, joker),
382 gp_lat[ip].fd[1] * gp_p[ip].fd[0]);
384 if (gp_lat[ip].fd[0] > 0 && gp_p[ip].fd[1] > 0)
386 diy_dpath(ip, joker, joker),
387 gp_lat[ip].fd[0] * gp_p[ip].fd[1]);
389 if (gp_lat[ip].fd[0] > 0 && gp_p[ip].fd[0] > 0)
391 diy_dpath(ip, joker, joker),
392 gp_lat[ip].fd[0] * gp_p[ip].fd[0]);
397 else if (atmosphere_dim == 3) {
398 for (Index ip = 0; ip < ppath.
np; ip++) {
400 nr2 * nr1 * gp_lon[ip].idx + nr1 * gp_lat[ip].idx + gp_p[ip].idx;
402 if (gp_lon[ip].fd[1] > 0 && gp_lat[ip].fd[1] > 0 && gp_p[ip].fd[1] > 0)
404 diy_dx(ix, joker, joker),
405 diy_dpath(ip, joker, joker),
406 gp_lon[ip].fd[1] * gp_lat[ip].fd[1] * gp_p[ip].fd[1]);
408 if (gp_lon[ip].fd[1] > 0 && gp_lat[ip].fd[1] > 0 && gp_p[ip].fd[0] > 0)
410 diy_dx(ix + 1, joker, joker),
411 diy_dpath(ip, joker, joker),
412 gp_lon[ip].fd[1] * gp_lat[ip].fd[1] * gp_p[ip].fd[0]);
414 if (gp_lon[ip].fd[1] > 0 && gp_lat[ip].fd[0] > 0 && gp_p[ip].fd[1] > 0)
416 diy_dx(ix + nr1, joker, joker),
417 diy_dpath(ip, joker, joker),
418 gp_lon[ip].fd[1] * gp_lat[ip].fd[0] * gp_p[ip].fd[1]);
420 if (gp_lon[ip].fd[1] > 0 && gp_lat[ip].fd[0] > 0 && gp_p[ip].fd[0] > 0)
422 diy_dx(ix + nr1 + 1, joker, joker),
423 diy_dpath(ip, joker, joker),
424 gp_lon[ip].fd[1] * gp_lat[ip].fd[0] * gp_p[ip].fd[0]);
430 if (gp_lon[ip].fd[0] > 0 && gp_lat[ip].fd[1] > 0 && gp_p[ip].fd[1] > 0)
432 diy_dx(ix, joker, joker),
433 diy_dpath(ip, joker, joker),
434 gp_lon[ip].fd[0] * gp_lat[ip].fd[1] * gp_p[ip].fd[1]);
436 if (gp_lon[ip].fd[0] > 0 && gp_lat[ip].fd[1] > 0 && gp_p[ip].fd[0] > 0)
438 diy_dx(ix + 1, joker, joker),
439 diy_dpath(ip, joker, joker),
440 gp_lon[ip].fd[0] * gp_lat[ip].fd[1] * gp_p[ip].fd[0]);
442 if (gp_lon[ip].fd[0] > 0 && gp_lat[ip].fd[0] > 0 && gp_p[ip].fd[1] > 0)
444 diy_dx(ix + nr1, joker, joker),
445 diy_dpath(ip, joker, joker),
446 gp_lon[ip].fd[0] * gp_lat[ip].fd[0] * gp_p[ip].fd[1]);
448 if (gp_lon[ip].fd[0] > 0 && gp_lat[ip].fd[0] > 0 && gp_p[ip].fd[0] > 0)
450 diy_dx(ix + nr1 + 1, joker, joker),
451 diy_dpath(ip, joker, joker),
452 gp_lon[ip].fd[0] * gp_lat[ip].fd[0] * gp_p[ip].fd[0]);
460 ConstMatrixView diy_dpos,
461 const Index& atmosphere_dim,
462 ConstVectorView rtp_pos) {
464 max(atmosphere_dim - 1, Index(1)));
469 const Numeric extpolfac = 1.0e99;
472 if (atmosphere_dim == 1) {
473 diy_dx(0, joker, joker) = diy_dpos;
482 nr1 = jacobian_quantity.
Grids()[0].nelem();
485 jacobian_quantity.
Grids()[0],
486 Vector(1, rtp_pos[1]),
496 if (atmosphere_dim > 2) {
498 if (jacobian_quantity.
Grids()[1].nelem() > 1) {
500 jacobian_quantity.
Grids()[1],
501 Vector(1, rtp_pos[2]),
510 if (atmosphere_dim == 2) {
511 if (gp_lat[0].fd[1] > 0) {
513 diy_dpos(joker, joker),
516 if (gp_lat[0].fd[0] > 0) {
518 diy_dpos(joker, joker),
524 Index ix = nr1 * gp_lon[0].idx + gp_lat[0].idx;
526 if (gp_lon[0].fd[1] > 0 && gp_lat[0].fd[1] > 0)
528 diy_dpos(joker, joker),
529 gp_lon[0].fd[1] * gp_lat[0].fd[1]);
531 if (gp_lon[0].fd[1] > 0 && gp_lat[0].fd[0] > 0)
533 diy_dpos(joker, joker),
534 gp_lon[0].fd[1] * gp_lat[0].fd[0]);
536 if (gp_lon[0].fd[0] > 0 && gp_lat[0].fd[1] > 0)
538 diy_dpos(joker, joker),
539 gp_lon[0].fd[0] * gp_lat[0].fd[1]);
541 if (gp_lon[0].fd[0] > 0 && gp_lat[0].fd[0] > 0)
543 diy_dpos(joker, joker),
544 gp_lon[0].fd[0] * gp_lat[0].fd[0]);
553 if (jacobian_quantities[iq] == Jacobian::Line::VMR) {
554 auto p = std::find_if(abs_species.cbegin(), abs_species.cend(),
555 [qid=jacobian_quantities[iq].QuantumIdentity()](
auto& specs){
556 return std::any_of(specs.cbegin(), specs.cend(),
557 [qid](auto& spec){return qid.Isotopologue() == spec.Isotopologue();});
559 if (p not_eq abs_species.cend()) {
560 aoi[iq] = Index(abs_species.cend() - p);
564 jacobian_quantities[iq].Subtag(),
565 " in species of abs_species.\n")
567 }
else if (jacobian_quantities[iq] == Jacobian::Special::ArrayOfSpeciesTagVMR) {
569 aoi[iq] =
chk_contains(
"abs_species", abs_species, atag);
570 }
else if (jacobian_quantities[iq] == Jacobian::Atm::Particulates) {
572 }
else if (jacobian_quantities[iq] == Jacobian::Atm::Electrons) {
581 ArrayOfTensor3 diy_dpath(jacobian_quantities.
nelem());
583 const Index nn = active ? np * nf : nf;
590 ArrayOfTensor3 diy_dx(jacobian_quantities.
nelem());
596 const Index nn = active ? np * nf : nf;
604 const bool cloudbox_on) {
608 if (cloudbox_on and jacobian_quantities[iq] == Jacobian::Special::ScatteringString) {
609 aoi[iq] =
find_first(scat_species, jacobian_quantities[iq].Subtag());
611 "Jacobian quantity with index ", iq,
" refers to\n"
612 " ", jacobian_quantities[iq].Subtag(),
613 "\nbut this species could not be found in *scat_species*.")
626 const Vector& p_grid,
627 const Vector& lat_grid,
628 const Vector& lon_grid,
629 const Vector& p_retr,
630 const Vector& lat_retr,
631 const Vector& lon_retr,
632 const String& p_retr_name,
633 const String& lat_retr_name,
634 const String& lon_retr_name,
638 if (p_retr.nelem() == 0) {
639 os <<
"The grid vector *" << p_retr_name <<
"* is empty,"
640 <<
" at least one pressure level\n"
641 <<
"should be specified.";
643 }
else if (!is_decreasing(p_retr)) {
644 os <<
"The pressure grid vector *" << p_retr_name <<
"* is not a\n"
645 <<
"strictly decreasing vector, which is required.";
647 }
else if (p_grid.nelem() == 1 and p_grid.nelem() == p_retr.nelem()) {
648 if (p_grid[0] not_eq p_retr[0]) {
649 os <<
"Mismatching 1-long grids for " << p_retr_name;
655 }
else if (log(p_retr[0]) > 1.5 * log(p_grid[0]) - 0.5 * log(p_grid[1]) ||
656 log(p_retr[p_retr.nelem() - 1]) <
657 1.5 * log(p_grid[p_grid.nelem() - 1]) -
658 0.5 * log(p_grid[p_grid.nelem() - 2])) {
659 os <<
"The grid vector *" << p_retr_name <<
"* is not covered by the\n"
660 <<
"corresponding atmospheric grid.";
669 if (lat_retr.nelem() == 0) {
670 os <<
"The grid vector *" << lat_retr_name <<
"* is empty,"
671 <<
" at least one latitude\n"
672 <<
"should be specified for a 2D/3D atmosphere.";
674 }
else if (!is_increasing(lat_retr)) {
675 os <<
"The latitude grid vector *" << lat_retr_name <<
"* is not a\n"
676 <<
"strictly increasing vector, which is required.";
678 }
else if (lat_grid.nelem() == 1 and lat_grid.nelem() == lat_retr.nelem()) {
679 if (lat_grid[0] not_eq lat_retr[0]) {
680 os <<
"Mismatching 1-long grids for " << lat_retr_name;
686 }
else if (lat_retr[0] < 1.5 * lat_grid[0] - 0.5 * lat_grid[1] ||
687 lat_retr[lat_retr.nelem() - 1] >
688 1.5 * lat_grid[lat_grid.nelem() - 1] -
689 0.5 * lat_grid[lat_grid.nelem() - 2]) {
690 os <<
"The grid vector *" << lat_retr_name <<
"* is not covered by the\n"
691 <<
"corresponding atmospheric grid.";
699 if (lon_retr.nelem() == 0) {
700 os <<
"The grid vector *" << lon_retr_name <<
"* is empty,"
701 <<
" at least one longitude\n"
702 <<
"should be specified for a 3D atmosphere.";
704 }
else if (!is_increasing(lon_retr)) {
705 os <<
"The longitude grid vector *" << lon_retr_name <<
"* is not a\n"
706 <<
"strictly increasing vector, which is required.";
708 }
else if (lon_grid.nelem() == 1 and
709 lon_grid.nelem() == lon_retr.nelem()) {
710 if (lon_grid[0] not_eq lon_retr[0]) {
711 os <<
"Mismatching 1-long grids for " << lon_retr_name;
717 }
else if (lon_retr[0] < 1.5 * lon_grid[0] - 0.5 * lon_grid[1] ||
718 lon_retr[lon_retr.nelem() - 1] >
719 1.5 * lon_grid[lon_grid.nelem() - 1] -
720 0.5 * lon_grid[lon_grid.nelem() - 2]) {
721 os <<
"The grid vector *" << lon_retr_name
722 <<
"* is not covered by the\n"
723 <<
"corresponding atmospheric grid.";
736 const Vector& lat_grid,
737 const Vector& lon_grid,
738 const Vector& lat_retr,
739 const Vector& lon_retr,
740 const String& lat_retr_name,
741 const String& lon_retr_name,
753 if (lat_retr.nelem() == 0) {
754 os <<
"The grid vector *" << lat_retr_name <<
"* is empty,"
755 <<
" at least one latitude\n"
756 <<
"should be specified for a 2D/3D atmosphere.";
758 }
else if (!is_increasing(lat_retr)) {
759 os <<
"The latitude grid vector *" << lat_retr_name <<
"* is not a\n"
760 <<
"strictly increasing vector, which is required.";
762 }
else if (lat_grid.nelem() == 1 and lat_grid.nelem() == lat_retr.nelem()) {
763 if (lat_grid[0] not_eq lat_retr[0]) {
764 os <<
"Mismatching 1-long grids for " << lat_retr_name;
770 }
else if (lat_retr[0] < 1.5 * lat_grid[0] - 0.5 * lat_grid[1] ||
771 lat_retr[lat_retr.nelem() - 1] >
772 1.5 * lat_grid[lat_grid.nelem() - 1] -
773 0.5 * lat_grid[lat_grid.nelem() - 2]) {
774 os <<
"The grid vector *" << lat_retr_name <<
"* is not covered by the\n"
775 <<
"corresponding atmospheric grid.";
784 if (lon_retr.nelem() == 0) {
785 os <<
"The grid vector *" << lon_retr_name <<
"* is empty,"
786 <<
" at least one longitude\n"
787 <<
"should be specified for a 3D atmosphere.";
789 }
else if (!is_increasing(lon_retr)) {
790 os <<
"The longitude grid vector *" << lon_retr_name <<
"* is not a\n"
791 <<
"strictly increasing vector, which is required.";
793 }
else if (lon_grid.nelem() == 1 and
794 lon_grid.nelem() == lon_retr.nelem()) {
795 if (lon_grid[0] not_eq lon_retr[0]) {
796 os <<
"Mismatching 1-long grids for " << lon_retr_name;
802 }
else if (lon_retr[0] < 1.5 * lon_grid[0] - 0.5 * lon_grid[1] ||
803 lon_retr[lon_retr.nelem() - 1] >
804 1.5 * lon_grid[lon_grid.nelem() - 1] -
805 0.5 * lon_grid[lon_grid.nelem() - 2]) {
806 os <<
"The grid vector *" << lon_retr_name
807 <<
"* is not covered by the\n"
808 <<
"corresponding atmospheric grid.";
820 for (Index i = 0; i < gp.
nelem(); i++) {
821 if (gp[i].fd[0] < 0) {
824 }
else if (gp[i].fd[0] > 1) {
833 const Index& poly_coeff) {
834 const Index l = x.nelem();
838 if (
b.nelem() != l)
b.resize(l);
840 if (poly_coeff == 0) {
843 const Numeric xmin =
min(x);
844 const Numeric dx = 0.5 * (
max(x) - xmin);
846 for (Index i = 0; i < l; i++) {
847 b[i] = (x[i] - xmin) / dx - 1.0;
848 b[i] = pow(
b[i],
int(poly_coeff));
857 const Index& mblock_index,
858 const Sparse& sensor_response,
860 const Vector& sensor_response_f_grid,
861 const Matrix& sensor_response_dlos_grid,
863 const Index rq_index,
865 bool is_sine_fit =
false;
866 if (rq == Jacobian::Sensor::Polyfit) {
868 }
else if (rq == Jacobian::Sensor::Sinefit) {
872 "Retrieval quantity is neither a polynomial or a sine "
878 const Index nf = sensor_response_f_grid.nelem();
879 const Index npol = sensor_response_pol_grid.
nelem();
880 const Index nlos = sensor_response_dlos_grid.nrows();
887 Numeric period = rq.
Grids()[0][0];
888 for (Index f = 0; f < nf; f++) {
889 Numeric
a = (sensor_response_f_grid[f] - sensor_response_f_grid[0]) * 2 *
895 Numeric poly_coeff = rq.
Grids()[0][0];
897 w, sensor_response_f_grid,
static_cast<Index
>(poly_coeff));
901 ArrayOfVector jg = rq.
Grids();
902 const Index n1 = jg[1].nelem();
903 const Index n2 = jg[2].nelem();
904 const Index n3 = jg[3].nelem();
906 const Index row4 = rowind.offset;
907 Index col4 = jacobian_indices[rq_index][0];
910 col4 += mblock_index * n2 * n1;
913 for (Index l = 0; l < nlos; l++) {
914 const Index row3 = row4 + l * nf * npol;
915 const Index col3 = col4 + l * n1 * (is_sine_fit ? 2 : 1);
917 for (Index f = 0; f < nf; f++) {
918 const Index row2 = row3 + f * npol;
920 for (Index p = 0; p < npol; p++) {
926 y_baseline[row2 + p] += x[col1] * s[f] + x[col1 + 1] *
c[f];
928 y_baseline[row2 + p] +=
w[f] * x[col1];
940 if (unit ==
"rel" || unit ==
"logrel") {
942 }
else if (unit ==
"vmr") {
948 }
else if (unit ==
"nd") {
956 "Allowed options for gas species jacobians are "
957 "\"rel\", \"vmr\" and \"nd\".\nYou have selected: ",
967 if (unit ==
"rel" || unit ==
"logrel") {
969 }
else if (unit ==
"vmr") {
971 }
else if (unit ==
"nd") {
975 "Allowed options for gas species jacobians are "
976 "\"rel\", \"vmr\" and \"nd\".\nYou have selected: ",
986 return t.Target().isWind();
990 return t.Target().isWind() or t.Target().isFrequency();
994 return t == Jacobian::Atm::MagneticMagnitude;
998 return t == Jacobian::Line::NLTE;
1001#define ISLINESHAPETYPE(X) \
1002 bool is_pressure_broadening_##X(const RetrievalQuantity& t) noexcept { \
1003 return t == Jacobian::Line::Shape##X##X0 or \
1004 t == Jacobian::Line::Shape##X##X1 or \
1005 t == Jacobian::Line::Shape##X##X2 or \
1006 t == Jacobian::Line::Shape##X##X3; \
1017#undef ISLINESHAPETYPE
1019#define VARISLINESHAPEPARAM(X, Y) (t == Jacobian::Line::Shape##X##Y)
1051#undef VARISLINESHAPEPARAM
1069 return t == Jacobian::Type::Line;
1073 return std::any_of(js.cbegin(), js.cend(), [](
auto& j){return (j == Jacobian::Atm::Temperature or j == Jacobian::Special::ArrayOfSpeciesTagVMR or j == Jacobian::Line::VMR or is_frequency_parameter(j));});
1077 return std::any_of(js.cbegin(), js.cend(), [](
auto& j){return (j == Jacobian::Atm::Temperature or j == Jacobian::Line::VMR or j == Jacobian::Special::ArrayOfSpeciesTagVMR or is_frequency_parameter(j));});
1081 ARTS_USER_ERROR_IF (std::any_of(js.cbegin(), js.cend(), [](
auto& j){return is_line_parameter(j);}),
1082 "Line specific parameters are not supported while using continuum tags.\nWe do not track what lines are in the continuum.\n")
1083 return std::any_of(js.cbegin(), js.cend(), [](
auto& j){return (j == Jacobian::Atm::Temperature or j == Jacobian::Special::ArrayOfSpeciesTagVMR or is_frequency_parameter(j));});
1087 ARTS_USER_ERROR_IF (std::any_of(js.cbegin(), js.cend(), [](
auto& j){return is_line_parameter(j);}),
1088 "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")
1089 return std::any_of(js.cbegin(), js.cend(), [](
auto& j){return (j == Jacobian::Atm::Temperature or is_frequency_parameter(j));});
1093 ARTS_USER_ERROR_IF (std::any_of(js.cbegin(), js.cend(), [](
auto& j){return is_line_parameter(j);}),
1094 "Line specific parameters are not supported while using Lookup table.\nWe do not track lines in the Lookup.\n")
1095 return std::any_of(js.cbegin(), js.cend(), [](
auto& j){return (j == Jacobian::Atm::Temperature or j == Jacobian::Special::ArrayOfSpeciesTagVMR or is_frequency_parameter(j));});
1099 return std::any_of(js.cbegin(), js.cend(), [](
auto& j){return not (j == Jacobian::Type::Sensor);});
1103 if (rq == Jacobian::Line::VMR) {
1104 for (
auto& st : ast) {
1134 return std::any_of(js.cbegin(), js.cend(), [](
auto& j){return j == Jacobian::Atm::Temperature;});
1139 auto p = std::find_if(js.cbegin(), js.cend(), [&line_qid](
auto& j) {
1140 return j == Jacobian::Line::VMR
1141 and j.QuantumIdentity().Species() == line_qid.Species()
1142 and j.QuantumIdentity().Isotopologue() == line_qid.Isotopologue();}
1144 if (p not_eq js.cend())
1145 return {
true, p -> QuantumIdentity()};
1147 return {
false, line_qid};
1151 return std::any_of(js.cbegin(), js.cend(), [](
auto& j){return j == Jacobian::Line::Center;});
1155 return std::any_of(js.cbegin(), js.cend(), [](
auto& j){return is_wind_parameter(j);});
1159 return std::any_of(js.cbegin(), js.cend(), [](
auto& j){return is_frequency_parameter(j);});
1163 return std::any_of(js.cbegin(), js.cend(), [](
auto& j){return j.is_mag();});
1167 auto p = std::find_if(js.cbegin(), js.cend(), [](
auto& j){return j == Jacobian::Atm::Temperature;});
1168 if (p not_eq js.cend())
1169 return p -> Target().perturbation;
1171 return std::numeric_limits<Numeric>::quiet_NaN();
1175 auto p = std::find_if(js.cbegin(), js.cend(), [](
auto& j){return is_frequency_parameter(j);});
1176 if (p not_eq js.cend())
1177 return p -> Target().perturbation;
1179 return std::numeric_limits<Numeric>::quiet_NaN();
1183 auto p = std::find_if(js.cbegin(), js.cend(), [](
auto& j){return j.is_mag();});
1184 if (p not_eq js.cend())
1185 return p -> Target().perturbation;
1187 return std::numeric_limits<Numeric>::quiet_NaN();
Array< Index > ArrayOfIndex
An array of Index.
Index find_first(const Array< base > &x, const base &w)
Find first occurance.
base max(const Array< base > &x)
Max function.
base min(const Array< base > &x)
Min function.
The global header file for ARTS.
Constants of physical expressions as constexpr.
TimeStep mean(const ArrayOfTimeStep &dt)
Returns the mean time step.
Index nelem() const ARTS_NOEXCEPT
Deals with internal derivatives, Jacobian definition, and OEM calculations.
const Matrix & TransformationMatrix() const
const String & Mode() const
Returns the mode.
const String & TransformationFunc() const
Index nelem() const
Number of elements in the grids.
const Vector & TFuncParameters() const
const Vector & OffsetVector() const
Jacobian::Target & Target()
Get the Jacobian Target.
const QuantumIdentifier & QuantumIdentity() const
Returns the identity of this Jacobian.
const ArrayOfVector & Grids() const
Returns the grids of the retrieval.
const String & Subtag() const
Returns the sub-tag.
void mult(MatrixView C, ConstMatrixView A, const Block &B)
#define ARTS_ASSERT(condition,...)
#define ARTS_USER_ERROR(...)
#define ARTS_USER_ERROR_IF(condition,...)
void gridpos(ArrayOfGridPos &gp, ConstVectorView old_grid, ConstVectorView new_grid, const Numeric &extpolfac)
Set up a grid position Array.
void gp4length1grid(ArrayOfGridPos &gp)
Grid position matching a grid of length 1.
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.
bool species_iso_match(const RetrievalQuantity &rq, const Species::IsotopeRecord &ir)
Returns if the Retrieval quantity is VMR derivative for all the species in the species tags.
ArrayOfIndex get_pointers_for_analytical_species(const ArrayOfRetrievalQuantity &jacobian_quantities, const ArrayOfArrayOfSpeciesTag &abs_species)
Help function for analytical jacobian calculations.
void vmrunitscf(Numeric &x, const String &unit, const Numeric &vmr, const Numeric &p, const Numeric &t)
Scale factor for conversion between gas species units.
#define VARISLINESHAPEPARAM(X, Y)
bool supports_propmat_clearsky(const ArrayOfRetrievalQuantity &js)
Returns if the array supports propagation matrix derivatives.
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
bool do_line_center_jacobian(const ArrayOfRetrievalQuantity &js) noexcept
Returns if the array wants a line center derivative.
ArrayOfTensor3 get_standard_starting_diy_dx(const ArrayOfRetrievalQuantity &jacobian_quantities, Index np, Index nf, Index ns, bool active)
Help function for analytical jacobian calculations.
void polynomial_basis_func(Vector &b, const Vector &x, const Index &poly_coeff)
Calculates polynomial basis functions.
bool supports_CIA(const ArrayOfRetrievalQuantity &js)
Returns if the array supports CIA derivatives.
void transform_jacobian(Matrix &jacobian, const Vector x, const ArrayOfRetrievalQuantity &jqs)
Applies both functional and affine transformations.
bool is_wind_parameter(const RetrievalQuantity &t) noexcept
Returns if the Retrieval quantity is a wind parameter in propagation matrix calculations.
bool is_lineshape_parameter_X3(const RetrievalQuantity &t) noexcept
bool is_lineshape_parameter_X1(const RetrievalQuantity &t) noexcept
Returns if the Retrieval quantity is a X1 derivative.
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.
bool supports_relaxation_matrix(const ArrayOfRetrievalQuantity &js)
Returns if the array supports relaxation matrix derivatives.
bool do_frequency_jacobian(const ArrayOfRetrievalQuantity &js) noexcept
Returns if the array wants a frequency derivative.
bool is_derived_magnetic_parameter(const RetrievalQuantity &t) noexcept
Returns if the Retrieval quantity is a derived magnetic parameter.
bool supports_continuum(const ArrayOfRetrievalQuantity &js)
Returns if the array supports continuum derivatives.
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.
bool do_magnetic_jacobian(const ArrayOfRetrievalQuantity &js) noexcept
Returns if the array wants a magnetic derivative.
bool do_temperature_jacobian(const ArrayOfRetrievalQuantity &js) noexcept
Returns if the array wants the temperature derivative.
#define ISLINESHAPETYPE(X)
ArrayOfTensor3 get_standard_diy_dpath(const ArrayOfRetrievalQuantity &jacobian_quantities, Index np, Index nf, Index ns, bool active)
Help function for analytical jacobian calculations.
bool supports_hitran_xsec(const ArrayOfRetrievalQuantity &js)
Returns if the array supports HITRAN cross-section derivatives.
bool supports_lookup(const ArrayOfRetrievalQuantity &js)
Returns if the array supports lookup table derivatives.
ArrayOfIndex get_pointers_for_scat_species(const ArrayOfRetrievalQuantity &jacobian_quantities, const ArrayOfString &scat_species, const bool cloudbox_on)
Help function for analytical jacobian calculations.
bool is_lineshape_parameter_X2(const RetrievalQuantity &t) noexcept
Returns if the Retrieval quantity is a X2 derivative.
void transform_x_back(Vector &x_t, const ArrayOfRetrievalQuantity &jqs, bool revert_functional_transforms)
Handles back-transformations of the state vector.
Numeric magnetic_field_perturbation(const ArrayOfRetrievalQuantity &js) noexcept
Returns the magnetic field perturbation if it exists.
constexpr Numeric NAT_LOG_TEN
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.
bool is_nlte_parameter(const RetrievalQuantity &t) noexcept
Returns if the Retrieval quantity is a NLTE parameter.
bool do_wind_jacobian(const ArrayOfRetrievalQuantity &js) noexcept
Returns if the array wants a wind-based frequency derivative derivative.
bool is_frequency_parameter(const RetrievalQuantity &t) noexcept
Returns if the Retrieval quantity is a frequency parameter in propagation matrix calculations.
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.
Numeric temperature_perturbation(const ArrayOfRetrievalQuantity &js) noexcept
Returns the temperature perturbation if it exists.
jacobianVMRcheck do_vmr_jacobian(const ArrayOfRetrievalQuantity &js, const QuantumIdentifier &line_qid) noexcept
Returns the required info for VMR Jacobian.
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.
Numeric frequency_perturbation(const ArrayOfRetrievalQuantity &js) noexcept
Returns the frequency perturbation if it exists.
void from_dpath_to_dx(MatrixView diy_dx, ConstMatrixView diy_dq, const Numeric &w)
void jacobian_type_extrapol(ArrayOfGridPos &gp)
Adopts grid positions to extrapolation used for jacobians.
bool is_lineshape_parameter_X0(const RetrievalQuantity &t) noexcept
Returns if the Retrieval quantity is a X0 derivative.
void transform_x(Vector &x, const ArrayOfRetrievalQuantity &jqs)
Handles transformations of the state vector.
ostream & operator<<(ostream &os, const RetrievalQuantity &ot)
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.
bool is_lineshape_parameter_bar_linemixing(const RetrievalQuantity &t) noexcept
Returns if the Retrieval quantity is a G0, D0, G2, D2, ETA, FVC derivative.
bool is_line_parameter(const RetrievalQuantity &t) noexcept
Returns if the Retrieval quantity is related to the absorption line.
Routines for setting up the jacobian.
bool is_pressure_broadening_D0(const RetrievalQuantity &t) noexcept
Returns if the Retrieval quantity is a D0 derivative.
bool is_pressure_broadening_Y(const RetrievalQuantity &t) noexcept
Returns if the Retrieval quantity is a Y derivative.
bool is_pressure_broadening_DV(const RetrievalQuantity &t) noexcept
Returns if the Retrieval quantity is a DV derivative.
bool is_pressure_broadening_G0(const RetrievalQuantity &t) noexcept
Returns if the Retrieval quantity is a G0 derivative.
bool is_pressure_broadening_FVC(const RetrievalQuantity &t) noexcept
Returns if the Retrieval quantity is a FVC derivative.
bool is_pressure_broadening_D2(const RetrievalQuantity &t) noexcept
Returns if the Retrieval quantity is a D2 derivative.
bool is_pressure_broadening_G(const RetrievalQuantity &t) noexcept
Returns if the Retrieval quantity is a G derivative.
bool is_pressure_broadening_G2(const RetrievalQuantity &t) noexcept
Returns if the Retrieval quantity is a G0 derivative.
bool is_pressure_broadening_ETA(const RetrievalQuantity &t) noexcept
Returns if the Retrieval quantity is a ETA derivative.
#define FOR_ANALYTICAL_JACOBIANS_DO2(what_to_do)
#define FOR_ANALYTICAL_JACOBIANS_DO(what_to_do)
constexpr Numeric pi
The following mathematical constants are generated in python Decimal package by the code:
constexpr Numeric ln_10
Natural logarithm of 10.
std::ostream & operator<<(std::ostream &os, const Target &x)
constexpr std::string_view Joker
This file contains declerations of functions of physical character.
constexpr Numeric number_density(Numeric p, Numeric t) noexcept
number_density
Range get_rowindex_for_mblock(const Sparse &sensor_response, const Index &mblock_index)
Returns the "range" of y corresponding to a measurement block.
Declaration of functions in rte.cc.
void p2gridpos(ArrayOfGridPos &gp, ConstVectorView old_pgrid, ConstVectorView new_pgrid, const Numeric &extpolfac)
Calculates grid positions for pressure values.
Header file for special_interp.cc.
Holds all information required for individual partial derivatives.
Numeric perturbation
Perturbations for methods where theoretical computations are impossible or plain slow.
String string_id
ID for some of the Special types of partial derivatives.
bool needArrayOfSpeciesTag() const noexcept
Does this type need the ArrayOfSpeciesTag?
Line line
Type of line quantity.
ArrayOfSpeciesTag species_array_id
ID for some of the Special types of partial derivatives.
std::string_view TargetType() const noexcept
Return type as string.
Sensor sensor
Type of sensor quantity.
Atm atm
Type of atm quantity.
bool needString() const noexcept
Does this type need the String?
QuantumIdentifier qid
ID for the Line types of partial derivatives.
bool needQuantumIdentity() const noexcept
Does this type need the QuantumIdentifier?
Special special
Type of special quantity.
The structure to describe a propagation path and releated quantities.
Index np
Number of points describing the ppath.
Matrix pos
The distance between start pos and the last position in pos.
A logical struct for global quantum numbers with species identifiers.
Species::Species Species() const noexcept
Species::IsotopeRecord Isotopologue() const noexcept
Struct containing all information needed about one isotope.
Species spec
Species type as defined in species.h.
std::string_view isotname
A custom name that is unique for this Species type.
Deals with whether or not we should do a VMR derivative.