ARTS  2.3.1285(git:92a29ea9-dirty)
check_input.cc
Go to the documentation of this file.
1 /* Copyright (C) 2002-2012
2  Patrick Eriksson <patrick.eriksson@chalmers.se>
3  Stefan Buehler <sbuehler@ltu.se>
4 
5  This program is free software; you can redistribute it and/or modify it
6  under the terms of the GNU General Public License as published by the
7  Free Software Foundation; either version 2, or (at your option) any
8  later version.
9 
10  This program is distributed in the hope that it will be useful,
11  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  GNU General Public License for more details.
14 
15  You should have received a copy of the GNU General Public License
16  along with this program; if not, write to the Free Software
17  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
18  USA. */
19 
20 /*===========================================================================
21  === File description
22  ===========================================================================*/
23 
32 /*===========================================================================
33  === External declarations
34  ===========================================================================*/
35 
36 #include "check_input.h"
37 #include <cfloat>
38 #include <cmath>
39 #include <stdexcept>
40 #include "array.h"
41 #include "auto_md.h"
42 #include "gridded_fields.h"
43 #include "logic.h"
44 
45 extern const Index GFIELD3_P_GRID;
46 extern const Index GFIELD3_LAT_GRID;
47 extern const Index GFIELD3_LON_GRID;
48 
49 /*===========================================================================
50  === Functions for Index
51  ===========================================================================*/
52 
54 
65 void chk_if_bool(const String& x_name, const Index& x) {
66  if (!is_bool(x)) {
67  ostringstream os;
68  os << "The variable *" << x_name << "* must be a boolean (0 or 1).\n"
69  << "The present value of *" << x_name << "* is " << x << ".";
70  throw runtime_error(os.str());
71  }
72 }
73 
75 
89 void chk_if_in_range(const String& x_name,
90  const Index& x,
91  const Index& x_low,
92  const Index& x_high) {
93  if ((x < x_low) || (x > x_high)) {
94  ostringstream os;
95  os << "The variable *" << x_name << "* must fulfill:\n"
96  << " " << x_low << " <= " << x_name << " <= " << x_high << "\n"
97  << "The present value of *" << x_name << "* is " << x << ".";
98  throw runtime_error(os.str());
99  }
100 }
101 
103 
117 void chk_if_increasing(const String& x_name, const ArrayOfIndex& x) {
118  if (!is_increasing(x)) {
119  ostringstream os;
120  os << "The ArrayOfIndex *" << x_name << "* must have strictly\n"
121  << "increasing values, but this is not the case.\n";
122  os << "x = " << x << "\n";
123  throw runtime_error(os.str());
124  }
125 }
126 
127 /*===========================================================================
128  === Functions for Numeric
129  ===========================================================================*/
130 
132 
143 void chk_not_negative(const String& x_name, const Numeric& x) {
144  if (x < 0) {
145  ostringstream os;
146  os << "The variable *" << x_name << "* must be >= 0.\n"
147  << "The present value of *" << x_name << "* is " << x << ".";
148  throw runtime_error(os.str());
149  }
150 }
151 
153 
167 void chk_if_in_range(const String& x_name,
168  const Numeric& x,
169  const Numeric& x_low,
170  const Numeric& x_high) {
171  if ((x < x_low) || (x > x_high)) {
172  ostringstream os;
173  os << "The variable *" << x_name << "* must fulfill:\n"
174  << " " << x_low << " <= " << x_name << " <= " << x_high << "\n"
175  << "The present value of *" << x_name << "* is " << x << ".";
176  throw runtime_error(os.str());
177  }
178 }
179 
181 
196  const Numeric& x,
197  const Numeric& x_low,
198  const Numeric& x_high) {
199  if ((x <= x_low) || (x > x_high)) {
200  ostringstream os;
201  os << "The variable *" << x_name << "* must fulfill:\n"
202  << " " << x_low << " < " << x_name << " <= " << x_high << "\n"
203  << "The present value of *" << x_name << "* is " << x << ".";
204  throw runtime_error(os.str());
205  }
206 }
207 
209 
224  const Numeric& x,
225  const Numeric& x_low,
226  const Numeric& x_high) {
227  if ((x < x_low) || (x >= x_high)) {
228  ostringstream os;
229  os << "The variable *" << x_name << "* must fulfill:\n"
230  << " " << x_low << " <= " << x_name << " < " << x_high << "\n"
231  << "The present value of *" << x_name << "* is " << x << ".";
232  throw runtime_error(os.str());
233  }
234 }
235 
237 
251 void chk_if_in_range_exclude(const String& x_name,
252  const Numeric& x,
253  const Numeric& x_low,
254  const Numeric& x_high) {
255  if ((x <= x_low) || (x >= x_high)) {
256  ostringstream os;
257  os << "The variable *" << x_name << "* must fulfill:\n"
258  << " " << x_low << " < " << x_name << " < " << x_high << "\n"
259  << "The present value of *" << x_name << "* is " << x << ".";
260  throw runtime_error(os.str());
261  }
262 }
263 
264 /*===========================================================================
265  === Functions for Vector
266  ===========================================================================*/
267 
269 
281 void chk_vector_length(const String& x_name,
282  ConstVectorView x,
283  const Index& l) {
284  if (x.nelem() != l) {
285  ostringstream os;
286  os << "The vector *" << x_name << "* must have the length " << l << ".\n"
287  << "The present length of *" << x_name << "* is " << x.nelem() << ".";
288  throw runtime_error(os.str());
289  }
290 }
291 
293 
306 void chk_vector_length(const String& x1_name,
307  const String& x2_name,
310  if (x1.nelem() != x2.nelem()) {
311  ostringstream os;
312  os << "The vectors *" << x1_name << "* and *" << x2_name
313  << "* must have the same length.\n"
314  << "The length of *" << x1_name << "* is " << x1.nelem() << ".\n"
315  << "The length of *" << x2_name << "* is " << x2.nelem() << ".";
316  throw runtime_error(os.str());
317  }
318 }
319 
321 
334 void chk_if_increasing(const String& x_name, ConstVectorView x) {
335  if (!is_increasing(x)) {
336  ostringstream os;
337  os << "The vector *" << x_name << "* must have strictly\n"
338  << "increasing values, but this is not the case.\n";
339  os << "x = " << x << "\n";
340  throw runtime_error(os.str());
341  }
342 }
343 
345 
358 void chk_if_decreasing(const String& x_name, ConstVectorView x) {
359  if (!is_decreasing(x)) {
360  ostringstream os;
361  os << "The vector *" << x_name << "* must have strictly\ndecreasing "
362  << "values, but this is not the case.\n";
363  throw runtime_error(os.str());
364  }
365 }
366 
368 
381 void chk_if_equal(const String& x1_name,
382  const String& x2_name,
383  ConstVectorView v1,
384  ConstVectorView v2,
385  Numeric margin) {
386  chk_vector_length(x1_name, x2_name, v1, v2);
387 
388  for (Index i = 0; i < v1.nelem(); i++) {
389  if (abs(v1[i] - v2[i]) > margin) {
390  ostringstream os;
391  os << "Vectors " << x1_name << " and " << x2_name << " differ.\n"
392  << x1_name << "[" << i << "]"
393  << " = " << v1[i] << "\n"
394  << x2_name << "[" << i << "]"
395  << " = " << v2[i] << "\n"
396  << "Difference should not exceed " << margin << "\n";
397  throw runtime_error(os.str());
398  }
399  }
400 }
401 
402 /*===========================================================================
403  === Functions for Matrix
404  ===========================================================================*/
405 
407 
419 void chk_matrix_ncols(const String& x_name, ConstMatrixView x, const Index& l) {
420  if (x.ncols() != l) {
421  ostringstream os;
422  os << "The matrix *" << x_name << "* must have " << l << " columns,\n"
423  << "but the number of columns is " << x.ncols() << ".";
424  throw runtime_error(os.str());
425  }
426 }
427 
429 
441 void chk_matrix_nrows(const String& x_name, ConstMatrixView x, const Index& l) {
442  if (x.nrows() != l) {
443  ostringstream os;
444  os << "The matrix *" << x_name << "* must have " << l << " rows,\n"
445  << "but the number of rows is " << x.nrows() << ".";
446  throw runtime_error(os.str());
447  }
448 }
449 
450 /*===========================================================================
451  === Functions for Tensors
452  ===========================================================================*/
453 
455 
466 void chk_size(const String& x_name, ConstVectorView x, const Index& c) {
467  if (!is_size(x, c)) {
468  ostringstream os;
469  os << "The object *" << x_name << "* does not have the right size.\n"
470  << "Dimension should be:"
471  << " " << c << ",\nbut it is: "
472  << " " << x.nelem() << ".";
473  throw runtime_error(os.str());
474  }
475 }
476 
478 
490 void chk_size(const String& x_name,
491  ConstMatrixView x,
492  const Index& r,
493  const Index& c) {
494  if (!is_size(x, r, c)) {
495  ostringstream os;
496  os << "The object *" << x_name << "* does not have the right size.\n"
497  << "Dimensions should be:"
498  << " " << r << " " << c << ",\nbut they are: "
499  << " " << x.nrows() << " " << x.ncols() << ".";
500  throw runtime_error(os.str());
501  }
502 }
503 
505 
518 void chk_size(const String& x_name,
520  const Index& p,
521  const Index& r,
522  const Index& c) {
523  if (!is_size(x, p, r, c)) {
524  ostringstream os;
525  os << "The object *" << x_name << "* does not have the right size.\n"
526  << "Dimensions should be:"
527  << " " << p << " " << r << " " << c << ",\nbut they are: "
528  << " " << x.npages() << " " << x.nrows() << " " << x.ncols() << ".";
529  throw runtime_error(os.str());
530  }
531 }
532 
534 
548 void chk_size(const String& x_name,
550  const Index& b,
551  const Index& p,
552  const Index& r,
553  const Index& c) {
554  if (!is_size(x, b, p, r, c)) {
555  ostringstream os;
556  os << "The object *" << x_name << "* does not have the right size.\n"
557  << "Dimensions should be:"
558  << " " << b << " " << p << " " << r << " " << c
559  << ",\nbut they are: "
560  << " " << x.nbooks() << " " << x.npages() << " " << x.nrows() << " "
561  << x.ncols() << ".";
562  throw runtime_error(os.str());
563  }
564 }
565 
567 
582 void chk_size(const String& x_name,
584  const Index& s,
585  const Index& b,
586  const Index& p,
587  const Index& r,
588  const Index& c) {
589  if (!is_size(x, s, b, p, r, c)) {
590  ostringstream os;
591  os << "The object *" << x_name << "* does not have the right size.\n"
592  << "Dimensions should be:"
593  << " " << s << " " << b << " " << p << " " << r << " " << c
594  << ",\nbut they are: "
595  << " " << x.nshelves() << " " << x.nbooks() << " " << x.npages() << " "
596  << x.nrows() << " " << x.ncols() << ".";
597  throw runtime_error(os.str());
598  }
599 }
600 
602 
618 void chk_size(const String& x_name,
620  const Index& v,
621  const Index& s,
622  const Index& b,
623  const Index& p,
624  const Index& r,
625  const Index& c) {
626  if (!is_size(x, v, s, b, p, r, c)) {
627  ostringstream os;
628  os << "The object *" << x_name << "* does not have the right size.\n"
629  << "Dimensions should be:"
630  << " " << v << " " << s << " " << b << " " << p << " " << r << " " << c
631  << ",\nbut they are: "
632  << " " << x.nvitrines() << " " << x.nshelves() << " " << x.nbooks()
633  << " " << x.npages() << " " << x.nrows() << " " << x.ncols() << ".";
634  throw runtime_error(os.str());
635  }
636 }
637 
639 
656 void chk_size(const String& x_name,
658  const Index& l,
659  const Index& v,
660  const Index& s,
661  const Index& b,
662  const Index& p,
663  const Index& r,
664  const Index& c) {
665  if (!is_size(x, l, v, s, b, p, r, c)) {
666  ostringstream os;
667  os << "The object *" << x_name << "* does not have the right size.\n"
668  << "Dimensions should be:"
669  << " " << l << " " << v << " " << s << " " << b << " " << p << " " << r
670  << " " << c << ",\nbut they are: "
671  << " " << x.nlibraries() << " " << x.nvitrines() << " " << x.nshelves()
672  << " " << x.nbooks() << " " << x.npages() << " " << x.nrows() << " "
673  << x.ncols() << ".";
674  throw runtime_error(os.str());
675  }
676 }
677 
678 /*===========================================================================
679  === Functions for Agendas
680  ===========================================================================*/
681 
683 
694 void chk_not_empty(const String& x_name, const Agenda& x) {
695  if (x.nelem() == 0) {
696  ostringstream os;
697  os << "The agenda *" << x_name << "* is empty.\nIt is not allowed \n"
698  << "that an empty agenda that is actually used.\n"
699  << "Empty agendas are only created of methods setting dummy values \n"
700  << "to variables.";
701  throw runtime_error(os.str());
702  }
703 }
704 
705 /*===========================================================================
706  === Functions for interpolation grids
707  ===========================================================================*/
708 
710 
736  Index& ing_max,
737  const String& which_interpolation,
738  ConstVectorView old_grid,
739  ConstVectorView new_grid,
741  const Index order) {
743  ing_min, ing_max, which_interpolation, old_grid, new_grid, order);
744 
746  ing_min, ing_max, which_interpolation, old_grid, new_grid, data);
747 }
748 
750 
774  Index& ing_min,
775  Index& ing_max,
776  const String& which_interpolation,
777  ConstVectorView old_grid,
778  ConstVectorView new_grid,
779  const Index order) {
780  const Index n_old = old_grid.nelem();
781 
782  if (!new_grid.nelem())
783  throw runtime_error("The new grid is not allowed to be empty.");
784 
785  ostringstream os;
786  os << "There is a problem with the grids for the following interpolation:\n"
787  << which_interpolation << "\n";
788 
789  // Old grid must have at least order+1 elements:
790  if (n_old < order + 1) {
791  os << "The original grid must have at least " << order + 1 << " elements.";
792  throw runtime_error(os.str());
793  }
794 
795  // Decide whether we have an ascending or descending grid:
796  const bool ascending = (old_grid[0] <= old_grid[1]);
797 
798  // Minimum and maximum allowed value from old grid. (Will include
799  // extrapolation tolerance.)
800  Numeric og_min, og_max;
801 
802  ing_min = 0;
803  ing_max = new_grid.nelem() - 1;
804  if (ascending) {
805  // Old grid must be strictly increasing (no duplicate values.)
806  if (!is_increasing(old_grid)) {
807  os << "The original grid must be strictly sorted\n"
808  << "(no duplicate values). Yours is:\n"
809  << old_grid << ".";
810  throw runtime_error(os.str());
811  }
812 
813  // Limits of extrapolation.
814  og_min = old_grid[0];
815  og_max = old_grid[n_old - 1];
816  } else {
817  // Old grid must be strictly decreasing (no duplicate values.)
818  if (!is_decreasing(old_grid)) {
819  os << "The original grid must be strictly sorted\n"
820  << "(no duplicate values). Yours is:\n"
821  << old_grid << ".";
822  throw runtime_error(os.str());
823  }
824 
825  // The max is now the first point, the min the last point!
826  og_max = old_grid[0];
827  og_min = old_grid[n_old - 1];
828  }
829 
830  // Min and max of new grid:
831  const Numeric ng_min = min(new_grid);
832  const Numeric ng_max = max(new_grid);
833 
834  // If new grid is not inside old grid, determine the indexes of the range
835  // that is.
836 
837  const Index iog_min = 0;
838  const Index iog_max = old_grid.nelem() - 1;
839 
840  ing_min = 0;
841  ing_max = new_grid.nelem() - 1;
842 
843  if (ascending) {
844  if (ng_max > og_max) {
845  while (ing_max > 0 && new_grid[ing_max] > old_grid[iog_max]) ing_max--;
846  }
847 
848  if (ng_min < og_min) {
849  while (ing_min < new_grid.nelem() - 1 &&
850  new_grid[ing_min] < old_grid[iog_min])
851  ing_min++;
852  }
853  } else {
854  if (ng_min < og_min) {
855  while (ing_max > 0 && new_grid[ing_max] < old_grid[iog_max]) ing_max--;
856  }
857 
858  if (ng_max > og_max) {
859  while (ing_min < new_grid.nelem() - 1 &&
860  new_grid[ing_min] > old_grid[iog_min])
861  ing_min++;
862  }
863  }
864 }
865 
867 
891  Index& ing_min,
892  Index& ing_max,
893  const String& which_interpolation,
894  ConstVectorView old_pgrid,
895  ConstVectorView new_pgrid,
896  const Index order) {
897  // Local variable to store log of the pressure grids
898  Vector logold(old_pgrid.nelem());
899  Vector lognew(new_pgrid.nelem());
900 
901  transform(logold, log, old_pgrid);
902  transform(lognew, log, new_pgrid);
903 
905  ing_min, ing_max, which_interpolation, logold, lognew, order);
906 }
907 
909 
931  Index& ing_max,
932  const String& which_interpolation,
933  ConstVectorView old_grid,
934  ConstVectorView new_grid,
936  if (!new_grid.nelem())
937  throw runtime_error("The new grid is not allowed to be empty.");
938 
939  ostringstream os;
940  os << "There is a problem with the grids for the following interpolation:\n"
941  << which_interpolation << "\n";
942 
943  // Decide whether we have an ascending or descending grid:
944  const bool ascending = (old_grid[0] <= old_grid[1]);
945 
946  // If new grid is not inside old grid, determine the indexes of the range
947  // that is.
948 
949  const Index iog_min = ascending ? old_grid.nelem() - 1 : 0;
950  const Index iog_max = ascending ? 0 : old_grid.nelem() - 1;
951 
952  if (ing_min > 0 && data[iog_min] != 0) {
953  os << "\nThe new grid is not fully inside the original grid.\n"
954  << "This is allowed if the corresponding boundary value of raw data is 0.\n"
955  << "New grid point: " << new_grid[ing_min] << "\n"
956  << "Old grid point: " << old_grid[iog_min] << "\n"
957  << "Boundary value: " << data[iog_min];
958  throw runtime_error(os.str());
959  }
960 
961  if (ing_max < new_grid.nelem() - 1 && data[iog_max] != 0) {
962  os << "\nThe the new grid is not fully inside the original grid.\n"
963  << "This is allowed if the corresponding boundary value of raw data is 0.\n"
964  << "New grid point: " << new_grid[ing_max] << "\n"
965  << "Old grid point: " << old_grid[iog_max] << "\n"
966  << "Boundary value: " << data[iog_max];
967  throw runtime_error(os.str());
968  }
969 }
970 
972 
989 void chk_interpolation_grids(const String& which_interpolation,
990  ConstVectorView old_grid,
991  ConstVectorView new_grid,
992  const Index order,
993  const Numeric& extpolfac,
994  const bool islog) {
995  const Index n_old = old_grid.nelem();
996 
997  if (!new_grid.nelem())
998  throw runtime_error("The new grid is not allowed to be empty.");
999 
1000  if (order < 0) {
1001  ostringstream os;
1002  os << "There is a problem with the grids for the following "
1003  << "interpolation:\n"
1004  << which_interpolation << "\n"
1005  << "Interpolation order must be 0 or larger (but your's is " << order
1006  << ").";
1007  throw runtime_error(os.str());
1008  }
1009 
1010  // Old grid must have at least order+1 elements:
1011  if (n_old < order + 1) {
1012  ostringstream os;
1013  os << "There is a problem with the grids for the following "
1014  << "interpolation:\n"
1015  << which_interpolation << "\n"
1016  << "For interpolation order " << order
1017  << ", the original grid must have at least\n"
1018  << order + 1 << " elements (but your's has only " << n_old << ").";
1019  throw runtime_error(os.str());
1020  }
1021 
1022  // Decide whether we have an ascending or descending grid:
1023  const bool ascending = ((n_old > 1) ? (old_grid[0] <= old_grid[1]) : true);
1024 
1025  // Minimum and maximum allowed value from old grid. (Will include
1026  // extrapolation tolerance.)
1027  Numeric og_min = old_grid[0], og_max = old_grid[0];
1028 
1029  if (ascending) {
1030  // Old grid must be strictly increasing (no duplicate values.)
1031  if (!is_increasing(old_grid)) {
1032  ostringstream os;
1033  os << "There is a problem with the grids for the "
1034  << "following interpolation:\n"
1035  << which_interpolation << "\n"
1036  << "The original grid must be strictly sorted\n"
1037  << "(no duplicate values). Yours is:\n"
1038  << old_grid << ".";
1039  throw runtime_error(os.str());
1040  }
1041 
1042  // Limits of extrapolation.
1043  if (n_old > 1) {
1044  og_min = old_grid[0] - extpolfac * (old_grid[1] - old_grid[0]);
1045  og_max = old_grid[n_old - 1] +
1046  extpolfac * (old_grid[n_old - 1] - old_grid[n_old - 2]);
1047  }
1048  } else {
1049  // Old grid must be strictly decreasing (no duplicate values.)
1050  if (!is_decreasing(old_grid)) {
1051  ostringstream os;
1052  os << "There is a problem with the grids for the "
1053  << "following interpolation:\n"
1054  << which_interpolation << "\n"
1055  << "The original grid must be strictly sorted\n"
1056  << "(no duplicate values). Yours is:\n"
1057  << old_grid << ".";
1058  throw runtime_error(os.str());
1059  }
1060 
1061  // The max is now the first point, the min the last point!
1062  // I think the sign is right here...
1063  if (n_old > 1) {
1064  og_max = old_grid[0] - extpolfac * (old_grid[1] - old_grid[0]);
1065  og_min = old_grid[n_old - 1] +
1066  extpolfac * (old_grid[n_old - 1] - old_grid[n_old - 2]);
1067  }
1068  }
1069 
1070  // Min and max of new grid:
1071  const Numeric ng_min = min(new_grid);
1072  const Numeric ng_max = max(new_grid);
1073 
1074  // New grid must be inside old grid (plus extpolfac).
1075  // (Values right on the edge (ng_min==og_min) are still allowed.)
1076 
1077  if (n_old > 1) {
1078  if (ng_min < og_min) {
1079  ostringstream os;
1080  os << "There is a problem with the grids for the "
1081  << "following interpolation:\n"
1082  << which_interpolation << "\n"
1083  << "The minimum of the new grid must be inside "
1084  << "the original grid.\n(We allow a bit of extrapolation, "
1085  << "but not so much).\n"
1086  << "Minimum of original grid: " << min(old_grid);
1087  if (islog) os << " (" << exp(min(old_grid)) << ")";
1088  os << "\nMinimum allowed value for new grid: " << og_min;
1089  if (islog) os << " (" << exp(og_min) << ")";
1090  os << "\nActual minimum of new grid: " << ng_min;
1091  if (islog) os << " (" << exp(ng_min) << ")";
1092  throw runtime_error(os.str());
1093  }
1094 
1095  if (ng_max > og_max) {
1096  ostringstream os;
1097  os << "There is a problem with the grids for the "
1098  << "following interpolation:\n"
1099  << which_interpolation << "\n"
1100  << "The maximum of the new grid must be inside\n"
1101  << "the original grid. (We allow a bit of extrapolation,\n"
1102  << "but not so much).\n"
1103  << "Maximum of original grid: " << max(old_grid);
1104  if (islog) os << " (" << exp(max(old_grid)) << ")";
1105  os << "\nMaximum allowed value for new grid: " << og_max;
1106  if (islog) os << " (" << exp(og_max) << ")";
1107  os << "\nActual maximum of new grid: " << ng_max;
1108  if (islog) os << " (" << exp(ng_max) << ")";
1109  throw runtime_error(os.str());
1110  }
1111  }
1112 
1113  // If we get here, than everything should be fine.
1114 }
1115 
1117 
1139 void chk_interpolation_grids(const String& which_interpolation,
1140  ConstVectorView old_grid,
1141  const Numeric& new_grid,
1142  const Index order,
1143  const Numeric& extpolfac) {
1144  const Vector v(1, new_grid);
1145  chk_interpolation_grids(which_interpolation, old_grid, v, order, extpolfac);
1146 }
1147 
1149 
1166 void chk_interpolation_pgrids(const String& which_interpolation,
1167  ConstVectorView old_pgrid,
1168  ConstVectorView new_pgrid,
1169  const Index order,
1170  const Numeric& extpolfac) {
1171  // Local variable to store log of the pressure grids
1172  Vector logold(old_pgrid.nelem());
1173  Vector lognew(new_pgrid.nelem());
1174 
1175  transform(logold, log, old_pgrid);
1176  transform(lognew, log, new_pgrid);
1177 
1179  which_interpolation, logold, lognew, order, extpolfac, true);
1180 }
1181 
1182 /*===========================================================================
1183  === Functions related to atmospheric and surface grids and fields.
1184  ===========================================================================*/
1185 
1187 
1201 void chk_atm_grids(const Index& dim,
1202  ConstVectorView p_grid,
1203  ConstVectorView lat_grid,
1204  ConstVectorView lon_grid) {
1205  // p_grid
1206  if (p_grid.nelem() < 2)
1207  throw runtime_error("The length of *p_grid* must be >= 2.");
1208  chk_if_decreasing("p_grid", p_grid);
1209 
1210  // lat_grid
1211  if (dim == 1) {
1212  if (lat_grid.nelem() > 0)
1213  throw runtime_error("For dim=1, the length of *lat_grid* must be 0.");
1214  } else {
1215  if (lat_grid.nelem() < 2)
1216  throw runtime_error("For dim>1, the length of *lat_grid* must be >= 2.");
1217  chk_if_increasing("lat_grid", lat_grid);
1218  }
1219 
1220  // lon_grid
1221  if (dim < 3) {
1222  if (lon_grid.nelem() > 0)
1223  throw runtime_error("For dim<3, the length of *lon_grid* must be 0.");
1224  } else {
1225  if (lon_grid.nelem() < 2)
1226  throw runtime_error("For dim=3, the length of *lon_grid* must be >= 2.");
1227  chk_if_increasing("lon_grid", lon_grid);
1228  }
1229 
1230  // Check that latitude and longitude grids are inside OK ranges for 3D
1231  if (dim == 3) {
1232  if (lat_grid[0] < -90)
1233  throw runtime_error(
1234  "The latitude grid cannot extend below -90 degrees for 3D");
1235  if (lat_grid[lat_grid.nelem() - 1] > 90)
1236  throw runtime_error(
1237  "The latitude grid cannot extend above 90 degrees for 3D");
1238  if (lon_grid[0] < -360)
1239  throw runtime_error(
1240  "No longitude (in lon_grid) can be below -360 degrees.");
1241  if (lon_grid[lon_grid.nelem() - 1] > 360)
1242  throw runtime_error(
1243  "No longitude (in lon_grid) can be above 360 degrees.");
1244  if (lon_grid[lon_grid.nelem() - 1] - lon_grid[0] > 360)
1245  throw runtime_error(
1246  "The longitude grid is not allowed to cover more than 360 degrees.");
1247  }
1248 }
1249 
1251 
1268 void chk_atm_field(const String& x_name,
1269  ConstTensor3View x,
1270  const Index& dim,
1271  ConstVectorView p_grid,
1272  ConstVectorView lat_grid,
1273  ConstVectorView lon_grid,
1274  const bool& chk_lat90) {
1275  // It is assumed that grids OK-ed through chk_atm_grids
1276  Index npages = p_grid.nelem(), nrows = 1, ncols = 1;
1277  if (dim > 1) nrows = lat_grid.nelem();
1278  if (dim > 2) ncols = lon_grid.nelem();
1279  if (x.ncols() != ncols || x.nrows() != nrows || x.npages() != npages) {
1280  ostringstream os;
1281  os << "The atmospheric field *" << x_name << "* has wrong size.\n"
1282  << "Expected size is " << npages << " x " << nrows << " x " << ncols
1283  << ", while actual size is " << x.npages() << " x " << x.nrows() << " x "
1284  << x.ncols() << ".";
1285  throw runtime_error(os.str());
1286  }
1287 
1288  // NaNs are not allowed
1289  for (Index ip = 0; ip < npages; ip++) {
1290  for (Index ir = 0; ir < nrows; ir++) {
1291  for (Index ic = 0; ic < ncols; ic++) {
1292  if (std::isnan(x(ip, ir, ic))) {
1293  ostringstream os;
1294  os << "The variable *" << x_name << "* contains one or "
1295  << "several NaNs. This is not allowed!";
1296  throw runtime_error(os.str());
1297  }
1298  }
1299  }
1300  }
1301 
1302  // Special 3D checks:
1303  if (dim == 3) {
1304  // If all lons are covered, check if cyclic
1305  if (is_lon_cyclic(lon_grid)) {
1306  const Index ic = ncols - 1;
1307  for (Index ip = 0; ip < npages; ip++) {
1308  for (Index ir = 0; ir < nrows; ir++) {
1310  x(ip, ir, ic), x(ip, ir, 0), 4 * DBL_EPSILON)) {
1311  ostringstream os;
1312  os << "The variable *" << x_name << "* covers 360 "
1313  << "degrees in the longitude direction, but the field "
1314  << "seems to deviate between first and last longitude "
1315  << "point. The field must be \"cyclic\".\n"
1316  << "Difference: " << setprecision(16)
1317  << x(ip, ir, ic) - x(ip, ir, 0) << "\n"
1318  << "Epsilon : "
1319  << 4 * DBL_EPSILON * max(x(ip, ir, ic), x(ip, ir, 0));
1320  throw runtime_error(os.str());
1321  }
1322  }
1323  }
1324  }
1325 
1326  chk_if_bool("chk_lat90", chk_lat90);
1327  if (chk_lat90) {
1328  // No variation at the South pole!
1329  if (lat_grid[0] == -90) {
1330  for (Index ip = 0; ip < npages; ip++) {
1331  for (Index ic = 1; ic < ncols; ic++) {
1333  x(ip, 0, ic), x(ip, 0, ic - 1), 2 * DBL_EPSILON)) {
1334  ostringstream os;
1335  os << "The variable *" << x_name << "* covers the South\n"
1336  << "pole. The data corresponding to the pole can not\n"
1337  << "vary with longitude, but this appears to be the\n"
1338  << "case.";
1339  /* << "case: at " << ip << ".th pressure it has val\n"
1340  << x(ip,0,ic-1) << ", but " << x(ip,0,ic)
1341  << " (i.e., a diff of " << fabs(x(ip,0,ic)-x(ip,0,ic-1))
1342  << ") at " << ic-1 << "th and " << ic << "th longitudes!\n";
1343 */
1344  throw runtime_error(os.str());
1345  }
1346  }
1347  }
1348  }
1349  // No variation at the North pole!
1350  if (lat_grid[nrows - 1] == 90) {
1351  const Index ir = nrows - 1;
1352  for (Index ip = 0; ip < npages; ip++) {
1353  for (Index ic = 1; ic < ncols; ic++) {
1355  x(ip, ir, ic), x(ip, ir, ic - 1), 2 * DBL_EPSILON)) {
1356  ostringstream os;
1357  os << "The variable *" << x_name << "* covers the North\n"
1358  << "pole. The data corresponding to the pole can not\n"
1359  << "vary with longitude, but this appears to be the "
1360  << "case.";
1361  /* << "case: at " << ip << ".th pressure it has val\n"
1362  << x(ip,ir,ic-1) << ", but " << x(ip,ir,ic)
1363  << " (i.e., a diff of " << fabs(x(ip,ir,ic)-x(ip,ir,ic-1))
1364  << ") at " << ic-1 << "th and " << ic << "th longitudes!\n";
1365 */
1366  throw runtime_error(os.str());
1367  }
1368  }
1369  }
1370  }
1371  }
1372  }
1373 }
1374 
1376 
1394 void chk_atm_field(const String& x_name,
1395  ConstTensor4View x,
1396  const Index& dim,
1397  const Index& nspecies,
1398  ConstVectorView p_grid,
1399  ConstVectorView lat_grid,
1400  ConstVectorView lon_grid,
1401  const bool& check_nan) {
1402  const Index nbooks = nspecies;
1403  //
1404  if (nbooks == 0) {
1405  if (x.nbooks()) {
1406  ostringstream os;
1407  os << "The atmospheric field *" << x_name << "* should be empty.\n";
1408  throw runtime_error(os.str());
1409  } else {
1410  return;
1411  }
1412  }
1413 
1414  Index npages = p_grid.nelem(), nrows = 1, ncols = 1;
1415  if (dim > 1) nrows = lat_grid.nelem();
1416  if (dim > 2) ncols = lon_grid.nelem();
1417 
1418  if (x.ncols() != ncols || x.nrows() != nrows || x.npages() != npages ||
1419  x.nbooks() != nbooks) {
1420  ostringstream os;
1421  os << "The atmospheric field *" << x_name << "* has wrong size.\n"
1422  << "Expected size is " << nbooks << " x " << npages << " x " << nrows
1423  << " x " << ncols << ",\n"
1424  << "while actual size is " << x.nbooks() << " x " << x.npages() << " x "
1425  << x.nrows() << " x " << x.ncols() << ".";
1426  throw runtime_error(os.str());
1427  }
1428 
1429  if (check_nan)
1430  // NaNs are not allowed
1431  {
1432  for (Index ib = 0; ib < nbooks; ib++) {
1433  for (Index ip = 0; ip < npages; ip++) {
1434  for (Index ir = 0; ir < nrows; ir++) {
1435  for (Index ic = 0; ic < ncols; ic++) {
1436  if (std::isnan(x(ib, ip, ir, ic))) {
1437  ostringstream os;
1438  os << "The variable *" << x_name << "* contains one or "
1439  << "several NaNs. This is not allowed!";
1440  throw runtime_error(os.str());
1441  }
1442  }
1443  }
1444  }
1445  }
1446  }
1447 
1448  // Special 3D checks:
1449  if (dim == 3) {
1450  // If all lons are covered, check if cyclic
1451  if ((lon_grid[ncols - 1] - lon_grid[0]) == 360) {
1452  const Index ic = ncols - 1;
1453  for (Index is = 0; is < nspecies; is++) {
1454  for (Index ip = 0; ip < npages; ip++) {
1455  for (Index ir = 0; ir < nrows; ir++) {
1457  x(is, ip, ir, ic), x(is, ip, ir, 0), 2 * DBL_EPSILON)) {
1458  ostringstream os;
1459  os << "The variable *" << x_name << "* covers 360 "
1460  << "degrees in the longitude direction, but at least "
1461  << "one field seems to deviate between first and last "
1462  << "longitude point. The field must be \"cyclic\". "
1463  << "This was found for field with index " << is
1464  << " (0-based).";
1465  throw runtime_error(os.str());
1466  }
1467  }
1468  }
1469  }
1470  }
1471  // No variation at the South pole!
1472  if (lat_grid[0] == -90) {
1473  for (Index is = 0; is < nspecies; is++) {
1474  for (Index ip = 0; ip < npages; ip++) {
1475  for (Index ic = 1; ic < ncols; ic++) {
1477  x(is, ip, 0, ic), x(is, ip, 0, ic - 1), 2 * DBL_EPSILON)) {
1478  ostringstream os;
1479  os << "The variable *" << x_name << "* covers the South "
1480  << "pole. The data corresponding to the pole can not "
1481  << "vary with longitude, but this appears to be the "
1482  << "case. This was found for field with index " << is
1483  << " (0-based).";
1484  throw runtime_error(os.str());
1485  }
1486  }
1487  }
1488  }
1489  }
1490  // No variation at the North pole!
1491  if (lat_grid[nrows - 1] == 90) {
1492  const Index ir = nrows - 1;
1493  for (Index is = 0; is < nspecies; is++) {
1494  for (Index ip = 0; ip < npages; ip++) {
1495  for (Index ic = 1; ic < ncols; ic++) {
1496  if (!is_same_within_epsilon(x(is, ip, ir, ic),
1497  x(is, ip, ir, ic - 1),
1498  2 * DBL_EPSILON)) {
1499  ostringstream os;
1500  os << "The variable *" << x_name << "* covers the North "
1501  << "pole. The data corresponding to the pole can not "
1502  << "vary with longitude, but this appears to be the "
1503  << "case. This was found for field with index " << is
1504  << " (0-based).";
1505  throw runtime_error(os.str());
1506  }
1507  }
1508  }
1509  }
1510  }
1511  }
1512 }
1513 
1515 
1540 void chk_atm_vecfield_lat90(const String& x1_name,
1542  const String& x2_name,
1544  const Index& dim,
1545  ConstVectorView lat_grid,
1546  const Numeric& threshold) {
1547  // It is assumed that grids OK-ed through chk_atm_grids and fields
1548  // individually OK-ed.
1549 
1550  // We only need to check 3D cases. Else there is no variation in longitude
1551  // anyways.
1552  if (dim == 3) {
1553  Index npages = x1.npages();
1554  Index nrows = x1.nrows();
1555  Index ncols = x1.ncols();
1556 
1557  // For safety check that both fields have identical dimensions
1558  if (x2.ncols() != ncols || x2.nrows() != nrows || x2.npages() != npages) {
1559  ostringstream os;
1560  os << "The atmospheric fields *" << x1_name << "* and *" << x2_name
1561  << "* do not match in size.\n"
1562  << "*" << x1_name << "*'s size is " << npages << " x " << nrows
1563  << " x " << ncols << ", while *" << x1_name << "*'s size is "
1564  << x2.npages() << " x " << x2.nrows() << " x " << x2.ncols() << ".";
1565  throw runtime_error(os.str());
1566  }
1567 
1568  // redefine ratio deviation threshold of vector lengths to ratio of
1569  // squared vector lengths, cause don't want to calc squareroot everytime.
1570  // (val1**2/val2**2 - 1) / (val1/val2 - 1) = val1/val2 + 1
1571  // and with val1~val2 = 2
1572  // i.e., (val1**2/val2**2 - 1) ~ 2 * (val1/val2 - 1)
1573  //
1574  // with val1/1 = sqrt(vec1/2), hence val1/2**2 = vec1/2
1575  // (vec1/vec2 - 1) ~ 2 * (sqrt(vec1)/sqrt(vec2) - 1)
1576  // (sqrt(vec1)/sqrt(vec2) - 1) ~ (vec1/vec2 - 1) / 2
1577  //
1578  // we want to check: sqrt(vec1)/sqrt(vec2) - 1. < threshold
1579  // i.e., with the above,
1580  // (vec1/vec2 - 1) / 2 < threshold
1581  // (vec1/vec2 - 1) < threshold*2
1582  Numeric th = threshold * 2.;
1583 
1584  // No variation at the South pole!
1585  if (lat_grid[0] == -90) {
1586  Numeric vec1, vec2;
1587  for (Index ip = 0; ip < npages; ip++) {
1588  for (Index ic = 1; ic < ncols; ic++) {
1589  vec1 = x1(ip, 0, ic) * x1(ip, 0, ic) + x2(ip, 0, ic) * x2(ip, 0, ic);
1590  vec2 = x1(ip, 0, ic - 1) * x1(ip, 0, ic - 1) +
1591  x2(ip, 0, ic - 1) * x2(ip, 0, ic - 1);
1592  if (fabs(vec1 / vec2 - 1.) > th) {
1593  ostringstream os;
1594  os << "The variables *" << x1_name << "* and *" << x2_name
1595  << "* are assumed\n"
1596  << "to be two horizontal components of a vector field.\n"
1597  << "At the pole, the data (here: the total length of\n"
1598  << "the horizontal vector) can NOT vary with longitude,\n"
1599  << "but this appears to be the case on the South pole.\n"
1600  << "The threshold is " << threshold << ", but the actual\n"
1601  << "deviation at pressure level " << ip << " and longitude\n"
1602  << "points " << ic - 1 << " and " << ic << " is "
1603  << sqrt(vec1) / sqrt(vec2) - 1.;
1604  throw runtime_error(os.str());
1605  }
1606  }
1607  }
1608  }
1609  // No variation at the North pole!
1610  if (lat_grid[nrows - 1] == 90) {
1611  Numeric vec1, vec2;
1612  const Index ir = nrows - 1;
1613  for (Index ip = 0; ip < npages; ip++) {
1614  for (Index ic = 1; ic < ncols; ic++) {
1615  vec1 =
1616  x1(ip, ir, ic) * x1(ip, ir, ic) + x2(ip, ir, ic) * x2(ip, ir, ic);
1617  vec2 = x1(ip, ir, ic - 1) * x1(ip, ir, ic - 1) +
1618  x2(ip, ir, ic - 1) * x2(ip, ir, ic - 1);
1619  if (fabs(vec1 / vec2 - 1.) > th) {
1620  ostringstream os;
1621  os << "The variables *" << x1_name << "* and *" << x2_name
1622  << "* are assumed\n"
1623  << "to be two horizontal components of a vector field.\n"
1624  << "At the pole, the data (here: the total length of\n"
1625  << "the horizontal vector) can NOT vary with longitude,\n"
1626  << "but this appears to be the case on the North pole.\n"
1627  << "The threshold is " << threshold << ", but the actual\n"
1628  << "deviation at pressure level " << ip << " and longitude\n"
1629  << "points " << ic - 1 << " and " << ic << " is "
1630  << sqrt(vec1) / sqrt(vec2) - 1.;
1631  throw runtime_error(os.str());
1632  }
1633  }
1634  }
1635  }
1636  }
1637 }
1638 
1640 
1652 void chk_latlon_true(const Index& atmosphere_dim,
1653  ConstVectorView lat_grid,
1654  ConstVectorView lat_true,
1655  ConstVectorView lon_true) {
1656  if (atmosphere_dim == 1) {
1657  if (lat_true.nelem() != 1 || lon_true.nelem() != 1) {
1658  throw runtime_error(
1659  "For 1D, the method requires that *lat_true* "
1660  "and *lon_true* have length 1.");
1661  }
1662  }
1663  //
1664  else if (atmosphere_dim == 2) {
1665  if (lat_true.nelem() != lat_grid.nelem() ||
1666  lon_true.nelem() != lat_grid.nelem()) {
1667  throw runtime_error(
1668  "For 2D, the method requires that *lat_true* "
1669  "and *lon_true* have the same length as *lat_grid*.");
1670  }
1671  }
1672 }
1673 
1675 
1689 void chk_atm_surface(const String& x_name,
1690  const Matrix& x,
1691  const Index& dim,
1692  ConstVectorView lat_grid,
1693  ConstVectorView lon_grid) {
1694  Index ncols = 1, nrows = 1;
1695  if (dim > 1) nrows = lat_grid.nelem();
1696  if (dim > 2) ncols = lon_grid.nelem();
1697  if (x.ncols() != ncols || x.nrows() != nrows) {
1698  ostringstream os;
1699  os << "The surface variable *" << x_name << "* has wrong size.\n"
1700  << "Expected size is " << nrows << " x " << ncols << ","
1701  << " while actual size is " << x.nrows() << " x " << x.ncols() << ".";
1702  throw runtime_error(os.str());
1703  }
1704 
1705  // Special 3D checks:
1706  if (dim == 3) {
1707  // If all lons are covered, check if cyclic
1708  if ((lon_grid[ncols - 1] - lon_grid[0]) == 360) {
1709  const Index ic = ncols - 1;
1710  for (Index ir = 0; ir < nrows; ir++) {
1711  if (!is_same_within_epsilon(x(ir, ic), x(ir, 0), 2 * DBL_EPSILON)) {
1712  ostringstream os;
1713  os << "The variable *" << x_name << "* covers 360 "
1714  << "degrees in the longitude direction, but the field "
1715  << "seems to deviate between first and last longitude "
1716  << "point. The field must be \"cyclic\".";
1717  throw runtime_error(os.str());
1718  }
1719  }
1720  }
1721 
1722  // No variation at the South pole!
1723  if (lat_grid[0] == -90) {
1724  for (Index ic = 1; ic < ncols; ic++) {
1725  if (!is_same_within_epsilon(x(0, ic), x(0, ic - 1), 2 * DBL_EPSILON)) {
1726  ostringstream os;
1727  os << "The variable *" << x_name << "* covers the South "
1728  << "pole. The data corresponding to the pole can not "
1729  << "vary with longitude, but this appears to be the "
1730  << "case.";
1731  throw runtime_error(os.str());
1732  }
1733  }
1734  }
1735  // No variation at the North pole!
1736  if (lat_grid[nrows - 1] == 90) {
1737  const Index ir = nrows - 1;
1738  for (Index ic = 1; ic < ncols; ic++) {
1740  x(ir, ic), x(ir, ic - 1), 2 * DBL_EPSILON)) {
1741  ostringstream os;
1742  os << "The variable *" << x_name << "* covers the North "
1743  << "pole. The data corresponding to the pole can not "
1744  << "vary with longitude, but this appears to be the "
1745  << "case.";
1746  throw runtime_error(os.str());
1747  }
1748  }
1749  }
1750  }
1751 }
1752 
1753 /*===========================================================================
1754  === Functions related to sensor variables.
1755  ===========================================================================*/
1756 
1758 
1770 void chk_rte_pos(const Index& atmosphere_dim,
1771  ConstVectorView rte_pos,
1772  const bool& is_rte_pos2)
1773 
1774 {
1775  String vname = "*rte_pos*";
1776  if (is_rte_pos2) {
1777  vname = "*rte_pos2*";
1778  }
1779 
1780  if (atmosphere_dim == 1) {
1781  if (!is_rte_pos2) {
1782  if (rte_pos.nelem() != 1) {
1783  ostringstream os;
1784  os << "For 1D, " << vname << " must have length 1.";
1785  throw runtime_error(os.str());
1786  }
1787  } else {
1788  if (rte_pos.nelem() != 2) {
1789  ostringstream os;
1790  os << "For 1D, " << vname << " must have length 2.";
1791  throw runtime_error(os.str());
1792  }
1793  if (rte_pos[1] < -180 || rte_pos[1] > 180) {
1794  ostringstream os;
1795  os << "For 1D, the latitude in " << vname << " must be in the "
1796  << "range [-180,180].";
1797  throw runtime_error(os.str());
1798  }
1799  }
1800  } else if (atmosphere_dim == 2) {
1801  if (rte_pos.nelem() != 2) {
1802  ostringstream os;
1803  os << "For 2D, " << vname << " must have length 2.";
1804  throw runtime_error(os.str());
1805  }
1806  } else {
1807  if (rte_pos.nelem() != 3) {
1808  ostringstream os;
1809  os << "For 3D, " << vname << " must have length 3.";
1810  throw runtime_error(os.str());
1811  }
1812  if (rte_pos[1] < -90 || rte_pos[1] > 90) {
1813  ostringstream os;
1814  os << "The (3D) latitude in " << vname << " must be in the "
1815  << "range [-90,90].";
1816  throw runtime_error(os.str());
1817  }
1818  if (rte_pos[2] < -360 || rte_pos[2] > 360) {
1819  ostringstream os;
1820  os << "The longitude in " << vname << " must be in the "
1821  << "range [-360,360].";
1822  throw runtime_error(os.str());
1823  }
1824  }
1825 }
1826 
1828 
1839 void chk_rte_los(const Index& atmosphere_dim, ConstVectorView rte_los)
1840 
1841 {
1842  if (atmosphere_dim == 1) {
1843  if (rte_los.nelem() != 1) {
1844  throw runtime_error("For 1D, los-vectors must have length 1.");
1845  }
1846  if (rte_los[0] < 0 || rte_los[0] > 180) {
1847  throw runtime_error(
1848  "For 1D, the zenith angle of a los-vector must "
1849  "be in the range [0,180].");
1850  }
1851  } else if (atmosphere_dim == 2) {
1852  if (rte_los.nelem() != 1) {
1853  throw runtime_error("For 2D, los-vectors must have length 1.");
1854  }
1855  if (rte_los[0] < -180 || rte_los[0] > 180) {
1856  throw runtime_error(
1857  "For 2D, the zenith angle of a los-vector must "
1858  "be in the range [-180,180].");
1859  }
1860  } else {
1861  if (rte_los.nelem() != 2) {
1862  throw runtime_error("For 3D, los-vectors must have length 2.");
1863  }
1864  if (rte_los[0] < 0 || rte_los[0] > 180) {
1865  throw runtime_error(
1866  "For 3D, the zenith angle of a los-vector must "
1867  "be in the range [0,180].");
1868  }
1869  if (rte_los[1] < -180 || rte_los[1] > 180) {
1870  throw runtime_error(
1871  "For 3D, the azimuth angle of a los-vector must "
1872  "be in the range [-180,180].");
1873  }
1874  }
1875 }
1876 
1877 /*===========================================================================
1878  === Functions related to GriddedFields.
1879  ===========================================================================*/
1880 
1882 
1892  const Index gridindex,
1893  const String& gridname) {
1894  if (gf.get_dim() - 1 < gridindex) {
1895  ostringstream os;
1896  os << "Grid index " << gridindex << " exceeds dimension of GriddedField";
1897  if (gf.get_name().nelem()) os << " \"" << gf.get_name() << "\"";
1898  throw runtime_error(os.str());
1899  }
1900 
1901  String gfgridnameupper = gf.get_grid_name(gridindex);
1902  gfgridnameupper.toupper();
1903 
1904  String gridnameupper = gridname;
1905  gridnameupper.toupper();
1906 
1907  if (gfgridnameupper != gridnameupper) {
1908  ostringstream os;
1909  os << "Name of grid " << gridindex << " in GriddedField";
1910  if (gf.get_name().nelem()) os << " \"" << gf.get_name() << "\"";
1911  os << " is \"" << gf.get_grid_name(gridindex) << "\".\n"
1912  << "The expected name is \"" << gridname << "\".";
1913  throw runtime_error(os.str());
1914  }
1915 }
1916 
1917 /*===========================================================================
1918  === Functions checking sensor
1919  ===========================================================================*/
1920 
1931 void chk_met_mm_backend(const Matrix& mmb) {
1932  if (!mmb.nrows())
1933  throw std::runtime_error("No channels defined in *met_mm_backend*.");
1934 
1935  if (mmb.ncols() != 4)
1936  throw std::runtime_error("*met_mm_backend* must have 4 columns.");
1937 
1938  for (Index ch = 0; ch < mmb.nrows(); ch++) {
1939  Numeric lo = mmb(ch, 0);
1940  Numeric offset1 = mmb(ch, 1);
1941  Numeric offset2 = mmb(ch, 2);
1942  Numeric bandwidth = mmb(ch, 3);
1943 
1944  // Negative LO
1945  if (lo < 0.) {
1946  ostringstream os;
1947  os << "Error in channel " << ch + 1 << " at row " << ch
1948  << " in *met_mm_backend*.\n"
1949  << "Center frequency is negative: " << mmb(ch, 0) << " Hz";
1950  throw std::runtime_error(os.str());
1951  }
1952 
1953  // Negative offsets
1954  if (offset1 < 0. || offset2 < 0.) {
1955  ostringstream os;
1956  os << "Error in channel " << ch + 1 << " at row " << ch
1957  << " in *met_mm_backend*.\n"
1958  << "Offset is negative:\n"
1959  << "offset1: " << offset1 << " Hz\n"
1960  << "offset2: " << offset2 << " Hz\n";
1961  throw std::runtime_error(os.str());
1962  }
1963 
1964  // First offset is smaller than second offset
1965  if (offset1 != 0. && offset1 <= offset2) {
1966  ostringstream os;
1967  os << "Error in channel " << ch + 1 << " at row " << ch
1968  << " in *met_mm_backend*.\n"
1969  << "First passband offset is smaller than/equal to the second offset:\n"
1970  << "offset1: " << offset1 << " Hz\n"
1971  << "offset2: " << offset2 << " Hz\n";
1972  throw std::runtime_error(os.str());
1973  }
1974 
1975  // Bandwidth too wide, overlap with LO
1976  if (offset1 > 0 && offset1 - offset2 <= bandwidth / 2.) {
1977  ostringstream os;
1978  os << "Error in channel " << ch + 1 << " at row " << ch
1979  << " in *met_mm_backend*.\n"
1980  << "Band touches or overlaps with the center frequency:\n"
1981  << "offset1 : " << offset1 << " Hz\n"
1982  << "offset2 : " << offset2 << " Hz\n"
1983  << "bandwidth : " << bandwidth << " Hz\n"
1984  << "offset1 - offset2 - bandwidth/2: "
1985  << offset1 - offset2 - bandwidth / 2. << " Hz\n";
1986  throw std::runtime_error(os.str());
1987  }
1988 
1989  // Bandwidth too wide, passbands overlap
1990  if (offset2 > 0 && offset2 <= bandwidth / 2.) {
1991  ostringstream os;
1992  os << "Error in channel " << ch + 1 << " at row " << ch
1993  << " in *met_mm_backend*.\n"
1994  << "Bands overlap or touch, offset2 > bandwidth/2:\n"
1995  << "offset2 : " << offset2 << " Hz\n"
1996  << "bandwidth/2: " << bandwidth / 2. << " Hz\n";
1997  throw std::runtime_error(os.str());
1998  }
1999 
2000  // Channel too wide, goes negative
2001  if (lo - offset1 - offset2 - bandwidth / 2. <= 0) {
2002  ostringstream os;
2003  os << "Error in channel " << ch + 1 << " at row " << ch
2004  << " in *met_mm_backend*.\n"
2005  << "Band too wide, reaches/exceeds 0 Hz:\n"
2006  << "LO : " << lo << " Hz\n"
2007  << "offset1 : " << offset1 << " Hz\n"
2008  << "offset2 : " << offset2 << " Hz\n"
2009  << "bandwidth : " << bandwidth << " Hz\n"
2010  << "LO - offset1 - offset2 - bandwidth/2: "
2011  << lo - offset1 - offset2 - bandwidth / 2. << " Hz\n";
2012  throw std::runtime_error(os.str());
2013  }
2014  }
2015 }
Index npages() const
Returns the number of pages.
Definition: matpackV.cc:50
INDEX Index
The type to use for all integer numbers and indices.
Definition: matpack.h:39
const Index GFIELD3_LAT_GRID
bool is_lon_cyclic(ConstVectorView grid, const Numeric &epsilon)
Check if the given longitude grid is cyclic.
Definition: logic.cc:369
void chk_if_in_range_exclude(const String &x_name, const Numeric &x, const Numeric &x_low, const Numeric &x_high)
chk_if_in_range_exclude
Definition: check_input.cc:251
Index nrows() const
Returns the number of rows.
Definition: matpackV.cc:53
The Agenda class.
Definition: agenda_class.h:44
#define x2
void chk_if_decreasing(const String &x_name, ConstVectorView x)
chk_if_decreasing
Definition: check_input.cc:358
A constant view of a Tensor7.
Definition: matpackVII.h:147
void chk_atm_surface(const String &x_name, const Matrix &x, const Index &dim, ConstVectorView lat_grid, ConstVectorView lon_grid)
chk_atm_surface
const Index GFIELD3_LON_GRID
void chk_if_increasing(const String &x_name, const ArrayOfIndex &x)
chk_if_increasing
Definition: check_input.cc:117
The Vector class.
Definition: matpackI.h:860
#define abs(x)
Index nvitrines() const
Returns the number of vitrines.
Definition: matpackVI.cc:42
A constant view of a Tensor6.
Definition: matpackVI.h:149
bool is_increasing(ConstVectorView x)
Checks if a vector is sorted and strictly increasing.
Definition: logic.cc:215
Index nrows() const
Returns the number of rows.
Definition: matpackVII.cc:57
Index npages() const
Returns the number of pages.
Definition: matpackIV.cc:60
void chk_not_negative(const String &x_name, const Numeric &x)
chk_not_negative
Definition: check_input.cc:143
void chk_rte_los(const Index &atmosphere_dim, ConstVectorView rte_los)
chk_rte_los
void chk_if_bool(const String &x_name, const Index &x)
chk_if_bool
Definition: check_input.cc:65
Index nbooks() const
Returns the number of books.
Definition: matpackV.cc:47
void chk_interpolation_grids_loose_check_data(Index &ing_min, Index &ing_max, const String &which_interpolation, ConstVectorView old_grid, ConstVectorView new_grid, ConstVectorView data)
Check interpolation grids.
Definition: check_input.cc:930
#define min(a, b)
Index nrows() const
Returns the number of rows.
Definition: matpackIII.h:147
G0 G2 FVC Y DV Numeric Numeric Numeric Zeeman LowerQuantumNumbers void * data
Index nrows() const
Returns the number of rows.
Definition: matpackIV.cc:63
void chk_matrix_ncols(const String &x_name, ConstMatrixView x, const Index &l)
chk_matrix_ncols
Definition: check_input.cc:419
Index nelem() const
Returns the number of elements.
Definition: matpackI.cc:51
#define x1
void chk_if_in_range_exclude_high(const String &x_name, const Numeric &x, const Numeric &x_low, const Numeric &x_high)
chk_if_in_range_exclude_high
Definition: check_input.cc:223
void chk_interpolation_grids(const String &which_interpolation, ConstVectorView old_grid, ConstVectorView new_grid, const Index order, const Numeric &extpolfac, const bool islog)
Check interpolation grids.
Definition: check_input.cc:989
A constant view of a Tensor4.
Definition: matpackIV.h:133
const Index GFIELD3_P_GRID
This file contains the definition of Array.
void chk_not_empty(const String &x_name, const Agenda &x)
chk_not_empty
Definition: check_input.cc:694
const String & get_name() const
Get the name of this gridded field.
Index get_dim() const
Get the dimension of this gridded field.
Index ncols() const
Returns the number of columns.
Definition: matpackI.cc:432
Index nshelves() const
Returns the number of shelves.
Definition: matpackV.cc:44
void chk_if_in_range_exclude_low(const String &x_name, const Numeric &x, const Numeric &x_low, const Numeric &x_high)
chk_if_in_range_exclude_low
Definition: check_input.cc:195
void chk_interpolation_grids_loose_no_data_check(Index &ing_min, Index &ing_max, const String &which_interpolation, ConstVectorView old_grid, ConstVectorView new_grid, const Index order)
Check interpolation grids.
Definition: check_input.cc:773
bool is_same_within_epsilon(const Numeric &a, const Numeric &b, const Numeric &epsilon)
Check, if two numbers agree within a given epsilon.
Definition: logic.cc:351
_CS_string_type str() const
Definition: sstream.h:491
void chk_met_mm_backend(const Matrix &mmb)
Check met_mm_backend.
void chk_latlon_true(const Index &atmosphere_dim, ConstVectorView lat_grid, ConstVectorView lat_true, ConstVectorView lon_true)
chk_latlon_true
void chk_interpolation_pgrids(const String &which_interpolation, ConstVectorView old_pgrid, ConstVectorView new_pgrid, const Index order, const Numeric &extpolfac)
Check log pressure interpolation grids.
void chk_rte_pos(const Index &atmosphere_dim, ConstVectorView rte_pos, const bool &is_rte_pos2)
chk_rte_pos
Index ncols() const
Returns the number of columns.
Definition: matpackIII.h:150
void toupper()
Convert to upper case.
Definition: mystring.h:74
void chk_griddedfield_gridname(const GriddedField &gf, const Index gridindex, const String &gridname)
Check name of grid in GriddedField.
Index nrows() const
Returns the number of rows.
Definition: matpackVI.cc:54
void chk_interpolation_grids_loose(Index &ing_min, Index &ing_max, const String &which_interpolation, ConstVectorView old_grid, ConstVectorView new_grid, ConstVectorView data, const Index order)
Check interpolation grids.
Definition: check_input.cc:735
A constant view of a Tensor5.
Definition: matpackV.h:143
NUMERIC Numeric
The type to use for all floating point numbers.
Definition: matpack.h:33
The Matrix class.
Definition: matpackI.h:1193
Index nlibraries() const
Returns the number of libraries.
Definition: matpackVII.cc:42
Index nelem() const
Number of elements.
Definition: mystring.h:246
void chk_atm_vecfield_lat90(const String &x1_name, ConstTensor3View x1, const String &x2_name, ConstTensor3View x2, const Index &dim, ConstVectorView lat_grid, const Numeric &threshold)
chk_atm_vecfield_lat90
Index nelem() const
Return the number of agenda elements.
Definition: agenda_class.h:266
void chk_interpolation_pgrids_loose_no_data_check(Index &ing_min, Index &ing_max, const String &which_interpolation, ConstVectorView old_pgrid, ConstVectorView new_pgrid, const Index order)
Check log pressure interpolation grids.
Definition: check_input.cc:890
Header file for logic.cc.
Index npages() const
Returns the number of pages.
Definition: matpackIII.h:144
This can be used to make arrays out of anything.
Definition: array.h:40
Index nshelves() const
Returns the number of shelves.
Definition: matpackVI.cc:45
Index ncols() const
Returns the number of columns.
Definition: matpackVI.cc:57
const String & get_grid_name(Index i) const
Get grid name.
void chk_size(const String &x_name, ConstVectorView x, const Index &c)
Runtime check for size of Vector.
Definition: check_input.cc:466
void chk_if_in_range(const String &x_name, const Index &x, const Index &x_low, const Index &x_high)
chk_if_in_range
Definition: check_input.cc:89
#define max(a, b)
A constant view of a Tensor3.
Definition: matpackIII.h:132
void chk_atm_field(const String &x_name, ConstTensor3View x, const Index &dim, ConstVectorView p_grid, ConstVectorView lat_grid, ConstVectorView lon_grid, const bool &chk_lat90)
chk_atm_field (simple fields)
A constant view of a Vector.
Definition: matpackI.h:476
Index npages() const
Returns the number of pages.
Definition: matpackVI.cc:51
Index nshelves() const
Returns the number of shelves.
Definition: matpackVII.cc:48
void chk_vector_length(const String &x_name, ConstVectorView x, const Index &l)
chk_vector_length
Definition: check_input.cc:281
void chk_if_equal(const String &x1_name, const String &x2_name, ConstVectorView v1, ConstVectorView v2, Numeric margin)
chk_if_equal
Definition: check_input.cc:381
A constant view of a Matrix.
Definition: matpackI.h:982
void chk_matrix_nrows(const String &x_name, ConstMatrixView x, const Index &l)
chk_matrix_nrows
Definition: check_input.cc:441
Index npages() const
Returns the number of pages.
Definition: matpackVII.cc:54
Index nbooks() const
Returns the number of books.
Definition: matpackIV.cc:57
void transform(VectorView y, double(&my_func)(double), ConstVectorView x)
A generic transform function for vectors, which can be used to implement mathematical functions opera...
Definition: matpackI.cc:1476
Implementation of gridded fields.
bool is_bool(const Index &x)
Checks if a variable equals 0 or 1.
Definition: logic.cc:50
Index ncols() const
Returns the number of columns.
Definition: matpackV.cc:56
bool is_decreasing(ConstVectorView x)
Checks if a vector is sorted in reversed order and is strictly decreasing.
Definition: logic.cc:252
bool is_size(ConstVectorView x, const Index &n)
Verifies that the size of x is l.
Definition: logic.cc:79
Index nvitrines() const
Returns the number of vitrines.
Definition: matpackVII.cc:45
Index ncols() const
Returns the number of columns.
Definition: matpackVII.cc:60
Index ncols() const
Returns the number of columns.
Definition: matpackIV.cc:66
void chk_atm_grids(const Index &dim, ConstVectorView p_grid, ConstVectorView lat_grid, ConstVectorView lon_grid)
chk_atm_grids
Index nrows() const
Returns the number of rows.
Definition: matpackI.cc:429
Index nbooks() const
Returns the number of books.
Definition: matpackVII.cc:51
Numeric sqrt(const Rational r)
Square root.
Definition: rational.h:620
Index nbooks() const
Returns the number of books.
Definition: matpackVI.cc:48