ARTS  2.2.66
interpolation_poly.cc
Go to the documentation of this file.
1 /* Copyright (C) 2012 Stefan Buehler <sbuehler(at)ltu.se>
2 
3  This program is free software; you can redistribute it and/or modify it
4  under the terms of the GNU General Public License as published by the
5  Free Software Foundation; either version 2, or (at your option) any
6  later version.
7 
8  This program is distributed in the hope that it will be useful,
9  but WITHOUT ANY WARRANTY; without even the implied warranty of
10  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11  GNU General Public License for more details.
12 
13  You should have received a copy of the GNU General Public License
14  along with this program; if not, write to the Free Software
15  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
16  USA. */
17 
39 #include <iostream>
40 #include <cmath>
41 #include "interpolation_poly.h"
42 #include "interpolation.h"
43 #include "logic.h"
44 #include "check_input.h"
45 #include "arts_omp.h"
46 
47 
49 
66 {
67  return a>b ? a:b;
68 }
69 
71 
88 {
89  return a<b ? a:b;
90 }
91 
92 // File-global constants:
93 
95 
107 
109 
128  ConstVectorView old_grid,
129  ConstVectorView new_grid,
130  const Index order,
131  const Numeric& extpolfac)
132 {
133  // Number of points used in the interpolation (order + 1):
134  Index m=order+1;
135 
136  const Index n_old = old_grid.nelem();
137  const Index n_new = new_grid.nelem();
138 
139  // Since we need m interpolation points, the old grid must have a
140  // least m elements.
141  assert(n_old>=m);
142 
143  // Consistently with gridpos, the array size of gp has to be set
144  // outside. Here, we only assert that it is correct:
145  assert( is_size(gp,n_new) );
146 
147  // First call the traditional gridpos to find the grid positions:
148  ArrayOfGridPos gp_trad(n_new);
149  if (n_old>1)
150  {
151  gridpos( gp_trad, old_grid, new_grid, extpolfac );
152  }
153  else if (n_old==1)
154  {
155  // This case is not handled by traditional gridpos, but is ok for zero
156  // order interpolation, so we handle it explicitly here. Since there is
157  // only 1 point in the old grid, it is nearest neighbour to all
158  // interpolation points.
159  for (Index i=0; i<n_new; ++i) {
160  gp_trad[i].idx = 0;
161  gp_trad[i].fd[0] = 0;
162  gp_trad[i].fd[1] = 1;
163  }
164  }
165  else
166  {
167  // We should never be here.
168  assert(false);
169  }
170 
171  for (Index s=0; s<n_new; ++s)
172  {
173 
174  // Here we calculate the index of the first of the range of
175  // points used for interpolation. For linear interpolation this
176  // is identical to j. The idea for this expression is from
177  // Numerical Receipes (Chapter 3, section "after the hunt"), but
178  // there it is for 1-based arrays.
179  Index k;
180  if (m!=1)
181  {
182  k = IMIN(IMAX(gp_trad[s].idx-(m-1)/2, 0),
183  n_old-m);
184  }
185  else
186  {
187  // The above formula for k is not valid for m==1
188  // (nearest neighbour interpolation).
189  if (gp_trad[s].fd[0]<=0.5)
190  k=gp_trad[s].idx;
191  else
192  k=gp_trad[s].idx+1;
193 
194  // It is a matter of definition what we do with the exact fd==0.5 case.
195  // Here I arbitrarily decided to stick with the "left" point (smaller
196  // index). I believe this is consistent with the behaviour for m=3,
197  // where 2 points on the left and 1 point on the right is used. (So,
198  // we always prefer the left side.)
199  }
200 
201  // cout << "m: "<< m << ", k: " << k << endl;
202 
203 
204  // Make gp[s].idx and gp[s].w the right size:
205  gp[s].idx.resize(m);
206  gp[s].w.resize(m);
207 
208  // Calculate w for each interpolation point. In the linear case
209  // these are just the fractional distances to each interpolation
210  // point. The w here correspond exactly to the terms in front of
211  // the yi in Numerical Recipes, 2nd edition, section 3.1,
212  // eq. 3.1.1.
213  for (Index i=0; i<m; ++i)
214  {
215  gp[s].idx[i] = k+i;
216 
217  // Numerical Recipes, 2nd edition, section 3.1, eq. 3.1.1.
218 
219  // Numerator:
220  Numeric num = 1;
221  for (Index j=0; j<m; ++j)
222  if (j!=i)
223  num *= new_grid[s] - old_grid[k+j];
224 
225  // Denominator:
226  Numeric denom = 1;
227  for (Index j=0; j<m; ++j)
228  if (j!=i)
229  denom *= old_grid[k+i] - old_grid[k+j];
230 
231  gp[s].w[i] = num / denom;
232  }
233 
234  // Debugging: Test if sum of all w is 1, as it should be:
235 // Numeric testsum = 0;
236 // for (Index i=0; i<m; ++i) testsum += gp[s].w[i];
237 // cout << "Testsum = " << testsum << endl;
238 
239  }
240 }
241 
242 
244 
267  ConstVectorView old_grid,
268  const Numeric& new_grid,
269  const Index order,
270  const Numeric& extpolfac )
271 {
272  ArrayOfGridPosPoly agp(1);
273  gridpos_poly( agp, old_grid, new_grid, order, extpolfac );
274  gp = agp[0];
275 }
276 
277 
279 
302 void gridpos_poly_longitudinal(const String& error_msg,
303  ArrayOfGridPosPoly& gp,
304  ConstVectorView old_grid,
305  ConstVectorView new_grid,
306  const Index order,
307  const Numeric& extpolfac)
308 {
309  bool global_lons = is_lon_cyclic(old_grid);
310 
311  if (global_lons)
312  gridpos_poly_cyclic_longitudinal(gp, old_grid, new_grid, order, extpolfac);
313  else
314  {
315  if (old_grid[0] >= new_grid[new_grid.nelem()-1])
316  {
317  Vector shifted_old_grid = old_grid;
318  shifted_old_grid -= 360;
319  chk_interpolation_grids(error_msg, shifted_old_grid, new_grid, order, extpolfac);
320 
321  gridpos_poly(gp, shifted_old_grid, new_grid, order, extpolfac);
322  }
323  else if (old_grid[old_grid.nelem()-1] <= new_grid[0])
324  {
325  Vector shifted_old_grid = old_grid;
326  shifted_old_grid += 360;
327  chk_interpolation_grids(error_msg, shifted_old_grid, new_grid, order, extpolfac);
328  gridpos_poly(gp, shifted_old_grid, new_grid, order, extpolfac);
329  }
330  else
331  {
332  chk_interpolation_grids(error_msg, old_grid, new_grid, order, extpolfac);
333  gridpos_poly(gp, old_grid, new_grid, order, extpolfac);
334  }
335  }
336 }
337 
338 
340 
360  ConstVectorView old_grid,
361  ConstVectorView new_grid,
362  const Index order,
363  const Numeric& extpolfac)
364 {
365  assert(is_lon_cyclic(old_grid));
366 
367  Index new_n = old_grid.nelem() - 1;
368  ConstVectorView old_grid_n1 = old_grid[Range(0, new_n)];
369  Range r_left = Range(0, new_n);
370  Range r_right = Range(new_n*2, new_n);
371 
372  Vector large_grid(new_n*3);
373 
374  large_grid[r_left] = old_grid_n1;
375  large_grid[r_left] -= 360.;
376 
377  large_grid[Range(new_n, new_n)] = old_grid_n1;
378 
379  large_grid[r_right] = old_grid_n1;
380  large_grid[r_right] += 360.;
381 
382  gridpos_poly(gp, large_grid, new_grid, order, extpolfac);
383 
384  for (ArrayOfGridPosPoly::iterator itgp = gp.begin(); itgp != gp.end(); itgp++)
385  for (ArrayOfIndex::iterator iti = itgp->idx.begin(); iti != itgp->idx.end(); iti++)
386  *iti %= new_n;
387 }
388 
389 
390 
392 
406 #define LOOPW(x) for ( ConstIterator1D x = t##x##begin; x!=t##x##end; ++x)
407 
409 #define CACHEW(x) const ConstIterator1D t##x##begin = t##x.w.begin(); \
410  const ConstIterator1D t##x##end = t##x.w.end();
411 
413 
418 #define LOOPIDX(x) for (ArrayOfIndex::const_iterator x=t##x##begin; x!=t##x##end; ++x)
419 
421 #define CACHEIDX(x) const ArrayOfIndex::const_iterator t##x##begin = t##x.idx.begin(); \
422  const ArrayOfIndex::const_iterator t##x##end = t##x.idx.end();
423 
424 
426 
434 ostream& operator<<(ostream& os, const GridPosPoly& gp)
435 {
436  os << "idx: " << gp.idx << "\n";
437  os << "w: " << gp.w << "\n";
438 
439 // cout << "Test iterator:\n";
440 // for (ArrayOfIndex::const_iterator x=gp.idx.begin(); x!=gp.idx.end(); ++x)
441 // cout << *x << ":";
442 // cout << "\n";
443 
444  return os;
445 }
446 
447 
448 
449 
450 
451 
453 // Red Interpolation
455 
457 
471  const GridPosPoly& tc )
472 {
473  assert(is_size(itw,tc.w.nelem()));
474 
475  // Interpolation weights are stored in this order (l=lower
476  // u=upper, c=column):
477  // 1. l-c
478  // 2. u-c
479 
480  Index iti = 0;
481 
482  CACHEW(c)
483  LOOPW(c)
484  {
485  itw.get(iti) = *c;
486  ++iti;
487  }
488 }
489 
491 
506  const GridPosPoly& tr,
507  const GridPosPoly& tc )
508 {
509  assert(is_size(itw,
510  tr.w.nelem()*
511  tc.w.nelem()));
512  Index iti = 0;
513 
514  CACHEW(r)
515  CACHEW(c)
516  LOOPW(r)
517  LOOPW(c)
518  {
519  itw.get(iti) = (*r) * (*c);
520  ++iti;
521  }
522 }
523 
525 
541  const GridPosPoly& tp,
542  const GridPosPoly& tr,
543  const GridPosPoly& tc )
544 {
545  assert(is_size(itw,
546  tp.w.nelem()*
547  tr.w.nelem()*
548  tc.w.nelem()));
549 
550  Index iti = 0;
551 
552  CACHEW(p)
553  CACHEW(r)
554  CACHEW(c)
555  LOOPW(p)
556  LOOPW(r)
557  LOOPW(c)
558  {
559  itw.get(iti) = (*p) * (*r) * (*c);
560  ++iti;
561  }
562 }
563 
565 
582  const GridPosPoly& tb,
583  const GridPosPoly& tp,
584  const GridPosPoly& tr,
585  const GridPosPoly& tc )
586 {
587  assert(is_size(itw,
588  tb.w.nelem()*
589  tp.w.nelem()*
590  tr.w.nelem()*
591  tc.w.nelem()));
592 
593  Index iti = 0;
594 
595  CACHEW(b)
596  CACHEW(p)
597  CACHEW(r)
598  CACHEW(c)
599  LOOPW(b)
600  LOOPW(p)
601  LOOPW(r)
602  LOOPW(c)
603  {
604  itw.get(iti) = (*b) * (*p) * (*r) * (*c);
605  ++iti;
606  }
607 }
608 
610 
628  const GridPosPoly& ts,
629  const GridPosPoly& tb,
630  const GridPosPoly& tp,
631  const GridPosPoly& tr,
632  const GridPosPoly& tc )
633 {
634  assert(is_size(itw,
635  ts.w.nelem()*
636  tb.w.nelem()*
637  tp.w.nelem()*
638  tr.w.nelem()*
639  tc.w.nelem()));
640 
641  Index iti = 0;
642 
643  CACHEW(s)
644  CACHEW(b)
645  CACHEW(p)
646  CACHEW(r)
647  CACHEW(c)
648  LOOPW(s)
649  LOOPW(b)
650  LOOPW(p)
651  LOOPW(r)
652  LOOPW(c)
653  {
654  itw.get(iti) = (*s) * (*b) * (*p) * (*r) * (*c);
655  ++iti;
656  }
657 }
658 
660 
679  const GridPosPoly& tv,
680  const GridPosPoly& ts,
681  const GridPosPoly& tb,
682  const GridPosPoly& tp,
683  const GridPosPoly& tr,
684  const GridPosPoly& tc )
685 {
686  assert(is_size(itw,
687  tv.w.nelem()*
688  ts.w.nelem()*
689  tb.w.nelem()*
690  tp.w.nelem()*
691  tr.w.nelem()*
692  tc.w.nelem()));
693 
694  Index iti = 0;
695 
696  CACHEW(v)
697  CACHEW(s)
698  CACHEW(b)
699  CACHEW(p)
700  CACHEW(r)
701  CACHEW(c)
702  LOOPW(v)
703  LOOPW(s)
704  LOOPW(b)
705  LOOPW(p)
706  LOOPW(r)
707  LOOPW(c)
708  {
709  itw.get(iti) = (*v) * (*s) * (*b) * (*p) * (*r) * (*c);
710  ++iti;
711  }
712 }
713 
715 
731  ConstVectorView a,
732  const GridPosPoly& tc )
733 {
734  assert(is_size(itw,tc.w.nelem()));
735 
736  // Check that interpolation weights are valid. The sum of all
737  // weights (last dimension) must always be approximately one.
738  assert( is_same_within_epsilon( itw.sum(),
739  1,
740  sum_check_epsilon ) );
741 
742  // To store interpolated value:
743  Numeric tia = 0;
744 
745  Index iti = 0;
746  CACHEIDX(c)
747  LOOPIDX(c)
748  {
749  tia += a.get(*c) * itw.get(iti);
750  ++iti;
751  }
752 
753  return tia;
754 }
755 
757 
774  ConstMatrixView a,
775  const GridPosPoly& tr,
776  const GridPosPoly& tc )
777 {
778  assert(is_size(itw,
779  tr.w.nelem()*
780  tc.w.nelem()));
781 
782  // Check that interpolation weights are valid. The sum of all
783  // weights (last dimension) must always be approximately one.
784  assert( is_same_within_epsilon( itw.sum(),
785  1,
786  sum_check_epsilon ) );
787 
788  // To store interpolated value:
789  Numeric tia = 0;
790 
791  Index iti = 0;
792  CACHEIDX(r)
793  CACHEIDX(c)
794  LOOPIDX(r)
795  LOOPIDX(c)
796  {
797  tia += a.get(*r,
798  *c) * itw.get(iti);
799  ++iti;
800  }
801 
802  return tia;
803 }
804 
806 
824  ConstTensor3View a,
825  const GridPosPoly& tp,
826  const GridPosPoly& tr,
827  const GridPosPoly& tc )
828 {
829  assert(is_size(itw,
830  tp.w.nelem()*
831  tr.w.nelem()*
832  tc.w.nelem()));
833 
834  // Check that interpolation weights are valid. The sum of all
835  // weights (last dimension) must always be approximately one.
836  assert( is_same_within_epsilon( itw.sum(),
837  1,
838  sum_check_epsilon ) );
839 
840  // To store interpolated value:
841  Numeric tia = 0;
842 
843  Index iti = 0;
844  CACHEIDX(p)
845  CACHEIDX(r)
846  CACHEIDX(c)
847  LOOPIDX(p)
848  LOOPIDX(r)
849  LOOPIDX(c)
850  {
851  tia += a.get(*p,
852  *r,
853  *c) * itw.get(iti);
854  ++iti;
855  }
856 
857  return tia;
858 }
859 
861 
880  ConstTensor4View a,
881  const GridPosPoly& tb,
882  const GridPosPoly& tp,
883  const GridPosPoly& tr,
884  const GridPosPoly& tc )
885 {
886  assert(is_size(itw,
887  tb.w.nelem()*
888  tp.w.nelem()*
889  tr.w.nelem()*
890  tc.w.nelem()));
891 
892  // Check that interpolation weights are valid. The sum of all
893  // weights (last dimension) must always be approximately one.
894  assert( is_same_within_epsilon( itw.sum(),
895  1,
896  sum_check_epsilon ) );
897 
898  // To store interpolated value:
899  Numeric tia = 0;
900 
901  Index iti = 0;
902  CACHEIDX(b)
903  CACHEIDX(p)
904  CACHEIDX(r)
905  CACHEIDX(c)
906  LOOPIDX(b)
907  LOOPIDX(p)
908  LOOPIDX(r)
909  LOOPIDX(c)
910  {
911  tia += a.get(*b,
912  *p,
913  *r,
914  *c) * itw.get(iti);
915  ++iti;
916  }
917 
918  return tia;
919 }
920 
922 
942  ConstTensor5View a,
943  const GridPosPoly& ts,
944  const GridPosPoly& tb,
945  const GridPosPoly& tp,
946  const GridPosPoly& tr,
947  const GridPosPoly& tc )
948 {
949  assert(is_size(itw,
950  ts.w.nelem()*
951  tb.w.nelem()*
952  tp.w.nelem()*
953  tr.w.nelem()*
954  tc.w.nelem()));
955 
956  // Check that interpolation weights are valid. The sum of all
957  // weights (last dimension) must always be approximately one.
958  assert( is_same_within_epsilon( itw.sum(),
959  1,
960  sum_check_epsilon ) );
961 
962  // To store interpolated value:
963  Numeric tia = 0;
964 
965  Index iti = 0;
966  CACHEIDX(s)
967  CACHEIDX(b)
968  CACHEIDX(p)
969  CACHEIDX(r)
970  CACHEIDX(c)
971  LOOPIDX(s)
972  LOOPIDX(b)
973  LOOPIDX(p)
974  LOOPIDX(r)
975  LOOPIDX(c)
976  {
977  tia += a.get(*s,
978  *b,
979  *p,
980  *r,
981  *c) * itw.get(iti);
982  ++iti;
983  }
984 
985  return tia;
986 }
987 
989 
1010  ConstTensor6View a,
1011  const GridPosPoly& tv,
1012  const GridPosPoly& ts,
1013  const GridPosPoly& tb,
1014  const GridPosPoly& tp,
1015  const GridPosPoly& tr,
1016  const GridPosPoly& tc )
1017 {
1018  assert(is_size(itw,
1019  tv.w.nelem()*
1020  ts.w.nelem()*
1021  tb.w.nelem()*
1022  tp.w.nelem()*
1023  tr.w.nelem()*
1024  tc.w.nelem()));
1025 
1026  // Check that interpolation weights are valid. The sum of all
1027  // weights (last dimension) must always be approximately one.
1028  assert( is_same_within_epsilon( itw.sum(),
1029  1,
1030  sum_check_epsilon ) );
1031 
1032  // To store interpolated value:
1033  Numeric tia = 0;
1034 
1035  Index iti = 0;
1036  CACHEIDX(v)
1037  CACHEIDX(s)
1038  CACHEIDX(b)
1039  CACHEIDX(p)
1040  CACHEIDX(r)
1041  CACHEIDX(c)
1042  LOOPIDX(v)
1043  LOOPIDX(s)
1044  LOOPIDX(b)
1045  LOOPIDX(p)
1046  LOOPIDX(r)
1047  LOOPIDX(c)
1048  {
1049  tia += a.get(*v,
1050  *s,
1051  *b,
1052  *p,
1053  *r,
1054  *c) * itw.get(iti);
1055  ++iti;
1056  }
1057 
1058  return tia;
1059 }
1060 
1061 
1062 
1064 // Blue interpolation
1066 
1068 
1084  const ArrayOfGridPosPoly& cgp )
1085 {
1086  Index n = cgp.nelem();
1087  assert(is_size(itw,n,
1088  cgp[0].w.nelem()));
1089 
1090 
1091  // We have to loop all the points in the sequence:
1092  for ( Index i=0; i<n; ++i )
1093  {
1094  // Current grid positions:
1095  const GridPosPoly& tc = cgp[i];
1096 
1097  // Interpolation weights are stored in this order (l=lower
1098  // u=upper, c=column):
1099  // 1. l-c
1100  // 2. u-c
1101 
1102  Index iti = 0;
1103 
1104  // We could use a straight-forward for loop here:
1105  //
1106  // for ( Index c=1; c>=0; --c )
1107  // {
1108  // ti[iti] = tc.fd[c];
1109  // ++iti;
1110  // }
1111  //
1112  // However, it is slightly faster to use pointers (I tried it,
1113  // the speed gain is about 20%). So we should write something
1114  // like:
1115  //
1116  // for ( const Numeric* c=&tc.fd[1]; c>=&tc.fd[0]; --c )
1117  // {
1118  // ti[iti] = *c;
1119  // ++iti;
1120  // }
1121  //
1122  // For higher dimensions we have to nest these loops. To avoid
1123  // typos and safe typing, I use the LOOPW macro, which expands
1124  // to the for loop above. Note: NO SEMICOLON AFTER THE LOOPW
1125  // COMMAND!
1126 
1127  CACHEW(c)
1128  LOOPW(c)
1129  {
1130  itw.get(i,iti) = *c;
1131  ++iti;
1132  }
1133  }
1134 }
1135 
1137 
1159  const ArrayOfGridPosPoly& rgp,
1160  const ArrayOfGridPosPoly& cgp )
1161 {
1162  Index n = cgp.nelem();
1163  assert(is_size(rgp,n)); // rgp must have same size as cgp.
1164  assert(is_size(itw,n,
1165  rgp[0].w.nelem()*
1166  cgp[0].w.nelem()));
1167 
1168 
1169  // We have to loop all the points in the sequence:
1170  for ( Index i=0; i<n; ++i )
1171  {
1172  // Current grid positions:
1173  const GridPosPoly& tr = rgp[i];
1174  const GridPosPoly& tc = cgp[i];
1175 
1176  // Interpolation weights are stored in this order (l=lower
1177  // u=upper, r=row, c=column):
1178  // 1. l-r l-c
1179  // 2. l-r u-c
1180  // 3. u-r l-c
1181  // 4. u-r u-c
1182 
1183  Index iti = 0;
1184 
1185  CACHEW(r)
1186  CACHEW(c)
1187  LOOPW(r)
1188  LOOPW(c)
1189  {
1190  itw.get(i,iti) = (*r) * (*c);
1191  ++iti;
1192  }
1193  }
1194 }
1195 
1197 
1220  const ArrayOfGridPosPoly& pgp,
1221  const ArrayOfGridPosPoly& rgp,
1222  const ArrayOfGridPosPoly& cgp )
1223 {
1224  Index n = cgp.nelem();
1225  assert(is_size(pgp,n)); // pgp must have same size as cgp.
1226  assert(is_size(rgp,n)); // rgp must have same size as cgp.
1227  assert(is_size(itw,n,
1228  pgp[0].w.nelem()*
1229  rgp[0].w.nelem()*
1230  cgp[0].w.nelem()));
1231 
1232 
1233  // We have to loop all the points in the sequence:
1234  for ( Index i=0; i<n; ++i )
1235  {
1236  // Current grid positions:
1237  const GridPosPoly& tp = pgp[i];
1238  const GridPosPoly& tr = rgp[i];
1239  const GridPosPoly& tc = cgp[i];
1240 
1241  Index iti = 0;
1242  CACHEW(p)
1243  CACHEW(r)
1244  CACHEW(c)
1245  LOOPW(p)
1246  LOOPW(r)
1247  LOOPW(c)
1248  {
1249  itw.get(i,iti) = (*p) * (*r) * (*c);
1250  ++iti;
1251  }
1252  }
1253 }
1254 
1256 
1280  const ArrayOfGridPosPoly& bgp,
1281  const ArrayOfGridPosPoly& pgp,
1282  const ArrayOfGridPosPoly& rgp,
1283  const ArrayOfGridPosPoly& cgp )
1284 {
1285  Index n = cgp.nelem();
1286  assert(is_size(bgp,n)); // bgp must have same size as cgp.
1287  assert(is_size(pgp,n)); // pgp must have same size as cgp.
1288  assert(is_size(rgp,n)); // rgp must have same size as cgp.
1289  assert(is_size(itw,n,
1290  bgp[0].w.nelem()*
1291  pgp[0].w.nelem()*
1292  rgp[0].w.nelem()*
1293  cgp[0].w.nelem()));
1294 
1295 
1296  // We have to loop all the points in the sequence:
1297  for ( Index i=0; i<n; ++i )
1298  {
1299  // Current grid positions:
1300  const GridPosPoly& tb = bgp[i];
1301  const GridPosPoly& tp = pgp[i];
1302  const GridPosPoly& tr = rgp[i];
1303  const GridPosPoly& tc = cgp[i];
1304 
1305  Index iti = 0;
1306  CACHEW(b)
1307  CACHEW(p)
1308  CACHEW(r)
1309  CACHEW(c)
1310  LOOPW(b)
1311  LOOPW(p)
1312  LOOPW(r)
1313  LOOPW(c)
1314  {
1315  itw.get(i,iti) = (*b) * (*p) * (*r) * (*c);
1316  ++iti;
1317  }
1318  }
1319 }
1320 
1322 
1347  const ArrayOfGridPosPoly& sgp,
1348  const ArrayOfGridPosPoly& bgp,
1349  const ArrayOfGridPosPoly& pgp,
1350  const ArrayOfGridPosPoly& rgp,
1351  const ArrayOfGridPosPoly& cgp )
1352 {
1353  Index n = cgp.nelem();
1354  assert(is_size(sgp,n)); // sgp must have same size as cgp.
1355  assert(is_size(bgp,n)); // bgp must have same size as cgp.
1356  assert(is_size(pgp,n)); // pgp must have same size as cgp.
1357  assert(is_size(rgp,n)); // rgp must have same size as cgp.
1358  assert(is_size(itw,n,
1359  sgp[0].w.nelem()*
1360  bgp[0].w.nelem()*
1361  pgp[0].w.nelem()*
1362  rgp[0].w.nelem()*
1363  cgp[0].w.nelem()));
1364 
1365 
1366  // We have to loop all the points in the sequence:
1367  for ( Index i=0; i<n; ++i )
1368  {
1369  // Current grid positions:
1370  const GridPosPoly& ts = sgp[i];
1371  const GridPosPoly& tb = bgp[i];
1372  const GridPosPoly& tp = pgp[i];
1373  const GridPosPoly& tr = rgp[i];
1374  const GridPosPoly& tc = cgp[i];
1375 
1376  Index iti = 0;
1377  CACHEW(s)
1378  CACHEW(b)
1379  CACHEW(p)
1380  CACHEW(r)
1381  CACHEW(c)
1382  LOOPW(s)
1383  LOOPW(b)
1384  LOOPW(p)
1385  LOOPW(r)
1386  LOOPW(c)
1387  {
1388  itw.get(i,iti) = (*s) * (*b) * (*p) * (*r) * (*c);
1389  ++iti;
1390  }
1391  }
1392 }
1393 
1395 
1421  const ArrayOfGridPosPoly& vgp,
1422  const ArrayOfGridPosPoly& sgp,
1423  const ArrayOfGridPosPoly& bgp,
1424  const ArrayOfGridPosPoly& pgp,
1425  const ArrayOfGridPosPoly& rgp,
1426  const ArrayOfGridPosPoly& cgp )
1427 {
1428  Index n = cgp.nelem();
1429  assert(is_size(vgp,n)); // vgp must have same size as cgp.
1430  assert(is_size(sgp,n)); // sgp must have same size as cgp.
1431  assert(is_size(bgp,n)); // bgp must have same size as cgp.
1432  assert(is_size(pgp,n)); // pgp must have same size as cgp.
1433  assert(is_size(rgp,n)); // rgp must have same size as cgp.
1434  assert(is_size(itw,n,
1435  vgp[0].w.nelem()*
1436  sgp[0].w.nelem()*
1437  bgp[0].w.nelem()*
1438  pgp[0].w.nelem()*
1439  rgp[0].w.nelem()*
1440  cgp[0].w.nelem()));
1441 
1442 
1443  // We have to loop all the points in the sequence:
1444  for ( Index i=0; i<n; ++i )
1445  {
1446  // Current grid positions:
1447  const GridPosPoly& tv = vgp[i];
1448  const GridPosPoly& ts = sgp[i];
1449  const GridPosPoly& tb = bgp[i];
1450  const GridPosPoly& tp = pgp[i];
1451  const GridPosPoly& tr = rgp[i];
1452  const GridPosPoly& tc = cgp[i];
1453 
1454  Index iti = 0;
1455  CACHEW(v)
1456  CACHEW(s)
1457  CACHEW(b)
1458  CACHEW(p)
1459  CACHEW(r)
1460  CACHEW(c)
1461  LOOPW(v)
1462  LOOPW(s)
1463  LOOPW(b)
1464  LOOPW(p)
1465  LOOPW(r)
1466  LOOPW(c)
1467  {
1468  itw.get(i,iti) = (*v) * (*s) * (*b) * (*p) * (*r) * (*c);
1469  ++iti;
1470  }
1471  }
1472 }
1473 
1475 
1492  ConstMatrixView itw,
1493  ConstVectorView a,
1494  const ArrayOfGridPosPoly& cgp)
1495 {
1496  Index n = cgp.nelem();
1497  assert(is_size(ia,n)); // ia must have same size as cgp.
1498  assert(is_size(itw,n,
1499  cgp[0].w.nelem()));
1500 
1501  // Check that interpolation weights are valid. The sum of all
1502  // weights (last dimension) must always be approximately one. We
1503  // only check the first element.
1504  assert( is_same_within_epsilon( itw(0,Range(joker)).sum(),
1505  1,
1506  sum_check_epsilon ) );
1507 
1508  // We have to loop all the points in the sequence:
1509  for ( Index i=0; i<n; ++i )
1510  {
1511  // Current grid positions:
1512  const GridPosPoly& tc = cgp[i];
1513 
1514  // Get handle to current element of output vector and initialize
1515  // it to zero:
1516  Numeric& tia = ia[i];
1517  tia = 0;
1518 
1519  Index iti = 0;
1520  CACHEIDX(c)
1521  LOOPIDX(c)
1522  {
1523  tia += a.get(*c) * itw.get(i,iti);
1524  ++iti;
1525  }
1526  }
1527 }
1528 
1530 
1552  ConstMatrixView itw,
1553  ConstMatrixView a,
1554  const ArrayOfGridPosPoly& rgp,
1555  const ArrayOfGridPosPoly& cgp)
1556 {
1557  Index n = cgp.nelem();
1558  assert(is_size(ia,n)); // ia must have same size as cgp.
1559  assert(is_size(rgp,n)); // rgp must have same size as cgp.
1560  assert(is_size(itw,n,
1561  rgp[0].w.nelem()*
1562  cgp[0].w.nelem()));
1563 
1564  // Check that interpolation weights are valid. The sum of all
1565  // weights (last dimension) must always be approximately one. We
1566  // only check the first element.
1567  assert( is_same_within_epsilon( itw(0,Range(joker)).sum(),
1568  1,
1569  sum_check_epsilon ) );
1570 
1571  // We have to loop all the points in the sequence:
1572  for ( Index i=0; i<n; ++i )
1573  {
1574  // Current grid positions:
1575  const GridPosPoly& tr = rgp[i];
1576  const GridPosPoly& tc = cgp[i];
1577 
1578  // Get handle to current element of output vector and initialize
1579  // it to zero:
1580  Numeric& tia = ia[i];
1581  tia = 0;
1582 
1583  Index iti = 0;
1584  CACHEIDX(r)
1585  CACHEIDX(c)
1586  LOOPIDX(r)
1587  LOOPIDX(c)
1588  {
1589  tia += a.get(*r,
1590  *c) * itw.get(i,iti);
1591  ++iti;
1592  }
1593  }
1594 }
1595 
1597 
1620  ConstMatrixView itw,
1621  ConstTensor3View a,
1622  const ArrayOfGridPosPoly& pgp,
1623  const ArrayOfGridPosPoly& rgp,
1624  const ArrayOfGridPosPoly& cgp)
1625 {
1626  Index n = cgp.nelem();
1627  assert(is_size(ia,n)); // ia must have same size as cgp.
1628  assert(is_size(pgp,n)); // pgp must have same size as cgp.
1629  assert(is_size(rgp,n)); // rgp must have same size as cgp.
1630  assert(is_size(itw,n,
1631  pgp[0].w.nelem()*
1632  rgp[0].w.nelem()*
1633  cgp[0].w.nelem()));
1634 
1635  // Check that interpolation weights are valid. The sum of all
1636  // weights (last dimension) must always be approximately one. We
1637  // only check the first element.
1638  assert( is_same_within_epsilon( itw(0,Range(joker)).sum(),
1639  1,
1640  sum_check_epsilon ) );
1641 
1642  // We have to loop all the points in the sequence:
1643  for ( Index i=0; i<n; ++i )
1644  {
1645  // Current grid positions:
1646  const GridPosPoly& tp = pgp[i];
1647  const GridPosPoly& tr = rgp[i];
1648  const GridPosPoly& tc = cgp[i];
1649 
1650  // Get handle to current element of output vector and initialize
1651  // it to zero:
1652  Numeric& tia = ia[i];
1653  tia = 0;
1654 
1655  Index iti = 0;
1656  CACHEIDX(p)
1657  CACHEIDX(r)
1658  CACHEIDX(c)
1659  LOOPIDX(p)
1660  LOOPIDX(r)
1661  LOOPIDX(c)
1662  {
1663  tia += a.get(*p,
1664  *r,
1665  *c) * itw.get(i,iti);
1666  ++iti;
1667  }
1668  }
1669 }
1670 
1672 
1696  ConstMatrixView itw,
1697  ConstTensor4View a,
1698  const ArrayOfGridPosPoly& bgp,
1699  const ArrayOfGridPosPoly& pgp,
1700  const ArrayOfGridPosPoly& rgp,
1701  const ArrayOfGridPosPoly& cgp)
1702 {
1703  Index n = cgp.nelem();
1704  assert(is_size(ia,n)); // ia must have same size as cgp.
1705  assert(is_size(bgp,n)); // bgp must have same size as cgp.
1706  assert(is_size(pgp,n)); // pgp must have same size as cgp.
1707  assert(is_size(rgp,n)); // rgp must have same size as cgp.
1708  assert(is_size(itw,n,
1709  bgp[0].w.nelem()*
1710  pgp[0].w.nelem()*
1711  rgp[0].w.nelem()*
1712  cgp[0].w.nelem()));
1713 
1714  // Check that interpolation weights are valid. The sum of all
1715  // weights (last dimension) must always be approximately one. We
1716  // only check the first element.
1717  assert( is_same_within_epsilon( itw(0,Range(joker)).sum(),
1718  1,
1719  sum_check_epsilon ) );
1720 
1721  // We have to loop all the points in the sequence:
1722  for ( Index i=0; i<n; ++i )
1723  {
1724  // Current grid positions:
1725  const GridPosPoly& tb = bgp[i];
1726  const GridPosPoly& tp = pgp[i];
1727  const GridPosPoly& tr = rgp[i];
1728  const GridPosPoly& tc = cgp[i];
1729 
1730  // Get handle to current element of output vector and initialize
1731  // it to zero:
1732  Numeric& tia = ia[i];
1733  tia = 0;
1734 
1735  Index iti = 0;
1736  CACHEIDX(b)
1737  CACHEIDX(p)
1738  CACHEIDX(r)
1739  CACHEIDX(c)
1740  LOOPIDX(b)
1741  LOOPIDX(p)
1742  LOOPIDX(r)
1743  LOOPIDX(c)
1744  {
1745  tia += a.get(*b,
1746  *p,
1747  *r,
1748  *c) * itw.get(i,iti);
1749  ++iti;
1750  }
1751  }
1752 }
1753 
1755 
1780  ConstMatrixView itw,
1781  ConstTensor5View a,
1782  const ArrayOfGridPosPoly& sgp,
1783  const ArrayOfGridPosPoly& bgp,
1784  const ArrayOfGridPosPoly& pgp,
1785  const ArrayOfGridPosPoly& rgp,
1786  const ArrayOfGridPosPoly& cgp)
1787 {
1788  Index n = cgp.nelem();
1789  assert(is_size(ia,n)); // ia must have same size as cgp.
1790  assert(is_size(sgp,n)); // sgp must have same size as cgp.
1791  assert(is_size(bgp,n)); // bgp must have same size as cgp.
1792  assert(is_size(pgp,n)); // pgp must have same size as cgp.
1793  assert(is_size(rgp,n)); // rgp must have same size as cgp.
1794  assert(is_size(itw,n,
1795  sgp[0].w.nelem()*
1796  bgp[0].w.nelem()*
1797  pgp[0].w.nelem()*
1798  rgp[0].w.nelem()*
1799  cgp[0].w.nelem()));
1800 
1801  // Check that interpolation weights are valid. The sum of all
1802  // weights (last dimension) must always be approximately one. We
1803  // only check the first element.
1804  assert( is_same_within_epsilon( itw(0,Range(joker)).sum(),
1805  1,
1806  sum_check_epsilon ) );
1807 
1808  // We have to loop all the points in the sequence:
1809  for ( Index i=0; i<n; ++i )
1810  {
1811  // Current grid positions:
1812  const GridPosPoly& ts = sgp[i];
1813  const GridPosPoly& tb = bgp[i];
1814  const GridPosPoly& tp = pgp[i];
1815  const GridPosPoly& tr = rgp[i];
1816  const GridPosPoly& tc = cgp[i];
1817 
1818  // Get handle to current element of output vector and initialize
1819  // it to zero:
1820  Numeric& tia = ia[i];
1821  tia = 0;
1822 
1823  Index iti = 0;
1824  CACHEIDX(s)
1825  CACHEIDX(b)
1826  CACHEIDX(p)
1827  CACHEIDX(r)
1828  CACHEIDX(c)
1829  LOOPIDX(s)
1830  LOOPIDX(b)
1831  LOOPIDX(p)
1832  LOOPIDX(r)
1833  LOOPIDX(c)
1834  {
1835  tia += a.get(*s,
1836  *b,
1837  *p,
1838  *r,
1839  *c) * itw.get(i,iti);
1840  ++iti;
1841  }
1842  }
1843 }
1844 
1846 
1872  ConstMatrixView itw,
1873  ConstTensor6View a,
1874  const ArrayOfGridPosPoly& vgp,
1875  const ArrayOfGridPosPoly& sgp,
1876  const ArrayOfGridPosPoly& bgp,
1877  const ArrayOfGridPosPoly& pgp,
1878  const ArrayOfGridPosPoly& rgp,
1879  const ArrayOfGridPosPoly& cgp)
1880 {
1881  Index n = cgp.nelem();
1882  assert(is_size(ia,n)); // ia must have same size as cgp.
1883  assert(is_size(vgp,n)); // vgp must have same size as cgp.
1884  assert(is_size(sgp,n)); // sgp must have same size as cgp.
1885  assert(is_size(bgp,n)); // bgp must have same size as cgp.
1886  assert(is_size(pgp,n)); // pgp must have same size as cgp.
1887  assert(is_size(rgp,n)); // rgp must have same size as cgp.
1888  assert(is_size(itw,n,
1889  vgp[0].w.nelem()*
1890  sgp[0].w.nelem()*
1891  bgp[0].w.nelem()*
1892  pgp[0].w.nelem()*
1893  rgp[0].w.nelem()*
1894  cgp[0].w.nelem()));
1895 
1896  // Check that interpolation weights are valid. The sum of all
1897  // weights (last dimension) must always be approximately one. We
1898  // only check the first element.
1899  assert( is_same_within_epsilon( itw(0,Range(joker)).sum(),
1900  1,
1901  sum_check_epsilon ) );
1902 
1903  // We have to loop all the points in the sequence:
1904  for ( Index i=0; i<n; ++i )
1905  {
1906  // Current grid positions:
1907  const GridPosPoly& tv = vgp[i];
1908  const GridPosPoly& ts = sgp[i];
1909  const GridPosPoly& tb = bgp[i];
1910  const GridPosPoly& tp = pgp[i];
1911  const GridPosPoly& tr = rgp[i];
1912  const GridPosPoly& tc = cgp[i];
1913 
1914  // Get handle to current element of output vector and initialize
1915  // it to zero:
1916  Numeric& tia = ia[i];
1917  tia = 0;
1918 
1919  Index iti = 0;
1920  CACHEIDX(v)
1921  CACHEIDX(s)
1922  CACHEIDX(b)
1923  CACHEIDX(p)
1924  CACHEIDX(r)
1925  CACHEIDX(c)
1926  LOOPIDX(v)
1927  LOOPIDX(s)
1928  LOOPIDX(b)
1929  LOOPIDX(p)
1930  LOOPIDX(r)
1931  LOOPIDX(c)
1932  {
1933  tia += a.get(*v,
1934  *s,
1935  *b,
1936  *p,
1937  *r,
1938  *c) * itw.get(i,iti);
1939  ++iti;
1940  }
1941  }
1942 }
1943 
1945 // Green interpolation
1947 
1949 
1971  const ArrayOfGridPosPoly& rgp,
1972  const ArrayOfGridPosPoly& cgp )
1973 {
1974  Index nr = rgp.nelem();
1975  Index nc = cgp.nelem();
1976  assert(is_size(itw,nr,nc,
1977  rgp[0].w.nelem()*
1978  cgp[0].w.nelem()));
1979 
1980 
1981  // We have to loop all the points in the new grid:
1982  for ( Index ir=0; ir<nr; ++ir )
1983  {
1984  // Current grid position:
1985  const GridPosPoly& tr = rgp[ir];
1986  CACHEW(r)
1987 
1988  for ( Index ic=0; ic<nc; ++ic )
1989  {
1990  // Current grid position:
1991  const GridPosPoly& tc = cgp[ic];
1992  CACHEW(c)
1993 
1994  // Interpolation weights are stored in this order (l=lower
1995  // u=upper, r=row, c=column):
1996  // 1. l-r l-c
1997  // 2. l-r u-c
1998  // 3. u-r l-c
1999  // 4. u-r u-c
2000 
2001  Index iti = 0;
2002 
2003  LOOPW(r)
2004  LOOPW(c)
2005  {
2006  itw.get(ir,ic,iti) = (*r) * (*c);
2007  ++iti;
2008  }
2009  }
2010  }
2011 }
2012 
2014 
2037  const ArrayOfGridPosPoly& pgp,
2038  const ArrayOfGridPosPoly& rgp,
2039  const ArrayOfGridPosPoly& cgp )
2040 {
2041  Index np = pgp.nelem();
2042  Index nr = rgp.nelem();
2043  Index nc = cgp.nelem();
2044 
2045  assert(is_size(itw,np,nr,nc,
2046  pgp[0].w.nelem()*
2047  rgp[0].w.nelem()*
2048  cgp[0].w.nelem()));
2049 
2050  // We have to loop all the points in the new grid:
2051  for ( Index ip=0; ip<np; ++ip )
2052  {
2053  const GridPosPoly& tp = pgp[ip];
2054  CACHEW(p)
2055  for ( Index ir=0; ir<nr; ++ir )
2056  {
2057  const GridPosPoly& tr = rgp[ir];
2058  CACHEW(r)
2059  for ( Index ic=0; ic<nc; ++ic )
2060  {
2061  const GridPosPoly& tc = cgp[ic];
2062  CACHEW(c)
2063 
2064  Index iti = 0;
2065 
2066  LOOPW(p)
2067  LOOPW(r)
2068  LOOPW(c)
2069  {
2070  itw.get(ip,ir,ic,iti) =
2071  (*p) * (*r) * (*c);
2072  ++iti;
2073  }
2074  }
2075  }
2076  }
2077 }
2078 
2080 
2104  const ArrayOfGridPosPoly& bgp,
2105  const ArrayOfGridPosPoly& pgp,
2106  const ArrayOfGridPosPoly& rgp,
2107  const ArrayOfGridPosPoly& cgp )
2108 {
2109  Index nb = bgp.nelem();
2110  Index np = pgp.nelem();
2111  Index nr = rgp.nelem();
2112  Index nc = cgp.nelem();
2113 
2114  assert(is_size(itw,nb,np,nr,nc,
2115  bgp[0].w.nelem()*
2116  pgp[0].w.nelem()*
2117  rgp[0].w.nelem()*
2118  cgp[0].w.nelem()));
2119 
2120  // We have to loop all the points in the new grid:
2121  for ( Index ib=0; ib<nb; ++ib )
2122  {
2123  const GridPosPoly& tb = bgp[ib];
2124  CACHEW(b)
2125  for ( Index ip=0; ip<np; ++ip )
2126  {
2127  const GridPosPoly& tp = pgp[ip];
2128  CACHEW(p)
2129  for ( Index ir=0; ir<nr; ++ir )
2130  {
2131  const GridPosPoly& tr = rgp[ir];
2132  CACHEW(r)
2133  for ( Index ic=0; ic<nc; ++ic )
2134  {
2135  const GridPosPoly& tc = cgp[ic];
2136  CACHEW(c)
2137 
2138  Index iti = 0;
2139 
2140  LOOPW(b)
2141  LOOPW(p)
2142  LOOPW(r)
2143  LOOPW(c)
2144  {
2145  itw.get(ib,ip,ir,ic,iti) =
2146  (*b) * (*p) * (*r) * (*c);
2147  ++iti;
2148  }
2149  }
2150  }
2151  }
2152  }
2153 }
2154 
2156 
2181  const ArrayOfGridPosPoly& sgp,
2182  const ArrayOfGridPosPoly& bgp,
2183  const ArrayOfGridPosPoly& pgp,
2184  const ArrayOfGridPosPoly& rgp,
2185  const ArrayOfGridPosPoly& cgp )
2186 {
2187  Index ns = sgp.nelem();
2188  Index nb = bgp.nelem();
2189  Index np = pgp.nelem();
2190  Index nr = rgp.nelem();
2191  Index nc = cgp.nelem();
2192 
2193  assert(is_size(itw,ns,nb,np,nr,nc,
2194  sgp[0].w.nelem()*
2195  bgp[0].w.nelem()*
2196  pgp[0].w.nelem()*
2197  rgp[0].w.nelem()*
2198  cgp[0].w.nelem()));
2199 
2200  // We have to loop all the points in the new grid:
2201  for ( Index is=0; is<ns; ++is )
2202  {
2203  const GridPosPoly& ts = sgp[is];
2204  CACHEW(s)
2205  for ( Index ib=0; ib<nb; ++ib )
2206  {
2207  const GridPosPoly& tb = bgp[ib];
2208  CACHEW(b)
2209  for ( Index ip=0; ip<np; ++ip )
2210  {
2211  const GridPosPoly& tp = pgp[ip];
2212  CACHEW(p)
2213  for ( Index ir=0; ir<nr; ++ir )
2214  {
2215  const GridPosPoly& tr = rgp[ir];
2216  CACHEW(r)
2217  for ( Index ic=0; ic<nc; ++ic )
2218  {
2219  const GridPosPoly& tc = cgp[ic];
2220  CACHEW(c)
2221 
2222  Index iti = 0;
2223 
2224  LOOPW(s)
2225  LOOPW(b)
2226  LOOPW(p)
2227  LOOPW(r)
2228  LOOPW(c)
2229  {
2230  itw.get(is,ib,ip,ir,ic,iti) =
2231  (*s) * (*b) * (*p) * (*r) * (*c);
2232  ++iti;
2233  }
2234  }
2235  }
2236  }
2237  }
2238  }
2239 }
2240 
2242 
2268  const ArrayOfGridPosPoly& vgp,
2269  const ArrayOfGridPosPoly& sgp,
2270  const ArrayOfGridPosPoly& bgp,
2271  const ArrayOfGridPosPoly& pgp,
2272  const ArrayOfGridPosPoly& rgp,
2273  const ArrayOfGridPosPoly& cgp )
2274 {
2275  Index nv = vgp.nelem();
2276  Index ns = sgp.nelem();
2277  Index nb = bgp.nelem();
2278  Index np = pgp.nelem();
2279  Index nr = rgp.nelem();
2280  Index nc = cgp.nelem();
2281 
2282  assert(is_size(itw,nv,ns,nb,np,nr,nc,
2283  vgp[0].w.nelem()*
2284  sgp[0].w.nelem()*
2285  bgp[0].w.nelem()*
2286  pgp[0].w.nelem()*
2287  rgp[0].w.nelem()*
2288  cgp[0].w.nelem()));
2289 
2290  // We have to loop all the points in the new grid:
2291  for ( Index iv=0; iv<nv; ++iv )
2292  {
2293  const GridPosPoly& tv = vgp[iv];
2294  CACHEW(v)
2295  for ( Index is=0; is<ns; ++is )
2296  {
2297  const GridPosPoly& ts = sgp[is];
2298  CACHEW(s)
2299  for ( Index ib=0; ib<nb; ++ib )
2300  {
2301  const GridPosPoly& tb = bgp[ib];
2302  CACHEW(b)
2303  for ( Index ip=0; ip<np; ++ip )
2304  {
2305  const GridPosPoly& tp = pgp[ip];
2306  CACHEW(p)
2307  for ( Index ir=0; ir<nr; ++ir )
2308  {
2309  const GridPosPoly& tr = rgp[ir];
2310  CACHEW(r)
2311  for ( Index ic=0; ic<nc; ++ic )
2312  {
2313  const GridPosPoly& tc = cgp[ic];
2314  CACHEW(c)
2315 
2316  Index iti = 0;
2317 
2318  LOOPW(v)
2319  LOOPW(s)
2320  LOOPW(b)
2321  LOOPW(p)
2322  LOOPW(r)
2323  LOOPW(c)
2324  {
2325  itw.get(iv,is,ib,ip,ir,ic,iti) =
2326  (*v) * (*s) * (*b) * (*p) * (*r) * (*c);
2327  ++iti;
2328  }
2329  }
2330  }
2331  }
2332  }
2333  }
2334  }
2335 }
2336 
2338 
2360  ConstTensor3View itw,
2361  ConstMatrixView a,
2362  const ArrayOfGridPosPoly& rgp,
2363  const ArrayOfGridPosPoly& cgp)
2364 {
2365  Index nr = rgp.nelem();
2366  Index nc = cgp.nelem();
2367  assert(is_size(ia,nr,nc));
2368  assert(is_size(itw,nr,nc,
2369  rgp[0].w.nelem()*
2370  cgp[0].w.nelem()));
2371 
2372  // Check that interpolation weights are valid. The sum of all
2373  // weights (last dimension) must always be approximately one. We
2374  // only check the first element.
2375  assert( is_same_within_epsilon( itw(0,0,Range(joker)).sum(),
2376  1,
2377  sum_check_epsilon ) );
2378 
2379  // We have to loop all the points in the new grid:
2380  for ( Index ir=0; ir<nr; ++ir )
2381  {
2382  // Current grid position:
2383  const GridPosPoly& tr = rgp[ir];
2384  CACHEIDX(r)
2385 
2386  for ( Index ic=0; ic<nc; ++ic )
2387  {
2388  // Current grid position:
2389  const GridPosPoly& tc = cgp[ic];
2390  CACHEIDX(c)
2391 
2392  // Get handle to current element of output tensor and initialize
2393  // it to zero:
2394  Numeric& tia = ia(ir,ic);
2395  tia = 0;
2396 
2397  Index iti = 0;
2398  LOOPIDX(r)
2399  LOOPIDX(c)
2400  {
2401  tia += a.get(*r,
2402  *c) * itw.get(ir,ic,iti);
2403  ++iti;
2404  }
2405  }
2406  }
2407 }
2408 
2410 
2433  ConstTensor4View itw,
2434  ConstTensor3View a,
2435  const ArrayOfGridPosPoly& pgp,
2436  const ArrayOfGridPosPoly& rgp,
2437  const ArrayOfGridPosPoly& cgp)
2438 {
2439  Index np = pgp.nelem();
2440  Index nr = rgp.nelem();
2441  Index nc = cgp.nelem();
2442  assert(is_size(ia,
2443  np,nr,nc));
2444  assert(is_size(itw,
2445  np,nr,nc,
2446  pgp[0].w.nelem()*
2447  rgp[0].w.nelem()*
2448  cgp[0].w.nelem()));
2449 
2450  // Check that interpolation weights are valid. The sum of all
2451  // weights (last dimension) must always be approximately one. We
2452  // only check the first element.
2453  assert( is_same_within_epsilon( itw(0,0,0,Range(joker)).sum(),
2454  1,
2455  sum_check_epsilon ) );
2456 
2457  // We have to loop all the points in the new grid:
2458  for ( Index ip=0; ip<np; ++ip )
2459  {
2460  const GridPosPoly& tp = pgp[ip];
2461  CACHEIDX(p);
2462  for ( Index ir=0; ir<nr; ++ir )
2463  {
2464  const GridPosPoly& tr = rgp[ir];
2465  CACHEIDX(r);
2466  for ( Index ic=0; ic<nc; ++ic )
2467  {
2468  // Current grid position:
2469  const GridPosPoly& tc = cgp[ic];
2470  CACHEIDX(c);
2471 
2472  // Get handle to current element of output tensor and
2473  // initialize it to zero:
2474  Numeric& tia = ia(ip,ir,ic);
2475  tia = 0;
2476 
2477  Index iti = 0;
2478  LOOPIDX(p)
2479  LOOPIDX(r)
2480  LOOPIDX(c)
2481  {
2482  tia += a.get(*p,
2483  *r,
2484  *c) * itw.get(ip,ir,ic,
2485  iti);
2486  ++iti;
2487  }
2488  }
2489  }
2490  }
2491 }
2492 
2494 
2518  ConstTensor5View itw,
2519  ConstTensor4View a,
2520  const ArrayOfGridPosPoly& bgp,
2521  const ArrayOfGridPosPoly& pgp,
2522  const ArrayOfGridPosPoly& rgp,
2523  const ArrayOfGridPosPoly& cgp)
2524 {
2525  Index nb = bgp.nelem();
2526  Index np = pgp.nelem();
2527  Index nr = rgp.nelem();
2528  Index nc = cgp.nelem();
2529  assert(is_size(ia,
2530  nb,np,nr,nc));
2531  assert(is_size(itw,
2532  nb,np,nr,nc,
2533  bgp[0].w.nelem()*
2534  pgp[0].w.nelem()*
2535  rgp[0].w.nelem()*
2536  cgp[0].w.nelem()));
2537 
2538  // Check that interpolation weights are valid. The sum of all
2539  // weights (last dimension) must always be approximately one. We
2540  // only check the first element.
2541  assert( is_same_within_epsilon( itw(0,0,0,0,Range(joker)).sum(),
2542  1,
2543  sum_check_epsilon ) );
2544 
2545  // We have to loop all the points in the new grid:
2546  for ( Index ib=0; ib<nb; ++ib )
2547  {
2548  const GridPosPoly& tb = bgp[ib];
2549  CACHEIDX(b);
2550  for ( Index ip=0; ip<np; ++ip )
2551  {
2552  const GridPosPoly& tp = pgp[ip];
2553  CACHEIDX(p);
2554  for ( Index ir=0; ir<nr; ++ir )
2555  {
2556  const GridPosPoly& tr = rgp[ir];
2557  CACHEIDX(r);
2558  for ( Index ic=0; ic<nc; ++ic )
2559  {
2560  // Current grid position:
2561  const GridPosPoly& tc = cgp[ic];
2562  CACHEIDX(c);
2563 
2564  // Get handle to current element of output tensor and
2565  // initialize it to zero:
2566  Numeric& tia = ia(ib,ip,ir,ic);
2567  tia = 0;
2568 
2569  Index iti = 0;
2570  LOOPIDX(b)
2571  LOOPIDX(p)
2572  LOOPIDX(r)
2573  LOOPIDX(c)
2574  {
2575  tia += a.get(*b,
2576  *p,
2577  *r,
2578  *c) * itw.get(ib,ip,ir,ic,
2579  iti);
2580  ++iti;
2581  }
2582  }
2583  }
2584  }
2585  }
2586 }
2587 
2589 
2614  ConstTensor6View itw,
2615  ConstTensor5View a,
2616  const ArrayOfGridPosPoly& sgp,
2617  const ArrayOfGridPosPoly& bgp,
2618  const ArrayOfGridPosPoly& pgp,
2619  const ArrayOfGridPosPoly& rgp,
2620  const ArrayOfGridPosPoly& cgp)
2621 {
2622  Index ns = sgp.nelem();
2623  Index nb = bgp.nelem();
2624  Index np = pgp.nelem();
2625  Index nr = rgp.nelem();
2626  Index nc = cgp.nelem();
2627  assert(is_size(ia,
2628  ns,nb,np,nr,nc));
2629  assert(is_size(itw,
2630  ns,nb,np,nr,nc,
2631  sgp[0].w.nelem()*
2632  bgp[0].w.nelem()*
2633  pgp[0].w.nelem()*
2634  rgp[0].w.nelem()*
2635  cgp[0].w.nelem()));
2636 
2637  // Check that interpolation weights are valid. The sum of all
2638  // weights (last dimension) must always be approximately one. We
2639  // only check the first element.
2640  assert( is_same_within_epsilon( itw(0,0,0,0,0,Range(joker)).sum(),
2641  1,
2642  sum_check_epsilon ) );
2643 
2644  // We have to loop all the points in the new grid:
2645  for ( Index is=0; is<ns; ++is )
2646  {
2647  const GridPosPoly& ts = sgp[is];
2648  CACHEIDX(s);
2649  for ( Index ib=0; ib<nb; ++ib )
2650  {
2651  const GridPosPoly& tb = bgp[ib];
2652  CACHEIDX(b);
2653  for ( Index ip=0; ip<np; ++ip )
2654  {
2655  const GridPosPoly& tp = pgp[ip];
2656  CACHEIDX(p);
2657  for ( Index ir=0; ir<nr; ++ir )
2658  {
2659  const GridPosPoly& tr = rgp[ir];
2660  CACHEIDX(r);
2661  for ( Index ic=0; ic<nc; ++ic )
2662  {
2663  // Current grid position:
2664  const GridPosPoly& tc = cgp[ic];
2665  CACHEIDX(c);
2666 
2667  // Get handle to current element of output tensor and
2668  // initialize it to zero:
2669  Numeric& tia = ia(is,ib,ip,ir,ic);
2670  tia = 0;
2671 
2672  Index iti = 0;
2673  LOOPIDX(s)
2674  LOOPIDX(b)
2675  LOOPIDX(p)
2676  LOOPIDX(r)
2677  LOOPIDX(c)
2678  {
2679  tia += a.get(*s,
2680  *b,
2681  *p,
2682  *r,
2683  *c) * itw.get(is,ib,ip,ir,ic,
2684  iti);
2685  ++iti;
2686  }
2687  }
2688  }
2689  }
2690  }
2691  }
2692 }
2693 
2695 
2721  ConstTensor7View itw,
2722  ConstTensor6View a,
2723  const ArrayOfGridPosPoly& vgp,
2724  const ArrayOfGridPosPoly& sgp,
2725  const ArrayOfGridPosPoly& bgp,
2726  const ArrayOfGridPosPoly& pgp,
2727  const ArrayOfGridPosPoly& rgp,
2728  const ArrayOfGridPosPoly& cgp)
2729 {
2730  Index nv = vgp.nelem();
2731  Index ns = sgp.nelem();
2732  Index nb = bgp.nelem();
2733  Index np = pgp.nelem();
2734  Index nr = rgp.nelem();
2735  Index nc = cgp.nelem();
2736  assert(is_size(ia,
2737  nv,ns,nb,np,nr,nc));
2738  assert(is_size(itw,
2739  nv,ns,nb,np,nr,nc,
2740  vgp[0].w.nelem()*
2741  sgp[0].w.nelem()*
2742  bgp[0].w.nelem()*
2743  pgp[0].w.nelem()*
2744  rgp[0].w.nelem()*
2745  cgp[0].w.nelem()));
2746 
2747  // Check that interpolation weights are valid. The sum of all
2748  // weights (last dimension) must always be approximately one. We
2749  // only check the first element.
2750  assert( is_same_within_epsilon( itw(0,0,0,0,0,0,Range(joker)).sum(),
2751  1,
2752  sum_check_epsilon ) );
2753 
2754  // We have to loop all the points in the new grid:
2755  for ( Index iv=0; iv<nv; ++iv )
2756  {
2757  const GridPosPoly& tv = vgp[iv];
2758  CACHEIDX(v);
2759  for ( Index is=0; is<ns; ++is )
2760  {
2761  const GridPosPoly& ts = sgp[is];
2762  CACHEIDX(s);
2763  for ( Index ib=0; ib<nb; ++ib )
2764  {
2765  const GridPosPoly& tb = bgp[ib];
2766  CACHEIDX(b);
2767  for ( Index ip=0; ip<np; ++ip )
2768  {
2769  const GridPosPoly& tp = pgp[ip];
2770  CACHEIDX(p);
2771  for ( Index ir=0; ir<nr; ++ir )
2772  {
2773  const GridPosPoly& tr = rgp[ir];
2774  CACHEIDX(r);
2775  for ( Index ic=0; ic<nc; ++ic )
2776  {
2777  // Current grid position:
2778  const GridPosPoly& tc = cgp[ic];
2779  CACHEIDX(c);
2780 
2781  // Get handle to current element of output tensor and
2782  // initialize it to zero:
2783  Numeric& tia = ia(iv,is,ib,ip,ir,ic);
2784  tia = 0;
2785 
2786  Index iti = 0;
2787  LOOPIDX(v)
2788  LOOPIDX(s)
2789  LOOPIDX(b)
2790  LOOPIDX(p)
2791  LOOPIDX(r)
2792  LOOPIDX(c)
2793  {
2794  tia += a.get(*v,
2795  *s,
2796  *b,
2797  *p,
2798  *r,
2799  *c) * itw.get(iv,is,ib,ip,ir,ic,
2800  iti);
2801  ++iti;
2802  }
2803  }
2804  }
2805  }
2806  }
2807  }
2808  }
2809 }
2810 
2811 
Tensor7View
The Tensor7View class.
Definition: matpackVII.h:780
is_same_within_epsilon
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:446
sum_check_epsilon
const Numeric sum_check_epsilon
The maximum difference from 1 that we allow for a sum check.
Definition: interpolation_poly.cc:106
ConstTensor7View::get
Numeric get(Index l, Index v, Index s, Index b, Index p, Index r, Index c) const
Get element implementation without assertions.
Definition: matpackVII.h:713
IMIN
Index IMIN(Index a, Index b)
Return the minimum of two integer numbers.
Definition: interpolation_poly.cc:87
MatrixView
The MatrixView class.
Definition: matpackI.h:679
operator<<
ostream & operator<<(ostream &os, const GridPosPoly &gp)
Output operator for GridPosPoly.
Definition: interpolation_poly.cc:434
ConstTensor5View::get
Numeric get(Index s, Index b, Index p, Index r, Index c) const
Get element implementation without assertions.
Definition: matpackV.h:216
gridpos
void gridpos(ArrayOfGridPos &gp, ConstVectorView old_grid, ConstVectorView new_grid, const Numeric &extpolfac)
Set up a grid position Array.
Definition: interpolation.cc:167
ConstTensor7View
A constant view of a Tensor7.
Definition: matpackVII.h:162
joker
const Joker joker
interpolation.h
Header file for interpolation.cc.
chk_interpolation_grids
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:1094
ConstTensor4View::get
Numeric get(Index b, Index p, Index r, Index c) const
Get element implementation without assertions.
Definition: matpackIV.h:185
interpweights
void interpweights(VectorView itw, const GridPosPoly &tc)
Red 1D interpolation weights.
Definition: interpolation_poly.cc:470
ConstVectorView::get
Numeric get(Index n) const
Get element implementation without assertions.
Definition: matpackI.h:311
ConstMatrixView::get
Numeric get(Index r, Index c) const
Get element implementation without assertions.
Definition: matpackI.h:618
VectorView::get
Numeric get(Index n) const
Get element implementation without assertions.
Definition: matpackI.h:387
is_size
bool is_size(ConstVectorView x, const Index &n)
Verifies that the size of x is l.
Definition: logic.cc:91
LOOPW
#define LOOPW(x)
Macro for interpolation weight loops.
Definition: interpolation_poly.cc:406
ConstTensor4View
A constant view of a Tensor4.
Definition: matpackIV.h:141
Tensor3View
The Tensor3View class.
Definition: matpackIII.h:232
CACHEW
#define CACHEW(x)
Macro for caching begin and end iterators for interpolation weight loops.
Definition: interpolation_poly.cc:409
w
cmplx FADDEEVA() w(cmplx z, double relerr)
Definition: Faddeeva.cc:679
Array< GridPosPoly >
ConstTensor6View::get
Numeric get(Index v, Index s, Index b, Index p, Index r, Index c) const
Get element implementation without assertions.
Definition: matpackVI.h:386
Tensor6View::get
Numeric get(Index v, Index s, Index b, Index p, Index r, Index c) const
Get element implementation without assertions.
Definition: matpackVI.h:662
gridpos_poly_cyclic_longitudinal
void gridpos_poly_cyclic_longitudinal(ArrayOfGridPosPoly &gp, ConstVectorView old_grid, ConstVectorView new_grid, const Index order, const Numeric &extpolfac)
Set up grid positions for higher order interpolation.
Definition: interpolation_poly.cc:359
gridpos_poly_longitudinal
void gridpos_poly_longitudinal(const String &error_msg, ArrayOfGridPosPoly &gp, ConstVectorView old_grid, ConstVectorView new_grid, const Index order, const Numeric &extpolfac)
Set up grid positions for higher order interpolation on longitudes.
Definition: interpolation_poly.cc:302
GridPosPoly
Structure to store a grid position for higher order interpolation.
Definition: interpolation_poly.h:64
Tensor3View::get
Numeric get(Index p, Index r, Index c) const
Get element implementation without assertions.
Definition: matpackIII.h:252
my_basic_string
The implementation for String, the ARTS string class.
Definition: mystring.h:64
Tensor5View::get
Numeric get(Index s, Index b, Index p, Index r, Index c) const
Get element implementation without assertions.
Definition: matpackV.h:322
ConstVectorView::nelem
Index nelem() const
Returns the number of elements.
Definition: matpackI.cc:180
VectorView
The VectorView class.
Definition: matpackI.h:372
CACHEIDX
#define CACHEIDX(x)
Macro for caching begin and end iterators for interpolation index loops.
Definition: interpolation_poly.cc:421
IMAX
Index IMAX(Index a, Index b)
Return the maximum of two integer numbers.
Definition: interpolation_poly.cc:65
ns
#define ns
Definition: continua.cc:21931
GridPosPoly::idx
ArrayOfIndex idx
Definition: interpolation_poly.h:67
ConstVectorView::sum
Numeric sum() const
The sum of all elements of a Vector.
Definition: matpackI.cc:186
ConstTensor6View
A constant view of a Tensor6.
Definition: matpackVI.h:159
Numeric
NUMERIC Numeric
The type to use for all floating point numbers.
Definition: matpack.h:29
Tensor5View
The Tensor5View class.
Definition: matpackV.h:276
LOOPIDX
#define LOOPIDX(x)
Macro for interpolation index loops.
Definition: interpolation_poly.cc:418
is_lon_cyclic
bool is_lon_cyclic(ConstVectorView grid, const Numeric &epsilon)
Check if the given longitude grid is cyclic.
Definition: logic.cc:466
MatrixView::get
Numeric get(Index r, Index c) const
Get element implementation without assertions.
Definition: matpackI.h:691
interpolation_poly.h
Header file for interpolation_poly.cc.
ConstMatrixView
A constant view of a Matrix.
Definition: matpackI.h:596
Tensor7View::get
Numeric get(Index l, Index v, Index s, Index b, Index p, Index r, Index c) const
Get element implementation without assertions.
Definition: matpackVII.h:1315
ConstTensor3View::get
Numeric get(Index p, Index r, Index c) const
Get element implementation without assertions.
Definition: matpackIII.h:176
Range
The range class.
Definition: matpackI.h:148
logic.h
Header file for logic.cc.
ConstTensor3View
A constant view of a Tensor3.
Definition: matpackIII.h:139
Tensor4View
The Tensor4View class.
Definition: matpackIV.h:243
GridPosPoly::w
Vector w
Definition: interpolation_poly.h:70
interp
Numeric interp(ConstVectorView itw, ConstVectorView a, const GridPosPoly &tc)
Red 1D Interpolate.
Definition: interpolation_poly.cc:730
Index
INDEX Index
The type to use for all integer numbers and indices.
Definition: matpack.h:35
check_input.h
gridpos_poly
void gridpos_poly(ArrayOfGridPosPoly &gp, ConstVectorView old_grid, ConstVectorView new_grid, const Index order, const Numeric &extpolfac)
Set up grid positions for higher order interpolation.
Definition: interpolation_poly.cc:127
Vector
The Vector class.
Definition: matpackI.h:556
arts_omp.h
Header file for helper functions for OpenMP.
ConstVectorView
A constant view of a Vector.
Definition: matpackI.h:292
Array::nelem
Index nelem() const
Number of elements.
Definition: array.h:176
ConstTensor5View
A constant view of a Tensor5.
Definition: matpackV.h:152
Tensor4View::get
Numeric get(Index b, Index p, Index r, Index c) const
Get element implementation without assertions.
Definition: matpackIV.h:272
Tensor6View
The Tensor6View class.
Definition: matpackVI.h:449