76 const String& bulkprop_name,
81 if (bulkprop_name ==
"ALL") {
86 if (particle_bulkprop_names[
i] == bulkprop_name) {
93 os <<
"Could not find " << bulkprop_name
94 <<
" in particle_bulkprop_names.\n";
95 throw std::runtime_error(os.
str());
99 Tensor4Clip(particle_bulkprop_field, iq, limit_low, limit_high);
110 if (species ==
"ALL") {
122 os <<
"Could not find " << species <<
" in abs_species.\n";
123 throw std::runtime_error(os.
str());
140 if (ijq < -1)
throw runtime_error(
"Argument *ijq* must be >= -1.");
143 os <<
"Argument *ijq* is too high.\n" 144 <<
"You have selected index: " << ijq <<
"\n" 145 <<
"but the number of quantities is only: " << nq <<
"\n" 146 <<
"(Note that zero-based indexing is used)\n";
147 throw runtime_error(os.
str());
163 if (!std::isinf(limit_low)) {
164 for (
Index i = ifirst;
i <= ilast;
i++) {
165 if (x[
i] < limit_low) x[
i] = limit_low;
168 if (!std::isinf(limit_high)) {
169 for (
Index i = ifirst;
i <= ilast;
i++) {
170 if (x[
i] > limit_high) x[
i] = limit_high;
179 const Index& atmfields_checked,
180 const Index& atmgeom_checked,
181 const Index& atmosphere_dim,
188 const Index& cloudbox_on,
189 const Index& cloudbox_checked,
190 const Tensor4& particle_bulkprop_field,
198 const Tensor3& surface_props_data,
200 const Agenda& water_p_eq_agenda,
204 if (atmfields_checked != 1)
206 "The atmospheric fields must be flagged to have " 207 "passed a consistency check (atmfields_checked=1).");
208 if (atmgeom_checked != 1)
210 "The atmospheric geometry must be flagged to have " 211 "passed a consistency check (atmgeom_checked=1).");
212 if (cloudbox_checked != 1)
214 "The cloudbox must be flagged to have " 215 "passed a consistency check (cloudbox_checked=1).");
227 xa.
resize(ji[nq - 1][1] + 1);
232 const Index np = ji[
q][1] - ji[
q][0] + 1;
236 if (jacobian_quantities[q].MainTag() == TEMPERATURE_MAINTAG) {
242 jacobian_quantities[q],
253 else if (jacobian_quantities[q].MainTag() == ABSSPECIES_MAINTAG) {
259 if (jacobian_quantities[q].Mode() ==
"rel") {
268 jacobian_quantities[q],
281 if (jacobian_quantities[q].Mode() ==
"vmr") {
282 flat(xa[ind], vmr_x);
283 }
else if (jacobian_quantities[q].Mode() ==
"nd") {
287 t_x, atmosphere_dim, t_field, gp_p, gp_lat, gp_lon);
290 for (
Index i3 = 0; i3 < vmr_x.
ncols(); i3++) {
291 for (
Index i2 = 0; i2 < vmr_x.
nrows(); i2++) {
301 }
else if (jacobian_quantities[q].Mode() ==
"rh") {
305 t_x, atmosphere_dim, t_field, gp_p, gp_lat, gp_lon);
310 for (
Index i3 = 0; i3 < vmr_x.
ncols(); i3++) {
311 for (
Index i2 = 0; i2 < vmr_x.
nrows(); i2++) {
313 xa[ji[
q][0] +
i] = vmr_x(i1, i2, i3) *
314 jacobian_quantities[
q].Grids()[0][i1] /
315 water_p_eq(i1, i2, i3);
320 }
else if (jacobian_quantities[q].Mode() ==
"q") {
325 for (
Index i3 = 0; i3 < vmr_x.
ncols(); i3++) {
326 for (
Index i2 = 0; i2 < vmr_x.
nrows(); i2++) {
329 vmr_x(i1, i2, i3) * jacobian_quantities[
q].Grids()[0][i1];
331 0.622 * e / (jacobian_quantities[
q].Grids()[0][i1] - e);
332 xa[ji[
q][0] +
i] = r / (1 +
r);
344 else if (jacobian_quantities[q].MainTag() == SCATSPECIES_MAINTAG) {
346 if (particle_bulkprop_field.
empty()) {
348 "One jacobian quantity belongs to the " 349 "scattering species category, but *particle_bulkprop_field* " 352 if (particle_bulkprop_field.
nbooks() !=
353 particle_bulkprop_names.
nelem()) {
355 "Mismatch in size between " 356 "*particle_bulkprop_field* and *particle_bulkprop_names*.");
360 jacobian_quantities[q].SubSubtag());
363 os <<
"Jacobian quantity with index " << q <<
" covers a " 364 <<
"scattering species, and the field quantity is set to \"" 365 << jacobian_quantities[
q].SubSubtag() <<
"\", but this quantity " 366 <<
"could not found in *particle_bulkprop_names*.";
367 throw runtime_error(os.
str());
374 jacobian_quantities[q],
386 flat(xa[ind], pbp_x);
393 else if (jacobian_quantities[q].MainTag() == WIND_MAINTAG) {
395 if (jacobian_quantities[q].Subtag() ==
"v") {
396 source_field = wind_v_field;
397 }
else if (jacobian_quantities[q].Subtag() ==
"w") {
398 source_field = wind_w_field;
407 jacobian_quantities[q],
415 wind_x, atmosphere_dim, source_field, gp_p, gp_lat, gp_lon);
416 flat(xa[ind], wind_x);
420 else if (jacobian_quantities[q].MainTag() == MAGFIELD_MAINTAG) {
421 if (jacobian_quantities[q].Subtag() ==
"strength") {
428 jacobian_quantities[q],
437 mag_u, atmosphere_dim, mag_u_field, gp_p, gp_lat, gp_lon);
439 mag_v, atmosphere_dim, mag_v_field, gp_p, gp_lat, gp_lon);
441 mag_w, atmosphere_dim, mag_w_field, gp_p, gp_lat, gp_lon);
447 mag_x(
i, j, k) = std::hypot(
448 std::hypot(mag_u(
i, j, k), mag_u(
i, j, k)),
450 flat(xa[ind], mag_x);
453 if (jacobian_quantities[q].Subtag() ==
"v") {
454 source_field = mag_v_field;
455 }
else if (jacobian_quantities[q].Subtag() ==
"w") {
456 source_field = mag_w_field;
457 }
else if (jacobian_quantities[q].Subtag() ==
"u") {
459 throw runtime_error(
"Unsupported magnetism type");
467 jacobian_quantities[q],
475 mag_x, atmosphere_dim, source_field, gp_p, gp_lat, gp_lon);
476 flat(xa[ind], mag_x);
481 else if (jacobian_quantities[q].MainTag() == SURFACE_MAINTAG) {
486 surface_props_names);
487 if (surface_props_data.
empty()) {
489 "One jacobian quantity belongs to the " 490 "surface category, but *surface_props_data* is empty.");
494 find_first(surface_props_names, jacobian_quantities[q].Subtag());
497 os <<
"Jacobian quantity with index " << q <<
" covers a " 498 <<
"surface property, and the field Subtag is set to \"" 499 << jacobian_quantities[
q].Subtag() <<
"\", but this quantity " 500 <<
"could not found in *surface_props_names*.";
501 throw runtime_error(os.
str());
507 jacobian_quantities[q],
517 flat(xa[ind], surf_x);
522 else if (jacobian_quantities[q].MainTag() == POINTING_MAINTAG ||
523 jacobian_quantities[q].MainTag() == FREQUENCY_MAINTAG ||
524 jacobian_quantities[q].MainTag() == POLYFIT_MAINTAG ||
525 jacobian_quantities[q].MainTag() == SINEFIT_MAINTAG) {
531 os <<
"Found a retrieval quantity that is not yet handled by\n" 532 <<
"internal retrievals: " << jacobian_quantities[
q].MainTag() << endl;
533 throw runtime_error(os.
str());
545 Tensor4& particle_bulkprop_field,
555 const Index& atmfields_checked,
556 const Index& atmgeom_checked,
557 const Index& atmosphere_dim,
562 const Index& cloudbox_on,
563 const Index& cloudbox_checked,
566 const Agenda& water_p_eq_agenda,
570 if (atmfields_checked != 1)
572 "The atmospheric fields must be flagged to have " 573 "passed a consistency check (atmfields_checked=1).");
574 if (atmgeom_checked != 1)
576 "The atmospheric geometry must be flagged to have " 577 "passed a consistency check (atmgeom_checked=1).");
578 if (cloudbox_checked != 1)
580 "The cloudbox must be flagged to have " 581 "passed a consistency check (cloudbox_checked=1).");
598 if (x_t.
nelem() != ji[nq - 1][1] + 1)
600 "Length of *x* does not match length implied by " 601 "*jacobian_quantities*.");
609 const Index np = ji[
q][1] - ji[
q][0] + 1;
614 if (jacobian_quantities[q].MainTag() == TEMPERATURE_MAINTAG) {
618 Index n_p, n_lat, n_lon;
625 jacobian_quantities[q].Grids(),
632 Tensor3 t_x(n_p, n_lat, n_lon);
635 t_field, atmosphere_dim, t_x, gp_p, gp_lat, gp_lon);
640 else if (jacobian_quantities[q].MainTag() == ABSSPECIES_MAINTAG) {
650 Index n_p, n_lat, n_lon;
657 jacobian_quantities[q].Grids(),
663 Tensor3 t3_x(n_p, n_lat, n_lon);
666 x_field, atmosphere_dim, t3_x, gp_p, gp_lat, gp_lon);
669 if (jacobian_quantities[q].Mode() ==
"rel") {
672 }
else if (jacobian_quantities[q].Mode() ==
"vmr") {
675 }
else if (jacobian_quantities[q].Mode() ==
"nd") {
677 for (
Index i3 = 0; i3 < vmr_field.
ncols(); i3++) {
678 for (
Index i2 = 0; i2 < vmr_field.
nrows(); i2++) {
679 for (
Index i1 = 0; i1 < vmr_field.
npages(); i1++) {
680 vmr_field(isp, i1, i2, i3) =
681 x_field(i1, i2, i3) /
686 }
else if (jacobian_quantities[q].Mode() ==
"rh") {
690 for (
Index i3 = 0; i3 < vmr_field.
ncols(); i3++) {
691 for (
Index i2 = 0; i2 < vmr_field.
nrows(); i2++) {
692 for (
Index i1 = 0; i1 < vmr_field.
npages(); i1++) {
693 vmr_field(isp, i1, i2, i3) =
694 x_field(i1, i2, i3) * water_p_eq(i1, i2, i3) / p_grid[i1];
698 }
else if (jacobian_quantities[q].Mode() ==
"q") {
703 for (
Index i3 = 0; i3 < vmr_field.
ncols(); i3++) {
704 for (
Index i2 = 0; i2 < vmr_field.
nrows(); i2++) {
705 for (
Index i1 = 0; i1 < vmr_field.
npages(); i1++) {
706 const Numeric r = x_field(i1, i2, i3) / (1 - x_field(i1, i2, i3));
707 const Numeric e = r * p_grid[i1] / (0.622 +
r);
708 vmr_field(isp, i1, i2, i3) = e / p_grid[i1];
719 else if (jacobian_quantities[q].MainTag() == SCATSPECIES_MAINTAG) {
722 if (particle_bulkprop_field.
empty()) {
724 "One jacobian quantity belongs to the " 725 "scattering species category, but *particle_bulkprop_field* " 728 if (particle_bulkprop_field.
nbooks() !=
729 particle_bulkprop_names.
nelem()) {
731 "Mismatch in size between " 732 "*particle_bulkprop_field* and *particle_bulkprop_field*.");
736 jacobian_quantities[q].SubSubtag());
739 os <<
"Jacobian quantity with index " << q <<
" covers a " 740 <<
"scattering species, and the field quantity is set to \"" 741 << jacobian_quantities[
q].SubSubtag() <<
"\", but this quantity " 742 <<
"could not found in *particle_bulkprop_names*.";
743 throw runtime_error(os.
str());
749 Index n_p, n_lat, n_lon;
756 jacobian_quantities[q].Grids(),
762 Tensor3 pbfield_x(n_p, n_lat, n_lon);
766 pbfield, atmosphere_dim, pbfield_x, gp_p, gp_lat, gp_lon);
773 else if (jacobian_quantities[q].MainTag() == WIND_MAINTAG) {
777 Index n_p, n_lat, n_lon;
784 jacobian_quantities[q].Grids(),
791 Tensor3 wind_x(n_p, n_lat, n_lon);
799 wind_field, atmosphere_dim, wind_x, gp_p, gp_lat, gp_lon);
801 if (jacobian_quantities[q].Subtag() ==
"u") {
802 wind_u_field = wind_field;
803 }
else if (jacobian_quantities[q].Subtag() ==
"v") {
804 wind_v_field = wind_field;
805 }
else if (jacobian_quantities[q].Subtag() ==
"w") {
806 wind_w_field = wind_field;
812 else if (jacobian_quantities[q].MainTag() == MAGFIELD_MAINTAG) {
816 Index n_p, n_lat, n_lon;
823 jacobian_quantities[q].Grids(),
830 Tensor3 mag_x(n_p, n_lat, n_lon);
838 mag_field, atmosphere_dim, mag_x, gp_p, gp_lat, gp_lon);
839 if (jacobian_quantities[q].Subtag() ==
"u") {
840 mag_u_field = mag_field;
841 }
else if (jacobian_quantities[q].Subtag() ==
"v") {
842 mag_v_field = mag_field;
843 }
else if (jacobian_quantities[q].Subtag() ==
"w") {
844 mag_w_field = mag_field;
845 }
else if (jacobian_quantities[q].Subtag() ==
"strength") {
847 for (
Index j = 0; j < n_lat; j++) {
848 for (
Index k = 0; k < n_lon; k++) {
852 std::hypot(mag_u_field(
i, j, k), mag_v_field(
i, j, k)),
853 mag_w_field(
i, j, k));
854 mag_u_field(
i, j, k) *= scale;
855 mag_v_field(
i, j, k) *= scale;
856 mag_w_field(
i, j, k) *= scale;
861 throw runtime_error(
"Unsupported magnetism type");
866 else if (jacobian_quantities[q].MainTag() == SURFACE_MAINTAG) {
871 surface_props_names);
872 if (surface_props_data.
empty()) {
874 "One jacobian quantity belongs to the " 875 "surface category, but *surface_props_data* is empty.");
879 find_first(surface_props_names, jacobian_quantities[q].Subtag());
882 os <<
"Jacobian quantity with index " << q <<
" covers a " 883 <<
"surface property, and the field Subtag is set to \"" 884 << jacobian_quantities[
q].Subtag() <<
"\", but this quantity " 885 <<
"could not found in *surface_props_names*.";
886 throw runtime_error(os.
str());
897 jacobian_quantities[q].Grids(),
902 Matrix surf_x(n_lat, n_lon);
917 Vector& sensor_response_f,
919 Matrix& sensor_response_dlos,
920 Vector& sensor_response_f_grid,
922 Matrix& sensor_response_dlos_grid,
926 const Agenda& sensor_response_agenda,
927 const Index& sensor_checked,
928 const Vector& sensor_time,
932 if (sensor_checked != 1)
934 "The sensor response must be flagged to have " 935 "passed a consistency check (sensor_checked=1).");
952 if (x_t.
nelem() != ji[nq - 1][1] + 1)
954 "Length of *x* does not match length implied by " 955 "*jacobian_quantities*.");
961 bool do_sensor =
false;
966 const Index np = ji[
q][1] - ji[
q][0] + 1;
973 os <<
"Only pointing off-sets treated by *jacobianAddPointingZa* " 974 <<
"are so far handled.";
975 throw runtime_error(os.
str());
978 if (jacobian_quantities[
q].Grids()[0][0] == -1) {
979 if (sensor_los.
nrows() != np)
981 "Mismatch between pointing jacobian and *sensor_los* found.");
984 sensor_los(
i, 0) += x_t[ji[
q][0] +
i];
989 if (sensor_los.
nrows() != sensor_time.
nelem())
991 "Sizes of *sensor_los* and *sensor_time* do not match.");
993 for (
Index c = 0; c < np; c++) {
996 sensor_los(
i, 0) += w[
i] * x_t[ji[
q][0] + c];
1004 else if (jacobian_quantities[
q].MainTag() == FREQUENCY_MAINTAG) {
1005 if (jacobian_quantities[
q].Subtag() == FREQUENCY_SUBTAG_0) {
1007 if (x_t[ji[
q][0]] != 0) {
1009 f_backend += x_t[ji[
q][0]];
1011 }
else if (jacobian_quantities[
q].Subtag() == FREQUENCY_SUBTAG_1) {
1013 if (x_t[ji[
q][0]] != 0) {
1018 f_backend[
i] += w[
i] * x_t[ji[
q][0]];
1028 else if (jacobian_quantities[
q].MainTag() == POLYFIT_MAINTAG ||
1029 jacobian_quantities[
q].MainTag() == SINEFIT_MAINTAG) {
1033 sensor_response_pol_grid.
nelem() *
1034 sensor_response_dlos_grid.
nrows();
1035 y_baseline.
resize(y_size);
1039 for (
Index mb = 0; mb < sensor_los.
nrows(); ++mb) {
1044 sensor_response_pol_grid,
1045 sensor_response_f_grid,
1046 sensor_response_dlos_grid,
1047 jacobian_quantities[
q],
1065 sensor_response_f_grid,
1066 sensor_response_pol,
1067 sensor_response_pol_grid,
1068 sensor_response_dlos,
1069 sensor_response_dlos_grid,
1072 sensor_response_agenda);
1078 throw runtime_error(
"Retrievals of spectroscopic variables not yet handled.");
1097 const Agenda& inversion_iterate_agenda,
1099 const Numeric& max_start_cost,
1101 const Index& max_iter,
1103 const Vector& lm_ga_settings,
1104 const Index& clear_matrices,
1105 const Index& display_progress,
1119 inversion_iterate_agenda,
1124 jacobian_quantities,
1134 oem_diagnostics.
resize(5);
1135 oem_diagnostics = NAN;
1137 if (method ==
"ml" || method ==
"lm" || method ==
"ml_cg" ||
1138 method ==
"lm_cg") {
1139 lm_ga_history.
resize(max_iter + 1);
1140 lm_ga_history = NAN;
1154 if (yf.
nelem() == 0) {
1156 ws, yf, jacobian, xa, 1, 0, inversion_iterate_agenda);
1161 os <<
"Mismatch between simulated y and input y.\n";
1162 os <<
"Input y is size " << y.
nelem() <<
" but simulated y is " 1163 << yf.
nelem() <<
"\n";
1164 os <<
"Use your frequency grid vector and your sensor response matrix to match simulations with measurements.\n";
1165 throw std::runtime_error(os.str());
1171 if (method ==
"ml" || method ==
"lm" || display_progress ||
1172 max_start_cost > 0) {
1176 mult(sdy, covmat_se, dy);
1180 mult(sdx, covmat_sx, dx);
1181 cost_start = dx * sdx + dy * sdy;
1182 cost_start /=
static_cast<Numeric>(m);
1184 oem_diagnostics[1] = cost_start;
1187 if (max_start_cost > 0 && cost_start > max_start_cost) {
1189 oem_diagnostics[0] = 99;
1191 if (display_progress) {
1192 cout <<
"\n No OEM inversion, too high start cost:\n" 1193 <<
" Set limit : " << max_start_cost << endl
1194 <<
" Found value : " << cost_start << endl
1200 bool apply_norm =
false;
1202 if (x_norm.
nelem() ==
n) {
1205 T.diagonal() = x_norm;
1207 T(
i,
i) = x_norm[
i];
1219 &inversion_iterate_agenda);
1222 int oem_verbosity =
static_cast<int>(display_progress);
1224 int return_code = 0;
1227 if (method ==
"li") {
1231 x_oem, y_oem, gn, oem_verbosity, lm_ga_history,
true);
1232 oem_diagnostics[0] =
static_cast<Index>(return_code);
1233 }
else if (method ==
"li_m") {
1237 x_oem, y_oem, gn, oem_verbosity, lm_ga_history,
true);
1238 oem_diagnostics[0] =
static_cast<Index>(return_code);
1239 }
else if (method ==
"li_cg") {
1240 oem::CG cg(T, apply_norm, 1e-10, 0);
1243 x_oem, y_oem, gn, oem_verbosity, lm_ga_history,
true);
1244 oem_diagnostics[0] =
static_cast<Index>(return_code);
1245 }
else if (method ==
"li_cg_m") {
1246 oem::CG cg(T, apply_norm, 1e-10, 0);
1249 x_oem, y_oem, gn, oem_verbosity, lm_ga_history,
true);
1250 oem_diagnostics[0] =
static_cast<Index>(return_code);
1251 }
else if (method ==
"gn") {
1253 oem::GN gn(stop_dx, (
unsigned int)max_iter, s);
1255 x_oem, y_oem, gn, oem_verbosity, lm_ga_history);
1256 oem_diagnostics[0] =
static_cast<Index>(return_code);
1257 }
else if (method ==
"gn_m") {
1259 oem::GN gn(stop_dx, (
unsigned int)max_iter, s);
1261 x_oem, y_oem, gn, oem_verbosity, lm_ga_history);
1262 oem_diagnostics[0] =
static_cast<Index>(return_code);
1263 }
else if (method ==
"gn_cg") {
1264 oem::CG cg(T, apply_norm, 1e-10, 0);
1265 oem::GN_CG gn(stop_dx, (
unsigned int)max_iter, cg);
1267 x_oem, y_oem, gn, oem_verbosity, lm_ga_history);
1268 oem_diagnostics[0] =
static_cast<Index>(return_code);
1269 }
else if (method ==
"gn_cg_m") {
1270 oem::CG cg(T, apply_norm, 1e-10, 0);
1271 oem::GN_CG gn(stop_dx, (
unsigned int)max_iter, cg);
1273 x_oem, y_oem, gn, oem_verbosity, lm_ga_history);
1274 oem_diagnostics[0] =
static_cast<Index>(return_code);
1275 }
else if ((method ==
"lm") || (method ==
"ml")) {
1281 std::make_pair(0, 0),
1282 make_shared<Sparse>(diagonal)));
1286 lm.set_tolerance(stop_dx);
1287 lm.set_maximum_iterations((
unsigned int)max_iter);
1288 lm.set_lambda(lm_ga_settings[0]);
1289 lm.set_lambda_decrease(lm_ga_settings[1]);
1290 lm.set_lambda_increase(lm_ga_settings[2]);
1291 lm.set_lambda_maximum(lm_ga_settings[3]);
1292 lm.set_lambda_threshold(lm_ga_settings[4]);
1293 lm.set_lambda_constraint(lm_ga_settings[5]);
1296 x_oem, y_oem, lm, oem_verbosity, lm_ga_history);
1297 oem_diagnostics[0] =
static_cast<Index>(return_code);
1298 if (lm.get_lambda() > lm.get_lambda_maximum()) {
1299 oem_diagnostics[0] = 2;
1301 }
else if ((method ==
"lm_cg") || (method ==
"ml_cg")) {
1302 oem::CG cg(T, apply_norm, 1e-10, 0);
1308 std::make_pair(0, 0),
1309 make_shared<Sparse>(diagonal)));
1312 lm.set_maximum_iterations((
unsigned int)max_iter);
1313 lm.set_lambda(lm_ga_settings[0]);
1314 lm.set_lambda_decrease(lm_ga_settings[1]);
1315 lm.set_lambda_increase(lm_ga_settings[2]);
1316 lm.set_lambda_threshold(lm_ga_settings[3]);
1317 lm.set_lambda_maximum(lm_ga_settings[4]);
1320 x_oem, y_oem, lm, oem_verbosity, lm_ga_history);
1321 oem_diagnostics[0] =
static_cast<Index>(return_code);
1322 if (lm.get_lambda() > lm.get_lambda_maximum()) {
1323 oem_diagnostics[0] = 2;
1327 oem_diagnostics[2] = oem.cost /
static_cast<Numeric>(m);
1328 oem_diagnostics[3] = oem.cost_y /
static_cast<Numeric>(m);
1329 oem_diagnostics[4] =
static_cast<Numeric>(oem.iterations);
1330 }
catch (
const std::exception& e) {
1331 oem_diagnostics[0] = 9;
1332 oem_diagnostics[2] = oem.cost;
1333 oem_diagnostics[3] = oem.cost_y;
1334 oem_diagnostics[4] =
static_cast<Numeric>(oem.iterations);
1337 for (
auto& s : sv) {
1340 while (std::getline(ss, t)) {
1341 errors.push_back(t.c_str());
1352 if (clear_matrices) {
1355 }
else if (oem_diagnostics[0] <= 2) {
1357 Matrix tmp1(n, m), tmp2(n, n), tmp3(n, n);
1359 mult(tmp2, tmp1, jacobian);
1362 mult(dxdy, tmp3, tmp1);
1375 if ((m == 0) || (
n == 0)) {
1376 throw runtime_error(
1377 "The gain matrix *dxdy* is required to compute the observation error covariance matrix.");
1379 if ((covmat_se.
nrows() != m) || (covmat_se.
ncols() != m)) {
1380 throw runtime_error(
1381 "The covariance matrix covmat_se has invalid dimensions.");
1386 mult(covmat_so, dxdy, tmp1);
1398 throw runtime_error(
1399 "The averaging kernel matrix *dxdy* is required to compute the smoothing error covariance matrix.");
1401 if ((covmat_sx.
nrows() !=
n) || (covmat_sx.
ncols() !=
n)) {
1402 throw runtime_error(
1403 "The covariance matrix *covmat_sx* invalid dimensions.");
1413 mult(covmat_ss, tmp1, tmp2);
1429 if ((m == 0) || (
n == 0))
1430 throw runtime_error(
"The Jacobian matrix is empty.");
1433 os <<
"Matrices have inconsistent sizes.\n" 1434 <<
" Size of gain matrix: " << dxdy.
nrows() <<
" x " << dxdy.
ncols()
1436 <<
" Size of Jacobian: " << jacobian.
nrows() <<
" x " 1437 << jacobian.
ncols() <<
"\n";
1438 throw runtime_error(os.
str());
1442 mult(avk, dxdy, jacobian);
1451 throw runtime_error(
1452 "WSM is not available because ARTS was compiled without " 1460 throw runtime_error(
1461 "WSM is not available because ARTS was compiled without " 1469 throw runtime_error(
1470 "WSM is not available because ARTS was compiled without " 1499 throw runtime_error(
1500 "WSM is not available because ARTS was compiled without " 1505 #if defined(OEM_SUPPORT) && 0 1517 void MPI_Initialize(
Matrix& sensor_los,
1522 MPI_Initialized(&initialized);
1524 MPI_Init(
nullptr,
nullptr);
1529 MPI_Comm_rank(MPI_COMM_WORLD, &rank);
1530 MPI_Comm_size(MPI_COMM_WORLD, &nprocs);
1532 int nmblock = (int)sensor_pos.
nrows();
1533 int mblock_range = nmblock / nprocs;
1534 int mblock_start = mblock_range * rank;
1535 int remainder = nmblock %
std::max(mblock_range, nprocs);
1541 if (rank < remainder) {
1543 mblock_start += rank;
1545 mblock_start += remainder;
1549 Range range =
Range(mblock_start, mblock_range);
1554 tmp_m = sensor_pos(range,
joker);
1557 Vector tmp_v = sensor_time[range];
1558 sensor_time = tmp_v;
1581 const Agenda& inversion_iterate_agenda,
1583 const Numeric& max_start_cost,
1585 const Index& max_iter,
1587 const Vector& lm_ga_settings,
1588 const Index& clear_matrices,
1589 const Index& display_progress,
1600 inversion_iterate_agenda,
1604 jacobian_quantities,
1619 MPI_Initialize(sensor_los, sensor_pos, sensor_time);
1629 ws, tmp, jacobian, xa, 1, inversion_iterate_agenda);
1633 oem_diagnostics.
resize(5);
1634 oem_diagnostics = NAN;
1636 if (method ==
"ml" || method ==
"lm") {
1637 lm_ga_history.
resize(max_iter);
1638 lm_ga_history = NAN;
1646 if (method ==
"ml" || method ==
"lm" || display_progress ||
1647 max_start_cost > 0) {
1650 cost_start = dot(dy, SeInvMPI * dy);
1652 oem_diagnostics[1] = cost_start;
1655 if (max_start_cost > 0 && cost_start > max_start_cost) {
1657 oem_diagnostics[0] = 99;
1659 if (display_progress) {
1660 cout <<
"\n No OEM inversion, too high start cost:\n" 1661 <<
" Set limit : " << max_start_cost << endl
1662 <<
" Found value : " << cost_start << endl
1673 OEMVector xa_oem(xa), y_oem(y), x_oem;
1676 OEM_PS_PS_MPI<AgendaWrapperMPI>
oem(aw, xa_oem, SaInvMPI, SeInvMPI);
1679 int return_value = 99;
1681 if (method ==
"li") {
1683 oem::GN_CG gn(stop_dx, (
unsigned int)max_iter, cg);
1684 return_value = oem.compute<
oem::GN_CG, invlib::MPILog>(
1685 x_oem, y_oem, gn, 2 * (int)display_progress);
1686 }
else if (method ==
"gn") {
1688 oem::GN_CG gn(stop_dx, (
unsigned int)max_iter, cg);
1689 return_value = oem.compute<
oem::GN_CG, invlib::MPILog>(
1690 x_oem, y_oem, gn, 2 * (int)display_progress);
1691 }
else if ((method ==
"lm") || (method ==
"ml")) {
1693 LM_CG_MPI lm(SaInvMPI, cg);
1695 lm.set_tolerance(stop_dx);
1696 lm.set_maximum_iterations((
unsigned int)max_iter);
1697 lm.set_lambda(lm_ga_settings[0]);
1698 lm.set_lambda_decrease(lm_ga_settings[1]);
1699 lm.set_lambda_increase(lm_ga_settings[2]);
1700 lm.set_lambda_threshold(lm_ga_settings[3]);
1701 lm.set_lambda_maximum(lm_ga_settings[4]);
1703 return_value = oem.compute<oem::LM_CG_MPI, invlib::MPILog>(
1704 x_oem, y_oem, lm, 2 * (int)display_progress);
1707 oem_diagnostics[0] = return_value;
1708 oem_diagnostics[2] = oem.cost;
1709 oem_diagnostics[3] = oem.cost_y;
1710 oem_diagnostics[4] =
static_cast<Numeric>(oem.iterations);
1714 if (clear_matrices && (oem_diagnostics[0])) {
1750 throw runtime_error(
1751 "You have to compile ARTS with OEM support " 1752 " and enable MPI to use OEM_MPI.");
1755 #endif // OEM_SUPPORT && ENABLE_MPI
INDEX Index
The type to use for all integer numbers and indices.
invlib::Matrix< invlib::MPIMatrix< invlib::Timer< ArtsCovarianceMatrixWrapper > >> MPICovarianceMatrix
MPI-distributed covariance matrix type.
Index find_first(const Array< base > &x, const base &w)
Find first occurance.
void MatrixFromCovarianceMatrix(Matrix &out, const CovarianceMatrix &in, const Verbosity &verbosity)
WORKSPACE METHOD: MatrixFromCovarianceMatrix.
Index nelem() const
Number of elements.
Vector diagonal() const
Diagonal elements as vector.
invlib::Matrix< ArtsCovarianceMatrixWrapper > CovarianceMatrix
invlib wrapper type for ARTS the ARTS covariance class.
QuantumIdentifier::QType Index LowerQuantumNumbers Species
void vmr_fieldClip(Tensor4 &vmr_field, const ArrayOfArrayOfSpeciesTag &abs_species, const String &species, const Numeric &limit_low, const Numeric &limit_high, const Verbosity &)
WORKSPACE METHOD: vmr_fieldClip.
invlib::MAP< ForwardModel, Matrix, CovarianceMatrix, CovarianceMatrix, Vector, Formulation::MFORM > OEM_MFORM
OEM m form.
void inversion_iterate_agendaExecute(Workspace &ws, Vector &yf, Matrix &jacobian, const Vector &x, const Index jacobian_do, const Index inversion_iteration_counter, const Agenda &input_agenda)
void sensor_response_agendaExecute(Workspace &ws, Sparse &sensor_response, Vector &sensor_response_f, Vector &sensor_response_f_grid, ArrayOfIndex &sensor_response_pol, ArrayOfIndex &sensor_response_pol_grid, Matrix &sensor_response_dlos, Matrix &sensor_response_dlos_grid, Matrix &mblock_dlos_grid, const Vector &f_backend, const Agenda &input_agenda)
Routines for setting up the jacobian.
Index Species() const
Molecular species index.
void regrid_atmfield_by_gp(Tensor3 &field_new, const Index &atmosphere_dim, ConstTensor3View field_old, const ArrayOfGridPos &gp_p, const ArrayOfGridPos &gp_lat, const ArrayOfGridPos &gp_lon)
Regrids an atmospheric field, for precalculated grid positions.
void water_p_eq_agendaExecute(Workspace &ws, Tensor3 &water_p_eq_field, const Tensor3 &t_field, const Agenda &input_agenda)
const String SINEFIT_MAINTAG
Index npages() const
Returns the number of pages.
invlib::Vector< ArtsVector > Vector
invlib wrapper type for ARTS vectors.
cmplx FADDEEVA() w(cmplx z, double relerr)
void avkCalc(Matrix &, const Matrix &, const Matrix &, const Verbosity &)
WORKSPACE METHOD: avkCalc.
bool empty() const
Check if variable is empty.
const String FREQUENCY_SUBTAG_1
Vector inverse_diagonal() const
Diagonal of the inverse of the covariance matrix as vector.
void get_gp_atmgrids_to_rq(ArrayOfGridPos &gp_p, ArrayOfGridPos &gp_lat, ArrayOfGridPos &gp_lon, const RetrievalQuantity &rq, const Index &atmosphere_dim, const Vector &p_grid, const Vector &lat_grid, const Vector &lon_grid)
Determines grid positions for regridding of atmospheric fields to retrieval grids.
Index nrows() const
Returns the number of rows.
void covmat_ssCalc(Matrix &, const Matrix &, const CovarianceMatrix &, const Verbosity &)
WORKSPACE METHOD: covmat_ssCalc.
const String FREQUENCY_SUBTAG_0
Index nrows() const
Returns the number of rows.
Numeric number_density(const Numeric &p, const Numeric &t)
number_density
Index nelem() const
Returns the number of elements.
basic_stringstream< char, string_char_traits< char >, alloc > stringstream
void xaStandard(Workspace &ws, Vector &xa, const ArrayOfRetrievalQuantity &jacobian_quantities, const Index &atmfields_checked, const Index &atmgeom_checked, const Index &atmosphere_dim, const Vector &p_grid, const Vector &lat_grid, const Vector &lon_grid, const Tensor3 &t_field, const Tensor4 &vmr_field, const ArrayOfArrayOfSpeciesTag &abs_species, const Index &cloudbox_on, const Index &cloudbox_checked, const Tensor4 &particle_bulkprop_field, const ArrayOfString &particle_bulkprop_names, const Tensor3 &wind_u_field, const Tensor3 &wind_v_field, const Tensor3 &wind_w_field, const Tensor3 &mag_u_field, const Tensor3 &mag_v_field, const Tensor3 &mag_w_field, const Tensor3 &surface_props_data, const ArrayOfString &surface_props_names, const Agenda &water_p_eq_agenda, const Verbosity &)
WORKSPACE METHOD: xaStandard.
void flat(VectorView x, ConstMatrixView X)
flat
Interface for distributed ARTS forward model.
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.
void x2artsSpectroscopy(const Verbosity &)
WORKSPACE METHOD: x2artsSpectroscopy.
This file contains the definition of Array.
std::vector< std::string > handle_nested_exception(const E &e, int level=0)
Handle exception encountered within invlib.
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. ...
Index ncols() const
Returns the number of columns.
const String WIND_MAINTAG
The global header file for ARTS.
void x2artsAtmAndSurf(Workspace &ws, Tensor4 &vmr_field, Tensor3 &t_field, Tensor4 &particle_bulkprop_field, Tensor3 &wind_u_field, Tensor3 &wind_v_field, Tensor3 &wind_w_field, Tensor3 &mag_u_field, Tensor3 &mag_v_field, Tensor3 &mag_w_field, Tensor3 &surface_props_data, const ArrayOfRetrievalQuantity &jacobian_quantities, const Vector &x, const Index &atmfields_checked, const Index &atmgeom_checked, const Index &atmosphere_dim, const Vector &p_grid, const Vector &lat_grid, const Vector &lon_grid, const ArrayOfArrayOfSpeciesTag &abs_species, const Index &cloudbox_on, const Index &cloudbox_checked, const ArrayOfString &particle_bulkprop_names, const ArrayOfString &surface_props_names, const Agenda &water_p_eq_agenda, const Verbosity &)
WORKSPACE METHOD: x2artsAtmAndSurf.
void reshape(Tensor3View X, ConstVectorView x)
reshape
const String POINTING_SUBTAG_A
invlib::GaussNewton< Numeric, CG > GN_CG
Gauss-Newton (GN) optimization using normed CG solver.
_CS_string_type str() const
Index ncols() const
Returns the number of columns.
void surface_props_check(const Index &atmosphere_dim, const Vector &lat_grid, const Vector &lon_grid, const Tensor3 &surface_props_data, const ArrayOfString &surface_props_names)
Peforms basic checks of surface_props_data and surface_props_names
const String MAGFIELD_MAINTAG
ArtsVector get_measurement_vector()
Return most recently simulated measurement vector.
Interface to ARTS inversion_iterate_agenda.
invlib::LevenbergMarquardt< Numeric, CovarianceMatrix, Std > LM
Levenberg-Marquardt (LM) optimization using normed ARTS QR solver.
A tag group can consist of the sum of several of these.
invlib::GaussNewton< Numeric, Std > GN
OEM Gauss-Newton optimization using normed ARTS QR solver.
void get_gp_rq_to_atmgrids(ArrayOfGridPos &gp_p, ArrayOfGridPos &gp_lat, ArrayOfGridPos &gp_lon, Index &n_p, Index &n_lat, Index &n_lon, const ArrayOfVector &ret_grids, const Index &atmosphere_dim, const Vector &p_grid, const Vector &lat_grid, const Vector &lon_grid)
Determines grid positions for regridding of atmospheric fields to retrieval grids.
const String POINTING_MAINTAG
NUMERIC Numeric
The type to use for all floating point numbers.
void regrid_atmsurf_by_gp_oem(Matrix &field_new, const Index &atmosphere_dim, ConstMatrixView field_old, const ArrayOfGridPos &gp_lat, const ArrayOfGridPos &gp_lon)
Regridding of surface field OEM-type.
void xClip(Vector &x, const ArrayOfRetrievalQuantity &jacobian_quantities, const Index &ijq, const Numeric &limit_low, const Numeric &limit_high, const Verbosity &)
WORKSPACE METHOD: xClip.
invlib::LevenbergMarquardt< Numeric, CovarianceMatrix, CG > LM_CG
Levenberg-Marquardt (LM) optimization using normed CG solver.
Header file for special_interp.cc.
const String POLYFIT_MAINTAG
void mult(ComplexVectorView y, const ConstComplexMatrixView &M, const ConstComplexVectorView &x)
Matrix-Vector Multiplication.
basic_ostringstream< char, string_char_traits< char >, alloc > ostringstream
void regrid_atmfield_by_gp_oem(Tensor3 &field_new, const Index &atmosphere_dim, ConstTensor3View field_old, const ArrayOfGridPos &gp_p, const ArrayOfGridPos &gp_lat, const ArrayOfGridPos &gp_lon)
Regridding of atmospheric field OEM-type.
void transform_x(Vector &x, const ArrayOfRetrievalQuantity &jqs)
Handles transformations of the state vector.
Index npages() const
Returns the number of pages.
This can be used to make arrays out of anything.
ConstComplexMatrixView transpose(ConstComplexMatrixView m)
Const version of transpose.
void compute_inverse() const
Compute the inverse of this correlation matrix.
void OEM(Workspace &, Vector &, Vector &, Matrix &, Matrix &, Vector &, Vector &, ArrayOfString &, const Vector &, const CovarianceMatrix &, const Vector &, const CovarianceMatrix &, const Index &, const ArrayOfRetrievalQuantity &, const ArrayOfArrayOfIndex &, const Agenda &, const String &, const Numeric &, const Vector &, const Index &, const Numeric &, const Vector &, const Index &, const Index &, const Verbosity &)
void Tensor4Clip(Tensor4 &x, const Index &iq, const Numeric &limit_low, const Numeric &limit_high)
Clip Tensor4.
void resize(Index n)
Resize function.
void inv(MatrixView Ainv, ConstMatrixView A)
Matrix Inverse.
bool empty() const
Check if variable is empty.
invlib::MAP< ForwardModel, Matrix, CovarianceMatrix, CovarianceMatrix, Vector, Formulation::STANDARD, invlib::Rodgers531 > OEM_STANDARD
OEM standard form.
void particle_bulkprop_fieldClip(Tensor4 &particle_bulkprop_field, const ArrayOfString &particle_bulkprop_names, const String &bulkprop_name, const Numeric &limit_low, const Numeric &limit_high, const Verbosity &)
WORKSPACE METHOD: particle_bulkprop_fieldClip.
A constant view of a Tensor3.
const String TEMPERATURE_MAINTAG
void x2artsSensor(Workspace &ws, Matrix &sensor_los, Vector &f_backend, Vector &y_baseline, Sparse &sensor_response, Vector &sensor_response_f, ArrayOfIndex &sensor_response_pol, Matrix &sensor_response_dlos, Vector &sensor_response_f_grid, ArrayOfIndex &sensor_response_pol_grid, Matrix &sensor_response_dlos_grid, Matrix &mblock_dlos_grid, const ArrayOfRetrievalQuantity &jacobian_quantities, const Vector &x, const Agenda &sensor_response_agenda, const Index &sensor_checked, const Vector &sensor_time, const Verbosity &)
WORKSPACE METHOD: x2artsSensor.
void OEM_MPI(Workspace &, Vector &, Vector &, Matrix &, Matrix &, Vector &, Vector &, Matrix &, Matrix &, Vector &, CovarianceMatrix &, CovarianceMatrix &, const Vector &, const Vector &, const Index &, const ArrayOfRetrievalQuantity &, const Agenda &, const String &, const Numeric &, const Vector &, const Index &, const Numeric &, const Vector &, const Index &, const Index &, const Verbosity &)
Defines the ARTS interface to the invlib library.
void mult_inv(MatrixView C, ConstMatrixView A, const CovarianceMatrix &B)
void polynomial_basis_func(Vector &b, const Vector &x, const Index &poly_coeff)
Calculates polynomial basis functions.
Index nbooks() const
Returns the number of books.
void OEM_checks(Workspace &ws, Vector &x, Vector &yf, Matrix &jacobian, const Agenda &inversion_iterate_agenda, const Vector &xa, const CovarianceMatrix &covmat_sx, const Vector &y, const CovarianceMatrix &covmat_se, const ArrayOfRetrievalQuantity &jacobian_quantities, const String &method, const Vector &x_norm, const Index &max_iter, const Numeric &stop_dx, const Vector &lm_ga_settings, const Index &clear_matrices, const Index &display_progress)
Error checking for OEM method.
void add_inv(MatrixView A, const CovarianceMatrix &B)
void add_correlation_inverse(Block c)
Add block inverse to covariance matrix.
void id_mat(MatrixView I)
Identity Matrix.
Header file for helper functions for OpenMP.
const String FREQUENCY_MAINTAG
void covmat_soCalc(Matrix &, const Matrix &, const CovarianceMatrix &, const Verbosity &)
WORKSPACE METHOD: covmat_soCalc.
Optimal estimation method for MPI-distributed retrieval.
Index ncols() const
Returns the number of columns.
void transform_x_back(Vector &x_t, const ArrayOfRetrievalQuantity &jqs, bool revert_functional_transforms)
Handles back-transformations of the state vector.
const String ABSSPECIES_MAINTAG
invlib::Matrix< ArtsMatrix > Matrix
invlib wrapper type for ARTS matrices.
const String SURFACE_MAINTAG
This file contains declerations of functions of physical character.
Index nrows() const
Returns the number of rows.
void get_gp_atmsurf_to_rq(ArrayOfGridPos &gp_lat, ArrayOfGridPos &gp_lon, const RetrievalQuantity &rq, const Index &atmosphere_dim, const Vector &lat_grid, const Vector &lon_grid)
Determines grid positions for regridding of atmospheric surfaces to retrieval grids.
invlib::Vector< invlib::MPIVector< invlib::Timer< ArtsVector > >> MPIVector
MPI-distributed vector type.
const String SCATSPECIES_MAINTAG
Declaration of functions in rte.cc.
void resize(Index r, Index c)
Resize function.